lima-1.0b5/
lima-1.0b5/driver/
lima-1.0b5/driver/ChangeLog.old/
lima-1.0b5/driver/Win32/
lima-1.0b5/driver/compat/
lima-1.0b5/driver/include/
lima-1.0b5/driver/testsuite/
lima-1.0b5/driver/testsuite/clone/
lima-1.0b5/driver/testsuite/command/
lima-1.0b5/driver/testsuite/data/
lima-1.0b5/driver/testsuite/etc/
lima-1.0b5/driver/testsuite/include/
lima-1.0b5/driver/testsuite/inherit/
lima-1.0b5/driver/testsuite/inherit/master/
lima-1.0b5/driver/testsuite/log/
lima-1.0b5/driver/testsuite/single/
lima-1.0b5/driver/testsuite/single/tests/compiler/
lima-1.0b5/driver/testsuite/single/tests/efuns/
lima-1.0b5/driver/testsuite/single/tests/operators/
lima-1.0b5/driver/testsuite/u/
lima-1.0b5/driver/tmp/
lima-1.0b5/etc/
lima-1.0b5/lib/WWW/help/
lima-1.0b5/lib/cmds/
lima-1.0b5/lib/cmds/create/
lima-1.0b5/lib/cmds/player/attic/
lima-1.0b5/lib/contrib/bboard/
lima-1.0b5/lib/contrib/boards/
lima-1.0b5/lib/contrib/marriage/
lima-1.0b5/lib/contrib/roommaker/
lima-1.0b5/lib/contrib/transient_effect/
lima-1.0b5/lib/daemons/channel/
lima-1.0b5/lib/daemons/imud/
lima-1.0b5/lib/data/
lima-1.0b5/lib/data/config/
lima-1.0b5/lib/data/links/
lima-1.0b5/lib/data/news/
lima-1.0b5/lib/data/players/
lima-1.0b5/lib/data/secure/
lima-1.0b5/lib/domains/
lima-1.0b5/lib/domains/std/2.4.5/maze1/
lima-1.0b5/lib/domains/std/2.4.5/npc/
lima-1.0b5/lib/domains/std/2.4.5/post_dir/
lima-1.0b5/lib/domains/std/2.4.5/sub/
lima-1.0b5/lib/domains/std/camera/
lima-1.0b5/lib/domains/std/config/
lima-1.0b5/lib/domains/std/cult/
lima-1.0b5/lib/domains/std/effects/
lima-1.0b5/lib/domains/std/misc/
lima-1.0b5/lib/domains/std/monsters/
lima-1.0b5/lib/domains/std/recorder/
lima-1.0b5/lib/domains/std/rooms/
lima-1.0b5/lib/domains/std/rooms/beach/
lima-1.0b5/lib/domains/std/rooms/labyrinth/
lima-1.0b5/lib/domains/std/school/
lima-1.0b5/lib/domains/std/school/O/
lima-1.0b5/lib/domains/std/spells/
lima-1.0b5/lib/domains/std/spells/stock-mage/
lima-1.0b5/lib/domains/std/spells/stock-priest/
lima-1.0b5/lib/help/
lima-1.0b5/lib/help/admin/
lima-1.0b5/lib/help/hints/General_Questions/
lima-1.0b5/lib/help/hints/Pirate_Quest/
lima-1.0b5/lib/help/player/
lima-1.0b5/lib/help/player/bin/
lima-1.0b5/lib/help/player/quests/
lima-1.0b5/lib/help/wizard/
lima-1.0b5/lib/help/wizard/coding/guilds/
lima-1.0b5/lib/help/wizard/coding/rooms/
lima-1.0b5/lib/help/wizard/lib/daemons/
lima-1.0b5/lib/help/wizard/lib/lfun/
lima-1.0b5/lib/help/wizard/lib/std/
lima-1.0b5/lib/help/wizard/mudos_doc/
lima-1.0b5/lib/help/wizard/mudos_doc/applies/
lima-1.0b5/lib/help/wizard/mudos_doc/applies/interactive/
lima-1.0b5/lib/help/wizard/mudos_doc/applies/parsing/
lima-1.0b5/lib/help/wizard/mudos_doc/concepts/
lima-1.0b5/lib/help/wizard/mudos_doc/driver/
lima-1.0b5/lib/help/wizard/mudos_doc/efuns/
lima-1.0b5/lib/help/wizard/mudos_doc/efuns/arrays/
lima-1.0b5/lib/help/wizard/mudos_doc/efuns/buffers/
lima-1.0b5/lib/help/wizard/mudos_doc/efuns/compile/
lima-1.0b5/lib/help/wizard/mudos_doc/efuns/filesystem/
lima-1.0b5/lib/help/wizard/mudos_doc/efuns/floats/
lima-1.0b5/lib/help/wizard/mudos_doc/efuns/functions/
lima-1.0b5/lib/help/wizard/mudos_doc/efuns/general/
lima-1.0b5/lib/help/wizard/mudos_doc/efuns/mappings/
lima-1.0b5/lib/help/wizard/mudos_doc/efuns/mixed/
lima-1.0b5/lib/help/wizard/mudos_doc/efuns/numbers/
lima-1.0b5/lib/help/wizard/mudos_doc/efuns/parsing/
lima-1.0b5/lib/help/wizard/mudos_doc/lpc/constructs/
lima-1.0b5/lib/help/wizard/mudos_doc/lpc/types/
lima-1.0b5/lib/include/driver/
lima-1.0b5/lib/log/
lima-1.0b5/lib/obj/admtool/
lima-1.0b5/lib/obj/admtool/internal/
lima-1.0b5/lib/obj/admtool/mudinfo/
lima-1.0b5/lib/obj/admtool/secure/
lima-1.0b5/lib/obj/secure/
lima-1.0b5/lib/obj/secure/cmd/
lima-1.0b5/lib/obj/secure/mailers/
lima-1.0b5/lib/obj/secure/shell/
lima-1.0b5/lib/obj/secure/shell/classes/
lima-1.0b5/lib/obj/tasktool/
lima-1.0b5/lib/obj/tasktool/internal/
lima-1.0b5/lib/open/
lima-1.0b5/lib/secure/
lima-1.0b5/lib/secure/cgi/
lima-1.0b5/lib/secure/modules/
lima-1.0b5/lib/secure/simul_efun/
lima-1.0b5/lib/std/adversary/
lima-1.0b5/lib/std/adversary/advancement/
lima-1.0b5/lib/std/adversary/armor/
lima-1.0b5/lib/std/adversary/blows/
lima-1.0b5/lib/std/adversary/death/
lima-1.0b5/lib/std/adversary/formula/
lima-1.0b5/lib/std/adversary/health/
lima-1.0b5/lib/std/adversary/pulse/
lima-1.0b5/lib/std/adversary/wield/
lima-1.0b5/lib/std/classes/event_info/
lima-1.0b5/lib/std/container/
lima-1.0b5/lib/std/living/
lima-1.0b5/lib/std/modules/contrib/
lima-1.0b5/lib/std/patterns/
lima-1.0b5/lib/std/race/
lima-1.0b5/lib/std/race/restricted/
lima-1.0b5/lib/std/room/
lima-1.0b5/lib/tmp/
lima-1.0b5/lib/trans/
lima-1.0b5/lib/trans/admincmds/
lima-1.0b5/lib/trans/obj/
lima-1.0b5/lib/wiz/
/* Do not remove the headers from this file! see /USAGE for more info. */
//  a room.c
// Rust@ZorkMUD,   Jan 12, 1994
// Nevyn@GUE       1-14-94
// Cleave@ZorkMUD 2-25-94 Added long(), long default.
// Beek@ZorkMud   4-6-94  Added the way cool exit code.  Look at the
//      lfun docs.
// Rust wrote in_room stuff to make looking in rooms more interesting
// Beek & Rust have both done a bit of work on this since....
// August 24 - Beek added light
// Satan@ArcadiaF 10-29-95 Added the OBVIOUS_EXITS_BOTTOM, casue I don't like
//      the way the exits look on the top, and Beek didn't want to fix it.
// Satan@ArcadiaF 10-30-95 Added set_hidden_exits(). This makes a list that
//      of exits that are hidden from all in the room.
//      Wizards can see DARK_EXITS as they are denoted with a *name format.
// 951113, Deathblade: removed some obsolete vars; made them all private

