EmberMUD-0.9.44/
EmberMUD-0.9.44/clan/
EmberMUD-0.9.44/classes/
EmberMUD-0.9.44/gods/
EmberMUD-0.9.44/log/
EmberMUD-0.9.44/player/
EmberMUD-0.9.44/player/temp/
EmberMUD-0.9.44/src/MSVC/
EmberMUD-0.9.44/src/Sleep/
EmberMUD-0.9.44/src/StartMUD/
EmberMUD-0.9.44/src/Win32Common/
/***************************************************************************
 *  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:  Clan.c                                                           *
 * Written by: Kyle Boyd                                                   *
 * Partially inspired by some code written by Zane(E.J. Wilburn), as well *
 * as clan code from SMAUG(?) and ROM muds.  None of what you see here was *
 * directly copied from those versions of clan code, just some of the      *
 * ideas were used.                                                        *
 ***************************************************************************/

#if defined(macintosh)
#include <types.h>
#else
#include <sys/types.h>
#endif
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <stdarg.h>
#include "merc.h"
#include "olc.h"
DECLARE_DO_FUN( do_look );
DECLARE_DO_FUN( do_save );

#define CEDIT( fun )		bool fun( CHAR_DATA *ch, char *argument )

const struct olc_cmd_type cedit_table[] =
{
/*  {   command		    function	    }, */
    {   "create",	    cedit_create	},
    {   "leader",		cedit_leader	},
    {   "sponsor",	    cedit_sponsor	},
    {   "name",		    cedit_name	    },
    {   "whoname",	    cedit_whoname   },
    {	"show",		    cedit_show	    },
    {   "minlevel",  	cedit_minlevel  },  
    {   "members",      cedit_members   },  
    {   "recall",		cedit_recall    },  
    {   "joinflags",	cedit_joinflags }, 
    {   "clanflags",	cedit_clanflags }, 
/* To be implemented later... */
/* These will add clan-specific skills and commands. */
/* 
    {   "skill",		cedit_skill     },
*/
    {   "rank",		    cedit_rank      },
    {   "cost",		    cedit_cost      },
    {   "?",		    show_help	    },
    {   "version",	    show_version	},
    {   "commands",	    show_commands	},
    {	"",		        0,      		}
};

void save_clans( void )
{
	FILE *fp;
	CLAN_DATA *clan;
	char buf[MAX_INPUT_LENGTH];
	int i;
	if( clan_first == NULL ) return;

    sprintf(buf, "%s/%s", sysconfig.area_dir, sysconfig.clans_file);
    fp = fopen( buf, "w" );
    if (fp == NULL)
    {
		bug("Cannot write to %s !!!", sysconfig.clans_file);
        return;
    }

    fprintf( fp, "#CLANS\n" );
	for( clan = clan_first; clan != NULL; clan = clan->next )
	{
		fprintf( fp, "%d\n", clan->number );
		fprintf( fp, "%s~\n", clan->name );
		fprintf( fp, "%s~\n", clan->whoname );
		fprintf( fp, "%s~\n", clan->leader );
		fprintf( fp, "%s~\n", clan->god );
		fprintf( fp, "%d\n", clan->max_members );
		fprintf( fp, "%d\n", clan->min_level );
		fprintf( fp, "%d\n", clan->num_members );
		buf[0]='\0';
		fprintf( fp, "%s\n", fwrite_flag( clan->clan_flags, buf ));
		buf[0]='\0';
		fprintf( fp, "%s\n", fwrite_flag( clan->join_flags, buf ));
		fprintf( fp, "%d\n", clan->cost_gold );
		fprintf( fp, "%d\n", clan->recall_room );
		fprintf( fp, "%d\n", clan->clan_fund );
		/* The reason that all of these fprintf functions have a letter to start off 
		   with is in case the MAX_* change, so the lines will be identifyable as what
		   they are, since the number of them may change.
		   Note: if you DECREASE the MAX_*'s, you'll need to edit the clans file and 
		   remove the excess lines.  -Kyle */
		for( i=0 ; i<MAX_CLAN_MEMBERS ; i++ )
		{
			if( clan->members[i][0]!='\0' )
			fprintf( fp, "M %d %s~\n", i+1, clan->members[i] );
		}
		for( i=0 ; i<MAX_CLAN ; i++ )
		{
			if( clan->kills[i] != 0 )
			fprintf( fp, "K %d %d\n", i+1, clan->kills[i] );
		}
		for( i=0 ; i<MAX_CLAN ; i++ )
		{
			if( clan->deaths[i] != 0 )
			fprintf( fp, "D %d %d\n", i+1, clan->deaths[i] );
		}
		for( i=0 ; i<MAX_RANK ; i++ )
		{
			fprintf( fp, "R %d %s~\n", i+1, clan->rank[i] );
		}
		fprintf( fp, "E\n" ); /* End of this clan. */
	}
	fprintf( fp, "999\n#$\n#$\n"); /* I hope you don't make more than 998 clans... :) */
	fclose( fp );

	return;
}

/* Read in str as the next string of fp.  
Free it if there's a string there already. 
	-Kyle */
#define GETSTR( str )  if ( str != NULL ) \
				{  \
				 free_string( &str ); \
				 str = fread_string( fp ); \
				}	\
				else	\
				str = fread_string( fp );

void load_clans( FILE *fp )
{
	int i, x, num;
	CLAN_DATA *clan;
	bool done;

	for( ;; )
	{
		num = fread_number( fp );
		if( num == 999 )
			break;
		else
		clan = new_clan();
		if( num != clan->number )
		{
			bug("%s clan #%d misaligned.", sysconfig.clans_file, num);
			return;
		}
		GETSTR( clan->name );
		GETSTR( clan->whoname );
		GETSTR( clan->leader );
		GETSTR( clan->god );
		clan->max_members = fread_number( fp );
		clan->min_level = fread_number( fp );
		clan->num_members = fread_number( fp );
		clan->clan_flags = fread_flag( fp );
		clan->join_flags = fread_flag( fp );
		clan->cost_gold = fread_number( fp );
		clan->recall_room = fread_number( fp );
		clan->clan_fund = fread_number( fp );
		done = FALSE;
		for( ; done == FALSE ; )
		{
		switch( fread_letter( fp ) )
		{
			default: bug("Bad letter in %s", sysconfig.clans_file); break;
			case 'M':
				i = fread_number( fp );
				GETSTR( clan->members[i-1] );
				{
				for(x=0;x<MAX_CLAN_MEMBERS;x++)
				{ if( x == (i-1) )continue;
				if( !str_cmp(clan->members[i-1], clan->members[x]))
				{
				free_string(&clan->members[i-1]);
				clan->members[i-1] = str_dup("");
				}  
				}
				}
				break;
			case 'K':
				i = fread_number( fp );
				clan->kills[i-1] = fread_number( fp );
				break;
			case 'D':
				i = fread_number( fp );
				clan->deaths[i-1] = fread_number( fp );
				break;
			case 'R':
				i = fread_number( fp );
				GETSTR( clan->rank[i-1] );
				break;
			case 'E':
				done = TRUE;
				break;
		}
		}
	}
	return;
}


/*
 * This code written by Rahl (dwa1844@rit.edu) for Broken Shadows.
 *
 * Permission to use this code is given freely as long as my
 * name stays with it.
 * - Daniel Anderson
 */
/* This was originally a new "log_string" function by Rahl. 
   I changed the name of the file it records and added printf-like stuff. 
   -Kyle */
void clan_log( CLAN_DATA *clan, char *str, ... )
{
    char *strtime;
    char logfile[20];
    char buf[10];
    char temp[20];
    int i, j;
    FILE *log_file;
    FILE *tempfile;
    char param[4*MAX_STRING_LENGTH];

/* Thanks to Tyrluk of MornMUD for showing me how to do this... -Kyle */
    {
       va_list args;

       va_start (args, str);
       vsprintf (param, str, args);
       va_end (args);
    }


    buf[0] = '\0';
    temp[0] = '\0';

    log_file = NULL;

    sprintf( buf, "%s", get_curdate() );
    for ( i = 0; i < 10; i++ )
    {
        if ( buf[i] == '/' )
            buf[i] = '-';
    }

/* The log for clan #1 will look like: 
   ../clan/1.01-31-99
   This log will be accesable to clan leaders. -Kyle */

    sprintf( temp, "%s/%d.", sysconfig.clan_dir, clan->number );
    strcat( temp, buf );

    if ( strcmp( temp, logfile ) )
    {
        tempfile = fopen( temp, "a" );
        if ( log_file != NULL )
            fclose( log_file );
        for ( j = 0; j < 20; j++ )
            logfile[j] = temp[j];
        log_file = fopen( logfile, "a" );
        if ( tempfile != NULL ) fclose( tempfile );

    }

    strtime = ctime( &current_time );
    strtime[strlen(strtime)-1] = '\0';
    fprintf( log_file, "%s:%s\n", &strtime[10], param );
    fclose( log_file );
    return;
}

