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

#include <mudlib.h>
#include <security.h>

inherit M_MESSAGES;
inherit M_COMPLETE;
inherit M_ACCESS;
inherit M_GRAMMAR;

private mapping emotes=([]);
private string* adverbs=({});

#define SAVE_FILE "/data/daemons/soul"
#define CMD_ADD_EMOTE "/cmds/wiz/addemote"
#define CMD_REMOVE_EMOTE "/cmds/wiz/rmemote"
#define CMD_MOVE_EMOTE "/cmds/wiz/mvemote"

void
create() {
    string verb, rule;
    mapping value;
    mixed ignore;

    unguarded(1, (: restore_object, SAVE_FILE, 1 :));

    parse_init();

    foreach (verb, value in emotes) {
	if (value[0]) {
	    value[""] = value[0];
	    map_delete(value, 0);
	}
	if (value[1]) {
	    value["STR"] = value[1];
	    map_delete(value, 1);
	}

	foreach (rule, ignore in value) {
	    catch(parse_add_rule(verb, rule));
	}
    }

    if (!adverbs)
	adverbs = ({});
}


string stat_me()
{
    return "Number of feelings: " + sizeof(emotes) + "\n";
}

int
add_emote(string verb, mixed rule, string array parts)
{
/*
    if( base_name( previous_object()) != CMD_ADD_EMOTE )
	error("Illegal call to add_emote()\n");
*/
    // try this first b/c it will error if rule is illegal
    parse_add_rule(verb, rule);

    if (!emotes[verb])
	emotes[verb] = ([]);

    if (sizeof(parts) > 1)
	emotes[verb][rule] = parts;
    else
	emotes[verb][rule] = parts[0];

    unguarded(1, (: save_object, SAVE_FILE :));

    return 1;
}

int
remove_emote(string verb, string rule) 
{
    if ( base_name(previous_object())!=CMD_REMOVE_EMOTE )
	error("Illegal call to remove_emote()\n");
    if (!emotes[verb]) return 0;
    if (sizeof( rule )) {
	if (!emotes[verb][rule]) return 0;
	map_delete(emotes[verb], rule);
    } else {
	map_delete(emotes, verb);
    }

    parse_remove(verb);
    parse_refresh();

    unguarded(1, (: save_object, SAVE_FILE :));
    return 1;
}

int
move_emote(string verb, string dest) 
{
    if (base_name(previous_object())!=CMD_MOVE_EMOTE)
	error("Illegal call to move_emote()\n");
    if ( (!emotes[verb]) || (!dest)) return 0;
    emotes[dest]=emotes[verb];
    foreach (string rule, string soul in emotes[verb])
    {
	parse_add_rule(dest, rule);
    }
    map_delete(emotes, verb);
    unguarded(1, (: save_object, SAVE_FILE :));
    return 1;
}

mixed
query_emote(string em) {
    return emotes[em];
}

private string get_completion(string);

#define IMUD_CHANNELT_DUMMY "/obj/mudlib/ichannelt"

