dpr/cnf/
dpr/lib/
dpr/lib/house/
dpr/lib/misc/
dpr/lib/text/clan/
dpr/lib/text/help/
dpr/lib/world/
dpr/lib/world/qst/
dpr/src-backup/src/util/
dpr/src/
dpr/src/src code added/
diff -c -P -x *.o orig-src/Makefile src/Makefile
*** orig-src/Makefile	Mon Feb 24 23:00:32 1997
--- src/Makefile	Mon Feb 24 16:28:51 1997
***************
*** 22,28 ****
  	castle.o class.o config.o constants.o db.o fight.o graph.o handler.o \
  	house.o interpreter.o limits.o magic.o mail.o mobact.o modify.o \
  	objsave.o olc.o shop.o spec_assign.o spec_procs.o spell_parser.o \
! 	spells.o utils.o weather.o 
  
  default: .accepted
  	$(MAKE) ../bin/circle
--- 22,28 ----
  	castle.o class.o config.o constants.o db.o fight.o graph.o handler.o \
  	house.o interpreter.o limits.o magic.o mail.o mobact.o modify.o \
  	objsave.o olc.o shop.o spec_assign.o spec_procs.o spell_parser.o \
! 	spells.o utils.o weather.o clan.o
  
  default: .accepted
  	$(MAKE) ../bin/circle
***************
*** 139,152 ****
  class.o: class.c conf.h sysdep.h structs.h db.h utils.h spells.h interpreter.h
  	$(CC) -c $(CFLAGS) class.c
  comm.o: comm.c conf.h sysdep.h structs.h utils.h comm.h interpreter.h handler.h \
!   db.h house.h
  	$(CC) -c $(CFLAGS) comm.c
  config.o: config.c conf.h sysdep.h structs.h
  	$(CC) -c $(CFLAGS) config.c
  constants.o: constants.c conf.h sysdep.h structs.h
  	$(CC) -c $(CFLAGS) constants.c
  db.o: db.c conf.h sysdep.h structs.h utils.h db.h comm.h handler.h spells.h mail.h \
!   interpreter.h house.h
  	$(CC) -c $(CFLAGS) db.c
  fight.o: fight.c conf.h sysdep.h structs.h utils.h comm.h handler.h interpreter.h \
    db.h spells.h screen.h
--- 139,152 ----
  class.o: class.c conf.h sysdep.h structs.h db.h utils.h spells.h interpreter.h
  	$(CC) -c $(CFLAGS) class.c
  comm.o: comm.c conf.h sysdep.h structs.h utils.h comm.h interpreter.h handler.h \
!   db.h house.h clan.h
  	$(CC) -c $(CFLAGS) comm.c
  config.o: config.c conf.h sysdep.h structs.h
  	$(CC) -c $(CFLAGS) config.c
  constants.o: constants.c conf.h sysdep.h structs.h
  	$(CC) -c $(CFLAGS) constants.c
  db.o: db.c conf.h sysdep.h structs.h utils.h db.h comm.h handler.h spells.h mail.h \
!   interpreter.h house.h clan.h
  	$(CC) -c $(CFLAGS) db.c
  fight.o: fight.c conf.h sysdep.h structs.h utils.h comm.h handler.h interpreter.h \
    db.h spells.h screen.h
***************
*** 161,167 ****
    utils.h house.h
  	$(CC) -c $(CFLAGS) house.c
  interpreter.o: interpreter.c conf.h sysdep.h structs.h comm.h interpreter.h db.h \
!   utils.h spells.h handler.h mail.h screen.h
  	$(CC) -c $(CFLAGS) interpreter.c
  limits.o: limits.c conf.h sysdep.h structs.h utils.h spells.h comm.h db.h \
    handler.h
--- 161,167 ----
    utils.h house.h
  	$(CC) -c $(CFLAGS) house.c
  interpreter.o: interpreter.c conf.h sysdep.h structs.h comm.h interpreter.h db.h \
!   utils.h spells.h handler.h mail.h screen.h clan.h
  	$(CC) -c $(CFLAGS) interpreter.c
  limits.o: limits.c conf.h sysdep.h structs.h utils.h spells.h comm.h db.h \
    handler.h
***************
*** 175,181 ****
    handler.h spells.h
  	$(CC) -c $(CFLAGS) mobact.c
  modify.o: modify.c conf.h sysdep.h structs.h utils.h interpreter.h handler.h db.h \
!   comm.h spells.h mail.h boards.h
  	$(CC) -c $(CFLAGS) modify.c
  objsave.o: objsave.c conf.h sysdep.h structs.h comm.h handler.h db.h \
    interpreter.h utils.h spells.h
--- 175,181 ----
    handler.h spells.h
  	$(CC) -c $(CFLAGS) mobact.c
  modify.o: modify.c conf.h sysdep.h structs.h utils.h interpreter.h handler.h db.h \
!   comm.h spells.h mail.h boards.h clan.h
  	$(CC) -c $(CFLAGS) modify.c
  objsave.o: objsave.c conf.h sysdep.h structs.h comm.h handler.h db.h \
    interpreter.h utils.h spells.h
***************
*** 206,208 ****
--- 206,212 ----
  weather.o: weather.c conf.h sysdep.h structs.h utils.h comm.h handler.h \
    interpreter.h db.h
  	$(CC) -c $(CFLAGS) weather.c
+ clan.o: clan.c conf.h sysdep.h structs.h db.h utils.h spells.h \
+  interpreter.h screen.h clan.h
+ 	$(CC) -c $(CFLAGS) clan.c
+ 
diff -c -P -x *.o orig-src/act.offensive.c src/act.offensive.c
*** orig-src/act.offensive.c	Mon Feb 24 23:00:32 1997
--- src/act.offensive.c	Sat Feb  8 13:26:17 1997
***************
*** 25,30 ****
--- 25,33 ----
  extern struct descriptor_data *descriptor_list;
  extern struct room_data *world;
  extern int pk_allowed;
+ extern int summon_allowed;
+ extern int charm_allowed;
+ extern int sleep_allowed;
  
  /* extern functions */
  void raw_kill(struct char_data * ch);
diff -c -P -x *.o orig-src/act.wizard.c src/act.wizard.c
*** orig-src/act.wizard.c	Mon Feb 24 23:00:32 1997
--- src/act.wizard.c	Sun Feb  9 17:07:59 1997
***************
*** 41,46 ****
--- 41,53 ----
  extern int top_of_objt;
  extern int top_of_p_table;
  
+ /* (FIDO) Added allowed extern variables here for ACMD(do_world) */
+ extern int pk_allowed;
+ extern int sleep_allowed;
+ extern int charm_allowed;
+ extern int summon_allowed;
+ extern int roomaffect_allowed;
+ 
  /* for objects */
  extern char *item_types[];
  extern char *wear_bits[];
***************
*** 2480,2483 ****
--- 2487,2601 ----
  
    sprintf(buf, "Your syslog is now %s.\r\n", logtypes[tp]);
    send_to_char(buf, ch);
+ }
+ 
+ /* (FIDO) New command: world <field> <on|off>      */
+ /*        It modifies the global variables:        */ 
+ /*        pk/sleep/charm/summon/roomaffect_allowed */
+ void send_to_imms(char *msg)
+ {
+   struct descriptor_data *pt;
+ 
+   for (pt = descriptor_list; pt; pt = pt->next)
+     if (!pt->connected && pt->character && GET_LEVEL(pt->character) >= LVL_GOD)
+ 	send_to_char(msg, pt->character);
+ 
+ }
+ 
+ ACMD(do_world)
+ {
+   char field[MAX_INPUT_LENGTH];
+ 
+   half_chop(argument, field, buf);
+ 
+   if (strcmp(field, "pk") == 0)
+   { 
+     if (pk_allowed == 1)
+     {
+       pk_allowed = 0;
+       sprintf(buf, "[SYS: %s disallows PKilling]\r\n", GET_NAME(ch));
+       send_to_imms(buf);
+     }
+     else
+     {
+       pk_allowed = 1;
+       sprintf(buf, "[SYS: %s allows PKilling]\r\n", GET_NAME(ch));
+       send_to_imms(buf);
+     }
+   }
+   else if (strcmp(field, "sleep") == 0)
+   {
+     if (sleep_allowed == 1)
+     {
+       sleep_allowed = 0;
+       sprintf(buf, "[SYS: %s disallows players from casting sleep on each other]\r\n", GET_NAME(ch));
+       send_to_imms(buf);
+     }
+     else
+     {
+       sleep_allowed = 1;
+       sprintf(buf, "[SYS: %s allows players to cast sleep on each other]\r\n", GET_NAME(ch));
+       send_to_imms(buf);
+     }
+   }
+   else if (strcmp(field, "summon") == 0)
+   {
+     if (summon_allowed == 1)
+     {
+       summon_allowed = 0;
+       sprintf(buf, "[SYS: %s disallows players from summoning one another]\r\n", GET_NAME(ch));
+       send_to_imms(buf);
+     }
+     else
+     {
+       summon_allowed = 1;
+       sprintf(buf, "[SYS: %s allows players to summon one another]\r\n", GET_NAME(ch));
+       send_to_imms(buf);
+     }
+   }
+   else if (strcmp(field, "charm") == 0)
+   {
+     if (charm_allowed == 1)
+     {
+       charm_allowed = 0;
+       sprintf(buf, "[SYS: %s disallows players from charming one another]\r\n", GET_NAME(ch));
+       send_to_imms(buf);
+     }
+     else
+     {
+       charm_allowed = 1;
+       sprintf(buf, "[SYS: %s allows players to charm one another]\r\n", GET_NAME(ch));
+       send_to_imms(buf);
+     }
+   }
+   else if (strcmp(field, "roomaffect") == 0)
+   {
+     if (roomaffect_allowed == 1)
+     {
+       roomaffect_allowed = 0;
+       sprintf(buf, "[SYS: %s disallows room affect spells from hurting other players]\r\n", GET_NAME(ch));
+       send_to_imms(buf);
+     }
+     else
+     {
+       roomaffect_allowed = 1;
+       sprintf(buf, "[SYS: %s allows room affect spells to hurt other players]\r\n", GET_NAME(ch));
+       send_to_imms(buf);
+     }
+   }
+   else
+   {
+     send_to_char("[Current world status:]\r\n", ch);
+     if (pk_allowed == 1) send_to_char("Pkilling allowed,\r\n", ch);
+     if (pk_allowed == 0) send_to_char("Pkilling not allowed,\r\n", ch);
+     if (sleep_allowed == 1) send_to_char("Casting sleep on other players allowed,\r\n", ch);
+     if (sleep_allowed == 0) send_to_char("Casting sleep on other players not allowed,\r\n", ch);
+     if (summon_allowed == 1) send_to_char("Summoning other players allowed,\r\n", ch);
+     if (summon_allowed == 0) send_to_char("Summoning other players not allowed,\r\n", ch);
+     if (charm_allowed == 1) send_to_char("Charming other players allowed,\r\n", ch);
+     if (charm_allowed == 0) send_to_char("Charming other players not allowed,\r\n", ch);
+     if (roomaffect_allowed == 1) send_to_char("Room affect spells will hurt other players.\r\n", ch);
+     if (roomaffect_allowed == 0) send_to_char("Room affect spells will not hurt other players.\r\n", ch);
+   }
+ 
  }
