ds2.9a12/bin/
ds2.9a12/extra/
ds2.9a12/extra/crat/
ds2.9a12/extra/creremote/
ds2.9a12/extra/mingw/
ds2.9a12/extra/wolfpaw/
ds2.9a12/fluffos-2.14-ds13/
ds2.9a12/fluffos-2.14-ds13/Win32/
ds2.9a12/fluffos-2.14-ds13/compat/
ds2.9a12/fluffos-2.14-ds13/compat/simuls/
ds2.9a12/fluffos-2.14-ds13/include/
ds2.9a12/fluffos-2.14-ds13/testsuite/
ds2.9a12/fluffos-2.14-ds13/testsuite/clone/
ds2.9a12/fluffos-2.14-ds13/testsuite/command/
ds2.9a12/fluffos-2.14-ds13/testsuite/data/
ds2.9a12/fluffos-2.14-ds13/testsuite/etc/
ds2.9a12/fluffos-2.14-ds13/testsuite/include/
ds2.9a12/fluffos-2.14-ds13/testsuite/inherit/
ds2.9a12/fluffos-2.14-ds13/testsuite/inherit/master/
ds2.9a12/fluffos-2.14-ds13/testsuite/log/
ds2.9a12/fluffos-2.14-ds13/testsuite/single/
ds2.9a12/fluffos-2.14-ds13/testsuite/single/tests/compiler/
ds2.9a12/fluffos-2.14-ds13/testsuite/single/tests/efuns/
ds2.9a12/fluffos-2.14-ds13/testsuite/single/tests/operators/
ds2.9a12/fluffos-2.14-ds13/testsuite/u/
ds2.9a12/lib/cmds/admins/
ds2.9a12/lib/cmds/common/
ds2.9a12/lib/cmds/creators/include/
ds2.9a12/lib/daemon/services/
ds2.9a12/lib/daemon/tmp/
ds2.9a12/lib/doc/
ds2.9a12/lib/doc/bguide/
ds2.9a12/lib/doc/efun/all/
ds2.9a12/lib/doc/efun/arrays/
ds2.9a12/lib/doc/efun/buffers/
ds2.9a12/lib/doc/efun/compile/
ds2.9a12/lib/doc/efun/floats/
ds2.9a12/lib/doc/efun/functions/
ds2.9a12/lib/doc/efun/general/
ds2.9a12/lib/doc/efun/mixed/
ds2.9a12/lib/doc/efun/numbers/
ds2.9a12/lib/doc/efun/parsing/
ds2.9a12/lib/doc/hbook/
ds2.9a12/lib/doc/help/classes/
ds2.9a12/lib/doc/help/races/
ds2.9a12/lib/doc/lfun/
ds2.9a12/lib/doc/lfun/all/
ds2.9a12/lib/doc/lfun/lib/abilities/
ds2.9a12/lib/doc/lfun/lib/armor/
ds2.9a12/lib/doc/lfun/lib/bank/
ds2.9a12/lib/doc/lfun/lib/bot/
ds2.9a12/lib/doc/lfun/lib/clay/
ds2.9a12/lib/doc/lfun/lib/clean/
ds2.9a12/lib/doc/lfun/lib/clerk/
ds2.9a12/lib/doc/lfun/lib/client/
ds2.9a12/lib/doc/lfun/lib/combat/
ds2.9a12/lib/doc/lfun/lib/connect/
ds2.9a12/lib/doc/lfun/lib/container/
ds2.9a12/lib/doc/lfun/lib/corpse/
ds2.9a12/lib/doc/lfun/lib/creator/
ds2.9a12/lib/doc/lfun/lib/daemon/
ds2.9a12/lib/doc/lfun/lib/damage/
ds2.9a12/lib/doc/lfun/lib/deterioration/
ds2.9a12/lib/doc/lfun/lib/donate/
ds2.9a12/lib/doc/lfun/lib/door/
ds2.9a12/lib/doc/lfun/lib/equip/
ds2.9a12/lib/doc/lfun/lib/file/
ds2.9a12/lib/doc/lfun/lib/fish/
ds2.9a12/lib/doc/lfun/lib/fishing/
ds2.9a12/lib/doc/lfun/lib/flashlight/
ds2.9a12/lib/doc/lfun/lib/follow/
ds2.9a12/lib/doc/lfun/lib/ftp_client/
ds2.9a12/lib/doc/lfun/lib/ftp_data_connection/
ds2.9a12/lib/doc/lfun/lib/fuel/
ds2.9a12/lib/doc/lfun/lib/furnace/
ds2.9a12/lib/doc/lfun/lib/genetics/
ds2.9a12/lib/doc/lfun/lib/holder/
ds2.9a12/lib/doc/lfun/lib/id/
ds2.9a12/lib/doc/lfun/lib/interactive/
ds2.9a12/lib/doc/lfun/lib/lamp/
ds2.9a12/lib/doc/lfun/lib/leader/
ds2.9a12/lib/doc/lfun/lib/light/
ds2.9a12/lib/doc/lfun/lib/limb/
ds2.9a12/lib/doc/lfun/lib/living/
ds2.9a12/lib/doc/lfun/lib/load/
ds2.9a12/lib/doc/lfun/lib/look/
ds2.9a12/lib/doc/lfun/lib/manipulate/
ds2.9a12/lib/doc/lfun/lib/meal/
ds2.9a12/lib/doc/lfun/lib/messages/
ds2.9a12/lib/doc/lfun/lib/player/
ds2.9a12/lib/doc/lfun/lib/poison/
ds2.9a12/lib/doc/lfun/lib/position/
ds2.9a12/lib/doc/lfun/lib/post_office/
ds2.9a12/lib/doc/lfun/lib/potion/
ds2.9a12/lib/doc/lfun/lib/room/
ds2.9a12/lib/doc/lfun/lib/server/
ds2.9a12/lib/doc/lfun/lib/spell/
ds2.9a12/lib/doc/lfun/lib/torch/
ds2.9a12/lib/doc/lfun/lib/vendor/
ds2.9a12/lib/doc/lfun/lib/virt_sky/
ds2.9a12/lib/doc/lfun/lib/weapon/
ds2.9a12/lib/doc/lfun/lib/worn_storage/
ds2.9a12/lib/doc/lpc/basic/
ds2.9a12/lib/doc/lpc/concepts/
ds2.9a12/lib/doc/lpc/constructs/
ds2.9a12/lib/doc/lpc/etc/
ds2.9a12/lib/doc/lpc/intermediate/
ds2.9a12/lib/doc/lpc/types/
ds2.9a12/lib/doc/misc/
ds2.9a12/lib/doc/old/
ds2.9a12/lib/domains/
ds2.9a12/lib/domains/Praxis/adm/
ds2.9a12/lib/domains/Praxis/attic/
ds2.9a12/lib/domains/Praxis/cemetery/mon/
ds2.9a12/lib/domains/Praxis/data/
ds2.9a12/lib/domains/Praxis/death/
ds2.9a12/lib/domains/Praxis/mountains/
ds2.9a12/lib/domains/Praxis/obj/armour/
ds2.9a12/lib/domains/Praxis/obj/magic/
ds2.9a12/lib/domains/Praxis/obj/weapon/
ds2.9a12/lib/domains/Praxis/orc_valley/
ds2.9a12/lib/domains/Ylsrim/
ds2.9a12/lib/domains/Ylsrim/adm/
ds2.9a12/lib/domains/Ylsrim/armor/
ds2.9a12/lib/domains/Ylsrim/broken/
ds2.9a12/lib/domains/Ylsrim/fish/
ds2.9a12/lib/domains/Ylsrim/meal/
ds2.9a12/lib/domains/Ylsrim/npc/
ds2.9a12/lib/domains/Ylsrim/obj/
ds2.9a12/lib/domains/Ylsrim/virtual/
ds2.9a12/lib/domains/Ylsrim/weapon/
ds2.9a12/lib/domains/campus/adm/
ds2.9a12/lib/domains/campus/etc/
ds2.9a12/lib/domains/campus/meals/
ds2.9a12/lib/domains/campus/save/
ds2.9a12/lib/domains/campus/txt/ai/charles/
ds2.9a12/lib/domains/campus/txt/ai/charles/bak2/
ds2.9a12/lib/domains/campus/txt/ai/charles/bak2/bak1/
ds2.9a12/lib/domains/campus/txt/ai/charly/
ds2.9a12/lib/domains/campus/txt/ai/charly/bak/
ds2.9a12/lib/domains/campus/txt/jenny/
ds2.9a12/lib/domains/cave/doors/
ds2.9a12/lib/domains/cave/etc/
ds2.9a12/lib/domains/cave/meals/
ds2.9a12/lib/domains/cave/weap/
ds2.9a12/lib/domains/default/creator/
ds2.9a12/lib/domains/default/doors/
ds2.9a12/lib/domains/default/etc/
ds2.9a12/lib/domains/default/vehicles/
ds2.9a12/lib/domains/default/virtual/
ds2.9a12/lib/domains/default/weap/
ds2.9a12/lib/domains/town/txt/shame/
ds2.9a12/lib/domains/town/virtual/
ds2.9a12/lib/domains/town/virtual/bottom/
ds2.9a12/lib/domains/town/virtual/space/
ds2.9a12/lib/estates/
ds2.9a12/lib/ftp/
ds2.9a12/lib/lib/comp/
ds2.9a12/lib/lib/daemons/
ds2.9a12/lib/lib/daemons/include/
ds2.9a12/lib/lib/lvs/
ds2.9a12/lib/lib/user/
ds2.9a12/lib/lib/virtual/
ds2.9a12/lib/log/
ds2.9a12/lib/log/adm/
ds2.9a12/lib/log/archive/
ds2.9a12/lib/log/chan/
ds2.9a12/lib/log/errors/
ds2.9a12/lib/log/law/adm/
ds2.9a12/lib/log/law/email/
ds2.9a12/lib/log/law/names/
ds2.9a12/lib/log/law/sites-misc/
ds2.9a12/lib/log/law/sites-register/
ds2.9a12/lib/log/law/sites-tempban/
ds2.9a12/lib/log/law/sites-watch/
ds2.9a12/lib/log/open/
ds2.9a12/lib/log/reports/
ds2.9a12/lib/log/router/
ds2.9a12/lib/log/secure/
ds2.9a12/lib/log/watch/
ds2.9a12/lib/obj/book_source/
ds2.9a12/lib/obj/include/
ds2.9a12/lib/powers/prayers/
ds2.9a12/lib/powers/spells/
ds2.9a12/lib/realms/template/adm/
ds2.9a12/lib/realms/template/area/armor/
ds2.9a12/lib/realms/template/area/npc/
ds2.9a12/lib/realms/template/area/obj/
ds2.9a12/lib/realms/template/area/room/
ds2.9a12/lib/realms/template/area/weap/
ds2.9a12/lib/realms/template/bak/
ds2.9a12/lib/realms/template/cmds/
ds2.9a12/lib/save/kills/o/
ds2.9a12/lib/secure/cfg/classes/
ds2.9a12/lib/secure/cmds/builders/
ds2.9a12/lib/secure/cmds/creators/include/
ds2.9a12/lib/secure/cmds/players/
ds2.9a12/lib/secure/cmds/players/include/
ds2.9a12/lib/secure/daemon/imc2server/
ds2.9a12/lib/secure/daemon/include/
ds2.9a12/lib/secure/lib/
ds2.9a12/lib/secure/lib/include/
ds2.9a12/lib/secure/lib/net/include/
ds2.9a12/lib/secure/lib/std/
ds2.9a12/lib/secure/log/adm/
ds2.9a12/lib/secure/log/bak/
ds2.9a12/lib/secure/log/intermud/
ds2.9a12/lib/secure/log/network/
ds2.9a12/lib/secure/modules/
ds2.9a12/lib/secure/npc/
ds2.9a12/lib/secure/obj/include/
ds2.9a12/lib/secure/room/
ds2.9a12/lib/secure/save/
ds2.9a12/lib/secure/save/backup/
ds2.9a12/lib/secure/save/boards/
ds2.9a12/lib/secure/tmp/
ds2.9a12/lib/secure/upgrades/files/
ds2.9a12/lib/secure/verbs/creators/
ds2.9a12/lib/std/board/
ds2.9a12/lib/std/lib/
ds2.9a12/lib/tmp/
ds2.9a12/lib/verbs/admins/include/
ds2.9a12/lib/verbs/builders/
ds2.9a12/lib/verbs/common/
ds2.9a12/lib/verbs/common/include/
ds2.9a12/lib/verbs/creators/
ds2.9a12/lib/verbs/creators/include/
ds2.9a12/lib/verbs/rooms/
ds2.9a12/lib/verbs/rooms/include/
ds2.9a12/lib/www/client/
ds2.9a12/lib/www/errors/
ds2.9a12/lib/www/images/
ds2.9a12/lib/www/lpmuds/downloads_files/
ds2.9a12/lib/www/lpmuds/intermud_files/
ds2.9a12/lib/www/lpmuds/links_files/
ds2.9a12/win32/
/*    /daemon/race.c
 *    from the Dead Souls  Object Library
 *    handles race configuration and administration
 *    created by Descartes of Borg 960108
 *    Version: @(#) races.c 1.4@(#)
 *    Fixed by Ashon @ Stargate Atlantis 16 March 2006
 */

