foundationI_fluffos_v1/
foundationI_fluffos_v1/bin/
foundationI_fluffos_v1/fluffos-2.9-ds2.12/
foundationI_fluffos_v1/fluffos-2.9-ds2.12/ChangeLog.old/
foundationI_fluffos_v1/fluffos-2.9-ds2.12/Win32/
foundationI_fluffos_v1/fluffos-2.9-ds2.12/compat/
foundationI_fluffos_v1/fluffos-2.9-ds2.12/compat/simuls/
foundationI_fluffos_v1/fluffos-2.9-ds2.12/include/
foundationI_fluffos_v1/fluffos-2.9-ds2.12/testsuite/
foundationI_fluffos_v1/fluffos-2.9-ds2.12/testsuite/clone/
foundationI_fluffos_v1/fluffos-2.9-ds2.12/testsuite/command/
foundationI_fluffos_v1/fluffos-2.9-ds2.12/testsuite/data/
foundationI_fluffos_v1/fluffos-2.9-ds2.12/testsuite/etc/
foundationI_fluffos_v1/fluffos-2.9-ds2.12/testsuite/include/
foundationI_fluffos_v1/fluffos-2.9-ds2.12/testsuite/inherit/
foundationI_fluffos_v1/fluffos-2.9-ds2.12/testsuite/inherit/master/
foundationI_fluffos_v1/fluffos-2.9-ds2.12/testsuite/log/
foundationI_fluffos_v1/fluffos-2.9-ds2.12/testsuite/single/
foundationI_fluffos_v1/fluffos-2.9-ds2.12/testsuite/single/tests/compiler/
foundationI_fluffos_v1/fluffos-2.9-ds2.12/testsuite/single/tests/efuns/
foundationI_fluffos_v1/fluffos-2.9-ds2.12/testsuite/single/tests/operators/
foundationI_fluffos_v1/fluffos-2.9-ds2.12/testsuite/u/
foundationI_fluffos_v1/fluffos-2.9-ds2.12/tmp/
foundationI_fluffos_v1/fluffos-2.9-ds2.12/windows/
foundationI_fluffos_v1/lib/
foundationI_fluffos_v1/lib/cmds/ambassador/
foundationI_fluffos_v1/lib/cmds/database/
foundationI_fluffos_v1/lib/cmds/soul/
foundationI_fluffos_v1/lib/daemon/include/
foundationI_fluffos_v1/lib/daemon/save/
foundationI_fluffos_v1/lib/daemon/services/
foundationI_fluffos_v1/lib/daemon/soul/
foundationI_fluffos_v1/lib/doc/build/
foundationI_fluffos_v1/lib/doc/build/room/
foundationI_fluffos_v1/lib/doc/build/virtual/
foundationI_fluffos_v1/lib/doc/driver/
foundationI_fluffos_v1/lib/doc/efun/
foundationI_fluffos_v1/lib/doc/etc/
foundationI_fluffos_v1/lib/doc/help/creator/
foundationI_fluffos_v1/lib/doc/help/hm/
foundationI_fluffos_v1/lib/doc/help/user/
foundationI_fluffos_v1/lib/doc/lpc/basic/
foundationI_fluffos_v1/lib/doc/lpc/data_types/
foundationI_fluffos_v1/lib/doc/lpc/etc/
foundationI_fluffos_v1/lib/doc/lpc/intermediate/
foundationI_fluffos_v1/lib/doc/lpc/types/
foundationI_fluffos_v1/lib/doc/mudlib/
foundationI_fluffos_v1/lib/doc/mudlib/features/
foundationI_fluffos_v1/lib/domains/Examples/etc/
foundationI_fluffos_v1/lib/domains/Examples/room/
foundationI_fluffos_v1/lib/domains/Examples/virtual/
foundationI_fluffos_v1/lib/domains/Examples/virtual/exaA/
foundationI_fluffos_v1/lib/domains/Examples/virtual/exaB/
foundationI_fluffos_v1/lib/domains/Examples/weapon/
foundationI_fluffos_v1/lib/domains/Standard/
foundationI_fluffos_v1/lib/domains/Standard/pools/
foundationI_fluffos_v1/lib/domains/Standard/std/
foundationI_fluffos_v1/lib/domains/Standard/xtra/
foundationI_fluffos_v1/lib/include/
foundationI_fluffos_v1/lib/news/
foundationI_fluffos_v1/lib/secure/cfg/
foundationI_fluffos_v1/lib/secure/cmds/adm/
foundationI_fluffos_v1/lib/secure/cmds/ambassador/
foundationI_fluffos_v1/lib/secure/cmds/mortal/
foundationI_fluffos_v1/lib/secure/etc/
foundationI_fluffos_v1/lib/secure/etc/approval/
foundationI_fluffos_v1/lib/secure/etc/elections/
foundationI_fluffos_v1/lib/secure/etc/mudlib/
foundationI_fluffos_v1/lib/secure/etc/quests/
foundationI_fluffos_v1/lib/secure/save/daemon/
foundationI_fluffos_v1/lib/secure/save/postal/d/descartes/
foundationI_fluffos_v1/lib/secure/save/users/d/
foundationI_fluffos_v1/lib/secure/std/
foundationI_fluffos_v1/lib/std/obj/
foundationI_fluffos_v1/lib/std/room/
foundationI_fluffos_v1/lib/std/user/
foundationI_fluffos_v1/lib/std/virtual/
foundationI_fluffos_v1/old/
foundationI_fluffos_v1/win32/
/*    /daemon/soul.c
 *    from Nightmare IV
 *    fear a soul from Discworld
 *    created by Pinkfish@Discworld on an unknown date
 *    ported to Nightmare doing very little by Descartes of Borg 940207
 */

