/
mudd/docs/html/
mudd/world/
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "mud.h"

SOCIETY_DATA *
new_society (void)
{
  SOCIETY_DATA *soc;
  int i;
  soc = mem_alloc (sizeof (*soc));
  
  soc->next = NULL;
  soc->vnum = 0;
  soc->name = str_dup ("New Society");
  soc->room_start_vnum = 0;
  soc->flags = 0;
  soc->num_start_rooms = 0;
  for (i = 0; i < NUM_CASTES; i++)
    soc->caste[i] = NULL;
  soc->next = society_list;
  society_list = soc;
  return soc;
}
  

CASTE_DATA
*new_caste (void)
{
  
  CASTE_DATA *caste;
  int i;
  caste = mem_alloc (sizeof (*caste));
  caste->num_ranks = MAX_CASTE_RANKS;
  caste->mob_start_vnum = 0;
  caste->flags = 0;
  caste->name = str_dup ("New Caste");
  for (i = 0; i < MAX_CASTE_RANKS; i++)
    {
      caste->chance_to_advance[i] = 0;
      caste->curr_pop[i] = 0;
      caste->max_pop[i] = 0;
    }

  return caste;
}




void load_society (void)
{
  FILE *fp;
  char society_fname[100];
  

  sprintf (society_fname, "society.dat");
  
  if ((fp = fopen (society_fname, "r")) == NULL)
    {
      fprintf (stderr, "No Society Data To Load!\n");
      return;
    }
  
  for (;;)
    {
      char letter;
      char *word;
      letter = fread_letter (fp);
      if (letter != '#')
	{
	  bug ("Load_Society: # not found.", 0);
	  break;
	}
      word = feof (fp) ? "END" : fread_word (fp);
      if (!str_cmp (word, "SOCIETY"))
	{
	  fread_society (fp);
	}
      else if (!str_cmp (word, "END"))
	break;
      else 
	{
	  bug ("Load_society: bad section.", 0);
	  break;
	}
    }
  
  
  fclose (fp);
  return;
}





void 
fread_society (FILE *fp)
     
{
  SOCIETY_DATA *soc;
  int j;
  int curr_caste = 0;
  soc = new_society ();
  for (;;)
    {
      char *word;

      word = feof (fp) ? "END" : fread_word (fp);
      if (!str_cmp (word, "END"))
	break;
      else if (!str_cmp (word, "Vnum"))
	{
	  soc->vnum = fread_number (fp);
	  top_society = UMAX (top_society, soc->vnum);
	}
      else if (!str_cmp (word, "Name"))
	soc->name = str_dup (fread_string (fp, NULL));
      else if (!str_cmp (word, "RoomStart"))
	soc->room_start_vnum = fread_number (fp);
      else if (!str_cmp (word, "RoomNumber"))
	soc->num_start_rooms = fread_number (fp);
      else if (!str_cmp (word, "SFlags"))
	soc->flags = fread_number (fp);
      else if (!str_cmp (word, "Caste"))
	{
	  curr_caste = fread_number (fp);
	  if (curr_caste < 0 || curr_caste >= NUM_CASTES)
	    continue;
	  if (!soc->caste[curr_caste])
	    soc->caste[curr_caste] = new_caste ();
	  for (;;)
	    {
	      word = feof (fp) ? "END" : fread_word (fp);
	      if (!str_cmp (word, "END"))
		break;
	      else if (!str_cmp (word, "NumRanks"))
		soc->caste[curr_caste]->num_ranks = fread_number (fp);
	      else if (!str_cmp (word, "Name"))
		{
		  if (soc->caste[curr_caste]->name)
		    free_string (soc->caste[curr_caste]->name);
		  soc->caste[curr_caste]->name = str_dup (fread_string (fp, NULL));
		}
	      else if (!str_cmp (word, "StartMob"))
		soc->caste[curr_caste]->mob_start_vnum = fread_number (fp);
	      else if (!str_cmp (word, "CFlags"))
		soc->caste[curr_caste]->flags = fread_number (fp);
	      else if (!str_cmp (word, "AdvanceChance"))
		{
		  for (j = 0; j < MAX_CASTE_RANKS; j++)
		    soc->caste[curr_caste]->chance_to_advance[j] = fread_number(fp);
		}
	     
	      else if (!str_cmp (word, "MaxPop"))
		{
		  for (j = 0; j < MAX_CASTE_RANKS; j++)
		    soc->caste[curr_caste]->max_pop[j] = fread_number(fp);
		}
	    }
	}
    }
  return;
}



void save_society (void)
{
  int i;
  SOCIETY_DATA *soc;
  char society_fname[100];
  FILE *fp;

  sprintf (society_fname, "society.dat");
  

  if ((fp = fopen (society_fname, "w")) == NULL)
    {
      fprintf (stderr, "BAD WRITE ON SOCIETY DATA!!!");
      perror (society_fname);
    }
  
  for (soc = society_list; soc != NULL; soc = soc->next)
    {
      if (!soc->caste[0] || soc->caste[0]->chance_to_advance[0] == 0)
	continue;
      fprintf (fp, "#SOCIETY\n");
      fprintf (fp, "Vnum %d\n", soc->vnum);
      fprintf (fp, "Name %s~\n", fix_string (soc->name));
      fprintf (fp, "RoomStart %d\n", soc->room_start_vnum);
      fprintf (fp, "RoomNumber %d\n", soc->num_start_rooms);
      fprintf (fp, "SFlags %d\n", soc->flags);
      for (i = 0; i < NUM_CASTES; i++)
	{
	  if (soc->caste[i])
	    {
	      fwrite_caste (soc, i , fp);
	    }
	}
      fprintf (fp, "END\n");
    }
  
  fprintf (fp, "#END\n");
  fclose (fp);
  
  return;
}


