sick features (#843)
(an instance of Generic Feature Object made by Sick )
     Sick's mostly useful programmerly features.
Go to location of this object, Sick .
HELP MANUAL:
     Nifty stuff for builders and programmers.
VERB SOURCE CODE:
@family @family-mail:
"Usage: @family[-mail] [with [branches] [! ... ]]";
"Displays indented list of ancestors and descendants/branches for the given object.";
"An optional list of objects can be given, in which case neither those objects, descendants
of those objects, nor other objects owned by those objects will be shown.";
"";
"If you use @family-mail rather than @family, the list will be MOOmailed to you rather
than spamming your screen.";
"";
"Please be careful when you use this verb. Do _not_ type `@family #1' or `@family
$thing' or anything else that is naturally going to spam you with a list of tens
of thousands of objects.";
if (!argstr)
return player:tell_lines($code_utils:verb_documentation(this, verb));
endif
if ((!valid(dobj)) && $command_utils:object_match_failed(dobj = player:my_match_object(dobjstr),
dobjstr))
return;
endif
dverbs = (dverb = "descendant") + "s";
excludes = {};
if (prepstr && iobjstr)
for s in ($string_utils:words(iobjstr))
if (index("branches", s) == 1)
dverbs = (dverb = "branch") + "es";
elseif (s[1] in {"!", "-"})
if ($command_utils:object_match_failed(o = player:my_match_object(s),
s))
return;
endif
excludes = setadd(excludes, o);
else
return player:tell("I don't understand `", s, "'.");
endif
endfor
endif
mail = index(verb, "mail") && 1;
player:tell("Compiling a list of ancestors and ", dverbs, " of ", $string_utils:nn(dobj),
excludes ? tostr(", excluding descendants of and objects owned by ", $string_utils:name_and_number_list(excludes))
| "", " ...");
if (mail)
player:tell("The list will be mailed to you when finished.");
endif
header = {tostr("Ancestors/", dverbs, " information on ", $string_utils:nn(dobj),
":")};
if (excludes)
header = {@header, tostr("Excluding descendants of and objects owned by ", $string_utils:nn_list(excludes),
".")};
endif
anum = length(atext = this:_ancestors(dobj));
dnum = length(dtext = this:("_" + dverbs)(dobj, $string_utils:space(anum * 2), excludes))
- 1;
footer = tostr("* ", anum, " ancestor", (anum == 1) ? "" | "s", ", ", dnum, " ",
(dnum == 1) ? dverb | dverbs, " found.");
text = {@header, @atext, @dtext, footer};
if (mail)
$mail_agent:send_message(this, player, tostr(verb, " ", argstr), text);
else
player:tell_lines_suspended(text);
endif
.
_ancestors:
"Syntax: _ancestors(obj [, str ]) => list";
"";
"Returns a formatted string list of ancestors for the given object.";
object = args[1];
prefix = (length(args) > 1) ? args[2] | "";
if (parents = $list_utils:reverse($object_utils:ancestors(object)))
lines = {this:object_line(parents[1], prefix)};
for p in (listdelete(parents, 1))
$command_utils:suspend_if_needed(0);
lines = {@lines, this:object_line(p, prefix = prefix + " ")};
endfor
return lines;
else
return {};
endif
.
_descendants _branches:
"Syntax: _descendants(obj [, str [, list ]]) => list";
" _branches(obj [, str [, list ]]) => list";
"";
"Returns a formatted string list of descendants/branches for the given object.";
lines = {this:object_line(object = args[1], prefix = (length(args) > 1) ? args[2]
| "")};
excludes = (length(args) > 2) ? args[3] | {};
for kid in (children(object))
$command_utils:suspend_if_needed(0);
if ((verb == "_descendants") || children(kid))
if (!(excludes && ((kid in excludes) || (kid.owner in excludes))))
lines = {@lines, @this:(verb)(kid, prefix + " ", excludes)};
endif
endif
endfor
return lines;
.
object_line:
"Syntax: object_line(obj [, str ) => str";
"";
"Takes an object and returns a string in the form:";
"";
" [][{} ] () ...: ()";
"Ex: {25} featureful programmer (#96) .......................: Sickness (#80)";
object = args[1];
prefix = {@args, ""}[2];
ownername = tostr("...: ", valid(object) ? tostr(valid(owner = object.owner) ? $list_utils:shortest(owner.aliases)
| "", " (", owner, ")") | "");
objectnum = tostr(" (", object, ") ");
maxnamelen = (pad = player:linelen() - length(ownername)) - length(objectnum);
objectname = (length(oname = tostr(prefix, (valid(object) && (c = length(children(object))))
? tostr("{", c, "} ") | "", valid(object) ? object.name | "")) > maxnamelen)
? tostr(oname[1..maxnamelen - 2], "++") | oname;
objectname = tostr(objectname, objectnum);
return tostr($string_utils:left(objectname, -pad, "."), ownername);
.
owned_matches:
"Syntax: owned_matches(str , obj ) => true/false";
"Returns true if is an index of 's name or an alias.";
substr = args[1];
for name in ({args[2].name, @args[2].aliases})
if (index(name, substr))
return 1;
endif
endfor
.
owned_includes:
"Syntax: owned_includes(obj , list , list ) => true/false";
"Returns true if included or not excluded.";
object = args[1];
includes = args[2];
excludes = args[3];
while (valid(object))
if (object in includes)
return 1;
elseif (object in excludes)
return 0;
endif
object = parent(object);
endwhile
return !includes;
.
owned_location:
"Syntax: owned_location(obj ) => str";
"Returns \"#source Source->#dest Dest\" for exits, \"Room\" for rooms, and \"#loc
Location\" (or \"[Nowhere]\" for others.";
if (!valid(loc = (o = args[1]).location))
nowhere = "[Nowhere]";
p = o;
while (valid(p = parent(p)))
if (p == $room)
return "Room";
elseif (p == $exit)
source = valid(s = o.source) ? tostr(s, (s.owner == o.owner) ? " " |
"*", s.name) | nowhere;
dest = valid(d = o.dest) ? tostr(d, (d.owner == o.owner) ? " " | "*",
d.name) | nowhere;
return tostr(source[1..min(length(source), 25 - length(dest))], "->",
dest);
endif
endwhile
return nowhere;
endif
return tostr(loc, (loc.owner == o.owner) ? " " | "*", loc.name);
.
@owned @pros-owned @po*wned:
"Syntax: @owned [] [named ] [with ...]";
"Display objects owned by , or yourself.";
"";
"If \"named \" is given, only objects with somewhere in their names
will be shown.";
"";
"By default, exits are omitted from the list. Use \"with ...\" to further
limit the ancestory of displayed objects. Each string can be one of:";
" \"exits\" -- do not exclude exits by default";
" -- include only those objects descended from ";
" ! -- exclude any objects descended from ";
"";
"Ex: @owned sick named util -- display Sick's objects matching \"util\"";
" @owned with $note !$letter -- display only notes that are not letters";
named = "";
inc = {};
exc = {$exit};
su = $string_utils;
cu = $command_utils;
ou = $object_utils;
lu = $list_utils;
myu = this.utils;
pros = verb[1..2] == "@p";
while (argstr && (m = rmatch(argstr, "%(^%| +%)%(named%|with%) +%(.+%)$")))
argstr[m[1]..m[2]] = "";
if ((pstr = substitute("%2", m)) == "named")
named = substitute("%3", m);
player:tell("named=", su:print(named));
elseif (pstr == "with")
for s in (su:words(substitute("%3", m)))
if ((length(s) > 3) && (index("prospectus", s) == 1))
pros = 1;
elseif (s == "exits")
exc = setremove(exc, $exit);
elseif (cu:object_match_failed(o = player:my_match_object((ex = s &&
("!" == s[1])) ? s = s[2..length(s)] | s), s))
return;
elseif (ex)
exc = setadd(exc, o);
inc = setremove(inc, o);
else
inc = setadd(inc, o);
exc = setremove(exc, o);
endif
endfor
else
return player:tell(pstr, ": huh?");
endif
endwhile
if (argstr ? cu:player_match_failed(who = su:match_player(argstr), argstr) | (who
= player))
return;
elseif (typeof(stuff = who.owned_objects) != LIST)
return player:tell(su:nn(who), " owns too much stuff to keep in a list.");
endif
data = keys = {};
nsize = tsize = 0;
slen = blen = olen = nlen = llen = 0;
for o in (stuff)
tsize = tsize + (size = o.object_size[1]);
if (((!named) || this:owned_matches(named, o)) && ((!(inc || exc)) || this:owned_includes(o,
inc, exc)))
nsize = nsize + size;
keys = listinsert(keys, size, i = lu:find_insert(keys, size));
slen = max(slen, length(size = size ? myu:byte_string(size) | "-?-"));
bits = tostr(" r"[o.r + 1], " f"[o.f + 1], " W"[o.w + 1]);
blen = max(blen, ((o.w * 3) || (o.f * 2)) || o.r);
olen = max(olen, length(onum = tostr(o)));
nlen = max(nlen, length(name = " !"[is_clear_property(o, "description") +
1] + o.name));
pros && (llen = max(llen, length(loc = this:owned_location(o))));
data = listinsert(data, pros ? {myu:verb_count(o) || "", length(children(o))
|| "", size, bits, onum, name, loc} | {size, bits, onum, name});
endif
endfor
tobj = length(stuff);
nobj = length(data);
format = tostr(pros ? "`vrbs:4R' `kids:4R' " | "", "`size:", slen, "R' ` :", blen
+ 1, "'` :", olen, "R' ` :", nlen, "'", @pros ? {" : ` :", llen, "'"} | {});
player:tell("format=", format);
text = data && listdelete(myu:generate_table(format, data), 2);
header = tostr("Showing ", inc ? "descendants of " + su:nanl(inc) | "all objects",
named ? (" matching \"" + named) + "\"" | "", " owned by ", su:nn(who), exc ? ",
excluding descendants of " + su:nanl(exc) | "", ":");
footer = tostr("--- ", @(nobj == tobj) ? {} | {nobj, " of "}, tobj, (tobj ==
1) ? " object " | " objects ", (nobj == 1) ? "uses " | "use ", myu:byte_string(nsize),
@(nsize == tsize) ? {} | {" of ", myu:byte_string(tsize), " total usage "}, " of
", myu:byte_string($quota_utils:get_quota(who)), " quota.");
player:tell_lines_suspended({header, "", @text, footer});
.
PROPERTY DATA:
      utils