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. */

/* 
 * Handler for simple string exits.  For anything more complex than what is
 * provided here, look at M_COMPLEX_EXIT.  With it, one is better able to 
 * utilize the abilities of OBJ and the parser to really flesh out an exit
 * and make it spectacular. 
 */

/* Major revamp done in Tigran's Great Exit Rewrite of 1999 */
#include <hooks.h>

inherit "/std/classes/move";

private mapping exits = ([]);
private string array hidden_exits = ({});
private string default_error;
private string default_desc;
private mixed default_exit_message;
private mixed default_enter_message;
private mixed default_check;
private mixed default_desc;
private nosave mixed base=(:file_name(this_object())[0..strsrch(file_name(this_object()),'/',-1)] :);

varargs mixed call_hooks(string tag,mixed func,mixed start,array args...);
mixed query_exit_check(string);
mapping debug_exits();
string array query_hidden_exits();

/* 
 * DEFAULTS AND ERRORS
 */

//:FUNCTION query_default_exit_message
//Return the default exit message
string query_default_exit_message() {
  return evaluate(default_exit_message);
}

//:FUNCTION query_default_enter_message
//Return the default enter message
string query_default_enter_message() {
  return evaluate(default_enter_message);
}

//:FUNCTION set_default_exit_message
//Set the default exit message for all exits.
//The argument can be a string, or function pointer 
void set_default_exit_message(mixed arg) {
    default_exit_message = arg;
}

//:FUNCTION set_default_enter_message
//Set the default enter message for all exits
//The argument can be a string or function pointer
void set_default_enter_message(mixed arg) {
    default_enter_message = arg;
}

//:FUNCTION set_default_check
//Set the default check for all exits
//The argument can be a 0, 1, string, or function pointer returning one of
//those
void set_default_check(mixed arg) {
    default_check = arg;
}

//:FUNCTION query_default_check
//Return the defaut check
mixed query_default_check()
{
  return evaluate(default_check);
}

//:FUNCTION set_default_error
//Set the default error message (the message given when someone goes a 
//direction with no exit).  This should be a string or a function ptr 
//returning a string.
void set_default_error(mixed value) {
  default_error = value;
}

//:FUNCTION has_default_error
//Return true if the room has a default exit error
int has_default_error() {
  return !!default_error;
}

//:FUNCTION query_default_error
//Returns the error default error message.
string query_default_error()
{
  if (has_default_error())
    return evaluate(default_error);
  return( "It doesn't appear possible to go that way.\n");
}

/* 
 * EXIT DIRECTIONS
 */

//:FUNCTION query_exit_directions
//Return all of the exit directions controlled by the exit object
//The optional argument determines whether hidden exits are included in this 
//list.  If nonnull, they are included
varargs string array query_exit_directions(int show_hidden)
{
  string array dirs = keys( exits );
  object exit_obs=filter(all_inventory(this_object()),
			 (: $1->is_exit() && $1->query_obvious_description() :) );
  foreach(object exit_ob in exit_obs)
    {
      if(show_hidden||
	 !exit_ob->query_hidden() )
	dirs+=({ exit_ob->query_direction() });
    }
  if (show_hidden)
    return dirs;
  else
    return dirs - hidden_exits;
}

//:FUNCTION show_exits
//Return a string giving the names of exits for the obvious exits line
string show_exits()
{
  string exit_str;
  string array exit_names;
  exit_names = query_exit_directions(0);
  exit_str = ((sizeof(exit_names)) ? implode(exit_names,", ") :"none");
#ifdef WIZARDS_SEE_HIDDEN_EXITS
  if ( wizardp(this_user()) && sizeof(query_hidden_exits()) )
    {
      exit_str += ", *" + implode(query_hidden_exits(), ", *");
    }
#endif
  return exit_str;
}

/* 
 * EXIT MESSAGES
 */

//:FUNCTION query_enter_msg
//Return the enter messages of a given exit
string query_enter_msg(string direction)
{
  object which=present(direction);
  int i;
  if(which && which->is_exit())
    return which->query_method_exit_messages("go");
  i=sizeof(exits[direction]->enter_messages);
  if(!i)
    return query_default_exit_message();
  return evaluate(exits[direction]->enter_messages[random(i)]);
}

//:FUNCTION set_enter_msg
//Set the enter message of a given exit.
//This message will be displayed in the destination room.
//The message can be a fucntion pointer or a string.
//If multiple messages are passed, a random one will be selected when invoked
void set_enter_msg(string direction, mixed array message...)
{
  object which=present(direction);
  if(which && which->is_exit())
  {
    which->set_method_enter_messages("go",message...);
    return;
  }
  exits[direction]->enter_messages = message;
}

//:FUNCTION add_enter_msg
//Add an additional enter message to a given exit.
//The message can be a function pointer or a string
//If multiple messages are passed, a random one will be selected when invoked
void add_enter_msg(string direction, mixed array message...)
{  
  object which=present(direction);
  if(which && which->is_exit())
  {
    which->add_method_enter_messages("go",message...);
    return;
  }
  exits[direction]->enter_messages+=message;
}

