sunder2.1a/clan/
sunder2.1a/class/
sunder2.1a/class/bak/
sunder2.1a/doc/ideas/
sunder2.1a/gods/
sunder2.1a/i3/
sunder2.1a/log/
sunder2.1a/msgbase/
sunder2.1a/player/
sunder2.1a/src/o/
sunder2.1a/time/
/**********************************************************
 *************** S U N D E R M U D *** 2 . 0 **************
 **********************************************************
 * The unique portions of the SunderMud code as well as   *
 * the integration efforts for code from other sources is *
 * based primarily on the efforts of:                     *
 *                                                        *
 * Lotherius <aelfwyne@operamail.com> (Alvin W. Brinson)  *
 *    and many others, see "help sundermud" in the mud.   *
 **********************************************************/

#include "everything.h"

struct clan_main_type   * clan_list;

/* Boot clans */
/* This function is not fool proof, CLAN_FILE must be in correct format. */

DECLARE_DO_FUN ( do_quit );

void boot_clans ( void )
{
     FILE               *fptr;
     FILE               *fp;
     CLAN_INDEX	        *tmp = NULL;
     CLAN_INDEX         *previous = NULL;
     bool                done = FALSE;
     char               *word;
     char                buf[MAX_STRING_LENGTH];
     int                 i, version;
     int                 placeholder;

     SNP ( buf, "%sClan.LST", DATA_DIR );

     if ( ( fptr = fopen ( buf, "r" ) ) == NULL )
     {
          bugf ( "Failed to open CLAN_FILE for reading." );
          return;
     }

     clan_list = NULL;

     while (!done)
     {
          word = fread_string( fptr ); // Get the list items
          if ( !str_cmp ( word, "END" ) )
          {
               done = TRUE;
          }
          else
          {
               if ( ( fp = fopen ( word, "r" ) ) == NULL )
               {
                    SNP (buf, "Failed to open clan %s for reading.", word );
                    exit ( 1 );
               }
               version = fread_number ( fp );
               if ( version > 2 ) // Ie, 2 is our current version number.
               {
                    bugf ( "CLAN::File with version > 2, can't handle. (Found Version %d)", version );
                    exit ( 1 );
               }
               fread_to_eol ( fp ); // Get the LF
               word = fread_string ( fp );
               tmp = (struct clan_main_type *)alloc_perm(sizeof(struct clan_main_type), "clan_main_type" );
               tmp->next = NULL;
               tmp->clan_short = str_dup ( word );

               if ( clan_list == NULL )
                    clan_list = tmp;
               else
                    previous->next = tmp;  // If we get here, previous stays through the loop.
               previous = tmp;

               tmp->clan_name = fread_string ( fp );
               for (i = 0 ; i < 6 ; i++ )
                    tmp->mranks[i] = fread_string( fp );
               for (i = 0 ; i < 6 ; i++ )
                    tmp->franks[i] = fread_string( fp );
               tmp->portalto = fread_number ( fp );
               tmp->status = fread_number ( fp );
               tmp->clanpk = fread_number ( fp );
               tmp->clandie = fread_number ( fp );
               tmp->clanbank = fread_number ( fp );
               tmp->clanmtax = fread_number ( fp );
               tmp->membercount = fread_number ( fp );
               fread_to_eol (fp);

               tmp->war_a = NULL;
               tmp->war_b = NULL;

               // I leave this as an example of clanfile versioning.
               // You can delete this I'm sure since nobody has version 1 clanfiles.
               if ( version >= 2 )
               {
                    tmp->reason = fread_string ( fp );
                    tmp->demigod = fread_string ( fp );
                    tmp->pkallow = fread_number ( fp );
                    tmp->autoaccept = fread_number ( fp );
                    tmp->moveyear = fread_number ( fp );
                    tmp->demiapprove = fread_number ( fp );
                    tmp->experience = fread_number ( fp );
                    tmp->join_level = fread_number ( fp );
                    tmp->join_cost = fread_number ( fp );
                    tmp->join_minalign = fread_number ( fp );
                    tmp->join_maxalign = fread_number ( fp );
                    tmp->rank_setjoin = fread_number ( fp );
                    tmp->rank_recruit = fread_number ( fp );
                    tmp->rank_outcast = fread_number ( fp );
                    tmp->rank_promote = fread_number ( fp );
                    tmp->rank_settax = fread_number ( fp );
                    tmp->rank_demote = fread_number ( fp );
                    placeholder = fread_number ( fp );
                    tmp->rank_declare = fread_number ( fp );
                    tmp->rank_claim = fread_number ( fp );
                    tmp->rank_bounty = fread_number ( fp );
                    tmp->rank_recall = fread_number ( fp );
                    tmp->rank_move = fread_number ( fp );
               }
               else
               {
                    tmp->reason = str_dup ( "" );
                    tmp->demigod = str_dup ( "None" );
                    tmp->pkallow = FALSE;
                    tmp->autoaccept = FALSE;
                    tmp->moveyear = 0;
                    tmp->demiapprove = FALSE;
                    tmp->experience = 0;
                    tmp->join_level = 15;
                    tmp->join_cost = 0;
                    tmp->join_minalign = -1000;
                    tmp->join_maxalign = 1000;
                    tmp->rank_setjoin = RANK_LEADER;
                    tmp->rank_recruit = RANK_LEADER;
                    tmp->rank_outcast = RANK_LEADER;
                    tmp->rank_promote = RANK_LEADER;
                    tmp->rank_settax = RANK_LEADER;
                    tmp->rank_declare = RANK_LEADER;
                    tmp->rank_claim = RANK_LEADER;
                    tmp->rank_bounty = RANK_LEADER;
                    tmp->rank_recall = RANK_LEADER;
                    tmp->rank_move = RANK_LEADER;
               }
               fclose (fp);
          }
     }

     fclose ( fptr );
     return;
}

void save_one_clan ( CLAN_INDEX *tmp )
{
     char buf[256];
     FILE *fp;
     int i;

     if (tmp->nosave)
          return;

     SNP ( buf, "%s%s.clan", DATA_DIR, tmp->clan_short );
     if ( ( fp = fopen ( buf, "w" ) ) == NULL )
     {
          bugf( "Failed to open clan %s for writing.", tmp->clan_short );
          return;
     }
     fprintf (fp, "2\n" ); // Version Number
	 /* Version 1 Fields */
     fprintf (fp, "%s~\n", tmp->clan_short );
     fprintf (fp, "%s~\n", tmp->clan_name );
     for ( i = 0 ; i < 6 ; i++ )
          fprintf (fp, "%s~\n", tmp->mranks[i] );
     for (i = 0 ; i < 6 ; i++ )
          fprintf (fp, "%s~\n", tmp->franks[i] );
     fprintf (fp, "%d %d %d %d %ld %d %d\n",
              tmp->portalto, tmp->status, tmp->clanpk, tmp->clandie,
              tmp->clanbank, tmp->clanmtax, tmp->membercount );

     i = 5; // For some placeholders.
	 /* Version 2 Fields */
     fprintf (fp, "%s~", tmp->reason );
     fprintf (fp, "%s~", tmp->demigod );
     fprintf (fp, "%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n",
              tmp->pkallow, tmp->autoaccept, tmp->moveyear, tmp->demiapprove,
              tmp->experience, tmp->join_level, tmp->join_cost, tmp->join_minalign,
              tmp->join_maxalign, tmp->rank_setjoin, tmp->rank_recruit, tmp->rank_outcast,
              tmp->rank_promote, tmp->rank_settax, tmp->rank_demote, i, // i is placeholder
              tmp->rank_declare, tmp->rank_claim, tmp->rank_bounty, tmp->rank_recall,
              tmp->rank_move );

     fclose ( fp );
     return;
}

void save_clans (void)
{
     FILE               *fptr;
     CLAN_INDEX	       *tmp = NULL;
     char	buf[256];

     SNP ( buf, "%sClan.LST", DATA_DIR );

     if ( ( fptr = fopen ( buf, "w" ) ) == NULL )
     {
          bugf ( "Failed to open CLAN_FILE for writing." );
          return;
     }

     for ( tmp = clan_list; tmp != NULL; tmp = tmp->next )
     {
          if (tmp->nosave)
               continue;
          SNP ( buf, "%s%s.clan", DATA_DIR, tmp->clan_short );
          fprintf ( fptr, "%s~\n", buf );
          save_one_clan ( tmp );
     }

     fprintf (fptr, "END~" );

     fclose ( fptr );

     return;
}

void list_clans (CHAR_DATA *ch, char *argument)
{
     BUFFER		*buffer;
     CLAN_INDEX		*tmp;
     if ( IS_NPC ( ch ) )
          return;

     buffer = buffer_new(1000);

     bprintf( buffer, "{CT{che clans of {W" TXT_MUDNAME "{w\n\r" );
     bprintf( buffer, "{C={c========================================={C::{w\n\r");
     bprintf( buffer, "[Members] [Taxrate] [Victories] [Defeats] :: Name\n\r");

     for ( tmp = clan_list; tmp != NULL; tmp = tmp->next )
     {
          if ( !IS_IMMORTAL ( ch ) && ( tmp->status < CLAN_RECOGNIZED ) )
               continue;
          bprintf( buffer, "{C[{w%7d{C] {C[{w%7d{C] {C[{w%9d{C] {C[{w%7d{C] {c:: {w%s", tmp->membercount,
                   tmp->clanmtax, tmp->clanpk, tmp->clandie, tmp->clan_name );
          if (tmp->nosave)
               bprintf( buffer, "{W({RDELETE STATUS{W)" );
          if ( IS_IMMORTAL ( ch ) )
          {
               switch (tmp->status)
               {
               case CLAN_NEW:
                    bprintf ( buffer, " {GNew Clan{w" );
                    break;
               case CLAN_PROBATION:
                    bprintf ( buffer, " {ROn Probation{w" );
                    break;
               case CLAN_UNDERGROUND:
                    bprintf ( buffer, " {rUnderGround (Hidden){w" );
                    break;
               case CLAN_RECOGNIZED:
                    break;
               case CLAN_RENEW:
                    bprintf ( buffer, " {YReNew Status{w" );
                    break;
               default:
                    bprintf ( buffer, " {R{&A Bug!!{w" );
                    break;
               }
          }
          bprintf(buffer, "\n\r");
     }

     page_to_char(buffer->data, ch);
     buffer_free(buffer);

     return;
}

