/
bin/95/
docs/DM/
docs/creatures/
docs/objects/
docs/rooms/
docs/utils/
help/
log/
objmon/ddesc/
player/
post/
rooms/
util/
util/fing/
util/italk/
util/lev-reset/
util/lib/
util/list/
util/msg/
util/tdel/
util/vote/
util/wtfix/
/*
 * COMMAND1.C:
 *
 *	Command handling/parsing routines.
 *
 *	Copyright (C) 1991, 1992, 1993, 1997 Brooke Paul & Brett Vickers
 *
 */

#include "mstruct.h"
#include "mextern.h"
#include <ctype.h>
#include <string.h>
#ifdef DMALLOC
  #include "/usr/local/include/dmalloc.h"
#endif
/**********************************************************************/
/*				login				      */
/**********************************************************************/

/* This function is the first function that gets input from a player when */
/* he logs in.  It asks for the player's name and password, and performs  */
/* the according function calls.					  */

void login(fd, param, str)
int 	fd;
int	param;
char	*str;
{
	int		i, match=0;
	extern int	Numplayers;
	char		tempstr[20], str2[50], path[80], forbid[20];
	long 		t;
	creature	*ply_ptr;
	FILE		*fp;


	switch(param) {
	case 0:
		if(strcmp(Ply[fd].extr->tempstr[0], str)) {
			disconnect(fd);
			return;
		}
		print(fd, "\nPlease enter name: ");
		RETURN(fd, login, 1);
	case 1:
		/* Doneval: Here I check the name of the player. If it's the same
		of one of the mail's boards, bad. 
		Brooke, check the already made characters! *
		for(i=0;i<=BOARDS;i++) {
			if(!strcmp(boards[i], str)) {
				print(fd, "\nThis is the name of a mail board.\n");
				ask_for(fd, "Please enter name: ");
			}
		}
		*/

		if(!isalpha(str[0])) {
			print(fd, "Please enter name: ");
			RETURN(fd, login, 1);
		}

if(PARANOID) {
	/* Check for ident */
	if((!strcmp(Ply[fd].io->userid, "no_port") || !strcmp(Ply[fd].io->userid, "unknown")) && (strcmp(Ply[fd].io->address, "moria.bio.uci.edu") || strcmp(Ply[fd].io->address, "128.200.21.101"))) {
		print(fd, "\n\nI am unable to get authorization from your server.\n");
		print(fd, "Please try connecting from another host, or contact\n");
		print(fd, "your system administrator to request RFC 931 auth/identd.\n\n");
		print(fd, "If you have connected from this account in the past,\n");
		print(fd, "try logging in more slowly.\n\n");
		output_buf();
		disconnect(fd);
		return;
	}
}

	/* Check for double log */
	for(i=0; i<Tablesize; i++) {
		if(!Ply[i].ply) continue;
		if(Ply[i].ply->fd < 0) continue;
		if(strcmp(Ply[i].io->userid, "no_port") || strcmp(Ply[i].io->userid, "unknown")) continue;
		if(!strcmp(Ply[i].io->userid, Ply[fd].io->userid)) {
			match += 1;
			if(match > 0){
				print(fd, "\n\n%s\n", account_exists);
				print(fd, "Please only play one character at a time.\n\n");
				output_buf();
				disconnect(fd);
				return;
			}
		}
	}


	if(strlen(str) < 3) {
		print(fd, "Name must be at least 3 characters.\n\n");
		print(fd, "Please enter name: ");
		RETURN(fd, login, 1);
	}
	if(strlen(str) >= 20) {
		print(fd, "Name must be less than 20 characters.\n\n");
		print(fd, "Please enter name: ");
		RETURN(fd, login, 1);
	}

	for(i=0; i<strlen(str); i++)
		if(!isalpha(str[i])) {
			print(fd, "Name must be alphabetic.\n\n");
			print(fd, "Please enter name: ");
			RETURN(fd, login, 1);
		}

		lowercize(str, 1);
		str[25]=0;

/* check to see the name is allowed */
/*
		sprintf(path, "%s/forbidden_name", PLAYERPATH);
        fp=fopen(path, "r");
        if(!fp)
                merror("ERROR - forbidden name", NONFATAL);
		else {
			while(!feof(fp)) {
                fscanf(fp, "%s", forbid);
                if(!strcmp(forbid, str)) {
                    print(fd, "That name is not allowed.\n");
					print(fd, "\nPlease enter name: ");
                    RETURN(fd, login, 1);
                }
			}
        }
*/
		if(load_ply(str, &ply_ptr) < 0) {
			strcpy(Ply[fd].extr->tempstr[0], str);
			print(fd, "\n%s? Did I get that right? ", str);
			RETURN(fd, login, 2);
		}

		else {
			ply_ptr->fd = -1;
			Ply[fd].ply = ply_ptr;

			if(CHECKDOUBLE) {
				if(checkdouble(ply_ptr->name)) {
			#ifdef WIN32
					scwrite(fd, "No simultaneous playing.\n\r", 26);
			#else 
					write(fd, "No simultaneous playing.\n\r", 26);
			#endif /* WIN32 */
					disconnect(fd);
					return;
				}
			} /* CHECKDOUBLE */

			print(fd, "%c%c%cPlease enter password: ", 255, 251, 1); 
			RETURN(fd, login, 3);
		}

	case 2:
		if(str[0] != 'y' && str[0] != 'Y') {
			Ply[fd].extr->tempstr[0][0] = 0;
			print(fd, "Please enter name: ");
			RETURN(fd, login, 1);
		}
		else {
			print(fd, "\nHit return: ");
			RETURN(fd, create_ply, 1);
		}

	case 3:
		if(strcmp(str, Ply[fd].ply->password)) {
			#ifdef WIN32
			     	scwrite(fd, "\255\252\1\n\rIncorrect.\n\r", 17);
			#else
				write(fd, "\255\252\1\n\rIncorrect.\n\r", 17);
			#endif /* WIN32 */

			disconnect(fd);
			return;
		}
		else {
			print(fd, "%c%c%c\n\r", 255, 252, 1);
			strcpy(tempstr, Ply[fd].ply->name);
			for(i=0; i<Tablesize; i++)
				if(Ply[i].ply && i != fd)
					if(!strcmp(Ply[i].ply->name,
					  Ply[fd].ply->name))
						disconnect(i);	
				free_crt(Ply[fd].ply);

/* It used to cause a crash if a player suicided at the same time */
/* as creating a new charater, this fixes it.			  */

			if(load_ply(tempstr, &Ply[fd].ply) < 0)
			{
				#ifdef WIN32
					scwrite(fd, "Player no longer exists!\n\r", 25);
				#else 	
					write(fd, "Player no longer exists!\n\r", 25);
				#endif /* WIN32 */        
			
				t = time(0);
				strcpy(str2, (char *)ctime(&t));
				str2[strlen(str2)-1] = 0;
				logn("sui_crash","%s: %s (%s) suicided.\n", 
					str2, Ply[fd].ply->name, Ply[fd].io->address);
				disconnect(fd);
				return;
			}
			Ply[fd].ply->fd = fd;
			init_ply(Ply[fd].ply);
			RETURN(fd, command, 1);
		}
	}
}