CLAN_DATA *get_clan( int clannum )
{
	CLAN_DATA *clan;

	if( top_clan == 0 )
		return NULL;

	for( clan = clan_first; clan != NULL; clan = clan->next )
	{
		if( clan->number == clannum )
			return clan;
	}

	return NULL;
}

CLAN_DATA *new_clan( void )
{
	CLAN_DATA *clan;
	int i;

	clan = alloc_perm( sizeof(CLAN_DATA) );
	if( clan == NULL )
	{
		bug("Could not create clan.", 0);
		return NULL;
	}
	if( clan_first == NULL )
		top_clan=0;
	top_clan++;

	clan->next = NULL;
	clan->number = top_clan;
	clan->name = str_dup( "Unnamed" );
	clan->leader = str_dup( "None" );
	clan->god = str_dup( "None" );
	clan->max_members = MAX_CLAN_MEMBERS;
	clan->min_level = MIN_CLAN_LEVEL;
	clan->recall_room = ROOM_VNUM_TEMPLE;
	clan->whoname = str_dup( "" );
	clan->command = str_dup( "" );
	clan->skill   = str_dup( "" );
	for( i=0; i < MAX_RANK ; i++ )
		clan->rank[i]=str_dup( "" );
	for( i=0; i < MAX_CLAN_MEMBERS ; i++ )
		clan->members[i]=str_dup( "" );

	if( clan_first == NULL )
	{
		clan_first = clan;
		clan_last = clan;
		return clan;
	}

	if( clan_last == NULL )
	{
		bug("clan_first but no clan_last.", 0);
		clan_last = clan;
		return clan;
	}

	clan_last->next = clan;
	clan_last = clan;

	return clan;
}

void do_cedit( CHAR_DATA *ch, char *argument )
{
    char arg[MAX_INPUT_LENGTH];
    CLAN_DATA *clan;
    int value;

    if ( IS_NPC(ch) ) return;

    argument = one_argument( argument, arg );

    if ( is_number( arg ) )
    {
        value = atoi( arg );
        
        if ( !( clan = get_clan( value ) ) )
        {
            send_to_char( "CEdit:  That clan does not exist.\n\r", ch );
            return;
        }

        ch->desc->pEdit = (void *)clan;
        ch->desc->editor = ED_CLAN;
        return;
    }
    else
    {
        if ( !str_cmp( arg, "create" ) )
        {
            if ( cedit_create( ch, argument ) )
            {
                ch->desc->editor = ED_CLAN;
            }
            return;
        }
    }

    send_to_char( "CEdit:  There is no default clan to edit.\n\r", ch );
    return;
}


void cedit( CHAR_DATA *ch, char *argument )
{
    char arg[MAX_INPUT_LENGTH];
    CLAN_DATA *clan;
    char command[MAX_INPUT_LENGTH];
    int  cmd;

    smash_tilde( argument );
    strcpy( arg, argument );
    argument = one_argument( argument, command );
    EDIT_CLAN(ch, clan);

    if ( !str_cmp(command, "done") )
    {
	edit_done( ch );
	return;
    }

	/* Change this depending on who you want to be able to edit clans. */
    if ( get_trust(ch) < (MAX_LEVEL - 1) )
    {
        send_to_char( "CEdit: Insufficient security to modify clans.\n\r", ch );
        interpret(ch, arg);
        return;
    }

    if ( command[0] == '\0' )
    {
        cedit_show( ch, argument );
        return;
    }
	if( clan == NULL )
	{
		send_to_char("You are not currently editing a clan.", ch);
		interpret(ch, arg);
		return;
	}
    /* Search Table and Dispatch Command. */
    for ( cmd = 0; cedit_table[cmd].name[0] != '\0'; cmd++ )
    {
        if ( !str_prefix( command, cedit_table[cmd].name ) )
        {
            if ( (*cedit_table[cmd].olc_fun) ( ch, argument ) )
            {
                return;
            }
            else
            return;
        }
    }

    /* Default to Standard Interpreter. */
    interpret( ch, arg );
    return;
}

CEDIT( cedit_show )
{
	CLAN_DATA *clan;
	int i;

	EDIT_CLAN( ch, clan );

	if( clan == NULL )
	{
		send_to_char("You are not currently editing a clan.", ch);
		return FALSE;
	}

	printf_to_char( ch, "Name:     [%s]\n\rNumber:   [%2d]\n\rLeader:   [%12s]\n\rSponsor:  [%12s]\n\r",
		clan->name,
		clan->number,
		clan->leader,
		clan->god );

	printf_to_char( ch, "Whoname: [%s]\n\rMaximum members: %d\n\rMinimum level: %d\n\r",
		clan->whoname,
		clan->max_members,
		clan->min_level );

	printf_to_char( ch, "Clan recall: %d\n\rCost to join: %d\n\r", clan->recall_room, clan->cost_gold );

	for( i = 0; i < MAX_RANK ; i++ )
	{
		printf_to_char( ch, "Rank %d:[%30s]\n\r", i+1, clan->rank[i][0]=='\0' ? "None" : clan->rank[i] );
	}
/*
	printf_to_char( ch, "Command: [%s]\n\rSkill:   [%s]\n\r", clan->command, clan->skill );
*/
	printf_to_char( ch, "Clan flags: [%s]\n\r", flag_string( clan_flags, clan->clan_flags ));
 	printf_to_char( ch, "Join flags: [%s]\n\r", flag_string( clan_join_flags, clan->join_flags ) );

	return FALSE;
}

CEDIT( cedit_create )
{
	CLAN_DATA *clan;

	if( top_clan >= MAX_CLAN )
	{
		send_to_char("Limit on clans has been reached.\n\r", ch );
		return FALSE;
	}

	clan = new_clan();
	if( clan == NULL )
	{
		send_to_char("ERROR! Could not create clan!\n\r", ch );
		return FALSE;
	}
	SET_BIT( clan->clan_flags, CLAN_CREATING );
	send_to_char("Clan created.\n\r", ch);
	clan_log(clan, "Clan created today!");
	ch->desc->pEdit = (void *) clan;
	return TRUE;
}

CEDIT( cedit_name )
{
	CLAN_DATA * clan;

	EDIT_CLAN(ch, clan);

	if( argument[0]=='\0' )
	{
		send_to_char("Syntax:  name <clan name>\n\r", ch);
		return FALSE;
	}

	if( strlen(argument) != str_len(argument) ) /* Check for color codes in the name */
	{
		send_to_char("You may not use color codes in the clan name.\n\r", ch);
		return FALSE;
	}

    if (strlen(argument) > 20)
    {
        send_to_char("Clan names must be 20 characters or less.\n\r", ch);
        return FALSE;
    }

	free_string( &clan->name );
	clan->name = str_dup( argument );
	send_to_char("Clan name set.\n\r", ch);
	return TRUE;
}

CEDIT( cedit_whoname )
{
	CLAN_DATA * clan;

	EDIT_CLAN(ch, clan);

	if( argument[0]=='\0' )
	{
		send_to_char("Syntax:  whoname <string>\n\r", ch);
		return FALSE;
	}

    if (str_len(argument) > 20)
    {
        send_to_char("Clan whonames must be 20 characters or less.\n\r", ch);
        return FALSE;
    }

	free_string( &clan->whoname );
	clan->whoname = str_dup( argument );
	send_to_char("Name visible on the \"who\" listing has been set.\n\r", ch);
	return TRUE;
}

CEDIT( cedit_rank )
{
	CLAN_DATA *clan;
	int i;
	char arg1[MAX_INPUT_LENGTH];
	EDIT_CLAN(ch, clan);

	if( argument[0]=='\0' )
	{
		send_to_char("Syntax:  rank <#> <title>\n\r",ch);
		return FALSE;
	}

	argument=one_argument( argument, arg1 );

	if( !is_number( arg1 ) )
	{
		send_to_char("Syntax:  rank <#> <title>\n\r",ch);
		return FALSE;
	}

	i = atoi( arg1 );
	if( i < 1 || i > MAX_RANK )
	{
		printf_to_char( ch, "Allowable rank numbers are 1 through %d.\n\r", MAX_RANK);
		return FALSE;
	}

	if (str_len(argument) > 40)
    {
        send_to_char( "Rank titles must be 40 characters or shorter.\n\r", ch );
        return FALSE;
    }

	free_string( &clan->rank[i-1] );
	clan->rank[i-1]=str_dup( argument );
	send_to_char("Rank set.\n\r", ch);
	return TRUE;
}