void do_claninfo( CHAR_DATA *ch, char *argument)
{
     CLAN_INDEX *tmp;
     CLAN_INDEX *fwtmp;
     BUFFER     *buffer;
     bool        foundwar = FALSE;
     int         i;
     
     if ( IS_NPC ( ch ) )
          return;

	 /* If in a clan, let's show our own clan first */

     if (argument[0] == '\0')
     {
          if (ch->pcdata->clan)
               tmp = ch->pcdata->clan;
          else
          {
               send_to_char("Syntax: claninfo <clan_short>\n\r", ch);
               return;
          }
     }
     else
          tmp = clan_by_short (argument);

     if (!tmp)
     {
          send_to_char("No such clan found.\n\r", ch);
          return;
     }

	 /* Now check if the user can see the clan. These rules can't work on greater or less than :(. */
	 /* Underground clans are hidden from public view. */

     if ( tmp->status == CLAN_UNDERGROUND && ( ch->pcdata->clan != tmp || !IS_IMMORTAL(ch) ) )
     {
          send_to_char ("No such clan found.\n\r", ch );
          return;
     }

     buffer = buffer_new(1000);

	 /* Okay let's show the clan stat! */

     bprintf(buffer, "{C={c======================================{C[ {wClan: {W%10s {C]{c={w\n\r",
             tmp->clan_short );
     bprintf(buffer, "   %s{x\n\r", tmp->clan_name);
     bprintf(buffer, "{C-{c----------------------------------------------------------{C-{w\n\r" );
     bprintf(buffer, "{G    %20s    %20s\n\r", "Male Ranks", "Female Ranks" );
     for (i = 5 ; i >= 0 ; i-- )   // Yeah it's backwords, sue me.
          bprintf(buffer, "{w    %20s    %20s\n\r", tmp->mranks[i], tmp->franks[i] );
     bprintf(buffer, "{x{C-{c----------------------------------------------------------{C-{w\n\r" );
     switch ( tmp->status )
     {
     case CLAN_NEW:
          bprintf ( buffer, "{RUnrecognized, New Clan.{w\n\r" );
          break;
     case CLAN_PROBATION:
          bprintf ( buffer, "{RUnrecognized, PROBATION.{w\n\r" );
          break;
     case CLAN_UNDERGROUND:
          bprintf ( buffer, "{DUnderground...{w\n\r" );
          break;
     case CLAN_RECOGNIZED:
     case CLAN_RENEW:  // Don't want non-imms to see if a clan is needing renewal
          bprintf ( buffer, "{COfficially Recognized Clan.{w\n\r" );
          break;
     default:
          bprintf ( buffer, "{WClan is experiencing a {RBUG{w.\n\r" );
          break;
     }
     if ( tmp->pkallow )
     {
          bprintf(buffer, "   {GPkill Victories: {W%d   {YPkill Defeats: {W%d{w\n\r",
                  tmp->clanpk, tmp->clandie );
     }
     bprintf(buffer, "   {GClan Experience: {W%d   {GClan DemiGod: {W%s{w\n\r",
             tmp->experience,
             tmp->demiapprove ? tmp->demigod : "None" );
     bprintf(buffer, "   {GMember Tax: {W%d   {GMember Count: {W%d{w\n\r",
             tmp->clanmtax, tmp->membercount );

     if ( IS_IMMORTAL(ch) || ch->pcdata->clan == tmp )
     {
          bprintf (buffer, "   {GBank Account     {W%d{w\n\r", tmp->clanbank );
     }

     if ( tmp->war_a || tmp->war_b )
     {
          bprintf ( buffer, "At War With: \n\r" );
          if ( tmp->war_a )
          {
               foundwar = TRUE;
               bprintf ( buffer, "   %s {W({RAgressor{W){w\n\r", tmp->war_a->clan_name );
          }
          if ( tmp->war_b )
          {
               foundwar = TRUE;
               bprintf ( buffer, "   %s {W({RAgressor{W){w\n\r", tmp->war_b->clan_name );
          }
     }
     for ( fwtmp = clan_list; fwtmp != NULL; fwtmp = fwtmp->next )
     {
          if ( ( fwtmp->war_a == tmp ) || ( fwtmp->war_b == tmp ) )
          {
               if (!foundwar)
                    bprintf ( buffer, "At War With: \n\r" );
               bprintf ( buffer, "   %s {W({YDefender{W){w\n\r", fwtmp->clan_name );
               foundwar = TRUE;
          }
     }

     bprintf(buffer, "{C={c=========================================================={C={w\n\r");
     page_to_char(buffer->data, ch);
     buffer_free(buffer);
}

// clan_war can be safely called if players aren't in a clan.
//
bool clan_war ( CHAR_DATA *ch, CHAR_DATA *victim )
{
     if ( !ch->pcdata->clan || !victim->pcdata->clan )
          return FALSE;
     if ( ( ch->pcdata->clan->war_a == victim->pcdata->clan )
          || ( ch->pcdata->clan->war_b == victim->pcdata->clan )
          || ( victim->pcdata->clan->war_a == ch->pcdata->clan )
          || ( victim->pcdata->clan->war_b == ch->pcdata->clan ) )
          return TRUE;
     return FALSE;
}

/* the order of who is who doesn't matter here */
bool is_same_clan (CHAR_DATA *ch, CHAR_DATA *victim)
{

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

	 /* Return false automatically if either (or both for that matter) are clanless */

     if ( !ch->pcdata->clan || !victim->pcdata->clan )
          return FALSE;

	 /* Return false if loner. Not a real clan. */

     if (!strcmp(ch->pcdata->clan->clan_short, "Loner") )
          return FALSE;
     if (!strcmp(victim->pcdata->clan->clan_short, "Loner") )
          return FALSE;

    /* Now do a check */

     if (!strcmp(victim->pcdata->clan->clan_short, ch->pcdata->clan->clan_short) )
          return TRUE;

	 /* Elsewise, return fasle */
     return FALSE;

}

CLAN_INDEX *clan_by_short (char *argument)
{
     CLAN_INDEX *lookup;
     bool found= FALSE;

     for ( lookup = clan_list; lookup != NULL; lookup = lookup->next )
     {
          if (!str_cmp(lookup->clan_short, argument) )
          {
               found = TRUE;
               break;
          }
     }
     if (found)
          return lookup;
     return NULL;
}

/* Immortal function to clear someone's clan pointer */
/* Not to be used in place of normal outcasting by a clan leader */

void do_declan(CHAR_DATA *ch, char *argument)
{
     CLAN_INDEX *tmp;
     CHAR_DATA *victim;

     if ( IS_NPC ( ch ) )
          return;

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

     if ( ( victim = get_char_world( ch, argument ) ) == NULL )
     {
          send_to_char( "Don't see that player.\n\r", ch );
          return;
     }

     if (IS_NPC(victim) )
     {
          send_to_char ("NPC's aren't in clans you siwwy IMM!\n\r", ch);
          return;
     }

     if (victim->pcdata->clan)
     {
          tmp = victim->pcdata->clan;
          victim->pcdata->clan->membercount--;  /* Decrement the counter */
          victim->pcdata->clan = NULL;		/* Nullify the pointer */
          victim->pcdata->clrank = -1;	/* Set Rank to null */
          send_to_char("All of a sudden, you feel that you are clanless.\n\r", victim);
          send_to_char("You have declanned the player.\n\r", ch);
          log_string( "INFO: %s declanned by %s", victim->name, ch->name);
          save_one_clan ( tmp );
         notify_message (victim, NOTIFY_CLANQUIT, TO_CLAN, tmp->clan_name);
     }
     else
          send_to_char("Your victim is already clanless.\n\r", ch);

     return;
}

/* Immortal function to set someone as a member of a clan */
/* NOT to be used in place of normal clan recruit function normally ! */
/* Sends no global notice */

void do_setclan (CHAR_DATA *ch, char *argument)
{
     CHAR_DATA   *victim;
     CLAN_INDEX  *tmp;
     char         arg1[MAX_INPUT_LENGTH];
     char         arg2[MAX_INPUT_LENGTH];

     if ( IS_NPC ( ch ) )
          return;

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

     if ( arg1[0] == '\0' || arg2[0] == '\0' )
     {
          send_to_char( "Syntax: setclan <character> <clan>.\n\r", ch );
          return;
     }
     if ( ( victim = get_char_world( ch, arg1 ) ) == NULL )
     {
          send_to_char( "Don't see that player.\n\r", ch );
          return;
     }
     if (IS_NPC(victim) )
     {
          send_to_char ("NPC's don't belong in clans you siwwy IMM!\n\r", ch);
          return;
     }
     if (victim->level < 5)
     {
          send_to_char("Players must reach level 10 before joining a clan.\n\r", ch);
          return;
     }
     if (victim->pcdata->clan)
     {
          send_to_char("That player is already in a clan!\n\r", ch);
          return;
     }
     tmp = clan_by_short( arg2 );
     if (!tmp)
     {
          send_to_char("That is not a valid clan.\n\r", ch);
          return;
     }

     victim->pcdata->clan = tmp;
     victim->pcdata->clan->membercount++;

     send_to_char("Thy will be done.\n\r", ch);

     victim->pcdata->clrank = RANK_BOTTOM;

     log_string( "INFO: %s setclanned into clan %s by %s.",
             victim->name, victim->pcdata->clan->clan_short, ch->name );

     form_to_char ( victim, "You are now a member of %s!\n\r", victim->pcdata->clan->clan_name );

     notify_message (victim, NOTIFY_CLANACCEPT, TO_CLAN, victim->pcdata->clan->clan_name);
     save_char_obj(victim);
     save_one_clan ( tmp );

     return;
}

void do_clan_tell (CHAR_DATA *ch, char *argument)
{
	 /* No NPC's */
     if (IS_NPC(ch))
          return;
     if (!ch->pcdata->clan)
     {
          send_to_char ("You do not belong to any clan.\n\r",ch);
          send_to_char ("Once you join a clan, you can use the clan channel.\n\r",ch);
          return;
     }
     if (!strcmp(ch->pcdata->clan->clan_short, "Loner") )
     {
          send_to_char("You're a loner, you can't use the clan channel.\n\r", ch);
          return;
     }
     channel_message (ch, argument, "clantalk");
     return;
}

