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: pinkfish $
 * $Id: topography.c,v 1.9 2002/02/28 23:13:52 pinkfish Exp pinkfish $
 *
 *
 */

/*
 * $Locker: pinkfish $
 * $Id: topography.c,v 1.9 2002/02/28 23:13:52 pinkfish Exp pinkfish $
 *
 *
 */

/*
** topography.c - the top-level handler that pulls together the areas,
**             irooms, and fixed rooms.
*/
/**
 * This is the top-level handler for the topography system.
 */
#include <dirs.h>
#include "path.h"

//inherit "/std/room";
inherit "/std/basic/setup";

class bounding_box {
   int* topleft;
   int* bottomright;
}

class FIXED_INFO {
  string path;
  object ob;
  int *coord;
  mixed bbox;
}

private mapping opposites = ([
  "north": "south", "south": "north", "west": "east",
  "east": "west", "northeast": "southwest", "southwest": "northeast",
  "northwest": "southeast", "southeast": "northwest", "up": "down",
  "down": "up"
]);

private int _dbg_lvl = 0;
private string _debugger;
private object *_area_handlers = ({ });
private object *_iroom_handlers = ({ });
private class FIXED_INFO *_fixed_rooms = ({ });
private mapping _fixed_room_index = ([ ]);
private class bounding_box _topo_box;

/**
 * This method sets the creator to whom debugging messages are sent.
 * @param d name of creator
 */
void set_debugger(string s) { _debugger = s; }

/**
 * This method returns the name of the creator to whom debugging messages
 * are sent.
 * @return name of creator
 */
string query_debugger() { return _debugger; }

/**
 * This method sets the level of debugging messages printed.
 * @param l debugging level (0 is off)
 */
void set_debug_level(int l) { _dbg_lvl = l; }

/**
 * This method returns the current debugging level.
 * @return current debug level (0 is off)
 */
int query_debug_level() { return _dbg_lvl; }

/**
 * @ignore
 * For debugging only
 */
//mixed query(string s) { return fetch_variable(s); }

void create() {

  //inc_setup();
  //::create();
  //dec_setup();

  do_setup();
} /* create() */

/**
 * This method returns the bounding box for the topography.
 * @return the bounding box
 */
class bounding_box query_bounding_box() {
   return _topo_box;
} /* query_bounding_box() */

/**
 * Checks to see if the co-ordinate is in the bounding box.
 * @param coord the co-ordinate to check
 * @param bbox the bounding box
 * @return 1 if it is, 0 if not
 */
int in_bbox(int *coord, class bounding_box bbox) {
  if ((coord[0] < bbox->topleft[0]) || (coord[0] > bbox->bottomright[0])) {
    return 0;
  }
  if ((coord[1] < bbox->topleft[1]) || (coord[1] > bbox->bottomright[1])) {
    return 0;
  }
  return 1;
} /* in_bbox() */

/**
 * This method makes a bounding box for a specified co ordinate and
 * a polygon.
 * @param coord the co-ordinate to get the box from
 * @param s the size (or integer square size) of the room
 * @return the bounding box
 */
class bounding_box bounding_box(int *coord, mixed s) {
  int *size;
  class bounding_box bbox;

  if (sizeof(coord) != 3) {
    return 0;
  }
  if (arrayp(s)) {
    if (sizeof(s) == 3) {
      size = s;
    } else {
      return 0;
    }
  } else if (intp(s)) {
    size = ({ s, s, s });
  } else {
    return 0;
  }
  bbox = new(class bounding_box);
  bbox->topleft = ({ coord[0]-size[0], coord[1]-size[1], coord[2]-size[2] });
  bbox->bottomright = ({ coord[0]+size[0], coord[1]+size[1], coord[2]+size[2] });
  return bbox;
} /* bounding_box() */

/**
 * This method adds in an area handler.
 * @param h the area handle to add
 */
