generic room (#3)

(an instance of Root Class made by The_Mayor)




VERB SOURCE CODE:

confunc:
this:look_self(player.brief);
this:announce(player.name, " has connected.");
.


disfunc:
fork (300)
    if ((((valid(player) && (!(player in connected_players()))) && ((player.last_connect_time 
+ 300) < time())) && (this != player.home)) && (player.location != player.home))
        fork (0)
            "This is forked so that it's protected from aborts due to errors in the 
player's :moveto verb.";
            if (player.location != player.home)
                move(player, $player_start);
            endif
        endfork
        start = player.location;
        player:moveto(player.home);
        if (player.location != start)
            start:announce("A gang of youths charge in, grab ", player.name, ", and 
quickly drag ", player.po, " out of sight.");
        endif
        if (player.location == player.home)
            player.home:announce("A gang of youths drag ", player.name, " in and 
roughly deposit ", player.po, ". They rummage around on ", player.pp, " body for 
a bit then run off.");
        endif
    endif
endfork
this:announce(player.name, " has disconnected.");
.


say:
player:tell("You say, \"", argstr, "\"");
this:announce(player.name, " says, \"", argstr, "\"");
.


emote:
if ((argstr != "") && (argstr[1] == ":"))
    this:announce_all(player.name, argstr[2..length(argstr)]);
else
    this:announce_all(player.name, " ", argstr);
endif
.


announce:
for dude in (setremove(this:contents(), player))
    dude:tell(@args);
endfor
.


match_exit:
what = args[1];
if (what)
    yes = $failed_match;
    for e in (this.exits)
        if (valid(e) && (what in {e.name, @e.aliases}))
            if (yes == $failed_match)
                yes = e;
            elseif (yes != e)
                return $ambiguous_match;
            endif
        endif
    endfor
    return yes;
else
    return $nothing;
endif
.


add_exit:
set_task_perms(caller_perms());
return (this.exits = setadd(this.exits, args[1])) != E_PERM;
.


tell_contents:
contents = args[1];
ctype = args[2];
if ((!this.dark) && (contents != {}))
    if (ctype == 0)
        player:tell("Contents:");
        for thing in (contents)
            player:tell("  ", thing:title());
        endfor
    elseif (ctype == 1)
        for thing in (contents)
            if (is_player(thing))
                player:tell(thing:title(), " is here.");
            else
                player:tell("You see ", thing:title(), " here.");
            endif
        endfor
    elseif (ctype == 2)
        player:tell("You see ", $string_utils:title_list(contents), " here.");
    elseif (ctype == 3)
        players = things = {};
        for x in (contents)
            if (is_player(x))
                players = {@players, x};
            else
                things = {@things, x};
            endif
        endfor
        if (things)
            player:tell("You see ", $string_utils:title_list(things), " here.");
        endif
        if (players)
            player:tell($string_utils:title_listc(players), (length(players) == 1) 
? " is" | " are", " here.");
        endif
    endif
endif
.


@exits:
if (!$perm_utils:controls(valid(caller_perms()) ? caller_perms() | player, this))
    player:tell("Sorry, only the owner of a room may list its exits.");
elseif (this.exits == {})
    player:tell("This room has no conventional exits.");
else
    for exit in (this.exits)
        player:tell(exit.name, " (", exit, ") leads to ", valid(exit.dest) ? exit.dest.name 
| "???", " (", exit.dest, ") via {", $string_utils:from_list(exit.aliases, ", "), 
"}.");
    endfor
endif
.


look_self:
player:tell(this:title());
if (!(args && args[1]))
    pass();
endif
this:tell_contents(setremove(this:contents(), player), this.ctype);
this:tell_exits();
.


acceptable:
what = args[1];
return this:is_unlocked_for(what) && (((this.free_entry || ((what == this.blessed_object) 
&& (task_id() == this.blessed_task))) || (what.owner == this.owner)) || ((typeof(this.residents) 
== LIST) && (what in this.residents)));
.


add_entrance:
set_task_perms(caller_perms());
return (this.entrances = setadd(this.entrances, args[1])) != E_PERM;
.


bless_for_entry:
if (caller in this.entrances)
    this.blessed_object = args[1];
    this.blessed_task = task_id();
endif
.


@entrances:
if (!$perm_utils:controls(valid(caller_perms()) ? caller_perms() | player, this))
    player:tell("Sorry, only the owner of a room may list its entrances.");
elseif (this.entrances == {})
    player:tell("This room has no conventional entrances.");
else
    for exit in (this.entrances)
        player:tell(exit.name, " (", exit, ") comes from ", valid(exit.source) ? 
exit.source.name | "???", " (", exit.source, ") via {", $string_utils:from_list(exit.aliases, 
", "), "}.");
    endfor
endif
.


go:
if ((!args) || (!(dir = args[1])))
    player:tell("You need to specify a direction.");
    return E_INVARG;
elseif (valid(exit = player.location:match_exit(dir)))
    exit:invoke();
    if (length(args) > 1)
        "Now give objects in the room we just passed through a chance to act.";
        suspend(0);
        player.location:go(@listdelete(args, 1));
    endif
elseif (exit == $failed_match)
    player:tell("You can't go that way (", dir, ").");
else
    player:tell("I don't know which direction `", dir, "' you mean.");
endif
.


l*ook:
if ((dobjstr == "") && (!prepstr))
    this:look_self();
elseif ((prepstr != "in") && (prepstr != "on"))
    if ((!dobjstr) && (prepstr == "at"))
        dobjstr = iobjstr;
        iobjstr = "";
    else
        dobjstr = dobjstr + (prepstr && ((dobjstr && " ") + prepstr));
        dobjstr = dobjstr + (iobjstr && ((dobjstr && " ") + iobjstr));
    endif
    dobj = this:match_object(dobjstr);
    if (!$command_utils:object_match_failed(dobj, dobjstr))
        dobj:look_self();
    endif
elseif (!iobjstr)
    player:tell(verb, " ", prepstr, " what?");
else
    iobj = this:match_object(iobjstr);
    if (!$command_utils:object_match_failed(iobj, iobjstr))
        if (dobjstr == "")
            iobj:look_self();
        elseif ((thing = iobj:match(dobjstr)) == $failed_match)
            player:tell("I don't see any \"", dobjstr, "\" ", prepstr, " ", iobj.name, 
".");
        elseif (thing == $ambiguous_match)
            player:tell("There are several things ", prepstr, " ", iobj.name, " one 
might call \"", dobjstr, "\".");
        else
            thing:look_self();
        endif
    endif
endif
.


announce_all:
for dude in (this:contents())
    dude:tell(@args);
endfor
.


announce_all_but:
text = listdelete(args, 1);
contents = this:contents();
for l in (args[1])
    contents = setremove(contents, l);
endfor
for listener in (contents)
    listener:tell(@text);
endfor
.


enterfunc:
object = args[1];
if (is_player(object))
    player = object;
    this:look_self(player.brief);
endif
if (object == this.blessed_object)
    this.blessed_object = #-1;
endif
.


exitfunc:
return;
.


remove_exit:
exit = args[1];
if (caller != exit)
    set_task_perms(caller_perms());
endif
return (this.exits = setremove(this.exits, exit)) != E_PERM;
.


remove_entrance:
exit = args[1];
if (caller != exit)
    set_task_perms(caller_perms());
endif
return (this.entrances = setremove(this.entrances, exit)) != E_PERM;
.


@add-exit:
set_task_perms(player);
if (!dobjstr)
    player:tell("Usage:  @add-exit ");
    return;
endif
exit = this:match_object(dobjstr);
if ($command_utils:object_match_failed(exit, dobjstr))
    return;
endif
if (!($exit in $object_utils:ancestors(exit)))
    player:tell("That doesn't look like an exit object to me...");
    return;
endif
dest = exit.dest;
source = exit.source;
if (dest == E_PERM)
    player:tell("You can't read the exit's destination to check that it's consistent!");
    return;
elseif (source == E_PERM)
    player:tell("You can't read that exit's source to check that it's consistent!");
    return;
elseif (source != this)
    player:tell("That exit wasn't made to be attached here; it was made as an exit 
from ", source.name, " (", source, ").");
    return;
elseif (((typeof(dest) != OBJ) || (!valid(dest))) || (!($room in $object_utils:ancestors(dest))))
    player:tell("That exit doesn't lead to a room!");
    return;
endif
if (!this:add_exit(exit))
    player:tell("Sorry, but you must not have permission to add exits to this room.");
else
    player:tell("You have added ", exit, " as an exit that goes to ", exit.dest.name, 
" (", exit.dest, ") via ", $string_utils:english_list(setadd(exit.aliases, exit.name)), 
".");
endif
.


@add-entrance:
set_task_perms(player);
if (!dobjstr)
    player:tell("Usage:  @add-entrance ");
    return;
endif
exit = this:match_object(dobjstr);
if ($command_utils:object_match_failed(exit, dobjstr))
    return;
endif
if (!($exit in $object_utils:ancestors(exit)))
    player:tell("That doesn't look like an exit object to me...");
    return;
endif
dest = exit.dest;
if (dest == E_PERM)
    player:tell("You can't read the exit's destination to check that it's consistent!");
    return;
elseif (dest != this)
    player:tell("That exit doesn't lead here!");
    return;
endif
if (!this:add_entrance(exit))
    player:tell("Sorry, but you must not have permission to add entrances to this 
room.");
else
    player:tell("You have added ", exit, " as an entrance that gets here via ", $string_utils:english_list(setadd(exit.aliases, 
exit.name)), ".");
endif
.


recycle:
"Make a mild attempt to keep people and objects from ending up in #-1 when people 
recycle a room";
if ((caller == this) || $perm_utils:controls(caller_perms(), this))
    "... first try spilling them out onto the floor of enclosing room if any";
    if (valid(this.location))
        for x in (this.contents)
            x:moveto(this.location);
        endfor
    endif
    "... try sending them home...";
    for x in (this.contents)
        if (is_player(x))
            if ((typeof(x.home) == OBJ) && valid(x.home))
                x:moveto(x.home);
            endif
            if (x.location == this)
                move(x, $player_start);
            endif
        elseif (valid(x.owner))
            x:moveto(x.owner);
        endif
    endfor
    pass(@args);
else
    return E_PERM;
endif
.


e east w west s south n north ne northeast nw northwest se southeast sw southwest u up d down:
exit = this:match_exit(verb);
if (valid(exit))
    exit:invoke();
elseif (exit == $failed_match)
    player:tell("You can't go that way.");
else
    player:tell("I don't know which direction `", verb, "' you mean.");
endif
.


@eject @eject! @eject!!:
set_task_perms(player);
if ($command_utils:object_match_failed(dobj, dobjstr))
    return;
elseif (dobj.location != this)
    player:tell(dobj.name, "(", dobj, ") is not here.");
    return;
elseif (!$perm_utils:controls(player, this))
    player:tell("You are not the owner of this room.");
    return;
elseif (dobj.wizard)
    player:tell("Sorry, you can't ", verb, " a wizard.");
    dobj:tell(player.name, " tried to ", verb, " you.");
    return;
endif
iobj = this;
player:tell(this:ejection_msg());
this:((verb == "@eject") ? "eject" | "eject_basic")(dobj);
if (verb != "@eject!!")
    dobj:tell(this:victim_ejection_msg());
endif
this:announce_all_but({player, dobj}, this:oejection_msg());
.


ejection_msg oejection_msg victim_ejection_msg:
return $string_utils:pronoun_sub(this.(verb));
.


accept_for_abode:
who = args[1];
return (valid(who) && ((this.free_home || $perm_utils:controls(who, this)) || ((typeof(residents 
= this.residents) == LIST) ? who in this.residents | (who == this.residents)))) && 
this:acceptable(who);
.


@resident*s:
if (!$perm_utils:controls(player, this))
    player:tell("You must own this room to manipulate the legal residents list.  
Try contacting ", this.owner.name, ".");
else
    if (typeof(this.residents) != LIST)
        this.residents = {this.residents};
    endif
    if (!dobjstr)
        "First, remove !valid objects from this room...";
        for x in (this.residents)
            if (!valid(x))
                player:tell("Warning: removing ", x, ", an invalid object, from the 
residents list.");
                this.residents = setremove(this.residents, x);
            endif
        endfor
        player:tell("Allowable residents in this room:  ", $string_utils:english_list($list_utils:map_prop(this.residents, 
"name"), "no one"), ".");
        return;
    elseif (dobjstr[1] == "!")
        notflag = 1;
        dobjstr = dobjstr[2..length(dobjstr)];
    else
        notflag = 0;
    endif
    result = $string_utils:match_player_or_object(dobjstr);
    if (!result)
        return;
    else
        "a one element list was returned to us if it won.";
        result = result[1];
        if (notflag)
            if (!(result in this.residents))
                player:tell(result.name, " doesn't appear to be in the residents 
list of ", this.name, ".");
            else
                this.residents = setremove(this.residents, result);
                player:tell(result.name, " removed from the residents list of ", 
this.name, ".");
            endif
        else
            if (result in this.residents)
                player:tell(result.name, " is already an allowed resident of ", this.name, 
".");
            else
                this.residents = {@this.residents, result};
                player:tell(result.name, " added to the residents list of ", this.name, 
".");
            endif
        endif
    endif
endif
.


match:
target = {@this:contents(), @this:exits()};
return $string_utils:match(args[1], target, "name", target, "aliases");
.


@remove-exit:
set_task_perms(player);
if (!dobjstr)
    player:tell("Usage:  @remove-exit ");
    return;
endif
exit = this:match_object(dobjstr);
if (!(exit in this.exits))
    if ($command_utils:object_match_failed(exit, dobjstr))
        return;
    endif
    player:tell("Couldn't find \"", dobjstr, "\" in the exits list of ", this.name, 
".");
    return;
elseif (!this:remove_exit(exit))
    player:tell("Sorry, but you do not have permission to remove exits from this 
room.");
else
    name = valid(exit) ? exit.name | "";
    player:tell("Exit ", exit, " (", name, ") removed from exit list of ", this.name, 
" (", this, ").");
endif
.


@remove-entrance:
set_task_perms(player);
if (!dobjstr)
    player:tell("Usage:  @remove-entrance ");
    return;
endif
entrance = $string_utils:match(dobjstr, this.entrances, "name", this.entrances, "aliases");
if (!valid(entrance))
    "Try again to parse it.  Maybe they gave object number.  Don't complain if it's 
invalid though; maybe it's been recycled in some nefarious way.";
    entrance = this:match_object(dobjstr);
endif
if (!(entrance in this.entrances))
    player:tell("Couldn't find \"", dobjstr, "\" in the entrances list of ", this.name, 
".");
    return;
elseif (!this:remove_entrance(entrance))
    player:tell("Sorry, but you do not have permission to remove entrances from this 
room.");
else
    name = valid(entrance) ? entrance.name | "";
    player:tell("Entrance ", entrance, " (", name, ") removed from entrance list 
of ", this.name, " (", this, ").");
endif
.


moveto:
if ((caller in {this, this.owner}) || $perm_utils:controls(caller_perms(), this))
    return pass(@args);
else
    return E_PERM;
endif
.


who_location_msg:
return (msg = this.(verb)) ? $string_utils:pronoun_sub(msg, args[1]) | "";
.


exits entrances:
if ((caller == this) || $perm_utils:controls(caller_perms(), this))
    return this.(verb);
else
    return E_PERM;
endif
.


obvious_exits:
"obvious_exits(FLAG)";
"FLAG=0 or not there - return all exits with .obvious>0";
"FLAG=1 - return all exits with .obvious=1";
"FLAG>=2 - return all exits with .obvious=2";
fl = 0;
if (args)
    fl = args[1] ? (args[1] == 1) ? args[1] | 2 | 0;
endif
exits = {};
for exit in (this.exits)
    if ((ob = exit:obvious()) && ((!fl) || (ob == fl)))
        exits = setadd(exits, exit);
    endif
endfor
return exits;
.


here_huh:
":here_huh(verb,args)  -- room-specific :huh processing.  This should return 1 if 
it finds something interesting to do and 0 otherwise; see $command_utils:do_huh.";
"For the generic room, we check for the case of the caller specifying an exit for 
which a corresponding verb was never defined.";
set_task_perms(caller_perms());
if (args[2] || ($failed_match == (exit = this:match_exit(verb = args[1]))))
    "... okay, it's not an exit.  we give up...";
    return 0;
elseif (valid(exit))
    exit:invoke();
else
    "... ambiguous exit ...";
    player:tell("I don't know which direction `", verb, "' you mean.");
endif
return 1;
.


room_announce*_all_but:
this:(verb[6..length(verb)])(@args);
.


examine_commands_ok:
return this == args[1].location;
.


examine_key:
"examine_key(examiner)";
"return a list of strings to be told to the player, indicating what the key on this 
type of object means, and what this object's key is set to.";
"the default will only tell the key to a wizard or this object's owner.";
who = args[1];
if (((caller == this) && $perm_utils:controls(who, this)) && (this.key != 0))
    return {tostr(this:title(), " will accept only objects matching the following 
key:"), tostr("  ", $lock_utils:unparse_key(this.key))};
endif
.


examine_contents:
"examine_contents(who)";
if (caller == this)
    this:tell_contents(this.contents, this.ctype);
endif
.


tell_exits:
"displays exits with obvious = 1 to player, ";
obexits_list = {};
for exit in (this:obvious_exits(1))
    obexits_list = listappend(obexits_list, (exit.name + " to ") + exit.dest.name);
endfor
if (obexits_list && this.exit_display)
    player:tell("Obvious exits: " + $string_utils:english_list(obexits_list));
endif
.


description:
"Adds on the exit integration messages, or :look_msg for each exit with .obvious=2. 
Adds a paragraph to the end of the description if it is a LIST of strings. Or tags 
onto the end if the description is a STR.";
desc = (f = pass(@args)) ? f | "You see nothing special.";
exmess = "";
for exit in (this:obvious_exits(2))
    exmess = (exmess + this.look_sep_msg) + exit:look_msg();
endfor
if ((typeof(desc) == STR) && exmess)
    desc = desc + exmess;
elseif (exmess)
    desc[length(desc)] = tostr(desc[length(desc)] + exmess);
endif
return desc;
.



PROPERTY DATA:
      who_location_msg
      free_home
      victim_ejection_msg
      ejection_msg
      oejection_msg
      residents
      free_entry
      entrances
      blessed_object
      blessed_task
      exits
      dark
      ctype
      look_sep_msg
      exit_display

CHILDREN:
Generic Editor River bank Zero Surface Cluttered Closet Crumbling Foundation Quonset Under The Rock Service Road North End of the Park riverrun The Disciple's Room Hovel mist filled cloud Z2 The Monkey House Z3 Somewhere lost Steps Camp Site Scorpion Nest East Jackson Treehouse Sanctuary The Annex The Lodge Maze maze maze maze maze maze maze The rusted hulk of Kerouac's Car. The Eye of Pan the shade Consumable Storage Room New York Flat The Abyss Drainage Ditch North Sanctuary Juxtaposition Cornea Little St. The Opium Den A Green Shade The Gymnasium Boy's Lockeroom footbridge BioLab coffing Burton's Bungalow nw grassy river bank Grassy River Bank Under the Ruins The Primal Chaos Square of Ruins The Barge topoi **Dj-CJ's Disco Tek** here mangrove Brian's Place Strap's Lockerroom allgemeiner Raum loft Forest Treehouse The Branches of Woody Willow Willow Grove Clearing Feline Forest Fox Terrace, Western side West Fox Terrace West Corner of The Park East Corner of The Park North Corner of The Park West Corner of The Park South Corner of The Park In the Pond a dark, unnamed alley Rhizome Myroom The Computer Screen A UNIX Directory TechnoTopia Axl's Mansion Heather's Haven Generic anonymous room Bathroom Training room Entrance Electric Godland generic integrating room thunk FirePlace Town Square TransPort Lobby Sea/Subterranean TransPort Aerospace TransPort TransPort Office Interdimensional TransPort Monorail TransPort Zariski Lighthouse Forest MedFaire Parking Lot Hotel Lobby Atrium Main Convention Hall Hotel Patio Changing Room/Showers Hot Tub here here Pool here Registration Homeless Shelter here Post Office Library Vestibule Government Street Government Street East Planning Office Police Station Prison Cell here West of Covenant Beach Covenant Beach here Northeast Covenant Beach King Street King Street Pebbly Walk Temple Entryway Administrative Concourse The Trash Bin Dark Tunnel Dark Tunnel Dark Tunnel Dark Tunnel Harv's Bargain Basement Sacrificial Pit Pit Ledge Moustapha's Auction Emporium Atop the Scaffold Crawlway King Street Shopping Center Intersection of King and Queen Streets Unicorn Point Unicorn Point Topiary Unicorn Point Gazebo Mountain Peak Midair Kiosk here Reference Room Encyclopedia Alcove Crowded Wooden Bridge here Under the Bridge here here Central Fairgrounds here Southern Fairgrounds here here here here Western Fairgrounds here here here here here Northern Fairgrounds here here Under Unicorn Point here here here here here here here here here here here here here here Crallway Corner here On the Ledge, Eastside On the Ledge, Northside On the Ledge, Southside here here here An Enigma A Dry Cave The Lotus Sunken TinyMUD Classic The Town Square The Temple of Arkteks-t'leep Junkpile THIS is the Rec Room!!!! In the Tub here here here here here here here Gully The Savior's Pad Sandbox goatpen Mina's Place Outside the Cave Sand Dune boardroom Marcus Garvey Tight Passageway Stopping Place Garden Underground Stomping Ground between a rock and a hard place Mom's Digs female dressing room Ground Floor Landing Second Floor Landing Hallway, Second Floor Third Floor Landing Hallway, Third Floor #19 Rich's Bungalo of Naughty Ideas 'Sweetheart's Room' The Greatest Deal A Big Spaceship The Ballroom Gene_Pool Indestructible_Object Arc The-Temple-of-Doom Generic Ambient Noise Room Stone Oasis Trans-Yuggothian Expressway Maid's Quarters Caged The Whipping Post a line Woods The Week Tibet Three story apartment house A drop of water The Last Page The Chandelier Cyberhutch within the looking glass alley Boathouse Boathouse Death's_Door Goat Pen The far north. Collapsed Subway Station Deep Sewer Inside the Box Athene Athene Sewer Sewer Den of Inequity Sewer riverden Gardening At Night FunLand stanza Kitchenette SunRay's Home Woodland Millebornes Game Promotional Plug a ditch The Velvet Edge Conference Room The Frying Pan Atomic Cafe Bitch Hideaway Acid-Rain-Glow Hut Razor's Edge. Moorishmaiden's mailbox Ancient Oak Tree RK's Place Cognito Helix of Semi-Precious Stones Egg of Inexistence Ein Spelunkhaus