void clan_advance (CHAR_DATA *ch, char *argument)
{
     CHAR_DATA *victim;

     if ( IS_NPC ( ch ) )
          return;

     if ( argument [0] == '\0' )
     {
          send_to_char( "Syntax: advance <character>\n\r", ch );
          return;
     }
     if ( ( victim = get_char_world( ch, argument ) ) == NULL )
     {
          send_to_char( "Don't see that player.\n\r", ch );
          return;
     }
     if (IS_NPC(victim) )
     {
          send_to_char ("NPC's don't have ranks!\n\r", ch);
          return;
     }
     if (ch == victim)
     {
          send_to_char("It isn't quite this easy.\n\r", ch);
          return;
     }
     if (!victim->pcdata->clan)
     {
          send_to_char("That player is not in a clan!\n\r", ch);
          return;
     }
     if (!ch->pcdata->clan)
     {
          send_to_char("You're not even in a clan yourself.\n\r", ch);
          return;
     }
     if (!is_same_clan (victim, ch) && !IS_IMMORTAL (ch) )
     {
          send_to_char("You are not authorized to advance this player.\n\r", ch);
          return;
     }

	 /* No is_immortal check here. Only leaders of fates therefore can set other clans ranks */

     if (ch->pcdata->clrank < ch->pcdata->clan->rank_promote )
     {
          send_to_char("You may not.\n\r", ch);
          return;
     }
     if (ch->pcdata->clrank <= victim->pcdata->clrank )
     {
          send_to_char ("You cannot promote someone that is your rank or higher.\n\r", ch );
          return;
     }

     if (victim->pcdata->clrank >= RANK_LEADER)
     {
          form_to_char ( ch, "%s is already a %s of %s.\n\r", victim->name,
                         victim->sex == 2 ? victim->pcdata->clan->franks[victim->pcdata->clrank] :
                         victim->pcdata->clan->mranks[victim->pcdata->clrank],
                         victim->pcdata->clan->clan_name );
          return;
     }

     victim->pcdata->clrank++;

     form_to_char ( ch, "%s is now a %s of %s.\n\r", victim->name,
                    victim->sex == 2 ? victim->pcdata->clan->franks[victim->pcdata->clrank] :
                    victim->pcdata->clan->mranks[victim->pcdata->clrank],
                    victim->pcdata->clan->clan_name );

     form_to_char ( victim, "You are now a %s of %s.\n\r",
                    victim->sex == 2 ? victim->pcdata->clan->franks[victim->pcdata->clrank] :
                    victim->pcdata->clan->mranks[victim->pcdata->clrank],
                    victim->pcdata->clan->clan_name );

     notify_message (victim, NOTIFY_CLANPROMOTE, TO_CLAN, victim->sex == 2 ?
                     victim->pcdata->clan->franks[victim->pcdata->clrank] :
                     victim->pcdata->clan->mranks[victim->pcdata->clrank] );
     save_char_obj(victim);
     return;
}

void clan_demote (CHAR_DATA *ch, char *argument)
{
     CHAR_DATA *victim;

     if ( IS_NPC ( ch ) )
          return;

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

     if ( ( victim = get_char_world( ch, argument ) ) == NULL )
     {
          send_to_char( "Don't see that player.\n\r", ch );
          return;
     }

     if (IS_NPC(victim) )
     {
          send_to_char ("NPC's don't have ranks!\n\r", ch);
          return;
     }

     if (!victim->pcdata->clan)
     {
          send_to_char("That player is not in a clan!\n\r", ch);
          return;
     }

     if (!ch->pcdata->clan)
     {
          send_to_char("You're not even in a clan yourself.\n\r", ch);
          return;
     }

     if (!is_same_clan (victim, ch) && !IS_IMMORTAL (ch) )
     {
          send_to_char("You are not authorized to demote this player.\n\r", ch);
          return;
     }
     if (ch == victim)
     {
          send_to_char("Sorry, can't demote yourself.\n\r", ch);
          return;
     }

     if (ch->pcdata->clrank < ch->pcdata->clan->rank_demote )
     {
          send_to_char("You may not.\n\r", ch);
          return;
     }
     if (ch->pcdata->clrank <= victim->pcdata->clrank && !IS_IMMORTAL(ch))
     {
          send_to_char ("You cannot demote someone that is your rank or higher.\n\r", ch );
          if (ch->pcdata->clrank == RANK_LEADER)
               send_to_char ("To demote another leader, you must contact an IMM.\n\r", ch);
          return;
     }

     if (victim->pcdata->clrank <= RANK_BOTTOM)
     {
          form_to_char ( ch, "%s is already a %s of %s.\n\r", victim->name,
                         victim->sex == 2 ? victim->pcdata->clan->franks[victim->pcdata->clrank] :
                         victim->pcdata->clan->mranks[victim->pcdata->clrank],
                         victim->pcdata->clan->clan_name );
          return;
     }

     victim->pcdata->clrank--;

     form_to_char ( ch, "%s is now a %s of %s.\n\r", victim->name,
                    victim->sex == 2 ? victim->pcdata->clan->franks[victim->pcdata->clrank] :
                    victim->pcdata->clan->mranks[victim->pcdata->clrank],
                    victim->pcdata->clan->clan_name );

     notify_message (victim, NOTIFY_CLANDEMOTE, TO_CLAN, victim->sex == 2 ?
                     victim->pcdata->clan->franks[victim->pcdata->clrank] :
                     victim->pcdata->clan->mranks[victim->pcdata->clrank] );

     form_to_char ( victim, "DEMOTION! You are now a %s of %s.\n\r",
              victim->sex == 2 ? victim->pcdata->clan->franks[victim->pcdata->clrank] :
              victim->pcdata->clan->mranks[victim->pcdata->clrank],
              victim->pcdata->clan->clan_name);

     save_char_obj(victim);

     return;
}

void clan_accept (CHAR_DATA *ch, char *argument)
{
     CHAR_DATA *victim;

     if ( IS_NPC ( ch ) )
          return;

     if ( argument [0] == '\0' )
     {
          send_to_char( "Syntax: advance <character>\n\r", ch );
          return;
     }
     if ( ( victim = get_char_room( ch, NULL, argument ) ) == NULL )
     {
          send_to_char( "Don't see that player in this room.\n\r", ch );
          return;
     }
     if (IS_NPC(victim) )
     {
          send_to_char ("NPC's can't join clans!\n\r", ch);
          return;
     }
     if (!ch->pcdata->clan)
     {
          send_to_char("You're not even in a clan yourself.\n\r", ch);
          return;
     }
     if (ch == victim)
     {
          send_to_char("Huh???\n\r", ch);
          return;
     }
     if (victim->pcdata->clan)
     {
          send_to_char("That player is already in a clan!\n\r", ch);
          return;
     }
     if (ch->pcdata->clrank < ch->pcdata->clan->rank_recruit )
     {
          send_to_char("You may not.\n\r", ch);
          return;
     }
     if ( !victim->pcdata->petition )
     {
          send_to_char ("They don't seem to have asked to join.\n\r", ch );
          return;
     }
     if ( victim->level < ch->pcdata->clan->join_level )
     {
          send_to_char ("They aren't high enough level to join your clan.\n\r", ch );
          send_to_char ("You aren't high enough level to join that clan.\n\r", victim );
          return;
     }
     if ( victim->gold < ch->pcdata->clan->join_cost )
     {
          send_to_char ("They don't seem to be wealthy enough to join your clan.\n\r", ch );
          send_to_char ("You aren't wealthy enough to join that clan.\n\r", victim );
          return;
     }
     if ( victim->alignment < ch->pcdata->clan->join_minalign )
     {
          send_to_char ("They aren't good enough to join your clan.\n\r", ch );
          send_to_char ("You aren't good enough to join that clan.\n\r", victim );
          return;
     }
     if ( victim->alignment > ch->pcdata->clan->join_maxalign )
     {
          send_to_char ("Their do-gooder ways wouldn't settle well in your clan.\n\r", ch );
          send_to_char ("The evil ways of that clan don't appeal to you.\n\r", victim );
          return;
     }
	 /* Okay ... go ahead and set the victim's clan pointer */

     victim->pcdata->clan = ch->pcdata->clan;
     ch->pcdata->clan->membercount++;
     victim->pcdata->clrank = RANK_BOTTOM;
     victim->pcdata->petition = NULL;

     victim->gold -= ch->pcdata->clan->join_cost;
     send_to_char("Done.\n\r", ch);
     form_to_char ( victim, "You are now a member of %s!\n\r", ch->pcdata->clan->clan_name );
     notify_message (victim, NOTIFY_CLANACCEPT, TO_CLAN, ch->pcdata->clan->clan_name);
     save_one_clan ( ch->pcdata->clan );
     save_char_obj(victim);
}

void clan_petition (CHAR_DATA *ch, char *argument)
{
     DESCRIPTOR_DATA *d;
     CLAN_INDEX      *tmp;
     CHAR_DATA       *victim;
     bool             join = FALSE;

     if ( IS_NPC ( ch ) )
          return;

     if ( argument [0] == '\0' )
     {
          send_to_char ("You must specify a clan to petition.\n\r", ch );
          return;
     }
     else if ( !str_cmp ( argument, "clear" ))
     {
          if (ch->pcdata->petition)
          {
               form_to_char ( ch, "You have decided against joining %s\n\r", ch->pcdata->petition->clan_name );
               ch->pcdata->petition = NULL;
          }
          else
               send_to_char ("You aren't petitioning to join a clan.\n\r", ch );
          return;
     }
     else if ( !str_cmp ( argument, "join" ) ) // handle autojoins
     {
          if ( !ch->pcdata->petition )
          {
               send_to_char ("You must petition a clan first.\n\r", ch );
               return;
          }
          if ( !ch->pcdata->petition->autoaccept )
          {
               send_to_char ("That clan requires a member to approve your petition.\n\r", ch );
               return;
          }
          tmp = ch->pcdata->petition;
          join = TRUE;
     }
     else
     {
          tmp = clan_by_short (argument);
          if ( !tmp )
          {
               send_to_char ( "That clan doesn't seem to exist.\n\r", ch );
               return;
          }
     }

     if (ch->pcdata->clan)
     {
          send_to_char("You're already in a clan.\n\r", ch);
          return;
     }

    /* Thanks to Dregnus (jholt@acom.us) for the autojoin fix below */
    if ( ch->pcdata->petition && join != TRUE )
    {
        send_to_char ("You have already petitioned either this or another clan.\n\r"
                      "You may clear the petition with \"petition clear\".\n\r", ch );
        return;
    }

     if ( ch->level < tmp->join_level )
     {
          send_to_char ("You aren't high enough level to join that clan.\n\r", ch );
          return;
     }
     if ( ch->gold < tmp->join_cost )
     {
          send_to_char ("You aren't wealthy enough to join that clan.\n\r", ch );
          return;
     }
     if ( ch->alignment < tmp->join_minalign )
     {
          send_to_char ("You aren't good enough to join that clan.\n\r", ch );
          return;
     }
     if ( ch->alignment > tmp->join_maxalign )
     {
          send_to_char ("The evil ways of that clan don't appeal to you.\n\r", ch );
          return;
     }

     if ( !join )
     {
         form_to_char ( ch, "You must be level %d", tmp->join_level );
         if (tmp->join_cost > 0 )
         {
             form_to_char ( ch, " and pay %d gold", tmp->join_cost );
         }
         form_to_char ( ch, " to join %s\n\r", tmp->clan_name );
         if ( tmp->join_minalign > -1000 )
         {
             form_to_char ( ch, "Minimum Alignment: %d\n\r", tmp->join_minalign );
         }
         if ( tmp->join_maxalign < 1000 )
         {
             form_to_char ( ch, "Maximum Alignment: %d\n\r", tmp->join_maxalign );
         }
         
          if (tmp->autoaccept)
          {
               form_to_char ( ch, "Good News!! %s can automatically accept you, if you like.\n\r", tmp->clan_name );
               send_to_char ( "To join this clan now, just type \"petition join\".\n\r", ch );
          }
          else
          {
               form_to_char ( ch, "You are now petitioning to join %s. Clan members have been notified.\n\r", tmp->clan_name );
               send_to_char ("This petition will last until you log off.\n\r", ch );
          }

          // Bad hack to find a member of the clan online to use to get the notify sent
          for ( d = descriptor_list; d; d = d->next )
          {
               if ( d->connected != CON_PLAYING )
                    continue;
               victim = d->original ? d->original : d->character;

               if ( victim->pcdata->clan )
               {
                    if ( victim->pcdata->clan == tmp )
                    {
                         notify_message (victim, NOTIFY_CLANPETITION, TO_CLAN, victim->name );
                         break;
                    }
               }
          }
          ch->pcdata->petition = tmp;
          return;
     }
     else // We're autojoining. Yay.
     {
          ch->pcdata->clan = ch->pcdata->petition;
          ch->pcdata->clan->membercount++;
          ch->pcdata->clrank = RANK_BOTTOM;
          ch->pcdata->petition = NULL;

          ch->gold -= tmp->join_cost;

          form_to_char ( ch, "You are now a member of %s!\n\r", ch->pcdata->clan->clan_name );

          notify_message (ch, NOTIFY_CLANACCEPT, TO_CLAN, ch->pcdata->clan->clan_name);
          save_one_clan ( ch->pcdata->clan );
          save_char_obj(ch);
     }
     return;
}

