~case/dbns

63a7a8eaeab8def221fa54768dec8120b5a7188f — case 4 years ago 9fa674e
reworking sockets
10 files changed, 3668 insertions(+), 4115 deletions(-)

M src/Makefile
M src/act_comm.c
M src/act_info.c
M src/comm.c
M src/fight.c
M src/handler.c
M src/mud.h
M src/save.c
M src/skills_dbs.c
M src/update.c
M src/Makefile => src/Makefile +2 -5
@@ 7,11 7,8 @@ MATH_LINK = -lm
DATA_FOLDERS = ../area ../clans ../classes ../councils ../deity ../doc ../gods \
	../houses ../planets ../races ../space ../system

# uncomment if you wish to enable the Mud Client Compression Protocol
OPT_FLAG = -DMCCP

C_FLAGS = ${OPT_FLAG} -O2 -g3 -Wall -std=c99 ${DBUGFLG} ${TIME} ${REG}
L_FLAGS = ${OPT_FLAG} ${MATH_LINK} -lz
C_FLAGS = -O2 -g3 -Wall -std=c99 ${DBUGFLG} ${TIME} ${REG}
L_FLAGS = ${MATH_LINK} -lz

O_FILES = act_comm.o act_info.o act_move.o act_obj.o act_wiz.o ban.o \
          board.o boards.o bounty.o build.o clans.o colorize.o comm.o \

M src/act_comm.c => src/act_comm.c +1 -0
@@ 2535,6 2535,7 @@ fquit(CHAR_DATA * ch)
	/* just incase */
	if (IS_NPC(ch))
		return;
	save_char_obj(ch);
	while ((o = carrying_noquit(ch)) != NULL) {
		obj_from_char(o);
		obj_to_room(o, ch->in_room);

M src/act_info.c => src/act_info.c +0 -5
@@ 26,11 26,6 @@
#include "mud.h"
#include "sha256.h"

#ifdef MCCP
#define TELOPT_COMPRESS 85
#define TELOPT_COMPRESS2 86
#endif

/* Had to add unknowns because someone added new positions and didn't
 * update them.  Just a band-aid till I have time to fix it right.
 * This was found thanks to mud@mini.axcomp.com pointing it out :)

M src/comm.c => src/comm.c +152 -642
@@ 49,22 49,10 @@ const char echo_off_str[] = {IAC, WILL, TELOPT_ECHO, '\0'};
const char echo_on_str[] = {IAC, WONT, TELOPT_ECHO, '\0'};
const char go_ahead_str[] = {IAC, GA, '\0'};

#ifdef MCCP
#define TELOPT_COMPRESS 85
#define TELOPT_COMPRESS2 86
const char eor_on_str[] = {IAC, WILL, TELOPT_EOR, '\0'};
const char compress_on_str[] = {IAC, WILL, TELOPT_COMPRESS2, '\0'};
const char compress2_on_str[] = {IAC, WILL, TELOPT_COMPRESS2, '\0'};

bool compressStart args((DESCRIPTOR_DATA * d, unsigned char telopt));
bool compressEnd args((DESCRIPTOR_DATA * d));

#endif

/*
 * External Functions
 */
void shutdown_mud args((char *reason));
void shutdown_mud(char *reason);

/*
 * Global variables.


@@ 102,33 90,33 @@ char   *alarm_section = "(unknown)";
/*
 * OS-dependent local functions.
 */
void game_loop args(());
int init_socket args((int port));
void new_descriptor args((int new_desc));
bool read_from_descriptor args((DESCRIPTOR_DATA * d));
bool write_to_descriptor args((int desc, char *txt, int length));
void game_loop();
int init_socket(int port);
void new_descriptor(int new_desc);
bool read_from_descriptor (DESCRIPTOR_DATA * d);
bool write_to_descriptor (int desc, char *txt, int length);


/*
 * Other local functions (OS-independent).
 */
bool check_parse_name args((char *name, bool newchar));
bool check_reconnect args((DESCRIPTOR_DATA * d, char *name, bool fConn));
bool check_playing args((DESCRIPTOR_DATA * d, char *name, bool kick));
int main args((int argc, char **argv));
void nanny args((DESCRIPTOR_DATA * d, char *argument));
bool flush_buffer args((DESCRIPTOR_DATA * d, bool fPrompt));
void read_from_buffer args((DESCRIPTOR_DATA * d));
void stop_idling args((CHAR_DATA * ch));
void free_desc args((DESCRIPTOR_DATA * d));
void display_prompt args((DESCRIPTOR_DATA * d));
int make_color_sequence args((const char *col, char *buf, DESCRIPTOR_DATA * d));
void set_pager_input args((DESCRIPTOR_DATA * d, char *argument));
bool pager_output args((DESCRIPTOR_DATA * d));
void mail_count args((CHAR_DATA * ch));
void tax_player args((CHAR_DATA * ch));
void mccp_interest args((CHAR_DATA * ch));
bool check_total_ip args((DESCRIPTOR_DATA * dnew));
bool check_parse_name(char *name, bool newchar);
bool check_reconnect(DESCRIPTOR_DATA * d, char *name, bool fConn);
bool check_playing(DESCRIPTOR_DATA * d, char *name);
bool reconnect(DESCRIPTOR_DATA * d, char *name);
int main (int argc, char **argv);
void nanny (DESCRIPTOR_DATA * d, char *argument);
bool flush_buffer (DESCRIPTOR_DATA * d, bool fPrompt);
void read_from_buffer(DESCRIPTOR_DATA * d);
void free_desc(DESCRIPTOR_DATA * d);
void display_prompt(DESCRIPTOR_DATA * d);
int make_color_sequence(const char *col, char *buf, DESCRIPTOR_DATA * d);
void set_pager_input(DESCRIPTOR_DATA * d, char *argument);
bool pager_output(DESCRIPTOR_DATA * d);
void mail_count(CHAR_DATA * ch);
void tax_player(CHAR_DATA * ch);
void mccp_interest(CHAR_DATA * ch);
bool check_total_ip(DESCRIPTOR_DATA * dnew);
void usage(void);

bool debug = false;


@@ 253,17 241,13 @@ main(int argc, char **argv)
		}
	}

	/*
         * Init time.
         */
	/* init time. */
	gettimeofday(&now_time, NULL);
	current_time = (time_t) now_time.tv_sec;
	boot_time = time(0);		/* <-- I think this is what you wanted */
	boot_time = time(0);
	strcpy(str_boot_time, ctime(&current_time));

	/*
         * Init boot time.
         */
	/* init boot time. */
	set_boot_time = &set_boot_time_struct;
	set_boot_time->manual = 0;



@@ 280,11 264,10 @@ main(int argc, char **argv)
	new_boot_time->tm_min = 0;
	new_boot_time->tm_hour = 4;

	/* Update new_boot_time (due to day increment) */
	/* update new_boot_time (due to day increment) */
	new_boot_time = update_time(new_boot_time);
	new_boot_struct = *new_boot_time;
	new_boot_time = &new_boot_struct;
	/* Bug fix submitted by Gabe Yoder */
	new_boot_time_t = mktime(new_boot_time);
	init_pfile_scan_time();		



@@ 293,14 276,13 @@ main(int argc, char **argv)
		exit(1);
	}

	/*
         * Run the game.
         */
        /* run the game. */
	log_string("Booting Database");
	boot_db();
	log_string("Initializing socket");
	control = init_socket(port);
	if (gethostname(hostn, sizeof(hostn)) < 0) {
		logmsg(LOG_ERR, "main: gethostname");
		perror("main: gethostname");
		strcpy(hostn, "unresolved");
	}


@@ 310,13 292,9 @@ main(int argc, char **argv)
	log_string(log_buf);

	game_loop();

	closesocket(control);

	/*
         * That's all, folks.
         */
	log_string("Normal termination of game.");
	log_string("normal termination of game.");
	return (0);
}



@@ 332,12 310,18 @@ init_socket(int port)
	gethostname(hostname, sizeof(hostname));

	if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
		perror("Init_socket: socket");
		perror("init_socket: socket");
		exit(1);
	}
	/* reuse addr for reconnect */
	if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,
		(void *) &x, sizeof(x)) < 0) {
		perror("Init_socket: SO_REUSEADDR");
		perror("init_socket: SO_REUSEADDR");
		closesocket(fd);
		exit(1);
	}
	if((fcntl(fd, F_SETFL, O_NONBLOCK) < 0)) {
		perror("init_socket: O_NONBLOCK");
		closesocket(fd);
		exit(1);
	}


@@ 347,12 331,12 @@ init_socket(int port)
	sa.sin_port = htons(port);

	if (bind(fd, (struct sockaddr *) & sa, sizeof(sa)) == -1) {
		perror("Init_socket: bind");
		perror("init_socket: bind");
		closesocket(fd);
		exit(1);
	}
	if (listen(fd, 50) < 0) {
		perror("Init_socket: listen");
		perror("init_socket: listen");
		closesocket(fd);
		exit(1);
	}


@@ 629,6 613,7 @@ game_loop()
	signal(SIGINT, sig_int);	
	signal(SIGHUP, sig_hup);	
	signal(SIGQUIT, sig_quit);	
	signal(SIGPIPE, SIG_IGN);	

	gettimeofday(&last_time, NULL);
	current_time = (time_t) last_time.tv_sec;


@@ 636,7 621,6 @@ game_loop()
	/* Main loop */
	while (!mud_down) {
		accept_new(control);

		/*
		 * Kick out descriptors with raised exceptions
		 * or have been idle, then check for input.


@@ 650,31 634,35 @@ game_loop()
			if (FD_ISSET(d->descriptor, &exc_set)) {
				FD_CLR(d->descriptor, &in_set);
				FD_CLR(d->descriptor, &out_set);
				if (d->character
				    && (d->connected == CON_PLAYING
					|| d->connected == CON_EDITING))
					save_char_obj(d->character);
				/* got descriptor, fquit */
				if (d->character) {
					log_string("preparing to fquit comm.c:652\n");
					fquit(d->character);
					continue;
				}
				d->outtop = 0;
				log_string("preparing to close socket at comm.c:658\n");
				log_string("preparing to close socket at comm.c:657\n");
				close_socket(d, true);
				continue;
			} else {
				d->fcommand = false;
				if (FD_ISSET(d->descriptor, &in_set)) {
					if (!read_from_descriptor(d)) {
						FD_CLR(d->descriptor, &out_set);
						if (d->character
						    && (d->connected == CON_PLAYING
						      || d->connected == CON_EDITING)) {
							save_char_obj(d->character);
							log_string("preparing to fquit comm.c:670\n");
							fquit(d->character);
							continue;
						}
					}
				     if (!read_from_descriptor(d)) {
					  FD_CLR(d->descriptor, &out_set);
					  if (d->character
					    && (d->connected == CON_PLAYING
					      || d->connected == CON_EDITING)) {
					       log_string("preparing to fquit comm.c:668\n");
					       fquit(d->character);
					       continue;
					  }
				     }
				}
				/* check for input from the dns */
				if ((d->connected == CON_PLAYING || d->character != NULL) && d->ifd != -1 && FD_ISSET(d->ifd, &in_set))
				if ((d->connected == CON_PLAYING
				    || d->character != NULL)
				    && d->ifd != -1
				    && FD_ISSET(d->ifd, &in_set))
					process_dns(d);
				if (d->character && d->character->wait > 0) {
					--d->character->wait;


@@ 683,14 671,11 @@ game_loop()
				read_from_buffer(d);
				if (d->incomm[0] != '\0') {
					d->fcommand = true;
					stop_idling(d->character);

					strcpy(cmdline, d->incomm);
					d->incomm[0] = '\0';

					if (d->character)
						set_cur_char(d->character);

					if (d->pagepoint)
						set_pager_input(d, cmdline);
					else


@@ 816,18 801,9 @@ new_descriptor(int new_desc)
		set_alarm(0);
		return;
	}
#if !defined(FNDELAY)
#define FNDELAY O_NDELAY
#endif

	set_alarm(20);
	alarm_section = "new_descriptor: after accept";

	if (fcntl(desc, F_SETFL, FNDELAY) == -1) {
		perror("New_descriptor: fcntl: FNDELAY");
		set_alarm(0);
		return;
	}
	if (check_bad_desc(new_desc))
		return;



@@ 835,7 811,7 @@ new_descriptor(int new_desc)
	dnew->next = NULL;
	dnew->descriptor = desc;
	dnew->connected = CON_GET_NAME;
	dnew->ansi = true;		/* force ansi */
	dnew->ansi = true;
	dnew->outsize = 2000;
	dnew->idle = 0;
	dnew->lines = 0;


@@ 874,14 850,6 @@ new_descriptor(int new_desc)
				last_descriptor = d;
	}
	LINK(dnew, first_descriptor, last_descriptor, next, prev);

#ifdef MCCP
	write_to_buffer(dnew, eor_on_str, 0);
	write_to_buffer(dnew, compress2_on_str, 0);
	write_to_buffer(dnew, compress_on_str, 0);
#endif


	/*
         * Send the greeting.
         */


@@ 917,14 885,10 @@ free_desc(DESCRIPTOR_DATA * d)
{
	closesocket(d->descriptor);
	DISPOSE(d->outbuf);
	STRFREE(d->user);		/* identd */
	/* identd */
	STRFREE(d->user);
	if (d->pagebuf)
		DISPOSE(d->pagebuf);

#ifdef MCCP
	compressEnd(d);
#endif

	DISPOSE(d);
	return;
}


@@ 935,7 899,6 @@ close_socket(DESCRIPTOR_DATA * dclose, bool force)
	CHAR_DATA *ch;
	DESCRIPTOR_DATA *d;
	bool do_not_unlink = false;
	OBJ_DATA *o;

	if (dclose->ipid != -1) {
		int 	status;


@@ 1013,42 976,12 @@ close_socket(DESCRIPTOR_DATA * dclose, bool force)
			do_not_unlink = true;
		}
	}
	if (dclose->character) {
		sprintf(log_buf, "Closing link to %s.", ch->pcdata->filename);
		log_string_plus(log_buf, LOG_COMM, UMAX(sysdata.log_level, ch->level));
		/* Link dead auth -- Rantic */
		if ((dclose->connected == CON_PLAYING
			|| dclose->connected == CON_EDITING)
		    || (dclose->connected >= CON_NOTE_TO
			&& dclose->connected <= CON_NOTE_FINISH)) {
			char 	ldbuf[MAX_STRING_LENGTH];

			act(AT_ACTION, "$n has lost $s link.", ch, NULL, NULL, TO_CANSEE);

			sprintf(ldbuf, "%s has gone linkdead", ch->name);
			while ((o = carrying_noquit(ch)) != NULL) {
				obj_from_char(o);
				obj_to_room(o, ch->in_room);
			}
			if (!IS_IMMORTAL(ch))
				do_info(ch, ldbuf);
			else
				do_ainfo(ch, ldbuf);
			ch->desc = NULL;
		} else {
			dclose->character->desc = NULL;
			free_char(dclose->character);
		}
	}
	if (!do_not_unlink) {
		/* make sure loop doesn't get messed up */
		if (d_next == dclose)
			d_next = d_next->next;
		UNLINK(dclose, first_descriptor, last_descriptor, next, prev);
	}
#ifdef MCCP
	compressEnd(dclose);
#endif
	if (dclose->descriptor == maxdesc)
		--maxdesc;
	free_desc(dclose);


@@ 1072,7 1005,7 @@ read_from_descriptor(DESCRIPTOR_DATA * d)
		sprintf(log_buf, "%s input overflow!", d->host);
		log_string(log_buf);
		write_to_descriptor(d->descriptor,
		    "\n\r*** PUT A LID ON IT!!! ***\n\rYou cannot enter the same command more than 20 consecutive times!\n\r", 0);
		    "\n\rYou cannot enter the same command more than 20 consecutive times!\n\r", 0);
		return (false);
	}
	for (;;) {


@@ 1102,37 1035,23 @@ read_from_descriptor(DESCRIPTOR_DATA * d)



/*
 * Transfer one line from input buffer to input line.
 */
/* transfer one line from input buffer to input line. */
void
read_from_buffer(DESCRIPTOR_DATA * d)
{
	int 	i , j, k;

#ifdef MCCP
	int 	iac = 0;

#endif

	/*
         * Hold horses if pending command already.
         */
	/* hold horses if pending command already. */
	if (d->incomm[0] != '\0')
		return;

	/*
         * Look for at least one new line.
         */
        /* look for at least one new line. */
	for (i = 0; d->inbuf[i] != '\n' && d->inbuf[i] != '\r' && i < MAX_INBUF_SIZE;
	    i++) {
		if (d->inbuf[i] == '\0')
			return;
	}

	/*
         * Canonical input processing.
         */
	/* canonical input processing. */
	for (i = 0, k = 0; d->inbuf[i] != '\n' && d->inbuf[i] != '\r'; i++) {
		int 	z = 0;



@@ 1146,76 1065,42 @@ read_from_buffer(DESCRIPTOR_DATA * d)
			d->inbuf[i + 1] = '\0';
			break;
		}
#ifdef MCCP
		if (d->inbuf[i] == (signed char) IAC)
			iac = 1;
		else if (iac == 1 && (d->inbuf[i] == (signed char) DO || d->inbuf[i] == (signed char) DONT))
			iac = 2;
		else if (iac == 2) {
			iac = 0;
			if (d->inbuf[i] == (signed char) TELOPT_COMPRESS) {
				if (d->inbuf[i - 1] == (signed char) DO)
					compressStart(d, TELOPT_COMPRESS);
				else if (d->inbuf[i - 1] == (signed char) DONT)
					compressEnd(d);
			} else if (d->inbuf[i] == (signed char) TELOPT_COMPRESS2) {
				if (d->inbuf[i - 1] == (signed char) DO)
					compressStart(d, TELOPT_COMPRESS2);
				else if (d->inbuf[i - 1] == (signed char) DONT)
					compressEnd(d);
			}
		} else
#endif

		if (d->inbuf[i] == '\b' && k > 0)
			--k;
		else if (isascii(d->inbuf[i]) && isprint(d->inbuf[i]))
			d->incomm[k++] = d->inbuf[i];
	}

	/*
         * Finish off the line.
         */
	/* finish off the line. */
	if (k == 0)
		d->incomm[k++] = ' ';
	d->incomm[k] = '\0';

	/*
         * Deal with bozos with #repeat 1000 ...
         */
	/* deal with bozos with #repeat 1000 */
	if (k > 1 || d->incomm[0] == '!') {
		if (d->incomm[0] != '!' && strcmp(d->incomm, d->inlast)) {
			d->repeat = 0;
		} else {
			if (++d->repeat >= 20) {
				write_to_descriptor(d->descriptor,
				    "\n\r*** PUT A LID ON IT!!! ***\n\rYou cannot enter the same command more than 20 consecutive times!\n\r", 0);
				    "\n\rYou cannot enter the same command more than 20 consecutive times!\n\r", 0);
				strcpy(d->incomm, "quit");
			}
		}
	}
	/*
         * Do '!' substitution.
         */
	/* do '!' substitution. */
	if (d->incomm[0] == '!')
		strcpy(d->incomm, d->inlast);
	else
		strcpy(d->inlast, d->incomm);

	/*
         * Shift the input buffer.
         */
	/* shift the input buffer. */
	while (d->inbuf[i] == '\n' || d->inbuf[i] == '\r')
		i++;
	for (j = 0; (d->inbuf[j] = d->inbuf[i + j]) != '\0'; j++);
	return;
}



/*
 * Low level output function.
 */
