/*
 * DM3.C:
 *
 *	DM functions
 *
 *	Copyright (C) 1991, 1992, 1993 Brett J. Vickers
 *
 */

#include "mstruct.h"
#include "mextern.h"
#ifdef DMALLOC
  #include "/usr/local/include/dmalloc.h"
#endif

/**********************************************************************/
/*				dm_set				      */
/**********************************************************************/

/* This function allows a DM to set a variable within a currently */
/* existing data structure in the game.				  */

int dm_set(ply_ptr, cmnd)
creature	*ply_ptr;
cmd		*cmnd;
{
	int	fd;

	fd = ply_ptr->fd;

	if(ply_ptr->class < CARETAKER)
		return(PROMPT);

	if(cmnd->num < 2) {
		print(fd, "Set what?\n");
		return;
	}

	switch(low(cmnd->str[1][0])) {
	case 'x': return(dm_set_ext(ply_ptr, cmnd));
	case 'r': return(dm_set_rom(ply_ptr, cmnd));
	case 'c':
	case 'p':
	case 'm': return(dm_set_crt(ply_ptr, cmnd));
	case 'i':
	case 'o': return(dm_set_obj(ply_ptr, cmnd));
	default: print(fd, "Invalid option.  *set <x|r|c|o> <options>\n");
		 return(0);
	}

}

/**********************************************************************/
/*				dm_set_rom			      */
/**********************************************************************/

/* This function allows a DM to set a characteristic of a room. */

int dm_set_rom(ply_ptr, cmnd)
creature	*ply_ptr;
cmd		*cmnd;
{
	room	*rom_ptr;
	int	num, fd;

	rom_ptr = ply_ptr->parent_rom;
	fd = ply_ptr->fd;

	if(cmnd->num < 3) {
		print(fd, "Syntax: *set r [trf] [<value>]\n");
		return(0);
	}

	switch(low(cmnd->str[2][0])) {
	case 't':
		rom_ptr->traffic = cmnd->val[2];
		print(fd, "Traffic is now %d%%.\n", cmnd->val[2]);
		return(0);
	case 'r':
		num = atoi(&cmnd->str[2][1]);
		if(num < 1 || num > 10) return(PROMPT);
		rom_ptr->random[num-1] = cmnd->val[2];
		print(fd, "Random #%d is now %d.\n", num, cmnd->val[2]);
		return(0);
	case 'f':
		num = cmnd->val[2];
		if(num < 1 || num > 64) return(PROMPT);
		if(F_ISSET(rom_ptr, num-1)) {
			F_CLR(rom_ptr, num-1);
			print(fd, "Room flag #%d off.\n", num);
		}
		else {
			F_SET(rom_ptr, num-1);	
			print(fd, "Room flag #%d on.\n", num);
		}
		return(0);
	case 'b':
		if (low(cmnd->str[2][1]) == 'l') {
			rom_ptr->lolevel = (char) cmnd->val[2];
			print(fd, "Low level boundary %d\n", cmnd->val[2]);
		}
		else if (low(cmnd->str[2][1]) == 'h') {
			rom_ptr->hilevel = (char) cmnd->val[2];
			print(fd, "Upper level boundary %d\n", cmnd->val[2]);
		}
		return(0);
	case 'x':
		
		rom_ptr->trap = (short) cmnd->val[2];
		print(fd, "Room has trap #%d set.", cmnd->val[2]);
		return(0);
	default:
		print(fd, "Invalid option.\n");
		return(0);
	}
}

/**********************************************************************/
/*				dm_set_crt			      */
/**********************************************************************/

/* This function allows a DM to set a defining characteristic of */
/* a creature or player						 */

