/*
 * FILE:        ai.c
 * Purpose:     To create a basic AI sub-system to make
 *              AI battles more realistic..
 * Credits:     Zachery Crosswhite (Cyhawk/Thri)
 * Contact:     cyhawkx@gmail.com
 * Contact2:    AIM: CalibanL
 *
 * Install      Very basic, I used rom's previous ACT_MAGE
 * and info:    bit for this. Near the top of mobile_update in
 *              update.c, after the check for specs, and after
 *              my forced do_wear(ch, "all") (cough) I stuck..
 *
 *              if (IS_SET(ch->act, ACT_MAGE))
 *                  ai_wizard(ch);
 *
 *              I also changed MOBILE_PULSE to 20, due to
 *              the fact its normaly 8, and 99% of stock spells
 *              are 12 or higher.. so.. This is to prevent
 *              un-human-like casting ability. I would
 *              say make it 12 perhaps..
 *
 *              Idealy, when this is expanded, there will be
 *              a wrapper to determine class/AI, as well as
 *              choices for universal stuff (returning home,
 *              sleeping, eating, etc) before the specifics...
 *              As well as checks for how much 'wait' the mob
 *              has from spells (I have timed casting, but the
 *              idea is the same for Insta-cast/wait stock) This
 *              way, the mob casts as fast, or faster than a 
 *              good player.
 *
 * TODO:        Well, obviously this is just a basic piece of code...
 *              There needs to be ones for each 'class' of mobile
 *              you want to have, the 4 basics included in stock,
 *              as well as other special ones, (Group Healers,
 *              mobile leaders/'boss' mobs, maybe special mobs in
 *              here too, or 'super' mages..
 *
 *              Intelligence/Wisdom Checks, dumb wizards wont always
 *              cast, this also gives credence to giving mobs stat points
 *              too.
 *
 *              Checks for Mana, right now, they will always attempt to cast,
 *              I forsee some major spam-fests whe theyre out of mana.. ugh
 *              Maybe if theyre really hurt, they flee/find a healer..
 *              Ooo, I can see some intersting City AI here.
 *
 *              Debuf/Curse spells seprated. Lets face it, in PK, it goes in
 *              a specific order. Debuf->curse->fight (curse being any stat
 *              reduction or offensive enchantments). Mobiles should do this
 *              too.
 *
 *              Add function wrappers for ease of expandability and improvement
 *              of universal AI functions like going home, eating, etc.
 *
 * Licence:     This code falls under the Rom Licence, with the following
 *              additions:
 *              8) A helpfile accessable via the keyword '_thri' Must be
 *              viewable to all players, regardless of level, with the following
 *              Information:
 *              
 *              AI Sub-system created by Thri of Vandagard MUD.
 *              Email: cyhawkx@gmail.com
 *              AIM: CalibanL
 *
 *              Any previous snippets of mine used must also be included
 *              in this helpfile.
 *
 *              9) If you have a 'credits' command or credits helpfile,
 *              a small mention of my Name and the code snip should also
 *              be there.
 *
 *              10) You are also required to make contact with Thri via
 *              any means listed. (AIM/Email) Telling him you are going
 *              to use his code. (Email is best).
 *
 * Afterward:   Anywho, Enjoy the code, and make sure you expand it!
 *              Also, if you do expand it, send me what ya did, id love
 *              to incorporate this into the main sources, and maybe
 *              release a new stock codebase based around this, ROM 3.0?
 *              well, you know what i mean =)
 *
 *  -Cyhawk/Thri
 */

#if defined(macintosh)
#include <types.h>
#else
#include <sys/types.h>
#endif
#include <ctype.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include "merc.h"
#include "interp.h"
#include "magic.h"
#include "recycle.h"
#include "tables.h"

/**
 * AI_DEBUG: Turn on/off Chatting of what the AI is doing
 */
#define AI_DEBUG 1

/*
                    -> Cast
        -> Fight    -> Melee
Action              -> Debuf
                    -> Flee?

                    -> Heal Self
        -> Idle     -> Enchant Self
                    -> Idle Chit Chat
*/

/** ai_wizard()
 *
 * Primary AI Control for Wizard mobs, follows
 * a basic procedure, hopefuly this will work.
 *
 */
