Dump of #7069 (Generic Player Class With Additional Features of Dubious Utility)

@create $prog named Generic Player Class With Additional Features of Dubious Utility:generic,programmer
@prop #7069."notify_huh" 1 rc
@prop #7069."contents_huh" 0 rc
@prop #7069."inward_xmit" 0 rc
"#7069.("respond_to") => E_PERM (Permission denied)
@prop #7069."move_passers" {} rc
@prop #7069."moved_by" {} rc
;;#7069.("moved_by") = {{{#102181, "shove", #117379, #102181, #117379}}, #117379, 1094697581}
@prop #7069."sessile" -1 rc
@prop #7069."look_sep_msg" "  " rc
@prop #7069."twitch_delay" 3 rc
@prop #7069."last_twitch" 0 r #78
@prop #7069."idle_msg" " stares off into the middle distance." rc
@prop #7069."twitch_threshold" 120 rc
@prop #7069."page_notify" 0 rc
"#7069.("witnessing") => E_PERM (Permission denied)
;;#7069.("rooms") = {{"Living", #17}, {"Dining", #28}, {"Library", #1670}, {"Pool", #1428}}
"#7069.("messages_going") => E_PERM (Permission denied)
"#7069.("current_message") => E_PERM (Permission denied)
"#7069.("messages") => E_PERM (Permission denied)
;;#7069.("features") = {#55317, #30203, #40842, #26787}
"#7069.("previous_connection") => E_PERM (Permission denied)
"#7069.("email_address") => E_PERM (Permission denied)
;;#7069.("help") = 0
"#7069.("linebuffer") => E_PERM (Permission denied)
"#7069.("current_folder") => E_PERM (Permission denied)
"#7069.("all_connect_places") => E_PERM (Permission denied)
"#7069.("last_connect_place") => E_PERM (Permission denied)
"#7069.("lines") => E_PERM (Permission denied)
"#7069.("ownership_quota") => E_PERM (Permission denied)
"#7069.("password") => E_PERM (Permission denied)
"#7069.("size_quota") => E_PERM (Permission denied)
"#7069.("last_password_time") => E_PERM (Permission denied)
"#7069.("last_connect_attempt") => E_PERM (Permission denied)
"#7069.("key") => E_PERM (Permission denied)
;;#7069.("aliases") = {"generic", "programmer"}
;;#7069.("description") = "You see a player who is probably remaining undescribed as a political statement. It has to be something like that."
;;#7069.("object_size") = {36961, 1141286549}

@verb #7069:"seek" any none none r #78
@program #7069:seek
"seek <player>   --  tries to enter <player>.location via an exit.";
set_task_perms(player);
if (valid(dobj))
  who = dobj;
else
  who = $string_utils:match_player(args[1]);
  if (length($command_utils:player_match_result(who, args[1])) == 1)
    return;
  endif
endif
from = player.location;
to = who.location;
if (!valid(to))
  player:tell(who.name, " is nowhere.");
  return;
elseif ($object_utils:isa(to, $generic_editor))
  player:tell(who.name, " is in ", to.name, ". You don't want to visit ", who.po, " there.");
  if (z = who in to.active)
    player:tell($string_utils:pronoun_sub(("%S should reappear in " + (to = to.original[z]).name) + " when %s %<has> finished editing. I'll send you there.", who));
  else
    player:tell($string_utils:pronoun_sub("Damned if I know what %s %<is> doing there, though. I give up.", who));
    return;
  endif
endif
obvious = {"n", "ne", "e", "se", "s", "sw", "w", "nw", "north", "northeast", "east", "southeast", "south", "southwest", "west", "northwest", "u", "d", "up", "down"};
reverse = {"s", "sw", "w", "nw", "n", "ne", "e", "se", "south", "southwest", "west", "northwest", "north", "northeast", "east", "southeast", "d", "u", "down", "up"};
out = en = $nothing;
for dir in (obvious)
  if ((!valid(out)) && (valid(y = from:match_exit(dir)) && y:is_unlocked_for(player)))
    out = y;
  endif
endfor
for d in [1..length(obvious)]
  if ((!valid(en)) && (valid(ex = to:match_exit(obvious[d])) && ($object_utils:isa(ex, $exit) && ((typeof(ex.dest) == OBJ) && ($object_utils:isa(ex.dest, $room) && (valid(y = ex.dest:match_exit(reverse[d])) && y:is_unlocked_for(player)))))))
    en = y;
  endif
endfor
if (valid(out))
  out:move(player);
endif
if (player.location != to)
  player.location:announce(this:title(), " leaves, of necessity by an ugly method.");
  if (valid(en))
    en:move(player);
  endif
  if (player.location != to)
    player:moveto(to);
    if (player.location != to)
      player:tell("You failed to seek out ", who.name, ".");
      player.location:announce(this:title(), " bounces off a topographic barrier, and into the room.");
    else
      to:announce(this:title(), " arrives, of necessity by an ugly method.");
    endif
  endif
endif
.

