/***************************************************************************
 *  OBLIVION 1.2 is copyright by Wes Wagner August, 1996                   *
 *  by using this code you have agreed to the terms of the Oblivion License*
 **************************************************************************/
 
/* this section of code is purely oblivion coding */

#if defined(macintosh)^M
#include <types.h>
#else
#include <sys/types.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "merc.h"
#include "magic.h"
#include "color.h"
#include "obmagsys.h"
#include "recycle.h"

const struct magic_flag magic_table[MAX_SCHOOLS] =
{
  { "abjuration", "abjuration", SCHOOL_ABJURATION, 0 },
  { "alteration", "alteration", SCHOOL_ALTERATION, 0 },
  { "conjuration","conjuration", SCHOOL_CONJURATION, 0 },
  { "summoning", "summoning", SCHOOL_SUMMONING, 0 },
  { "illusion", "illusion", SCHOOL_ILLUSION, 0 },
  { "phantasm", "phantasm", SCHOOL_PHANTASM, 0 },
  { "invocation","invocation", SCHOOL_INVOCATION, 0 },
  { "evocation", "evocation", SCHOOL_EVOCATION, 0 },
  { "enchantment","enchantment", SCHOOL_ENCHANTMENT, 0 },
  { "charm", "charm", SCHOOL_CHARM, 0 },
  { "divination", "divination", SCHOOL_DIVINATION, 0 },
  { "necromancy", "necromancy", SCHOOL_NECROMANCY, 0 },
  { "wild magic", "wild magic", DISC_WILD_MAGIC, 1 },
  { "earth", "earth", DISC_ELEM_EARTH, 1 },
  { "air", "air", DISC_ELEM_AIR, 1 },
  { "water", "water", DISC_ELEM_WATER, 1 },
  { "fire", "fire", DISC_ELEM_FIRE, 1 },
  { "healing", "healing", SPHERE_HEALING, 1 },
  { "weather", "weather", SPHERE_WEATHER, 1 },
  { "protection", "protection", SPHERE_PROTECTION, 1 },
  { "plant", "plant", SPHERE_PLANT, 1 },
  { "law", "law", SPHERE_LAW, 1 },
  { "sun", "sun", SPHERE_SUN, 1 },
  { "animal", "animal", SPHERE_ANIMAL, 1 },
  { "combat", "combat", SPHERE_COMBAT, 1 },
  { "creation", "creation", SPHERE_CREATION, 1 },
  { "time", "time", SPHERE_TIME, 1 }
};

void check_realm_imp(CHAR_DATA * ch, int sn, bool success)
{
   int i;

   for(i=0; i<MAX_SCHOOLS; i++)
   {
     if(magic_table[i].is_sphere)
     {
        if(IS_SET(skill_table[sn].sphere_req, magic_table[i].flag))
        {
          check_improve(ch,skill_lookup(magic_table[i].school_name),
                         success,5);
        }
     }
     else
     {
        if(IS_SET(skill_table[sn].realm_req, magic_table[i].flag))
        {
          check_improve(ch,skill_lookup(magic_table[i].school_name),
                         success,5);
        }
     }
   }

   return ;
}

void set_char_magic_bits(CHAR_DATA * ch)
{
  int i;

  if(IS_NPC(ch))
	return ;
  	
  for(i=0; i<MAX_SCHOOLS; i++)
  {
    if(get_skill(ch,skill_lookup(magic_table[i].school_name))>0)
    {
	if(!magic_table[i].is_sphere)
           SET_BIT(ch->pcdata->schools, magic_table[i].flag);
        else
	   SET_BIT(ch->pcdata->spheres, magic_table[i].flag);
    }		

  }
 
  return ;
}

bool has_spell_req(CHAR_DATA * ch, int sn)
{ 
  if(IS_NPC(ch))
    return TRUE;
  
  if((IS_SET(ch->pcdata->schools, skill_table[sn].realm_req) ||
     skill_table[sn].realm_req==0) &&
     (IS_SET(ch->pcdata->spheres, skill_table[sn].sphere_req) ||
     skill_table[sn].sphere_req== 0   ))
       return TRUE;
     return FALSE;
}

int get_avg(CHAR_DATA * ch, int sn)
/*
 * returns the average skills % for the character in all spell realms
 * schools, disciplines and spheres for a given spell
 */
{
   int i;
   int count=0;
   int total=0;
   int chance=0;

   for(i=0; i<MAX_SCHOOLS; i++)
   {
     if(magic_table[i].is_sphere)
     {
 	if(IS_SET(skill_table[sn].sphere_req, magic_table[i].flag))
        {
	  count++;
          total+=get_skill(ch,skill_lookup(magic_table[i].school_name));	
	}
     }
     else
     {
        if(IS_SET(skill_table[sn].realm_req, magic_table[i].flag))
	{
          count++;
	  total+=get_skill(ch,skill_lookup(magic_table[i].school_name));
	}
     }	   	
   }

   if(count==0)
     return 0;

   chance=total/count;
    
   return chance;	
}

