legend/
legend/area/
legend/player/
/*
 * Legend of Chrystancia Kingdom Code
 * Based upon code originally created by Aioros and Tracker.
 * Updated for Legend of Chrystancia by Matthew 24/05/2003
 */

#include <sys/types.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <ctype.h>
#include "merc.h"

int min_kingdom_members;
MEMBER_DATA *get_member_of_rank (MEMBER_DATA * mem, int rank);
void get_min_kingdom_members ();
void do_help args ((CHAR_DATA * ch, char *argument));

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

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

/*
                    //free_string(field);             \
*/

const   struct  kcommand_data        kcmd_table     [] =
{
    { "Initiate",    KCMD_INDUCT  },
    { "PromoteRank", KCMD_PROMOTE },
    { "DemoteRank",  KCMD_DEMOTE  },
    { "Expell",      KCMD_OUTCAST },
    { "Declare",     KCMD_DECLARE },
    { "",            KCMD_MAX     }
};

char *put_spc (char *buffer, int size, bool center)
{
   char aux[MAX_INPUT_LENGTH];
   int i, j, len;

   for (i = 0, len = 0; buffer[i] != '\0'; i++)
   {
      if (buffer[i] == '#' || buffer[i] == '^')
	 i++;
      else
	 len++;
   }

   if (center)
   {
      j = (size - len) / 2;
      i = 0;
      aux[0] = '\0';

      while (i < j)
      {
	 sprintf (aux + strlen (aux), " ");
	 i++;
      }

      strcat (aux, buffer);
      strcpy (buffer, aux);
      len += j;
   }

   while (len < size)
   {
      sprintf (buffer + strlen (buffer), " ");
      len++;
   }

   return buffer;
}

void kingdom (CHAR_DATA * ch, char *kname)
{
   MEMBER_DATA *m;
   int rank = 0;

   m = get_kingdom_char (ch->name);
   if (m != NULL)
   {
      char buf[MAX_STRING_LENGTH];

      rank = m->rank;
      if (ch->sex == SEX_MALE)
	 strcpy (buf, m->kingdom->ranks[rank - 1]);
      else if (m->kingdom->ranks[rank + 4][0] == '\0')
	 strcpy (buf, m->kingdom->ranks[rank - 1]);
      else
	 strcpy (buf, m->kingdom->ranks[rank + 4]);

      sprintf (kname, "%s#w%s of #g%s%s",
	       m->kingdom->open, buf, m->kingdom->descr, m->kingdom->close);
   }
   else
      sprintf (kname, "%s", "");

   put_spc (kname, 10, TRUE);
}

/*
 * search for the kingdom member information of one player,
 * receives the name of the player and 
 * returns NULL if the player is not in a kingdom
 */

MEMBER_DATA *get_kingdom_char (char *name)
{
   KINGDOM_DATA *k;
   MEMBER_DATA *m;

   for (k = king_first; k != NULL; k = k->next)
   {
      for (m = k->members; m != NULL; m = m->next)
	 if (!str_cmp (name, m->name))
	    return m;
   }

   return NULL;
}

void kingdom2 (CHAR_DATA * ch, char *kname)
{
   MEMBER_DATA *m;

   m = get_kingdom_char (ch->name);
   if (m != NULL)
   {

      sprintf (kname, "%s", m->kingdom->descr);
   }
   else
      sprintf (kname, "%s", "");

   put_spc (kname, 0, TRUE);
}

/*
 * Read the kingdom data file
 */

void fread_kingdom (FILE * fp)
{
   KINGDOM_DATA *kingdom;
   KINGDOM_DATA *kiter;

   int i;
   char *word;
   bool fMatch;

   if (kingdom_free == NULL)
      kingdom = alloc_perm (sizeof (*kingdom));
   else
   {
      kingdom = kingdom_free;
      kingdom_free = kingdom_free->next;
   }

   kingdom->next = NULL;
   kingdom->prev = NULL;
   kingdom->diplomacy = NULL;

   kingdom->members = NULL;
   kingdom->descr = str_dup ("");
   kingdom->close = str_dup ("");
   kingdom->open = str_dup ("");
   kingdom->name = str_dup ("");

   kingdom->memnum = 0;

   for (i = 0; i < 10; i++)
      kingdom->ranks[i] = str_dup ("");

   for (i = 0; i < 10; i++)
      kingdom->materials[i] = 0;

   for (i = 0; i < KCMD_MAX; i++)
      kingdom->cmd[i] = 1;

   kingdom->vnum[0] = 0;
   kingdom->vnum[1] = 0;
   kingdom->krecall = 0;
   kingdom->helper = 0;

   if (king_first == NULL)
      king_first = kingdom;

   if (king_last != NULL)
   {
      king_last->next = kingdom;
      kingdom->prev = king_last;
   }

   king_last = kingdom;

   for (kiter = king_first; kiter != NULL; kiter = kiter->next)
   {
      DIPLOMACY_DATA *diplomacy;

      // Inserting diplomacy into new kingdom
      if (diplomacy_free == NULL)
	 diplomacy = alloc_perm (sizeof (*diplomacy));
      else
      {
	 diplomacy = diplomacy_free;
	 diplomacy_free = diplomacy_free->next;
      }

      diplomacy->next = NULL;
      diplomacy->prev = NULL;
      diplomacy->diplomacy = DIPL_NEUTRAL;
      diplomacy->kingdom = kiter;

      if (kingdom->diplomacy == NULL)
	 kingdom->diplomacy = diplomacy;

      if (kingdom->diplomacy_last != NULL)
      {
	 kingdom->diplomacy_last->next = diplomacy;
	 diplomacy->prev = kingdom->diplomacy_last;
      }

      kingdom->diplomacy_last = diplomacy;

      if (kiter == king_last)
	 break;

      // Inserting diplomacy into old kingdom
      if (diplomacy_free == NULL)
	 diplomacy = alloc_perm (sizeof (*diplomacy));
      else
      {
	 diplomacy = diplomacy_free;
	 diplomacy_free = diplomacy_free->next;
      }

      diplomacy->next = NULL;
      diplomacy->diplomacy = DIPL_NEUTRAL;
      diplomacy->kingdom = kingdom;

      if (kiter->diplomacy == NULL)
	 kiter->diplomacy = diplomacy;

      if (kiter->diplomacy_last != NULL)
      {
	 kiter->diplomacy_last->next = diplomacy;
	 diplomacy->prev = kiter->diplomacy_last;
      }

      kiter->diplomacy_last = diplomacy;
   }


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

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

      case 'C':
	 KKEY ("Close", kingdom->close, fread_string (fp));
	 KKEY ("CmdInduct",  kingdom->cmd[KCMD_INDUCT],  fread_number (fp));
	 KKEY ("CmdPromote", kingdom->cmd[KCMD_PROMOTE], fread_number (fp));
	 KKEY ("CmdDemote",  kingdom->cmd[KCMD_DEMOTE],  fread_number (fp));
	 KKEY ("CmdOutcast", kingdom->cmd[KCMD_OUTCAST], fread_number (fp));
	 KKEY ("CmdDeclare", kingdom->cmd[KCMD_DECLARE], fread_number (fp));

      case 'D':
	 KKEY ("Descr", kingdom->descr, fread_string (fp));

      case 'E':
	 if (!str_cmp (word, "End"))
	 {
	    if (get_member_of_rank (king_last->members, 1) != NULL
		&& king_last->memnum < min_kingdom_members && king_last->helper == 0)
	       min_kingdom_members = king_last->memnum;
	    return;
	 }
	 return;

      case 'G':
	 KEY ("Gold", kingdom->materials[MAT_GOLD], fread_number (fp));

      case 'H':
         KEY ("Helper", kingdom->helper, fread_number (fp));

      case 'K':
	 KEY ("Kreca", kingdom->krecall, fread_number (fp));

      case 'M':
	 if (!str_cmp (word, "Member"))
	 {
	    MEMBER_DATA *m;
	    MEMBER_DATA *maux;

	    if (member_free == NULL)
	       m = alloc_perm (sizeof (*m));
	    else
	    {
	       m = member_free;
	       member_free = member_free->next;
	    }

	    m->rank = fread_number (fp);
	    m->sex = fread_number (fp);
	    free_string (m->name);
	    m->name = fread_string (fp);
	    m->kingdom = kingdom;
	    m->next = NULL;
	    m->prev = NULL;

	    if (kingdom->members == NULL)
	       kingdom->members = m;
	    else
	    {
	       for (maux = kingdom->members; maux->next != NULL;
		    maux = maux->next);
	       maux->next = m;
	       m->prev = maux;
	    }

	    kingdom->memnum++;

	    fMatch = TRUE;
	    break;
	 }

      case 'N':
	 KKEY ("Name", kingdom->name, fread_string (fp));

      case 'O':
	 KKEY ("Open", kingdom->open, fread_string (fp));
      case 'P':
	 if (!str_cmp (word, "PKPD"))
	 {
	    kingdom->pk_pd[0] = fread_number (fp);
	    kingdom->pk_pd[1] = fread_number (fp);

	    fMatch = TRUE;
	    break;
	 }
      case 'Q':
	 KEY ("Quest", kingdom->materials[MAT_QUEST], fread_number (fp));

      case 'R':
	 KKEY ("Rank1", kingdom->ranks[0], fread_string (fp));
	 KKEY ("Rank2", kingdom->ranks[1], fread_string (fp));
	 KKEY ("Rank3", kingdom->ranks[2], fread_string (fp));
	 KKEY ("Rank4", kingdom->ranks[3], fread_string (fp));
	 KKEY ("Rank5", kingdom->ranks[4], fread_string (fp));
	 KKEY ("Rank6", kingdom->ranks[5], fread_string (fp));
	 KKEY ("Rank7", kingdom->ranks[6], fread_string (fp));
	 KKEY ("Rank8", kingdom->ranks[7], fread_string (fp));
	 KKEY ("Rank9", kingdom->ranks[8], fread_string (fp));
	 KKEY ("Rank10", kingdom->ranks[9], fread_string (fp));

      case 'S':
	 KEY ("Stone", kingdom->materials[MAT_STONE], fread_number (fp));
	 KEY ("Steel", kingdom->materials[MAT_STEEL], fread_number (fp));

      case 'V':
	 if (!str_cmp (word, "Vnum"))
	 {
	    kingdom->vnum[0] = fread_number (fp);
	    kingdom->vnum[1] = fread_number (fp);

	    fMatch = TRUE;
	    break;
	 }

      case 'W':
	 KEY ("Wood", kingdom->materials[MAT_WOOD], fread_number (fp));
      }

      if (!fMatch)
      {
	 bug ("Fread_char: no match.", 0);
	 fread_to_eol (fp);
      }
   }
}

