Recycling Center (#62)

(an instance of generic thing made by Hacker)

     Object reuse. Call $recycler:_create() to create an object (semantics the same as 
create()), $recycler:_recycle() to recycle an object. Will create a new object if 
nothing available in its contents. Note underscores, to avoid builtin :recycle() 
verb called when objects are recycled. Uses $building_utils:recreate() to prepare 
objects.

Recycling Center contains Recyclable #2654, Recyclable #2191, Recyclable #2660, Recyclable #2522, Recyclable #2525, Recyclable #2647, Recyclable #2648 and Recyclable #2155.



VERB SOURCE CODE:

_recreate:
"Return a toad (child of #1, owned by $hacker) from this.contents.  Move it to #-1. 
 Recreate as a child of args[1], or of #1 if no args are given.  Chown to caller_perms() 
or args[2] if present.";
what = args ? args[1] | #1;
who = (length(args) == 2) ? args[2] | caller_perms();
if (!(caller_perms().wizard || (who == caller_perms())))
    return E_PERM;
elseif (!(valid(what) && is_player(who)))
    return E_INVARG;
elseif ((((who != what.owner) && (!what.f)) && (!who.wizard)) && (!caller_perms().wizard))
    return E_PERM;
endif
for potential in (this.contents)
    if (((potential.owner == $hacker) && (parent(potential) == $garbage)) && (!children(potential)))
        return this:setup_toad(potential, who, what);
    endif
endfor
return E_NONE;
.


_recycle:
"Take the object in args[1], and turn it into a child of #1 owned by $hacker.";
item = args[1];
if (!$perm_utils:controls(caller_perms(), item))
    $error:raise(E_PERM);
endif
this:addhist(caller_perms(), item);
if (is_player(item))
    $wiz_utils:unset_player(item);
endif
"...recreate can fail (:recycle can crash)...";
this:add_orphan(item);
$quota_utils:preliminary_reimburse_quota(item.owner, item);
$building_utils:recreate(item, $garbage);
this:remove_orphan(item);
"...";
$wiz_utils:set_owner(item, $hacker);
item.name = tostr("Recyclable ", item);
move(item, this);
.


_create:
e = set_task_perms(caller_perms());
if (typeof(e) == ERR)
    return e;
else
    val = this:_recreate(@args);
    return (val == E_NONE) ? $quota_utils:bi_create(@args) | val;
endif
.


addhist:
if (caller == this)
    h = this.history;
    if ((len = length(h)) > this.nhist)
        h = h[len - this.nhist..len];
    endif
    this.history = {@h, args};
endif
.


show*-history:
if ($perm_utils:controls(valid(caller_perms()) ? caller_perms() | player, this))
    for x in (this.history)
        pname = valid(x[1]) ? x[1].name | "A recycled player";
        oname = valid(x[2]) ? x[2].name | "recycled";
        player:notify(tostr(pname, " (", x[1], ") recycled ", x[2], " (now ", oname, 
")"));
    endfor
else
    player:notify("Sorry.");
endif
.


request:
dobj = valid(dobj) ? dobj | $string_utils:match_object(dobjstr, player.location);
if (!valid(dobj))
    dobj = (n = tonum(dobjstr)) ? toobj(n) | #-1;
endif
if (!valid(dobj))
    player:tell("Couldn't parse ", dobjstr, " as a valid object number.");
elseif (!(dobj in this.contents))
    player:tell("Couldn't find ", dobj, " in ", this.name, ".");
elseif ($object_utils:has_callable_verb(this, "request_refused") && (msg = this:request_refused(player, 
dobj)))
    player:tell("Sorry, can't do that:  ", msg);
else
    if (typeof(emsg = this:setup_toad(dobj, player, #1)) != ERR)
        dobj:moveto(player);
        dobj.aliases = {dobj.name = "Object " + tostr(dobj)};
        player:tell("You now have ", dobj, " ready for @recreation.");
        if (this.announce_removal_msg)
            player.location:announce($string_utils:pronoun_sub(this.announce_removal_msg));
        endif
    else
        player:tell(emsg);
    endif
endif
.


setup_toad:
"this:setup_toad(objnum,new_owner,parent)";
"Called by :_create and :request.";
if (caller != this)
    return E_PERM;
endif
potential = args[1];
who = args[2];
what = args[3];
if (!$quota_utils:creation_permitted(who))
    return E_QUOTA;
else
    $wiz_utils:set_owner(potential, who);
    move(potential, #-1);
    set_task_perms({@callers(), {#-1, "", player}}[2][3]);
    "... if :initialize crashes...";
    this:add_orphan(potential);
    $building_utils:recreate(potential, what);
    this:remove_orphan(potential);
    "... if we don't get this far, the object stays on the orphan list...";
    "... orphan list should be checked periodically...";
    return potential;
endif
.


add_orphan:
if (caller == this)
    this.orphans = setadd(this.orphans, args[1]);
endif
.


remove_orphan:
if (caller == this)
    this.orphans = setremove(this.orphans, args[1]);
endif
.


valid:
"Usage:  valid(object)";
"True if object is valid and not $garbage.";
return valid(args[1]) && (parent(args[1]) != $garbage);
.


init_for_core:
this.orphans = {};
this.history = {};
pass();
.


resurrect:
who = caller_perms();
if (!valid(parent = {@args, $garbage}[1]))
    return E_INVARG;
elseif (!who.wizard)
    return E_PERM;
elseif (typeof(o = renumber($quota_utils:bi_create(parent))) == ERR)
    "..death...";
elseif (parent == $garbage)
    $recycler:_recycle(o);
else
    o.aliases = {o.name = tostr("Resurrectee ", o)};
    $wiz_utils:set_owner(o, who);
    move(o, who);
endif
reset_max_object();
return o;
.



PROPERTY DATA:
      orphans
      announce_removal_msg
      nhist
      history