int dm_set_crt(ply_ptr, cmnd)
creature	*ply_ptr;
cmd		*cmnd;
{
	room		*rom_ptr;
	creature	*crt_ptr;
	int		num, fd;

	fd = ply_ptr->fd;
	rom_ptr = ply_ptr->parent_rom;

	if(cmnd->num < 4) {
		print(fd, "Syntax: *set c <name> <a|con|c|dex|e|f|g|hm|h|int|l|mm|m|\n                       pie|p#|r#|str> [<value>]\n");
		return(0);
	}
	
	if(ply_ptr->class < DM) {
               print(fd, "Check with a Dungeonmaster to get permission.\n");
               return(0);
        }

	cmnd->str[2][0] = up(cmnd->str[2][0]);
	crt_ptr = find_who(cmnd->str[2]);
	if(!crt_ptr || (ply_ptr->class<CARETAKER && F_ISSET(crt_ptr, PDMINV)))
		crt_ptr = find_crt(ply_ptr, rom_ptr->first_ply,
				   cmnd->str[2], cmnd->val[2]);
	if(!crt_ptr) {
		cmnd->str[2][0] = low(cmnd->str[2][0]);
		crt_ptr = find_crt(ply_ptr, rom_ptr->first_mon,
				   cmnd->str[2], cmnd->val[2]);
	}

	if(!crt_ptr) {
		print(fd, "Creature not found.\n");
		return(0);
	}

	switch(low(cmnd->str[3][0])) {
	case 'a':
		if (!strcmp(cmnd->str[3], "ar") && 
			crt_ptr->type == MONSTER){
			crt_ptr->armor = cmnd->val[3];
			return(PROMPT);
		}
		crt_ptr->alignment = cmnd->val[3];
		print(fd, "Alignment set.\n");
		return(PROMPT);
	case 'c':
		if(!strcmp(cmnd->str[3], "con")) {
			crt_ptr->constitution = cmnd->val[3];
			return(PROMPT);
		}

		if(ply_ptr->class < DM)
                return(PROMPT);
				
		crt_ptr->class = cmnd->val[3];
		if (crt_ptr->type == PLAYER && cmnd->val[3] == DM)
        if(strcmp(crt_ptr->name, DMNAME) &&
           strcmp(crt_ptr->name, DMNAME2) && strcmp(crt_ptr->name, DMNAME3) &&
           strcmp(crt_ptr->name, DMNAME4) && strcmp(crt_ptr->name, DMNAME5) &&
           strcmp(crt_ptr->name, DMNAME6) && strcmp(crt_ptr->name, DMNAME7))
                crt_ptr->class = CARETAKER;      
		print(fd, "Class set.\n");
		return(PROMPT);
	case 'd':
		if(!strcmp(cmnd->str[3], "dex")) {
			crt_ptr->dexterity = cmnd->val[3];
			print(fd, "Dexterity set.\n");
			return(PROMPT);
		} 
		else if (!strcmp(cmnd->str[3], "dn") && 
			crt_ptr->type == MONSTER){
			crt_ptr->ndice = cmnd->val[3];
			print(fd, "Number of dice set.\n");
			return(PROMPT);
		}
		else if (!strcmp(cmnd->str[3], "ds") && 
			crt_ptr->type == MONSTER){
			crt_ptr->sdice = cmnd->val[3];
			print(fd, "Sides of dice set.\n");
			return(PROMPT);
		}
		else if (!strcmp(cmnd->str[3], "dp") && 
			crt_ptr->type == MONSTER){
			crt_ptr->pdice = cmnd->val[3];
			print(fd, "Plus on dice set.\n");
			return(PROMPT);
		}
		break;
	case 'e':
		crt_ptr->experience = cmnd->val[3];
		print(fd, "%M has %ld experience.\n", crt_ptr, cmnd->val[3]);
		return(0);
	case 'f':
		num = cmnd->val[3];
		if(num < 1 || num > 64) return(PROMPT);
		if(F_ISSET(crt_ptr, num-1)) {
			F_CLR(crt_ptr, num-1);
			print(fd, "%M's flag #%d off.\n", crt_ptr, num);
		}
		else {
			F_SET(crt_ptr, num-1);
			print(fd, "%M's flag #%d on.\n", crt_ptr, num);
		}
		return(0);
	case 'g':
		crt_ptr->gold = cmnd->val[3];
		print(fd, "%M has %ld gold.\n", crt_ptr, cmnd->val[3]);
		return(0);
	case 'h':
		if(cmnd->str[3][1] == 'm'){
			crt_ptr->hpmax = cmnd->val[3];
			print(fd, "Hits max set.\n");
		}
		else {
			crt_ptr->hpcur = cmnd->val[3];
			print(fd, "Hits set.\n");
		}
		return(PROMPT);
	case 'i':
		if(!strcmp(cmnd->str[3], "int")) {
			crt_ptr->intelligence = cmnd->val[3];
			print(fd, "Intellegence set.\n");
			return(PROMPT);
		}
		break;
	case 'l':
		crt_ptr->level = cmnd->val[3];
		print(fd, "Level set.\n");
		return(PROMPT);
	case 'm':
		if(cmnd->str[3][1] == 'm'){
			crt_ptr->mpmax = cmnd->val[3];
			print(fd, "Magic pts max set.\n");
		}
		else {
			crt_ptr->mpcur = cmnd->val[3];
			print(fd, "Magic pts set.\n");
		}
		return(PROMPT);
	case 'p':
		if(!strcmp(cmnd->str[3], "pie")) {
			crt_ptr->piety = cmnd->val[3];
			print(fd, "Piety set.\n");
			return(PROMPT);
		}
		num = atoi(&cmnd->str[3][1]);
		if(num < 0 || num > 4) return(0);
		crt_ptr->proficiency[num] = cmnd->val[3];
		print(fd, "%M given %d shots in prof#%d.\n", crt_ptr, 
		      cmnd->val[3], num);
		return(0);
	case 'r':
		if(!cmnd->str[3][1]) {
			crt_ptr->race = cmnd->val[3];
			print(fd, "Race set.\n");
			return(PROMPT);
		}
		num = atoi(&cmnd->str[3][1]);
		if(num < 0 || num > 3) return(PROMPT);
		crt_ptr->realm[num] = cmnd->val[3];
		print(fd, "%M given %d shots in realm#%d.\n", crt_ptr,
			cmnd->val[3], num);
		return(0);
	case 's':
		if(!strcmp(cmnd->str[3], "str")) {
			crt_ptr->strength = cmnd->val[3];
			print(fd, "Strength set.\n");
			return(PROMPT);
		}
		break;
	case 't':
		if (!strcmp(cmnd->str[3], "thac") && 
			crt_ptr->type == MONSTER){
			crt_ptr->thaco = cmnd->val[3];
			print(fd, "THAC0 set.\n");
			return(PROMPT);
		}
		break;
	}
	print(fd, "Invalid option.\n");
	return(0);
}