void add_area_handler(mixed h) {
  object oh;

  if (stringp(h)) {
    oh = load_object(h);
    oh->set_handler(base_name(this_object()));
    if (objectp(oh)) {
      _area_handlers += ({ oh });
    } else {
      error(sprintf("Couldn't find area handler %s.\n", h));
    }
  } else if (objectp(h)) {
    h->set_handler(base_name(this_object()));
    _area_handlers += ({ h });
  } else {
    error(sprintf("Couldn't find area handler %O.\n", h));
  }
} /* add_area_handler() */

/**
 * This method adds in an inter-room handler.  An interroom is something like
 * a path that has a rectangular bounding box allowing multiple rooms to
 * connect to it.
 * @param h the interoom handler
 */
void add_iroom_handler(mixed h) {
  object oh;

  if (stringp(h)) {
    oh = load_object(h);
    oh->set_handler(base_name(this_object()));
    if (objectp(oh)) {
      _iroom_handlers += ({ oh });
    } else {
      error(sprintf("Couldn't find interroom handler %s.\n", h));
    }
  } else if (objectp(h)) {
    h->set_handler(base_name(this_object()));
    _iroom_handlers += ({ h });
  } else {
    error(sprintf("Couldn't find interroom handler %O.\n", h));
  }
} /* add_iroom_handler() */

/**
 * This is the internal function to add a fixed location room.
 * @param path the path to the object
 * @param ob the object itself
 * @param coord the coordinate of the object
 * @param bbox the bounding box of the object
 */
private void add_internal_fixed_room(string path,
                                     object ob,
                                     int* coord,
                                     class bounding_box bbox) {
  class FIXED_INFO cf;

  cf = new(class FIXED_INFO);
  cf->path = path;
  cf->ob = ob;
  cf->coord = coord;
  cf->bbox = bbox;
  _fixed_room_index[cf->path] = sizeof(_fixed_rooms);
  _fixed_rooms += ({ cf });
} /* add_internal_fixed_room() */

/**
 * This method adds a room in a fixed location.  It gets the co-ordinate
 * and size information from the room itself.
 * @param f the room to add
 * @add add_fixed_room_object()
 * @add add_fixed_room_coord()
 */
void add_fixed_room(string f) {
  object of;

  of = load_object(f);
  if (!objectp(of)) {
    error(sprintf("Couldn't load fixed room %s.\n", f));
    return;
  }
  add_internal_fixed_room(f, of, of->query_co_ord(),
                      bounding_box(of->query_co_ord(), of->query_room_size()));
} /* add_fixed_room() */

/**
 * This method adds a fixed room from an object.
 * @param of the object file
 * @add add_fixed_room()
 * @add add_fixed_room_coord()
 */
void add_fixed_room_object(object of) {
  add_internal_fixed_room(file_name(of), of, of->query_co_ord(),
                    bounding_box(of->query_co_ord(), of->query_room_size()));
} /* add_fixed_room() */

/**
 * This method adds a fixed room with a room and a co-ordinate.
 * @param f the file name of the room
 * @param coord the coordinate of the room
 * @param size the size of the room
 * @add add_fixed_room_object()
 * @add add_fixed_room()
 */
void add_fixed_room_coordinate(string f, int* coord, int* size) {
    add_internal_fixed_room(f, 0, coord, bounding_box(coord, size));
} /* add_fixed_room_coordinate() */

/**
 * This method is called from a loaded object to setup the fixed room
 * into the topology.
 */
void setup_fixed_room() {
  object shad, r;
  int i;

  r = previous_object();
  shad = clone_object(FIXED_SHADOW);
  if (!objectp(shad)) {
    error(sprintf("Couldn't create shadow for fixed room %O.\n", r));
    return;
  }
  shad->attach(r);
  shad->set_area_handler(file_name(this_object()));
  if (undefinedp(i = _fixed_room_index[file_name(r)])) {
    error(sprintf("Couldn't find entry for fixed room %O.\n", r));
  }
  r->set_co_ord(_fixed_rooms[i]->coord);
  //tell_creator("jeremy", "%O coords = %O\n", r, r->query_co_ord());
} /* setup_fixed_room() */

