atd/area/
atd/build/
atd/clans/
atd/log/
atd/player/store/
atd/site/
atd/src/bin/
#if defined( macintosh )
#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 "build.h"

/*
 * Globals
 */
CLAN_DATA *             clan_first;
CLAN_DATA *             clan_last;
CLAN_DATA *             clan_free;
sh_int                  top_clan;

char      * rank_string     args( ( CHAR_DATA * ch, sh_int rank ) );

#if defined(KEY)
#undef KEY
#endif

#if defined(SKEY)
#undef SKEY
#endif

#define KEY( literal, field, value )                \
				if ( !str_cmp( word, literal ) )	\
                {                                   \
                    field  = value;                 \
                    fMatch = TRUE;                  \
                    break;                          \
				}

#define SKEY( string, field )                       \
    if ( !str_cmp( word, string ) )     \
    {                                   \
      free_string( field );           \
      field = fread_string( fp );     \
      fMatch = TRUE;                  \
      break;                          \
    }


bool is_clan( CHAR_DATA *ch )
{
    if ( !IS_NPC( ch )
	&& ch->pcdata->clan
	&& ch->pcdata->clan_rank > RANK_EXILED )
	return TRUE;

    return FALSE;
}

/*
 * It is very important that this be an equivalence relation:
 * (1) A ~ A
 * (2) if A ~ B then B ~ A
 * (3) if A ~ B  and B ~ C, then A ~ C
 */
bool is_same_clan( CHAR_DATA *ach, CHAR_DATA *bch )
{
    if ( !ach || !bch )
        return FALSE;

    if ( is_clan( ach ) && is_clan( bch ) )
	return ach->pcdata->clan == bch->pcdata->clan;
    else
	return FALSE;
}


/*
 * Get pointer to clan structure from clan name.
 */
CLAN_DATA *get_clan( const char *name )
{
    CLAN_DATA *clan;
    
    for ( clan = clan_first; clan; clan = clan->next )
       if ( !str_cmp( name, clan->name ) )
         return clan;
    return NULL;
}

void remove_from_clan( CHAR_DATA *ch )
{
    CLAN_DATA *clan;

    if ( !is_clan( ch ) )
	return;

    clan = ch->pcdata->clan;

    switch ( ch->pcdata->clan_rank )
    {
    default: break;
    case RANK_CLANSMAN:  break;
    case RANK_CLANHERO:  clan->clanheros--; break;
    case RANK_SUBCHIEF:  clan->subchiefs--; break;
    case RANK_CHIEFTAIN: free_string( clan->chieftain ); break;
    case RANK_OVERLORD:  free_string( clan->overlord ); break;
    }

    clan->members--;
    ch->pcdata->clan = NULL;

    return;    
}

char * rank_string( CHAR_DATA *ch, sh_int rank )
{
    switch ( rank )
    {
    default:
    case RANK_CLANSMAN:  return "soldier";
    case RANK_CLANHERO:  return "warhero";
    case RANK_SUBCHIEF:  return "general";
    case RANK_CHIEFTAIN: return "baron";
    case RANK_OVERLORD:  return "overlord";
    }

}
    
