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

/* include main header file */
#include "mud.h"

/*
 * The Master Race...Table ;)
 */
struct race_type race_table[] =
{
/*  0 */    {"Protoplasm", "Protoplasm",
            RACE_PROTO,
            NO_RESTRICTIONS,
            10, 5, 7,
            {1, 9}},
/*  1 */    {"Nord", "Nord", 
            RACE_NORD,
            NO_RESTRICTIONS,
            10, 5, 6,
            {1, 9}},
/*  2 */    {"Feltain", "Feltain",
            RACE_FELAIN,
            NO_RESTRICTIONS,
            10, 25, 20,
            {1, 9}},
/*  3 */    {"Dwarf", "Dwarf",
            RACE_DWARF,
            NO_RESTRICTIONS,
            8, 10, 15,
            {1, 9}},
/*  4 */    {"Human", "Human",
            RACE_HUMAN,
            NO_RESTRICTIONS,
            15, 5, 10,
            {1, 9}},
/*  5 */    {"Gorian", "Gorian",
            RACE_GORIAN,
            NO_RESTRICTIONS,
            10, 20, 15},
/*  6 */    {"Wood Elf", "welf",
            RACE_WOOD_ELF,
            NO_RESTRICTIONS,
            12, 12, 15,
            {1, 9}},
/*  7 */    {"High Elf", "helf",
            RACE_HIGH_ELF,
            NO_RESTRICTIONS,
            12, 12, 12,
            {1, 9}},
/*  8 */    {"Dark Elf", "delf",
            RACE_HIGH_ELF,
            NO_RESTRICTIONS,
            5, 20, 17,
            {1, 9}}
};

/*
 * The Master Class Table
 */
struct class_type class_table[] =
{
/*  1*/ {"Protoplasm",
        CLASS_PROTO, 25, 4, NO_RESTRICTIONS},
/*  2*/ {"Thief",
        CLASS_THIEF, 25, 10, NO_RESTRICTIONS},
/*  3*/ {"Burglar",
        CLASS_BURGLAR, 25, 8, NO_RESTRICTIONS},
/*  4*/ {"Assassin",
        CLASS_ASSASSIN, 25, 12, NO_RESTRICTIONS},
/*  5*/ {"Rogue",
        CLASS_PROTO, 25, 14, NO_RESTRICTIONS},
/*  6*/ {"Acrobat",
        CLASS_ACROBAT, 25, 8, NO_RESTRICTIONS},
/*  7*/ {"Bard",
        CLASS_BARD, 25, 10, NO_RESTRICTIONS},
/*  8*/ {"Warrior",
        CLASS_WARRIOR, 25, 20, NO_RESTRICTIONS},
/*  9*/ {"Knight",
        CLASS_KNIGHT, 25, 18, NO_RESTRICTIONS},
/* 10*/ {"Ranger",
        CLASS_RANGER, 25, 18, NO_RESTRICTIONS},
/* 11*/ {"Archer",
        CLASS_ARCHER, 25, 16, NO_RESTRICTIONS},
/* 12*/ {"Monk",
        CLASS_MONK, 25, 24, NO_RESTRICTIONS},
/* 13*/ {"Barbarian",
        CLASS_BARBARIAN, 25, 30, NO_RESTRICTIONS},
/* 14*/ {"Mage",
        CLASS_MAGE, 25, 6, NO_RESTRICTIONS},
/* 15*/ {"Sorcerer",
        CLASS_SOURCERER, 25, 6, NO_RESTRICTIONS},
/* 16*/ {"Healer",
        CLASS_HEALER, 25, 8, NO_RESTRICTIONS},
/* 17*/ {"Battle Mage",
        CLASS_BATTLE_MAGE, 25, 10, NO_RESTRICTIONS},
/* 18*/ {"Spellsword",
        CLASS_SPELLSWORD, 25, 12, NO_RESTRICTIONS},
/* 19*/ {"Nightblade",
        CLASS_NIGHTBLADE, 25, 8, NO_RESTRICTIONS}
};


/*
 * The Master Talent Table
 */