#include <setbit.h>
#include <move.h>
#include <hooks.h>

inherit CONTAINER;
inherit M_ITEMS;
inherit M_GETTABLE;
inherit M_EXIT;
inherit __DIR__ "room/roomdesc";
inherit __DIR__ "room/state";

private nosave string array area_names = ({ });
private string listen, smell;
private nosave mixed chat_msg;
private nosave int chat_period = 15;
private nosave int tag;

//:FUNCTION stat_me
//Returns some debugging info about the object.  Shows the container info,
//as well as the short and exits.
string stat_me()
{
    return sprintf("Room: %s [ %s ]\n\n",
      short(), implode(query_exit_directions(1), ", ")) +
    container::stat_me();
}

//:FUNCTION set_brief
//Set the name of the room seen at the top of the description and in brief mode
void set_brief(string str) {
    set_proper_name(str);
}

//:FUNCTION can_hold_water
//Return 1 if the object can hold water.
/* by default, rooms can hold water */
int can_hold_water()
{
    return 1;
}

void create(array args...)
{
    container::create();

    // cloned rooms will already have this stuff happen... We need this
    // because setup() is the way people configure mudlib objects.
    // Almost always, except in the case of rooms, game objects are clones.

    //### Small problem here; some rooms are clones, and this bails for them.
    //### We really need a better way to test if we should call setup().
    //###
    //### Virtual grids, for example, usually depend on cloned rooms working
    //### properly.
    //###
    //### BTW, contrary to the above, it appears this is *NOT* already done for cloned rooms

#if 0
    if( !clonep() )
    {
#endif
	// initialize the mudlib (default) stuff, then the area coder's
	mudlib_setup();
	this_object()->internal_setup();

	setup(args...);
#if 0
    }
#endif
}