#include <soul.h>
#include <save.h>
#include <daemons.h>

private mapping __Soul;
static private string __Adj, __Chunk;
static private object __CurrentTarget;

static private void become_emotional(mapping info, string adj, object *who);
static private void compile_soul(string str);
static private string compile_message(mixed *parts, object *targets);
static private string remove_whitespace(string str);
static string filter_stuff(mixed *parts, object *targets);
static private void save_soul();
static private void restore_soul();
static string handle_names(object ob);
static private void compile_file(string str);
static private void parse_assoc(mapping borg);
static private mixed parse_chunk();
static private mapping parse_mapping();
static private string *parse_array();

void create() {
    string *files;
    int i;

    if(file_exists(SAVE_SOUL+".o")) restore_soul();
    if(!__Soul || !sizeof(__Soul)) {
        __Soul = ([]);
        i = sizeof(files = get_dir(DIR_SOUL_FILES+"/"));
        while(i--) compile_soul(files[i]);
    }
    call_out("save_soul", 60);
}

object *match_living(string nom) {
    object *who;
    object ob;

    if(!nom || nom == "") return ({});
    if(nom == "everyone") {
        who = filter_array(all_inventory(environment(this_player())),
          (: living :));
        return who - ({ this_player() });
    }
    else if(ob = present(lower_case(nom), environment(this_player())))
      return (hiddenp(ob) || ob == this_player()) ? ({}) : ({ ob });
    else return ({});
}

varargs string match_adj(string str, mapping data1, mapping data2) {
    string a, b;

    a = (data1["adverbs"] ? data1["adverbs"] : "");
    b = (data2["adverbs"] ? data2["adverbs"] : "");
    if(str == "" && b[0] == '#' && strlen(b) > 2) b = b[2..strlen(b)-1];
    if(a[0] == '#' || b[0] == '#') return str;
    if(sscanf(sprintf(",%s,%s,", b, a), "%s,"+str+"%s,", a, b)) {
        if(b && strlen(b)) return sprintf("%s%s", str, b);
        else return str;
    }
    return 0;
}

