1stMUD/corefiles/
1stMUD/gods/
1stMUD/log/
1stMUD/player/
1stMUD/win32/
1stMUD/win32/ROM/
diff -ur ./src/Makefile ./new/Makefile
--- ./src/Makefile	Fri May 16 00:04:53 2003
+++ ./new/Makefile	Fri May 16 01:57:25 2003
@@ -3,8 +3,8 @@
 WARN    = -Wall -Werror
 LIBS	= -lcrypt -lz
 #STRHASH: 0 = no string hashing.
-          1 = ROM fread_string() hashing only.
-	  2 = full string hashing
+#         1 = ROM fread_string() hashing only.
+#         2 = full string hashing
 D_FLAGS = -DSTRHASH=0 #-DNO_MCCP -DNO_WEB -DNOCRYPT
 C_FLAGS = $(WARN) $(PROF) $(D_FLAGS)
 L_FLAGS = $(PROF) $(LIBS)
diff -ur ./src/act_comm.c ./new/act_comm.c
--- ./src/act_comm.c	Fri May 16 00:04:56 2003
+++ ./new/act_comm.c	Fri May 16 02:11:34 2003
@@ -1874,9 +1874,10 @@
 	vsnprintf(buf2, sizeof(buf2), message, args);
 	va_end(args);
 
-	if (ch && IS_SET(bit, INFO_PRIVATE))
+	if (IS_SET(bit, INFO_PRIVATE))
 	{
-		Private = TRUE;
+		if (ch)
+			Private = TRUE;
 		REMOVE_BIT(bit, INFO_PRIVATE);
 	}
 
@@ -1913,7 +1914,7 @@
 				continue;
 
 			if (ch == NULL)
-				chprintf(och, "%s\n\r", buf);
+				chprintln(och, buf);
 			else
 				act_new(buf, ch, NULL, och, TO_VICT, POS_DEAD);
 		}
@@ -1925,7 +1926,7 @@
 			bug("NULL ch in private announce", 0);
 			return;
 		}
-		chprintf(ch, "%s\n\r", buf);
+		chprintln(ch, buf);
 	}
 	return;
 }
diff -ur ./src/act_info.c ./new/act_info.c
--- ./src/act_info.c	Fri May 16 00:04:56 2003
+++ ./new/act_info.c	Fri May 16 02:11:34 2003
@@ -265,7 +265,7 @@
 		strcat(buf, "({YGolden Aura{x) ");
 	if (IS_AFFECTED(victim, AFF_SANCTUARY))
 		strcat(buf, "({WWhite Aura{x) ");
-	if (!IS_NPC(victim) && IS_SET(victim->act, PLR_WAR))
+	if (IS_IN_WAR(victim))
 		strcat(buf, "({RWAR{x) ");
 	if (!IS_NPC(victim) && IS_SET(victim->act, PLR_KILLER))
 		strcat(buf, "({rKILLER{x) ");
@@ -276,7 +276,7 @@
 		strcat(buf, "{r[{RTARGET{r]{x ");
 
 	if (ON_GQUEST(ch) && IS_NPC(victim)
-		&& is_gqmob(ch, victim->pIndexData->vnum) != -1)
+		&& is_gqmob(ch->gquest, victim->pIndexData->vnum) != -1)
 	{
 		strcat(buf, "{Y({RGquest{Y){x ");
 	}
@@ -1454,7 +1454,7 @@
 	}
 
 	/* RT shows exp to level */
-	if (!IS_NPC(ch) && ch->level < LEVEL_HERO)
+	if (!IS_NPC(ch) && ch->level < calc_max_level(ch))
 	{
 		chprintlnf(ch,
 				   "" CTAG(_SCORE1) "You need " CTAG(_SCORE2) "%d"
@@ -2001,7 +2001,6 @@
 
 char *format_who(CHAR_DATA * ch, CHAR_DATA * wch)
 {
-	char const *Class;
 	char block[MIL];
 	static char buf[MSL];
 
@@ -2009,45 +2008,6 @@
 		return "ERROR";
 
 	/*
-	 * Figure out what to print for class.
-	 */
-	Class = class_who(wch);
-	switch (wch->level)
-	{
-	default:
-		break;
-		{
-	case MAX_LEVEL - 0:
-			Class = "IMP";
-			break;
-	case MAX_LEVEL - 1:
-			Class = "CRE";
-			break;
-	case MAX_LEVEL - 2:
-			Class = "SUP";
-			break;
-	case MAX_LEVEL - 3:
-			Class = "DEI";
-			break;
-	case MAX_LEVEL - 4:
-			Class = "GOD";
-			break;
-	case MAX_LEVEL - 5:
-			Class = "IMM";
-			break;
-	case MAX_LEVEL - 6:
-			Class = "DEM";
-			break;
-	case MAX_LEVEL - 7:
-			Class = "ANG";
-			break;
-	case MAX_LEVEL - 8:
-			Class = "AVA";
-			break;
-		}
-	}
-
-	/*
 	 * Format it up.
 	 */
 	if (wch->pcdata->who_descr[0] != '\0' && wch->pcdata->who_descr != NULL)
@@ -2055,16 +2015,16 @@
 				stringf(ch, 14, ALIGN_CENTER, NULL, wch->pcdata->who_descr));
 	else
 		sprintf(block,
-				"[" CTAG(_WLEVEL) "%03d " CTAG(_WRACE) "%6s " CTAG(_WCLASS)
-				"%s{x] ", wch->level, wch->race->who_name, Class);
+				"[" CTAG(_WLEVEL) "%3.3s " CTAG(_WRACE) "%4.4s " CTAG(_WCLASS)
+				"%3.3s{x] ", high_level_name(wch->level, FALSE),
+				wch->race->name, class_who(wch));
 
 	sprintf(buf, "%s%s%s%s%s%s%s%s%s%s%s%s\n\r", block,
 			wch->incog_level >= LEVEL_HERO ? "(Incog) " : "",
 			wch->invis_level >= LEVEL_HERO ? "(Wizi) " : "",
 			IS_SET(wch->comm, COMM_AFK) ? "[AFK] " : "",
 			IS_QUESTOR(wch) ? "[Q] " : "",
-			ON_GQUEST(wch) ? "(GQuest) " : "", IS_SET(wch->act,
-													  PLR_WAR) ? "(WAR) " :
+			ON_GQUEST(wch) ? "(GQuest) " : "", wch->war ? "(WAR) " :
 			"", IS_SET(wch->act, PLR_KILLER) ? "(KILLER) " : "",
 			IS_SET(wch->act, PLR_THIEF) ? "(THIEF) " : "", wch->name,
 			IS_NPC(wch) ? "" : wch->pcdata->title, format_clan(wch));
diff -ur ./src/act_obj.c ./new/act_obj.c
--- ./src/act_obj.c	Fri May 16 00:04:56 2003
+++ ./new/act_obj.c	Fri May 16 02:11:34 2003
@@ -815,7 +815,7 @@
 		return;
 	}
 
-	if (IS_OBJ_STAT(obj, ITEM_QUEST) && ch->level <= HERO)
+	if (IS_OBJ_STAT(obj, ITEM_QUEST) && ch->level <= MAX_MORTAL_LEVEL)
 	{
 		chprintln(ch, "You can't give quest items.");
 		return;
diff -ur ./src/act_wiz.c ./new/act_wiz.c
--- ./src/act_wiz.c	Fri May 16 00:04:56 2003
+++ ./new/act_wiz.c	Fri May 16 02:11:34 2003
@@ -1478,10 +1478,9 @@
 	chprintlnf(ch,
 			   "Vnum: %ld  Format: %s  Race: %s  Group: %d  Sex: %s  Room: %ld",
 			   IS_NPC(victim) ? victim->pIndexData->vnum : 0,
-			   IS_NPC(victim) ? victim->
-			   pIndexData->new_format ? "new" : "old" : "pc",
-			   victim->race->name, IS_NPC(victim) ? victim->group : 0,
-			   sex_table[victim->sex].name,
+			   IS_NPC(victim) ? victim->pIndexData->
+			   new_format ? "new" : "old" : "pc", victim->race->name,
+			   IS_NPC(victim) ? victim->group : 0, sex_table[victim->sex].name,
 			   victim->in_room == NULL ? 0 : victim->in_room->vnum);
 
 	if (IS_NPC(victim))
@@ -1955,13 +1954,12 @@
 		sprintf(buf, "Reboot by %s.", ch->name);
 		do_function(ch, &do_echo, buf);
 	}
-	if (war_info.iswar != WAR_OFF)
-		end_war();
 	while (auction_first != NULL)
 		reset_auc(auction_first, TRUE);
 	save_donation_pit();
 	merc_down = TRUE;
 	save_gquest_data();
+	save_war_data();
 	for (d = descriptor_first; d != NULL; d = d_next)
 	{
 		d_next = d->next;
@@ -1995,13 +1993,12 @@
 	{
 		do_function(ch, &do_echo, buf);
 	}
-	if (war_info.iswar != WAR_OFF)
-		end_war();
 	while (auction_first != NULL)
 		reset_auc(auction_first, TRUE);
 	save_donation_pit();
 	merc_down = TRUE;
 	save_gquest_data();
+	save_war_data();
 	for (d = descriptor_first; d != NULL; d = d_next)
 	{
 		d_next = d->next;
@@ -3401,8 +3398,7 @@
 
 		for (iClass = 0; iClass < maxClass; iClass++)
 		{
-			if (!str_prefix(arg4, class_table[iClass].name)
-				|| !str_cmp(arg4, class_table[iClass].who_name))
+			if (!str_prefix(arg4, class_table[iClass].name))
 			{
 				value = iClass;
 				break;
@@ -4087,8 +4083,8 @@
 			count++;
 			sprintf(buf + strlen(buf), "[%3d %2d] %s@%s\n\r",
 					d->descriptor, d->connected,
-					d->original ? d->original->name : d->
-					character ? d->character->name : "(none)", d->host);
+					d->original ? d->original->name : d->character ? d->
+					character->name : "(none)", d->host);
 		}
 	}
 	if (count == 0)
@@ -4168,7 +4164,7 @@
 			vch_next = vch->next;
 
 			if (!IS_NPC(vch) && get_trust(vch) < get_trust(ch) &&
-				vch->level < LEVEL_HERO)
+				vch->level < MAX_MORTAL_LEVEL)
 			{
 				act(buf, ch, NULL, vch, TO_VICT);
 				interpret(vch, argument);
@@ -4191,7 +4187,7 @@
 			vch_next = vch->next;
 
 			if (!IS_NPC(vch) && get_trust(vch) < get_trust(ch) &&
-				vch->level >= LEVEL_HERO)
+				vch->level >= MAX_MORTAL_LEVEL)
 			{
 				act(buf, ch, NULL, vch, TO_VICT);
 				interpret(vch, argument);
@@ -4430,9 +4426,7 @@
 	do_asave(NULL, "changed");
 
 	save_gquest_data();
-
-	if (war_info.iswar != WAR_OFF)
-		end_war();
+	save_war_data();
 
 	while (auction_first != NULL)
 		reset_auc(auction_first, TRUE);
diff -ur ./src/alias.c ./new/alias.c
--- ./src/alias.c	Fri May 16 00:04:56 2003
+++ ./new/alias.c	Fri May 16 02:11:34 2003
@@ -32,6 +32,7 @@
 #include <time.h>
 #include "merc.h"
 #include "interp.h"
+#include "proto.h"
 
 /* does aliasing and other fun stuff */
 void substitute_alias(DESCRIPTOR_DATA * d, char *argument)
@@ -47,7 +48,7 @@
 	/* check for prefix */
 	if (ch->prefix[0] != '\0' && str_prefix("prefix", argument))
 	{
-		if (strlen(ch->prefix) + strlen(argument) > MAX_INPUT_LENGTH)
+		if (strlen(ch->prefix) + strlen(argument) > MAX_INPUT_LENGTH - 2)
 			chprintln(ch, "Line to long, prefix not processed.");
 		else
 		{
@@ -60,7 +61,8 @@
 		!str_prefix("alias", argument) || !str_prefix("una", argument)
 		|| !str_prefix("prefix", argument))
 	{
-		interpret(d->character, argument);
+		if (!run_olc_editor(d, argument))
+			interpret(d->character, argument);
 		return;
 	}
 
@@ -78,9 +80,11 @@
 			{
 				buf[0] = '\0';
 				strcat(buf, ch->pcdata->alias_sub[alias]);
-				strcat(buf, " ");
-				strcat(buf, point);
-
+				if (point[0])
+				{
+					strcat(buf, " ");
+					strcat(buf, point);
+				}
 				if (strlen(buf) > MAX_INPUT_LENGTH - 1)
 				{
 					chprintln(ch, "Alias substitution too long. Truncated.");
@@ -90,7 +94,8 @@
 			}
 		}
 	}
-	interpret(d->character, buf);
+	if (!run_olc_editor(d, buf))
+		interpret(d->character, buf);
 }
 
 CH_CMD(do_alia)
diff -ur ./src/board.c ./new/board.c
--- ./src/board.c	Fri May 16 00:04:56 2003
+++ ./new/board.c	Fri May 16 02:11:34 2003
@@ -657,10 +657,10 @@
 			has_shown++;		/* note that we want to see X VISIBLE note, not just last X */
 			if (!show || ((count - show) < has_shown))
 			{
-				chprintlnf(ch, "{W%3d{x>{B%c{Y%-13s{y %s{x",
-						   num,
-						   last_note < p->date_stamp ? '*' : ' ',
-						   p->sender, p->subject);
+				chprintf(ch, "{W%3d{x>{B%c{Y%-13s{y %s{x",
+						 num,
+						 last_note < p->date_stamp ? '*' : ' ',
+						 p->sender, p->subject);
 			}
 		}
 
diff -ur ./src/clans.c ./new/clans.c
--- ./src/clans.c	Fri May 16 00:04:56 2003
+++ ./new/clans.c	Fri May 16 02:11:34 2003
@@ -330,8 +330,8 @@
 			{
 				chprintlnf(ch, "%-12s %-8s %s", victim->name,
 						   position_table[victim->position].name,
-						   victim->in_room ? victim->in_room->area->
-						   name : "Unknown");
+						   victim->in_room ? victim->in_room->
+						   area->name : "Unknown");
 				found = TRUE;
 			}
 		}
diff -ur ./src/comm.c ./new/comm.c
--- ./src/comm.c	Fri May 16 00:04:56 2003
+++ ./new/comm.c	Fri May 16 02:11:34 2003
@@ -649,8 +649,7 @@
 					switch (d->connected)
 					{
 					case CON_PLAYING:
-						if (!run_olc_editor(d))
-							substitute_alias(d, d->incomm);
+						substitute_alias(d, d->incomm);
 						break;
 					default:
 						nanny(d, d->incomm);
@@ -1510,12 +1509,21 @@
 			}
 
 			ch = d->original ? d->original : d->character;
-			if (!IS_SET(ch->comm, COMM_COMPACT))
+			if (!IS_SET(ch->comm, COMM_COMPACT)
+				&& (d->fcommand || ch->fighting || d->editor > 0))
 				write_to_buffer(d, "\n\r", 2);
 
 			if (IS_SET(ch->comm, COMM_PROMPT))
-				bust_a_prompt(d->character);
-
+			{
+				if ((d->fcommand && !d->run_buf) || ch->fighting)
+					bust_a_prompt(d->character);
+				else if (d->editor > 0)
+				{
+					chprintlnf(ch, "{cOLC %s : {W%s{x",
+							   olc_ed_name(d->character),
+							   olc_ed_vnum(d->character));
+				}
+			}
 			if (IS_SET(ch->comm, COMM_TELNET_GA))
 			{
 				write_to_buffer(d, go_ahead_str, 0);
@@ -1681,8 +1689,8 @@
 						((!IS_NPC(ch) &&
 						  IS_SET(ch->act, PLR_HOLYLIGHT)) ||
 						 (!IS_AFFECTED(ch, AFF_BLIND) &&
-						  !room_is_dark(ch->in_room))) ? ch->in_room->
-						name : "darkness");
+						  !room_is_dark(ch->in_room))) ? ch->
+						in_room->name : "darkness");
 			else
 				sprintf(buf2, " ");
 			i = buf2;
@@ -1695,10 +1703,10 @@
 			i = buf2;
 			break;
 		case 'Q':
-			if (ON_GQUEST(ch))
+			if (gquest_info.running != GQUEST_OFF)
 				sprintf(buf2, "%d", gquest_info.timer);
 			else
-				sprintf(buf2, "%dn", gquest_info.next);
+				sprintf(buf2, "%dn", gquest_info.timer);
 			i = buf2;
 			break;
 
@@ -1983,8 +1991,8 @@
 			dold->connected != CON_GET_NAME &&
 			dold->connected != CON_GET_OLD_PASSWORD &&
 			!str_cmp(name,
-					 dold->original ? dold->original->name : dold->character->
-					 name))
+					 dold->original ? dold->original->name : dold->
+					 character->name))
 		{
 			write_to_buffer(d, "That character is already playing.\n\r", 0);
 			write_to_buffer(d, "Do you wish to connect anyway (Y/N)?", 0);
@@ -2038,23 +2046,47 @@
  */
 void page_to_char(const char *txt, CHAR_DATA * ch)
 {
-	if (txt == NULL || ch->desc == NULL)
+	DESCRIPTOR_DATA *d;
+
+	if (txt == NULL || (d = ch->desc) == NULL)
 		return;
 
 	if (ch->lines == 0)
 	{
-		chprint(ch, txt);
+		write_to_buffer(d, txt, strlen(txt));
 		return;
 	}
 
-	alloc_mem(ch->desc->showstr_head, char, strlen(txt) + 1);
-	strcpy((char *) ch->desc->showstr_head, txt);
-	ch->desc->showstr_point = ch->desc->showstr_head;
-	show_string(ch->desc, "");
+	/*
+	 * If there is already some data being "paged" for this descriptor,
+	 * append the new string.
+	 */
+	if (!IS_NULLSTR(d->showstr_head))
+	{
+		char *fub;
+		int i;
+		int size_new = strlen(txt) + strlen(d->showstr_head) + 2;
+
+		alloc_mem(fub, char, size_new);
+		fub[0] = '\0';
+		strncat(fub, d->showstr_head, size_new);
+		i = strlen(fub) - strlen(d->showstr_point);
+		strncat(fub, txt, size_new);
+
+		replace_string(d->showstr_head, fub);
+		d->showstr_point = d->showstr_head + i;
+		free_mem(fub);
+		return;
+	}
+
+	replace_string(d->showstr_head, txt);
+	d->showstr_point = d->showstr_head;
+	show_string(d, "");
+	return;
 }
 
 /* string pager */
-void show_string(struct descriptor_data *d, char *input)
+void show_string(DESCRIPTOR_DATA * d, char *input)
 {
 	char buffer[MAX_STRING_LENGTH * 3];
 	char buf[MAX_INPUT_LENGTH];
@@ -2699,7 +2731,18 @@
 	log_string(buf);
 }
 
-#if !defined(WIN32)
+void update_last_func(DESCRIPTOR_DATA * d, const char *lstr, const char *sstr)
+{
+#if !defined(WIN32) && !defined(__CYGWIN__)
+	last_descriptor = d;
+	if (lstr != NULL)
+		strcpy(last_func_long, lstr);
+	if (sstr != NULL)
+		strcpy(last_func_short, sstr);
+#endif
+}
+
+#if !defined(WIN32) && !defined(__CYGWIN__)
 
 #define	CORE_EXAMINE_SCRIPT	"../corefiles/gdbscript"
 
@@ -2707,30 +2750,35 @@
 {
 	DESCRIPTOR_DATA *d;
 	CHAR_DATA *ch;
-	extern char last_command2[MAX_INPUT_LENGTH];
-	extern DESCRIPTOR_DATA *last_descriptor;
 	struct sigaction default_action;
 	int i;
 	pid_t forkpid;
 	int status;
+	char message[MSL];
 
 	waitpid(-1, &status, WNOHANG);
 	if (!crashed)
 	{
 		crashed++;
 		logf("GAME CRASHED (SIGNAL %d, %s).", sig, strsignal(sig));
-		logf("Last command: %s", last_command);
+		logf("Last recored function: %s", last_func_long);
 		// Inform last command typer that he caused the crash
-		if (!IS_NULLSTR(last_command2))
+		if (last_descriptor && !IS_NULLSTR(last_func_short))
 		{
 			write_to_descriptor(last_descriptor,
 								"\n\rThe last command you typed, '", 0);
-			write_to_descriptor(last_descriptor, last_command2, 0);
+			write_to_descriptor(last_descriptor, last_func_short, 0);
 			write_to_descriptor(last_descriptor,
 								"', might have caused this crash.\n\r"
 								"Please note any unusual circumstances to IMP and avoid using that command.\n\r",
 								0);
 		}
+		sprintf(message,
+				"\n\r---CRASH INFORMATION---\n\rSignal %d (%s)\n\rLast recorded function: %s\n\rDetails: %s\n\n",
+				sig, strsignal(sig),
+				!IS_NULLSTR(last_func_short) ? last_func_short : "<unknown>",
+				last_func_long);
+
 		for (d = descriptor_first; d != NULL; d = d_next)
 		{
 			d_next = d->next;
@@ -2743,12 +2791,15 @@
 			if (IS_NPC(ch))
 				continue;
 
-			if ((sig == SIGVTALRM || sig == SIGALRM)
-				&& get_trust(ch) >= LEVEL_IMMORTAL)
+			if ((sig == SIGVTALRM || sig == SIGALRM) && IS_IMMORTAL(ch))
 				write_to_descriptor(d,
 									"\n\rThe mud has been unresponsive for 60 seconds.  Rebooting.\n\r",
 									0);
+
 			write_to_descriptor(d, "\n\rThe mud has CRASHED.\007\n\r", 0);
+
+			if (IS_IMMORTAL(ch))
+				write_to_descriptor(d, message, 0);
 		}
 
 		// try to save all characters - save_char_obj has sanity checking
diff -ur ./src/db.c ./new/db.c
--- ./src/db.c	Fri May 16 00:04:56 2003
+++ ./new/db.c	Fri May 16 02:11:34 2003
@@ -196,7 +196,6 @@
 
 	}
 
-	end_war();
 	log_string("Loading skills...");
 	load_skills();
 	log_string("Loading groups...");
@@ -337,6 +336,7 @@
 		log_string("Loading socials...");
 		load_social_table();
 		load_gquest_data();
+		load_war_data();
 		log_string("Loading commands...");
 		load_commands();
 		load_corpses();
@@ -1615,7 +1615,7 @@
 			char_to_room(pMob, pRoom);
 
 			LastMob = pMob;
-			level = URANGE(0, pMob->level - 2, LEVEL_HERO - 1);	/* -1 ROM */
+			level = URANGE(0, pMob->level - 2, MAX_MORTAL_LEVEL - 1);	/* -1 ROM */
 			last = TRUE;
 			break;
 
@@ -1646,7 +1646,8 @@
 			}
 
 			pObj = create_object(pObjIndex,	/* UMIN - ROM OLC */
-								 UMIN(number_fuzzy(level), LEVEL_HERO - 1));
+								 UMIN(number_fuzzy(level),
+									  MAX_MORTAL_LEVEL - 1));
 			pObj->cost = 0;
 			obj_to_room(pObj, pRoom);
 			last = TRUE;
@@ -1788,7 +1789,7 @@
 					pObj =
 						create_object(pObjIndex,
 									  UMIN(number_fuzzy
-										   (level), LEVEL_HERO - 1));
+										   (level), MAX_MORTAL_LEVEL - 1));
 					/* error message if it is too high 
 					   if (pObj->level > LastMob->level + 3
 					   ||  (pObj->item_type == ITEM_WEAPON 
diff -ur ./src/db2.c ./new/db2.c
--- ./src/db2.c	Fri May 16 00:04:56 2003
+++ ./new/db2.c	Fri May 16 02:11:34 2003
@@ -1630,7 +1630,7 @@
 	else if (is_name("IMM", arg))
 		return LEVEL_IMMORTAL;
 	else if (is_name("HERO", arg) || is_name("HRO", arg))
-		return LEVEL_HERO;
+		return MAX_MORTAL_LEVEL;
 	else
 		return 0;
 }
diff -ur ./src/fight.c ./new/fight.c
--- ./src/fight.c	Fri May 16 00:04:56 2003
+++ ./new/fight.c	Fri May 16 02:11:34 2003
@@ -1898,17 +1898,15 @@
 
 		if (IS_NPC(victim) && !IS_NPC(ch) &&
 			gquest_info.running == GQUEST_RUNNING && ON_GQUEST(ch) &&
-			(i = is_gqmob(ch, victim->pIndexData->vnum)) != -1)
+			(i = is_gqmob(ch->gquest, victim->pIndexData->vnum)) != -1)
 		{
-			ch->pcdata->gq_mobs[i] = -1;
+			ch->gquest->gq_mobs[i] = -1;
 			chprintln
 				(ch,
 				 "Congratulations, that that mob was part of your global quest!");
-			chprintln(ch, "You receive an extra 3 Quest Points");
+			chprint(ch, "You receive an extra 3 Quest Points");
 			ch->pcdata->questpoints += 3;
-			if (chance
-				((MAX_GQUEST_MOB - gquest_info.mob_count) / 2 +
-				 gquest_info.mob_count))
+			if (chance(URANGE(5, gquest_info.mob_count, 95)))
 			{
 				chprintln(ch, " and a Trivia Point!");
 				ch->pcdata->trivia += 1;
@@ -1920,7 +1918,7 @@
 					victim->short_descr);
 			wiznet(buf, ch, NULL, 0, 0, 0);
 
-			if (count_gqmobs(ch) == gquest_info.mob_count)
+			if (count_gqmobs(ch->gquest) == gquest_info.mob_count)
 				chprintln(ch,
 						  "You are now ready to complete the global quest. Type 'GQUEST COMPLETE' to finish.");
 		}
@@ -3112,9 +3110,8 @@
 		if ((pexit = was_in->exit[door]) == 0 || pexit->u1.to_room == NULL
 			|| IS_SET(pexit->exit_info, EX_CLOSED) ||
 			number_range(0, ch->daze) != 0 || (IS_NPC(ch) &&
-											   IS_SET(pexit->u1.
-													  to_room->room_flags,
-													  ROOM_NO_MOB)))
+											   IS_SET(pexit->u1.to_room->
+													  room_flags, ROOM_NO_MOB)))
 			continue;
 
 		move_char(ch, door, FALSE);
diff -ur ./src/gquest.c ./new/gquest.c
--- ./src/gquest.c	Fri May 16 00:04:56 2003
+++ ./new/gquest.c	Fri May 16 02:11:34 2003
@@ -122,10 +122,10 @@
 		return FALSE;
 	}
 
-	if (mobs < 5 || mobs >= MAX_GQUEST_MOB)
+	if (mobs < 5 || mobs > (IS_IMMORTAL(ch) ? (mobile_count / 2) : 25))
 	{
 		chprintlnf(ch, "Number of mobs must be between 5 and %d.",
-				   MAX_GQUEST_MOB - 1);
+				   IS_IMMORTAL(ch) ? (mobile_count / 2) : 25);
 		return FALSE;
 	}
 
@@ -182,7 +182,7 @@
 void auto_gquest(void)
 {
 	CHAR_DATA *wch = NULL, *registar = NULL;
-	int middle = LEVEL_HERO / 2, maxlvl = 0;
+	int middle = MAX_MORTAL_LEVEL / 2, maxlvl = 0;
 	int minlvl = MAX_LEVEL, count = 0, lbonus = 0, half = 0;
 
 	if (gquest_info.running != GQUEST_OFF)
@@ -206,7 +206,7 @@
 	/* all this is basically so level ranges aren't to far apart */
 	lbonus = number_range(5, 10);
 	minlvl = UMAX(1, minlvl - lbonus);
-	maxlvl = UMIN(LEVEL_HERO, maxlvl + lbonus);
+	maxlvl = UMIN(MAX_MORTAL_LEVEL, maxlvl + lbonus);
 	half = ((maxlvl - minlvl) / 2);
 	middle = URANGE(minlvl, maxlvl - half, maxlvl);
 	minlvl = number_range(minlvl, middle - lbonus);
