/
Archipelago/
Archipelago/doc/
Archipelago/lib/misc/
Archipelago/lib/plrobjs/
Archipelago/lib/plrobjs/P-T/
Archipelago/lib/world/mob/
Archipelago/lib/world/obj/
Archipelago/lib/world/shp/
Archipelago/lib/world/wld/
Archipelago/lib/world/zon/
Archipelago/slave/
/* ************************************************************************
 *   File: guilds.c                                   Part of Archipelago  *
 *  Usage: implementation of special procedures for guilds                 *
 *                                                                         *
 *  Archipelago is based on                                                *
 *  CircleMUD is based on DikuMUD, Copyright (C) 1990, 1991.               *
 *  Archipelago changes by Alastair J. Neil Copyright (C) 1993, 94, 95, 96 * 
 ************************************************************************ */

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

#include "structs.h"
#include "utils.h"
#include "comm.h"
#include "interpreter.h"
#include "handler.h"
#include "db.h"
#include "spells.h"
#include "limits.h"


/*   external vars  */
extern struct room_data *world;
extern struct char_data *character_list;
extern struct descriptor_data *descriptor_list;
extern struct index_data *mob_index;
extern struct index_data *obj_index;
extern struct time_info_data time_info;
extern struct spell_info_type spell_info[];
extern struct list_index_type CrIg[];
extern struct list_index_type wizened[];
extern struct list_index_type archivist[];
extern struct list_index_type clio[];
extern struct list_index_type Water[];
extern struct list_index_type CrCo[];
extern struct list_index_type ReCo[];
extern struct list_index_type Mason_spells[];
extern struct list_index_type MuCo[];
extern struct list_index_type PeCo[];
extern struct list_index_type PeIm[];
extern struct list_index_type InIm[];
extern struct list_index_type Thin_spells[];
extern struct list_index_type Stout_spells[];
extern struct list_index_type Animal[];
extern struct list_index_type am_skills[];
extern struct list_index_type Cleric_skills[];
extern struct list_index_type Warrior_skills[];
extern struct list_index_type Thief_skills[];
extern struct list_index_type Hasad_skills[];
extern struct list_index_type Horse_skills[];
extern struct list_index_type Ranger_skills[];
extern struct list_index_type Weapons[];
int	add_follower(struct char_data *ch, struct char_data *leader);
int     calc_difficulty(struct char_data *ch, int number);
int     calc_prof_difficulty(struct char_data *ch, int number);
/*int     calc_max_ability(struct char_data *ch, int number); */
void check_autowiz(struct char_data *ch);
struct social_type {
  char	*cmd;
  int	next_line;
};


/* ********************************************************************
 *  Special procedures for rooms                                       *
 ******************************************************************** */
int     get_stat(struct char_data *ch, int stat_index)
{

  switch(stat_index){
  case 0:
    return 20;
  case 1:
    return GET_RAW_STR(ch);
  case 2:
    return GET_RAW_INT(ch);
  case 3:
    return GET_RAW_WIS(ch);
  case 4:
    return GET_RAW_CON(ch);
  case 5:
    return GET_RAW_DEX(ch);
  case 6:
    return GET_RAW_CHR(ch);    
  case 7:
    return GET_RAW_PER(ch);    
  case 8:
    return GET_RAW_GUI(ch);    
  case 9:
    return GET_RAW_LUC(ch);
  case 10:
    return GET_RAW_FOC(ch);
  case 11:
    return GET_RAW_DEV(ch);    	 
  default:
    return 20;
  }
}

