/*
 *      The spell casting skill.
 *
 * (C) Vikingmud 1992
 * Non-commercial users may distribute or modify. Ask first.
 *
 * Contributors:	Stig Saether Bakken (Auronthas)
 *
 *
 *  Function descriptions:
 *
 *  newsay(str)         Converts normal english to old english.
 *                      Crude, but it works!
 *  cast_spell(str)     Checks if the caster knows the spell, has enough spell
 *                      points and if he's wearing bad armour before calling
 *                      the spell function in spells.c.
 *  wearing_bad_armour()Returns a 1 if this_player() is wearing a piece of
 *                      armour with an individual class of more that one and
 *                      this piece of armour does not return a 1 in the
 *                      function mage_friendly().
 *  learn_spell(int)    Checks if the character can learn a spell or if he
 *                      knows it already before setting the spell's bit in
 *                      the global string 'known'.
 *                      Return values:
 *                      LEARN_SUCCESS		- The spell was learned successfully.
 *                      LEARN_UNKNOWN		- The spell does not exist.
 *                      LEARN_ALREADY_KNOWN	- The spell was already known.
 *                      LEARN_NOT_ALLOWED	- The character can not learn this spell.
 */


#include "/std/include/std.h"
#include "/std/include/levels.h"
#include "defines.h"
#include "spells.h"


int     t, n, i;        /* Universal counter variables. */
int     max_spells;     /* Simply the number of spells. */
string  known;          /* Bit-array of which spell the character knows. */
string  specialization; /* Which school the character is specialized in. */
string  forbidden;      /* The school the character has chosen to sack. */
string  mess1,mess2,mess3;
int     oldspeak;
string  prepmess1,prepmess2;
string  damage_type;
int	spell_damage;
int     spell_cost;


reset(arg)
{
    max_spells = SPELLS->query_max_spells();
    if(!known)
    {
	known=" ";
	known = set_bit(known,max_spells);
	known = clear_bit(known,5);
    }
    if(!forbidden) forbidden = "none";
    if(!specialization) specialization = "none";
}


id(str)
{
    /*    if(TP->query_level() < 20) return;*/
    return str=="skill" || str=="spell_skill" || str=="guild";
}

init()
{
    int lev;
    string spl,name;
    if (ENV != TP)
	return;
    add_action("cast_spell","", 1);
    add_action("help","help");
    add_action("do_help","help");
    add_action("learn","learn");
    add_action("bits","bits");
    add_action("learnall","learnall");
#if 0
    add_action("newsay","say");
    add_action("oldspeak","oldspeak");
    add_action("newspeak","newspeak");
#endif
    add_action("forget","forget");
    add_action("do_spells","spells");
}


forget(str)
{
    if(str!="skill")
    {
	notify_fail("Nope!\n");
	return 0;
    }
    write("Ok.. You forget the skill.\n");
    destruct(this_object());
    return 1;
}

oldspeak()
{
    notify_fail("You already speak old english.\n");
    if(oldspeak) return;
    oldspeak = 1;
    write("You will now talk old english.\n");
    return 1;
}


newspeak()
{
    notify_fail("You already speak modern english.\n");
    if(!oldspeak) return;
    oldspeak = 0;
    write("You will now talk modern english.\n");
    return 1;
}


learnall()
{
    for(t=0;t<max_spells+1;t++)
    {
	learn_spell(t);
    }
    write("Learned all spells...\n");
    return 1;
}


bits()
{
    write("known: ");
    for (t=0;t<max_spells;t++)
    {
	if(test_bit(known,t)) write("1"); else write("0");
    }
    write("\n");
    return 1;
}


get()
{
    return 1; 
}

drop()
{
    return 1;
}


short()
{
    return "spell casting skill"; 
}


query_auto_load()
{
    
    string  temp;
    
    temp = SPELLDIR + "skill" + ":" + known + "##" + specialization + "##" +
	forbidden + "##";
    return temp;
}

init_arg(str)
{
    
    string temp1, temp2, temp3;
    
    if (sscanf(str, "%s##%s##%s##", temp1, temp2, temp3) != 3)
    {
	tell_object(ENV,"Loading error in you spell casting skill!!!\n");
	return;
    }
    known = temp1;
    specialization = temp2;
    forbidden = temp3;
}

query_known()
{
    return known;
}


help(str)
{
    if(!str) return;
    return 0;
}

do_help(str)
{
    int spell;
    if (!str)
	return 0;
    if(str == "spells")
    {
	TP->more_file(HOMEDIR+"docs/spells.list1");
	return 1;
    }
    spell = SPELLS->recognize_spell(str);
    if (spell == -1)
	return 0;
    SPELLS->spell_help(spell);
    return 1;
}


list(str)
{
    if(str!="spells") return;
    write("The spells you know are:\n");
    if(!known || known=="")
    {
        write("Absolutely none!\n");
        return;
    }
    n=0;
    for (t=0;t<max_spells;t++)
    {
        if(test_bit(known,t))
        {
            write(extract(SPELLS->query_spell_name(t) +
			  "                   ", 0, 18));
            if(n==3) { n=-1; write("\n"); }
            n++;
        }
    }
    if(n!=4) write("\n");
    return 1;
}