CEDIT( cedit_cost )
{
	CLAN_DATA *clan;
	int i;

	EDIT_CLAN(ch, clan);

	if( argument[0]=='\0' || !is_number( argument ) )
	{
		send_to_char("Syntax: cost <cost in gold>\n\r", ch);
		return FALSE;
	}

	i = atoi(argument);
	if( i < 0 || i > 100000000 ) /* I think 100 million should be about the limit for cost... */
	{
		send_to_char("Illegal cost.\n\r", ch);
		return FALSE;
	}

	clan->cost_gold = i;
	send_to_char("Cost to join set.\n\r", ch);
	return TRUE;
}

CEDIT( cedit_members )
{
	CLAN_DATA *clan;
	int i;

	EDIT_CLAN(ch, clan);

	if( argument[0]=='\0' || !is_number( argument ) )
	{
		send_to_char("Syntax: members <max members>\n\r", ch);
		return FALSE;
	}

	i = atoi(argument);
	if( i < 1 || i > MAX_CLAN_MEMBERS ) 
	{
		send_to_char("That number of members is not allowed.\n\r", ch);
		return FALSE;
	}

	clan->max_members = i;
	send_to_char("Max members set.\n\r", ch);
	return TRUE;
}

CEDIT( cedit_minlevel )
{
	CLAN_DATA *clan;
	char buff[MAX_STRING_LENGTH];
	int i;

	EDIT_CLAN(ch, clan);

	if( argument[0]=='\0' || !is_number( argument ) )
	{
		send_to_char("Syntax: minlevel <level>\n\r", ch);
		return FALSE;
	}

	i = atoi(argument);
	if( i < 1 || i > MAX_LEVEL )
	{
		sprintf(buff, "Range is 1 to %d.\n\r", MAX_LEVEL);
		send_to_char(buff, ch);
		return FALSE;
	}

	clan->min_level = i;
	send_to_char("Minimum level to join set.\n\r", ch);
	return TRUE;
}

CEDIT( cedit_recall )
{
	CLAN_DATA *clan;
	int room;

	EDIT_CLAN(ch, clan);

	if( argument[0]=='\0' || !is_number( argument ) )
	{
		send_to_char("Syntax: recall <room vnum>\n\r", ch);
		return FALSE;
	}

	room = atoi(argument);
	if ( room < 0 || room > 32767 )
	{
		send_to_char("Illegal room number.\n\r", ch);
		return FALSE;
	}

	if ( get_room_index( room ) == NULL )
	{
		send_to_char("That room does not exist.\n\r", ch);
		return FALSE;
	}

	clan->recall_room = room;
	send_to_char("Clan recall room set.\n\r", ch);
	return TRUE;
}

CEDIT( cedit_leader )
{
	CLAN_DATA *clan;
	FILE *fp;
	char buf[MAX_INPUT_LENGTH];

	EDIT_CLAN(ch, clan);

	   
	if (argument[0] == '\0' )
	{
		send_to_char("You must supply an argument.\n\r", ch);
		return FALSE;
	}
#if defined(unix)
    /* decompress if .gz file exists */
    sprintf( buf, "%s/%s%s", sysconfig.player_dir, capitalize(argument),".gz");
    if ( ( fp = fopen( buf, "r" ) ) != NULL )
    {
	char buf1[MAX_INPUT_LENGTH];
	fclose(fp);
	sprintf(buf1,"gzip -dfq %s",buf);
	system(buf1);
    }
#endif
	sprintf(buf, "%s/%s", sysconfig.player_dir, capitalize(argument) );
	if ( (fp = fopen( buf, "r" ) ) != NULL )
	{
		printf_to_char(ch , "%s is now the the leader of %s.\n\r", capitalize(argument), clan->name);
		clan->leader = str_dup(capitalize(argument));
		fclose(fp);
		return TRUE;
	}
	send_to_char("That character is not a player on this mud.\n\r", ch);
	if (fp!=NULL) fclose(fp);
	return FALSE;
}

CEDIT( cedit_sponsor )
{
	CLAN_DATA *clan;
	char buf[MAX_INPUT_LENGTH];
	FILE *fp;
	   
	EDIT_CLAN(ch, clan);

	if (argument[0] == '\0' )
	{
		send_to_char("You must supply an argument.\n\r", ch);
		return FALSE;
	}
	sprintf(buf, "%s/%s", sysconfig.god_dir, capitalize(argument) );
	if ( (fp = fopen( buf, "r" ) ) != NULL )
	{
		printf_to_char( ch, "%s is now the god sponsor for %s.\n\r", capitalize(argument), clan->name);
		clan->god = str_dup(capitalize(argument));
		fclose(fp);
		return TRUE;
	}
	send_to_char("That player is not a god on this mud.\n\r", ch);
	if (fp!=NULL) fclose(fp);
	return FALSE;
}

CEDIT( cedit_joinflags )
{
	CLAN_DATA *clan;
	int value;
	EDIT_CLAN(ch, clan);

	if ( argument[0] != '\0' )
	{
		if ( ( value = flag_value( clan_join_flags, argument ) ) != NO_FLAG )
		{
			if( value == CLAN_NO_PK && IS_SET( clan->join_flags, CLAN_REQ_PK ) )
			{
				clan->join_flags ^= CLAN_REQ_PK;
			}
			else if( value == CLAN_REQ_PK && IS_SET( clan->join_flags, CLAN_NO_PK ) )
			{
				clan->join_flags ^= CLAN_NO_PK;
			}
			clan->join_flags ^= value;
			send_to_char( "Join flag toggled.\n\r", ch);
			return TRUE;
		}
	}
	send_to_char( "Syntax:  joinflags [flag]\n\r"
	"Type '? joinflags' for a list of flags.\n\r", ch );
	return FALSE;
}

CEDIT( cedit_clanflags )
{
	CLAN_DATA *clan;
	int value;
	EDIT_CLAN(ch, clan);

	if ( argument[0] != '\0' )
	{
		if ( ( value = flag_value( clan_flags, argument ) ) != NO_FLAG )
		{
		clan->clan_flags ^= value;
		send_to_char( "Clan flag toggled.\n\r", ch);
		return TRUE;
		}
	}
	send_to_char( "Syntax:  clanflags <auto-accept/private/secret>\n\r", ch );
	return FALSE;
}


bool can_ch_join( CHAR_DATA *ch, CLAN_DATA *clan, bool is_petitioning )
{
	if( ch->level < clan->min_level )
	{
		printf_to_char(ch, "You must be level %d to join this clan.\n\r", clan->min_level);
		return FALSE;
	}

	if( ( IS_SET( clan->join_flags, CLAN_ANTI_MAGE) && ch->Class == CLASS_MAGE )
	|| ( IS_SET( clan->join_flags, CLAN_ANTI_CLERIC) && ch->Class == CLASS_CLERIC )
	|| ( IS_SET( clan->join_flags, CLAN_ANTI_WARRIOR) && ch->Class == CLASS_WARRIOR )
	|| ( IS_SET( clan->join_flags, CLAN_ANTI_THIEF) && ch->Class == CLASS_THIEF ) )
	{
		send_to_char("This clan does not allow your class to join.\n\r", ch);
		return FALSE;
	}

	if( IS_SET( clan->join_flags, CLAN_REQ_PK ) && !IS_SET( ch->act, PLR_KILLER ) )
	{
		send_to_char("You must be a player killer to join this clan.\n\r", ch);
		send_to_char("Type PK twice to become a player killer.\n\r", ch);
		return FALSE;
	}

	if( IS_SET( clan->join_flags, CLAN_NO_PK ) && IS_SET( ch->act, PLR_KILLER ) )
	{
		send_to_char("You may not be a player killer and join this clan.\n\r", ch);
		send_to_char("Ask a high level god to remove your killer flag if you still wish to join.\n\r", ch);
		return FALSE;
	}

	if( IS_SET( clan->join_flags, CLAN_ANTI_EVIL ) && IS_EVIL( ch ) )
	{
		send_to_char("Evil-aligned players may not join this clan.\n\r", ch);
		return FALSE;
	}

	if( IS_SET( clan->join_flags, CLAN_ANTI_GOOD ) && IS_GOOD( ch ) )
	{
		send_to_char("Good-aligned players may not join this clan.\n\r", ch);
		return FALSE;
	}

	if( !IS_SET( clan->clan_flags, CLAN_AUTO_ACCEPT ) && !is_petitioning )
	{
		send_to_char("This clan does not auto-accept new members.\n\r", ch);
		send_to_char("Use the PETITION command on one of its members.\n\r", ch);
		return FALSE;
	}

	return TRUE;
}

void add_member(CHAR_DATA *ch, CLAN_DATA *clan)
{
	int i;

	for( i=0; i < clan->max_members; i++ )
	{
		if( clan->members[i][0]=='\0' )
		{
			free_string(&clan->members[i]);
			clan->members[i]=str_dup(ch->name);
			clan->num_members++;
			clan_log( clan, "New member: %s", ch->name );
			save_clans();
			do_save(ch,"");
			return;
		}
	}
	bug("Add_member: No spots in clan %d!", clan->number);
	return;
}

