daleken/
daleken/data/notes/
daleken/data/player/
daleken/data/system/poses/
daleken/doc/Homepage/images/
daleken/log/
/*___________________________________________________________________________*
   )()(			  DalekenMUD 1.12 (C) 2000			)()(
   `]['		       by Martin Thomson, Lee Brooks,			`]['
    ||		       Ken Herbert and David Jacques			 ||
    || ----------------------------------------------------------------- ||
    || Envy Diku Mud improvements copyright (C) 1994 by Michael Quan,	 ||
    || David Love, Guilherme 'Willie' Arnold, and Mitchell Tse.		 ||
    || Merc Diku Mud improvments copyright (C) 1992, 1993 by Michael	 ||
    || Chastain, Michael Quan, and Mitchell Tse.			 ||
    || Original Diku Mud copyright (C) 1990, 1991			 ||
    || by Sebastian Hammer, Michael Seifert, Hans Henrik St{rfeldt,	 ||
    || Tom Madsen, and Katja Nyboe.					 ||
    || ----------------------------------------------------------------- ||
    || Any use of this software must follow the licenses of the		 ||
    || creators.  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.					 ||
    || ----------------------------------------------------------------- ||
    ||				   religion.c				 ||
    || All religion and clan related code, including online editing.	 ||
    || Inspired in part by Greed and Smaug clans.			 ||
 *_/<>\_________________________________________________________________/<>\_*/


#if defined( unix )
#include <unistd.h>
#endif
#include "mud.h"
#include "olc.h"
#include "event.h"


/* That constant from magic_*.c */
extern const char *target_name;

/*
 * Local data
 */
int	top_religion;
CLAN_DATA *clan_first;
CLAN_DATA *clan_last;
int	top_clan;
extern char strArea[];

DECLARE_DO_FUN(	   clan_consider	);
DECLARE_DO_FUN(	   clan_demote		);
DECLARE_DO_FUN(	   clan_donate		);
DECLARE_DO_FUN(	   clan_exil		);
DECLARE_DO_FUN(	   clan_exile		);
DECLARE_DO_FUN(	   clan_holywar		);
DECLARE_DO_FUN(	   clan_info		);
DECLARE_DO_FUN(	   clan_initiate	);
DECLARE_DO_FUN(	   clan_peace		);
DECLARE_DO_FUN(	   clan_power		);
DECLARE_DO_FUN(	   clan_promote		);
DECLARE_DO_FUN(	   clan_recall		);
DECLARE_DO_FUN(	   clan_war		);
DECLARE_DO_FUN(	   religion_info	);
DECLARE_DO_FUN(	   religion_list	);
DECLARE_DO_FUN(	   religion_overtake	);
DECLARE_DO_FUN(	   religion_take	);


RELIGION_DATA *religion_lookup( const char *name )
{
    RELIGION_DATA *rel;
    for( rel = religion_first; rel; rel = rel->next )
	if( is_name( name, rel->name ) )
	    break;
    return rel;
}


CLAN_DATA *clan_lookup( const char *name )
{
    CLAN_DATA *clan;
    for( clan = clan_first; clan; clan = clan->next )
	if( is_name( name, clan->name ) )
	    break;
    return clan;
}


void add_religion_tokens()
{
    AREA_DATA *pArea;
    ROOM_INDEX_DATA *pRoom;
    OBJ_INDEX_DATA *pObj;
    OBJ_DATA *obj;

    for( pArea = area_first; pArea; pArea = pArea->next )
    {
	if( !pArea->order )
	    continue;

	pRoom = get_room_index( pArea->token_room );
	if( !pRoom || pRoom->area != pArea )
	{
	    bug( "Token room bad for area %s(%d) - %d.\n\r",
		       pArea->name, pArea->vnum, pArea->token_room );
	    pArea->order = NULL;
	    return;
	}
	pObj = get_obj_index( pArea->order->religion->token );
	if( !pObj )
	{
	    bug( "Bad token vnum %d for %s.\n\r",
		       pArea->order->religion->token,
		       pArea->order->religion->name );
	    pArea->order = NULL;
	    return;
	}
	obj = create_object( pObj, 0 );
	obj_to_room( obj, pRoom );
	obj->item_type = ITEM_CORPSE_PC;	/* prevent accidental purge */
	strip_events( &obj->events, evn_obj_decay );
	strip_events( &obj->events, evn_imp_grab );
	REMOVE_BIT( obj->extra_flags, ITEM_TAKE );
    }
}


bool is_religion( CHAR_DATA *ch )
{
    if( !IS_NPC( ch ) && ch->pcdata->religion )
	return TRUE;
    return FALSE;
}


void do_religion( CHAR_DATA *ch, const char *argument )
{
    char arg[MAX_INPUT_LENGTH];

    if( !str_cmp( argument, "list" ) )
    {
	religion_list( ch, argument );
	return;
    }

    if( !is_religion( ch ) )
    {
	send_to_char( "You don't belong to a religion.\n\r", ch );
	return;
    }

    argument = one_argument( argument, arg );

    if( !str_prefix( arg, "info" ) )
	religion_info( ch, argument );
    else if( !str_prefix( arg, "holypower" ) || !str_prefix( arg, "power" ) )
	do_holypower( ch, argument );
    else if( !str_prefix( arg, "list" ) )
	religion_list( ch, argument );
    else if( !str_cmp( arg, "leave" ) )
	do_leave( ch, "religion" );
    else if( !str_cmp( arg, "overtake" ) )
	religion_overtake( ch, argument );
    else if( !str_cmp( arg, "take" ) )
	religion_take( ch, argument );
    else
	do_help( ch, "religion" );
    return;
}


/*
 * Adds the number (positive or negative) to the orders karma.
 * This function also ensures that orders don't get too much
 * or too little karma somewhat, by limiting the change when
 * the order reaches extremes.
 * Of course you should add other limits, such as not spending
 * karma when it is below zero and so on.
 */
void add_karma( CLAN_DATA *order, int amount )
{
    if( order->clan_type != CLAN_ORDER )
    {
	bug( "Modifying karma on a clan/guild." );
	return;
    }

    if( amount < 0 )
    {
	if( order->karma < -1000 )
	    amount += order->karma / 1000;
	else if( order->karma > 500 )
	    amount -= order->karma / 500;
	amount = UMIN( amount, 0 );
    }
    else
    {
	if( order->karma < -2000 )
	    amount += order->karma / 2000;
	else if( order->karma > 1000 )
	    amount -= order->karma / 1000;
	amount = UMAX( amount, 0 );
    }

    order->karma += amount;
    return;
}


void do_pray( CHAR_DATA *ch, const char *argument )
{
    RELIGION_DATA *pReligion;
    CHAR_DATA *god;
    int sn;

    if( !is_religion( ch ) )
    {
	send_to_char( "You don't know who to pray to.\n\r", ch );
	return;
    }
    pReligion = ch->pcdata->religion;

    act( "&g$n get$% down on $s knees and pray$% to $g.",
	 ch, NULL, NULL, TO_ALL );
    if( argument[0] != '\0' )
	charprintf( ch, "&gYou pray '%s&n&g'&n\n\r", argument );
    if( ( god = get_char_world( ch, pReligion->god_name ) ) )
	charprintf( god, "&g<PRAYER:%s> %s&n\n\r", ch->name, argument );

    sn = skill_lookup( "prayer" );
    if( ( ch->pcdata->clan_rank == RANK_EXILED && number_bits( 2 ) == 0 )
	|| ch->alignment < pReligion->align_min
	|| ch->alignment > pReligion->align_max )
	sn = skill_lookup( "lightning bolt" );
    (*skill_table[sn].spell_fun)( sn, ch->level, ch, (void*)ch );
    return;
}