/**
 * This method finds the room as the specified co-ordinates.
 * @param coord the coordinate to look up the room at
 * @return the room
 */
object find_room_at_coord(int *coord) {
  int i;
  object ob;

  if (_dbg_lvl > 0) {
    tell_creator(_debugger, "%s::find_room_at_coord()\n"
                 "  coord: %O\n",
                 file_name(this_object()), coord);
  }
  // Check fixed rooms first...
  for (i = 0; i < sizeof(_fixed_rooms); i++) {
    if (in_bbox(coord, _fixed_rooms[i]->bbox)) {
      if (!objectp(_fixed_rooms[i]->ob)) {
        _fixed_rooms[i]->ob = load_object(_fixed_rooms[i]->path);
      }
      return _fixed_rooms[i]->ob;
    }
  }
  // ...then irooms...
  for (i = 0; i < sizeof(_iroom_handlers); i++) {
    if (objectp(ob = _iroom_handlers[i]->find_room_at_coord(coord))) {
      return ob;
    }
  }
  // ...finally, check areas...
  for (i = 0; i < sizeof(_area_handlers); i++) {
    if (objectp(ob = _area_handlers[i]->find_room_at_coord(coord))) {
      return ob;
    }
  }
  return 0;
} /* find_room_at_coord() */

/**
 * This method does a virtual object lookup for the room.
 * @param x the x coord
 * @param y the y coord
 * @param z the z coord
 */
object create_virtual_object(int x, int y, int z) {
   if (undefinedp(x) || undefinedp(y) || undefinedp(z)) {
      return 0;
   }

   return find_room_at_coord(({ x, y, z }));
} /* create_virtual_object() */

/**
 * This method finds the room at the specified exit in the specified room.
 * @param r the room to look up
 * @param d the dimension of the room
 * @param direc the direction we are moving in
 * @return the room at the exit
 */
object find_room_at_exit(object r, int *d, string direc) {
  int i, s, dist, max_dist, max_iroom, *coord, *coord_r, *coord_ob;
  string msg;
  object ob, *irooms = ({ });
  mixed size_r;
  class bounding_box bbox_r;

