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

/* 
 * Written by Tigran@Illusions,Lima Bean. 2/6/99
 * The purpose of this inheritable is to make it easier for writing complex 
 * exit type objects.  This is intended to be used by vehicles, and furniture
 * and such things as that.  
 * 
 * Unlike SIMPLE_EXIT_OBJ only one exit can be assigned to COMPLEX_EXIT.  
 * This will serve to allow more full utilization of OBJ and all of the 
 * features of the parser.
 */

inherit "/std/classes/move";

/* 
 * VARIABLES
 */

private mixed hidden;            /* Is this a hidden exit? */ 
private mapping methods=([]);    /* All of the data for methods of this exit */
private mixed obvious_desc;      /* The obvious exit description */
private mixed base=this_object();/* The base directory to determine exit 
				  * destinations from.  This can be either a
				  * string, object, or function pointer */

/* 
 * PROTOTYPES
 */
string query_primary_id();
string array list_methods();
string the_short();
string query_primary_name();

/* 
 * FUNCTIONS
 */

//:FUNCTION is_exit
//Return whether or not the object is an exit. 
int is_exit()
{
    return 1;
}

private string array all_methods_matched(string method)
{
    string verb;
    string prep;
    string array matches=({});
    /* The first word of the method is expected to be the verb, the rest is 
     * a preposition, if it exists.  If it is only one word, that is the verb */
    if(sscanf(method,"%s %s",verb,prep)==2)
    {
	/* Translate the preposition to it's base form */
	prep=PREPOSITION_D->translate_preposition(prep);
	/* Put the method back together */
	method=sprintf("%s %s",verb,prep);
    }
    /* Must sweep through the methods to find matches.*/
    foreach(string test_method in METHOD_D->list_methods())
    {
	if(member_array(method,METHOD_D->list_method_equivalents(test_method))!=-1)
	{
	    matches+=({test_method});
	}
    }
    return matches;
}

/* Return an array of all of the methods which might match the method passed
 * to the function.  It breaks down the preposition to it's lowest form before
 * making its determination, allowing for the fullest range of possible forms.
 */
private string array methods_matched(string method)
{
    string array matches=all_methods_matched(method);
    /* We only want to return those matches which are also methods on this object
     * so eliminate those that aren't */
    matches=filter(matches, (: member_array($1,list_methods() ) > -1 :) );
    /* Return the matches */
    return matches;
}

//:FUNCTION prime_method
//This function merely returns nonzero if the argument is a prime method.  More
//specifically this means that the method is one of the root methods that 
//others can be built off of.
int prime_method(string method)
{
    string verb;
    string prep;
    string array matches=({});
    /* The first word of the method is expected to be the verb, the rest is 
     * a preposition, if it exists.  If it is only one word, that is the verb */
    if(sscanf(method,"%s %s",verb,prep)==2)
    {
	/* Translate the preposition to it's base form */
	prep=PREPOSITION_D->translate_preposition(prep);
	/* Put the method back together */
	method=sprintf("%s %s",verb,prep);
    }
    return member_array(method,METHOD_D->list_methods())>-1;
}

//:FUNCTION set_base
//Set the base directory from which relative paths are figured
//The argument can be a string (directory), object, or function pointer
//evaluating to one of these.
void set_base(mixed foo)
{
    base=foo;
}

//:FUNCTION query_base
//Return the evaluated directory string or object from which relative paths 
//are figured
mixed query_base()
{
    return evaluate(base);
}

/*********   Hidden exits    ********/
//:FUNCTION set_hidden
//Set whether or not the exit is going to show up in the obvious exits list. 
//Possible arguments are an int, or a function pointer.
void set_hidden(int i)
{
    hidden=i;
}

//:FUNCTION query_hidden
//Return 1 if the exit is not to show up as an obvious exit, or 0
int query_hidden()
{
    /* Exits are also hidden if there is no "go" method */
    if(member_array("go",keys(methods))==-1)
	return 0;
    return !!evaluate(hidden);
}

/********   Directions   ********/