newsay(str)
{
    string  temp1,temp2;
    
    if (!oldspeak)
	return 0; /* Leave it to the soul, then */
    if (!str) 
    {
	write("Say what?\n");
	return 1;
    }
    while(sscanf(str,"%syours%s",temp1,temp2)) { str=temp1+"thine"+temp2; }
    while(sscanf(str,"%sYours%s",temp1,temp2)) { str=temp1+"Thine"+temp2; }
    while(sscanf(str,"%syour%s",temp1,temp2)) { str=temp1+"thy"+temp2; }
    while(sscanf(str,"%sYour%s",temp1,temp2)) { str=temp1+"Thy"+temp2; }
    while(sscanf(str,"%syou%s",temp1,temp2)) { str=temp1+"thou"+temp2; }
    while(sscanf(str,"%sYou%s",temp1,temp2)) { str=temp1+"Thou"+temp2; }
    while(sscanf(str,"%sshall%s",temp1,temp2)) { str=temp1+"shallt"+temp2; }
    while(sscanf(str,"%sShall%s",temp1,temp2)) { str=temp1+"Shallt"+temp2; }
    while(sscanf(str,"%sdone%s",temp1,temp2)) { str=temp1+"doneth"+temp2; }
    while(sscanf(str,"%sDone%s",temp1,temp2)) { str=temp1+"Doneth"+temp2; }
    while(sscanf(str,"%shave%s",temp1,temp2)) { str=temp1+"hath"+temp2; }
    while(sscanf(str,"%sHave%s",temp1,temp2)) { str=temp1+"Hath"+temp2; }
    while(sscanf(str,"%sare%s",temp1,temp2)) { str=temp1+"art"+temp2; }
    while(sscanf(str,"%sAre%s",temp1,temp2)) { str=temp1+"Art"+temp2; }
    
    say(CAP(TP->QN)+" says: "+str+"\n");
    write("Ok.\n");
    return 1;
}

cast_spell(str) 
{
    int     sp, cost;
    string  spell, arg, temp1;
    
    spell = query_verb();
    if (!function_exists("do_" + spell, find_object(SPELLS)) || SPELLS->recognize_spell(spell) == -1)
	return 0;
    if(this_player()->query_ghost())
    {
	notify_fail("You can't do that in your immaterial state.\n");
	return 0;
    }
    if(!str) 
    {
	notify_fail("Syntax: cast 'spell name' [(at) target]\n");
	return 0;
    }
    if(arg)
    {
	if (sscanf(arg, "at %s", temp1))
	    arg = temp1;
	else if (sscanf(arg, "on %s", temp1))
	    arg = temp1;
    }
    if (!test_bit(known,sp))
    {
	write("You do not know that spell!\n");
	return 1;
    }
    if (EN(TP)->query_property("no_magic") && TP->QL < APPRENTICE_WIZ)
    {
	write("Your magic doesn't seem to work here.\n");
	return 1;
    }
    if (wearing_bad_armour()) 
    {
	notify_fail("Your wear armour preventing the spell.\n");
	return 0;
    }
    
#if 0
    if(TP->query_busy())
    {
	write("You are already doing something this round!\n");
	return 1;
    }
#endif
    
    cost = SPELLS->query_spell_cost(sp);
    write("SP: "+cost+"\n");
    if (cost > TP->QSP) 
    {
	write("You are too low on power!\n");
	say(CAP(TP->QN) + " tries to cast a spell, but fails.\n");
	return 1;
    }
    spell = SPELLS->query_spell_abbr(sp);
    if(ENV->QN == "Auronthas")
    {
	write("spell = "+spell+"\n");
	write("abbr = "+spell+"\n");
    }
    if (call_other(SPELLS, "do_" + spell, arg))
    {
	/*    TP->set_busy(""); */
	TP->restore_spell_points(-cost);
	return 1;
    }
    return 1;
}

#define TEST(OO) call_other(call_other(this_player(),"query_head_armour"),"test_type",OO)

wearing_bad_armour()
{
    object all;
    string type;
    if(!this_player()->query_head_armour()) return 0;
    if(TEST("gaunlets")||TEST("armour")||TEST("shield")||TEST("helmet"))
	return 1;
    return 0;
}

learn(str) 
{
    int sn,res;
    write("Trying to learn..\n");
    sn = SPELLS->recognize_spell(str);
    res=learn_spell(sn);
    if(res == LEARN_SUCCESS)
    {
	write("Everything fine!\n");
	return 1;
    }
    if(res == LEARN_UNKNOWN)
    {
	write("What spell?\n");
	return 1;
    }
    if(res == LEARN_ALREADY_KNOWN)
    {
	write("Already known.\n");
	return 1;
    }
    if(res == LEARN_NOT_ALLOWED)
    {
	write("Forbidden school. ("+forbidden+")\n");
	return 1;
    }
    write("This is not possible. BUGBUGBUGBUG!!!! Mail Auronthas!!\n");
    return 1;
}

long()
{
    write("Commands available for magicians:\n\n"+
          "help <spell>   - Info about a spell.\n"+
	  "help spells    - Lists all spells.\n" +
          "spells         - Gives a list of the spells you know.\n"+
          "forget skill   - Sad thing.\n"+
          "oldspeak       - Switch to old english language.\n"+
          "newspeak       - Switch back to modern english.\n"+
          "learnall (temp)- Teaches you all spells.\n"+
          "bits     (temp)- Prints out the bits of known spells.\n"+
          "\nThat's about all, I think..\n");
}

set_damage_type(str)
{
    damage_type = str;
}

set_spell_damage(d)
{
    spell_damage = d;
}

query_cost()
{
    return spell_cost;
}

query_damage()
{
    return spell_damage;
}

damage_done(dmg,who)
{
    string arg;
    arg=lower_case(who->query_name()+"#"+damage_type+"#"+dmg);
    "obj/dmg_mess"->damage_message(arg);
}


set_forbidden(s)
{
    forbidden = s;
}

set_specialization(s)
{
    specialization = s;
}

query_forbidden()
{
    return forbidden; 
}

query_specialization()
{
    return specialization;
}