@@ -220,9 +220,9 @@
 			break;
 	}
 	gquest_info.running = GQUEST_WAITING;
-	gquest_info.mob_count = number_range(5, MAX_GQUEST_MOB - lbonus);
+	gquest_info.mob_count = number_range(5, 30 - lbonus);
 	gquest_info.minlevel = UMAX(1, minlvl);
-	gquest_info.maxlevel = UMIN(LEVEL_HERO, maxlvl);
+	gquest_info.maxlevel = UMIN(MAX_MORTAL_LEVEL, maxlvl);
 	free_string(gquest_info.who);
 	gquest_info.who =
 		!registar ? str_dup("AutoQuest (tm)") : str_dup(registar->short_descr);
@@ -233,7 +233,7 @@
 void post_gquest(CHAR_DATA * ch)
 {
 	BUFFER *output;
-	CHAR_DATA *wch;
+	GQ_LIST *gql;
 	MOB_INDEX_DATA *mob;
 	int i;
 	GQUEST_HIST *hist;
@@ -259,11 +259,10 @@
 	add_buf(output, buf);
 	sprintf(buf, "Those Playing\n\r-------------\n\r");
 	add_buf(output, buf);
-	for (wch = char_first; wch != NULL; wch = wch->next)
-		if (!IS_NPC(wch) && ON_GQUEST(wch)
-			&& count_gqmobs(wch) != gquest_info.mob_count)
-			sprintf(buf, "%s [%d mobs left]\n\r", wch->name,
-					gquest_info.mob_count - count_gqmobs(wch));
+	for (gql = gquest_info.first; gql != NULL; gql = gql->next)
+		if (gql->ch != ch)
+			sprintf(buf, "%s [%d mobs left]\n\r", gql->ch->name,
+					gquest_info.mob_count - count_gqmobs(gql));
 	add_buf(output, buf);
 	sprintf(buf, "%s won the GQuest.\n\r", ch->name);
 	add_buf(output, buf);
@@ -291,6 +290,33 @@
 	return;
 }
 
+void new_gqlist(CHAR_DATA * ch)
+{
+	GQ_LIST *gql;
+	int i;
+
+	if (!ch)
+		return;
+
+	alloc_mem(gql, GQ_LIST, 1);
+	alloc_mem(gql->gq_mobs, vnum_t, gquest_info.mob_count);
+	for (i = 0; i < gquest_info.mob_count; i++)
+		gql->gq_mobs[i] = gquest_info.mobs[i];
+	gql->ch = ch;
+	ch->gquest = gql;
+	LINK(gql, gquest_info.first, gquest_info.last, next, prev);
+	return;
+}
+
+void free_gqlist(GQ_LIST * gql)
+{
+	free_mem(gql->gq_mobs);
+	gql->ch->gquest = NULL;
+	gql->ch = NULL;
+	UNLINK(gql, gquest_info.first, gquest_info.last, next, prev);
+	free_mem(gql);
+}
+
 CH_CMD(do_gquest)
 {
 	char arg1[MAX_INPUT_LENGTH];
@@ -298,6 +324,7 @@
 	CHAR_DATA *wch;
 	MOB_INDEX_DATA *mob;
 	int i = 0;
+	BUFFER *output;
 
 	if (IS_NPC(ch))
 	{
@@ -341,9 +368,9 @@
 		}
 
 		i = is_number(argument) ? atoi(argument) : number_range(30, 100);
-		gquest_info.next = i;
+		gquest_info.timer = i;
 		chprintlnf(ch, "The next gquest will start in %d minutes.",
-				   gquest_info.next);
+				   gquest_info.timer);
 		return;
 	}
 	else if (!str_prefix(arg1, "hist"))
@@ -357,10 +384,10 @@
 			return;
 		}
 
+		output = new_buf();
+
 		if (argument[0] == '\0')
 		{
-			BUFFER *output = new_buf();
-
 			add_buf(output,
 					"Num Finished Time            Levels  Mobs Completed by\n\r"
 					"--- ------------------------ ------- ---- ------------\n\r");
@@ -371,8 +398,6 @@
 				add_buf(output, hist->short_descr);
 			}
 			add_buf(output, "Type 'gquest hist #' to view details.\n\r");
-			page_to_char(buf_string(output), ch);
-			free_buf(output);
 		}
 		else
 		{
@@ -387,20 +412,22 @@
 			for (hist = gqhist_first; hist != NULL; hist = hist->next)
 				if (++count == atoi(argument))
 				{
-					chprint(ch, hist->text);
+					add_buf(output, hist->text);
 					found = TRUE;
 				}
 
 			if (!found)
-				chprintln(ch, "History data not found.");
+				add_buf(output, "History data not found.");
 		}
+		page_to_char(buf_string(output), ch);
+		free_buf(output);
 		return;
 	}
 	else if (gquest_info.running == GQUEST_OFF)
 	{
 		chprintlnf(ch,
 				   "There is no global quest running.  The next Gquest will start in %d minutes.",
-				   gquest_info.next);
+				   gquest_info.timer);
 		return;
 	}
 	else if (!str_prefix(arg1, "end") && IS_IMMORTAL(ch))
@@ -408,10 +435,10 @@
 		end_gquest(gquest_info.last_registar);
 		chprintlnf(ch,
 				   "You end the global quest. Next autoquest in %d minutes.",
-				   gquest_info.next);
+				   gquest_info.timer);
 		announce(ch, INFO_GQUEST,
 				 "$n has ended the global quest. Next gquest in %d minutes.",
-				 gquest_info.next);
+				 gquest_info.timer);
 		return;
 	}
 	else if (!str_prefix(arg1, "join"))
@@ -435,23 +462,14 @@
 			return;
 		}
 
-		if (!IS_NPC(ch) && IS_SET(ch->act, PLR_WAR))
+		if (ch->war)
 		{
 			chprintlnf(ch, "Your %s combat right now.\n\r",
-					   war_info.iswar == WAR_WAITING ? "waiting for" : "in");
-			return;
-		}
-
-		/* slight hack here */
-		if (count_gqmobs(ch) == gquest_info.mob_count)
-		{
-			chprintln(ch, "You have already quit this gquest.");
+					   war_info.status == WAR_WAITING ? "waiting for" : "in");
 			return;
 		}
 
-		for (i = 0; i < gquest_info.mob_count; i++)
-			ch->pcdata->gq_mobs[i] = gquest_info.mobs[i];
-		SET_BIT(ch->act, PLR_GQUEST);
+		new_gqlist(ch);
 		gquest_info.involved++;
 		chprintln
 			(ch,
@@ -466,9 +484,7 @@
 			chprintln(ch, "Your not in a global quest.");
 			return;
 		}
-		/* hack to prevent coming back */
-		reset_gqmob(ch, -1);
-		REMOVE_BIT(ch->act, PLR_GQUEST);
+		free_gqlist(ch->gquest);
 		gquest_info.involved--;
 		chprintln(ch,
 				  "Your global quest flag is now off. Sorry you couldn't complete it.");
@@ -478,39 +494,50 @@
 	}
 	else if (!str_prefix(arg1, "info"))
 	{
-		chprintln(ch, "[ GLOBAL QUEST INFO ]");
-		chprintlnf(ch, "Started by  : %s",
-				   gquest_info.who[0] == '\0' ? "Unknown" : gquest_info.who);
-		chprintlnf(ch, "Playing     : %d player%s.",
-				   gquest_info.involved, gquest_info.involved == 1 ? "" : "s");
-		chprintlnf(ch, "Levels      : %d - %d", gquest_info.minlevel,
-				   gquest_info.maxlevel);
-		chprintlnf(ch, "Status      : %s for %d minute%s.",
-				   gquest_info.running ==
-				   GQUEST_WAITING ? "Waiting" : "Running",
-				   gquest_info.timer, gquest_info.timer == 1 ? "" : "s");
-		chprintln(ch, "[ Quest Rewards ]");
-		chprintlnf(ch, "Qp Reward   : %d", gquest_info.qpoints);
-		chprintlnf(ch, "Gold Reward : %d", gquest_info.gold);
-		chprintln(ch, "[ Quest Targets ]");
+		output = new_buf();
+
+		add_buf(output, "[ GLOBAL QUEST INFO ]\n\r");
+		sprintf(buf, "Started by  : %s\n\r",
+				gquest_info.who[0] == '\0' ? "Unknown" : gquest_info.who);
+		add_buf(output, buf);
+		sprintf(buf, "Playing     : %d player%s.\n\r",
+				gquest_info.involved, gquest_info.involved == 1 ? "" : "s");
+		add_buf(output, buf);
+		sprintf(buf, "Levels      : %d - %d\n\r", gquest_info.minlevel,
+				gquest_info.maxlevel);
+		add_buf(output, buf);
+		sprintf(buf, "Status      : %s for %d minute%s.\n\r",
+				gquest_info.running ==
+				GQUEST_WAITING ? "Waiting" : "Running",
+				gquest_info.timer, gquest_info.timer == 1 ? "" : "s");
+		add_buf(output, buf);
+		add_buf(output, "[ Quest Rewards ]\n\r");
+		sprintf(buf, "Qp Reward   : %d\n\r", gquest_info.qpoints);
+		add_buf(output, buf);
+		sprintf(buf, "Gold Reward : %d\n\r", gquest_info.gold);
+		add_buf(output, buf);
+		add_buf(output, "[ Quest Targets ]\n\r");
 		for (i = 0; i < gquest_info.mob_count; i++)
 		{
 			if ((mob = get_mob_index(gquest_info.mobs[i])) != NULL)
 			{
-				chprintlnf(ch,
-						   "%2d) [%-20s] %-30s (level %3d)",
-						   i + 1, mob->area->name,
-						   smash_colour(mob->short_descr), mob->level);
+				sprintf(buf,
+						"%2d) [%-20s] %-30s (level %3d)\n\r",
+						i + 1, mob->area->name,
+						smash_colour(mob->short_descr), mob->level);
+				add_buf(output, buf);
 			}
 		}
+		page_to_char(buf_string(output), ch);
+		free_buf(output);
 		return;
 	}
 	else if (!str_prefix(arg1, "time"))
 	{
-		if (gquest_info.next > 0)
+		if (gquest_info.running == GQUEST_OFF)
 			sprintf(buf,
 					"THe next Global Quest will start in %d minute%s.\n\r",
-					gquest_info.next, gquest_info.next == 1 ? "" : "s");
+					gquest_info.timer, gquest_info.timer == 1 ? "" : "s");
 		else
 			chprintlnf(ch, "The Global Quest is %s for %d minute%s.",
 					   gquest_info.running ==
@@ -520,26 +547,28 @@
 	}
 	else if (!str_prefix(arg1, "progress"))
 	{
+		GQ_LIST *gql;
 
-		if (gquest_info.running == GQUEST_WAITING)
+		if (gquest_info.running != GQUEST_RUNNING)
 		{
 			chprintln(ch, "The global quest hasn't started yet.");
 			return;
 		}
-		for (wch = char_first; wch != NULL; wch = wch->next)
+		for (gql = gquest_info.first; gql != NULL; gql = gql->next)
 		{
-			if (!IS_NPC(wch) && ON_GQUEST(wch) && wch != ch)
+			if (gql->ch != ch)
 			{
 				chprintlnf(ch, "%-12s has %d of %d mobs left.",
-						   wch->name,
+						   gql->ch->name,
 						   gquest_info.mob_count -
-						   count_gqmobs(wch), gquest_info.mob_count);
+						   count_gqmobs(gql), gquest_info.mob_count);
 			}
 		}
 		return;
 	}
 	else if (!str_prefix(arg1, "check"))
 	{
+		int count = 0;
 
 		if (IS_IMMORTAL(ch) && argument[0] != '\0')
 		{
@@ -559,35 +588,42 @@
 			return;
 		}
 
-		chprintlnf(ch, "[ %s have %d of %d mobs left ]",
-				   wch == ch ? "You" : wch->name,
-				   gquest_info.mob_count - count_gqmobs(wch),
-				   gquest_info.mob_count);
+		output = new_buf();
+		sprintf(buf, "[ %s have %d of %d mobs left ]\n\r",
+				wch == ch ? "You" : wch->name,
+				gquest_info.mob_count - count_gqmobs(wch->gquest),
+				gquest_info.mob_count);
+		add_buf(output, buf);
 		for (i = 0; i < gquest_info.mob_count; i++)
 		{
-			if ((mob = get_mob_index(wch->pcdata->gq_mobs[i])) != NULL)
+			if ((mob = get_mob_index(wch->gquest->gq_mobs[i])) != NULL)
 			{
-				chprintlnf(ch,
-						   "%2d) [%-20s] %-30s (level %3d)",
-						   i + 1, mob->area->name, mob->short_descr,
-						   mob->level);
+				count++;
+				sprintf(buf,
+						"%2d) [%-20s] %-30s (level %3d)\n\r",
+						count, mob->area->name, mob->short_descr, mob->level);
+				add_buf(output, buf);
 			}
 		}
+		page_to_char(buf_string(output), ch);
+		free_buf(output);
 		return;
 	}
 	else if (!str_prefix(arg1, "complete"))
 	{
+		int mobs;
+
 		if (!ON_GQUEST(ch))
 		{
 			chprintln(ch, "Your not in a global quest.");
 			return;
 		}
 
-		if (count_gqmobs(ch) != gquest_info.mob_count)
+		if ((mobs = count_gqmobs(ch->gquest)) != gquest_info.mob_count)
 		{
 			chprintlnf(ch,
 					   "You haven't finished just yet, theres still %d mobs to kill.",
-					   gquest_info.mob_count - count_gqmobs(ch));
+					   gquest_info.mob_count - mobs);
 			return;
 		}
 		chprintln(ch, "YES! You have completed the global quest.");
@@ -599,7 +635,7 @@
 		end_gquest(gquest_info.last_registar);
 		sprintf(buf,
 				"$n has completed the global quest, next gquest in %d minutes.",
-				gquest_info.next);
+				gquest_info.timer);
 		announce(ch, INFO_GQUEST, buf);
 		return;
 	}
@@ -610,39 +646,34 @@
 
 void end_gquest(CHAR_DATA * who)
 {
-	CHAR_DATA *wch;
+	GQ_LIST *gql, *gql_next;
 
 	gquest_info.running = GQUEST_OFF;
 	free_string(gquest_info.who);
 	gquest_info.who = str_dup("");
 	gquest_info.mob_count = 0;
-	gquest_info.timer = 0;
+	gquest_info.timer = number_range(100, 200);
 	gquest_info.involved = 0;
 	gquest_info.qpoints = 0;
 	gquest_info.gold = 0;
 	gquest_info.minlevel = 0;
 	gquest_info.maxlevel = 0;
-	gquest_info.next = number_range(100, 200);
-	reset_gqmob(NULL, 0);
+	if (gquest_info.mobs)
+		free_mem(gquest_info.mobs);
 	gquest_info.last_registar = who;
 
-	for (wch = char_first; wch != NULL; wch = wch->next)
+	for (gql = gquest_info.first; gql != NULL; gql = gql_next)
 	{
-		if (!IS_NPC(wch) && IS_SET(wch->act, PLR_GQUEST))
-		{
-			REMOVE_BIT(wch->act, PLR_GQUEST);
-			reset_gqmob(wch, 0);
-		}
+		gql_next = gql->next;
+		free_gqlist(gql);
 	}
 }
 
 void gquest_update(void)
 {
-	char buf[MSL];
-
 	if (gquest_info.running == GQUEST_OFF)
 	{
-		if (--gquest_info.next <= 0)
+		if (--gquest_info.timer <= 0)
 			auto_gquest();
 	}
 
@@ -653,22 +684,19 @@
 
 		if (gquest_info.timer > 0)
 		{
-			sprintf(buf,
-					"%d minute%s left to join the global quest. (Levels %d - %d)",
-					gquest_info.timer,
-					gquest_info.timer == 1 ? "" : "s",
-					gquest_info.minlevel, gquest_info.maxlevel);
-			announce(NULL, INFO_GQUEST, buf);
+			announce(NULL, INFO_GQUEST,
+					 "%d minute%s left to join the global quest. (Levels %d - %d)",
+					 gquest_info.timer, gquest_info.timer == 1 ? "" : "s",
+					 gquest_info.minlevel, gquest_info.maxlevel);
 		}
 		else
 		{
 			if (gquest_info.involved == 0)
 			{
 				end_gquest(gquest_info.last_registar);
-				sprintf(buf,
-						"Not enough people for the global quest. The next quest will start in %d minutes.",
-						gquest_info.next);
-				announce(NULL, INFO_GQUEST, buf);
+				announce(NULL, INFO_GQUEST,
+						 "Not enough people for the global quest. The next quest will start in %d minutes.",
+						 gquest_info.timer);
 			}
 			else
 			{
@@ -676,10 +704,9 @@
 					number_range(4 * gquest_info.mob_count,
 								 6 * gquest_info.mob_count);
 				gquest_info.running = GQUEST_RUNNING;
-				sprintf(buf,
-						"The Global Quest begins! You have %d minutes to complete the task!",
-						gquest_info.timer);
-				announce(NULL, INFO_GQUEST, buf);
+				announce(NULL, INFO_GQUEST,
+						 "The Global Quest begins! You have %d minutes to complete the task!",
+						 gquest_info.timer);
 			}
 		}
 	}
@@ -688,10 +715,9 @@
 		if (gquest_info.involved == 0)
 		{
 			end_gquest(gquest_info.last_registar);
-			sprintf(buf,
-					"No one left in the Global Quest, next quest will start in %d minutes.",
-					gquest_info.next);
-			announce(NULL, INFO_GQUEST, buf);
+			announce(NULL, INFO_GQUEST,
+					 "No one left in the Global Quest, next quest will start in %d minutes.",
+					 gquest_info.timer);
 			return;
 		}
 
@@ -699,10 +725,9 @@
 		{
 		case 0:
 			end_gquest(gquest_info.last_registar);
-			sprintf(buf,
-					"Time has run out on the Global Quest, next quest will start in %d minutes.",
-					gquest_info.next);
-			announce(NULL, INFO_GQUEST, buf);
+			announce(NULL, INFO_GQUEST,
+					 "Time has run out on the Global Quest, next quest will start in %d minutes.",
+					 gquest_info.timer);
 			return;
 		case 1:
 		case 2:
@@ -711,10 +736,9 @@
 		case 5:
 		case 10:
 		case 15:
-			sprintf(buf,
-					"%d minute%s remaining in the global quest.",
-					gquest_info.timer, gquest_info.timer > 1 ? "s" : "");
-			announce(NULL, INFO_GQUEST, buf);
+			announce(NULL, INFO_GQUEST,
+					 "%d minute%s remaining in the global quest.",
+					 gquest_info.timer, gquest_info.timer > 1 ? "s" : "");
 		default:
 			gquest_info.timer--;
 			break;
@@ -723,6 +747,8 @@
 	}
 }
 
+#define MAX_GQUEST_MOB_SEARCH    mobile_count
+
 bool generate_gquest(CHAR_DATA * who)
 {
 	CHAR_DATA *victim = NULL;
@@ -731,40 +757,32 @@
 	char buf[MAX_STRING_LENGTH];
 	int i;
 
-	reset_gqmob(NULL, 0);
-
 	mob_count = 0;
-	alloc_mem(vnums, vnum_t, top_mob_index);
+	alloc_mem(vnums, vnum_t, MAX_GQUEST_MOB_SEARCH);
 
 	for (victim = char_first; victim; victim = victim->next)
 	{
-		if (!IS_NPC(victim))
-		{
-			REMOVE_BIT(victim->act, PLR_GQUEST);
-			reset_gqmob(victim, 0);
-			continue;
-		}
-		else if (!IS_NPC(victim)
-				 || victim->level > (gquest_info.maxlevel + 10)
-				 || victim->level < (gquest_info.minlevel - 10)
-				 || (victim->pIndexData == NULL
-					 || victim->in_room == NULL
-					 || victim->pIndexData->pShop != NULL)
-				 || victim->pIndexData->vnum < 100
-				 || IS_SET(victim->in_room->room_flags, ROOM_PET_SHOP)
-				 || victim->in_room->clan != NULL
-				 || IS_SET(victim->imm_flags, IMM_WEAPON | IMM_MAGIC)
-				 || IS_SET(victim->act,
-						   ACT_TRAIN | ACT_PRACTICE | ACT_IS_HEALER |
-						   ACT_PET | ACT_GAIN)
-				 || IS_SET(victim->affected_by, AFF_CHARM)
-				 || (IS_SET(victim->act, ACT_SENTINEL)
-					 && IS_SET(victim->in_room->room_flags,
-							   ROOM_PRIVATE | ROOM_SOLITARY | ROOM_SAFE)))
+		if (!IS_NPC(victim) || victim->gquest
+			|| victim->level > (gquest_info.maxlevel + 10)
+			|| victim->level < (gquest_info.minlevel - 10)
+			|| (victim->pIndexData == NULL
+				|| victim->in_room == NULL
+				|| victim->pIndexData->pShop != NULL)
+			|| victim->pIndexData->vnum < 100
+			|| IS_SET(victim->in_room->room_flags, ROOM_PET_SHOP)
+			|| victim->in_room->clan != NULL
+			|| IS_SET(victim->imm_flags, IMM_WEAPON | IMM_MAGIC)
+			|| IS_SET(victim->act,
+					  ACT_TRAIN | ACT_PRACTICE | ACT_IS_HEALER |
+					  ACT_PET | ACT_GAIN)
+			|| IS_SET(victim->affected_by, AFF_CHARM)
+			|| (IS_SET(victim->act, ACT_SENTINEL)
+				&& IS_SET(victim->in_room->room_flags,
+						  ROOM_PRIVATE | ROOM_SOLITARY | ROOM_SAFE)))
 			continue;
 		vnums[mob_count] = victim->pIndexData->vnum;
 		mob_count++;
-		if (mob_count >= top_mob_index)
+		if (mob_count >= MAX_GQUEST_MOB_SEARCH)
 			break;
 	}
 
@@ -779,6 +797,8 @@
 		gquest_info.mob_count = mob_count;
 	}
 
+	alloc_mem(gquest_info.mobs, vnum_t, gquest_info.mob_count);
+
 	for (i = 0; i < gquest_info.mob_count; i++)
 	{
 		randm = number_range(0, mob_count - 1);
@@ -791,7 +811,6 @@
 	gquest_info.qpoints = number_range(15, 30) * gquest_info.mob_count;
 	gquest_info.gold = number_range(100, 150) * gquest_info.mob_count;
 	gquest_info.timer = 3;
-	gquest_info.next = 0;
 	sprintf(buf,
 			"%s Global Quest for levels %d to %d%s.  Type 'GQUEST INFO' to see the quest.",
 			!who ? "A" : "$n announces a", gquest_info.minlevel,
@@ -805,7 +824,7 @@
 	return TRUE;
 }
 
-int is_gqmob(CHAR_DATA * ch, vnum_t vnum)
+int is_gqmob(GQ_LIST * gql, vnum_t vnum)
 {
 	int i;
 
@@ -814,55 +833,41 @@
 
 	for (i = 0; i < gquest_info.mob_count; i++)
 	{
-		if (ch && !IS_NPC(ch))
+		if (gql)
 		{
-			if (ch->pcdata->gq_mobs[i] == vnum)
+			if (gql->gq_mobs[i] == vnum)
 				return i;
-			else
-				continue;
 		}
 		else
 		{
 			if (gquest_info.mobs[i] == vnum)
 				return i;
-			else
-				continue;
 		}
 	}
 
 	return -1;
 }
 
-int count_gqmobs(CHAR_DATA * ch)
+int count_gqmobs(GQ_LIST * gql)
 {
 	int i, count = 0;
 
-	if (IS_NPC(ch))
+	if (gquest_info.running == GQUEST_OFF || !gql)
 		return 0;
 
 	for (i = 0; i < gquest_info.mob_count; i++)
-		if (ch->pcdata->gq_mobs[i] == -1)
+		if (gql->gq_mobs[i] == -1)
 			count++;
 
 	return count;
 }
 
-void reset_gqmob(CHAR_DATA * ch, vnum_t value)
-{
-	int i;
-
-	for (i = 0; i < MAX_GQUEST_MOB; i++)
-	{
-		if (ch && !IS_NPC(ch))
-			ch->pcdata->gq_mobs[i] = value;
-		else
-			gquest_info.mobs[i] = value;
-	}
-}
-
 bool is_random_gqmob(vnum_t vnum)
 {
 	int i;
+
+	if (gquest_info.running == GQUEST_OFF)
+		return FALSE;
 
 	if (get_mob_index(vnum) == NULL)
 		return FALSE;
diff -ur ./src/handler.c ./new/handler.c
--- ./src/handler.c	Fri May 16 00:04:56 2003
+++ ./new/handler.c	Fri May 16 02:11:35 2003
@@ -818,8 +818,8 @@
 	if (ch->trust)
 		return ch->trust;
 
-	if (IS_NPC(ch) && ch->level >= LEVEL_HERO)
-		return LEVEL_HERO - 1;
+	if (IS_NPC(ch) && ch->level >= MAX_MORTAL_LEVEL)
+		return MAX_MORTAL_LEVEL - 1;
 	else
 		return ch->level;
 }
@@ -2512,8 +2512,8 @@
 														  victim->in_room
 														  &&
 														  IS_SET
-														  (victim->in_room->
-														   room_flags,
+														  (victim->
+														   in_room->room_flags,
 														   ROOM_ARENA)))
 		return TRUE;
 
@@ -2522,7 +2522,7 @@
 		return TRUE;
 
 	if (gquest_info.running == GQUEST_RUNNING && ON_GQUEST(ch) &&
-		IS_NPC(victim) && is_gqmob(ch, victim->pIndexData->vnum) != -1)
+		IS_NPC(victim) && is_gqmob(ch->gquest, victim->pIndexData->vnum) != -1)
 		return TRUE;
 
 	if (room_is_dark(ch->in_room) && !IS_AFFECTED(ch, AFF_INFRARED))
@@ -2664,11 +2664,53 @@
 	}
 	if (tz > -1 && tz < MAX_TZONE)
 	{
+#if defined(__CYGWIN__)
+		timet += (time_t) timezone;
+#else
 		timet += timezone;
+#endif
 		timet += (60 * 60 * tzone_table[tz].gmt_offset);
 	}
 	strftime(result, 100, !IS_NULLSTR(format) ? format : "%a %b %d %r %Y",
 			 localtime(&timet));
 
 	return result;
+}
+
+int calc_max_level(CHAR_DATA * ch)
+{
+	if (IS_NPC(ch) || IS_IMMORTAL(ch))
+		return MAX_LEVEL;
+
+	return UMIN(MAX_MORTAL_LEVEL, (LEVEL_HERO + number_classes(ch) - 1));
+}
+
+const char *high_level_name(int level, bool fLong)
+{
+	static char buf[MSL];
+	const char *imm_long[MAX_LEVEL - MAX_MORTAL_LEVEL] =
+		{ "AVATAR", "ANGEL", "DEMI", "IMMORTAL", "GOD", "DEITY", "SUPREME",
+			"CREATOR", "IMPLEMENTOR"
+	};
+	const char *imm_short[MAX_LEVEL - MAX_MORTAL_LEVEL] =
+		{ "AVA", "ANG", "DEM", "IMM", "GOD", "DEI", "SUP", "CRE", "IMP" };
+
+	if (level > MAX_MORTAL_LEVEL && level <= MAX_LEVEL)
+		return fLong ? imm_long[level - MAX_MORTAL_LEVEL -
+								1] : imm_short[level - MAX_MORTAL_LEVEL - 1];
+
+	if (level <= MAX_MORTAL_LEVEL && level > LEVEL_HERO)
+	{
+		sprintf(buf, "%s+%d", fLong ? "HERO" : "H", level - LEVEL_HERO);
+		return buf;
+	}
+
+	if (level == LEVEL_HERO)
+	{
+		return fLong ? "HERO" : "HRO";
+	}
+
+	sprintf(buf, "%03d", level);
+
+	return buf;
 }
