dw_fluffos_v2/
dw_fluffos_v2/fluffos-2.9-ds2.05/
dw_fluffos_v2/fluffos-2.9-ds2.05/ChangeLog.old/
dw_fluffos_v2/fluffos-2.9-ds2.05/Win32/
dw_fluffos_v2/fluffos-2.9-ds2.05/compat/
dw_fluffos_v2/fluffos-2.9-ds2.05/compat/simuls/
dw_fluffos_v2/fluffos-2.9-ds2.05/include/
dw_fluffos_v2/fluffos-2.9-ds2.05/testsuite/
dw_fluffos_v2/fluffos-2.9-ds2.05/testsuite/clone/
dw_fluffos_v2/fluffos-2.9-ds2.05/testsuite/command/
dw_fluffos_v2/fluffos-2.9-ds2.05/testsuite/data/
dw_fluffos_v2/fluffos-2.9-ds2.05/testsuite/etc/
dw_fluffos_v2/fluffos-2.9-ds2.05/testsuite/include/
dw_fluffos_v2/fluffos-2.9-ds2.05/testsuite/inherit/
dw_fluffos_v2/fluffos-2.9-ds2.05/testsuite/inherit/master/
dw_fluffos_v2/fluffos-2.9-ds2.05/testsuite/log/
dw_fluffos_v2/fluffos-2.9-ds2.05/testsuite/single/
dw_fluffos_v2/fluffos-2.9-ds2.05/testsuite/single/tests/compiler/
dw_fluffos_v2/fluffos-2.9-ds2.05/testsuite/single/tests/efuns/
dw_fluffos_v2/fluffos-2.9-ds2.05/testsuite/single/tests/operators/
dw_fluffos_v2/fluffos-2.9-ds2.05/testsuite/u/
dw_fluffos_v2/fluffos-2.9-ds2.05/tmp/
dw_fluffos_v2/fluffos-2.9-ds2.05/windows/
dw_fluffos_v2/lib/
dw_fluffos_v2/lib/binaries/cmds/
dw_fluffos_v2/lib/binaries/cmds/creator/
dw_fluffos_v2/lib/binaries/cmds/living/
dw_fluffos_v2/lib/binaries/cmds/player/
dw_fluffos_v2/lib/binaries/d/admin/obj/
dw_fluffos_v2/lib/binaries/d/liaison/
dw_fluffos_v2/lib/binaries/global/virtual/
dw_fluffos_v2/lib/binaries/global/virtual/setup_compiler/
dw_fluffos_v2/lib/binaries/obj/handlers/autodoc/
dw_fluffos_v2/lib/binaries/obj/handlers/terrain_things/
dw_fluffos_v2/lib/binaries/obj/misc/
dw_fluffos_v2/lib/binaries/obj/misc/buckets/
dw_fluffos_v2/lib/binaries/obj/monster/
dw_fluffos_v2/lib/binaries/obj/reactions/
dw_fluffos_v2/lib/binaries/obj/reagents/
dw_fluffos_v2/lib/binaries/secure/cmds/creator/
dw_fluffos_v2/lib/binaries/secure/master/
dw_fluffos_v2/lib/binaries/std/
dw_fluffos_v2/lib/binaries/std/dom/
dw_fluffos_v2/lib/binaries/std/effects/object/
dw_fluffos_v2/lib/binaries/std/guilds/
dw_fluffos_v2/lib/binaries/std/languages/
dw_fluffos_v2/lib/binaries/std/races/
dw_fluffos_v2/lib/binaries/std/room/
dw_fluffos_v2/lib/binaries/std/room/basic/
dw_fluffos_v2/lib/binaries/std/shops/
dw_fluffos_v2/lib/binaries/std/shops/inherit/
dw_fluffos_v2/lib/binaries/www/
dw_fluffos_v2/lib/cmds/guild-race/
dw_fluffos_v2/lib/cmds/guild-race/crafts/
dw_fluffos_v2/lib/cmds/guild-race/other/
dw_fluffos_v2/lib/cmds/playtester/
dw_fluffos_v2/lib/cmds/playtester/senior/
dw_fluffos_v2/lib/d/admin/
dw_fluffos_v2/lib/d/admin/log/
dw_fluffos_v2/lib/d/admin/mapper/31-10-01/mapmaker/event/
dw_fluffos_v2/lib/d/admin/meetings/
dw_fluffos_v2/lib/d/admin/obj/
dw_fluffos_v2/lib/d/admin/room/we_care/
dw_fluffos_v2/lib/d/admin/save/
dw_fluffos_v2/lib/d/dist/
dw_fluffos_v2/lib/d/dist/mtf/
dw_fluffos_v2/lib/d/dist/pumpkin/
dw_fluffos_v2/lib/d/dist/pumpkin/chars/
dw_fluffos_v2/lib/d/dist/pumpkin/desert/
dw_fluffos_v2/lib/d/dist/pumpkin/gumboot/
dw_fluffos_v2/lib/d/dist/pumpkin/hospital/
dw_fluffos_v2/lib/d/dist/pumpkin/inherit/
dw_fluffos_v2/lib/d/dist/pumpkin/map/
dw_fluffos_v2/lib/d/dist/pumpkin/plain/
dw_fluffos_v2/lib/d/dist/pumpkin/pumpkin/
dw_fluffos_v2/lib/d/dist/pumpkin/save/
dw_fluffos_v2/lib/d/dist/pumpkin/squash/
dw_fluffos_v2/lib/d/dist/pumpkin/terrain/
dw_fluffos_v2/lib/d/dist/pumpkin/woods/
dw_fluffos_v2/lib/d/dist/start/
dw_fluffos_v2/lib/d/learning/TinyTown/buildings/
dw_fluffos_v2/lib/d/learning/TinyTown/map/
dw_fluffos_v2/lib/d/learning/TinyTown/roads/
dw_fluffos_v2/lib/d/learning/add_command/
dw_fluffos_v2/lib/d/learning/arms_and_weps/
dw_fluffos_v2/lib/d/learning/chars/
dw_fluffos_v2/lib/d/learning/cutnpaste/
dw_fluffos_v2/lib/d/learning/examples/npcs/
dw_fluffos_v2/lib/d/learning/examples/player_houses/npcs/
dw_fluffos_v2/lib/d/learning/examples/terrain_map/basic/
dw_fluffos_v2/lib/d/learning/functions/
dw_fluffos_v2/lib/d/learning/handlers/
dw_fluffos_v2/lib/d/learning/help_topics/npcs/
dw_fluffos_v2/lib/d/learning/help_topics/objects/
dw_fluffos_v2/lib/d/learning/help_topics/rcs_demo/
dw_fluffos_v2/lib/d/learning/help_topics/rooms/
dw_fluffos_v2/lib/d/learning/help_topics/rooms/crowd/
dw_fluffos_v2/lib/d/learning/help_topics/rooms/situations/
dw_fluffos_v2/lib/d/learning/items/
dw_fluffos_v2/lib/d/learning/save/
dw_fluffos_v2/lib/d/liaison/
dw_fluffos_v2/lib/d/liaison/NEWBIE/doc/
dw_fluffos_v2/lib/d/liaison/NEWBIE/save/oldlog/
dw_fluffos_v2/lib/db/
dw_fluffos_v2/lib/doc/
dw_fluffos_v2/lib/doc/creator/
dw_fluffos_v2/lib/doc/creator/autodoc/include/reaction/
dw_fluffos_v2/lib/doc/creator/autodoc/include/ritual_system/
dw_fluffos_v2/lib/doc/creator/autodoc/include/talker/
dw_fluffos_v2/lib/doc/creator/autodoc/include/terrain_map/
dw_fluffos_v2/lib/doc/creator/autodoc/obj/baggage/
dw_fluffos_v2/lib/doc/creator/autodoc/obj/clock/
dw_fluffos_v2/lib/doc/creator/autodoc/obj/clothing/
dw_fluffos_v2/lib/doc/creator/autodoc/obj/cont_save/
dw_fluffos_v2/lib/doc/creator/autodoc/obj/corpse/
dw_fluffos_v2/lib/doc/creator/autodoc/obj/money/
dw_fluffos_v2/lib/doc/creator/autodoc/obj/monster/
dw_fluffos_v2/lib/doc/creator/autodoc/obj/scabbard/
dw_fluffos_v2/lib/doc/creator/autodoc/obj/service_provider/
dw_fluffos_v2/lib/doc/creator/autodoc/obj/state_changer/
dw_fluffos_v2/lib/doc/creator/autodoc/obj/wand/
dw_fluffos_v2/lib/doc/creator/autodoc/std/book_dir/
dw_fluffos_v2/lib/doc/creator/autodoc/std/key/
dw_fluffos_v2/lib/doc/creator/autodoc/std/learning/
dw_fluffos_v2/lib/doc/creator/autodoc/std/map/
dw_fluffos_v2/lib/doc/creator/autodoc/std/race/
dw_fluffos_v2/lib/doc/creator/autodoc/std/weapon_logic/
dw_fluffos_v2/lib/doc/creator/files/
dw_fluffos_v2/lib/doc/creator/policy/
dw_fluffos_v2/lib/doc/creator/room/
dw_fluffos_v2/lib/doc/effects/
dw_fluffos_v2/lib/doc/ideas/
dw_fluffos_v2/lib/doc/known_command/
dw_fluffos_v2/lib/doc/lpc/basic_manual/
dw_fluffos_v2/lib/doc/lpc/intermediate/
dw_fluffos_v2/lib/doc/new/add_command/
dw_fluffos_v2/lib/doc/new/handlers/
dw_fluffos_v2/lib/doc/new/living/
dw_fluffos_v2/lib/doc/new/living/race/
dw_fluffos_v2/lib/doc/new/living/spells/
dw_fluffos_v2/lib/doc/new/player/
dw_fluffos_v2/lib/doc/new/room/guild/
dw_fluffos_v2/lib/doc/new/room/outside/
dw_fluffos_v2/lib/doc/new/room/storeroom/
dw_fluffos_v2/lib/doc/object/
dw_fluffos_v2/lib/doc/playtesters/
dw_fluffos_v2/lib/doc/policy/
dw_fluffos_v2/lib/doc/weapons/
dw_fluffos_v2/lib/global/handlers/
dw_fluffos_v2/lib/global/virtual/setup_compiler/
dw_fluffos_v2/lib/include/
dw_fluffos_v2/lib/include/cmds/
dw_fluffos_v2/lib/include/effects/
dw_fluffos_v2/lib/include/npc/
dw_fluffos_v2/lib/include/shops/
dw_fluffos_v2/lib/net/daemon/chars/
dw_fluffos_v2/lib/net/inherit/
dw_fluffos_v2/lib/net/intermud3/
dw_fluffos_v2/lib/net/intermud3/services/
dw_fluffos_v2/lib/net/obj/
dw_fluffos_v2/lib/net/save/
dw_fluffos_v2/lib/net/smnmp/
dw_fluffos_v2/lib/net/snmp/
dw_fluffos_v2/lib/obj/amulets/
dw_fluffos_v2/lib/obj/b_day/
dw_fluffos_v2/lib/obj/examples/
dw_fluffos_v2/lib/obj/food/alcohol/
dw_fluffos_v2/lib/obj/food/chocolates/
dw_fluffos_v2/lib/obj/food/fruits/
dw_fluffos_v2/lib/obj/food/meat/
dw_fluffos_v2/lib/obj/food/nuts/
dw_fluffos_v2/lib/obj/food/seafood/
dw_fluffos_v2/lib/obj/food/vegetables/
dw_fluffos_v2/lib/obj/fungi/
dw_fluffos_v2/lib/obj/furnitures/artwork/
dw_fluffos_v2/lib/obj/furnitures/bathroom/
dw_fluffos_v2/lib/obj/furnitures/beds/
dw_fluffos_v2/lib/obj/furnitures/cabinets/
dw_fluffos_v2/lib/obj/furnitures/chairs/
dw_fluffos_v2/lib/obj/furnitures/chests/
dw_fluffos_v2/lib/obj/furnitures/clocks/
dw_fluffos_v2/lib/obj/furnitures/crockery/
dw_fluffos_v2/lib/obj/furnitures/cupboards/
dw_fluffos_v2/lib/obj/furnitures/cushions/
dw_fluffos_v2/lib/obj/furnitures/fake_plants/
dw_fluffos_v2/lib/obj/furnitures/lamps/
dw_fluffos_v2/lib/obj/furnitures/mirrors/
dw_fluffos_v2/lib/obj/furnitures/outdoor/
dw_fluffos_v2/lib/obj/furnitures/safes/
dw_fluffos_v2/lib/obj/furnitures/shelves/
dw_fluffos_v2/lib/obj/furnitures/sideboards/
dw_fluffos_v2/lib/obj/furnitures/sofas/
dw_fluffos_v2/lib/obj/furnitures/stoves/
dw_fluffos_v2/lib/obj/furnitures/tables/
dw_fluffos_v2/lib/obj/furnitures/wardrobes/
dw_fluffos_v2/lib/obj/handlers/
dw_fluffos_v2/lib/obj/handlers/autodoc/
dw_fluffos_v2/lib/obj/jewellery/anklets/
dw_fluffos_v2/lib/obj/jewellery/bracelets/
dw_fluffos_v2/lib/obj/jewellery/earrings/
dw_fluffos_v2/lib/obj/jewellery/misc/
dw_fluffos_v2/lib/obj/jewellery/necklaces/
dw_fluffos_v2/lib/obj/jewellery/rings/
dw_fluffos_v2/lib/obj/media/
dw_fluffos_v2/lib/obj/misc/buckets/
dw_fluffos_v2/lib/obj/misc/jars/
dw_fluffos_v2/lib/obj/misc/papers/
dw_fluffos_v2/lib/obj/misc/player_shop/
dw_fluffos_v2/lib/obj/misc/shops/
dw_fluffos_v2/lib/obj/misc/traps/
dw_fluffos_v2/lib/obj/monster/
dw_fluffos_v2/lib/obj/monster/godmother/
dw_fluffos_v2/lib/obj/monster/transport/
dw_fluffos_v2/lib/obj/plants/inherit/
dw_fluffos_v2/lib/obj/potions/
dw_fluffos_v2/lib/open/boards/
dw_fluffos_v2/lib/save/autodoc/
dw_fluffos_v2/lib/save/bank_accounts/
dw_fluffos_v2/lib/save/boards/frog/
dw_fluffos_v2/lib/save/books/bed_catalog/
dw_fluffos_v2/lib/save/creators/
dw_fluffos_v2/lib/save/mail/
dw_fluffos_v2/lib/save/mail/p/
dw_fluffos_v2/lib/save/soul/data/
dw_fluffos_v2/lib/save/tasks/
dw_fluffos_v2/lib/save/vaults/
dw_fluffos_v2/lib/secure/cmds/lord/
dw_fluffos_v2/lib/secure/config/
dw_fluffos_v2/lib/secure/items/
dw_fluffos_v2/lib/secure/player/
dw_fluffos_v2/lib/soul/
dw_fluffos_v2/lib/soul/i/
dw_fluffos_v2/lib/soul/j/
dw_fluffos_v2/lib/soul/k/
dw_fluffos_v2/lib/soul/o/
dw_fluffos_v2/lib/soul/q/
dw_fluffos_v2/lib/soul/to_approve/
dw_fluffos_v2/lib/soul/u/
dw_fluffos_v2/lib/soul/v/
dw_fluffos_v2/lib/soul/wish_list/
dw_fluffos_v2/lib/soul/y/
dw_fluffos_v2/lib/soul/z/
dw_fluffos_v2/lib/std/creator/
dw_fluffos_v2/lib/std/effects/
dw_fluffos_v2/lib/std/effects/attached/
dw_fluffos_v2/lib/std/effects/external/
dw_fluffos_v2/lib/std/effects/fighting/
dw_fluffos_v2/lib/std/effects/other/
dw_fluffos_v2/lib/std/environ/
dw_fluffos_v2/lib/std/guilds/
dw_fluffos_v2/lib/std/hospital/
dw_fluffos_v2/lib/std/house/
dw_fluffos_v2/lib/std/house/onebedhouse/
dw_fluffos_v2/lib/std/house/onebedhut/
dw_fluffos_v2/lib/std/house/tworoomflat/
dw_fluffos_v2/lib/std/languages/
dw_fluffos_v2/lib/std/liquids/
dw_fluffos_v2/lib/std/nationality/
dw_fluffos_v2/lib/std/nationality/accents/
dw_fluffos_v2/lib/std/nationality/accents/national/
dw_fluffos_v2/lib/std/nationality/accents/regional/
dw_fluffos_v2/lib/std/npc/goals/
dw_fluffos_v2/lib/std/npc/goals/basic/
dw_fluffos_v2/lib/std/npc/goals/misc/
dw_fluffos_v2/lib/std/npc/inherit/
dw_fluffos_v2/lib/std/npc/plans/
dw_fluffos_v2/lib/std/npc/plans/basic/
dw_fluffos_v2/lib/std/outsides/
dw_fluffos_v2/lib/std/races/shadows/
dw_fluffos_v2/lib/std/room/basic/topography/
dw_fluffos_v2/lib/std/room/controller/
dw_fluffos_v2/lib/std/room/controller/topography/
dw_fluffos_v2/lib/std/room/furniture/games/
dw_fluffos_v2/lib/std/room/furniture/inherit/
dw_fluffos_v2/lib/std/room/inherit/carriage/
dw_fluffos_v2/lib/std/room/inherit/topography/
dw_fluffos_v2/lib/std/room/punishments/
dw_fluffos_v2/lib/std/room/topography/area/
dw_fluffos_v2/lib/std/room/topography/iroom/
dw_fluffos_v2/lib/std/room/topography/milestone/
dw_fluffos_v2/lib/std/shadows/
dw_fluffos_v2/lib/std/shadows/attached/
dw_fluffos_v2/lib/std/shadows/curses/
dw_fluffos_v2/lib/std/shadows/disease/
dw_fluffos_v2/lib/std/shadows/fighting/
dw_fluffos_v2/lib/std/shadows/room/
dw_fluffos_v2/lib/std/shops/controllers/
dw_fluffos_v2/lib/std/shops/objs/
dw_fluffos_v2/lib/std/shops/player_shop/
dw_fluffos_v2/lib/std/shops/player_shop/office_code/
dw_fluffos_v2/lib/std/socket/
dw_fluffos_v2/lib/www/
dw_fluffos_v2/lib/www/external/autodoc/
dw_fluffos_v2/lib/www/external/java/telnet/Documentation/
dw_fluffos_v2/lib/www/external/java/telnet/Documentation/images/
dw_fluffos_v2/lib/www/external/java/telnet/examples/
dw_fluffos_v2/lib/www/external/java/telnet/tools/
dw_fluffos_v2/lib/www/pics/
dw_fluffos_v2/lib/www/secure/creator/
dw_fluffos_v2/lib/www/secure/editors/
dw_fluffos_v2/lib/www/secure/survey_results/
dw_fluffos_v2/win32/
/*  -*- LPC -*-  */
/*
 * $Locker:  $
 * $Id: room_handler.c,v 1.54 2003/02/13 23:33:56 ceres Exp $
 */
