1stMUD4.0/bin/
1stMUD4.0/doc/MPDocs/
1stMUD4.0/player/
1stMUD4.0/win32/
1stMUD4.0/win32/rom/
/**************************************************************************
*  Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer,        *
*  Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe.   *
*                                                                         *
*  Merc Diku Mud improvements copyright (C) 1992, 1993 by Michael         *
*  Chastain, Michael Quan, and Mitchell Tse.                              *
*                                                                         *
*  In order to use any part of this Merc Diku Mud, you must comply with   *
*  both the original Diku license in 'license.doc' as well the Merc       *
*  license in 'license.txt'.  In particular, you may not remove either of *
*  these copyright notices.                                               *
*                                                                         *
*  Much time and thought has gone into this software and you are          *
*  benefiting.  We hope that you share your changes too.  What goes       *
*  around, comes around.                                                  *
***************************************************************************
*       ROM 2.4 is copyright 1993-1998 Russ Taylor                        *
*       ROM has been brought to you by the ROM consortium                 *
*           Russ Taylor (rtaylor@hypercube.org)                           *
*           Gabrielle Taylor (gtaylor@hypercube.org)                      *
*           Brian Moore (zump@rom.org)                                    *
*       By using this code, you have agreed to follow the terms of the    *
*       ROM license, in the file Rom24/doc/rom.license                    *
***************************************************************************
*       1stMUD ROM Derivative (c) 2001-2003 by Ryan Jennings              *
*            http://1stmud.dlmud.com/  <r-jenn@shaw.ca>                   *
***************************************************************************/
#include "merc.h"
#include "interp.h"
#include "recycle.h"
#include "tables.h"
#include "lookup.h"
#include "telnet.h"
#include "webserver.h"
#include "magic.h"
#include "tablesave.h"
#include "signals.h"

/*
 * Local functions.
 */
PROTOTYPE(ROOM_INDEX_DATA * find_location, (CHAR_DATA *, const char *));

CH_CMD(do_wiznet)
{
	int flag, col;
	char arg[MIL];

	col = 0;

	argument = one_argument(argument, arg);

	if (IS_NULLSTR(arg))
	{
		chprintln(ch, stringf
				  (ch, 0, ALIGN_CENTER, "-",
				   "{W[ " CTAG(_WIZNET) "WIZNET STATUS {W]{x"));

		for (flag = 0; wiznet_table[flag].name != NULL; flag++)
		{
			if (wiznet_table[flag].level <= get_trust(ch))
			{
				print_on_off(ch,
							 IS_SET(ch->wiznet, wiznet_table[flag].flag),
							 wiznet_table[flag].name, NULL);
				col++;
				if (col == 4)
				{
					chprintln(ch, "");
					col = 0;
				}
			}
		}
		if (col != 0)
			chprintln(ch, "");
		chprintln(ch, draw_line(ch, NULL, 0));
		return;
	}

	if (!str_prefix(arg, "on"))
	{
		chprintln(ch, "" CTAG(_WIZNET) "Welcome to Wiznet!{x");
		SET_BIT(ch->wiznet, WIZ_ON);
		return;
	}

	if (!str_prefix(arg, "off"))
	{
		chprintln(ch, "" CTAG(_WIZNET) "Signing off of Wiznet.{x");
		REMOVE_BIT(ch->wiznet, WIZ_ON);
		return;
	}

	if (!str_prefix(arg, "all"))
	{
		if (!str_prefix(argument, "on"))
		{
			for (flag = 0; wiznet_table[flag].name != NULL; flag++)
			{
				if (get_trust(ch) >= wiznet_table[flag].level
					&& !IS_SET(ch->wiznet, wiznet_table[flag].flag))
					SET_BIT(ch->wiznet, wiznet_table[flag].flag);
			}
			chprintln(ch, "" CTAG(_WIZNET)
					  "All available wiznet flags turned on.{x");
			return;
		}
		if (!str_prefix(argument, "off"))
		{
			for (flag = 0; wiznet_table[flag].name != NULL; flag++)
			{
				if (get_trust(ch) >= wiznet_table[flag].level
					&& IS_SET(ch->wiznet, wiznet_table[flag].flag))
					REMOVE_BIT(ch->wiznet, wiznet_table[flag].flag);
			}
			chprintln(ch, "" CTAG(_WIZNET)
					  "All available wiznet flags turned off.{x");
			return;
		}
		chprintln(ch, "Syntax: wiznet all on/off");
		return;
	}
	flag = wiznet_lookup(arg);

	if (flag == -1 || get_trust(ch) < wiznet_table[flag].level)
	{
		chprintln(ch, "No such option.");
		return;
	}

	set_on_off(ch, &ch->wiznet, wiznet_table[flag].flag,
			   FORMATF("" CTAG(_WIZNET) "You will now see {W%s" CTAG(_WIZNET)
					   " on wiznet.{x", wiznet_table[flag].name),
			   FORMATF("" CTAG(_WIZNET) "You will no longer see {W%s"
					   CTAG(_WIZNET) " on wiznet.{x", wiznet_table[flag].name));
}

void new_wiznet(CHAR_DATA * ch, OBJ_DATA * obj, flag_t flag,
				flag_t flag_skip, int min_level, const char *format, ...)
{
	DESCRIPTOR_DATA *d;
	va_list args;
	char string[MSL * 2];
	int i;
	const char *chan;

	if (IS_NULLSTR(format))
		return;

	va_start(args, format);
	vsnprintf(string, sizeof(string), format, args);
	va_end(args);

	for (i = 0; wiznet_table[i].name != NULL; i++)
		if (wiznet_table[i].flag == flag)
			break;

	chan = wiznet_table[i].name == NULL ? "all" : wiznet_table[i].name;

	for (d = descriptor_first; d != NULL; d = d->next)
	{
		if (d->connected == CON_PLAYING && IS_IMMORTAL(d->character) &&
			IS_SET(d->character->wiznet, WIZ_ON) && (!flag ||
													 IS_SET
													 (d->character->wiznet,
													  flag))
			&& (!flag_skip || !IS_SET(d->character->wiznet, flag_skip))
			&& get_trust(d->character) >= min_level && d->character != ch)
		{
			if (IS_SET(d->character->wiznet, WIZ_PREFIX))
				d_printf(d, CTAG(_WIZNET) "-%s-%s-> ", str_time(-1,
																GET_TZONE
																(d->character),
																"%I:%M:%S"),
						 chan);
			else
				d_print(d, CTAG(_WIZNET), 0);
			act_new(string, d->character, obj, ch, TO_CHAR, POS_DEAD);
		}
	}

	return;
}

CH_CMD(do_guild)
{
	char arg1[MAX_INPUT_LENGTH], arg2[MAX_INPUT_LENGTH];
	CHAR_DATA *victim;
	CLAN_DATA *clan;

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

	if (IS_NULLSTR(arg1) || IS_NULLSTR(arg2))
	{
		chprintln(ch, "Syntax: guild <char> <cln name>");
		return;
	}
	if ((victim = get_char_world(ch, arg1)) == NULL)
	{
		chprintln(ch, "They aren't playing.");
		return;
	}

	if (!str_prefix(arg2, "none"))
	{
		chprintln(ch, "They are now clanless.");
		chprintln(victim, "You are now a member of no clan!");
		victim->clan = NULL;
		victim->rank = 0;
		update_members(victim, TRUE);
		return;
	}

	if ((clan = clan_lookup(arg2)) == NULL)
	{
		chprintln(ch, "No such clan exists.");
		return;
	}

	if (clan->independent)
	{
		chprintlnf(ch, "They are now a %s.", clan->name);
		chprintlnf(victim, "You are now a %s.", clan->name);
	}
	else
	{
		chprintlnf(ch, "They are now a member of clan %s.",
				   capitalize(clan->name));
		chprintlnf(victim, "You are now a member of clan %s.\n\r",
				   capitalize(clan->name));
	}

	if (is_clan(victim))
	{
		update_members(victim, TRUE);
	}

	victim->clan = clan;
	victim->rank = 0;
	update_members(victim, FALSE);
}

/* equips a character */
CH_CMD(do_outfit)
{
	OBJ_DATA *obj;
	int i, sn;
	vnum_t vnum;

	if (ch->level > 5 || IS_NPC(ch))
	{
		chprintln(ch, "Find it yourself!");
		return;
	}

	if ((obj = get_eq_char(ch, WEAR_LIGHT)) == NULL)
	{
		obj = create_object(get_obj_index(OBJ_VNUM_SCHOOL_BANNER), 0);
		obj->cost = 0;
		obj_to_char(obj, ch);
		equip_char(ch, obj, WEAR_LIGHT);
	}

	if ((obj = get_eq_char(ch, WEAR_BODY)) == NULL)
	{
		obj = create_object(get_obj_index(OBJ_VNUM_SCHOOL_VEST), 0);
		obj->cost = 0;
		obj_to_char(obj, ch);
		equip_char(ch, obj, WEAR_BODY);
	}

	/* do the weapon thing */
	if ((obj = get_eq_char(ch, WEAR_WIELD)) == NULL)
	{
		sn = 0;
		vnum = OBJ_VNUM_SCHOOL_SWORD;	/* just in case! */

		for (i = 0; weapon_table[i].name != NULL; i++)
		{
			if (ch->pcdata->learned[sn] <
				ch->pcdata->learned[*weapon_table[i].gsn])
			{
				sn = *weapon_table[i].gsn;
				vnum = weapon_table[i].vnum;
			}
		}

		obj = create_object(get_obj_index(vnum), 0);
		obj_to_char(obj, ch);
		equip_char(ch, obj, WEAR_WIELD);
	}

	if (((obj = get_eq_char(ch, WEAR_WIELD)) == NULL ||
		 !IS_WEAPON_STAT(obj, WEAPON_TWO_HANDS)) &&
		(obj = get_eq_char(ch, WEAR_SHIELD)) == NULL)
	{
		obj = create_object(get_obj_index(OBJ_VNUM_SCHOOL_SHIELD), 0);
		obj->cost = 0;
		obj_to_char(obj, ch);
		equip_char(ch, obj, WEAR_SHIELD);
	}

	act("You have been equipped by $g.", ch, NULL, NULL, TO_CHAR);
}

/* RT nochannels command, for those spammers */
CH_CMD(do_nochannels)
{
	char arg[MAX_INPUT_LENGTH], buf[MAX_STRING_LENGTH];
	CHAR_DATA *victim;

	one_argument(argument, arg);

	if (IS_NULLSTR(arg))
	{
		chprintln(ch, "Nochannel whom?");
		return;
	}

	if ((victim = get_char_world(ch, arg)) == NULL)
	{
		chprintln(ch, "They aren't here.");
		return;
	}

	if (get_trust(victim) >= get_trust(ch))
	{
		chprintln(ch, "You failed.");
		return;
	}

	if (IS_SET(victim->comm, COMM_NOCHANNELS))
	{
		REMOVE_BIT(victim->comm, COMM_NOCHANNELS);
		chprintln(victim, "The gods have restored your channel priviliges.");
		chprintln(ch, "NOCHANNELS removed.");
		sprintf(buf, "$N restores channels to %s", victim->name);
		wiznet(buf, ch, NULL, WIZ_PENALTIES, WIZ_SECURE, 0);
	}
	else
	{
		SET_BIT(victim->comm, COMM_NOCHANNELS);
		chprintln(victim, "The gods have revoked your channel priviliges.");
		chprintln(ch, "NOCHANNELS set.");
		sprintf(buf, "$N revokes %s's channels.", victim->name);
		wiznet(buf, ch, NULL, WIZ_PENALTIES, WIZ_SECURE, 0);
	}

	return;
}

CH_CMD(do_smote)
{
	CHAR_DATA *vch;
	const char *letter, *name;
	char last[MAX_INPUT_LENGTH], temp[MAX_STRING_LENGTH];
	unsigned int matches = 0;

	if (!IS_NPC(ch) && IS_SET(ch->comm, COMM_NOEMOTE))
	{
		chprintln(ch, "You can't show your emotions.");
		return;
	}

	if (IS_NULLSTR(argument))
	{
		chprintln(ch, "Emote what?");
		return;
	}

	if (strstr(argument, ch->name) == NULL)
	{
		chprintln(ch, "You must include your name in an smote.");
		return;
	}

	chprintln(ch, argument);

	for (vch = ch->in_room->first_person; vch != NULL; vch = vch->next_in_room)
	{
		if (vch->desc == NULL || vch == ch)
			continue;

		if ((letter = strstr(argument, vch->name)) == NULL)
		{
			chprintln(vch, argument);
			continue;
		}

		strcpy(temp, argument);
		temp[strlen(argument) - strlen(letter)] = '\0';
		last[0] = '\0';
		name = vch->name;

		for (; *letter != '\0'; letter++)
		{
			if (*letter == '\'' && matches == strlen(vch->name))
			{
				strcat(temp, "r");
				continue;
			}

			if (*letter == 's' && matches == strlen(vch->name))
			{
				matches = 0;
				continue;
			}

			if (matches == strlen(vch->name))
			{
				matches = 0;
			}

			if (*letter == *name)
			{
				matches++;
				name++;
				if (matches == strlen(vch->name))
				{
					strcat(temp, "you");
					last[0] = '\0';
					name = vch->name;
					continue;
				}
				strncat(last, letter, 1);
				continue;
			}

			matches = 0;
			strcat(temp, last);
			strncat(temp, letter, 1);
			last[0] = '\0';
			name = vch->name;
		}

		chprintln(vch, temp);
	}

	return;
}

CH_CMD(do_bamfin)
{

	if (!IS_NPC(ch))
	{
		smash_tilde(argument);

		if (IS_NULLSTR(argument))
		{
			chprintlnf(ch, "Your poofin is %s", ch->pcdata->bamfin);
			return;
		}

		if (strstr(argument, ch->name) == NULL)
		{
			chprintln(ch, "You must include your name.");
			return;
		}

		replace_string(ch->pcdata->bamfin, argument);

		chprintlnf(ch, "Your poofin is now %s", ch->pcdata->bamfin);
	}
	return;
}

CH_CMD(do_bamfout)
{

	if (!IS_NPC(ch))
	{
		smash_tilde(argument);

		if (IS_NULLSTR(argument))
		{
			chprintlnf(ch, "Your poofout is %s", ch->pcdata->bamfout);
			return;
		}

		if (strstr(argument, ch->name) == NULL)
		{
			chprintln(ch, "You must include your name.");
			return;
		}

		replace_string(ch->pcdata->bamfout, argument);

		chprintlnf(ch, "Your poofout is now %s", ch->pcdata->bamfout);
	}
	return;
}