//:FUNCTION set_obvious_description
//Set the obvious exit description.  This is the string that will appear in 
//the obvious exits line of a room description.  It can be either a function
//pointer or a string.
void set_obvious_description(mixed desc)
{
    obvious_desc=desc;
}

//:FUNCTION query_obvious_description
//Return the unevaluated obvious description. 
mixed query_obvious_description()
{
    /* If there is no go method, there is no description to be obvious */
    if(member_array("go",keys(methods))==-1)
	return 0;
    return obvious_desc?obvious_desc:query_primary_name();
}

//:FUNCTION query_direction
//Return the diretion of the exit, that is to show up for obvious exits.
string query_direction()
{
    string tmp;
    if(tmp=query_obvious_description())
	return tmp;
    return query_primary_id();
}

/********   Destination   ********/

//:FUNCTION set_method
//Setup a go method.  The first argument is the verb to be used, the second 
//argument is the destination to move the body to when invoked successfully,
//the third argument is the check to be performed before invoking the method
//the fourth argument is an array of possible exit messages, and the fifth
//argument is an array of possible enter messages.  Only the first two
//arguments are required, the rest are optional.
varargs void set_method(string method,mixed destination,mixed checks,mixed array exit_messages,mixed array enter_messages)
{
    class move_data new_method=new(class move_data);
    string array matches=all_methods_matched(method);
    if(sizeof(matches)!=1&&!prime_method(method))
    {
	error(sprintf("Cannot set method '%s'.  Method is either too ambiguous "
	    "or should be added to METHOD_D",
	    method));
    }
    if(destination) 
	new_method->destination=destination;
    if(checks)
	new_method->checks=checks;
    else 
	new_method->checks=1;
    if(arrayp(exit_messages))
	new_method->exit_messages=exit_messages;
    else if(stringp(exit_messages))
	new_method->exit_messages=({exit_messages});
    else
	new_method->exit_messages=({});
    if(arrayp(enter_messages))
	new_method->enter_messages=enter_messages;
    else if(stringp(exit_messages))
	new_method->enter_messages=({enter_messages});
    else
	new_method->enter_messages=({});
    new_method->exit_dir=(:the_short:);
    new_method->source=this_object();
    methods[matches[0]]=new_method;
}

//:FUNCTION add_method
//Add a go method.  The first argument is the verb to be used, the second 
//argument is the destination to move the body to when invoked successfully,
//the third argument is the check to be performed before invoking the method
//the fourth argument is an array of possible exit messages, and the fifth
//argument is an array of possible enter messages.  Only the first two
//arguments are required, the rest are optional.
varargs void add_method(string method,mixed destination,mixed checks,mixed array exit_messages,mixed array enter_messages)
{
    set_method(method,destination,checks,exit_messages,enter_messages);
}

//:FUNCTION remove_method
//Remove a go method from the exit
void remove_method(string method)
{
    map_delete(methods,method);
}

//:FUNCTION list_methods
//Return a list of arrays of all of the current go methods of the exit
string array list_methods()
{
    return keys(methods);
}

//:FUNCTION has_method
//Return true if the method exists
int has_method(string method) {
    string array applicable_methods=methods_matched(method);
    if(!sizeof(applicable_methods))
	return 0;
    return 1;
}

//:FUNCTION set_method_checks
//Set the checks for a method.  The checks can be either an int, function
//pointer, or string.
void set_method_checks(string method,mixed checks)
{
    string array applicable_methods=methods_matched(method);
    if(!sizeof(applicable_methods))
	error("Attempted to set_method_checks on a nonexistant method");
    if(sizeof(applicable_methods)>1)
	error("Attempted to set_method_checks on an ambiguous method");
    methods[applicable_methods[0]]->checks=checks;
}

//:FUNCTION query_method_checks
//Return the evaluated checks on the given method.
//If 1 is returned, the checks is successful, 0 - the checks is a failure and 
//the parser will generate an error (maybe), else, a string should be returned
//which is the error message received by the body.
mixed query_method_checks(string method)
{
    string array applicable_methods=methods_matched(method);
    if(!sizeof(applicable_methods))
	error("Attempted to query_method_checks on a nonexistant method");
    if(sizeof(applicable_methods)>1)
	error("Attempted to query_method_checks on an ambiguous method");
    return evaluate(methods[applicable_methods[0]]->checks,
      query_obvious_description(),
      this_body());
}