diff -ur ./src/interp.c ./new/interp.c
--- ./src/interp.c	Fri May 16 00:04:56 2003
+++ ./new/interp.c	Fri May 16 02:11:35 2003
@@ -46,8 +46,8 @@
 /*
  * Log-all switch.
  */
-char last_command[MAX_STRING_LENGTH];
-char last_command2[MAX_INPUT_LENGTH];
+char last_func_long[MAX_STRING_LENGTH];
+char last_func_short[MAX_INPUT_LENGTH];
 DESCRIPTOR_DATA *last_descriptor;
 
 CH_CMD(do_null)
@@ -96,17 +96,10 @@
 	 *   also no spaces needed after punctuation.
 	 */
 	strcpy(logline, argument);
-	sprintf(last_command, "%s in room[%ld]: %s.", ch->name,
-			ch->in_room->vnum, argument);
-	if (ch->desc != NULL)
-	{
-		sprintf(last_command2, "%s", argument);
-		last_descriptor = ch->desc;
-	}
-	else
-	{
-		last_command2[0] = '\0';
-	}
+
+	update_last_func(ch->desc, FORMATF("%s in room[%ld]: %s.", ch->name,
+									   ch->in_room ? ch->in_room->vnum : 0,
+									   argument), argument);
 
 	if (!isalpha(argument[0]) && !isdigit(argument[0]))
 	{
@@ -219,6 +212,10 @@
 	 */
 	(*cmd->do_fun) (ch, argument);
 
+	update_last_func(ch->desc,
+					 FORMATF("(Finished) %s in room[%ld]: %s.", ch->name,
+							 ch->in_room ? ch->in_room->vnum : 0, cmd->name),
+					 FORMATF("(Finished) %s", cmd->name));
 	tail_chain();
 	return;
 }
diff -ur ./src/interp.h ./new/interp.h
--- ./src/interp.h	Fri May 16 00:04:56 2003
+++ ./new/interp.h	Fri May 16 02:11:35 2003
@@ -33,9 +33,11 @@
 /* wrapper function for safe command execution */
 void do_function args((CHAR_DATA * ch, DO_FUN * do_fun, const char *argument));
 
-extern char last_command[MAX_STRING_LENGTH];
-extern char last_command2[MAX_INPUT_LENGTH];
+extern char last_func_long[MAX_STRING_LENGTH];
+extern char last_func_short[MAX_INPUT_LENGTH];
 extern DESCRIPTOR_DATA *last_descriptor;
+void update_last_func
+args((DESCRIPTOR_DATA * d, const char *lstr, const char *sstr));
 
 /* for command types */
 #define ML 	MAX_LEVEL			/* implementor */
diff -ur ./src/magic.c ./new/magic.c
--- ./src/magic.c	Fri May 16 00:04:56 2003
+++ ./new/magic.c	Fri May 16 02:11:35 2003
@@ -286,8 +286,8 @@
 	if ((sn = find_spell(ch, arg1)) < 1 ||
 		skill_table[sn].spell_fun == spell_null || (!IS_NPC(ch) &&
 													(!can_use_skpell(ch, sn)
-													 || ch->pcdata->
-													 learned[sn] == 0)))
+													 || ch->
+													 pcdata->learned[sn] == 0)))
 	{
 		chprintln(ch, "You don't know any spells of that name.");
 		return;
@@ -2268,8 +2268,8 @@
 
 	/* now add the enchantments */
 
-	if (obj->level < LEVEL_HERO)
-		obj->level = UMIN(LEVEL_HERO - 1, obj->level + 1);
+	if (obj->level < MAX_MORTAL_LEVEL)
+		obj->level = UMIN(MAX_MORTAL_LEVEL - 1, obj->level + 1);
 
 	if (ac_found)
 	{
@@ -2462,8 +2462,8 @@
 
 	/* now add the enchantments */
 
-	if (obj->level < LEVEL_HERO - 1)
-		obj->level = UMIN(LEVEL_HERO - 1, obj->level + 1);
+	if (obj->level < MAX_MORTAL_LEVEL - 1)
+		obj->level = UMIN(MAX_MORTAL_LEVEL - 1, obj->level + 1);
 
 	if (dam_found)
 	{
@@ -2787,16 +2787,14 @@
 		|| IS_SET(victim->in_room->room_flags, ROOM_SOLITARY)
 		|| IS_SET(victim->in_room->room_flags, ROOM_NO_RECALL)
 		|| IS_SET(ch->in_room->room_flags, ROOM_NO_RECALL) || (IS_NPC(victim)
-															   && is_gqmob(ch,
-																		   victim->
-																		   pIndexData->
-																		   vnum)
+															   && is_gqmob(NULL,
+																		   victim->pIndexData->vnum)
 															   != -1)
 		|| (IS_NPC(victim) && IS_QUESTOR(ch)
 			&& ch->pcdata->questmob == victim->pIndexData->vnum)
 		|| victim->level >= level + 3 || (is_clan(victim)
 										  && !is_same_clan(ch, victim))
-		|| (!IS_NPC(victim) && victim->level >= LEVEL_HERO)	/* NOT trust */
+		|| (!IS_NPC(victim) && victim->level >= MAX_MORTAL_LEVEL)	/* NOT trust */
 		|| (IS_NPC(victim) && IS_SET(victim->imm_flags, IMM_SUMMON))
 		|| (IS_NPC(victim) && saves_spell(level, victim, DAM_OTHER)))
 	{
@@ -4222,7 +4220,7 @@
 		|| IS_SET(victim->in_room->area->area_flags, AREA_CLOSED)
 		|| IS_SET(victim->in_room->room_flags, ROOM_ARENA)
 		|| IS_SET(ch->in_room->room_flags, ROOM_ARENA)
-		|| (IS_NPC(victim) && is_gqmob(ch, victim->pIndexData->vnum) != -1)
+		|| (IS_NPC(victim) && is_gqmob(NULL, victim->pIndexData->vnum) != -1)
 		|| (IS_NPC(victim) && IS_QUESTOR(ch)
 			&& ch->pcdata->questmob == victim->pIndexData->vnum)
 		|| (IS_NPC(victim) && IS_SET(victim->act, ACT_AGGRESSIVE))
diff -ur ./src/magic2.c ./new/magic2.c
--- ./src/magic2.c	Fri May 16 00:04:56 2003
+++ ./new/magic2.c	Fri May 16 02:11:35 2003
@@ -63,12 +63,14 @@
 		|| IS_SET(ch->in_room->room_flags, ROOM_ARENA)
 		|| IS_SET(victim->in_room->room_flags, ROOM_NO_RECALL)
 		|| IS_SET(ch->in_room->room_flags, ROOM_NO_RECALL) || (IS_NPC(victim)
-															   && is_gqmob(ch,
-																		   victim->pIndexData->vnum)
+															   && is_gqmob(NULL,
+																		   victim->
+																		   pIndexData->
+																		   vnum)
 															   != -1)
 		|| (IS_NPC(victim) && IS_QUESTOR(ch)
 			&& ch->pcdata->questmob == victim->pIndexData->vnum)
-		|| victim->level >= level + 3 || (!IS_NPC(victim) && victim->level >= LEVEL_HERO)	/* NOT trust */
+		|| victim->level >= level + 3 || (!IS_NPC(victim) && victim->level >= MAX_MORTAL_LEVEL)	/* NOT trust */
 		|| (IS_NPC(victim) && IS_SET(victim->imm_flags, IMM_SUMMON))
 		|| (IS_NPC(victim) && saves_spell(level, victim, DAM_NONE))
 		|| (is_clan(victim) && !is_same_clan(ch, victim)))
@@ -122,12 +124,19 @@
 		|| IS_SET(to_room->area->area_flags, AREA_CLOSED)
 		|| IS_SET(to_room->room_flags, ROOM_ARENA)
 		|| IS_SET(from_room->room_flags, ROOM_ARENA) || (IS_NPC(victim)
-														 && is_gqmob(ch,
-																	 victim->pIndexData->vnum)
-														 != -1)
-		|| (IS_NPC(victim) && IS_QUESTOR(ch)
-			&& ch->pcdata->questmob == victim->pIndexData->vnum)
-		|| victim->level >= level + 3 || (!IS_NPC(victim) && victim->level >= LEVEL_HERO)	/* NOT trust */
+														 && is_gqmob(NULL,
+																	 victim->
+																	 pIndexData->
+																	 vnum) !=
+														 -1) || (IS_NPC(victim)
+																 &&
+																 IS_QUESTOR(ch)
+																 && ch->pcdata->
+																 questmob ==
+																 victim->
+																 pIndexData->
+																 vnum)
+		|| victim->level >= level + 3 || (!IS_NPC(victim) && victim->level >= MAX_MORTAL_LEVEL)	/* NOT trust */
 		|| (IS_NPC(victim) && IS_SET(victim->imm_flags, IMM_SUMMON))
 		|| (IS_NPC(victim) && saves_spell(level, victim, DAM_NONE))
 		|| (is_clan(victim) && !is_same_clan(ch, victim)))
diff -ur ./src/merc.h ./new/merc.h
--- ./src/merc.h	Fri May 16 00:04:56 2003
+++ ./new/merc.h	Fri May 16 02:11:35 2003
@@ -149,6 +149,8 @@
 typedef struct wpwd_data WPWD_DATA;
 typedef struct mbr_data MBR_DATA;
 typedef struct file_data FILE_DATA;
+typedef struct war_list_type WAR_LIST;
+typedef struct gquest_list_type GQ_LIST;
 
 /*
  * Function types.
@@ -193,28 +195,29 @@
 #define    MAX_HOUSE_ROOMS            5
 #define    MAX_VNUM                   60000
 #define MAX_LEVEL		   60
-#define LEVEL_HERO		   (MAX_LEVEL - 9)
 #define LEVEL_IMMORTAL		   (MAX_LEVEL - 8)
+#define MAX_MORTAL_LEVEL	   (MAX_LEVEL - 9)
+#define LEVEL_HERO			   (MAX_MORTAL_LEVEL - MAX_REMORT)
 
 #define PULSE_PER_SECOND	    4
 #define PULSE_VIOLENCE		  ( 3 * PULSE_PER_SECOND)
 #define PULSE_MOBILE		  ( 4 * PULSE_PER_SECOND)
 #define PULSE_MUSIC		  ( 6 * PULSE_PER_SECOND)
-#define PULSE_TICK		  (60 * PULSE_PER_SECOND)
+#define PULSE_TICK		  (45 * PULSE_PER_SECOND)
 #define PULSE_AREA		  (120 * PULSE_PER_SECOND)
 
 #define    AUCTION_LENGTH           (60 * PULSE_PER_SECOND)
 
-#define IMPLEMENTOR		MAX_LEVEL
-#define	CREATOR			(MAX_LEVEL - 1)
-#define SUPREME			(MAX_LEVEL - 2)
-#define DEITY			(MAX_LEVEL - 3)
-#define GOD			(MAX_LEVEL - 4)
-#define IMMORTAL		(MAX_LEVEL - 5)
-#define DEMI			(MAX_LEVEL - 6)
-#define ANGEL			(MAX_LEVEL - 7)
-#define AVATAR			(MAX_LEVEL - 8)
-#define HERO			LEVEL_HERO
+#define IMPLEMENTOR		  MAX_LEVEL
+#define	CREATOR			 (MAX_LEVEL - 1)
+#define SUPREME			 (MAX_LEVEL - 2)
+#define DEITY			 (MAX_LEVEL - 3)
+#define GOD				 (MAX_LEVEL - 4)
+#define IMMORTAL		 (MAX_LEVEL - 5)
+#define DEMI			 (MAX_LEVEL - 6)
+#define ANGEL			 (MAX_LEVEL - 7)
+#define AVATAR			 (MAX_LEVEL - 8)
+#define HERO			 LEVEL_HERO
 
 /*
  * Site ban structure.
@@ -529,7 +532,6 @@
 struct class_type
 {
 	const char *name;			/* the full name of the class */
-	const char *who_name;		/* Three-letter name for 'who'  */
 	int attr_prime;				/* Prime attribute      */
 	vnum_t weapon;				/* First weapon         */
 	vnum_t guild[MAX_GUILD];	/* Vnum of guild rooms      */
@@ -599,7 +601,6 @@
 	flag_t vuln;				/* vuln bits for the race */
 	flag_t form;				/* default form flag_t for the race */
 	flag_t parts;				/* default parts for the race */
-	const char *who_name;
 	int points;					/* cost in points of the race */
 	int *class_mult;			/* exp multiplier for class, * 100 */
 	const char *skills[5];		/* bonus skills for the race */
@@ -635,12 +636,18 @@
 
 #include "board.h"
 
-#define	MAX_GQUEST_MOB 26
+struct gquest_list_type
+{
+	GQ_LIST *next, *prev;
+	CHAR_DATA *ch;
+	vnum_t *gq_mobs;
+};
 
 struct gquest_data
 {
+	GQ_LIST *first, *last;
 	CHAR_DATA *last_registar;
-	vnum_t mobs[MAX_GQUEST_MOB];
+	vnum_t *mobs;
 	const char *who;
 	int mob_count;
 	int timer;
@@ -650,7 +657,6 @@
 	int minlevel;
 	int maxlevel;
 	int running;
-	int next;
 };
 
 #define		GQUEST_OFF			0
@@ -1371,8 +1377,7 @@
 #define PLR_AUTOSAC         (BIT_F)
 #define PLR_AUTOGOLD		(BIT_G)
 #define PLR_AUTOSPLIT		(BIT_H)
-#define PLR_GQUEST          (BIT_I)
-#define	PLR_WAR         (BIT_J)
+
 #define PLR_AUTODAMAGE  (BIT_K)
 
 /* Arena flags */
@@ -1466,19 +1471,28 @@
 	WAR_CLASS = 3,
 	WAR_GENOCIDE = 4,
 	WAR_DEITY = 5,
-	MAX_WAR = 6
+	WAR_SEX = 6,
+	MAX_WAR = 7
+};
+
+struct war_list_type
+{
+	WAR_LIST *next, *prev;
+	CHAR_DATA *ch;
+	long hit, mana, move;
+	flag_t flags;
 };
 
 struct war_data
 {
+	WAR_LIST *first, *last;
 	const char *who;
 	int min_level;
 	int max_level;
 	int inwar;
 	enum war_types wartype;
 	int timer;
-	int iswar;
-	int next;
+	int status;
 };
 
 struct wpwd_data
@@ -1625,6 +1639,8 @@
 	PC_DATA *pcdata;
 	GEN_DATA *gen_data;
 	CHAR_DATA *hunting;
+	WAR_LIST *war;
+	GQ_LIST *gquest;
 	bool valid;
 	const char *name;
 	long id;
@@ -1767,9 +1783,7 @@
 	int trivia;
 	bool confirm_remort;
 	bool stay_race;
-	vnum_t gq_mobs[MAX_GQUEST_MOB];
 	char explored[MAX_EXPLORE_HASH];
-	bool still_in_war;
 	long home_invite;
 	vnum_t home[MAX_HOUSE_ROOMS];
 	vnum_t home_key;
@@ -2352,7 +2366,7 @@
 #define IS_OUTSIDE(ch)		(!IS_SET(				    \
 				    (ch)->in_room->room_flags,		    \
 				    ROOM_INDOORS))
-#define IS_IN_WAR(ch)   (!IS_NPC(ch) && IS_SET((ch)->act, PLR_WAR) \
+#define IS_IN_WAR(ch)   (ch->war != NULL \
                         && IS_SET((ch)->in_room->room_flags, ROOM_ARENA))
 
 #define WAIT_STATE(ch, npulse)	((ch)->wait = UMAX((ch)->wait, (npulse)))
@@ -2381,7 +2395,7 @@
 #define IS_REMORT(ch)      (!IS_NPC(ch) && ( IS_SET((ch)->act, PLR_REMORT) \
                                 || number_classes(ch) > 1))
 
-#define	ON_GQUEST(ch)      (!IS_NPC(ch) && IS_SET((ch)->act, PLR_GQUEST) && gquest_info.running != GQUEST_OFF)
+#define	ON_GQUEST(ch)      (gquest_info.running != GQUEST_OFF && ch->gquest)
 
 #define STR_EDIT_KEY(ch) (IS_NPC(ch) ? '.' : ch->pcdata->str_ed_key)
 
@@ -2490,6 +2504,7 @@
 #define DISABLED_FILE	DATA_DIR "disabled.dat"	/* disabled commands */
 #define STAT_FILE       DATA_DIR "statlist.dat"
 #define	GQUEST_FILE		DATA_DIR "gquest.dat"
+#define WAR_FILE		DATA_DIR "war.dat"
 #define CLAN_FILE       DATA_DIR "clans.dat"
 #define COMMAND_FILE    DATA_DIR "commands.dat"
 #define SKILL_FILE      DATA_DIR "skills.dat"
@@ -2515,6 +2530,7 @@
  * Used in save.c to load objects that don't exist.
  */
 #define OBJ_VNUM_DUMMY	30
+#define MOB_VNUM_DUMMY	30
 
 #define NO_FLAG  -99
 
diff -ur ./src/multiclass.c ./new/multiclass.c
--- ./src/multiclass.c	Fri May 16 00:04:56 2003
+++ ./new/multiclass.c	Fri May 16 02:11:35 2003
@@ -64,15 +64,14 @@
 		return;
 	}
 
-/* Legend = HERO + 1, gained not by exp but gold and quest points.
-   Optionally you can add a check for gold/questpoints here. */
-	if (ch->level != LEVEL_HERO)
+	if (ch->level != calc_max_level(ch))
 	{
-		chprintln(ch, "You must be a HERO to remort.");
+		chprintlnf(ch, "You must be a %s to remort.",
+				   high_level_name(calc_max_level(ch), TRUE));
 		return;
 	}
 
-	if (number_classes(ch) == MAX_REMORT)
+	if (number_classes(ch) == MAX_REMORT || number_classes(ch) == maxClass)
 	{
 		chprintln(ch, "You can't remort any more!");
 		return;
@@ -149,12 +148,11 @@
 			   All other skills are reset back to 1%. */
 			for (sn = 0; sn < maxSkill; sn++)
 			{
-				if (ch->pcdata->learned[sn] > 0)
+				if (ch->pcdata->learned[sn] > 0
+					&& ch->pcdata->learned[sn] < 100)
 				{
 					if (is_race_skill(ch, sn) && !ch->pcdata->stay_race)
 						ch->pcdata->learned[sn] = 0;
-					else if (ch->pcdata->learned[sn] == 100)
-						ch->pcdata->learned[sn] = 100;
 					else
 						ch->pcdata->learned[sn] = 1;
 				}
@@ -279,15 +277,16 @@
  */
 bool is_same_class(CHAR_DATA * ch, CHAR_DATA * victim)
 {
-	int iClass;
+	int iClass, jClass;
 
 	if (IS_NPC(ch) || IS_NPC(victim))
 		return FALSE;
 
 	for (iClass = 0; ch->Class[iClass] != -1; iClass++)
 	{
-		if (ch->Class[iClass] == victim->Class[iClass])
-			return TRUE;
+		for (jClass = 0; victim->Class[jClass] != -1; jClass++)
+			if (ch->Class[iClass] == victim->Class[jClass])
+				return TRUE;
 	}
 
 	return FALSE;
@@ -339,10 +338,10 @@
 		return "Mob";
 
 	if (number_classes(ch) > 1)
-		sprintf(buf, "%c+%d", class_table[ch->Class[0]].who_name[0],
+		sprintf(buf, "%c+%d", class_table[ch->Class[0]].name[0],
 				number_classes(ch) - 1);
 	else
-		sprintf(buf, class_table[ch->Class[0]].who_name);
+		sprintf(buf, "%3.3s", class_table[ch->Class[0]].name);
 	return buf;
 }
 
@@ -358,7 +357,7 @@
 	for (iClass = 0; ch->Class[iClass] != -1; iClass++)
 	{
 		strcat(buf, "/");
-		strcat(buf, class_table[ch->Class[iClass]].who_name);
+		strcat(buf, FORMATF("%3.3s", class_table[ch->Class[iClass]].name));
 	}
 	return buf + 1;
 }
@@ -541,7 +540,7 @@
 	if (IS_NPC(ch))
 		return FALSE;
 
-	if (gn < 0 || gn > maxGroup)
+	if (gn < 0 || gn >= maxGroup)
 		return FALSE;
 
 	for (iClass = 0; ch->Class[iClass] != -1; iClass++)
@@ -565,7 +564,7 @@
 	if (IS_NPC(ch))
 		return FALSE;
 
-	if (sn < 0 || sn > maxSkill)
+	if (sn < 0 || sn >= maxSkill)
 		return FALSE;
 
 	for (iClass = 0; ch->Class[iClass] != -1; iClass++)
diff -ur ./src/olc.c ./new/olc.c
--- ./src/olc.c	Fri May 16 00:04:56 2003
+++ ./new/olc.c	Fri May 16 02:11:35 2003
@@ -72,57 +72,57 @@
 DEITY_DATA xDeity;
 
 /* Executed from comm.c.  Minimizes compiling when changes are made. */
-bool run_olc_editor(DESCRIPTOR_DATA * d)
+bool run_olc_editor(DESCRIPTOR_DATA * d, char *incomm)
 {
 	switch (d->editor)
 	{
 	case ED_AREA:
-		aedit(d->character, d->incomm);
+		aedit(d->character, incomm);
 		break;
 	case ED_ROOM:
-		redit(d->character, d->incomm);
+		redit(d->character, incomm);
 		break;
 	case ED_OBJECT:
-		oedit(d->character, d->incomm);
+		oedit(d->character, incomm);
 		break;
 	case ED_MOBILE:
-		medit(d->character, d->incomm);
+		medit(d->character, incomm);
 		break;
 	case ED_MPCODE:
-		mpedit(d->character, d->incomm);
+		mpedit(d->character, incomm);
 		break;
 	case ED_OPCODE:
-		opedit(d->character, d->incomm);
+		opedit(d->character, incomm);
 		break;
 	case ED_RPCODE:
-		rpedit(d->character, d->incomm);
+		rpedit(d->character, incomm);
 		break;
 	case ED_HELP:
-		hedit(d->character, d->incomm);
+		hedit(d->character, incomm);
 		break;
 	case ED_SOCIAL:
-		sedit(d->character, d->incomm);
+		sedit(d->character, incomm);
 		break;
 	case ED_CLAN:
-		cedit(d->character, d->incomm);
+		cedit(d->character, incomm);
 		break;
 	case ED_CMD:
-		cmdedit(d->character, d->incomm);
+		cmdedit(d->character, incomm);
 		break;
 	case ED_SKILL:
-		skedit(d->character, d->incomm);
+		skedit(d->character, incomm);
 		break;
 	case ED_GROUP:
-		gredit(d->character, d->incomm);
+		gredit(d->character, incomm);
 		break;
 	case ED_RACE:
-		raedit(d->character, d->incomm);
+		raedit(d->character, incomm);
 		break;
 	case ED_CLASS:
-		cledit(d->character, d->incomm);
+		cledit(d->character, incomm);
 		break;
 	case ED_DEITY:
-		dedit(d->character, d->incomm);
+		dedit(d->character, incomm);
 		break;
 	default:
 		return FALSE;
@@ -774,7 +774,6 @@
 	{"stats", NULL, olced_olded, (const void *) raedit_stats},
 	{"mstats", NULL, olced_olded, (const void *) raedit_mstats},
 	{"skills", NULL, olced_olded, (const void *) raedit_skills},
-	{"whoname", (void *) &xRace.who_name, olced_str, NULL},
 	{"size", (void *) &xRace.size, olced_flag, (const void *) size_flags},
 	{"classx", NULL, olced_olded, (const void *) raedit_classx},
 	{"commands", NULL, olced_olded, (const void *) show_commands},
@@ -790,8 +789,6 @@
 
 	{"name", (void *) &xClass.name, olced_str,
 	 (const void *) validate_classname},
-	{"who", (void *) &xClass.who_name, olced_str,
-	 (const void *) validate_whoname},
 	{"prime", NULL, olced_olded, (const void *) cledit_prime},
 
 	{"weapon", (void *) &xClass.weapon, olced_vnum,
diff -ur ./src/olc.h ./new/olc.h
--- ./src/olc.h	Fri May 16 00:04:56 2003
+++ ./new/olc.h	Fri May 16 02:11:35 2003
@@ -229,7 +229,6 @@
 DECLARE_VALIDATE_FUN(validate_level);
 DECLARE_VALIDATE_FUN(validate_groupname);
 
-DECLARE_VALIDATE_FUN(validate_whoname);
 DECLARE_VALIDATE_FUN(validate_weapon);
 DECLARE_VALIDATE_FUN(validate_adept);
 DECLARE_VALIDATE_FUN(validate_hmv);
diff -ur ./src/olc_act.c ./new/olc_act.c
--- ./src/olc_act.c	Fri May 16 00:04:56 2003
+++ ./new/olc_act.c	Fri May 16 02:11:35 2003
@@ -820,8 +820,9 @@
 
 #if 0							/* ROM OLC */
 	chprintlnf(ch, "Recall:   [%5d] %s", pArea->recall,
-			   get_room_index(pArea->recall) ? get_room_index(pArea->recall)->
-			   name : "none");
+			   get_room_index(pArea->recall) ? get_room_index(pArea->
+															  recall)->name :
+			   "none");
 #endif							/* ROM */
 
 	chprintlnf(ch, "File:     %s", pArea->file_name);
@@ -1914,7 +1915,7 @@
 
 		add_reset(pRoom, pReset, 0 /* Last slot */ );
 
-		olevel = URANGE(0, to_mob->level - 2, LEVEL_HERO);
+		olevel = URANGE(0, to_mob->level - 2, MAX_MORTAL_LEVEL);
 		newobj = create_object(pObjIndex, number_fuzzy(olevel));
 
 		if (to_mob->pIndexData->pShop)	/* Shop-keeper? */
@@ -2079,8 +2080,9 @@
 				   "[v4] Weight Mult [%ld]", obj->value[0],
 				   flag_string(container_flags, obj->value[1]),
 				   get_obj_index(obj->value[2]) ? get_obj_index(obj->value
-																[2])->short_descr
-				   : "none", obj->value[2], obj->value[3], obj->value[4]);
+																[2])->
+				   short_descr : "none", obj->value[2], obj->value[3],
+				   obj->value[4]);
 		break;
 
 	case ITEM_DRINK_CON:
diff -ur ./src/olc_class.c ./new/olc_class.c
--- ./src/olc_class.c	Fri May 16 00:04:56 2003
+++ ./new/olc_class.c	Fri May 16 02:11:35 2003
@@ -90,7 +90,6 @@
 	class_table = new_table;
 
 	class_table[i].name = str_dup(buf);
-	class_table[i].who_name = str_dup("");
 	pClass = &class_table[i];
 	edit_start(ch, pClass, ED_CLASS);
 	chprintln(ch, "Class created.");
@@ -204,7 +203,6 @@
 
 	chprintln(ch, draw_line(ch, NULL, 0));
 	chprintlnf(ch, "Name           : %s", pClass->name);
-	chprintlnf(ch, "Who Name       : %s", pClass->who_name);
 	chprintlnf(ch, "Prime Attribute: %s", stat_name(pClass->attr_prime));
 	chprintlnf(ch, "Weapon Vnum    : %ld", pClass->weapon);
 	chprintlnf(ch, "Skill Adept    : %d", pClass->skill_adept);
@@ -223,16 +221,6 @@
 	return TRUE;
 }
 