CH_CMD(do_deny)
{
	char arg[MAX_INPUT_LENGTH], buf[MAX_STRING_LENGTH];
	CHAR_DATA *victim;

	one_argument(argument, arg);
	if (IS_NULLSTR(arg))
	{
		chprintln(ch, "Deny whom?");
		return;
	}

	if ((victim = get_char_world(ch, arg)) == NULL)
	{
		chprintln(ch, "They aren't here.");
		return;
	}

	if (IS_NPC(victim))
	{
		chprintln(ch, "Not on NPC's.");
		return;
	}

	if (get_trust(victim) >= get_trust(ch))
	{
		chprintln(ch, "You failed.");
		return;
	}

	SET_BIT(victim->act, PLR_DENY);
	chprintln(victim, "You are denied access!");
	sprintf(buf, "$N denies access to %s", victim->name);
	wiznet(buf, ch, NULL, WIZ_PENALTIES, WIZ_SECURE, 0);
	chprintln(ch, "OK.");
	save_char_obj(victim);
	stop_fighting(victim, TRUE);
	do_function(victim, &do_quit, "");

	return;
}

CH_CMD(do_disconnect)
{
	char arg[MAX_INPUT_LENGTH];
	DESCRIPTOR_DATA *d;
	CHAR_DATA *victim;

	one_argument(argument, arg);
	if (IS_NULLSTR(arg))
	{
		chprintln(ch, "Disconnect whom?");
		return;
	}

	if (is_number(arg))
	{
		int desc;

		desc = atoi(arg);
		for (d = descriptor_first; d != NULL; d = d->next)
		{
			if (d->descriptor == desc)
			{
				close_socket(d);
				chprintln(ch, "Ok.");
				return;
			}
		}
	}

	if ((victim = get_char_world(ch, arg)) == NULL)
	{
		chprintln(ch, "They aren't here.");
		return;
	}

	if (victim->desc == NULL)
	{
		act("$N doesn't have a descriptor.", ch, NULL, victim, TO_CHAR);
		return;
	}

	for (d = descriptor_first; d != NULL; d = d->next)
	{
		if (d == victim->desc)
		{
			close_socket(d);
			chprintln(ch, "Ok.");
			return;
		}
	}

	bug("Do_disconnect: desc not found.");
	chprintln(ch, "Descriptor not found!");
	return;
}

CH_CMD(do_pardon)
{
	char arg1[MAX_INPUT_LENGTH];
	char arg2[MAX_INPUT_LENGTH];
	CHAR_DATA *victim;

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

	if (IS_NULLSTR(arg1) || IS_NULLSTR(arg2))
	{
		chprintln(ch, "Syntax: pardon <character> <killer|thief>.");
		return;
	}

	if ((victim = get_char_world(ch, arg1)) == NULL)
	{
		chprintln(ch, "They aren't here.");
		return;
	}

	if (IS_NPC(victim))
	{
		chprintln(ch, "Not on NPC's.");
		return;
	}

	if (!str_cmp(arg2, "killer"))
	{
		if (IS_SET(victim->act, PLR_KILLER))
		{
			REMOVE_BIT(victim->act, PLR_KILLER);
			chprintln(ch, "Killer flag removed.");
			chprintln(victim, "You are no longer a KILLER.");
		}
		return;
	}

	if (!str_cmp(arg2, "thief"))
	{
		if (IS_SET(victim->act, PLR_THIEF))
		{
			REMOVE_BIT(victim->act, PLR_THIEF);
			chprintln(ch, "Thief flag removed.");
			chprintln(victim, "You are no longer a THIEF.");
		}
		return;
	}

	chprintln(ch, "Syntax: pardon <character> <killer|thief>.");
	return;
}

CH_CMD(do_echo)
{
	DESCRIPTOR_DATA *d;

	if (IS_NULLSTR(argument))
	{
		chprintln(ch, "Global echo what?");
		return;
	}

	for (d = descriptor_first; d; d = d->next)
	{
		if (d->connected == CON_PLAYING)
		{
			if (get_trust(d->character) >= get_trust(ch))
				chprint(d->character, "global> ");
			chprintln(d->character, argument);
		}
	}

	return;
}

CH_CMD(do_recho)
{
	DESCRIPTOR_DATA *d;

	if (IS_NULLSTR(argument))
	{
		chprintln(ch, "Local echo what?");

		return;
	}

	for (d = descriptor_first; d; d = d->next)
	{
		if (d->connected == CON_PLAYING && d->character->in_room == ch->in_room)
		{
			if (get_trust(d->character) >= get_trust(ch))
				chprint(d->character, "local> ");
			chprintln(d->character, argument);
		}
	}

	return;
}

CH_CMD(do_zecho)
{
	DESCRIPTOR_DATA *d;

	if (IS_NULLSTR(argument))
	{
		chprintln(ch, "Zone echo what?");
		return;
	}

	for (d = descriptor_first; d; d = d->next)
	{
		if (d->connected == CON_PLAYING && d->character->in_room != NULL
			&& ch->in_room != NULL
			&& d->character->in_room->area == ch->in_room->area)
		{
			if (get_trust(d->character) >= get_trust(ch))
				chprint(d->character, "zone> ");
			chprintln(d->character, argument);
		}
	}
}

CH_CMD(do_pecho)
{
	char arg[MAX_INPUT_LENGTH];
	CHAR_DATA *victim;

	argument = one_argument(argument, arg);

	if (IS_NULLSTR(argument) || IS_NULLSTR(arg))
	{
		chprintln(ch, "Personal echo what?");
		return;
	}

	if ((victim = get_char_world(ch, arg)) == NULL)
	{
		chprintln(ch, "Target not found.");
		return;
	}

	if (get_trust(victim) >= get_trust(ch) && get_trust(ch) != MAX_LEVEL)
		chprint(victim, "personal> ");

	chprintln(victim, argument);
	chprint(ch, "personal> ");
	chprintln(ch, argument);
}

ROOM_INDEX_DATA *find_location(CHAR_DATA * ch, const char *arg)
{
	CHAR_DATA *victim;
	OBJ_DATA *obj;

	if (is_number(arg))
		return get_room_index(atol(arg));

	if ((victim = get_char_world(ch, arg)) != NULL)
		return victim->in_room;

	if ((obj = get_obj_world(ch, arg)) != NULL)
		return obj->in_room;

	return NULL;
}

CH_CMD(do_transfer)
{
	char arg1[MAX_INPUT_LENGTH];
	char arg2[MAX_INPUT_LENGTH];
	ROOM_INDEX_DATA *location;
	DESCRIPTOR_DATA *d;
	CHAR_DATA *victim;

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

	if (IS_NULLSTR(arg1))
	{
		chprintln(ch, "Transfer whom (and where)?");
		return;
	}

	if (!str_cmp(arg1, "all"))
	{
		for (d = descriptor_first; d != NULL; d = d->next)
		{
			if (d->connected == CON_PLAYING && d->character != ch &&
				d->character->in_room != NULL && can_see(ch, d->character))
			{
				char buf[MAX_STRING_LENGTH];
				sprintf(buf, "%s %s", d->character->name, arg2);
				do_function(ch, &do_transfer, buf);
			}
		}
		return;
	}

	/*
	 * Thanks to Grodyn for the optional location parameter.
	 */
	if (IS_NULLSTR(arg2))
	{
		location = ch->in_room;
	}
	else
	{
		if ((location = find_location(ch, arg2)) == NULL)
		{
			chprintln(ch, "No such location.");
			return;
		}

		if (!is_room_owner(ch, location) && room_is_private(location)
			&& get_trust(ch) < MAX_LEVEL)
		{
			chprintln(ch, "That room is private right now.");
			return;
		}
	}

	if ((victim = get_char_world(ch, arg1)) == NULL)
	{
		chprintln(ch, "They aren't here.");
		return;
	}

	if (victim->in_room == NULL)
	{
		chprintln(ch, "They are in limbo.");
		return;
	}

	if (victim->fighting != NULL)
		stop_fighting(victim, TRUE);
	act("$n disappears in a mushroom cloud.", victim, NULL, NULL, TO_ROOM);
	char_from_room(victim);
	char_to_room(victim, location);
	act("$n arrives from a puff of smoke.", victim, NULL, NULL, TO_ROOM);
	if (ch != victim)
		act("$n has transferred you.", ch, NULL, victim, TO_VICT);
	do_function(victim, &do_look, "auto");
	chprintln(ch, "Ok.");
}

CH_CMD(do_at)
{
	char arg[MAX_INPUT_LENGTH];
	ROOM_INDEX_DATA *location;
	ROOM_INDEX_DATA *original;
	OBJ_DATA *on;
	CHAR_DATA *wch;

	argument = one_argument(argument, arg);

	if (IS_NULLSTR(arg) || IS_NULLSTR(argument))
	{
		chprintln(ch, "At where what?");
		return;
	}

	if ((location = find_location(ch, arg)) == NULL)
	{
		chprintln(ch, "No such location.");
		return;
	}

	if (!is_room_owner(ch, location) && room_is_private(location) &&
		get_trust(ch) < MAX_LEVEL)
	{
		chprintln(ch, "That room is private right now.");
		return;
	}

	original = ch->in_room;
	on = ch->on;
	char_from_room(ch);
	char_to_room(ch, location);
	interpret(ch, argument);

	/*
	 * See if 'ch' still exists before continuing!
	 * Handles 'at XXXX quit' case.
	 */
	for (wch = char_first; wch != NULL; wch = wch->next)
	{
		if (wch == ch)
		{
			char_from_room(ch);
			char_to_room(ch, original);
			ch->on = on;
			break;
		}
	}

	return;
}

CH_CMD(do_goto)
{
	ROOM_INDEX_DATA *location;
	CHAR_DATA *rch;
	int count = 0;

	if (IS_NULLSTR(argument))
	{
		chprintln(ch, "Goto where?");
		return;
	}

	if ((location = find_location(ch, argument)) == NULL)
	{
		chprintln(ch, "No such location.");
		return;
	}

	count = 0;
	for (rch = location->first_person; rch != NULL; rch = rch->next_in_room)
		count++;

	if (!is_room_owner(ch, location) && room_is_private(location) &&
		(count > 1 || get_trust(ch) < MAX_LEVEL))
	{
		chprintln(ch, "That room is private right now.");
		return;
	}

	if (ch->fighting != NULL)
		stop_fighting(ch, TRUE);

	for (rch = ch->in_room->first_person; rch != NULL; rch = rch->next_in_room)
	{
		if (get_trust(rch) >= ch->invis_level)
		{
			if (ch->pcdata != NULL && !IS_NULLSTR(ch->pcdata->bamfout))
				act("$t", ch, ch->pcdata->bamfout, rch, TO_VICT);
			else
				act("$n leaves in a swirling mist.", ch, NULL, rch, TO_VICT);
		}
	}

	char_from_room(ch);
	char_to_room(ch, location);

	for (rch = ch->in_room->first_person; rch != NULL; rch = rch->next_in_room)
	{
		if (get_trust(rch) >= ch->invis_level)
		{
			if (ch->pcdata != NULL && !IS_NULLSTR(ch->pcdata->bamfin))
				act("$t", ch, ch->pcdata->bamfin, rch, TO_VICT);
			else
				act("$n appears in a swirling mist.", ch, NULL, rch, TO_VICT);
		}
	}

	do_function(ch, &do_look, "auto");
	return;
}

CH_CMD(do_violate)
{
	ROOM_INDEX_DATA *location;
	CHAR_DATA *rch;

	if (IS_NULLSTR(argument))
	{
		chprintln(ch, "Goto where?");
		return;
	}

	if ((location = find_location(ch, argument)) == NULL)
	{
		chprintln(ch, "No such location.");
		return;
	}

	if (!room_is_private(location))
	{
		chprintln(ch, "That room isn't private, use goto.");
		return;
	}

	if (ch->fighting != NULL)
		stop_fighting(ch, TRUE);

	for (rch = ch->in_room->first_person; rch != NULL; rch = rch->next_in_room)
	{
		if (get_trust(rch) >= ch->invis_level)
		{
			if (ch->pcdata != NULL && !IS_NULLSTR(ch->pcdata->bamfout))
				act("$t", ch, ch->pcdata->bamfout, rch, TO_VICT);
			else
				act("$n leaves in a swirling mist.", ch, NULL, rch, TO_VICT);
		}
	}

	char_from_room(ch);
	char_to_room(ch, location);

	for (rch = ch->in_room->first_person; rch != NULL; rch = rch->next_in_room)
	{
		if (get_trust(rch) >= ch->invis_level)
		{
			if (ch->pcdata != NULL && !IS_NULLSTR(ch->pcdata->bamfin))
				act("$t", ch, ch->pcdata->bamfin, rch, TO_VICT);
			else
				act("$n appears in a swirling mist.", ch, NULL, rch, TO_VICT);
		}
	}

	do_function(ch, &do_look, "auto");
	return;
}

/* RT to replace the 3 stat commands */

CH_CMD(do_old_stat)
{
	char arg[MAX_INPUT_LENGTH];
	const char *string;
	OBJ_DATA *obj;
	ROOM_INDEX_DATA *location;
	CHAR_DATA *victim;

	string = one_argument(argument, arg);
	if (IS_NULLSTR(arg))
	{
		chprintln(ch, "Syntax:");
		chprintln(ch, "  stat <name>");
		chprintln(ch, "  stat obj <name>");
		chprintln(ch, "  stat mob <name>");
		chprintln(ch, "  stat room <number>");
		return;
	}

	if (!str_cmp(arg, "room"))
	{
		do_function(ch, &do_rstat, string);
		return;
	}

	if (!str_cmp(arg, "obj"))
	{
		do_function(ch, &do_ostat, string);
		return;
	}

	if (!str_cmp(arg, "char") || !str_cmp(arg, "mob"))
	{
		do_function(ch, &do_mstat, string);
		return;
	}

	/* do it the old way */

	obj = get_obj_world(ch, argument);
	if (obj != NULL)
	{
		do_function(ch, &do_ostat, argument);
		return;
	}

	victim = get_char_world(ch, argument);
	if (victim != NULL)
	{
		do_function(ch, &do_mstat, argument);
		return;
	}

	location = find_location(ch, argument);
	if (location != NULL)
	{
		do_function(ch, &do_rstat, argument);
		return;
	}

	chprintln(ch, "Nothing by that name found anywhere.");
}