bool
flush_buffer(DESCRIPTOR_DATA * d, bool fPrompt)
{


@@ 1223,9 1108,7 @@ flush_buffer(DESCRIPTOR_DATA * d, bool fPrompt)
	char 	promptbuf[MAX_STRING_LENGTH];
	extern bool mud_down;

	/*
         * If buffer has more than 4K inside, spit out .5K at a time   -Thoric
         */
	/* if buffer has more than 4K inside, spit out .5K at a time   -Thoric */
	if (!mud_down && d->outtop > 4096) {
		memcpy(buf, d->outbuf, 512);
		d->outtop -= 512;


@@ 1250,9 1133,7 @@ flush_buffer(DESCRIPTOR_DATA * d, bool fPrompt)
		}
		return (true);
	}
	/*
         * Bust a prompt.
         */
	/* bust a prompt. */
	if (fPrompt && !mud_down && d->connected == CON_PLAYING) {
		CHAR_DATA *ch;



@@ 1299,22 1180,18 @@ flush_buffer(DESCRIPTOR_DATA * d, bool fPrompt)
			if (xIS_SET(ch->act, PLR_TELNET_GA))
				write_to_buffer(d, go_ahead_str, 0);
	}
	/*
         * Short-circuit if nothing to write.
         */
	/* short-circuit if nothing to write. */
	if (d->outtop == 0)
		return (true);

	/*
         * Snoop-o-rama.
         */
	/* snoop-o-rama. */
	if (d->snoop_by) {
		/*
		 * without check, 'force mortal quit' while snooped caused
		 * crash, -h
		 */
		if (d->character && d->character->name) {
			/* Show original snooped names. -- Altrag */
			/* show original snooped names. -- Altrag */
			if (d->original && d->original->name)
				sprintf(buf, "%s (%s)", d->character->name, d->original->name);
			else


@@ 1324,9 1201,7 @@ flush_buffer(DESCRIPTOR_DATA * d, bool fPrompt)
		write_to_buffer(d->snoop_by, "% ", 2);
		write_to_buffer(d->snoop_by, d->outbuf, d->outtop);
	}
	/*
         * OS-dependent output.
         */
	/* output */
	if (!write_to_descriptor(d->descriptor, d->outbuf, d->outtop)) {
		d->outtop = 0;
		return (false);


@@ 1345,7 1220,7 @@ void
write_to_buffer(DESCRIPTOR_DATA * d, const char *txt, int length)
{
	if (!d) {
		bug("Write_to_buffer: NULL descriptor");
		bug("write_to_buffer: NULL descriptor");
		return;
	}
	/*


@@ 1392,122 1267,29 @@ write_to_buffer(DESCRIPTOR_DATA * d, const char *txt, int length)
	return;
}

#ifdef MCCP
#define COMPRESS_BUF_SIZE 1024

bool
write_to_descriptor(int desc, char *txt, int length)
{
	DESCRIPTOR_DATA *d;
	int 	iStart = 0;
	int 	nWrite = 0;
	int 	nBlock;
	int 	len;
	int 	i_start;
	int 	n_write;
	int 	n_block;
	int	i_err;

	if (length <= 0)
		length = strlen(txt);

	for (d = first_descriptor; d; d = d->next)
		if (d->descriptor == desc)
			break;

	if (d && d->descriptor != desc)
		d = NULL;


	if (d && d->out_compress) {
		d->out_compress->next_in = (unsigned char *) txt;
		d->out_compress->avail_in = length;

		while (d->out_compress->avail_in) {
			d->out_compress->avail_out = COMPRESS_BUF_SIZE - (d->out_compress->next_out - d->out_compress_buf);

			if (d->out_compress->avail_out) {
				int 	status = deflate(d->out_compress, Z_SYNC_FLUSH);

				if (status != Z_OK)
					return (false);
			}
			len = d->out_compress->next_out - d->out_compress_buf;
			if (len > 0) {
				for (iStart = 0; iStart < len; iStart += nWrite) {
					nBlock = UMIN(len - iStart, 4096);
					if ((nWrite = write(d->descriptor, d->out_compress_buf + iStart, nBlock)) < 0) {
						perror("Write_to_descriptor: compressed");
						return (false);
					}
					if (!nWrite)
						break;
				}

				if (!iStart)
					break;

				if (iStart < len)
					memmove(d->out_compress_buf, d->out_compress_buf + iStart, len - iStart);

				d->out_compress->next_out = d->out_compress_buf + len - iStart;
			}
		}
		return (true);
	}
	for (iStart = 0; iStart < length; iStart += nWrite) {
		nBlock = UMIN(length - iStart, 4096);
		if ((nWrite = write(desc, txt + iStart, nBlock)) < 0) {
			perror("Write_to_descriptor");
			return (false);
		}
	}

	return (true);
}

#else

/*
 * Lowest level output function.
 * Write a block of text to the file descriptor.
 * If this gives errors on very long blocks (like 'ofind all'),
 *   try lowering the max block size.
 */
bool
write_to_descriptor(int desc, char *txt, int length)
{
	int 	iStart;
	int 	nWrite;
	int 	nBlock;

	if (length <= 0)
		length = strlen(txt);

	for (iStart = 0; iStart < length; iStart += nWrite) {
		nBlock = UMIN(length - iStart, 4096);
		if ((nWrite = send(desc, txt + iStart, nBlock, 0)) < 0) {
			perror("Write_to_descriptor");
			return (false);
		}
	}

	return (true);
}

#endif

/* Added to try to fix hotboot issue */
bool
write_to_descriptor_old(int desc, char *txt, int length)
{
	int 	iStart;
	int 	nWrite;
	int 	nBlock;

	if (length <= 0)
		length = strlen(txt);

	for (iStart = 0; iStart < length; iStart += nWrite) {
		nBlock = UMIN(length - iStart, 4096);
		if ((nWrite = send(desc, txt + iStart, nBlock, 0)) < 0) {
			perror("Write_to_descriptor");
	for (i_start = 0; i_start < length; i_start += n_write) {
		n_block = UMIN(length - i_start, 4096);
		n_write = send(desc, txt + i_start, n_block, 0);
		i_err = errno;
		/* broken pipe (linkdead) */
		if (i_err == EPIPE) {
		     logmsg(LOG_INFO, "broken pipe");
		     return (false);

		} else if (n_write  < 0) {
			logmsg(LOG_ERR, "write_to_descriptor");
			perror("write_to_descriptor");
			return (false);
		}
	}


@@ 1515,8 1297,6 @@ write_to_descriptor_old(int desc, char *txt, int length)
	return (true);
}

/* End added */

void
show_title(DESCRIPTOR_DATA * d)
{


@@ 1553,7 1333,7 @@ nanny(DESCRIPTOR_DATA * d, char *argument)
	char   *p;
	int 	b = 0;
	int 	iClass;
	bool 	fOld;
	bool 	f_old;
	bool 	blocked = false;
	NOTE_DATA *catchup_notes;
	int 	i = 0;


@@ 1623,12 1403,16 @@ nanny(DESCRIPTOR_DATA * d, char *argument)
			send_to_desc_color("\n\r\n\r&wName: ", d);
			return;
		}
		if (check_playing(d, argument, false) == true) {
			write_to_buffer(d, "Already playing, disconnecting.\n\r", 0);
			close_socket(d, false);
			return;
		/* brittle as fuck */
		f_old = load_char_obj(d, argument, true);
		if (f_old) {
		     if (check_playing(d, argument)) {
			  send_to_desc_color("&wPassword: &D", d);
			  write_to_buffer(d, echo_off_str, 0);
			  d->connected = CON_GET_OLD_PASSWORD;
			  return;
		     }
		}
		fOld = load_char_obj(d, argument, true);
		if (!d->character) {
			sprintf(log_buf, "Bad player file %s@%s.", argument, d->host);
			log_string(log_buf);


@@ 1663,7 1447,7 @@ nanny(DESCRIPTOR_DATA * d, char *argument)
			close_socket(d, false);
			return;
		}
		if (fOld) {
		if (f_old) {
			if (d->newstate != 0) {
				send_to_desc_color("&wThat name is already taken. Please choose another: &D", d);
				d->connected = CON_GET_NAME;


@@ 1702,13 1486,20 @@ nanny(DESCRIPTOR_DATA * d, char *argument)
			return;
		}
		write_to_buffer(d, echo_on_str, 0);
		if (check_playing(d, ch->pcdata->filename, true))
			return;
		if (check_playing(d, ch->pcdata->filename)) {
		     if (!(reconnect(d, ch->pcdata->filename))) {
			  write_to_buffer(d, "error, disconnecting.\n\r", 0);
			  d->character->desc = NULL;
			  close_socket(d, false);
			  return;
		     }
		     break;
		}
		strncpy(buf, ch->pcdata->filename, MAX_STRING_LENGTH);
		d->character->desc = NULL;
		free_char(d->character);
		d->character = NULL;
		fOld = load_char_obj(d, buf, false);
		f_old = load_char_obj(d, buf, false);
		ch = d->character;
		if (ch->position > POS_SITTING && ch->position < POS_STANDING)
			ch->position = POS_STANDING;


@@ 2443,8 2234,7 @@ nanny(DESCRIPTOR_DATA * d, char *argument)
			d->ansi = true;

		if (ch->level == 0) {
			OBJ_DATA *obj;
			int 	iLang;
			int 	i_lang;

			ch->pcdata->upgradeL = CURRENT_UPGRADE_LEVEL;



@@ 2493,20 2283,20 @@ nanny(DESCRIPTOR_DATA * d, char *argument)
			ch->height = number_range(race_table[ch->race]->height * .9, race_table[ch->race]->height * 1.1);
			ch->weight = number_range(race_table[ch->race]->weight * .9, race_table[ch->race]->weight * 1.1);

			if ((iLang = skill_lookup("common")) < 0)
			if ((i_lang = skill_lookup("common")) < 0)
				bug("Nanny: cannot find common language.");
			else
				ch->pcdata->learned[iLang] = 100;
				ch->pcdata->learned[i_lang] = 100;

			for (iLang = 0; lang_array[iLang] != LANG_UNKNOWN; iLang++)
				if (lang_array[iLang] == race_table[ch->race]->language)
			for (i_lang = 0; lang_array[i_lang] != LANG_UNKNOWN; i_lang++)
				if (lang_array[i_lang] == race_table[ch->race]->language)
					break;
			if (lang_array[iLang] == LANG_UNKNOWN);
			if (lang_array[i_lang] == LANG_UNKNOWN);
			else {
				if ((iLang = skill_lookup(lang_names[iLang])) < 0)
				if ((i_lang = skill_lookup(lang_names[i_lang])) < 0)
					bug("Nanny: cannot find racial language.");
				else
					ch->pcdata->learned[iLang] = 100;
					ch->pcdata->learned[i_lang] = 100;
			}

			name_stamp_stats(ch);


@@ 2730,52 2520,17 @@ check_parse_name(char *name, bool newchar)
	return (true);
}



/*
 * Look for link-dead player to reconnect.
 */
bool
check_reconnect(DESCRIPTOR_DATA * d, char *name, bool fConn)
check_playing(DESCRIPTOR_DATA * d, char *name)
{
	CHAR_DATA *ch;

	for (ch = first_char; ch; ch = ch->next) {
		if (!IS_NPC(ch)
		    && (!fConn || !ch->desc)
		    && ch->pcdata->filename
		    && !str_cmp(name, ch->pcdata->filename)) {
			if (fConn && ch->switched) {
				write_to_buffer(d, "Already playing.\n\rName: ", 0);
				d->connected = CON_GET_NAME;
				if (d->character) {
					d->character->desc = NULL;
					free_char(d->character);
					d->character = NULL;
				}
				/* didn't find the character, disconnect */
				return (false);
			}
			if (fConn == false) {
				DISPOSE(d->character->pcdata->pwd);
				d->character->pcdata->pwd = str_dup(ch->pcdata->pwd);
			} else {
				d->character->desc = NULL;
				free_char(d->character);
				d->character = ch;
				ch->desc = d;
				ch->timer = 0;
				send_to_char("Reconnecting.\n\r", ch);
				do_look(ch, "auto");
				act(AT_ACTION, "$n has reconnected.", ch, NULL, NULL, TO_CANSEE);
				sprintf(log_buf, "%s@%s(%s) reconnected.",
				    ch->pcdata->filename, d->host, d->user);
				log_string_plus(log_buf, LOG_COMM, UMAX(sysdata.log_level, ch->level));
				d->connected = CON_PLAYING;
				if (ch->pcdata->in_progress)
					send_to_char("You have a note in progress. Type \"note write\" to continue it.\n\r", ch);

			}
	DESCRIPTOR_DATA *d_old;

	for (d_old = first_descriptor; d_old; d_old = d_old->next) {
		if (d_old != d
		    && (d_old->character || d_old->original)
		    && !str_cmp(name, d_old->original
			? d_old->original->pcdata->filename :
			d_old->character->pcdata->filename)) {
			return (true);
		}
	}


@@ 2783,43 2538,24 @@ check_reconnect(DESCRIPTOR_DATA * d, char *name, bool fConn)
	return (false);
}



/*
 * Check if already playing.
 */
bool
check_playing(DESCRIPTOR_DATA * d, char *name, bool kick)
{
reconnect(DESCRIPTOR_DATA * d, char *name) {
	CHAR_DATA *ch;

	DESCRIPTOR_DATA *dold;
	int 	cstate;

	for (dold = first_descriptor; dold; dold = dold->next) {
		if (dold != d
		    && (dold->character || dold->original)
		    && !str_cmp(name, dold->original
			? dold->original->pcdata->filename :
			dold->character->pcdata->filename)) {
			cstate = dold->connected;
			ch = dold->original ? dold->original : dold->character;
			if (!ch->name
			    || (cstate != CON_PLAYING && cstate != CON_EDITING)) {
				write_to_buffer(d, "Already connected - try again.\n\r", 0);
				sprintf(log_buf, "%s already connected.",
				    ch->pcdata->filename);
				log_string_plus(log_buf, LOG_COMM, sysdata.log_level);
				return (true);
			}
			if (!kick)
				return (true);
	DESCRIPTOR_DATA *d_old;
	int 	conn_state;

	for (d_old = first_descriptor; d_old; d_old = d_old->next) {
		if (d_old != d
		    && (d_old->character || d_old->original)
		    && !str_cmp(name, d_old->original
			? d_old->original->pcdata->filename :
			d_old->character->pcdata->filename)) {
			conn_state = d_old->connected;
			ch = d_old->original ? d_old->original : d_old->character;
			write_to_buffer(d, "Already playing... Kicking off old connection.\n\r", 0);
			write_to_buffer(dold, "Kicking off old connection... bye!\n\r", 0);
			write_to_buffer(d_old, "Kicking off old connection... bye!\n\r", 0);
			log_string("preparing to close socket at comm.c:2824\n");
			close_socket(dold, false);
			d->character->desc = NULL;
			free_char(d->character);
			close_socket(d_old, false);
			d->character = ch;
			ch->desc = d;
			ch->timer = 0;


@@ 2833,42 2569,14 @@ check_playing(DESCRIPTOR_DATA * d, char *name, bool kick)
			sprintf(log_buf, "%s@%s reconnected, kicking off old link.",
			    ch->pcdata->filename, d->host);
			log_string_plus(log_buf, LOG_COMM, UMAX(sysdata.log_level, ch->level));
			d->connected = cstate;
			d->connected = conn_state;
			return (true);
		}
	}

	return (false);
}



void
stop_idling(CHAR_DATA * ch)
{
	ROOM_INDEX_DATA *was_in_room;

	if (!ch
	    || !ch->desc
	    || ch->desc->connected != CON_PLAYING
	    || !IS_IDLE(ch))
		return;

	ch->timer = 0;
	was_in_room = ch->was_in_room;
	char_from_room(ch);
	char_to_room(ch, was_in_room);
	ch->was_in_room = ch->in_room;
	REMOVE_BIT(ch->pcdata->flags, PCFLAG_IDLE);
	act(AT_ACTION, "$n has returned from the void.", ch, NULL, NULL, TO_ROOM);
	return;
}



/*
 * Write to one char. (update for color -Goku)
 */
  
void
send_to_char(const char *txt, CHAR_DATA * ch)
{


@@ 2880,9 2588,6 @@ send_to_char(const char *txt, CHAR_DATA * ch)
	return;
}

/*
 * Same as above, but converts &color codes to ANSI sequences..
 */
void
send_to_char_color(const char *txt, CHAR_DATA * ch)
{


@@ 3458,7 3163,6 @@ act(sh_int AType, const char *format, CHAR_DATA * ch, const void *arg1, const vo
			&& (IS_NPC(to) && !HAS_PROG(to->pIndexData, ACT_PROG)))
		    || !IS_AWAKE(to))
			continue;

		if (type == TO_CHAR && to != ch)
			continue;
		if (type == TO_VICT && (to != vch || to == ch))


@@ 4778,197 4482,3 @@ act2(sh_int AType, const char *format, CHAR_DATA * ch, const void *arg1, const v
	MOBtrigger = true;
	return;
}


#ifdef MCCP
/*
 * Ported to SMAUG by Garil of DOTDII Mud
 * aka Jesse DeFer <dotd@dotd.com>  http://www.dotd.com
 *
 * revision 1: MCCP v1 support
 * revision 2: MCCP v2 support
 * revision 3: Correct MMCP v2 support
 * revision 4: clean up of write_to_descriptor() suggested by Noplex@CB
 *
 * See the web site below for more info.
 */

/*
 * mccp.c - support functions for mccp (the Mud Client Compression Protocol)
 *
 * see http://homepages.ihug.co.nz/~icecube/compress/ and README.Rom24-mccp
 *
 * Copyright (c) 1999, Oliver Jowett <icecube@ihug.co.nz>.
 *
 * This code may be freely distributed and used if this copyright notice is
 * retained intact.
 */

void   *
zlib_alloc(void *opaque, unsigned int items, unsigned int size)
{
	return (calloc(items, size));
}

void
zlib_free(void *opaque, void *address)
{
	DISPOSE(address);
}

bool
process_compressed(DESCRIPTOR_DATA * d)
{
	int 	iStart = 0, nBlock, nWrite, len;

	if (!d->out_compress)
		return (true);

	//Try to write out some data..
	    len = d->out_compress->next_out - d->out_compress_buf;

	if (len > 0) {
		//we have some data to write
		    for (iStart = 0; iStart < len; iStart += nWrite) {
			nBlock = UMIN(len - iStart, 4096);
			if ((nWrite = write(d->descriptor, d->out_compress_buf + iStart, nBlock)) < 0) {
				if (errno == EAGAIN ||
				    errno == ENOSR)
					break;

				return (false);
			}
			if (!nWrite)
				break;
		}

		if (iStart) {
			//We wrote "iStart" bytes
			    if (iStart < len)
				memmove(d->out_compress_buf, d->out_compress_buf + iStart, len - iStart);

			d->out_compress->next_out = d->out_compress_buf + len - iStart;
		}
	}
	return (true);
}

char 	enable_compress[] =
{
	IAC, SB, TELOPT_COMPRESS, WILL, SE, 0
};
char 	enable_compress2[] =
{
	IAC, SB, TELOPT_COMPRESS2, IAC, SE, 0
};

bool
compressStart(DESCRIPTOR_DATA * d, unsigned char telopt)
{
	z_stream *s;
	char 	buf[MAX_INPUT_LENGTH];

	if (d->out_compress)
		return (true);

	sprintf(buf, "Starting compression for descriptor %d", d->descriptor);
	log_string_plus(buf, LOG_COMM, LEVEL_SUPREME);

	CREATE(s, z_stream, 1);
	CREATE(d->out_compress_buf, unsigned char, COMPRESS_BUF_SIZE);

	s->next_in = NULL;
	s->avail_in = 0;

	s->next_out = d->out_compress_buf;
	s->avail_out = COMPRESS_BUF_SIZE;

	s->zalloc = zlib_alloc;
	s->zfree = zlib_free;
	s->opaque = NULL;

	if (deflateInit(s, 9) != Z_OK) {
		DISPOSE(d->out_compress_buf);
		DISPOSE(s);
		return (false);
	}
	if (telopt == TELOPT_COMPRESS)
		write_to_descriptor(d->descriptor, enable_compress, 0);
	else if (telopt == TELOPT_COMPRESS2)
		write_to_descriptor(d->descriptor, enable_compress2, 0);
	else
		bug("compressStart: bad TELOPT passed");

	d->compressing = telopt;
	d->out_compress = s;

	return (true);
}

bool
compressEnd(DESCRIPTOR_DATA * d)
{
	unsigned char dummy[1];
	char 	buf[MAX_INPUT_LENGTH];

	if (!d->out_compress)
		return (true);

	sprintf(buf, "Stopping compression for descriptor %d", d->descriptor);
	log_string_plus(buf, LOG_COMM, LEVEL_SUPREME);

	d->out_compress->avail_in = 0;
	d->out_compress->next_in = dummy;

	if (deflate(d->out_compress, Z_FINISH) != Z_STREAM_END)
		return (false);

	if (!process_compressed(d))	/* try to send any residual data */
		return (false);

	deflateEnd(d->out_compress);
	DISPOSE(d->out_compress_buf);
	DISPOSE(d->out_compress);
	d->compressing = 0;

	return (true);
}

void
do_compress(CHAR_DATA * ch, char *argument)
{
	char 	arg[MAX_STRING_LENGTH];

	if (!ch->desc) {
		send_to_char("What descriptor?!\n", ch);
		return;
	}
	argument = one_argument(argument, arg);

	if (!str_cmp(arg, "on")) {
		send_to_char("Initiating compression....", ch);
		compressStart(ch->desc, TELOPT_COMPRESS2);
		if (!ch->desc->out_compress)
			send_to_char("failure\n\r", ch);
		else
			send_to_char("success\n\r", ch);
	} else if (!str_cmp(arg, "off")) {
		send_to_char("Terminating compression...", ch);
		compressEnd(ch->desc);
		if (!ch->desc->out_compress)
			send_to_char("success\n\r", ch);
		else
			send_to_char("failure\n\r", ch);
	} else {
		send_to_char("Syntax: compression <on/off>\n\r", ch);
		send_to_char("MCCP compression is currently: ", ch);
		if (!ch->desc->out_compress)
			send_to_char("Off\n\r", ch);
		else
			send_to_char("On\n\r", ch);
	}

	return;
}

#endif

M src/fight.c => src/fight.c +1 -3
@@ 1252,12 1252,10 @@ one_hit(CHAR_DATA * ch, CHAR_DATA * victim, int dt)

	if (wield)
		prof_bonus = 0;
	/* Aparently this was screwing things way up - Karma */
	/* prof_bonus = weapon_prof_bonus_check( ch, wield, &prof_gsn ); */
	else
		prof_bonus = 0;

	if (ch->fighting		/* make sure fight is already started */
	if (ch->fighting	
	    && dt == TYPE_UNDEFINED && IS_NPC(ch) && !xIS_EMPTY(ch->attacks)) {
		cnt = 0;
		for (;;) {

M src/handler.c => src/handler.c +3510 -3420
@@ 24,212 24,207 @@
#include "mud.h"


extern int		top_exit;
extern int		top_ed;
extern int		top_affect;
extern int		cur_qobjs;
extern int		cur_qchars;
extern CHAR_DATA *	gch_prev;
extern OBJ_DATA  *	gobj_prev;
extern int top_exit;
extern int top_ed;
extern int top_affect;
extern int cur_qobjs;
extern int cur_qchars;
extern CHAR_DATA *gch_prev;
extern OBJ_DATA *gobj_prev;

CHAR_DATA	*cur_char;
ROOM_INDEX_DATA	*cur_room;
bool		 cur_char_died;
ch_ret		 global_retcode;
CHAR_DATA *cur_char;
ROOM_INDEX_DATA *cur_room;
bool 	cur_char_died;
ch_ret 	global_retcode;

int		 cur_obj;
int		 cur_obj_serial;
bool		 cur_obj_extracted;
obj_ret		 global_objcode;
int 	cur_obj;
int 	cur_obj_serial;
bool 	cur_obj_extracted;
obj_ret global_objcode;

OBJ_DATA *group_object( OBJ_DATA *obj1, OBJ_DATA *obj2 );
bool in_magic_container( OBJ_DATA *obj );
OBJ_DATA *group_object(OBJ_DATA * obj1, OBJ_DATA * obj2);
bool 	in_magic_container(OBJ_DATA * obj);



/*
 * Return how much exp a char has
 */
int get_exp( CHAR_DATA *ch )
int 
get_exp(CHAR_DATA * ch)
{
    return ch->exp;
	return ch->exp;
}

/*
 * Calculate roughly how much experience a character is worth
 */
int get_exp_worth( CHAR_DATA *ch )
int 
get_exp_worth(CHAR_DATA * ch)
{
    int exp = 0;
	int 	exp = 0;

/* arg!  all this requires stuff that won't be used any more! REWRITE!

    exp = ch->level * ch->level * ch->level * 5;
    exp += ch->max_hit;
    exp -= (ch->armor-50) * 2;
    exp += ( ch->barenumdie * ch->baresizedie + GET_DAMROLL(ch) ) * 50;
    exp += GET_HITROLL(ch) * ch->level * 10;
    if ( IS_AFFECTED(ch, AFF_SANCTUARY) )
      exp += exp * 1.5;
    if ( IS_AFFECTED(ch, AFF_FIRESHIELD) )
      exp += exp * 1.2;
    if ( IS_AFFECTED(ch, AFF_SHOCKSHIELD) )
      exp += exp * 1.2;
    exp = URANGE( MIN_EXP_WORTH, exp, MAX_EXP_WORTH );

*/
	if ( !IS_NPC(ch) )
	if (!IS_NPC(ch))
		exp = ch->pl;
	if ( IS_NPC(ch) )
	if (IS_NPC(ch))
		exp = ch->exp;
    exp = URANGE( MIN_EXP_WORTH, exp, MAX_EXP_WORTH );
    return exp;
	exp = URANGE(MIN_EXP_WORTH, exp, MAX_EXP_WORTH);
	return exp;
}

sh_int get_exp_base( CHAR_DATA *ch )
sh_int 
get_exp_base(CHAR_DATA * ch)
{
    if ( IS_NPC(ch) )
      return 1000;
    return class_table[ch->class]->exp_base;
	if (IS_NPC(ch))
		return 1000;
	return class_table[ch->class]->exp_base;
}

/*								-Thoric
 * Return how much experience is required for ch to get to a certain level
 */
int exp_level( CHAR_DATA *ch, sh_int level )
int 
exp_level(CHAR_DATA * ch, sh_int level)
{
   int lvl;
	int 	lvl;

   lvl = UMAX(0, level - 1);
   return ( lvl * lvl * lvl * get_exp_base(ch) );
	lvl = UMAX(0, level - 1);
	return (lvl * lvl * lvl * get_exp_base(ch));
}

/*
 * Get what level ch is based on exp
 */
sh_int level_exp( CHAR_DATA *ch, int exp )
sh_int 
level_exp(CHAR_DATA * ch, int exp)
{
    int x, lastx, y, tmp;
	int 	x , lastx, y, tmp;

    x = LEVEL_SUPREME;
    lastx = x;
    y = 0;
    while ( !y )
    {
	tmp = exp_level(ch, x);
	x = LEVEL_SUPREME;
	lastx = x;
	if ( tmp > exp )
	  x /= 2;
	else
	if (lastx != x )
	  x += ( x / 2 );
	else
	  y = x;
    }
    if ( y < 1 )
      y = 1;
    if ( y > LEVEL_SUPREME )
      y = LEVEL_SUPREME;
    return y;
	y = 0;
	while (!y) {
		tmp = exp_level(ch, x);
		lastx = x;
		if (tmp > exp)
			x /= 2;
		else if (lastx != x)
			x += (x / 2);
		else
			y = x;
	}
	if (y < 1)
		y = 1;
	if (y > LEVEL_SUPREME)
		y = LEVEL_SUPREME;
	return y;
}

/*
 * Retrieve a character's trusted level for permission checking.
 */
sh_int get_trust( CHAR_DATA *ch )
sh_int 
get_trust(CHAR_DATA * ch)
{
    if ( ch->desc && ch->desc->original )
	ch = ch->desc->original;
	if (ch->desc && ch->desc->original)
		ch = ch->desc->original;

    if ( ch->trust != 0 )
	return ch->trust;
	if (ch->trust != 0)
		return ch->trust;

    if ( IS_NPC(ch) && ch->level >= LEVEL_AVATAR )
	return LEVEL_AVATAR;
	if (IS_NPC(ch) && ch->level >= LEVEL_AVATAR)
		return LEVEL_AVATAR;

    if ( ch->level >= LEVEL_NEOPHYTE && IS_RETIRED( ch ) )
      return LEVEL_NEOPHYTE;
	if (ch->level >= LEVEL_NEOPHYTE && IS_RETIRED(ch))
		return LEVEL_NEOPHYTE;

    return ch->level;
	return ch->level;
}


/*
 * Retrieve a character's age.
 */
sh_int get_age( CHAR_DATA *ch )
sh_int 
get_age(CHAR_DATA * ch)
{
	    return 4 + ( ch->played + (current_time - ch->logon) ) / 7200;
	return 4 + (ch->played + (current_time - ch->logon)) / 7200;
}

/*
 * Retrieve character's current strength.
 */
sh_int get_curr_str( CHAR_DATA *ch )
sh_int 
get_curr_str(CHAR_DATA * ch)
{
    return UMAX( (ch->perm_str + ch->mod_str), 1 );
	return UMAX((ch->perm_str + ch->mod_str), 1);
}

/*
 * Retrieve character's current intelligence.
 */
sh_int get_curr_int( CHAR_DATA *ch )
sh_int 
get_curr_int(CHAR_DATA * ch)
{
    return UMAX( (ch->perm_int + ch->mod_int), 1 );
	return UMAX((ch->perm_int + ch->mod_int), 1);
}

/*
 * Retrieve character's current dexterity.
 */
sh_int get_curr_dex( CHAR_DATA *ch )
sh_int 
get_curr_dex(CHAR_DATA * ch)
{
    return UMAX( (ch->perm_dex + ch->mod_dex), 1 );
	return UMAX((ch->perm_dex + ch->mod_dex), 1);
}

/*
 * Retrieve character's current constitution.
 */
sh_int get_curr_con( CHAR_DATA *ch )
sh_int 
get_curr_con(CHAR_DATA * ch)
{
    return UMAX( (ch->perm_con + ch->mod_con), 1 );
	return UMAX((ch->perm_con + ch->mod_con), 1);
}

/*
 * Retrieve character's current luck.
 */
sh_int get_curr_lck( CHAR_DATA *ch )
sh_int 
get_curr_lck(CHAR_DATA * ch)
{
    return UMAX( (ch->perm_lck + ch->mod_lck), 1 );
	return UMAX((ch->perm_lck + ch->mod_lck), 1);
}

/*
 * Retrieve a character's carry capacity.
 * Vastly reduced (finally) due to containers		-Thoric
 */
int can_carry_n( CHAR_DATA *ch )
int 
can_carry_n(CHAR_DATA * ch)
{
    int penalty = 0;
	int 	penalty = 0;

    if ( !IS_NPC(ch) && ch->level >= LEVEL_IMMORTAL )
	return get_trust(ch)*200;
	if (!IS_NPC(ch) && ch->level >= LEVEL_IMMORTAL)
		return get_trust(ch) * 200;

    if ( IS_NPC(ch) && xIS_SET(ch->act, ACT_PET) )
	return 0;
	if (IS_NPC(ch) && xIS_SET(ch->act, ACT_PET))
		return 0;

    if ( IS_NPC(ch) && xIS_SET(ch->act, ACT_IMMORTAL) )
	return ch->level*200;
	if (IS_NPC(ch) && xIS_SET(ch->act, ACT_IMMORTAL))
		return ch->level * 200;

    if ( get_eq_char(ch, WEAR_WIELD) )
      ++penalty;
    if ( get_eq_char(ch, WEAR_DUAL_WIELD) )
      ++penalty;
    if ( get_eq_char(ch, WEAR_MISSILE_WIELD) )
      ++penalty;
    if ( get_eq_char(ch, WEAR_HOLD) )
      ++penalty;
    if ( get_eq_char(ch, WEAR_SHIELD) )
      ++penalty;
    return URANGE(5, ( (get_curr_str(ch)/5) - penalty ), 20);
	if (get_eq_char(ch, WEAR_WIELD))
		++penalty;
	if (get_eq_char(ch, WEAR_DUAL_WIELD))
		++penalty;
	if (get_eq_char(ch, WEAR_MISSILE_WIELD))
		++penalty;
	if (get_eq_char(ch, WEAR_HOLD))
		++penalty;
	if (get_eq_char(ch, WEAR_SHIELD))
		++penalty;
	return URANGE(5, ((get_curr_str(ch) / 5) - penalty), 20);
}




@@ 237,168 232,165 @@ int can_carry_n( CHAR_DATA *ch )
/*
 * Retrieve a character's carry capacity.
 */
int can_carry_w( CHAR_DATA *ch )
int 
can_carry_w(CHAR_DATA * ch)
{
    if ( !IS_NPC(ch) && ch->level >= LEVEL_IMMORTAL )
	return 1000000;
	if (!IS_NPC(ch) && ch->level >= LEVEL_IMMORTAL)
		return 1000000;

    if ( IS_NPC(ch) && xIS_SET(ch->act, ACT_PET) )
	return 0;
	if (IS_NPC(ch) && xIS_SET(ch->act, ACT_PET))
		return 0;

    if ( IS_NPC(ch) && xIS_SET(ch->act, ACT_IMMORTAL) )
	return 1000000;
	if (IS_NPC(ch) && xIS_SET(ch->act, ACT_IMMORTAL))
		return 1000000;

    return ( get_curr_str(ch) * 5 );
	return (get_curr_str(ch) * 5);
}


/*
 * See if a player/mob can take a piece of prototype eq		-Thoric
 */
bool can_take_proto( CHAR_DATA *ch )
bool 
can_take_proto(CHAR_DATA * ch)
{
    if ( IS_IMMORTAL(ch) )
	return true;
    else
    if ( IS_NPC(ch) && xIS_SET(ch->act, ACT_PROTOTYPE) )
	return true;
    else
	return false;
	if (IS_IMMORTAL(ch))
		return true;
	else if (IS_NPC(ch) && xIS_SET(ch->act, ACT_PROTOTYPE))
		return true;
	else
		return false;
}


/*
 * See if a string is one of the names of an object.
 */
bool is_name( const char *str, char *namelist )
bool 
is_name(const char *str, char *namelist)
{
    char name[MAX_INPUT_LENGTH];
	char 	name[MAX_INPUT_LENGTH];

    for ( ; ; )
    {
	namelist = one_argument( namelist, name );
	if ( name[0] == '\0' )
	    return false;
	if ( !str_cmp( str, name ) )
	    return true;
    }
	for (;;) {
		namelist = one_argument(namelist, name);
		if (name[0] == '\0')
			return false;
		if (!str_cmp(str, name))
			return true;
	}
}

bool is_name_prefix( const char *str, char *namelist )
bool 
is_name_prefix(const char *str, char *namelist)
{
    char name[MAX_INPUT_LENGTH];
	char 	name[MAX_INPUT_LENGTH];

    for ( ; ; )
    {
	namelist = one_argument( namelist, name );
	if ( name[0] == '\0' )
	    return false;
	if ( !str_prefix( str, name ) )
	    return true;
    }
	for (;;) {
		namelist = one_argument(namelist, name);
		if (name[0] == '\0')
			return false;
		if (!str_prefix(str, name))
			return true;
	}
}

/*
 * See if a string is one of the names of an object.		-Thoric
 * Treats a dash as a word delimiter as well as a space
 */
bool is_name2( const char *str, char *namelist )
bool 
is_name2(const char *str, char *namelist)
{
    char name[MAX_INPUT_LENGTH];
	char 	name[MAX_INPUT_LENGTH];

    for ( ; ; )
    {
	namelist = one_argument2( namelist, name );
	if ( name[0] == '\0' )
	    return false;
	if ( !str_cmp( str, name ) )
	    return true;
    }
	for (;;) {
		namelist = one_argument2(namelist, name);
		if (name[0] == '\0')
			return false;
		if (!str_cmp(str, name))
			return true;
	}
}

bool is_name2_prefix( const char *str, char *namelist )
bool 
is_name2_prefix(const char *str, char *namelist)
{
    char name[MAX_INPUT_LENGTH];
	char 	name[MAX_INPUT_LENGTH];

    for ( ; ; )
    {
	namelist = one_argument2( namelist, name );
	if ( name[0] == '\0' )
	    return false;
	if ( !str_prefix( str, name ) )
	    return true;
    }
	for (;;) {
		namelist = one_argument2(namelist, name);
		if (name[0] == '\0')
			return false;
		if (!str_prefix(str, name))
			return true;
	}
}

/*								-Thoric
 * Checks if str is a name in namelist supporting multiple keywords
 */
bool nifty_is_name( char *str, char *namelist )
bool 
nifty_is_name(char *str, char *namelist)
{
    char name[MAX_INPUT_LENGTH];
	char 	name[MAX_INPUT_LENGTH];

    if ( !str || str[0] == '\0' )
      return false;
	if (!str || str[0] == '\0')
		return false;

    for ( ; ; )
    {
	str = one_argument2( str, name );
	if ( name[0] == '\0' )
	    return true;
	if ( !is_name2( name, namelist ) )
	    return false;
    }
	for (;;) {
		str = one_argument2(str, name);
		if (name[0] == '\0')
			return true;
		if (!is_name2(name, namelist))
			return false;
	}
}

bool nifty_is_name_prefix( char *str, char *namelist )
bool 
nifty_is_name_prefix(char *str, char *namelist)
{
    char name[MAX_INPUT_LENGTH];
	char 	name[MAX_INPUT_LENGTH];

    if ( !str || str[0] == '\0' )
      return false;
	if (!str || str[0] == '\0')
		return false;

    for ( ; ; )
    {
	str = one_argument2( str, name );
	if ( name[0] == '\0' )
	    return true;
	if ( !is_name2_prefix( name, namelist ) )
	    return false;
    }
	for (;;) {
		str = one_argument2(str, name);
		if (name[0] == '\0')
			return true;
		if (!is_name2_prefix(name, namelist))
			return false;
	}
}

void room_affect( ROOM_INDEX_DATA *pRoomIndex, AFFECT_DATA *paf, bool fAdd )
void 
room_affect(ROOM_INDEX_DATA * pRoomIndex, AFFECT_DATA * paf, bool fAdd)
{
    if ( fAdd )
    {
	switch(paf->location)
	{
	    case APPLY_ROOMFLAG:
	    case APPLY_SECTORTYPE:
		break;
	    case APPLY_ROOMLIGHT:
		pRoomIndex->light += paf->modifier;
		break;
	    case APPLY_TELEVNUM:
	    case APPLY_TELEDELAY:
		break;
	}
    }
    else
    {
	switch(paf->location)
	{
	    case APPLY_ROOMFLAG:
	    case APPLY_SECTORTYPE:
		break;
	    case APPLY_ROOMLIGHT:
		pRoomIndex->light -= paf->modifier;
		break;
	    case APPLY_TELEVNUM:
	    case APPLY_TELEDELAY:
		break;
	if (fAdd) {
		switch (paf->location) {
			case APPLY_ROOMFLAG:
			case APPLY_SECTORTYPE:
			break;
		case APPLY_ROOMLIGHT:
			pRoomIndex->light += paf->modifier;
			break;
		case APPLY_TELEVNUM:
		case APPLY_TELEDELAY:
			break;
		}
	} else {
		switch (paf->location) {
		case APPLY_ROOMFLAG:
		case APPLY_SECTORTYPE:
			break;
		case APPLY_ROOMLIGHT:
			pRoomIndex->light -= paf->modifier;
			break;
		case APPLY_TELEVNUM:
		case APPLY_TELEDELAY:
			break;
		}
	}
    }
}

/*


@@ 407,282 399,388 @@ void room_affect( ROOM_INDEX_DATA *pRoomIndex, AFFECT_DATA *paf, bool fAdd )
 * On "adding" a skill modifying affect, the value set is unimportant
 * upon removing the affect, the skill it enforced to a proper range.
 */
void modify_skill( CHAR_DATA *ch, int sn, int mod, bool fAdd )
void 
modify_skill(CHAR_DATA * ch, int sn, int mod, bool fAdd)
{
    if ( !IS_NPC(ch) )
    {
	if ( fAdd )
	    ch->pcdata->learned[sn] += mod;
	else
	    ch->pcdata->learned[sn] = URANGE(0, ch->pcdata->learned[sn] + mod,
		GET_ADEPT(ch, sn));
    }
	if (!IS_NPC(ch)) {
		if (fAdd)
			ch->pcdata->learned[sn] += mod;
		else
			ch->pcdata->learned[sn] = URANGE(0, ch->pcdata->learned[sn] + mod,
			    GET_ADEPT(ch, sn));
	}
}

/*
 * Apply or remove an affect to a character.
 */
void affect_modify( CHAR_DATA *ch, AFFECT_DATA *paf, bool fAdd )
{
    OBJ_DATA *wield;
    int mod;
    struct skill_type *skill;
    ch_ret retcode;

    mod = paf->modifier;

    if ( fAdd )
    {
	xSET_BITS( ch->affected_by, paf->bitvector );
		if ( paf->location % REVERSE_APPLY == APPLY_RECURRINGSPELL )
		{
	    mod = abs(mod);
	    if ( IS_VALID_SN(mod)
	    &&  (skill=skill_table[mod]) != NULL
	    &&   skill->type == SKILL_SPELL)
		xSET_BIT(ch->affected_by, AFF_RECURRINGSPELL);
	    else
	        bug( "affect_modify(%s) APPLY_RECURRINGSPELL with bad sn %d",
		    ch->name, mod );
void 
affect_modify(CHAR_DATA * ch, AFFECT_DATA * paf, bool fAdd)
{
	OBJ_DATA *wield;
	int 	mod;
	struct skill_type *skill;
	ch_ret 	retcode;

	mod = paf->modifier;

	if (fAdd) {
		xSET_BITS(ch->affected_by, paf->bitvector);
		if (paf->location % REVERSE_APPLY == APPLY_RECURRINGSPELL) {
			mod = abs(mod);
			if (IS_VALID_SN(mod)
			    && (skill = skill_table[mod]) != NULL
			    && skill->type == SKILL_SPELL)
				xSET_BIT(ch->affected_by, AFF_RECURRINGSPELL);
			else
				bug("affect_modify(%s) APPLY_RECURRINGSPELL with bad sn %d",
				    ch->name, mod);
		}
    }
    else
    {
	xREMOVE_BITS( ch->affected_by, paf->bitvector );
	/*
	 * might be an idea to have a duration removespell which returns
	 * the spell after the duration... but would have to store
	 * the removed spell's information somewhere...		-Thoric
	 * (Though we could keep the affect, but disable it for a duration)
	 */
	if ( (paf->location % REVERSE_APPLY) == APPLY_REMOVESPELL )
	    return;

	if ( paf->location % REVERSE_APPLY == APPLY_RECURRINGSPELL )
	{
	    mod = abs(mod);
	    if ( !IS_VALID_SN(mod)
	    ||  (skill=skill_table[mod]) == NULL
	    ||   skill->type != SKILL_SPELL )
	        bug( "affect_modify(%s) APPLY_RECURRINGSPELL with bad sn %d.",
		    ch->name, mod );
	    xREMOVE_BIT(ch->affected_by, AFF_RECURRINGSPELL);
	    return;
	} else {
		xREMOVE_BITS(ch->affected_by, paf->bitvector);
		/*
		 * might be an idea to have a duration removespell which returns
		 * the spell after the duration... but would have to store
		 * the removed spell's information somewhere...		-Thoric
		 * (Though we could keep the affect, but disable it for a duration)
		 */
		if ((paf->location % REVERSE_APPLY) == APPLY_REMOVESPELL)
			return;

		if (paf->location % REVERSE_APPLY == APPLY_RECURRINGSPELL) {
			mod = abs(mod);
			if (!IS_VALID_SN(mod)
			    || (skill = skill_table[mod]) == NULL
			    || skill->type != SKILL_SPELL)
				bug("affect_modify(%s) APPLY_RECURRINGSPELL with bad sn %d.",
				    ch->name, mod);
			xREMOVE_BIT(ch->affected_by, AFF_RECURRINGSPELL);
			return;
		}
		switch (paf->location % REVERSE_APPLY) {
		case APPLY_AFFECT:
			REMOVE_BIT(ch->affected_by.bits[0], mod);
			return;
		case APPLY_EXT_AFFECT:
			xREMOVE_BIT(ch->affected_by, mod);
			return;
		case APPLY_RESISTANT:
			REMOVE_BIT(ch->resistant, mod);
			return;
		case APPLY_IMMUNE:
			REMOVE_BIT(ch->immune, mod);
			return;
		case APPLY_SUSCEPTIBLE:
			REMOVE_BIT(ch->susceptible, mod);
			return;
		case APPLY_REMOVE:
			SET_BIT(ch->affected_by.bits[0], mod);
			return;
		default:
			break;
		}
		mod = 0 - mod;
	}

	switch( paf->location % REVERSE_APPLY )
	{
	  case APPLY_AFFECT:        REMOVE_BIT( ch->affected_by.bits[0], mod );	return;
	  case APPLY_EXT_AFFECT:   xREMOVE_BIT( ch->affected_by, mod );	return;
	  case APPLY_RESISTANT:     REMOVE_BIT( ch->resistant, mod );	return;
	  case APPLY_IMMUNE:        REMOVE_BIT( ch->immune, mod );	return;
	  case APPLY_SUSCEPTIBLE:   REMOVE_BIT( ch->susceptible, mod );	return;
	  case APPLY_REMOVE:	    SET_BIT( ch->affected_by.bits[0], mod );	return;
	  default:   break;
	}
	mod = 0 - mod;
    }
	switch (paf->location % REVERSE_APPLY) {
	default:
		bug("Affect_modify: unknown location %d.", paf->location);
		return;

    switch ( paf->location % REVERSE_APPLY )
    {
    default:
	bug( "Affect_modify: unknown location %d.", paf->location );
	return;
	case APPLY_NATURALAC:
		if (!IS_NPC(ch))
			ch->pcdata->natural_ac_max += mod;
		break;

	case APPLY_NATURALAC:	if( !IS_NPC(ch) ) ch->pcdata->natural_ac_max	+= mod; break;

    case APPLY_NONE:						break;
    case APPLY_STR:           ch->mod_str		+= mod;	break;
    case APPLY_DEX:           ch->mod_dex		+= mod;	break;
    case APPLY_INT:           ch->mod_int		+= mod;	break;
    case APPLY_CON:	      ch->mod_con		+= mod;	break;
    case APPLY_LCK:	      ch->mod_lck		+= mod; break;
    case APPLY_ALLSTATS:
    				      ch->mod_str		+= mod;
    				      ch->mod_dex		+= mod;
    				      ch->mod_int		+= mod;
    				      ch->mod_con		+= mod;
    				      break;
    case APPLY_SEX:
	ch->sex = (ch->sex+mod) % 3;
	if ( ch->sex < 0 )
	    ch->sex += 2;
	ch->sex = URANGE( 0, ch->sex, 2 );
	break;

    /*
     * These are unused due to possible problems.  Enable at your own risk.
     */
    case APPLY_CLASS:						break;
    case APPLY_LEVEL:						break;
    case APPLY_AGE:						break;
    case APPLY_GOLD:						break;
    case APPLY_EXP:						break;

    /*
     * Regular apply types
     */
    case APPLY_HEIGHT:	      ch->height		+= mod;	break;
    case APPLY_WEIGHT:	      ch->weight		+= mod;	break;
    case APPLY_MANA:          ch->max_mana		+= mod;	break;
    case APPLY_HIT:           ch->max_hit		+= mod;	break;
    case APPLY_MOVE:          ch->max_move		+= mod;	break;
    case APPLY_AC:            ch->armor			+= mod;	break;
    case APPLY_HITROLL:       ch->hitroll		+= mod;	break;
    case APPLY_DAMROLL:       ch->damroll		+= mod;	break;
    case APPLY_SAVING_POISON: ch->saving_poison_death	+= mod;	break;
    case APPLY_SAVING_ROD:    ch->saving_wand		+= mod;	break;
    case APPLY_SAVING_PARA:   ch->saving_para_petri	+= mod;	break;
    case APPLY_SAVING_BREATH: ch->saving_breath		+= mod;	break;
    case APPLY_SAVING_SPELL:  ch->saving_spell_staff	+= mod;	break;

    /*
     * Bitvector modifying apply types
     */
    case APPLY_AFFECT:        SET_BIT( ch->affected_by.bits[0], mod );	break;
    case APPLY_EXT_AFFECT:   xSET_BIT( ch->affected_by, mod );  break;
    case APPLY_RESISTANT:     SET_BIT( ch->resistant, mod );	break;
    case APPLY_IMMUNE:        SET_BIT( ch->immune, mod );	break;
    case APPLY_SUSCEPTIBLE:   SET_BIT( ch->susceptible, mod );	break;
    case APPLY_WEAPONSPELL:	/* see fight.c */		break;
    case APPLY_REMOVE:	      REMOVE_BIT(ch->affected_by.bits[0], mod);	break;

    /*
     * Player condition modifiers
     */
    case APPLY_FULL:
	if ( !IS_NPC(ch) )
	    ch->pcdata->condition[COND_FULL] =
		URANGE( 0, ch->pcdata->condition[COND_FULL] + mod, 48 );
	break;

    case APPLY_THIRST:
	if ( !IS_NPC(ch) )
	    ch->pcdata->condition[COND_THIRST] =
		URANGE( 0, ch->pcdata->condition[COND_THIRST] + mod, 48 );
	break;

    case APPLY_DRUNK:
	if ( !IS_NPC(ch) )
	    ch->pcdata->condition[COND_DRUNK] =
		URANGE( 0, ch->pcdata->condition[COND_DRUNK] + mod, 48 );
	break;

    case APPLY_MENTALSTATE:
	ch->mental_state	= URANGE(-100, ch->mental_state + mod, 100);
	break;
    case APPLY_EMOTION:
	ch->emotional_state	= URANGE(-100, ch->emotional_state + mod, 100);
	break;


    /*
     * Specialty modfiers
     */
    case APPLY_CONTAGIOUS:
	break;
    case APPLY_ODOR:
	break;
    case APPLY_STRIPSN:
	if ( IS_VALID_SN(mod) )
	    affect_strip( ch, mod );
	else
	    bug( "affect_modify: APPLY_STRIPSN invalid sn %d", mod );
	break;
	case APPLY_NONE:
		break;
	case APPLY_STR:
		ch->mod_str += mod;
		break;
	case APPLY_DEX:
		ch->mod_dex += mod;
		break;
	case APPLY_INT:
		ch->mod_int += mod;
		break;
	case APPLY_CON:
		ch->mod_con += mod;
		break;
	case APPLY_LCK:
		ch->mod_lck += mod;
		break;
	case APPLY_ALLSTATS:
		ch->mod_str += mod;
		ch->mod_dex += mod;
		ch->mod_int += mod;
		ch->mod_con += mod;
		break;
	case APPLY_SEX:
		ch->sex = (ch->sex + mod) % 3;
		if (ch->sex < 0)
			ch->sex += 2;
		ch->sex = URANGE(0, ch->sex, 2);
		break;

		/*
	         * These are unused due to possible problems.  Enable at your own risk.
	         */
	case APPLY_CLASS:
		break;
	case APPLY_LEVEL:
		break;
	case APPLY_AGE:
		break;
	case APPLY_GOLD:
		break;
	case APPLY_EXP:
		break;

		/*
	         * Regular apply types
	         */
	case APPLY_HEIGHT:
		ch->height += mod;
		break;
	case APPLY_WEIGHT:
		ch->weight += mod;
		break;
	case APPLY_MANA:
		ch->max_mana += mod;
		break;
	case APPLY_HIT:
		ch->max_hit += mod;
		break;
	case APPLY_MOVE:
		ch->max_move += mod;
		break;
	case APPLY_AC:
		ch->armor += mod;
		break;
	case APPLY_HITROLL:
		ch->hitroll += mod;
		break;
	case APPLY_DAMROLL:
		ch->damroll += mod;
		break;
	case APPLY_SAVING_POISON:
		ch->saving_poison_death += mod;
		break;
	case APPLY_SAVING_ROD:
		ch->saving_wand += mod;
		break;
	case APPLY_SAVING_PARA:
		ch->saving_para_petri += mod;
		break;
	case APPLY_SAVING_BREATH:
		ch->saving_breath += mod;
		break;
	case APPLY_SAVING_SPELL:
		ch->saving_spell_staff += mod;
		break;

		/*
	         * Bitvector modifying apply types
	         */
	case APPLY_AFFECT:
		SET_BIT(ch->affected_by.bits[0], mod);
		break;
	case APPLY_EXT_AFFECT:
		xSET_BIT(ch->affected_by, mod);
		break;
	case APPLY_RESISTANT:
		SET_BIT(ch->resistant, mod);
		break;
	case APPLY_IMMUNE:
		SET_BIT(ch->immune, mod);
		break;
	case APPLY_SUSCEPTIBLE:
		SET_BIT(ch->susceptible, mod);
		break;
	case APPLY_WEAPONSPELL:	/* see fight.c */
		break;
	case APPLY_REMOVE:
		REMOVE_BIT(ch->affected_by.bits[0], mod);
		break;

		/*
	         * Player condition modifiers
	         */
	case APPLY_FULL:
		if (!IS_NPC(ch))
			ch->pcdata->condition[COND_FULL] =
			    URANGE(0, ch->pcdata->condition[COND_FULL] + mod, 48);
		break;

	case APPLY_THIRST:
		if (!IS_NPC(ch))
			ch->pcdata->condition[COND_THIRST] =
			    URANGE(0, ch->pcdata->condition[COND_THIRST] + mod, 48);
		break;

	case APPLY_DRUNK:
		if (!IS_NPC(ch))
			ch->pcdata->condition[COND_DRUNK] =
			    URANGE(0, ch->pcdata->condition[COND_DRUNK] + mod, 48);
		break;

	case APPLY_MENTALSTATE:
		ch->mental_state = URANGE(-100, ch->mental_state + mod, 100);
		break;
	case APPLY_EMOTION:
		ch->emotional_state = URANGE(-100, ch->emotional_state + mod, 100);
		break;


		/*
	         * Specialty modfiers
	         */
	case APPLY_CONTAGIOUS:
		break;
	case APPLY_ODOR:
		break;
	case APPLY_STRIPSN:
		if (IS_VALID_SN(mod))
			affect_strip(ch, mod);
		else
			bug("affect_modify: APPLY_STRIPSN invalid sn %d", mod);
		break;

/* spell cast upon wear/removal of an object	-Thoric */
    case APPLY_WEARSPELL:
    case APPLY_REMOVESPELL:
	if ( xIS_SET(ch->in_room->room_flags, ROOM_NO_MAGIC)
		||   IS_SET(ch->immune, RIS_MAGIC)
		|| ( ( paf->location % REVERSE_APPLY ) == APPLY_WEARSPELL && !fAdd )
		|| ( ( paf->location % REVERSE_APPLY ) == APPLY_REMOVESPELL && !fAdd )
		||   saving_char == ch          /* so save/quit doesn't trigger */
		||   loading_char == ch )       /* so loading doesn't trigger */
	return;
	case APPLY_WEARSPELL:
	case APPLY_REMOVESPELL:
		if (xIS_SET(ch->in_room->room_flags, ROOM_NO_MAGIC)
		    || IS_SET(ch->immune, RIS_MAGIC)
		    || ((paf->location % REVERSE_APPLY) == APPLY_WEARSPELL && !fAdd)
		    || ((paf->location % REVERSE_APPLY) == APPLY_REMOVESPELL && !fAdd)
		    || saving_char == ch/* so save/quit doesn't trigger */
		    || loading_char == ch)	/* so loading doesn't trigger */
			return;

		mod = abs(mod);
		if (IS_VALID_SN(mod)
		    && (skill = skill_table[mod]) != NULL
		    && skill->type == SKILL_SPELL) {
			if (skill->target == TAR_IGNORE || skill->target == TAR_OBJ_INV) {
				bug("APPLY_WEARSPELL trying to apply bad target spell.  SN is %d.", mod);
				return;
			}
			if ((retcode = (*skill->spell_fun) (mod, ch->level, ch, ch)) == rCHAR_DIED
			    || char_died(ch))
				return;
		}
		break;

	mod = abs(mod);
	if ( IS_VALID_SN(mod)
	&&  (skill=skill_table[mod]) != NULL
	&&   skill->type == SKILL_SPELL )
	{
	   if (skill->target == TAR_IGNORE || skill->target == TAR_OBJ_INV)
	   {
	     bug("APPLY_WEARSPELL trying to apply bad target spell.  SN is %d.", mod);
	     return;
	   }
	   if ( (retcode=(*skill->spell_fun) ( mod, ch->level, ch, ch )) == rCHAR_DIED
	   ||   char_died(ch) )
	      return;
	}
	break;


    /*
     * Skill apply types
     */
    case APPLY_PALM:	/* not implemented yet */			break;
    case APPLY_HIDE:	modify_skill(ch, gsn_hide, 	mod, fAdd);	break;
    case APPLY_STEAL:	modify_skill(ch, gsn_steal, 	mod, fAdd);	break;
    case APPLY_SNEAK:	modify_skill(ch, gsn_sneak, 	mod, fAdd);	break;
    case APPLY_PICK:	modify_skill(ch, gsn_pick_lock, mod, fAdd);	break;
    case APPLY_BACKSTAB:modify_skill(ch, gsn_backstab, 	mod, fAdd);	break;
    case APPLY_DETRAP:	modify_skill(ch, gsn_detrap, 	mod, fAdd);	break;
    case APPLY_DODGE:	modify_skill(ch, gsn_dodge, 	mod, fAdd);	break;
    case APPLY_PEEK:	modify_skill(ch, gsn_peek, 	mod, fAdd);	break;
    case APPLY_GOUGE:	modify_skill(ch, gsn_gouge, 	mod, fAdd);	break;
    case APPLY_SEARCH:	modify_skill(ch, gsn_search, 	mod, fAdd);	break;
    case APPLY_DIG:	modify_skill(ch, gsn_dig, 	mod, fAdd);	break;
    case APPLY_MOUNT:	modify_skill(ch, gsn_mount, 	mod, fAdd);	break;
    case APPLY_DISARM:	modify_skill(ch, gsn_disarm, 	mod, fAdd);	break;
    case APPLY_KICK:	modify_skill(ch, gsn_kick, 	mod, fAdd);	break;
    case APPLY_PARRY:	modify_skill(ch, gsn_parry, 	mod, fAdd);	break;
    case APPLY_BASH:	modify_skill(ch, gsn_bash, 	mod, fAdd);	break;
    case APPLY_STUN:	modify_skill(ch, gsn_stun, 	mod, fAdd);	break;
    case APPLY_PUNCH:	modify_skill(ch, gsn_punch, 	mod, fAdd);	break;
    case APPLY_CLIMB:	modify_skill(ch, gsn_climb, 	mod, fAdd);	break;
    case APPLY_GRIP:	modify_skill(ch, gsn_grip, 	mod, fAdd);	break;
    case APPLY_SCRIBE:	modify_skill(ch, gsn_scribe, 	mod, fAdd);	break;
    case APPLY_BREW:	modify_skill(ch, gsn_brew, 	mod, fAdd);	break;
    case APPLY_COOK:	modify_skill(ch, gsn_cook,	mod, fAdd);	break;

    /*
     * Room apply types
     */
    case APPLY_ROOMFLAG:
    case APPLY_SECTORTYPE:
    case APPLY_ROOMLIGHT:
    case APPLY_TELEVNUM:
	break;

    /*
     * Object apply types
     */
    }

    /*
     * Check for weapon wielding.
     * Guard against recursion (for weapons with affects).
     */
    if ( !IS_NPC( ch )
    &&   saving_char != ch
    &&  (wield = get_eq_char(ch, WEAR_WIELD) ) != NULL
    &&   get_obj_weight(wield) > (get_curr_str(ch)/2) )
    {
	static int depth;

	if ( depth == 0 )
	{
	    depth++;
	    act( AT_ACTION, "You are too weak to wield $p any longer.",
		ch, wield, NULL, TO_CHAR );
	    act( AT_ACTION, "$n stops wielding $p.", ch, wield, NULL, TO_ROOM );
	    unequip_char( ch, wield );
	    depth--;

		/*
	         * Skill apply types
	         */
	case APPLY_PALM:		/* not implemented yet */
		break;
	case APPLY_HIDE:
		modify_skill(ch, gsn_hide, mod, fAdd);
		break;
	case APPLY_STEAL:
		modify_skill(ch, gsn_steal, mod, fAdd);
		break;
	case APPLY_SNEAK:
		modify_skill(ch, gsn_sneak, mod, fAdd);
		break;
	case APPLY_PICK:
		modify_skill(ch, gsn_pick_lock, mod, fAdd);
		break;
	case APPLY_BACKSTAB:
		modify_skill(ch, gsn_backstab, mod, fAdd);
		break;
	case APPLY_DETRAP:
		modify_skill(ch, gsn_detrap, mod, fAdd);
		break;
	case APPLY_DODGE:
		modify_skill(ch, gsn_dodge, mod, fAdd);
		break;
	case APPLY_PEEK:
		modify_skill(ch, gsn_peek, mod, fAdd);
		break;
	case APPLY_GOUGE:
		modify_skill(ch, gsn_gouge, mod, fAdd);
		break;
	case APPLY_SEARCH:
		modify_skill(ch, gsn_search, mod, fAdd);
		break;
	case APPLY_DIG:
		modify_skill(ch, gsn_dig, mod, fAdd);
		break;
	case APPLY_MOUNT:
		modify_skill(ch, gsn_mount, mod, fAdd);
		break;
	case APPLY_DISARM:
		modify_skill(ch, gsn_disarm, mod, fAdd);
		break;
	case APPLY_KICK:
		modify_skill(ch, gsn_kick, mod, fAdd);
		break;
	case APPLY_PARRY:
		modify_skill(ch, gsn_parry, mod, fAdd);
		break;
	case APPLY_BASH:
		modify_skill(ch, gsn_bash, mod, fAdd);
		break;
	case APPLY_STUN:
		modify_skill(ch, gsn_stun, mod, fAdd);
		break;
	case APPLY_PUNCH:
		modify_skill(ch, gsn_punch, mod, fAdd);
		break;
	case APPLY_CLIMB:
		modify_skill(ch, gsn_climb, mod, fAdd);
		break;
	case APPLY_GRIP:
		modify_skill(ch, gsn_grip, mod, fAdd);
		break;
	case APPLY_SCRIBE:
		modify_skill(ch, gsn_scribe, mod, fAdd);
		break;
	case APPLY_BREW:
		modify_skill(ch, gsn_brew, mod, fAdd);
		break;
	case APPLY_COOK:
		modify_skill(ch, gsn_cook, mod, fAdd);
		break;

		/*
	         * Room apply types
	         */
	case APPLY_ROOMFLAG:
	case APPLY_SECTORTYPE:
	case APPLY_ROOMLIGHT:
	case APPLY_TELEVNUM:
		break;

		/*
	         * Object apply types
	         */
	}
    }

    return;
	/*
         * Check for weapon wielding.
         * Guard against recursion (for weapons with affects).
         */
	if (!IS_NPC(ch)
	    && saving_char != ch
	    && (wield = get_eq_char(ch, WEAR_WIELD)) != NULL
	    && get_obj_weight(wield) > (get_curr_str(ch) / 2)) {
		static int depth;

		if (depth == 0) {
			depth++;
			act(AT_ACTION, "You are too weak to wield $p any longer.",
			    ch, wield, NULL, TO_CHAR);
			act(AT_ACTION, "$n stops wielding $p.", ch, wield, NULL, TO_ROOM);
			unequip_char(ch, wield);
			depth--;
		}
	}
	return;
}




@@ 690,71 788,67 @@ void affect_modify( CHAR_DATA *ch, AFFECT_DATA *paf, bool fAdd )
/*
 * Give an affect to a char.
 */
void affect_to_char( CHAR_DATA *ch, AFFECT_DATA *paf )
void 
affect_to_char(CHAR_DATA * ch, AFFECT_DATA * paf)
{
    AFFECT_DATA *paf_new;

    if ( !ch )
    {
	bug( "Affect_to_char(NULL, %d)", paf ? paf->type : 0 );
	return;
    }
	AFFECT_DATA *paf_new;

    if ( !paf )
    {
	bug( "Affect_to_char(%s, NULL)", ch->name );
	if (!ch) {
		bug("Affect_to_char(NULL, %d)", paf ? paf->type : 0);
		return;
	}
	if (!paf) {
		bug("Affect_to_char(%s, NULL)", ch->name);
		return;
	}
	CREATE(paf_new, AFFECT_DATA, 1);
	LINK(paf_new, ch->first_affect, ch->last_affect, next, prev);
	paf_new->type = paf->type;
	paf_new->duration = paf->duration;
	paf_new->location = paf->location;
	paf_new->modifier = paf->modifier;
	paf_new->bitvector = paf->bitvector;
	paf_new->affLocator = paf->affLocator;

	affect_modify(ch, paf_new, true);
	return;
    }

    CREATE( paf_new, AFFECT_DATA, 1 );
    LINK( paf_new, ch->first_affect, ch->last_affect, next, prev );
    paf_new->type	= paf->type;
    paf_new->duration	= paf->duration;
    paf_new->location	= paf->location;
    paf_new->modifier	= paf->modifier;
    paf_new->bitvector	= paf->bitvector;
    paf_new->affLocator = paf->affLocator;

    affect_modify( ch, paf_new, true );
    return;
}


/*
 * Remove an affect from a char.
 */
void affect_remove( CHAR_DATA *ch, AFFECT_DATA *paf )
void 
affect_remove(CHAR_DATA * ch, AFFECT_DATA * paf)
{
    if ( !ch->first_affect )
    {
	bug( "Affect_remove(%s, %d): no affect.", ch->name,
		paf ? paf->type : 0 );
	return;
    }

    affect_modify( ch, paf, false );
	if (!ch->first_affect) {
		bug("Affect_remove(%s, %d): no affect.", ch->name,
		    paf ? paf->type : 0);
		return;
	}
	affect_modify(ch, paf, false);

    UNLINK( paf, ch->first_affect, ch->last_affect, next, prev );
    DISPOSE( paf );
    return;
	UNLINK(paf, ch->first_affect, ch->last_affect, next, prev);
	DISPOSE(paf);
	return;
}

/*
 * Strip all affects of a given sn.
 */
void affect_strip( CHAR_DATA *ch, int sn )
void 
affect_strip(CHAR_DATA * ch, int sn)
{
    AFFECT_DATA *paf;
    AFFECT_DATA *paf_next;
	AFFECT_DATA *paf;
	AFFECT_DATA *paf_next;

    for ( paf = ch->first_affect; paf; paf = paf_next )
    {
	paf_next = paf->next;
	if ( paf->type == sn )
	    affect_remove( ch, paf );
    }
	for (paf = ch->first_affect; paf; paf = paf_next) {
		paf_next = paf->next;
		if (paf->type == sn)
			affect_remove(ch, paf);
	}

    return;
	return;
}




@@ 762,15 856,16 @@ void affect_strip( CHAR_DATA *ch, int sn )
/*
 * Return true if a char is affected by a spell.
 */
bool is_affected( CHAR_DATA *ch, int sn )
bool 
is_affected(CHAR_DATA * ch, int sn)
{
    AFFECT_DATA *paf;
	AFFECT_DATA *paf;

    for ( paf = ch->first_affect; paf; paf = paf->next )
	if ( paf->type == sn )
	    return true;
	for (paf = ch->first_affect; paf; paf = paf->next)
		if (paf->type == sn)
			return true;

    return false;
	return false;
}




@@ 779,48 874,47 @@ bool is_affected( CHAR_DATA *ch, int sn )
 * Limitations put in place by Thoric, they may be high... but at least
 * they're there :)
 */
void affect_join( CHAR_DATA *ch, AFFECT_DATA *paf )
{
    AFFECT_DATA *paf_old;

    for ( paf_old = ch->first_affect; paf_old; paf_old = paf_old->next )
	if ( paf_old->type == paf->type )
	{
	    paf->duration = UMIN( 1000000, paf->duration + paf_old->duration );
	    if ( paf->modifier )
		paf->modifier = UMIN( 5000, paf->modifier + paf_old->modifier );
	    else
	        paf->modifier = paf_old->modifier;
	    affect_remove( ch, paf_old );
	    break;
	}

    affect_to_char( ch, paf );
    return;
void 
affect_join(CHAR_DATA * ch, AFFECT_DATA * paf)
{
	AFFECT_DATA *paf_old;

	for (paf_old = ch->first_affect; paf_old; paf_old = paf_old->next)
		if (paf_old->type == paf->type) {
			paf->duration = UMIN(1000000, paf->duration + paf_old->duration);
			if (paf->modifier)
				paf->modifier = UMIN(5000, paf->modifier + paf_old->modifier);
			else
				paf->modifier = paf_old->modifier;
			affect_remove(ch, paf_old);
			break;
		}
	affect_to_char(ch, paf);
	return;
}


/*
 * Apply only affected and RIS on a char
 */
void aris_affect( CHAR_DATA *ch, AFFECT_DATA *paf )
void 
aris_affect(CHAR_DATA * ch, AFFECT_DATA * paf)
{
    xSET_BITS(ch->affected_by, paf->bitvector);
    switch(paf->location % REVERSE_APPLY)
    {
	xSET_BITS(ch->affected_by, paf->bitvector);
	switch (paf->location % REVERSE_APPLY) {
	case APPLY_AFFECT:
	    SET_BIT(ch->affected_by.bits[0], paf->modifier);
	    break;
		SET_BIT(ch->affected_by.bits[0], paf->modifier);
		break;
	case APPLY_RESISTANT:
	    SET_BIT(ch->resistant, paf->modifier);
	    break;
		SET_BIT(ch->resistant, paf->modifier);
		break;
	case APPLY_IMMUNE:
	    SET_BIT(ch->immune, paf->modifier);
	    break;
		SET_BIT(ch->immune, paf->modifier);
		break;
	case APPLY_SUSCEPTIBLE:
	    SET_BIT(ch->susceptible, paf->modifier);
	    break;
    }
		SET_BIT(ch->susceptible, paf->modifier);
		break;
	}
}

/*


@@ 834,19 928,21 @@ void aris_affect( CHAR_DATA *ch, AFFECT_DATA *paf )

/* Temp mod to bypass immortals so they can keep their mset affects,
 * just a band-aid until we get more time to look at it -- Blodkai */
void update_aris(CHAR_DATA *ch)
void 
update_aris(CHAR_DATA * ch)
{
	AFFECT_DATA *paf;
	OBJ_DATA *obj;
	int hiding;
	int aff_a, aff_b, aff_c, aff_d, aff_e, aff_f, aff_g, aff_h;
	int aff_i, aff_j, aff_k, aff_l, aff_m, aff_n, aff_o;
        int aff_p, aff_q, aff_r, aff_s, aff_t, aff_u, aff_v;
        int aff_w, aff_x, aff_y, aff_z, aff_aa;
	int aff_ab, aff_ac, aff_ad, aff_ae, aff_af, aff_ag, aff_ah;
	int aff_ai, aff_aj, aff_ak, aff_al, aff_am, aff_an;
	int 	hiding;
	int 	aff_a, aff_b, aff_c, aff_d, aff_e, aff_f, aff_g, aff_h;
	int 	aff_i, aff_j, aff_k, aff_l, aff_m, aff_n, aff_o;
	int 	aff_p, aff_q, aff_r, aff_s, aff_t, aff_u, aff_v;
	int 	aff_w, aff_x, aff_y, aff_z, aff_aa;
	int 	aff_ab, aff_ac, aff_ad, aff_ae, aff_af, aff_ag, aff_ah;
	int 	aff_ai, aff_aj, aff_ak, aff_al, aff_am, aff_an;

	if (IS_NPC(ch) || IS_IMMORTAL(ch))
	    return;
		return;

	/* So chars using hide skill will continue to hide */
	hiding = IS_AFFECTED(ch, AFF_HIDE);


@@ 867,24 963,24 @@ void update_aris(CHAR_DATA *ch)
	aff_m = IS_AFFECTED(ch, AFF_HEART);
	aff_n = IS_AFFECTED(ch, AFF_TAG);
	aff_o = IS_AFFECTED(ch, AFF_FLYING);
        aff_p = IS_AFFECTED(ch, AFF_HYPER);
        aff_q = IS_AFFECTED(ch, AFF_SEMIPERFECT);
        aff_r = IS_AFFECTED(ch, AFF_PERFECT);
        aff_s = IS_AFFECTED(ch, AFF_ULTRAPERFECT);
        aff_t = IS_AFFECTED(ch, AFF_GROWTH);
        aff_u = IS_AFFECTED(ch, AFF_GIANT);
        aff_v = IS_AFFECTED(ch, AFF_SPLIT_FORM);
        aff_w = IS_AFFECTED(ch, AFF_TRI_FORM);
        aff_x = IS_AFFECTED(ch, AFF_MULTI_FORM);
        aff_y = IS_AFFECTED(ch, AFF_USSJ);
        aff_z = IS_AFFECTED(ch, AFF_USSJ2);
	aff_p = IS_AFFECTED(ch, AFF_HYPER);
	aff_q = IS_AFFECTED(ch, AFF_SEMIPERFECT);
	aff_r = IS_AFFECTED(ch, AFF_PERFECT);
	aff_s = IS_AFFECTED(ch, AFF_ULTRAPERFECT);
	aff_t = IS_AFFECTED(ch, AFF_GROWTH);
	aff_u = IS_AFFECTED(ch, AFF_GIANT);
	aff_v = IS_AFFECTED(ch, AFF_SPLIT_FORM);
	aff_w = IS_AFFECTED(ch, AFF_TRI_FORM);
	aff_x = IS_AFFECTED(ch, AFF_MULTI_FORM);
	aff_y = IS_AFFECTED(ch, AFF_USSJ);
	aff_z = IS_AFFECTED(ch, AFF_USSJ2);
	aff_aa = IS_AFFECTED(ch, AFF_EXTREME);
	aff_ab = IS_AFFECTED(ch, AFF_MYSTIC);
	aff_ac = IS_AFFECTED(ch, AFF_SUPERANDROID);
	aff_ad = IS_AFFECTED(ch, AFF_EVILBOOST);
        aff_ae = IS_AFFECTED(ch, AFF_EVILSURGE);
        aff_af = IS_AFFECTED(ch, AFF_EVILOVERLOAD);
        aff_ag = IS_AFFECTED(ch, AFF_MAKEOSTAR);
	aff_ae = IS_AFFECTED(ch, AFF_EVILSURGE);
	aff_af = IS_AFFECTED(ch, AFF_EVILOVERLOAD);
	aff_ag = IS_AFFECTED(ch, AFF_MAKEOSTAR);
	aff_ah = IS_AFFECTED(ch, AFF_EVIL_TRANS);
	aff_ai = IS_AFFECTED(ch, AFF_SUPER_TRANS);
	aff_aj = IS_AFFECTED(ch, AFF_KID_TRANS);


@@ 913,135 1009,129 @@ void update_aris(CHAR_DATA *ch)
	SET_BIT(ch->susceptible, class_table[ch->class]->suscept);

	/* Add in effects from deities */
	if (ch->pcdata->deity)
	{
	    if (ch->pcdata->favor > ch->pcdata->deity->affectednum)
		xSET_BITS(ch->affected_by, ch->pcdata->deity->affected);
	    if (ch->pcdata->favor > ch->pcdata->deity->elementnum)
		SET_BIT(ch->resistant, ch->pcdata->deity->element);
	    if (ch->pcdata->favor < ch->pcdata->deity->susceptnum)
		SET_BIT(ch->susceptible, ch->pcdata->deity->suscept);
	if (ch->pcdata->deity) {
		if (ch->pcdata->favor > ch->pcdata->deity->affectednum)
			xSET_BITS(ch->affected_by, ch->pcdata->deity->affected);
		if (ch->pcdata->favor > ch->pcdata->deity->elementnum)
			SET_BIT(ch->resistant, ch->pcdata->deity->element);
		if (ch->pcdata->favor < ch->pcdata->deity->susceptnum)
			SET_BIT(ch->susceptible, ch->pcdata->deity->suscept);
	}

	/* Add in effect from spells */
	for (paf = ch->first_affect; paf; paf = paf->next)
	    aris_affect(ch, paf);
		aris_affect(ch, paf);

	/* Add in effects from equipment */
	for (obj = ch->first_carrying; obj; obj = obj->next_content)
	{
	    if (obj->wear_loc != WEAR_NONE)
	    {
		for (paf = obj->first_affect; paf; paf= paf->next)
		    aris_affect(ch, paf);

		for (paf=obj->pIndexData->first_affect; paf; paf = paf->next)
		    aris_affect(ch, paf);
	    }
	for (obj = ch->first_carrying; obj; obj = obj->next_content) {
		if (obj->wear_loc != WEAR_NONE) {
			for (paf = obj->first_affect; paf; paf = paf->next)
				aris_affect(ch, paf);

			for (paf = obj->pIndexData->first_affect; paf; paf = paf->next)
				aris_affect(ch, paf);
		}
	}

	/* Add in effects from the room */
	if (ch->in_room)  /* non-existant char booboo-fix --TRI */
	    for (paf = ch->in_room->first_affect; paf; paf = paf->next)
	       aris_affect(ch, paf);
	if (ch->in_room)		/* non-existant char booboo-fix --TRI */
		for (paf = ch->in_room->first_affect; paf; paf = paf->next)
			aris_affect(ch, paf);

	/* Add in effects for polymorph */
	if ( ch->morph )
	{
	   xSET_BITS(ch->affected_by, ch->morph->affected_by );
	   SET_BIT(ch->immune, ch->morph->immune );
	   SET_BIT(ch->resistant, ch->morph->resistant );
	   SET_BIT(ch->susceptible, ch->morph->suscept );
	   /* Right now only morphs have no_ things --Shaddai */
	   xSET_BITS(ch->no_affected_by, ch->morph->no_affected_by );
	   SET_BIT(ch->no_immune, ch->morph->no_immune );
	   SET_BIT(ch->no_resistant, ch->morph->no_resistant );
	   SET_BIT(ch->no_susceptible, ch->morph->no_suscept );
	if (ch->morph) {
		xSET_BITS(ch->affected_by, ch->morph->affected_by);
		SET_BIT(ch->immune, ch->morph->immune);
		SET_BIT(ch->resistant, ch->morph->resistant);
		SET_BIT(ch->susceptible, ch->morph->suscept);
		/* Right now only morphs have no_ things --Shaddai */
		xSET_BITS(ch->no_affected_by, ch->morph->no_affected_by);
		SET_BIT(ch->no_immune, ch->morph->no_immune);
		SET_BIT(ch->no_resistant, ch->morph->no_resistant);
		SET_BIT(ch->no_susceptible, ch->morph->no_suscept);
	}

	/* If they were hiding before, make them hiding again */
	if (hiding)
	    xSET_BIT(ch->affected_by, AFF_HIDE);
		xSET_BIT(ch->affected_by, AFF_HIDE);
	if (aff_a)
	    xSET_BIT(ch->affected_by, AFF_KAIOKEN);
		xSET_BIT(ch->affected_by, AFF_KAIOKEN);
	if (aff_b)
	    xSET_BIT(ch->affected_by, AFF_SSJ);
		xSET_BIT(ch->affected_by, AFF_SSJ);
	if (aff_c)
	    xSET_BIT(ch->affected_by, AFF_SSJ2);
		xSET_BIT(ch->affected_by, AFF_SSJ2);
	if (aff_d)
	    xSET_BIT(ch->affected_by, AFF_SSJ3);
		xSET_BIT(ch->affected_by, AFF_SSJ3);
	if (aff_e)
	    xSET_BIT(ch->affected_by, AFF_SSJ4);
		xSET_BIT(ch->affected_by, AFF_SSJ4);
	if (aff_an)
	    xSET_BIT(ch->affected_by, AFF_SGOD);
		xSET_BIT(ch->affected_by, AFF_SGOD);
	if (aff_f)
	    xSET_BIT(ch->affected_by, AFF_SNAMEK);
		xSET_BIT(ch->affected_by, AFF_SNAMEK);
	if (aff_g)
	    xSET_BIT(ch->affected_by, AFF_ICER2);
		xSET_BIT(ch->affected_by, AFF_ICER2);
	if (aff_h)
	    xSET_BIT(ch->affected_by, AFF_ICER3);
		xSET_BIT(ch->affected_by, AFF_ICER3);
	if (aff_i)
	    xSET_BIT(ch->affected_by, AFF_ICER4);
		xSET_BIT(ch->affected_by, AFF_ICER4);
	if (aff_j)
	    xSET_BIT(ch->affected_by, AFF_ICER5);
		xSET_BIT(ch->affected_by, AFF_ICER5);
	if (aff_k)
	    xSET_BIT(ch->affected_by, AFF_OOZARU);
		xSET_BIT(ch->affected_by, AFF_OOZARU);
	if (aff_l)
	    xSET_BIT(ch->affected_by, AFF_DEAD);
		xSET_BIT(ch->affected_by, AFF_DEAD);
	if (aff_m)
	    xSET_BIT(ch->affected_by, AFF_HEART);
		xSET_BIT(ch->affected_by, AFF_HEART);
	if (aff_n)
	    xSET_BIT(ch->affected_by, AFF_TAG);
		xSET_BIT(ch->affected_by, AFF_TAG);
	if (aff_o)
	    xSET_BIT(ch->affected_by, AFF_FLYING);
		xSET_BIT(ch->affected_by, AFF_FLYING);
	if (aff_p)
	    xSET_BIT(ch->affected_by, AFF_HYPER);
		xSET_BIT(ch->affected_by, AFF_HYPER);
	if (aff_q)
	    xSET_BIT(ch->affected_by, AFF_SEMIPERFECT);
		xSET_BIT(ch->affected_by, AFF_SEMIPERFECT);
	if (aff_r)
	    xSET_BIT(ch->affected_by, AFF_PERFECT);
		xSET_BIT(ch->affected_by, AFF_PERFECT);
	if (aff_s)
	    xSET_BIT(ch->affected_by, AFF_ULTRAPERFECT);
		xSET_BIT(ch->affected_by, AFF_ULTRAPERFECT);
	if (aff_t)
	    xSET_BIT(ch->affected_by, AFF_GROWTH);
		xSET_BIT(ch->affected_by, AFF_GROWTH);
	if (aff_u)
	    xSET_BIT(ch->affected_by, AFF_GIANT);
		xSET_BIT(ch->affected_by, AFF_GIANT);
	if (aff_v)
	    xSET_BIT(ch->affected_by, AFF_SPLIT_FORM);
		xSET_BIT(ch->affected_by, AFF_SPLIT_FORM);
	if (aff_w)
	    xSET_BIT(ch->affected_by, AFF_TRI_FORM);
		xSET_BIT(ch->affected_by, AFF_TRI_FORM);
	if (aff_x)
	    xSET_BIT(ch->affected_by, AFF_MULTI_FORM);
		xSET_BIT(ch->affected_by, AFF_MULTI_FORM);
	if (aff_y)
	    xSET_BIT(ch->affected_by, AFF_USSJ);
		xSET_BIT(ch->affected_by, AFF_USSJ);
	if (aff_z)
	    xSET_BIT(ch->affected_by, AFF_USSJ2);
		xSET_BIT(ch->affected_by, AFF_USSJ2);
	if (aff_aa)
	    xSET_BIT(ch->affected_by, AFF_EXTREME);
        if (aff_ab)
            xSET_BIT(ch->affected_by, AFF_MYSTIC);
        if (aff_ac)
            xSET_BIT(ch->affected_by, AFF_SUPERANDROID);
        if (aff_ad)
            xSET_BIT(ch->affected_by, AFF_EVILBOOST);
        if (aff_ae)
            xSET_BIT(ch->affected_by, AFF_EVILSURGE);
        if (aff_af)
            xSET_BIT(ch->affected_by, AFF_EVILOVERLOAD);
        if (aff_ag)
            xSET_BIT(ch->affected_by, AFF_MAKEOSTAR);
		xSET_BIT(ch->affected_by, AFF_EXTREME);
	if (aff_ab)
		xSET_BIT(ch->affected_by, AFF_MYSTIC);
	if (aff_ac)
		xSET_BIT(ch->affected_by, AFF_SUPERANDROID);
	if (aff_ad)
		xSET_BIT(ch->affected_by, AFF_EVILBOOST);
	if (aff_ae)
		xSET_BIT(ch->affected_by, AFF_EVILSURGE);
	if (aff_af)
		xSET_BIT(ch->affected_by, AFF_EVILOVERLOAD);
	if (aff_ag)
		xSET_BIT(ch->affected_by, AFF_MAKEOSTAR);
	if (aff_ah)
	    xSET_BIT(ch->affected_by, AFF_EVIL_TRANS);
		xSET_BIT(ch->affected_by, AFF_EVIL_TRANS);
	if (aff_ai)
	    xSET_BIT(ch->affected_by, AFF_SUPER_TRANS);
		xSET_BIT(ch->affected_by, AFF_SUPER_TRANS);
	if (aff_aj)
	    xSET_BIT(ch->affected_by, AFF_KID_TRANS);
		xSET_BIT(ch->affected_by, AFF_KID_TRANS);
	if (aff_ak)
            xSET_BIT(ch->affected_by, AFF_BIOJR);
		xSET_BIT(ch->affected_by, AFF_BIOJR);
	if (aff_al)
            xSET_BIT(ch->affected_by, AFF_SANCTUARY);
		xSET_BIT(ch->affected_by, AFF_SANCTUARY);
	if (aff_am)
            xSET_BIT(ch->affected_by, AFF_GOLDEN_OOZARU);
		xSET_BIT(ch->affected_by, AFF_GOLDEN_OOZARU);
	return;
}



@@ 1049,261 1139,234 @@ void update_aris(CHAR_DATA *ch)
/*
 * Move a char out of a room.
 */
void char_from_room( CHAR_DATA *ch )
void 
char_from_room(CHAR_DATA * ch)
{
    OBJ_DATA *obj;
    AFFECT_DATA *paf;

    if ( !ch->in_room )
    {
	bug( "Char_from_room: NULL.", 0 );
	return;
    }

    if ( !IS_NPC(ch) )
	--ch->in_room->area->nplayer;
	OBJ_DATA *obj;
	AFFECT_DATA *paf;

    if ( ( obj = get_eq_char( ch, WEAR_LIGHT ) ) != NULL
    &&   obj->item_type == ITEM_LIGHT
    &&   obj->value[2] != 0
    &&   ch->in_room->light > 0 )
	--ch->in_room->light;
	if (!ch->in_room) {
		bug("Char_from_room: NULL.", 0);
		return;
	}
	if (!IS_NPC(ch))
		--ch->in_room->area->nplayer;

    /*
     * Character's affect on the room
     */
    for ( paf = ch->first_affect; paf; paf = paf->next )
	room_affect(ch->in_room, paf, false);
	if ((obj = get_eq_char(ch, WEAR_LIGHT)) != NULL
	    && obj->item_type == ITEM_LIGHT
	    && obj->value[2] != 0
	    && ch->in_room->light > 0)
		--ch->in_room->light;

    /*
     * Room's affect on the character
     */
    if ( !char_died(ch) )
    {
	for ( paf = ch->in_room->first_affect; paf; paf = paf->next )
	    affect_modify(ch, paf, false);
	/*
         * Character's affect on the room
         */
	for (paf = ch->first_affect; paf; paf = paf->next)
		room_affect(ch->in_room, paf, false);

	if ( char_died(ch) )	/* could die from removespell, etc */
	    return;
    }
	/*
         * Room's affect on the character
         */
	if (!char_died(ch)) {
		for (paf = ch->in_room->first_affect; paf; paf = paf->next)
			affect_modify(ch, paf, false);

    UNLINK( ch, ch->in_room->first_person, ch->in_room->last_person,
		next_in_room, prev_in_room );
    ch->was_in_room  = ch->in_room;
    ch->in_room      = NULL;
    ch->next_in_room = NULL;
    ch->prev_in_room = NULL;
		if (char_died(ch))	/* could die from removespell, etc */
			return;
	}
	UNLINK(ch, ch->in_room->first_person, ch->in_room->last_person,
	    next_in_room, prev_in_room);
	ch->was_in_room = ch->in_room;
	ch->in_room = NULL;
	ch->next_in_room = NULL;
	ch->prev_in_room = NULL;

    if ( !IS_NPC(ch)
    &&   get_timer( ch, TIMER_SHOVEDRAG ) > 0 )
	remove_timer( ch, TIMER_SHOVEDRAG );
	if (!IS_NPC(ch)
	    && get_timer(ch, TIMER_SHOVEDRAG) > 0)
		remove_timer(ch, TIMER_SHOVEDRAG);

    return;
	return;
}

void char_to( CHAR_DATA *ch, int vnum )
void 
char_to(CHAR_DATA * ch, int vnum)
{
    char_from_room( ch );
    char_to_room( ch, get_room_index( vnum ) );
    return;
	char_from_room(ch);
	char_to_room(ch, get_room_index(vnum));
	return;
}

/*
 * Move a char into a room.
 */
void char_to_room( CHAR_DATA *ch, ROOM_INDEX_DATA *pRoomIndex )
void 
char_to_room(CHAR_DATA * ch, ROOM_INDEX_DATA * pRoomIndex)
{
    OBJ_DATA *obj;
    AFFECT_DATA *paf;
	OBJ_DATA *obj;
	AFFECT_DATA *paf;

    if ( !ch )
    {
	bug( "Char_to_room: NULL ch!", 0 );
	return;
    }
    if ( !pRoomIndex )
    {
	bug( "Char_to_room: %s -> NULL room!  Putting char in limbo (%d)",
		ch->name, ROOM_VNUM_LIMBO );
        /*
         * This used to just return, but there was a problem with crashing
         * and I saw no reason not to just put the char in limbo.  -Narn
         */
        pRoomIndex = get_room_index( ROOM_VNUM_LIMBO );
    }

    ch->in_room		= pRoomIndex;
    LINK( ch, pRoomIndex->first_person, pRoomIndex->last_person,
    	      next_in_room, prev_in_room );

    if ( !IS_NPC(ch) )
	if ( ++pRoomIndex->area->nplayer > pRoomIndex->area->max_players )
	    pRoomIndex->area->max_players = pRoomIndex->area->nplayer;

    if ( (obj=get_eq_char(ch, WEAR_LIGHT)) != NULL
    &&   obj->item_type == ITEM_LIGHT
    &&   obj->value[2] != 0 )
	++pRoomIndex->light;

    /*
     * Room's effect on the character
     */
    if ( !char_died(ch) )
    {
	for ( paf = pRoomIndex->first_affect; paf; paf = paf->next )
	    affect_modify(ch, paf, true);

	if ( char_died(ch) )	/* could die from a wearspell, etc */
	    return;
    }

    /*
     * Character's effect on the room
     */
    for ( paf = ch->first_affect; paf; paf = paf->next )
	room_affect(pRoomIndex, paf, true);


    if ( !IS_NPC(ch)
    &&    xIS_SET(pRoomIndex->room_flags, ROOM_SAFE)
    &&    get_timer(ch, TIMER_SHOVEDRAG) <= 0 )
	add_timer(ch, TIMER_SHOVEDRAG, 10, NULL, 0);  /*-30 Seconds-*/

    if( !IS_NPC( ch )
     && xIS_SET( pRoomIndex->room_flags, ROOM_TIME_CHAMBER ) )
    {
      if( ch->pcdata->HBTCTimeLeft <= 0 )
      {
        ch->pcdata->HBTCTimeLeft = 15;
      }

      if( ch->pcdata->nextHBTCDate <= 0 )
      {
        struct tm *tms;

        tms = localtime(&current_time);
        tms->tm_mday += 2;
        ch->pcdata->nextHBTCDate = mktime(tms);
      }
    }

    /*
     * Delayed Teleport rooms					-Thoric
     * Should be the last thing checked in this function
     */
    if ( xIS_SET(pRoomIndex->room_flags, ROOM_TELEPORT)
    &&	 pRoomIndex->tele_delay > 0 )
    {
	TELEPORT_DATA *tele;

	for ( tele = first_teleport; tele; tele = tele->next )
	    if ( tele->room == pRoomIndex )
	if (!ch) {
		bug("Char_to_room: NULL ch!", 0);
		return;
	}
	if (!pRoomIndex) {
		bug("Char_to_room: %s -> NULL room!  Putting char in limbo (%d)",
		    ch->name, ROOM_VNUM_LIMBO);
		/*
	         * This used to just return, but there was a problem with crashing
	         * and I saw no reason not to just put the char in limbo.  -Narn
	         */
		pRoomIndex = get_room_index(ROOM_VNUM_LIMBO);
	}
	ch->in_room = pRoomIndex;
	LINK(ch, pRoomIndex->first_person, pRoomIndex->last_person,
	    next_in_room, prev_in_room);

	if (!IS_NPC(ch))
		if (++pRoomIndex->area->nplayer > pRoomIndex->area->max_players)
			pRoomIndex->area->max_players = pRoomIndex->area->nplayer;

	if ((obj = get_eq_char(ch, WEAR_LIGHT)) != NULL
	    && obj->item_type == ITEM_LIGHT
	    && obj->value[2] != 0)
		++pRoomIndex->light;

	/*
         * Room's effect on the character
         */
	if (!char_died(ch)) {
		for (paf = pRoomIndex->first_affect; paf; paf = paf->next)
			affect_modify(ch, paf, true);

		if (char_died(ch))	/* could die from a wearspell, etc */
			return;
	}
	/*
         * Character's effect on the room
         */
	for (paf = ch->first_affect; paf; paf = paf->next)
		room_affect(pRoomIndex, paf, true);


	if (!IS_NPC(ch)
	    && xIS_SET(pRoomIndex->room_flags, ROOM_SAFE)
	    && get_timer(ch, TIMER_SHOVEDRAG) <= 0)
		add_timer(ch, TIMER_SHOVEDRAG, 10, NULL, 0);	/*-30 Seconds-*/

	if (!IS_NPC(ch)
	    && xIS_SET(pRoomIndex->room_flags, ROOM_TIME_CHAMBER)) {
		if (ch->pcdata->HBTCTimeLeft <= 0) {
			ch->pcdata->HBTCTimeLeft = 15;
		}
		if (ch->pcdata->nextHBTCDate <= 0) {
			struct tm *tms;

	CREATE( tele, TELEPORT_DATA, 1 );
	LINK( tele, first_teleport, last_teleport, next, prev );
	tele->room		= pRoomIndex;
	tele->timer		= pRoomIndex->tele_delay;
    }
    if ( !ch->was_in_room )
    	ch->was_in_room = ch->in_room;
    return;
			tms = localtime(&current_time);
			tms->tm_mday += 2;
			ch->pcdata->nextHBTCDate = mktime(tms);
		}
	}
	/*
         * Delayed Teleport rooms					-Thoric
         * Should be the last thing checked in this function
         */
	if (xIS_SET(pRoomIndex->room_flags, ROOM_TELEPORT)
	    && pRoomIndex->tele_delay > 0) {
		TELEPORT_DATA *tele;

		for (tele = first_teleport; tele; tele = tele->next)
			if (tele->room == pRoomIndex)
				return;

		CREATE(tele, TELEPORT_DATA, 1);
		LINK(tele, first_teleport, last_teleport, next, prev);
		tele->room = pRoomIndex;
		tele->timer = pRoomIndex->tele_delay;
	}
	if (!ch->was_in_room)
		ch->was_in_room = ch->in_room;
	return;
}

/*
 * Give an obj to a char.
 */
OBJ_DATA *obj_to_char( OBJ_DATA *obj, CHAR_DATA *ch )
{
    OBJ_DATA *otmp;
    OBJ_DATA *oret = obj;
    bool skipgroup, grouped;
    int oweight = get_obj_weight(obj);
    int onum = get_obj_number(obj);
    int wear_loc = obj->wear_loc;
    EXT_BV extra_flags = obj->extra_flags;

    skipgroup = false;
    grouped = false;


    if (IS_OBJ_STAT( obj, ITEM_PROTOTYPE ) )
    {
	if (!IS_IMMORTAL( ch )
	&& (IS_NPC(ch) && !xIS_SET(ch->act, ACT_PROTOTYPE)) )
	  return obj_to_room( obj, ch->in_room );
    }

    if ( loading_char == ch )
    {
	int x,y;
	for ( x = 0; x < MAX_WEAR; x++ )
	    for ( y = 0; y < MAX_LAYERS; y++ )
		if ( save_equipment[x][y] == obj )
		{
		    skipgroup = true;
		    break;
		}
    }
OBJ_DATA *
obj_to_char(OBJ_DATA * obj, CHAR_DATA * ch)
{
	OBJ_DATA *otmp;
	OBJ_DATA *oret = obj;
	bool 	skipgroup, grouped;
	int 	oweight = get_obj_weight(obj);
	int 	onum = get_obj_number(obj);
	int 	wear_loc = obj->wear_loc;
	EXT_BV 	extra_flags = obj->extra_flags;

    if ( !skipgroup )
	for ( otmp = ch->first_carrying; otmp; otmp = otmp->next_content )
	    if ( (oret=group_object( otmp, obj )) == otmp )
	    {
		grouped = true;
		break;
	    }
    if ( !grouped )
    {
	if (!IS_NPC(ch) || !ch->pIndexData->pShop)
	{
	    LINK( obj, ch->first_carrying, ch->last_carrying,
		next_content, prev_content );
	    obj->carried_by                 = ch;
	    obj->in_room                    = NULL;
	    obj->in_obj                     = NULL;
        }
        else
        {
	    /* If ch is a shopkeeper, add the obj using an insert sort */
	    for ( otmp = ch->first_carrying; otmp; otmp = otmp->next_content)
	    {
		if ( obj->level > otmp->level )
		{
		    INSERT(obj, otmp, ch->first_carrying,
			next_content, prev_content);
		    break;
		}
		else
		if ( obj->level == otmp->level
		&&   strcmp(obj->short_descr,otmp->short_descr) < 0 )
		{
		    INSERT(obj, otmp, ch->first_carrying,
			next_content, prev_content);
		    break;
		}
	    }
	skipgroup = false;
	grouped = false;

	    if ( !otmp )
	    {
		LINK(obj, ch->first_carrying, ch->last_carrying,
		    next_content, prev_content);
	    }

	    obj->carried_by = ch;
	    obj->in_room = NULL;
	    obj->in_obj = NULL;
	if (IS_OBJ_STAT(obj, ITEM_PROTOTYPE)) {
		if (!IS_IMMORTAL(ch)
		    && (IS_NPC(ch) && !xIS_SET(ch->act, ACT_PROTOTYPE)))
			return obj_to_room(obj, ch->in_room);
	}
	if (loading_char == ch) {
		int 	x , y;

		for (x = 0; x < MAX_WEAR; x++)
			for (y = 0; y < MAX_LAYERS; y++)
				if (save_equipment[x][y] == obj) {
					skipgroup = true;
					break;
				}
	}
	if (!skipgroup)
		for (otmp = ch->first_carrying; otmp; otmp = otmp->next_content)
			if ((oret = group_object(otmp, obj)) == otmp) {
				grouped = true;
				break;
			}
	if (!grouped) {
		if (!IS_NPC(ch) || !ch->pIndexData->pShop) {
			LINK(obj, ch->first_carrying, ch->last_carrying,
			    next_content, prev_content);
			obj->carried_by = ch;
			obj->in_room = NULL;
			obj->in_obj = NULL;
		} else {
			/*
			 * If ch is a shopkeeper, add the obj using an
			 * insert sort
			 */
			for (otmp = ch->first_carrying; otmp; otmp = otmp->next_content) {
				if (obj->level > otmp->level) {
					INSERT(obj, otmp, ch->first_carrying,
					    next_content, prev_content);
					break;
				} else if (obj->level == otmp->level
				    && strcmp(obj->short_descr, otmp->short_descr) < 0) {
					INSERT(obj, otmp, ch->first_carrying,
					    next_content, prev_content);
					break;
				}
			}

			if (!otmp) {
				LINK(obj, ch->first_carrying, ch->last_carrying,
				    next_content, prev_content);
			}
			obj->carried_by = ch;
			obj->in_room = NULL;
			obj->in_obj = NULL;
		}
	}
    }
    if (wear_loc == WEAR_NONE)
    {
	ch->carry_number	+= onum;
	ch->carry_weight	+= oweight;
    }
    else
    if ( !xIS_SET(extra_flags, ITEM_MAGIC) )
	ch->carry_weight	+= oweight;
    return (oret ? oret : obj);
	if (wear_loc == WEAR_NONE) {
		ch->carry_number += onum;
		ch->carry_weight += oweight;
	} else if (!xIS_SET(extra_flags, ITEM_MAGIC))
		ch->carry_weight += oweight;
	return (oret ? oret : obj);
}




@@ 1311,33 1374,32 @@ OBJ_DATA *obj_to_char( OBJ_DATA *obj, CHAR_DATA *ch )
/*
 * Take an obj from its character.
 */
void obj_from_char( OBJ_DATA *obj )
void 
obj_from_char(OBJ_DATA * obj)
{
    CHAR_DATA *ch;

    if ( ( ch = obj->carried_by ) == NULL )
    {
	bug( "Obj_from_char: null ch.", 0 );
	return;
    }
	CHAR_DATA *ch;

    if ( obj->wear_loc != WEAR_NONE )
	unequip_char( ch, obj );
	if ((ch = obj->carried_by) == NULL) {
		bug("Obj_from_char: null ch.", 0);
		return;
	}
	if (obj->wear_loc != WEAR_NONE)
		unequip_char(ch, obj);

    /* obj may drop during unequip... */
    if ( !obj->carried_by )
      return;
	/* obj may drop during unequip... */
	if (!obj->carried_by)
		return;

    UNLINK( obj, ch->first_carrying, ch->last_carrying, next_content, prev_content );
	UNLINK(obj, ch->first_carrying, ch->last_carrying, next_content, prev_content);

    if ( IS_OBJ_STAT(obj, ITEM_COVERING) && obj->first_content )
	empty_obj( obj, NULL, NULL );
	if (IS_OBJ_STAT(obj, ITEM_COVERING) && obj->first_content)
		empty_obj(obj, NULL, NULL);

    obj->in_room	 = NULL;
    obj->carried_by	 = NULL;
    ch->carry_number	-= get_obj_number(obj);
    ch->carry_weight	-= get_obj_weight(obj);
    return;
	obj->in_room = NULL;
	obj->carried_by = NULL;
	ch->carry_number -= get_obj_number(obj);
	ch->carry_weight -= get_obj_weight(obj);
	return;
}




@@ 1346,37 1408,58 @@ void obj_from_char( OBJ_DATA *obj )
 *
 * Removed position effect for new AC system   -Warren
 */
int apply_ac( OBJ_DATA *obj, int iWear )
{
    if ( obj->item_type != ITEM_ARMOR )
	return 0;
int 
apply_ac(OBJ_DATA * obj, int iWear)
{
	if (obj->item_type != ITEM_ARMOR)
		return 0;

	switch (iWear) {
	case WEAR_BODY:
		return obj->value[0];
	case WEAR_HEAD:
		return obj->value[0];
	case WEAR_LEGS:
		return obj->value[0];
	case WEAR_FEET:
		return obj->value[0];
	case WEAR_HANDS:
		return obj->value[0];
	case WEAR_ARMS:
		return obj->value[0];
	case WEAR_SHIELD:
		return obj->value[0];
	case WEAR_FINGER_L:
		return obj->value[0];
	case WEAR_FINGER_R:
		return obj->value[0];
	case WEAR_NECK_1:
		return obj->value[0];
	case WEAR_NECK_2:
		return obj->value[0];
	case WEAR_ABOUT:
		return obj->value[0];
	case WEAR_WAIST:
		return obj->value[0];
	case WEAR_WRIST_L:
		return obj->value[0];
	case WEAR_WRIST_R:
		return obj->value[0];
	case WEAR_HOLD:
		return obj->value[0];
	case WEAR_EYES:
		return obj->value[0];
	case WEAR_FACE:
		return obj->value[0];
	case WEAR_BACK:
		return obj->value[0];
	case WEAR_ANKLE_L:
		return obj->value[0];
	case WEAR_ANKLE_R:
		return obj->value[0];
	}

    switch ( iWear )
    {
    case WEAR_BODY:	return  obj->value[0];
    case WEAR_HEAD:	return  obj->value[0];
    case WEAR_LEGS:	return  obj->value[0];
    case WEAR_FEET:	return     obj->value[0];
    case WEAR_HANDS:	return     obj->value[0];
    case WEAR_ARMS:	return     obj->value[0];
    case WEAR_SHIELD:	return     obj->value[0];
    case WEAR_FINGER_L:	return     obj->value[0];
    case WEAR_FINGER_R: return     obj->value[0];
    case WEAR_NECK_1:	return     obj->value[0];
    case WEAR_NECK_2:	return     obj->value[0];
    case WEAR_ABOUT:	return  obj->value[0];
    case WEAR_WAIST:	return     obj->value[0];
    case WEAR_WRIST_L:	return     obj->value[0];
    case WEAR_WRIST_R:	return     obj->value[0];
    case WEAR_HOLD:	return     obj->value[0];
    case WEAR_EYES:	return	   obj->value[0];
    case WEAR_FACE:	return	   obj->value[0];
    case WEAR_BACK:	return	   obj->value[0];
    case WEAR_ANKLE_L:	return	   obj->value[0];
    case WEAR_ANKLE_R:	return	   obj->value[0];
    }

    return 0;
	return 0;
}




@@ 1385,20 1468,20 @@ int apply_ac( OBJ_DATA *obj, int iWear )
 * Find a piece of eq on a character.
 * Will pick the top layer if clothing is layered.		-Thoric
 */
OBJ_DATA *get_eq_char( CHAR_DATA *ch, int iWear )
OBJ_DATA *
get_eq_char(CHAR_DATA * ch, int iWear)
{
    OBJ_DATA *obj, *maxobj = NULL;
	OBJ_DATA *obj, *maxobj = NULL;

    for ( obj = ch->first_carrying; obj; obj = obj->next_content )
	if ( obj->wear_loc == iWear ) {
	    if ( !obj->pIndexData->layers )
		return obj;
	    else
	    if ( !maxobj
	    ||    obj->pIndexData->layers > maxobj->pIndexData->layers )
		maxobj = obj;
	}
    return maxobj;
	for (obj = ch->first_carrying; obj; obj = obj->next_content)
		if (obj->wear_loc == iWear) {
			if (!obj->pIndexData->layers)
				return obj;
			else if (!maxobj
			    || obj->pIndexData->layers > maxobj->pIndexData->layers)
				maxobj = obj;
		}
	return maxobj;
}




@@ 1406,68 1489,61 @@ OBJ_DATA *get_eq_char( CHAR_DATA *ch, int iWear )
/*
 * Equip a char with an obj.
 */
void equip_char( CHAR_DATA *ch, OBJ_DATA *obj, int iWear )
void 
equip_char(CHAR_DATA * ch, OBJ_DATA * obj, int iWear)
{
    AFFECT_DATA *paf;
    OBJ_DATA	*otmp;
	AFFECT_DATA *paf;
	OBJ_DATA *otmp;

    if ( (otmp=get_eq_char( ch, iWear )) != NULL
    &&   (!otmp->pIndexData->layers || !obj->pIndexData->layers) )
    {
	bug( "Equip_char: already equipped (%d).", iWear );
	return;
    }

    if( obj->carried_by != ch )
    {
        bug( "equip_char: obj not being carried by ch!" );
        return;
    }

    separate_obj(obj);	/* just in case */
    if ( (( IS_OBJ_STAT(obj, ITEM_ANTI_EVIL)    && IS_EVIL(ch)    )
    ||   ( IS_OBJ_STAT(obj, ITEM_ANTI_GOOD)    && IS_GOOD(ch)    )
    ||   ( IS_OBJ_STAT(obj, ITEM_ANTI_NEUTRAL) && IS_NEUTRAL(ch) ))
    && !IS_HC(ch) )
    {
	/*
	 * Thanks to Morgenes for the bug fix here!
	 */
	if ( loading_char != ch )
	{
	   act( AT_MAGIC, "You are zapped by $p and remove it.", ch, obj, NULL, TO_CHAR );
	   act( AT_MAGIC, "$n is zapped by $p and removes it.",  ch, obj, NULL, TO_ROOM );
	if ((otmp = get_eq_char(ch, iWear)) != NULL
	    && (!otmp->pIndexData->layers || !obj->pIndexData->layers)) {
		bug("Equip_char: already equipped (%d).", iWear);
		return;
	}
	if ( obj->carried_by )
	{
	   obj_from_char( obj );
	   obj_to_char( obj, ch );
	if (obj->carried_by != ch) {
		bug("equip_char: obj not being carried by ch!");
		return;
	}
	/*obj_to_room( obj, ch->in_room );*/
	oprog_zap_trigger( ch, obj);
	if ( IS_SET(sysdata.save_flags, SV_ZAPDROP) && !char_died(ch) )
	    save_char_obj( ch );
	return;
    }

    ch->armor      	-= apply_ac( obj, iWear );
    obj->wear_loc	 = iWear;
	separate_obj(obj);		/* just in case */
	if (((IS_OBJ_STAT(obj, ITEM_ANTI_EVIL) && IS_EVIL(ch))
		|| (IS_OBJ_STAT(obj, ITEM_ANTI_GOOD) && IS_GOOD(ch))
		|| (IS_OBJ_STAT(obj, ITEM_ANTI_NEUTRAL) && IS_NEUTRAL(ch)))
	    && !IS_HC(ch)) {
		/*
		 * Thanks to Morgenes for the bug fix here!
		 */
		if (loading_char != ch) {
			act(AT_MAGIC, "You are zapped by $p and remove it.", ch, obj, NULL, TO_CHAR);
			act(AT_MAGIC, "$n is zapped by $p and removes it.", ch, obj, NULL, TO_ROOM);
		}
		if (obj->carried_by) {
			obj_from_char(obj);
			obj_to_char(obj, ch);
		}
		/* obj_to_room( obj, ch->in_room ); */
		oprog_zap_trigger(ch, obj);
		if (IS_SET(sysdata.save_flags, SV_ZAPDROP) && !char_died(ch))
			save_char_obj(ch);
		return;
	}
	ch->armor -= apply_ac(obj, iWear);
	obj->wear_loc = iWear;

    ch->carry_number	-= get_obj_number( obj );
    if ( IS_OBJ_STAT(obj, ITEM_MAGIC) )
      ch->carry_weight  -= get_obj_weight( obj );
	ch->carry_number -= get_obj_number(obj);
	if (IS_OBJ_STAT(obj, ITEM_MAGIC))
		ch->carry_weight -= get_obj_weight(obj);

    for ( paf = obj->pIndexData->first_affect; paf; paf = paf->next )
	affect_modify( ch, paf, true );
    for ( paf = obj->first_affect; paf; paf = paf->next )
	affect_modify( ch, paf, true );
	for (paf = obj->pIndexData->first_affect; paf; paf = paf->next)
		affect_modify(ch, paf, true);
	for (paf = obj->first_affect; paf; paf = paf->next)
		affect_modify(ch, paf, true);

    if ( obj->item_type == ITEM_LIGHT
    &&   obj->value[2] != 0
    &&   ch->in_room )
	++ch->in_room->light;
	if (obj->item_type == ITEM_LIGHT
	    && obj->value[2] != 0
	    && ch->in_room)
		++ch->in_room->light;

    return;
	return;
}




@@ 1475,41 1551,40 @@ void equip_char( CHAR_DATA *ch, OBJ_DATA *obj, int iWear )
/*
 * Unequip a char with an obj.
 */
void unequip_char( CHAR_DATA *ch, OBJ_DATA *obj )
void 
unequip_char(CHAR_DATA * ch, OBJ_DATA * obj)
{
    AFFECT_DATA *paf;

    if ( obj->wear_loc == WEAR_NONE )
    {
	bug( "Unequip_char: already unequipped.", 0 );
	return;
    }
	AFFECT_DATA *paf;

    ch->carry_number	+= get_obj_number( obj );
    if ( IS_OBJ_STAT(obj, ITEM_MAGIC) )
	ch->carry_weight  += get_obj_weight( obj );
	if (obj->wear_loc == WEAR_NONE) {
		bug("Unequip_char: already unequipped.", 0);
		return;
	}
	ch->carry_number += get_obj_number(obj);
	if (IS_OBJ_STAT(obj, ITEM_MAGIC))
		ch->carry_weight += get_obj_weight(obj);

    ch->armor		+= apply_ac( obj, obj->wear_loc );
    obj->wear_loc	 = -1;
	ch->armor += apply_ac(obj, obj->wear_loc);
	obj->wear_loc = -1;

    for ( paf = obj->pIndexData->first_affect; paf; paf = paf->next )
	affect_modify( ch, paf, false );
    if ( obj->carried_by )
      for ( paf = obj->first_affect; paf; paf = paf->next )
	affect_modify( ch, paf, false );
	for (paf = obj->pIndexData->first_affect; paf; paf = paf->next)
		affect_modify(ch, paf, false);
	if (obj->carried_by)
		for (paf = obj->first_affect; paf; paf = paf->next)
			affect_modify(ch, paf, false);

    update_aris(ch);
	update_aris(ch);

    if ( !obj->carried_by )
      return;
	if (!obj->carried_by)
		return;

    if ( obj->item_type == ITEM_LIGHT
    &&   obj->value[2] != 0
    &&   ch->in_room
    &&   ch->in_room->light > 0 )
	--ch->in_room->light;
	if (obj->item_type == ITEM_LIGHT
	    && obj->value[2] != 0
	    && ch->in_room
	    && ch->in_room->light > 0)
		--ch->in_room->light;

    return;
	return;
}




@@ 1517,23 1592,22 @@ void unequip_char( CHAR_DATA *ch, OBJ_DATA *obj )
/*
 * Count occurrences of an obj in a list.
 */
int count_obj_list( OBJ_INDEX_DATA *pObjIndex, OBJ_DATA *list )
int 
count_obj_list(OBJ_INDEX_DATA * pObjIndex, OBJ_DATA * list)
{
    OBJ_DATA *obj;
    int nMatch = 0;

    for ( obj = list; obj; obj = obj->next_content )
    {
	if ( obj->pIndexData == pObjIndex )
	{
		if ( obj->count > 1 )
			nMatch += obj->count;
		else
			nMatch ++;
	OBJ_DATA *obj;
	int 	nMatch = 0;

	for (obj = list; obj; obj = obj->next_content) {
		if (obj->pIndexData == pObjIndex) {
			if (obj->count > 1)
				nMatch += obj->count;
			else
				nMatch++;
		}
	}
    }

    return nMatch;
	return nMatch;
}




@@ 1541,163 1615,160 @@ int count_obj_list( OBJ_INDEX_DATA *pObjIndex, OBJ_DATA *list )
/*
 * Move an obj out of a room.
 */
void	write_corpses	args( ( CHAR_DATA *ch, char *name, OBJ_DATA *objrem ) );
void write_corpses args((CHAR_DATA * ch, char *name, OBJ_DATA * objrem));

int falling;
int 	falling;

void obj_from_room( OBJ_DATA *obj )
void 
obj_from_room(OBJ_DATA * obj)
{
    ROOM_INDEX_DATA *in_room;
    AFFECT_DATA *paf;

    if ( (in_room = obj->in_room) == NULL )
    {
	bug( "obj_from_room: NULL.", 0 );
	return;
    }
	ROOM_INDEX_DATA *in_room;
	AFFECT_DATA *paf;

    for ( paf = obj->first_affect; paf; paf = paf->next )
	room_affect(in_room, paf, false);
	if ((in_room = obj->in_room) == NULL) {
		bug("obj_from_room: NULL.", 0);
		return;
	}
	for (paf = obj->first_affect; paf; paf = paf->next)
		room_affect(in_room, paf, false);

    for ( paf = obj->pIndexData->first_affect; paf; paf = paf->next )
	room_affect(in_room, paf, false);
	for (paf = obj->pIndexData->first_affect; paf; paf = paf->next)
		room_affect(in_room, paf, false);

    UNLINK( obj, in_room->first_content, in_room->last_content,
	next_content, prev_content );
	UNLINK(obj, in_room->first_content, in_room->last_content,
	    next_content, prev_content);

    /* uncover contents */
    if ( IS_OBJ_STAT( obj, ITEM_COVERING ) && obj->first_content )
	empty_obj( obj, NULL, obj->in_room );
	/* uncover contents */
	if (IS_OBJ_STAT(obj, ITEM_COVERING) && obj->first_content)
		empty_obj(obj, NULL, obj->in_room);

    if ( obj->item_type == ITEM_FIRE )
	  obj->in_room->light -= obj->count;
	if (obj->item_type == ITEM_FIRE)
		obj->in_room->light -= obj->count;

    obj->carried_by   = NULL;
    obj->in_obj	      = NULL;
    obj->in_room      = NULL;
    if ( obj->pIndexData->vnum == OBJ_VNUM_CORPSE_PC && falling < 1 )
	write_corpses( NULL, obj->short_descr+14, obj );
    return;
	obj->carried_by = NULL;
	obj->in_obj = NULL;
	obj->in_room = NULL;
	if (obj->pIndexData->vnum == OBJ_VNUM_CORPSE_PC && falling < 1)
		write_corpses(NULL, obj->short_descr + 14, obj);
	return;
}


/*
 * Move an obj into a room.
 */
OBJ_DATA *obj_to_room( OBJ_DATA *obj, ROOM_INDEX_DATA *pRoomIndex )
OBJ_DATA *
obj_to_room(OBJ_DATA * obj, ROOM_INDEX_DATA * pRoomIndex)
{
    OBJ_DATA *otmp, *oret;
    sh_int count = obj->count;
    sh_int item_type = obj->item_type;
    AFFECT_DATA *paf;
	OBJ_DATA *otmp, *oret;
	sh_int 	count = obj->count;
	sh_int 	item_type = obj->item_type;
	AFFECT_DATA *paf;

    for ( paf = obj->first_affect; paf; paf = paf->next )
	room_affect(pRoomIndex, paf, true);
	for (paf = obj->first_affect; paf; paf = paf->next)
		room_affect(pRoomIndex, paf, true);

    for ( paf = obj->pIndexData->first_affect; paf; paf = paf->next )
	room_affect(pRoomIndex, paf, true);
	for (paf = obj->pIndexData->first_affect; paf; paf = paf->next)
		room_affect(pRoomIndex, paf, true);

    for ( otmp = pRoomIndex->first_content; otmp; otmp = otmp->next_content )
	if ( (oret=group_object( otmp, obj )) == otmp )
	{
	    if ( item_type == ITEM_FIRE )
	for (otmp = pRoomIndex->first_content; otmp; otmp = otmp->next_content)
		if ((oret = group_object(otmp, obj)) == otmp) {
			if (item_type == ITEM_FIRE)
				pRoomIndex->light += count;
			return oret;
		}
	LINK(obj, pRoomIndex->first_content, pRoomIndex->last_content,
	    next_content, prev_content);
	obj->in_room = pRoomIndex;
	obj->carried_by = NULL;
	obj->in_obj = NULL;
	if (item_type == ITEM_FIRE)
		pRoomIndex->light += count;
	    return oret;
	}

    LINK( obj, pRoomIndex->first_content, pRoomIndex->last_content,
    	       next_content, prev_content );
    obj->in_room				= pRoomIndex;
    obj->carried_by				= NULL;
    obj->in_obj					= NULL;
    if ( item_type == ITEM_FIRE )
	pRoomIndex->light += count;
    falling++;
    obj_fall( obj, false );
    falling--;
    if ( obj->pIndexData->vnum == OBJ_VNUM_CORPSE_PC && falling < 1 )
	write_corpses( NULL, obj->short_descr+14, NULL );
    return obj;
	falling++;
	obj_fall(obj, false);
	falling--;
	if (obj->pIndexData->vnum == OBJ_VNUM_CORPSE_PC && falling < 1)
		write_corpses(NULL, obj->short_descr + 14, NULL);
	return obj;
}


/*
 * Who's carrying an item -- recursive for nested objects	-Thoric
 */
CHAR_DATA *carried_by( OBJ_DATA *obj )
CHAR_DATA *
carried_by(OBJ_DATA * obj)
{
    if ( obj->in_obj )
	return carried_by(obj->in_obj);
	if (obj->in_obj)
		return carried_by(obj->in_obj);

    return obj->carried_by;
	return obj->carried_by;
}


/*
 * Move an object into an object.
 */
OBJ_DATA *obj_to_obj( OBJ_DATA *obj, OBJ_DATA *obj_to )
OBJ_DATA *
obj_to_obj(OBJ_DATA * obj, OBJ_DATA * obj_to)
{
    OBJ_DATA *otmp, *oret;
    CHAR_DATA *who;

    if ( obj == obj_to )
    {
	bug( "Obj_to_obj: trying to put object inside itself: vnum %d", obj->pIndexData->vnum );
	return obj;
    }
	OBJ_DATA *otmp, *oret;
	CHAR_DATA *who;

    if ( !in_magic_container(obj_to) && (who=carried_by(obj_to)) != NULL )
	who->carry_weight += get_obj_weight(obj);
	if (obj == obj_to) {
		bug("Obj_to_obj: trying to put object inside itself: vnum %d", obj->pIndexData->vnum);
		return obj;
	}
	if (!in_magic_container(obj_to) && (who = carried_by(obj_to)) != NULL)
		who->carry_weight += get_obj_weight(obj);

    for ( otmp = obj_to->first_content; otmp; otmp = otmp->next_content )
	if ( (oret=group_object(otmp, obj)) == otmp )
	    return oret;
	for (otmp = obj_to->first_content; otmp; otmp = otmp->next_content)
		if ((oret = group_object(otmp, obj)) == otmp)
			return oret;

    LINK( obj, obj_to->first_content, obj_to->last_content,
	next_content, prev_content );
	LINK(obj, obj_to->first_content, obj_to->last_content,
	    next_content, prev_content);

    obj->in_obj				 = obj_to;
    obj->in_room			 = NULL;
    obj->carried_by			 = NULL;
	obj->in_obj = obj_to;
	obj->in_room = NULL;
	obj->carried_by = NULL;

    return obj;
	return obj;
}


/*
 * Move an object out of an object.
 */
void obj_from_obj( OBJ_DATA *obj )
void 
obj_from_obj(OBJ_DATA * obj)
{
    OBJ_DATA *obj_from;
    bool magic;

    if ( (obj_from = obj->in_obj) == NULL )
    {
	bug( "Obj_from_obj: null obj_from.", 0 );
	return;
    }
	OBJ_DATA *obj_from;
	bool 	magic;

    magic = in_magic_container(obj_from);
	if ((obj_from = obj->in_obj) == NULL) {
		bug("Obj_from_obj: null obj_from.", 0);
		return;
	}
	magic = in_magic_container(obj_from);

    UNLINK( obj, obj_from->first_content, obj_from->last_content,
	next_content, prev_content );
	UNLINK(obj, obj_from->first_content, obj_from->last_content,
	    next_content, prev_content);

    /* uncover contents */
    if ( IS_OBJ_STAT(obj, ITEM_COVERING) && obj->first_content )
	empty_obj(obj, obj->in_obj, NULL);
	/* uncover contents */
	if (IS_OBJ_STAT(obj, ITEM_COVERING) && obj->first_content)
		empty_obj(obj, obj->in_obj, NULL);

    obj->in_obj       = NULL;
    obj->in_room      = NULL;
    obj->carried_by   = NULL;
	obj->in_obj = NULL;
	obj->in_room = NULL;
	obj->carried_by = NULL;

    if ( !magic )
	for ( ; obj_from; obj_from = obj_from->in_obj )
	    if ( obj_from->carried_by )
		obj_from->carried_by->carry_weight -= get_obj_weight( obj );
	if (!magic)
		for (; obj_from; obj_from = obj_from->in_obj)
			if (obj_from->carried_by)
				obj_from->carried_by->carry_weight -= get_obj_weight(obj);

    return;
	return;
}




@@ 1705,77 1776,71 @@ void obj_from_obj( OBJ_DATA *obj )
/*
 * Extract an obj from the world.
 */
void extract_obj( OBJ_DATA *obj )
void 
extract_obj(OBJ_DATA * obj)
{
    OBJ_DATA *obj_content;

    if ( obj_extracted(obj) )
    {
	bug( "extract_obj: obj %d already extracted!", obj->pIndexData->vnum );
	return;
    }

    if ( obj->item_type == ITEM_PORTAL )
      remove_portal( obj );
	OBJ_DATA *obj_content;

    if ( obj->carried_by )
	obj_from_char( obj );
    else
    if ( obj->in_room )
	obj_from_room( obj );
    else
    if ( obj->in_obj )
	obj_from_obj( obj );
	if (obj_extracted(obj)) {
		bug("extract_obj: obj %d already extracted!", obj->pIndexData->vnum);
		return;
	}
	if (obj->item_type == ITEM_PORTAL)
		remove_portal(obj);

    while ( ( obj_content = obj->last_content ) != NULL )
	extract_obj( obj_content );
	if (obj->carried_by)
		obj_from_char(obj);
	else if (obj->in_room)
		obj_from_room(obj);
	else if (obj->in_obj)
		obj_from_obj(obj);

    /* remove affects */
    {
	AFFECT_DATA *paf;
	AFFECT_DATA *paf_next;
	while ((obj_content = obj->last_content) != NULL)
		extract_obj(obj_content);

	for ( paf = obj->first_affect; paf; paf = paf_next )
	/* remove affects */
	{
	    paf_next    = paf->next;
	    DISPOSE( paf );
	}
	obj->first_affect = obj->last_affect = NULL;
    }
		AFFECT_DATA *paf;
		AFFECT_DATA *paf_next;

    /* remove extra descriptions */
    {
	EXTRA_DESCR_DATA *ed;
	EXTRA_DESCR_DATA *ed_next;
		for (paf = obj->first_affect; paf; paf = paf_next) {
			paf_next = paf->next;
			DISPOSE(paf);
		}
		obj->first_affect = obj->last_affect = NULL;
	}

	for ( ed = obj->first_extradesc; ed; ed = ed_next )
	/* remove extra descriptions */
	{
	    ed_next = ed->next;
	    STRFREE( ed->description );
	    STRFREE( ed->keyword     );
	    DISPOSE( ed );
		EXTRA_DESCR_DATA *ed;
		EXTRA_DESCR_DATA *ed_next;

		for (ed = obj->first_extradesc; ed; ed = ed_next) {
			ed_next = ed->next;
			STRFREE(ed->description);
			STRFREE(ed->keyword);
			DISPOSE(ed);
		}
		obj->first_extradesc = obj->last_extradesc = NULL;
	}
	obj->first_extradesc = obj->last_extradesc = NULL;
    }

    if ( obj == gobj_prev )
	gobj_prev = obj->prev;
	if (obj == gobj_prev)
		gobj_prev = obj->prev;

    UNLINK( obj, first_object, last_object, next, prev );
	UNLINK(obj, first_object, last_object, next, prev);

    /* shove onto extraction queue */
    queue_extracted_obj( obj );
	/* shove onto extraction queue */
	queue_extracted_obj(obj);

    obj->pIndexData->count -= obj->count;
    numobjsloaded -= obj->count;
    --physicalobjects;
    if ( obj->serial == cur_obj )
    {
	cur_obj_extracted = true;
	if ( global_objcode == rNONE )
	    global_objcode = rOBJ_EXTRACTED;
    }
    return;
	obj->pIndexData->count -= obj->count;
	numobjsloaded -= obj->count;
	--physicalobjects;
	if (obj->serial == cur_obj) {
		cur_obj_extracted = true;
		if (global_objcode == rNONE)
			global_objcode = rOBJ_EXTRACTED;
	}
	return;
}




@@ 1783,247 1848,205 @@ void extract_obj( OBJ_DATA *obj )
/*
 * Extract a char from the world.
 */
void new_extract_char( CHAR_DATA *ch, bool fPull, bool death )
void 
new_extract_char(CHAR_DATA * ch, bool fPull, bool death)
{
    CHAR_DATA *wch;
    OBJ_DATA *obj;
    char buf[MAX_STRING_LENGTH];
    ROOM_INDEX_DATA *location;
    ROOM_INDEX_DATA *in_room;

    if ( !ch )
    {
    	bug( "Extract_char: NULL ch.", 0 );
	return;
    }

    if ( !ch->in_room )
    {
	bug( "Extract_char: %s in NULL room.", ch->name ? ch->name : "???" );
	return;
    }

    if ( ch == supermob )
    {
	bug( "Extract_char: ch == supermob!", 0 );
	return;
    }
	CHAR_DATA *wch;
	OBJ_DATA *obj;
	char 	buf[MAX_STRING_LENGTH];
	ROOM_INDEX_DATA *location;
	ROOM_INDEX_DATA *in_room;

    if ( char_died(ch) )
    {
	bug( "extract_char: %s already died!", ch->name );
	return;
    }
	if (!ch) {
		bug("Extract_char: NULL ch.", 0);
		return;
	}
	if (!ch->in_room) {
		bug("Extract_char: %s in NULL room.", ch->name ? ch->name : "???");
		return;
	}
	if (ch == supermob) {
		bug("Extract_char: ch == supermob!", 0);
		return;
	}
	if (char_died(ch)) {
		bug("extract_char: %s already died!", ch->name);
		return;
	}
	if (ch == cur_char)
		cur_char_died = true;

    if ( ch == cur_char )
	cur_char_died = true;
	/* shove onto extraction queue */
	queue_extracted_char(ch, fPull);

    /* shove onto extraction queue */
    queue_extracted_char( ch, fPull );
	if (gch_prev == ch)
		gch_prev = ch->prev;
	if (fPull)
		die_follower(ch);

    if ( gch_prev == ch )
	gch_prev = ch->prev;
	stop_fighting(ch, true);

/* DELETE LATER SHADDAI
    if ( fPull && !xIS_SET(ch->act, ACT_POLYMORPHED))
*/
    if ( fPull)
	die_follower( ch );

    stop_fighting( ch, true );

    if ( ch->mount )
    {
	xREMOVE_BIT( ch->mount->act, ACT_MOUNTED );
	ch->mount = NULL;
	ch->position = POS_STANDING;
    }

    /*
     * check if this NPC was a mount or a pet
     */
    if ( IS_NPC(ch) )
    {
	for ( wch = first_char; wch; wch = wch->next )
	{
	    if ( wch->mount == ch )
	    {
		wch->mount = NULL;
		wch->position = POS_STANDING;
		if ( wch->in_room == ch->in_room )
		{
		    act( AT_SOCIAL, "Your faithful mount, $N collapses beneath you...",
		    	wch, NULL, ch, TO_CHAR );
		    act( AT_SOCIAL, "Sadly you dismount $M for the last time.",
			wch, NULL, ch, TO_CHAR );
		    act( AT_PLAIN, "$n sadly dismounts $N for the last time.",
			wch, NULL, ch, TO_ROOM );
	if (ch->mount) {
		xREMOVE_BIT(ch->mount->act, ACT_MOUNTED);
		ch->mount = NULL;
		ch->position = POS_STANDING;
	}
	/*
         * check if this NPC was a mount or a pet
         */
	if (IS_NPC(ch)) {
		for (wch = first_char; wch; wch = wch->next) {
			if (wch->mount == ch) {
				wch->mount = NULL;
				wch->position = POS_STANDING;
				if (wch->in_room == ch->in_room) {
					act(AT_SOCIAL, "Your faithful mount, $N collapses beneath you...",
					    wch, NULL, ch, TO_CHAR);
					act(AT_SOCIAL, "Sadly you dismount $M for the last time.",
					    wch, NULL, ch, TO_CHAR);
					act(AT_PLAIN, "$n sadly dismounts $N for the last time.",
					    wch, NULL, ch, TO_ROOM);
				}
			}
			if (wch->pcdata && wch->pcdata->pet == ch) {
				wch->pcdata->pet = NULL;
				if (wch->in_room == ch->in_room)
					act(AT_SOCIAL, "You mourn for the loss of $N.",
					    wch, NULL, ch, TO_CHAR);
			}
		}
	    }
	    if ( wch->pcdata && wch->pcdata->pet == ch )
	    {
		wch->pcdata->pet = NULL;
		if ( wch->in_room == ch->in_room )
		    act( AT_SOCIAL, "You mourn for the loss of $N.",
			wch, NULL, ch, TO_CHAR );
	    }
	}
    }
    xREMOVE_BIT( ch->act, ACT_MOUNTED );
	xREMOVE_BIT(ch->act, ACT_MOUNTED);

	if (!death)
    {
    	while ( (obj = ch->last_carrying) != NULL )
	if (!death) {
		while ((obj = ch->last_carrying) != NULL)
			extract_obj(obj);
	}

    in_room = ch->in_room;

    char_from_room(ch);

    if ( !fPull )
    {
	location = NULL;

//	if ( !IS_NPC(ch) && ch->pcdata->clan )
//	    location = get_room_index( ch->pcdata->clan->recall );

	if ( !location )
	{
		if ( ch->pcdata->release_date != 0 )
		{
			location = get_room_index(8);
		}
		else
		{
		    if( IS_SET(ch->pcdata->flags, PCFLAG_IMMORTALITY) )
			location = get_room_index( ROOM_VNUM_TEMPLE );
		    else if (is_android(ch) || is_superandroid(ch) )
			    location = get_room_index( ROOM_START_ANDROID );
		    else
			    location = get_room_index( ROOM_VNUM_ALTAR );
	in_room = ch->in_room;

	char_from_room(ch);

	if (!fPull) {
		location = NULL;

		if (!location) {
			if (ch->pcdata->release_date != 0) {
				location = get_room_index(8);
			} else {
				if (IS_SET(ch->pcdata->flags, PCFLAG_IMMORTALITY))
					location = get_room_index(ROOM_VNUM_TEMPLE);
				else if (is_android(ch) || is_superandroid(ch))
					location = get_room_index(ROOM_START_ANDROID);
				else
					location = get_room_index(ROOM_VNUM_ALTAR);
			}
		}
		if (!location)
			location = get_room_index(1);

		if (IS_SET(ch->pcdata->flags, PCFLAG_IMMORTALITY))
			location = in_room;

		char_to_room(ch, location);
		/*
		 * Make things a little fancier				-Thoric
		 */
		if ((wch = get_char_room(ch, "healer")) != NULL) {
			act(AT_MAGIC, "$n mutters a few incantations, waves $s hands and points $s finger.",
			    wch, NULL, NULL, TO_ROOM);
			act(AT_MAGIC, "$n appears from some strange swirling mists!", ch, NULL, NULL, TO_ROOM);
			sprintf(buf, "Welcome back to the land of the living, %s",
			    capitalize(ch->name));
			do_say(wch, buf);
		} else
			act(AT_MAGIC, "$n appears from some strange swirling mists!", ch, NULL, NULL, TO_ROOM);
		ch->position = POS_RESTING;
		return;
	}

	if ( !location )
	    location = get_room_index( 1 );

	if( IS_SET(ch->pcdata->flags, PCFLAG_IMMORTALITY) )
	    location = in_room;

	char_to_room( ch, location );
	/*
	 * Make things a little fancier				-Thoric
	 */
	if ( ( wch = get_char_room( ch, "healer" ) ) != NULL )
	{
	    act( AT_MAGIC, "$n mutters a few incantations, waves $s hands and points $s finger.",
		wch, NULL, NULL, TO_ROOM );
	    act( AT_MAGIC, "$n appears from some strange swirling mists!", ch, NULL, NULL, TO_ROOM );
	    sprintf(buf, "Welcome back to the land of the living, %s",
		    capitalize( ch->name ) );
	    do_say( wch, buf );
	if (IS_NPC(ch)) {
		--ch->pIndexData->count;
		--nummobsloaded;
	}
	else
	    act( AT_MAGIC, "$n appears from some strange swirling mists!", ch, NULL, NULL, TO_ROOM );
        ch->position = POS_RESTING;
	return;
    }

    if ( IS_NPC(ch) )
    {
	--ch->pIndexData->count;
	--nummobsloaded;
    }

  /* Not sure this should stay or not Shaddai */
	/* Not sure this should stay or not Shaddai */
/*
    if ( ch->morph )
        do_unmorph( ch );
*/

    if ( ch->desc && ch->desc->original )
	do_return( ch, "" );
	if (ch->desc && ch->desc->original)
		do_return(ch, "");

    for ( wch = first_char; wch; wch = wch->next )
    {
    	if ( wch->reply == ch )
	    wch->reply = NULL;
	if( wch->retell == ch )
	    wch->retell = NULL;
    }
	for (wch = first_char; wch; wch = wch->next) {
		if (wch->reply == ch)
			wch->reply = NULL;
		if (wch->retell == ch)
			wch->retell = NULL;
	}

    UNLINK( ch, first_char, last_char, next, prev );
	UNLINK(ch, first_char, last_char, next, prev);

    if ( ch->desc )
    {
	if ( ch->desc->character != ch )
	    bug( "Extract_char: char's descriptor points to another char", 0 );
	else
	{
	    ch->desc->character = NULL;
	    close_socket( ch->desc, false );
	    ch->desc = NULL;
	if (ch->desc) {
		if (ch->desc->character != ch)
			bug("Extract_char: char's descriptor points to another char", 0);
		else {
			ch->desc->character = NULL;
			close_socket(ch->desc, false);
			ch->desc = NULL;
		}
	}
    }

    return;
	return;
}


/*
 * Find a char in the room.
 */
CHAR_DATA *get_char_room( CHAR_DATA *ch, char *argument )
CHAR_DATA *
get_char_room(CHAR_DATA * ch, char *argument)
{
    char arg[MAX_INPUT_LENGTH];
    CHAR_DATA *rch;
    int number, count, vnum;
	char 	arg[MAX_INPUT_LENGTH];
	CHAR_DATA *rch;
	int 	number, count, vnum;

    number = number_argument( argument, arg );
    if ( !str_cmp( arg, "self" ) )
	return ch;
	number = number_argument(argument, arg);
	if (!str_cmp(arg, "self"))
		return ch;

    if ( get_trust(ch) >= LEVEL_SAVIOR && is_number( arg ) )
	vnum = atoi( arg );
    else
	vnum = -1;

    count  = 0;
	if (get_trust(ch) >= LEVEL_SAVIOR && is_number(arg))
		vnum = atoi(arg);
	else
		vnum = -1;

	count = 0;

	for (rch = ch->in_room->first_person; rch; rch = rch->next_in_room)
		if (can_see(ch, rch)
		    && (nifty_is_name(arg, rch->name)
			|| (IS_NPC(rch) && vnum == rch->pIndexData->vnum))) {
			if (number == 0 && !IS_NPC(rch))
				return rch;
			else if (++count == number)
				return rch;
		}
	if (vnum != -1)
		return NULL;

    for ( rch = ch->in_room->first_person; rch; rch = rch->next_in_room )
	if ( can_see( ch, rch )
	&&  (nifty_is_name( arg, rch->name )
	||  (IS_NPC(rch) && vnum == rch->pIndexData->vnum)) )
	{
	    if ( number == 0 && !IS_NPC(rch) )
		return rch;
	    else
	    if ( ++count == number )
		return rch;
	/*
         * If we didn't find an exact match, run through the list of characters
         * again looking for prefix matching, ie gu == guard.
         * Added by Narn, Sept/96
         */
	count = 0;
	for (rch = ch->in_room->first_person; rch; rch = rch->next_in_room) {
		if (!can_see(ch, rch) || !nifty_is_name_prefix(arg, rch->name))
			continue;
		if (number == 0 && !IS_NPC(rch))
			return rch;
		else if (++count == number)
			return rch;
	}

    if ( vnum != -1 )
	return NULL;

    /*
     * If we didn't find an exact match, run through the list of characters
     * again looking for prefix matching, ie gu == guard.
     * Added by Narn, Sept/96
     */
    count  = 0;
    for ( rch = ch->in_room->first_person; rch; rch = rch->next_in_room )
    {
	if ( !can_see( ch, rch ) || !nifty_is_name_prefix( arg, rch->name ) )
	    continue;
	if ( number == 0 && !IS_NPC(rch) )
	    return rch;
	else
	if ( ++count == number )
	    return rch;
    }

    return NULL;
}




@@ 2032,185 2055,167 @@ CHAR_DATA *get_char_room( CHAR_DATA *ch, char *argument )
/*
 * Find a char in the world.
 */
CHAR_DATA *get_char_world( CHAR_DATA *ch, char *argument )
{
    char arg[MAX_INPUT_LENGTH];
    CHAR_DATA *wch;
    int number, count, vnum;

    number = number_argument( argument, arg );
    count  = 0;
    if ( !str_cmp( arg, "self" ) )
	return ch;

    /*
     * Allow reference by vnum for saints+			-Thoric
     */
    if ( get_trust(ch) >= LEVEL_SAVIOR && is_number( arg ) )
	vnum = atoi( arg );
    else
	vnum = -1;

    /* check the room for an exact match */
    for ( wch = ch->in_room->first_person; wch; wch = wch->next_in_room )
	if ( can_see( ch, wch )
	&&  (nifty_is_name( arg, wch->name )
	||  (IS_NPC(wch) && vnum == wch->pIndexData->vnum)) )
	{
	    if ( number == 0 && !IS_NPC(wch) )
		return wch;
	    else
	    if ( ++count == number )
		return wch;
	}
CHAR_DATA *
get_char_world(CHAR_DATA * ch, char *argument)
{
	char 	arg[MAX_INPUT_LENGTH];
	CHAR_DATA *wch;
	int 	number, count, vnum;

    count = 0;
	number = number_argument(argument, arg);
	count = 0;
	if (!str_cmp(arg, "self"))
		return ch;

	/*
         * Allow reference by vnum for saints+			-Thoric
         */
	if (get_trust(ch) >= LEVEL_SAVIOR && is_number(arg))
		vnum = atoi(arg);
	else
		vnum = -1;

	/* check the room for an exact match */
	for (wch = ch->in_room->first_person; wch; wch = wch->next_in_room)
		if (can_see(ch, wch)
		    && (nifty_is_name(arg, wch->name)
			|| (IS_NPC(wch) && vnum == wch->pIndexData->vnum))) {
			if (number == 0 && !IS_NPC(wch))
				return wch;
			else if (++count == number)
				return wch;
		}
	count = 0;


    /* check the world for an exact match */
    for ( wch = first_char; wch; wch = wch->next )
	if ( can_see( ch, wch )
	&&  (nifty_is_name( arg, wch->name )
	||  (IS_NPC(wch) && vnum == wch->pIndexData->vnum)) )
	{
	    if ( number == 0 && !IS_NPC(wch) )
		return wch;
	    else
	    if ( ++count == number )
		return wch;
	}

    /* bail out if looking for a vnum match */
    if ( vnum != -1 )
	return NULL;
	/* check the world for an exact match */
	for (wch = first_char; wch; wch = wch->next)
		if (can_see(ch, wch)
		    && (nifty_is_name(arg, wch->name)
			|| (IS_NPC(wch) && vnum == wch->pIndexData->vnum))) {
			if (number == 0 && !IS_NPC(wch))
				return wch;
			else if (++count == number)
				return wch;
		}
	/* bail out if looking for a vnum match */
	if (vnum != -1)
		return NULL;

    /*
     * If we didn't find an exact match, check the room for
     * for a prefix match, ie gu == guard.
     * Added by Narn, Sept/96
     */
    count  = 0;
    for ( wch = ch->in_room->first_person; wch; wch = wch->next_in_room )
    {
	if ( !can_see( ch, wch ) || !nifty_is_name_prefix( arg, wch->name ) )
	    continue;
	if ( number == 0 && !IS_NPC(wch) )
	    return wch;
	else
	if ( ++count == number )
	    return wch;
    }

    /*
     * If we didn't find a prefix match in the room, run through the full list
     * of characters looking for prefix matching, ie gu == guard.
     * Added by Narn, Sept/96
     */
    count  = 0;
    for ( wch = first_char; wch; wch = wch->next )
    {
	if ( !can_see( ch, wch ) || !nifty_is_name_prefix( arg, wch->name ) )
	    continue;
	if ( number == 0 && !IS_NPC(wch) )
	    return wch;
	else
	if ( ++count == number )
	    return wch;
    }
	/*
         * If we didn't find an exact match, check the room for
         * for a prefix match, ie gu == guard.
         * Added by Narn, Sept/96
         */
	count = 0;
	for (wch = ch->in_room->first_person; wch; wch = wch->next_in_room) {
		if (!can_see(ch, wch) || !nifty_is_name_prefix(arg, wch->name))
			continue;
		if (number == 0 && !IS_NPC(wch))
			return wch;
		else if (++count == number)
			return wch;
	}

    return NULL;
	/*
         * If we didn't find a prefix match in the room, run through the full list
         * of characters looking for prefix matching, ie gu == guard.
         * Added by Narn, Sept/96
         */
	count = 0;
	for (wch = first_char; wch; wch = wch->next) {
		if (!can_see(ch, wch) || !nifty_is_name_prefix(arg, wch->name))
			continue;
		if (number == 0 && !IS_NPC(wch))
			return wch;
		else if (++count == number)
			return wch;
	}

	return NULL;
}

/* For purposes of Instant Transmission or other things that "find"
 * the character by their "ki"
 **/
CHAR_DATA *get_char_ki_world( CHAR_DATA *ch, char *argument )
{
    char arg[MAX_INPUT_LENGTH];
    CHAR_DATA *wch;
    int number, count, vnum;

    number = number_argument( argument, arg );
    count  = 0;
    if ( !str_cmp( arg, "self" ) )
	return ch;

    /*
     * Allow reference by vnum for saints+			-Thoric
     */
    if ( get_trust(ch) >= LEVEL_SAVIOR && is_number( arg ) )
	vnum = atoi( arg );
    else
	vnum = -1;

    /* check the room for an exact match */
    for ( wch = ch->in_room->first_person; wch; wch = wch->next_in_room )
	if ( nifty_is_name( arg, wch->name )
	||  (IS_NPC(wch) && vnum == wch->pIndexData->vnum) )
	{
	    if ( number == 0 && !IS_NPC(wch) )
		return wch;
	    else
	    if ( ++count == number )
		return wch;
	}
CHAR_DATA *
get_char_ki_world(CHAR_DATA * ch, char *argument)
{
	char 	arg[MAX_INPUT_LENGTH];
	CHAR_DATA *wch;
	int 	number, count, vnum;

    count = 0;
	number = number_argument(argument, arg);
	count = 0;
	if (!str_cmp(arg, "self"))
		return ch;

	/*
         * Allow reference by vnum for saints+			-Thoric
         */
	if (get_trust(ch) >= LEVEL_SAVIOR && is_number(arg))
		vnum = atoi(arg);
	else
		vnum = -1;

	/* check the room for an exact match */
	for (wch = ch->in_room->first_person; wch; wch = wch->next_in_room)
		if (nifty_is_name(arg, wch->name)
		    || (IS_NPC(wch) && vnum == wch->pIndexData->vnum)) {
			if (number == 0 && !IS_NPC(wch))
				return wch;
			else if (++count == number)
				return wch;
		}
	count = 0;


    /* check the world for an exact match */
    for ( wch = first_char; wch; wch = wch->next )
	if ( nifty_is_name( arg, wch->name )
	||  (IS_NPC(wch) && vnum == wch->pIndexData->vnum) )
	{
	    if ( number == 0 && !IS_NPC(wch) )
		return wch;
	    else
	    if ( ++count == number )
		return wch;
	}

    /* bail out if looking for a vnum match */
    if ( vnum != -1 )
	return NULL;
	/* check the world for an exact match */
	for (wch = first_char; wch; wch = wch->next)
		if (nifty_is_name(arg, wch->name)
		    || (IS_NPC(wch) && vnum == wch->pIndexData->vnum)) {
			if (number == 0 && !IS_NPC(wch))
				return wch;
			else if (++count == number)
				return wch;
		}
	/* bail out if looking for a vnum match */
	if (vnum != -1)
		return NULL;

    /*
     * If we didn't find an exact match, check the room for
     * for a prefix match, ie gu == guard.
     * Added by Narn, Sept/96
     */
    count  = 0;
    for ( wch = ch->in_room->first_person; wch; wch = wch->next_in_room )
    {
	if ( !nifty_is_name_prefix( arg, wch->name ) )
	    continue;
	if ( number == 0 && !IS_NPC(wch) )
	    return wch;
	else
	if ( ++count == number )
	    return wch;
    }

    /*
     * If we didn't find a prefix match in the room, run through the full list
     * of characters looking for prefix matching, ie gu == guard.
     * Added by Narn, Sept/96
     */
    count  = 0;
    for ( wch = first_char; wch; wch = wch->next )
    {
	if ( !nifty_is_name_prefix( arg, wch->name ) )
	    continue;
	if ( number == 0 && !IS_NPC(wch) )
	    return wch;
	else
	if ( ++count == number )
	    return wch;
    }
	/*
         * If we didn't find an exact match, check the room for
         * for a prefix match, ie gu == guard.
         * Added by Narn, Sept/96
         */
	count = 0;
	for (wch = ch->in_room->first_person; wch; wch = wch->next_in_room) {
		if (!nifty_is_name_prefix(arg, wch->name))
			continue;
		if (number == 0 && !IS_NPC(wch))
			return wch;
		else if (++count == number)
			return wch;
	}

    return NULL;
	/*
         * If we didn't find a prefix match in the room, run through the full list
         * of characters looking for prefix matching, ie gu == guard.
         * Added by Narn, Sept/96
         */
	count = 0;
	for (wch = first_char; wch; wch = wch->next) {
		if (!nifty_is_name_prefix(arg, wch->name))
			continue;
		if (number == 0 && !IS_NPC(wch))
			return wch;
		else if (++count == number)
			return wch;
	}

	return NULL;
}




@@ 2219,144 2224,145 @@ CHAR_DATA *get_char_ki_world( CHAR_DATA *ch, char *argument )
 * Find some object with a given index data.
 * Used by area-reset 'P', 'T' and 'H' commands.
 */
OBJ_DATA *get_obj_type( OBJ_INDEX_DATA *pObjIndex )
OBJ_DATA *
get_obj_type(OBJ_INDEX_DATA * pObjIndex)
{
    OBJ_DATA *obj;
	OBJ_DATA *obj;

    for ( obj = last_object; obj; obj = obj->prev )
	if ( obj->pIndexData == pObjIndex )
	    return obj;
	for (obj = last_object; obj; obj = obj->prev)
		if (obj->pIndexData == pObjIndex)
			return obj;

    return NULL;
	return NULL;
}


/*
 * Find an obj in a list.
 */
OBJ_DATA *get_obj_list( CHAR_DATA *ch, char *argument, OBJ_DATA *list )
{
    char arg[MAX_INPUT_LENGTH];
    OBJ_DATA *obj;
    int number;
    int count;

    number = number_argument( argument, arg );
    count  = 0;
    for ( obj = list; obj; obj = obj->next_content )
	if ( can_see_obj( ch, obj ) && nifty_is_name( arg, obj->name ) )
	    if ( (count += obj->count) >= number )
		return obj;
OBJ_DATA *
get_obj_list(CHAR_DATA * ch, char *argument, OBJ_DATA * list)
{
	char 	arg[MAX_INPUT_LENGTH];
	OBJ_DATA *obj;
	int 	number;
	int 	count;

    /*
     * If we didn't find an exact match, run through the list of objects
     * again looking for prefix matching, ie swo == sword.
     * Added by Narn, Sept/96
     */
    count = 0;
    for ( obj = list; obj; obj = obj->next_content )
	if ( can_see_obj( ch, obj ) && nifty_is_name_prefix( arg, obj->name ) )
	    if ( (count += obj->count) >= number )
		return obj;
	number = number_argument(argument, arg);
	count = 0;
	for (obj = list; obj; obj = obj->next_content)
		if (can_see_obj(ch, obj) && nifty_is_name(arg, obj->name))
			if ((count += obj->count) >= number)
				return obj;

	/*
         * If we didn't find an exact match, run through the list of objects
         * again looking for prefix matching, ie swo == sword.
         * Added by Narn, Sept/96
         */
	count = 0;
	for (obj = list; obj; obj = obj->next_content)
		if (can_see_obj(ch, obj) && nifty_is_name_prefix(arg, obj->name))
			if ((count += obj->count) >= number)
				return obj;

    return NULL;
	return NULL;
}

/*
 * Find an obj in a list...going the other way			-Thoric
 */
OBJ_DATA *get_obj_list_rev( CHAR_DATA *ch, char *argument, OBJ_DATA *list )
{
    char arg[MAX_INPUT_LENGTH];
    OBJ_DATA *obj;
    int number;
    int count;

    number = number_argument( argument, arg );
    count  = 0;
    for ( obj = list; obj; obj = obj->prev_content )
	if ( can_see_obj( ch, obj ) && nifty_is_name( arg, obj->name ) )
	    if ( (count += obj->count) >= number )
		return obj;
OBJ_DATA *
get_obj_list_rev(CHAR_DATA * ch, char *argument, OBJ_DATA * list)
{
	char 	arg[MAX_INPUT_LENGTH];
	OBJ_DATA *obj;
	int 	number;
	int 	count;

    /*
     * If we didn't find an exact match, run through the list of objects
     * again looking for prefix matching, ie swo == sword.
     * Added by Narn, Sept/96
     */
    count = 0;
    for ( obj = list; obj; obj = obj->prev_content )
	if ( can_see_obj( ch, obj ) && nifty_is_name_prefix( arg, obj->name ) )
	    if ( (count += obj->count) >= number )
		return obj;
	number = number_argument(argument, arg);
	count = 0;
	for (obj = list; obj; obj = obj->prev_content)
		if (can_see_obj(ch, obj) && nifty_is_name(arg, obj->name))
			if ((count += obj->count) >= number)
				return obj;

    return NULL;
	/*
         * If we didn't find an exact match, run through the list of objects
         * again looking for prefix matching, ie swo == sword.
         * Added by Narn, Sept/96
         */
	count = 0;
	for (obj = list; obj; obj = obj->prev_content)
		if (can_see_obj(ch, obj) && nifty_is_name_prefix(arg, obj->name))
			if ((count += obj->count) >= number)
				return obj;

	return NULL;
}

/*
 * Find an obj in player's inventory or wearing via a vnum -Shaddai
 */

OBJ_DATA *get_obj_vnum( CHAR_DATA *ch, int vnum )
OBJ_DATA *
get_obj_vnum(CHAR_DATA * ch, int vnum)
{
    OBJ_DATA *obj;
	OBJ_DATA *obj;

    for ( obj = ch->last_carrying; obj; obj = obj->prev_content )
        if (  can_see_obj( ch, obj ) && obj->pIndexData->vnum == vnum )
                return obj;
    return NULL;
	for (obj = ch->last_carrying; obj; obj = obj->prev_content)
		if (can_see_obj(ch, obj) && obj->pIndexData->vnum == vnum)
			return obj;
	return NULL;
}


/*
 * Find an obj in player's inventory.
 */
OBJ_DATA *get_obj_carry( CHAR_DATA *ch, char *argument )
{
    char arg[MAX_INPUT_LENGTH];
    OBJ_DATA *obj = NULL;
    int number, count, vnum;

    number = number_argument( argument, arg );
    if ( get_trust(ch) >= LEVEL_SAVIOR && is_number( arg ) )
	vnum = atoi( arg );
    else
	vnum = -1;

    count  = 0;
    for ( obj = ch->last_carrying; obj; obj = obj->prev_content )
    {
	if ( obj->wear_loc == WEAR_NONE
	&&   can_see_obj( ch, obj )
	&&  (nifty_is_name( arg, obj->name ) || obj->pIndexData->vnum == vnum) )
        {
	    if ( (count += obj->count) >= number )
		return obj;
        }
    }
OBJ_DATA *
get_obj_carry(CHAR_DATA * ch, char *argument)
{
	char 	arg[MAX_INPUT_LENGTH];
	OBJ_DATA *obj = NULL;
	int 	number, count, vnum;

    if ( vnum != -1 )
	return NULL;
	number = number_argument(argument, arg);
	if (get_trust(ch) >= LEVEL_SAVIOR && is_number(arg))
		vnum = atoi(arg);
	else
		vnum = -1;

	count = 0;
	for (obj = ch->last_carrying; obj; obj = obj->prev_content) {
		if (obj->wear_loc == WEAR_NONE
		    && can_see_obj(ch, obj)
		    && (nifty_is_name(arg, obj->name) || obj->pIndexData->vnum == vnum)) {
			if ((count += obj->count) >= number)
				return obj;
		}
	}

    /*
     * If we didn't find an exact match, run through the list of objects
     * again looking for prefix matching, ie swo == sword.
     * Added by Narn, Sept/96
     */
    obj   = NULL;
    count = 0;
    for ( obj = ch->last_carrying; obj; obj = obj->prev_content )
    {
	if ( obj->wear_loc == WEAR_NONE
	&&   can_see_obj( ch, obj )
	&&   nifty_is_name_prefix( arg, obj->name ) )
        {
	    if ( (count += obj->count) >= number )
		return obj;
        }
    }
	if (vnum != -1)
		return NULL;

    return NULL;
	/*
         * If we didn't find an exact match, run through the list of objects
         * again looking for prefix matching, ie swo == sword.
         * Added by Narn, Sept/96
         */
	obj = NULL;
	count = 0;
	for (obj = ch->last_carrying; obj; obj = obj->prev_content) {
		if (obj->wear_loc == WEAR_NONE
		    && can_see_obj(ch, obj)
		    && nifty_is_name_prefix(arg, obj->name)) {
			if ((count += obj->count) >= number)
				return obj;
		}
	}

	return NULL;
}




@@ 2364,44 2370,45 @@ OBJ_DATA *get_obj_carry( CHAR_DATA *ch, char *argument )
/*
 * Find an obj in player's equipment.
 */
OBJ_DATA *get_obj_wear( CHAR_DATA *ch, char *argument )
OBJ_DATA *
get_obj_wear(CHAR_DATA * ch, char *argument)
{
    char arg[MAX_INPUT_LENGTH];
    OBJ_DATA *obj;
    int number, count, vnum;
	char 	arg[MAX_INPUT_LENGTH];
	OBJ_DATA *obj;
	int 	number, count, vnum;

    number = number_argument( argument, arg );
	number = number_argument(argument, arg);

    if ( get_trust(ch) >= LEVEL_SAVIOR && is_number( arg ) )
	vnum = atoi( arg );
    else
	vnum = -1;
	if (get_trust(ch) >= LEVEL_SAVIOR && is_number(arg))
		vnum = atoi(arg);
	else
		vnum = -1;

    count  = 0;
    for ( obj = ch->last_carrying; obj; obj = obj->prev_content )
	if ( obj->wear_loc != WEAR_NONE
	&&   can_see_obj( ch, obj )
	&&  (nifty_is_name( arg, obj->name ) || obj->pIndexData->vnum == vnum) )
	    if ( ++count == number )
		return obj;
	count = 0;
	for (obj = ch->last_carrying; obj; obj = obj->prev_content)
		if (obj->wear_loc != WEAR_NONE
		    && can_see_obj(ch, obj)
		    && (nifty_is_name(arg, obj->name) || obj->pIndexData->vnum == vnum))
			if (++count == number)
				return obj;

    if ( vnum != -1 )
	return NULL;
	if (vnum != -1)
		return NULL;

    /*
     * If we didn't find an exact match, run through the list of objects
     * again looking for prefix matching, ie swo == sword.
     * Added by Narn, Sept/96
     */
    count = 0;
    for ( obj = ch->last_carrying; obj; obj = obj->prev_content )
	if ( obj->wear_loc != WEAR_NONE
	&&   can_see_obj( ch, obj )
	&&   nifty_is_name_prefix( arg, obj->name ) )
	    if ( ++count == number )
		return obj;
	/*
         * If we didn't find an exact match, run through the list of objects
         * again looking for prefix matching, ie swo == sword.
         * Added by Narn, Sept/96
         */
	count = 0;
	for (obj = ch->last_carrying; obj; obj = obj->prev_content)
		if (obj->wear_loc != WEAR_NONE
		    && can_see_obj(ch, obj)
		    && nifty_is_name_prefix(arg, obj->name))
			if (++count == number)
				return obj;

    return NULL;
	return NULL;
}




@@ 2409,97 2416,100 @@ OBJ_DATA *get_obj_wear( CHAR_DATA *ch, char *argument )
/*
 * Find an obj in the room or in inventory.
 */
OBJ_DATA *get_obj_here( CHAR_DATA *ch, char *argument )
OBJ_DATA *
get_obj_here(CHAR_DATA * ch, char *argument)
{
    OBJ_DATA *obj;
	OBJ_DATA *obj;

    obj = get_obj_list_rev( ch, argument, ch->in_room->last_content );
    if ( obj )
	return obj;
	obj = get_obj_list_rev(ch, argument, ch->in_room->last_content);
	if (obj)
		return obj;

    if ( ( obj = get_obj_carry( ch, argument ) ) != NULL )
	return obj;
	if ((obj = get_obj_carry(ch, argument)) != NULL)
		return obj;

    if ( ( obj = get_obj_wear( ch, argument ) ) != NULL )
	return obj;
	if ((obj = get_obj_wear(ch, argument)) != NULL)
		return obj;

    return NULL;
	return NULL;
}

/* find an obj in a room */
OBJ_DATA *get_obj_room( CHAR_DATA *ch, char *argument )
OBJ_DATA *
get_obj_room(CHAR_DATA * ch, char *argument)
{
    OBJ_DATA *obj;
	OBJ_DATA *obj;

    obj = get_obj_list_rev( ch, argument, ch->in_room->last_content );
    if ( obj )
        return obj;
	obj = get_obj_list_rev(ch, argument, ch->in_room->last_content);
	if (obj)
		return obj;

    return NULL;
	return NULL;
}

/* find an obj in a room based on its vnum */
OBJ_DATA *get_obj_vnum_room( CHAR_DATA *ch, int vnum )
OBJ_DATA *
get_obj_vnum_room(CHAR_DATA * ch, int vnum)
{
    OBJ_DATA *obj;
	OBJ_DATA *obj;

    for ( obj = ch->in_room->first_content; obj; obj = obj->next_content )
    {
	if( !obj )
	  continue;
	if( obj->pIndexData->vnum == vnum )
	  return obj;
    }
	for (obj = ch->in_room->first_content; obj; obj = obj->next_content) {
		if (!obj)
			continue;
		if (obj->pIndexData->vnum == vnum)
			return obj;
	}

    return NULL;
	return NULL;
}


/*
 * Find an obj in the world.
 */
OBJ_DATA *get_obj_world( CHAR_DATA *ch, char *argument )
OBJ_DATA *
get_obj_world(CHAR_DATA * ch, char *argument)
{
    char arg[MAX_INPUT_LENGTH];
    OBJ_DATA *obj;
    int number, count, vnum;

    if ( ( obj = get_obj_here( ch, argument ) ) != NULL )
	return obj;
	char 	arg[MAX_INPUT_LENGTH];
	OBJ_DATA *obj;
	int 	number, count, vnum;

    number = number_argument( argument, arg );

    /*
     * Allow reference by vnum for saints+			-Thoric
     */
    if ( get_trust(ch) >= LEVEL_SAVIOR && is_number( arg ) )
	vnum = atoi( arg );
    else
	vnum = -1;

    count  = 0;
    for ( obj = first_object; obj; obj = obj->next )
	if ( can_see_obj( ch, obj ) && (nifty_is_name( arg, obj->name )
	||   vnum == obj->pIndexData->vnum) )
	    if ( (count += obj->count) >= number )
	if ((obj = get_obj_here(ch, argument)) != NULL)
		return obj;

    /* bail out if looking for a vnum */
    if ( vnum != -1 )
	return NULL;
	number = number_argument(argument, arg);

    /*
     * If we didn't find an exact match, run through the list of objects
     * again looking for prefix matching, ie swo == sword.
     * Added by Narn, Sept/96
     */
    count  = 0;
    for ( obj = first_object; obj; obj = obj->next )
	if ( can_see_obj( ch, obj ) && nifty_is_name_prefix( arg, obj->name ) )
	    if ( (count += obj->count) >= number )
		return obj;
	/*
         * Allow reference by vnum for saints+			-Thoric
         */
	if (get_trust(ch) >= LEVEL_SAVIOR && is_number(arg))
		vnum = atoi(arg);
	else
		vnum = -1;

	count = 0;
	for (obj = first_object; obj; obj = obj->next)
		if (can_see_obj(ch, obj) && (nifty_is_name(arg, obj->name)
			|| vnum == obj->pIndexData->vnum))
			if ((count += obj->count) >= number)
				return obj;

	/* bail out if looking for a vnum */
	if (vnum != -1)
		return NULL;

	/*
         * If we didn't find an exact match, run through the list of objects
         * again looking for prefix matching, ie swo == sword.
         * Added by Narn, Sept/96
         */
	count = 0;
	for (obj = first_object; obj; obj = obj->next)
		if (can_see_obj(ch, obj) && nifty_is_name_prefix(arg, obj->name))
			if ((count += obj->count) >= number)
				return obj;

    return NULL;
	return NULL;
}




@@ 2508,62 2518,114 @@ OBJ_DATA *get_obj_world( CHAR_DATA *ch, char *argument )
 * Used by get/drop/put/quaff/recite/etc
 * Increasingly freaky based on mental state and drunkeness
 */
bool ms_find_obj( CHAR_DATA *ch )
{
    int ms = ch->mental_state;
    int drunk = IS_NPC(ch) ? 0 : ch->pcdata->condition[COND_DRUNK];
    char *t;

    /*
     * we're going to be nice and let nothing weird happen unless
     * you're a tad messed up
     */
    drunk = UMAX( 1, drunk );
    if ( abs(ms) + (drunk/3) < 30 )
	return false;
    if ( (number_percent() + (ms < 0 ? 15 : 5))> abs(ms)/2 + drunk/4 )
	return false;
    if ( ms > 15 )	/* range 1 to 20 -- feel free to add more */
	switch( number_range( UMAX(1, (ms/5-15)), (ms+4) / 5 ) )
	{
	    default:
	    case  1: t="As you reach for it, you forgot what it was...\n\r";					break;
	    case  2: t="As you reach for it, something inside stops you...\n\r";				break;
	    case  3: t="As you reach for it, it seems to move out of the way...\n\r";				break;
	    case  4: t="You grab frantically for it, but can't seem to get a hold of it...\n\r";		break;
	    case  5: t="It disappears as soon as you touch it!\n\r";						break;
	    case  6: t="You would if it would stay still!\n\r";							break;
	    case  7: t="Whoa!  It's covered in blood!  Ack!  Ick!\n\r";						break;
	    case  8: t="Wow... trails!\n\r";									break;
	    case  9: t="You reach for it, then notice the back of your hand is growing something!\n\r";		break;
	    case 10: t="As you grasp it, it shatters into tiny shards which bite into your flesh!\n\r";		break;
	    case 11: t="What about that huge dragon flying over your head?!?!?\n\r";				break;
	    case 12: t="You stratch yourself instead...\n\r";							break;
	    case 13: t="You hold the universe in the palm of your hand!\n\r";					break;
	    case 14: t="You're too scared.\n\r";								break;
	    case 15: t="Your mother smacks your hand... 'NO!'\n\r";						break;
	    case 16: t="Your hand grasps the worst pile of revoltingness that you could ever imagine!\n\r";	break;
	    case 17: t="You stop reaching for it as it screams out at you in pain!\n\r";			break;
	    case 18: t="What about the millions of burrow-maggots feasting on your arm?!?!\n\r";		break;
	    case 19: t="That doesn't matter anymore... you've found the true answer to everything!\n\r";	break;
	    case 20: t="A supreme entity has no need for that.\n\r";						break;
	}
    else
    {
	int sub = URANGE(1, abs(ms)/2 + drunk, 60);
	switch( number_range( 1, sub/10 ) )
	{
	    default:
	    case  1: t="In just a second...\n\r";					break;
	    case  2: t="You can't find that...\n\r";					break;
	    case  3: t="It's just beyond your grasp...\n\r";				break;
	    case  4: t="...but it's under a pile of other stuff...\n\r";		break;
	    case  5: t="You go to reach for it, but pick your nose instead.\n\r";	break;
	    case  6: t="Which one?!?  I see two... no three...\n\r";			break;
bool 
ms_find_obj(CHAR_DATA * ch)
{
	int 	ms = ch->mental_state;
	int 	drunk = IS_NPC(ch) ? 0 : ch->pcdata->condition[COND_DRUNK];
	char   *t;

	/*
         * we're going to be nice and let nothing weird happen unless
         * you're a tad messed up
         */
	drunk = UMAX(1, drunk);
	if (abs(ms) + (drunk / 3) < 30)
		return false;
	if ((number_percent() + (ms < 0 ? 15 : 5)) > abs(ms) / 2 + drunk / 4)
		return false;
	if (ms > 15)			/* range 1 to 20 -- feel free to add
					 * more */
		switch (number_range(UMAX(1, (ms / 5 - 15)), (ms + 4) / 5)) {
		default:
		case 1:
			t = "As you reach for it, you forgot what it was...\n\r";
			break;
		case 2:
			t = "As you reach for it, something inside stops you...\n\r";
			break;
		case 3:
			t = "As you reach for it, it seems to move out of the way...\n\r";
			break;
		case 4:
			t = "You grab frantically for it, but can't seem to get a hold of it...\n\r";
			break;
		case 5:
			t = "It disappears as soon as you touch it!\n\r";
			break;
		case 6:
			t = "You would if it would stay still!\n\r";
			break;
		case 7:
			t = "Whoa!  It's covered in blood!  Ack!  Ick!\n\r";
			break;
		case 8:
			t = "Wow... trails!\n\r";
			break;
		case 9:
			t = "You reach for it, then notice the back of your hand is growing something!\n\r";
			break;
		case 10:
			t = "As you grasp it, it shatters into tiny shards which bite into your flesh!\n\r";
			break;
		case 11:
			t = "What about that huge dragon flying over your head?!?!?\n\r";
			break;
		case 12:
			t = "You stratch yourself instead...\n\r";
			break;
		case 13:
			t = "You hold the universe in the palm of your hand!\n\r";
			break;
		case 14:
			t = "You're too scared.\n\r";
			break;
		case 15:
			t = "Your mother smacks your hand... 'NO!'\n\r";
			break;
		case 16:
			t = "Your hand grasps the worst pile of revoltingness that you could ever imagine!\n\r";
			break;
		case 17:
			t = "You stop reaching for it as it screams out at you in pain!\n\r";
			break;
		case 18:
			t = "What about the millions of burrow-maggots feasting on your arm?!?!\n\r";
			break;
		case 19:
			t = "That doesn't matter anymore... you've found the true answer to everything!\n\r";
			break;
		case 20:
			t = "A supreme entity has no need for that.\n\r";
			break;
		}
	else {
		int 	sub = URANGE(1, abs(ms) / 2 + drunk, 60);

		switch (number_range(1, sub / 10)) {
		default:
		case 1:
			t = "In just a second...\n\r";
			break;
		case 2:
			t = "You can't find that...\n\r";
			break;
		case 3:
			t = "It's just beyond your grasp...\n\r";
			break;
		case 4:
			t = "...but it's under a pile of other stuff...\n\r";
			break;
		case 5:
			t = "You go to reach for it, but pick your nose instead.\n\r";
			break;
		case 6:
			t = "Which one?!?  I see two... no three...\n\r";
			break;
		}
	}
    }
    send_to_char( t, ch );
    return true;
	send_to_char(t, ch);
	return true;
}




@@ 2571,116 2633,109 @@ bool ms_find_obj( CHAR_DATA *ch )
 * Generic get obj function that supports optional containers.	-Thoric
 * currently only used for "eat" and "quaff".
 */
OBJ_DATA *find_obj( CHAR_DATA *ch, char *argument, bool carryonly )
{
    char arg1[MAX_INPUT_LENGTH];
    char arg2[MAX_INPUT_LENGTH];
    OBJ_DATA *obj = NULL;

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

    if ( !str_cmp( arg2, "from" )
    &&   argument[0] != '\0' )
	argument = one_argument( argument, arg2 );

    if ( arg2[0] == '\0' )
    {
	if ( carryonly && ( obj = get_obj_carry( ch, arg1 ) ) == NULL )
	{
	    send_to_char( "You do not have that item.\n\r", ch );
	    return NULL;
	}
	else
	if ( !carryonly && ( obj = get_obj_here( ch, arg1 ) ) == NULL )
	{
	    act( AT_PLAIN, "I see no $T here.", ch, NULL, arg1, TO_CHAR );
	    return NULL;
	}
	return obj;
    }
    else
    {
	OBJ_DATA *container = NULL;

	if ( carryonly
	&& ( container = get_obj_carry( ch, arg2 ) ) == NULL
	&& ( container = get_obj_wear( ch, arg2 ) ) == NULL )
	{
	    send_to_char( "You do not have that item.\n\r", ch );
	    return NULL;
	}
	if ( !carryonly && ( container = get_obj_here( ch, arg2 ) ) == NULL )
	{
	    act( AT_PLAIN, "I see no $T here.", ch, NULL, arg2, TO_CHAR );
	    return NULL;
	}

	if ( !IS_OBJ_STAT(container, ITEM_COVERING )
	&&    IS_SET(container->value[1], CONT_CLOSED) )
	{
	    act( AT_PLAIN, "The $d is closed.", ch, NULL, container->name, TO_CHAR );
	    return NULL;
OBJ_DATA *
find_obj(CHAR_DATA * ch, char *argument, bool carryonly)
{
	char 	arg1[MAX_INPUT_LENGTH];
	char 	arg2[MAX_INPUT_LENGTH];
	OBJ_DATA *obj = NULL;

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

	if (!str_cmp(arg2, "from")
	    && argument[0] != '\0')
		argument = one_argument(argument, arg2);

	if (arg2[0] == '\0') {
		if (carryonly && (obj = get_obj_carry(ch, arg1)) == NULL) {
			send_to_char("You do not have that item.\n\r", ch);
			return NULL;
		} else if (!carryonly && (obj = get_obj_here(ch, arg1)) == NULL) {
			act(AT_PLAIN, "I see no $T here.", ch, NULL, arg1, TO_CHAR);
			return NULL;
		}
		return obj;
	} else {
		OBJ_DATA *container = NULL;

		if (carryonly
		    && (container = get_obj_carry(ch, arg2)) == NULL
		    && (container = get_obj_wear(ch, arg2)) == NULL) {
			send_to_char("You do not have that item.\n\r", ch);
			return NULL;
		}
		if (!carryonly && (container = get_obj_here(ch, arg2)) == NULL) {
			act(AT_PLAIN, "I see no $T here.", ch, NULL, arg2, TO_CHAR);
			return NULL;
		}
		if (!IS_OBJ_STAT(container, ITEM_COVERING)
		    && IS_SET(container->value[1], CONT_CLOSED)) {
			act(AT_PLAIN, "The $d is closed.", ch, NULL, container->name, TO_CHAR);
			return NULL;
		}
		obj = get_obj_list(ch, arg1, container->first_content);
		if (!obj)
			act(AT_PLAIN, IS_OBJ_STAT(container, ITEM_COVERING) ?
			    "I see nothing like that beneath $p." :
			    "I see nothing like that in $p.",
			    ch, container, NULL, TO_CHAR);
		return obj;
	}

	obj = get_obj_list( ch, arg1, container->first_content );
	if ( !obj )
	    act( AT_PLAIN, IS_OBJ_STAT(container, ITEM_COVERING) ?
		"I see nothing like that beneath $p." :
		"I see nothing like that in $p.",
		ch, container, NULL, TO_CHAR );
	return obj;
    }
    return NULL;
	return NULL;
}

int get_obj_number( OBJ_DATA *obj )
int 
get_obj_number(OBJ_DATA * obj)
{
    return obj->count;
	return obj->count;
}

/*
 * Return true if an object is, or nested inside a magic container
 */
bool in_magic_container( OBJ_DATA *obj )
bool 
in_magic_container(OBJ_DATA * obj)
{
    if ( obj->item_type == ITEM_CONTAINER && IS_OBJ_STAT(obj, ITEM_MAGIC) )
	return true;
    if ( obj->in_obj )
	return in_magic_container(obj->in_obj);
    return false;
	if (obj->item_type == ITEM_CONTAINER && IS_OBJ_STAT(obj, ITEM_MAGIC))
		return true;
	if (obj->in_obj)
		return in_magic_container(obj->in_obj);
	return false;
}

/*
 * Return weight of an object, including weight of contents (unless magic).
 */
int get_obj_weight( OBJ_DATA *obj )
int 
get_obj_weight(OBJ_DATA * obj)
{
    int weight;
	int 	weight;

    weight = obj->count * obj->weight;
	weight = obj->count * obj->weight;

    /* magic containers */
    if ( obj->item_type != ITEM_CONTAINER || !IS_OBJ_STAT(obj, ITEM_MAGIC) )
	for ( obj = obj->first_content; obj; obj = obj->next_content )
	    weight += get_obj_weight(obj);
	/* magic containers */
	if (obj->item_type != ITEM_CONTAINER || !IS_OBJ_STAT(obj, ITEM_MAGIC))
		for (obj = obj->first_content; obj; obj = obj->next_content)
			weight += get_obj_weight(obj);

    return weight;
	return weight;
}

/*
 * Return real weight of an object, including weight of contents.
 */
int get_real_obj_weight( OBJ_DATA *obj )
int 
get_real_obj_weight(OBJ_DATA * obj)
{
    int weight;
	int 	weight;

    weight = obj->count * obj->weight;
	weight = obj->count * obj->weight;

    for ( obj = obj->first_content; obj; obj = obj->next_content )
	weight += get_real_obj_weight(obj);
	for (obj = obj->first_content; obj; obj = obj->next_content)
		weight += get_real_obj_weight(obj);

    return weight;
	return weight;
}




@@ 2688,29 2743,28 @@ int get_real_obj_weight( OBJ_DATA *obj )