@verb #7069:"title" this none this
@program #7069:title
if ($list_utils:assoc("tell_contents", callers(), 2) && (msg = this:idle_suffix()))
  return tostr(pass(@args), " (", msg, ")");
else
  return pass(@args);
endif
.

@verb #7069:"@cor*rection" this none this rd #78
@program #7069:@correction
p = index(dobjstr, "+");
m = index(dobjstr, "/");
if ((p && m) || ((!p) && (!m)))
  player:tell("Usage: @correct <object>:<verb>/<line> to <code>");
  player:tell("   or: @correct <object>:<verb>+<line> to <code>");
  return;
elseif (p)
  k = p - 1;
else
  k = m - 1;
endif
vs = dobjstr[1..k];
line = tonum(dobjstr[k + 2..length(dobjstr)]);
if ((line < 0) || ((line == 0) && m))
  player:tell("Illegal line number");
endif
vl = $code_utils:parse_verbref(vs);
if (vl)
  OBJ = this.location:match_object(vl[1]);
  verb = vl[2];
else
  player:tell("Usage: @correct <object>:<verb>/<line> to <code>");
  player:tell("   or: @correct <object>:<verb>+<line> to <code>");
  return;
endif
code = verb_code(OBJ, verb);
text = "";
for foo in (args[3..length(args)])
  text = (text + " ") + foo;
endfor
if (p)
  code = {@code[1..line], text, @code[line + 1..length(code)]};
else
  code = {@code[1..line - 1], text, @code[line + 1..length(code)]};
endif
if (set_verb_code(OBJ, verb, code) == {})
  player:tell("Line corrected.");
else
  player:tell("Correction failed.");
endif
code = verb_code(OBJ, verb);
if (line < 5)
  s1 = 1;
else
  s1 = line - 3;
endif
if (line > (length(code) - 4))
  s2 = length(code);
else
  s2 = line + 3;
endif
for k in [s1..s2]
  player:tell($string_utils:right(tostr(k), 4), " : ", code[k]);
endfor
.

@verb #7069:"gear @gear" any none none rxd
@program #7069:gear
if (!args)
  sp = "";
  who = player;
elseif (length(args) == 1)
  sp = "";
  who = dobj;
else
  sp = args[2];
  who = args[1];
endif
player:tell((sp + $string_utils:left(who, length(tostr(max_object())) + 1)) + who.name);
for k in (who.contents)
  this:gear(k, "  " + sp);
endfor
.

@verb #7069:"page_echo_msg" this none this rxd #78
@program #7069:page_echo_msg
return pass(@args) + ((s = this:idle_suffix()) ? tostr("  ", this.name, " seems to be ", s, ", though.") | "");
.

@verb #7069:"idle_suffix" this none this
@program #7069:idle_suffix
if (!(this in connected_players()))
  return "asleep";
elseif ((z = idle_seconds(this)) > 3600)
  return ("out on " + this.pp) + " feet";
elseif (z > 600)
  return "dozing";
elseif (z > 180)
  return "daydreaming";
elseif (z > 60)
  return "distracted";
else
  return "";
endif
.

@verb #7069:"tell" this none this rx #67
@program #7069:tell
pass(@args);
if (((!$login:is_lagging()) && (player != this)) && ((caller in {this.location, this}) && ((this.twitch_delay >= 0) && ((this.twitch_threshold > 0) && ((this in connected_players()) && (((idle = idle_seconds(this)) > this.twitch_threshold) && ((time() - idle) > this.last_twitch)))))))
  text = tostr(@args);
  for y in (listinsert(this.aliases, this.name))
    if ($string_utils:index_delimited(text, y))
      this.last_twitch = time();
      fork (this.twitch_delay)
        if ((idle_seconds(this) > this.twitch_threshold) && (msg = this:idle_msg()))
          this.location:announce_all(this.name, msg);
        endif
      endfork
      return;
    endif
  endfor
endif
.

@verb #7069:"idle_msg" this none this
@program #7069:idle_msg
return this.(verb);
.

@verb #7069:"@que*ued_tasks" none none none rxd #78
@program #7069:@queued_tasks
set_task_perms(this);
tasks = queued_tasks();
if (tasks == {})
  this:tell("You have no queued tasks.");
else
  t = time();
  player:tell("----------------------------------------------------------------------------");
  for job in (tasks)
    name = strsub(job[7], "*", "");
    if (y = index(name, " "))
      name = name[1..y - 1];
    endif
    this:tell($string_utils:left(job[1], 10), $string_utils:right($time_utils:dhms(job[2] - time()), 12), "  ", $string_utils:left(valid(what = job[9]) ? what.name | "** recycled **", -19 + length(tostr(what))), " (", what, ")", $string_utils:right(job[6], 9), ":", name, " (", job[8], ")");
  endfor
  player:tell("----------------------------------------------------------------------------");
endif
.

@verb #7069:"alt_examine" any any any rxd #78
@program #7069:alt_examine
if (dobjstr == "")
  player:tell("Usage:  @examine <object>");
  return;