CH_CMD(do_rstat)
{
	char buf[MAX_STRING_LENGTH];
	char arg[MAX_INPUT_LENGTH];
	ROOM_INDEX_DATA *location;
	OBJ_DATA *obj;
	CHAR_DATA *rch;
	int door;

	one_argument(argument, arg);
	location = (IS_NULLSTR(arg)) ? ch->in_room : find_location(ch, arg);
	if (location == NULL)
	{
		chprintln(ch, "No such location.");
		return;
	}

	if (!is_room_owner(ch, location) && ch->in_room != location &&
		room_is_private(location) && !IS_TRUSTED(ch, IMPLEMENTOR))
	{
		chprintln(ch, "That room is private right now.");
		return;
	}

	chprintlnf(ch, "Name: '%s'\n\rArea: '%s'", location->name,
			   location->area->name);

	chprintlnf(ch,
			   "Vnum: %ld  Sector: %d  Light: %d  Healing: %d  Mana: %d",
			   location->vnum, location->sector_type, location->light,
			   location->heal_rate, location->mana_rate);

	chprintf(ch, "Room flags: %s.\n\rDescription:\n\r%s",
			 flag_string(room_flags, location->room_flags),
			 location->description);

	if (location->first_extra_descr != NULL)
	{
		EXTRA_DESCR_DATA *ed;

		chprint(ch, "Extra description keywords: '");
		for (ed = location->first_extra_descr; ed; ed = ed->next)
		{
			chprint(ch, ed->keyword);
			if (ed->next != NULL)
				chprint(ch, " ");
		}
		chprintln(ch, "'.");
	}

	chprint(ch, "Characters:");
	for (rch = location->first_person; rch; rch = rch->next_in_room)
	{
		if (can_see(ch, rch))
		{
			chprint(ch, " ");
			one_argument(rch->name, buf);
			chprint(ch, buf);
		}
	}

	chprint(ch, ".\n\rObjects:   ");
	for (obj = location->first_content; obj; obj = obj->next_content)
	{
		chprint(ch, " ");
		one_argument(obj->name, buf);
		chprint(ch, buf);
	}
	chprintln(ch, ".");

	for (door = 0; door <= 5; door++)
	{
		EXIT_DATA *pexit;

		if ((pexit = location->exit[door]) != NULL)
		{
			chprintf(ch,
					 "Door: %d.  To: %ld.  Key: %ld.  Exit flags: %s.\n\rKeyword: '%s'.  Description: %s",
					 door,
					 (pexit->u1.to_room ==
					  NULL ? -1 : pexit->u1.to_room->vnum),
					 pexit->key, flag_string(exit_flags, pexit->exit_info),
					 pexit->keyword,
					 pexit->description[0] !=
					 '\0' ? pexit->description : "(none).\n\r");
		}
	}

	return;
}

CH_CMD(do_ostat)
{
	char buf[MAX_STRING_LENGTH];
	char arg[MAX_INPUT_LENGTH];
	AFFECT_DATA *paf;
	OBJ_DATA *obj;

	one_argument(argument, arg);

	if (IS_NULLSTR(arg))
	{
		chprintln(ch, "Stat what?");
		return;
	}

	if ((obj = get_obj_world(ch, argument)) == NULL)
	{
		chprintln(ch, "Nothing like that in hell, earth, or heaven.");
		return;
	}

	chprintlnf(ch, "Name(s): %s", obj->name);

	chprintlnf(ch, "Vnum: %ld  Format: %s  Type: %s  Resets: %d",
			   obj->pIndexData->vnum,
			   obj->pIndexData->new_format ? "new" : "old",
			   item_name(obj->item_type), obj->pIndexData->reset_num);

	chprintlnf(ch, "Short description: %s\n\rLong description: %s",
			   obj->short_descr, obj->description);

	chprintlnf(ch, "Wear bits: %s\n\rExtra bits: %s",
			   flag_string(wear_flags, obj->wear_flags),
			   flag_string(extra_flags, obj->extra_flags));

	chprintlnf(ch, "Number: %d/%d  Weight: %d/%d/%d (10th pounds)", 1,
			   get_obj_number(obj), obj->weight, get_obj_weight(obj),
			   get_true_weight(obj));

	chprintlnf(ch, "Level: %d  Cost: %d  Condition: %d  Timer: %d",
			   obj->level, obj->cost, obj->condition, obj->timer);

	chprintlnf(ch,
			   "In room: %ld  In object: %s  Carried by: %s  Wear_loc: %d",
			   obj->in_room == NULL ? 0 : obj->in_room->vnum,
			   obj->in_obj == NULL ? "(none)" : obj->in_obj->short_descr,
			   obj->carried_by == NULL ? "(none)" : can_see(ch,
															obj->carried_by)
			   ? obj->carried_by->name : "someone", obj->wear_loc);

	chprintlnf(ch, "Values: %ld %ld %ld %ld %ld", obj->value[0],
			   obj->value[1], obj->value[2], obj->value[3], obj->value[4]);

	/* now give out vital statistics as per identify */

	switch (obj->item_type)
	{
	case ITEM_SCROLL:
	case ITEM_POTION:
	case ITEM_PILL:
		chprintf(ch, "Level %ld spells of:", obj->value[0]);

		if (obj->value[1] >= 0 && obj->value[1] < maxSkill)
		{
			chprint(ch, " '");
			chprint(ch, skill_table[obj->value[1]].name);
			chprint(ch, "'");
		}

		if (obj->value[2] >= 0 && obj->value[2] < maxSkill)
		{
			chprint(ch, " '");
			chprint(ch, skill_table[obj->value[2]].name);
			chprint(ch, "'");
		}

		if (obj->value[3] >= 0 && obj->value[3] < maxSkill)
		{
			chprint(ch, " '");
			chprint(ch, skill_table[obj->value[3]].name);
			chprint(ch, "'");
		}

		if (obj->value[4] >= 0 && obj->value[4] < maxSkill)
		{
			chprint(ch, " '");
			chprint(ch, skill_table[obj->value[4]].name);
			chprint(ch, "'");
		}

		chprintln(ch, ".");
		break;

	case ITEM_WAND:
	case ITEM_STAFF:
		chprintf(ch, "Has %ld(%ld) charges of level %ld", obj->value[1],
				 obj->value[2], obj->value[0]);

		if (obj->value[3] >= 0 && obj->value[3] < maxSkill)
		{
			chprint(ch, " '");
			chprint(ch, skill_table[obj->value[3]].name);
			chprint(ch, "'");
		}

		chprintln(ch, ".");
		break;

	case ITEM_DRINK_CON:
		chprintlnf(ch, "It holds %s-colored %s.",
				   liq_table[obj->value[2]].liq_color,
				   liq_table[obj->value[2]].liq_name);
		break;

	case ITEM_WEAPON:
		chprint(ch, "Weapon type is ");
		switch (obj->value[0])
		{
		case (WEAPON_EXOTIC):
			chprintln(ch, "exotic");
			break;
		case (WEAPON_SWORD):
			chprintln(ch, "sword");
			break;
		case (WEAPON_DAGGER):
			chprintln(ch, "dagger");
			break;
		case (WEAPON_SPEAR):
			chprintln(ch, "spear/staff");
			break;
		case (WEAPON_MACE):
			chprintln(ch, "mace/club");
			break;
		case (WEAPON_AXE):
			chprintln(ch, "axe");
			break;
		case (WEAPON_FLAIL):
			chprintln(ch, "flail");
			break;
		case (WEAPON_WHIP):
			chprintln(ch, "whip");
			break;
		case (WEAPON_POLEARM):
			chprintln(ch, "polearm");
			break;
		default:
			chprintln(ch, "unknown");
			break;
		}
		if (obj->pIndexData->new_format)
			sprintf(buf, "Damage is %ldd%ld (average %ld)\n\r",
					obj->value[1], obj->value[2],
					(1 + obj->value[2]) * obj->value[1] / 2);
		else
			chprintlnf(ch, "Damage is %ld to %ld (average %ld)",
					   obj->value[1], obj->value[2],
					   (obj->value[1] + obj->value[2]) / 2);

		chprintlnf(ch, "Damage noun is %s.",
				   (obj->value[3] > 0 &&
					obj->value[3] <
					MAX_DAMAGE_MESSAGE) ? attack_table[obj->value[3]].noun :
				   "undefined");

		if (obj->value[4])		/* weapon flags */
		{
			chprintlnf(ch, "Weapons flags: %s",
					   flag_string(weapon_type2, obj->value[4]));
		}
		break;

	case ITEM_ARMOR:
		chprintlnf(ch,
				   "Armor class is %ld pierce, %ld bash, %ld slash, and %ld vs. magic",
				   obj->value[0], obj->value[1], obj->value[2], obj->value[3]);
		break;

	case ITEM_CONTAINER:
		chprintlnf(ch,
				   "Capacity: %ld#  Maximum weight: %ld#  flags: %s",
				   obj->value[0], obj->value[3],
				   flag_string(container_flags, obj->value[1]));
		if (obj->value[4] != 100)
		{
			chprintlnf(ch, "Weight multiplier: %ld%%", obj->value[4]);
		}
		break;
	}

	if (obj->first_extra_descr != NULL
		|| obj->pIndexData->first_extra_descr != NULL)
	{
		EXTRA_DESCR_DATA *ed;

		chprint(ch, "Extra description keywords: '");

		for (ed = obj->first_extra_descr; ed != NULL; ed = ed->next)
		{
			chprint(ch, ed->keyword);
			if (ed->next != NULL)
				chprint(ch, " ");
		}

		for (ed = obj->pIndexData->first_extra_descr; ed != NULL; ed = ed->next)
		{
			chprint(ch, ed->keyword);
			if (ed->next != NULL)
				chprint(ch, " ");
		}

		chprintln(ch, "'");
	}

	for (paf = obj->first_affect; paf != NULL; paf = paf->next)
	{
		chprintf(ch, "Affects %s by %d, level %d",
				 flag_string(apply_flags, paf->location), paf->modifier,
				 paf->level);
		if (paf->duration > -1)
			sprintf(buf, ", %d hours.", paf->duration);
		else
			sprintf(buf, ".");
		chprintln(ch, buf);
		if (paf->bitvector)
		{
			switch (paf->where)
			{
			case TO_AFFECTS:
				sprintf(buf, "Adds %s affect.",
						flag_string(affect_flags, paf->bitvector));
				break;
			case TO_WEAPON:
				sprintf(buf, "Adds %s weapon flags.",
						flag_string(weapon_type2, paf->bitvector));
				break;
			case TO_OBJECT:
				sprintf(buf, "Adds %s object flag.",
						flag_string(extra_flags, paf->bitvector));
				break;
			case TO_IMMUNE:
				sprintf(buf, "Adds immunity to %s.",
						flag_string(imm_flags, paf->bitvector));
				break;
			case TO_RESIST:
				sprintf(buf, "Adds resistance to %s.",
						flag_string(imm_flags, paf->bitvector));
				break;
			case TO_VULN:
				sprintf(buf, "Adds vulnerability to %s.",
						flag_string(imm_flags, paf->bitvector));
				break;
			default:
				sprintf(buf, "Unknown bit %d.", paf->where);
				break;
			}
			chprintln(ch, buf);
		}
	}

	if (!obj->enchanted)
		for (paf = obj->pIndexData->first_affect; paf != NULL; paf = paf->next)
		{
			chprintlnf(ch, "Affects %s by %d, level %d.",
					   flag_string(apply_flags, paf->location),
					   paf->modifier, paf->level);
			if (paf->bitvector)
			{
				switch (paf->where)
				{
				case TO_AFFECTS:
					sprintf(buf, "Adds %s affect.",
							flag_string(affect_flags, paf->bitvector));
					break;
				case TO_OBJECT:
					sprintf(buf, "Adds %s object flag.",
							flag_string(extra_flags, paf->bitvector));
					break;
				case TO_IMMUNE:
					sprintf(buf, "Adds immunity to %s.",
							flag_string(imm_flags, paf->bitvector));
					break;
				case TO_RESIST:
					sprintf(buf, "Adds resistance to %s.",
							flag_string(imm_flags, paf->bitvector));
					break;
				case TO_VULN:
					sprintf(buf, "Adds vulnerability to %s.",
							flag_string(imm_flags, paf->bitvector));
					break;
				default:
					sprintf(buf, "Unknown bit %d.", paf->where);
					break;
				}
				chprintln(ch, buf);
			}
		}

	return;
}