  if (_dbg_lvl > 0) {
    tell_creator(_debugger, "%s::find_room_at_exit()\n"
                 "  r: %O\n"
                 "  d: %O\n"
                 "  direc: %O\n",
                 file_name(this_object()), r, d, direc);
  }
  if (!arrayp(d)) {
    return 0;
  }
  coord = r->query_co_ord();
  // Some rooms (like milestones) have "fake" sizes.
  size_r = r->query_actual_room_size();
  if (!arrayp(size_r)) {
    size_r = r->query_room_size();
    if (!arrayp(size_r)) {
      // Must be a single int for all 3 dimensions.
      size_r = ({ size_r, size_r, size_r });
    }
  }
  coord_r = allocate(3);
  for (i = 0; i < 3; i++) {
    // This assumes the rooms are adjacent, either on an edge or at
    // a corner (note to self: figure out why this seems to hit areas
    // before irooms).
    //coord_r[i] = coord[i] + (size_r[i] + 1) * d[i];
    coord_r[i] = coord[i] + 2 * size_r[i] * d[i];
  }
  // Check fixed rooms first...
  for (i = 0; i < sizeof(_fixed_rooms); i++) {
    if (in_bbox(coord_r, _fixed_rooms[i]->bbox)) {
      if (!objectp(_fixed_rooms[i]->ob)) {
        _fixed_rooms[i]->ob = load_object(_fixed_rooms[i]->path);
      }
      // Check that the fixed room allows entrances from this direction.
      msg = evaluate(_fixed_rooms[i]->ob->query_topo_barrier(direc));
      if (!undefinedp(msg)) {
        if (!stringp(msg)) {
          msg = "You can't go that way.\n";
        }
        notify_fail(msg);
        return 0;
      }
      return _fixed_rooms[i]->ob;
    }
  }
  // ...then irooms...
  // This is a bit complicated.  I need to check the distance to
  // the rooms returned by all the handlers and pick the closest.
  bbox_r = bounding_box(coord, size_r);
  for (i = 0; i < sizeof(_iroom_handlers); i++) {
    ob = _iroom_handlers[i]->find_room_at_crossing(coord, coord_r);
    tell_creator("rhinehold", "ob = %O\n", ob);
    if (objectp(ob /*(= _iroom_handlers[i]->find_room_at_crossing(coord, coord_r)*/)
        && (ob != r)) {
      if (_dbg_lvl > 1) {
        tell_creator(_debugger, "%s::find_room_at_exit()\n"
                     "  %O->find_room_at_crossing() returned %O\n",
                     file_name(this_object()), _iroom_handlers[i], ob);
      }
      // This is a kludge, but I can't think of a way around it.  Milestones
      // (like all normal rooms), get their coords set in a callout, so
      // I can't calculate the distance here.  I'll have to assume that
      // a room without coordinates is the "correct" one.
      if (!arrayp(ob->query_co_ord())) {
        return ob;
      }
      // Ignore irooms that are in the current room's bounding box, if
      // the current room is a fixed room.
      // *** NOTE: I'm not sure if this is sufficient.  There are cases
      // where I want irooms to take precedence (like the path around
      // the maze), but there are others where the current room should
      // take precedence (like s_cara03b).  Hopefully, the latter case
      // is always a fixed room.
      if (r->query_fixed_room() && in_bbox(ob->query_co_ord(), bbox_r)) {
        continue;
      }
      irooms += ({ ob });
    }
  }
  if ((s = sizeof(irooms)) > 0) {
    if (s == 1) {
      return irooms[0];
    } else {
      // Hopefully this won't happen often...
      max_dist = 0;
      max_iroom = -1;
      for (i = 0; i < s; i++) {
        coord_ob = irooms[i]->query_co_ord();
        dist = (coord[0] - coord_ob[0])*(coord[0] - coord_ob[0]) +
          (coord[1] - coord_ob[1])*(coord[1] - coord_ob[1]);
        if (dist > max_dist) {
          max_dist = dist;
          max_iroom = i;
        }
      }
      if (max_iroom >= 0) {
        return irooms[max_iroom];
      }
    }
  }
  // ...finally, check areas...
  for (i = 0; i < sizeof(_area_handlers); i++) {
    if (objectp(ob = _area_handlers[i]->find_room_at_exit(r, d))) {
      if (_dbg_lvl > 1) {
        tell_creator(_debugger, "%s::find_room_at_exit()\n"
                     "  %O->find_room_at_exit() returned %O\n",
                     file_name(this_object()), _area_handlers[i], ob);
      }
      return ob;
    }
  }
  return 0;
} /* find_room_at_exit() */

// This is a testing convenience function
/**
 * This method allows you to be moved quickly to a room at the specified
 * co-ordinate.
 * @param coord the coordinate to go to
 */
int goto_room_at_coord(int *coord) {
  return this_player()->move_with_look(find_room_at_coord(coord));
} /* goto_room_at_coord() */

/**
 * This method will make a map of the specified width based on the data in
 * the topography area.
 * @param width the width of the map
 * @return the map
 */
string query_text_map(int width) {
   int x;
   int y;
   int maxy;
   string map;
   object room;

   map = "";
   for (y = 0; y < maxy; y++) {
      for (x = 0; x < width; x++) {
         room = find_room_at_coord( ({ x, y, 0 }) );
         if (!room) {
            map += " ";
         } else if (!room->query_room_letter()) {
            map += "?";
         } else {
            map += room->query_room_letter();
         }
      }
      map += "\n";
   }
   return map;
} /* query_text_map() */