mixed * internal_get_soul(string verb, string rule, mixed *args,
			  int add_imud_msg)
{
    mapping rules;
    mixed soul;
    int i, j, num;
    object *who, *imud_who;
    string token;
    mixed * result;

    rules = emotes[verb];
    if (!rules) return 0;
    soul = rules[rule];
    if (!soul) return 0;

    // minus the verb's real name; we don't want to process the real names
    // of any of the objects
    num = (sizeof(args) - 1)/2;

    for (i = 0; i < num; i++) {
	if (stringp(args[i]) && strlen(args[i]) && args[i][<1] == '*'
	  && member_array(' ', args[i]) == -1) {
	    args[i] = get_completion(args[i][0..<2]);
	    if (!args[i])
		return 0;
	    break;
	}
    }

    if (soul[0] == '=') soul = rules[soul[1..]];
    if (stringp(soul)) {
	if (soul[<1] != '\n') soul += "\n";
    } else {
	soul = map_array(soul, (: $1[<1] == '\n' ? $1 : $1 + "\n" :));
    }


    who = ({ this_body() });
    if ( add_imud_msg )
      imud_who = ({ new( IMUD_CHANNELT_DUMMY, this_body(), 3 ) });

    if (strsrch(rule, "LIV") != -1)
    {
	i = 0;

	foreach (token in explode(rule, " ")) {
	    if (token == "LIV") {
		who += ({ args[i] });
		
		if ( add_imud_msg )
		  imud_who += ({ new( IMUD_CHANNELT_DUMMY, args[i], 2 ) });
		
		args[i..i] = ({});
	    } else
	      if (token[0] >= 'A' && token[0] <= 'Z')
		i++;
	}
    }
    
    if ( add_imud_msg )
      result = ({ who, allocate( sizeof( who )+1 ),
		  allocate( sizeof( imud_who )+1) });
    else
      result = ({ who, allocate(sizeof(who) + 1) });

    for ( j = 0; j < add_imud_msg+1; j++ )
    {
	object *w;

	w = ( j ? imud_who : who );
//RABUG(sprintf("%O", w));

	for (i = 0; i < sizeof(w); i++) {
	    string tmp;
	    if (stringp(soul))
	      tmp = soul;
	    else {
		if (i && i + 1 < sizeof(soul))
		  tmp = soul[i + 1];
		else
		  tmp = soul[0];
	    }
//RABUG(sprintf("i: %d, tmp: %s, soul: %O", i, tmp, soul));
//RABUG(sprintf("w[i]: %O, w: %O, args: %O", w[i], w, args));
	    result[1+j][i] = compose_message(w[i], tmp, w, args...);
	}
	//### tmp fix
	result[1+j][<1] =
	  compose_message(0, stringp(soul) ? soul : soul[1], w, args...);
    }

    return result;
}

varargs mixed *
get_soul(string verb, string rule, mixed *args)
{
    return internal_get_soul(verb, rule, args, 0);
}

varargs mixed *
get_imud_soul(string verb, string rule, mixed args...)
{
    return internal_get_soul(verb, rule, args, 1);
}

mixed
list_emotes()
{
    return keys( emotes );
}

string *
emote_apropos(string str) {
    int num_verbs, num_rules;
    int i, j;
    string *verbs, *rules;
    mapping rules_for_verb;
    mixed data;
    string *found;
    
    found = ({});
    verbs = keys(emotes);
    num_verbs = sizeof(verbs);
    for (i=0; i<num_verbs; i++) {
	rules_for_verb = emotes[verbs[i]];
	rules = keys(rules_for_verb);
	num_rules = sizeof(rules);
	for (j=0; j<num_rules; j++) {
	    data = rules_for_verb[rules[j]];
	    if (arrayp(data)) {
		if (strsrch(lower_case(data[0]), lower_case(str)) != -1 || 
		    strsrch(lower_case(data[1]), lower_case(str)) != -1)
		    found += ({ verbs[i] + " " + rules[j] });
	    }
	    else {
		if (strsrch(lower_case(data), lower_case(str)) != -1)
		    found += ({ verbs[i] + " " + rules[j] });
	    }
	}
    }
    return found;
}


private string get_completion(string s)
{
    string * completions;
    
    completions = complete(s, adverbs);
    switch(sizeof(completions))
	{
	case 0:
	    write("Can't find a match for '" + s + "*'.\n");
	    return 0;
	case 1:
	    return completions[0];
	default:
	    write("Can't find a unique match.\nFound: " + implode(completions, ", ") + "\n");
	    return 0;
	}
}

/*
** Interface with parsing functions.  We use the "wild" card functions
** so that we don't have to support a gazillion can/do type actions.
*/
int livings_are_remote() { return 1; }

mixed can_verb_wrd(string verb, string wrd) 
{
    return member_array(wrd, adverbs) != -1 || member_array('*', wrd) != -1;
}

mixed can_verb_rule(string verb, string rule)
{
    if (!emotes[verb]) return;
    return !undefinedp(emotes[verb][rule]);
}

mixed direct_verb_rule(string verb, string rule) 
{
    return !undefinedp(emotes[verb][rule]);
}