void remove_member(CHAR_DATA *ch, CLAN_DATA *clan)
{
	int i;

	for( i=0; i < clan->max_members; i++ )
	{
		if( !str_cmp(clan->members[i], ch->name ) )
		{
			free_string(&clan->members[i]);
			clan->members[i]=str_dup("");
			clan->num_members--;
			clan_log( clan, "Removed from clan: %s", ch->name );
			save_clans();
			do_save(ch,"");
			return;
		}
	}
	bug("Add_member: Name not found in clan %d!", clan->number);
	return;
}

void do_show(CHAR_DATA *ch, char *argument)
{
	CLAN_DATA *clan;
	char arg1[MAX_INPUT_LENGTH];
	int num=0;
	bool found=FALSE;

	argument = one_argument( argument, arg1 );

	if( clan_first == NULL )
	{
		send_to_char("There are no clans at all yet.\n\r", ch);
		return;
	}

	if( !str_cmp( arg1, "active" ) )
	{
		found = FALSE;
		send_to_char("Clans actively recruiting:\n\r", ch);
		send_to_char("===============================\n\r", ch);
		for( clan=clan_first; clan!=NULL; clan=clan->next )
		{
			if( IS_SET(clan->clan_flags, CLAN_ACTIVE) && ( !IS_SET(clan->clan_flags, CLAN_SECRET)
            || IS_IMMORTAL(ch) ) && clan->num_members < MAX_CLAN_MEMBERS )
			{
				num++;
				printf_to_char(ch, "[%3d] %s\n\r", num, clan->name);
				found = TRUE;
			}
		}
		if( found == FALSE )
		{
			send_to_char("No clans are publicly recruiting.\n\r", ch);
		}
		return;
	}

	if( !str_cmp( arg1, "inactive" ) )
	{
		found = FALSE;
		send_to_char("Clans not actively recruiting:\n\r", ch);
		send_to_char("===============================\n\r", ch);
		for( clan=clan_first; clan!=NULL; clan=clan->next )
		{
			if( (IS_SET(clan->clan_flags, CLAN_INACTIVE) && ( !IS_SET(clan->clan_flags, CLAN_SECRET) 
            || IS_IMMORTAL(ch) ) ) || ((IS_SET(clan->clan_flags, CLAN_ACTIVE) && !IS_SET(clan->clan_flags, CLAN_SECRET)
			&& clan->num_members >= MAX_CLAN_MEMBERS )) )
			{
				num++;
				printf_to_char(ch, "[%3d] %s\n\r", num, clan->name);
				found = TRUE;
			}
		}
		if( found == FALSE )
		{
			send_to_char("No clans are inactive at this time.\n\r", ch);
		}
		return;
	}

	if( !str_cmp( arg1, "all" ) )
	{
		found = FALSE;
		send_to_char("Current existing clans:\n\r", ch);
		send_to_char("===============================\n\r", ch);
		for( clan=clan_first; clan!=NULL; clan=clan->next )
		{
			if ( ( !IS_SET( clan->clan_flags, CLAN_SECRET ) 
                   && ( IS_SET( clan->clan_flags, CLAN_ACTIVE )
                        || IS_SET( clan->clan_flags, CLAN_INACTIVE )
                      )
                 )
                 || IS_IMMORTAL(ch)
               )
			{
				num++;
				printf_to_char(ch, "[%3d] %s\n\r", num, clan->name);
				found = TRUE;
			}
		}
		if( found == FALSE )
		{
			send_to_char("None.\n\r", ch);
		}
		return;
	}

	if( !str_cmp( arg1, "members" ) )
	{
		if( IS_NPC(ch) ) return;
		if( ch->pcdata->clan > 0 )
		{
		clan = get_clan( ch->pcdata->clan );
		printf_to_char(ch, "Sponsor: %s\n\rLeader: %s\n\r", clan->god, clan->leader);
		send_to_char("Members:\n\r", ch);
		for( num = 0; num < MAX_CLAN_MEMBERS; num++)
		{
		printf_to_char(ch, "%s ", clan->members[num]);
		if( num != 0 && num % 5 == 0 ) send_to_char("\n\r", ch);
		}
		send_to_char("\n\r", ch);
		}
		return;
	}
	if( IS_NPC(ch) ) return;

	if( ch->pcdata->clan == 0 )
	{
	send_to_char("Syntax: show <active/inactive/all>\n\r", ch);
	return;
	}

	send_to_char("Syntax: show <active/inactive/all/members>\n\r", ch);

	return;
}

void do_join(CHAR_DATA *ch, char *argument)
{
	CLAN_DATA *clan;
	int num, i=0;
	char arg1[MAX_INPUT_LENGTH];

	if( IS_NPC(ch) )
	{
		send_to_char("Are you nuts? NPC's may not join clans!\n\r", ch);
		return;
	}

	if( ch->pcdata == NULL )
		return;

	if( ch->pcdata->clan != 0 )
	{
		send_to_char("You are already a member of a clan!  Duh!\n\r", ch);
		return;
	}

	if( argument[0]=='\0' && ch->pcdata->join_status != JOIN_START )
	{
		send_to_char("Syntax: join <clan number, 0 to cancel>\n\r", ch);
		return;
	}

	argument = one_argument( argument, arg1 );

	switch( ch->pcdata->join_status )
	{
	case JOIN_START:
		send_to_char("This is a list of actively recruiting clans.\n\r", ch);
		do_show(ch, "active");
		send_to_char("\n\rTo see this list again, type 'show active'.\n\r", ch);
		send_to_char("To join a clan, type JOIN followed by the number of the clan.\n\r", ch);
		ch->pcdata->join_status = JOIN_SEE_LIST;
		return;
	case JOIN_SEE_LIST:
		if( !is_number( arg1 ) )
		{
			send_to_char("You must join a clan by using its number.\n\r", ch);
			return;
		}
		num = atoi( arg1 );
		
		if( num == 0 )
		{
			send_to_char("Cancelling your joining of a clan.\n\r", ch);
			ch->pcdata->join_status = JOIN_START;
			return;
		}

		for( clan=clan_first; clan!=NULL; clan=clan->next )
		{
			if( IS_SET(clan->clan_flags, CLAN_ACTIVE) && !IS_SET(clan->clan_flags, CLAN_SECRET)
			&& clan->num_members < MAX_CLAN_MEMBERS )
			{
				i++;
				if( num == i )
				{
					printf_to_char(ch, "You are attempting to join clan #%d, %s.\n\r", num, clan->name );
					if( can_ch_join( ch, clan, FALSE ) == FALSE )
						return;
					send_to_char("You are eligable to join.\n\r", ch);
if( clan->cost_gold > 0 )
{
	printf_to_char(ch, "This clan costs %d gold to join.\n\r", clan->cost_gold);
	if( ch->gold < clan->cost_gold )
	{
		send_to_char("You cannot afford to join!\n\r", ch);
		return;
	}
}
					printf_to_char(ch, "To confirm, please type JOIN %d\n\r", num);
					send_to_char("Type JOIN 0 to cancel this choice.\n\r", ch);
					ch->pcdata->join_status = JOIN_CONFIRM;
					ch->pcdata->join_clan = num;
					return;
				}
			}
		}
		send_to_char("That clan does not exist.\n\r", ch);
		return;
	case JOIN_CONFIRM:
		if( !is_number( arg1 ) )
		{
			send_to_char("You must join a clan by using its number.\n\r", ch);
			return;
		}
		num = atoi( arg1 );

		if( num == 0 )
		{
			send_to_char("Your selection of a clan has been canceled.\n\r", ch);
			ch->pcdata->join_status = JOIN_START;
			ch->pcdata->join_clan = 0;
			return;
		}

		if( num != ch->pcdata->join_clan )
		{
			send_to_char("Your clan selections do not match.\n\r", ch);
			printf_to_char(ch, "Type JOIN 0 to cancel or JOIN %d to confirm.\n\r", 
ch->pcdata->join_clan );
		}

		for( clan=clan_first; clan!=NULL; clan=clan->next )
		{
			if( IS_SET(clan->clan_flags, CLAN_ACTIVE) && !IS_SET(clan->clan_flags, CLAN_SECRET)
			&& clan->num_members < MAX_CLAN_MEMBERS )
			{
				i++;
				if( num == i )
				{
if( clan->cost_gold > 0 )
{
	printf_to_char(ch, "This clan costs %d gold to join.\n\r", clan->cost_gold);
	if( clan->cost_gold > ch->gold )
	{
		send_to_char("You cannot afford this clan!\n\r", ch);
		do_join(ch, "0");
		return;
	}
	ch->gold -= clan->cost_gold;
	clan->clan_fund += clan->cost_gold;
	printf_to_char(ch, "You now have %d gold left.\n\r", ch->gold);
}
					printf_to_char(ch, "You are now a member of clan #%d, %s!\n\r", i, clan->name);
					ch->pcdata->clan = clan->number;
					ch->pcdata->join_status = JOIN_START;
					add_member( ch, clan );
					ch->pcdata->clan_rank = MAX_RANK;
					return;
				}
			}
		}
	case JOIN_PETITIONING:
		send_to_char("You are currently petitioning to join a clan.\n\r", ch);
		send_to_char("If you are refused, then you may use the JOIN command again.\n\r", ch);
		return;
	case JOIN_DECIDING:
		send_to_char("You have already been invited to join a clan.\n\r", ch);
		send_to_char("Use the ACCEPT or DECLINE commands to join or not.\n\r", ch);
		return;
	case JOIN_CONSIDERING:
	case JOIN_OFFERING:
		send_to_char("Doh, a bug.  Ignore this.\n\r", ch);
		bug("Ch without clan in JOIN_CONSIDERING or JOIN_OFFERING", 0);
		ch->pcdata->join_status = JOIN_START;
		return;
	default:
		send_to_char("Doh, a bug.  Ignore this.\n\r", ch);
		bug("Unknown join_status %d!", ch->pcdata->join_status );
		ch->pcdata->join_status = JOIN_START;
		return;
	}
	return;
}