#include <lib.h>
#include <save.h>
#include <privs.h>
#include <armor_types.h>
#include <mouth_types.h>
#include <size_types.h>

inherit LIB_DAEMON;

private mapping Races = ([]);
static private mapping Resistances = ([]);
static private mapping Armors = ([]);
static private mapping Sizes = ([]);
static private mapping Btypes = ([]);
string array FlyingRaces = ({});
string array LimblessCombatRaces = ({});
string array LimblessRaces = ({});
string array NonBitingRaces = ({});
string array SwimmingRaces = ({});
string array NonMeatRaces = ({});

static void create() {
    daemon::create();

    if( unguarded((: file_size(SAVE_RACES __SAVE_EXTENSION__) :)) > 0 )
        unguarded((: restore_object(SAVE_RACES) :));

    if( !Races ) Races = ([]);
    if(!FlyingRaces) FlyingRaces = ({});
    if(!LimblessCombatRaces) LimblessCombatRaces = ({});
    if(!LimblessRaces) LimblessRaces = ({});
    if(!NonBitingRaces) NonBitingRaces = ({});
    if(!NonMeatRaces) NonMeatRaces = ({});
}

static private void validate() {
    if( !((int)master()->valid_apply(({ PRIV_ASSIST }))) )
        error("Illegal attempt to modify race data");
}