int do_cmd(string verb, string arg) {
    mapping data, info;
    object *target;
    string *args;
    string adj;

    if(!(data = __Soul[verb])) return 0;
    target = ({});
    if(!arg) {
        info = data["noargs"];
        adj = "nothing";
        args = ({ arg = "" });
    }
    if(!info) {
        if(!args) {
            args = explode(arg, " ");
	}
        if(data["prepositions"]) args = args - (string *)data["prepositions"];
        arg = implode(args, " ");
        if(sizeof(args) == 1) {
            if(!sizeof(target = match_living(arg))) {
                if(!(info = data["undirected"])) {
                    message("emote", sprintf("%s whom?", capitalize(verb)),
                      this_player());
                    return 1;
                }
                adj = match_adj(arg, data, info);
            }
            else {
                if(!(info = data["directed"]))
                  return notify_fail("That makes no sense.\n");
                adj = match_adj("", data, info);
            }
        }
        else {
            if(sizeof(target = match_living(args[0]))) {
                if(!(info = data["directed"]))
                  return notify_fail("That makes no sense.\n");
		adj = match_adj(implode(args[1..sizeof(args)-1]," "),data,info);
            }
            else {
                if(sizeof(target = match_living(args[sizeof(args)-1]))) {
                    if(!(info = data["directed"]))
                      return notify_fail("That makes no sense.\n");
                    adj = match_adj(implode(args[0..sizeof(args)-2], " "),
                      data, info);
                }
                else {
                    if(!(info = data["undirected"])) {
                        message("emote", sprintf("%s whom?", capitalize(verb)),
                          this_player());
                        return 1;
                    }
                    adj = match_adj(arg, data, info);
                }
            }
        }
    }
    if(!adj) {
        message("emote", sprintf("What an odd way in which to %s!", verb),
          this_player());
	return 1;
    }
    become_emotional(info, adj, target);
    return 1;
}

void become_emotional(mapping info, string adj, object *who) {
    string cmd;
    int i;

    __Adj = adj;
    __CurrentTarget = 0;
    message("emote", compile_message(info["mymsg"], who), this_player());
    if(!who || !sizeof(who)) 
      message("emote", compile_message(info["theirmsg"], ({})), 
        environment(this_player()), ({ this_player() }));
    else message("emote", compile_message(info["theirmsg"], who),
      environment(this_player()), ({ this_player() }) + who);
    i = sizeof(who);
    while(i--) {
        __CurrentTarget = who[i];
        if(info["obmsg"])
          message("emote", compile_message(info["obmsg"], who), who[i]);
        else message("emote", compile_message(info["theirmsg"], who), who[i]);
      }
  }

void compile_soul(string str) {
    compile_file(sprintf("%s/%s", DIR_SOUL_FILES, str));
}

string compile_message(mixed *parts, object *targets) {
    return filter_stuff(parts, targets);
  }

string compile_names(object *who) {
    int x;

    if((x = sizeof(who)) == 1) return handle_names(who[0]);
    else return implode(map_array(who[1..x-1], "handle_names", this_object()),
      ", ") + " and " + handle_names(who[0]);
  }

static void save_soul() {
    save_object(SAVE_SOUL);
}

static private void restore_soul() {
    restore_object(SAVE_SOUL);
}

string filter_stuff(mixed *parts, object *targets) {
    string *arr;

    arr = map_array(parts, "handle_part", this_object(), targets) - ({ "" });
    return implode(arr, " ");
  }

string handle_names(object ob) {
    if(!ob) return "";
    if(ob == __CurrentTarget) return "you";
    else return (string)ob->query_cap_name();
  }

string handle_part(mixed part, object *targets) {
    if(stringp(part)) return part;
    else switch(part) {
    case ADJ: return __Adj;
    case TP_NAME: return (string)this_player()->query_cap_name();
    case TP_PRONOUN: return nominative(this_player());
    case TP_POSSESSIVE: return possessive(this_player());
    case TP_NPOSS: return possessive_noun(this_player());
    case TP_FOO: return reflexive(this_player());
    case OB_NAME: return compile_names(targets);
    case OB_PRONOUN: return nominative(targets[0]);
    case OB_POSSESSIVE: return possessive(targets[0]);
    case OB_NPOSS: return possessive_noun(targets[0]);
    case OB_FOO: return reflexive(targets[0]);
    }
    return part + "";
  }