void do_petition(CHAR_DATA *ch, char *argument)
{
	char arg1[MAX_INPUT_LENGTH];
	CLAN_DATA *clan;
	CHAR_DATA *victim;

	if( IS_NPC(ch) )
		return;

	if( ch->pcdata == NULL )
		return;

	if( ch->pcdata->clan != 0 )
	{
		send_to_char("You are already a member of a clan!\n\r", ch);
		return;
	}

	if( ch->pcdata->join_status == JOIN_PETITIONING )
	{
		send_to_char("You are already petitioning to join a clan!\n\r", ch);
		return;
	}

	if( ch->pcdata->join_status == JOIN_DECIDING )
	{
		send_to_char("You have already been offered membership in a clan!\n\r", ch);
		send_to_char("Type ACCEPT or DECLINE.\n\r", ch);
	}

	if( argument[0]=='\0' )
	{
		send_to_char("Petition who?\n\r", ch);
		return;
	}

	argument = one_argument( argument, arg1 );

	victim = get_char_world( ch, arg1 );
	if( victim == NULL )
	{
		send_to_char("Petition who?\n\r", ch);
		return;
	}

	if( IS_NPC( victim ) )
	{
		send_to_char("Only players can be petitioned!\n\r", ch);
		return;
	}

	if( victim->pcdata == NULL )
		return;

	if( victim->pcdata->clan == 0 )
	{
		send_to_char("That person is not a member of a clan.\n\r", ch);
		return;
	}

	if( victim->pcdata->clan_ch != ch && victim->pcdata->clan_ch != NULL )
	{
		send_to_char("That person is currently being petitioned by someone else.\n\r", ch);
		return;
	}

	if( victim->pcdata->clan_ch == ch )
	{
		send_to_char("You are already petitioning them!  Be patient!\n\r", ch);
		return;
	}

	clan = get_clan( victim->pcdata->clan );

	if( clan == NULL )
	{
		bug("NULL clan %d", victim->pcdata->clan );
		return;
	}

	if( IS_SET(clan->clan_flags, CLAN_SECRET) )
	{
		send_to_char("That person is not a member of a clan.\n\r", ch);
		return;
	}

	if( victim->pcdata->clan_rank > RANK_CAN_ACCEPT || victim->pcdata->clan_rank < 1 )
	{
		send_to_char("That person is not of sufficient rank to accept you.\n\r", ch);
		return;
	}

	if( can_ch_join( ch, clan, TRUE ) == FALSE )
		return;
	if( clan->cost_gold > 0 )
	{
		printf_to_char(ch, "It costs %d gold to join.\n\r",clan->cost_gold);
		if( clan->cost_gold > ch->gold )
		{
		send_to_char("You cannot afford it!\n\r", ch);
		return;
		}
	}
	clan_log(clan,"%s petitions %s to join.", ch->name, victim->name);
	printf_to_char(victim, "%s has petitioned to join your clan!\n\r", ch->name);
	send_to_char("Type ACCEPT or DECLINE, or talk to them for a while.\n\r", victim);
	send_to_char("Petition sent!\n\r", ch);

	ch->pcdata->join_status = JOIN_PETITIONING;
	victim->pcdata->join_status = JOIN_CONSIDERING;
	ch->pcdata->clan_ch = victim;
	victim->pcdata->clan_ch = ch;
	return;
}

void do_accept(CHAR_DATA *ch, char *argument)
{
	CLAN_DATA *clan;

	if( IS_NPC(ch) )
		return;
	if( ch->pcdata == NULL )
		return;

	if( ch->pcdata->join_status != JOIN_DECIDING && ch->pcdata->join_status != JOIN_CONSIDERING )
	{
		send_to_char("What, exactly, are you trying to accept?\n\r", ch);
		return;
	}

	if( ch->pcdata->join_status == JOIN_CONSIDERING )
	{
		clan = get_clan( ch->pcdata->clan );
if( clan->cost_gold > ch->pcdata->clan_ch->gold )
{
	send_to_char("They can no longer afford to join.\n\r",ch);
	send_to_char("Use DECLINE to refuse, or wait come more.\n\r", ch);
	return;
}
		clan_log(clan, "Petition accepted by %s", ch->name);
		printf_to_char(ch, "You accept %s into clan %s!\n\r", ch->pcdata->clan_ch->name, clan->name );
		printf_to_char(ch->pcdata->clan_ch, "You have been accepted into clan %s!\n\r", clan->name);
		ch->pcdata->clan_ch->gold -= clan->cost_gold;
		clan->clan_fund += clan->cost_gold;
		ch->pcdata->clan_ch->pcdata->clan = clan->number;
		ch->pcdata->clan_ch->pcdata->clan_rank = MAX_RANK;
		ch->pcdata->clan_ch->pcdata->join_status = JOIN_START;
		ch->pcdata->clan_ch->pcdata->clan_ch = NULL;
		ch->pcdata->clan_ch->pcdata->join_clan = 0;
		add_member( ch->pcdata->clan_ch, clan );
		ch->pcdata->clan_ch = NULL;
		ch->pcdata->join_status = JOIN_START;
		return;
	}

	clan = get_clan( ch->pcdata->clan_ch->pcdata->clan );
if( ch->gold < clan->cost_gold )
{
	send_to_char("You cannot afford to join that clan!\n\r", ch);
	send_to_char("Use DECLINE to turn them down or go get more gold fast.\n\r",ch);
	return;
}
	clan_log(clan, "%s accepts membership.", ch->name);
	printf_to_char(ch, "You accept membership in clan %s!\n\r", clan->name);
	printf_to_char(ch->pcdata->clan_ch, "%s has accepted membership in your clan!\n\r", ch->name);
	ch->gold -= clan->cost_gold;
	clan->clan_fund += clan->cost_gold;
	ch->pcdata->clan = clan->number;
	ch->pcdata->clan_rank = MAX_RANK;
	ch->pcdata->join_status = JOIN_START;
	add_member( ch, clan );
	ch->pcdata->clan_ch->pcdata->clan_ch = NULL;
	ch->pcdata->clan_ch->pcdata->join_status = JOIN_START;
	ch->pcdata->clan_ch = NULL;
	return;
}





void do_decline(CHAR_DATA *ch, char *argument)
{
	CLAN_DATA *clan;

	if( IS_NPC(ch) )
		return;
	if( ch->pcdata == NULL )
		return;

	if( ch->pcdata->join_status != JOIN_DECIDING && ch->pcdata->join_status != JOIN_CONSIDERING )
	{
		send_to_char("What, exactly, are you trying to decline?\n\r", ch);
		return;
	}

	if( ch->pcdata->join_status == JOIN_CONSIDERING )
	{
		clan = get_clan( ch->pcdata->clan );
		clan_log(clan, "%s declines the petition.", ch->name);
		printf_to_char(ch, "You decline to accept %s into clan %s.\n\r", ch->pcdata->clan_ch->name, clan->name );
		printf_to_char(ch->pcdata->clan_ch, "You have been denied membership into clan %s.\n\r", clan->name);
		ch->pcdata->clan_ch->pcdata->join_status = JOIN_START;
		ch->pcdata->clan_ch->pcdata->clan_ch = NULL;
		ch->pcdata->clan_ch = NULL;
		ch->pcdata->join_status = JOIN_START;
		return;
	}

	clan = get_clan( ch->pcdata->clan_ch->pcdata->clan );
	clan_log(clan, "%s declines to join.", ch->name);
	printf_to_char(ch, "You decline membership in clan %s.\n\r", clan->name);
	printf_to_char(ch->pcdata->clan_ch, "%s has declined membership in your clan.\n\r", ch->name);
	ch->pcdata->clan_ch->pcdata->join_status = JOIN_START;
	ch->pcdata->clan_ch->pcdata->clan_ch = NULL;
	ch->pcdata->clan_ch = NULL;
	ch->pcdata->join_status = JOIN_START;
	return;
}

