new object $thing_frob: $frob, $thing; var $described prose = []; var $has_name name = ['uniq, "Thing Frob", "the Thing Frob"]; var $located location = $void; var $located obvious = 1; var $root created_on = 796268969; var $root fertile = 1; var $root flags = ['methods, 'code, 'fertile, 'variables, 'core, 'frob]; var $root inited = 1; var $root managed = [$thing_frob]; var $root manager = $thing_frob; var $thing gender = $gender_neuter; frob method .add_name_template() { arg this, template; var new; new = setadd(.name_templates(this), template); return .change_data(this, 'name_templates, new); }; frob method .all_defined_settings(): nooverride { arg this; (> .perms(this, sender()) <); return ._all_defined_settings(); }; frob method .all_local_commands() { arg this; return pass(); }; frob method .all_msgs(): nooverride { arg this; if (dict_contains(this, 'msgs)) return pass(this['msgs]); return pass(); }; frob method .all_remote_commands() { arg this; return pass(); }; frob method .all_shortcuts() { arg this; return pass(); }; private method .change_data() { arg this, what, new, @remove; if (valid(this['location])) (this['location]).del_frob_from_contents((<this(), this>)); if (remove) this = this.del(what); else this = this.add(what, new); if (valid(this['location])) (this['location]).add_frob_to_contents((<this(), this>)); return (<this(), this>); }; frob method .clear_msg(): nooverride { arg this, name, @branches; var messages, branch, msg; (caller() != definer()) && (> .perms(this, sender()) <); if (dict_contains(this, 'msgs)) messages = this['msgs]; else messages = #[]; if (!dict_contains(messages, name)) return; if (!branches) { messages = dict_del(messages, name); } else { msg = messages[name]; for branch in (branches) { if (dict_contains(msg, branch)) msg = dict_del(msg, branch); } if (!msg) messages = dict_del(messages, name); } if (!messages) return .change_data(this, 'msgs, 0, 'remove); else return .change_data(this, 'msgs, messages); }; frob method .clear_setting(): nooverride { arg this, name, definer; var info, args, settings; (caller() == definer()) || (> .perms(this, sender()) <); info = (> definer.setting_info(name) <); if (dict_contains(info, 'clear)) { args = sublist(info['clear], 2); return (> .((info['clear])[1])(this, name) <); } else if (dict_contains(this, 'settings) && dict_contains(this['settings], name)) { settings = dict_del(settings, name); if (!settings) return .change_data(this, 'settings, 0, 'remove); else return .change_data(this, 'settings, settings); } }; frob method .configure() { arg this, set; var p, end, ctext, s, still, type; (> .perms(this, sender()) <); s = sender(); still = ("Do you still want to describe " + (.name(this))) + "? [no] "; if (!(set.contains('described_prose))) { while (!end) { if (.is(this, $exit)) type = "exit "; else type = ""; p = s.read((("Describe " + type) + (.name(this))) + ", Enter \".\" to finish or \"@abort\" to abort description."); if (p == 'aborted) { end = !(s.prompt_yesno(still, 0)); } else { catch any { ctext = (> $compiler.compile_cml(p) <); s.tell(["You submitted the following description:", ""]); s.tell(ctext); s.tell(""); if (!(end = s.prompt_yesno("Keep this description? [yes] "))) ctext = 0; } with { s.tell(["The following CML compiler error occurred:", " ", (traceback()[1])[2]]); end = !(s.prompt_yesno(still, 0)); } } } if (ctext) this = (.set_prose(this, ctext)).value(); set = set.add('described_prose, 1); } return [this, set]; }; frob method .del_name_template() { arg this, template; var new; new = setremove(.name_templates(this), template); return .change_data(this, 'name_templates, new); }; frob method .description() { arg this, flags; var out; out = (<$ctext_frob, [[(<$format, ["subj", [], [.name(this)], 'do_subj]>)], #[]]>); if ((| flags['prose] |)) return [out, .prose(this)]; return [out]; }; frob method .did_move() { arg this; return (<this(), this>); }; frob method .discard() { arg data; //// just allow anybody to discard for now.. // if (data['manager] != sender()) // throw(~perm, "You are not the manager of " + .name(data)); (data['location]).del_frob_from_contents((<this(), data>)); }; frob method .eval_message() { arg this, name, definer, vars; var eval, msg; eval = (| definer.get_msg_attr(name, 'evaluator) |) || $bs_eval; msg = $message_frob.new_with(.get_msg(this, name, definer)); vars = dict_add(vars, 'evaluator, eval); msg = msg.set_vars(vars); vars = dict_add(vars, 'time, 'pre); return msg.eval_ctext(vars); }; frob method .format_setting(): nooverride { arg this, name, definer, value; var i, args; return pass(name, definer, value); }; frob method .get_command_info() { arg this, @args; return pass(@args); }; frob method .get_description(): nooverride { arg this, @dflags; var flags, f; flags = #[['prose, 1], ['actor, sender()]]; if (dflags && (type(dflags[1]) == 'dictionary)) { dflags = dflags[1]; for f in (dflags.keys()) flags = dict_add(flags, f, dflags[f]); } return .description(this, flags); }; frob method .get_lock() { arg this, name, definer; return (| this['lock] |) || (<$true_lock_frob, []>); }; frob method .get_msg(): nooverride { arg this, name, definer; return dict_union(definer.get_default_msg(name), (| (this['msgs])[name] |) || #[]); }; frob method .get_setting(): nooverride { arg this, name, definer; var i, settings; i = definer.setting_info(name); if (dict_contains(i, 'access)) (> .((i['access])[1])(this, name, sender(), caller(), @sublist(i['access], 2.0)) <); if (dict_contains(i, 'get)) return (> .((i['get])[1])(this, name, definer, @sublist(i['get], 2)) <); if ((!dict_contains(this, 'settings)) || (!dict_contains(this['settings], name))) return (> pass(name, definer) <); return (this['settings])[name]; }; frob method .is_obvious_to() { arg this, whom; return 1; }; frob method .local_commands() { arg this; return pass(); }; frob method .location() { arg this; return (| this['location] |) || $nowhere; }; frob method .manager() { arg this; return this['manager]; }; frob method .match_name() { arg this, str; var t, m; if ((m = match_begin((this['name])[2], str))) return 1; if (this.contains('name_templates)) { for t in (this['name_templates]) { if ((m = match_template(str, t))) return 1; } } return 0; }; frob method .move_to() { arg data, place; var location; if (!(place.has_ancestor($location))) throw(~type, "Argument is not a location."); location = data['location]; if (!valid(location)) location = $nowhere; (> .will_move(data, sender(), place) <); return .change_data(data, 'location, place); }; frob method .msg_definer(): nooverride { arg this, name; return pass(name); }; frob method .name() { arg dict, @args; var name; name = dict['name]; if (!name) return tostr(this()); if (!args) return name[3]; switch (args[1]) { case 'type: return name[1]; case 'noarticle: return name[2]; default: return name; } }; frob method .name_templates() { arg this; return (| this['name_templates] |) || []; }; frob method .namef() { arg dict, @args; return .name(dict); }; public method .new() { var location; if (sender().is($location)) location = sender(); else if (sender().is($located)) location = sender().location(); else location = $nowhere; return (<this(), #[['prose, []], ['location, location], ['manager, sender()], ['name, .name('literal)]]>); }; public method .new_with() { arg @args; var name, prose, data, new; name = (listlen(args) > 0) && (args[1]); prose = (listlen(args) > 1) && (args[2]); new = .new(); if (prose) new = new.set_prose(prose); if (name) new = new.set_name(name); return new; }; frob method .perms() { arg this, what, @args; return (what == (this['manager])) || (> (this['location]).perms(what, @args) <); }; frob method .prose() { arg this, @no_default; return (| this['prose] |) || (no_default ? 0 : "You see nothing special"); }; frob method .remote_commands() { arg this; return pass(); }; frob method .set_gender(): nooverride { arg name, definer, value; throw(~perm, "You cannot set the gender on frobs, sorry."); }; frob method .set_lock() { arg this, name, definer, value; if (class(value) == $true_lock_frob) return .change_data(this, 'lock, 0, 'remove); else return .change_data(this, 'lock, value); }; frob method .set_msg(): nooverride { arg this, name, branch, definer, value; var compiler, branches, msg, definer, msgs; (> .perms(this, sender()) <); compiler = (| definer.get_msg_attr(name, 'compiler) |) || $compiler; value = (> compiler.compile_cml(value) <); branch ?= "general"; if (!(branch in (definer.get_msg_attr(name, 'branches)))) throw(~badbranch, ((("Message branch \"" + name) + ".") + branch) + "\" is not defined."); if (dict_contains(this, 'msgs)) msgs = this['msgs]; else msgs = #[]; msg = dict_add((| msgs[name] |) || #[], branch, value); msgs = dict_add(msgs, name, msg); return .change_data(this, 'msgs, msgs); }; frob method .set_name() { arg this, new, @args; var type; if (!new) return; if (new && ((new[1]) in ["$", "#"])) throw(~invname, "Names cannot begin with \"$\" or \"#\"."); if (match_regexp(new, "^(a|an|the) +")) throw(~bad_name, "Do not include articles in name, use +u +n or +p instead."); [(type ?= 'normal)] = args; switch (type) { case 'prop: new = [type, new, new]; case 'uniq: new = [type, new, "the " + new]; case 'normal: new = [type, new, ((new.a_or_an()) + " ") + new]; default: throw(~invarg, "Type must be one of: 'prop, 'normal or 'uniq."); } return .change_data(this, 'name, new); }; frob method .set_prose() { arg this, new; return .change_data(this, 'prose, new); }; frob method .set_setting(): nooverride { arg this, name, definer, value; var i, args, settings; (> .perms(this, sender()) <); i = (> definer.setting_info(name) <); if (dict_contains(i, 'parse)) { args = sublist(i['parse], 2); catch ~methodnf value = (> .((i['parse])[1])(value, @args) <); with value = (> $settings.((i['parse])[1])(value, @args) <); } if (dict_contains(i, 'set)) { return (> .((i['set])[1])(this, name, definer, value, @sublist(i['set], 2)) <); } else { settings = dict_add((| this['settings] |) || #[], name, value); return .change_data(this, 'settings, settings); } }; frob method .set_visibility() { arg this, name, definer, value; return .change_data(this, 'visibility, value); }; frob method .setting_definer(): nooverride { arg this, name; return pass(name); }; frob method .shortcuts() { arg this; return pass(); }; public method .try_lock() { arg this, @args; return (| this['lock] |) ? ((this['lock]).try(@args)) : 1; }; frob method .visibility() { arg this, @args; return (| this['visibility] |) || 0; }; frob method .will_move() { arg this, mover, place; if (!(> .try_lock(this, mover) <)) throw(~locked, ((((.name()).capitalize()) + " is locked to ") + ((this['lock]).lock_name('thing))) + "."); return 1; }; frob method .writers(): nooverride { arg this, @literal; if (literal) return []; return [this['manager]]; };