diff -c -P -x *.o orig-src/clan.c src/clan.c
*** orig-src/clan.c	Thu Jan  1 10:00:00 1970
--- src/clan.c	Mon Feb 24 22:54:58 1997
***************
*** 0 ****
--- 1,2022 ----
+ /*
+ ************************************************************************
+ *   File: clan.c				    Addition to CircleMUD *
+ *  Usage: Source file for clan-specific code                              *
+ *                                                                         *
+ *  Copyright (c) to Daniel Muller					  *
+ *									  *
+ ************************************************************************ */
+ 
+ /*
+  * This file attempts to concentrate all of the clan specific code for the
+  * implementation of clans in CircleMUD.  I've tried to mimic the code 
+  * style of the rest of CircleMUD's code, to make it easier for you to
+  * modify as needed.
+ */
+ 
+ 
+ 
+ #include "conf.h"
+ #include "sysdep.h"
+ #include "string.h"
+ 
+ #include "structs.h"
+ #include "db.h"
+ #include "utils.h"
+ #include "spells.h"
+ #include "interpreter.h"
+ #include "comm.h"
+ #include "screen.h"
+ #include "clan.h"
+ #include "handler.h"
+ 
+ #define YES 	1
+ #define NO 	0
+ 
+ /*   external vars  */
+ extern struct clan_info *clan_index;
+ extern struct descriptor_data *descriptor_list;
+ extern char *class_abbrevs[];
+ extern FILE *player_fl;
+ extern int clan_top;
+ extern int mini_mud;
+ 
+ /* Local functions */
+ void prepare_colour_table(struct char_data *ch);
+ void update_clan_cross_reference();
+ void clan_save(int system, struct char_data *ch);
+ void write_clan(FILE *fl, int cnum);
+ void display_menu(struct char_data *ch, int cnum);
+ int is_clannum_already_used(int cnum);
+ void update_cnum(int oldcnum, int newcnum);
+ void setup_new_clan(struct char_data *ch, int cnum);
+ void setup_clan_edit(struct char_data *ch, int cnum);
+ void cleanup_clan_edit(struct descriptor_data *d, int method);
+ void refresh_clan_index();
+ void display_rank_menu(struct descriptor_data *d, int num);
+ void display_colour_menu(struct descriptor_data *d);
+ void fix_illegal_cnum();
+ int debug_clan(char *what, struct char_data *ch);
+ int already_being_edited(int cnum);
+ 
+ /*
+  * Clan levels
+ */
+ const int CLAN_APPLY = 1;
+ const int CLAN_SOLDIER = 2;
+ const int CLAN_SARGEANT = 3;
+ const int CLAN_CAPTAIN = 4;
+ const int CLAN_RULER = 5;
+ 
+ /* Define cross reference table */
+ int cross_reference[9999];
+ 
+ /* Define quick reference for colours (global) */
+ struct clan_colours clan_colour[8];
+ 
+ /* Define clan editing table */
+ struct clan_editing clan_edit[10];
+ 
+ /*
+  * 			General functions go here
+ */
+ 
+ 
+ 
+ 
+ /*
+  * The general player commands go here
+ */
+ ACMD(do_clan)
+ {
+   char subbcmd[MAX_INPUT_LENGTH], val_arg[MAX_INPUT_LENGTH];
+   int  players_clan = 0, players_clannum = 0, ccmd = 0, value = 0, found = 0, temp = 0, temp2 = 0;
+   struct char_data *vict = NULL;
+   struct descriptor_data *pt;
+ 
+   half_chop(argument, subbcmd, buf);
+   strcpy(val_arg, buf);
+ 
+   /* if (ch) belongs to a clan, find its number in the index array */
+   if (!((PLAYERCLANNUM(ch) == 0) && (CLANRANK(ch) == 0)))
+     for (ccmd = 0; ccmd <= clan_top; ccmd++)
+       if (CLANNUM(clan_index[ccmd]) == PLAYERCLAN(ch))
+       {
+         players_clannum = ccmd;
+ 	players_clan = CLANNUM(clan_index[ccmd]);
+       }
+ 
+   if (players_clan == 0)
+     players_clan = -1;
+ 
+   /* Prepare the colour table for this player */
+   prepare_colour_table(ch);
+ 
+   /* Update clan cross reference */
+   update_clan_cross_reference();
+ 
+   if (strcasecmp(subbcmd, "debug") == 0)
+   {
+ 
+     if (GET_LEVEL(ch) != LVL_IMPL)
+     {
+       send_to_char("Huh?!\r\n", ch);
+       return;
+     }
+ 
+     /* Debug clan variables */
+     if (debug_clan(val_arg, ch) == NO)
+       send_to_char("Debug dump not written to disk.\r\n", ch);
+     else
+       send_to_char("Debug dump complete.\r\n", ch);
+     return;
+   }
+ 
+   if (strcasecmp(subbcmd, "save") == 0)
+   {
+     /* Save clans */
+     if (!(GET_LEVEL(ch) >= LVL_GOD))
+     {
+       send_to_char("Huh?!", ch);
+       return;
+     }
+     clan_save(NO, ch);
+     return;
+   }
+ 
+   if (strcasecmp(subbcmd, "edit") == 0)
+   {
+     if (!(GET_LEVEL(ch) == LVL_IMPL))
+     {
+       send_to_char("Huh?!", ch);
+       return;
+     }
+   
+     value = atoi(val_arg);
+     if (value == 0)
+     {
+       send_to_char("Zero is an illegal clan number.\r\n", ch);
+       return;
+     }
+ 
+     if (already_being_edited(value) == YES)
+     {
+       send_to_char("Someone is already editing that clan number.\r\n", ch);
+       return;
+     }
+ 
+     if (is_clannum_already_used(value) == YES)
+       setup_clan_edit(ch, value);
+     else
+       setup_new_clan(ch, value);
+ 
+     STATE(ch->desc) = CON_CLAN_EDIT;
+     
+     act("$n starts editing clans.", YES, ch, 0, 0, TO_ROOM);
+     SET_BIT(PLR_FLAGS(ch), PLR_WRITING);
+ 
+     return;
+   }
+ 
+   if (strcasecmp(subbcmd, "list") == 0)
+   {
+     /* Display title for list */
+     send_to_char("[   # Clan Title                Clan Owner     ]\r\n", ch);
+     /* List all clans and owners */
+     for (ccmd = 0; ccmd < clan_top; ccmd++)
+     {
+       sprintf(buf, " %4d %s%-25s%s %-15s\r\n", 
+         CLANNUM(clan_index[ccmd]), CLANCOLOUR(ccmd), 
+ 	CLANNAME(clan_index[ccmd]), 
+         CCNRM(ch, C_NRM), CLANOWNER(clan_index[ccmd]));
+       send_to_char(buf, ch);
+     }
+   sprintf(buf, "\r\n[%d clans displayed.]\r\n", (ccmd));
+   send_to_char(buf, ch);
+ 
+   return;
+   }
+ 
+   if (strcasecmp(subbcmd, "info") == 0)
+   {
+     /* Use index to retrieve information on clan */
+     value = atoi(val_arg);
+     if (value != 0)
+     {
+       for (ccmd = 0; ccmd < clan_top; ccmd++)
+ 	if (CLANNUM(clan_index[ccmd]) == value)
+ 	{
+ 	  found = 1;
+ 	  temp2 = 0;
+ 	  
+ 	  /* Find number of members in clan */
+ 	  temp = CLANPLAYERS(clan_index[ccmd]);
+ 
+ 	  temp2 = 0;
+ 	  /* Find number of clan members currently online */
+   	  for (pt = descriptor_list; pt; pt = pt->next)
+     	    if (!pt->connected && pt->character && 
+                 pt->character->player_specials->saved.clannum == value)
+ 	      temp2++;
+ 
+ 	  /* Display info header */
+ 	  sprintf(buf, "[%s", CLANCOLOUR(ccmd));
+ 	  
+ 	  sprintf(buf, "%s%-25s%s]\r\n", buf, CLANNAME(clan_index[ccmd]), CCNRM(ch, C_NRM));
+ 	  send_to_char(buf, ch);
+ 	
+ 	  send_to_char("\r\n", ch);
+ 	  sprintf(buf, "Owner: %-15s\r\n", CLANOWNER(clan_index[ccmd]));
+ 	  send_to_char(buf, ch);
+ 	  sprintf(buf, "Clan Gold: %d\r\n", CLANGOLD(clan_index[ccmd]));
+ 	  send_to_char(buf, ch);
+ 	  sprintf(buf, "Members currently online: %-3d\r\nTotal number of members: %-3d\r\n", temp2, temp);
+ 	  send_to_char(buf, ch);
+ 	  send_to_char("\r\n", ch);
+ 
+ 	    send_to_char(CCGRN(ch, C_NRM), ch);
+ 	    send_to_char(CLANDESC(clan_index[ccmd]), ch);
+ 	    send_to_char(CCNRM(ch, C_NRM), ch);
+ 
+ 	  send_to_char("\r\n", ch);
+ 	}
+     
+       if (found == 0)
+       {
+ 	send_to_char("Unable to find a clan with that number.\r\n", ch);
+ 	return;
+       }
+     }
+     else
+     {
+       send_to_char("Unable to find a clan with that number.\r\n", ch);
+     }
+   return;
+   }
+ 
+   if (strcasecmp(subbcmd, "resign") == 0)
+   {
+     temp2 = 0;
+ 
+     /* This handles clan resignations */
+     if ((PLAYERCLANNUM(ch) == 0) && (CLANRANK(ch) == 0))
+     {
+       send_to_char("But you don't belong to any clan!\r\n", ch);
+       return;
+     }
+ 
+     if (strcasecmp(GET_NAME(ch), CLANOWNER(clan_index[players_clannum])) == 0)
+     {
+       send_to_char("You can't resign from a clan you own!\r\n", ch);
+       return;
+     }
+ 
+     PLAYERCLAN(ch) = 0;
+     CLANRANK(ch) = 0;
+     
+     /* Update number of members in clan */
+     if (CLANRANK(ch) != CLAN_APPLY)
+       CLANPLAYERS(clan_index[players_clannum]) = CLANPLAYERS(clan_index[players_clannum]) - 1;  
+ 
+     send_to_char("You have resigned from your clan.\r\n", ch);
+ 
+   return;
+   }
+ 
+   if (strcasecmp(subbcmd, "apply") == 0)
+   {
+     /* This handles clan applications */
+     if (CLANRANK(ch) != 0)
+     {
+       send_to_char("You must resign from the clan you currently belong to, first.\r\n", ch);
+       return;
+     }
+ 
+     value = 0;
+     found = 0;
+     value = atoi(val_arg);
+     if (value >= 0)
+     {
+       for (ccmd = 0; ((ccmd < clan_top) && (found != 1)); ccmd++)
+         if (CLANNUM(clan_index[ccmd]) == value)
+ 	{
+ 	  found = 1;
+ 
+ 	  PLAYERCLAN(ch) = CLANNUM(clan_index[ccmd]);
+ 	  CLANRANK(ch) = CLAN_APPLY;
+ 
+ 	  sprintf(buf, "You have applied to the clan '%s'.\r\n", 
+ 		CLANNAME(clan_index[ccmd]));
+ 	  send_to_char(buf, ch);
+ 	}
+ 
+       if (found != 1)
+       {
+ 	send_to_char("Unable to find that clan.\r\n", ch);
+ 	return;
+       }
+     }
+     else
+     {
+       send_to_char("Which clan number?!\r\n", ch);
+       return;
+     }
+ 
+   return;
+   }
+ 
+   if (strcasecmp(subbcmd, "enlist") == 0)
+   {
+     /* This handles the enlistment of characters who have applied to your
+      * clan.
+      *
+      * Implementors can force an enlistment.  So, when creating a new clan,
+      * make sure your owner applies to join it.  Then the implementor must
+      * do a 'clan enlist <character>' so that the owner belongs to the clan.
+     */
+     
+     if (!(GET_LEVEL(ch) == LVL_IMPL))
+     {
+       if ((CLANRANK(ch) == 0) && (PLAYERCLANNUM(ch) == 0))
+       {
+         send_to_char("But you don't belong to any clan!\r\n", ch);
+         return;
+       }
+ 
+       if (!(CLANRANK(ch) >= CLAN_SARGEANT))
+       {
+ 	send_to_char("You have insufficent rank in your clan to do this.\r\n", ch);
+ 	return;
+       }
+ 
+       if ((vict = get_player_vis(ch, val_arg, 0)))
+       {
+ 	if (CLANRANK(vict) != CLAN_APPLY)
+ 	{
+ 	  send_to_char("But that person isn't applying to any clan!\r\n", ch);
+ 	  return;
+ 	}
+ 
+ 	if (PLAYERCLAN(vict) != PLAYERCLAN(ch))
+ 	{
+ 	  send_to_char("But that person isn't applying to your clan!\r\n", ch);
+ 	  return;
+ 	}
+ 
+ 	CLANRANK(vict) = CLAN_SOLDIER;
+ 	sprintf(buf, "You have been enlisted into the ranks of the '%s' clan.\r\n", 
+ 		CLANNAME(clan_index[players_clannum]));
+ 	send_to_char(buf, vict);
+ 
+ 	sprintf(buf, "You have enlisted '%s' into your clan.\r\n", 
+ 		GET_NAME(vict));
+ 	send_to_char(buf, ch);
+ 
+ 	SET_BIT(PRF_FLAGS(vict), PRF_CLANTALK);
+ 
+ 	/* Update number of clan members */
+ 	
+ 	CLANPLAYERS(clan_index[players_clannum])++;
+ 	
+       }
+       else
+       {
+ 	send_to_char("But there is noone here by that name!\r\n", ch);
+ 	return;
+       }
+     }
+     else
+     {
+ 
+       if ((vict = get_player_vis(ch, val_arg, 0)))
+       {
+         if (CLANRANK(vict) != CLAN_APPLY)
+         {
+ 	  send_to_char("But that person isn't applying to any clan!\r\n", ch);
+ 	  return;
+       	}
+ 
+ 	if (strcasecmp(GET_NAME(vict), 
+ 		CLANOWNER(clan_index[PLAYERCLANNUM(vict)])) == 0)
+ 	  CLANRANK(vict) = CLAN_RULER;
+ 	else
+ 	  CLANRANK(vict) = CLAN_SOLDIER;
+ 	log("Done forcing enlistment");
+ 
+ 	sprintf(buf, "You have forced the enlistment of '%s' into the clan '%s'.\r\n", 
+ 		GET_NAME(vict), CLANNAME(clan_index[PLAYERCLANNUM(vict)]));
+ 	send_to_char(buf, ch);
+ 
+ 	sprintf(buf, "You have been enlisted into the clan '%s'.\r\n", 
+ 		CLANNAME(clan_index[PLAYERCLANNUM(vict)]));
+ 	send_to_char(buf, vict);
+ 
+ 	/* Update number of clan members */
+ 	CLANPLAYERS(clan_index[PLAYERCLANNUM(vict)])++;
+       }
+       else
+       {
+         send_to_char("Unable to find a character of that name.\r\n", ch);
+         return;
+       }
+ 
+     }
+   return;
+   }
+ 
+   if (strcasecmp(subbcmd, "promote") == 0)
+   {
+     /* Clan promotions */
+     if (CLANRANK(ch) < CLAN_CAPTAIN)
+     {
+       send_to_char("You have insufficent rank to do that.\r\n", ch);
+       return;
+     }
+ 
+     if ((vict = get_player_vis(ch, val_arg, 0)))
+     {
+       if (CLANRANK(vict) > CLANRANK(ch))
+       {
+ 	send_to_char("You can't promote someone who ranks higher than you!\r\n", ch);
+ 	return;
+       }
+   
+       if ((CLANRANK(vict) < CLAN_SOLDIER) || 
+ 		(PLAYERCLAN(vict) != PLAYERCLAN(ch)))
+       {
+ 	send_to_char("You can't promote someone who doesn't belong to your clan!\r\n", ch);
+ 	return;
+       }
+ 
+       if (CLANRANK(vict) == CLAN_RULER)
+       {
+ 	send_to_char("You can't promote this person any higher in rank!\r\n", ch);
+ 	return;
+       }
+ 
+       CLANRANK(vict)++;
+       sprintf(buf, "%sYou have been promoted to ", CCRED(vict, C_NRM));
+       if (CLANRANK(vict) == CLAN_SARGEANT)
+         strcat(buf, SARGEANTTITLE(clan_index[players_clannum]));
+       if (CLANRANK(vict) == CLAN_CAPTAIN) strcat(buf, CAPTAINTITLE(clan_index[players_clannum]));
+       if (CLANRANK(vict) == CLAN_RULER) strcat(buf, RULERTITLE(clan_index[players_clannum]));
+ 
+       sprintf(buf, "%s in your clan.%s\r\n", buf, CCNRM(ch, C_NRM));
+       send_to_char(buf, vict);
+ 
+       sprintf(buf, "%sYou have promoted '%s' to the rank of ", 
+ 		CCRED(vict, C_NRM), GET_NAME(vict));
+       if (CLANRANK(vict) == CLAN_SARGEANT) strcat(buf, SARGEANTTITLE(clan_index[players_clannum]));
+       if (CLANRANK(vict) == CLAN_CAPTAIN) strcat(buf, CAPTAINTITLE(clan_index[players_clannum]));
+       if (CLANRANK(vict) == CLAN_RULER) strcat(buf, RULERTITLE(clan_index[players_clannum]));
+ 
+       sprintf(buf, "%s in your clan.%s\r\n", buf, CCNRM(ch, C_NRM));
+       send_to_char(buf, ch);
+     }
+     else
+     {
+       send_to_char("Promote who?!\r\n", ch);
+       return;
+     }
+ 
+   return;
+   }
+ 
+   if (strcasecmp(subbcmd, "demote") == 0)
+   {
+     /* Clan demotions */
+     if (CLANRANK(ch) == 0)
+     {
+       send_to_char("But you don't belong to any clan!\r\n", ch);
+       return;
+     }
+ 
+     if (CLANRANK(ch) < CLAN_CAPTAIN)
+     {
+       send_to_char("You have insufficent rank to do that.\r\n", ch);
+       return;
+     }
+ 
+     if ((vict = get_player_vis(ch, val_arg, 0)))
+     {
+       if (CLANRANK(vict) > CLANRANK(ch))
+       {
+ 	send_to_char("You can't demote someone who ranks higher than you!\r\n", ch);
+ 	return;
+       }
+   
+       if ((CLANRANK(vict) < CLAN_SOLDIER) || 
+ 		(PLAYERCLAN(vict) != PLAYERCLAN(ch)))
+       {
+ 	send_to_char("You can't demote someone who doesn't belong to your clan!\r\n", ch);
+ 	return;
+       }
+ 
+       if (CLANRANK(vict) == CLAN_SOLDIER)
+       {
+ 	send_to_char("You can't demote this person any lower! Try clan boot <person>!\r\n", ch);
+ 	return;
+       }
+ 
+       if (strcasecmp(GET_NAME(vict), CLANOWNER(clan_index[players_clannum])) == 0)
+       {
+ 	send_to_char("You can't demote the clan owner!\r\n", ch);
+ 	return;
+       }
+ 
+       CLANRANK(vict)--;
+       sprintf(buf, "%sYou have been demoted to ", CCRED(vict, C_NRM));
+       if (CLANRANK(vict) == CLAN_SOLDIER) strcat(buf, SOLDIERTITLE(clan_index[players_clannum]));
+       if (CLANRANK(vict) == CLAN_SARGEANT) strcat(buf, SARGEANTTITLE(clan_index[players_clannum]));
+       if (CLANRANK(vict) == CLAN_CAPTAIN) strcat(buf, CAPTAINTITLE(clan_index[players_clannum]));
+ 
+       sprintf(buf, "%s in your clan.%s\r\n", buf, CCNRM(ch, C_NRM));
+       send_to_char(buf, vict);
+ 
+       sprintf(buf, "%sYou have demoted '%s' to the rank of ", 
+ 		CCRED(vict, C_NRM), GET_NAME(vict));
+       if (CLANRANK(vict) == CLAN_SOLDIER) strcat(buf, SOLDIERTITLE(clan_index[players_clannum]));
+       if (CLANRANK(vict) == CLAN_CAPTAIN) strcat(buf, CAPTAINTITLE(clan_index[players_clannum]));
+       if (CLANRANK(vict) == CLAN_SARGEANT) strcat(buf, SARGEANTTITLE(clan_index[players_clannum]));
+ 
+       sprintf(buf, "%s in your clan.%s\r\n", buf, CCNRM(ch, C_NRM));
+       send_to_char(buf, ch);
+     }
+     else
+     {
+       send_to_char("Demote who?!\r\n", ch);
+       return;
+     }
+ 
+   return;
+   }
+ 
+   if (strcasecmp(subbcmd, "who") == 0)
+   {
+     /* List all clan members online, along with their clan rank */
+     if ((PLAYERCLANNUM(ch) == 0) && (CLANRANK(ch) == 0))
+     {
+       send_to_char("But you don't belong to any clan!\r\n", ch);
+       return;
+     }
+ 
+     sprintf(buf, "Members of the clan '%s' currently online:\r\n", 
+ 	CLANNAME(clan_index[players_clannum]));
+     send_to_char(buf, ch);
+ 
+     for (pt = descriptor_list; pt; pt = pt->next)
+       if (!pt->connected && pt->character && 
+           PLAYERCLAN(pt->character) == PLAYERCLAN(ch))
+ 	{ 
+           sprintf(buf, "%s[%2d %s ",  
+               (GET_LEVEL(pt->character) >= LVL_IMMORT ? CCYEL(ch, C_SPR) : ""),
+               GET_LEVEL(pt->character), CLASS_ABBR(pt->character));
+ 	  if (CLANRANK(pt->character) == CLAN_APPLY) sprintf(buf, "%s%-10s", buf, "(Applying)");
+ 	  if (CLANRANK(pt->character) == CLAN_SOLDIER) 
+ 		sprintf(buf, "%s%-10s", buf, SOLDIERTITLE(clan_index[players_clannum])); 
+ 	  if (CLANRANK(pt->character) == CLAN_SARGEANT) 
+ 		sprintf(buf, "%s%-10s", buf, SARGEANTTITLE(clan_index[players_clannum])); 
+ 	  if (CLANRANK(pt->character) == CLAN_CAPTAIN) 
+ 		sprintf(buf, "%s%-10s", buf, CAPTAINTITLE(clan_index[players_clannum])); 
+ 	  if (CLANRANK(pt->character) == CLAN_RULER) 
+ 		sprintf(buf, "%s%-10s", buf, RULERTITLE(clan_index[players_clannum])); 
+ 	  sprintf(buf, "%s] %s %s%s\r\n", buf, GET_NAME(pt->character), GET_TITLE(pt->character), CCNRM(ch, C_NRM));
+ 	  send_to_char(buf, ch);
+         }
+   return;
+   }
+ 
+   if (strcasecmp(subbcmd, "say") == 0)
+   {
+     /* Clan say */
+     if (CLANRANK(ch) == 0)
+     {
+       send_to_char("But you don't belong to any clan!\r\n", ch);
+       return;
+     }
+ 
+     if (CLANRANK(ch) < CLAN_SOLDIER)
+     {
+       send_to_char("You have insufficent rank to do that!\r\n", ch);
+       return;
+     }
+ 
+     if (!PRF_FLAGGED(ch, PRF_CLANTALK))
+     {
+       send_to_char("Try turning your clan talk channel on first, dork!\r\n", ch);
+       return;
+     }    
+ 
+     for (pt = descriptor_list; pt; pt = pt->next)
+       if (!pt->connected && pt->character && 
+           PLAYERCLAN(pt->character) == PLAYERCLAN(ch) &&
+ 	  pt->character != ch && PRF_FLAGGED(pt->character, PRF_CLANTALK))
+ 	{
+ 	  sprintf(buf, "%s%s says to the clan, '%s'%s\r\n", CCRED(pt->character, C_NRM),
+ 			GET_NAME(ch), val_arg, CCNRM(pt->character, C_NRM));
+ 	  send_to_char(buf, pt->character);
+         }
+     sprintf(buf, "%sYou say to the clan, '%s'%s\r\n", CCRED(ch, C_NRM),
+ 		val_arg, CCNRM(ch, C_NRM));
+     send_to_char(buf, ch);
+ 
+   return;
+   }
+ 
+   if (strcasecmp(subbcmd, "channel") == 0)
+   {
+     if (PRF_FLAGGED(ch, PRF_CLANTALK))
+     {
+       TOGGLE_BIT(PRF_FLAGS(ch), PRF_CLANTALK);
+       send_to_char("Clan talk channel turned off.\r\n", ch);
+     }
+     else
+     {
+       TOGGLE_BIT(PRF_FLAGS(ch), PRF_CLANTALK);
+       send_to_char("Clan talk channel turned on.\r\n", ch);
+     }
+   return;
+   }
+ 
+   if (strcasecmp(subbcmd, "deposit") == 0)
+   {
+     /* This handles the process of depositing gold into the clan account */
+     /* This may only be done in the clan room */
+     
+     if ((PLAYERCLANNUM(ch) == 0) && (CLANRANK(ch) == 0))
+     {
+       send_to_char("But you don't belong to any clan!\r\n", ch);
+       return;
+     }
+ 
+     if (CLANRANK(ch) < CLAN_SOLDIER)
+     {
+       send_to_char("You have insufficent rank to do that!\r\n", ch);
+       return;
+     }
+ 
+     if (ch->in_room != CLANROOM(clan_index[players_clannum]))
+     {
+       send_to_char("You can only do that in clan rooms!\r\n", ch);
+       return;
+     }
+ 
+     value = atoi(val_arg);
+     if (value != 0)
+     {
+       if (ch->points.gold < value)
+       {
+    	send_to_char("But you don't have that much gold!\r\n", ch);
+ 	return;
+       }
+ 
+       ch->points.gold = ch->points.gold - value;
+ 
+       CLANGOLD(clan_index[players_clannum]) = CLANGOLD(clan_index[players_clannum]) + value;      
+ 
+       sprintf(buf, "%d gold deposited into clan account.\r\n", value);
+       send_to_char(buf, ch);
+ 
+     }
+     else
+     {
+       send_to_char("Huh?\r\n", ch);
+     }
+ 
+   return;
+   }
+ 
+   if (strcasecmp(subbcmd, "withdraw") == 0)
+   {
+     /* This handles withdrawals from the clan account */
+     if ((CLANRANK(ch) == 0) && (PLAYERCLANNUM(ch) == 0))
+     {
+       send_to_char("But you don't belong to any clan!\r\n", ch);
+       return;
+     }
+ 
+ 
+     value = atoi(val_arg);
+     if (value > -1)
+     {
+       if (CLANRANK(ch) < CLAN_RULER)
+       {
+ 	send_to_char("You have insufficent rank to do that!\r\n", ch);
+ 	return;
+       }
+ 
+       if (ch->in_room != CLANROOM(clan_index[players_clannum]))
+       {
+ 	send_to_char("But you can only do that in your clan room!\r\n", ch);
+ 	return;
+       }
+ 
+       if (CLANGOLD(clan_index[players_clannum]) < value)
+       {
+ 	send_to_char("But your clan doesn't have that much money!\r\n", ch);
+ 	return;
+       }
+       else
+       {
+         CLANGOLD(clan_index[players_clannum]) = CLANGOLD(clan_index[players_clannum]) - value;    
+ 	ch->points.gold = ch->points.gold + value;
+ 	sprintf(buf, "%d gold coins withdrawn from the clan account.\r\n",  value);
+ 	send_to_char(buf, ch);
+       }
+ 
+     }
+     else
+     {
+       send_to_char("Huh?\r\n", ch);
+       return;
+     }
+ 
+   return;
+   }
+ 
+   if (strcasecmp(subbcmd, "kick") == 0)
+   {
+     if ((CLANRANK(ch) == 0) && (PLAYERCLANNUM(ch) == 0))
+     {
+       send_to_char("But you do not belong to any clan!\r\n", ch);
+       return;
+     }
+ 
+     if (CLANRANK(ch) < CLAN_RULER)
+     {
+       send_to_char("You have insufficent rank to do that!\r\n", ch);
+       return;
+     }
+ 
+     if ((vict = get_player_vis(ch, val_arg, 0)))
+     {
+       if (PLAYERCLAN(vict) != PLAYERCLAN(ch))
+       {
+ 	send_to_char("But that person doesn't belong to your clan!\r\n", ch);
+ 	return;
+       }
+ 
+       if (strcasecmp(CLANOWNER(clan_index[players_clannum]), GET_NAME(vict)) == 0)
+       {
+         send_to_char("You can't kick the clan owner out!\r\n", ch);
+         return;
+       }
+ 
+       CLANRANK(vict) = 0;
+       PLAYERCLAN(vict) = 0;
+ 
+       sprintf(buf, "You have kicked '%s' from your clan.\r\n", GET_NAME(vict));
+       send_to_char(buf, ch);
+       sprintf(buf, "You have been kicked from the clan, '%s'.\r\n", CLANNAME(clan_index[players_clannum]));
+       send_to_char(buf, vict);
+ 
+       /* Update number of members in clan */
+       if (CLANRANK(vict) != CLAN_APPLY)
+ 	CLANPLAYERS(clan_index[players_clannum])--;
+ 
+     }
+     else
+     {
+       send_to_char("Can't find that person.\r\n", ch);
+       return;
+     }
+     return;
+   }
+ 
+ 
+   /* If no recognised subcommand given, display help */
+   if (strcasecmp(subbcmd, "help") != 0)
+   {
+     send_to_char("Clan help:\r\n", ch);
+     send_to_char("\r\n", ch);
+     if (CLANRANK(ch) == 0)
+       send_to_char("apply, info, list.\r\n", ch);
+     if (CLANRANK(ch) == CLAN_APPLY)
+       send_to_char("info, list, resign, who.\r\n", ch);
+     if (CLANRANK(ch) == CLAN_SOLDIER)
+       send_to_char("channel, deposit, info, list, resign, say, who.\r\n", ch);
+     if (CLANRANK(ch) == CLAN_SARGEANT)
+       send_to_char("channel, deposit, enlist, info, list, resign, say, who.\r\n", ch);
+     if (CLANRANK(ch) == CLAN_CAPTAIN)
+       send_to_char("channel, demote, deposit, enlist, info, list, promote, resign, say, who.\r\n", ch);
+     if (CLANRANK(ch) == CLAN_RULER)
+     {
+       send_to_char("channel, demote, deposit, enlist, info, kick, list, promote, resign, say,\r\n", ch);
+       send_to_char("withdraw, who.\r\n", ch);
+     }
+     if (GET_LEVEL(ch) == LVL_IMPL)
+     {
+       send_to_char("\r\nImplementor commands:\r\n", ch);
+       send_to_char("debug, edit, save.\r\n", ch);
+     }
+     send_to_char("\r\n", ch);
+     send_to_char("For further help type: clan help <command>\r\n", ch);
+     return;
+   }
+   else
+   {
+     if (strcasecmp(val_arg, "debug") == 0)
+     {
+       send_to_char("CLAN DEBUG <type>\r\n", ch);
+       send_to_char("\r\nDump debug information to debug file.\r\n", ch);
+       send_to_char("Type 'clan debug' for more information.\r\n", ch);
+       return;
+     }
+     if (strcasecmp(val_arg, "save") == 0)
+     {
+       send_to_char("CLAN SAVE\r\n", ch);
+       send_to_char("\r\nSave clan data to clan files.\r\n", ch);
+       return;
+     }
+     if (strcasecmp(val_arg, "edit") == 0)
+     {
+       send_to_char("CLAN EDIT <num>\r\n", ch);
+       send_to_char("\r\nEnter full screen clan editor for clan <num>.\r\n", ch);
+       send_to_char("If <num> doesn't exist, a clan will be created.\r\n", ch);
+       return;
+     }
+     if (strcasecmp(val_arg, "apply") == 0)
+     {
+       send_to_char("CLAN APPLY <num>\r\n", ch);
+       send_to_char("\r\n", ch);
+       send_to_char("Apply to the clan with the number <num>.  To find out the number of a\r\n", ch);
+       send_to_char("clan, use the CLAN INFO command.\r\n", ch);
+       send_to_char("\r\nRelated topics: resign, enlist.\r\n", ch);
+       return;
+     }
+     if (strcasecmp(val_arg, "kick") == 0)
+     {
+       send_to_char("CLAN KICK <player>\r\n", ch);
+       send_to_char("\r\nThis kicks <player> from your clan.\r\n", ch);
+       return;
+     }
+     if (strcasecmp(val_arg, "channel") == 0)
+     {
+       send_to_char("CLAN CHANNEL\r\n", ch);
+       send_to_char("\r\nUsed to toggle the clan talk channel.  Similar to the gossip channel command.\r\n", ch);
+       send_to_char("\r\nRelated topics: say.\r\n", ch);
+       return;
+     }
+     if (strcasecmp(val_arg, "demote") == 0)
+     {
+       send_to_char("CLAN DEMOTE <player>\r\n", ch);
+       send_to_char("\r\nThis command demotes <player> one rank in your clan.\r\n", ch);
+       send_to_char("\r\nRelated topics: promote.\r\n", ch);
+       return;
+     }
+     if (strcasecmp(val_arg, "deposit") == 0)
+     {
+       send_to_char("CLAN DEPOSIT <amount>\r\n", ch);
+       send_to_char("\r\nThis command deposits <amount> of gold into the clan account.\r\n", ch);
+       send_to_char("This can only be done in the clan room.\r\n", ch);
+       send_to_char("\r\nRelated topics: withdraw.\r\n", ch);
+       return;
+     }
+     if (strcasecmp(val_arg, "enlist") == 0)
+     {
+       send_to_char("CLAN ENLIST <player>\r\n", ch);
+       send_to_char("\r\nThis command enlists <player> into your clan.\r\n", ch);
+       send_to_char("<player> must be applying to your clan first, of course.\r\n", ch);
+       if (GET_LEVEL(ch) == LVL_IMPL)
+         send_to_char("\r\nAs an implementor you can force the enlisting of <player> into\r\nthe clan they are applying for whether you are in that clan or not.\r\n", ch);
+ 
+       send_to_char("\r\nRelated topics: apply, resign.\r\n", ch);
+       return;
+     }
+     if (strcasecmp(val_arg, "info") == 0)
+     {
+       send_to_char("CLAN INFO <num>\r\n", ch);
+       send_to_char("\r\nThis command gives info on the clan <num>.  To get the number of a\r\n", ch);
+       send_to_char("clan, use the CLAN LIST command.\r\n", ch);
+       send_to_char("\r\nRelated topics: list.\r\n", ch);
+       return;
+     }
+     if (strcasecmp(val_arg, "list") == 0)
+     {
+       send_to_char("CLAN LIST\r\n", ch);
+       send_to_char("\r\nThis command lists all the existing clans.\r\n", ch);
+       send_to_char("\r\nRelated topics: info.\r\n", ch);
+       return;
+     }
+     if (strcasecmp(val_arg, "promote") == 0)
+     {
+       send_to_char("CLAN PROMOTE <player>\r\n", ch);
+       send_to_char("\r\nThis command promotes <player> a level in your clan.  Provided\r\n", ch);
+       send_to_char("they already belong to your clan.\r\n", ch);
+       send_to_char("\r\nRelated topics: demote, enlist.\r\n", ch);
+       return;
+     }
+     if (strcasecmp(val_arg, "resign") == 0)
+     {
+       send_to_char("CLAN RESIGN\r\n", ch);
+       send_to_char("\r\nThis command resigns you from your clan.\r\n", ch);
+       send_to_char("\r\nRelated topics: apply, enlist.\r\n", ch);
+       return;
+     }
+     if (strcasecmp(val_arg, "say") == 0)
+     {
+       send_to_char("CLAN SAY <message>\r\n", ch);
+       send_to_char("\r\nThis command passes a message onto your fellow clan members.\r\n", ch);
+       send_to_char("Much the same as GOSSIP.\r\n", ch);
+       send_to_char("Abbreviation: | <message>\r\n", ch);
+       send_to_char("\r\nRelated topics: channel.\r\n", ch);
+       return;
+     }
+     if (strcasecmp(val_arg, "withdraw") == 0)
+     {
+       send_to_char("CLAN WITHDRAW <amount>\r\n", ch);
+       send_to_char("\r\nThis withdraws <amount> of gold from the clan account.\r\n", ch);
+       send_to_char("You must be in the clan room to do this.\r\n", ch);
+       send_to_char("\r\nRelated topics: deposit.\r\n", ch);
+       return;
+     }
+     if (strcasecmp(val_arg, "who") == 0)
+     {
+       send_to_char("CLAN WHO\r\n", ch);
+       send_to_char("\r\nThis command is similar to WHO.  It displays all the clan members\r\n", ch);
+       send_to_char("currently online.  As well as their rank in the clan.\r\n", ch);
+       send_to_char("\r\nRelated topics: list, info.\r\n", ch);
+       return;
+     }
+     send_to_char("Huh?\r\n", ch);
+   }
+ 
+ };
+ 
+ ACMD(do_clansay)
+ {
+   struct descriptor_data *pt;
+ 
+     /* Clan say */
+     if (CLANRANK(ch) == 0)
+     {
+       send_to_char("But you don't belong to any clan!\r\n", ch);
+       return;
+     }
+ 
+     if (!PRF_FLAGGED(ch, PRF_CLANTALK))
+     {
+       send_to_char("Try turning your clan talk channel on first, dork!\r\n", ch);
+       return;
+     }    
+ 
+     for (pt = descriptor_list; pt; pt = pt->next)
+       if (!pt->connected && pt->character && 
+           PLAYERCLAN(pt->character) == PLAYERCLAN(ch) &&
+ 	  pt->character != ch && PRF_FLAGGED(pt->character, PRF_CLANTALK))
+ 	{
+ 	  sprintf(buf, "%s%s says to the clan, '%s'%s\r\n", CCRED(pt->character, C_NRM),
+ 			GET_NAME(ch), argument, CCNRM(pt->character, C_NRM));
+ 	  send_to_char(buf, pt->character);
+         }
+     sprintf(buf, "%sYou say to the clan, '%s'%s\r\n", CCRED(ch, C_NRM),
+ 		argument, CCNRM(ch, C_NRM));
+     send_to_char(buf, ch);
+ 
+ };
+ 
+ /*
+  * The following procedures attempt to fit into the db.c load procedures
+  * to allow the dynamic creation, editing, and removal of clans whilst
+  * in game play.
+  *
+  * Most of these functions will be almost direct copies of the db.c
+  * procedures.
+  *
+ */
+ 
+ void parse_clan(FILE *fl, int virtual_nr)
+ {
+   static int clan_nr = 0;
+   int t[10];
+   char line[256];
+ 
+   sprintf(buf2, "Parsing clan #%d", virtual_nr);
+   log(buf2);
+   
+   clan_index[clan_nr].number = virtual_nr;
+   clan_index[clan_nr].title = fread_string(fl, buf2);
+   clan_index[clan_nr].description = fread_string(fl, buf2);
+   clan_index[clan_nr].owner = fread_string(fl, buf2);
+   clan_index[clan_nr].ranksoldiertitle = fread_string(fl, buf2);
+   clan_index[clan_nr].ranksargeanttitle = fread_string(fl, buf2);
+   clan_index[clan_nr].rankcaptaintitle = fread_string(fl, buf2);
+   clan_index[clan_nr].rankrulertitle = fread_string(fl, buf2);
+ 
+   if (!get_line(fl,line) || sscanf(line, " %d %d %d %d ", t, t + 1, t + 2, t + 3) != 4) {
+     fprintf(stderr, "Format error in clan #%d\n", virtual_nr);
+     exit(1);
+   }
+ 
+   clan_index[clan_nr].clanroom = t[0];
+   clan_index[clan_nr].clangold = t[1];
+   clan_index[clan_nr].nummembers = t[2];
+   clan_index[clan_nr].colour = t[3];
+   clan_index[clan_nr].status = CLAN_OLD;
+ 
+ }
+ 
+ void prepare_colour_table(struct char_data *ch)
+ {
+   clan_colour[0].colour_string = CCWHT(ch, C_NRM);
+   clan_colour[1].colour_string = CCGRN(ch, C_NRM);
+   clan_colour[2].colour_string = CCRED(ch, C_NRM);
+   clan_colour[3].colour_string = CCBLU(ch, C_NRM);
+   clan_colour[4].colour_string = CCMAG(ch, C_NRM);
+   clan_colour[5].colour_string = CCYEL(ch, C_NRM);
+   clan_colour[6].colour_string = CCCYN(ch, C_NRM);
+   clan_colour[7].colour_string = CCNRM(ch, C_NRM);
+ }
+ 
+ void update_clan_cross_reference()
+ {
+   int i = 0;
+ 
+   for (i = 0; i < 9999; i++)
+     cross_reference[i] = -1;
+ 
+   for (i = 0; i < clan_top; i++)
+     cross_reference[CLANNUM(clan_index[i])] = i;
+ 
+ }
+ 
+ void clan_save(int system, struct char_data *ch)
+ {
+   int i = 0, found = 0, last = 0, rec_count = 0, files = 0;
+   FILE *fl, *index;
+   char *index_file;
+   char line[256];
+   int reference[9999];
+ 
+   if (mini_mud)
+     index_file = MINDEX_FILE;
+   else
+     index_file = INDEX_FILE;
+ 
+   sprintf(buf, "%s/%s", CLAN_PREFIX, index_file);
+ 
+   if (!(index = fopen(buf, "r")))
+   {
+     log("FUNCTION(clan_save): Unable to open clan index file");
+     if (system == NO)
+       send_to_char("ClanSave: Unable to open index file (ERROR)\r\n", ch);
+     return;
+   }
+ 
+   fscanf(index, "%s\n", buf);
+   while (*buf != '$')
+   {
+     sprintf(buf2, "%s/%s", CLAN_PREFIX, buf);
+     if (!(fl = fopen(buf2, "r")))
+     {
+       log("FUNCTION(clan_save): Unable to open sub file from index file");
+       if (system == NO)
+       {
+ 	sprintf(buf, "ClanSave: Unable to open '%s' (ERROR)\r\n", buf2);
+         send_to_char(buf, ch);
+       }
+       return;
+     }
+     else
+     {
+       rec_count = 0;
+ 
+       while (found == 0)
+       {
+         if (!get_line(fl, line))
+         {
+           log("FUNCTION(clan_save): Format error encountered");
+           if (system == NO);
+           {
+   	    sprintf(buf, "ClanSave: Format error after clan #%d (ERROR)\r\n", i);
+             send_to_char(buf, ch);
+           }
+           exit(1);
+         }
+ 
+         if (*line == '$')
+ 	  found = 1;
+ 
+ 	if (*line == '#')
+ 	{
+ 	  last = i;
+ 
+ 	  if (sscanf(line, "#%d", &i) != 1)
+ 	  {
+ 	    log("FUNCTION(clan_save): Format error in clan file");
+ 	    if (system == NO)
+ 	    {
+ 	      sprintf(buf, "ClanSave: Format error after clan #%d\r\n", last);
+ 	      send_to_char(buf, ch);
+ 	    }
+ 	    exit(1);
+ 	  }
+ 	  
+ 	  if (i >= 99999)
+ 	    return;
+ 
+ 	  reference[rec_count] = i;
+ 	  rec_count++;
+ 	}	  
+       }
+ 
+       /* Now that we have a list of the clan #'s in this clan file */
+       /* We replace them with the updated records */
+       fclose(fl);
+       
+       sprintf(buf2, "%s/%s", CLAN_PREFIX, buf);
+       if (!(fl = fopen(buf2, "w")))
+       {
+         log("FUNCTION(clan_save): Error truncuating clan file for rewrite");
+ 	if (system == NO)
+ 	{
+ 	  sprintf(buf, "ClanSave: Unable to truncuate '%s' (ERROR)\r\n", buf2);
+ 	  send_to_char(buf, ch);
+ 	}
+         return;
+       }
+       
+       for (i = 0; i < rec_count; i++)
+ 	write_clan(fl, reference[i]);
+ 
+       /* New clan records go at the end of the first file in the index */
+       if (files == 0)
+         for (i = 0; i < clan_top; i++)
+ 	  if (CLANSTATUS(i) == CLAN_NEW)
+ 	  {
+ 	    write_clan(fl, CLANNUM(clan_index[i]));
+ 	    CLANSTATUS(i) = CLAN_OLD;
+ 	  }
+ 
+       fputs("$~\n", fl);
+       fclose(fl);
+     }  
+ 
+   fscanf(index, "%s\n", buf);
+   files++;
+   }
+ 
+   log("Successfully saved clan details");
+ 
+   if (system == NO)
+     send_to_char("Clans saved.\r\n", ch);
+ 
+ }
+ 
+ void write_clan(FILE *fl, int cnum)
+ {
+   int j = 0;
+ 
+   log("Whew! Made it to the 'write_clan' function");
+ 
+   update_clan_cross_reference();
+   j = cross_reference[cnum];
+ 
+   if (j == -1) return;
+ 
+   fprintf(stderr, "Writing clan #%d which is '%s'\n", cnum, clan_index[j].title);
+ 
+ 
+   fprintf(fl, "#%d\n", clan_index[j].number);
+   fprintf(fl, "%s~\n", clan_index[j].title);
+   fprintf(fl, "%s\n~\n", clan_index[j].description);
+   fprintf(fl, "%s~\n", clan_index[j].owner);
+   fprintf(fl, "%s~\n", clan_index[j].ranksoldiertitle);
+   fprintf(fl, "%s~\n", clan_index[j].ranksargeanttitle);
+   fprintf(fl, "%s~\n", clan_index[j].rankcaptaintitle);
+   fprintf(fl, "%s~\n", clan_index[j].rankrulertitle);
+   fprintf(fl, "%d %d %d %d\n", clan_index[j].clanroom, 
+           clan_index[j].clangold, clan_index[j].nummembers, 
+ 	  clan_index[j].colour);
+ 
+ }
+ 
+ void display_menu(struct char_data *ch, int cnum)
+ {
+ 
+   sprintf(buf, "\x1B[H\x1B[J"
+                "%s[Editing clan record]%s\r\n\r\n", 
+ 	CCRED(ch, C_NRM), CCNRM(ch, C_NRM));
+   send_to_char(buf, ch);
+ 
+   sprintf(buf2, "%sClan #%s%4d%s", CCYEL(ch, C_NRM), CCGRN(ch, C_NRM),
+ 		 cnum, CCNRM(ch, C_NRM));
+   sprintf(buf, "%54s\r\n", buf2);
+   send_to_char(buf, ch);
+ 
+   sprintf(buf2, "%s'%s'%s", 
+ 	CLANCOLOUR(cross_reference[cnum]), 
+ 	CLANNAME(clan_index[cross_reference[cnum]]), 
+ 	CCNRM(ch, C_NRM));
+   sprintf(buf, "%54s\r\n", buf2);
+   send_to_char(buf, ch);
+ 
+   sprintf(buf2, "%sClan Gold : %s%d", CCYEL(ch, C_NRM), 
+ 		CCGRN(ch, C_NRM),
+ 		CLANGOLD(clan_index[cross_reference[cnum]]));
+   sprintf(buf, "\r\n%50s\r\n", buf2);
+   send_to_char(buf, ch);
+ 
+   sprintf(buf2, "%sClan Room : %s%d", CCYEL(ch, C_NRM),
+ 		CCGRN(ch, C_NRM),
+ 		CLANROOM(clan_index[cross_reference[cnum]]));
+   sprintf(buf, "%50s\r\n", buf2);
+   send_to_char(buf, ch);
+ 
+   sprintf(buf2, "%sClan Owner : %s%s", CCYEL(ch, C_NRM),
+ 		CCGRN(ch, C_NRM),
+ 		CLANOWNER(clan_index[cross_reference[cnum]]));
+   sprintf(buf, "%56s\r\n", buf2);
+   send_to_char(buf, ch);
+ 
+   sprintf(buf2, "%s1. %sChange clan number%s", CCYEL(ch, C_NRM), 
+ 	CCGRN(ch, C_NRM), CCNRM(ch, C_NRM));
+   sprintf(buf, "\r\n%59s\r\n", buf2);
+   send_to_char(buf, ch);
+ 
+   sprintf(buf2, "%s2. %sChange clan name%s", CCYEL(ch, C_NRM), 
+ 		CCGRN(ch, C_NRM), CCNRM(ch, C_NRM));
+   sprintf(buf, "%57s\r\n", buf2);
+   send_to_char(buf, ch);
+ 
+   sprintf(buf2, "%s3. %sChange clan owner%s", CCYEL(ch, C_NRM),
+ 		CCGRN(ch, C_NRM), CCNRM(ch, C_NRM));
+   sprintf(buf, "%58s\r\n", buf2);
+   send_to_char(buf, ch);
+ 
+   sprintf(buf2, "%s4. %sChange clan description%s", CCYEL(ch, C_NRM),
+ 		CCGRN(ch, C_NRM), CCNRM(ch, C_NRM));
+   sprintf(buf, "%64s\r\n", buf2);
+   send_to_char(buf, ch);
+ 
+   sprintf(buf2, "%s5. %sChange clan colour%s", CCYEL(ch, C_NRM),
+ 		CCGRN(ch, C_NRM), CCNRM(ch, C_NRM));
+   sprintf(buf, "%59s\r\n", buf2);
+   send_to_char(buf, ch);
+ 
+   sprintf(buf2, "%s6. %sChange clan gold%s", CCYEL(ch, C_NRM),
+ 		CCGRN(ch, C_NRM), CCNRM(ch, C_NRM));
+   sprintf(buf, "%57s\r\n", buf2);
+   send_to_char(buf, ch);
+ 
+   sprintf(buf2, "%s7. %sChange clan room%s", CCYEL(ch, C_NRM),
+ 		CCGRN(ch, C_NRM), CCNRM(ch, C_NRM));
+   sprintf(buf, "%57s\r\n", buf2);
+   send_to_char(buf, ch);
+ 
+   sprintf(buf2, "%s8. %sChange clan ranks%s", CCYEL(ch, C_NRM),
+ 		CCGRN(ch, C_NRM), CCNRM(ch, C_NRM));
+   sprintf(buf, "%58s\r\n", buf2);
+   send_to_char(buf, ch);
+ 
+   sprintf(buf2, "%sQ. %sQuit editing clan%s", CCYEL(ch, C_NRM),
+ 		CCGRN(ch, C_NRM), CCNRM(ch, C_NRM));
+   sprintf(buf, "%58s\r\n", buf2);
+   send_to_char(buf, ch);
+ 
+   sprintf(buf2, "%sD. %sDelete clan%s", CCYEL(ch, C_NRM), CCGRN(ch, C_NRM),
+ 		CCNRM(ch, C_NRM));
+   sprintf(buf, "\r\n%52s\r\n", buf2);
+   send_to_char(buf, ch);
+ 
+ }
+ 
+ /* Some generic tests */
+ int is_clannum_already_used(int cnum)
+ {
+   update_clan_cross_reference();
+ 
+   if (cross_reference[cnum] >= 0)
+     return YES;
+ 
+ 
+   return NO;
+ 
+ }
+ 
+ int already_being_edited(int cnum)
+ {
+   int i = 0;
+ 
+   for (i = 0; i < 10; i ++)
+     if (CLAN_EDIT_CLAN(i) == cnum) return YES;
+ 
+   return NO;
+ }
+ 
+ void update_cnum(int oldcnum, int newcnum)
+ {
+   struct descriptor_data *pt;
+ 
+   for (pt = descriptor_list; pt; pt = pt->next)
+     if (!pt->connected && pt->character && 
+           PLAYERCLAN(pt->character) == oldcnum)
+       PLAYERCLAN(pt->character) = newcnum;
+ 
+   clan_index[cross_reference[oldcnum]].number = newcnum;
+ 
+   update_clan_cross_reference();
+ }
+ 
+ void setup_new_clan(struct char_data *ch, int cnum)
+ {
+   int i = 0;
+   int node_assigned = 0;
+ 
+   for (i = 0; i < 10; i++)
+     if ((CLAN_EDIT_DESC(i) == NULL) && (node_assigned == NO))
+     {
+       CLAN_EDIT_DESC(i) = ch->desc;
+       CLAN_EDIT_CLAN(i) = cnum;
+       CLAN_EDIT_MODE(i) = CLAN_EDIT_MAIN_MENU;
+       node_assigned = YES;
+     }
+ 
+   if (node_assigned == NO)
+   {
+     send_to_char("Sorry, but all editing slots are full.  Try again later.\r\n", ch);
+     cleanup_clan_edit(ch->desc, CLEAN_ALL);
+     return;
+   }
+   
+   clan_index[clan_top].number = cnum;
+   clan_index[clan_top].title = str_dup("New Clan");
+   clan_index[clan_top].owner = str_dup(GET_NAME(ch));
+   clan_index[clan_top].description = str_dup("A new clan");
+   clan_index[clan_top].clangold = 0;
+   clan_index[clan_top].clanroom = 0;
+   clan_index[clan_top].colour = CLAN_NORMAL;
+   clan_index[clan_top].ranksoldiertitle = str_dup("Soldier");
+   clan_index[clan_top].ranksargeanttitle = str_dup("Sargeant");
+   clan_index[clan_top].rankcaptaintitle = str_dup("Captain");
+   clan_index[clan_top].rankrulertitle = str_dup("Ruler");
+   clan_index[clan_top].status = CLAN_NEW;
+ 
+   clan_top++;
+ 
+   update_clan_cross_reference();
+ 
+   display_menu(ch, cnum);
+ 
+ }
+ 
+ void setup_clan_edit(struct char_data *ch, int cnum)
+ {
+   int i = 0;
+   int node_assigned = 0;
+ 
+   for (i = 0; i < 10; i++)
+     if ((CLAN_EDIT_DESC(i) == NULL) && (node_assigned == NO))
+     {
+       CLAN_EDIT_DESC(i) = ch->desc;
+       CLAN_EDIT_CLAN(i) = cnum;
+       CLAN_EDIT_MODE(i) = CLAN_EDIT_MAIN_MENU;
+       node_assigned = YES;
+     }
+ 
+   if (node_assigned == NO)
+   {
+     send_to_char("Sorry, but all editing slots are full.  Try again later.\r\n", ch);
+     cleanup_clan_edit(ch->desc, CLEAN_ALL);
+     return;
+   }
+   
+   display_menu(ch, cnum);
+ 
+ }
+ 
+ void cleanup_clan_edit(struct descriptor_data *d, int method)
+ {
+   int i = 0;
+ 
+   for (i = 0; i < 10; i++)
+     if (CLAN_EDIT_DESC(i) == d)
+     {
+       CLAN_EDIT_DESC(i) = NULL;
+       CLAN_EDIT_MODE(i) = 0;
+       if (method == CLEAN_ALL)
+         CLANSTATUS(cross_reference[CLAN_EDIT_CLAN(i)]) = CLAN_DELETE;
+       CLAN_EDIT_CLAN(i) = 0;
+     }
+ 
+   refresh_clan_index();
+ 
+   if (d->character)
+   {
+     STATE(d) = CON_PLAYING;
+     REMOVE_BIT(PLR_FLAGS(d->character), PLR_WRITING);
+     act("$n stops editing clans.", YES, d->character, 0, 0, TO_ROOM);
+   }
+ 
+   if (method == CLEAN_ALL)
+     fix_illegal_cnum();
+ 
+ }
+ 
+ void fix_illegal_cnum()
+ {
+   /* Search out and destroy cnum's in player's records which no longer */
+   /* exist in the clan_index array */
+   int i = 0, valid = 0;
+   struct descriptor_data *pt;
+ 
+   for (pt = descriptor_list; pt; pt = pt->next)
+   {
+     for (i = 0; i < clan_top; i++)
+       if (clan_index[i].number == PLAYERCLAN(pt->character)) valid = YES;
+     if (valid == NO)
+     {
+       sprintf(buf, "(ILLEGAL CLAN NUMBER FOUND) belonging to '%s' - #%d\n",
+ 	GET_NAME(pt->character), PLAYERCLAN(pt->character));
+       fprintf(stderr, "%s", buf);
+       PLAYERCLAN(pt->character) = -1;
+       CLANRANK(pt->character) = 0;
+     }
+     valid = NO;
+   }
+ 
+   log("Done fixing illegal clannum links");
+ 
+ }
+ 
+ void refresh_clan_index()
+ {
+   int i = 0;
+   int j = 0;
+   int k = 0;
+ 
+   for (i = 0; i < clan_top; i++)
+     if (CLANSTATUS(i) == CLAN_DELETE)
+     {
+ 
+       k = clan_index[i].number;
+       clan_index[i].number = -1;
+       update_cnum(k, -1);
+       if (i != (clan_top - 1))
+         for (j = i; j < (clan_top - 1); j++)
+ 	  clan_index[j] = clan_index[j + 1];
+       clan_top--;
+     }
+ 
+   update_clan_cross_reference();
+ 
+ }
+ 
+ void parse_clan_edit(struct descriptor_data *d, char *arg)
+ {
+   int i = 0;
+   int num = -1;
+ 
+   for (i = 0; i < 10; i++)
+     if (CLAN_EDIT_DESC(i) == d) num = i;
+ 
+   if (num == -1) return;
+ 
+   switch (CLAN_EDIT_MODE(num))
+   {
+     case CLAN_EDIT_MAIN_MENU:
+       switch (*arg)
+       {
+         case 'd':
+ 	case 'D':
+ 	  CLAN_EDIT_MODE(num) = CLAN_EDIT_CONFIRM_DELETE;
+ 	  send_to_char("\r\nAre you sure you wish to delete this clan? [Yy/Nn]", d->character);
+ 	  break;
+ 	case 'q':
+ 	case 'Q':
+ 	  CLAN_EDIT_MODE(num) = CLAN_EDIT_CONFIRM_SAVE;
+ 	  send_to_char("\r\nDo you wish to save this clan? [Yy/Nn]", d->character);
+ 	  break;
+ 	case '1':
+ 	  CLAN_EDIT_MODE(num) = CLAN_EDIT_NUMBER;
+ 	  send_to_char("\r\nEnter new clan number: ", d->character);
+ 	  break;
+ 	case '2':
+ 	  CLAN_EDIT_MODE(num) = CLAN_EDIT_NAME;
+ 	  send_to_char("\r\nEnter clan name: \r\n", d->character);
+ 	  break;
+ 	case '3':
+ 	  CLAN_EDIT_MODE(num) = CLAN_EDIT_OWNER;
+ 	  send_to_char("\r\nEnter clan owners name: \r\n", d->character);
+ 	  break;
+ 	case '4':
+ 	  CLAN_EDIT_MODE(num) = CLAN_EDIT_DESCRIPTION;
+ 	  SEND_TO_Q("\x1B[H\x1B[J", d);
+ 	  /*
+ 	   * Attempting the impossible - Using the inbuilt text editor */
+        	  clan_index[cross_reference[CLAN_EDIT_CLAN(num)]].old_description = NULL;
+ 	  clan_index[cross_reference[CLAN_EDIT_CLAN(num)]].old_description =
+ 		str_dup(CLANDESC(clan_index[cross_reference[CLAN_EDIT_CLAN(num)]]));
+           SEND_TO_Q("Old clan description:\r\n\r\n", d);
+ 	  SEND_TO_Q(CLANDESC(clan_index[cross_reference[CLAN_EDIT_CLAN(num)]]), d);
+ 	  SEND_TO_Q("\r\n\r\nEnter new description: \r\n\r\n", d);
+ 	  clan_index[cross_reference[CLAN_EDIT_CLAN(num)]].description = NULL;
+ 	  d->str = &clan_index[cross_reference[CLAN_EDIT_CLAN(num)]].description;
+ 	  d->max_str = 1000;
+ 	  break;
+ 	case '5':
+ 	  CLAN_EDIT_MODE(num) = CLAN_EDIT_COLOUR;
+ 	  display_colour_menu(d);
+ 	  break;
+ 	case '6':
+ 	  CLAN_EDIT_MODE(num) = CLAN_EDIT_GOLD;
+ 	  send_to_char("\r\nEnter new gold value: ", d->character);
+ 	  break;
+ 	case '7':
+ 	  CLAN_EDIT_MODE(num) = CLAN_EDIT_CLANROOM;
+ 	  send_to_char("\r\nEnter new clan room: ", d->character);
+ 	  break;
+ 	case '8':
+ 	  CLAN_EDIT_MODE(num) = CLAN_EDIT_RANK_MENU;
+ 	  display_rank_menu(d, num);
+ 	  break;
+ 	default:
+ 	  send_to_char("r\nInvalid command!", d->character);
+ 	  display_menu(d->character, CLAN_EDIT_CLAN(num));
+ 	  break;
+       }
+       return;
+ 
+     case CLAN_EDIT_DESCRIPTION_FINISHED:
+       switch (*arg)
+       {
+ 	case 'S':
+         case 's':
+ 	  CLAN_EDIT_MODE(num) = CLAN_EDIT_MAIN_MENU;
+ 	  display_menu(d->character, CLAN_EDIT_CLAN(num));
+ 	  break;
+ 	default:
+ 	  CLANDESC(clan_index[cross_reference[CLAN_EDIT_CLAN(num)]]) =
+ 		str_dup(clan_index[cross_reference[CLAN_EDIT_CLAN(num)]].old_description);
+ 	  CLAN_EDIT_MODE(num) = CLAN_EDIT_MAIN_MENU;
+ 	  display_menu(d->character, CLAN_EDIT_CLAN(num));
+ 	  break;
+       }
+       break;
+ 
+     case CLAN_EDIT_CONFIRM_DELETE:
+       switch (*arg)
+       {
+ 	case 'Y':
+ 	case 'y':
+ 	  CLANSTATUS(cross_reference[CLAN_EDIT_CLAN(num)]) = CLAN_DELETE;
+ 	  refresh_clan_index();
+ 	  cleanup_clan_edit(d, CLEAN_NODE);
+ 	  send_to_char("\r\nClan deleted.\r\n", d->character);
+ 	  break;
+ 	case 'N':
+ 	case 'n':
+ 	  send_to_char("\r\nNOT deleted.\r\n", d->character);
+ 	  CLAN_EDIT_MODE(num) = CLAN_EDIT_MAIN_MENU;
+ 	  display_menu(d->character, CLAN_EDIT_CLAN(num));
+ 	  break;
+       }
+       break;
+ 
+     case CLAN_EDIT_CONFIRM_SAVE:
+       switch (*arg)
+       {
+ 	case 'Y':
+ 	case 'y':
+ 	  cleanup_clan_edit(d, CLEAN_NODE);
+ 	  send_to_char("\r\nSaved.\r\n", d->character);
+ 	  break;
+ 	case 'N':
+ 	case 'n':
+ 	  cleanup_clan_edit(d, CLEAN_ALL);
+ 	  send_to_char("\r\nNOT saved.\r\n", d->character);
+ 	  break;
+ 	default:
+ 	  send_to_char("\r\nInvalid command!", d->character);
+ 	  display_menu(d->character, CLAN_EDIT_CLAN(num));
+ 	  break;
+       }
+       return;
+ 
+     case CLAN_EDIT_NUMBER:
+       i = 0;
+       i = atoi(arg);
+       if (!(i <= 0))
+       {
+ 	if (is_clannum_already_used(i) == NO)
+ 	{
+ 	  update_cnum(CLAN_EDIT_CLAN(num), i);
+ 	  CLAN_EDIT_CLAN(num) = i;
+ 	  CLAN_EDIT_MODE(num) = CLAN_EDIT_MAIN_MENU;
+ 	  display_menu(d->character, CLAN_EDIT_CLAN(num));
+ 	}
+ 	else
+ 	{
+ 	  send_to_char("\r\nThat number already in use!\r\n", d->character);
+ 	  CLAN_EDIT_MODE(num) = CLAN_EDIT_MAIN_MENU;
+ 	  display_menu(d->character, CLAN_EDIT_CLAN(num));
+ 	}
+       }
+       else
+       {
+         send_to_char("\r\nInvalid number!\r\n", d->character);
+ 	CLAN_EDIT_MODE(num) = CLAN_EDIT_MAIN_MENU;
+ 	display_menu(d->character, CLAN_EDIT_CLAN(num));
+       }
+       break;
+ 
+     case CLAN_EDIT_NAME:
+       CLANNAME(clan_index[cross_reference[CLAN_EDIT_CLAN(num)]]) = str_dup(arg);
+       CLAN_EDIT_MODE(num) = CLAN_EDIT_MAIN_MENU;
+       display_menu(d->character, CLAN_EDIT_CLAN(num));
+       break;
+ 
+     case CLAN_EDIT_OWNER:
+       /* No error checking here */
+       CLANOWNER(clan_index[cross_reference[CLAN_EDIT_CLAN(num)]]) = str_dup(arg);
+       CLAN_EDIT_MODE(num) = CLAN_EDIT_MAIN_MENU;
+       display_menu(d->character, CLAN_EDIT_CLAN(num));
+       break;
+ 
+     case CLAN_EDIT_GOLD:
+       i = 0;
+       i = atoi(arg);
+       if (!(i <= 0))
+       {
+ 	CLANGOLD(clan_index[cross_reference[CLAN_EDIT_CLAN(num)]]) = i;
+ 	CLAN_EDIT_MODE(num) = CLAN_EDIT_MAIN_MENU;
+         display_menu(d->character, CLAN_EDIT_CLAN(num));
+       }
+       else
+       {
+ 	send_to_char("\r\nInvalid number!\r\n", d->character);
+ 	CLAN_EDIT_MODE(num) = CLAN_EDIT_MAIN_MENU;
+ 	display_menu(d->character, CLAN_EDIT_CLAN(num));
+       }
+       break;
+ 
+     case CLAN_EDIT_CLANROOM:
+ 	/* No error checking */
+       i = 0;
+       i = atoi(arg);
+       if (!(i <= 0))
+       {
+ 	CLANROOM(clan_index[cross_reference[CLAN_EDIT_CLAN(num)]]) = i;
+ 	CLAN_EDIT_MODE(num) = CLAN_EDIT_MAIN_MENU;
+         display_menu(d->character, CLAN_EDIT_CLAN(num));
+       }
+       else
+       {
+ 	send_to_char("\r\nInvalid number!\r\n", d->character);
+ 	CLAN_EDIT_MODE(num) = CLAN_EDIT_MAIN_MENU;
+ 	display_menu(d->character, CLAN_EDIT_CLAN(num));
+       }
+       break;
+ 
+     case CLAN_EDIT_COLOUR:
+       switch (*arg)
+       {
+ 	case 'w':
+ 	case 'W':
+ 	  CLANCOLOR(cross_reference[CLAN_EDIT_CLAN(num)]) = CLAN_WHITE;
+ 	  display_menu(d->character, CLAN_EDIT_CLAN(num));
+           CLAN_EDIT_MODE(num) = CLAN_EDIT_MAIN_MENU;
+ 	  break;
+ 	case 'n':
+ 	case 'N':
+ 	  CLANCOLOR(cross_reference[CLAN_EDIT_CLAN(num)]) = CLAN_NORMAL;
+ 	  display_menu(d->character, CLAN_EDIT_CLAN(num));
+           CLAN_EDIT_MODE(num) = CLAN_EDIT_MAIN_MENU;
+ 	  break;
+ 	case 'r':
+ 	case 'R':
+ 	  CLANCOLOR(cross_reference[CLAN_EDIT_CLAN(num)]) = CLAN_RED;
+ 	  display_menu(d->character, CLAN_EDIT_CLAN(num));
+           CLAN_EDIT_MODE(num) = CLAN_EDIT_MAIN_MENU;
+ 	  break;
+ 	case 'g':
+ 	case 'G':
+ 	  CLANCOLOR(cross_reference[CLAN_EDIT_CLAN(num)]) = CLAN_GREEN;
+ 	  display_menu(d->character, CLAN_EDIT_CLAN(num));
+           CLAN_EDIT_MODE(num) = CLAN_EDIT_MAIN_MENU;
+ 	  break;
+ 	case 'b':
+ 	case 'B':
+ 	  CLANCOLOR(cross_reference[CLAN_EDIT_CLAN(num)]) = CLAN_BLUE;
+ 	  display_menu(d->character, CLAN_EDIT_CLAN(num));
+           CLAN_EDIT_MODE(num) = CLAN_EDIT_MAIN_MENU;
+ 	  break;
+ 	case 'y':
+ 	case 'Y':
+ 	  CLANCOLOR(cross_reference[CLAN_EDIT_CLAN(num)]) = CLAN_YELLOW;
+ 	  display_menu(d->character, CLAN_EDIT_CLAN(num));
+           CLAN_EDIT_MODE(num) = CLAN_EDIT_MAIN_MENU;
+ 	  break;
+ 	case 'm':
+ 	case 'M':
+ 	  CLANCOLOR(cross_reference[CLAN_EDIT_CLAN(num)]) = CLAN_MAGENTA;
+ 	  display_menu(d->character, CLAN_EDIT_CLAN(num));
+           CLAN_EDIT_MODE(num) = CLAN_EDIT_MAIN_MENU;
+ 	  break;
+ 	case 'c':
+ 	case 'C':
+ 	  CLANCOLOR(cross_reference[CLAN_EDIT_CLAN(num)]) = CLAN_CYAN;
+ 	  display_menu(d->character, CLAN_EDIT_CLAN(num));
+           CLAN_EDIT_MODE(num) = CLAN_EDIT_MAIN_MENU;
+ 	  break;
+ 	default:
+ 	  send_to_char("Invalid colour!\r\n", d->character);
+ 	  display_menu(d->character, CLAN_EDIT_CLAN(num));
+           CLAN_EDIT_MODE(num) = CLAN_EDIT_MAIN_MENU;
+ 	  break;
+       }
+       display_menu(d->character, CLAN_EDIT_CLAN(num));
+       CLAN_EDIT_MODE(num) = CLAN_EDIT_MAIN_MENU;
+       break;
+ 
+     case CLAN_EDIT_SOLDIER:
+       SOLDIERTITLE(clan_index[cross_reference[CLAN_EDIT_CLAN(num)]]) =
+ 	str_dup(arg);
+       CLAN_EDIT_MODE(num) = CLAN_EDIT_RANK_MENU;
+       display_rank_menu(d, num);
+       break;
+ 
+     case CLAN_EDIT_SARGEANT:
+       SARGEANTTITLE(clan_index[cross_reference[CLAN_EDIT_CLAN(num)]]) =
+ 	str_dup(arg);
+       CLAN_EDIT_MODE(num) = CLAN_EDIT_RANK_MENU;
+       display_rank_menu(d, num);
+       break;
+   
+     case CLAN_EDIT_CAPTAIN:
+       CAPTAINTITLE(clan_index[cross_reference[CLAN_EDIT_CLAN(num)]]) =
+ 	str_dup(arg);
+       CLAN_EDIT_MODE(num) = CLAN_EDIT_RANK_MENU;
+       display_rank_menu(d, num);
+       break;
+ 
+     case CLAN_EDIT_RULER:
+       RULERTITLE(clan_index[cross_reference[CLAN_EDIT_CLAN(num)]]) =
+ 	str_dup(arg);
+       CLAN_EDIT_MODE(num) = CLAN_EDIT_RANK_MENU;
+       display_rank_menu(d, num);
+       break;
+ 
+     case CLAN_EDIT_RANK_MENU:
+       switch (*arg)
+       {
+ 	case '1':
+ 	  CLAN_EDIT_MODE(num) = CLAN_EDIT_SOLDIER;
+ 	  send_to_char("\r\nEnter new soldier rank: \r\n", d->character);
+ 	  break;
+ 	case '2':
+ 	  CLAN_EDIT_MODE(num) = CLAN_EDIT_SARGEANT;
+ 	  send_to_char("\r\nEnter new sargeant rank: \r\n", d->character);
+ 	  break;
+ 	case '3':
+ 	  CLAN_EDIT_MODE(num) = CLAN_EDIT_CAPTAIN;
+ 	  send_to_char("\r\nEnter new captain rank: \r\n", d->character);
+ 	  break;
+ 	case '4':
+ 	  CLAN_EDIT_MODE(num) = CLAN_EDIT_RULER;
+ 	  send_to_char("\r\nEnter new ruler rank: \r\n", d->character);
+ 	  break;
+ 	case 'q':
+         case 'Q':
+ 	  CLAN_EDIT_MODE(num) = CLAN_EDIT_MAIN_MENU;
+ 	  display_menu(d->character, CLAN_EDIT_CLAN(num));
+ 	  break;
+ 	default:
+ 	  send_to_char("\r\nInvalid command!\r\n", d->character);
+ 	  display_rank_menu(d, num);
+ 	  break;
+       }
+       break;
+ 
+     }
+ 
+ }
+ 
+ void display_colour_menu(struct descriptor_data *d)
+ {
+   struct char_data *ch;
+ 
+   ch = d->character;
+ 
+   send_to_char("\r\n\x1B[H\x1B[J", ch);
+   sprintf(buf, "%s(W)hite\r\n", CCWHT(ch, C_NRM));
+   sprintf(buf, "%s%s(R)ed\r\n", buf, CCRED(ch, C_NRM));
+   sprintf(buf, "%s%s(G)reen\r\n", buf, CCGRN(ch, C_NRM));
+   sprintf(buf, "%s%s(B)lue\r\n", buf, CCBLU(ch, C_NRM));
+   sprintf(buf, "%s%s(Y)ellow\r\n", buf, CCYEL(ch, C_NRM));
+   sprintf(buf, "%s%s(M)agenta\r\n", buf, CCMAG(ch, C_NRM));
+   sprintf(buf, "%s%s(C)yan\r\n", buf, CCCYN(ch, C_NRM));
+   sprintf(buf, "%s%s(N)ormal\r\n", buf, CCNRM(ch, C_NRM));
+   sprintf(buf, "%s\r\nSelect a colour: ", buf);
+   send_to_char(buf, ch);
+ 
+ }
+ 
+ void display_rank_menu(struct descriptor_data *d, int num)
+ {
+   struct char_data *ch;
+ 
+   ch = d->character;
+ 
+   sprintf(buf, "\x1B[H\x1B[J\r\n%sSoldier Rank : %s%s\r\n", CCYEL(ch, C_NRM), 
+ 		CCGRN(ch, C_NRM), 
+ 	SOLDIERTITLE(clan_index[cross_reference[CLAN_EDIT_CLAN(num)]]));
+   sprintf(buf, "%s%sSargeant Rank: %s%s\r\n", buf, CCYEL(ch, C_NRM),
+ 		CCGRN(ch, C_NRM), 
+ 	SARGEANTTITLE(clan_index[cross_reference[CLAN_EDIT_CLAN(num)]]));
+   sprintf(buf, "%s%sCaptain Rank : %s%s\r\n", buf, CCYEL(ch, C_NRM),
+ 		CCGRN(ch, C_NRM), 
+ 	CAPTAINTITLE(clan_index[cross_reference[CLAN_EDIT_CLAN(num)]]));
+   sprintf(buf, "%s%sRuler Rank: %s%s\r\n", buf, CCYEL(ch, C_NRM),
+ 		CCGRN(ch, C_NRM), 
+ 	RULERTITLE(clan_index[cross_reference[CLAN_EDIT_CLAN(num)]]));
+   sprintf(buf, "%s\r\n%s1. %sEdit Soldier Rank\r\n", buf, CCYEL(ch, C_NRM),
+ 		CCGRN(ch, C_NRM));
+   sprintf(buf, "%s%s2. %sEdit Sargeant Rank\r\n", buf, CCYEL(ch, C_NRM),
+ 		CCGRN(ch, C_NRM));
+   sprintf(buf, "%s%s3. %sEdit Captain Rank\r\n", buf, CCYEL(ch, C_NRM),
+ 		CCGRN(ch, C_NRM));
+   sprintf(buf, "%s%s4. %sEdit Ruler Rank\r\n", buf, CCYEL(ch, C_NRM),
+ 		CCGRN(ch, C_NRM));
+   sprintf(buf, "%s\r\n%sQ. %sReturn to main menu\r\n", buf, CCYEL(ch, C_NRM),
+ 		CCGRN(ch, C_NRM));
+   send_to_char(buf, ch);
+ 
+ 
+ }
+ 
+ /* Debug stuff goes here */
+ int debug_clan(char *what, struct char_data *ch)
+ {
+   int i = 0, count = 0, debug_type = 0;
+   time_t ct;
+   char *tmstr;
+   FILE *fl = NULL;
+ 
+   /* Find type of debug request */
+   if (strcasecmp(what, "cref") == 0)
+     debug_type = CLAN_DEBUG_CREF;
+   if (strcasecmp(what, "node") == 0)
+     debug_type = CLAN_DEBUG_NODE;
+   if (strcasecmp(what, "var") == 0)
+     debug_type = CLAN_DEBUG_VAR;
+   if (strcasecmp(what, "all") == 0)
+     debug_type = CLAN_DEBUG_ALL;
+ 
+   if (debug_type != CLAN_DEBUG_UNKNOWN)
+   {
+     /* Open debug file */
+     sprintf(buf, "%s/DEBUG", CLAN_PREFIX);
+     if (!(fl = fopen(buf, "a")))
+     {
+       fprintf(stderr, "Error opening clan debug file '%s'!\n", buf);
+       return NO;
+     }
+ 
+     /* DateTime stamp entry */
+     ct = time(0);
+     tmstr = asctime(localtime(&ct));
+     *(tmstr + strlen(tmstr) - 1 ) = '\0';
+     fprintf(fl, "%-19.19s :: Debug requested by user\n", tmstr);
+     fprintf(fl, "\nDebug requested by: %s\n", GET_NAME(ch));
+   }
+ 
+   if ((debug_type == CLAN_DEBUG_VAR) || (debug_type == CLAN_DEBUG_ALL))
+   {
+     /* Dump relevant global variables */
+     fprintf(fl, "Debug request type: -GLOBAL VARIABLES-\n\n");
+     
+     fprintf(fl, "-CLAN STATUS-\n\n");
+     fprintf(fl, "Clan # | Status\n");
+     fprintf(fl, "-------|-------\n");
+ 
+     for (i = 0; i < clan_top; i++)
+       fprintf(fl, "  %-4d | %d    \n", clan_index[i].number, CLANSTATUS(i));
+ 
+ 
+     fprintf(fl, "\n\n");
+   }
+ 
+   if ((debug_type == CLAN_DEBUG_CREF) || (debug_type == CLAN_DEBUG_ALL))
+   {
+     i = 0;
+     /* Dump cross reference variable to debug file */
+     fprintf(fl, "Debug request type: -CROSS REFERENCE-\n");
+ 
+     fprintf(fl, "\nClan # | Index\n");
+     fprintf(fl, "-------|------\n");
+     for (i = 0; i < 9999; i++)
+       if (cross_reference[i] != -1) 
+ 	fprintf(fl, "%-6d | %d\n", i, cross_reference[i]);
+       else
+   	count++;
+     fprintf(fl, "\n%d valid records, %d empty records.\n\n", 
+ 	(9999 - count), count);
+   }
+ 
+   if ((debug_type == CLAN_DEBUG_NODE) || (debug_type == CLAN_DEBUG_ALL))
+   {
+     count = 0;
+     /* Dump clan editing nodes to debug file */
+     fprintf(fl, "Debug request type: -CLAN EDIT NODES-\n");
+ 
+     fprintf(fl, "\nNode # | Clan # | Mode   | Owner\n");
+     fprintf(fl, "-------|--------|--------|-------------------\n");
+     for (i = 0; i < 10; i++)
+       if (CLAN_EDIT_DESC(i) != NULL)
+       {
+ 	sprintf(buf2, "    %-2d |   %-4d | ", i, CLAN_EDIT_CLAN(i));
+         switch (CLAN_EDIT_MODE(i))
+     	{
+ 	  case CLAN_EDIT_DESCRIPTION_FINISHED:
+ 	    fprintf(fl, "%s-Desc- | %s\n", buf2,
+ 		GET_NAME(CLAN_EDIT_DESC(i)->character));
+ 	    break;
+ 	  case CLAN_EDIT_CONFIRM_SAVE:
+ 	    fprintf(fl, "%sCon-Sv | %s\n", buf2, 
+ 		GET_NAME(CLAN_EDIT_DESC(i)->character));
+ 	    break;
+ 	  case CLAN_EDIT_MAIN_MENU:
+ 	    fprintf(fl, "%s-Main- | %s\n", buf2, 
+ 		GET_NAME(CLAN_EDIT_DESC(i)->character));
+ 	    break;
+ 	  case CLAN_EDIT_NAME:
+ 	    fprintf(fl, "%sClnNam | %s\n", buf2, 
+ 		GET_NAME(CLAN_EDIT_DESC(i)->character));
+ 	    break;
+ 	  case CLAN_EDIT_NUMBER:
+ 	    fprintf(fl, "%sClnNum | %s\n", buf2, 
+ 		GET_NAME(CLAN_EDIT_DESC(i)->character));
+ 	    break;
+ 	  case CLAN_EDIT_GOLD:
+ 	    fprintf(fl, "%sClnGld | %s\n", buf2, 
+ 		GET_NAME(CLAN_EDIT_DESC(i)->character));
+ 	    break;
+ 	  case CLAN_EDIT_OWNER:
+ 	    fprintf(fl, "%sClnOwn | %s\n", buf2, 
+ 		GET_NAME(CLAN_EDIT_DESC(i)->character));
+ 	    break;
+ 	  case CLAN_EDIT_DESCRIPTION:
+ 	    fprintf(fl, "%sClnDsc | %s\n", buf2, 
+ 		GET_NAME(CLAN_EDIT_DESC(i)->character));
+ 	    break;
+ 	  case CLAN_EDIT_CLANROOM:
+ 	    fprintf(fl, "%sCln-Rm | %s\n", buf2, 
+ 		GET_NAME(CLAN_EDIT_DESC(i)->character));
+ 	    break;
+ 	  case CLAN_EDIT_COLOUR:
+ 	    fprintf(fl, "%sClnClr | %s\n", buf2, 
+ 		GET_NAME(CLAN_EDIT_DESC(i)->character));
+ 	    break;
+ 	  case CLAN_EDIT_RANK_MENU:
+ 	    fprintf(fl, "%sRnkMnu | %s\n", buf2, 
+ 		GET_NAME(CLAN_EDIT_DESC(i)->character));
+ 	    break;
+ 	  case CLAN_EDIT_SELECT_COLOUR:
+ 	    fprintf(fl, "%sSltClr | %s\n", buf2, 
+ 		GET_NAME(CLAN_EDIT_DESC(i)->character));
+ 	    break;
+ 	  case CLAN_EDIT_SOLDIER:
+ 	    fprintf(fl, "%sRnkSld | %s\n", buf2, 
+ 		GET_NAME(CLAN_EDIT_DESC(i)->character));
+ 	    break;
+ 	  case CLAN_EDIT_SARGEANT:
+ 	    fprintf(fl, "%sRnkSgt | %s\n", buf2, 
+ 		GET_NAME(CLAN_EDIT_DESC(i)->character));
+ 	    break;
+ 	  case CLAN_EDIT_CAPTAIN:
+ 	    fprintf(fl, "%sRnkCpt | %s\n", buf2, 
+ 		GET_NAME(CLAN_EDIT_DESC(i)->character));
+ 	    break;
+ 	  case CLAN_EDIT_RULER:
+ 	    fprintf(fl, "%sRnkRlr | %s\n", buf2, 
+ 		GET_NAME(CLAN_EDIT_DESC(i)->character));
+ 	    break;
+ 	  default:
+ 	    fprintf(fl, "%s%d | %s\n", buf2, CLAN_EDIT_MODE(i),
+ 		GET_NAME(CLAN_EDIT_DESC(i)->character));
+ 	    break;
+ 	}
+       }
+       else count++;
+ 
+     fprintf(fl, "\n%d nodes used, %d free nodes.\n\n", (10 - count), count);
+   }
+ 
+   if (debug_type == CLAN_DEBUG_UNKNOWN)
+   {
+     send_to_char("clan debug <type>\r\n", ch);
+     send_to_char("\r\nValid types:\r\n", ch);
+     send_to_char("            cref          - cross reference variable\r\n", ch);
+     send_to_char("            node          - clan edit nodes\r\n", ch);
+     send_to_char("            var           - global variables\r\n", ch);
+     send_to_char("            all           - all debug reports\r\n", ch);
+     return NO;
+   }
+ 
+   fclose(fl);
+   return YES;
+ }
+ 
+ 
+ /* (FIDO) End */
diff -c -P -x *.o orig-src/clan.ct src/clan.ct
*** orig-src/clan.ct	Thu Jan  1 10:00:00 1970
--- src/clan.ct	Tue Feb 11 22:15:10 1997
***************
*** 0 ****
--- 1,742 ----
+ /* ************************************************************************
+ *   File: clan.c				    Addition to CircleMUD *
+ *  Usage: Source file for clan-specific code                              *
+ *                                                                         *
+ *  Copyright (c) to Daniel Muller					  *
+ *									  *
+ ************************************************************************ */
+ 
+ /*
+  * This file attempts to concentrate all of the clan specific code for the
+  * implementation of clans in CircleMUD.  I've tried to mimic the code 
+  * style of the rest of CircleMUD's code, to make it easier for you to
+  * modify as needed.
+ */
+ 
+ 
+ 
+ #include "conf.h"
+ #include "sysdep.h"
+ #include "string.h"
+ 
+ #include "structs.h"
+ #include "db.h"
+ #include "utils.h"
+ #include "spells.h"
+ #include "interpreter.h"
+ #include "comm.h"
+ #include "screen.h"
+ #include "clan.h"
+ #include "handler.h"
+ 
+ /*   external vars  */
+ extern struct descriptor_data *descriptor_list;
+ extern char *class_abbrevs[];
+ extern FILE *player_fl;
+ 
+ /*   external functions */
+ extern int file_to_string(char *name, char *buf);
+ 
+ /*
+  * Clan names go here.
+  *
+  * Restrictions: A clan title must not be longer than 25 characters.
+  *               A Owner's name may not be longer than 15 characters.
+  *		 Rank titles must not be longer than 10 characters.
+  *               
+  *       Format: "clan title", "colour of title", "Owner", 
+  *		 "clan description filename", "Title of rank SOLDIER",
+  *		 "Title of rank SARGEANT", "Title of rank CAPTAIN",
+  *		 "Title of rank RULER"
+  *
+  *       Dialog: For the colour of the title, use valid CircleMUD colour codes
+  *               ie. CCBLU
+  *
+  *               The "Owner" is the name of the clan owner character.  This is
+  *               displayed in the clan information command as a reference point
+  *
+  *		 The "clan description filename" is the filename + path of a
+  *		 plain textfile with a short clan description.  Put "\n" if
+  * 		 you don't want one to display.  It goes in the lib/ dir.
+  *
+  *		 The rank titles are simply the clan names for each rank.
+  *
+  *               Feel free to change the two existing clans.
+  *
+  */
+ const struct clan_info clans[] = {
+   { "Da Funky Immortals"      , "CCMAG", "Regulator"     , "clanimm",
+     "Grunt"  , "Sarge"  , "Captain", "Ruler"  },
+   { "Da Gross Mortals"        , "CCBLU", "Regulator"     , "clanmort",
+     "Absolum", "Tweekie", "Mr."    , "SIR!" },
+ 
+   /* New clans go here */
+ 
+   /* This must go at the end */
+   { "\n"                      , "NULL" , "NULL"          , "NULL",
+     "NULL", "NULL", "NULL", "NULL" }
+ };
+ 
+ /*
+  * Clan levels
+ */
+ const int CLAN_APPLY = 1;
+ const int CLAN_SOLDIER = 2;
+ const int CLAN_SARGEANT = 3;
+ const int CLAN_CAPTAIN = 4;
+ const int CLAN_RULER = 5;
+ 
+ /*
+  * General functions go here
+ */
+ 
+ 
+ 
+ 
+ /*
+  * The general player commands go here
+ */
+ ACMD(do_clan)
+ {
+   char subbcmd[MAX_INPUT_LENGTH], val_arg[MAX_INPUT_LENGTH];
+   int  ccmd = 0, value = 0, found = 0, temp = 0, temp2 = 0, player_i = 0;
+   struct char_data *cbuf = NULL, *vict = NULL;
+   struct char_file_u tmp_store;
+   struct descriptor_data *pt;
+ 
+   half_chop(argument, subbcmd, buf);
+   strcpy(val_arg, buf);
+   
+   if (strcasecmp(subbcmd, "list") == 0)
+   {
+     /* Display title for list */
+     send_to_char("[ # Clan Title                Clan Owner     ]\r\n", ch);
+     /* List all clans and owners */
+     for (ccmd = 0; clans[ccmd].title != "\n"; ccmd++)
+     {
+       if (clans[ccmd].colour == "CCNRM") sprintf(buf, " %2d %s%-25s%s %-15s\r\n", 
+         ccmd, CCNRM(ch, C_NRM), clans[ccmd].title, 
+         CCNRM(ch, C_NRM), clans[ccmd].owner);
+       if (clans[ccmd].colour == "CCRED") sprintf(buf, " %2d %s%-25s%s %-15s\r\n", 
+         ccmd, CCRED(ch, C_NRM), clans[ccmd].title, 
+ 	CCNRM(ch, C_NRM), clans[ccmd].owner);
+       if (clans[ccmd].colour == "CCYEL") sprintf(buf, " %2d %s%-25s%s %-15s\r\n", 
+         ccmd, CCYEL(ch, C_NRM), clans[ccmd].title, 
+ 	CCNRM(ch, C_NRM), clans[ccmd].owner);
+       if (clans[ccmd].colour == "CCGRN") sprintf(buf, " %2d %s%-25s%s %-15s\r\n", 
+         ccmd, CCGRN(ch, C_NRM), clans[ccmd].title, 
+ 	CCNRM(ch, C_NRM), clans[ccmd].owner);
+       if (clans[ccmd].colour == "CCBLU") sprintf(buf, " %2d %s%-25s%s %-15s\r\n", 
+         ccmd, CCBLU(ch, C_NRM), clans[ccmd].title, 
+ 	CCNRM(ch, C_NRM), clans[ccmd].owner);
+       if (clans[ccmd].colour == "CCMAG") sprintf(buf, " %2d %s%-25s%s %-15s\r\n", 
+         ccmd, CCMAG(ch, C_NRM), clans[ccmd].title, 
+ 	CCNRM(ch, C_NRM), clans[ccmd].owner);
+       if (clans[ccmd].colour == "CCCYN") sprintf(buf, " %2d %s%-25s%s %-15s\r\n", 
+         ccmd, CCCYN(ch, C_NRM), clans[ccmd].title, 
+ 	CCNRM(ch, C_NRM), clans[ccmd].owner);
+       if (clans[ccmd].colour == "CCWHT") sprintf(buf, " %2d %s%-25s%s %-15s\r\n", 
+         ccmd, CCWHT(ch, C_NRM), clans[ccmd].title, 
+ 	CCNRM(ch, C_NRM), clans[ccmd].owner);
+       send_to_char(buf, ch);
+     }
+   sprintf(buf, "\r\n[%d clans displayed.]\r\n", ccmd);
+   send_to_char(buf, ch);
+ 
+   }
+ 
+   if (strcasecmp(subbcmd, "info") == 0)
+   {
+     /* Use index to retrieve information on clan */
+     value = atoi(val_arg);
+     if (value != 0)
+     {
+       for (ccmd = 0; clans[ccmd].title != "\n"; ccmd++)
+ 	if (ccmd == value)
+ 	{
+ 	  found = 1;
+ 	  temp2 = 0;
+ 	  
+ 	  /* Find number of members in clan */
+ 	  /* This is stored in the owners char structure */
+ 	  if (!(vict = get_char_vis(ch, clans[ccmd].owner)))
+ 	  {
+ 	    CREATE(cbuf, struct char_data, 1);
+             clear_char(cbuf);
+     	    if ((player_i = load_char(clans[ccmd].owner, &tmp_store)) > -1) 
+ 	    {
+               store_to_char(&tmp_store, cbuf);
+               vict = cbuf;
+             } 
+ 	    else 
+             {
+               free(cbuf);
+   	      sprintf(buf, "Clan info: Unable to find owner of '%s' clan.", 
+ 		          clans[ccmd].title);
+       	      mudlog(buf, BRF, LVL_GOD, TRUE);
+               return;
+             }
+ 	  }
+ 	  else temp2 = 1;
+ 
+ 	  temp = CLANPLAYERS(vict);
+ 
+ 	  /* Store player record */
+ 	  if (temp2 == 0)
+ 	  {
+             char_to_store(vict, &tmp_store);
+   	    fseek(player_fl, (player_i) * sizeof(struct char_file_u), SEEK_SET);
+     	    fwrite(&tmp_store, sizeof(struct char_file_u), 1, player_fl);
+     	    free_char(cbuf);
+ 	  }
+ 
+ 	  temp2 = 0;
+ 	  /* Find number of clan members currently online */
+   	  for (pt = descriptor_list; pt; pt = pt->next)
+     	    if (!pt->connected && pt->character && 
+                 pt->character->player_specials->saved.clannum == value)
+ 	      temp2++;
+ 
+ 	  /* Display info header */
+ 	  if (clans[ccmd].colour == "CCNRM")
+ 	    sprintf(buf, "[%s", CCNRM(ch, C_NRM));
+ 	  if (clans[ccmd].colour == "CCRED")
+ 	    sprintf(buf, "[%s", CCRED(ch, C_NRM));
+ 	  if (clans[ccmd].colour == "CCGRN")
+ 	    sprintf(buf, "[%s", CCGRN(ch, C_NRM));
+ 	  if (clans[ccmd].colour == "CCYEL")
+ 	    sprintf(buf, "[%s", CCYEL(ch, C_NRM));
+ 	  if (clans[ccmd].colour == "CCBLU")
+ 	    sprintf(buf, "[%s", CCBLU(ch, C_NRM));
+ 	  if (clans[ccmd].colour == "CCMAG")
+ 	    sprintf(buf, "[%s", CCMAG(ch, C_NRM));
+ 	  if (clans[ccmd].colour == "CCWHT")
+ 	    sprintf(buf, "[%s", CCWHT(ch, C_NRM));
+ 	  if (clans[ccmd].colour == "CCCYN")
+ 	    sprintf(buf, "[%s", CCCYN(ch, C_NRM));
+ 	  
+ 	  sprintf(buf, "%s%-25s%s]\r\n", buf, clans[ccmd].title, CCNRM(ch, C_NRM));
+ 	  send_to_char(buf, ch);
+ 	
+ 	  send_to_char("\r\n", ch);
+ 	  sprintf(buf, "Owner: %-15s\r\n", clans[ccmd].owner);
+ 	  send_to_char(buf, ch);
+ 	  sprintf(buf, "Members currently online: %-3d\r\nTotal number of members: %-3d\r\n", temp2, temp);
+ 	  send_to_char(buf, ch);
+ 	  send_to_char("\r\n", ch);
+ 
+ 	  if (!(clans[ccmd].fname == "\n"))
+ 	  {
+ 	    file_to_string(clans[ccmd].fname, buf);
+ 	    send_to_char(CCGRN(ch, C_NRM), ch);
+ 	    send_to_char(buf, ch);
+ 	    send_to_char(CCNRM(ch, C_NRM), ch);
+ 	  }
+ 	  send_to_char("\r\n", ch);
+ 	}
+     
+       if (found == 0)
+       {
+ 	send_to_char("Unable to find a clan with that number.\r\n", ch);
+ 	return;
+       }
+     }
+     else
+     {
+       send_to_char("Unable to find a clan with that number.\r\n", ch);
+     }
+   }
+ 
+   if (strcasecmp(subbcmd, "resign") == 0)
+   {
+     temp2 = 0;
+ 
+     /* This handles clan resignations */
+     if ((ch->player_specials->saved.clannum == 0) && (CLANRANK(ch) == 0))
+     {
+       send_to_char("But you don't belong to any clan!\r\n", ch);
+       return;
+     }
+ 
+     if (strcasecmp(GET_NAME(ch), CLANOWNER(ch)) == 0)
+     {
+       send_to_char("You can't resign from a clan you own!\r\n", ch);
+       return;
+     }
+ 
+     value = ch->player_specials->saved.clannum;
+     ch->player_specials->saved.clannum = 0;
+     ch->player_specials->saved.clanrank = 0;
+     
+     /* Update number of members in clan */
+     /* This is stored in the owners char structure */
+     for (ccmd = 0; clans[ccmd].title != "\n"; ccmd++)
+       if (ccmd == value)
+ 	  if (!(vict = get_char_vis(ch, clans[ccmd].owner)))
+ 	  {
+ 	    CREATE(cbuf, struct char_data, 1);
+             clear_char(cbuf);
+     	    if ((player_i = load_char(clans[ccmd].owner, &tmp_store)) > -1) 
+ 	    {
+               store_to_char(&tmp_store, cbuf);
+               vict = cbuf;
+             } 
+ 	    else 
+             {
+               free(cbuf);
+   	      sprintf(buf, "Clan info: Unable to find owner of '%s' clan.", 
+ 		          clans[ccmd].title);
+       	      mudlog(buf, BRF, LVL_GOD, TRUE);
+               return;
+             }
+ 	  }
+       else
+ 	temp2 = 1;
+ 
+     if (!(CLANRANK(ch) == CLAN_APPLY))    
+       vict->player_specials->saved.numclanmembers--;
+ 
+ 	  /* Store player record */
+ 	if (temp2 == 0)
+ 	{
+           char_to_store(vict, &tmp_store);
+   	  fseek(player_fl, (player_i) * sizeof(struct char_file_u), SEEK_SET);
+     	  fwrite(&tmp_store, sizeof(struct char_file_u), 1, player_fl);
+     	  free_char(cbuf);
+ 	}
+ 
+     send_to_char("You have resigned from your clan.\r\n", ch);
+ 
+   }
+ 
+   if (strcasecmp(subbcmd, "apply") == 0)
+   {
+     /* This handles clan applications */
+     if (CLANRANK(ch) != 0)
+     {
+       send_to_char("You must resign from the clan you currently belong to, first.\r\n", ch);
+       return;
+     }
+ 
+     value = 0;
+     found = 0;
+     value = atoi(val_arg);
+     if (value >= 0)
+     {
+       for (ccmd = 0; ((clans[ccmd].title != "\n") && (found != 1)); ccmd++)
+         if (ccmd == value)
+ 	{
+ 	  found = 1;
+ 
+ 	  CLANNUM(ch) = ccmd;
+ 	  CLANRANK(ch) = CLAN_APPLY;
+ 
+ 	  sprintf(buf, "You have applied to the clan '%s'.\r\n", CLANNAME(ch));
+ 	  send_to_char(buf, ch);
+ 	}
+ 
+       if (found != 1)
+       {
+ 	send_to_char("Unable to find that clan.\r\n", ch);
+ 	return;
+       }
+     }
+     else
+     {
+       send_to_char("Which clan number?!\r\n", ch);
+       return;
+     }
+ 
+   }
+ 
+   if (strcasecmp(subbcmd, "enlist") == 0)
+   {
+     /* This handles the enlistment of characters who have applied to your
+      * clan.
+      *
+      * Implementors can force an enlistment.  So, when creating a new clan,
+      * make sure your owner applies to join it.  Then the implementor must
+      * do a 'clan enlist <character>' so that the owner belongs to the clan.
+     */
+     
+     if (!(GET_LEVEL(ch) == LVL_IMPL))
+     {
+       if (CLANRANK(ch) == 0)
+       {
+         send_to_char("But you don't belong to any clan!\r\n", ch);
+         return;
+       }
+ 
+       if (!(CLANRANK(ch) >= CLAN_SARGEANT))
+       {
+ 	send_to_char("You have insufficent rank in your clan to do this.\r\n", ch);
+ 	return;
+       }
+ 
+       if ((vict = get_player_vis(ch, val_arg, 0)))
+       {
+ 	if (CLANRANK(vict) != CLAN_APPLY)
+ 	{
+ 	  send_to_char("But that person isn't applying to any clan!\r\n", ch);
+ 	  return;
+ 	}
+ 
+ 	if (CLANNUM(vict) != CLANNUM(ch))
+ 	{
+ 	  send_to_char("But that person isn't applying to your clan!\r\n", ch);
+ 	  return;
+ 	}
+ 
+ 	CLANRANK(vict) = CLAN_SOLDIER;
+ 	sprintf(buf, "You have been enlisted into the ranks of the '%s' clan.\r\n", 
+ 		CLANNAME(ch));
+ 	send_to_char(buf, vict);
+ 
+ 	sprintf(buf, "You have enlisted '%s' into your clan.\r\n", 
+ 		GET_NAME(vict));
+ 	send_to_char(buf, ch);
+ 
+ 	SET_BIT(PRF_FLAGS(vict), PRF_CLANTALK);
+ 
+ 	/* Update number of clan members */
+ 	/* This is stored in the owners char structure */
+ 	    if (!(vict = get_char_vis(ch, clans[CLANNUM(ch)].owner)))
+ 	    {
+ 	      CREATE(cbuf, struct char_data, 1);
+               clear_char(cbuf);
+     	      if ((player_i = load_char(clans[CLANNUM(ch)].owner, &tmp_store)) > -1) 
+ 	      {
+                 store_to_char(&tmp_store, cbuf);
+                 vict = cbuf;
+               } 
+ 	      else 
+               {
+                 free(cbuf);
+   	        sprintf(buf, "Clan info: Unable to find owner of '%s' clan.", 
+ 		          clans[CLANNUM(ch)].title);
+       	        mudlog(buf, BRF, LVL_GOD, TRUE);
+                 return;
+               }
+ 	    }
+         else
+ 	  temp2 = 1;
+     
+       vict->player_specials->saved.numclanmembers++;
+ 
+ 	  /* Store player record */
+ 	  if (temp2 == 0)
+ 	  {
+             char_to_store(vict, &tmp_store);
+   	    fseek(player_fl, (player_i) * sizeof(struct char_file_u), SEEK_SET);
+     	    fwrite(&tmp_store, sizeof(struct char_file_u), 1, player_fl);
+     	    free_char(cbuf);
+ 	  }
+ 	
+ 	
+       }
+       else
+       {
+ 	send_to_char("But there is noone here by that name!\r\n", ch);
+ 	return;
+       }
+     }
+     else
+     {
+ 
+       if ((vict = get_player_vis(ch, val_arg, 0)))
+       {
+         if (CLANRANK(vict) != CLAN_APPLY)
+         {
+ 	  send_to_char("But that person isn't applying to any clan!\r\n", ch);
+ 	  return;
+       	}
+ 
+ 	if (strcasecmp(GET_NAME(vict), CLANOWNER(vict)) == 0)
+ 	  CLANRANK(vict) = CLAN_RULER;
+ 	else
+ 	  CLANRANK(vict) = CLAN_SOLDIER;
+ 
+ 	sprintf(buf, "You have forced the enlistment of '%s' into the clan '%s'.\r\n", 
+ 		GET_NAME(vict), CLANNAME(vict));
+ 	send_to_char(buf, ch);
+ 
+ 	sprintf(buf, "You have been enlisted into the clan '%s'.\r\n", 
+ 		CLANNAME(vict));
+ 	send_to_char(buf, vict);
+ 
+ 	/* Update number of clan members */
+ 	/* This is stored in the owners char structure */
+ 	    if (!(vict = get_char_vis(ch, clans[CLANNUM(ch)].owner)))
+ 	    {
+ 	      CREATE(cbuf, struct char_data, 1);
+               clear_char(cbuf);
+     	      if ((player_i = load_char(clans[CLANNUM(ch)].owner, &tmp_store)) > -1) 
+ 	      {
+                 store_to_char(&tmp_store, cbuf);
+                 vict = cbuf;
+               } 
+ 	      else 
+               {
+                 free(cbuf);
+   	        sprintf(buf, "Clan info: Unable to find owner of '%s' clan.", 
+ 		          clans[CLANNUM(ch)].title);
+       	        mudlog(buf, BRF, LVL_GOD, TRUE);
+                 return;
+               }
+ 	    }
+         else
+ 	  temp2 = 1;
+     
+       vict->player_specials->saved.numclanmembers++;
+ 
+ 	  /* Store player record */
+ 	  if (temp2 == 0)
+ 	  {
+             char_to_store(vict, &tmp_store);
+   	    fseek(player_fl, (player_i) * sizeof(struct char_file_u), SEEK_SET);
+     	    fwrite(&tmp_store, sizeof(struct char_file_u), 1, player_fl);
+     	    free_char(cbuf);
+ 	  }
+       }
+       else
+       {
+         send_to_char("Unable to find a character of that name.\r\n", ch);
+         return;
+       }
+ 
+     }
+   }
+ 
+   if (strcasecmp(subbcmd, "promote") == 0)
+   {
+     /* Clan promotions */
+     if (CLANRANK(ch) < CLAN_CAPTAIN)
+     {
+       send_to_char("You have insufficent rank to do that.\r\n", ch);
+       return;
+     }
+ 
+     if ((vict = get_player_vis(ch, val_arg, 0)))
+     {
+       if (CLANRANK(vict) > CLANRANK(ch))
+       {
+ 	send_to_char("You can't promote someone who ranks higher than you!\r\n", ch);
+ 	return;
+       }
+   
+       if ((CLANRANK(vict) < CLAN_SOLDIER) || (CLANNUM(vict) != CLANNUM(ch)))
+       {
+ 	send_to_char("You can't promote someone who doesn't belong to your clan!\r\n", ch);
+ 	return;
+       }
+ 
+       if (CLANRANK(vict) == CLAN_RULER)
+       {
+ 	send_to_char("You can't promote this person any higher in rank!\r\n", ch);
+ 	return;
+       }
+ 
+       CLANRANK(vict)++;
+       sprintf(buf, "%sYou have been promoted to ", CCRED(vict, C_NRM));
+       if (CLANRANK(vict) == CLAN_SARGEANT)
+         strcat(buf, SARGEANTTITLE(vict));
+       if (CLANRANK(vict) == CLAN_CAPTAIN) strcat(buf, CAPTAINTITLE(vict));
+       if (CLANRANK(vict) == CLAN_RULER) strcat(buf, RULERTITLE(vict));
+ 
+       sprintf(buf, "%s in your clan.%s\r\n", buf, CCNRM(ch, C_NRM));
+       send_to_char(buf, vict);
+ 
+       sprintf(buf, "%sYou have promoted '%s' to the rank of ", 
+ 		CCRED(vict, C_NRM), GET_NAME(vict));
+       if (CLANRANK(vict) == CLAN_SARGEANT) strcat(buf, SARGEANTTITLE(vict));
+       if (CLANRANK(vict) == CLAN_CAPTAIN) strcat(buf, CAPTAINTITLE(vict));
+       if (CLANRANK(vict) == CLAN_RULER) strcat(buf, RULERTITLE(vict));
+ 
+       sprintf(buf, "%s in your clan.%s\r\n", buf, CCNRM(ch, C_NRM));
+       send_to_char(buf, ch);
+     }
+     else
+     {
+       send_to_char("Promote who?!\r\n", ch);
+       return;
+     }
+ 
+   }
+ 
+   if (strcasecmp(subbcmd, "demote") == 0)
+   {
+     /* Clan demotions */
+     if (CLANRANK(ch) == 0)
+     {
+       send_to_char("But you don't belong to any clan!\r\n", ch);
+       return;
+     }
+ 
+     if (CLANRANK(ch) < CLAN_CAPTAIN)
+     {
+       send_to_char("You have insufficent rank to do that.\r\n", ch);
+       return;
+     }
+ 
+     if ((vict = get_player_vis(ch, val_arg, 0)))
+     {
+       if (CLANRANK(vict) > CLANRANK(ch))
+       {
+ 	send_to_char("You can't demote someone who ranks higher than you!\r\n", ch);
+ 	return;
+       }
+   
+       if ((CLANRANK(vict) < CLAN_SOLDIER) || (CLANNUM(vict) != CLANNUM(ch)))
+       {
+ 	send_to_char("You can't demote someone who doesn't belong to your clan!\r\n", ch);
+ 	return;
+       }
+ 
+       if (CLANRANK(vict) == CLAN_SOLDIER)
+       {
+ 	send_to_char("You can't demote this person any lower! Try clan boot <person>!\r\n", ch);
+ 	return;
+       }
+ 
+       if (strcasecmp(GET_NAME(vict), CLANOWNER(vict)) == 0)
+       {
+ 	send_to_char("You can't demote the clan owner!\r\n", ch);
+ 	return;
+       }
+ 
+       CLANRANK(vict)--;
+       sprintf(buf, "%sYou have been demoted to ", CCRED(vict, C_NRM));
+       if (CLANRANK(vict) == CLAN_SOLDIER) strcat(buf, SOLDIERTITLE(vict));
+       if (CLANRANK(vict) == CLAN_SARGEANT) strcat(buf, SARGEANTTITLE(vict));
+       if (CLANRANK(vict) == CLAN_CAPTAIN) strcat(buf, CAPTAINTITLE(vict));
+ 
+       sprintf(buf, "%s in your clan.%s\r\n", buf, CCNRM(ch, C_NRM));
+       send_to_char(buf, vict);
+ 
+       sprintf(buf, "%sYou have demoted '%s' to the rank of ", 
+ 		CCRED(vict, C_NRM), GET_NAME(vict));
+       if (CLANRANK(vict) == CLAN_SOLDIER) strcat(buf, SOLDIERTITLE(vict));
+       if (CLANRANK(vict) == CLAN_CAPTAIN) strcat(buf, CAPTAINTITLE(vict));
+       if (CLANRANK(vict) == CLAN_SARGEANT) strcat(buf, SARGEANTTITLE(vict));
+ 
+       sprintf(buf, "%s in your clan.%s\r\n", buf, CCNRM(ch, C_NRM));
+       send_to_char(buf, ch);
+     }
+     else
+     {
+       send_to_char("Demote who?!\r\n", ch);
+       return;
+     }
+ 
+   }
+ 
+   if (strcasecmp(subbcmd, "who") == 0)
+   {
+     /* List all clan members online, along with their clan rank */
+     if ((CLANNUM(ch) == 0) && (CLANRANK(ch) == 0))
+     {
+       send_to_char("But you don't belong to any clan!\r\n", ch);
+       return;
+     }
+ 
+     sprintf(buf, "Members of the clan '%s' currently online:\r\n", CLANNAME(ch));
+     send_to_char(buf, ch);
+ 
+     for (pt = descriptor_list; pt; pt = pt->next)
+       if (!pt->connected && pt->character && 
+           pt->character->player_specials->saved.clannum == CLANNUM(ch))
+ 	{
+           sprintf(buf, "%s[%2d %s ",  
+               (GET_LEVEL(pt->character) >= LVL_IMMORT ? CCYEL(ch, C_SPR) : ""),
+               GET_LEVEL(pt->character), CLASS_ABBR(pt->character));
+ 	  if (CLANRANK(pt->character) == CLAN_APPLY) sprintf(buf, "%s%-10s", buf, "--");
+ 	  if (CLANRANK(pt->character) == CLAN_SOLDIER) 
+ 		sprintf(buf, "%s%-10s", buf, SOLDIERTITLE(pt->character)); 
+ 	  if (CLANRANK(pt->character) == CLAN_SARGEANT) 
+ 		sprintf(buf, "%s%-10s", buf, SARGEANTTITLE(pt->character)); 
+ 	  if (CLANRANK(pt->character) == CLAN_CAPTAIN) 
+ 		sprintf(buf, "%s%-10s", buf, CAPTAINTITLE(pt->character)); 
+ 	  if (CLANRANK(pt->character) == CLAN_RULER) 
+ 		sprintf(buf, "%s%-10s", buf, RULERTITLE(pt->character)); 
+ 	  sprintf(buf, "%s] %s %s%s\r\n", buf, GET_NAME(pt->character), GET_TITLE(pt->character), CCNRM(ch, C_NRM));
+ 	  send_to_char(buf, ch);
+         }
+   }
+ 
+   if (strcasecmp(subbcmd, "say") == 0)
+   {
+     /* Clan say */
+     if (CLANRANK(ch) == 0)
+     {
+       send_to_char("But you don't belong to any clan!\r\n", ch);
+       return;
+     }
+ 
+     if (!PRF_FLAGGED(ch, PRF_CLANTALK))
+     {
+       send_to_char("Try turning your clan talk channel on first, dork!\r\n", ch);
+       return;
+     }    
+ 
+     for (pt = descriptor_list; pt; pt = pt->next)
+       if (!pt->connected && pt->character && 
+           pt->character->player_specials->saved.clannum == CLANNUM(ch) &&
+ 	  pt->character != ch && PRF_FLAGGED(ch, PRF_CLANTALK))
+ 	{
+ 	  sprintf(buf, "%s%s says to the clan, '%s'%s\r\n", CCRED(pt->character, C_NRM),
+ 			GET_NAME(ch), val_arg, CCNRM(pt->character, C_NRM));
+ 	  send_to_char(buf, pt->character);
+         }
+     sprintf(buf, "%sYou say to the clan, '%s'%s\r\n", CCRED(ch, C_NRM),
+ 		val_arg, CCNRM(ch, C_NRM));
+     send_to_char(buf, ch);
+ 
+   }
+ 
+   if (strcasecmp(subbcmd, "channel") == 0)
+   {
+     if (PRF_FLAGGED(ch, PRF_CLANTALK))
+     {
+       TOGGLE_BIT(PRF_FLAGS(ch), PRF_CLANTALK);
+       send_to_char("Clan talk channel turned off.\r\n", ch);
+     }
+     else
+     {
+       TOGGLE_BIT(PRF_FLAGS(ch), PRF_CLANTALK);
+       send_to_char("Clan talk channel turned on.\r\n", ch);
+     }
+   }
+ 
+ };
+ 
+ ACMD(do_clansay)
+ {
+     struct descriptor_data *pt;
+   
+     /* Clan say */
+     if (CLANRANK(ch) == 0)
+     {
+       send_to_char("But you don't belong to any clan!\r\n", ch);
+       return;
+     }
+ 
+     if (!PRF_FLAGGED(ch, PRF_CLANTALK))
+     {
+       send_to_char("Try turning your clan talk channel on first, dork!\r\n", ch);
+       return;
+     }    
+ 
+     for (pt = descriptor_list; pt; pt = pt->next)
+       if (!pt->connected && pt->character && 
+           pt->character->player_specials->saved.clannum == CLANNUM(ch) &&
+ 	  pt->character != ch && PRF_FLAGGED(ch, PRF_CLANTALK))
+ 	{
+ 	  sprintf(buf, "%s%s says to the clan, '%s'%s\r\n", CCRED(pt->character, C_NRM),
+ 			GET_NAME(ch), argument, CCNRM(pt->character, C_NRM));
+ 	  send_to_char(buf, pt->character);
+         }
+     sprintf(buf, "%sYou say to the clan, '%s'%s\r\n", CCRED(ch, C_NRM),
+ 		argument, CCNRM(ch, C_NRM));
+     send_to_char(buf, ch);
+ 
+ };
diff -c -P -x *.o orig-src/clan.h src/clan.h
*** orig-src/clan.h	Thu Jan  1 10:00:00 1970
--- src/clan.h	Mon Feb 24 16:44:13 1997
***************
*** 0 ****
--- 1,99 ----
+ /* *************************************************************************
+ *   File: clan.h				     Addition to CircleMUD *
+ *  Usage: Contains structure definitions for clan.c                        *
+ *                                                                          *
+ *  Written by Daniel Muller                                                *
+ *                                                                          *
+ ************************************************************************* */
+ 
+ struct clan_info {
+    char *title;
+    int colour;
+    char *owner;
+    char *description;
+    char *old_description;
+    char *ranksoldiertitle;
+    char *ranksargeanttitle;
+    char *rankcaptaintitle;
+    char *rankrulertitle;
+    int clanroom;
+    int clangold;
+    int nummembers;
+    int number;
+    int status;
+ };
+ 
+ struct clan_colours {
+   char *colour_string;
+ };
+ 
+ struct clan_editing {
+   int mode;		/* What edit mode are we in? */
+   struct descriptor_data *desc; /* Who owns this clan node? */
+   int clan;
+ };
+ 
+ #define CLAN_DEBUG_UNKNOWN		0
+ #define CLAN_DEBUG_ALL			1
+ #define CLAN_DEBUG_CREF			2
+ #define CLAN_DEBUG_NODE			3
+ #define CLAN_DEBUG_VAR			4
+ 
+ #define CLEAN_NODE	0
+ #define CLEAN_ALL	1
+ 
+ #define CON_CLAN_EDIT	17
+ 
+ #define CLAN_EDIT_CONFIRM_SAVE	0
+ #define CLAN_EDIT_MAIN_MENU	1
+ #define CLAN_EDIT_NAME		2
+ #define CLAN_EDIT_NUMBER	3
+ #define CLAN_EDIT_GOLD		4
+ #define CLAN_EDIT_OWNER		5
+ #define CLAN_EDIT_DESCRIPTION	6
+ #define CLAN_EDIT_CLANROOM	7
+ #define CLAN_EDIT_COLOUR	8
+ #define CLAN_EDIT_RANK_MENU	9
+ #define CLAN_EDIT_SELECT_COLOUR 10
+ #define CLAN_EDIT_SOLDIER	11
+ #define CLAN_EDIT_SARGEANT	12
+ #define CLAN_EDIT_CAPTAIN	13
+ #define CLAN_EDIT_RULER		14
+ #define CLAN_EDIT_DESCRIPTION_FINISHED		15
+ #define CLAN_EDIT_CONFIRM_DELETE		16
+ 
+ #define CLAN_EDIT_MODE(num)	(clan_edit[(num)].mode)
+ #define CLAN_EDIT_DESC(num)	(clan_edit[(num)].desc)
+ #define CLAN_EDIT_CLAN(num)	(clan_edit[(num)].clan)
+ 
+ #define CLANSTATUS(cnum)	(clan_index[(cnum)].status)
+ #define CLAN_DELETE		2
+ #define CLAN_NEW		1
+ #define CLAN_OLD		0
+ 
+ #define PLAYERCLAN(ch)		((ch)->player_specials->saved.clannum)
+ #define PLAYERCLANNUM(ch)	(cross_reference[(ch)->player_specials->saved.clannum])
+ #define	CLANNUM(clan)		((clan).number)
+ #define	CLANNAME(clan)		((clan).title)
+ #define	CLANRANK(ch)		((ch)->player_specials->saved.clanrank)
+ #define CLANPLAYERS(clan) 	((clan).nummembers)	
+ #define CLANOWNER(clan)   	((clan).owner)
+ #define CLANGOLD(clan)		((clan).clangold)
+ #define CLANROOM(clan)		((clan).clanroom)
+ #define CLANDESC(clan)		((clan).description)
+ #define CLANCOLOUR(num)	(clan_colour[clan_index[(num)].colour].colour_string)
+ #define CLANCOLOR(num)		(clan_index[(num)].colour)
+ 
+ #define SOLDIERTITLE(clan)	((clan).ranksoldiertitle)
+ #define SARGEANTTITLE(clan)	((clan).ranksargeanttitle)
+ #define CAPTAINTITLE(clan)	((clan).rankcaptaintitle)
+ #define RULERTITLE(clan)	((clan).rankrulertitle)
+ 
+ #define CLAN_WHITE		0
+ #define CLAN_GREEN		1
+ #define CLAN_RED		2
+ #define CLAN_BLUE		3
+ #define CLAN_MAGENTA		4
+ #define CLAN_YELLOW		5
+ #define CLAN_CYAN		6
+ #define CLAN_NORMAL		7
diff -c -P -x *.o orig-src/comm.c src/comm.c
*** orig-src/comm.c	Mon Feb 24 23:00:33 1997
--- src/comm.c	Sun Feb 23 04:58:21 1997
***************
*** 32,37 ****
--- 32,38 ----
  #include "handler.h"
  #include "db.h"
  #include "house.h"
