Mud20/accounts/
Mud20/accounts/c/
Mud20/accounts/f/
Mud20/accounts/k/
Mud20/accounts/s/
Mud20/accounts/t/
Mud20/area_current/
Mud20/area_current/newareas/
Mud20/bin/
Mud20/clans/
Mud20/gods/
Mud20/old-sources/
Mud20/player/
Mud20/player/a/del/
Mud20/player/b/
Mud20/player/b/bak/
Mud20/player/b/del/
Mud20/player/f/
Mud20/player/f/bak/
Mud20/player/f/del/
Mud20/player/k/
Mud20/player/k/bak/
Mud20/player/k/del/
Mud20/player/k/dmp/
Mud20/player/m/
Mud20/player/m/bak/
Mud20/player/o/
Mud20/player/o/bak/
Mud20/player/p/
Mud20/player/s/
Mud20/player/s/bak/
Mud20/player/s/del/
Mud20/player/t/
Mud20/player/t/del/
Mud20/player/v/
Mud20/public_html/
Mud20/races/
Mud20/skilltables/
__MACOSX/Mud20/accounts/
__MACOSX/Mud20/accounts/c/
__MACOSX/Mud20/accounts/f/
__MACOSX/Mud20/accounts/k/
__MACOSX/Mud20/accounts/s/
__MACOSX/Mud20/area_current/
__MACOSX/Mud20/area_current/core_areas/
__MACOSX/Mud20/area_current/helps/
__MACOSX/Mud20/area_current/newareas/
__MACOSX/Mud20/backups/
__MACOSX/Mud20/bin/
__MACOSX/Mud20/clans/
__MACOSX/Mud20/gods/
__MACOSX/Mud20/log/
__MACOSX/Mud20/old-sources/
__MACOSX/Mud20/player/
__MACOSX/Mud20/player/a/del/
__MACOSX/Mud20/player/b/
__MACOSX/Mud20/player/b/bak/
__MACOSX/Mud20/player/f/
__MACOSX/Mud20/player/f/bak/
__MACOSX/Mud20/player/f/del/
__MACOSX/Mud20/player/k/
__MACOSX/Mud20/player/k/bak/
__MACOSX/Mud20/player/k/del/
__MACOSX/Mud20/player/k/dmp/
__MACOSX/Mud20/player/m/
__MACOSX/Mud20/player/m/bak/
__MACOSX/Mud20/player/o/
__MACOSX/Mud20/player/o/bak/
__MACOSX/Mud20/player/p/
__MACOSX/Mud20/player/s/
__MACOSX/Mud20/player/s/bak/
__MACOSX/Mud20/player/t/del/
__MACOSX/Mud20/player/v/
__MACOSX/Mud20/public_html/
__MACOSX/Mud20/races/
__MACOSX/Mud20/skilltables/
/***************************************************************************
 * Mud20 1.0 by Todd H. Johnson (Kregor) a derivative of the Open Gaming   *
 * License by Wizards of the Coast. All comments referring to D20, OGL,    *
 * and SRD refer to the System Reference Document for the Open Gaming      *
 * system. Any inclusion of these derivatives must include credit to the   *
 * Mud20 system, the full and complete Open Gaming LIcense, and credit to  *
 * the respective authors. See ../doc/srd.txt for more information.        *
 *                                                                         *
 * Emud  2.2 by Igor van den Hoven, Michiel Lange, and Martin Bethlehem.   *
 *                                                                         *
 * MrMud 1.4 by David Bills, Dug Michael and Martin Gallwey                *
 *                                                                         *
 * Merc  2.1 Diku Mud improvments copyright (C) 1992, 1993 by Michael      *
 * Chastain, Michael Quan, and Mitchell Tse.                               *
 *                                                                         *
 * Original Diku Mud copyright (C) 1990 1991 by Sebastian Hammer,          *
 * Michael Seifert, Hans Henrik St{rfeld, Tom Madsen, and Katje Nyboe.     *
 ***************************************************************************/

/***************************************************************************
 * mob_commands.c: Command functions for mob programs										   *
 ***************************************************************************/

#include "mud.h"

/*
 * Swaps given room exits
 */
void do_mpswap( CHAR_DATA *ch, char *argument )
{
	EXIT_DATA  *pExit;
	RESET_DATA *pReset;

	char arg[MAX_INPUT_LENGTH];
	int dir1, dir2;

	push_call("do_mpswap(%p,%p",ch, argument);

	argument = one_argument(argument, arg);

	dir1 = direction_door(arg);
	dir2 = direction_door(argument);

	if (dir1 == -1 || dir2 == -1 || dir1 == dir2)
	{
		if (IS_NPC(ch))
		{
			log_build_printf(ch->pIndexData->vnum, "Bad argument <mpswap %s %s>", arg, argument);
		}
		else
		{
			ch_printf_color(ch, "Syntax: mpswap <dir1> <dir2>\n\r");
		}
		pop_call();
		return;
	}

	pExit = ch->in_room->exit[dir1];

	ch->in_room->exit[dir1] = ch->in_room->exit[dir2];
	ch->in_room->exit[dir2] = pExit;

	for (pReset = ch->in_room->area->first_reset ; pReset ; pReset = pReset->next)
	{
		if (is_room_reset(pReset, ch->in_room))
		{
			if (is_door_reset(pReset, dir1))
			{
				pReset->arg2 = dir2;
			}
			else if (is_door_reset(pReset, dir2))
			{
				pReset->arg2 = dir1;
			}
		}
	}
	pop_call();
	return;
}


void do_maze( CHAR_DATA *ch, char *argument )
{
	int x, y, z, size;
	int room, start_room, door;

	push_call("do_maze(%p,%p)",ch,argument);

	if (sscanf(argument, "%d %d %d %d", &x, &y, &z, &size) != 4)
	{
		if (IS_NPC(ch))
		{
			log_build_printf(ch->pIndexData->vnum, "Bad Syntax <maze %s>", argument);
		}
		else
		{
			send_to_char( "Format: MAZE <X size> <Y size> <Z size> <Total Rooms>\n\r", ch);
		}
		pop_call();
		return;
	}

	if (x < 1 || y < 1 || z < 1 || x * y * z < 4 || x * y * z > 8000 || size < 2 || size > 100)
	{
		if (IS_NPC(ch))
		{
			log_build_printf(ch->pIndexData->vnum, "Bad Coordinates <maze %s>", argument);
		}
		else
		{
			ch_printf_color(ch, "Invalid maze coordinates.\n\r");
		}
		pop_call();
		return;
	}

	for (room = start_room = ch->in_room->vnum ; room < start_room + size ; room++)
	{
		for (door = 0 ; door < 6 ; door++)
		{
			if (room_index[room] && room_index[room]->exit[door] && room_index[room]->exit[door]->vnum <= 0)
			{
				room_index[room]->exit[door]->exit_info = 0;
				room_index[room]->exit[door]->key		= 0;
				room_index[room]->exit[door]->pvnum	= 0;
				STRFREE(room_index[room]->exit[door]->keyword);
				STRFREE(room_index[room]->exit[door]->description);
				room_index[room]->exit[door]->keyword		= STRDUPE(str_empty);
				room_index[room]->exit[door]->description	= STRDUPE(str_empty);
				set_exit(room, door, -1);
			}
		}
	}

	mazegen(ch, 0, 0, 0, x, y, z, size, 0, number_bits(16), -1);

	if (!IS_NPC(ch) && ch->level >= LEVEL_IMMORTAL)
	{
		send_to_char( "Maze generated.\n\r", ch);
	}
	pop_call();
	return;
}


void mazegen( CHAR_DATA *ch, int cx, int cy, int cz, int x, int y, int z, int size, int count, int seed, int last_door)
{
	int door, room, next_room, cnt;

	push_call("mazegen(%p,%p,%p,%p,%p,%p)",ch,x,y,z,size,count,seed);

	if (count >= size-1)
	{
		pop_call();
		return;
	}

	room = ((count + seed) % size) + ch->in_room->vnum;

	for (cnt = 0 ; cnt < 1000 ; cnt++)
	{
		door = number_door();

		if (door == last_door)
		{
			continue;
		}
		if (room_index[room] && room_index[room]->exit[door] && room_index[room]->exit[door]->vnum > 0)
		{
			continue;
		}
		switch (door)
		{
			case 0: if (cy+1 >= y) continue; break;
			case 1: if (cx+1 >= x) continue; break;
			case 2: if (cy-1 <  0) continue; break;
			case 3: if (cx-1 <  0) continue; break;
			case 4: if (cz+1 >= z) continue; break;
			case 5: if (cz-1 <  0) continue; break;
		}
		break;
	}
	if (cnt == 1000)
	{
		log_printf("Failed to create a maze: room vnum: %d", room);
		pop_call();
		return;
	}
	switch (door)
	{
		case 0: cy++;	break;
		case 1: cx++;	break;
		case 2: cy--;	break;
		case 3: cx--;	break;
		case 4: cz++;	break;
		case 5: cz--;	break;
	}

	count++;
	next_room = ((count + seed) % size) + ch->in_room->vnum;
	last_door = rev_dir[door];

	set_exit(room, door, next_room);
	set_exit(next_room, last_door, room);

	mazegen(ch, cx, cy, cz, x, y, z, size, count, seed, last_door);
	pop_call();
	return;
}


void do_mpdelay( CHAR_DATA *ch, char *argument )
{
	CHAR_DATA *victim;
	char arg1[MAX_INPUT_LENGTH];
	sh_int delay;

	push_call("do_mpdelay(%p,%p",ch, argument);

	argument = one_argument_nolower(argument, arg1);

	if (!IS_NPC(ch) || arg1[0] == '\0' || argument[0] == '\0')
	{
		if (IS_NPC(ch))
		{
			log_build_printf(ch->pIndexData->vnum, "Bad Syntax <mpdelay %s %s>", arg1, argument);
		}
		else
		{
			send_to_char("NPC ONLY: Syntax: mpdelay <victim> <time> <index> <$X>\n\r", ch);
		}
		pop_call();
		return;
	}

	if ((victim = get_char_room_even_blinded(ch, arg1)) == NULL)
	{
		log_build_printf(ch->pIndexData->vnum, "Target not found <mpdelay %s %s>", arg1, argument);
		pop_call();
		return;
	}

	if (!IS_NPC(victim))
	{
		log_build_printf(ch->pIndexData->vnum, "Target is a player <mpdelay %s %s>", arg1, argument);
		pop_call();
		return;
	}

	argument = one_argument_nolower(argument, arg1);
	delay = atol(arg1);

	if (delay >= 60)
	{
		victim->timer	= delay / 60;
		victim->wait	= 0;
	}
	else
	{
		victim->timer	= 0;
		victim->wait	= delay * 2;
	}

	argument = one_argument_nolower(argument, arg1);
	victim->npcdata->delay_index = atol(arg1);

	strcpy(arg1, argument);

	if (!strcasecmp(arg1, "null"))
	{
		STRFREE(victim->npcdata->remember);
		victim->npcdata->remember = STRDUPE(str_empty);
	}
	else
	{
		STRFREE(victim->npcdata->remember);
		victim->npcdata->remember = STRALLOC(arg1);
	}
	pop_call();
	return;
}