/**********************************************************************/
/*				create_ply			      */
/**********************************************************************/

/* This function allows a new player to create his or her character. */

void create_ply(fd, param, str)
int	fd;
int	param;
char	*str;
{
	int 	i, k, l, n, sum, num[5], dm_need_pass=0;
	char	ph, ph_str[10];

	switch(param) {
	case 1:
/*		print(fd,"\n\n"); */
		Ply[fd].ply = (creature *)malloc(sizeof(creature));
		if(!Ply[fd].ply)
			merror("create_ply", FATAL);
		zero(Ply[fd].ply, sizeof(creature));
		Ply[fd].ply->fd = -1;
		Ply[fd].ply->rom_num = 1;


	if((!strcmp(Ply[fd].extr->tempstr[0],dmname[0])) ||
	   (!strcmp(Ply[fd].extr->tempstr[0],dmname[1])) ||
	   (!strcmp(Ply[fd].extr->tempstr[0],dmname[2])) ||
	   (!strcmp(Ply[fd].extr->tempstr[0],dmname[3])) ||
	   (!strcmp(Ply[fd].extr->tempstr[0],dmname[4])) ||
	   (!strcmp(Ply[fd].extr->tempstr[0],dmname[5])) ||
	   (!strcmp(Ply[fd].extr->tempstr[0],dmname[6]))) {
		print(fd, "\nA password is required to create that character.\n");
	 	print(fd, "Please enter password: ");
		output_buf();
RETURN(fd, create_ply, 2);
}
else goto no_pass;
case 2:
		if(strcmp(dm_pass, str)) {
		   disconnect(fd);
		   return;
		}
case 3:
no_pass:
		if(ANSILINE) {
			clrscr(fd);
			ask_for(fd, "[M] Male or [F] Female: ");
		}
		else
			print(fd, "[M] Male or [F] Female: ");
		RETURN(fd, create_ply, 4);
	case 4:
		if(low(str[0]) != 'm' && low(str[0]) != 'f') {
			if(ANSILINE)
				ask_for(fd, "[M] Male or [F] Female: ");
			else
				print(fd, "[M] Male or [F] Female: ");
			RETURN(fd, create_ply, 4);
		}
		if(low(str[0]) == 'm')
			F_SET(Ply[fd].ply, PMALES);
		print(fd, "\nAvailable classes:");
		print(fd, "\n		    /----- AVAILABLE CLASSES ------\\");
		print(fd, "\n		    |                              |");
		print(fd, "\n		    |  [A] Assassin  [B] Barbarian |");  
		print(fd, "\n		    |  [C] Cleric    [D] Fighter   |");
		print(fd, "\n		    |  [E] Bard      [F] Mage      |"); 
		print(fd, "\n		    |  [G] Paladin   [H] Ranger    |");
		print(fd, "\n		    |  [I] Thief     [J] Monk      |");
		print(fd, "\n		    |  [K] Druid     [L] Alchemist |");
		print(fd, "\n		    \\------------------------------/");
		if(ANSILINE)
			ask_for(fd, "Choose one: ");
		else
			print(fd, "\nChoose one: ");
		RETURN(fd, create_ply, 5);
	case 5:
		switch(low(str[0])) {
			case 'a': Ply[fd].ply->class = ASSASSIN; break;
			case 'b': Ply[fd].ply->class = BARBARIAN; break;
			case 'c': Ply[fd].ply->class = CLERIC; break;
			case 'd': Ply[fd].ply->class = FIGHTER; break;
			case 'e': Ply[fd].ply->class = BARD; break;
			case 'f': Ply[fd].ply->class = MAGE; break;
			case 'g': Ply[fd].ply->class = PALADIN; break;
			case 'h': Ply[fd].ply->class = RANGER; break;
			case 'i': Ply[fd].ply->class = THIEF; break;
			case 'j': Ply[fd].ply->class = MONK; break;
			case 'k': Ply[fd].ply->class = DRUID; break;
			case 'l': Ply[fd].ply->class = ALCHEMIST; break;
			default: {
				if(ANSILINE)
					ask_for(fd, "Choose one: ");
				else
					print(fd, "\nChoose one: ");
				RETURN(fd, create_ply, 5);
			}
		}
		if(!Ply[fd].ply->class) {
			print(fd, "Invalid selection: %s", str);
			if(ANSILINE)
				ask_for(fd, "Choose one: ");
			else
				print(fd, "\nChoose one: ");
			RETURN(fd, create_ply, 5);
		}

		print(fd, "\n		 ----- CHARACTER STATS -----");
		print(fd, "\nYou have 54 points to distribute among your 5 stats. Please enter your 5");
		print(fd, "\nnumbers in the following order: Strength, Dexterity, Constitution,");
		print(fd, "\nIntelligence, Piety.  No stat may be smaller than 3 or larger than 18.i");
		print(fd, "\nUse the following format: ## ## ## ## ##\n\n");
		
		if(ANSILINE)
			ask_for(fd, ": ");
		else
			print(fd, ": ");
		RETURN(fd, create_ply, 6);
	case 6:
		n = strlen(str); l = 0; k = 0;
		for(i=0; i<=n; i++) {
			if(str[i]==' ' || str[i]==0) {
				str[i] = 0;
				num[k++] = atoi(&str[l]);
				l = i+1;
			}
			if(k>4) break;
		}
		if(k<5) {
			print(fd, "Please enter all 5 numbers.\n");
			if(ANSILINE)
				ask_for(fd, ": ");
			else
				print(fd, "\n: ");
			RETURN(fd, create_ply, 6);
		}
		sum = 0;
		for(i=0; i<5; i++) {
			if(num[i] < 3 || num[i] > 18) {
				print(fd, "No stats < 3 or > 18 please.\n");
				print(fd, ": ");
				RETURN(fd, create_ply, 6);
			}
			sum += num[i];
		}
		if(sum > 54) {
			print(fd, "Stat total may not exceed 54.\n");
			print(fd, ": ");
			RETURN(fd, create_ply, 6);
		}
		Ply[fd].ply->strength = num[0];
		Ply[fd].ply->dexterity = num[1];
		Ply[fd].ply->constitution = num[2];
		Ply[fd].ply->intelligence = num[3];
		Ply[fd].ply->piety = num[4];
		print(fd, "\n		      ----- WEAPON PROFICIENCIES -----");
		print(fd, "\nChoose a weapons proficiency:");
		print(fd, "\n[A] Sharp  [B] Thrusting  [C] Blunt");
		print(fd, "\n[D] Pole   [E] Missile\n\n");
		if(ANSILINE)
			ask_for(fd, ": ");
		else
			print(fd, ": ");
		RETURN(fd, create_ply, 7);
	case 7:
		switch(low(str[0])) {
			case 'a': Ply[fd].ply->proficiency[0]=1024; break;
			case 'b': Ply[fd].ply->proficiency[1]=1024; break;
			case 'c': Ply[fd].ply->proficiency[2]=1024; break;
			case 'd': Ply[fd].ply->proficiency[3]=1024; break;
			case 'e': Ply[fd].ply->proficiency[4]=1024; break;
			default: print(fd, "        <-- Try again.");
				if(ANSILINE)
					ask_for(fd, ": ");
				else
					print(fd, "\n: ");
				RETURN(fd, create_ply, 7);
		}
		print(fd, "\n			  ----- ALIGNMENT -----");
		print(fd, "\nLawful players cannot attack or steal from other players, nor can they\nbe attacked or stolen from by other players.");
		print(fd, "\nChaotic players may attack or steal from other chaotic players, and they can\nbe attacked or stolen from by other chaotic players.\n\n");
		if(ANSILINE)
			ask_for(fd, "Choose an alignment, [C] Chaotic or [L] Lawful: "); 
		else
			print(fd, "\nChoose an alignment, [C] Chaotic or [L] Lawful: ");
		RETURN(fd, create_ply, 8);
	case 8:
		if(low(str[0]) == 'c')
			F_SET(Ply[fd].ply, PCHAOS);
		else if(low(str[0]) == 'l')
			F_CLR(Ply[fd].ply, PCHAOS);
		else {
			if(ANSILINE)
				ask_for(fd, "[C] Chaotic or [L] Lawful: ");
			else
				print(fd, "\n[C] Chaotic or [L] Lawful: ");
			RETURN(fd, create_ply, 8);
		}
		print(fd, "\nAvailable races:");
		print(fd, "\n      /----------------- ELF RACES ----------------\\");
		print(fd, "\n      |  [A] Elf    [B] Dark-Elf    [C] Half-Elf   |");
		print(fd, "\n      |----------------- ORC RACES ----------------|");
		print(fd, "\n      |  [D] Orc    [E] Half-Orc    [F] Goblin     |");
		print(fd, "\n      |----------------- BIG RACES ----------------|");
		print(fd, "\n      |  [G] Troll  [H] Ogre        [I] Half-Giant |");
		print(fd, "\n      |-------------- LITTLE RACES ----------------|");
		print(fd, "\n      |  [J] Dwarf  [K] Hobbit      [L] Gnome      |");
		print(fd, "\n      |------------ HUMANOID RACES ----------------|");
		print(fd, "\n      |  [M] Human                                 |");
		print(fd, "\n      \\-------------------------------------------/\n\n");
		if(ANSILINE)
			ask_for(fd, "Choose one: ");
		else
			print(fd, "\nChoose one: ");
		RETURN(fd, create_ply, 9);
	case 9:
		switch(low(str[0])) {
 		case 'a': Ply[fd].ply->race = ELF; break;
 		case 'b': Ply[fd].ply->race = DARKELF; break;
		case 'c': Ply[fd].ply->race = HALFELF; break;
		case 'd': Ply[fd].ply->race = ORC; break;
		case 'e': Ply[fd].ply->race = HALFORC; break;
		case 'f': Ply[fd].ply->race = GOBLIN; break;
		case 'g': Ply[fd].ply->race = TROLL; break;
		case 'h': Ply[fd].ply->race = OGRE; break;
		case 'i': Ply[fd].ply->race = HALFGIANT; break;
		case 'j': Ply[fd].ply->race = DWARF; break;
		case 'k': Ply[fd].ply->race = HOBBIT; break;
		case 'l': Ply[fd].ply->race = GNOME; break;
		case 'm': Ply[fd].ply->race = HUMAN; break;
		}
		if(!Ply[fd].ply->race) {
			if(ANSILINE)
				ask_for(fd, "Choose one: ");
			else
				print(fd, "\nChoose one: ");
			RETURN(fd, create_ply, 9);
		}

		switch(Ply[fd].ply->race) {
		case DARKELF:
			Ply[fd].ply->intelligence+=1;
			Ply[fd].ply->constitution+=1;
			Ply[fd].ply->piety-=2;
			break;
		case DWARF: 
			Ply[fd].ply->strength++; 
			Ply[fd].ply->piety--; 
			break;
		case ELF: 
			Ply[fd].ply->intelligence+=2;
			Ply[fd].ply->constitution--;
			Ply[fd].ply->strength--; 
			break;
		case GOBLIN:
			Ply[fd].ply->intelligence-=2;
			Ply[fd].ply->constitution++;
			Ply[fd].ply->strength++;
			break;
		case GNOME:
			Ply[fd].ply->piety++;
			Ply[fd].ply->strength--;
			break;
		case HALFELF: 
			Ply[fd].ply->intelligence++; 
			Ply[fd].ply->constitution--; 
			break;
		case HALFORC:
			Ply[fd].ply->constitution--;
			break;			
		case HOBBIT: 
			Ply[fd].ply->dexterity++; 
			Ply[fd].ply->strength--; 
			break;
		case HUMAN: 
			Ply[fd].ply->constitution++; 
			break;
		case OGRE:
			Ply[fd].ply->strength++;
			Ply[fd].ply->piety--;
			break;
		case ORC: 
			Ply[fd].ply->strength++; 
			Ply[fd].ply->constitution++;
			Ply[fd].ply->dexterity--; 
			Ply[fd].ply->intelligence--;
			break;
		case TROLL: 
			Ply[fd].ply->strength++; 
			Ply[fd].ply->intelligence--;
			break;
		case HALFGIANT: 
			Ply[fd].ply->strength+=2; 
			Ply[fd].ply->intelligence--; 
			Ply[fd].ply->piety--; 
			break;
		}

		print(fd, "\nChoose a password (up to 14 chars): ");
		RETURN(fd, create_ply, 10);
	case 10:
		if(strlen(str) > 14) {
			print(fd, "Too long.\nChoose a password: ");
			RETURN(fd, create_ply, 10);
		}
		if(strlen(str) < 3) {
			print(fd, "Too short.\nChoose a password: ");
			RETURN(fd, create_ply, 10);
		}
		strncpy(Ply[fd].ply->password, str, 14);
		strcpy(Ply[fd].ply->name, Ply[fd].extr->tempstr[0]);
		up_level(Ply[fd].ply);
		Ply[fd].ply->fd = fd;
		init_ply(Ply[fd].ply);
		save_ply(Ply[fd].ply->name, Ply[fd].ply);
		print(fd, "\n");
		F_SET(Ply[fd].ply, PNOAAT);
		print(fd, "Type 'welcome' at prompt to get more info on the game\nand help you get started.\n");

		RETURN(fd, command, 1);
	}
}

