/***************************************************************************
 *  Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer,	   *
 *  Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe.   *
 *									   *
 *  Merc Diku Mud improvments copyright (C) 1992, 1993 by Michael	   *
 *  Chastain, Michael Quan, and Mitchell Tse.				   *
 *									   *
 *  In order to use any part of this Merc Diku Mud, you must comply with   *
 *  both the original Diku license in 'license.doc' as well the Merc	   *
 *  license in 'license.txt'.  In particular, you may not remove either of *
 *  these copyright notices.						   *
 *									   *
 *  Much time and thought has gone into this software and you are	   *
 *  benefitting.  We hope that you share your changes too.  What goes	   *
 *  around, comes around.						   *
 ***************************************************************************/
 
/***************************************************************************
 *  File: clans.c							   *
 *        Clan code copyright (C) 1995 by Kevin Williams, and James 	   *
 *	  Ledbetter (zak@woodtech.com and thexder@woodtech.com)		   *
 ***************************************************************************/

#if defined(macintosh)
#include <types.h>
#else
#include <sys/types.h>
#endif
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <stdlib.h>
#include "merc.h"

/***************************************************************************
 *  Name:	find_clan						   *
 *  Purpose:	Accepts a string argument, searches the clans in memory    *
 *		for a clan->name matching the argument.	 Returns CLAN_DATA *
 *		for the clan if it exists, or NULL if it doesn't.	   *
 *  Called By:  do_mset (act_wiz.c), add_clan (clans.c),                   *
 *              do_show (act_info.c)		                           *
 ***************************************************************************/

CLAN_DATA *find_clan( char *name )
{
   CLAN_DATA *pClan;
   sh_int clannum;
   
   pClan = clan_first;
   while (pClan != NULL)
     {
	if (is_number(name))
	  {
	     clannum = atoi(name);
	     if (pClan->number == clannum ) return pClan;
	  }
	if (strcmp(pClan->name, name)==0) return pClan;
	pClan=pClan->next;
     }
   return pClan;
}

/***************************************************************************
 * Name:        clan_accept                                                *
 * Purpose:     Check CHAR_DATA arg to see if they can join clan arg2.     *
 * Called By:   ?                                                          *
 *                                                                         *
 * Returns:                                                                *
 *           0 : Yes                                                       *
 *           1 : Clan doesn't exist                                        *
 *           2 : Clan has reached max_members                              *
 *           3 : Player doesn't meet min_level req.                        *
 *           4 : Player must be PK.                                        *
 *           5 : Player doesn't meet class reqs.                           *
 *           6 : Player doesn't meet race reqs.                            *
 *           7 : Player is already a member of Clan.                       *
 ***************************************************************************/

sh_int clan_accept( CHAR_DATA *ch, char *clan )
{
   CLAN_DATA *pClan;
   bool      flag;
   sh_int    iClass;
   sh_int    iRace;
   sh_int    iMembers;
   
   flag = TRUE;
   pClan = find_clan(clan);
   if (pClan == NULL)
     {
	return 1;
     }
   if ((pClan->num_members+1) > pClan->max_members)
     {
	return 2;
     }
   if (pClan->min_level > ch->level)
     {
	return 3;
     }
   if ((pClan->req_flags == PLR_KILLER) && (!IS_SET(ch->act, PLR_KILLER)))
     {
	return 4;
     }
   for ( iClass=0 ; iClass < MAX_CLASS ; iClass++ )
     {
	if ((pClan->classes[iClass] == 0) && (ch->class == iClass))
	  {
	     flag = FALSE;
	  }
     }
   if (!flag)
     {
	return 5;
     }
   
   flag = TRUE;
   for ( iRace=0 ; iRace < MAX_PC_RACE ; iRace++ )
     {
	if ((pClan->races[iRace] == 0) && (ch->race == iRace))
	  {
	     flag = FALSE;
	  }
     }
   if (!flag)
     {
	return 6;
     }
   flag = TRUE;
   for ( iMembers=0 ; iMembers < pClan->num_members ; iMembers++ )
     {
	if (pClan->members[iMembers] == ch->name)
	  {
	     flag = FALSE;
	  }
     }
   if (!flag)
     {
	return 7;
     }
   return 0;
}

/***************************************************************************
 *  Name:	add_clan						   *
 *  Purpose:	Sticks CLAN_DATA argument on the end of the Clans stack.   *
 *  Called By:	?							   *
 ***************************************************************************/

void add_clan( CLAN_DATA *Clan )
{
char buf[MAX_STRING_LENGTH];
   CLAN_DATA *pClan;
   
   buf[0]='\0';
   if (top_clan==0)
     {
	clan_first = Clan;
	pClan = Clan;
	pClan->next = NULL;
	clan_last = pClan;
     	top_clan++;
	return;
     }
   else
     {
       pClan = clan_last;
	pClan->next = Clan;
	clan_last = pClan->next;
	clan_last->next=NULL;
	top_clan++;
	return;
     }
}