/*
 * Added obj prog support for mptrigger
 */
void do_mptrigger( CHAR_DATA *ch, char *argument )
{
	CHAR_DATA *victim;
	OBJ_DATA *obj;
	char arg1[MAX_INPUT_LENGTH];

	push_call("do_mptrigger(%p,%p",ch, argument);

	argument = one_argument_nolower(argument, arg1);

	if (arg1[0] == '\0' || argument[0] == '\0')
	{
		if (IS_NPC(ch))
		{
			log_build_printf(ch->pIndexData->vnum, "Bad Syntax <mptrigger %s %s>", arg1, argument);
		}
		else
		{
			send_to_char("Syntax: mptrigger <victim> <wordlist>\n\r", ch);
		}
		pop_call();
		return;
	}

	if ((victim = get_char_room_even_blinded(ch, arg1)) == NULL)
	{
		if ((obj = get_obj_here_even_blinded(ch, arg1)) == NULL)
		{
			pop_call();
			return;
		}
		else
		{
			oprog_trigger_trigger(argument, obj, ch);
		}
	}

	if (MP_VALID_MOB(victim))
	{
		mprog_trigger_trigger(argument, victim, ch);
	}
	pop_call();
	return;
}


void do_mpcalculate( CHAR_DATA *ch, char *argument)
{
	char arg1[MAX_INPUT_LENGTH];
	char arg2[MAX_INPUT_LENGTH];
	char arg3[MAX_INPUT_LENGTH];
	char arg4[MAX_INPUT_LENGTH];

	push_call("do_mpcalculate(%p,%p)",ch, argument);

	if (IS_NPC(ch))
	{
		sprintf(arg4, "%lld", mathexp(ch, argument));
		STRFREE(ch->npcdata->remember);
		ch->npcdata->remember = STRALLOC(arg4);
	}
	else
	{
		ch_printf_color(ch, "%s = %lld\n\r", argument, mathexp(ch, argument));
	}

	pop_call();
	return;

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

	if (*arg1 == '\0' || *arg2 == '\0' || *arg2 == '\0')
	{
		if (IS_NPC(ch))
		{
			log_build_printf(ch->pIndexData->vnum, "Bad Syntax <mpcalculate %s %s %s>", arg1, arg2, arg3);
		}
		else
		{
			send_to_char("Syntax: mpcalculate <value> <+ - / * %> <value>\n\r", ch);
		}
		pop_call();
		return;
	}

	if (!is_number(arg1) || !is_number(arg3))
	{
		if (IS_NPC(ch))
		{
			log_build_printf(ch->pIndexData->vnum, "Bad Syntax <mpcalculate %s %s %s>", arg1, arg2, arg3);
		}
		else
		{
			send_to_char("You must use numbers to calculate.\n\r", ch);
		}
		pop_call();
		return;
	}

	arg4[0] = '\0';

	switch (arg2[0])
	{
		case '+':
			sprintf(arg4, "%lld", atoll(arg1) + atoll(arg3));
			break;
		case '-':
			sprintf(arg4, "%lld", atoll(arg1) - atoll(arg3));
			break;
		case '*':
			sprintf(arg4, "%lld", atoll(arg1) * atoll(arg3));
			break;
		case '/':
			if (atoll(arg3) == 0)
			{
				if (IS_NPC(ch))
				{
					log_build_printf(ch->pIndexData->vnum, "Division Zero <mpcalculate %s %s %s>", arg1, arg2, arg3);
				}
				else
				{
					send_to_char("You formulate infinity, and store it deep inside you.\n\r", ch);
				}
				pop_call();
				return;
			}
			sprintf(arg4, "%lld", atoll(arg1) / atoll(arg3));
			break;
		case '%':
			sprintf(arg4, "%lld", atoll(arg1) % atoll(arg3));
			break;
		default:
			if (IS_NPC(ch))
			{
				log_build_printf(ch->pIndexData->vnum, "Bad Operator <mpcalculate %s %s %s>", arg1, arg2, arg3);
			}
			else
			{
				send_to_char("Unknown operator.\n\r", ch);
			}
			pop_call();
			return;
	}

	if (IS_NPC(ch))
	{
		STRFREE(ch->npcdata->remember);
		ch->npcdata->remember = STRALLOC(arg4);
	}
	else
	{
		ch_printf_color(ch, "%s %s %s = %s\n\r", arg1, arg2, arg3, arg4);
	}
	if (argument[0] != '\0')
	{
		sprintf(arg1, "%s %s", arg4, argument);
		pop_call();
		return do_mpcalculate(ch, arg1);
	}
	pop_call();
	return;
}
	
void do_mplog( CHAR_DATA *ch, char *argument )
{
	push_call("do_mplog(%p,%p",ch, argument);

	if (IS_NPC(ch))
	{
		log_build_printf(ch->pIndexData->vnum, "MPLOG %s", argument);
	}
	else
	{
		log_printf("[%s] MPLOG %s", ch->name, argument);
	}
	pop_call();
	return;
}

/*
 * Set some area (zone) related stuff
 */
void do_mpzset(CHAR_DATA *ch, char *argument)
{
	AREA_DATA *tarea;
	char arg1[MAX_INPUT_LENGTH];

	push_call("do_mpzset(%p,%p)",ch);

	argument = one_argument_nolower(argument, arg1);

	if (arg1[0] == '\0' || argument[0] == '\0')
	{
		send_to_char("Syntax: mpzset <field> <argument>\n\r", ch);
		send_to_char("  Field being one of:\n\r", ch);
		send_to_char("    resetmsg, quest\n\r", ch);
		pop_call();
		return;
	}

	tarea = ch->in_room->area;

	if (!strcasecmp(arg1, "resetmsg"))
	{
		if (strcasecmp(argument, "null"))
		{
			RESTRING(tarea->resetmsg, argument);
		}
		else
		{
			RESTRING(tarea->resetmsg, "");
		}
		pop_call();
		return;
	}

	if (!strcasecmp(arg1, "quest" ) )
	{
		int firstBit,len,value;

		strcpy(arg1, argument);

		if (sscanf(arg1, "%d %d %d", &firstBit, &len, &value) != 3)
		{
			if (IS_NPC(ch))
			{
				log_build_printf(ch->pIndexData->vnum, "bad parameters <mpzset quest %s>", arg1);
			}
			pop_call();
			return;
		}

		if (IS_NPC(ch))
		{
			set_quest_bits(&ch->pIndexData->area->area_quest, firstBit, len, value);
		}
		else
		{
			set_quest_bits(&ch->in_room->area->area_quest, firstBit, len, value);
		}
		pop_call();
		return;
	}
	do_mpzset(ch, "");
	pop_call();
	return;
}

/*
 * Brand new mpdamage with damage types, selective
 * targeting of groups, and special damage string - Kregor
 */
void do_mpdamage( CHAR_DATA *ch, char *argument )
{
	char arg[MAX_INPUT_LENGTH];
	CHAR_DATA *victim, *victim_next;
	int dam_lo, dam_hi, dam_all, dam_tar, dam_pcs, sn;

	push_call("do_mpdamage(%p,%p)",ch,argument);

	argument = one_argument_nolower(argument, arg);

	if (arg[0] == '\0')
	{
		if (IS_NPC(ch))
		{
			log_build_printf(ch->pIndexData->vnum, "No argument <mpdamage>" );
		}
		else
		{
			send_to_char("Syntax: mpdamage <victim|all|pcs|foe> <num dice> <size dice> <dam type> <message>\n\r", ch);
		}
		pop_call();
		return;
	}

	dam_all = !strcasecmp(arg, "all");
	dam_pcs = !strcasecmp(arg, "pcs");
	dam_tar = !strcasecmp(arg, "foe");

	if (dam_all || dam_pcs)
	{
		victim = NULL;
	}
	else if (dam_tar)
	{
		if ((victim = who_fighting(ch)) == NULL)
		{
			pop_call();
			return;
		}
	}
	else if ((victim = get_char_room_even_blinded(ch, arg)) == NULL)
	{
		pop_call();
		return;
	}

	if (victim == ch)
	{
		if (IS_NPC(ch))
		{
			log_build_printf(ch->pIndexData->vnum, "victim == ch <mpdamage %s %s>", arg, argument );
		}
		pop_call();
		return;
	}

	argument = one_argument_nolower(argument, arg);
	dam_lo   = atol(arg);
	argument = one_argument_nolower(argument, arg);
	dam_hi   = atol(arg);
	
	argument = one_argument_nolower(argument, arg);
	if (!strcasecmp(arg, "pierce"))
		sn = gsn_pierce_hit;
	else if (!strcasecmp(arg, "slash"))
		sn = gsn_slash_hit;
	else if (!strcasecmp(arg, "bash"))
		sn = gsn_bash_hit;
	else if (!strcasecmp(arg, "acid"))
		sn = gsn_acid_hit;
	else if (!strcasecmp(arg, "cold"))
		sn = gsn_frost_hit;
	else if (!strcasecmp(arg, "electric"))
		sn = gsn_shock_hit;
	else if (!strcasecmp(arg, "fire"))
		sn = gsn_fire_hit;
	else if (!strcasecmp(arg, "sonic"))
		sn = gsn_sonic_hit;
	else if (!strcasecmp(arg, "divine"))
		sn = gsn_divine_hit;
	else if (!strcasecmp(arg, "force"))
		sn = gsn_force_hit;
	else
	{
		if (IS_NPC(ch))
		{
			log_build_printf(ch->pIndexData->vnum, "mpdamage: no dam_type argument" );
		}
		else
		{
			send_to_char("bad dam_type: <pierce|slash|bash|acid|cold|electric|fire|sonic|divine|force>\n\r", ch);
		}
		pop_call();
		return;
	}

	if (argument[0] == '\0')
	{
		if (IS_NPC(ch))
		{
			log_build_printf(ch->pIndexData->vnum, "Bad argument <mpdamage: %s %d %d %s>", dam_all ? "all" : victim->name, dam_lo, dam_hi, argument);
		}
		else
		{
			do_mpdamage(ch, "");
		}
		pop_call();
		return;
	}

	strcpy(mpdamstring, argument);

	if (!dam_all && !dam_pcs)
	{
		damage( ch, victim, dice(dam_lo, dam_hi), sn, NULL );

		mpdamstring[0] = '\0';
		pop_call();
		return;
	}

	for (victim = ch->in_room->first_person ; victim ; victim = victim_next)
	{
		victim_next = victim->next_in_room;

		if (can_mass_attack(ch, victim))
		{
			if (dam_all || !IS_NPC(victim))
			{
				damage( ch, victim, dice(dam_lo, dam_hi), sn, NULL );
			}
		}
	}
	
	mpdamstring[0] = '\0';
	pop_call();
	return;
}


/*
 * Infect a character with disease - Kregor
 */