void
copy_society (SOCIETY_DATA *old, SOCIETY_DATA *new)
{
  int i, j;

  new->name = str_dup (old->name);
  new->room_start_vnum = old->room_start_vnum;
  new->num_start_rooms = old->num_start_rooms;
  new->vnum = old->vnum;
  new->flags = old->flags;
  for (i = 0; i < NUM_CASTES; i++)
    {
      if (old->caste[i])
	{
	  CASTE_DATA *cst, *ocst;
	  cst = new_caste();
	  ocst = old->caste[i];
	  cst->name = str_dup (ocst->name);
	  cst->num_ranks = ocst->num_ranks;
	  cst->mob_start_vnum = ocst->mob_start_vnum;
	  cst->flags = ocst->flags;
	  for (j = 0;j < MAX_CASTE_RANKS; j++)
	    {
	      cst->chance_to_advance[j] = ocst->chance_to_advance[j];
	      cst->max_pop[j] = number_range (ocst->max_pop[j]*3/4,
					      ocst->max_pop[j]*5/4);
	      cst->curr_pop[j] = 0;
	    }
	  new->caste[i] = cst;
	}
    }
  
  return;
}
void
fwrite_caste (SOCIETY_DATA *soc, int num, FILE *fp)
{
  
  int i;
  CASTE_DATA *caste;
  if (!soc->caste[num])
    return;
  else
    caste = soc->caste[num];
  fprintf (fp, "Caste %d\n", num);
  fprintf (fp, "NumRanks %d\n", caste->num_ranks);
  fprintf (fp, "Name %s~\n", fix_string (caste->name));
  fprintf (fp, "StartMob %d\n", caste->mob_start_vnum);
  fprintf (fp, "CFlags %d\n", caste->flags);
  fprintf (fp, "AdvanceChance ");
  for (i = 0; i < MAX_CASTE_RANKS; i++)
    {
      fprintf (fp, "%d ", caste->chance_to_advance[i]);
    }
  fprintf (fp, "\n");
  
  fprintf (fp, "MaxPop ");
  for (i = 0; i < MAX_CASTE_RANKS; i++)
    {
      fprintf (fp, "%d ", caste->max_pop[i]);
    }
  fprintf (fp, "\nEND\n");
  return;
  
}
  


void save_mobile_info (void)
{
  FILE *fp;
  char mob_filename[100];
  AFFECT_DATA *paf;
  int iHash;
  ROOM_DATA *room;
  CHAR_DATA *rch;
  RESET_DATA *reset;
  bool found = FALSE;
  sprintf (mob_filename, "mobiles.dat");
  
  if ((fp = fopen (mob_filename, "w")) == NULL)
    {
      perror ("mobiles.dat");
      return;
    }
  
  for (iHash = 0; iHash < HASH_MAX; iHash++)
    {
      for (room = room_hash[iHash]; room != NULL; room = room->next)
	{
	  for (rch = room->people; rch != NULL; rch = rch->next_in_room)
	    {
	      found = FALSE;
	      if (IS_PLAYER (rch) || rch->data_type == 50 || !rch->in_room)
		continue;
	      if (!rch->society)
		{
		  for (reset = room->resets; reset != NULL; reset = reset->next)
		    {
		      if (reset->command == 'M' &&
			  reset->rs_vnum == rch->pIndexData->vnum)
			{
			  found = TRUE;
			  break;
			}
		    }
		}
	      if (found)
		continue;
	      fprintf (fp, "#Mob %d %d %d %ld %ld %d %d %d %s~\n", 
		       rch->pIndexData->vnum,   rch->in_room->vnum,   
		       rch->society, rch->hit, 
		       rch->max_hit, rch->move, rch->max_move,
		       ((MASTER (rch) && IS_MOB (MASTER (rch)) && 
			MASTER(rch)->in_room == rch->in_room) ? 
		       MASTER(rch)->pIndexData->vnum : 0), 
		       (HUNTING (rch) ? HUNTING (rch) : "none"));
	      
	      for (paf = rch->affected; paf && paf != NULL; paf = paf->next)
		{
		  fprintf (fp, "AffectData %d %d %d %d %d %d %d %d\n",
			   paf->type,
			   paf->duration,
			   paf->modifier,
			   paf->location,
			   paf->aff[0],
			   paf->aff[1],
			   paf->aff[2],
			   paf->aff[3]);
		}
	      if (rch->carrying)
		fwrite_obj (rch, rch->carrying, fp, 0);
	      fprintf (fp, "END\n");
	    }
	}
    }
  fprintf (fp, "\n\n#END\n\n");
  fclose (fp);
  return;
}

void 
save_object_info (void)
{
  FILE *fp;
  char obj_filename[100];
  int hash;
  ROOM_DATA *room;
  sprintf (obj_filename, "objects.dat");
  
  if ((fp = fopen (obj_filename, "w")) == NULL)
    {
      perror ("Could not open objects.dat for write.");
      return;
    }
  
  for (hash = 0; hash < HASH_MAX; hash++)
    {
      for (room = room_hash[hash]; room != NULL; room = room->next)
	{
	  if (room->contents)
	    {
	      fwrite_obj (NULL, room->contents, fp, 0);
	    }
	}
    } 
  fprintf (fp, "\n\n#END\n\n");
  fclose (fp);
}


void 
fread_and_place_objects (void)
{
  FILE *fp;
  char obj_filename[100];
  
  sprintf (obj_filename , "objects.dat");
  
if ((fp = fopen (obj_filename, "r")) == NULL)
    {
      fprintf (stderr, "No objects data to load up!\n");
      return;
    }

  
  for (;;)
    {
      char letter;
      char *word;
      letter = fread_letter (fp);
      if (letter != '#')
	break;
      word = feof (fp) ? "END" : fread_word (fp);
      if (!str_cmp (word, "END"))
	break;
      if (!str_cmp (word, "OBJECT"))
	fread_obj (NULL, fp , 100);
    }
  fclose (fp);
  return;
}

 

void 
fread_and_place_mobiles (void)
{
  FILE *fp;
  char mob_filename[100];
  CHAR_DATA *ch, *rch;
  int follownum, i;
  sprintf (mob_filename , "mobiles.dat");
  if ((fp = fopen (mob_filename, "r")) == NULL)
    {
      fprintf (stderr, "No mobiles data to load up!\n");
      return;
    }


  for (;;)
    {
      char letter;
      char *word;
      
      letter = fread_letter (fp);
      if (letter != '#')
	{
	  fprintf (stderr, "Missing # in mobiles.dat.\n");
	  break;
	}
      word = feof (fp) ? "END" : fread_word (fp);
      if (!str_cmp (word, "Mob"))
	{
	  place_one_mob (fp);
	  
	}
      else if (!str_cmp (word, "END"))
	break;
      else 
	{
	  fprintf (stderr, "BAD WORD READ IN MOBILES.DAT: %s\n", word);
	}
    }
  fclose (fp);
  for (i = 0; i < TOTAL_LIST; i++)
    {
      for (ch = char_list[i]; ch != NULL; ch = ch->next)
	{
	  if (ch->fgt && ch->fgt->hunting && is_number (ch->fgt->hunting))
	    {
	      follownum = atoi (ch->fgt->hunting);
	      free_string (ch->fgt->hunting);
	      ch->fgt->hunting = NULL;
	      for (rch = ch->in_room->people; rch != NULL; rch = rch->next_in_room)
		{
		  if (rch == ch || IS_PLAYER (rch) ||
		      rch->pIndexData->vnum != follownum)
		    continue;
		  add_follower (ch, rch);
		  break;
		}
	    }
	}
    }
  return;
}