void do_offer(CHAR_DATA *ch, char *argument)
{
	CLAN_DATA *clan;
	CHAR_DATA *victim;

	if( IS_NPC( ch ) || ch->pcdata == NULL )
		return;

	if( ch->pcdata->clan == 0 )
	{
		send_to_char("You can't offer membership in a clan if you are clanless!\n\r", ch);
		return;
	}

	victim = get_char_world( ch, argument );

	if( victim == NULL )
	{
		send_to_char("Offer membership to who?\n\r", ch);
		return;
	}

	if( IS_NPC(victim) || victim->pcdata == NULL )
	{
		send_to_char("You cannot offer membership to NPC's.\n\r", ch);
		return;
	}

	if( ch->pcdata->join_status != 0 && ch->pcdata->clan_ch != NULL )
	{
		printf_to_char(ch, "You are currently being petitioned by or offering membership to %s.\n\r",
		ch->pcdata->clan_ch->name);
		return;
	}

	clan = get_clan( ch->pcdata->clan );

	if( ch->pcdata->clan_rank < 1 || ch->pcdata->clan_rank > RANK_CAN_ACCEPT )
	{
		send_to_char("You are not of high enough rank to offer membership to anyone.\n\r", ch);
		return;
	}

	if( victim->pcdata->join_status > JOIN_SEE_LIST )
	{
		send_to_char("That player is considering membership in another clan.\n\r", ch);
		send_to_char("Better make them change their mind, fast! :)\n\r", ch);
		return;
	}

	/* The reason the "That person is ineligable to join your clan." message is 
	   everywhere is to preserve the secretness of the secret clans. */

	if( victim->pcdata->clan != 0 )
	{
		CLAN_DATA *tmpclan;
		tmpclan = get_clan( victim->pcdata->clan );
		if( IS_SET( tmpclan->clan_flags, CLAN_SECRET ) )
			send_to_char("That person is ineligable to join your clan.\n\r", ch);
		else
			send_to_char("That person is already a member of a clan!\n\r", ch);
		return;
	}

	if( victim->level < clan->min_level )
	{
		send_to_char("That person is ineligable to join your clan.\n\r", ch);
		send_to_char("To find out why, they must petition you.\n\r", ch);
		return;
	}

	if( (IS_SET( clan->join_flags, CLAN_ANTI_MAGE) && victim->Class == CLASS_MAGE )
	|| ( IS_SET( clan->join_flags, CLAN_ANTI_CLERIC) && victim->Class == CLASS_CLERIC )
	|| ( IS_SET( clan->join_flags, CLAN_ANTI_WARRIOR) && victim->Class == CLASS_WARRIOR )
	|| ( IS_SET( clan->join_flags, CLAN_ANTI_THIEF) && victim->Class == CLASS_THIEF ) )
	{
		send_to_char("That person is ineligable to join your clan.\n\r", ch);
		return;
	}

	if( IS_SET( clan->join_flags, CLAN_REQ_PK ) && !IS_SET( victim->act, PLR_KILLER ) )
	{
		send_to_char("That person is ineligable to join your clan.\n\r", ch);
		return;
	}

	if( IS_SET( clan->join_flags, CLAN_NO_PK ) && IS_SET( victim->act, PLR_KILLER ) )
	{
		send_to_char("That person is ineligable to join your clan.\n\r", ch);
		return;
	}

	if( IS_SET( clan->join_flags, CLAN_ANTI_EVIL ) && IS_EVIL( victim ) )
	{
		send_to_char("That person is ineligable to join your clan.\n\r", ch);
		return;
	}

	if( IS_SET( clan->join_flags, CLAN_ANTI_GOOD ) && IS_GOOD( victim ) )
	{
		send_to_char("That person is ineligable to join your clan.\n\r", ch);
		return;
	}

	if( victim->gold < clan->cost_gold )
	{
		send_to_char("They cannot afford to join! they are too poor!\n\r",ch);
		return;
	}
	printf_to_char(ch, "You offer %s membership in clan %s.\n\r", victim->name, clan->name);
	printf_to_char(victim, "You have been offered membership in clan %s by %s!\n\r", clan->name, ch->name);
	if( clan->cost_gold > 0 )
		printf_to_char(victim, "It will cost %d gold to join.\n\r", clan->cost_gold);
	clan_log(clan, "Membership offered to %s by %s.", victim->name, ch->name);
	ch->pcdata->clan_ch = victim;
	ch->pcdata->join_status = JOIN_OFFERING;
	victim->pcdata->clan_ch = ch;
	victim->pcdata->join_status = JOIN_DECIDING;
	return;
}

void do_promote(CHAR_DATA *ch, char *argument)
{
	CLAN_DATA *clan;
	CHAR_DATA *victim;
	char buf[MAX_INPUT_LENGTH];

	if( IS_NPC( ch ) )
		return;

	if(ch->pcdata == NULL) return;

	if( argument[0] == '\0' )
	{
		send_to_char("Promote who?\n\r", ch);
		return;
	}

	victim = get_char_world( ch, argument );
	if( victim == NULL )
	{
		send_to_char("Promote who?\n\r", ch);
		return;
	}

	if( IS_NPC(victim) )
	{
		send_to_char("Um, you can't promote mobs.\n\r", ch);
		return;
	}

	if( get_trust( ch ) < MAX_LEVEL ) /* IMPS can promote anyone :) */
	{
	if( ch->pcdata->clan == 0 )
	{
		send_to_char("You are not a member of a clan!\n\r", ch);
		return;
	}

	if( ch->pcdata->clan != victim->pcdata->clan )
	{
		send_to_char("They are not even IN your clan!\n\r", ch);
		return;
	}

	if( victim->pcdata->clan_rank < 1 )
	{
		victim->pcdata->clan_rank=MAX_RANK;
	}

	if( ch->pcdata->clan_rank > 2 )
	{
		send_to_char("You are not high enough rank to promote anyone.\n\r", ch);
		return;
	}

	clan = get_clan( ch->pcdata->clan );

	if( str_cmp( ch->name, clan->leader) ) 
	{
		if( (ch->pcdata->clan_rank == 2 && victim->pcdata->clan_rank < 4 )
		|| ( ch->pcdata->clan_rank == 1 && victim->pcdata->clan_rank < 3 ) )
		{
 			send_to_char("Only the clan leader, an IMP, or a higher rank can promote them.\n\r", ch);
			return;
		}
	}

	}
	else
	{
		clan = get_clan( victim->pcdata->clan );
	}
	if( victim->pcdata->clan_rank < 2 )
	{
		send_to_char("That person's rank is as high as it can be!\n\r", ch );
		return;
	}
	printf_to_char(ch, "You promote %s to %s!\n\r", victim->name, clan->rank[victim->pcdata->clan_rank-2]);
	victim->pcdata->clan_rank--;
	printf_to_char(victim, "%s promotes you to %s in clan %s!\n\r",
		ch->name, clan->rank[victim->pcdata->clan_rank-1], clan->name);
	sprintf(buf, "%s promoted %s in clan %d.", ch->name, victim->name, clan->number );
	log_string( buf );
	clan_log( clan, "%s promoted %s to %s.", ch->name, victim->name, 
		clan->rank[victim->pcdata->clan_rank-1] );
	return;
}

