name root 1 name foundation 2 name core 3 name event_handler 4 name has_commands 5 name environment 6 name has_messages 7 name public 8 name network 9 name help_root 10 name text 11 name messaged 12 name has_settings 13 name named 14 name gender 15 name libraries 16 name misc 17 name utilities 18 name frob 19 name sys 0 name control 20 name backdoor 21 name described 22 name gendered 23 name physical 24 name command_cache 25 name exit 26 name located 27 name thing 28 name location 29 name located_location 30 name body 31 name user_interfaces 32 name interaction 33 name mail_root 34 name mail_list 35 name mail_ui 36 name command_aliases 37 name bad_commands 38 name user_data 39 name help_ui 40 name messages_ui 41 name settings_ui 42 name user 43 name place 44 name connection 45 name daemon 46 name connection_interface 47 name help_index 48 name help 49 name help_node 50 name note 51 name project 52 name mail_message 53 name event_frob 54 name gender_female 55 name gender_male 56 name gender_plural 57 name gender_neuter 58 name dictionary 59 name time_root 60 name buffer 61 name string 62 name command_lib 63 name http_lib 64 name object_lib 65 name integer 66 name parse_lib 67 name code_lib 68 name list 69 name security 70 name help_lib 71 name ctext_lib 72 name mail_lib 73 name time_lib 74 name data_lib 75 name symbol 76 name tree 77 name db 78 name user_parsers 79 name trie 80 name filters 81 name lock_parser 82 name cml2 83 name world 84 name root_evaluator 85 name has_hooks 86 name lag_watcher 87 name channels 88 name places 89 name motd 90 name heart 91 name projects 92 name scheduler 93 name housekeeper 94 name logic_frob 95 name realms_frob 96 name ctext_frob 97 name ctext_tag 98 name thing_frob 99 name read_parser 100 name ctext2_frob 101 name message_frob 102 name editors 103 name builder 104 name guest 105 name reaper 106 name no_one 107 name player 108 name nothing 109 name nowhere 110 name body_cave 111 name void 112 name detailed_place 113 name the_pit 114 name login_connection 115 name http_connection 116 name http_daemon 117 name login_daemon 118 name login_interface 119 name http_interface 120 name help_index_root 121 name help_summary 122 name log 123 name movement_event 124 name time 125 name dark_time 126 name mail_envelope 127 name mail_address 128 name registry 129 name mail_db 130 name null_parser 131 name command_aliases_parser 132 name command_parser 133 name conference_parser 134 name epic_filter 135 name wrap_filter 136 name ctext_filter 137 name cml2_evaluator 138 name cml2_form 139 name cml2_compiler 140 name xor 141 name and 142 name lock_frob 143 name not 144 name or 145 name true 146 name false 147 name realm_of_creation 148 name ctext_generator 149 name ctext_format 150 name wearable_frob 151 name help_editing_ui 152 name tree_ui 153 name editor 156 name set_ui 157 name generic_editor 158 name programmer 159 name storyteller 161 name on_location 162 name in_location 163 name http_log 171 name reaper_log 172 name login_log 173 name mail_list_news 174 name mail_list_bugs 175 name place_db 176 name user_db 177 name cml2_format 178 name cml2_base_eval 179 name cml2_uncompiler 180 name or_lock_frob 181 name true_lock_frob 182 name false_lock_frob 183 name not_lock_frob 184 name object_lock_frob 185 name and_lock_frob 186 name inside_lock_frob 187 name admin 188 name code_editor 190 name note_editor 191 name lost_and_found 192 name cml2_telnet_format 193 name cml2_html_format 194 object $root var $root manager $root var $root owners [$root] var $root trusted [] var $root owned 0 var $root child_index 12 var $root fertile 1 var $root inited 0 var $root quota 75000 var $root managed 0 var $root writers [$root] var $root objname 'root var $root created_on 0 var $root indestructable 1 var $root flags ['parameters, 'methods, 'code, 'fertile, 'core] var $root quota_exempt 0 var $root writes 0 var $root trusted_by 0 root init_root .change_manager(this()); flags = ['parameters, 'methods, 'code]; created_on = time(); .add_owner(this()); . root uninit_root var obj; (| manager.del_managed_obj() |); catch any { for obj in (.managed()) obj.change_manager($reaper); } catch any { for obj in (.writers('literal)) .del_writer(obj); } catch any { for obj in (.writes()) obj.del_writer(this()); } catch any { for obj in (.trusted('literal)) .del_trusted(obj); } catch any { for obj in (.trusted_by()) obj.del_trusted(this()); } catch any { for obj in (.owners()) .del_owner(obj, 1); } catch any { for obj in (.owned()) obj.del_owner(this()); } // tell $sys we are going away $sys.sender_going_away(); . public initialize: disallow_overrides var ancestors, ancestor, pos, len; if (caller() != $sys && sender() != this()) throw(~perm, "Caller is not $sys and sender is not this."); if (inited) throw(~perm, "Already initialized."); ancestors = ancestors(); len = ancestors.length(); for pos in [0 .. len - 1] { (> ._initialize_ancestor(ancestors[len - pos]) <); // pause(); } inited = 1; . public uninitialize: disallow_overrides var ancestor, errors; (> .perms(caller(), $root, $sys) <); errors = []; for ancestor in (ancestors()) { catch any { ._uninitialize_ancestor(ancestor); } with handler { errors = [@errors, traceback()]; } // pause(); } return errors; . public perms: disallow_overrides arg what, [args]; var flag, second; if (!args) args = ['writer]; if (type(args[1]) == 'symbol) { switch (args[1]) { case 'this: if (what != this() && !$sys.is_system(what)) throw(~perm, "Permission Denied: " + what.objname() + " is not this.", what); case 'system: if (!$sys.is_system(what)) throw(~perm, "Permission Denied: " + what.objname() + " is not of the system.", what); case 'manager: if (.manager() != what && !$sys.is_system(what)) throw(~perm, "Permission Denied: " + what.objname() + " is not the manager.", what); case 'trusts: if (!.trusts(what)) throw(~perm, "Permission Denied: " + what.objname() + " is not a trustee.", what); default: if (!.is_writable_by(what)) throw(~perm, "Permission Denied: " + what.objname() + " is not a writer.", what); } } else if (type(what) == 'dbref) { if (!(what in args)) throw(~perm, what.objname() + " is not one of: " + $list.to_english($list.map(args, 'namef, 'ref)), what); } . root _change_parents: disallow_overrides arg parents; var old, old_p, init, uninit, ancestor, pos, errors; if (!parents) throw(~noparents, "Objects must have at least 1 parent"); // Perform the actual change. old = ancestors(); old_p = .parents(); (> $sys.change_sender_parents(parents) <); // Figure out new ancestors to initialize, and old ones to uninitialize. init = []; uninit = old; for ancestor in (ancestors()) { uninit = uninit.setremove(ancestor); if (!(ancestor in old)) init = [@init, ancestor]; } // Initialize the new ancestors. catch any { for ancestor in (init) ._initialize_ancestor(ancestor); } with handler { // Initialization error // deinitialize parents we initialized, and fall back to old parents. pos = ancestor in init; for ancestor in (init.subrange(1, pos)) (| ._uninitialize_ancestor(ancestor) |); (> $sys.change_sender_parents(old_p) <); throw(~init, "Failed to initialize new ancestors.", traceback()); } // Uninitialize the old ancestors. for ancestor in (uninit) (| .(tosym("uninit_" + tostr(ancestor.objname('symbol))))() |); . public chparents arg [parents]; var parent; if (!(| .perms(sender(), 'manager) |)) (> .perms(caller(), $root, $sys) <); if (!parents) throw(~noparents, "There must be at least 1 parent for each object."); // Notify parents of impending change. for parent in (parents) (> parent.will_inherit(sender()) <); // Everything's okay, go ahead and try it. ._change_parents(parents); . public will_inherit arg obj; // Throw an error if it's not okay for obj to inherit from us. if (!.has_flag('fertile, sender()) && !.trusts(obj) && !obj.has_ancestor(this())) throw(~perm, .objname() + " refuses to be parent of " + obj.objname() + "."); . public manager: disallow_overrides return manager || $control; . public owners: disallow_overrides return owners || [$control]; . public writers: disallow_overrides arg [literal]; if (literal) return writers || []; // for speed, just add rather than setadd, use .compress() later if necessary return (writers || []) + [.manager(), this()]; . public trusted: disallow_overrides arg [literal]; if (literal) return trusted || []; return (trusted || []) + .writers(); . public is_writable_by: disallow_overrides arg obj; return (| obj in .writers() |) || $sys.is_system(obj); . public trusts: disallow_overrides arg obj; return (| obj in .trusted() |) || obj == $scheduler || $sys.is_system(obj); . root set_manager: disallow_overrides arg new; if (type(new) != 'dbref) throw(~invarg, "Managers must be given as a single dbref."); if (new == $control) (| clear_var('manager) |); else manager = new; . public change_manager: disallow_overrides arg new; var old; caller() == definer() || (> .perms(sender(), 'manager) <); if (type(new) != 'dbref) throw(~invarg, "Managers must be given as a single dbref."); old = .manager(); .set_manager(new); old.del_managed_obj(); new.add_managed_obj(); . public add_writer: disallow_overrides arg obj; (> .perms(sender(), 'manager) <); writers = (writers || []).setadd(obj); obj.add_writable_obj(); . public del_writer: disallow_overrides arg obj; caller() == definer() || (> .perms(sender(), 'manager) <); writers = (writers || []).setremove(obj); if (!writers) (| clear_var('writers) |); obj.del_writable_obj(); . public add_trusted: disallow_overrides arg obj; caller() == definer() || (> .perms(sender(), 'manager) <); trusted = (trusted || []).setadd(obj); obj.add_trusted_obj(); . public del_trusted: disallow_overrides arg obj; (> .perms(sender(), 'manager) <); trusted = (trusted || []).setremove(obj); if (!trusted) clear_var('trusted); obj.del_trusted_obj(); . public as_this_run arg obj, method, args; if (!.trusts(sender())) throw(~perm, "Sender not allowed to gain access to object perms."); return (> obj.(method)(@args) <); . public add_parent arg parent; (> .perms(sender(), 'manager) <); if (parent in .parents()) throw(~parent, .objname() + " already has " + parent.objname() + " as a parent."); if (!valid(parent)) throw(~type, "Not a valid parent, must send a dbref or pointer"); .chparents(@.parents(), parent); . public del_parent arg parent; var parents; (> .perms(sender(), 'manager) <); if (!valid(parent)) throw(~type, "Not a valid parent, must send a valid object."); parents = .parents(); if (!(parent in parents)) throw(~parentnf, parent.objname() + " is not a parent of " + .objname() + "."); parents = parents.setremove(parent); (> .chparents(@parents) <); . public spawn: disallow_overrides arg [suffix]; var obj, tmp, objname, owner, mngr, na; na = "!@#$%^&*()+-=~`'{}[]|/?\"\\,.<>;: "; if (!.has_flag('fertile, sender())) throw(~perm, "Not fertile or readable."); // available quota? if (!sender().quota_valid()) throw(~quota, "Sender does not have the available quota"); // Figure out the suffix from the arguments and child index. if (suffix) { suffix = suffix[1]; // so they dont confuse child_index: if ($string.is_numeric(suffix)) throw(~perm, "Can't specify a numeric suffix."); // so we get correct symbols & it is always lowercase: suffix = $string.strip(suffix, na); //.lowercase(); } else { // make sure it doesn't exist already: objname = .objname('symbol).to_string(); tmp = .objname('symbol); while ((| get_dbref(tmp) |)) { child_index = child_index + 1; tmp = tosym(objname + "_" + tostr(child_index)); } suffix = tostr(child_index); } // Ask the system object for a child. obj = $sys.spawn_sender(suffix, sender()); return obj; . public destroy: disallow_overrides // This doesn't actually destroy us immediately, but we will go away when // nothing is holding onto us any more. (> .perms(sender(), 'manager) <); if (.has_flag('core)) throw(~perm, "This object is a core object, and cannot be destroyed!"); (| .uninitialize() |); $sys.destroy_sender(); . public add_parameter arg name, [args]; var tmp, kid; // .add_parameter('name[, default-value, 'inherit]) // Add the given parameter to this object. // if 'default-value' is included, initialize the variable to that value // if 'inherit is given the value is initialized on all descendents (> .perms(sender()) <); (> add_parameter(name) <); // The following code is a kludge as we can't send a default value to the // primitive. if (args) { tmp = tosym("__set_" + tostr(name) + "_" + tostr(random(1000))); catch any { compile([tostr(name) + " = " + toliteral(args[1]) + ";"], tmp); .(tmp)(); if (args.length() > 1 && args[2] == 'inherit) { for kid in (.descendants()) kid.(tmp)(); } del_method(tmp); } with handler { del_method(tmp); rethrow(error()); } } . protected parameters return parameters(); . public del_parameter: disallow_overrides arg name; var n, obj; (> .perms(sender()) <); // try and clear the variable on all of the descendants, before deleting // the parameter... (> .clear_variable(name) <); // now delete the parameter (> del_parameter(name) <); . public del_method arg name; (> .perms(sender()) <); (> del_method(name) <); . public methods: disallow_overrides if (!.has_flag('methods, sender())) throw(~perm, sender().objname() + " doesn't have permission to find methods on " + .objname()); return methods(); . public parents: disallow_overrides return parents(); . public children: disallow_overrides return children(); . public ancestors: disallow_overrides return ancestors(); . public find_method: disallow_overrides arg name; if (!.has_flag('methods, sender())) throw(~perm, sender().objname() + " doesn't have permission to find methods on " + .objname()); return (> find_method(name) <); . public find_next_method: disallow_overrides arg name, after; if (!.has_flag('methods, sender())) throw(~perm, sender().objname() + " doesn't have permission to find methods on " + .objname()); return (> find_next_method(name, after) <); . public list_method arg [args]; if (!.has_flag('code, sender())) throw(~perm, "Method code on " + .namef('ref) + " is not readable by " + sender().namef('ref)); return (> list_method(@args) <); . public compile arg code, name; (> .perms(sender()) <); (| $sys.touch() |); return (> compile(code, name) <); . public show: disallow_overrides arg wildcard, chop, sinv, [what]; var output, what, wildcard, actor, parent, readable, m, p, x, line; actor = sender(); output = "Object: " + .namef('ref) + " [" + tostr(.size()) + " bytes]"; output = [output, "Parents: " + $data_lib.unparse(parents())]; if ('methods in what) { if (.has_flag('methods, sender())) output = output + ._show_methods(wildcard, actor); else output = output + [" ** No permission to list Methods **"]; } if ('parameters in what) { if (.has_flag('parameters, sender())) output = output + ._show_parameters(wildcard, actor, chop, sinv); else output = output + [" ** No permission to list Parameters **"]; } return output; . public has_ancestor: disallow_overrides arg obj; return has_ancestor(obj); . public eval: disallow_overrides arg code, [dest]; var errors, result; dest = dest ? dest[1] | this(); if (sender() != $scheduler) (> .perms(sender()) <); // Compile the code. errors = .compile(code, 'tmp_eval); if (errors) return ['errors, errors, 0, 0]; // Evaluate the expression. Be sure to remove it afterwards, so that no // one else can call it. catch any { result = (> dest.tmp_eval() <); } with handler { (| del_method('tmp_eval) |); rethrow(error()); } (| del_method('tmp_eval) |); return ['result, result]; . public method_info arg [args]; var gen, i, definers, filter, method, public, private, protected, anc, ancs, root, driver, match; if (!.has_flag('methods, sender())) throw(~perm, "Method code on " + .namef('ref) + " is not readable by " + sender().namef('ref)); // Just assume if they are sending arguments it is @display not @show if (args) { gen = args[1]; definers = args[2]; filter = args[3]; } else { if (definers) gen = ['ancestor_to, definers[1]]; else gen = ['generations, 1]; filter = ""; } public = private = protected = root = driver = []; ancs = .(gen[1])(gen[2]); if (definers) ancs = $list.intersection(ancs, definers); if (!ancs) ancs = [this()]; match = (| .setting("match-with") |) || 'match_regexp; for anc in (ancs) { for method in (anc.methods()) { if ($string.(match)(filter, tostr(method))) { i = ._get_method_info(anc, method); switch (anc.method_state(method)) { case 'root: root = root + [i]; case 'driver: driver = driver + [i]; case 'public: public = public + [i]; case 'private: private = private + [i]; case 'protected: protected = protected + [i]; } } } } return [public, protected, private, root, driver]; . public data: disallow_overrides var par, data, out; if (!.has_flag('parameters, sender())) throw(~perm, sender().namef('ref) + " is not allowed to read parameters on " + .namef('ref)); data = $sys.sender_data(); out = #[]; for par in (data) { // if the parent doesn't exist anymore, just let them see the data. if (!valid(par[1]) || par[1].has_flag('parameters, sender())) out = out.add(par[1], par[2]); else out = out.add(par[1], ["*** Permission Denied ***"]); } return out; . public size: disallow_overrides arg [args]; args = [@args, 'int][1]; switch (args) { case 'string: return tostr(size()); case 'english: return $int.to_english(size()); default: return size(); } . public descendants: disallow_overrides var kids, i, c; kids = children(); while ((| c = kids[i = i + 1] |)) kids = kids.union(c.children()); return kids; . public get_quota: disallow_overrides return quota; . public owned: disallow_overrides return owned || []; . public quota_valid: disallow_overrides if (quota_exempt == -1) return 1; if (!.is($user)) return 0; return .quota_byte_usage() < .quota(); . root del_owned_obj: disallow_overrides if (owned) { owned = owned.setremove(sender()); (| clear_var('owned) |); } . root add_owned_obj: disallow_overrides owned = (owned || []).setadd(sender()); . public match_children arg string; var children, child_names, c; children = .children(); child_names = $list.map(children, 'namef); // direct matches first. for c in (child_names) { if (c == string) return children[c in child_names]; } // ok, try partial matches for c in (child_names) { if ($string.match_begin(c, string)) return children[c in child_names]; } return 0; . public del_flag: disallow_overrides arg flag; (> .perms(sender(), 'manager) <); // let them add any flag they want flags = (flags || []).setremove(flag); . public _display_descendants arg space, checked, levels, maxlev; var space, checked, c, anc, biguglylist, id, perms; id = space + .namef('xref) + " " + $object_lib.see_perms(this()); for anc in (checked) { if (.has_ancestor(anc)) return [id + " (above)"]; } if (.parents().length() > 1) id = id + " (MI)"; else id = id + ""; biguglylist = [id]; space = space + " "; levels = levels + 1; // check children if (!maxlev || maxlev != levels) { for c in (.children()) { biguglylist = biguglylist + c._display_descendants(space, checked, levels, maxlev); checked = checked.setadd(c); pause(); } } return biguglylist; . public _get_method_info: disallow_overrides arg anc, method; var code, lines, dis_flag, meth_args, flags, first_comment; code = anc.list_method(method); lines = code.length(); if (lines > 5) code = code.subrange(1, 5); flags = anc.method_flags(method); if (code) { meth_args = "arg (.*);".sub(code[1]); if (meth_args) { meth_args = meth_args[1]; code = code.delete(1); } else { meth_args = ""; } if (code && (!code[1] || code[1][1] == "v")) code = code.delete(1); if (code && (!code[1] || code[1][1] == "v")) code = code.delete(1); first_comment = code ? code[1] + " " | " "; first_comment = first_comment[1] == "/" || first_comment[1] == "r" ? first_comment | ""; } else { meth_args = ""; first_comment = ""; } return [anc, method, meth_args, flags, lines, first_comment]; . public namef arg [args]; var output, type, part, rval; if (!args) args = [['objname]]; if (args[1] == 'ref || args[1] == 'xref) args = [['objname]]; // the actual switch, punctuation is treated oddly (parens specifically) output = ""; for part in (args) { type = type(part); if (type == 'list) output = output + ((| .(part[1])(@part.subrange(2)) |) || ""); else if (type == 'string) output = output + part; } return output; . public match_descendants arg string; var match, child; match = .match_children(string); if (match) return match; for child in (.children()) { match = child.match_descendants(string); if (match) return match; } return 0; . public chown: disallow_overrides arg [new_owners]; var owner; (> .perms(sender(), 'manager) <); if (new_owners && type(new_owners[1]) == 'list) throw(~invarg, "Arguments must be objects."); for owner in (new_owners) { if (!valid(owner)) throw(~invowner, "Owner is an invalid object."); } for owner in (owners || []) { if (!valid(owner)) owners = owners.setremove(owner); } for owner in ((owners || []).set_difference(new_owners)) owner.del_owned_obj(); if (!new_owners || new_owners == [$control]) { $control.add_owned_obj(); (| clear_var('owners) |); return; } for owner in (new_owners.set_difference(owners || [])) owner.add_owned_obj(); owners = new_owners; . public debug arg [stuff]; var x, line, mngr, meth; meth = (| callers()[2][3] |); if (meth) line = "DEBUG " + sender().objname() + "." + tostr(meth) + "(): "; else line = "DEBUG " + sender().objname() + ": "; for x in (stuff) line = line + " " + (type(x) == 'string ? x | $data_lib.unparse(x)); (| .manager().tell(line) |); . public set_quota arg value; (> .perms(caller(), $user, @$sys.system(), $root) <); quota = value; . public name arg [args]; return .objname(); . public del_owner: disallow_overrides arg owner, [nodefault]; caller() == definer() || sender() == owner || (> .perms(sender(), 'manager) <); owners = (owners || []).setremove(owner); owner.del_owned_obj(); if (!nodefault) .add_owner(.manager()); . public add_owner: disallow_overrides arg owner; caller() == definer() || sender() == owner || (> .perms(sender(), 'manager) <); owners = (owners || []).setadd(owner); owner.add_owned_obj(); . public generate_html arg [args]; var actor, name, out, line, obj, col, colx, objs, x; actor = sender(); name = .namef('ref); out = ["<head><title>" + name + "</title></head>", "<body>", "<h1 align=center><a href=\"/bin/display?" + .objname() + "\">" + name + "</a></h1>"]; line = []; for obj in (.parents()) line = [@line, $http_lib.make_object_href(obj, obj.namef('xref), "/bin/object?")]; out = [@out, "<P align=center><b>Parent(s): </b><code>" + $list.to_english(line) + "</code>", "<pre>"]; // duplicate the $code.generate_family_listing code because we // want to put in hrefs. objs = .children(); if (objs) { out = [@out, "Children:"]; col = ((| sender().linelen() |) || 79) / 8; colx = col * 3; line = "Name".pad(colx + 2) + " Perms".pad(col - 2); out = [@out, line + "Size ".pad(-col) + "Manager"]; for obj in (objs) { name = obj.objname(); line = $http_lib.make_object_href(obj, name.pad(colx + 2), "/bin/object?"); line = line + $object_lib.see_perms(obj).pad(col - 2); line = line + tostr(obj.size()).pad(" ", -col); x = obj.manager(); if (!valid(x)) name = ("** invalid object *(" + tostr(x) + ") **").pad(colx); else name = $http_lib.make_object_href(x, x.namef('xref).pad(colx)); line = line + name; out = [@out, line]; } } out = [@out, "</pre>"]; return out; . public show_in_html: disallow_overrides var out, actor, data, parent, info, m, p, x, line, types; // duplicating code in .show because I want it to be htmlified actor = sender(); data = $sys.sender_data(); // the beginning. out = "Object: " + $http_lib.make_object_href(this(), 0, "/bin/object?") + " [" + tostr(.size()) + " bytes]"; line = []; for x in (.parents()) line = [@line, $http_lib.make_object_href(x)]; out = [out, "Parent(s): " + $list.to_english(line), "<pre>"]; // Methods if (.has_flag('methods, sender())) { types = ["Public", "Protected", "Private", "Root", "Driver"]; info = .method_info(['ancestors_to, this()], [this()], ""); for m in [1 .. 5] { if (info[m]) { out = out + [types[m] + " Methods:"]; for m in (info[m]) out = [@out, $object_lib.parse_method_flags(m[4]) + tostr(m[5]).right(4) + " " + $http_lib.make_method_href(m)]; } } } else { out = out + [" ** No permission to list Methods **"]; } // Parameters if (.has_flag('parameters, sender())) { for parent in (data) { // because the server is FKD we have to make sure your params // all have valid parents: if (valid(parent[1])) { out = out + [parent[1].namef('xref) + " Parameters:"]; if (parent[1].has_flag('parameters, actor)) { for p in (parent[2]) { line = " " + tostr(p[1]) + ": " + ($http_lib.filter_text([$data_lib.unparse(p[2])]))[1]; out = out + [line]; } } else { out = out + [" ** Permission Denied **"]; } } else { out = out + ["(Invalid parent-object You cannot reference because it's broke) Parameters:"]; for p in (parent[2]) { line = " " + tostr(p[1]) + ": " + ($http_lib.filter_text([$data_lib.unparse(p[2])]))[1]; out = out + [line]; } } } } else { out = out + [" ** No permission to list Parameters **"]; } // Return what we've got. return out; . public quota return quota; . public quota_byte_usage var total, obj; // perm checking goes here for obj in (.owned()) total = total + obj.size(); return total; . public _coreify_root . root _initialize_ancestor arg ancestor; var method; method = tosym("init_" + tostr(ancestor.objname('symbol))); catch ~methodnf { if (find_method(method) != ancestor) throw(~perm, "Initialization method for " + ancestor.objname() + " in wrong place (" + find_method(method).objname() + ")"); .(method)(); } . root _uninitialize_ancestor arg ancestor; var method; method = tosym("uninit_" + tostr(ancestor.objname('symbol))); catch ~methodnf { if (.find_method(method) != ancestor) throw(~perm, "UnInitialization method for " + ancestor.objname() + " in wrong place (" + .find_method(method).objname() + ")"); .(method)(); } . public objname arg [args]; args = [@args, 'string][1]; switch (args) { case 'string: return "$" + tostr(objname); case 'symbol: return objname; default: throw(~type, "args must be 'string or 'symbol"); } . public set_objname arg new_objname; var old_objname; // Only accept calls from owners or admins. (> .perms(sender()) <); // Make sure first argument is a symbol. if (type(new_objname) != 'symbol) throw(~type, "New objname is not a symbol."); // Make sure everything is lowercase. new_objname = tosym(tostr(new_objname).lowercase()); // Do nothing if new_objname isn't different. if (new_objname == objname) return; // Grab the new objname (> $sys.assign_objname(new_objname) <); old_objname = objname; objname = new_objname; // If we already had a objname, get rid of the old one. if (old_objname) (> $sys.deassign_objname(old_objname) <); . root _show_methods: disallow_overrides arg wildcard, actor; var output, methods, m, types, type; methods = .method_info(['ancestors_to, this()], [this()], wildcard); types = ["Public", "Protected", "Private"]; output = []; for type in [1 .. 3] { if (methods[type]) { output = output + [types[type] + " Methods:"]; for m in (methods[type]) { output = output + [" " + tostr(m[2]) + "(" + m[3] + ")"]; pause(); } } } return output; . root _show_parameters: disallow_overrides arg wildcard, actor, chop, show_invalid; var parent, data, output, p, line, len; output = []; data = $sys.sender_data(); len = actor.linelen(); for parent in (data) { if (valid(parent[1])) { output = output + [parent[1].objname() + " Parameters:"]; if (parent[1].has_flag('parameters, actor)) { for p in (parent[2]) { line = " " + tostr(p[1]) + ": " + $data_lib.unparse(p[2]); if (chop) line = line.chop(len); output = output + [line]; } } else { output = output + [" ** Permission Denied **"]; } } else if (show_invalid) { output = output + [$object_lib.get_name(parent[1]) + " Parameters:"]; for p in (parent[2]) { line = " " + tostr(p[1]) + ": " + $data_lib.unparse(p[2]); output = output + [line]; } } pause(); } return output; . public set_created arg value; created_on = value; . public created_on return created_on; . public is_of: disallow_overrides arg obj; return obj in ancestors(); . public _object_header_in_html arg [args]; var len, line, out, chop; chop = [@args, 1][1]; len = (| sender().linelen() |) || 79; out = ["<font size=+1>"]; line = "Object: " + .namef('xref) + " "; line = line + $object_lib.see_perms(this()); out = [@out, line.left(len / 3 * 2) + " Size: " + .size().to_english()]; line = .owners(); if (line.length() > 1) line = "Owners: " + line.map('objname).to_english(); else if (!line) line = "Owner: (none)"; else line = "Owner: " + line.namef('xref); if (chop) line = line.chop(len); out = [@out, line]; line = .parents(); if (line.length() > 1) line = "Parents: " + line.map('objname).to_english(); else if (!line) line = "Parents: (none)"; else line = "Parent: " + line[1].namef('xref); if (chop) line = line.chop(len); out = [@out, line]; if (.has_ancestor($located)) { line = $object_lib.get_name(.location(), 'namef, ['xref]); out = [@out, "Location: " + line]; } return out + ["</font>"]; . public is: disallow_overrides arg obj; return has_ancestor(obj); . public hname arg [args]; return "<a href=\"/bin/display?" + .objname() + "\">" + .objname() + "</a>"; . public add_flag: disallow_overrides arg flag; (> .perms(sender(), 'manager) <); if (flag == 'core && !$sys.is_system(sender())) throw(~perm, "Only system objects can set the 'core flag."); flag == 'fertile && (> .perms(sender(), 'manager) <); // let them add any flag they want flags = (flags || []).setadd(flag); . public clear_variables arg [variables]; var v; (> .perms(sender()) <); for v in (variables) (| .clear_variable(v) |); . public clear_variable: disallow_overrides arg name; var n, obj; (> .perms(sender()) <); n = tosym("_clear_var_" + tostr(time())); catch any { .compile(["clear_var(" + toliteral(name) + ");"], n); for obj in (.descendants()) { (| obj.(n)() |); pause(); } (| del_method(n) |); } with handler { (| del_method(n) |); } . public ancestors_to arg obj; var a, out; out = [this()]; for a in (.ancestors()) { if (a.has_ancestor(obj)) out = out.setadd(a); } return out; . public descendants_to: disallow_overrides arg checked, levels, maxlev; var c, list; list = [this()]; levels = levels + 1; // check parents if (!maxlev || maxlev != levels) { for c in (.children()) { list = list + [c.descendants_to(checked, levels, maxlev)]; checked = checked.setadd(c); } } return list; . public ancestry arg gen; var i, out; out = []; if (type(gen) == 'dbref) { for i in (.ancestors()) { if (i.has_ancestor(gen)) out = [@out, i]; } return out; } if (gen != 0) { for i in (.parents()) out = out.union(i.ancestry(gen - 1)); } return out; . public generations arg gen; var p, out; out = [this()]; if (gen != 0) { for p in (.parents()) out = out.union(p.generations(gen - 1)); } return out; . public variable_info arg [args]; var data, pattern, gen, match, definers, ancs, pparams, param, filter; // data() reformated as // [[$parent,'param,val],...] if (!.has_flag('parameters, sender())) throw(~perm, "Parameters on " + .objname() + " are not readable by " + sender().objname()); if (args) { definers = args[2]; filter = args[3]; } else { filter = ""; } if (definers) gen = ['ancestors_to, definers[1]]; else if (!gen) gen = ['generations, 1]; ancs = .(gen[1])(gen[2]); if (definers) ancs = $list.intersection(ancs, definers); if (!ancs) ancs = this(); data = []; match = (| .setting("match-with") |) || 'match_regexp; for pparams in ($list.reverse($sys.sender_data())) { if (valid(pparams[1]) && pparams[1] in ancs) { for param in (pparams[2]) { if ($string.(match)(filter, tostr(param[1]))) data = [@data, [pparams[1], @param]]; } } } return data; . public method_flags: disallow_overrides, synchronized arg method; if (!.has_flag('methods, sender())) throw(~perm, sender().objname() + " doesn't have permission to find methods on " + .objname()); return (> method_flags(method) <); . public method_state: disallow_overrides, synchronized arg method; if (!.has_flag('methods, sender())) throw(~perm, sender().objname() + " doesn't have permission to find methods on " + .objname()); return (> method_state(method) <); . public set_method_flags: disallow_overrides, synchronized arg method, flags; if (!.is_writable_by(sender())) throw(~perm, sender().objname() + " cannot write to " + .objname()); if ('locked in flags && !$sys.is_system(sender())) throw(~perm, "Only administrators can set the locked method flag."); return (> set_method_flags(method, flags) <); . public set_method_state: disallow_overrides, synchronized arg method, state; if (!.is_writable_by(sender())) throw(~perm, sender().objname() + " cannot write to " + .objname()); return (> set_method_state(method, state) <); . public method_args arg method; if (!.has_flag('methods, sender())) throw(~perm, sender().objname() + " doesn't have permission to find methods on " + .objname()); return (> method_args(method) <); . public set_flags: disallow_overrides arg new_flags; (> .perms(sender(), 'manager) <); if (type(new_flags) != 'list) throw(~invflags, "Flags must be submitted as a list of symbols."); if (!new_flags && flags) return clear_var('flags); if ('core in new_flags && !$sys.is_system(sender())) throw(~perm, "Only system objects can set the 'core flag."); 'fertile in new_flags && (> .perms(sender, 'manager) <); flags = new_flags; . public managed: disallow_overrides return managed || []; . root add_managed_obj: disallow_overrides managed = (managed || []).setadd(sender()); . root del_managed_obj: disallow_overrides managed = (managed || []).setremove(sender()); if (!managed) clear_var('managed); . public writes: disallow_overrides (> .perms(sender(), 'trusts) <); return writes || []; . root add_writable_obj: disallow_overrides writes = (writes || []).setadd(sender()); . root del_writable_obj: disallow_overrides writes = (writes || []).setremove(sender()); if (!writes) clear_var('writes); . public trusted_by: disallow_overrides return trusted_by || []; . root add_trusted_obj: disallow_overrides trusted_by = (trusted_by || []).setadd(sender()); . root del_trusted_obj: disallow_overrides trusted_by = (trusted_by || []).setremove(sender()); if (!trusted_by) clear_var('trusted_by); . public has_flag: disallow_overrides arg flag, [sender]; if (flag == 'core) return flag in .flags(); return flag in .flags() || .trusts([@sender, sender()][1]); . public flags: disallow_overrides return flags || []; . root clean_root var obj, type, list; for type in (['owners, 'owned, 'managed, 'writes]) { if (list = get_var(type)) { list = list.valid_objects(); if (!list) clear_var(type); else set_var(type, list); } } . public _clean_database: disallow_overrides var obj, iobjs, vobjs, icount, result, name; (> .perms(sender(), $sys) <); for obj in (.descendants()) { if (!valid(obj)) { iobjs = iobjs + 1; } else { obj.clean_root(); vobjs = vobjs + 1; name = tosym("clean_" + tostr(obj.objname('symbol))); catch ~methodnf { def = find_method(name); if (def != obj) { icount = icount + 1; } else { result = (| obj.(name)() |); (| $sys.log(result) |); } } } // incase we need more ticks pause(); } return [iobjs, vobjs, icount]; . parent $root object $foundation var $root child_index 5 var $root fertile 1 var $root trusted [] var $root inited 1 var $root objname 'foundation var $root created_on 796268969 var $root indestructable 1 var $root flags ['parameters, 'methods, 'code, 'fertile, 'core] public configure // it is intended that this method is called just after an object is created // descended methods should pass() up the line. If something which should // be set, is already set, do NOT re-set it again. Blank returns at prompts // should always be taken as a skip request, along with "skip" and "@skip" (> .perms(sender()) <); . parent $root object $core var $root objname 'core var $root child_index 4 var $root inited 1 var $root created_on 796268969 var $root indestructable 1 var $root flags ['parameters, 'methods, 'code, 'core] parent $foundation object $event_handler var $root inited 1 var $root objname 'event_handler var $root created_on 796268969 var $root indestructable 1 var $root flags ['parameters, 'methods, 'code, 'core] public event arg frob; . public announce_event arg frob; var x; for x in (.environment()) (| x.event(frob) |); . parent $foundation object $has_commands var $root fertile 1 var $root inited 1 var $root objname 'has_commands var $root created_on 796268969 var $root indestructable 1 var $root flags ['parameters, 'methods, 'code, 'fertile, 'core] var $has_commands commands 0 var $has_commands shortcuts #[] var $has_commands local 0 var $has_commands remote 0 public add_command arg template, method, [type]; var cmd, types, count, x; (> .perms(sender()) <); type = [@type, 'local][1]; if ("*" in template) throw(~invcmd, "Invalid command, command templates cannot contain \"*\"!."); cmd = (> $command_lib.validate_command_template(template) <); if (!(type in ['local, 'remote])) throw(~type, "Command types can be either 'local or 'remote"); if ('this in cmd[2].values().slice(1)) type = 'remote; if (type == 'remote) { for x in (cmd[2].values().slice(1)) { if (x == 'this) count = count + 1; } if (!count) throw(~add_command, "Command type defined as remote with no <this> argument."); else if (count > 1) throw(~add_command, "More than one <this> argument specified in template."); } if (!get_var(type)) set_var(type, #[]); set_var(type, get_var(type).add_elem_union(cmd[1][1], [@cmd[1], template, method, cmd[2]])); . public all_local_commands var cmds, a, acmds; cmds = #[]; for a in (ancestors()) { if (a == definer()) break; if (acmds = (| a.local_commands() |)) cmds = cmds.add(a, acmds); } return cmds; . public local_commands return local || #[]; . public get_command_info arg type, cmd; var info, a, ainfo; info = []; for a in (ancestors()) { if (a == definer()) break; if (ainfo = (| a.command_info(type, cmd) |)) info = info.union(ainfo); } return info; . public del_command arg template, method; var cmd, c, d, info, type; (> .perms(sender()) <); cmd = template.explode(); if (!cmd) throw(~type, "Invalid template."); cmd = cmd[1]; info = #[['local, .get_command_info('local, cmd)]]; info = info.add('remote, .get_command_info('remote, cmd)); for type in (info) { for c in (type[2]) { if (c[3] == template && c[4] == method) { set_var(type[1], get_var(type[1]).del_elem(cmd, c)); d = d + 1; } } } return d; . public remote_commands return remote || #[]; . root init_has_commands local = remote = shortcuts = #[]; . root uninit_has_commands .clear_variables(@.parameters()); . public add_shortcut arg shortcut, template, method; var relation; (> .perms(sender()) <); if (type(shortcut) != 'string || type(template) != 'string) throw(~type, "Both shortcut and template must be strings."); if (type(method) != 'symbol) throw(~type, "Method must be submitted as a symbol."); relation = (> $command_lib.parse_relation(shortcut, template) <); if (!shortcuts) shortcuts = #[]; shortcuts = shortcuts.add(pattern, [method, relation]); . public del_shortcut arg shortcut; var value; (> .perms(sender()) <); value = (| shortcuts.del(shortcut) |); if (type(value) != 'dictionary) throw(~shortcutnf, "Shortcut \"" + shortcut + "\" is not defined on this object."); shortcuts = value; . public all_shortcuts var s, a, as; s = []; for a in (ancestors()) { if (a == definer()) break; if (as = (| a.shortcuts() |)) s = [@s, @as.to_list()]; } return s; . public get_shortcut_info arg shortcut; return (| shortcuts[shortcut] |) || throw(~shortcutnf, "Shortcut \"" + shortcut + "\" is not defined on this object.", shortcut); . public coreify_has_commands var line; (> .perms(caller(), $sys) <); line = "commands = " + toliteral(commands) + ";"; line = line + "shortcuts = " + toliteral(shortcuts) + ";"; .compile([line], 'CORE_EVAL); commands = shortcuts = 0; . public shortcuts return shortcuts || #[]; . public command_info arg type, cmd; return (| get_var(type)[cmd] |) || throw(~cmdnf, "Command \"" + cmd + "\" is not defined on this object.", cmd); . public all_remote_commands var cmds, a, acmds; cmds = #[]; for a in (ancestors()) { if (a == definer()) break; if (acmds = (| a.remote_commands() |)) cmds = cmds.add(a, acmds); } return cmds; . parent $foundation object $environment var $root inited 1 var $root objname 'environment var $root created_on 796268969 var $root indestructable 1 var $root flags ['parameters, 'methods, 'code, 'core] public environment return []; . public match_environment arg str; var obj, env, found, match; if (!str) throw(~objnf, "No object specified.", str); str = str.strip_article(); // Handle special cases. if (str == "me") return this(); else if (str[1] == "$" || str[1] == "#") return (> $object_lib.to_dbref(str) <); else if (str in ["it", "him", "her"]) return (| .match_context(str) |) || throw(~context, "I don't see " + str + " here, do you?"); // Ok, do the long matching process... found = []; for obj in (.environment()) { if (obj.name('noarticle) == str) return obj; if (match = obj.match_name(str)) found = found + [[obj, match]]; } if (!found) throw(~objnf, "No \"" + str + "\" in your environment.", str); if (found.length() == 1) { return found[1][1]; } else { match = found.slice(2); if (match.count(found.slice(2)) == 1) return found[match in found.slice(2)][1]; else throw(~ambig, "\"" + str + "\" can match " + found.slice(1).map('name).to_english("", " or ") + "."); } . public local_to_environment arg obj; return obj in .environment(); . parent $foundation object $has_messages var $root fertile 1 var $root inited 1 var $root objname 'has_messages var $root created_on 796268969 var $root indestructable 1 var $root flags ['parameters, 'methods, 'code, 'fertile, 'core] var $has_messages messages 0 var $has_messages message_info 0 public add_message arg name; (> .perms(sender(), 'writer) <); if (type(name) != 'string) throw(~type, "Name must be a string"); if (!messages) messages = #[]; if (!message_info) message_info = #[]; message_info = message_info.add(name, #[]); . public message_info arg name, field; var m; catch ~keynf { m = message_info[name]; } with handler { throw(~messagenf, "Message " + name + " is not defined here."); } switch (field) { case 'evaluator: return (| m['evaluator] |) || $cml2_base_eval; case 'compiler: return (| m['compiler] |) || $cml2_compiler; case 'uncompiler: return (| m['uncompiler] |) || $cml2_uncompiler; default: throw(~fieldnf, "Invalid field."); } . public set_message_info arg name, field, value; var m; catch ~keynf { m = message_info[name]; } with handler { throw(~messagenf, "Message " + name + " is not defined here."); } m = m.add(field, value); message_info = message_info.add(name, m); . public message_parts arg name; return (| message_info[name][4] |) || []; . public evalutor arg name; return defined_messages[name][1]; . public set_evaluator arg name, evaluator; var current; .perms(sender(), 'writer); current = defined_messages[name]; current = current.replace(1, evaluator); .set_message_info(name, current); . public defines_message arg name; var n; // returns 1 if the message <name> is defined here. if (message_info) { for n in (message_info.keys()) { if (name == n) return 1; } } return 0; . public del_message arg name; var mess, kids; (> .perms(sender(), 'writer) <); message_info = message_info.del(name); . public local_messages return messages || #[]; . public messages var all_messages, a, a_messages, d_messages, d, m, my_d; // return all messages set on this() or parents // a : on eancestor // all_messages: the sum total of message // a_messages: messages from ancestor a // d: the definer of a message // d_messages: messages from ancestor a, defined on d // m: a specific message // my_d: messags from definer d that have already been found. all_messages = #[]; for a in (.ancestors()) { if (a == definer()) break; if (a.has_ancestor(definer())) { a_messages = a.local_messages(); for d in (a_messages.keys()) { d_messages = a_messages[d]; my_d = (| all_messages[d] |) || #[]; for m in (d_messages.keys()) { if (!(m in my_d.keys())) my_d = my_d.add(m, d_messages[m]); } all_messages = all_messages.add(d, my_d); } } } return all_messages; . public local_message arg name, [definer]; var d; if (messages) { if (!definer) { for d in (messages.keys()) { catch ~keynf { return messages[d][name]; } } } else { catch ~keynf { return messages[definer[1]][name]; } } } throw(~messagenf, "Message was not found."); . public prep_evaluator arg name; .perms(sender(), 'writers); return (.messaage_info(name))[2]; // 9-26-95/19:57 Jeff ($jeff), moved from $has_messages.prep_evalutor . public message arg name, [definer]; var a, message, mes, m, empty; //retrieve the specified message as ctext if (definer) definer = definer[1]; else definer = (._find_message_definer(name))[2]; message = $message_frob.new(#[]); empty = $ctext_frob.new(""); for a in (.ancestors()) { catch ~methodnf, ~messagenf { return a.local_message(name, definer); } } throw(~messagenf, "No matching message."); . public set_message arg name, message, [definer]; var mes, partial, compiler; (> .perms(sender(), 'writer) <); definer = ._find_message_definer(name); partial = definer[1]; definer = definer[2]; if (!messages) messages = #[]; mes = (| messages[definer] |) || #[]; compiler = definer.message_info(partial, 'compiler); message = compiler.compile_cml(message); messages = messages.add(definer, mes.add(name, message)); . public local_matching_messages arg name, [definer]; var n, matches, d; matches = []; if (definer) { for n in (messages[definer].keys()) { if ($string.match_begin(n, name)) matches = [@matches, n]; } } else { for d in (messages.keys()) { for n in (messages[d].keys()) { if ($string.match_begin(n, name)) matches = [@matches, n]; } } } return matches; . public matching_messages arg name, definer; var mes, a, m, len, messages, found, anc; mes = $message_frob.new(#[]); found = []; //if (messages) // return mes; name = name + "."; len = name.length(); anc = .ancestors(); a = $has_messages in anc; anc = anc.subrange(1, a - 1); for a in (anc) { messages = (| (a.local_messages())[definer] |) || #[]; for m in (messages.keys()) { if ($string.match_begin(m, name) && !(m in found)) mes = mes.add_entry(m.subrange(len + 1), messages[m]); found = [@found, m]; } } return mes; . public _del_message arg name; var mess; mess = messages[sender()]; mess = mess.del(name); messages = messages.add(sender(), mess); . public _find_message_definer arg name; var a, pos, name2; pos = name.rindex("."); if (pos) name2 = name.subrange(1, pos - 1); for a in (.ancestors()) { catch ~methodnf { if (a.defines_message(name)) return [name, a]; else if (a.defines_message(name2)) return [name2, a]; } } throw(~definernf, "Could not find definer for " + name + "."); . public eval_message arg name, vars, [definer]; var message, partial; definer = [@definer, 0][1]; if (!definer) { definer = ._find_message_definer(name); partial = definer[1]; definer = definer[2]; } else { partial = name; } vars = vars.add('evaluator, definer.message_info(partial, 'evaluator)); message = .matching_messages(partial, definer); if (message == (<$message_frob, #[]>)) message = $message_frob.new(#[["general", .message(partial, definer)]]); message = message.set_vars(vars); return message.eval_ctext(vars.add('time, 'pre)); . root uninit_has_messages messages = 0; defined_messages = 0; . public _del_message_part arg name, part; var m, mess; .debug(sender(), name, part); if (messages && sender() in messages.keys()) { mess = messages[sender()]; .debug(mess); if (name in mess.keys()) { m = mess[name]; .debug(m); m = m.del_entry(part); .debug(m); mess = mess.add(name, m); messages = messages.add(sender(), mess); } } . public unset_message arg message, definer; var mes; mes = (| messages[definer] |) || #[]; mes = mes.del(message); messages = messages.add(definer, mes); . public set_var arg this, name, value; var vars; vars = this[2]; vars = vars.add(name, value); return (<this(), [this[1], vars]>); . public set_vars arg this, new; var vars, key; vars = this[2]; for key in (new) vars = vars.add(key, new[key]); return (<this(), [this[1], vars]>); . parent $foundation object $public var $root fertile 1 var $root inited 1 var $root objname 'public var $root created_on 796268969 var $root indestructable 1 var $root flags ['parameters, 'methods, 'code, 'fertile, 'core] var $public public [] public is_publicly arg what; return (| what in public |) || 0; . public set_public arg what; var x, valid; if (sender() != this()) (> .perms(sender(), 'manager) <); if (!public) public = []; if (type(what) == 'symbol) { if (what in public) return; what = [@public, what]; } if (type(what) != 'list) throw(~type, toliteral(what) + " is an invalid type."); public = what; . public public return public; . parent $foundation object $network var $root objname 'network var $root child_index 3 var $root created_on 809051864 var $root inited 1 var $root indestructable 1 var $root flags ['parameters, 'methods, 'code, 'core] public reassign_connection arg [args]; return (> reassign_connection(@args) <); . public hostname arg [args]; return (> hostname(@args) <); . public ip arg [args]; return (> ip(@args) <); . parent $foundation object $help_root var $root inited 1 var $root objname 'help_root var $root created_on 796268969 var $root indestructable 1 var $root flags ['parameters, 'methods, 'code, 'core] parent $foundation object $text var $root fertile 1 var $root inited 1 var $root objname 'text var $root created_on 796268969 var $root indestructable 1 var $root flags ['parameters, 'methods, 'code, 'fertile, 'core] var $text text 0 root init_text text = []; . root uninit_text text = []; . public text // returns text if (!.is_writable_by(sender()) && sender() != this()) throw(~perm, "Permission Denied."); return text; . public set_text arg txt; // resets ,text to the list sent if (!.is_writable_by(sender()) && sender() != this()) throw(~perm, "Permission Denied."); text = txt; . public ins_line arg txt, [loc]; // inserts txt at loc (where loc is an integer) if (!.is_writable_by(sender()) && sender() != this()) throw(~perm, "Permission Denied."); if (!loc) text = [@text, txt]; else text = (> text.insert(loc, txt) <); . public del_text // deletes all text if (!.is_writable_by(sender()) && sender() != this()) throw(~perm, "Permission Denied."); text = []; . public del_line arg linestr; // deletes "line" where line is the actual line to delete if (!.is_writable_by(sender()) && sender() != this()) throw(~perm, "Permission Denied."); text = text.setremove(line); . public del_nline arg nline; // deletes nline where nline is an integer reference to a list location if (!.is_writable_by(sender()) && sender() != this()) throw(~perm, "Permission Denied."); text = (> text.delete(nline) <); . public ins_lines arg lines, loc; var line; // inserts txt at loc (where loc is an integer) if (!.is_writable_by(sender()) && sender() != this()) throw(~perm, "Permission Denied."); if (type(lines) != 'list) throw(~type, "Lines should be passed as a list of strings."); for line in (lines) { text = (> text.insert(loc, line) <); loc = loc + 1; } . parent $foundation object $messaged var $root fertile 1 var $root inited 1 var $root objname 'messaged var $root created_on 796268969 var $root indestructable 1 var $root flags ['parameters, 'methods, 'code, 'fertile, 'core] var $messaged messages 0 public messages .perms(sender(), 'this); return messages || #[]; . public all_messages var msgs, anc, all; // For message to call when inheriting, or something .perms(sender(), 'this); all = #[]; for anc in (.ancestors()) { msgs = (| anc.messages() |); if (msgs) all = all.union(msgs); if (anc == definer()) break; } return all; . public message arg id; var ret; // Don't check .all_messages, we should get rid of it. Methods // calling .message should have their own defaults. // ret = (| (.all_messages())[id] |); return (| (.messages())[id] |) || 0; . public add_message arg id, msg; (> .perms(sender()) <); if (!messages) messages = #[]; if (.has_message(id)) throw(~msgexists, "Message already defined."); messages = messages.add(id, msg); . public set_message arg id, msg; (> .perms(sender()) <); if (!messages) messages = #[]; if (.defines_msg(id)) messages = messages.replace(id, msg); else .add_message(id, msg); . public has_message arg id; return id in .all_messages().keys(); . public defines_msg arg id; return id in .messages().keys(); . root init_messaged messages = #[]; . parent $foundation object $has_settings var $root child_index 1 var $root fertile 1 var $root inited 1 var $root flags ['parameters, 'methods, 'code, 'fertile, 'core] var $root indestructable 1 var $root objname 'has_settings var $root created_on 796268969 var $has_settings settings #[] var $has_settings defined_settings #[] var $has_settings local_settings [] root uninit_has_settings settings = 0; defined_settings = 0; local_settings = 0; . public _find_definers arg name, count, [begin]; var a, matches; // Find a definer for <name> // <count> is a number // 1 finds the first possible definer // 0 finds all // If <begin> is given cound a match_begin as a match matches = []; for a in (ancestors()) { if (a.has_ancestor($has_settings)) { if (a.defines_setting(name, begin)) { switch (count) { case 0: matches = [@matches, a]; case 1: return [@matches, a]; default: matches = [@matches, a]; count = count - 1; } } } } return matches; . public set_setting arg definer, name, value; var options; (> .perms(sender(), 'writers) <); if (type(name) != 'string) throw(~type, "name must be a string"); if (!definer) definer = ._find_setting_definer(name); options = definer.configure_setting(name); value = (> .((| options['check] |) || 'is_any)(definer, value, @(| options['check_args] |) || []) <); (> .((| options['set] |) || 'set_local_setting)(definer, name, value, sender(), @(| options['set_args] |) || []) <); if (!local_settings) local_settings = []; local_settings = local_settings.union([name]); . public add_setting arg name, [options]; (> .perms(sender(), 'writers) <); if (type(name) != 'string) throw(~type, "name must be a string"); options = [@options, #[]][1]; if (!defined_settings) defined_settings = #[]; if (defined_settings.contains(name)) throw(~error, .objname() + " already has a setting named " + name); defined_settings = defined_settings.add(name, ._default_options()); .configure_setting(name, options); . public defines_setting arg name; if (name in defined_settings.keys()) return 1; return 0; . public del_setting arg name; var k, m; (> .perms(sender(), 'writers) <); if (!(name in defined_settings.keys())) throw(~namenf, name + " not defined on " + .dbref()); m = defined_settings[name]['del]; defined_settings = defined_settings.del(name); for k in (.children()) (| k.m(this(), name) |); . public is_boolean arg definer, value, [args]; if (!value || value in ["y", "yes", "true", "t", "1", "on"]) return 1; return 0; . public get_inherited_setting arg name, definer, [args]; var sets, a; for a in (.ancestors()) { if (a.has_ancestor(definer) && a.local_settings(definer)) return a.get_local_setting(definer, name); } return 0; . public get_indirect_setting arg name, definer, args; var fname, val; fname = ._to_fullname(name, definer); if (fname in setting_data.keys()) { val = setting_data[fname]; if (type(val) == 'dbref) return (> setting_data[fname].get_setting(spec, definer, args) <); else return setting_data[fname]; } else { return (definer.setting_data())[fname]; } . public setting arg name, [definer]; var sets, options; definer = [@definer, 0][1]; if (type(name) != 'string) throw(~type, "name must be a string"); if (type(definer) != 'dbref && definer != 0) throw(~type, "definer must be zero or a dbref"); if (!name && !definer) throw(~huh, "definer must be non-zero or name must be given"); if (!definer) { definer = ._find_setting_definer(name); if (!definer) throw(~definernf, "No definer could be found for " + name); } else if (!name) { sets = #[]; for name in (definer.defined_settings()) { options = definer.configure_setting(name); catch ~keynf { .(options['access_check])(sender()); } sets = sets.add(name, .((| options['get] |) || 'get_local_method)(name, definer, @(| options['get_args] |) || [])); } return sets; } options = definer.configure_setting(name); return (> .((| options['get] |) || 'get_local_setting)(name, definer, @(| options['get_args] |) || []) <); . public default_setting_info return #[['type, "string"], ['check, 'is_anything], ['get, 'get_direct_setting], ['set, 'set_direct_setting], ['del, 'del_direct_setting], ['set_args, ['name, 'definer, 'value, 'style]], ['get_args, ['name, 'definer]]]; . public _find_setting_definer arg name; var a; for a in (.ancestors()) { if (a.has_ancestor(definer()) && name in a.defined_settings()) return a; } throw(~definernf, "Unable to find setting " + toliteral(name) + " on " + .name() + "."); . public _default_options return #[['get, 'get_local_setting], ['set, 'set_local_setting], ['check, 'is_any], ['del, 'delete_local_setting], ['check_args, []], ['get_args, []], ['set_args, []]]; . public configure_setting arg name, [options]; var o, new; //configure options for a setting // check perms and types if (type(name) != 'string) throw(~type, "name must be a string."); if (options) options = options[1]; else options = #[]; if (type(options) != 'dictionary) throw(~type, "options must be a dictionary."); //make sure the name exists if (!(name in defined_settings.keys())) throw(~namenf, "Setting " + name + " is not defined on " + .objname()); //If no options were given return the current options if (!options) return defined_settings[name]; //ok, now iterate through the options and make changes. (> .perms(sender(), 'writers) <); new = defined_settings[name]; for o in (options.keys()) new = new.add(o, options[o]); defined_settings = defined_settings.add(name, new); . public defined_settings return (| defined_settings.keys() |) || []; . public delete_local_setting arg definer, name; var sets; (> .perms(sender(), this()) <); sets = (| defined_settings[definer] |) || #[]; sets = (| sets.del(name) |) || sets; defined_settings = sets; . public is_any arg definer, value, [args]; return value; . public set_local_setting arg definer, name, value, [args]; var sets; (> .perms(sender(), 'this) <); if (!settings) settings = #[]; sets = (| settings[definer] |) || #[]; sets = sets.add(name, value); settings = settings.add(definer, sets); . public get_local_setting: disallow_overrides arg name, definer, [args]; return (| settings[definer][name] |) || throw(~setting, "Setting \"" + name + "\" has not been defined."); . root init_has_settings defined_settings = #[]; local_settings = #[]; settings = #[]; . public settings var a, out, s; //returns all settings available on this object out = #[]; for a in (.ancestors()) { if (a == definer()) break; s = (| a.defined_settings() |) || []; if (s) out = out.add(a, s); } return out; . public is_list_of arg definer, value, type; var out, element; switch (type(value)) { case 'string: if (value[1] != "[" || value.last() != "]") throw(~type, "value is not parsable as a list."); value = value.subrange(2, value.length() - 2).explode(","); .debug(value); out = []; for element in (value) out = [@out, .is_type(definer, element.strip(" "), type)]; return out; case 'list: out = []; for element in (value) out = [@out, .is_type(definer, element, type)]; return out; default: throw(~type, "value is not parsable as list."); } . public is_type arg definer, value, type; if (type(value) == type) return value; switch (type) { case 'string: return toliteral(value); case 'integer: if (value.is_numeric()) return toint(value); else throw(~type, "Value is unparseable as integer."); case 'dbref: return $object_lib.to_dbref(value); default: return value; } . public local_setting arg [definer]; definer = [definer[1], 0][1]; if (definer) return (| local_settings[definer] |) || []; return local_settings; . public local_settings arg [definer]; definer = [@definer, 0][1]; if (definer) return (| local_settings[definer] |) || []; return local_settings; . public display_setting arg name, [definer]; var sets, options, s; (> .perms(sender(), 'trusts) <); definer = [@definer, 0][1]; if (type(name) != 'string) throw(~type, "name must be a string"); if (type(definer) != 'dbref && definer != 0) throw(~type, "definer must be zero or a dbref"); if (!name && !definer) throw(~huh, "definer must be non-zero or name must be given"); if (!definer) { definer = ._find_setting_definer(name); if (!definer) throw(~definernf, "No definer could be found for " + name); } else if (!name) { sets = #[]; for name in (definer.defined_settings()) { options = definer.configure_setting(name); catch ~keynf { .(options['access_check])(sender()); } s = .((| options['get] |) || 'get_local_method)(name, definer, @(| options['get_args] |) || []); sets = sets.add(name, (| .(options['display])(s) |) || s); } return sets; } options = definer.configure_setting(name); s = (> .((| options['get] |) || 'get_local_setting)(name, definer, @(| options['get_args] |) || []) <); return (| .(options['display])(s) |) || $data_lib.unparse(s, #[['dbref, ['namef, ['ref]]]]); . public display_boolean_yes_no arg value; if (value) return "yes"; else return "no"; . public display_boolean_on_off arg value; if (value) return "on"; else return "off"; . parent $has_settings object $named var $root child_index 1 var $root fertile 1 var $root inited 1 var $root objname 'named var $root created_on 796268969 var $root indestructable 1 var $root flags ['parameters, 'methods, 'code, 'fertile, 'core] var $named name ['normal, "Generic Named Object.", "a Generic Named Object."] var $named name_aliases 0 var $has_settings defined_settings #[] var $has_settings local_settings #[] var $has_settings settings #[] public set_name arg new_name, [args]; var type; (> .perms(sender()) <); if (new_name && new_name[1] in ["$", "#"]) throw(~invname, "Names cannot begin with \"$\" or \"#\"."); if (type(new_name) != 'string) throw(~type, "New name must be given as a string."); // this will not catch them all, but we can try. if ("^(a|an|the)\\s+".match_regexp(new_name)) throw(~bad_name, "Do not include articles in name."); type = [@args, 'normal][1]; if (!(type in ['prop, 'normal, 'uniq])) throw(~invarg, "Type must be one of: 'prop, 'normal or 'uniq"); switch (type) { case 'prop: new_name = [new_name, new_name]; case 'uniq: new_name = [new_name, "the " + new_name]; case 'normal: new_name = [new_name, new_name.a_or_an() + " " + new_name]; } name = [type, @new_name]; . public name_aliases return name_aliases; . public add_name_alias arg alias; .perms(sender()); name_aliases = [@name_aliases, alias]; . public del_name_alias arg alias; .perms(sender()); name_aliases = name_aliases.setremove(alias); . root init_named var objname; objname = tostr(.objname('symbol)); name = ['proper, tostr(objname), tostr(objname)]; name_aliases = []; . public match_name arg str; return .match_name_exact(str) || .match_name_aliases(str); . public name arg [args]; if (!args) return name[3]; switch (args[1]) { case 'type: return name[1]; case 'noarticle: return name[2]; default: return name; } . public match_name_aliases arg str; return (| str in name_aliases |); . public namef arg [args]; if (!args) args = [['name]]; if (args[1] == 'ref) { if (.has_ancestor($named)) args = [['name], " (", ['objname], ")"]; else args = [['objname]]; } else if (args[1] == 'xref) { if (.has_ancestor($named)) args = [['objname], " (", ['name], ")"]; else args = [['objname]]; } return pass(@args); . public hname arg [args]; return "<a href=\"/bin/describe?" + .objname() + "\">" + .namef(@args) + "</a>"; . public match_name_exact arg str; return $string.match_begin(.name('noarticle), str); . root uninit_named clear_var('name); clear_var('name_aliases); . public set_name_aliases arg [aliases]; (> .perms(sender()) <); name_aliases = aliases; . parent $foundation parent $named object $gender var $root inited 1 var $root objname 'gender var $root created_on 796268969 var $root indestructable 1 var $root flags ['parameters, 'methods, 'code, 'core] var $gender pronouns 0 var $gender gender 0 var $gender cgender_name 0 var $gender gender_name 0 var $gender person 0 var $gender has 0 var $gender number 0 var $gender context [] var $named name ['normal, "Gendered Object", "a Gendered Object"] var $named name_aliases [] var $has_settings defined_settings #[] var $has_settings local_settings #[] var $has_settings settings #[] root init_gender cgender_name = ""; gender_name = ""; // these should be inited by hand, later. pronouns = #[['pr, "itself"], ['pp, "its"], ['po, "it"], ['ps, "it"], ['pq, "its"], ['prc, "Itself"], ['ppc, "Its"], ['poc, "It"], ['psc, "It"], ['pqc, "Its"], ['have, "has"]]; . public pronoun arg pronoun; return pronouns[pronoun]; . public gender return gender; . public set_gender_names arg name, cname; .perms(sender()); cgender_name = cname; gender_name = name; . public set_pronouns arg nmbr, ps, po, pp, pq, pr, psc, poc, ppc, pqc, prc; var x; .perms(sender(), 'manager); pronouns = #[['pr, pr], ['pp, pp], ['po, po], ['ps, ps], ['pq, pq], ['prc, prc], ['ppc, ppc], ['poc, poc], ['psc, psc], ['pqc, pqc]]; number = nmbr; context = [ps, po, pp, pq, pr, psc, poc, ppc, pqc, prc]; . public pronouns return pronouns; . public gender_name arg [caps]; caps = [@caps, 'null][1]; switch (caps) { case 'caps: return cgender_name; default: return gender_name; } . public context return context; . parent $core object $libraries var $root child_index 8 var $root fertile 1 var $root inited 1 var $root objname 'libraries var $root created_on 796268969 var $root indestructable 1 var $root flags ['parameters, 'methods, 'code, 'fertile, 'core] parent $core object $misc var $root child_index 26 var $root fertile 1 var $root inited 1 var $root objname 'misc var $root created_on 796268969 var $root indestructable 1 var $root flags ['parameters, 'methods, 'code, 'fertile, 'core] parent $core object $utilities var $root child_index 11 var $root inited 1 var $root objname 'utilities var $root created_on 796268969 var $root indestructable 1 var $root flags ['parameters, 'methods, 'code, 'core] parent $core object $frob var $root child_index 4 var $root fertile 1 var $root inited 1 var $root objname 'frob var $root created_on 796268969 var $root indestructable 1 var $root flags ['parameters, 'methods, 'code, 'fertile, 'core] public unparse arg rep; return "<" + $data_lib.unparse(this()) + ", " + $data_lib.unparse(rep) + ">"; . public new arg value; return (<this(), value>); . public to_frob arg value; // this differs from .new in it's application return (<this(), value>); . public value arg value; return value; . parent $core object $sys var $sys admins [] var $sys agents [$root, $daemon, $backdoor] var $sys startup #[['time, 813382395], ['objects, [$login_daemon, $backdoor, $lag_watcher, $http_daemon]], ['heartbeat_interval, 5]] var $sys starting #[['quota, 75000], ['exit_source, $void], ['place, $the_pit], ['new_user_class, $admin], ['anonymous_user_class, $guest]] var $sys server_address ["127.0.0.1", "somewhere.cold.org"] var $sys system_email_addresses #[['default, "nobody@localhost"]] var $sys core_version "2.0" var $sys validate_email_addresses 1 var $sys backup #[['interval, 3600], ['last, 813386253], ['next, 813389853]] var $sys system [$sys, $root, $backdoor, $control] var $sys touched 813386609 var $sys loggers [$http_interface, $daemon, $user, $connection] var $sys core_date 0 var $sys names ["root", "foundation", "core", "event_handler", "has_commands", "environment", "has_messages", "public", "network", "help_root", "text", "messaged", "has_settings", "named", "gender", "libraries", "misc", "utilities", "frob", "sys"] var $sys dumped [$root, $foundation, $core, $event_handler, $has_commands, $environment, $has_messages, $public, $network, $help_root, $text, $messaged, $has_settings, $named, $gender, $libraries, $misc, $utilities, $frob, $sys] var $root created_on 796268969 var $root inited 1 var $root objname 'sys var $root indestructable 1 var $root flags ['parameters, 'methods, 'code, 'core] var $root quota_exempt -1 public next_dbref return next_dbref(); . driver startup arg args; var opt, str, obj; if (args && "-clean" in args) { catch any { (> .clean_database() <); } with handler { .log($parse_lib.traceback(traceback())); } shutdown(); return; } catch any { // Bind all initial functions ._bind_functions(); // Set up five-second heartbeat. set_heartbeat(startup['heartbeat_interval]); // set the startup time, reset backup time. startup = startup.add('time, time()); backup = backup.add('next, time() + backup['interval]); // tell objects who should know, that we are up. if (type(args) != 'list) args = []; for obj in (startup['objects]) { .log("Calling " + obj.objname() + ".startup()"); catch any { (> obj.startup(@args) <); } with handler { .log($parse_lib.traceback(traceback())); } } } with handler { .log("Startup ERROR at " + ctime() + ":"); .log($parse_lib.traceback(traceback(), -1, "")); } . public server_info arg what, [long]; var tmp; switch (what) { case 'up_time: return time() - startup['time]; case 'startup_time: return startup['time]; case 'server_hostname: return server_address[2]; case 'server_ip: return server_address[1]; case 'load: return .load(); case 'last_backup: return backup['last]; case 'driver_version: tmp = version(); return (long ? "ColdX Genesis " | "") + tostr(tmp[1]) + "." + tostr(tmp[2]) + "-" + tostr(tmp[3]); case 'core_version: return (long ? "ColdCore " | "") + core_version; default: throw(~unknown, "Unknown flag."); } . public callers (> .perms(sender(), 'system) <); return (> callers() <); . public create_user arg name, password, email, [type]; var user; if (!(| .perms(caller(), $login_interface) |) && !(| .perms(sender(), 'system) |)) throw(~perm, "Caller and Sender are not allowed to call this method."); type = [@type, 'new_user_class][1]; catch any { user = starting[type].spawn(name); user.set_name(name); if (type == 'new_user_class) user.set_password(password); else user.set_password(tostr(time() / mtime()).crypt()); user.change_manager(user); user.set_data('email, email, 0); user.chown(user); } with handler { // Failed to initialize the child; destroy it. if (!(| user.destroy() |)) { (| user.uninitialize() |); (| del_objname(user.objname('symbol)) |); (| del_objname(tosym(name)) |); (| destroy(user) |); } rethrow(error()); } return user; . public admins return admins; . public is_admin arg obj; return obj == $sys || obj in admins; . public binary_dump if (!$sys.is_admin(sender())) throw(~perm, "Sender is not an admin."); pause(); return backup(); . public shutdown var opt, str, obj; (> .perms(sender(), $sys) <); // tell startup objects that we are closing shop for obj in (startup['objects]) { .log("Calling " + obj.objname() + ".shutdown()"); catch any { (> obj.shutdown() <); } with handler { .log($parse_lib.traceback(traceback())); } } return shutdown(); . public change_sender_parents arg parents; var p; if (caller() != $root) throw(~perm, "Caller is not $root."); (> chparents(sender(), parents) <); . public spawn_sender arg suffix, manager, [owners]; var namestr; (> .perms(caller(), $root, $sys) <); if (!owners) owners = [manager]; namestr = tostr(sender().objname('symbol)) + "_" + suffix; return .create([sender()], tosym(namestr), manager, owners); . public destroy_sender (> .perms(caller(), $root) <); (| .deassign_objname(sender().objname('symbol)) |); (> destroy(sender()) <); . public is_system arg obj; return obj in system || obj.has_ancestor($backdoor); . public log arg text; var l; if (!sender() in loggers) { if (!(| .perms(sender(), 'system) |) && !(| .perms(caller(), 'system) |)) throw(~perm, "Only system objects can log."); } if (type(text) == 'list) { for l in (text) .log(l); } else { log("[" + $time.format("%d %h %y %H:%M") + "] " + text); } . public open_connection arg [args]; (> .perms(caller(), $network) <); (> open_connection(@args) <); . driver heartbeat if (sender() != 0) throw(~perm, "Sender is not the server."); (| $scheduler.pulse() |); if (time() > backup['next]) .do_backup(this(), 'interval); . public do_backup arg [args]; var line, who, how, name, time, dirty; (> .perms(sender(), 'system) <); dirty = .dirty(); who = [@args, sender()][1]; how = [@args, 'request, 'request][2]; if (!valid(who)) who = sender(); backup = backup.add('next, time() + backup['interval]); backup = backup.add('last, time()); if (how == 'interval && !dirty) return; catch any { name = who.namef('ref); .log("BACKUP (" + name + ") "); line = "Backup called at " + $time.ltime() + " by " + name; $channels.announce('System, line); } pause(); time = time(); .binary_dump(); catch any { line = "Backup completed, executing filesystem cleanup..."; $channels.announce('System, line); pause(); } .execute("backup", []); time = time() - time; catch any { line = "Backup completed, elapsed time "; $channels.announce('System, line + $time.elapsed(time, 'long)); } . public set_startup arg what, value; var valid; (> .perms(sender(), 'system) <); valid = startup.keys(); if (!what in valid) throw(~type, "Key must be one of " + toliteral(valid)); startup = startup.add(what, value); . public sender_data var output, i; if (caller() != $root) throw(~perm, "Caller is not $root."); return data(sender()); . public get_system_email arg what; var email; // email directory for system services, such as arch admins. email = (| system_email_addresses[what] |); if (!email) email = (| system_email_addresses['default] |) || "<no email set>"; return email; . public new_admin if (caller() != $admin) throw(~perm, "Caller is not $admin."); admins = admins.setadd(sender()); . public agents return agents; . public text_dump .perms(sender(), 'this); pause(); return text_dump(); . public get_startup arg what; return starting[what]; . public set_starting arg what, value; var valid; (> .perms(sender(), 'system) <); valid = starting.keys(); if (!what in valid) throw(~type, "Key must be one of " + toliteral(valid)); starting = starting.add(what, value); . public execute arg script, args, [background]; (> .perms(sender(), 'system) <); (> execute(script, args, @background) <); . public get_starting arg what; return starting[what]; . public create arg parents, name, manager, [owners]; var new; .perms(sender(), 'system); new = create(parents); catch any { new.set_objname(name); new.initialize(); new.change_manager(manager); new.chown(@[@owners, [new]][1]); } with handler { // Failed to initialize the child; destroy it. if (!(| new.destroy() |)) { (| new.uninitialize() |); (| del_objname(new.objname('symbol)) |); (| del_objname(tosym(name)) |); (| destroy(new) |); } rethrow(error()); } return new; . public system return system; . public bind_port arg port, obj; (> .perms(caller(), $network, $backdoor) <); (> bind_port(port, obj) <); . public del_system_email arg key; (> .perms(sender(), 'manager) <); system_email_addresses = system_email_addresses.del(key); . public add_system_email arg key, email; (> .perms(sender(), 'manager) <); if (type(key) != 'symbol) throw(~type, "Key is not a symbol."); if (type(email) != 'string) throw(~type, "Email address is not a string."); system_email_addresses = system_email_addresses.add(key, email); . public compile arg code, name; var line; (> .perms(sender()) <); line = "SYSTEM: ." + tostr(name) + "() MODIFIED"; line = line + " by " + sender().namef('ref); .log(line); return (> pass(code, name) <); . public unbind_port arg port, obj; (> .perms(caller(), $network, $backdoor) <); (> unbind_port(port) <); . public tasks return (> tasks() <); . public resume arg task, [args]; (> resume(task, @args) <); . public suspend return (> suspend() <); . public validate_email_addresses return validate_email_addresses; . public reassign_connection arg obj; (> .perms(caller(), $network, $backdoor) <); (> reassign_connection(obj) <); . public cancel arg [args]; return (> cancel(@args) <); . public signal arg sig, sigstr; var line; if (sender() || caller()) throw(~perm, "Sender is not the server."); line = "** Caught Signal: " + sigstr + " **"; (| $channels.announce('System, line) |); if (!(sig in [1, 13, 16, 30, 31])) { (| $channels.announce('System, "******************************") |); (| $channels.announce('System, "** IMMINENT SERVER SHUTDOWN **") |); (| $channels.announce('System, "******************************") |); } . root sender_going_away admins = admins.setremove(sender()); agents = agents.setremove(sender()); system = system.setremove(sender()); . public do_loadcheck return; (> .perms(sender(), 'system) <); load = load.add('load, load()); (| $channels.announce('System, $time.ltime() + " LOADCHECK: " + load['load]) |); . public status return (> status() <) + [backup['interval], backup['last], backup['next]]; . public hostname arg [args]; return (> hostname(@args) <); . private _loop_for_core arg code; var obj; $root.compile(code, '___coretmp); for obj in ($root.descendants()) { obj.___coretmp(); pause(); } $root.del_method('___coretmp); . private initialize_core var obj; (| .clean_database() |); // reset child indices ._loop_for_core(["child_index = 0;"]); . public clean_database var obj, objs, iobjs, count, name, def; (> .perms(caller(), definer()) <); .log("Cleaning database ..."); count = $root._clean_database(); .log("-- " + tostr(count[1] + count[2]) + " total objects --"); .log(" (" + tostr(count[1]) + " invalid descendants of $root)"); .log(" (" + tostr(count[3]) + " with clean methods in the wrong location)"); objs = $place.descendants(); for obj in (objs) { if (!obj.has_flag('core)) obj.rehash_caches(); // incase we need more ticks pause(); } .log("-- Places command cache rehash pass complete --"); .log(" (" + tostr(objs.length()) + " total places)"); // rehash user info objs = $user.descendants(); for obj in (objs) { if (!obj.has_flag('core)) obj.purge_caches(); if ((| obj.home() != obj.location() |)) obj.move_to(obj.home()); // incase we need more ticks pause(); } .log("-- User command cache reset pass complete --"); .log(" (" + tostr(objs.length()) + " total users)"); // validate all locations content's objs = $location.descendants(); for obj in (objs) { // incase we need more ticks pause(); (| obj.validate_contents() |); if (obj.is($located_location)) { if (!valid(obj.location()) || !(obj in obj.location().contents())) { obj.move_to(obj.home() || $lost_and_found); icount = icount + 1; } } } .log("-- Location pass complete --"); .log(" (" + tostr(objs.length()) + " objects with invalid locations)"); for obj in ($connection_interface.children()) (| obj.rehash_caches() |); . public ip arg [args]; return (> ip(@args) <); . public assign_objname arg name; var keepers, x; (> .perms(caller(), $root, $sys) <); if (type(name) != 'symbol) throw(~type, "Name must be given as a symbol."); // don't run this for now--tosym is fucked. if (0) { // yeah, we change it to a string, but they don't have to know that. name = tostr(name); // lowercase all names: name = name.lowercase(); // If it isn't a keeper toss the good old error keepers = "abcdefghijklmnopqrstuvwxyz1234567890_"; for x in [1 .. name.length()] { if (!(name[x] in keepers)) throw(~type, "Name has one or more non-alphanumeric characters."); } name = tosym(name); } // make sure nobody has it yet if ((| get_dbref(name) |) != ~namenf) throw(~perm, "Name already assigned to " + get_dbref(name).namef('ref)); // woo woo, i'm filled with joy, lets give them the name. add_objname(name, sender()); . public deassign_objname arg name; (> .perms(caller(), $root, $sys) <); del_objname(name); . private _bind_functions // these will eventually be native methods bind_function('buffer_len, $buffer); bind_function('buffer_retrieve, $buffer); bind_function('buffer_append, $buffer); bind_function('buffer_replace, $buffer); bind_function('buffer_add, $buffer); bind_function('buffer_truncate, $buffer); bind_function('buffer_tail, $buffer); bind_function('buffer_to_string, $buffer); bind_function('buffer_to_strings, $buffer); bind_function('buffer_from_string, $buffer); bind_function('buffer_from_strings, $buffer); bind_function('dict_keys, $dictionary); bind_function('dict_add, $dictionary); bind_function('dict_del, $dictionary); bind_function('dict_contains, $dictionary); bind_function('listlen, $list); bind_function('sublist, $list); bind_function('insert, $list); bind_function('replace, $list); bind_function('delete, $list); bind_function('setadd, $list); bind_function('setremove, $list); bind_function('union, $list); bind_function('strlen, $string); bind_function('substr, $string); bind_function('explode, $string); bind_function('pad, $string); bind_function('match_begin, $string); bind_function('match_template, $string); bind_function('match_pattern, $string); bind_function('match_regexp, $string); bind_function('strsub, $string); bind_function('crypt, $string); bind_function('uppercase, $string); bind_function('lowercase, $string); bind_function('strcmp, $string); bind_function('strfmt, $string); bind_function('next_dbref, $sys); bind_function('load, $sys); bind_function('status, $sys); bind_function('version, $sys); bind_function('strftime, $time); // bind_function('bind_function, this()); bind_function('unbind_function, this()); bind_function('create, this()); bind_function('chparents, this()); bind_function('log, this()); bind_function('reassign_connection, $daemon); bind_function('binary_dump, this()); bind_function('text_dump, this()); bind_function('execute, this()); bind_function('shutdown, this()); bind_function('bind_port, $daemon); bind_function('unbind_port, $daemon); bind_function('hostname, $network); bind_function('ip, $network); bind_function('load, this()); bind_function('status, this()); bind_function('backup, this()); . public add_to_system arg obj; if (!.is_admin(sender())) throw(~perm, "Sender is not an admin."); if (!(obj in admins || obj in agents)) throw(~perm, "Object is not an agent or admin."); system = system.union([obj]); . public del_from_system arg obj; if (!.is_admin(sender())) throw(~perm, "Sender is not an admin."); if (!(obj in admins || obj in agents)) throw(~perm, "Object is not an agent or admin."); system = system.setremove(obj); . public touch touched = time(); . public touched return touched; . public backup return backup; . public dirty return touched > backup['last]; . public _clean_object_ownership arg objs; var code, cname, obj; (> .perms(caller(), definer()) <); // this will be removed when object ownership works better code = ["var obj;"]; code = code + ["for obj in (owners) {"]; code = code + [" if (!(this() in obj.owned()))"]; code = code + [" owners = owners.setremove(obj);"]; code = code + [" pause();"]; code = code + ["}"]; code = code + ["for obj in (owned) {"]; code = code + [" if (!valid(obj)) owned = owned.setremove(obj);"]; code = code + [" pause();"]; code = code + ["}"]; code = code + ["if (!valid(manager)) manager = this();"]; cname = tosym("___clean_" + tostr(time())); // do it catch any { $root.compile(code, cname); for obj in (objs) { (| obj.(cname)() |); pause(); } } $root.del_method(cname); .log("-- Object Ownership pass completed --"); . public do_shutdown arg [args]; var why, time, increments, line, name, mins; if (!$sys.is_admin(sender()) || definer() != this()) throw(~perm, "Sender is not an admin."); time = [@args, 0][1]; why = [@args, "", ""][2]; increments = [600, 300, 180, 60]; while (increments && time < increments[1]) increments = increments.delete(1); name = sender().namef('xref); .log("*** SHUTDOWN called by " + name + " ***"); if (why) { why = "*** " + why + " ***"; .log(why); } while (1) { if (!increments) { $channels.announce('all, "*** SYSTEM SHUTDOWN ***"); break; } line = "*** SYSTEM SHUTDOWN IN "; mins = increments[1] / 60; line = line + tostr(mins) + " MINUTE" + (mins == 1 ? "" | "S"); line = line + " CALLED BY " + name + " ***"; $channels.announce('all, line); if (why) $channels.announce('all, why); $scheduler.sleep(increments[1]); increments = increments.delete(1); } return .shutdown(); . public core_date return core_date; . public loggers return loggers; . private dump_names var x, o, n; x = 1; o = []; if ((| names |) == ~paramnf) return "No names to dump"; for n in (names) { pause(); if (n == "sys") { o = o + ["name " + n + " 0"]; } else { o = o + ["name " + n + " " + tostr(x)]; x = x + 1; } } .tell(o); .del_parameter('names); . private dump_db arg c; var obj, list; // This uses a dumping script i've written in perl. Once file // ops are fully online, this will be much more comprehensive. // Furthermore, you need to dump the names by hand! // Also, this is _NOT_ the 1.0 textdump format. if ((| names |) == ~paramnf) .add_parameter('names); if ((| dumped |) == ~paramnf) .add_parameter('dumped); names = dumped = []; list = $root.descendants(); c.write("#$#LOG#$#"); while (list) { obj = (| list[1] |); if (!obj) break; list = list.delete(1); pause(); while (list && obj && obj in dumped) { obj = (| list[1] |); if (!obj) break; list = list.delete(1); pause(); } if (obj) .dump_object(obj, c); } c.write("#$#/LOG#$#"); .del_parameter('dumped); return "Now log $sys.dump_names()"; . private dump_object arg obj, c; var p, name, v, l, code, line, f, flags; // call .dump_db() for p in (obj.parents()) { if (!(p in dumped)) .dump_object(p, c); } dumped = dumped + [obj]; names = names + [tostr(obj.objname('symbol))]; c.write(["", ""]); for p in (obj.parents()) c.write("parent " + p.objname()); c.write(["object " + obj.objname(), ""]); for p in (obj.data()) { name = (| p[1].objname() |) || toliteral(p[1]); for v in (p[2]) c.write("var " + name + " " + tostr(v[1]) + " " + $data_lib.unparse(v[2])); pause(); } c.write(""); for v in (obj.methods()) { if (v == 'tmp_eval) continue; switch (obj.method_state(v)) { case 'root: line = "root "; case 'driver: line = "driver "; case 'public: line = "public "; case 'protected: line = "protected "; case 'private: line = "private "; } code = obj.list_method(v); line = line + tostr(v); // write $symbol and just have flags.map('tostr).join(", "); flags = obj.method_flags(v); f = ""; if ('disallow_overrides in flags) f = "disallow_overrides"; if ('synchronized in flags) f = (f ? f + ", " | "") + "synchronized"; if ('locked in flags) f = (f ? f + ", " | "") + "locked"; if ('native in flags) f = (f ? f + ", " | "") + "native"; c.write(line + (f ? ": " + f | "")); for l in (code) c.write(" " + l); c.write([".", ""]); pause(); } . parent $core object $control var $root objname 'control var $root managed [$foundation, $core, $event_handler, $has_commands, $environment, $public, $help_root, $text, $messaged, $gender, $libraries, $misc, $utilities, $frob, $sys, $backdoor, $control, $physical, $described, $exit, $thing, $place, $help_ui, $help_index, $help, $help_node, $note, $mail_message, $event_frob, $named, $user_data, $gender_female, $gender_male, $gender_plural, $gender_neuter, $dictionary, $time_root, $buffer, $string, $command_lib, $http_lib, $object_lib, $integer, $parse_lib, $code_lib, $list, $security, $mail_lib, $time_lib, $data_lib, $mail_root, $db, $user_parsers, $filters, $lock_parser, $world, $housekeeper, $root_evaluator, $channels, $places, $motd, $heart, $logic_frob, $realms_frob, $thing_frob, $read_parser, $located, $location, $user_interfaces, $editors, $located_location, $nothing, $nowhere, $void, $help_summary, $log, $movement_event, $gendered, $mail_list, $time, $dark_time, $mail_db, $registry, $null_parser, $command_aliases_parser, $conference_parser, $epic_filter, $wrap_filter, $xor, $and, $lock_frob, $not, $or, $true, $false, $realm_of_creation, $wearable_frob, $interaction, $mail_ui, $command_aliases, $bad_commands, $settings_ui, $tree_ui, $programmer_interface, $help_interface_new, $set_ui, $generic_editor, $body, $http_log, $reaper_log, $login_log, $mail_list_news, $place_db, $user_db, $or_lock_frob, $true_lock_frob, $false_lock_frob, $not_lock_frob, $object_lock_frob, $and_lock_frob, $inside_lock_frob, $code_editor, $note_editor, $scheduler, $ctext_lib, $help_lib, $symbol, $cml2, $body_cave, $detailed_place, $the_pit, $trie, $lag_watcher, $editor, $has_messages, $has_settings, $tree, $has_hooks, $ctext_frob, $ctext_tag, $reaper, $ctext2_frob, $message_frob, $ctext_filter, $cml2_evaluator, $cml2_form, $cml2_compiler, $ctext_generator, $ctext_format, $messages_ui, $cml2_format, $cml2_base_eval, $cml2_uncompiler, $connection, $daemon, $connection_interface, $login_connection, $http_connection, $http_daemon, $login_daemon, $login_interface, $http_interface, $network, $help_index_root, $projects, $project, $command_cache, $mail_envelope, $mail_address, $command_parser, $help_editing_ui, $on_location, $in_location, $mail_list_bugs, $storyteller, $lost_and_found, $cml2_telnet_format, $player] var $root created_on 812170946 var $root inited 1 var $root flags ['parameters, 'methods, 'code, 'core] parent $core object $backdoor var $root child_index 64 var $root inited 1 var $root objname 'backdoor var $root created_on 796268969 var $root indestructable 1 var $root flags ['core] var $root quota_exempt -1 var $backdoor buffer `[] var $backdoor ip "" var $backdoor hostname "" var $backdoor line_buffer [] var $backdoor valid_hosts ["127.0.0.1"] var $backdoor passwords #[] var $backdoor connected 1 var $backdoor programming #[] var $backdoor port 1169 var $backdoor who "" root init_backdoor buffer = `[]; ip = ""; hostname = ""; line_buffer = []; programming = #[]; who = ""; . root uninit_backdoor buffer = `[]; ip = ""; hostname = ""; line_buffer = []; programming = []; . driver parse arg incoming; var lines, line, index; lines = buffer.append(incoming).to_strings(); index = lines.length(); buffer = lines[index]; lines = lines.delete(index); line_buffer = [@line_buffer, @lines]; while (line_buffer) { line = line_buffer[1]; line_buffer = line_buffer.delete(1); (| .parse_line(line) |); } . protected parse_line arg line; var l; if (sender() != this()) throw(~perm, "Sender is not this."); catch any { if (connected) { if (programming) ._handle_programming_line(line); else ._handle_command_line(line); } else { ._handle_login(line); } } with handler { for l in ($parse_lib.traceback(traceback())) .echo(l); } . protected quit_cmd arg [cmd]; if (sender() != this()) throw(~perm, "Sender is not this."); .echo("Goodbye."); .backdoor_log("Disconnect <" + .address() + ">"); .close(); . protected eval_cmd arg cmd, [args]; var code, result; if (sender() != this()) throw(~perm, "Sender is not this."); code = args.to_string() + ";"; if (code && code[1] == ";") code = code.subrange(2); else code = "return " + code; result = .eval([code], this()); if (result[1] == 'errors) .echo(result[2]); else .echo("=> " + .toliteral(result[2])); . protected eval_as_cmd arg cmd, [args]; var result, code, obj; if (sender() != this()) throw(~perm, "Sender is not this."); args = args.to_string(); result = $string.match_template("* eval *", args); if (!result) { .echo("Syntax: `as <object> eval <code>`"); return; } obj = (| $object_lib.to_dbref(result[1]) |); if (!obj) { .echo("Unable to find object \"" + result[1] + "\"."); return; } code = result[3] + ";"; result = obj.eval([code]); if (result[1] == 'errors) .echo(result[2]); else .echo("as eval => " + toliteral(result[2])); . protected echo arg what; var line; if (type(what) == 'list) { for line in (what) .echo(line); } else { ._echo(what); } . protected eval_as_to_cmd arg cmd, [args]; var result, code, obj, target; if (sender() != this()) throw(~perm, "Sender is not this."); args = args.to_string(); result = $string.match_template("* as * eval *", args); if (!result) { .echo("Syntax: `definer <object> as <object> eval <code>`"); return; } obj = (| $object_lib.to_dbref(result[1]) |); target = (| $object_lib.to_dbref(result[3]) |); if (!obj) { .echo("Unable to find object \"" + result[1] + "\"."); return; } if (!target) { .echo("Unable to find object \"" + result[3] + "\"."); return; } code = result[5] + ";"; result = obj.eval([code], target); if (result[1] == 'errors) .echo(result[2]); else .echo("definer as eval => " + toliteral(result[2])); . protected close close_connection(); .destroy(); . protected set_password arg what, word; var x, i, a, cword; if (!$sys.is_admin(sender())) { .log_backdoor("Invalid set password attempt by " + sender().namef('xref)); throw(~perm, "Permission denied, only admins may set backdoor passwords."); } if (word.length() < 6) throw(~badpasswd, "Passwords must be at least 6 characters long."); for x in [1 .. word.length()] { if (word[x] in "1234567890") i = i + 1; else a = a + 1; } if (a < 2 || i < 2) throw(~badpasswd, "Passwords must contain at least 2 numeric characters and 2 non-numeric characters."); cword = word.crypt(); if (cword in passwords.values()) throw(~badpasswd, "That password already exists."); passwords = passwords.add(what, cword); . protected del_password arg what; if (!$sys.is_admin(sender())) { .log_backdoor("Invalid password removal attempt by " + sender().namef('xref)); throw(~perm, "Permission denied, only admins may adjust backdoor passwords."); } passwords = passwords.add(what); . protected address arg [args]; if (sender() != this()) throw(~perm, "Sender is not this."); args = [@args, 'hostname][1]; switch (args) { case 'ip: return ip; case 'hostname: return hostname; } . protected set_address arg host; if (sender() != this() && !sender().has_ancestor(definer())) throw(~perm, "Sender is not this."); ip = host; hostname = hostname(ip); . driver connect arg host, socket; var c; if (!(host in valid_hosts)) { .backdoor_log("Connection from invalid host: " + host); .echo("Your host is not one of the valid hosts."); .close(); return; } .backdoor_log("Connection from: " + host); c = .spawn(); if ($daemon.reassign_connection(c)) c.set_address(host); else c.destroy(); . protected program if (sender() != this()) throw(~perm, "Sender is not this."); programming = #[['task_id, task_id()], ['code, []]]; return $sys.suspend(); . protected check_passwords arg str; var line, pwd; if (sender() != this()) throw(~perm, "Sender is not this."); line = str.explode(); pwd = $backdoor.passwords(); if (!(| pwd[line[1]] |) || line.length() != 4 || !.check_encrypted(line[1], line[2]) || !.check_encrypted("back1", line[3]) || !.check_encrypted("back2", line[4])) return 0; return 1; . protected disconnect arg [args]; if (sender() || caller()) throw(~perm, "Sender is not the server."); .close(); . public startup arg [args]; var opt, curr_port; (> .perms(caller(), $sys) <); catch any { opt = "-pbackdoor" in args; curr_port = (| toint(args[opt + 1]) |) || port; $sys.log("** Starting $backdoor on port " + tostr(curr_port) + " **"); $daemon.bind_port(curr_port); } with handler { $sys.log($parse_lib.traceback(traceback())); } . public passwords if (!sender().has_ancestor(this())) throw(~perm, "Sender is not descended from this."); return passwords; . protected backdoor_log arg str; if (sender() != this()) throw(~perm, "Sender is not this."); $sys.log(.objname() + " (" + who + "): " + str); . protected check_encrypted arg key, str; var pwd; pwd = ($backdoor.passwords())[key]; if (sender() != this()) throw(~perm, "Sender is not this."); return str.crypt(pwd.subrange(1, 2)) == pwd; . protected _echo arg what; // send off a string or buffer if (sender() != this()) throw(~perm, "Sender is not this."); (> echo($buffer.from_strings([what])) <); . protected program_cmd arg cmd, what; var code, ref, ignore, errors; if (sender() != this()) throw(~perm, "Sender is not this."); ref = $parse_lib.full_reference(what); if (ref[1] != 'method || !ref[3]) { .echo("Invalid object.method() reference, ignoring code until \".\""); ignore = 1; } .echo("-- Enter text for " + ref[2].objname() + "." + tostr(ref[3]) + " --"); code = .program(); if (code == 'aborted) { .echo("** Aborted **"); } else if (ignore) { .echo("Finished ignoring text."); } else { errors = ref[2].compile(code, ref[3]); if (errors) .echo(errors); else .echo("Method compiled."); } . protected _handle_programming_line arg line; if (sender() != this()) throw(~perm, "Sender is not this."); if (!line) { programming = programming.add_elem('code, ""); } else if (line == ".") { $sys.resume(programming['task_id], programming['code]); programming = #[]; } else if (line == "@abort") { $sys.cancel(programming['task_id]); programming = #[]; .echo("** Aborted **"); } else { programming = programming.add_elem('code, line); } . protected _handle_command_line arg line; var cmds, cmd; if (sender() != this()) throw(~perm, "Sender is not this."); // cmds = "list, program, quit, eval, as eval, def as eval"; if (!line) { .echo("Available commands: " + cmds); return; } // because I'm lazy, check for ';' if (line[1] == ";") line = "eval " + line.subrange(2); .backdoor_log("Command: " + line); cmd = line.explode(); if (cmd.length() == 1) cmd = [cmd[1], ""]; switch (cmd[1]) { case "@program", ".program", "program": .program_cmd(@cmd); case "@quit", "quit": .quit_cmd(@cmd); case "eval": .eval_cmd(@cmd); case "as": .eval_as_cmd(@cmd); case "definer", "def": .eval_as_to_cmd(@cmd); case "list", "@list", "@nlist": .list_cmd(@cmd); default: .echo("Available commands: " + cmds); } . protected _handle_login arg line; if (sender() != this()) throw(~perm, "Sender is not the definer."); if (.check_passwords(line)) { connected = 1; who = (line.explode())[1]; .backdoor_log("Valid login sequence."); .echo("Valid login sequence."); } else { .backdoor_log("Invalid login sequence (" + ((| line[1] |) || "<none>") + " ...) from: " + .address()); .echo("Invalid login sequence."); .close(); } . protected list_cmd arg cmd, what; var code, ref, ancestor, nums, line; if (sender() != this()) throw(~perm, "Sender is not this."); if (!what) return .echo("no reference specified."); catch any { ref = $parse_lib.full_reference(what); nums = cmd == "@nlist"; if (ref[1] != 'method || !ref[3]) { .echo("Invalid object.method() reference."); return; } ancestor = ref[2].find_method(ref[3]); code = ancestor.list_method(ref[3]); if (nums) { for line in [1 .. code.length()] code = code.replace(line, (line < 10 ? " " | "") + tostr(line) + ": " + code[line]); } else { for line in [1 .. code.length()] code = code.replace(line, " " + code[line]); } .echo("program " + ancestor.objname() + "." + tostr(ref[3])); .echo(code); .echo("."); } with handler { .echo(traceback()[1][2]); } . public linelen return 79; . protected toliteral arg data; var str, element, association, pos; switch (type(data)) { case 'integer, 'string, 'symbol, 'error, 'buffer: return toliteral(data); case 'dbref: if (!valid(data)) return "** invalid object (" + toliteral(data) + ") **"; return (| data.objname() |) || toliteral(data); case 'list: if (!data) return "[]"; str = "["; for element in (data.subrange(1, data.length() - 1)) { str = str + .toliteral(element); str = str + ", "; } str = str + .toliteral(data[data.length()]); return str + "]"; case 'dictionary: if (!data) return "#[]"; str = "#["; for association in (data) { str = str + .toliteral(association); str = str + ", "; } return str.subrange(1, str.length() - 2) + "]"; case 'frob: return toliteral(data); } . parent $named parent $has_commands object $described var $described prose [] var $root inited 1 var $root objname 'described var $root created_on 796268969 var $root flags ['parameters, 'methods, 'code, 'core] var $messaged verbs #[["l?ook at %this", ['look_vrb, 'noremote]], ["l?ook %this", ['look_vrb, 'noremote]], ["exam?ine %this", ['examine_vrb, 'remote]]] var $named name ['uniq, "Generic Described Object", "the Generic Described Object"] var $named name_aliases [] var $has_commands shortcuts #[] var $has_commands remote #[["l?ook", [["l?ook", "at *", "l?ook at <this>", 'look_at_cmd, #[[2, ['this, []]]]], ["l?ook", "*", "l?ook <this>", 'look_at_cmd, #[[1, ['this, []]]]]]]] root init_described prose = []; . public description arg flags; var out, name; // No option of getting the name, you always do name = (<$ctext_format, ["subj", #[], #[], [.name()], 'do_subj]>); if (flags['brief]) name = [name]; else name = [name, (<$ctext_format, ["br", #[], #[], [], 'do_br]>)]; out = (<$ctext2_frob, [name, #[]]>); if (flags['prose]) out = out.append(.prose()); return [out]; . public prose: disallow_overrides arg [no_default]; return prose || (no_default ? 0 | "You see nothing special"); . public set_prose arg new; (> .perms(sender(), 'manager) <); switch (type(new)) { case 'string, 'list: new = (> $cml2_compiler.compile_cml(new) <); case 'frob: // we'll let this pass by unharmed default: throw(~invalid, "Prose can be submitted as CML or Ctext"); } prose = new; . root uninit_described prose = 0; . public coreify_described (> .perms($root, caller()) <); .compile(["prose = " + toliteral(prose) + ";"], 'CORE_EVAL); . public look_at_cmd arg [args]; return .get_description(); . public get_description: disallow_overrides arg [def_flags]; var flags; flags = $code_lib.default_description_flags(); if (def_flags && type(def_flags[1]) == 'dictionary) { flags = def_flags[1].union(flags); } else { flags = flags.add('actor, sender()); flags = flags.add_elem('exclude, sender()); } return .description(flags); . parent $named object $gendered var $root inited 1 var $root objname 'gendered var $root created_on 796268969 var $root flags ['parameters, 'methods, 'code, 'core] var $messaged verbs 0 var $gendered gender 0 var $described prose #[] var $named name ['uniq, "The Generic Gendered Object", "the The Generic Gendered Object"] var $named name_aliases [] var $has_settings defined_settings #[["gender", #[['get, 'gender], ['set, 'set_gender], ['check, 'check_gender], ['del, 'delete_local_setting], ['check_args, []], ['get_args, []], ['set_args, []]]]] public gender_context return gender.pronoun('po); . root init_gendered gender = $gender_neuter; . public set_gender arg definer, name, value, [args]; (> .perms(sender(), 'manager) <); gender = value; . public gender arg [args]; return gender; . parent $event_handler parent $described parent $gendered parent $environment parent $has_settings object $physical var $root trusted [] var $root inited 1 var $root objname 'physical var $root created_on 796268969 var $root flags ['parameters, 'methods, 'code, 'core] var $messaged verbs #[] var $described prose [] var $gendered gender $gender_neuter var $physical visibility 0 var $named name ['uniq, "Generic Physical Object", "the Generic Physical Object"] var $named name_aliases [] var $has_settings defined_settings #[["visibility", #[['get, 'visibility], ['set, 'set_visibility], ['check, 'is_type], ['del, 'delete_local_setting], ['check_args, ['integer]], ['get_args, []], ['set_args, []]]]] var $has_settings local_settings #[] var $has_settings settings #[] public set_visibility arg definer, name, value, [args]; (> .perms(sender()) <); visibility = value; . public visibility arg [args]; return visibility; . public is_visible_to arg whom; return .visibility() >= whom.location().darkness(); . public set_darkness arg definer, name, value, [args]; (> .perms(sender()) <); darkness = value; . parent $has_commands object $command_cache var $root objname 'command_cache var $root child_index 3 var $root fertile 1 var $root created_on 796605573 var $root inited 1 var $root flags ['parameters, 'methods, 'code, 'fertile, 'core] var $command_cache shortcut_cache 0 var $command_cache remote_cache 0 var $command_cache local_cache 0 var $has_commands shortcuts #[] root uninit_command_cache (| .purge_caches() |); . public rehash_caches var obj, part, element; (| .purge_caches() |); (> .add_object_to_local_caches(this()) <); if (.is($location)) { for obj in ([this()] + .contents()) (> .add_object_to_remote_caches(obj) <); } shortcut_cache = .all_shortcuts(); . public add_to_command_cache arg command, definer; (> .perms(sender(), 'this) <); if (type(command_cache) != 'dictionary) command_cache = #[]; command_cache = command_cache.add_elem(command, definer); . public purge_caches (> .perms(sender()) <); local_cache = remote_cache = shortcut_cache = 0; . public add_object_to_caches arg obj; var info, thing, element, part; (> .perms(sender(), 'this) <); .add_object_to_local_caches(); .add_object_to_remote_caches(); . public add_to_remote_cache arg command, definer; var part, cmd, value, cmds, defs; (> .perms(sender(), 'this) <); if (type(remote_cache) != 'dictionary) remote_cache = #[]; // if this dies, it will also fail on explode_template_word cmd = (| (command.explode())[1] |); for part in (command.explode_template_word()) { if (value = (| remote_cache[part] |)) { cmds = value[1].union([cmd]); defs = value[2].union([definer]); remote_cache = remote_cache.add(part, [cmds, defs]); } else { remote_cache = remote_cache.add(part, [[cmd], [definer]]); } } . public add_to_local_cache arg command; var part, cmd; (> .perms(sender(), 'this) <); if (type(local_cache) != 'dictionary) local_cache = #[]; // if this dies, it will also fail on explode_template_word cmd = (| (command.explode())[1] |); for part in (command.explode_template_word()) local_cache = local_cache.add_elem_union(part, cmd); . public match_in_shortcut_cache arg str, cmd, args; var shortcut, match; if (shortcut_cache) { for shortcut in (shortcut_cache) { if (match = $string.match_pattern(shortcut[1], str)) return ['shortcut, [shortcut[2][1], [str, @$command_lib.handle_shortcut_fields(shortcut[2][2], match)]]]; } } return 0; . public shortcut_cache return shortcut_cache; . public remote_cache return remote_cache; . public local_cache return local_cache; . public match_in_remote_cache arg str, cmd, args; var cache, definer, command, info, cdef, match, matched, templates; if (!remote_cache) return 0; cache = (| remote_cache[cmd] |); templates = []; matched = []; for command in (cache[1]) { for definer in (cache[2]) { info = definer.get_command_info('remote, command); if (!info) continue; for cdef in (info) { match = $string.match_template(cdef[2], args); if (match != 0) matched = matched + [[match.length(), definer, [str, cmd, @match], @cdef.subrange(3)]]; } templates = templates.union(info.slice(3)); } } if (matched) { info = [matched[1]]; matched = matched.delete(1); for match in (matched) { if (match[1] > info[1][1]) info = [match]; else if (match[1] == info[1][1]) info = info + [match]; } return ['remote, info]; } return ['partial, templates]; . public match_in_local_cache arg str, cmd, args; var command, match, matched, templates, info, cdef; if (!local_cache) return 0; templates = matched = []; for command in ((| local_cache[cmd] |) || []) { info = .get_command_info('local, command); if (!info) continue; for cdef in (info) { match = $string.match_template(cdef[2], args); if (match != 0) matched = matched + [[match.length(), [str, cmd, @match], @cdef.subrange(3)]]; } templates = templates.union(info.slice(3)); } if (matched) { info = [matched[1]]; matched = matched.delete(1); for match in (matched) { if (match[1] > info[1][1]) info = [match]; else if (match[1] == info[1][1]) info = info + [match]; } return ['local, info]; } if (!templates) return 0; return ['partial, templates]; . public add_object_to_local_caches arg obj; var info, thing, element, part; (> .perms(sender(), 'this) <); info = (| obj.all_local_commands() |); if (info) { for element in (info) { for part in (element[2]) .add_to_local_cache(part[1]); } } . public add_object_to_remote_caches arg obj; var info, thing, element, part; // (> .perms(sender(), 'this) <); info = (| obj.all_remote_commands() |); if (info) { for element in (info) { for part in (element[2]) .add_to_remote_cache(part[1], element[1]); } } . parent $physical parent $has_messages object $exit var $exit source $void var $exit dest $void var $exit lock <$true_lock_frob, []> var $exit coordinates 0 var $root child_index 260 var $root fertile 1 var $root inited 1 var $root objname 'exit var $root created_on 796268969 var $root flags ['parameters, 'methods, 'code, 'fertile, 'core] var $messaged verbs #[["@lock %this with *", ['lock_vrb, 'remote]]] var $gendered gender $gender_neuter var $described prose [] var $named name ['uniq, "Generic Exit", "the Generic Exit"] var $named name_aliases [] var $has_commands remote #[["@lock", [["@lock", "*", "@lock <this>", 'lock_cmd, #[[1, ['this, []]]]], ["@lock", "* with|to *", "@lock <this> with|to <any>", 'lock_with_cmd, #[[1, ['this, []]], [3, ['any, []]]]]]], ["@unlock", [["@unlock", "*", "@unlock <this>", 'unlock_cmd, #[[1, ['this, []]]]]]]] var $has_messages messages #[[$exit, #[["exit.actor", <$ctext2_frob, [["You take ", <$ctext_generator, ["exit", #[], #[], [], 'gen_exit]>, "."], #[['line, 1], ['this, $exit]]]>], ["exit.source", <$ctext2_frob, [[<$ctext_generator, ["actor", #[], #[], [], 'gen_actor]>, " goes through ", <$ctext_generator, ["exit", #[], #[], [], 'gen_exit]>, "."], #[['line, 1], ['this, $exit]]]>], ["exit.dest", <$ctext2_frob, [[<$ctext_generator, ["actor", #[], #[], [], 'gen_actor]>, " arrives."], #[['line, 1], ['this, $exit]]]>]]]] var $has_messages message_info #[["exit", #[]]] root init_exit source = $places.place('default); dest = source; source.add_exit(0, 0); lock = $true_lock_frob.new(); . root uninit_exit (| source.del_exit() |); (| source.did_detach() |); (| dest.did_detach() |); source = 0; dest = 0; lock = 0; . public environment return [this()] + source.environment().setremove(this()); . public invoke arg [flags]; var a, here, vars, m; a = sender(); flags = [@flags, #[]][1]; flags = flags.add('actor, a); flags = flags.add_elem('exclude, a); if (!valid(.dest())) $parse_lib.tell_error(.name() + " has an invalid destination, notify the manager (" + .manager().namef('ref) + ").", "", a); if (!lock.try(sender())) return a.tell(.name() + " is locked."); vars = #[["$actor", a], ["actor", a.name()], ["$source", .source()], ["source", .source().name()], ["$dest", .dest()], ["dest", .dest().name()], ["$exit", this()], ["exit", .name()]]; m = .eval_message("exit", vars, $exit); .dest().announce(m); .source().announce(m); a.move_to(.dest()); a.tell(.dest().get_description(flags)); $movement_event.new(a, .source(), .dest()).dispatch(); . public lock return lock; . public attach: disallow_overrides arg source_place, dest_place, radial, azimuth; // radial/azimuth coordinates. (> .perms(sender()) <); (> $places.is_place(source_place) <); (> $places.is_place(dest_place) <); if (source_place == source) return; (> source_place.will_attach('source, sender()) <); (> dest_place.will_attach('dest, sender()) <); (| source.del_exit() |); source = source_place; dest = dest_place; coordinates = [radial, azimuth]; source_place.add_exit(radial, azimuth); (| source_place.did_attach('source, sender()) |); (| dest_place.did_attach('dest, sender()) |); . public dest return dest; . public source return source; . public place_destroyed arg place; (> .perms(caller(), $place) <); if (sender() in [dest, source]) .destroy(); . public short_description arg actor, [exclude]; var prose; return .long_description(actor, @exclude); . public long_description arg actor, [exclude]; var prose; prose = .prose('literal); if (!(| prose['long] |)) return (| .dest().short_description(sender(), sender()) |) || (> pass(actor, @exclude) <); return (> pass(actor, @exclude) <); . public lock_cmd arg cmdstr, cmd, this; if (!(| .perms(sender()) |)) return "Only " + .manager().name() + " can lock " + .name('def) + "!"; lock = $false_lock_frob.new(); sender().tell("You lock " + .name('def)); . public lock_with_cmd arg cmdstr, cmd, this, prep, str; if (!(| .perms(sender()) |)) return "Only " + .manager().name() + " can lock " + .name('def) + "!"; catch ~objnf, ~parse { lock = $lock_parser.parse(str, sender()); return "You lock " + .name('def) + " to allow " + lock.lock_name('exit) + "."; } with handler { switch (error()) { case ~objnf: return "Object not found in lock string."; case ~parse: return "Invalid lock string."; } } . public unlock_cmd arg cmdstr, cmd, this; if (!(| .perms(sender()) |)) return "Only " + .manager().name() + " can lock " + .name('def) + "!"; lock = $true_lock_frob.new(); sender().tell("You unlock " + .name('def)); . public is_visible_to arg whom; return .visibility() >= whom.location().darkness(); . parent $physical object $located var $located inited 0 var $located location $nowhere var $located obvious 1 var $root objname 'located var $root created_on 796268969 var $root flags ['parameters, 'methods, 'code, 'core] var $messaged verbs #[] var $gendered gender $gender_neuter var $described prose [] var $named name ['uniq, "Generic Located Object", "the Generic Located Object"] var $named name_aliases [] root init_located location = $nowhere; location.add_sender_to_contents(); obvious = 1; . public uninit if (caller() != $root) throw(~perm, "Caller is not root."); location.del_sender_from_contents(); location = 0; . public environment return [this()] + location.environment().setremove(this()); . public match_environment arg str; var thing, matches; if (str == "here") { return location; } else if (str in ["everyone", "everybody", "everything"]) { matches = []; if (str in ["everyone", "everybody"]) { for thing in (.location().contents().setremove(this())) { if (thing.has_ancestor($user)) matches = [@matches, thing]; } } else { matches = .location().contents(); } if (matches.length() > 1) throw(~ambig, "Several matches.", matches); else if (matches) return matches[1]; else throw(~objnf, "No matches."); } else { return (> pass(str) <); } . public location return location || $void; . public will_move arg mover, place; . public did_move arg mover, old_place; if (caller() != definer() || sender() != this()) throw(~perm, "Invalid call to protected method."); . public realm return realm; . root uninit_located .location().del_sender_from_contents(); . public move_to arg place; var old; // Don't do anything if we're already here. if (place == location) return; if (!place.has_ancestor($location)) throw(~type, "Argument is not a location."); // Notify involved parties of impending move, allowing them to throw // errors. if (!valid(location)) location = $nowhere; (> .will_move(sender(), place) <); (> location.will_leave(place) <); (> place.will_arrive(location) <); // Set location. old = location; location = place; old.del_sender_from_contents(); place.add_sender_to_contents(); // Notify involved parties of completed move, in reverse order. place.did_arrive(old); old.did_leave(place); .did_move(sender(), old); . public match_environment_all arg s; if (s == "here") return [location, @(> pass(@args) <)]; else return (> pass(s) <); . public obvious return obvious; . public set_obvious arg obv; .perms(sender()); obvious = obv; . public realm_name arg [args]; return .location().realm_name(@args); . public announce arg [args]; . public is_obvious_to arg whom; // will later do something creative here return 1; . parent $located parent $public object $thing var $root child_index 64 var $root fertile 1 var $root inited 1 var $root objname 'thing var $root created_on 796268969 var $root flags ['parameters, 'methods, 'code, 'fertile, 'core] var $messaged verbs #[["take|get %this", ['take_vrb, 'noremote]], ["drop %this", ['drop_vrb, 'noremote]]] var $located location $void var $located obvious 1 var $gendered gender $gender_neuter var $described prose [] var $named name ['uniq, "Generic Thing", "the Generic Thing"] var $named name_aliases [] var $public public ['readable] var $has_commands shortcuts #[] var $has_commands remote #[["@lock", [["@lock", "* with|to *", "@lock <this> with|to <any>", 'lock_with_cmd, #[[1, ['this, []]], [3, ['any, []]]]], ["@lock", "*", "@lock <this>", 'lock_cmd, #[[1, ['this, []]]]]]], ["@unlock", [["@unlock", "*", "@unlock <this>", 'unlock_cmd, #[[1, ['this, []]]]]]], ["@boot", [["@boot", "*", "@boot <this>", 'boot_cmd, #[[1, ['this, []]]]]]]] var $has_commands local #[] var $thing lock <$object_lock_frob, [$void]> var $has_settings defined_settings #[["home", #[['get, 'home], ['set, 'set_local_setting], ['check, 'check_home], ['del, 'delete_local_setting], ['check_args, []], ['get_args, []], ['set_args, []]]]] var $has_settings local_settings #[] var $has_settings settings #[] public boot_cmd arg cmdstr, cmd, this; var loc, dest, exit; loc = .location(); if (!(| .perms(sender(), 'manager) |)) { .tell(sender().name() + " tried to boot you from " + loc.name() + "!"); loc.announce(sender().name() + " tried to boot " + .name() + " from " + loc.name() + "!", sender(), this()); return "Only " + loc.manager().name() + " can boot people from " + loc.name() + "!"; } dest = .home(); catch any { sender().tell("You boot " + .namef() + "."); loc.announce(sender().namef() + " boots " + .namef() + " from " + .location().name('def) + ".", this(), sender()); if (sender().location() != loc) sender().location().announce(sender().namef() + " boots " + .namef() + " from " + .location().name('def) + ".", this(), sender()); (> .move_to(dest) <); } with handler { return traceback()[1][2]; } . public lock return lock; . public lock_cmd arg cmdstr, cmd, this; if (!(| .perms(sender()) |)) return "Only " + .manager().name() + " can lock " + .name('def) + "!"; lock = $false_lock_frob.new(); return "You lock " + .name('def); . public lock_with_cmd arg cmdstr, cmd, this, prep, str; if (!(| .perms(sender()) |)) return "Only " + .manager().name() + " can lock " + .name('def) + "!"; catch ~objnf, ~parse { lock = $lock_parser.parse(str, sender()); return "You lock " + .name('def) + " " + prep + " " + lock.lock_name('thing) + "."; } with handler { switch (error()) { case ~objnf: return "Object not found in lock string."; case ~parse: return "Invalid lock string."; } } . public unlock_cmd arg cmdstr, cmd, this; if (!(| .perms(sender()) |)) return "Only " + .manager().name() + " can lock " + .name('def) + "!"; lock = $true_lock_frob.new(); return "You unlock " + .name('def); . public will_move arg mover, place; (> pass(mover, place) <); if (mover.is($housekeeper)) return; if (lock && mover != $exit && !lock.try(mover)) throw(~locked, .name('def).capitalize() + " is locked to " + lock.lock_name('thing) + "."); else if (!.is_writable_by(sender())) throw(~move, "You cannot move " + .objname()); . public home arg [args]; return (| .get_local_setting("home", $thing) |) || $lost_and_found; . public check_home arg definer, value, [args]; var home; home = (> .match_environment(value) <); if (!(| home.perms(sender()) |) && !(| home.setting("public-home") |)) throw(~perm, "You do not have permission to make " + home.name() + " your home."); return home; . public check_gender arg definer, value, [args]; var g, gs; gs = [$gender_female, $gender_male, $gender_neuter]; g = value in gs.map('name); if (!g) throw(~set, "Gender must be one of: " + gs.map('name).to_english("", " or ")); return gs[g]; . public check_match_with arg definer, value, [args]; var matching; if (value in ["regexp", "pattern", "begin"]) return tosym("match_" + value.lowercase()); throw(~perm, "You can match with: regexp, pattern, begin."); . parent $physical parent $command_cache object $location var $location contents [] var $root fertile 1 var $root inited 1 var $root objname 'location var $root created_on 796268969 var $root flags ['parameters, 'methods, 'code, 'fertile, 'core] var $messaged verbs #[] var $gendered gender $gender_neuter var $described prose [] var $named name ['uniq, "Generic Container Object", "the Generic Container Object"] var $named name_aliases [] var $command_cache shortcut_cache 0 var $command_cache remote_cache 0 var $command_cache local_cache 0 var $has_commands shortcuts #[] var $has_settings defined_settings #[] var $has_settings local_settings #[] var $has_settings settings #[] root init_location contents = []; . root uninit_location var obj; for obj in (contents) obj.move_to($nowhere); . public contents return contents || []; . public contains arg obj; return obj in .contents() ? 1 | 0; . public find_in_contents arg str; var obj; for obj in (.contents()) { if (obj.match_name(str)) return; } . public will_arrive arg old_place; if (caller() != $located) throw(~perm, "Caller is not $located."); . public will_leave arg place; if (caller() != $located) throw(~perm, "Caller is not $located."); . public did_arrive arg place; if (caller() != $located) throw(~perm, "Caller is not $located."); .add_object_to_remote_caches(sender()); . public did_leave arg place; if (caller() != $located) throw(~perm, "Caller is not $located."); (| .del_from_command_environment(sender()) |); . public add_sender_to_contents: disallow_overrides if (caller() != $located) throw(~perm, "Caller is not $located."); if (sender().location() != this()) throw(~location, "Sorry, but you're not here."); contents = .contents().setadd(sender()); . public del_sender_from_contents: disallow_overrides if (caller() != $located) throw(~perm, "Caller not an agent of located protocol."); contents = contents.setremove(sender()); . public validate_contents var obj, newcont; if (!.is_writable_by(sender())) throw(~perm, "Must be an owner to validate contents"); newcont = []; for obj in (contents) { if (valid(obj) && obj.has_ancestor($located) && obj.location() == this()) newcont = newcont.setadd(obj); } contents = newcont; . public environment return [this()] + contents; . public add_to_contents: disallow_overrides arg what; if (caller() != $located) throw(~perm, "Caller is not $located."); . public contents_accept_mail return 1; . public realm arg [args]; var loc; loc = ""; if ((| .location() |)) loc = .location().realm(); return loc + "[" + .namef() + "]"; . public realm_name return ""; . parent $thing parent $location object $located_location var $root child_index 3 var $root fertile 1 var $root inited 1 var $root objname 'located_location var $root created_on 796268969 var $root flags ['parameters, 'methods, 'code, 'fertile, 'core] var $messaged verbs #[] var $location contents [] var $located location $nowhere var $located obvious 1 var $gendered gender $gender_neuter var $described prose [] var $named name ['uniq, "Generic Located Location", "the Generic Located Location"] var $named name_aliases [] var $command_cache shortcut_cache 0 var $command_cache remote_cache 0 var $command_cache local_cache 0 public environment return pass() + .contents(); . parent $located_location object $body var $root child_index 14 var $root fertile 1 var $root inited 1 var $root objname 'body var $root created_on 796268969 var $root flags ['parameters, 'methods, 'code, 'fertile, 'core] var $messaged verbs #[] var $location contents [] var $located location $nowhere var $located obvious 1 var $body body_parts #[] var $body available_body_parts 0 var $body wearing 0 var $body following 0 var $gendered gender $gender_neuter var $described prose [] var $named name ['uniq, "Generic Body", "the Generic Body"] var $named name_aliases [] var $command_cache shortcut_cache 0 var $command_cache remote_cache 0 var $command_cache local_cache 0 public tell arg [args]; . public 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(part, param)); . public 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; . public body_parts return body_parts; . public namef arg [args]; if (!args) args = [['name]]; if (args[1] == 'nactivity || args[1] == 'titled) args = args.subrange(2); return pass(@args); . public available_body_parts return available_body_parts || ['head, 'rleg, 'lleg, 'rarm, 'larm, 'torso]; . public wear arg frob; if (caller() != $wearable_frob) throw(~wear, "You can only wear descendants of $wearable_frob."); wearing = wearing ? [@wearing, frob] | [frob]; . public shed arg name; var f; (> .perms(sender(), 'this) <); for f in (.wearing()) { if ($string.match_begin(f.name(), name)) wearing = wearing.setremove(f); } . public environment return pass() + .wearing(); . public 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) <); . public set_following arg what; (> .perms(sender()) <); following = what; . public event arg event; (> pass(event) <); if (following) { if (following == event.actor() && event.dest() != .location()) event.exit().invoke(#[['prose, 0], ['extra, 0]]); } . public description arg flags; var ctext, what, w; ctext = (> pass(flags) <); if (w = .wearing()) ctext = ctext + [.gender().pronoun('psc) + " is wearing " + w.map('name).to_english() + "."]; else ctext = ctext + [.gender().pronoun('psc) + " is naked, baring it all to the world."]; return ctext; . parent $command_cache object $user_interfaces var $root child_index 7 var $root fertile 1 var $root inited 1 var $root objname 'user_interfaces var $root created_on 796268969 var $root flags ['parameters, 'methods, 'code, 'fertile, 'core] var $has_commands shortcuts #[] var $command_cache shortcut_cache 0 var $command_cache remote_cache 0 var $command_cache local_cache 0 parent $user_interfaces object $interaction var $root inited 1 var $root objname 'interaction var $root created_on 796268969 var $root flags ['parameters, 'methods, 'code, 'core] var $interaction stage #[[">", " -> "], ["<", " <- "], ["[", " ["], ["|", " | "]] var $interaction last_interacted_with 0 var $interaction interaction 0 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>", 'say_to_cmd, #[[1, ['any, []]], [3, ['any, []]]]]]], ["@paste", [["@paste", "*", "@paste <any>", 'paste_cmd, #[[1, ['any, []]]]]]], ["emote", [["emote", "*", "emote <any>", 'emote_cmd, #[[1, ['any, []]]]]]], ["on", [["on", "* say *", "on <any> say <any>", 'on_subj_cmd, #[[1, ['any, []]], [3, ['any, []]]]]]], ["@to|@page", [["@to|@page", "* with|say *", "@to|@page <any> with|say <any>", 'remote_say_cmd, #[[1, ['any, []]], [3, ['any, []]]]]]], ["@emote?-to|@epage", [["@emote?-to|@epage", "* with *", "@emote?-to|@epage <any> with <any>", 'remote_emote_cmd, #[[1, ['any, []]], [3, ['any, []]]]]]]] var $has_commands shortcuts #[["|*", ['_interact, ["|", 1]]], ["<*", ['_interact, ["<", 1]]], ["%*", ['think_cmd, ["think", 1]]], ["!*", ['spoof_cmd, ["spoof", 1]]], ["''*", ['say_to_cmd, ["to", "", "say", 1]]], ["'* *", ['say_to_cmd, ["to", 1, "say", 2]]], ["]*", ['right_encapsulate_cmd, ["]", 1]]], [")*", ['right_encapsulate_cmd, [")", 1]]], [",*, *", ['esay_cmd, ["esay", 1, "with", 2]]], [",*,*", ['esay_cmd, ["esay", 1, "with", 2]]], ["--*", ['remote_say_cmd, ["rsay", "", "with", 1]]], ["-* *", ['remote_say_cmd, ["rsay", 1, "with", 2]]], ["++*", ['remote_emote_cmd, ["@emote", "", "with", 1]]], ["+* *", ['remote_emote_cmd, ["@emote", 1, "with", 2]]], ["\"*", ['say_cmd, ["say", 1]]], [":*", ['emote_cmd, ["emote", 1]]]] var $command_cache shortcut_cache 0 var $command_cache remote_cache 0 var $command_cache local_cache 0 public remote_say_cmd arg cmdstr, com, who, prep, message; var target, targets, line, fromline; (> .perms(sender(), 'this) <); targets = (> ._parse_interaction_reference(who, "say") <); if (targets) { ._add_interaction('objs, targets); line = .namef() + " "; if (message) line = .name() + " " + $code_lib.punctuation_type(message); else line = .name() + " say"; line = line + "s, \"" + message + "\""; fromline = "[from " + .location().namef() + "] " + line; for target in (targets) (| target.tell(fromline) |); .tell("[to " + targets.map('name).to_english() + "] " + line); } . public polite_spoof_cmd arg cmd, what; var name; (> .perms(sender(), 'this) <); name = .namef(); if (!(name + " " in what || " " + name in what)) what = what + " -- " + name; .location().announce(what); . public say_to_cmd arg cmdstr, com, who, prep, message; var targets, target, line; (> .perms(sender(), 'this) <); targets = (> ._parse_interaction_reference(who, "say") <); if (targets) { ._add_interaction('objs, targets); line = .namef() + " (to " + targets.map_to_english('namef) + ") "; if (message) line = line + $code_lib.punctuation_type(message); else how = line + "say"; line = line + "s, \"" + message + "\""; .location().announce(line); } . public whisper_cmd arg cmdstr, com, what, prep, who; var loc; (> .perms(sender(), 'this) <); who = .match_env_nice(who); loc = .location(); if (who.location() != loc) { .tell("You must be in the same room as a person, to whisper to them."); return; } who.tell(.namef() + " whispers, \"" + what + "\""); .tell("You whisper, \"" + what + "\" to " + who.namef() + "."); loc.announce(.namef() + " whispers to " + who.namef() + ".", who, this()); . public _interact arg cmdstr, cmd, what; var stage; (> .perms(sender(), 'this) <); stage = $interaction.get_stage(); // echo .namef()+stage[cmd]+what to the room if (cmd in stage.keys()) .location().announce(.namef() + stage[cmd] + what); else throw(~unknowncmd, "Unknown cmd '" + cmd + "'"); . public get_stage return stage; . public think_cmd arg cmdstr, cmd, what; (> .perms(sender(), 'this) <); .location().announce(.namef() + " . o O ( " + what + " )"); . public emote_cmd arg cmdstr, com, what; if (what && what[1] == ":") .location().announce(.name() + what.subrange(2)); else .location().announce(.name() + " " + what); . public say_cmd arg cmdstr, cmd, what; var type, how, idx; (> .perms(sender(), 'this) <); if (what) how = $code_lib.punctuation_type(what); else how = "say"; .location().announce(.name() + " " + how + "s, \"" + what + "\""); . public paste_cmd arg cmdstr, com, [who]; var obj, text; (> .perms(sender(), 'this) <); who = [@who, 0][1]; if (who) { who = $list.to_string(who.explode().subrange(2)); obj = (| .find_object(who, 'environment, 'environment, 'grasp) |); if (!obj) .tell_error(com + "[to <user>]", "No user found by the name \"" + who + "\"."); } text = .read(); if (text == 'aborted) return .tell("@paste aborted."); else if (!text) return .tell("@paste nothing?"); text = [$string.center(" " + .namef() + " (@paste's) ", 79, "-"), @text, $string.center(" + Finis + ", 79, "-")]; if (obj) { obj.tell(text); .tell("Text pasted to " + who.namef() + "."); } else { .location().announce(text); } . public esay_cmd arg cmdstr, cmd, how, prep, what; (> .perms(sender(), 'this) <); .location().announce(.name() + " " + how + ", \"" + what + "\""); . public page_emote_cmd arg cmdstr, com, who, prep, message; var user, recipient, targets, name; (> .perms(sender(), 'this) <); who = who && $string.explode_english_list(who) || []; if (!who) { if (last_interacted_with) who = last_interacted_with[2]; else $parse_lib.tell_error("You must specify somebody or something to speak to."); } targets = who; name = .namef() + " "; for recipient in (who) { if (type(recipient) == 'dbref) { user = recipient; } else { user = (| $user_db.match_begin(recipient) |); if (!user) user = (| .match_environment(recipient) |); } if (user && user.has_ancestor($user) && user.connected()) { user.tell("[from " + .location().namef() + "] " + name + message); who = who.replace(recipient in who, user.namef()); targets = targets.replace(recipient in targets, user); } else { .tell("! " + $data_lib.unparse(recipient) + " is either not connected, not a user, or misspelled."); who = who.setremove(recipient); targets = targets.setremove(recipient); } } if (targets) { last_interacted_with = [time(), targets]; who = who.to_english(); .tell("You epage \"" + name + message.chop(.linelen() - 17 - who.length()) + "\" to " + who + "."); } . public right_encapsulate_cmd arg cmdstr, right, line; var space, line, left, right; (> .perms(sender(), 'this) <); space = " "; if (!line) space = ""; switch (right) { case "]": left = "["; case ")": left = "("; } .location().announce(left + .namef() + space + line + right); . public remote_emote_cmd arg cmdstr, com, who, prep, message; var target, targets, line, fline; (> .perms(sender(), 'this) <); targets = (> ._parse_interaction_reference(who, "emote") <); if (targets) { ._add_interaction('objs, targets); line = .namef() + " " + message; fline = "[from " + .location().namef() + "] " + line; for target in (targets) (| target.tell(fline) |); .tell("[to " + targets.map('name).to_english() + "] " + line); } . public _parse_interaction_reference arg targets, what, [syn]; var recip, target; (> .perms(sender(), 'this) <); syn = [@syn, ""][1]; targets = targets && targets.explode_list() || []; if (!targets) { targets = ._get_interaction('objs) || .tell_error(syn, "You must direct your " + what + "."); targets = targets[2]; } else { for recip in (targets) { target = (| $user_db.match_begin(recip) |) || (| .match_environment(recip) |); if (target) { targets = targets.replace(recip in targets, target); } else { .tell("Unable to find " + toliteral(recip) + "."); targets = targets.setremove(recip); } } } return targets; . public _get_interaction arg key; (> .perms(sender(), 'this) <); return (| interaction[key] |) || 0; . public _add_interaction arg key, value; (> .perms(sender(), 'this) <); if (!interaction) interaction = #[]; if (type(value) != 'list) value = [value]; value = [time(), value]; interaction = interaction.add(key, value); . public _purge_interaction interaction = 0; . parent $misc object $mail_root var $root child_index 2 var $root fertile 1 var $root trusted [] var $root inited 1 var $root objname 'mail_root var $root created_on 796268969 var $root indestructable 1 var $root flags ['parameters, 'methods, 'code, 'fertile, 'core] parent $mail_root parent $named object $mail_list var $root child_index 2 var $root inited 1 var $root objname 'mail_list var $root created_on 796268969 var $root indestructable 1 var $root flags ['parameters, 'methods, 'code, 'core] var $named name_aliases [] var $named name ['uniq, "mail_list", "the mail_list"] var $messaged verbs 0 var $mail_list notify [$mail_list] var $mail_list last_received_on 0 var $mail_list senders 1 var $mail_list mail [] var $mail_list readers 1 var $public public ['readable] var $gendered gender $gender_neuter var $described prose #[] public del_sender_from_notification var who; who = sender(); if (!who.has_ancestor($user)) throw(~type, "Sender is not a user."); if (!.has_flag('sender, who)) throw(~perm, who.name() + " cannot read " + .mail_name()); notify = notify.setremove(who); . public add_sender_to_notification var who; who = sender(); if (!who.has_ancestor($user)) throw(~type, "Sender is not a user."); if (!.has_flag('sender, who)) throw(~perm, who.name() + " cannot read " + .mail_name()); notify = [@notify, who]; . public list_is_sendable_by arg who; if (.is_writable_by(who)) return 1; if (type(senders) == 'list) return who in senders; return senders; . public list_is_readable_by arg who; if (.is_writable_by(who)) return 1; if (type(readers) == 'list) return who in readers; return readers; . public set_name arg new_name, [args]; var old_name; old_name = .name(); if (new_name && new_name[1] == "*") new_name = new_name.subrange(2); (> pass(new_name, @args) <); (| $mail_db.key_changed(old_name, new_name) |); . public start if (!.list_is_readable_by(sender())) throw(~perm, "Sender cannot read " + .mail_name() + "."); if (mail) return mail[1]; return 0; . public last_received_on return last_received_on; . public recent_mail arg [diff]; if (!.list_is_readable_by(sender())) throw(~perm, "Sender cannot read " + .mail_name() + "."); diff = [@diff, 20][1]; if (mail.length() < diff) return [0, mail]; return [mail.length() - diff - 1, mail.subrange(mail.length() - diff)]; . public set_notify arg new_value; (> .perms(sender(), 'manager) <); if (type(new_value) != 'integer && type(new_value) != 'list) throw(~type, "new value must be submitted as a list of users or boolean integer."); notify = new_value; . public set_senders arg new_value; (> .perms(sender(), 'manager) <); if (type(new_value) != 'integer && type(new_value) != 'list) throw(~type, "new value must be submitted as a list of users or boolean integer."); senders = new_value; . public notify (> .perms(sender(), 'manager) <); return notify; . public del_mail arg old_mail, [sender]; // what the hell am I thinking? sender = [@sender, sender()][1]; if (!$mail_lib.has_mail_perms(caller())) throw(~perm, caller().namef('xref) + " cannot remove " + old_mail.mail_name()); old_mail.del_recipient(this()); mail = mail.del(old_mail); . public _announce_new_mail arg new_mail; var line, who, n; (> .perms(sender(), 'this) <); if (!notify) return; line = .mail_name() + " has been sent new mail by " + new_mail.from().namef() + ": " + new_mail.subject(); for who in (notify) (| who.tell(line.chop(who.linelen())) |); . public mail // if (!.list_is_sendable_by(sender())) // throw(~perm, "Sender cannot read " + .mail_name() + "."); return mail; . public add_mail var new_mail; (> .perms(caller(), $mail_message) <); last_received_on = time(); new_mail = sender(); // make sure we do not already have it if (new_mail in mail) return; // add it mail = mail.add(new_mail); ._announce_new_mail(new_mail); . public senders (> .perms(sender(), 'manager) <); return senders; . public mail_name return $mail_lib.mail_name(this()); . root init_mail_list mail = []; senders = 1; readers = [.manager()]; notify = [.manager()]; if (!.has_ancestor($user)) { readers = 1; (| $mail_db.insert(.name(), this()) |); } else { readers = [.manager()]; } . root uninit_mail_list var m; for m in (mail) .del_mail(let[1]); mail = []; senders = 1; readers = [.manager()]; notify = []; if (!.has_ancestor($user)) (| $mail_db.remove(.name()) |); . public next arg current_mail; if (!.list_is_readable_by(sender())) throw(~perm, "Sender cannot read this list."); return mail[(current_mail in mail) + 1]; . public mail_list_prev arg current_mail; if (!.list_is_readable_by(sender())) throw(~perm, "Sender cannot read this list."); return mail[(current_mail in mail) - 1]; . parent $mail_list parent $user_interfaces object $mail_ui var $root inited 1 var $root objname 'mail_ui var $root created_on 796268969 var $root indestructable 1 var $root flags ['parameters, 'methods, 'code, 'core] var $mail_ui subscribed #[] var $mail_ui current 0 var $mail_list letters #[] var $mail_list letters_index #[] var $mail_list senders 1 var $mail_list readers [] var $mail_list notify [$mail_ui] var $mail_list last_letter 0 var $mail_list mail [] var $gendered gender $gender_neuter var $described prose #[] var $has_commands local #[["@mail|@send", [["@mail|@send", "* to *", "@mail|@send <any> to <any>", 'mail_to_cmd, #[[1, ['any, []]], [3, ['any, []]]]]]], ["@sub?scribed", [["@sub?scribed", "*", "@sub?scribed <any>", 'subscribe_cmd, #[[1, ['any, []]]]]]], ["@unsub?scribed", [["@unsub?scribed", "*", "@unsub?scribed <any>", 'unsubscribe_cmd, #[[1, ['any, []]]]]]], ["@mail-list?s", [["@mail-list?s", "", "@mail-list?s", 'mail_lists_cmd, #[]]]], ["@mail", [["@mail", "*", "@mail <any>", 'mail_on_cmd, #[[1, ['any, []]]]]]], ["@read", [["@read", "*", "@read <any>", 'mail_read_cmd, #[[1, ['any, []]]]]]], ["@remove-m?ail|@rmm?ail", [["@remove-m?ail|@rmm?ail", "*", "@remove-m?ail|@rmm?ail <any>", 'mail_remove_cmd, #[[1, ['any, []]]]]]]] var $has_commands shortcuts #[] var $named name ['prop, "Mail User Interface", "Mail User Interface"] var $command_cache shortcut_cache 0 var $command_cache remote_cache 0 var $command_cache local_cache 0 public mail_to_cmd arg cmdstr, cmd, note, prep, args; var subj, lists, list, x, mail, text; (> .perms(sender(), 'this) <); lists = []; for x in (args.explode_english_list()) { catch ~listnf { list = $mail_lib.match_mail_recipient(x); lists = [@lists, list]; } with handler { .tell("The list \"" + x + "\" is invalid."); } } if (!lists) return "No valid lists are specified!"; if (note) { text = .match_env_nice(note).text(); } else { text = .read("-- Enter text for mail message, \".\" when done or \"@abort\" to abort --"); if (text == 'aborted) return; } subj = .prompt("Subject: "); if (subj == "@abort") return "** Aborted mail send **"; mail = $mail_message.new_mail(); mail.set_subject(subj); mail.set_text(text); catch any { mail.send(@lists); } with handler { .tell(traceback()[1][2]); } .tell("Mail sent."); . public mail_read_cmd arg cmdstr, cmd, str; var mail, x, args, lname, list, rng; (> .perms(sender(), 'this) <); if (args = $string.match_template("* on *", str)) { rng = args[1]; list = args[3] && (| $mail_lib.match_mail_recipient(args[3]) |) || .current_mail_list(); } else if (str) { rng = str; list = .current_mail_list(); } else { rng = ""; list = .current_mail_list(); } .new_list(list); if (rng) { if (rng == "next") { mail = (| list.next(.current_mail_location()) |); if (!mail) .tell("No next message."); else .read_mail(mail, mail in list.mail(), list.mail_name()); return; } if (rng == "prev") { mail = (| list.mail_list_prev(.current_mail_location()) |); if (!mail) .tell("No previous message."); else .read_mail(mail, mail in list.mail(), list.mail_name()); return; } catch ~range { rng = $mail_lib.range_to_actual($parse_lib.range(rng), current); } with handler { .tell(traceback()[1][2]); return; } } mail = list.mail(); lname = list.mail_name(); if (rng) { for x in [rng[1] .. rng[2]] { if (x > mail.length()) break; .read_mail(mail[x], x, lname); } } else if (current['location]) { .read_mail(current['location], current['location] in mail, lname); } else { .tell("List " + lname + " has no mail on it."); } . public mail_remove_cmd arg cmdstr, cmd, str; var mail, args, list, rng, all_mail, x, name; (> .perms(sender(), 'this) <); args = ._parse_mail_reference(str, "from"); list = args[2]; rng = args[1]; .new_list(list); if (rng) { catch ~range { mail = (| $object_lib.to_dbref(rng) |); if (!mail) { rng = $mail_lib.range_to_actual($parse_lib.range(rng), current); all_mail = list.mail(); mail = []; for x in [rng[1] .. rng[2]] { if (x > all_mail.length()) break; mail = [@mail, all_mail[x]]; } } else { mail = [mail]; } } with handler { .tell(traceback()[1][2]); return; } } else { mail = [current['location]]; } for x in (mail) { catch ~perm { name = x.name(); list.del_mail(x); .tell("Removed mail message " + name + " from " + list.mail_name() + "."); } with handler { .tell(traceback()[1][2]); } } . public read_mail arg mail, loc, list_name; (> .perms(sender(), 'this) <); .tell("Message %l (%l) on %s:".format(loc, mail.name(), list_name)); .tell(mail.format()); mail.did_read(); current = current.add('location, mail); . public subscribed (> .perms(sender(), 'this) <); return subscribed; . public unsubscribe_cmd arg cmdstr, com, str; var list, line, mname; (> .perms(sender(), 'this) <); list = .match_mail_recipient(str); if (list == this()) return .tell("You cannot unsubscribe yourself."); mname = .mail_name(listr); if (!(list in subscribed.keys())) return .tell("You are not subscribed to " + mname); .unsubscribe(list); .tell("Successfully unsubscribed from" + mname + "."); . public subscribe_cmd arg cmdstr, cmd, str; var list, mname, l, args, line, len, out; (> .perms(sender(), 'this) <); // this is ugly bad bad args = $parse_lib.getopt(str, [["n?ew"]]); if (!args[1]) { if ("n?ew" in args[2].slice(1)) { out = []; for l in (subscribed.keys().setremove(this())) { if (l.last_received_on() > subscribed[l]) out = out = [" " + l.mail_name()]; } if (out) .tell(["New mail on:"] + out); return; } .tell("Currently Subscribed Lists:"); len = .linelen() / 3; for l in (subscribed.keys().setremove(this())) { line = " " + l.mail_name(); if (l.last_received_on() > subscribed[l]) line = line + " (new mail)"; .tell(line); } return; } list = $mail_lib.match_mail_recipient(str); mname = $mail_lib.mail_name(list); if (list in subscribed.keys()) return .tell("You are already subscribed to " + mname + "."); if (!list.list_is_readable_by(this())) return .tell(mname + " is not subscribeable by you."); .subscribe(list); .tell("Successfully subscribed to " + mname + "."); . public subscribe arg list; (> .perms(sender(), 'this) <); if (!subscribed) subscribed = #[]; subscribed = subscribed.add(list, time()); (| list.add_sender_to_notification() |); . public unsubscribe arg list; (> .perms(sender(), 'this) <); subscribed = subscribed.del(list); (| list.del_sender_from_notification() |); . public mail_lists_cmd arg [args]; var l, line; (> .perms(sender(), 'this) <); for l in ($mail_db.database().values()) { line = ""; if (l.list_is_readable_by(this())) line = "[Readable]"; if (l.list_is_sendable_by(this())) line = "[Sendable]" + (line ? " " | "") + line; .tell(l.mail_name().pad(.linelen() - line.length() - 1) + " " + line); } . public new_list arg list; (> .perms(sender(), 'this) <); if (list in subscribed.keys()) subscribed = subscribed.add(list, time()); if (list != current['list]) current = current.add('list, list); if (!valid(current['location])) current = current.add('location, list.start()); . root init_mail_ui current = #[['location, .start()], ['list, this()]]; .subscribe(this()); (| .subscribe($mail_list_news) |); .new_list(this()); . public mail_on_cmd arg cmdstr, cmd, str; var syn, args, r, all_mail, mail, rng, x, line, list; (> .perms(sender(), 'this) <); syn = cmd + " [<range> on <mail list>]"; if (args = $string.match_template("* on *", str)) { rng = args[1]; list = args[3] && $mail_lib.match_mail_recipient(args[3]) || this(); } else if (args = (| $mail_lib.match_mail_recipient(str) |)) { return .mail_to_cmd(cmdstr, cmd, "", "", str); } else { rng = ""; list = current['list]; } if (!list.list_is_readable_by(this())) return "You cannot read mail on " + list.mail_name(); catch any { if (list != current['list]) .new_list(list); all_mail = current['list].mail(); if (!all_mail) { .tell("No mail on " + $mail_lib.mail_name(list) + "."); return; } if (!rng) { r = [1, all_mail.length()]; rng = r; } else { rng = $parse_lib.range(rng); r = $mail_lib.range_to_actual(rng, current); } } with handler { switch (error()) { case ~listnf, ~range: .tell(traceback()[1][2]); default: rethrow(error()); } return; } line = "Mail"; if (r[1] != r[2]) line = line + " from " + tostr(rng[1]) + " to " + tostr(rng[2]); line = line + " on " + $mail_lib.mail_name(current['list]) + ":"; .tell(line); for x in [r[1] .. r[2]] { mail = all_mail[x]; line = mail == current['location] ? "=>" | " "; line = line + tostr(x).pad(-3) + ":"; line = line + (mail.has_read(this()) ? " " | "!") + " "; line = line + mail.subject().pad(.linelen() - 38) + " "; line = line + mail.from().name().pad(19) + " "; line = line + $time.ldate(mail.time(), 'date).pad(9); .tell(line); } .tell("------"); . public _parse_mail_reference arg str, prep; var args; if (args = $string.match_template("* " + prep + " *", str)) return [args[1], args[3] && (| $mail_lib.match_mail_recipient(args[3]) |) || current['list]]; return ["", current['list]]; . public current_mail_location (> .perms(sender()) <); if (!(| valid(current['location]) |)) current = current.add('location, .start()); return current['location]; . public current_mail_list (> .perms(sender()) <); if (!(| valid(current['list]) |)) current = current.add('location, this()); return current['list]; . parent $user_interfaces object $command_aliases var $root inited 1 var $root objname 'command_aliases var $root created_on 796268969 var $root flags ['parameters, 'methods, 'code, 'core] var $command_aliases command_aliases [] var $command_cache shortcut_cache 0 var $command_cache remote_cache 0 var $command_cache local_cache 0 root init_command_aliases command_aliases = []; . root uninit_command_aliases command_aliases = []; . public command_aliases return command_aliases; . public all_command_aliases var user, aliases, userc; // Collect complete command alias list from ancestors. aliases = []; for user in (.ancestors()) { userc = (| user.command_aliases() |); if (userc) aliases = aliases + userc; if (user == definer()) break; } return aliases; . public match_command_aliases arg str; var alias, argf, match, newstr; // attempts to rebuild the string for an alias. if (sender() != this()) throw(~perm, "Sender is not this."); for alias in (.all_command_aliases()) { match = $string.match_pattern(alias[1], str); if (match != 0) { newstr = alias[2]; for argf in [1 .. match.length()] newstr = newstr.replace("%" + tostr(argf), match[argf]); return newstr; } } return str; . public add_command_alias arg alias, actual; var index, a; (> .perms(sender()) <); if (type(alias) != 'string || type(actual) != 'string) throw(~type, "alias and actual are not strings."); while ("%" in alias) { alias = alias.replace("%" + tostr(index), "*"); index = index + 1; } // have it 'replace' the old alias (if one exists) by first removing // the old one, and adding the new one later. for a in (command_aliases) { if (a[1] == alias) command_aliases = command_aliases.setremove(a); } command_aliases = [@command_aliases, [alias, actual]]; . public del_command_alias arg alias; var ca; (> .perms(sender()) <); if (type(alias) != 'string) throw(~type, "alias is not a string."); for ca in (command_aliases) { if (ca[1] == alias) { command_aliases = command_aliases.setremove(ca); return; } } throw(~aliasnf, "alias `" + alias + "' is not found"); . parent $user_interfaces object $bad_commands var $root inited 1 var $root objname 'bad_commands var $root created_on 796268969 var $root flags ['parameters, 'methods, 'code, 'core] var $bad_commands non_supported_cmds #[["quit", "@quit"], ["WHO", "@who"], ["@create", "@spawn"], ["@dig", "@build"], ["help", "@help"], ["news", "@news"], ["page", "@page"], ["@gender", "@set gender"], ["uptime", "@uptime"]] var $has_commands local #[["@create", [["@create", "*", "@create <any>", 'old_command_cmd, #[[1, ['any, []]]]]]], ["@dig", [["@dig", "*", "@dig <any>", 'old_command_cmd, #[[1, ['any, []]]]]]], ["help", [["help", "*", "help <any>", 'old_command_cmd, #[[1, ['any, []]]]]]], ["page", [["page", "*", "page <any>", 'old_command_cmd, #[[1, ['any, []]]]]]], ["who", [["who", "*", "who <any>", 'old_command_cmd, #[[1, ['any, []]]]]]], ["quit", [["quit", "*", "quit <any>", 'old_command_cmd, #[[1, ['any, []]]]]]], ["news", [["news", "*", "news <any>", 'old_command_cmd, #[[1, ['any, []]]]]]], ["@gender", [["@gender", "*", "@gender <any>", 'old_command_cmd, #[[1, ['any, []]]]]]], ["uptime", [["uptime", "*", "uptime <any>", 'old_command_cmd, #[[1, ['any, []]]]]]]] var $command_cache shortcut_cache 0 var $command_cache remote_cache 0 var $command_cache local_cache 0 public mangled_command arg str; . public add_old_cmd_reference arg oldcmd, [newcmd]; (> .perms(sender(), 'admin) <); if (this() != $bad_commands) throw(~perm, "Only define bad commands on $bad_commands"); if (newcmd) non_supported_cmds = non_supported_cmds.add(oldcmd, newcmd[1]); .add_command(oldcmd, 'old_command_cmd); . public del_old_cmd_reference . public old_command_cmd arg cmdstr, com, [args]; var line, equiv, pref; (> .perms(sender(), 'this) <); equiv = (| ($bad_commands.non_supported_cmds())[com] |); line = "Oops, `" + com + "` is not supported here."; if (equiv) line = line + " Try `" + equiv + "`"; .tell(line); .tell("Use `@help commands` for an explanation on the differences in commands."); . public non_supported_cmds return non_supported_cmds; . parent $user_interfaces parent $has_settings object $user_data var $root inited 1 var $root objname 'user_data var $root created_on 796268969 var $root flags ['parameters, 'methods, 'code, 'core] var $user_data valid_settings #[["real-name", 'real_name], ["email", 'email], ["address", 'address], ["affiliation", 'affiliation], ["position", 'position], ["location", 'location], ["interests", 'interests], ["plan", 'plan], ["projects", 'projects], ["see-also", 'see_also]] var $user_data user_data #[] var $messaged verbs #[] var $has_commands local #[["@finger-data|@user-data", [["@finger-data|@user-data", "* my * is|are *", "@finger-data|@user-data <any> my <any> is|are <any>", 'data_is_cmd, #[[1, ['any, []]], [3, ['any, []]], [5, ['any, []]]]]]], ["@finger|@user-data", [["@finger|@user-data", "*", "@finger|@user-data <any>", 'data_cmd, #[[1, ['any, []]]]]]], ["@set-finger|@set-user-data", [["@set-finger|@set-user-data", "* as|to *", "@set-finger|@set-user-data <any> as|to <any>", 'set_info_cmd, #[[1, ['any, []]], [3, ['any, []]]]]]]] var $command_cache shortcut_cache 0 var $command_cache remote_cache 0 var $command_cache local_cache 0 var $has_settings defined_settings #[] var $has_settings local_settings #[] var $has_settings settings #[] public data_on arg data; data = (| user_data[data] |); if (data) { if (data[1] || .is_writable_by(sender())) return data[2]; return "not public."; } else { return "not set."; } . public set_data arg key, value, public; (> .perms(sender(), 'this) <); if (!value) { if ((| user_data[key] |)) user_data = (| user_data.del(key) |); } else { user_data = user_data.add(key, [public, value]); } . root init_user_data user_data = #[['real_name, [1, "???"]], ['email, [1, "???"]]]; . public valid_settings return valid_settings; . public data_is_cmd arg cmdstr, cmd, what, is, args; var valid, line, syntax, value, public; (> .perms(sender(), 'this) <); valid = $user_data.valid_settings(); what = (| valid[what] |); if (!what) { syntax = cmd + " <setting name> is|to <value> [+/-public]"; lines = ["Where setting name can be any of: "]; lines = [@lines, valid.keys().to_english()]; $parse_lib.tell_error(lines, syntax); } args = $parse_lib.options(args, #[["public", [1, 0]]]); public = args[2]; value = args[1].to_string(); .set_data(what, value, public["public"][1]); . public data_cmd arg cmdstr, com, who; var valid, line, user, out; if (!who) user = this(); else user = (| .find_object(who, 'user, 'environment, 'grasp) |); if (!user) { .tell("! No user found by the name \"" + who + "\"."); .tell("! To set a value use the syntax:"); .tell("! '" + com + " [+p|+public|-p|-public] my <parameter> is|are <value>'"); return 0; } out = "Current personal data settings on " + user.namef() + ":"; // valid = $user_data.valid_settings(); out = [out, @user.display_data()]; if (user.connected()) out = [@out, user.name() + " is connected."]; else out = [@out, user.name() + " was last connected at " + $time.ltime(abs(user.connected_at())) + " " + $time.ldate(abs(user.connected_at()))]; return out; . public display_data arg [dont_display]; var x, valid, line, len, pub, actor, data, lines, output; actor = sender(); len = actor.linelen(); valid = $user_data.valid_settings(); output = []; for x in (valid) { if (!(x[2] in dont_display)) { data = (| user_data[x[2]] |); if (data) { if (data[1] || .is_writable_by(actor)) line = data[2]; else line = "not public."; } else { continue; } pub = (| user_data[x[2]][1] |); pub = !pub && type(pub) != 'error ? "*" | " "; if (len - 20 < line.length()) { output = [@output, pub + $string.capitalize(x[1]) + ":"]; lines = $string.wrap_line(line, len, " "); lines = lines.replace(1, " " + lines[1]); output = output + lines; } else { output = output + [pub + ($string.capitalize(x[1]) + ": ").pad(13) + line]; } } } return output; . public set_info_cmd arg cmdstr, cmd, what, is, args; var valid, lines, syntax, value, public; (> .perms(sender(), 'this) <); valid = $user_data.valid_settings(); what = (| valid[what] |); if (!what) { syntax = cmd + " <setting name> is|to <value> [+/-public]"; lines = ["Where setting name can be any of: "]; lines = [@lines, valid.keys().to_english()]; $parse_lib.tell_error(lines, syntax); } args = $parse_lib.options(args, #[["public", [1, 0]]]); public = args[2]; value = args[1].to_string(); if (value in ["none", "<none>"]) value = ""; .set_data(what, value, public["public"][1]); if (!value) .tell("You unset " + tostr(what).capitalize() + "."); else .tell("You set " + tostr(what).capitalize() + " to " + $string.chop(value, 50)); . public user_data arg [which]; var d, v; if (!which && !.is_writable_by(sender())) throw(~perm, "You are unable to get full user data, try specific fields."); if (which) { which = which[1]; v = $user_data.valid_settings().values(); d = (| user_data[which] |); if (!d && !(which in v)) throw(~type, "No user data field type of " + toliteral(which)); else if (!d) return "Not set."; else if (!d[1] && !.is_writable_by(sender())) throw(~perm, "That value is not public."); else return d[2]; } else { return user_data; } . parent $help_root parent $user_interfaces object $help_ui var $root fertile 1 var $root inited 1 var $root objname 'help_ui var $root created_on 796268969 var $root flags ['parameters, 'methods, 'code, 'fertile, 'core] var $has_commands local #[["@help", [["@help", "*", "@help <any>", 'help_cmd, #[[1, ['any, []]]]]]], ["@help-link", [["@help-link", "*", "@help-link <any>", 'help_link_cmd, #[[1, ['any, []]]]]]]] var $has_commands shortcuts #[["?*", ['help_cmd, ["?", 1]]]] var $command_cache shortcut_cache 0 var $command_cache remote_cache 0 var $command_cache local_cache 0 var $help_ui current 1 var $help_ui history [$help_summary] var $help_ui indices [$help_index_root] protected help_indices return indices; . root init_help_ui history = [$help_lib.default_node()]; indices = [$help_lib.default_index()]; current = 1; . public current_node return history[current]; . protected help_cmd arg cmdstr, cmd, args; var o, opt, optval, way, node; o = #[["?", ["h?istory"]], ["<", ["b?ack"]], [">", ["f?orward"]], [".", ["fixate"]]]; args = $parse_lib.getopt(args, o.values()); opt = args[2]; args = args[1]; if (!opt) { if (!args) { if (cmd == "?") node = .current_node(); else node = $help_lib.default_node(); } else { args = args.to_string(); if (args[1] in o.keys()) { opt = o[args[1]][1]; if (args.length() > 1) optval = args.subrange(2); } else { catch ~nonode { node = (> $help_lib.parse_reference(args) <); } with handler { return traceback()[1][2]; } } } } else { // since all options override each other, just use the last one. optval = opt[opt.length()][4]; opt = opt[opt.length()][1]; } if (!node) { catch ~nonode { switch (opt) { case "h?istory": return ._help_node_history(); case "b?ack": node = (> ._navigate_node_history(optval, 'back) <); case "f?orward": node = (> ._navigate_node_history(optval, 'forward) <); case "fixate": if (current != history.length()) { node = history[current]; history = (| history.delete(current) |) || history; history = history + [node]; current = history.length(); } return; } } with handler { return traceback()[1][2]; } } .set_help_node(node); .tell_help_node(node); . protected last_visited (> .perms(sender()) <); return last_visited; . protected _find_help_node arg what, type; var pos, cnode; (> .perms(sender(), 'this) <); switch (type) { case 'index: cnode = $help_index.find_help_node(what); if (cnode) return cnode; else throw(~nonode, "Unable to find help on \"" + what + "\"."); case 'link: if (what in current_node.links().keys()) return (current_node.links())[what]; else throw(~nonode, "No node link \"" + what + "\" found on current node."); default: if (current_node.(type)()) { if (what.length() == 1) { return current_node.(type)()[1]; } else { what = what.subrange(2); pos = what in current_node.(type)().map('name); if (pos) return current_node.(type)()[pos]; else throw(~nonode, "No downnode named " + what); } } else { throw(~nonode, "No " + tostr(type) + " defined from node " + current_node.name() + "."); } } . protected _back_help_node var pos; (> .perms(sender(), 'this) <); pos = current - 1; if (pos >= 1) { current = pos; return history[current]; } throw(~nonode, "You are at the start of your help node history, use \"??\" to list the history."); . protected _forward_help_node var pos; (> .perms(sender(), 'this) <); pos = current + 1; if (pos <= $help_lib.history_cap() && pos <= history.length()) { current = pos; return history[current]; } throw(~nonode, "You are at the end of your help node history, use \"??\" to list the history."); . protected set_help_node arg node; if (node in history && history[current] == node) return; while (history.length() >= $help_lib.history_cap()) history = history.delete(1); history = history + [node]; current = history.length(); . protected _navigate_node_history arg what, way; var node; (> .perms(sender(), 'this) <); if (!what) { return (> .(tosym("_" + tostr(way) + "_help_node"))() <); } else { for node in (history) { if (node.match_name(what)) return node; } throw(~nonode, "There is no node \"" + what + "\" in your history."); } . protected _help_node_history var node, line; .tell("Help node history:"); for node in [1 .. history.length()] { line = " "; if (node == current) line = "=> "; catch any { .tell(line + history[node].name()); } with handler { history = history.delete(node); .set_help_node(history[1]); .tell(line + ">> ERROR: INVALID NODE IN HISTORY <<"); } } . protected tell_help_node arg node; var out, len, clen, line, n; len = .linelen() % 2 ? .linelen() - 1 | .linelen(); .tell((" " + node.node_name() + " ").center(len, "-")); .ptell(node.body(), #[['type, 'help], ['ctype, 'ctext]]); .tell("".pad(len, "-")); . root uninit_help_ui .clear_variable('history); .clear_variable('indices); .clear_variable('current); . protected help_node_history return history; . parent $user_interfaces object $messages_ui var $root fertile 1 var $root inited 1 var $root objname 'messages_ui var $root created_on 796268969 var $root flags ['parameters, 'methods, 'code, 'fertile, 'core] var $has_commands local #[["@mes?sages|@mesg", [["@mes?sages|@mesg", "*", "@mes?sages|@mesg <any>", 'messages_cmd, #[[1, ['any, []]]]]]]] var $command_cache shortcut_cache 0 var $command_cache remote_cache 0 var $command_cache local_cache 0 public messages_cmd arg cmdstr, cmd, args; var opt, definer, t, p, name, value, object, reg, s; if (!args) return .display_messages("", this()); reg = "(.*)<(.*)>(.*)".sub(args); if (reg) { definer = .match_env_nice(reg[2]); args = reg[1] + reg[2]; } if ("=" in args) s = "="; else s = " "; if (s in args) { name = args.subrange(1, (s in args) - 1).trim(); args = args.subrange((s in args) + 1); } else { name = args; args = ""; } if (":" in name) { object = .match_env_nice(name.subrange(1, (":" in name) - 1)); name = name.subrange((":" in name) + 1); } else { object = this(); } if (!object.has_ancestor($has_messages)) return object.namef() + " cannot have any messages."; if (!name) return .display_messages("", object); value = args.unquote(); catch any { object.set_message(name, value); .tell("Message changed to:"); .display_messages(name, object); } with handler { return traceback()[1][2]; } . public display_messages arg mask, obj; var output, definer, message, p, s, uncompiler, name, messages; output = []; messages = obj.messages(); for definer in (messages.keys()) { output = [@output, definer.namef('xref) + ":"]; for message in (messages[definer].keys()) { name = (definer._find_message_definer(message))[1]; uncompiler = definer.message_info(name, 'uncompiler); p = uncompiler.eval_ctext(obj.message(message)._ctext()); if (type(p) == 'dictionary) { for s in (p.keys()) { if ($string.match_begin(message + "." + s, mask)) output = [@output, [" " + message + "." + s + " = "].join(p[s])]; } } else if ($string.match_begin(message, mask)) { output = [@output, [" " + message + " = "].join(p)]; } } } return output; . parent $user_interfaces object $settings_ui var $root inited 1 var $root objname 'settings_ui var $root created_on 796268969 var $root flags ['parameters, 'methods, 'code, 'core] var $has_commands local #[["@set?ings", [["@set?ings", "*", "@set?ings <any>", 'set_cmd, #[[1, ['any, []]]]]]], ["@set?tings", [["@set?tings", "on|from *", "@set?tings on|from <object reference>", 'settings_on_cmd, #[[2, ['objref, []]]]]]]] var $command_cache shortcut_cache 0 var $command_cache remote_cache 0 var $command_cache local_cache 0 public settings_cmd arg cmdstr, cmd, args; var flag, value, template, syn, bool, line; (> .perms(sender()) <); syn = cmd + " [+|-]<flag>[=<value>]"; if (!args) { return .list_settings('local); } else if (args in ["-all", "-a"]) { return .list_settings('all); } else { bool = args[1] in ["-", "+"]; if (bool) args = args.subrange(2); args = args.explode("="); flag = args[1]; if (args.length() == 2) value = args[2]; else value = ""; template = .setting_template(flag); if (!template) $parse_lib.tell_error("No setting available with the flag \"" + flag + "\".", syn); switch (template[2]) { case 'boolean: if (!bool) $parse_lib.tell_error("Value must be boolean (+|-" + flag + ").", syn); value = bool - 1; case 'integer: if (!$string.is_numeric(value)) $parse_lib.tell_error("Value must be an integer (" + flag + "=<integer>).", syn); value = toint(value); case 'string: if (!value) $parse_lib.tell_error("Value must be a string (" + flag + "=<string>).", syn); } .set_setting(flag, value); line = "Setting " + flag + " set to "; switch (template[2]) { case 'boolean: line = line + (value == 1 ? "+" | "-"); default: line = line + toliteral(value); } .tell(line); } . public settings_on_cmd arg cmdstr, cmd, prep, ref; (> .perms(sender()) <); // this is a hookneyed way to do it, and wont work out in the long run, // but until we get arguments in the parser this will work fine if (ref[2] == ref[3]) return ._show_settings(ref[3]); else return ._show_settings_on(ref[3], ref[2]); . public _show_setting arg setting, definer, object; var line; line = " " + setting + " = "; setting = (| object.display_setting(setting, definer) |); if (setting != ~setting) line = line + setting; return line; . public _show_settings_on arg definer, object; var settings, s, setting, line, out; if (!object.trusts(this())) return [definer.namef('xref) + ":", " ** Unable to see settings **"]; settings = (| definer.defined_settings() |) || []; out = []; for s in (settings) out = [@out, ._show_setting(s, definer, object)]; if (!out) out = [" (none)"]; return [definer.namef('xref) + ":"] + out; . public set_cmd arg cmdstr, cmd, args; var opt, definer, t, p, name, value, object, reg, s; (> .perms(sender()) <); if (!args) return ._show_settings(this()); reg = $string.match_regexp("<.*>", args); if (reg) { definer = .match_env_nice(args.subrange(reg[1][1] + 1, reg[1][2] - 2)); args = args.subrange(1, reg[1][1] - 1) + args.subrange(reg[1][1] + reg[1][2]); } if ("=" in args) s = "="; else s = " "; if (s in args) { name = args.subrange(1, (s in args) - 1).trim(); args = args.subrange((s in args) + 1); } else { name = args; args = ""; } if (":" in name) { object = .match_env_nice(name.subrange(1, (":" in name) - 1)); name = name.subrange((":" in name) + 1); } else { object = this(); } if (!name) return ._show_settings(object); // this should fix the quotes value = args.unquote(); catch any { ._change_setting(name, value, definer, object); .tell(["Setting changed to:", ._show_setting(name, definer, object)]); } with handler { return traceback()[1][2]; } . public _show_settings arg object; var a, s, out; if (!object.trusts(this())) return object.namef('ref) + " does not trust you enough to show you " + ((| object.gender() |) || $gender_neuter).pronoun('pp) + " settings."; out = []; for a in (object.ancestors()) { if (a == definer()) break; s = (| a.defined_settings() |); if (s) out = out + ._show_settings_on(a, object); } return out; . public _change_setting arg name, value, definer, object; var current, style, index, pos; (> .perms(sender(), 'writers) <); style = name.last(); if (style in ["+", "-"]) { name = name.subrange(1, name.length() - 1); if (!definer) definer = object._find_setting_definer(name); current = object.setting(name, definer) || []; if (style == "+") value = [@current || [], value]; else value = current.delete(toint(value)); } catch ~check, ~set { (> object.set_setting(definer, name, value) <); } with handler { .tell(traceback()[1][2]); throw(~stop, "", 'no_traceback); } . parent $body parent $interaction parent $mail_ui parent $command_aliases parent $bad_commands parent $user_data parent $help_ui parent $messages_ui parent $has_messages parent $settings_ui object $user var $root owners [$user] var $root inited 1 var $root created_on 796268969 var $root owned [$user] var $root manager $user var $root objname 'user var $root flags ['parameters, 'methods, 'code, 'core, 'fertile] var $root managed [$user] var $root child_index 2 var $messaged verbs #[] var $location contents [] var $located location $nowhere var $located obvious 1 var $user password "*" var $user connected_at 0 var $user last_command_at 0 var $user connections [] var $user linelen 0 var $user title 0 var $user action 0 var $user channels [] var $user pagelen 0 var $user activity 0 var $user parsers [$command_parser] var $user filters [] var $user tell_traceback 0 var $user context #[] var $user remembered 0 var $user evaluator 0 var $user connected_seconds 0 var $command_aliases command_aliases [] var $mail_list letters #[] var $mail_list letters_index #[] var $mail_list senders 1 var $mail_list readers [] var $mail_list notify [$user] var $mail_list last_letter 0 var $mail_list mail [] var $mail_ui subscribed #[[$user, 791485891]] var $mail_ui current #[['location, 0], ['list, $user]] var $gendered gender $gender_neuter var $described prose [] var $named name ['prop, "Generic User Object", "Generic User Object"] var $named name_aliases [] var $user_data user_data #[['real_name, [1, "???"]], ['email, [1, "???"]]] var $has_commands local #[["@quit", [["@quit", "", "@quit", 'quit_cmd, #[]]]], ["i?nventory", [["i?nventory", "", "i?nventory", 'inventory_cmd, #[]]]], ["@title", [["@title", "*", "@title <any>", 'title_cmd, #[[1, ['any, []]]]]]], ["@add-name-alias|@ana", [["@add-name-alias|@ana", "*", "@add-name-alias|@ana <any>", 'add_name_alias_cmd, #[[1, ['any, []]]]]]], ["@del-name-alias|@dna", [["@del-name-alias|@dna", "*", "@del-name-alias|@dna <any>", 'del_name_alias_cmd, #[[1, ['any, []]]]]]], ["@audit", [["@audit", "*", "@audit <any>", 'audit_cmd, #[[1, ['any, []]]]]]], ["@who", [["@who", "*", "@who <any>", 'who_cmd, #[[1, ['any, []]]]]]], ["@del-command-a?lias|@dca?lias", [["@del-command-a?lias|@dca?lias", "*", "@del-command-a?lias|@dca?lias <any>", 'del_command_alias_cmd, #[[1, ['any, []]]]]]], ["@command-a?liases|@ca?liases", [["@command-a?liases|@ca?liases", "*", "@command-a?liases|@ca?liases <any>", 'command_aliases_cmd, #[[1, ['any, []]]]]]], ["@wrap", [["@wrap", "*", "@wrap <any>", 'wrap_cmd, #[[1, ['any, []]]]]]], ["@add-command-a?lias|@aca?lias", [["@add-command-a?lias|@aca?lias", "*", "@add-command-a?lias|@aca?lias <any>", 'add_command_alias_cmd, #[[1, ['any, []]]]]]], ["@com?mands", [["@com?mands", "*", "@com?mands <any>", 'commands_cmd, #[[1, ['any, []]]]]]], ["@spawn", [["@spawn", "*", "@spawn <any>", 'spawn_cmd, #[[1, ['any, []]]]]]], ["@rehash?-commands", [["@rehash?-commands", "", "@rehash?-commands", 'rehash_cmd, #[]]]], ["@news", [["@news", "", "@news", 'news_cmd, #[]]]], ["@forget", [["@forget", "*", "@forget <any>", 'forget_cmd, #[[1, ['any, []]]]]]], ["@whereis|@where-is", [["@whereis|@where-is", "*", "@whereis|@where-is <any>", 'whereis_cmd, #[[1, ['any, []]]]]]], ["@ways", [["@ways", "", "@ways", 'ways_cmd, #[]]]], ["@password|@passwd", [["@password|@passwd", "*", "@password|@passwd <any>", 'password_cmd, #[[1, ['any, []]]]]]], ["@describe|@prose", [["@describe|@prose", "*", "@describe|@prose <any>", 'description_cmd, #[[1, ['any, []]]]]]], ["l?ook", [["l?ook", "", "l?ook", 'look_cmd, #[]]]], ["@age", [["@age", "*", "@age <object>", 'age_cmd, #[[1, ['object, []]]]]]], ["@context", [["@context", "", "@context", 'context_cmd, #[]]]], ["get|take", [["get|take", "*", "get|take <thing>", 'get_cmd, #[[1, ['descendant, [$thing]]]]], ["get|take", "* from *", "get|take <any> from <thing>", 'get_from_cmd, #[[1, ['any, []]], [3, ['descendant, [$thing]]]]]]], ["drop", [["drop", "*", "drop <thing>", 'drop_cmd, #[[1, ['descendant, [$thing]]]]]]], ["give|put", [["give|put", "* to|in *", "give|put <thing> to|in <thing>", 'give_to_cmd, #[[1, ['descendant, [$thing]]], [3, ['descendant, [$thing]]]]]]], ["@rename", [["@rename", "*", "@rename <any>", 'rename_cmd, #[[1, ['any, []]]]]]], ["@name-alias?es|@na", [["@name-alias?es|@na", "*", "@name-alias?es|@na <object>", 'name_aliases_cmd, #[[1, ['object, []]]]]]], ["go", [["go", "*", "go <any>", 'go_cmd, #[[1, ['any, []]]]]]], ["@status|@uptime", [["@status|@uptime", "", "@status|@uptime", 'status_cmd, #[]]]], ["@add-writer|@aw", [["@add-writer|@aw", "*", "@add-writer|@aw <any>", 'add_writer_cmd, #[[1, ['any, []]]]]]], ["@del-writer|@dw", [["@del-writer|@dw", "*", "@del-writer|@dw <any>", 'del_writer_cmd, #[[1, ['any, []]]]]]], ["@trusted?-by", [["@trusted?-by", "*", "@trusted?-by <any>", 'trusted_by_cmd, #[[1, ['any, []]]]]]], ["@add-trust?ee|@at", [["@add-trust?ee|@at", "*", "@add-trust?ee|@at <any>", 'add_trustee_cmd, #[[1, ['any, []]]]]]], ["@del-trust?ee|@dt", [["@del-trust?ee|@dt", "*", "@del-trust?ee|@dt <any>", 'del_trustee_cmd, #[[1, ['any, []]]]]]], ["@writes", [["@writes", "*", "@writes <any>", 'writes_cmd, #[[1, ['any, []]]]]]], ["@chman?age", [["@chman?age", "*", "@chman?age <any>", 'chmanage_cmd, #[[1, ['any, []]]]]]], ["@manage?d", [["@manage?d", "*", "@manage?d <any>", 'managed_cmd, #[[1, ['any, []]]]]]], ["@owned", [["@owned", "*", "@owned <any>", 'owned_cmd, #[[1, ['any, []]]]]]], ["@remember", [["@remember", "* as *", "@remember <object> as <any>", 'remember_cmd, #[[1, ['object, []]], [3, ['any, []]]]]]], ["@remembered", [["@remembered", "*", "@remembered <any>", 'remembered_cmd, #[[1, ['any, []]]]]]]] var $has_commands shortcuts #[] var $has_settings settings #[] var $has_settings setting_types #[["terminated-tell", #[['type, "boolean"], ['check, 'is_boolean], ['get, 'get_direct_setting], ['set, 'set_direct_setting], ['del, 'del_direct_setting], ['set_args, ['name, 'definer, 'value, 'style]], ['get_args, ['name, 'definer]]]], ["content-type", #[['type, "string"], ['check, 'is_anything], ['get, 'get_direct_setting], ['set, 'set_direct_setting], ['del, 'del_direct_setting], ['set_args, ['name, 'definer, 'value, 'style]], ['get_args, ['name, 'definer]]]]] var $has_settings setting_data #[[$user, #[["content-type", "text/plain"]]]] var $has_settings defined_settings #[["content-type", #[['get, 'get_local_setting], ['set, 'set_content_type], ['check, 'check_content_type], ['del, 'delete_local_setting], ['check_args, []], ['get_args, []], ['set_args, []]]], ["home-page", #[['get, 'get_local_setting], ['set, 'set_local_setting], ['check, 'is_any], ['del, 'delete_local_setting], ['check_args, []], ['get_args, []], ['set_args, []]]], ["terminated-tell", #[['get, 'get_local_setting], ['set, 'set_local_setting], ['check, 'is_boolean], ['del, 'delete_local_setting], ['check_args, []], ['get_args, []], ['set_args, []], ['display, 'display_boolean_yes_no]]], ["experienced", #[['get, 'get_local_setting], ['set, 'set_local_setting], ['check, 'is_boolean], ['del, 'delete_local_setting], ['check_args, []], ['get_args, []], ['set_args, []], ['display, 'display_boolean_yes_no]]]] var $has_settings local_settings #[] var $help_ui indices [$help_index_root] var $help_ui history [$help_summary] var $help_ui current 1 var $command_cache shortcut_cache 0 var $command_cache remote_cache 0 var $command_cache local_cache 0 root init_user password = "*"; connected_at = 0; last_command_at = 0; connections = []; parsers = [$command_parser]; action = ""; context = #[]; .set_quota($sys.get_starting('quota)); $user_db.insert(.name(), this()); .set_flags([]); .move_to($body_cave); . root uninit_user var conn; if (.connected()) (| .location().did_disconnect() |); // and incase any are lying about for conn in (connections) (| conn.user_going_away() |); password = 0; connections = 0; (| $user_db.remove(.name()) |); . public will_move arg mover, place; (> pass(mover, place) <); if (!place.has_ancestor($place)) throw(~user, "Users can only move into descendants of $place."); . public connected_at return connected_at; . public last_command_at return last_command_at; . public tell arg what, [args]; var filter, ctype; // first argument should always be the content type, subsequent // arguments can relate to the content type. if (!.connected()) return; ctype = [@args, 'interaction][1]; switch (ctype) { case 'channel: if (!.listens_to_channel(@args.subrange(2))) return; } ._tell(what); . public set_password arg str; var x, num; .perms(sender(), 'manager); if (str.length() < 5) throw(~badpasswd, "Passwords must be at least 5 characters long."); // this is assuming they have alphabetic characters as well (shrug). // for x in [1 .. str.length()] { // if (str[x] in "1234567890") // num = num + 1; // } // if (num < 2) // throw(~badpasswd, "Passwords must contain at least 2 numeric characters."); password = str.crypt(); . public check_password arg str; return str.crypt(password.subrange(1, 2)) == password; . public did_move arg [args]; var loc; (> pass(@args) <); loc = .location(); (| loc.look_cmd("look") |); . public parsers .perms(sender(), 'trusts); return parsers; . public add_parser arg parser, [position]; // adds a new $parse_libr at 'position. (> .perms(sender(), 'this) <); // do this in three steps, first make sure the posistion is valid, // then check for it already, then figure its insert position. position = [@position, 'first][1]; if (!(position in ['last, 'first])) throw(~type, "Posistion types must be one of: 'last, 'first."); // does it exist? If so remove it. if (parser in parsers) parsers = parsers.setremove(parser); // figure position if (position == 'last) position = parsers.length() + 1; else if (position == 'first) position = 1; parsers = parsers.insert(position, parser); . public del_parser arg parser; var keepers; // removes a parser. Cannot remove $command_parser (put things in // front of it instead). if (parser == $command_parser) throw(~no, "You must always have the $command_parser."); parsers = parsers.setremove(parser); . public parse_line arg line; var result, c, rval; (> .perms(caller(), $connection) <); last_command_at = time(); catch any { result = parsers ? parsers[1].parse(this(), line, @parsers.subrange(2), $null_parser) | 'failed; if (type(result) == 'list) { rval = (> result[1].(result[2])(@result.subrange(3)) <); switch (type(rval)) { case 'list, 'frob, 'string: return .ptell(rval, #[['type, 'parser], ['command, result[2]]]); default: return rval; } } switch (result) { case 'failed: // try one last time to at least give them an intelligent // answer... for c in ($places.coordinate_shortcuts().keys()) { if ($string.match_template(c, line)) return .tell("There is no exit " + line + " here."); } .tell("I don't understand \"" + $string.chop(line, .linelen() - 22) + "\"."); case 'ok: default: .tell(tostr(result)); } } with handler { if (traceback()[1][3] != 'no_traceback) .tell_traceback(traceback(), line, 0, error()); } . public login arg connection; var loc; if (sender() != this() || definer() != caller()) throw(~perm, "Invalid access to private method."); (| .reset_parsers() |); $user_db.did_connect(); connected_at = time(); last_command_at = time(); loc = .location(); if (loc == $body_cave) { if (.home() != $body_cave) (| .move_to(.home()) |); else (| .move_to($places.place('starting)) |); } (| .location().did_connect() |); (| .rehash_caches() |); (| .login_notify(connection) |); $channels.announce('login, .namef('titled) + " has connected (total: " + tostr($user_db.total_connected()) + ")", 0, [this()], this()); . public login_again arg connection; if (sender() != this() || definer() != caller()) throw(~perm, "Invalid access to private method."); last_command_at = time(); (| .tell($string.center("* * * " + $integer.n_to_nth(connection in .connections()) + " Login successful (" + connection.addr() + ") * * *", .linelen())) |) || (| .tell($string.center("* * * " + $integer.n_to_nth(connection in .connections()) + " Login successful (" + connection.address() + ") * * *", .linelen())) |); . public logout arg connection; if (sender() != this() || definer() != caller()) throw(~perm, "Invalid access to private method."); (| .location().did_disconnect() |); (| .reset_parsers() |); (| $user_db.did_disconnect() |); // Track how long they are online (random info) -Lynx connected_seconds = connected_seconds + (time() - connected_at); // set this to -last_command so we know they aren't connected // (and using last command will be last_login) connected_at = -last_command_at; // user specific things if (!($guest in .parents())) { (| $housekeeper.did_disconnect() |); (| $user_db.last_log_disconnect(this()) |); } else { (| $user_db.last_log_disconnect($guest) |); } (| .purge_caches() |); $channels.announce('login, .namef('titled) + " has disconnected (total: " + tostr($user_db.total_connected()) + ")", 0, [this()], this()); . public connections return connections; . public connected return connections ? 1 | 0; . protected who_cmd arg cmdstr, com, [line]; var who, opts, opt, args, all; // just the basic who listing who = []; if (!line[1]) { args = [$user_db.connected(), "Connected Users"]; } else if (line[1][1] == "@") { args = ._who_at_place(line[1].subrange(2)); } else { args = $parse_lib.getopt(line[1], [["a?ll"], ["p?rogrammers"], ["a?dmins"], ["s?hort"]]); opts = args[2]; args = args[1]; if (opt = "a?ll" in opts.slice(1)) all = opts[opt][3]; if (opt = "p?rogrammers" in opts.slice(1)) args = ._who_programmers(args, all); else if (opt = "a?dmins" in opts.slice(1)) args = ._who_admins(args, all); else if (opt = "s?hort" in opts.slice(1)) return ._who_short(); else args = ._who_is(@line); } if (!args) return "Ack, nobody to list?"; .tell($code_lib.generate_listing(@args)); . protected quit_cmd arg [args]; return 'disconnect; . protected inventory_cmd arg [args]; var i; if (.contents()) { .tell("Carrying:"); for i in (.contents()) .tell(" " + i.namef()); } else { .tell("You are empty-handed."); } . public match_env_nice arg name, [syntax]; var obj, args, line; // calls .match_environment() returns nice errors. as well as stopping if it // breaks. No returns neccessary syntax = [@syntax, ""][1]; catch any { obj = .match_environment(name); } with handler { switch (error()) { case ~ambig: args = traceback()[1][3]; line = "\"" + args[args.length()] + "\" can match any of: "; line = line + $list.map_to_english(args[1], 'namef); (> .tell_error(syntax, line) <); case ~objnf: line = "Nothing found by the name \"" + traceback()[1][3] + "\"."; (> .tell_error(syntax, line) <); default: line = traceback()[1][2]; (> .tell_error(syntax, line) <); } } return obj; . public linelen return linelen || 79; . public idle_seconds return time() - last_command_at; . public title return title || ""; . public action // different from activity, returns a more accurate second to second action if (.connected()) return action || ""; else return "(asleep)"; . protected title_cmd arg cmdstr, com, str; catch any { .set_title(str); .tell("Title Set as: \"" + str + "\""); } with handler { $parse_lib.tell_error(traceback()[1][2]); } . protected commands_cmd arg cmdstr, cmd, args; var s, full, o, opt, opts, lcmds, rcmds, len, obj, shorts, m, c, local, remote, short, all; s = cmd + " [options] <object>"; opts = [["f?ull"], ["a?ll"], ["l?ocal"], ["r?emote"], ["s?hortcuts"]]; args = $parse_lib.getopt(args, opts); o = args[2]; local = remote = short = 1; if (opt = "f?ull" in o.slice(1)) full = o[opt][3]; if (opt = "a?ll" in o.slice(1)) all = o[opt][3]; if (opt = "r?emote" in o.slice(1)) remote = o[opt][3]; if (opt = "s?hortcuts" in o.slice(1)) short = o[opt][3]; if (opt = "l?ocal" in o.slice(1)) local = o[opt][3]; args = args[1].to_string(); if (!args && !all) { (| .tell_error(cmd + " [options] <object>") |); return "! Defaults: -f?ull -a?ll +l?ocal +r?emote +s?hortcuts"; } else { args = args || "me"; obj = .match_env_nice(args); } lcmds = rcmds = #[]; shorts = []; if (all) { if (local) lcmds = obj.all_local_commands(); if (remote) rcmds = obj.all_remote_commands(); if (short) shorts = obj.all_shortcuts(); } else { if (local) { c = obj.local_commands(); if (c) lcmds = #[[obj, c]]; } if (remote) { c = obj.remote_commands(); if (c) rcmds = #[[obj, c]]; } if (short) shorts = obj.shortcuts().to_list(); } if (full) { m = "long"; len = .linelen() / 3 * 2; } else { m = "short"; len = .linelen(); } o = []; if (lcmds) o = o + $command_lib.(tosym("format_commands_" + m))(lcmds, "Local", len); if (rcmds) o = o + $command_lib.(tosym("format_commands_" + m))(rcmds, "Remote", len); if (shorts) { o = o + ["Shortcuts:"]; for c in (shorts) o = o + [" " + $command_lib.unparse_shortcut(c)]; } return o || "No commands defined on " + obj.namef('ref); . public pagelen return pagelen || 24; . public set_pagelen arg len; if (!.is_writable_by(sender())) throw(~perm, "Sender not an owner."); if (type(len) != 'integer) throw(~type, "pagelength must be an integer"); pagelen = len; . public set_linelen arg len; if (!.is_writable_by(sender())) throw(~perm, "Sender not an owner."); if (type(len) != 'integer) throw(~type, "Linelength must be an integer"); linelen = len; . protected name_aliases_cmd arg cmdstr, com, obj; if (!obj.is($named)) return obj.name() + " is not descended from $named!"; return "Name aliases for " + obj.name() + ": " + obj.name_aliases().to_english("none"); . public activity var idle; // different from action, returns a broader version of your doings if (!.connected()) return "asleep"; if (activity) return activity; idle = .idle_seconds(); if (idle < 180) return ""; if (idle < 300) return "daydreaming"; if (idle < 900) return "zoned"; else return "long gone"; . protected add_name_alias_cmd arg cmdstr, com, args; var syn, obj, alias; syn = com + " <alias> [to] <object>"; args = args.explode_quoted(); alias = (| args[1] |); if (!alias) return .tell_error("", syn); if (args.length() > 1 && args[2] == "to") args = args.delete(2); obj = .match_env_nice([@args, "me", "me"][2]); if (!obj) return "You must specify an object to add an alias to."; if (!obj.is($named)) return obj.name() + " is not a descendant of $named!"; if (alias in .name_aliases()) return "You already have the name alias " + toliteral(alias); catch any { (> obj.add_name_alias(alias) <); } with handler { .tell_error(traceback()[1][2], syn); } return "Name Alias " + toliteral(alias) + " added to " + obj.name() + " (" + obj.name_aliases().to_english() + ")."; . protected del_name_alias_cmd arg cmdstr, com, args; var syn, obj, alias; syn = com + " <alias> [from] <object>"; args = args.explode_quoted(); alias = (| args[1] |); if (!alias) return .tell_error("", syn); if (args.length() > 1 && args[2] == "from") args = args.delete(2); obj = .match_env_nice([@args, "me", "me"][2]); if (!obj) return "You must specify an object to delete an alias from."; if (!obj.is($named)) return obj.name() + " is not a descendant of $named!"; if (!(alias in .name_aliases())) return obj.name() + " does not have the name alias " + toliteral(alias); catch any { (> obj.del_name_alias(alias) <); } with handler { .tell_error(traceback()[1][2], syn); } return "Name Alias " + toliteral(alias) + " deleted from " + obj.name() + (obj.name_aliases() ? " (" + obj.name_aliases().to_english() + ")" | ""); . public home arg [args]; return (| .get_local_setting("home", $thing) |) || $body_cave; . protected rename_cmd arg cmdstr, cmd, args; var syn, object, name, aliases, article; syn = cmd + " <object> [to] <newname> [flags]"; args = args.explode_quoted(); if (!args || args.length() == 1) return .tell_error("", syn); object = .match_env_nice(args[1]); if (args[2] == "to") args = args.delete(2); if (args.length() == 1) return .tell_error("", syn); catch any { name = $code_lib.parse_name(args.subrange(2).to_string()); aliases = name[2]; article = name[1][2]; name = name[1][1]; if (name[1] == "$") { if (object.is($user) && !.is($admin)) return "User objnames can only be changed by administrators."; name = tosym(name.subrange(2)); (> object.set_objname(name) <); return "Sucessfully changed object name to " + object.objname() + "."; } else { if (!object.is($named)) return .tell_error("Object \"" + object.objname() + "\" is not descended from $named.", syn); (> object.set_name(name, article) <); if (aliases) (> object.set_name_aliases(@aliases) <); return "Sucessfully changed " + (object == this() ? "your " | "") + "name [" + tostr(article) + "] to \"" + object.name() + "\"" + (object.name_aliases() ? " (" + object.name_aliases().to_english() + ")" | ""); } } with handler { .tell_traceback(traceback()); .tell_error(traceback()[1][2], syn); } . protected audit_cmd arg cmdstr, cmd, args; var owner, obj, col, str, out, total, line, syntax, loc, size, full, s, o; o = $parse_lib.getopt(args, [["f?ull"]]); args = o[1].to_string(); full = (| "f?ull" in o[2].slice(1) |); if (full) full = o[2][full][3]; owner = (| .match_environment(args) |); if (!owner) { owner = (| $user_db.find(args) |); if (!owner) return "Unable to find \"" + args + "\"."; } if (!owner.owned()) return owner.name() + " does not own anything."; if (full) { col = .linelen() / 2; out = [("Objects owned by " + owner.namef('ref) + ":").pad(col) + "bytes".pad(-10) + " Location"]; for obj in (owner.owned()) { if (!valid(obj)) { .tell(" ** invalid object (" + toliteral(obj) + ") **"); continue; } line = (" " + obj.namef('xref)).pad(col); s = obj.size(); size = s.to_english(); line = line + size.pad(-(size.length() > 10 ? size.length() | 10)) + " "; loc = obj.has_ancestor($located) ? "[" + obj.location().name() + "]" | ""; out = out + [(line + loc).pad(.linelen())]; total = total + s; } } else { if (owner != this() && !.is($admin)) return "Only admins can get quota usage information from other users."; out = ["Quota information on " + owner.namef('ref) + ":"]; for obj in (owner.owned()) { if (valid(obj)) total = total + obj.size(); } } if (owner == this() || .is($admin)) { out = out + ["Total usage: " + $integer.to_english(total) + " bytes"]; size = owner.get_quota(); line = "Total quota: " + $integer.to_english(size) + " bytes"; out = out + [line, "Remaining: " + $integer.to_english(size - total) + " bytes"]; } if (!owner.quota_valid()) { if (owner == this()) out = out + ["*** You are over quota! ***"]; else out = out + ["*** " + owner.name() + " is over quota! ***"]; } return out; . protected login_notify arg connection; // Login Notifications -- called by .login() .tell(("*** Login successful (" + connection.address() + ") ***").center(.linelen())); .tell(("** Last connection at " + $time.date(abs(.connected_at())) + " **").center(.linelen())); .look_cmd(); .tell(""); if (.last_received_on() > (.subscribed())[this()]) .tell("** You have new mail (use `@help mail` to learn about mail) **"); .subscribe_cmd("", "", "-new"); . protected news_cmd arg [args]; var line, x, mail, m, base, length, out; mail = $mail_list_news.recent_mail(); base = mail[1]; mail = mail[2]; length = mail.length(); .new_list($mail_list_news); out = [$motd.server_name() + " news:", ""]; for x in [1 .. length] { m = mail[x]; out = out + [(m.has_read(this()) ? " " | "NEW => ") + tostr(x + base).pad(-3) + ") " + m.subject()]; } return out + ["", "Use \"@read #\", where # is the news item number, such as \"@read 1\". All news items can be found on mail list *news.", "---"]; . protected add_command_alias_cmd arg cmdstr, com, input; var syn, alias, actual, tmpalias, tmpactual, num; if (sender() != this()) throw(~perm, "Sender is not this"); input = input.explode("\""); // hell, i'll be nice and check for a few possibilities: syn = com + " \"<alias>\" [to] \"<actual command>\""; if (input.length() < 2) $parse_lib.tell_error("Not enough arguments (enclose each alias in quotes)", syn); if (input.length() > 3) $parse_lib.tell_error("Too many arguments (enclose each alias in quotes)", syn); // sort and get the alias and actual if (input.length() == 3) input = input.delete(2); alias = input[1]; actual = input[2]; // make sure the %foo's match up tmpalias = alias; tmpactual = actual; while ("%" in tmpalias) { num = tmpalias[("%" in tmpalias) + 1]; if (!toint(num)) $parse_lib.tell_error("referece cards must be integers", syn); num = "%" + num; if (!(num in tmpactual)) $parse_lib.tell_error("reference cards to not match up", syn); tmpalias = tmpalias.replace(num, ""); tmpactual = tmpactual.replace(num, ""); } if ("%" in tmpactual) $parse_lib.tell_error("reference cards do not match up", syn); .add_command_alias(alias, actual); .tell("New command alias \"" + alias + "\" => \"" + actual + "\" added."); . protected del_command_alias_cmd arg cmdstr, com, template; if (sender() != this()) throw(~perm, "Sender is not this"); template = (template.explode("\""))[1]; catch ~aliasnf { .del_command_alias(template); } with handler { $parse_lib.tell_error("No command alias is found matching the template \"" + template + "\"."); } .tell("Command alias \"" + template + "\" deleted."); . protected command_aliases_cmd arg cmdstr, com, what; var aliases, a, line; if (!what) what = this(); else what = .match_env_nice(what); if (what != this() && !what.is_writable_by(this())) $parse_lib.tell_error("You are not allowed to read the command aliases on " + what.namef()); .tell("--- Command aliases on " + what.namef('xref) + ":"); aliases = what.command_aliases(); if (aliases) { for a in (aliases) { line = " " + ("\"" + a[1] + "\"").pad((.linelen() - 10) / 2); .tell(line + " => \"" + a[2] + "\""); } } else { .tell(" <none>"); } .tell("---"); . public _tell arg what, [args]; var line, conn, filter; if (sender() != this()) throw(~perm, "Sender is not this."); if (type(what) == 'frob) what = $ctext_filter.filter(what, #[['formatter, $cml2_telnet_format]]); if (type(what) == 'list) { for line in (what) ._tell(line); } else { for conn in (connections) (| conn.write(what) |); } . public add_filter arg filter, [position]; if (!sender().has_ancestor($filters) && !.is_writable_by(sender())) throw(~perms, "%O does not have permission to remove filters.", sender()); // do this in three steps, first make sure the posistion is valid, // then check for it already, then figure its insert position. position = [@position, 'first][1]; if (!(position in ['last, 'first])) throw(~type, "Posistion types must be one of: 'last, 'first."); // does it exist? If so remove it. if (filter in filters) filters = filters.setremove(filter); // figure position if (position == 'last) position = filters.length() + 1; else if (position == 'first) position = 1; filters = filters.insert(position, filter); . public del_filter arg filter; if (!sender().has_ancestor($filters) && !.is_writable_by(sender())) throw(~perms, "%O does not have permission to remove filters.", sender()); if (filters) { filters = filters.setremove(filter); return; } else { throw(~nofilters, "You do not have any tell filters."); } . protected wrap_cmd arg cmdstr, com, how; var filters; if (!(how in ["on", "off"])) return .tell("! You can either turn line wrapping `on' or `off'"); filters = .filters(); if (how == "on") { if (filters && $wrap_filter in filters) return .tell("! You already have line wrapping on.."); .add_filter($wrap_filter); return .tell("Line wrapping turned on."); } else { if (filters && !($wrap_filter in filters)) return .tell("! You dont have line wrapping turned on."); .del_filter($wrap_filter); return .tell("Line wrapping turned off."); } . public filters .perms(sender()); return filters; . public tell_traceback arg traceback, [args]; var tt, name, eargs, error, str; // tt = tell_traceback || ['verbose, 0, "! "]; str = [@args, ""][1]; eargs = [@args, 0, 0][2]; error = [@args, 0, 0, 0][3]; tt = ['verbose, -1, "! "]; switch (tt[1]) { case 'verbose: traceback = $parse_lib.traceback(traceback, tt[2], tt[3], error); if (args) name = (| $list.to_english($list.map(args, 'namef, 'ref)) |); if (!name) name = "Object"; .tell(traceback[1].replace("%O", name)); .tell(traceback.subrange(2)); default: .tell("! Internal error processing \"" + str + "\", contact an administrator."); } . public set_tell_traceback arg which, [lines]; .perms(sender(), 'manager); if (!(which in ['verbose, 'brief, 'none])) throw(~type, "Which style must either be 'verbose, 'brief, or 'none."); if (lines && type(lines[1]) != 'integer) throw(~type, "You must specify the max lines as an integer."); if (!lines) lines = 0; else lines = lines[1]; tell_traceback = [which, lines]; . public namef arg [args]; if (!args) args = [['name]]; // first check for shortcuts, if so re-call this method correctly. if (args[1] == 'nactivity) { if (.activity()) args = [['name], " (", ['activity], ")"] + args.subrange(2); else args = [['name]] + args.subrange(2); } if (args[1] == 'titled) { if (.title()) args = [['name], ", ", ['title]] + args.subrange(2); else args = [['name]] + args.subrange(2); } return pass(@args); . protected password_cmd arg cmdstr, com, [args]; var syn; syn = com + " <old password> <new password>"; args = args[1].explode(); if (args.length() < 2 || args.length() > 2) .tell_error(syn, "Specify old and new password (passwords cannot contain spaces)."); if (!.check_password(args[1])) .tell_error(syn, "Sorry."); catch any { .set_password(args[2]); } with handler { .tell_error(syn, traceback()[1][2]); } .tell("Password changed."); . public set_title arg str; .perms(sender(), 'manager); if (str.length() > 30) throw(~type, "Titles must be under 30 characters."); title = str; . public match_context arg str; return context[str]; . public context return context; . public match_environment arg str; var match, gend; if (!str && match = (| context['last] |)) { if (!valid(match)) context = context.del('last); else return match; } if (match = (| (.remembered())[str] |)) { if (!valid(match)) .del_remembered(str); else return match; } match = (> pass(str) <); if (match.has_ancestor($thing)) { gend = (| match.gender() |); if (gend) context = context.add(gend.pronoun('po), match); } context = context.add('last, match); return match; . public non_terminated_tell arg text; var conn; if ((| .setting("terminated-tell") |)) { for conn in (.connections()) conn.write(text, 'non_terminated); } else { .tell(text); } . public set_name arg new_name, [ignore]; var old_name, part, sname; (> .perms(sender(), 'manager) <); // so it doesnt bomb on .set_objname if ((> $user_db.valid_name(new_name) <)) old_name = .name(); catch any { (> pass(new_name, 'prop) <); if (!(| $user_db.key_changed(old_name, new_name) |)) $user_db.insert(new_name, this()); if (old_name != new_name) { sname = $string.strip(new_name, $user_db.stripped_characters()); (> .set_objname(tosym("user_" + sname)) <); } } with handler { (| pass(old_name, 'prop) |); rethrow(error()); } . public find_object_nice arg str, [args]; var match; catch any { match = .find_object(str, @args); } with handler { .tell("! " + traceback()[1][2]); throw(~stop, "", 'no_traceback); } return match; . public find_object arg str, [args]; var trace, match; // comprehensive matching method. // args define what to match. if (!args) args = ['environment]; while (args) { switch (args[1]) { case 'environment: match = (| .match_environment(str) |); case 'user: match = (| $user_db.find(str) |); case 'grasp: match = (| $object_lib.to_dbref(str) |); } if (match) return match; args = args.delete(1); } throw(~objnf, "No object found by the reference \"" + str + "\"."); . protected age_cmd arg cmdstr, com, obj; var time, gender; .debug(obj); time = obj.created_on(); if (obj.is($gendered)) gender = obj.gender().pronoun('psc); else gender = "It"; .tell(obj.namef() + " was created on " + $time.ldate(time)); .tell(gender + " is " + $time.elapsed(time() - time, 'long) + " old."); if (obj.is($user)) .tell(gender + " has logged " + $time.elapsed(obj.connected_seconds(), 'long) + " online."); . protected spawn_cmd arg cmdstr, com, args; var match, syn, new, name, parent, line, set; syn = "If object cannot have a name, <new name> will be the objname."; syn = [com + " <parent> <new name>", syn]; args = args.explode_quoted(); parent = .match_env_nice(args[1]); if (args.length() > 1 && args[2] == "named") args = args.delete(2); catch any { if (args.length() > 1) name = (> $code_lib.parse_name(args.subrange(2).to_string()) <); if (!parent.is($thing) && !.is($programmer)) return "Only programmers are allowed to spawn non VR objects."; if (!parent.has_flag('fertile)) return "Spawn failed: " + parent.namef('xref) + " is not fertile!"; new = (> parent.spawn() <); .tell("Spawned new object " + new.namef('xref) + " from " + parent.namef('xref) + "."); if (new.is($located)) new.move_to(this()); if (name && name[1][1][1] == "$") { name = tosym(name[1][1].subrange(2)); (> new.set_objname(name) <); return "Object name changed to: " + new.objname(); } else if (name) { if (!new.is($named)) return new.objname() + " is not descended from $named, name " + toliteral(name[1][1]) + " not added."; (> new.set_name(@name[1]) <); if (name[2]) (> new.set_name_aliases(@name[2]) <); return "Name set as: \"" + new.name() + "\"" + (new.name_aliases() ? " (" + new.name_aliases().to_english() + ")" | ""); } } with handler { (| .tell_error(@syn, traceback()[1][2]) |); catch any { line = new.objname(); if (!valid(new.destroy())) .tell("! Sucessfully destroyed new object " + line + "."); } } . protected description_cmd arg cmdstr, cmd, str; var args, obj, syn, desc, long; syn = cmd + " [<what> as <description>|<what>]"; args = $string.match_template("* as *", str); if (!args) { args = str.explode(); if (!args) .tell_error(syn); obj = args.to_string(); desc = .read(); } else { obj = args[1]; desc = args[3]; } if (!desc) { .tell("No description given, aborting..."); return; } else if (desc == 'aborted) { return; } obj = .match_env_nice(obj); catch any { obj.set_prose(desc); .tell("Description for " + obj.namef('ref) + " set."); } with handler { .tell(traceback()[1][2]); } . protected status_cmd arg cmdstr, com, [args]; var line, s, x; s = $sys.status(); for x in [1 .. s.length()] { if (s[x] < 0) s = s.replace(x, "(unknown)"); } .tell("--- " + $motd.server_name() + " status report ---"); if ($sys.dirty()) .tell("System is: dirty, will do normal backup."); else .tell("System is: clean, will skip backup."); .tell("System lag: " + $lag_watcher.lag()); .tell("Next dbref: " + toliteral($sys.next_dbref())); .tell("Driver: " + $sys.server_info('driver_version, 'long)); .tell("Core: " + $sys.server_info('core_version, 'long)); .tell("Started: " + $time.to_english(time() - $sys.server_info('startup_time)) + " ago"); .tell("Backup: last: " + $time.to_english(time() - s[20]) + " ago"); .tell(" next: " + $time.to_english(s[21] - time()) + " from now"); .tell(" interval: " + $time.to_english(s[19])); .tell("Page: " + tostr(s[9]) + " reclaims"); .tell(" " + tostr(s[10]) + " faults"); .tell("Signals: " + tostr(s[16])); .tell("Context switches: " + tostr(s[17]) + " voluntary"); .tell(" " + tostr(s[18]) + " involuntary"); . public del_command_alias arg alias; (> .perms(sender()) <); (> pass(alias) <); if (!.command_aliases() && $command_aliases_parser in .parsers()) { .tell("Removing $command_aliases_parser from your list of parsers."); .del_parser($command_aliases_parser); } . public add_command_alias arg alias, actual; (> .perms(sender()) <); (> pass(alias, actual) <); if (.command_aliases() && !($command_aliases_parser in .parsers())) { .tell("Adding $command_aliases_parser to your list of parsers.."); .add_parser($command_aliases_parser, 'first); } . public logout_connection arg connection; if (sender() != this() || definer() != caller()) throw(~perm, "Invalid access to private method."); .tell($string.center("* * * " + $integer.n_to_nth(.connections().length() + 1) + " Logout sucessful * * *", .linelen())); . protected rehash_cmd arg cmdstr, cmd; .tell("Rehashing your command caches..."); pause(); .rehash_caches(); . public description arg flags; var c, contents, ctext, pronoun, lines, p, br; pronoun = .gender().pronoun('psc); lines = [pronoun + " is " + (.activity() || "awake") + "."]; if (contents = .contents()) { lines = lines + [pronoun + " is holding:"]; for c in (contents) lines = lines + [" " + c.namef()]; } else { lines = [lines, pronoun + " is holding nothing."]; } return (> pass(flags) <) + lines; . protected _who_at_place arg str; var place, thing, who, args; // This should actually be done with a global place dictionary and // a local place dictionary for each user. place = $place.match_descendants(str); if (!place) { .tell("I do not know where \"" + str + "\" is."); return 0; } who = []; for thing in (place.contents()) { if (thing.has_ancestor($user)) who = [@who, thing]; } if (!who) { .tell("Nobody is in " + place.namef() + "."); return 0; } args = [who, "Users in " + place.namef()]; args = [@args, [['namef, 'titled], ['time_poll]]]; args = [@args, ["Name", "Times (idle)"], [1, 1]]; return args; . protected _who_is arg [args]; var person, p, who; who = []; args = $string.explode_english_list(@args) || []; for p in (args) { catch any { person = $user_db.find(p); } with handler { switch (error()) { case ~ambig: .tell("The name \"" + p + "\" can match any of: " + $list.to_english($list.map(traceback()[1][3], 'namef)) + "."); default: .tell("I don't know who \"" + p + "\" is."); } continue; } who = [@who, person]; } if (!who) return 0; return [who, who.length() == 1 ? "User" | "Users"]; . protected _who_programmers arg args, all; var out, progs, p, x, t; progs = []; if (args && !all) { for p in (args) { x = $user_db.find(p); if (!x) .tell("I don't know who \"" + p + "\" is."); else progs = [@progs, x]; } t = "Programmer" + progs.length() == 1 ? "" | "s"; } else if (all) { t = "All Programmers"; progs = $programmer.descendants(); progs = progs.setremove($admin); } else { t = "Connected Programmers"; for p in ($user_db.connected()) { if (p.has_ancestor($programmer)) progs = [@progs, p]; } } if (!progs) return 0; return [progs, t]; . protected _who_admins arg args, all; var out, admins, a, x, t; admins = []; if (args && !all) { for a in (args) { x = $user_db.find(a); if (!x) .tell("I don't know who \"" + a + "\" is."); else admins = [@admins, x]; } t = "Admin" + admins.length() == 1 ? "" | "s"; } else if (all) { t = "All Admins"; admins = $sys.admins(); } else { t = "Connected Admins"; for a in ($user_db.connected()) { if (a.has_ancestor($admin)) admins = [@admins, a]; } } if (!admins) return 0; return [admins, t]; . protected _who_short var user, tmp, who, namestr, total; who = []; total = $user_db.connected().length(); .tell("Currently connected users (total: " + tostr(total) + (total == 1 ? " person" | " people") + "):"); for user in ($user_db.connected()) { namestr = " " + user.namef() + " (" + $time.elapsed(user.connected_at()) + " " + $time.dhms(user.idle_seconds()) + ")"; who = [@who, namestr]; if (tmp < namestr.length() + 2) tmp = namestr.length() + 2; } .tell($list.columnize(who, .linelen() / (tmp + 1), " ", .linelen())); . protected remember_cmd arg cmdstr, cmd, what, as, str; .add_remembered(what, str); return "Remembering " + what.namef('xref) + " as \"" + str + "\"."; . protected forget_place arg place; if (type(place) != 'dbref) throw(~type, "Place must be submitted as an object."); remembered_places = remembered_places.setremove(place); . protected remembered_cmd arg cmdstr, cmd, args; var item, out; if (!.remembered()) return .tell("You do not remember anything."); out = []; for item in (.remembered()) out = out + [" " + item[1] + " is " + item[2].namef('xref)]; return ["Remembered Items:"] + out.lcolumnize(); . protected forget_cmd arg cmdstr, cmd, str; var what; what = (| remembered[str] |); if (!what) return "You don't remember what \"" + str + "\" is..."; .del_remembered(str); return "Forgetting " + what.namef('xref) + " as \"" + str + "\"."; . public idle_time arg [args]; var idle; args = [@args, 'dhms][1]; idle = .idle_seconds(); if (connected_at < 0 || idle < 30) return ""; switch (args) { case 'dhms: return $time.dhms(idle, 'long); case 'elapsed: return $time.elapsed(idle); case 'seconds: return idle; } . public tell_error arg syntax, [problem]; var problem, line, sprefix, prefix, length; // arg 1 == syntax // arg 2 == problem lines length = .linelen(); if (syntax) .tell("=> Syntax: `" + syntax + "`"); if (problem) { for line in (problem) { if (type(line) == 'string) line = line.wrap_lines(length, "! ", 1); .tell(line); } } throw(~stop, "=> Syntax: `" + syntax + "`", 'no_traceback); . protected whereis_cmd arg cmdstr, cmd, who; var user, u; who = who && who.explode_english_list() || []; if (who && who[1] == "is") who = who.delete(1); if (!who) $parse_lib.tell_error("You must specify somebody."); for user in [1 .. who.length()] { u = (| $user_db.find(who[user]) |); if (!u) { .tell("I don't know who \"" + who[user] + "\" is."); who = who.replace(user, 0); } else { who = who.replace(user, u); } } for user in (who) { if (user) .tell(user.namef('nactivity) + " is in " + user.location().name('def)); } . public connected_time arg [args]; args = [@args, 'dhms][1]; if (connected_at < 0) return "Last on: " + $time.ctime(abs(connected_at)); switch (args) { case 'dhms: return $time.dhms(time() - connected_at, 'long); case 'elapsed: return $time.elapsed(time() - connected_at); case 'seconds: return time() - connected_at; } . public terminated_tell return (| settings[$user]["terminated-tell"] |) || "text/plain"; . public connection_going_away arg addr, port; var con, line; catch any { (> .perms(caller(), $connection) <); for con in (connections) { if (!valid(con)) connections = connections.setremove(con); } con = sender() in connections; connections = connections.setremove(sender()); if (!connections) .logout(sender()); else .logout_connection(sender()); line = "DISCONNECT " + tostr(con) + " ("; line = line + (.parents())[1].objname() + "): "; line = line + .objname() + " <" + addr + ">"; (| $sys.log(line) |); } with handler { $sys.log($parse_lib.traceback(traceback())); } . public read arg [args]; var text, output, head, tail; if (!.connections()) return 'not_connected; if ((.connections())[1].is_reading_block()) return 'engaged; head = [@args, "Now receiving input, enter \".\" to finish or \"@abort\" to abort."][1]; tail = [@args, "** Aborted **; Text thrown away.", "** Aborted **; Text thrown away."][2]; if (head) .tell(head); output = (.connections())[1].start_reading_block('multiple); if (output == 'aborted && tail) .tell(tail); return output; . public read_line arg [args]; var line, abort_msg, head; if (!.connections()) return 'not_connected; if ((.connections())[1].is_reading_block()) return 'engaged; head = [@args, ""][1]; abort_msg = [@args, "** Aborted **", "** Aborted **"][2]; if (head) .tell(head); line = (.connections())[1].start_reading_block('one); if (line == 'aborted && abort_msg) .tell(abort_msg); return line[1]; . public prompt arg prompt, [abort_msg]; .non_terminated_tell(prompt); return (> .read_line("", @abort_msg) <); . protected ways_cmd arg cmdstr, cmd; var exits, e, line, out; exits = .location().exits_visible_to(this()); if (!exits) return "There are no visible exits from this room."; // come up with some settings to configure how to display exits // for now they can deal with the following out = ["Visible exits from " + .location().name() + ":"]; for e in (exits) out = out + [" " + e.name() + (e.name_aliases() ? " (" + e.name_aliases().to_english() + ")" | "") + " to " + e.dest().name()]; return out + ["---"]; . public content_type return (| settings_data[$user]["content-type"] |) || "text/plain"; . public set_objname: disallow_overrides arg new_objname; if (caller() != $user && !(sender() in $sys.system())) throw(~perm, "User objnames can only be changed by $user."); (> pass(new_objname) <); . protected context_cmd arg [args]; var out; out = "Last thing: " + ((| context['last].name() |) || "(nothing)"); out = [out, "Last it: " + ((| context["it"].name() |) || "(nothing)")]; out = [out, "Last her: " + ((| context["her"].name() |) || "(nothing)")]; out = [out, "Last him: " + ((| context["him"].name() |) || "(nothing)")]; return out; . public del_channel arg channel; if (sender() != this()) (> .perms(sender(), 'system) <); if (!channels) return; channels = channels.del(channel); if (!channels) channels = 0; . public add_channel arg channel, [value]; if (sender() != this()) (> .perms(sender(), 'system) <); if (!channels) channels = #[]; if (!value) value = 1; channels = channels.add(channel, value); . public listens_to_channel arg channel, [args]; if (sender() != this()) (> .perms(sender(), 'system) <); if (!channels) return 1; if (args && channel == 'login && (| type(channels['login]) == 'list |)) return args[1] in channels['login]; return channel in channels.keys(); . protected look_cmd arg [args]; .ptell(.location().get_description(), #[['type, 'description], ['dtype, 'location], ['object, .location()]]); . public walk_path arg [path]; var p, exit; for p in (path) { // we need to go through the command parser, because it can // see all of the exits. exit = $command_parser.parse(this(), p, $null_parser); if (exit == 'failed) throw(~invpath, "No exit " + toliteral(p) + " from " + .location().name()); exit[1].invoke(#[['nofork, 1], ['prose, 0], ['extra, 0]]); pause(); } .look_cmd(); . public set_content_type arg definer, name, value, [args]; var sets; (> .set_local_setting(definer, name, value, @args) <); if (value == "text/html") evaluator = $html_formatter; else evaluator = $format_evaluator; . public check_content_type arg definer, value, [args]; var sets; if (!(value in ["text/plain", "text/html"])) throw(~check, "Content-type must be either \"text/plain\" or \"text/html\"."); return value; . public evaluator return evaluator; . public check_experienced arg definer, value, [args]; // called by the settings system if (value in ["", "y", "ye", "yes"]) return "yes"; else return ""; . protected get_cmd arg cmdstr, cmd, what; var ol, l; if (what.location() == sender()) { return "You already have " + what.name('def) + "."; } else if (what == this()) { return "Ewww, its all twisty."; } else { catch any { ol = what.location(); l = .location(); (> what.move_to(this()) <); if (l != ol) (| l.announce(.namef() + " takes " + what.namef() + ".", this(), what) |); (| l.announce(.namef() + " takes " + what.namef() + ".", this(), what) |); return "You take " + what.namef() + "."; } with handler { if (error() == ~locked) return "You are unable to " + cmd + " " + what.name() + "!"; else return traceback()[1][2]; } } . protected drop_cmd arg cmdstr, cmd, what; if (!(what in .contents())) { return "You don't have " + what.name('def) + "."; } else { catch any { (> what.move_to(.location()) <); .tell("You drop " + what.namef() + "."); (| .location().announce(.namef() + " drops " + what.namef() + ".", this(), what) |); } with handler { return traceback()[1][2]; } } . public announce arg [args]; return .location().announce(@args); . protected take_from_cmd arg cmdstr, cmd, what, p, where; var c, obj, l, wl; if (where == this()) return "You already have " + what.name() + "."; for c in (where.contents()) { if (c.match_name(what)) obj = c; } if (!obj) return .name() + " does not have " + what; if (obj == this() || obj == where) return "Ewww, its all twisty."; catch any { l = .location(); wl = where.location(); (> obj.move_to(this()) <); if (l != wl) wl.announce(.name() + " " + cmd + "s " + obj.name() + " " + p + " " + where.name(), this()); l.announce(.name() + " " + cmd + "s " + obj.name() + " " + p + " " + where.name(), this()); return "You " + cmd + " " + obj.name() + " " + where + " " + where.name() + "."; } with handler { switch (error()) { case ~locked: if (where.is($user)) where.tell(.namef() + " tried to take " + obj.name() + " from you."); return obj.name() + " is locked to " + obj.lock().lock_name('thing) + "."; default: return traceback()[1][2]; } } . public set_activity arg str; (> .perms(sender()) <); activity = str; . public is_tellable_by arg caller, sender; if (!(caller in [$user, $programmer, $admin, $mail_ui, $help_ui, $messages_ui, $settings_ui]) && sender != this()) return 0; . protected go_cmd arg cmdstr, cmd, path; path = path.explode_quoted(); .walk_path(@path); . public name arg [args]; if (activity) return (> pass(@args) <) + " (" + activity + ")"; else return (> pass(@args) <); . public ptell arg what, flags; if (!.is_tellable_by(caller(), sender())) throw(~perm, "Only allowed objects may call protected tell."); switch ((| flags['type] |) || 'interaction) { case 'channel: if (!.listens_to_channel(@args.subrange(2))) return; } ._tell(what); . public connection_starting arg addr, port; var line, c; (> .perms(caller(), $connection) <); for c in (connections) { if (!valid(c)) connections = connections.setremove(c); } connections = connections.setadd(sender()); if (connections.length() == 1) (| .login(sender()) |); else (| .login_again(sender()) |); line = "CONNECT " + tostr(sender() in connections) + " ("; line = line + (.parents())[1].objname() + "): "; line = line + .objname() + " <" + sender().address() + "> "; (| $sys.log(line) |); . public purge_caches if (!.connected()) return (> pass() <); . protected reset_parsers parsers = [$command_parser]; . public connected_seconds return connected_seconds; . protected add_trustee_cmd arg cmdstr, cmd, args; var syn, obj, trustee; args = args.replace(" to ", " ").explode(); if (!args || args.length() != 2) .tell_error(cmd + " <trustee> [to] <object>"); trustee = .match_env_nice(args[1]); obj = .match_env_nice(args[2]); catch any { obj.add_trusted(trustee); return ["Sucessfully added trustee " + trustee.namef('xref) + " to " + obj.namef('xref), "New trusted list: " + obj.trusted('literal).compress().map('namef, 'xref).to_english() + "."]; } with handler { .tell(traceback()[1][2]); } . protected del_trustee_cmd arg cmdstr, cmd, args; var syn, obj, trustee; args = args.replace(" from ", " ").explode(); if (!args || args.length() != 2) .tell_error(cmd + " <trustee> [from] <object>"); trustee = .match_env_nice(args[1]); obj = .match_env_nice(args[2]); catch any { obj.del_trusted(trustee); return ["Sucessfully removed trustee " + trustee.namef('xref) + " from " + obj.namef('xref), "New trusted list: " + obj.trusted('literal).compress().map('namef, 'xref).to_english() + "."]; } with handler { .tell(traceback()[1][2]); } . protected add_writer_cmd arg cmdstr, cmd, args; var syn, obj, writer; args = args.replace(" to ", " ").explode(); if (!args || args.length() != 2) .tell_error(cmd + " <writer> [to] <object>"); writer = .match_env_nice(args[1]); obj = .match_env_nice(args[2]); catch any { obj.add_writer(writer); return ["Sucessfully added writer " + writer.namef('xref) + " to " + obj.namef('xref), "New writers list: " + obj.writers('literal).compress().map('namef, 'xref).to_english() + "."]; } with handler { .tell(traceback()[1][2]); } . protected del_writer_cmd arg cmdstr, cmd, args; var syn, obj, writer; args = args.replace(" from ", " ").explode(); if (!args || args.length() != 2) .tell_error(cmd + " <writer> [from] <object>"); writer = .match_env_nice(args[1]); obj = .match_env_nice(args[2]); catch any { obj.del_writer(writer); return ["Sucessfully removed writer " + writer.namef('xref) + " from " + obj.namef('xref), "New writers list: " + obj.writers('literal).compress().map('namef, 'xref).to_english() + "."]; } with handler { .tell(traceback()[1][2]); } . protected writes_cmd arg cmdstr, cmd, args; var target, writes, obj, out, len; target = (| .match_environment(args) |); if (!target) { target = (| $user_db.find(args) |); if (!target) return "Unable to find \"" + args + "\"."; } writes = target.writes(); if (!writes) return target.namef('ref) + " is not in any object's writers list."; out = [target.namef('ref) + " is in the writers list for:"]; return out + $code_lib.generate_object_listing(writes, 'writers, 'literal); . protected managed_cmd arg cmdstr, cmd, args; var manager, managed, obj, out, len; manager = (| .match_environment(args) |); if (!manager) { manager = (| $user_db.find(args) |); if (!manager) return "Unable to find \"" + args + "\"."; } managed = manager.managed(); if (!managed) return manager.namef('ref) + " does not manage any objects."; out = [manager.namef('ref) + " manages:"]; len = .linelen() / 2; for obj in (managed) out = out + [" " + obj.namef('xref).pad(len) + " " + $object_lib.see_perms(obj, ["", ""])]; return out; . protected owned_cmd arg cmdstr, cmd, args; var target, owned, obj, line, name, out, len, mlen, llen; target = (| .match_environment(args) |); if (!target) { target = (| $user_db.find(args) |); if (!target) return "Unable to find \"" + args + "\"."; } owned = target.owned(); if (!owned) return target.namef('ref) + " does not own any objects list."; out = [target.namef('ref) + " owns:"]; return out + $code_lib.generate_object_listing(owned, 'owners); . protected add_remembered arg what, name; remembered = (remembered || #[]).add(name, what); . protected del_remembered arg name; remembered = (remembered || #[]).del(name); if (!remembered) clear_var('remembered); . public remembered return remembered || #[]; . parent $location parent $public object $place var $root child_index 147 var $root fertile 1 var $root inited 1 var $root objname 'place var $root created_on 796268969 var $root flags ['parameters, 'methods, 'code, 'fertile, 'core] var $gendered gender $gender_neuter var $described prose [] var $messaged verbs #[] var $named name ['uniq, "place", "the place"] var $named name_aliases [] var $place realm 0 var $place exits [] var $place coordinates 0 var $place darkness 0 var $public public ['readable] var $location contents [] var $command_cache shortcut_cache [] var $command_cache remote_cache 0 var $command_cache local_cache 0 var $has_settings defined_settings #[["public-home", #[['get, 'get_local_setting], ['set, 'set_local_setting], ['check, 'is_boolean], ['del, 'delete_local_setting], ['check_args, []], ['get_args, []], ['set_args, []], ['display, 'display_boolean_yes_no]]], ["realm", #[['get, 'realm], ['set, 'set_realm], ['check, 'check_realm], ['del, 'del_realm], ['check_args, []], ['get_args, []], ['set_args, []], ['display, 'display_setting_realm]]], ["darkness", #[['get, 'darkness], ['set, 'set_darkness], ['check, 'is_type], ['del, 'delete_local_setting], ['check_args, ['integer]], ['get_args, []], ['set_args, []]]]] root init_place exits = []; realm = $realm_of_creation.new(); coordinates = #[]; . root uninit_place var x; for x in (exits) (| x.place_destroyed() |); (| realm.place_destroyed(this()) |); for x in (.area()) (| x.place_destroyed(this()) |); (| $place_db.place_destroyed() |); . public environment return pass() + exits; . public description arg flags; return (> pass(flags) <) + ._desc_contents(flags); . public exits (| .perms(caller(), definer(), $command_parser) |) || (> .perms(sender()) <); // check a callers list or something, so that not any joe schmo can check // this list (limit to any core object...?) return exits; . public 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) <); . public _add_exit: disallow_overrides arg obj; // use .add_exit() .perms(sender(), 'this); exits = [@exits, obj]; . public _del_exit: disallow_overrides arg obj; // use .del_exit() .perms(sender(), 'this); exits = exits.setremove(obj); . public del_exit: disallow_overrides var exit; exit = sender(); .perms(caller(), $exit); (| ._del_exit(exit) |); (| ._del_coordinate(exit) |); (| ._del_coordinate(exit.dest()) |); . public _add_coordinate arg obj, coord1, coord2; .perms(sender(), 'this); // should only be called from inside this object. coordinates = coordinates.add(obj, [coord1, coord2]); . public _del_coordinate arg obj; .perms(sender(), 'this); // should only be called from inside this object. coordinates = coordinates.del(obj); . public did_connect if (.visibility() >= 0) .announce(sender().namef('titled) + " wakes up.", sender()); . public did_disconnect if (.visibility() >= 0) .announce(sender().namef('titled) + " falls asleep.", sender()); . public realm arg [args]; var tmp, r; return realm; . public announce arg str, [except]; var obj, part; if (type(str) == 'frob && class(str) == $message_frob && this() in str.parts()) { part = str.get_part(this()); str = str.del_entry(this()); str = str.add_entry("general", part); } for obj in (.contents()) { if (!(obj in except)) (| obj.tell(str) |); } . public 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(message.replace("%N", who.namef())); . public set_name arg new_name, [args]; var old_name; old_name = .name(); (> pass(new_name, @args) <); (| $place_db.room_changed_name(old_name) |); . public set_realm arg definer, name, value, [args]; (> .perms(sender(), 'this) <); realm = value; . public short_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; . public _desc_contents arg flags; var users, br, exclude, actor, objects, output, obj, line; // called by .description (> .perms(sender(), 'this) <); users = []; objects = []; actor = flags['actor]; exclude = flags['exclude]; for obj in (.contents()) { if (!(obj in exclude) && (| obj.is_obvious_to(actor) |)) { if (obj.has_ancestor($body)) users = [@users, obj.namef('nactivity)]; else objects = [@objects, obj.name()]; } } output = []; br = (<$ctext_format, ["br", #[], #[], [], 'do_br]>); if (users) { line = $list.to_english(users) + " "; line = line + (users.length() > 1 ? "are" | "is") + " here."; //output = [@output, br, line]; output = [@output, line]; } if (objects) { line = "You see "; line = line + $list.to_english(objects) + " here."; //output = [@output, br, line]; output = [@output, line]; } return output; . public exits_visible_to arg who; var obv, exit; obv = []; for exit in (.exits()) { if (exit.is_visible_to(who)) obv = obv + [exit]; } return obv; . public visible_exits var obv, exit; obv = []; for exit in (.exits()) { if (exit.visibility() >= .visibility()) obv = [@obv, exit]; } return obv; . public area var out, x; out = []; for x in (coordinates.keys()) { if (x.has_ancestor($place)) out = out + [x]; } return out; . public realm_name arg [ctype]; ctype = [@ctype, "text/plain"][1]; switch (ctype) { case "text/html": return .hname() + " (" + realm.realm_name() + ")"; default: return .name() + " (" + realm.realm_name() + ")"; } . public will_attach arg type, [by_whom]; by_whom = [@by_whom, sender()][1]; if (!(| .trusts(by_whom) |) && !.is_publicly('extendable)) throw(~perm, "Place is not publicly extendable."); . public 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, 'name), "none")]; case 'average: output = []; for ex in (exits) { line = ex.name() + " ("; 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.name() + " (to " + ex.dest().name() + ")"]; return output ? ["Exits: ", @$list.lcolumnize(output, actor.linelen())] | []; case 'verbose: output = []; for ex in (exits) { line = ex.prose(); if (!line) line = [ex.name()]; output = [@output, line[1]]; } return output ? [output.to_string()] | []; } . public place_destroyed arg place; // announces when a place is destroyed (> .perms(caller(), $place, $realms_frob) <); (| ._del_coordinate(place) |); . public exit_arrival arg actor; var exit, omsg, msg; exit = sender(); msg = (| exit.message('arrive) |); omsg = (| exit.message('oarrive) |) || "%N arrives."; // should be ctext... if (msg) { msg = msg.replace("%N", actor.name()); msg = msg.replace("%E", exit.name()); actor.tell(msg); } omsg = omsg.replace("%N", actor.name()); omsg = omsg.replace("%E", exit.name()); .announce(omsg, actor); . public exit_departure arg actor; var exit, msg, omsg; exit = sender(); // remove the crit's later, it will have 4 whopping ticks msg = (| exit.message('depart) |); omsg = (| exit.message('odepart) |) || "%N leaves."; // should be ctext... if (msg) { msg = msg.replace("%N", actor.name()); msg = msg.replace("%E", exit.name()); actor.tell(msg); } omsg = omsg.replace("%N", actor.name()); omsg = omsg.replace("%E", exit.name()); .announce(omsg, actor); . public long_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; . public announce_to arg type, str, [except]; var obj; switch (type) { case 'realm, 'sub_realm: .realm().announce('sub, str, @except); case 'super_realm: .realm().announce('super, str, @except); case 'local: .announce(str, @except); case 'area: for obj in (.area() + [this()]) obj.announce(str, @except); } . public set_objname: disallow_overrides arg new_objname; if (caller() != $place && !(sender() in $sys.system())) throw(~perm, "Place objname can only be changed by $place."); (> pass(new_objname) <); . public mesg_announce arg mesg; var obj; //workaround to allow message to work. for obj in (.contents()) (| obj.tell(mesg, 'ctext) |); . public did_attach arg type, [by_whom]; if (caller() != $exit) throw(~perm, "Caller is not $exit."); .add_object_to_remote_caches(sender()); . public rehash_caches var exit; (> pass() <); for exit in (exits) (> .add_object_to_remote_caches(exit) <); . public coordinates return coordinates; . public check_realm arg definer, value, [args]; return $places.match_realm(value) || throw(~invrealm, "Unable to find the realm " + toliteral(value) + "."); . public del_realm arg name, definer, [args]; (> .perms(sender()) <); realm = $realm_of_creation; . public darkness arg [args]; return darkness; . public display_setting_realm arg frob; return frob.name(); . parent $network object $connection var $root objname 'connection var $root child_index 6 var $root created_on 809051864 var $root inited 1 var $root indestructable 1 var $root flags ['parameters, 'methods, 'code, 'core] var $connection buffer `[] var $connection host "" var $connection daemon 0 var $connection active 0 var $connection line_buffer 0 var $connection interface 0 var $connection timeout 0 var $connection read_block [] var $connection started_at 0 var $connection port 0 public new var child, daemon, port, i; (> .perms(caller(), $daemon) <); child = .spawn(); daemon = sender(); i = interface.new(child); port = daemon.current_port(); // do perms stuff child.add_writer(daemon); child.add_writer(interface); child.add_writer((| class(i) |) || i); child.add_writer(this()); child.set_daemon(daemon); child.set_port(port); child.new_interface(i); child.change_manager(child); // call scheduler // if (timeout) { // } return child; . public daemon_shutdown var c; (> .perms(caller(), $daemon) <); for c in (.children()) (> c.close() <); . root init_connection buffer = `[]; host = ""; daemon = 0; active = 0; line_buffer = []; interface = 0; timeout = 0; read_block = 0; started_at = 0; .set_flags([]); . root uninit_connection (| close_connection() |); active = 0; if (interface) (| interface.connection_going_away(.address(), daemon.current_port()) |); interface = 0; . public timeout return timeout; . public address (> .perms(sender()) <); return host; . public set_host arg host; (> .perms(sender()) <); set_var('host, host); . public change_interface arg new; var old; (> .perms(sender()) <); if (interface) { old = interface; old.connection_going_away(.address(), daemon.current_port()); .del_writer((| class(old) |) || old); } interface = new; .add_writer((| class(new) |) || new); interface.connection_starting(.address(), daemon.current_port()); . public new_interface arg interface; (> .perms(sender()) <); set_var('interface, interface); . public set_daemon arg daemon; (> .perms(sender()) <); set_var('daemon, daemon); . public write arg what, [how]; var elem, sep; sep = 'non_terminated in how ? `[] | `[10]; switch (type(what)) { case 'string: what = $buffer.from_strings([what], sep); case 'list: what = $buffer.from_strings(what, sep); case 'buffer: default: throw(~type, "Write: strings, list of strings and buffers."); } echo(what); . driver parse arg incoming; var lines, line, index; lines = buffer.append(incoming).to_strings(); index = lines.length(); buffer = lines[index]; lines = lines.delete(index); line_buffer = [@line_buffer, @lines]; while (line_buffer) { line = line_buffer[1]; line_buffer = line_buffer.delete(1); (| .parse_line(line) |); } . public parse_line arg line; (> .perms(sender()) <); if (read_block) { read_block = read_block.parse(line); line = .rehash_read_status(); if (!line && line != "") return; } if (interface.parse_line(line) == 'disconnect) (> .close() <); . public echo_file arg fname; (> .perms(sender()) <); (> echo_file(fname) <); . public is_reading_block return read_block ? 1 | 0; . public finish_reading_block var task_id, lines; (> .perms(sender()) <); task_id = read_block.task_id(); lines = read_block.lines(); read_block = 0; $sys.resume(task_id, lines); . public abort_reading_block (> .perms(sender()) <); read_block = read_block.add('lines, 'aborted); .finish_reading_block(); . public start_reading_block arg count; (> .perms(sender()) <); read_block = $read_parser.new(task_id(), count); return $sys.suspend(); . public rehash_read_status (> .perms(sender(), 'this) <); switch (read_block.status()) { case 'abort: .abort_reading_block(); case 'not_done: // do nothing case 'done: .finish_reading_block(); case 'pass_command: return read_block.command(); } return 0; . public do_timeout arg seconds; (> .perms(sender(), $scheduler) <); .write("Timeout (" + tostr(seconds) + ")"); .close(); . public close (> .perms(sender()) <); (> .destroy() <); . public disconnect arg [args]; if (sender()) throw(~perm, "Sender is not the driver."); (| .close() |); . public set_port arg port; (> .perms(sender()) <); set_var('port, port); . public init_connection_settings (> .perms(caller(), $connection) <); . public active return active; . driver connect arg host, socket; set_var('host, host); daemon.new_connection(); . public write_string arg string; if (sender() != interface && sender() != (| class(interface) |)) throw(~perm, sender().objname() + " cannot write this connection."); if (type(string) != 'string) throw(~type, "Argument must be a string."); echo($buffer.from_string(string)); . public write_strings arg strings; if (sender() != interface && sender() != (| class(interface) |)) throw(~perm, sender().objname() + " cannot write this connection."); if (type(strings) != 'list) throw(~type, "Argument must be a list of strings."); echo($buffer.from_strings(string)); . public write_buffer arg buffer; if (sender() != interface && sender() != (| class(interface) |)) throw(~perm, sender().objname() + " cannot write this connection."); if (type(buffer) != 'buffer) throw(~type, "Argument must be a buffer."); echo(buffer); . public active_since return active; . public start // Make this method 'fork' from the regular thread stack (> .perms(caller(), $daemon) <); active = time(); interface.connection_starting(host, port); . public interface caller() == $daemon || (> .perms(sender()) <); return interface; . parent $network object $daemon var $root objname 'daemon var $root child_index 2 var $root created_on 809051864 var $root inited 1 var $root indestructable 1 var $root flags ['parameters, 'methods, 'code, 'core] var $daemon default_port 0 var $daemon connection 0 var $daemon next_connection 0 var $daemon current_port 0 public set_default_port arg port; (> .perms(sender()) <); default_port = port; . public set_connection arg connection; (> .perms(sender()) <); set_var('connection, connection); . public stop_listening arg [port]; (> .perms(sender()) <); connection.daemon_shutdown(); next_connection = 0; . public start_listening arg [port]; (> .perms(sender()) <); (| .stop_listening() |); current_port = [@port, default_port][1]; next_connection = connection.new(); bind_port(current_port, next_connection); . public new_connection var new_connection; (> .perms(caller(), $connection, definer()) <); if (!valid(next_connection)) next_connection = connection.new(); new_connection = next_connection; next_connection = connection.new(); bind_port(current_port, next_connection); // With forked methods, put this before we create the new connection new_connection.start(); . public startup arg [args]; var name, opt, port; catch any { (> .perms(caller(), $sys) <); name = tostr(.objname('symbol)); name = "-p" + name.subrange(1, ("_" in name) - 1); opt = name in args; port = (| toint(args[opt + 1]) |) || default_port; (| .stop_listening() |); (> .start_listening(port) <); $sys.log("** Starting " + .objname() + " on port " + tostr(port) + " **"); } with handler { switch (error()) { case ~bind: $sys.log("** Unable to bind to port " + tostr(port) + "! **"); default: $sys.log($parse_lib.traceback(traceback())); } } . public current_port return current_port; . public bind_port arg port; if (caller() == $backdoor) return (> bind_port(port, sender()) <); . public shutdown arg [args]; (> .perms(caller(), $sys) <); (> .stop_listening() <); . parent $network parent $command_cache object $connection_interface var $root objname 'connection_interface var $root child_index 2 var $root created_on 809051864 var $root inited 1 var $root quota_exempt -1 var $root indestructable 1 var $root flags ['parameters, 'methods, 'code, 'core] var $command_cache shortcut_cache 0 var $command_cache remote_cache 0 var $command_cache local_cache 0 var $has_commands shortcuts #[] var $has_commands remote #[] var $has_commands local #[] var $connection_interface connection 0 public parse_line arg this, line; var cmd, c, match, parsed, i, m, a, u; catch any { while (line && line[1] == " ") line = line.subrange(2); if (!line) { return .null_cmd(this, line); } else { cmd = line.explode(); cmd = [line, cmd[1], cmd.subrange(2).to_string() || ""]; c = (| .match_in_local_cache(@cmd) |); if (c && c[1] == 'local) { // screw duplicates, take the first match match = c[2][1]; m = match[2]; i = match[5]; parsed = i.keys(); for a in [1 .. m.length()] { if (a in parsed) m = m.replace(a + 2, (> $command_lib.convert_arg(i[a][1], m[a + 2], $no_one, i[a][2] ? i[a][2][1] | $no_one, $no_one) <)); } return (> .(match[4])(this, @m) <); } return (> .invalid_cmd(this, line) <); } } with handler { if (traceback()[1][3] != 'no_traceback) { this['connection].write($parse_lib.traceback(traceback())); return 'disconnect; } } . public connection_going_away arg [args]; (| .destroy() |); . public linelen arg [args]; return 79; . public send arg [args]; return (> .write(@args) <); . public write arg this, what; return (> this['connection].write(what) <); . public null_cmd arg [args]; return 'disconnect; . public invalid_cmd arg [args]; return 'disconnect; . public connection return connection; . public tell arg [args]; (> .write(@args) <); . public new arg c; var i; (> .perms(caller(), $connection) <); i = .spawn(); i.set_connection(c); i.change_manager(i); return i; . public new_connection arg this, host, port; . public set_connection arg c; (> .perms(caller(), definer()) <); connection = c; . public daemon_shutdown var i; (> .perms(caller(), $daemon) <); for i in (.children()) (| i.destroy() |); . parent $help_root parent $named object $help_index var $root child_index 1 var $root inited 1 var $root trusted 1 var $root objname 'help_index var $root created_on 796268969 var $root flags ['parameters, 'methods, 'code, 'core] var $help_index topics 0 var $named name ['uniq, "help_index", "the help_index"] var $named name_aliases [] root init_help_index topics = []; . public node_going_away var node; (> .perms(caller(), $help_node) <); node = sender(); // do something intelligent with the text body as well links = links.del(node); . public find_help_node arg str; var node; for node in (topics) { if (node.match_name(str)) return node; } return 0; . parent $help_root object $help var $root inited 1 var $root objname 'help var $root created_on 796268969 var $root flags ['parameters, 'methods, 'code, 'core] public default_help_node return $help_node_summary; . parent $help_root parent $named object $help_node var $root child_index 5 var $root fertile 1 var $root inited 1 var $root objname 'help_node var $root created_on 796268969 var $root flags ['parameters, 'methods, 'code, 'fertile, 'core] var $named name ['uniq, "help_node", "the help_node"] var $named name_aliases [] var $help_node links 0 var $help_node title 0 var $help_node body 0 var $help_node linked [] var $help_node indices 0 var $help_node linked_by [] var $help_node upnodes [] var $help_node downnodes [] root init_help_node linked_by = []; links = #[]; // title = ""; body = $ctext_frob.new([]); // upnodes = []; // downnodes = []; . root uninit_help_node var obj; for obj in (linked) (| obj.node_going_away() |); for obj in (indices) (| obj.node_going_away() |); indices = []; linked = []; links = #[]; title = ""; body = []; . public index_going_away (> .perms(caller(), $help_index) <); // ack, it is going away! Not good, but we cannot do anything about it .del_index(sender()); . public set_body arg new_body; var new_body, anchors, key, keys, values, value; (> .perms(sender()) <); // Compile a string into help ctext new_body = $cml2_compiler.compile_cml(new_body); body = new_body; //new_body = $help_evaluator.compile_cml(new_body); //body = $ctext_frob.new(new_body['result]); // If old anchors aren't in the new body, delete them. // old_anchors = links; //anchors = (| new_body['anchors] |) || #[]; anchors = (| new_body.get_var('links) |) || #[]; keys = anchors.keys(); values = anchors.values(); links = #[]; for key in (keys) links = links.add(key, $object_lib.to_dbref(anchors[key])); . public body return body; . public links return links; . public add_link arg key, node; (> .perms(sender(), 'manager) <); links = links.add(key, node); . public del_link arg name; (> .perms(sender(), 'manager) <); if (name in links.keys()) links = links.del(name); . public node_going_away var node; (> .perms(caller(), $help_node) <); node = sender(); // do something intelligent with the text body as well links = links.del(node); . public eval_body return body.eval_ctext(); . public add_index arg index; (> .perms(caller(), 'this) <); indices = indices.setadd(index); . public del_index arg index; (> .perms(caller(), 'this) <); indices = indices.setremove(index); // There can be unindexed topics. // if (!indices) // .add_index($help_index_general); . public generate_body_as arg type; switch (type) { case "text/plain": // $help_evaluator.eval_cml( hsm, this isn't right... case "text/html": } . public set_title arg new_title; .perms(sender(), 'manager); title = new_title; . public title return title; . public accept_link linked_by = [@linked_by, sender()]; return 1; . public _del_link //sender no longer links to us. if (sender() in linked_by) linked_by = linked_by.delete(sender() in linked_by); . public _set_link arg node, name; var linked_as; //Ask node if we can link to it. linked_as = node.accept_link(name); if (linked_as) { if (name in links.keys()) links[name]._del_link(back_links[node]); links = links.add(name, node); back_links = back_links.add(linked_as); } else { throw(~refuse, "Node refused link"); } . public delete_all var l; // delete all links to and from this node. if ("upnodes" in links.keys()) { for l in (links["upnodes"]) l._del_downnode(); links = links.del("upnodes"); } if ("downnodes" in links.keys()) { for l in (links["downnodes"]) l._del_upnode(); links = links.del("downnodes"); } for l in (links.keys()) l._del_link(); . public downnode_names var output, t; output = []; for t in (.downnodes()) output = [@output, t.title()]; return output; . public make_downnode arg name; var new; //make a new help node that is a downnode of this node. new = $help_node.spawn(); new.set_name(name); .add_downnode(new); new.add_upnode(this()); . public tell_help_node arg node; var out, len, clen, line, n; (> .perms(sender(), 'this) <); len = .linelen() % 2 ? .linelen() - 1 | .linelen(); .tell((" " + node.name() + " ").center(len, "-")); .tell(node.eval_body()); .tell("".pad(len, "-")); //if (node.upnodes()) // .tell("Up-nodes: " + node.upnodes().map('name).to_english()); //if (node.downnodes()) // .tell("Down-nodes: " + node.downnodes().map('name).to_english()); . public node_name var name; if (this() == definer()) return ""; name = (.parents())[1].node_name(); if (!name) return .name(); return name + ": " + .name(); . public html_node_name var name; if (this() == definer()) return ""; name = (.parents())[1].html_node_name(); if (!name) return "<a href=\"/bin/help?" + .objname() + "\">" + .name() + "</a>"; return name + ": <a href=\"/bin/help?" + .objname() + "\">" + .name() + "</a>"; . parent $thing parent $text object $note var $root child_index 31 var $root fertile 1 var $root inited 1 var $root objname 'note var $root created_on 796268969 var $root flags ['parameters, 'methods, 'code, 'fertile, 'core] var $text text [] var $located location $nowhere var $located obvious 1 var $described prose [] var $messaged verbs #[["erase %this", ['erase_vrb, 'remote]], ["read|nread %this", ['read_vrb, 'remote]], ["write on %this", ['write_vrb, 'remote]], ["write at * on %this", ['write_at_vrb, 'remote]], ["write * on %this", ['write_str_vrb, 'remote]], ["copy from %this to *", ['copy_vrb, 'remote]], ["erase * on|from %this", ['erase_on_vrb, 'remote]]] var $gendered gender $gender_neuter var $named name ['uniq, "Generic Note", "the Generic Note"] var $named name_aliases ["note"] var $note seperator 0 var $public public [] var $has_commands remote #[["erase", [["erase", "*", "erase <this>", 'erase_cmd, #[[1, ['this, []]]]], ["erase", "* on|from *", "erase <string> on|from <this>", 'erase_on_cmd, #[[1, ['any, []]], [3, ['this, []]]]]]], ["read|nread", [["read|nread", "*", "read|nread <this>", 'read_cmd, #[[1, ['this, []]]]]]], ["write", [["write", "on *", "write on <this>", 'write_cmd, #[[2, ['this, []]]]], ["write", "at * on *", "write at <string> on <this>", 'write_at_cmd, #[[2, ['any, []]], [4, ['this, []]]]]]], ["copy", [["copy", "from * to *", "copy from <this> to <any>", 'copy_cmd, #[[2, ['this, []]], [4, ['any, []]]]]]]] public add_text arg ntext, who, [args]; // if at they should be an int defining where to insert. if (sender() != this()) { if (!.is_publicly('writable) && !.is_writable_by(sender())) throw(~perm, "Permission Denied."); } if (ntext) { if (ntext == 'aborted) return; if (args) { if (!(| .ins_lines(ntext, args[1]) |)) who.tell("There are not that many lines in " + .name('ref) + "."); } else { .set_text(.text() + ntext); } who.tell("Line" + (ntext.length() == 1 ? "" | "s") + " added to " + .name('def) + "."); } else { who.tell("Text not added."); } . public seperator return type(seperator) == 'string ? seperator | "---"; . root init_note .del_flag('parameters); .set_public('readable); . public init_for_core .perms(caller(), $sys); . public set_seperator arg newsep; .perms(sender(), 'manager); seperator = newsep; . public read_cmd arg cmdstr, cmd, [args]; var who, text, prose; who = sender(); if (!.is_publicly('readable) && !.trusts(who)) return who.tell(.name() + " is not publicly readable!"); who.tell(.name()); who.tell(.prose()); who.tell(.seperator()); text = .text(); if (cmd == "nread" && text) text = $list.numbered_text(text); who.tell(text ? text | ["", "(nothing)", ""]); who.tell(.seperator()); who.tell("You finish reading " + .name() + "."); . public write_cmd arg cmdstr, cmd, [args]; var who, line; who = sender(); if (!.is_publicly('writable) && !.is_writable_by(who)) return who.tell(.namef() + " is not publicly writable!"); // because I'm odd lets do this all 1 one command. if (args.length() == 2) { line = "Now writing on " + .name('def); line = line + ", enter \".\" to finish and \"@abort\" to abort."; // who.tell(line); .add_text(who.read(line), who); } else { args = args[1].explode(); who.debug(args); } . public erase_on_cmd arg cmdstr, cmd, str, prep, this; var line, nline, who, len, oldline; who = sender(); if (!.is_publicly('writable) && !.is_writable_by(who)) return who.tell(.namef() + " is not publicly writable!"); if (!str) return who.tell("You must erase either a line, line number, or all"); catch any { if ($string.match_begin("all", str)) { .del_text(); // if cmd is null, this method was called by an editor if (cmd) who.tell("All text cleared from " + .name('def) + "."); } else { if (str.explode().length() > 1) nline = toint((str.explode())[2]); else nline = toint(str); oldline = (.text())[nline]; .del_nline(nline); line = "Line " + tostr(nline) + " (\""; len = who.linelen() - (25 + .name('def).length()); line = line + $string.chop(oldline, len); line = line + "\") erased from " + .name('def); who.tell(line); } } with handler { switch (error()) { case ~range: who.tell("There are not that many lines in the text."); default: who.tell("Oops: " + traceback()[1][2]); } } . public erase_cmd arg cmdstr, cmd, this; var line, nline, len; if (!.is_publicly('writable) && !.is_writable_by(sender())) return sender().tell(.namef() + " is not publicly writable!"); .del_text(); // if cmd is null, this method was called by an editor originally. if (cmd) sender().tell("All text cleared from " + .name('def) + "."); . public write_str_cmd arg cmdstr, cmd, str, prep, this; if (!.is_publicly('writable) && !.is_writable_by(sender())) return .namef() + " is not publicly writable!"; if (!str) return "Nothing to write on " + .name('def) + "!"; .add_text([str], sender()); . public write_at_cmd arg cmdstr, cmd, at, str, prep, this; var who, line, lines, syn; who = sender(); if (!.is_publicly('writable) && !.is_writable_by(who)) return who.tell(.namef() + " is not publicly writable!"); syn = "`" + cmd + " at [line] <line number> on " + this + "`"; str = str.explode(); if (str[1] == "line") str = str.delete(1); line = $string.is_numeric(str[1]); if (!at) $parse_lib.tell_error("Unknown line \"" + str[1] + "\".", syn, who); lines = .text().length(); if (line > lines + 1) $parse_lib.tell_error("There are only " + tostr(lines) + " lines!", syn, who); .add_text(who.read(), who, line); . public copy_cmd arg cmdstr, cmd, from, this, prep, where; var obj, what; // this method is outdated, needs to be rewritten. // it probably doesn't even work. if (!.is_writable_by(sender()) && !.is_publicly_readable()) return sender().tell("You cannot read the text on " + .namef('ref) + "."); if ("." in where) { where = $parse_lib.reference(where); what = 1; } else { where = $parse_lib.reference(where, ","); } obj = sender().match_env_nice(where[1]); if (!obj.is_writable_by(sender())) return .tell("! " + obj.namef('ref) + " is not owned by you."); if (obj.has_ancestor($note) && !where[2]) obj.add_text(text, sender()); // they want a method ref if (where[2]) { catch any { where = tosym(where[2]); if (what) { obj.(where)(text, sender()); sender().tell("Text copied to " + $data_lib.unparse(obj) + "." + tostr(where) + "()."); } else { if (!(where in obj.parameters())) return .tell("! parameter '" + tostr(where) + " not found"); obj.eval([tostr(where) + " = " + $data_lib.unparse(.text())]); } } with handler { $brandon.tell_traceback(traceback()); $parse_lib.tell_error(traceback()[1][2], "`" + cmd + " <obj>[.,<destination]`", sender()); } } sender().tell("Text copied from " + .namef()); . public description arg flags; return (> pass(flags) <) + ["You see some writing on the note, and may be able to read it..."]; . parent $utilities parent $text parent $named object $project var $root objname 'project var $root child_index 24 var $root created_on 799192659 var $root inited 1 var $root flags ['parameters, 'methods, 'code, 'core] var $project list 0 var $text text [] var $named name ['uniq, "project", "the project"] var $named name_aliases [] public list return list; . public change_list_to arg new_list; (> .perms(caller(), $projects) <); list = new_list; . public generate_html var out, tmp, line; out = ["<head><title>" + $motd.server_name() + " Project:" + .name() + "</title><center><img src=\"/tCD.gif\"><p><i><b><font size=+1>" + .name() + "</font></b></i></center></head>", "<body>", "<hr>"]; tmp = .developers(); // Developers line = "<b>Developer"; if (tmp.length() > 1) line = line + "s:</b>"; else line = line + ":</b>"; out = out + [line + tmp.map('name).to_english() + "<br>"]; // Status tmp = .list(); if (!tmp) tmp = "No Status Set"; else tmp = tostr(tmp).capitalize(); out = out + ["<b>Status:</b> " + tostr(tmp), "<hr>"]; return out + (.text() || []); . public developers return .writable().compress().setremove(this()); . parent $text parent $mail_root object $mail_message var $root child_index 88 var $root fertile 1 var $root inited 1 var $root objname 'mail_message var $root created_on 796268969 var $root indestructable 1 var $root flags ['parameters, 'methods, 'code, 'fertile, 'core] var $root quota_exempt -1 var $located location $the_pit var $messaged verbs #[] var $mail_message readers [] var $mail_message header #[] var $mail_message delivered 0 public del_recipient: disallow_overrides arg whom; var rcpts; if (!$mail_lib.has_mail_perms(caller())) (> .perms(sender()) <); rcpts = header['rcpt].setremove(whom); if (!rcpts) .destroy(); else header = header.add('rcpt, rcpts); . public add_recipient: disallow_overrides arg whom; var current; if (!$mail_lib.has_mail_perms(caller())) (> .perms(sender()) <); current = (| header['rcpt] |) || []; if ((| whom in current |)) throw(~type, "Recipient is already in the list of recipients"); header = header.add('rcpt, current.union([whom])); . public letter: disallow_overrides if (!$mail_lib.has_mail_perms(caller())) (> .perms(sender()) <); return .header().add('text, .text()); . public readers: disallow_overrides if (!$mail_lib.has_mail_perms(caller())) (> .perms(sender()) <); return readers; . public did_read: disallow_overrides if (!$mail_lib.has_mail_perms(caller())) (> .perms(sender()) <); readers = [@readers, sender()]; . public set_time: disallow_overrides arg time; if (!$mail_lib.has_mail_perms(caller())) (> .perms(sender()) <); header = header.add('time, time); . public set_recipients: disallow_overrides arg whom; if (!$mail_lib.has_mail_perms(caller())) (> .perms(sender()) <); header = header.add('rcpt, whom); . public set_subject: disallow_overrides arg what; if (!$mail_lib.has_mail_perms(caller())) (> .perms(sender()) <); header = header.add('subj, what); . public set_from: disallow_overrides arg whom; if (!$mail_lib.has_mail_perms(caller())) (> .perms(sender()) <); header = header.add('from, whom); . public add_reader: disallow_overrides arg who; if (!$mail_lib.has_mail_perms(caller())) (> .perms(sender()) <); readers = readers.union([who]); . public recipients: disallow_overrides if (!$mail_lib.has_mail_perms(caller())) (> .perms(sender()) <); return (| header['rcpt] |) || [$no_one]; . public from: disallow_overrides if (!$mail_lib.has_mail_perms(caller())) (> .perms(sender()) <); return (| header['from] |) || $no_one; . public subject: disallow_overrides if (!$mail_lib.has_mail_perms(caller())) (> .perms(sender()) <); return (| header['subj] |) || "<none>"; . public time: disallow_overrides if (!$mail_lib.has_mail_perms(caller())) (> .perms(sender()) <); return (| header['time] |) || 0; . public format: disallow_overrides var output, names, o, h; if (!$mail_lib.has_mail_perms(caller())) (> .perms(sender()) <); h = .header(); output = ["From: " + h['from].namef('ref)]; names = h['rcpt].omap($mail_lib, 'mail_name).to_english(); output = [@output, "To: " + names]; output = [@output, "When: " + $time.date(h['time])]; output = [@output, "Subject: " + h['subj]]; output = [@output, "---", @.text(), "---"]; return output; . public header: disallow_overrides var h, d; (> .perms(sender()) <); h = #[['from, $no_one], ['rcpt, [$no_one]], ['subj, "<none>"], ['time, 0]]; for d in (header) h = h.add(@d); return h; . root uninit_mail_message var r; for r in (.recipients()) (| r.del_mail(this(), (| .from() || this() |)) |); header = #[]; readers = []; . root init_mail_message header = #[]; readers = []; .set_flags([]); . public has_read: disallow_overrides arg who; return who in readers; . public text return (> pass() <) || ["", "(no message)", ""]; . public send arg [recips]; var r, valid, invalid; if (!$mail_lib.has_mail_perms(caller())) (> .perms(sender()) <); if (delivered) throw(~delivered, "This mail has already been delivered."); if (!recips) recips = .recipients(); if (recips.length() == 1 && recips[1] == $no_one) throw(~norcpt, "No recipients specified."); valid = []; invalid = []; for r in (recips) { if (r.has_ancestor($mail_list)) valid = [@valid, r]; else invalid = [@invalid, r]; } if (invalid) throw(~invrcpt, "Invalid mail recipients: " + invalid.map('name), invalid); recips = valid; invalid = []; // ok, now that we have that cleared up, lets set pertinent info... .set_time(time()); .set_from(sender()); // and now to finalize the recipients for r in (recips) { if (r.list_is_sendable_by(sender())) { r.add_mail(); .add_recipient(r); } else { invalid = [@invalid, r]; } } delivered = 1; return invalid; . public new_mail var new; if (!$mail_lib.has_mail_perms(caller())) (> .perms(sender()) <); if (definer() != $mail_message) throw(~perm, "Only spawn mail from $mail_message."); new = .spawn(); new.add_writer(sender()); new.change_manager(new); return new; . parent $frob parent $messaged object $event_frob var $root inited 1 var $root objname 'event_frob var $root created_on 796268969 var $root flags ['parameters, 'methods, 'code, 'core] var $event_frob type 'generic var $messaged messages #[] public new arg [args]; .perms(caller(), $event_handler); // we still don't know what we want // if (type(location) != 'dbref) // throw(~type, "The location must be given as a objname"); // return <this(), #[['actor, sender()], ['action, action], ['what, what], ['where, location], ['direction, direction]]>; return (<this(), [sender(), @args]>); . public dispatch arg dict; dict['where].event((<this(), dict>)); . public set_event_type arg newtype; .perms(sender()); if (type(newtype) != 'symbol) throw(~type, "New event types must be symbols."); type = newtype; . public type arg frob; return type; . public process arg [args]; . parent $gender object $gender_female var $root inited 1 var $root objname 'gender_female var $root created_on 796268969 var $root flags ['parameters, 'methods, 'code, 'core] var $gender cgender_name "Female" var $gender gender_name "female" var $gender pronouns #[['pr, "herself"], ['pp, "her"], ['po, "her"], ['ps, "she"], ['pq, "hers"], ['prc, "Herself"], ['ppc, "Her"], ['poc, "Her"], ['psc, "She"], ['pqc, "Hers"]] var $gender number 'singular var $gender context ["herself", "her", "her", "she", "hers", "Herself", "Her", "Her", "She", "Hers"] var $named name ['prop, "female", "female"] parent $gender object $gender_male var $root inited 1 var $root objname 'gender_male var $root created_on 796268969 var $root flags ['parameters, 'methods, 'code, 'core] var $gender cgender_name "Male" var $gender gender_name "male" var $gender pronouns #[['pr, "himself"], ['pp, "his"], ['po, "him"], ['ps, "he"], ['pq, "his"], ['prc, "Himself"], ['ppc, "His"], ['poc, "Him"], ['psc, "He"], ['pqc, "His"]] var $gender number 'singular var $gender context ["himself", "his", "him", "he", "his", "Himself", "His", "Him", "He", "His"] var $named name ['prop, "male", "male"] parent $gender object $gender_plural var $root trusted [] var $root inited 1 var $root objname 'gender_plural var $root created_on 796268969 var $root flags ['parameters, 'methods, 'code, 'core] var $gender cgender_name "Plural" var $gender gender_name "plural" var $gender pronouns #[['pr, "themselves"], ['pp, "their"], ['po, "them"], ['ps, "they"], ['pq, "theirs"], ['prc, "Themselves"], ['ppc, "Their"], ['poc, "Them"], ['psc, "They"], ['pqc, "Theirs"]] var $gender number 2 var $gender context ["themselves", "their", "them", "they", "theirs", "Themselves", "Their", "Them", "They", "Theirs"] var $named name ['prop, "plural", "plural"] parent $gender object $gender_neuter var $root inited 1 var $root objname 'gender_neuter var $root created_on 796268969 var $root flags ['parameters, 'methods, 'code, 'core] var $gender cgender_name "Neuter" var $gender gender_name "neuter" var $gender pronouns #[['pr, "itself"], ['pp, "its"], ['po, "it"], ['ps, "it"], ['pq, "its"], ['prc, "Itself"], ['ppc, "Its"], ['poc, "It"], ['psc, "It"], ['pqc, "Its"]] var $gender number 'singular var $gender context ["itself", "its", "it", "it", "its", "Itself", "Its", "It", "It", "Its"] var $named name ['prop, "neuter", "neuter"] parent $libraries object $dictionary var $root inited 1 var $root objname 'dictionary var $root created_on 796268969 var $root flags ['parameters, 'methods, 'code, 'core] public map_method arg ls, what; var x, dict; // args[1] == list of objects // args[2] == symbol for method on objects // it will create a dictionary out of the two. dict = #[]; // Get list's method(whatever) and add it to the dictionary for x in [1 .. ls.length()] dict = dict.add(ls[x], ls[x].(what)()); return dict; . public merge arg [args]; var x, dict, z, tule, dz, axz, keys; // merges all dictionaries into a single one, if they have the same key's -- // basing off of args[1] (this should be the longest list (i know, bad Lynx). dict = args[1]; keys = args[1].keys(); for x in [2 .. args.length()] { for z in (keys) { dz = dict[z]; axz = args[x][z]; if (type(dict[z]) == 'list) tule = dz; else tule = [dz]; tule = [@tule, axz]; dict = dict.add(z, tule); } } return dict; . public to_list arg dict; var list, x, k; // merges into an associated list. k = dict.keys(); list = []; for x in (k) list = [@list, [x, dict[x]]]; return list; . public merge_to_list arg [args]; var x, dict, z, tule, dz, axz, keys, list; // merges all dictionaries into a single list, where each related key // is merged with all it's other values as a subrange // basing off of args[1] (this should be the longest list (i know, bad Lynx). dict = .merge(@args); list = []; for z in (dict.keys()) list = [@list, dict[z]]; return list; . public union arg dict1, dict2; var key; // like union() but for dictionaries. adds any keys from dict2 that don't // already exist in dict1 to dict1 and returns the result. Order of keys in // result is not guaranteed. for key in (dict1) dict2 = dict2.add(key[1], key[2]); return dict2; . public values arg dict; var list, x, k; // returns values same as dict_keys() returns keys. k = dict.keys(); list = []; for x in (k) list = [@list, dict[x]]; return list; . public replace arg dict, key, value; dict = (> dict.del(key) <); dict = (> dict.add(key, value) <); return dict; . public apply arg tdict, list; var x; // Apply a translation-dict to a list for x in [1 .. list.length()] { catch ~keynf { list = list.replace(x, tdict[list[x]]); } } return list; . public apply_to_keys arg tdict, dict; var x, newdict; // Apply a t-dict to the keys of a dict newdict = #[]; for x in (dict) { catch ~keynf { x = x.replace(1, tdict[x[1]]); } newdict = newdict.add(@x); } return newdict; . public apply_to_values arg tdict, dict; var x, newdict; // Apply a t-dict to the values of a dict newdict = #[]; for x in (dict) { catch ~keynf { x = x.replace(2, tdict[x[2]]); } newdict = newdict.add(@x); } return newdict; . public invert arg dict; var inverted, x; // Invert a dict (keys<->values) inverted = #[]; for x in (dict.invert()) inverted = inverted.add(dict[x], x); return inverted; . public add_elem arg dict, key, elem; var value; // same as old dict_add_elem value = (| dict[key] |); if (type(value) != 'list && type(value) != 'error) throw(~type, "Value for key " + $data_lib.unparse(key) + " (" + $data_lib.unparse(value) + ") is not a list."); if (value) value = [@value, elem]; else value = [elem]; return dict.add(key, value); . public del_elem arg dict, key, elem; var value; value = (| dict[key] |); if (type(value) != 'list && type(value) != 'error) throw(~type, "Value for key " + $data_lib.unparse(key) + " (" + $data_lib.unparse(value) + ") is not a list."); value = value.setremove(elem); if (!value) return dict.del(key); return dict.add(key, value); . public add arg [args]; return (> dict_add(@args) <); . public del arg [args]; return (> dict_del(@args) <); . public keys arg dict; return (> dict_keys(dict) <); . public add_elem_union arg dict, key, elem; var value; value = (| dict[key] |); if (value) value = value.union([elem]); else value = [elem]; return dict.add(key, value); . public contains arg [args]; return (> dict_contains(@args) <); . parent $libraries object $time_root var $root inited 1 var $root objname 'time_root var $root created_on 796268969 var $root flags ['parameters, 'methods, 'code, 'core] var $time_root secs_per_year 31536000 var $time_root mins_per_hour 60 var $time_root secs_per_week 604800 var $time_root secs_per_day 86400 var $time_root created_on 758611955 var $time_root hours_per_day 24 var $time_root days_per_year 365 var $time_root year_begin 0 var $time_root secs_per_min 60 var $time_root days [""] var $time_root months #[["Jan", "January"], ["Feb", "February"], ["Mar", "March"], ["Apr", "April"], ["May", "May"], ["Jun", "June"], ["Jul", "July"], ["Aug", "August"], ["Sep", "September"], ["Oct", "October"], ["Nov", "November"], ["Dec", "December"]] var $time_root standard 0 var $time_root secs_per_hour 3600 public init_time .perms(caller(), $root); secs_per_min = 60; secs_per_hour = 3600; secs_per_day = 86400; secs_per_week = 604800; secs_per_year = 31536000; created_on = 0; mins_per_hour = 60; hours_per_day = 24; days_per_year = 365; year_begin = 0; days = [""]; months = [""]; standard = 0; . public time return .convert(); . public ctime arg [time]; time = [@time, .time()][1]; if (!standard) return "still working on this"; else return ctime(time); . public hr_min_sec arg [time]; // returns a list: ["hh", "mm", "ss"] return [tostr(.hour()), tostr(.minute()), tostr(.second())]; . public hour arg [time]; // either send a pre-converted time, or nothing. time = time ? time[1] | standard ? time() | .convert(); return time % secs_per_year % secs_per_day / secs_per_hour; . public convert arg [time]; // converts time into whatever time based off created_on return [@time, time()][1] - created_on; . public minute arg [time]; // either send a pre-converted time, or nothing. time = time ? time[1] | standard ? time() | .convert(); return time % secs_per_year % secs_per_day % secs_per_hour / secs_per_min; . public second arg [time]; // either send a pre-converted time, or nothing. time = time ? time[1] | standard ? time() | .convert(); return time % secs_per_year % secs_per_day % secs_per_hour % secs_per_min; . public year arg [time]; // either send a pre-converted time, or nothing. // returns years since 'created_on; // prolly not right. time = time ? time[1] | standard ? time() | .convert(); return time / secs_per_year + year_begin; . public day arg [time]; // either send a pre-converted time, or nothing. // returns days since 'created_on; // prolly not right. time = time ? time[1] | standard ? time() | .convert(); return time / secs_per_day; . public minute_str arg [args]; // will call $integer.int_to_name return 'null; . public hour_str arg [args]; // will call $integer.int_to_name return 'null; . public second_str arg [args]; // will call $integer.int_to_name return 'null; . public day_str arg [time]; time = [@time, .time()][1]; return tostr(.day()); . public months return months; . public days return days; . public secs_per_min return secs_per_min; . public secs_per_hour return secs_per_hour; . public secs_per_day return secs_per_day; . public secs_per_week return secs_per_week; . public secs_per_year return secs_per_year; . parent $libraries object $buffer var $root trusted [] var $root inited 1 var $root objname 'buffer var $root created_on 796268969 var $root flags ['parameters, 'methods, 'code, 'core] public to_list arg buf; var idx, list; list = []; for idx in [1 .. buf.length()] list = list + [buf.retrieve(idx)]; return list; . public from_list arg list; var buf, x; buf = `[]; for x in [1 .. list.length()] buf = buf.add(list[x]); return buf; . public length arg buffer; return (> buffer_len(buffer) <); . public retrieve arg buffer, position; return (> buffer_retrieve(buffer, position) <); . public append arg buffer, buffer_2; return (> buffer_append(buffer, buffer_2) <); . public replace arg buffer, position, value; return (> buffer_replace(buffer, position, value) <); . public add arg buffer, value; return (> buffer_add(buffer, value) <); . public truncate arg buffer, position; return (> buffer_truncate(buffer, position) <); . public tail arg buffer, position; return (> buffer_tail(buffer, position) <); . public to_string arg buffer; return (> buffer_to_string(buffer) <); . public to_strings arg [args]; return (> buffer_to_strings(@args) <); . public from_string arg string; return (> buffer_from_string(string) <); . public from_strings arg strings, [seperator]; return (> buffer_from_strings(strings, @seperator) <); . parent $libraries object $string var $root inited 1 var $root objname 'string var $root created_on 796268969 var $root flags ['parameters, 'methods, 'code, 'core] var $string alphabet "abcdefghijklmnopqrstuvwxyz" var $string numbers "1234567890" var $string non_alphanumeric "!@#$%^&*()_+-=~`'{}[]|/?\"\\,.<>;: " public left arg str, width, [fchar]; // will NOT chop off 'str' if it is longer than width, use pad() for that. if (fchar) return str + (str.length() < width ? "".pad(width - str.length(), fchar[1]) | ""); else return str + (str.length() < width ? "".pad(width - str.length()) | ""); . public fill arg n, [args]; var fill, x; // same as pad("", n, [args]); fill = [@args, " "][1]; return "".pad(n, fill); . public center arg text, len, [args]; var lfill, rfill, textlen, padlen; // args[1] == string to center // args[2] == integer of width to center in // args[3] <op> == what to fill the left|right side with. // args[4] <op> == what to fill the right side with. lfill = args.length() >= 1 && args[1] || " "; rfill = args.length() >= 2 ? args[2] | lfill == " " ? "" | lfill; textlen = text.length(); padlen = (len - textlen) / 2; if (textlen < len) return .fill(padlen, lfill) + text + (rfill ? .fill(padlen, rfill) | ""); else return len > 0 ? text | text.pad(len); . public trim arg string, [args]; var rl, chars, type; // remove leading and trailing characters. // if args includes a string, it takes that as the strip string. // args can also include symbols of what edge to trim: 'left 'right (or both) // left and right defaults on. rl = []; while (args) { type = type(args[1]); if (type == 'string) chars = args[1]; else if (type == 'symbol) rl = [@rl, args[1]]; args = args.subrange(2); } if (!chars) chars = " "; if (!rl) rl = ['left, 'right]; if ('left in rl) { // strip from left while (string && string[1] in chars) string = string.subrange(2); } if ('right in rl) { // strip from right while (string && string[string.length()] in chars) string = string.subrange(1, string.length() - 1); } return string; . public to_list arg str, [sep]; var result, list; // separate a string into a list of strings, breaking wherever 'sep' appears. // if not provided, sep defaults to a comma. // One word of warning. sep should not contain an asterisk. If it does, // this routine will separate the string oddly, most likely losing bits. if (!str) return []; sep = "*" + (sep ? sep[1] | ",") + "*"; list = []; while (1) { result = $string.match_pattern(sep, str); if (result) { list = list + [result[1]]; str = result[2]; } else { return list + [str]; } } . public right arg str, width, [fchar]; // will not chop off 'str' if it is longer than width (unlike pad()) if (fchar) return "".pad(width - str.length(), fchar[1]) + str; else return "".pad(width - str.length()) + str; . public alphabet return alphabet; . public numbers return numbers; . public capitalize arg string; // Capitalizes the first character of a word. return string[1].uppercase() + string.subrange(2); . public is_numeric arg string; return toint(string) || string == "0"; . public a_or_an arg string; if (string[1].lowercase() in "aeiou") return "an"; return "a"; . public strip arg string, strip; var new_str, char; // strips all of "strip" characters from the string // if "strip" is -1 it will use .non_alphanumeric() if (type(string) != 'string || type(strip) != 'string && strip != -1) throw(~type, "First argument must be a string, second can be -1"); new_str = ""; if (strip == -1) new_str = non_alphanumeric; for char in [1 .. string.length()] { if (!(string[char] in strip)) new_str = new_str + string[char]; } return new_str; . public non_alphanumeric return non_alphanumeric; . public chop arg str, len, [end]; // chops string off end.length() characters before len and appends len end = [@end, "..."][1]; if (str.length() < len) return str; if (str.length() < end.length()) return str; return str.pad(len - end.length()) + end; . public replace arg [args]; return (> strsub(@args) <); . public explode_english_list arg line, [opts]; var x, output, tmp; // explodes an english list ("foo, bar and zoo"). line = line.explode(","); output = []; for x in (line) { x = .trim(x); if ((| x.subrange(1, 3) |) == "and") output = [@output, .trim(x.subrange(4))]; else output = [@output, x]; } // check the last element, if they didn't specify 'noand if (!('noand in opts)) { line = output[output.length()].explode(); tmp = ""; for x in [1 .. line.length()] { if (line[x] == "and") { output = output.delete(output.length()); if (tmp) output = [@output, tmp]; tmp = $list.to_string(line.subrange(x + 1)); if (tmp) output = [@output, tmp]; // only bother with the first "and" break; } tmp = tmp + (tmp ? " " | "") + line[x]; } } return output; . public explode_delimited arg str, left, right; var pattern, parsed, matched, match_num, match_result; // parse str looking for anything surrounded by left and right // ;$string.explode_delimited("foo%[bar]baz", "%[", "]") // => [["foo", 1, "baz"], ["bar"]] pattern = "*" + left + "*" + right + "*"; parsed = []; matched = []; match_num = 0; while (str) { match_result = $string.match_pattern(pattern, str); if (match_result) { match_num = match_num + 1; parsed = [@parsed, match_result[1], match_num]; matched = [@matched, match_result[2]]; str = match_result[3]; } else { parsed = [@parsed, str]; str = ""; } } return [parsed, matched]; . public wrap_line arg string, length, [stuff]; var output, cutoff, firstline, prefix; // takes string and wraps it by words, compared to length, breaks with \n prefix = [@stuff, ""][1]; firstline = [@stuff, 0, 0][2]; output = ""; if (firstline) string = prefix + string; while (string.length() > length) { cutoff = .rindex(string.subrange(1, length), " "); output = output + "\\n" + string.subrange(1, cutoff - 1); string = prefix + string.subrange(cutoff + 1); } return output + "\\n" + string; . public rindex arg string, index; var loc, rest; // returns the first occurance of index starting from the end of the string, // and moving to the beginning. loc = index in string; rest = loc && string.subrange(loc + 1); while (loc && index in rest) { loc = loc + (index in rest); rest = loc && string.subrange(loc + 1); } return loc; . public match_sub_tag arg string, tag; var x, expl, output, match, matches; // matches a string between 'tag' and " " in a larger string against // the sender's environment. If a match is found it subs the match.name // with the string, otherwize it lets it pass through with the tag, ie: // .match_sub_tag("this test #of something #note or other"); // => "this test #of something Note of sorts or other" // where the note is in the sender's environment. expl = .explode_delimited(string + " ", tag, " "); matches = expl[2]; expl = expl[1]; output = ""; for x in (expl) { if (type(x) == 'integer) { match = (| sender().match_environment(matches[x]) |); if (match) output = output + match.namef() + " "; else output = output + tag + matches[x] + " "; } else { output = output + x; } } return output.subrange(1, output.length() - 1); . public search_pat arg pat, text, [start_at]; var line, match_result, type; line = 1; type = [@start_at, 'pattern, 'pattern][2] == 'pattern ? 'match_pattern | 'match_regexp; if (start_at) { line = start_at[1]; start_at = [@start_at, 1, 1][2]; match_result = pat.(type)(text[line].subrange(line)); if (match_result != 0) { if (type == 'match_pattern) { pat = $string.pat_sub(pat, match_result); return [line, start_at + pat in text[line].subrange(start_at)]; } else { return [line, start_at + match_result[1][1]]; } } line = line + 1; } while (line <= text.length()) { match_result = pat.(type)(text[line]); if (match_result != 0) { if (type == 'pattern) { pat = $string.pat_sub(pat, match_result); return [line, pat in text[line]]; } else { return [line, match_result[1][1]]; } } line = line + 1; } throw(~strnf, "String not found in text."); . public pat_sub arg pat, subs; var wc_idx; // wc_idx == wildcard index while (subs) { wc_idx = "*" in pat; if (wc_idx == 1) pat = subs[1] + pat.subrange(2); else if (wc_idx == pat.length()) pat = pat.subrange(1, wc_idx - 1) + subs[1]; else pat = pat.subrange(1, wc_idx - 1) + subs[1] + pat.subrange(wc_idx + 1); subs = subs.delete(1); } return pat; . public is_boolean arg str; if ($string.match_begin("yes", str) || $string.match_begin("true", str) || str == "1") return 1; else if ($string.match_begin("no", str) || $string.match_begin("false", str) || str == "0") return 0; else return -1; . public parse_template arg str; var index, out; out = (str.explode(" *"))[1]; // index = "?" in str; // if (index) { // out = uppercase(str.subrange(1, index - 1)); // out = out + "?" + str.subrange(index + 1); // } else { // out = uppercase(out); // } return out; . public repeat arg string, times; var t, out; // repeats <string> <times> times if (type(string) != 'string) throw(~type, "The first agrument must be a string."); if (type(times) != 'integer || times < 0) throw(~type, "The second agrument must be a non-negatiive integer."); out = ""; for t in [1 .. times] out = out + string; return out; . public explode arg [args]; return (> explode(@args) <); . public match_template arg template, string; return (> match_template(template, string) <); . public find_next arg str, choices; var t, first, pos; //Returns the index of the first string in choices to appear. //Returns str.length() if none are in str. first = str.length() + 1; for t in (choices) { pos = t in str; if (pos && pos < first) first = pos; } return first; . public split_on_next arg str, choices; var pos, pre, post; // splits str around whichever choice appears first. pos = $string.find_next(str, choices); pre = (| str.subrange(1, pos - 1) |) || ""; post = (| str.subrange(pos + 1) |) || ""; return [pre, (| str[pos] |) || "", post]; . public explode_template_word arg template; var t, x, idx, out, new; // this only explodes single word templates template = template.explode("|"); out = []; for t in (template) { idx = "?" in t; if (idx) { t = t.strip("?"); new = t.subrange(1, idx - 1); out = [@out, new]; for x in [idx .. t.length()] { new = new + t[x]; out = [@out, new]; } } else { out = [@out, t]; } } return out; . public match_pattern arg pattern, string; return (> match_pattern(pattern, string) <); . public match_regexp arg [args]; return (> match_regexp(@args) <); . public to_number arg str; if (str.is_numeric()) return toint(str); throw(~nonum, "\"" + str + "\" is not a number."); . public toliteral arg [args]; return (> toliteral(@args) <); . public last arg str; return str[str.length()]; . public explode_list arg str; if ("," in str) return str.explode_english_list(); else return str.explode(); . public onespace arg str; var c, l, out; l = ""; out = ""; for c in [1 .. str.length()] { pause(); if (str[c] != " " || str[c] != l) out = out + str[c]; l = str[c]; } return out; . public find_next_escaped arg str, choices; var t, first, pos, good, p, start; //Returns the index of the first string in choices to appear. //If //Returns str.length() if none are in str. first = str.length() + 1; for t in (choices) { pos = str.find_escaped(t); if (pos < first) first = pos; } return first; . public split_on_next_escaped arg str, choices; var pos, pre, post; // splits str around whichever choice appears first. pos = str.find_next_escaped(choices); pre = (| str.subrange(1, pos - 1) |) || ""; post = (| str.subrange(pos + 1) |) || ""; return [pre, (| str[pos] |) || "", post]; . public find_escaped arg str, char; var good, start, pos, p; good = 0; start = 0; while (!good && start < str.length()) { pos = (char in str.subrange(start + 1)) + start; good = 1; if (pos > start) { p = pos - 1; while (p > 0 && str[p] == "\\") { good = good ? 0 | 1; p = p - 1; } } if (good) return pos; else start = pos; } . public explode_quoted arg str; var out, result; out = []; while (str) { result = .match_pattern("*\"*\"*", str); if (result) { out = [@out, @result[1].explode(), result[2].trim()]; str = result[3]; } else { out = [@out, @str.explode()]; str = ""; } } return out; . public strip_article arg str; var articles, a, r; articles = ["a ", "an ", "the "]; for a in (articles) { if (r = $string.match_regexp("^" + a + "[ ]*(.*)", str)) return str.subrange(@r[2]); } return str; . public rindexc arg str, c; var i; // same as rindex, but only with a single character, faster. i = str.length(); while (i) { if (str[i] == c) return i; i = i - 1; } return 0; . public echo arg str; return str; . public sub arg regexp, string; var match, m, complete, out; match = $string.match_regexp(regexp, string); if (!match) return 0; complete = match[1]; out = []; for m in (match.delete(1)) { if (!m[1]) break; out = out + [string.subrange(@m)]; } return out || string.subrange(@complete); . public unquote arg str; if (str && str[1] == "\"" && str[str.length()] == "\"") return str.subrange(2, str.length() - 2); return str; . public to_buffer arg string; return (> $buffer.from_string(string) <); . public pad arg [args]; return (> pad(@args) <); . public valid_method_name arg str; return .strip_others(str, alphabet + numbers + "_").length() == str.length(); . public strip_others arg string, valid; var new_str, char; // strips all but "strip" characters from the string new_str = ""; for char in [1 .. string.length()] { if (string[char] in valid) new_str = new_str + string[char]; } return new_str; . public wrap_lines arg string, length, [stuff]; var output, cutoff, firstline, prefix; // takes string and wraps it by words, compared to length, returns a list. prefix = [@stuff, ""][1]; firstline = [@stuff, 0, 0][2]; output = []; if (firstline) string = prefix + string; while (string.length() > length) { cutoff = .rindex(string.subrange(1, length), " "); output = [@output, string.subrange(1, cutoff - 1)]; string = prefix + string.subrange(cutoff + 1); } return [@output, string]; . public length arg str; return (> strlen(str) <); . public subrange arg [args]; return (> substr(@args) <); . public match_begin arg [args]; return (> match_begin(@args) <); . public crypt arg [args]; return (> crypt(@args) <); . public uppercase arg string; return (> uppercase(string) <); . public lowercase arg string; return (> lowercase(string) <); . public compare arg str1, str2; return (> strcmp(str1, str2) <); . public format arg format, [args]; return (> strfmt(format, args) <); . public to_symbol arg [args]; return (> tosym(@args) <); . parent $libraries object $command_lib var $root inited 1 var $root objname 'command_lib var $root created_on 796268969 var $root flags ['parameters, 'methods, 'code, 'core] var $command_lib argument_types [["any", 'any], ["text", 'any], ["string", 'any], ["object", 'object], ["thing", 'thing], ["user", 'user], ["descendant of *", 'descendant], ["this", 'this], ["number", 'number], ["object reference", 'objref]] public argument_types return argument_types; . public get_argument_type arg type; var x, m; for x in [1 .. argument_types.length()] { m = $string.match_pattern(argument_types[x][1], type); if (type(m) == 'list) { switch (argument_types[x][2]) { case 'descendant: if (!m) throw(~type, "Argument type \"descendant of\" must have an object."); return ['descendant, [(> $object_lib.to_dbref(m[1]) <)]]; case 'thing: return ['descendant, [$thing]]; default: return [argument_types[x][2], []]; } } } throw(~command, "Invalid command argument type \"" + type + "\""); . public handle_shortcut_fields arg subs, fields; var subbed_list, elem; subbed_list = []; for elem in (subs) { if (type(elem) == 'string) subbed_list = [@subbed_list, elem]; else if (type(elem) == 'integer) subbed_list = [@subbed_list, (> fields[elem] <)]; else throw(~type, "Substitution element is of wrong type."); } return subbed_list; . public validate_command_template arg str; var cmd, tmp, loc, types, part, relations; tmp = str.explode_delimited("<", ">"); loc = []; types = tmp[2]; tmp = tmp[1]; cmd = []; relations = #[]; for part in (tmp) { if (type(part) == 'string) cmd = cmd + part.explode(); else cmd = [@cmd, part]; } // clean for part in [1 .. cmd.length()] { if (type(cmd[part]) == 'string) { cmd = cmd.replace(part, cmd[part].trim()); } else { relations = relations.add(part - 1, (> .get_argument_type(types[cmd[part]]) <)); cmd = cmd.replace(part, "*"); } } cmd = [cmd[1], cmd.subrange(2).to_string()]; return [cmd, relations]; . public parse_relation arg str, template; var part, out, list, index; // "foo* *", "foo $2 bar $1" => ["foo* *", ["foo", 2, "bar", 1]] list = []; index = [0, 0]; out = []; for part in [1 .. str.length()] { if (str[part] == "*") index = [index[1] + 1, 0]; } for part in (template.explode("$")) list = [@list, @part.explode()]; for part in (list) { if ($string.is_numeric(part)) { index = [index[1], index[2] + 1]; out = [@out, toint(part)]; } else { out = [@out, part]; } } if (index[1] > index[2]) throw(~invrelation, "Invalid relation: template one has more arguments than template two."); else if (index[1] < index[2]) throw(~invrelation, "Invalid relation: template two has more arguments than template one."); return out; . public unparse_shortcut arg s; var x, line; line = ""; for x in (s[2][2]) { if (type(x) == 'string) line = line + (line ? " " | "") + x; else line = line + (line ? " " | "") + "%" + tostr(x); } return ("\"" + s[1] + "\"").left(10) + " => \"" + line + "\""; . public format_commands_long arg cmds, type, clen; var def, name, c, cdef, line, o, cs, dname; o = []; for def in (cmds.keys()) { o = o + [type + " commands on " + def.name() + ":"]; for cdef in (cmds[def]) { for c in (cdef[2]) o = o + [" " + toliteral(c[3]).left(clen) + "." + tostr(c[4]) + "()"]; } } return o; . public format_commands_short arg cmds, type, len; var def, name, c, cdef, line, o, cs, dname; o = []; for def in (cmds.keys()) { o = o + [type + " commands on " + def.name() + ":"]; for cdef in (cmds[def]) { for c in (cdef[2]) o = o + [" " + toliteral(c[3])]; } } return o; . parent $libraries object $http_lib var $root inited 1 var $root objname 'http_lib var $root created_on 796268969 var $root flags ['parameters, 'methods, 'code, 'core] var $http_lib errors #[[400, ["<head><title>400 Bad Request</title></head>", "<body>", "<center><h1>400 Bad Request</h1></center>", "%s", "</body>"]], [403, ["<head><title>403 Permission Denied</title></head>", "<body>", "<center><h1>403 Permission Denied</h1></center>", "%s", "</body>"]], [404, ["<head><title>404 Not Found</title></head>", "<center><h1>404 Not Found</h1></center>", "%s", "</body>"]]] var $http_lib gateways #[["describe", "describe?$the_pit"], ["see", "see?$the_pit"], ["who", "who"], ["display", "display?$http_lib"], ["list_method", "list_method?$http_lib.list_method"], ["project", "project"], ["help", "help?$help_summary"], ["object", "object?$http_lib"]] var $http_lib http_methods ["GET"] var $http_lib codes #[[200, "Ok"], [201, "Created"], [202, "Accepted"], [203, "Provisional Information"], [204, "No Content"], [300, "Multiple Choices"], [301, "Moved Permanently"], [302, "Moved Temporarily"], [303, "Method"], [304, "Not Modified"], [400, "Bad Request"], [401, "Unauthorized"], [402, "Payment Required"], [403, "Forbidden"], [404, "Not Found"], [405, "Method Not Allowed"], [406, "None Acceptable"], [407, "Proxy Authentication Required"], [408, "Request Timeout"], [409, "Conflict"], [410, "Gone"], [500, "Internal Server Error"], [501, "Not Implemented"], [502, "Bad Gateway"], [503, "Service Unavailable"], [504, "Gateway Timeout"]] var $http_lib html_version "text/html" public _html_traceback arg type, what, [more]; var line; switch (type) { case 'function: return "function <tt>" + tostr(what) + "()</tt>"; case 'opcode: return "operator <tt>" + toliteral(what) + "</tt>"; default: line = $data_lib.unparse(more[2]) + "." + tostr(what) + "()"; if (more[1] != more[2]) line = line + " (" + $data_lib.unparse(more[1]) + ") "; line = line + " line " + tostr(more[3]); return line; } . public html_traceback arg status, t; var line, out, x; out = "<h2>" + (.filter_text([t[1][2]]))[1] + "</h2>"; out = [out, "<i><b>Thrown by " + ._html_traceback(@t[2]) + "</b></i>", "<p>"]; for x in [3 .. t.length()] { line = "<code><i>" + toliteral(t[x][1]) + "</i>: "; out = out + [line + ._html_traceback(@t[x]) + "</code><br>"]; } return .response(status, [@out, "</p>"]); . public make_obj_show_href arg obj, [name]; var line, oname; oname = obj.objname(); name = [@name, "<code>" + oname + "</code>"][1]; return "<a href=\"/bin/show?" + oname + "\">" + name + "</a>"; . public make_method_href arg m; return "<a href=\"/bin/list_method?" + m[1].objname() + "." + tostr(m[2]) + "()\">" + tostr(m[2]) + "(" + m[3] + ")</a>"; . public make_object_href arg obj, [args]; var line, name, href; name = [@args, 0][1]; if (!name) name = obj.namef('xref); href = [@args, "/bin/display?", "/bin/display?"][2]; return "<code><a href=\"" + href + obj.objname() + "\">" + name + "</a></code>"; . public bin_list_method arg [args]; var ref, str_ref, name, obj, code, anc, out, line, x; if (!args) return [400, .response(400, "Must specify a method reference")]; catch any { ref = $parse_lib.reference(args[1]); name = tosym(ref[2]); obj = $object_lib.to_dbref(ref[1]); anc = obj.find_method(name); code = anc.list_method(name); code = .filter_text(code); for x in [1 .. code.length()] line = " " + code[x]; str_ref = obj.objname() + "." + tostr(name) + "()"; out = ["<head><title>" + str_ref + "</title></head>"]; out = [@out, "<body><center><h1>" + str_ref + "</h1></center>"]; out = [@out, "<hr><pre>", @code, "</pre>"]; } with handler { switch (error()) { case ~methodnf: line = obj.objname() + "." + tostr(name) + "()"; return [400, .response(400, line + " not found.")]; default: return [400, .response(400, traceback()[1][2])]; } } return [200, out]; . public bin_who arg [args]; var who, namel, names, times, idle, realm, x, cols, out, output, line; out = ["<head><title>Connected users to " + $motd.server_name() + "</title>", "<center><h2>Connected users to <i>" + $motd.server_name() + "</i></h2></center></head><body><pre>"]; who = $user_db.connected(); names = who.map('hname); namel = []; for x in (who.map('name)) namel = [@namel, x.length()]; cols = namel.max() + 1; if (cols < 5) cols = 5; times = who.map('connected_time); cols = [cols, times.element_maxlength() + 1]; if (cols[2] < 7) cols = [cols[1], 7]; idle = who.map('idle_time); cols = [@cols, idle.element_maxlength() + 1]; if (cols[3] < 5) cols = cols.replace(3, 5); realm = who.map('realm_name, "text/html"); out = [@out, "<hr><b>" + "Name".pad(cols[1]) + " " + "On for".pad(cols[2]) + " " + "Idle".pad(cols[3]) + " Location", "----".pad(cols[1]) + " " + "------".pad(cols[2]) + " " + "----".pad(cols[3]) + " --------</b>"]; for x in [1 .. who.length()] { line = "<b>" + names[x] + "</b>" + "".pad(cols[1] - namel[x]) + " "; line = line + "<i>" + times[x] + "".pad(cols[2] - times[x].length()) + " "; line = line + idle[x] + "</i>" + "".pad(cols[3] - idle[x].length()) + " "; line = line + realm[x]; out = [@out, line]; } return [200, out]; . public filter_text arg text; var x, line; // embed's characters ('>' becomes '>' etc) for x in [1 .. text.length()] { if (text[x]) { line = text[x].replace("&", "&"); line = line.replace("<", "<"); line = line.replace(">", ">"); text = text.replace(x, line); } } return text; . public gateways return gateways; . public bin_display arg [args]; var out, obj; if (!args) return [400, .response(400, "Must specify an object")]; obj = (| $object_lib.to_dbref(args[1]) |); if (!obj) return [404, .response(404, "Unable to find object \"" + args[1] + "\"")]; return [200, ["<pre>", @obj.show_in_html(), "</pre>"]]; . public page_tail arg [args]; var tail; tail = "<hr size=4><a href=\"/\"><b>" + $motd.server_name() + "</b></a>"; if (args) return $buffer.from_string(tail); return [tail]; . public http_methods return http_methods; . public parse_traceback arg traceback; return ["<head><title>Internal System Error</title></head><body><center><h1>Internal System Error</h1></center><hr><h3>Traceback:</h3><pre>"] + .filter_text($parse_lib.traceback(traceback())) + ["</pre>"] + .page_tail(); . public list_gateways var out, line, gate; out = ["<ul>"]; for gate in (gateways) { line = "<li><b><a href=\"/bin/" + gate[2] + "\">" + gate[1] + "</a></b>"; out = [@out, line]; } return out + ["</ul>"]; . public make_href arg obj, [args]; var line, oname, method, name; oname = obj.objname(); name = [@args, "<code>" + oname + "</code>"][1]; method = [@args, "/bin/show?" + oname, "/bin/show?" + oname][2]; return "<a href=\"" + method + "\">" + name + "</a>"; . public make_href_static arg obj, [args]; var line, oname, method, name; oname = obj.objname(); name = [@args, "<code>" + oname + "</code>"][1]; method = [@args, "/bin/show?" + oname, "/bin/show?" + oname][2]; return "<a href=\"" + method + "\">" + name + "</a>"; . public process_bin_request arg [path]; var gate, who; if (!path) { return ["text/html", .list_gateways()]; } else { gate = path[1]; path = path.subrange(2); if ("?" in gate) { path = [gate.subrange(("?" in gate) + 1), @path]; gate = gate.subrange(1, ("?" in gate) - 1); } if (!(gate in gateways.keys())) return ["text/html", .get_error(400, "Unknown gateway \"" + gate + "\".")]; return ["text/html", .(tosym("bin_" + gate))(@path)]; } . public bin_describe arg [path]; var obj, desc, flags; if (!path) return [400, .response(400, "Must specify an object.")]; obj = (| $object_lib.to_dbref(path[1]) |) || (| $user_db.find(path[1]) |); if (!obj) return [404, .response(404, "Unable to find object \"" + path[1] + "\"")]; // this is a quick hack, .description should return in html return [200, .build_page(obj.get_description(#[['actor, $no_one]]), obj.name())]; . public bin_see arg [path]; return [400, .response(400, "VRML support is pending completion, sorry!")]; . public bin_project arg [path]; var project, name; if (!path) return [200, $projects.list_projects()]; name = path.to_string(); project = (| $object_lib.to_dbref(path.to_string()) |); if (!project) return [400, .respose(400, "<hr>Unable to find project \"" + name + "\".")]; return [200, project.generate_html()]; . public bin_help arg [str]; var node, head, tail, cout, list; if (!str) str = "$help_summary"; else str = str[1]; catch ~namenf { node = $object_lib.to_dbref(str); } with handler { return [404, .response(404, "Unable to find help node " + toliteral(str))]; } head = $buffer.from_strings(["<head><title>Help: " + node.name() + "</title></head>", "<body><h2 align=center>" + node.name() + "</h2><hr>"]); cout = $ctext_filter.filter(node.body(), #[['formatter, $cml2_html_format], ['node, node.objname()]]); tail = "<hr size=4><a href=\"/\"><b>" + $motd.server_name() + "</b></a> | <a href=\"/bin/help\">Help Summary</a>"; tail = $buffer.from_string(tail + "</body>"); switch (type(cout)) { case 'string: cout = [cout]; case 'frob: cout = `[]; } return [200, head.append(cout).append(tail)]; . public process_text arg what; var out, l, b; switch (type(what)) { case 'frob: return $ctext_filter.filter(what, #[['formatter, $cml2_html_format]]); case 'list: out = `[]; for l in (what) out = out.append(.process_text(l)); return out; case 'string: // "<br>" == `[60, 98, 114, 62] return `[60, 98, 114, 62].append($buffer.from_string(what)); } . public response arg code, message; var name, x; if (!name = (| codes[code] |)) return .response(500, "We had a booboo! Invalid code: " + tostr(code)); if (type(message) == 'string) message = ["<p align=center><b>" + message + "</b></p>"]; return ["<head><title>" + tostr(code) + " " + name + "</title></head>", "<body>", "<h1 align=center>" + tostr(code) + " " + name + "</h1>", "<hr>", @message, @.page_tail()]; . public html_version return html_version; . public build_page arg what, name; var out; return $buffer.append(`[60, 104, 101, 97, 100, 62, 60, 116, 105, 116, 108, 101, 62], $buffer.from_string(name)).append(`[60, 47, 116, 105, 116, 108, 101, 62, 60, 47, 104, 101, 97, 100, 62]).append(.process_text(what)); . public bin_object arg [args]; var out, obj; if (!args) return [400, .response(400, "Must specify an object")]; obj = (| $object_lib.to_dbref(args[1]) |); if (!obj) return [404, .response(404, "Unable to find object \"" + args[1] + "\"")]; return [200, obj.generate_html()]; . parent $libraries object $object_lib var $root trusted [] var $root inited 1 var $root objname 'object_lib var $root created_on 796268969 var $root flags ['parameters, 'methods, 'code, 'core] public to_dbref arg obj; var type, dbref; type = type(obj); switch (type) { case 'string: if (obj[1] == "$") { dbref = (| get_dbref(tosym(obj.subrange(2))) |); } else if (obj[1] == "#") { obj = obj.subrange(2); if ($string.is_numeric(obj)) dbref = (| todbref(toint(obj)) |); else throw(~objnf, "Cannot find object \"#" + obj + "\"."); } if (!dbref) dbref = (> get_dbref(tosym(obj.replace(" ", "_").lowercase())) <); return dbref; case 'dbref: return obj; default: return (> get_dbref(obj) <); } . public get_name arg obj, [args]; var meth; // get_name(obj, 'method, [args]) (3rd arg must be a list) if (!valid(obj)) return tostr(obj); meth = [@args, 'name][1]; args = [@args, [], []][2]; return obj.(meth)(@args); . public see_perms arg obj, [args]; var str, r, who, encapsulate; encapsulate = [@args, ["[", "]"]][1]; str = encapsulate[1]; if (obj.has_flag('core)) str = str + "*"; else str = str + "-"; if (obj.has_flag('fertile)) str = str + "f"; else str = str + "-"; if (obj.has_flag('methods, sender())) str = str + "m"; else str = str + "-"; if (obj.has_flag('parameters, sender())) str = str + "p"; else str = str + "-"; if (obj.has_flag('code, sender())) str = str + "c"; else str = str + "-"; return str + encapsulate[2]; . public str_to_objlist arg args; var out, x, obj; if ("," in args) args = args.explode_english_list(); else args = args.explode(); return .list_to_objlist(args); . public list_to_objlist arg args; var out, x, obj; out = #[['valid, []], ['invalid, []]]; for x in (args) { obj = (| .to_dbref(x) |); if (obj) out = out.add_elem('valid, obj); else out = out.add_elem('invalid, x); } return out; . public parse_method_flags arg flags; return " " + ('disallow_overrides in flags ? "d" | "-") + ('syncronized in flags ? "s" | "-") + ('locked in flags ? "l" | "-") + ('native in flags ? "n" | "-"); . parent $libraries object $integer var $root inited 1 var $root objname 'integer var $root created_on 796268969 var $root flags ['parameters, 'methods, 'code, 'core] public n_to_nth arg number; var tens_digit_is_1, ones_digit, single_digit; if (type(number) != 'integer) throw(~type, "Must receive an integer"); ones_digit = abs(number) % 10; tens_digit_is_1 = abs(number) / 10 % 10 == 1; single_digit = abs(number) < 10; if (ones_digit in [1, 2, 3] && !tens_digit_is_1) { switch (ones_digit) { case 1: return tostr(number) + "st"; case 2: return tostr(number) + "nd"; case 3: return tostr(number) + "rd"; } } else { return tostr(number) + "th"; } . public parse_range arg range_str; var r1, r2; // ("1-5") => (1, 5) -- 1, 5 // ("1-$") => (1, 'end) -- 1, 'end (end number) // (".-3") => ('cur, 3) -- 'cur (current number), 3 // ("#-3") => ('bgn, 3) -- 'bgn (beginning number), 3 range_str = $parse_lib.reference(range_str, "-"); r1 = range_str[1]; r2 = range_str[2]; // if (!r2) r2 = r1; if (!toint(r1)) { if (r1 == ".") r1 = 'cur; else if (r1 == "#") r1 = 'bgn; else throw(~type, "Beginning range invalid."); } else { r1 = toint(r1); } // if (!toint(r2)) { if (r2 == "$") r2 = 'end; else throw(~type, "Ending range invalid."); } else { r2 = toint(r2); } return [r1, r2]; . public to_english arg num; var num_str, sign; // 12500 => "12,500" // if (abs(num) < 9999) // return tostr(num); sign = num ? abs(num) / num | 1; num = abs(num); num_str = ""; while (num > 999) { num_str = "," + tostr(1000 + num % 1000).subrange(2) + num_str; num = num / 1000; } num_str = tostr(num) + num_str; return (sign == 1 ? "" | "-") + num_str; . public range arg x, y; var list, element; // creates a list of every number between x and y list = []; for element in [x .. y] list = list + [element]; return list; . parent $libraries object $parse_lib var $root inited 1 var $root objname 'parse_lib var $root created_on 796268969 var $root flags ['parameters, 'methods, 'code, 'core] var $parse_lib boolean_strs [["yes", "true", "1", "on"], ["no", "false", "0", "off"]] public reference arg string, [sep]; var middle, ref; // receives: "<object><seperator><method/param>" // returns ["<object>", "<method/param>"] // seperator defaults to a period. sep = [@sep, "."][1]; middle = sep in string; if (!middle) ref = [string, ""]; else if (middle == 1) ref = [sender().namef(['objname]), string.subrange(2)]; else ref = [string.subrange(1, middle - 1), string.subrange(middle + 1)]; // assumes "()" will appear at the end of the reference if at all, // and strips it off if present if ("()" in ref[2]) ref = [ref[1], ref[2].subrange(1, ("()" in ref[2]) - 1)]; return ref; . public object_match arg name, [who]; var msg; // .object_match("name"[, who]) // -> 0 name was the empty string // -> ~objnf nothing matched name // -> ~ambig more than one object matched name // Attempt to match an object name with who.match_environment(). If one is found, return it. Else, print a message and return one of the above false values. // 'who' defaults to sender(). who = who ? who[1] | sender(); if (!name) { (| who.tell("You must give the name of something.") |); return 0; } catch ~objnf, ~ambig { return who.match_environment(name); } with handler { switch (error()) { case ~objnf: msg = "I don't see any \"" + name + "\" here."; case ~ambig: msg = "I don't know which \"" + name + "\" you mean."; } (| who.tell(msg) |); return error(); } . public tell_error arg problem, [args]; var who, syntax, line, sprefix, prefix; // arg 1 == error // arg 2 (opt) == syntax // arg 3 (opt) == who // arg 4 (opt) == subbing object (in place of 'Object') -- string. syntax = [@args, 0][1]; who = [@args, sender(), sender()][2]; sprefix = (| sender().setting("error-syntax-prefix") |) || "=> "; prefix = (| sender().setting("error-prefix") |) || "! "; if (syntax) who.tell(sprefix + "Syntax: `" + syntax + "`"); if (problem) { if (type(problem) == 'string) { problem = $string.wrap_line(problem, (| who.linelen() |) || 79, prefix, 1); } else { for line in [1 .. problem.length()] problem = problem.replace(line, prefix + problem[line]); } who.tell(problem); } throw(~stop, "", 'no_traceback); . public usage arg method, [objname]; var code, extracted; // .usage(method[, objname]) // Extract initial comments from the given method, returning them as a list of strings. // Throw ~methodnf if objname does not define method. // objname defaults to sender. objname = objname ? objname[1] | sender(); objname = objname.find_method(method); code = objname.list_method(method); extracted = []; if (code[1] == "disallow_overrides;") code = code.delete(1); if (("arg " in code[1]) == 1) code = code.delete(1); if (("var " in code[1]) == 1) code = code.delete(1); while (!code[1]) code = code.delete(1); while (("//" in code[1]) == 1) { extracted = [@extracted, code[1].replace("//", "")]; code = code.delete(1); } return extracted; . public match arg string; var loc, obj; // called by $user.match_* methods, simply parses up the basic me/here/$* if (string == "me") return sender(); if (string == "here") return sender().location(); if (string && string[1] == "$") { obj = todbref(string.subrange(2)); if (!valid(obj)) throw(~objnf, "No such object " + string); return obj; } else { return 0; } . public boolean arg str; if (str in boolean_strs[1]) return 1; else if (str in boolean_strs[2]) return 0; else throw(~unknown, "Boolean flag not recognized."); . public full_reference arg str, [args]; var sep, defobj, middle, ref, type, match; defobj = [@args, sender()][1]; match = [@args, [$object_lib, 'to_dbref], [$object_lib, 'to_dbref]][2]; if ("()" in str) str = str.subrange(1, ("()" in str) - 1); if ("." in str) { type = 'method; sep = "."; } else if ("," in str) { type = 'parameter; sep = ","; } else { type = 'unknown; sep = "."; } middle = sep in str; if (!middle) ref = [(> match[1].(match[2])(str) <), ""]; else if (middle == 1) ref = [defobj, str.subrange(2)]; else ref = [(> match[1].(match[2])(str.subrange(1, middle - 1)) <), str.subrange(middle + 1)]; return [type, ref[1], ref[2] ? tosym(ref[2]) | 0]; . public traceback arg traceback, [args]; var line, out, pre, lines, cur, x, error; // $parse_lib.traceback(traceback(), lines, pre); // -1 lines represents the full error // pre is set to "! " unless otherwise specified. lines = [@args, -1][1]; pre = [@args, "! ", "! "][2]; error = [@args, 0, 0, 0][3]; // out = [pre + "=> " + traceback[1][2]]; pre = pre + " "; // if (error == 0) out = [@out, pre + "Thrown by " + ._traceback(@traceback[2].subrange(2))]; else out = [@out, pre + "Error " + toliteral(error) + " caused by " + ._traceback(@traceback[2].subrange(2))]; // for x in [1 .. traceback.length() - 2] { if (x <= lines || lines == -1) { line = $data_lib.unparse(traceback[x + 2][1]) + ": "; line = line + ._traceback(@traceback[x + 2].subrange(2)); out = [@out, pre + line]; } } return out; . public _traceback arg what, [more]; var line; if (more) { if (more[1] == more[2]) return $data_lib.unparse(more[1]) + "." + tostr(what) + "() line " + tostr(more[3]); else return $data_lib.unparse(more[2]) + "." + tostr(what) + "() (" + $data_lib.unparse(more[1]) + ") line " + tostr(more[3]); } else { return tostr(what); } . public options arg line, [defaults]; var loc, opt, x, out, defs; // this will not pay attention to groupings with quotes, should add // the functionality in later. // templates: #[["opt", [0/1, 0/1]]]; / #[['opt, [bool, value]]]; defaults = [@defaults, #[]][1]; if (!("-" in line || "+" in line)) return [line.explode(), defaults]; line = line.explode(); out = line; for x in [1 .. line.length()] { if (line[x][1] in ["-", "+"]) { out = out.setremove(line[x]); opt = line[x].subrange(2); defs = (| defaults[opt] |) || [0, ""]; defs = [line[x][1] in ["+"], defs[2]]; if (defs[2]) { if (line.length() >= x + 1) { defs = [defs[1], line[x + 1]]; out = out.setremove(line[x + 1]); } } defaults = defaults.add(opt, defs); } } return [out, defaults]; . public my_options arg line, options; var args, word, c, pos, key, p, p2; word = ""; args = ""; while (line) { c = line[1]; switch (c) { case "+": pos = " " in line; if (!pos) { key = line.subrange(2); line = ""; } else { key = line.subrange(2, pos); line = line.subrange(pos); } key = tosym(key); catch ~keynf { if (options[key][1] == 'bool) options = options.add(key, ['bool, 1]); else throw(~opttype, "Option " + tostr(key) + " is not boolean."); } with handler { throw(~badopt, "Option " + tostr(key) + " is not a valid option."); } case "-": pos = " " in line; if (!pos) { key = line.subrange(2); line = ""; } else { key = line.subrange(2, pos); line = line.subrange(pos); } key = tosym(key); catch ~keynf { if (options[key][1] == 'bool) options = options.add(key, ['bool, 0]); else throw(~opttype, "Option " + tostr(key) + " is not boolean."); } with handler { throw(~badopt, "Option " + tostr(key) + " is not a valid option."); } case "=": key = word; word = ""; pos = " " in line; if (!pos) pos = line.length(); key = tosym(key); catch ~keynf { if (options[key][1] == 'value) options = options.add(key, ['value, line.subrange(2, pos - 1)]); else throw(~opttype, "Option " + tostr(key) + " is not a value."); } with handler { throw(~badopt, "Option " + tostr(key) + " is not a valid option."); } line = line.subrange(pos + 1); case " ": args = args + word; word = ""; line = line.subrange(2); default: pos = " " in line; if (!pos) pos = line.length(); p = "=" in line; if (p > 0 && p < pos) { word = word + line.subrange(1, p - 1); line = line.subrange(p); } else { p = "-" in line; p2 = "+" in line; if (p2 < p) p = p2; if (p > 0 && p < pos) { args = args + line.subrange(1, p - 1); line = line.subrange(p); } else { args = args + line.subrange(1, pos); line = line.subrange(pos + 1); } } } } args = args + word; for key in (options.keys()) { word = options[key][2]; if (type(word) == 'string) word = $string.trim(word); options = options.keys(key, word); } return [args, options]; . public xreference arg str, [args]; var out, def, obj, reg, tmp, sep, member, p, obj, match; obj = [@args, sender()][1]; match = [@args, [sender(), 'match_environment, []], [sender(), 'match_environment, []]][2]; reg = $string.match_regexp("<.*>", str); if (reg) { def = str.subrange(reg[1][1] + 1, reg[1][2] - 2); tmp = str.subrange(1, reg[1][1] - 1); str = tmp + str.subrange(reg[1][1] + reg[1][2]); } if ("(" in str) str = str.subrange(1, ("(" in str) - 1); if ("." in str) { out = ['method]; sep = "."; } else if ("," in str) { out = ['variable]; sep = ","; } else { out = ['object]; } if (sep) { p = sep in str; member = tosym(str.subrange(p + 1)); if (p > 1) obj = str.subrange(1, p - 1); } else { obj = str; } if (type(obj) != 'dbref) obj = (> match[1].(match[2])(obj, @match[3]) <); if (def && type(def) != 'dbref) def = (> match[1].(match[2])(def, @match[3]) <); else def = obj; return out + [obj, def, member]; . public range arg str; var out; out = str.explode("-"); if (out.length() == 1) { out = [(> ._range(str) <), 'single]; } else if (out.length() == 2) { out = out.replace(1, (> ._range(out[1]) <)); out = out.replace(2, (> ._range(out[2]) <)); } else { throw(~range, "Invalid range reference."); } return out; . public _range arg str; if (str.is_numeric()) { return toint(str); } else { switch (str[1]) { case "$": return 'end; case ".": return 'current; case "^": return 'start; default: throw(~range, "Invalid range reference."); } } . public getopt arg line, [defaults]; var out, newlist, part, v, opt, t, templates, keys, key, l, x; // submit: [["template", value], [...]]; // => if value is 1, it will take the next part of the string // receive: [["template", "flag", bool, value]], [...]]; line = line.explode_quoted(); out = []; newlist = []; defaults = (| defaults[1] |) || []; templates = defaults.slice(1); x = 1; l = line.length(); while (1) { if (x > l) break; if (line[x][1] in ["-", "+"]) { opt = 0; v = ""; part = line[x].subrange(2); for t in [1 .. templates.length()] { if ("=" in part) { part = part.explode("="); v = (| part[2] |) || ""; part = part[1]; } if ($string.match_template(templates[t], part)) { opt = [templates[t], part, line[x][1] == "+"]; if ((| defaults[t][2] |) && !v) { if (x + 1 <= l) { x = x + 1; if (line[x] == "=") { if (x + 1 <= l) x = x + 1; } v = line[x]; } } opt = opt + [v]; } } if (!opt) opt = [0, part, line[x][1] == "+", ""]; out = out + [opt]; } else { newlist = newlist + [line[x]]; } x = x + 1; } return [newlist, out]; . public buildref arg type, obj, def, name; var line; line = obj.objname(); if (obj != def) line = line + "<" + def.objname() + ">"; if (type == 'object) return line; if (type == 'method) return line + "." + tostr(name) + "()"; if (type == 'parameter) return line + "," + tostr(name); . parent $libraries object $code_lib var $root inited 1 var $root objname 'code_lib var $root created_on 796268969 var $root flags ['parameters, 'methods, 'code, 'core] var $code_lib quotes [["\"Abandon all hope, ye who enter here.\""], ["\"Pull out Wedge, your not doing any more good back there.\"", "", "- Luke Skywalker, StarWars"], ["\"God is in the details.\""], ["\"I don't practice what I preach,", "because I'm not the type of person I'm preaching too.\"", "", "- Bob Dobbs"], ["\"I haven't shaved for six years.", "I seem to be cursed with a thin beard.\"", "", "- Calvin, Age 6 (of Calvin & Hobbes)"], ["\"I may be a Dreamer, but I'm not the only one.\"", "", "- John Lennon"], ["\"C code. C code run. Run, Code, Run! Please!?\"", "", "- Anonymous C hacker."], ["\"They who dream by day are cognizant of many things", "which escape those who dream only by night.\"", "", "- Edgar Allan Poe"], ["\"The good die first,", "and they whose hearts are dry as a summer dust", "burn to the socket.\"", "", "- William Wordsworth"], ["\"Banning guns to prevent murder", "is like banning word processors to prevent libel.\"", "", "- Unknown"], ["\"You will not be punished for your anger,", "you will be punished by your anger.\"", "", "- Buddha"], ["What part of:", "", "main() { printf(&unix[\"\\021%six\\012\\0\"],(unix)[\"have\"]+\"fun\"-0x60);}", "", "do you not understand?", "", "(taken from the 1987 Obfuscated C Code Contest)"], ["\"The goal of computer science is to build something that will", "last at least until we've finished building it.\""], ["\"Give me ambiguity or give me something else.\""], ["\"We are born naked, wet and hungry. Then things get worse.\""], ["\"Make it idiot proof and someone will make a better idiot.\""], ["\"Lottery: A tax on people who are bad at math.\""], ["\"There's too much blood in my caffeine system.\""], ["\"Artificial Intelligence usually beats real stupidity.\""], ["\"Ever notice how fast MS-Windows runs? Neither did I.\""], ["\"Very funny, Scotty. Now beam down my clothes.\""], ["\"Consciousness: that annoying time between naps.\""], ["\"The gene pool could use a little chlorine.\""], ["\"When there's a will, I want to be in it.\""], ["\"Change is inevitable, except from a vending machine.\""], ["\"MS-Windows is a virus:", "it takes over your computer and makes it run bad.\""], ["\"I have not failed 10,000 times,", "I have sucessfully found 10,000 ways that do not work.\"", "- Thomas Edison"], ["\"The difference between literature and journalism is", "that journalism is unreadable and literature is not read.\"", "", "- Oscar Wilde (1854-1900)"], ["\"The man who reads nothing at all is better educated", "than the man who reads nothing but newspapers.\"", "", "- Thomas Jefferson (1743-1826)"], ["\"In the mind of the beginner, there are many possibilities.", "In the mind of the expert there are few.\"", "", "- Shunryu Suzuki"], ["\"Time is a great teacher, but unfortunately it kills all of its pupils.\"", "", "- Hector Berlioz"], ["\"After I'm dead I'd rather have people ask", "why I have no monument, than why I have one.\"", "", "- Cato the Elder (234-249 B.C.)"], ["\"I loathe people who keep dogs. They are cowards who haven't", "got the guts to bite people themselves.\"", "", "-August Strindberg"], ["\"By the time I'd grown up, I natrually supposed that I'd be grown up.\"", "", "-Eve Babitz"], ["\"Every place has a spirit:", "it may be good, it may be bad", "it can be restful as eternity.", "This place-spirit can inhabit a book, a house, a town, a valley;", "the nature of the spirits is they remain.\"", "", "- William S. Burroughs"]] var $code_lib command_argument_types [['any, "any"], ['text, "text"], ['object, "object"], ['thing, "thing"], ['user, "user"], ['descendant, "descendant of *"], ['this, "this"], ['number, "number"]] public set_obj_param arg obj, param, val; var set_code; // set param on obj to val if (!(sender() == $root || $sys.is_admin(sender()))) throw(~perm, "Sender not admin or $root"); if (!valid(obj)) throw(~objnf, "Object " + $data_lib.unparse(obj) + " is not a valid object."); if (!(param in obj.parameters())) throw(~parmnf, "Parameter " + $data_lib.unparse(param) + " is not a parmater on " + $data_lib.unparse(obj) + "."); if ('__set_any in $obj.methods()) throw(~methexist, "Method '__set_any already defined on target object."); // Copy _set_any to obj set_code = .list_method('_set_var); obj.compile(set_code, '__set_var); // Set and delete method catch any { obj.__set_var(param, val); obj.del_method('__set_var); } with handler { obj.del_method('__set_var); rethrow(error()); } . public _set_var arg param, val; if (sender() != $code_lib) throw(~perm, "Sender not $code_lib"); return set_var(param, val); . public quotes return quotes; . public add_random_quote arg quote, [from]; if (!$sys.is_admin(sender())) throw(~perm, "Sender is not an owner"); if (type(quote) != 'string) throw(~type, "Quote must be given as a string."); quote = "\"" + quote + "\""; quote = $string.wrap_line(quote, 70); quote = from ? [@quote, " - " + from[1]] | quote; quotes = quotes + [quote]; . public generate_listing arg who, [args]; var meths, methval, input, output, element, header, title, cols, x, z, len, line, linea, y; // called by one of the who_cmds, does all the grunge work. title = [@args, "Connected Users"][1]; meths = [@args, [['name], ['connected_time], ['idle_time], ['realm_name]], [['name], ['connected_time], ['idle_time], ['realm_name]]][2]; header = [@args, ["Name", "On for", "Idle", "Location"], ["Name", "On for", "Idle", "Location"], ["Name", "On for", "Idle", "Location"]][3]; cols = [@args, [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]][4]; // get values using $list.map element = $list.map(who, meths[1][1], @meths[1].subrange(2)); input = []; for x in (element) { input = [@input, [x]]; if (x.length() > cols[1]) cols = cols.replace(1, x.length()); } // ok, get on with it. for x in [2 .. meths.length()] { methval = $list.map(who, meths[x][1], @meths[x].subrange(2)); for z in [1 .. methval.length()] { if (methval[z].length() > cols[x]) cols = cols.replace(x, methval[z].length()); input = input.replace(z, [@input[z], methval[z]]); } } // this will remove columns with no information in them. z = []; for x in [1 .. cols.length()] { if (!cols[x]) z = [@z, x]; } for x in (z) { cols = cols.delete(x); meths = meths.delete(x); header = header.delete(x); for y in [1 .. input.length()] input = input.replace(y, input[y].delete(x)); } // the header. len = (| sender().linelen() |) || 79; line = ""; linea = ""; for x in [1 .. cols.length()] { line = line + header[x].pad(cols[x] + 2); linea = linea + "".pad(header[x].length(), "-").pad(cols[x] + 2); } output = ["--- " + title + " (" + tostr(input.length()) + ") ---"]; output = [@output, line.pad(len)]; output = [@output, linea.pad(len)]; // tell the rest: for x in (input) { line = ""; for z in [1 .. cols.length()] line = line + x[z].pad(cols[z] + 2); output = [@output, line.pad(len).trim()]; } return [@output]; . public random_quote var which; which = random(quotes.length()); if (which) return quotes[which]; return []; . public valid_email arg email; var host, user, ip, tmp; email = email.explode("@"); if (email.length() != 2) return ['invalid, email, ""]; // if we want we can do something overly extensive with this, but we will not user = email[1]; host = email[2]; return ['valid, user, host]; if (toint(host[1])) { tmp = hostname(host); if (tmp == "-1") return ['invip, user, host]; } else { tmp = $sys.ip(host); if (tmp == "-1") return ['invhostname, user, host]; } return ['valid, user, host]; . public unparse_command arg command; var x, line; // command should be passed as a list, and can either be a command // or shortcut. This will return a string. if (command.length() == 2) return toliteral(command[1]); line = ""; for x in (command[3]) { if (type(x) == 'string) line = line + (line ? " " | "") + x; else line = line + (line ? " " | "") + "%" + tostr(x); } return "\"" + command[1] + "\" => \"" + line + "\""; . public parse_name arg name; var article, args, flag; // used to parse $named names and aliases. args = $parse_lib.getopt(name, [["u?nique"], ["p?roper"], ["n?ormal"]]); flag = args[2]; name = args[1].to_string(); flag = (| flag[flag.length()] |) || ["n?ormal", "n", 1, ""]; switch (flag[1]) { case "p?roper": article = 'prop; case "u?nique": article = 'uniq; default: // n?ormal article = 'normal; } name = name.explode(","); return [[name[1], article], name.subrange(2)]; . public random_word arg [args]; var x, out, min, max, con, vow, flag, lcon, lvow, extra; min = [@args, 5][1]; max = [@args, 9, 9][2]; extra = [@args, "", "", ""][3]; x = random(max - min) + min; out = ""; con = "bcdfghjklmnpqrstvwxz" + extra; vow = "aeiouy"; lcon = con.length(); lvow = vow.length(); while (out.length() < x) { if (!flag) out = out + con[random(lcon)]; else out = out + vow[random(lvow)]; flag = !flag; } return out; . public punctuation_type arg str; var end; end = str.length(); switch (str[end]) { case "!": return "exclaim"; case "?": return "ask"; case ".": return "say"; case ")": if (end > 1) { switch (str[end - 1]) { case ";": return "wink"; case ":": return "smile"; case "8": return "grin"; default: return "say"; } } case "(": if (end > 1 && str[end - 1] in [":", "8"]) return "frown"; } return "say"; . public check_encrypted arg cstr, str; return str.crypt(cstr.subrange(1, 2)) == cstr; . public user_type arg user; var p; // The reason for this is because the parents list may get messed up // if they add/remove parents. p = user.parents(); if ($user in p) return 'user; else if ($builder in p) return 'builder; else if ($programmer in p) return 'programmer; else if ($admin in p) return 'admin; else return 'none; . public command_argument_types return command_argument_types; . public get_command_argument_type arg type; var x, m; for x in [1 .. command_argument_types.length()] { m = $string.match_pattern(command_argument_types[x][2], type); if (type(m) == 'list) return [command_argument_types[x][1], m]; } throw(~command, "Invalid command argument type \"" + type + "\""); . public verify_code arg code, method; var line, m, warns; warns = []; method = "\\." + tostr(method) + "\\("; for line in [1 .. code.length()] { m = $string.match_regexp(method, code[line]); if (m) { warns = warns + ["Warning: Possible Recursion, line " + tostr(line) + ":"]; warns = warns + [" " + code[line]]; warns = warns + ["".pad(m[1][1] + 2, "-") + "".pad(m[1][2] - 2, "^")]; } } return warns; . public default_description_flags return #[['prose, 1], ['contents, 1], ['extra, 1], ['visibility, 1], ['actor, sender()], ['exclude, []], ['brief, 0]]; . public generate_object_listing arg objs, multi, [args]; var line, obj, col, name, fmt, out; if (!objs) { out = ["** None **"]; } else { col = ((| sender().linelen() |) || 79) / 10; fmt = "%3L%" + tostr(col * 4) + "L %" + tostr(col) + "L %" + tostr(col) + "R "; out = [fmt.format("#", "Name", "Perms", "Size") + "Manager"]; col = col * 4; for obj in (objs) { line = fmt.format(obj.(multi)(@args).length(), obj.namef('xref), $object_lib.see_perms(obj, ["", ""]), obj.size()); name = obj.manager().namef('xref); if (name.length() > col) name = name.pad(col); out = out + [line + name]; } } return out; . parent $libraries object $list var $root inited 1 var $root objname 'list var $root created_on 796268969 var $root flags ['parameters, 'methods, 'code, 'core] public to_string arg list, [sep]; var str, part; // uses $data_lib.unparse() rather than tostr() if (!list) return ""; sep = [@sep, " "][1]; str = tostr(list[1]); for part in (list.delete(1)) str = str + sep + tostr(part); return str; . public to_english arg list, [options]; var empty, and, sep; // uses $data_lib.unparse() rather than tostr() empty = [@options, "nothing"][1]; switch (list.length()) { case 0: return empty; case 1: return tostr(list[1]); } and = [@options, " and ", " and "][2]; sep = [@options, ", ", ", ", ", "][3]; return .to_string(list.delete(list.length()), sep) + and + tostr(list[list.length()]); . public map arg list, method, [args]; var out, x; // call 'method on each object, return results. out = []; for x in (list) out = [@out, x.(method)(@args)]; return out; . public filter arg list, method, [args]; var out, x; // similar to .map, but returns a list of objects which returned a // true value from 'method. out = []; for x in (list) { if (x.(method)(@args)) out = [@out, x]; } return out; . public sort arg list, [sortby]; // calls ._sort(). Does not set an element to sort by yet, but should // eventually will have to fix. return ._sort(list, 1, list.length()); . public _sort arg lst, x, y; var p, i, j; switch (y - x + 1) { case 0, 1: return lst; case 2: if (lst[x] <= lst[y]) return lst; p = lst[x]; lst = lst.replace(x, lst[y]); lst = lst.replace(y, p); return lst; case 3: if (lst[x] <= lst[x + 1]) { if (lst[x + 1] <= lst[y]) { } else if (lst[x] <= lst[y]) { p = lst[x + 1]; lst = lst.replace(x + 1, lst[y]); lst = lst.replace(y, p); } else { p = lst[x]; lst = lst.replace(x, lst[y]); lst = lst.replace(y, lst[x + 1]); lst = lst.replace(x + 1, p); } } else if (lst[x] <= lst[y]) { p = lst[x]; lst = lst.replace(x, lst[x + 1]); lst = lst.replace(x + 1, p); } else if (lst[x + 1] <= lst[y]) { p = lst[x]; lst = lst.replace(x, lst[x + 1]); lst = lst.replace(x + 1, lst[y]); lst = lst.replace(y, p); } else { p = lst[x]; lst = lst.replace(x, lst[y]); lst = lst.replace(y, p); } return lst; } p = lst[x]; i = x; j = y; while (1) { while (i < j && p <= lst[j]) j = j - 1; if (i == j) break; lst = lst.replace(i, lst[j]); i = i + 1; while (i < j && p >= lst[i]) i = i + 1; if (i == j) break; lst = lst.replace(j, lst[i]); j = j - 1; } lst = lst.replace(i, p); lst = ._sort(lst, x, i - 1); lst = ._sort(lst, i + 1, y); return lst; . public columnize arg list, cols, [rest]; var width, lines, line, separator, linelength, curcol; // turn [...] into ". . ." // rest[1]==separator; rest[2]==linelength separator = [@rest, " "][1]; linelength = [@rest, 78, 78][2]; width = linelength / cols - separator.length(); lines = []; while (list) { line = list[1].pad(width); list = list.subrange(2); for curcol in [2 .. cols] { if (list) { line = line + separator + list[1].pad(width); list = list.subrange(2); } } lines = [@lines, line]; } return lines; . public reverse arg list; var elm, reversed; // .reverse(list) // -> list with its elements reversed reversed = []; for elm in (list) reversed = [elm, @reversed]; return reversed; . public compress arg list; var out, last, x; // [a,a,b,b,c,c,d,d] => [a,b,c,d] // removes duplicate entries in a list out = []; for x in (list) { if (!(x in out)) out = [@out, x]; } return out; . public last arg list; return list[list.length()]; . public count arg elem, list; var count; // count of elem in list while (elem in list) { count = count + 1; list = list.subrange((elem in list) + 1); } return count; . public element_maxlength arg list; var elm, max, len; for elm in (list) { len = tostr(elm).length(); if (len > max) max = len; } return max; . public nth_element_maxlength arg lists, element; var list, max, len; // Returns longest string whose index is element in one of the lists in lists. if (type(element) != 'integer) throw(~type, "First argument is not an integer"); if (type(lists) != 'list) throw(~type, "Second argument is not a list"); max = 0; for list in (lists) { len = tostr(list[element]).length(); if (len > max) max = len; } return max; . public numbered_text arg text; var line; // receives a list of strings, returns that list with line numbers pre-pended for line in [1 .. text.length()] text = text.replace(line, (line < 10 ? " " | "") + tostr(line) + ": " + text[line]); return text; . public slice arg big_list, element; var list, ret_list; // Return elementh' element of all lists in big_list // No type or length checking done for speed purposes. ret_list = []; for list in (big_list) ret_list = [@ret_list, list[element]]; return ret_list; . public swap arg list, a, b; var holder; // swap elements at indexes a and b holder = (> list[a] <); list = (> list.replace(a, list[b]) <); list = list.replace(b, holder); return list; . public max arg list; // return greatest element of list (no type checking performed) // if list is [], returns 0 while (list.length() > 1) { if (list[1] > list[2]) list = list.delete(2); else list = list.delete(1); } return [@list, 0][1]; . public min arg list; // return least element of list (no type checking performed) // if list is [], returns 0 while (list.length() > 1) { if (list[1] < list[2]) list = list.delete(2); else list = list.delete(1); } return [@list, 0][1]; . public lcolumnize arg list, [args]; var line, part, lines, max, cols, col, width, len, sep; len = [@args, (| sender().linelen() |) || 79][1]; sep = [@args, "", ""][2]; lines = []; line = ""; max = .element_maxlength(list) + sep.length(); cols = len > max ? len / max | 1; width = len / cols - sep.length(); col = cols; for part in (list) { col = col - 1; if (!col) { lines = lines + [line + part]; line = ""; col = cols; continue; } line = line + part.pad(width); } if (line) return lines + [line]; return lines; . public swapsort arg list, [sort_by]; var bot_elem, cur_elem, elem, compare; // note: iterative implementation allows sorts of extra-long lists elem = [@sort_by, 1]; compare = [@sort_by, 'gt, 'lt][2]; for bot_elem in [1 .. list.length()] { for cur_elem in [bot_elem + 1 .. list.length()] { if (._swap_compare(list[bot_elem], list[cur_elem], compare, elem)) list = $list.swap(list, bot_elem, cur_elem); } } return list; . public _swap_compare arg elem1, elem2, compare, [elem]; elem = [@elem, 1][1]; switch (compare) { case 'lt: return elem1[elem] < elem2[elem]; case 'gt: return elem1[elem] > elem2[elem]; default: return 0; } . public heapsort arg list, [sort_by]; var heap, sort_type, sort_elem; sort_elem = [@sort_by, 1][1]; sort_type = [@sort_by, 'gt, 'gt][2]; switch (sort_type) { case 'gt: heap = $small_first_heap_class.new(list, sort_elem); default: return list; } list = []; while (heap.length()) { list = heap.element(1); heap = heap.del(1); } return list; . public map_to_english arg list, method, [args]; // because I (Lynx) am lazy return .to_english(.map(list, method, @args)); . public map_to_string arg list, method, [args]; // because I (Lynx) am lazy return .to_string(.map(list, method, @args)); . public flatten arg list; var toret, elem; // [[[x], x], x] => [x, x, x] toret = []; for elem in (list) { if (type(elem) == 'list) toret = toret + .flatten(elem); else toret = toret + [elem]; } return toret; . public sum arg ints; var ret; // returns a sum of each integer in the list. ret = 0; while (ints) { ret = ret + ints[1]; ints = ints.delete(1); } return ret; . public non_alphanumeric // returns nun-alphanumeric in a list of characters return ["!", "@", "#", "$", "%", "^", "&", "*", "(", ")", "_", "+", "-", "=", "~", "`", "'", "{", "}", "[", "]", "|", "/", "?", "\"", "\\", ",", ".", "<", ">", ";", ":", " "]; . public numbers // returns a list of numbers return ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"]; . public alphabet //returns the alphabet in a list return ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"]; . public center_lines arg lines, width, [args]; var output, line; output = []; for line in (lines) output = [@output, $string.center(line, width, @args)]; return output; . public to_buffer arg [args]; return (> $buffer.from_strings(@args) <); . public delete arg [args]; return (> delete(@args) <); . public replace arg [args]; return (> replace(@args) <); . public chop arg list, [count]; // chops the last <count> elements off the list. // return [] if count is longer then the list. count = count || 1; return (| list.subrange(1, list.length() - count) |) || []; . public join arg l1, l2; var last, first; // Combines l1 and l2 by appending the first element of l2 to the last // of l1. if (type(l2) != 'list) l2 = [l2]; last = (| l1.last() |) || ""; first = (| l2[1] |) || ""; l1 = [@l1.chop(), last + first]; if (l2.length() > 1) l1 = l1 + l2.subrange(2); return l1; . public lmap arg list, method, [args]; var out, x, s; //call methods for each thing in list on sender() out = []; s = sender(); for x in (list) out = [@out, s.(method)(x, @args)]; return out; . public length arg l; return listlen(l); . public union arg [args]; return (> union(@args) <); . public omap arg list, object, method, [args]; var out, obj; // calls object.method(obj, @args) for each obj in list out = []; for obj in (list) out = [@out, object.(method)(obj, @args)]; return out; . public del arg list, element; return (> list.setremove(element) <); . public add arg list, element; return (> list.setadd(element) <); . public set_difference arg [args]; var set, list, element; // Usage: diff(set 1, set 2, ..., set n) // Returns all elements of set 1 that are not in sets 2..n if (!args) return []; set = args[1]; for list in (args.delete(1)) { for element in (list) set = set.setremove(element); } return set; . public set_contains arg [args]; var super, list, element; // True if the first list given is a superset of all subsequent lists. // False otherwise. [] is a superset of [] and nothing else; anything is // a superset of []. If only one list is given, return true. super = args ? args[1] | []; for list in (args.delete(1)) { for element in (list) { if (!(element in super)) return 0; } } return 1; . public set_equal arg set1, set2; var element; // True if the two lists given contain the same elements. // False otherwise. while (set1) { element = set1[1]; if (!element in set2) return 0; while (element in set2) set2 = set2.setremove(element); while (element in set1) set1 = set1.setremove(element); } return set2 == []; . public fold arg list, object, method, [args]; var i, out; // apply object.method to a current result and the next element, return the // result if (list == []) return 0; out = list[1]; for i in (list.subrange(2, list.length() - 1)) out = object.(method)(out, i, @args); return out; . public setadd arg [args]; return (> setadd(@args) <); . public intersection arg l1, l2; var i, out; // set intersection if the arguments out = []; for i in (l1) { if (i in l2) out = out.setadd(i); } return out; . public setremove arg [args]; return (> setremove(@args) <); . public insert arg [args]; return (> insert(@args) <); . public subrange arg [args]; return (> sublist(@args) <); . public msort arg list, [keys]; keys = keys ? keys[1] | list; if (listlen(list) != listlen(keys)) throw(~invarg, "Invalid key list - the list lengths must be the same."); if (!list) return []; return (._merge_sort(list, keys))[1]; // 9-25-95/21:26 Jenner ($jenner), moved from $jenner.msort . private _merge_sort arg list, keys; var i, j, l1, k1, l2, k2, n1, n2, n; n = listlen(list); if (n == 1) return [list, keys]; n1 = n / 2; n2 = n - n1; l1 = ._merge_sort(list.subrange(1, n1), keys.subrange(1, n1)); k1 = l1[2]; l1 = l1[1]; l2 = ._merge_sort(list.subrange(n1 + 1, n2), keys.subrange(n1 + 1, n2)); k2 = l2[2]; l2 = l2[1]; list = []; keys = []; i = 1; j = 1; if (n > 30) pause(); while (i <= n1 && j <= n2) { if (k1[i] <= k2[j]) { list = [@list, l1[i]]; keys = [@keys, k1[i]]; i = i + 1; } else { list = [@list, l2[j]]; keys = [@keys, k2[j]]; j = j + 1; } } return [[@list, @l1.subrange(i), @l2.subrange(j)], [@keys, @k1.subrange(i), @k2.subrange(j)]]; . public prefix arg list, prefix; var out, elem; out = []; for elem in (list) out = out + [prefix + elem]; return out; . public valid_objects arg list; var obj; for obj in (list) { if (!valid(obj)) list = list.setremove(obj); } return list; . parent $libraries object $security var $root objname 'security var $root created_on 796593414 var $root inited 1 var $root flags ['parameters, 'methods, 'code, 'core] var $security valid_flags ['indestrucable, 'fertile, 'methods, 'parameters, 'code] public valid_flags return valid_flags; . public index arg flag; if (!flag in valid_flags) throw(~type, "Invalid flag."); return flag in valid_flags; . parent $libraries object $help_lib var $root objname 'help_lib var $root created_on 805931416 var $root inited 1 var $root flags ['parameters, 'methods, 'code, 'core] var $help_lib default_node $help_summary var $help_lib default_index $help_index_root public default_node return default_node; . public default_index return default_index; . public find_help_node arg what, type; var pos, node, current, indices, l; current = (| sender().current_node() |) || .default_node(); switch (type) { case 'index: indices = sender().help_indices(); l = indices.length(); while (l && !node) { node = indices[l].find_help_node(what); l = l - 1; } if (node) return node; else throw(~nonode, "Unable to find help on \"" + what + "\"."); case 'link: for node in (current.keys().links()) { if ($string.match_begin(node, what)) return (current.links())[node]; } throw(~nonode, "No node link \"" + what + "\" found on current node."); default: // Up/Down nodes need to be redone for groups } return 0; . public history_cap return 15; . public parse_reference arg str; var node, current, indices, l, links; if (str[1] in ["$", "#"]) { node = (> $object_lib.to_dbref(str) <); if (!node.has_ancestor($help_node)) throw(~nonode, "\"" + str + "\" is not descended from $help_node."); return node; } links = ((| sender().current_node() |) || .default_node()).links(); for node in (links.keys()) { if ($string.match_begin(node, str)) return links[node]; } indices = (| sender().help_indices() |) || [.default_index()]; node = 0; l = indices.length(); while (l && !node) { node = indices[l].find_help_node(str); l = l - 1; } return node || throw(~nonode, "Unable to find help on \"" + str + "\"."); . public group_nodes_in_html arg nodes, noemph, [args]; var name, names, n; names = []; for n in (nodes) { if (n in noemph) name = n.name(); else name = .node_name_in_html(n); names = [@names, name]; } return names.to_english(@args); . public node_name_in_html arg node; return "<a href=\"/bin/help?" + node.objname() + "\">" + node.name() + "</a>"; . parent $libraries object $ctext_lib var $root objname 'ctext_lib var $root created_on 799277513 var $root inited 1 var $root flags ['parameters, 'methods, 'code, 'core] parent $libraries parent $mail_root object $mail_lib var $root inited 1 var $root objname 'mail_lib var $root created_on 796268969 var $root indestructable 1 var $root flags ['parameters, 'methods, 'code, 'core] var $mail_lib mail_system [$mail_message, $mail_list, $mail_ui, $mail_lib] public mail_name arg obj; if (!obj.has_ancestor($mail_list)) throw(~type, "Object is not a child of $mail_recipient"); if (obj.has_ancestor($user)) return obj.namef().replace(" ", "-"); return "*" + obj.namef().replace(" ", "-"); . public has_mail_perms arg [args]; var obj; for obj in (args) { if (!(obj in mail_system) && !$sys.is_system(obj)) return 0; } . public match_mail_recipient arg name; var mname, list; catch ~namenf, ~objnf { if (name[1] == "*") { list = "list"; return $mail_db.find(name.subrange(2)); } else { list = "user"; } return sender().find_object(name, 'environment, 'user, 'grasp); } with handler { throw(~listnf, "No " + list + " found by the name \"" + name + "\"."); } . public range_to_actual arg r, current; var start, end; if (type(r[1]) == 'symbol) { switch (r[1]) { case 'end: if (type(r[2]) != 'symbol) throw(~range, "Backwards range."); start = current['list].mail().length(); case 'start: start = 1; case 'current: start = current['location] in current['list].mail(); } } else { start = r[1]; } if (type(r[2]) == 'symbol) { switch (r[2]) { case 'end: end = current['list].mail().length(); case 'single: end = start; case 'start: throw(~range, "Backwards range."); case 'current: end = current['location] in current['list].mail(); } } else { start = r[2]; } if (start > end) throw(~range, "Backwards range."); return [start, end]; . parent $libraries object $time_lib var $root inited 1 var $root objname 'time_lib var $root created_on 796268969 var $root flags ['parameters, 'methods, 'code, 'core] parent $libraries object $data_lib var $root inited 1 var $root objname 'data_lib var $root created_on 796268969 var $root flags ['parameters, 'methods, 'code, 'core] public unparse arg data, [unparse]; var str, element, association, pos, method; unparse = [@unparse, #[]][1]; switch (type(data)) { case 'integer, 'float: return tostr(data); case 'string: method = (| unparse['string] |) || 'toliteral; return $string.(method)(data); case 'symbol: return toliteral(data); case 'error: return toliteral(data); case 'buffer: return toliteral(data); case 'dbref: method = (| unparse['dbref] |) || ['objname]; return $object_lib.get_name(data, @method); case 'list: if (!data) return "[]"; str = "["; for element in (data.subrange(1, data.length() - 1)) { str = str + $data_lib.unparse(element); str = str + ", "; } str = str + $data_lib.unparse(data[data.length()]); return str + "]"; case 'dictionary: if (!data) return "#[]"; str = "#["; for association in (data) { str = str + $data_lib.unparse(association); str = str + ", "; } return str.subrange(1, str.length() - 2) + "]"; case 'frob: catch any { return data.unparse(); } with handler { return toliteral(data); } } . public verify_type arg value, type; var elem, type_elem, ok_flag; // returns true if type(value) is type, or in the case // of lists and dicts it checks the elements // // If type is a list or dict, the elements it contains are possible types for value // for example: .verify_value([['foo], 1],['integer, 'list, ['symbol]]) => 1 // To indicate that you don't care what the elements of a dict or list are, // simply use 'list or 'dictionary. if (type(value) == type) return 1; if (type(type) in ['dictionary, 'list] && type(type) == type(value)) { for elem in (value) { ok_flag = 0; for type_elem in (type) { if (.verify_type(elem, type_elem)) { ok_flag = 1; break; } if (!ok_flag) return 0; } } return 1; } // value is not of type, or values elements are not of @type, or etc return 0; . parent $libraries object $symbol var $root objname 'symbol var $root created_on 811822782 var $root inited 1 var $root flags ['parameters, 'methods, 'code, 'core] public to_string arg sym; return tostr(sym); . parent $misc object $tree var $root child_index 5 var $root fertile 1 var $root inited 1 var $root objname 'tree var $root created_on 796268969 var $root indestructable 1 var $root flags ['parameters, 'methods, 'code, 'fertile, 'core] var $tree parents_by_tree 0 var $tree children_by_tree 0 var $tree tree_parents 0 var $tree tree_children 0 public parent_nodes arg node; return tree_parents[node]; . public child_nodes arg node; return tree_children[node]; . public unlink_nodes arg parent, child; var parents, kids; (> .perms(sender(), 'writers) <); parents = .parent_nodes(child); kids = .child_nodes(parent); parents = parents.setremove(parent); kids = kids.setremove(child); tree_children = tree_children.add(parent, kids); tree_parents = tree_parents.add(child, parents); . public _del_links arg n, node; var nodes; //delete links from n to node nodes = tree_parents[n]; nodes = nodes.delete(node in nodes); tree_parents = tree_parents.add(n, nodes); nodes = tree_children[n]; nodes = nodes.delete(node in nodes); tree_children = tree_children.add(n, nodes); . public link_nodes arg parent, child; var parents, kids; (> .perms(sender(), 'writers) <); parents = .parent_nodes(child); kids = .child_nodes(parent); parents = parents.setadd(parent); kids = kids.setadd(child); tree_children = tree_children.add(parent, kids); tree_parents = tree_parents.add(child, parents); . root init_tree tree_parents = #[]; tree_children = #[]; . root uninit_tree parents_by_tree = 0; children_by_tree = 0; . public del_node arg node; var n, kids, parents, nodes; (> .perms(sender(), 'writers) <); kids = tree_children[node]; tree_children = tree_children.del(node); parents = tree_parents[node]; tree_parents = tree_parents.del(node); for n in (kids) { nodes = tree_parents[n]; nodes = nodes.delete(node in nodes); tree_parents = tree_parents.add(n, nodes); } for n in (parents) { nodes = tree_children[n]; nodes = nodes.delete(node in nodes); tree_children = tree_children.add(n, nodes); } . public add_node arg node; (> .perms(sender(), 'writers) <); tree_children = tree_children.add(node, []); tree_parents = tree_parents.add(node, []); . parent $misc object $db var $root inited 1 var $root objname 'db var $root created_on 796268969 var $root indestructable 1 var $root flags ['parameters, 'methods, 'code, 'core] var $db database #[] root init_db database = #[]; . public database return database; . public value_changed arg key, new_value; // change the value of a key. (> .remove(key) <); (> .insert(key, new_value) <); . public remove arg key; // remove a key/value from the database //THIS: is breaking the user_db (quick comment fix :) // .perms(sender(), 'writer); database = database.del(key); . public exact_match arg key; var match; // get an exact match of a key, return the value match = (| database[key] |); if (match == ~keynf) throw(~matchnf, "No object by that key exists in the database."); return match; . public match_begin arg key; var matches, entry; // use match_begin of the key, return the value matches = [(| .exact_match(key) |)]; if (!matches[1]) { matches = []; for entry in (database) { if ($string.match_begin(entry[1], key)) matches = [@matches, entry[2]]; } } if (matches) { if (matches.length() == 1) return matches[1]; else throw(~ambig, "More than one object matches that key.", matches); } else { throw(~matchnf, "No entries in the database match that key."); } . public insert arg key, value; // insert a key/value to the database // .perms(sender(), 'writer); database = database.add(key, value); . root uninit_db database = 0; . public key_changed arg old_key, new_key; var val; // change the value of a key. val = (> database[old_key] <); .remove(old_key); .insert(new_key, val); . parent $misc object $user_parsers var $root child_index 9 var $root fertile 1 var $root trusted [] var $root inited 1 var $root objname 'user_parsers var $root created_on 796268969 var $root indestructable 1 var $root flags ['parameters, 'methods, 'code, 'fertile, 'core] public parse arg user, str, next_parser, [other_parsers]; // Minimum parser routine. return next_parser.parse(user, str, @other_parsers); . parent $misc object $trie var $root objname 'trie var $root created_on 800074237 var $root inited 1 var $root flags ['parameters, 'methods, 'code, 'core] var $trie data 0 public find_key arg trie, key; var char, n; if (!key) { if (!trie[1]) throw(~ambig, "Trie: ambiguous match."); else return trie[1]; } if (!n = key[1] in trie[2]) throw(~keynf, "Trie: key not found."); else return (> .find_key(key.subrange(2), trie[n + 2]) <); . public add arg trie, key, [values]; var n; if (!key) return trie.replace(1, [key, @values]); if (!n = key[1] in trie[2]) return [@trie.replace(2, trie[2] + key[1]), .add([0, ""], key.subrange(2), @values)]; return trie.replace(n + 2, .add(trie[n + 2], key.subrange(2), @values)); . public del arg trie, key; var n; if (!key) return trie.replace(1, 0); if (!n = key[1] in trie[2]) return trie; return trie.replace(n + 2, .del(trie[n + 2], key.subrange(2))); . parent $misc object $filters var $root child_index 1 var $root inited 1 var $root objname 'filters var $root created_on 796268969 var $root indestructable 1 var $root flags ['parameters, 'methods, 'code, 'core] public compress arg input; var e, output; // only goes 1 element deep--sorry, anybody sending anything past that will // be shot. output = []; if (type(input) == 'list) { for e in (input) { if (type(e) == 'list) output = [@output, @e]; else output = [@output, e]; } } else { output = [input]; } return output; . parent $misc object $lock_parser var $root inited 1 var $root objname 'lock_parser var $root created_on 796268969 var $root indestructable 1 var $root flags ['parameters, 'methods, 'code, 'core] public parse arg s, env; var stack, lock, n, m, obj, len, reg; stack = []; s = " " + s; s = s.replace(" or ", " || "); s = s.replace(" and ", " || "); s = s.replace(" not ", " !"); while (1) { // Look for valid prefixes. while (1) { while (s && s[1] == " ") s = s.subrange(2); if (!s) throw(~parse, "String ends unexpectedly."); if (s[1] == "(") { stack = stack + ['open]; s = s.subrange(2); } else if (s[1] == "!") { stack = stack + ['not]; s = s.subrange(2); } else { break; } } // Look for an object name or tag for n in [1 .. s.length()] { if (s[n] in ")&|") { n = n - 1; break; } } m = n; while (m && s[m] == " ") m = m - 1; if (!m) throw(~parse, "Null object obj_name."); // try and match it if (lock = (| env.match_environment(s.subrange(1, m)) |)) { obj = (> env.match_environment(s.subrange(1, m)) <); lock = $object_lock_frob.new(obj); } else { switch (s.subrange(1, m)) { case "any", "true", "anybody": lock = $true_lock_frob.new(); case "none", "false", "nobody": lock = $false_lock_frob.new(); default: throw(~parse, "Invalid lock tag \"" + s.subrange(1, m) + "\""); } } stack = stack + [lock]; s = s.subrange(n + 1); // Loop until no more reduction to be done. while (1) { // Process negations, ands, ors. while (1) { len = stack.length(); if (len < 2) break; if (stack[len - 1] == 'not) { lock = $not_lock_frob.new(stack[len]); stack = stack.subrange(1, len - 2) + [lock]; } else if (stack[len - 1] == 'and) { lock = $and_lock_frob.new(stack[len - 2], stack[len]); stack = stack.subrange(1, len - 3) + [lock]; } else if (stack[len - 1] == 'or) { lock = $or_lock_frob.new(stack[len - 2], stack[len]); stack = stack.subrange(1, len - 3) + [lock]; } else { break; } } // Close parens, if necessary; otherwise stop. if (!s || s[1] != ")") break; while (s && s[1] == ")") { len = stack.length(); if (len < 2 || stack[len - 1] != 'open) throw(~parse, "Misplaced right parenthesis."); stack = stack.subrange(1, len - 2) + [stack[len]]; s = s.subrange(2); while (s && s[1] == " ") s = s.subrange(2); } } // Are we done? if (!s) { if (stack.length() > 1) throw(~parse, "Unmatched left parentheses."); return stack[1]; } // No, we're at a conjunction. if (s[1] == "&") { stack = stack + ['and]; s = s.subrange(3); } else if (s[1] == "|") { stack = stack + ['or]; s = s.subrange(3); } else { throw(~parse, "Illegal character following right parenthesis."); } } . parent $utilities object $cml2 var $root objname 'cml2 var $root child_index 3 var $root created_on 806017887 var $root inited 1 var $root flags ['parameters, 'methods, 'code, 'core] parent $utilities object $world var $root fertile 1 var $root inited 1 var $root objname 'world var $root created_on 796268969 var $root flags ['parameters, 'methods, 'code, 'fertile, 'core] var $world starting_place 0 public daylight // should eventually return something like 'day 'night 'dusk 'dawn return 'day; . public starting_place return starting_place || $body_cave; . parent $utilities object $root_evaluator var $root child_index 2 var $root fertile 1 var $root inited 1 var $root objname 'root_evaluator var $root created_on 796268969 var $root flags ['parameters, 'methods, 'code, 'fertile, 'core] var $root_evaluator append_str "_stmt" var $has_messages messages 0 public eval_ctext arg vars, term; var vars; // message is the message to be evaluated. // times is a list of the symbols that should be processed. // times = [] processes all symbols. if (type(term) != 'list) throw(~type, "Term must be a list. Was " + $data_lib.unparse(term)); if ('time in vars.keys()) { if (type(vars['time]) != 'symbol) throw(~type, "Time must be a symbol."); } else { vars = vars.add('time, 'pre); } vars = vars.add('force, 1).add('delay, 0).add('debug, 0); vars = ._eval_ctext(vars, term); if ('process in vars.keys()) return vars; else return $ctext_frob.new(vars['result]); . public apply arg vars, list, method, [args]; var l, output; // call method once for each element in list. // the element is passed as the first argument. output = []; if (args) { for l in (list) { vars = .(method)(vars, [l, @args]); output = [@output, vars['result]]; } } else { for l in (list) { vars = .(method)(vars, l); output = [@output, vars['result]]; } } if (output.length() > 1) return vars.add('result, ['list_type, output]); else if (output.length() == 1) return vars.add('result, output[1]); else return vars.add('result, ['list_type, []]); . public list_type arg vars, term; var t, output, output2; output = []; for t in (term) { if (type(t[1]) == 'list) t = t[1]; vars = ._eval_ctext(vars, t); output = [@output, vars['result]]; } return vars.add('result, ['list_type, output]); . public parse_command arg text; var output, ret_val, term, word, final, first_term, final_args, token; output = []; term = []; word = ""; while (text) { ret_val = text.split_on_next(["\"", "{", "%", "&", "[", " ", "}"]); word = ret_val[1]; token = ret_val[2]; text = ret_val[3]; switch (token) { case "{": output = ._handle_word(output, term); ret_val = .parse_command(text); output = [@output, ret_val[1]]; text = ret_val[2]; case "[": output = ._handle_word(output, term); ret_val = .parse_list(text); output = [@output, ret_val[1]]; text = ret_val[2]; case "%": output = ._handle_word(output, term); ret_val = .parse_varref(text); output = [@output, ret_val[1]]; text = ret_val[2]; case "\"": output = ._handle_word(output, term); ret_val = .parse_string(text); output = [@output, ret_val[1]]; text = ret_val[2]; case " ": output = ._handle_word(output, word); case "}": output = ._handle_word(output, word); if (type(output[1]) != 'list) output = [output]; first_term = output[1]; if (first_term[1] == 'string_type) { first_term = tosym(first_term[2] + "_stmt"); final_args = []; } else { first_term = 'eval_stmt; final_args = [first_term]; } if (output.length() > 1) final_args = [@(final_args + output.subrange(2))]; return [[first_term, final_args], text]; } } . public normalize arg args; var key, new; // turns ctext style data into Coldc data switch (args[1]) { case 'dictionary_type: new = #[]; for key in (args[2].keys()) new = new.add(key, .normalize(args[2][key])); return new; case 'list_type: new = []; for key in (args[2]) new = [@new, .normalize(key)]; return new; default: return args[2]; } . public fix_values arg stuff; var key, new; switch (type(stuff)) { case 'dictionary: new = #[]; for key in (stuff) new = new.add(key[1], .fix_values(key[2])); return new; case 'list: new = []; for key in (stuff) new = [@new, .fix_values(key)]; return ['list_type, new]; case 'symbol: return ['symbol_type, stuff]; case 'string: return ['string_type, stuff]; case 'integer: return ['integer_type, stuff]; case 'dbref: return ['dbref_type, stuff]; } . public _truth arg value; var result; switch (value[1]) { case 'symbol_type: return 1; case 'integer_type: return value[2]; case 'string_type: if (value[2] == "0" || value[2] == "") return 0; else return 1; case 'list_type: return value[2].length(); default: return ">>ERROR: Argument to condtional not a value<<"; } . public parse_list arg text; var output, ret_val, term, word, token, int; output = []; term = []; word = ""; while (text) { ret_val = text.split_on_next(["[", "]", "(", "\"", "%", "&", " "]); word = ret_val[1]; token = ret_val[2]; text = ret_val[3]; switch (token) { case "(": output = ._handle_word(output, word); vars = .parse_command(text); output = [@output, vars['result]]; text = vars['text]; case "[": output = ._handle_word(output, word); vars = .parse_list(text); output = [@output, vars['result]]; text = vars['text]; case "%": output = ._handle_word(output, word); vars = .parse_varref(text); output = [@output, vars['result]]; text = vars['result]; case "\"": output = ._handle_word(output, word); ret_val = .parse_string(text); output = [@output, vars['result]]; text = vars['result]; case " ": output = ._handle_word(output, word); case "]": output = ['list_type, ._handle_word(output, word)]; vars = vars.add('text, text); return vars.add('result, output); } } . public parse_string arg text; var output, word, ret_val, is_text, token; output = []; word = ""; is_text = 0; while (text) { ret_val = text.split_on_next(["\"", "{", "%", "&"]); word = ret_val[1]; token = ret_val[2]; text = ret_val[3]; switch (token) { case "{": output = ._handle_word(output, word); ret_val = .parse_command(text); output = [@output, ret_val[1]]; text = ret_val[2]; is_text = 1; case "%": output = ._handle_word(output, word); ret_val = .parse_varref(text); output = [@output, ret_val[1]]; text = ret_val[2]; is_text = 1; case "&": output = ._handle_word(output, word); ret_val = .parse_charref(text); output = [@output, ret_val[1]]; text = ret_val[2]; is_text = 1; case "\"": output = ._handle_word(output, word); if (is_text) output = ['text_stmt, output]; if (output.length() == 1) output = output[1]; return [output, text]; } } return [output, text]; . public parse_charref arg text; var pos; pos = ";" in text; return [['char_type, text.subrange(1, pos - 1)], text.subrange(pos + 1)]; . public parse_varref arg text; var output, ret_val, word, token; output = []; word = ""; while (text) { ret_val = text.split_on_next(["{", "%", "&", ";"]); word = ret_val[1]; token = ret_val[2]; text = ret_val[3]; switch (token) { case "{": output = ._handle_word(output, word); ret_val = .parse_command(length, text); output = [@output, @ret_val[1]]; text = ret_val[2]; case "%": output = ._handle_word(output, word); ret_val = .parse_varref(length, text); output = [@output, @ret_val[1]]; text = ret_val[2]; case "&": output = ._handle_word(output, word); ret_val = .parse_charref(length, text); output = [@output, @ret_val[1]]; text = ret_val[2]; case ";": output = ._handle_word(output, word); return [['get_stmt, output], text]; } } . parent $utilities object $has_hooks var $root objname 'has_hooks var $root child_index 1 var $root fertile 1 var $root created_on 809174672 var $root inited 1 var $root flags ['parameters, 'methods, 'code, 'fertile, 'core] var $has_hooks hooks #[] public hooks return hooks.keys(); . public add_hook arg hook; (> .perms(sender(), 'writer) <); hooks = hooks.add(hook, []); . public del_hook arg hook; (> .perms(sender(), 'writer) <); hooks = hooks.del(hook); . public set_hook arg hook; var ret; if (sender() in hooks[hook]) return 1; catch ~methodnf { ret = .(tosym("accept_" + tostr(hook) + "_hook"))(sender()); } with handler { ret = 1; } if (!ret) throw(~perm, "Hook not allowed."); hooks = hooks.add(hook, [@hooks[hook], sender()]); (| .(tosym("record_" + tostr(hook) + "_hook"))(sender()) |); . public unset_hook arg hook; if (sender() in hooks[hook]) { hooks = hooks.add(hook, hook.delete(sender() in hooks[hook])); (| .(tosym("abort_" + tostr(hook) + "_hook"))(sender()) |); } . protected call_hook arg hook, [args]; var objects, method, o; //Notify all hooked objects that the hook has been triggered normally. objects = hooks[hook]; method = tosym("hook_" + tostr(hook) + "_triggered"); for o in (objects) (| o.(method)('normal, @args) |); . public remove_hook arg hook; (> .perms(sender(), 'writers) <); hooks = hooks.add(hook, hooks[hook].delete(sender() in hooks[hook])); . public init_has_hooks hooks = #[]; . parent $utilities object $lag_watcher var $root inited 1 var $root objname 'lag_watcher var $root created_on 796268969 var $root flags ['parameters, 'methods, 'code, 'core] var $lag_watcher lags [0, 0, 0, 0, 0, 0, 0, 0, 0, 0] var $lag_watcher last_time 813386635 public startup // Called by $sys.startup() (> .perms(sender(), 'manager) <); lags = []; last_time = time(); $heart.add_heartbeat(14); . public update arg lag; // Called by .pulse() every 15 minutes (> .perms(sender(), 'this) <); if (type(lags) != 'list) lags = []; while (lags.length() > 9) lags = lags.delete(1); lag = lag > 15 ? lag - 15 | 0; lags = [@lags, lag]; . public lag_str return "Current server lag is " + .lag() + " seconds."; . public lag var lag, total, weight, lag_i, lag_d; // the current lag floated total = 0; weight = 0; for lag in (lags) { weight = weight + 1; total = total + lag * weight; } lag_i = total / 55; lag_d = tostr((total - lag_i * 55) * 10 / 55).subrange(1, 1); return tostr(lag_i) + "." + lag_d; . public verbose_lag_str // returns lag as a string with verbosity return ["Current server lag is " + .lag() + " seconds.", $data_lib.unparse(lags)]; . public value var lag, total, weight, lag_i; // unparsed lag value total = 0; weight = 0; for lag in (lags) { weight = weight + 1; total = total + lag * weight; } lag_i = total / 55; return lag_i; . public pulse var lag; // Called by $heart every 15 mins (> .perms(sender(), $heart) <); lag = time() - last_time; last_time = time(); .update(lag); . parent $utilities object $channels var $root inited 1 var $root objname 'channels var $root created_on 796268969 var $root flags ['parameters, 'methods, 'code, 'core] public announce arg channel, text, [args]; var user, name, line, exempt, listeners; if (!.can_send_to(channel, caller(), sender())) throw(~perm, "Sorry, unable to send to that channel."); name = [@args, 'objname][1]; if (!name && !(channel in ['login, 'System])) name = 'objname; exempt = [@args, [], []][2]; listeners = .listeners(channel).set_difference(exempt); if (args.length() > 2) args = args.subrange(3); else args = []; line = "<" + tostr(channel); if (name) line = line + " - " + sender().(name)(); line = line + ": " + text + ">"; for user in (listeners) { if ((| user.connected() |)) user.tell(line, 'channel, channel, @args); } . public listeners arg channel; switch (channel) { case 'System: return $programmer.descendants(); case 'admin: return $admin.children(); default: return $user_db.connected(); } . public can_send_to arg channel, caller, sender; switch (channel) { case 'System, 'all: if ($sys.is_system(sender)) return 1; case 'login: if (caller == $user) return 1; default: return 1; } return 0; . parent $utilities object $places var $root inited 1 var $root objname 'places var $root created_on 796268969 var $root flags ['parameters, 'methods, 'code, 'core] var $places default_place $nowhere var $places exit_starting_place $void var $places starting_place $the_pit var $places default_new_place $place var $places coordinate_shortcuts #[["n?orth", [0, 0]], ["s?outh", [180, 0]], ["e?ast", [90, 0]], ["w?est", [270, 0]], ["ne|northeast", [45, 0]], ["se|southeast", [135, 0]], ["nw|northwest", [225, 0]], ["sw|southwest", [315, 0]], ["d?own", [-1, -90]], ["u?p", [-1, 90]]] var $places known_realms [$realm_of_creation] var $places build_hints #[[1, <$ctext2_frob, [["This is the do-it-all system for building places. At any time you can enter \"@abort\" to abort building. To turn off these hints \"@set experienced\" in your regular command environment.", <$ctext_format, ["hr", #[], #[], [], 'do_hr]>], #[['line, 1], ['this, $places], ['time, 'pre], ['sender, $places], ['evaluator, $cml2_base_eval]]]>], [2, <$ctext2_frob, [["The specified destination does not exist, therefore a new one will be created with the name you specified.", <$ctext_format, ["hr", #[], #[], [], 'do_hr]>], #[['line, 1], ['this, $places], ['time, 'pre], ['sender, $places], ['evaluator, $cml2_base_eval]]]>], [3, <$ctext2_frob, [["Name aliases can be specified on the same line as the name. This is done by seperating them from the name with commas. Any number of aliases can be specified in this manner (such as \"Name, alias, alias, alias\"). Names types can be defined by appending ", <$ctext_format, ["tt", #[], #[], ["+type"], 'do_tt]>, ", where ", <$ctext_format, ["tt", #[], #[], ["type"], 'do_tt]>, " is one of ", <$ctext_format, ["tt", #[], #[], ["proper"], 'do_tt]>, ", ", <$ctext_format, ["tt", #[], #[], ["unique"], 'do_tt]>, " or ", <$ctext_format, ["tt", #[], #[], ["normal"], 'do_tt]>, ". Not specifying a type defaults to ", <$ctext_format, ["tt", #[], #[], ["normal"], 'do_tt]>, ".", <$ctext_format, ["hr", #[], #[], [], 'do_hr]>], #[['line, 1], ['this, $places], ['time, 'pre], ['sender, $places], ['evaluator, $cml2_base_eval]]]>], [4, <$ctext2_frob, [["Realms are used to keep locations in relation with each other. To get a list of commonly known realms type ", <$ctext_format, ["tt", #[], #[], ["@realms"], 'do_tt]>, ".", <$ctext_format, ["hr", #[], #[], [], 'do_hr]>], #[['line, 1], ['this, $places], ['time, 'pre], ['sender, $places], ['evaluator, $cml2_base_eval]]]>], [5, <$ctext2_frob, [["Coordinates are used to define a basic relation between locations by pointing in the direction each place is. They use the radial/azimuth system. More help on Coordinates can be found in help under ", <$ctext_format, ["tt", #[], #[], ["places"], 'do_tt]>, ". For now it may be easier to use a coordinate shorcut (such as ", <$ctext_format, ["tt", #[], #[], ["up"], 'do_tt]>, "). To get a list of coordinate shortcuts type ", <$ctext_format, ["tt", #[], #[], ["@shortcuts"], 'do_tt]>, " now. Note: coordinates are automatically inverted for return exits (so if you specify ", <$ctext_format, ["tt", #[], #[], ["down"], 'do_tt]>, " the return exit will use the coordinates of ", <$ctext_format, ["tt", #[], #[], ["up"], 'do_tt]>, ").", <$ctext_format, ["hr", #[], #[], [], 'do_hr]>], #[['line, 1], ['this, $places], ['time, 'pre], ['sender, $places], ['evaluator, $cml2_base_eval]]]>]] public place arg which; which = tosym(tostr(which) + "_place"); return (> get_var(which) <); . public is_place arg obj; if (!obj.has_ancestor($place)) throw(~place, "Object \"" + obj.namef('ref) + "\" is not a place."); . public set_place arg which, obj; .perms(sender(), 'manager); (> .is_place(obj) <); if (!(which in .parameters())) throw(~place, toliteral(which) + " is not a valid entry try one of: " + toliteral(.parameters())); set_var(which, obj); . public coordinates arg str; var x; for x in (coordinate_shortcuts) { if ($string.match_template(x[1], str)) return x[2]; } throw(~coordnf, "Unable to find coordinate shortcut for \"" + str + "\"."); . public coordinate_shortcuts return coordinate_shortcuts; . public valid_coordinates arg radial, azimuth; if (radial > 360 || radial < -1) throw(~invcoord, "Radial coordinate must be from -1 to 360 degrees."); if (azimuth > 90 || azimuth < -90) throw(~invcoord, "Azimuth coordinate must be from 90 to -90 degrees."); . public invert_coordinates arg radial, azimuth; radial = radial + 180; if (radial > 360) radial = radial - 360; if (azimuth > 0) azimuth = -azimuth; else azimuth = abs(azimuth); return [radial, azimuth]; . public known_realms return known_realms; . public match_realm arg str; var r; for r in ($realms_frob.descendants()) { if (r.match_name(str)) return r; } return (| $object_lib.to_dbref(str) |) || 0; . public add_known_realm arg obj; (> .perms(sender()) <); known_realms = [@known_realms, obj]; . public del_known_realm arg obj; (> .perms(sender()) <); known_realms = known_realms.setremove(obj); . public del_build_hint arg hint_key; (> .perms(sender()) <); build_hints = build_hints.add(hint_key); . public build_hint arg hint; return build_hints[hint]; . public build_hints return build_hints; . public add_build_hint arg hint_key, hint_text; (> .perms(sender()) <); build_hints = build_hints.add(hint_key, hint_text); . parent $utilities object $motd var $root inited 1 var $root objname 'motd var $root created_on 796268969 var $root flags ['parameters, 'methods, 'code, 'core] var $motd server_name "ColdCore" var $motd notes [] var $motd server_title "Virtual Environment Server" var $motd connect_help ["Connection HELP", "===============", "", "Connecting as a guest: 'connect-guest <name> <email>'", " Example: 'connect-guest John Doe johnd@site.usa.com'", "", "Connecting as a user: 'connect <name> <password>'", " Example: 'connect John Doe mypassword'", "", "Quitting (this screen): '@quit' or 'quit'", "", "Connected User's Listing: '@who' or 'who'"] public build arg [args]; var output, out; output = []; if (!args) args = ['long, 'quote]; if (args[1] == 'default) args = ['name, "", 'title, "", "", 'quote, "", 'notes, "", 'admins, 'connected, 'core_version, 'driver_version]; while (args) { if (type(args[1]) == 'string) { output = output + [""]; } else { switch (args[1]) { case 'long: args = args.delete(1); args = ['title, 'long_name] + args; continue; case 'short: args = args.delete(1); args = ['title, 'name] + args; continue; case 'title: out = $string.center(server_title, 79); output = output + [out]; case 'name: out = $string.center("+ " + server_name + " +", 79); output = output + [out]; case 'notes: out = $list.center_lines(notes, 79); output = output + out; case 'quote: out = $list.center_lines($code_lib.random_quote(), 79); output = output + out; case 'admins: out = $list.to_english($list.map($sys.admins(), 'namef)); out = $string.center("Administrators: " + out, 79); output = output + [out]; case 'connected: out = "Currently Connected users: "; out = out + tostr($user_db.connected().length()); out = $string.center(out, 79); output = output + [out]; case 'version: args = args.delete(1); args = ['driver_version, 'core_version] + args; continue; case 'driver_version: out = "Driver: " + $sys.server_info('driver_version, 'long); output = output + [$string.center(out, 79)]; case 'core_version: out = "Core: " + $sys.server_info('core_version, 'long); output = output + [$string.center(out, 79)]; } } args = args.delete(1); } return output; . public set_motd arg what, value; .perms(sender()); if (!(what in .parameters())) throw(~motd, toliteral(what) + " is not a valid motd parameter, try one of: " + toliteral(.parameters())); if (!(type(value) in ['string, 'list])) throw(~motd, "Value must be sent as a string or a list of strings."); set_var(what, value); . public build_html arg [args]; return ["<head><title>" + server_name + "</title></head>", "<body>", "<p align=center><img src=\"/tCD.gif\" alt=\"The Cold Dark\"></p>", "<h3 align=center>" + server_title + "</h3>", "<p align=center><tt>", @$code_lib.random_quote(), "</tt></p>", "<p align=center>", @notes, "</p>", "<p align=center>Administrators: " + $sys.admins().map('hname).to_english() + "<br>", "<a href=\"/bin/who\">Currently Connected users</a>: " + tostr($user_db.total_connected()) + "<br>", "Server Lag: " + $lag_watcher.lag() + " seconds.<br>", "Driver: <b><a href=\"http://cold.org:8080/\">ColdX Genesis</a></b> " + $sys.server_info('driver_version), "<br>Core: <b>" + $sys.server_info('core_version, 'long) + "</b>", "<p align=center><a href=\"telnet://" + $sys.server_info('server_hostname) + ":" + tostr($login_daemon.current_port()) + "\"><b><i>Enter the Cold Dark</i></b></a>", "<p align=center>The Cold Dark is a Virtual Environment System. There is no game in the Cold Dark, the purpose is to create a core which expands the physicality of a Virtual Environment. To further explore the database, follow the <a href=\"/start.html\">Database Starting Points</a> link.</p>", "<hr>", "<p align=center>", "<a href=\"/bin/project/\"><b>Projects List</b></a> |", "<a href=\"/history.html\"><b>History</b></a> |", "<a href=\"/features.html\"><b>Features</b></a> |", "<a href=\"http://cold.org:8080/Intro/\"><b>Introduction</b></a> |", "<a href=\"/start.html\"><b>DB Starting Points</b></a>", "</p>", @$http_lib.page_tail()]; . public server_name return server_name; . public server_title return server_title; . public connect_help return connect_help; . public set_connect_help arg text; (> .perms(sender(), 'manager) <); connect_help = text; . parent $utilities object $heart var $root inited 1 var $root objname 'heart var $root created_on 796268969 var $root flags ['parameters, 'methods, 'code, 'core] var $heart heart_failures [] var $heart hearts [[$lag_watcher, 813386635, 14]] public pulse var robot, h; // send every robot that has a heart a pulse, if needed. for robot in [1 .. hearts.length()] { if (hearts[robot][2] + hearts[robot][3] < time()) { hearts = hearts.replace(robot, [hearts[robot][1], time(), hearts[robot][3]]); (| hearts[robot][1].pulse() |); } } . public add_heartbeat arg [delay]; var p; delay = [@delay, 60][1]; for p in [1 .. hearts.length()] { if (hearts[p][1] == sender()) { hearts = hearts.replace(p, [sender(), 0, delay]); return; } } hearts = [@hearts, [sender(), 0, delay]]; . public del_heartbeat var h, pos; h = []; for pos in [1 .. hearts.length()] { if (hearts[pos][1] == sender()) { if (pos > 1) h = [@s, hearts.subrange(1, pos - 1)]; if (pos < hearts.length()) h = [@h, hearts.subrange(pos + 1)]; hearts = h; return; } } throw(~objnf, "Sender (" + tostr(sender()) + ") does not have a heartbeat."); . parent $utilities object $projects var $root objname 'projects var $root created_on 799192627 var $root inited 1 var $root flags ['parameters, 'methods, 'code, 'core] var $projects lists #[['bugs, []], ['suggested, []], ['considered, []], ['accepted, []], ['rejected, []], ['completed, []]] public add_list arg list; (> .perms(sender()) <); if (!lists) lists = #[]; if (type(list) != 'symbol) throw(~type, "Lists must be submitted as a symbol."); lists = lists.add(list, []); . public del_list arg list; var p; (> .perms(sender()) <); if (!(| lists[list] |)) throw(~listnf, "List " + toliteral(list) + " is not found in list index."); for p in (lists[list]) p.change_list_to(0); lists = lists.del(list); . public add_project_to_list arg list, project; (> .perms(sender()) <); if (type((| lists[list] |)) == 'error) throw(~listnf, "List " + toliteral(list) + " is not found in list index."); if (!project.has_ancestor($project)) throw(~project, "Invalid project."); lists = lists.add_elem(list, project); project.change_list_to(list); . public del_project_from_list arg list, project; (> .perms(sender()) <); if (!(| lists[list] |)) throw(~listnf, "List " + toliteral(list) + " is not found in list index."); if (!project.has_ancestor($project)) throw(~project, "Invalid project."); lists = lists.del_elem(list, project); project.change_list_to(list); . public list_projects var list, project, out, line; out = ["<head><title>" + $motd.server_name() + " Projects List</title><center><img src=\"/tCD.gif\"><p><i><b><font size=+1>PROJECTS LIST</font></b></i></center></head>", "<body>"]; for list in (lists.keys()) { if (!lists[list]) continue; out = out + ["<hr width=50% align=center><center><font size=+1><b>" + tostr(list).capitalize() + " Projects</b></font></center>", "<pre>", "<i><b>Project Developers</b></i>"]; for project in (lists[list]) out = out + ["<a href=\"/bin/project?" + project.objname() + "\"><b>" + project.name() + "</b></a>" + $string.fill(40 - project.name().length()) + " " + project.developers().map('hname).to_english()]; out = out + ["</pre>"]; } return out + ["</pre>"]; . public lists return lists; . public set_project_in_list arg list, project; var l; // this removes project from any existing list and inserts to desired list (> .perms(sender()) <); if (!(| lists[list] |)) throw(~listnf, "List " + toliteral(list) + " is not found in list index."); if (!project.has_ancestor($project)) throw(~project, "Invalid project."); for l in (lists.keys()) { if (project in list[l]) (| .del_project_from_list(l, project) |); } (> .add_project_to_list(l, project) <); . parent $utilities object $scheduler var $root objname 'scheduler var $root created_on 810294797 var $root inited 1 var $root flags ['parameters, 'methods, 'code, 'core] var $scheduler task_index 1 var $scheduler blocked_tasks #[] var $scheduler task_queue [] var $scheduler sub_schedulers [$heart] var $scheduler expected_lag 0 var $scheduler server_lag 0 public sleep arg howlong; .add_task(howlong, 'resume_job, task_id()); $sys.suspend(); . public remove_first_task var len, i, min; // sender must be an agent, or admin catch any { if (caller() != this()) throw(~perm, "Invalid call to private method"); len = task_queue.length(); i = 1; while (i != len) { min = len; if (i * 2 < len && task_queue[i * 2][2] < task_queue[min][2]) min = i * 2; if (i * 2 + 1 < len && task_queue[i * 2 + 1][2] < task_queue[min][2]) min = i * 2 + 1; task_queue = task_queue.replace(i, task_queue[min]); i = min; } task_queue = task_queue.subrange(1, len - 1); } with handler { // $sys.log(traceback()); } if (!task_queue) task_index = 1; . public task_queue // sender must be system, for now (> .perms(sender(), 'system) <); return task_queue; . public del_task arg tid; var task; // sender must be system, for now. (> .perms(sender(), 'system) <); if (type(tid) != 'integer) throw(~type, "Task Identification must be an integer"); for task in (task_queue) { if (task[1] == tid) { task_queue = task_queue.delete(task in task_queue); return 1; } } throw(~tasknf, "No task found by that TID"); . public add_task arg time, method, [args]; var task, i, tid, flags, x, y, tmpq, task_time; // use `@info $scheduler' for more information. // [tid, time, time(), sender(), caller(), method, flags, args] // time is seconds from insertion time that it will be run (ie 300 == 5 mins) // if (type(time) != 'integer || type(method) != 'symbol || type(args) != 'list) throw(~type, "Arguments are not an integer, symbol, and list."); if (time < 1) throw(~time, "Time is negative."); if (time > 31536000) throw(~time, "Try to schedule a task LESS than a year from now?"); // task_index = task_index + 1; tid = task_index; // flags can be set in a system only add_task, for now set them as 'system flags = ['system]; task = [tid, time, time(), sender(), caller(), method, flags, args]; task_queue = task_queue + [task]; i = task_queue.length(); // // while (i > 1 && task[2] < task_queue[i / 2][2] + task_queue[i / 2][3]) { // task_queue = task_queue.replace(i, task_queue[i / 2]); // i = i / 2; // } task_queue = task_queue.replace(i, task); tmpq = []; while (task_queue) { y = 1; task_time = task_queue[1][2] + task_queue[1][3]; for x in [1 .. task_queue.length()] { if (task_time > task_queue[x][2] + task_queue[x][3]) { y = x; task_time = task_queue[y][2] + task_queue[y][3]; } } tmpq = tmpq + [task_queue[y]]; task_queue = task_queue.delete(y); } task_queue = tmpq; return tid; . public pulse var task, sub; // called by $sys.heartbeat if (caller() != $sys) throw(~perm, "Sender is not system"); while (task_queue && time() > task_queue[1][2] + task_queue[1][3]) { task = task_queue[1]; (| ._run_task(task) |); .remove_first_task(); } // call sub schedulers for sub in (sub_schedulers) (| sub.pulse() |); . public _run_task arg task; var code, args, a; // called by $scheduler only if (caller() != this()) throw(~perm, "Caller is not this"); catch any { // setup the args by hand, becuase we use eval and it expects a string args = task[8]; if (args) { for a in [1 .. args.length()] args = args.replace(a, $data_lib.unparse(args[a])); args = $list.to_string(args, ","); } else { args = ""; } code = "." + tostr(task[6]) + "(" + args + ");"; // run it through eval as the sender(): // task[5].eval([code], task[4]); task[5].as_this_run(task[5], task[6], task[8]); } with handler { // bounce the errors to the person, or to the system board if it's 'system //catch any { (| task[4].tell(["SCHEDULER ERROR: ", @traceback()]) |); // } with handler { // if ('system in task[7]) { // $channels.announce('System, traceback()[1]); // $channels.announce('System, "task: " + $data_lib.unparse(task)); // } // } } . public sys_add_task arg time, method, sender, caller, flags, [args]; var task, i, tid, x, y, tmpq, task_time; // use `@info $scheduler' for more information. // [tid, time, time(), sender(), caller(), method, flags, args] // if (!$sys.is_agent(sender())) throw(~perm, "Sender is not an agent or admin, use .add_task()"); if (type(time) != 'integer || type(method) != 'symbol || type(args) != 'list) throw(~type, "Arguments are not an integer, symbol, and list."); if (time < 1) throw(~time, "Time is negative."); if (time > 31536000) throw(~time, "Try to schedule a task LESS than a year from now?"); if (!valid(sender)) throw(~type, "The argument for sender is not a valid object"); if (!valid(caller)) throw(~type, "The argument for caller is not a valid object"); if (type(flags) != 'list) throw(~type, "Send flags as a list of symbols"); // task_index = task_index + 1; tid = task_index; // flags can be set in a system only add_task, for now set them as 'system task = [tid, time, time(), sender, caller, method, flags, args]; task_queue = task_queue + [task]; // i = task_queue.length(); while (i > 1 && task[2] < task_queue[i / 2][2] + task_queue[i / 2][3]) { task_queue = task_queue.replace(i, task_queue[i / 2]); i = i / 2; } task_queue = task_queue.replace(i, task); tmpq = []; while (task_queue) { y = 1; task_time = task_queue[1][2] + task_queue[1][3]; for x in [1 .. task_queue.length()] { if (task_time > task_queue[x][2] + task_queue[x][3]) { y = x; task_time = task_queue[y][2] + task_queue[y][3]; } } tmpq = tmpq + [task_queue[y]]; task_queue = task_queue.delete(y); } task_queue = tmpq; return tid; . public add_sub_scheduler arg object; if (!$sys.is_admin(sender())) throw(~perm, "Only admins may add sub schedulers."); if (type(object) != 'dbref) throw(~type, "Object must be a dbref."); sub_schedulers = [@sub_schedulers, object]; . public del_sub_scheduler arg object; var pos, s; if (!$sys.is_admin(sender())) throw(~perm, "Only admins may delete sub schedulers."); if (type(object) != 'dbref) throw(~type, "Object must be a dbref."); pos = object in sub_schedulers; if (!pos) throw(~objnf, "Object not a sub scheduler."); s = []; if (pos > 1) s = [@s, sub_schedulers.subrange(1, pos - 1)]; if (s < sub_schedulers.length()) s = [@s, sub_schedulers.subrange(pos + 1)]; sub_schedulers = s; . public has_blocked_tasks arg ident; return blocked_tasks.contains(ident); . public block_task arg ident; var tasks; // I want to be atomic! // Add the task_id to the queue of blocked tasks for this identifier. if (blocked_tasks.contains(ident)) tasks = blocked_tasks[ident] + [task_id()]; else tasks = [task_id()]; blocked_tasks = blocked_tasks.add(ident, tasks); // And go to sleep until we are woken. $sys.suspend(); . public unblock_task arg ident; var tasks; // I want to be atomic! // The caller should have checked first, but we will fail silently. if (!.has_blocked_tasks(ident)) return; // Get the blocked tasks queue for this identifier. tasks = blocked_tasks[ident]; // If this is the last blocked task, then clear the queue, otherwise // just delete the task_id that we are resuming. if (tasks.length() == 1) blocked_tasks = blocked_tasks.del(ident); else blocked_tasks = blocked_tasks.add(ident, tasks.delete(1)); // Wake it up and go. $sys.resume(tasks[1]); . protected resume_job arg tid; $sys.resume(tid); . parent $utilities object $housekeeper var $root inited 1 var $root objname 'housekeeper var $root created_on 796268969 var $root flags ['parameters, 'methods, 'code, 'core] var $messaged verbs #[] public did_disconnect var task_queue, task; if (caller() != $user) throw(~perm, "Permission denied"); // because of guests if (valid(sender())) $scheduler.add_task(300, 'move_user_home, sender()); . public _move_user_home arg who; var home, curloc; .perms(caller(), 'this); if (who.connected()) return; curloc = who.location(); home = who.home(); if (curloc == home) return; curloc.sending_user_home(who); who.move_to(home); . public move_user_home arg who; var home, curloc; if (who.connected()) return; curloc = who.location(); home = who.home(); if (curloc == home) return; who.move_to(home); curloc.did_housekeep(who); . parent $frob object $logic_frob var $root child_index 6 var $root trusted [] var $root inited 1 var $root objname 'logic_frob var $root created_on 796268969 var $root flags ['parameters, 'methods, 'code, 'core] public test arg [args]; return 0; . parent $frob parent $named parent $world object $realms_frob var $root inited 1 var $root objname 'realms_frob var $root created_on 796268969 var $root flags ['parameters, 'methods, 'code, 'core] var $named name ['uniq, "realms_frob", "the realms_frob"] var $named name_aliases [] var $realms_frob local #[] public new arg [args]; args = [@args, ['interior]][1]; (> $places.is_place(sender()) <); local = local.add(sender(), args); return (<this(), args>); . public destroyed arg frob; . public init_realms_frob local = #[]; . root uninit_realms_frob var x; for x in (local) x[1].set_realm($realm_of_creation, 'interior); . public place_destroyed arg place; var x; local = local.del(place); for x in (local.keys()) (| x.place_destroyed(place) |); . public local return local; . public name arg [article]; if (article && type(article[1]) == 'frob) article = article.delete(1); return (> pass(@article) <); . public realm_name arg [args]; var realms; realms = .realms(); while (realms.length() > 2) realms = realms.delete(2); return realms.to_string(", "); . public realms arg [args]; var r; if (definer() == this()) return []; return [.name()] + (.parents())[1].realms(); . parent $frob object $ctext_frob var $root inited 1 var $root objname 'ctext_frob var $root created_on 796268969 var $root flags ['parameters, 'methods, 'code, 'core] public _ctext arg this; return this; . public new arg data, [evaluator]; evaluator = [@evaluator, $compile_evaluator][1]; if (type(data) == 'frob && class(data) == this()) return data; if (type(data) == 'string) data = (evaluator.compile_cml(data))['result]; return (<this(), data>); . public eval_ctext arg this, [vars]; var keys; vars = [@vars, #[]][1]; keys = vars.keys(); if (!('time in keys)) vars = vars.add('time, 'pre); if (!('evaluator in keys)) vars = vars.add('evaluator, $base_evaluator); if (!('this in keys)) vars = vars.add('this, sender()); if (!('sender in keys)) vars = vars.add('sender, sender()); return vars['evaluator].eval_ctext(vars, this); . public finish arg this; var term, output, line; output = []; line = ""; for term in (this) { if (type(term) in ['symbol, 'integer, 'string]) { line = line + tostr(term); } else if (type(term) == 'dbref) { line = line + term.objname(); } else if (type(term) == 'list) { if (term[1] == 'b_stmt) { output = [@output, line]; line = ""; } else { output = [@output, line, term.to_string()]; line = ""; } } else { line = line + $data_lib.unparse(term); } } output = [@output, line]; return output; . public uncompile arg this; return $uncompile_evaluator.eval_ctext(this); . public ctext arg this; return this; . public append arg this, data, [evaluator]; var tmp; // Make sure data is ctext evaluator = [@evaluator, $compile_evaluator][1]; data = $ctext_frob.new(data, evaluator); if (this[1][1] == 'text_stmt && data[1][1] == 'text_stmt) { //If this is a text_stmt we just add the data to the end this = ['text_stmt, [@this[1][2], @(data.ctext())[2]]]; } else { // anything else get wrapped in a text_stmt this = ['text_stmt, @this[1], @data.ctext()]; } return (<this(), this>); . parent $frob object $ctext_tag var $root objname 'ctext_tag var $root child_index 2 var $root created_on 806278619 var $root inited 1 var $root flags ['parameters, 'methods, 'code, 'core] public new arg name, flags, args, method; var item, self, eflags, uflags; self = [name, #[], #[], []]; eflags = #[]; uflags = #[]; for item in (flags) { switch (type(item)) { case 'string: eflags = eflags.add(item, 1); case 'list: if (type(item[1]) != 'string) throw(~flagerr, "Flag name must be a string."); if (type(item[2]) == 'list && item[2].length() == 1) item = item.insert(2, item[2][1]); if (type(item[2]) == 'frob && class(item[2]) == $ctext_generator) uflags = uflags.add(item[1], item[2]); else eflags = eflags.add(item[1], item[2]); default: throw(~flagerr, "Flag must be a string or key,value pair."); } } return (<this(), [name, eflags, uflags, args, method]>); . public name arg self; // if (type(self)=='dictionary) // return self['name]; //else return self[1]; . public uflags arg self; //if (type(self)=='dictionary) // return (| self['uflags]|) || #[]; //else return self[3]; . public add_flags arg self, key, value; var efalgs, uflags; eflags = (| self['flags] |) || #[]; uflags = (| self['uflags] |) || #[]; if (type(value) == 'frob && class(value) == $ctext_generator) { uflags = uflags.add(key, value); } else { eflags = eflags.add(key, value); if (key in uflags.keys()) uflags = uflags.del(key); } if (eflags.keys()) self = self.add('eflags, eflags); if (uflags.keys()) self = self.add('uflags, uflags); return (<this(), self>); . public args arg self; //if (type(self)=='dictionary) // return (| self['args]|) || []; //else return self[4]; . public set_args arg self, args; //if (type(self) == 'dictionary) // return <this(), self.add('args,args)>; //else return (<this(), self.replace(4, args)>); . public append_arg arg self, new; var args; //if (type(self)=='dictionary) { // args = (| self['args] |) || []; //args = [@args,new]; // return <this(), self.add('args,args)>; //} else { args = self[4]; args = [@args, new]; return (<this(), self.replace(4, args)>); //} . public method arg self; return self[5]; . public ctext_flags arg self; //if (type(self)=='dictionary) // return ((| self['flags]|) || #[]).union((|self['uflags]|) || #[]); //else return self[2].union(self[3]); . public ctext_uflags arg self; //if (type(self)=='dictionary) // return (| self['uflags]|) || #[]; //else return self[3]; . public add_ctext_flag arg self, key, value; var eflags, uflags; //if (type(self) == 'dictionary) { // eflags = (|self['flags]|) || #[]; // uflags = (|self['uflags]|) || #[]; //} else { eflags = self[2]; uflags = self[3]; //} if (type(value) == 'frob && class(value) == $ctext_generator) { uflags = uflags.add(key, value); } else { eflags = eflags.add(key, value); if (key in uflags.keys()) uflags = uflags.del(key); } //if (type(self)=='dictionary) { // if (eflags.keys()) // self = self.add('flags,eflags); // if (uflags.keys()) // self = self.add('uflags,uflags); //} else { self = self.replace(2, eflags); self = self.replace(3, uflags); //} return (<this(), self>); . parent $frob parent $thing object $thing_frob var $root child_index 1 var $root fertile 1 var $root inited 1 var $root objname 'thing_frob var $root created_on 796268969 var $root flags ['parameters, 'methods, 'code, 'fertile, 'core] var $located location $nowhere var $located obvious 1 var $described prose [] var $messaged verbs #[] var $gendered gender $gender_neuter var $named name ['uniq, "thing_class", "the thing_class"] var $named name_aliases [] public name arg [args]; if (args && type(args[1]) == 'dictionary) return (> ._name(@args) <); return (> pass(@args) <); . public namef arg [args]; if (args && type(args[1]) == 'dictionary) return (> ._namef(@args) <); return (> pass(@args) <); . public short_description arg [args]; if (args && type(args[1]) == 'dictionary) return (> ._description(@args) <); return (> pass(@args) <); . public long_description arg [args]; if (args && type(args[1]) == 'dictionary) return (> ._description(@args) <); return (> pass(@args) <); . public prose arg [args]; var dict; if (args && type(args[1]) == 'dictionary) return (> ._prose(@args) <); return (> pass(@args) <); . public _namef arg dict, [args]; return (> ._name(dict, args) <); . public _prose arg dict, [args]; (> .perms(sender(), 'this) <); return (| dict['prose] |) || "You see nothing special."; . public _name arg dict, [args]; var name, article; name = (| dict['name] |) || [[.name(), 'normal], [.name_aliases()]]; switch (name[1][2]) { case 'prop: return name[1][1]; case 'uniq: return "the " + name[1][1]; case 'normal: return name[1][1].a_or_an() + " " + name[1][1]; } . public _description arg dict, [args]; (> .perms(sender(), 'this) <); return [._name(dict), @._prose(dict)]; . public match_name arg [args]; if (args && type(args[1]) == 'dictionary) return (> ._match_name(@args) <); return (> pass(@args) <); . public _match_name_exact arg this, str; return $string.match_begin(this['name][1][1], str); . public _match_name_aliases arg this, str; return (| str in this['name][2] |); . public _match_name arg this, str; return ._match_name_exact(this, str) || ._match_name_aliases(this, str); . parent $frob object $read_parser var $root inited 1 var $root objname 'read_parser var $root created_on 796268969 var $root flags ['parameters, 'methods, 'code, 'core] public parse_line arg dict, line; var cmd; if (!line) { // we have to do this as such, because of logic (shrug) dict = dict.add('status, 'not_done); return dict.add_elem('lines, line); } else if (line[1] == ".") { if (line.length() > 1 && line[2] == ".") line = line.subrange(2); else if (line.length() == 1) return dict.add('status, 'done); } else if (line[1] == ">") { if (line.length() > 1 && line[2] == ">") { line = line.subrange(2); } else { dict = dict.add('command, line.subrange(2)); return dict.add('status, 'pass_command); } } else if (line == "@abort") { return dict.add('status, 'abort); } dict = dict.add('status, 'not_done); return dict.add_elem('lines, line); . public new arg task_id, count; return (<this(), #[['lines, []], ['status, 'not_done], ['count, count], ['task_id, task_id]]>); . public parse arg dict, line; var line, result; // checks the incoming line to see if its a keeper, or a command. if (dict['count] == 'one) { dict = dict.add_elem('lines, line); return (<this(), dict.add('status, 'done)>); } else { return (<this(), .parse_line(dict, line)>); } . public status arg dict; return dict['status]; . public task_id arg dict; return dict['task_id]; . public lines arg dict; return dict['lines]; . public command arg dict; return (| dict['command] |) || ""; . public add arg dict, [args]; return (<this(), (> dict.add(@args) <)>); . parent $frob object $ctext2_frob var $root objname 'ctext2_frob var $root created_on 807320067 var $root inited 1 var $root flags ['parameters, 'methods, 'code, 'core] public new arg data, [vars]; var ret; vars = [@vars, #[]][1]; return (<this(), [data, vars]>); . public eval_ctext arg this; var data, vars; data = this[1]; vars = this[2]; vars = vars.add('time, 'pre); if (!('sender in vars.keys())) vars = vars.add('sender, sender()); if (!('evalautor in vars.keys())) vars = vars.add('evaluator, $cml2_base_eval); return vars['evaluator].eval_ctext(data, vars); . public format arg this; var data, vars; data = this[1]; vars = this[2]; vars = vars.add('time, 'format); if (!('receiver in vars.keys())) vars = vars.add('receiver, sender()); if (!('formatter in vars.keys())) vars = vars.add('formatter, $cml2_telnet_format); if (!('evalautor in vars.keys())) vars = vars.add('evaluator, $cml2_base_eval); this = vars['formatter].eval_ctext(data, vars); return $buffer.from_string(this); . public set_var arg this, name, value; var vars; vars = this[2]; vars = vars.add(name, value); return (<this(), [this[1], vars]>); . public get_var arg this, name; return this[2][name]; . public vars arg this; return this[2]; . public _ctext arg this; return this[1]; . public set_vars arg this, new; var vars, key; vars = this[2]; for key in (new.keys()) vars = vars.add(key, new[key]); return (<this(), [this[1], vars]>); . public uncompile arg this; var vars; vars = this[2]; if (!('uncompiler in vars.keys())) vars = vars.add('uncompiler, $cml2_uncompiler); return vars['uncompiler].eval_ctext(this[1]); . public append arg this, new, [br]; var data, tmp; data = this[1]; if (br) { switch (br[1]) { case "p": data = [@data, (<$ctext_generator, #[['name, "p"]]>)]; case "br": data = [@data, (<$ctext_generator, #[['name, "br"]]>)]; default: data = [@data, $ctext_generator.new(br[1], [], [])]; } } if (type(new) == 'list) data = [@data, @new]; else if (type(new) == 'frob && class(new) == $ctext2_frob) data = [@data, @new._ctext()]; else data = [@data, new]; return (<this(), [data, this[2]]>); . parent $frob object $message_frob var $root inited 1 var $root objname 'message_frob var $root created_on 796268969 var $root flags ['parameters, 'methods, 'code, 'core] public add_entry arg this, key, what; var data; this = this.add(key, what); return (<this(), this>); . public del_entry arg this, key; this = this.del(key); return (<this(), this>); . public eval_ctext arg this, vars; var key, new, temp, t, list, vars; new = .new(#[]); vars = vars.add('this, sender()); if ("general" in this.keys()) vars = vars.add("$general", "general"); list = this.keys(); for key in (list) { temp = this[key].set_var('this, vars['this]).eval_ctext(); new = new.add_entry((| vars["$" + key] |) || vars[key], temp); } return new; . public new arg what; var key, this; if (type(what) != 'dictionary) throw(~type, "A message should be a dictionary."); this = #[]; for key in (what) this = this.add_entry(key[1], key[2]); return (<this(), this>); . public has_entry arg this, name; return name in this.keys(); . public get_part arg this, part; return this[part]; . public uncompile arg this; var key, output; output = #[]; for key in (this) output = output.add(key[1], key[2].uncompile()); return output; . public parts arg this; return this.keys(); . public message arg name, [definer]; var a, message, mes, m, empty; //retrieve the specified message as ctext if (definer) definer = definer[1]; else definer = (._find_message_definer(name))[2]; message = $message_frob.new(#[], #[]); empty = $ctext_frob.new(""); for a in (.ancestors()) { catch ~methodnf, ~messagenf { return a.local_message(name, definer); } } throw(~messagenf, "No matching message."); . public set_vars arg this, new; var d; for d in (this.keys()) this = this.add(d, this[d].set_vars(new)); return (<this(), this>); . public format arg this, vars; var new; new = (| this[vars['receiver]] |) || (| this["general"] |) || $ctext_frob.new([""]); new = new.set_vars(vars); new = new.format(); return new; . parent $command_cache object $editors var $root trusted [] var $root inited 1 var $root objname 'editors var $root created_on 796268969 var $root flags ['parameters, 'methods, 'code, 'core] var $has_commands shortcuts #[] var $command_cache shortcut_cache 0 var $command_cache remote_cache 0 var $command_cache local_cache 0 parent $user object $builder var $root owners [$builder] var $root inited 1 var $root owned [$builder] var $root manager $builder var $root quota 75000 var $root objname 'builder var $root created_on 796268969 var $root flags ['parameters, 'methods, 'code, 'core] var $root managed [$builder] var $messaged verbs #[] var $location contents [] var $located location $body_cave var $located obvious 1 var $user password "*" var $user connected_at 0 var $user last_command_at 0 var $user connections [] var $user modes #[] var $user prompt "" var $user parsers [$command_parser] var $user tell_traceback ['brief, 0] var $user context #[] var $user filters [] var $command_aliases command_aliases [] var $mail_list letters #[] var $mail_list letters_index #[] var $mail_list senders 1 var $mail_list readers [] var $mail_list notify [$builder] var $mail_list last_letter 0 var $mail_list mail [] var $mail_ui subscribed #[[$builder, 791485891]] var $mail_ui current #[['location, 0], ['list, $builder]] var $gendered gender $gender_neuter var $described prose [] var $named name ['prop, "Generic Builder", "Generic Builder"] var $named name_aliases [] var $user_data user_data #[['real_name, [1, "???"]], ['email, [1, "???"]]] var $has_commands local #[["@par?ents", [["@par?ents", "*", "@par?ents <any>", 'parents_cmd, #[[1, ['any, []]]]]]], ["@dest?roy", [["@dest?roy", "*", "@dest?roy <any>", 'destroy_cmd, #[[1, ['any, []]]]]]], ["@child?ren|@kids", [["@child?ren|@kids", "*", "@child?ren|@kids <any>", 'children_cmd, #[[1, ['any, []]]]]]], ["@build", [["@build", "*", "@build <any>", 'build_cmd, #[[1, ['any, []]]]]]], ["@attach", [["@attach", "* to *", "@attach <any> to <any>", 'attach_cmd, #[[1, ['any, []]], [3, ['any, []]]]]]], ["@realm?s", [["@realm?s", "", "@realm?s", 'realms_cmd, #[]]]]] var $help_ui indices [$help_index_root] var $help_ui history [$help_summary] var $help_ui current 1 var $command_cache shortcut_cache 0 var $command_cache remote_cache 0 var $command_cache local_cache 0 protected children_cmd arg cmdstr, cmd, what; var out; what = .match_env_nice(what); out = ["Children of " + what.namef('xref) + ":"]; what = what.children(); return out + $code_lib.generate_object_listing(what, 'parents); . protected parents_cmd arg cmdstr, cmd, what; var out; what = .match_env_nice(what); out = ["Parent" + (.parents().length() > 1 ? "s" | "") + " of " + what.namef('ref) + ":"]; what = what.parents(); return out + $code_lib.generate_object_listing(what, 'children); . public destroy_cmd arg cmdstr, cmd, what; var name; if (sender() != this()) throw(~perm, "Sender not this."); what = .match_env_nice(what); catch any { name = what.namef('xref); what.destroy(); .tell("Sucessfully destroyed " + name + "."); } with handler { .tell(traceback()[1][2]); } . public _build_query_coordinates arg [returning]; var radial, azimuth, coord; (> .perms(sender(), 'this) <); ._build_hint(5); while (1) { coord = .prompt("Exit coordinates (radial,azimuth): "); if (coord == "@abort") throw(~abort, "Abort"); if (coord == "@shortcuts") { ._build_shortcuts(); continue; } if (!coord) { .tell("Invalid Coordinates."); continue; } catch ~coordnf, ~invcoord { if (coord.is_numeric()) { coord = coord.explode_english_list(); if (coord.length() != 2) { .tell("Seperate coordinates with a comma."); continue; } if (!coord[1].is_numeric() || !coord[2].is_numeric()) { .tell("Invalid coordinates."); continue; } if (!coord[1].is_numeric() || !coord[2].is_numeric()) { .tell("Invalid coordinates."); continue; } radial = toint(coord[1]); azimuth = toint(coord[2]); } else { coord = $places.coordinates(coord); radial = coord[1]; azimuth = coord[2]; } (> $places.valid_coordinates(radial, azimuth) <); } with handler { .tell(traceback()[1][2]); continue; } return [radial, azimuth]; } . public build_cmd arg cmdstr, cmd, str; var dest, source, exits; (> .perms(sender(), 'this) <); source = .location(); if (!(| source.will_attach('source) |)) return "This room is not publicly extendable."; // Establish the objects catch any { dest = (> ._build_get_location(str) <); if (!(| dest[1].will_attach('dest) |)) { .tell(dest[1].name() + " will not allow you to attach to it!"); ._build_cleanup(dest); return "** Build Aborted **"; } exits = (> ._build_get_exits(dest, source) <); (> ._build_attach_exit(source, dest[1], @exits[1]) <); (> ._build_attach_exit(dest[1], source, @exits[2]) <); } with handler { if (dest) ._build_cleanup(dest); .tell_traceback(traceback()); return [traceback()[1][2], "** Build Aborted **"]; } // Flesh them out if (dest[2]) (| dest.configure() |); if (exits[1]) (| exits[1][1].configure() |); if (exits[2]) (| exits[2][2].configure() |); return ["Completed building (*whew*)", "---"]; . public _build_shortcuts var x; (> .perms(sender(), 'this) <); .tell("Radial/Azimuth Coordinate shortcuts:"); .tell(" Shortcut Radial Azimuth"); for x in ($places.coordinate_shortcuts()) .tell(" " + x[1].pad(20) + tostr(x[2][1]).pad(7) + tostr(x[2][2])); . public _build_hint arg n; (> .perms(sender()) <); if ((| .setting("experienced") |) == "yes") return; .tell($places.build_hint(n)); . public _build_cleanup arg [what]; var obj; (> .perms(caller(), definer()) <); for obj in (what) { if (valid(obj[1]) && obj[2]) { .tell("Destroying " + obj[1].name() + "..."); (| obj[1].destroy() |); } } . public _build_query_exit arg source, dest; var exit, line, name; (> .perms(sender(), 'this) <); line = "Exit from " + dest.name() + " to " + source.name() + ":"; name = (> ._build_loop_name_query(line) <); if (name in ["none", "<none>"]) return 0; exit = (| $exit.spawn() |); if (!exit) { .tell("Unable to create exit!"); return 0; } ._build_set_name(exit, @name); return exit; . public attach_cmd arg cmdstr, cmd, source_str, prep, dest_str; var source, dest, coords, coords_str, exit, ename; (> .perms(sender(), 'this) <); if (!source_str) source = .location(); else source = .match_env_nice(source_str); dest = .match_env_nice(dest_str); exit = ._build_query_exitname(dest, source); if (exit == -1) return .tell("Aborted."); coords = ._build_query_coordinates(); if (!coords) return .tell("Aborted."); ._build_query_prose(exit); catch any { exit.attach(source, dest, @coords); } with handler { .tell("Ack, unable to attach exit because:"); .tell(" " + traceback()[1][2]); (| exit.destroy() |); return; } .tell("Successfully attached exit."); . public realms_cmd arg cmdstr, cmd; var x, realms; (> .perms(sender(), 'this) <); realms = $places.known_realms().union($realms_frob.descendants()); .tell("Realms: " + realms.map('name).to_english()); . public _build_set_name arg obj, name, aliases; var a, x; (> .perms(sender(), 'this) <); catch any { obj.set_name(@name); } with handler { .tell("Unable to set name; " + traceback()[1][2]); .tell("Setting name as " + tostr(obj.objname('symbol))); obj.set_name(tostr(obj.objname('symbol))); } for a in (aliases) obj.add_name_alias(a); . public _build_loop_name_query arg prompt, [args]; var invalid, syntax, line, out; (> .perms(sender(), 'this) <); invalid = [@args, "Invalid name."][1]; syntax = [@args, "", ""][2]; ._build_hint(3); while (1) { line = .prompt(prompt); if (line == "@abort") throw(~abort, "Aborted"); if (!line) { .tell(invalid); continue; } line = (| $code_lib.parse_name(line) |); if (!line) { .tell("Empty name."); continue; } return line; } . public _build_get_location arg name; var dest; (> .perms(sender()) <); ._build_hint(1); if (name) { if ($string.match_begin(name, "to ")) name = name.subrange(4); name = (| $code_lib.parse_name(name) |); } if (!name) name = (> ._build_loop_name_query("Enter destination name: ") <); // first try to see if it already exists catch any { dest = (> .match_environment(name[1][1]) <); (> $places.is_place(dest) <); return [dest, 0]; } with handler { return [(> ._build_create_place(name) <), 1]; } . public _build_query_realm arg there; var line, realm, r; while (!realm) { line = .prompt("What realm is " + there.name() + " in? "); if (line == "@abort") throw(~abort, "Aborted"); if (line == "@realms" || line == "?") { .tell("Known realms:"); for r in ($realms_frob.descendants()) .tell(" " + r.name()); continue; } realm = $places.match_realm(line); } // add interior/exterior query later return realm; . public _build_create_place arg name; var name, dest, realm; (> .perms(sender()) <); ._build_hint(2); dest = (> $places.place('default_new).spawn() <); ._build_set_name(dest, @name); ._build_hint(4); catch any { realm = (> ._build_query_realm(dest) <); } with handler { ._build_cleanup([dest, 1]); rethrow(error()); } // because of how settings work, we want to give it the string name instead dest.set_setting($place, "realm", realm.name()); return dest; . public _build_attach_exit arg source, dest, exit, coords; var line; (> .perms(sender()) <); catch any { exit.attach(source, dest, @coords); } with handler { .tell("Unable to attach " + exit.name() + " because: "); .tell(" " + traceback()[1][2]); line = .prompt("Continue building? "); if (line in ["no", "n"]) throw(~abort, "Aborted"); } . public _build_get_exits arg dest, source; var eleave, earrive; // Get the exits catch any { if (eleave = (> ._build_query_exit(dest[1], source) <)) { eleave = [eleave, (> ._build_query_coordinates() <)]; if (earrive = (> ._build_query_exit(source, dest[1]) <)) earrive = [earrive, (> $places.invert_coordinates(@eleave[2]) <)]; } } with handler { if (eleave) { if (earrive) ._build_cleanup([eleave[1], 1], [earrive[1], 1]); else ._build_cleanup([eleave[1], 1]); } rethrow(error()); } return [eleave, earrive]; . parent $user object $guest var $root child_index 44 var $root owners [$guest] var $root inited 1 var $root owned [$guest] var $root manager $guest var $root quota 75000 var $root objname 'guest var $root created_on 796268969 var $root flags ['parameters, 'methods, 'code, 'core] var $root managed [$guest] var $messaged verbs #[] var $location contents [] var $located location $body_cave var $located obvious 1 var $user password "*" var $user connected_at 0 var $user last_command_at 0 var $user connections [] var $user modes #[] var $user prompt "" var $user parsers [$command_parser] var $user tell_traceback ['verbose, 4] var $user context #[] var $user filters [] var $command_aliases command_aliases [] var $mail_list letters #[] var $mail_list letters_index #[] var $mail_list senders 1 var $mail_list readers 1 var $mail_list notify [$guest] var $mail_list last_letter 0 var $mail_list mail [] var $mail_ui subscribed #[[$guest, 791485891]] var $mail_ui current #[['location, 0], ['list, $guest]] var $gendered gender $gender_neuter var $described prose [] var $named name ['prop, "Generic Guest Object", "Generic Guest Object"] var $named name_aliases [] var $user_data user_data #[['real_name, [1, "???"]], ['email, [1, "???"]]] var $help_ui indices [$help_index_root] var $help_ui history [$help_summary] var $help_ui current 1 var $command_cache shortcut_cache 0 var $command_cache remote_cache 0 var $command_cache local_cache 0 root init_guest .set_title("a guest"); . public logout arg connection; (| pass(connection) |); .destroy(); . public title_cmd arg cmdstr, com, str; (> .perms(sender(), 'this) <); .tell("Guests are not allowed to change their titles."); . parent $user object $reaper var $root quota 75000 var $root inited 1 var $root objname 'reaper var $root created_on 796268969 var $root flags ['core] var $messaged verbs #[] var $user_data user_data #[['real_name, [1, "???"]], ['email, [1, "???"]]] var $command_aliases command_aliases [] var $named name ['prop, "Reaper", "Reaper"] var $named name_aliases [] var $gendered gender $gender_neuter var $described prose [] var $location contents [] var $located location $body_cave var $located obvious 1 var $body body_parts #[] var $user password "*" var $user connected_at 0 var $user last_command_at 0 var $user connections [] var $user creation_time 780375877 var $user parsers [$command_parser] var $user filters [] var $user action "" var $user prompt "" var $user context #[] var $help_ui indices [$help_index_root] var $help_ui history [$help_summary] var $help_ui current 1 var $mail_list mail [] var $mail_list senders 1 var $mail_list notify [$reaper] var $mail_ui subscribed #[[$reaper, 791485891]] var $mail_ui current #[['location, 0], ['list, $reaper]] var $command_cache shortcut_cache 0 var $command_cache remote_cache 0 var $command_cache local_cache 0 parent $user object $no_one var $root inited 1 var $root manager $no_one var $root quota 75000 var $root objname 'no_one var $root created_on 796268969 var $root flags ['parameters, 'methods, 'code, 'core] var $root managed [$no_one] var $command_aliases command_aliases [] var $messaged verbs #[] var $location contents [] var $located location $body_cave var $located obvious 1 var $user password "*" var $user connected_at 0 var $user last_command_at 0 var $user connections [] var $user creation_time 759878010 var $user action "" var $user modes #[] var $user prompt "" var $user parsers [$command_parser] var $user tell_traceback ['brief, 0] var $user context #[] var $user filters [] var $mail_list letters #[] var $mail_list letters_index #[] var $mail_list senders 1 var $mail_list notify [$no_one] var $mail_list last_letter 0 var $mail_list mail [] var $mail_ui subscribed #[[$no_one, 791485891]] var $mail_ui current #[['location, 0], ['list, $no_one]] var $gendered gender $gender_neuter var $described prose [] var $named name ['prop, "No One", "No One"] var $named name_aliases ["No", "One"] var $user_data user_data #[['real_name, [1, "???"]], ['email, [1, "???"]]] var $help_ui indices [$help_index_root] var $help_ui history [$help_summary] var $help_ui current 1 var $command_cache shortcut_cache 0 var $command_cache remote_cache 0 var $command_cache local_cache 0 parent $user object $player var $root objname 'player var $root child_index 1 var $root fertile 1 var $root created_on 809926794 var $root inited 1 var $root quota 75000 var $root flags ['core] var $user password "*" var $user connected_at 0 var $user last_command_at 0 var $user connections [] var $user parsers [$command_parser] var $user action "" var $user context #[] var $located location $nowhere var $located obvious 1 var $has_commands shortcuts #[] var $has_commands remote #[] var $has_commands local #[["@sheet|@score", [["@sheet|@score", "*", "@sheet|@score <any>", 'sheet_cmd, #[[1, ['any, []]]]]]]] var $player strength [0, 0] var $player agility [0, 0] var $player appearance [0, 0] var $player health [0, 0] var $player life [0, 0] var $player intellect [0, 0] var $player knowledge [0, 0] var $player backbone [0, 0] var $player charisma [0, 0] var $player humanity [0, 0] var $player perception [0, 0] var $player presence [0, 0] var $player source 0 var $player dead 0 var $player weapons 0 var $player identity 0 var $player affiliation 0 var $player points 0 var $player deaths 0 var $player encumbrance 0 var $player fatigue 0 var $player characteristics 0 var $named name ['proper, "player", "player"] var $named name_aliases [] var $has_settings defined_settings #[] var $has_settings local_settings #[] var $has_settings settings #[] var $location contents [] var $described prose [] var $gendered gender $gender_neuter var $mail_ui current #[['location, 0], ['list, $player]] var $mail_ui subscribed #[[$player, 813278553], [$mail_list_news, 813278553]] var $mail_list mail [] var $mail_list senders 1 var $mail_list readers [$player] var $mail_list notify [$player] var $command_aliases command_aliases [] var $user_data user_data #[['real_name, [1, "???"]], ['email, [1, "???"]]] var $help_ui history [$help_summary] var $help_ui indices [$help_index_root] var $help_ui current 1 protected lower_attribute arg attribute, difference; var new; new = get_var(attribute)[1] - difference; set_var(attribute, get_var(attribute).replace(1, new)); . public attribute: disallow_overrides, synchronized arg attribute; if (caller() != definer()) (> .perms(sender(), $storyteller) <); return get_var(attribute); . root init_player: disallow_overrides, synchronized strength = [0, 0]; agility = [0, 0]; appearance = [0, 0]; health = [0, 0]; life = [0, 0]; intellect = [0, 0]; knowledge = [0, 0]; backbone = [0, 0]; charisma = [0, 0]; humanity = [0, 0]; perception = [0, 0]; presence = [0, 0]; source = [0, 0]; weapons = []; . protected raise_attribute arg attribute, difference; var new; new = get_var(attribute)[1] + difference; if (new > get_var(attribute)[2]) new = get_var(attribute)[2]; set_var(attribute, get_var(attribute).replace(1, new)); . public dead return dead; . public sheet_cmd arg cmdstr, cmd, args; var t, out, g; if (args && !.is($storyteller)) return "Only storytellers can see other players stats."; t = args ? .match_env_nice(args) | this(); g = $game_lib; out = ["Strength: " + g.format_rank(@t.attribute('strength)) + "Reaction: " + tostr((t.attribute('agility))[1] / 5).pad(8) + "Strength Damage: 0", "Agility: " + g.format_rank(@t.attribute('agility)) + "Source: " + g.format_rank(@t.attribute('source)), "Appearance: " + g.format_rank(@t.attribute('appearance)) + "Learn: " + tostr((t.attribute('intellect))[1] / 3).pad(8) + "Competancy Level: 0", "Intellect: " + g.format_rank(@t.attribute('intellect)) + " Advancement Points: " + tostr(t.attribute('points)), "Knowledge: " + g.format_rank(@t.attribute('intellect)) + "Life: " + g.format_rank(@t.attribute('life)), "Presence: " + g.format_rank(@t.attribute('presence)) + "Health: " + g.format_rank(@t.attribute('health)) + "Humanity: " + g.format_rank(@t.attribute('humanity)), "Backbone: " + g.format_rank(@t.attribute('backbone)), "Charisma: " + g.format_rank(@t.attribute('charisma)) + "Deaths: " + tostr(t.attribute('deaths)).pad(8) + "Encumbrance: " + tostr(t.attribute('encumbrance)), "Perception: " + g.format_rank(@t.attribute('perception)) + " Fatigue: " + tostr(t.attribute('fatigue))]; return out; . public set_attribute arg attribute, value; (> .perms(sender()) <); set_var(attribute, [value, value]); . parent $thing object $nothing var $root inited 1 var $root objname 'nothing var $root created_on 796268969 var $root flags ['parameters, 'methods, 'code, 'core] var $messaged verbs #[] var $located location 0 var $located obvious 1 var $gendered gender $gender_neuter var $described prose [] var $named name ['prop, "nothing whatsoever", "nothing whatsoever"] var $named name_aliases [] parent $place object $nowhere var $root inited 1 var $root objname 'nowhere var $root created_on 796268969 var $root flags ['parameters, 'methods, 'code, 'core] var $messaged verbs #[] var $location contents [$located_location, $body, $user, $reaper_log, $log, $http_log, $note, $login_log, $thing_frob, $player] var $gendered gender $gender_neuter var $described prose [] var $named name ['prop, "Nowhere", "Nowhere"] var $named name_aliases [] var $place exits [] var $place realm <$realm_of_creation, ['interior]> var $place coordinates #[] var $public public [] var $command_cache shortcut_cache 0 var $command_cache remote_cache 0 var $command_cache local_cache 0 parent $place object $body_cave var $root objname 'body_cave var $root created_on 808865147 var $root inited 1 var $root flags ['parameters, 'methods, 'code, 'core] var $has_settings defined_settings #[] var $has_settings local_settings ["public-home"] var $has_settings settings #[[$place, #[["public-home", "1"]]]] var $has_commands shortcuts #[] var $has_commands remote #[] var $has_commands local #[] var $command_cache shortcut_cache 0 var $command_cache remote_cache 0 var $command_cache local_cache 0 var $named name ['normal, "the Body Cave", "a the Body Cave"] var $named name_aliases [] var $gendered gender $gender_neuter var $messaged verbs #[] var $described prose [] var $location contents [$reaper, $builder, $guest, $no_one, $programmer, $admin, $player] var $place exits [] var $place realm <$realm_of_creation, ['interior]> var $place coordinates #[] var $physical visibility -100 parent $place object $void var $root inited 1 var $root objname 'void var $root created_on 796268969 var $root flags ['parameters, 'methods, 'code, 'core] var $messaged verbs #[] var $location contents [$thing, $lost_and_found] var $gendered gender $gender_neuter var $described prose ["A place existing for the soul purpose of doing so, when it wishes be."] var $named name ['uniq, "Void", "the Void"] var $named name_aliases [] var $place exits [] var $place realm <$realm_of_creation, ['interior]> var $place coordinates #[] var $public public [] var $command_cache shortcut_cache 0 var $command_cache remote_cache 0 var $command_cache local_cache 0 parent $place object $detailed_place var $root objname 'detailed_place var $root created_on 809582204 var $root inited 1 var $root flags ['parameters, 'methods, 'code, 'core] var $has_commands shortcuts #[] var $has_commands remote #[] var $has_commands local #[] var $command_cache shortcut_cache 0 var $command_cache remote_cache 0 var $command_cache local_cache 0 var $has_settings defined_settings #[] var $has_settings local_settings #[] var $has_settings settings #[] var $named name ['uniq, "place_128", "the place_128"] var $named name_aliases [] var $gendered gender $gender_neuter var $messaged verbs #[] var $described prose [] var $location contents [] var $place exits [] var $place realm <$realm_of_creation, ['interior]> var $place coordinates #[] parent $place object $the_pit var $root inited 1 var $root objname 'the_pit var $root created_on 796268969 var $root flags ['parameters, 'methods, 'code, 'core] var $has_settings local_settings ["realm"] var $messaged verbs #[] var $location contents [] var $gendered gender $gender_neuter var $described prose <$ctext2_frob, [["This is a room with a low ceiling, worn couches and furniture, and walls worn from scribbling, burn marks, and other unrecognizeable usages. Desipite its cramped feel, there is a warm comfortable atmosphere, almost as if somebody could just come here and relax for a while. To the north is a cement opening in the wall."], #[['line, 1], ['this, $the_pit]]]> var $named name ['prop, "The Pit", "The Pit"] var $named name_aliases [] var $place exits [] var $place realm $realm_of_creation var $place coordinates #[] var $public public [] var $command_cache shortcut_cache 0 var $command_cache remote_cache #[["l", [["l?ook"], [$described]]], ["lo", [["l?ook"], [$described]]], ["loo", [["l?ook"], [$described]]], ["look", [["l?ook"], [$described]]], ["@lock", [["@lock"], [$thing]]], ["@unlock", [["@unlock"], [$thing]]], ["@boot", [["@boot"], [$thing]]]] var $command_cache local_cache 0 parent $connection object $login_connection var $root objname 'login_connection var $root child_index 1722 var $root writes [$login_connection_1720, $login_connection_1721, $login_connection_1722] var $root created_on 809051865 var $root inited 1 var $root indestructable 1 var $root quota_exempt -1 var $root writers [$login_daemon] var $root flags ['parameters, 'methods, 'code, 'core] var $root owned [$login_connection_1720, $login_connection_1721, $login_connection_1722] var $connection interface $login_interface var $connection active 0 var $connection buffer `[] var $connection host "" var $connection daemon 0 var $connection line_buffer [] var $connection timeout 0 var $connection read_block 0 var $connection started_at 0 parent $connection object $http_connection var $root objname 'http_connection var $root child_index 1854 var $root owned [$http_connection_1854] var $root created_on 809075134 var $root inited 1 var $root indestructable 1 var $root quota_exempt -1 var $root flags ['parameters, 'methods, 'code, 'core] var $root writes [$http_connection_1854] var $connection buffer `[27] var $connection host "" var $connection daemon 0 var $connection active 0 var $connection line_buffer [] var $connection interface $http_interface var $connection timeout 0 var $connection read_block 0 var $connection started_at 0 public address return (> pass() <); . parent $daemon object $http_daemon var $root objname 'http_daemon var $root writes [$http_connection_1854] var $root created_on 809075222 var $root inited 1 var $root indestructable 1 var $root flags ['parameters, 'methods, 'code, 'core] var $daemon default_port 1180 var $daemon connection $http_connection var $daemon next_connection $http_connection_1854 var $daemon current_port 1180 parent $daemon object $login_daemon var $root objname 'login_daemon var $root writes [$login_connection_1720, $login_connection_1721, $login_connection_1722] var $root created_on 809051992 var $root inited 1 var $root indestructable 1 var $root flags ['parameters, 'methods, 'code, 'core] var $daemon connection $login_connection var $daemon default_port 1138 var $daemon current_port 1138 var $daemon next_connection $login_connection_1722 parent $connection_interface object $login_interface var $root objname 'login_interface var $root child_index 620 var $root owned [$login_interface_620] var $root writes [$login_connection_1720, $login_connection_1721, $login_connection_1722] var $root created_on 809051864 var $root inited 1 var $root quota_exempt -1 var $root indestructable 1 var $root flags ['parameters, 'methods, 'code, 'core] var $has_commands local #[["@who", [["@who", "", "@who", 'who_cmd, #[]]]], ["m?otd", [["m?otd", "", "m?otd", 'motd_cmd, #[]]]], ["h?elp", [["h?elp", "", "h?elp", 'help_cmd, #[]]]], ["guest|connect-guest", [["guest|connect-guest", "*", "guest|connect-guest <any>", 'connect_guest_cmd, #[[1, ['any, []]]]]]], ["c?onnect", [["c?onnect", "*", "c?onnect <any>", 'connect_cmd, #[[1, ['any, []]]]]]], ["@quit|QUIT", [["@quit|QUIT", "", "@quit|QUIT", 'quit_cmd, #[]]]], ["create", [["create", "*", "create <any>", 'create_cmd, #[[1, ['any, []]]]]]]] var $command_cache shortcut_cache [] var $command_cache remote_cache 0 var $command_cache local_cache #[["@who", ["@who"]], ["m", ["m?otd"]], ["mo", ["m?otd"]], ["mot", ["m?otd"]], ["motd", ["m?otd"]], ["h", ["h?elp"]], ["he", ["h?elp"]], ["hel", ["h?elp"]], ["help", ["h?elp"]], ["guest", ["guest|connect-guest"]], ["connect-guest", ["guest|connect-guest"]], ["c", ["c?onnect"]], ["co", ["c?onnect"]], ["con", ["c?onnect"]], ["conn", ["c?onnect"]], ["conne", ["c?onnect"]], ["connec", ["c?onnect"]], ["connect", ["c?onnect"]], ["@quit", ["@quit|QUIT"]], ["QUIT", ["@quit|QUIT"]], ["create", ["create"]]] protected connect_cmd arg cmdstr, cmd, args; var syn, stderr, passwd, name, user; syn = cmd + " <name> <password>"; stderr = "Either that user does not exist or has a different password."; args = args.explode(); if (args.length() < 2) .tell_error("Last word is taken as the password.", syn); passwd = args[args.length()]; name = args.subrange(1, args.length() - 1).to_string(); user = (| $user_db.find(name) |) || .tell_error(syn, stderr); user.check_password(passwd) || .tell_error(syn, stderr); .connection().change_interface(user); . protected create_cmd arg cmdstr, cmd, args; var syn, msg, user, semail; syn = cmd + " <name> <password> <email@host>"; semail = $sys.get_system_email('login); args = args.explode(); args.length() == 3 || .tell_error(syn); catch any { user = $sys.create_user(@args); } with handler { if (user) (| user.destroy() |); if (error() == ~duplicate) { msg = "The user " + toliteral(args[1]) + " already exists."; } else { msg = ["There was a problem creating you:"]; msg = [@msg, traceback()[1][2]]; msg = [@msg, "If there is a problem contact: " + semail]; } (| $login_log.log(traceback()) |); (> .tell_error(syn, msg) <); } .connection().change_interface(user); . protected quit_cmd arg cmdstr, cmd; .print("Goodbye."); return 'disconnect; . protected connect_guest_cmd arg cmdstr, cmd, args; var syn, msg, c, email, name, result, semail, user; syn = cmd + " <your name> <your email>"; semail = $sys.get_system_email('login); args = args.explode(); if (args.length() < 2) (> .tell_error(syn) <); name = args.subrange(1, args.length() - 1).to_string(); email = args[args.length()]; if ($sys.validate_email_addresses()) result = $code_lib.valid_email(email); if (result[1] != 'valid) { switch (result[1]) { case 'invalid: (| .tell_error(c, syn) |); c.write("The given email address is not a legitimate address."); c.write("Specify both username and hostname."); return; case 'invip, 'invhostname: c.write("Your hostname seems to be invalid."); c.write("You should set a valid email address."); } } catch any { user = (> $sys.create_user(name, 0, email, 'anonymous_user_class) <); } with handler { if (error() == ~duplicate) { msg = ["The name " + toliteral(words[1]) + " is already in use."]; } else { msg = "There was a problem creating you:"; msg = [msg, " => " + traceback()[1][2]]; msg = [@msg, "If there is a problem contact: " + semail]; } (| $login_log.log(traceback()) |); (> .tell_error(syn, msg) <); } .connection().change_interface(user); . protected who_cmd arg cmdstr, cmd; .print($code_lib.generate_listing($user_db.connected())); . protected help_cmd arg cmdstr, cmd; .print($motd.connect_help()); . protected null_cmd arg [args]; return (> .invalid_cmd(@args) <); . protected invalid_cmd arg [args]; var line; (> .perms(sender(), 'this) <); line = $login_interface.local_cache().to_list().slice(2).slice(1).compress(); .print("Try: " + line.to_english("", " or ")); . protected print arg what; .connection().write(what); . protected motd var out; out = $motd.build('default) + ["", " ** Use 'H?elp' for a list of commands **".center(79), ""]; return out; . protected motd_cmd arg cmdstr, cmd; .print(.motd()); . protected tell_error arg syntax, [problem]; var problem, line, sprefix, prefix, length; length = 79; if (syntax) .print("=> Syntax: `" + syntax + "`"); if (problem) { for line in (problem) { if (type(line) == 'string) line = line.wrap_lines(length, "! ", 1); .print(line); } } .print("! ** use h?elp for a list of commands and their usages **"); throw(~stop, "", 'no_traceback); . public connection_starting arg host, port; (> .perms(caller(), $connection) <); .print(.motd()); . public parse_line arg line; var cmd, c, match, parsed, i, m, a, u; catch any { while (line && line[1] == " ") line = line.subrange(2); if (!line) { return .null_cmd(line); } else { cmd = line.explode(); cmd = [line, cmd[1], cmd.subrange(2).to_string() || ""]; c = (| $login_interface.match_in_local_cache(@cmd) |); if (c && c[1] == 'local) { // screw duplicates, take the first match match = c[2][1]; m = match[2]; i = match[5]; parsed = i.keys(); for a in [1 .. m.length()] { if (a in parsed) m = m.replace(a + 2, (> $command_parser.convert_arg(i[a][1], m[a + 2], $no_one, i[a][2] ? i[a][2][1] | $no_one, $no_one) <)); } return (> .(match[4])(@m) <); } return (> .invalid_cmd(line) <); } } with handler { if (traceback()[1][3] != 'no_traceback) { .print($parse_lib.traceback(traceback())); return 'disconnect; } } . public daemon_shutdown var i; (> .perms(caller(), $daemon) <); for i in (.children()) (| i.destroy() |); . parent $connection_interface object $http_interface var $root objname 'http_interface var $root child_index 1843 var $root writes [$http_connection_1854] var $root created_on 809075102 var $root inited 1 var $root indestructable 1 var $root quota_exempt -1 var $root managed [$http_interface_1843] var $root flags ['parameters, 'methods, 'code, 'core] var $root owned [$http_interface_1843] var $has_commands shortcuts #[] var $has_commands remote #[] var $has_commands local #[] var $command_cache shortcut_cache [] var $command_cache remote_cache 0 var $command_cache local_cache 0 var $http_interface cache [] var $http_interface method "GET" var $http_interface http "HTTP/0.9" var $http_interface status 405 var $http_interface URI "/" var $http_interface bytes 205 var $http_interface ctype 0 var $http_interface connection 0 var $http_interface cached 0 var $http_interface full 0 var $http_interface header 0 public new arg c; var i; (> .perms(caller(), $connection) <); i = .pull_from_cache(); i.set_connection(c); return i; . public pull_from_cache var i; if (sender() != this()) throw(~perm, "Sender is not this."); return .spawn(); while (cache) { i = cache[1]; cache = cache.delete(1); if (valid(i)) break; } if (i) { i.set_cached(1); return i; } else { return .spawn(); } . public add_obj_to_cache arg i; if (caller() != definer()) throw(~perm, "Sender is not this."); i.destroy(); return; if (!cache) cache = []; cache = cache.setadd(i); i.set_cached(1); . public del_obj_from_cache arg i; if (sender() != this()) throw(~perm, "Sender is not this."); if (!cache) return; cache = cache.setremove(i); i.set_cached(0); . root init_http_interface .initialize_http(); . public close var c; if (connection) { .log_request(connection.address()); c = connection; connection = 0; c.close(); definer().add_obj_to_cache(this()); } . public connection_starting arg addr, port; . public connection_going_away arg addr, port; (| .close() |); .initialize_http(); definer().add_obj_to_cache(this()); . public initialize_http if (caller() != definer()) throw(~perm, "Caller is not " + definer().objname()); method = ""; http = "HTTP/1.0"; status = 200; URI = ""; bytes = 0; ctype = $http_lib.html_version(); full = 1; header = #[]; . public send_header arg [lines]; if (!full) return; connection.write([http + " " + tostr(status), "Server: ColdWeb-db/0.2", "Content-type: " + ctype, "Content-length: " + tostr(bytes)] + lines + [""]); . public respond arg body; if (type(body) != 'buffer) body = $buffer.from_strings(body); bytes = body.length(); .send_header(); connection.write(body); .close(); . public respond_with_file arg fstat; bytes = fstat[2]; .send_header(); connection.echo_file("html" + URI); .close(); . public find_filename var file, actual, stat, ifiles, i; stat = (| stat_file("html" + URI) |); if (!stat) { ifiles = ["home.html", "index.html", "welcome.html"]; file = URI; actual = URI; if (file[file.length()] != "/") file = file + "/"; while (!stat && ifiles) { URI = file + ifiles[1]; stat = (| stat_file("html" + URI) |); ifiles = ifiles.delete(1); } if (!stat) { URI = actual; status = 404; .respond($http_lib.response(status, "Unable to find URL " + toliteral(URI) + ".")); return 0; } } if (i = URI.rindex(".")) { switch (URI.subrange(i + 1)) { case "txt": ctype = "text/plain"; case "gif": ctype = "image/gif"; } } return stat; . public process_header arg line, i; var n, v; if (!method) { status = 400; return .respond($http_lib.response(400, "No Method Specified!")); } n = line.subrange(1, i - 1); if (line[i + 1] == " ") i = i + 1; v = line.subrange(i + 1); header = header.add_elem(n, v); . public process_method arg line; line = line.explode(); if (!(line[1] in $http_lib.http_methods())) { status = 405; return .respond($http_lib.response(status, "Method: \"" + line[1] + "\".")); } method = line[1]; line = line.delete(1); if (!line) { status = 400; return .respond($http_lib.response(status, "No URI specified!")); } URI = line[1]; if (line.length() > 1) { http = line[2]; } else { http = "HTTP/0.9"; full = 0; } . public handle_method if (!method) { status = 400; return .respond($http_lib.response(status, "No Method specified!")); } .(tosym("http_method_" + method))(); . public parse_line arg line; var i; if (i = ":" in line) { .process_header(line, i); } else if (line) { .process_method(line); if (!full) { if (method != "GET") { status = 400; .respond($http_lib.response(status, "Invalid HTTP/0.9 method.")); } else { .handle_method(); } } } else { .handle_method(); } . public log_request arg host; var line; line = host + " - - [" + $time.format("%d %h %y %H:%M") + "] \"" + method + " " + URI + " " + http + "\" " + tostr(status) + " " + tostr(bytes); if ((| header["User-Agent"] |)) line = line + ";; " + header["User-Agent"].to_string(); $sys.log(line); . public http_method_GET var info, target, gate; if (URI == "/") { .respond($motd.build_html()); } else if ($string.match_begin(URI, "/~")) { target = (| $user_db.find((URI.explode("/"))[1].subrange(2)) |); info = (| target.setting("home-page") |); if (info) { status = 302; .redirect(info); } else { status = 404; .respond($http_lib.response(404, "Unable to find user " + (URI.explode("/"))[1].subrange(2))); } } else if ($string.match_begin(URI, "/bin")) { target = URI.explode("/").delete(1); if (!target) { status = 300; return .respond($http_lib.response(300, ["Multiple Choices: "] + $http_lib.list_gateways())); } gate = target[1]; target = target.delete(1); if ("?" in gate) { target = [gate.subrange(("?" in gate) + 1), @target]; gate = gate.subrange(1, ("?" in gate) - 1); } if (!(gate in $http_lib.gateways().keys())) { status = 502; .respond($http_lib.response(502, "Bad gateway: \"" + gate + "\"")); } else if (!gate) { status = 300; return .respond($http_lib.response(300, ["Multiple Choices: "] + $http_lib.list_gateways())); } else { catch any { info = (> $http_lib.(tosym("bin_" + gate))(@target) <); status = info[1]; if (type(info[2]) == 'buffer || status != 200) return .respond(info[2]); return .respond(info[2] + $http_lib.page_tail()); } with handler { status = 500; return .respond($http_lib.html_traceback(500, traceback())); } } } else if (info = .find_filename()) { .respond_with_file(info); } . public http_method_HEAD var stat; if (!stat = .find_filename()) return; bytes = stat[2]; .send_header(); .respond_with_file(stat); .close(); . public set_connection arg c; (> .perms(caller(), definer()) <); connection = c; . public set_cached arg v; if (caller() != definer()) throw(~perm, "Caller is not " + definer().objname() + "."); cached = v; . public redirect arg location; var body; body = $buffer.from_strings($http_lib.response(302, "Relocated at: " + location)); bytes = body.length(); .send_header("Location: " + location); connection.write(body); .close(); . parent $help_index object $help_index_root var $root objname 'help_index_root var $root created_on 806626103 var $root inited 1 var $root flags ['parameters, 'methods, 'code, 'core] var $named name ['prop, "Index", "Index"] var $named name_aliases [] var $help_index topics [] parent $help_node object $help_summary var $root inited 1 var $root objname 'help_summary var $root created_on 796268969 var $root flags ['parameters, 'methods, 'code, 'core] var $named name ['prop, "Summary", "Summary"] var $named name_aliases [] var $help_node linked_by [] var $help_node links #[] var $help_node body <$ctext2_frob, [["This help system is still being re-engineered, for now access the help topics via the world wide web at:", " ", <$ctext_format, ["p", #[], #[], [], 'do_p]>, "http://www.cold.org:8080/Software/ColdCore/help/"], #[['line, 2], ['this, $help_summary]]]> parent $note object $log var $root child_index 4 var $root fertile 1 var $root trusted [] var $root inited 1 var $root objname 'log var $root created_on 796268969 var $root flags ['methods, 'code, 'fertile, 'core] var $messaged verbs #[["read * on %this", ['read_cmd, 'remote]]] var $described prose ["the place that Ye administrators should be logging somewhat impacting changes that others would like to know about."] var $gendered gender $gender_neuter var $located location $nowhere var $located obvious 1 var $named name ['uniq, "Generic Log", "the Generic Log"] var $named name_aliases ["log", "changes", "log"] var $text text ["9-28-94/22:33:17> foo"] var $public public ['readable] var $has_commands remote #[["read", [["read", "* on *", "read <any> on <this>", 'read_cmd, #[[1, ['any, []]], [3, ['this, []]]]]]]] public read_cmd arg [args]; var loglen, text; if (0) { // later on i'll adjust this so you can 'read from line 12 on log' return; } else { text = .text(); loglen = text.length(); sender().tell(["---", .namef() + ", entries " + tostr(loglen - 10) + " to " + tostr(loglen) + " (last 10 lines).", "---"]); sender().tell(text.subrange(loglen - 10)); sender().tell("---"); } . public log arg line; var l; (> .perms(caller(), 'trusts) <); if (type(line) == 'list) { for l in (line) .ins_line($time.format("%d %h %y %H:%M") + "> " + l); } else { .ins_line($time.format("%d %h %y %H:%M") + "> " + line); } . parent $event_frob object $movement_event var $root inited 1 var $root objname 'movement_event var $root created_on 796268969 var $root flags ['parameters, 'methods, 'code, 'core] var $event_frob type 'movement public exit arg event; return event['exit]; . public new arg actor, source, dest; // (> .perms(caller(), $exit) <); return (<this(), #[['exit, sender()], ['actor, actor], ['source, source], ['dest, dest]]>); . public dest arg frob; return frob['dest]; . public source arg args; return args[3].source(); . public dispatch arg dict; dict['source].announce_event((<this(), dict>)); dict['dest].announce_event((<this(), dict>)); . public process arg dict; . public actor arg frob; return frob['actor]; . parent $time_root object $time var $root inited 1 var $root objname 'time var $root created_on 796268969 var $root flags ['parameters, 'methods, 'code, 'core] var $time_root secs_per_min 60 var $time_root secs_per_hour 3600 var $time_root secs_per_day 86400 var $time_root secs_per_week 604800 var $time_root secs_per_year 31536000 var $time_root created_on 0 var $time_root mins_per_hour 60 var $time_root hours_per_day 24 var $time_root days_per_year 365 var $time_root year_begin 0 var $time_root days ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"] var $time_root months #[["Jan", ["January", 1, 31]], ["Feb", ["February", 2, 28]], ["Mar", ["March", 3, 31]], ["Apr", ["April", 4, 30]], ["May", ["May", 5, 31]], ["Jun", ["June", 6, 30]], ["Jul", ["July", 7, 31]], ["Aug", ["August", 8, 31]], ["Sep", ["September", 9, 30]], ["Oct", ["October", 10, 31]], ["Nov", ["November", 11, 30]], ["Dec", ["December", 12, 31]]] var $time_root standard 1 public format arg [args]; return (> strftime(@args) <); . public elapsed arg time, [flag]; var str, t, p; // compares args[1] with time() and returns hh:mm elapsed // will eventually make flags do things like 'long etc. For now its // just your own time, rather than time(). flag = [@flag, 'stopwatch][1]; str = ""; switch (flag) { case 'long: return .to_english(time); default: if (time > 356400) p = 3; else p = 2; str = str + tostr(time / 3600).pad(-p, "0"); str = str + ":" + tostr(time % 3600 / 60).pad(-2, "0"); return str; } . public dhms arg secs, [long]; var ret_str, x; if (long) long = 1; if (secs > 86400) { x = secs / 86400; ret_str = tostr(x) + (long ? " day" + (x < 2 ? "" | "s") | "d"); } else if (secs > 3600) { x = secs / 3600; ret_str = tostr(x) + (long ? " hr" + (x < 2 ? "" | "s") | "h"); } else if (secs > 60) { x = secs / 60; ret_str = tostr(x) + (long ? " min" + (x < 2 ? "" | "s") | "m"); } else { ret_str = tostr(secs) + (long ? " sec" + (secs < 2 ? "" | "s") | "s"); } return ret_str; . public month_str arg [args]; var month, m, time, option; // args[1] = time (opt); args[2] == 'num, 'long, 'short; if (args && type(args[1]) != 'integer) { time = time(); option = [@args, 'long][1]; } else { time = [@args, time()][1]; option = [@args, 'long, 'long][2]; } if (type(time) == 'integer) month = ctime(time).subrange(5, 3); else month = time.subrange(5, 3); // special case: switch (option) { case 'short: return month; case 'num: return tostr((.months())[month][2]); default: return (.months())[month][1]; } . public year_str arg [time]; var how; // (time, how) time defaults to time(), how defaults to long how = [@time, 'long, 'long][2]; time = [@time, .time()][1]; if (how == 'long) return ctime(time).subrange(21); return ctime(time).subrange(23); . public ldate arg [args]; var time, ctime, how, options, sep, hrs, mins, secs; // takes a bunch of numbers and returns info depending upon what the // symbol is. Time is optional, so is how for that matter. // options are listed to the right of the descriptions. // How: 'long -- Monday, January 10th, 1994 (default) // 'noyear -- 'long without the year. // 'short -- Mon, Jan 10, 94 // 'date -- 01-Dec-95 (ie: DD-MMM-YY) // 'dmy -- 10/01/94 (ie: DD/MM/YY) ['slash | 'dash] // 'mdy -- 01/10/94 (ie: MM/DD/YY) ['slash | 'dash] // 'ymd -- 94/10/01 (ie: YY/MM/DD) ['slash | 'dash] args = [@args, 'long]; if (type(args[1]) != 'integer) { time = time(); how = args[1]; args = args.delete(1); } else { time = args[1]; how = args[2]; args = args.subrange(3); } // figure options first options = [@args, 0][1]; sep = "/"; if (options) { switch (options) { case 'dash: sep = "-"; case 'slash: sep = "/"; } } // figure actual time switch (how) { case 'long: return .day_str(time) + ", " + .month_str(time) + " " + .month_day_str(time, 'num) + ", " + .year_str(time); case 'noyear: return .day_str(time) + ", " + .month_str(time) + " " + .month_day_str(time, 'num); case 'short: ctime = ctime(time); return ctime.pad(3) + "," + ctime.subrange(4).pad(7) + ", `" + .year_str(time, 'short); case 'date: return .month_day_str(time) + "-" + .month_str(time, 'short) + "-" + .year_str(time, 'short); case 'dmy: return .month_day_str(time) + sep + .month_str(time, 'num) + sep + .year_str(time, 'short); case 'mdy: return .month_str(time, 'num) + sep + .month_day_str(time) + sep + .year_str(time, 'short); case 'ymd: return .year_str(time, 'short) + sep + .month_str(time, 'num) + sep + .month_day_str(time, 'num); } . public ltime arg [args]; var time, ctime, how, options, sep1, sep2, ampm, hrs, mins, secs; // takes a bunch of numbers and returns info depending upon what the symbol is // time is optional, so is how for that matter. Uses '12hr '_ampm for default // options are listed after the descriptions. // '24hr -- 24:00 ['a_m_p_m|'ampm|'_ampm|'ap|'no_ampm] // '12hr -- 12:00 ['a_m_p_m|'ampm|'_ampm|'ap|'no_ampm] // '24hr_sec -- 24:00:00 ['a_m_p_m|'ampm|'_ampm|'ap|'no_ampm] // '12hr_sec -- 12:00:00 ['a_m_p_m|'ampm|'_ampm|'ap|'no_ampm] // 'long -- twelve thirty four pm['a_m_p_m|'ampm|'_ampm|'no_ampm] // 'hour -- Twelve o'clock // BTW, incase your wondering, ltime stands for Lynx Time; i'm a bastard 8b args = [@args, '12hr]; if (type(args[1]) != 'integer) { time = time(); how = args[1]; args = args.delete(1); } else { time = args[1]; how = args[2]; args = args.subrange(3); } // figure options first options = [@args, '_ampm][1]; sep1 = "/"; sep2 = ":"; ampm = ["", ""]; if (options) { switch (options) { case 'dash: sep1 = "-"; case 'slash: sep1 = "/"; case 'a_m_p_m: ampm = [" a.m.", " p.m."]; case 'ampm: ampm = ["am", "pm"]; case '_ampm: ampm = [" am", " pm"]; case 'ap: ampm = ["a", "p"]; case 'no_ampm: ampm = ["", ""]; } } // figure actual time switch (how) { case '24hr: return .ctime(time).subrange(12, 5); case '24hr_sec: return .ctime(time).subrange(12, 8); case '12hr: time = .hr_min_sec(time); hrs = toint(time[1]); ampm = hrs < 12 ? ampm[1] | ampm[2]; hrs = hrs % 12; hrs = hrs == 0 ? 12 | hrs; return tostr(abs(hrs)) + sep2 + time[2] + ampm; case '12hr_sec: time = .hr_min_sec(time); hrs = toint(time[1]); ampm = hrs < 12 ? ampm[1] | ampm[2]; hrs = hrs % 12; hrs = hrs == 0 ? 12 | hrs; return tostr(hrs) + sep2 + time[2] + sep2 + time[3] + ampm; } . public day_str arg [args]; var day, days, d, time, option; if (args && type(args[1]) != 'integer) { time = time(); option = [@args, 'long][1]; } else { time = [@args, time()][1]; option = [@args, 'long, 'long][2]; } if (type(time) == 'integer) day = (ctime(time).explode())[1]; else day = (time.explode())[1]; days = .days(); switch (option) { case 'num: return .month_day_str(); case 'short: return day; default: for d in (days) { if ($string.match_begin(d, day)) return d; } } . public month_day_str arg [time]; time = .ctime([@time, .time()][1]); return time.subrange(9, 2).replace(" ", "0"); . public hr_min_sec arg [time]; var ctime; ctime = .ctime(@time); return [ctime.subrange(12, 2), ctime.subrange(15, 2), ctime.subrange(18, 2)]; . public time_stamp return .ldate('date) + "/" + $time.ltime('24hr_sec); . public to_english arg time, [reftime]; var times, words, x, seconds, ctime, months, month, year, days, out; // most of this was stolen from MOO (und ve are evil) if (time < 1) return "0 seconds"; reftime = reftime || time(); ctime = type(reftime) == 'integer ? ctime(reftime) | reftime; words = ["year", "month", "day", "hour", "minute", "second"]; times = []; seconds = [60, 60, 24]; for x in (seconds) { times = [time % x, @times]; time = time / x; } months = 0; month = (.months())[ctime.subrange(5, 3)][2]; year = toint(.year_str(reftime)); days = (.months())[ctime.subrange(5, 3)][3]; while (time >= days + (month == 2 && year % 4 == 0 && !(year % 400 in [100, 200, 300]))) { time = time - days; months = months + 1; month = month + 1; if (month > 12) { year = year + 1; month = 1; } } times = [months / 12, months % 12, time, @times]; out = []; for x in [1 .. words.length()] { if (times[x] > 0) out = [@out, tostr(times[x]) + " " + words[x] + (times[x] == 1 ? "" | "s")]; } return $list.to_english(out); . public date arg [args]; var time, opt; time = [@args, time()][1]; opt = [@args, 'long, 'long][2]; if (type(time) != 'integer) throw(~type, "Time must be submitted as an integer."); switch (opt) { case 'short: return ctime(time); default: return .ltime(time) + ", " + .ldate(time); } . parent $time_root object $dark_time var $root inited 1 var $root objname 'dark_time var $root created_on 796268969 var $root flags ['parameters, 'methods, 'code, 'core] var $time_root created_on 695533749 var $time_root hours_per_day 21 var $time_root days_per_year 345 var $time_root year_begin 425 var $time_root secs_per_min 60 var $time_root secs_per_hour 4320 var $time_root secs_per_day 90720 var $time_root secs_per_week 453600 var $time_root secs_per_year 41731200 var $time_root mins_per_hour 72 var $time_root standard 0 public paradise_time arg [args]; var time, hour, mde; // args: terran time() == output of server builtin. // 'seconds == with seconds // 'no_mde == with morning/day/evening hour pre-pension if (args && type(args[1]) == 'integer) { time = .convert(args[1]); args = args.delete(1); } else { time = .time(); } hour = .hour(time); mde = hour > 7 ? hour > 14 ? "eh " | "dh " | "mh "; if (args && 'no_mde in args) mde = ""; hour = hour % 7; hour = hour == 0 ? 7 | hour; if (args && 'seconds in args) return mde + tostr(hour) + ":" + tostr(.minute(time)).pad(2, "0") + ":" + tostr(.second(time)).pad(2, "0"); else return mde + tostr(hour) + ":" + tostr(.minute(time)).pad(2, "0"); . public ilraitheen_time arg [args]; var time; // args: terran time() == output of server builtin. // 'seconds == with seconds if (args && type(args[1]) == 'integer) { time = .convert(args[1]); args = args.delete(1); } else { time = .time(); } if (args && type(args[1]) == 'symbol) return tostr(.hour(time)) + ":" + tostr(.minute(time)).pad(2, "0") + ":" + tostr(.second(time)).pad(2, "0"); else return tostr(.hour(time)) + ":" + tostr(.minute(time)).pad(2, "0"); . parent $mail_root object $mail_envelope var $root objname 'mail_envelope var $root created_on 800473788 var $root inited 1 var $root flags ['parameters, 'methods, 'code, 'core] parent $mail_root object $mail_address var $root objname 'mail_address var $root created_on 800473783 var $root inited 1 var $root flags ['parameters, 'methods, 'code, 'core] parent $db object $registry var $root fertile 1 var $root inited 1 var $root objname 'registry var $root created_on 796268969 var $root flags ['parameters, 'methods, 'code, 'fertile, 'core] var $db database #[] var $registry stripped_characters "" var $registry min_char_len 0 var $registry max_char_len 0 var $registry max_word_len 0 var $registry reserved_names [] var $registry invalid_names [] root uninit_registry reserved_names = 0; invalid_names = 0; trusted = 0; stripped_characters = 0; . public set_max_word_len arg value; .perms(sender(), 'manager); if (type(value) != 'integer) throw(~type, "Value is not an integer"); max_word_len = value; . public set_max_char_len arg value; .perms(sender(), 'manager); if (type(value) != 'integer) throw(~type, "Value is not an integer"); max_char_len = value; . public set_min_char_len arg value; .perms(sender(), 'manager); if (type(value) != 'integer) throw(~type, "Value is not an integer"); min_char_len = value; . public set_stripped_characters arg string; .perms(sender(), 'manager); if (type(string) != 'string) throw(~type, "Value is not a string."); stripped_characters = string; . public insert arg name, obj; // registers obj with obj.name // .perms(caller(), 'trusts); if (stripped_characters) name = $string.strip(name, stripped_characters); (> pass(name, obj) <); . public remove arg name; // removes the object from the database. // THIS: is what is broken with guests, should fix it. // .perms(caller(), 'trusts); if (stripped_characters) name = $string.strip(name, stripped_characters); (> pass(name) <); . public database if (!.has_flag('parameters, sender())) throw(~perm, "Database is not readable by sender."); return (> pass() <); . public exact_match arg name; // returns a direct match of the name (if there is one) if (!.has_flag('parameters, sender())) throw(~perm, "Database is not readable by sender."); if (stripped_characters) name = $string.strip(name, stripped_characters); return (> pass(name) <); . public valid_name arg name; var word, sname; // returns 1 if the name is valid /// if (!.has_flag('parameters,sender())) // throw(~perm, "Database is not readable by sender."); (> .perms(caller(), 'trusts) <); // check name itself first sname = name; if (stripped_characters) sname = $string.strip(name, stripped_characters); if (max_word_len && name.explode().length() > max_word_len) throw(~invname, "Names can only be " + tostr(max_word_len) + " words long."); if (min_char_len && sname.length() < min_char_len) throw(~invname, "Names must have at least " + tostr(min_char_len) + " alpha-numeric characters in them"); if (max_char_len && name.length() > max_char_len) throw(~invname, "Names can only be " + tostr(max_char_len) + " characters long."); // see if it already exists if ((| .exact_match(name) |)) { if (!((.database())[sname] == sender())) throw(~invname, "Name already exists."); } // check reserved and invalid names for word in (name.explode()) { if (reserved_names && word in reserved_names) throw(~invname, "`" + word + "' is a reserved name."); if (invalid_names) { for word in (invalid_names) { if ($string.match_pattern("*" + word + "*", name)) throw(~invname, "`" + word + "' is not allowed as part of a name."); } } } . public match_begin arg name; var matches, obj; // returns a direct match, or partial matches if (stripped_characters) name = $string.strip(name, stripped_characters); return (> pass(name) <); . public stripped_characters return stripped_characters; . public key_changed arg old_name, new_name; // adjusts the database for the new name .perms(caller(), 'trusts); if (stripped_characters) { old_name = $string.strip(old_name, stripped_characters); new_name = $string.strip(new_name, stripped_characters); } (> pass(old_name, new_name) <); . public find arg name; var tmp; if (.stripped_characters()) name = $string.strip(name, .stripped_characters()); name || throw(~namenf, "No matches found."); tmp = (| .exact_match(name) |); if (tmp) return tmp; catch any { tmp = (> .match_begin(name) <); } with handler { switch (error()) { case ~ambig: rethrow(error()); default: throw(~namenf, "No matches found."); } } return tmp; . parent $registry parent $mail_root object $mail_db var $root trusted [] var $root inited 1 var $root objname 'mail_db var $root created_on 796268969 var $root indestructable 1 var $root flags ['parameters, 'methods, 'code, 'core] var $db database #[["news", $mail_list_news], ["bugs", $mail_list_bugs]] public valid_recipient arg recip; if (recip.has_ancestor($mail_list)) return 1; return 0; . public mail_name arg obj; return "*" + obj.namef(); . parent $user_parsers object $null_parser var $root inited 1 var $root objname 'null_parser var $root created_on 796268969 var $root flags ['parameters, 'methods, 'code, 'core] public parse arg user, str, [anything_else]; var i; for i in [1 .. str.length()] { if (str[i] != " ") return 'failed; } return 'ok; . parent $user_parsers object $command_aliases_parser var $root trusted [] var $root inited 1 var $root objname 'command_aliases_parser var $root created_on 796268969 var $root flags ['parameters, 'methods, 'code, 'core] public parse arg user, str, next_parser, [other_parsers]; var alias, match, i, result; for alias in (user.command_aliases()) { match = $string.match_pattern(alias[1], str); if (match != 0) { str = alias[2]; for i in [1 .. match.length()] str = str.replace("%" + tostr(i), match[i]); break; } } result = next_parser.parse(user, str, @other_parsers); if (match != 0 && result == 'failed) return "Command converted to \"" + str + "\" but not understood."; return result; . parent $user_parsers object $command_parser var $root objname 'command_parser var $root created_on 796680318 var $root inited 1 var $root indestructable 1 var $root flags ['parameters, 'methods, 'code, 'core] public parse arg u, str, next_parser, [other_parsers]; var l, cmd, c, p, obj; while (str && str[1] == " ") str = str.subrange(2); if (str) { cmd = str.explode(); cmd = [str, cmd[1], cmd.subrange(2).to_string() || ""]; p = []; if (c = (| u.match_in_shortcut_cache(@cmd) |)) { if (c[1] == 'shortcut) return .shortcut(u, @c[2]); p = c[2]; } if (c = (| u.match_in_local_cache(@cmd) |)) { if (c[1] == 'local) return .local(u, @c[2]); p = p + c[2]; } if (c = (| u.match_in_remote_cache(@cmd) |)) { if (c[1] == 'remote) return .remote(u, @c[2]); p = p + c[2]; } l = u.location(); if (c = (| l.match_in_locl_cache(@cmd) |)) { if (c[1] == 'remote) return .remote(u, @c[2]); p = p + c[2]; } if (c = (| l.match_in_remote_cache(@cmd) |)) { if (c[1] == 'remote) return .remote(u, @c[2]); p = p + c[2]; } if (c = (| .grasp_for_remote_command(@cmd) |)) return .remote(u, @c[2]); for obj in ((| u.location().exits() |) || []) { if (obj.match_name(str)) return [obj, 'invoke]; } if (p) return .partial(u, cmd, p); } return next_parser.parse(u, str, @other_parsers); . public partial arg user, args, templates; var part, line; for part in (templates) templates = templates.replace(part in templates, toliteral(part)); if (templates.length() == 1) line = toliteral(args[2]) + " could match "; else if (templates.length() == 2) line = toliteral(args[2]) + " could match either "; else line = toliteral(args[2]) + " could match any of "; return line + templates.to_english("", " or ") + "."; . public shortcut arg user, method, parsed; return [user, method, @parsed]; . public complete arg cmd, user, obj, match, info; var x, method, parsed; method = info[2]; info = info[4]; parsed = info.keys(); for x in [1 .. match.length()] { if (x in parsed) match = match.replace(x, (> $command_lib.convert_arg(info[x][1], match[x], user, info[x][2] ? info[x][2] | user, user) <)); } return [user, method, (cmd.explode())[1], @match]; . public grasp_for_remote_command arg str, cmd, args; var reg, obj, cdef, match, matched, pick, info; reg = $string.match_regexp("[$#][a-z_0-9][a-z_0-9]*", args); if (!reg) return 0; obj = (| $object_lib.to_dbref(args.subrange(@reg[1])) |); if (!obj) return 0; info = (| obj.get_command_info('remote, cmd) |); if (!info) return 0; matched = []; for cdef in (info) { match = $string.match_template(cdef[2], args); if (match != 0) matched = matched + [[match.length(), obj, [str, cmd, @match], @cdef.subrange(3)]]; } if (matched) { pick = matched[1]; matched = matched.delete(1); for match in (matched) { if (match[1] > pick[1]) pick = match; } return ['remote, pick.delete(1)]; } return ['partial, [[str, cmd], info.slice(3)]]; . public local arg user, [matches]; var parsed, match; parsed = []; for match in (matches) { match = ._local(user, @match); if (match[1] == 'match) return match.delete(1); parsed = [match[2]] + parsed; } return 0; . public remote arg user, [matches]; var parsed, match; parsed = []; for match in (matches) { match = ._remote(user, @match); if (match[1] == 'match) return match.delete(1); parsed = [match[2]] + parsed; } return parsed[1]; . public handle_error arg traceback; return traceback[1][2]; . public _remote arg user, nmatch, definer, match, template, method, info; var x, parsed, str, value, that, tinfo, new, c; parsed = info.keys(); catch any { for x in [1 .. nmatch] { if (x in parsed) { if (info[x][1] == 'this) { value = (> user.match_environment(match[x + 2]) <); // talk about a hack around, hope its not a prob if (!value.has_ancestor(definer)) { tinfo = (| value.get_command_info('remote, match[2]) |); if (!tinfo || tinfo[1] != 'remote) return ['error, value.name('def).capitalize() + " does not define remote command \"" + template + "\""]; // mebbe we'll get lucky... tinfo = tinfo[2]; for c in (tinfo) { if (c[3] == template) { new = 1; definer = value; method = c[4]; } } // we should only do this once if (!new) return ['error, value.name('def).capitalize() + " does not define remote command \"" + template + "\""]; } that = value; } else { value = (> .convert_arg(info[x][1], match[x + 2], user, info[x][2] ? info[x][2][1] | definer, user) <); } match = match.replace(x + 2, value); } } } with handler { return ['error, .handle_error(traceback())]; } if (!that) return ['error, "An error was encountered: no target object found."]; return ['match, that, method, @match]; . public _local arg user, nmatch, match, template, method, info; var x, parsed, str; parsed = info.keys(); catch any { for x in [1 .. match.length()] { if (x in parsed) match = match.replace(x + 2, (> .convert_arg(info[x][1], match[x + 2], user, info[x][2] ? info[x][2][1] | user, user) <)); } } with handler { ['error, .handle_error(traceback())]; } return ['match, user, method, @match]; . public convert_arg arg type, str, me, ancestor, target; var obj; switch (type) { case 'any: return str; case 'object: return (> me.match_environment(str) <); case 'objref: return (> $parse_lib.xreference(str, me, [me, 'match_environment, []]) <); case 'user: if (str == "me") return me; return (> $user_db.find(str) <); case 'number: return (> str.to_number() <); case 'descendant: obj = (> me.match_environment(str) <); if (!obj.has_ancestor(ancestor)) throw(~parse, obj.name() + " is not descended from " + ancestor.name() + "!"); return obj; } . parent $user_parsers object $conference_parser var $root trusted [] var $root inited 1 var $root objname 'conference_parser var $root created_on 796268969 var $root flags ['parameters, 'methods, 'code, 'core] public parse arg user, str, next_parser, [other_parsers]; if (str && str[1] == ">") str = str.subrange(2); else str = "say " + str; return next_parser.parse(user, str, @other_parsers); . parent $filters object $epic_filter var $root inited 1 var $root objname 'epic_filter var $root created_on 796268969 var $root flags ['parameters, 'methods, 'code, 'core] public old_filter arg input; var output, x, z, line; // this filter MUST be first in the filters list.. output = []; input = .compress(input); for z in (input) { line = []; z = ($string.explode_delimited(z, "<", ">"))[1]; for x in (z) { if (type(x) == 'string) line = [@line, x]; } output = [@output, $list.to_string(line, "")]; } return output; . public filter arg what; var tags; $jeff.debug('filter, what); if (type(what) != 'frob) return what; if (!(class(what) in [$ctext])) return what; $jeff.debug('frob); what = what.evaluate(sender()); $jeff.debug(what); return what; . parent $filters object $wrap_filter var $root inited 1 var $root objname 'wrap_filter var $root created_on 796268969 var $root flags ['parameters, 'methods, 'code, 'core] public filter arg input; var len, output, e, line; len = sender().linelen(); output = []; input = .compress(input); for e in (input) { e = $string.wrap_line(e, len); output = [@output, e[1]]; for line in (e.subrange(2)) output = [@output, " " + line]; } return output; . parent $filters object $ctext_filter var $root inited 1 var $root objname 'ctext_filter var $root created_on 796268969 var $root flags ['parameters, 'methods, 'code, 'core] public filter arg what, [defaults]; var dic, output; dic = [@defaults, #[]][1].union(#[['receiver, sender()], ['time, 'post], ['formatter, $cml2_telnet_format]]); switch (class(what)) { case $message_frob: output = what.format(dic); case $ctext2_frob: what = what.set_vars(dic); output = what.format(); case $ctext_frob: output = what.eval_ctext(dic); case $ctext_format: output = dic['formatter].eval_ctext(what, dic); default: output = what; } return output; . parent $cml2 object $cml2_evaluator var $root objname 'cml2_evaluator var $root child_index 3 var $root created_on 806300471 var $root inited 1 var $root flags ['parameters, 'methods, 'code, 'core] public eval_ctext arg data, [vars]; var ret; vars = [@vars, #[]][1]; vars = vars.add('line, 1); ret = ._eval_ctext(vars, data); return $ctext2_frob.new(ret[1], ret[2].add('evaluator, this())); . public eval_generator arg vars, gen; var flags, key, value, ret, name; flags = gen.ctext_uflags(); for key in (flags.keys()) { ret = ._eval_ctext(vars, flags[key]); gen = gen.add_ctext_flag(key, ret[1]); vars = ret[2]; } catch ~methodnf { ret = .(gen.method())(vars, gen.ctext_flags(), gen.args()); return [ret[1], ret[2]]; } with handler { catch ~keynf { return [[vars[gen.name()]], vars]; } with handler { return [[">>ERROR: Unknown generator [" + gen.name() + "] on line " + tostr(vars['line]) + ".<<"], vars]; } } . public eval_formator arg vars, form; var flags, ret, key; if (vars['time] == 'format) return vars['formatter]._eval_ctext(vars, form); flags = form.ctext_uflags(); for key in (flags.keys()) { ret = ._eval_ctext(flags[key], vars); form = form.add_ctext_flag(key, ret[1]); vars = ret[2]; } catch ~methodnf { return .(tosym("do_" + form.name()))(vars, form.ctext_flags(), form.args()); } with handler { ret = ._eval_ctext(vars, form.args()); form = form.set_args(ret[1]); vars = ret[2]; return [[form], vars]; } . public _eval_ctext arg vars, data; var out, uflags, ret, token; out = []; if (type(data) != 'list) data = [data]; for token in (data) { if (type(token) == 'frob) { switch (class(token)) { case $ctext_generator: ret = .eval_generator(vars, token); out = [@out, @ret[1]]; vars = ret[2]; case $ctext_format: ret = .eval_formatter(vars, token); if (vars['time] == 'format) out = out.join(ret[1]); else out = [@out, @ret[1]]; vars = ret[2]; default: out = [@out, token]; } } else { out = [@out, token]; } } return [out, vars]; . public _eval_ctext_list arg vars, data; var out, uflags, ret, token; out = []; while (data) { token = data[1]; data = data.subrange(2); if (type(token) == 'frob) { if (class(token) == $ctext_generator) { ret = .eval_generator(vars, token); out = [@out, ret[1]]; vars = ret[2]; } else if (class(token) == $ctext_format) { ret = .eval_formatter(vars, token); out = [@out, ret[1]]; vars = ret[2]; } else { out = [@out, token]; } } else { out = [@out, token]; } } return [out, data, vars]; . public init return #[['line, 1]]; . public do_group arg vars, flags, args; var out, token, ret; out = []; for token in (args) { ret = ._eval_ctext(vars, token); if (out.length() && type(out.last()) == 'string && type((| ret[1][1] |) || ret[1]) == 'string) out = out.join(ret[1]); else out = [@out, @ret[1]]; vars = ret[2]; } return [out, vars]; . parent $cml2 object $cml2_form var $root objname 'cml2_form var $root created_on 806551381 var $root inited 1 var $root flags ['parameters, 'methods, 'code, 'core] var $cml2_form options #[["ul", []], ["strong", []], ["pre", []], ["dl", []], ["bold", []], ["anchor", []], ["em", []], ["link", []], ["web", []], ["hr", []], ["tt", []]] var $cml2_form fields #[["ul", ["lh", "li"]], ["strong", []], ["pre", []], ["dl", ["lh", "dt", "dd"]], ["bold", []], ["anchor", []], ["em", []], ["header", []], ["link", []], ["web", []], ["name", []], ["tt", []], ["action", []], ["subj", []], ["li", []], ["dt", []], ["dd", []]] public blocks return fields.keys(); . public is_block arg tag; return tag in fields.keys(); . public fields arg tag; return fields[tag]; . public has_field arg tag, field; return field in fields[tag]; . public options arg tag; return options.keys(); . public has_option arg tag, opt; return opt in options.keys(); . public add_block arg b; fields = fields.add(b, []); . public del_block arg b; fields = fields.del(b); . public add_field arg b, f; fields = fields.add_elem(b, f); . public del_field arg b, f; fields = fields.del_elem(b, f); . public add_tag arg t; options = options.add(t, []); . public del_tag arg t; (| fields = fields.del(t) |); options = options.del(t); . public add_option arg t, o; options = options.add_elem(t, o); . public del_option arg t, o; options = options.del_elem(t, o); . public tags return options.keys(); . public is_field arg field; var f, b; f = []; for b in (fields.values()) f = f.union(b); return field in f; . parent $cml2 object $cml2_compiler var $root objname 'cml2_compiler var $root created_on 806018078 var $root inited 1 var $root flags ['parameters, 'methods, 'code, 'core] public compile_cml arg text; var vars, ret; vars = #[['line, 1], ['this, sender()]]; text = .tokenize(text); ret = (> .parse_string(vars, text) <); return $ctext2_frob.new(ret[1], ret[3]); . public parse_string arg vars, tokens; var out, ret, word, token; word = ""; out = []; while (tokens) { token = tokens[1]; tokens = tokens.subrange(2); if (token in ["{", "["]) { if (word.length()) out = [@out, word]; word = ""; ret = .parse_command(vars, tokens, token); out = [@out, @ret[1]]; tokens = ret[2]; vars = ret[3]; } else if (token == "" || token[1] == " ") { if (word.length() || out.length()) word = word + " "; } else if (token in ["]", "}"]) { if (word.length()) out = [@out, word]; return [out, tokens, vars]; } else { word = word + token; } pause(); } if (word.length()) out = [@out, word]; return [out, tokens, vars]; . public parse_top arg vars, tokens; var out, ret, word, token; tokens = ._eat_space(tokens); out = []; while (tokens) { token = tokens[1]; tokens = tokens.subrange(2); switch (token) { case "{", "[": ret = (> .parse_command(vars, tokens, token) <); out = [@out, @ret[1]]; tokens = ret[2]; vars = ret[3]; case "]", "}": return [out, tokens, vars]; case "\"", "\\:": out = out.join(token); default: out = [@out, token]; } if (text.length() && tokens[1][1] == " ") { out = out.join(" "); token = token.subrange(2); } } return [out, tokens, vars]; . public parse_command arg vars, text, token; var ret, name, flags, args, end; name = ""; flags = []; args = []; text = ._eat_space(text); name = text[1]; if (name == ":") name = "group"; else text = text.subrange(2); text = ._eat_space(text); if (!(text[1] in ["]", "}", ":"])) { ret = .parse_flags(vars, text); flags = ret[1]; text = ret[2]; text = ._eat_space(text); vars = ret[3]; } if (text[1] == ":") { if (token == "[") ret = .parse_top(vars, text.subrange(2)); else ret = .parse_string(vars, text.subrange(2)); args = ret[1]; text = ret[2]; vars = ret[3]; } else if (token == "{" && $cml2_form.is_block(name)) { ret = .parse_nested(vars, text.subrange(2), name); args = ret[1]; text = ret[2]; vars = ret[3]; } else { text = text.subrange(2); } if (token == "{") ret = ._make_form(vars, name, flags, args); else ret = ._make_gen(vars, name, flags, args); return [ret[1], text, ret[2]]; . public parse_flags arg vars, tokens; var flags, flag, token, set, ret; set = 0; flag = ""; flags = []; while (tokens) { token = tokens[1]; tokens = tokens.subrange(2); switch (token) { case "}", "]", ":": return [flags, [token, @tokens], vars]; case "=": catch ~range { flag = flags.last(); } with handler { throw(~parse, "key=value flag with no key."); } flags = flags.chop(); if (type(flag) == 'list) throw(~parse, "key=value flag with no key."); set = 1; default: if (set) { switch (token) { case "{", "[": ret = .parse_command(vars, tokens, token); token = ret[1]; tokens = ret[2]; case "\"": ret = .parse_string(vars, tokens); token = ret[1]; tokens = ret[2]; } flags = [@flags, [flag, token]]; flag = ""; set = 0; } else { flags = [@flags, token]; } } } . public tokenize arg text; var spaces, word, out, escaped, char, i; //break text into a list of tokens. if (type(text) == 'list) text = text.to_string("{_ln}"); out = []; word = ""; spaces = ""; escaped = 0; for i in [1 .. text.length()] { char = text[i]; if (escaped) { escaped = 0; word = word + char; } else { switch (char) { case "\\": escaped = 1; if (spaces.length()) { out = [@out, spaces]; spaces = " "; } case " ": if (!spaces.length()) { if (word.length()) out = [@out, word]; word = ""; } spaces = spaces + " "; case "{", "}", "[", "]", "=", "\"", ":": if (spaces.length()) { out = [@out, spaces]; spaces = ""; } if (word.length()) out = [@out, word, char]; else out = [@out, char]; word = ""; default: if (spaces.length()) { out = [@out, spaces]; spaces = ""; } word = word + char; } } pause(); } if (spaces.length()) { out = [@out, spaces]; spaces = ""; } else if (word.length()) { out = [@out, word]; word = ""; } if (word.length()) return [@out, word]; return out; . public parse_list arg tokens; var out, ret, token; out = []; while (tokens) { token = tokens[1]; tokens = tokens.subrange(2); if (token in ["{", "["]) { ret = .parse_command(tokens); out = [@out, @ret[1]]; tokens = ret[2]; } else if (token in ["]", "}"]) { return [out, [token, @tokens]]; } else { out = [@out, token]; } } if (word.length()) out = [@out, word]; return [out, tokens]; . public parse_nested arg vars, tokens, name; var out, ret, token, word, start_line; if (name == "pre") return ._parse_pre(vars, tokens); start_line = vars['line]; word = ""; out = []; tokens = ._eat_space(tokens); while (tokens) { token = tokens[1]; tokens = tokens.subrange(2); if (token in ["{", "["]) { if (word.length()) { out = [@out, word]; word = ""; } ret = .parse_command(vars, tokens, token); tokens = ret[2]; out = [@out, @ret[1]]; vars = ret[3]; if (type(out.last()) == 'frob && class(out.last()) == $ctext_format && out.last().end()) { if (out.last().name().subrange(2) == name) return [out.chop(), tokens, vars]; else throw(~parse, "{" + name + "} at line " + tostr(start_line) + " ended by {" + out.last().name() + "} at line " + tostr(vars['line]) + "."); } } else { if (word.length()) word = word + " "; if (token[1] != " ") word = word + token; } pause(); } return [out, tokens, vars]; . public _make_gen arg vars, name, flags, args; var ret; catch ~methodnf { ret = .(tosym("gen_" + name))(vars, flags, args); return [ret[1], ret[2]]; } with handler { return [[$ctext_generator.new(name, flags, args)], vars]; } . public _make_form arg vars, name, flags, args; var ret; catch ~methodnf { ret = .(tosym("do_" + name))(vars, flags, args); return [ret[1], ret[2]]; } with handler { return [[$ctext_format.new(name, flags, args)], vars]; } . public _eat_space arg text; if (!text.length()) return text; if (text[1][1] == " ") return text.subrange(2); return text; . public _parse_pre arg vars, tokens; var out, ln, pos, line, token; out = []; line = ""; ln = $ctext_format.new("_ln", [], []); while (tokens) { token = tokens[1]; tokens = tokens.subrange(2); if (tokens.length() >= 2 && token == "{" && tokens[2] == "}") { if (tokens[1] == "-pre") { if (line) out = [@out, line]; return [out, tokens.subrange(3), vars]; } else if (tokens[1] == "_ln") { vars = vars.add('line, vars['line] + 1); } else { line = line + token; } } else { line = line + token; } } throw(~parse, "{pre} unended."); . public do__ln arg vars, flags, args; return [[" "], vars.add('line, vars['line] + 1)]; . public _make_form2 arg vars, name, flags, args; var ret; catch ~methodnf { ret = .(tosym("do_" + name))(vars, flags, args); return [ret[1], ret[2]]; } with handler { return [[$ctext_format.new(name, flags, args)], vars]; } . public do_link arg vars, flags, args; var links, item, node; links = (| vars['links] |) || #[]; for item in (flags) { if (type(item) == 'list && item[1] == "node") { node = item[2]; break; } } if (!node) throw(~parse, "No node for {link} on line " + tostr(vars['line]) + "."); links = links.add(args[1], node); return [[$ctext_format.new("link", flags, args)], vars.add('links, links)]; . public gen_group arg vars, flags, args; return [args, vars]; . parent $logic_frob object $xor var $root trusted [] var $root inited 1 var $root objname 'xor var $root created_on 796268969 var $root flags ['parameters, 'methods, 'code, 'core] public unparse arg xorlist; var str, x; str = ""; for x in (xorlist) { catch any { str = str + x.unparse() + " ^^ "; } with handler { str = str + tostr(x) + " ^^ "; } } return "(" + (str && str.subrange(1, str.length() - 4)) + ")"; . public test arg xorlist, [args]; var val, x; val = 0; for x in (xorlist) { catch ~type, ~methodnf { val = val ? !x.test(@args) | x.test(@args); } with handler { val = val ? !x | x; } } return val; . parent $logic_frob object $and var $root trusted [] var $root inited 1 var $root objname 'and var $root created_on 796268969 var $root flags ['parameters, 'methods, 'code, 'core] public unparse arg andlist; var str, x; str = ""; for x in (andlist) { catch any { str = str + x.unparse() + " && "; } with handler { str = str + tostr(x) + " && "; } } return "(" + (str && str.subrange(1, str.length() - 4)) + ")"; . public test arg andlist, [args]; var val, x; val = 0; for x in (andlist) { catch ~type, ~methodnf { val = x.test(@args); } with handler { val = x; } if (!val) break; } return val; . parent $logic_frob object $lock_frob var $root child_index 2 var $root objname 'lock_frob var $root created_on 796268969 var $root flags ['parameters, 'methods, 'code, 'core] var $named name ['uniq, "lock_frob"] var $named name_aliases [] var $lock_frob names 0 public lock_name arg value, [type]; type = [@type, 'default][1]; if (type == 'literal) type = 'default; return (| names[type] |) || names['default]; . public set_lock_name arg name; (> .perms(sender(), 'manager) <); lock_name = name; . public add_name arg type, name; (> .perms(sender(), 'manager) <); if (!names) names = #[]; names = names.add(type, name); . parent $logic_frob object $not var $root trusted [] var $root inited 1 var $root objname 'not var $root created_on 796268969 var $root flags ['parameters, 'methods, 'code, 'core] public unparse arg notlist; catch any { catch ~type, ~methodnf { return "!" + notlist[1].unparse(); } with handler { return "!" + tostr(notlist[1]); } } with handler { return "!()"; } . public test arg notlist, [args]; var val; catch ~range { catch ~type, ~methodnf { return !notlist[1].test(@args); } with handler { return !notlist[1]; } } with handler { return 1; } . parent $logic_frob object $or var $root trusted [] var $root inited 1 var $root objname 'or var $root created_on 796268969 var $root flags ['parameters, 'methods, 'code, 'core] public unparse arg orlist; var str, x; str = ""; for x in (orlist) { catch any { str = str + x.unparse() + " || "; } with handler { str = str + tostr(x) + " || "; } } return "(" + (str && str.subrange(1, str.length() - 4)) + ")"; . public test arg orlist, [args]; var val, x; val = 0; for x in (orlist) { catch ~type, ~methodnf { val = x.test(@args); } with handler { val = x; } if (val) break; } return val; . parent $logic_frob object $true var $root trusted [] var $root inited 1 var $root objname 'true var $root created_on 796268969 var $root flags ['parameters, 'methods, 'code, 'core] public unparse arg dummy; return "1"; . public test arg [args]; return 1; . parent $logic_frob object $false var $root trusted [] var $root inited 1 var $root objname 'false var $root created_on 796268969 var $root flags ['parameters, 'methods, 'code, 'core] public unparse arg dummy; return "0"; . public test arg [args]; return 0; . parent $realms_frob object $realm_of_creation var $root inited 1 var $root objname 'realm_of_creation var $root created_on 796268969 var $root flags ['parameters, 'methods, 'code, 'core] var $named name ['prop, "<Creation>", "<Creation>"] var $realms_frob local #[] parent $ctext_tag object $ctext_generator var $root objname 'ctext_generator var $root created_on 806278855 var $root inited 1 var $root flags ['parameters, 'methods, 'code, 'core] public new arg name, flags, args; return pass(name, flags, args, tosym("gen_" + name)); . public method arg self; if (type(self) == 'dictionary) return tosym("gen_" + self['name]); else return pass(self); . parent $ctext_tag object $ctext_format var $root objname 'ctext_format var $root created_on 806278844 var $root inited 1 var $root flags ['parameters, 'methods, 'code, 'core] public end arg self; if (type(self) == 'dictionary) { if (self['name][1] == "-") return 1; else return 0; } else if (self[1][1] == "-") { return 1; } else { return 0; } . public method arg self; if (type(self) == 'dictionary) return tosym("do_" + self['name]); else return pass(self); . public new arg name, flags, args; return pass(name, flags, args, tosym("do_" + name)); . parent $thing_frob object $wearable_frob var $root child_index 1 var $root fertile 1 var $root inited 1 var $root objname 'wearable_frob var $root created_on 796268969 var $root flags ['parameters, 'methods, 'code, 'fertile, 'core] var $described prose [] var $named name ['normal, "Generic Wearable Frob", "a Generic Wearable Frob"] public new arg [args]; var name, prose; name = [@args, ["", 'none, []]][1]; prose = [@args, [], []][2]; if (type(name) != 'list) name = (> $code_lib.parse_name(name) <); if (type(prose) != 'list) throw(~type, "Prose must be submitted as a list."); return (<this(), #[['name, name], ['prose, prose]]>); . public wear arg dict; sender().wear(.to_frob(dict)); . parent $user_interfaces object $help_editing_ui var $root objname 'help_editing_ui var $root fertile 1 var $root created_on 805936681 var $root inited 1 var $root flags ['parameters, 'methods, 'code, 'fertile, 'core] var $has_commands shortcuts #[] var $has_commands local #[["@hl?ist|@help-list", [["@hl?ist|@help-list", "*", "@hl?ist|@help-list <any>", 'help_list_cmd, #[[1, ['any, []]]]]]], ["@hwrite|@help-write", [["@hwrite|@help-write", "*", "@hwrite|@help-write <any>", 'help_write_cmd, #[[1, ['any, []]]]]]]] var $command_cache shortcut_cache 0 var $command_cache remote_cache 0 var $command_cache local_cache 0 protected help_write_cmd arg cmdstr, cmd, str; var node, text, errors; if (!str) node = .current_node(); else node = .match_env_nice(str); if (!node.is($help_node)) return node.namef('ref) + " is not a descendant of $help_node."; if (!node.is_writable_by(this())) return "You cannot write help on " + node.name() + "!"; text = .read("-- Enter CML text for " + node.namef('ref) + " --"); if (text == 'aborted) return; node.set_body(text); return "New help text set for " + node.namef('ref) + "."; . protected help_list_cmd arg cmdstr, cmd, str; var node, out; if (!str) node = .current_node(); else node = .match_env_nice(str); if (!node.is($help_node)) return node.namef('ref) + " is not a descendant of $help_node."; return ["@hwrite " + node.objname()] + node.body().uncompile() + ["."]; . parent $user_interfaces object $tree_ui var $root inited 1 var $root objname 'tree_ui var $root created_on 796268969 var $root flags ['parameters, 'methods, 'code, 'core] var $has_commands local #[["@tparents", [["@tparents", "* tree *", "@tparents <any> tree <any>", 'parents_by_tree_cmd, #[[1, ['any, []]], [3, ['any, []]]]], ["@tparents", "*", "@tparents <any>", 'parents_by_tree_cmd, #[[1, ['any, []]]]]]], ["@tkids|@tchildren", [["@tkids|@tchildren", "* tree *", "@tkids|@tchildren <any> tree <any>", 'children_by_tree_cmd, #[[1, ['any, []]], [3, ['any, []]]]], ["@tkids|@tchildren", "*", "@tkids|@tchildren <any>", 'children_by_tree_cmd, #[[1, ['any, []]]]]]]] var $command_cache shortcut_cache 0 var $command_cache remote_cache 0 var $command_cache local_cache 0 public parents_by_tree_cmd arg cmdstr, com, obj, [tree]; var parents, line, par, colx, col, x; if (!tree) tree = "tree inheritance"; tree = tosym(tree.to_list(" ").subrange(2).to_string()); obj = .match_env_nice(obj); if (tree == 'inheritance) parents = obj.parents(); else parents = obj.parents_by_tree(tree); col = .linelen() / 8; colx = col * 3; line = "Parent" + (parents.length() > 1 ? "s" | ""); .tell(line + " of " + obj.namef('ref) + " in tree " + tostr(tree) + ":"); line = " Name".pad(colx + 2) + " Perms".pad(col - 2); .tell(line + "Size ".pad(-col) + "Manager"); for par in (parents) { line = " " + par.namef('xref); line = line.pad(colx + 2); line = line + (" " + $object_lib.see_perms(par)).pad(col - 2); line = line + (tostr(par.size()) + " ").pad(-col); line = line + $object_lib.get_name(par.manager(), 'namef, ['xref]).pad(colx); } .tell(line); . public children_by_tree_cmd arg cmdstr, com, obj, [tree]; var children, line, child, colx, col, x; tree = [@tree, "", "inheritance"][2]; tree = tosym(tree); obj = .match_env_nice(obj); if (tree == 'inheritance) { children = obj.children(); } else { catch ~treenf { children = obj.children_by_tree(tree); } with handler { children = []; } } if (!children) { .tell("Children of " + obj.namef('xref) + "in tree " + tostr(tree) + ": ** None **"); } else { col = .linelen() / 8; colx = col * 3; line = "Children" + (children.length() > 1 ? "s" | ""); .tell(line + " of " + obj.namef('ref) + " in tree " + tostr(tree) + ":"); line = " Name".pad(colx + 2) + " Perms".pad(col - 2); .tell(line + "Size ".pad(-col) + "Manager"); for child in (children) { line = " " + child.namef('xref); line = line.pad(colx + 2); line = line + (" " + $object_lib.see_perms(child)).pad(col - 2); line = line + (tostr(child.size()) + " ").pad(-col); line = line + $object_lib.get_name(child.manager(), 'namef, ['xref]).pad(colx); .tell(line); } } . parent $user_interfaces object $editor var $root objname 'editor var $root created_on 807225689 var $root inited 1 var $root flags ['parameters, 'methods, 'code, 'core] var $has_commands shortcuts #[] var $has_commands remote #[] var $has_commands local #[["@e-abort", [["@e-abort", "", "@e-abort", 'abort_cmd, #[]]]], ["@e-insert", [["@e-insert", "*", "@e-insert <any>", 'insert_cmd, #[[1, ['any, []]]]]]], ["@e-delete", [["@e-delete", "*", "@e-delete <any>", 'delete_cmd, #[[1, ['any, []]]]]]], ["@e-save", [["@e-save", "", "@e-save", 'save_cmd, #[]]]], ["@e-line", [["@e-line", "*", "@e-line <number>", 'line_cmd, #[[1, ['number, []]]]]]], ["@e-list", [["@e-list", "*", "@e-list <any>", 'elist_cmd, #[[1, ['any, []]]]]]], ["@e-append", [["@e-append", "*", "@e-append <any>", 'eappend_cmd, #[[1, ['any, []]]]]]]] var $command_cache shortcut_cache 0 var $command_cache remote_cache 0 var $command_cache local_cache 0 var $editor sender 0 var $editor finisher 0 var $editor text 0 var $editor line 0 var $editor modified 0 public startup arg finish_method, initial_text; (> .perms(sender(), 'this) <); if (modified) throw(~lock, "Editor is being used. Do a @save or @abort."); if (type(initial_text) == 'string) initial_text = [initial_text]; sender = sender(); finisher = finish_method; text = initial_text; line = 1; modified = 0; . public abort_cmd arg [args]; (> .perms(sender(), 'this) <); clear_var('sender); clear_var('finisher); clear_var('text); clear_var('line); clear_var('modified); .tell("The editor is cleared."); . public insert_cmd arg cmdstr, cmd, what; (> .perms(sender(), 'this) <); modified = 1; text = text.insert(line, what); .tell("Line " + tostr(line) + " added."); line = line + 1; . public save_cmd arg [args]; (> .perms(sender(), 'this) <); if ((> sender.(finisher)(text) <) == 'clear) { clear_var('sender); clear_var('finisher); clear_var('text); clear_var('line); clear_var('modified); .tell("Done. Editor cleared."); } else { .tell("Save completed."); } . public delete_cmd arg cmdstr, cmd, what; var start, end; (> .perms(sender(), 'this) <); catch any { start = ._parse_range(what); } with handler { .tell("Illegal range, can't delete."); return; } end = start[2]; start = start[1]; text = text.subrange(1, start - 1) + text.subrange(end + 1); modified = 1; line = start; .tell("Deleted " + tostr(end - start + 1) + (end == start ? " line." | " lines.") + " Current set to " + tostr(line) + "."); . public line_cmd arg cmdstr, cmd, number; (> .perms(sender(), 'this) <); if (number < 1 || number > text.length() + 1) { .tell("Out if range."); return; } else { line = number; } .tell("Current set to " + tostr(line)); . public elist_cmd arg cmdstr, cmd, rangestr; var start, end, out, i, j, k, lineno; (> .perms(sender(), 'this) <); if (text == []) { .tell("There is no text."); return; } catch any { start = ._parse_range(rangestr); } with handler { .tell("Illegal range, can't list that."); return; } end = start[2]; start = start[1]; out = []; j = start; for i in (text.subrange(start, end - start + 1)) { lineno = tostr(j).right(5, j == line ? "^" | " ") + ": "; out = [@out, (lineno + i).wrap_line(.linelen(), " ")]; j = j + 1; } .tell(out); . public _parse_range arg what; var start, end, range; what = what.replace("$", tostr(text.length())); if (!what) { start = end = line > 1 ? line - 1 | 1; } else { range = (> $parse_lib.range(what) <); start = range[1]; end = range[2] == 'single ? start | range[2]; } if (start < 1 || end > text.length() || end < start) throw(~range, "Illegal range."); return [start, end]; . public eappend_cmd arg cmdstr, cmd, what; (> .perms(sender(), 'this) <); modified = 1; if (line == 1) { text = text.insert(line, what); .tell("Line " + tostr(line) + " added."); line = line + 1; } else { text = text.replace(line - 1, what + text[line - 1]); .tell("Appended to line " + tostr(line - 1) + "."); } . parent $user_interfaces object $set_ui var $root fertile 1 var $root inited 1 var $root objname 'set_ui var $root created_on 796268969 var $root flags ['parameters, 'methods, 'code, 'fertile, 'core] var $has_commands local #[["@set", [["@set", "*", "@set <any>", 'set_cmd, #[[1, ['any, []]]]]]], ["@add-setting", [["@add-setting", "*", "@add-setting <any>", 'add_setting_cmd, #[[1, ['any, []]]]]]], ["@del-setting", [["@del-setting", "* on|from *", "@del-setting <any> on|from <any>", 'del_setting_cmd, #[[1, ['any, []]], [3, ['any, []]]]]]], ["@set-info", [["@set-info", "* on *", "@set-info <any> on <any>", 'settings_info_cmd, #[[1, ['any, []]], [3, ['any, []]]]]]]] var $command_cache shortcut_cache 0 var $command_cache remote_cache 0 var $command_cache local_cache 0 public set_cmd arg set, name; var pos, obj; pos = name.rindex(" on "); if (pos) { obj = .match_env_nice(name.subrange(pos + 4)); name = name.subrange(1, pos - 1); } else { obj = this(); } return ._set_cmd(obj, name); . public add_setting_cmd arg cmdstr, com, name; var obj, pos, values, key, old_vals, line; pos = " on " in name; if (pos) { obj = .match_env_nics(name.subrange(pos + 4)); name = name.subrange(pos - 1); } else { obj = this(); } pos = " " in name; if (pos) { name = $string.trim(name.subrange(1, pos)); line = name.subrange(pos); } else { line = ""; } values = (| obj.get_setting_info(name) |) || $has_settings.default_setting_info(); if (line) { values = values.add('check, ['value, tostr(values['check])]); values = values.add('get, ['value, tostr(values['get])]); values = values.add('set, ['value, tostr(values['set])]); values = values.add('del, ['value, tostr(values['del])]); values = values.add('type, ['value, values['type]]); old_vals = #[]; old_vals = old_vals.add('set_args, values['set_args]); old_vals = old_vals.add('get_args, values['get_args]); values = $parse_lib.my_options(line, values); line = values[1]; values = values[2]; values = values.add('check, tosym(values['check])); values = values.add('get, tosym(values['get])); values = values.add('set, tosym(values['set])); values = values.add('del, tosym(values['del])); values = values.add('get_args, old_vals['get_args]); values = values.add('set_args, old_vals['set_args]); } if (obj.add_setting(name, values)) .tell("Setting added."); else .tell("Usage: @add-setting <name> <options"); . public _set_cmd arg obj, name; var pos, style, value, obj, definer, output, m, matches, info, args, n, o; // The method to do all the actual work for set_cmd and set_on_cmd if (!name) name = " "; //Find out just what the user wants to do. switch (name[1]) { case "+": style = 'boolean; value = 1; name = name.subrange(2); case "-": style = 'boolean; value = 0; name = name.subrange(2); default: pos = "=" in name; if (pos) { switch (name[pos - 1]) { case "+": style = 'add; value = name.subrange(pos + 1); name = name.subrange(1, pos - 2); case "-": style = 'del; value = name.subrange(pos + 1); name = name.subrange(1, pos - 2); default: style = 'set; value = name.subrange(pos + 1); name = name.subrange(1, pos - 1); } } else { style = 'get; value = ""; } } pos = ":" in name; if (pos > 1) { definer = name.subrange(1, pos - 1); name = name.subrange(pos + 1); } else if (pos == 1) { definer = 0; name = name.subrange(2); } else { definer = 0; } // We think we know what the definer is. // Make sure it's in the settings. // If not, add that string back on to the name if (definer && !obj.has_ancestor($object_lib.to_dbref(definer))) { name = definer + ":" + name; definer = 0; } // style may be 'boolean, 'set, 'add, 'del, 'get // 'get means we are looking at settings. // others mean we want to change settings. // If we are changing the a setting 'value is what we want to change it to. // name will contain whatever is left of the name. // Something like: // help-node.evaluator // terminated-tell // .foo // The stuff before the first '.' may be the objname of the definer. // If it is, that string will be in settings.keys() // If the style is 'get, // we want to show the names and values of all settings that match name. if (style == 'get) { output = ["Settings on " + obj.name() + ":"]; matches = obj.all_matching_settings(name, [], 1); // .debug(matches); for m in (matches) { o = m[1]; output = [@output, o.objname() + ":"]; for n in (m[2]) { info = m[1].get_setting_info(n); output = [@output, " " + n + " (" + info['type] + "): " + $data_lib.unparse(obj.get_setting(n, o))]; } } .tell(output); return; } // After all that, we know // what the definer is, // the actual name of the setting, // The value we wnat to set it to // The style of change we are makeing catch ~definernf { if (!.set_setting(name, definer, value, style)) { .tell("! That is an invalid entry for that setting."); return; } .tell("Setting set"); } with handler { .tell("Setting " + name + " not found."); return; } . public set_on_cmd arg set, name, on, obj; .debug("foo"); return ._set_cmd(.match_env_nice(obj), name); . public set_info_cmd arg cmdstr, com, setting, on, definer; var pos, part, values, value, v, output; pos = " is " in definer; if (pos) { value = definer.subrange(pos + 4); definer = .match_env_nice(definer.subrange(1, pos - 1)); setting = setting.to_list(":"); part = tosym(setting[2]); setting = setting[1]; switch (part) { case "set_args", "get_args": values = value.to_list(","); value = []; for v in (values) { v = v.trim(); if (v[1] == "'") v = tosym(v); value = [@value, v]; } case "check", "get", "set", "del": value = tosym(value); case "type": value = value; default: .tell("The setting part must be on of set_args, get_args, check, get, set, del, type"); } part = tosym(part); definer.add_setting(setting, #[[part, value]]); .tell("Setting info changed."); } else { output = ["Setting " + setting + " on " + definer + ":"]; definer = .match_env_nice(definer); values = .get_setting_info(setting); for value in (values.keys()) output = [@output, " " + tostr(value) + " = " + $data_lib.unparse(values[value])]; .tell(output); } . public settings_info_cmd arg cmdstr, com, setting, on, definer; var pos, part, values, value, v, output; pos = " is " in definer; if (pos) { value = definer.subrange(pos + 4); definer = .match_env_nice(definer.subrange(1, pos - 1)); setting = setting.to_list(":"); part = tosym(setting[2]); setting = setting[1]; switch (part) { case 'set_args, 'get_args: values = value.to_list(","); value = []; for v in (values) { v = v.trim(); if (v[1] == "'") v = tosym(v); value = [@value, v]; } case 'check, 'get, 'set, 'del: value = tosym(value); case 'type: value = value; default: .tell("The setting part must be on of set_args, get_args, check, get, set, del, type"); } definer.add_setting(setting, #[[part, value]]); .tell("Setting info changed."); } else { output = ["Setting " + setting + " on " + definer + ":"]; definer = .match_env_nice(definer); if (!definer.defines_setting(setting)) .tell("Object does not define that setting."); values = definer.get_setting_info(setting); for value in (values.keys()) output = [@output, " " + tostr(value) + ": " + $data_lib.unparse(values[value])]; .tell(output); } . public del_setting_cmd arg cmdstr, com, setting, on, obj; obj = .match_env_nice(obj); obj.del_setting(setting); .tell("Setting deleted."); . parent $editors object $generic_editor var $root inited 1 var $root objname 'generic_editor var $root created_on 796268969 var $root flags ['parameters, 'methods, 'code, 'core] var $command_aliases command_aliases [] var $generic_editor pass_through 0 var $has_commands local #[["@abort|abort", [["@abort|abort", "", "@abort|abort", 'abort_cmd, #[]]]], ["quit|@quit", [["quit|@quit", "", "quit|@quit", 'quit_cmd, #[]]]], ["list|nlist", [["list|nlist", "*", "list|nlist <any>", 'list_cmd, #[[1, ['any, []]]]]]], ["ins?ert", [["ins?ert", "*", "ins?ert <any>", 'insert_cmd, #[[1, ['any, []]]]]]], ["del?ete", [["del?ete", "*", "del?ete <any>", 'del_line_cmd, #[[1, ['any, []]]]]]], ["join", [["join", "*", "join <any>", 'join_cmd, #[[1, ['any, []]]]]]], ["enter", [["enter", "", "enter", 'enter_cmd, #[]]]], ["help", [["help", "", "help", 'help_screen, #[]]]]] var $has_commands shortcuts #[["\"*", ['add_line_cmd, [1]]], ["s/*/*", ['sub_cmd, ["", 1, 2]]], ["fill * @*", ['fill_cmd, ["", 1, 2]]], ["fill *", ['fill_cmd, ["", 1, ""]]]] var $command_cache shortcut_cache 0 var $command_cache remote_cache 0 var $command_cache local_cache 0 public start_editing arg what; // called by user.edit_cmd sender().tell(["The selected editor, " + .namef('id) + "must define .start_editing()."]); return 0; . public parse_command arg str; var cmd, loc, result, i, j, templates, template, word, fields, obj, verb_info, subbed_str; // This method works like $user.parse_command // The difference is that the permissions have changed, and after checking aliases and // commands, and nothing was found, resorting to sender().match_command() is an option. if (sender().editor() != this() || caller() != $user_input) throw(~perm, "Invalid access to parse_command."); // remove leading spaces, abort on blank line subbed_str = str; while (subbed_str && subbed_str[1] == " ") subbed_str = subbed_str.subrange(2); if (!subbed_str) return sender().editing(); // sub the string through command aliases first subbed_str = .match_command_aliases(subbed_str); // Check commands on this. cmd = .match_command(subbed_str); if (cmd) return .(cmd[1])(sender().editing(), @cmd[2]); // if we're passing unknowns on to user.parse_command()... if (pass_through) { sender().tell("(Still editing.)"); sender().run_with_users_perms(sender(), 'parse_command, str); } else { sender().tell("I don't understand that."); } return sender().editing(); . public abort_cmd arg editing, com; (> .perms(sender(), 'this) <); if (type(editing) == 'dict) { if (editing['changed]) editing['user].tell("Threw away changes and cleared editor variables."); else editing['user].tell("No changes to throw away. Cleared editor variables."); } else { (| $admin_2.tell(.namef('id) + ": editing corrupeted, == " + $data_lib.unparse(editing)) |); } return 0; . public quit_cmd arg editing, com; (> .perms(sender(), 'this) <); if (editing['changed]) { editing['user].tell("Changes have been made. Save first, or abort to cancel."); return editing; } else { editing['user].tell("Quiting editor."); return 0; } . public adjust arg text, [how]; var line; for line in [1 .. text.length()] { if ('spaces in how) text = text.replace(line, " " + text[line]); if ('numbers in how) text = text.replace(line, $string.right(tostr(line), 3) + " :" + text[line]); } return text; . public list_cmd arg editing, com, rest; var line, text; (> .perms(sender(), 'this) <); if (com == "list") { editing['user].tell(editing['text]); } else { text = $generic_editor.adjust(editing['text], 'numbers); for line in [1 .. text.length()] { if (line == editing['cur_line] - 1) editing['user].tell(strsub($string.right(tostr(line), 3), " ", "_") + "_:" + editing['text][line]); else if (line == editing['cur_line]) editing['user].tell(strsub($string.right(tostr(line), 3), " ", "^") + "^:" + editing['text][line]); else editing['user].tell(text[line]); } } return editing; . public insert_cmd arg editing, com, [args]; var line, text; // re-position and (eventually/optionally) add text (> .perms(sender(), 'this) <); line = [@args, ""][1]; text = [@args, "", ""][2]; if (!line) { editing['user].tell(["Syntax: ins*ert line [text]", "! You must supply a line number."]); return editing; } if (line != "$") line = toint(line); else line = editing['text].length() + 1; if (!line) { editing['user].tell(["Syntax: ins*ert line [text]", "! You must supply a line number greater than or equal to 1."]); return editing; } if (line > editing['text].length() + 1) line = editing['text].length() + 1; editing = editing.replace('cur_line, line); ._show_line(editing); return editing; . public _show_line arg editing; var line; line = editing['cur_line] - 1; if (line) editing['user].tell(strsub($string.right(tostr(line), 3), " ", "_") + "_:" + editing['text][line]); else editing['user].tell("____"); line = line + 1; if (line <= editing['text].length()) editing['user].tell(strsub($string.right(tostr(line), 3), " ", "^") + "^:" + editing['text][line]); else editing['user].tell("^^^^"); return editing; . public insert_line arg editing, line; // insert line at editing['cur_line] // assumes editing['cur_line] is within 1 .. editing['text].length() .perms(sender(), 'this); editing = editing.replace('text, editing['text].insert(editing['cur_line], line)); editing = editing.replace('cur_line, editing['cur_line] + 1); editing = editing.replace('changed, 1); return editing; . public add_line_cmd arg editing, line; // "* (> .perms(sender(), 'this) <); editing = .insert_line(editing, line); // ._show_line(editing); editing['user].tell("Added line " + tostr(editing['cur_line] - 1) + "."); return editing; . public delete_line arg editing; // delete line at editing['cur_line] // assumes editing['cur_line] is within 1 .. editing['text].length() .perms(sender(), 'this); editing = editing.replace('text, editing['text].delete(editing['cur_line])); editing = editing.replace('changed, 1); editing = editing.replace('cur_line, $list.min(editing['cur_line], editing['text].length())); return editing; . public del_line_cmd arg editing, com, line; // del?ete line_num (> .perms(sender(), 'this) <); line = toint(line) || editing['cur_line]; if (line <= editing['cur_line]) { editing = editing.replace('cur_line, line); editing['user].tell("Removed line " + tostr(editing['cur_line]) + ": \"" + editing['text][line] + "\"."); editing = .delete_line(editing); } else { editing['user].tell("Line number out of range."); } //._show_line(editing); return editing; . public sub_cmd arg editing, com, was, is; // s/from/to/ editing = editing.replace('text, editing['text].replace(editing['cur_line] - 1, editing['text][editing['cur_line] - 1].replace(was, is))); ._show_line(editing); return editing; . public fill_cmd arg editing, com, range, [col]; var start, current, stop, new_text, idx; col = toint([@col, "75"][1]) || 75; if ("-" in range) { start = toint(range); if (!start) { editing['user].tell("Must supply a valid range, such as 10, 2-3, or 1-$."); return editing; } range = range.subrange(tostr(start).length() + 2); if (!range || range == "$") stop = editing['text].length(); else stop = toint(range); } else { if (!range) start = editing['cur_line]; else start = toint(range); if (!start) { editing['user].tell("Must supply a valid range, such as 10, 2-3, or 1-$."); return editing; } stop = start; } // actual change: new_text = editing['text]; current = start; while (current <= stop) { if (new_text[current].length() > col) { idx = col; while (idx && new_text[current][idx] != " ") idx = idx - 1; if (!idx) { idx = col + 1; while (idx < new_text[current].length() && new_text[current][idx] != " ") idx = idx + 1; if (idx == new_text[current].length()) idx = col; } new_text = new_text.insert(current + 1, new_text[current].subrange(idx + 1)); new_text = new_text.replace(current, new_text[current].subrange(1, idx)); stop = stop + 1; } current = current + 1; } editing = editing.replace('text, new_text); editing = editing.replace('cur_line, stop + 1); new_text = $generic_editor.adjust(editing['text], 'numbers); for current in [start .. stop - 1] editing['user].tell(new_text[current]); ._show_line(editing); return editing; . public join_cmd arg editing, com, range; var start, stop, current, new_text; new_text = editing['text]; start = toint(range); range = range.subrange(tostr(start).length() + 2); stop = toint(range); if (range == "$") stop = new_text.length(); if (!start || !stop) { editing['user].tell("Syntax: join <range>"); editing['user].tell("! You must supply a range of lines to join, such as 3-4 or 1-$"); return editing; } stop = $list.min(stop, new_text.length()); // actual change: while (start < stop) { new_text = new_text.replace(start, new_text[start] + new_text[start + 1]); new_text = new_text.delete(start + 1); stop = stop - 1; } editing = editing.replace('text, new_text); editing = editing.replace('cur_line, stop + 1); ._show_line(editing); return editing; . public enter_cmd arg editing, com; editing['user].read('done_entering, editing); return editing; . public done_entering arg text, editing; if (sender() != editing['user]) throw(~perm, "Invalid access to done_entering."); if (text.length()) { if (text.length() > 1) editing['user].tell("Added lines " + tostr(editing['cur_line]) + " .. " + tostr(editing['cur_line] + text.length() - 1) + "."); else editing['user].tell("Added line " + tostr(editing['cur_line]) + "."); while (text) { editing = editing.replace('text, editing['text].insert(text[1], editing['cur_line])); editing = editing.replace('cur_line, editing['cur_line] + 1); text = test.delete(1); } } . public help_msg var msg; msg = []; msg = msg + [" ins?ert * set line number"]; msg = msg + [" del?ete * delete line"]; msg = msg + [" \"* insert text"]; msg = msg + [" abort cancel changes and exit editor"]; msg = msg + [" quit exit if no changes made since last save"]; msg = msg + [" list|nlist list text without|with numbers"]; msg = msg + [" s/*/* str sub: replace first with second in current line."]; msg = msg + [" fill * [@*] wrap lines (@ col, def: 75)"]; msg = msg + [" join * concatonates a range of lines"]; return msg; . public help_screen arg editing, com; // l?ook .perms(sender(), 'this); editing['user].tell(.help_msg()); . parent $builder object $programmer var $root owners [$programmer] var $root inited 1 var $root owned [$programmer] var $root manager $programmer var $root quota 75000 var $root objname 'programmer var $root created_on 796268969 var $root flags ['parameters, 'methods, 'code, 'core] var $root managed [$programmer] var $messaged verbs #[] var $location contents [] var $located location $body_cave var $located obvious 1 var $user password "*" var $user connected_at 0 var $user last_command_at 0 var $user connections [] var $user modes #[] var $user prompt "" var $user parsers [$command_parser] var $user tell_traceback ['brief, 0] var $user context #[] var $user filters [] var $programmer eval_prefix 0 var $programmer eval_tick_offset 0 var $programmer eval_offset 0 var $command_aliases command_aliases [] var $mail_list letters #[] var $mail_list letters_index #[] var $mail_list senders 1 var $mail_list readers [] var $mail_list notify [$programmer] var $mail_list last_letter 0 var $mail_list mail [] var $mail_ui subscribed #[[$programmer, 791485891]] var $mail_ui current #[['location, 0], ['list, $programmer]] var $gendered gender $gender_neuter var $described prose [] var $named name ['prop, "Generic Programmer", "Generic Programmer"] var $named name_aliases [] var $user_data user_data #[['real_name, [1, "???"]], ['email, [1, "???"]]] var $has_commands local #[["@show", [["@show", "*", "@show <any>", 'show_cmd, #[[1, ['any, []]]]]]], ["@program", [["@program", "*", "@program <any>", 'program_cmd, #[[1, ['any, []]]]]]], ["@d?isplay", [["@d?isplay", "*", "@d?isplay <any>", 'display_cmd, #[[1, ['any, []]]]]]], ["@dump", [["@dump", "*", "@dump <any>", 'dump_cmd, #[[1, ['any, []]]]]]], ["@id", [["@id", "*", "@id <any>", 'id_cmd, #[[1, ['any, []]]]]]], ["@which", [["@which", "*", "@which <any>", 'which_cmd, #[[1, ['any, []]]]]]], ["@mv|@move|@cp|@copy", [["@mv|@move|@cp|@copy", "*", "@mv|@move|@cp|@copy <any>", 'copy_move_cmd, #[[1, ['any, []]]]]]], ["@del-m?ethod|@delm?ethod|@dm", [["@del-m?ethod|@delm?ethod|@dm", "*", "@del-m?ethod|@delm?ethod|@dm <any>", 'del_method_cmd, #[[1, ['any, []]]]]]], ["@add-m?ethod|@addm?ethod|@am", [["@add-m?ethod|@addm?ethod|@am", "*", "@add-m?ethod|@addm?ethod|@am <any>", 'add_method_cmd, #[[1, ['any, []]]]]]], ["@eval", [["@eval", "*", "@eval <any>", 'eval_cmd, #[[1, ['any, []]]]]]], ["@add-c?ommand|@ac", [["@add-c?ommand|@ac", "*", "@add-c?ommand|@ac <any>", 'add_command_cmd, #[[1, ['any, []]]]]]], ["@del-c?ommand|@dc", [["@del-c?ommand|@dc", "*", "@del-c?ommand|@dc <any>", 'del_command_cmd, #[[1, ['any, []]]]]]], ["@as", [["@as", "* eval *", "@as <any> eval <any>", 'eval_as_cmd, #[[1, ['any, []]], [3, ['any, []]]]]]], ["@def?iner", [["@def?iner", "* this|as * eval *", "@def?iner <any> this|as <any> eval <any>", 'eval_as_to_cmd, #[[1, ['any, []]], [3, ['any, []]], [5, ['any, []]]]]]], ["@join", [["@join", "*", "@join <any>", 'join_cmd, #[[1, ['any, []]]]]]], ["@ledit", [["@ledit", "*", "@ledit <any>", 'local_edit_cmd, #[[1, ['any, []]]]]]], ["@descend?ants", [["@descend?ants", "*", "@descend?ants <any>", 'descendants_cmd, #[[1, ['any, []]]]]]], ["@chpar?ents", [["@chpar?ents", "*", "@chpar?ents <any>", 'chparents_cmd, #[[1, ['any, []]]]]]], ["@del-p?arameter|@delp?arameter|@dp", [["@del-p?arameter|@delp?arameter|@dp", "*", "@del-p?arameter|@delp?arameter|@dp <any>", 'del_parameter_cmd, #[[1, ['any, []]]]]]], ["@add-p?arameter|@addp?arameter|@ap", [["@add-p?arameter|@addp?arameter|@ap", "*", "@add-p?arameter|@addp?arameter|@ap <any>", 'add_parameter_cmd, #[[1, ['any, []]]]]]], ["@chown", [["@chown", "*", "@chown <any>", 'chown_cmd, #[[1, ['any, []]]]]]], ["@add-parent|@addparent", [["@add-parent|@addparent", "*", "@add-parent|@addparent <any>", 'add_parent_cmd, #[[1, ['any, []]]]]]], ["@del-parent|@delparent", [["@del-parent|@delparent", "*", "@del-parent|@delparent <any>", 'del_parent_cmd, #[[1, ['any, []]]]]]], ["@add-owner|@addowner|@ao", [["@add-owner|@addowner|@ao", "*", "@add-owner|@addowner|@ao <any>", 'add_owner_cmd, #[[1, ['any, []]]]]]], ["@del-owner|@delowner|@do", [["@del-owner|@delowner|@do", "*", "@del-owner|@delowner|@do <any>", 'del_owner_cmd, #[[1, ['any, []]]]]]], ["@trace-method|@trace", [["@trace-method|@trace", "*", "@trace-method|@trace <object reference>", 'trace_method_cmd, #[[1, ['objref, []]]]]]], ["@teleport|@go", [["@teleport|@go", "*", "@teleport|@go <any>", 'teleport_cmd, #[[1, ['any, []]]]]]], ["@mmod|@method-mod", [["@mmod|@method-mod", "*", "@mmod|@method-mod <any>", 'mmod_cmd, #[[1, ['any, []]]]]]], ["@make-patch|@mp", [["@make-patch|@mp", "*", "@make-patch|@mp <any>", 'make_patch_cmd, #[[1, ['any, []]]]]]], ["@omod|@object-mod", [["@omod|@object-mod", "*", "@omod|@object-mod <any>", 'object_modify_cmd, #[[1, ['any, []]]]]]], ["@list", [["@list", "*", "@list <any>", 'list_cmd, #[[1, ['any, []]]]]]]] var $has_commands shortcuts #[[";*", ['eval_cmd, ["eval", 1]]]] var $help_ui indices [$help_index_root] var $help_ui history [$help_summary] var $help_ui current 1 var $has_messages message_info #[["teleport", #[]]] var $has_messages messages #[[$programmer, #[["teleport.actor", <$ctext2_frob, [["You teleport to ", <$ctext_generator, ["dest", #[], #[], [], 'gen_dest]>, "."], #[['line, 1], ['this, $programmer]]]>], ["teleport.source", <$ctext2_frob, [[<$ctext_generator, ["actor", #[], #[], [], 'gen_actor]>, " teleports to ", <$ctext_generator, ["dest", #[], #[], [], 'gen_dest]>, "."], #[['line, 1], ['this, $programmer]]]>], ["teleport.dest", <$ctext2_frob, [[<$ctext_generator, ["actor", #[], #[], [], 'gen_actor]>, " teleports here from ", <$ctext_generator, ["source", #[], #[], [], 'gen_source]>, "."], #[['line, 1], ['this, $programmer]]]>]]]] var $has_settings defined_settings #[["@program-options", #[['get, 'get_local_setting], ['set, 'set_local_setting], ['check, 'is_any], ['del, 'delete_local_setting], ['check_args, []], ['get_args, []], ['set_args, []]]], ["@list-options", #[['get, 'get_local_setting], ['set, 'set_local_setting], ['check, 'is_any], ['del, 'delete_local_setting], ['check_args, []], ['get_args, []], ['set_args, []]]], ["match-with", #[['get, 'get_local_setting], ['set, 'set_local_setting], ['check, 'check_match_with], ['del, 'delete_local_setting], ['check_args, []], ['get_args, []], ['set_args, []]]]] var $has_settings local_settings #[] var $has_settings settings #[] var $command_cache shortcut_cache 0 var $command_cache remote_cache 0 var $command_cache local_cache 0 root init_programmer .set_tell_traceback('verbose, 4); . protected object_modify_cmd arg cmdstr, cmd, args; var opts, o, obj, out, name; opts = [["core"], ["f?ertile"], ["code"], ["p?arameters"], ["m?ethods"]]; args = $parse_lib.getopt(args, opts); if (!args[1]) { out = []; for o in (opts.slice(1)) out = [@out, "+|-" + o]; out = out.prefix(" "); out = out.lcolumnize(.linelen() - 3); out = out.prefix("! "); return ["=> Syntax: `" + cmd + " <object> [options]`", "! Options:"] + out; } obj = .match_env_nice(args[1].to_string()); if (!args[2]) return ._display_object_header("", obj, 1); name = obj.name(); for o in (args[2]) { catch any { if (!o[3]) { obj.del_flag(o[1].strip("?").to_symbol()); .tell("Removing flag '" + o[1].strip("?") + " from " + name + "."); } else { obj.add_flag(o[1].strip("?").to_symbol()); .tell("Adding flag '" + o[1].strip("?") + " to " + name + "."); } } with handler { .tell("Error: " + traceback()[1][2]); } } . protected eval_cmd arg cmdstr, com, str; var result, adjust, vars, v, evalp, ticks, time, mtime, line, offset; (> .perms(sender(), 'this) <); adjust = !str; if (!eval_offset) { adjust = 2; eval_offset = #[]; } evalp = .eval_prefix(); vars = "var " + evalp.keys().to_string(", ") + "; "; for v in (evalp.values()) vars = vars + v + "; "; // perform escape substitution if (str && str[1] == "|") str = str.subrange(2); else str = .eval_subs(str); // Evaluate the line. if (str && str[1] == ";") { str = str.subrange(2); result = .eval([str]); } else { if (str) { while (str[str.length()] == ";") str = str.subrange(1, str.length() - 1); } str = vars + " return (> " + str + " <);"; result = (> .evaluate(str) <); ticks = result[1][1]; time = result[1][2]; mtime = result[1][3]; result = result[2]; offset = .eval_offset(); if (!adjust) { ticks = ticks - offset['ticks]; time = time - offset['time]; mtime = mtime - offset['mtime]; } // figure out times/ticks if (adjust) { eval_offset = eval_offset.add('ticks, ticks); eval_offset = eval_offset.add('mtime, mtime); eval_offset = eval_offset.add('time, time); line = tostr(offset['ticks] - ticks) + " ticks and "; line = line + tostr(offset['time] - time) + "."; line = line + tostr(offset['mtime] - mtime) + " seconds."; .tell("Eval offset adjusted by " + line); if (adjust == 1) return; } } // Display the errors, or the result. if (result[1] == 'errors) { .tell(result[2]); } else { .tell("=> " + $data_lib.unparse(result[2], 'full)); if (ticks) { line = "[ ticks: " + tostr(ticks) + " seconds: " + tostr(time); line = line + "." + tostr(mtime); if (time) line = line + " (" + tostr(ticks / time) + " ticks per second)"; .tell(line + " ]"); } } . protected program_cmd arg cmdstr, com, args; var syn, opts, edited, sref, line, code, errors; syn = com + " [obj].<method> [options...]"; edited = ""; args = args + ((| " " + .setting("@program-options") |) || ""); opts = .parse_methodcmd_options(syn, args, [["e?dited"], ["c?omment", 1]], #[['edited, [1, ""]], ['comment, [0, ""]]]); if (opts['error]) { (| .tell_error(syn, opts['error]) |); opts = opts.add('ignore, 1); } if (!opts['edited][1] && !$sys.is_admin(this())) { .tell("Only admins can shut off edited comments."); opts = opts.add('edited, 0).add('ignore, 1); } if (opts['edited][1]) { edited = "// $#Edited: " + $time.format("%d %h %y %H:%M") + " " + .namef('ref); if (opts['comment][2]) edited = edited + ": " + opts['comment][2]; } if (opts['ignore]) { line = "Ignoring input until \".\" or \"@abort\""; } else { sref = opts['object].objname() + "." + tostr(opts['method]) + "()"; if (opts['exists]) line = "Reprogramming " + sref; else line = "Programming " + sref; } code = .read("-- " + line + " --"); if (code == 'aborted) return; if (opts['ignore]) return "Finished ignoring input."; if (edited) code = code + [edited]; catch any { errors = opts['object].compile(code, opts['method]); if (errors) return errors; line = $code_lib.verify_code(code, opts['method]); opts['object].set_method_flags(opts['method], opts['mflags]); opts['object].set_method_state(opts['method], opts['mstate]); if (line) .tell(line); return "Method " + sref + " " + (opts['exists] ? "re" | "") + "compiled"; } with handler { return traceback()[1][2]; } . protected show_cmd arg cmdstr, com, args; var obj, opts, show, syn, wildcard; (> .perms(sender(), 'this) <); syn = com + " <object> [<wildcard>] [flags]"; opts = #[["p", [1, 0]], ["m", [1, 0]], ["v", [0, 0]], ["c", [1, 0]]]; args = $parse_lib.options(args, opts); opts = args[2]; args = args[1]; if (!args) $parse_lib.tell_error("", syn); show = []; if (opts["p"][1]) show = ['parameters]; if (opts["m"][1]) show = [@show, 'methods]; obj = .match_env_nice(args[1]); if (args.length() > 1) wildcard = args[2]; else wildcard = ""; catch ~perm { return obj.show(wildcard, opts["c"][1], opts["v"][1], @show); } with handler { .tell(traceback()[1][2]); } . protected _move_method arg syn, ref1, ref2, [opts]; var line, code; .perms(sender(), 'this); catch any { ref1 = $parse_lib.reference(ref1); ref2 = $parse_lib.reference(ref2); if (!ref1[2] || !ref2[2]) .tell_error(syn, "You must define both a method to be copied from, and one to be copied to."); ref1 = ref1.replace(1, .match_env_nice(ref1[1])); ref1 = ref1.replace(2, tosym(ref1[2])); ref2 = ref2.replace(1, .match_env_nice(ref2[1])); ref2 = ref2.replace(2, tosym(ref2[2])); code = ref1[1].list_method(ref1[2]); // Parse Options if (opts && "-edited" in $list.to_string(opts[1])) { if (!$sys.is_system(sender())) .tell("! Sorry, only admins can turn off the edited messages."); } else { line = " // " + $time.ldate('mdy, 'dash) + "/"; line = line + $time.ltime('24hr) + " " + .namef('ref); line = line + ", moved from " + ref1[1].objname() + "." + tostr(ref1[2]); code = [@code, line]; } // delete the old method, compile the new one. ref1[1].del_method(ref1[2]); ref2[1].compile(code, ref2[2]); // cool, we made it. line = "Method " + ref1[1].objname() + "." + tostr(ref1[2]) + " moved to "; line = line + ref2[1].objname() + "." + tostr(ref2[2]) + "."; .tell(line); } with handler { switch (error()) { case ~methodnf: line = traceback()[1][2]; line = line.subrange(1, line.length() - 1); .tell_error(syn, line + " on " + ref1[1].namef('ref) + "."); case ~perm: .tell_error(syn, "You cannot write on that object."); case ~stop: rethrow(error()); default: // they are tuff programmers, they can deal with the tracebacks .tell_traceback(traceback()); } } . protected del_method_cmd arg cmdstr, com, what; var syntax, obj, ref, res; (> .perms(sender(), 'this) <); syntax = com + " <obj>.<method>()"; what = what.explode(); if (!what) $parse_lib.tell_error("You must give an object and a method to delete.", syntax); catch any { ref = $parse_lib.full_reference(what[1], this(), [this(), 'match_env_nice]); if (ref[1] != 'method || ref[3] == 0) { .tell("The object.method() reference \"" + what[1] + "\" is invalid."); return; } ref[2].del_method(ref[3]); .tell("Method " + ref[2].objname() + "." + tostr(ref[3]) + "() deleted."); } with handler { .tell(traceback()[1][2]); } . protected move_cmd arg cmdstr, com, [args]; var syn; (> .perms(sender(), 'this) <); syn = com + " [from] <$obj.ref> [to] <$obj.ref>"; // figure up args args = args[1].explode(); if (args && args[1] == "from") args = args.delete(1); if (args.length() > 1 && args[2] == "to") args = args.delete(2); if (args.length() < 2) $parse_lib.tell_error("Not enough arguments sent.", syn); // what type is it (method/parameter) if ("." in args[1] && "." in args[2]) return ._move_method(syn, @args); else if ("," in args[1] && "," in args[2]) return ._move_parameter(syn, @args); else $parse_lib.tell_error("You must define both methods, or both parameters.", syn); . protected list_cmd arg cmdstr, com, args; var nums, pattern, ref, methods, s, def, method, opts, str; s = com + " <object>.<method>"; opts = (| " " + .setting("@list-options") |) || ""; args = $parse_lib.getopt(args + opts, [["n?umbered"]]); nums = (| "n?umbered" in args[2].slice(1) |); opts = (| .setting("@program-options") |) || ""; if (nums) nums = args[2][nums][3]; str = args[1].to_string(); catch any { ref = $parse_lib.xreference(str); if (ref[1] != 'method) (> .tell_error(s, "You must submit an object.method() reference") <); def = (| ref[2].find_method(ref[4]) |); if (!def) { if (ref[4] == 0) pattern = "*"; else pattern = tostr(ref[4]); def = ref[2]; methods = []; for method in (def.methods()) { if ($string.match_pattern(pattern, tostr(method))) methods = methods + [method]; } } else { pattern = tostr(ref[4]); methods = [ref[4]]; } } with handler { switch (error()) { case ~methodnf: str = ref[2].objname() + "." + tostr(ref[4]) + "()"; .tell_error(s, line + " not found."); case ~stop: return; default: .tell_error(s, traceback()[1][2]); } .tell_error(s, traceback()[1][2]); } if (!methods) return .tell("No method found matching \"" + pattern + "\"."); for method in (methods) .tell(._list_method(def, method, nums, opts)); . protected copy_move_cmd arg cmdstr, com, [args]; var syn, how, line; (> .perms(sender(), 'this) <); syn = com + " [from] <$obj.ref> [to] <$obj.ref>"; // figure up args args = args[1].explode(); args = [@args, ""]; args = args.setremove("from"); args = args.setremove("to"); if (args.length() != 3) $parse_lib.tell_error("Send two object references.", syn); how = com in ["@mv", "@move"] ? 'move | 'copy; catch ~namenf { args = [$parse_lib.full_reference(args[1], sender()), args[2], args[3]]; args = [args[1], $parse_lib.full_reference(args[2], sender()), args[3]]; if (args[1][1] != args[2][1] && args[2][1] != 'unknown) $parse_lib.tell_error("Cannot " + tostr(how) + (args[1][1] == 'unknown ? " an object" | "from a " + tostr(args[1][1])) + " to " + "a " + tostr(args[2][1]) + ".", syn); else if (args[1][1] == 'method) ._copy_move_method(syn, how, @args); else if (args[1][1] == 'parameter) .tell("Parameters are currently unsupported, sorry!"); else $parse_lib.tell("You must specify a full reference for the source object.", syn); } with handler { $parse_lib.tell_error(traceback()[1][2], syn); } . protected id_cmd arg cmdstr, cmd, obj; (> .perms(sender(), 'this) <); obj = .match_env_nice(obj); .tell(obj.namef('xref) + " " + $object_lib.see_perms(obj) + " " + $data_lib.unparse(obj.parents()) + " " + tostr(obj.size()) + " bytes"); . protected dump_cmd arg cmdstr, com, args; var opts, obj, objname, x, pobjname, par, data, readable, me, code, syn, tail; (> .perms(sender(), 'this) <); syn = [["Options can be:", " +/-n -- nice formatting", " +/-t -- textdump formatting", " +/-m -- show/don't show methods", " +/-p -- show/don't show parameters", "Flags default to \"-n +m +p\""], com + " [options] <object>"]; opts = #[["n", [0, 0]], ["t", [1, 0]], ["m", [1, 0]], ["p", [1, 0]], ["e", [0, 0]]]; args = $parse_lib.options(args, opts); if (!args[1]) $parse_lib.tell_error(@syn); obj = .match_env_nice(args[1][1]); me = this(); objname = obj.objname(); opts = args[2]; readable = obj.flags(); data = (| obj.data() |); if (opts["p"][1]) { if (!data) { .tell(" *** Parameters are unreadable by you ***"); } else { if (opts["n"][1]) { .tell("Object: " + obj.namef('ref)); .tell("Parents: " + $list.to_english($list.map(obj.parents(), 'namef))); .tell("Size: " + tostr(obj.size()) + " bytes"); } else { // I'm not sure how the latest drivers handle objname vs objnums for x in (obj.parents()) .tell("parent " + x.objname()); .tell("object " + objname); .tell(""); } for par in (data) { if (type(par[2]) == 'string) { .tell(" *** " + par[1].objname() + "'s parameters are unreadable by you ***"); } else { pobjname = (| par[1].objname() |) || toliteral(par[1]); for x in (par[2]) .tell("var " + pobjname + " " + tostr(x[1]) + " " + $data_lib.unparse(x[2])); } } } } if (opts["m"][1]) { .tell(""); if (!('code in readable)) { .tell(" *** " + objname + "'s methods are unreadable by you ***"); } else { if (opts["e"][1]) tail = " -edited"; else tail = ""; for x in (obj.methods()) { code = obj.list_method(x); if (opts["n"][1]) .tell("@program " + objname + "." + tostr(x) + tail); else .tell("method " + tostr(x)); for x in [1 .. code.length()] code = code.replace(x, " " + code[x]); .tell(code); .tell([".", ""]); // this can get long pause(); } } } . protected add_method_cmd arg cmdstr, com, what; var syntax, obj, ref, res; (> .perms(sender(), 'this) <); syntax = com + " <obj>.<method>()"; what = what.explode(); if (!what) $parse_lib.tell_error("You must give an object and a method to add.", syntax); catch any { ref = $parse_lib.full_reference(what[1], this(), [this(), 'match_env_nice]); if (ref[1] != 'method || ref[3] == 0) { .tell("The object.method() reference \"" + what[1] + "\" is invalid."); return; } if ((| ref[2].find_method(ref[3]) |)) { .tell("Method " + ref[2].objname() + "," + tostr(ref[3]) + " already exists!"); return; } ref[2].compile([""], ref[3]); .tell("Method " + ref[2].objname() + "," + tostr(ref[3]) + " added."); } with handler { .tell(traceback()[1][2]); } . protected descendants_cmd arg cmdstr, cmd, args; var syn, obj, maxlevels, line; (> .perms(sender(), 'this) <); syn = cmd + " <obj> [<levels>]"; args = args.explode(); if (!(args.length() in [1, 2])) $parse_lib.tell_error("", syn); obj = .match_env_nice(args[1]); if (args.length() == 2) { if (args[2] == "all") maxlevels = 0; else maxlevels = abs(toint(args[2])) + 1; } else { maxlevels = 3; } line = "Descendants of " + obj.objname() + " ["; line = line + obj.parents().map('objname).to_english() + "], "; if (maxlevels) { line = line + tostr(maxlevels - 1); line = line + " level" + (maxlevels - 1 > 1 ? "s" | "s") + ":"; } else { line = line + "all levels:"; } .tell(line); .tell(obj._display_descendants("", [], 0, maxlevels)); .tell("---"); . protected chparents_cmd arg cmdstr, cmd, args; var objs, syn, x, obj, parents; (> .perms(sender(), 'this) <); syn = cmd + " <child> [to] <parent>, <parent>, ..."; if (!args) $parse_lib.tell_error("", syn); if (" to " in args) { if ("," in args) args = args.replace(" to ", ", "); else args = args.replace(" to ", " "); } objs = $object_lib.str_to_objlist(args); if (objs['invalid]) .tell("Unable to find objects: " + objs['invalid].to_english()); objs = objs['valid]; if (!objs) return; if (objs.length() < 2) $parse_lib.tell_error("No parents defined.", syn); obj = objs[1]; parents = objs.subrange(2); catch any { obj.chparents(@parents); .tell("Successfully changed parent list for " + obj.objname() + " to " + $data_lib.unparse(parents) + "."); } with handler { .tell(traceback()[1][2]); } . protected _display_object_header arg what, obj, chop; var len, line, out; (> .perms(sender(), 'this) <); len = .linelen(); line = "Object: " + obj.namef('xref) + " "; line = line + $object_lib.see_perms(obj); .tell(line.left(len / 3 * 2) + " Size: " + obj.size().to_english()); .tell("Manager: " + $object_lib.get_name(obj.manager(), 'namef, ['xref])); line = obj.writers(); if (line.length() > 1) line = "Writers: " + line.map('objname).to_english(); else if (!line) line = "Writers: (none)"; else line = "Writer: " + line[1].namef('xref); line = obj.owners(); if (line.length() > 1) line = "Owners: " + line.map('objname).to_english(); else if (!line) line = "Owner: (none)"; else line = "Owner: " + line[1].namef('xref); if (chop) line = line.chop(len); .tell(line); line = obj.parents(); if (line.length() > 1) line = "Parents: " + line.map('objname).to_english(); else if (!line) line = "Parents: (none)"; else line = "Parent: " + line[1].namef('xref); if (chop) line = line.chop(len); .tell(line); if (obj.has_ancestor($located)) .tell("Location: " + $object_lib.get_name(obj.location(), 'namef, ['xref])); . protected _display_methods arg obj, info, chop, comments; var type, types, line, out, tidbit, len; (> .perms(sender(), 'this) <); len = .linelen(); types = ["Public", "Protected", "Private", "Root", "Driver"]; out = []; for type in [1 .. 5] { if (info[type]) { out = out + [types[type] + " Methods:"]; for tidbit in (info[type]) { line = $object_lib.parse_method_flags(tidbit[4]) + tostr(tidbit[5]).right(4) + " " + (tidbit[1] != obj ? tidbit[1].objname() | "") + "." + tostr(tidbit[2]) + "(" + tidbit[3] + ")"; if (comments && tidbit[6]) { line = line.pad((len - 1) / 2); if (tidbit[6][1] != "/") line = line + " // " + tidbit[6]; else line = line + " " + tidbit[6]; } if (chop) line = line.chop(len); out = out + [line]; pause(); } } pause(); } .tell(out); . protected teleport_cmd arg cmdstr, com, where; var loc, p; (> .perms(sender(), 'this) <); if (!where) { .tell("Specify a destination."); return; } if (where == "home") loc = .home(); else loc = (| .match_environment(where) |); // if we have still not found a location... if (!loc) { catch any { loc = $place_db.find(where); } with handler { switch (error()) { case ~ambig: .tell("Several rooms match that name: " + traceback()[1][3].map('namef).to_english()); case ~namenf: .tell("Unable to find place \"" + where + "\"."); return; default: $parse_lib.tell_error(traceback()[1][2]); } } } if (!loc) { .tell("Unable to find place \"" + where + "\"."); return; } if (loc == .location()) { .tell("You are already there!"); return; } if (!.teleport(loc)) .tell("Sorry."); . protected info_cmd arg cmdstr, com, obj; var info; (> .perms(sender(), 'this) <); obj = .match_env_nice(obj); info = obj.info(); if (!info) return .tell("No information about " + obj.namef('ref)); .tell("-----"); .tell(info); .tell("-----"); . protected eval_subs arg code; var idx, ret_code, sub; ret_code = ""; while (code) { idx = "^" in code; if (!idx) { return ret_code + code; } else if (idx == code.length() || code.subrange(idx + 1, 1) == "^") { ret_code = ret_code + code.subrange(1, idx); code = code.subrange(idx + 1); if (code && code[1] == "^") code = code.subrange(2); } else { if (idx > 1) { ret_code = ret_code + code.subrange(1, idx - 1); code = code.subrange(idx + 1); } else { code = code.subrange(2); } idx = 1; while (idx <= code.length() && !(code[idx] in " =.()[]=<>?|&!*+-/';\"")) idx = idx + 1; sub = .match_env_nice(code.subrange(1, idx - 1)); ret_code = ret_code + sub.objname(); code = code.subrange(idx); } } return ret_code; . protected eval_prefix (> .perms(sender(), 'this) <); return $dictionary.union(#[["me", "me = this();"], ["here", "here = me.location()"]], eval_prefix || #[]); . protected del_command_cmd arg cmdstr, cmd, str; var s, ref, t, args; (> .perms(sender(), 'this) <); // we have to do our own matching, because the parser would get the // template mixed up with our template s = cmd + " \"template\" [from] $object.method()"; args = str.explode_quoted(); if (args.length() < 2) .tell_error(s, "Unable to parse arguments \"" + str + "\"."); t = args[1]; if (!t) return "No template specified."; catch any { ref = $parse_lib.xreference(args[args.length()]); if (ref[1] != 'method) return toliteral(str) + " is an invalid method reference."; if (!(> ref[2].del_command(t, ref[4]) <)) return "Command " + toliteral(t) + " is not defined on " + ref[2].objname() + "."; } with handler { return traceback()[1][2]; } return "Removed command " + toliteral(t) + " associated with " + $parse_lib.buildref(@ref) + "."; . public _which_cmd arg partial, parent, type, more; var p, cmds, cmd, def, matches; cmds = (| parent.(type)() |) || #[]; matches = []; for def in (cmds.keys()) { for cmd in (cmds[def]) { if (partial in cmd[3].strip("?")) matches = matches + [[more, cmd[3], cmd[4]]]; } } return matches; . protected which_cmd arg cmdstr, command, str; var m, c, l, t, p, s, cmds, def, out, dname, line, lcache, rcache; if (!str) .tell_error(command + " <partial or full template>"); m = #[]; t = (str.explode())[1]; for p in (.ancestors()) { if (p == $has_commands) break; cmds = ._which_cmd(str, p, 'local_commands, " "); cmds = cmds + ._which_cmd(str, p, 'remote_commands, "*"); if (cmds) m = m.add(p, cmds); } if (!m) return "No commands found matching the template \"" + str + "\"."; l = .linelen() / 2; out = ["Commands matching the template \"" + str + "\":"]; lcache = .local_cache(); rcache = .remote_cache(); for def in (m) { dname = " " + def[1].objname() + "."; for c in (def[2]) { line = c[1] + c[2].pad(l) + dname + tostr(c[3]) + "()"; s = ((c[2].explode())[1].strip("?").explode("|"))[1]; if ((| lcache[s] |) || (| rcache[s] |)) line = " " + line; else line = "!" + line; out = out + [line]; } } return out; . protected _copy_move_method arg syn, how, ref1, ref2, opts; var line, code, type; .perms(sender(), 'this); catch any { code = ref1[2].list_method(ref1[3]); if (opts && "-edited" in opts) { if (!$sys.is_system(sender())) .tell("! Only admins can turn off the edited messages."); } else { line = " // " + $time.ldate('mdy, 'dash) + "/"; line = line + $time.ltime('24hr) + " " + .namef('ref); line = line + ", moved from " + ref1[2].objname() + "." + tostr(ref1[3]); code = [@code, line]; } if (how == 'move) ref1[2].del_method(ref1[3]); ref2[2].compile(code, ref2[3]); line = $string.capitalize(tostr(ref1[1])) + " "; line = line + ref1[2].objname() + "." + tostr(ref1[3]) + " "; line = line + (how == 'move ? "moved" | "copied") + " "; line = line + ref2[2].objname() + "." + tostr(ref2[3]) + "."; .tell(line); } with handler { switch (error()) { case ~methodnf: line = traceback()[1][2]; line = line.subrange(1, line.length() - 1); $parse_lib.tell_error(line + " on " + ref1[1].namef('ref) + ".", syn); case ~perm: $parse_lib.tell_error("You cannot write on that object.", syn); case ~stop: rethrow(error()); default: // they are men, they can deal with the tracebacks .tell("Error encountered:"); .tell_traceback(traceback()); } } . protected add_command_cmd arg cmdstr, cmd, str; var s, ref, t, args; (> .perms(sender(), 'this) <); // we have to do our own matching, because the parser would get the // template mixed up with our template s = cmd + " \"template\" [to|for] $object.method()"; args = str.explode_quoted(); if (args.length() < 2) .tell_error(s, "Unable to parse arguments \"" + str + "\"."); t = args[1]; if (!t) return "No template specified."; catch any { ref = $parse_lib.xreference(args[args.length()]); if (ref[1] != 'method) return toliteral(str) + " is an invalid method reference."; (> ref[2].add_command(t, ref[4]) <); } with handler { return traceback()[1][2]; } return "Added command " + toliteral(t) + " associated with " + $parse_lib.buildref(@ref) + "."; . protected eval_as_cmd arg cmdstr, cmd, objname, prep, line; var obj, result; (> .perms(sender(), 'this) <); line = line + ";"; obj = .match_env_nice(objname); result = obj.eval([line]); if (result[1] == 'errors) .tell(result[2]); else .tell("eval as " + obj.objname() + " => " + $data_lib.unparse(result[2])); . protected eval_as_to_cmd arg cmdstr, cmd, objname, this, targetname, eval, line; var obj, target, result; (> .perms(sender(), 'this) <); line = line + ";"; obj = .match_env_nice(objname); target = .match_env_nice(targetname); result = obj.eval([line], target); if (result[1] == 'errors) .tell(result[2]); else .tell(cmd + " " + objname + " " + this + " " + targetname + " eval => " + $data_lib.unparse(result[2])); . protected teleport arg dest; var m, source, vars; (> .perms(sender(), 'this) <); source = .location(); if (!(| .move_to(dest) |)) return 0; .look_cmd(); vars = #[["$actor", this()], ["actor", .name()], ["$source", source], ["source", source.name()], ["$dest", dest], ["dest", dest.name()]]; m = .eval_message("teleport", vars, $programmer); dest.announce(m); source.announce(m); . protected join_cmd arg cmdstr, cmd, who; var loc, p, user; (> .perms(sender(), 'this) <); if (!who) { .tell("Specify a user to join."); return; } catch any { if (who[1] in "$#") { user = (> $object_lib.to_dbref(who) <); if (!user.has_ancestor($thing)) return "You can only join things in the VR."; } else { user = (> $user_db.find(who) <); } } with handler { .tell(traceback()[1][2]); return; } loc = user.location(); if (loc == .location()) { .tell("You are already with " + user.name() + "!"); return; } if (!.teleport(loc)) .tell("Sorry."); else .tell("You join " + user.name() + "."); . protected local_edit_cmd arg cmdstr, cmd, args; var syn, ref, edited, why, epref, spref, line, code, ancestor; syn = cmd + " <obj>.<method> [-edited] [comments]"; args = $parse_lib.options(args, #[["edited", [1, ""]]]); edited = args[2]["edited"][1]; args = args[1]; if (!args) .tell_error(syn, "No <object>.<method> reference specified."); catch any { ref = $parse_lib.full_reference(args[1], this(), [this(), 'match_environment]); } with handler { .tell_error(syn, traceback()[1][2]); } if (ref[1] != 'method) .tell_error(syn, "Invalid <object>.<method> reference."); if (!edited && !$sys.is_admin(this())) { .tell("Only administrators can compile without history comments."); edited = 1; } if (ref[2] && !ref[2].is_writable_by(this())) return .tell("You cannot program on that object."); why = args.subrange(2).to_string(); catch any { ancestor = ref[2].find_method(ref[3]); code = ancestor.list_method(ref[3]); } with handler { switch (error()) { case ~methodnf: line = ref[2].objname() + "." + tostr(ref[3]) + "()"; .tell_error(syn, line + " not found."); default: .tell_error(syn, traceback()[1][2]); } } .tell("#$# edit name: " + ref[2].name() + "." + tostr(ref[3]) + " upload: @program " + ancestor.objname() + "." + tostr(ref[3])); .tell(code); .tell("."); . protected display_cmd arg cmdstr, cmd, args; var opts, args, i, chop, filter, comments, gen, def, info, what, swhat, obj, syn, ref; (> .perms(sender(), 'this) <); syn = cmd + " <object reference> [<object>]"; // parse args opts = [["c?hop", 0], ["f?ull", 0], ["g?eneration", 1], ["d?efiners", 1]]; args = $parse_lib.getopt(args, opts); opts = args[2]; args = args[1]; chop = 1; gen = ['generations, 1]; if (!(args.length() == 1)) .tell_error(syn); catch any { ref = $parse_lib.xreference(args[1]); def = [ref[3]]; for i in (opts) { switch (i[1]) { case "c?hop": comments = i[3]; case "f?ull": comments = i[3]; case "g?eneration": gen = i[4]; if (gen.is_numeric()) gen = ['generations, toint(gen)]; else gen = ['ancestors_to, .match_env_nice(gen)]; case "d?efiners": def = i[4].parse_english_list().omap(this(), 'match_env_nice).union(def).compress(); default: .tell_error(syn); } } } with handler { .tell_error(syn, traceback()[1][2]); } what = ref[1]; swhat = tostr(ref[1]).capitalize(); obj = ref[2]; // display it ._display_object_header(what, obj, chop); if (what in ['method, 'variable]) { if (!tostr(ref[4])) filter = ""; else filter = tostr(ref[4]); info = obj.(tosym(tostr(what) + "_info"))(gen, def, filter); if (info) { if (info.length() > 1) swhat = swhat + "s"; .tell(swhat + " matching \"" + filter + "\":"); .(tosym("_display_" + tostr(what) + "s"))(obj, info, chop, comments); } } return "+ finis +"; . protected eval_offset return eval_offset || #[['mtime, 0], ['time, 0], ['ticks, 0]]; . protected chown_cmd arg cmdstr, cmd, args; var objs, syn, x, obj, owners; (> .perms(sender(), 'this) <); syn = cmd + " <object> [to] <owner>, <owner>, ..."; if (!args) .tell_error(syn); if (" to " in args) { if ("," in args) args = args.replace(" to ", ", "); else args = args.replace(" to ", " "); } objs = $object_lib.str_to_objlist(args); if (objs['invalid]) .tell("Unable to find objects: " + objs['invalid].to_english()); objs = objs['valid]; if (!objs) return; if (objs.length() < 2) .tell_error(syn, "No owners defined."); obj = objs[1]; owners = objs.subrange(2); catch any { obj.chown(@owners); .tell("Successfully changed owner list for " + obj.objname() + " to " + $data_lib.unparse(owners) + "."); } with handler { .tell(traceback()[1][2]); } . protected del_parameter_cmd arg cmdstr, cmd, what; var syntax, ref; (> .perms(sender(), 'this) <); syntax = cmd + " <obj>,<parameter>"; what = what.explode(); if (!what) .tell_error(syntax, "You must give an object and parameter to delete"); catch ~paramnf, ~namenf, ~perm { ref = $parse_lib.full_reference(what[1], this(), [this(), 'match_env_nice]); if (ref[1] != 'parameter || ref[3] == 0) { .tell("The object,parameter reference \"" + what[1] + "\" is invalid."); return; } ref[2].del_parameter(ref[3]); .tell("Parameter " + ref[2].objname() + "," + tostr(ref[3]) + " deleted."); } with handler { .tell(traceback()[1][2]); } . protected add_parameter_cmd arg cmdstr, cmd, what; var syntax, ref, value; (> .perms(sender(), 'this) <); syntax = cmd + " <obj>,<parameter> [<value>]"; what = what.explode(); if (!what) .tell_error(syntax, "You must give an object and parameter to add"); catch ~paramnf, ~namenf, ~perm { ref = $parse_lib.full_reference(what[1], this(), [this(), 'match_env_nice]); if (ref[1] != 'parameter || ref[3] == 0) { .tell("The object,parameter reference \"" + what[1] + "\" is invalid."); return; } // this is a cheap way to evaluate their set value if (what.length() > 1) { value = .eval(["return " + what.subrange(2).to_string() + ";"]); if (value[1] == 'errors) { .tell("Unable to parse value \"" + what.subrange(2).to_string() + "\", default value is \"0\"."); value = 0; } else { value = value[2]; } } ref[2].add_parameter(ref[3], value); .tell("Parameter " + ref[2].objname() + "," + tostr(ref[3]) + " added" + (value != 0 ? " with value " + toliteral(value) + "." | ".")); } with handler { .tell(traceback()[1][2]); } . protected add_parent_cmd arg cmdstr, cmd, args; var syn, obj, parent; (> .perms(sender(), 'this) <); syn = cmd + " <parent> [to] <object>"; if (!args) .tell_error(syn); if (" to " in args) args = args.replace(" to ", " "); args = args.explode(); if (args.length() != 2) .tell_error(syn, "Invalid number of arguments."); parent = .match_env_nice(args[1]); obj = .match_env_nice(args[2]); catch any { obj.add_parent(parent); .tell("Sucessfully added parent to " + obj.objname() + ", new parent list: " + obj.parents().map_to_english('objname) + "."); } with handler { .tell(traceback()[1][2]); } . protected del_parent_cmd arg cmdstr, cmd, args; var syn, obj, parent; (> .perms(sender(), 'this) <); syn = cmd + " <parent> [from] <object>"; if (!args) .tell_error(syn); if (" from " in args) args = args.replace(" from ", " "); args = args.explode(); if (args.length() != 2) .tell_error(syn, "Invalid number of arguments."); parent = .match_env_nice(args[1]); obj = .match_env_nice(args[2]); catch any { obj.del_parent(parent); .tell("Sucessfully removed parent from " + obj.objname() + ", new parent list: " + obj.parents().map_to_english('objname) + "."); } with handler { .tell(traceback()[1][2]); } . protected add_owner_cmd arg cmdstr, cmd, args; var syn, obj, owner; (> .perms(sender(), 'this) <); syn = cmd + " <owner> [to] <object>"; if (!args) .tell_error(syn); if (" to " in args) args = args.replace(" to ", " "); args = args.explode(); if (args.length() != 2) .tell_error(syn, "Invalid number of arguments."); owner = .match_env_nice(args[1]); obj = .match_env_nice(args[2]); catch any { obj.add_owner(owner); .tell("Sucessfully added owner to " + obj.objname() + ", new owner list: " + obj.owners().map_to_english('objname) + "."); } with handler { .tell(traceback()[1][2]); } . protected del_owner_cmd arg cmdstr, cmd, args; var syn, obj, owner; (> .perms(sender(), 'this) <); syn = cmd + " <owner> [from] <object>"; if (!args) .tell_error(syn); if (" from " in args) args = args.replace(" from ", " "); args = args.explode(); if (args.length() != 2) .tell_error(syn, "Invalid number of arguments."); owner = .match_env_nice(args[1]); obj = .match_env_nice(args[2]); catch any { obj.del_owner(owner); .tell("Sucessfully removed owner from " + obj.objname() + ", new owner list: " + obj.owners().map_to_english('objname) + "."); } with handler { .tell(traceback()[1][2]); } . protected trace_method_cmd arg cmdstr, cmd, ref; var method, current, trace, syn, minfo, line, anc, len; (> .perms(sender(), 'this) <); syn = cmd + " <object.method()>"; if (ref[1] != 'method) return .tell_error(syn, toliteral(cmd) + " requires a full method reference."); catch any { method = ref[4]; current = ref[2].find_method(method); trace = []; while (current) { trace = [@trace, current]; current = (| ref[2].find_next_method(method, current) |); } } with handler { if (error() != ~stop) .tell(traceback()[1][2]); } .tell("Method trace of " + ref[2].objname() + "." + tostr(ref[4]) + "():"); len = .linelen(); for anc in (trace.reverse()) { minfo = ._get_method_info(anc, method); line = minfo[4] ? "+" | " "; line = line + tostr(minfo[5]).right(4) + " "; line = line + anc.objname() + "."; line = line + tostr(minfo[2]) + "(" + minfo[3] + ")"; line = line.pad(len / 2); line = line + minfo[6]; line = line.chop(len); .tell(line); } . protected evaluate arg str; var time, ticks, mtime, result; time = [time()]; ticks = [tick()]; mtime = [mtime()]; result = (> .eval([str]) <); mtime = mtime + [mtime()]; ticks = ticks + [tick()]; time = time + [time()]; // this is a rough way to figure mtime, but its the best we can do.. time = time[2] - time[1]; ticks = ticks[2] - ticks[1]; if (mtime[1] > mtime[2] && !time) mtime = 1000000 - mtime[1] + mtime[2]; else if (mtime[1] > mtime[2] && time) mtime = time * 1000000 + (1000000 - mtime[1]) + mtime[2]; else mtime = mtime[2] - mtime[1]; return [[ticks, time, mtime], result]; . protected _list_method arg obj, method, [args]; var out, code, line, opt, nums, opt, state, flags, f; (> .perms(sender(), 'this) <); nums = [@args, 0][1]; opt = [@args, "", ""][2]; code = obj.list_method(method); if (nums) { code = code.numbered_text(); } else { for line in [1 .. code.length()] code = code.replace(line, " " + code[line]); } switch (obj.method_state(method)) { case 'root: line = "+root"; case 'driver: line = "+driver"; case 'public: line = "+public"; case 'protected: line = "+protected"; case 'private: line = "+private"; } opt = (opt ? opt + " " | "") + line; flags = obj.method_flags(method); if ('disallow_overrides in flags) opt = opt + " +disallow"; if ('synchronized in flags) opt = opt + " +sync"; if ('locked in flags) opt = opt + " +locked"; line = obj.objname() + "." + tostr(method) + " " + opt; if (nums) out = ["--- Method " + line]; else out = ["@program " + line]; out = out + code + ["."]; return out; . protected _display_variables arg obj, info, chop, comments; var line, tidbit, len; (> .perms(sender(), 'this) <); len = .linelen(); for tidbit in (info) { line = " " + (tidbit[1] != obj ? tidbit[1].objname() | "") + ","; line = line + tostr(tidbit[2]) + ": "; line = line + $data_lib.unparse(tidbit[3]); if (chop) line = line.chop(len); .tell(line); } . protected mmod_cmd arg cmdstr, cmd, str; var args, options, ref, obj, meth, opt, info, line, def, mname, flags, b; options = [["dr?iver"], ["r?oot"], ["pub?lic"], ["priv?ate"], ["prot?ected"], ["di?sallow_overrides"], ["s?yncronized"], ["l?ocked"], ["n?ative"]]; if (!str) { .tell(["", "=> Syntax: " + cmd + " <method> <method flags>", "", "Where flags can be any of:", ""]); for opt in (options.slice(1)) .tell(" +|-" + opt); return; } args = $parse_lib.getopt(str, options); catch any { ref = $parse_lib.xreference(args[1].to_string()); } with handler { return traceback()[1][2]; } if (!ref || ref[1] != 'method) return "Invalid object.method reference."; meth = ref[4]; obj = ref[3]; mname = ref[3].objname() + "." + tostr(ref[4]) + "()"; if (!ref[2].is_writable_by(this())) return "You cannot write to " + ref[2].namef('xref) + "."; def = (| ref[3].find_method(ref[4]) |); if (!def) return "Method " + mname + " does not exist."; if (def != ref[3]) return ref[2].objname() + " does not define " + mname; if (!args[2]) { return .display_cmd("", "", ref[3].objname() + "." + tostr(ref[4]) + "*"); info = ._get_method_info(obj, meth); switch (obj.method_state(meth)) { case 'public: .tell("Public Method:"); case 'private: .tell("Private Method:"); case 'protected: .tell("Protected Method:"); } return [$object_lib.parse_method_flags(info[4]) + tostr(info[5]).right(4) + " " + info[1].objname() + "." + tostr(info[2]) + "(" + info[3] + ")"]; } flags = obj.method_flags(meth); if ('locked in flags) return mname + " is locked, and cannot be changed."; if ('native in flags) return mname + " is native, and cannot be changed."; for opt in (args[2]) { switch (opt[1]) { case "pub?lic": obj.set_method_state(meth, 'public); .tell("Method " + mname + " set to Public."); case "r?oot": obj.set_method_state(meth, 'root); .tell("Method " + mname + " set to Root."); case "dr?iver": obj.set_method_state(meth, 'driver); .tell("Method " + mname + " set to Driver."); case "priv?ate": obj.set_method_state(meth, 'private); .tell("Method " + mname + " set to Private."); case "prot?ected": obj.set_method_state(meth, 'protected); .tell("Method " + mname + " set to Protected."); case "di?sallow_overrides": flags = obj.method_flags(meth).setadd('disallow_overrides); obj.set_method_flags(meth, flags); .tell("Method " + mname + " flags are now: " + $object_lib.parse_method_flags(flags)); case "s?yncronized": flags = obj.method_flags(meth).setadd('synchronized); obj.set_method_flags(meth, flags); .tell("Method " + mname + " flags are now: " + $object_lib.parse_method_flags(flags)); case "l?ocked": .tell("You cannot set the locked flag."); case "n?ative": .tell("You cannot set the native flag."); default: .tell("Unable to process flag: \"" + (opt[3] ? "+" | "-") + opt[2] + "\"."); } } . public parse_methodcmd_options arg syntax, args, [more]; var o, opt, opts, out, r; o = [@more, []][1] + [["pub?lic"], ["r?oot"], ["dr?iver"], ["pri?vate"], ["pro?tected"], ["di?sallow_overrides"], ["s?yncronized"], ["l?ocked"], ["n?ative"]]; opts = #[['exists, 0], ['ignore, 0], ['mflags, []], ['mstate, 'public], ['error, 0]].union([@more, #[], #[]][2]); args = $parse_lib.getopt(args, o); if (!args[1]) { out = []; for opt in (o) out = [@out, " +|-" + opt[1]]; (> .tell_error(syntax, ["Valid options:"] + out.lcolumnize()) <); } r = (| $parse_lib.xreference(args[1].to_string()) |); if (!r) { opts = opts.add('error, "Invalid <object>.<method> reference."); opts = opts.add('ignore, 1); } if (r[2] && !r[2].is_writable_by(this())) { opts = opts.add('error, "You cannot program " + r[2].objname() + "."); opts = opts.add('ignore, 1); } if ((| r[2].find_method(r[4]) |) == r[2]) { opts = opts.add('mflags, r[2].method_flags(r[4])); opts = opts.add('mstate, r[2].method_state(r[4])); opts = opts.add('exists, 1); } opts = opts.add('object, r[2]); opts = opts.add('method, r[4]); for opt in (args[2]) { switch (opt[1]) { case "pub?lic", "r?oot", "dr?iver", "pri?vate", "pro?tected": opts = opts.add('mstate, opt[1].strip("?").to_symbol()); case "di?sallow_overrides", "s?yncronized": opts = opts.add('mflags, opts['mflags].setadd(opt[1].strip("?").to_symbol())); case "l?ocked": .tell("You cannot set the locked flag on a method."); case "n?ative": .tell("You cannot set the native flag on a method."); default: if (!opt[1]) { .tell("Unknown option: \"" + opt[2] + "\""); .tell("Valid options: " + o.slice(1).to_english()); continue; } opts = opts.add(opt[1].strip("?").to_symbol(), [opt[3], opt[4]]); } } return opts; . protected chmanage_cmd arg cmdstr, cmd, args; var obj, manager; args = args.replace(" to ", " ").explode(); if (!args || args.length() != 2) .tell_error(cmd + " <object> [to] <user>"); obj = .match_env_nice(args[1]); manager = .match_env_nice(args[2]); if (!manager.is($user) && !.is($admin)) return "Sorry you can only set users as managers."; catch any { (> obj.change_manager(manager) <); } with handler { return traceback()[1][2]; } return "Manager on " + obj.namef('xref) + " changed to " + manager.namef('xref) + "."; . protected managed_cmd arg cmdstr, cmd, args; var manager, managed, obj, out, len; manager = (| .match_environment(args) |); if (!manager) { manager = (| $user_db.find(args) |); if (!manager) return "Unable to find \"" + args + "\"."; } managed = manager.managed(); if (!managed) return manager.namef('ref) + " does not manage any objects."; out = [manager.namef('ref) + " manages:"]; len = .linelen() / 2; for obj in (managed) out = out + [" " + obj.namef('xref).pad(len) + " " + $object_lib.see_perms(obj, ["", ""])]; return out; . protected trusted_by_cmd arg cmdstr, cmd, args; var target, trusted, obj, out, len; target = (| .match_environment(args) |); if (!target) { target = (| $user_db.find(args) |); if (!target) return "Unable to find \"" + args + "\"."; } trusted = target.trusted_by(); if (!trusted) return target.namef('ref) + " is not in any object's trusted list."; out = [target.namef('ref) + " is in the trusted list for:"]; return out + $object_lib.generate_object_listing('trusted_by, 'trusted, 'literal); . public create_cmd arg cmdstr, cmd, args; var new, parents, obj; args = args.replace(" from ", " ").explode(); if (!args || args.length() < 2) .tell_error(cmd + " <object> [from] <parent>[, <parent> ...]"); new = args[1]; parents = []; for obj in (args.subrange(2)) parents = parents + [.match_env_nice(obj)]; . public make_patch_cmd arg cmdstr, com, args; var objs, obj, tmp, last, out, line, p, n; objs = out = []; for tmp in (args.explode()) { if (tmp[1] == "-") { out = out + ["old " + tmp.subrange(2)]; continue; } objs = objs + [.match_env_nice(tmp)]; } for obj in (objs) { n = obj.objname(); p = obj.parents(); line = "object " + n; if (obj.is($named)) line = line + " \"" + obj.name() + "\""; out = out + ["", line]; for tmp in (p.map('objname)) out = out + ["parent " + tmp]; } return out; . parent $player object $storyteller var $root objname 'storyteller var $root created_on 809928922 var $root inited 1 var $root flags ['parameters, 'methods, 'code, 'core] var $has_commands shortcuts #[] var $has_commands remote #[] var $has_commands local #[] var $player strength [0, 0] var $player agility [0, 0] var $player appearance [0, 0] var $player health [0, 0] var $player life [0, 0] var $player intellect [0, 0] var $player knowledge [0, 0] var $player backbone [0, 0] var $player charisma [0, 0] var $player humanity [0, 0] var $player perception [0, 0] var $player presence [0, 0] var $player source [0, 0] var $player weapons [] parent $located_location object $on_location var $root objname 'on_location var $root created_on 809991549 var $root inited 1 var $root flags ['parameters, 'methods, 'code, 'core] var $has_commands shortcuts #[] var $has_commands remote #[] var $has_commands local #[] var $has_settings defined_settings #[] var $has_settings local_settings #[] var $has_settings settings #[] var $named name ['uniq, "located_location_2", "the located_location_2"] var $named name_aliases [] var $gendered gender $gender_neuter var $described prose [] var $location contents [] var $located location $nowhere var $located obvious 1 public description arg flags; var line; line = "You see " + .contents().map_to_english('namef) + " on " + .name() + "."; return (> pass(flags) <) + [line]; . parent $located_location object $in_location var $root objname 'in_location var $root created_on 809991552 var $root inited 1 var $root flags ['parameters, 'methods, 'code, 'core] var $has_commands shortcuts #[] var $has_commands remote #[] var $has_commands local #[] var $has_settings defined_settings #[] var $has_settings local_settings #[] var $has_settings settings #[] var $named name ['uniq, "located_location_3", "the located_location_3"] var $named name_aliases [] var $gendered gender $gender_neuter var $described prose [] var $location contents [] var $located location $nowhere var $located obvious 1 public description arg flags; var line; line = "You see " + .contents().map_to_english('namef) + " in " + .name() + "."; return (> pass(flags) <) + [line]; . parent $log object $http_log var $root inited 1 var $root objname 'http_log var $root created_on 796268969 var $root flags ['methods, 'code, 'core] var $root writers [$http_lib, $false] var $messaged verbs #[] var $messaged messages #[] var $public public ['readable] var $text text [] var $named name ['prop, "HTTP Log", "HTTP Log"] var $named name_aliases [] var $gendered gender $gender_neuter var $described prose [] var $located location $nowhere var $located obvious 1 var $http_log tally 3896 public log arg [args]; tally = tally + 1; . public tally return tally; . parent $log object $reaper_log var $root inited 1 var $root objname 'reaper_log var $root created_on 796268969 var $root flags ['methods, 'code, 'core] var $public public ['readable] var $text text [] var $named name ['prop, "Reaper Logfile", "Reaper Logfile"] var $named name_aliases [] var $gendered gender $gender_neuter var $messaged verbs #[] var $messaged messages #[] var $described prose [] var $located location $nowhere var $located obvious 1 parent $log object $login_log var $root inited 1 var $root trusted [$login_interface] var $root objname 'login_log var $root created_on 796268969 var $root flags ['methods, 'code, 'core] var $messaged verbs #[] var $public public ['readable] var $text text [] var $named name ['uniq, "log_3", "the log_3"] var $named name_aliases [] var $gendered gender $gender_neuter var $described prose [] var $located location $nowhere var $located obvious 1 parent $mail_list object $mail_list_news var $root fertile 1 var $root inited 1 var $root objname 'mail_list_news var $root created_on 796268969 var $root flags ['parameters, 'methods, 'code, 'fertile, 'core] var $root indestructable 1 var $named name ['prop, "news", "news"] var $named name_aliases [] var $mail_list mail [] var $mail_list senders 1 var $mail_list readers 1 var $mail_list notify [] var $mail_list last_received_on 812313975 parent $mail_list object $mail_list_bugs var $root objname 'mail_list_bugs var $root created_on 811630223 var $root inited 1 var $root flags ['parameters, 'methods, 'code, 'core] var $has_settings defined_settings #[] var $has_settings local_settings #[] var $has_settings settings #[] var $named name ['prop, "bugs", "bugs"] var $named name_aliases [] var $mail_list mail [] var $mail_list senders 1 var $mail_list readers 1 var $mail_list notify [] var $mail_list last_received_on 812141528 parent $registry object $place_db var $root trusted 1 var $root inited 1 var $root objname 'place_db var $root created_on 796268969 var $root flags ['parameters, 'methods, 'code, 'core] var $db database #[["void", $void], ["nowhere", $nowhere], ["The Pit", $the_pit]] var $registry stripped_characters "!@#$%^&*()_+-=~`'{}[]|/?\"\\,.<>;:" public place_destroyed // called in $place.uninit_place (incase the place is in the db) . parent $registry object $user_db var $root trusted [$user] var $root inited 1 var $root objname 'user_db var $root created_on 796268969 var $root flags ['methods, 'parameters, 'code, 'core] var $root indestructable 1 var $db database #[["GenericUserObject", $user], ["GenericBuilder", $builder], ["GenericGuestObject", $guest], ["Reaper", $reaper], ["NoOne", $no_one], ["GenericProgrammer", $programmer], ["GenericAdmin", $admin], ["player", $player]] var $user_db connected [] var $user_db invalid_chars "$#@!^&%~" var $registry stripped_characters "!@#$%^&*()_+-=~`'{}[]|/?\"\\,.<>;: " var $registry reserved_names ["user", "builder", "programmer", "admin", "housekeeper", "Reaper", "noone", "guest", "a", "i", "an", "your", "you'r", "me", "god"] var $registry invalid_names ["ass", "cunt", "fuck", "shit", "damn", "the"] var $registry min_char_len 3 var $registry max_char_len 20 public users return .database().keys(); . public connected var x; for x in (connected) { if (!valid(x) || (| !x.connections() |)) connected = connected.setremove(x); } return connected; . public did_connect (> .perms(caller(), $user) <); connected = connected.setadd(sender()); . public did_disconnect .perms(caller(), $user); connected = connected.setremove(sender()); . public valid_name arg name; if ($string.strip(name, invalid_chars).length() < name.length()) throw(~invname, "Names cannot contain any of '" + invalid_chars + "'."); return (> pass(name) <); . public match arg name; return (> .find(name) <); . public total_connected return .connected().length(); . public clean_user_db var key, db, invalid; connected = []; db = .database(); invalid = []; for key in (.database().keys()) { if (!valid(db[key])) { .remove(key); invalid = [@invalid, key]; } } return ["Invalid $user_db entries: " + invalid.to_english()]; . parent $cml2_evaluator object $cml2_format var $root objname 'cml2_format var $root child_index 4 var $root fertile 1 var $root created_on 806313297 var $root inited 1 var $root flags ['parameters, 'methods, 'code, 'fertile, 'core] public eval_ctext arg data, vars; var ret, v, k; v = .init(); for k in (v.keys()) vars = vars.add(k, v[k]); ret = ._eval_ctext(vars, data); if (!ret[2]['newline]) return ret[1] + "\\n"; else return ret[1]; . public _eval_ctext arg vars, data; var out, uflags, ret, token; out = ""; if (type(data) != 'list) data = [data]; for token in (data) { switch (type(token)) { case 'frob: switch (class(token)) { case $ctext_generator: ret = vars['evaluator].eval_generator(vars, token); token = ret[1]; vars = ret[2]; catch ~type { out = out + token; } with handler { ret = ._eval_ctext(vars, token); out = out + token; } case $ctext_format: ret = .eval_formatter(vars, token); token = ret[1]; vars = ret[2]; out = out + token; default: out = out + token; } case 'string: out = out + token; case 'list: ret = ._eval_ctext(vars, token); token = ret[1]; out = out + token; vars = ._check_newline(ret[2], token); default: out = out + token; } if (token.length() >= 3 && token.subrange(token.length() - 1) == "\\n") vars = vars.add('newline, 1); else vars = vars.add('newline, 0); } return [out, vars]; . public do__ln arg vars, flags, args; return ["", vars.add('line, vars['line] + 1)]; . public eval_generator arg vars, gen; return vars['evaluator].eval_generator(vars, gen); . public gen_group arg vars, flags, args; return ._eval_ctext(vars, args); . public do_group arg vars, flags, args; var out, token, ret; ret = ._eval_ctext(vars, args); return ret; . public _check_newline arg vars, str; if (str && str.last() == "\\n") return vars.add('newline, 1); else return vars.add('newline, 0); . public eval_formatter arg vars, form; var flags, key, value, ret; flags = form.ctext_uflags(); for key in (flags.keys()) { ret = ._eval_ctext(flags[key], vars); form = form.add_ctext_flag(key, ret[1]); vars = ret[2]; } catch ~methodnf { ret = .(form.method())(vars, form.ctext_flags(), form.args()); } with handler { return [">>ERROR: unknown formatter " + form.name() + ".<<", vars]; } return [ret[1], ret[2]]; . parent $cml2_evaluator object $cml2_base_eval var $root objname 'cml2_base_eval var $root child_index 1 var $root created_on 806303080 var $root inited 1 var $root flags ['parameters, 'methods, 'code, 'core] public gen_server_name arg vars, flags, args; return [$motd.server_name(), vars]; . public gen_set arg vars, flags, args; var ret, name; ret = ._eval_ctext(vars, [args[1]]); name = ret[1][1]; ret = ._eval_ctext(vars, [args[2]]); return [[""], vars.add(name, ret[1])]; . public gen_name arg vars, flags, args; var ret, out, name; ret = ._eval_ctext(vars, args); args = ret[1]; vars = ret[2]; out = []; if (!args) out = [vars['this].name()]; for name in (args) { switch (type(name)) { case 'dbref: name = name.name(); case 'string: catch ~objnf { name = vars['this].match_environment(name).name(); } with handler { name = name; } } out = [@out, name]; } return [out, vars]; . public gen_english arg vars, flags, args; var out, item, ret, sep, empty; sep = ((| flags["sep"] |) || ",") + " "; empty = (| flags["empty"] |) || "nothing"; ret = ._eval_ctext(vars, args); args = ret[1]; vars = ret[2]; out = []; if (args.length() == 0) return [[empty], vars]; if (args.length() == 1) return [args, vars]; if (args.length() == 2) return [[args[1], " and ", args[2]], vars]; out = [@out, args[1]]; for item in (args.chop().subrange(2)) out = [@out, sep, item]; out = [@out, " and ", args.last()]; return [out, vars]; . public gen_group arg vars, flags, args; return ._eval_ctext(vars, args); . public gen_def arg vars, flags, args; var ret, name; ret = ._eval_ctext(vars, [args[1]]); name = ret[1][1]; return [[""], vars.add(name, args[2])]; . public gen_foreach arg vars, flags, args; var v, list, body, out, item, ret; v = (| flags["var"] |) || "##"; list = flags["list"]; out = []; for item in (list) { vars = vars.add(v, item); ret = ._eval_ctext(vars, args); if (vars['time] == 'format) out = out.join(ret[1]); else out = [@out, @ret[1]]; vars = ret[2]; } return [out, vars]; . public gen_time arg vars, flags, args; var out, ret, a, word; ret = ._eval_ctext(vars, args); args = ret[1]; vars = ret[2]; if (!args) return [tostr(time()), vars]; out = ""; for a in (args) { if (type(a) == 'string && "%" in a) out = out + (out ? " " | "") + $time.format(a); else out = out + (out ? " " | "") + a; } return [out, vars]; . public gen_vars arg vars, flags, args; var out, v; out = []; for v in (vars.keys()) { if (type(v) == 'string) out = [@out, v]; } return [out, vars]; . public gen_get arg vars, flags, args; var name, ret; ret = ._eval_ctext(vars, args); args = ret[1]; vars = ret[2]; name = args[1]; return [[vars[name]], vars]; . parent $cml2_evaluator object $cml2_uncompiler var $root objname 'cml2_uncompiler var $root created_on 806303067 var $root inited 1 var $root flags ['parameters, 'methods, 'code, 'core] public eval_ctext arg data, [vars]; var ret; vars = [@vars, #[]][1]; vars = vars.add('line, 1); ret = ._eval_ctext(vars, data); return ret[1]; . public eval_generator arg vars, gen; var out, flags, key, value, ret; catch ~methodnf { ret = .(tosym("gen_" + gen.name()))(vars, gen.ctext_flags(), gen.args()); return [ret[1], ret[2]]; } with handler { out = ["[" + gen.name()]; flags = gen.ctext_flags(); for key in (flags.keys()) { if (flags[key] == 1) { out = out.join(" " + key); } else if (type(flags[key]) == 'list) { ret = (> ._eval_ctext(vars, [flags[key]]) <); out = out.join(" " + key + "=" + ret[1][1]); vars = ret[2]; } else { ret = (> ._eval_ctext(vars, flags[key]) <); out = out.join(" " + key + "=" + ret[1][1]); vars = ret[2]; } } if (gen.args()) out = out.join(":"); for key in (gen.args()) { ret = (> ._eval_ctext(vars, [key]) <); out = out.join([" "].join(ret[1])); vars = ret[2]; } return [out.join("]"), vars]; } . public _eval_ctext arg vars, data; var out, uflags, ret, token, a; out = []; if (type(data) != 'list) data = [data]; while (data) { token = data[1]; data = data.subrange(2); switch (type(token)) { case 'frob: if (class(token) == $ctext_generator) { ret = (> .eval_generator(vars, token) <); out = out.join(ret[1]); vars = ret[2]; } else if (class(token) == $ctext_format) { ret = (> .eval_formatter(vars, token) <); out = out.join(ret[1]); vars = ret[2]; } else { out = out.join(token); } case 'string: out = out.join(token); case 'list: out = out.join("[:"); for a in (token) { ret = ._eval_ctext(vars, a); out = out.join(" ").join(ret[1]); vars = ret[2]; } out = out.join("]"); default: out = out.join($data_lib.unparse(token)); } } return [out, vars]; . public do__ln arg vars, flags, args; return [[""], vars]; . public do_dl arg vars, flags, args; var out, ret, key, a; out = "dl"; for key in (flags.keys()) { if (flags[key] == 1) { out = out + " " + key; } else { ret = ._eval_ctext(vars, flags[key]); out = out + " " + key + "=" + ret[1][1]; vars = ret[2]; } } out = ["", "{" + out + "}", ""]; for a in (args) { ret = ._eval_ctext(vars, a); out = out.join(ret[1]); vars = ret[2]; } out = out.join(["{-dl}", ""]); return [out, vars]; . public do_dd arg vars, flags, args; var ret, out; out = ["", "{dd}"]; ret = ._eval_ctext(vars, args); out = out.join(ret[1]).join("{-dd}"); return [[@out, ""], ret[2]]; . public gen_group arg vars, gen; var out, a, ret; out = ["[:"]; for a in (gen.args()) { ret = ._eval_ctext(vars, a); out = out.join(" ").join(ret[1]); vars = ret[2]; } return [out.join("]"), vars]; . public do_group arg vars, flags, args; var ret, out; out = ["", "{:"]; ret = (> ._eval_ctext(vars, args) <); out = out.join(ret[1]).join("}"); return [out, ret[2]]; . public eval_formatter arg vars, gen; var out, flags, key, value, ret; catch ~methodnf { ret = .(tosym("do_" + gen.name()))(vars, gen.ctext_flags(), gen.args()); return [ret[1], ret[2]]; } with handler { out = ["{" + gen.name()]; flags = gen.ctext_flags(); for key in (flags.keys()) { if (flags[key] == 1) { out = out.join(" " + key); } else { ret = ._eval_ctext(vars, flags[key]); out = out.join(" " + key + "=" + ret[1][1]); vars = ret[2]; } } flags = gen.ctext_uflags(); for key in (flags.keys()) { if (flags[key] == 1) { out = out.join(" " + key); } else { ret = ._eval_ctext(flags[key], vars); out = out.join(" " + key + "=" + ret[1][1]); vars = ret[2]; } } if ($cml2_form.is_block(gen.name())) { out = out.join("}"); for key in (gen.args()) { ret = ._eval_ctext(vars, [key]); out = out.join(ret[1]); vars = ret[2]; } out = out.join("{-" + gen.name() + "}"); } else if ($cml2_form.is_field(gen.name())) { out = out.join("}"); for key in (gen.args()) { ret = ._eval_ctext(vars, [key]); out = out.join(ret[1]); vars = ret[2]; } } else { out = out.join("}"); } return [out, vars]; } . parent $lock_frob object $or_lock_frob var $root objname 'or_lock_frob var $root created_on 796268969 var $root flags ['parameters, 'methods, 'code, 'core] public new arg lhs, rhs; if (type(lhs) != 'frob || type(rhs) != 'frob) throw(~perm, "Arguments are not both frobs."); return (<this(), [lhs, rhs]>); . public try arg lock, obj; return lock[1].try(obj) || lock[2].try(obj); . public lock_name arg lock, [type]; type = [@type, 'literal][1]; switch (type) { case 'literal: return "(" + lock[1].lock_name(type) + " || " + lock[2].lock_name(type) + ")"; default: return lock[1].lock_name(type) + " or " + lock[2].lock_name(type); } . parent $lock_frob object $true_lock_frob var $root objname 'true_lock_frob var $root created_on 796268969 var $root flags ['parameters, 'methods, 'code, 'core] var $lock_frob names #[['default, "true"], ['exit, "anybody"], ['str, "any"]] public new return (<this(), []>); . public try arg lock, obj; return 1; . parent $lock_frob object $false_lock_frob var $root objname 'false_lock_frob var $root created_on 796268969 var $root flags ['parameters, 'methods, 'code, 'core] var $lock_frob names #[['str, "none"], ['exit, "nobody"], ['default, "false"]] public new return (<this(), []>); . public try arg lock, obj; return 0; . parent $lock_frob object $not_lock_frob var $root objname 'not_lock_frob var $root created_on 796268969 var $root flags ['parameters, 'methods, 'code, 'core] public new arg lock; if (type(lock) != 'frob) throw(~perm, "Argument is not a lock."); return (<this(), [lock]>); . public try arg lock, obj; return !lock[1].try(obj); . public lock_name arg lock, [type]; type = [@type, 'literal][1]; switch (type) { case 'literal: return "(!" + lock[1].lock_name(type) + ")"; default: return "not " + lock[1].lock_name(type); } . parent $lock_frob object $object_lock_frob var $root objname 'object_lock_frob var $root created_on 796268969 var $root flags ['parameters, 'methods, 'code, 'core] public new arg obj; if (type(obj) != 'dbref) throw(~perm, "Argument is not a dbref."); return (<this(), [obj]>); . public try arg lock, obj; return lock[1] == obj || obj == sender() || $sys.is_system(obj); . public test arg testlist, testee, [args]; var x; for x in (testlist) { if (testee == x) return 1; } return 0; . public lock_name arg value, [type]; return value[1].name(); . parent $lock_frob object $and_lock_frob var $root objname 'and_lock_frob var $root created_on 796268969 var $root flags ['parameters, 'methods, 'code, 'core] public new arg lhs, rhs; if (type(lhs) != 'frob || type(rhs) != 'frob) throw(~perm, "Arguments are not both frobs."); return (<this(), [lhs, rhs]>); . public try arg lock, obj; return lock[1].try(obj) && lock[2].try(obj); . public lock_name arg lock, [type]; type = [@type, 'literal][1]; switch (type) { case 'literal: return "(" + lock[1].lock_name(type) + " && " + lock[2].lock_name(type) + ")"; default: return lock[1].lock_name(type) + " and " + lock[2].lock_name(type); } . parent $lock_frob object $inside_lock_frob var $root trusted [] var $root inited 1 var $root objname 'inside_lock_frob var $root created_on 796268969 var $root flags ['parameters, 'methods, 'code, 'core] public try arg objs, obj; var o; for o in (objs) { if (o.contains(obj)) return 1; } return 0; . parent $programmer object $admin var $root owners [$admin] var $root inited 1 var $root owned [$admin] var $root manager $admin var $root quota 75000 var $root objname 'admin var $root created_on 796268969 var $root flags ['parameters, 'methods, 'code, 'core] var $root managed [$admin] var $messaged verbs #[] var $location contents [] var $located location $body_cave var $located obvious 1 var $user password "*" var $user connected_at 0 var $user last_command_at 0 var $user connections [] var $user modes #[] var $user prompt "" var $user parsers [$command_parser] var $user tell_traceback ['verbose, 4] var $user context #[] var $user filters [] var $programmer eval_prefix #[["me", "me = this()"], ["here", "here = this().location()"]] var $programmer eval_offset #[] var $admin shutdown_started 0 var $command_aliases command_aliases [] var $mail_list letters #[] var $mail_list letters_index #[] var $mail_list senders 1 var $mail_list readers [] var $mail_list notify [$admin] var $mail_list last_letter 0 var $mail_list mail [] var $mail_ui subscribed #[[$admin, 791485891]] var $mail_ui current #[['location, 0], ['list, $admin]] var $gendered gender $gender_neuter var $described prose [] var $named name ['prop, "Generic Admin", "Generic Admin"] var $named name_aliases [] var $user_data user_data #[['real_name, [1, "???"]], ['email, [1, "???"]]] var $has_commands local #[["@task?s", [["@task?s", "", "@task?s", 'tasks_cmd, #[]]]], ["@del-t?ask|@kill", [["@del-t?ask|@kill", "*", "@del-t?ask|@kill <any>", 'del_task_cmd, #[[1, ['any, []]]]]]], ["@backup", [["@backup", "", "@backup", 'backup_cmd, #[]]]], ["@shutdown", [["@shutdown", "*", "@shutdown <any>", 'shutdown_cmd, #[[1, ['any, []]]]]]], ["@adjust", [["@adjust", "user|att?itude * to *", "@adjust user|att?itude <any> to <any>", 'adjust_user_cmd, #[[2, ['any, []]], [4, ['any, []]]]]]], ["@ustat", [["@ustat", "*", "@ustat <any>", 'user_stat_cmd, #[[1, ['any, []]]]]]], ["@grep", [["@grep", "*", "@grep <any>", 'grep_cmd, #[[1, ['any, []]]]]]], ["@dump-grep|@dgrep", [["@dump-grep|@dgrep", "*", "@dump-grep|@dgrep <any>", 'dump_grep_cmd, #[[1, ['any, []]]]]]], ["@mojo", [["@mojo", "*", "@mojo <any>", 'mojo_cmd, #[[1, ['any, []]]]]]]] var $help_ui indices [$help_index_root] var $help_ui history [$help_summary] var $help_ui current 1 var $command_cache shortcut_cache 0 var $command_cache remote_cache 0 var $command_cache local_cache 0 root init_admin $sys.new_admin(); . public del_task_cmd arg cmdstr, com, task; var syn; (> .perms(sender(), 'this) <); (> .check_mojo() <); syn = com + " <task ID>"; task = toint(task); if (!task) (> .tell_error(syn, "Tasks must be given as an integer") <); catch any { $scheduler.del_task(task); } with handler { (> .tell_error(syn, traceback()[1][2]) <); } .tell("Task number " + tostr(task) + " deleted."); . public tasks_cmd arg cmdstr, com; var out, task, task_queue, line, len_c1, time, args, fmt, tfmt; (> .perms(sender(), 'this) <); (> .check_mojo() <); task_queue = $scheduler.task_queue(); if (task_queue) { out = []; tfmt = "%d %h %y %H:%M:%S"; fmt = "%5L %20L %s"; time = $time.format(tfmt); out = fmt.format("ID", "Exec Time", "Task"); out = [out, fmt.format("---", "---------", "----")]; fmt = fmt + ".%s(%s)"; for task in (task_queue) { args = $data_lib.unparse(task[8]); out = out + [fmt.format(task[1], $time.format(tfmt, task[2] + task[3]), $data_lib.unparse(task[4]), task[6], args.subrange(2, args.length() - 2))]; } // once tasks() returns more intelligent info, we can parse it here return out + ["---"]; } else { .tell("*** NO TASKS ****"); } . public backup_cmd arg cmdstr, com; (> .perms(sender(), 'this) <); (> .check_mojo() <); .tell("Starting backup."); $sys.do_backup(this()); .tell("Done."); . public shutdown_cmd arg cmdstr, com, [args]; var time, opt, why, answer; (> .perms(sender(), 'this) <); (> .check_mojo() <); args = $parse_lib.getopt(args, [["t?ime", 1]]); if (opt = "t?ime" in args[2].slice(1) && args[2][opt][4].is_numeric()) time = toint(args[2][opt][4]); else time = 5; if (!why = args[1].to_string()) why = "Administrator's whim."; .tell("Server shutdown in " + tostr(time) + " minutes"); .tell("Reason for shutdown: " + why); ans = .prompt("Is this correct? [yes]: "); if (!ans) ans = "yes"; if (!(ans in ["yes", "y"])) { .tell("I didn't think so, aborting shutdown..."); return; } .tell("Ok!"); $sys.do_shutdown(time, why); . public adjust_user_cmd arg cmdstr, com, com, who, com, what; var promos, wp, name, pwd; (> .perms(sender(), 'this) <); (> .check_mojo() <); what = what.explode(); what = what[what.length()]; promos = #[["user", ['user, $user]], ["builder", ['builder, $builder]], ["programmer", ['programmer, $programmer]], ["admin", ['admin, $admin]]]; who = .match_env_nice(who); wp = who.parents(); if (!(what in promos.keys())) $parse_lib.tell_error("Promote to any of: " + promos.keys().to_english() + "."); (| who.chparents(promos[what][2]) |); who.tell(.namef() + " has made you " + $string.a_or_an(what) + " " + what + "."); if ($guest in wp) { pwd = $code_lib.random_word(); who.set_password(pwd); (| who.del_filter($wrap_filter) |); who.tell("Your password is currently \"" + pwd + "\"."); who.tell("You can change it with the command: `@password`"); who.set_title(""); } who.rehash_caches(); .tell("Ok, " + who.namef('titled) + " is now a " + what + "."); . public grep_cmd arg cmdstr, cmd, args; var what, from, obj, syn, opts, d, f; (> .perms(sender(), 'this) <); (> .check_mojo() <); syn = cmd + " <regexp> <object> [+|-d?escend] [+|-f?ull]"; syn = [syn, "Flags default to -descend -full."]; if (!args) .tell_error(@syn); args = $parse_lib.getopt(args, [["d?escend"], ["f?ull"]]); d = (| "d?escend" in args[2].slice(1) |); if (d) d = args[2][d][3]; f = (| "f?ull" in args[2].slice(1) |); if (f) f = args[2][f][3]; args = args[1]; if (args.length() != 2) return .tell(syn); what = args[1]; obj = .match_env_nice(args[2]); if (!what) return .tell(syn); .tell("Searching for \"" + what + "\"..."); .grep(what, d, f, obj); .tell("---"); . public egrep_cmd arg what; var found, x; (> .perms(sender(), 'this) <); (> .check_mojo() <); .tell("Searching..."); found = .grep(what, 'regexp); for x in (found) .tell(x[1].name_str() + "." + tostr(x[2]) + " : " + tostr(x[3][1])); .tell("--- + Finis + ---"); . public grep arg regexp, from, full, object; var objects, x, method, total; objects = [object]; if (from) objects = [@objects, @object.descendants()]; method = full ? '_grep_object_full | '_grep_object_brief; for object in (objects) { .(method)(regexp, object, full); total = total + 1; pause(); } // fix later .tell(tostr(total) + " Object" + (total == 1 ? "" | "s") + " Searched."); . public user_stat_cmd arg cmdstr, cmd, str; var u, x, y, cs, line; (> .perms(sender(), 'this) <); (> .check_mojo() <); u = .find_object_nice(str, 'user, 'environment, 'grasp); line = "Random stats on user " + u.name(); line = line + " <" + u.user_data('email) + ">"; .tell(line + " [" + tostr($code_lib.user_type(u)) + "]:"); x = u.quota_byte_usage(); y = u.quota(); line = " Quota: " + y.to_english() + " Usage: " + x.to_english() + " Remaining: " + (y - x).to_english(); .tell(line); if (u.connected()) { .tell(" Connections:"); cs = u.connections(); for x in [1 .. cs.length()] { line = " " + cs[x].objname() + ": ["; line = line + $time.ldate(cs[x].active_since(), 'date); line = line + "/" + $time.ltime(cs[x].active_since(), '24hr_sec); .tell(line + "] " + cs[x].address()); } } else { .tell(" Last connected at " + $time.ltime(abs(u.connected_at())) + " " + $time.ldate(abs(u.connected_at()))); } .tell(u.display_data()); . public _grep_object arg regexp, obj, [how]; var method, found, findings, what; (> .perms(sender(), 'this) <); findings = []; if (valid(obj)) { for method in (obj.methods()) { found = ._grep_text(regexp, obj.list_method(method), @how); if (found) findings = findings + [[obj, method, found]]; pause(); } } return findings; . private _grep_text arg regexp, text; var line, result, lines; lines = []; for line in [1 .. text.length()] { if ($string.match_regexp(regexp, text[line])) lines = lines + [[line, text[line]]]; } return lines; . public dump_grep_cmd arg cmdstr, cmd, args; var what, from, obj, syn, opts, objs, found, local, anc; (> .perms(sender(), 'this) <); (> .check_mojo() <); syn = cmd + " <regexp> <object> [+|-d (descend)]"; syn = [syn, "The descend flag defaults to +d."]; if (!args) return .tell_error(@syn); opts = #[["d", [1, 0]]]; args = $parse_lib.options(args, opts); opts = args[2]; args = args[1]; if (args.length() != 2) return .tell(syn); what = args[1]; obj = .match_env_nice(args[2]); if (!what) return .tell(syn); if (opts["d"][1]) objs = [obj] + obj.descendants(); else objs = [objs]; what = "*" + what + "*"; found = []; for obj in (objs) { local = ._grep_object(what, obj); if (local) found = found + local; pause(); } if (found) { .tell("-----starting output-----"); for local in (found) { anc = local[1].find_method(local[2]); .tell("@program -e " + anc.objname() + "." + tostr(local[2])); .tell(anc.list_method(local[2])); .tell("."); pause(); } .tell("-----finished output-----"); } else { .tell("no objects found."); } . public dump_methgrep_cmd arg cmdstr, cmd, args; var what, from, obj, syn, opts, objs, found, local, anc; (> .perms(sender(), 'this) <); (> .check_mojo() <); syn = cmd + " <regexp> <object> [+|-d (descend)"; syn = [syn, "The descend flag defaults to +d."]; if (!args) return .tell_error(syn); opts = #[["d", [1, 0]]]; args = $parse_lib.options(args, opts); opts = args[2]; args = args[1]; if (args.length() != 2) return .tell(syn); what = args[1]; obj = .match_env_nice(args[2]); if (!what) return .tell(syn); if (opts["d"][1]) objs = [obj] + obj.descendants(); else objs = [objs]; what = "*" + what + "*"; found = []; for obj in (objs) { local = ._methgrep_object(what, obj); if (local) found = found + local; pause(); } if (found) { .tell("-----starting output-----"); for local in (found) { anc = local[1].find_method(local[2]); .tell("@program -e " + anc.objname() + "." + tostr(local[2])); .tell(anc.list_method(local[2])); .tell("."); pause(); } .tell("-----finished output-----"); } else { .tell("no objects found."); } . public _methgrep_object arg regexp, obj, [how]; var method, found, findings, what; (> .perms(sender(), 'this) <); findings = []; if (valid(obj)) { for method in (obj.methods()) { if ($string.match_pattern(regexp, tostr(method))) findings = findings + [[obj, method, found]]; } } return findings; . public mojo arg [args]; var name; if (args) name = "Your "; else name = .name() + "'s "; (> .perms(sender(), 'this) <); if (this() in $sys.system()) return name + "eyes glow from Mojo."; else return name + "eyes do not glow from Mojo."; . public mojo_cmd arg cmdstr, cmd, str; var syn, line; (> .perms(sender(), 'this) <); syn = cmd + " on|off"; if (!str || !(str in ["on", "up", "off", "down"])) .tell_error(syn, .mojo(1)); switch (str) { case "on", "up": .location().announce(.name() + "'s eyes begin to glow as Mojo courses through " + .gender().pronoun('po) + ".", this()); $sys.add_to_system(this()); case "off", "down": .location().announce(.name() + "'s eyes stop glowing as the Mojo leaves " + .gender().pronoun('pq) + " body.", this()); $sys.del_from_system(this()); } .tell(.mojo(1)); . public description arg flags; return (> pass(flags) <) + [.mojo()]; . public logout arg [args]; (| $sys.del_from_system(this()) |); return (> pass(@args) <); . protected check_mojo if (!(this() in $sys.system())) { .tell("This command requires Mojo."); throw(~stop, "", 'no_traceback); } . public _grep_object_brief arg regexp, obj, [how]; var method, f, findings, found, what, line; findings = []; if (valid(obj)) { for method in (obj.methods()) { found = ._grep_text(regexp, obj.list_method(method)); if (found) findings = findings + [[method, found.slice(1)]]; pause(); } } line = obj.objname() + "."; for f in (findings) .tell(line + tostr(f[1]) + " line" + (f[2].length() == 1 ? " " | "s ") + f[2].to_english()); . public _grep_object_full arg regexp, obj, [how]; var method, found, findings, what, line; findings = []; line = obj.objname() + "."; if (valid(obj)) { for method in (obj.methods()) { for found in (._grep_text(regexp, obj.list_method(method))) .tell(line + tostr(method) + "() " + tostr(found[1]) + ": " + found[2]); pause(); } } return findings; . parent $generic_editor object $code_editor var $root inited 1 var $root objname 'code_editor var $root created_on 796268969 var $root flags ['parameters, 'methods, 'code, 'core] var $command_aliases command_aliases [] var $has_commands local #[["compile", [["compile", "", "compile", 'compile_cmd, #[]]]], ["refresh", [["refresh", "", "refresh", 'refresh_cmd, #[]]]]] var $command_cache shortcut_cache 0 var $command_cache remote_cache 0 var $command_cache local_cache 0 public start_editing arg what; var ref, obj, method, code; // called by $user_input.edit_cmd ref = $parse_lib.reference(what); obj = (| sender().match_environment(ref[1]) |); if (!obj) { sender().tell(what + " does not describe an editable method."); return 0; } method = tosym(ref[2]); catch any { code = sender().run_with_users_perms(obj, 'list_method, method, 2); } with handler { if (error() == ~methodnf) { code = []; } else { sender().tell("You cannot edit " + what + "."); sender().tell("Error: " + traceback()[1][2]); return 0; } } sender().tell("Now editing " + what + "."); code = $generic_editor.adjust(code, 'spaces); // user doing editing, obj to be programmed, method to be programmed, code, current line // number, changes made return #[['user, sender()], ['obj, obj], ['method, method], ['text, code], ['cur_line, 1], ['changed, 0]]; . public compile_cmd arg editing, cmd; var errors, last_edit; (> .perms(sender(), 'this) <); catch any { last_edit = " // Edited: " + $time.ldate('mdy, 'dash) + "/"; last_edit = last_edit + $time.ltime('12hr, '_ampm) + " "; last_edit = last_edit + "by: " + editing['user].namef('ref); errors = editing['user].run_with_users_perms(editing['obj], 'compile, editing['text] + [last_edit], editing['method]); if (errors) { editing['user].tell(errors); } else { editing['user].tell("Method compiled."); // clear modified flag editing = editing.replace('changed, 0); } } with handler { editing['user].tell("An error occurred attempting to compile."); editing['user].tell("The error was " + traceback()[1][2]); } return editing; . public refresh_cmd arg editing, com; var code; // re-loads method if not changed (> .perms(sender(), 'this) <); if (editing['changed]) { editing['user].tell("Changes have been made. Compile first to refresh."); } else { catch any { code = editing['user].run_with_users_perms(editing['obj], 'list_method, editing['method], 2); } with handler { editing['user].tell("Unable to list method into buffer, error was " + traceback()[1][2]); return editing; } editing = editing.replace('text, code); editing['user].tell("Done."); } return editing; . public help_msg var msg; msg = []; msg = msg + ["The code editor allows you to modify and re-compile methods."]; msg = msg + ["It includes these commands it inherits from the generic editor:"]; msg = msg + pass(); msg = msg + [""]; msg = msg + ["And adds the following:"]; msg = msg + [" compile compile and store current text"]; msg = msg + [" refresh re-load compiled method"]; msg = msg + [""]; return msg; . parent $generic_editor object $note_editor var $root inited 1 var $root objname 'note_editor var $root created_on 796268969 var $root flags ['parameters, 'methods, 'code, 'core] var $command_aliases command_aliases [] var $has_commands local #[["save", [["save", "", "save", 'save_cmd, #[]]]]] var $command_cache shortcut_cache 0 var $command_cache remote_cache 0 var $command_cache local_cache 0 public start_editing arg what; var obj, text; // called by $user_input.edit_cmd obj = (| sender().match_environment(what) |); if (!obj || !(| obj.writeable_by(sender()) |)) { sender().tell("I don't see a note around here called " + what + " that you can edit."); return 0; } catch any { text = sender().run_with_users_perms(obj, 'text); } with handler { sender().tell("You cannot edit " + what + "."); sender().tell("Error: " + traceback()[1][2]); return 0; } sender().tell("Now editing " + what + "."); // user doing editing, obj edited, text, current line number, changes made return #[['user, sender()], ['obj, obj], ['text, text], ['cur_line, 1], ['changed, 0]]; . public help_msg var msg; msg = []; msg = msg + ["The note editor allows you to write on notes interactively."]; msg = msg + ["It includes these commands it inherits from the generic editor:"]; msg = msg + pass(); msg = msg + [""]; msg = msg + ["And adds the following:"]; msg = msg + [" save store text to note"]; msg = msg + [""]; return msg; . public save_cmd arg editing, cmd; var error; (> .perms(sender(), 'this) <); catch any { editing['user].run_with_users_perms(editing['obj], 'erase_cmd, "", "all", "", ""); editing['user].run_with_users_perms(editing['obj], 'add_text, editing['text], $user); editing['user].tell("Done."); // clear modified flag editing = editing.replace('changed, 0); } with handler { editing['user].tell("An error occurred attempting to save."); editing['user].tell("The error was " + traceback()[1][2]); } return editing; . parent $in_location object $lost_and_found var $root objname 'lost_and_found var $root created_on 806811775 var $root inited 1 var $root flags ['parameters, 'methods, 'code, 'core] var $has_commands shortcuts #[] var $has_commands remote #[] var $has_commands local #[] var $command_cache shortcut_cache 0 var $command_cache remote_cache 0 var $command_cache local_cache 0 var $named name ['prop, "Lost and Found box", "Lost and Found box"] var $named name_aliases [] var $gendered gender $gender_neuter var $messaged verbs #[] var $described prose [] var $location contents [] var $located location $void var $located obvious 1 var $thing lock <$object_lock_frob, [$void]> parent $cml2_format object $cml2_telnet_format var $root objname 'cml2_telnet_format var $root created_on 806313932 var $root inited 1 var $root flags ['parameters, 'methods, 'code, 'core] public init return #[['indent, 0]]; . public do_ul arg vars, flags, args; var ret, out, header, iline, line, token; vars = vars.add('indent, vars['indent] + 1); iline = " ".repeat(vars['indent] + 1); // + "* "; line = iline; out = "\\n\\n"; while (args) { token = args[1]; args = args.subrange(2); switch (type(token)) { case 'frob: switch (class(token)) { case $ctext_format: switch (token.name()) { case "lh": ret = ._eval_ctext(vars, token.args()); out = out + ret[1]; vars = ret[2]; case "li": ret = ._eval_ctext(vars, token.args()); out = out + iline + ret[1] + "\\n"; vars = ret[2]; } case $ctext_generator: ret = vars['evaluator]._eval_ctext(vars, token); args = [@ret[1], @args]; vars = ret[2]; } } } vars = vars.add('indent, vars['indent] - 1); out = out + "\\n"; return [out, vars]; . public do_strong arg vars, flags, args; var out, ret, a; ret = ._eval_ctext(vars, args); return [ret[1].uppercase(), ret[2]]; . public do_dl arg vars, flags, args; var out, indent, ret, token; indent = vars['indent]; vars = vars.add('indent, indent = 1); vars = vars.add('compact, (| flags["compact"] |) || 0); out = "\\n"; for token in (args) { if (type(token) == 'frob && class(token) == $ctext_format && token.name() in ["dl", "lh", "dd", "dt"]) { ret = ._eval_ctext(vars, token); out = out + ret[1]; vars = ret[2]; } } vars = vars.add('indent, indent); return [out + "\\n", vars]; . public do_anchor arg vars, flags, args; var ret; ret = ._eval_ctext(vars, [args[1]]); return [["/" + ret[1][1] + "/"], ret[2]]; . public do_p arg vars, args, flags; return ["\\n\\n", vars]; . public do_em arg vars, flags, args; var out, ret, a; ret = ._eval_ctext(vars, args); return [ret[1].uppercase(), ret[2]]; . public do_br arg vars, args, flags; return ["\\n", vars]; . public do_bold arg vars, flags, args; var out, ret, a; ret = ._eval_ctext(vars, args); return [ret[1].uppercase(), ret[2]]; . public do_link arg vars, flags, args; var ret; ret = ._eval_ctext(vars, [args[1]]); return ["/" + ret[1] + "/", ret[2]]; . public do_web arg vars, flags, args; var ret; ret = ._eval_ctext(vars, [args[1]]); return [ret[1] + "<" + flags["name"] + ": " + flags["src"] + ">", ret[2]]; . public do_hr arg vars, flags, args; return ["\\n---\\n", vars]; . public do_tt arg vars, flags, args; var out, ret, a; ret = ._eval_ctext(vars, args); args = ret[1]; vars = ret[2]; return ["`" + args + "`", vars]; . public do_action arg vars, flags, args; var ret; ret = ._eval_ctext(vars, args[1]); (| vars['receiver].register_action(ret[1], vars['this], flags["token"]) |); return ["\\" + ret[1] + "\\", ret[2]]; . public do_subj arg vars, flags, args; var out, ret, word, l; ret = ._eval_ctext(vars, args); out = ret[1]; switch (toint((| flags["level"] |) || "4")) { case 1: out = "\\n" + out.uppercase() + "".pad(out.length(), "=") + "\\n"; case 2: out = "\\n\\n" + out + "\\n" + "".pad(out.length(), "-"); default: out = "\\n" + out; } return [out, ret[2]]; . public do_dd arg vars, flags, args; var ret; vars = vars.add('indent, vars['indent] + 1); ret = ._eval_ctext(vars, args); vars = vars.add('indent, vars['indent] - 1); if (vars['compact]) return [ret[1], vars]; else return [ret[1].wrap_line(74, " ", 1) + "\\n", vars]; . public do_b arg vars, flags, args; var out, ret, a; ret = ._eval_ctext(vars, args); args = ret[1]; vars = ret[2]; out = []; for a in (args) out = [@out, a.uppercase()]; return [out, vars]; // 8-23-95/17:04 Jeff ($jeff), moved from $cml2_telnet_format.do_bold . public do_i arg vars, flags, args; var out, ret, a; ret = ._eval_ctext(vars, args); args = ret[1]; vars = ret[2]; out = []; for a in (args) out = [@out, a.uppercase()]; return [out, vars]; // 8-23-95/17:04 Jeff ($jeff), moved from $cml2_telnet_format.do_em . public do_dt arg vars, flags, args; var ret, term; term = " ".repeat(vars['indent]); ret = ._eval_ctext(vars, args); if (vars['compact]) return ["\\n" + (term + ret[1]).pad(25), ret[2]]; else return ["\\n" + term + ret[1] + "\\n", ret[2]]; . public do_li arg vars, flags, args; var line, ret; line = [" ".repeat(vars['indent] + 1) + "* "]; ret = ._eval_ctext(vars, args); return [[@line.join(@ret[1]), ""], ret[2]]; . parent $cml2_format object $cml2_html_format var $root objname 'cml2_html_format var $root created_on 811463041 var $root inited 1 var $root flags ['parameters, 'methods, 'code, 'core] public do_hr arg vars, flags, args; return ["\\n<hr>\\n", vars]; . public do_ul arg vars, flags, args; var ret, out, header, line, token; ret = ._eval_ctext(vars, args); return ["\\n<ul>\\n" + ret[1] + "\\n</ul>\\n", ret[2]]; . public do_strong arg vars, flags, args; var out, ret, a; ret = ._eval_ctext(vars, args); return ["<strong>" + ret[1] + "</strong>", ret[2]]; . public do_dl arg vars, flags, args; var out, ret, token; vars = vars.add('compact, (| flags["compact"] |) || 0); if ((| flags["compact"] |)) out = "\\n<dl compact>"; else out = "\\n<dl>"; for token in (args) { if (type(token) == 'frob && class(token) == $ctext_format && token.name() in ["dl", "lh", "dd", "dt"]) { ret = ._eval_ctext(vars, token); out = out + ret[1]; vars = ret[2]; } } return [out + "\\n</dl>", vars]; . public do_anchor arg vars, flags, args; var ret; ret = ._eval_ctext(vars, [args[1]]); return [["/" + ret[1][1] + "/"], ret[2]]; . public do_p arg vars, args, flags; return ["\\n<p>\\n", vars]; . public do_em arg vars, flags, args; var out, ret, a; ret = ._eval_ctext(vars, args); return [ret[1].uppercase(), ret[2]]; . public do_br arg vars, args, flags; return ["\\n<br>", vars]; . public do_bold arg vars, flags, args; var out, ret, a; ret = ._eval_ctext(vars, args); return [ret[1].uppercase(), ret[2]]; . public do_link arg vars, flags, args; var ret, node; ret = ._eval_ctext(vars, [args[1]]); node = (| flags["node"] |); if (node) return ["<a href=\"/bin/help?" + node + "\">" + ret[1] + "</a>", ret[2]]; return [">>ERROR: Invalid node<<", ret[2]]; . public do_web arg vars, flags, args; var ret; ret = ._eval_ctext(vars, [args[1]]); return [ret[1] + "<a href=\"" + flags["src"] + "\">" + flags["name"] + "</a>", ret[2]]; . public do_tt arg vars, flags, args; var out, ret, a; ret = ._eval_ctext(vars, args); args = ret[1]; vars = ret[2]; return ["<tt>`" + args + "`</tt>", vars]; . public do_action arg vars, flags, args; var ret; ret = ._eval_ctext(vars, args[1]); (| vars['receiver].register_action(ret[1], vars['this], flags["token"]) |); return ["\\" + ret[1] + "\\", ret[2]]; . public do_subj arg vars, flags, args; var out, ret, word, l; ret = ._eval_ctext(vars, args); // our levels are kindof different from html's levels, so shift them l = tostr(abs(toint((| flags["level"] |) || 2)) || 1); return ["<h" + l + ">" + ret[1] + "</h" + l + ">\\n", ret[2]]; . public do_dd arg vars, flags, args; var ret; ret = ._eval_ctext(vars, args); return ["<dd>" + ret[1], vars]; . public do_b arg vars, flags, args; var out, ret, a; ret = ._eval_ctext(vars, args); return ["<b>" + ret[1] + "</b>", ret[2]]; . public do_i arg vars, flags, args; var out, ret, a; ret = ._eval_ctext(vars, args); return ["<i>" + ret[1] + "</i>", ret[2]]; . public do_dt arg vars, flags, args; var ret, term; ret = ._eval_ctext(vars, args); return ["\\n<dt>" + ret[1], ret[2]]; . public do_li arg vars, flags, args; var ret; ret = ._eval_ctext(vars, args); return ["<li>" + ret[1], ret[2]]; . parent $root_evaluator object $compile_evaluator var $root fertile 1 var $root manager $control var $root inited 1 var $root objname 'compile_evaluator var $root created_on 796268969 var $root flags ['parameters, 'methods, 'code, 'fertile, 'core] public compile_cml arg text; var output, char, mode, vars; //Turn the given text into the ctext format. if (type(text) == 'list) text = text.to_string("").onespace(); if (type(text) != 'string) throw(~type, "Text should be a string."); text = text + "\""; if (text[1] == "\"") text = text.subrange(1); vars = #[['this, sender()]]; vars = .parse_string(vars, text); return vars; . public parse_string arg vars, text; var output, word, is_text, token, ret_val; output = []; word = ""; is_text = 0; while (text) { ret_val = text.split_on_next(["\"", "{", "%", "&"]); word = ret_val[1]; token = ret_val[2]; text = ret_val[3]; switch (token) { case "{": output = ._handle_word(output, word); vars = .parse_command(vars, text); output = [@output, vars['result]]; text = vars['text]; is_text = 1; case "%": output = ._handle_word(output, word); vars = .parse_varref(vars, text); output = [@output, vars['result]]; text = vars['text]; is_text = 1; case "&": output = ._handle_word(output, word); vars = .parse_charref(vars, text); output = [@output, vars['result]]; text = vars['text]; is_text = 1; case "\"": output = ._handle_word(output, word); if (is_text) { vars = .text_stmt(vars, output); output = vars['result]; } if (output.length() == 1) output = output[1]; vars = vars.add('text, text); return vars.add('result, output); } } vars = vars.add('text, text); return vars.add('result, output); . public parse_command arg vars, text; var output, ret_val, term, word, final, first_term, final_args, token; output = []; term = []; word = ""; while (text) { ret_val = text.split_on_next(["\"", "{", "%", "&", "[", " ", "}"]); word = ret_val[1]; token = ret_val[2]; text = ret_val[3]; switch (token) { case "{": output = ._handle_word(output, term); vars = .parse_command(vars, text); output = [@output, vars['result]]; text = vars['text]; case "[": output = ._handle_word(output, term); vars = .parse_list(vars, text); output = [@output, vars['result]]; text = vars['text]; case "%": output = ._handle_word(output, term); vars = .parse_varref(vars, text); output = [@output, vars['result]]; text = vars['text]; case "\"": output = ._handle_word(output, term); vars = .parse_string(vars, text); output = [@output, vars['result]]; text = vars['text]; case " ": if (word == "pre" && !output) { ret_val = ")" in text; output = [['string_type, "pre"], ['string_type, text.subrange(1, ret_val - 1)]]; text = text.subrange(ret_val); } else { output = ._handle_word(output, word); } case "}": output = ._handle_word(output, word); // if (type(output[1]) != 'list) // output = [output]; first_term = output[1]; if (first_term[1] == 'string_type) { first_term = tosym(first_term[2] + "_stmt"); final_args = output.subrange(2); catch ~methodnf { vars = .(first_term)(vars, final_args); } with handler { vars = vars.add('result, [first_term, final_args]); } } else if (type(first_term[1]) == 'symbol) { final_args = [@first_term[2], @output.subrange(2)]; first_term = first_term[1]; vars = vars.add('result, [first_term, final_args]); } else { first_term = 'eval_stmt; final_args = [first_term]; vars = vars.add('result, [first_term, final_args]); } vars = vars.add('text, text); return vars; } } vars = vars.add('text, ""); return vars.add('result, ['string_type, "unended command"]); . public parse_charref arg vars, text; var pos; pos = ";" in text; vars = vars.add('text, text.subrange(pos + 1)); text = text.subrange(1, pos - 1); switch (text) { case "lp": text = "("; case "amp": text = "&"; case "quote": text = "\""; case "per": text = "%"; case "lb": text = "{"; case "rb": text = "}"; case "tick": text = "'"; default: text = ">>ERROR: Unknown character " + text + "<<"; } return vars.add('result, ['string_type, text]); . public parse_varref arg vars, text; var output, ret_val, word, token; output = []; word = ""; while (text) { ret_val = text.split_on_next(["{", "%", "&", ";"]); word = ret_val[1]; token = ret_val[2]; text = ret_val[3]; switch (token) { case "{": output = ._handle_word(output, word); ret_val = .parse_command(vars, text); output = [@output, vars['result]]; text = vars['text]; case "%": output = ._handle_word(output, word); ret_val = .parse_varref(vars, text); output = [@output, vars['result]]; text = vars['text]; case "&": output = ._handle_word(output, word); ret_val = .parse_charref(vars, text); output = [@output, vars['result]]; text = vars['result]; case ";": output = ._handle_word(output, word); vars = vars.add('text, text); return vars.add('result, ['get_stmt, output]); } } . public parse_list arg vars, text; var output, term, word, token, int, ret_val; output = []; term = []; word = ""; while (text) { ret_val = text.split_on_next(["[", "]", "{", "\"", "%", "&", " "]); word = ret_val[1]; token = ret_val[2]; text = ret_val[3]; switch (token) { case "{": output = ._handle_word(output, word); vars = .parse_command(vars, text); output = [@output, vars['result]]; text = vars['text]; case "[": output = ._handle_word(output, word); vars = .parse_list(vars, text); output = [@output, vars['result]]; text = vars['text]; case "%": output = ._handle_word(output, word); vars = .parse_varref(vars, text); output = [@output, vars['result]]; text = vars['text]; case "\"": output = ._handle_word(output, word); vars = .parse_string(vars, text); output = [@output, vars['text]]; text = vars['text]; case " ": output = ._handle_word(output, word); case "]": output = ['list_type, ._handle_word(output, word)]; vars = vars.add('text, text); return vars.add('result, output); } } . public _handle_word arg output, word; if (word) { if (type(word) == 'string) { if (word.is_numeric()) { word = ['integer_type, toint(word)]; } else if (word[1] == "$") { if (" " in word) word = ['string_type, word]; else word = ['dbref_type, $object_lib.to_dbref(word)]; } else if (word[1] == "'") { word = ['symbol_type, tosym(word)]; } else { word = ['string_type, word]; } } output = [@output, word]; } return output; . public char_type arg vars, args; if (args[1] != 'string_type) return ['string_type, ">>ERROR: Character must be a constant string."]; switch (args) { case "lp": return ['string_type, "("]; case "amp": return [string_type, "&"]; case "quote": return ['string_type, "\""]; case "per": return ['string_type, "%"]; default: return ['string_type, ">>ERROR: Unknown character " + args + "<<"]; } . public text_stmt arg vars, args; var last, output, term, first; output = []; for term in (args) { if (output) { last = output.last(); if (term[1] == 'string_type && last[1] == 'string_type) { term = ['string_type, last[2] + term[2]]; output = output.chop(); } } output = [@output, term]; } if (output.length() == 1) { first = output[1]; if (first[1] == 'string_type) return vars.add('result, first); } return vars.add('result, ['text_stmt, output]); . public action_stmt arg vars, args; return vars.add('result, ['action_stmt, [vars['this], @args]]); .