bool check_learn_spell(CHAR_DATA * ch, int sn)
{
  int chance;

  if(IS_NPC(ch))
    return FALSE;	

  if(!has_spell_req(ch,sn))
    return FALSE;      

  if(get_skill(ch, sn)>0)
    return FALSE;

  chance=get_avg(ch, sn);

  if(( number_range(1,100) < (chance-(skill_table[sn].skill_level[ch->class])*10) * (ch->level/10+1) / skill_table[sn].rating[ch->class] ) 
   && ( skill_table[sn].skill_level[ch->class]*10-10<ch->level && number_range(1,3)==3 ))
    return TRUE; 

  return FALSE; 	
}

void on_level_learn(CHAR_DATA * ch)
{
  int i;
  char buf[MAX_STRING_LENGTH];

  if(IS_NPC(ch))
	return ;
  
  set_char_magic_bits(ch); 
 	
  for(i=skill_lookup("acid blast"); i<=skill_lookup("wrath"); i++)
  {
    if(check_learn_spell(ch,i))
    {
      check_realm_imp(ch,i,TRUE); 	
      ch->pcdata->learned[i]=1;
      sprintf(buf,"You have mastered the spell %s.\n\r", skill_table[i].name);
      send_to_char(buf,ch);	
    }
  }		

  return ;
}

void do_spinfo(CHAR_DATA *ch, char * argument)
{
  char buf[MAX_STRING_LENGTH];
  char arg[MAX_STRING_LENGTH];
  int i, j, k;
  bool found=FALSE;

  one_argument(argument,arg);
  
  if(arg[0]=='\0')
  {
    send_to_char("Realms:\n\r",ch);
    send_to_char("Abjuration  Alteration   Conjuration  Summoning    Illusion\n\r",ch);
    send_to_char("Phantasm    Invocation   Evocation	Enchantment  Charm  Necromancy\n\r",ch);
    send_to_char("Spheres:\n\r",ch);
    send_to_char("Wild magic  Earth   Air   Water   Fire   Healing   Weather\n\r",ch);
    send_to_char("Protection  Plant   Law   Sun   Animal  Combat  Creation  Time\n\r",ch);
    return ;
  }
  
  for(i=0; i<MAX_SCHOOLS; i++)
  {
    if(!str_cmp(magic_table[i].school_name, arg))
    {
	found=TRUE;
        break ; 
    }
  }

  if(!found)
  {
    send_to_char("No such school, discipline or sphere of influence.\n\r",ch);
    return ;	
 }

sprintf(buf, "Spell:           Required realms and Spheres of Influence\n\r____________________________________________________________________\n\r");
send_to_char(buf,ch);

  for(j=skill_lookup("acid blast"); j<=skill_lookup("wrath"); j++)
  {
    if(((magic_table[i].is_sphere) && IS_SET(skill_table[j].sphere_req, 
        magic_table[i].flag)) ||
       ((!magic_table[i].is_sphere) && IS_SET(skill_table[j].realm_req,
        magic_table[i].flag)))
    {
       sprintf(buf, "%-20s:", skill_table[j].name);
       send_to_char(buf,ch);
       for(k=0; k<MAX_SCHOOLS; k++)
       {
	if(((magic_table[k].is_sphere) && IS_SET(skill_table[j].sphere_req,
        magic_table[k].flag)) ||
       ((!magic_table[k].is_sphere) && IS_SET(skill_table[j].realm_req,
        magic_table[k].flag)))
	{
	  sprintf(buf, "%s ",magic_table[k].school_name);
          send_to_char(buf,ch);
 	}
       }  		
       send_to_char("\n\r", ch);
    }
  }

  return ;
}

void do_spells(CHAR_DATA *ch, char * argument)
{
  bool found=FALSE;
  int i;
  int counter=0;
  char buf[MAX_STRING_LENGTH];
  char col[MAX_STRING_LENGTH];
  BUFFER *output;

  if(IS_NPC(ch))
    return ;

  output = new_buf();

  for(i=skill_lookup("acid blast"); i<=skill_lookup("wrath"); i++)
  {
     if(ch->pcdata->learned[i])
     {
        found=TRUE;
        if(ch->pcdata->learned[i]>90)
          strcpy(col,FG_LT_BLUE);
        else if(ch->pcdata->learned[i]>70)
          strcpy(col,FG_LT_GREEN);
         else if(ch->pcdata->learned[i]>50)
          strcpy(col,FG_YELLOW);
        else if(ch->pcdata->learned[i]>20)
          strcpy(col,FG_LT_RED);
        else strcpy(col,FG_DK_GRAY);
        sprintf(buf,"%s%-20s %3d ", IS_SET(ch->act, PLR_COLOR) ? col : "",
          skill_table[i].name, skill_table[i].min_mana);
        counter++;
        add_buf( output, buf );

        if(counter>2)
        {
          add_buf( output, "\n\r" );
          counter=0;
        }
     }
  }

  if(!found)
     send_to_char("You have no spells.\n\r",ch);
  else {
     add_buf( output, "\n\r" );
     page_to_char( str_dup( buf_string(output)), ch );
  }
   free_buf(output);
  return ;
}
 