void place_one_mob (FILE *fp)
{
  
  int vnum;
  CHAR_DATA *ch;
  MOB_PROTOTYPE *pMob;
  int room_num, i;
  ROOM_DATA *pRoom;
  SOCIETY_DATA *soc;
  int following;
  char *t;
  char follownum[20];
  char *hunting_string = NULL;
  vnum = fread_number (fp);
  room_num = fread_number (fp);
  if ((pMob = get_mob_index (vnum)) == NULL)
    {
      fprintf (stderr, "Attempted to load nonexistent mob number: %d.\n", vnum);
      return;
    }
  if ((pRoom = get_room_index (room_num)) == NULL)
    {
      fprintf (stderr, "Attempted to load mob into nonexistent room: %d.\n", room_num);
      return;
    }
  
  ch = create_mobile (pMob);
  ch->society = fread_number (fp);
  ch->hit = fread_number (fp);
  ch->max_hit = fread_number (fp);
  ch->move = fread_number (fp);
  ch->max_move = fread_number (fp);
  following = fread_number (fp);
  hunting_string = str_dup (fread_string(fp, NULL));
  if (str_cmp (hunting_string, "none"))
    {
      check_fgt(ch);
      if (ch->fgt->hunting)
	free_string (ch->fgt->hunting);
      ch->fgt->hunting = t;
    }
  if (following > 0)
    {
      check_fgt (ch);
      sprintf (follownum, "%d", following);
      if (ch->fgt->hunting)
	free_string (ch->fgt->hunting);
      ch->fgt->hunting = str_dup (follownum);
    }
  char_to_room (ch, pRoom);
  if (ch->society && (soc = society_lookup (NULL, ch->society)) != NULL)
    {
      for (i = 0; i < NUM_CASTES; i++)
	{
	  if (soc->caste[i] && ch->pIndexData->vnum >= soc->caste[i]->mob_start_vnum && ch->pIndexData->vnum < soc->caste[i]->mob_start_vnum + UMIN(soc->caste[i]->num_ranks, MAX_CASTE_RANKS))
	    {
	      soc->caste[i]->curr_pop[ch->pIndexData->vnum - soc->caste[i]->mob_start_vnum]++;
	      break;
	    }
	}
    }
  
  for (;;)
    {
      char *word;
      word = feof (fp) ? "END" : fread_word (fp);
      if (!str_cmp ("END", word))
	break;
      else if (!str_cmp (word, "AffectData"))
	{
	  AFFECT_DATA *paf;
	  if (affect_free == NULL)
	    {
	      paf = mem_alloc (sizeof (*paf));
	    }
	  else
	    {
	      paf = affect_free;
	      affect_free = affect_free->next;
	    }
	  paf->type = fread_number (fp);
	  paf->duration = fread_number (fp);
	  paf->modifier = fread_number (fp);
	  paf->location = fread_number (fp);
	  paf->aff[0] = fread_number(fp);
	  paf->aff[1] = fread_number(fp);
	  paf->aff[2] = fread_number(fp);
	  paf->aff[3] = fread_number(fp);
	  paf->next = ch->affected;
	  ch->affected = paf;
	}
      else if (!str_cmp ("#OBJECT", word))
	{
	  fread_obj (ch, fp, 0);
	}
      else
	{
	  fprintf (fp, "BAD WORD READ IN MOBILES.DAT: %s.\n", word);
	}
    }
  return;




}



  
SOCIETY_DATA*
society_lookup (char *name, int vnum)

{

  /* This may have to be hashed later on, but not likely as there
     will probably be very few socities made. */


  SOCIETY_DATA *soc;
  for (soc = society_list; soc != NULL; soc = soc->next)
    {
      if (soc->vnum == vnum ||
	  !str_cmp (soc->name, name))
	return soc;
    }
  return NULL;
}


void 
do_society (CHAR_DATA *ch, char *argy)
{
  SOCIETY_DATA *soc;
  int num_castes, i, j;
  char buf[STD_LENGTH];
  char arg1[SML_LENGTH];
  int society_number = -1;
  char buf1[100];
  
  DEFINE_COMMAND ("society", do_society, POSITION_DEAD, MAX_LEVEL, LOG_NORMAL, "This lists all of the societies in the game!")
    
    if (IS_MOB (ch))
      return;
  
  argy = one_argy (argy, arg1);
  
  if (arg1[0] == '\0' || arg1 == "")
    {
      send_to_char ("Syntax: Society list, or Society <name> or Society <number>\n\r", ch);
      return;
    }
  
  if (!str_cmp (arg1, "list"))
    {
      for (soc = society_list; soc != NULL; soc = soc->next)
	{
	  num_castes = 0;
	  for (i = 0; i < NUM_CASTES; i++)
	    {
	      if (soc->caste[i])
		num_castes++;
	    }
	  sprintf (buf, "[%d] %15s:  Room Start: %6d  Num Castes: %d\n\r", soc->vnum, soc->name, soc->room_start_vnum, num_castes);
	  send_to_char (buf, ch);
	}
      return;
    }

  if (!str_cmp (arg1, "purge") && is_number (argy))
    {
      int i = atoi(argy);
      SOCIETY_DATA *soc;
      if ((soc = society_lookup (NULL, i)) != NULL)
	{
	  CHAR_DATA *rch, *rchn;
	  for (j = 0; j < TOTAL_LIST -1; j++)
	    {
	      for (rch = char_list[j]; rch ; rch = rchn)
		{
		  rchn = rch->next;
		  if (IS_MOB (rch) && rch->society == i)
		    {
		      extract_char (rch, TRUE);
		    }
		}
	    }
	  send_to_char ("Ok, society purged of mobs.\n\r", ch);
	  return;
	}
      else
	{
	  send_to_char ("Society purge <number>\n\r", ch);
	  return;
	}
    }
  
  if (!str_cmp (arg1, "update") && LEVEL (ch)  == MAX_LEVEL)
    {
      update_society ();
      send_to_char ("All societies updated once.\n\r", ch);
      return;
    }


  if (is_number (arg1))
    society_number = atoi (arg1);
  if ((soc = society_lookup (arg1, society_number)) != NULL)
    {
      sprintf (buf, "[%d] %15s  Flags: %d   Room Start: %6d  Num Rooms: %d\n\r", soc->vnum, soc->name, soc->flags, soc->room_start_vnum, soc->num_start_rooms);
      send_to_char (buf, ch);
      for (i = 0; i < NUM_CASTES; i++)
	{
	  if (soc->caste[i])
	    {
	      sprintf (buf, "[%d] %-12s Start: %d  ", i, 
		       (soc->caste[i]->name ? 
			soc->caste[i]->name : "No Name"),
		       soc->caste[i]->mob_start_vnum);
	      strcat (buf, "Adv  (Cpop/Mpop):\n\r ");
	      for (j = 0; j < UMIN (soc->caste[i]->num_ranks, MAX_CASTE_RANKS); j++)
		{
		  sprintf (buf1, "%2d (\x1b[1;31m%2d\x1b[0;37m/\x1b[1;37m%2d\x1b[0;37m)   ", 
			   soc->caste[i]->chance_to_advance[j], soc->caste[i]->curr_pop[j],
			   soc->caste[i]->max_pop[j]);
		  strcat (buf, buf1);
		}
	      strcat (buf, "\n\r");
	      send_to_char (buf, ch);
	    }
	}
      return;
    }
  send_to_char ("Syntax: Society list, or Society <name> or Society <number> or Society update\n\r", ch);
  return;
}