void do_mpinfect( CHAR_DATA *ch, char *argument )
{
	char arg[MAX_INPUT_LENGTH];
	CHAR_DATA *victim, *victim_next;
	int dam_all, dam_tar, dam_pcs, disease;

	push_call("do_mpinfect(%p,%p)",ch,argument);

	argument = one_argument_nolower(argument, arg);

	if (arg[0] == '\0')
	{
		if (IS_NPC(ch))
		{
			log_build_printf(ch->pIndexData->vnum, "Improper arguments <mpinfect>" );
		}
		else
		{
			send_to_char("Syntax: mpinfect <victim|all|pcs|foe> <'disease name'>\n\r", ch);
		}
		pop_call();
		return;
	}

	dam_all = !strcasecmp(arg, "all");
	dam_pcs = !strcasecmp(arg, "pcs");
	dam_tar = !strcasecmp(arg, "foe");

	if (dam_all || dam_pcs)
	{
		victim = NULL;
	}
	else if (dam_tar)
	{
		if ((victim = who_fighting(ch)) == NULL)
		{
			pop_call();
			return;
		}
	}
	else if ((victim = get_char_room_even_blinded(ch, arg)) == NULL)
	{
		pop_call();
		return;
	}

	if (victim == ch)
	{
		if (IS_NPC(ch))
		{
			log_build_printf(ch->pIndexData->vnum, "victim == ch <mpinfect %s %s>", arg, argument );
		}
		pop_call();
		return;
	}
	
	if (argument[0] == '\0' ||  (disease = lookup_disease(argument)) == -1)
	{
		if (IS_NPC(ch))
		{
			log_build_printf(ch->pIndexData->vnum, "Bad argument <mpinfect: %s %s>", dam_all ? "all" : victim->name, argument);
		}
		else if (argument[0] != '\0')
		{
			ch_printf(ch, "mpinfect: bad disease name %s\n\r", argument);
		}
		else
		{
			do_mpinfect(ch, "");
		}
		pop_call();
		return;
	}

	if (!dam_all && !dam_pcs)
	{
		infect_char(NULL, victim, disease);
		pop_call();
		return;
	}

	for (victim = ch->in_room->first_person ; victim ; victim = victim_next)
	{
		victim_next = victim->next_in_room;

		if (can_mass_attack(ch, victim))
		{
			if (dam_all || !IS_NPC(victim))
			{
				infect_char(NULL, victim, disease);
			}
		}
	}
	pop_call();
	return;
}


/*
 * Poison a character - Kregor
 */
void do_mppoison( CHAR_DATA *ch, char *argument )
{
	char arg[MAX_INPUT_LENGTH];
	CHAR_DATA *victim, *victim_next;
	int dam_all, dam_tar, dam_pcs, poison;

	push_call("do_mppoison(%p,%p)",ch,argument);

	argument = one_argument_nolower(argument, arg);

	if (arg[0] == '\0')
	{
		if (IS_NPC(ch))
		{
			log_build_printf(ch->pIndexData->vnum, "Improper arguments <mppoison>" );
		}
		else
		{
			send_to_char("Syntax: mppoison <victim|all|pcs|foe> <'poison name'>\n\r", ch);
		}
		pop_call();
		return;
	}

	dam_all = !strcasecmp(arg, "all");
	dam_pcs = !strcasecmp(arg, "pcs");
	dam_tar = !strcasecmp(arg, "foe");

	if (dam_all || dam_pcs)
	{
		victim = NULL;
	}
	else if (dam_tar)
	{
		if ((victim = who_fighting(ch)) == NULL)
		{
			pop_call();
			return;
		}
	}
	else if ((victim = get_char_room_even_blinded(ch, arg)) == NULL)
	{
		pop_call();
		return;
	}

	if (victim == ch)
	{
		if (IS_NPC(ch))
		{
			log_build_printf(ch->pIndexData->vnum, "victim == ch <mppoison %s %s>", arg, argument );
		}
		pop_call();
		return;
	}
	
	if (argument[0] == '\0' ||  (poison = lookup_poison(argument)) == -1)
	{
		if (IS_NPC(ch))
		{
			log_build_printf(ch->pIndexData->vnum, "Bad argument <mppoison: %s %s>", dam_all ? "all" : victim->name, argument);
		}
		else if (argument[0] != '\0')
		{
			ch_printf(ch, "mppoison: bad poison name %s\n\r", argument);
		}
		else
		{
			do_mppoison(ch, "");
		}
		pop_call();
		return;
	}

	if (!dam_all && !dam_pcs)
	{
		poison_attack(ch, victim, poison);
		pop_call();
		return;
	}

	for (victim = ch->in_room->first_person ; victim ; victim = victim_next)
	{
		victim_next = victim->next_in_room;

		if (can_mass_attack(ch, victim))
		{
			if (dam_all || !IS_NPC(victim))
			{
				poison_attack(ch, victim, poison);
			}
		}
	}
	pop_call();
	return;
}


/*
 * set an affect on an object
 */
void do_mpaset( CHAR_DATA *ch, char *argument )
{
	char arg1[MAX_INPUT_LENGTH];
	char arg2[MAX_INPUT_LENGTH];
	char arg3[MAX_INPUT_LENGTH];
	OBJ_DATA *obj;
	AFFECT_DATA af;
	CHAR_DATA *victim;
	int value, type;
	int duration = -1;

	push_call("do_mpaset(%p,%p)",ch,argument);

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

	if (arg1[0] == '\0' || arg2[0] == '\0' || arg3[0] == '\0')
	{
		if (IS_NPC(ch))
		{
			log_build_printf(ch->pIndexData->vnum, "Bad argument <mpaset: %s %s %s>", arg1, arg2, arg3);
		}
		else
		{
			ch_printf_color(ch, "Syntax: mpaset [on victim] <object> <apply> <value> [duration]\n\r");
		}
		pop_call();
		return;
	}

	if (!strcasecmp(arg1, "on"))
	{
		if ((victim = get_char_room_even_blinded(ch, arg2)) == NULL)
		{
			ch_printf_color(ch, "They're not here.\n\r");
			pop_call();
			return;
		}
		argument = one_argument( argument, arg1 );
		{
			if ((obj = get_obj_carry_even_blinded(victim, arg3)) == NULL)
			{
				if ((obj = get_obj_wear_even_blinded(victim, arg3)) == NULL)
				{
					ch_printf_color(ch, "They're not carrying that.\n\r");
					pop_call();
					return;
				}
			}
		}
		argument = one_argument(argument, arg2);
		argument = one_argument(argument, arg3);
	}
	if ((obj = get_obj_here_even_blinded(ch, arg1)) == NULL)
	{
		pop_call();
		return;
	}

	if ((type = get_flag(arg2, a_types)) == -1)
	{
		if (IS_NPC(ch))
		{
			log_build_printf(ch->pIndexData->vnum, "Bad type <mpaset: %s %s %s>", arg1, arg2, arg3);
		}
		else
		{
			ch_printf_color(ch, "Syntax: mpaset <object> <%s> <value>\n\r", give_flags(a_types));
		}
		pop_call();
		return;
	}
	
	if (!is_number(arg3))
	{
		ch_printf_color(ch, "Value must be a number.\n\r");
		pop_call();
		return;
	}
	
	value = atol(arg3);
	
	if (*argument && atoi(argument) > 0)
	{
		duration = atoi(argument);
	}

	af.type				= gsn_object_rape;
	af.duration		= duration;
	af.modifier		= value;
	af.bitvector	= 0;
	af.bittype		= AFFECT_TO_NONE;
	af.location		= type;
	af.level  		= 0;
	affect_to_obj(ch, obj, &af);

	pop_call();
	return;
}

/*
 * lets the mobile attack any player or mobile without murder
 */
void do_mpkill( CHAR_DATA *ch, char *argument )
{
	char arg[ MAX_INPUT_LENGTH ];
	CHAR_DATA *victim;

	push_call("do_mpkill(%p,%p)",ch,argument);

	if (!IS_NPC(ch))
	{
		pop_call();
		return;
	}

	one_argument( argument, arg );

	if (arg[0] == '\0')
	{
		if (IS_NPC(ch))
		{
			log_build_printf(ch->pIndexData->vnum, "No argument <mpkill>" );
			pop_call();
			return;
		}
		pop_call();
		return;
	}

	if ((victim = get_char_room_even_blinded(ch, arg)) == NULL)
	{
		pop_call();
		return;
	}

	if (victim == ch)
	{
		if (IS_NPC(ch))
		{
			log_build_printf(ch->pIndexData->vnum, "victim == ch <mpkill %s>", arg );
		}
		pop_call();
		return;
	}

	if (in_combat(ch))
	{
		pop_call();
		return;
	}

	if (in_combat (victim))
	{
		char_to_combat (ch, victim->in_battle);
		set_fighting(ch, victim);
		act ("$n rushes headlong into the fray!", ch, NULL, victim, TO_ROOM);
		pop_call();
		return;
	}
	initiate_combat (ch, victim);
	act ("$n initiates combat against you.", ch, NULL, victim, TO_VICT);
	act ("$n initiates combat against $N.", ch, NULL, victim, TO_NOTVICT);
	pop_call();
	return;

	pop_call();
	return;
}


/*
 * repeats intercepted command in intercept_prog
 */
void do_mpunintercept( CHAR_DATA *ch, char *argument )
{
	CHAR_DATA *actor;

	push_call("do_mpunintercept(%p,%p) <%s, %s>",ch,argument,ch->name,argument);
	
	if (!IS_NPC(ch))
	{
		pop_call();
		return;
	}
	if ((actor = ch->npcdata->prog_char) == NULL)
	{
		log_build_printf(ch->pIndexData->vnum, "mpunintercept with no actor. Is this an intercept_prog?");
		pop_call();
		return;
	}
	if (!ch->npcdata->prog_cmd)
	{
		log_build_printf(ch->pIndexData->vnum, "mpunintercept with no command string. Is this an intercept_prog?");
		pop_call();
		return;
	}
	if (actor->in_room != ch->in_room)
	{
		pop_call();
		return;
	}
	interpret(actor, ch->npcdata->prog_cmd);
	
	ch->npcdata->prog_char = NULL;
	STRFREE(ch->npcdata->prog_cmd);
	
	pop_call();
	return;
}

/*
 * destroys an object worn or in inventory using obj name,
 * all.obj or all. on self or [victim]
 */
void do_mpjunk( CHAR_DATA *ch, char *argument )
{
	char		arg[MAX_INPUT_LENGTH];
	OBJ_DATA	*obj;
	OBJ_DATA	*obj_next;
	CHAR_DATA *victim;

	push_call("do_mpjunk(%p,%p) <%s, %s>",ch,argument,ch->name,argument);

	argument = one_argument( argument, arg );

	if (arg[0] == '\0')
	{
		if (IS_NPC(ch))
		{
			log_build_printf(ch->pIndexData->vnum, "No argument <mpjunk>" );
		}
		pop_call();
		return;
	}

	if (argument[0] == '\0')
	{
		victim = ch;
	}
	else
	{
		if ((victim = get_char_room_even_blinded(ch, argument)) == NULL)
		{
			if (IS_NPC(ch))
			{
				log_build_printf(ch->pIndexData->vnum, "NULL target for mpjunk %s", argument );
			}
			pop_call();
			return;
		}
	}
	if (strcasecmp(arg, "all") && str_prefix("all.", arg))
	{
		if ((obj = get_obj_wear_even_blinded(victim, arg)) != NULL)
		{
			junk_obj( obj );
		}
		else if ((obj = get_obj_carry_even_blinded(victim, arg)) != NULL)
		{
			junk_obj( obj );
		}
		pop_call();
		return;
	}
	else
	{
		for (obj = victim->first_carrying ; obj != NULL ; obj = obj_next)
		{
			obj_next = obj->next_content;

			if (arg[3] == '\0' || is_name(&arg[4], obj->name))
			{
				junk_obj( obj );
			}
		}
	}
	pop_call();
	return;
}