void do_clan(CHAR_DATA *ch, char *argument)
{
	CLAN_DATA *clan;
   const char syntax[] = "Syntax: clan list\n\r        clan snoop\n\r        clan <clan #> view\n\r        clan <clan #> member <add/remove> <member name>\n\r        clan <clan #> bank <deposit/withdraw> <amount>\n\r        clan <clan #> status <creating/active/inactive/disbanding/dead>\n\r";
	char arg1[MAX_INPUT_LENGTH];
	char arg2[MAX_INPUT_LENGTH];
	char arg3[MAX_INPUT_LENGTH];
	int i, active=0, recruit=0, x;

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

   if( arg1[0] == '\0' )
	{
      send_to_char(syntax, ch);
		return;
	}

	if( !str_cmp( arg1, "list" ) )
	{
		if( clan_first == NULL )
		{
			send_to_char("There are no clans.  Use 'edit clan create'.\n\r", ch);
			return;
		}
		send_to_char("`wNumber Name                           Status               Fund\n\r", ch);
		send_to_char("`K====== ============================== ==================== ==========`w\n\r", ch);
		for( clan = clan_first; clan != NULL; clan = clan->next )
		{
			printf_to_char(ch, "%6d %30s %20s %10d\n\r", clan->number, 
			clan->name, flag_string( clan_flags, clan->clan_flags ), clan->clan_fund );
			if( clan->num_members < clan->max_members && IS_SET( clan->clan_flags, CLAN_ACTIVE ) )
				recruit++;
			if( IS_SET( clan->clan_flags, CLAN_ACTIVE ) )
				active++;
		}
		printf_to_char(ch, "Active Clans: %d\n\rRecruiting Clans: %d\n\r", active, recruit);
		return;
	}

	if( !str_cmp( arg1, "snoop") )
	{
		if( IS_SET( ch->comm, COMM_SNOOP_CLAN ) )
		{
			REMOVE_BIT( ch->comm, COMM_SNOOP_CLAN );
			send_to_char("You no longer are snooping the clan channels.\n\r", ch);
			return;
		}
		else
		{
			SET_BIT( ch->comm, COMM_SNOOP_CLAN );
			send_to_char("You are now snooping clans.\n\r", ch);
			return;
		}
		return;
	}

   if (!is_number(arg1))
   {
      send_to_char(syntax, ch);
		return;
   }

   i = atoi( arg1 );

	clan = get_clan( i );

	if( clan == NULL )
	{
		send_to_char("No such clan.\n\r", ch);
		return;
	}

	if( !str_cmp( arg2, "view" ) )
	{
		printf_to_char( ch, "Name:   [%s]\n\rNumber: [%2d]\n\rLeader: [%12s]\n\rSponsor:[%12s]\n\r",
		                clan->name, clan->number, clan->leader, clan->god );
		send_to_char("Members:", ch);

      for( x=0; x<MAX_CLAN_MEMBERS; x++ )
		{
			printf_to_char( ch, " %s", clan->members[x]);
		}
		
      send_to_char("\n\r", ch);
		printf_to_char( ch, "Recall: %d\n\rClan fund: %d\n\r", clan->recall_room, clan->clan_fund );
		printf_to_char( ch, "Clan status: %s\n\r", flag_string( clan_flags, clan->clan_flags ) );
		
      return;
	}

   if( !str_cmp( arg2, "member" ) )
   {
      CHAR_DATA *victim;

      victim = get_char_world( ch, argument );

      if ( ( victim == NULL ) || ( argument[0] == '\0' ) )
      {
         send_to_char("Player not found!\n\r", ch);
         return;
      }

      if ( IS_NPC(victim) )
      {
         send_to_char("Not on NPCs.\n\r", ch);
         return;
      }

      if ( !str_cmp( arg3, "add" ) )
      {
         if (victim->pcdata->clan != 0)
         {
            send_to_char("They are already in a clan.", ch);
            return;
         }

         if ( !can_ch_join( victim, clan, TRUE ) == FALSE )
         {
            send_to_char("WARNING!  This player does not meet the requirements of that clan!\n\r", ch);
         }

         victim->pcdata->clan        = clan->number;
			victim->pcdata->clan_rank   = MAX_RANK;
			victim->pcdata->join_status = JOIN_START;
			victim->pcdata->clan_ch     = NULL;

         add_member(victim, clan);
         printf_to_char(victim, "You have been made a member of %s.\n\r", clan->name);

         send_to_char("Member added.\n\r", ch);
         return;
      }

      if ( !str_cmp( arg3, "remove" ) )
      {
         if (victim->pcdata->clan != clan->number)
         {
            send_to_char("They are not a member of that clan!", ch);
            return;
         }

         victim->pcdata->clan = 0;
         victim->pcdata->clan_rank = 0;
         victim->pcdata->join_status = 0;
         victim->pcdata->clan_ch = NULL;

         remove_member(victim, clan);
         printf_to_char(victim, "You have been removed from %s.\n\r", clan->name);

         send_to_char("Member removed.\n\r", ch);
         return;
      }

      send_to_char(syntax, ch);
      return;
   }

   if( !str_cmp( arg2, "bank" ) || !str_cmp( arg2, "fund" ) )
	{
      int mod;

      if ( argument[0]=='\0' || !is_number( argument ) )
      {
         send_to_char(syntax, ch);
         return;
      }

      mod = atoi( argument );

      if (mod <= 0)
      {
         send_to_char("Positive numbers ONLY.\n\r", ch);
         return;
      }

      if ( !str_cmp( arg3, "deposit" ) )
      {
         clan->clan_fund += mod;
         printf_to_char(ch, "Balance: %d\n\r", clan->clan_fund);
         clan_log(clan, "%d credited by %s.", mod, ch->name);
         save_clans();
         return;
      }

      if ( !str_cmp( arg3, "withdraw" ) )
      {
         if ( mod > clan->clan_fund )
         {
            send_to_char("The clan cannot afford that.\n\r", ch);
            return;
         }

         clan->clan_fund -= mod;
         printf_to_char(ch, "Balance: %d\n\r", clan->clan_fund);
         clan_log(clan, "%d funds deducted by %s.", mod, ch->name);
         save_clans();
         return;
      }

      send_to_char(syntax, ch);
      return;
   }

	if( !str_cmp( arg2, "status" ) )
	{
      if ( !str_cmp( arg3, "creating" ) )
      {
			REMOVE_BIT( clan->clan_flags, CLAN_ACTIVE );
			REMOVE_BIT( clan->clan_flags, CLAN_INACTIVE );
			REMOVE_BIT( clan->clan_flags, CLAN_DISBANDING );
			REMOVE_BIT( clan->clan_flags, CLAN_DEAD );
			SET_BIT( clan->clan_flags, CLAN_CREATING );
			printf_to_char( ch, "Clan %s is now in the 'creating' stage.\n\r", clan->name );
			save_clans();
			return;
      }
      
   	if( !str_cmp( arg3, "active" ) )
		{
			REMOVE_BIT( clan->clan_flags, CLAN_INACTIVE );
			REMOVE_BIT( clan->clan_flags, CLAN_CREATING );
			REMOVE_BIT( clan->clan_flags, CLAN_DISBANDING );
			REMOVE_BIT( clan->clan_flags, CLAN_DEAD );
			SET_BIT( clan->clan_flags, CLAN_ACTIVE );
			printf_to_char( ch, "Clan %s is now in the 'active' stage.\n\r", clan->name );
			clan_log(clan, "Clan is now active.");
			save_clans();
			return;
		}

      if( !str_cmp( arg3, "inactive" ) )
		{
			REMOVE_BIT( clan->clan_flags, CLAN_ACTIVE );
			REMOVE_BIT( clan->clan_flags, CLAN_CREATING );
			REMOVE_BIT( clan->clan_flags, CLAN_DISBANDING );
			REMOVE_BIT( clan->clan_flags, CLAN_DEAD );
			SET_BIT( clan->clan_flags, CLAN_INACTIVE );
			printf_to_char( ch, "Clan %s is now in the 'inactive' stage.\n\r", clan->name );
			clan_log(clan, "The clan is no longer recruiting.");
			save_clans();
			return;
		}

      if( !str_cmp( arg3, "disbanding" ) )
		{
			REMOVE_BIT( clan->clan_flags, CLAN_ACTIVE );
			REMOVE_BIT( clan->clan_flags, CLAN_INACTIVE );
			REMOVE_BIT( clan->clan_flags, CLAN_CREATING );
			REMOVE_BIT( clan->clan_flags, CLAN_DEAD );
			SET_BIT( clan->clan_flags, CLAN_DISBANDING );
			printf_to_char( ch, "Clan %s is now in the 'disbanding' stage.\n\r", clan->name );
			clan_log(clan, "The clan is now disbanding.");
			save_clans();
			return;
		}

      if( !str_cmp( arg3, "dead" ) )
		{
			REMOVE_BIT( clan->clan_flags, CLAN_ACTIVE );
			REMOVE_BIT( clan->clan_flags, CLAN_INACTIVE );
			REMOVE_BIT( clan->clan_flags, CLAN_CREATING );
			REMOVE_BIT( clan->clan_flags, CLAN_DISBANDING );
			SET_BIT( clan->clan_flags, CLAN_DEAD );
			printf_to_char( ch, "Clan %s is now in the 'dead' stage.\n\r", clan->name );
			clan_log(clan, "The clan is now dead.");
			save_clans();
			return;
		}

      send_to_char(syntax, ch);
		return;
	}

   send_to_char(syntax, ch);
	return;
}