void religion_info( CHAR_DATA *ch, const char *argument )
{
    RELIGION_DATA *pReligion;
    RELIGION_SKILL *ski;
    AREA_DATA *pArea;
    BUFFER *buf = buffer_new( MAX_STRING_LENGTH );
    int cnt = 0;

    if( IS_IMMORTAL( ch ) && argument[0] != '\0' )
    {
	pReligion = religion_lookup( argument );
	if( !pReligion )
	{
	    send_to_char( "No such religion.\n\r", ch );
	    buffer_free( buf );
	    return;
	}
	bprintf( buf, "&cStatistics for the %s religion:\n\r", pReligion->name );
    }
    else
    {
	pReligion = ch->pcdata->religion;
	buffer_strcat( buf, "&cStatistics for your religion:\n\r" );
    }

    bprintf( buf, "&gReligion:      &b[&c%s&b]&n\n\r",
	     pReligion->display_name );
    bprintf( buf, "&gGod's Name:    &b[&c%s&b]&n\n\r",
	     pReligion->god_name );
    bprintf( buf, "&gAlignment:     &b[&c%d - %d&b]&n\n\r",
	     pReligion->align_min, pReligion->align_max );
    bprintf( buf, "&gToken:         &b[&c%d&b]&g %s&n\n\r",
	     pReligion->token,
	     get_obj_index( pReligion->token )
	     ? ( get_obj_index( pReligion->token ) )->short_descr : "none" );
    for( ski = pReligion->skills; ski; ski = ski->next )
    {
	if( cnt++ == 0 )
	{
	    buffer_strcat( buf, "&gSkill           Rank\n\r"
				"&b=============== ============\n\r" );
	}
	bprintf( buf, "&g%-15.15s %s&n\n\r",
		 ski->sn > 0 ? skill_table[ski->sn].name : "ERROR!",
		 rank_name( ski->level, CLAN_ORDER ) );
    }
    cnt = 0;
    for( pArea = area_first; pArea; pArea = pArea->next )
    {
	if( !pArea->order || pArea->order->religion != pReligion )
	    continue;
	if( cnt++ == 0 )
	    buffer_strcat( buf, "&cOwned areas:&n\n\r" );
	bprintf( buf, "&g%2d:  %s, %s order", cnt, pArea->name,
		 pArea->order->display_name );
	if( IS_IMMORTAL( ch ) )
	    bprintf( buf, " &c(Token Room: %d)", pArea->token_room );
	buffer_strcat( buf, "&n\n\r" );
    }

    send_to_char( buf->data, ch );
    buffer_free( buf );
    return;
}


void religion_list( CHAR_DATA *ch, const char *argument )
{
    RELIGION_DATA *pReligion;
    AREA_DATA *pArea;
    int found = 0, narea = 0;
    BUFFER *buf = buffer_new( MAX_STRING_LENGTH );
    char tmp[MAX_INPUT_LENGTH];

    for( pReligion = religion_first; pReligion; pReligion = pReligion->next )
    {
	if( !found++ )
	{
	    buffer_strcat( buf, "&cReligion        God	        Alignments   Number of Areas\n\r" );
	    buffer_strcat( buf, LINE_SEPARATOR );
	}
	for( pArea = area_first; pArea; pArea = pArea->next )
	{
	    if( pArea->order && pArea->order->religion == pReligion )
		narea++;
	}
	bprintf( buf, "&y%s&g %-12.12s %5d - %5d %5d&n\n\r",
		 colour_strpad( tmp, pReligion->display_name, 15 ),
		 pReligion->god_name,
		 pReligion->align_min, pReligion->align_max, narea );
    }
    if( !found )
	send_to_char( "No religions found.\n\r", ch );
    else
    {
	buffer_strcat( buf, LINE_SEPARATOR );
	bprintf( buf, "&g%d religions found on Daleken.&n\n\r", found );
	send_to_char( buf->data, ch );
    }
    buffer_free( buf );
    return;
}


void religion_take( CHAR_DATA *ch, const char *argument )
{
    RELIGION_DATA *pReligion;
    AREA_DATA *pArea;
    OBJ_INDEX_DATA *pObj;
    OBJ_DATA *obj;
    char buf[MAX_STRING_LENGTH];

    if( !is_clan( ch ) || ch->pcdata->clan->clan_type != CLAN_ORDER )
    {
	send_to_char( "You aren't a member of a religious order.\n\r", ch );
	return;
    }
    if( ch->pcdata->clan_rank <= RANK_CLANHERO )
    {
	send_to_char( "You aren't high enough in your order to do this.\n\r", ch );
	return;
    }
    pReligion = ch->pcdata->clan->religion;
    pArea = ch->in_room->area;
    if( pArea->nmobile )
    {
	charprintf( ch, "There are still %d mobiles left in this area.\n\r",
		    pArea->nmobile );
	return;
    }
    if( pArea->order && pArea->order->religion == pReligion )
    {
	send_to_char( "Your religion already controls this area.\n\r", ch );
	return;
    }
    if( pArea->order )
    {
	send_to_char( "Another religion controls this area already.\n\r", ch );
	send_to_char( "Destroy their token first by using 'overtake'.\n\r", ch );
	return;
    }
    if( ch->pcdata->clan->karma < 50 )
    {
	send_to_char(
	    "Your god refuses to grant anyone from your order that power.\n\r",
	    ch );
	return;
    }

    pObj = get_obj_index( pReligion->token );
    if( !pObj )
    {
	bug( "Bad token vnum %d for %s.\n\r",
		   pReligion->token, pReligion->name );
	send_to_char( "Your religion doesn't have a token, sorry.\n\r", ch );
	return;
    }
    pArea->order = ch->pcdata->clan;
    pArea->token_room = ch->in_room->vnum;
    add_karma( pArea->order, -50 );
    do_asave( NULL, "" );
    reset_area( pArea );

    obj = create_object( pObj, 0 );
    obj_to_room( obj, ch->in_room );
    REMOVE_BIT( obj->extra_flags, ITEM_TAKE );
    obj->item_type = ITEM_CORPSE_NPC;	/* prevent accidental purge */
    strip_events( &obj->events, evn_obj_decay );
    strip_events( &obj->events, evn_imp_grab );
    log_string( "Religion: %s takes %s for %s.",
	       ch->name, pArea->name, pReligion->name );
    wiznetf( ch, WIZ_CLAN, 0, "%s has taken %s for %s.", ch->name,
	     pArea->name, pReligion->name );
    sprintf( buf, "$n has shown %s&x the wrath of $g.", pArea->name );
    talk_channel( ch, buf, CHANNEL_INFO, "INFO" );
    return;
}


void religion_overtake( CHAR_DATA *ch, const char *argument )
{
    RELIGION_DATA *pReligion;
    AREA_DATA *pArea;
    OBJ_DATA *token;
    char buf[MAX_STRING_LENGTH];

    if( !is_clan( ch ) || ch->pcdata->clan->clan_type != CLAN_ORDER )
    {
	send_to_char( "You aren't a member of a religious order.\n\r", ch );
	return;
    }
    if( ch->pcdata->clan_rank <= RANK_CLANHERO )
    {
	send_to_char( "You aren't high enough in your order to do this.\n\r", ch );
	return;
    }
    pReligion = ch->pcdata->religion;
    pArea = ch->in_room->area;
    if( pArea->nmobile )
    {
	charprintf( ch, "There are still %d mobiles left in this area.\n\r",
		    pArea->nmobile );
	return;
    }
    if( !pArea->order )
    {
	send_to_char( "No need to overtake, no-one controls this area.\n\r", ch );
	return;
    }
    if( pArea->order->religion == pReligion )
    {
	send_to_char( "Your religion already controls this area.\n\r", ch );
	return;
    }
    for( token = ch->in_room->contents; token; token = token->next_content )
    {
	if( !token->deleted
	    && token->pIndexData->vnum == pArea->order->religion->token )
	{
	    extract_obj( token );
	    break;
	}
    }
    if( !token )	/* clever eh, no need for extra variables */
    {
	send_to_char( "You need to be at the controlling religions token to overtake.\n\r", ch );
	return;
    }
    log_string( "Religion: %s overtaking %s for %s.",
	       ch->name, pArea->name, pReligion->name );
    wiznetf( ch, WIZ_CLAN, 0, "%s has taken %s from %s for %s.", ch->name,
	     pArea->name, pArea->order->religion->name, pReligion->name );
    sprintf( buf, "$n has shown %s&x the wrath of $g.", pArea->name );
    talk_channel( ch, buf, CHANNEL_INFO, "INFO" );
    pArea->order = NULL;
    pArea->token_room = -1;
    do_asave( NULL, "" );
    reset_area( pArea );
    return;
}