/**********************************************************************/
/*				command			 	      */
/**********************************************************************/

/* This function handles the main prompt commands, and calls the   	*/
/* appropriate function, depending on what service is requested by the 	*/
/* player.								*/

void command(fd, param, str)
int	fd;
int	param;
char	*str;
{
	cmd	cmnd;
	int	n;
	unsigned char ch;

	/*
	this logn command will print out all the commands entered by players.
	It should be used in extreme cases when trying to isolate a players
	input which may be causing a crash.
	*/
	if(RECORD_ALL)
		logn("all_cmd","\n%s-%d (%d): %s\n",Ply[fd].ply->name,fd,Ply[fd].ply->rom_num,str);  

	switch(param) {
	case 1:

		if(F_ISSET(Ply[fd].ply, PHEXLN)) {
			for(n=0;n<strlen(str);n++) {
				ch = str[n];
				print(fd, "%02X", ch);
			}
			print(fd, "\n");
		}

		if(!strcmp(str, "!"))
			strncpy(str, Ply[fd].extr->lastcommand, 79);

		if(str[0]) {
			for(n=0; str[n] && str[n] == ' '; n++) ;
			strncpy(Ply[fd].extr->lastcommand, &str[n], 79);
		}

		strncpy(cmnd.fullstr, str, 255);
		lowercize(str, 0);
		parse(str, &cmnd); n = 0;

		if(cmnd.num)
			n = process_cmd(fd, &cmnd);
		else
			n = PROMPT;

		if(n == DISCONNECT) {
			#ifdef WIN32
				scwrite(fd, "Goodbye!\n\r\n\r", 11);
			#else
				write(fd, "Goodbye!\n\r\n\r", 11);
			#endif

			disconnect(fd);
			return;
		}
		else if(n == PROMPT) {
				ANSI(fd, MAGENTA);
				if(F_ISSET(Ply[fd].ply, PPROMP))
					sprintf(str, "(%d H %d M): ",
						Ply[fd].ply->hpcur, Ply[fd].ply->mpcur);
				else
					strcpy(str, ": ");
				#ifdef WIN32
					scwrite(fd, str, strlen(str));
				#else 
					write(fd, str, strlen(str));
				#endif /* WIN32 */
				ANSI(fd, WHITE);
			}

		if(n != DOPROMPT) {
			RETURN(fd, command, 1);
		}
		else
			return;
	}
}