void do_clantalk( CHAR_DATA *ch, char *argument )
{
   DESCRIPTOR_DATA *d;
   CLAN_DATA *clan;
   if( IS_NPC(ch) )
	return;

	if( ch->pcdata->clan == 0 )
	{
		send_to_char("You are not even in a clan!\n\r", ch);
		return;
	}

    if (argument[0] == '\0' )
    {
      if (IS_SET(ch->comm,COMM_NOCLAN))
      {
	send_to_char("`BClan channel is now ON.\n\r`w",ch);
	REMOVE_BIT(ch->comm,COMM_NOCLAN);
      }
      else
      {
	send_to_char("`BClan channel is now OFF.\n\r`w",ch);
	SET_BIT(ch->comm,COMM_NOCLAN);
      }
    }
    else  /* clan message sent, turn clantalk on if it isn't already */
    {
	if (IS_SET(ch->comm,COMM_QUIET))
	{
	  send_to_char("You must turn off quiet mode first.\n\r",ch);
	  return;
	}
 
	if (IS_SET(ch->comm,COMM_NOCHANNELS))
	{
	  send_to_char("The gods have revoked your channel priviliges.\n\r",ch);
	  return;
 
	}

      REMOVE_BIT(ch->comm,COMM_NOCLAN);
		clan = get_clan( ch->pcdata->clan );

       for ( d = descriptor_list; d != NULL; d = d->next )
	 {
	    CHAR_DATA *victim;
	    victim = d->original ? d->original : d->character;
	if( IS_NPC( victim ) ) continue;
	if( victim == NULL ) continue;
	if( victim->pcdata == NULL ) continue;
	    if ( ( d->character != NULL &&
		d->connected == CON_PLAYING &&
		!IS_SET(victim->comm,COMM_NOCLAN) &&
		!IS_SET(victim->comm,COMM_QUIET) &&
		victim->pcdata->clan == ch->pcdata->clan &&
		d->character->position >= POS_SLEEPING
		&& clan != NULL) || IS_SET(victim->comm,COMM_SNOOP_CLAN)) 
	     {
		printf_to_char(victim, "`B%s`R<`w%s`R>`w %s`w\n\r",
		clan->whoname[0] != '\0' ? clan->whoname : clan->name,
		IS_NPC(ch) ? ch->short_descr : ch->name, argument);
	      }
	 }
    }
}


void do_resign( CHAR_DATA *ch, char *argument )
{
	CLAN_DATA *clan;

	if( IS_NPC(ch) )
	{
		send_to_char("You cannot resign from a clan, you're a mob!\n\r", ch);
		return;
	}

	if ( ch->pcdata->clan == 0 )
	{
		send_to_char("You're not in a clan, so how can you resign from one?\n\r", ch);
		return;
	}

	clan = get_clan( ch->pcdata->clan );

	if( !str_cmp( clan->leader, ch->name) || !str_cmp( clan->god, ch->name ) )
	{
		send_to_char("You cannot resign from this clan, you're too high ranked!\n\r", ch);
		return;
	}

	if( ch->pcdata->join_status != JOIN_RESIGNING )
	{
		send_to_char("You are attempting to remove yourself from your clan.\n\r", ch);
		send_to_char("Please type RESIGN again to confirm.\n\r", ch);
		ch->pcdata->join_status = JOIN_RESIGNING;
		return;
	}

	clan_log( clan, "%s resigned from the clan!", ch->name);
	ch->pcdata->clan = 0;
	ch->pcdata->clan_rank = 0;
	ch->pcdata->join_status = 0;
	remove_member( ch, clan );
	send_to_char("You are no longer a member of the clan.\n\r", ch);
	return;
}

void do_crecall( CHAR_DATA *ch, char *argument )
{
   char buf[MAX_STRING_LENGTH]; 
   CHAR_DATA *victim;
    ROOM_INDEX_DATA *location;
	CLAN_DATA *clan;

    if (IS_NPC(ch) && !IS_SET(ch->act,ACT_PET))
    {
	send_to_char("Only players can recall.\n\r",ch);
	return;
    }
		
	if( !IS_NPC(ch) && ch->pcdata->clan < 1 )
	{
		send_to_char("The clan recall command is for clan members only.\n\r",ch);
		return;
	}


    act( "$n prays for transportation!", ch, 0, 0, TO_ROOM );

    if (!IS_NPC(ch))
    {
    	if ( ch->pcdata->clan == 0)
	    {
	     send_to_char("You can't use clan recall, you're not in a clan!", ch);
		return;
	    }
	clan = get_clan( ch->pcdata->clan );
	location = get_room_index( clan->recall_room );
    }
    else
	{
	clan = get_clan( ch->master->pcdata->clan );
	location = get_room_index( clan->recall_room );	
	}

	if( location == NULL )
	{
		send_to_char("Whoops, no such room.\n\r", ch);
		bug("NULL recall room %d", clan->recall_room );
		return;
	}
    if ( ch->in_room == location )
	{
	send_to_char( "Look around, look familiar?\n\r", ch);
	return;
	}

    if ( IS_SET(ch->in_room->room_flags, ROOM_NO_RECALL)
    ||   IS_AFFECTED(ch, AFF_CURSE) )
    {
	send_to_char( "The gods have forsaken you.\n\r", ch );
	return;
    }

    if ( ( victim = ch->fighting ) != NULL )
    {
	int lose,skill;

	if (IS_NPC(ch))
	    skill = 40 + ch->level;
	else
	    skill = ch->pcdata->learned[gsn_recall];

	if ( number_percent() < 80 * skill / 100 )
	{
	    check_improve(ch,gsn_recall,FALSE,6);
	    WAIT_STATE( ch, 4 );
	    send_to_char( "You failed!\n\r", ch );
	    return;
	}
	if(!IS_NPC(ch))
{
	lose = (int)(0.02 * exp_per_level(ch, ch->pcdata->points));
	gain_exp( ch, 0 - lose );
	check_improve(ch,gsn_recall,TRUE,4);
	sprintf( buf, "You recall from combat!  You lose %d exps.\n\r", lose );
	send_to_char( buf, ch );
}
	stop_fighting( ch, TRUE );
	
    }

    ch->move /= 2;
    send_to_char("You pray to the gods for transportation!\n\r", ch);
    act( "$n disappears.", ch, NULL, NULL, TO_ROOM );
    char_from_room( ch );
    char_to_room( ch, location );
    act( "$n appears in the room.", ch, NULL, NULL, TO_ROOM );
    do_look( ch, "auto" );
    
    if (ch->pet != NULL)
	do_crecall(ch->pet,"");

    return;
}

void do_demote(CHAR_DATA *ch, char *argument)
{
	CLAN_DATA *clan;
	CHAR_DATA *victim;
	char buf[MAX_INPUT_LENGTH];

	if( IS_NPC( ch ) )
		return;

	if(ch->pcdata == NULL) return;

	if( argument[0] == '\0' )
	{
		send_to_char("Demote who?\n\r", ch);
		return;
	}

	victim = get_char_world( ch, argument );
	if( victim == NULL )
	{
		send_to_char("Demote who?\n\r", ch);
		return;
	}

	if( IS_NPC(victim) )
	{
		send_to_char("Um, you can't demote mobs.\n\r", ch);
		return;
	}

	if( get_trust( ch ) < MAX_LEVEL ) /* IMPS can demote anyone :) */
	{
	if( ch->pcdata->clan == 0 )
	{
		send_to_char("You are not a member of a clan!\n\r", ch);
		return;
	}

	if( ch->pcdata->clan != victim->pcdata->clan )
	{
		send_to_char("They are not even IN your clan!\n\r", ch);
		return;
	}

	if( victim->pcdata->clan_rank < 1 )
	{
		victim->pcdata->clan_rank = MAX_RANK;
	}

	if( ch->pcdata->clan_rank > 1 )
	{
		send_to_char("You are not high enough rank to demote anyone.\n\r", ch);
		return;
	}

	clan = get_clan( ch->pcdata->clan );

	if( str_cmp( ch->name, clan->leader) ) 
	{
		if( (ch->pcdata->clan_rank == 2 && victim->pcdata->clan_rank <= 3 )
		|| ( ch->pcdata->clan_rank == 1 && victim->pcdata->clan_rank <= 2 ) )
		{
 			send_to_char("Only the clan leader, an IMP, or a higher rank can demote them.\n\r", ch);
			return;
		}
	}

	}
	else
	{
		clan = get_clan( victim->pcdata->clan );
	}
	if( victim->pcdata->clan_rank == MAX_RANK )
	{
		send_to_char("That person's rank is as low as it can be!\n\r", ch );
		return;
	}
	printf_to_char(ch, "You demote %s to %s!\n\r", victim->name, clan->rank[victim->pcdata->clan_rank]);
	victim->pcdata->clan_rank++;
	printf_to_char(victim, "%s demotes you to %s in clan %s! :(\n\r",
		ch->name, clan->rank[victim->pcdata->clan_rank-1], clan->name);
	sprintf(buf, "%s demoted %s in clan %d.", ch->name, victim->name, clan->number );
	log_string( buf );
	clan_log( clan, "%s demoted %s to %s.", ch->name, victim->name, 
		clan->rank[victim->pcdata->clan_rank-1] );
	return;
}