//:FUNCTION remove_enter_msg
//Remove an enter emssage from a given exit.
void remove_enter_msg(string direction, mixed array message...)
{
  object which=present(direction);
  if(which && which->is_exit())
  {
    which->remove_method_enter_messages("go",message...);
    return;
  }
  exits[direction]->enter_messages-=message;
}

//:FUNCTION list_enter_msgs
//Return all possible enter messages for a given exit
mixed array list_enter_msgs(string direction)
{
  object which=present(direction);
  if(which && which->is_exit())
    return which->list_method_enter_messages("go");
  return exits[direction]->enter_messages;
}

//:FUNCTION query_exit_msg
//Return the exit messages of a given exit
string query_exit_msg(string direction)
{  
  int i=sizeof(exits[direction]->exit_messages);
  object which=present(direction);
  if(which && which->is_exit())
    return which->query_method_exit_messages("go");
  if(i)
    return evaluate(exits[direction]->exit_messages[random(i)]);
  return query_default_exit_message();
}

//:FUNCTION set_exit_msg
//Set the exit message of a given exit.
//This message will be displayed in the room the body is leaving
void set_exit_msg(string direction, mixed array message...)
{
  object which=present(direction);
  if(which && which->is_exit())
  {
    which->set_method_exit_messages("go",message...);
    return;
  }
  exits[direction]->exit_messages = message;
}

//:FUNCTION add_exit_msg
//Add an additional exit message to a given exit.
//The message can be a function pointer or a string
void add_exit_msg(string direction, mixed array message...)
{
  object which=present(direction);
  if(which && which->is_exit())
  {
    which->add_method_exit_messages("go",message...);
    return;
  }
  exits[direction]->exit_messages+=message;
}

//:FUNCTION remove_exit_msg
//Remove an exit emssage from a given exit.
void remove_exit_msg(string direction, mixed array message...)
{
  object which=present(direction);
  if(which && which->is_exit())
  {
    which->remove_method_exit_messages("go",message...);
    return;
  }
  exits[direction]->exit_messages-=message;
}

//:FUNCTION list_exit_msgs
//List all of the possible exit messages for an exit
mixed array list_exit_msgs(string direction)
{
  object which=present(direction);
  if(which && which->is_exit())
    return which->list_method_exit_messages("go");
  return exits[direction]->exit_messages;
}

/* 
 * EXIT DESTINATIONS
 */

/* eval_dest() returns the full pathname of the destination of the exit, or an 
 * error. */
private string eval_dest(mixed arg)
{
  mixed tmp;
  if(!arg||arg=="")
    return 0;
  tmp=(class move_data)exits[arg]->destination;
  tmp = evaluate(tmp);
  if (!stringp(tmp))
    return 0;
  if (tmp[0] == '#') 
    return tmp;
  return absolute_path(tmp,evaluate(base));
}

//:FUNCTION query_exit_destination
//Return the destination path of the given exit.
varargs string query_exit_destination(string arg)
{
  object which=present(arg);
  if(which && which->is_exit())
    return which->query_method_destination("go");
  return eval_dest(arg);
}

/* 
 * EXIT DESCRIPTIONS
 */

//:FUNCTION query_exit_description
//Returns the description of the given exit.
string query_exit_description(string direction)
{
  object which = present(direction);
  if(which && which->is_exit())
    return which->query_method_description("go");
  if(exits[direction])
    return evaluate(exits[direction]->description);
  return 0;
}

//:FUNCTION set_exit_description
//Set the description of an exit.
void set_exit_description(string direction, mixed description)
{  
  object which=present(direction);
  if(which && which->is_exit())
  {
    which->set_long(description);
    return;
  }
  exits[direction]->description = description;
}

/* 
 * EXIT CHECKS
 */

//:FUNCTION query_exit_check
//Return whether or not the exit can be passed through
mixed query_exit_check(string direction)
{
  if(member_array(direction,keys(exits))==-1)
    return;
  return exits[direction]->checks;
}

//:FUNCTION set_exit_check
//Function setting the check funciton for the exit
void set_exit_check(string direction, function f)
{
  object which=present(direction);
  if(which && which->is_exit())
  {
    which->set_method_check("go",f);
    return;
  }
  exits[direction]->checks = f;
}

/* 
 * EXIT ADDITION AND REMOVAL
 */

//:FUNCTION delete_exit
//Remove a single exit from the room.  The direction should be an exit
//name.
void delete_exit(mixed direction)
{
  object which=present(direction);
  if(which && which->is_exit())
    destruct(which);
  map_delete(exits, direction);
}
 
//:FUNCTION add_exit
//Add an exit to the object with a destination.  .
//Add the value should be a filename or a more complex structure as
//described in the exits doc.
varargs void add_exit(mixed direction, mixed destination)
{
#ifdef USE_COMPLEX_EXITS
  object exit_ob=new(COMPLEX_EXIT_OBJ);
  exit_ob->add_method(direction,destination);
  return;
#else
  class move_data new_exit=new(class move_data);
  new_exit->description=default_desc;
  new_exit->enter_messages=({});
  new_exit->exit_messages=({});
  new_exit->destination=destination;
  if (stringp(destination) && strlen(destination) == 0)
    error("Bogus exit passed into add_exit");
  if (stringp(destination) && destination[0] == '#')
    new_exit->checks = destination[1..];
  else
    new_exit->checks = 1;
  exits[direction] = new_exit;
#endif
}