void clan_outcast(CHAR_DATA *ch, char *argument)
{
     CHAR_DATA *victim;

     if ( IS_NPC ( ch ) )
          return;
     if ( argument[0] == '\0' )
     {
          send_to_char( "Syntax: outcast <character>\n\r", ch );
          return;
     }
     if ( ( victim = get_char_world( ch, argument ) ) == NULL )
     {
          send_to_char( "Don't see that player.\n\r", ch );
          return;
     }
     if (IS_NPC(victim) )
     {
          send_to_char ("NPC's aren't in clans!\n\r", ch);
          return;
     }
     if (!ch->pcdata->clan)
     {
          send_to_char("You're not even in a clan yourself.\n\r", ch);
          return;
     }
     if (ch == victim)
     {
          send_to_char("Sorry, you can't outcast yourself.\n\rIf you are a leader and wish to leave, contact in IMM.\n\r", ch);
          return;
     }
     if (!victim->pcdata->clan)
     {
          send_to_char("That player is not in a clan!\n\r", ch);
          return;
     }
     if (!is_same_clan (victim, ch) || ch->pcdata->clrank < ch->pcdata->clan->rank_outcast )
     {
          send_to_char("You're not authorized for that.\n\r", ch);
          return;
     }
     if (victim->pcdata->clrank >= ch->pcdata->clrank)
     {
          send_to_char("You cannot outcast someone the same or higher rank than you.\n\r", ch);
     }
     notify_message (victim, NOTIFY_CLANQUIT, TO_CLAN, ch->pcdata->clan->clan_name);

     ch->pcdata->clan->membercount--;  /* Decrement the counter */
     victim->pcdata->clan = NULL;            /* Nullify the pointer */
     victim->pcdata->clrank = -1;    /* Set Rank to null */
     form_to_char ( victim, "{R%s has outcast you!!!{w", ch->name );
     form_to_char ( ch, "You have outcast %s!\n\r", victim->name );
     log_string( "CLANINFO: %s outcast by %s", victim->name, ch->name);
     save_one_clan ( ch->pcdata->clan );

     return;
}

void clan_truce ( CHAR_DATA *ch, char *argument )
{
     CLAN_INDEX *tmp = NULL;
     char buf[MIL];

     if ( IS_NPC ( ch ) )
          return;
     if ( !ch->pcdata->clan )
     {
          send_to_char ( "Who are you to be talking of war?\n\r", ch );
          return;
     }
     if ( ch->pcdata->clrank < ch->pcdata->clan->rank_declare )
     {
          send_to_char ( "Perhaps you had best consult with your superiors about this first.\n\r", ch );
          return;
     }
     if (argument[0] == '\0')
     {
          send_to_char("Syntax: clantruce <clan_short>\n\r", ch);
          return;
     }
     else
          tmp = clan_by_short (argument);
     if (!tmp)
     {
          send_to_char("No such clan found.\n\r", ch);
          return;
     }
     if ( ( tmp->war_a == ch->pcdata->clan ) || ( tmp->war_b == ch->pcdata->clan ) )
     {
          send_to_char ( "Sounds nice, but they are the ones who instigated the war.\n\r", ch );
          return;
     }
     if ( !ch->pcdata->clan->war_a && !ch->pcdata->clan->war_b )
     {
          send_to_char ( "You are not the agressor in any current warfare.\n\r", ch );
          return;
     }
     if ( ( ch->pcdata->clan->war_a != tmp ) && ( ch->pcdata->clan->war_b != tmp ) )
     {
          send_to_char ( "You aren't at war with that clan!\n\r", ch );
          return;
     }

     // clear the war
     //
     if ( ch->pcdata->clan->war_a == tmp )        // Find which pointer to free
          ch->pcdata->clan->war_a = NULL;
     else if ( ch->pcdata->clan->war_b == tmp )
          ch->pcdata->clan->war_b = NULL;

     SNP ( buf, "%s {whas ceased hostilities against %s{w.", ch->pcdata->clan->clan_name, tmp->clan_name );
     notify_message (ch, NOTIFY_CLANG, TO_ALL, buf );
     send_to_char ( "Done.\n\r", ch );

     save_one_clan ( ch->pcdata->clan );
     return;
}

void clan_declare ( CHAR_DATA *ch, char *argument )
{
     CLAN_INDEX   *tmp = NULL;
     char buf[MIL];

     if ( IS_NPC ( ch ) )
          return;
     if ( !ch->pcdata->clan )
     {
          send_to_char ( "Who are you to be talking of war?\n\r", ch );
          return;
     }
     if ( ch->pcdata->clrank < ch->pcdata->clan->rank_declare )
     {
          send_to_char ( "Perhaps you had best consult with your superiors about this first.\n\r", ch );
          return;
     }
     if ( !ch->pcdata->clan->pkallow )
     {
          send_to_char ( "Your clan's peaceful ways do not allow warfare.\n\r", ch );
          return;
     }
     if (argument[0] == '\0')
     {
          send_to_char("Syntax: clanwar <clan_short>\n\r", ch);
          return;
     }
     else
          tmp = clan_by_short (argument);
     if (!tmp)
     {
          send_to_char("No such clan found.\n\r", ch);
          return;
     }
     if ( tmp == ch->pcdata->clan )
     {
          send_to_char ( "Sad to see you think so little of your own clan.\n\r", ch );
          return;
     }
     if ( !str_cmp ( argument, "Loner" ) )
     {
          send_to_char ("Haha... Funny. Run along.\n\r", ch );
          return;
     }
     if ( !tmp->pkallow )
     {
          send_to_char ("That clan does not participate in warfare.\n\r", ch );
          return;
     }
     if ( ch->pcdata->clan->war_a && ch->pcdata->clan->war_b )
     {
          send_to_char ( "World domination is best left to the Gods.\n\r", ch );
          return;
     }
     if ( ( tmp->war_a == ch->pcdata->clan ) || ( tmp->war_b == ch->pcdata->clan ) )
     {
          send_to_char ( "You are already at war with that clan!\n\r", ch );
          return;
     }
     // Okay set the war up.
     //
     if ( !ch->pcdata->clan->war_a )        // Find which pointer is free
          ch->pcdata->clan->war_a = tmp;
     else if ( !ch->pcdata->clan->war_b )
          ch->pcdata->clan->war_b = tmp;

     SNP ( buf, "%s {whas unleashed the dogs of {RWAR{w on %s{w!!!", ch->pcdata->clan->clan_name, tmp->clan_name );
     notify_message (ch, NOTIFY_CLANG, TO_ALL, buf );
     send_to_char ( "Done.\n\r", ch );

     save_one_clan ( ch->pcdata->clan );
     return;
}