void do_initiate( CHAR_DATA *ch, char *argument )
{
    CHAR_DATA *victim;
    CLAN_DATA *clan;
    OBJ_DATA  *card;
    OBJ_DATA  *ring;
    char       arg [ MAX_INPUT_LENGTH ];
    char       buf [ MAX_STRING_LENGTH ];

    one_argument( argument, arg );

    if ( arg[0] == '\0' )
    {
        send_to_char( "Initiate whom?\n\r", ch );
        return;
    }

    if ( !( victim = get_char_room( ch, arg ) ) )
    {
        send_to_char( "They aren't here.\n\r", ch );
        return;
    }

    if ( !is_clan( ch )
        || ch->pcdata->clan_rank < RANK_CHIEFTAIN
        || victim->level > ch->level )
    {
        send_to_char( "You don't have the power to do this.\n\r", ch );
        return;
    }

    clan = ch->pcdata->clan;

    if ( victim == ch )
        return;

    card = get_eq_char( victim, WEAR_HOLD );
    if ( is_clan( victim )
	 || IS_NPC( victim )
         || !card
	 || victim->pcdata->clan_rank == RANK_EXILED
         || victim->level < 20 )
    {
        act( "$N hasn't what's required to be initiated.",
	    ch, NULL, victim, TO_CHAR );
        act( "You can't be initiated to $t!",
	    ch, clan->name, victim, TO_VICT );
        return;
    }

    victim->pcdata->clan      = clan;
    victim->pcdata->clan_rank = RANK_CLANSMAN;
    clan->members++;

    ring = create_object( get_obj_index( clan->clanobj1 ), victim->level );

    if ( ring )
	obj_to_char( ring, victim );

    sprintf( buf, "Log %s: initiated %s to %s",
	    ch->name,
	    victim->name,
	    clan->name  );
    log_clan( buf );

    sprintf( buf, "I %s %s, hereby declare you %s a member of %s!",
		  rank_string( ch, PC(ch,clan_rank) ),
		  ch->name,
		  victim->name,
		  clan->name );
    do_say( ch, buf );
    sprintf( buf, "Take %s as a symbol of this union for all time.",
		  ring ? ring->short_descr : "my handshake" );
    do_say( ch, buf );

    sprintf( buf, "Forever remember our motto: \"%s\"\n\r",
		  clan->motto );
    do_say( ch, buf );

    act( "$N has been initiated to $t!", ch, clan->name, victim, TO_ROOM );
    act( "You have initiated $N to $t!", ch, clan->name, victim, TO_CHAR );
    save_char_obj( victim );

    return;
}

/*
 * "exil" command is a trap to the "exile" command.
 */
void do_exil( CHAR_DATA *ch, char *argument )
{
    send_to_char( "If you want to EXILE, you have to spell it out.\n\r", ch );

    return;
}


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

    one_argument( argument, arg );

    if ( arg[0] == '\0' )
    {
        send_to_char( "Exile whom?\n\r", ch );
        return;
    }

    if ( !is_clan( ch )
        || ch->pcdata->clan_rank != RANK_OVERLORD )
    {
        send_to_char( "You don't have the power to do this.\n\r", ch );
        return;
    }

    clan = ch->pcdata->clan;

    if ( !( victim = get_char_room( ch, arg ) ) )
    {
        send_to_char( "They aren't here.\n\r", ch );
        return;
    }

    if ( IS_NPC( victim ) || victim == ch )
        return;

    if ( !is_same_clan( ch, victim ) )
    {
        act( "$N isn't even from $t.", ch, clan->name, victim, TO_CHAR );
        return;
    }

    sprintf( buf, "Log %s: exiling %s from %s",
	    ch->name,
	    victim->name,
	    ch->pcdata->clan->name  );
    log_clan( buf );

    sprintf( buf,
	    "The grand %s of %s %s says:\n\r\n\r"
	    "'Then so be done, you %s shall be exiled from %s!'\n\r"
	    "You hear a thundering sound...\n\r\n\r"
	    "A booming voice says: 'You have been exiled!n\r",
	    rank_string( ch, PC(ch,clan_rank) ),
	    clan->name,
	    clan->overlord,
	    victim->name,
	    clan->name );

    send_to_char( buf, victim );

    remove_from_clan( victim );
    victim->pcdata->clan_rank = RANK_EXILED;


    act( "You have exiled $N from $t!", ch, clan->name, victim, TO_CHAR );
    save_char_obj( victim );
    
    return;
}