int     calc_difficulty(struct char_data *ch, int number)
{
  int stat1,stat2,stat3,stat4;
  int tmp;


  stat1 = spell_info[number].key_stats;
  stat2 = spell_info[number].sec_stats;
  stat3 = spell_info[number].ter_stats;

  if(!(spell_info[number].spll_pointer)){
    if (stat1 !=0 && stat2 == 0 && stat3 ==0 )
      return (20*spell_info[number].difficulty)/get_stat(ch,stat1);
    if (stat1 !=0 && stat2 != 0 && stat3 ==0 ){
      stat4 = MAX(1,3*get_stat(ch,stat1)/4 + get_stat(ch,stat2)/4);
      return (20*spell_info[number].difficulty)/stat4;}
    if (stat1 !=0 && stat2 == 0 && stat3 !=0 ){
      stat4 = MAX(1,5*get_stat(ch,stat1)/6 + get_stat(ch,stat3)/6);
      return (20*spell_info[number].difficulty)/stat4;}
    if (stat1 !=0 && stat2 != 0 && stat3 !=0 ){
        stat4 = spell_info[number].difficulty;
        tmp = 8 - get_stat(ch,stat1)/3;
        tmp = MAX(0, tmp);
        stat4 += tmp;
        tmp = (8 - get_stat(ch,stat2)/3)/2;
        tmp = MAX(0, tmp);
        stat4 += tmp;
        tmp = (8 - get_stat(ch,stat3)/3)/4;
        tmp = MAX(0, tmp);
        stat4 += tmp;
        stat4 = MAX(spell_info[number].difficulty - 1, stat4);
      return( stat4);
}

    return spell_info[number].difficulty;
  }
  else{
    stat4 = GET_SKILL(ch,SKILL_MAGICTHEORY) + GET_RAW_INT(ch)
      + 3*stat1 + 3*stat4;
    if (stat4)
      return(MAX(1,(spell_info[number].difficulty*
		    spell_info[number].min_level)/stat4));
	 
    return spell_info[number].difficulty;
  }
}

int     calc_prof_difficulty(struct char_data *ch, int number)
{
  int stat1,stat2,stat3,stat4;

  stat1 = spell_info[number].key_stats;
  stat2 = spell_info[number].sec_stats;
  stat3 = spell_info[number].ter_stats;

  if (stat1 !=0 && stat2 == 0 && stat3 ==0 )
    return (20*spell_info[number].difficulty)/get_stat(ch,stat1);
  if (stat1 !=0 && stat2 != 0 && stat3 ==0 ){
    stat4 = MAX(1,3*get_stat(ch,stat1)/4 + get_stat(ch,stat2)/4);
    return (20*spell_info[number].difficulty)/stat4;}
  if (stat1 !=0 && stat2 == 0 && stat3 !=0 ){
    stat4 = MAX(1,5*get_stat(ch,stat1)/6 + get_stat(ch,stat3)/6);
    return (20*spell_info[number].difficulty)/stat4;}
  if (stat1 !=0 && stat2 != 0 && stat3 !=0 ){
    stat4 = MAX(1,2*get_stat(ch,stat1)/3 + 2*get_stat(ch,stat2)/9 
      + get_stat(ch,stat3)/9);
    return (20*spell_info[number].difficulty)/stat4;}

  return spell_info[number].difficulty;
}