endif
what = player.location:match_object(dobjstr);
if (!$command_utils:object_match_failed(what, dobjstr))
  player:tell(what.name, " (", what, ") is owned by ", what.owner.name, " (", what.owner, ").");
  player:tell("Aliases:  ", $string_utils:english_list(what.aliases));
  desc = what:description();
  if (desc)
    player:tell_lines(what:description());
  else
    player:tell("(No description set.)");
  endif
  if ($perm_utils:controls(player, what))
    player:tell("Key:  ", $lock_utils:unparse_key(what.key));
  endif
  contents = what.contents;
  if (contents)
    player:tell("Contents:");
    for item in (contents)
      player:tell("  ", item.name, " (", item, ")");
    endfor
  endif
  name = what.name;
  if ((typeof(what.aliases) == LIST) && (what.aliases != {}))
    for alias in (what.aliases)
      if (length(alias) <= length(name))
        name = alias;
      endif
    endfor
  endif
  vrbs = {};
  commands_ok = what in {player, player.location};
  dull_classes = {$root_class, $room, $player, $prog};
  what = what;
  while (what != $nothing)
    if (!(what in dull_classes))
      for i in [0..length(verbs(what)) - 1]
        info = verb_info(what, tostr(i));
        syntax = verb_args(what, tostr(i));
        if (index(info[2], "r") && ((syntax[2..3] != {"none", "this"}) && (commands_ok || ("this" in syntax))))
          dobj = syntax[1];
          prep = syntax[2];
          iobj = syntax[3];
          if (syntax == {"any", "any", "any"})
            prep = "none";
          endif
          if (prep != "none")
            for x in ($string_utils:explode(prep, "/"))
              if (length(x) <= length(prep))
                prep = x;
              endif
            endfor
          endif
          "NOTE: Is this the correct way to handle verbs named *?";
          names = $string_utils:explode(info[3], " ");
          if ("*" in names)
            vname = "<anything>";
          else
            vname = $string_utils:from_list(names, "/");
          endif
          rest = "";
          if (prep != "none")
            rest = " " + ((prep == "any") ? "<anything>" | prep);
            if (iobj != "none")
              rest = (rest + " ") + ((iobj == "this") ? name | "<anything>");
            endif
          endif
          if (dobj != "none")
            rest = (" " + ((dobj == "this") ? name | "<anything>")) + rest;
          endif
          vrbs = setadd(vrbs, ("  " + vname) + rest);
        endif
      endfor
    endif
    what = parent(what);
  endwhile
  if (vrbs)
    player:tell("Obvious Verbs:");
    player:tell_lines(vrbs);
  endif
endif
.

@verb #7069:"@destroy" any any any rd #78
@program #7069:@destroy
dobj = player:my_match_object(dobjstr);
if (player != this)
  player:tell("Sorry, that @destroy command is off limits for you.");
  #15.destroy_abusers = listappend(#15.destroy_abusers, {player, this});
elseif (dobj == $nothing)
  player:notify(tostr("Usage:  ", verb, " <object>"));
elseif ($command_utils:object_match_failed(dobj, dobjstr))
  "...bogus object...";
elseif (player == dobj)
  player:notify("You don't *really* want to commit suicide, do you?");