/*********************************************************************/
/*********************************************************************/

int dm_set_ext(ply_ptr, cmnd)
creature	*ply_ptr;
cmd		*cmnd;
{
	room	*rom_ptr, *rom_ptr2;
	int	num, fd;

	fd = ply_ptr->fd;

	if (low(cmnd->str[1][1]) == 'f'){
		dm_set_xflg(ply_ptr, cmnd);
		return(0);
	}
	if(cmnd->num < 3) {
		print(fd, "Syntax: *set [#] x <name> <#> [. or name]\n");
		return(0);
	}

	if(cmnd->val[1] == 1)
		rom_ptr = ply_ptr->parent_rom;
	else
		if(load_rom(cmnd->val[1], &rom_ptr) < 0) {
			print(fd, "Room %d does not exist.\n", cmnd->val[1]);
			return(0);
		}

	cmnd->str[2][24] = 0;
	expand_exit_name(cmnd->str[2]);

	if(cmnd->val[2] == 1) {
		print(fd, "Link exit to which room?\n");
		return(0);
	}
	else if(cmnd->val[2] == 0) {
		if(del_exit(&rom_ptr, cmnd->str[2]))
			print(fd, "Exit %s deleted.\n", cmnd->str[2]);
		else
			print(fd, "Exit %s not found.\n", cmnd->str[2]);
	}
	else if(cmnd->num > 3) {
		if(*cmnd->str[3] == '.')
			if(!opposite_exit_name(cmnd->str[2], cmnd->str[3]))
				strcpy(cmnd->str[3], cmnd->str[2]);
		link_rom(&rom_ptr, cmnd->val[2], cmnd->str[2]);
		if(load_rom(cmnd->val[2], &rom_ptr2) < 0)
			print(fd, "Room %d does not exist.\n", cmnd->val[1]);
		else {
			link_rom(&rom_ptr2, rom_ptr->rom_num, cmnd->str[3]);
			resave_rom(rom_ptr2->rom_num);
		}

		print(fd, "Room #%d linked to room #%d in %s direction, both ways.\n", rom_ptr->rom_num, cmnd->val[2], cmnd->str[2]);
	}
	else {
		link_rom(&rom_ptr, cmnd->val[2], cmnd->str[2]);
		print(fd, "Room #%d linked to room #%d in %s direction.\n",
			rom_ptr->rom_num, cmnd->val[2], cmnd->str[2]);
	}

	resave_rom(rom_ptr->rom_num);

	return(0);
}