void ai_wizard(CHAR_DATA * mob)
{
    int _mob_hp = 100 * (mob->hit) / (mob->max_hit + 1);
    int _level  = mob->level;
    int control = -1;
    int chance  = 0;S
    
    /* Ok, Lets start with idle actions.. */
    if (mob->fighting == NULL)
    {
        /* ACTION_ Heal Start (75% or lower) */
        if (_mob_hp < 75)
        {
#if AI_DEBUG
            do_function (mob, &do_say, "I need to heal myself");
#endif
            /* ACTION_ Heal: Lets see if he can hide first */
            if (!is_affected (mob, skill_lookup("invisibility"))
                && _level >= 8
                && !IS_AFFECTED(mob, AFF_INVISIBLE))
            {
#if AI_DEBUG
                do_function (mob, &do_say, "Woha that was close, gotta hide!");
#endif
                do_function (mob, &do_cast, "'invisibility'");
                return;
            }
            
            if (_level >= 25)
            {
#if AI_DEBUG
                do_function (mob, &do_say, "I'm over level 25, I'll use Heal");
#endif
                do_function (mob, &do_cast, "heal self");
                return;
            }
            else
            {
                if (mob->position == POS_RESTING)
                    return;
#if AI_DEBUG
                do_function (mob, &do_say, "I'm not over level 25, I need to rest");
#endif
                do_function (mob, &do_rest, "rest");
                return;
            }
        }
        else
        {
            if (mob->position != POS_STANDING)
            {
#if AI_DEBUG
                do_function (mob, &do_say, "Much Better!");
#endif
                do_function (mob, &do_stand, "");
            }
        }
                
        /* ACTION_ Heal End */
        
        /* ACTION_ Enchant */
        /* Enchant - Orcish Strength */
        if (!is_affected (mob, skill_lookup("orcish strength"))
           && _level >= 3)
        {
#if AI_DEBUG
            do_function (mob, &do_say, "I don't have orcish strength on.");
#endif
            do_function (mob, &do_cast, "'orcish strength'");
            return;
        }
        /* Enchant - Invisibility */
        if (!is_affected (mob, skill_lookup("invisibility"))
            && _level >= 8
            && !IS_AFFECTED(mob, AFF_INVISIBLE))
        {
#if AI_DEBUG
            do_function (mob, &do_say, "I need to be invisible!");
#endif
            do_function (mob, &do_cast, "'invisibility'");
            return;
        }
        /* Enchant - Invisibility */
        if (!is_affected (mob, skill_lookup("stone skin"))
            && _level >= 12)
        {
#if AI_DEBUG
            do_function (mob, &do_say, "I need to protect myself with Stone skin!");
#endif
            do_function (mob, &do_cast, "'stone skin'");
            return;
        }
        /* Enchant - Adept */
        if (!is_affected (mob, skill_lookup("adept"))
            && _level >= 20)
        {
#if AI_DEBUG
            do_function (mob, &do_say, "What kind of Wizard isnt adept?");
#endif
            do_function (mob, &do_cast, "'adept'");
            return;
        }
        /* Enchant - Haste */
        if (!is_affected (mob, skill_lookup("haste"))
            && _level >= 30)
        {
#if AI_DEBUG
            do_function (mob, &do_say, "I feel sluggish...");
#endif
            do_function (mob, &do_cast, "'haste'");
            return;
        }
        /* Enchant - Immolate */
        if (!is_affected (mob, skill_lookup("immolate"))
            && _level >= 31)
        {
#if AI_DEBUG
            do_function (mob, &do_say, "I need to feel some POWAAAHH!!");
#endif
            do_function (mob, &do_cast, "'immolate'");
            return;
        }
        /* Enchant - Anti-magic Shell */
        if (!is_affected (mob, skill_lookup("anti-magic shell"))
            && _level >= 35)
        {
#if AI_DEBUG
            do_function (mob, &do_say, "I feel too vulnerable..");
#endif
            do_function (mob, &do_cast, "'anti-magic shell'");
            return;
        }
        /* Enchant - Manashield */
        if (!is_affected (mob, skill_lookup("manashield"))
            && _level >= 45)
        {
#if AI_DEBUG
            do_function (mob, &do_say, "Dude? Wheres my Manashield?");
#endif
            do_function (mob, &do_cast, "'manashield'");
            return;
        }
    }
    
    /* Ok, Idle actions done, lets start the fighting stuff! */
    if (mob->fighting != NULL)
    {
        /* ACTION_ Fighting: Flee under 35% */
        if (_mob_hp <= 35)
        {
            /* 50% chance to flee every update */
            if (number_range(1, 100) > 50)
            {
#if AI_DEBUG
                do_function (mob, &do_say, "Holy bejezzus batman, Im out of here!");
#endif
                do_function (mob, &do_flee, "");
                return;
            }
        }
        /* Idealy, spells will be Highest Level to Lowest
         * So the AI will hit harder as theyre stronger..
         */
        /* Cut levels every 20 for ease of use */
        if (_level <= 999)
        {
            control = 8;
            chance = number_range(1, 8);

            if (chance == 1 && _level >= 1)
            {
#if AI_DEBUG
                do_function (mob, &do_say, "Eat Wizard Fire!");
#endif
                do_function (mob, &do_cast, "'wizard fire'");
                return;
            }
            if (chance == 2 && _level >= 1)
            {
#if AI_DEBUG
                do_function (mob, &do_say, "Suck on some Wizard Frost!");
#endif
                do_function (mob, &do_cast, "'wizard frost'");
                return;
            }
            if (chance == 3 && _level >= 1)
            {
#if AI_DEBUG
                do_function (mob, &do_say, "Feel the Powah of Wizard Spark!");
#endif
                do_function (mob, &do_cast, "'wizard spark'");
                return;
            }
            if (chance == 4 && _level >= 4)
            {
#if AI_DEBUG
                do_function (mob, &do_say, "Are my hands hot to you?");
#endif
                do_function (mob, &do_cast, "'burning hands'");
                return;
            }
            if (chance == 5 && _level >= 5)
            {
#if AI_DEBUG
                do_function (mob, &do_say, "Do you feel sick?");
#endif
                do_function (mob, &do_cast, "'weaken'");
                return;
            }
            if (chance == 6 && _level >= 6)
            {
#if AI_DEBUG
                do_function (mob, &do_say, "Ooo, purtty colours...");
#endif
                do_function (mob, &do_cast, "'colour spray'");
                return;
            }
            if (chance == 7 && _level >= 9)
            {
#if AI_DEBUG
                do_function (mob, &do_say, "Ooo, its chilly in here!");
#endif
                do_function (mob, &do_cast, "'chill touch'");
                return;
            }
            if (chance == 8 && _level >= 10)
            {
#if AI_DEBUG
                do_function (mob, &do_say, "Wow, your strong, can I have some?");
#endif
                do_function (mob, &do_cast, "'leech strength'");
                return;
            }
            return;
        }
    }   /* End fighting */
    
    return;
}