generic player (#6)(an instance of Root Class made by The_Mayor)     You see a player who should type '@describe me as ...'. generic player owns VERB SOURCE CODE: init_for_core:
if (caller_perms().wizard)
pass();
this.home = (this in {$no_one, $hacker}) ? $nothing | $player_start;
if (a = $list_utils:assoc(this, {{$prog, {$prog_help, $builtin_function_help,
$verb_help, $core_help}}, {$wiz, $wiz_help}}))
this.help = a[2];
else
this.help = 0;
endif
if (this != $player)
for p in ({"last_connect_place", "all_connect_places"})
clear_property(this, p);
endfor
endif
endif
.
confunc:
if (((valid(cp = caller_perms()) && (caller != this)) && (!$perm_utils:controls(cp,
this))) && (caller != #0))
return E_PERM;
endif
nm = this:length_all_msgs() - this:length_date_le(this:get_current_message()[2]);
if (nm)
this:notify(tostr("You have new mail (", nm, " message", (nm == 1) ? "" | "s",
").", this:mail_option("expert") ? "" | " Type 'help mail' for info on reading it."));
endif
this:mail_catch_up();
this:check_mail_lists();
this:("@last-connection")();
$news:check();
.
disfunc:
if (((valid(cp = caller_perms()) && (caller != this)) && (!$perm_utils:controls(cp,
this))) && (caller != #0))
return E_PERM;
endif
this:expunge_rmm();
this:erase_paranoid_data();
return;
.
initialize:
if ((caller == this) || $perm_utils:controls(caller_perms(), this))
this.help = 0;
return pass(@args);
else
return E_PERM;
endif
.
recycle:
set_task_perms(caller_perms());
if ((!is_player(this)) || caller_perms().wizard)
pass(@args);
return;
endif
"...start off with a wizard shout...";
for p in (connected_players())
if (p.wizard)
p:tell($string_utils:pronoun_sub("%N (%#) is currently trying to recycle
%t (%[#t])"));
endif
endfor
"...Okay here's the fun part.";
"...Doing kill_task(task_id()) doesn't work because the server can";
"...figure out that it's okay to go ahead and recycle once the task finishes.";
"...Evidently, suspend() confuses the server sufficiently that it forgets to";
"...do the recycle once the task finishes or dies. Now of course, we don't";
"...want suspended tasks hanging around indefinitely, so we fork something";
"...off to kill it. This seems to work...";
t = task_id();
fork (1)
kill_task(t);
endfork
"...let him think he succeeded (should we do this ?)...no.";
"...boot_player(this)";
"...emergency life support...";
suspend(1073741823);
"...code not reached --- the patient lives...";
"...keep this around for posterity...";
if (is_player(this))
for a in (this.aliases)
$player_db:delete(a);
endfor
$player_db:delete(this.name);
endif
pass(@args);
.
acceptable: return !is_player(args[1]); . my_huh:
"Extra parsing of player commands. Called by $command_utils:do_huh.";
"This version of my_huh just handles features.";
if ((caller != this) && (!$perm_utils:controls(caller_perms(), this)))
"Standard permissions check.";
return E_PERM;
endif
"verb - obvious pass - would be args";
"plist - list of prepspecs that this command matches";
"dlist and ilist - likewise for dobjspecs, iobjspecs";
verb = args[1];
if ($code_utils:tonum(verb))
return;
endif
pass = args[2];
plist = {"any", prepstr ? $code_utils:full_prep(prepstr) | "none"};
dlist = dobjstr ? {"any"} | {"none", "any"};
ilist = iobjstr ? {"any"} | {"none", "any"};
for fobj in (this.features)
if (!$recycler:valid(fobj))
this:remove_feature(fobj);
elseif (valid(loc = $object_utils:has_callable_verb(fobj, verb)[1]))
vargs = verb_args(loc, verb);
if ((vargs[2] in plist) && ((vargs[1] in dlist) && (vargs[3] in ilist)))
"(got rid of notify_huh - should write a @which command)";
"if (this.notify_huh)";
"player:notify(tostr(\"Using \", what.name, \" (\", what, \")\"));";
"endif";
set_task_perms(this);
fobj:(verb)(@pass);
"Problem with verbs of the same name. If we use which=vrb in the loop
instead, we have a problem with verbs that use the variable verb.";
return 1;
endif
endif
if ($command_utils:running_out_of_time())
player:tell("You have too many features. Parsing your command runs out of
ticks while checking ", fobj.name, " (", fobj, ").");
return 1;
endif
endfor
.
last_huh:
":last_huh(verb,args) final attempt to parse a command...";
set_task_perms(caller_perms());
verb = args[1];
args = args[2];
if ((verb[1] == "@") && (prepstr == "is"))
"... set or show _msg property ...";
set_task_perms(player);
$last_huh:(verb)(@args);
elseif (verb in {"give", "hand", "get", "take", "drop", "throw"})
$last_huh:(verb)(@args);
else
return 0;
endif
return 1;
.
my_match_object:
":my_match_object(string [,location])";
return $string_utils:match_object(@{@args, this.location}[1..2], this);
.
tell_contents:
c = args[1];
if (c)
longear = {};
gear = {};
width = player:linelen();
half = width / 2;
player:tell("Carrying:");
for thing in (c)
cx = tostr(" ", thing:title());
if (length(cx) > half)
longear = {@longear, cx};
else
gear = {@gear, cx};
endif
endfor
player:tell_lines($string_utils:columnize(gear, 2, width));
player:tell_lines(longear);
endif
.
titlec: return $object_utils:has_property(this, "namec") ? this.namec | this:title(); . notify:
line = args[1];
if (this.pagelen)
if (!(this in connected_players()))
"...drop it on the floor...";
return 0;
elseif ((caller != this) && (!$perm_utils:controls(caller_perms(), this)))
return E_PERM;
endif
"...need wizard perms if this and this.owner are different, since...";
"...only this can notify() and only this.owner can read .linebuffer...";
if ((player == this) && (this.linetask[2] != task_id()))
"...player has started a new task...";
"....linetask[2] is the taskid of the most recent player task...";
if (this.linetask[2] != this.linetask[1])
this.linesleft = this.pagelen - 2;
endif
this.linetask[2] = task_id();
endif
"... digest the current line...";
if (this.linelen > 0)
lbuf = {@this.linebuffer, @this:linesplit(line, this.linelen)};
else
lbuf = {@this.linebuffer, line};
endif
"... print out what we can...";
if (this.linesleft)
howmany = min(this.linesleft, length(lbuf));
for l in (lbuf[1..howmany])
notify(this, l);
endfor
this.linesleft = this.linesleft - howmany;
lbuf[1..howmany] = {};
endif
if (lbuf)
"...see if we need to say ***More***";
if (this.linetask[1] != this.linetask[2])
"....linetask[1] is the taskid of the most recent player task";
"... for which ***More*** was printed...";
this.linetask[1] = this.linetask[2];
fork (0)
notify(this, strsub(this.more_msg, "%n", tostr(length(this.linebuffer))));
endfork
endif
llen = length(lbuf);
if (llen > 500)
"...way too much saved text, flush some of it...";
lbuf[1..llen - 100] = {"*** buffer overflow, lines flushed ***"};
endif
endif
this.linebuffer = lbuf;
else
if (caller != this)
set_task_perms(caller_perms());
endif
if (this.linelen > 0)
for l in (this:linesplit(line, this.linelen))
notify(this, l);
endfor
else
notify(this, line);
endif
endif
.
notify_lines:
if ($perm_utils:controls(caller_perms(), this) || (caller == this))
set_task_perms(caller_perms());
for line in ((typeof(lines = args[1]) != LIST) ? {lines} | lines)
this:notify(tostr(line));
endfor
else
return E_PERM;
endif
.
linesplit:
":linesplit(line,len) => list of substrings of line";
"used by :notify to split up long lines if .linelen>0";
line = args[1];
len = args[2];
cline = {};
while (length(line) > len)
cutoff = rindex(line[1..len], " ");
if (nospace = cutoff < ((4 * len) / 5))
cutoff = len + 1;
nospace = line[cutoff] != " ";
endif
cline = {@cline, line[1..cutoff - 1]};
line = (nospace ? " " | "") + line[cutoff..length(line)];
endwhile
return {@cline, line};
.
linelen: return abs(this.linelen); . @more:
if (player != this)
"... somebody's being sneaky...";
"... Can't do set_task_perms(player) since we need to be `this'...";
"... to notify and `this.owner' to change +c properties...";
return;
elseif (!(lbuf = this.linebuffer))
this.linesleft = this.pagelen - 2;
notify(this, "*** No more ***");
elseif (index("flush", dobjstr || "x") == 1)
this.linesleft = this.pagelen - 2;
notify(this, tostr("*** Flushed *** ", length(lbuf), " lines"));
this.linebuffer = {};
elseif ((index("rest", dobjstr || "x") == 1) || (!this.pagelen))
this.linesleft = this.pagelen - 2;
for l in (lbuf)
notify(this, l);
endfor
this.linebuffer = {};
else
howmany = min(this.pagelen - 2, llen = length(lbuf = this.linebuffer));
for l in (lbuf[1..howmany])
notify(this, l);
endfor
this.linesleft = (this.pagelen - 2) - howmany;
this.linebuffer = lbuf[howmany + 1..llen];
if (howmany < llen)
notify(this, strsub(this.more_msg, "%n", tostr(llen - howmany)));
this.linetask[1] = task_id();
endif
endif
this.linetask[2] = task_id();
.
@wrap:
if (player != this)
"... someone is being sneaky...";
"... Can't do set_task_perms(player) since we need to be `this'...";
"... to notify and `this.owner' to change +c properties...";
return;
endif
linelen = player.linelen;
if (!(prepstr in {"on", "off"}))
player:notify("Usage: @wrap on|off");
player:notify(tostr("Word wrap is currently ", (linelen > 0) ? "on" | "off",
"."));
return;
endif
player.linelen = abs(linelen) * ((prepstr == "on") ? 1 | -1);
player:notify(tostr("Word wrap is now ", prepstr, "."));
.
@linelen*gth:
if (callers() ? (caller != this) && (!$perm_utils:controls(caller_perms(), this))
| (player != this))
"... somebody is being sneaky ...";
return;
endif
curlen = player.linelen;
wrap = curlen > 0;
wrapstr = wrap ? "on" | "off";
if (!dobjstr)
player:notify(tostr("Usage: ", verb, "
@pagelen*gth:
"@pagelength number -- sets page buffering to that many lines (or 0 to turn off
page buffering)";
if (player != this)
"... somebody is being sneaky ...";
"... Can't do set_task_perms(player) since we need to be `this'...";
"... to notify and `this.owner' to change +c properties...";
return;
elseif (!dobjstr)
notify(player, tostr("Usage: ", verb, "
tell:
if (this.gaglist || this.paranoid)
"Check the above first, default case, to save ticks. Paranoid gaggers are cost
an extra three or so ticks by this, probably a net savings.";
if (this:gag_p())
return;
endif
if (this.paranoid == 1)
$paranoid_db:add_data(this, {{@callers(), {player, "
gag_p:
if (player in this.gaglist)
return 1;
elseif (gag = this.gaglist)
for x in (callers())
if ((x[1] in gag) || (x[4] in gag))
return 1;
endif
endfor
endif
return 0;
"--- old definition --";
if (player in this.gaglist)
return 1;
elseif (this.gaglist)
for x in (callers())
if (valid(x[1]))
if (x[1] in this.gaglist)
return 1;
endif
endif
endfor
endif
return 0;
.
set_gaglist:
":set_gaglist(@newlist) => this.gaglist = newlist";
if (!((caller == this) || $perm_utils:controls(caller_perms(), this)))
return E_PERM;
else
return this.gaglist = args;
endif
.
@gag*!:
set_task_perms(player);
if (player != this)
player:notify("Permission denied.");
return;
endif
if (!args)
player:notify(tostr("Usage: ", verb, "
@listgag @gaglist:
set_task_perms(valid(caller_perms()) ? caller_perms() | player);
if (!this.gaglist)
player:notify(tostr("You are ", callers() ? "no longer gagging anything." | "not
gagging anything right now."));
else
player:notify(tostr("You are ", callers() ? "now" | "currently", " gagging ",
$string_utils:english_list($list_utils:map_arg(2, $string_utils, "pronoun_sub", "%n
(%#)", this.gaglist)), "."));
endif
gl = {};
if (args)
player:notify("Searching for players who may be gagging you...");
for p in (players())
if ((typeof(p.gaglist) == LIST) && (this in p.gaglist))
gl = {@gl, p};
endif
$command_utils:suspend_if_needed(0);
endfor
if (gl || (!callers()))
player:notify(tostr($string_utils:english_list($list_utils:map_arg(2, $string_utils,
"pronoun_sub", "%n (%#)", gl), "No one"), " appear", (length(gl) <= 1) ? "s" | "",
" to be gagging you."));
endif
endif
.
@ungag:
if ((player != this) || ((caller != this) && (!$perm_utils:controls(caller_perms(),
this))))
player:notify("Permission denied.");
elseif (dobjstr == "")
player:notify(tostr("Usage: ", verb, "
whodunnit:
record = args[1];
trust = args[2];
mistrust = args[3];
s = {this, "???", this};
for w in (record)
if (((s[3].wizard || (s[3] in trust)) && (!(s[3] in mistrust))) || (s[1] == this))
s = w;
else
return s;
endif
endfor
return s;
.
@ch*eck-full:
responsible = $paranoid_db:get_data(this);
if (length(verb) <= 6)
"@check, not @check-full";
n = 5;
trust = {this, $no_one};
"... trust no one, my friend.... no one.... --Herod";
mistrust = {};
for k in (args)
if (z = $code_utils:tonum(k))
n = z;
elseif (k[1] == "!")
mistrust = listappend(mistrust, $string_utils:match_player(k[2..length(k)]));
else
trust = listappend(trust, $string_utils:match_player(k));
endif
endfor
msg_width = player:linelen() - 60;
for q in ((n > (y = length(responsible))) ? responsible | responsible[(y - n)
+ 1..y])
msg = tostr(@q[2]);
if (length(msg) > msg_width)
msg = msg[1..msg_width];
endif
s = this:whodunnit(q[1], trust, mistrust);
text = valid(s[1]) ? s[1].name | "** NONE **";
this:notify(tostr($string_utils:left(tostr((length(text) > 13) ? text[1..13]
| text, " (", s[1], ")"), 20), $string_utils:left(s[2], 15), $string_utils:left(tostr((length(s[3].name)
> 13) ? s[3].name[1..13] | s[3].name, " (", s[3], ")"), 20), msg));
endfor
this:notify("*** finished ***");
else
"@check-full, from @traceback by APHiD";
matches = {};
if (length(match = argstr) == 0)
player:notify(tostr("Usage: ", verb, "
@paranoid:
if ((args == {}) || ((typ = args[1]) == ""))
$paranoid_db:set_kept_lines(this, 10);
this.paranoid = 1;
this:notify("Anti-spoofer on and keeping 10 lines.");
elseif (index("immediate", typ))
$paranoid_db:set_kept_lines(this, 0);
this.paranoid = 2;
this:notify("Anti-spoofer now in immediate mode.");
elseif (index("off", typ) || (typ == "0"))
this.paranoid = 0;
$paranoid_db:set_kept_lines(this, 0);
this:notify("Anti-spoofer off.");
elseif ((tostr(y = tonum(typ)) != typ) || (y < 0))
this:notify(tostr("Usage: ", verb, "
@sw*eep:
buggers = 1;
found_listener = 0;
here = this.location;
for thing in (setremove(here.contents, this))
tellwhere = $object_utils:has_verb(thing, "tell");
notifywhere = $object_utils:has_verb(thing, "notify");
if (thing in connected_players())
this:notify(tostr(thing.name, " (", thing, ") is listening."));
found_listener = 1;
elseif ($object_utils:has_callable_verb(thing, "sweep_msg") && (typeof(msg =
thing:sweep_msg()) == STR))
this:notify(tostr(thing.name, " (", thing, ") ", msg, "."));
found_listener = 1;
elseif (tellwhere && (((owner = verb_info(tellwhere[1], "tell")[1]) != this)
&& (!owner.wizard)))
this:notify(tostr(thing.name, " (", thing, ") has been taught to listen by
", owner.name, " (", owner, ")"));
found_listener = 1;
elseif (notifywhere && (((owner = verb_info(notifywhere[1], "notify")[1]) !=
this) && (!owner.wizard)))
this:notify(tostr(thing.name, " (", thing, ") has been taught to listen by
", owner.name, " (", owner, ")"));
found_listener = 1;
endif
endfor
buggers = {};
for v in ({"announce", "announce_all", "announce_all_but", "say", "emote", "huh",
"here_huh", "huh2", "whisper"})
vwhere = $object_utils:has_verb(here, v);
if (vwhere && (((owner = verb_info(vwhere[1], v)[1]) != this) && (!owner.wizard)))
buggers = setadd(buggers, owner);
endif
endfor
if (buggers != {})
if ($object_utils:has_verb(here, "sweep_msg") && (typeof(msg = here:sweep_msg())
== STR))
this:notify(tostr(here.name, " (", here, ") ", msg, "."));
else
this:notify(tostr(here.name, " (", here, ") may have been bugged by ", $string_utils:english_list($list_utils:map_prop(buggers,
"name")), "."));
endif
elseif (!found_listener)
this:notify("Communications look secure.");
endif
.
wh*isper:
this:tell(player.name, " whispers, \"", dobjstr, "\"");
player:tell("You whisper, \"", dobjstr, "\" to ", this.name, ".");
.
page:
nargs = length(args);
if (nargs < 1)
player:notify(tostr("Usage: ", verb, "
receive_page:
"called by $player:page. Two args, the page header and the text, all pre-processed
by the page command. Could be extended to provide haven abilities, multiline pages,
etc. Indeed, at the moment it just does :tell_lines, so we already do have multiline
pages, if someone wants to take advantage of it.";
"Return codes:";
" 1: page was received";
" 2: player is not connected";
" 0: page refused";
"If a specialization wants to refuse a page, it should return 0 to say it was refused.
If it uses pass(@args) it should propagate back up the return value. It is possible
that this code should interact with gagging and return 0 if the page was gagged.";
if (this:is_listening())
this:tell_lines(args);
return 1;
else
return 2;
endif
.
page_origin_msg page_echo_msg page_absent_msg: "set_task_perms(this.owner)"; return (msg = this.(verb)) ? $string_utils:pronoun_sub(this.(verb), this) | ""; . i inv*entory:
if (c = player:contents())
this:tell_contents(c);
else
player:tell("You are empty-handed.");
endif
.
look_self:
player:tell(this:titlec());
pass();
if (!(this in connected_players()))
player:tell($gender_utils:pronoun_sub("%{:He} %{!is} sleeping.", this));
elseif ((idle = idle_seconds(this)) < 60)
player:tell($gender_utils:pronoun_sub("%{:He} %{!is} awake and %{!looks} alert.",
this));
else
time = $string_utils:from_seconds(idle);
player:tell($gender_utils:pronoun_sub("%{:He} %{!is} awake, but %{!has} been
staring off into space for ", this), time, ".");
endif
if (c = this:contents())
this:tell_contents(c);
endif
.
home:
start = this.location;
if (start == this.home)
player:tell("You're already home!");
return;
elseif (typeof(this.home) != OBJ)
player:tell("You've got a weird home, pal. I've reset it to the default one.");
this.home = $player_start;
elseif (!valid(this.home))
player:tell("Oh no! Your home's been recycled. Time to look around for a new
one.");
this.home = $player_start;
else
player:tell("You click your heels three times.");
endif
this:moveto(this.home);
if (!valid(start))
elseif (start == this.location)
start:announce(player.name, " learns that you can never go home...");
else
start:announce(player.name, " goes home.");
endif
if (this.location == this.home)
this.location:announce(player.name, " comes home.");
elseif (this.location == start)
player:tell("Either home doesn't want you, or you don't really want to go.");
else
player:tell("Wait a minute! This isn't your home...");
if (valid(this.location))
this.location:announce(player.name, " arrives, looking quite bewildered.");
endif
endif
.
@sethome:
set_task_perms(this);
here = this.location;
if (!$object_utils:has_callable_verb(here, "accept_for_abode"))
player:notify("This is a pretty odd place. You should make your home in an actual
room.");
elseif (here:accept_for_abode(this))
this.home = here;
player:notify(tostr(here.name, " is your new home."));
else
player:notify(tostr("This place doesn't want to be your home. Contact ", here.owner.name,
" to be added to the residents list of this place, or choose another place as your
home."));
endif
.
g*et take:
player:tell("This is not a pick-up joint!");
this:tell(player.name, " tried to pick you up.");
.
@move: "'@move @eject @eject! @eject!!:
set_task_perms(player);
if (iobjstr == "here")
iobj = player.location;
elseif (iobjstr == "me")
iobj = player;
elseif ($command_utils:object_match_failed(iobj, iobjstr))
return;
endif
if (!$perm_utils:controls(player, iobj))
player:notify(tostr("You are not the owner of ", iobj.name, "."));
return;
endif
if (dobjstr == "me")
dobj = player;
elseif (($failed_match == (dobj = $string_utils:literal_object(dobjstr))) && $command_utils:object_match_failed(dobj
= iobj:match(dobjstr), dobjstr))
return;
endif
if (dobj.location != iobj)
player:notify(tostr(dobj.name, "(", dobj, ") is not in ", iobj.name, "(", iobj,
")."));
return;
endif
if (dobj.wizard)
player:notify(tostr("Sorry, you can't ", verb, " a wizard."));
dobj:tell(player.name, " tried to ", verb, " you.");
return;
endif
iobj:((verb == "@eject") ? "eject" | "eject_basic")(dobj);
player:notify($object_utils:has_callable_verb(iobj, "ejection_msg") ? iobj:ejection_msg()
| $room:ejection_msg());
if (verb != "@eject!!")
dobj:tell($object_utils:has_callable_verb(iobj, "victim_ejection_msg") ? iobj:victim_ejection_msg()
| $room:victim_ejection_msg());
endif
iobj:announce_all_but({player, dobj}, $object_utils:has_callable_verb(iobj, "oejection_msg")
? iobj:oejection_msg() | $room:oejection_msg());
.
where*is @where*is:
if (!args)
them = connected_players();
else
who = $command_utils:player_match_result($string_utils:match_player(args), args);
if (length(who) <= 1)
if (!who[1])
player:notify("Where is who?");
endif
return;
elseif (who[1])
player:notify("");
endif
them = listdelete(who, 1);
endif
lmax = rmax = 0;
for p in (them)
player:notify($string_utils:pronoun_sub("%N (%#) is in %l (%[#l]).", p));
endfor
.
@who:
if (caller != player)
return E_PERM;
endif
plyrs = args ? listdelete($command_utils:player_match_result($string_utils:match_player(args),
args), 1) | connected_players();
if (!plyrs)
return;
endif
$code_utils:show_who_listing(plyrs);
.
@wizards:
"@wizards [all]";
if (caller != player)
return E_PERM;
endif
if (args)
$code_utils:show_who_listing($wiz_utils:all_wizards());
else
$code_utils:show_who_listing($wiz_utils:connected_wizards()) || player:notify("No
wizards currently logged in.");
endif
.
?* help info*rmation @help:
set_task_perms(callers() ? caller_perms() | player);
"...this code explicitly relies on being !d in several places...";
if ((index(verb, "?") != 1) || (length(verb) <= 1))
what = $string_utils:trimr(argstr);
elseif (argstr)
what = tostr(verb[2..length(verb)], " ", $string_utils:trimr(argstr));
else
what = verb[2..length(verb)];
endif
"...find a db that claims to know about `what'...";
dblist = $code_utils:help_db_list();
result = $code_utils:help_db_search(what, dblist);
if (!result)
"... note: all of the last-resort stuff...";
"... is now located on $help:find_topics/get_topic...";
"$wiz_utils:missed_help(what, result)";
player:notify(tostr("Sorry, but no help is available on `", what, "'."));
elseif (result[1] == $ambiguous_match)
"$wiz_utils:missed_help(what, result)";
player:notify_lines(tostr("Sorry, but the topic-name `", what, "' is ambiguous.
I don't know which of the following topics you mean:"));
for x in ($string_utils:columnize($help:sort_topics(result[2]), 3, 60))
player:notify(tostr(" ", x));
endfor
else
help = result[1];
topic = result[2];
if (topic != what)
player:notify(tostr("Showing help on `", topic, "':"));
player:notify("----");
endif
dblist = dblist[1 + (help in dblist)..length(dblist)];
if (1 == (text = help:get_topic(topic, dblist)))
"...get_topic took matters into its own hands...";
elseif (text)
"...these can get long...";
for line in ((typeof(text) == LIST) ? text | {text})
if (typeof(line) != STR)
player:notify("Odd results from help -- complain to a wizard.");
else
player:notify(line);
endif
$command_utils:suspend_if_needed(0);
endfor
else
player:notify(tostr("Help DB ", help, " thinks it knows about `", what, "'
but something's messed up."));
player:notify(tostr("Tell ", help.owner.wizard ? "" | tostr(help.owner.name,
" (", help.owner, ") or "), "a wizard."));
endif
endif
.
news: $news:read(); . mail_forward mail_notify:
if (typeof(mf = this.(verb)) == STR)
return $string_utils:pronoun_sub(mf, @args);
else
return mf;
endif
.
receive_message:
":receive_message(msg,from)";
if ((!$perm_utils:controls(caller_perms(), this)) && (caller != this))
return E_PERM;
endif
if (this:mail_option("netmail"))
msg = args[1];
message = {"Forwarded: " + msg[4], "Original-date: " + ctime(msg[1]), "Original-From:
" + msg[2], "Original-To: " + msg[3], ((("Reply-To: " + args[2].name) + "@") + $network.moo_name)
+ ".moo.mud.org"};
for x in (msg[5..length(msg)])
message = {@message, @$generic_editor:fill_string(x, this:linelen())};
endfor
if (this:send_self_netmail(message, @listdelete(args, 1)) == 0)
return 0;
endif
endif
set_task_perms(this.owner);
new = this:new_message_num();
ncur = (new <= 1) ? 0 | min(this:current_message(this), new);
this:set_current_message(this, ncur);
new = max(new, ncur + 1);
this.messages = {@this.messages, {new, args[1]}};
"... new-mail notification is now done directly by $mail_agent:raw_send";
"... see :notify_mail...";
return new;
.
display_message:
":display_message(preamble,msg) --- prints msg to player.";
vb = ((this._mail_task == task_id()) || (caller == $mail_editor)) ? "notify_lines"
| "tell_lines";
preamble = args[1];
player:(vb)({@(typeof(preamble) == LIST) ? preamble | {preamble}, @args[2], "--------------------------"});
.
parse_message_seq from_msg_seq %from_msg_seq to_msg_seq %to_msg_seq subject_msg_seq body_msg_seq kept_msg_seq unkept_msg_seq display_seq_headers display_seq_full messages_in_seq list_rmm new_message_num length_num_le length_date_le length_date_gt length_all_msgs exists_num_eq msg_seq_to_msg_num_list msg_seq_to_msg_num_string rm_message_seq undo_rmm expunge_rmm renumber keep_message_seq:
"parse_message_seq(strings,cur) => msg_seq";
"messages_in_seq(msg_seq); => text of messages in msg_seq";
"display_seq_headers(msg_seq[,current]) :displays summary lines of those msgs";
"rmm_message_seq(msg_seq) => string giving msg numbers removed";
"undo_rmm() => msg_seq of restored messages";
"expunge_rmm() => number of messages expunged";
"list_rmm() => number of messages awaiting expunge";
"renumber(cur) => {number of messages in folder, new_cur}";
"";
"See the corresponding routines on $mail_agent.";
if ((caller == $mail_agent) || $perm_utils:controls(caller_perms(), this))
set_task_perms(this.owner);
return $mail_agent:(verb)(@args);
else
return E_PERM;
endif
.
msg_summary_line: return $mail_agent:msg_summary_line(@args); . msg_text: return $mail_agent:to_text(@args); . notify_mail: ":notify_mail(from,recipients[,msgnums])"; " used by $mail_agent:raw_send to notify this player about mail being sent"; " from __fix:
"runs the old->new format conversion on every message in this.messages.";
" => 1 if successful";
" => 0 if anything toward happened during a suspension";
" (e.g., new message received, someone deleted stuff) ";
" in which case this.messages is left as if this routine were never run.";
if (!$perm_utils:controls(caller_perms(), this))
return E_PERM;
endif
msgs = {};
i = 1;
for m in (oldmsgs = this.messages)
msgs = {@msgs, {m[1], $mail_agent:__convert_new(@m[2])}};
if ($command_utils:running_out_of_time())
player:notify(tostr("...", i, " ", this));
suspend(0);
if (oldmsgs != this.messages)
return 0;
endif
endif
i = i + 1;
endfor
this.messages = msgs;
return 1;
.
current_message:
":current_message([recipient])";
" => current message number for the given recipient (defaults to this).";
" => 0 if we have no record of that recipient.";
if ((caller != this) && (!$perm_utils:controls(caller_perms(), this)))
$error:raise(E_PERM);
elseif ((!args) || (args[1] == this))
return this.current_message[1];
elseif (a = $list_utils:assoc(args[1], this.current_message))
return a[2];
else
return 0;
endif
.
get_current_message:
":get_current_message([recipient])";
" => {msg_num, last_read_date} for the given recipient.";
" => 0 if we have no record of that recipient.";
if ((caller != this) && (!$perm_utils:controls(caller_perms(), this)))
$error:raise(E_PERM);
elseif ((!args) || (args[1] == this))
return this.current_message[1..2];
elseif (a = $list_utils:assoc(args[1], this.current_message))
return a[2..3];
else
return 0;
endif
.
set_current_message:
":set_current_message(recipient[,number[,date]])";
"Returns the new {number,last-read-date} pair for recipient.";
if ((caller != this) && (!$perm_utils:controls(caller_perms(), this)))
return $error:raise(E_PERM);
endif
recip = args[1];
number = {@args, E_NONE}[2];
date = {@args, 0, 0}[3];
cm = this.current_message;
if (recip == this)
this.current_message[2] = max(date, cm[2]);
if (number != E_NONE)
this.current_message[1] = number;
endif
return this.current_message[1..2];
elseif (i = $list_utils:iassoc(recip, cm))
return (this.current_message[i] = {recip, (number == E_NONE) ? cm[i][2] | number,
max(date, cm[i][3])})[2..3];
else
entry = {recip, (number != E_NONE) && number, date};
this.current_message = {@cm, entry};
return entry[2..3];
endif
.
make_current_message:
":make_current_message(recipient)";
"starts a new current_message record for recipient";
if ((caller != this) && (!$perm_utils:controls(caller_perms(), this)))
return $error:raise(E_PERM);
elseif (((recip = args[1]) != this) && (!$list_utils:assoc(recip, cm = this.current_message)))
this.current_message = listappend(cm, {recip, 0, 0});
endif
.
kill_current_message:
":kill_current_message(recipient)";
"entirely forgets current message for this recipient...";
"Returns true iff successful.";
if ((caller != this) && (!$perm_utils:controls(caller_perms(), this)))
return $error:raise(E_PERM);
else
return ((recip = args[1]) != this) && ((i = $list_utils:iassoc(recip, cm = this.current_message))
&& (this.current_message = listdelete(cm, i)));
endif
.
current_folder:
":current_folder() => default folder to use, always an object, usually `this'";
set_task_perms(caller_perms());
return ((!this:mail_option("sticky")) || this.current_folder) && this;
.
set_current_folder: set_task_perms(caller_perms()); return this.current_folder = args[1]; . parse_folder_spec:
":parse_folder_spec(verb,args,expected_preposition[,allow_trailing_args_p])";
" => {folder, msg_seq_args, trailing_args}";
set_task_perms(caller_perms());
folder = this:current_folder();
if (!prepstr)
return {folder, args[2], {}};
endif
verb = args[1];
prep = args[3];
extra = {@args, 0}[4];
args = args[2];
p = prepstr in args;
if (prepstr != prep)
"...unexpected preposition...";
if (extra && (!index(prepstr, " ")))
return {folder, args[1..p - 1], args[p..length(args)]};
else
player:tell("Usage: ", verb, " [
parse_mailread_cmd:
":parse_mailread_cmd(verb,args,default,prep[,trailer])";
" handles anything of the form `VERB message_seq [PREP folder ...]'";
" default is the default msg-seq to use if none given";
" prep is the expected prepstr (assumes prepstr is set), usually `on'";
" trailer, if present and true, indicates trailing args are permitted.";
" returns {recipient object, message_seq, current_msg,\"...\"} or 0";
set_task_perms(caller_perms());
if (!(pfs = this:parse_folder_spec(@listdelete(args, 3))))
return 0;
endif
verb = args[1];
default = args[3];
extra = {@args, 0}[5];
folder = pfs[1];
cur = this:get_current_message(folder) || {0};
if (typeof(pms = folder:parse_message_seq(pfs[2], @cur)) == LIST)
rest = {@listdelete(pms, 1), @pfs[3]};
if ((!extra) && rest)
"...everything should have been gobbled by :parse_message_seq...";
player:tell("I don't understand `", rest[1], "'");
return 0;
elseif (pms[1])
"...we have a nonempty message sequence...";
return {folder, pms[1], cur, rest};
elseif (used = (length(pfs[2]) + 1) - length(pms))
"...:parse_message_seq used some words, but didn't get anything out of it";
pms = ("%f %
@mail:
@read @peek: "@read @next @prev:
set_task_perms(player);
if (dobjstr)
player:notify(tostr("Usage: ", verb, " [on
@rmm*ail: "@rmm @renumber:
set_task_perms(player);
if (!dobjstr)
folder = this:current_folder();
elseif ($mail_agent:match_failed(folder = $mail_agent:match_recipient(dobjstr), dobjstr))
return;
endif
cur = this:current_message(folder);
fname = $mail_agent:name(folder);
if (typeof(h = folder:renumber(cur)) == ERR)
player:notify(tostr(h));
else
if (!h[1])
player:notify(tostr("No messages on ", fname, "."));
else
player:notify(tostr("Messages on ", fname, " renumbered 1-", h[1], "."));
this:set_current_folder(folder);
if (h[2] && this:set_current_message(folder, h[2]))
player:notify(tostr("Current message is now ", h[2], "."));
endif
endif
endif
.
@unrmm*ail: "@unrmm [on @send:
if (args && (args[1] == "to"))
args = listdelete(args, 1);
endif
subject = {};
for a in (args)
if (((i = index(a, "=")) > 3) && (index("subject", a[1..i - 1]) == 1))
args = setremove(args, a);
a[1..i] = "";
subject = {a};
endif
endfor
$mail_editor:invoke(args, verb, @subject);
.
@answer @repl*y: "@answer @forward: "@forward @gripe: $mail_editor:invoke($gripe_recipients, "@gripe", "@gripe: " + argstr); . @typo @bug @suggest*ion @idea @comment:
subject = tostr($string_utils:capitalize(verb[2..length(verb)]), ": ", (loc = this.location).name,
"(", loc, ")");
if (this != player)
return E_PERM;
elseif (argstr)
result = $mail_agent:send_message(this, {loc.owner}, subject, argstr);
if (result && result[1])
player:notify(tostr("Your ", verb, " sent to ", $mail_agent:name_list(@listdelete(result,
1)), ". Input is appreciated, as always."));
else
player:notify(tostr("Huh? This room's owner (", loc.owner, ") is invalid?
Tell a wizard..."));
endif
return;
elseif (!($object_utils:isa(loc, $room) && loc.free_entry))
player:notify_lines({tostr("You need to make it a one-liner, i.e., `", verb,
" something or other'."), "This room may not let you back in if you go to the Mail
Room."});
elseif ($object_utils:isa(loc, $generic_editor))
player:notify_lines({tostr("You need to make it a one-liner, i.e., `", verb,
" something or other'."), "Sending you to the Mail Room from an editor is usually
a bad idea."});
else
$mail_editor:invoke({tostr(loc.owner)}, verb, subject);
endif
if (verb == "@bug")
player:notify("For a @bug report, be sure to mention exactly what it was you
typed to trigger the error...");
endif
.
@skip: "@skip [* @subscribe @unsubscribed: "@subscribe * mail_catch_up:
set_task_perms((caller == this) ? this.owner | caller_perms());
new_cm = head = {};
for n in (this.current_message)
$command_utils:suspend_if_needed(0);
if (typeof(n) != LIST)
head = {@head, n};
elseif ($object_utils:isa(folder = n[1], $mail_recipient) && folder:is_readable_by(this))
"...set current msg to be the last one you could possibly have read.";
if (n[3] < folder.last_msg_date)
i = folder:length_date_le(n[3]);
n[2] = i && folder:messages_in_seq(i)[1];
endif
new_cm = listappend(new_cm, n, $list_utils:iassoc_sorted(n[3], new_cm, 3));
endif
endfor
this.current_message = {@head, @$list_utils:reverse(new_cm)};
this:set_current_folder(this);
.
@rn check_mail_lists @subscribed:
set_task_perms((caller == this) ? this.owner | caller_perms());
which = {};
cm = this.current_message;
cm[1..2] = (verb == "@rn") ? {{this, @cm[1..2]}} | {};
all = verb == "@subscribed";
for n in (cm)
rcpt = n[1];
if (n == $news)
"... $news is handled separately ...";
elseif ($mail_agent:is_recipient(rcpt))
if ((nmsgs = n[1]:length_date_gt(n[3])) || all)
which = {@which, {n[1], nmsgs}};
endif
else
player:notify(tostr("Bogus recipient ", rcpt, " removed from .current_message."));
this.current_message = setremove(this.current_message, n);
endif
$command_utils:suspend_if_needed(0);
endfor
if (which)
player:notify((verb == "@subscribed") ? "You are subscribed to the following
lists:" | "There is new activity on the following lists:");
for w in (which)
name = (w[1] == this) ? " me" | $mail_agent:name(w[1]);
player:notify(tostr($string_utils:left(" " + name, 40), " ", w[2], " new
message", (w[2] == 1) ? "" | "s"));
endfor
elseif (verb == "@rn")
player:notify("No new activity on any of your lists.");
elseif (verb == "@subscribed")
player:notify("You aren't subscribed to any mailing lists.");
endif
return which;
.
mail_option:
":mail_option(name)";
"Returns the value of the specified mail option";
if ((caller in {this, $mail_editor, $mail_agent}) || $perm_utils:controls(caller_perms(),
this))
return $mail_options:get(this.mail_options, args[1]);
else
return E_PERM;
endif
.
display_option:
":display_option(name) => returns the value of the specified @display option";
if ((caller == this) || $perm_utils:controls(caller_perms(), this))
return $display_options:get(this.display_options, args[1]);
else
return E_PERM;
endif
.
edit_option:
":edit_option(name) => returns the value of the specified edit option";
if ((caller == this) || ($object_utils:isa(caller, $generic_editor) || $perm_utils:controls(caller_perms(),
this)))
return $edit_options:get(this.edit_options, args[1]);
else
return E_PERM;
endif
.
set_mail_option set_edit_option set_display_option:
":set_edit_option(oname,value)";
":set_display_option(oname,value)";
":set_mail_option(oname,value)";
"Changes the value of the named option.";
"Returns a string error if something goes wrong.";
if (!((caller == this) || $perm_utils:controls(caller_perms(), this)))
return tostr(E_PERM);
endif
"...this is kludgy, but it saves me from writing the same verb 3 times.";
"...there's got to be a better way to do this...";
verb[1..4] = "";
foo_options = verb + "s";
"...";
if (typeof(s = #0.(foo_options):set(this.(foo_options), @args)) == STR)
return s;
elseif (s == this.(foo_options))
return 0;
else
this.(foo_options) = s;
return 1;
endif
.
@mailo*ptions @mail-o*ptions @edito*ptions @edit-o*ptions @displayo*ptions @display-o*ptions: "@ set_name:
"set_name(newname) attempts to change this.name to newname";
" => E_PERM if you don't own this";
" => E_INVARG if the name is already taken or prohibited for some reason";
" => E_NACC if the player database is not taking new names right now.";
" => E_ARGS if the name is too long (controlled by $login.max_player_name)";
if (!($perm_utils:controls(caller_perms(), this) || (this == caller)))
return E_PERM;
elseif (!is_player(this))
"we don't worry about the names of player classes.";
set_task_perms(caller_perms());
return pass(@args);
elseif ($player_db.frozen)
return E_NACC;
elseif (length(name = args[1]) > $login.max_player_name)
return E_ARGS;
elseif (!($player_db:available(name) in {this, 1}))
return E_INVARG;
else
old = this.name;
this.name = name;
if ((name != old) && (!(old in this.aliases)))
$player_db:delete(old);
endif
$player_db:insert(name, this);
return 1;
endif
.
set_aliases:
"set_aliases(alias_list)";
"For changing player aliases, we check to make sure that none of the aliases match
existing player names/aliases. Aliases containing spaces are not entered in the
$player_db and so are not subject to this restriction ($string_utils:match_player
will not match on them, however, so they only match if used in the immediate room,
e.g., with match_object() or somesuch).";
"Also we make sure that the .name is included in the .alias list. In any situation
where .name and .aliases are both being changed, do the name change first.";
" => E_PERM if you don't own this";
" => E_NACC if the player database is not taking new aliases right now.";
" => E_TYPE if alias_list is not a list";
" => E_INVARG if any element of alias_list is not a string";
if (!($perm_utils:controls(caller_perms(), this) || (this == caller)))
return E_PERM;
elseif (!is_player(this))
"we don't worry about the names of player classes.";
return pass(@args);
elseif ($player_db.frozen)
return E_NACC;
elseif (typeof(aliases = args[1]) != LIST)
return E_TYPE;
elseif ((length(aliases = setadd(aliases, this.name)) > 30) && (length(aliases) >=
length(this.aliases)))
return E_INVARG;
else
for a in (aliases)
if (typeof(a) != STR)
return E_INVARG;
endif
if ((!(index(a, " ") || index(a, " "))) && (!($player_db:available(a) in
{this, 1})))
aliases = setremove(aliases, a);
endif
endfor
old = this.aliases;
this.aliases = aliases;
for a in (old)
if (!(a in aliases))
$player_db:delete2(a, this);
endif
endfor
for a in (aliases)
if (!(index(a, " ") || index(a, " ")))
$player_db:insert(a, this);
endif
endfor
return 1;
endif
.
@rename:
if ((player != caller) || (player != this))
return;
endif
set_task_perms(player);
spec = $code_utils:parse_verbref(dobjstr);
if (spec)
object = this:my_match_object(spec[1]);
if (!$command_utils:object_match_failed(object, spec[1]))
vname = spec[2];
info = verb_info(object, vname);
if (info == E_VERBNF)
player:notify("That object does not define that verb.");
elseif (typeof(info) == ERR)
player:notify(tostr(info));
else
result = set_verb_info(object, vname, listset(info, iobjstr, 3));
if (typeof(result) == ERR)
player:notify(tostr(result));
else
player:notify("Verb name changed.");
endif
endif
endif
else
object = this:my_match_object(dobjstr);
if (!$command_utils:object_match_failed(object, dobjstr))
old_name = object.name;
old_aliases = object.aliases;
if (e = $building_utils:set_names(object, iobjstr))
if (strcmp(object.name, old_name) == 0)
name_message = tostr("Name of ", object, " (", old_name, ") is unchanged");
else
name_message = tostr("Name of ", object, " changed to \"", object.name,
"\"");
endif
aliases = $string_utils:from_value(object.aliases, 1);
if (object.aliases == old_aliases)
alias_message = tostr(". Aliases are unchanged (", aliases, ").");
else
alias_message = tostr(", with aliases ", aliases, ".");
endif
player:notify(name_message + alias_message);
elseif (e == E_INVARG)
player:notify("That particular name change not allowed (see help @rename).");
if (object == player)
player:notify($player_db:why_bad_name(player, iobjstr));
endif
elseif (e == E_NACC)
player:notify("Oops. You can't update that name right now; try again
in a few minutes.");
elseif (e == E_ARGS)
player:notify(tostr("Sorry, name too long. Maximum number of characters
in a name: ", $login.max_player_name));
else
player:notify(tostr(e));
endif
endif
endif
.
@addalias @add-alias: "Syntax: @addalias @rmalias: "Syntax: @rmalias @desc*ribe:
set_task_perms(player);
dobj = player:my_match_object(dobjstr);
if ($command_utils:object_match_failed(dobj, dobjstr))
"...lose...";
elseif (e = dobj:set_description(iobjstr))
player:notify("Description set.");
else
player:notify(tostr(e));
endif
.
@mess*ages:
set_task_perms(player);
if (dobjstr == "")
player:notify(tostr("Usage: ", verb, "
@notedit: $note_editor:invoke(dobjstr, verb); . @password:
if (typeof(player.password) != STR)
if (length(args) != 1)
return player:notify(tostr("Usage: ", verb, "
@last-c*onnection:
"@last-c reports when and from where you last connected.";
"@last-c all adds the 10 most recent places you connected from.";
"@last-c confunc is like `@last-c' but is silent on first login.";
opts = {"all", "confunc"};
i = 0;
if (caller != this)
return E_PERM;
elseif (args && ((length(args) > 1) || (!(i = $string_utils:find_prefix(args[1],
opts)))))
this:notify(tostr("Usage: ", verb, " [all]"));
return;
endif
opt_all = i && (opts[i] == "all");
opt_confunc = i && (opts[i] == "confunc");
if (!(prev = this.previous_connection))
this:notify("Something was broken when you logged in; tell a wizard.");
elseif (prev[1] == 0)
opt_confunc || this:notify("Your previous connection was before we started keeping
track.");
elseif (prev[1] > time())
this:notify("This is your first time connected.");
else
this:notify(tostr("Last connected ", ctime(prev[1]), " from ", prev[2]));
if (opt_all)
this:notify("Previous connections have been from the following sites:");
for l in (this.all_connect_places)
this:notify(" " + l);
endfor
endif
endif
.
set_gender:
"set_gender(newgender) attempts to change this.gender to newgender";
" => E_PERM if you don't own this or aren't its parent";
" => Other return values as from $gender_utils:set.";
if (!($perm_utils:controls(caller_perms(), this) || (this == caller)))
return E_PERM;
else
result = $gender_utils:set(this, args[1]);
this.gender = (typeof(result) == STR) ? result | args[1];
return result;
endif
.
@gender:
set_task_perms(valid(caller_perms()) ? caller_perms() | player);
if (!args)
player:notify(tostr("Your gender is currently ", this.gender, "."));
player:notify($string_utils:pronoun_sub("Your pronouns: %s,%o,%p,%q,%r,%S,%O,%P,%Q,%R"));
player:notify(tostr("Available genders: ", $string_utils:english_list($gender_utils.genders,
"", " or ")));
else
result = this:set_gender(args[1]);
quote = (result == E_NONE) ? "\"" | "";
player:notify(tostr("Gender set to ", quote, this.gender, quote, "."));
if (typeof(result) != ERR)
player:notify($string_utils:pronoun_sub("Your pronouns: %s,%o,%p,%q,%r,%S,%O,%P,%Q,%R"));
elseif (result != E_NONE)
player:notify(tostr("Couldn't set pronouns: ", result));
else
player:notify("Pronouns unchanged.");
endif
endif
.
set_brief: "set_brief(value)"; "set_brief(value, anything)"; "If @mode: "@mode @exam*ine:
"This verb should probably go away once 'examine' is in place.";
if (dobjstr == "")
player:notify(tostr("Usage: ", verb, "
exam*ine:
set_task_perms(player);
if (!dobjstr)
player:notify(tostr("Usage: ", verb, "
add_feature:
"Add a feature to this player's features list. Caller must be this or have suitable
permissions (this or wizardly).";
"If this is a nonprogrammer, then ask feature if it is feature_ok (that is, if it
has a verb :feature_ok which returns a true value, or a property .feature_ok which
is true).";
"After adding feature, call feature:feature_add(this).";
"Returns true if successful, E_INVARG if not a valid object, and E_PERM if !feature_ok
or if caller doesn't have permission.";
if ((caller == this) || $perm_utils:controls(caller_perms(), this))
feature = args[1];
if ((typeof(feature) != OBJ) || (!valid(feature)))
return E_INVARG;
"Not a valid object.";
endif
if ($code_utils:verb_or_property(feature, "feature_ok", this))
"The object is willing to be a feature.";
if (typeof(this.features) == LIST)
"If list, we can simply setadd the feature.";
this.features = setadd(this.features, feature);
else
"If not, we erase the old value and create a new list.";
this.features = {feature};
endif
"Tell the feature it's just been added.";
feature:feature_add(this);
return 1;
"We're done.";
else
return E_PERM;
"Feature isn't feature_ok.";
endif
else
return E_PERM;
"Caller doesn't have permission.";
endif
.
remove_feature:
"Remove a feature from this player's features list. Caller must be this, or have
permissions of this, a wizard, or feature.owner.";
"Returns true if successful, E_PERM if caller didn't have permission.";
feature = args[1];
if (((caller == this) || $perm_utils:controls(caller_perms(), this)) || (caller_perms()
== feature.owner))
if (typeof(this.features) == LIST)
"If this is a list, we can just setremove...";
this.features = setremove(this.features, feature);
"Otherwise, we leave it alone.";
endif
"Let the feature know it's been removed.";
feature:feature_remove(this);
return 1;
"We're done.";
else
return E_PERM;
"Caller didn't have permission.";
endif
.
@add-feature @addfeature: "Usage: @add-feature @remove-feature @rmfeature: "Usage: @remove-feature @features: "Usage: @features [ @features: "Usage: @features [ @memory:
stats = memory_usage();
if (!stats)
player:notify("Sorry, but no memory-usage statistics are available for this server.");
return;
endif
su = $string_utils;
player:notify("Block Size # In Use # Free Bytes In Use Bytes Free");
player:notify("---------- -------- -------- ------------ ----------");
nused = nfree = bytesused = bytesfree = 0;
kilo = 1024;
meg = kilo * kilo;
for x in (stats)
if (x[2..3] != {0, 0})
bsize = x[1];
if ((bsize % meg) == 0)
bsize = tostr(bsize / meg, " M");
elseif ((bsize % kilo) == 0)
bsize = tostr(bsize / kilo, " K");
endif
bused = x[1] * x[2];
bfree = x[1] * x[3];
player:notify(tostr(su:left(bsize, 10), " ", su:right(su:group_number(x[2]),
8), " ", su:right(su:group_number(x[3]), 8), " ", su:right(su:group_number(bused),
12), " ", su:right(su:group_number(bfree), 10)));
nused = nused + x[2];
nfree = nfree + x[3];
bytesused = bytesused + bused;
bytesfree = bytesfree + bfree;
endif
endfor
player:notify("");
player:notify(tostr(su:left("Totals:", 10), " ", su:right(su:group_number(nused),
8), " ", su:right(su:group_number(nfree), 8), " ", su:right(su:group_number(bytesused),
12), " ", su:right(su:group_number(bytesfree), 10)));
player:notify("");
player:notify(tostr("Total Memory Size: ", su:group_number(bytesused + bytesfree),
" bytes."));
.
@version:
player:notify(tostr("The MOO is currently running version ", server_version(), "
of the LambdaMOO server code."));
.
@uptime:
player:notify(tostr("The server has been up for ", $time_utils:english_time(time()
- $last_restart_time), "."));
.
@quit: boot_player(player); "-- argh, let the player decide; #3:disfunc() takes care of this --Rog"; "player:moveto(player.home)"; . examine_commands_ok: return this == args[1]; . is_listening: "return true if player is active. This verb is !d"; return typeof(idle_seconds(this)) != ERR; . moveto:
if (args[1] == #-1)
return E_INVARG;
this:notify("You are now in #-1, The Void. Type `home' to get back.");
endif
set_task_perms(caller_perms());
pass(@args);
.
announce*_all_but:
return this.location:(verb)(@args);
"temporarily let player:announce be noisy to player";
if (verb == "announce_all_but")
if (this in args[1])
return;
endif
args = args[2..length(args)];
endif
this:tell("(from within you) ", @args);
.
linewrap: "Return a true value if this needs linewrapping."; "default is true if .linelen > 0"; return this.linelen > 0; . @set-note-string @set-note-text:
"Usage: @set-note-{string | text} {#xx | #xx.pname}";
" ...lines of text...";
" .";
"";
"For use by clients' local editors, to save new text for a note or object property.
See $note_editor:local_editing_info() for details.";
set_task_perms(player);
text = $command_utils:read_lines();
if ((verb == "@set-note-string") && (length(text) <= 1))
text = text ? text[1] | "";
endif
if (spec = $code_utils:parse_propref(argstr))
o = toobj(spec[1]);
p = spec[2];
if ($object_utils:has_verb(o, vb = "set_" + p) && (typeof(e = o:(vb)(text)) !=
ERR))
player:tell("Set ", p, " property of ", o.name, " (", o, ") via :", vb, ".");
elseif (text != (e = o.(p) = text))
player:tell("Error: ", e);
else
player:tell("Set ", p, " property of ", o.name, " (", o, ").");
endif
elseif (typeof(note = $code_utils:toobj(argstr)) == OBJ)
e = note:set_text(text);
if (typeof(e) == ERR)
player:tell("Error: ", e);
else
player:tell("Set text of ", note.name, " (", note, ").");
endif
else
player:tell("Error: Malformed argument to ", verb, ": ", argstr);
endif
.
verb_sub:
"Copied from Generic Player Class With Additional Features of Dubious Utility (#7069):verb_sub
by ur-Rog (#6349) Tue Nov 10 15:03:38 1992 PST";
text = args[1];
if (a = $list_utils:assoc(text, this.verb_subs))
return a[2];
else
return $gender_utils:get_conj(text, this);
endif
.
ownership_quota:
if ($perm_utils:controls(caller_perms(), this))
return this.(verb);
else
return E_PERM;
endif
.
tell_lines:
lines = args[1];
if (typeof(lines) != LIST)
lines = {lines};
endif
if (this.gaglist || this.paranoid)
"Check the above first, default case, to save ticks. Paranoid gaggers are cost
an extra three or so ticks by this, probably a net savings.";
if (this:gag_p())
return;
endif
if (this.paranoid == 2)
z = this:whodunnit({@callers(), {player, "", player}}, {this, $no_one}, {})[3];
lines = {((("[start text by " + z.name) + " (") + tostr(z)) + ")]", @lines,
((("[end text by " + z.name) + " (") + tostr(z)) + ")]"};
elseif (this.paranoid == 1)
$paranoid_db:add_data(this, {{@callers(), {player, "
@lastlog:
"Copied from generic room (#3):@lastlog by Haakon (#2) Wed Dec 30 13:30:02 1992 PST";
if (dobjstr != "")
dobj = $string_utils:match_player(dobjstr);
if (!valid(dobj))
player:tell("Who?");
return;
endif
folks = {dobj};
else
folks = players();
endif
day = week = month = ever = never = {};
a_day = (24 * 60) * 60;
a_week = 7 * a_day;
a_month = 30 * a_day;
now = time();
for x in (folks)
when = x.last_connect_time;
how_long = now - when;
if ((when == 0) || (when > now))
never = {@never, x};
elseif (how_long < a_day)
day = {@day, x};
elseif (how_long < a_week)
week = {@week, x};
elseif (how_long < a_month)
month = {@month, x};
else
ever = {@ever, x};
endif
endfor
for entry in ({{day, "the last day"}, {week, "the last week"}, {month, "the last
30 days"}, {ever, "recorded history"}})
if (entry[1])
player:tell("Players who have connected within ", entry[2], ":");
for x in (entry[1])
player:tell(" ", x.name, " last connected ", ctime(x.last_connect_time),
".");
endfor
endif
endfor
if (never)
player:tell("Players who have never connected:");
player:tell(" ", $string_utils:english_list($list_utils:map_prop(never, "name")));
endif
.
set_linelength:
"Set linelength. Linelength must be an integer >= 10.";
"If wrap is currently off (i.e. linelength is less than 0), maintains sign. That
is, this function *takes* an absolute value, and coerces the sign to be appropriate.";
"If you want to override the dwimming of wrap, pass in a second argument.";
"returns E_PERM if not allowed, E_INVARG if linelength is too low, otherwise the
linelength.";
if ((caller != this) && (!$perm_utils:controls(caller_perms(), this)))
return E_PERM;
elseif (abs(len = args[1]) < 10)
return E_INVARG;
elseif (length(args) > 1)
this.linelen = len;
else
"DWIM here.";
this.linelen = (this.linelen > 0) ? len | (-len);
return len;
endif
.
set_pagelength:
"Set pagelength. Must be an integer >= 5, or 0 to turn pagelength off.";
"Returns E_PERM if you shouldn't be doing this, E_INVARG if it's too low, otherwise,
what it got set to.";
if ((caller != this) && (!$perm_utils:controls(caller_perms(), this)))
return E_PERM;
elseif (((len = args[1]) < 5) && (len != 0))
return E_INVARG;
else
return this.pagelen = len;
endif
.
set_home:
"set_home(newhome) attempts to change this.home to newhome";
"E_TYPE if newhome doesn't have a callable :accept_for_abode verb.";
"E_INVARG if newhome won't accept you as a resident.";
"E_PERM if you don't own this and aren't its parent.";
"1 if it works.";
newhome = args[1];
if ((caller == this) || $perm_utils:controls(caller_perms(), this))
if ($object_utils:has_callable_verb(newhome, "accept_for_abode"))
if (newhome:accept_for_abode(this))
return (typeof(e = this.home = args[1]) != ERR) || e;
else
return E_INVARG;
endif
else
return E_TYPE;
endif
else
return E_PERM;
endif
.
@unsub*scribe: "@unsubscribe [* @registerme: "@registerme as ctime: ":ctime([NUM time]) => STR as the function."; "May be hacked by players and player-classes to reflect differences in time-zone."; return ctime(@args); . send_self_netmail:
":send_self_netmail(msg [ ,from ])";
"return 0 if successful, otherwise error.";
if (!$perm_utils:controls(caller_perms(), this))
return E_PERM;
elseif (error = $network:invalid_email_address(this.email_address))
return "Invalid email address: " + error;
else
msg = args[1];
if (length(args) > 1)
from = args[2];
this:notify(tostr("Receiving mail from ", from:title(), " (", from, ") and
forwarding it to your .email_address."));
endif
oplayer = player;
player = this;
error = $network:sendmail(this.email_address, @msg);
if (error && (length(args) > 1))
this:notify(tostr("Mail sending failed: ", error));
endif
player = oplayer;
return error;
endif
.
@netforw*ard: "@netforward @@sendmail:
"Syntax: @@sendmail";
"This is intended for use with client editors. You probably don't want to try using
this command manually.";
"Reads a formatted mail message, extracts recipients, subject line and/or reply-to
header and sends message without going to the mailroom. Example:";
"";
"@@send";
"To: Rog (#4292)";
"Subject: random";
"";
"first line";
"second line";
".";
"";
"Currently, header lines must have the same format as in an actual message.";
set_task_perms(player);
if (args)
player:notify(tostr("The ", verb, " command takes no arguments."));
$command_utils:read_lines();
return;
elseif (this != player)
player:notify(tostr("You can't use ", this.pp, " ", verb, " verb."));
$command_utils:read_lines();
return;
endif
msg = $command_utils:read_lines();
end_head = ("" in msg) || (length(msg) + 1);
from = this;
subject = "";
replyto = "";
rcpts = {};
body = msg[end_head + 1..length(msg)];
for i in [1..end_head - 1]
line = msg[i];
if (index(line, "Subject:") == 1)
subject = $string_utils:trim(line[9..length(line)]);
elseif (index(line, "To:") == 1)
if (!(rcpts = $mail_agent:parse_address_field(line)))
player:notify("No recipients found in To: line");
return;
endif
elseif (index(line, "Reply-to:") == 1)
if ((!(replyto = $mail_agent:parse_address_field(line))) && $string_utils:trim(line[10..length(line)]))
player:notify("No address found in Reply-to: line");
return;
endif
elseif (index(line, "From:") == 1)
"... :send_message() bombs if designated sender != player ...";
if (!(from = $mail_agent:parse_address_field(line)))
player:notify("No sender found in From: line");
return;
elseif (length(from) > 1)
player:notify("Multiple senders?");
return;
endif
from = from[1];
elseif (i = index(line, ":"))
player:notify(tostr("Unknown header \"", line[1..i], "\""));
return;
else
player:notify("Blank line must separate headers from body.");
return;
endif
endfor
if (!rcpts)
player:notify("No To: line found.");
elseif (!(subject || body))
player:notify("Blank message not sent.");
else
player:notify("Sending...");
result = $mail_agent:send_message(from, rcpts, replyto ? subject | {subject, replyto},
body);
if (e = result && result[1])
if (length(result) == 1)
player:notify("Mail actually went to no one.");
else
player:notify(tostr("Mail actually went to ", $mail_agent:name_list(@listdelete(result,
1)), "."));
endif
else
player:notify(tostr((typeof(e) == ERR) ? e | ("Bogus recipients: " + $string_utils:from_list(result[2]))));
player:notify("Mail not sent.");
endif
endif
.
@keep-m*ail @keepm*ail: "@keep-mail [ my_match_recipient:
":my_match_recipient(string) => matches string against player's private mailing lists.";
if (!(string = args[1]))
return $nothing;
elseif (string[1] == "*")
string = string[2..length(string)];
endif
return $string_utils:match(string, this.mail_lists, "aliases");
.
expire_old_messages:
set_task_perms(caller_perms());
if (!$perm_utils:controls(caller_perms(), this))
return E_PERM;
elseif (0 >= (period = this:mail_option("expire") || $mail_agent.player_expire_time))
"...no expiration allowed here...";
return E_NACC;
elseif (!(curmsg = this:get_current_message(this)))
"No messages! Don't even try.";
return 0;
elseif (rmseq = $seq_utils:remove(this:unkept_msg_seq(), 1 + this:length_date_le(min(time()
- period, curmsg[2] - 86400))))
"... the 86400 is pure fudge...";
this:rm_message_seq(rmseq);
return this:expunge_rmm();
else
return 0;
endif
.
@age:
if ((dobjstr == "") || (dobj == player))
dobj = player;
else
dobj = $string_utils:match_player(dobjstr);
if (!valid(dobj))
$command_utils:player_match_failed(dobj, dobjstr);
return;
endif
endif
time = dobj.first_connect_time;
if (time == $maxint)
player:notify(tostr(dobj.name, " has never connected."));
elseif (time == 0)
player:notify(tostr(dobj.name, " first connected before initial connections were
being recorded."));
else
player:notify(tostr(dobj.name, " first connected on ", ctime(time)));
duration = time() - time;
if (duration < 86400)
notice = $string_utils:from_seconds(duration);
else
notice = $time_utils:english_time((duration / 86400) * 86400);
endif
player:notify(tostr($string_utils:pronoun_sub("%S %
@edit:
"Calls the verb editor on verbs, the note editor on properties, and on anything else
assumes it's an object for which you want to edit the .description.";
if (!args)
((player in $note_editor.active) ? $note_editor | $verb_editor):invoke(dobjstr,
verb);
elseif ($code_utils:parse_verbref(args[1]))
if (player.programmer)
$verb_editor:invoke(argstr, verb);
else
player:notify("You need to be a programmer to do this.");
player:notify("If you want to become a programmer, talk to a wizard.");
return;
endif
else
$note_editor:invoke(dobjstr, verb);
endif
.
erase_paranoid_data:
if (!($perm_utils:controls(caller_perms(), this) || (this == caller)))
return E_PERM;
else
$paranoid_db:erase_data(this);
endif
.
PROPERTY DATA:       features       previous_connection       mail_lists       email_address       last_disconnect_time       help       more_msg       linetask       linesleft       linebuffer       pagelen       _mail_task       owned_objects       linelen       current_folder       all_connect_places       last_connect_place       dict       messages_going       brief       responsible       lines       page_absent_msg       pq       pqc       page_origin_msg       page_echo_msg       mail_notify       mail_forward       edit_options       mail_options       current_message       messages       last_connect_time       ownership_quota       gender       prc       ppc       poc       psc       pr       pp       po       ps       home       password       gaglist       paranoid       display_options       verb_subs       first_connect_time       messages_kept       message_keep_date       size_quota CHILDREN: Everyman Basic Local PC Nymph Three Meep Chrysalis Nightfall Lachesis |