//:FUNCTION set_exits
//Sets the exit mapping of a room.  The keys should be exit names, the values
//should be either filenames or more complex structures described in the
//exits doc
void set_exits( mapping new_exits )
{
  mixed key; 
  if ( mapp(new_exits) )
    foreach(string direction,mixed destination in new_exits)
      add_exit(direction,destination);
}

/* 
 * HIDDEN EXITS 
 */

//:FUNCTION set_hidden_exits
//This is the list of exits to NOT be shown to the mortals in the room.
//If "all" is any of the arguements in exits_list all exits for the object 
//will be marked as hidden regardless to the rest of the arguments.
void set_hidden_exits( string array exits_list ... )
{
  if(member_array("all",exits_list)>-1)
    hidden_exits=keys(exits);
  else
    hidden_exits = exits_list;
}

//:FUNCTION add_hidden_exit
//Make a given exit direction a hidden exit.  See set_hidden_exits
void add_hidden_exit( string array exits_list ... )
{
  if( sizeof( exits_list ) == 1 && exits_list[0] == "all" )
    hidden_exits = query_exit_directions(1);
  else
    hidden_exits += exits_list;
}

//:FUNCTION remove_hidden_exit
//Make a given exit direction no longer a hidden exit.  See set_hidden_exits
void remove_hidden_exit( string array exits_list ... )
{
  if( sizeof( exits_list ) == 1 && exits_list[0] == "all" )
    hidden_exits = 0;
  else
    hidden_exits -= exits_list;
}

//:FUNCTION query_hidden_exits
//Return all of the hidden exits controlled by the exit object
string array query_hidden_exits() {
  string exit_obs=filter(all_inventory(this_object()), (: $1->is_exit() && $1->query_hidden() :) );
  
  return hidden_exits + exit_obs->query_direction();
}

/*
 * VERB RULES
 */
/* Called by the go verb
 * The return value determines whether or not the exit can be used.  A 
 * string returned is an error, 0 is simple failure (parser makes the 
 * error, and 1 is success */
mixed can_go_str(string arg)
{
  mixed ret=evaluate(query_exit_check(arg));
  if(!stringp(ret) && ret!=1 && is_normal_direction(arg))
    return query_default_error();
  return ret;
}

void do_go_str(string dir)
{
  class move_data exit=new(class move_data);
  if (call_hooks("block_" + dir, HOOK_LOR, 0, dir)
      || call_hooks("block_all", HOOK_LOR, 0, dir))
    return;  
  exit->destination=query_exit_destination(dir); 
  exit->exit_messages=query_exit_msg(dir);
  exit->enter_messages=query_enter_msg(dir);
  exit->exit_dir=dir;
  if (!this_body()->query_driving_vehicle())
  {
    if(!exit->exit_messages)
      exit->exit_messages=this_body()->query_msg("leave");
    if(!exit->enter_messages)
      exit->enter_messages=this_body()->query_msg("enter");
/* Normal movement, which should be the scope of this module should
 * always send to the method "in" */
    exit->who = this_body();
    this_body()->move_to(exit);
  } else {
    exit->who = environment(this_body());
    environment(this_body())->move_to(exit);
  }
}
/* 
 * DEBUGGING
 */
//:FUNCTION debug_exits
//Return all of the exit info contained within the object
mapping debug_exits()
{
  return copy(exits);
}

//:FUNCTION query_base
//Return the evaluated string which is the directory the object is in.
string query_base()
{
  return evaluate(base);
}

//:FUNCTION set_base
//Set the base directory to be used by the exits of the environment.
void set_base(mixed what)
{
  base=what;
}

mapping lpscript_attributes() {
  return (["exits" : ({ LPSCRIPT_MAPPING, "setup", "set_exits" }),
	  "hidden_exits" : ({ LPSCRIPT_LIST, "setup", "set_hidden_exits" }),
	  "default_exit_message" : ({ LPSCRIPT_STRING, "setup", "set_default_exit_message" }),
	  "default_enter_message" : ({ LPSCRIPT_STRING, "setup", "set_default_enter_message" }),
	  "wrong_exit" : ({ LPSCRIPT_STRING, "setup", "set_default_error"}),
	  "enter_msg" : ({ LPSCRIPT_TWO,  (: ({ "setup", "set_enter_msg(\""+$1+"\",\""+$2[0]+"\")" }) :) }),
	  "exit_msg" : ({ LPSCRIPT_TWO, (: ({ "setup", "set_exit_msg(\""+$1+"\",\""+$2[0]+"\")" }) :) }),
	  "exit_description" : ({ LPSCRIPT_TWO, (: ({ "setup", "set_exit_description(\""+$1+"\",\""+$2[0]+"\")" }) :) }),
	  ]);
}