void fread_diplomacy (FILE * fp)
{
   KINGDOM_DATA *kiter;
   char *word;
   bool fMatch;

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

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

      case 'D':
	 if (!str_cmp (word, "Diplomacy"))
	 {
	    bool stop = FALSE;

	    int diplomacy;
	    char *k1 = NULL;
	    char *k2 = NULL;

	    free_string (k1);
	    free_string (k2);

	    diplomacy = fread_number (fp);
	    k1 = fread_string (fp);
	    k2 = fread_string (fp);

	    for (kiter = king_first; kiter != NULL && !stop;
		 kiter = kiter->next)
	    {
	       DIPLOMACY_DATA *d;

	       for (d = kiter->diplomacy; d != NULL && !stop; d = d->next)
	       {
		  if (!str_cmp (k1, kiter->name)
		      && !str_cmp (k2, d->kingdom->name))
		  {
		     d->diplomacy = diplomacy;
		     stop = TRUE;
		  }
	       }
	    }

	    free_string (k1);
	    free_string (k2);

	    fMatch = TRUE;
	    break;
	 }

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

      if (!fMatch)
      {
	 bug ("Fread_diplomacy: no match.", 0);
	 fread_to_eol (fp);
      }
   }
}


void load_kingdoms ()
{
   FILE *fp;
   char *word;

   if ((fp = fopen ("../db/kingdom.dat", "r")) == NULL)
   {
      bug ("load_kingdoms: error opening file.", 0);
      exit (1);
   }

   while (1)
   {
      if (fread_letter (fp) != '#')
      {
	 bug ("load_kingdoms: # not found.", 0);
	 exit (1);
      }

      word = fread_word (fp);

      if (!strcmp (word, "END"))
	 break;
      else if (!strcmp (word, "KINGDOM"))
	 fread_kingdom (fp);
      else if (!strcmp (word, "DIPLOMACY"))
	 fread_diplomacy (fp);

      else
      {
	 bug ("load_kingdoms: bad section name.", 0);
	 exit (1);
      }
   }

   get_min_kingdom_members ();

   fclose (fp);
}

/*
 * Save kingdom data to file
 */

void do_save_kings (CHAR_DATA * ch, char *argument)
{
   KINGDOM_DATA *k;
   MEMBER_DATA *m;
   FILE *fd;

   if ((fd = fopen ("../db/kingdom.dat", "w")) == NULL)
   {
      bug ("Do_save_kings: error opening file.", 0);
      return;
   }

   for (k = king_first; k != NULL; k = k->next)
   {
      fprintf (fd, "#KINGDOM\n");
      fprintf (fd, "Descr        %s~\n", k->descr);
      fprintf (fd, "Open         %s~\n", k->open);
      fprintf (fd, "Close        %s~\n", k->close);
      fprintf (fd, "Name         %s~\n", k->name);
      fprintf (fd, "Rank1        %s~\n", k->ranks[0]);
      fprintf (fd, "Rank2        %s~\n", k->ranks[1]);
      fprintf (fd, "Rank3        %s~\n", k->ranks[2]);
      fprintf (fd, "Rank4        %s~\n", k->ranks[3]);
      fprintf (fd, "Rank5        %s~\n", k->ranks[4]);
      fprintf (fd, "Rank6        %s~\n", k->ranks[5]);
      fprintf (fd, "Rank7        %s~\n", k->ranks[6]);
      fprintf (fd, "Rank8        %s~\n", k->ranks[7]);
      fprintf (fd, "Rank9        %s~\n", k->ranks[8]);
      fprintf (fd, "Rank10       %s~\n", k->ranks[9]);
      fprintf (fd, "Vnum         %d %d\n", k->vnum[0], k->vnum[1]);
      fprintf (fd, "Kreca        %d\n", k->krecall);
      fprintf( fd, "Helper       %d\n", k->helper);
      fprintf (fd, "Gold         %d\n", k->materials[MAT_GOLD]);
      fprintf (fd, "Stone        %d\n", k->materials[MAT_STONE]);
      fprintf (fd, "Wood         %d\n", k->materials[MAT_WOOD]);
      fprintf (fd, "Steel        %d\n", k->materials[MAT_STEEL]);
      fprintf (fd, "Quest        %d\n", k->materials[MAT_QUEST]);
      fprintf (fd, "PKPD         %d %d\n", k->pk_pd[0], k->pk_pd[1]);

      fprintf (fd, "CmdInduct    %d\n", k->cmd[KCMD_INDUCT]);
      fprintf (fd, "CmdPromote   %d\n", k->cmd[KCMD_PROMOTE]);
      fprintf (fd, "CmdDemote    %d\n", k->cmd[KCMD_DEMOTE]);
      fprintf (fd, "CmdOutcast   %d\n", k->cmd[KCMD_OUTCAST]);
      fprintf (fd, "CmdDeclare   %d\n", k->cmd[KCMD_DECLARE]);

      for (m = k->members; m != NULL; m = m->next)
	 fprintf (fd, "Member       %d %d %s~\n", m->rank, m->sex, m->name);

      fprintf (fd, "End\n\n");
   }

   fprintf (fd, "#DIPLOMACY\n");

   for (k = king_first; k != NULL; k = k->next)
   {
      DIPLOMACY_DATA *d = NULL;

      for (d = k->diplomacy; d != NULL; d = d->next)
      {
	 fprintf (fd, "Diplomacy    %d %s~ %s~\n",
		  d->diplomacy, k->name, d->kingdom->name);
      }
   }

   fprintf (fd, "End\n\n");


   fprintf (fd, "#END\n");
   get_min_kingdom_members();

   fclose (fd);
}

void do_ksave (CHAR_DATA * ch, char *argument)
{
   do_save_kings (ch, argument);
   send_to_char ("Kingdoms SAVED!.\n\r", ch);
}


/*
 * search for a player of a given rank (1 to 5)
 * receives a list of members and the rank you want to search and
 * returns NULL if there is no member with that rank 
 */

MEMBER_DATA *get_member_of_rank (MEMBER_DATA * mem, int rank)
{
   MEMBER_DATA *m;

   for (m = mem; m != NULL; m = m->next)
      if (m->rank == rank)
	 break;

   return m;
}

void get_min_kingdom_members ()
{
   KINGDOM_DATA *kiter;
   MEMBER_DATA *m;

   for (kiter = king_first; kiter != NULL; kiter = kiter->next)
   {
      m = get_member_of_rank (kiter->members, 1);

      if (m == NULL)
	 continue;

      if (kiter->helper == 1) break;

      if (kiter->memnum < min_kingdom_members && kiter->helper == 0)
	 min_kingdom_members = kiter->memnum;
   }
}

/*
 * Shows the information about a kingdom (OLC style)
 */

void kshow (CHAR_DATA * ch, KINGDOM_DATA * k)
{
   char buf[MAX_INPUT_LENGTH];
   MEMBER_DATA *m;
   int i;

   send_to_char ("\n\r#yKing#7dom Edi#ytor#n\n\r\n\r", ch);

   sprintf (buf, "#yName#7:  %s#n\n\r", k->name);
   send_to_char (buf, ch);

   sprintf (buf, "#yOpen/Close#7: %s, %s#n\n\r", k->open, k->close);
   send_to_char (buf, ch);

   sprintf (buf, "#yDescr#7: %s#n\n\r", k->descr);
   send_to_char (buf, ch);

   m = get_member_of_rank (k->members, 1);

   sprintf (buf, "#yKing#7:  %s#n\n\r", ((m != NULL) ? m->name : "none"));
   send_to_char (buf, ch);

   for (i = 0; i < 5; i++)
   {
      sprintf (buf, "#yRank%d (m/f)#7: %s#7, %s#n\n\r",
	       i + 1, k->ranks[i], k->ranks[i + 5]);
      send_to_char (buf, ch);
   }

   sprintf (buf, "#yVnums#7: %d %d#n\n\r", k->vnum[0], k->vnum[1]);
   send_to_char (buf, ch);

   sprintf (buf, "#yKreca#7: %d#n\n\r", k->krecall);
   send_to_char (buf, ch);

   sprintf (buf, "#yHelper#7: %d (0 = no, 1 = yes)#n\n\r", k->helper);
   send_to_char (buf, ch);

   sprintf (buf, "#yNo. Members#7 :%d#n\n\r", k->memnum);
   send_to_char (buf, ch);
   send_to_char ("\n\r", ch);
}


/*
 * OLC style kingdom editor
 */
void do_kedit (CHAR_DATA * ch, char *argument)
{
   KINGDOM_DATA *kiter;
   KINGDOM_DATA *kingdom;
   char buf[MAX_INPUT_LENGTH];
   int value;

   argument = one_argument (argument, buf);

   if (!str_cmp ("create", buf))
   {
      if (member_free == NULL)
	 kingdom = alloc_perm (sizeof (*kingdom));
      else
      {
	 kingdom = kingdom_free;
	 kingdom_free = kingdom_free->next;
      }

      kingdom->next = NULL;
      kingdom->prev = NULL;
      kingdom->members = NULL;
      kingdom->ranks[0] = str_dup ("#wKing");
      kingdom->ranks[1] = str_dup ("#wHeir");
      kingdom->ranks[2] = str_dup ("#wPrince");
      kingdom->ranks[3] = str_dup ("#wKnight");
      kingdom->ranks[4] = str_dup ("#wSquire");
      kingdom->ranks[5] = str_dup ("#wQueen");
      kingdom->ranks[6] = str_dup ("#wHeir");
      kingdom->ranks[7] = str_dup ("#wPrincess");
      kingdom->ranks[8] = str_dup ("#wLady");
      kingdom->ranks[9] = str_dup ("#wMaiden");
      kingdom->vnum[0] = 0;
      kingdom->vnum[1] = 0;
      kingdom->pk_pd[0] = 0;
      kingdom->pk_pd[1] = 0;
      kingdom->krecall = 0;
      kingdom->helper = 0;

      kingdom->open = str_dup ("");
      kingdom->close = str_dup ("");
      kingdom->descr = str_dup ("#7New Kingdom");
      kingdom->name = str_dup ("new");
      kingdom->memnum = 0;
      if (king_first == NULL)
	 king_first = kingdom;

      if (king_last != NULL)
      {
	 king_last->next = kingdom;
	 kingdom->prev = king_last;
      }
      king_last = kingdom;
      for (kiter = king_first; kiter != NULL; kiter = kiter->next)
      {
	 DIPLOMACY_DATA *diplomacy;

	 // Inserting diplomacy into new kingdom
	 if (diplomacy_free == NULL)
	    diplomacy = alloc_perm (sizeof (*diplomacy));
	 else
	 {
	    diplomacy = diplomacy_free;
	    diplomacy_free = diplomacy_free->next;
	 }

	 diplomacy->next = NULL;
	 diplomacy->prev = NULL;
	 diplomacy->diplomacy = DIPL_NEUTRAL;
	 diplomacy->kingdom = kiter;

	 if (kingdom->diplomacy == NULL)
	    kingdom->diplomacy = diplomacy;

	 if (kingdom->diplomacy_last != NULL)
	 {
	    kingdom->diplomacy_last->next = diplomacy;
	    diplomacy->prev = kingdom->diplomacy_last;
	 }

	 kingdom->diplomacy_last = diplomacy;

	 if (kiter == king_last)
	    break;

	 // Inserting diplomacy into old kingdom
	 if (diplomacy_free == NULL)
	    diplomacy = alloc_perm (sizeof (*diplomacy));
	 else
	 {
	    diplomacy = diplomacy_free;
	    diplomacy_free = diplomacy_free->next;
	 }

	 diplomacy->next = NULL;
	 diplomacy->diplomacy = DIPL_NEUTRAL;
	 diplomacy->kingdom = kingdom;

	 if (kiter->diplomacy == NULL)
	    kiter->diplomacy = diplomacy;

	 if (kiter->diplomacy_last != NULL)
	 {
	    kiter->diplomacy_last->next = diplomacy;
	    diplomacy->prev = kiter->diplomacy_last;
	 }

	 kiter->diplomacy_last = diplomacy;
      }

      ch->desc->pEdit = (void *) kingdom;
      ch->desc->connected = CON_KEDITOR;
      kshow (ch, kingdom);
   }
   else if (is_number (buf))
   {
      int i;

      value = atoi (buf);

      for (i = 1, kingdom = king_first;
	   kingdom != NULL && i < value; i++, kingdom = kingdom->next);

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

      ch->desc->pEdit = (void *) kingdom;
      ch->desc->connected = CON_KEDITOR;
      kshow (ch, kingdom);
   }
   else
   {
      send_to_char ("Syntax:  kedit create|<number>\n\r\n\r", ch);
      return;
   }
}