void do_holypower( CHAR_DATA *ch, const char *argument )
{
    AFFECT_DATA *af;
    char arg[MAX_INPUT_LENGTH];
    char buf[MAX_INPUT_LENGTH];
    RELIGION_SKILL *ski;

    target_name = argument = one_argument( argument, arg );
    if( IS_NPC( ch ) || !ch->pcdata->clan || !ch->pcdata->religion
	|| ch->pcdata->clan->clan_type != CLAN_ORDER
	|| ( !ch->pcdata->religion->skills && !ch->pcdata->clan->skills ) )
    {
	send_to_char( "You don't know how.\n\r", ch );
	return;
    }

    if( arg[0] == '\0' || !str_cmp( arg, "help" ) )
    {
	send_to_char( "&gYou have access to the religious skill(s):\n\r", ch );
	for( ski = ch->pcdata->religion->skills; ski; ski = ski->next )
	{
	    if( ski->level >= RANK_CLANSMAN )
		continue;
	    if( ski->level <= ch->pcdata->clan_rank )
		charprintf( ch, "    '&y%s&g'\n\r",
			    skill_table[ski->sn].name );
	}
	for( ski = ch->pcdata->clan->skills; ski; ski = ski->next )
	{
	    if( ski->level >= RANK_CLANSMAN )
		continue;
	    if( ski->level <= ch->pcdata->clan_rank )
		charprintf( ch, "    '&y%s&g'\n\r",
			    skill_table[ski->sn].name );
	}
	return;
    }

    for( ski = ch->pcdata->religion->skills; ski; ski = ski->next )
    {
	if( ski->level >= RANK_CLANSMAN )
	    continue;
	if( ski->level <= ch->pcdata->clan_rank
	    && !str_prefix( arg, skill_table[ski->sn].name ) )
	    break;
    }
    if( !ski || ski->sn <= 0 )
	for( ski = ch->pcdata->clan->skills; ski; ski = ski->next )
	{
	    if( ski->level >= RANK_CLANSMAN )
		continue;
	    if( ski->level <= ch->pcdata->clan_rank
		&& !str_prefix( arg, skill_table[ski->sn].name ) )
		break;
	}

    if( !ski || ski->sn <= 0 )
    {
	charprintf( ch, "%s hasn't given you that power.\n\r",
		    ch->pcdata->religion->god_name );
	return;
    }

    for( af = ch->affected; af; af = af->next )
    {
	/* may as well let imms use their powers a few times */
	if( af->type == gsn_religious
	    && af->location == ski->sn
	    && !af->deleted && !IS_IMMORTAL( ch ) )
	{
	    charprintf( ch, "%s doesn't favour you at this point.\n\r",
			ch->pcdata->religion->god_name );
	    return;
	}
    }

    act( "&c$n calls upon $g.&n", ch, NULL, NULL, TO_ROOM );
    SET_BIT( ch->pcdata->pc_bits, PC_BIT_RACIAL );
    if( skill_table[ski->sn].spell_fun == spell_null )
    {
	sprintf( buf, "\"%s\" %s",
		 skill_table[ski->sn].name, argument );
	interpret( ch, buf );
    }
    else
    {
	cast_spell( ch, ski->sn, argument );
    }

    REMOVE_BIT( ch->pcdata->pc_bits, PC_BIT_RACIAL );

    af = new_affect( );
    af->type = gsn_religious;
    af->level = LEVEL_HERO;
    af->location = ski->sn;
    af->modifier = 0;
    af->duration = 10 + power( 20, 5, 25 - ch->level );
    vzero( af->bitvector );
    affect_to_char( ch, af, NULL );
    free_affect( af );
    ch->wait = 2;
    return;
}


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

    return FALSE;
}


bool is_clan_enemy( CHAR_DATA *victim, CHAR_DATA *ch )
{
    if( !is_clan( ch ) || !is_clan( victim ) )
	return FALSE;
    if( ch->pcdata->clan->clan_type != CLAN_NORMAL
	|| victim->pcdata->clan->clan_type != CLAN_NORMAL )
	return FALSE;
    if( !str_str( victim->pcdata->clan->name, ch->pcdata->clan->enemies )
	|| !str_str( "All", ch->pcdata->clan->enemies ) )
	return TRUE;
    return FALSE;
}


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:
	bug( "%s had strange clan rank of %d.", ch->pcdata->clan_rank );
	break;
    case RANK_EXILED:
    case RANK_CLANSMAN:							 break;
    case RANK_CLANHERO:	 clan->clanheros--;				 break;
    case RANK_CHIEFTAIN:
	string_replace( &clan->chieftains, ch->name, "\0", FALSE );
	clan->chieftains = string_unpad( clan->chieftains );
	break;
    case RANK_OVERLORD:
	free_string( clan->overlord );
	clan->overlord = str_dup( "" );
	break;
    }

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

    return;
}


void add_to_clan( CHAR_DATA *ch, CLAN_DATA *clan, int rank )
{
    char buf[MAX_INPUT_LENGTH];

    if( IS_NPC( ch ) )
	return;

    if( is_clan( ch ) )
	remove_from_clan( ch );

    switch( rank )
    {
    default:
	bug( "Trying to set %s'n clan rank to %d.\n\r", ch->name, rank );
	return;
    case RANK_EXILED:
    case RANK_CLANSMAN:
	break;
    case RANK_CLANHERO:
	if( clan->members < clan->members / 3 )
	    bug( "%s increased to hero (%d) in clan %s.",
		       ch->name, rank, clan->name );
	clan->clanheros++;
	break;
    case RANK_CHIEFTAIN:
	if( clan->members < clan->members / 10 )
	    bug( "%s increased to chief (%d) in clan %s.",
		       ch->name, rank, clan->name );
	if( clan->chieftains[0] != '\0' )
	{
	    strcat( buf, clan->chieftains );
	    strcat( buf, " " );
	}
	strcat( buf, ch->name );
	free_string( clan->chieftains );
	clan->chieftains = string_proper( str_dup( buf ) );
	break;
    case RANK_OVERLORD:
	if( clan->overlord != NULL && clan->overlord[0] != '\0' )
	    bug( "%s increased to overlord of clan %s over %s.",
		       ch->name, clan->name, clan->overlord );
	free_string( clan->overlord );
	clan->overlord = str_dup( ch->name );
	break;
    }

    clan->members++;
    ch->pcdata->clan = clan;
    ch->pcdata->clan_rank = rank;
    if( clan->clan_type == CLAN_ORDER )
	add_karma( clan, 10 );

    return;
}


const char *rank_name( int rank, int type )
{
    if( type == CLAN_NORMAL )
    {
	switch( rank )
	{
	case RANK_OVERLORD:	return "General";
	case RANK_CHIEFTAIN:	return "Captain";
	case RANK_CLANHERO:	return "Soldier";
	case RANK_CLANSMAN:	return "Recruit";
	case RANK_EXILED:	return "Scum";
	}
    }
    else if( type == CLAN_ORDER )
    {
	switch( rank )
	{
	case RANK_OVERLORD:	return "High Priest";
	case RANK_CHIEFTAIN:	return "Priest";
	case RANK_CLANHERO:	return "Initiate";
	case RANK_CLANSMAN:	return "Believer";
	case RANK_EXILED:	return "Sinner";
	}
    }
    else if( type == CLAN_GUILD )
    {
	switch( rank )
	{
	case RANK_OVERLORD:	return "Grand Master";
	case RANK_CHIEFTAIN:	return "Master";
	case RANK_CLANHERO:	return "Adept";
	case RANK_CLANSMAN:	return "Student";
	case RANK_EXILED:	return "Exile";
	}
    }
    return "none";
}


void do_clan( CHAR_DATA *ch, const char *argument )
{
    char arg[MAX_INPUT_LENGTH];

    if( !str_prefix( argument, "consider" ) && !str_prefix( "con", argument ) )
    {
	clan_consider( ch, argument );
	return;
    }

    if( !is_clan( ch ) )
    {
	send_to_char( "You don't belong to clan, guild or order.\n\r", ch );
	return;
    }
    argument = one_argument( argument, arg );

    if( !str_prefix( arg, "info" ) )
	clan_info( ch, argument );
    else if( !str_prefix( arg, "donate" ) )
	clan_donate( ch, argument );
    else if( !str_prefix( arg, "demote" ) )
	clan_demote( ch, argument );
    else if( !str_cmp( arg, "exile" ) )
	clan_exile( ch, argument );
    else if( !str_cmp( arg, "holywar" ) )
	clan_holywar( ch, argument );
    else if( !str_prefix( arg, "initiate" ) )
	clan_initiate( ch, argument );
    else if( !str_prefix( arg, "list" ) )
	interpret( ch, argument );
    else if( !str_prefix( arg, "peace" ) )
	clan_peace( ch, argument );
    else if( !str_prefix( arg, "promote" ) )
	clan_promote( ch, argument );
    else if( !str_prefix( arg, "recall" ) )
	do_recall( ch, "|clan|" );
    else if( !str_prefix( arg, "talk" ) )
	do_clantalk( ch, argument );
    else if( !str_cmp( arg, "war" ) )
	clan_war( ch, argument );
    else
	send_to_char(
	    "Clan options are:\n\r"
	    "info demote exile initiate list peace promote recall talk war\n\r", ch );
}