/**
 * This file contains all the bits needed to handle rooms, plus the code to
 * handle following when moving.
 * @author Pinkfish
 * @revision Deutha Who knows
 * Severely changed, move the follow code in here from the living object
 * @see /std/room/basic_room.c
 */
#include <climate.h>
#include <living.h>
#include <move_failures.h>
#include <player.h>
#include <room.h>
#include <weather.h>
#include <position.h>

#define CHATSIZE 80
#define DOORSIZE 60 

mapping exit_types;
mapping door_types;
mapping opposite;
mixed *chatters, *doors;

void add_door( object thing );

/* ({ mess, obv, size, func }) */
void create() {
   seteuid( (string)"/secure/master"->
           creator_file( file_name( this_object() ) ) );
   exit_types = ([
"standard" :({ 0, 1,   400, 0 }),
"corridor" :({ 0, 1,   250, 0 }),
"plain"    :({ 0, 1, 10000, 0 }), /* very large */
"door"     :({ 0, 1,   300, 0 }),
"stair"    :({ 0, 1,   300, 0 }), /* going up? */
"hidden"   :({ 0, 0,   300, 0 }), /* hidden non door exit */
"secret"   :({ 0, 0,   300, 0 }), /* secret door */
"gate"     :({ 0, 1,   450, 0 }),
"road"     :({ 0, 1,  1300, 0 }),
"path"     :({ 0, 1,   800, 0 }),
"window"   :({ "$N climb$s through a window.\n", 0, 75, 0 }),
]);
   door_types = ([
"door"      : ({ 0, 0, "generic_key", 2, 0, 0, "door" }),
"secret"    : ({ 0, 0, "generic_key", 3, 1, 0, "door" }),
"gate"      : ({ 1, 0, "generic_key", 1, 0, 1, "door" }),
"window"    : ({ 1, 0, "generic_key", 1, 0, 1, "window" }),
]);
   opposite = ([
"north" : ({ 0, "$R$[the ]+south$R$" }),
"south" : ({ 0, "$R$[the ]+north$R$" }),
"east" : ({ 0, "$R$[the ]+west$R$" }),
"west" : ({ 0, "$R$[the ]+east$R$" }),
"northeast" : ({ 0, "$R$[the ]+southwest$R$" }),
"southwest" : ({ 0, "$R$[the ]+northeast$R$" }),
"southeast" : ({ 0, "$R$[the ]+northwest$R$" }),
"northwest" : ({ 0, "$R$[the ]+southeast$R$" }),
"up":({0,"below"}), "down":({0,"above"}),
"out":({0,"inside"}), "in":({0,"outside"}),
"exit":({0,"inside"}), "enter":({0,"outside"}),
"hubward":({0,"rimward"}), "rimward":({0,"hubward"}),
"turnwise":({0,"widdershins"}),
"widdershins":({0,"turnwise"}) ]);
   chatters = allocate( CHATSIZE );
   doors = allocate( DOORSIZE );
   call_out( "housekeeping", 4 );
} /* create() */