/**********************************************************************/
/*				parse				      */
/**********************************************************************/

/* This function takes the string in the first parameter and breaks it */
/* up into its component words, stripping out useless words.  The      */
/* resulting words are stored in a command structure pointed to by the */
/* second argument. 						       */

void parse(str, cmnd)
char	*str;
cmd	*cmnd;
{
	int	i, j, l, m, n, o, art;
	char	tempstr[25];

	l = m = n = 0;
	j = strlen(str);

	for(i=0; i<=j; i++) {
		if(str[i] == ' ' || str[i] == '#' || str[i] == 0) {
			str[i] = 0;	/* tokenize */

			/* Strip extra white-space */
			while((str[i+1] == ' ' || str[i] == '#') && i < j+1)
				str[++i] = 0;

			strncpy(tempstr, &str[l], 24); tempstr[24] = 0;
			l = i+1;
			if(!strlen(tempstr)) continue;

			/* Ignore article/useless words */
			o = art = 0;
			while(article[o][0] != '@') {
				if(!strcmp(article[o++], tempstr)) {
					art = 1;
					break;
				}
			}
			if(art) continue;

			/* Copy into command structure */
			if(n == m) {
				strncpy(cmnd->str[n++], tempstr, 20);
				cmnd->val[m] = 1L;
			}
			else if(isdigit(tempstr[0]) || (tempstr[0] == '-' &&
				isdigit(tempstr[1]))) {
				cmnd->val[m++] = atol(tempstr);
			}
			else {
				strncpy(cmnd->str[n++], tempstr, 20);
				cmnd->val[m++] = 1L;
			}

		}
		if(m >= COMMANDMAX) {
			n = 5;
			break;
		}
	}

	if(n > m)
		cmnd->val[m++] = 1L;
	cmnd->num = n;

}