void do_mpjunk_person( CHAR_DATA *ch, char *argument )
{
	char		arg[MAX_INPUT_LENGTH];
	OBJ_DATA	*obj;
	OBJ_DATA	*obj_next;
	CHAR_DATA	*victim;

	push_call("do_mpjunk_person(%p,%p)",ch,argument);

	argument = one_argument( argument, arg );

	if (arg[0] == '\0')
	{
		if (IS_NPC(ch))
		{
			log_build_printf(ch->pIndexData->vnum, "No argument <mpjunkperson>" );
		}
		pop_call();
		return;
	}

	if ((victim = get_char_room_even_blinded(ch, arg)) == NULL)
	{
		pop_call();
		return;
	}

	one_argument( argument, arg );

	if (strcasecmp(arg, "all") && str_prefix("all.", arg))
	{
		if ((obj = get_obj_wear_even_blinded(victim, arg)) != NULL)
		{
			junk_obj( obj );
		}
		else if ((obj = get_obj_carry_even_blinded(victim, arg)) != NULL)
		{
			junk_obj( obj );
		}
		pop_call();
		return;
	}
	else
	{
		for (obj = victim->first_carrying ; obj != NULL ; obj = obj_next)
		{
			obj_next = obj->next_content;

			if (arg[3] == '\0' || is_name(&arg[4], obj->name))
			{
				junk_obj( obj );
			}
		}
	}
	pop_call();
	return;
}

/*
 * prints the argument to all the rooms aroud the mobile
 */
void do_mpasound( CHAR_DATA *ch, char *argument )
{
	EXIT_DATA *pExit;
	int door, temp_vnum;
	bool removed = FALSE;
	char buf[MAX_STRING_LENGTH];

	push_call("do_mpasound(%p,%p)",ch,argument);

	if (argument[0] == '\0')
	{
		if (IS_NPC(ch))
		{
			log_build_printf(ch->pIndexData->vnum, "No argument <mpasound>" );
			pop_call();
			return;
		}
	}

	if (IS_ACT(ch, ACT_SECRETIVE))
	{
		REMOVE_BIT(ch->act, ACT_SECRETIVE);
		removed = TRUE;
	}
	
	temp_vnum = ch->in_room->vnum;

	for (door = 0 ; door <= 5 ; door++)
	{
		if ((pExit = get_exit(temp_vnum, door)) != NULL)
		{
			ch->in_room = room_index[pExit->to_room];
			sprintf(buf, "%s to %s.", argument, rev_dir_name[door]);
			act( buf, ch, NULL, NULL, TO_ROOM );
		}
	}
	ch->in_room = room_index[temp_vnum];

	if (IS_NPC(ch))
	{
		if (removed)
			SET_BIT(ch->act, ACT_SECRETIVE);
		pop_call();
		return;
	}
	pop_call();
	return;
}

/*
 * prints the message to everyone in the room other
 * than the mob and victim
 */
void do_mpechoaround( CHAR_DATA *ch, char *argument )
{
	char       arg[ MAX_INPUT_LENGTH ];
	CHAR_DATA *victim;
	bool removed = FALSE;

	push_call("do_mpechoaround(%p,%p [%s])",ch,argument,argument);

	argument = one_argument( argument, arg );

	if (arg[0] == '\0')
	{
		pop_call();
		return;
	}

	if (IS_ACT(ch, ACT_SECRETIVE))
	{
		REMOVE_BIT(ch->act, ACT_SECRETIVE);
		removed = TRUE;
	}
	
	if ((victim = get_char_room_even_blinded(ch, arg)) != NULL)
	{
		act( argument, ch, NULL, victim, TO_NOTVICT );
		act( argument, ch, NULL, victim, TO_CHAR );
	}
	if (IS_NPC(ch))
	{
		if (removed)
			SET_BIT(ch->act, ACT_SECRETIVE);
		pop_call();
		return;
	}
	pop_call();
	return;
}

/*
 * prints the message to only the victim
 */
void do_mpechoat( CHAR_DATA *ch, char *argument )
{
	char       arg[ MAX_INPUT_LENGTH ];
	CHAR_DATA *victim;
	bool removed = FALSE;

	push_call("do_mpechoat(%p,%p)",ch,argument);

	argument = one_argument( argument, arg );

	if (arg[0] == '\0' || argument[0] == '\0')
	{
		pop_call();
		return;
	}

	if (IS_ACT(ch, ACT_SECRETIVE))
	{
		REMOVE_BIT(ch->act, ACT_SECRETIVE);
		removed = TRUE;
	}
	
	if ((victim = get_char_room_even_blinded(ch, arg)) != NULL)
	{
		if (victim == ch)
		{
			act( argument, ch, NULL, NULL, TO_CHAR);
		}
		else
		{
			act( argument, ch, NULL, victim, TO_VICT);
		}
	}
	if (IS_NPC(ch))
	{
		if (removed)
			SET_BIT(ch->act, ACT_SECRETIVE);
		pop_call();
		return;
	}
	pop_call();
	return;
}

/*
 *	prints the message to the room at large
 */

void do_mpecho( CHAR_DATA *ch, char *argument )
{
	bool removed = FALSE;

	push_call("do_mpecho(%p,%p)",ch,argument);

	if (argument[0] == '\0')
	{
		pop_call();
		return;
	}

	if (IS_ACT(ch, ACT_SECRETIVE))
	{
		REMOVE_BIT(ch->act, ACT_SECRETIVE);
		removed = TRUE;
	}
	
	if (!IS_NPC(ch))
	{
		act( argument, ch, NULL, NULL, TO_CHAR );
	}

	act( argument, ch, NULL, NULL, TO_ROOM );

	if (IS_NPC(ch))
	{
		if (removed)
			SET_BIT(ch->act, ACT_SECRETIVE);
		pop_call();
		return;
	}
	pop_call();
	return;
}

/*
 * Print the message to every awake player in the area
 * add "sleepers" to echo to sleeping chars,
 * add "outdoors" to echo to only outdoors chars,
 * add "indoors" to echo to only indoors chars.
 */

void do_mpareaecho( CHAR_DATA *ch, char *argument )
{
	PLAYER_GAME	*pch;
	char      	arg[MAX_INPUT_LENGTH];
	int			echo_type;
	bool removed = FALSE;

	push_call("do_mpareaecho(%p,%p)",ch,argument);

	if (ch->in_room->area->nplayer == 0 || argument[0] == '\0')
	{
		pop_call();
		return;
	}

	if (IS_ACT(ch, ACT_SECRETIVE))
	{
		REMOVE_BIT(ch->act, ACT_SECRETIVE);
		removed = TRUE;
	}
	
	if (!str_prefix("sleepers", argument))
	{
		echo_type = 1;
	}
	else if (!str_prefix("outdoors", argument))
	{
		echo_type = 2;
	}
	else if (!str_prefix("indoors", argument))
	{
		echo_type = 3;
	}
	else
	{
		echo_type = 0;
	}

	if (echo_type > 0)
	{
		argument = one_argument_nolower(argument, arg);
	}

	for (pch = mud->f_player ; pch ; pch = pch->next)
	{
		if (pch->ch->in_room->area == ch->in_room->area)
		{
			switch (echo_type)
			{
				case 1:
					if (IS_AWAKE(pch->ch))
					{
						continue;
					}
					break;
				case 2:
					if (!IS_AWAKE(pch->ch) || !IS_OUTSIDE(pch->ch) ||  NO_WEATHER_SECT(pch->ch->in_room->sector_type))
					{
						continue;
					}
					break;
				case 3:
					if (!IS_AWAKE(pch->ch) ||  IS_OUTSIDE(pch->ch) || !NO_WEATHER_SECT(pch->ch->in_room->sector_type))
					{
						continue;
					}
					break;
				default:
					if (!IS_AWAKE(pch->ch))
					{
						continue;
					}
					break;
			}
			ch_printf_color(pch->ch, "%s\n\r", ansi_translate_text(pch->ch, ansi_justify(argument, get_page_width(pch->ch))));
		}
	}
	if (IS_NPC(ch))
	{
		if (removed)
			SET_BIT(ch->act, ACT_SECRETIVE);
		pop_call();
		return;
	}
	pop_call();
	return;
}

/*
 * load an item or mobile.  All items are loaded into inventory.
 */
void do_mpmload( CHAR_DATA *ch, char *argument )
{
	char            arg[ MAX_INPUT_LENGTH ];
	MOB_INDEX_DATA *pMobIndex;
	CHAR_DATA      *victim;

	push_call("do_mpmload(%p,%p)",ch,argument);

	one_argument( argument, arg );

	if (arg[0] == '\0' || !is_number(arg))
	{
		if (IS_NPC(ch))
		{
			log_build_printf(ch->pIndexData->vnum, "Bad argument: <mpmload %s>", arg );
		}
		pop_call();
		return;
	}

	if ((pMobIndex = get_mob_index(atol(arg))) == NULL)
	{
		if (IS_NPC(ch))
		{
			log_build_printf(ch->pIndexData->vnum, "Bad vnum: <mpmload %s>", arg );
		}
		pop_call();
		return;
	}

	victim = create_mobile( pMobIndex );
	victim->npcdata->mloaded = TRUE;
	char_to_room( victim, ch->in_room->vnum, FALSE );

	pop_call();
	return;
}

void do_mpoload( CHAR_DATA *ch, char *argument )
{
	char arg1[MAX_INPUT_LENGTH];
	char arg2[MAX_INPUT_LENGTH];

	OBJ_INDEX_DATA *pObjIndex;
	OBJ_DATA       *obj;
	bool			load_to_room = FALSE;
	bool			wear_on_load = FALSE;

	push_call("do_mpoload(%p,%p)",ch,argument);

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

	if (arg1[0] == '\0')
	{
		if (IS_NPC(ch))
		{
			log_build_printf(ch->pIndexData->vnum, "Bad argument: <mpoload %s>", arg1 );
		}
		pop_call();
		return;
	}

	switch (arg2[0])
	{
		case 'r':
			load_to_room = TRUE;
			break;

		case 'w':
			wear_on_load = TRUE;
			break;

		case '\0':
			break;

		default:
			if (IS_NPC(ch))
			{
				log_build_printf(ch->pIndexData->vnum, "Bad argument: <mpoload %s %s>", arg1, arg2 );
			}
			pop_call();
			return;
	}

	if ((pObjIndex = get_obj_index(atol(arg1))) == NULL)
	{
		if (IS_NPC(ch))
		{
			log_build_printf(ch->pIndexData->vnum, "Bad vnum: <mpoload %s>", arg1 );
		}
		pop_call();
		return;
	}

	obj = create_object( pObjIndex, 0 );

	if (!CAN_WEAR(obj, CAN_WEAR_TAKE) || load_to_room)
	{
		obj->sac_timer = OBJ_SAC_TIME;
		obj_to_room(obj, ch->in_room->vnum);
	}
	else
	{
		obj_to_char(obj, ch);
		if (wear_on_load)
		{
			wear_obj(ch, obj, FALSE, WEAR_NONE, FALSE);
		}
	}

	pop_call();
	return;
}