mapping query_soul() { return copy(__Soul); }
 
static private void compile_file(string file) { 
    string *cles; 
 
    if(!(file = read_file(file))) error("Failed to read file.\n"); 
    file = replace_string(file, "\t", "");
    cles = map_array(explode(file, "\n"), "remove_indentation", this_object()); 
    filter_array(explode(implode(cles, ""), "$$"), "decode_file",this_object()); 
  } 
 
static void decode_file(string str) {
    call_out("define_action", 0, str);
}
 
static void define_action(string str) { 
    __Chunk = remove_whitespace(str);
    parse_assoc(__Soul); 
  } 
 
static private void parse_assoc(mapping borg) { 
    string str; 
    mixed val; 
 
    if(sscanf(__Chunk, "(%s %s", str, __Chunk) < 2)  
      error("Syntax error compiling file in parse_assoc().\n"); 
    val = parse_chunk(); 
    __Chunk = __Chunk[1..strlen(__Chunk)-1]; 
    borg[str] = val; 
  } 
 
static private mixed parse_chunk() { 
    string str; 
 
    __Chunk = remove_whitespace(__Chunk);
    switch(__Chunk[0]) { 
    case '*': return parse_mapping(); 
    case '[': return parse_array(); 
    case '(': return error("Syntax error compiling file in parse_chunk().\n"); 
    } 
    if(sscanf(__Chunk, "%s)%s", str, __Chunk) == 2) return str; 
    error("sscanf() failed in parse_chunk().\n"); 
  } 
 
static private mapping parse_mapping() { 
    mapping borg; 
    int i; 
 
    borg = ([]); 
    if(!sscanf(__Chunk, "*(%s", __Chunk)) 
        error("Failed: sscanf() in parse_mapping().\n"); 
    while((__Chunk = remove_whitespace(__Chunk))[0] != ')') parse_assoc(borg);
    __Chunk = __Chunk[1..strlen(__Chunk)-1]; 
    return borg; 
  } 
 
static private string *parse_array() { 
    string str; 
 
    if(sscanf(__Chunk, "[%s]%s", str, __Chunk) != 2) 
      error("Failed: sscanf() in parse_array().\n"); 
    return map_array(explode(str, " "), "fix_macros", this_object()); 
  } 
 
static mixed fix_macros(string foo) { 
    if(foo[0] == '$') { 
        switch(foo) { 
        case "$ADJ": return ADJ; 
        case "$TP_NAME": return TP_NAME; 
        case "$OB_NAME": return OB_NAME; 
        case "$TP_PRONOUN": return TP_PRONOUN; 
        case "$OB_PRONOUN": return OB_PRONOUN; 
        case "$TP_POSS": return TP_POSSESSIVE; 
        case "$OB_POSS": return OB_POSSESSIVE; 
        case "$TP_NPOSS": return TP_NPOSS; 
        case "$OB_NPOSS": return OB_NPOSS; 
        case "$TP_FOO": return TP_FOO; 
        case "$OB_FOO": return OB_FOO; 
	} 
      } 
    return foo; 
  } 
 
static string remove_indentation(string str) { 
    str = remove_whitespace(str);
    if(!(['(': 1, '[':1, '*':1 ])[str[0]]) return str; 
    else return sprintf(" %s", str); 
  } 

void recompile_soul() {
    string *files;
    int i;

    __Soul = ([]);
    i = sizeof(files = get_dir(DIR_SOUL_FILES+"/"));
    while(i--) compile_soul(files[i]);
    save_soul();
}

static private string remove_whitespace(string str) {
    while(sscanf(str, "    %s", str));
    sscanf(str, "  %s", str);
    sscanf(str, " %s", str);
    return str;
}