//:FUNCTION set_method_destination
//Set the destination for a given method
//The first argument is the method to have the destination assigned, and
//the second argument is either a string or function pointer which will return
//a string.
void set_method_destination(string method,mixed destination)
{
    string array applicable_methods=methods_matched(method);
    if(!sizeof(applicable_methods))
	error("Attempted to set_method_destination on a nonexistant method");
    if(sizeof(applicable_methods)>1)
	error("Attempted to set_method_destination on an ambiguous method");
    methods[applicable_methods[0]]->destination=destination;
}

//:FUNCTION query_method_destination
//Return the evaluated destination for the given method.
//The argument is the method being checked
mixed query_method_destination(string method)
{
    string array applicable_methods=methods_matched(method);
    mixed ret;
    if(!sizeof(applicable_methods))
	error("Attempted to query_method_destination on a nonexistant method");
    if(sizeof(applicable_methods)>1)
	error("Attempted to query_method_destination on an ambiguous method");
    ret=evaluate(methods[applicable_methods[0]]->destination);
    if(stringp(ret))
	return absolute_path(ret,query_base());
    return ret;
}

//:FUNCTION set_method_enter_messages
//Set the enter messages to be used by the given method.  
//Acceptable arguments are strings, or function pointers, or an array of 
//either (mixed is acceptable)
//The method is to be seen by the bodies in the room that the body is entering
varargs void set_method_enter_messages(string method,mixed array messages...)
{
    string array applicable_methods=methods_matched(method);
    if(!sizeof(applicable_methods))
	error("Attempted to set_method_enter_messages on a nonexistant method");
    if(sizeof(applicable_methods)>1)
	error("Attempted to set_method_enter_messages on an ambiguous method");
    methods[applicable_methods[0]]->enter_messages=flatten_array(messages);
}

//:FUNCTION add_method_enter_messages
//Add the enter messages to be used by the given method.  
//Acceptable arguments are strings, or function pointers, or an array of 
//either (mixed is acceptable)
//The method is to be seen by the bodies in the room that the body is entering
varargs void add_method_enter_messages(string method,mixed messages...)
{
    string array applicable_methods=methods_matched(method);
    if(!sizeof(applicable_methods))
	error("Attempted to add_method_enter_messages on a nonexistant method");
    if(sizeof(applicable_methods)>1)
	error("Attempted to add_method_enter_messages on an ambiguous method");
    methods[applicable_methods[0]]->enter_messages+=flatten_array(messages);
}

//:FUNCTION remove_method_enter_messages
//Remove the enter messages to be used by the given method.  
//Acceptable arguments are strings, or function pointers, or an array of 
//either (mixed is acceptable)
//The method is to be seen by the bodies in the room that the body is entering
varargs void remove_method_enter_messages(string method,mixed messages...)
{
    string array applicable_methods=methods_matched(method);
    if(!sizeof(applicable_methods))
	error("Attempted to remove_method_enter_messages on a nonexistant method");
    if(sizeof(applicable_methods)>1)
	error("Attempted to remove_method_enter_messages on an ambiguous method");
    methods[applicable_methods[0]]->enter_messages-=flatten_array(messages);
}

//:FUNCTION query_method_enter_message
//Return a random method enter message
//The method is to be seen by the bodies in the room that the body is entering
string query_method_enter_message(string method)
{
    string array applicable_methods=methods_matched(method);
    mixed ret;

    if(!sizeof(applicable_methods))
	error("Attempted to query_method_enter_message on a nonexistant method");
    if(sizeof(applicable_methods)>1)
	error("Attempted to query_method_enter_message on an ambiguous method");
    if(!sizeof(methods[applicable_methods[0]]->enter_messages))
	return;

    ret=methods[applicable_methods[0]]->enter_messages;
    /* We know that ret has to be an array at this point, select one element
     * randomly */
    ret=ret[random(sizeof(ret))];
    /* Evaluate it on the chance it's a function pointer */
    ret=evaluate(ret);
    return ret;
}