+ #include "clan.h"
  
  #ifdef HAVE_ARPA_TELNET_H
  #include <arpa/telnet.h>
***************
*** 43,48 ****
--- 44,52 ----
  #define INVALID_SOCKET -1
  #endif
  
+ #define YES	1
+ #define NO	0
+ 
  /* externs */
  extern int restrict;
  extern int mini_mud;
***************
*** 53,58 ****
--- 57,65 ----
  extern int MAX_PLAYERS;
  extern int MAX_DESCRIPTORS_AVAILABLE;
  
+ extern void clan_save(int system, struct char_data *ch);
+ extern void cleanup_clan_edit(struct descriptor_data *d, int method);
+ 
  extern struct room_data *world;	/* In db.c */
  extern int top_of_world;	/* In db.c */
  extern struct time_info_data time_info;		/* In db.c */
***************
*** 689,694 ****
--- 696,702 ----
        mins_since_crashsave = 0;
        Crash_save_all();
        House_save_all();
+       clan_save(YES, NULL); /* Fido - Crash save and auto save clans */
      }
    }
    if (!(pulse % (5 * 60 * PASSES_PER_SEC)))	/* 5 minutes */
***************
*** 1363,1368 ****
--- 1371,1385 ----
      SEND_TO_Q("Your victim is no longer among us.\r\n", d->snoop_by);
      d->snoop_by->snooping = NULL;
    }