/**
 * This method returns the opposite direction to this exit.  This should
 * only be used for printing, since it is not a useful
 * real name.
 * @param dir the direction to get the opposite of
 * @return the opposite direction
 */
string query_opposite_direction(string dir) {
   if (opposite[dir]) {
      return opposite[dir][1];
   }
   return 0;
}

/**
 * This method returns the current list of rooms that are enabled for
 * chatting.
 * @return the current chatters
 */
mixed *query_chatters() { return chatters; }

/**
 * This method returns the current list of doors handled by the room
 * handler.
 * @return the current array of doors
 */
mixed *query_doors() { return doors; }

/**
 * This method adds an exit type to the current list of available exit types.
 * This is used when the room handler is setup to add all the used exit
 * types.
 * @param type the name of the exit type
 * @param message the message to display when going through the exit
 * @param obvious if the exit is obvious or not
 * @param size the size of the exit (used for heigh restrictions)
 * @param func the function to call when using the exit
 * @return 1 if successfuly added, 0 if not
 * @see remove_exit_type()
 */
int add_exit_type(string type, mixed message, mixed obvious,
                            int size, mixed func) {
  if (exit_types[type]) {
    return 0;
  }
  exit_types[type] = ({ message, obvious, size, func });
  return 1;
} /* add_exit_type() */