/*
 * purge a mob, obj, entire room, or entire area
 */
void do_mppurge( CHAR_DATA *ch, char *argument )
{
	char       arg[ MAX_INPUT_LENGTH ];
	CHAR_DATA *victim;
	OBJ_DATA  *obj;

	push_call("do_mppurge(%p,%p)",ch,argument);

	one_argument( argument, arg );

	if (arg[0] == '\0')
	{
		if (IS_NPC(ch))
		{
			log_build_printf(ch->pIndexData->vnum, "No argument: <mppurge>");
		}
		pop_call();
		return;
	}

	if (!strcasecmp(arg, "on"))
	{
		argument = one_argument(argument, arg);
		
		if ((victim = get_char_room_even_blinded(ch, arg)) == NULL)
		{
			if (IS_NPC(ch))
				log_build_printf(ch->pIndexData->vnum, "obj 'on' NULL target: <mppurge>");
			pop_call();
			return;
		}
		if ((obj = get_obj_carry_even_blinded(victim, argument)) == NULL)
		{
			if (IS_NPC(ch))
				log_build_printf(ch->pIndexData->vnum, "NULL obj on target: <mppurge>");
			pop_call();
			return;
		}
		if (obj->item_type != ITEM_CORPSE_PC)
		{
			if (ch->desc)
				ch_printf_color(ch, "You purge %s\n\r", obj->name);
			junk_obj( obj );
		}
		else
		{
			if (IS_NPC(ch))
			{
				log_build_printf(ch->pIndexData->vnum, "Attempe to purge PC corpse: <mppurge>");
			}
			else
			{
				send_to_char("Cannot purge a PC corpse.\n\r", ch);
			}
		}
		pop_call();
		return;
	}
	if (strcasecmp(arg, "all") && strcasecmp(arg, "area") && str_prefix("all.", arg))
	{
		if ((victim = get_char_room_even_blinded(ch, arg)) == NULL || victim == supermob)
		{
			if ((obj = get_obj_here(ch, arg)) != NULL)
			{
				if (obj->item_type != ITEM_CORPSE_PC)
				{
					if (ch->desc)
						ch_printf_color(ch, "You purge %s\n\r", obj->name);
					junk_obj( obj );
				}
				else
				{
					if (IS_NPC(ch))
					{
						log_build_printf(ch->pIndexData->vnum, "Attempe to purge PC corpse: <mppurge>");
					}
					else
					{
						send_to_char("Cannot purge a PC corpse.\n\r", ch);
					}
				}
			}
			else
			{
				if (IS_NPC(ch))
					log_build_printf(ch->pIndexData->vnum, "NULL target: <mppurge>");
			}
			pop_call();
			return;
		}

		if (!IS_NPC(victim))
		{
			if (IS_NPC(ch))
			{
				log_build_printf(ch->pIndexData->vnum, "Target is a PC <mppurge %s>", arg );
			}
			pop_call();
			return;
		}
		if (victim == supermob)
		{
			if (IS_NPC(ch))
			{
				log_build_printf(ch->pIndexData->vnum, "Trying to purge SuperMob! <mppurge %s>", arg );
			}
			pop_call();
			return;
		}		

		/*
			Use the junk room - Scandum
		*/
		if (ch->desc)
			ch_printf_color(ch, "You purge %s\n\r", victim->name);
		junk_mob(victim);

		pop_call();
		return;
	}

	if (!strcasecmp(arg, "all") || !str_prefix("all.", arg))
	{
		CHAR_DATA *vnext;
		OBJ_DATA  *obj_next;

		for (victim = ch->in_room->first_person ; victim ; victim = vnext)
		{
			vnext = victim->next_in_room;

			if (IS_NPC(victim) && victim != ch && victim != supermob)
			{
				if (arg[3] == '\0' || is_name(&arg[4], victim->name))
				{
					if (ch->desc)
						ch_printf_color(ch, "You purge %s\n\r", victim->name);
					junk_mob(victim);
				}
			}
		}

		for (obj = ch->in_room->first_content ; obj ; obj = obj_next)
		{
			obj_next = obj->next_content;

			if (obj->item_type != ITEM_CORPSE_PC)
			{
				if (arg[3] == '\0' || is_name(&arg[4], obj->name))
				{
					if (ch->desc)
						ch_printf_color(ch, "You purge %s\n\r", obj->name);
					junk_obj( obj );
				}
			}
		}
		pop_call();
		return;
	}
	else
	{
		CHAR_DATA	*vnext;
		OBJ_DATA	*obj_next;
		int room, room_start;

		/*
			Purge every room in the area, nolonger jams on null rooms - Scandum
		*/

		room_start = ch->in_room->vnum;

		for (room = room_index[room_start]->area->low_r_vnum ; room <= room_index[room_start]->area->hi_r_vnum ; room++)
		{
			if (room_index[room] == NULL)
			{
				continue;
			}
			if (room_index[room_start]->area != room_index[room]->area)
			{
				break;
			}
			char_from_room(ch);
			char_to_room(ch, room, FALSE);

			for (victim = ch->in_room->first_person ; victim != NULL ; victim = vnext)
			{
				vnext = victim->next_in_room;

				if (IS_NPC(victim) && victim != ch && victim != supermob)
				{
					junk_mob(victim);
				}
			}

			for (obj = ch->in_room->first_content ; obj ; obj = obj_next)
			{
				obj_next = obj->next_content;

				if (obj->item_type != ITEM_CORPSE_PC)
				{
					junk_obj( obj );
				}
			}
		}
		char_from_room(ch);
		char_to_room(ch, room_start, FALSE);
		if (ch->desc)
			ch_printf_color(ch, "You purge the entire area of %s\n\r", room_index[room_start]->area->name);
	}
	pop_call();
	return;
}

/*
 * sends the mobile to given location
 */
void do_mpgoto( CHAR_DATA *ch, char *argument )
{
	int location;

	push_call("do_mpgoto(%p,%p)",ch,argument);

	if (argument[0] == '\0')
	{
		if (IS_NPC(ch))
		{
			log_build_printf(ch->pIndexData->vnum, "- No argument <mpgoto>" );
		}
		pop_call();
		return;
	}

	if ((location = find_mp_location(ch, argument)) == -1)
	{
		if (IS_NPC(ch))
		{
			log_build_printf(ch->pIndexData->vnum, "Bad location: <mpgoto %s>", argument );
		}
		pop_call();
		return;
	}

	if (is_mounting(ch))
	{
		transference(ch->mounting, location);
	}
	transference(ch, location);

	pop_call();
	return;
}

/*
 * execute command at another location.
 */
void do_mpat( CHAR_DATA *ch, char *argument )
{
	char arg[ MAX_INPUT_LENGTH ];
	int	location, original;
	CHAR_DATA *mount;
	OBJ_DATA *furniture = NULL;

	push_call("do_mpat(%p,%p)",ch,argument);

	if (!IS_NPC(ch) && in_combat(ch))
	{
		pop_call();
		return;
 	}

	argument = one_argument_nolower(argument, arg);

	if (arg[0] == '\0' || argument[0] == '\0')
	{
		if (IS_NPC(ch))
		{
			log_build_printf(ch->pIndexData->vnum, "No argument: <mpat>" );
		}
		pop_call();
		return;
	}

	if ((location = find_mp_location(ch, arg)) == -1)
	{
		if (IS_NPC(ch))
		{
			log_build_printf(ch->pIndexData->vnum, "Bad location: <mpat %s %s>", arg, argument );
		}
		pop_call();
		return;
	}

	mount	= ch->mounting;
	original  = ch->in_room->vnum;

	if (ch->furniture)
	{
		furniture = ch->furniture;
		user_from_furniture(ch);
	}
	char_from_room( ch );
	char_to_room( ch, location, FALSE );

	do_mpdo(ch, argument);

	if (ch && ch->name)
	{
		char_from_room(ch);
		char_to_room(ch, original, FALSE);
		if (furniture)
			user_to_furniture(ch, furniture);
		ch->mounting = mount;
	}
	pop_call();
	return;
}

/*
 * transfer person. [all] and [allgame] are additional parameters
 * [pet] or [group] after the command transfers the target's pet or group.
 */
