Dump of #10161 (Depeartment of Environmental Protection)

@create #258 named Department of Environmental Protection:Department of Environmental Protection,vacuum
@prop #10161."hah" {} rc
;;#10161.("hah") = {#155, #4038}
@prop #10161."armour" {} rc
;;#10161.("armour") = {#457, #1247, #2138, #20864, #20865}
@prop #10161."thrown" {} rc
;;#10161.("thrown") = {#10902, #3089, #8833, #8909}
@prop #10161."missiles" {} rc
;;#10161.("missiles") = {#8833, #8909}
@prop #10161."weapons" {} rc
;;#10161.("weapons") = {#76, #159, #243, #1394, #1454, #1660, #2231, #3791, #8751, #283, #20769, #20868}
@prop #10161."monsters" {} rc
;;#10161.("monsters") = {#1381, #3730, #3777, #4002, #4048, #1214, #8077, #17777, #19044, #4418, #13573, #4981, #10249, #16104, #21598, #15458, #7057, #5632, #26608, #35896, #52165, #40259, #2955, #42381, #53178, #53798, #45991, #31020, #45622, #40379, #40890, #51765, #51082, #44015, #55272, #6527, #8953, #50841, #36198, #20474, #48474, #22224, #7686, #39500, #16410, #53941, #53978, #22055, #51809, #57159, #56543, #61004, #9096, #102, #62858, #56299, #33020, #73468, #73054, #71798, #73373, #72883, #32401, #79574, #79214, #4142, #8954, #8952, #85990, #4677, #29929, #4375, #4186, #74798, #77819, #83797, #33931, #1383, #93374, #67730, #7151, #94799, #41501, #26450, #21252, #97587, #95558, #90796, #61620, #63670, #66635, #365, #819, #820, #1453, #2805, #2992, #3048, #3094, #3098, #3764, #3032, #3760, #3956, #4049, #4050, #7965, #10441, #11966, #2230, #15844, #15907, #15908, #15990, #12689, #86696, #103632, #73404, #58625, #87886, #88892, #83242, #8891, #1112, #20800, #1092, #69439, #66341, #104015, #98531, #1285, #1298, #1355, #1338, #1348, #1091, #1011, #76667, #87453, #1798, #1251, #9799, #9365, #7744, #75947, #52869, #4713, #1742, #6113, #5003, #4688, #12763, #1178, #1179, #79322, #1987, #2705, #2605, #41330, #15884, #63530, #52868, #61023, #1233, #1354, #71462, #15974, #40223, #6310, #5606, #5925, #79797, #5496, #12619, #92075, #34301, #7137, #7582, #2775, #3530, #5532, #6333, #6334, #10134, #54413, #2615, #5245, #48732, #43198, #110176, #2110, #2125, #2167, #2130, #2100, #2106, #2120, #2134, #2161, #2123, #2168, #3366, #85968, #15130, #13694, #13685, #13695, #13693, #11494, #26388, #222, #7666, #8887, #3007, #3511, #72141, #1654, #1877, #1864, #1875, #16595, #1978, #1974, #1966, #1902, #11500, #111994, #1263, #1264, #2009, #4777, #12098, #72796, #80113, #111613, #72018, #53628, #31745, #52484, #52304, #78224, #94515, #102680, #76481, #106254, #6330, #1157, #5141, #114923, #61225, #27745, #96256, #80660, #87390, #2081, #7416, #89468, #96286, #13692, #2248, #4785, #8365, #5488, #3592, #94167, #26263, #70900, #4946, #63454, #1698, #2089, #8651, #72739, #50011, #8942, #1377, #14523, #13545, #60384, #5236, #4849, #7794, #112666, #1975, #7366, #4122, #5619, #5690, #5916, #4448, #1599, #1633, #1677, #1844, #9477, #1753, #3646, #90644, #14297, #51060, #108282, #116088, #40495, #18039, #74774, #5067, #113666, #5485, #13761, #95522, #111919, #105896, #97427, #31400, #2275, #75602, #47746, #101666, #107666, #66752, #85317, #58057, #4104, #90719, #1952, #3176, #7990, #8721, #3083, #2025, #3156, #7064, #78972, #7661, #7993, #4696, #116667, #59892, #9595, #116602, #95336, #114031, #3614, #84448, #85888, #86888, #89888, #88444, #65556, #4293, #2011, #28361, #108264, #61905, #2461, #106729, #103138, #23080, #55525, #47845, #88315, #8920, #77919, #52904, #79012, #97164, #21175, #74293, #92603, #40122, #62049, #76525, #4746, #1635, #1694, #3455, #11968, #51097, #116671, #6941, #60404, #70505, #1201, #78878, #88288, #51946, #10469, #65245, #88223, #62009, #8718, #6713, #3659, #10573, #10826, #7430, #93545, #10911, #6876, #7890, #66601, #55035, #37403, #119167, #8262, #5145, #115078, #7537, #9020, #1725, #9456, #9590, #4385, #2188, #97553, #60277, #43789, #2109, #3606, #9330, #67090, #69605, #3439, #62126, #102692, #26264, #63686, #62395, #82643, #107799, #62803, #112302, #115533, #115544, #115577, #115599, #45301, #8229, #4370, #60066, #109758, #85246}
@prop #10161."threshold" 7776000 rc
@prop #10161."targets" {} rc
@prop #10161."objects" {} rc
;;#10161.("objects") = {#52828, #52833, #51553, #46232, #22361, #37163, #35734, #39717, #40354, #32208, #47882, #42808, #38110, #33838, #39280, #34604, #29924, #25313, #20788, #54004, #31156, #36484, #55345, #21094, #26848, #55546, #41748, #55486, #29881, #55839, #55804, #55825, #55926, #55942, #56127, #56166, #51624, #42092, #48046, #13133, #1389, #1397, #307, #168, #2078, #2244, #4039, #8844, #9358, #12446, #11485, #50619, #39313, #38059, #51768, #48233, #53888, #49779, #45021, #20132, #52737, #45259, #41567, #5618, #28806, #55360, #55451, #55550, #55495, #38567, #55501, #55580, #52435, #40975, #55544, #55588, #54282, #48800, #54076, #39223, #55596, #48172, #21714, #36854, #55239, #55484, #55760, #55759, #29200, #55821, #55849, #55774, #53115, #55883, #55956, #55799, #53713, #55952, #55992, #56018, #42813, #52974, #51364, #40070, #42977, #9730, #55909, #26275, #21129, #39253, #51985, #43852, #28513, #56188, #33329, #56233, #56218, #56236, #56220, #56219, #35025, #36299, #55373, #37351, #34364, #54710, #28400, #52147, #39441, #55618, #37240, #33968, #30138, #31573, #40021, #31016, #24200, #28401, #33417, #23388, #43121, #55431, #15753, #52073, #24353, #37750, #35439, #50219, #53366, #41759, #11352, #30680, #25842, #42246, #35867, #41701, #36160, #46030, #55561, #17530, #48946, #54045, #52267}
@prop #10161."cycle" 9000 rc
@prop #10161."protected" {} rc
@prop #10161."doomed" {} r
;;#10161.("doomed") = {#108604, #114536, #9066, #62224, #109758, #10611, #70749, #91457, #86723, #101508}
@prop #10161."cemetery" #1131 rc
@prop #10161."cycle_task" 1653831457 r
@prop #10161."reap_in_progress" 0 r
@prop #10161."rotten" {} r
;;#10161.("rotten") = {#70597}
@prop #10161."sweep_log" {} rc
;;#10161.("sweep_log") = {{1141624947, 1141624947, 4225, 9, 16, {{"morphic armour (#100597)", 0, {}}, {"Scroll of Adamantite (#114488)", 0, {#1131}}, {"red ribbons (#11036)", 5, {#65545}}, {"red ribbons (#28281)", 5, {#53781}}, {"red ribbons (#115960)", 5, {#24164}}, {"red ribbons (#117665)", 5, {#1048}}, {"red ribbons (#101461)", 5, {#17239, #8928, #22047}}, {"red ribbons (#70093)", 5, {#46025}}, {"red ribbons (#61208)", 5, {#24102, #8928, #22047}}}, 2, 1, {{"recycled", #114571, "Cairo's Voodoo Doll", #117278}, {"doomed", #114571, "Cairo's Voodoo Doll", #117278}, {"doomed", #7262, "Uriel's Voodoo Doll", #121946}}, 582}, {1141513767, 1141513768, 4215, 7, 22, {{"steel miner's pick (#69391)", 5, {#77440, #66133, #85872}}, {"grey cowled robe (#104492)", 5, {#100806, #96119}}, {"sandals (#111534)", 5, {#100806, #96119}}, {"red ribbons (#18586)", 5, {#38226}}, {"red ribbons (#90121)", 5, {#12757}}, {"red ribbons (#69087)", 5, {#49586}}, {"red ribbons (#74619)", 5, {#116688}}}, 1, 2, {{"recycled", #114571, "Cairo's Voodoo Doll", #117278}, {"recycled", #85486, "Gideon's Voodoo Doll", #109600}, {"doomed", #114571, "Cairo's Voodoo Doll", #117278}}, 582}, {1141394746, 1141394748, 4194, 12, 12, {{"giant club (#10711)", 0, {}}, {"collar (#7415)", 5, {#972, #8399}}, {"gauntlets (#116262)", 0, {#1131}}, {"o-yoroi (#94668)", 0, {}}, {"mint green potion (#43095)", 0, {}}, {"red ribbons (#17748)", 5, {#1048}}, {"red ribbons (#1782)", 5, {#2743, #854, #45765}}, {"red ribbons (#67353)", 5, {#9459}}, {"red ribbons (#117326)", 5, {#46025}}, {"red ribbons (#17976)", 5, {#24102, #8928, #22047}}, {"red ribbons (#77662)", 5, {#24164}}, {"red ribbons (#17574)", 5, {#46670}}}, 2, 2, {{"recycled", #114571, "Cairo's Voodoo Doll", #117278}, {"recycled", #102534, "Darkson's Voodoo Doll", #100806}, {"doomed", #114571, "Cairo's Voodoo Doll", #117278}, {"doomed", #85486, "Gideon's Voodoo Doll", #109600}}, 582}, {1141281477, 1141281478, 4218, 15, 391, {{"vambraces (#53458)", 0, {#1131}}, {"broadsword (#94873)", 0, {}}, {"giant club (#116621)", 0, {}}, {"vial of essence of water weird (#31421)", 5, {#101247}}, {"vial of essence of water weird (#12936)", 5, {#101247}}, {"vial of essence of water weird (#1730)", 5, {#101247}}, {"o-yoroi (#31014)", 0, {}}, {"grey cowled robe (#105134)", 5, {#24319}}, {"red ribbons (#46144)", 5, {#12757}}, {"red ribbons (#76794)", 5, {#49586}}, {"red ribbons (#91013)", 5, {#38226}}, {"red ribbons (#68151)", 5, {#53781}}, {"red ribbons (#107889)", 5, {#17239, #8928, #22047}}, {"red ribbons (#106196)", 5, {#11675}}, {"red ribbons (#84715)", 5, {#116688}}}, 2, 2, {{"recycled", #114571, "Cairo's Voodoo Doll", #117278}, {"recycled", #56356, "Rama's Voodoo Doll", #120283}, {"doomed", #114571, "Cairo's Voodoo Doll", #117278}, {"doomed", #102534, "Darkson's Voodoo Doll", #100806}}, 583}, {1141180108, 1141180109, 4220, 11, 18, {{"scythe (#119490)", 5, {}}, {"morphic armour (#87123)", 0, {}}, {"collar (#59973)", 5, {#972, #8399}}, {"steel miner's pick (#70520)", 5, {#77440, #66133, #85872}}, {"red ribbons (#111314)", 5, {#24164}}, {"red ribbons (#59815)", 5, {#1048}}, {"red ribbons (#52423)", 5, {#2743, #854, #45765}}, {"red ribbons (#53455)", 5, {#33644}}, {"red ribbons (#116181)", 5, {#46670}}, {"red ribbons (#82528)", 5, {#46025}}, {"red ribbons (#120790)", 5, {#24102, #8928, #22047}}}, 2, 2, {{"recycled", #114571, "Cairo's Voodoo Doll", #117278}, {"recycled", #107011, "Snowy's Voodoo Doll", #87867}, {"doomed", #114571, "Cairo's Voodoo Doll", #117278}, {"doomed", #56356, "Rama's Voodoo Doll", #120283}}, 584}}
@prop #10161."dumps" {} r
@prop #10161."dumpers" {} r
@prop #10161."warehouses" {} r
;;#10161.("warehouses") = {#175, #1138, #93337, #44938, #11561, #40553, #63560, #45309, #77404}
@prop #10161."doomed_dolls" {} r
;;#10161.("doomed_dolls") = {#114571, #7262}
@prop #10161."monster_stash_update_int" 86400 rc
@prop #10161."vault" #377 rc
"#10161.("orphans") => E_PERM (Permission denied)
@prop #10161."restart" #77 rc
@prop #10161."immortal" {} rc
;;#10161.("immortal") = {{#86050, 0}, {#106488, 0}, {#93228, 0}, {#117004, 0}, {#100337, 0}, {#63635, 0}, {#110586, 0}, {#116995, 0}, {#1449, 0}, {#55619, 0}, {#88395, 0}, {#104202, 0}, {#115397, 0}}
@prop #10161."backpack" #9350 rc
@prop #10161."next_reap" 1141724900 r
;;#10161.("blessed_exit") = {#2011, 2071541878}
"#10161.("misc_notes") => E_PERM (Permission denied)
"#10161.("magic_effects") => E_PERM (Permission denied)
"#10161.("combat_effects") => E_PERM (Permission denied)
"#10161.("unannounced") => E_PERM (Permission denied)
;;#10161.("teleport_object") = #2011
;;#10161.("teleport_task") = 2128548115
"#10161.("allowed_exits") => E_PERM (Permission denied)
;;#10161.("room_data") = {"structure"}
;;#10161.("dawn_msg") = ""
;;#10161.("night_msg") = ""
;;#10161.("dusk_msg") = ""
;;#10161.("day_msg") = ""
;;#10161.("delay") = 7200
"#10161.("entrances") => E_PERM (Permission denied)
;;#10161.("blessed_task") = 1406396582
"#10161.("exits") => E_PERM (Permission denied)
;;#10161.("ctype") = 5
"#10161.("key") => E_PERM (Permission denied)
;;#10161.("aliases") = {"Department of Environmental Protection", "vacuum"}
;;#10161.("description") = {"A pleasant room painted a deep forest green.  Potted plants abound, and you believe you hear monkeys chattering in the rafters.  A poster on the wall shows a cat dangling from a branch with the words \"Hang on!\" below it."}
;;#10161.("object_size") = {45013, 1141286561}