-VALIDATE_FUN(validate_whoname)
-{
-	if (strlen((const char *) arg) != 3)
-	{
-		chprintln(ch, "Please limit who name to 3 characters.");
-		return FALSE;
-	}
-	return TRUE;
-}
-
 CLEDIT(cledit_prime)
 {
 	CLASS_DATA *pClass;
@@ -387,7 +375,9 @@
 
 VALIDATE_FUN(validate_classname)
 {
-	if (class_lookup((const char *) arg) != -1)
+	if (class_lookup((const char *) arg) != -1
+		&& !str_casecmp(((CLASS_DATA *) ch->desc->pEdit)->name,
+						(const char *) arg))
 	{
 		chprintln(ch, "A class with that name already exits.");
 		return FALSE;
diff -ur ./src/olc_cmd.c ./new/olc_cmd.c
--- ./src/olc_cmd.c	Fri May 16 00:04:56 2003
+++ ./new/olc_cmd.c	Fri May 16 02:11:35 2003
@@ -49,13 +49,27 @@
 	bool found = FALSE;
 
 	if (IS_NULLSTR(argument))
-		chprintln(ch, "Syntax: cmdcheck null|missing|<do_fun_name>");
+		chprintln(ch, "Syntax: cmdcheck null|missing|hidden|<do_fun_name>");
 	else if (!str_prefix(argument, "null"))
 	{
 		chprintln(ch, "NULL commands:");
 		for (i = cmd_first_sorted; i; i = i->next_sort)
 		{
 			if (i->do_fun == do_null)
+			{
+				found = TRUE;
+				chprintlnf(ch, "%s", i->name);
+			}
+		}
+		if (!found)
+			chprintln(ch, "None.");
+	}
+	else if (!str_prefix(argument, "hidden"))
+	{
+		chprintln(ch, "Hidden commands:");
+		for (i = cmd_first_sorted; i; i = i->next_sort)
+		{
+			if (!i->show)
 			{
 				found = TRUE;
 				chprintlnf(ch, "%s", i->name);
diff -ur ./src/olc_group.c ./new/olc_group.c
--- ./src/olc_group.c	Fri May 16 00:04:56 2003
+++ ./new/olc_group.c	Fri May 16 02:11:35 2003
@@ -51,7 +51,7 @@
 	chprintlnf(ch, "Name: %s", pGroup->name);
 	chprintln(ch, "Class Ratings:");
 	for (x = 0; x < maxClass; x++)
-		chprintf(ch, "[%s: %3d] ", class_table[x].who_name, pGroup->rating[x]);
+		chprintf(ch, "[%3.3s: %3d] ", class_table[x].name, pGroup->rating[x]);
 	chprintln(ch, "");
 	chprintln(ch, "Spells:");
 	for (x = 0; pGroup->spells[x] != NULL; x++)
diff -ur ./src/olc_race.c ./new/olc_race.c
--- ./src/olc_race.c	Fri May 16 00:04:56 2003
+++ ./new/olc_race.c	Fri May 16 02:11:35 2003
@@ -89,8 +89,8 @@
 
 	chprintln(ch, draw_line(ch, NULL, 0));
 
-	chprintlnf(ch, "Name:\t[%s] Who Name: [%s] PC Race: [%s]", pRace->name,
-			   pRace->who_name, pRace->pc_race == 0 ? "{WNO{w" : "{RYES{w");
+	chprintlnf(ch, "Name:\t[%s] PC Race: [%s]", pRace->name,
+			   pRace->pc_race == 0 ? "{WNO{w" : "{RYES{w");
 
 	chprintlnf(ch, "Act:\t[%s]", flag_string(act_flags, pRace->act));
 	chprintlnf(ch, "Aff:\t[%s]", flag_string(affect_flags, pRace->aff));
diff -ur ./src/olc_skill.c ./new/olc_skill.c
--- ./src/olc_skill.c	Fri May 16 00:04:56 2003
+++ ./new/olc_skill.c	Fri May 16 02:11:35 2003
@@ -118,12 +118,12 @@
 	chprintlnf(ch, "Name: %s", pSkill->name);
 	chprintln(ch, "Class Levels:");
 	for (x = 0; x < maxClass; x++)
-		chprintf(ch, "[%s: %3d] ", class_table[x].who_name,
+		chprintf(ch, "[%3.3s: %3d] ", class_table[x].name,
 				 pSkill->skill_level[x]);
 	chprintln(ch, "");
 	chprintln(ch, "Class Ratings:");
 	for (x = 0; x < maxClass; x++)
-		chprintf(ch, "[%s: %3d] ", class_table[x].who_name, pSkill->rating[x]);
+		chprintf(ch, "[%3.3s: %3d] ", class_table[x].name, pSkill->rating[x]);
 	chprintln(ch, "");
 	chprintlnf(ch, "Spell_Fun: %s", spell_fun_name(pSkill->spell_fun));
 	chprintlnf(ch, "Target: %s", flag_string(target_flags, pSkill->target));
diff -ur ./src/proto.h ./new/proto.h
--- ./src/proto.h	Fri May 16 00:04:56 2003
+++ ./new/proto.h	Fri May 16 02:11:35 2003
@@ -421,7 +421,7 @@
 args((const char **text, int command, const char *string, CHAR_DATA * ch));
 
 /* olc.c */
-bool run_olc_editor args((DESCRIPTOR_DATA * d));
+bool run_olc_editor args((DESCRIPTOR_DATA * d, char *incomm));
 char *olc_ed_name args((CHAR_DATA * ch));
 char *olc_ed_vnum args((CHAR_DATA * ch));
 void clean_area_links args((AREA_DATA * target));
@@ -452,9 +452,8 @@
 void end_gquest args((CHAR_DATA * who));
 void gquest_update args((void));
 bool generate_gquest args((CHAR_DATA * who));
-int count_gqmobs args((CHAR_DATA * ch));
-int is_gqmob args((CHAR_DATA * ch, vnum_t vnum));
-void reset_gqmob args((CHAR_DATA * ch, vnum_t value));
+int count_gqmobs args((GQ_LIST * gql));
+int is_gqmob args((GQ_LIST * gql, vnum_t vnum));
 bool is_random_gqmob args((vnum_t vnum));
 
 /*explored.c */
@@ -481,6 +480,8 @@
 bool abort_class_war args((void));
 bool abort_clan_war args((void));
 void extract_war args((CHAR_DATA * ch));
+bool load_war_data args((void));
+bool save_war_data args((void));
 
 void save_clans args((void));
 void load_clans args((void));
@@ -598,6 +599,9 @@
 
 void set_vtimer args((long sec));
 char *str_time args((time_t timet, int tz, const char *format));
+
+int calc_max_level args((CHAR_DATA * ch));
+const char *high_level_name args((int level, bool fLong));
 
 #undef	CD
 #undef	MID
diff -ur ./src/recycle.c ./new/recycle.c
--- ./src/recycle.c	Fri May 16 00:04:56 2003
+++ ./new/recycle.c	Fri May 16 02:11:35 2003
@@ -95,6 +95,7 @@
 		return;
 
 	free_string(d->host);
+	free_string(d->showstr_head);
 	free_mem(d->outbuf);
 	INVALIDATE(d);
 	PUT_FREE(d, next, descriptor_free);
@@ -748,7 +749,6 @@
 	*race = race_zero;
 
 	race->name = &str_empty[0];
-	race->who_name = &str_empty[0];
 	race->pc_race = FALSE;
 	race->act = 0;
 	race->aff = 0;
@@ -784,7 +784,6 @@
 		return;
 
 	free_string(race->name);
-	free_string(race->who_name);
 	for (x = 0; x < 5; x++)
 		free_string(race->skills[x]);
 	free_mem(race->class_mult);
diff -ur ./src/save.c ./new/save.c
--- ./src/save.c	Fri May 16 00:04:56 2003
+++ ./new/save.c	Fri May 16 02:11:35 2003
@@ -40,6 +40,11 @@
 
 /* int rename(const char *oldfname, const char *newfname); viene en stdio.h */
 
+void new_warlist args((CHAR_DATA * ch));
+void free_warlist args((WAR_LIST * wl));
+void new_gqlist args((CHAR_DATA * ch));
+void free_gqlist args((GQ_LIST * gql));
+
 /*
  * Array of containers read for proper re-nesting of objects.
  */
@@ -168,20 +173,7 @@
 		fprintf(fp, "Silv %d\n", 0);
 	fprintf(fp, "Exp  %d\n", ch->exp);
 	if (ch->act != 0)
-	{
-		if (!IS_NPC(ch) && gquest_info.running == GQUEST_OFF
-			&& IS_SET(ch->act, PLR_GQUEST))
-		{
-			REMOVE_BIT(ch->act, PLR_GQUEST);
-			reset_gqmob(ch, 0);
-		}
-		if (!IS_NPC(ch))
-		{
-			if (war_info.iswar == WAR_OFF && IS_SET(ch->act, PLR_WAR))
-				REMOVE_BIT(ch->act, PLR_WAR);
-		}
 		fprintf(fp, "Act  %s\n", fwrite_flags(ch->act));
-	}
 	if (ch->affected_by != 0)
 		fprintf(fp, "AfBy %s\n", fwrite_flags(ch->affected_by));
 	fprintf(fp, "Comm %s\n", fwrite_flags(ch->comm));
@@ -277,15 +269,20 @@
 		if (ch->deity != NULL)
 			fprintf(fp, "Deity %s~\n", ch->deity->name);
 
-		if (ON_GQUEST(ch) || (gquest_info.running != GQUEST_OFF
-							  && count_gqmobs(ch) == gquest_info.mob_count))
+		if (ON_GQUEST(ch))
 		{
-			fprintf(fp, "GQmobs %d ", gquest_info.mob_count);
+			fprintf(fp, "GQmobs ");
 			for (i = 0; i < gquest_info.mob_count; i++)
-				fprintf(fp, "%ld ", ch->pcdata->gq_mobs[i]);
+				fprintf(fp, "%ld ", ch->gquest->gq_mobs[i]);
 			fprintf(fp, "\n");
 		}
 
+		if (war_info.status != WAR_OFF && ch->war != NULL)
+		{
+			fprintf(fp, "WarInfo  %ld %ld %ld %s\n", ch->war->hit,
+					ch->war->mana, ch->war->move, fwrite_flags(ch->war->flags));
+		}
+
 		if (count_home(ch) > 0)
 		{
 			fprintf(fp, "Homes  %d ", MAX_HOUSE_ROOMS);
@@ -623,7 +620,6 @@
 		ch->pcdata->gamestat[i] = 0;
 	ch->pcdata->trivia = 0;
 	end_quest(ch, 0);
-	reset_gqmob(ch, 0);
 	ch->pcdata->timezone = -1;
 }
 
@@ -733,6 +729,11 @@
 				REMOVE_BIT(d->d_flags, DESC_COLOUR);
 		}
 
+		if (ch->war && war_info.status == WAR_OFF)
+			free_warlist(ch->war);
+
+		if (ch->gquest && gquest_info.running == GQUEST_OFF)
+			free_gqlist(ch->gquest);
 	}
 
 	if (found)
@@ -1089,11 +1090,12 @@
 			KEY("Gold", ch->gold, fread_number(fp));
 			if (!str_cmp(word, "GQmobs"))
 			{
-				int maxMob = fread_number(fp);
 				int i;
 
-				for (i = 0; i < maxMob; i++)
-					ch->pcdata->gq_mobs[i] = fread_number(fp);
+				new_gqlist(ch);
+				for (i = 0; i < gquest_info.mob_count; i++)
+					ch->gquest->gq_mobs[i] = fread_number(fp);
+				fread_to_eol(fp);
 				fMatch = TRUE;
 			}
 			if (!str_cmp(word, "Group") || !str_cmp(word, "Gr"))
@@ -1242,8 +1244,6 @@
 				ch->in_room = get_room_index(fread_number(fp));
 				if (ch->in_room == NULL)
 					ch->in_room = get_room_index(ROOM_VNUM_LIMBO);
-				else if (IS_SET(ch->in_room->room_flags, ROOM_ARENA))
-					ch->in_room = get_room_index(ROOM_VNUM_TEMPLE);
 				fMatch = TRUE;
 				break;
 			}
@@ -1326,6 +1326,16 @@
 			break;
 
 		case 'W':
+			if (!str_cmp(word, "WarInfo"))
+			{
+				new_warlist(ch);
+				ch->war->hit = fread_number(fp);
+				ch->war->mana = fread_number(fp);
+				ch->war->move = fread_number(fp);
+				ch->war->flags = fread_flag(fp);
+				fMatch = TRUE;
+				break;
+			}
 			KEY("Wimpy", ch->wimpy, fread_number(fp));
 			KEY("Wimp", ch->wimpy, fread_number(fp));
 			KEY("Wizn", ch->wiznet, fread_flag(fp));
diff -ur ./src/scan.c ./new/scan.c
--- ./src/scan.c	Fri May 16 00:04:56 2003
+++ ./new/scan.c	Fri May 16 02:11:35 2003
@@ -127,7 +127,7 @@
 		&& victim->pIndexData->vnum == ch->pcdata->questmob)
 		strcat(buf, "{r[{RTARGET{r]{x ");
 	if (ON_GQUEST(ch) && IS_NPC(victim) &&
-		is_gqmob(ch, victim->pIndexData->vnum) != -1)
+		is_gqmob(ch->gquest, victim->pIndexData->vnum) != -1)
 		strcat(buf, "(Gquest) ");
 	strcat(buf, PERS(victim, ch));
 	strcat(buf, ", ");
diff -ur ./src/skills.c ./new/skills.c
--- ./src/skills.c	Fri May 16 00:04:56 2003
+++ ./new/skills.c	Fri May 16 02:11:35 2003
@@ -246,9 +246,9 @@
 {
 	BUFFER *buffer;
 	char arg[MAX_INPUT_LENGTH];
-	char spell_list[LEVEL_HERO + 1][MAX_STRING_LENGTH];
-	char spell_columns[LEVEL_HERO + 1];
-	int sn, level, min_lev = 1, max_lev = LEVEL_HERO, mana;
+	char spell_list[MAX_MORTAL_LEVEL + 1][MAX_STRING_LENGTH];
+	char spell_columns[MAX_MORTAL_LEVEL + 1];
+	int sn, level, min_lev = 1, max_lev = MAX_MORTAL_LEVEL, mana;
 	bool fAll = FALSE, found = FALSE;
 	char buf[MAX_STRING_LENGTH];
 
@@ -269,9 +269,10 @@
 			}
 			max_lev = atoi(arg);
 
-			if (max_lev < 1 || max_lev > LEVEL_HERO)
+			if (max_lev < 1 || max_lev > MAX_MORTAL_LEVEL)
 			{
-				chprintlnf(ch, "Levels must be between 1 and %d.", LEVEL_HERO);
+				chprintlnf(ch, "Levels must be between 1 and %d.",
+						   MAX_MORTAL_LEVEL);
 				return;
 			}
 
@@ -286,10 +287,11 @@
 				min_lev = max_lev;
 				max_lev = atoi(arg);
 
-				if (max_lev < 1 || max_lev > LEVEL_HERO)
+				if (max_lev < 1 || max_lev > MAX_MORTAL_LEVEL)
 				{
 					chprintlnf(ch,
-							   "Levels must be between 1 and %d.", LEVEL_HERO);
+							   "Levels must be between 1 and %d.",
+							   MAX_MORTAL_LEVEL);
 					return;
 				}
 
@@ -303,7 +305,7 @@
 	}
 
 	/* initialize data */
-	for (level = 0; level < LEVEL_HERO + 1; level++)
+	for (level = 0; level < MAX_MORTAL_LEVEL + 1; level++)
 	{
 		spell_columns[level] = 0;
 		spell_list[level][0] = '\0';
@@ -314,7 +316,7 @@
 		if (skill_table[sn].name == NULL)
 			break;
 
-		if ((level = skill_level(ch, sn)) < LEVEL_HERO + 1 &&
+		if ((level = skill_level(ch, sn)) < MAX_MORTAL_LEVEL + 1 &&
 			(fAll || level <= ch->level) && level >= min_lev &&
 			level <= max_lev && skill_table[sn].spell_fun != spell_null &&
 			ch->pcdata->learned[sn] > 0)
@@ -351,7 +353,7 @@
 	}
 
 	buffer = new_buf();
-	for (level = 0; level < LEVEL_HERO + 1; level++)
+	for (level = 0; level < MAX_MORTAL_LEVEL + 1; level++)
 		if (spell_list[level][0] != '\0')
 			add_buf(buffer, spell_list[level]);
 	add_buf(buffer, "\n\r");
@@ -363,9 +365,9 @@
 {
 	BUFFER *buffer;
 	char arg[MAX_INPUT_LENGTH];
-	char skill_list[LEVEL_HERO + 1][MAX_STRING_LENGTH];
-	char skill_columns[LEVEL_HERO + 1];
-	int sn, level, min_lev = 1, max_lev = LEVEL_HERO;
+	char skill_list[MAX_MORTAL_LEVEL + 1][MAX_STRING_LENGTH];
+	char skill_columns[MAX_MORTAL_LEVEL + 1];
+	int sn, level, min_lev = 1, max_lev = MAX_MORTAL_LEVEL;
 	bool fAll = FALSE, found = FALSE;
 	char buf[MAX_STRING_LENGTH];
 
@@ -386,9 +388,10 @@
 			}
 			max_lev = atoi(arg);
 
-			if (max_lev < 1 || max_lev > LEVEL_HERO)
+			if (max_lev < 1 || max_lev > MAX_MORTAL_LEVEL)
 			{
-				chprintlnf(ch, "Levels must be between 1 and %d.", LEVEL_HERO);
+				chprintlnf(ch, "Levels must be between 1 and %d.",
+						   MAX_MORTAL_LEVEL);
 				return;
 			}
 
@@ -403,10 +406,11 @@
 				min_lev = max_lev;
 				max_lev = atoi(arg);
 
-				if (max_lev < 1 || max_lev > LEVEL_HERO)
+				if (max_lev < 1 || max_lev > MAX_MORTAL_LEVEL)
 				{
 					chprintlnf(ch,
-							   "Levels must be between 1 and %d.", LEVEL_HERO);
+							   "Levels must be between 1 and %d.",
+							   MAX_MORTAL_LEVEL);
 					return;
 				}
 
@@ -420,7 +424,7 @@
 	}
 
 	/* initialize data */