void do_mptransfer( CHAR_DATA *ch, char *argument )
{
	char		arg1[ MAX_INPUT_LENGTH ];
	char		arg2[ MAX_INPUT_LENGTH ];
	char		arg3[ MAX_INPUT_LENGTH ];
	int		location;
	CHAR_DATA *victim, *next_victim;
	CHAR_DATA *rch, *rch_next;


	push_call("do_mptransfer(%p,%p)",ch,argument);

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

	if (ch->in_room == NULL)
	{
		pop_call();
		return;
	}

	if (arg1[0] == '\0')
	{
		if (IS_NPC(ch))
		{
			log_build_printf(ch->pIndexData->vnum, "bad parameters <mptransfer %s %s>", arg1, arg2);
		}
		pop_call();
		return;
	}

	/* test for numerical name */

	if (*arg1 >= '0' && *arg1 <= '9' && *arg2=='\0' )
	{
		if (IS_NPC(ch))
		{
			log_build_printf(ch->pIndexData->vnum, "bad parameters <mptransfer %s %s>", arg1, arg2);
		}
		pop_call();
		return;
	}

	/*
	 * Thanks to Grodyn for the optional location parameter.
	 */
	if (arg2[0] == '\0' || !strcasecmp(arg2, "pet") || !strcasecmp(arg2, "group"))
	{
		location = ch->in_room->vnum;
	}
	else
	{
		if ((location = find_mp_location(ch, arg2)) == -1)
		{
			if (IS_NPC(ch))
			{
				log_build_printf(ch->pIndexData->vnum, "unknown location <mptransfer %s %s>", arg1, arg2);
			}
			pop_call();
			return;
		}
		if (location == ch->in_room->vnum)
		{
			if (IS_NPC(ch))
			{
				log_build_printf(ch->pIndexData->vnum, "already there <mptransfer %s %s>", arg1, arg2);
			}
			pop_call();
			return;
		}
	}

	if (!strcasecmp(arg1, "all" ))
	{
		CHAR_DATA *next_victim;

		if (arg2[0] == '\0')
		{
			if (IS_NPC(ch))
			{
				log_build_printf(ch->pIndexData->vnum, "bad argument <mptransfer %s %s>", arg1, arg2);
			}
			pop_call();
			return;
		}

		for (victim = ch->in_room->first_person ; victim != NULL ; victim = next_victim)
		{
			next_victim = victim->next_in_room;

			if (NEW_AUTH(ch))
				continue;

			if (victim != ch)
			{
				transference( victim, location );
			}
		}
		pop_call();
		return;
	}

	if (!strcasecmp(arg1, "pcs"))
	{
		if (arg2[0]=='\0')
		{
			if (IS_NPC(ch))
			{
				log_build_printf(ch->pIndexData->vnum, "bad argument <mptransfer %s %s>", arg1, arg2);
			}
			pop_call();
			return;
		}

		for (victim = ch->in_room->first_person ; victim ; victim = next_victim)
		{
			next_victim = victim->next_in_room;

			if (NEW_AUTH(victim))
				continue;

			if (victim != ch && (!IS_NPC(victim) || IS_AFFECTED(victim, AFF_DOMINATE) || (IS_SET(victim->act, ACT_PET) && victim->master)))
			{
				transference( victim, location );
			}
		}
		pop_call();
		return;
	}

	if (!strcasecmp(arg1, "area"))
	{
		DESCRIPTOR_DATA *d;
		
		if (arg2[0]=='\0')
		{
			if (IS_NPC(ch))
			{
				log_build_printf(ch->pIndexData->vnum, "bad argument <mptransfer %s %s>", arg1, arg2);
			}
			pop_call();
			return;
		}

		for (d = mud->f_desc ; d ; d = d->next)
		{
			if (d->connected != CON_PLAYING && d->connected != CON_EDITING)
				continue;
			if ((victim = d->character) == NULL)
				continue;
			if (victim->in_room == NULL || victim->in_room->area != ch->in_room->area)
				continue;
			if (NEW_AUTH(victim))
				continue;
			if (victim != ch && (!IS_NPC(victim) || IS_AFFECTED(victim, AFF_DOMINATE) || (IS_SET(victim->act, ACT_PET) && victim->master)))
			{
				transference( victim, location );
			}
		}
		pop_call();
		return;
	}

	if (arg2[0] == '\0' || !strcasecmp(arg2, "pet") || !strcasecmp(arg2, "group"))
	{
		if ((victim = get_char_area_even_blinded(ch, arg1)) == NULL)
		{
			if (IS_NPC(ch))
			{
				log_build_printf(ch->pIndexData->vnum, "target not found <mptransfer %s>", arg1);
			}
			pop_call();
			return;
		}
	}
	else
	{
		if ((victim = get_char_room_even_blinded(ch, arg1)) == NULL)
		{
			if (IS_NPC(ch))
			{
				log_build_printf(ch->pIndexData->vnum, "target not found <mptransfer %s %s>", arg1, arg2);
			}
			pop_call();
			return;
		}
	}

	if (victim->in_room == NULL)
	{
		pop_call();
		return;
	}

	if (NEW_AUTH(victim))
	{
		if (!IS_NPC(ch))
		{
			send_to_char("That character is not yet authorized.\n\r", ch);
		}
		pop_call();
		return;
	}

	if (victim != ch)
	{
		if (is_mounting(victim))
		{
			transference(victim->mounting, location);
		}
		if (!strcasecmp(arg2, "pet") || !strcasecmp(arg3, "pet"))
		{
			for (rch = victim->in_room->first_person ; rch ; rch = rch->next_in_room)
			{
				rch_next = rch->next_in_room;
				
				if (is_master(rch, victim))
				{
					transference(rch, location);
				}
			}
		}
		if (!strcasecmp(arg2, "group") || !strcasecmp(arg3, "group"))
		{
			for (rch = victim->in_room->first_person ; rch ; rch = rch->next_in_room)
			{
				rch_next = rch->next_in_room;
				
				if (is_master(rch, victim))
				{
					transference(rch, location);
				}
				if (is_same_group(rch, victim))
				{
					transference(rch, location);
				}
			}
		}
		transference(victim, location);
	}
	else
	{
		if (IS_NPC(ch))
		{
			log_build_printf(ch->pIndexData->vnum, "target is self <mptransfer %s %s>", arg1, arg2);
		}
	}
	pop_call();
	return;
}

void do_mpdo( CHAR_DATA *ch, char *argument )
{
	char arg[MAX_INPUT_LENGTH];
	int value;

	push_call("mpdo(%p,%p)",ch,argument);

	if (!MP_VALID_MOB(ch))
	{
		interpret(ch, argument);
	}
	else
	{
		argument = one_argument_nolower(argument, arg);

		if ((value = find_command(arg, MAX_LEVEL - 1)) > -1)
		{
			(*cmd_table[value].do_fun) (ch, argument);
		}
		else if (!check_social(ch, arg, argument))
		{
			log_build_printf(ch->pIndexData->vnum, "unknown command: %s", arg);
		}
	}
	pop_call();
	return;
}

/*
	force someone to do something.  must be mortal level
	and the all argument only affects those in the room with the mobile
*/

void do_mpforce( CHAR_DATA *ch, char *argument )
{
	char arg[ MAX_INPUT_LENGTH ];

	push_call("do_mpforce(%p,%p)",ch,argument);

	argument = one_argument( argument, arg );

	if (arg[0] == '\0' || argument[0] == '\0')
	{
		if (IS_NPC(ch))
		{
			log_build_printf(ch->pIndexData->vnum, "bad syntax <mpforce %s %s>", arg, argument);
		}
		pop_call();
		return;
	}

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

		for (vch = ch->in_room->first_person ; vch != NULL ; vch = vch_next)
		{
			vch_next = vch->next_in_room;

			if (!IS_NPC(ch) && !IS_NPC(vch) && IS_PLR(vch, PLR_HOLYLIGHT))
			{
				ch_printf_color(ch, "%s is a god, you cannot force them to do anything.\n\r",capitalize(vch->name));
				continue;
			}
			if (vch != ch && !IS_SET(vch->act, ACT_MOBINVIS))
			{
				if (vch->desc) SET_BIT(CH(vch->desc)->pcdata->interp, INTERP_FORCE);

				do_mpdo(vch, argument);

				if (vch->desc) REMOVE_BIT(CH(vch->desc)->pcdata->interp, INTERP_FORCE);
			}
		}
	}
	else
	{
		CHAR_DATA *victim;

		if ((victim = get_char_room_even_blinded(ch, arg)) == NULL)
		{
			pop_call();
			return;
		}

		if (victim == ch)
		{
			if (IS_NPC(ch))
			{
				log_build_printf(ch->pIndexData->vnum, "mpforce: forcing oneself");
			}
			pop_call();
			return;
		}

		if (!IS_NPC(ch) && !IS_NPC(victim) && IS_PLR(ch, PLR_HOLYLIGHT))
		{
			ch_printf_color(ch,"%s is a God, and thus cannot be forced.\n\r",capitalize(victim->name));

			pop_call();
			return;
		}

		if (victim->desc) SET_BIT(CH(victim->desc)->pcdata->interp, INTERP_FORCE);

		do_mpdo(victim, argument);

		if (victim->desc) REMOVE_BIT(CH(victim->desc)->pcdata->interp, INTERP_FORCE);
	}
	pop_call();
	return;
}

/*
 * Added group argument 9/29/08 - Kregor
 */
void do_mpmset( CHAR_DATA *ch, char *argument )
{
	char arg1[MAX_INPUT_LENGTH];
	char arg2[MAX_INPUT_LENGTH];
	CHAR_DATA *victim;
	PLAYER_GAME *gch;

	push_call("do_mpmset(%p,%p)",ch,argument);

	if (!IS_NPC(ch))
	{
		send_to_char("Use mset instead.\n\r", ch);
		pop_call();
		return;
	}
	
	argument = one_argument( argument, arg1 );

	if ((victim = get_char_room_even_blinded(ch, arg1)) == NULL)
	{
		log_build_printf(ch->pIndexData->vnum, "mset_char on nonexistent target");
		pop_call();
		return;
	}

	one_argument( argument, arg2 );
	
	/*
		group argument will not count NPCs, or immortals
	*/
	if (!strcasecmp(arg2, "group"))
	{
		argument = one_argument( argument, arg2 );
		
		for (gch = mud->f_player ; gch ; gch = gch->next)
		{
			if (IS_NPC(gch->ch))
				continue;
			if (IS_IMMORTAL(gch->ch))
				continue;
			if (gch->ch == victim)
				continue;
			if (!is_same_group(victim, gch->ch))
				continue;

			mset_char(ch, gch->ch, argument, TRUE);
		}
	}
	mset_char(ch, victim, argument, TRUE);
	pop_call();
	return;
}


void do_mposet( CHAR_DATA *ch, char *argument )
{
	char arg1 [MAX_INPUT_LENGTH];
	OBJ_DATA *obj;
	CHAR_DATA *victim;

	push_call("do_mposet(%p,%p)",ch,argument);

	if (!IS_NPC(ch))
	{
		send_to_char("Use oset instead.\n\r", ch);
		pop_call();
		return;
	}
	
	if (!strcasecmp(arg1, "on"))
	{
		argument = one_argument( argument, arg1 );
		if ((victim = get_char_room_even_blinded(ch, arg1)) == NULL)
		{
			ch_printf_color(ch, "They're not here.\n\r");
			pop_call();
			return;
		}
		argument = one_argument( argument, arg1 );
		{
			if ((obj = get_obj_carry_even_blinded(victim, arg1)) == NULL)
			{
				if ((obj = get_obj_wear_even_blinded(victim, arg1)) == NULL)
				{
					ch_printf_color(ch, "They're not carrying that.\n\r");
					pop_call();
					return;
				}
			}
		}
	}
	else if ((obj = get_obj_here_even_blinded(ch, arg1)) == NULL)
	{
		log_build_printf(ch->pIndexData->vnum, "oset_obj on nonexistent target");
		pop_call();
		return;
	}
	oset_obj(ch, obj, argument, TRUE);
	pop_call();
	return;
}


/*
 * Added group argument 9/29/08 - Kregor
 */
void do_mpmadd( CHAR_DATA *ch, char *argument )
{
	char arg1[MAX_INPUT_LENGTH];
	char arg2[MAX_INPUT_LENGTH];
	CHAR_DATA *victim;
	PLAYER_GAME *gch;

	push_call("do_mpmadd(%p,%p)",ch,argument);

	if (!IS_NPC(ch))
	{
		send_to_char("Use madd instead.\n\r", ch);
		pop_call();
		return;
	}
	
	argument = one_argument( argument, arg1 );

	if ((victim = get_char_room_even_blinded(ch, arg1)) == NULL)
	{
		log_build_printf(ch->pIndexData->vnum, "madd_char on nonexistent target");
		pop_call();
		return;
	}

	one_argument( argument, arg2 );
	
	/*
		group argument will not count NPCs, or immortals
	*/
	if (!strcasecmp(arg2, "group"))
	{
		argument = one_argument( argument, arg2 );
		
		for (gch = mud->f_player ; gch ; gch = gch->next)
		{
			if (IS_NPC(gch->ch))
				continue;
			if (IS_IMMORTAL(gch->ch))
				continue;
			if (gch->ch == victim)
				continue;
			if (!is_same_group(victim, gch->ch))
				continue;

			madd_char(ch, gch->ch, argument);
		}
	}
	madd_char(ch, victim, argument);
	pop_call();
	return;
}