void make_clan (CHAR_DATA *ch, char *argument)
{
     CLAN_INDEX          *tmp = NULL;
     CLAN_INDEX          *previous = NULL;
     LEASE               *lease = NULL;
     char		  cbuf[MIL];
     int                  i = 0;
     int                  hq = 0;
     bool                 self = TRUE;
     char                *pc;
     bool                 fIll = TRUE;

     if ( IS_NPC (ch) )
          return;

     if ( argument [0] == '\0' )
     {
          send_to_char("You must specify a name to use for the \"short\" name of this clan.\n\r", ch);
          send_to_char("Additionally, you may type \"makeclan cost\" to find out the current costs.\n\r", ch);
          return;
     }

     if ( !str_cmp (argument, "cost" ) )
     {
          send_to_char ("The gods have declared that it shall cost the following to make a clan:\n\r", ch );
          form_to_char ( ch, "  Gold {W: {Y%d{w", mud.makecost );
          form_to_char ( ch, "    QP {W: {Y%d{w\n\r", mud.makeqp );
          form_to_char ( ch, "You must be at least level {C%d{w.\n\r", mud.makelevel );
          send_to_char ( "You must also be in the room you wish this clan's headquarters to be located.\n\r", ch );
          send_to_char ( "That may either be the City Common Room in Lukhan, or a room you have leased.\n\r", ch );
          return;
     }

     if ( (strlen (argument) > 10 ) || (strlen (argument) < 3) )
     {
          send_to_char("Clans must have a shortname greater than 3 letters, and shorter than 10.\n\r", ch);
          return;
     }

     for ( pc = argument; *pc != '\0'; pc++ )
     {
          if ( !isalpha ( *pc ) )
               fIll = FALSE;
          if ( LOWER ( *pc ) != 'i' && LOWER ( *pc ) != 'l' )
               fIll = FALSE;
     }

     if ( fIll )
     {
          send_to_char ("That name does not seem to be acceptable.\n\r"
                        "However, if you feel the system has disallowed a perfectly good name,\n\r"
                        "you may contact an admin if you like about this.\n\r", ch);
          return;
     }

     tmp = clan_by_short (argument);

     if (tmp)
     {
          send_to_char("Odd, it seems that clan already exists.\n\r", ch);
          return;
     }

     if ( IS_IMMORTAL (ch) && ch->pcdata->clan )
     {
          self = FALSE;
          send_to_char ("Assuming you are making someone else's clan, Immortal....\n\r", ch);
     }

	 /* A set of rules for mortals to be able to make a clan */

     if ( !IS_IMMORTAL (ch) )
     {
          if (ch->pcdata->clan)
          {
               send_to_char ("It seems your current clan may not like the idea.\n\r", ch);
               return;
          }
          if ( ch->pcdata->account->status < ACCT_VERIFIED )
          {
               send_to_char ("You may not make a clan until you verify your account.\n\r", ch );
               return;
          }
          if (ch->gold < mud.makecost)
          {
               send_to_char ("You don't appear to be wealthy enough to start a clan.\n\r", ch);
               form_to_char ( ch, "You would need ${Y%d{w coins to do so.\n\r", mud.makecost );
               return;
          }
          if (ch->level < mud.makelevel )
          {
               send_to_char ("It would appear that you are not well enough known to start a clan.\n\r", ch );
               form_to_char ( ch, "You need to advance to level {C%d{w first.\n\r", mud.makelevel );
               return;
          }
          if (ch->pcdata->questpoints < mud.makeqp )
          {
               send_to_char ("Questor has vetoed your attempt to make a clan.\n\r", ch );
               form_to_char ( ch, "You would need {G%d{w quest points to do so.\n\r", mud.makeqp );
               return;
          }
          if ( ch->in_room->vnum == ROOM_VNUM_TEMPLE )
          {
               send_to_char ( "Your temporary clan headquarters will be the City Common Room.\n\r", ch );
               hq = ROOM_VNUM_TEMPLE;
          }
          else
          {
               if ( IS_LEASE (ch->in_room->lease) )
               {
                    lease = ch->in_room->lease;

                    if ( IS_RENTED(lease) )
                    {
                         if ( lease->rented_by != ch->name )
                         {
                              send_to_char ("You cannot build a clan here.\n\r", ch );
                              return;
                         }
                         else
                         {
                              send_to_char ("Setting clan headquarters to this room.\n\r", ch );
                              hq = ch->in_room->vnum;
                              lease->rented_by = str_dup ("Clan"); /* Little hack */
							  /* No clan yet, can't set the pointer */
                         }
                    }
                    else
                    {
                         send_to_char ("You must lease a room to be your clan's headquarters, and be in that room, to create a clan.\n\r", ch );
                         send_to_char ("Alternatively, you can set up a clan without a headquarters. To do so, create the clan in the City Common Room of Lukhan.\n\r", ch );
                         return;
                    }
               }
               else
               {
                    send_to_char ("You must lease a room to be your clan's headquarters, and be in that room, to create a clan.\n\r", ch );
                    send_to_char ("Alternatively, you can set up a clan without a headquarters. To do so, create the clan in the City Common Room of Lukhan.\n\r", ch );
                    return;
               }
          }

          ch->gold -= mud.makecost;
          ch->pcdata->questpoints -= mud.makeqp;

          form_to_char ( ch, "Charging you ${Y%d{w coins and {G%d{w questpoints.\n\r", mud.makecost, mud.makeqp );
     }

     if ( IS_IMMORTAL (ch) )
          hq = ROOM_VNUM_TEMPLE;

     for ( tmp = clan_list; tmp != NULL; tmp = tmp->next )
          previous = tmp;

     tmp = (struct clan_main_type *)alloc_perm(sizeof(struct clan_main_type), "clan_main_type" );
     tmp->next = NULL;
     if ( clan_list == NULL )
          clan_list = tmp;
     else
          previous->next = tmp;

     previous = tmp;
     tmp->clan_short = str_dup (capitalize (argument ) );
     SNP (cbuf, "%s (New)", argument );
     tmp->clan_name = str_dup (cbuf);
     for (i = 0 ; i < 6 ; i++ )
          tmp->mranks[i] = str_dup ( "Man" );
     for (i = 0 ; i < 6 ; i++ )
          tmp->franks[i] = str_dup ( "Woman" );
     tmp->portalto = 1; 	/* No Portal Yet */
     tmp->status = CLAN_NEW;
     tmp->clanpk = 0;
     tmp->clandie = 0;
     tmp->clanbank = 0;
     tmp->clanmtax = 0;
     tmp->membercount = 0;

     tmp->reason = str_dup ("Unchecked");
     tmp->pkallow = FALSE;
     tmp->autoaccept = FALSE;
     tmp->moveyear = 0;
     tmp->demigod = str_dup ("Nobody");
     tmp->demiapprove = FALSE;
     tmp->experience = 0;
     tmp->join_level = 5; /* A good default */
     tmp->join_cost = 5000; /* ditto */
     tmp->join_minalign = -1000;
     tmp->join_maxalign = 1000;
     tmp->rank_setjoin = RANK_LEADER;
     tmp->rank_recruit = RANK_LEADER;
     tmp->rank_outcast = RANK_LEADER;
     tmp->rank_promote = RANK_LEADER;
     tmp->rank_demote = RANK_LEADER;
     tmp->rank_settax = RANK_LEADER;
     tmp->rank_declare = RANK_LEADER;
     tmp->rank_claim = RANK_LEADER;
     tmp->rank_bounty = RANK_LEADER;
     tmp->rank_recall = RANK_LEADER;
     tmp->rank_move = RANK_LEADER;
     tmp->war_a = NULL;
     tmp->war_b = NULL;

     send_to_char ("Your clan has been made!\n\r", ch );
     log_string( "[CLAN]:: %s made by %s", argument, ch->name );

     if ( hq == ROOM_VNUM_TEMPLE ) // We depend on hq to equal this if there's no lease. Make sure this doesn't break.
     {
          tmp->portalto = ROOM_VNUM_TEMPLE;
     }
     else
     {
          if ( !IS_LEASE ( lease ) )
          {
               send_to_char ( "Woops. Bugola. Null Lease-o-roonie.\n\r", ch );
               bugf ("We got a null lease creating a clan.");
               return;
          }
          tmp->portalto = ch->in_room->vnum;
          lease->clan = ch->pcdata->clan; // This depends on making sure the room is leased!
     }

     tmp->hq = ch->in_room; /* This depends on ch being in the right room (see above) */
	                        /* This includes IMMs!!! */

     if ( self )
     {
          ch->pcdata->clan = tmp;
          tmp->membercount++;
          ch->pcdata->clrank = RANK_LEADER;
          save_char_obj (ch);
          send_to_char ("You should now use the \"cedit\" command to setup your new clan.\n\r", ch );
     }
     save_clans ( ); // Need full save_clan here, so that it gets added to the list
     return;
}

void do_clandelete( CHAR_DATA *ch, char *argument)
{
     CLAN_INDEX *tmp;
     char buf[MIL];

     if ( IS_NPC (ch) )
          return;

     // Just in case someone messes with interp.c -- this is a dangerous command.
     if ( !IS_IMMORTAL ( ch ) )
     {
          bugf ( "Non-Immortal (%s) got into clan delete. Change interp.c back to the way it was or modify"
                 "do_clandelete to have security checking.\n\r", ch->name );
          return;
     }

     if (argument[0] == '\0')
     {
          send_to_char("Syntax: clandelete <argument>\n\r", ch);
          send_to_char("        Will {Wtoggle{w delete status of specified clan.\n\r", ch);
          return;
     }
     else
          tmp = clan_by_short (argument);

     if (!tmp)
     {
          send_to_char("No such clan found.\n\r", ch);
          return;
     }

     if (tmp->nosave) /* Clan is already set to nosave, ie, will be deleted */
     {
          tmp->nosave = FALSE;
          send_to_char ( "Undeleted specified clan.\n\r", ch );
     }
     else
     {
          tmp->nosave = TRUE;
          send_to_char ( "Specified clan WILL BE DELETED if not toggled by next reboot.\n\r", ch );
     }

     save_clans ( ); /* Need to save all here so that it gets deleted from the list. */

     SNP ( buf, "%s is being deleted! Oh No!\n\r", tmp->clan_name );
     notify_message (ch, NOTIFY_CLANG, TO_ALL, buf );
}

void do_clancharge(CHAR_DATA *ch, char *argument)
{
     DESCRIPTOR_DATA *d;
     CLAN_INDEX      *tmp;
     CHAR_DATA       *victim;
     char             arg2[MAX_INPUT_LENGTH];
     char             buf[MAX_STRING_LENGTH];
     int              a;

     if ( IS_NPC (ch) )
          return;

     argument = one_argument (argument, arg2);

     if (arg2[0] == '\0')
     {
          send_to_char ("Syntax: clancharge <clan> <value>\n\r", ch);
          return;
     }
     else
          tmp = clan_by_short (arg2);

     if (!tmp)
     {
          send_to_char("No such clan found!\n\r", ch );
          return;
     }

     if (!is_number(argument) )
     {
          send_to_char ("Syntax: clancharge <clan> <value>\n\r", ch );
          return;
     }

     a = atoi(argument);

     if ( a == 0 )
     {
          send_to_char ("Planning on making this free?\n\r", ch );
          return;
     }

     if ( a < 1 || a > 1000000000 )
     {
          send_to_char ("Amounts must be between 1 and 1000000000. For more, charge multiple times.\n\r", ch);
          return;
     }

     form_to_char ( ch, "Charging %d coins to %s.\n\r", a, tmp->clan_name );

     // Bad hack to find a member of the clan online to use to get the notify sent
     for ( d = descriptor_list; d; d = d->next )
     {
          if ( d->connected != CON_PLAYING )
               continue;
          victim = d->original ? d->original : d->character;

          if ( victim->pcdata->clan )
          {
               if ( victim->pcdata->clan == tmp )
               {
                    SNP ( buf, "%s has charged your clan %d coins.\n\r", ch->name, a );
                    notify_message (victim, NOTIFY_CLANG, TO_CLAN, buf );
                    break;
               }
          }
     }

     tmp->clanbank -= a;
     save_one_clan ( tmp );

     return;
}