+ 
+   /* Clean up clan edit if necessary */
+   switch (d->connected)
+   {
+     case CON_CLAN_EDIT:
+       cleanup_clan_edit(d, CLEAN_ALL);
+       break;
+   }
+ 
    if (d->character) {
      target_idnum = GET_IDNUM(d->character);
      if (d->connected == CON_PLAYING) {
diff -c -P -x *.o orig-src/config.c src/config.c
*** orig-src/config.c	Mon Feb 24 23:00:33 1997
--- src/config.c	Sat Feb  8 13:35:03 1997
***************
*** 52,57 ****
--- 52,61 ----
   * PK Mud, just set pk_allowed to YES - and anything goes.
   */
  int pk_allowed = NO;
+ int summon_allowed = NO;
+ int charm_allowed = NO;
+ int sleep_allowed = NO;
+ int roomaffect_allowed = NO;
  
  /* is playerthieving allowed? */
  int pt_allowed = NO;
***************
*** 71,77 ****
  int max_pc_corpse_time = 10;
  
  /* should items in death traps automatically be junked? */
! int dts_are_dumps = YES;
  
  /* "okay" etc. */
  char *OK = "Okay.\r\n";
--- 75,81 ----
  int max_pc_corpse_time = 10;
  
  /* should items in death traps automatically be junked? */
! int dts_are_dumps = NO;
  
  /* "okay" etc. */
  char *OK = "Okay.\r\n";
diff -c -P -x *.o orig-src/constants.c src/constants.c
*** orig-src/constants.c	Mon Feb 24 23:00:33 1997
--- src/constants.c	Sun Feb 23 03:13:00 1997
***************
*** 230,235 ****
--- 230,236 ----
    "Changing PW 3",
    "Self-Delete 1",
    "Self-Delete 2",
+   "Editing Clans",
    "\n"
  };
  
diff -c -P -x *.o orig-src/db.c src/db.c
*** orig-src/db.c	Mon Feb 24 23:00:33 1997
--- src/db.c	Sun Feb 23 03:00:14 1997
***************
*** 14,19 ****
--- 14,20 ----
  #include "sysdep.h"
  
  
+ #include "clan.h"
  #include "structs.h"
  #include "utils.h"
  #include "db.h"
***************
*** 28,33 ****
--- 29,37 ----
  *  declarations of most of the 'global' variables                         *
  ************************************************************************ */
  
+ struct clan_info *clan_index = NULL; /* (FIDO) Clan global */
+ int clan_top = 0;			/* (FIDO) Top of clan struct */
+ 
  struct room_data *world = NULL;	/* array of rooms		 */
  int top_of_world = 0;		/* ref to top element of world	 */
  
***************
*** 109,114 ****
--- 113,119 ----
  void clear_char(struct char_data * ch);
  
  /* external functions */
+ extern void parse_clan(FILE *fl, int virtual_nr);
  extern struct descriptor_data *descriptor_list;
  void load_messages(void);
  void weather_and_time(int mode);
***************
*** 220,225 ****
--- 225,233 ----
    log("Loading objs and generating index.");
    index_boot(DB_BOOT_OBJ);
  
+   log("Loading clans and generating index.");
+   index_boot(DB_BOOT_CLAN);
+ 
    log("Renumbering zone table.");
    renum_zone_table();
  
***************
*** 462,467 ****
--- 470,478 ----
    case DB_BOOT_HLP:
      prefix = HLP_PREFIX;
      break;
+   case DB_BOOT_CLAN:
+     prefix = CLAN_PREFIX;
+     break;
    default:
      log("SYSERR: Unknown subcommand to index_boot!");
      exit(1);
***************
*** 528,533 ****
--- 539,548 ----
    case DB_BOOT_HLP:
      CREATE(help_table, struct help_index_element, rec_count * 2);
      break;
+   case DB_BOOT_CLAN:
+     CREATE(clan_index, struct clan_info, rec_count + 10);
+     clan_top = rec_count - 1;
+     break;
    }
  
    rewind(index);