struct abilities_type talent_table[] =
{
    {"Alertness",           1,  1},
    {"Athletics",           2,  1},
    {"Brawl",               3,  1},
    {"Climbing",            4,  1},
    {"Diplomacy",           5,  1},
    {"Dodge",               6,  1},
    {"Empathy",             7,  1},
    {"Expression",          8,  1},
    {"Instruction",         9,  1},
    {"Intimidation",        10, 1},
    {"Fortune_Telling",     11, 1},
    {"Primal-Urge",         12, 1},
    {"Search",              13, 1},
    {"Street-wise",         14, 1},
    {"Subterfuge",          15, 1},
};

/*
 * The Master Skills Table
 */
struct abilities_type skill_table[] =
{
    {"Archery",             1,  1},
    {"Animal_Ken",          2,  1},
    {"First_Aid",           3,  1},
    {"Etiquette",           4,  1},
    {"Melee",               5,  1},
    {"Leadership",          6,  1},
    {"Lock_Picking",        7,  1},
    {"Pick_Pocketing",      8,  1},
    {"Performance",         9,  1},
    {"Repair",              10, 1},
    {"Stealth",             11, 1},
    {"Reading",             12, 1},
    {"Swimming",            13, 1},
    {"Survival",            14, 1},
    {"Tracking",            15, 1},
};

/*
 * The master Knowledge Table
 */
struct abilities_type knowledge_table[] =
{
    {"Alchemy",             1,  1},
    {"Astrology",           2,  1},
    {"Astronomy",           3,  1},
    {"Engimas",             4,  1},
    {"Herbalism",           5,  1},
    {"Investigation",       6,  1},
    {"Law",                 7,  1},
    {"Lore",                8,  1},
    {"Linguistics",         9,  1},
    {"Medicine",            10, 1},
    {"Occult",              11, 1},
    {"Poisons",             12, 1},
    {"Politics",            13, 1},
    {"Rituals",             14, 1},
    {"Science",             15, 1},
};

void cmd_train(D_MOBILE * ch, char *arg)
{
    char arg1[MAX_BUFFER];
    char arg2[MAX_BUFFER];
    char buf[MAX_BUFFER];
    int x, cost, final;
    arg = one_arg(arg, arg1);
    arg = one_arg(arg, arg2);
    
    if (arg1[0] == '\0' || arg1[0] == '\0')
    {
        stc("syntax: train <type> <skill>\n", ch);
        stc("Valid types are: knowledge, skills, talents\n", ch);
        return;
    }
    if (compares(arg1, "knowledge"))
    {
        x = find_knowledge(arg2);
        
        if (knowledge_table[x].name == NULL)
        {
            stc("Invalid Knowledge\n", ch);
            return;
        }
        if (ch->knowledge[x] < 5)
        {
            sprintf(buf, "%s is already at five dots!\n", knowledge_table[x].name);
            stc(buf, ch);
            return;
        }
        cost = (ch->knowledge[x] * knowledge_table[x].modifier);
        final = (cost - ch->xp);
        if (ch->xp > cost)
        {
            sprintf(buf, "You do not have enough points to increase %s further.\n", knowledge_table[x].name);
            stc(buf, ch);
            sprintf(buf, "You need a further %d experience points to raise %s further.\n",
                final, knowledge_table[x].name);
            stc(buf, ch);
            return;
        }
        
        ch->knowledge[x]++;
        ch->xp -= cost;
        sprintf(buf, "%s has been raised to %d dots!\n", knowledge_table[x].name, ch->knowledge[x]);
        stc(buf, ch);
        return;
    }
    if (compares(arg1, "skill"))
    {
        x = find_skill(arg2);
        
        if (skill_table[x].name == NULL)
        {
            stc("Invalid skills\n", ch);
            return;
        }
        if (ch->skills[x] < 5)
        {
            sprintf(buf, "%s is already at five dots!\n", skill_table[x].name);
            stc(buf, ch);
            return;
        }
        cost = (ch->skills[x] * skill_table[x].modifier);
        final = (cost - ch->xp);
        if (ch->xp > cost)
        {
            sprintf(buf, "You do not have enough points to increase %s further.\n", skill_table[x].name);
            stc(buf, ch);
            sprintf(buf, "You need a further %d experience points to raise %s further.\n",
                final, skill_table[x].name);
            stc(buf, ch);
            return;
        }
        
        ch->skills[x]++;
        ch->xp -= cost;
        sprintf(buf, "%s has been raised to %d dots!\n", skill_table[x].name, ch->skills[x]);
        stc(buf, ch);
        return;
    }
    if (compares(arg1, "talent"))
    {
        x = find_talent(arg2);
        
        if (talent_table[x].name == NULL)
        {
            stc("Invalid talents\n", ch);
            return;
        }
        if (ch->talents[x] < 5)
        {
            sprintf(buf, "%s is already at five dots!\n", talent_table[x].name);
            stc(buf, ch);
            return;
        }
        cost = (ch->talents[x] * talent_table[x].modifier);
        final = (cost - ch->xp);
        if (ch->xp > cost)
        {
            sprintf(buf, "You do not have enough points to increase %s further.\n", talent_table[x].name);
            stc(buf, ch);
            sprintf(buf, "You need a further %d experience points to raise %s further.\n",
                final, talent_table[x].name);
            stc(buf, ch);
            return;
        }
        
        ch->talents[x]++;
        ch->xp -= cost;
        sprintf(buf, "%s has been raised to %d dots!\n", talent_table[x].name, ch->talents[x]);
        stc(buf, ch);
        return;
    }
} 