void do_bestow( CHAR_DATA *ch, char *argument )
{
    CHAR_DATA *victim;
    CLAN_DATA *clan;
    OBJ_DATA  *obj;
    char       arg [ MAX_INPUT_LENGTH ];
    char       buf [ MAX_STRING_LENGTH ];
    int        newrank;

    one_argument( argument, arg );

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

    if ( !is_clan( ch )
        || ch->pcdata->clan_rank != RANK_OVERLORD )
    {
        send_to_char( "You don't have the power to do this.\n\r", ch );
        return;
    }

    clan = ch->pcdata->clan;

    if ( !( victim = get_char_room( ch, arg ) ) )
    {
        send_to_char( "They aren't here.\n\r", ch );
        return;
    }

    if ( IS_NPC( victim ) || victim == ch )
        return;

    if ( !is_same_clan( ch, victim ) )
    {
        act( "$N isn't even from $t.", ch, clan->name, victim, TO_CHAR );
        return;
    }

    obj = NULL;

    switch ( victim->pcdata->clan_rank )
    {
    default:
	return;
	break;
    case RANK_CLANSMAN:
	if ( clan->clanheros >= clan->members / 3 )
	{
	    send_to_char( "You may have only 1 clanhero per 3 clansmen.\n\r", ch );
	    return;
	}
	obj = create_object( get_obj_index( clan->clanobj2 ), victim->level );
	clan->clanheros++;
    	break;
    case RANK_CLANHERO:
	if ( clan->subchiefs >= clan->members / 6 )
	{
	    send_to_char( "You may have only 1 subchief per 6 clansmen.\n\r", ch );
	    return;
	}
	obj = create_object( get_obj_index( clan->clanobj3 ), victim->level );
	clan->clanheros--;
	clan->subchiefs++;
	break;
    case RANK_SUBCHIEF:
	if ( clan->chieftain[0] != '\0' )
	{
	    send_to_char( "You may have only 1 chieftain.\n\r", ch );
	    return;
	}
	else if ( clan->members < 9 )
	{
	    send_to_char( "You need to have 9 clansmen before you can have a chieftain.\n\r", ch );
	    return;
	}

	clan->subchiefs--;
	if( clan->chieftain )
		free_string( clan->chieftain );
	clan->chieftain = str_dup( victim->name );
	break;
    case RANK_CHIEFTAIN:
    case RANK_OVERLORD:
	send_to_char( "You may not promote any further that person.\n\r", ch );
	return;
	break;
    }

    victim->pcdata->clan_rank++;
    newrank = victim->pcdata->clan_rank;

    if ( obj )
	obj_to_char( obj, victim );

    sprintf( buf, "Log %s: promoting %s to %s",
	    ch->name,
	    victim->name,
	    ch->pcdata->clan->name  );
    log_clan( buf );

    sprintf( buf,
	    "The grand Overlord %s says:\n\r\n\r"
	    "'I hereby promote you %s to %s!'\n\r"
	    "Take %s as a prize for your superb performance.\n\r"
	    "%s\n\r",
	    ch->name,
	    victim->name,
	    rank_string( ch, newrank ),
	    obj ? obj->short_descr : "this promotion",
	    clan->motto );

    send_to_char( buf, victim );

    act( "You have promoted $N to $t.",
	ch, rank_string( ch, newrank ), victim, TO_CHAR );
    save_char_obj( victim );
    
    return;
}


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

    one_argument( argument, arg );

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

    if ( !is_clan( ch )
        || ch->pcdata->clan_rank != RANK_OVERLORD )
    {
        send_to_char( "You don't have the power to do this.\n\r", ch );
        return;
    }

    clan = ch->pcdata->clan;

    if ( !( victim = get_char_room( ch, arg ) ) )
    {
        send_to_char( "They aren't here.\n\r", ch );
        return;
    }

    if ( IS_NPC( victim ) || victim == ch )
        return;

    if ( !is_same_clan( ch, victim ) )
    {
        act( "$N isn't even from $t.", ch, clan->name, victim, TO_CHAR );
        return;
    }

    switch ( victim->pcdata->clan_rank )
    {
    default:
	return;
	break;
    case RANK_CLANSMAN:
	send_to_char( "He's as low as they can get.\n\r", ch );
	return;
	break;
    case RANK_CLANHERO:
	clan->clanheros--;
	break;
    case RANK_SUBCHIEF:
	clan->clanheros++;
	clan->subchiefs--;
	break;
    case RANK_CHIEFTAIN:
	clan->subchiefs++;
	free_string( clan->chieftain );
	break;
    case RANK_OVERLORD:
	send_to_char( "You may not demote an Overlord!?\n\r", ch );
	return;
	break;
    }

    victim->pcdata->clan_rank--;
    newrank = victim->pcdata->clan_rank;

    sprintf( buf, "Log %s: demoting %s to %s",
	    ch->name,
	    victim->name,
	    ch->pcdata->clan->name  );
    log_clan( buf );

    sprintf( buf,
	    "The grand Overlord %s says:\n\r\n\r"
	    "'I hereby demote you %s to %s!!!'\n\r"
	    "You should make more efforts to improve!",
	    ch->name,
	    victim->name,
	    rank_string( ch, newrank ) );
    send_to_char( buf, victim );

    act( "You have demoted $N to $t.",
	ch, rank_string( ch, newrank ), victim, TO_CHAR );
    save_char_obj( victim );
    
    return;
}