void clan_donate( CHAR_DATA *ch, const char *argument )
{
    CLAN_DATA *order = ch->pcdata->clan;
    char arg[MAX_INPUT_LENGTH];
    int amnt;

    if( order->clan_type != CLAN_ORDER )
    {
	charprintf( ch, "Donating money to your %s gives no benefit.\n\r",
		    flag_string( clan_type_flags, &order->clan_type ) );
	return;
    }

    if( ch->pcdata->clan_rank < RANK_CHIEFTAIN )
    {
	charprintf( ch, "Please redirect donations to a %s.\n\r",
		    rank_name( RANK_CHIEFTAIN, CLAN_ORDER ) );
	return;
    }

    argument = one_argument( argument, arg );

    if( argument[0] == '\0' || arg[0] == '\0' || !is_number( arg )
	|| ( str_cmp( argument, "gold" ) && str_cmp( argument, "quest" ) ) )
    {
	send_to_char( "Usage: order donate <amount> gold|quest\n\r", ch );
	return;
    }

    amnt = atoi( arg );
    if( amnt <= 0 )
    {
	send_to_char( "How generous of you!\n\r", ch );
	return;
    }

    if( !str_cmp( argument, "quest" ) )
    {
	if( amnt > ch->pcdata->quest->score )
	{
	    send_to_char( "You don't quite have that much.\n\r", ch );
	    return;
	}

	ch->pcdata->quest->score -= amnt;
	add_karma( order, amnt );
    }
    else
    {
	if( amnt > ch->gold )
	{
	    send_to_char( "You aren't carrying that much gold.\n\r", ch );
	    return;
	}

	ch->gold -= amnt;
	add_karma( order, amnt / ( ch->level * 100 ) );
    }
    send_to_char( "&gYour donation is much appreciated!&n\n\r", ch );
}


void clan_power( CHAR_DATA *ch, const char *argument )
{
    AFFECT_DATA *af;
    char arg[MAX_INPUT_LENGTH];
    char buf[MAX_INPUT_LENGTH];
    RELIGION_SKILL *ski;

    target_name = argument = one_argument( argument, arg );
    if( IS_NPC( ch ) || !ch->pcdata->clan || !ch->pcdata->clan->skills )
    {
	send_to_char( "You don't know how.\n\r", ch );
	return;
    }

    if( arg[0] == '\0' || !str_cmp( arg, "help" ) )
    {
	send_to_char( "&gYou have access to the clan skill(s):\n\r", ch );
	for( ski = ch->pcdata->clan->skills; ski; ski = ski->next )
	{
	    if( ski->level >= RANK_CLANSMAN )
		continue;
	    if( ski->level <= ch->pcdata->clan_rank )
		charprintf( ch, "    '&y%s&g'\n\r",
			    skill_table[ski->sn].name );
	}
	return;
    }

    for( ski = ch->pcdata->clan->skills; ski; ski = ski->next )
    {
	if( ski->level >= RANK_CLANSMAN )
	    continue;
	if( ski->level <= ch->pcdata->clan_rank
	    && !str_prefix( arg, skill_table[ski->sn].name ) )
	    break;
    }

    if( !ski || ski->sn <= 0 )
    {
	charprintf( ch, "Your clan hasn't been given that power.\n\r",
		    ch->pcdata->religion->god_name );
	return;
    }

    for( af = ch->affected; af; af = af->next )
    {
	/* may as well let imms use their powers a few times */
	if( af->type == gsn_religious
	    && af->location == ski->sn
	    && !af->deleted && !IS_IMMORTAL( ch ) )
	{
	    send_to_char( "Your power for that skillhas been used up.\n\r",
			  ch );
	    return;
	}
    }

    SET_BIT( ch->pcdata->pc_bits, PC_BIT_RACIAL );
    if( skill_table[ski->sn].spell_fun == spell_null )
    {
	sprintf( buf, "\"%s\" %s",
		 skill_table[ski->sn].name, argument );
	interpret( ch, buf );
    }
    else
    {
	cast_spell( ch, ski->sn, argument );
    }

    REMOVE_BIT( ch->pcdata->pc_bits, PC_BIT_RACIAL );

    af = new_affect( );
    af->type = gsn_religious;
    af->level = LEVEL_HERO;
    af->location = ski->sn;
    af->modifier = 0;
    af->duration = 10 + power( 20, 5, 25 - ch->level );
    vzero( af->bitvector );
    affect_to_char( ch, af, NULL );
    free_affect( af );
    ch->wait = 2;
    return;
}


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

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

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

    if( 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;

    if( clan->clan_type == CLAN_GUILD && clan->class != victim->class )
    {
	send_to_char( "You may only initiate those of your class.\n\r", ch );
	return;
    }
    else if( clan->clan_type == CLAN_ORDER
	     && clan->religion != victim->pcdata->religion )
    {
	send_to_char( "You may only initiate followers of your own religion.\n\r", ch );
	return;
    }

    add_to_clan( victim, clan, RANK_CLANSMAN );

    log_string( "Clan %s: initiated %s to %s.",
	       ch->name, victim->name, clan->name  );
    wiznetf( ch, WIZ_CLAN, 0, "%s has initiated %s to the %s of %s.",
	     ch->name, victim->name,
	     flag_string( clan_type_flags, &clan->clan_type ), clan->name );
    charprintf( victim, "%s has initiated you into the %s of %s!\n\r",
		PERS( victim, ch ),
		flag_string( clan_type_flags, &clan->clan_type ), clan->name );
    charprintf( victim, "Welcome and remember to follow %s's motto:\n\r",
		clan->name );
    charprintf( victim, "%s\n\r", clan->motto );

    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;
}


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

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

    if( 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, argument ) )
	|| IS_NPC( victim ) || victim == ch || victim->level > ch->level + 10 )
    {
	send_to_char( "They aren't here.\n\r", ch );
	return;
    }

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

    log_string( "Clan %s: exiling %s from %s",
	       ch->name, victim->name, clan->name  );
    wiznetf( ch, WIZ_CLAN, 0, "%s has exiled %s from the %s of %s.",
	     ch->name, victim->name,
	     flag_string( clan_type_flags, &clan->clan_type ), clan->name  );

    remove_from_clan( victim );		/* easier this way */
    add_to_clan( victim, clan, RANK_EXILED );

    charprintf( victim, "You have been exiled from %s!\n\r", clan->name );
    send_to_char( "All will shun you until you seek forgiveness from your god.\n\r",
		  victim );
    act( "You have exiled $N from $t!", ch, clan->name, victim, TO_CHAR );
    save_char_obj( victim );
}


void clan_promote( CHAR_DATA *ch, const char *argument )
{
    CHAR_DATA *victim;
    CLAN_DATA *clan;
    int	       newrank;

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

    if( 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, argument ) )
	|| IS_NPC( victim ) || victim == ch )
    {
	send_to_char( "They aren't here.\n\r", 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:
	break;
    case RANK_CLANSMAN:
	if( clan->clanheros >= clan->members / 3 )
	{
	    charprintf(
		ch, "You may have only 1 %s per 3 %s.\n\r",
		rank_name( RANK_CLANHERO, clan->clan_type ),
		rank_name( RANK_CLANSMAN, clan->clan_type ) );
	    return;
	}
	break;
    case RANK_CLANHERO:
	if( clan->members < 10 )
	{
	    charprintf(
		ch, "You need to have 9 %ss before you can have a %s.\n\r",
		rank_name( RANK_CLANHERO, clan->clan_type ),
		rank_name( RANK_CHIEFTAIN, clan->clan_type ) );
	    return;
	}
	break;
    case RANK_CHIEFTAIN:
    case RANK_OVERLORD:
	send_to_char( "You may not promote any further that person.\n\r", ch );
	return;
    }

    newrank = victim->pcdata->clan_rank + 1;
    remove_from_clan( victim );
    add_to_clan( victim, clan, newrank );

    log_string( "Clan %s: promoting %s to %s in %s",
	       ch->name, victim->name,
	       rank_name( newrank, clan->clan_type ), clan->name );
    wiznetf( ch, WIZ_CLAN, 0, "%s has promoted %s to the rank of %s.",
	     ch->name, victim->name,
	     rank_name( newrank, clan->clan_type ) );

    charprintf( victim, "%s finds you worthy and has promoted you!",
		ch->name );
    charprintf( victim, "You are now a %s of the %s %s!",
		rank_name( newrank, clan->clan_type ),
		clan->name, flag_string( clan_type_flags, &clan->clan_type ) );
    act( "You have promoted $N to $t.",
	 ch, rank_name( newrank, clan->clan_type ), victim, TO_CHAR );
    save_char_obj( victim );
    return;
}