CH_CMD(do_mstat)
{
	char arg[MAX_INPUT_LENGTH];
	AFFECT_DATA *paf;
	CHAR_DATA *victim;

	one_argument(argument, arg);

	if (IS_NULLSTR(arg))
	{
		chprintln(ch, "Stat whom?");
		return;
	}

	if ((victim = get_char_world(ch, argument)) == NULL)
	{
		chprintln(ch, "They aren't here.");
		return;
	}

	chprintlnf(ch, "Name: %s", victim->name);

	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,
			   victim->in_room == NULL ? 0 : victim->in_room->vnum);

	if (IS_NPC(victim))
	{
		chprintlnf(ch, "Count: %d  Killed: %d",
				   victim->pIndexData->count, victim->pIndexData->killed);
	}

	chprintlnf(ch,
			   "Str: %d(%d)  Int: %d(%d)  Wis: %d(%d)  Dex: %d(%d)  Con: %d(%d)",
			   victim->perm_stat[STAT_STR], get_curr_stat(victim, STAT_STR),
			   victim->perm_stat[STAT_INT], get_curr_stat(victim, STAT_INT),
			   victim->perm_stat[STAT_WIS], get_curr_stat(victim, STAT_WIS),
			   victim->perm_stat[STAT_DEX], get_curr_stat(victim, STAT_DEX),
			   victim->perm_stat[STAT_CON], get_curr_stat(victim, STAT_CON));

	chprintlnf(ch,
			   "Hp: %ld/%ld  Mana: %ld/%ld  Move: %ld/%ld  Practices: %d",
			   victim->hit, victim->max_hit, victim->mana, victim->max_mana,
			   victim->move, victim->max_move,
			   IS_NPC(ch) ? 0 : victim->practice);

	chprintlnf(ch,
			   "Lv: %d  Class: %s  Align: %d  Gold: %ld  Silver: %ld  Exp: %d",
			   victim->level,
			   IS_NPC(victim) ? "mobile" : class_short(victim),
			   victim->alignment, victim->gold, victim->silver, victim->exp);

	chprintlnf(ch, "Armor: pierce: %d  bash: %d  slash: %d  magic: %d",
			   GET_AC(victim, AC_PIERCE), GET_AC(victim, AC_BASH),
			   GET_AC(victim, AC_SLASH), GET_AC(victim, AC_EXOTIC));

	chprintlnf(ch,
			   "Hit: %d  Dam: %d  Saves: %d  Size: %s  Position: %s  Wimpy: %d",
			   GET_HITROLL(victim), GET_DAMROLL(victim),
			   victim->saving_throw, size_table[victim->size].name,
			   position_table[victim->position].name, victim->wimpy);

	if (IS_NPC(victim) && victim->pIndexData->new_format)
	{
		chprintlnf(ch, "Damage: %dd%d  Message:  %s",
				   victim->damage[DICE_NUMBER], victim->damage[DICE_TYPE],
				   attack_table[victim->dam_type].noun);
	}
	chprintlnf(ch, "Fighting: %s",
			   victim->fighting ? victim->fighting->name : "(none)");

	if (!IS_NPC(victim))
	{
		chprintlnf(ch, "Thirst: %d  Hunger: %d  Full: %d  Drunk: %d",
				   victim->pcdata->condition[COND_THIRST],
				   victim->pcdata->condition[COND_HUNGER],
				   victim->pcdata->condition[COND_FULL],
				   victim->pcdata->condition[COND_DRUNK]);
	}

	chprintlnf(ch, "Carry number: %d  Carry weight: %ld",
			   victim->carry_number, get_carry_weight(victim) / 10);

	if (!IS_NPC(victim))
	{
		chprintlnf(ch,
				   "Age: %d  Played: %d  Last Level: %d  Timer: %d",
				   get_age(victim),
				   (int) (victim->played + current_time -
						  victim->logon) / 3600, victim->pcdata->last_level,
				   victim->timer);
	}

	if (IS_NPC(victim))
		chprintlnf(ch, "Act: %s", flag_string(act_flags, victim->act));
	else
		chprintlnf(ch, "Plr: %s", flag_string(plr_flags, victim->act));

	if (victim->comm)
	{
		chprintlnf(ch, "Comm: %s", flag_string(comm_flags, victim->comm));
	}

	if (IS_NPC(victim) && victim->off_flags)
	{
		chprintlnf(ch, "Offense: %s",
				   flag_string(off_flags, victim->off_flags));
	}

	if (victim->imm_flags)
	{
		chprintlnf(ch, "Immune: %s", flag_string(imm_flags, victim->imm_flags));
	}

	if (victim->res_flags)
	{
		chprintlnf(ch, "Resist: %s", flag_string(imm_flags, victim->res_flags));
	}

	if (victim->vuln_flags)
	{
		chprintlnf(ch, "Vulnerable: %s",
				   flag_string(imm_flags, victim->vuln_flags));
	}

	chprintlnf(ch, "Form: %s\n\rParts: %s",
			   flag_string(form_flags, victim->form),
			   flag_string(part_flags, victim->parts));

	if (victim->affected_by)
	{
		chprintlnf(ch, "Affected by %s",
				   flag_string(affect_flags, victim->affected_by));
	}

	chprintlnf(ch, "Master: %s  Leader: %s  Pet: %s",
			   victim->master ? victim->master->name : "(none)",
			   victim->leader ? victim->leader->name : "(none)",
			   victim->pet ? victim->pet->name : "(none)");

	if (!IS_NPC(victim))
	{
		chprintlnf(ch, "Security: %d.", victim->pcdata->security);	/* OLC */
	}

	chprintf(ch, "Short description: %s\n\rLong  description: %s",
			 victim->short_descr,
			 !IS_NULLSTR(victim->long_descr) ? victim->
			 long_descr : "(none)\n\r");

	if (IS_NPC(victim) && victim->spec_fun != 0)
	{
		chprintlnf(ch, "Mobile has special procedure %s.",
				   spec_name(victim->spec_fun));
	}
	if (victim->desc != NULL)
	{
		if (victim->desc->d_flags != 0)
			chprintlnf(ch, "Descriptor Flags: %s",
					   flag_string(desc_flags, victim->desc->d_flags));
		if (!IS_NULLSTR(victim->desc->ttype))
			chprintlnf(ch, "Terminal: %s", victim->desc->ttype);
		if (victim->desc->bytes_normal != 0)
			chprintlnf(ch, "Bytes Normal: %ld", victim->desc->bytes_normal);
#if !defined(NO_MCCP)
		if (victim->desc->out_compress && victim->desc->bytes_compressed != 0)
			chprintlnf(ch, "Bytes Compressed: %ld",
					   victim->desc->bytes_compressed);
		if (victim->desc->mccp_version != 0)
			chprintlnf(ch, "MCCP version: %d", victim->desc->mccp_version);
#endif
	}
	if (!IS_NPC(victim) && IS_SET(victim->act, PLR_QUESTOR))
	{
		OBJ_INDEX_DATA *questinfoobj;
		MOB_INDEX_DATA *questinfo;
		ROOM_INDEX_DATA *questroom = get_room_index(victim->pcdata->questloc);

		if (victim->pcdata->questmob == -1 || has_questobj(victim))
		{
			chprintlnf(ch, "%s's Quest is ALMOST complete.", victim->name);
		}
		else if (victim->pcdata->questobj > 0)
		{
			if ((questinfoobj =
				 get_obj_index(victim->pcdata->questobj)) != NULL)
			{
				chprintf(ch, "They are on a quest to recover %s. ",
						 questinfoobj->short_descr);
				if (questroom != NULL)
				{
					chprintlnf(ch, "(Room: %ld)", questroom->vnum);
				}
				else
					chprintln(ch, "");
			}
			else
				chprintln(ch, "BUG: player has NULL quest obj.");
		}
		else if (victim->pcdata->questmob > 0)
		{
			if ((questinfo = get_mob_index(victim->pcdata->questmob)) != NULL)
			{
				chprintf(ch, "They are on a quest to slay %s. ",
						 questinfo->short_descr);
				if (questroom != NULL)
				{
					chprintlnf(ch, "(Room: %ld)", questroom->vnum);
				}
				else
					chprintln(ch, "");
			}
			else
				chprintln(ch, "BUG: player has NULL quest mob.");
		}
	}

	for (paf = victim->first_affect; paf != NULL; paf = paf->next)
	{
		chprintlnf(ch,
				   "Spell: '%s' modifies %s by %d for %d hours with bits %s, level %d.",
				   skill_table[(int) paf->type].name,
				   flag_string(apply_flags, paf->location), paf->modifier,
				   paf->duration, flag_string(affect_flags,
											  paf->bitvector), paf->level);
	}

	return;
}

/* ofind and mfind replaced with vnum, vnum skill also added */

CH_CMD(do_vnum)
{
	char arg[MAX_INPUT_LENGTH];
	const char *string;

	string = one_argument(argument, arg);

	if (IS_NULLSTR(arg))
	{
		chprintln(ch, "Syntax:");
		chprintln(ch, "  vnum obj <name>");
		chprintln(ch, "  vnum mob <name>");
		chprintln(ch, "  vnum skill <skill or spell>");
		return;
	}

	if (!str_cmp(arg, "obj"))
	{
		do_function(ch, &do_ofind, string);
		return;
	}

	if (!str_cmp(arg, "mob") || !str_cmp(arg, "char"))
	{
		do_function(ch, &do_mfind, string);
		return;
	}

	if (!str_cmp(arg, "skill") || !str_cmp(arg, "spell"))
	{
		do_function(ch, &do_slookup, string);
		return;
	}
	/* do both */
	do_function(ch, &do_mfind, argument);
	do_function(ch, &do_ofind, argument);
}

CH_CMD(do_mfind)
{
	char arg[MAX_INPUT_LENGTH];
	MOB_INDEX_DATA *pMobIndex;
	vnum_t vnum;
	int nMatch;
	bool fAll;
	bool found;

	one_argument(argument, arg);
	if (IS_NULLSTR(arg))
	{
		chprintln(ch, "Find whom?");
		return;
	}

	fAll = FALSE;				/* !str_cmp( arg, "all" ); */
	found = FALSE;
	nMatch = 0;

	/*
	 * Yeah, so iterating over all vnum's takes 10,000 loops.
	 * Get_mob_index is fast, and I don't feel like threading another link.
	 * Do you?
	 * -- Furey
	 */
	for (vnum = 0; nMatch < top_mob_index; vnum++)
	{
		if ((pMobIndex = get_mob_index(vnum)) != NULL)
		{
			nMatch++;
			if (fAll || is_name(argument, pMobIndex->player_name))
			{
				found = TRUE;
				chprintlnf(ch, "[%5ld] %s", pMobIndex->vnum,
						   pMobIndex->short_descr);
			}
		}
	}

	if (!found)
		chprintln(ch, "No mobiles by that name.");

	return;
}

CH_CMD(do_ofind)
{
	char arg[MAX_INPUT_LENGTH];
	OBJ_INDEX_DATA *pObjIndex;
	vnum_t vnum;
	int nMatch;
	bool fAll;
	bool found;

	one_argument(argument, arg);
	if (IS_NULLSTR(arg))
	{
		chprintln(ch, "Find what?");
		return;
	}

	fAll = FALSE;				/* !str_cmp( arg, "all" ); */
	found = FALSE;
	nMatch = 0;

	/*
	 * Yeah, so iterating over all vnum's takes 10,000 loops.
	 * Get_obj_index is fast, and I don't feel like threading another link.
	 * Do you?
	 * -- Furey
	 */
	for (vnum = 0; nMatch < top_obj_index; vnum++)
	{
		if ((pObjIndex = get_obj_index(vnum)) != NULL)
		{
			nMatch++;
			if (fAll || is_name(argument, pObjIndex->name))
			{
				found = TRUE;
				chprintlnf(ch, "[%5ld] %s", pObjIndex->vnum,
						   pObjIndex->short_descr);
			}
		}
	}

	if (!found)
		chprintln(ch, "No objects by that name.");

	return;
}

CH_CMD(do_owhere)
{
	BUFFER *buffer;
	OBJ_DATA *obj;
	OBJ_DATA *in_obj;
	bool found;
	int number = 0, max_found;

	found = FALSE;
	number = 0;
	max_found = 200;

	buffer = new_buf();

	if (IS_NULLSTR(argument))
	{
		chprintln(ch, "Find what?");
		return;
	}

	for (obj = object_first; obj != NULL; obj = obj->next)
	{
		if (!can_see_obj(ch, obj) || !is_name(argument, obj->name) ||
			ch->level < obj->level)
			continue;

		found = TRUE;
		number++;

		for (in_obj = obj; in_obj->in_obj != NULL; in_obj = in_obj->in_obj)
			;

		if (in_obj->carried_by != NULL && can_see(ch, in_obj->carried_by)
			&& in_obj->carried_by->in_room != NULL)
			bprintlnf(buffer, "%3d) %s is carried by %s [Room %ld]",
					  number, obj->short_descr, PERS(in_obj->carried_by,
													 ch),
					  in_obj->carried_by->in_room->vnum);
		else if (in_obj->in_room != NULL && can_see_room(ch, in_obj->in_room))
			bprintlnf(buffer, "%3d) %s is in %s [Room %ld]", number,
					  obj->short_descr, in_obj->in_room->name,
					  in_obj->in_room->vnum);
		else
			bprintlnf(buffer, "%3d) %s is somewhere", number, obj->short_descr);

		if (number >= max_found)
			break;
	}

	if (!found)
		chprintln(ch, "Nothing like that in heaven or earth.");
	else
		sendpage(ch, buf_string(buffer));

	free_buf(buffer);
}

CH_CMD(do_mwhere)
{
	BUFFER *buffer;
	CHAR_DATA *victim;
	bool found;
	int count = 0;

	if (IS_NULLSTR(argument))
	{
		DESCRIPTOR_DATA *d;

		/* show characters logged */

		buffer = new_buf();
		for (d = descriptor_first; d != NULL; d = d->next)
		{
			if (d->character != NULL && d->connected == CON_PLAYING &&
				d->character->in_room != NULL
				&& can_see(ch, d->character)
				&& can_see_room(ch, d->character->in_room))
			{
				victim = d->character;
				count++;
				if (d->original != NULL)
					bprintlnf(buffer,
							  "%3d) %s (in the body of %s) is in %s [%ld]",
							  count, d->original->name,
							  victim->short_descr,
							  victim->in_room->name, victim->in_room->vnum);
				else
					bprintlnf(buffer, "%3d) %s is in %s [%ld]",
							  count, victim->name,
							  victim->in_room->name, victim->in_room->vnum);
			}
		}

		sendpage(ch, buf_string(buffer));
		free_buf(buffer);
		return;
	}

	found = FALSE;
	buffer = new_buf();
	for (victim = char_first; victim != NULL; victim = victim->next)
	{
		if (victim->in_room != NULL && is_name(argument, victim->name))
		{
			found = TRUE;
			count++;
			bprintlnf(buffer, "%3d) [%5ld] %-28s [%5ld] %s", count,
					  IS_NPC(victim) ? victim->pIndexData->vnum : 0,
					  IS_NPC(victim) ? victim->short_descr : victim->name,
					  victim->in_room->vnum, victim->in_room->name);
		}
	}

	if (!found)
		act("You didn't find any $T.", ch, NULL, argument, TO_CHAR);
	else
		sendpage(ch, buf_string(buffer));

	free_buf(buffer);

	return;
}

long get_seconds(long value, const char *arg)
{
	if (is_number(arg))
		return value * atol(arg);
	else if (!str_prefix(arg, "seconds"))
		return value * SECOND;
	else if (!str_prefix(arg, "minutes"))
		return value * MINUTE;
	else if (!str_prefix(arg, "hours"))
		return value * HOUR;
	else if (!str_prefix(arg, "days"))
		return value * DAY;
	else
		return value;
}

const char *crs_type_name(crs_t type)
{
	switch (type)
	{
	case CRS_COPYOVER:
		return "Copyover";
	case CRS_REBOOT:
		return "Reboot";
	case CRS_SHUTDOWN:
		return "Shutdown";
	default:
		return "Unknown";
	}
}

PROTOTYPE(void copyover, (void));
PROTOTYPE(void reboot_mud, (void));
PROTOTYPE(void shutdown_mud, (void));

void crs_fun(crs_t type)
{								// Weeeeeeee
	switch (type)
	{
	case CRS_COPYOVER:
		copyover();
		break;
	case CRS_REBOOT:
		reboot_mud();
		break;
	case CRS_SHUTDOWN:
		shutdown_mud();
		break;
	default:
		bug("crs_fun: bad type");
		break;
	}
}