/***************************************************************************
 *  Name:	new_clan						   *
 *  Purpose:    Creates a new clan with default values.			   *
 *  Called By:	?							   *
 ***************************************************************************/

void new_clan(char *clan_name, CHAR_DATA *ch)
{
   CLAN_DATA *tempClan;
   int	  iClass;
   int	  iRace;
   
   tempClan = alloc_perm( sizeof(*tempClan));
   if (top_clan==0)
     tempClan->number=1;
   else
     tempClan->number=(clan_last->number)+1;
   tempClan->name = str_dup(clan_name);
   tempClan->visible = str_dup(clan_name);
   tempClan->leader="Emberly";
   tempClan->god = str_dup(ch->name);
   tempClan->max_members=10;
   tempClan->min_level=90;
   tempClan->num_members=0;
   tempClan->req_flags=0;
   for (iClass=0;iClass<MAX_CLASS;iClass++)
     tempClan->classes[iClass]=1;
   for (iRace=0;iRace<MAX_PC_RACE;iRace++)
     tempClan->races[iRace]=1;
   tempClan->auto_accept=1;
   tempClan->next=NULL;
   add_clan(tempClan);
}

/***************************************************************************
 *  Name:	save_clans						   *
 *  Purpose:	Save #CLANS section of the clans.are file.		   *
 *  Called By:	do_asave (olc_save.c).					   *
 ***************************************************************************/

void save_clans()		       
{
   FILE *clanfile;
   CLAN_DATA *Clan;
   int iClass, iRace, iMembers;
   
   clanfile = fopen( "clans.are", "w" );
   Clan=clan_first;
   fprintf( clanfile, "#CLANS\n" );
   while (Clan != NULL)
     {
        fprintf( clanfile, "%d\n", Clan->number);
        fprintf( clanfile, "%s~\n%s~\n", Clan->name, Clan->visible);
        fprintf( clanfile, "%s~\n%s~\n", Clan->leader, Clan->god);
	fprintf( clanfile, "%d %d %d ", Clan->max_members, Clan->min_level, Clan->num_members);
	fprintf( clanfile, "%ld ", Clan->req_flags);
	fprintf( clanfile, "%ld %ld ", Clan->cost_gold, Clan->cost_xp);
	for ( iClass=0;iClass<MAX_CLASS;iClass++)
	 fprintf( clanfile, "%d ", Clan->classes[iClass]);
	fprintf( clanfile, "\n");
	for ( iRace=0;iRace<MAX_PC_RACE;iRace++)
	 fprintf( clanfile, "%d ", Clan->races[iRace]);
	fprintf( clanfile, "\n");
	fprintf( clanfile, "%d\n", Clan->auto_accept);
	for ( iMembers=0;iMembers<Clan->num_members;iMembers++)
	 fprintf( clanfile, "%s~\n", Clan->members[iMembers]);
	fprintf( clanfile, "\n");
	Clan=Clan->next;
    }
    fprintf( clanfile, "999\n");
    fprintf( clanfile, "#$\n");
    fclose(clanfile);
    
    return;
}	     

/***************************************************************************
 *  Name:	do_clan 						   *
 *  Purpose:	Create, delete, and modify a clan.		           *
 *  Called By:	interp.c.       					   *
 ***************************************************************************/