int CanFly(string str){
    if( !Races[str] ) return 0;
    if(member_array(str, FlyingRaces) != -1) return 1;
    else return 0;
}

int CanSwim(string str){
    if( !Races[str] ) return 0;
    if(member_array(str, SwimmingRaces) != -1) return 1;
    else return 0;
}

int GetNonMeatRace(string str){
    if(member_array(str,NonMeatRaces) == -1) return 0;
    else return 1;
}

int GetLimblessCombatRace(string str){
    if(member_array(str,LimblessCombatRaces) == -1) return 0;
    else return 1;
}

int GetLimblessRace(string str){
    if(member_array(str,LimblessRaces) == -1) return 0;
    else return 1;
}

int SetNonMeatRace(string str){
    if(member_array(str,NonMeatRaces) != -1) return 0;
    NonMeatRaces += ({ lower_case(str) });
    return 1;
}

int SetLimblessCombatRace(string str){
    if(member_array(str,LimblessCombatRaces) != -1) return 0;
    LimblessCombatRaces += ({ lower_case(str) });
    return 1;
}

int SetLimblessRace(string str){
    if(member_array(str,LimblessRaces) != -1) return 0;
    LimblessRaces += ({ lower_case(str) });
    return 1;
}

int SetFlyingRace(string str){
    FlyingRaces += ({ str });
    return 1;
}