void
update_society (void)
{
  
  CHAR_DATA *rch;
  CHAR_DATA *rchn;
  SOCIETY_DATA *soc;
  SINGLE_OBJECT *obj;
  MOB_PROTOTYPE *pMob;
  ROOM_DATA *room;
  int room_num;
  int i, j;
  bool found = FALSE;
  int rank = -1;
  CASTE_DATA *cst;
  int num_raw;
  int total_pop = 0;
  bool top_in_castes;
  
  /* Update growth in societies and make them do things */
  if (--pulse_society < 0)
    pulse_society = MOB_LIST;
  for (rch = char_list[pulse_society]; rch != NULL; rch = rchn)
    {
      rchn = rch->next;
      found = FALSE;
      
      if (IS_PLAYER(rch) || !rch->society || !rch->in_room ||
	  (soc = society_lookup (NULL, rch->society)) == NULL )
	continue;
      
      /* Now pick the path of any child that has grown up. */
      
      if (soc->caste[0] &&
	  rch->pIndexData->vnum == 
	  (soc->caste[0]->mob_start_vnum +
	   soc->caste[0]->num_ranks - 1))
	{
	  for (i = 1; i < NUM_CASTES; i++)
	    {
	      if ((cst = soc->caste[i]) != NULL &&
		  number_percent () < cst->chance_to_advance[0] &&
		  ((pMob = get_mob_index (cst->mob_start_vnum)) != NULL) &&
		  cst->curr_pop[0] < cst->max_pop[0])
		{
		  CHAR_DATA *sch;
		  sch = create_mobile (pMob);
		  if (replace_mob (rch, cst->mob_start_vnum))
		    {
		      cst->curr_pop[0]++;
		      soc->caste[0]->curr_pop[soc->caste[0]->num_ranks -1]--;
		      if (IS_SET (cst->flags, CASTE_BUILDER))
			{
			  SINGLE_OBJECT *hammer;
			  SINGLE_OBJECT *anvil;
			  hammer = create_object (get_obj_index(90017), 0);
			  obj_to (hammer, rch);
			  wear_obj (rch, hammer, TRUE);
			  anvil = create_object (get_obj_index (90018), 0);
			  obj_to (anvil, rch);
			}
		      if (IS_SET (cst->flags, CASTE_GATHERER))
			{
			  SINGLE_OBJECT *pickaxe;
			  pickaxe = create_object (get_obj_index (20), 0);
			  obj_to (pickaxe, rch);
			  wear_obj (rch, pickaxe, TRUE);
			}
		    }
		  break;
		}
	    }
	}
      else
	{
	  for (i = 0; i < NUM_CASTES; i++)
	    {
	      /* Advance in a caste.... */
	      
	      if ((cst = soc->caste[i]) != NULL && 
		  (rank = (rch->pIndexData->vnum - cst->mob_start_vnum)) >= 0)
		{
		  if (rank < (cst->num_ranks -1) &&
		      (number_percent () < cst->chance_to_advance[rank + 1]) &&
		       (cst->curr_pop[rank + 1] < cst->max_pop[rank + 1]) &&
		      (pMob = get_mob_index (rch->pIndexData->vnum + 1)) != NULL)
		    {
		      if (replace_mob (rch, rch->pIndexData->vnum + 1))
			{
			  cst->curr_pop[rank + 1]++;
			  cst->curr_pop[rank]--;
			}
		      break;
		    }
		  if (IS_SET (cst->flags, CASTE_GATHERER))
		    {
		      if (number_range (1,3) == 2)
			do_mine (rch, "");
		      num_raw = 0;
		      for (obj = rch->carrying; obj != NULL; obj = obj->next_content)
			if (obj->pIndexData->item_type == ITEM_RAW)
			  num_raw++;
		      if (num_raw > 20 && number_range (1,3) == 2 &&
			  !HUNTING (rch))
			{
			  CASTE_DATA *cstt;
			  int lowvnum;
			  int upvnum;
			  for (i = 0; i < NUM_CASTES; i++)
			    {
			      if ((cstt = soc->caste[i]) != NULL &&
				  cstt != cst &&
				  IS_SET (cstt->flags, CASTE_BUILDER))
				{
				  lowvnum = cstt->mob_start_vnum;
				  upvnum = cstt->mob_start_vnum + cstt->num_ranks -1;
				}
			    }
			}
		    }
		  if (IS_SET (cst->flags, CASTE_BUILDER))
		    { 
		      send_to_char ("moo", rch);
		    }
		}
	    }
	}
    }
  
  for (soc = society_list; soc != NULL; soc = soc->next)
    {
      
      /* Check if the society was wiped out and possibly end it... */
      
      if ((cst = soc->caste[0]) != NULL &&
	  number_percent () < cst->chance_to_advance[0] &&
	  cst->curr_pop[0] < cst->max_pop[0])
	{
	  CHAR_DATA *sch;
	  room_num = soc->room_start_vnum + number_range (0, UMAX(0, soc->num_start_rooms));
	  if ((pMob = get_mob_index (cst->mob_start_vnum)) == NULL ||
	      ((room = get_room_index (room_num)) == NULL))
	    continue;
	  sch = create_mobile (pMob);
	  sch->society = soc->vnum;
	  cst->curr_pop[0]++;
	  char_to_room (sch, room);
	}
      
      total_pop = 0;
      top_in_castes = TRUE;
      for (i = 0; i < NUM_CASTES; i++)
	{
	  if ((cst = soc->caste[i]) != NULL)
	    {
	      for (j = 0; j < cst->num_ranks; j++)
		{
		  if (i > 0  && j == cst->num_ranks - 1 && 
		      cst->curr_pop[j] < cst->max_pop[j])
		    top_in_castes = FALSE;
		  total_pop += cst->curr_pop[j];
		}
	    }
	}
      if (total_pop == 0 && soc->caste[0] &&
	  IS_SET (soc->flags, SOCIETY_DESTRUCTIBLE) && number_range(1,2) == 2)
	soc->caste[0]->max_pop[0] = 0;
      if (!top_in_castes)
	continue;
      room = NULL;
      if (IS_SET(soc->flags, SOCIETY_SPAWNING) && number_range (1,10) == 2)
	{
	  for (i = 0; i < 10; i++)
	    {
	      if ((room = get_room_index (number_range(1,200000))) != NULL)
		break;
	    }
	}
      else if (IS_SET (soc->flags, SOCIETY_EXPANDING) && number_range(1,10))
	{
	  AREA_DATA *ar, *oldarea, *newarea;
	  ROOM_DATA *rid;
	  int hash, door, num_adjacent_areas, area_chosen, choice;
	  
	  if ((rid = get_room_index(soc->room_start_vnum)) == NULL)
	    continue;
	  else
	    oldarea = rid->area;
	  for (ar = area_first; ar != NULL; ar = ar->next)
	    REMOVE_BIT (ar->area_flags, AREA_TEMPFLAG);
	  for (hash = 0; hash < HASH_MAX; hash = hash++)
	    {
	      for (rid = room_hash[hash]; room != NULL; room = room->next)
		{
		  if (rid->area != oldarea)
		    continue;
		  for (door = 0; door < MAX_DIR; door++)
		    {
		      if (rid->exit[door] && rid->exit[door]->to_room)
			SET_BIT (rid->exit[door]->to_room->area->area_flags, AREA_TEMPFLAG);
		    }
		}
	    }
	  num_adjacent_areas = 0;
	  for (ar = area_first; ar != NULL; ar = ar->next)
	    {
	      if (IS_SET (ar->area_flags, AREA_TEMPFLAG))
		num_adjacent_areas++;
	    }
	  if (num_adjacent_areas < 2)
	    continue;
	  else
	    area_chosen = number_range(1,num_adjacent_areas);
	  newarea = NULL;
	  choice = 0;
	  for (ar = area_first; ar != NULL; ar = ar->next)
	    {
	      if (IS_SET (ar->area_flags, AREA_TEMPFLAG))
		{
		  choice++;
		}
	      if (choice == area_chosen)
		{
		  newarea = ar;
		  break;
		}
	    }
	  for (ar = area_first; ar != NULL; ar = ar->next)
	    {
	      REMOVE_BIT (ar->area_flags, AREA_TEMPFLAG);
	    }
	  if (newarea)
	    {
	      room = NULL;
	      for (i = 0; i < 10; i++)
		{
		  if ((room = get_room_index (number_range(newarea->lvnum, newarea->uvnum))) != NULL)
		    break;
		}
	    }
	}
      
      
      if (room)
	{
	  SOCIETY_DATA *newsoc;
	  bool caste_done[NUM_CASTES];
	  for (j = 0; j < NUM_CASTES; j++)
	    caste_done[j] = FALSE;
	  newsoc = new_society();
	  copy_society (soc, newsoc);
	  newsoc->vnum = ++top_society;
	  newsoc->flags |= SOCIETY_DESTRUCTIBLE;
	  newsoc->room_start_vnum = room->vnum;
	  for (rch = char_list[pulse_society]; rch != NULL; rch = rchn)
	    {
	      rchn = rch->next;
	      if (IS_MOB (rch) && rch->society == soc->vnum)
		{
		  for (j = 1; j < NUM_CASTES; j++)
		    {
		      if (newsoc->caste[j] && 
			  rch->pIndexData->vnum == soc->caste[j]->mob_start_vnum + soc->caste[j]->num_ranks -1)
			{
			  if (number_range(1,5) == 2)
			    {
			      char_from_room (rch);
			      char_to_room (rch, room);
			      soc->caste[j]->curr_pop[soc->caste[j]->num_ranks -1]--;
			      newsoc->caste[j]->curr_pop[newsoc->caste[j]->num_ranks -1]++;
			      rch->society = newsoc->vnum;
			      caste_done[j] = TRUE;
			    }
			  else if (number_range(1,2) == 2)
			    {
			      char_from_room(rch);
			      extract_char (rch, TRUE);
			    }
			}
		      
		    }
		}
	    }
	}
    }       
  save_society ();
  return;
}