@verb #10161:"killable" this none this
@program #10161:killable
":killable(object) => True if object may be recycled.";
{what} = args;
if ((!valid(what)) || (parent(what) == $garbage))
  "... let GMs recycle invalid objects";
  return valid(what) ? what.owner == this.owner | 0;
elseif (what.owner != this.owner)
  return 0;
elseif (!valid(parent(what)))
  "... If an child of $nothing is recycled it will probably break some exitfuncs.  Just add it to the 'rotten' list for now.";
  this.rotten = setadd(this.rotten, what);
  return 0;
elseif (this:unique(what))
  "... Hey this is somethin' special.";
  return 0;
elseif (this:in_use(what))
  "... Somebody's using it.";
  return 0;
elseif (what.location in this.warehouses)
  "elseif ($object_utils:isa(what.location, #25476))";
  "... In an RPG-shop storeroom. Maybe add a .warehouses property later, but this'll do for now.";
  return 0;
else
  return 1;
endif
"DR 06-MAY-1995 -- Using in_use_test, a more correct (and hopefully bug free) version of the old, nasty in_use";
"Profane 15-MAR-95 13:06EST - Dunno what #25476 was supposed to be, but it's nothing now. Added warehouses stuff.";
"Slither 6/15/95 -- Got rid of the old in_use, and replaced it with what used to be in_use_test, so changed the reference here.";
"Profane 6-JAN-97 2017PST -- added valid() check, line 5, so truly invalid objects won't bomb out with tb";
.