//:FUNCTION list_method_enter_messages
//Return an array of the method's enter messages
mixed array list_method_enter_messages(string method)
{
    string array applicable_methods=methods_matched(method);
    if(!sizeof(applicable_methods))
	error("Attempted to list_method_enter_messages on a nonexistant method");
    if(sizeof(applicable_methods)>1)
	error("Attempted to list_method_enter_messages on an ambiguous method");
    return methods[applicable_methods[0]]->enter_messages;
}

//:FUNCTION set_method_exit_messages
//Set the exit messages to be used by the given method.  
//Acceptable arguments are strings, or function pointers, or an array of 
//either (mixed is acceptable)
//The method is to be seen by the bodies in the room that the body is exiting
varargs void set_method_exit_messages(string method,mixed messages...)
{
    string array applicable_methods=methods_matched(method);
    if(!sizeof(applicable_methods))
	error("Attempted to set_method_exit_messages on a nonexistant method");
    if(sizeof(applicable_methods)>1)
	error("Attempted to set_method_exit_messages on an ambiguous method");
    methods[applicable_methods[0]]->exit_messages=flatten_array(messages);
}

//:FUNCTION add_method_exit_messages
//Add the exit messages to be used by the given method.  
//Acceptable arguments are strings, or function pointers, or an array of 
//either (mixed is acceptable)
//The method is to be seen by the bodies in the room that the body is exiting
varargs void add_method_exit_messages(string method,mixed messages...)
{
    string array applicable_methods=methods_matched(method);
    if(!sizeof(applicable_methods))
	error("Attempted to add_method_exit_messages on a nonexistant method");
    if(sizeof(applicable_methods)>1)
	error("Attempted to add_method_exit_messages on an ambiguous method");
    methods[applicable_methods[0]]->exit_messages+=flatten_array(messages);
}

//:FUNCTION remove_method_exit_messages
//Remove the exit messages to be used by the given method.  
//Acceptable arguments are strings, or function pointers, or an array of 
//either (mixed is acceptable)
//The method is to be seen by the bodies in the room that the body is exiting
varargs void remove_method_exit_messages(string method,mixed messages...)
{
    string array applicable_methods=methods_matched(method);
    if(!sizeof(applicable_methods))
	error("Attempted to remove_method_exit_messages on a nonexistant method");
    if(sizeof(applicable_methods)>1)
	error("Attempted to remove_method_exit_messages on an ambiguous method");
    methods[applicable_methods[0]]->exit_messages-=flatten_array(messages);
}

//:FUNCTION query_method_exit_messages
//Return a random method exit message
//The method is to be seen by the bodies in the room that the body is exiting
string query_method_exit_message(string method)
{
    string array applicable_methods=methods_matched(method);
    mixed ret;

    if(!sizeof(applicable_methods))
	error("Attempted to query_method_exit_message on a nonexistant method");
    if(sizeof(applicable_methods)>1)
	error("Attempted to query_method_exit_message on an ambiguous method");
    if(!sizeof(methods[applicable_methods[0]]->exit_messages))
	return;

    ret=methods[applicable_methods[0]]->exit_messages;
    /* We know that ret has to be an array at this point, select one element
     * randomly */
    ret=ret[random(sizeof(ret))];
    /* Evaluate it on the chance it's a function pointer */
    ret=evaluate(ret);
    return ret;
}

//:FUNCTION list_method_exit_messages
//Return an array of the method's exit messages
mixed array list_method_exit_messages(string method)
{
    string array applicable_methods=methods_matched(method);
    if(!sizeof(applicable_methods))
	error("Attempted to list_method_exit_messages on a nonexistant method");
    if(sizeof(applicable_methods)>1)
	error("Attempted to list_method_exit_messages on an ambiguous method");
    return methods[applicable_methods[0]]->exit_messages;
}

/*
 * Parser Rules 
 */