bool
replace_mob (CHAR_DATA *ch, int vnum)
{
  int oldhp, oldmaxhp, oldmove, oldmaxmove, i;
  MOB_PROTOTYPE *pMob;
  
  if ((pMob = get_mob_index (vnum)) == NULL || !ch || IS_PLAYER (ch))
    return FALSE;
  
  oldhp = ch->hit;
  oldmaxhp = ch->max_hit;
  if (oldmaxhp < 1)
    oldmaxhp = 1;
  oldmove = ch->move;
  oldmaxmove = ch->max_move;
  if (oldmaxmove < 1)
    oldmaxmove = 1;
  ch->pIndexData = pMob;
  for (i = 0; i < 4; i++)
    {
      ch->aff[i] |= pMob->aff[i];
    }
  ch->max_hit = UMAX(10+10*ch->pIndexData->level,
		      ch->pIndexData->level*ch->pIndexData->level *
		      ch->pIndexData->level/1000); 

  ch->max_hit += number_range(0, ch->max_hit/10);
  
  ch->max_move = 100 + (2+ IS_SET(ch->pIndexData->act, ACT_MOUNTABLE)*4)*ch->pIndexData->level;
  ch->max_move += number_range(0, ch->max_move/10);
  if (ch->max_move > 30000 || ch->max_move < 100)
    ch->max_move = number_range(200, 1200);
  ch->damroll = 2 + ch->max_hit / (number_range (36, 48));

  ch->max_hit = (ch->max_hit * 10 * (pMob->hpmult > 1000 ? (pMob->hpmult % 1000) : pMob->hpmult)) / 100;
  if (ch->max_hit <= 1)
    {
      ch->max_hit = 10;
    }
  ch->hit = ch->max_hit * PERCENTAGE (oldhp, oldmaxhp)/100;
  ch->move = ch->max_move * PERCENTAGE (oldmove, oldmaxmove)/100;
  
  add_char_to_list (ch);
  return TRUE;
}

void 
do_sociedit (CHAR_DATA * ch, char *argy)
{
  int value;
  SOCIETY_DATA *soc;
  DEFINE_COMMAND ("sociedit", do_sociedit, POSITION_DEAD, MAX_LEVEL, LOG_NORMAL, "The society editor: yay!")

    if (IS_MOB (ch))
      return;
 
  if (!str_cmp (argy, "create"))
    {
      soc = new_society ();
      top_society++;
      soc->vnum = top_society;
      changed_societies = TRUE;
      ch->desc->pEdit = (void *) soc;
      ch->desc->connected = CON_SOCIEDITOR;
      show_society (ch, soc, -1);
      return;
    }
  
  if (is_number (argy))
    value = atoi (argy);
  else 
    value = -1;
  if ((soc = society_lookup ( (argy[0] ? argy : NULL), value)) != NULL)
    {
      ch->desc->pEdit = (void *) soc;
      ch->desc->connected = CON_SOCIEDITOR;
      
      show_society (ch, soc, -1);
      return;
    }
  
  send_to_char ("Syntax: SOCIEDIT <number>, SOCIEDIT <name>, SOCIEDIT CREATE.\n\r", ch);
  return;
}