@verb #10161:"cycle" this none this
@program #10161:cycle
if (((time() < this.next_reap) || $login.checkpoint_in_progress) || $code_utils:task_valid(this.cycle_task))
  return E_NONE;
elseif ($list_utils:iassoc("read_lines_escape", queued_tasks(), 7))
  return E_QUOTA;
elseif (caller_perms() == this.owner)
  force_input(this.owner, tostr("eval ", this, ":call_reap()"));
  "fork tid (0)";
  "  this.reap_in_progress = {time(), task_id()};";
  "  this:reap();";
  "  this.reap_in_progress = 0;";
  "  this.next_reap = (time() + 99999) - random(999);";
  "endfork";
  fork (5)
    $local.rpg.clock:check_cycles();
  endfork
  this.cycle_task = tid;
else
  return E_PERM;
endif
"Profane (#30788) - Sat Apr 14, 2001 - New paradigm. Called by enterfunc in the academy.";
"THX (#105941) - Sat Apr 14, 2001 - Just added a thingie to prevent this from going off during checkpoint.  Changed to .next_reap to speed up the intial check too.";
"THX (#105941) - Tue May 22, 2001 - Changed to force_input a call_reap() instead of forking the reap process.  This way G_M will be 'player' and will stop muchos complaints.  Check for read_lines_escape in queued_tasks() before forcing input too.";
.