/************************************************************************/
/*				dm_set_obj				*/
/************************************************************************/

int dm_set_obj(ply_ptr, cmnd)
creature	*ply_ptr;
cmd		*cmnd;
{
	room		*rom_ptr;
	creature	*crt_ptr;
	object		*obj_ptr;
	int		n, fd, match=0;
	long		num;
	char		flags[25];

	fd = ply_ptr->fd;
	rom_ptr = ply_ptr->parent_rom;

	if(cmnd->num < 4) {
		print(fd, "Syntax: *set o <name> [<crt>] <ad|ar|dn|ds|dp|f|m|sm|s|t|v|wg|wr> [<value>]\n");
		return(0);
	}

	if(ply_ptr->class < DM) {
                 print(fd, "Check with a Dungeonmaster for permission.\n");
                 return(0);
         }

	if(cmnd->num == 4) {
		strcpy(flags, cmnd->str[3]);
		num = cmnd->val[3];
		obj_ptr = find_obj(ply_ptr, ply_ptr->first_obj, cmnd->str[2],
			cmnd->val[2]);
		if(!obj_ptr)
			obj_ptr = find_obj(ply_ptr, rom_ptr->first_obj,
				cmnd->str[2], cmnd->val[2]);
		if(!obj_ptr) {
			print(fd, "Object not found.\n");
			return(0);
		}
	}

	else if(cmnd->num == 5) {
		strcpy(flags, cmnd->str[4]);
		num = cmnd->val[4];
		cmnd->str[3][0] = up(cmnd->str[3][0]);
		crt_ptr = find_who(cmnd->str[3]);
		if(!crt_ptr) {
			cmnd->str[3][0] = low(cmnd->str[3][0]);
			crt_ptr = find_crt(ply_ptr, rom_ptr->first_mon,
				cmnd->str[3], cmnd->val[3]);
		}
		if(!crt_ptr) {
			cmnd->str[3][0] = up(cmnd->str[3][0]);
			crt_ptr = find_crt(ply_ptr, rom_ptr->first_ply,
				cmnd->str[3], cmnd->val[3]);
		}
		if(!crt_ptr) {
			print(fd, "Creature not found.\n");
			return(0);
		}

		obj_ptr = find_obj(ply_ptr, crt_ptr->first_obj,
			cmnd->str[2], cmnd->val[2]);
		if(!obj_ptr || !cmnd->val[2]) {
			for(n=0; n<MAXWEAR; n++) {
				if(!crt_ptr->ready[n]) continue;
				if(EQUAL(crt_ptr->ready[n], cmnd->str[2]))
					match++;
				else continue;
				if(cmnd->val[1] == match || !cmnd->val[2]) {
					obj_ptr = crt_ptr->ready[n];
					break;
				}
			}
		}
		if(!obj_ptr) {
			print(fd, "Object not found.\n");
			return(0);
		}
	}

	switch(flags[0]) {
	case 'a':
		switch(flags[1]) {
		case 'd': obj_ptr->adjustment = num; print(fd, "Adjustment set.\n"); return(PROMPT);
		case 'r': obj_ptr->armor = num; print(fd, "Armor set.\n");return(PROMPT);
		}
		break;
	case 'd':
		switch(flags[1]) {
		case 'n': obj_ptr->ndice = num; print(fd, "Dice # set.\n");return(PROMPT);
		case 's': obj_ptr->sdice = num; print(fd, "Dice sides set.\n");return(PROMPT);
		case 'p': obj_ptr->pdice = num; print(fd, "Dice plus set.\n");return(PROMPT);
		}
		break;
	case 'f':
		if(num < 1 || num > 64) return(PROMPT);
		if(F_ISSET(obj_ptr, num-1)) {
			F_CLR(obj_ptr, num-1);
			print(fd, "%I's flag #%d off.\n", obj_ptr, num);
		}
		else {
			F_SET(obj_ptr, num-1);
			print(fd, "%I's flag #%d on.\n", obj_ptr, num);
		}
		return(0);
	case 'm':
		obj_ptr->magicpower = num;
		print(fd, "Magic power set.\n");
		return(PROMPT);
	case 's':
		if(flags[1] == 'm'){
			obj_ptr->shotsmax = num;
			print(fd, "Max shots set.\n");
		}
		else {
			obj_ptr->shotscur = num;
			print(fd, "Current shots set.\n");
		}
		return(PROMPT);
	case 't':
		if ((num<0 || num>14) && ply_ptr->class<DM) return(PROMPT);
		switch(num) {
		case SHARP: obj_ptr->type = SHARP; print(fd, "Object is a sharp weapon.\n");return(PROMPT);
		case THRUST: obj_ptr->type = THRUST; print(fd, "Object is a thrust weapon.\n");return(PROMPT);
		case BLUNT: obj_ptr->type = BLUNT; print(fd, "Object is a blunt weapon.\n");return(PROMPT);
		case POLE: obj_ptr->type = POLE; print(fd, "Object is a pole weapon.\n");return(PROMPT);
		case MISSILE: obj_ptr->type = MISSILE; print(fd, "Object is a missile weapon.\n");return(PROMPT);
		case ARMOR: obj_ptr->type = ARMOR; print(fd, "Object is armor.\n");return(PROMPT);
		case POTION:obj_ptr->type = POTION; print(fd, "Object is a potion.\n");return(PROMPT);
                case SCROLL:obj_ptr->type = SCROLL; print(fd, "Object is a scroll.\n");return(PROMPT);
               	case WAND:obj_ptr->type = WAND; print(fd, "Object is a wand.\n");return(PROMPT);
               	case CONTAINER:obj_ptr->type = CONTAINER; print(fd, "Object is a container.\n");return(PROMPT);
               	case MONEY:obj_ptr->type = MONEY; print(fd, "Object is money.\n");return(PROMPT);               
		case KEY:obj_ptr->type = KEY; print(fd, "Object is a key.\n");return(PROMPT);
		case LIGHTSOURCE:obj_ptr->type = LIGHTSOURCE; print(fd, "Object is a lightsource.\n");return(PROMPT);
		case MISC:obj_ptr->type = MISC; print(fd, "Object is a misc item.\n");
		}

		break;
	case 'v':
		obj_ptr->value = num;
		print(fd, "Value set.\n");
		return(PROMPT);
	case 'w':
		switch(flags[1]) {
		case 'g': obj_ptr->weight = num; print(fd, "Weight set.\n");return(PROMPT);
		case 'r': obj_ptr->wearflag = num; print(fd, "Wear location set.\n");return(PROMPT);
		}
		break;
	}

	print(fd, "Invalid option.\n");
	return(0);
}