void clan_donate ( CHAR_DATA * ch, char *argument )
{
     char      arg1[MIL];
     char      arg2[MIL];
     char      buf[MIL];
     int       value;

     if ( IS_NPC ( ch ) )
          return;

     if ( !ch->pcdata->clan )
     {
          send_to_char ("You aren't in a clan.\n\r", ch );
          return;
     }

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

     if ( arg1[0] == '\0' )
     {
          send_to_char ( "What would you like to donate?\n\r", ch  );
          return;
     }
     if ( is_number ( arg1 ) )
     {
          value = atoi ( arg1 );

          if ( value <= 0 )
          {
               send_to_char ("You can't make money by donating, sorry.\n\r", ch );
               return;
          }
          if ( value > ch->gold )
          {
               send_to_char ("But you don't have that much gold!\n\r", ch );
               return;
          }
          if ((value >= (0.75*ch->gold)) && value > 10000) /*very generous*/
          {
               send_to_char ("Your large donation is appreciated.\n\r", ch );
          }
          ch->gold -= value;
          ch->pcdata->clan->clanbank += value;

          SNP ( buf, "%s donated %d gold coins.\n\r", ch->name, value );
          notify_message (ch, NOTIFY_CLANG, TO_CLAN, buf );

          save_one_clan ( ch->pcdata->clan );
          return;
     }
     /* Arg1 isn't a number, so what are we donating? */
     else if ( !str_cmp ( arg1, "exp" ) || !str_cmp ( arg1, "xp" ) ) // Experience. Yay!
     {
          int cxp;

          if ( arg2[0] == '\0' || !is_number ( arg2 ) )
          {
               send_to_char ( "Yes, yes, but how MUCH?\n\r", ch );
               return;
          }
          value = atoi ( arg2 );
          if ( value <= 0 )
          {
               send_to_char ( "You can't earn experience by donating, sorry.\n\r", ch );
               return;
          }
          // Can only donate extra EXP from this level.
          cxp = ch->exp - ( ch->level * exp_per_level( ch, ch->pcdata->points) );
          if ( value > cxp )
          {
               form_to_char ( ch, "You may currently only donate up to %d experience points.\n\r", cxp );
               return;
          }
          ch->exp -= value;
          ch->pcdata->clan->experience += value;

          SNP ( buf, "%s donated %d {Gexperience{x.\n\r", ch->name, value );
          notify_message ( ch, NOTIFY_CLANG, TO_CLAN, buf );

          save_one_clan ( ch->pcdata->clan );
          return;
     }
     // Okay not gold and not exp, we must be donating an item.
     else
     {
          OBJ_DATA     *obj;
          CHAR_DATA    *gch;

          // Check the room first, then held
          //
          obj = get_obj_list ( ch, arg1, ch->in_room->contents );
          if ( obj == NULL )
               obj = get_obj_carry ( ch, arg1, NULL );

          if ( obj == NULL )
          {
               send_to_char ( "Couldn't find anything like that here.\n\r", ch );
               return;
          }
          // Okay we got an object, make sure it is suitable.
          if ( IS_SET ( obj->extra_flags, ITEM_NO_SAC ) || obj->owner )
          {
               send_to_char ( "That object cannot be donated.\n\r", ch );
               return;
          }

          if ( obj->in_room )
          {
               for ( gch = obj->in_room->people; gch != NULL; gch = gch->next_in_room )
                    if ( gch->on == obj )
                    {
                         act ( "$N appears to be using $p.", ch, obj, gch, TO_CHAR );
                         return;
                    }
          }

          if ( ( obj->item_type == ITEM_CORPSE_PC) || (obj->item_type == ITEM_CORPSE_NPC ) )
          {
               send_to_char ( "If your clan really needs the dead, take it to them yourself.\n\r", ch );
               return;
          }
          value = UMAX ( 1, obj->level * 4 );

          ch->pcdata->clan->clanbank += value;
          // These are generally very small, incremental amounts.... And will happen often,
          // so we aren't going to save the clan here, otherwise it could thrash the disk.
          form_to_char ( ch, "Your clan earns %d gold from the sale of %s.\n\r",
                         value, obj->short_descr );
          extract_obj ( obj );
          return;
     }
     return;
}

void clan_recognize ( CHAR_DATA *ch, char *argument )
{
     DESCRIPTOR_DATA *d;
     CHAR_DATA     *victim;
     CLAN_INDEX    *tmp;
     CLAN_INDEX    *tmpf;
     char          buf[MIL];

     if ( IS_NPC ( ch ) )
          return;
     if ( argument[0] == '\0' )
     {
          send_to_char ( "You must specify a clan name.\n\r", ch );
          return;
     }
     else
          tmp = clan_by_short (argument);
     if (!tmp)
     {
          send_to_char("No such clan found!\n\r", ch );
          return;
     }
     if ( IS_IMMORTAL ( ch ) )
     {
          if ( !tmp->demiapprove )
               send_to_char ( "Warning! The clan has no Demi-God!\n\r", ch );
          send_to_char ( "Recognizing the clan....\n\r", ch );
          tmp->status = CLAN_RECOGNIZED;
          SNP ( buf, "%s is now Recognized.", tmp->clan_name );
          notify_message ( ch, NOTIFY_CLANG, TO_ALL, buf );
     }
     else
     {
          if ( ch->pcdata->mortal )
          {
               send_to_char ( "Mere mortals cannot sponsor clans.\n\r", ch );
               return;
          }
          else if ( IS_NULLSTR ( tmp->demigod ) )
          {
               send_to_char ( "That clan must request your sponsorship first.\n\r", ch );
               return;
          }
          else if ( ch->level < 50 )
          {
               send_to_char ( "You are not powerful enough yet to sponsor a clan.\n\r", ch );
               return;
          }
          else if ( !str_cmp ( ch->name, tmp->demigod ) )
          {
               send_to_char ( "It is not you whom that clan offers its alliegiance.\n\r", ch );
               return;
          }
          for ( tmpf = clan_list; tmpf != NULL; tmpf = tmpf->next )
          {
               if ( !str_cmp ( tmpf->demigod, ch->name ) && tmpf != tmp )
               {
                    send_to_char ( "You are already sponsoring another clan. Sorry.\n\r", ch );
                    return;
               }
          }
          tmp->demiapprove = TRUE;
          send_to_char ( "You have now recognized this clan as your subjects.\n\r", ch );

          /* Try to find an online member of the clan */

          for ( d = descriptor_list; d; d = d->next )
          {
               if ( d->connected != CON_PLAYING )
                    continue;
               victim = d->original ? d->original : d->character;

               if ( victim->pcdata->clan )
               {
                    if ( victim->pcdata->clan == tmp )
                    {
                         SNP ( buf, "%s has consented to be your Clan Demi-God.\n\r", ch->name );
                         notify_message (victim, NOTIFY_CLANG, TO_CLAN, buf );
                         break;
                    }
               }
          }
     }
     save_one_clan ( tmp );
     return;
}

// Sigh... Paging breaks the display badly....
void cedit_show ( CHAR_DATA *ch, char *argument )
{
     BUFFER       *buffer;
     CLAN_INDEX   *ed = NULL;
     int           i;

     if ( IS_NPC (ch) )
          return;

     buffer = buffer_new(1024);
     ed = ch->pcdata->cedit; // To save typing :)

     bprintf ( buffer, VT_CLS );
     bprintf ( buffer, "{c----{C[ {WGeneral Clan Information {C]{c----\n\r" );
     bprintf ( buffer, "Long Name    {W: {w%s\n\r", ed->clan_name );
     bprintf ( buffer, "Short Name   {W: {w%s (Unchangeable)\n\r", ed->clan_short );
     if ( ( ch->pcdata->clrank >= RANK_LEADER) || (IS_IMMORTAL(ch) ) )
     {
          bprintf ( buffer, " (You have access to change this Clan's Long Name and Ranks)\n\r");
          bprintf ( buffer, "Rank Names, Highest to Lowest:\n\r" );
          bprintf ( buffer, "    {B%20s    {M%20s{w\n\r", "Male Ranks", "Female Ranks" ); // Yeah it's odd, sue me
          for (i = 5 ; i >= 0 ; i-- )   // Yeah it's backwards, sue me.
               bprintf(buffer, "%d   {B%20s    {M%20s{w\n\r", i, ed->mranks[i], ed->franks[i] );
     }
     bprintf ( buffer, "\n\r");
     if ( IS_IMMORTAL ( ch ) )
          bprintf ( buffer, "Portal: {C[{w%5d{C]{w  ", ed->portalto );
     if ( ( IS_IMMORTAL ( ch ) ) || (ch->pcdata->clrank >= ed->rank_settax) )
          bprintf ( buffer, "Clan Tax: {C[{w%5d{C]{w", ed->clanmtax );
     bprintf ( buffer, "\n\r" );

     if ( IS_IMMORTAL ( ch ) || ch->pcdata->clrank >= RANK_LEADER )
     {
          bprintf ( buffer, "AllowPK: {C[%s{C] {W({YIrreversible{W){w\n\r",
                    ed->pkallow ? "{RYes" : "{GNo" );
          bprintf ( buffer, "DemiGod: {C[{w%s{C] {C({wChange requires Review{C){w\n\r",
                    !IS_NULLSTR ( ed->demigod) ? ed->demigod : "Nobody" );
     }
     if ( ( IS_IMMORTAL ( ch ) ) || (ch->pcdata->clrank >= ed->rank_setjoin) )
     {
          bprintf ( buffer, "{c----{C[ {WJoining Requirements {C]{c----{w\n\r" );
          bprintf ( buffer, "Level: {C[{w%3d{C]{w  Cost {C[{w%10d{C]{w  Align {C[{r%5d{C]{w to {C[{W%5d{C]{w\n\r",
                    ed->join_level, ed->join_cost, ed->join_minalign, ed->join_maxalign );
     }
     if ( ch->pcdata->clrank == RANK_LEADER )
     {
          bprintf ( buffer, "\n\rSet Rank Names with mrank x <name>, or frank x <name>, where x is the number in the column to the left.\n\r");
          bprintf ( buffer, "\n\rAlso, to view {Wrank-based{w security, type \"ranks\".\n\r" );
     }
     send_to_char ( buffer->data, ch );
     buffer_free ( buffer );
}

void do_cedit ( CHAR_DATA *ch, char *argument )
{

     if ( IS_NPC ( ch ) )
          return;

     if ( argument[0] == '\0' || !IS_IMMORTAL (ch) )
     {
          if ( !ch->pcdata->clan )   /* Boot em' out without a message. That'll teach 'em. */
          {
               send_to_char ( "Type {YCOMMANDS{w for a list of valid commands.\n\r", ch);
               return;
          }

		  /* Make sure the person has some business being in the clan editor. */

          if ( ( !IS_IMMORTAL (ch) ) && ( ch->pcdata->clrank < ch->pcdata->clan->rank_setjoin)
               && ( ch->pcdata->clrank < ch->pcdata->clan->rank_settax )
               && ( ch->pcdata->clrank < ch->pcdata->clan->rank_move )
               && ( ch->pcdata->clrank < RANK_LEADER ) )
          {
               send_to_char ( "Type {YCOMMANDS{w for a list of valid commands.\n\r", ch );
               return;
          }

		  /* Okay... I think we can assume it's safe to let the person into the clan editor. */
		  /* For now let's just edit our own clan. */

          ch->pcdata->cedit = ch->pcdata->clan;
     }
     else
     {
          ch->pcdata->cedit = clan_by_short (argument);

          if (!ch->pcdata->cedit)
          {
               send_to_char("No such clan found!\n\r", ch );
               return;
          }

     }

     cedit_show ( ch, "" );
     send_to_char ( "\n\r{YClan Editor Commands {W:: {w", ch );

     ch->desc->connected = CON_EDIT_CLAN;
     return;
}