@verb #10161:"cull_players" none none none rxd
@program #10161:cull_players
{?nn = 0} = args;
rpg = $local.rpg;
if (rpg:is_grandmaster(caller_perms()))
  player:tell("Length: ", len = length(rpg.pcs));
  t = time();
  for k in [1..len]
    n = (len + 1) - k;
    who = rpg.pcs[n];
    doll = rpg.dolls[n];
    if ((!valid(doll)) || (!$object_utils:isa(doll, rpg.doll)))
      rpg.dolls = listdelete(rpg.dolls, n);
      rpg.pcs = listdelete(rpg.pcs, n);
    elseif (doll.character != who)
      player:tell("Inconsistent: ", n);
      nn = nn - 1;
      if (nn < 0)
        return;
      endif
    elseif ((!valid(who)) || ((!is_player(who)) && (!$object_utils:has_callable_verb(who, "die"))))
      rpg.dolls = listdelete(rpg.dolls, n);
      rpg.pcs = listdelete(rpg.pcs, n);
      rpg.recycler:_recycle(doll);
    elseif (is_player(who) && ((doll.last_action + this.threshold) < t))
      rpg.dolls = listdelete(rpg.dolls, n);
      rpg.pcs = listdelete(rpg.pcs, n);
      rpg.recycler:_recycle(doll);
      player:tell("> ", who.name, " (", who, ")");
    elseif ((doll.last_action + this.threshold) < t)
      player:tell("* ", who.name, " (", who, ")");
    endif
    rpg:time_stop();
  endfor
endif
player:tell("Length: ", length(rpg.pcs));
"DR 30-NOV-94 -- Now test doll.last_action, not the player's last_connect.";
"If the person hasn't done any RPG stuff in .threshold time, they die.";
"Profane 13-MAY-96 515EST - change perms so only Grandmasters my cull players.";
.

@verb #10161:"cull_weapons" none none none rx
@program #10161:cull_weapons
"Disarm players who are dead and who haven't connected in a long time.  Out of paranoia, make sure the weapon is owned by Grand_Master.";
(rpg = $local.rpg):secure();
{G_M, threshold, o_u, now, thing, backpack} = {rpg.owner, this.threshold, $object_utils, time(), rpg.thing, this.backpack};
culls = {};
for p in (players())
  rpg:s_i_f_i_n();
  if (((p.last_connect_time + threshold) < now) && (!(p in rpg.pcs)))
    for target in (p.contents)
      if (o_u:isa(target, thing) && (target.owner == G_M))
        rpg:s_i_f_i_n();
        do_cull = 1;
        if (o_u:isa(target, backpack))
          "descend into it if it's a backpack in case its contents aren't RPG items.  If so, don't flush the pack either.";
          for item in (target.contents)
            if ((item.owner != G_M) || (!o_u:isa(item, thing)))
              do_cull = 0;
            endif
          endfor
        endif
        if (do_cull)
          culls = {target, @culls};
        endif
      endif
    endfor
  endif