***************
*** 542,547 ****
--- 557,563 ----
      case DB_BOOT_WLD:
      case DB_BOOT_OBJ:
      case DB_BOOT_MOB:
+     case DB_BOOT_CLAN:
        discrete_load(db_file, mode);
        break;
      case DB_BOOT_ZON:
***************
*** 573,579 ****
    int nr = -1, last = 0;
    char line[256];
  
!   char *modes[] = {"world", "mob", "obj"};
  
    for (;;) {
      /*
--- 589,595 ----
    int nr = -1, last = 0;
    char line[256];
  
!   char *modes[] = {"world", "mob", "obj", "clan"};
  
    for (;;) {
      /*
***************
*** 606,611 ****
--- 622,630 ----
  	  break;
  	case DB_BOOT_OBJ:
  	  strcpy(line, parse_object(fl, nr));
+ 	  break;
+ 	case DB_BOOT_CLAN:
+ 	  parse_clan(fl, nr);
  	  break;
  	}
      } else {
diff -c -P -x *.o orig-src/db.c.save src/db.c.save
*** orig-src/db.c.save	Thu Jan  1 10:00:00 1970
--- src/db.c.save	Sat Feb 22 15:51:46 1997
***************
*** 0 ****
--- 1,2425 ----
+ /* ************************************************************************
+ *   File: db.c                                          Part of CircleMUD *
+ *  Usage: Loading/saving chars, booting/resetting world, internal funcs   *
+ *                                                                         *
+ *  All rights reserved.  See license.doc for complete information.        *
+ *                                                                         *
+ *  Copyright (C) 1993, 94 by the Trustees of the Johns Hopkins University *
+ *  CircleMUD is based on DikuMUD, Copyright (C) 1990, 1991.               *
+ ************************************************************************ */
+ 
+ #define __DB_C__
+ 
+ #include "conf.h"
+ #include "sysdep.h"
+ 
+ 
+ #include "structs.h"
+ #include "utils.h"
+ #include "db.h"
+ #include "comm.h"
+ #include "handler.h"
+ #include "spells.h"
+ #include "mail.h"
+ #include "interpreter.h"
+ #include "house.h"
+ 
+ /**************************************************************************
+ *  declarations of most of the 'global' variables                         *
+ ************************************************************************ */
+ 
+ struct room_data *world = NULL;	/* array of rooms		 */
+ int top_of_world = 0;		/* ref to top element of world	 */
+ 
+ struct char_data *character_list = NULL;	/* global linked list of
+ 						 * chars	 */
+ struct index_data *mob_index;	/* index table for mobile file	 */
+ struct char_data *mob_proto;	/* prototypes for mobs		 */
+ int top_of_mobt = 0;		/* top of mobile index table	 */
+ 
+ struct obj_data *object_list = NULL;	/* global linked list of objs	 */
+ struct index_data *obj_index;	/* index table for object file	 */
+ struct obj_data *obj_proto;	/* prototypes for objs		 */
+ int top_of_objt = 0;		/* top of object index table	 */
+ 
+ struct zone_data *zone_table;	/* zone table			 */
+ int top_of_zone_table = 0;	/* top element of zone tab	 */
+ struct message_list fight_messages[MAX_MESSAGES];	/* fighting messages	 */
+ 
+ struct player_index_element *player_table = NULL;	/* index to plr file	 */
+ FILE *player_fl = NULL;		/* file desc of player file	 */
+ int top_of_p_table = 0;		/* ref to top of table		 */
+ int top_of_p_file = 0;		/* ref of size of p file	 */
+ long top_idnum = 0;		/* highest idnum in use		 */
+ 
+ int no_mail = 0;		/* mail disabled?		 */
+ int mini_mud = 0;		/* mini-mud mode?		 */
+ int no_rent_check = 0;		/* skip rent check on boot?	 */
+ time_t boot_time = 0;		/* time of mud boot		 */
+ int restrict = 0;		/* level of game restriction	 */
+ sh_int r_mortal_start_room;	/* rnum of mortal start room	 */
+ sh_int r_immort_start_room;	/* rnum of immort start room	 */
+ sh_int r_frozen_start_room;	/* rnum of frozen start room	 */
+ 
+ char *credits = NULL;		/* game credits			 */
+ char *news = NULL;		/* mud news			 */
+ char *motd = NULL;		/* message of the day - mortals */
+ char *imotd = NULL;		/* message of the day - immorts */
+ char *help = NULL;		/* help screen			 */
+ char *info = NULL;		/* info page			 */
+ char *wizlist = NULL;		/* list of higher gods		 */
+ char *immlist = NULL;		/* list of peon gods		 */
+ char *background = NULL;	/* background story		 */
+ char *handbook = NULL;		/* handbook for new immortals	 */
+ char *policies = NULL;		/* policies page		 */
+ 
+ struct help_index_element *help_table = 0;	/* the help table	 */
+ int top_of_helpt = 0;		/* top of help index table	 */
+ 
+ struct time_info_data time_info;/* the infomation about the time    */
+ struct weather_data weather_info;	/* the infomation about the weather */
+ struct player_special_data dummy_mob;	/* dummy spec area for mobs	 */
+ struct reset_q_type reset_q;	/* queue of zones to be reset	 */
+ 
+ /* local functions */
+ void setup_dir(FILE * fl, int room, int dir);
+ void index_boot(int mode);
+ void discrete_load(FILE * fl, int mode);
+ void parse_room(FILE * fl, int virtual_nr);
+ void parse_mobile(FILE * mob_f, int nr);
+ char *parse_object(FILE * obj_f, int nr);
+ void load_zones(FILE * fl, char *zonename);
+ void load_help(FILE *fl);
+ void assign_mobiles(void);
+ void assign_objects(void);
+ void assign_rooms(void);
+ void assign_the_shopkeepers(void);
+ void build_player_index(void);
+ void char_to_store(struct char_data * ch, struct char_file_u * st);
+ void store_to_char(struct char_file_u * st, struct char_data * ch);
+ int is_empty(int zone_nr);
+ void reset_zone(int zone);
+ int file_to_string(char *name, char *buf);
+ int file_to_string_alloc(char *name, char **buf);
+ void check_start_rooms(void);
+ void renum_world(void);
+ void renum_zone_table(void);
+ void log_zone_error(int zone, int cmd_no, char *message);
+ void reset_time(void);
+ void clear_char(struct char_data * ch);
+ 
+ /* external functions */
+ extern struct descriptor_data *descriptor_list;
+ void load_messages(void);
+ void weather_and_time(int mode);
+ void mag_assign_spells(void);
+ void boot_social_messages(void);
+ void update_obj_file(void);	/* In objsave.c */
+ void sort_commands(void);
+ void sort_spells(void);
+ void load_banned(void);
+ void Read_Invalid_List(void);
+ void boot_the_shops(FILE * shop_f, char *filename, int rec_count);
+ int hsort(const void *a, const void *b);
+ 
+ /* external vars */
+ extern int no_specials;
+ 
+ #define READ_SIZE 256
+ 
+ /*************************************************************************
+ *  routines for booting the system                                       *
+ *********************************************************************** */
+ 
+ /* this is necessary for the autowiz system */
+ void reboot_wizlists(void)
+ {
+   file_to_string_alloc(WIZLIST_FILE, &wizlist);
+   file_to_string_alloc(IMMLIST_FILE, &immlist);
+ }
+ 
+ 
+ ACMD(do_reboot)
+ {
+   int i;
+ 
+   one_argument(argument, arg);
+ 
+   if (!str_cmp(arg, "all") || *arg == '*') {
+     file_to_string_alloc(WIZLIST_FILE, &wizlist);
+     file_to_string_alloc(IMMLIST_FILE, &immlist);
+     file_to_string_alloc(NEWS_FILE, &news);
+     file_to_string_alloc(CREDITS_FILE, &credits);
+     file_to_string_alloc(MOTD_FILE, &motd);
+     file_to_string_alloc(IMOTD_FILE, &imotd);
+     file_to_string_alloc(HELP_PAGE_FILE, &help);
+     file_to_string_alloc(INFO_FILE, &info);
+     file_to_string_alloc(POLICIES_FILE, &policies);
+     file_to_string_alloc(HANDBOOK_FILE, &handbook);
+     file_to_string_alloc(BACKGROUND_FILE, &background);
+   } else if (!str_cmp(arg, "wizlist"))
+     file_to_string_alloc(WIZLIST_FILE, &wizlist);
+   else if (!str_cmp(arg, "immlist"))
+     file_to_string_alloc(IMMLIST_FILE, &immlist);
+   else if (!str_cmp(arg, "news"))
+     file_to_string_alloc(NEWS_FILE, &news);
+   else if (!str_cmp(arg, "credits"))
+     file_to_string_alloc(CREDITS_FILE, &credits);
+   else if (!str_cmp(arg, "motd"))
+     file_to_string_alloc(MOTD_FILE, &motd);
+   else if (!str_cmp(arg, "imotd"))
+     file_to_string_alloc(IMOTD_FILE, &imotd);
+   else if (!str_cmp(arg, "help"))
+     file_to_string_alloc(HELP_PAGE_FILE, &help);
+   else if (!str_cmp(arg, "info"))
+     file_to_string_alloc(INFO_FILE, &info);
+   else if (!str_cmp(arg, "policy"))
+     file_to_string_alloc(POLICIES_FILE, &policies);
+   else if (!str_cmp(arg, "handbook"))
+     file_to_string_alloc(HANDBOOK_FILE, &handbook);
+   else if (!str_cmp(arg, "background"))
+     file_to_string_alloc(BACKGROUND_FILE, &background);
+   else if (!str_cmp(arg, "xhelp")) {
+     if (help_table) {
+       for (i = 0; i <= top_of_helpt; i++) {
+         if (help_table[i].keyword)
+ 	  free(help_table[i].keyword);
+         if (help_table[i].entry && !help_table[i].duplicate)
+ 	  free(help_table[i].entry);
+       }
+       free(help_table);
+     }
+     top_of_helpt = 0;
+     index_boot(DB_BOOT_HLP);
+   } else {
+     send_to_char("Unknown reload option.\r\n", ch);
+     return;
+   }
+ 
+   send_to_char(OK, ch);
+ }
+ 
+ 
+ void boot_world(void)
+ {
+   log("Loading zone table.");
+   index_boot(DB_BOOT_ZON);
+ 
+   log("Loading rooms.");
+   index_boot(DB_BOOT_WLD);
+ 
+   log("Renumbering rooms.");
+   renum_world();
+ 
+   log("Checking start rooms.");
+   check_start_rooms();
+ 
+   log("Loading mobs and generating index.");
+   index_boot(DB_BOOT_MOB);
+ 
+   log("Loading objs and generating index.");
+   index_boot(DB_BOOT_OBJ);
+ 
+   log("Renumbering zone table.");
+   renum_zone_table();
+ 
+   if (!no_specials) {
+     log("Loading shops.");
+     index_boot(DB_BOOT_SHP);
+   }
+ }
+ 
+   
+ 
+ /* body of the booting system */
+ void boot_db(void)
+ {
+   int i;
+ 
+   log("Boot db -- BEGIN.");
+ 
+   log("Resetting the game time:");
+   reset_time();
+ 
+   log("Reading news, credits, help, bground, info & motds.");
+   file_to_string_alloc(NEWS_FILE, &news);
+   file_to_string_alloc(CREDITS_FILE, &credits);
+   file_to_string_alloc(MOTD_FILE, &motd);
+   file_to_string_alloc(IMOTD_FILE, &imotd);
+   file_to_string_alloc(HELP_PAGE_FILE, &help);
+   file_to_string_alloc(INFO_FILE, &info);
+   file_to_string_alloc(WIZLIST_FILE, &wizlist);
+   file_to_string_alloc(IMMLIST_FILE, &immlist);
+   file_to_string_alloc(POLICIES_FILE, &policies);
+   file_to_string_alloc(HANDBOOK_FILE, &handbook);
+   file_to_string_alloc(BACKGROUND_FILE, &background);
+ 
+ 
+   boot_world();
+ 
+   log("Loading help entries.");
+   index_boot(DB_BOOT_HLP);
+ 
+   log("Generating player index.");
+   build_player_index();
+ 
+   log("Loading fight messages.");
+   load_messages();
+ 
+   log("Loading social messages.");
+   boot_social_messages();
+ 
+   log("Assigning function pointers:");
+ 
+   if (!no_specials) {
+     log("   Mobiles.");
+     assign_mobiles();
+     log("   Shopkeepers.");
+     assign_the_shopkeepers();
+     log("   Objects.");
+     assign_objects();
+     log("   Rooms.");
+     assign_rooms();
+   }
+   log("   Spells.");
+   mag_assign_spells();
+ 
+   log("Assigning spell and skill levels.");
+   init_spell_levels();
+ 
+   log("Sorting command list and spells.");
+   sort_commands();
+   sort_spells();
+ 
+   log("Booting mail system.");
+   if (!scan_file()) {
+     log("    Mail boot failed -- Mail system disabled");
+     no_mail = 1;
+   }
+   log("Reading banned site and invalid-name list.");
+   load_banned();
+   Read_Invalid_List();
+ 
+   if (!no_rent_check) {
+     log("Deleting timed-out crash and rent files:");
+     update_obj_file();
+     log("Done.");
+   }
+   for (i = 0; i <= top_of_zone_table; i++) {
+     sprintf(buf2, "Resetting %s (rooms %d-%d).",
+ 	    zone_table[i].name, (i ? (zone_table[i - 1].top + 1) : 0),
+ 	    zone_table[i].top);
+     log(buf2);
+     reset_zone(i);
+   }
+ 
+   reset_q.head = reset_q.tail = NULL;
+ 
+   if (!mini_mud) {
+     log("Booting houses.");
+     House_boot();
+   }
+   boot_time = time(0);
+ 
+   log("Boot db -- DONE.");
+ }
+ 
+ 
+ /* reset the time in the game from file */
+ void reset_time(void)
+ {
+   long beginning_of_time = 650336715;
+   struct time_info_data mud_time_passed(time_t t2, time_t t1);
+ 
+   time_info = mud_time_passed(time(0), beginning_of_time);
+ 
+   if (time_info.hours <= 4)
+     weather_info.sunlight = SUN_DARK;
+   else if (time_info.hours == 5)
+     weather_info.sunlight = SUN_RISE;
+   else if (time_info.hours <= 20)
+     weather_info.sunlight = SUN_LIGHT;
+   else if (time_info.hours == 21)
+     weather_info.sunlight = SUN_SET;
+   else
+     weather_info.sunlight = SUN_DARK;
+ 
+   sprintf(buf, "   Current Gametime: %dH %dD %dM %dY.", time_info.hours,
+ 	  time_info.day, time_info.month, time_info.year);
+   log(buf);
+ 
+   weather_info.pressure = 960;
+   if ((time_info.month >= 7) && (time_info.month <= 12))
+     weather_info.pressure += dice(1, 50);
+   else
+     weather_info.pressure += dice(1, 80);
+ 
+   weather_info.change = 0;
+ 
+   if (weather_info.pressure <= 980)
+     weather_info.sky = SKY_LIGHTNING;
+   else if (weather_info.pressure <= 1000)
+     weather_info.sky = SKY_RAINING;
+   else if (weather_info.pressure <= 1020)
+     weather_info.sky = SKY_CLOUDY;
+   else
+     weather_info.sky = SKY_CLOUDLESS;
+ }
+ 
+ 
+ 
+ /* generate index table for the player file */
+ void build_player_index(void)
+ {
+   int nr = -1, i;
+   long size, recs;
+   struct char_file_u dummy;
+ 
+   if (!(player_fl = fopen(PLAYER_FILE, "r+b"))) {
+     if (errno != ENOENT) {
+       perror("fatal error opening playerfile");
+       exit(1);
+     } else {
+       log("No playerfile.  Creating a new one.");
+       touch(PLAYER_FILE);
+       if (!(player_fl = fopen(PLAYER_FILE, "r+b"))) {
+ 	perror("fatal error opening playerfile");
+ 	exit(1);
+       }
+     }
+   }
+ 
+   fseek(player_fl, 0L, SEEK_END);
+   size = ftell(player_fl);
+   rewind(player_fl);
+   if (size % sizeof(struct char_file_u))
+     fprintf(stderr, "\aWARNING:  PLAYERFILE IS PROBABLY CORRUPT!\n");
+   recs = size / sizeof(struct char_file_u);
+   if (recs) {
+     sprintf(buf, "   %ld players in database.", recs);
+     log(buf);
+     CREATE(player_table, struct player_index_element, recs);
+   } else {
+     player_table = NULL;
+     top_of_p_file = top_of_p_table = -1;
+     return;
+   }
+ 
+   for (; !feof(player_fl);) {
+     fread(&dummy, sizeof(struct char_file_u), 1, player_fl);
+     if (!feof(player_fl)) {	/* new record */
+       nr++;
+       CREATE(player_table[nr].name, char, strlen(dummy.name) + 1);
+       for (i = 0;
+ 	   (*(player_table[nr].name + i) = LOWER(*(dummy.name + i))); i++);
+       player_table[nr].id = dummy.char_specials_saved.idnum;
+       top_idnum = MAX(top_idnum, dummy.char_specials_saved.idnum);
+     }
+   }
+ 
+   top_of_p_file = top_of_p_table = nr;
+ }
+ 
+ 
+ 
+ /* function to count how many hash-mark delimited records exist in a file */
+ int count_hash_records(FILE * fl)
+ {
+   char buf[128];
+   int count = 0;
+ 
+   while (fgets(buf, 128, fl))
+     if (*buf == '#')
+       count++;
+ 
+   return count;
+ }
+ 
+ 
+ 
+ void index_boot(int mode)
+ {
+   char *index_filename, *prefix;
+   FILE *index, *db_file;
+   int rec_count = 0;
+ 
+   switch (mode) {
+   case DB_BOOT_WLD:
+     prefix = WLD_PREFIX;
+     break;
+   case DB_BOOT_MOB:
+     prefix = MOB_PREFIX;
+     break;
+   case DB_BOOT_OBJ:
+     prefix = OBJ_PREFIX;
+     break;
+   case DB_BOOT_ZON:
+     prefix = ZON_PREFIX;
+     break;
+   case DB_BOOT_SHP:
+     prefix = SHP_PREFIX;
+     break;
+   case DB_BOOT_HLP:
+     prefix = HLP_PREFIX;
+     break;
+   case DB_BOOT_CLAN:
+     prefix = CLAN_PREFIX;
+   default:
+     log("SYSERR: Unknown subcommand to index_boot!");
+     exit(1);
+     break;
+   }
+ 
+   if (mini_mud)
+     index_filename = MINDEX_FILE;
+   else
+     index_filename = INDEX_FILE;
+ 
+   sprintf(buf2, "%s/%s", prefix, index_filename);
+ 
+   if (!(index = fopen(buf2, "r"))) {
+     sprintf(buf1, "Error opening index file '%s'", buf2);
+     perror(buf1);
+     exit(1);
+   }
+ 
+   /* first, count the number of records in the file so we can malloc */
+   fscanf(index, "%s\n", buf1);
+   while (*buf1 != '$') {
+     sprintf(buf2, "%s/%s", prefix, buf1);
+     if (!(db_file = fopen(buf2, "r"))) {
+       perror(buf2);
+       log("file listed in index not found");
+       exit(1);
+     } else {
+       if (mode == DB_BOOT_ZON)
+ 	rec_count++;
+       else
+ 	rec_count += count_hash_records(db_file);
+     }
+ 
+     fclose(db_file);
+     fscanf(index, "%s\n", buf1);
+   }
+ 
+   /* Exit if 0 records, unless this is shops */
+   if (!rec_count) {
+     if (mode == DB_BOOT_SHP)
+       return;
+     log("SYSERR: boot error - 0 records counted");
+     exit(1);
+   }
+ 
+   rec_count++;
+ 
+   switch (mode) {
+   case DB_BOOT_WLD:
+     CREATE(world, struct room_data, rec_count);
+     break;
+   case DB_BOOT_MOB:
+     CREATE(mob_proto, struct char_data, rec_count);
+     CREATE(mob_index, struct index_data, rec_count);
+     break;
+   case DB_BOOT_OBJ:
+     CREATE(obj_proto, struct obj_data, rec_count);
+     CREATE(obj_index, struct index_data, rec_count);
+     break;
+   case DB_BOOT_ZON:
+     CREATE(zone_table, struct zone_data, rec_count);
+     break;
+   case DB_BOOT_HLP:
+     CREATE(help_table, struct help_index_element, rec_count * 2);
+     break;
+   case DB_BOOT_CLAN:
+     CREATE(clan_index, struct clan_info, rec_count);
+     break;
+   }
+ 
+   rewind(index);
+   fscanf(index, "%s\n", buf1);
+   while (*buf1 != '$') {
+     sprintf(buf2, "%s/%s", prefix, buf1);
+     if (!(db_file = fopen(buf2, "r"))) {
+       perror(buf2);
+       exit(1);
+     }
+     switch (mode) {
+     case DB_BOOT_WLD:
+     case DB_BOOT_OBJ:
+     case DB_BOOT_MOB:
+       discrete_load(db_file, mode);
+       break;
+     case DB_BOOT_ZON:
+       load_zones(db_file, buf2);
+       break;
+     case DB_BOOT_HLP:
+       load_help(db_file);
+       break;
+     case DB_BOOT_SHP:
+       boot_the_shops(db_file, buf2, rec_count);
+       break;
+     }
+ 
+     fclose(db_file);
+     fscanf(index, "%s\n", buf1);
+   }
+ 
+   /* sort the help index */
+   if (mode == DB_BOOT_HLP) {
+     qsort(help_table, top_of_helpt, sizeof(struct help_index_element), hsort);
+     top_of_helpt--;
+   }
+ 
+ }
+ 
+ 
+ void discrete_load(FILE * fl, int mode)
+ {
+   int nr = -1, last = 0;
+   char line[256];
+ 
+   char *modes[] = {"world", "mob", "obj", "clan"};
+ 
+   for (;;) {
+     /*
+      * we have to do special processing with the obj files because they have
+      * no end-of-record marker :(
+      */
+     if (mode != DB_BOOT_OBJ || nr < 0)
+       if (!get_line(fl, line)) {
+ 	fprintf(stderr, "Format error after %s #%d\n", modes[mode], nr);
+ 	exit(1);
+       }
+     if (*line == '$')
+       return;
+ 
+     if (*line == '#') {
+       last = nr;
+       if (sscanf(line, "#%d", &nr) != 1) {
+ 	fprintf(stderr, "Format error after %s #%d\n", modes[mode], last);
+ 	exit(1);
+       }
+       if (nr >= 99999)
+ 	return;
+       else
+ 	switch (mode) {
+ 	case DB_BOOT_WLD:
+ 	  parse_room(fl, nr);
+ 	  break;
+ 	case DB_BOOT_MOB:
+ 	  parse_mobile(fl, nr);
+ 	  break;
+ 	case DB_BOOT_OBJ:
+ 	  strcpy(line, parse_object(fl, nr));
+ 	  break;
+ 	case DB_BOOT_CLAN:
+ 	  parse_clan(fl, nr);
+ 	  break;
+ 	}
+     } else {
+       fprintf(stderr, "Format error in %s file near %s #%d\n",
+ 	      modes[mode], modes[mode], nr);
+       fprintf(stderr, "Offending line: '%s'\n", line);
+       exit(1);
+     }
+   }
+ }
+ 
+ 
+ long asciiflag_conv(char *flag)
+ {
+   long flags = 0;
+   int is_number = 1;
+   register char *p;
+ 
+   for (p = flag; *p; p++) {
+     if (islower(*p))
+       flags |= 1 << (*p - 'a');
+     else if (isupper(*p))
+       flags |= 1 << (26 + (*p - 'A'));
+ 
+     if (!isdigit(*p))
+       is_number = 0;
+   }
+ 
+   if (is_number)
+     flags = atol(flag);
+ 
+   return flags;
+ }
+ 
+ 
+ /* load the rooms */
+ void parse_room(FILE * fl, int virtual_nr)
+ {
+   static int room_nr = 0, zone = 0;
+   int t[10], i;
+   char line[256], flags[128];
+   struct extra_descr_data *new_descr;
+ 
+   sprintf(buf2, "room #%d", virtual_nr);
+ 
+   if (virtual_nr <= (zone ? zone_table[zone - 1].top : -1)) {
+     fprintf(stderr, "Room #%d is below zone %d.\n", virtual_nr, zone);
+     exit(1);
+   }
+   while (virtual_nr > zone_table[zone].top)
+     if (++zone > top_of_zone_table) {
+       fprintf(stderr, "Room %d is outside of any zone.\n", virtual_nr);
+       exit(1);
+     }
+   world[room_nr].zone = zone;
+   world[room_nr].number = virtual_nr;
+   world[room_nr].name = fread_string(fl, buf2);
+   world[room_nr].description = fread_string(fl, buf2);
+ 
+   if (!get_line(fl, line) || sscanf(line, " %d %s %d ", t, flags, t + 2) != 3) {
+     f
+ 
+ 
+ 
+ 
+ 
+ 
+ 
+ 
+ printf(stderr, "Format error in room #%d\n", virtual_nr);
+     exit(1);
+   }
+   /* t[0] is the zone number; ignored with the zone-file system */
+   world[room_nr].room_flags = asciiflag_conv(flags);
+   world[room_nr].sector_type = t[2];
+ 
+   world[room_nr].func = NULL;
+   world[room_nr].contents = NULL;
+   world[room_nr].people = NULL;
+   world[room_nr].light = 0;	/* Zero light sources */
+ 
+   for (i = 0; i < NUM_OF_DIRS; i++)
+     world[room_nr].dir_option[i] = NULL;
+ 
+   world[room_nr].ex_description = NULL;
+ 
+   sprintf(buf, "Format error in room #%d (expecting D/E/S)", virtual_nr);
+ 
+   for (;;) {
+     if (!get_line(fl, line)) {
+       fprintf(stderr, "%s\n", buf);
+       exit(1);
+     }
+     switch (*line) {
+     case 'D':
+       setup_dir(fl, room_nr, atoi(line + 1));
+       break;
+     case 'E':
+       CREATE(new_descr, struct extra_descr_data, 1);
+       new_descr->keyword = fread_string(fl, buf2);
+       new_descr->description = fread_string(fl, buf2);
+       new_descr->next = world[room_nr].ex_description;
+       world[room_nr].ex_description = new_descr;
+       break;
+     case 'S':			/* end of room */
+       top_of_world = room_nr++;
+       return;
+       break;
+     default:
+       fprintf(stderr, "%s\n", buf);
+       exit(1);
+       break;
+     }
+   }
+ }
+ 
+ 
+ 
+ /* read direction data */
+ void setup_dir(FILE * fl, int room, int dir)
+ {
+   int t[5];
+   char line[256];
+ 
+   sprintf(buf2, "room #%d, direction D%d", world[room].number, dir);
+ 
+   CREATE(world[room].dir_option[dir], struct room_direction_data, 1);
+   world[room].dir_option[dir]->general_description = fread_string(fl, buf2);
+   world[room].dir_option[dir]->keyword = fread_string(fl, buf2);
+ 
+   if (!get_line(fl, line)) {
+     fprintf(stderr, "Format error, %s\n", buf2);
+     exit(1);
+   }
+   if (sscanf(line, " %d %d %d ", t, t + 1, t + 2) != 3) {
+     fprintf(stderr, "Format error, %s\n", buf2);
+     exit(1);
+   }
+   if (t[0] == 1)
+     world[room].dir_option[dir]->exit_info = EX_ISDOOR;
+   else if (t[0] == 2)
+     world[room].dir_option[dir]->exit_info = EX_ISDOOR | EX_PICKPROOF;
+   else
+     world[room].dir_option[dir]->exit_info = 0;
+ 
+   world[room].dir_option[dir]->key = t[1];
+   world[room].dir_option[dir]->to_room = t[2];
+ }
+ 
+ 
+ /* make sure the start rooms exist & resolve their vnums to rnums */
+ void check_start_rooms(void)
+ {
+   extern sh_int mortal_start_room;
+   extern sh_int immort_start_room;
+   extern sh_int frozen_start_room;
+ 
+   if ((r_mortal_start_room = real_room(mortal_start_room)) < 0) {
+     log("SYSERR:  Mortal start room does not exist.  Change in config.c.");
+     exit(1);
+   }
+   if ((r_immort_start_room = real_room(immort_start_room)) < 0) {
+     if (!mini_mud)
+       log("SYSERR:  Warning: Immort start room does not exist.  Change in config.c.");
+     r_immort_start_room = r_mortal_start_room;
+   }
+   if ((r_frozen_start_room = real_room(frozen_start_room)) < 0) {
+     if (!mini_mud)
+       log("SYSERR:  Warning: Frozen start room does not exist.  Change in config.c.");
+     r_frozen_start_room = r_mortal_start_room;
+   }
+ }
+ 
+ 
+ /* resolve all vnums into rnums in the world */
+ void renum_world(void)
+ {
+   register int room, door;
+ 
+   for (room = 0; room <= top_of_world; room++)
+     for (door = 0; door < NUM_OF_DIRS; door++)
+       if (world[room].dir_option[door])
+ 	if (world[room].dir_option[door]->to_room != NOWHERE)
+ 	  world[room].dir_option[door]->to_room =
+ 	    real_room(world[room].dir_option[door]->to_room);
+ }
+ 
+ 
+ #define ZCMD zone_table[zone].cmd[cmd_no]
+ 
+ /* resulve vnums into rnums in the zone reset tables */
+ void renum_zone_table(void)
+ {
+   int zone, cmd_no, a, b;
+ 
+   for (zone = 0; zone <= top_of_zone_table; zone++)
+     for (cmd_no = 0; ZCMD.command != 'S'; cmd_no++) {
+       a = b = 0;
+       switch (ZCMD.command) {
+       case 'M':
+ 	a = ZCMD.arg1 = real_mobile(ZCMD.arg1);
+ 	b = ZCMD.arg3 = real_room(ZCMD.arg3);
+ 	break;
+       case 'O':
+ 	a = ZCMD.arg1 = real_object(ZCMD.arg1);
+ 	if (ZCMD.arg3 != NOWHERE)
+ 	  b = ZCMD.arg3 = real_room(ZCMD.arg3);
+ 	break;
+       case 'G':
+ 	a = ZCMD.arg1 = real_object(ZCMD.arg1);
+ 	break;
+       case 'E':
+ 	a = ZCMD.arg1 = real_object(ZCMD.arg1);
+ 	break;
+       case 'P':
+ 	a = ZCMD.arg1 = real_object(ZCMD.arg1);
+ 	b = ZCMD.arg3 = real_object(ZCMD.arg3);
+ 	break;
+       case 'D':
+ 	a = ZCMD.arg1 = real_room(ZCMD.arg1);
+ 	break;
+       case 'R': /* rem obj from room */
+         a = ZCMD.arg1 = real_room(ZCMD.arg1);
+ 	b = ZCMD.arg2 = real_object(ZCMD.arg2);
+         break;
+       }
+       if (a < 0 || b < 0) {
+ 	if (!mini_mud)
+ 	  log_zone_error(zone, cmd_no, "Invalid vnum, cmd disabled");
+ 	ZCMD.command = '*';
+       }
+     }
+ }
+ 
+ 
+ 
+ void parse_simple_mob(FILE *mob_f, int i, int nr)
+ {
+   int j, t[10];
+   char line[256];
+ 
+     mob_proto[i].real_abils.str = 11;
+     mob_proto[i].real_abils.intel = 11;
+     mob_proto[i].real_abils.wis = 11;
+     mob_proto[i].real_abils.dex = 11;
+     mob_proto[i].real_abils.con = 11;
+     mob_proto[i].real_abils.cha = 11;
+ 
+     get_line(mob_f, line);
+     if (sscanf(line, " %d %d %d %dd%d+%d %dd%d+%d ",
+ 	  t, t + 1, t + 2, t + 3, t + 4, t + 5, t + 6, t + 7, t + 8) != 9) {
+       fprintf(stderr, "Format error in mob #%d, first line after S flag\n"
+ 	      "...expecting line of form '# # # #d#+# #d#+#'\n", nr);
+       exit(1);
+     }
+     GET_LEVEL(mob_proto + i) = t[0];
+     mob_proto[i].points.hitroll = 20 - t[1];
+     mob_proto[i].points.armor = 10 * t[2];
+ 
+     /* max hit = 0 is a flag that H, M, V is xdy+z */
+     mob_proto[i].points.max_hit = 0;
+     mob_proto[i].points.hit = t[3];
+     mob_proto[i].points.mana = t[4];
+     mob_proto[i].points.move = t[5];
+ 
+     mob_proto[i].points.max_mana = 10;
+     mob_proto[i].points.max_move = 50;
+ 
+     mob_proto[i].mob_specials.damnodice = t[6];
+     mob_proto[i].mob_specials.damsizedice = t[7];
+     mob_proto[i].points.damroll = t[8];
+ 
+     get_line(mob_f, line);
+     sscanf(line, " %d %d ", t, t + 1);
+     GET_GOLD(mob_proto + i) = t[0];
+     GET_EXP(mob_proto + i) = t[1];
+ 
+     get_line(mob_f, line);
+     if (sscanf(line, " %d %d %d %d ", t, t + 1, t + 2, t + 3) != 3) {
+       fprintf(stderr, "Format error in mob #%d, second line after S flag\n"
+ 	      "...expecting line of form '# # #'\n", nr);
+     }
+ 
+     mob_proto[i].char_specials.position = t[0];
+     mob_proto[i].mob_specials.default_pos = t[1];
+     mob_proto[i].player.sex = t[2];
+ 
+     mob_proto[i].player.class = 0;
+     mob_proto[i].player.weight = 200;
+     mob_proto[i].player.height = 198;
+ 
+     for (j = 0; j < 3; j++)
+       GET_COND(mob_proto + i, j) = -1;
+ 
+     /*
+      * these are now save applies; base save numbers for MOBs are now from
+      * the warrior save table.
+      */
+     for (j = 0; j < 5; j++)
+       GET_SAVE(mob_proto + i, j) = 0;
+ }
+ 
+ 
+ /*
+  * interpret_espec is the function that takes espec keywords and values
+  * and assigns the correct value to the mob as appropriate.  Adding new
+  * e-specs is absurdly easy -- just add a new CASE statement to this
+  * function!  No other changes need to be made anywhere in the code.
+  */
+ 
+ #define CASE(test) if (!matched && !str_cmp(keyword, test) && (matched = 1))
+ #define RANGE(low, high) (num_arg = MAX((low), MIN((high), (num_arg))))
+ 
+ void interpret_espec(char *keyword, char *value, int i, int nr)
+ {
+   int num_arg, matched = 0;
+ 
+   num_arg = atoi(value);
+ 
+   CASE("BareHandAttack") {
+     RANGE(0, 99);
+     mob_proto[i].mob_specials.attack_type = num_arg;
+   }
+ 
+   CASE("Str") {
+     RANGE(3, 25);
+     mob_proto[i].real_abils.str = num_arg;
+   }
+ 
+   CASE("StrAdd") {
+     RANGE(0, 100);
+     mob_proto[i].real_abils.str_add = num_arg;    
+   }
+ 
+   CASE("Int") {
+     RANGE(3, 25);
+     mob_proto[i].real_abils.intel = num_arg;
+   }
+ 
+   CASE("Wis") {
+     RANGE(3, 25);
+     mob_proto[i].real_abils.wis = num_arg;
+   }
+ 
+   CASE("Dex") {
+     RANGE(3, 25);
+     mob_proto[i].real_abils.dex = num_arg;
+   }
+ 
+   CASE("Con") {
+     RANGE(3, 25);
+     mob_proto[i].real_abils.con = num_arg;
+   }
+ 
+   CASE("Cha") {
+     RANGE(3, 25);
+     mob_proto[i].real_abils.cha = num_arg;
+   }
+ 
+   if (!matched) {
+     fprintf(stderr, "Warning: unrecognized espec keyword %s in mob #%d\n",
+ 	    keyword, nr);
+   }    
+ }
+ 
+ #undef CASE
+ #undef RANGE
+ 
+ void parse_espec(char *buf, int i, int nr)
+ {
+   char *ptr;
+ 
+   if ((ptr = strchr(buf, ':')) != NULL) {
+     *(ptr++) = '\0';
+     while (isspace(*ptr))
+       ptr++;
+   } else
+     ptr = "";
+ 
+   interpret_espec(buf, ptr, i, nr);
+ }
+ 
+ 
+ void parse_enhanced_mob(FILE *mob_f, int i, int nr)
+ {
+   char line[256];
+ 
+   parse_simple_mob(mob_f, i, nr);
+ 
+   while (get_line(mob_f, line)) {
+     if (!strcmp(line, "E"))	/* end of the ehanced section */
+       return;
+     else if (*line == '#') {	/* we've hit the next mob, maybe? */
+       fprintf(stderr, "Unterminated E section in mob #%d\n", nr);
+       exit(1);
+     } else
+       parse_espec(line, i, nr);
+   }
+ 
+   fprintf(stderr, "Unexpected end of file reached after mob #%d\n", nr);
+   exit(1);
+ }
+ 
+ 
+ void parse_mobile(FILE * mob_f, int nr)
+ {
+   static int i = 0;
+   int j, t[10];
+   char line[256], *tmpptr, letter;
+   char f1[128], f2[128];
+ 
+   mob_index[i].virtual = nr;
+   mob_index[i].number = 0;
+   mob_index[i].func = NULL;
+ 
+   clear_char(mob_proto + i);
+ 
+   mob_proto[i].player_specials = &dummy_mob;
+   sprintf(buf2, "mob vnum %d", nr);
+ 
+   /***** String data *** */
+   mob_proto[i].player.name = fread_string(mob_f, buf2);
+   tmpptr = mob_proto[i].player.short_descr = fread_string(mob_f, buf2);
+   if (tmpptr && *tmpptr)
+     if (!str_cmp(fname(tmpptr), "a") || !str_cmp(fname(tmpptr), "an") ||
+ 	!str_cmp(fname(tmpptr), "the"))
+       *tmpptr = LOWER(*tmpptr);
+   mob_proto[i].player.long_descr = fread_string(mob_f, buf2);
+   mob_proto[i].player.description = fread_string(mob_f, buf2);
+   mob_proto[i].player.title = NULL;
+ 
+   /* *** Numeric data *** */
+   get_line(mob_f, line);
+   sscanf(line, "%s %s %d %c", f1, f2, t + 2, &letter);
+   MOB_FLAGS(mob_proto + i) = asciiflag_conv(f1);
+   SET_BIT(MOB_FLAGS(mob_proto + i), MOB_ISNPC);
+   AFF_FLAGS(mob_proto + i) = asciiflag_conv(f2);
+   GET_ALIGNMENT(mob_proto + i) = t[2];
+ 
+   switch (letter) {
+   case 'S':	/* Simple monsters */
+     parse_simple_mob(mob_f, i, nr);
+     break;
+   case 'E':	/* Circle3 Enhanced monsters */
+     parse_enhanced_mob(mob_f, i, nr);
+     break;
+   /* add new mob types here.. */
+   default:
+     fprintf(stderr, "Unsupported mob type '%c' in mob #%d\n", letter, nr);
+     exit(1);
+     break;
+   }
+ 
+   mob_proto[i].aff_abils = mob_proto[i].real_abils;
+ 
+   for (j = 0; j < NUM_WEARS; j++)
+     mob_proto[i].equipment[j] = NULL;
+ 
+   mob_proto[i].nr = i;
+   mob_proto[i].desc = NULL;
+ 
+   top_of_mobt = i++;
+ }
+ 
+ 
+ 
+ 
+ /* read all objects from obj file; generate index and prototypes */
+ char *parse_object(FILE * obj_f, int nr)
+ {
+   static int i = 0, retval;
+   static char line[256];
+   int t[10], j;
+   char *tmpptr;
+   char f1[256], f2[256];
+   struct extra_descr_data *new_descr;
+ 
+   obj_index[i].virtual = nr;
+   obj_index[i].number = 0;
+   obj_index[i].func = NULL;
+ 
+   clear_object(obj_proto + i);
+   obj_proto[i].in_room = NOWHERE;
+   obj_proto[i].item_number = i;
+ 
+   sprintf(buf2, "object #%d", nr);
+ 
+   /* *** string data *** */
+   if ((obj_proto[i].name = fread_string(obj_f, buf2)) == NULL) {
+     fprintf(stderr, "Null obj name or format error at or near %s\n", buf2);
+     exit(1);
+   }
+   tmpptr = obj_proto[i].short_description = fread_string(obj_f, buf2);
+   if (*tmpptr)
+     if (!str_cmp(fname(tmpptr), "a") || !str_cmp(fname(tmpptr), "an") ||
+ 	!str_cmp(fname(tmpptr), "the"))
+       *tmpptr = LOWER(*tmpptr);
+ 
+   tmpptr = obj_proto[i].description = fread_string(obj_f, buf2);
+   if (tmpptr && *tmpptr)
+     *tmpptr = UPPER(*tmpptr);
+   obj_proto[i].action_description = fread_string(obj_f, buf2);
+ 
+   /* *** numeric data *** */
+   if (!get_line(obj_f, line) ||
+       (retval = sscanf(line, " %d %s %s", t, f1, f2)) != 3) {
+     fprintf(stderr, "Format error in first numeric line (expecting 3 args, got %d), %s\n", retval, buf2);
+     exit(1);
+   }
+   obj_proto[i].obj_flags.type_flag = t[0];
+   obj_proto[i].obj_flags.extra_flags = asciiflag_conv(f1);
+   obj_proto[i].obj_flags.wear_flags = asciiflag_conv(f2);
+ 
+   if (!get_line(obj_f, line) ||
+       (retval = sscanf(line, "%d %d %d %d", t, t + 1, t + 2, t + 3)) != 4) {
+     fprintf(stderr, "Format error in second numeric line (expecting 4 args, got %d), %s\n", retval, buf2);
+     exit(1);
+   }
+   obj_proto[i].obj_flags.value[0] = t[0];
+   obj_proto[i].obj_flags.value[1] = t[1];
+   obj_proto[i].obj_flags.value[2] = t[2];
+   obj_proto[i].obj_flags.value[3] = t[3];
+ 
+   if (!get_line(obj_f, line) ||
+       (retval = sscanf(line, "%d %d %d", t, t + 1, t + 2)) != 3) {
+     fprintf(stderr, "Format error in third numeric line (expecting 3 args, got %d), %s\n", retval, buf2);
+     exit(1);
+   }
+   obj_proto[i].obj_flags.weight = t[0];
+   obj_proto[i].obj_flags.cost = t[1];
+   obj_proto[i].obj_flags.cost_per_day = t[2];
+ 
+   /* check to make sure that weight of containers exceeds curr. quantity */
+   if (obj_proto[i].obj_flags.type_flag == ITEM_DRINKCON ||
+       obj_proto[i].obj_flags.type_flag == ITEM_FOUNTAIN) {
+     if (obj_proto[i].obj_flags.weight < obj_proto[i].obj_flags.value[1])
+       obj_proto[i].obj_flags.weight = obj_proto[i].obj_flags.value[1] + 5;
+   }
+ 
+   /* *** extra descriptions and affect fields *** */
+ 
+   for (j = 0; j < MAX_OBJ_AFFECT; j++) {
+     obj_proto[i].affected[j].location = APPLY_NONE;
+     obj_proto[i].affected[j].modifier = 0;
+   }
+ 
+   strcat(buf2, ", after numeric constants (expecting E/A/#xxx)");
+   j = 0;
+ 
+   for (;;) {
+     if (!get_line(obj_f, line)) {
+       fprintf(stderr, "Format error in %s\n", buf2);
+       exit(1);
+     }
+     switch (*line) {
+     case 'E':
+       CREATE(new_descr, struct extra_descr_data, 1);
+       new_descr->keyword = fread_string(obj_f, buf2);
+       new_descr->description = fread_string(obj_f, buf2);
+       new_descr->next = obj_proto[i].ex_description;
+       obj_proto[i].ex_description = new_descr;
+       break;
+     case 'A':
+       if (j >= MAX_OBJ_AFFECT) {
+ 	fprintf(stderr, "Too many A fields (%d max), %s\n", MAX_OBJ_AFFECT, buf2);
+ 	exit(1);
+       }
+       get_line(obj_f, line);
+       sscanf(line, " %d %d ", t, t + 1);
+       obj_proto[i].affected[j].location = t[0];
+       obj_proto[i].affected[j].modifier = t[1];
+       j++;
+       break;
+     case '$':
+     case '#':
+       top_of_objt = i++;
+       return line;
+       break;
+     default:
+       fprintf(stderr, "Format error in %s\n", buf2);
+       exit(1);
+       break;
+     }
+   }
+ }
+ 
+ 
+ #define Z	zone_table[zone]
+ 
+ /* load the zone table and command tables */
+ void load_zones(FILE * fl, char *zonename)
+ {
+   static int zone = 0;
+   int cmd_no = 0, num_of_cmds = 0, line_num = 0, tmp, error;
+   char *ptr, buf[256], zname[256];
+ 
+   strcpy(zname, zonename);
+ 
+   while (get_line(fl, buf))
+     num_of_cmds++;		/* this should be correct within 3 or so */
+   rewind(fl);
+ 
+   if (num_of_cmds == 0) {
+     fprintf(stderr, "%s is empty!\n", zname);
+     exit(0);
+   } else
+     CREATE(Z.cmd, struct reset_com, num_of_cmds);
+ 
+   line_num += get_line(fl, buf);
+ 
+   if (sscanf(buf, "#%d", &Z.number) != 1) {
+     fprintf(stderr, "Format error in %s, line %d\n", zname, line_num);
+     exit(0);
+   }
+   sprintf(buf2, "beginning of zone #%d", Z.number);
+ 
+   line_num += get_line(fl, buf);
+   if ((ptr = strchr(buf, '~')) != NULL)	/* take off the '~' if it's there */
+     *ptr = '\0';
+   Z.name = str_dup(buf);
+ 
+   line_num += get_line(fl, buf);
+   if (sscanf(buf, " %d %d %d ", &Z.top, &Z.lifespan, &Z.reset_mode) != 3) {
+     fprintf(stderr, "Format error in 3-constant line of %s", zname);
+     exit(0);
+   }
+   cmd_no = 0;
+ 
+   for (;;) {
+     if ((tmp = get_line(fl, buf)) == 0) {
+       fprintf(stderr, "Format error in %s - premature end of file\n", zname);
+       exit(0);
+     }
+     line_num += tmp;
+     ptr = buf;
+     skip_spaces(&ptr);
+ 
+     if ((ZCMD.command = *ptr) == '*')
+       continue;
+ 
+     ptr++;
+ 
+     if (ZCMD.command == 'S' || ZCMD.command == '$') {
+       ZCMD.command = 'S';
+       break;
+     }
+     error = 0;
+     if (strchr("MOEPD", ZCMD.command) == NULL) {	/* a 3-arg command */
+       if (sscanf(ptr, " %d %d %d ", &tmp, &ZCMD.arg1, &ZCMD.arg2) != 3)
+ 	error = 1;
+     } else {
+       if (sscanf(ptr, " %d %d %d %d ", &tmp, &ZCMD.arg1, &ZCMD.arg2,
+ 		 &ZCMD.arg3) != 4)
+ 	error = 1;
+     }
+ 
+     ZCMD.if_flag = tmp;
+ 
+     if (error) {
+       fprintf(stderr, "Format error in %s, line %d: '%s'\n", zname, line_num, buf);
+       exit(0);
+     }
+     ZCMD.line = line_num;
+     cmd_no++;
+   }
+ 
+   top_of_zone_table = zone++;
+ }
+ 
+ #undef Z
+ 
+ 
+ void get_one_line(FILE *fl, char *buf)
+ {
+   if (fgets(buf, READ_SIZE, fl) == NULL) {
+     log("error reading help file: not terminated with $?");
+     exit(1);
+   }
+ 
+   buf[strlen(buf) - 1] = '\0'; /* take off the trailing \n */
+ }
+ 
+ 
+ void load_help(FILE *fl)
+ {
+   char key[READ_SIZE+1], next_key[READ_SIZE+1], entry[32384];
+   char line[READ_SIZE+1], *scan;
+   struct help_index_element el;
+ 
+   /* get the first keyword line */
+   get_one_line(fl, key);
+   while (*key != '$') {
+     /* read in the corresponding help entry */
+     strcpy(entry, strcat(key, "\r\n"));
+     get_one_line(fl, line);
+     while (*line != '#') {
+       strcat(entry, strcat(line, "\r\n"));
+       get_one_line(fl, line);
+     }
+ 
+     /* now, add the entry to the index with each keyword on the keyword line */
+     el.duplicate = 0;
+     el.entry = str_dup(entry);
+     scan = one_word(key, next_key);
+     while (*next_key) {
+       el.keyword = str_dup(next_key);
+       help_table[top_of_helpt++] = el;
+       el.duplicate++;
+       scan = one_word(scan, next_key);
+     }
+ 
+     /* get next keyword line (or $) */
+     get_one_line(fl, key);
+   }
+ }
+ 
+ 
+ int hsort(const void *a, const void *b)
+ {
+   struct help_index_element *a1, *b1;
+ 
+   a1 = (struct help_index_element *) a;
+   b1 = (struct help_index_element *) b;
+ 
+   return (str_cmp(a1->keyword, b1->keyword));
+ }
+ 
+ 
+ /*************************************************************************
+ *  procedures for resetting, both play-time and boot-time	 	 *
+ *********************************************************************** */
+ 
+ 
+ 
+ int vnum_mobile(char *searchname, struct char_data * ch)
+ {
+   int nr, found = 0;
+ 
+   for (nr = 0; nr <= top_of_mobt; nr++) {
+     if (isname(searchname, mob_proto[nr].player.name)) {
+       sprintf(buf, "%3d. [%5d] %s\r\n", ++found,
+ 	      mob_index[nr].virtual,
+ 	      mob_proto[nr].player.short_descr);
+       send_to_char(buf, ch);
+     }
+   }
+ 
+   return (found);
+ }
+ 
+ 
+ 
+ int vnum_object(char *searchname, struct char_data * ch)
+ {
+   int nr, found = 0;
+ 
+   for (nr = 0; nr <= top_of_objt; nr++) {
+     if (isname(searchname, obj_proto[nr].name)) {
+       sprintf(buf, "%3d. [%5d] %s\r\n", ++found,
+ 	      obj_index[nr].virtual,
+ 	      obj_proto[nr].short_description);
+       send_to_char(buf, ch);
+     }
+   }
+   return (found);
+ }
+ 
+ 
+ /* create a character, and add it to the char list */
+ struct char_data *create_char(void)
+ {
+   struct char_data *ch;
+ 
+   CREATE(ch, struct char_data, 1);
+   clear_char(ch);
+   ch->next = character_list;
+   character_list = ch;
+ 
+   return ch;
+ }
+ 
+ 
+ /* create a new mobile from a prototype */
+ struct char_data *read_mobile(int nr, int type)
+ {
+   int i;
+   struct char_data *mob;
+ 
+   if (type == VIRTUAL) {
+     if ((i = real_mobile(nr)) < 0) {
+       sprintf(buf, "Mobile (V) %d does not exist in database.", nr);
+       return (0);
+     }
+   } else
+     i = nr;
+ 
+   CREATE(mob, struct char_data, 1);
+   clear_char(mob);
+   *mob = mob_proto[i];
+   mob->next = character_list;
+   character_list = mob;
+ 
+   if (!mob->points.max_hit) {
+     mob->points.max_hit = dice(mob->points.hit, mob->points.mana) +
+       mob->points.move;
+   } else
+     mob->points.max_hit = number(mob->points.hit, mob->points.mana);
+ 
+   mob->points.hit = mob->points.max_hit;
+   mob->points.mana = mob->points.max_mana;
+   mob->points.move = mob->points.max_move;
+ 
+   mob->player.time.birth = time(0);
+   mob->player.time.played = 0;
+   mob->player.time.logon = time(0);
+ 
+   mob_index[i].number++;
+ 
+   return mob;
+ }
+ 
+ 
+ /* create an object, and add it to the object list */
+ struct obj_data *create_obj(void)
+ {
+   struct obj_data *obj;
+ 
+   CREATE(obj, struct obj_data, 1);
+   clear_object(obj);
+   obj->next = object_list;
+   object_list = obj;
+ 
+   return obj;
+ }
+ 
+ 
+ /* create a new object from a prototype */
+ struct obj_data *read_object(int nr, int type)
+ {
+   struct obj_data *obj;
+   int i;
+ 
+   if (nr < 0) {
+     log("SYSERR: trying to create obj with negative num!");
+     return NULL;
+   }
+   if (type == VIRTUAL) {
+     if ((i = real_object(nr)) < 0) {
+       sprintf(buf, "Object (V) %d does not exist in database.", nr);
+       return NULL;
+     }
+   } else
+     i = nr;
+ 
+   CREATE(obj, struct obj_data, 1);
+   clear_object(obj);
+   *obj = obj_proto[i];
+   obj->next = object_list;
+   object_list = obj;
+ 
+   obj_index[i].number++;
+ 
+   return obj;
+ }
+ 
+ 
+ 
+ #define ZO_DEAD  999
+ 
+ /* update zone ages, queue for reset if necessary, and dequeue when possible */
+ void zone_update(void)
+ {
+   int i;
+   struct reset_q_element *update_u, *temp;
+   static int timer = 0;
+   char buf[128];
+ 
+   /* jelson 10/22/92 */
+   if (((++timer * PULSE_ZONE) / PASSES_PER_SEC) >= 60) {
+     /* one minute has passed */
+     /*
+      * NOT accurate unless PULSE_ZONE is a multiple of PASSES_PER_SEC or a
+      * factor of 60
+      */
+ 
+     timer = 0;
+ 
+     /* since one minute has passed, increment zone ages */
+     for (i = 0; i <= top_of_zone_table; i++) {
+       if (zone_table[i].age < zone_table[i].lifespan &&
+ 	  zone_table[i].reset_mode)
+ 	(zone_table[i].age)++;
+ 
+       if (zone_table[i].age >= zone_table[i].lifespan &&
+ 	  zone_table[i].age < ZO_DEAD && zone_table[i].reset_mode) {
+ 	/* enqueue zone */
+ 
+ 	CREATE(update_u, struct reset_q_element, 1);
+ 
+ 	update_u->zone_to_reset = i;
+ 	update_u->next = 0;
+ 
+ 	if (!reset_q.head)
+ 	  reset_q.head = reset_q.tail = update_u;
+ 	else {
+ 	  reset_q.tail->next = update_u;
+ 	  reset_q.tail = update_u;
+ 	}
+ 
+ 	zone_table[i].age = ZO_DEAD;
+       }
+     }
+   }	/* end - one minute has passed */
+ 
+ 
+   /* dequeue zones (if possible) and reset */
+   /* this code is executed every 10 seconds (i.e. PULSE_ZONE) */
+   for (update_u = reset_q.head; update_u; update_u = update_u->next)
+     if (zone_table[update_u->zone_to_reset].reset_mode == 2 ||
+ 	is_empty(update_u->zone_to_reset)) {
+       reset_zone(update_u->zone_to_reset);
+       sprintf(buf, "Auto zone reset: %s",
+ 	      zone_table[update_u->zone_to_reset].name);
+       mudlog(buf, CMP, LVL_GOD, FALSE);
+       /* dequeue */
+       if (update_u == reset_q.head)
+ 	reset_q.head = reset_q.head->next;
+       else {
+ 	for (temp = reset_q.head; temp->next != update_u;
+ 	     temp = temp->next);
+ 
+ 	if (!update_u->next)
+ 	  reset_q.tail = temp;
+ 
+ 	temp->next = update_u->next;
+       }
+ 
+       free(update_u);
+       break;
+     }
+ }
+ 
+ void log_zone_error(int zone, int cmd_no, char *message)
+ {
+   char buf[256];
+ 
+   sprintf(buf, "SYSERR: error in zone file: %s", message);
+   mudlog(buf, NRM, LVL_GOD, TRUE);
+ 
+   sprintf(buf, "SYSERR: ...offending cmd: '%c' cmd in zone #%d, line %d",
+ 	  ZCMD.command, zone_table[zone].number, ZCMD.line);
+   mudlog(buf, NRM, LVL_GOD, TRUE);
+ }
+ 
+ #define ZONE_ERROR(message) \
+ 	{ log_zone_error(zone, cmd_no, message); last_cmd = 0; }
+ 
+ /* execute the reset command table of a given zone */
+ void reset_zone(int zone)
+ {
+   int cmd_no, last_cmd = 0;
+   struct char_data *mob = NULL;
+   struct obj_data *obj, *obj_to;
+ 
+   for (cmd_no = 0; ZCMD.command != 'S'; cmd_no++) {
+ 
+     if (ZCMD.if_flag && !last_cmd)
+       continue;
+ 
+     switch (ZCMD.command) {
+     case '*':			/* ignore command */
+       last_cmd = 0;
+       break;
+ 
+     case 'M':			/* read a mobile */
+       if (mob_index[ZCMD.arg1].number < ZCMD.arg2) {
+ 	mob = read_mobile(ZCMD.arg1, REAL);
+ 	char_to_room(mob, ZCMD.arg3);
+ 	last_cmd = 1;
+       } else
+ 	last_cmd = 0;
+       break;
+ 
+     case 'O':			/* read an object */
+       if (obj_index[ZCMD.arg1].number < ZCMD.arg2) {
+ 	if (ZCMD.arg3 >= 0) {
+ 	  obj = read_object(ZCMD.arg1, REAL);
+ 	  obj_to_room(obj, ZCMD.arg3);
+ 	  last_cmd = 1;
+ 	} else {
+ 	  obj = read_object(ZCMD.arg1, REAL);
+ 	  obj->in_room = NOWHERE;
+ 	  last_cmd = 1;
+ 	}
+       } else
+ 	last_cmd = 0;
+       break;
+ 
+     case 'P':			/* object to object */
+       if (obj_index[ZCMD.arg1].number < ZCMD.arg2) {
+ 	obj = read_object(ZCMD.arg1, REAL);
+ 	if (!(obj_to = get_obj_num(ZCMD.arg3))) {
+ 	  ZONE_ERROR("target obj not found");
+ 	  break;
+ 	}
+ 	obj_to_obj(obj, obj_to);
+ 	last_cmd = 1;
+       } else
+ 	last_cmd = 0;
+       break;
+ 
+     case 'G':			/* obj_to_char */
+       if (!mob) {
+ 	ZONE_ERROR("attempt to give obj to non-existant mob");
+ 	break;
+       }
+       if (obj_index[ZCMD.arg1].number < ZCMD.arg2) {
+ 	obj = read_object(ZCMD.arg1, REAL);
+ 	obj_to_char(obj, mob);
+ 	last_cmd = 1;
+       } else
+ 	last_cmd = 0;
+       break;
+ 
+     case 'E':			/* object to equipment list */
+       if (!mob) {
+ 	ZONE_ERROR("trying to equip non-existant mob");
+ 	break;
+       }
+       if (obj_index[ZCMD.arg1].number < ZCMD.arg2) {
+ 	if (ZCMD.arg3 < 0 || ZCMD.arg3 >= NUM_WEARS) {
+ 	  ZONE_ERROR("invalid equipment pos number");
+ 	} else {
+ 	  obj = read_object(ZCMD.arg1, REAL);
+ 	  equip_char(mob, obj, ZCMD.arg3);
+ 	  last_cmd = 1;
+ 	}
+       } else
+ 	last_cmd = 0;
+       break;
+ 
+     case 'R': /* rem obj from room */
+       if ((obj = get_obj_in_list_num(ZCMD.arg2, world[ZCMD.arg1].contents)) != NULL) {
+         obj_from_room(obj);
+         extract_obj(obj);
+       }
+       last_cmd = 1;
+       break;
+ 
+ 
+     case 'D':			/* set state of door */
+       if (ZCMD.arg2 < 0 || ZCMD.arg2 >= NUM_OF_DIRS ||
+ 	  (world[ZCMD.arg1].dir_option[ZCMD.arg2] == NULL)) {
+ 	ZONE_ERROR("door does not exist");
+       } else
+ 	switch (ZCMD.arg3) {
+ 	case 0:
+ 	  REMOVE_BIT(world[ZCMD.arg1].dir_option[ZCMD.arg2]->exit_info,
+ 		     EX_LOCKED);
+ 	  REMOVE_BIT(world[ZCMD.arg1].dir_option[ZCMD.arg2]->exit_info,
+ 		     EX_CLOSED);
+ 	  break;
+ 	case 1:
+ 	  SET_BIT(world[ZCMD.arg1].dir_option[ZCMD.arg2]->exit_info,
+ 		  EX_CLOSED);
+ 	  REMOVE_BIT(world[ZCMD.arg1].dir_option[ZCMD.arg2]->exit_info,
+ 		     EX_LOCKED);
+ 	  break;
+ 	case 2:
+ 	  SET_BIT(world[ZCMD.arg1].dir_option[ZCMD.arg2]->exit_info,
+ 		  EX_LOCKED);
+ 	  SET_BIT(world[ZCMD.arg1].dir_option[ZCMD.arg2]->exit_info,
+ 		  EX_CLOSED);
+ 	  break;
+ 	}
+       last_cmd = 1;
+       break;
+ 
+     default:
+       ZONE_ERROR("unknown cmd in reset table; cmd disabled");
+       ZCMD.command = '*';
+       break;
+     }
+   }
+ 
+   zone_table[zone].age = 0;
+ }
+ 
+ 
+ 
+ /* for use in reset_zone; return TRUE if zone 'nr' is free of PC's  */
+ int is_empty(int zone_nr)
+ {
+   struct descriptor_data *i;
+ 
+   for (i = descriptor_list; i; i = i->next)
+     if (!i->connected)
+       if (world[i->character->in_room].zone == zone_nr)
+ 	return 0;
+ 
+   return 1;
+ }
+ 
+ 
+ 
+ 
+ 
+ /*************************************************************************
+ *  stuff related to the save/load player system				 *
+ *********************************************************************** */
+ 
+ 
+ long get_id_by_name(char *name)
+ {
+   int i;
+ 
+   one_argument(name, arg);
+   for (i = 0; i <= top_of_p_table; i++)
+     if (!strcmp((player_table + i)->name, arg))
+       return ((player_table + i)->id);
+ 
+   return -1;
+ }
+ 
+ 
+ char *get_name_by_id(long id)
+ {
+   int i;
+ 
+   for (i = 0; i <= top_of_p_table; i++)
+     if ((player_table + i)->id == id)
+       return ((player_table + i)->name);
+ 
+   return NULL;
+ }
+ 
+ 
+ /* Load a char, TRUE if loaded, FALSE if not */
+ int load_char(char *name, struct char_file_u * char_element)
+ {
+   int player_i;
+ 
+   int find_name(char *name);
+ 
+   if ((player_i = find_name(name)) >= 0) {
+     fseek(player_fl, (long) (player_i * sizeof(struct char_file_u)), SEEK_SET);
+     fread(char_element, sizeof(struct char_file_u), 1, player_fl);
+     return (player_i);
+   } else
+     return (-1);
+ }
+ 
+ 
+ 
+ 
+ /*
+  * write the vital data of a player to the player file
+  *
+  * NOTE: load_room should be an *RNUM* now.  It is converted to a vnum here.
+  */
+ void save_char(struct char_data * ch, sh_int load_room)
+ {
+   struct char_file_u st;
+ 
+   if (IS_NPC(ch) || !ch->desc || GET_PFILEPOS(ch) < 0)
+     return;
+ 
+   char_to_store(ch, &st);
+ 
+   strncpy(st.host, ch->desc->host, HOST_LENGTH);
+   st.host[HOST_LENGTH] = '\0';
+ 
+   if (!PLR_FLAGGED(ch, PLR_LOADROOM)) {
+     if (load_room == NOWHERE)
+       st.player_specials_saved.load_room = NOWHERE;
+     else
+       st.player_specials_saved.load_room = world[load_room].number;
+   }
+ 
+   strcpy(st.pwd, GET_PASSWD(ch));
+ 
+   fseek(player_fl, GET_PFILEPOS(ch) * sizeof(struct char_file_u), SEEK_SET);
+   fwrite(&st, sizeof(struct char_file_u), 1, player_fl);
+ }
+ 
+ 
+ 
+ /* copy data from the file structure to a char struct */
+ void store_to_char(struct char_file_u * st, struct char_data * ch)
+ {
+   int i;
+ 
+   /* to save memory, only PC's -- not MOB's -- have player_specials */
+   if (ch->player_specials == NULL)
+     CREATE(ch->player_specials, struct player_special_data, 1);
+ 
+   GET_SEX(ch) = st->sex;
+   GET_CLASS(ch) = st->class;
+   GET_LEVEL(ch) = st->level;
+ 
+   ch->player.short_descr = NULL;
+   ch->player.long_descr = NULL;
+   ch->player.title = str_dup(st->title);
+   ch->player.description = str_dup(st->description);
+ 
+   ch->player.hometown = st->hometown;
+   ch->player.time.birth = st->birth;
+   ch->player.time.played = st->played;
+   ch->player.time.logon = time(0);
+ 
+   ch->player.weight = st->weight;
+   ch->player.height = st->height;
+ 
+   ch->real_abils = st->abilities;
+   ch->aff_abils = st->abilities;
+   ch->points = st->points;
+   ch->char_specials.saved = st->char_specials_saved;
+   ch->player_specials->saved = st->player_specials_saved;
+   POOFIN(ch) = NULL;
+   POOFOUT(ch) = NULL;
+ 
+   if (ch->points.max_mana < 100)
+     ch->points.max_mana = 100;
+ 
+   ch->char_specials.carry_weight = 0;
+   ch->char_specials.carry_items = 0;
+   ch->points.armor = 100;
+   ch->points.hitroll = 0;
+   ch->points.damroll = 0;
+ 
+   if (ch->player.name == NULL)
+     CREATE(ch->player.name, char, strlen(st->name) + 1);
+   strcpy(ch->player.name, st->name);
+   strcpy(ch->player.passwd, st->pwd);
+ 
+   /* Add all spell effects */
+   for (i = 0; i < MAX_AFFECT; i++) {
+     if (st->affected[i].type)
+       affect_to_char(ch, &st->affected[i]);
+   }
+ 
+   /*
+    * If you're not poisioned and you've been away for more than an hour of
+    * real time, we'll set your HMV back to full
+    */
+ 
+   if (!IS_AFFECTED(ch, AFF_POISON) &&
+       (((long) (time(0) - st->last_logon)) >= SECS_PER_REAL_HOUR)) {
+     GET_HIT(ch) = GET_MAX_HIT(ch);
+     GET_MOVE(ch) = GET_MAX_MOVE(ch);
+     GET_MANA(ch) = GET_MAX_MANA(ch);
+   }
+ }				/* store_to_char */
+ 
+ 
+ 
+ 
+ /* copy vital data from a players char-structure to the file structure */
+ void char_to_store(struct char_data * ch, struct char_file_u * st)
+ {
+   int i;
+   struct affected_type *af;
+   struct obj_data *char_eq[NUM_WEARS];
+ 
+   /* Unaffect everything a character can be affected by */
+ 
+   for (i = 0; i < NUM_WEARS; i++) {
+     if (GET_EQ(ch, i))
+       char_eq[i] = unequip_char(ch, i);
+     else
+       char_eq[i] = NULL;
+   }
+ 
+   for (af = ch->affected, i = 0; i < MAX_AFFECT; i++) {
+     if (af) {
+       st->affected[i] = *af;
+       st->affected[i].next = 0;
+       af = af->next;
+     } else {
+       st->affected[i].type = 0;	/* Zero signifies not used */
+       st->affected[i].duration = 0;
+       st->affected[i].modifier = 0;
+       st->affected[i].location = 0;
+       st->affected[i].bitvector = 0;
+       st->affected[i].next = 0;
+     }
+   }
+ 
+ 
+   /*
+    * remove the affections so that the raw values are stored; otherwise the
+    * effects are doubled when the char logs back in.
+    */
+ 
+   while (ch->affected)
+     affect_remove(ch, ch->affected);
+ 
+   if ((i >= MAX_AFFECT) && af && af->next)
+     log("SYSERR: WARNING: OUT OF STORE ROOM FOR AFFECTED TYPES!!!");
+ 
+   ch->aff_abils = ch->real_abils;
+ 
+   st->birth = ch->player.time.birth;
+   st->played = ch->player.time.played;
+   st->played += (long) (time(0) - ch->player.time.logon);
+   st->last_logon = time(0);
+ 
+   ch->player.time.played = st->played;
+   ch->player.time.logon = time(0);
+ 
+   st->hometown = ch->player.hometown;
+   st->weight = GET_WEIGHT(ch);
+   st->height = GET_HEIGHT(ch);
+   st->sex = GET_SEX(ch);
+   st->class = GET_CLASS(ch);
+   st->level = GET_LEVEL(ch);
+   st->abilities = ch->real_abils;
+   st->points = ch->points;
+   st->char_specials_saved = ch->char_specials.saved;
+   st->player_specials_saved = ch->player_specials->saved;
+ 
+   st->points.armor = 100;
+   st->points.hitroll = 0;
+   st->points.damroll = 0;
+ 
+   if (GET_TITLE(ch))
+     strcpy(st->title, GET_TITLE(ch));
+   else
+     *st->title = '\0';
+ 
+   if (ch->player.description)
+     strcpy(st->description, ch->player.description);
+   else
+     *st->description = '\0';
+ 
+   strcpy(st->name, GET_NAME(ch));
+ 
+   /* add spell and eq affections back in now */
+   for (i = 0; i < MAX_AFFECT; i++) {
+     if (st->affected[i].type)
+       affect_to_char(ch, &st->affected[i]);
+   }
+ 
+   for (i = 0; i < NUM_WEARS; i++) {
+     if (char_eq[i])
+       equip_char(ch, char_eq[i], i);
+   }
+ /*   affect_total(ch); unnecessary, I think !?! */
+ }				/* Char to store */
+ 
+ 
+ 
+ void save_etext(struct char_data * ch)
+ {
+ /* this will be really cool soon */
+ 
+ }
+ 
+ 
+ /* create a new entry in the in-memory index table for the player file */
+ int create_entry(char *name)
+ {
+   int i;
+ 
+   if (top_of_p_table == -1) {
+     CREATE(player_table, struct player_index_element, 1);
+     top_of_p_table = 0;
+   } else if (!(player_table = (struct player_index_element *)
+ 	       realloc(player_table, sizeof(struct player_index_element) *
+ 		       (++top_of_p_table + 1)))) {
+     perror("create entry");
+     exit(1);
+   }
+   CREATE(player_table[top_of_p_table].name, char, strlen(name) + 1);
+ 
+   /* copy lowercase equivalent of name to table field */
+   for (i = 0; (*(player_table[top_of_p_table].name + i) = LOWER(*(name + i)));
+        i++);
+ 
+   return (top_of_p_table);
+ }
+ 
+ 
+ 
+ /************************************************************************
+ *  funcs of a (more or less) general utility nature			*
+ ********************************************************************** */
+ 
+ 
+ /* read and allocate space for a '~'-terminated string from a given file */
+ char *fread_string(FILE * fl, char *error)
+ {
+   char buf[MAX_STRING_LENGTH], tmp[512], *rslt;
+   register char *point;
+   int done = 0, length = 0, templength = 0;
+ 
+   *buf = '\0';
+ 
+   do {
+     if (!fgets(tmp, 512, fl)) {
+       fprintf(stderr, "SYSERR: fread_string: format error at or near %s\n",
+ 	      error);
+       exit(1);
+     }
+     /* If there is a '~', end the string; else put an "\r\n" over the '\n'. */
+     if ((point = strchr(tmp, '~')) != NULL) {
+       *point = '\0';
+       done = 1;
+     } else {
+       point = tmp + strlen(tmp) - 1;
+       *(point++) = '\r';
+       *(point++) = '\n';
+       *point = '\0';
+     }
+ 
+     templength = strlen(tmp);
+ 
+     if (length + templength >= MAX_STRING_LENGTH) {
+       log("SYSERR: fread_string: string too large (db.c)");
+       log(error);
+       exit(1);
+     } else {
+       strcat(buf + length, tmp);
+       length += templength;
+     }
+   } while (!done);
+ 
+   /* allocate space for the new string and copy it */
+   if (strlen(buf) > 0) {
+     CREATE(rslt, char, length + 1);
+     strcpy(rslt, buf);
+   } else
+     rslt = NULL;
+ 
+   return rslt;
+ }
+ 
+ 
+ /* release memory allocated for a char struct */
+ void free_char(struct char_data * ch)
+ {
+   int i;
+   struct alias *a;
+   void free_alias(struct alias * a);
+ 
+   if (ch->player_specials != NULL && ch->player_specials != &dummy_mob) {
+     while ((a = GET_ALIASES(ch)) != NULL) {
+       GET_ALIASES(ch) = (GET_ALIASES(ch))->next;
+       free_alias(a);
+     }
+     if (ch->player_specials->poofin)
+       free(ch->player_specials->poofin);
+     if (ch->player_specials->poofout)
+       free(ch->player_specials->poofout);
+     free(ch->player_specials);
+     if (IS_NPC(ch))
+       log("SYSERR: Mob had player_specials allocated!");
+   }
+   if (!IS_NPC(ch) || (IS_NPC(ch) && GET_MOB_RNUM(ch) == -1)) {
+     /* if this is a player, or a non-prototyped non-player, free all */
+     if (GET_NAME(ch))
+       free(GET_NAME(ch));
+     if (ch->player.title)
+       free(ch->player.title);
+     if (ch->player.short_descr)
+       free(ch->player.short_descr);
+     if (ch->player.long_descr)
+       free(ch->player.long_descr);
+     if (ch->player.description)
+       free(ch->player.description);
+   } else if ((i = GET_MOB_RNUM(ch)) > -1) {
+     /* otherwise, free strings only if the string is not pointing at proto */
+     if (ch->player.name && ch->player.name != mob_proto[i].player.name)
+       free(ch->player.name);
+     if (ch->player.title && ch->player.title != mob_proto[i].player.title)
+       free(ch->player.title);
+     if (ch->player.short_descr && ch->player.short_descr != mob_proto[i].player.short_descr)
+       free(ch->player.short_descr);
+     if (ch->player.long_descr && ch->player.long_descr != mob_proto[i].player.long_descr)
+       free(ch->player.long_descr);
+     if (ch->player.description && ch->player.description != mob_proto[i].player.description)
+       free(ch->player.description);
+   }
+   while (ch->affected)
+     affect_remove(ch, ch->affected);
+ 
+   free(ch);
+ }
+ 
+ 
+ 
+ 
+ /* release memory allocated for an obj struct */
+ void free_obj(struct obj_data * obj)
+ {
+   int nr;
+   struct extra_descr_data *this, *next_one;
+ 
+   if ((nr = GET_OBJ_RNUM(obj)) == -1) {
+     if (obj->name)
+       free(obj->name);
+     if (obj->description)
+       free(obj->description);
+     if (obj->short_description)
+       free(obj->short_description);
+     if (obj->action_description)
+       free(obj->action_description);
+     if (obj->ex_description)
+       for (this = obj->ex_description; this; this = next_one) {
+ 	next_one = this->next;
+ 	if (this->keyword)
+ 	  free(this->keyword);
+ 	if (this->description)
+ 	  free(this->description);
+ 	free(this);
+       }
+   } else {
+     if (obj->name && obj->name != obj_proto[nr].name)
+       free(obj->name);
+     if (obj->description && obj->description != obj_proto[nr].description)
+       free(obj->description);
+     if (obj->short_description && obj->short_description != obj_proto[nr].short_description)
+       free(obj->short_description);
+     if (obj->action_description && obj->action_description != obj_proto[nr].action_description)
+       free(obj->action_description);
+     if (obj->ex_description && obj->ex_description != obj_proto[nr].ex_description)
+       for (this = obj->ex_description; this; this = next_one) {
+ 	next_one = this->next;
+ 	if (this->keyword)
+ 	  free(this->keyword);
+ 	if (this->description)
+ 	  free(this->description);
+ 	free(this);
+       }
+   }
+ 
+   free(obj);
+ }
+ 
+ 
+ 
+ /* read contets of a text file, alloc space, point buf to it */
+ int file_to_string_alloc(char *name, char **buf)
+ {
+   char temp[MAX_STRING_LENGTH];
+ 
+   if (*buf)
+     free(*buf);
+ 
+   if (file_to_string(name, temp) < 0) {
+     *buf = "";
+     return -1;
+   } else {
+     *buf = str_dup(temp);
+     return 0;
+   }
+ }
+ 
+ 
+ /* read contents of a text file, and place in buf */
+ int file_to_string(char *name, char *buf)
+ {
+   FILE *fl;
+   char tmp[READ_SIZE+3];
+ 
+   *buf = '\0';
+ 
+   if (!(fl = fopen(name, "r"))) {
+     sprintf(tmp, "Error reading %s", name);
+     perror(tmp);
+     return (-1);
+   }
+   do {
+     fgets(tmp, READ_SIZE, fl);
+     tmp[strlen(tmp) - 1] = '\0'; /* take off the trailing \n */
+     strcat(tmp, "\r\n");
+ 
+     if (!feof(fl)) {
+       if (strlen(buf) + strlen(tmp) + 1 > MAX_STRING_LENGTH) {
+         sprintf(buf, "SYSERR: %s: string too big (%d max)", name,
+ 		MAX_STRING_LENGTH);
+ 	log(buf);
+ 	*buf = '\0';
+ 	return -1;
+       }
+       strcat(buf, tmp);
+     }
+   } while (!feof(fl));
+ 
+   fclose(fl);
+ 
+   return (0);
+ }
+ 
+ 
+ 
+ /* clear some of the the working variables of a char */
+ void reset_char(struct char_data * ch)
+ {
+   int i;
+ 
+   for (i = 0; i < NUM_WEARS; i++)
+     GET_EQ(ch, i) = NULL;
+ 
+   ch->followers = NULL;
+   ch->master = NULL;
+   ch->in_room = NOWHERE;
+   ch->carrying = NULL;
+   ch->next = NULL;
+   ch->next_fighting = NULL;
+   ch->next_in_room = NULL;
+   FIGHTING(ch) = NULL;
+   ch->char_specials.position = POS_STANDING;
+   ch->mob_specials.default_pos = POS_STANDING;
+   ch->char_specials.carry_weight = 0;
+   ch->char_specials.carry_items = 0;
+ 
+   if (GET_HIT(ch) <= 0)
+     GET_HIT(ch) = 1;
+   if (GET_MOVE(ch) <= 0)
+     GET_MOVE(ch) = 1;
+   if (GET_MANA(ch) <= 0)
+     GET_MANA(ch) = 1;
+ 
+   GET_LAST_TELL(ch) = NOBODY;
+ }
+ 
+ 
+ 
+ /* clear ALL the working variables of a char; do NOT free any space alloc'ed */
+ void clear_char(struct char_data * ch)
+ {
+   memset((char *) ch, 0, sizeof(struct char_data));
+ 
+   ch->in_room = NOWHERE;
+   GET_PFILEPOS(ch) = -1;
+   GET_WAS_IN(ch) = NOWHERE;
+   GET_POS(ch) = POS_STANDING;
+   ch->mob_specials.default_pos = POS_STANDING;
+ 
+   GET_AC(ch) = 100;		/* Basic Armor */
+   if (ch->points.max_mana < 100)
+     ch->points.max_mana = 100;
+ }
+ 
+ 
+ void clear_object(struct obj_data * obj)
+ {
+   memset((char *) obj, 0, sizeof(struct obj_data));
+ 
+   obj->item_number = NOTHING;
+   obj->in_room = NOWHERE;
+ }
+ 
+ 
+ 
+ 
+ /* initialize a new character only if class is set */
+ void init_char(struct char_data * ch)
+ {
+   int i;
+ 
+   /* create a player_special structure */
+   if (ch->player_specials == NULL)
+     CREATE(ch->player_specials, struct player_special_data, 1);
+ 
+   /* *** if this is our first player --- he be God *** */
+ 
+   if (top_of_p_table == 0) {
+     GET_EXP(ch) = 7000000;
+     GET_LEVEL(ch) = LVL_IMPL;
+ 
+     ch->points.max_hit = 500;
+     ch->points.max_mana = 100;
+     ch->points.max_move = 82;
+   }
+   set_title(ch, NULL);
+ 
+   ch->player.short_descr = NULL;
+   ch->player.long_descr = NULL;
+   ch->player.description = NULL;
+ 
+   ch->player.hometown = 1;
+ 
+   ch->player.time.birth = time(0);
+   ch->player.time.played = 0;
+   ch->player.time.logon = time(0);
+ 
+   for (i = 0; i < MAX_TONGUE; i++)
+     GET_TALK(ch, i) = 0;
+ 
+   /* make favors for sex */
+   if (ch->player.sex == SEX_MALE) {
+     ch->player.weight = number(120, 180);
+     ch->player.height = number(160, 200);
+   } else {
+     ch->player.weight = number(100, 160);
+     ch->player.height = number(150, 180);
+   }
+ 
+   ch->points.max_mana = 100;
+   ch->points.mana = GET_MAX_MANA(ch);
+   ch->points.hit = GET_MAX_HIT(ch);
+   ch->points.max_move = 82;
+   ch->points.move = GET_MAX_MOVE(ch);
+   ch->points.armor = 100;
+ 
+   player_table[top_of_p_table].id = GET_IDNUM(ch) = ++top_idnum;
+ 
+   for (i = 1; i <= MAX_SKILLS; i++) {
+     if (GET_LEVEL(ch) < LVL_IMPL)
+       SET_SKILL(ch, i, 0)
+     else
+       SET_SKILL(ch, i, 100);
+   }
+ 
+   ch->char_specials.saved.affected_by = 0;
+ 
+   for (i = 0; i < 5; i++)
+     GET_SAVE(ch, i) = 0;
+ 
+   ch->real_abils.intel = 25;
+   ch->real_abils.wis = 25;
+   ch->real_abils.dex = 25;
+   ch->real_abils.str = 25;
+   ch->real_abils.str_add = 100;
+   ch->real_abils.con = 25;
+   ch->real_abils.cha = 25;
+ 
+   for (i = 0; i < 3; i++)
+     GET_COND(ch, i) = (GET_LEVEL(ch) == LVL_IMPL ? -1 : 24);
+ 
+   GET_LOADROOM(ch) = NOWHERE;
+ }
+ 
+ 
+ 
+ /* returns the real number of the room with given virtual number */
+ int real_room(int virtual)
+ {
+   int bot, top, mid;
+ 
+   bot = 0;
+   top = top_of_world;
+ 
+   /* perform binary search on world-table */
+   for (;;) {
+     mid = (bot + top) / 2;
+ 
+     if ((world + mid)->number == virtual)
+       return mid;
+     if (bot >= top)
+       return NOWHERE;
+     if ((world + mid)->number > virtual)
+       top = mid - 1;
+     else
+       bot = mid + 1;
+   }
+ }
+ 
+ 
+ 
+ /* returns the real number of the monster with given virtual number */
+ int real_mobile(int virtual)
+ {
+   int bot, top, mid;
+ 
+   bot = 0;
+   top = top_of_mobt;
+ 
+   /* perform binary search on mob-table */
+   for (;;) {
+     mid = (bot + top) / 2;
+ 
+     if ((mob_index + mid)->virtual == virtual)
+       return (mid);
+     if (bot >= top)
+       return (-1);
+     if ((mob_index + mid)->virtual > virtual)
+       top = mid - 1;
+     else
+       bot = mid + 1;
+   }
+ }
+ 
+ 
+ 
+ /* returns the real number of the object with given virtual number */
+ int real_object(int virtual)
+ {
+   int bot, top, mid;
+ 
+   bot = 0;
+   top = top_of_objt;
+ 
+   /* perform binary search on obj-table */
+   for (;;) {
+     mid = (bot + top) / 2;
+ 
+     if ((obj_index + mid)->virtual == virtual)
+       return (mid);
+     if (bot >= top)
+       return (-1);
+     if ((obj_index + mid)->virtual > virtual)
+       top = mid - 1;
+     else
+       bot = mid + 1;
+   }
+ }
diff -c -P -x *.o orig-src/db.h src/db.h
*** orig-src/db.h	Mon Feb 24 23:00:33 1997
--- src/db.h	Sat Feb 22 16:19:26 1997
***************
*** 15,20 ****
--- 15,21 ----
  #define DB_BOOT_ZON	3
  #define DB_BOOT_SHP	4
  #define DB_BOOT_HLP	5
+ #define DB_BOOT_CLAN	6
  
  /* names of various files and directories */
  #define INDEX_FILE	"index"		/* index of world files		*/
***************
*** 25,30 ****
--- 26,32 ----
  #define ZON_PREFIX	"world/zon"	/* zon defs & command tables	*/
  #define SHP_PREFIX	"world/shp"	/* shop definitions		*/
  #define HLP_PREFIX	"text/help"	/* for HELP <keyword>		*/
+ #define CLAN_PREFIX	"text/clan"		/* For clan info		*/
  
  #define CREDITS_FILE	"text/credits"	/* for the 'credits' command	*/
  #define NEWS_FILE	"text/news"	/* for the 'news' command	*/
diff -c -P -x *.o orig-src/fight.c src/fight.c
*** orig-src/fight.c	Mon Feb 24 23:00:33 1997
--- src/fight.c	Sat Feb  8 13:27:18 1997
***************
*** 30,35 ****
--- 30,38 ----
  extern struct message_list fight_messages[MAX_MESSAGES];
  extern struct obj_data *object_list;
  extern int pk_allowed;		/* see config.c */
+ extern int summon_allowed;	/*       "      */
+ extern int sleep_allowed;       /*       "      */
+ extern int charm_allowed;       /*       "      */
  extern int auto_save;		/* see config.c */
  extern int max_exp_gain;	/* see config.c */
  
diff -c -P -x *.o orig-src/interpreter.c src/interpreter.c
*** orig-src/interpreter.c	Mon Feb 24 23:00:34 1997
--- src/interpreter.c	Sun Feb 23 04:06:52 1997
***************
*** 23,29 ****
  #include "handler.h"
  #include "mail.h"
  #include "screen.h"
! 
  
  extern const struct title_type titles[NUM_CLASSES][LVL_IMPL + 1];
  extern char *motd;
--- 23,29 ----
  #include "handler.h"
  #include "mail.h"
  #include "screen.h"
! #include "clan.h"
  
  extern const struct title_type titles[NUM_CLASSES][LVL_IMPL + 1];
  extern char *motd;
***************
*** 50,55 ****
--- 50,56 ----
  int special(struct char_data *ch, int cmd, char *arg);
  int isbanned(char *hostname);
  int Valid_Name(char *newname);
+ extern void parse_clan_edit(struct descriptor_data *d, char *arg);
  
  
  /* prototypes for all do_x functions. */
***************
*** 179,184 ****
--- 180,189 ----
  ACMD(do_write);
  ACMD(do_zreset);
  
+ /* (FIDO) New commands here */
+ ACMD(do_world);
+ ACMD(do_clan);
+ ACMD(do_clansay);
  
  /* This is the Master Command List(tm).
  
***************
*** 532,537 ****
--- 537,547 ----
  
    { "zreset"   , POS_DEAD    , do_zreset   , LVL_GRGOD, 0 },
  
+ /* (FIDO) New commands enter the master list here */
+   { "world"    , POS_DEAD    , do_world    , LVL_GOD, 0 },  /* Added 9/2/96 */
+   { "clan"     , POS_DEAD    , do_clan     , 0, 0 },	    /* Added 10/2/96 */
+   { "|"        , POS_DEAD    , do_clansay  , 0, 0 },        /* Added 11/2/96 */
+ 
    { "\n", 0, 0, 0, 0 } };	/* this must be last */
  
  