void handle_edit_clan ( DESCRIPTOR_DATA *d, char *argument )
{
     int          i;
     char         buf[MIL];
     char         arg2[MAX_INPUT_LENGTH];
     char         arg[MAX_INPUT_LENGTH];
     char         *argunbroke;
     char         *argorig;
     bool         changes = FALSE;
     bool         cMatch = FALSE;
     BUFFER       *buffer;
     CHAR_DATA    *ch = d->character;
     CHAR_DATA    *victim;
     CLAN_INDEX   *ed = NULL;
     CLAN_INDEX   *tmp = NULL;

     if ( !ch->pcdata->cedit)
     {
          bugf ( "%s in clanedit without a cedit pointer?", ch->name );
          return;
     }

     ed = ch->pcdata->cedit; // To save typing :)

     argorig = str_dup ( argument ); // In case we need to pass it to interpret
     argument = one_argument ( argument, arg );
     argunbroke = str_dup ( argument ); // For the couple of times below you need an unbroken argument
     argument = one_argument ( argument, arg2 );

	 /* arg is the function we're calling, argument is the data for it */

	 /*
	  * You only get to see what you can change here.
	  */

     if ( arg[0] == '\0' ) // Blank argument, let's call this "show"
     {
          cMatch = TRUE;
          cedit_show (ch, "");
          send_to_char ( "\n\r{YClan Editor Commands {W:: {w", ch );
     }
     else
     {
          buffer = buffer_new ( 1024 );
          cMatch = FALSE;
          switch ( tolower (arg[0]) )
          {
          case 'r':
               if ( !str_cmp ( arg, "ranks" ) )
               {
                    cMatch = TRUE;
                    if ( ( ch->pcdata->clrank < RANK_LEADER) && (!IS_IMMORTAL(ch) ) )
                    {
                         bprintf (buffer, "Sorry, only those of the highest rank may view this field.\n\r");
                         break;
                    }
                    bprintf ( buffer, VT_CLS );
                    bprintf ( buffer, "----[ Security ]----\n\r" );
                    bprintf ( buffer, "Minimum Ranks to perform actions:\n\r" );
                    bprintf ( buffer, "(A) Set Join Costs  : %s\n\r", ed->mranks[ed->rank_setjoin] );
                    bprintf ( buffer, "(B) Recruit Members : %s\n\r", ed->mranks[ed->rank_recruit] );
                    bprintf ( buffer, "(C) Outcast Members : %s\n\r", ed->mranks[ed->rank_outcast] );
                    bprintf ( buffer, "(D) Promote Members : %s\n\r", ed->mranks[ed->rank_promote] );
                    bprintf ( buffer, "(E) Demote Members  : %s\n\r", ed->mranks[ed->rank_demote] );
                    bprintf ( buffer, "(F) Set Tax Rate    : %s\n\r", ed->mranks[ed->rank_settax] );
                    bprintf ( buffer, "(G) Declare Wars    : %s\n\r", ed->mranks[ed->rank_declare] );
                    bprintf ( buffer, "(H) Claim Area      : %s\n\r", ed->mranks[ed->rank_claim] );
                    bprintf ( buffer, "(I) Set Bounty      : %s\n\r", ed->mranks[ed->rank_bounty] );
                    bprintf ( buffer, "(J) Can Recall      : %s\n\r", ed->mranks[ed->rank_recall] );
                    bprintf ( buffer, "(K) Move Hold       : %s\n\r", ed->mranks[ed->rank_move] );
                    bprintf ( buffer, "\n\rTo change a rank, enter the LETTER of the rank to change, and a number.\n\r"
                              "The number should be from 1 to 5, with 1 being second lowest and 5 being highest\n\r"
                              "ranks. The bottom rank is, of course, 0, however, those of this rank cannot ever\n\r"
                              "perform these actions.\n\r\n\r" );
               }
               break;
          case 'a':
               if ( !str_cmp ( arg, "a" ) )
               {
                    cMatch = TRUE;
                    if ( ENTRE(0,atoi(arg2),6 )) // Range from 1 to 5
                    {
                         ed->rank_setjoin = atoi(arg2);
                         bprintf ( buffer, "Set Join Costs :: %s", ed->mranks[ed->rank_setjoin] );
                         changes = TRUE;
                    }
                    else
                         bprintf ( buffer, "Range must be from 1 to 5. 1 being second lowest, 5 being highest.\n\r" );
               }
               else if ( !str_cmp ( arg, "autoaccept" ) )
               {
                    cMatch = TRUE;
                    if ( ed->autoaccept )
                    {
                         ed->autoaccept = FALSE;
                         bprintf ( buffer, "Turning off AUTOACCEPT. New members will have to be manually accepted now.\n\r" );
                         changes = TRUE;
                    }
                    else
                    {
                         ed->autoaccept = TRUE;
                         bprintf ( buffer, "Autoaccept turned on, those who petition will be automatically accepted now.\n\r" );
                         changes = TRUE;
                    }
               }
               else if ( !str_cmp ( arg, "align" ) || !str_cmp ( arg, "alignment" ) )
               {
                    cMatch = TRUE;
                    if ( arg2[0] == '\0' || argument[0] == '\0' )
                    {
                         bprintf ( buffer, "Syntax for alignment is :: alignment <min> <max>\n\r" );
                         break;
                    }
                    if ( ENTRE(-1001,atoi(arg2),1001) && ENTRE(-1001,atoi(argument),1001)) // Between -1000 and +1000
                    {
                         if ( atoi(arg2) >= atoi(argument) )
                         {
                              bprintf ( buffer, "Minimum alignment must be less than Maximum alignment.\n\r" );
                              break;
                         }
                         ed->join_minalign = atoi (arg2);
                         ed->join_maxalign = atoi (argument);
                         bprintf ( buffer, "Alignment Requirements :: %d Min, %d Max",
                                   ed->join_minalign, ed->join_maxalign );
                         changes = TRUE;
                    }
                    else
                         bprintf ( buffer, "Alignment must be between -1000 and 1000.\n\r" );
               }
               else if ( !str_cmp ( arg, "allowpk" ) )
               {
                    cMatch = TRUE;
                    if ( ed->status == CLAN_NEW )
                    {
                         bprintf ( buffer, "New clans may not enable PK or Warfare. You must be recognized, or go underground, first.\n\r" );
                         break;
                    }
                    if ( ed->pkallow )
                    {
                         bprintf ( buffer, "Your clan is already PK Enabled. You may not remove this flag.\n\r" );
                         break;
                    }
                    if ( arg2[0] == '\0' || str_cmp ( arg2, "ireallymeanit" ) ) // No ! here, this means it doesn't match
                    {
                         bprintf ( buffer, "To enbable PK and WarFare in your clan, you must type this command as follows:\n\r" );
                         bprintf ( buffer, "\n\rallowpk ireallymeanit\n\r\n\r" );
                         bprintf ( buffer, "By doing so, you indicate that you understand this change is {R{&IRREVERSIBLE.{x.\n\r" );
                         break;
                    }
                    ed->pkallow = TRUE;
                    bprintf ( buffer, "Good luck! It's a tough world out there!\n\r" );
                    if ( ed->status >= CLAN_RECOGNIZED )
                    {
                         SNP ( buf, "%s has announced a willingness to engage in the rough and tumble.", ed->clan_name );
                         notify_message ( ch, NOTIFY_CLANG, TO_ALL, buf );
                    }
                    else
                    {
                         SNP ( buf, "The leaders of %s meet behind closed doors to plan for warfare.", ed->clan_name );
                         notify_message ( ch, NOTIFY_CLANG, TO_CLAN, buf );
                    }
                    changes = TRUE;
                    break;
               }
               break;
          case 'b':
               if ( !str_cmp ( arg, "b" ) )
               {
                    cMatch = TRUE;
                    if ( ENTRE(0,atoi(arg2),6 )) // Range from 1 to 5
                    {
                         ed->rank_recruit = atoi(arg2);
                         bprintf ( buffer, "Recruit :: %s", ed->mranks[ed->rank_recruit] );
                         changes = TRUE;
                    }
                    else
                         bprintf ( buffer, "Range must be from 1 to 5. 1 being second lowest, 5 being highest.\n\r" );
               }
               break;
          case 'c':
               if ( !str_cmp ( arg, "commands" ) )
               {
                    cMatch = TRUE;
                    bprintf ( buffer, "Valid Commands in the Clan Editor (You may not have access to all of these):\n\r"
                              "done, frank, mrank, quit, ranks, A-K, cost, align,\n\r"
                              "allowpk, commands, demigod, name, level, autojoin\n\r");
               }
               else if ( !str_cmp ( arg, "c" ) )
               {
                    cMatch = TRUE;
                    if ( ENTRE(0,atoi(arg2),6 )) // Range from 1 to 5
                    {
                         ed->rank_outcast = atoi(arg2);
                         bprintf ( buffer, "Outcast :: %s", ed->mranks[ed->rank_outcast] );
                         changes = TRUE;
                    }
                    else
                         bprintf ( buffer, "Range must be from 1 to 5. 1 being second lowest, 5 being highest.\n\r" );
               }
               else if ( !str_cmp ( arg, "cost" ) )
               {
                    cMatch = TRUE;
                    if ( ENTRE(-1,atoi(arg2),100000000)) // Hopefully no clan will ever cost that much to join
                    {
                         ed->join_cost = atoi(arg2);
                         bprintf ( buffer, "Join Cost :: %d", ed->join_cost );
                         changes = TRUE;
                    }
                    else
                         bprintf ( buffer, "Cost out of range.\n\r" );
               }
               break;
          case 'd':
               if ( !str_cmp ( arg, "done" ) )
               {
                    cMatch = TRUE;
                    bprintf ( buffer, "Exiting Editor.\n\r" );
                    ch->desc->connected = CON_PLAYING;
                    ed = NULL;
                    ch->pcdata->cedit = NULL;
               }
               else if ( !str_cmp ( arg, "demigod" ) )
               {
                    bool already = FALSE;
                    cMatch = TRUE;

                    if ( ( victim = get_char_world ( ch, arg2 ) ) == NULL )
                    {
                         bprintf ( buffer, "I can't find anyone in the realm by that name.\n\r" );
                         break;
                    }
                    for ( tmp = clan_list; tmp != NULL; tmp = tmp->next )
                    {
                         if ( !str_cmp ( tmp->demigod, victim->name ) )
                         {
                              already = TRUE;
                         }
                    }
                    if ( already )
                    {
                         bprintf ( buffer, "That Demi-God has already sponsored a clan.\n\r" );
                         break;
                    }
                    if ( victim->level < 50 )
                    {
                         bprintf ( buffer, "A Demi-God of that low level would not make a wise counsel.\n\r"
                                   "Perhaps one level 50 or higher would do better?\n\r" );
                         break;
                    }
                    free_string ( ed->demigod );
                    ed->demigod = str_dup ( victim->name );
                    SNP ( buf, "%s has been asked to be the new Clan Demi-God.", victim->name );
                    notify_message ( ch, NOTIFY_CLANG, TO_CLAN, buf );
                    SNP ( buf, "%s requests you to become the Demi-God for %s.\n\r"
                              "To do so, type \"recognize %s\" at your prompt, if you approve of the clan.\n\r",
                              ch->name, ed->clan_name, ed->clan_short );
                    send_to_char ( buf, victim );
                    changes = TRUE;
                    break;
               }
               else if ( !str_cmp ( arg, "d" ) )
               {
                    cMatch = TRUE;
                    if ( ENTRE(0,atoi(arg2),6 )) // Range from 1 to 5
                    {
                         ed->rank_promote = atoi(arg2);
                         bprintf ( buffer, "Promote :: %s", ed->mranks[ed->rank_promote] );
                         changes = TRUE;
                    }
                    else
                         bprintf ( buffer, "Range must be from 1 to 5. 1 being second lowest, 5 being highest.\n\r" );
               }
               break;
          case 'e':
               if ( !str_cmp ( arg, "e" ) )
               {
                    cMatch = TRUE;
                    if ( ENTRE(0,atoi(arg2),6 )) // Range from 1 to 5
                    {
                         ed->rank_demote = atoi(arg2);
                         bprintf ( buffer, "Demote :: %s", ed->mranks[ed->rank_demote] );
                         changes = TRUE;
                    }
                    else
                         bprintf ( buffer, "Range must be from 1 to 5. 1 being second lowest, 5 being highest.\n\r" );
               }
               break;
          case 'f':
               if ( !str_cmp ( arg, "f" ) )
               {
                    cMatch = TRUE;
                    if ( ENTRE(0,atoi(arg2),6 )) // Range from 1 to 5
                    {
                         ed->rank_settax = atoi(arg2);
                         bprintf ( buffer, "Set Tax :: %s", ed->mranks[ed->rank_settax] );
                         changes = TRUE;
                    }
                    else
                         bprintf ( buffer, "Range must be from 1 to 5. 1 being second lowest, 5 being highest.\n\r" );
               }
               // NO BREAK... 'f': must pass straight to 'm': as the very next case!!!!!!!!!!! - Lotherius
          case 'm':
               if ( ( !str_cmp ( arg, "mrank" ) || !str_cmp ( arg, "frank" ) ) )
               {
                    cMatch = TRUE;
                    if ( ( ch->pcdata->clrank < RANK_LEADER) && (!IS_IMMORTAL(ch) ) )
                    {
                         bprintf (buffer, "Sorry, only those of the highest rank may change this field.\n\r");
                         break;
                    }
                    if ( !is_number ( arg2 ) )
                    {
                         bprintf (buffer, "Please use 'mrank x <name>' where x is a number.\n\r" );
                         break;
                    }
                    i = atoi ( arg2 );
                    if ( (i < 0 ) || ( i > 5 ) )
                    {
                         bprintf ( buffer, "Number must be from 0 (lowest rank) to 5 (highest rank).\n\r" );
                         break;
                    }
                    if ( ( strlen (argument) > 18 ) || (strlen (argument) < 4 ) )
                    {
                         bprintf ( buffer, "Rank must be from 4 to 18 characters in length.\n\r" );
                         break;
                    }
                    /* We're going to recheck our arg, to remember if we're doing male or female */
                    if ( !str_cmp ( arg, "mrank" ) )
                         ed->mranks[i] = str_dup (argument);
                    else
                         ed->franks[i] = str_dup (argument);
                    changes = TRUE;
                    bprintf ( buffer, "Rank set.\n\r" );
                    if ( ed->status == CLAN_RECOGNIZED )
                    {
                         bprintf ( buffer, "Marking your clan for Immortal Review to approve the new title.\n\r" );
                         ed->status = CLAN_RENEW;
                    }
                    break;
               }
               break;
          case 'n':
               if ( !str_cmp ( arg, "name" ) )
               {
                    cMatch = TRUE;
                    if ( argunbroke[0] == '\0' )
                    {
                         bprintf ( buffer, "Please specify a name, no longer than 20 characters and no less than 5.\n\r" );
                         break;
                    }
                    if ( ( cstrlen ( argunbroke ) > 20 ) || ( strlen ( argunbroke ) < 5 ) )
                    {
                         bprintf ( buffer, "The clan's name can be no longer than 20 characters, and no less than 5.\n\r" );
                         break;
                    }
                    // Go ahead and change the name.
                    free_string ( ed->clan_name );
                    ed->clan_name = str_dup ( argunbroke );
                    if ( ed->status == CLAN_RECOGNIZED )
                    {
                         bprintf ( buffer, "Marking your clan for Immortal Review to approve the new title.\n\r" );
                         ed->status = CLAN_RENEW;
                    }
                    // Check here in case it is an imm changing it
                    if ( ch->pcdata->clan == ed )
                    {
                         SNP ( buf, "New Clan Logo: %s{w", ed->clan_name );
                         notify_message ( ch, NOTIFY_CLANG, TO_CLAN, buf );
                    }
                    changes = TRUE;
                    break;
               }
          case 'g':
               if ( !str_cmp ( arg, "g" ) )
               {
                    cMatch = TRUE;
                    if ( ENTRE(0,atoi(arg2),6 )) // Range from 1 to 5
                    {
                         ed->rank_declare = atoi(arg2);
                         changes = TRUE;
                         bprintf ( buffer, "Declare War :: %s", ed->mranks[ed->rank_declare] );
                    }
                    else
                         bprintf ( buffer, "Range must be from 1 to 5. 1 being second lowest, 5 being highest.\n\r" );
               }
               break;
          case 'h':
               if ( !str_cmp ( arg, "h" ) )
               {
                    cMatch = TRUE;
                    if ( ENTRE(0,atoi(arg2),6 )) // Range from 1 to 5
                    {
                         ed->rank_claim = atoi(arg2);
                         changes = TRUE;
                         bprintf ( buffer, "Claim :: %s", ed->mranks[ed->rank_claim] );
                    }
                    else
                         bprintf ( buffer, "Range must be from 1 to 5. 1 being second lowest, 5 being highest.\n\r" );
               }
               break;
          case 'i':
               if ( !str_cmp ( arg, "i" ) )
               {
                    cMatch = TRUE;
                    if ( ENTRE(0,atoi(arg2),6 )) // Range from 1 to 5
                    {
                         ed->rank_bounty = atoi(arg2);
                         changes = TRUE;
                         bprintf ( buffer, "Set Bounties :: %s", ed->mranks[ed->rank_bounty] );
                    }
                    else
                         bprintf ( buffer, "Range must be from 1 to 5. 1 being second lowest, 5 being highest.\n\r" );
               }
               break;
          case 'j':
               if ( !str_cmp ( arg, "j" ) )
               {
                    cMatch = TRUE;
                    if ( ENTRE(0,atoi(arg2),6 )) // Range from 1 to 5
                    {
                         ed->rank_recall = atoi(arg2);
                         changes = TRUE;
                         bprintf ( buffer, "Can Recall :: %s", ed->mranks[ed->rank_recall] );
                    }
                    else
                         bprintf ( buffer, "Range must be from 1 to 5. 1 being second lowest, 5 being highest.\n\r" );
               }
               break;
          case 'k':
               if ( !str_cmp ( arg, "k" ) )
               {
                    cMatch = TRUE;
                    if ( ENTRE(0,atoi(arg2),6 )) // Range from 1 to 5
                    {
                         ed->rank_move = atoi(arg2);
                         changes = TRUE;
                         bprintf ( buffer, "Move Stronghold :: %s", ed->mranks[ed->rank_move] );
                    }
                    else
                         bprintf ( buffer, "Range must be from 1 to 5. 1 being second lowest, 5 being highest.\n\r" );
               }
               break;
          case 'l':
               if ( !str_cmp ( arg, "level" ) )
               {
                    cMatch = TRUE;
                    if ( ENTRE(4,atoi(arg2),(LEVEL_HERO+1) ) || IS_IMMORTAL ( ch )) // Level range 5 to 101
                    {
                         ed->join_level = atoi(arg2);
                         changes = TRUE;
                         bprintf ( buffer, "Join Level :: %d", ed->join_level );
                    }
                    else
                         bprintf ( buffer, "Range is from level 1 to %d", LEVEL_HERO );
               }
               break;
          case 'q':
               if ( !str_cmp ( arg, "quit" ) ) // Special case, we have to clean up for ourselves here
               {
                    cMatch = TRUE;
                    buffer_free ( buffer );
                    send_to_char ( "Quitting....\n\r", ch );
                    do_quit ( ch, "" );
                    return;
               }
               break;
          case 't':
               if ( !str_cmp ( arg, "tax" ) )
               {
                    cMatch = TRUE;
                    if ( ENTRE(-1,atoi(arg2),101 ) )
                    {
                         ed->clanmtax = atoi(arg2);
                         changes = TRUE;
                         SNP ( buf, "Tax Rate : %d", ed->clanmtax );
                         notify_message ( ch, NOTIFY_CLANG, TO_CLAN, buf );
                         break;
                    }
                    else
                         bprintf ( buffer, "Valid range is 0 to 100.\n\r" );
               }
               break;
          }
          if ( !cMatch )
          {
               // I don't interpret here because handling the prompt doesn't work well...
               //		  interpret ( ch, argorig );
               bprintf ( buffer, "\n\rIf you need help, type \"commands\" for a list of valid cedit commands.\n\r" );
          }
          else
          {
               if ( changes )
                    save_one_clan ( ed );
          }
          if ( ed )                  // Make sure we're still editing
               bprintf ( buffer, "\n\r{YClan Editor Commands {W:: {w" );
          send_to_char ( buffer->data, ch );
          buffer_free ( buffer );
     }
     free_string ( argunbroke );
     free_string ( argorig );
     return;
}