/*
 * RAM $Id: tables.c 16 2008-10-22 04:42:21Z ram $
 */

/***************************************************************************
 *  Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer,        *
 *  Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe.   *
 *                                                                         *
 *  Merc Diku Mud improvments copyright (C) 1992, 1993 by Michael          *
 *  Chastain, Michael Quan, and Mitchell Tse.                              *
 *                                                                         *
 *  In order to use any part of this Merc Diku Mud, you must comply with   *
 *  both the original Diku license in 'license.doc' as well the Merc       *
 *  license in 'license.txt'.  In particular, you may not remove either of *
 *  these copyright notices.                                               *
 *                                                                         *
 *  Much time and thought has gone into this software and you are          *
 *  benefitting.  We hope that you share your changes too.  What goes      *
 *  around, comes around.                                                  *
 ***************************************************************************/

/***************************************************************************
*       ROM 2.4 is copyright 1993-1998 Russ Taylor                         *
*       ROM has been brought to you by the ROM consortium                  *
*           Russ Taylor (rtaylor@hypercube.org)                            *
*           Gabrielle Taylor (gtaylor@hypercube.org)                       *
*           Brian Moore (zump@rom.org)                                     *
*       By using this code, you have agreed to follow the terms of the     *
*       ROM license, in the file Rom24/doc/rom.license                     *
***************************************************************************/

#include <sys/types.h>
#include <sys/time.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>

#include "merc.h"
#include "db.h"
#include "interp.h"
#include "tables.h"

/* for clans */
const struct clan_type  clan_table[MAX_CLAN] = {
    /*
     * name, who entry, death-transfer room, independent 
     */
    /*
     * independent should be FALSE if is a real clan 
     */
    {"", "", ROOM_VNUM_ALTAR, TRUE},
    {"loner", "[ Loner ] ", ROOM_VNUM_ALTAR, TRUE},
    {"rom", "[  ROM  ] ", ROOM_VNUM_ALTAR, FALSE}
};

/* for position */
const struct position_type position_table[] = {
    {"dead", "dead"},
    {"mortally wounded", "mort"},
    {"incapacitated", "incap"},
    {"stunned", "stun"},
    {"sleeping", "sleep"},
    {"resting", "rest"},
    {"sitting", "sit"},
    {"fighting", "fight"},
    {"standing", "stand"},
    {NULL, NULL}
};

/* for sex */
const struct sex_type   sex_table[] = {
    {"none"},
    {"male"},
    {"female"},
    {"either"},
    {NULL}
};

/* for sizes */
const struct size_type  size_table[] = {
    {"tiny"},
    {"small"},
    {"medium"},
    {"large"},
    {"huge",},
    {"giant"},
    {NULL}
};

/* various flag tables */
const struct flag_type  act_flags[] = {
    {"npc", A, FALSE},
    {"sentinel", B, TRUE},
    {"scavenger", C, TRUE},
    {"aggressive", F, TRUE},
    {"stay_area", G, TRUE},
    {"wimpy", H, TRUE},
    {"pet", I, TRUE},
    {"train", J, TRUE},
    {"practice", K, TRUE},
    {"undead", O, TRUE},
    {"cleric", Q, TRUE},
    {"mage", R, TRUE},
    {"thief", S, TRUE},
    {"warrior", T, TRUE},
    {"noalign", U, TRUE},
    {"nopurge", V, TRUE},
    {"outdoors", W, TRUE},
    {"indoors", Y, TRUE},
    {"healer", aa, TRUE},
    {"gain", bb, TRUE},
    {"update_always", cc, TRUE},
    {"changer", dd, TRUE},
    {NULL, 0, FALSE}
};

const struct flag_type  plr_flags[] = {
    {"npc", A, FALSE},
    {"autoassist", C, FALSE},
    {"autoexit", D, FALSE},
    {"autoloot", E, FALSE},
    {"autosac", F, FALSE},
    {"autogold", G, FALSE},
    {"autosplit", H, FALSE},
    {"holylight", N, FALSE},
    {"can_loot", P, FALSE},
    {"nosummon", Q, FALSE},
    {"nofollow", R, FALSE},
    {"permit", U, TRUE},
    {"log", W, FALSE},
    {"deny", X, FALSE},
    {"freeze", Y, FALSE},
    {"thief", Z, FALSE},
    {"killer", aa, FALSE},
    {NULL, 0, 0}
};