void do_leave( CHAR_DATA *ch, char *argument )
{
    CLAN_DATA *clan;
    char       buf [ MAX_STRING_LENGTH ];

    if ( !is_clan( ch )  )
    {
        send_to_char( "You aren't a clansman.\n\r", ch );
        return;
    }

    clan = ch->pcdata->clan;

    if ( ch->pcdata->clan_rank == RANK_OVERLORD )
    {
        send_to_char( "Huh? An Overlord shouldn't leave his clan!\n\r", ch );
        return;
    }

    remove_from_clan( ch );
    ch->pcdata->clan_rank = RANK_EXILED;

    sprintf( buf,
	    "You leave %s off into exile.\n\r"
	    "You hear a thundering sound...\n\r\n\r"
	    "A booming voice says: 'You have been exiled!'\n\r",
	    clan->name );

    send_to_char( buf, ch );

    act( "You have left clan $t.", ch, clan->name, NULL, TO_CHAR );
    save_char_obj( ch );
    
    return;
}

void do_overthrow( CHAR_DATA *ch, char *argument )
{
    CHAR_DATA *victim;
    CLAN_DATA *pClan;
    char       buf [ MAX_STRING_LENGTH ];
    
    if( IS_NPC(ch) )
        return;

    pClan = PC(ch,clan);
    
    if( !(victim = get_char_room( ch, argument ) ) )
    {
        stc( "There is noone here by that name.\n\r", ch );
        return;
    }

    if( IS_NPC(victim) )
    {
        stc( "Not on NPC's.\n\r", ch );
        return;
    }

    if( victim == ch )
    {
        stc( "Why would you want to do that?\n\r", ch );
        return;
    }
    
    if( PC(victim,clan) != pClan )
    {
        ch_printf( ch, "%s is not the overlord of %s.\n\r",
                   PERS(victim,ch), pClan->name );
        return;
    }

    if( PC(victim,clan_rank) != RANK_OVERLORD )
    {
        ch_printf( ch, "%s is not the overlord of %s.\n\r",
                   PERS(victim,ch), pClan->name );
        return;
    }

    if( victim->hit > 0 )
    {
        ch_printf( ch, "%s must be morted.\n\r", PERS(victim,ch) );
        return;
    }

    PC(victim,clan_rank) = PC(ch,clan_rank);
    PC(ch,clan_rank)     = RANK_OVERLORD;

    free_string( pClan->overlord );
    pClan->overlord = str_dup( ch->name );
    

    if( PC(victim,clan_rank) == RANK_CHIEFTAIN )
    {
        free_string( pClan->chieftain );
        pClan->chieftain = str_dup( victim->name );
    }

    sprintf( buf, "I %s, a former %s of %s\n\r",
             ch->name, rank_string(victim, PC(victim,clan_rank)),pClan->name );
    do_say( ch, buf );

    sprintf( buf, "declare that %s kingdom is now under my control.",
             pClan->name );
    do_say( ch, buf );

    save_char_obj( victim );
    save_char_obj( ch );
    return;
}