void clan_demote( CHAR_DATA *ch, const char *argument )
{
    CHAR_DATA *victim;
    CLAN_DATA *clan;
    int	       newrank;

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

    if( 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, argument ) )
	|| IS_NPC( victim ) || victim == ch )
    {
	send_to_char( "They aren't here.\n\r", ch );
	return;
    }

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

    if( victim->pcdata->clan_rank >= ch->pcdata->clan_rank )
    {
	send_to_char( "You may not demote an equal or superior.\n\r", ch );
	return;
    }
    else if( victim->pcdata->clan_rank <= RANK_CLANSMAN )
    {
	send_to_char( "They are as low as you can demote them, use exile.\n\r",
		      ch );
	return;
    }

    newrank = victim->pcdata->clan_rank - 1;
    remove_from_clan( victim );
    add_to_clan( victim, clan, newrank );

    log_string( "Clan %s: demoting %s to %s in %s",
	       ch->name, victim->name,
	       rank_name( newrank, clan->clan_type ), clan->name );
    wiznetf( ch, WIZ_CLAN, 0, "%s has demoted %s to the rank of %s.",
	     ch->name, victim->name,
	     rank_name( newrank, clan->clan_type ) );
    charprintf( victim, "%s finds you truly unworthy and has demoted you.",
		ch->name );
    charprintf( victim, "You are now a %s, try to be more worthy of this position.",
		rank_name( newrank, clan->clan_type ) );
    act( "You have demoted $N to $t.",
	 ch, rank_name( newrank, clan->clan_type ), victim, TO_CHAR );
    save_char_obj( victim );
    return;
}


void do_leave( CHAR_DATA *ch, const char *argument )
{
    if( !str_cmp( argument, "clan" ) || !str_cmp( argument, "guild" )
	|| !str_cmp( argument, "order" ) )
    {
	CLAN_DATA *clan;
	if( !is_clan( ch ) )
	{
	    send_to_char( "You don't belong to a clan guild or order.\n\r", ch );
	    return;
	}

	clan = ch->pcdata->clan;

	if( ch->pcdata->clan_rank == RANK_OVERLORD )
	{
	    charprintf( ch, "Huh? A %s shouldn't leave his %s!\n\r",
			rank_name( RANK_OVERLORD, clan->clan_type ),
			flag_string( clan_type_flags, &clan->clan_type ) );
	    return;
	}

	remove_from_clan( ch );

	wiznetf( ch, WIZ_CLAN, get_trust( ch ), "%s has decided to leave the %s of %s.",
		 ch->name, flag_string( clan_type_flags, &clan->clan_type ),
		 clan->name );
	act( "You have left the $T $t for exile.", ch, clan->name,
	     flag_string( clan_type_flags, &clan->clan_type ), TO_CHAR );
	save_char_obj( ch );
    }
    else if( !str_cmp( argument, "religion" ) )
    {
	if( IS_NPC( ch ) || !ch->pcdata->religion )
	{
	    send_to_char( "You don't need to leave nothing.\n\r", ch );
	    return;
	}
	act( "You have just forsaken $g to strike out on your own.",
	     ch, NULL, NULL, TO_CHAR );

	wiznetf( ch, WIZ_CLAN, get_trust( ch ), "%s has decided to leave %s religion.",
		 ch->name, ch->pcdata->religion->name );
	ch->pcdata->religion = NULL;
	save_char_obj( ch );
    }
    else
	send_to_char( "Choose to leave clan, guild, order or religion?\n\r", ch );
}


void clan_peace( CHAR_DATA *ch, const char *argument )
{
    CLAN_DATA *peace = NULL, *clan;
    CHAR_DATA *gch;
    bool fGroup = FALSE;
    char buf[MAX_STRING_LENGTH];

    if( argument[0] == '\0' )
    {
	send_to_char(
	    "Syntax:  clan peace group  - peace with all group.\n\r"
	    "	     clan peace <clan> - peace with <clan>.\n\r"
	    "To make peace you must have someone of that clan in your group\n\r",
	    ch );
	return;
    }
    if( !str_cmp( argument, "group" ) )
	fGroup = TRUE;
    else if( !( peace = clan_lookup( argument ) ) )
    {
	send_to_char( "That clan doesn't exist.\n\r", ch );
	return;
    }

    clan = ch->pcdata->clan;

    for( gch = ch->in_room->people; gch; gch = gch->next_in_room )
    {
	if( gch->deleted || IS_NPC( gch ) || !is_same_group( ch, gch ) )
	    continue;
	if( is_clan_enemy( gch, ch )
	    && ( gch->pcdata->clan == peace || fGroup ) )
	{
	    peace = gch->pcdata->clan;

	    string_replace( &clan->enemies, peace->name, "\0", FALSE );
	    clan->enemies = string_unpad( clan->enemies );

	    if( clan->enemies[0] == '\0' )
	    {
		free_string( clan->enemies );
		clan->enemies = str_dup( "None" );
	    }
	    log_string( "Clan: %s has made peace between %s and %s.",
		     ch->name, clan->name, peace->name );
	    wiznetf( ch, WIZ_CLAN, 0,
		     "%s has made peace between %s and %s.",
		     ch->name, clan->name, peace->name );
	    sprintf( buf, "%s has made peace between %s and %s.",
		     ch->name, clan->name, peace->name );
	    talk_channel( NULL, buf, CHANNEL_INFO, "INFO" );
	    sprintf( buf, "%s have just made peace with us.", clan->name );
	    do_clantalk( gch, buf );
	    sprintf( buf, "We have just made peace with %s.", peace->name );
	    do_clantalk( ch, buf );
	}
    }
    return;
}


void clan_holywar( CHAR_DATA *ch, const char *argument )
{
    CLAN_DATA *order;
    CHAR_DATA *rch;
    char buf[MAX_INPUT_LENGTH];
    bool other = FALSE;

    order = ch->pcdata->clan;

    if( order->clan_type != CLAN_ORDER )
    {
	send_to_char( "Only religious orders may declare holy war.\n\r", ch );
	return;
    }

    if( ch->pcdata->clan_rank < RANK_OVERLORD )
    {
	send_to_char( "You may rant and rave, but no-one will take any notice.\n\r", ch );
	return;
    }

    if( IS_SET( SysInfo->flags, SYSINFO_HOLYWAR ) )
    {
	send_to_char( "A Holy War already rages all around you!\n\r", ch );
	return;
    }
    if( battle_min || battle_max )
    {
	send_to_char( "Everyone is a little too occupied with a battle.\n\r", ch );
	return;
    }

    SET_BIT( SysInfo->flags, SYSINFO_HOLYWAR );
    for( rch = char_list; rch; rch = rch->next )
    {
	if( !rch->deleted && !IS_NPC( rch ) && rch->pcdata->clan
	    && rch->pcdata->clan->clan_type == CLAN_ORDER )
	{
	    xSET_BIT( rch->act, PLR_BATTLE );
	    if( rch->pcdata->religion != order->religion )
		other = TRUE;
	}
    }
    if( !other )
    {
	send_to_char( "Sadly, there are no infidels to burn.\n\r", ch );
	for( rch = char_list; rch; rch = rch->next )
	    if( !IS_NPC( rch ) )
		xSET_BIT( rch->act, PLR_BATTLE );
	REMOVE_BIT( SysInfo->flags, SYSINFO_HOLYWAR );
	return;
    }
    add_karma( order, -100 );

    sprintf( buf, "%s has declared the %s religion will burn all unbelievers!",
	     ch->name, order->religion->name );
    wiznet( ch, WIZ_CLAN, 0, buf );
    log_string( buf );

    sprintf( buf, "%s has declared that %s are on a Holy War!",
	     ch->name, order->name );
    talk_channel( NULL, buf, CHANNEL_INFO, "INFO" );

    sprintf( buf, "All those heathens will feel the wrath of %s!",
	     order->religion->god_name );
    do_clantalk( ch, buf );

    return;
}