mixed indirect_verb_rule(string verb, string rule) 
{
    return !undefinedp(emotes[verb][rule]);
}

void do_verb_rule(string verb, string rule, mixed args...)
{
    mixed soul;
    
//    RABUG(sprintf("do_verb_rule: (args: %O)", args));
    soul = get_soul(verb, rule, args);
    if (!soul) return;
    if ( sizeof(soul[0]) == 2 &&
	 !immediately_accessible(soul[0][1]))
	{
	    soul[1][0] = "*" + soul[1][0];
	    soul[1][1] = "*" + soul[1][1];
	    inform(soul[0], soul[1], 0);
	}
    else
	{
	    inform(soul[0], soul[1], environment(this_body()));
	}
    
    return; 
}

mixed *parse_soul(string str) {
    mixed result;
    mixed soul;
    
    result = parse_my_rules(this_body(), str, 0);
    if (!result) return 0;
    if( intp(result) || stringp(result)) return 0;
    soul = get_soul(result[0], result[1], result[2..]);
    if (!soul) return 0;
    return soul;
}

mixed *parse_imud_soul(string str) {
    object temp;
    string user;
    string tmp;
    mixed result;
    mixed soul;
    int i;

    // This bit of the code can only handle one person,
    // could make it handle more, but its not worth it while the IMUD stuff
    // only handles two people
    i = strsrch( str, "@" );
    //    if ( i > -1 ) 
    if(sscanf(str,"%s@%s",user,tmp)==2)
    {
      
      string array muds=IMUD_D->query_up_muds();
      string array words=explode(tmp," ");
      string array matches;
      string array previous_matches=muds;
      string emote;
      int j=sizeof(words);
      

      /* The soul is all of the user except for the last word. */
      emote=implode(explode(user," ")[0..<2]," ");

      /* Assume that the last word of user, is the actual users name
       * this has problems if there are cases where the users name includes
       * a space, but we will deal with that later.*/
      user=explode(user," ")[<1];

      tmp="";
      for(i=0;i<j;i++) {
	tmp += " " + words[i];
	if(tmp[0]==' ')
	  tmp=tmp[1..];
	matches=find_best_match_or_complete(tmp,muds);

	/* If there are multiple matches, add the next word first and see
	 * if that narrows the possibilities down. */
	if(sizeof(previous_matches&matches)>1) {
	  previous_matches&=matches;
	  continue;
	}
	
	/* We know that there is either 1 or no matches now.  Check for none
	 * first.  The fact that we are at this point means that the previous
	 * iteration had more than one match, but this one doesn't.  It's 
	 * ambiguous */
	if(!sizeof(matches)) {
	  write("Vague mud name.  could be: " + 
		implode(previous_matches,", ") + "\n");
	  return;
	}

	/* We have narrowed things down to one successful match.  Nothing more
	 * needs to be done.  Just use it. */
      }

      tmp=sprintf("%s@%s",user,matches[0]);

      temp = new( IMUD_CHANNELT_DUMMY, tmp );

      if ( temp )
	{
	str = replace_string( sprintf("%s %s",emote,tmp), tmp, "wibblewibble"+tmp );
	}
    }

    result = parse_my_rules(this_body(), str, 0 );

    if (!result || intp(result) || stringp(result))
    {
	if ( temp ) temp->remove();
	return 0;
    }

    soul = get_imud_soul(result...);

    if (!soul)
      return 0;
    return soul;
}

void set_adverbs(string* mods)
{
    if(!arrayp(mods)) error("bad arg type");
    adverbs = mods;
    unguarded(1, (: save_object, SAVE_FILE :));
}


string* get_adverbs(){
    return adverbs;
}

void add_adverb(string adverb)
{
    if(!stringp(adverb)) error("bad arg type");
    adverbs += ({adverb});
    unguarded(1, (: save_object, SAVE_FILE :));
}

void remove_adverb(string adverb)
{
    adverbs -= ({adverb});
    unguarded(1, (: save_object, SAVE_FILE :));
}