void sociedit (CHAR_DATA *ch, char *argy)
{

  char *oldarg = argy;
  CASTE_DATA *caste = NULL;
  char arg1[SML_LENGTH];
  char arg2[SML_LENGTH];
  char arg3[SML_LENGTH];
  char arg4[SML_LENGTH];
  char arg5[SML_LENGTH];
  char buf[SML_LENGTH];
  int value = 0;
  int value2 = 0;
  int caste_num = -1;
  SOCIETY_DATA *soc = (SOCIETY_DATA *) ch->desc->pEdit;
  
  if (!soc)
    {
      interpret (ch, argy);
      return;
    }
  
  arg1[0] = '\0';
  arg2[0] = '\0';
  
  argy = one_argy (argy, arg1);
  if (arg1[0] == '\0')
    {
      show_society (ch, soc, -1);
      return;
    }
  if (!str_cmp (arg1, "done"))
    {
      ch->desc->pEdit = NULL;
      ch->desc->connected = CON_PLAYING;
      sprintf (arg1, "\x1B[1;%dr\x1B[2J\x1B[%d;1f", ch->pcdata->pagelen, ch->pcdata->pagelen);
      send_to_char (arg1, ch);
      return;
    }
  if (!str_cmp ("name", arg1))
    {
      if (argy[0] == '\0' || argy == "")
	{
	  send_to_char ("Syntax: Name <string>\n\r", ch);
	  return;
	}
      if (soc->name)
	{
	  free_string (soc->name);
	}
      argy[0] = UPPER (argy[0]);
      soc->name = str_dup (argy);
      changed_societies = TRUE;
      show_society (ch, soc, 1);
      return;
    }

  argy = one_argy (argy, arg2);
  
  if (!str_cmp (arg1, "room_start"))
    {
      if (is_number (arg2))
	value = atoi (arg2);
      else
	{
	  send_to_char ("Syntax room_start <number>\n\r", ch);
	  return;
	}
      soc->room_start_vnum = atoi (arg2);
      changed_societies = TRUE;
      show_society (ch, soc, 1);
      return;
    }
  if (!str_cmp (arg1, "num_rooms"))
    {
      if (is_number (arg2))
	value = atoi (arg2);
      else
	{
	  send_to_char ("Syntax num_rooms <number>\n\r", ch);
	  return;
	}
      soc->num_start_rooms = atoi (arg2);
      changed_societies = TRUE;
      show_society (ch, soc, 1);
      return;
    }
  
  if (society_name_bit (arg1) != 0)
    {
      send_to_char ("Flag toggled\n\r", ch);
      TOGGLE_BIT (soc->flags, society_name_bit (arg1));
      changed_societies = TRUE;
      show_society (ch, soc, 2);
      return;
    }
  if (!str_cmp (arg1, "caste"))
    {
      if (is_number (arg2) || atoi (arg2) < 0 || atoi (arg2) >= NUM_CASTES)
	caste_num = atoi(arg2);
      else
	{
	  send_to_char ("Syntax caste <caste number> <what to change>.\n\r", ch);
	  return;
	}
     

      if (!str_cmp (argy, "delete"))
	{
	  if (!soc->caste[caste_num])
	    {
	      send_to_char ("There was no caste there to delete.\n\r", ch);
	      return;
	    }
	  if (soc->caste[caste_num]->name)
	    free_string (soc->caste[caste_num]->name);
	  free_m (soc->caste[caste_num]);
	  soc->caste[caste_num] = NULL;
	  send_to_char ("Ok, the caste was deleted.\n\r", ch);
	  changed_societies = TRUE;
	  show_society (ch, soc, 3 + caste_num);
	  return;
	}
      if (!soc->caste[caste_num])
	{
	  soc->caste[caste_num] = new_caste ();
	  changed_societies = TRUE;
	}
      caste = soc->caste[caste_num];
      
      argy = one_argy (argy, arg3);
      argy = one_argy (argy, arg4); 
      if (caste_name_bit (arg3) != 0)
	{
	  send_to_char ("Caste flag toggled\n\r", ch);
	  TOGGLE_BIT (caste->flags, caste_name_bit (arg3));
	  changed_societies = TRUE;
	  show_society (ch, soc, 3 + caste_num);
	  return;
	}
      
      
      if (is_number (arg4))
	value = atoi (arg4);
      else
	value = -1;
      if (!str_cmp (arg3, "name"))
	{
	  if (arg4[0] == '\0' || arg4 == "")
	    {
	      send_to_char ("Syntax Caste <number> name <Name of caste>.\n\r", ch);
	      return;
	    }
	  if (caste->name)
	    free_string (caste->name);
	  arg4[0] = UPPER (arg4[0]);
	  caste->name = str_dup (arg4);
	  changed_societies = TRUE;
	  show_society (ch, soc, 3 + caste_num);
	  return;
	}
      if (!str_cmp (arg3, "ranks") || !str_cmp (arg3, "rank"))
	{
	  if (value < 1 || value > MAX_CASTE_RANKS)
	    {
	      sprintf (buf, "The number of ranks must be a number between 1 and %d.\n\r", MAX_CASTE_RANKS);
	      send_to_char (buf, ch);
	      return;
	    }
	  caste->num_ranks = atoi (arg4);
	  send_to_char ("The number of ranks is changed.\n\r", ch);
	  changed_societies = TRUE;
	  show_society (ch, soc, 3 + caste_num);
	  return;
	}
      if (!str_cmp (arg3, "mobstart") || !str_cmp (arg3, "mob_start") ||
	  !str_cmp (arg3, "start_vnum"))
	{
	  
	  caste->mob_start_vnum = atoi (arg4);
	  send_to_char ("The mob_vnum where this caste starts is changed.\n\r", ch);
	  changed_societies = TRUE;
	  show_society (ch, soc, 3 + caste_num);
	  return;
	}
      if (!str_cmp (arg3, "maxpop") || !str_cmp (arg3, "max_pop"))
	{
	  argy = one_argy (argy, arg5);
	  if (is_number (arg5))
	    value2 = atoi (arg5);
	  else
	    value2 = -1;
	  if (value < 0 || value2 < 0 || 
	      value > UMIN (MAX_CASTE_RANKS, caste->num_ranks) || 
	      value2 > 1000)
	    {
	      send_to_char ("Syntax: caste <caste_number> maxpop <rank_number> <value>\n\r", ch);
	      return;
	    }
	  caste->max_pop[value] = value2;
	  changed_societies = TRUE;
	  show_society (ch, soc, 3 + caste_num);
	  return;
	}
      
      if (!str_cmp (arg3, "adv_chance") || !str_cmp (arg3, "advance"))
	{
	  argy = one_argy (argy, arg5);
	  if (is_number (arg5))
	    value2 = atoi (arg5);
	  else
	    value2 = -1;
	  if (value < 0 || value2 < 0 || 
	      value > UMIN (MAX_CASTE_RANKS - 1, caste->num_ranks - 1) || 
	      value2 > 1000)
	    {
	      send_to_char ("Syntax: caste <caste_number> advance <rank_number> <value>\n\r", ch);
	      return;
	    }
	  caste->chance_to_advance[value] = value2;
	  changed_societies = TRUE;
	  show_society (ch, soc, 3 + caste_num);
	  return;
	}
    }
  interpret (ch, oldarg);
  return;
}