-	for (level = 0; level < LEVEL_HERO + 1; level++)
+	for (level = 0; level < MAX_MORTAL_LEVEL + 1; level++)
 	{
 		skill_columns[level] = 0;
 		skill_list[level][0] = '\0';
@@ -431,7 +435,7 @@
 		if (skill_table[sn].name == NULL)
 			break;
 
-		if ((level = skill_level(ch, sn)) < LEVEL_HERO + 1 &&
+		if ((level = skill_level(ch, sn)) < MAX_MORTAL_LEVEL + 1 &&
 			(fAll || level <= ch->level) && level >= min_lev &&
 			level <= max_lev && skill_table[sn].spell_fun == spell_null &&
 			ch->pcdata->learned[sn] > 0)
@@ -464,7 +468,7 @@
 	}
 
 	buffer = new_buf();
-	for (level = 0; level < LEVEL_HERO + 1; level++)
+	for (level = 0; level < MAX_MORTAL_LEVEL + 1; level++)
 		if (skill_list[level][0] != '\0')
 			add_buf(buffer, skill_list[level]);
 	add_buf(buffer, "\n\r");
@@ -1028,8 +1032,8 @@
 	char buf2[MSL];
 	char buf3[MSL];
 	BUFFER *buffer;
-	char skill_list[LEVEL_HERO + 1][MSL];
-	char skill_columns[LEVEL_HERO + 1];
+	char skill_list[MAX_MORTAL_LEVEL + 1][MSL];
+	char skill_columns[MAX_MORTAL_LEVEL + 1];
 	int sn, snc, level;
 	int x;
 	int clas;
@@ -1047,7 +1051,7 @@
 
 	if ((clas = class_lookup(argument)) > -1)
 	{
-		for (level = 0; level < LEVEL_HERO + 1; level++)
+		for (level = 0; level < MAX_MORTAL_LEVEL + 1; level++)
 		{
 			skill_columns[level] = 0;
 			skill_list[level][0] = '\0';
@@ -1058,7 +1062,8 @@
 			if (skill_table[snc].name == NULL)
 				break;
 
-			if ((level = skill_table[snc].skill_level[clas]) <= LEVEL_HERO)
+			if ((level = skill_table[snc].skill_level[clas]) <=
+				MAX_MORTAL_LEVEL)
 			{
 				found = TRUE;
 				level = skill_table[snc].skill_level[clas];
@@ -1081,7 +1086,7 @@
 		}
 
 		buffer = new_buf();
-		for (level = 0; level < LEVEL_HERO + 1; level++)
+		for (level = 0; level < MAX_MORTAL_LEVEL + 1; level++)
 		{
 			if (!IS_NULLSTR(skill_list[level]))
 				add_buf(buffer, skill_list[level]);
@@ -1098,10 +1103,10 @@
 		strcat(buf, "{m: [");
 		for (x = 0; x < maxClass; x++)
 		{
-			if (skill_table[sn].skill_level[x] > LEVEL_HERO)
-				sprintf(buf2, "{W%s: {c%s  ", class_table[x].who_name, "n/a");
+			if (skill_table[sn].skill_level[x] > MAX_MORTAL_LEVEL)
+				sprintf(buf2, "{W%3.3s: {c%s  ", class_table[x].name, "n/a");
 			else
-				sprintf(buf2, "{W%s: {c%03d  ", class_table[x].who_name,
+				sprintf(buf2, "{W%3.3s: {c%03d  ", class_table[x].name,
 						skill_table[sn].skill_level[x]);
 			strcat(buf, buf2);
 		}
diff -ur ./src/tables.c ./new/tables.c
--- ./src/tables.c	Fri May 16 00:04:56 2003
+++ ./new/tables.c	Fri May 16 02:11:35 2003
@@ -96,7 +96,6 @@
 const struct flag_type plr_flags[] = {
 	{"npc", PLR_IS_NPC, FALSE},
 	{"automap", PLR_AUTOMAP, TRUE},
-	{"war", PLR_WAR, FALSE},
 	{"autoassist", PLR_AUTOASSIST, FALSE},
 	{"autoexit", PLR_AUTOEXIT, FALSE},
 	{"autoloot", PLR_AUTOLOOT, FALSE},
@@ -104,7 +103,6 @@
 	{"autogold", PLR_AUTOGOLD, FALSE},
 	{"autosplit", PLR_AUTOSPLIT, FALSE},
 	{"holylight", PLR_HOLYLIGHT, FALSE},
-	{"gquest", PLR_GQUEST, TRUE},
 	{"can_loot", PLR_CANLOOT, FALSE},
 	{"nosummon", PLR_NOSUMMON, FALSE},
 	{"nofollow", PLR_NOFOLLOW, FALSE},
diff -ur ./src/tablesave.c ./new/tablesave.c
--- ./src/tablesave.c	Fri May 16 00:04:56 2003
+++ ./new/tablesave.c	Fri May 16 02:11:35 2003
@@ -64,6 +64,7 @@
 #define FIELD_LONG              13
 #define FIELD_STRING_ARRAY_NULL 14
 #define FIELD_RANK              15
+#define FIELD_LONG_ALLOC_ARRAY  16
 
 typedef char *STR_FUNC(void *);
 typedef bool STR_READ_FUNC(void *, const char *);
@@ -81,6 +82,7 @@
 DEITY_DATA deity;
 WPWD_DATA pwd;
 MBR_DATA mbr;
+WAR_DATA war;
 
 const char *do_fun_name(DO_FUN *);
 DO_FUN *do_fun_lookup(const char *);
@@ -272,7 +274,6 @@
 	{"vuln", FIELD_FLAGVECTOR, (void *) &race.vuln, NULL, NULL},
 	{"form", FIELD_FLAGVECTOR, (void *) &race.form, NULL, NULL},
 	{"parts", FIELD_FLAGVECTOR, (void *) &race.parts, NULL, NULL},
-	{"who", FIELD_STRING, (void *) &race.who_name, NULL, NULL},
 	{"points", FIELD_INT, (void *) &race.points, NULL, NULL},
 
 	{"classx", FIELD_INT_ALLOC_ARRAY, (void *) &race.class_mult,
@@ -303,7 +304,6 @@
 
 const struct savetable_type classsavetable[] = {
 	{"name", FIELD_STRING, (void *) &cls.name, NULL, NULL},
-	{"whoname", FIELD_STRING, (void *) &cls.who_name, NULL, NULL},
 	{"prime", FIELD_INT, (void *) &cls.attr_prime, NULL, NULL},
 	{"weapon", FIELD_LONG, (void *) &cls.weapon, NULL, NULL},
 
@@ -359,8 +359,6 @@
 
 const struct savetable_type gqsavetable[] = {
 
-	{"mobs", FIELD_LONG_ARRAY, (void *) &gq.mobs, (void *) MAX_GQUEST_MOB,
-	 (void *) -1},
 	{"mcount", FIELD_INT, (void *) &gq.mob_count, NULL, NULL},
 	{"who", FIELD_STRING, (void *) &gq.who, NULL, NULL},
 	{"timer", FIELD_INT, (void *) &gq.timer, NULL, NULL},
@@ -370,7 +368,8 @@
 	{"minlev", FIELD_INT, (void *) &gq.minlevel, NULL, NULL},
 	{"maxlev", FIELD_INT, (void *) &gq.maxlevel, NULL, NULL},
 	{"running", FIELD_INT, (void *) &gq.running, NULL, NULL},
-	{"next", FIELD_INT, (void *) &gq.next, NULL, NULL},
+	{"mobs", FIELD_LONG_ALLOC_ARRAY, (void *) &gq.mobs, (void *) &gquest_info.mob_count,
+	 (void *) -1},
 	{NULL, 0, NULL, NULL, NULL}
 };
 
@@ -396,6 +395,17 @@
 	{NULL, 0, NULL, NULL, NULL}
 };
 
+const struct savetable_type warsavetable[] = {
+	{"who", FIELD_STRING, (void *) &war.who, NULL, NULL},
+	{"minlvl", FIELD_INT, (void *) &war.min_level, NULL, NULL},
+	{"maxlvl", FIELD_INT, (void *) &war.max_level, NULL, NULL},
+	{"inwar", FIELD_INT, (void *) &war.inwar, NULL, NULL},
+	{"type", FIELD_INT, (void *) &war.wartype, NULL, NULL},
+	{"timer", FIELD_INT, (void *) &war.timer, NULL, NULL},
+	{"status", FIELD_INT, (void *) &war.status, NULL, NULL},
+	{NULL, 0, NULL, NULL, NULL}
+};
+
 void load_struct(FILE * fp, void *typebase,
 				 const struct savetable_type *table, void *puntero)
 {
@@ -407,6 +417,7 @@
 	int *pint;
 	int **array;
 	long *plong;
+	long **larray;
 	STR_READ_FUNC *function;
 	struct flag_type *flagtable;
 	bool found = FALSE;
@@ -556,6 +567,25 @@
 					found = TRUE, cnt++;
 					break;
 
+				case FIELD_LONG_ALLOC_ARRAY:
+					larray =
+						(long **) ((int) temp->puntero_field - (int) typebase +
+								   (int) puntero);
+					i = 0;
+					alloc_mem(*larray, long, *(int *) temp->argument);
+					while (str_cmp((string = fread_word(fp)), "@"))
+					{
+						if (i == *(int *) temp->argument)
+							bugf("field_shint_array %s has excess elements",
+								 temp->field);
+						else
+							(*larray)[i++] = (long) atol(string);
+					}
+					while (i < *(int *) temp->argument)
+						(*larray)[i++] = (long) temp->argument2;
+					found = TRUE, cnt++;
+					break;
+
 				case FIELD_STRING_ARRAY:
 				case FIELD_STRING_ARRAY_NULL:
 					pstring =
@@ -633,6 +663,7 @@
 	int *pint;
 	long *plong;
 	int **array;
+	long **larray;
 	STR_FUNC *function;
 	const char *string;
 	flag_t *pentero;
@@ -744,6 +775,16 @@
 			fprintf(fp, "@\n");
 			break;
 
+		case FIELD_LONG_ALLOC_ARRAY:
+			larray =
+				(long **) ((int) temp->puntero_field - (int) typebase +
+						   (int) puntero);
+			fprintf(fp, "%s\t\t", temp->field);
+			for (i = 0; i < *(int *) temp->argument; i++)
+				fprintf(fp, "%ld ", (*larray)[i]);
+			fprintf(fp, "@\n");
+			break;
+
 		case FIELD_STRING_ARRAY:
 			pstring =
 				(const char **) ((int) temp->puntero_field - (int) typebase +
@@ -774,8 +815,8 @@
 			fprintf(fp, "%s\t\t", temp->field);
 			for (i = 0;
 				 i <
-				 (temp->argument ? (int) temp->argument : *(int *) temp->
-				  argument2); i++)
+				 (temp->argument ? (int) temp->
+				  argument : *(int *) temp->argument2); i++)
 				fprintf(fp, "%d ", pbool[i] == TRUE ? 1 : 0);
 			fprintf(fp, "@\n");
 			break;
@@ -1629,4 +1670,56 @@
 		LINK(pmbr, mbr_first, mbr_last, next, prev);
 	}
 	file_close(fp);
+}
+
+bool save_war_data(void)
+{
+	FILE_DATA *fp;
+
+	if (!(fp = fopen_temp(WAR_FILE)))
+	{
+		bugf("Could not open file %s in order to save war data.", WAR_FILE);
+		return FALSE;
+	}
+
+	fprintf(fp->file, "#WARDATA\n");
+	save_struct(fp->file, &war, warsavetable, &war_info);
+	fprintf(fp->file, "#END\n");
+	fprintf(fp->file, "\n#!\n");
+	fclose_temp(fp);
+	return TRUE;
+}
+
+bool load_war_data(void)
+{
+	FILE *fp;
+	const char *word;
+
+	end_war();
+
+	if (!(fp = file_open(WAR_FILE, "r")))
+	{
+		bugf("Could not open file %s in order to read gquest data. Creating.",
+			 WAR_FILE);
+		file_close(fp);
+		return save_war_data();
+	}
+
+	for (;;)
+	{
+		word = fread_word(fp);
+
+		if (!str_cmp(word, "#!"))
+			break;
+
+		if (str_cmp(word, "#WARDATA"))
+		{
+			bugf("Invalid war data file (%s).\n\r", WAR_FILE);
+			return FALSE;
+		}
+		load_struct(fp, &war, warsavetable, &war_info);
+	}
+
+	file_close(fp);
+	return TRUE;
 }
diff -ur ./src/update.c ./new/update.c
--- ./src/update.c	Fri May 16 00:04:56 2003
+++ ./new/update.c	Fri May 16 02:11:35 2003
@@ -111,12 +111,13 @@
 void gain_exp(CHAR_DATA * ch, int gain)
 {
 	char buf[MAX_STRING_LENGTH];
+	int maxl;
 
-	if (IS_NPC(ch) || ch->level >= LEVEL_HERO)
+	if (IS_NPC(ch) || ch->level >= (maxl = calc_max_level(ch)))
 		return;
 
 	ch->exp = UMAX(exp_per_level(ch, ch->pcdata->points), ch->exp + gain);
-	while (ch->level < LEVEL_HERO &&
+	while (ch->level < maxl &&
 		   ch->exp >= exp_per_level(ch, ch->pcdata->points) * (ch->level + 1))
 	{
 		chprintln(ch, "You raise a level!!");
@@ -125,7 +126,15 @@
 		log_string(buf);
 		sprintf(buf, "$N has attained level %d!", ch->level);
 		wiznet(buf, ch, NULL, WIZ_LEVELS, 0, 0);
-		announce(ch, INFO_LEVEL, "$n has attained level %d!", ch->level);
+		if (ch->level >= LEVEL_HERO)
+		{
+			chprintlnf(ch, "Congratulations, you are now a %s!",
+					   high_level_name(ch->level, TRUE));
+			announce(ch, INFO_LEVEL, "$n is now a %s!",
+					 high_level_name(ch->level, TRUE));
+		}
+		else
+			announce(ch, INFO_LEVEL, "$n has attained level %d!", ch->level);
 		advance_level(ch, FALSE);
 		save_char_obj(ch);
 	}
@@ -669,6 +678,7 @@
 			/* check to see if we need to go home */
 			if (IS_NPC(ch) && ch->zone != NULL &&
 				ch->zone != ch->in_room->area && ch->desc == NULL &&
+				ch->war == NULL &&
 				ch->fighting == NULL && !IS_AFFECTED(ch, AFF_CHARM)
 				&& number_percent() < 5)
 			{
@@ -1171,6 +1181,7 @@
 	{
 		pulse_area = PULSE_AREA;
 		/* number_range( PULSE_AREA / 2, 3 * PULSE_AREA / 2 ); */
+		update_last_func(NULL, "pulse_area", "");
 		area_update();
 		bank_update();
 #if !defined(NO_WEB)
@@ -1182,26 +1193,30 @@
 	if (--pulse_music <= 0)
 	{
 		pulse_music = PULSE_MUSIC;
+		update_last_func(NULL, "pulse_music", "");
 		song_update();
 	}
 
 	if (--pulse_mobile <= 0)
 	{
 		pulse_mobile = PULSE_MOBILE;
+		update_last_func(NULL, "pulse_mobile", "");
 		mobile_update();
 	}
 
 	if (--pulse_violence <= 0)
 	{
 		pulse_violence = PULSE_VIOLENCE;
+		update_last_func(NULL, "pulse_violence", "");
 		violence_update();
 	}
 
 	if (--pulse_point <= 0)
 	{
-		wiznet("TICK!", NULL, NULL, WIZ_TICKS, 0, 0);
 		pulse_point = PULSE_TICK;
 /* number_range( PULSE_TICK / 2, 3 * PULSE_TICK / 2 ); */
+		update_last_func(NULL, "pulse_point", "");
+		wiznet("TICK!", NULL, NULL, WIZ_TICKS, 0, 0);
 		weather_update();
 		char_update();
 		obj_update();
@@ -1210,8 +1225,11 @@
 		war_update();
 	}
 
+	update_last_func(NULL, "auction_update", "");
 	auction_update();
+	update_last_func(NULL, "aggr_update", "");
 	aggr_update();
+	update_last_func(NULL, "N/A", "");
 	tail_chain();
 	return;
 }
diff -ur ./src/war.c ./new/war.c
--- ./src/war.c	Fri May 16 00:04:56 2003
+++ ./new/war.c	Fri May 16 02:11:35 2003
@@ -36,11 +36,12 @@
 #include "recycle.h"
 #include "interp.h"
 
+#define WAR_KILLED	(BIT_A)
+#define WAR_DECOY	(BIT_B)
+
 void make_note(const char *board_name, const char *sender, const char *to,
 			   const char *subject, const int expire_days, const char *text);
 
-#define IS_SET_WAR(ch) (!IS_NPC(ch) && (IS_SET((ch)->act, PLR_WAR) || (ch)->pcdata->still_in_war == TRUE))
-
 struct war_type
 {
 	const char *name;
@@ -54,7 +55,8 @@
 	{"race", "races", WAR_RACE},
 	{"class", "classes", WAR_CLASS},
 	{"genocide", "people", WAR_GENOCIDE},
-	{"deity", "deities", WAR_DEITY}
+	{"deity", "deities", WAR_DEITY},
+	{"sex", "sexes", WAR_SEX}
 };
 
 int war_lookup(const char *arg)
@@ -82,13 +84,50 @@
 	return "Unknown";
 }
 
+void new_warlist(CHAR_DATA * ch)
+{
+	WAR_LIST *wl;
+
+	if (!ch)
+		return;
+
+	alloc_mem(wl, WAR_LIST, 1);
+	wl->hit = ch->hit;
+	wl->mana = ch->mana;
+	wl->move = ch->move;
+	if (IS_NPC(ch))
+		wl->flags = WAR_DECOY;
+	else
+	{
+		wl->flags = 0;
+		war_info.inwar++;
+	}
+	wl->ch = ch;
+	ch->war = wl;
+	LINK(wl, war_info.first, war_info.last, next, prev);
+	return;
+}
+
+void free_warlist(WAR_LIST * wl)
+{
+	if (wl->ch)
+	{
+		if (!IS_NPC(wl->ch))
+			wl->ch->war = NULL;
+		else
+			extract_char(wl->ch, TRUE);
+	}
+	UNLINK(wl, war_info.first, war_info.last, next, prev);
+	free_mem(wl);
+}
+
 #define WAR_COST 3				// in trivia points
 
 bool start_war(CHAR_DATA * ch, const char *argument)
 {
 	char arg1[MIL], arg2[MIL];
 	char arg3[MIL];
-	CHAR_DATA *wch, *warmaster = NULL;
+	CHAR_DATA *warmaster = NULL;
 	int blevel, elevel, type;
 
 	for (warmaster = ch->in_room->first_person; warmaster != NULL;
@@ -168,7 +207,7 @@
 		return FALSE;
 	}
 
-	if (war_info.iswar != WAR_OFF)
+	if (war_info.status != WAR_OFF)
 	{
 		chprintln(ch, "There is already a war going!");
 		return FALSE;
@@ -197,7 +236,7 @@
 		}
 	}
 
-	war_info.iswar = WAR_WAITING;
+	war_info.status = WAR_WAITING;
 	replace_string(war_info.who, ch->name);
 	war_info.min_level = blevel;
 	war_info.max_level = elevel;
@@ -206,31 +245,22 @@
 			 "$n announces a %s war for levels %d to %d.  Type 'WAR JOIN' to kill or be killed.",
 			 wartype_name(war_info.wartype, FALSE), war_info.min_level,
 			 war_info.max_level);
-	if (ch)
-		chprintf(ch,
-				 "You announce a %s war for levels %d to %d.  Type 'WAR JOIN' to kill or be killed.",
-				 wartype_name(war_info.wartype, FALSE), war_info.min_level,
-				 war_info.max_level);
+	announce(ch, INFO_WAR | INFO_PRIVATE,
+			 "You announce a %s war for levels %d to %d.  Type 'WAR JOIN' to kill or be killed.",
+			 wartype_name(war_info.wartype, FALSE), war_info.min_level,
+			 war_info.max_level);
 	war_info.timer = 3;
-	war_info.next = 0;
-	for (wch = player_first; wch != NULL; wch = wch->next_player)
-	{
-		if (IS_SET(wch->act, PLR_WAR))
-			REMOVE_BIT(wch->act, PLR_WAR);
-		if (wch->pcdata->still_in_war)
-			wch->pcdata->still_in_war = FALSE;
-	}
 	return TRUE;
 }
 
 void auto_war(void)
 {
 	CHAR_DATA *wch, *wch_last, *warmaster;
-	int maxlvl = 0, minlvl = MAX_LEVEL, middle = LEVEL_HERO / 2;
+	int maxlvl = 0, minlvl = MAX_LEVEL, middle = MAX_MORTAL_LEVEL / 2;
 	int clan = 0, count = 0, lbonus = 0, half = 0;
 	int heros = 0;
 
-	if (war_info.iswar != WAR_OFF)
+	if (war_info.status != WAR_OFF)
 		return;
 
 	for (wch = player_first; wch != NULL; wch = wch->next_player)
@@ -243,7 +273,7 @@
 			count++;
 			maxlvl = UMAX(maxlvl, wch->level);
 			minlvl = UMIN(minlvl, wch->level);
-			if (wch->level == LEVEL_HERO || wch->level == LEVEL_HERO)
+			if (wch->level >= LEVEL_HERO && wch->level <= MAX_MORTAL_LEVEL)
 				heros++;
 			if (is_clan(wch))
 			{
@@ -266,19 +296,19 @@
 
 	lbonus = number_range(15, 30);
 	minlvl = UMAX(1, minlvl - lbonus);
-	maxlvl = UMIN(LEVEL_HERO, maxlvl + lbonus);
+	maxlvl = UMIN(MAX_MORTAL_LEVEL, maxlvl + lbonus);
 	half = ((maxlvl - minlvl) / 2);
 	middle = URANGE(minlvl, maxlvl - half, maxlvl);
 	minlvl = UMAX(1, number_range(minlvl, (middle * 2) / 3));
 	if (heros > 2 && number_percent() < 25)
-		maxlvl = LEVEL_HERO;
+		maxlvl = MAX_MORTAL_LEVEL;
 	else
-		maxlvl = UMIN(LEVEL_HERO, number_range((middle * 3) / 2, maxlvl));
+		maxlvl = UMIN(MAX_MORTAL_LEVEL, number_range((middle * 3) / 2, maxlvl));
 	for (warmaster = char_first; warmaster != NULL; warmaster = warmaster->next)
 		if (warmaster->pIndexData
 			&& warmaster->pIndexData->vnum == MOB_VNUM_WARMASTER)
 			break;
-	war_info.iswar = WAR_WAITING;
+	war_info.status = WAR_WAITING;
 	replace_string(war_info.who,
 				   (!warmaster ? "AutoWar (tm)" : warmaster->short_descr));
 	war_info.min_level = minlvl;
@@ -299,55 +329,46 @@
 			 !warmaster ? "A" : "$n announces a",
 			 wartype_name(war_info.wartype, FALSE), war_info.min_level,
 			 war_info.max_level, !warmaster ? " has started" : "");
-	if (warmaster)
-		chprintf(warmaster,
-				 "You announce a %s war for levels %d"
-				 " to %d.  Type 'WAR JOIN' to kill or be killed.",
-				 wartype_name(war_info.wartype, FALSE), war_info.min_level,
-				 war_info.max_level);
+	announce(warmaster, INFO_WAR | INFO_PRIVATE,
+			 "You announce a %s war for levels %d"
+			 " to %d.  Type 'WAR JOIN' to kill or be killed.",
+			 wartype_name(war_info.wartype, FALSE), war_info.min_level,
+			 war_info.max_level);
 	war_info.timer = 3;
-	war_info.next = 0;
-	for (wch = player_first; wch != NULL; wch = wch->next_player)
-	{
-		if (IS_SET(wch->act, PLR_WAR))
-			REMOVE_BIT(wch->act, PLR_WAR);
-		if (wch->pcdata->still_in_war)
-			wch->pcdata->still_in_war = FALSE;
-	}
 }
 
 void end_war(void)
 {
-	CHAR_DATA *wch;
+	WAR_LIST *wl, *wl_next;
 
-	replace_string(war_info.who, "");
-	war_info.wartype = WAR_NONE;
-	war_info.min_level = 0;
-	war_info.max_level = 0;
-	war_info.iswar = WAR_OFF;
-	war_info.inwar = 0;
-	war_info.timer = 0;
-	war_info.next = number_range(100, 200);
-	for (wch = player_first; wch != NULL; wch = wch->next_player)
+	for (wl = war_info.first; wl != NULL; wl = wl_next)
 	{
-		if (IS_SET_WAR(wch))
+		wl_next = wl->next;
+
+		if (!IS_SET(wl->flags, WAR_DECOY) && wl->ch)
 		{
-			stop_fighting(wch, TRUE);
-			REMOVE_BIT(wch->act, PLR_WAR);
-			wch->pcdata->still_in_war = FALSE;
-			if (IS_SET(wch->in_room->room_flags, ROOM_ARENA)
-				|| wch->in_room->vnum == ROOM_VNUM_WAITROOM)
+			stop_fighting(wl->ch, TRUE);
+			if (!IS_SET(wl->flags, WAR_KILLED))
 			{
-				char_from_room(wch);
-				char_to_room(wch, get_room_index(ROOM_VNUM_TEMPLE));
+				char_from_room(wl->ch);
+				char_to_room(wl->ch, get_room_index(ROOM_VNUM_TEMPLE));
 			}
-			wch->hit = wch->max_hit;
-			wch->mana = wch->max_mana;
-			wch->move = wch->max_move;
-			update_pos(wch);
-			do_function(wch, &do_look, "auto");
+			wl->ch->hit = wl->hit;
+			wl->ch->mana = wl->mana;
+			wl->ch->move = wl->move;
+			update_pos(wl->ch);
+			do_function(wl->ch, &do_look, "auto");
 		}
+		free_warlist(wl);
 	}
+	replace_string(war_info.who, "");
+	war_info.wartype = WAR_NONE;
+	war_info.min_level = 0;
+	war_info.max_level = 0;
+	war_info.status = WAR_OFF;
+	war_info.inwar = 0;
+	war_info.timer = number_range(100, 200);
+	war_info.first = war_info.last = NULL;
 }
 
 const char *wartype_info(CHAR_DATA * ch)
@@ -359,32 +380,36 @@
 	case WAR_RACE:
 		return ch->race->name;
 	case WAR_CLASS:
-		return class_table[ch->Class[0]].name;
+		return class_table[prime_class(ch)].name;
 	case WAR_GENOCIDE:
 		return ch->name;
 	case WAR_CLAN:
 		return ch->clan->who_name;
 	case WAR_DEITY:
 		return ch->deity->name;
+	case WAR_SEX:
+		return flag_string(sex_flags, ch->sex);
 	}
 }
 
-void *wartype_data(CHAR_DATA * ch)
+bool check_wartype_data(CHAR_DATA * ch, CHAR_DATA * victim)
 {
 	switch (war_info.wartype)
 	{
 	default:
-		return NULL;
+		return FALSE;
 	case WAR_RACE:
-		return ch->race;
+		return (ch->race == victim->race);
 	case WAR_CLASS:
-		return &ch->Class[0];
+		return (prime_class(ch) == prime_class(victim));
 	case WAR_GENOCIDE:
-		return &ch->id;
+		return (ch->id == victim->id);
 	case WAR_CLAN:
-		return ch->clan;
+		return (ch->clan == victim->clan);
 	case WAR_DEITY:
-		return ch->deity;
+		return (ch->deity == victim->deity);
+	case WAR_SEX:
+		return (ch->sex == victim->sex);
 	}
 }
 
@@ -418,6 +443,7 @@
 		chprintln(ch, "         {Rwar {Wstatus");
 		chprintln(ch, "         {Rwar {Winfo");
 		chprintln(ch, "         {Rwar {Wjoin{x");
+		chprintln(ch, "         {Rwar {Wdecoy{x");
 		if (IS_IMMORTAL(ch))
 			chprintln(ch, "         {Rwar {Wend{x");
 		return;
@@ -442,24 +468,24 @@
 	}
 	else if (!str_cmp(arg, "next") && IS_IMMORTAL(ch))
 	{
-		if (war_info.iswar == WAR_RUNNING)
+		if (war_info.status != WAR_OFF)
 		{
 			chprintln(ch, "Not while a war is running.");
 			return;
 		}
 
 		i = is_number(argument) ? atoi(argument) : number_range(30, 100);
-		war_info.next = i;
+		war_info.timer = i;
 		chprintf(ch, "The next war will start in %d minutes.\n\r",
-				 war_info.next);
+				 war_info.timer);
 		return;
 	}
 
-	if (war_info.iswar != WAR_RUNNING && war_info.iswar != WAR_WAITING)
+	if (war_info.status != WAR_RUNNING && war_info.status != WAR_WAITING)
 	{
 		chprintf(ch,
 				 "There is no war going! The next war will start in %d minutes.",
-				 war_info.next);
+				 war_info.timer);
 		return;
 	}
 
@@ -468,10 +494,10 @@
 		end_war();
 		announce(ch, INFO_WAR,
 				 "$n has ended the war. The next autowar will start in %d minutes.",
-				 war_info.next);
+				 war_info.timer);
 		announce(ch, INFO_WAR | INFO_PRIVATE,
 				 "You have ended the war. The next autowar will start in %d minutes.",
-				 war_info.next);
+				 war_info.timer);
 		return;
 	}
 	else if (!str_cmp(arg, "info"))
@@ -486,7 +512,7 @@
 		chprintlnf(ch, "{RLevels      : {W%d - %d{x", war_info.min_level,
 				   war_info.max_level);
 		chprintlnf(ch, "{RStatus      : {W%s for %d minutes.{x",
-				   war_info.iswar == WAR_WAITING ? "Waiting" : "Running",
+				   war_info.status == WAR_WAITING ? "Waiting" : "Running",
 				   war_info.timer);
 		chprintlnf(ch, "{RType        : {W%s war.{x",
 				   wartype_name(war_info.wartype, FALSE));
@@ -495,21 +521,25 @@
 	}
 	else if (!str_cmp(arg, "status"))
 	{
-		CHAR_DATA *wch;
+		WAR_LIST *wl;
 		bool found = FALSE;
 
 		chprintlnf(ch, "{g%s{x",
 				   stringf(ch, 0, ALIGN_CENTER, "-", "[ {WWAR COMBATENTS{g ]"));
-		for (wch = player_first; wch != NULL; wch = wch->next_player)
+		for (wl = war_info.first; wl != NULL; wl = wl->next)
 		{
-			if (IS_SET(wch->act, PLR_WAR))
+			if (!IS_SET(wl->flags, WAR_DECOY) && wl->ch)
 			{
-				chprintf(ch,
-						 "{W%s : [{R%ld%% hit{W] [{M%ld%% mana{W] [Pos: {G%s{W]{x",
-						 warrior_status(wch),
-						 wch->hit * 100 / wch->max_hit,
-						 wch->mana * 100 / wch->max_mana,
-						 position_flags[wch->position].name);
+				if (!IS_SET(wl->flags, WAR_KILLED))
+					chprintlnf(ch,
+							   "{W%-25s : [{R%ld%% hit{W] [{M%ld%% mana{W] [Pos: {G%s{W]{x",
+							   warrior_status(wl->ch),
+							   wl->ch->hit * 100 / wl->ch->max_hit,
+							   wl->ch->mana * 100 / wl->ch->max_mana,
+							   position_flags[wl->ch->position].name);
+				else
+					chprintlnf(ch, "{W%-25s [{RKILLED{W]{x",
+							   warrior_status(wl->ch));
 				found = TRUE;
 			}
 		}
@@ -518,6 +548,71 @@
 		chprintf(ch, "{g%s{x\n\r", draw_line(ch, NULL, 0));
 		return;
 	}
+	else if (!str_cmp(arg, "decoy"))
+	{
+		WAR_LIST *wl;
+		CHAR_DATA *dc;
+		char buf[MSL];
+		int count = 0;
+
+		if (war_info.status != WAR_RUNNING)
+		{
+			chprintln(ch, "Wait untill the war starts.");
+			return;
+		}
+
+		if (!IS_IN_WAR(ch))
+		{
+			chprintln(ch, "You aren't in the war.");
+			return;
+		}
+
+		for (wl = war_info.first; wl; wl = wl->next)
+		{
+			if (!IS_SET(wl->flags, WAR_DECOY))
+				continue;
+
+			if (!wl->ch || wl->ch == ch)
+				continue;
+
+			if (str_cmp(wl->ch->name, ch->name))
+				continue;
+
+			count++;
+		}
+
+		if (count >= 5)
+		{
+			chprintln(ch, "I'm sorry you are only allowed to deploy 5 decoys.");
+			return;
+		}
+
+		if ((dc = create_mobile(get_mob_index(MOB_VNUM_DUMMY))) == NULL)
+		{
+			chprintln(ch, "Opps, seems there was a problem creating a decoy!");
+			return;
+		}
+
+		replace_string(dc->name, ch->name);
+		sprintf(buf, "%s's Decoy", ch->name);
+		replace_string(dc->short_descr, buf);
+		sprintf(buf, "%s%s is here.\n\r", ch->name, ch->pcdata->title);
+		replace_string(dc->long_descr, buf);
+		replace_string(dc->description, ch->description);
+		dc->affected_by = ch->affected_by;
+		dc->level = ch->level;
+		dc->sex = ch->sex;
+		dc->race = ch->race;
+		memcpy(dc->Class, ch->Class, MAX_MCLASS);
+		dc->deity = ch->deity;
+		dc->hit = ch->hit;
+		dc->max_hit = ch->max_hit;
+		dc->clan = ch->clan;
+		char_to_room(dc, ch->in_room);
+		new_warlist(dc);
+		chprintln(ch, "A decoy of yourself suddenly appears in the room.");
+		return;
+	}
 	else if (!str_cmp(arg, "join"))
 	{
 
@@ -527,7 +622,7 @@
 			return;
 		}
 
-		if (war_info.iswar == WAR_RUNNING)
+		if (war_info.status == WAR_RUNNING)
 		{
 			chprintln(ch, "The war has already started, your too late.");
 			return;
@@ -539,7 +634,7 @@
 			return;
 		}
 
-		if (IS_SET_WAR(ch))
+		if (ch->war != NULL)
 		{
 			chprintln(ch, "You are already in the war.");
 			return;
@@ -573,11 +668,9 @@
 				NULL, TO_ROOM);
 			char_from_room(ch);
 			char_to_room(ch, location);
-			ch->pcdata->still_in_war = TRUE;
-			SET_BIT(ch->act, PLR_WAR);
+			new_warlist(ch);
 			announce(NULL, INFO_WAR, "%s joins the war!", warrior_status(ch));
 			act("$n arrives to get $s ass whipped!", ch, NULL, NULL, TO_ROOM);
-			war_info.inwar++;
 			do_function(ch, &do_look, "auto");
 		}
 		return;
@@ -588,21 +681,20 @@
 
 bool abort_war(void)
 {
-	CHAR_DATA *ch;
-	CHAR_DATA *vict;
+	WAR_LIST *cwl, *vwl;
 
-	for (ch = player_first; ch != NULL; ch = ch->next_player)
+	for (cwl = war_info.first; cwl != NULL; cwl = cwl->next)
 	{
-		if (IS_SET(ch->act, PLR_WAR))
+		if (IS_SET(cwl->flags, WAR_KILLED | WAR_DECOY))
+			continue;
+
+		for (vwl = war_info.first; vwl != NULL; vwl = vwl->next)
 		{
-			for (vict = player_first; vict != NULL; vict = vict->next_player)
-			{
-				if (IS_SET(vict->act, PLR_WAR))
-				{
-					if (wartype_data(ch) != wartype_data(vict))
-						return FALSE;
-				}
-			}
+			if (IS_SET(vwl->flags, WAR_KILLED | WAR_DECOY))
+				continue;
+
+			if (!check_wartype_data(cwl->ch, vwl->ch))
+				return FALSE;
 		}
 	}
 	return TRUE;
@@ -612,9 +704,9 @@
 {
 	BUFFER *output;
 	char sender[MIL], subject[MIL], buf[MSL];
-	CHAR_DATA *wch;
+	WAR_LIST *wl;
 
-	if (war_info.iswar != WAR_RUNNING)
+	if (war_info.status != WAR_RUNNING)
 		return;
 
 	output = new_buf();
@@ -629,12 +721,12 @@
 			wartype_name(war_info.wartype, FALSE));
 	add_buf(output, buf);
 	add_buf(output, "{WWAR COMBATENTS{g\n\r--------------{x\n\r");
-	for (wch = player_first; wch != NULL; wch = wch->next_player)
+	for (wl = war_info.first; wl != NULL; wl = wl->next)
 	{
-		if (!IS_SET_WAR(wch))
+		if (IS_SET(wl->flags, WAR_DECOY) || !wl->ch)
 			continue;
 
-		sprintf(buf, "{W%s{x\n\r", warrior_status(wch));
+		sprintf(buf, "{W%s{x\n\r", warrior_status(wl->ch));
 		add_buf(output, buf);
 	}
 	add_buf(output, "{g--------------{x\n\r");
@@ -661,13 +753,13 @@
 
 void war_update(void)
 {
-	if (war_info.iswar == WAR_OFF && war_info.next > 0)
+	if (war_info.status == WAR_OFF && war_info.timer > 0)
 	{
-		if (--war_info.next <= 0)
+		if (--war_info.timer <= 0)
 			auto_war();
 	}
 
-	else if (war_info.iswar == WAR_WAITING)
+	else if (war_info.status == WAR_WAITING)
 	{
 		vnum_t randm = 0;
 
@@ -696,29 +788,26 @@
 			}
 			else
 			{
-				CHAR_DATA *wch;
+				WAR_LIST *wl;
 
 				announce(NULL, INFO_WAR,
 						 "The battle begins! %d players are fighting!",
 						 war_info.inwar);
 				war_info.timer =
 					number_range(3 * war_info.inwar, 5 * war_info.inwar);
-				war_info.iswar = WAR_RUNNING;
-				for (wch = player_first; wch != NULL; wch = wch->next_player)
+				war_info.status = WAR_RUNNING;
+				for (wl = war_info.first; wl != NULL; wl = wl->next)
 				{
-					if (IS_SET(wch->act, PLR_WAR))
-					{
-						randm = number_range(17601, 17636);
-						char_from_room(wch);
-						char_to_room(wch, get_room_index(randm));
-						do_function(wch, &do_look, "auto");
-					}
+					randm = number_range(17601, 17636);
+					char_from_room(wl->ch);
+					char_to_room(wl->ch, get_room_index(randm));
+					do_function(wl->ch, &do_look, "auto");
 				}
 			}
 		}
 	}
 