/**
 * This method remove the named exit from the type list.
 * @param type the name of the exit type to remove
 * @return always returns 1
 * @see add_exit_type()
 */
int remove_exit_type(string type) {
   map_delete(exit_types, type);
   return 1;
} /* remove_exit_type() */

/**
 * This method returns information about the door type, the door has
 * extra information associated with it than the standard exit type.
 * This function does a double job of trying to find the corresponding
 * door on the other side of the room.
 * @param type the type of the door
 * @param direc the direction the door points
 * @param dest the destination of the door
 * @return the door type array of information
 */
mixed *query_door_type(string type, string direc, string dest) {
   if (!door_types[type]) {
      return 0;
   }
   /* If there isnt a door on the other side.  We don't join. */
   call_out( "check_door", 1, ({ previous_object(), direc }) );
   return door_types[type];
} /* query_door_type() */

/**
 * This method checks to see if the door exists or not.
 * It is passed in the room we are going from and the direction the
 * exit faces in the array.<br>
 * <pre>({ room_from, direction })</pre><br>
 * This is the function which generates those door xx not found messages.
 * @param args the arguements passed into the function
 * @see query_door_type()
 */
void check_door( mixed args ) {
   string direc, dest;
   string door_name;
   
   if ( !args[ 0 ] ) {
      return;
   }
   args[ 0 ]->set_destination( args[ 1 ] );
   dest = (string)args[ 0 ]->query_destination( args[ 1 ] );
   if ( !dest ) {
      tell_room( args[ 0 ], "Error: "+ args[ 1 ] +
            " is no longer an exit.\n" );
      return;
   }
   if ( !find_object( dest ) ) {
      return;
   }

   door_name = args[0]->call_door(args[1], "query_door_name");
   direc = (string)dest->query_door( args[ 0 ], door_name );

   if ( !direc && 
       !args[ 0 ]->call_door( args[ 1 ], "query_one_way" ) ) {
      tell_room( args[ 0 ], "Error: "+ dest +
                "does not have a door coming back here.\n" );
      return;
   }
   args[ 0 ]->modify_exit( args[ 1 ], ({ "other", direc }) );

   /*
    * This makes sure that whatever the states of the two sides, they'll
    * both end up the same.  Think about it...
    */
   args[ 0 ]->modify_exit( args[ 1 ], ({
      "closed", (int)dest->call_door( direc, "query_closed" ),
      "locked", (int)dest->call_door( direc, "query_locked" ) }) );
   if ( !args[ 0 ]->call_door( args[ 1 ], "query_closed" ) &&
       ( (string)args[ 0 ]->query_property( "location" ) == "outside" ) ) {
      add_door( (object)args[ 0 ]->query_door_control( args[ 1 ], door_name ) );
   }
} /* check_door() */