endfor
for item in (culls)
  "move it somewhere random, let the regular vacuum cleaner sweep it up.";
  player:tell("Moving ", item:title(), "(", item, ") from ", item.location.name, "(", item.location, ")");
  item:moveto($nothing);
  rpg:s_i_f_i_n();
endfor
.

@verb #10161:"is_named_weapon" this none this
@program #10161:is_named_weapon
"return 1 if this object is a 'named' weapon, 0 if it is not.";
"Called by cull_weapons.";
target = args[1];
return ($object_utils:has_property(target, "title") ? target.title | 0) || ($object_utils:has_property(target, "crest") ? target.crest | 0);
.

@verb #10161:"reap" this none this
@program #10161:reap
":reap() -- Recycle all those damned weapons lying around.";
if (caller_perms() != this.owner)
  return E_PERM;
endif
start_time = time();
this.owner:tell(tostr(this, "> ", task_id(), " Beginning RPG Sweep ..."));
"Run the following scatter to prep a few variables that run inside the for loop.  This'll save a surprising number of ticks. - THX";
{rpg, o_u, c_u, s_u, rpg_doll, nothing} = {$local.rpg, $object_utils, $command_utils, $string_utils, $local.rpg.doll, $nothing};
scythe = rpg.recycler;
cemetery = this.cemetery;
owner = this.owner;
recycled = 0;
msg = {};
if (random(12) == 1)
  leaves = o_u:leaves_suspended(rpg.thing);
  leaves = {@leaves, @children(rpg.stat_sheet)};
  for t in (this.doomed)
    if (valid(t) && (t.owner == owner))
      "... do nothing ... ";
      rpg:s_i_n(1);
    else
      this.doomed = setremove(this.doomed, t);
    endif
  endfor
else
  leaves = {};
  for t in (rpg.dispenser.dispenses)
    leaves = {@leaves, @children(t)};
    rpg:s_i_n(1);
  endfor