void do_clans( CHAR_DATA *ch, char *argument )
{
    CLAN_DATA *clan;
    char       buf1 [ MAX_STRING_LENGTH ];
    char       buf  [ MAX_STRING_LENGTH ];
    int        found;

    buf1[0] = '\0';

    sprintf( buf, "{o{rClan              Overlord          Chieftain         Pkills{x\n\r" );
    strcat( buf1, buf );

    for ( clan = clan_first, found = 0; clan; clan = clan->next )
    {
	sprintf( buf, "{R%-16.16s  %-16.16s  %-16.16s   %5.5d{x\n\r",
		clan->name,
		clan->overlord,
		clan->chieftain,
		clan->pkills );
	strcat( buf1, buf );
	found++;
    }

    if ( !found )
	sprintf( buf, "{RThere are no Clans currently formed.{x\n\r" );
    else
	sprintf( buf, "{RYou see %d clan%s in the game.{x\n\r",
		found,
		found == 1 ? "" : "s" );

    strcat( buf1, buf );
    send_to_char( buf1, ch );

    return;
}

void show_clan( CHAR_DATA *ch, CLAN_DATA *clan )
{
    DESCRIPTOR_DATA *d;
    CHAR_DATA *wch;
    int found = 0;
    char temp[MAX_INPUT_LENGTH];

    ch_printf( ch, "{yOrder: {b[{c%s{b] {n%s{n\n\r",
             clan->name, clan->who_name );
    ch_printf( ch, "{gMotto{n\n\r    %s{n\n\r", clan->motto );
    ch_printf( ch, "{gStory\n\r{W... %s ...{n\n\r", clan->description );
    ch_printf( ch, "{g%-14.14s {b[{c%s{b]{n\n\r",
             rank_string( ch, RANK_OVERLORD ), clan->overlord );
    if( clan->chieftain && clan->chieftain[0] )
    {
        sprintf( temp, "%ss", rank_string( ch, RANK_CHIEFTAIN ) );
        ch_printf( ch, "{g%-14.14s {b[{c%s{b]{n\n\r",
                 rank_string( ch, RANK_CHIEFTAIN ),
                 clan->chieftain );
    }
    sprintf( temp, "%ss", rank_string( ch, RANK_CLANHERO ) );
    ch_printf( ch, "{g%-14.14s {b[{c%d{b/{c%d{b]{n\n\r", temp,
	     clan->clanheros, clan->members / 3 );
    sprintf( temp, "%ss", rank_string( ch, RANK_CLANSMAN ) );
    ch_printf( ch, "{g%-14.14s {b[{c%d{b]{n\n\r", temp, clan->members );
    ch_printf( ch, "{gKills          {b[{c%d{b]{n\n\r", clan->pkills );
    ch_printf( ch, "{gDeaths         {b[{c%d{b]{n\n\r", clan->pdeaths );
    ch_printf( ch, "{gRecall         {b[{c%d{b]{y %s{n\n\r",
             IS_IMMORTAL( ch ) ? clan->recall : 0,
             get_room_index( clan->recall )
             ? ( get_room_index( clan->recall ) )->name : "nowhere" );
    for( d = descriptor_list; d; d = d->next )
    {
        wch = CH( d );
        if( wch->pcdata->clan != clan || !can_see( ch, wch ) )
            continue;
        if( !found )
        {
            stc( LINE_SEPERATOR, ch );
            stc("{gMembers online:{n\n\r",ch );
        }
        found++;
        ch_printf( ch, "{y%25.25s", wch->name );
        if( found % 3 == 0 )
            stc("{n\n\r", ch);
    }
    if( found % 3 != 0 )
	stc("{n\n\r", ch );
    if( found )
	ch_printf( ch,"{gFound {c%d {gmember%s online.{n\n\r", found,
		 ( found == 1 ) ? "" : "s" );

}

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

    if ( !is_clan( ch )  )
    {
        send_to_char( "You aren't a clansman.\n\r", ch );
        return;
    }

    clan = ch->pcdata->clan;

    stc( LINE_SEPERATOR, ch );
    show_clan( ch, clan );
    stc( LINE_SEPERATOR, ch );
    return;
}