/**
 * This method returns the information associated with the exit type.
 * @param type the exit type to query
 * @param dir the direction the type information is for
 * @return a huge amount of info as specified above
 */
mixed *query_exit_type(string type, string dir) {
  mixed s;

   if (!(s = opposite[dir])) {
      s = ({ 0, "elsewhere" });
   }
   if (!exit_types[type]) {
      return exit_types["standard"] + ({ s, 0, 0, 0, 0, 0, 0, 0, 0, 0 });
   }
   return exit_types[ type ] + ({ s, 0, 0, 0, 0, 0, 0, 0, 0, 0 });
} /* query_exit_type() */

/**
 * THis is the code that actually moves the thing around the place.
 * It handles all the weirdness involved with dragging things and other
 * such stuff.
 * @param thing what is being moved
 * @param dir the direction we are going
 * @param dest the destionation room
 * @param exit the exit name
 * @param enter the enter name
 * @param move the string to tell the object when it moves
 * @return 1 on success, 0 on failure
 */
int move_thing( object thing, string dir, string dest, mixed exit,
                mixed enter, string move ) {
  int ret;
  string arrive, leave;
  object dragging;
  
  dragging = (object)thing->query_dragging();

  if (dragging && environment(dragging) != environment(thing)) {
    thing->reset_dragging();
    dragging = 0;
  }

  if ( ( exit != "none" ) || objectp( dragging ) ) {
    if ( stringp( enter ) )
      enter = ({ 1, enter });
    else if ( functionp(enter) )
      enter = ({ 1, evaluate(enter, thing) });
    else if ( !pointerp( enter ) )
      enter = ({ 0, "somewhere" });
    
    switch ( enter[ 0 ] ) {
    case 0 :
      arrive = replace( (string)thing->query_msgin(), 
                        ({"$F", enter[ 1 ], 
                          "$r", thing->query_pronoun() }) );
      break;
    default :
      arrive = enter[ 1 ];
    }

    if ( stringp( exit) )
      leave = exit;
    else if ( functionp( exit ) )
      leave = evaluate(exit, thing);
    else if ( pointerp( exit ) )
      leave = exit[ 0 ];
    else
      leave = (string)thing->query_msgout();

    leave = replace( leave, ({"$T", "$R$-"+ dir +"$R$",
                              "$r", thing->query_pronoun() }) );
  }

  /* Check position... */
  thing->return_to_default_position(1);
  
  if ( arrive || objectp( dragging ) ) {
    thing->remove_hide_invis( "hiding" );
    if ( stringp( arrive ) && objectp( dragging ) ) {
      arrive += "\n$C$"+ (string)thing->query_pronoun() +" drags "+
        (string)dragging->a_short() +" in behind "+
        (string)thing->query_objective() +".";
    }

    if ( stringp( leave ) && objectp( dragging ) ) {
      leave += "\n$C$"+ (string)thing->query_pronoun() +" drags "+
        (string)dragging->the_short() +" away behind "+
        (string)thing->query_objective() +".";
    }

    if ( stringp( move ) ) {
      tell_object( thing, move );
    }

    ret = (int)thing->move( dest, arrive, leave );
    if ( ( ret == MOVE_OK ) && objectp( dragging ) ) {
      if(dragging->move(environment(thing)) == MOVE_OK) {
        tell_object( thing, "You drag "+
                     (string)dragging->the_short() +" behind you.\n" );
        thing->adjust_time_left( -DEFAULT_TIME );
        //dragging->adjust_cond(-100);
      } else {
        tell_object( thing, "You fail to drag "+
                     (string)dragging->the_short() +" behind you.\n" );
      }
    }
  } else {
    if ( stringp( move ) ) {
      tell_object( thing, move );
    }
    ret = (int)thing->move( dest );
  }

  if ( ret == MOVE_OK ) {
    thing->adjust_time_left( -DEFAULT_TIME );
    return 1;
  }

  return 0;
} /* move_thing() */