void crs_update(void)
{
	if (crs_info.status == CRS_NONE || crs_info.timer <= 0)
		return;

	--crs_info.timer;

	if (crs_info.timer % PULSE_PER_SECOND != 0)
		return;

	switch (crs_info.timer / PULSE_PER_SECOND)
	{
	case 0:
		crs_fun(crs_info.status);
		break;
	case 1:
	case 2:
	case 3:
	case 30:
	case MINUTE:
	case MINUTE * 3:
	case MINUTE * 5:
	case MINUTE * 10:
	case MINUTE * 15:
	case MINUTE * 20:
	case MINUTE * 30:
		announce(NULL, INFO_ALL, crs_sprintf(TRUE, FALSE));
		break;
	}
}

const char *format_pulse(int time)
{
	static char buf[5][100];
	static int i;
	char temp[100];
	double timer = time / PULSE_PER_SECOND;

	++i;
	i %= 5;

	sprintf(temp, "%%.%sf %s%%s",
			(timer < MINUTE
			 || (int) timer % MINUTE == 0) ? "" : "2",
			timer >= MINUTE ? "minute" : "second");
	sprintf(buf[i], temp, timer >= MINUTE ? timer / MINUTE : timer,
			(timer == MINUTE || timer == 1) ? "" : "s");
	return buf[i];
}

const char *crs_sprintf(bool pTime, bool reason)
{
	char buf[MSL];
	const char *prstr;

	if (crs_info.status == CRS_NONE || (pTime && crs_info.timer < 0))
		return "";

	if (reason)
		prstr = crs_info.reason;
	else
		prstr = "";

	if (pTime)
	{
		sprintf(buf, "%s by %s in %s.%s",
				crs_type_name(crs_info.status),
				!IS_NULLSTR(crs_info.who) ? crs_info.who : "System",
				format_pulse(crs_info.timer), prstr);
	}
	else
	{
		sprintf(buf, "%s by %s.%s%s",
				crs_type_name(crs_info.status),
				!IS_NULLSTR(crs_info.who) ? crs_info.who : "System",
				prstr,
				crs_info.status == CRS_COPYOVER ? " Please wait....." : "");
	}
	return smash_colour(buf);
}

void do_crs(CHAR_DATA * ch, const char *argument, crs_t type)
{
	char arg[MIL], arg2[MIL];
	int value = -1;
	const char *cmd_name = crs_type_name(type);

	argument = one_argument(argument, arg);

	if (IS_NULLSTR(arg))
	{
		chprintlnf(ch, "Usage: %s now [reason]", cmd_name);
		chprintlnf(ch, "Usage: %s <#value> <#mod> [reason]", cmd_name);
		chprintlnf(ch, "Usage: %s cancel [why]", cmd_name);
		chprintlnf(ch, "Usage: %s status", cmd_name);
		return;
	}

	if (!str_cmp(arg, "cancel"))
	{
		crs_info.timer = -1;
		replace_string(crs_info.who, "");
		replace_string(crs_info.reason, "");
		crs_info.status = CRS_NONE;
		announce(ch, INFO_ALL, "$n has cancelled the %s.", cmd_name);
		announce(ch, INFO_ALL | INFO_PRIVATE,
				 "You have cancelled the %s.", cmd_name);
		return;
	}

	if (!str_cmp(arg, "status"))
	{
		if (crs_info.timer == -1 || crs_info.status != type)
			chprintlnf(ch, "Automatic %s is inactive.", cmd_name);
		else
			chprintln(ch, crs_sprintf(TRUE, TRUE));
		return;
	}

	if (!str_cmp(arg, "now"))
	{
		crs_info.status = type;
		replace_string(crs_info.who,
					   (ch->invis_level > 0 ? "an Immortal" : ch->name));
		if (!IS_NULLSTR(argument))
			replace_string(crs_info.reason, FORMATF(" (%s)", argument));
		crs_fun(crs_info.status);
		return;
	}

	if (!str_cmp(arg, "random"))
		value = number_range(60, 360);
	else if (is_number(arg))
		value = atoi(arg);
	else
	{
		chprintln(ch, "Thats not a valid value.");
		return;
	}

	argument = one_argument(argument, arg2);

	if (IS_NULLSTR(arg2) || !is_name(arg2, "seconds minutes hours days"))
	{
		chprintlnf(ch, "Syntax: %s %d seconds/minutes/hours/days.", cmd_name,
				   value);
		return;
	}

	value = get_seconds(value, arg2);
	value *= PULSE_PER_SECOND;
	crs_info.timer = value;

	if (!IS_NULLSTR(argument))
		replace_string(crs_info.reason, FORMATF(" (%s)", argument));

	replace_string(crs_info.who,
				   (ch->invis_level > 0 ? "an Immortal" : ch->name));
	crs_info.status = type;
	announce(NULL, INFO_ALL, crs_sprintf(TRUE, FALSE));
}

CH_CMD(do_reboo)
{
	chprintln(ch, "If you want to REBOOT, spell it out.");
	return;
}

CH_CMD(do_reboot)
{
	do_crs(ch, argument, CRS_REBOOT);
	return;
}

void reboot_mud(void)
{
	DESCRIPTOR_DATA *d, *d_next;
	CHAR_DATA *vch;

	logf(crs_sprintf(FALSE, TRUE));

	for (d = descriptor_first; d != NULL; d = d_next)
	{
		d_next = d->next;
		d_write(d, "\n\r", 2);
		d_write(d, crs_sprintf(FALSE, TRUE), 0);
		d_write(d, "\n\r", 2);
		vch = CH(d);
		if (vch != NULL)
		{
			save_char_obj(vch);
		}
		close_socket(d);
	}
	run_level = RUNLEVEL_SHUTDOWN;
	return;
}

CH_CMD(do_shutdow)
{
	chprintln(ch, "If you want to SHUTDOWN, spell it out.");
	return;
}

CH_CMD(do_shutdown)
{
	do_crs(ch, argument, CRS_SHUTDOWN);
	return;
}

void shutdown_mud()
{
	DESCRIPTOR_DATA *d, *d_next;
	CHAR_DATA *vch;

	append_file(NULL, SHUTDOWN_FILE, crs_sprintf(FALSE, TRUE));
	for (d = descriptor_first; d != NULL; d = d_next)
	{
		d_next = d->next;
		d_write(d, "\n\r", 2);
		d_write(d, crs_sprintf(FALSE, TRUE), 0);
		d_write(d, "\n\r", 2);
		vch = CH(d);
		if (vch != NULL)
		{
			save_char_obj(vch);
		}
		close_socket(d);
	}
	run_level = RUNLEVEL_SHUTDOWN;
	return;
}

CH_CMD(do_protect)
{
	CHAR_DATA *victim;

	if (IS_NULLSTR(argument))
	{
		chprintln(ch, "Protect whom from snooping?");
		return;
	}

	if ((victim = get_char_world(ch, argument)) == NULL)
	{
		chprintln(ch, "You can't find them.");
		return;
	}

	if (IS_SET(victim->comm, COMM_SNOOP_PROOF))
	{
		act_new("$N is no longer snoop-proof.", ch, NULL, victim,
				TO_CHAR, POS_DEAD);
		chprintln(victim, "Your snoop-proofing was just removed.");
		REMOVE_BIT(victim->comm, COMM_SNOOP_PROOF);
	}
	else
	{
		act_new("$N is now snoop-proof.", ch, NULL, victim, TO_CHAR, POS_DEAD);
		chprintln(victim, "You are now immune to snooping.");
		SET_BIT(victim->comm, COMM_SNOOP_PROOF);
	}
}

CH_CMD(do_snoop)
{
	char arg[MAX_INPUT_LENGTH];
	DESCRIPTOR_DATA *d;
	CHAR_DATA *victim;
	char buf[MAX_STRING_LENGTH];

	one_argument(argument, arg);

	if (IS_NULLSTR(arg))
	{
		chprintln(ch, "Snoop whom?");
		return;
	}

	if ((victim = get_char_world(ch, arg)) == NULL)
	{
		chprintln(ch, "They aren't here.");
		return;
	}

	if (victim->desc == NULL)
	{
		chprintln(ch, "No descriptor to snoop.");
		return;
	}

	if (victim == ch)
	{
		chprintln(ch, "Cancelling all snoops.");
		wiznet("$N stops being such a snoop.", ch, NULL, WIZ_SNOOPS,
			   WIZ_SECURE, get_trust(ch));
		for (d = descriptor_first; d != NULL; d = d->next)
		{
			if (d->snoop_by == ch->desc)
				d->snoop_by = NULL;
		}
		return;
	}

	if (victim->desc->snoop_by != NULL)
	{
		chprintln(ch, "Busy already.");
		return;
	}

	if (!is_room_owner(ch, victim->in_room) &&
		ch->in_room != victim->in_room && room_is_private(victim->in_room)
		&& !IS_TRUSTED(ch, IMPLEMENTOR))
	{
		chprintln(ch, "That character is in a private room.");
		return;
	}

	if (get_trust(victim) >= get_trust(ch) ||
		IS_SET(victim->comm, COMM_SNOOP_PROOF))
	{
		chprintln(ch, "You failed.");
		return;
	}

	if (ch->desc != NULL)
	{
		for (d = ch->desc->snoop_by; d != NULL; d = d->snoop_by)
		{
			if (d->character == victim || d->original == victim)
			{
				chprintln(ch, "No snoop loops.");
				return;
			}
		}
	}

	victim->desc->snoop_by = ch->desc;
	sprintf(buf, "$N starts snooping on %s",
			(IS_NPC(ch) ? victim->short_descr : victim->name));
	wiznet(buf, ch, NULL, WIZ_SNOOPS, WIZ_SECURE, get_trust(ch));
	chprintln(ch, "Ok.");
	return;
}

CH_CMD(do_switch)
{
	char arg[MAX_INPUT_LENGTH], buf[MAX_STRING_LENGTH];
	CHAR_DATA *victim;

	one_argument(argument, arg);

	if (IS_NULLSTR(arg))
	{
		chprintln(ch, "Switch into whom?");
		return;
	}

	if (ch->desc == NULL)
		return;

	if (ch->desc->original != NULL)
	{
		chprintln(ch, "You are already switched.");
		return;
	}

	if ((victim = get_char_world(ch, arg)) == NULL)
	{
		chprintln(ch, "They aren't here.");
		return;
	}

	if (victim == ch)
	{
		chprintln(ch, "Ok.");
		return;
	}

	if (!IS_NPC(victim))
	{
		chprintln(ch, "You can only switch into mobiles.");
		return;
	}

	if (!is_room_owner(ch, victim->in_room) &&
		ch->in_room != victim->in_room && room_is_private(victim->in_room)
		&& !IS_TRUSTED(ch, IMPLEMENTOR))
	{
		chprintln(ch, "That character is in a private room.");
		return;
	}

	if (victim->desc != NULL)
	{
		chprintln(ch, "Character in use.");
		return;
	}

	sprintf(buf, "$N switches into %s", victim->short_descr);
	wiznet(buf, ch, NULL, WIZ_SWITCHES, WIZ_SECURE, get_trust(ch));

	ch->desc->character = victim;
	ch->desc->original = ch;
	victim->desc = ch->desc;
	ch->desc = NULL;
	/* change communications to match */
	if (ch->prompt != NULL)
		replace_string(victim->prompt, ch->prompt);
	victim->comm = ch->comm;
	victim->lines = ch->lines;
	victim->columns = ch->columns;
	chprintln(victim, "Ok.");
	return;
}

CH_CMD(do_return)
{
	char buf[MAX_STRING_LENGTH];

	if (ch->desc == NULL)
		return;

	if (ch->desc->original == NULL)
	{
		chprintln(ch, "You aren't switched.");
		return;
	}

	chprintln(ch,
			  "You return to your original body. Type replay to see any missed tells.");
	if (ch->prompt != NULL)
	{
		free_string(ch->prompt);
		ch->prompt = NULL;
	}

	sprintf(buf, "$N returns from %s.", ch->short_descr);
	wiznet(buf, ch->desc->original, 0, WIZ_SWITCHES, WIZ_SECURE, get_trust(ch));
	ch->desc->character = ch->desc->original;
	ch->desc->original = NULL;
	ch->desc->character->desc = ch->desc;
	ch->desc = NULL;
	return;
}

/* trust levels for load and clone */
bool obj_check(CHAR_DATA * ch, OBJ_DATA * obj)
{
	if (IS_TRUSTED(ch, GOD) ||
		(IS_TRUSTED(ch, IMMORTAL) && obj->level <= 20 &&
		 obj->cost <= 1000) || (IS_TRUSTED(ch, DEMI) &&
								obj->level <= 10 && obj->cost <= 500) ||
		(IS_TRUSTED(ch, ANGEL) && obj->level <= 5 && obj->cost <= 250)
		|| (IS_TRUSTED(ch, AVATAR) && obj->level == 0 && obj->cost <= 100))
		return TRUE;
	else
		return FALSE;
}

/* for clone, to insure that cloning goes many levels deep */
void recursive_clone(CHAR_DATA * ch, OBJ_DATA * obj, OBJ_DATA * clone)
{
	OBJ_DATA *c_obj, *t_obj;

	for (c_obj = obj->first_content; c_obj != NULL; c_obj = c_obj->next_content)
	{
		if (obj_check(ch, c_obj))
		{
			t_obj = create_object(c_obj->pIndexData, 0);
			clone_object(c_obj, t_obj);
			obj_to_obj(t_obj, clone);
			recursive_clone(ch, c_obj, t_obj);
		}
	}
}