-	else if (war_info.iswar == WAR_RUNNING)
+	else if (war_info.status == WAR_RUNNING)
 	{
 		if (war_info.inwar == 0)
 		{
@@ -753,40 +842,53 @@
 
 void check_war(CHAR_DATA * ch, CHAR_DATA * victim)
 {
-	CHAR_DATA *wch;
-	int reward;
-	int qreward;
+	WAR_LIST *wl, *wl_next;
 
-	if (IS_NPC(ch) || IS_NPC(victim))
+	if (war_info.status == WAR_OFF)
 		return;
 
-	reward = number_range(500, 1500);
-	qreward = number_range(50, 150);
+	if (!IS_IN_WAR(ch) || !IS_IN_WAR(victim))
+		return;
 
-	REMOVE_BIT(victim->act, PLR_WAR);
-	victim->pcdata->still_in_war = TRUE;
 	war_info.inwar--;
 	stop_fighting(victim, TRUE);
 	stop_fighting(ch, TRUE);
+	if (IS_NPC(victim))
+	{
+		act("$n disappears suddenly.", victim, NULL, NULL, TO_ROOM);
+		free_warlist(victim->war);
+		return;
+	}
 	char_from_room(victim);
-	char_to_room(victim, get_room_index(ROOM_VNUM_WAITROOM));
-	if (victim->hit < 1)
-		victim->hit = 1;
-	if (victim->mana < 1)
-		victim->mana = 1;
-	if (victim->move < 1)
-		victim->move = 1;
+	char_to_room(victim, get_room_index(ROOM_VNUM_TEMPLE));
+	for (wl = war_info.first; wl; wl = wl_next)
+	{
+		wl_next = wl->next;
+
+		if (!IS_SET(wl->flags, WAR_DECOY))
+			continue;
+
+		if (!str_cmp(wl->ch->name, victim->name))
+		{
+			act("$n dissapears suddenly.", wl->ch, NULL, NULL, TO_ROOM);
+			free_warlist(wl);
+		}
+	}
+	victim->hit = victim->war->hit;
+	victim->mana = victim->war->mana;
+	victim->move = victim->war->move;
+	SET_BIT(victim->war->flags, WAR_KILLED);
 	update_pos(victim);
 	do_function(victim, &do_look, "auto");
-	chprintln(victim,
-			  "Please wait here untill the war ends and you'll be transfered and healed.");
 	chprintln(ch, "");
-	chprintln(victim, "");
 	announce(NULL, INFO_WAR, "%s was killed in combat by %s!{x",
-			 victim->name, ch->name);
+			 victim->name, IS_NPC(ch) ? ch->short_descr : ch->name);
 
 	if (abort_war())
 	{
+		int reward;
+		int qreward;
+
 		switch (war_info.wartype)
 		{
 		case WAR_RACE:
@@ -799,16 +901,18 @@
 			break;
 		}
 		note_war(ch);
-		for (wch = player_first; wch != NULL; wch = wch->next_player)
+		reward = number_range(500, 1500);
+		qreward = number_range(50, 150);
+		for (wl = war_info.first; wl != NULL; wl = wl->next)
 		{
-			if (!IS_SET_WAR(wch))
+			if (IS_SET(wl->flags, WAR_DECOY))
 				continue;
 
-			if (wartype_data(wch) == wartype_data(ch))
+			if (check_wartype_data(wl->ch, ch))
 			{
-				wch->gold += reward;
-				wch->pcdata->questpoints += qreward;
-				chprintf(wch,
+				wl->ch->gold += reward;
+				wl->ch->pcdata->questpoints += qreward;
+				chprintf(wl->ch,
 						 "You recieve %d gold and %d questpoints from the war tribunal!",
 						 reward, qreward);
 			}
@@ -821,16 +925,13 @@
 
 bool is_safe_war(CHAR_DATA * ch, CHAR_DATA * wch)
 {
-	if (war_info.iswar == WAR_OFF)
+	if (war_info.status == WAR_OFF)
 		return FALSE;
 
 	if (!IS_IN_WAR(ch) || !IS_IN_WAR(wch))
 		return FALSE;
 
-	if (wartype_data(ch) == wartype_data(wch))
-		return TRUE;
-
-	return FALSE;
+	return check_wartype_data(ch, wch);
 }
 
 void war_talk(CHAR_DATA * ch, const char *argument)
@@ -863,11 +964,10 @@
 
 void extract_war(CHAR_DATA * ch)
 {
-	if (war_info.iswar != WAR_OFF && IS_SET(ch->act, PLR_WAR))
+	if (war_info.status != WAR_OFF && ch->war != NULL)
 	{
-		REMOVE_BIT(ch->act, PLR_WAR);
 		war_info.inwar--;
-		if (war_info.iswar == WAR_RUNNING)
+		if (war_info.status == WAR_RUNNING)
 		{
 			if (war_info.inwar == 0 || war_info.inwar == 1)
 			{
@@ -887,5 +987,6 @@
 		}
 		char_from_room(ch);
 		char_to_room(ch, get_room_index(ROOM_VNUM_TEMPLE));
+		free_warlist(ch->war);
 	}
 }
diff -ur ./src/webserver.c ./new/webserver.c
--- ./src/webserver.c	Fri May 16 00:04:56 2003
+++ ./new/webserver.c	Fri May 16 02:11:35 2003
@@ -56,6 +56,8 @@
  *   easier management of the file behind the internal web server.
  */
 
+/* Modded for use on 1stMUD by Markanth 14/05/2003 */
+
 #include <errno.h>
 #include <stdarg.h>
 #include <sys/types.h>
@@ -717,18 +719,71 @@
 	return;
 }
 
-const char *DEFAULT_URL_PORT(void)
+const char *HTTP_URL(void)
 {
-	static char result[100];
-	int len;
+	return FORMATF(DEFAULT_URL, WEBSERVERPORT);
+}
+
+char *get_next(char *path)
+{
+	static char *buf[5];
+	static int i;
+
+	if (IS_NULLSTR(path))
+		return path;
+
+	++i;
+	i %= 5;
+
+	buf[i] = strchr(path, '/');
+
+	if (IS_NULLSTR(buf[i]))
+		return buf[i];
+	else
+	{
+		buf[i]++;
+		return buf[i];
+	}
+}
+
+bool get_name_password(WEB_DESCRIPTOR * wdesc, const char *stuff)
+{
+	char *where;
+	char encoded[MIL];
+	char username[MIL];
+	char *password = &str_empty[0];
+
+	username[0] = '\0';
+	encoded[0] = '\0';
 
-	sprintf(result, "%s", DEFAULT_URL);
-	len = strlen(result);
-	if (result[len - 1] == '/')
-		sprintf(result + (len - 1), ":%d/", WEBSERVERPORT);	// get rid of appending backslash
+	where = strstr(stuff, "Authorization: Basic");
+
+	if (!where)
+		send_401UNAUTHORISED(wdesc, AUTH_DOMAIN);
 	else
-		sprintf(result + len, ":%d/", WEBSERVERPORT);
-	return result;
+	{
+		where += strlen("Authorization: Basic");
+
+		where++;
+		for (password = encoded; *where && !isspace(*where);
+			 where++, password++)
+			*password = *where;
+
+		*password = '\0';
+
+		Base64Decode(encoded, (unsigned char *) username, MIL);
+
+		for (password = username; *password && *password != ':'; password++);
+		{
+			if (*password == ':')
+			{
+				*password = '\0';
+				password++;
+			}
+		}
+	}
+
+	return check_web_pass(username, password);
 }
 
 void under_line(char *under_lined, const char *spaced_out)
@@ -766,19 +821,36 @@
 
 void print_header(WEB_DESCRIPTOR * wdesc, const char *title)
 {
+	int i;
+
 	send_buf(wdesc->fd, DOCTYPE);
 	send_buf(wdesc->fd, "<HTML>\n");
 	send_buf(wdesc->fd, "<HEAD>\n");
 	send_buf(wdesc->fd, "<TITLE>%s @ %s</TITLE>\n", title, MUD_NAME);
-	send_buf(wdesc->fd, "</HEAD><BODY>\n");
+	send_buf(wdesc->fd,
+			 "</HEAD><BODY BGCOLOR=BLACK TEXT=WHITE LINK=#FFFFCC VLINK=#FFFFCC>\n");
+	send_buf(wdesc->fd,
+			 "<TABLE CELLSPACING=3 CELLPADDING=3 BORDER=0><TR><TD VALIGN=TOP WIDTH=15%%>\n");
+	send_buf(wdesc->fd, "<UL>\n");
+	for (i = 0; request_table[i].req != NULL; i++)
+	{
+		if (request_table[i].name == NULL)
+			continue;
+
+		send_buf(wdesc->fd, "<LI><A href=\"%s%s\">%s</A></LI>\n", HTTP_URL(),
+				 request_table[i].req, request_table[i].name);
+	}
+	send_buf(wdesc->fd, "</UL>\n");
+	send_buf(wdesc->fd, "</TD><TD VALIGN=TOP WIDTH=100%%>\n");
 	send_buf(wdesc->fd, "<H2>%s @ %s</H2>\n", title, MUD_NAME);
 }
 
 void print_footer(WEB_DESCRIPTOR * wdesc)
 {
+	send_buf(wdesc->fd, "</TD></TR></TABLE>\n");
 	send_buf(wdesc->fd, "<BR><ADDRESS>\n");
 	send_buf(wdesc->fd,
-			 "This page is automatically generated by " MUD_NAME " Mud.<BR>\n");
+			 "This page is automatically generated by %s.\n", MUD_NAME);
 	send_buf(wdesc->fd, "</ADDRESS>\n");
 	send_buf(wdesc->fd, "</BODY>\n");
 	send_buf(wdesc->fd, "</HTML>\n");
@@ -828,53 +900,48 @@
 		return output;
 
 	if (IS_OBJ_STAT(obj, ITEM_INVIS))
-		strcat(output, "{W(Invis) ");
+		strcat(output, "(Invis) ");
 	if (IS_OBJ_STAT(obj, ITEM_DARK))
-		strcat(output, "{D(Dark) ");
+		strcat(output, "(Dark) ");
 	if (IS_OBJ_STAT(obj, ITEM_EVIL))
-		strcat(output, "{R(Red Aura) ");
+		strcat(output, "(Red Aura) ");
 	if (IS_OBJ_STAT(obj, ITEM_BLESS))
-		strcat(output, "{B(Blue Aura) ");
+		strcat(output, "(Blue Aura) ");
 	if (IS_OBJ_STAT(obj, ITEM_MAGIC))
-		strcat(output, "{G(Magical) ");
+		strcat(output, "(Magical) ");
 	if (IS_OBJ_STAT(obj, ITEM_GLOW))
-		strcat(output, "{Y(Glowing) ");
+		strcat(output, "(Glowing) ");
 	if (IS_OBJ_STAT(obj, ITEM_HUM))
-		strcat(output, "{C(Humming) ");
+		strcat(output, "(Humming) ");
 
 	if (obj->item_type == ITEM_WEAPON)
 	{
 		for (paf = obj->first_affect; paf; paf = paf->next)
 		{
 			if (IS_SET(paf->bitvector, WEAPON_FLAMING))
-				strcat(output, "{Y(Flaming){x ");
+				strcat(output, "(Flaming) ");
 			if (IS_SET(paf->bitvector, WEAPON_FROST))
-				strcat(output, "{C(Frost){x ");
+				strcat(output, "(Frost) ");
 			if (IS_SET(paf->bitvector, WEAPON_VAMPIRIC))
-				strcat(output, "{R(Vampiric){x ");
+				strcat(output, "(Vampiric) ");
 			if (IS_SET(paf->bitvector, WEAPON_SHOCKING))
-				strcat(output, "{M(Shocking){x ");
+				strcat(output, "(Shocking) ");
 			if (IS_SET(paf->bitvector, WEAPON_POISON))
-				strcat(output, "{g(Poison){x ");
+				strcat(output, "(Poison) ");
 			if (IS_SET(paf->bitvector, WEAPON_SHARP))
-				strcat(output, "{W(Sharp){x ");
+				strcat(output, "(Sharp) ");
 			if (IS_SET(paf->bitvector, WEAPON_VORPAL))
-				strcat(output, "{r(Vorpal){x ");
+				strcat(output, "(Vorpal) ");
 		}
 	}
 
 	if (IS_OBJ_STAT(obj, ITEM_AUCTIONED))
-		strcat(output, "{Y(Auctioned){x ");
+		strcat(output, "(Auctioned) ");
 
 	if (obj->condition <= 9 && obj->condition >= 0)
-		strcat(output, "{b(Ruined) ");
+		strcat(output, "(Ruined) ");
 	else if (obj->condition >= 10 && obj->condition <= 24)
-		strcat(output, "{b(Broken) ");
-
-	strcat(output, "{x");
-
-	html_colourconv(buf, output);
-	sprintf(output, buf);
+		strcat(output, "(Broken) ");
 
 	if (obj->description != NULL)
 	{
@@ -882,7 +949,7 @@
 
 		html_colourconv(buf, obj->description);
 		sprintf(temp, "<A href=\"%sobjs/%ld\">%s</A><br>",
-				DEFAULT_URL_PORT(), obj->pIndexData->vnum, buf);
+				HTTP_URL(), obj->pIndexData->vnum, buf);
 		strcat(output, temp);
 	}
 
@@ -980,44 +1047,44 @@
 	buf[0] = '\0';
 
 	if (IS_AFFECTED(victim, AFF_INVISIBLE))
-		strcat(buf, "({wInvis{x) ");
+		strcat(buf, "(Invis) ");
 	if (victim->invis_level >= LEVEL_IMMORTAL)
-		strcat(buf, "({WWizi{x) ");
+		strcat(buf, "(Wizi) ");
 	if (IS_AFFECTED(victim, AFF_HIDE))
-		strcat(buf, "({DHide{x) ");
+		strcat(buf, "(Hide) ");
 	if (IS_AFFECTED(victim, AFF_CHARM))
-		strcat(buf, "({MCharmed{x) ");
+		strcat(buf, "(Charmed) ");
 	if (IS_AFFECTED(victim, AFF_PASS_DOOR))
-		strcat(buf, "({cTranslucent{x) ");
+		strcat(buf, "(Translucent) ");
 	if (IS_AFFECTED(victim, AFF_FAERIE_FIRE))
-		strcat(buf, "({mPink Aura{x) ");
+		strcat(buf, "(Pink Aura) ");
 	if (IS_EVIL(victim))
-		strcat(buf, "({RRed Aura{x) ");
+		strcat(buf, "(Red Aura) ");
 	if (IS_GOOD(victim))
-		strcat(buf, "({YGolden Aura{x) ");
+		strcat(buf, "(Golden Aura) ");
 	if (IS_AFFECTED(victim, AFF_SANCTUARY))
-		strcat(buf, "({WWhite Aura{x) ");
+		strcat(buf, "(White Aura) ");
 	if (!IS_NPC(victim) && !victim->desc)
-		strcat(buf, "({CLinkdead{x) ");
+		strcat(buf, "(Linkdead) ");
 
 	if (!IS_NPC(victim))
 	{
 		if (IS_SET(victim->comm, COMM_AFK))
-			strcat(buf, "{Y*{RAFK{Y*{x ");
-		if (IS_SET(victim->act, PLR_WAR))
-			strcat(buf, "{Y({RWAR{Y){x ");
+			strcat(buf, "*AFK* ");
+		if (victim->war)
+			strcat(buf, "(WAR) ");
 		if (!IS_NPC(victim) && IS_SET(victim->act, PLR_KILLER))
-			strcat(buf, "({rKILLER{x) ");
+			strcat(buf, "(KILLER) ");
 		if (!IS_NPC(victim) && IS_SET(victim->act, PLR_THIEF))
-			strcat(buf, "({rTHIEF{x) ");
+			strcat(buf, "(THIEF) ");
 		if (IS_SET(victim->comm, COMM_QUIET))
-			strcat(buf, "{R[{WQUIET{R]{x ");
+			strcat(buf, "[QUIET] ");
 		if (victim->desc && victim->desc->editor != 0)
-			strcat(buf, "{M[{mOLC{M]{x ");
+			strcat(buf, "[OLC] ");
 		if (victim->pcdata->in_progress != NULL)
-			strcat(buf, "{g[{wNote{g]{x ");
+			strcat(buf, "[Note] ");
 		if (IS_QUESTOR(victim))
-			strcat(buf, "{W[{CQ{W]{x ");
+			strcat(buf, "[Q] ");
 	}
 
 	if (victim->level > 0)
@@ -1030,21 +1097,19 @@
 			vict_condition = -1;
 
 		if (vict_condition < 0)
-			strcat(buf, "{R(DEAD){x ");
+			strcat(buf, "(DEAD) ");
 		else if (vict_condition < 33)
-			strcat(buf, "{R(Wounded){x ");
+			strcat(buf, "(Wounded) ");
 	}
 
 	if (victim->position ==
 		(IS_NPC(victim) ? victim->start_pos : POS_STANDING)
 		&& !IS_NULLSTR(victim->long_descr))
 	{
-		html_colourconv(cbuf, buf);
-		strcpy(buf, cbuf);
 		if (IS_NPC(victim))
 		{
 			html_colourconv(cbuf, victim->long_descr);
-			sprintf(temp, "<A href=\"%schars/%ld\">%s</A>", DEFAULT_URL_PORT(),
+			sprintf(temp, "<A href=\"%schars/%ld\">%s</A>", HTTP_URL(),
 					victim->pIndexData->vnum, cbuf);
 			strcat(buf, temp);
 		}
@@ -1053,14 +1118,12 @@
 	if (IS_NPC(victim))
 	{
 		html_colourconv(cbuf, victim->short_descr);
-		sprintf(temp, "<A href=\"%schars/%ld\">%s</A>", DEFAULT_URL_PORT(),
+		sprintf(temp, "<A href=\"%schars/%ld\">%s</A>", HTTP_URL(),
 				victim->pIndexData->vnum, cbuf);
 		strcat(buf, temp);
 	}
 	else
 	{
-		html_colourconv(cbuf, buf);
-		strcat(buf, cbuf);
 		strcat(buf, victim->name);
 	}
 
@@ -1172,8 +1235,8 @@
 		else if (victim->in_room == victim->fighting->in_room)
 		{
 			strcat(buf,
-				   IS_NPC(victim) ? victim->fighting->
-				   short_descr : victim->fighting->name);
+				   IS_NPC(victim) ? victim->fighting->short_descr : victim->
+				   fighting->name);
 			strcat(buf, ".");
 		}
 		else
@@ -1200,7 +1263,7 @@
 	return (output);
 }
 
-void HandleMemoryRequest(WEB_DESCRIPTOR * wdesc)
+HANDLE_URL(HandleMemoryRequest)
 {
 	int sn, count_spell = 0, count_skill = 0;
 
@@ -1246,10 +1309,10 @@
 	send_buf(wdesc->fd, "<TD>Shops</TD> <TD>%5d</TD></TR>\n", top_shop);
 	send_buf(wdesc->fd, "</TABLE>\n");
 	print_footer(wdesc);
-
+	return TRUE;
 }
 
-void HandleRulesRequest(WEB_DESCRIPTOR * wdesc)
+HANDLE_URL(HandleRulesRequest)
 {
 	HELP_DATA *pHelp;
 
@@ -1261,9 +1324,10 @@
 		send_buf(wdesc->fd, "There are no rules!! Anarchy!!\n");
 	send_buf(wdesc->fd, "</PRE>\n");
 	print_footer(wdesc);
+	return TRUE;
 }
 
-void HandleAreaRequest(WEB_DESCRIPTOR * wdesc)
+HANDLE_URL(HandleAreaRequest)
 {
 	AREA_DATA *pArea;
 	int count = 0;
@@ -1271,7 +1335,7 @@
 	print_header(wdesc, "Areas");
 	send_buf(wdesc->fd, "<TABLE>\n");
 	send_buf(wdesc->fd, "<TR>\n");
-	send_buf(wdesc->fd, "<TD>Low/High<BR>Level</TD>\n");
+	send_buf(wdesc->fd, "<TD>Low/High Level</TD>\n");
 	send_buf(wdesc->fd, "<TD>Author</TD>\n");
 	send_buf(wdesc->fd, "<TD>Area Name</TD></TR>\n");
 	for (pArea = area_first;;)
@@ -1281,6 +1345,11 @@
 		if (!IS_SET(pArea->area_flags, AREA_CLOSED | AREA_PLAYER_HOMES))
 		{
 			send_buf(wdesc->fd, "<TR>\n");
+			if (!IS_NULLSTR(pArea->lvl_comment))
+				send_buf(wdesc->fd, "<TD>%s</TD>\n", pArea->lvl_comment);
+			else
+				send_buf(wdesc->fd, "<TD>%03d %03d</TD>\n", pArea->min_level,
+						 pArea->max_level);
 			send_buf(wdesc->fd, "<TD>%s</TD>\n", pArea->credits);
 			send_buf(wdesc->fd, "<TD>%s</TD></TR>\n", pArea->name);
 			count++;
@@ -1290,9 +1359,10 @@
 	send_buf(wdesc->fd, "</TABLE>\n");
 	send_buf(wdesc->fd, "<P>Areas Found: %d.</P>\n", count);
 	print_footer(wdesc);
+	return TRUE;
 }
 
-void HandleSpellsRequest(WEB_DESCRIPTOR * wdesc)
+HANDLE_URL(HandleSpellsRequest)
 {
 	int gn;
 	int sn, i;
@@ -1437,7 +1507,7 @@
 
 	send_buf(wdesc->fd,
 			 "<P>To view skills in class specific tables, visit the <a href=\"%sclass\">Classes</a> section.</P>\n",
-			 DEFAULT_URL_PORT());
+			 HTTP_URL());
 
 	send_buf(wdesc->fd, "<H3><A NAME=\"RaceSkills\">Race Skills</A></H3>\n");
 	send_buf(wdesc->fd, "The following skills and spells are race specific.\n");
@@ -1509,10 +1579,10 @@
 	send_buf(wdesc->fd, "</TABLE>\n");
 	print_footer(wdesc);
 	free_mem(displayed);
-
+	return TRUE;
 }
 
-void HandleWhoRequest(WEB_DESCRIPTOR * wdesc)
+HANDLE_URL(HandleWhoRequest)
 {
 	CHAR_DATA *wch;
 	char buf[MSL * 2];
@@ -1536,7 +1606,7 @@
 			send_buf(wdesc->fd, "<TD>%d</TD>\n", wch->level);
 			send_buf(wdesc->fd,
 					 "<TD><A href=\"%sraces/%s\">%s</A></TD>\n",
-					 DEFAULT_URL_PORT(), wch->race->name, wch->race->name);
+					 HTTP_URL(), wch->race->name, wch->race->name);
 			send_buf(wdesc->fd, "<TD>%s</TD>\n", class_who(wch));
 		}
 		else
@@ -1550,7 +1620,7 @@
 			html_colourconv(buf, wch->clan->who_name);
 			send_buf(wdesc->fd,
 					 "<TD><A href=\"%sclans/%s\">%s</A></TD>\n",
-					 DEFAULT_URL_PORT(), wch->clan->name, buf);
+					 HTTP_URL(), wch->clan->name, buf);
 		}
 		else
 			send_buf(wdesc->fd, "<TD></TD>\n");
@@ -1565,95 +1635,107 @@
 	}
 	send_buf(wdesc->fd, "</TABLE><BR>\n");
 	print_footer(wdesc);
+	return TRUE;
 }
 
-const char *stat_type_name[MAX_GAMESTAT] = {
-	"PLAYER KILLERS",
-	"MOB KILLERS",
-	"PK DEATHS",
-	"MOB DEATHS",
+const char *stat_type_name[MAX_GAMESTAT][2] = {
+/*    Display           filename  */
+	{"PLAYER KILLERS", "pkill"},
+	{"MOB KILLERS", "mkill"},
+	{"PK DEATHS", "pkdead"},
+	{"MOB DEATHS", "mdead"}
 };
 
-void HandleStatsRequest(WEB_DESCRIPTOR * wdesc)
+HANDLE_URL(HandleStatsRequest)
 {
 	int pos;
+	char *buf = get_next(path);
 
-	print_header(wdesc, "Stats");
-	send_buf(wdesc->fd, "<OL>\n");
-	send_buf(wdesc->fd,
-			 "<li><A HREF=\"%sstats/general\">General Stats</A>\n",
-			 DEFAULT_URL_PORT());
-	for (pos = 0; pos < MAX_GAMESTAT; pos++)
+	if (IS_NULLSTR(buf))
 	{
-		send_buf(wdesc->fd,
-				 "<li><A HREF=\"%sstats/%s\">%s</A>\n", DEFAULT_URL_PORT(),
-				 stat_type_name[pos], stat_type_name[pos]);
+		print_header(wdesc, "Stats");
+		send_buf(wdesc->fd, "<OL>\n");
+		for (pos = 0; pos < MAX_GAMESTAT; pos++)
+		{
+			send_buf(wdesc->fd,
+					 "<li><A HREF=\"%sstats/%s\">%s</A>\n", HTTP_URL(),
+					 stat_type_name[pos][1], stat_type_name[pos][0]);
+		}
+		send_buf(wdesc->fd, "</OL>\n");
+		print_footer(wdesc);
+		return TRUE;
 	}
-	send_buf(wdesc->fd, "</OL>\n");
-	print_footer(wdesc);
-}
-
-int count_statlist args((void));
-int compare_stats args((const void *v1, const void *v2));
-
-void HandleStatsTypeRequest(WEB_DESCRIPTOR * wdesc, int type)
-{
-	char temp[MSL];
-	STAT_DATA *curr;
-	STAT_DATA **top;
-	int count, loop, pos = 0;
-	bool found = FALSE;
-	extern int compare_type;
-
-	sprintf(temp, "Ranking of %s", stat_type_name[type]);
-	print_header(wdesc, temp);
-	send_buf(wdesc->fd, "<TABLE>\n");
+	else
+	{
+		for (pos = 0; pos < MAX_GAMESTAT; pos++)
+		{
+			if (!str_cmp(stat_type_name[pos][1], buf))
+			{
+				int count_statlist args((void));
+				int compare_stats args((const void *v1, const void *v2));
+				char temp[MSL];
+				STAT_DATA *curr;
+				STAT_DATA **top;
+				int count, loop;
+				bool found = FALSE;
+				extern int compare_type;
+
+				sprintf(temp, "Ranking of %s", stat_type_name[pos][0]);
+				print_header(wdesc, temp);
+				send_buf(wdesc->fd, "<TABLE>\n");
+
+				alloc_mem(top, STAT_DATA *, count_statlist());
+
+				count = 0;
+				compare_type = pos;
+				loop = 0;
+				pos = 0;
+				for (curr = stat_first; curr != NULL; curr = curr->next)
+				{
+					top[count] = curr;
+					count++;
+					found = TRUE;
+				}
 
-	alloc_mem(top, STAT_DATA *, count_statlist());
+				qsort(top, count, sizeof(*top), compare_stats);
 
-	count = 0;
-	compare_type = type;
-	loop = 0;
-	for (curr = stat_first; curr != NULL; curr = curr->next)
-	{
-		top[count] = curr;
-		count++;
-		found = TRUE;
-	}
+				send_buf(wdesc->fd,
+						 "<TR><TD><I>Rank</I></TD><TD><I>Name</I></TD><TD><I>Number</I></TD>"
+						 "<TD><I>Rank</I></TD><TD><I>Name</I></TD><TD><I>Number</I></TD></TR>");
+				for (loop = 0; loop < count; loop++)
+				{
+					if (loop >= 50)
+						break;
 
-	qsort(top, count, sizeof(*top), compare_stats);
+					sprintf(temp, "%s<TD>%2d)</TD><TD>%-20s</TD><TD>%ld</TD>\n",
+							pos == 0 ? "<TR>" : "", loop + 1, top[loop]->name,
+							top[loop]->gamestat[compare_type]);
+					send_buf(wdesc->fd, temp);
+					if (++pos % 2 == 0)
+					{
+						send_buf(wdesc->fd, "</TR>");
+						pos = 0;
+					}
 
-	send_buf(wdesc->fd,
-			 "<TR><TD><I>Rank</I></TD><TD><I>Name</I></TD><TD><I>Number</I></TD>"
-			 "<TD><I>Rank</I></TD><TD><I>Name</I></TD><TD><I>Number</I></TD></TR>");
-	for (loop = 0; loop < count; loop++)
-	{
-		if (loop >= 50)
-			break;
+				}
+				if (!found)
+					send_buf(wdesc->fd,
+							 "<TR><TD COLSPAN=3>No one found yet.</TD></TR>\n");
 
-		sprintf(temp, "%s<TD>%2d)</TD><TD>%-20s</TD><TD>%ld</TD>\n",
-				pos == 0 ? "<TR>" : "", loop + 1, top[loop]->name,
-				top[loop]->gamestat[type]);
-		send_buf(wdesc->fd, temp);
-		if (++pos % 2 == 0)
-		{
-			send_buf(wdesc->fd, "</TR>");
-			pos = 0;
+				send_buf(wdesc->fd, "</TABLE>");
+				send_buf(wdesc->fd,
+						 "<BR><A href=\"%sstats\">Back to Stats Index</A>\n",
+						 HTTP_URL());
+				print_footer(wdesc);
+				free_mem(top);
+				return TRUE;
+			}
 		}
-
 	}
-	if (!found)
-		send_buf(wdesc->fd, "<TR><TD COLSPAN=3>No one found yet.</TD></TR>\n");
-
-	send_buf(wdesc->fd, "</TABLE>");
-	send_buf(wdesc->fd,
-			 "<BR><A href=\"%sstats\">Back to Stats Index</A>\n",
-			 DEFAULT_URL_PORT());
-	print_footer(wdesc);
-	free_mem(top);
+	return FALSE;
 }
 
-void HandleCommandsRequest(WEB_DESCRIPTOR * wdesc)
+HANDLE_URL(HandleCommandsRequest)
 {
 	CMD_DATA *i;
 	int pos = 0;
@@ -1676,8 +1758,7 @@
 		}
 		if (pHelp)
 			send_buf(wdesc->fd, "%s<TD><A href=\"%shelps/%d\">%s</TD>\n",
-					 (pos == 0) ? "<TR>" : "", DEFAULT_URL_PORT(), count,
-					 i->name);
+					 (pos == 0) ? "<TR>" : "", HTTP_URL(), count, i->name);
 		else
 			send_buf(wdesc->fd,
 					 "%s<TD>%s</TD>\n", (pos == 0) ? "<TR>" : "", i->name);
@@ -1689,382 +1770,438 @@
 	}
 	send_buf(wdesc->fd, "</TABLE>\n");
 	print_footer(wdesc);
+	return TRUE;
 }
 