void 
show_society (CHAR_DATA *ch, SOCIETY_DATA *soc, int row)
{
  char buf[SML_LENGTH];
  char buf1[100];
  int i, j;
  if (!ch || !soc || IS_MOB (ch))
    return;
  
  
  if (row == -1)
    {
      sprintf (buf, "\x1B[1;1f\x1B[K\x1B[2;1f\x1B[K\x1B[3;1f\x1B[K\x1B[4;1f\x1B[K\x1B[5;1f\x1B[K\x1B[6;1f\x1B[K\x1B[7;1f\x1B[K\x1B[8;1f\x1B[K\x1B[9;1f\x1B[K\x1B[10;1f\x1B[K\x1B[11;1f\x1B[K\x1B[12;1f\x1B[K\x1B[13;1f\x1B[K\x1B[14;%dr", ch->pcdata->pagelen);



      send_to_char (buf, ch);
    } 
  if (row == -1 || row == 1)
    {
      send_to_char ("\x1B[1;1f\x1B[K", ch);
      sprintf (buf, "[%2d] %20s   Room Start: %d  Num Rooms: %d\n\r", soc->vnum, soc->name, soc->room_start_vnum, soc->num_start_rooms);
      send_to_char (buf, ch);
    }
  if (row == 2 || row == -1)
    {
      send_to_char ("\x1B[2;1f\x1B[K", ch);
      sprintf (buf, "Flags: %s\n\r", society_bit_name (soc->flags));
      send_to_char (buf, ch);
    }
  
  for (i = 0; i < NUM_CASTES; i++)
    {
      if (row == 3 + i || row == -1)
	{
	  sprintf (buf, "\x1b[%d;1f\x1b[K", 3 + i);
	  send_to_char (buf, ch);
	  if (!soc->caste[i])
	    {
	      sprintf (buf, "[%d] No Caste.\n\r", i);
	      send_to_char(buf, ch);
	    }
	  else
	    {
	      sprintf (buf, "[%d] %-12s  Start: %d ", i, 
		       (soc->caste[i]->name ? 
			soc->caste[i]->name : "No Name"), 
		       soc->caste[i]->mob_start_vnum);
	      strcat (buf, "Adv(Mpop): ");
	      for (j = 0; j < (UMIN (soc->caste[i]->num_ranks, MAX_CASTE_RANKS)); j++)
		{
		  sprintf (buf1, "%2d(\x1b[1;37m%2d\x1b[0;37m)", 
			   soc->caste[i]->chance_to_advance[j], 
			   soc->caste[i]->max_pop[j]);
		  strcat (buf, buf1);
		}
	    }
	  strcat (buf, "\n\r");
	  send_to_char (buf, ch);
	}
    }
  sprintf (buf, "\x1B[%d;1f", ch->pcdata->pagelen);
  send_to_char (buf, ch);
  return;
}
  


void 
update_area_control (void)
{
  AREA_DATA *ar;
  int i;
  MOB_PROTOTYPE *mob;

  for (i = 0; i < NUM_ALIGN; i++)
    {
      areas_controlled[NUM_ALIGN] = 0;
      max_area_power[NUM_ALIGN] = 0;
    }
  raidable = 0;
  for (ar = area_first; ar != NULL; ar = ar->next)
    {
      ar->power = 0;
      if (IS_SET (ar->area_flags, AREA_RAIDABLE))
	{
	  if (ar->alignment >= 0 && ar->alignment < NUM_ALIGN)
	    {
	      areas_controlled[ar->alignment]++;
	    }
	  else
	    {
	      ar->alignment = 0;
	    }
	  raidable++;
	}
    }
  for (i = 0; i < HASH_MAX; i++)
    {
      for (mob = mob_index_hash[i]; mob; mob = mob->next)
	{
	  mob->area->power += mob->level * mob->max_in_world;
	}
    }
  for (ar = area_first; ar; ar = ar->next)
    {
      if (ar->power > max_area_power[ar->alignment])
	max_area_power[ar->alignment] = ar->power;
    }
  return;
}

void
do_seize (CHAR_DATA * ch, char * argy)
{
  SINGLE_OBJECT *token;
  MOB_PROTOTYPE *mob;
  int i;
  AREA_DATA *ar;
  bool any_alive = FALSE;
  DEFINE_COMMAND ("seize", do_seize, POSITION_STANDING, 0, LOG_ALWAYS, "This command allows you to seize a city for your alignment. You must be in the war room to do it.\n\r")
    
    if (IS_MOB (ch))
      return;
  
  ar = ch->in_room->area;
  if (LEVEL (ch) < MAX_LEVEL)
    {

      
      if (ch->pcdata->alignment >= NUM_ALIGN || ch->pcdata->alignment < 1)
	{
	  send_to_char ("Those of your alignment cannot seize control of a city!\n\r", ch);
	  return;
	}
      
      if (!ch->in_room || ch->in_room->vnum != ch->in_room->area->lvnum)
	{
	  send_to_char ("You must be in the war room to seize control of the city!\n\r", ch);
	  return;
	}
      
      
      
      if (!IS_SET (ar->area_flags, AREA_RAIDABLE))
	{
	  send_to_char ("This area cannot be raided and seized!\n\r", ch);
	  return;
	}
      for (token = ch->carrying; token != NULL; token = token->next_content)
	{
	  if (token->pIndexData->vnum == WAR_TOKEN_VNUM)
	    break;
	}
      if (!token)
	{
	  send_to_char ("You must be holding a war token to seize control of a city.\n\r", ch);
	  return;
	}
      for (i = 0; i < HASH_MAX && !any_alive; i++)
	{
	  for (mob = mob_index_hash[i]; mob; mob = mob->next)
	    {
	      if (mob->vnum >= ar->lvnum && mob->vnum <= ar->uvnum && mob->count > 0)
		{
		  any_alive = TRUE;
		  break;
		}
	    }
	}
      if (any_alive)
	{
	  send_to_char ("You have failed to kill all of the creatures in this city!\n\r", ch);
	  obj_from (token);
	  free_it (token);
	  return;
	}
      ar->lastkiller = ch->pcdata->online_spot;
      set_area_align (ar, ch->pcdata->alignment, ch);
      obj_from (token);
      free_it (token);
      return;
    }
  else
    {
      ar->lastkiller = ch->pcdata->online_spot;
      ar->area_flags |= AREA_RAIDABLE;
      if (is_number (argy) && atoi (argy) >= 0 && atoi (argy) < NUM_ALIGN)
	{
	  set_area_align (ar, atoi(argy), ch);
	}
      else
	{
	  set_area_align (ar, ch->pcdata->alignment, ch);
	}
      ar->lastkiller = NULL;
      send_to_char ("Ok, area alignment set.\n\r", ch);     
      return;
    }
  return;
}