/*
 * All the file and loading for clans from here on down
 */

/*
 * New code for loading clans from file.
 */
bool fread_clan( CLAN_DATA *clan, FILE *fp )
{
    char *word;
    bool  fMatch;

    for ( ; ; )
    {
	word   = feof( fp ) ? "End" : fread_word( fp );
	fMatch = FALSE;

	switch ( UPPER( word[0] ) )
	{
	case '*':
	    fMatch = TRUE;
	    fread_to_eol( fp );
	    break;

	case 'C':
            SKEY( "Chieftain",   clan->chieftain );
            KEY( "ClanHeros",    clan->clanheros, fread_number( fp ) );
            KEY( "ClanObjOne",   clan->clanobj1,  fread_number( fp ) );
            KEY( "ClanObjTwo",   clan->clanobj2,  fread_number( fp ) );
            KEY( "ClanObjThree", clan->clanobj3,  fread_number( fp ) );
	    break;

	case 'D':
            SKEY( "Desc",    clan->description );
	    break;

	case 'E':
	    if ( !str_cmp( word, "End" ) )
		return TRUE;
	    break;

	case 'M':
            KEY( "Members",     clan->members, fread_number( fp ) );
            SKEY( "Motto", clan->motto );
	    break;

	case 'N':
            SKEY( "Name",      clan->name    );
	    break;

	case 'O':
            SKEY( "Overlord", clan->overlord );
	    break;

	case 'P':
            KEY( "PKills",  clan->pkills,  fread_number( fp ) );
            KEY( "PDeaths", clan->pdeaths, fread_number( fp ) );
	    break;

	case 'R':
            KEY( "Recall",  clan->recall,  fread_number( fp ) );
	    break;

	case 'S':
            KEY( "Subchiefs", clan->subchiefs, fread_number( fp ) );
	    break;

	case 'W':
            SKEY( "WhoName",   clan->who_name    );
	    break;

	}

	if ( !fMatch )
	{
            bugf( "Load_clan_file: no match: %s", word );
	    fread_to_eol(fp);
	}
    }

    return FALSE;
}

bool load_clan_file( char *filename )
{
    CLAN_DATA *clan;
    FILE      *fp;
    char       buf [ MAX_STRING_LENGTH ];

    sprintf( buf, "%s%s", CLAN_DIR, filename );
    if ( !( fp = fopen( buf, "r" ) ) )
    {
        perror( buf );
        return FALSE;
    }

    clan = alloc_mem ( sizeof( CLAN_DATA ) );
    clan->filename = str_dup( filename );
    
    for ( ; ; )
    {
	char *word;
	int   letter;

	letter = fread_letter( fp );
	if ( letter == '*' )
	{
	    fread_to_eol( fp );
	    continue;
	}

	if ( letter != '#' )
	{
	    bug( "Load_clan_file: # not found.", 0 );
	    free_mem( clan, sizeof( CLAN_DATA ) );
	    break;
	}

	word = fread_word( fp );

	if ( !str_cmp( word, "CLAN" ) )
	{
	    fread_clan( clan, fp );

	    if ( !clan_first )
		clan_first	= clan;
	    else
		clan_last->next	= clan;
	    clan->next		= NULL;
	    clan_last		= clan;
            top_clan++;
	    break;
	}
	else if ( !str_cmp( word, "END"  ) ) break;
	else
	{
	    bugf( "Load_clan_file: bad section: %s.", word );
	    free_mem( clan, sizeof( CLAN_DATA ) );
	    break;
	}
    }
    fclose( fp );

    return TRUE;
}