/** @ignore yes
 * This function performs the door checks for exit_move(). It is called
 * for the object moving and each of its followers.  It returns 1 if
 * the player can move or 0 if not.
 */
int exit_move_door_checks(object thing, mixed closed) {

  closed->force_other();
  
  if(closed->query_open())
    return 1;
  
  if(thing->query_property( "demon" ) || thing->query_property("dead")) {
    tell_object(thing, "You ghost through "+(string)closed->the_short()+
                ".\n");
    return 1;
  }

  // Too small to open the door or unlock it!
  if(thing->query_weight() < 300)
    return 0;
  
  if(closed->query_locked() && !closed->moving_unlock(thing)) {
    // It is locked and invisible...
    if(!closed->query_visible(thing)) {
      return 0;
    }
    
    tell_object(thing, (string)closed->the_short() +
                ({ " is ", " are " })[(int)closed->query_how_many()] +
                "locked.\n");
    return notify_fail("");
  }

  if(!closed->moving_open(thing)) {
    return 0;
  }

  return 1;
}

/** @ignore yes
 * This function performs the function checks for exit_move(). It returns 1 if
 * the player can move or 0 if not.
 */
int exit_move_func_checks(string verb, string special, object thing,
                          mixed func, object place) {
  if(stringp(func))
    return call_other(place, func, verb, thing, special);

  if(functionp(func))
    return evaluate(func, verb, thing, special);

  if(pointerp(func) && sizeof(func) > 1 && func[0] && func[1])
    return call_other(func[0], func[1], verb, thing, special);
  
  return 1;
}