/* command that is similar to load */
CH_CMD(do_clone)
{
	char arg[MAX_INPUT_LENGTH];
	const char *rest;
	CHAR_DATA *mob;
	OBJ_DATA *obj;

	rest = one_argument(argument, arg);

	if (IS_NULLSTR(arg))
	{
		chprintln(ch, "Clone what?");
		return;
	}

	if (!str_prefix(arg, "object"))
	{
		mob = NULL;
		obj = get_obj_here(ch, NULL, rest);
		if (obj == NULL)
		{
			chprintln(ch, "You don't see that here.");
			return;
		}
	}
	else if (!str_prefix(arg, "mobile") || !str_prefix(arg, "character"))
	{
		obj = NULL;
		mob = get_char_room(ch, NULL, rest);
		if (mob == NULL)
		{
			chprintln(ch, "You don't see that here.");
			return;
		}
	}
	else						/* find both */
	{
		mob = get_char_room(ch, NULL, argument);
		obj = get_obj_here(ch, NULL, argument);
		if (mob == NULL && obj == NULL)
		{
			chprintln(ch, "You don't see that here.");
			return;
		}
	}

	/* clone an object */
	if (obj != NULL)
	{
		OBJ_DATA *clone;

		if (!obj_check(ch, obj))
		{
			chprintln(ch, "Your powers are not great enough for such a task.");
			return;
		}

		clone = create_object(obj->pIndexData, 0);
		clone_object(obj, clone);
		if (obj->carried_by != NULL)
			obj_to_char(clone, ch);
		else
			obj_to_room(clone, ch->in_room);
		recursive_clone(ch, obj, clone);

		act("$n has created $p.", ch, clone, NULL, TO_ROOM);
		act("You clone $p.", ch, clone, NULL, TO_CHAR);
		wiznet("$N clones $p.", ch, clone, WIZ_LOAD, WIZ_SECURE, get_trust(ch));
		return;
	}
	else if (mob != NULL)
	{
		CHAR_DATA *clone;
		OBJ_DATA *new_pobj;
		char buf[MAX_STRING_LENGTH];

		if (!IS_NPC(mob))
		{
			chprintln(ch, "You can only clone mobiles.");
			return;
		}

		if ((mob->level > 20 && !IS_TRUSTED(ch, GOD)) ||
			(mob->level > 10 && !IS_TRUSTED(ch, IMMORTAL)) ||
			(mob->level > 5 && !IS_TRUSTED(ch, DEMI)) ||
			(mob->level > 0 && !IS_TRUSTED(ch, ANGEL)) ||
			!IS_TRUSTED(ch, AVATAR))
		{
			chprintln(ch, "Your powers are not great enough for such a task.");
			return;
		}

		clone = create_mobile(mob->pIndexData);
		clone_mobile(mob, clone);

		for (obj = mob->first_carrying; obj != NULL; obj = obj->next_content)
		{
			if (obj_check(ch, obj))
			{
				new_pobj = create_object(obj->pIndexData, 0);
				clone_object(obj, new_pobj);
				recursive_clone(ch, obj, new_pobj);
				obj_to_char(new_pobj, clone);
				new_pobj->wear_loc = obj->wear_loc;
			}
		}
		char_to_room(clone, ch->in_room);
		act("$n has created $N.", ch, NULL, clone, TO_ROOM);
		act("You clone $N.", ch, NULL, clone, TO_CHAR);
		sprintf(buf, "$N clones %s.", clone->short_descr);
		wiznet(buf, ch, NULL, WIZ_LOAD, WIZ_SECURE, get_trust(ch));
		return;
	}
}

/* RT to replace the two load commands */

CH_CMD(do_load)
{
	char arg[MAX_INPUT_LENGTH];

	argument = one_argument(argument, arg);

	if (IS_NULLSTR(arg))
	{
		chprintln(ch, "Syntax:");
		chprintln(ch, "  load mob <vnum>");
		chprintln(ch, "  load obj <vnum> <level>");
		return;
	}

	if (!str_cmp(arg, "mob") || !str_cmp(arg, "char"))
	{
		do_function(ch, &do_mload, argument);
		return;
	}

	if (!str_cmp(arg, "obj"))
	{
		do_function(ch, &do_oload, argument);
		return;
	}
	/* echo syntax */
	do_function(ch, &do_load, "");
}

CH_CMD(do_mload)
{
	char arg[MAX_INPUT_LENGTH];
	MOB_INDEX_DATA *pMobIndex;
	CHAR_DATA *victim;
	char buf[MAX_STRING_LENGTH];

	one_argument(argument, arg);

	if (IS_NULLSTR(arg) || !is_number(arg))
	{
		chprintln(ch, "Syntax: load mob <vnum>.");
		return;
	}

	if ((pMobIndex = get_mob_index(atol(arg))) == NULL)
	{
		chprintln(ch, "No mob has that vnum.");
		return;
	}

	victim = create_mobile(pMobIndex);
	char_to_room(victim, ch->in_room);
	act("$n has created $N!", ch, NULL, victim, TO_ROOM);
	sprintf(buf, "$N loads %s.", victim->short_descr);
	wiznet(buf, ch, NULL, WIZ_LOAD, WIZ_SECURE, get_trust(ch));
	chprintln(ch, "Ok.");
	return;
}

CH_CMD(do_oload)
{
	char arg1[MAX_INPUT_LENGTH], arg2[MAX_INPUT_LENGTH];
	OBJ_INDEX_DATA *pObjIndex;
	OBJ_DATA *obj;
	int level;

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

	if (IS_NULLSTR(arg1) || !is_number(arg1))
	{
		chprintln(ch, "Syntax: load obj <vnum> <level>.");
		return;
	}

	level = get_trust(ch);		/* default */

	if (!IS_NULLSTR(arg2))		/* load with a level */
	{
		if (!is_number(arg2))
		{
			chprintln(ch, "Syntax: oload <vnum> <level>.");
			return;
		}
		level = atoi(arg2);
		if (level < 0 || level > get_trust(ch))
		{
			chprintln(ch, "Level must be be between 0 and your level.");
			return;
		}
	}

	if ((pObjIndex = get_obj_index(atol(arg1))) == NULL)
	{
		chprintln(ch, "No object has that vnum.");
		return;
	}

	obj = create_object(pObjIndex, level);
	if (CAN_WEAR(obj, ITEM_TAKE))
		obj_to_char(obj, ch);
	else
		obj_to_room(obj, ch->in_room);
	act("$n has created $p!", ch, obj, NULL, TO_ROOM);
	wiznet("$N loads $p.", ch, obj, WIZ_LOAD, WIZ_SECURE, get_trust(ch));
	chprintln(ch, "Ok.");
	return;
}

CH_CMD(do_purge)
{
	char arg[MAX_INPUT_LENGTH];
	CHAR_DATA *victim;
	OBJ_DATA *obj;
	DESCRIPTOR_DATA *d;

	one_argument(argument, arg);

	if (IS_NULLSTR(arg))
	{
		/* 'purge' */
		CHAR_DATA *vnext;
		OBJ_DATA *obj_next;

		for (victim = ch->in_room->first_person; victim != NULL; victim = vnext)
		{
			vnext = victim->next_in_room;
			if (IS_NPC(victim) && !IS_SET(victim->act, ACT_NOPURGE) && victim != ch	/* safety precaution */
				)
				extract_char(victim, TRUE);
		}

		for (obj = ch->in_room->first_content; obj != NULL; obj = obj_next)
		{
			obj_next = obj->next_content;
			if (!IS_OBJ_STAT(obj, ITEM_NOPURGE))
				extract_obj(obj);
		}

		act("$n purges the room!", ch, NULL, NULL, TO_ROOM);
		chprintln(ch, "Ok.");
		return;
	}

	if ((victim = get_char_world(ch, arg)) == NULL)
	{
		chprintln(ch, "They aren't here.");
		return;
	}

	if (!IS_NPC(victim))
	{

		if (ch == victim)
		{
			chprintln(ch, "Ho ho ho.");
			return;
		}

		if (get_trust(ch) <= get_trust(victim))
		{
			chprintln(ch, "Maybe that wasn't a good idea...");
			chprintlnf(victim, "%s tried to purge you!", ch->name);
			return;
		}

		act("$n disintegrates $N.", ch, 0, victim, TO_NOTVICT);

		if (victim->level > 1)
			save_char_obj(victim);
		d = victim->desc;
		extract_char(victim, TRUE);
		if (d != NULL)
			close_socket(d);

		return;
	}

	act("$n purges $N.", ch, NULL, victim, TO_NOTVICT);
	extract_char(victim, TRUE);
	return;
}

CH_CMD(do_advance)
{
	char arg1[MAX_INPUT_LENGTH];
	char arg2[MAX_INPUT_LENGTH];
	CHAR_DATA *victim;
	int level;
	int iLevel;

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

	if (IS_NULLSTR(arg1) || IS_NULLSTR(arg2) || !is_number(arg2))
	{
		chprintln(ch, "Syntax: advance <char> <level>.");
		return;
	}

	if ((victim = get_char_world(ch, arg1)) == NULL)
	{
		chprintln(ch, "That player is not here.");
		return;
	}

	if (IS_NPC(victim))
	{
		chprintln(ch, "Not on NPC's.");
		return;
	}

	if ((level = atoi(arg2)) < 1 || level > MAX_LEVEL)
	{
		chprintlnf(ch, "Level must be 1 to %d.", MAX_LEVEL);
		return;
	}

	if (level > get_trust(ch))
	{
		chprintln(ch, "Limited to your trust level.");
		return;
	}

	/*
	 * Lower level:
	 *   Reset to level 1.
	 *   Then raise again.
	 *   Currently, an imp can lower another imp.
	 *   -- Swiftest
	 */
	if (level <= victim->level)
	{
		int temp_prac;

		chprintln(ch, "Lowering a player's level!");
		chprintln(victim, "**** OOOOHHHHHHHHHH  NNNNOOOO ****");
		temp_prac = victim->practice;
		victim->level = 1;
		victim->exp = exp_per_level(victim, victim->pcdata->points);
		victim->max_hit = 10;
		victim->max_mana = 100;
		victim->max_move = 100;
		victim->practice = 0;
		victim->hit = victim->max_hit;
		victim->mana = victim->max_mana;
		victim->move = victim->max_move;
		advance_level(victim, TRUE);
		victim->practice = temp_prac;
	}
	else
	{
		chprintln(ch, "Raising a player's level!");
		chprintln(victim, "**** OOOOHHHHHHHHHH  YYYYEEEESSS ****");
	}

	for (iLevel = victim->level; iLevel < level; iLevel++)
	{
		victim->level += 1;
		advance_level(victim, TRUE);
	}
	chprintlnf(victim, "You are now level %d.", victim->level);
	victim->exp =
		exp_per_level(victim, victim->pcdata->points) * UMAX(1, victim->level);
	victim->trust = 0;
	save_char_obj(victim);
	return;
}

CH_CMD(do_trust)
{
	char arg1[MAX_INPUT_LENGTH];
	char arg2[MAX_INPUT_LENGTH];
	CHAR_DATA *victim;
	int level;

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

	if (IS_NULLSTR(arg1) || IS_NULLSTR(arg2) || !is_number(arg2))
	{
		chprintln(ch, "Syntax: trust <char> <level>.");
		return;
	}

	if ((victim = get_char_world(ch, arg1)) == NULL)
	{
		chprintln(ch, "That player is not here.");
		return;
	}

	if ((level = atoi(arg2)) < 0 || level > MAX_LEVEL)
	{
		chprintlnf(ch, "Level must be 0 (reset) or 1 to %d.", MAX_LEVEL);
		return;
	}

	if (level > get_trust(ch))
	{
		chprintln(ch, "Limited to your trust.");
		return;
	}

	victim->trust = level;
	return;
}

CH_CMD(do_restore)
{
	char arg[MAX_INPUT_LENGTH], buf[MAX_STRING_LENGTH];
	CHAR_DATA *victim;
	CHAR_DATA *vch;
	DESCRIPTOR_DATA *d;

	one_argument(argument, arg);
	if (IS_NULLSTR(arg) || !str_cmp(arg, "room"))
	{
		/* cure room */

		for (vch = ch->in_room->first_person; vch != NULL;
			 vch = vch->next_in_room)
		{
			affect_strip(vch, gsn_plague);
			affect_strip(vch, gsn_poison);
			affect_strip(vch, gsn_blindness);
			affect_strip(vch, gsn_sleep);
			affect_strip(vch, gsn_curse);

			vch->hit = vch->max_hit;
			vch->mana = vch->max_mana;
			vch->move = vch->max_move;
			update_pos(vch);
			act("$n has restored you.", ch, NULL, vch, TO_VICT);
		}

		sprintf(buf, "$N restored room %ld.", ch->in_room->vnum);
		wiznet(buf, ch, NULL, WIZ_RESTORE, WIZ_SECURE, get_trust(ch));

		chprintln(ch, "Room restored.");
		return;

	}

	if (get_trust(ch) >= MAX_LEVEL - 1 && !str_cmp(arg, "all"))
	{
		/* cure all */

		for (d = descriptor_first; d != NULL; d = d->next)
		{
			victim = d->character;

			if (victim == NULL || IS_NPC(victim))
				continue;

			affect_strip(victim, gsn_plague);
			affect_strip(victim, gsn_poison);
			affect_strip(victim, gsn_blindness);
			affect_strip(victim, gsn_sleep);
			affect_strip(victim, gsn_curse);

			victim->hit = victim->max_hit;
			victim->mana = victim->max_mana;
			victim->move = victim->max_move;
			update_pos(victim);
			if (victim->in_room != NULL)
				act("$n has restored you.", ch, NULL, victim, TO_VICT);
		}
		chprintln(ch, "All active players restored.");
		return;
	}

	if ((victim = get_char_world(ch, arg)) == NULL)
	{
		chprintln(ch, "They aren't here.");
		return;
	}

	affect_strip(victim, gsn_plague);
	affect_strip(victim, gsn_poison);
	affect_strip(victim, gsn_blindness);
	affect_strip(victim, gsn_sleep);
	affect_strip(victim, gsn_curse);
	victim->hit = victim->max_hit;
	victim->mana = victim->max_mana;
	victim->move = victim->max_move;
	update_pos(victim);
	act("$n has restored you.", ch, NULL, victim, TO_VICT);
	sprintf(buf, "$N restored %s",
			IS_NPC(victim) ? victim->short_descr : victim->name);
	wiznet(buf, ch, NULL, WIZ_RESTORE, WIZ_SECURE, get_trust(ch));
	chprintln(ch, "Ok.");
	return;
}

CH_CMD(do_freeze)
{
	char arg[MAX_INPUT_LENGTH], buf[MAX_STRING_LENGTH];
	CHAR_DATA *victim;

	one_argument(argument, arg);

	if (IS_NULLSTR(arg))
	{
		chprintln(ch, "Freeze whom?");
		return;
	}

	if ((victim = get_char_world(ch, arg)) == NULL)
	{
		chprintln(ch, "They aren't here.");
		return;
	}

	if (IS_NPC(victim))
	{
		chprintln(ch, "Not on NPC's.");
		return;
	}

	if (get_trust(victim) >= get_trust(ch))
	{
		chprintln(ch, "You failed.");
		return;
	}

	if (IS_SET(victim->act, PLR_FREEZE))
	{
		REMOVE_BIT(victim->act, PLR_FREEZE);
		chprintln(victim, "You can play again.");
		chprintln(ch, "FREEZE removed.");
		sprintf(buf, "$N thaws %s.", victim->name);
		wiznet(buf, ch, NULL, WIZ_PENALTIES, WIZ_SECURE, 0);
	}
	else
	{
		SET_BIT(victim->act, PLR_FREEZE);
		chprintln(victim, "You can't do ANYthing!");
		chprintln(ch, "FREEZE set.");
		sprintf(buf, "$N puts %s in the deep freeze.", victim->name);
		wiznet(buf, ch, NULL, WIZ_PENALTIES, WIZ_SECURE, 0);
	}

	save_char_obj(victim);

	return;
}