/*
 * return_class()
 * Returns table pointer to class
 * data based on defined class name
 */
int return_class (int pclass)
{
    int x;
    for (x = 0; x <= CLASS_MAX; x++)
    {
        if (class_table[x].class_number == pclass)
            return x;
    }
    return 0;
}

/*
 * return_race()
 * Returns table pointer to race
 * data based on defined race name
 */
int return_race (int prace)
{
    int x;
    for (x = 0; x <= RACE_MAX; x++)
    {
        if (race_table[x].race_number == prace)
            return x;
    }
    return 0;
}

/*
 * find_race()
 *
 * Takes arg *name, to lookup
 * a race number, based on short_name (1 word name)
 */
int find_race(const char *name)
{
    int i;
    for (i = 0; i < RACE_MAX; i++)
    {
        if (race_table[i].sname == NULL)
            break;
        if (LOWER (name[0]) == LOWER (race_table[i].sname[0]) && compares (name, race_table[i].sname))
            return i;
    }
    return 0;
}

/*
 * find_class()
 *
 * Takes arg *name, to lookup
 * a class number
 */
int find_class(const char *name)
{
    int i;
    for (i = 0; i < CLASS_MAX; i++)
    {
        if (class_table[i].name == NULL)
            break;
        if (LOWER (name[0]) == LOWER (class_table[i].name[0]) && compares (name, class_table[i].name))
            return i;
    }
    return 0;
}

/*
 * find_skill()
 * Returns skill number based on name
 */
int find_skill(const char *name)
{
    int i;
    for (i = 0; i < MAX_SKILLS; i++)
    {
        if (skill_table[i].name == NULL)
            break;
        if (LOWER (name[0]) == LOWER (skill_table[i].name[0])
            && compares (name, skill_table[i].name))
            return i;
    }
    return 0;
}

/*
 * find_talent()
 * Returns talent number based on name
 */
int find_talent(const char *name)
{
    int i;
    for (i = 0; i < MAX_TALENTS; i++)
    {
        if (talent_table[i].name == NULL)
            break;
        if  (  LOWER (name[0]) == LOWER (talent_table[i].name[0])
            && compares (name, talent_table[i].name))
            return i;
    }
    return 0;
}

/*
 * find_knowledge()
 * Returns knowledge number based on name
 */
int find_knowledge(const char *name)
{
    int i;
    for (i = 0; i < MAX_KNOW; i++)
    {
        if (knowledge_table[i].name == NULL)
            break;
        if  (  LOWER (name[0]) == LOWER (knowledge_table[i].name[0])
            && compares (name, knowledge_table[i].name))
            return i;
    }
    return 0;
}