/**
 * This is the main code for moving someone.  The move_thing code above
 * should not be called directly.  This code handlers all the followers
 * and any other things that need to be handled.
 * @param verb the movement verb
 * @param extra extra information
 * @param special special informaiton
 * @param thing the thing to move
 * @return 1 on success, 0 on failure
 */
int exit_move( string verb, string extra, mixed special, object thing ) {
   string leave;
   // Place is where we are right now.
   object place;
   object follower;
   object *okay;
   mixed closed;
   int locked;
   mixed func;
   mixed *dest_other;
   object *all_followers;
   object *tmp_followers;
   object *more_followers;

   /* Find the exit infomation. */
   place = environment( thing );
   verb = (string)place->expand_alias( verb );
   place->set_destination( verb );
   
   /* This checks that the destination is correctly set. */
   dest_other = (mixed *)place->query_dest_other( verb );
   if (!pointerp(dest_other))
      return 0;

   if(thing->cannot_walk( verb, dest_other ))
      return notify_fail( "" );
   
   /* This checks that the door exists if there should be one. */
   closed = (object)place->query_door_control( verb );

   // Force the other side of the door to load. Once this is done make
   // sure our door hasn't been destructed & replaced by another. I know
   // that sounds unlikely but it does happen sometimes.
   if(objectp(closed)) {
     closed->force_other();
     if(!closed)
       closed = (object)place->query_door_control( verb );
   }

   /* This checks to see if this is an NPC trying
    * to go through a "no follow" exit. */
   if (!interactive(thing) && living(thing)
         && sizeof(dest_other) > ROOM_NPC_STOP && dest_other[ROOM_NPC_STOP])
      return 0;

   if (objectp(closed)) {
      locked = closed->query_locked();
   }
   /* If the door is already open we don't need the closed thing coz
      we aren't going to do anything to the door. */
   if(objectp(closed) && closed->query_open()) {
     closed = 0;
   }

   if(objectp(closed) && !exit_move_door_checks(thing, closed)) {
     return 0;
   }
   
   //To allow the room to override exits from a central location.
   if ( place->block_exit_move( verb, thing ) ) {
     return notify_fail( "" );
   }

   /* Check exit functions. */
   func = dest_other[ROOM_FUNC];
   if(func && !thing->query_property( "demon" ) &&
      !exit_move_func_checks(verb, special, thing, func, place))
     return 0;
   
   if ( place->query_relative( verb ) )
     leave = (string)thing->find_rel( verb, 0 );
   else
     leave = verb;

   /* Check height. */
   if((int)thing->query_height() > dest_other[ ROOM_SIZE ] &&
      !(thing->query_crawling() &&
        (int)thing->query_height()/3 <= dest_other[ ROOM_SIZE ])) {
     tell_object( thing, "You are too tall to go that way.\n" );
     return notify_fail( "" );
   }

   /* Now actually move. */
   if ( !stringp( special ) ) {
      special = dest_other[ ROOM_EXIT ];
   }

   if ( !move_thing( thing, verb, dest_other[ ROOM_DEST ], special,
                     dest_other[ ROOM_ENTER ], dest_other[ ROOM_MESS ] ) ) {
     return 0;
   }

   thing->return_to_default_position(1);

   okay = ({ });
   if (place) {
     // Get all the followers of the followers.
     all_followers = thing->query_followers();
     more_followers = all_followers;
     do {
       tmp_followers = ({ });
       foreach (follower in more_followers) {
         //
         // Make sure that we only follow lists of people that are actually
         // here.
         //
         if (follower &&
             environment( follower ) == place ) {
           // Make sure we not end up with duplicates in this array.
           tmp_followers |= follower->query_followers();
         }
       }
       // Make sure we do not get repeated followers.
       more_followers = tmp_followers - all_followers;
       all_followers |= tmp_followers;
     } while (sizeof(more_followers));
     
     // Move all those people following us too!
     foreach ( follower in all_followers) {

       if ( !objectp( follower ) ) {
         thing->remove_follower( follower );
         continue;
       }
       
       /* Make sure they are in the start room and
        * if they are a user they are interactive and
        * the person they are following is visible and
        * they aren't passed out and can walk.
        */
       if(environment(follower) != place ||
          (userp(follower) && !interactive(follower)) ||
          (!thing->query_visible(follower) || (special == "none")) ||
          follower->query_property( PASSED_OUT) ||
          follower->cannot_walk( verb, dest_other ))
         continue;

       // do the door checks
       if(objectp(closed) && !exit_move_door_checks(follower, closed))
         continue;

       // do the function checks.
       if ( func && !follower->query_property( "demon" ) &&
            !exit_move_func_checks(verb, special, follower, func, place))
         continue;

       // do the NPC check.
       if (!interactive(follower) && living(follower)
           && sizeof(dest_other) > ROOM_NPC_STOP && dest_other[ROOM_NPC_STOP])
         continue;

       if ( place->query_relative( verb ) ) {
         leave = (string)follower->find_rel( verb, 0 );
         follower->reorient_rel( leave );
       } else {
         leave = verb;
         follower->reorient_abs( leave );
       }

       if ( (int)follower->query_height() > dest_other[ ROOM_SIZE ] ) {
         tell_object( follower, "You are too tall to follow "+
                      (string)thing->the_short() +" "+ leave +".\n" );
         continue;
       }

       if (function_exists("check_doing_follow", follower) &&
           !follower->check_doing_follow(thing, verb, special)) {
         continue;
       }

       if(move_thing( follower, verb, dest_other[ROOM_DEST], special,
                      dest_other[ROOM_ENTER], dest_other[ROOM_MESS]) &&
          living(follower)) {

         tell_object(follower, "You follow "+ (string)thing->the_short() +
                     " "+ leave +".\n");

         if(follower->query_visible(thing))
           okay += ({ follower });


         follower->return_to_default_position(1);

       } else {
         tell_object( follower, "You fail to follow "+
                      (string)thing->the_short() +" "+ leave +".\n" );
       }
     }
   }

   //
   // Move everyone then do the look.  Fix up problems with followers
   // that have light, like the fireflies and blue lights.
   //
   thing->room_look();
   if(sizeof(okay)) {
     okay->room_look();
     tell_object(thing, query_multiple_short(okay) +
                 " $V$0=follows,follow$V$ you.\n" );
   }

   if(objectp(closed)) {
      closed->moving_close(thing);

      if (locked)
        closed->moving_lock(thing);
   }

   return 1;
}