/*
 * Load in all the clan files.
 */ 
void load_clans( void )
{
    FILE *fpList;
    char *filename;
    char  fname		[ MAX_STRING_LENGTH ];
    char  clanslist	[ MAX_STRING_LENGTH ];
    
    clan_first  = NULL;
    clan_last   = NULL;
    top_clan    = 0;

    sprintf( clanslist, "%s%s", CLAN_DIR, CLAN_LIST );

    if ( !( fpList = fopen( clanslist, "r" ) ) )
    {
        perror( clanslist );
        exit( 1 );
    }

    for ( ; ; )
    {
        filename = feof( fpList ) ? "$" : fread_word( fpList );
	strcpy( fname, filename );
        if ( fname[0] == '$' )
	    break;

        if ( !load_clan_file( fname ) )
	    bugf( "Cannot load clan file: %s", fname );

    }
    fclose( fpList );

    return;
}

void save_clan_list( void )
{
    FILE      *fp;
    CLAN_DATA *clan;
    char       clanslist	[ MAX_STRING_LENGTH ];

    sprintf( clanslist, "%s%s", CLAN_DIR, CLAN_LIST );
    fclose( fpReserve );

    if ( !( fp = fopen( clanslist, "w" ) ) )
    {
        bug( "Save_clan_list: fopen", 0 );
        perror( clanslist );
	return;
    }

    for ( clan = clan_first; clan; clan = clan->next )
	fprintf( fp, "%s\n", clan->filename );

    fprintf( fp, "$\n" );
    fclose( fp );

    fpReserve = fopen( NULL_FILE, "r" );
    return;
}


void clan_update( void )
{
    CLAN_DATA *clan;

    for ( clan = clan_first; clan; clan = clan->next )
	save_clan( clan );
    return;
}

/*
 * New code for writing a clan to a file.
 */
void save_clan( CLAN_DATA *clan )
{
    FILE                    *fp;
    char                     buf	[ MAX_STRING_LENGTH ];

    if ( !clan->filename )
	return;
    
    sprintf( buf, "%s%s", CLAN_DIR, clan->filename );

    fclose( fpReserve );

    if ( !( fp = fopen( buf, "w" ) ) )
    {
        bugf( "Cannot open: %s for writing", clan->filename );
    }
    else
    {
	fprintf( fp, "#CLAN\n" );
	fprintf( fp, "WhoName       %s~\n",        clan->who_name );
	fprintf( fp, "Name          %s~\n",        clan->name );
	fprintf( fp, "Motto         %s~\n",        clan->motto );
	fprintf( fp, "Desc          %s~\n",        strip_cr(clan->description ) );
	fprintf( fp, "Overlord      %s~\n",        clan->overlord );
	fprintf( fp, "Chieftain     %s~\n",        clan->chieftain );
	fprintf( fp, "PKills        %d\n",         clan->pkills );
	fprintf( fp, "PDeaths       %d\n",         clan->pdeaths );
	fprintf( fp, "Clanheros     %d\n",         clan->clanheros );
	fprintf( fp, "Subchiefs     %d\n",         clan->subchiefs );
	fprintf( fp, "Members       %d\n",         clan->members );
	fprintf( fp, "ClanObjOne    %d\n",         clan->clanobj1 );
	fprintf( fp, "ClanObjTwo    %d\n",         clan->clanobj2 );
	fprintf( fp, "ClanObjThree  %d\n",         clan->clanobj3 );
	fprintf( fp, "Recall        %d\n",         clan->recall );
	fprintf( fp, "End\n" );
	fprintf( fp, "#END\n" );

	fclose( fp );
    }

    fpReserve = fopen( NULL_FILE, "r" );

    return;
}