int SetNonBitingRace(string str){
    NonBitingRaces += ({ str });
    return 1;
}

int SetSwimmingRace(string str){
    SwimmingRaces += ({ str });
    return 1;
}

int GetSwimmingRace(string str){
    if(member_array(str,SwimmingRaces) != -1) return 1;
    else return 0;
}

string *GetNonMeatRaces(){
    return copy(NonMeatRaces);
}

string *GetSwimmingRaces(){
    return copy(SwimmingRaces);
}

string *GetLimblessCombatRaces(){
    return copy(LimblessCombatRaces);
}

string *GetLimblessRaces(){
    return copy(LimblessRaces);
}

string *GetFlyingRaces(){
    return copy(FlyingRaces);
}

int GetBitingRace(string str){
    if(member_array(str,NonBitingRaces) == -1) return 1;
    else return 0;
}

int RemoveRaceVars(string str){
    if(previous_object() != this_object()) return 0;
    FlyingRaces  -= ({ str });
    LimblessCombatRaces -= ({ str });
    LimblessRaces -= ({ str });
    NonBitingRaces -= ({ str }); 
    NonBitingRaces -= ({ str });
    SwimmingRaces -= ({ str });
    return 1;
}

int GetRaceMass(string str){
    int Mass = Races[str]["Mass"];
    if(Mass) return Mass;
    else return 0;
}