void housekeeping() {
   call_out( "check_chatters", 1 );
   call_out( "check_doors", 2 );
   call_out( "housekeeping", 4 );
} /* housekeeping() */

void add_chatter(object thing, int number) {
   number /= 4;
   if ( number > CHATSIZE - 1 )
      number = CHATSIZE - 1;
   if ( !pointerp( chatters[ number ] ) )
      chatters[ number ] = ({ thing });
   else
      chatters[ number ] += ({ thing });
} /* add_chatter() */

void check_chatters() {
   object thing, *things;
   things = chatters[ 0 ];
   chatters[ 0 .. <2 ] = chatters[ 1 .. <1 ];
   chatters[ <1 ] = 0;
   if ( !pointerp( things ) )
      return;
   foreach ( thing in things ) {
      if ( objectp( thing ) )
         thing->make_chat();
   }
} /* check_chatters() */

void add_door( object thing ) {
   int number;
   number = random( DOORSIZE );
   if ( !pointerp( doors[ number ] ) )
      doors[ number ] = ({ thing });
   else
      doors[ number ] += ({ thing });
} /* add_door() */

void check_doors() {
   int wind;
   string dest, other, mess;
   object mine, thing, *things;
   things = doors[ 0 ];
   doors[ 0 .. <2 ] = doors[ 1 .. <1 ];
   doors[ <1 ] = 0;
   if ( !pointerp( things ) )
      return;
   foreach ( thing in things ) {
      if ( !objectp( thing ) )
         continue;
      if ( thing->query_closed() )
         continue;
      if(thing->query_stuck())
         continue;
      
      dest = (string)thing->query_dest();
      other = (string)thing->query_other_id();
      mine = (object)thing->query_my_room();
      wind = (int)WEATHER->calc_actual( mine, WINDSP );
      if ( random( 25 ) > wind ) {
         add_door( thing );
         return;
      }
      switch ( wind ) {
       case -1000 .. 20 :
         mess = "blow$s shut in the breeze.\n";
         break;
       case 21 .. 40 :
         mess = "blow$s shut in the wind.\n";
         break;
       default :
         mess = "slam$s shut in the wind.\n";
      }
      if ( find_object( dest ) ) {
         dest->modify_exit( other, ({ "closed", 1 }) );
         if(thing->query_autolock())
           dest->modify_exit(other, ({ "locked", 1 }));
         dest->tell_door( other, "The $D "+ mess, 0 );
      }
      thing->set_closed( 1 );
      if(thing->query_autolock())
        thing->set_locked();
      thing->tell_door( "The $D "+ mess, 0 );
   }
} /* check_doors() */

/* these two are not here because the handler can be saved, but to keep
 * the info over updates.
 */
mapping query_dynamic_auto_load() {
   mapping tmp;
   tmp = ([ "exit_types" : exit_types,
            "door_types" : door_types,
            "opposite" : opposite,
            "chatters" : chatters,
            "doors" : doors,
          ]);
   return tmp;
} /* query_dynamic_auto_load() */

void init_dynamic_arg(mapping maps) {
   if (maps["exit_types"])
      exit_types = maps["exit_types"];
   if (maps["door_types"])
      door_types = maps["door_types"];
   if (maps["opposite"])
      opposite = maps["opposite"];
   if (maps["chatters"])
      chatters = maps["chatters"];
   if (maps["doors"])
      doors = maps["doors"];
} /* init_dynamic_arg() */

mixed *stats() {
   int door_count, chatter_count;
   mixed temp;
   foreach (temp in chatters)
      chatter_count += sizeof( temp );
   foreach (temp in doors)
      door_count += sizeof( temp );
   return ({
      ({ "exit types", sizeof( exit_types ) }),
      ({ "door types", sizeof( door_types ) }),
      ({ "opposites",  sizeof( opposite ) }),
      ({ "chatters",  chatter_count }),
      ({ "doors", door_count }),
   });
}