***************
*** 1255,1260 ****
--- 1265,1273 ----
    skip_spaces(&arg);
  
    switch (STATE(d)) {
+   case CON_CLAN_EDIT:		/* Editing clans */
+     parse_clan_edit(d, arg);
+     break;
    case CON_GET_NAME:		/* wait for input of name */
      if (d->character == NULL) {
        CREATE(d->character, struct char_data, 1);
diff -c -P -x *.o orig-src/magic.c src/magic.c
*** orig-src/magic.c	Mon Feb 24 23:00:34 1997
--- src/magic.c	Sat Feb  8 13:32:45 1997
***************
*** 30,35 ****
--- 30,39 ----
  
  extern int mini_mud;
  extern int pk_allowed;
+ extern int sleep_allowed;
+ extern int summon_allowed;
+ extern int charm_allowed;
+ extern int roomaffect_allowed;
  
  extern struct default_mobile_stats *mob_defaults;
  extern char weapon_verbs[];
***************
*** 582,589 ****
      to_room = "$n is surrounded by a white aura.";
      break;
  
!   case SPELL_SLEEP:
!     if (!pk_allowed && !IS_NPC(ch) && !IS_NPC(victim))
        return;
      if (MOB_FLAGGED(victim, MOB_NOSLEEP))
        return;
--- 586,593 ----
      to_room = "$n is surrounded by a white aura.";
      break;
  
!   case SPELL_SLEEP:   /* (FIDO) Changed this from pk_allowed to sleep_allowed */
!     if (!sleep_allowed && !IS_NPC(ch) && !IS_NPC(victim))
        return;
      if (MOB_FLAGGED(victim, MOB_NOSLEEP))
        return;
***************
*** 793,799 ****
        continue;
      if (!IS_NPC(tch) && GET_LEVEL(tch) >= LVL_IMMORT)
        continue;
!     if (!pk_allowed && !IS_NPC(ch) && !IS_NPC(tch))
        continue;
      if (!IS_NPC(ch) && IS_NPC(tch) && IS_AFFECTED(tch, AFF_CHARM))
        continue;
--- 797,807 ----
        continue;
      if (!IS_NPC(tch) && GET_LEVEL(tch) >= LVL_IMMORT)
        continue;
!     /* (FIDO) Changed this from pk_allowed to roomaffect_allowed */
!     /* The whole idea being, that you can specify whether room affect spells */
!     /* WILL hurt other players or not.  You could even set it up to change */
!     /* from room to room. */
!     if (!roomaffect_allowed && !IS_NPC(ch) && !IS_NPC(tch))
        continue;
      if (!IS_NPC(ch) && IS_NPC(tch) && IS_AFFECTED(tch, AFF_CHARM))
        continue;
diff -c -P -x *.o orig-src/make.log src/make.log
*** orig-src/make.log	Thu Jan  1 10:00:00 1970
--- src/make.log	Sat Feb 22 21:47:33 1997
***************
*** 0 ****
--- 1,19 ----
+ make ../bin/circle
+ make[1]: Entering directory `/home/circle30bpl11/src'
+ gcc -c -g -O -Wall -fno-strict-prototypes  clan.c
+ clan.c: In function `clan_save':
+ clan.c:993: warning: suggest parentheses around assignment used as truth value
+ clan.c:996: warning: suggest parentheses around assignment used as truth value
+ clan.c:1021: warning: passing arg 1 of `close' makes integer from pointer without a cast
+ clan.c:1036: warning: implicit declaration of function `write_clan'
+ clan.c:1039: warning: passing arg 1 of `close' makes integer from pointer without a cast
+ clan.c: At top level:
+ clan.c:1051: warning: type mismatch with previous external decl
+ clan.c:1036: warning: previous external decl of `write_clan'
+ clan.c:1051: warning: type mismatch with previous implicit declaration
+ clan.c:1036: warning: previous implicit declaration of `write_clan'
+ clan.c:1051: warning: `write_clan' was previously implicitly declared to return `int'
+ clan.c: In function `write_clan':
+ clan.c:1052: warning: `preline' might be used uninitialized in this function
+ gcc -o ../bin/circle  comm.o act.comm.o act.informative.o act.movement.o act.item.o act.offensive.o act.other.o act.social.o act.wizard.o ban.o boards.o castle.o class.o config.o constants.o db.o fight.o graph.o handler.o house.o interpreter.o limits.o magic.o mail.o mobact.o modify.o objsave.o olc.o shop.o spec_assign.o spec_procs.o spell_parser.o spells.o utils.o weather.o clan.o 
+ make[1]: Leaving directory `/home/circle30bpl11/src'
diff -c -P -x *.o orig-src/modify.c src/modify.c
*** orig-src/modify.c	Mon Feb 24 23:00:34 1997
--- src/modify.c	Mon Feb 24 16:17:27 1997
***************
*** 21,28 ****
--- 21,30 ----
  #include "spells.h"
  #include "mail.h"
  #include "boards.h"
+ #include "clan.h"
  
  void show_string(struct descriptor_data *d, char *input);
+ extern struct clan_editing clan_edit[];
  
  char *string_fields[] =
  {
***************
*** 54,60 ****
  /* Add user input to the 'current' string (as defined by d->str) */
  void string_add(struct descriptor_data *d, char *str)
  {
!   int terminator = 0;
    extern char *MENU;
  
    /* determine if this is the terminal string, and truncate if so */
--- 56,62 ----
  /* Add user input to the 'current' string (as defined by d->str) */
  void string_add(struct descriptor_data *d, char *str)
  {
!   int terminator = 0, i = 0;
    extern char *MENU;
  
    /* determine if this is the terminal string, and truncate if so */
***************
*** 94,99 ****
--- 96,102 ----
        d->mail_to = 0;
        free(*d->str);
        free(d->str);
+       if (STATE(d) != CON_CLAN_EDIT) /* (FIDO) No message if edit clan */
        SEND_TO_Q("Message sent!\r\n", d);
        if (!IS_NPC(d->character))
  	REMOVE_BIT(PLR_FLAGS(d->character), PLR_MAILING | PLR_WRITING);
***************
*** 104,109 ****
--- 107,123 ----
        Board_save_board(d->mail_to - BOARD_MAGIC);
        d->mail_to = 0;
      }
+     /* (FIDO) This handles cleaning up the mess of clan edits */
+     if (STATE(d) == CON_CLAN_EDIT)
+     {
+       for (i = 0; i < 10; i++)
+ 	if (CLAN_EDIT_DESC(i) == d)
+ 	{
+       	  CLAN_EDIT_MODE(i) = CLAN_EDIT_DESCRIPTION_FINISHED;
+       	  SEND_TO_Q("\r\n(s)ave (a)bort : ", d);
+ 	}
+     }
+ 
      if (d->connected == CON_EXDESC) {
        SEND_TO_Q(MENU, d);
        d->connected = CON_MENU;
diff -c -P -x *.o orig-src/spells.c src/spells.c
*** orig-src/spells.c	Mon Feb 24 23:00:35 1997
--- src/spells.c	Sun Feb  9 16:57:16 1997
***************
*** 32,37 ****
--- 32,41 ----
  
  extern int mini_mud;
  extern int pk_allowed;
+ extern int summon_allowed;
+ extern int sleep_allowed;
+ extern int charm_allowed;
+ extern int roomaffect_allowed;
  
  extern struct default_mobile_stats *mob_defaults;
  extern char weapon_verbs[];
***************
*** 132,138 ****
      return;
    }
  
!   if (!pk_allowed) {
      if (MOB_FLAGGED(victim, MOB_AGGRESSIVE)) {
        act("As the words escape your lips and $N travels\r\n"
  	  "through time and space towards you, you realize that $E is\r\n"
--- 136,143 ----
      return;
    }
  
!   /* (FIDO) Changed from pk_allowed to summon_allowed */
!   if (!summon_allowed) {
      if (MOB_FLAGGED(victim, MOB_AGGRESSIVE)) {
        act("As the words escape your lips and $N travels\r\n"
  	  "through time and space towards you, you realize that $E is\r\n"
***************
*** 227,234 ****
  
    if (victim == ch)
      send_to_char("You like yourself even better!\r\n", ch);
!   else if (!IS_NPC(victim) && !PRF_FLAGGED(victim, PRF_SUMMONABLE))
!     send_to_char("You fail because SUMMON protection is on!\r\n", ch);
    else if (IS_AFFECTED(victim, AFF_SANCTUARY))
      send_to_char("Your victim is protected by sanctuary!\r\n", ch);
    else if (MOB_FLAGGED(victim, MOB_NOCHARM))
--- 232,243 ----
  
    if (victim == ch)
      send_to_char("You like yourself even better!\r\n", ch);
!   else if (!IS_NPC(victim))
!     {
!       if (charm_allowed == 0)
!         if (!PRF_FLAGGED(victim, PRF_SUMMONABLE))
!           send_to_char("You fail because SUMMON protection is on!\r\n", ch);
!     }
    else if (IS_AFFECTED(victim, AFF_SANCTUARY))
      send_to_char("Your victim is protected by sanctuary!\r\n", ch);
    else if (MOB_FLAGGED(victim, MOB_NOCHARM))
***************
*** 238,244 ****
    else if (IS_AFFECTED(victim, AFF_CHARM) || level < GET_LEVEL(victim))
      send_to_char("You fail.\r\n", ch);
    /* player charming another player - no legal reason for this */
!   else if (!pk_allowed && !IS_NPC(victim))
      send_to_char("You fail - shouldn't be doing it anyway.\r\n", ch);
    else if (circle_follow(victim, ch))
      send_to_char("Sorry, following in circles can not be allowed.\r\n", ch);
--- 247,254 ----
    else if (IS_AFFECTED(victim, AFF_CHARM) || level < GET_LEVEL(victim))
      send_to_char("You fail.\r\n", ch);
    /* player charming another player - no legal reason for this */
!   /* (FIDO) Changed from pk_allowed to charm_allowed */
!   else if (!charm_allowed && !IS_NPC(victim))
      send_to_char("You fail - shouldn't be doing it anyway.\r\n", ch);
    else if (circle_follow(victim, ch))
      send_to_char("Sorry, following in circles can not be allowed.\r\n", ch);
diff -c -P -x *.o orig-src/structs.h src/structs.h
*** orig-src/structs.h	Mon Feb 24 23:00:35 1997
--- src/structs.h	Sat Feb 22 17:55:28 1997
***************
*** 173,179 ****
  #define PRF_NOGOSS	(1 << 19) /* Can't hear gossip channel		*/
  #define PRF_NOGRATZ	(1 << 20) /* Can't hear grats channel		*/
  #define PRF_ROOMFLAGS	(1 << 21) /* Can see room flags (ROOM_x)	*/
! 
  
  /* Affect bits: used in char_data.char_specials.saved.affected_by */
  /* WARNING: In the world files, NEVER set the bits marked "R" ("Reserved") */
--- 173,180 ----
  #define PRF_NOGOSS	(1 << 19) /* Can't hear gossip channel		*/
  #define PRF_NOGRATZ	(1 << 20) /* Can't hear grats channel		*/
  #define PRF_ROOMFLAGS	(1 << 21) /* Can see room flags (ROOM_x)	*/
! /* (FIDO) Clan talk channel pref */
! #define PRF_CLANTALK    (1 << 22) /* Can hear clan talk */
  
  /* Affect bits: used in char_data.char_specials.saved.affected_by */
  /* WARNING: In the world files, NEVER set the bits marked "R" ("Reserved") */
***************
*** 730,739 ****
     int spells_to_learn;		/* How many can you learn yet this level*/
     int spare7;
     int spare8;
!    int spare9;
!    int spare10;
!    int spare11;
!    int spare12;
     int spare13;
     int spare14;
     int spare15;
--- 731,740 ----
     int spells_to_learn;		/* How many can you learn yet this level*/
     int spare7;
     int spare8;
!    int clannum;			/* Index number of clan you belong to (FIDO) */
!    int spare10;	
!    int clanrank;                /* Rank within clan */
!    int spare12;		
     int spare13;
     int spare14;
     int spare15;
Common subdirectories: orig-src/util and src/util