void mudlib_setup()
{
    ::mudlib_setup();
    set_light(DEFAULT_LIGHT_LEVEL);
    /* First add the relation 'in'. */
    add_relation("in",1000000);
    /* Make it the default relation for all rooms */
    set_default_relation("in");
    add_id_no_plural("here");
    add_id("environment");
    set_gettable( -1 );
    set_flag( ATTACHED );
}

//:FUNCTION set_area
//Used by m_wander to prevent monsters from wandering to far.
//Can either be a string, or an array of strings
void set_area(string array names...)
{
    area_names = names;
}

//:FUNCTION query_area
//Find out what 'areas' the room belongs to.  See set_area.
string array query_area()
{
    return area_names;
}

string query_name()
{
    return "the ground";
}

string get_brief()
{
    return short();
}

void possible_light_change(int old_light, int new_light) {
    if (old_light && !new_light) {
	tell_from_inside(this_object(), "The room goes dark.\n");
    } else 
    if (!old_light && new_light) {
	tell_from_inside(this_object(), "You can see again.\n");
    }
}

void set_light(int x) {
    int old = query_light();

    ::set_light(x);

    possible_light_change(old, query_light());
}

void adjust_light(int x) {
    int old = query_light();

    ::adjust_light(x);

    possible_light_change(old, query_light());
}

mixed direct_get_obj(object ob)
{
    if( this_object() == environment( this_body()))
	return "#A surreal idea.";
    return ::direct_get_obj(ob);
}