void do_study(CHAR_DATA * ch, char * argument)
{
  char arg1[MAX_INPUT_LENGTH];
  char buf[MAX_STRING_LENGTH];
  OBJ_DATA *scroll;
  int i;

  if(IS_NPC(ch))
	return ;
 
  set_char_magic_bits(ch);
 
  argument = one_argument( argument, arg1 );

  if ( ( scroll = get_obj_carry( ch, arg1 ) ) == NULL )
  {
    send_to_char( "You do not have that scroll.\n\r", ch );
    return;
  }

  if ( scroll->item_type != ITEM_SCROLL )
  {
    send_to_char( "You can study only scrolls.\n\r", ch );
    return;
  }
  
  for(i=1; i<=3; i++)
  {
    if(scroll->value[i]<1)
      continue ; 
    if(ch->pcdata->learned[scroll->value[i]]>0)
    {
	sprintf(buf, "You already know %s.\n\r", 
                 skill_table[scroll->value[i]].name);
        send_to_char(buf,ch);
        continue ;
    }
    if(!has_spell_req(ch,scroll->value[i]))
    {
      sprintf(buf, "You do not have the requirements to learn %s.\n\r",
                skill_table[scroll->value[i]].name);
      send_to_char(buf,ch);
      continue ;
    }
    if(check_learn_spell(ch,scroll->value[i]))
    {
      ch->pcdata->learned[scroll->value[i]]=1;
      sprintf(buf, "Your studious nature has paid off.\n\rYou have learned %s.\n\r",
               skill_table[scroll->value[i]].name); 
      send_to_char(buf,ch);
      check_realm_imp(ch,scroll->value[i], TRUE);
    }
    else
    {
      sprintf(buf, "You have failed to learn %s.\n\r",
               skill_table[scroll->value[i]].name);
      check_realm_imp(ch,scroll->value[i], FALSE);
    }    

  }
  extract_obj(scroll);
  WAIT_STATE(ch, 300);
  return ;
}

void do_teach(CHAR_DATA *ch, char * argument)
{
  char arg1[MAX_INPUT_LENGTH];
  char arg2[MAX_INPUT_LENGTH];
  char buf[MAX_STRING_LENGTH];
  int sn;
  CHAR_DATA *victim;

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

  if(arg1[0]=='\0' || arg2[0]=='\0')
  {
    send_to_char("Syntax: teach <character> <spell>\n\r",ch);
    return ;	
  }
  
  if ( ( victim = get_char_room( ch, arg1 ) ) == NULL )
  {
    send_to_char( "They aren't here.\n\r", ch );
    return ; 
  }

  if(IS_SET(victim->act, PLR_NOTEACH))
  {
    send_to_char( "They can not be taught.\n\r", ch);	
    return ;
  }

  if( ( sn = skill_lookup(arg2) ) == -1  || 
        sn < skill_lookup("acid blast") ||
        sn > skill_lookup("wrath") )
  {
    send_to_char("That is not a spell.\n\r", ch);
    return ;
  } 

  if(IS_NPC(ch) || IS_NPC(victim))
  {
    send_to_char("Not with npcs.\n\r", ch);
    return ;
  }

  set_char_magic_bits(victim);
  
  if(ch->pcdata->learned[sn]<1)
  {
    send_to_char("You do not know that spell.\n\r",ch);
    return ;
  }

  if(victim->pcdata->learned[sn]>0)
  {
    send_to_char("They already know tht spell.\n\r",ch);
    return ;
  }

  if(victim->position>POS_RESTING)
  {
    send_to_char("Your student must be in a relaxed state.\n\r",ch);
    return ;
  }

  if(victim->position<POS_RESTING)
  {
    send_to_char("Your student must be awake.\n\r",ch);
    return ;
  }

  if(check_learn_spell(victim,sn))
  {
    victim->pcdata->learned[sn]=1;
    sprintf(buf,"You have learned %s from %s.\n\r",
            skill_table[sn].name, ch->name);
    send_to_char(buf,victim);
    send_to_char("You have taught your student well.\n\r",ch);
    check_realm_imp(ch,sn,TRUE);
    check_realm_imp(ch,sn,TRUE);
  }
  else
  { 
    send_to_char("You have failed.\n\r", ch);
    send_to_char("Your teacher was unable to help you.\n\r", victim);
    check_realm_imp(victim,sn,FALSE);
  }
 
  WAIT_STATE(ch, 400);
  WAIT_STATE(victim, 400);

  return ; 
}