void 
set_area_align (AREA_DATA *ar, int align, CHAR_DATA *ch)
{
  CHAR_DATA *sch;
  int i;
  MOB_PROTOTYPE *mob;
  char buf[STD_LENGTH];
  
  if (!ar->lastkiller || align < 0 || align >= NUM_ALIGN)
    return;
  if (ar->alignment != align && (!ch || LEVEL (ch) < MAX_LEVEL))
    {
      sch = create_mobile (get_mob_index(1));
      char_to_room (sch, get_room_index(1));
      sprintf (buf, "Hear Ye! Hear Ye! %s and the %s forces have conquered %s, and it is now closed to all not allied with them! Beware!\n\r", ar->lastkiller->name, align_info[ar->lastkiller->alignment].name, ar->name);
      do_echo (sch, buf);
      extract_char (sch, TRUE);
    }
  ar->alignment = align;
  for (i = 0; i < HASH_MAX; i++)
    {
      for (mob = mob_index_hash[i]; mob != NULL; mob = mob->next)
	{
	  if (mob->vnum >= ar->lvnum && mob->vnum <= ar->uvnum)
	    {
	      mob->alignment = align;
	      if (align > 0)
		{
		  if (!ch || LEVEL(ch) < MAX_LEVEL)
		    {
		      mob->level += 5;
		    }
		  if (mob->guard && mob->guard->guarding_door)
		    {
		      SET_BIT (mob->act3, ACT3_GUARD_DOOR_ALIGN);
		      REMOVE_BIT (mob->act3, ACT3_GUARD_DOOR);
		    }
		  SET_BIT (mob->act4, ACT4_KILL_OPP);
		  REMOVE_BIT (mob->act, ACT_AGGRESSIVE | ACT_ANGRY);
		}
	      else
		{
		  REMOVE_BIT (mob->act4, ACT4_KILL_OPP);
		  REMOVE_BIT (mob->act3, ACT3_GUARD_DOOR_ALIGN);
		}
	    }
	}
    }
  SET_BIT (ar->area_flags, AREA_CHANGED);
  save_area_list ();
  save_area (ar);
  update_area_control ();
  return;
}


void 
do_control (CHAR_DATA * ch, char * argy)
{ 
  int align = NUM_ALIGN;
  char buf[SML_LENGTH];
  AREA_DATA *ar;
  int i;
  DEFINE_COMMAND ("control", do_control, POSITION_STANDING, 0, LOG_NORMAL, "This command lets you see the state of the areas under the control of the various alignments.\n\r")
    
    update_area_control();
  if (!str_cmp (argy, "full"))
    {
      sprintf (hugebuf_o, "All areas currently under control and who owns them:\n\n\r");
      for (i = 0; i < NUM_ALIGN; i++)
	{
	  sprintf (buf, "\n\n\r%s held cities:\n\n\r", align_info[i].name);
	  strcat (hugebuf_o, buf);
	  for (ar = area_first; ar != NULL; ar = ar->next)
	    {
	      if (IS_SET (ar->area_flags, AREA_RAIDABLE) &&
		  ar->alignment == i)
		{
		  sprintf (buf, "%30s held by %s with power %d.\n\r", ar->name, align_info[ar->alignment].name, ar->power);
		  strcat (hugebuf_o, buf);
		}
	    }
	}
      page_to_char (hugebuf_o, ch);
      return;
    }
    for (i = 0; i < NUM_ALIGN; i++)
      {
	if (!str_cmp (argy, align_info[i].name))
	  {
	    align = i;
	    break;
	  }
      }
  if (align != NUM_ALIGN)
    {
      do_areas (ch, align_info[i].name);
      return;
    }
  
  
  send_to_char ("This is the breakdown of the areas under control in the game:\n\r", ch);
  
  sprintf (buf, "\n\n\rNumber of raidable areas: %d\n\n\r", raidable);
  send_to_char (buf, ch);
  
  for (i = 0; i < NUM_ALIGN; i++)
    {
      sprintf (buf, "%s cities : %d    Max Power:   %d\n\r", align_info[i].name, areas_controlled[i], max_area_power[i]);
      send_to_char (buf, ch);
    }
  return;
}



void 
do_citymap (CHAR_DATA *ch, char *argy)
{
  AREA_DATA *ar;
  int i;
  char *t;
  char area_name[SML_LENGTH];
  DEFINE_COMMAND ("citymap", do_citymap, POSITION_STANDING, 0, LOG_NORMAL, "This command lets you see a map of what the cities under alignment control look like.")
    
    bzero (outp, sizeof(outp));
  bzero (colrs, sizeof(colrs));
  
  for (ar = area_first; ar != NULL; ar = ar->next)
    {
      if (IS_SET (ar->area_flags, AREA_RAIDABLE) &&
	  ar->alignment >= 0 && ar->alignment < NUM_ALIGN)
	{
	  outp[ar->x][ar->y -1] = '*';
	  colrs[ar->x][ar->y -1] = 8 + ar->alignment;
	  strcpy (area_name, ar->name);
	  t = area_name;
	  if (!str_prefix ("The City of", area_name))
	    {
	      while (*t && *t != 'f')
		t++;
	      t++;
	      t++;
	    }
	  else if (!str_prefix ("The ", area_name) ||
		   !str_prefix ("An ", area_name) ||
		   !str_prefix ("A ", area_name) ||
		   !str_prefix ("More ", area_name))
	    {
	      while (*t && *t != ' ')
		t++;
	      t++;
	    }
	  for (i = 0; i < 5; i++)
	    {
	      if ((ar->x + i + 1< 80) && outp[ar->x + i + 1][ar->y-1] == '\0')
		{
		  if (*t)
		    {
		      colrs[ar->x + i + 1][ar->y-1] = 7;
		      outp[ar->x + i + 1][ar->y-1] = *t;
		    }
		  t++;
		}
	    }
	}
    }
  ch->pcdata->maxx = 80;
  ch->pcdata->maxy = 25;
  do_rawclear(ch);
  draw_data (ch, 25);
  return;
}