mapping lpscript_attributes() {
    return ([
      "area" : ({ LPSCRIPT_STRING, "setup", "set_area" }),
      "brief" : ({ LPSCRIPT_STRING, "setup", "set_brief" }),
      "exits" : ({ LPSCRIPT_MAPPING, "setup", "set_exits" }),
      "state" : ({ LPSCRIPT_TWO, (: ({ "setup", "set_state_description(\"" + $1 + "\", \"" + $2[0] + "\")" }) :) }),
      "item" : ({ LPSCRIPT_SPECIAL, (: ({ "setup", "add_item(\"" + $1[0] + "\", \"" + implode($1[1..], " ") + "\")" }) :) })
    ]);
}

/* tweak the base long description to add the state stuff */
string get_base_long()
{
    string base = ::get_base_long();
    array fmt;
    int i;
    
    fmt = reg_assoc(base, ({ "\\$[A-Za-z_]*" }), ({ 1 }))[0];

    for (i = 1; i < sizeof(fmt); i++) {
	string tmp;
	
	if (tmp = query_state_desc(fmt[i][1..]))
	    fmt[i] = tmp;
    }

    base = implode(fmt, "");
    if (base[<1] != '\n') base += "\n";
    return base;
}


string long()
{
#ifdef OBVIOUS_EXITS_BOTTOM
    string objtally = show_objects();
    if( sizeof(objtally))
	objtally = "You also see:\n" + objtally;
    return sprintf("%sObvious Exits: %%^ROOM_EXIT%%^%s%%^RESET%%^\n%s",
      (dont_show_long() ? "" : simple_long()),
      show_exits(),
      objtally);
#else
    return sprintf("%s%s",
      (dont_show_long() ? "" : simple_long()),
      show_objects());
#endif
}

//:FUNCTION long_without_object
//This is used by things like furniture, so the furniture can use the
//same long as the room, but not see itself in the description.
string long_without_object(object o)
{
#ifdef OBVIOUS_EXITS_BOTTOM
    return sprintf("%sObvious Exits: %%^ROOM_EXIT%%^%s%%^RESET%%^\n%s",
      simple_long(),
      show_exits(),
      show_objects(o));
#else
    return sprintf("%s%s",
      simple_long(),
      show_objects(o));
#endif
}

void set_listen(string str) { listen = str; }

string query_listen() { return listen; }

void set_smell(string str) { smell = str; }

string query_smell() { return smell; }

void do_listen()
{
  if(listen)
    write(listen);
  else
    write( "You hear nothing unusual.\n" );
}

void do_pray() { write( "Nothing special happens.\n" ); }

void do_smell()
{
  if(smell)
    write(smell);
  else
    write( "You smell nothing unusual.\n" );
}

int listeners()
{
  object array inv = all_inventory(this_object());
  return sizeof(filter(inv, (: $1->query_link() :) ) );
}

void check_anybody_here()
{
  if(listeners())
  {
    tag = call_out("room_chat", chat_period, chat_msg);
  } else {
    remove_call_out(tag);
    tag = 0;
  }
}

void room_chat()
{
  if(stringp(chat_msg))
    tell_from_outside(this_object(), chat_msg + "\n");
  else if(arrayp(chat_msg))
    tell_from_outside(this_object(), choice(chat_msg) + "\n");
  else if(functionp(chat_msg))
    tell_from_outside(this_object(), evaluate(chat_msg) + "\n");
  check_anybody_here();
}

void departure(object who)
{
  call_out("check_anybody_here",0);
}

void arrival(object who)
{
  if(!listeners())
    tag = call_out("room_chat", chat_period, chat_msg);
}

void set_room_chat(mixed chat, int interval)
{
  chat_msg = chat;
  chat_period = interval;

  add_hook("object_arrived", (: arrival :) );
  add_hook("object_left", (: departure :) );

  if(tag)
  {
    remove_call_out(tag);
    tag = 0;
  }

  call_out("check_anybody_here",0);
}