SPECIAL(guild)
{
  ACMD(do_say);
  int number, npracs, mpracs,i, percent,diff;
  long guild_no = 0 ;
  int eff_lev, pc_race, race_mult=15, max_lev;
  struct char_data *guildmaster;
  char str0[100],str1[100],str2[100],str3[100];
  struct list_index_type *this_list;
  
  bool no_pointer = FALSE, found = FALSE;
  /*
    164 = study
    170 = learn
    309 = train
    */
  /* find a guildmaster */
  for (guildmaster = world[ch->in_room].people;
       guildmaster;
       guildmaster= guildmaster->next_in_room)
    if (mob_index[guildmaster->nr].func == guild)
      break;
  if(!guildmaster)
    return(FALSE);
     
     
  if (IS_NPC(ch) || ((cmd != 164) && (cmd != 170) && (cmd != 302) && (cmd != 309)))
    return(FALSE);
     
  pc_race = (1 << GET_RACE(ch));     
  if (cmd == 164 || cmd == 170){
    if (cmd == 164){
      strcpy(str0,"You have got %d study sessions left.\r\nYou can study any of these spells:\r\n");
      sprintf(str1,"%-36s      %-5s %-10s %-10s %-10s\r\n","Spell Name","Level","Difficulty","How Well","Max Guild.");
      strcpy(str2,"----------------------------------------- ----- ---------- ---------- ----------\r\n");
      strcpy(str3,"You do not know of this spell...\r\n");
      if (mob_index[guildmaster->nr].virtual == 1219){
	SET_BIT(guild_no, (1 << CRIG_GUILD));
	this_list = CrIg;
      }
      else if (mob_index[guildmaster->nr].virtual == 1221){
	SET_BIT(guild_no, (1 << CRAQ_GUILD));
	SET_BIT(guild_no, (1 << MUAQ_GUILD));		
	this_list = Water;
      }
      else if (mob_index[guildmaster->nr].virtual == 2011){
	SET_BIT(guild_no, (1 << CRCO_GUILD));
	SET_BIT(guild_no, (1 << CRIG_GUILD));	
	SET_BIT(guild_no, (1 << MUAQ_GUILD));		
	this_list = wizened;
      }
      else if (mob_index[guildmaster->nr].virtual == 1206){
	SET_BIT(guild_no, (1 << CRCO_GUILD));
	SET_BIT(guild_no, (1 << MUCO_GUILD));
	SET_BIT(guild_no, (1 << RECO_GUILD));			
	this_list = clio;
      }
      else if (mob_index[guildmaster->nr].virtual == 1222){
	SET_BIT(guild_no, (1 << CRCO_GUILD));	
	this_list = CrCo;
      }
      else if (mob_index[guildmaster->nr].virtual == 1223){
	SET_BIT(guild_no, (1 << RECO_GUILD));
	SET_BIT(guild_no, (1 << MUCO_GUILD));
	SET_BIT(guild_no, (1 << PECO_GUILD));				
	this_list = Stout_spells;
      }
      else if (mob_index[guildmaster->nr].virtual == 2067){
	SET_BIT(guild_no, (1 << MUCO_GUILD));
	SET_BIT(guild_no, (1 << PEIM_GUILD));
	SET_BIT(guild_no, (1 << INIM_GUILD));
	SET_BIT(guild_no, (1 << INVM_GUILD)); 		
	SET_BIT(guild_no, (1 << CRIM_GUILD));
	SET_BIT(guild_no, (1 << MUAU_GUILD)); 			
	this_list = Thin_spells;
      }
      else if (mob_index[guildmaster->nr].virtual == 2083){
	SET_BIT(guild_no, (1 << INVM_GUILD));
	SET_BIT(guild_no, (1 << INIM_GUILD)); 			
	SET_BIT(guild_no, (1 << CRIM_GUILD)); 		
	this_list = archivist;
      }
      else if (mob_index[guildmaster->nr].virtual == 2080){
	SET_BIT(guild_no, (1 << RETE_GUILD));
	SET_BIT(guild_no, (1 << MUTE_GUILD));				
	this_list = Mason_spells;
      }
      else
	return(FALSE);
    }
    else if (cmd == 170){
      strcpy(str0,"You have got %d study sessions left.\r\nYou can practice any of these skills:\r\n");
      sprintf(str1,"%-36s %-10s %-10s %-10s\r\n","Skill Name","Difficulty","How Well","Max Guild.");
      strcpy(str2,"----------------------------------   ---------- ---------- ------------\r\n");
      strcpy(str3,"You do not know of this skill...\r\n");
      if ((mob_index[guildmaster->nr].virtual == 2014)){
	SET_BIT(guild_no, (1 << WARRIOR_GUILD));		
	this_list = Warrior_skills;
      }
      else if (mob_index[guildmaster->nr].virtual == 2070){
	SET_BIT(guild_no, (1 << RIDING_GUILD));			
	this_list = Horse_skills;
      }
      else if ((mob_index[guildmaster->nr].virtual == 2012)){
	SET_BIT(guild_no, (1 << CLERIC_GUILD));	
	this_list = Cleric_skills;
      } 
      else if (mob_index[guildmaster->nr].virtual == 2013){
	SET_BIT(guild_no, (1 << THIEF_GUILD));	 	
	this_list = Thief_skills;
      }
      else{
	this_list = am_skills;
	SET_BIT(guild_no, (1 << ARSMAGICA_GUILD));	 		
	no_pointer = TRUE;
      }
    }
  }
  else if ((cmd == 309) &&((mob_index[guildmaster->nr].virtual== 2014))){
    strcpy(str0,"You have got %d training sessions left.\r\nYou can train any of the following weapons:\r\n");
    sprintf(str1,"%-36s %-10s %-10s %-10s\r\n","Weapon Name","Difficulty","How Well","Max Guild.");
    strcpy(str2,"----------------------------------   ---------- ---------- ------------\r\n");
    strcpy(str3,"You do not know of this weapon...\r\n");
    SET_BIT(guild_no, (1 << WARRIOR_GUILD));		    
    this_list = Weapons;
  }
  else
    return(FALSE);
  for (; *arg == ' '; arg++)
    ;
  if (!*arg) {
    found = FALSE;
    for (i = 0; *(this_list[i].entry) != '\n';i++){
      diff = calc_difficulty(ch,this_list[i].index ) + 1;
      if (!spell_info[this_list[i].index].use_bas_lev)
	eff_lev = (ubyte) spell_info[this_list[i].index].min_level*diff;
      else
	eff_lev = (ubyte) spell_info[this_list[i].index].min_level;
      if (cmd == 164){
	if ((!spell_info[this_list[i].index].race_flag ||
	     IS_SET(spell_info[this_list[i].index].race_flag, pc_race)) &&
	    (spell_info[this_list[i].index].min_level
	     <= (GET_SKILL(ch, SKILL_MAGICTHEORY)+GET_RAW_INT(ch)
		 + 3*GET_SKILL(ch, spell_info[this_list[i].index].key_stats) +
		 3*GET_SKILL(ch, spell_info[this_list[i].index].sec_stats))) &&
	    IS_SET(guild_no,(1<< spell_info[this_list[i].index].which_guild)))
	  {
	    found = TRUE;
	    break;}		     
      }
      else
	{
	  if (eff_lev <= GET_LEVEL(ch) &&
	      IS_SET(guild_no,(1<< spell_info[this_list[i].index].which_guild))) {
	    found = TRUE;
	    break;
	  }
	}
    }
    if (!found){
      do_say(guildmaster,"I cannot instruct you in this.",0,0);
      do_say(guildmaster,"You are not ready for my lore.",0,0); 
      return(TRUE);
    }
    sprintf(buf,str0 ,SPELLS_TO_LEARN(ch));
    sprintf(buf2,str1);
    strcat(buf,buf2);
    sprintf(buf2,str2);
    strcat(buf,buf2);
    if (cmd == 164) {
      for (i = 0; *(this_list[i].entry) != '\n'; i++){
	diff = calc_difficulty(ch,this_list[i].index ) + 1;	
	eff_lev = (GET_SKILL(ch, SKILL_MAGICTHEORY) +
		   GET_RAW_INT(ch) + 
		   3*GET_SKILL(ch, spell_info[this_list[i].index].key_stats) +
		   3*GET_SKILL(ch, spell_info[this_list[i].index].sec_stats));
	if (spell_info[this_list[i].index].race_flag &&
	    IS_SET(spell_info[this_list[i].index].race_flag, pc_race))
	  race_mult = 15;
	else
	  race_mult = 10;
	max_lev = (race_mult*spell_info[this_list[i].index].max_level)/10
	  + (GET_RAW_CHR(ch) -15)/3;
	max_lev = MIN(30,max_lev);
	if ((!spell_info[this_list[i].index].race_flag ||
	     IS_SET(spell_info[this_list[i].index].race_flag, pc_race)) &&
	    (eff_lev >= spell_info[this_list[i].index].min_level) &&
	    IS_SET(guild_no,(1<< spell_info[this_list[i].index].which_guild)))
	  {
	  sprintf(buf2, "%-36s %4s %-5d %-10d %-10d %-10d\r\n",
		  this_list[i].entry,
		  this_list[i].components,
		  spell_info[this_list[i].index].min_level,		  
		  diff,
		  GET_SKILL(ch, this_list[i].index),
		  ((spell_info[this_list[i].index].max_level)
		   ? max_lev : 30));
	  strcat(buf, buf2);
	}
      }
    }
    else {
      for (i = 0; *(this_list[i].entry) != '\n'; i++){
	diff = calc_difficulty(ch,this_list[i].index) + 1;
	if (spell_info[this_list[i].index].race_flag &&
	    !IS_SET(spell_info[this_list[i].index].race_flag,pc_race)) {
	  diff *= 2;
	  race_mult = 10;
	}
	else
	  race_mult = 15;
	max_lev = (race_mult*spell_info[this_list[i].index].max_level)/10
	  + (GET_RAW_CHR(ch) -15)/3;
	max_lev = MIN(30,max_lev);	
	if (!spell_info[this_list[i].index].use_bas_lev)
	  eff_lev = (ubyte) spell_info[this_list[i].index].min_level*diff;
	else
	  eff_lev =(ubyte) spell_info[this_list[i].index].min_level;
	if ((eff_lev <= GET_LEVEL(ch)) && 
	    IS_SET(guild_no,(1<< spell_info[this_list[i].index].which_guild)))
	  {
	    sprintf(buf2, "%-37s %-10d %-10d %-10d\r\n", this_list[i].entry,
		    diff,
		    GET_SKILL(ch, this_list[i].index),
		    ((spell_info[this_list[i].index].max_level)
		     ? max_lev :30));  
	    strcat(buf, buf2);
	  }
      }
    }
    send_to_char(buf, ch);
    return(TRUE); 
  }
  half_chop(arg,buf1,buf2);
  if (!is_number(buf1)) {
    npracs = 1;
    strcpy(buf2, arg);
  }
  else
    npracs = atoi(buf1);
  if (!*buf2){
    send_to_char("What was that?\r\n",ch);
    return(TRUE);}
  number = search_list(buf2, this_list, FALSE);
  if (number == -1) {
    send_to_char(str3, ch);
    return(TRUE);
  }
  if (number >= 0 &&
      !(IS_SET(guild_no,(1<< spell_info[number].which_guild))))
    {
      send_to_char("Can you be a bit more specific?\r\n",ch);
      return(TRUE);
    }
  diff = calc_difficulty(ch,number) +1;
  if (cmd == 164){
    eff_lev = (GET_SKILL(ch, SKILL_MAGICTHEORY) + GET_RAW_INT(ch) +
	       3*GET_SKILL(ch, spell_info[number].key_stats) +
	       3*GET_SKILL(ch, spell_info[number].sec_stats));
    if ( (!spell_info[number].race_flag ||
	  IS_SET(spell_info[number].race_flag, pc_race)) && 
	 (eff_lev < spell_info[number].min_level) &&
	 (IS_SET(guild_no,(1<< spell_info[number].which_guild))))
      {
	send_to_char(str3, ch);
	return(TRUE);
      }
  }
  else{
    if (spell_info[number].race_flag &&
	!IS_SET(spell_info[number].race_flag, pc_race))
      diff *= 2;
    if (!spell_info[number].use_bas_lev)
      eff_lev = (ubyte) spell_info[number].min_level*diff;
    else
      eff_lev = (ubyte) spell_info[number].min_level;
    if ((GET_LEVEL(ch) < eff_lev) &&
	(IS_SET(guild_no,(1<< spell_info[number].which_guild))))
      {
	send_to_char(str3, ch);
	return(TRUE);
      }
  }
  if (SPELLS_TO_LEARN(ch) <= 0) {
    send_to_char("You do not seem to be able to practice now.\r\n", ch);
    return(TRUE);
  }
  if (spell_info[number].race_flag &&
      !IS_SET(spell_info[number].race_flag,pc_race)) 
    race_mult = 10;
  else
    race_mult = 15;
  max_lev =(race_mult*spell_info[number].max_level)/10+(GET_RAW_CHR(ch) -15)/3;
  max_lev = MIN(30,max_lev);  
  if (spell_info[number].max_level &&
      (GET_SKILL(ch, number) >= max_lev))
    {
      send_to_char("I'm sorry I cannot instruct you further.\r\n", ch);
      return(TRUE);
    }	     
  if (GET_SKILL(ch, number) >= 30) {
    send_to_char("You are already learned in this area.\r\n", ch);
    return(TRUE);
  }

  while (npracs && GET_SKILL(ch, number) < 30) {
    if (SPELLS_TO_LEARN(ch) <  (diff*GET_SKILL(ch,number) +1 )) {
      send_to_char("Not enough practices to get to the next level.\r\n",ch);
      return(TRUE);}      
    if (spell_info[number].max_level &&
	(GET_SKILL(ch, number) >= max_lev))
      break;
    percent = GET_SKILL(ch,number) + 1;
    SET_SKILL(ch,number, percent);
    SPELLS_TO_LEARN(ch) -= diff*GET_SKILL(ch,number);
    npracs--;
  }
	 
  send_to_char("You Practice for a while...\r\n", ch);	 

  if (GET_SKILL(ch, number) >= 30) {
    send_to_char("You are now learned in this area.\r\n", ch);
    return(TRUE);
  }
  return(TRUE);
}