CH_CMD(do_log)
{
	char arg[MAX_INPUT_LENGTH];
	CHAR_DATA *victim;

	one_argument(argument, arg);

	if (IS_NULLSTR(arg))
	{
		chprintln(ch, "Log whom?");
		return;
	}

	if (!str_cmp(arg, "all"))
	{
		if (IS_SET(mud_info.mud_flags, MUD_LOGALL))
		{
			REMOVE_BIT(mud_info.mud_flags, MUD_LOGALL);
			chprintln(ch, "Log ALL off.");
		}
		else
		{
			SET_BIT(mud_info.mud_flags, MUD_LOGALL);
			chprintln(ch, "Log ALL on.");
		}
		return;
	}

	if ((victim = get_char_world(ch, arg)) == NULL)
	{
		chprintln(ch, "They aren't here.");
		return;
	}

	if (IS_NPC(victim))
	{
		chprintln(ch, "Not on NPC's.");
		return;
	}

	/*
	 * No level check, gods can log anyone.
	 */
	if (IS_SET(victim->act, PLR_LOG))
	{
		REMOVE_BIT(victim->act, PLR_LOG);
		chprintln(ch, "LOG removed.");
	}
	else
	{
		SET_BIT(victim->act, PLR_LOG);
		chprintln(ch, "LOG set.");
	}

	return;
}

CH_CMD(do_noemote)
{
	char arg[MAX_INPUT_LENGTH], buf[MAX_STRING_LENGTH];
	CHAR_DATA *victim;

	one_argument(argument, arg);

	if (IS_NULLSTR(arg))
	{
		chprintln(ch, "Noemote whom?");
		return;
	}

	if ((victim = get_char_world(ch, arg)) == NULL)
	{
		chprintln(ch, "They aren't here.");
		return;
	}

	if (get_trust(victim) >= get_trust(ch))
	{
		chprintln(ch, "You failed.");
		return;
	}

	if (IS_SET(victim->comm, COMM_NOEMOTE))
	{
		REMOVE_BIT(victim->comm, COMM_NOEMOTE);
		chprintln(victim, "You can emote again.");
		chprintln(ch, "NOEMOTE removed.");
		sprintf(buf, "$N restores emotes to %s.", victim->name);
		wiznet(buf, ch, NULL, WIZ_PENALTIES, WIZ_SECURE, 0);
	}
	else
	{
		SET_BIT(victim->comm, COMM_NOEMOTE);
		chprintln(victim, "You can't emote!");
		chprintln(ch, "NOEMOTE set.");
		sprintf(buf, "$N revokes %s's emotes.", victim->name);
		wiznet(buf, ch, NULL, WIZ_PENALTIES, WIZ_SECURE, 0);
	}

	return;
}

CH_CMD(do_noshout)
{
	char arg[MAX_INPUT_LENGTH], buf[MAX_STRING_LENGTH];
	CHAR_DATA *victim;

	one_argument(argument, arg);

	if (IS_NULLSTR(arg))
	{
		chprintln(ch, "Noshout whom?");
		return;
	}

	if ((victim = get_char_world(ch, arg)) == NULL)
	{
		chprintln(ch, "They aren't here.");
		return;
	}

	if (IS_NPC(victim))
	{
		chprintln(ch, "Not on NPC's.");
		return;
	}

	if (get_trust(victim) >= get_trust(ch))
	{
		chprintln(ch, "You failed.");
		return;
	}

	if (IS_SET(victim->comm, COMM_NOSHOUT))
	{
		REMOVE_BIT(victim->comm, COMM_NOSHOUT);
		chprintln(victim, "You can shout again.");
		chprintln(ch, "NOSHOUT removed.");
		sprintf(buf, "$N restores shouts to %s.", victim->name);
		wiznet(buf, ch, NULL, WIZ_PENALTIES, WIZ_SECURE, 0);
	}
	else
	{
		SET_BIT(victim->comm, COMM_NOSHOUT);
		chprintln(victim, "You can't shout!");
		chprintln(ch, "NOSHOUT set.");
		sprintf(buf, "$N revokes %s's shouts.", victim->name);
		wiznet(buf, ch, NULL, WIZ_PENALTIES, WIZ_SECURE, 0);
	}

	return;
}

CH_CMD(do_notell)
{
	char arg[MAX_INPUT_LENGTH], buf[MAX_STRING_LENGTH];
	CHAR_DATA *victim;

	one_argument(argument, arg);

	if (IS_NULLSTR(arg))
	{
		chprintln(ch, "Notell whom?");
		return;
	}

	if ((victim = get_char_world(ch, arg)) == NULL)
	{
		chprintln(ch, "They aren't here.");
		return;
	}

	if (get_trust(victim) >= get_trust(ch))
	{
		chprintln(ch, "You failed.");
		return;
	}

	if (IS_SET(victim->comm, COMM_NOTELL))
	{
		REMOVE_BIT(victim->comm, COMM_NOTELL);
		chprintln(victim, "You can tell again.");
		chprintln(ch, "NOTELL removed.");
		sprintf(buf, "$N restores tells to %s.", victim->name);
		wiznet(buf, ch, NULL, WIZ_PENALTIES, WIZ_SECURE, 0);
	}
	else
	{
		SET_BIT(victim->comm, COMM_NOTELL);
		chprintln(victim, "You can't tell!");
		chprintln(ch, "NOTELL set.");
		sprintf(buf, "$N revokes %s's tells.", victim->name);
		wiznet(buf, ch, NULL, WIZ_PENALTIES, WIZ_SECURE, 0);
	}

	return;
}

CH_CMD(do_peace)
{
	CHAR_DATA *rch;

	for (rch = ch->in_room->first_person; rch != NULL; rch = rch->next_in_room)
	{
		if (rch->fighting != NULL)
			stop_fighting(rch, TRUE);
		if (IS_NPC(rch) && IS_SET(rch->act, ACT_AGGRESSIVE))
			REMOVE_BIT(rch->act, ACT_AGGRESSIVE);
	}

	chprintln(ch, "Ok.");
	return;
}

CH_CMD(do_wizlock)
{
	if (!IS_SET(mud_info.mud_flags, MUD_WIZLOCK))
	{
		wiznet("$N has wizlocked the game.", ch, NULL, 0, 0, 0);
		chprintln(ch, "Game wizlocked.");
		SET_BIT(mud_info.mud_flags, MUD_WIZLOCK);
	}
	else
	{
		wiznet("$N removes wizlock.", ch, NULL, 0, 0, 0);
		chprintln(ch, "Game un-wizlocked.");
		REMOVE_BIT(mud_info.mud_flags, MUD_WIZLOCK);
	}

	return;
}

/* RT anti-newbie code */

CH_CMD(do_newlock)
{
	if (!IS_SET(mud_info.mud_flags, MUD_NEWLOCK))
	{
		wiznet("$N locks out new characters.", ch, NULL, 0, 0, 0);
		chprintln(ch, "New characters have been locked out.");
		SET_BIT(mud_info.mud_flags, MUD_NEWLOCK);
	}
	else
	{
		wiznet("$N allows new characters back in.", ch, NULL, 0, 0, 0);
		chprintln(ch, "Newlock removed.");
		REMOVE_BIT(mud_info.mud_flags, MUD_NEWLOCK);
	}

	return;
}

CH_CMD(do_slookup)
{
	char arg[MAX_INPUT_LENGTH];
	int sn;

	one_argument(argument, arg);
	if (IS_NULLSTR(arg))
	{
		chprintln(ch, "Lookup which skill or spell?");
		return;
	}

	if (!str_cmp(arg, "all"))
	{
		for (sn = 0; sn < maxSkill; sn++)
		{
			if (skill_table[sn].name == NULL)
				break;
			chprintlnf(ch, "Sn: %3d  Skill/spell: '%s'",
					   sn, skill_table[sn].name);
		}
	}
	else
	{
		if ((sn = skill_lookup(arg)) < 0)
		{
			chprintln(ch, "No such skill or spell.");
			return;
		}

		chprintlnf(ch, "Sn: %3d  Skill/spell: '%s'", sn, skill_table[sn].name);
	}

	return;
}

CH_CMD(do_sset)
{
	char arg1[MAX_INPUT_LENGTH];
	char arg2[MAX_INPUT_LENGTH];
	char arg3[MAX_INPUT_LENGTH];
	CHAR_DATA *victim;
	int value;
	int sn;
	bool fAll;

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

	if (IS_NULLSTR(arg1) || IS_NULLSTR(arg2) || IS_NULLSTR(arg3))
	{
		chprintln(ch, "Syntax:");
		chprintln(ch, "  set skill <name> <spell or skill> <value>");
		chprintln(ch, "  set skill <name> all <value>");
		chprintln(ch, "   (use the name of the skill, not the number)");
		return;
	}

	if ((victim = get_char_world(ch, arg1)) == NULL)
	{
		chprintln(ch, "They aren't here.");
		return;
	}

	if (IS_NPC(victim))
	{
		chprintln(ch, "Not on NPC's.");
		return;
	}

	fAll = !str_cmp(arg2, "all");
	sn = 0;
	if (!fAll && (sn = skill_lookup(arg2)) < 0)
	{
		chprintln(ch, "No such skill or spell.");
		return;
	}

	/*
	 * Snarf the value.
	 */
	if (!is_number(arg3))
	{
		chprintln(ch, "Value must be numeric.");
		return;
	}

	value = atoi(arg3);
	if (value < 0 || value > 100)
	{
		chprintln(ch, "Value range is 0 to 100.");
		return;
	}

	if (fAll)
	{
		for (sn = 0; sn < maxSkill; sn++)
		{
			if (skill_table[sn].name != NULL)
				victim->pcdata->learned[sn] = value;
		}
	}
	else
	{
		victim->pcdata->learned[sn] = value;
	}

	return;
}

CH_CMD(do_sockets)
{
	char buf[2 * MAX_STRING_LENGTH];
	char buf2[MAX_STRING_LENGTH];
	char arg[MAX_INPUT_LENGTH];
	DESCRIPTOR_DATA *d;
	int count;

	count = 0;
	buf[0] = '\0';

	one_argument(argument, arg);
	for (d = descriptor_first; d != NULL; d = d->next)
	{
		if (d->character != NULL && can_see(ch, d->character) &&
			(IS_NULLSTR(arg) || is_name(arg, d->character->name) ||
			 (d->original && is_name(arg, d->original->name))))
		{
			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);
		}
	}
	if (count == 0)
	{
		chprintln(ch, "No one by that name is connected.");
		return;
	}

	sprintf(buf2, "%d user%s\n\r", count, count == 1 ? "" : "s");
	strcat(buf, buf2);
	sendpage(ch, buf);
	return;
}

/*
 * Thanks to Grodyn for pointing out bugs in this function.
 */
CH_CMD(do_force)
{
	char buf[MAX_STRING_LENGTH];
	char arg[MAX_INPUT_LENGTH];
	char arg2[MAX_INPUT_LENGTH];

	argument = one_argument(argument, arg);

	if (IS_NULLSTR(arg) || IS_NULLSTR(argument))
	{
		chprintln(ch, "Force whom to do what?");
		return;
	}

	one_argument(argument, arg2);

	if (!str_cmp(arg2, "delete") || !str_prefix(arg2, "mob"))
	{
		chprintln(ch, "That will NOT be done.");
		return;
	}

	sprintf(buf, "$n forces you to '%s'.", argument);

	if (!str_cmp(arg, "all"))
	{
		CHAR_DATA *vch;
		CHAR_DATA *vch_next;

		if (get_trust(ch) < MAX_LEVEL - 3)
		{
			chprintln(ch, "Not at your level!");
			return;
		}

		for (vch = char_first; vch != NULL; vch = vch_next)
		{
			vch_next = vch->next;

			if (!IS_NPC(vch) && get_trust(vch) < get_trust(ch))
			{
				act(buf, ch, NULL, vch, TO_VICT);
				interpret(vch, argument);
			}
		}
	}
	else if (!str_cmp(arg, "players"))
	{
		CHAR_DATA *vch;
		CHAR_DATA *vch_next;

		if (get_trust(ch) < MAX_LEVEL - 2)
		{
			chprintln(ch, "Not at your level!");
			return;
		}

		for (vch = char_first; vch != NULL; vch = vch_next)
		{
			vch_next = vch->next;

			if (!IS_NPC(vch) && get_trust(vch) < get_trust(ch) &&
				vch->level < MAX_MORTAL_LEVEL)
			{
				act(buf, ch, NULL, vch, TO_VICT);
				interpret(vch, argument);
			}
		}
	}
	else if (!str_cmp(arg, "gods"))
	{
		CHAR_DATA *vch;
		CHAR_DATA *vch_next;

		if (get_trust(ch) < MAX_LEVEL - 2)
		{
			chprintln(ch, "Not at your level!");
			return;
		}

		for (vch = char_first; vch != NULL; vch = vch_next)
		{
			vch_next = vch->next;

			if (!IS_NPC(vch) && get_trust(vch) < get_trust(ch) &&
				vch->level >= MAX_MORTAL_LEVEL)
			{
				act(buf, ch, NULL, vch, TO_VICT);
				interpret(vch, argument);
			}
		}
	}
	else
	{
		CHAR_DATA *victim;

		if ((victim = get_char_world(ch, arg)) == NULL)
		{
			chprintln(ch, "They aren't here.");
			return;
		}

		if (victim == ch)
		{
			chprintln(ch, "Aye aye, right away!");
			return;
		}

		if (!is_room_owner(ch, victim->in_room) &&
			ch->in_room != victim->in_room &&
			room_is_private(victim->in_room) && !IS_TRUSTED(ch, IMPLEMENTOR))
		{
			chprintln(ch, "That character is in a private room.");
			return;
		}

		if (get_trust(victim) >= get_trust(ch))
		{
			chprintln(ch, "Do it yourself!");
			return;
		}

		if (!IS_NPC(victim) && get_trust(ch) < MAX_LEVEL - 3)
		{
			chprintln(ch, "Not at your level!");
			return;
		}

		act(buf, ch, NULL, victim, TO_VICT);
		interpret(victim, argument);
	}

	chprintln(ch, "Ok.");
	return;
}