endif
doomed = this.doomed;
for thing in (leaves)
  "...loop through all kids of adventure gear.";
  "...if killable and already doomed, recycle.";
  "...else, add to the doomed list.";
  rpg:s_i_f_i_n();
  if (this:killable(thing))
    if ((thing in doomed) || (thing.location in {nothing, cemetery}))
      locs = {};
      where = thing;
      while (valid(where = where.location))
        locs = {@locs, where};
      endwhile
      msg = {@msg, {s_u:nn(thing), thing in doomed, locs}};
      "Dump out the contents. Can't do this inna :recycle verb, since the";
      "thing is moved to $nowhere BEFORE :recycle is called.";
      for junk in (thing.contents)
        `junk:moveto(thing.location) ! ANY';
        rpg:s_i_f_i_n();
      endfor
      if (thing.owner == owner)
        `scythe:_recycle(thing) ! ANY';
      endif
      recycled = recycled + 1;
      doomed = setremove(doomed, thing);
      leaves = setremove(leaves, thing);
    else
      doomed = setadd(doomed, thing);
    endif
  else
    doomed = setremove(doomed, thing);
    if (`thing.last_action ! E_PROPNF => 0' && (thing.last_action < time()))
      (valid(loc = thing.location) && (loc.owner in rpg.gms)) && (thing.last_action = 0);
      thing.last_action && `((typeof(cond = thing.condition) == NUM) && ((thing.condition = cond - random(3)) < 1)) && thing:("break")() ! ANY';
    endif
  endif
endfor
this.doomed = doomed;
"this.rpg_things = leaves";
"Now, destroy all the doomed dolls that are still there";
doomed_dolls = this.doomed_dolls;
"Reset the doomed dolls list, to avoid race conditions";
this.doomed_dolls = {};
dollmsg = {};
dollsrecycled = 0;
for doll in (doomed_dolls)
  rpg:s_i_f_i_n();
  "make sure that the thing is still a doll, and still not on the dolls list";
  if (($recycler:valid(doll) && o_u:isa(doll, rpg_doll)) && (!(doll in rpg.dolls)))
    dollmsg = {@dollmsg, {"recycled", doll, doll.name, doll.character}};
    scythe:_recycle(doll);
    dollsrecycled = dollsrecycled + 1;
  endif
endfor
"Go through dolls list, seeing which ones can be doomed";
for doll in (o_u:descendants_suspended(rpg_doll))
  rpg:s_i_f_i_n();
  if (this:doll_reapable(doll))
    dollmsg = {@dollmsg, {"doomed", doll, doll.name, doll.character}};
    this:reap_doll(doll);
  endif
endfor
rpg:s_i_n();
this:clean_susa();
rpg:s_i_n();
info = {start_time, time(), length(leaves), recycled, length(doomed), msg, length(this.doomed_dolls), dollsrecycled, dollmsg, length(rpg.dolls)};
this.sweep_log = log = {info, @this.sweep_log};
this.sweep_log = log[1..min(5, length(log))];
this.owner:tell(tostr(this, "> ", task_id(), " Finished RPG Sweep.  Elapsed time: ", $time_utils:english_time(time() - start_time)));
"Profane 14-APR-95 20:45EST - Added contents dumping.";
"   (People were having their unclaimed packs reaped, thus dumping their nice";
"    claimed stuff in $nowhere, where it got rapidly auto-unclaimed and reaped.)";
"Slither July 5, 1995 -- removed check of .protected";
"                     -- added storage of .rpg_things";
"                     -- added destruction of doomed dolls, and doll reaping.";
"Irin Fri Nov  8 17:53:38 1996 PST -- Minor change to reap saved dolls.  We'll keep em for 3 months...";
"Irin Sat Mar 22 09:24:11 1997 PST -- Lets reap all dolls now.";
"THX 3-Dec-1997  -- Added code to clean Susa's stuff from doll-less players and $nowhere.  Added code to clean out this.doomed occasionally too ... doomed stuff sometimes gets smoked and rebuilt and is thus never doublechecked.";
"Profane (#30788) - Tue Dec 30, 1997 - add stat sheet sweeping to full reap check";
"THX1138 (#105941) - Tue Jun 16, 1998 - Added idle equipment (.last_action) code to break stuff that never gets used.";
.

@verb #10161:"clean_up" this none this
@program #10161:clean_up
":clean_up() => remove invalid stuff from various lists.";
if (!(caller_perms() in (rpg = $local.rpg).grand_masters))
  return E_PERM;
endif
len = length(rpg.gms);
for dude in (rpg.gms)
  if ((!$recycler:valid(dude)) || (!is_player(dude)))
    rpg.gms = setremove(rpg.gms, dude);
  endif
  $command_utils:suspend_if_needed(5, "Checking validity of all GMs. . .");
endfor
player:tell("Eliminated ", tostr(len - length(rpg.GMs)), " bad GMs.");
player:tell("Number of dolls before: ", tostr(len = length(rpg.dolls)));
for k in [1..len]
  n = (len + 1) - k;
  doll = rpg.dolls[n];
  if (((!$object_utils:isa(doll, rpg.doll)) || (!$recycler:valid(dude = doll.character))) || ((!is_player(dude)) && (!rpg:trusted_verb(dude, "die"))))
    rpg.dolls = listdelete(rpg.dolls, n);
    rpg.pcs = listdelete(rpg.pcs, n);
  endif
  $command_utils:suspend_if_needed(5, ("Checked " + tostr(k)) + " dolls. . .");
endfor
player:tell("Number of dolls after: ", tostr(length(rpg.dolls)));
this:update_monsters();
player:tell("Reset #10161.monsters");
rpg.spell_skill_object:update();
player:tell("Updated the subspells of the Forms and Techniques.");
len = length(this.protected);
for thing in (this.protected)
  if (!$object_utils:isa(thing, rpg.thing))
    this.protected = setremove(this.protected, thing);
  endif
  $command_utils:suspend_if_needed(5, "Checking validity of ~vacuum.protected objects. . .");
endfor
player:tell("Eliminated ", tostr(len - length(this.protected)), " bad .protected objects.");
len = length(this.doomed);
for thing in (this.doomed)
  if (!$object_utils:isa(thing, rpg.thing))
    this.doomed = setremove(this.doomed, thing);
  endif
  $command_utils:suspend_if_needed(5, "Checking validity of ~vacuum.doomed objects. . .");
endfor
player:tell("Eliminated ", tostr(len - length(this.doomed)), " bad .doomed objects.");
player:tell("Number of dumpers before: ", tostr(len = length(this.dumpers)));
for k in [1..len]
  n = (len + 1) - k;
  if (((!$recycler:valid(dude = this.dumpers[n])) || (!is_player(dude))) || (!$recycler:valid(this.dumps[n])))
    this.dumps = listdelete(this.dumps, n);
    this.dumpers = listdelete(this.dumpers, n);
  endif
  $command_utils:suspend_if_needed(5, ("Checked " + tostr(k)) + " dumpers. . .");
endfor
player:tell("Number of dumpers after: ", tostr(length(this.dumpers)));
for item in (k = rpg.recycler.rotten)
  if (!(item in rpg.owner.owned_objects))
    rpg.recycler.rotten = setremove(rpg.recycler.rotten, item);
  endif
endfor
player:tell("Removed ", tostr(length(k) - length(rpg.recycler.rotten)), " no-longer `rotten' objects from ~recycler.rotten.");
rpg.puzzle_log:clean_up();
for doll in (rpg.saved_dolls)
  if ((valid(doll) && (parent(doll) == rpg.doll)) && is_player(doll.character))
    "... do nothing ...";
  else
    rpg.saved_dolls = setremove(rpg.saved_dolls, doll);
    player:tell($string_utils:nn(doll), " removed from $local.rpg.saved_dolls.");
  endif
endfor
"Profane 6-APR-95 16:24EST -- Added.";
.

@verb #10161:"in_use" this none this
@program #10161:in_use
":in_use(OBJ thing, [OBJ deadly location, ... ]) => 0 if not in use, ";
"                                       or a positive value otherwise.";
"If an object is in a deadly location, it is always considered";
"not to be in use.";
{thing, ?ok_to_destroy_here = {$nothing}} = args;
" ... if the location is $nothing, axe it.  Thanks, Slither ... ";
if (valid(where = thing.location))
  pcs = (rpg = $local.rpg).pcs;
  if (valid(claimant = `thing:claimed_by() ! ANY => $nothing'))
    " ... if the thing is claimed and the person is still in the RPG ... ";
    if (claimant in pcs)
      " ... let it be considered in_use ... ";
      return 3;
    else
      thing:unclaim_for(claimant);
    endif
  endif
  while (valid(where))
    " ... if the thing is in a place the caller said was a `lethal zone' ... ";
    if (where in ok_to_destroy_here)
      " ... give it the kiss of death ... ";
      return 0;
    elseif (where in pcs)
      return is_player(where) ? 2 | 1;
    endif
    where = where.location;
  endwhile
else
  return 0;
endif
.

@verb #10161:"unique" this none this
@program #10161:unique
{y} = args;
rpg = $local.rpg;
if ((((valid(y) && (y.owner == rpg.owner)) && rpg.recycler:ok_to_recycle(y)) && (!`y.unique ! ANY => 0')) && (!(y in rpg.dispenser.dispenses)))
  return 0;
else
  return 1;
endif
"Quinn 08-OCT-93 0438: Added check for object being dispensed.";
"Slither 6/22/95 removed check that y.name == parent(y).name";
"THX (#105941) - Tue Apr 17, 2001 - made this more readable and used error-trapping instead of has_property.";
.

@verb #10161:"doll_reapable" this none this
@program #10161:doll_reapable
":doll_reapable(OBJ doll) => true if doll can be reaped";
{thing} = args;
rpg = $local.rpg;
"If doesn't exist, or isn't a G_M owned doll, forget about it";
if ((!$recycler:valid(thing)) || (!$object_utils:isa(thing, rpg.doll)))
  return 0;
elseif (thing.owner != this.owner)
  return 0;
endif
{threshold, time} = {this:threshold(thing), time()};
try
  "If the doll.character has a $garbage parent, nuke it.  - THX";
  "If character isn't a player or a monster, then reap!";
  if ((!valid(character = thing.character)) || (parent(character) == $garbage))
    return 1;
  elseif (!(thing in {@rpg.dolls, @rpg.saved_dolls}))
    return 1;
  elseif (is_player(character))
    if ((character in rpg.gms) && ((time - character.last_disconnect_time) < 10368000))
      thing.last_action = (time + 999) - threshold;
    elseif ((set = $list_utils:assoc(character, this.immortal)) && ((!set[2]) || (set[2] > time)))
      "... a 0 means permanent immortalization ...";
      "... otherwise, it's a time limit        ...";
      return 0;
    endif
    activity = thing.last_action + threshold;
    if ((thing in rpg.dolls) && ("notifyreap" in thing.rpg_options))
      if ((time > (activity - 610000)) && (time < (activity - 480000)))
        (caller == this) && $mail_agent:send_message(this, {thing.character}, "Imminent Doll Reap Alert", {"The LambdaRPG core has determined that your voodoo doll will be reaped due to inactivity at the end of one week."});
      endif
    endif
    return (activity < time) || ((!(thing in rpg.dolls)) && (!(thing in rpg.saved_dolls)));
  else
    return (`character.doll ! ANY => $nothing' != thing) || (!(character in rpg.pcs));
  endif
except (ANY)
  return 0;
endtry
"July 3, 1995  Slither -- first version";
"THX 30-Mar-1997 -- Added a check that keeps gm dolls alive if they've logged in within the past 4 months.";
"Mooshie (#106469) - Fri May 28, 1999 - Added check for Immortalized players.";
"THX (#105941) - Thu Sep 28, 2000 - Use this:threshold(doll) rather than this.threshold to allow longer idle times if the player has put a lot of work into the doll.";
.

@verb #10161:"reap_doll" this none this
@program #10161:reap_doll
":reap_doll(OBJ doll) => true if successful   may suspend";
"Removes a doll from the database, and prepares it to be recycled.";
{doll} = args;
if (caller_perms() != this.owner)
  return E_PERM;
elseif (!$object_utils:isa(doll, (rpg = $local.rpg).doll))
  return E_INVARG;
endif
rpg:s_i_n(0);
for t in (doll.armour_effects)
  if (parent(t) == rpg.doll)
    doll:remove_teammate(t);
    t:remove_teammate(doll);
  endif
endfor
"remove any claims";
for item in (doll.claimed_objects)
  rpg:s_i_f_i_n();
  (valid(claimant = `item.claimed_by ! ANY => $nothing') && (claimant == doll.character)) && item:unclaim_for(claimant);
endfor
"remove from database";
result = rpg:rm_doll(doll);
if (typeof(result) != ERR)
  this.doomed_dolls = {@this.doomed_dolls, doll};
  return 1;
else
  return 0;
endif
"July 3, 1995  Slither -- first version";
"THX (#105941) - Wed May 10, 2000 - Added teammate removal.";
.

@verb #10161:"description" this none this
@program #10161:description
base = pass(@args);
base = (typeof(base) == LIST) ? base | {base};
books = {};
for thingy in (this.contents)
  if ($object_utils:isa(thingy, $note))
    books = {@books, thingy};
  endif
endfor
if (books)
  munge = ($string_utils:title_list(books) + ((length(books) == 1) ? " lies" | " lie")) + " on Harvey's desk.";
  return {@base, $string_utils:capitalise(munge)};
else
  return base;
endif
.

@verb #10161:"tell_contents" this none this
@program #10161:tell_contents
for thingy in (args[1])
  if ($object_utils:isa(thingy, $note))
    args[1] = setremove(args[1], thingy);
  endif
endfor
return pass(@args);
.

@verb #10161:"clean_susa" this none this
@program #10161:clean_susa
"Swiped from THX_utils (99799):clean_susa by THX (105941) Wed Dec  3 10:42:48 1997 PST";
(rpg = $local.rpg):secure();
ok = {@rpg.gms, @rpg.pcs};
moolah = $object_utils:descendants(rpg.money);
{c_u, s_u} = {$command_utils, $string_utils};
{turf, dispenser, vault} = {rpg.cemetery.turf[1], rpg.gem_dispenser, this.vault};
relax = 2 + rpg.gm_lag;
for t in (children(rpg.gem))
  if (valid(loc = t.location) && (loc.owner in ok))
    "... do nothing ...";
  else
    if (((value = t:get_true_value()) > 0) && (value < 200))
      t:moveto(vault);
    else
      t:moveto(dispenser);
    endif
  endif
  c_u:suspend_if_needed(relax);
endfor
relax = 2 + rpg.gm_lag;
for s in (moolah)
  if (valid(loc = s.location) && (loc.owner in ok))
    "... do nothing ...";
  else
    s:set_quantity(min(s.quantity, 100));
    s:moveto(s.quantity ? vault | turf);
  endif
  c_u:suspend_if_needed(relax);
endfor
.

@verb #10161:"update_monsters" this none this
@program #10161:update_monsters
(rpg = $local.rpg):secure();
possible = $object_utils:descendents_suspended(rpg.monster);
monsters = {};
for t in (rpg.pcs)
  (t in possible) && (monsters = {@monsters, t});
endfor
this.monsters = monsters;
.

@verb #10161:"back_in_play" this none this
@program #10161:back_in_play
(rpg = $local.rpg):secure();
gms = rpg.gms;
for t in (this.orphans)
  if (valid(t) && (t.owner in gms))
    valid(t.location) || t:moveto(this.restart);
  endif
  this.orphans = setremove(this.orphans, t);
endfor
for stuff in (args)
  (valid(stuff) && (stuff.owner in gms)) && (this.orphans = {@this.orphans, stuff});
endfor
.

@verb #10161:"dispose" none none none rxd
@program #10161:dispose
":dis*pose -- Recycle all those weapons lying useless in the Cemetery.";
(rpg = $local.rpg):secure_x();
n = 0;
c_u = $command_utils;
recycler = rpg.recycler;
cemetery = this.cemetery;
gm = player in rpg.gms;
if (howmany = length(doomed = cemetery:contents()))
  for k in (doomed)
    if (this:killable(k))
      c_u:suspend_if_needed(rpg.gm_lag, gm ? tostr("...~vacuum:dispose Suspending after checking ", n, "/", howmany, " objects.") | "");
      n = n + 1;
      recycler:_recycle(k);
    endif
  endfor
  gm && player:tell("[", n, "] objects cleared from ", $string_utils:nn(cemetery), ".");
else
  gm && player:tell("There isn't any RPG equipment in ", $string_utils:nn(cemetery), " waiting to be destroyed.");
endif
.

@verb #10161:"threshold" this none this
@program #10161:threshold
{doll} = args;
$local.rpg:secure();
return max(this.(verb), ((doll.total - 350) + max(doll.melee, doll.magic_theory)) * 99999);
.

@verb #10161:"cycle(old)" this none this
@program #10161:cycle(old)
"Fork once a day, this.cycle seconds past midnight.";
"Fork off the actual :reap, in case something messes it up.";
if (caller_perms() == this.owner)
  fork tid (#2487:time_til_midnite() + this.cycle)
    fork (0)
      this.reap_in_progress = {time(), task_id()};
      this:reap();
      this.reap_in_progress = 0;
    endfork
    fork (5)
      $local.rpg.clock:check_cycles();
    endfork
    this:cycle();
  endfork
  this.cycle_task = tid;
else
  return E_PERM;
endif
"DR 30-NOV-94 -- Modified to reap just once a day, at a low-lag time.";
"Profane 5-AUG-96 1558PDT -- Added call to :check_cycles.";
.

@verb #10161:"call_reap" this none this
@program #10161:call_reap
if (caller_perms() == this.owner)
  fork tid (0)
    this.reap_in_progress = {time(), task_id()};
    this:reap();
    this.reap_in_progress = 0;
    this.next_reap = (time() + 99999) - random(999);
  endfork
endif
.

@verb #10161:"orphans" this none this
@program #10161:orphans
$local.rpg:secure();
return this.orphans;
.

"***finished***