void do_mpoadd( CHAR_DATA *ch, char *argument )
{
	char arg1 [MAX_INPUT_LENGTH];
	char arg2 [MAX_INPUT_LENGTH];
	char arg3 [MAX_INPUT_LENGTH];
	OBJ_DATA *obj;
	CHAR_DATA *victim;
	int value;

	push_call("do_mpoadd(%p,%p)",ch,argument);

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

	if (arg1[0] == '\0' || arg2[0] == '\0' || arg3[0] == '\0')
	{
		if (IS_NPC(ch))
		{
			log_build_printf(ch->pIndexData->vnum, "bad parameters <mpoadd %s %s %s>", arg1, arg2, arg3);
		}
		pop_call();
		return;
	}

	if (!strcasecmp(arg1, "on"))
	{
		argument = one_argument( argument, arg1 );
		if ((victim = get_char_room_even_blinded(ch, arg1)) == NULL)
		{
			ch_printf_color(ch, "They're not here.\n\r");
			pop_call();
			return;
		}
		argument = one_argument( argument, arg1 );
		{
			if ((obj = get_obj_carry_even_blinded(victim, arg1)) == NULL)
			{
				if ((obj = get_obj_wear_even_blinded(victim, arg1)) == NULL)
				{
					ch_printf_color(ch, "They're not carrying that.\n\r");
					pop_call();
					return;
				}
			}
		}
	}
	if ((obj = get_obj_here_even_blinded(ch, arg1)) == NULL)
	{
		pop_call();
		return;
	}

	/*
		Snarf the value (which need not be numeric).
	*/

 	value = is_number( arg3 ) ? atol( arg3 ) : -1;

	/*
		Set something.
	*/

	if ( !strcasecmp( arg1, "charges" ) )
	{
		switch(obj->item_type)
		{
			case ITEM_WAND:
			case ITEM_STAFF:
				break;
			default:
				pop_call();
				return;
		}
		obj->value[1] = URANGE(0, obj->value[1] + value, obj->value[2]);
		pop_call();
		return;
	}

	if (!strcasecmp(arg2, "cost"))
	{
		obj->cost = URANGE(0, obj->cost + value, 1 << 31);

		pop_call();
		return;
	}

	if ( !strcasecmp( arg2, "level" ) )
	{
		obj->level = URANGE(1, obj->level + value, LEVEL_HERO);

		pop_call();
		return;
	}

	if ( !strcasecmp( arg2, "quest" ) )
	{
		int firstBit,len;

		if(sscanf(arg3,"%d %d %d",&firstBit,&len,&value)!=3)
		{
			if (IS_NPC(ch))
			{
				log_build_printf(ch->pIndexData->vnum, "bad parameters <mpoadd quest %s>", arg3);
			}
			pop_call();
			return;
		}
		value += get_quest_bits( obj->obj_quest, firstBit, len);
		set_quest_bits( &obj->obj_quest, firstBit, len, value);

		pop_call();
		return;
	}

	if ( !strcasecmp( arg2, "size" ) )
	{
		obj->size = URANGE(SIZE_FINE, obj->size + value, SIZE_GARGANTUAN);

		pop_call();
		return;
	}

	if ( !strcasecmp( arg2, "timer" ) )
	{
		value += obj->timer;
		value = URANGE(0, value, 32000);

		obj->timer = value;

		pop_call();
		return;
	}

	if ( !strcasecmp( arg2, "value0" ) || !strcasecmp( arg2, "v0" ) )
	{
		obj->value[0] = URANGE(0, obj->value[0] + value, 100);

		pop_call();
		return;
	}

	if ( !strcasecmp( arg2, "value1" ) || !strcasecmp( arg2, "v1" ) )
	{
		obj->value[1] = URANGE(0, obj->value[1] + value, 100);

		pop_call();
		return;
	}

	if ( !strcasecmp( arg2, "value2" ) || !strcasecmp( arg2, "v2" ) )
	{
		obj->value[2] = URANGE(0, obj->value[2] + value, 100);

		pop_call();
		return;
	}

	if ( !strcasecmp( arg2, "value3" ) || !strcasecmp( arg2, "v3" ) )
	{
		obj->value[3] = URANGE(0, obj->value[3] + value, 100);

		pop_call();
		return;
	}

	if ( !strcasecmp( arg2, "value4" ) || !strcasecmp( arg2, "v4" ) )
	{
		obj->value[4] = URANGE(0, obj->value[4] + value, 100);

		pop_call();
		return;
	}

	if ( !strcasecmp( arg2, "value5" ) || !strcasecmp( arg2, "v5" ) )
	{
		obj->value[5] = URANGE(0, obj->value[5] + value, 100);

		pop_call();
		return;
	}

	if ( !strcasecmp( arg2, "value6" ) || !strcasecmp( arg2, "v6" ) )
	{
		obj->value[6] = URANGE(0, obj->value[6] + value, 100);

		pop_call();
		return;
	}

	if ( !strcasecmp( arg2, "value7" ) || !strcasecmp( arg2, "v7" ) )
	{
		obj->value[7] = URANGE(0, obj->value[7] + value, 100);

		pop_call();
		return;
	}

	if (!strcasecmp(arg2, "weight"))
	{
		obj->weight = URANGE(0, obj->weight + value, 32000);

		pop_call();
		return;
	}

	if (IS_NPC(ch))
	{
		log_build_printf(ch->pIndexData->vnum, "Unknown argument: <mpoadd %s %s %s>", arg1, arg2, arg3);
	}
	pop_call();
	return;
}

/*
 * mpgorand <startroom> <endroom> <offset> <skipsize>
 *
 * say, you have a 4x4 area from room #6400 to #6415 arranged like:
 *
 *      6400 6401 6402 6403
 *      6404 6405 6406 6407
 *      6408 6409 6410 6411
 *      6412 6413 6414 6415
 *
 * then "mpgorand 6400 6415 0 4" would put the mobile in one of the
 * the following rooms: 6400 6404 6408 6412
 *
 * then "mpgorand 6400 6415 3 4" would put the mobile in one of the
 * the following rooms: 6403 6407 6411 6415
 */

void do_mpgorand( CHAR_DATA *ch, char *argument )
{
	int cnt, is_gate, startroom, endroom, offset, skipsize, rvnum, beginroom;

	push_call("do_mpgorand(%p,%p)",ch,argument);

	if (sscanf(argument," %d %d %d %d", &startroom, &endroom, &offset, &skipsize) != 4)
	{
		if (IS_NPC(ch))
		{
			log_build_printf(ch->pIndexData->vnum, "Bad syntax: <mpgorand %s>", argument);
		}
		else
		{
			ch_printf_color(ch, "Syntax: mpgorand <firstRoom> <lastRoom> <offset> <skipSize>\n\r");
		}
		pop_call();
		return;
	}

	is_gate   = endroom - startroom;
	rvnum 	= number_range(0, is_gate - offset);
	beginroom = startroom + offset + rvnum ;
	rvnum	= beginroom;

	if (skipsize <= 0 || rvnum > endroom || rvnum < startroom || get_room_index(startroom) == NULL)
	{
		if (IS_NPC(ch))
		{
			log_build_printf(ch->pIndexData->vnum, "Mpgorand - bad arguments.");
		}
		pop_call();
		return;
	}

	for (cnt = 0 ; cnt < is_gate ; cnt++)
	{
		if (rvnum > endroom)
		{
			rvnum = rvnum - endroom + startroom;
		}

		if (get_room_index(rvnum) != NULL)
		{
			if (is_gate > 1000)
			{
				if (is_room_good_for_teleport(ch, rvnum))
				{
					break;
				}
			}
			else
			{
				break;
			}
		}
		rvnum += skipsize;
	}
	if (cnt == is_gate)
	{
		log_printf("transference: failed after %d loops", is_gate);
	}
	else
	{
		transference(ch, rvnum);
	}
	pop_call();
	return;
}

void transference( CHAR_DATA *victim, int location )
{
	CHAR_DATA *mount;

	push_call("transference(%p,%p)",victim,location);

	mount = victim->mounting;

	char_from_room( victim );
	char_to_room( victim, location, TRUE );

	victim->mounting = mount;

	pop_call();
	return;
}

/*
 * For setting crafts and knowledge skills thru mob quests
 * syntax:  mppractice victim skill_name max
 */
void do_mppractice( CHAR_DATA * ch, char *argument )
{
	char arg1[MAX_INPUT_LENGTH];
	char arg2[MAX_INPUT_LENGTH];
	char arg3[MAX_INPUT_LENGTH];
	char buf[MAX_INPUT_LENGTH];
	CHAR_DATA *victim;
	int sn, max, adept;
	char *skill_name;

	push_call("do_mppractice(%p,%p)",ch,argument);

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

	if (!IS_NPC(ch))
	{
		send_to_char( "Only mobiles can use this command.\n\r", ch );
		pop_call();
		return;
	}

	if( arg1[0] == '\0' || arg2[0] == '\0' || arg3[0] == '\0' )
	{
		log_printf( "%s: bad parameters <mppractice %s %s %s>", ch->name, arg1, arg2, arg3);
		pop_call();
		return;
	}

	if ( ( victim = get_char_room_even_blinded( ch, arg1 ) ) == NULL )
	{
		log_printf( "%s: mppractice: No target", ch->name );
		pop_call();
		return;
	}

	if( ( sn = skill_lookup( arg2 ) ) < 0 )
	{
		log_printf( "%s: mppractice: Invalid spell/skill name", ch->name );
		pop_call();
		return;
	}

	if( skill_table[sn].skilltype != FSKILL_CRAFT && skill_table[sn].skilltype != FSKILL_KNOWLEDGE )
	{
		log_printf( "%s: mppractice: sn not a craft or knowledge skill", ch->name );
		pop_call();
		return;
	}

	if( IS_NPC( victim ) )
	{
		log_printf( "%s: mppractice: Can't train a mob", ch->name );
		pop_call();
		return;
	}

	skill_name = skill_table[sn].name;

	max = atoi( arg3 );
	if( ( max < 0 ) || ( max > 100 ) )
	{
		sprintf( buf, "%s: mp_practice: Invalid maxpercent: %d", ch->name, max );
		log_printf( buf );
		pop_call();
		return;
	}

	/*
	 * adept is how high the player can learn it 
	 */
	adept = victim->level + 3;

	if (multi(victim , sn) == -1)
	{
		adept /= 2;
	}

	if( ( victim->learned[sn] >= adept ) || ( victim->learned[sn] >= max ) )
	{
		ch_printf_color(victim, "%s shows some knowledge of %s, but yours is clearly superior.\n\r", get_name(ch), skill_name );
		pop_call();
		return;
	}

	/*
	 * past here, victim learns something 
	 */
	ch_printf_color(victim, "%s demonstrates %s to you. You feel more learned in this subject.\n\r", get_name(ch), skill_name );
	log_printf( "%s: mppractice: %s has gained one point in %s", ch->name, victim, skill_name );

	victim->learned[sn] += 1;

	if( victim->learned[sn] >= adept )
	{
		victim->learned[sn] = adept;
		ch_printf_color( victim, "You have learned all you can for now on this subject.\n\r" );
	}
	pop_call();
	return;
}


/*
 * syntax:  mpsetfeat victim feat_name <"ignore" to ignore prerequisites>
 */