int GetRaceSize(string str){
    int Size = Races[str]["Size"];
    if(Size) return Size;
    else return 0;
}

int GetRaceBodyType(string str){
    int Btype = Races[str]["Btype"];
    if(Btype) return Btype;
    else return 0;
}

int GetRaceRespirationType(string str){
    int Btype = Races[str]["Btype"];
    if(Btype) return Btype;
    else return 0;
}
int GetRaceMouthType(string str){
    int Mtype = Races[str]["Mouthtype"];
    if(Mtype) return Mtype;
    else return 0;
}

mapping GetRace(string str){
    mapping ret = Races[str] + ([]);
    return ret;
}

void AddRace(string file, int player) {
    mapping res;
    string array tmp, parts;
    string race, test_string;
    int x;
    mixed array limb = allocate(4);
    mixed array tmp_limb = allocate(4);
    mapping s; 

    res = ([]);

    res["Resistance"] = ([]);
    res["Skills"] = ([]);
    res["Stats"] = ([]);
    res["Limbs"] = ({});
    res["Mass"] = 0;
    res["Size"] = 0;
    res["Btype"] = 0;
    res["Rtype"] = 0;
    res["Mouthtype"] = 0;

    validate();

    if( !file_exists(file) ) error("No such file: " + file);
    race = last_string_element(file,"/");

    res["Fingers"] = ([]);


    foreach(string line in explode(read_file(file),"\n")){
        mixed *tmp_vision;
        test_string = first_string_element(line," ");
        if(!test_string || !sizeof(test_string)) test_string = line;

        switch(test_string){
            string type = "";

        case "FLYING_RACE":
            line = trim(replace_string(line, "FLYING_RACE", ""));
            if(sizeof(line) && atoi(line) < 1) break;
            else SetFlyingRace(race);
            break;

        case "NOT_MEAT":
            line = trim(replace_string(line, "NOT_MEAT", ""));
            if(sizeof(line) && atoi(line) < 1) break;
            else SetNonMeatRace(race);
            break;

        case "LIMBLESS_RACE":
            line = trim(replace_string(line, "LIMBLESS_RACE", ""));
            if(sizeof(line) && atoi(line) < 1) break;
            else SetLimblessRace(race);
            break;

        case "LIMBLESS_COMBAT_RACE":
            line = trim(replace_string(line, "LIMBLESS_COMBAT_RACE", ""));
            if(sizeof(line) && atoi(line) < 1) break;
            else SetLimblessCombatRace(race);
            break;

        case "NONBITING_RACE":
            line = trim(replace_string(line, "NONBITING_RACE", ""));
            if(sizeof(line) && atoi(line) < 1) break;
            else SetNonBitingRace(race);
            break;

        case "SWIMMING_RACE":
            line = trim(replace_string(line, "SWIMMING_RACE", ""));
            if(sizeof(line) && atoi(line) < 1) break;
            else SetSwimmingRace(race);
            break;

        case "RACE":
            race = replace_string(line, "RACE ", "");
            if( Races[race] ) error(race+": Race already exists");
            break;

        case "SENSITIVITY":
            line = replace_string(line, "SENSITIVITY ", "");
            tmp_vision = map(explode(line, ":"), (: to_int :));
            res["Sensitivity"] = ({ tmp_vision[0], tmp_vision[1] * 10 });
            break;

        case "PLAYER_RACE":
            line = replace_string(line, "PLAYER_RACE ", "");
            if(player || atoi(line) > 0) player = 1;
            else player = 0;
            break;

        case "LANGUAGE":
            //TODO: This should be a Language array to handle multiple 
            //languages but further research is required first.
            res["Language"] = replace_string(line, "LANGUAGE ", "");
            break;

        case "RESISTANCE":			  
            tmp = explode(replace_string(line, "RESISTANCE ", ""), ":");
            x = to_int(tmp[0]);
            if( x == 0 && tmp[0] != "0" ) x = this_object()->GetResistance(tmp[0]);
            res["Resistance"][x] = tmp[1];
            break;

        case "SKILL":      
            tmp = explode(replace_string(line, "SKILL ", ""), ":");
            res["Skills"][tmp[0]] = ({ tmp[1], tmp[2], tmp[3], tmp[4] });
            break;

        case "MASS":
            x = 0;
            sscanf(line, "MASS %d",x);
            if(x) res["Mass"] = x;
            break;

        case "SIZE":
            type = "";
            x = 0;
            if(sscanf(line, "SIZE %s",type)) res["Size"] = this_object()->GetSize(type);
            else res["Size"] = x;
            break;

        case "BODY_TYPE":
            type = "";
            x = 0;
            if(sscanf(line, "BODY_TYPE %s",type)) res["Btype"] = this_object()->GetBodyType(type);
            else res["Btype"] = x;
            break;

        case "RESPIRATION_TYPE":
            type = "";
            x = 0;
            if(sscanf(line, "RESPIRATION_TYPE %s",type)) res["Btype"] = this_object()->GetRespirationType(type);
            else res["Btype"] = x;
            break;

        case "STATS":
            tmp = ({});
            s = ([]);
            tmp = explode(replace_string(line, "STATS ",""), ":");
            s["Average"] = copy(to_int(tmp[1]));
            s["Class"] = copy(to_int(tmp[2]));
            res["Stats"][tmp[0]] = s;
            break;

        case "MOUTH":
            type = "";
            x = 0;
            if(sscanf(line, "MOUTH %s",type)){
                res["Mouthtype"] = this_object()->GetMouthType(type);
            }
            break;

        case "LIMB":
            limb = ({ ({}), ({}), ({}), ({}) });
            tmp_limb = explode(replace_string(line, "LIMB ",""), ":");
            limb[0] = tmp_limb[0];
            limb[1] = (tmp_limb[1] == "0" ? 0 : tmp_limb[1]);
            limb[2] = to_int(tmp_limb[2]);
            limb[3] = map(explode(tmp_limb[3], ","), function(string str) {
                  int x = to_int(str);
                  if( x == 0 && str != "0" ) { return this_object()->GetArmor(str); }
                  return x;
                });

              res["Limbs"] = ({ res["Limbs"]..., limb });
              res["Limbs"] += ({limb});
              break;

              case "HAND":
              parts = explode(replace_string(line, "HAND ",""), ":");
              res["Fingers"][parts[0]] = to_int(parts[1]);
              break;

              default:
              break;
          } 
        }  

        res["Complete"] = 1;

        if( player ) {
            res["PlayerFlag"] = 1;
        }

        else {
            res["PlayerFlag"] = 0;
        }

        Races[race] = res;
        save_object(SAVE_RACES);
    } 

    void RemoveRace(string race) {
        validate();
        map_delete(Races, race);
        RemoveRaceVars(race);
        if(Races[race]) 
            save_object(SAVE_RACES);
    }

    string ConvertPipe(string str){
        str = replace_string(str," ","");
        str = replace_string(str,"|","+");
        return str;
    }

    int GetArmor(string foo) {
        string str = ConvertPipe(foo);
        string file = DIR_DAEMONS "/tmp/" + str + ".c";

        if( !unguarded((: file_exists($(file)) :)) ) {
            unguarded((: write_file($(file), "#include <armor_types.h>\n" +
                  "int armor() { return " + $(str) + "; }\n") :));
        }
        return call_other(file, "armor"); 
    }

    int GetSize(string foo) {
        string str = ConvertPipe(foo);
        string file = DIR_DAEMONS "/tmp/" + str + ".c";

        if( !unguarded((: file_exists($(file)) :)) ) {
            unguarded((: write_file($(file), "#include <size_types.h>\n" +
                  "int size() { return " + $(str) + "; }\n") :));
        }
        return call_other(file, "size"); 
    }

    int GetBodyType(string foo) {
        string str = ConvertPipe(foo);
        string file = DIR_DAEMONS "/tmp/" + str + ".c";

        if( !unguarded((: file_exists($(file)) :)) ) {
            unguarded((: write_file($(file), "#include <body_types.h>\n" +
                  "int btype() { return " + $(str) + "; }\n") :));
        }
        return call_other(file, "btype"); 
    }

    int GetRespirationType(string foo) {
        string str = ConvertPipe(foo);
        string file = DIR_DAEMONS "/tmp/" + str + ".c";

        if( !unguarded((: file_exists($(file)) :)) ) {
            unguarded((: write_file($(file), "#include <respiration_types.h>\n" +
                  "int rtype() { return " + $(str) + "; }\n") :));
        }
        return call_other(file, "rtype"); 
    }

    int GetMouthType(string foo) {
        string str = ConvertPipe(foo);
        string file = DIR_DAEMONS "/tmp/" + str + ".c";

        if( !unguarded((: file_exists($(file)) :)) ) {
            unguarded((: write_file($(file), "#include <mouth_types.h>\n" +
                  "int mtype() { return " + $(str) + "; }\n") :));
        }
        return call_other(file, "mtype"); 
    }

    int GetResistance(string str) {
        string file = DIR_DAEMONS "/tmp/" + str + ".c";

        if( !unguarded((: file_exists($(file)) :)) ) {
            unguarded((: write_file($(file), "#include <damage_types.h>\n" +
                  "int damage() { return " + $(str) + "; }\n") :));
        }
        return call_other(file, "damage"); 
    }

    varargs mapping GetRemoteRaces(string str) {
        mapping mp = ([]);
        mapping foo = ([]);

        if(str && Races[str]) foo[str] = Races[str];
        else foo = copy(Races);

        foreach(string race, mapping res in foo) {
            mapping stats = ([]);

            mp[race] = ([]);
            mp[race]["limbs"] = res["Limbs"];
            mp[race]["resistance"] = res["Resistance"];

            foreach(string stat, mapping st in res["Stats"]) {
                stats[stat] = ([]);
                stats[stat]["class"] = st["Class"];
                stats[stat]["average"] = st["Average"];
            }

            mp[race]["stats"] = stats;
            mp[race]["fingers"] = res["Fingers"];
            mp[race]["sensitivity"] = res["Sensitivity"];
            mp[race]["player"] = res["PlayerFlag"];
            mp[race]["language"] = res["Language"];

        }
        return mp;
    }

    void SetComplete(string race) {
        mapping res;

        validate();

        if( !Races[race] ) error("No such race");
        else res = Races[race];
        res["Complete"] = 1;
        save_object(SAVE_RACES);
    }

    void SetLightSensitivity(string race, int array sensitivity) {
        mapping res;

        validate();

        if( !Races[race] ) error("No such race");
        else res = Races[race];
        if( sensitivity[0] < 1 ) error("Invalid sensitivity value");
        if( sensitivity[1] > 99 ) error("Invalid sensitivity value");
        if( sensitivity[0] > sensitivity[1] ) error("Invalid sensitivity value");
        res["Sensitivity"] = sensitivity;
        save_object(SAVE_RACES);
    }

    void SetCharacterLimbs(string race, mixed array args) {
        mapping res = Races[race];
        mixed array tmp = ({});

        if( !res || !res["Complete"] || sizeof(args) != 2 ) return;
        args[0] = copy(res["Limbs"]);
        foreach(string finger, int count in res["Fingers"])
            tmp = ({ tmp..., ({ finger, count }) });
        args[1] = tmp;
    }

    void SetCharacterRace(string race, mixed array args) {
        mapping res = Races[race];
        mixed array tmp;
        mapping StatMap;
        string schluss;

        if( !res || !res["Complete"] || sizeof(args) != 5 ) return;
        tmp = ({});
        foreach(int key, string val in res["Resistance"])
            tmp = ({ tmp..., ({ key, val }) });
        args[0] = tmp;
        tmp = ({});
        StatMap = copy(res["Stats"]);
        schluss = "";
        foreach(schluss in keys(StatMap)){
            tmp = ({ tmp..., ({ schluss, StatMap[schluss]["Average"], StatMap[schluss]["Class"] }) });
        }
        args[1] = tmp;
        args[2] = res["Language"];
        args[3] = res["Sensitivity"];
        args[4] = res["Skills"]; 
    }

    varargs string array GetRaces(int player_only) {

        return filter(keys(Races), function(string race, int player_only) {
              mapping res = Races[race];

              if( !res["Complete"] ) return 0;
              if( player_only && !res["PlayerFlag"] )
                  return 0;
              return 1;
          }, player_only);
    }

    string GetHelp(string race) {
        mapping res = Races[race];
        string array limbs;
        string help = "Race: " + race + "\n\n";
        string tmp, h_file;
        int x;

        if( !res ) return 0;
        h_file = "/doc/help/races/"+lower_case(race);
        if(file_exists(h_file)) return read_file(h_file); 
        limbs = map(res["Limbs"], (: $1[0] :));
        limbs = distinct_array(limbs);
        help += "Limbs:\n";
        help += capitalize(item_list(map(limbs, (: add_article :)))) + ".\n";
        help += "\nFingered limbs:\n";
        foreach(string finger, int count in res["Fingers"])
            help += "\t" + finger + " (" + count + ")\n";
        limbs = regexp(limbs, ".* wing");
        if( sizeof(limbs) ) {
            help += "\nFlying\n";
        }

        else {
            help += "\nNon-flying\n";
        }

        x = res["Sensitivity"][0];
        if( x < 11 ) tmp = "excellent";
        else if( x < 16 ) tmp = "above average";
        else if( x < 21 ) tmp = "good";
        else if( x < 26 ) tmp = "average";
        else if( x < 31 ) tmp = "below average";
        else if( x < 36 ) tmp = "very poor";    
        else tmp = "extremely poor";
        help += "\nNight vision: " + tmp + "\n";
        x = res["Sensitivity"][1];
        if( x < 61 ) tmp = "extremely poor";
        else if( x < 66 ) tmp = "very poor";
        else if( x < 71 ) tmp = "below average";
        else if( x < 76 ) tmp = "average";
        else if( x < 81 ) tmp = "good";
        else if( x < 86 ) tmp = "above average";
        else tmp = "excellent";
        help += "Day vision: " + tmp + "\n\n";
        return help;
    }

    public mapping GetResistances() {
        return copy(Resistances);
    }

    public mapping GetArmors() {
        return copy(Armors);
    }