/**********************************************************************/
/*				process_cmd			      */
/**********************************************************************/

/* This function takes the command structure of the person at the socket */
/* in the first parameter and interprets the person's command.		 */

int process_cmd(fd, cmnd)
int	fd;
cmd	*cmnd;
{
	int	match=0, cmdno=0, c=0;

	do {
		if(!strcmp(cmnd->str[0], cmdlist[c].cmdstr)) {
			match = 1;
			cmdno = c;
			break;
		}
		else if(!strncmp(cmnd->str[0], cmdlist[c].cmdstr, 
			strlen(cmnd->str[0]))) {
			match++;
			cmdno = c;
		}
		c++;
	} while(cmdlist[c].cmdno);

	if(match == 0) {
		print(fd, "The command \"%s\" does not exist.\n", cmnd->str[0]);
		RETURN(fd, command, 1);
	}

	else if(match > 1) {
		print(fd, "Command is not unique.\n");
		RETURN(fd, command, 1);
	}

	if(cmdlist[cmdno].cmdno < 0)
		return(special_cmd(Ply[fd].ply, 0-cmdlist[cmdno].cmdno, cmnd));
	
	return((*cmdlist[cmdno].cmdfn)(Ply[fd].ply, cmnd));
}


int checkdouble(name)
char *name;
{
	char	path[128], tempname[80];
	FILE 	*fp;
	int	rtn=0;

	sprintf(path, "%s/simul/%s", PLAYERPATH, name);
	fp = fopen(path, "r");
	if(!fp)
		return(0);

	while(!feof(fp)) {
		fgets(tempname, 80, fp);
		tempname[strlen(tempname)-1] = 0;
		if(!strcmp(tempname, name))
			continue;
		if(find_who(tempname)) {
			rtn = 1;
			break;
		}
	}

	fclose(fp);
	return(rtn);
}