void clan_war( CHAR_DATA *ch, const char *argument )
{
    CLAN_DATA *clan, *war;
    char buf[MAX_INPUT_LENGTH];

    if( ch->pcdata->clan_rank < RANK_CHIEFTAIN )
    {
	send_to_char( "You can't declare war on another clan.\n\r", ch );
	return;
    }

    clan = ch->pcdata->clan;

    if( !( war = clan_lookup( argument ) ) )
    {
	send_to_char( "War against which clan?\n\r", ch );
	return;
    }

    if( clan->clan_type != CLAN_NORMAL || war->clan_type != CLAN_NORMAL )
    {
	send_to_char( "Only regular clans can participate in wars.\n\r", ch );
	return;
    }

    buf[0] = '\0';
    if( str_str( clan->enemies, "None" ) != '\0' )
    {
	string_replace( &clan->enemies, "None", "\0", FALSE );
	clan->enemies = string_unpad( clan->enemies );
    }
    if( clan->enemies[0] != '\0' )
    {
	strcat( buf, clan->enemies );
	strcat( buf, " " );
    }
    strcat( buf, capitalize( war->name ) );
    free_string( clan->enemies );
    clan->enemies = string_proper( str_dup( buf ) );
    sprintf( buf, "%s has just set %s to war against %s.",
	     ch->name, clan->name, war->name );
    wiznet( ch, WIZ_CLAN, 0, buf );
    log_string( buf );
    sprintf( buf, "%s has declared that %s are at war with %s!",
	     ch->name, clan->name, war->name );
    talk_channel( NULL, buf, CHANNEL_INFO, "INFO" );
    sprintf( buf, "We are now at war with %s!", war->name );
    do_clantalk( ch, buf );
    return;
}


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

    clan = ch->pcdata->clan;
    send_to_char( LINE_SEPARATOR, ch );
    show_clan( ch, clan );
    send_to_char( LINE_SEPARATOR, ch );
}


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

    bprintf( buf, "&y%-14.14s &b[&c%s&b] &n%s&n\n\r",
	     capitalize( flag_string( clan_type_flags, &clan->clan_type ) ),
	     clan->name, clan->display_name );
    if( clan->clan_type == CLAN_ORDER )
    {
	bprintf( buf, "&gReligion       &b[&c%s&b]&n\n\r",
		 clan->religion ? clan->religion->name : "NONE!" );
	bprintf( buf, "&gKarma          &b[&c%d&b]&n\n\n",
		 clan->karma );
    }
    else if( clan->clan_type == CLAN_GUILD )
	bprintf( buf, "&gClass          &b[&c%s&b]&n\n\r",
		 clan->class >= 0 ? class_table[clan->class].name : "NONE!" );
    bprintf( buf, "&gMotto&n\n\r    %s&n\n\r", clan->motto );
    bprintf( buf, "&gStory\n\r&w... %s ...&n\n\r", clan->description );
    bprintf( buf, "&gRules/Restrictions\n\r&w%s&n\n\r", clan->rules );
    bprintf( buf, "&gEnemies        &b[&c%s&b]&n\n\r", clan->enemies );
    bprintf( buf, "&g%-14.14s &b[&c%s&b]&n\n\r",
	     rank_name( RANK_OVERLORD, clan->clan_type ), clan->overlord );
    if( clan->chieftains && clan->chieftains[0] )
    {
	sprintf( temp, "%ss", rank_name( RANK_CHIEFTAIN, clan->clan_type ) );
	bprintf( buf, "&g%-14.14s &b[&c%s&b]&n\n\r",
		 rank_name( RANK_CHIEFTAIN, clan->clan_type ),
		 clan->chieftains );
    }
    sprintf( temp, "%ss", rank_name( RANK_CLANHERO, clan->clan_type ) );
    bprintf( buf, "&g%-14.14s &b[&c%d&b/&c%d&b]&n\n\r", temp,
	     clan->clanheros, clan->members / 3 );
    sprintf( temp, "%ss", rank_name( RANK_CLANSMAN, clan->clan_type ) );
    bprintf( buf, "&g%-14.14s &b[&c%d&b]&n\n\r", temp, clan->members );
    bprintf( buf, "&gKills          &b[&c%d&b]&n\n\r", clan->kills );
    bprintf( buf, "&gDeaths         &b[&c%d&b]&n\n\r", clan->deaths );
    bprintf( buf, "&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 )
	{
	    buffer_strcat( buf, LINE_SEPARATOR );
	    buffer_strcat( buf, "&gMembers online:&n\n\r" );
	}
	found++;
	bprintf( buf, "&y%25.25s", wch->name );
	if( found % 3 == 0 )
	    buffer_strcat( buf, "&n\n\r" );
    }
    if( found % 3 != 0 )
	buffer_strcat( buf, "&n\n\r" );
    if( found )
	bprintf( buf, "&gFound &c%d &gmember%s online.&n\n\r", found,
		 ( found == 1 ) ? "" : "s" );

    send_to_char( buf->data, ch );
    buffer_free( buf );
}


/*
 * Trimmed down version of clan_info above for those who don't
 * need to know everything.
 */
void clan_consider( CHAR_DATA *ch, const char *argument )
{
    CLAN_DATA *clan;
    BUFFER *buf;
    char temp[MAX_INPUT_LENGTH];
    DESCRIPTOR_DATA *d;
    CHAR_DATA *wch;
    int found = 0;

    if( argument[0] == '\0' || !( clan = clan_lookup( argument ) ) )
    {
	send_to_char( "Consider joining/annihilating which clan?\n\r", ch );
	return;
    }

    if( !IS_NPC( ch ) && ch->pcdata->clan == clan )
    {
	send_to_char( "This is your own clan...\n\r", ch );
	clan_info( ch, argument );
	return;
    }
    buf = buffer_new( MAX_STRING_LENGTH );

    bprintf( buf, "&y%-14.14s &b[&c%s&b] &n%s&n\n\r",
	     capitalize( flag_string( clan_type_flags, &clan->clan_type ) ),
	     clan->name, clan->display_name );
    if( clan->clan_type == CLAN_ORDER )
	bprintf( buf, "&gReligion       &b[&c%s&b]&n\n\r",
		 clan->religion ? clan->religion->name : "NONE!" );
    else if( clan->clan_type == CLAN_GUILD )
	bprintf( buf, "&gClass          &b[&c%s&b]&n\n\r",
		 clan->class >= 0 ? class_table[clan->class].name : "NONE!" );
    bprintf( buf, "&gMotto&n\n\r    %s&n\n\r", clan->motto );
    bprintf( buf, "&gStory\n\r&w... %s ...&n\n\r", clan->description );
    bprintf( buf, "&gRules/Restrictions\n\r&w%s&n\n\r", clan->rules );
    bprintf( buf, "&gEnemies        &b[&c%s&b]&n\n\r", clan->enemies );
    bprintf( buf, "&g%-14.14s &b[&c%s&b]&n\n\r",
	     rank_name( RANK_OVERLORD, clan->clan_type ), clan->overlord );
    sprintf( temp, "%ss", rank_name( RANK_CLANSMAN, clan->clan_type ) );
    bprintf( buf, "&g%-14.14s &b[&c%d&b]&n\n\r", temp, clan->members );
    for( d = descriptor_list; d; d = d->next )
    {
	wch = CH( d );
	if( wch->pcdata->clan != clan || !can_see( ch, wch ) )
	    continue;
	found++;
    }
    bprintf( buf, "&gFound &c%d &gmember%s online.&n\n\r", found,
	     ( found == 1 ) ? "" : "s" );

    send_to_char( buf->data, ch );
    buffer_free( buf );
}


void do_clans( CHAR_DATA *ch, const char *argument )
{
    CLAN_DATA *clan;
    BUFFER *buf = buffer_new( MAX_STRING_LENGTH );
    int found = 0;

    buffer_strcat( buf, "&cClan                 Chief            Members PKills PDeaths\n\r" );
    buffer_strcat( buf, LINE_SEPARATOR );
    for( clan = clan_first; clan; clan = clan->next )
    {
	if( clan->clan_type != CLAN_NORMAL )
	    continue;

	bprintf( buf, "&y%-20.20s &g%-15.15s %5d   %5d %5d\n\r",
		 clan->name, clan->overlord, clan->members,
		 clan->kills, clan->deaths );
	found++;
    }
    if( found )
    {
	buffer_strcat( buf, LINE_SEPARATOR );
	bprintf( buf, "&gThere are %d clans on Daleken.&n\n\r", found );
	send_to_char( buf->data, ch );
    }
    else
	send_to_char( "There are no clans on Daleken at the moment.\n\r", ch );
    buffer_free( buf );
}


void do_orders( CHAR_DATA *ch, const char *argument )
{
    CLAN_DATA *order;
    BUFFER *buf = buffer_new( MAX_STRING_LENGTH );
    int found = 0;

    buffer_strcat( buf, "&cOrder                High Priest  Religion     Members Karma\n\r" );
    buffer_strcat( buf, LINE_SEPARATOR );
    for( order = clan_first; order; order = order->next )
    {
	char tmp[MAX_INPUT_LENGTH];

	if( order->clan_type != CLAN_ORDER )
	    continue;

	bprintf( buf, "&y%-20.20s &g%-12.12s &r%s&g %5d %5d\n\r",
		 order->name, order->overlord,
		 order->religion ?
		 colour_strpad( tmp, order->religion->display_name, 12 ) : "NONE!",
		 order->members, order->karma );
	found++;
    }
    if( found )
    {
	buffer_strcat( buf, LINE_SEPARATOR );
	bprintf( buf, "&gThere are %d religious orders on Daleken.&n\n\r",
		 found );
	send_to_char( buf->data, ch );
    }
    else
	send_to_char( "There are no orders on Daleken at the moment.\n\r", ch );
    buffer_free( buf );
}