/**********************************************************************/
/*                       dm_set_xflg                                  */
/**********************************************************************/

/* This function allows a DM to set a characteristic of a exit. */

int dm_set_xflg(ply_ptr, cmnd)
creature    *ply_ptr;
cmd     *cmnd;
{
    room    *rom_ptr;
    xtag    *xp;
    int     num, fd;
    char    found=0;

    rom_ptr = ply_ptr->parent_rom;
    fd = ply_ptr->fd;

    if(cmnd->num < 3) {
        print(fd, "Syntax: *set xf <exit> <value>\n");
        return(0);
    }

    xp = rom_ptr->first_ext;
        while(xp) {
                if(!strcmp(xp->ext->name, cmnd->str[2]) && 
                        !F_ISSET(xp->ext,XNOSEE)){
                        found = 1;
                        break;
                }
                xp = xp->next_tag;
        }
 
        if(!found) {
                print(fd, "Exit not found.\n");
                return(0);
        }
           
    num = cmnd->val[2];
     if(num < 1 || num > 32) return(PROMPT);
        if(F_ISSET(xp->ext, num-1)) {
            F_CLR(xp->ext, num-1);
            print(fd, "%s exit flag #%d off.\n", xp->ext->name, num);
        }
        else {
            F_SET(xp->ext, num-1);
            print(fd, "%s exit flag #%d on.\n", xp->ext->name, num);
        }

        return(0);   
}
/***********************************************************************/
/***********************************************************************/

