[...]

 

generic detailed room, $detailed_room

$detailed_room.autoexit
$detailed_room.listen_description
$detailed_room.smell_description
$detailed_room.feel_description
$detailed_room.taste_description
$detailed_room:"listen_self smell_self feel_self taste_self"
$detailed_room:look_self
$detailed_room:autoexits
$detailed_room:tell_contents
$detailed_room:here_huh

@create $room called "generic detailed room",detailed_room @chmod $detailed_room +rf @prop $detailed_room.autoexit 1 @prop $detailed_room.listen_description @prop $detailed_room.smell_description @prop $detailed_room.feel_description @prop $detailed_room.taste_description @verb $detailed_room:"listen_self smell_self feel_self taste_self" tnt @program $detailed_room:listen_self desc = this.(verb[1..$-5] + "_description"); if (verb == "listen_self") report = "hear"; elseif (verb == "smell_self") report = "smell"; elseif (verb == "feel_self") report = "feel"; else report = "taste"; endif if (desc) player:tell(desc); else player:tell("You ", report, " nothing special."); endif . @verb $detailed_room:look_self tnt @program $detailed_room:look_self {?brief = 0} = args; player:tell(); player:tell(this:title()); if (!brief) desc = this:description(); if (desc) player:tell_lines(desc); else player:tell("You see nothing special."); endif endif if(this.autoexit && player.autoexit) player:tell(this:autoexits()); endif this:tell_contents(setremove(this:contents(), player), this.ctype); . @verb $detailed_room:autoexits tnt @program $detailed_room:autoexits exits = this:obvious_exits(); elist = " Exits: "; if (exits) for n in (exits) if ($object_utils:isa(n, $exit)) exname = "`2y" + n.name + "`00"; elseif ($object_utils:isa(n, $two_way)) index = this in n.exits == 1 ? 1 | 2; exname = "`2y" + n._aliases[index][1] + "`00"; else exname = "`1rbad exit type (" + n + ")`00"; endif if ($object_utils:has_property(n, "is_door") && n.is_door && n.is_closed) exname = "`1x[`2y" + exname + "`1x]`00"; endif if (n == exits[$]) elist = elist + exname + "."; else elist = elist + exname + ", "; endif endfor else elist = elist + "`2wnone`00."; endif return elist; . @verb $detailed_room:here_huh tnt rxd @program $detailed_room:here_huh if ((verb = args[1]) in {"open", "close", "lock", "unlock"}) exit = this:match_exit((target = args[2][1])); if ($recycler:valid(exit) && ($object_utils:has_callable_verb(exit, verb))) exit:(verb)(); return 1; endif return 0; endif return pass(@args); . @verb $detailed_room:@exits none none none rd @program $detailed_room:@exits if (!$perm_utils:controls(valid(caller_perms()) ? caller_perms() | player, this)) player:tell("Sorry, only the owner of a room may list its exits."); elseif (this.exits == {}) player:tell("This room has no conventional exits."); else try for exit in (this.exits) try player:tell(exit:title(), " (", exit, ") leads to ", valid(exit.dest) ? exit.dest:title() | "???", " (", exit.dest, ") via {", $string_utils:from_list(exit.aliases, ", "), "}."); except (ANY) player:tell("Bad exit or missing .dest property: ", $string_utils:nn(exit)); continue exit; endtry endfor except (E_TYPE) player:tell("Bad .exits property. This should be a list of exit objects. Please fix this."); endtry endif . @verb detailed_room:tell_contents tnt @program $detailed_room:tell_contents {contents, ctype} = args; if(!this.dark && contents != {} && ctype == 4) players = things = {}; for x in (contents) if(is_player(x)) players = {@players, x}; else things = {@things, x}; endif endfor if(!this.integrate) for t in (things) if($object_utils:has_readable_property(t, "look_msg")) player:tell($string_utils:pronoun_sub(t.look_msg, player, t, this)); else player:tell("You see ", t:title(), " here."); endif endfor endif for p in (players) player:tell($string_utils:pronoun_sub(tostr("%N ", $gender_utils:get_conj("is", p), " here."), p)); endfor else pass(@args); endif . @verb detailed_room:match_detail tnt @program $detailed_room:match_detail {alias, ?senses = {"look", "listen", "smell", "touch", "taste"}} = args; senses = typeof(senses) == LIST ? senses | {senses}; match = $failed_match; r = {}; for sense in (senses) senseprop = sense + "_details"; for x in (`this.(senseprop) ! E_PROPNF => {}') if (alias in x[1]) r = {@r, {sense, x in this.(senseprop)}}; if (match == $failed_match) match = x in this.(senseprop); else match = $ambiguous_match; endif endif endfor endfor if (match != $failed_match) return {match, r}; endif "checking for partial matches"; for sense in (senses) senseprop = sense + "_details"; for x in (`this.(senseprop) ! E_PROPNF => {}') for y in (x[1]) if (index(y, alias) != 1) elseif (match == $failed_match) r = {@r, {sense, x in this.(senseprop)}}; match = x in this.(senseprop); else r = {@r, {sense, x in this.(senseprop)}}; match = $ambiguous_match; endif endfor endfor endfor return {match, r}; . @verb $detailed_room:display_detail tnt @program $detailed_room:display_detail {alias, sense} = args; senseprop = sense + "_details"; {match, r} = this:match_detail(alias, sense); if (match == $failed_match || match == $ambiguous_match) return match; endif player:tell_lines(this.(senseprop)[r[1][2]][2]); return 1; . @prop $detailed_room.look_details {} @prop $detailed_room.listen_details {} @prop $detailed_room.smell_details {} @prop $detailed_room.touch_details {} @prop $detailed_room.taste_details {} @verb $detailed_room:@de*tail any any any @program $detailed_room:@detail desc = `args[4..$] ! E_RANGE => iobjstr'; if (!$perm_utils:controls(player, this)) player:tell("You don't have the permissions for that."); return E_PERM; endif "this manual unfolding is so we can properly handle the cases where 1) the alias has quoted spaces and 2) the alias is a preposition. args knows what's up, but :explode/:words fails in the first case and dobjstr fails in the second."; sense = args[1]; if (args[2] != "as" || `args[3] == "as" ! E_RANGE => 0') aliaslist = args[2]; else aliaslist = ""; endif if (!sense || (j = !(sense in {"look", "listen", "touch", "taste", "smell"})) || !aliaslist) if(!aliaslist && !j) msg = "If you want to set the room description, use @describe or @edit."; else msg = ""; endif this:here_explain_syntax(caller, verb, args, msg); return; endif aliaslist = $string_utils:explode(aliaslist, ","); dups = {}; for a in (aliaslist) {m, r} = this:match_detail(a, sense); if (m != $failed_match) dups = {@dups, a}; endif endfor if (length(dups)) player:tell("The keyword", length(dups) == 1 ? " " | "s ", $string_utils:english_list(dups), length(dups) == 1 ? " is" | " are", " already in use with that sense."); return E_PERM; endif this.(sense+"_details") = {@this.(sense+"_details"), {aliaslist, desc}}; player:tell("Detail for ", sense, " with alias", length(aliaslist) == 1 ? " " | "es ", "\"", $string_utils:english_list(aliaslist), "\" created in ", this:title(), " (", this, ")." ); . @verb $detailed_room:@rmde*tail any any any @program $detailed_room:@rmdetail if (prepstr && !(prepstr in {"for", "from"})) "ack, detail w/ the name of a preposition"; match = prepstr == "for" ? "for" | "from"; if (i = match in args) alias = `$string_utils:from_list(args[1..i-1], " ") ! E_RANGE => ""'; sense = `$string_utils:from_list(args[i+1..$], " ") ! E_RANGE => ""'; else alias = argstr; sense = ""; endif elseif (prepstr == "for" || prepstr == "from") alias = dobjstr; sense = iobjstr; else alias = dobjstr; sense = ""; endif player:tell_lines({toliteral(args), alias, sense}); if (!$perm_utils:controls(player, this)) player:tell("You don't have the permissions for that."); return E_PERM; elseif (!alias) player:tell("Remove which detail?"); return; elseif (!sense) player:tell("Since you didn't specify, I'm assuming you mean all details called \"", alias, "\", no matter the sense."); sense = {"look", "listen", "smell", "touch", "taste"}; else if (!(sense in {"sight", "sound", "touch", "taste", "smell"})) this:here_explain_syntax(caller, verb, args); return; endif if (sense == "sight") sense = "look"; elseif (sense == "sound") sense = "listen"; endif endif {match, r} = this:match_detail(alias, sense); if (match == $failed_match) player:tell("There's no detail called \"", alias, "\" to remove."); return; endif for i in (r) senseprop = i[1] + "_details"; aliaslist = this.(senseprop)[i[2]][1]; this.(senseprop) = setremove(this.(senseprop), this.(senseprop)[i[2]]); player:tell("Detail for ", i[1], " with alias", length(aliaslist) == 1 ? " " | "es ", "\"", $string_utils:english_list(aliaslist), "\" has been removed from ", this:title(), " (", this, ")."); endfor . @verb $detailed_room:here_explain_syntax tnt @program $detailed_room:here_explain_syntax {caller, verb, vargs, ?msg="", @args} = args; r = 0; if ($code_utils:verbname_match("@rmde*tail", verb)) player:tell_lines({ "Syntax: @rmdetail [from/for ].", " Where is one of: sight sound touch taste smell."}); r = 1; elseif ($code_utils:verbname_match("@details", verb)) elseif ($code_utils:verbname_match("@de*tail", verb)) player:tell_lines({ "Syntax: @detail as \"\".", " Where is one of: look listen touch taste smell."}); r = 1; endif if(msg) if(r == 1) msg = $string_utils:space(9, " ") + msg; endif player:tell(msg); r = 1; endif return r; . @verb $detailed_room:@details none none none @program $detailed_room:@details if (!$perm_utils:controls(valid(caller_perms()) ? caller_perms() | player, this)) player:tell("Sorry, only the owner of a room may list its details."); return E_PERM; endif output = 0; limit = `player:linelen() ! ANY => 79'; for sense in ({"look", "listen", "taste", "smell", "touch"}) for detail in (this.(sense+"_details")) start = $ansi_utils:slice(tostr(" ", sense, ": \"", typeof(detail[2]) == LIST ? detail[2][1] | detail[2], "\""), limit); if($ansi_utils:length(start) == limit) start = start[1..$-4] + "...`00\""; endif player:tell_lines({tostr($string_utils:english_list(detail[1]), ": "), start}); output = output + 1; endfor endfor if (output == 0) player:tell("This room has no details."); endif . @prop $detailed_room.echo_to {} @prop $detailed_room.estart_msg "Elsewhere, " @prop $detailed_room.eend_msg "" @verb $detailed_room:"announce announce_all announce_all_but" tnt @program $detailed_room:announce pass(@args); if(verb == "announce_all_but") {ignore, @text} = args; else ignore = {}; {@text} = args; endif try for target in (this.echo_to) if (valid(target) && target:is_unlocked_for(this)) try if ($object_utils:isa(target, $detailed_room) || $object_utils:isa(target, $echo_room)) target:announce_noecho(ignore, this:estart(), @text, this:eend()); elseif ($object_utils:isa(target, #155)) target:announce_all_e(this:estart(), @text, this:eend()); else target:announce(this:estart(), @text, this:eend()); endif except (ANY) continue target; endtry endif endfor except (E_TYPE) this.owner:tell(this.name, " `00has a bad .echo_to property. It should be a list of rooms. Please fix this."); endtry . @verb $detailed_room:announce_noecho tnt @program $detailed_room:announce_noecho ":announce_noecho(LIST of targets to ignore, @text)"; ""; "This is $room:announce_all_but, but called to replace all :announce* verbs when dealing with an echo from another room, so we don't get infinitely bouncing echos."; {ignore, @text} = args; contents = this:contents(); for l in (ignore) contents = setremove(contents, l); endfor for listener in (contents) try listener:tell(@text); except (ANY) "Ignore listener with bad :tell"; continue listener; endtry endfor . @verb $detailed_room:"estart eend" tnt rxd @program $detailed_room:estart return this.(verb+"_msg"); . "@prop detail.help_msg "" "@edit detail.help_msg "A detailed room is like a room, only better! " "It's got capacities for the following alternative behaviours: " - automatic listing of exits, if .autoexits is on " - unique descriptions of objects in room, if applicable (and .ctype = 4) <-- but it is very bad " - details. use @detail or @rmdetail to add/remove details to rooms you own. The details will be visible on a "look ", and are a way to create extra depth in a room without having everything you can look at be a seperate object. Use @details to see all the details on a room (but only if you're the owner) " - echoes. set .echo_to to a list of rooms that will hear what happens in the room. set .estart_msg and .end_msg to alter how the message is displayed. " " (also, the l*ook code catches stuff like "look at foo on bar", which it doesn't normally) "save "done "ideally will handle integration, later on.