void kedit (CHAR_DATA * ch, char *argument)
{
   KINGDOM_DATA *k;
   MEMBER_DATA *m;
   char arg[MAX_STRING_LENGTH];
   char arg1[MAX_STRING_LENGTH];
   char arg2[MAX_STRING_LENGTH];
   char arg3[MAX_STRING_LENGTH];

   strcpy (arg, argument);
   smash_tilde (argument);
   argument = one_argument (argument, arg1);
   strcpy (arg2, argument);

   k = (KINGDOM_DATA *) ch->desc->pEdit;

   if (!str_cmp (arg1, "show") || arg1[0] == '\0')
   {
      kshow (ch, k);
      return;
   }

   if (!str_cmp (arg1, "delete"))
   {
      del_kingdom (k);
      //get_min_kingdom_members ();
   }
   if (!str_cmp (arg1, "done") || !str_cmp (arg1, "delete"))
   {
      ch->desc->pEdit = NULL;
      ch->desc->connected = CON_PLAYING;
      return;
   }

   if (!str_cmp (arg1, "?"))
   {
      do_help (ch, "kedit");
      return;
   }

   if (!str_cmp (arg1, "name"))
   {
      if (arg2[0] == '\0')
      {
	 send_to_char ("Syntax:  name [string]\n\r", ch);
	 return;
      }

      free_string (k->name);
      k->name = str_dup (arg2);

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

   if (!str_cmp (arg1, "descr"))
   {
      if (arg2[0] == '\0')
      {
	 send_to_char ("Syntax:  descr [string]\n\r", ch);
	 return;
      }

      free_string (k->descr);
      k->descr = str_dup (arg2);

      send_to_char ("Kingdom descr set.\n\r", ch);
      return;
   }

   if (!str_cmp (arg1, "open"))
   {
      if (arg2[0] == '\0')
      {
	 send_to_char ("Syntax:  open [string]\n\r", ch);
	 return;
      }

      free_string (k->open);
      k->open = str_dup (arg2);

      send_to_char ("Kingdom open descr set.\n\r", ch);
      return;
   }

   if (!str_cmp (arg1, "close"))
   {
      if (arg2[0] == '\0')
      {
	 send_to_char ("Syntax:  close [string]\n\r", ch);
	 return;
      }

      free_string (k->close);
      k->close = str_dup (arg2);

      send_to_char ("Kingdom close descr set.\n\r", ch);
      return;
   }

   if (!str_cmp (arg1, "rank"))
   {
      int rank_n;

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

      if (arg2[0] == '\0' || !is_number (arg2))
      {
	 send_to_char ("Syntax:  rank <number> <m/f> [string]\n\r", ch);
	 return;
      }

      if (atoi (arg2) < 1 || atoi (arg2) > 5)
      {
	 send_to_char ("Rank must be a number between 1 and 5.\n\r", ch);
	 return;
      }

      if (argument[0] == '\0')
      {
	 send_to_char ("You haven't specified a string.\n\r", ch);
	 return;
      }

      rank_n = (!str_cmp (arg3, "f")) ? 5 : 0;
      rank_n += atoi (arg2) - 1;

      free_string (k->ranks[rank_n]);
      k->ranks[rank_n] = str_dup (argument);

      send_to_char ("Kingdom rank set.\n\r", ch);
      return;
   }

   if (!str_cmp (arg1, "king"))
   {
      char *name;
      FILE *fd;
      int sex = 1;
      char line[MAX_STRING_LENGTH];

      one_argument (argument, arg2);
      name = capitalize (arg2);

      if (!str_cmp ("none", arg2))
      {
	 m = get_member_of_rank (k->members, 1);

	 if (m == NULL)
	 {
	    send_to_char ("This kingdom has no king.\n\r", ch);
	    return;
	 }

	 del_member (m);
	 k->memnum--;
	 get_min_kingdom_members ();

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

      sprintf (arg1, "../player/%s", name);
      if ((fd = fopen (arg1, "r")) == NULL)
      {
	 send_to_char ("That player doesn't exist.\n\r", ch);
	 return;
      }

      while (fgets (line, 100, fd))
      {
	 if (sscanf (line, "Sex          %d", &sex))
	    break;
      }

      fclose (fd);

      m = get_kingdom_char (name);

      if (m != NULL)
      {
	 send_to_char ("That player already has a kingdom.\n\r", ch);
	 return;
      }

      m = get_member_of_rank (k->members, 1);
      del_member (m);

      if (member_free == NULL)
	 m = alloc_perm (sizeof (*m));
      else
      {
	 m = member_free;
	 member_free = member_free->next;
      }

      m->rank = 1;
      m->name = str_dup (name);
      m->sex = sex;
      m->kingdom = k;
      m->next = NULL;
      m->prev = NULL;

      if (k->members == NULL)
	 k->members = m;
      else
      {
	 m->next = k->members;
	 k->members->prev = m;
	 k->members = m;
      }
      k->memnum++;
      get_min_kingdom_members ();

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

   if (!str_cmp (arg1, "qp+"))
   {
      one_argument (argument, arg2);

      if (!is_number (arg2))
      {
	 send_to_char ("Syntax:  qp+ <number>\n\r", ch);
	 return;
      }

      k->materials[MAT_QUEST] += atoi (arg2);

      send_to_char ("QP added.\n\r", ch);
      return;
   }
   if (!str_cmp (arg1, "qp-"))
   {
      one_argument (argument, arg2);

      if (!is_number (arg2))
      {
	 send_to_char ("Syntax:  qp- <number>\n\r", ch);
	 return;
      }

      k->materials[MAT_QUEST] -= atoi (arg2);

      send_to_char ("QP removed.\n\r", ch);
      return;
   }
   if (!str_cmp (arg1, "qp"))
   {
      one_argument (argument, arg2);

      if (!is_number (arg2))
      {
	 send_to_char ("Syntax:  qp <number>\n\r", ch);
	 return;
      }

      k->materials[MAT_QUEST] = atoi (arg2);

      send_to_char ("QP set.\n\r", ch);
      return;
   }
   if (!str_cmp (arg1, "members"))
   {
      one_argument (argument, arg2);

      if (!is_number (arg2))
      {
	 send_to_char ("Syntax: members <number>\n\r", ch);
	 return;
      }

      k->memnum = atoi (arg2);

      send_to_char ("Members set.\n\r", ch);
      return;
   }
   if (!str_cmp (arg1, "pk"))
   {
      one_argument (argument, arg2);

      if (!is_number (arg2))
      {
	 send_to_char ("Syntax:  pk <number>\n\r", ch);
	 return;
      }

      k->pk_pd[0] = atoi (arg2);

      send_to_char ("Pkills set.\n\r", ch);
      return;
   }
   if (!str_cmp (arg1, "pd"))
   {
      one_argument (argument, arg2);

      if (!is_number (arg2))
      {
	 send_to_char ("Syntax:  pk <number>\n\r", ch);
	 return;
      }

      k->pk_pd[1] = atoi (arg2);

      send_to_char ("Pdeaths set.\n\r", ch);
      return;
   }
   if (!str_cmp (arg1, "lvnum"))
   {
      one_argument (argument, arg2);

      if (!is_number (arg2))
      {
	 send_to_char ("Syntax:  lvnum <number>\n\r", ch);
	 return;
      }

      if (atoi (arg2) > k->vnum[1])
      {
	 send_to_char
	    ("The lower vnum must be smaller or equal to upper vnum.\n\r",
	     ch);
	 return;
      }

      k->vnum[0] = atoi (arg2);

      send_to_char ("Lower vnum set.\n\r", ch);
      return;
   }

   if (!str_cmp (arg1, "uvnum"))
   {
      one_argument (argument, arg2);

      if (!is_number (arg2))
      {
	 send_to_char ("Syntax:  uvnum <number>\n\r", ch);
	 return;
      }

      if (atoi (arg2) < k->vnum[0])
      {
	 send_to_char
	    ("The upper vnum must be greater or equal to lower vnum.\n\r",
	     ch);
	 return;
      }

      k->vnum[1] = atoi (arg2);

      send_to_char ("Upper vnum set.\n\r", ch);
/*
        if( k->vnum[0] > k->krecall || k->krecall > k->vnum[1] )
        {
            k->krecall = 0;
            send_to_char("Kingdom recall was reseted.\n\r",ch);
        }
*/
      return;
   }

   if (!str_cmp (arg1, "vnums"))
   {
      argument = one_argument (argument, arg2);
      one_argument (argument, arg1);

      if (!is_number (arg2) || !is_number (arg1) || atoi (arg2) > atoi (arg1))
      {
	 send_to_char ("Syntax:  vnums <lvnum> <uvnum>\n\r", ch);
	 send_to_char ("         lvnum must be lower or equal to uvnum.\n\r",
		       ch);
	 return;
      }

      k->vnum[0] = atoi (arg2);
      k->vnum[1] = atoi (arg1);

      send_to_char ("Castle vnums set.\n\r", ch);
      /*
         if( k->vnum[0] > k->krecall || k->krecall > k->vnum[1] )
         {
         k->krecall = 0;
         send_to_char("Kingdom recall was reseted.\n\r",ch);
         }
       */
      return;
   }

   if (!str_cmp ( arg1, "helper"))
   {
      one_argument (argument, arg2);
      
      if (!str_cmp(arg2,"yes")) k->helper = 1;
      else if (!str_cmp(arg2,"no")) k->helper = 0;
      else send_to_char("Options are yes, or no.\n\r",ch);

      send_to_char("Helper flag changed.\n\r",ch);
      return;
   }

   if (!str_cmp (arg1, "krecall"))
   {
      one_argument (argument, arg2);

      if (!is_number (arg2))
      {
	 send_to_char ("Syntax:  kreca <number>\n\r", ch);
	 return;
      }
/*
        if( (k->vnum[0] > atoi(arg2)) || (k->vnum[1] < atoi(arg2)) )
        {
            sprintf( arg1, "The kingdom recall must be a number between %d and %d.\n\r",
                k->vnum[0], k->vnum[1] );
            send_to_char( arg1, ch );
            return;
        }
*/
      k->krecall = atoi (arg2);

      send_to_char ("Kingdom recall set.\n\r", ch);

      return;
   }

   interpret (ch, arg);
   return;
}

void gshow (CHAR_DATA * ch, KINGDOM_DATA * k)
{
   char buf[MAX_INPUT_LENGTH];
   MEMBER_DATA *m;

   send_to_char ("\n\r#yKing#7dom Edi#ytor#n\n\r\n\r", ch);

   sprintf (buf, "#yName#7:  %s#n\n\r", k->name);
   send_to_char (buf, ch);

   sprintf (buf, "#yDescr#7: %s#n\n\r", k->descr);
   send_to_char (buf, ch);

   m = get_member_of_rank (k->members, 1);

   sprintf (buf, "#yKing#7:  %s#n\n\r", ((m != NULL) ? m->name : "none"));
   send_to_char (buf, ch);

   send_to_char ("\n\r", ch);
}

/*
 * OLC style kingdom editor
 */
void do_kingdoms (CHAR_DATA * ch, char *argument)
{

   KINGDOM_DATA *kingdom;
   KINGDOM_DATA *kiter;
   KINGDOM_DATA *k;
   MEMBER_DATA *m;
   char buf[MAX_INPUT_LENGTH];
   char buf2[MAX_INPUT_LENGTH];
   char *name;

   argument = one_argument (argument, buf);
   strcpy (buf2, argument);
   if ((m = get_kingdom_char (ch->name)) != NULL)
   {
      do_kingdom (ch, "");
      return;
   }
   return;

   if (get_hours (ch) < 10)
   {
      stc ("You need at least 10 hours before creating a Kingdom.\n\r", ch);
      return;
   }
/*
   if (ch->max_hit < 25000)
   {
      stc ("You need at least 25,000 hit points  to create a Kingdom.\n\r",
	   ch);
      return;
   }

   if (ch->race < 15)
   {
      stc ("You require 15 status before you can create a kingdom!\n\r", ch);
      return;
   }

   if (ch->exp < 1500000)
   {
      stc ("It takes 1.5 million exp to create a Kingdom.\n\r", ch);
      return;
   }
*/
   if (buf[0] == '\0' || buf2[0] == '\0')
   {
      stc ("Syntax: kingdom create <name>\n\r", ch);
      return;
   }


   if (strlen (bash_color (buf2)) > 19 || strlen (bash_color (buf2)) < 3)
   {
      send_to_char ("From 3 to 19 characters please.\n\r", ch);
      return;
   }

   name = ch->name;

   if (!str_cmp ("create", buf))
   {
      for (k = king_first; k != NULL; k = k->next)
      {
	 if (!str_cmp (bash_color(buf2), k->name))
	 {
	    stc ("Theres already a kingdom named that!\n\r", ch);
	    return;
	 }
      }

      if (member_free == NULL)
	 kingdom = alloc_perm (sizeof (*kingdom));
      else
      {
	 kingdom = kingdom_free;
	 kingdom_free = kingdom_free->next;
      }

      kingdom->next = NULL;
      kingdom->prev = NULL;
      kingdom->members = NULL;
      kingdom->ranks[0] = str_dup ("#wKing");
      kingdom->ranks[1] = str_dup ("#wPrince");
      kingdom->ranks[2] = str_dup ("#wBaron");
      kingdom->ranks[3] = str_dup ("#wKnight");
      kingdom->ranks[4] = str_dup ("#wMember");
      kingdom->ranks[5] = str_dup ("#wQueen");
      kingdom->ranks[6] = str_dup ("#wPrincess");
      kingdom->ranks[7] = str_dup ("#wBaroness");
      kingdom->ranks[8] = str_dup ("#wKnight");
      kingdom->ranks[9] = str_dup ("#wMember");
      kingdom->vnum[0] = 0;
      kingdom->vnum[1] = 0;
      kingdom->krecall = 0;
      if (IS_SET (ch->extra2, NHELPER)) kingdom->helper = 1;
      else
      kingdom->helper = 0;
      kingdom->memnum = 0;
      kingdom->memnum += 1;
      kingdom->open = str_dup ("");
      kingdom->close = str_dup ("");
      //free_string (kingdom->descr);
      kingdom->descr = str_dup (buf2);
      //free_string (kingdom->name);
      kingdom->name = str_dup (bash_color (buf2));

      if (king_first == NULL)
	 king_first = kingdom;

      if (king_last != NULL)
      {
	 king_last->next = kingdom;
	 kingdom->prev = king_last;
      }
      king_last = kingdom;

      for (kiter = king_first; kiter != NULL; kiter = kiter->next)
      {
	 DIPLOMACY_DATA *diplomacy;

	 // Inserting diplomacy into new kingdom
	 if (diplomacy_free == NULL)
	    diplomacy = alloc_perm (sizeof (*diplomacy));
	 else
	 {
	    diplomacy = diplomacy_free;
	    diplomacy_free = diplomacy_free->next;
	 }

	 diplomacy->next = NULL;
	 diplomacy->prev = NULL;
	 diplomacy->diplomacy = DIPL_NEUTRAL;
	 diplomacy->kingdom = kiter;

	 if (kingdom->diplomacy == NULL)
	    kingdom->diplomacy = diplomacy;

	 if (kingdom->diplomacy_last != NULL)
	 {
	    kingdom->diplomacy_last->next = diplomacy;
	    diplomacy->prev = kingdom->diplomacy_last;
	 }

	 kingdom->diplomacy_last = diplomacy;

	 if (kiter == king_last)
	    break;

	 // Inserting diplomacy into old kingdom
	 if (diplomacy_free == NULL)
	    diplomacy = alloc_perm (sizeof (*diplomacy));
	 else
	 {
	    diplomacy = diplomacy_free;
	    diplomacy_free = diplomacy_free->next;
	 }

	 diplomacy->next = NULL;
	 diplomacy->diplomacy = DIPL_NEUTRAL;
	 diplomacy->kingdom = kingdom;

	 if (kiter->diplomacy == NULL)
	    kiter->diplomacy = diplomacy;

	 if (kiter->diplomacy_last != NULL)
	 {
	    kiter->diplomacy_last->next = diplomacy;
	    diplomacy->prev = kiter->diplomacy_last;
	 }

	 kiter->diplomacy_last = diplomacy;
      }

      if (member_free == NULL)
	 m = alloc_perm (sizeof (*m));
      else
      {
	 m = member_free;
	 member_free = member_free->next;
      }

      m->rank = 1;
      m->name = str_dup (ch->name);
      m->sex = ch->sex;
      m->kingdom = kingdom;
      m->next = NULL;
      m->prev = NULL;

      if (kingdom->members == NULL)
	 kingdom->members = m;
      else
      {
	 m->next = kingdom->members;
	 kingdom->members->prev = m;
	 kingdom->members = m;
      }
      get_min_kingdom_members();
      do_ksave (ch, "");
sprintf (buf, "#y%s #7has founded #y%s#7.", ch->name, m->kingdom->descr);
   do_info (ch, buf);
  //    ch->exp -= 1500000;
      return;
   }
   else
   {
      send_to_char ("Syntax:  kingdom create <name>\n\r\n\r", ch);
      return;
   }
}
void del_diplomacy (DIPLOMACY_DATA * d, KINGDOM_DATA * k)
{
   if (d == NULL)
      return;

   if (d->prev != NULL)
      d->prev->next = d->next;

   if (d->next != NULL)
      d->next->prev = d->prev;

   if (k->diplomacy == d)
      k->diplomacy = d->next;

   if (k->diplomacy_last == d)
      k->diplomacy_last = d->prev;

   d->next = diplomacy_free;
   diplomacy_free = d;
}

/*
 * Delete a member from the member list in the kingdom structure
 */

void del_member( MEMBER_DATA* m )
{
    if( m == NULL ) return;

    if( m->prev != NULL )
        m->prev->next = m->next;

    if( m->next != NULL )
        m->next->prev = m->prev;

    if( m->kingdom->members == m )
        m->kingdom->members = m->next;

    free_string( m->name );
    
    m->next = member_free;
    member_free = m;
}

/*
 * Delete one kingdom and related information
 */
void del_kingdom( KINGDOM_DATA* k )
{
    KINGDOM_DATA *	kiter = NULL;
    DIPLOMACY_DATA *	dipl = NULL;

    if( k == NULL ) return;

    if( k->prev != NULL )
        k->prev->next = k->next;

    if( k->next != NULL )
        k->next->prev = k->prev;

    if( king_first == k )
        king_first = k->next;

    if( king_last == k )
        king_last = k->prev;

    k->pk_pd[0] = 0;
    k->pk_pd[1] = 0;
    free_string( k->name );
    free_string( k->descr );
    free_string( k->open );
    free_string( k->close );
    free_string( k->ranks[0] );
    free_string( k->ranks[1] );
    free_string( k->ranks[2] );
    free_string( k->ranks[3] );
    free_string( k->ranks[4] );
    free_string( k->ranks[5] );
    free_string( k->ranks[6] );
    free_string( k->ranks[7] );
    free_string( k->ranks[8] );
    free_string( k->ranks[9] );

    for( kiter = king_first; kiter != NULL; kiter = kiter->next )
    {
        bool stop = FALSE;

        for( dipl = kiter->diplomacy; dipl != NULL && !stop; dipl = dipl->next )
        {
            if( dipl->kingdom == k )
            {
                del_diplomacy(dipl, kiter);
                stop = TRUE;
            }
        }
    }

    while( k->members != NULL )
        del_member(k->members);

    while( k->diplomacy != NULL )
        del_diplomacy(k->diplomacy,k);

    k->next = kingdom_free;
    kingdom_free = k;    
}


void odel_kingdom (KINGDOM_DATA * k)
{
   KINGDOM_DATA *kiter = NULL;
   DIPLOMACY_DATA *dipl = NULL;

   if (k == NULL)
      return;

   if (k->prev != NULL)
      k->prev->next = k->next;

   if (k->next != NULL)
      k->next->prev = k->prev;

   if (king_first == k)
      king_first = k->next;

   if (king_last == k)
      king_last = k->prev;

   free_string (k->name);
   free_string (k->descr);
   free_string (k->ranks[0]);
   free_string (k->ranks[1]);
   free_string (k->ranks[2]);
   free_string (k->ranks[3]);
   free_string (k->ranks[4]);

   for (kiter = king_first; kiter != NULL; kiter = kiter->next)
   {
      bool stop = FALSE;

      for (dipl = kiter->diplomacy; dipl != NULL && !stop; dipl = dipl->next)
      {
	 if (dipl->kingdom == k)
	 {
	    del_diplomacy (dipl, kiter);
	    stop = TRUE;
	 }
      }
   }

   while (k->members != NULL)
      del_member (k->members);
   get_min_kingdom_members();
   k->memnum = 0;
   k->pk_pd[0] = 0;
   k->pk_pd[1] = 0;
   k->next = kingdom_free;
   kingdom_free = k;
}

//////////////////////////////////////////
// Kingdom related commands for members //
//////////////////////////////////////////

/*
 * Descr: Add a player to a kingdom
 * Ranks allowed: 1,2 and 3
 * Requirements: Player must be clannable
 */

void do_kinduct (CHAR_DATA * ch, char *argument)
{
   MEMBER_DATA *m;
   CHAR_DATA *wch;
   KINGDOM_DATA *k;
   char buf[MAX_STRING_LENGTH];

   if ((m = get_kingdom_char (ch->name)) == NULL || m->rank > m->kingdom->cmd[KCMD_INDUCT] )
   {
      send_to_char ("Huh?\n\r", ch);
      return;
   }
   return;
   k = m->kingdom;

   if (argument[0] == '\0')
   {
      send_to_char ("Who do you wish to induct?\n\r", ch);
      return;
   }

   if (k->helper == 1) {
   send_to_char("You cannot induct any members.\n\r",ch); return; }
   if (k->memnum >= min_kingdom_members + 5)
   {
      send_to_char
	 ("You must wait until the kingdom with least members gets more.\n\r",
	  ch);
      return;
   }
   if ((wch = get_char_room (ch, argument)) == NULL)
   {
      send_to_char
	 ("You search for them but they are nowhere in the room.\n\r", ch);
      return;
   }

   if (IS_NPC (wch))
      return;

   if ((m = get_kingdom_char (wch->name)) != NULL)
   {
      send_to_char ("They already have a kingdom.\n\r", ch);
      return;
   }

   if (!IS_SET (wch->newbits, NEW_CLANNABLE))
   {
      send_to_char ("They are not willing to join your cause.\n\r", ch);
      return;
   }
/*
   if (k->materials[MAT_QUEST] < ((k->memnum + 1) * 10000) )
   {
        stc("Your kingdom is not wealthy enough to induct them.\n\r", ch);
        return;
   }
*/

   if (member_free == NULL)
      m = alloc_perm (sizeof (*m));
   else
   {
      m = member_free;
      member_free = member_free->next;
   }

   m->rank = 5;
   m->name = str_dup (wch->name);
   m->sex = ch->sex;
   m->kingdom = k;
   m->next = NULL;
   m->prev = NULL;

   if (k->members == NULL)
      k->members = m;
   else
   {
      m->next = k->members;
      k->members->prev = m;
      k->members = m;
   }

   k->memnum++;

/*
   if (k->materials[MAT_QUEST] < (k->memnum * 10000) )
   {
	stc("Your kingdom is not wealthy enough to induct them.\n\r", ch);
        return;
   }*/
//   k->materials[MAT_QUEST] -= (k->memnum * 10000);
   sprintf (buf, "#y%s #whas joined #c%s.", wch->name, k->descr);
//   do_kinfo (ch, buf);
   REMOVE_BIT (wch->newbits, NEW_CLANNABLE);
   sprintf (buf, "I %s, hereby declare you %s a member of %s!",
	    ch->name, wch->name, k->descr);
   do_say (ch, buf);
   do_save_kings (ch, argument);
   get_min_kingdom_members ();
}

/*
 * Descr: Remove a player from a kingdom
 * Ranks allowed: 1 and 2
 * Requirements: none
 */

void do_koutcast (CHAR_DATA * ch, char *argument)
{
   MEMBER_DATA *m1;
   MEMBER_DATA *m2;
   KINGDOM_DATA *k;
   char buf[MAX_STRING_LENGTH];

   m1 = get_kingdom_char (ch->name);
   m2 = get_kingdom_char (argument);

   if ((m1 == NULL || m1->rank > m1->kingdom->cmd[KCMD_OUTCAST]) && !IS_IMMORTAL (ch))
   {
      send_to_char ("Huh?\n\r", ch);
      return;
   }
   return;
   if (argument[0] == '\0')
   {
      send_to_char ("Who do you wish to outcast?\n\r", ch);
      return;
   }

   if (m2 == NULL || (!IS_IMMORTAL (ch) && m2->kingdom != m1->kingdom))
   {
      send_to_char ("No one with that name in your kingdom.\n\r", ch);
      return;
   }

   if (m2->rank == 1 || (!IS_IMMORTAL (ch) && m1->rank >= m2->rank))
   {
      send_to_char ("Their rank doesn't allow you to outcast them.\n\r", ch);
      return;
   }
   k = m2->kingdom;
   sprintf (buf, "#y%s #whas been #rOutcast from #c%s.",
	    capitalize (m2->name), k->descr);
//   do_kinfo (ch, buf);
   sprintf (buf, "You outcast %s from %s\n\r", m2->name, k->descr);
   stc (buf, ch);

   m2->kingdom->memnum--;
   del_member (m2);
   get_min_kingdom_members ();
   do_save_kings (ch, argument);


}

/*
 * Descr: increase the kingdom rank of a player
 * Ranks allowed: 1 and 2
 * Requirements: none
 */

void do_kpromote (CHAR_DATA * ch, char *argument)
{
   MEMBER_DATA *m1;
   MEMBER_DATA *m2;
   char buf[MAX_STRING_LENGTH];

   m1 = get_kingdom_char (ch->name);
   m2 = get_kingdom_char (argument);

   if (m1 == NULL || m1->rank > m1->kingdom->cmd[KCMD_PROMOTE])
   {
      send_to_char ("Huh?\n\r", ch);
      return;
   }

   if (argument[0] == '\0')
   {
      send_to_char ("Who do you wish to promote?\n\r", ch);
      return;
   }

   if (m2 == NULL || m2->kingdom != m1->kingdom)
   {
      send_to_char ("No one with that name in your kingdom.\n\r", ch);
      return;
   }

   if (m2->rank <= m1->rank)
   {
      send_to_char ("Their rank doesn't allow you to do that.\n\r", ch);
      return;
   }

   if (m2->rank <= m1->rank + 1)
   {
      send_to_char ("You can not promote someone to your own rank.\n\r", ch);
      return;
   }

   if (m2->rank - 1 < 3
       && get_member_of_rank (m1->kingdom->members, 2) != NULL)
   {
      send_to_char ("That rank is already taken.\n\r", ch);
      return;
   }

   m2->rank--;

   sprintf (buf, "#y%s #7has been promoted to #C%s#7.",
	    capitalize (m2->name), m2->kingdom->ranks[m2->rank - 1]);

//   do_kinfo (ch, buf);
   do_save_kings (ch, "");
}

/*
 * Descr: decrease the kingdom rank of a player
 * Ranks allowed: 1 and 2
 * Requirements: none
 */

void do_kdemote (CHAR_DATA * ch, char *argument)
{
   MEMBER_DATA *m1;
   MEMBER_DATA *m2;
   char buf[MAX_STRING_LENGTH];

   m1 = get_kingdom_char (ch->name);
   m2 = get_kingdom_char (argument);

   if (m1 == NULL || m1->rank > m1->kingdom->cmd[KCMD_DEMOTE])
   {
      send_to_char ("Huh?\n\r", ch);
      return;
   }

   if (argument[0] == '\0')
   {
      send_to_char ("Who do you wish to demote?\n\r", ch);
      return;
   }

   if (m2 == NULL || m2->kingdom != m1->kingdom)
   {
      send_to_char ("No one with that name in your kingdom.\n\r", ch);
      return;
   }

   if (m2->rank <= m1->rank)
   {
      send_to_char ("Their rank doesn't allow you to do that.\n\r", ch);
      return;
   }

   if (m2->rank == 5)
   {
      send_to_char ("They already have the lowest rank.\n\r", ch);
      return;
   }

   m2->rank++;

   sprintf (buf, "#y%s #7has been demoted to #C%s#7.",
	    capitalize (m2->name), m2->kingdom->ranks[m2->rank - 1]);

//   do_kinfo (ch, buf);
   do_save_kings (ch, "");
}

/*
 * Descr: leave the kingdom
 * Ranks allowed: 1,2,34 and 5
 * Requirements: none
 */

void do_kdesert (CHAR_DATA * ch, char *argument)
{
   MEMBER_DATA *m;
   char buf[MAX_STRING_LENGTH];
   char arg1[MAX_INPUT_LENGTH];
   char *pArg;
   char cEnd;

   m = get_kingdom_char (ch->name);

   if (m == NULL)
   {
      send_to_char ("Huh?\n\r", ch);
      return;
   }

   if (m->rank == 1)
   {
      send_to_char ("Leaders may not desert.\n\r", ch);
      return;
   }

   pArg = arg1;
   while (isspace (*argument))
      argument++;

   cEnd = ' ';

   if (*argument == '\'' || *argument == '"')
      cEnd = *argument++;

   while (*argument != '\0')
   {
      if (*argument == cEnd)
      {
	 argument++;
	 break;
      }

      *pArg++ = *argument++;
   }

   *pArg = '\0';

   if (arg1[0] == '\0')
   {
      send_to_char ("Are you sure you wish to leave your kingdom?\n\r", ch);
      send_to_char
	 ("Type desert <password> if you really wish to leave your kingdom.\n\r",
	  ch);
      return;
   }


   if (strcmp (arg1, ch->pcdata->pwd)
       && strcmp (crypt (arg1, ch->pcdata->pwd), ch->pcdata->pwd))
   {
      WAIT_STATE (ch, 40);
      send_to_char ("Wrong password.  Wait 10 seconds.\n\r", ch);
      return;
   }

   sprintf (buf, "#y%s #7has left #y%s#7.", ch->name, m->kingdom->descr);
//   do_kinfo (ch, buf);

   m->kingdom->memnum--;
   get_min_kingdom_members ();
   del_member (m);
   char_from_room (ch);
   char_to_room (ch, get_room_index (ROOM_VNUM_TEMPLE));
   do_save_kings (ch, "");
}

/*
 * Descr: Finish and delete a kingdom
 * Ranks allowed: 1
 * Requirements: king password
 */

void do_kdisband (CHAR_DATA * ch, char *argument)
{
   MEMBER_DATA *m;
   char buf[MAX_STRING_LENGTH];
   char arg1[MAX_INPUT_LENGTH];
   char *pArg;
   char cEnd;
   int refund = 0;
   m = get_kingdom_char (ch->name);

   if (m == NULL || m->rank > 1)
   {
      send_to_char ("Huh?\n\r", ch);
      return;
   }

   pArg = arg1;
   while (isspace (*argument))
      argument++;

   cEnd = ' ';

   if (*argument == '\'' || *argument == '"')
      cEnd = *argument++;

   while (*argument != '\0')
   {
      if (*argument == cEnd)
      {
	 argument++;
	 break;
      }

      *pArg++ = *argument++;
   }

   *pArg = '\0';

   if (arg1[0] == '\0')
   {
      send_to_char ("Are you sure you wish to disband your kingdom?\n\r", ch);
      send_to_char
	 ("Type disband <password> if you really wish to disband your kingdom.\n\r",
	  ch);
      return;
   }

   if (strcmp (arg1, ch->pcdata->pwd)
       && strcmp (crypt (arg1, ch->pcdata->pwd), ch->pcdata->pwd))
   {
      WAIT_STATE (ch, 40);
      send_to_char ("Wrong password.  Wait 10 seconds.\n\r", ch);
      return;
   }

   sprintf (buf, "%s disbanded %s.", ch->name, m->kingdom->name);
   log_string (buf, ch);

   sprintf (buf, "#y%s #7has disbanded #y%s#7.", ch->name, m->kingdom->descr);
   do_info (ch, buf);
   if (m->kingdom->materials[MAT_QUEST] > 10000)
   {
      refund = (m->kingdom->materials[MAT_QUEST] / 2);
      sprintf (buf, "You receive a refund of %d quest points\n\r", refund);
      stc (buf, ch);
      ch->pcdata->quest += refund;
   }
   m->kingdom->materials[MAT_QUEST] = 0;

   del_kingdom (m->kingdom);
   get_min_kingdom_members ();

   do_save_kings (ch, "");
}

/*
 * Descr: Pass the leadership the a rank 2 member
 * Ranks allowed: 1
 * Requirements: king password, there must be a rank 2 member
 */

void do_krenounce (CHAR_DATA * ch, char *argument)
{
   MEMBER_DATA *m;
   MEMBER_DATA *m2;
   char buf[MAX_STRING_LENGTH];
   char arg1[MAX_INPUT_LENGTH];
   char *pArg;
   char cEnd;

   m = get_kingdom_char (ch->name);

   if (m == NULL || m->rank > 1)
   {
      send_to_char ("Huh?\n\r", ch);
      return;
   }

   if ((m2 = get_member_of_rank (m->kingdom->members, 2)) == NULL)
   {
      send_to_char
	 ("First you must promote someone to second in command.\n\r", ch);
      return;
   }

   pArg = arg1;
   while (isspace (*argument))
      argument++;

   cEnd = ' ';

   if (*argument == '\'' || *argument == '"')
      cEnd = *argument++;

   while (*argument != '\0')
   {
      if (*argument == cEnd)
      {
	 argument++;
	 break;
      }

      *pArg++ = *argument++;
   }

   *pArg = '\0';

   if (arg1[0] == '\0')
   {
      send_to_char ("Are you sure you wish to renounce?\n\r", ch);
      send_to_char
	 ("Type renounce <password> if you really wish to do it.\n\r", ch);
      return;
   }

   if (strcmp (arg1, ch->pcdata->pwd)
       && strcmp (crypt (arg1, ch->pcdata->pwd), ch->pcdata->pwd))
   {
      WAIT_STATE (ch, 40);
      send_to_char ("Wrong password.  Wait 10 seconds.\n\r", ch);
      return;
   }

   sprintf (buf, "%s renounced %s to %s.", ch->name, m->kingdom->name,
	    m2->name);
   log_string (buf, ch);

   sprintf (buf, "#y%s #7has renounced #y%s #7to #y%s#7.", ch->name,
	    m->kingdom->descr, m2->name);
//   do_kinfo (ch, buf);

   m2->rank = 1;
   m->kingdom->memnum--;
   get_min_kingdom_members ();
   del_member (m);
   do_save_kings (ch, "");
   //load_kingdoms();
}

/*
 * Descr: recall to kingdom recall room
 * Ranks allowed: 1 and 2
 * Requirements: no fight timer, no curse
 */

void do_krecall (CHAR_DATA * ch, char *argument)
{
   char buf[MAX_STRING_LENGTH];
   CHAR_DATA *victim;
   CHAR_DATA *mount;
   ROOM_INDEX_DATA *location;
   MEMBER_DATA *m;

   if (IS_NPC (ch) || (m = get_kingdom_char (ch->name)) == NULL)
   {
      send_to_char ("Huh?\n\r", ch);
      return;
   }

   if (IS_SET (ch->in_room->room_flags, ROOM_NO_RECALL)
       || IS_AFFECTED (ch, AFF_CURSE))
   {
      send_to_char ("You are unable to recall.\n\r", ch);
      return;
   }
   if (m->kingdom->materials[MAT_QUEST] == 0)
   {
      stc ("You have been evicted!!\n\r", ch);
      return;
   }
   if (ch->fight_timer)
   {
      send_to_char ("Not with a fight timer.\n\r", ch);
      return;
   }
   if (IS_AFFECTED (ch, AFF_WEBBED))
   {
      send_to_char
	 ("You are unable to move with all this sticky webbing on.\n\r", ch);
      return;
   }
   if (IS_SET (ch->affected_by, AFF_ENTRAILS))
   {
      send_to_char
	 ("You are unable to move with these entrails entrapping you.\n\r",
	  ch);
      return;
   }
   if (IS_SET (ch->flag2, AFF_TOTALBLIND))
   {
      stc ("You are unable to recall.\n\r", ch);
      return;
   }
   act ("A look of concentration crosses $n's face.", ch, NULL, NULL,
	TO_ROOM);

   if ((location = get_room_index (m->kingdom->krecall)) == NULL)
   {
      send_to_char ("You are completely lost.\n\r", ch);
      return;
   }

   if (ch->in_room == location)
      return;

   if ((victim = ch->fighting) != NULL)
   {
      if (number_bits (1) == 0)
      {
	 WAIT_STATE (ch, 4);
	 sprintf (buf, "You failed!\n\r");
	 send_to_char (buf, ch);
	 return;
      }
      sprintf (buf, "You recall from combat!\n\r");
      send_to_char (buf, ch);
      stop_fighting (ch, TRUE);
   }

   act ("$n disappears.", ch, NULL, NULL, TO_ROOM);
   char_from_room (ch);
   char_to_room (ch, location);
   act ("$n appears in the room.", ch, NULL, NULL, TO_ROOM);
   do_look (ch, "auto");
   if ((mount = ch->mount) == NULL)
      return;
   char_from_room (mount);
   char_to_room (mount, ch->in_room);
   return;
}

////////////////////////////
// Information commands   //
////////////////////////////

/* 
 * Deposit QPS into Kingdom Balance
 */

void do_depositqps (CHAR_DATA * ch, char *argument)
{
   KINGDOM_DATA *k;
   MEMBER_DATA *m;
   char buf[MSL];
   int amt;

   if (IS_NPC (ch))
      return;

   amt = atoi (argument);

   if ((m = get_kingdom_char (ch->name)) == NULL)
   {
      send_to_char
	 ("How can you deposit QP when you are not in a KINGDOM???\n\r", ch);
      return;
   }
   k = m->kingdom;
   if (argument[0] == '\0')
   {
      stcprintf (ch, "Your kingdoms balance is %d quest points.\n\r",
		 k->materials[MAT_QUEST]);

      send_to_char ("How much do you want to deposit?\n\r", ch);
      return;
   }

   if (amt < 1)
   {
      send_to_char ("Im sorry but we dont give work on negatives here!", ch);
      return;
   }
   if (amt > ch->pcdata->quest)
   {
      send_to_char ("You dont have that amount of QPS sorry!\n\r", ch);
      return;
   }

   sprintf (buf,
	    "%s has deposited %d quest points into the kingdom treasury.",
	    ch->name, amt);
//   do_kinfo (ch, buf);

   ch->pcdata->quest -= amt;
   k->materials[MAT_QUEST] += amt;
   do_save_kings (ch, "");
   stcprintf (ch, "Your kingdoms balance is now %d quest points.\n\r",
	      k->materials[MAT_QUEST]);
   return;
}

/*
 * Withdraw QPS from a Kingdom balance
 */

void do_withdrawqps (CHAR_DATA * ch, char *argument)
{
   KINGDOM_DATA *k;
   MEMBER_DATA *m;
   char buf[MSL];
   int amt;

   if (IS_NPC (ch))
      return;

   amt = atoi (argument);

   if ((m = get_kingdom_char (ch->name)) == NULL)
   {
      send_to_char
	 ("How can you withdraw QP when you are not in a KINGDOM???\n\r", ch);
      return;
   }
   k = m->kingdom;
   if (argument[0] == '\0')
   {
      stcprintf (ch, "Your kingdoms balance is %d quest points.\n\r",
		 k->materials[MAT_QUEST]);

      send_to_char ("How much do you want to withdraw?\n\r", ch);
      return;
   }

   if (amt < 1 || amt > 100000)
   {
      send_to_char
	 ("You can only withdraw a maximum of 100000 qps from your kingdoms balance",
	  ch);
      return;
   }

   if (amt > k->materials[MAT_QUEST])
   {
      send_to_char ("Your Kingdom doesn't have enough qps\n\r", ch);
      return;
   }
   sprintf (buf,
	    "You withdraw %d quest points from the kingdom treasury.\n\r",
	    amt);
   send_to_char (buf, ch);
   sprintf (buf,
	    "%s has withdrawn %d quest points from the kingdom treasury.",
	    ch->name, amt);
//   do_kinfo (ch, buf);
   k->materials[MAT_QUEST] -= amt;
   ch->pcdata->quest += amt;
   save_char_obj (ch);
   do_save_kings (ch, "");

   stcprintf (ch, "Your kingdoms balance is now %d quest points.\n\r",
	      k->materials[MAT_QUEST]);
   return;
}

/*
 * Display the members of a given kingdom and their ranks
 */

void do_kinginfo (CHAR_DATA * ch, char *argument)
{
   KINGDOM_DATA *k;
   KINGDOM_DATA *k2;
   MEMBER_DATA *m;
   MEMBER_DATA *member_list;
   char buf[MAX_INPUT_LENGTH];
   char nbuf[MAX_INPUT_LENGTH];
   int rank;
   int align = 0;
   int col = 0;
   argument = one_argument (argument, buf);

   if (buf[0] == '\0')
   {
      stc ("Get info on which kingdom?\n\r\n\r", ch);
      for (k2 = king_first; k2; k2 = k2->next)
      {
	 sprintf (nbuf, "%s, ", k2->name);
	 stc (nbuf, ch);
	 if (++col % 4 == 0)
	    send_to_char ("\n\r", ch);
      }
      if (col % 4 != 0)
	 send_to_char ("\n\r", ch);
//      do_kinglist (ch, "");
      return;
   }
   for (k = king_first; k != NULL; k = k->next)
      if (!str_prefix (buf, k->name))
	 break;

   if (k == NULL)
   {
      send_to_char ("\n\r\n\rNo such Kingdom.\n\r\n\r", ch);
      return;
   }
   stc ("#b------------------------------------------------------------#n\n\r", ch);
   sprintf (buf, "#yThe Current statistics of the #r%s #yKingdom#n\n\r",
	    k->descr);
   send_to_char (buf, ch);
   stc ("#b------------------------------------------------------------#n\n\r", ch);
   send_to_char ("#rRanks:\n\r", ch);
   stc ("#b------------------------------------------------------------#n\n\r", ch);
   m = get_member_of_rank (k->members, 1);
   sprintf (buf, "#p%s#e:#w %s#n\n\r",
	    (m != NULL) ? k->ranks[(m->sex * 5) - 5] : k->ranks[0],
	    (m != NULL) ? m->name : "");
   send_to_char (buf, ch);


   m = get_member_of_rank (k->members, 2);
   sprintf (buf, "%s#e:#w %s#n\n\r",
	    (m != NULL) ? k->ranks[(m->sex * 5) - 4] : k->ranks[1],
	    (m != NULL) ? m->name : "");
   send_to_char (buf, ch);

   for (rank = 3; rank < 6; rank++)
   {
      member_list = k->members;
      align = 0;

      if (k->ranks[4 + rank] == NULL ||
	  k->ranks[4 + rank][0] == '\0' ||
	  !str_cmp (k->ranks[rank - 1], k->ranks[4 + rank]))
      {
	 sprintf (buf, "\n\r%s#e:#w\n\r  ", k->ranks[rank - 1]);
      }
      else
      {
	 sprintf (buf,
		  "\n\r%s#e/#n%s#e:#w\n\r  ",
		  k->ranks[rank - 1], k->ranks[4 + rank]);
      }
      send_to_char (buf, ch);

      while ((m = get_member_of_rank (member_list, rank)) != NULL)
      {
	 align++;

	 if (align == 6)
	 {
	    send_to_char ("\n\r  ", ch);
	    align = 0;
	 }

	 sprintf (buf, "#w%s", m->name);
	 put_spc (buf, 15, TRUE);
	 send_to_char (buf, ch);

	 member_list = m->next;
      }
   }
   stc ("#b\n\r------------------------------------------------------------#n\n\r", ch);
   sprintf (buf, "#wThe %s #wKingdom has a QP balance of #r%d#n\n\r",
	    k->descr, k->materials[MAT_QUEST]);
   send_to_char (buf, ch);
   stc ("#b------------------------------------------------------------#n\n\r", ch);
}


/*
 * Immortal command to show kingdom info
 */

void do_kshow (CHAR_DATA * ch, char *argument)
{
   int i;
   KINGDOM_DATA *kingdom;
   int value;

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

   value = atoi (argument);
   for (i = 1, kingdom = king_first;
	kingdom != NULL && i < value; i++, kingdom = kingdom->next);

   if (kingdom == NULL)
   {
      return;
   }

   kshow (ch, kingdom);
}

/*
 * Display the list of existing kingdoms
 */

void do_kinglist (CHAR_DATA * ch, char *argument)
{
   char buf[MSL], buf2[MSL];
   KINGDOM_DATA *k;
   MEMBER_DATA *m;
   int i = 1;
   int pk_pd_ratio = 0;


   buf[0] = '\0';
   send_to_char ("\n\r", ch);
   stc ("#wThe Kingdoms of Legend of Chrystancia..\n\r", ch);

   stc ("#w[#rNUM#w] [#g       NAME        #w] [#y   LEADER   #w] [#b  PKS#w  ] [#p  PDS  #w] [#P RATIO #w] [#c  MEMBERS   #w]\n\r", ch);

   for (k = king_first; k; k = k->next)
   {

      m = get_member_of_rank (k->members, 1);

      if (k->pk_pd[1] > 0)
	 pk_pd_ratio = (k->pk_pd[0] * 100) / (k->pk_pd[1] + k->pk_pd[0]);
      else if (k->pk_pd[0] < 1)
	 pk_pd_ratio = 0;
      else
	 pk_pd_ratio = 100;
/*  
    if (k->pk_pd[0] == 0)
	 pk_pd_ratio = 0;
      else if (k->pk_pd[1] == 0)
	 pk_pd_ratio = 100;
      else
	 pk_pd_ratio = (k->pk_pd[0] / k->pk_pd[1]) * 100;
*/
      sprintf (buf2,
	       "#w[#r%3d#w] [#g%-19s#w] [#y%-12s#w] [#b%7d#w] [#p%7d#w] [#P%6d#w%%] [#c%12d#w]#n\n\r",
	       i++, mal_align (k->descr, 19, TRUE),
	       ((m != NULL) ? m->name : ""), k->pk_pd[0], k->pk_pd[1],
	       pk_pd_ratio, k->memnum);
      strcat (buf, buf2);
   }
   stc (buf, ch);

}


/*
 * Show what members of the player are on
 */

void do_kingdom (CHAR_DATA * ch, char *argument)
{
   DESCRIPTOR_DATA *d;
   char buf[MAX_STRING_LENGTH];
   char buf2[MAX_STRING_LENGTH];
   MEMBER_DATA *m1;
   MEMBER_DATA *m2;

   if ((m1 = get_kingdom_char (ch->name)) == NULL)
   {
      send_to_char ("Huh?\n\r", ch);
      return;
   }


   sprintf (buf, "#wThe '#y%s#w' clan.\n\r", m1->kingdom->descr);
   send_to_char (buf, ch);

   send_to_char
      ("#g[    Name    ] [ Hits  ] [ HPmax ] [ Mana  ] [ Move  ] [ Status  ] [   Rank   ]#n\n\r",
       ch);
   for (d = first_descriptor; d != NULL; d = d->next)
   {
      CHAR_DATA *wch;
      int rank;

      if (d->connected != CON_PLAYING)
	 continue;

      wch = (d->original != NULL) ? d->original : d->character;

      m2 = get_kingdom_char (wch->name);

      if (m2 == NULL || m2->kingdom != m1->kingdom)
	 continue;

      rank = m2->rank;
      if (wch->sex == SEX_MALE)
	 strcpy (buf2, m2->kingdom->ranks[rank - 1]);
      else if (m2->kingdom->ranks[rank + 4][0] == '\0')
	 strcpy (buf2, m2->kingdom->ranks[rank - 1]);
      else
	 strcpy (buf2, m2->kingdom->ranks[rank + 4]);

      sprintf (buf,
	       "#g[#n%-12s#g] [#n%7d#g] [#n%7d#g] [#n%7d#g] [#n%7d#g] [#n   %-3d   #g] [ #n%-8s #g]#n\n\r",
	       wch->name, wch->hit, wch->max_hit, wch->mana, wch->move,
	       wch->race, put_spc (buf2, 8, TRUE));
      send_to_char (buf, ch);
   }

}

void do_kresources (CHAR_DATA * ch, char *argument)
{
   KINGDOM_DATA *k;
   MEMBER_DATA *m;
   char buf[MAX_INPUT_LENGTH];

   if ((m = get_kingdom_char (ch->name)) == NULL)
   {
      send_to_char ("But you have no kingdom.\n\r", ch);
      return;
   }
   else
      k = m->kingdom;

   sprintf (buf, "Resources of the kingdom of %s#n:\n\r\n\r", k->descr);
   send_to_char (buf, ch);

   sprintf (buf, "    #yQPS#n: #C%d.\n\r", k->materials[MAT_QUEST]);
   send_to_char (buf, ch);
   sprintf (buf, "    #yGold#n: #C%d #npieces.\n\r", k->materials[MAT_GOLD]);
   send_to_char (buf, ch);
   sprintf (buf, "    #nStone#n: #C%d #nslabs.\n\r", k->materials[MAT_STONE]);
   send_to_char (buf, ch);
   sprintf (buf, "    #oWood#n: #C%d #nlogs.\n\r", k->materials[MAT_WOOD]);
   send_to_char (buf, ch);
   sprintf (buf, "    #0Steel#n: #C%d #nslabs.\n\r", k->materials[MAT_STEEL]);
   send_to_char (buf, ch);
}


void do_ktalk (CHAR_DATA * ch, char *argument)
{
   DESCRIPTOR_DATA *d;
   MEMBER_DATA *m1;
   MEMBER_DATA *m2;
   KINGDOM_DATA *k;
   char buf[MAX_STRING_LENGTH];
   char ibuf[MSL];
   char king[MSL];
   FILE *fp;
   char *nstr;
   char time_buf[MSL];
   time_t nowtime;
   struct tm *t;
   char *strtime;
   if ((m1 = get_kingdom_char (ch->name)) == NULL)
   {
      send_to_char ("Huh?\n\r", ch);
      return;
   }

   k = m1->kingdom;
   if (argument[0] == '\0')
   {
      send_to_char ("Ktalk what?\n\r", ch);
      return;
   }
   if (IS_SET (ch->act, PLR_SILENCE))
   {
      sprintf (buf, "You can't ktalk because you are silenced.\n\r");
      send_to_char (buf, ch);
      return;
   }
   for (d = first_descriptor; d != NULL; d = d->next)
   {
      CHAR_DATA *wch;
      bool CAN_VIEW = FALSE;

      if (d->connected != CON_PLAYING)
	 continue;

      wch = d->original ? d->original : d->character;

      if (IS_SET (wch->deaf, CHANNEL_KTALK))
	 continue;
      if (IS_JUDGE (wch))
	 CAN_VIEW = TRUE;

      if (!CAN_VIEW)
      {
	 if ((m2 = get_kingdom_char (wch->name)) == NULL)
	    continue;
      }

      if (!CAN_VIEW)
      {
	 if (m1->kingdom != m2->kingdom)
	    continue;
      }

      if (IS_IMMORTAL (wch))
      {
	 kingdom2 (ch, king);
	 sprintf (ibuf, "#w(#nKingdom #r%s#w)#n #y.x[#w%s#y]x. '#w%s#y'\n\r",
		  king, ch->name, argument);
	 send_to_char (ibuf, wch);
      }
      else
      {
	 sprintf (buf, "#y.x[#w%s#y]x. '#w%s#y'\n\r", ch->name, argument);
	 send_to_char (buf, wch);
      }
   }

   if (!(fp = fopen (KTALK_LOG_FILE, "a+")))
   {
      bug ("Cannot open KTALK_LOG_FILE!", 0);
   }
   else
   {
      char t_king[100];
      /*
       * We use this char in 'chatlog.dat' to represent start of line
       * Thus we cannot use it in chat... so strip it out...
       */
      nstr = switch_char (argument, '>', ' ');
      argument = nstr;

      nowtime = time (&current_time);
      t = localtime (&nowtime);

    time_buf[0] = '\0';
   
    strtime = asctime(gmtime(&current_time));
    strtime[strlen(strtime)-1] = '\0';
    strcat(time_buf, datestring(strtime)); 
    

      kingdom2 (ch, t_king);
      fprintf (fp, ">#w[#r%s#w] #c%20s #w%15s: #y%s#n\r\n", time_buf,
	       bash_color (t_king), ch->name, argument);
      fclose (fp);
   }
}

void do_atalk (CHAR_DATA * ch, char *argument)
{
   DESCRIPTOR_DATA *d;
   DIPLOMACY_DATA *diplomacy;
   MEMBER_DATA *m1;
   MEMBER_DATA *m2 = NULL;
   char buf[MAX_STRING_LENGTH];

   if ((m1 = get_kingdom_char (ch->name)) == NULL)
   {
      send_to_char ("Huh?\n\r", ch);
      return;
   }

   if (IS_SET (ch->act, PLR_SILENCE))
   {
      stc ("You can't Atalk.\n\r", ch);
      return;
   }

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

   for (d = first_descriptor; d != NULL; d = d->next)
   {
      CHAR_DATA *wch;

      diplomacy = NULL;

      if (d->connected != CON_PLAYING)
	 continue;

      wch = (d->original != NULL) ? d->original : d->character;

      if (!IS_IMMORTAL (wch) && (m2 = get_kingdom_char (wch->name)) == NULL)
	 continue;

      if (!IS_IMMORTAL (wch) && m1->kingdom != m2->kingdom)
	 for (diplomacy = m1->kingdom->diplomacy;
	      diplomacy->kingdom != m2->kingdom && diplomacy != NULL;
	      diplomacy = diplomacy->next);

      if (!IS_IMMORTAL (wch) && m1->kingdom != m2->kingdom
	  && (diplomacy == NULL || diplomacy->diplomacy != DIPL_ALLIANCE))
	 continue;

      sprintf (buf, "#r.x[#w%s#r]x. '#w%s#r'\n\r", ch->name, argument);
      send_to_char (buf, wch);
   }
}


void do_clannable (CHAR_DATA * ch, char *argument)
{
   char arg[MAX_INPUT_LENGTH];
   argument = one_argument (argument, arg);

   if (IS_NPC (ch))
      return;

   if (!IS_SET (ch->newbits, NEW_CLANNABLE))
   {
      send_to_char ("You are now clannable.\n\r", ch);
      SET_BIT (ch->newbits, NEW_CLANNABLE);
      return;
   }

   send_to_char ("You are no longer clannable.\n\r", ch);
   REMOVE_BIT (ch->newbits, NEW_CLANNABLE);
   return;
}

/* Diplomacy */

void do_kdeclare (CHAR_DATA * ch, char *argument)
{
   MEMBER_DATA *m;
   DIPLOMACY_DATA *d;
   char info_str[1024];
   char kingdom[128];
   char target[128];
   char diplomacy[128];

   m = get_kingdom_char (ch->name);

   if (m == NULL || m->rank > m->kingdom->cmd[KCMD_DECLARE])
   {
      send_to_char ("Huh?\n\r", ch);
      return;
   }

   argument = one_argument (argument, kingdom);
   argument = one_argument (argument, diplomacy);

   if (kingdom[0] == '\0' || diplomacy[0] == '\0')
   {
      send_to_char
         ("Syntax:  kdeclare <kingdom> neutral|war\n\r\n\r", ch);
//         ("Syntax:  kdeclare <kingdom> alliance|neutral|war\n\r\n\r", ch);
      return;
   }

   for (d = m->kingdom->diplomacy; d != NULL; d = d->next)
      if (!str_prefix (kingdom, d->kingdom->name))
	 break;

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

   if (d->kingdom == m->kingdom)
   {
      send_to_char ("Not on your own kingdom.\n\r\n\r", ch);
      return;
   }

   sprintf (kingdom, "%s%s%s", m->kingdom->open, m->kingdom->descr,
	    m->kingdom->close);
   sprintf (target, "%s%s%s", d->kingdom->open, d->kingdom->descr,
	    d->kingdom->close);

   if (!str_prefix (diplomacy, "war"))
   {
      sprintf (info_str, "%s #Chas declared the state of %s #Con %s#C.",
	       kingdom, "#rWar", target);
      do_info (ch, info_str);
      d->diplomacy = -1;
   }
   else if (!str_prefix (diplomacy, "neutral"))
   {
      sprintf (info_str, "%s #Chas declared the state of %s #Con %s#C.",
	       kingdom, "#cNeutrality", target);
      do_info (ch, info_str);
      d->diplomacy = 0;
   }
/*   else if (!str_prefix (diplomacy, "alliance"))
   {
      sprintf (info_str, "%s #Chas declared the state of %s #Con %s#C.",
	       kingdom, "#7Alliance", target);
      do_info (ch, info_str);
      d->diplomacy = 1;
   }*/
   else
   {
      send_to_char ("That diplomatic state is not acceptable.\n\r\n\r", ch);
      return;
   }

   do_save_kings (ch, "");
}

void do_kdiplomacy (CHAR_DATA * ch, char *argument)
{
   MEMBER_DATA *m = NULL;
   KINGDOM_DATA *kiter;
   DIPLOMACY_DATA *diplomacy1;
   DIPLOMACY_DATA *diplomacy2;
   char buf[1024];

   if (argument[0] == '\0' && (m = get_kingdom_char (ch->name)) == NULL)
   {
      send_to_char ("Please choose a kingdom.\n\r", ch);
      return;
   }

   for (kiter = king_first; kiter != NULL; kiter = kiter->next)
   {
      if (argument[0] != '\0' && !str_prefix (argument, kiter->name))
	 break;

      if (m != NULL && m->kingdom == kiter)
	 break;
   }

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

   sprintf (buf, "#CDiplomatic condition of #n%s%s%s#c:\n\r\n\r", kiter->open,
	    kiter->descr, kiter->close);
   send_to_char (buf, ch);

   send_to_char
      (" #C+#c---------------------------------------------------------------------------#C+\n\r",
       ch);
   send_to_char
      (" #c| #CK#7ingdom                   #c| #CC#7urrent       #c| #CT#7his #CK#7ingdom  #c| #CO#7ther #CK#7ingdom #c|\n\r",
       ch);
   send_to_char
      (" #C+#c---------------------------------------------------------------------------#C+\n\r",
       ch);

   for (diplomacy1 = kiter->diplomacy; diplomacy1 != NULL;
	diplomacy1 = diplomacy1->next)
   {
      char d1_str[32];;
      char d2_str[32];;
      char d3_str[32];;
      int diplomacy;
      char kingdom[128];

      if (diplomacy1->kingdom == kiter)
	 continue;

      for (diplomacy2 = diplomacy1->kingdom->diplomacy;
	   diplomacy2->kingdom != kiter; diplomacy2 = diplomacy2->next);

      diplomacy = diplomacy2->diplomacy;

      if (diplomacy1->diplomacy < diplomacy)
	 diplomacy = diplomacy1->diplomacy;

      switch (diplomacy)
      {
      case DIPL_ALLIANCE:
	 sprintf (d1_str, "#7Alliance");
	 break;
      case DIPL_NEUTRAL:
	 sprintf (d1_str, "#cNeutral");
	 break;
      case DIPL_WAR:
	 sprintf (d1_str, "#rWar");
	 break;
      }

      put_spc (d1_str, 13, TRUE);

      switch (diplomacy1->diplomacy)
      {
      case DIPL_ALLIANCE:
	 sprintf (d2_str, "#7Alliance");
	 break;
      case DIPL_NEUTRAL:
	 sprintf (d2_str, "#cNeutral");
	 break;
      case DIPL_WAR:
	 sprintf (d2_str, "#rWar");
	 break;
      }

      put_spc (d2_str, 13, TRUE);

      switch (diplomacy2->diplomacy)
      {
      case DIPL_ALLIANCE:
	 sprintf (d3_str, "#7Alliance");
	 break;
      case DIPL_NEUTRAL:
	 sprintf (d3_str, "#cNeutral");
	 break;
      case DIPL_WAR:
	 sprintf (d3_str, "#rWar");
	 break;
      }

      put_spc (d3_str, 13, TRUE);

      sprintf (kingdom, "%s%s%s", diplomacy1->kingdom->open,
	       diplomacy1->kingdom->descr, diplomacy1->kingdom->close);
      put_spc (kingdom, 25, TRUE);

      sprintf (buf, " #c| %s #c| %s #c| %s #c| %s #c|\n\r", kingdom, d1_str,
	       d2_str, d3_str);
      send_to_char (buf, ch);
   }

   send_to_char
      (" #C+#c---------------------------------------------------------------------------#C+\n\r\n\r",
       ch);
}

void do_kcmdset( CHAR_DATA *ch, char* argument )
{
   MEMBER_DATA *m;
   KINGDOM_DATA *k;
   char arg[MAX_INPUT_LENGTH];
   char buf[MAX_STRING_LENGTH];
   int i = 0;
      
   if ((m = get_kingdom_char (ch->name)) == NULL || m->rank > 1 )
   {
      send_to_char ("Huh?\n\r", ch);
      return;
   }

   k = m->kingdom;

   argument = one_argument(argument, arg);

   if( arg[0] == '\0' )
   {
      send_to_char ("Syntax:  kcmdset [command] [rank]\n\r", ch);
      send_to_char ("Rank goes from 1 to 5, being rank 1 the king.\n\r", ch);

      sprintf(buf, "\n\r#wKingdom Commands:\n\r\n\r");
      send_to_char(buf,ch);

      for( i = 0; i < KCMD_MAX; i++ )
      {
         sprintf(buf, "#w%s: usable by rank%s #y%d#w%s.\n\r",
            kcmd_table[i].command,
            k->cmd[kcmd_table[i].pos] > 1 ? "s" : "",
            k->cmd[kcmd_table[i].pos],
            k->cmd[kcmd_table[i].pos] > 1 ? " and below" : "");
         send_to_char(buf,ch);
      }

      return;
   }

   for( i = 0; kcmd_table[i].pos != KCMD_MAX; i++ )
   {
      if(str_prefix(arg, kcmd_table[i].command))
         continue;

      if(!is_number(argument))
      {
         send_to_char("Please insert a numeric rank.\n\r",ch);
         return;
      }

      if( atoi(argument) < 0 || atoi(argument) > 5 )
      {
         send_to_char ("Rank goes from 1 to 5, being rank 1 the king.\n\r", ch);
         return;
      }

      k->cmd[kcmd_table[i].pos] = atoi(argument);
      send_to_char("Rank set for that command.\n\r",ch);
      do_save_kings(ch,"");

      return;
   }

   if( kcmd_table[i].pos == KCMD_MAX )
   {
      send_to_char("There is no such command.\n\r",ch);
      return;
   }
}