void link_rom(rom_ptr, tonum, dir)
room	**rom_ptr;
short	tonum;
char	*dir;
{
	exit_	*ext;
	xtag	*xp, *prev = 0, *temp;

	xp = (*rom_ptr)->first_ext;

	while(xp) {
		ext = xp->ext;
		prev = xp;
		xp = xp->next_tag;
		if (!strcmp(ext->name, dir)) {
			strcpy(ext->name, dir);
			ext->room = tonum;
			return;
		}
	}

	temp = (xtag *)malloc(sizeof(xtag));
	ext = (exit_ *)malloc(sizeof(exit_));

	zero(ext, sizeof(exit_));
	strcpy(ext->name, dir);
	ext->room = tonum;

	temp->next_tag = 0;
	temp->ext = ext;

	if (prev)
		prev->next_tag = temp;
	else
		(*rom_ptr)->first_ext = temp;
}

/*********************************************************************/
/*********************************************************************/
int del_exit(rom_ptr, dir)
room	**rom_ptr;
char	*dir;
{
	xtag	*xp, *prev = 0;

	xp = (*rom_ptr)->first_ext;

	while(xp) {
		if (!strcmp(xp->ext->name, dir)) {
			if(prev)
				prev->next_tag = xp->next_tag;
			else
				(*rom_ptr)->first_ext = xp->next_tag;

			free(xp->ext);
			free(xp);
			return(1);
		}
		prev = xp;
		xp = xp->next_tag;
	}

	return(0);
}

/*********************************************************************/
/*********************************************************************/
void expand_exit_name(name)
char *name;
{
	if(!strcmp(name, "n"))  strcpy(name, "north");
	else if(!strcmp(name, "s"))  strcpy(name, "south");
	else if(!strcmp(name, "e"))  strcpy(name, "east");
	else if(!strcmp(name, "w"))  strcpy(name, "west");
	else if(!strcmp(name, "sw"))  strcpy(name, "southwest");
	else if(!strcmp(name, "nw"))  strcpy(name, "northwest");
	else if(!strcmp(name, "se"))  strcpy(name, "southeast");
	else if(!strcmp(name, "ne"))  strcpy(name, "northeast");
	else if(!strcmp(name, "d")) strcpy(name, "door");
	else if(!strcmp(name, "o")) strcpy(name, "out");
	else if(!strcmp(name, "p")) strcpy(name, "passage");
	else if(!strcmp(name, "t")) strcpy(name, "trap door");
}

/*********************************************************************/
/*********************************************************************/
int opposite_exit_name(name, name2)
char *name, *name2;
{
	if(!strcmp(name, "south"))  strcpy(name2, "north");
	else if(!strcmp(name, "north"))  strcpy(name2, "south");
	else if(!strcmp(name, "west"))  strcpy(name2, "east");
	else if(!strcmp(name, "east"))  strcpy(name2, "west");
	else if(!strcmp(name, "northeast"))  strcpy(name2, "southwest");
	else if(!strcmp(name, "southeast"))  strcpy(name2, "northwest");
	else if(!strcmp(name, "northwest"))  strcpy(name2, "southeast");
	else if(!strcmp(name, "southwest"))  strcpy(name2, "northeast");
	else return(0);		/* search failed */

	return(1);		/* search successful */
}

/************************************************************************/
/*				dm_log					*/
/************************************************************************/

/* This function allows DMs to peruse the log file while in the game.	*/
/* If *log r is typed, then the log file is removed (i.e. cleared).	*/

int dm_log(ply_ptr, cmnd)
creature *ply_ptr;
cmd *cmnd;
{
	char fn[80];

	if(ply_ptr->class < CARETAKER) 
		return(PROMPT);

	sprintf(fn, "%s/log", LOGPATH);

	if(cmnd->num == 2 && !strcmp(cmnd->str[1], "r")) {
		unlink(fn);
		print(ply_ptr->fd, "Log removed.\n");
		return(0);
	}

	view_file(ply_ptr->fd, 1, fn);
	return(DOPROMPT);
}

/************************************************************************/
/*				dm_loadlockout				*/
/************************************************************************/

/* This function allows the DM to force the game to reload the lockout	*/
/* file.  Use this command when you have modified the lockout file and	*/
/* don't want to restart the game to put it into effect.		*/

int dm_loadlockout(ply_ptr, cmnd)
creature	*ply_ptr;
cmd		*cmnd;
{
int	i;

	if(ply_ptr-> class < CARETAKER)
		return(PROMPT);

	load_lockouts();
	print(ply_ptr->fd, "Lockout sites read in:\n");
	for(i=0; i<Numlockedout; i++) {
		print(ply_ptr->fd, "%s@%s\n", Lockout[i].userid, Lockout[i].address);
	}
	return(0);
}