void do_mpsetfeat( CHAR_DATA * ch, char *argument )
{
	char arg1[MAX_INPUT_LENGTH];
	char arg2[MAX_INPUT_LENGTH];
	char arg3[MAX_INPUT_LENGTH];
	char buf[MAX_INPUT_LENGTH];
	CHAR_DATA *victim;
	int sn;
	char *skill_name;

	push_call("do_mpsetfeat(%p,%p)",ch,argument);

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

	if( arg1[0] == '\0' || arg2[0] == '\0' )
	{
		log_printf( "%s: bad parameters <mpsetfeat %s %s %s>", ch->name, arg1, arg2, arg3);
		pop_call();
		return;
	}

	if ( ( victim = get_char_room_even_blinded( ch, arg1 ) ) == NULL )
	{
		log_printf( "%s: mpsetfeat: No target", ch->name );
		pop_call();
		return;
	}

	if( ( sn = skill_lookup( arg2 ) ) < 0 )
	{
		log_printf( "%s: mpsetfeat: Invalid spell/skill name", ch->name );
		pop_call();
		return;
	}

	if( skill_table[sn].skilltype != FSKILL_FEAT && skill_table[sn].skilltype != FSKILL_WEAPON )
	{
		log_printf( "%s: mpsetfeat: sn not a feat or weapon prof.", ch->name );
		pop_call();
		return;
	}

	if( IS_NPC( victim ) )
	{
		log_printf( "%s: mpsetfeat %s: Can't train a mob", ch->name, victim->name );
		pop_call();
		return;
	}

	skill_name = skill_table[sn].name;

	/*
	 * still has to have a prereqs unless "ignore" is in command
	 */
	if( arg3[0] == '\0' || strcasecmp(arg3, "ignore") )
	{
		if (!can_train_feat(victim, sn, TRUE))
		{
			sprintf( buf, "%s: mpsetfeat %s: target missing prerequisites.", ch->name, victim->name );
			log_printf( buf );
			pop_call();
			return;
		}
	}

	/*
	 * still has to have a feat point to train it
	 */
	if( ch->pcdata->feat_pts <= 0 )
	{
		ch_printf_color(victim, "You lack the feat point to learn %s from %s.\n\r", skill_name, get_name(ch) );
		sprintf( buf, "%s: mpsetfeat %s: target lacks a feat pt.", ch->name, victim->name );
		log_printf( buf );
		pop_call();
		return;
	}

	/*
	 * past here, victim learns something 
	 */
	ch_printf_color(victim, "%s demonstrates the art of %s to you.\n\r", get_name(ch), skill_name );
	log_printf( "%s: mpsetfeat: %s has gained one point in %s", ch->name, victim, skill_name );

	if (learned(victim,sn) == 1)
		victim->learned[sn] = 2;
	else
		victim->learned[sn] += 1;
		
	victim->pcdata->feat_pts -= 1;
	victim->pcdata->skill_level[victim->level][sn] += 1;

	pop_call();
	return;
}


/*
 * syntax:  mpclearfeat victim feat_name
 */
void do_mpclearfeat( CHAR_DATA * ch, char *argument )
{
	char arg1[MAX_INPUT_LENGTH];
	char arg2[MAX_INPUT_LENGTH];
	CHAR_DATA *victim;
	int sn, points;
	char *skill_name;

	push_call("do_mpclearfeat(%p,%p)",ch,argument);

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

	if( arg1[0] == '\0' || arg2[0] == '\0' )
	{
		log_printf( "%s: bad parameters <mpclearfeat %s %s>", ch->name, arg1, arg2);
		pop_call();
		return;
	}

	if ( ( victim = get_char_room_even_blinded( ch, arg1 ) ) == NULL )
	{
		log_printf( "%s: mpclearfeat: No target", ch->name );
		pop_call();
		return;
	}

	if( ( sn = skill_lookup( arg2 ) ) < 0 )
	{
		log_printf( "%s: mpclearfeat: Invalid spell/skill name", ch->name );
		pop_call();
		return;
	}

	/* Make sure we don't try to clear default feats, only trained ones */
	if( ch->learned[sn] == 0 )
	{
		log_printf( "%s: mpclearfeat %s: no points in feat", ch->name, victim->name );
		pop_call();
		return;
	}

	if( skill_table[sn].skilltype != FSKILL_FEAT && skill_table[sn].skilltype != FSKILL_WEAPON )
	{
		log_printf( "%s: mpclearfeat %s: sn not a feat or weapon proficiency", ch->name, victim->name );
		pop_call();
		return;
	}

	if( IS_NPC( victim ) )
	{
		log_printf( "%s: mpclearfeat %s: Can't set a mob", ch->name, victim->name );
		pop_call();
		return;
	}

	skill_name = skill_table[sn].name;
	points = ch->learned[sn];

	/*
	 * lose the feat, get the feat points back 
	 */
	victim->learned[sn] = 0;
	victim->pcdata->feat_pts += points;
	log_printf( "%s: mpclearfeat: %s has had their points in %s reset", ch->name, victim, skill_name );

	pop_call();
	return;
}

/*
 * Set the walking path of a mobile.
 * uses the funcitons in pathfind.c - Kregor 6/22/07
 */
void do_mpwalkto( CHAR_DATA *ch, char *argument )
{
	int area_size, vnum;
	ROOM_INDEX_DATA *room;

	push_call("do_mpwalkto(%p,%p)",ch,argument);

	if (!IS_NPC(ch))
	{
		pop_call();
		return;
	}

	if (!is_number(argument))
	{
		log_build_printf(ch->in_room->vnum, "do_mpwalkto: argument must be a number");
		pop_call();
		return;
	}
	vnum = atol (argument);

	if ((room = get_room_index(vnum)) == NULL)
	{
		log_build_printf(ch->in_room->vnum, "do_mpwalkto: invalid room vnum");
		pop_call();
		return;
	}

	if (ch->in_room == room)
	{
		pop_call();
		return;
	}

	if (ch->in_room->area != room->area)
	{
		pop_call();
		return;
	}

	if ((area_size = ch->in_room->area->hi_r_vnum - ch->in_room->area->low_r_vnum) >= 2000)
	{
		log_build_printf(ch->in_room->vnum, "do_mpwalkto: Area too big");
		pop_call();
		return;
	}
	
	ch->walkto = vnum;
	
	pop_call();
	return;
}

/*
 * Taken from do_follow, for mobile progs bypasses
 * PC restrictions, and also groups mobile with the
 * group leader of the target - Kregor
 */
void do_mpfollow (CHAR_DATA * ch, char *argument)
{
	char arg[MAX_INPUT_LENGTH];
	CHAR_DATA *victim;

	push_call("do_follow(%p,%p)",ch,argument);

	one_argument (argument, arg);

	if (!IS_NPC(ch))	
	{
		pop_call();
		return;
	}

	if (arg[0] == '\0')
	{
		pop_call();
		return;
	}

	if ((victim = get_char_room_even_blinded (ch, arg)) == NULL)
	{
		pop_call();
		return;
	}

	if (victim == ch)
	{
		if (ch->master == NULL)
		{
			pop_call();
			return;
		}
		stop_follower(ch);
		pop_call();
		return;
	}

	if (ch->master != NULL)
	{
		stop_follower (ch);
	}

	add_follower (ch, victim);
	if (victim->leader)
		ch->leader = victim->leader;
	else
		ch->leader = victim;

	pop_call();
	return;
}


/*
 * lock or unlock a door or container without a key - Kregor
 */
void do_mplock( CHAR_DATA *ch, char *argument )
{
	char arg [MAX_INPUT_LENGTH];
	int door;
	OBJ_DATA *obj;
	EXIT_DATA *pExit;

	push_call("do_mplock(%p,%p)",ch,argument);

	smash_tilde( argument );
	strcpy( arg, argument );

	if (arg[0] == '\0')
	{
		send_to_char( "Syntax: mplock <object|direction>\n\r",ch );
		pop_call();
		return;
	}

	if ((obj = get_obj_here(ch, arg)) != NULL)
	{
		switch (obj->item_type)
		{
			case ITEM_CONTAINER:
			case ITEM_SHEATH:
			case ITEM_SPELLPOUCH:
			case ITEM_CART:
			case ITEM_QUIVER:
				SET_BIT(obj->value[1], CONT_LOCKED);
				break;
			default:
				if (IS_NPC(ch))
					log_build_printf(ch->pIndexData->vnum, "mplock: Invalid object type");
				else
					ch_printf_color(ch, "Invalid object type.\n\r");
				break;
		}
		pop_call();
		return;
	}
	
	door = direction_door(arg);

	if (door < 0)
	{
		door = atol(arg);
	}
	if (door < 0 || door > 5)
	{
		send_to_char ("Invalid exit direction.\n\r",ch);
		pop_call();
		return;
	}
	if ((pExit = ch->in_room->exit[door]) == NULL)
	{
		if (IS_NPC(ch))
			log_build_printf(ch->pIndexData->vnum, "mplock: Invalid direction %s", arg);
		send_to_char( "There is no exit in that direction.\n\r", ch);
		pop_call();
		return;
	}
	if (!IS_SET(pExit->exit_info, EX_ISDOOR))
	{
		if (IS_NPC(ch))
			log_build_printf(ch->pIndexData->vnum, "mplock: door not set %s", arg);
		send_to_char( "There is no door in that direction.\n\r", ch);
		pop_call();
		return;
	}
	SET_BIT(pExit->exit_info, EX_CLOSED);
	SET_BIT(pExit->exit_info, EX_LOCKED);
	pop_call();
	return;
}


void do_mpunlock( CHAR_DATA *ch, char *argument )
{
	char arg [MAX_INPUT_LENGTH];
	int door;
	OBJ_DATA *obj;
	EXIT_DATA *pExit;

	push_call("do_mpunlock(%p,%p)",ch,argument);

	smash_tilde( argument );
	strcpy( arg, argument );

	if (arg[0] == '\0')
	{
		send_to_char( "Syntax: mpunlock <object|direction>\n\r",ch );
		pop_call();
		return;
	}

	if ((obj = get_obj_here(ch, arg)) != NULL)
	{
		switch (obj->item_type)
		{
			case ITEM_CONTAINER:
			case ITEM_SHEATH:
			case ITEM_SPELLPOUCH:
			case ITEM_QUIVER:
			case ITEM_CART:
				REMOVE_BIT(obj->value[1], CONT_LOCKED);
				break;
			default:
				if (IS_NPC(ch))
					log_build_printf(ch->pIndexData->vnum, "mpunlock: Invalid object type");
				else
					ch_printf_color(ch, "Invalid object type.\n\r");
				break;
		}
		pop_call();
		return;
	}
	
	door = direction_door(arg);

	if (door < 0)
	{
		door = atol(arg);
	}
	if (door < 0 || door > 5)
	{
		send_to_char ("Invalid exit direction.\n\r",ch);
		pop_call();
		return;
	}
	if ((pExit = ch->in_room->exit[door]) == NULL)
	{
		if (IS_NPC(ch))
			log_build_printf(ch->pIndexData->vnum, "mpunlock: Invalid direction %s", arg);
		send_to_char( "There is no exit in that direction.\n\r", ch);
		pop_call();
		return;
	}
	if (!IS_SET(pExit->exit_info, EX_ISDOOR))
	{
		if (IS_NPC(ch))
			log_build_printf(ch->pIndexData->vnum, "mpunlock: door not set %s", arg);
		send_to_char( "There is no door in that direction.\n\r", ch);
		pop_call();
		return;
	}
	REMOVE_BIT(pExit->exit_info, EX_LOCKED);
	pop_call();
	return;
}