mixed complex_exit_direct_verb_rule(string verb,string rule,mixed args...)
//second_part,mixed third)
{
    string prep;
    string array matches;
    string method;
    /* The first argument is always the verb used. */
    /* The second argument is the rule used.  For our purposes it should always
     * be WRD OBJ or OBJ, but lets make sure, just in case.*/
    if(rule!="WRD OBJ"&&rule!="OBJ")
	return 0;
    // Commenting this out. A direct_verb_rule() check should not error on
    // the format of a particular rule, especially if no previous
    // checks eliminated that kind of rule.  -- Marroc
    //	error(sprintf("Cannot properly parse the rule in complex_exit_direct_verb_rule().\nUnknown Rule: %s",rule));

    if(stringp(args[0]))
	method=sprintf("%s %s",verb,args[0]);
    else 
	method=verb;
    /* Get all possible matches */
    matches=methods_matched(method);
    /* If there are no matches, fail. */
    if(sizeof(matches)==0)
	return 0;
    /* If there are more than one match, it is ambiguous and we can't determine
     * which method to use */
    if(sizeof(matches)>1)
	return sprintf("Unable to determine whether you want to %s the %s",
	  format_list(matches,"or"),
	  the_short());
    /* Now that the failures have been eliminated, return the check */
    return query_method_checks(method);
}

int complex_exit_do_verb_rule(string verb,string rule,mixed args...)
{
  class move_data data;
  string prep;
  string match;
  string method;
  mixed dest;
  object sibling;

/* For our purposes the rule should always be WRD OBJ or OBJ or no rule at 
   all.  -- Check for no rule first.*/

/* Make a method out of it */
  if(rule=="WRD OBJ")
  {
    args[0]=PREPOSITION_D->translate_preposition(args[0]);
    method=sprintf("%s %s",verb,args[0]);
  } else if(rule=="WRD") {
    method=sprintf("%s %s",verb,args[0]);
  } else
    method=verb;

/* We know now that there can be only one match, or it would not have 
 * passed the direct_verb_rule */
  match=methods_matched(method)[0];
  sscanf(match,"%s %s",method,prep);
  dest=query_method_destination(match);

/* Default to everything that's in the method. */
  data=copy(methods[match]);

/* We want to do some operation on these */
  data->destination=objectp(dest)?file_name(query_method_destination(match)):dest;
  data->relation=prep;
  data->exit_messages=query_method_exit_message(match);
/* Fetch enter msg from sibling, if one is found */
  if (sibling = this_object()->get_sibling())
    data->enter_messages = sibling->query_method_enter_message(match);
  else
    data->enter_messages = query_method_enter_message(match);
/* Set up the through object for M_SMARTMOVE */
  data->through = sibling;
  data->who=this_body();

/* It is now time to move the body to the destination */
  return this_body()->move_to(data);
}

string stat_me()
{
    string ret="Methods: \n";
    foreach(string met in list_methods())
    {
	ret=sprintf("%s\t%O: Destination - %O\n",
	  ret,
	  met,
	  query_method_destination(met));
    }
    return ret;
}

mapping lpscript_attributes() {
    return ([ "hidden" : ({LPSCRIPT_INT, "setup", "set_hidden" }),
      "brief" : ({LPSCRIPT_STRING, "setup","set_obvious_description"}),
      "method" : ({LPSCRIPT_STRING,  "setup", "set_method" }),
      "destination" : ({LPSCRIPT_TWO, (: ({ "setup", "set_method_destination(\""+ $1 + "\",\""+ $2[0] + "\")" }) :) }),
      "check" : ({ LPSCRIPT_TWO, (: ({ "setup", "set_method_check(\"" + $1 + "\",\"" + $2[0] + "\")" }) :)  }),
      "exit_message" : ({LPSCRIPT_TWO, (: ({ "setup", "add_method_exit_messages(\"" + $1 + "\", \"" + $2[0] + "\")" }) :) }),
      "enter_message" : ({LPSCRIPT_TWO, (: ({ "setup", "add_method_enter_messages(\"" + $1 + "\", \"" + $2[0] + "\")" }) :) }),
    ]);
}