void do_guilds( CHAR_DATA *ch, const char *argument )
{
    CLAN_DATA *guild;
    BUFFER *buf = buffer_new( MAX_STRING_LENGTH );
    int found = 0;

    buffer_strcat( buf, "&cGuild                Grand Master Class        Members Kills  Deaths\n\r" );
    buffer_strcat( buf, LINE_SEPARATOR );
    for( guild = clan_first; guild; guild = guild->next )
    {
	if( guild->clan_type != CLAN_GUILD )
	    continue;

	bprintf( buf, "&y%-20.20s &g%-12.12s &b%-12.12s&g %5d %7d %6d\n\r",
		 guild->name, guild->overlord,
		 guild->class >= 0 ? class_table[guild->class].name : "mobs?",
		 guild->members, guild->kills, guild->deaths );
	found++;
    }
    if( found )
    {
	buffer_strcat( buf, LINE_SEPARATOR );
	bprintf( buf, "&gThere are %d guilds on Daleken.&n\n\r", found );
	send_to_char( buf->data, ch );
    }
    else
	send_to_char( "There are no guilds on Daleken at the moment.\n\r", ch );
    buffer_free( buf );
}


/*************************************************************
 * Religion editor functions.
 */
bool reledit_create( CHAR_DATA *ch, const char *argument )
{
    RELIGION_DATA *pReligion;

    pReligion = new_religion_data();
    ch->desc->pEdit = (void *)pReligion;
    log_string( "%s has just created a new religion!", ch->name );
    wiznetf( ch, WIZ_CREATE, get_trust( ch ),
	     "%s has just created a new religion!", ch->name );
    send_to_char( "Religion created.\n\r", ch );
    return TRUE;
}


bool reledit_name( CHAR_DATA *ch, const char *argument )
{
    RELIGION_DATA *pReligion;

    EDIT_RELIGION( ch, pReligion );

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

    free_string( pReligion->name );
    pReligion->name = str_dup( argument );

    send_to_char( "Name set.\n\r", ch );
    return TRUE;
}


bool reledit_display( CHAR_DATA *ch, const char *argument )
{
    RELIGION_DATA *pReligion;

    EDIT_RELIGION( ch, pReligion );

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

    free_string( pReligion->display_name );
    pReligion->display_name = str_dup( argument );

    send_to_char( "Display name set.\n\r", ch );
    return TRUE;
}


bool reledit_show( CHAR_DATA *ch, const char *argument )
{
    RELIGION_DATA *pReligion;
    RELIGION_SKILL *ski;
    BUFFER *buf = buffer_new( MAX_STRING_LENGTH );
    int cnt = 0;

    EDIT_RELIGION( ch, pReligion );

    bprintf( buf, "&gName:          &b[&c%s&b]&n %s&n\n\r",
	     pReligion->name, pReligion->display_name );
    bprintf( buf, "&gGod's Name:    &b[&c%s&b]&n\n\r", pReligion->god_name );
    bprintf( buf, "&gAlignment:     &b[&c%d &b- &c%d&b]&n\n\r",
	     pReligion->align_min, pReligion->align_max );
    bprintf( buf, "&gSacrifice:     &b[&c%s&b]&n\n\r",
	     flag_string( sac_event_flags, &pReligion->sac_events ) );
    bprintf( buf, "&gToken:         &b[&c%d&b]&g %s&n\n\r",
	     pReligion->token,
	     get_obj_index( pReligion->token )
	     ? ( get_obj_index( pReligion->token ) )->short_descr : "none" );
    for( ski = pReligion->skills; ski; ski = ski->next )
    {
	if( cnt++ == 0 )
	{
	    buffer_strcat(
		buf, "&b[&rNum&b]&g Skill           &b(&c--&b)&y Rank&n\n\r"
		"&B===== =============== ==================&n\n\r" );
	}
	bprintf( buf, "&b[&r%3d&b]&g %-15.15s &b(&c%2d&b)&y %s&n\n\r", cnt,
		 ski->sn > 0 ? skill_table[ski->sn].name : "ERROR!",
		 ski->level, rank_name( ski->level, CLAN_ORDER ) );
    }

    send_to_char( buf->data, ch );
    buffer_free( buf );
    return FALSE;
}


bool reledit_align( CHAR_DATA *ch, const char *argument )
{
    RELIGION_DATA *pReligion;
    char lower[MAX_STRING_LENGTH];
    char upper[MAX_STRING_LENGTH];
    int ilower;
    int iupper;

    EDIT_RELIGION( ch, pReligion );

    one_argument( one_argument( argument, lower ), upper );

    if( !is_number( lower ) || lower[0] == '\0'
	|| !is_number( upper ) || upper[0] == '\0' )
    {
	send_to_char( "Syntax:  align <#lower> <#upper>\n\r", ch );
	return FALSE;
    }

    if( ( ilower = atoi( lower ) ) > ( iupper = atoi( upper ) ) )
    {
	send_to_char( "RelEdit:	 Upper must be larger then lower.\n\r", ch );
	return FALSE;
    }

    if( ilower < -1000 || ilower > 1000 || iupper < -1000 || iupper > 1000 )
    {
	send_to_char( "RelEdit: vnum must be between -1000 and 1000.\n\r", ch );
	return FALSE;
    }

    pReligion->align_min = ilower;
    pReligion->align_max = iupper;
    send_to_char( "Alignment range set.\n\r", ch );
    return TRUE;
}


bool reledit_god( CHAR_DATA *ch, const char *argument )
{
    RELIGION_DATA *pReligion;

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

    free_string( pReligion->god_name );
    pReligion->god_name = str_dup( argument );

    send_to_char( "God name set.\n\r", ch );
    return TRUE;
}


bool reledit_token( CHAR_DATA *ch, const char *argument )
{
    RELIGION_DATA *pReligion;
    int token;

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

    token = atoi( argument );

    if( !get_obj_index( token ) )
    {
	send_to_char( "RelEdit:	 Object vnum does not exist.\n\r", ch );
	return FALSE;
    }

    pReligion->token = token;

    send_to_char( "Token object set.\n\r", ch );
    return TRUE;
}