void do_clan(CHAR_DATA *ch, char *argument)
{
   char buf [MAX_STRING_LENGTH];
   char arg  [MAX_INPUT_LENGTH];
   char arg2 [MAX_INPUT_LENGTH];
   char arg3 [MAX_INPUT_LENGTH];
   char arg4 [MAX_INPUT_LENGTH];
   char tempfile[MAX_STRING_LENGTH];
   CLAN_DATA *Clan;
   int value;
   
   
   tempfile[0] = '\0';
   buf[0] = '\0';
   smash_tilde( argument );
   argument = one_argument( argument, arg );
   argument = one_argument( argument, arg2 );
   argument = one_argument( argument, arg3 );
   strcpy( arg4, argument );
   
   /*
    * Snarf the value (which need not be numeric).
    */
   value = is_number( arg4 ) ? atoi( arg4 ) : -1;
   
   if ( arg[0] == '\0')
     { 
	send_to_char("Syntax:\n\r",ch);
	send_to_char("   clan create <name>\n\r",ch);
	send_to_char("   clan delete <name>\n\r",ch);
	send_to_char("   clan set <name> <field> <value>\n\r",ch);
	send_to_char("   Fields: name, visible, leader, god \n\r",ch);
	send_to_char("           max, level, flags, race, class\n\r",ch);
	send_to_char("		 accept\n\r",ch);
	return;
     }
   
   if (!str_cmp( arg, "create"))
     {
	if (arg2[0] == '\0')
	  {
	     send_to_char("You must provide a clan name.\n\r",ch);
	     return;
	  }
        if (find_clan(arg2) != NULL)
	  {
	     send_to_char("That clan already exists.\n\r",ch);
	   return;
	  }
	if (top_clan == MAX_CLAN)
	  {
	     send_to_char("Cannot create clan, max clans has been reached.\n\r", ch);
	     return;
	  }
	sprintf(buf, "Creating clan %s.\n\r", arg2);
	send_to_char(buf, ch);
        new_clan(arg2, ch);
	return;
     }
   else if (!str_cmp( arg, "set"))
   {
      if (arg2[0] == '\0')
	{
	   send_to_char("You must provide a clan name.\n\r",ch);
	   return;
	}
      if ((Clan = find_clan(arg2) ) == NULL)
	{
	   send_to_char("That clan does not exist.\n\r",ch);
	   return;
	}
      if (arg3[0] == '\0')
	{
	   send_to_char("You must selecet a field to edit.\n\r",ch);
	   send_to_char("   Fields: name, visible, leader, god \n\r",ch);
	   send_to_char("           max, level, flags, race, class\n\r",ch);
	   send_to_char("		 accept\n\r",ch);
	   return;
	}
      
    /* Set something */
      
      if (!str_cmp(arg3, "name") )
	{
	   if (arg4[0] == '\0' )
	     {
		send_to_char("You must supply an argument.\n\r", ch);
		return;
	     }
	   
	   if (is_number(arg4) )
	     {
		send_to_char("Clan name must not be numeric.\n\r", ch);
		return;
	     }
	   sprintf(buf, "Clan %s will now be known as %s.\n\r", Clan->name, arg4);
	   send_to_char(buf,ch);
	   Clan->name = str_dup( arg4 );
	   return;
	}
      if (!str_cmp(arg3, "visible" ) )
	   {
	      if (arg4[0] == '\0' )
	     {
		send_to_char("You must supply an argument.\n\r", ch);
		return;
	     }
	      sprintf(buf, "Clan %s will now be shown as %s.\n\r", Clan->name, arg4);
	      Clan->visible = str_dup(arg4);
	      send_to_char(buf, ch);
	      return;
	   }
      if (!str_cmp(arg3, "leader" ) )
	{
	   FILE *fp;
	   
	   if (arg4[0] == '\0' )
	     {
		send_to_char("You must supply an argument.\n\r", ch);
		return;
	     }
	   sprintf(tempfile, "%s%s", PLAYER_DIR, capitalize(arg4) );
	   if ( (fp = fopen( tempfile, "r" ) ) != NULL )
	     {
		sprintf(buf, "%s is now the the leader of %s.\n\r", capitalize(arg4), Clan->visible);
		Clan->leader = str_dup(arg4);
		send_to_char(buf, ch);
		fclose(fp);
		return;
	     }
	   send_to_char("That character is not a player on this mud.\n\r", ch);
	   fclose(fp);
	   return;
	}
      if (!str_cmp( arg3, "god") )
	{
	   FILE *fp;
	   
	   if (arg4[0] == '\0' )
	     {
		send_to_char("You must supply an argument.\n\r", ch);
		return;
	     }
	   sprintf(tempfile, "%s%s", GOD_DIR, capitalize(arg4) );
	   if ( (fp = fopen( tempfile, "r" ) ) != NULL )
	     {
		sprintf( buf, "%s is now the god sponsor for %s.\n\r", capitalize(arg4), Clan->visible);
		Clan->god = str_dup(arg4);
		send_to_char(buf, ch);
		fclose(fp);
		return;
	     }
	   send_to_char("That player is not a god on this mud.\n\r", ch);
	   fclose(fp);
	   return;
	}
      if (!str_cmp( arg3, "max") )
	{
	   if (arg4[0] == '\0' )
	     {
		send_to_char("You must supply an argument.\n\r", ch);
		return;
	     }
	   if ( !is_number(arg4) )
	     {
		send_to_char("Max clan members must be a numeric value.\n\r", ch);
		return;
	     }
	   if ( value < 1 || value > MAX_CLAN_MEMBERS )
	     {
		sprintf(buf, "Max clan members must be between 1 and %d.\n\r", MAX_CLAN_MEMBERS);
		send_to_char( buf, ch);
		return;
	     }
	   sprintf(buf, "%s can now have %d members.\n\r", Clan->visible, value);
	   Clan->max_members = value;
	   send_to_char(buf, ch);
	   return;
	}
      if (!str_cmp( arg3, "level" ) )
	   {
	      if (arg4[0] == '\0' )
		{
		   send_to_char("You must supply an argument.\n\r", ch);
		   return;
		}
	      if ( !is_number(arg4) )
		{
		   send_to_char("Minimum level for clan must be a numeric value.\n\r", ch);
		   return;
		}
	      if (value < 1 || value > MAX_LEVEL + 2 )
		{
		   sprintf(buf, "Min level for clan must be between 1 and %d.\n\r", MAX_LEVEL+2);
		   send_to_char(buf, ch);
		   return;
		}
	      sprintf(buf, "The min level for %s is now %d.\n\r", Clan->visible, value);
	      Clan->min_level = value;
	      send_to_char(buf, ch);
	      return;
	   }
      if (!str_cmp( arg3, "reqs" ) )
	{
	   if (arg4[0] == '\0' )
	     {
		send_to_char("Flags:\n\r", ch);
		send_to_char("      PLR_KILLER\n\r", ch);
		return;
	     }
	   if ( str_cmp( arg4, "PLR_KILLER") )
	     {
		send_to_char("Flags:\n\r", ch);
		send_to_char("      PLR_KILLER\n\r", ch);
		return;
	     }
	   if (Clan->req_flags == PLR_KILLER) 
	     {
		sprintf( buf, "PK is no longer required by %s.\n\r", Clan->visible);
		send_to_char(buf, ch);
		Clan->req_flags = 0;
		return;
	     }
	   sprintf( buf, "PK is now required by %s.\n\r", Clan->visible);
	   send_to_char(buf, ch);
	   Clan->req_flags = PLR_KILLER;
	   return;
	}
      if (!str_cmp( arg3, "race") )
	{
	   int race;
	   
	   if (arg4[0] == '\0' )
	     {
		send_to_char("You must supply an argument.\n\r", ch);
		return;
	     }
	   race = race_lookup(arg4);
	   if ( race == 0  || !race_table[race].pc_race)
	     {
		send_to_char("That is not a valid player race.\n\r", ch);
		return;
	     }
	   if (Clan->races[race] == 1 )
	     {
		sprintf(buf, "%s are no longer allowed in %s.\n\r", pc_race_table[race].name, Clan->visible);
		Clan->races[race] = 0;
		send_to_char(buf, ch);
		return;
	     }
	   else
	     {
		sprintf(buf, "%s are now allowed in %s.\n\r", pc_race_table[race].name, Clan->visible);
		Clan->races[race] = 1;
		send_to_char(buf, ch);
		return;
	     }
	   bug("Error while setting clan race.", 0);
	   return;
	}
      if (!str_cmp( arg3, "class") )
	{
	   int class;
	   
	   if (arg4[0] == '\0' )
	     {
		send_to_char("You must supply an argument.\n\r", ch);
		return;
	     }
	   class = class_lookup(arg4);
	   if ( class == 0)
	     {
		send_to_char("That is not a valid class.\n\r", ch);
		return;
	     }
	   if (Clan->classes[class] == 1)
	     {
		sprintf(buf, "%ss are no longer allowed in %s.\n\r", class_table[class].name, Clan->visible);
		Clan->classes[class] = 0;
		send_to_char(buf, ch);
		return;
	     }
	   else
	     {
		sprintf(buf, "%ss are now allowed in %s.\n\r", class_table[class].name, Clan->visible);
		Clan->classes[class] = 1;
		send_to_char(buf, ch);
		return;
	     }
	   bug("error while setting clan class.", 0);
	   return;
	}
      if ( !str_cmp( arg3, "accept") )
	{
	   if (Clan->auto_accept == 0 )
	     {
		sprintf( buf, "%s will now auto-accept members.\n\r", Clan->visible);
		Clan->auto_accept = 1;
		send_to_char(buf, ch);
		return;
	     }
	   sprintf( buf, "%s will no longer auto-accept members.\n\r", Clan->visible);
	   Clan->auto_accept = 0;
	   send_to_char(buf, ch);
	   return;
	}
   }
/*
 * Generate Usage Message   
 */
   do_clan(ch, "");
   return;
}

bool is_clan_leader(char *name, char *Clan)
{
   CLAN_DATA    *pClan;
   
   pClan = find_clan(Clan);
   if (!str_cmp(name, pClan->leader) )
     {
	return TRUE;
     }
   else
     return FALSE;
}

char * vis_clan(int clan)
{
    CLAN_DATA * pClan;
    
    for ( pClan=clan_first; pClan != NULL ; pClan=pClan->next)
        if ( pClan->number == clan)
    	    return( pClan->visible );
    return( "" );
}

char * clan_lookup(int clan)
{
   CLAN_DATA *pClan;
   
   for ( pClan=clan_first; pClan !=NULL; pClan=pClan->next)
     {
	if ( pClan->number == clan)
	  return( pClan->name );
     }
   return( "" );
}