-void HandleHelpsRequest(WEB_DESCRIPTOR * wdesc)
+HANDLE_URL(HandleHelpsRequest)
 {
 	HELP_DATA *pHelp;
-	int count = 0;
+	char *buf = get_next(path);
 	int pos = 0;
+	char temp[MIL];
 
-	print_header(wdesc, "Help Files");
-	send_buf(wdesc->fd, "<TABLE>\n");
-	for (pHelp = help_first; pHelp != NULL; pHelp = pHelp->next)
+	if (IS_NULLSTR(buf))
 	{
-		count++;
-		if (pHelp->level <= LEVEL_HERO && pHelp->level >= 0)
-		{
-			const char *temp;
-			char wordkey[MSL];
+		int count = 0;
 
-			temp = pHelp->keyword;
-			while (!IS_NULLSTR(temp))
+		print_header(wdesc, "Help Files");
+		send_buf(wdesc->fd, "<TABLE>\n");
+		for (pHelp = help_first; pHelp != NULL; pHelp = pHelp->next)
+		{
+			count++;
+			if (pHelp->level <= MAX_MORTAL_LEVEL && pHelp->level >= 0)
 			{
-				wordkey[0] = '\0';
-				temp = one_argument(temp, wordkey);
-				send_buf(wdesc->fd,
-						 "%s<TD><A HREF=\"%shelps/%d\">%s</A></TD>\n",
-						 (pos == 0) ? "<TR>" : "", DEFAULT_URL_PORT(), count,
-						 wordkey);
-				if (++pos % 5 == 0)
+				const char *temp;
+				char wordkey[MSL];
+
+				temp = pHelp->keyword;
+				while (!IS_NULLSTR(temp))
 				{
-					send_buf(wdesc->fd, "</TR>");
-					pos = 0;
+					wordkey[0] = '\0';
+					temp = one_argument(temp, wordkey);
+					send_buf(wdesc->fd,
+							 "%s<TD><A HREF=\"%shelps/%d\">%s</A></TD>\n",
+							 (pos == 0) ? "<TR>" : "", HTTP_URL(), count,
+							 wordkey);
+					if (++pos % 5 == 0)
+					{
+						send_buf(wdesc->fd, "</TR>");
+						pos = 0;
+					}
 				}
 			}
 		}
+		send_buf(wdesc->fd, "</TABLE>\n");
+		print_footer(wdesc);
+		return TRUE;
 	}
-	send_buf(wdesc->fd, "</TABLE>\n");
-	print_footer(wdesc);
-}
-
-void HandleHelpDumpRequest(WEB_DESCRIPTOR * wdesc, HELP_DATA * pHelp)
-{
-	char buf[MSL * 5];
-
-	print_header(wdesc, pHelp->keyword);
-	send_buf(wdesc->fd, "<TABLE>\n");
-	send_buf(wdesc->fd, "<TR><TD>[%d] %s<TD></TR>\n", pHelp->level,
-			 pHelp->keyword);
-	html_colourconv(buf, fix_string(pHelp->text));
-	send_buf(wdesc->fd, "<TR><TD>%s</TD></TR>\n", buf);
-	send_buf(wdesc->fd, "</TABLE>\n");
-	send_buf(wdesc->fd, "<BR><A HREF=\"%shelps\">Back to Help Index</A>\n",
-			 DEFAULT_URL_PORT());
-	print_footer(wdesc);
+	else
+	{
+		pos = 0;
+		for (pHelp = help_first; pHelp != NULL; pHelp = pHelp->next)
+		{
+			pos++;
+			sprintf(temp, "%d", pos);
+			if (!str_cmp(buf, temp))
+			{
+				char buf2[MSL * 5];
+
+				print_header(wdesc, pHelp->keyword);
+				send_buf(wdesc->fd, "<TABLE>\n");
+				send_buf(wdesc->fd, "<TR><TD>[%d] %s<TD></TR>\n", pHelp->level,
+						 pHelp->keyword);
+				html_colourconv(buf2, fix_string(pHelp->text));
+				send_buf(wdesc->fd, "<TR><TD>%s</TD></TR>\n", buf2);
+				send_buf(wdesc->fd, "</TABLE>\n");
+				send_buf(wdesc->fd,
+						 "<BR><A HREF=\"%shelps\">Back to Help Index</A>\n",
+						 HTTP_URL());
+				print_footer(wdesc);
+				return TRUE;
+			}
+		}
+	}
+	return FALSE;
 }
 
-void HandleRaceRequest(WEB_DESCRIPTOR * wdesc)
+HANDLE_URL(HandleRaceRequest)
 {
 	RACE_DATA *race;
+	char *buf = get_next(path);
 
-	print_header(wdesc, "Races");
-	send_buf(wdesc->fd, "<TABLE><TR>\n");
-	send_buf(wdesc->fd, "<TD><I>Race</I></TD>\n");
-	send_buf(wdesc->fd,
-			 "<TD><I>Str</I></TD><TD><I>Int</I></TD><TD><I>Wis</I></TD><TD><I>Dex</I></TD><TD><I>Con</I></TD><TD><I>Luck</I></TD>\n");
-	send_buf(wdesc->fd, "<TD><I>Creation<BR>Points</I></TD></TR>\n");
-	for (race = race_first; race != NULL; race = race->next)
+	if (IS_NULLSTR(buf))
 	{
-		if (!race->pc_race)
-			continue;
+		print_header(wdesc, "Races");
+		send_buf(wdesc->fd, "<TABLE><TR>\n");
+		send_buf(wdesc->fd, "<TD><I>Race</I></TD>\n");
+		send_buf(wdesc->fd,
+				 "<I><TD>Str</TD><TD>Int</TD><TD>Wis</TD><TD>Dex</TD><TD>Con</TD></I>\n");
+		send_buf(wdesc->fd, "<TD><I>Creation<BR>Points</I></TD></TR>\n");
+		for (race = race_first; race != NULL; race = race->next)
+		{
+			if (!race->pc_race)
+				continue;
 
-		send_buf(wdesc->fd, "<TR>\n");
+			send_buf(wdesc->fd, "<TR>\n");
+			send_buf(wdesc->fd,
+					 "<TD><A HREF=\"%s"
+					 "races/%s\">%s</A></TD>\n<TD>%d</TD>\n<TD>%d</TD>\n<TD>%d</TD>\n"
+					 "<TD>%d</TD>\n<TD>%d</TD><TD ALIGN=\"center\">%d</TD></TR>\n",
+					 HTTP_URL(),
+					 race->name, race->name,
+					 race->max_stats[STAT_STR],
+					 race->max_stats[STAT_INT],
+					 race->max_stats[STAT_WIS],
+					 race->max_stats[STAT_DEX],
+					 race->max_stats[STAT_CON], race->points);
+		}
+		send_buf(wdesc->fd, "</TABLE>\n");
 		send_buf(wdesc->fd,
-				 "<TD><A HREF=\"%s"
-				 "races/%s\">%s</A></TD>\n<TD>%d</TD>\n<TD>%d</TD>\n<TD>%d</TD>\n"
-				 "<TD>%d</TD>\n<TD>%d</TD><TD ALIGN=\"center\">%d</TD></TR>\n",
-				 DEFAULT_URL_PORT(),
-				 race->name, race->name,
-				 race->max_stats[STAT_STR],
-				 race->max_stats[STAT_INT],
-				 race->max_stats[STAT_WIS],
-				 race->max_stats[STAT_DEX],
-				 race->max_stats[STAT_CON], race->points);
+				 "<P>Creation points increase the amount of experience it takes to gain a level. Maximum a stat can go is 30.</P>\n");
+		send_buf(wdesc->fd,
+				 "<P>To view skills and spells available to each race, visit the <a href=\"%sspells#RaceSkills\">Skill/Spell</A> section.</P>\n",
+				 HTTP_URL());
+		print_footer(wdesc);
+		return TRUE;
 	}
-	send_buf(wdesc->fd, "</TABLE>\n");
-	send_buf(wdesc->fd,
-			 "<P>Creation points increase the amount of experience it takes to gain a level. Maximum a stat can go is 30.</P>\n");
-	send_buf(wdesc->fd,
-			 "<P>To view skills and spells available to each race, visit the <a href=\"%sspells#RaceSkills\">Skill/Spell</A> section.</P>\n",
-			 DEFAULT_URL_PORT());
-	print_footer(wdesc);
-}
+	else
+	{
+		for (race = race_first; race; race = race->next)
+		{
+			if (!str_cmp(race->name, buf))
+			{
+				HELP_DATA *pHelp;
+				char buf2[MSL * 2];
 
-void HandleRaceDumpRequest(WEB_DESCRIPTOR * wdesc, RACE_DATA * race)
-{
-	HELP_DATA *pHelp;
-	char buf[MSL * 2];
+				print_header(wdesc, race->name);
+				if ((pHelp = help_lookup(race->name)) != NULL)
+				{
+					html_colourconv(buf2, pHelp->text);
+					send_buf(wdesc->fd, "<P>%s</P><BR>\n", buf2);
+				}
+				else
+					send_buf(wdesc->fd, "<P>No Info Available</P><BR>\n");
 
-	print_header(wdesc, race->name);
-	sprintf(buf, "%s", race->name);
-	if ((pHelp = help_lookup(buf)) != NULL)
-	{
-		html_colourconv(buf, pHelp->text);
-		send_buf(wdesc->fd, "<P>%s</P><BR>\n", buf);
+				print_footer(wdesc);
+				return TRUE;
+			}
+		}
 	}
-	else
-		send_buf(wdesc->fd, "<P>No Info Available</P><BR>\n");
-
-	print_footer(wdesc);
+	return FALSE;
 }
 
-void HandleClanRequest(WEB_DESCRIPTOR * wdesc)
+HANDLE_URL(HandleClanRequest)
 {
 	CLAN_DATA *clan;
-	char buf[MSL * 3];
+	char buf[MSL * 3], i[MSL], j[MSL];
+	MBR_DATA *pmbr;
 
 	print_header(wdesc, "Clans");
 	send_buf(wdesc->fd, "<TABLE>\n");
 	send_buf(wdesc->fd,
-			 "<TR><B><TD><I>Name</I></TD><TD><I>Description</I></TD><TD><I>Homepage</I></TD></TR>\n");
+			 "<TR><B><I><TD>Name</TD><TD>Leaders</TD></I></B></TR>\n");
 	for (clan = clan_first; clan; clan = clan->next)
 	{
 
 		html_colourconv(buf, clan->who_name);
-
-		send_buf(wdesc->fd, "<TR><TD>%s</TD></TR>\n", buf);
-	}
-	send_buf(wdesc->fd, "</TABLE>\n");
-	print_footer(wdesc);
-
-}
-
-void HandleClassRequest(WEB_DESCRIPTOR * wdesc)
-{
-	int iClass;
-
-	print_header(wdesc, "Classes");
-	send_buf(wdesc->fd, "<TABLE>\n");
-	for (iClass = 0; iClass < maxClass; iClass++)
-	{
-		send_buf(wdesc->fd,
-				 "<TR><TD><A HREF=\"%sclass/%s\">%s</A>"
-				 "</TD></TR>\n", DEFAULT_URL_PORT(),
-				 class_table[iClass].name, class_table[iClass].name);
+		i[0] = '\0';
+		j[0] = '\0';
+		for (pmbr = mbr_first; pmbr != NULL; pmbr = pmbr->next)
+		{
+			if (pmbr->clan != clan || pmbr->rank != (MAX_RANK - 1))
+				continue;
+			sprintf(j, " %s,", pmbr->name);
+			strcat(i, j);
+		}
+		if (!IS_NULLSTR(i))
+		{
+			i[strlen(i) - 1] = '\0';
+			send_buf(wdesc->fd, "<TR><TD>%s</TD><TD>%s</TD></TR>\n", buf, i);
+		}
+		else
+			send_buf(wdesc->fd, "<TR><TD>%s</TD><TD>None</TD></TR>\n", buf);
 	}
 	send_buf(wdesc->fd, "</TABLE>\n");
 	print_footer(wdesc);
+	return TRUE;
 }
 
-void HandleClassDumpRequest(WEB_DESCRIPTOR * wdesc, int Class)
+HANDLE_URL(HandleClassRequest)
 {
-	char buf[MSL * 2], buf2[MSL];
-	char skill_list[LEVEL_HERO + 1][MSL];
-	int snc, lev;
-	HELP_DATA *pHelp;
-
-	print_header(wdesc, class_table[Class].name);
-	if ((pHelp = help_lookup(class_table[Class].name)) != NULL)
-	{
-		html_colourconv(buf, pHelp->text);
-		send_buf(wdesc->fd, "<TABLE><TR><TD>%s</TD></TR></TABLE>\n", buf);
-	}
-	send_buf(wdesc->fd, "<TABLE>\n");
-	for (lev = 0; lev < LEVEL_HERO + 1; lev++)
-		skill_list[lev][0] = '\0';
+	int i;
+	char *buf = get_next(path);
 
-	for (snc = 0; snc < maxSkill; snc++)
+	if (IS_NULLSTR(buf))
 	{
-		if (skill_table[snc].name == NULL)
-			break;
-
-		if ((lev = skill_table[snc].skill_level[Class]) <= LEVEL_HERO)
+		print_header(wdesc, "Classes");
+		send_buf(wdesc->fd, "<TABLE>\n");
+		for (i = 0; i < maxClass; i++)
 		{
-			sprintf(buf2, "%s, ", skill_table[snc].name);
-			if (IS_NULLSTR(skill_list[lev]))
-				sprintf(skill_list[lev], "<TR><TD>Level %d</TD><TD>%s", lev,
-						buf2);
-			else
-				strcat(skill_list[lev], buf2);
+			send_buf(wdesc->fd,
+					 "<TR><TD><A HREF=\"%sclass/%s\">%s</A>"
+					 "</TD></TR>\n", HTTP_URL(),
+					 class_table[i].name, class_table[i].name);
 		}
+		send_buf(wdesc->fd, "</TABLE>\n");
+		print_footer(wdesc);
+		return TRUE;
 	}
-	for (lev = 0; lev < LEVEL_HERO + 1; lev++)
+	else
 	{
-		if (skill_list[lev][0] != '\0')
+		for (i = 0; i < maxClass; i++)
 		{
-			if (strlen(skill_list[lev]) > 2)
-				skill_list[lev][(strlen(skill_list[lev]) - 2)] = '\0';
+			if (!str_cmp(class_table[i].name, buf))
+			{
+				char buf2[MSL * 2], buf3[MSL];
+				char skill_list[MAX_MORTAL_LEVEL + 1][MSL];
+				int snc, lev;
+				HELP_DATA *pHelp;
 
-			send_buf(wdesc->fd, skill_list[lev]);
-			send_buf(wdesc->fd, "</TD></TR>\n");
-		}
+				print_header(wdesc, class_table[i].name);
+				if ((pHelp = help_lookup(class_table[i].name)) != NULL)
+				{
+					html_colourconv(buf2, pHelp->text);
+					send_buf(wdesc->fd, "<TABLE><TR><TD>%s</TD></TR></TABLE>\n",
+							 buf2);
+				}
+				send_buf(wdesc->fd, "<TABLE>\n");
+				for (lev = 0; lev < MAX_MORTAL_LEVEL + 1; lev++)
+					skill_list[lev][0] = '\0';
+
+				for (snc = 0; snc < maxSkill; snc++)
+				{
+					if (skill_table[snc].name == NULL)
+						break;
 
+					if ((lev = skill_table[snc].skill_level[i]) <=
+						MAX_MORTAL_LEVEL)
+					{
+						sprintf(buf3, "%s, ", skill_table[snc].name);
+						if (IS_NULLSTR(skill_list[lev]))
+							sprintf(skill_list[lev],
+									"<TR><TD>Level %d</TD><TD>%s", lev, buf3);
+						else
+							strcat(skill_list[lev], buf3);
+					}
+				}
+				for (lev = 0; lev < MAX_MORTAL_LEVEL + 1; lev++)
+				{
+					if (skill_list[lev][0] != '\0')
+					{
+						if (strlen(skill_list[lev]) > 2)
+							skill_list[lev][(strlen(skill_list[lev]) - 2)] =
+								'\0';
+
+						send_buf(wdesc->fd, skill_list[lev]);
+						send_buf(wdesc->fd, "</TD></TR>\n");
+					}
+
+				}
+				send_buf(wdesc->fd, "</TABLE>\n");
+				print_footer(wdesc);
+				return TRUE;
+			}
+		}
 	}
-	send_buf(wdesc->fd, "</TABLE>\n");
-	print_footer(wdesc);
+	return FALSE;
 }
 
-void HandleNotesRequest(WEB_DESCRIPTOR * wdesc)
+HANDLE_URL(HandleNotesRequest)
 {
+	char *buf = get_next(path);
 	int pos = 0;
 
-	print_header(wdesc, "Notes");
-	send_buf(wdesc->fd, "<OL>\n");
-	for (pos = 0; pos < MAX_BOARD - 3; pos++)
+	if (IS_NULLSTR(buf))
 	{
-		send_buf(wdesc->fd,
-				 "<li><A HREF=\"%snotes/%s\">%s</A>\n", DEFAULT_URL_PORT(),
-				 boards[pos].short_name, boards[pos].short_name);
+		print_header(wdesc, "Notes");
+		send_buf(wdesc->fd, "<OL>\n");
+		for (pos = 0; pos < MAX_BOARD - 1; pos++)
+		{
+			send_buf(wdesc->fd,
+					 "<li><A HREF=\"%snotes/%s\">%s</A>\n", HTTP_URL(),
+					 boards[pos].short_name, boards[pos].short_name);
+		}
+		send_buf(wdesc->fd, "</OL>\n");
+		print_footer(wdesc);
+		return TRUE;
 	}
-	send_buf(wdesc->fd, "</OL>\n");
-	print_footer(wdesc);
-}
-
-void HandleNotesDumpRequest(WEB_DESCRIPTOR * wdesc, BOARD_DATA * board)
-{
-	NOTE_DATA *pnote;
-	char buf[MSL * 5];
-
-	sprintf(buf, "Notes on %s Board", board->short_name);
-	print_header(wdesc, buf);
-	for (pnote = board->note_first; pnote != NULL; pnote = pnote->next)
+	else
 	{
-		if (!is_name(pnote->to_list, "all"))
-			continue;
+		for (pos = 0; pos < MAX_BOARD - 1; pos++)
+		{
+			if (!str_cmp(boards[pos].short_name, buf))
+			{
+				BOARD_DATA *board = &boards[pos];
+				NOTE_DATA *pnote;
+				char buf2[MSL * 5];
+
+				sprintf(buf2, "Notes on %s Board", board->short_name);
+				print_header(wdesc, buf2);
+				for (pnote = board->note_first; pnote != NULL;
+					 pnote = pnote->next)
+				{
+					if (!is_name("all", pnote->to_list))
+						continue;
 
-		html_colourconv(buf, pnote->text);
-		send_buf(wdesc->fd,
-				 "<TABLE><TR><TD><b>%s</b></TD><TD>%s</TD></TR><TR><TD><B>Date</B></TD>\n"
-				 "<TD>%s</TD></TR><TR><TD COLSPAN=2>%s</TD><TR></TABLE><BR>\n",
-				 pnote->sender, pnote->subject, pnote->date, buf);
+					html_colourconv(buf2, pnote->text);
+					send_buf(wdesc->fd,
+							 "<TABLE><TR><TD><b>%s</b></TD><TD>%s</TD></TR><TR><TD><B>Date</B></TD>\n"
+							 "<TD>%s</TD></TR><TR><TD COLSPAN=2>%s</TD><TR></TABLE><BR>\n",
+							 pnote->sender, pnote->subject, pnote->date, buf2);
+				}
+				send_buf(wdesc->fd,
+						 "<BR><A href=\"%snotes\">Back to Board Index</A>\n",
+						 HTTP_URL());
+				print_footer(wdesc);
+				return TRUE;
+			}
+		}
 	}
-	send_buf(wdesc->fd,
-			 "<BR><A href=\"%snotes\">Back to Board Index</A>\n",
-			 DEFAULT_URL_PORT());
-	print_footer(wdesc);
+	return FALSE;
 }
 
-void HandleSkDebugRequest(WEB_DESCRIPTOR * wdesc)
+HANDLE_URL(HandleObjsRequest)
 {
-	int i, sn;
+	OBJ_INDEX_DATA *pObj;
+	char *buf = get_next(path);
 
-	print_header(wdesc, "Skill List");
-	send_buf(wdesc->fd, "<TABLE><TR><TD>Skill Name</TD>\n");
-	for (i = 0; i < maxClass; i++)
-		send_buf(wdesc->fd, "<TD>%s</TD>\n", class_table[i].name);
-	send_buf(wdesc->fd, "</TR>\n");
-	for (sn = 0; sn < maxSkill; sn++)
+	if (!IS_NULLSTR(buf))
 	{
-		send_buf(wdesc->fd, "<TR><TD>%s</TD>\n", skill_table[sn].name);
-		for (i = 0; i < maxClass; i++)
+		if (!is_number(buf))
 		{
-			if (skill_table[sn].skill_level[i] >= LEVEL_IMMORTAL)
-				send_buf(wdesc->fd, "<TD>---</TD>\n");
-			else
-				send_buf(wdesc->fd, "<TD>%d</TD>\n",
-						 skill_table[sn].skill_level[i]);
+			return FALSE;
+		}
+		if ((pObj = get_obj_index(atol(buf))) != NULL)
+		{
+			char buf2[MSL * 3];
+
+			print_header(wdesc, smash_colour(pObj->short_descr));
+			html_colourconv(buf2, pObj->short_descr);
+			send_buf(wdesc->fd, "<P>%s<br>", buf2);
+			html_colourconv(buf2, pObj->description);
+			send_buf(wdesc->fd, "%s<br>", buf2);
+			send_buf(wdesc->fd, "Material: %s<br>", pObj->material);
+			send_buf(wdesc->fd, "Type: %s<br></P>", item_name(pObj->item_type));
+			print_footer(wdesc);
+			return TRUE;
 		}
-		send_buf(wdesc->fd, "</TR>\n");
 	}
-	send_buf(wdesc->fd, "</TABLE>");
-	print_footer(wdesc);
+	return FALSE;
 }
 
-void HandleLogRequest(WEB_DESCRIPTOR * wdesc)
+HANDLE_URL(HandleMobsRequest)
 {
-	struct dirent *Dir;
-	DIR *Directory;
-	char buf[MSL];
-	int count = 0;
+	MOB_INDEX_DATA *pMob;
+	char *buf = get_next(path);
 
-	print_header(wdesc, "Log Files");
-	send_buf(wdesc->fd, "<TABLE><TR>\n");
-	Directory = opendir("../log");
-	Dir = readdir(Directory);
-	while (Dir != NULL)
+	if (!IS_NULLSTR(buf))
 	{
-		if (!str_suffix(".log", Dir->d_name))
+		if (!is_number(buf))
 		{
-			strcpy(buf, Dir->d_name);
-			buf[strlen(buf) - 4] = '\0';
-			send_buf(wdesc->fd,
-					 "%s<TD><A href=\"%s%s/log/%s\">%s</A></TD>\n",
-					 count % 5 == 0 ? "</TR><TR>" : "",
-					 DEFAULT_URL_PORT(), SECURE_URL, buf, Dir->d_name);
-			count++;
+			return FALSE;
 		}
-		Dir = readdir(Directory);
-	}
-	closedir(Directory);
-	send_buf(wdesc->fd, "%s</TABLE>\n", count % 5 != 0 ? "</TR>" : "");
-	print_footer(wdesc);
-}
-
-void HandleLogDumpRequest(WEB_DESCRIPTOR * wdesc, char *file)
-{
-	char buf[MSL];
-
-	print_header(wdesc, file);
-	send_buf(wdesc->fd, "<PRE>\n");
-	sprintf(buf, "../log/%s.log", file);
-	print_file(wdesc, buf);
-	send_buf(wdesc->fd, "</PRE>\n");
-	print_footer(wdesc);
-
-}
-
-void HandleObjsRequest(WEB_DESCRIPTOR * wdesc, OBJ_INDEX_DATA * pObj)
-{
-	char buf[MSL * 3];
-
-	print_header(wdesc, smash_colour(pObj->short_descr));
-	html_colourconv(buf, pObj->short_descr);
-	send_buf(wdesc->fd, "<P>%s<br>", buf);
-	html_colourconv(buf, pObj->description);
-	send_buf(wdesc->fd, "%s<br>", buf);
-	send_buf(wdesc->fd, "Material: %s<br>", pObj->material);
-	send_buf(wdesc->fd, "Type: %s<br></P>", item_name(pObj->item_type));
-	print_footer(wdesc);
-}
-
-void HandleMobsRequest(WEB_DESCRIPTOR * wdesc, MOB_INDEX_DATA * pMob)
-{
-	char buf[MSL * 3];
+		if ((pMob = get_mob_index(atol(buf))) != NULL)
+		{
+			char buf2[MSL * 3];
 
-	print_header(wdesc, smash_colour(pMob->short_descr));
-	html_colourconv(buf, pMob->short_descr);
-	send_buf(wdesc->fd, "<P>%s<br>", buf);
-	html_colourconv(buf, pMob->description);
-	send_buf(wdesc->fd, "%s<br>", buf);
-	send_buf(wdesc->fd, "Race: %s<br>", pMob->race->name);
-	send_buf(wdesc->fd, "Sex: %s<br>", sex_table[pMob->sex].name);
-	send_buf(wdesc->fd, "Alignment: %d<br>", pMob->alignment);
-	send_buf(wdesc->fd, "</P>");
-	print_footer(wdesc);
+			print_header(wdesc, smash_colour(pMob->short_descr));
+			html_colourconv(buf2, pMob->short_descr);
+			send_buf(wdesc->fd, "<P>%s<br>", buf2);
+			html_colourconv(buf2, pMob->description);
+			send_buf(wdesc->fd, "%s<br>", buf2);
+			send_buf(wdesc->fd, "Race: %s<br>", pMob->race->name);
+			send_buf(wdesc->fd, "Sex: %s<br>", sex_table[pMob->sex].name);
+			send_buf(wdesc->fd, "Alignment: %d<br>", pMob->alignment);
+			send_buf(wdesc->fd, "</P>");
+			print_footer(wdesc);
+			return TRUE;
+		}
+	}
+	return FALSE;
 }
 