bool reledit_addskill( CHAR_DATA *ch, const char *argument )
{
    RELIGION_DATA *pReligion;
    RELIGION_SKILL *ski;
    char level[MAX_INPUT_LENGTH];

    EDIT_RELIGION( ch, pReligion );
    argument = one_argument( argument, level );
    if( !level[0] || !is_number( level ) || !argument[0]
	|| skill_lookup( argument ) <= 0 )
    {
	send_to_char( "RelEdit: addskill <#level> <$skill>\n\r", ch );
	return FALSE;
    }
    if( atoi( level ) < RANK_NONE || atoi( level ) > RANK_OVERLORD )
    {
	charprintf( ch, "RelEdit: Level range from %d to %d.\n\r",
		    RANK_NONE, RANK_OVERLORD );
	return FALSE;
    }
    ski = new_religion_skill( );
    ski->level = atoi( level );
    ski->sn = skill_lookup( argument );
    ski->next = pReligion->skills;
    pReligion->skills = ski;

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


bool reledit_delskill( CHAR_DATA *ch, const char *argument )
{
    RELIGION_DATA *pReligion;
    RELIGION_SKILL *pSki, *pSki_next;
    int value, cnt = 0;
    char num[MAX_INPUT_LENGTH];

    EDIT_RELIGION( ch, pReligion );

    one_argument( argument, num );

    if( !is_number( num ) || num[0] == '\0' )
    {
	send_to_char( "Syntax:  delskill <#skill>\n\r", ch );
	return FALSE;
    }

    value = atoi( num );

    if( value < 0 )
    {
	send_to_char( "Only non-negative skill-numbers allowed.\n\r", ch );
	return FALSE;
    }

    if( !( pSki = pReligion->skills ) )
    {
	send_to_char( "RelEdit: Non-existant skill.\n\r", ch );
	return FALSE;
    }

    if( value == 0 )
    {
	pReligion->skills = pSki->next;
	free_religion_skill( pSki );
    }
    else
    {
	while( ( pSki_next = pSki->next ) && ( ++cnt < value ) )
	    pSki = pSki_next;
	if( pSki_next )
	{
	    pSki->next = pSki_next->next;
	    free_religion_skill( pSki_next );
	}
	else
	{
	    send_to_char( "RelEdit: Non-existant skill.\n\r", ch );
	    return FALSE;
	}
    }
    send_to_char( "Skill removed.\n\r", ch );
    return TRUE;
}


/*
 * Clan editor functions
 */
bool cedit_create( CHAR_DATA *ch, const char *argument )
{
    CLAN_DATA *pClan;

    pClan = new_clan_data();
    ch->desc->pEdit = (void *)pClan;
    log_string( "%s has just created a new clan!", ch->name );
    wiznetf( ch, WIZ_CREATE, get_trust( ch ),
	     "%s has just created a new clan!", ch->name );
    send_to_char( "Clan created.\n\r", ch );
    return TRUE;
}


bool cedit_name( CHAR_DATA *ch, const char *argument )
{
    CLAN_DATA *pClan;

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

    free_string( pClan->name );
    pClan->name = str_dup( argument );

    send_to_char( "Name set.\n\r", ch );
    return TRUE;
}


bool cedit_display( CHAR_DATA *ch, const char *argument )
{
    CLAN_DATA *pClan;

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

    free_string( pClan->display_name );
    pClan->display_name = str_dup( argument );

    send_to_char( "Display name set.\n\r", ch );
    return TRUE;
}


bool cedit_show( CHAR_DATA *ch, const char *argument )
{
    CLAN_DATA *pClan;

    EDIT_CLAN( ch, pClan );

    show_clan( ch, pClan );
    return FALSE;
}


bool cedit_motto( CHAR_DATA *ch, const char *argument )
{
    CLAN_DATA *pClan;

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

    free_string( pClan->motto );
    pClan->motto = str_dup( argument );
    pClan->motto[0] = UPPER( pClan->motto[0] );

    send_to_char( "Clan motto set.\n\r", ch );
    return TRUE;
}


bool cedit_desc( CHAR_DATA *ch, const char *argument )
{
    CLAN_DATA *pClan;

    EDIT_CLAN( ch, pClan );
    if( argument[0] == '\0' )
    {
	string_edit( ch, &pClan->description );
	return TRUE;
    }

    send_to_char( "Syntax:  desc    - line editor\n\r", ch );
    return FALSE;
}


bool cedit_rules( CHAR_DATA *ch, const char *argument )
{
    CLAN_DATA *pClan;

    EDIT_CLAN( ch, pClan );
    if( argument[0] == '\0' )
    {
	string_edit( ch, &pClan->rules );
	return TRUE;
    }

    send_to_char( "Syntax:  rules    - line editor\n\r", ch );
    return FALSE;
}


bool cedit_enemies( CHAR_DATA *ch, const char *argument )
{
    CLAN_DATA *pClan;
    char buf[MAX_STRING_LENGTH];

    EDIT_CLAN( ch, pClan );

    if( argument[0] == '\0' )
    {
	send_to_char( "Syntax:  enemies <$clan name> -toggles enemy\n\r", ch );
	send_to_char( "Syntax:  enemies All          -toggles all\n\r", ch );
	return FALSE;
    }

    argument = capitalize( argument );

    if( str_str( pClan->enemies, argument ) != '\0' )
    {
	string_replace( &pClan->enemies, argument, "\0", FALSE );
	pClan->enemies = string_unpad( pClan->enemies );

	if( pClan->enemies[0] == '\0' )
	{
	    free_string( pClan->enemies );
	    pClan->enemies = str_dup( "None" );
	}
	send_to_char( "Enemy removed.\n\r", ch );
    }
    else
    {
	buf[0] = '\0';
	if( str_str( pClan->enemies, "None" ) != '\0' )
	{
	    string_replace( &pClan->enemies, "None", "\0", FALSE );
	    pClan->enemies = string_unpad( pClan->enemies );
	}
	if( pClan->enemies[0] != '\0' )
	{
	    strcat( buf, pClan->enemies );
	    strcat( buf, " " );
	}
	strcat( buf, argument );
	free_string( pClan->enemies );
	pClan->enemies = string_proper( str_dup( buf ) );

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

    return TRUE;
}


bool cedit_recall( CHAR_DATA *ch, const char *argument )
{
    CLAN_DATA *pClan;
    char room[MAX_STRING_LENGTH];
    int value;

    EDIT_CLAN( ch, pClan );

    one_argument( argument, room );

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

    value = atoi( room );

    if( !get_room_index( value ) )
    {
	send_to_char( "CEdit:  Room vnum does not exist.\n\r", ch );
	return FALSE;
    }
    pClan->recall = value;

    send_to_char( "Recall set.\n\r", ch );
    return TRUE;
}


bool cedit_religion( CHAR_DATA *ch, const char *argument )
{
    CLAN_DATA *pClan;
    RELIGION_DATA *pRel;

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

    if( !( pRel = religion_lookup( argument ) ) )
    {
	send_to_char( "No such religion.\n\r", ch );
	return FALSE;
    }
    pClan->religion = pRel;
    send_to_char( "Religion set.\n\r", ch );
    return TRUE;
}


bool cedit_class( CHAR_DATA *ch, const char *argument )
{
    CLAN_DATA *pClan;

    EDIT_CLAN( ch, pClan );
    if( argument[0] == '\0' || !str_cmp( argument, "none" ) )
    {
	send_to_char( "Syntax:  class <class name>\n\r", ch );
	return FALSE;
    }

    if( flag_value( NULL, class_flags, argument ) != NO_FLAG )
    {
	pClan->class = flag_value( NULL, class_flags, argument );
	send_to_char( "Class set.\n\r", ch );
	return TRUE;
    }

    send_to_char( "CEdit: No such class.\n\r", ch );
    return FALSE;
}


bool cedit_leader( CHAR_DATA *ch, const char *argument )
{
    CLAN_DATA *pClan;
    CHAR_DATA *victim, *oldleader = NULL;
    char buf[MAX_INPUT_LENGTH];

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

    if( !( victim = get_char_world( ch, argument ) ) || IS_NPC( victim ) )
    {
	send_to_char( "You can't find them.\n\r", ch );
	return FALSE;
    }

    if( pClan->overlord && pClan->overlord[0]
	&& ( !( oldleader = get_char_world( ch, pClan->overlord ) )
	     || IS_NPC( oldleader ) ) )
    {
	send_to_char( "You must have the old leader logged on (use pload).\n\r", ch );
	return FALSE;
    }

    /*
     * Demote the old leader, no message.
     */
    if( oldleader )
    {
	oldleader->pcdata->clan_rank = RANK_CHIEFTAIN;
	buf[0] = '\0';
	if( pClan->chieftains[0] != '\0' )
	{
	    strcat( buf, pClan->chieftains );
	    strcat( buf, " " );
	}
	strcat( buf, oldleader->name );
	free_string( pClan->chieftains );
	pClan->chieftains = string_proper( str_dup( buf ) );
    }

    /*
     * change new leader's clan and make him appropriate rank.
     */
    if( victim->pcdata->clan )
	remove_from_clan( victim );
    free_string( pClan->overlord );
    add_to_clan( victim, pClan, RANK_OVERLORD );

    send_to_char( "Leader set.\n\r", ch );
    return TRUE;
}


bool cedit_addskill( CHAR_DATA *ch, const char *argument )
{
    CLAN_DATA *pClan;
    RELIGION_SKILL *ski;
    char level[MAX_INPUT_LENGTH];

    EDIT_CLAN( ch, pClan );
    argument = one_argument( argument, level );
    if( !level[0] || !is_number( level ) || !argument[0]
	|| skill_lookup( argument ) <= 0 )
    {
	send_to_char( "Cedit: addskill <#level> <$skill>\n\r", ch );
	return FALSE;
    }
    if( atoi( level ) < RANK_NONE || atoi( level ) > RANK_OVERLORD )
    {
	charprintf( ch, "Cedit: Level range from %d to %d.\n\r",
		    RANK_NONE, RANK_OVERLORD );
	return FALSE;
    }
    ski = new_religion_skill( );
    ski->level = atoi( level );
    ski->sn = skill_lookup( argument );
    ski->next = pClan->skills;
    pClan->skills = ski;

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


bool cedit_delskill( CHAR_DATA *ch, const char *argument )
{
    CLAN_DATA *pClan;
    RELIGION_SKILL *pSki, *pSki_next;
    int value, cnt = 0;
    char num[MAX_INPUT_LENGTH];

    EDIT_CLAN( ch, pClan );

    one_argument( argument, num );

    if( !is_number( num ) || num[0] == '\0' )
    {
	send_to_char( "Syntax:  delskill <#skill>\n\r", ch );
	return FALSE;
    }

    value = atoi( num );

    if( value < 0 )
    {
	send_to_char( "Only non-negative skill-numbers allowed.\n\r", ch );
	return FALSE;
    }

    if( !( pSki = pClan->skills ) )
    {
	send_to_char( "Cedit: Non-existant skill.\n\r", ch );
	return FALSE;
    }

    if( value == 0 )
    {
	pClan->skills = pSki->next;
	free_religion_skill( pSki );
    }
    else
    {
	while( ( pSki_next = pSki->next ) && ( ++cnt < value ) )
	    pSki = pSki_next;
	if( pSki_next )
	{
	    pSki->next = pSki_next->next;
	    free_religion_skill( pSki_next );
	}
	else
	{
	    send_to_char( "Cedit: Non-existant skill.\n\r", ch );
	    return FALSE;
	}
    }
    send_to_char( "Skill removed.\n\r", ch );
    return TRUE;
}