const struct flag_type  affect_flags[] = {
    {"blind", A, TRUE},
    {"invisible", B, TRUE},
    {"detect_evil", C, TRUE},
    {"detect_invis", D, TRUE},
    {"detect_magic", E, TRUE},
    {"detect_hidden", F, TRUE},
    {"detect_good", G, TRUE},
    {"sanctuary", H, TRUE},
    {"faerie_fire", I, TRUE},
    {"infrared", J, TRUE},
    {"curse", K, TRUE},
    {"poison", M, TRUE},
    {"protect_evil", N, TRUE},
    {"protect_good", O, TRUE},
    {"sneak", P, TRUE},
    {"hide", Q, TRUE},
    {"sleep", R, TRUE},
    {"charm", S, TRUE},
    {"flying", T, TRUE},
    {"pass_door", U, TRUE},
    {"haste", V, TRUE},
    {"calm", W, TRUE},
    {"plague", X, TRUE},
    {"weaken", Y, TRUE},
    {"dark_vision", Z, TRUE},
    {"berserk", aa, TRUE},
    {"swim", bb, TRUE},
    {"regeneration", cc, TRUE},
    {"slow", dd, TRUE},
    {NULL, 0, 0}
};

const struct flag_type  off_flags[] = {
    {"area_attack", A, TRUE},
    {"backstab", B, TRUE},
    {"bash", C, TRUE},
    {"berserk", D, TRUE},
    {"disarm", E, TRUE},
    {"dodge", F, TRUE},
    {"fade", G, TRUE},
    {"fast", H, TRUE},
    {"kick", I, TRUE},
    {"dirt_kick", J, TRUE},
    {"parry", K, TRUE},
    {"rescue", L, TRUE},
    {"tail", M, TRUE},
    {"trip", N, TRUE},
    {"crush", O, TRUE},
    {"assist_all", P, TRUE},
    {"assist_align", Q, TRUE},
    {"assist_race", R, TRUE},
    {"assist_players", S, TRUE},
    {"assist_guard", T, TRUE},
    {"assist_vnum", U, TRUE},
    {NULL, 0, 0}
};

const struct flag_type  imm_flags[] = {
    {"summon", A, TRUE},
    {"charm", B, TRUE},
    {"magic", C, TRUE},
    {"weapon", D, TRUE},
    {"bash", E, TRUE},
    {"pierce", F, TRUE},
    {"slash", G, TRUE},
    {"fire", H, TRUE},
    {"cold", I, TRUE},
    {"lightning", J, TRUE},
    {"acid", K, TRUE},
    {"poison", L, TRUE},
    {"negative", M, TRUE},
    {"holy", N, TRUE},
    {"energy", O, TRUE},
    {"mental", P, TRUE},
    {"disease", Q, TRUE},
    {"drowning", R, TRUE},
    {"light", S, TRUE},
    {"sound", T, TRUE},
    {"wood", X, TRUE},
    {"silver", Y, TRUE},
    {"iron", Z, TRUE},
    {NULL, 0, 0}
};

const struct flag_type  form_flags[] = {
    {"edible", FORM_EDIBLE, TRUE},
    {"poison", FORM_POISON, TRUE},
    {"magical", FORM_MAGICAL, TRUE},
    {"instant_decay", FORM_INSTANT_DECAY, TRUE},
    {"other", FORM_OTHER, TRUE},
    {"animal", FORM_ANIMAL, TRUE},
    {"sentient", FORM_SENTIENT, TRUE},
    {"undead", FORM_UNDEAD, TRUE},
    {"construct", FORM_CONSTRUCT, TRUE},
    {"mist", FORM_MIST, TRUE},
    {"intangible", FORM_INTANGIBLE, TRUE},
    {"biped", FORM_BIPED, TRUE},
    {"centaur", FORM_CENTAUR, TRUE},
    {"insect", FORM_INSECT, TRUE},
    {"spider", FORM_SPIDER, TRUE},
    {"crustacean", FORM_CRUSTACEAN, TRUE},
    {"worm", FORM_WORM, TRUE},
    {"blob", FORM_BLOB, TRUE},
    {"mammal", FORM_MAMMAL, TRUE},
    {"bird", FORM_BIRD, TRUE},
    {"reptile", FORM_REPTILE, TRUE},
    {"snake", FORM_SNAKE, TRUE},
    {"dragon", FORM_DRAGON, TRUE},
    {"amphibian", FORM_AMPHIBIAN, TRUE},
    {"fish", FORM_FISH, TRUE},
    {"cold_blood", FORM_COLD_BLOOD, TRUE},
    {NULL, 0, 0}
};