else
  name = dobj.name;
  if (!$perm_utils:controls(this, dobj))
    this:tell(name, " (", dobj, ") belongs to ", dobj.owner.name, " (", dobj.owner, "), only they or a wizard can recycle it.");
    return;
  endif
  this:tell(name, " (", dobj, ") scheduled for recycling in sixty seconds. Type \"@rescue\" to save it.");
  #5586.going = setadd(#5586.going, dobj);
  set_task_perms(this);
  dobj:moveto(#5586);
  fork (60)
    if (valid(dobj))
      if (dobj in #5586.going)
        result = #4455:_recycle(dobj);
        if (typeof(result) == ERR)
          this:tell("Couldn't recycle ", name, ": ", result);
        else
          this:tell(name, " (", dobj, ") recycled.");
        endif
      elseif (dobj.location == #5586)
        dobj:moveto(this);
        if (dobj.location == this)
          s = "You now have";
        else
          s = ((dobj.location.name + " (") + tostr(dobj.location)) + ") now has";
        endif
        this:tell(s, " the rescued ", dobj.name, " (", dobj, ")");
      endif
      #5586:sweep();
    endif
  endfork
endif
.

@verb #7069:"@rescue" any any any rd #78
@program #7069:@rescue
c = 0;
objs = {};
for q in (args)
  if (valid(w = $string_utils:match(q, #5586.contents, "name", #5586.contents, "aliases")) || valid(this.location:match_object(q)))
    objs = setadd(objs, w);
  endif
endfor
for q in (#5586.going)
  if (this.wizard || (this == q.owner))
    if ((objs == {}) || (q in objs))
      c = c + 1;
      #5586.going = setremove(#5586.going, q);
      this:tell(q.name, " (", q, ") rescued.");
      if (this != q.owner)
        q.owner:tell(q.name, " (", q, ") rescued by ", this.name, ".");
      endif
    else
      this:tell(q.name, " (", q, ") left to its fate.");
    endif
  endif
endfor
this:tell(c, " objects rescued.");
.

@verb #7069:"@purge" any any any rd #78
@program #7069:@purge
c = 0;
objs = {};
for q in (args)
  if (valid(w = $string_utils:match(q, #5586.contents, "name", #5586.contents, "aliases")) || valid(this.location:match_object(q)))
    objs = setadd(objs, w);
  endif
endfor
for q in (#5586.going)
  if (this.wizard || (this == q.owner))
    if ((objs == {}) || (q in objs))
      c = c + 1;
      #5586.going = setremove(#5586.going, q);
      this:tell(q.name, " (", q, ") purged.");
      if (this != q.owner)
        q.owner:tell(q.name, " (", q, ") purged.");
      endif
      #4455:_recycle(q);
    endif
  endif
endfor
this:tell(c, " objects purged.");
.

@verb #7069:"look_self" this none this
@program #7069:look_self
player:tell(this:titlec());
c = i = {};
for k in (setremove(this:contents(), player))
  if ((y = this:ok(k)) > 0)
    i = {@i, k};
  elseif (!y)
    c = {@c, k};
  endif
endfor
player:tell_lines(this:description(@i));
if (!(this in connected_players()))
  player:tell($string_utils:alt_pronoun_sub("%S %<is> sleeping.", this));
elseif ((idle = idle_seconds(this)) < 60)
  player:tell($string_utils:alt_pronoun_sub("%S %<is> awake and %<looks> alert.", this));
else
  time = $string_utils:from_seconds(idle);
  player:tell($string_utils:alt_pronoun_sub(("%S %<is> awake, but %<has> been staring off into space for " + time) + ".", this));
endif
this:tell_contents(c);
.

@verb #7069:"ok" this none this
@program #7069:ok
"Stolen from #6792:ok()";
k = args[1];
if (y = $code_utils:verb_or_property(k, "carried_msg"))
  if (k.owner == this.owner)
    return (typeof(y) == STR) ? 1 | -1;
  elseif (typeof(y) != STR)
    return;
  endif
  for a in ({"%n", k.name, @k.aliases})
    if (index(y, a))
      return 1;
    endif
  endfor
endif
.

@verb #7069:"description" this none this
@program #7069:description
d = pass();
if (args == {})
  return d;
else
  s = ex = "";
  for k in (args)
    s = (s + ex) + $string_utils:pronoun_sub($object_utils:has_verb(k, "carried_msg") ? k:carried_msg() | k.carried_msg, this, k);
    ex = this.look_sep_msg;
  endfor
endif
if (typeof(d) == LIST)
  return listappend(d, s);
elseif (typeof(d) == STR)
  return (d + this.look_sep_msg) + s;
else
  return s;
endif
.

@verb #7069:"kill_exit" this none this rxd #78
@program #7069:kill_exit
"if this is a legit call, then player==cp. So the messages should go to the right place.";
set_task_perms(cp = caller_perms());
"if (length(callers()) != 1 || callers()[1][1] != this)";
"player:tell(\"Security violation.\");";
"else";
exit = args[1];
from = args[2];
to = args[3];
if (exit in from.exits)
  if ((from.owner != cp) && (!cp.wizard))
    player:tell("Can't remove ", exit.name, " (", exit, ") from exit list of ", from.name, " (", from, "). Ask ", from.owner.name, " (", from.owner, ")");
  else
    player:tell("Removed ", exit.name, " (", exit, ") from exit list of ", from.name, " (", from, "). Ask ", from.owner.name, " (", from.owner, ").");
    from.exits = setremove(from.exits, exit);
  endif
endif
if (exit in to.entrances)
  if ((to.owner != cp) && (!cp.wizard))
    player:tell("Can't remove ", exit.name, " (", exit, ") from entrance list of ", to.name, " (", to, "). Ask ", to.owner.name, " (", to.owner, ").");
  else
    player:tell("Removed ", exit.name, " (", exit, ") from entrance list of ", to.name, " (", to, ").");
    to.entrances = setremove(to.entrances, exit);
  endif
endif
if ((exit.owner != cp) && (!cp.wizard))
  player:tell("Can't recycle ", exit.name, " (", exit, "). Ask ", exit.owner.name, " (", exit.owner, ")");
else
  player:tell(exit.name + " (", exit, ") recycled.");
  cp:_recycle(exit);
endif
"endif";
.

@verb #7069:"@fill" any any any rd #78
@program #7069:@fill
if (valid(dobj))
  exit = dobj;
elseif (argstr)
  exit = this.location:match_exit(argstr);
else
  this:tell("Usage: @fill <exit-name>");
  this:tell("  recycles the exit named and eliminates it from the relevant lists in the rooms, and does the same for the reverse exit(s), if any.");
endif
if (!valid(exit))
  player:tell("I don't see that exit.");
  return;
endif
to = exit.dest;
back = {};
set_task_perms(player);
this:kill_exit(exit, this.location, to);
for foo in (to.exits)
  if (foo.dest == this.location)
    this:kill_exit(foo, to, this.location);
  endif
endfor
.

@verb #7069:"move_ok" this none this rxd #78
@program #7069:move_ok
if ((!valid(args[1])) && (args[1] != $nothing))
  return 0;
elseif (this.sessile <= 0)
  return 1;
else
  "We want to include the owner, but if we're in #-1, we want nothing.  So, we abuse list splicing.";
  ok = {this, @valid(this.location) ? {this.location.owner} | {}};
  by = listappend(callers(), {player, "", player});
  n = 1;
  exits = $object_utils:has_property(this.location, "exits") ? this.location.exits | {};
  while (((y = by[n])[1] == this) && (y[2] == "moveto"))
    n = n + 1;
  endwhile
  for k in (by[n..length(by)])
    if (k[3] in ok)
      return 1;
    elseif (!((k[3].wizard || (k[1] in exits)) || (k[3] in this.move_passers)))
      return 0;
    endif
  endfor
  return k[3].wizard || (player == this);
endif
.

@verb #7069:"moveto" this none this rxd #78
@program #7069:moveto
this.moved_by = this.sessile ? {callers(), player, time()} | {};
if (this:move_ok(@args))
  return pass(@args);
endif
.

@verb #7069:"@whom*ovedme" none none none rxd #78
@program #7069:@whomovedme
if (w = this.moved_by)
  who = w[2];
  this:tell("Task of ", $string_utils:from_seconds(time() - w[3]), " ago was initiated by ", valid(who) ? who.name | "(recycled)", " (", who, "), your moveto was");
  for k in (w[1])
    vrb = (z = index(k[2], " ")) ? k[2][1..z - 1] | k[2];
    vrb = strsub(vrb, "*", "");
    this:tell("called from: ", $string_utils:right(k[1], 6), ":", $string_utils:left(vrb, -15), " programmed by ", valid(who = k[3]) ? who.name | "(recycled)", " (", who, ")");
  endfor
  this:tell("(End of responsibility traceback.)");
else
  this:tell("I'm sorry, I didn't notice.");
endif
.

@verb #7069:"res*pond =*" any any any rxd #78
@program #7069:respond
if (typeof(r = this:respond_to()) == LIST)
  this:tell("Do you mean ", r[1].name, " or ", r[2].name, "?");
elseif (!valid(r))
  this:tell("Nobody to respond to.");
elseif (!(r in connected_players()))
  this:tell("Don't respond to ", r.name, " now, ", r.ps, "'s asleep.");
else
  text = ((length(verb) > 1) && (verb[1] == "=")) ? verb[2..length(verb)] + (argstr ? " " + argstr | "") | argstr;
  if (text)
    if (r:receive_page(tostr(this.name, " responds, \"", text, "\"")))
      this:tell("You respond to ", r.name, ".");
    else
      this:tell("Your response to ", r.name, " was refused.");
    endif
  elseif (r in connected_players())
    this:tell("You are ready to respond to ", r.name, ".");
  else
    this:tell("You would like to respond to ", r.name, ", but ", r.ps, "'s asleep.");
  endif
endif
.

@verb #7069:"wh*isper" any to this rxd #78
@program #7069:whisper
this:set_respond_to(player);
pass(@args);
.

@verb #7069:"@rel*ink" any any any rxd #78
@program #7069:@relink
if ((iobj != $nothing) && (!valid(iobj)))
  player:tell("Relink to where?");
elseif (!valid(out = player.location:match_exit(dobjstr)))
  player:tell("I don't understand \"", dobjstr, "\"");
elseif (!$object_utils:isa(out, $exit))
  player:tell(out.name, " (", out, ") isn't an exit. I think you better do this.");
elseif (out.owner != player)
  player:tell("You don't own ", out.name, " (", out, ").");
elseif (from.owner != player)
  player:tell("You don't own this room.");
elseif (!$object_utils:isa(iobj, $room))
  player:tell(iobj.name, " (", iobj, ") isn't a room.");
elseif (iobj.owner != player)
  player:tell("You don't own ", iobj.name, " (", iobj, ").");
else
  from = player.location;
  to = out.dest;
  if (out.source != from)
    player:tell(out.name, " (", out, ") doesn't have it's source here.");
  elseif (!(out in from.exits))
    player:tell(out.name, " (", out, ") isn't an exit from here.");
  elseif (!valid(to = out.dest))
    player:tell(out.name, " (", out, ") doesn't have a destination.");
  elseif (to.owner != player)
    player:tell("You don't own ", out.name, " (", out, ")'s destination, ", to.name, " (", to, ")");
  else
    back = {};
    for k in (to.exits)
      if ((valid(k) && $object_utils:isa(k, $exit)) && (k.dest == from))
        if (k.source != to)
          player:tell(k.name, " (", k, ") doesn't seem to come from ", to.name, " (", to, ").");
        elseif (k.owner != player)
          player:tell(k.name, "( ", k, ") is owned by ", valid(k.owner) ? k.owner.name | "** recycled ** ", " (", k.owner, ").");
        else
          back = listappend(back, k);
        endif
      endif
    endfor
    out.dest = iobj;
    iobj.entrances = setadd(iobj.entrances, out);
    to.entrances = setremove(to.entrances, out);
    player:tell("Redirected ", out.name, " (", out, ") to go to ", iobj.name, " (", iobj, ").");
    for k in (back)
      k.source = iobj;
      iobj.exits = setadd(iobj.exits, k);
      to.exits = setremove(to.exits, k);
      player:tell("Redirected ", k.name, " (", k, ") to come from ", iobj.name, " (", iobj, ").");
    endfor
  endif
endif
.

@verb #7069:"set_respond_to" this none this rxd #78
@program #7069:set_respond_to
who = args[1];
if ((typeof(this.respond_to) != LIST) || (length(this.respond_to) < 2))
  this.respond_to = {{$nothing, 0}, {who, time()}};
elseif (this.respond_to[2][1] == who)
  this.respond_to = {this.respond_to[1], {who, time()}};
else
  this.respond_to = {this.respond_to[2], {who, time()}};
endif
.

@verb #7069:"pose-old" any any any rxd
@program #7069:pose-old
if (index(verb, ".") == 1)
  text = (verb[2..length(verb)] + " ") + argstr;
else
  text = argstr;
endif
genders = {};
people = setremove(this.location.contents, player);
them = {this};
c = 0;
for k in ({"ps", "psc", "po", "poc", "pp", "ppc", "pr", "prc", "pq", "pqc"})
  for z in (people)
    if (index(text, this.(k)))
      genders = listappend(genders, {z, k, length(z.(k))});
    endif
  endfor
endfor
for z in (people)
  if (index(text, z.name))
    them = listappend(them, z);
    for k in (genders)
      if (this.(k) == z.(k))
        player:tell("Ambiguity: \"", this.(k), "\" refers to you or ", z.name, "?");
      endif
    endfor
  endif
endfor
genders = $list_utils:sort_alist(genders, 3);
for z in (people)
  out = text;
  if (z in them)
    sub = {{(". " + z.name) + "'s", ". Your"}, {(".  " + z.name) + "'s", ".  Your"}, {("\"" + z.name) + "'s", "\"Your"}, {z.name + "'s", "your"}, {". " + z.name, ". You"}, {".  " + z.name, ".  You"}, {"\"" + z.name, "\" You"}, {z.name, "you"}};
    for k in (genders)
      if (z == k[1])
        sub = listappend(sub, {z.k[2], $you.(k[2])});
      endif
    endfor
    out = $string_utils:substitute(text, sub);
    player:tell(z.name, " sees \"", player.name, " ", out, "\"");
  else
    out = text;
  endif
  z:tell(player.name, " ", out);
endfor
player:tell("You ", text);
.

@verb #7069:"verb_sub(old)" this none this rxd #78
@program #7069:verb_sub(old)
text = args[1];
return $string_utils:alt_pronoun_sub($string_utils:substitute_delimited(text, this.verb_subs, 1), this);
.

@verb #7069:"sub_tell" this none this rxd #78
@program #7069:sub_tell
";who:sub_tell([object,] args); where args are like those to tell()";
if (!args)
  this:tell();
elseif (typeof(args[1]) == OBJ)
  this:tell($string_utils:pronoun_sub(tostr(@listdelete(args, 1)), args[1]));
else
  this:tell($string_utils:pronoun_sub(tostr(@args), player));
endif
.

@verb #7069:"@abort" any any any rxd #78
@program #7069:@abort
set_task_perms(valid(c = caller_perms()) ? c | player);
if (argstr == "")
  player:tell("Usage: @abort [<object>][:<verb>]  (aborts queued tasks.)");
  return;
elseif (y = index(argstr, ":"))
  what = argstr[1..y - 1];
  vrb = argstr[y + 1..length(argstr)];
else
  what = argstr;
  vrb = "";
endif
n = (argstr == tostr(n = tonum(argstr))) ? n | -1;
it = toobj(what);
if (tostr(it) != what)
  it = $nothing;
endif
c = 1;
for y in (queued_tasks())
  if (((((((what == "") || (valid(y[6]) && (index(y[6].name, what) == 1))) || (valid(y[9]) && (index(y[9].name, what) == 1))) || (y[9] == it)) || (y[6] == it)) && ((vrb == "") || (index(" " + strsub(y[7], "*", ""), " " + vrb) == 1))) || (y[1] == n))
    player:tell("Killed ", y[1], "  (", y[9], ":", y[7], ")");
    kill_task(y[1]);
    c = 0;
  endif
endfor
if (c)
  this:tell("No such tasks in the queue.");
endif
.

@verb #7069:"my_huh" this none this rx #78
@program #7069:my_huh
permissions = (((caller == this) || $perm_utils:controls(caller_perms(), this)) && $command_utils:validate_feature(@args)) ? this | $no_one;
if (ret = pass(@args))
  return ret;
elseif (!this.contents_huh)
  return 0;
endif
verb = args[1];
pass = args[2];
what = $nothing;
plist = {"any", prepstr ? $code_utils:full_prep(prepstr) | "none"};
dlist = dobjstr ? {"any"} | {"none", "any"};
ilist = iobjstr ? {"any"} | {"none", "any"};
for fobj in (this.contents)
  if (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)))
      "if (this.notify_huh)";
      "player:notify(tostr(\"Using \", what.name, \" (\", what, \")\"));";
      "endif";
      set_task_perms(permissions);
      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're carrying too much stuff.  Parsing your command runs out of time at about ", fobj.name, " (", fobj, ").");
    return 1;
  endif
endfor
.

@verb #7069:"receive_page" this none this rxd #2487
@program #7069:receive_page
val = pass(@args);
if (val)
  "Page received if returned 1, refused if 0.";
  this:set_respond_to(player);
  notifies = (typeof(this.page_notify) == LIST) ? this.page_notify | setremove(setremove({@this:mail_notify(), @(typeof(this.mail_forward) == LIST) ? this.mail_forward | {}}, this), player);
  if (length(notifies) > $mail_agent.max_mail_notify)
    notifies = {};
  endif
  for who in (notifies)
    is = $gender_utils:get_conj("is", player);
    who:tell(player.name, " ", is, " paging ", this.name, ".");
  endfor
endif
return val;
.

@verb #7069:"move_ok(old)" this none this rxd #2487
@program #7069:move_ok(old)
if ((!valid(args[1])) && (args[1] != $nothing))
  return 0;
elseif (this.sessile <= 0)
  return 1;
else
  "We want to include the owner, but if we're in #-1, we want nothing.  So, we abuse list splicing.";
  ok = {this, @valid(this.location) ? {this.location.owner} | {}, @this.move_ok};
  by = listappend(callers(), {player, "", player});
  n = 1;
  exits = $object_utils:has_property(this.location, "exits") ? this.location.exits | {};
  while (((y = by[n])[1] == this) && (y[2] == "moveto"))
    n = n + 1;
  endwhile
  for k in (by[n + 1..length(by)])
    if (k[3] in ok)
      return 1;
    elseif (!((k[3].wizard || (k[1] in exits)) || (k[3] in this.move_passers)))
      return 0;
    endif
  endfor
  return k[3].wizard || (player == this);
endif
.

@verb #7069:"seek_arrive_msg seek_leave_msg seek_failed_msg" this none this
@program #7069:seek_arrive_msg
return $string_utils:pronoun_sub((index(l = player.(verb), "%n") ? "" | "%n ") + l);
.

@verb #7069:"tell(expensive)" this none this rx #24442
@program #7069:tell(expensive)
pass(@args);
if (this.inward_xmit && (((z = typeof(this.inward_xmit) == LIST) || (this.inward_xmit > 0)) || ($perm_utils:caller()[1] == this.location)))
  callers = $list_utils:slice(callers());
  for what in (this.contents)
    if ((!(what in callers)) && ((!z) || (what in this.inward_xmit)))
      what:tell(@args);
    endif
  endfor
endif
if (((((((player != this) && (caller in {this.location, this})) && (this.twitch_delay >= 0)) && (this.twitch_threshold > 0)) && (this in connected_players())) && ((idle = idle_seconds(this)) > this.twitch_threshold)) && ((time() - idle) > this.last_twitch))
  text = tostr(@args);
  for y in (listinsert(this.aliases, this.name))
    if ($string_utils:index_delimited(text, y))
      this.last_twitch = time();
      fork (this.twitch_delay)
        if (idle_seconds(this) > this.twitch_threshold)
          this.location:announce_all(this.name, this:idle_msg());
        endif
      endfork
      return;
    endif
  endfor
endif
.

@verb #7069:"title(old)" this none this
@program #7069:title(old)
c = callers();
while ((c != {}) && (c[1][1] in {this, $list_utils}))
  c = listdelete(c, 1);
endwhile
if (((c == {}) || (c[1][2] != "tell_contents")) || ((msg = this:idle_suffix()) == ""))
  return pass(@args);
else
  return ((pass(@args) + " (") + msg) + ")";
endif
.

@verb #7069:"my_huh(old)" this none this rd #6349
@program #7069:my_huh(old)
if ((caller != this) && (!$perm_utils:controls(caller_perms(), this)))
  return E_PERM;
endif
verb = args[1];
pass = args[2];
what = $nothing;
for y in (this.contents_huh ? $list_utils:remove_duplicates({@this.features, @this.contents}) | this.features)
  "for y in ({@this.features, @this.contents_huh ? this.contents | {}})";
  for v in [0..length(verbs(y)) - 1]
    info = verb_info(y, vrb = tostr(v));
    if (index(info[2], "x"))
      s = info[3];
      while (s)
        if (nspace = index(s, " "))
          ss = s[1..nspace - 1];
          s = s[nspace + 1..length(s)];
        else
          nspace = 1 + length(s);
          ss = s;
          s = "";
        endif
        nast = index(ss, "*");
        if (nast == (nspace - 1))
          q = index(verb, ss[1..nast - 1]) == 1;
        elseif (nast)
          q = (index(verb, ss[1..nast - 1]) == 1) && (index(ss[1..nast - 1] + ss[nast + 1..nspace - 1], verb) == 1);
        else
          q = verb == ss;
        endif
        if (q)
          template = verb_args(y, vrb);
          if (((((template[2] == "any") || ((prepstr == "") && (template[2] == "none"))) || index(("/" + template[2]) + "/", ("/" + prepstr) + "/")) && ((template[1] == "any") || ((template[1] == "none") && (dobjstr == "")))) && ((template[3] == "any") || ((template[3] == "none") && (iobjstr == ""))))
            if (valid(what))
              player:tell("I'm sorry, that's ambiguous. That command might be executable by either ", what.name, " (", what, ") or ", y.name, " (", y, ").");
              return 1;
            else
              s = "";
              what = y;
            endif
          endif
        endif
      endwhile
    endif
  endfor
endfor
if (valid(what))
  if (this.notify_huh)
    player:tell("Using ", what.name, " (", what, ")");
  endif
  set_task_perms(this);
  what:(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
.

@verb #7069:"my_huh(oldold)" this none this rd #24442
@program #7069:my_huh(oldold)
if ((caller != this) && (!$perm_utils:controls(caller_perms(), this)))
  return E_PERM;
endif
verb = args[1];
pass = args[2];
what = $nothing;
for y in (this.contents_huh ? $list_utils:remove_duplicates({@this.features, @this.contents}) | this.features)
  "for y in ({@this.features, @this.contents_huh ? this.contents | {}})";
  for v in [0..length(verbs(y)) - 1]
    info = verb_info(y, vrb = tostr(v));
    if (index(info[2], "x"))
      s = info[3];
      while (s)
        if (nspace = index(s, " "))
          ss = s[1..nspace - 1];
          s = s[nspace + 1..length(s)];
        else
          nspace = 1 + length(s);
          ss = s;
          s = "";
        endif
        nast = index(ss, "*");
        if (nast == (nspace - 1))
          q = index(verb, ss[1..nast - 1]) == 1;
        elseif (nast)
          q = (index(verb, ss[1..nast - 1]) == 1) && (index(ss[1..nast - 1] + ss[nast + 1..nspace - 1], verb) == 1);
        else
          q = verb == ss;
        endif
        if (q)
          template = verb_args(y, vrb);
          if (((((template[2] == "any") || ((prepstr == "") && (template[2] == "none"))) || index(("/" + template[2]) + "/", ("/" + prepstr) + "/")) && ((template[1] == "any") || ((template[1] == "none") && (dobjstr == "")))) && ((template[3] == "any") || ((template[3] == "none") && (iobjstr == ""))))
            if (valid(what))
              player:tell("I'm sorry, that's ambiguous. That command might be executable by either ", what.name, " (", what, ") or ", y.name, " (", y, ").");
              return 1;
            else
              s = "";
              what = y;
            endif
          endif
        endif
      endwhile
    endif
  endfor
endfor
if (valid(what))
  if (this.notify_huh)
    player:tell("Using ", what.name, " (", what, ")");
  endif
  set_task_perms(this);
  what:(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
.

@verb #7069:"respond_to" this none this rx #78
@program #7069:respond_to
"Who to respond to.";
"Return:";
"#-1 if no one to respond to.";
"{OBJ, OBJ} if someone different has paged within the last 30 seconds.";
"OBJ if unambiguous.";
who = args[1];
if ((caller == this) || $perm_utils:controls(caller_perms(), this))
  if (!valid(r = this.respond_to[2][1]))
    return #-1;
  elseif ((time() - this.respond_to[1][2]) < 30)
    return {r, this.respond_to[1][1]};
  else
    return r;
  endif
else
  return E_PERM;
endif
.

@verb #7069:"@db*size" none none none rd #2487
@program #7069:@dbsize
at_big_FO = #174;
player:tell("You really didn't want to use the @dbsize command.  It would go through all the possible object numbers, from #0 to ", max_object(), ", taking about ", at_big_FO.last_run_time, " minutes, and calculate how many valid and invalid numbers there are.  Let's just say there are about 20,000 invalid numbers.  Now you know, and we didn't lag telling you.  :-)");
.

@verb #7069:"receive_page(old)" this none this rxd #2487
@program #7069:receive_page(old)
"Copied from Generic Player Class With Additional Features of Dubious Utility (#7069):receive_page by Nosredna (#2487) Tue Jun  6 22:46:39 1995 PDT";
val = pass(@args);
if (val)
  "Page received if returned 1, refused if 0.";
  this:set_respond_to(player);
  for who in ((typeof(this.page_notify) == LIST) ? this.page_notify | setremove(setremove({@this.mail_notify, @this.mail_forward}, this), player))
    who:tell(player.name, " is paging ", this.name, ".");
  endfor
endif
return val;
.

"***finished***