-void HandleRoomsRequest(WEB_DESCRIPTOR * wdesc, vnum_t room)
+HANDLE_URL(HandleRoomsRequest)
 {
-	ROOM_INDEX_DATA *pRoom = get_room_index(room);
-	EXIT_DATA *pexit;
-	int door;
-	char buf[MSL * 4];
-
-	if (!pRoom)
-		return;
+	ROOM_INDEX_DATA *pRoom;
+	char *buf = get_next(path);
+	vnum_t vnum;
 
-	print_header(wdesc, pRoom->name);
-	send_buf(wdesc->fd, "<TABLE><TR><TD colspan=3>");
-	html_colourconv(buf, pRoom->name);
-	send_buf(wdesc->fd, buf);
-	send_buf(wdesc->fd, "</TD><TD colspan=3>%s", pRoom->area->name);
-	send_buf(wdesc->fd, "</TD></TR><TR><TD colspan=6>");
-	html_colourconv(buf, pRoom->description);
-	send_buf(wdesc->fd, buf);
-	send_buf(wdesc->fd, "</TD></TR><TR>");
-	for (door = 0; door < MAX_DIR; door++)
+	if (IS_NULLSTR(buf))
 	{
-		if ((pexit = pRoom->exit[door]) != NULL && pexit->u1.to_room != NULL)
+		vnum = ROOM_VNUM_TEMPLE;
+	}
+	else
+	{
+		if (!is_number(buf))
 		{
-			send_buf(wdesc->fd,
-					 "<TD><A href=\"%srooms/%ld\">%s</A></TD>",
-					 DEFAULT_URL_PORT(), pexit->u1.to_room->vnum,
-					 dir_name[door]);
+			return FALSE;
 		}
-		else
-			send_buf(wdesc->fd, "<TD></TD>");
+		vnum = atol(buf);
 	}
-	send_buf(wdesc->fd, "</TR><TR><TD colspan=6>%s</TD>",
-			 show_list_to_html(pRoom->first_content));
-	send_buf(wdesc->fd, "</TR><TR><TD colspan=6>%s</TD>",
-			 show_char_to_html(pRoom->first_person));
-
-	send_buf(wdesc->fd, "</TR></TABLE>");
-	print_footer(wdesc);
+	if ((pRoom = get_room_index(vnum)) != NULL)
+	{
+		if (!IS_SET(pRoom->area->area_flags, AREA_CLOSED | AREA_PLAYER_HOMES))
+		{
+			EXIT_DATA *pexit;
+			int door;
+			char buf2[MSL * 4];
+
+			print_header(wdesc, pRoom->name);
+			send_buf(wdesc->fd, "<TABLE><TR><TD colspan=3>");
+			html_colourconv(buf2, pRoom->name);
+			send_buf(wdesc->fd, buf2);
+			send_buf(wdesc->fd, "</TD><TD colspan=3>%s", pRoom->area->name);
+			send_buf(wdesc->fd, "</TD></TR><TR><TD colspan=6>");
+			html_colourconv(buf2, pRoom->description);
+			send_buf(wdesc->fd, buf2);
+			send_buf(wdesc->fd, "</TD></TR><TR>");
+			for (door = 0; door < MAX_DIR; door++)
+			{
+				if ((pexit = pRoom->exit[door]) != NULL
+					&& pexit->u1.to_room != NULL)
+				{
+					send_buf(wdesc->fd,
+							 "<TD><A href=\"%srooms/%ld\">%s</A></TD>",
+							 HTTP_URL(), pexit->u1.to_room->vnum,
+							 dir_name[door]);
+				}
+				else
+					send_buf(wdesc->fd, "<TD></TD>");
+			}
+			send_buf(wdesc->fd, "</TR><TR><TD colspan=6>%s</TD>",
+					 show_list_to_html(pRoom->first_content));
+			send_buf(wdesc->fd, "</TR><TR><TD colspan=6>%s</TD>",
+					 show_char_to_html(pRoom->first_person));
+
+			send_buf(wdesc->fd, "</TR></TABLE>");
+			print_footer(wdesc);
+			return TRUE;
+		}
+	}
+	return FALSE;
 }
 
-void HandleSocialsRequest(WEB_DESCRIPTOR * wdesc)
+HANDLE_URL(HandleSocialsRequest)
 {
 	SOCIAL_DATA *iSocial;
 	int i;
@@ -2076,450 +2213,227 @@
 				 i++ % 5 == 0 ? "</TR><TR>" : "", iSocial->name);
 	send_buf(wdesc->fd, "%s</TABLE>\n", i % 5 != 0 ? "</TR>" : "");
 	print_footer(wdesc);
+	return TRUE;
 }
 
-void HandleImmRequest(WEB_DESCRIPTOR * wdesc)
-{
-	print_header(wdesc, "Immortal Info Page");
-	send_buf(wdesc->fd,
-			 "<hr><P><A href=\"%s%s/skdebug\">Skill Debug List</A></P>",
-			 DEFAULT_URL_PORT(), SECURE_URL);
-	send_buf(wdesc->fd, "<P><A href=\"%s%s/log\">Log Files</A></P>",
-			 DEFAULT_URL_PORT(), SECURE_URL);
-	send_buf(wdesc->fd, "<hr>");
-	print_footer(wdesc);
-}
-
-void HandleImmInvalid(WEB_DESCRIPTOR * wdesc)
-{
-	print_header(wdesc, "Invalid Username/Password");
-	send_buf(wdesc->fd,
-			 "<P>Invalid username/password.  Each field is Case Sensitive.</P>\n");
-	print_footer(wdesc);
-}
-
-void handle_web_request(WEB_DESCRIPTOR * wdesc)
+HANDLE_URL(HandleImmRequest)
 {
-	char tpath[MSL];
-	const char *stuff;
-	char *path;
-	int addr;
-	char web_buf[MSL];
-
-	stuff = first_arg(wdesc->request, tpath, FALSE);
-	first_arg(stuff, tpath, FALSE);
-
-	path = tpath;
-	path++;
-
-	/* process request */
-	/* are we using HTTP/1.x? If so, write out header stuff.. */
-	if (!strstr(wdesc->request, "GET"))
-	{
-		send_buf(wdesc->fd, "HTTP/1.1 501 Not Implemented");
-		return;
-	}
-	else if (strstr(wdesc->request, "HTTP/1."))
+	if (get_name_password(wdesc, stuff))
 	{
-		if (!str_prefix(SECURE_URL, path))
-		{
-			char *where;
-			char encoded[MIL];
-			char username[MIL];
-			char *password = &str_empty[0];
+		char *buf = get_next(path);
 
-			username[0] = '\0';
-			encoded[0] = '\0';
-
-			where = strstr(stuff, "Authorization: Basic");
-
-			if (!where)
-				send_401UNAUTHORISED(wdesc, AUTH_DOMAIN);
-			else
+		if (IS_NULLSTR(buf))
+		{
+			print_header(wdesc, "Immortal Info Page");
+			send_buf(wdesc->fd,
+					 "<hr><P><A href=\"%sstaffarea/skdebug\">Skill Debug List</A></P>",
+					 HTTP_URL());
+			send_buf(wdesc->fd,
+					 "<P><A href=\"%sstaffarea/log\">Log Files</A></P>",
+					 HTTP_URL());
+			send_buf(wdesc->fd, "<hr>");
+			print_footer(wdesc);
+			return TRUE;
+		}
+		else
+		{
+			if (!str_prefix("skdebug", buf))
 			{
-				where += strlen("Authorization: Basic");
-
-				where++;
-				for (password = encoded; *where && !isspace(*where);
-					 where++, password++)
-					*password = *where;
-
-				*password = '\0';
+				int i, sn;
 
-				Base64Decode(encoded, (unsigned char *) username, MIL);
-
-				for (password = username; *password && *password != ':';
-					 password++);
+				print_header(wdesc, "Skill List");
+				send_buf(wdesc->fd, "<TABLE><TR><TD>Skill Name</TD>\n");
+				for (i = 0; i < maxClass; i++)
+					send_buf(wdesc->fd, "<TD>%s</TD>\n", class_table[i].name);
+				send_buf(wdesc->fd, "</TR>\n");
+				for (sn = 0; sn < maxSkill; sn++)
 				{
-					if (*password == ':')
+					send_buf(wdesc->fd, "<TR><TD>%s</TD>\n",
+							 skill_table[sn].name);
+					for (i = 0; i < maxClass; i++)
 					{
-						*password = '\0';
-						password++;
+						if (skill_table[sn].skill_level[i] >= LEVEL_IMMORTAL)
+							send_buf(wdesc->fd, "<TD>---</TD>\n");
+						else
+							send_buf(wdesc->fd, "<TD>%d</TD>\n",
+									 skill_table[sn].skill_level[i]);
 					}
+					send_buf(wdesc->fd, "</TR>\n");
 				}
+				send_buf(wdesc->fd, "</TABLE>");
+				print_footer(wdesc);
+				return TRUE;
 			}
-
-			if (check_web_pass(username, password))
+			else if (!str_prefix("log", buf))
 			{
-				char *buf;
+				char buf2[MSL];
+				char *check = get_next(buf);
+				DIR *Directory;
+				struct dirent *Dir;
 
-				if (!str_cmp(path, SECURE_URL)
-					|| !str_cmp(path, SECURE_URL "/"))
+				if (IS_NULLSTR(check))
 				{
-					logf("Web Request: %s - Secure listing", web_buf);
-					HandleImmRequest(wdesc);
-					return;
-				}
-				buf = strchr(path, '/');
-				if (!IS_NULLSTR(buf))
-				{
-					buf++;
-					if (!str_cmp(buf, "skdebug") || !str_cmp(buf, "skdebug/"))
-					{
-						logf("Web Request: %s - Skill Debug listing", web_buf);
-						HandleSkDebugRequest(wdesc);
-						return;
-					}
-					else if (!str_prefix("log", buf))
-					{
-						char buf2[MSL];
-						char *check;
-						DIR *Directory;
-						struct dirent *Dir;
+					char buff[MSL];
+					int count = 0;
 
-						if (!str_cmp(buf, "log") || !str_cmp(buf, "log/"))
+					print_header(wdesc, "Log Files");
+					send_buf(wdesc->fd, "<TABLE><TR>\n");
+					Directory = opendir("../log");
+					Dir = readdir(Directory);
+					while (Dir != NULL)
+					{
+						if (!str_suffix(".log", Dir->d_name))
 						{
-							logf("Web Request: %s - Log listing", web_buf);
-							HandleLogRequest(wdesc);
-							return;
+							strcpy(buff, Dir->d_name);
+							buff[strlen(buff) - 4] = '\0';
+							send_buf(wdesc->fd,
+									 "%s<TD><A href=\"%s%s/log/%s\">%s</A></TD>\n",
+									 count % 5 == 0 ? "</TR><TR>" : "",
+									 HTTP_URL(), "staffarea", buff,
+									 Dir->d_name);
+							count++;
 						}
-						Directory = opendir("../log");
 						Dir = readdir(Directory);
-						check = strrchr(buf, '/');
-						if (!IS_NULLSTR(check))
+					}
+					closedir(Directory);
+					send_buf(wdesc->fd, "%s</TABLE>\n",
+							 count % 5 != 0 ? "</TR>" : "");
+					print_footer(wdesc);
+					return TRUE;
+				}
+				else
+				{
+					Directory = opendir("../log");
+					Dir = readdir(Directory);
+					while (Dir != NULL)
+					{
+						if (!str_suffix(".log", Dir->d_name))
 						{
-							check++;
-
-							while (Dir != NULL)
+							strcpy(buf2, Dir->d_name);
+							buf2[strlen(buf2) - 4] = '\0';
+							if (!str_cmp(buf2, check))
 							{
-								if (!str_suffix(".log", Dir->d_name))
-								{
-									strcpy(buf2, Dir->d_name);
-									buf2[strlen(buf2) - 4] = '\0';
-									if (!str_cmp(buf2, check))
-									{
-										logf("Web Request: Log %s", buf2);
-										HandleLogDumpRequest(wdesc, buf2);
-										return;
-									}
-								}
-								Dir = readdir(Directory);
+								print_header(wdesc, buf2);
+								send_buf(wdesc->fd, "<PRE>\n");
+								sprintf(buf2, "../log/%s", Dir->d_name);
+								print_file(wdesc, buf2);
+								send_buf(wdesc->fd, "</PRE>\n");
+								print_footer(wdesc);
+								return TRUE;
 							}
 						}
-						closedir(Directory);
-						goto unknown;
+						Dir = readdir(Directory);
 					}
+					closedir(Directory);
 				}
-				goto unknown;
-			}
-			else
-			{
-				HandleImmInvalid(wdesc);
-				return;
+				return FALSE;
 			}
 		}
+		return FALSE;
 	}
-
-	addr = ntohl(wdesc->their_addr.sin_addr.s_addr);
-
-	strcpy(web_buf, inet_ntoa(wdesc->their_addr.sin_addr));
-
-	if (!str_cmp(path, "online") || !str_cmp(path, "online/"))
-	{
-		logf("Web Request: %s - Who listing", web_buf);
-		HandleWhoRequest(wdesc);
-	}
-	else if (!str_cmp(path, "tech") || !str_cmp(path, "tech/"))
-	{
-		logf("Web Request: %s - Memory status", web_buf);
-		HandleMemoryRequest(wdesc);
-	}
-	else if (!str_cmp(path, "areas") || !str_cmp(path, "areas/"))
-	{
-		logf("Web Request: %s - Area listing", web_buf);
-		HandleAreaRequest(wdesc);
-	}
-	else if (!str_cmp(path, "spells") || !str_cmp(path, "spells/"))
-	{
-		logf("Web Request: %s - Spell listing", web_buf);
-		HandleSpellsRequest(wdesc);
-	}
-	else if (!str_cmp(path, "rules") || !str_cmp(path, "rules/"))
-	{
-		logf("Web Request: %s - Rules listing", web_buf);
-		HandleRulesRequest(wdesc);
-	}
-	else if (!str_cmp(path, "socials") || !str_cmp(path, "socials/"))
+	else
 	{
-		logf("Web Request: %s - Socials", web_buf);
-		HandleSocialsRequest(wdesc);
+		print_header(wdesc, "Invalid Username/Password");
+		send_buf(wdesc->fd,
+				 "<P>Invalid username/password.  Each field is Case Sensitive.</P>\n");
+		print_footer(wdesc);
+		return TRUE;
 	}
-	else if (!str_prefix("helps", path))
-	{
-		HELP_DATA *pHelp;
-		char *buf;
-		int pos;
-		char temp[MIL];
+}
 
-		if (!str_cmp(path, "helps") || !str_cmp(path, "helps/"))
-		{
-			logf("Web Request: %s - Help listing", web_buf);
-			HandleHelpsRequest(wdesc);
-			return;
-		}
-		buf = strrchr(path, '/');
-		if (!IS_NULLSTR(buf))
-		{
-			buf++;
+HANDLE_URL(HandleIndexRequest)
+{
+	print_header(wdesc, "Welcome");
+	send_buf(wdesc->fd, "<P>Connect to <A href=\"" TELNET_URL "\">%s</A></P>\n",
+			 port, MUD_NAME);
+	print_footer(wdesc);
+	return TRUE;
+}
 
-			pos = 0;
-			for (pHelp = help_first; pHelp != NULL; pHelp = pHelp->next)
-			{
-				pos++;
-				sprintf(temp, "%d", pos);
-				if (!str_cmp(buf, temp))
-				{
-					logf("Web Request: %s - Help File %s", pHelp->keyword,
-						 web_buf);
-					HandleHelpDumpRequest(wdesc, pHelp);
-					return;
-				}
-			}
-		}
-		goto unknown;
-	}
-	else if (!str_prefix("notes", path))
-	{
-		char *buf;
-		int pos;
+HANDLE_URL(HandleUnknownRequest)
+{
+	print_header(wdesc, "Error");
+	send_buf(wdesc->fd, "<p>Unknown url '%s'.</p>", path);
+	print_footer(wdesc);
+	return TRUE;
+}
 
-		if (!str_cmp(path, "notes") || !str_cmp(path, "notes/"))
-		{
-			logf("Web Request: %s - Note listing", web_buf);
-			HandleNotesRequest(wdesc);
-			return;
-		}
-		buf = strrchr(path, '/');
-		if (!IS_NULLSTR(buf))
-		{
-			buf++;
+const struct request_type request_table[] = {
+	{"index", "Home", HandleIndexRequest, FALSE},
+	{"online", "Online", HandleWhoRequest, FALSE},
+	{"tech", "Tech", HandleMemoryRequest, FALSE},
+	{"areas", "Areas", HandleAreaRequest, FALSE},
+	{"spells", "Spells", HandleSpellsRequest, FALSE},
+	{"rules", "Rules", HandleRulesRequest, FALSE},
+	{"socials", "Socials", HandleSocialsRequest, FALSE},
+	{"helps", "Helps", HandleHelpsRequest, FALSE},
+	{"notes", "Notes", HandleNotesRequest, FALSE},
+	{"races", "Races", HandleRaceRequest, FALSE},
+	{"commands", "Commands", HandleCommandsRequest, FALSE},
+	{"clans", "Clans", HandleClanRequest, FALSE},
+	{"class", "Classes", HandleClassRequest, FALSE},
+	{"stats", "Stats", HandleStatsRequest, FALSE},
+	{"rooms", "Explore", HandleRoomsRequest, FALSE},
+	{"objs", NULL, HandleObjsRequest, FALSE},
+	{"chars", NULL, HandleMobsRequest, FALSE},
+	{"staffarea", "Imm Only", HandleImmRequest, TRUE},
+	{NULL, NULL, NULL, 0}
+};
 
-			for (pos = 0; pos < MAX_BOARD - 3; pos++)
-			{
-				if (!str_cmp(boards[pos].short_name, buf))
-				{
-					logf("Web Request: %s - Note Board %s", web_buf,
-						 boards[pos].short_name);
-					HandleNotesDumpRequest(wdesc, &boards[pos]);
-					return;
-				}
-			}
-		}
-		goto unknown;
+void handle_web_request(WEB_DESCRIPTOR * wdesc)
+{
+	char temp[MSL];
+	const char *stuff;
+	char *path;
+	int addr, i;
+	char web_buf[MSL];
 
-	}
-	else if (!str_prefix("races", path))
-	{
-		RACE_DATA *race;
-		char *buf;
+	stuff = first_arg(wdesc->request, temp, FALSE);
+	first_arg(stuff, temp, FALSE);
 
-		if (!str_cmp(path, "races") || !str_cmp(path, "races/"))
-		{
-			logf("Web Request: %s - Race listing", web_buf);
-			HandleRaceRequest(wdesc);
-			return;
-		}
-		buf = strrchr(path, '/');
-		if (!IS_NULLSTR(buf))
-		{
-			buf++;
-			for (race = race_first; race; race = race->next)
-			{
-				if (!str_cmp(race->name, buf))
-				{
-					logf("Web Request: %s - Race %s", web_buf, race->name);
-					HandleRaceDumpRequest(wdesc, race);
-					return;
-				}
-			}
-		}
-		goto unknown;
-	}
-	else if (!str_cmp(path, "commands") || !str_cmp(path, "commands/"))
-	{
-		logf("Web Request: %s - Commands listing", web_buf);
-		HandleCommandsRequest(wdesc);
-		return;
-	}
-	else if (!str_prefix("clans", path))
+	path = temp;
+
+	if (path[0] == '/')
+		path++;
+
+	/* process request */
+	/* are we using HTTP/1.x? If so, write out header stuff.. */
+	if (!strstr(wdesc->request, "GET"))
 	{
-		logf("Web Request: %s - Clan listing", web_buf);
-		HandleClanRequest(wdesc);
+		send_buf(wdesc->fd, "HTTP/1.1 501 Not Implemented");
 		return;
 	}
-	else if (!str_prefix("class", path))
-	{
-		int i;
-		char *buf;
 
-		if (!str_cmp(path, "class") || !str_cmp(path, "class/"))
-		{
-			logf("Web Request: %s - Class listing", web_buf);
-			HandleClassRequest(wdesc);
-			return;
-		}
-		buf = strrchr(path, '/');
-		if (!IS_NULLSTR(buf))
-		{
-			buf++;
-			for (i = 0; i < maxClass; i++)
-			{
-				if (!str_cmp(class_table[i].name, buf))
-				{
-					logf("Web Request: %s - Class %s", web_buf,
-						 class_table[i].name);
-					HandleClassDumpRequest(wdesc, i);
-					return;
-				}
-			}
-		}
-		goto unknown;
-	}
-	else if (!str_prefix("chars", path))
-	{
-		MOB_INDEX_DATA *pMob;
-		char *buf;
+	addr = ntohl(wdesc->their_addr.sin_addr.s_addr);
 
-		buf = strrchr(path, '/');
-		if (!IS_NULLSTR(buf))
-		{
-			buf++;
+	strcpy(web_buf, inet_ntoa(wdesc->their_addr.sin_addr));
 
-			if (!is_number(buf))
-			{
-				logf("Request: %s - Bad mob vnum", web_buf);
-				goto unknown;
-			}
-			if ((pMob = get_mob_index(atol(buf))) != NULL)
-			{
-				logf("Web Request: %s - Mob %ld", web_buf, pMob->vnum);
-				HandleMobsRequest(wdesc, pMob);
-				return;
-			}
-		}
-		goto unknown;
-	}
-	else if (!str_prefix("objs", path))
+	if (IS_NULLSTR(path))
 	{
-		OBJ_INDEX_DATA *pObj;
-		char *buf;
-
-		buf = strrchr(path, '/');
-		if (!IS_NULLSTR(buf))
-		{
-			buf++;
-
-			if (!is_number(buf))
-			{
-				logf("Request: %s - Bad obj vnum", web_buf);
-				goto unknown;
-			}
-			if ((pObj = get_obj_index(atol(buf))) != NULL)
-			{
-				logf("Web Request: %s - Obj %ld", web_buf, pObj->vnum);
-				HandleObjsRequest(wdesc, pObj);
-				return;
-			}
-		}
-		goto unknown;
+		HandleIndexRequest(wdesc, "", "");
+		return;
 	}
-	else if (!str_prefix("rooms", path))
-	{
-		ROOM_INDEX_DATA *pRoom;
 
-		if (!str_cmp("rooms", path))
-		{
-			logf("Web Request: %s - Rooms listing", web_buf);
-			HandleRoomsRequest(wdesc, ROOM_VNUM_TEMPLE);
-			return;
-		}
-		else
-		{
-			char *buf;
-
-			buf = strrchr(path, '/');
-			if (!IS_NULLSTR(buf))
-			{
-				buf++;
+	logf("WebServer: %s requested '%s'.", web_buf, path);
 
-				if (!is_number(buf))
-				{
-					logf("Request: %s - Bad room vnum", web_buf);
-					goto unknown;
-				}
-				if ((pRoom = get_room_index(atol(buf))) != NULL)
-				{
-					if (!IS_SET
-						(pRoom->area->area_flags,
-						 AREA_CLOSED | AREA_PLAYER_HOMES))
-					{
-						logf("Web Request: %s - Room %ld", web_buf,
-							 pRoom->vnum);
-						HandleRoomsRequest(wdesc, pRoom->vnum);
-						return;
-					}
-				}
-			}
-			goto unknown;
-		}
-	}
-	else if (!str_prefix("stats", path))
+	for (i = 0; request_table[i].fun != NULL; i++)
 	{
-		int pos;
-		char *buf;
+		if (request_table[i].secure && !strstr(wdesc->request, "HTTP/1."))
+			break;
 
-		if (!str_cmp(path, "stats") || !str_cmp(path, "stats/"))
-		{
-			logf("Web Request: %s - Stats listing", web_buf);
-			HandleStatsRequest(wdesc);
-			return;
-		}
-		buf = strrchr(path, '/');
-		if (!IS_NULLSTR(buf))
+		if (!str_prefix(request_table[i].req, path))
 		{
-			buf++;
-
-			for (pos = 0; pos < MAX_GAMESTAT; pos++)
+			if ((*request_table[i].fun) (wdesc, path, stuff))
 			{
-				if (!str_cmp(stat_type_name[pos], buf))
-				{
-					logf("Web Request: %s - Stats %s", web_buf,
-						 stat_type_name[pos]);
-					HandleStatsTypeRequest(wdesc, pos);
-					return;
-				}
+				tail_chain();
+				return;
 			}
+			else
+				break;
 		}
-		goto unknown;
-	}
-	else
-	{
-	  unknown:
-		print_header(wdesc, "Error");
-		logf("Unknown Request [%s] by %s", path, web_buf);
-		send_buf(wdesc->fd, "Unknown url '%s'.<BR>", path);
-		print_footer(wdesc);
 	}
+
+	HandleUnknownRequest(wdesc, path, stuff);
 	tail_chain();
 }
 
diff -ur ./src/webserver.h ./new/webserver.h
--- ./src/webserver.h	Fri May 16 00:04:56 2003
+++ ./new/webserver.h	Fri May 16 02:11:35 2003
@@ -26,6 +26,9 @@
  *
  *	-- Christopher Aaron Haslage (Yakkov) 6/3/99 (No Help)
  */
+
+ /* Modded for 1stMUD by Markanth 14/05/2003 */
+
 #if !defined(WIN32)
 #include <arpa/inet.h>
 #else
@@ -45,13 +48,13 @@
  * as well as any other misc files req.
  */
 
-#define SECURE_URL      "staffarea"	/* The secure URL. http://mud.is.here:<port>/SECURE_URL */
-
-#define AUTH_DOMAIN     "Staff Area - Username and Password are CASE SENSITIVE."	/* Secure Area Description (tell me where this is used) */
+#define AUTH_DOMAIN     "Staff Area - Username and Password are CASE SENSITIVE."	/* Secure Area Description */
 #define MAXDATA         1024
 
-#define DEFAULT_URL     "http://localhost/"	// CHANGE THIS TO YOUR SERVER ADDRESS
-											// Important that it has a trailing '/'
+#define DEFAULT_URL     "http://localhost:%d/"	// CHANGE THIS TO YOUR SERVER ADDRESS
+
+#define TELNET_URL		"telnet://localhost:%d/"	// CHANGE THIS TO YOUR SEVER ADDRESS
+
 #define WEBSERVERPORT   (port + 5)	// port the web server will run on
 
 #define MUD_NAME        "1stMUD"	// You mud's name here
@@ -79,6 +82,20 @@
 	bool valid;
 	bool keepalive;
 };
+
+typedef bool WEB_FUN
+args((WEB_DESCRIPTOR * wdesc, char *path, const char *stuff));
+#define HANDLE_URL(fun)	bool fun (WEB_DESCRIPTOR *wdesc, char *path, const char *stuff)
+
+struct request_type
+{
+	char *req;
+	char *name;
+	WEB_FUN *fun;
+	bool secure;
+};
+
+extern const struct request_type request_table[];
 
 /* FUNCTION DEFS */
 int send_buf(int fd, const char *fmt, ...)