/************************************************************************/
/*				dm_finger				*/
/************************************************************************/

/* This command allows a DM to finger the machine that a player is 	*/
/* calling from.  If a second argument is passed, then finger will	*/
/* do a finger on the person named.  The DM can also request to 	*/
/* explicitly name the site he is fingering using the @ in front of	*/
/* the address.								*/

int dm_finger(ply_ptr, cmnd)
creature	*ply_ptr;
cmd		*cmnd;
{
#ifdef FINGERACCT
	char		addr[80];
	char		name[80];
	char		path[80];
	char		fdstr[5];
	creature	*crt_ptr;

	if(ply_ptr->class < CARETAKER)
		return(PROMPT);

	if(cmnd->num < 2) {
		print(ply_ptr->fd, "Finger whom?\n");
		return(0);
	}

	if(cmnd->str[1][0] == '@')
		strcpy(addr, &cmnd->str[1][1]);
	else {
		cmnd->str[1][0] = up(cmnd->str[1][0]);
		crt_ptr = find_who(cmnd->str[1]);
		if(!crt_ptr) {
			print(ply_ptr->fd, "Use entire player name please.\n");
			return(0);
		}
		strcpy(addr, Ply[crt_ptr->fd].io->address);
	}

#ifdef IRIX
	#define _BSD_COMPAT
        if(!fork())  {
#else
        if(!vfork())  {
#endif
		if(cmnd->num == 3)
			strncpy(name, cmnd->str[2], 79);
		else
			name[0] = 0;

		sprintf(path, "%s/fing", BINPATH);
		sprintf(fdstr, "%d", ply_ptr->fd);
		execl(path, "fing", fdstr, addr, name, 0);
		exit(0);
/* no idea why this is in here causes spawning frps should be exit */
		/*return(PROMPT); */
	}
	else {
		print(ply_ptr->fd, "Forking to %s.\n", addr);
		print(ply_ptr->fd, 
			"Output will arrive shortly.\n");
		return(0);
	}

#endif
}

/************************************************************************/
/*				dm_list					*/
/************************************************************************/

/* This function allows DMs to fork a "list" process.  List is the 	*/
/* utility program that allows one to nicely output a list of monsters,	*/
/* objects or rooms in the game.  There are many flags provided with	*/
/* the command, and they can be entered here in the same way that they	*/
/* are entered on the command line.  					*/

int dm_list(ply_ptr, cmnd)
creature	*ply_ptr;
cmd		*cmnd;
{
#ifndef WIN32
	char		path[80];
	char		fdstr[10];
	int		i;

	if(ply_ptr->class < CARETAKER)
		return(PROMPT);

	if(cmnd->num < 2) {
		print(ply_ptr->fd, "List what?\n");
		return(0);
	}

#ifdef IRIX
        if(!fork())  {
#else
        if(!vfork())  {
#endif
		sprintf(path, "%s/list", BINPATH);
		sprintf(fdstr, "-s%d", ply_ptr->fd);

		for(i=cmnd->num; i<COMMANDMAX; i++)
			cmnd->str[i][0] = 0;

		execl(path, "list", cmnd->str[1], fdstr, cmnd->str[2], 
			cmnd->str[3], cmnd->str[4], 0);
		exit(0);
	}
	else return(0);
#endif
}

/************************************************************************/
/*				dm_info					*/
/************************************************************************/

/* This command allows the DM to view various system statistics		*/

int dm_info(ply_ptr, cmnd)
creature	*ply_ptr;
cmd		*cmnd;
{
	extern int	Rsize, Csize, Osize, Numplayers, Numwaiting;
	int		fd;
	extern short	Random_update_interval;

	if(ply_ptr->class < CARETAKER)
		return(PROMPT);

	fd = ply_ptr->fd;
	print(fd, "Internal Cache Queue Sizes:\n");
	print(fd, "   Rooms: %-5d   Monsters: %-5d   Objects: %-5d\n\n",
		Rsize, Csize, Osize);
	print(fd, "Wander update: %d\n", Random_update_interval);

	print(fd, "      Players: %d  Queued: %d\n\n", Numplayers, Numwaiting);

}