/*
 * New routines by Dionysos.
 */
CH_CMD(do_invis)
{
	int level;
	char arg[MAX_STRING_LENGTH];

	/* RT code for taking a level argument */
	one_argument(argument, arg);

	if (IS_NULLSTR(arg))
		/* take the default path */

		if (ch->invis_level)
		{
			ch->invis_level = 0;
			act("$n slowly fades into existence.", ch, NULL, NULL, TO_ROOM);
			chprintln(ch, "You slowly fade back into existence.");
		}
		else
		{
			ch->invis_level = get_trust(ch);
			act("$n slowly fades into thin air.", ch, NULL, NULL, TO_ROOM);
			chprintln(ch, "You slowly vanish into thin air.");
		}
	else
		/* do the level thing */
	{
		level = atoi(arg);
		if (level < 2 || level > get_trust(ch))
		{
			chprintln(ch, "Invis level must be between 2 and your level.");
			return;
		}
		else
		{
			ch->reply = NULL;
			ch->invis_level = level;
			act("$n slowly fades into thin air.", ch, NULL, NULL, TO_ROOM);
			chprintln(ch, "You slowly vanish into thin air.");
		}
	}

	return;
}

CH_CMD(do_incognito)
{
	int level;
	char arg[MAX_STRING_LENGTH];

	/* RT code for taking a level argument */
	one_argument(argument, arg);

	if (IS_NULLSTR(arg))
		/* take the default path */

		if (ch->incog_level)
		{
			ch->incog_level = 0;
			act("$n is no longer cloaked.", ch, NULL, NULL, TO_ROOM);
			chprintln(ch, "You are no longer cloaked.");
		}
		else
		{
			ch->incog_level = get_trust(ch);
			act("$n cloaks $s presence.", ch, NULL, NULL, TO_ROOM);
			chprintln(ch, "You cloak your presence.");
		}
	else
		/* do the level thing */
	{
		level = atoi(arg);
		if (level < 2 || level > get_trust(ch))
		{
			chprintln(ch, "Incog level must be between 2 and your level.");
			return;
		}
		else
		{
			ch->reply = NULL;
			ch->incog_level = level;
			act("$n cloaks $s presence.", ch, NULL, NULL, TO_ROOM);
			chprintln(ch, "You cloak your presence.");
		}
	}

	return;
}

CH_CMD(do_holylight)
{
	if (IS_NPC(ch))
		return;

	if (IS_SET(ch->act, PLR_HOLYLIGHT))
	{
		REMOVE_BIT(ch->act, PLR_HOLYLIGHT);
		chprintln(ch, "Holy light mode off.");
	}
	else
	{
		SET_BIT(ch->act, PLR_HOLYLIGHT);
		chprintln(ch, "Holy light mode on.");
	}

	return;
}

/* prefix command: it will put the string typed on each line typed */

CH_CMD(do_prefi)
{
	chprintln(ch, "You cannot abbreviate the prefix command.");
	return;
}

CH_CMD(do_prefix)
{
	char buf[MAX_INPUT_LENGTH];

	if (IS_NULLSTR(argument))
	{
		if (IS_NULLSTR(ch->prefix))
		{
			chprintln(ch, "You have no prefix to clear.");
			return;
		}

		chprintln(ch, "Prefix removed.");
		replace_string(ch->prefix, "");
		return;
	}

	if (!IS_NULLSTR(ch->prefix))
	{
		sprintf(buf, "Prefix changed to %s.\r\n", argument);
		replace_string(ch->prefix, argument);
	}
	else
	{
		sprintf(buf, "Prefix set to %s.\r\n", argument);
		replace_string(ch->prefix, argument);
	}
}

/*  Copyover - Original idea: Fusion of MUD++
 *  Adapted to Diku by Erwin S. Andreasen, <erwin@andreasen.org>
 *  http://www.andreasen.org
 *  Changed into a ROM patch after seeing the 100th request for it :)
 */
 /* Updated by Markanth 08/06/2003. */

CH_CMD(do_copyove)
{
	chprintln(ch, "If you want to COPYOVER, spell it out.");
	return;
}

CH_CMD(do_copyover)
{
#if defined(NO_COPYOVER)
	chprintln(ch, "Copyover is disabled.");
#else
	do_crs(ch, argument, CRS_COPYOVER);
#endif
	return;
}

void copyover(void)
{
#if !defined(NO_COPYOVER)
	WRITE_DATA *fp;
	DESCRIPTOR_DATA *d, *d_next;
	char buf[100], buf2[100];
	extern bool verbose_log;

	fp = open_write(COPYOVER_FILE);

	if (!fp)
	{
		logf("Could not write to copyover file: %s", COPYOVER_FILE);
		log_error("do_copyover:file open");
		return;
	}

	crs_info.status = CRS_COPYOVER;

	/* For each playing descriptor, save its state */
	for (d = descriptor_first; d; d = d_next)
	{
		CHAR_DATA *och = CH(d);
		d_next = d->next;		/* We delete from the list , so need to save this */

#if !defined(NO_MCCP)
		compressEnd(d, d->mccp_version);
#endif

		if (!och || d->connected > CON_PLAYING)	/* drop those logging on */
		{
			d_write(d,
					"\n\rSorry, we are rebooting. Come back in a few minutes.\n\r",
					0);
			close_socket(d);	/* throw'em out */
		}
		else
		{
			fprintf(fp->stream, "%d %s\n", d->descriptor, och->name);

			if (och->fighting != NULL)
			{
				stop_fighting(och->fighting, TRUE);
				stop_fighting(och, TRUE);
			}
			extract_arena(och);

			update_pos(och);
			save_char_obj(och);

			d_write(d, "\n\r", 2);
			d_write(d, crs_sprintf(FALSE, TRUE), 0);
			d_write(d, "\n\r", 2);
		}
	}

	fprintf(fp->stream, "-1\n");
	close_write(fp);

	/* Close reserve and other always-open files and release other resources */

	cleanup_mud();				// don't move this

	/* exec - descriptors are inherited */

	sprintf(buf, "%d", port);
	sprintf(buf2, "%d", control);

	if (verbose_log)
		execl(EXE_FILE, EXE_FILE, buf, "-v", "-c", buf2, (char *) NULL);
	else
		execl(EXE_FILE, EXE_FILE, buf, "-c", buf2, (char *) NULL);
	/* Failed - sucessful exec will not return */

	log_error("do_copyover: execl");
	announce(NULL, INFO_ALL, "Copyover FAILED!");

	/* Here you might want to reopen fpReserve */
	if (fpReserve == NULL)
		fpReserve = fopen(NULL_FILE, "r");
#endif
}

#if !defined(NO_COPYOVER)
/* Recover from a copyover - load players */
void copyover_recover()
{
	DESCRIPTOR_DATA *d;
	READ_DATA *fp;
	char *name;
	int desc;
	bool fOld;

	logf("Copyover recovery initiated");
	crs_info.status = CRS_COPYOVER_RECOVER;

	fp = open_read(COPYOVER_FILE);

	if (!fp)					/* there are some descriptors open which will hang forever then ? */
	{
		log_error("copyover_recover:file open");
		logf("Copyover file not found. Exitting.\n\r");
		exit(1);
	}

	unlink(COPYOVER_FILE);		/* In case something crashes - doesn't prevent reading  */

	for (;;)
	{
		desc = read_number(fp);

		if (desc == -1)
			break;

		name = read_word(fp);

		d = new_descriptor();
		d->descriptor = desc;
		LINK(d, descriptor_first, descriptor_last, next, prev);
		d->connected = CON_COPYOVER_RECOVER;	/* -15, so close_socket frees the char */

		if (!d_write(d, "\n\rRestoring from copyover...\n\r", 0))
		{
			close_socket(d);	/* nope */
			continue;
		}

		/* Now, find the pfile */

		fOld = load_char_obj(d, name);

		if (!fOld)				/* Player file not found?! */
		{
			d_write(d,
					"\n\rSomehow, your character was lost in the copyover. Sorry.\n\r",
					0);
			close_socket(d);
		}
		else					/* ok! */
		{
			d_write(d, "\n\rCopyover recovery complete.\n\r", 0);

			/* Just In Case */
			if (!d->character->in_room)
				d->character->in_room = get_room_index(ROOM_VNUM_TEMPLE);

			/* Insert in the char_first */
			LINK(d->character, char_first, char_last, next, prev);

			LINK(d->character, player_first, player_last, next_player,
				 prev_player);

#if !defined(NO_MCCP)
			if (d->mccp_version > 0)
				compressStart(d, d->mccp_version);
#endif

			update_explored(d->character);
			update_all_qobjs(d->character);

			char_to_room(d->character, d->character->in_room);
			do_look(d->character, "auto");
			checkcorpse(d->character);
			act("$n materializes!", d->character, NULL, NULL, TO_ROOM);
			d->connected = CON_PLAYING;

			if (d->character->pet != NULL)
			{
				char_to_room(d->character->pet, d->character->in_room);
				act("$n materializes!.", d->character->pet, NULL,
					NULL, TO_ROOM);
			}
		}

	}
	close_read(fp);
	crs_info.status = CRS_NONE;
}
#endif

struct qspell_type
{
	SPELL_FUN *spellf;
};

int sn_spellfun_lookup(SPELL_FUN * fun)
{
	int sn;

	for (sn = 0; sn < maxSkill; sn++)
	{
		if (skill_table[sn].spell_fun == fun)
			return sn;
	}
	return -1;
}

const struct qspell_type qspell_table[] = {
	{spell_bless},
	{spell_giant_strength},
	{spell_haste},
	{spell_frenzy},
	{spell_shield},
	{spell_armor},
	{spell_sanctuary},
	{spell_detect_hidden},
	{spell_detect_invis},
	{spell_stone_skin},
	{NULL},
};

CH_CMD(do_spellup)
{
	CHAR_DATA *vch;
	char arg[MIL];
	DESCRIPTOR_DATA *tempdesc;
	int i, sn;

	argument = one_argument(argument, arg);

	if (IS_NULLSTR(arg))
	{
		chprintln(ch, "Syntax: spellup [all, room, <char>]");
		return;
	}

	if (!str_cmp(arg, "all"))
	{
		tempdesc = ch->desc;
		ch->desc = NULL;
		for (vch = player_first; vch != NULL; vch = vch->next_player)
		{
			if (vch == ch || !can_see(ch, vch))
				continue;

			do_function(ch, &do_spellup, vch->name);
		}
		ch->desc = tempdesc;
		chprintln(ch, "OK.");
	}
	else if (!str_cmp(arg, "room"))
	{
		//Lets not spam the caster out
		tempdesc = ch->desc;
		ch->desc = NULL;
		for (vch = ch->in_room->first_person; vch; vch = vch->next_in_room)
		{
			if (vch == ch || IS_NPC(vch) || !can_see(ch, vch))
				continue;

			do_function(ch, &do_spellup, vch->name);
		}
		ch->desc = tempdesc;
		chprintln(ch, "OK.");
	}
	else if ((vch = get_char_world(ch, arg)) != NULL)
	{
		//Lets not spam the caster out
		tempdesc = ch->desc;
		ch->desc = NULL;
		for (i = 0, sn = 0; qspell_table[i].spellf != NULL; i++)
		{
			sn = sn_spellfun_lookup(qspell_table[i].spellf);
			if (sn == -1)
				continue;
			if (is_affected(vch, sn))
				continue;
			qspell_table[i].spellf(sn, get_trust(ch), ch, vch, TARGET_CHAR);
		}
		ch->desc = tempdesc;
		chprintln(ch, "OK.");
	}
	else
		chprintln(ch, "Syntax: spellup [all, room, <char>]");

	return;
}

/** Function: do_pload
  * Descr   : Loads a player object into the mud, bringing them (and their
  *           pet) to you for easy modification.  Player must not be connected.
  *           Note: be sure to send them back when your done with them.
  * Returns : (void)
  * Syntax  : pload (who)
  * Written : v1.0 12/97
  * Author  : Gary McNickle <gary@dharvest.com>
  */
CH_CMD(do_pload)
{
	DESCRIPTOR_DATA d;
	bool isChar = FALSE;
	char name[MAX_INPUT_LENGTH];

	if (IS_NULLSTR(argument))
	{
		chprintln(ch, "Load who?");
		return;
	}

	argument = one_argument(argument, name);

	/* Dont want to load a second copy of a player who's allready online! */
	if (get_char_world(ch, name) != NULL)
	{
		chprintln(ch, "That person is already connected!");
		return;
	}

	isChar = load_char_obj(&d, capitalize(name));	/* char pfile exists? */

	if (!isChar)
	{
		chprintln(ch, "Load Who? Are you sure? I cant seem to find them.");
		return;
	}

	d.character->desc = NULL;
	LINK(d.character, char_first, char_last, next, prev);
	LINK(d.character, player_first, player_last, next_player, prev_player);
	d.connected = CON_PLAYING;
	reset_char(d.character);

	/* bring player to imm */
	if (d.character->in_room != NULL)
	{
		char_to_room(d.character, ch->in_room);	/* put in room imm is in */
	}

	act("$n has pulled $N from the pattern!", ch, NULL, d.character, TO_ROOM);

	if (d.character->pet != NULL)
	{
		char_to_room(d.character->pet, d.character->in_room);
		act("$n has entered the game.", d.character->pet, NULL, NULL, TO_ROOM);
	}

}

/** Function: do_punload
  * Descr   : Returns a player, previously 'ploaded' back to the void from
  *           whence they came.  This does not work if the player is actually 
  *           connected.
  * Returns : (void)
  * Syntax  : punload (who)
  * Written : v1.0 12/97
  * Author  : Gary McNickle <gary@dharvest.com>
  */
CH_CMD(do_punload)
{
	CHAR_DATA *victim;
	char who[MAX_INPUT_LENGTH];

	argument = one_argument(argument, who);

	if ((victim = get_char_world(ch, who)) == NULL)
	{
		chprintln(ch, "They aren't here.");
		return;
	}

  /** Person is legitametly logged on... was not ploaded.
   */
	if (victim->desc != NULL)
	{
		chprintln(ch, "I dont think that would be a good idea...");
		return;
	}

	if (victim->was_in_room != NULL)	/* return player and pet to orig room */
	{
		char_to_room(victim, victim->was_in_room);
		if (victim->pet != NULL)
			char_to_room(victim->pet, victim->was_in_room);
	}

	save_char_obj(victim);
	do_quit(victim, "");

	act("$n has released $N back to the Pattern.", ch, NULL, victim, TO_ROOM);
}