const struct flag_type  part_flags[] = {
    {"head", PART_HEAD, TRUE},
    {"arms", PART_ARMS, TRUE},
    {"legs", PART_LEGS, TRUE},
    {"heart", PART_HEART, TRUE},
    {"brains", PART_BRAINS, TRUE},
    {"guts", PART_GUTS, TRUE},
    {"hands", PART_HANDS, TRUE},
    {"feet", PART_FEET, TRUE},
    {"fingers", PART_FINGERS, TRUE},
    {"ear", PART_EAR, TRUE},
    {"eye", PART_EYE, TRUE},
    {"long_tongue", PART_LONG_TONGUE, TRUE},
    {"eyestalks", PART_EYESTALKS, TRUE},
    {"tentacles", PART_TENTACLES, TRUE},
    {"fins", PART_FINS, TRUE},
    {"wings", PART_WINGS, TRUE},
    {"tail", PART_TAIL, TRUE},
    {"claws", PART_CLAWS, TRUE},
    {"fangs", PART_FANGS, TRUE},
    {"horns", PART_HORNS, TRUE},
    {"scales", PART_SCALES, TRUE},
    {"tusks", PART_TUSKS, TRUE},
    {NULL, 0, 0}
};

const struct flag_type  comm_flags[] = {
    {"quiet", COMM_QUIET, TRUE},
    {"deaf", COMM_DEAF, TRUE},
    {"nowiz", COMM_NOWIZ, TRUE},
    {"noclangossip", COMM_NOAUCTION, TRUE},
    {"nogossip", COMM_NOGOSSIP, TRUE},
    {"noquestion", COMM_NOQUESTION, TRUE},
/*  {"nomusic", COMM_NOMUSIC, TRUE}, Legacy */
    {"noclan", COMM_NOCLAN, TRUE},
    {"noquote", COMM_NOQUOTE, TRUE},
    {"shoutsoff", COMM_SHOUTSOFF, TRUE},
    {"compact", COMM_COMPACT, TRUE},
    {"brief", COMM_BRIEF, TRUE},
    {"prompt", COMM_PROMPT, TRUE},
    {"combine", COMM_COMBINE, TRUE},
    {"telnet_ga", COMM_TELNET_GA, TRUE},
    {"show_affects", COMM_SHOW_AFFECTS, TRUE},
    {"nograts", COMM_NOGRATS, TRUE},
    {"noemote", COMM_NOEMOTE, FALSE},
    {"noshout", COMM_NOSHOUT, FALSE},
    {"notell", COMM_NOTELL, FALSE},
    {"nochannels", COMM_NOCHANNELS, FALSE},
    {"snoop_proof", COMM_SNOOP_PROOF, FALSE},
    {"afk", COMM_AFK, TRUE},
    {NULL, 0, 0}
};

int flag_lookup( const char *name, const struct flag_type *flag_table )
{
    int                     flag;

    for ( flag = 0; flag_table[flag].name != NULL; flag++ )
    {
        if ( LOWER( name[0] ) == LOWER( flag_table[flag].name[0] )
             && !str_prefix( name, flag_table[flag].name ) )
            return flag_table[flag].bit;
    }

    return 0;
}

void do_flag( CHAR_DATA *ch, const char *argument )
{
    char                    arg1[MAX_INPUT_LENGTH],
                            arg2[MAX_INPUT_LENGTH],
                            arg3[MAX_INPUT_LENGTH];
    char                    word[MAX_INPUT_LENGTH];
    CHAR_DATA              *victim;
    int                    *flag,
                            old = 0,
        inew = 0,
        marked = 0,
        pos;
    char                    type;
    const struct flag_type *flag_table;

    argument = one_argument( argument, arg1 );
    argument = one_argument( argument, arg2 );
    argument = one_argument( argument, arg3 );

    type = argument[0];

    if ( type == '=' || type == '-' || type == '+' )
        argument = one_argument( argument, word );

    if ( arg1[0] == '\0' )
    {
        send_to_char( "Syntax:\n\r", ch );
        send_to_char( "  flag mob  <name> <field> <flags>\n\r", ch );
        send_to_char( "  flag char <name> <field> <flags>\n\r", ch );
        send_to_char( "  mob  flags: act,aff,off,imm,res,vuln,form,part\n\r", ch );
        send_to_char( "  char flags: plr,comm,aff,imm,res,vuln,\n\r", ch );
        send_to_char( "  +: add flag, -: remove flag, = set equal to\n\r", ch );
        send_to_char( "  otherwise flag toggles the flags listed.\n\r", ch );
        return;
    }

    if ( arg2[0] == '\0' )
    {
        send_to_char( "What do you wish to set flags on?\n\r", ch );
        return;
    }

    if ( arg3[0] == '\0' )
    {
        send_to_char( "You need to specify a flag to set.\n\r", ch );
        return;
    }

    if ( argument[0] == '\0' )
    {
        send_to_char( "Which flags do you wish to change?\n\r", ch );
        return;
    }

    if ( !str_prefix( arg1, "mob" ) || !str_prefix( arg1, "char" ) )
    {
        victim = get_char_world( ch, arg2 );
        if ( victim == NULL )
        {
            send_to_char( "You can't find them.\n\r", ch );
            return;
        }

        /*
         * select a flag to set 
         */
        if ( !str_prefix( arg3, "act" ) )
        {
            if ( !IS_NPC( victim ) )
            {
                send_to_char( "Use plr for PCs.\n\r", ch );
                return;
            }

            flag = &victim->act;
            flag_table = act_flags;
        }

        else if ( !str_prefix( arg3, "plr" ) )
        {
            if ( IS_NPC( victim ) )
            {
                send_to_char( "Use act for NPCs.\n\r", ch );
                return;
            }

            flag = &victim->act;
            flag_table = plr_flags;
        }

        else if ( !str_prefix( arg3, "aff" ) )
        {
            flag = &victim->affected_by;
            flag_table = affect_flags;
        }

        else if ( !str_prefix( arg3, "immunity" ) )
        {
            flag = &victim->imm_flags;
            flag_table = imm_flags;
        }

        else if ( !str_prefix( arg3, "resist" ) )
        {
            flag = &victim->res_flags;
            flag_table = imm_flags;
        }

        else if ( !str_prefix( arg3, "vuln" ) )
        {
            flag = &victim->vuln_flags;
            flag_table = imm_flags;
        }

        else if ( !str_prefix( arg3, "form" ) )
        {
            if ( !IS_NPC( victim ) )
            {
                send_to_char( "Form can't be set on PCs.\n\r", ch );
                return;
            }

            flag = &victim->form;
            flag_table = form_flags;
        }

        else if ( !str_prefix( arg3, "parts" ) )
        {
            if ( !IS_NPC( victim ) )
            {
                send_to_char( "Parts can't be set on PCs.\n\r", ch );
                return;
            }

            flag = &victim->parts;
            flag_table = part_flags;
        }

        else if ( !str_prefix( arg3, "comm" ) )
        {
            if ( IS_NPC( victim ) )
            {
                send_to_char( "Comm can't be set on NPCs.\n\r", ch );
                return;
            }

            flag = &victim->comm;
            flag_table = comm_flags;
        }

        else
        {
            send_to_char( "That's not an acceptable flag.\n\r", ch );
            return;
        }

        old = *flag;
        victim->zone = NULL;

        if ( type != '=' )
            inew = old;

        /*
         * mark the words 
         */
        for ( ;; )
        {
            argument = one_argument( argument, word );

            if ( word[0] == '\0' )
                break;

            pos = flag_lookup( word, flag_table );
            if ( pos == 0 )
            {
                send_to_char( "That flag doesn't exist!\n\r", ch );
                return;
            }
            else
                SET_BIT( marked, pos );
        }

        for ( pos = 0; flag_table[pos].name != NULL; pos++ )
        {
            if ( !flag_table[pos].settable && IS_SET( old, flag_table[pos].bit ) )
            {
                SET_BIT( inew, flag_table[pos].bit );
                continue;
            }

            if ( IS_SET( marked, flag_table[pos].bit ) )
            {
                switch ( type )
                {
                    case '=':
                    case '+':
                        SET_BIT( inew, flag_table[pos].bit );
                        break;
                    case '-':
                        REMOVE_BIT( inew, flag_table[pos].bit );
                        break;
                    default:
                        if ( IS_SET( inew, flag_table[pos].bit ) )
                            REMOVE_BIT( inew, flag_table[pos].bit );
                        else
                            SET_BIT( inew, flag_table[pos].bit );
                }
            }
        }
        *flag = inew;
        return;
    }
}

int clan_lookup( const char *name )
{
    int                     clan;

    for ( clan = 0; clan < MAX_CLAN; clan++ )
    {
        if ( LOWER( name[0] ) == LOWER( clan_table[clan].name[0] )
             && !str_prefix( name, clan_table[clan].name ) )
            return clan;
    }

    return 0;
}

int position_lookup( const char *name )
{
    int                     pos;

    for ( pos = 0; position_table[pos].name != NULL; pos++ )
    {
        if ( LOWER( name[0] ) == LOWER( position_table[pos].name[0] )
             && !str_prefix( name, position_table[pos].name ) )
            return pos;
    }

    return -1;
}

int sex_lookup( const char *name )
{
    int                     sex;

    for ( sex = 0; sex_table[sex].name != NULL; sex++ )
    {
        if ( LOWER( name[0] ) == LOWER( sex_table[sex].name[0] )
             && !str_prefix( name, sex_table[sex].name ) )
            return sex;
    }

    return -1;
}

int size_lookup( const char *name )
{
    int                     size;

    for ( size = 0; size_table[size].name != NULL; size++ )
    {
        if ( LOWER( name[0] ) == LOWER( size_table[size].name[0] )
             && !str_prefix( name, size_table[size].name ) )
            return size;
    }

    return -1;
}