changeset 36:2128c7dc8a40

Import Super-Rogue 9.0 from the Roguelike Restoration Project (r1490)
author elwin
date Thu, 25 Nov 2010 12:21:41 +0000
parents 05018c63a721
children 34d7a614855e
files srogue/LICENSE.TXT srogue/Makefile srogue/armor.c srogue/bob.h srogue/bsdtty.c srogue/chase.c srogue/command.c srogue/cx.h srogue/daemon.c srogue/daemons.c srogue/disply.c srogue/encumb.c srogue/fight.c srogue/global.c srogue/init.c srogue/io.c srogue/list.c srogue/main.c srogue/makevers.c srogue/misc.c srogue/monsters.c srogue/move.c srogue/ncx.h srogue/new_leve.c srogue/newterm.c srogue/options.c srogue/pack.c srogue/passages.c srogue/potions.c srogue/pstats.c srogue/rdk.h srogue/rgdata.c srogue/rings.c srogue/rip.c srogue/rogue.ext srogue/rogue.h srogue/rogue.nr srogue/rooms.c srogue/save.c srogue/scrolls.c srogue/state.c srogue/sticks.c srogue/things.c srogue/trader.c srogue/vers.c srogue/weapons.c srogue/wizard.c srogue/xcrypt.c
diffstat 48 files changed, 17601 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/srogue/LICENSE.TXT	Thu Nov 25 12:21:41 2010 +0000
@@ -0,0 +1,139 @@
+Copyright (C) 1984 Robert D. Kindelberger
+Portions Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
+Portions Copyright (C) 2005 Nicholas J. Kisseberth
+Portions Copyright (C) 1994 David Burren
+All rights reserved.
+
+===========================================================================
+
+Super-Rogue
+Copyright (C) 1984 Robert D. Kindelberger
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+1. Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+3. Neither the name(s) of the author(s) nor the names of other contributors
+   may be used to endorse or promote products derived from this software
+   without specific prior written permission.
+4. The name "Super-Rogue" must not be used to endorse or promote products 
+   derived from this software without prior written permission.
+5. Products derived from this software may not be called "Super-Rogue",
+   nor may "Super-Rogue" appear in their name, without prior written
+   permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) AND CONTRIBUTORS ``AS IS'' AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR(S) OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGE.
+
+===========================================================================
+
+
+Portions of this software are based on the work of Michael Toy, Ken Arnold
+and Glenn Wichman. Used under license:
+
+Rogue: Exploring the Dungeons of Doom
+Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+1. Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+3. Neither the name(s) of the author(s) nor the names of other contributors
+   may be used to endorse or promote products derived from this software
+   without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) AND CONTRIBUTORS ``AS IS'' AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR(S) OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGE.
+
+===========================================================================
+
+Portions of this software (save/restore game state) are based on the work 
+of Nicholas J. Kisseberth. Used under license:
+
+Copyright (C) 2005 Nicholas J. Kisseberth
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+1. Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+3. Neither the name(s) of the author(s) nor the names of other contributors
+   may be used to endorse or promote products derived from this software
+   without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) AND CONTRIBUTORS ``AS IS'' AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR(S) OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGE.
+
+===========================================================================
+
+Portions of this software (encryption) are based on the work 
+of David Burren. Used under license:
+
+FreeSec: libcrypt
+
+Copyright (C) 1994 David Burren
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+1. Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+3. Neither the name(s) of the author(s) nor the names of other contributors
+   may be used to endorse or promote products derived from this software
+   without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) AND CONTRIBUTORS ``AS IS'' AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR(S) OR CONTRIBUTORS BE LIABLE
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGE.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/srogue/Makefile	Thu Nov 25 12:21:41 2010 +0000
@@ -0,0 +1,130 @@
+# Makefile for rogue
+# %W% (Berkeley) %G%
+#
+# Super-Rogue
+# Copyright (C) 1984 Robert D. Kindelberger
+# All rights reserved.
+#
+# Based on "Rogue: Exploring the Dungeons of Doom"
+# Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
+# All rights reserved.
+#
+# See the file LICENSE.TXT for full copyright and licensing information.
+
+DISTNAME=srogue9.0-1
+PROGRAM=srogue
+
+HDRS= bob.h cx.h ncx.h rdk.h rogue.h 
+OBJS= vers.o armor.o chase.o command.o daemon.o daemons.o disply.o encumb.o \
+      fight.o global.o init.o io.o list.o main.o misc.o monsters.o move.o \
+      new_leve.o options.o pack.o passages.o potions.o pstats.o rings.o rip.o \
+      rooms.o save.o scrolls.o state.o sticks.o things.o trader.o weapons.o \
+      wizard.o xcrypt.o
+CFILES= vers.c armor.c chase.c command.c daemon.c daemons.c disply.c encumb.c \
+      fight.c global.c init.c io.c list.c main.c misc.c monsters.c move.c \
+      new_leve.c options.c pack.c passages.c potions.c pstats.c rings.c rip.c \
+      rooms.c save.c scrolls.c state.c sticks.c things.c trader.c weapons.c \
+      wizard.c xcrypt.c
+
+MISC=	Makefile LICENSE.TXT rogue.nr
+
+CC    = gcc
+CFLAGS= -g
+CRLIB = -lcurses
+RM    = rm -f
+TAR   = tar
+
+$(PROGRAM): $(HDRS) $(OBJS)
+	$(CC) $(CFLAGS) $(LDFLAGS) $(OBJS) $(CRLIB) -o $@
+
+tags: $(HDRS) $(CFILES)
+	ctags -u $?
+	ed - tags < :ctfix
+	sort tags -o tags
+
+lint:
+	lint -hxbc $(CFILES) $(CRLIB) > linterrs
+
+clean:
+	rm -f $(OBJS) core 
+	rm -f $(PROGRAM) $(PROGRAM).exe $(PROGRAM) $(PROGRAM).exe $(PROGRAM).tar $(PROGRAM).tar.gz $(PROGRAM).doc
+
+count:
+	wc -l $(HDRS) $(CFILES)
+
+realcount:
+	cc -E $(CFILES) | ssp - | wc -l
+
+update:
+	ar uv .SAVE $(CFILES) $(HDRS) $(MISC)
+
+dist:
+	@mkdir dist
+	cp $(CFILES) $(HDRS) $(MISC) dist
+
+dist.src:
+	make clean
+	tar cf $(DISTNAME)-src.tar $(CFILES) $(HDRS) $(MISC)
+	gzip -f $(DISTNAME)-src.tar
+
+dist.irix:
+	make clean
+	make CC=cc CFLAGS="-woff 1116 -O3" $(PROGRAM)
+	tbl rogue.nr | nroff -mm | colcrt - > $(PROGRAM).doc
+	tar cf $(DISTNAME)-irix.tar $(PROGRAM) LICENSE.TXT $(PROGRAM).doc
+	gzip -f $(DISTNAME)-irix.tar
+
+debug.aix:
+	make clean
+	make CC=xlc CFLAGS="-qmaxmem=16768 -g -DWIZARD  -qstrict" $(PROGRAM)
+
+dist.aix:
+	make clean
+	make CC=xlc CFLAGS="-qmaxmem=16768 -O3 -qstrict" $(PROGRAM)
+	tbl rogue.nr | nroff -mm | colcrt - > $(PROGRAM).doc
+	tar cf $(DISTNAME)-aix.tar $(PROGRAM) LICENSE.TXT $(PROGRAM).doc
+	gzip -f $(DISTNAME)-aix.tar
+
+debug.linux:
+	make clean
+	make CFLAGS="-g -DWIZARD" $(PROGRAM)
+
+dist.linux:
+	make clean
+	make $(PROGRAM)
+	groff -P-c -t -mm -Tascii rogue.nr | sed -e 's/.\x08//g' >$(PROGRAM).doc
+	tar cf $(DISTNAME)-linux.tar $(PROGRAM) LICENSE.TXT $(PROGRAM).doc
+	gzip -f $(DISTNAME)-linux.tar
+	
+debug.interix: 
+	make clean
+	make CFLAGS="-g3 -DWIZARD" $(PROGRAM)
+	
+dist.interix: 
+	make clean
+	make $(PROGRAM)
+	groff -P-b -P-u -t -mm -Tascii rogue.nr > $(PROGRAM).doc
+	tar cf $(DISTNAME)-interix.tar $(PROGRAM) LICENSE.TXT $(PROGRAM).doc
+	gzip -f $(DISTNAME)-interix.tar
+	
+debug.cygwin:
+	make clean
+	make CFLAGS="-g3 -DWIZARD" $(PROGRAM)
+
+dist.cygwin:
+	make clean
+	make $(PROGRAM)
+	groff -P-c -t -mm -Tascii rogue.nr | sed -e 's/.\x08//g' >$(PROGRAM).doc
+	tar cf $(DISTNAME)-cygwin.tar $(PROGRAM).exe LICENSE.TXT $(PROGRAM).doc
+	gzip -f $(DISTNAME)-cygwin.tar
+	
+debug.djgpp: 
+	make clean
+	make CFGLAGS="-g3 -DWIZARD" LDFLAGS="-L$(DJDIR)/LIB" CRLIB="-lpdcurses" $(PROGRAM)
+
+dist.djgpp: 
+	make clean
+	make LDFLAGS="-L$(DJDIR)/LIB" CRLIB="-lpdcurses" $(PROGRAM)
+	groff -t -mm -Tascii rogue.nr | sed -e 's/.\x08//g' > $(PROGRAM).doc
+	rm -f $(DISTNAME)-djgpp.zip
+	zip $(DISTNAME)-djgpp.zip $(PROGRAM).exe LICENSE.TXT $(PROGRAM).doc
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/srogue/armor.c	Thu Nov 25 12:21:41 2010 +0000
@@ -0,0 +1,108 @@
+/*
+ * This file contains misc functions for dealing with armor
+ *
+ * @(#)armor.c	9.0	(rdk)	 7/17/84
+ *
+ * Super-Rogue
+ * Copyright (C) 1984 Robert D. Kindelberger
+ * All rights reserved.
+ *
+ * Based on "Rogue: Exploring the Dungeons of Doom"
+ * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
+ * All rights reserved.
+ *
+ * See the file LICENSE.TXT for full copyright and licensing information.
+ */
+
+#include "rogue.h"
+#include "rogue.ext"
+
+/*
+ * wear:
+ *	The player wants to wear something, so let the hero try
+ */
+wear()
+{
+	reg struct linked_list *item;
+	reg struct object *obj;
+
+	if (cur_armor != NULL) {
+		msg("You are already wearing some.");
+		after = FALSE;
+		return;
+	}
+	if ((item = get_item("wear", ARMOR)) == NULL)
+		return;
+	obj = OBJPTR(item);
+	if (obj->o_type != ARMOR) {
+		msg("You can't wear that.");
+		return;
+	}
+	waste_time();
+	msg("Wearing %s.", a_magic[obj->o_which].mi_name);
+	cur_armor = obj;
+	setoflg(obj,ISKNOW);
+	nochange = FALSE;
+}
+
+
+/*
+ * take_off:
+ *	Get the armor off of the players back
+ */
+take_off()
+{
+	reg struct object *obj;
+
+	if ((obj = cur_armor) == NULL) {
+		msg("Not wearing any armor.");
+		return;
+	}
+	if (!dropcheck(cur_armor))
+		return;
+	cur_armor = NULL;
+	msg("Was wearing %c) %s",pack_char(obj),inv_name(obj,TRUE));
+	nochange = FALSE;
+}
+
+/*
+ * initarmor:
+ *		Initialize some armor.
+ */
+initarmor(obj, what)
+struct object *obj;
+int what;
+{
+	struct init_armor *iwa;
+	struct magic_item *mi;
+
+	obj->o_type = ARMOR;
+	obj->o_which = what;
+	iwa = &armors[what];
+	mi = &a_magic[what];
+	obj->o_vol = iwa->a_vol;
+	obj->o_ac = iwa->a_class;
+	obj->o_weight = iwa->a_wght;
+	obj->o_typname = things[TYP_ARMOR].mi_name;
+}
+
+/*
+ * hurt_armor:
+ *	Returns TRUE if armor is damaged
+ */
+hurt_armor(obj)
+struct object *obj;
+{
+	reg int type, ac;
+
+	if (obj != NULL) {
+		if (o_on(obj, ISPROT) || (o_on(obj, ISBLESS) && rnd(100) < 10))
+			return FALSE;
+		ac = obj->o_ac;
+		type = obj->o_which;
+		if (type != PADDED && type != LEATHER)
+			if ((type == STUDDED && ac < 8) || (type != STUDDED && ac < 9))
+				return TRUE;
+	}
+	return FALSE;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/srogue/bob.h	Thu Nov 25 12:21:41 2010 +0000
@@ -0,0 +1,12 @@
+/*
+ * Super-Rogue
+ * Copyright (C) 1984 Robert D. Kindelberger
+ * All rights reserved.
+ *
+ * See the file LICENSE.TXT for full copyright and licensing information.
+ */
+
+#include	<sgtty.h>
+typedef	struct sgttyb	SGTTY;
+static SGTTY _tty, _res_flg;
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/srogue/bsdtty.c	Thu Nov 25 12:21:41 2010 +0000
@@ -0,0 +1,121 @@
+/*
+ * Super-Rogue
+ * Copyright (C) 1984 Robert D. Kindelberger
+ * All rights reserved.
+ *
+ * See the file LICENSE.TXT for full copyright and licensing information.
+ */
+
+#include "rogue.h"
+
+extern	bool NONL;
+
+raw()
+{
+/*
+	VERSION 5.0
+	_tty.c_lflag &= ~ICANON;
+	_tty.c_cc[VMIN] = 1;
+	_tty.c_cc[VTIME] = 255;
+	_tty.c_oflag &= ~OPOST;
+*/
+	_rawmode = TRUE;
+	_tty.sg_flags |= CBREAK;
+	ioctl(_tty_ch, TIOCSETN, &_tty);
+}
+
+
+noraw()
+{
+/*
+	VERSION 5.0
+	_tty.c_lflag |= ICANON;
+	_tty.c_cc[VMIN] = _res_flg.c_cc[VMIN];
+	_tty.c_cc[VTIME] = _res_flg.c_cc[VTIME];
+	_tty.c_oflag |= OPOST;
+*/
+	_rawmode = FALSE;
+	_tty.sg_flags &= ~CBREAK;
+	ioctl(_tty_ch, TIOCSETN, &_tty);
+}
+
+
+crmode()
+{
+/*
+	VERSION 5.0
+	_tty.c_lflag &= ~ICANON;
+	_tty.c_oflag |= ONLCR;
+	_tty.c_cc[VMIN] = 1;
+	_tty.c_cc[VTIME]=255;
+*/
+	_rawmode = TRUE;
+	_tty.sg_flags |= (CBREAK | CRMOD);
+	ioctl(_tty_ch, TIOCSETN, &_tty);
+}
+
+
+nocrmode()
+{
+/*
+	_tty.c_lflag |= ICANON;
+	_tty.c_cc[VMIN]=_res_flg.c_cc[VMIN];
+	_tty.c_cc[VTIME]=_res_flg.c_cc[VTIME];
+*/
+	_rawmode = FALSE;
+	_tty.sg_flags &= ~CBREAK;
+	ioctl(_tty_ch, TIOCSETN, &_tty);
+}
+
+
+echo()
+{
+	_tty.sg_flags |= ECHO;
+	_echoit=TRUE;
+	ioctl(_tty_ch, TIOCSETN, &_tty);
+}
+
+noecho()
+{
+	_tty.sg_flags &= ~ECHO;
+	_echoit = FALSE;
+	ioctl(_tty_ch, TIOCSETN, &_tty);
+}
+
+
+nl()
+{
+/*
+	VERSION 5.0
+	_tty.c_iflag |= ICRNL;
+	_tty.c_oflag |= ONLCR;
+*/
+	_tty.sg_flags |= CRMOD;
+	NONL = TRUE;
+	ioctl(_tty_ch, TIOCSETN, &_tty);
+}
+
+
+nonl()
+{
+/*
+	VERSION 5.0
+	_tty.c_iflag &= ~ICRNL;
+	_tty.c_oflag &= ~ONLCR;
+*/
+	_tty.sg_flags &= ~CRMOD;
+	NONL = FALSE;
+	ioctl(_tty_ch, TIOCSETN, &_tty);
+}
+
+savetty()
+{
+	ioctl(_tty_ch, TIOCGETP, &_tty);
+	_res_flg = _tty;
+}
+
+resetty()
+{
+	_tty = _res_flg;
+	ioctl(_tty_ch, TIOCSETN, &_tty);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/srogue/chase.c	Thu Nov 25 12:21:41 2010 +0000
@@ -0,0 +1,486 @@
+/*
+ * Code for one object to chase another
+ *
+ * @(#)chase.c	9.0	(rdk)	 7/17/84
+ *
+ * Super-Rogue
+ * Copyright (C) 1984 Robert D. Kindelberger
+ * All rights reserved.
+ *
+ * Based on "Rogue: Exploring the Dungeons of Doom"
+ * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
+ * All rights reserved.
+ *
+ * See the file LICENSE.TXT for full copyright and licensing information.
+ */
+
+#include "rogue.h"
+#include "rogue.ext"
+
+#define FARAWAY	32767
+#define RDIST(a, b)	(DISTANCE((a)->y, (a)->x, (b).y, (b).x))
+
+struct coord ch_ret;	/* Where chasing takes you */
+
+/*
+ * runners:
+ *	Make all the running monsters move.
+ */
+runners()
+{
+	reg struct thing *tp;
+	reg struct linked_list *mon,*nextmon;
+
+	for (mon = mlist; mon != NULL; mon = nextmon) {
+		tp = THINGPTR(mon);
+		nextmon = next(mon);
+		if (off(*tp, ISHELD) && on(*tp, ISRUN)) {
+			if (tp->t_nomove > 0)
+				if (--tp->t_nomove > 0)
+					continue;
+			if (on(*tp, ISHASTE))
+				if (do_chase(mon) == -1)
+					continue;
+			if (off(*tp, ISSLOW) || tp->t_turn)
+				if (do_chase(mon) == -1)
+					continue;
+			tp->t_turn ^= TRUE;
+		}
+	}
+}
+
+
+/*
+ * do_chase:
+ *	Make one thing chase another.
+ */
+do_chase(mon)
+struct linked_list *mon;
+{
+	reg struct thing *th;
+	reg struct room *rer, *ree, *rxx;
+	reg int mindist, i, dist;
+	struct stats *st;
+	bool stoprun = FALSE, ondoor = FALSE, link = FALSE;
+	char runaway, dofight, wound, sch, ch;
+	struct coord this;
+	struct trap *trp;
+
+	th = THINGPTR(mon);
+	wound = th->t_flags & ISWOUND;
+	if (wound)
+		mindist = 0;
+	else
+		mindist = FARAWAY;
+	runaway = wound;
+	dofight = !runaway;
+	rer = th->t_room;
+	if (th->t_type == 'V') {
+		if (rer != NULL && !rf_on(rer, ISDARK)) {
+			/*
+			 * Vampires can't stand the light
+			 */
+			if (cansee(th->t_pos.y, th->t_pos.x))
+				msg("The vampire vaporizes into thin air !");
+			killed(mon, FALSE);
+			return(-1);
+		}
+	}
+	ree = roomin(th->t_dest);	/* room of chasee */
+	this = *th->t_dest;
+	/*
+	 * If the object of our desire is in a different
+	 * room, then run to the door nearest to our goal.
+	 */
+	if (mvinch(th->t_pos.y, th->t_pos.x) == DOOR)
+		ondoor = TRUE;
+	rxx = NULL;
+	if (rer != NULL || ree != NULL) {
+		/*
+		 * Monster not in room, hero in room. Run to closest door
+		 * in hero's room if not wounded. Run away if wounded.
+		 */
+		if (rer == NULL && ree != NULL) {
+			if (!wound)
+				rxx = ree;
+		}
+		/*
+		 * Monster in a room, hero not in room. If on a door,
+		 * then use closest distance. If not on a door, then
+		 * run to closest door in monsters room.
+		 */
+		else if (rer != NULL && ree == NULL) {
+			if (!ondoor) {
+				rxx = rer;
+				if (wound)
+					runaway = FALSE;
+			}
+		}
+		/*
+		 * Both hero and monster in a DIFFERENT room. Set flag to
+		 * check for links between the monster's and hero's rooms.
+		 * If no links are found, then the closest door in the
+		 * monster's room is used.
+		 */
+		else if (rer != ree) {
+			if (!wound) {
+				link = TRUE;
+				if (ondoor)
+					rxx = ree;	/* if on door, run to heros room */
+				else
+					rxx = rer;	/* else to nearest door this room */
+			}
+		}
+		/*
+		 * Both hero and monster in same room. If monster is
+		 * wounded, find the best door to run to.
+		 */
+		else if (wound) {
+			struct coord *ex;
+			int poss, mdtd, hdtd, ghdtd, nx, gx = 0, best;
+
+			best = ghdtd = -FARAWAY;
+			for (nx = 0; nx < ree->r_nexits; nx++) {
+				ex = &ree->r_exit[nx];
+				if (mvinch(ex->y, ex->x) == SECRETDOOR)
+					continue;
+				gx += 1;
+				mdtd = abs(th->t_pos.y - ex->y) + abs(th->t_pos.x - ex->x);
+				hdtd = abs(hero.y - ex->y) + abs(hero.x - ex->x);
+				poss = hdtd - mdtd;				/* possible move */
+				if (poss > best) {
+					best = poss;
+					this = *ex;
+				}
+				else if (poss == best && hdtd > ghdtd) {
+					ghdtd = hdtd;
+					best = poss;
+					this = *ex;
+				}
+			}
+			runaway = FALSE;		/* go for target */
+			if (best < 1)
+				dofight = TRUE;		/* fight if we must */
+			mdtd = (gx <= 1 && best < 1);
+			if (ondoor || mdtd) {
+				this = hero;
+				runaway = TRUE;
+				if (!mdtd)
+					dofight = FALSE;
+			}
+		}
+		if (rxx != NULL) {
+			for (i = 0; i < rxx->r_nexits; i += 1) {
+				dist = RDIST(th->t_dest, rxx->r_exit[i]);
+				if (link && rxx->r_ptr[i] == ree)
+					dist = -1;
+				if ((!wound && dist < mindist) ||
+				    (wound && dist > mindist)) {
+					this = rxx->r_exit[i];
+					mindist = dist;
+				}
+			}
+		}
+	}
+	else if (DISTANCE(hero.y, hero.x, th->t_pos.y, th->t_pos.x) <= 3)
+		dofight = TRUE;
+	/*
+	 * this now contains what we want to run to this time
+	 * so we run to it.  If we hit it we either want to
+	 * fight it or stop running.
+	 */
+	if (chase(th, &this, runaway, dofight) == FIGHT) {
+		return( attack(th) );
+	}
+	else if ((th->t_flags & (ISSTUCK | ISPARA)))
+		return(0);				/* if paralyzed or stuck */
+	if ((trp = trap_at(ch_ret.y, ch_ret.x)) != NULL) {
+		ch = be_trapped(&ch_ret, th);
+		if (ch == GONER || nlmove) {
+			if (ch == GONER)
+				remove_monster(&th->t_pos, mon);
+			nlmove = FALSE;
+			return((ch == GONER) ? -1 : 0);
+		}
+	}
+	if (pl_off(ISBLIND))
+		mvwaddch(cw,th->t_pos.y,th->t_pos.x,th->t_oldch);
+	sch = mvwinch(cw, ch_ret.y, ch_ret.x);
+	if (rer != NULL && rf_on(rer,ISDARK) && sch == FLOOR &&
+	  DISTANCE(ch_ret.y,ch_ret.x,th->t_pos.y,th->t_pos.x) < 3 &&
+	  pl_off(ISBLIND))
+		th->t_oldch = ' ';
+	else
+		th->t_oldch = sch;
+	if (cansee(unc(ch_ret)) && off(*th, ISINVIS))
+		mvwaddch(cw, ch_ret.y, ch_ret.x, th->t_type);
+	mvwaddch(mw, th->t_pos.y, th->t_pos.x, ' ');
+	mvwaddch(mw, ch_ret.y, ch_ret.x, th->t_type);
+	th->t_oldpos = th->t_pos;
+	th->t_pos = ch_ret;
+	th->t_room = roomin(&ch_ret);
+	i = 5;
+	if (th->t_flags & ISREGEN)
+		i = 40;
+	st = &th->t_stats;
+	if (rnd(100) < i) {
+		if (++st->s_hpt > st->s_maxhp)
+			st->s_hpt = st->s_maxhp;
+		if (!monhurt(th))
+			th->t_flags &= ~ISWOUND;
+	}
+	if (stoprun && ce(th->t_pos, *(th->t_dest)))
+		th->t_flags &= ~ISRUN;
+	return CHASE;
+}
+
+
+/*
+ * chase:
+ *	Find the spot for the chaser to move closer to the
+ *	chasee.  Returns TRUE if we want to keep on chasing
+ *	later FALSE if we reach the goal.
+ */
+chase(tp, ee, runaway, dofight)
+struct thing *tp;
+struct coord *ee;
+bool runaway, dofight;
+{
+	reg int x, y, ch;
+	reg int dist, thisdist, closest;
+	reg struct coord *er = &tp->t_pos;
+	struct coord try, closecoord;
+	int numsteps, onscare;
+
+	/*
+	 * If the thing is confused, let it move randomly.
+	 */
+	ch = CHASE;
+	onscare = FALSE;
+	if (on(*tp, ISHUH)) {
+		ch_ret = *rndmove(tp);
+		dist = DISTANCE(hero.y, hero.x, ch_ret.y, ch_ret.x);
+		if (rnd(1000) < 5)
+			tp->t_flags &= ~ISHUH;
+		if (dist == 0)
+			ch = FIGHT;
+	}
+	else {
+		/*
+		 * Otherwise, find the the best spot to run to
+		 * in order to get to your goal.
+		 */
+		numsteps = 0;
+		if (runaway)
+			closest = 0;
+		else
+			closest = FARAWAY;
+		ch_ret = *er;
+		closecoord = tp->t_oldpos;
+		for (y = er->y - 1; y <= er->y + 1; y += 1) {
+			for (x = er->x - 1; x <= er->x + 1; x += 1) {
+				if (!cordok(y, x))
+					continue;
+				try.x = x;
+				try.y = y;
+				if (!diag_ok(er, &try))
+					continue;
+				ch = winat(y, x);
+				if (step_ok(ch)) {
+					struct trap *trp;
+
+					if (isatrap(ch)) {
+						trp = trap_at(y, x);
+						if (trp != NULL && off(*tp, ISHUH)) {
+							/*
+							 * Dont run over found traps unless
+							 * the hero is standing on it. If confused,
+							 * then he can run into them.
+							 */
+							if (trp->tr_flags & ISFOUND) {
+								if (trp->tr_type == POOL && rnd(100) < 80)
+									continue;
+								else if (y != hero.y || x != hero.x)
+									continue;
+							}
+						}
+					}
+					/*
+					 * Check for scare monster scrolls.
+					 */
+					if (ch == SCROLL) {
+						struct linked_list *item;
+
+						item = find_obj(y, x);
+						if (item != NULL)
+							if ((OBJPTR(item))->o_which == S_SCARE) {
+								if (ce(hero, try))
+									onscare = TRUE;
+								continue;
+							}
+					}
+					/*
+					 * Vampires will not run into a lit room.
+					 */
+					if (tp->t_type == 'V') {
+						struct room *lr;
+
+						lr = roomin(&try);
+						if (lr != NULL && !rf_on(lr, ISDARK))
+							continue;
+					}
+					/*
+					 * This is a valid place to step
+					 */
+					if (y == hero.y && x == hero.x) {
+						if (dofight) {
+							ch_ret = try;	/* if fighting */
+							return FIGHT;	/* hit hero */
+						}
+						else
+							continue;
+					}
+					thisdist = DISTANCE(y, x, ee->y, ee->x);
+					if (thisdist <= 0) {
+						ch_ret = try;	/* got here but */
+						return CHASE;	/* dont fight */
+					}
+					numsteps += 1;
+					if ((!runaway && thisdist < closest) ||
+						(runaway && thisdist > closest)) {
+						/*
+						 * dont count the monsters last position as
+						 * the closest spot, unless running away and
+						 * in the same room.
+						 */
+						if (!ce(try, tp->t_oldpos) || (runaway
+						  && player.t_room == tp->t_room
+						  && tp->t_room != NULL)) {
+							closest = thisdist;
+							closecoord = try;
+						}
+					}
+				}
+			}
+		}
+		/*
+		 * If dead end, then go back from whence you came.
+		 * Otherwise, pick the closest of the remaining spots.
+		 */
+		if (numsteps > 0)			/* move to best spot */
+			ch_ret = closecoord;
+		else {						/* nowhere to go */
+			if (DISTANCE(tp->t_pos.y, tp->t_pos.x, hero.y, hero.x) < 2)
+				if (!onscare)
+					ch_ret = hero;
+		}
+		if (ce(hero, ch_ret))
+			ch = FIGHT;
+	}
+	return ch;
+}
+
+
+/*
+ * runto:
+ *	Set a monster running after something
+ */
+runto(runner, spot)
+struct coord *runner;
+struct coord *spot;
+{
+	reg struct linked_list *item;
+	reg struct thing *tp;
+
+	if ((item = find_mons(runner->y, runner->x)) == NULL)
+		return;
+	tp = THINGPTR(item);
+	if (tp->t_flags & ISPARA)
+		return;
+	tp->t_dest = spot;
+	tp->t_flags |= ISRUN;
+	tp->t_flags &= ~ISHELD;
+}
+
+
+/*
+ * roomin:
+ *	Find what room some coordinates are in.
+ *	NULL means they aren't in any room.
+ */
+struct room *
+roomin(cp)
+struct coord *cp;
+{
+	reg struct room *rp;
+
+	if (cordok(cp->y, cp->x)) {
+		for (rp = rooms; rp < &rooms[MAXROOMS]; rp += 1)
+			if (inroom(rp, cp))
+				return rp;
+	}
+	return NULL;
+}
+
+
+/*
+ * find_mons:
+ *	Find the monster from his coordinates
+ */
+struct linked_list *
+find_mons(y, x)
+int y, x;
+{
+	reg struct linked_list *item;
+	reg struct thing *th;
+
+	for (item = mlist; item != NULL; item = next(item)) {
+		th = THINGPTR(item);
+		if (th->t_pos.y == y && th->t_pos.x == x)
+			return item;
+	}
+	return NULL;
+}
+
+
+/*
+ * diag_ok:
+ *	Check to see if the move is legal if it is diagonal
+ */
+diag_ok(sp, ep)
+struct coord *sp, *ep;
+{
+	if (ep->x == sp->x || ep->y == sp->y)
+		return TRUE;
+	if (step_ok(mvinch(ep->y,sp->x)) && step_ok(mvinch(sp->y,ep->x)))
+		return TRUE;
+	return FALSE;
+}
+
+
+/*
+ * cansee:
+ *	returns true if the hero can see a certain coordinate.
+ */
+cansee(y, x)
+int y, x;
+{
+	reg struct room *rer;
+	struct coord tp;
+
+	if (pl_on(ISBLIND))
+		return FALSE;
+	/*
+	 * We can only see if the hero in the same room as
+	 * the coordinate and the room is lit or if it is close.
+	 */
+	if (DISTANCE(y, x, hero.y, hero.x) < 3)
+		return TRUE;
+	tp.y = y;
+	tp.x = x;
+	rer = roomin(&tp);
+	if (rer != NULL && levtype != MAZELEV)
+		if (rer == player.t_room && !rf_on(rer,ISDARK))
+			return TRUE;
+	return FALSE;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/srogue/command.c	Thu Nov 25 12:21:41 2010 +0000
@@ -0,0 +1,714 @@
+/*
+ * Read and execute the user commands
+ *
+ * @(#)command.c	9.0	(rdk)	 7/17/84
+ *
+ * Super-Rogue
+ * Copyright (C) 1984 Robert D. Kindelberger
+ * All rights reserved.
+ *
+ * Based on "Rogue: Exploring the Dungeons of Doom"
+ * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
+ * All rights reserved.
+ *
+ * See the file LICENSE.TXT for full copyright and licensing information.
+ */
+
+#include <ctype.h>
+#include <signal.h>
+#include <limits.h>
+#include "rogue.h"
+#include "rogue.ext"
+#ifdef __DJGPP__
+#include <process.h>
+#endif
+
+/*
+ * command:
+ *	Process the user commands
+ */
+command()
+{
+	reg char ch;
+	reg int ntimes = 1;		/* Number of player moves */
+	static char countch, direction, newcount = FALSE;
+
+	if (pl_on(ISHASTE))
+		ntimes++;
+	/*
+	 * Let the daemons start up
+	 */
+	while (ntimes-- > 0) {
+		do_daemons(BEFORE);
+		look(TRUE);
+		if (!running)
+			door_stop = FALSE;
+		lastscore = purse;
+		wmove(cw, hero.y, hero.x);
+		if (!(running || count))
+			draw(cw);			/* Draw screen */
+		take = 0;
+		after = TRUE;
+		/*
+		 * Read command or continue run
+		 */
+		if (wizard)
+			waswizard = TRUE;
+		if (player.t_nocmd <= 0) {
+			player.t_nocmd = 0;
+			if (running)
+				ch = runch;
+			else if (count)
+				ch = countch;
+			else {
+				ch = readchar();
+				if (mpos != 0 && !running) /* Erase message if its there */
+					msg("");
+			}
+		}
+		else
+			ch = '.';
+		if (player.t_nocmd > 0) {
+			if (--player.t_nocmd <= 0)
+				msg("You can move again.");	
+		}
+		else {
+			/*
+			 * check for prefixes
+			 */
+			if (isdigit(ch)) {
+				count = 0;
+				newcount = TRUE;
+				while (isdigit(ch)) {
+					count = count * 10 + (ch - '0');
+					ch = readchar();
+				}
+				countch = ch;
+				/*
+				 * turn off count for commands which don't make sense
+				 * to repeat
+				 */
+				switch (ch) {
+					case 'h': case 'j': case 'k': case 'l':
+					case 'y': case 'u': case 'b': case 'n':
+					case 'H': case 'J': case 'K': case 'L':
+					case 'Y': case 'U': case 'B': case 'N':
+					case 'q': case 'r': case 's': case 'f':
+					case 't': case 'C': case 'I': case '.':
+					case 'z': case 'p':
+						break;
+					default:
+						count = 0;
+				}
+			}
+			switch (ch) {
+			case 'f':
+			case 'g':
+				if (pl_off(ISBLIND)) {
+					door_stop = TRUE;
+					firstmove = TRUE;
+				}
+				if (count && !newcount)
+					ch = direction;
+				else
+					ch = readchar();
+				switch (ch) {
+					case 'h': case 'j': case 'k': case 'l':
+					case 'y': case 'u': case 'b': case 'n':
+						ch = toupper(ch);
+				}
+				direction = ch;
+			}
+			newcount = FALSE;
+			/*
+			 * execute a command
+			 */
+			if (count && !running)
+				count--;
+			switch (ch) {
+				case '!' : shell(); after = FALSE;
+				when 'h' : do_move(0, -1);
+				when 'j' : do_move(1, 0);
+				when 'k' : do_move(-1, 0);
+				when 'l' : do_move(0, 1);
+				when 'y' : do_move(-1, -1);
+				when 'u' : do_move(-1, 1);
+				when 'b' : do_move(1, -1);
+				when 'n' : do_move(1, 1);
+				when 'H' : do_run('h');
+				when 'J' : do_run('j');
+				when 'K' : do_run('k');
+				when 'L' : do_run('l');
+				when 'Y' : do_run('y');
+				when 'U' : do_run('u');
+				when 'B' : do_run('b');
+				when 'N' : do_run('n');
+				when 't':
+					if (!get_dir())
+						after = FALSE;
+					else
+						missile(delta.y, delta.x);
+				when 'Q' : after = FALSE; quit(-1);
+				when 'i' : after = FALSE; inventory(pack, 0);
+				when 'I' : after = FALSE; picky_inven();
+				when 'd' : drop(NULL);
+				when 'q' : quaff();
+				when 'r' : read_scroll();
+				when 'e' : eat();
+				when 'w' : wield();
+				when 'W' : wear();
+				when 'T' : take_off();
+				when 'P' : ring_on();
+				when 'R' : ring_off();
+				when 'O' : option();
+				when 'c' : call();
+				when '>' : after = FALSE; d_level();
+				when '<' : after = FALSE; u_level();
+				when '?' : after = FALSE; help();
+				when '/' : after = FALSE; identify(0);
+				when 's' : search();
+				when 'z' : do_zap(FALSE);
+				when 'p':
+					if (get_dir())
+						do_zap(TRUE);
+					else
+						after = FALSE;
+				when 'v': msg("Super Rogue version %s.",release);
+				when 'D': dip_it();
+				when CTRL('L') : after = FALSE; restscr(cw);
+				when CTRL('R') : after = FALSE; msg(huh);
+				when 'a': after = FALSE; dispmax();
+				when '@' : if (author())
+					msg("Hero @ %d,%d : Stairs @ %d,%d",hero.y,hero.x,stairs.y,stairs.x);
+				when 'S' : 
+					after = FALSE;
+					if (save_game()) {
+						wclear(cw);
+						draw(cw);
+						endwin();
+						byebye(0);
+					}
+				when '.' : ;				/* Rest command */
+				when ' ' : after = FALSE;	/* do nothing */
+				when '=' :
+					if (author()) {
+						activity();
+						after = FALSE;
+					}
+				when CTRL('P') :
+					after = FALSE;
+					if (wizard) {
+						wizard = FALSE;
+						msg("Not wizard any more");
+					}
+					else {
+						wizard = passwd();
+						if (wizard) {
+							msg("Welcome back, Bob!!!!!");
+							waswizard = TRUE;
+						}
+						else
+							msg("Sorry");
+					}
+				when ESCAPE :	/* Escape */
+					door_stop = FALSE;
+					count = 0;
+					after = FALSE;
+				when '#':
+					if (levtype == POSTLEV)		/* buy something */
+						buy_it();
+					after = FALSE;
+				when '$':
+					if (levtype == POSTLEV)		/* price something */
+						price_it();
+					after = FALSE;
+				when '%':
+					if (levtype == POSTLEV)		/* sell something */
+						sell_it();
+					after = FALSE;
+				otherwise :
+					after = FALSE;
+					if (wizard) switch (ch) {
+					case CTRL('A') : ;
+					when 'C'     :	create_obj(FALSE);
+					when CTRL('I') :	inventory(lvl_obj, 1);
+					when CTRL('W') :	whatis(NULL);
+					when CTRL('D') :	level++; new_level(NORMLEV);
+					when CTRL('U') :	if (level > 1) level--; new_level(NORMLEV);
+					when CTRL('F') :	displevl();
+					when CTRL('X') :	dispmons();
+					when CTRL('T') :	teleport(rndspot,&player);
+					when CTRL('E') :	msg("food left: %d", food_left);
+					when CTRL('O') :	add_pass();
+					when 'M' : {
+						int tlev, whichlev;
+						prbuf[0] = '\0';
+						msg("Which level? ");
+						if (get_str(prbuf,cw) == NORM) {
+							whichlev = NORMLEV;
+							tlev = atoi(prbuf);
+							if (tlev < 1)
+								level = 1;
+							if (tlev >= 200) {
+								tlev -= 199;
+								whichlev = MAZELEV;
+							}
+							else if (tlev >= 100) {
+								tlev -= 99;
+								whichlev = POSTLEV;
+							}
+							level = tlev;
+							new_level(whichlev);
+						}
+					}
+					when CTRL('N') : {
+						struct linked_list *item;
+
+						item = get_item("charge", STICK);
+						if (item != NULL) {
+							(OBJPTR(item))->o_charges = 10000;
+							msg("");
+						}
+					}
+					when CTRL('H') : {
+						int i;
+						struct linked_list *item;
+						struct object *obj;
+
+						him->s_exp = e_levels[him->s_lvl + 7] + 1;
+						check_level();
+						/*
+						 * Give the rogue a very good sword
+						 */
+						item = new_thing(FALSE, WEAPON, TWOSWORD);
+						obj = OBJPTR(item);
+						obj->o_hplus = 3;
+						obj->o_dplus = 3;
+						obj->o_flags = ISKNOW;
+						i = add_pack(item, TRUE);
+						if (i)
+							cur_weapon = obj;
+						else
+							discard(item);
+						/*
+						 * And his suit of armor
+						 */
+						item = new_thing(FALSE, ARMOR, PLATEARMOR);
+						obj = OBJPTR(item);
+						obj->o_ac = -8;
+						obj->o_flags = ISKNOW;
+						i = add_pack(item, TRUE);
+						if (i)
+							cur_armor = obj;
+						else
+							discard(item);
+						nochange = FALSE;
+					}
+					otherwise:
+						msg(illegal, unctrl(ch));
+						count = 0;
+				}
+				else {
+					msg(illegal, unctrl(ch));
+					count = 0;
+				}
+			}
+			/*
+			 * turn off flags if no longer needed
+			 */
+			if (!running)
+				door_stop = FALSE;
+		}
+		/*
+		 * If he ran into something to take, let the
+		 * hero pick it up if not in a trading post.
+		 */
+		if (take != 0 && levtype != POSTLEV)
+			pick_up(take);
+		if (!running)
+			door_stop = FALSE;
+	}
+	/*
+	 * Kick off the rest if the daemons and fuses
+	 */
+	if (after) {
+		int  j;
+
+		look(FALSE);
+		do_daemons(AFTER);
+		do_fuses();
+		if (pl_on(ISSLOW))
+			waste_time();
+		for (j = LEFT; j <= RIGHT; j++) {
+			if (cur_ring[j] != NULL) {
+				if (cur_ring[j]->o_which == R_SEARCH)
+					search();
+				else if (cur_ring[j]->o_which == R_TELEPORT)
+					if (rnd(100) < 5)
+						teleport(rndspot, &player);
+	 		}
+		}
+	}
+}
+
+
+/*
+ * quit:
+ *	Have player make certain, then exit.
+ */
+void
+quit(int a)
+{
+	reg char ch, good;
+	/*
+	 * Reset the signal in case we got here via an interrupt
+	 */
+	if (signal(SIGINT, quit) != quit)
+		mpos = 0;
+	msg("Really quit? [y/n/s]");
+/*	ch = tolower(readchar());*/
+	ch = readchar();
+	if (ch == 'y') {
+		clear();
+		move(LINES-1, 0);
+		refresh();
+		score(purse, CHICKEN, 0);
+		byebye(0);
+	}
+	else if (ch == 's') {
+		good = save_game();
+		if (good) {
+			wclear(cw);
+			draw(cw);
+			endwin();
+			byebye(0);
+		}
+	}
+	else {
+		signal(SIGINT, quit);
+		wmove(cw, 0, 0);
+		wclrtoeol(cw);
+		draw(cw);
+		mpos = 0;
+		count = 0;
+		nochange = FALSE;
+	}
+}
+
+/*
+ * search:
+ *	Player gropes about him to find hidden things.
+ */
+
+search()
+{
+	reg int x, y;
+	reg char ch;
+
+	/*
+	 * Look all around the hero, if there is something hidden there,
+	 * give him a chance to find it.  If its found, display it.
+	 */
+	if (pl_on(ISBLIND))
+		return;
+	for (x = hero.x - 1; x <= hero.x + 1; x++) {
+		for (y = hero.y - 1; y <= hero.y + 1; y++) {
+			ch = winat(y, x);
+			if (isatrap(ch)) {		/* see if its a trap */
+				reg struct trap *tp;
+
+				if ((tp = trap_at(y, x)) == NULL)
+					break;
+				if (tp->tr_flags & ISFOUND)
+					break;		/* no message if its seen */
+				if (mvwinch(cw, y, x) == ch)
+					break;
+				if (rnd(100) > (him->s_lvl * 9 + herowis() * 5))
+					 break;
+				tp->tr_flags |= ISFOUND;
+				mvwaddch(cw, y, x, tp->tr_type);
+				count = 0;
+				running = FALSE;
+				msg(tr_name(tp->tr_type));
+			}
+			else if(ch == SECRETDOOR) {
+				if (rnd(100) < (him->s_lvl * 4 + herowis() * 5)) {
+					mvaddch(y, x, DOOR);
+					count = 0;
+				}
+			}
+		}
+	}
+}
+
+/*
+ * help:
+ *	Give single character help, or the whole mess if he wants it
+ */
+help()
+{
+	extern struct h_list helpstr[];
+	reg struct h_list *strp;
+	reg char helpch;
+	reg int cnt;
+
+	strp = &helpstr[0];
+	msg("Character you want help for (* for all): ");
+	helpch = readchar();
+	mpos = 0;
+	/*
+	 * If its not a *, print the right help string
+	 * or an error if he typed a funny character.
+	 */
+	if (helpch != '*') {
+		wmove(cw, 0, 0);
+		while (strp->h_ch) {
+			if (strp->h_ch == helpch) {
+				msg("%s%s", unctrl(strp->h_ch), strp->h_desc);
+				break;
+			}
+			strp++;
+		}
+		if (strp->h_ch != helpch)
+			msg("Unknown character '%s'", unctrl(helpch));
+		return;
+	}
+	/*
+	 * Here we print help for everything.
+	 * Then wait before we return to command mode
+	 */
+	wclear(hw);
+	cnt = 0;
+	while (strp->h_ch) {
+		mvwaddstr(hw, cnt % 23, cnt > 22 ? 40 : 0, unctrl(strp->h_ch));
+		waddstr(hw, strp->h_desc);
+		cnt++;
+		strp++;
+	}
+	wmove(hw, LINES-1, 0);
+	wprintw(hw,spacemsg);
+	draw(hw);
+	wait_for(hw,' ');
+	wclear(hw);
+	draw(hw);
+	wmove(cw, 0, 0);
+	wclrtoeol(cw);
+	touchwin(cw);
+	nochange = FALSE;
+}
+
+
+/*
+ * identify:
+ *	Tell the player what a certain thing is.
+ */
+char *
+identify(what)
+int what;
+{
+	reg char ch, *str;
+
+	if (what == 0) {
+		msg("What do you want identified? ");
+		ch = readchar();
+		mpos = 0;
+		if (ch == ESCAPE) {
+			msg("");
+			return NULL;
+		}
+	}
+	else
+		ch = what;
+	if (isalpha(ch))
+		str = monsters[midx(ch)].m_name;
+	else {
+		switch(ch) {
+			case '|':
+			case '-':	str = "the wall of a room";
+			when GOLD:	str = "gold";
+			when STAIRS:	str = "passage leading up/down";
+			when DOOR:	str = "door";
+			when FLOOR:	str = "room floor";
+			when PLAYER:	str = "you";
+			when PASSAGE:	str = "passage";
+			when POST:	str = "trading post";
+			when MAZETRAP:	str = "maze trap";
+			when TRAPDOOR:	str = "trapdoor";
+			when ARROWTRAP:	str = "arrow trap";
+			when SLEEPTRAP:	str = "sleeping gas trap";
+			when BEARTRAP:	str = "bear trap";
+			when TELTRAP:	str = "teleport trap";
+			when DARTTRAP:	str = "dart trap";
+			when POOL:	str = "magic pool";
+			when POTION:	str = "potion";
+			when SCROLL:	str = "scroll";
+			when FOOD:	str = "food";
+			when WEAPON:	str = "weapon";
+			when ' ' :	str = "solid rock";
+			when ARMOR:	str = "armor";
+			when AMULET:	str = "The Amulet of Yendor";
+			when RING:	str = "ring";
+			when STICK:	str = "wand or staff";
+			otherwise:
+				if (what == 0)
+					str = "unknown character";
+				else
+					str = "a magical ghost";
+		}
+	}
+	if (what == 0)
+		msg("'%s' : %s", unctrl(ch), str);
+	return str;
+}
+
+/*
+ * d_level:
+ *	He wants to go down a level
+ */
+d_level()
+{
+	if (winat(hero.y, hero.x) != STAIRS)
+		msg("I see no way down.");
+	else {
+		if (pl_on(ISHELD)) {
+			msg("You are being held.");
+			return;
+		}
+		level++;
+		new_level(NORMLEV);
+	}
+}
+
+/*
+ * u_level:
+ *	He wants to go up a level
+ */
+u_level()
+{
+	if (winat(hero.y, hero.x) == STAIRS)  {
+		if (pl_on(ISHELD)) {
+			msg("You are being held.");
+			return;
+		}
+		else {				/* player not held here */
+			if (amulet) {
+				level--;
+				if (level == 0)
+					total_winner();
+				new_level(NORMLEV);
+				msg("You feel a wrenching sensation in your gut.");
+				return;
+			}
+		}
+	}
+	msg("I see no way up.");
+}
+
+
+/*
+ * Let him escape for a while
+ */
+shell()
+{
+	reg int pid;
+	reg char *sh;
+	int ret_status;
+
+	/*
+	 * Set the terminal back to original mode
+	 */
+	sh = getenv("SHELL");
+	wclear(hw);
+	wmove(hw, LINES-1, 0);
+	draw(hw);
+	endwin();
+	in_shell = TRUE;
+	fflush(stdout);
+	/*
+	 * Fork and do a shell
+	 */
+#ifndef __DJGPP__
+	while((pid = fork()) < 0)
+		sleep(1);
+	if (pid == 0) {
+		setuid(playuid);	/* Set back to original user */
+		setgid(playgid);
+		execl(sh == NULL ? "/bin/sh" : sh, "shell", "-i", 0);
+		perror("No shelly");
+		byebye(-1);
+	}
+	else {
+		signal(SIGINT, SIG_IGN);
+		signal(SIGQUIT, SIG_IGN);
+		while (wait(&ret_status) != pid)
+			continue;
+		signal(SIGINT, quit);
+		signal(SIGQUIT, endit);
+
+#else
+	{
+		char shell[PATH_MAX];
+
+		if (sh && *sh)
+			strncpy(shell,sh,PATH_MAX);
+		else
+			sprintf(shell, "%s\\bin\\sh.exe", getenv("DJDIR"));
+
+		if (spawnl(P_WAIT,shell, "shell", "-i", 0) == -1)
+			msg("No shelly: %s", shell);
+
+#endif
+		printf("\n%s", retstr);
+		fflush(stdout);
+		noecho();
+		crmode();
+		in_shell = FALSE;
+		wait_for(cw, '\n');
+		restscr(cw);
+	}
+}
+
+
+/*
+ * call:
+ *	Allow a user to call a potion, scroll, or ring something
+ */
+call()
+{
+	reg struct object *obj;
+	reg struct linked_list *item;
+	reg char **guess, *elsewise;
+	int wh;
+
+	if ((item = get_item("call", 0)) == NULL)
+		return;
+	obj = OBJPTR(item);
+	wh = obj->o_which;
+	switch (obj->o_type) {
+	case RING:
+		guess = r_guess;
+		elsewise = (r_guess[wh] != NULL ? r_guess[wh] : r_stones[wh]);
+	when POTION:
+		guess = p_guess;
+		elsewise = (p_guess[wh] != NULL ? p_guess[wh] : p_colors[wh]);
+	when SCROLL:
+		guess = s_guess;
+		elsewise = (s_guess[wh] != NULL ? s_guess[wh] : s_names[wh]);
+	when STICK:
+		guess = ws_guess;
+		elsewise =(ws_guess[wh] != NULL ?
+			ws_guess[wh] : ws_stuff[wh].ws_made);
+	otherwise:
+		msg("You can't call %ss anything",obj->o_typname);
+		return;
+	}
+	msg("Was called \"%s\"", elsewise);
+	msg(callit);
+	if (guess[wh] != NULL)
+		free(guess[wh]);
+	strcpy(prbuf, elsewise);
+	if (get_str(prbuf, cw) == NORM) {
+		guess[wh] = new(strlen(prbuf) + 1);
+		strcpy(guess[wh], prbuf);
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/srogue/cx.h	Thu Nov 25 12:21:41 2010 +0000
@@ -0,0 +1,130 @@
+/*
+ * Super-Rogue
+ * Copyright (C) 1984 Robert D. Kindelberger
+ * All rights reserved.
+ *
+ * See the file LICENSE.TXT for full copyright and licensing information.
+ */
+
+#include	<stdio.h>
+#include	<sgtty.h>
+
+#define	bool	char		/* boolean variable	*/
+#define	reg	register	/* register abbr.	*/
+
+#define	TRUE	(1)
+#define	FALSE	(0)
+#define	ERR	(0)	/* default return on error	*/
+#define	OK	(1)	/* default return on good run	*/
+
+#define	_SUBWIN	01	/* window is a subwindow	*/
+#define	_ENDLINE 02	/* lines go to end of screen	*/
+#define	_FULLWIN 04	/* window is entire screen	*/
+#define	_SCROLLWIN 010	/* window could cause scroll	*/
+#define	_STANDOUT 0200	/* standout mode in effect	*/
+#define	_NOCHANGE -1	/* no change on this line	*/
+
+#define	_puts(s)	tputs(s, 0, _putchar);
+
+typedef	struct sgttyb	SGTTY;
+
+#ifndef WINDOW
+
+#define	WINDOW	struct _win_st
+
+/* window description structure		*/
+struct _win_st {
+    short _cury, _curx;		/* current y,x positions */
+    short _maxy, _maxx;		/* maximum y,x positions */
+    short _begy, _begx;		/* start y,x positions	 */
+    short _flags;		/* various window flags	 */
+    bool _clear;		/* need to clear	 */
+    bool _leave;		/* leave cur x,y at last update	*/
+    bool _scroll;		/* scrolls allowed	*/
+    char **_y;			/* actual window	*/
+    short *_firstch;		/* first change on line	*/
+    short *_lastch;		/* last change on line	*/
+};
+
+extern bool My_term,	/* user specied terminal	*/
+	    _echoit,	/* set if echoing characters	*/
+	    _rawmode;	/* set if terminal in raw mode	*/
+
+extern char *Def_term,	/* default terminal type	*/
+	    ttytype[];	/* long name of current term	*/
+# ifdef DEBUG
+extern FILE *outf;	/* error outfile		*/
+# endif
+
+extern int LINES, COLS;	/* # of lines & columns		*/
+extern int _tty_ch;	/* channel with tty on it	*/
+extern WINDOW *stdscr, *curscr;
+
+static SGTTY _tty, _res_flg;
+
+/*
+ * Define VOID to stop lint from generating "null effect"
+ * comments.
+ */
+# ifdef lint
+int	__void__;	/* place to assign to		*/
+
+# define	VOID(x)	(__void__ = (int) (x))
+# else
+# define	VOID(x)	(x)
+# endif
+
+# endif
+
+/*
+ * psuedo functions for standard screen
+ */
+#define	addch(ch)	VOID(waddch(stdscr, ch))
+#define	getch()		VOID(wgetch(stdscr))
+#define	addstr(str)	VOID(waddstr(stdscr, str))
+#define	getstr(str)	VOID(wgetstr(stdscr, str))
+#define	move(y, x)	VOID(wmove(stdscr, y, x))
+#define	clear()		VOID(wclear(stdscr))
+#define	erase()		VOID(werase(stdscr))
+#define	clrtobot()	VOID(wclrtobot(stdscr))
+#define	clrtoeol()	VOID(wclrtoeol(stdscr))
+#define	insertln()	VOID(winsertln(stdscr))
+#define	deleteln()	VOID(wdeleteln(stdscr))
+#define	refresh()	VOID(wrefresh(stdscr))
+#define	inch()		VOID(winch(stdscr))
+
+#ifdef STANDOUT
+#define	standout()	VOID(wstandout(stdscr))
+#define	standend()	VOID(wstandend(stdscr))
+#endif
+
+/*
+# define	CBREAK 	FALSE
+# define	_IOSTRG 01
+*/
+
+/*
+ * mv functions
+ */
+#define	mvwaddch(win,y,x,ch)	VOID(wmove(win,y,x)==ERR?ERR:waddch(win,ch))
+#define	mvwgetch(win,y,x,ch)	VOID(wmove(win,y,x)==ERR?ERR:wgetch(win,ch))
+#define	mvwaddstr(win,y,x,str)	VOID(wmove(win,y,x)==ERR?ERR:waddstr(win,str))
+#define	mvwgetstr(win,y,x,str)	VOID(wmove(win,y,x)==ERR?ERR:wgetstr(win,str))
+#define	mvwinch(win,y,x)	VOID(wmove(win,y,x) == ERR ? ERR : winch(win))
+#define	mvaddch(y,x,ch)		mvwaddch(stdscr,y,x,ch)
+#define	mvgetch(y,x,ch)		mvwgetch(stdscr,y,x,ch)
+#define	mvaddstr(y,x,str)	mvwaddstr(stdscr,y,x,str)
+#define	mvgetstr(y,x,str)	mvwgetstr(stdscr,y,x,str)
+#define	mvinch(y,x)		mvwinch(stdscr,y,x)
+
+/*
+ * psuedo functions
+ */
+
+#define	clearok(win,bf)	 (win->_clear = bf)
+#define	leaveok(win,bf)	 (win->_leave = bf)
+#define	scrollok(win,bf) (win->_scroll = bf)
+#define	getyx(win,y,x)	 y = win->_cury, x = win->_curx
+#define	winch(win)	 (win->_y[win->_cury][win->_curx])
+
+WINDOW	*initscr(), *newwin();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/srogue/daemon.c	Thu Nov 25 12:21:41 2010 +0000
@@ -0,0 +1,177 @@
+/*
+ * Contains functions for dealing with things that
+ * happen in the future.
+ *
+ * @(#)daemon.c	9.0	(rdk)	 7/17/84
+ *
+ * Super-Rogue
+ * Copyright (C) 1984 Robert D. Kindelberger
+ * All rights reserved.
+ *
+ * Based on "Rogue: Exploring the Dungeons of Doom"
+ * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
+ * All rights reserved.
+ *
+ * See the file LICENSE.TXT for full copyright and licensing information.
+ */
+
+#include "rogue.h"
+#include "rogue.ext"
+
+#define EMPTY 0
+#define DAEMON -1
+
+#define _X_ { 0, 0, 0, 0 }
+
+struct delayed_action d_list[MAXDAEMONS] = {
+	_X_, _X_, _X_, _X_, _X_, _X_, _X_, _X_, _X_, _X_,
+	_X_, _X_, _X_, _X_, _X_, _X_, _X_, _X_, _X_, _X_,
+};
+
+
+/*
+ * d_insert:
+ *	Insert a function in the daemon list.
+ */
+struct delayed_action *
+d_insert(func, arg, type, time)
+int arg, type, time, (*func)();
+{
+	reg struct delayed_action *dev;
+
+	if (demoncnt < MAXDAEMONS) {
+		dev = &d_list[demoncnt];
+		dev->d_type = type;
+		dev->d_time = time;
+		dev->d_func = func;
+		dev->d_arg = arg;
+		demoncnt += 1;
+		return dev;
+	}
+	return NULL;
+}
+
+d_delete(wire)
+struct delayed_action *wire;
+{
+	reg struct delayed_action *d1, *d2;
+
+	for (d1 = d_list; d1 < &d_list[demoncnt]; d1++) {
+		if (wire == d1) {
+			for (d2 = d1 + 1; d2 < &d_list[demoncnt]; d2++)
+				*d1++ = *d2;
+			demoncnt -= 1;
+			d1 = &d_list[demoncnt];
+			d1->d_type = EMPTY;
+			d1->d_func = EMPTY;
+			return;
+		}
+	}
+}
+/*
+ * find_slot:
+ *	Find a particular slot in the table
+ */
+struct delayed_action *
+find_slot(func)
+int (*func)();
+{
+	reg struct delayed_action *dev;
+
+	for (dev = d_list; dev < &d_list[demoncnt]; dev++)
+		if (dev->d_type != EMPTY && func == dev->d_func)
+			return dev;
+	return NULL;
+}
+
+/*
+ * daemon:
+ *	Start a daemon, takes a function.
+ */
+daemon(func, arg, type)
+int arg, type, (*func)();
+{
+	d_insert(func, arg, type, DAEMON);
+}
+
+/*
+ * do_daemons:
+ *	Run all the daemons that are active with the current
+ *	flag, passing the argument to the function.
+ */
+do_daemons(flag)
+int flag;
+{
+	reg struct delayed_action *dev;
+
+	for (dev = d_list; dev < &d_list[demoncnt]; dev++)
+		if (dev->d_type == flag && dev->d_time == DAEMON)
+			(*dev->d_func)(dev->d_arg);
+}
+
+/*
+ * fuse:
+ *	Start a fuse to go off in a certain number of turns
+ */
+fuse(func, arg, time)
+int (*func)(), arg, time;
+{
+	d_insert(func, arg, AFTER, time);
+}
+
+/*
+ * lengthen:
+ *	Increase the time until a fuse goes off
+ */
+lengthen(func, xtime)
+int (*func)(), xtime;
+{
+	reg struct delayed_action *wire;
+
+	for (wire = d_list; wire < &d_list[demoncnt]; wire++)
+		if (wire->d_type != EMPTY && func == wire->d_func)
+			wire->d_time += xtime;
+}
+
+/*
+ * extinguish:
+ *	Put out a fuse. Find all such fuses and kill them.
+ */
+extinguish(func)
+int (*func)();
+{
+	reg struct delayed_action *dev;
+
+	for (dev = d_list; dev < &d_list[demoncnt]; dev++)
+		if (dev->d_type != EMPTY && func == dev->d_func)
+			d_delete(dev);
+}
+
+/*
+ * do_fuses:
+ *	Decrement counters and start needed fuses
+ */
+do_fuses()
+{
+	reg struct delayed_action *dev;
+
+	for (dev = d_list; dev < &d_list[demoncnt]; dev++) {
+		if (dev->d_type == AFTER && dev->d_time > DAEMON) {
+			if (--dev->d_time == 0) {
+				(*dev->d_func)(dev->d_arg);
+				d_delete(dev);
+			}
+		}
+	}
+}
+
+
+/*
+ * activity:
+ *	Show wizard number of demaons and memory blocks used
+ */
+activity()
+{
+	msg("Daemons = %d : Memory Items = %d : Memory Used = %d",
+	    demoncnt,total,sbrk(0));
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/srogue/daemons.c	Thu Nov 25 12:21:41 2010 +0000
@@ -0,0 +1,254 @@
+/*
+ * All the daemon and fuse functions are in here
+ *
+ * @(#)daemons.c	9.0	(rdk)	 7/17/84
+ *
+ * Super-Rogue
+ * Copyright (C) 1984 Robert D. Kindelberger
+ * All rights reserved.
+ *
+ * Based on "Rogue: Exploring the Dungeons of Doom"
+ * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
+ * All rights reserved.
+ *
+ * See the file LICENSE.TXT for full copyright and licensing information.
+ */
+
+#include "rogue.h"
+#include "rogue.ext"
+
+int between = 0;
+
+/*
+ * doctor:
+ *	A healing daemon that restores hit points after rest
+ */
+doctor(fromfuse)
+int fromfuse;
+{
+	reg int *thp, lv, ohp, ccon;
+
+	lv = him->s_lvl;
+	thp = &him->s_hpt;
+	ohp = *thp;
+	quiet += 1;
+
+	ccon = him->s_ef.a_con;
+	if (ccon > 16 && !isfight)
+		*thp += rnd(ccon - 15);
+	if (lv < 8) {
+		if (quiet > 20 - lv * 2)
+			*thp += 1;
+	}
+	else {
+		if (quiet >= 3)
+			*thp += rnd(lv - 7) + 1;
+	}
+	if (isring(LEFT, R_REGEN))
+		*thp += 1;
+	if (isring(RIGHT, R_REGEN))
+		*thp += 1;
+	if (pl_on(ISREGEN))
+		*thp += 1;
+	if (ohp != *thp) {
+		nochange = FALSE;
+		if (*thp > him->s_maxhp)
+			*thp = him->s_maxhp;
+		quiet = 0;
+	}
+}
+
+
+/*
+ * Swander:
+ *	Called when it is time to start rolling for wandering monsters
+ */
+swander(fromfuse)
+int fromfuse;
+{
+	daemon(rollwand, TRUE, BEFORE);
+}
+
+
+/*
+ * rollwand:
+ *	Called to roll to see if a wandering monster starts up
+ */
+rollwand(fromfuse)
+int fromfuse;
+{
+
+	if (++between >= 4) {
+		if (roll(1, 6) == 4) {
+			if (levtype != POSTLEV)		/* no monsters for posts */
+				wanderer();
+			extinguish(rollwand);
+			fuse(swander, TRUE, WANDERTIME);
+		}
+		between = 0;
+	}
+}
+
+
+/*
+ * unconfuse:
+ *	Release the poor player from his confusion
+ */
+unconfuse(fromfuse)
+int fromfuse;
+{
+	if (pl_on(ISHUH))
+		msg("You feel less confused now.");
+	player.t_flags &= ~ISHUH;
+}
+
+/*
+ * unsee:
+ *	He lost his see invisible power
+ */
+unsee(fromfuse)
+int fromfuse;
+{
+	player.t_flags &= ~CANSEE;
+}
+
+/*
+ * sight:
+ *	He gets his sight back
+ */
+sight(fromfuse)
+int fromfuse;
+{
+	if (pl_on(ISBLIND))
+		msg("The veil of darkness lifts.");
+	player.t_flags &= ~ISBLIND;
+	light(&hero);
+}
+
+/*
+ * nohaste:
+ *	End the hasting
+ */
+nohaste(fromfuse)
+int fromfuse;
+{
+	if (pl_on(ISHASTE))
+		msg("You feel yourself slowing down.");
+	player.t_flags &= ~ISHASTE;
+}
+
+
+/*
+ * stomach:
+ *	Digest the hero's food
+ */
+stomach(fromfuse)
+int fromfuse;
+{
+	reg int oldfood, old_hunger;
+
+	old_hunger = hungry_state;
+	if (food_left <= 0) {		 /* the hero is fainting */
+		if (--food_left == -150) {
+			msg("Your stomach writhes with hunger pains.");
+		}
+		else if (food_left < -350) {
+			msg("You starve to death !!");
+			msg(" ");
+			death(K_STARVE);
+		}
+		if (player.t_nocmd > 0 || rnd(100) > 20)
+			return;
+		player.t_nocmd = rnd(8)+4;
+		msg("You faint.");
+		running = FALSE;
+		count = 0;
+		hungry_state = F_FAINT;
+	}
+	else {
+		oldfood = food_left;
+		food_left -= ringfood + foodlev - amulet;
+		if (player.t_nocmd > 0)		/* wait till he can move */
+			return;
+		if (food_left < WEAKTIME && oldfood >= WEAKTIME) {
+			msg("You are starting to feel weak.");
+			hungry_state = F_WEAK;
+		}
+		else if(food_left < HUNGTIME && oldfood >= HUNGTIME) {
+			msg("Getting hungry.");
+			hungry_state = F_HUNGRY;
+		}
+	}
+	if (old_hunger != hungry_state)
+	    updpack();				/* new pack weight */
+	wghtchk(FALSE);
+}
+
+/*
+ * noteth:
+ *	Hero is no longer etherereal
+ */
+noteth(fromfuse)
+int fromfuse;
+{
+	int ch;
+
+	if (pl_on(ISETHER)) {
+		msg("You begin to feel more corporeal.");
+		ch = player.t_oldch;
+		if (dead_end(ch)) {
+			msg("You materialize in %s.",identify(ch));
+			msg(" ");
+			death(K_STONE);	/* can't materialize in walls */
+		}
+	}
+	player.t_flags &= ~ISETHER;
+}
+
+/*
+ * sapem:
+ *	Sap the hero's life away
+ */
+sapem(fromfuse)
+int fromfuse;
+{
+	chg_abil(rnd(4) + 1, -1, TRUE);
+	fuse(sapem, TRUE, 150);
+	nochange = FALSE;
+}
+
+/*
+ * notslow:
+ *	Restore the hero's normal speed
+ */
+notslow(fromfuse)
+int fromfuse;
+{
+	if (pl_on(ISSLOW))
+		msg("You no longer feel hindered.");
+	player.t_flags &= ~ISSLOW;
+}
+
+/*
+ * notregen:
+ *	Hero is no longer regenerative
+ */
+notregen(fromfuse)
+int fromfuse;
+{
+	if (pl_on(ISREGEN))
+		msg("You no longer feel bolstered.");
+	player.t_flags &= ~ISREGEN;
+}
+
+/*
+ * notinvinc:
+ *	Hero not invincible any more
+ */
+notinvinc(fromfuse)
+int fromfuse;
+{
+	if (pl_on(ISINVINC))
+		msg("You no longer feel invincible.");
+	player.t_flags &= ~ISINVINC;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/srogue/disply.c	Thu Nov 25 12:21:41 2010 +0000
@@ -0,0 +1,199 @@
+/*
+ * various display routines and flag checking functions
+ *
+ * @(#)disply.c		9.0	(rdk)	 7/17/84
+ *
+ * Super-Rogue
+ * Copyright (C) 1984 Robert D. Kindelberger
+ * All rights reserved.
+ *
+ * See the file LICENSE.TXT for full copyright and licensing information.
+ */
+
+#include "rogue.h"
+#include <ctype.h>
+#include "rogue.ext"
+
+/*
+ * displevl:
+ *	Display detailed level for wizard and scroll
+ */
+displevl()
+{
+	reg char ch, mch;
+	reg int i,j;
+	reg struct room *rp;
+
+	for (rp = rooms; rp < &rooms[MAXROOMS]; rp++)
+		rp->r_flags &= ~ISDARK;
+
+	for (i = 0; i < LINES - 2; i++) {
+		for (j = 0; j < COLS - 1; j++) {
+			ch = mvinch(i,j);
+			if (isatrap(ch)) {
+				struct trap *what;
+
+				what = trap_at(i, j);
+				if (what != NULL)
+					what->tr_flags |= ISFOUND;
+			}
+			else if (ch == SECRETDOOR) {
+				ch = DOOR;
+				mvaddch(i, j, ch);
+			}
+			else if (illeg_ch(ch)) {
+				ch = FLOOR;
+				mvaddch(i, j, ch);
+			}
+			if (mvwinch(mw, i, j) != ' ') {
+				struct linked_list *what;
+				struct thing *it;
+
+				what = find_mons(i, j);
+				if (what == NULL) {
+					ch = FLOOR;
+					mvaddch(i, j, ch);
+				}
+				else {
+					it = THINGPTR(what);
+					it->t_oldch = ch;
+				}
+			}
+			mch = mvwinch(cw, i, j);
+			if (isalpha(mch))
+				ch = mch;
+			mvwaddch(cw, i, j, ch);
+		}
+	}
+	nochange = FALSE;	/* display status again */
+	draw(cw);
+}
+
+/*
+ * dispmons:
+ *	Show monsters for wizard and potion
+ */
+dispmons()
+{
+	reg int ch, y, x;
+	reg struct thing *it;
+	reg struct linked_list *item;
+
+	for (item = mlist; item != NULL; item = next(item)) {
+		it = THINGPTR(item);
+		y = it->t_pos.y;
+		x = it->t_pos.x;
+		mvwaddch(cw, y, x, it->t_type);
+		it->t_flags |= ISFOUND;
+		if (it->t_type == 'M')			/* if a mimic */
+			it->t_disguise = 'M';		/* give it away */
+	}
+	draw(cw);
+}
+
+/*
+ * winat:
+ *	Get whatever character is at a location on the screen
+ */
+winat(y, x)
+int x, y;
+{
+	reg char ch;
+
+	if (mvwinch(mw,y,x) == ' ')
+		ch = mvinch(y, x);			/* non-monsters */
+	else
+		ch = winch(mw);				/* monsters */
+	return ch;
+}
+
+/*
+ * cordok:
+ *	Returns TRUE if coordinate is on usable screen
+ */
+cordok(y, x)
+int y, x;
+{
+	if (x < 0 || y < 0 || x >= COLS || y >= LINES - 1)
+		return FALSE;
+	return TRUE;
+}
+
+/*
+ * pl_on:
+ *	Returns TRUE if the player's flag is set
+ */
+pl_on(what)
+long what;
+{
+	return (player.t_flags & what);
+}
+
+
+/*
+ * pl_off:
+ *	Returns TRUE when player's flag is reset
+ */
+pl_off(what)
+long what;
+{
+	return (!(player.t_flags & what));
+}
+
+
+/*
+ * o_on:
+ *	Returns TRUE in the objects flag is set
+ */
+o_on(what,bit)
+struct object *what;
+long bit;
+{
+	reg int flag;
+
+	flag = FALSE;
+	if (what != NULL)
+		flag = (what->o_flags & bit);
+	return flag;
+}
+
+
+/*
+ * o_off:
+ *	Returns TRUE is the objects flag is reset
+ */
+o_off(what,bit)
+struct object *what;
+long bit;
+{
+	reg int flag;
+
+	flag = FALSE;
+	if (what != NULL)
+		flag = !(what->o_flags & bit);
+	return flag;
+}
+
+
+/*
+ * setoflg:
+ *	Set the specified flag for the object
+ */
+setoflg(what,bit)
+struct object *what;
+long bit;
+{
+	what->o_flags |= bit;
+}
+
+
+/*
+ * resoflg:
+ *	Reset the specified flag for the object
+ */
+resoflg(what,bit)
+struct object *what;
+long bit;
+{
+	what->o_flags &= ~bit;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/srogue/encumb.c	Thu Nov 25 12:21:41 2010 +0000
@@ -0,0 +1,237 @@
+/*
+ * Stuff to do with encumberence
+ *
+ * @(#)encumb.c		9.0	(rdk)	 7/17/84
+ *
+ * Super-Rogue
+ * Copyright (C) 1984 Robert D. Kindelberger
+ * All rights reserved.
+ *
+ * See the file LICENSE.TXT for full copyright and licensing information.
+ */
+
+#include "rogue.h"
+#include "rogue.ext"
+
+/*
+ * updpack:
+ *	Update his pack weight and adjust fooduse accordingly
+ */
+updpack()
+{
+	reg int topcarry, curcarry;
+
+	him->s_carry = totalenc();			/* get total encumb */
+	curcarry = packweight();			/* get pack weight */
+	topcarry = him->s_carry / 5;		/* 20% of total carry */
+	if (curcarry > 4 * topcarry) {
+		if (rnd(100) < 80)
+			foodlev = 3;				/* > 80% of pack */
+	}
+	else if (curcarry > 3 * topcarry) {
+		if (rnd(100) < 60)
+			foodlev = 2;				/* > 60% of pack */
+	}
+	else
+		foodlev = 1;					/* <= 60% of pack */
+	him->s_pack = curcarry;				/* update pack weight */
+	packvol = pack_vol();				/* update pack volume */
+	nochange = FALSE;					/* also change display */
+}
+
+
+/*
+ * packweight:
+ *	Get the total weight of the hero's pack
+ */
+packweight()
+{
+	reg struct object *obj;
+	reg struct linked_list *pc;
+	reg int weight, i;
+
+	weight = 0;
+	for (pc = pack ; pc != NULL ; pc = next(pc)) {
+		obj = OBJPTR(pc);
+		weight += itemweight(obj) * obj->o_count;
+	}
+	if (weight < 0)		/* in case of amulet */
+		 weight = 0;
+	for (i = LEFT; i <= RIGHT; i += 1) {
+		obj = cur_ring[i];
+		if (obj != NULL) {
+			if (obj->o_type == R_HEAVY && o_off(obj, ISBLESS))
+				weight += weight / 4;
+		}
+	}
+	return weight;
+}
+
+
+/*
+ * itemweight:
+ *	Get the weight of an object
+ */
+itemweight(wh)
+struct object *wh;
+{
+	reg int weight;
+
+	weight = wh->o_weight;		/* get base weight */
+	switch (wh->o_type) {
+		case ARMOR:
+			if ((armors[wh->o_which].a_class - wh->o_ac) > 0)
+				weight /= 2;
+		when WEAPON:
+			if ((wh->o_hplus + wh->o_dplus) > 0)
+				weight /= 2;
+	}
+	if (o_on(wh,ISCURSED))
+		weight += weight / 5;	/* 20% more for cursed */
+	if (o_on(wh, ISBLESS))
+		weight -= weight / 5;	/* 20% less for blessed */
+	return weight;
+}
+
+/*
+ * pack_vol:
+ *	Get the total volume of the hero's pack
+ */
+pack_vol()
+{
+	reg struct object *obj;
+	reg struct linked_list *pc;
+	reg int volume;
+
+	volume = 0;
+	for (pc = pack ; pc != NULL ; pc = next(pc)) {
+		obj = OBJPTR(pc);
+		volume += itemvol(obj);
+	}
+	return volume;
+}
+
+/*
+ * itemvol:
+ *	Get the volume of an object
+ */
+itemvol(wh)
+struct object *wh;
+{
+	reg int volume, what, extra;
+
+	extra = 0;
+	what = getindex(wh->o_type);
+	switch (wh->o_type) {
+		case ARMOR:		extra = armors[wh->o_which].a_vol;
+		when WEAPON:	extra = weaps[wh->o_which].w_vol;
+		when STICK:		if (strcmp(ws_stuff[wh->o_which].ws_type,"staff") == 0)
+							extra = V_WS_STAFF;
+						else
+							extra = V_WS_WAND;
+	}
+	volume = thnginfo[what].mf_vol + extra;
+	volume *= wh->o_count;
+	return volume;
+}
+
+/*
+ * playenc:
+ *	Get hero's carrying ability above norm
+ */
+playenc()
+{
+	reg estr = him->s_ef.a_str;
+	if (estr >= 24)
+		return 3000;
+	switch(him->s_ef.a_str) {
+		case 23: return 2000;
+		case 22: return 1500;
+		case 21: return 1250;
+		case 20: return 1100;
+		case 19: return 1000;
+		case 18: return 700;
+		case 17: return 500;
+		case 16: return 350;
+		case 15:
+		case 14: return 200;
+		case 13:
+		case 12: return 100;
+		case 11:
+		case 10:
+		case  9:
+		case  8: return 0;
+		case  7:
+		case  6: return -150;
+		case  5:
+		case  4: return -250;
+	}
+	return -350;
+}
+
+
+/*
+ * totalenc:
+ *	Get total weight that the hero can carry
+ */
+totalenc()
+{
+	reg int wtotal;
+
+	wtotal = NORMENCB + playenc();
+	switch(hungry_state) {
+		case F_OKAY:
+		case F_HUNGRY:	;						/* no change */
+		when F_WEAK:	wtotal -= wtotal / 10;	/* 10% off weak */
+		when F_FAINT:	wtotal /= 2;			/* 50% off faint */
+	}
+	return wtotal;
+}
+
+/*
+ * whgtchk:
+ *	See if the hero can carry his pack
+ */
+wghtchk(fromfuse)
+int fromfuse;
+{
+	reg int dropchk, err = TRUE;
+	reg char ch;
+
+	inwhgt = TRUE;
+	if (him->s_pack > him->s_carry) {
+		ch = player.t_oldch;
+		extinguish(wghtchk);
+		if ((ch != FLOOR && ch != PASSAGE) || isfight) {
+			fuse(wghtchk, TRUE, 1);
+			inwhgt = FALSE;
+			return;
+		}
+		msg("Your pack is too heavy for you.");
+		do {
+			dropchk = drop(NULL);
+			if (dropchk == SOMTHERE)
+				err = FALSE;
+			else if (dropchk == FALSE) {
+				mpos = 0;
+				msg("You must drop something");
+			}
+			if (dropchk == TRUE)
+				err = FALSE;
+		} while(err);
+	}
+	inwhgt = FALSE;
+}
+
+
+/*
+ * hitweight:
+ *	Gets the fighting ability according to current weight
+ * 	This returns a  +1 hit for light pack weight
+ * 			 0 hit for medium pack weight
+ *			-1 hit for heavy pack weight
+ */
+hitweight()
+{
+	return(2 - foodlev);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/srogue/fight.c	Thu Nov 25 12:21:41 2010 +0000
@@ -0,0 +1,711 @@
+/*
+ * All the fighting gets done here
+ *
+ * @(#)fight.c	9.0	(rdk)	 7/17/84
+ *
+ * Super-Rogue
+ * Copyright (C) 1984 Robert D. Kindelberger
+ * All rights reserved.
+ *
+ * Based on "Rogue: Exploring the Dungeons of Doom"
+ * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
+ * All rights reserved.
+ *
+ * See the file LICENSE.TXT for full copyright and licensing information.
+ */
+
+#include <ctype.h>
+#include "rogue.h"
+#include "rogue.ext"
+
+
+/*
+ * fight:
+ *	The player attacks the monster.
+ */
+fight(mp, weap, thrown)
+struct coord *mp;
+struct object *weap;
+bool thrown;
+{
+
+	reg struct thing *tp;
+	reg struct stats *st;
+	reg struct linked_list *item;
+	bool did_hit = TRUE;
+
+	if (pl_on(ISETHER))			/* cant fight when ethereal */
+		return 0;
+
+	if ((item = find_mons(mp->y, mp->x)) == NULL) {
+		mvaddch(mp->y, mp->x, FLOOR);
+		mvwaddch(mw, mp->y, mp->x, ' ');
+		look(FALSE);
+		msg("That monster must have been an illusion.");
+		return 0;
+	}
+	tp = THINGPTR(item);
+	st = &tp->t_stats;
+	/*
+	 * Since we are fighting, things are not quiet so
+	 * no healing takes place.
+	 */
+	quiet = 0;
+	isfight = TRUE;
+	runto(mp, &hero);
+	/*
+	 * Let him know it was really a mimic (if it was one).
+	 */
+	if(tp->t_type == 'M' && tp->t_disguise != 'M' && pl_off(ISBLIND)) {
+		msg("Wait! That's a mimic!");
+		tp->t_disguise = 'M';
+		did_hit = thrown;
+	}
+	if (did_hit) {
+		reg char *mname;
+
+		did_hit = FALSE;
+		if (pl_on(ISBLIND))
+			mname = "it";
+		else
+			mname = monsters[tp->t_indx].m_name;
+		/*
+		 * If the hero can see the invisibles, then
+		 * make it easier to hit.
+		 */
+		if (pl_on(CANSEE) && on(*tp, ISINVIS) && off(*tp, WASHIT)) {
+			tp->t_flags |= WASHIT;
+			st->s_arm += 3;
+		}
+		if (roll_em(him, st, weap, thrown)) {
+			did_hit = TRUE;
+			if (thrown)
+				thunk(weap, mname);
+			else
+				hit(NULL);
+			if (pl_on(CANHUH)) {
+				msg("Your hands stop glowing red");
+				msg("The %s appears confused.", mname);
+				tp->t_flags |= ISHUH;
+				player.t_flags &= ~CANHUH;
+				/*
+				 * If our hero was stuck by a bone devil,
+				 * release him now because the devil is
+				 * confused.
+				 */
+				if (pl_on(ISHELD))
+					unhold(tp->t_type);
+			}
+			if (st->s_hpt <= 0)
+				killed(item, TRUE);
+			else if (monhurt(tp) && off(*tp, ISWOUND)) {
+				if (levtype != MAZELEV && tp->t_room != NULL &&
+				  !rf_on(tp->t_room, ISTREAS)) {
+					tp->t_flags |= ISWOUND;
+					msg("You wounded %s.",prname(mname,FALSE));
+					unhold(tp->t_type);
+				}
+			}
+		}
+		else {
+			if (thrown)
+				bounce(weap, mname);
+			else
+				miss(NULL);
+		}
+	}
+	count = 0;
+	return did_hit;
+}
+
+
+/*
+ * attack:
+ *	The monster attacks the player
+ */
+attack(mp)
+struct thing *mp;
+{
+	reg char *mname;
+
+	if (pl_on(ISETHER))		/* ethereal players cant be hit */
+		return(0);
+	if (mp->t_flags & ISPARA)	/* paralyzed monsters */
+		return(0);
+	running = FALSE;
+	quiet = 0;
+	isfight = TRUE;
+	if (mp->t_type == 'M' && pl_off(ISBLIND))
+		mp->t_disguise = 'M';
+	if (pl_on(ISBLIND))
+		mname = "it";
+	else
+		mname = monsters[mp->t_indx].m_name;
+	if (roll_em(&mp->t_stats, him, NULL, FALSE)) {
+		if (pl_on(ISINVINC)) {
+			msg("%s does not harm you.",prname(mname,TRUE));
+		}
+		else {
+			nochange = FALSE;
+			if (mp->t_type != 'E')
+				hit(mname);
+			if (him->s_hpt <= 0)
+				death(mp->t_indx);
+			if (off(*mp, ISCANC))
+				switch (mp->t_type) {
+				case 'R':
+					if (hurt_armor(cur_armor)) {
+						msg("Your armor weakens.");
+						cur_armor->o_ac++;
+					}
+				when 'E':
+				/*
+				 * The gaze of the floating eye hypnotizes you
+				 */
+					if (pl_off(ISBLIND) && player.t_nocmd <= 0) {
+						player.t_nocmd = rnd(16) + 25;
+						msg("You are transfixed.");
+					}
+				when 'Q':
+					if (!save(VS_POISON) && !iswearing(R_SUSAB)) {
+						if (him->s_ef.a_dex > MINABIL) {
+							chg_abil(DEX, -1, TRUE);
+							msg("You feel less agile.");
+						}
+					}
+				when 'A':
+					if (!save(VS_POISON) && herostr() > MINABIL) {
+						if (!iswearing(R_SUSTSTR) && !iswearing(R_SUSAB)) {
+							if (levcount > 0) {
+								chg_abil(STR, -1, TRUE);
+								msg("A sting has weakened you");
+							}
+						}
+						else
+							msg("Sting has no effect.");
+					}
+				when 'W':
+					if (rnd(100) < 15 && !iswearing(R_SUSAB)) {
+						if (him->s_exp <= 0)
+							death(mp->t_indx);
+						msg("You suddenly feel weaker.");
+						if (--him->s_lvl == 0) {
+							him->s_exp = 0;
+							him->s_lvl = 1;
+						}
+						else
+							him->s_exp = e_levels[him->s_lvl - 1] + 1;
+						chg_hpt(-roll(1,10),TRUE,mp->t_indx);
+					}
+				when 'F':
+					player.t_flags |= ISHELD;
+					sprintf(monsters[midx('F')].m_stats.s_dmg,"%dd1",++fung_hit);
+				when 'L': {
+					long lastpurse;
+					struct linked_list *lep;
+
+					lastpurse = purse;
+					purse -= GOLDCALC;
+					if (!save(VS_MAGIC))
+						purse -= GOLDCALC + GOLDCALC + GOLDCALC + GOLDCALC;
+					if (purse < 0)
+						purse = 0;
+					if (purse != lastpurse)
+						msg("Your purse feels lighter.");
+					lep = find_mons(mp->t_pos.y,mp->t_pos.x);
+					if (lep != NULL)
+					{
+						remove_monster(&mp->t_pos, lep);
+						mp = NULL;
+					}
+				}
+				when 'N': {
+					struct linked_list *steal, *list;
+					struct object *sobj;
+					int stworth = 0, wo;
+
+					/*
+					 * Nymph's steal a magic item, look through the pack
+					 * and pick out one we like, namely the object worth
+					 * the most bucks.
+					 */
+					steal = NULL;
+					for (list = pack; list != NULL; list = next(list)) {
+						wo = get_worth(OBJPTR(list));
+						if (wo > stworth) {
+							stworth = wo;
+							steal = list;
+						}
+					}
+					if (steal != NULL) {
+						sobj = OBJPTR(steal);
+						if (o_off(sobj, ISPROT)) {
+							struct linked_list *nym;
+
+							nym = find_mons(mp->t_pos.y, mp->t_pos.x);
+							if (nym != NULL)
+							{
+								remove_monster(&mp->t_pos, nym);
+								mp = NULL;
+							}
+							msg("She stole %s!", inv_name(sobj, TRUE));
+							detach(pack, steal);
+							discard(steal);
+							cur_null(sobj);
+							updpack();
+						}
+					}
+				}
+				when 'c':
+					if (!save(VS_PETRIFICATION)) {
+						msg("Your body begins to solidify.");
+						msg("You are turned to stone !!! --More--");
+						wait_for(cw, ' ');
+						death(mp->t_indx);
+					}
+				when 'd':
+					if (rnd(100) < 50 && !(mp->t_flags & ISHUH))
+						player.t_flags |= ISHELD;
+					if (!save(VS_POISON)) {
+						if (iswearing(R_SUSAB) || iswearing(R_SUSTSTR))
+							msg("Sting has no effect.");
+						else {
+							int fewer, ostr;
+
+							fewer = roll(1,4);
+							ostr = herostr();
+							chg_abil(STR,-fewer,TRUE);
+							if (herostr() < ostr) {
+								fewer = ostr - herostr();
+								fuse(rchg_str, fewer - 1, 10);
+							}
+							msg("You feel weaker now.");
+						}
+					}
+				when 'g':
+					if (!save(VS_BREATH) && !iswearing(R_BREATH)) {
+						msg("You feel singed.");
+						chg_hpt(-roll(1,8),FALSE,mp->t_indx);
+					}
+				when 'h':
+					if (!save(VS_BREATH) && !iswearing(R_BREATH)) {
+						msg("You are seared.");
+						chg_hpt(-roll(1,4),FALSE,mp->t_indx);
+					}
+				when 'p':
+					if (!save(VS_POISON) && herostr() > MINABIL) {
+						if (!iswearing(R_SUSTSTR) && !iswearing(R_SUSAB)) {
+							msg("You are gnawed.");
+							chg_abil(STR,-1,TRUE);
+						}
+					}
+				when 'u':
+					if (!save(VS_POISON) && herostr() > MINABIL) {
+						if (!iswearing(R_SUSTSTR) && !iswearing(R_SUSAB)) {
+							msg("You are bitten.");
+							chg_abil(STR, -1, TRUE);
+							fuse(rchg_str, 1, roll(5,10));
+				 		}
+					}
+				when 'w':
+					if (!save(VS_POISON) && !iswearing(R_SUSAB)) {
+						msg("You feel devitalized.");
+						chg_hpt(-1,TRUE,mp->t_indx);
+					}
+				when 'i':
+					if (!save(VS_PARALYZATION) && !iswearing(R_SUSAB)) {
+						if (pl_on(ISSLOW))
+							lengthen(notslow,roll(3,10));
+						else {
+							msg("You feel impaired.");
+							player.t_flags |= ISSLOW;
+							fuse(notslow,TRUE,roll(5,10));
+						}
+					}
+				otherwise:
+					break;
+			}
+		}
+	}
+	else if (mp->t_type != 'E') {
+		if (mp->t_type == 'F') {
+			him->s_hpt -= fung_hit;
+			if (him->s_hpt <= 0)
+				death(mp->t_indx);
+		}
+		miss(mname);
+	}
+	flushinp();					/* flush type ahead */
+	count = 0;
+
+	if (mp == NULL)
+		return(-1);
+	else
+		return(0);
+}
+
+
+/*
+ * swing:
+ *	Returns true if the swing hits
+ */
+swing(at_lvl, op_arm, wplus)
+int at_lvl, op_arm, wplus;
+{
+	reg int res = rnd(20)+1;
+	reg int need = (21 - at_lvl) - op_arm;
+
+	return (res + wplus >= need);
+}
+
+
+/*
+ * check_level:
+ *	Check to see if the guy has gone up a level.
+ */
+check_level()
+{
+	reg int lev, add, dif;
+
+	for (lev = 0; e_levels[lev] != 0; lev++)
+	if (e_levels[lev] > him->s_exp)
+		break;
+	lev += 1;
+	if (lev > him->s_lvl) {
+		dif = lev - him->s_lvl;
+		add = roll(dif, 10) + (dif * getpcon(him));
+		him->s_maxhp += add;
+		if ((him->s_hpt += add) > him->s_maxhp)
+			him->s_hpt = him->s_maxhp;
+		msg("Welcome to level %d", lev);
+	}
+	him->s_lvl = lev;
+}
+
+
+/*
+ * roll_em:
+ *	Roll several attacks
+ */
+roll_em(att, def, weap, hurl)
+struct stats *att, *def;
+struct object *weap;
+bool hurl;
+{
+	reg char *cp;
+	reg int ndice, nsides, def_arm, prop_hplus, prop_dplus;
+	reg bool did_hit = FALSE;
+	char *mindex();
+
+	prop_hplus = prop_dplus = 0;
+	if (weap == NULL) {
+		cp = att->s_dmg;
+	}
+	else if (hurl) {
+		if (o_on(weap,ISMISL) && cur_weapon != NULL &&
+		  cur_weapon->o_which == weap->o_launch) {
+			cp = weap->o_hurldmg;
+			prop_hplus = cur_weapon->o_hplus;
+			prop_dplus = cur_weapon->o_dplus;
+		}
+		else
+			cp = (o_on(weap,ISMISL) ? weap->o_damage : weap->o_hurldmg);
+	}
+	else {
+		cp = weap->o_damage;
+		/*
+		 * Drain a staff of striking
+		 */
+		if (weap->o_type == STICK && weap->o_which == WS_HIT
+		  && weap->o_charges == 0) {
+			strcpy(weap->o_damage, "0d0");
+			weap->o_hplus = weap->o_dplus = 0;
+		}
+    }
+	while(1) {
+		int damage;
+		int hplus = prop_hplus + (weap == NULL ? 0 : weap->o_hplus);
+		int dplus = prop_dplus + (weap == NULL ? 0 : weap->o_dplus);
+
+		if (att == him && weap == cur_weapon) {
+			if (isring(LEFT, R_ADDDAM))
+				dplus += cur_ring[LEFT]->o_ac;
+			else if (isring(LEFT, R_ADDHIT))
+				hplus += cur_ring[LEFT]->o_ac;
+			if (isring(RIGHT, R_ADDDAM))
+				dplus += cur_ring[RIGHT]->o_ac;
+			else if (isring(RIGHT, R_ADDHIT))
+				hplus += cur_ring[RIGHT]->o_ac;
+		}
+		ndice = atoi(cp);
+		if ((cp = mindex(cp, 'd')) == NULL)
+			break;
+		nsides = atoi(++cp);
+
+		if (def == him) {			/* defender is hero */
+			if (cur_armor != NULL)
+				def_arm = cur_armor->o_ac;
+			else
+				def_arm = def->s_arm;
+			if (isring(LEFT, R_PROTECT))
+				def_arm -= cur_ring[LEFT]->o_ac;
+			if (isring(RIGHT, R_PROTECT))
+				def_arm -= cur_ring[RIGHT]->o_ac;
+		}
+		else						/* defender is monster */
+			def_arm = def->s_arm;
+		if (hurl)
+			hplus += getpdex(att,TRUE);
+		if (swing(att->s_lvl, def_arm + getpdex(def, FALSE),
+		  hplus + str_plus(att))) {
+			reg int proll;
+
+			proll = roll(ndice, nsides);
+			damage = dplus + proll + add_dam(att);
+			if (pl_off(ISINVINC) || def != him)
+				def->s_hpt -= max(0, damage);
+			did_hit = TRUE;
+		}
+		if ((cp = mindex(cp, '/')) == NULL)
+			break;
+		cp++;
+	}
+	return did_hit;
+}
+
+
+/*
+ * mindex:
+ *	Look for char 'c' in string pointed to by 'cp'
+ */
+char *
+mindex(cp, c)
+char *cp, c;
+{
+	reg int i;
+
+	for (i = 0; i < 3; i++)
+		if (*cp != c)  cp++;
+	if (*cp == c)
+		return cp;
+	else
+		return NULL;
+}
+
+
+/*
+ * prname:
+ *	The print name of a combatant
+ */
+char *
+prname(who, upper)
+char *who;
+bool upper;
+{
+static char tbuf[LINLEN];
+
+	*tbuf = '\0';
+	if (who == 0)
+		strcpy(tbuf, "you"); 
+	else if (pl_on(ISBLIND))
+		strcpy(tbuf, "it");
+	else {
+		strcpy(tbuf, "the ");
+		strcat(tbuf, who);
+	}
+	if (upper)
+		*tbuf = toupper(*tbuf);
+	return tbuf;
+}
+
+/*
+ * hit:
+ *	Print a message to indicate a succesful hit
+ */
+hit(er)
+char *er;
+{
+	msg("%s hit.",prname(er, TRUE));
+}
+
+
+/*
+ * miss:
+ *	Print a message to indicate a poor swing
+ */
+miss(er)
+char *er;
+{
+	msg("%s miss%s.",prname(er, TRUE),(er == 0 ? "":"es"));
+}
+
+
+/*
+ * save_throw:
+ *	See if a creature saves against something
+ */
+save_throw(which, tp)
+int which;
+struct thing *tp;
+{
+	reg int need;
+	reg struct stats *st;
+
+	st = &tp->t_stats;
+	need = 14 + which - (st->s_lvl / 2) - getpwis(st);
+	return (roll(1, 20) >= need);
+}
+
+
+/*
+ * save:
+ *	See if he saves against various nasty things
+ */
+save(which)
+int which;
+{
+	return save_throw(which, &player);
+}
+
+/*
+ * raise_level:
+ *	The guy just magically went up a level.
+ */
+raise_level()
+{
+	him->s_exp = e_levels[him->s_lvl-1] + 1L;
+	check_level();
+}
+
+
+/*
+ * thunk:
+ *	A missile hits a monster
+ */
+thunk(weap, mname)
+struct object *weap;
+char *mname;
+{
+	if (weap->o_type == WEAPON)
+		msg("The %s hits the %s.",w_magic[weap->o_which].mi_name,mname);
+	else
+		msg("You hit the %s.", mname);
+}
+
+
+/*
+ * bounce:
+ *	A missile misses a monster
+ */
+bounce(weap, mname)
+struct object *weap;
+char *mname;
+{
+	if (weap->o_type == WEAPON)
+		msg("The %s misses the %s.", w_magic[weap->o_which].mi_name,mname);
+	else
+		msg("You missed the %s.", mname);
+}
+
+
+/*
+ * remove:
+ *	Remove a monster from the screen
+ */
+remove_monster(mp, item)
+struct coord *mp;
+struct linked_list *item;
+{
+	reg char what;
+
+	mvwaddch(mw, mp->y, mp->x, ' ');
+	if (pl_on(ISBLIND))
+		what = ' ';							/* if blind, then a blank */
+	else
+		what = (THINGPTR(item))->t_oldch;	/* normal char */
+	mvwaddch(cw, mp->y, mp->x, what);
+	detach(mlist, item);
+	discard(item);
+}
+
+
+/*
+ * is_magic:
+ *	Returns true if an object radiates magic
+ */
+is_magic(obj)
+struct object *obj;
+{
+	switch (obj->o_type) {
+		case ARMOR:
+			return obj->o_ac != armors[obj->o_which].a_class;
+		case WEAPON:
+			return obj->o_hplus != 0 || obj->o_dplus != 0;
+		case POTION:
+		case SCROLL:
+		case STICK:
+		case RING:
+		case AMULET:
+			return TRUE;
+	}
+	return FALSE;
+}
+
+
+/*
+ * killed:
+ *	Called to put a monster to death
+ */
+killed(item, pr)
+struct linked_list *item;
+bool pr;
+{
+	reg struct thing *tp;
+	reg struct object *obj;
+	struct linked_list *pitem, *nexti, *itspack;
+	struct coord here;
+	
+	nochange = FALSE;
+	tp = THINGPTR(item);
+	here = tp->t_pos;
+	if (pr) {
+		addmsg("Defeated ");
+		if (pl_on(ISBLIND))
+			msg("it.");
+		else
+			msg("%s.", monsters[tp->t_indx].m_name);
+	}
+	him->s_exp += tp->t_stats.s_exp;
+	isfight = FALSE;
+	check_level();
+	unhold(tp->t_type);					/* free player if held */
+	if (tp->t_type == 'L') {
+		reg struct room *rp;
+
+		rp = roomin(&here);
+		if (rp != NULL) {
+			if (rp->r_goldval!=0 || fallpos(&here, &rp->r_gold, FALSE)) {
+				rp->r_goldval += GOLDCALC;
+				if (!save_throw(VS_MAGIC,tp))
+					rp->r_goldval += GOLDCALC + GOLDCALC + GOLDCALC
+								   + GOLDCALC + GOLDCALC;
+				mvaddch(rp->r_gold.y, rp->r_gold.x, GOLD);
+				if (!rf_on(rp,ISDARK)) {
+					light(&hero);
+					mvwaddch(cw, hero.y, hero.x, PLAYER);
+				}
+			}
+		}
+	}
+	pitem = tp->t_pack;
+	itspack = tp->t_pack;
+	remove_monster(&here, item);
+	while (pitem != NULL) {
+		nexti = next(pitem);
+		obj = OBJPTR(pitem);
+		obj->o_pos = here;
+		detach(itspack, pitem);
+		fall(pitem, FALSE);
+		pitem = nexti;
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/srogue/global.c	Thu Nov 25 12:21:41 2010 +0000
@@ -0,0 +1,446 @@
+/*
+ * global variable declaration
+ *
+ * @(#)global.c	9.0	(rdk)	 7/17/84
+ *
+ * Super-Rogue
+ * Copyright (C) 1984 Robert D. Kindelberger
+ * All rights reserved.
+ *
+ * Based on "Rogue: Exploring the Dungeons of Doom"
+ * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
+ * All rights reserved.
+ *
+ * See the file LICENSE.TXT for full copyright and licensing information.
+ */
+
+#include "rogue.h"
+
+struct room rooms[MAXROOMS];		/* One for each room -- A level */
+struct room *oldrp;					/* Roomin(&oldpos) */
+struct linked_list *mlist = NULL;	/* monsters on this level */
+struct thing player;				/* The rogue */
+struct stats max_stats;				/* The maximum for the player */
+struct linked_list *lvl_obj = NULL;	/* objects on this level */
+struct object *cur_weapon = NULL;	/* Which weapon he is weilding */
+struct object *cur_armor = NULL;	/* the rogue's armor */
+struct object *cur_ring[2];			/* Which rings are being worn */
+struct stats *him;					/* pointer to hero stats */
+struct trap traps[MAXTRAPS];		/* traps on this level */
+
+int playuid;				/* uid of current player */
+int playgid;				/* gid of current player */
+int level = 1;				/* What level rogue is on */
+int levcount = 0;			/* # of active mons this level */
+int levtype = NORMLEV;		/* type of level this is, maze, etc. */
+int trader = 0;				/* no. of purchases */
+int curprice = -1;			/* current price of item */
+int purse = 0;				/* How much gold the rogue has */
+int mpos = 0;				/* Where cursor is on top line */
+int ntraps;					/* # of traps on this level */
+int packvol = 0;			/* volume of things in pack */
+int total = 0;				/* Total dynamic memory bytes */
+int demoncnt = 0;			/* number of active daemons */
+int lastscore = -1;			/* Score before this turn */
+int no_food = 0;			/* # of levels without food */
+int seed;					/* Random number seed */
+int dnum;					/* Dungeon number */
+int count = 0;				/* # of times to repeat cmd */
+int fung_hit = 0;			/* # of time fungi has hit */
+int quiet = 0;				/* # of quiet turns */
+int max_level = 1;			/* Deepest player has gone */
+int food_left = HUNGERTIME;	/* Amount of food stomach */
+int group = NEWGROUP;		/* Current group number */
+int hungry_state = F_OKAY;	/* How hungry is he */
+int foodlev = 1;			/* how fast he eats food */
+int ringfood = 0;			/* rings affect on food consumption */
+char take;					/* Thing the rogue is taking */
+char runch;					/* Direction player is running */
+char curpurch[15];			/* name of item ready to buy */
+
+char prbuf[LINLEN];			/* Buffer for sprintfs */
+char whoami[LINLEN];		/* Name of player */
+char fruit[LINLEN];			/* Favorite fruit */
+char huh[LINLEN];			/* The last message printed */
+char file_name[LINLEN];		/* Save file name */
+char scorefile[LINLEN];		/* place for scorefile */
+char home[LINLEN];			/* User's home directory */
+char outbuf[BUFSIZ];		/* Output buffer for stdout */
+
+char *s_guess[MAXSCROLLS];		/* his guess at what scroll is */
+char *p_guess[MAXPOTIONS];		/* his guess at what potion is */
+char *r_guess[MAXRINGS];		/* his guess at what ring is */
+char *ws_guess[MAXSTICKS];		/* his guess at what wand is */
+
+bool isfight = FALSE;		/* true if player is fighting */
+bool nlmove = FALSE;		/* true when transported to new level */
+bool inpool = FALSE;		/* true if hero standing in pool */
+bool inwhgt = FALSE;		/* true if from wghtchk() */
+bool running = FALSE;		/* True if player is running */
+bool playing = TRUE;		/* True until he quits */
+bool wizard = FALSE;		/* True if he is a wizard */
+bool after = TRUE;			/* True if we want after daemons */
+bool door_stop = FALSE;		/* Stop run when we pass a door */
+bool firstmove = FALSE;		/* First move after door_stop */
+bool waswizard = FALSE;		/* Was a wizard sometime */
+bool amulet = FALSE;		/* He found the amulet */
+bool in_shell = FALSE;		/* True if executing a shell */
+bool nochange = FALSE;		/* true if last stat same as now */
+
+bool s_know[MAXSCROLLS];		/* Does he know about a scroll */
+bool p_know[MAXPOTIONS];		/* Does he know about a potion */
+bool r_know[MAXRINGS];			/* Does he know about a ring */
+bool ws_know[MAXSTICKS];		/* Does he know about a stick */
+
+char spacemsg[] =	{ "-- Press space to continue --" };
+char morestr[] =	{ "-- More --" };
+char retstr[] =		{ "[Press return to continue]" };
+char wizstr[] =		{ "Wizards Password: " };
+char illegal[] =	{ "Illegal command '%s'." };
+char callit[] =		{ "Call it: " };
+char starlist[] =	{ " (* for a list)" };
+
+struct coord oldpos;		/* Pos before last look() call */
+struct coord delta;			/* Change indicated to get_dir() */
+struct coord stairs;		/* where the stairs are put */
+struct coord rndspot = { -1, -1 };	/* for random teleporting */
+
+struct monster *mtlev[MONRANGE];
+
+#define _r {10,10,10,10}	/* real ability (unused) */
+#define _p 0,0,0,0			/* hit points, pack, carry (unused) */
+#define _c 10				/* constitution (unused) */
+
+/*
+ * NAME SHOW CARRY {LEVEL} FLAGS _r {STR DEX WIS _c} EXP LVL ARM _p DMG
+ */
+struct monster monsters[MAXMONS + 1] = {
+{"giant ant",'A',0,{3,12,1},ISMEAN,{_r,{10,16,5,_c},10,2,3,_p,"1d6"}},
+{"bat",'B',0,{1,6,1},ISHUH,{_r,{10,10,10,_c},1,1,3,_p,"1d2"}},
+{"centaur",'C',15,{8,17,1},0,{_r,{16,10,15,_c},15,4,4,_p,"1d6/1d6"}},
+{"red dragon",'D',100,{21,500,0},ISGREED,{_r,{17,10,17,_c},9000,11,-1,_p,"1d8/1d8/3d10"}},
+{"floating eye",'E',0,{2,11,0},0,{_r,{10,10,10,_c},5,1,9,_p,"0d0"}},
+{"violet fungi",'F',0,{15,24,0},ISMEAN|ISSTUCK,{_r,{10,5,3,_c},85,8,2,_p,"000d0"}},
+{"gnome",'G',10,{6,15,1},0,{_r,{10,10,11,_c},8,1,5,_p,"1d6"}},
+{"hobgoblin",'H',0,{1,8,1},ISMEAN,{_r,{10,10,10,_c},3,1,5,_p,"1d8"}},
+{"invisible stalker",'I',0,{16,25,1},ISINVIS|ISHUH,{_r,{10,15,15,_c},120,8,2,_p,"4d4"}},
+{"jackal",'J',0,{1,6,1},ISMEAN,{_r,{10,10,10,_c},2,1,7,_p,"1d2"}},
+{"kobold",'K',0,{1,6,1},ISMEAN,{_r,{10,10,10,_c},1,1,8,_p,"1d4"}},
+{"leprechaun",'L',0,{7,16,0},0,{_r,{10,15,16,_c},10,3,8,_p,"1d1"}},
+{"mimic",'M',30,{19,500,0},0,{_r,{10,10,10,_c},140,8,7,_p,"3d4"}},
+{"nymph",'N',100,{11,20,0},0,{_r,{10,18,18,_c},40,3,9,_p,"0d0"}},
+{"orc",'O',15,{4,13,1},0,{_r,{10,10,10,10},5,1,6,_p,"1d8"}},
+{"purple worm",'P',70,{22,500,0},0,{_r,{18,5,10,_c},7000,15,6,_p,"2d12/2d4"}},
+{"quasit",'Q',30,{10,19,1},ISMEAN,{_r,{10,15,16,_c},35,3,2,_p,"1d2/1d2/1d4"}},
+{"rust monster",'R',0,{9,18,1},ISMEAN,{_r,{10,10,10,_c},25,5,2,_p,"0d0/0d0"}},
+{"snake",'S',0,{1,7,1},ISMEAN,{_r,{10,10,10,_c},3,1,5,_p,"1d3"}},
+{"troll",'T',50,{13,22,0},ISMEAN|ISREGEN,{_r,{10,10,11,_c},55,6,4,_p,"1d8/1d8/2d6"}},
+{"umber hulk",'U',40,{18,500,1},ISMEAN,{_r,{17,10,10,_c},130,8,2,_p,"3d4/3d4/2d5"}},
+{"vampire",'V',20,{20,500,1},ISMEAN|ISREGEN,{_r,{21,16,16,_c},380,8,1,_p,"1d10"}},
+{"wraith",'W',0,{14,23,1},ISMEAN,{_r,{10,10,10,_c},55,5,4,_p,"1d6"}},
+{"xorn",'X',0,{17,26,1},ISMEAN,{_r,{17,6,11,_c},120,7,-2,_p,"1d3/1d3/1d3/4d6"}},
+{"yeti",'Y',30,{12,21,1},ISMEAN,{_r,{10,10,10,_c},50,4,6,_p,"1d6/1d6"}},
+{"zombie",'Z',0,{5,14,1},ISMEAN,{_r,{10,10,10,_c},7,2,8,_p,"1d8"}},
+{"anhkheg",'a',10,{7,16,1},ISMEAN,{_r,{10,15,3,_c},20,3,2,_p,"3d6"}},
+{"giant beetle",'b',0,{9,18,1},ISMEAN,{_r,{10,15,10,_c},30,5,3,_p,"4d4"}},
+{"cockatrice",'c',100,{8,17,0},0,{_r,{10,10,11,_c},200,5,6,_p,"1d3"}},
+{"bone devil",'d',0,{27,500,1},ISMEAN,{_r,{18,10,16,_c},8000,12,-1,_p,"5d4"}},
+{"elasmosaurus",'e',0,{28,500,1},ISMEAN,{_r,{17,5,3,_c},4500,12,7,_p,"4d6"}},
+{"killer frog",'f',0,{3,8,1},ISMEAN,{_r,{10,10,10,_c},4,3,8,_p,"2d3/1d4"}},
+{"green dragon",'g',50,{25,500,1},0,{_r,{18,10,18,_c},7500,10,2,_p,"1d6/1d6/2d10"}},
+{"hell hound",'h',20,{10,19,1},ISMEAN,{_r,{10,15,10,_c},30,5,4,_p,"1d10"}},
+{"imp",'i',20,{2,9,1},ISMEAN|ISREGEN,{_r,{10,14,11,_c},6,2,1,_p,"1d4"}},
+{"jaguar",'j',0,{10,19,0},0,{_r,{10,10,11,_c},25,8,6,_p,"2d3/2d5"}},
+{"koppleganger",'k',20,{8,17,1},ISMEAN,{_r,{10,10,16,_c},35,4,5,_p,"1d12"}},
+{"lonchu",'l',15,{2,9,1},ISMEAN,{_r,{10,4,18,_c},5,2,1,_p,"1d4/1d4"}},
+{"minotaur",'m',0,{12,21,1},ISMEAN,{_r,{10,10,11,_c},40,8,6,_p,"1d3/2d4"}},
+{"neotyugh",'n',10,{14,23,1},ISMEAN,{_r,{10,6,4,_c},50,6,3,_p,"1d8/1d8/2d3"}},
+{"ogre",'o',50,{7,16,1},0,{_r,{20,10,10,_c},15,4,5,_p,"2d6"}},
+{"pseudo dragon",'p',50,{9,18,1},0,{_r,{10,10,16,_c},20,4,2,_p,"2d3/1d6"}},
+{"quellit",'q',85,{30,500,1},0,{_r,{17,10,10,_c},12500,17,0,_p,"2d10/2d6"}},
+{"rhynosphinx",'r',40,{26,500,0},0,{_r,{19,6,18,_c},5000,13,-1,_p,"2d10/2d8"}},
+{"shadow",'s',15,{5,14,1},ISMEAN|ISREGEN|ISINVIS,{_r,{10,17,18,_c},6,3,5,_p,"1d6"}},
+{"titanothere",'t',0,{19,500,0},0,{_r,{17,6,3,_c},750,14,6,_p,"2d8/1d6"}},
+{"ulodyte",'u',10,{2,8,1},ISMEAN,{_r,{10,10,10,_c},3,2,5,_p,"1d3/1d3"}},
+{"vrock",'v',0,{4,13,1},ISMEAN,{_r,{10,10,11,_c},8,3,2,_p,"1d4/1d6"}},
+{"wuccubi",'w',0,{14,23,1},ISMEAN,{_r,{10,10,10,_c},90,6,0,_p,"1d4/1d10"}},
+{"xonoclon",'x',0,{20,500,0},0,{_r,{19,10,4,_c},1750,14,0,_p,"3d8"}},
+{"yeenoghu",'y',10,{15,24,1},ISMEAN,{_r,{17,15,10,_c},250,8,1,_p,"3d6"}},
+{"zemure",'z',0,{1,6,1},ISMEAN|ISREGEN,{_r,{10,10,10,_c},4,2,7,_p,"1d4"}},
+{"devil Asmodeus",'A',-1,{1,500,1},ISMEAN|ISREGEN,{_r,{24,18,18,_c},500000,40,-10,_p,"4d10/4d10"}},
+};
+
+#undef _p		/* erase these definitions */
+#undef _c
+#undef _r
+
+struct h_list helpstr[] = {
+	'?',	"	prints help",
+	'/',	"	identify object",
+	'h',	"	left",
+	'j',	"	down",
+	'k',	"	up",
+	'l',	"	right",
+	'y',	"	up & left",
+	'u',	"	up & right",
+	'b',	"	down & left",
+	'n',	"	down & right",
+	'H',	"	run left",
+	'J',	"	run down",
+	'K',	"	run up",
+	'L',	"	run right",
+	'Y',	"	run up & left",
+	'U',	"	run up & right",
+	'B',	"	run down & left",
+	'N',	"	run down & right",
+	't',	"<dir>	throw something",
+	'f',	"<dir>	forward until find something",
+	'p',	"<dir>	zap a wand in a direction",
+	'z',	"	zap a wand or staff",
+	'>',	"	go down a staircase",
+	's',	"	search for trap/secret door",
+	'.',	"	(dot) rest for a while",
+	'i',	"	inventory pack",
+	'I',	"	inventory single item",
+	'q',	"	quaff potion",
+	'r',	"	read a scroll",
+	'e',	"	eat food",
+	'w',	"	wield a weapon",
+	'W',	"	wear armor",
+	'T',	"	take armor off",
+	'P',	"	put on ring",
+	'R',	"	remove ring",
+	'd',	"	drop object",
+	'c',	"	call object",
+	'O',	"	examine/set options",
+	'a',	"	display maximum stats",
+	'D',	"	dip object in pool",
+	CTRL('L'),"	redraw screen",
+	ESCAPE,	"	cancel command",
+	'!',	"	shell escape",
+	'S',	"	save game",
+	'Q',	"	quit",
+	0, 0
+};
+
+char *s_names[MAXSCROLLS];		/* Names of the scrolls */
+char *p_colors[MAXPOTIONS];		/* Colors of the potions */
+char *r_stones[MAXRINGS];		/* Stone settings of the rings */
+struct rod ws_stuff[MAXSTICKS];	/* Stuff for sticks */
+
+struct magic_item things[NUMTHINGS + 1] = {
+	{ "potion",	257,	 5, },
+	{ "scroll",	250,	30, },
+	{ "food",	185,	 7, },
+	{ "weapon",	 92,	 0, },
+	{ "armor",	 92,	 0, },
+	{ "ring",	 62,	 5, },
+	{ "stick",	 62,	 0, },
+	{ "amulet",	 0,   -250, },
+	{ NULL,		 0,		 0,	},
+};
+
+struct magic_item a_magic[MAXARMORS + 1] = {
+	{ "leather armor",			170,   5 },
+	{ "ring mail",				130,  30 },
+	{ "studded leather armor",	130,  20 },
+	{ "scale mail",				120,   3 },
+	{ "padded armor",			100, 250 },
+	{ "chain mail",				 90,  75 },
+	{ "splint mail",			 90,  80 },
+	{ "banded mail",			 90,  90 },
+	{ "plate mail",		 		 50, 400 },
+	{ "plate armor",			 30, 650 },
+	{ NULL,						  0,   0 },
+};
+struct init_armor armors[MAXARMORS] = {
+	{ 8,	150,	500,	},
+	{ 7,	250,	650,	},
+	{ 7,	200,	550,	},
+	{ 6,	400,	900,	},
+	{ 6,	100,	450,	},
+	{ 5,	300,	650,	},
+	{ 4,	400,	700,	},
+	{ 4,	350,	600,	},
+	{ 3,	450,	950,	},
+	{ 2,	350,	750,	},
+};
+struct magic_item w_magic[MAXWEAPONS + 1] = {
+	{ "mace",				 70,  25 },
+	{ "long sword",			 70,  60 },
+	{ "short bow",			 60, 150 },
+	{ "arrow",				 60,   2 },
+	{ "dagger",				 20,   5 },
+	{ "rock",				 20,   1 },
+	{ "two-handed sword",	 50, 120 },
+	{ "sling",				 20,   5 },
+	{ "dart",				 30,   3 },
+	{ "crossbow",			 60,  70 },
+	{ "crossbow bolt",		 60,   3 },
+	{ "spear",				 70,   8 },
+	{ "trident",			 70,  90 },
+	{ "spetum",				 70,  50 },
+	{ "bardiche",			 70,  30 },
+	{ "pike",				 70,  75 },
+	{ "bastard sword",		 60, 100 },
+	{ "halberd",			 70,  40 },
+	{ NULL,					  0,   0 },
+};
+
+struct init_weps weaps[MAXWEAPONS] = {
+	{ "2d4",  "1d3", 0, 100, 300, NONE },
+	{ "1d10", "1d2", 0,  60, 180, NONE },
+	{ "1d1",  "1d1", 0,  40, 190, NONE },
+	{ "1d1",  "1d6", ISMANY|ISMISL, 5, 8, BOW },
+	{ "1d6",  "1d4", ISMISL, 10, 30, NONE },
+	{ "1d2",  "1d4", ISMANY|ISMISL, 5, 10, SLING },
+	{ "3d6",  "1d2", 0, 250, 550, NONE },
+	{ "0d0",  "0d0", 0,   5, 7, NONE },
+	{ "1d1",  "1d3", ISMANY|ISMISL, 5, 5, NONE },
+	{ "1d1",  "1d1", 0, 100, 250, NONE },
+	{ "1d2", "1d10", ISMANY|ISMISL, 7, 11, CROSSBOW },
+	{ "1d8",  "1d6", ISMISL, 50, 200, NONE },
+	{ "3d4",  "1d4", 0,  50, 220, NONE },
+	{ "2d5",  "1d3", 0,  50, 200, NONE },
+	{ "3d3",  "1d2", 0, 125, 270, NONE },
+	{ "1d12", "1d8", 0,  80, 260, NONE },
+	{ "2d7",  "1d2", 0, 100, 400, NONE },
+	{ "2d6",  "1d3", 0, 175, 370, NONE },
+};
+
+struct magic_item s_magic[MAXSCROLLS + 1] = {
+	{ "monster confusion",	 50, 200 },
+	{ "magic mapping",		 52, 200 },
+	{ "light",				 80, 100 },
+	{ "hold monster",		 25, 200 },
+	{ "sleep",				 41,  50 },
+	{ "enchant armor",		 75, 175 },
+	{ "identify",			211, 150 },
+	{ "scare monster",		 42, 300 },
+	{ "gold detection",		 32, 100 },
+	{ "teleportation",		 73, 200 },
+	{ "enchant weapon",		 91, 175 },
+	{ "create monster",		 34,  75 },
+	{ "remove curse",		 82, 100 },
+	{ "aggravate monsters",	 10,  50 },
+	{ "blank paper",		 11,  50 },
+	{ "genocide",			  5, 350 },
+	{ "item knowledge",		 14, 250 },
+	{ "item protection",	  9, 250 },
+	{ "demons curse",		  5,  25 },
+	{ "transport",			 11, 100 },
+	{ "enchantment",		  3, 300 },
+	{ "gods blessing",		  4, 450 },
+	{ "aquirement",			  3, 450 },
+	{ "banishment",			  5,  25 },
+	{ "recharge wand",		 14, 250 },
+	{ "locate traps",		 18, 185 },
+	{ NULL,					  0,   0 },
+};
+
+struct magic_item p_magic[MAXPOTIONS + 1] = {
+	{ "confusion",			 69,  50 },
+	{ "paralysis",			 69,  50 },
+	{ "poison",				 55,  50 },
+	{ "gain strength",		130, 150 },
+	{ "see invisible",		 25, 175 },
+	{ "healing",			120, 130 },
+	{ "monster detection",	 59, 120 },
+	{ "magic detection",	 54, 105 },
+	{ "raise level",		 25, 300 },
+	{ "extra healing",		 52, 175 },
+	{ "haste self",			 41, 200 },
+	{ "restore strength",	140, 200 },
+	{ "blindness",			 25,  50 },
+	{ "thirst quenching",	 10,  50 },
+	{ "increase dexterity",	 50, 175 },
+	{ "etherealness",		 20, 150 },
+	{ "increase wisdom",	 35, 175 },
+	{ "regeneration",		 10, 175 },
+	{ "super ability",		  3, 500 },
+	{ "decrepedness",		  4,  25 },
+	{ "invincibility",		  4, 500 },
+	{ NULL,					  0,   0 },
+};
+
+struct magic_item r_magic[MAXRINGS + 1] = {
+	{ "protection",			 71, 200 },
+	{ "strength",			 70, 200 },
+	{ "sustain strength",	 45, 250 },
+	{ "searching",			 70, 150 },
+	{ "see invisible",		 77, 175 },
+	{ "constitution",		 13, 350 },
+	{ "aggravate monster",	 60, 100 },
+	{ "agility",			 75, 250 },
+	{ "increase damage",	 61, 250 },
+	{ "regeneration",		 41, 250 },
+	{ "digestion",			 60, 225 },
+	{ "teleportation",		 60, 100 },
+	{ "stealth",			 75, 200 },
+	{ "speed",				 40, 225 },
+	{ "find traps",			 27, 200 },
+	{ "delusion",			 18, 100 },
+	{ "sustain ability",	  9, 450 },
+	{ "blindness",			 10,  50 },
+	{ "lethargy",			 14,  75 },
+	{ "ogre strength",		  8, 350 },
+	{ "enfeeblement",		  5,  25 },
+	{ "burden",				 10,  50 },
+	{ "illumination",		 16, 100 },
+	{ "fire protection",	  5, 225 },
+	{ "wisdom",				 25, 200 },
+	{ "dexterity",			 35, 200 },
+	{ NULL,					  0,   0 },
+};
+
+struct magic_item ws_magic[MAXSTICKS + 1] = {
+	{ "light",				 95, 120 },
+	{ "striking",			 75, 115 },
+	{ "lightning",			 30, 200 },
+	{ "fire",				 30, 200 },
+	{ "cold",				 30, 200 },
+	{ "polymorph",			 95, 210 },
+	{ "magic missile",		 70, 170 },
+	{ "haste monster",		 80,  50 },
+	{ "slow monster",		 90, 220 },
+	{ "drain life",			 80, 210 },
+	{ "nothing",			 10,  70 },
+	{ "teleport away",		 55, 140 },
+	{ "teleport to",		 50,  60 },
+	{ "cancellation",		 55, 130 },
+	{ "sap life",			 20,  50 },
+	{ "curing",				 25, 250 },
+	{ "pyromania",			 15,  25 },
+	{ "annihilate monster",	  5, 750 },
+	{ "paralyze monster",	 10, 650 },
+	{ "food absorption",	 10,  75 },
+	{ "regenerate monster",	 15,  25 },
+	{ "hide monster",		 10,  50 },
+	{ "anti-matter",		  5,  25 },
+	{ "clone monster",		 10,  10 },
+	{ "confuse monster",	 15, 150 },
+	{ "degenerate monster",	 15, 150 },
+	{ NULL,					  0,   0 },
+};
+
+struct magic_info thnginfo[NUMTHINGS] = {
+	{ MAXPOTIONS,	V_POTION,	POTION,	p_magic,	},
+	{ MAXSCROLLS,	V_SCROLL,	SCROLL,	s_magic,	},
+	{ MAXFOODS,		V_FOOD,		FOOD,	NULL,		},
+	{ MAXWEAPONS,	V_WEAPON,	WEAPON,	w_magic,	},
+	{ MAXARMORS,	V_ARMOR,	ARMOR,	a_magic,	},
+	{ MAXRINGS,		V_RING,		RING,	r_magic,	},
+	{ MAXSTICKS,	V_STICK,	STICK,	ws_magic,	},
+	{ MAXAMULETS,	V_AMULET,	AMULET,	NULL,		},
+};
+
+long e_levels[] = {
+    10L,20L,40L,80L,160L,320L,640L,1280L,2560L,5120L,10240L,20480L,
+    40920L, 81920L, 163840L, 327680L, 655360L, 1310720L, 2621440L,
+	3932160L, 5242880L, 7864320L, 10485760L, 15728640L, 20971520L,
+	41943040L, 83886080L, 167772160L, 335544320L, 0L,
+};
+
+WINDOW *cw;		/* what the hero sees */
+WINDOW *hw;		/* utility window */
+WINDOW *mw;		/* monster window */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/srogue/init.c	Thu Nov 25 12:21:41 2010 +0000
@@ -0,0 +1,338 @@
+/*
+ * initializate various things
+ *
+ * @(#)init.c	9.0	(rdk)	 7/17/84
+ *
+ * Super-Rogue
+ * Copyright (C) 1984 Robert D. Kindelberger
+ * All rights reserved.
+ *
+ * Based on "Rogue: Exploring the Dungeons of Doom"
+ * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
+ * All rights reserved.
+ *
+ * See the file LICENSE.TXT for full copyright and licensing information.
+ */
+
+#include <ctype.h>
+#include "rogue.h"
+#include "rogue.ext"
+
+char *rainbow[NCOLORS] = {
+	"Red",		"Blue",		"Green",	"Yellow",
+	"Black",	"Brown",	"Orange",	"Pink",
+	"Purple",	"Grey",		"White",	"Silver",
+	"Gold",		"Violet",	"Clear",	"Vermilion",
+	"Ecru",		"Turquoise","Magenta",	"Amber",
+	"Topaz",	"Plaid",	"Tan",		"Tangerine",
+	"Aquamarine", "Scarlet","Khaki",	"Crimson",
+	"Indigo",	"Beige",	"Lavender",	"Saffron",
+};
+
+char *sylls[NSYLS] = {
+	"a", "ab", "ag", "aks", "ala", "an", "ankh", "app", "arg", "arze",
+	"ash", "ban", "bar", "bat", "bek", "bie", "bin", "bit", "bjor",
+	"blu", "bot", "bu", "byt", "comp", "con", "cos", "cre", "dalf",
+	"dan", "den", "do", "e", "eep", "el", "eng", "er", "ere", "erk",
+	"esh", "evs", "fa", "fid", "for", "fri", "fu", "gan", "gar",
+	"glen", "gop", "gre", "ha", "he", "hyd", "i", "ing", "ion", "ip",
+	"ish", "it", "ite", "iv", "jo", "kho", "kli", "klis", "la", "lech",
+	"man", "mar", "me", "mi", "mic", "mik", "mon", "mung", "mur",
+	"nej", "nelg", "nep", "ner", "nes", "nes", "nih", "nin", "o", "od",
+	"ood", "org", "orn", "ox", "oxy", "pay", "pet", "ple", "plu", "po",
+	"pot","prok","re", "rea", "rhov", "ri", "ro", "rog", "rok", "rol",
+	"sa", "san", "sat", "see", "sef", "seh", "shu", "ski", "sna",
+	"sne", "snik", "sno", "so", "sol", "sri", "sta", "sun", "ta",
+	"tab", "tem", "ther", "ti", "tox", "trol", "tue", "turs", "u",
+	"ulk", "um", "un", "uni", "ur", "val", "viv", "vly", "vom", "wah",
+	"wed", "werg", "wex", "whon", "wun", "xo", "y", "yot", "yu",
+	"zant", "zap", "zeb", "zim", "zok", "zon", "zum",
+};
+
+char *stones[] = {
+	"Agate",		"Alexandrite",	"Amethyst",
+	"Azurite",		"Carnelian",	"Chrysoberyl",
+	"Chrysoprase",	"Citrine",		"Diamond",
+	"Emerald",		"Garnet",		"Hematite",
+	"Jacinth",		"Jade",			"Kryptonite",
+	"Lapus lazuli",	"Malachite",	"Moonstone",
+	"Obsidian",		"Olivine",		"Onyx",
+	"Opal",			"Pearl",		"Peridot",
+	"Quartz",		"Rhodochrosite","Ruby",
+	"Sapphire",		"Sardonyx",		"Serpintine",
+	"Spinel",		"Tiger eye",	"Topaz",
+	"Tourmaline",	"Turquoise",
+};
+
+char *wood[NWOOD] = {
+	"Avocado wood",	"Balsa",	"Banyan",		"Birch",
+	"Cedar",		"Cherry",	"Cinnibar",		"Dogwood",
+	"Driftwood",	"Ebony",	"Eucalyptus",	"Hemlock",
+	"Ironwood",		"Mahogany",	"Manzanita",	"Maple",
+	"Oak",			"Pine",		"Redwood",		"Rosewood",
+	"Teak",			"Walnut",	"Zebra wood", 	"Persimmon wood",
+};
+
+char *metal[NMETAL] = {
+	"Aluminium",	"Bone",		"Brass",	"Bronze",
+	"Copper",		"Chromium",	"Iron",		"Lead",
+	"Magnesium",	"Pewter",	"Platinum",	"Steel",
+	"Tin",			"Titanium",	"Zinc",
+};
+
+/*
+ * init_everything:
+ *	Set up all important stuff.
+ */
+init_everything()
+{
+	init_player();			/* Roll up the rogue */
+	init_things();			/* Set up probabilities */
+	init_names();			/* Set up names of scrolls */
+	init_colors();			/* Set up colors of potions */
+	init_stones();			/* Set up stones in rings */
+	init_materials();		/* Set up materials of wands */
+}
+
+/*
+ * init_things:
+ *	Initialize the probabilities for types of things
+ */
+init_things()
+{
+	struct magic_item *mi;
+	
+	/*
+	 * init general things
+	 */
+	for (mi = &things[1]; mi < &things[NUMTHINGS]; mi++)
+		mi->mi_prob += (mi-1)->mi_prob;
+	badcheck("things", things);
+	/*
+	 * init armor things
+	 */
+	for (mi = &a_magic[1]; mi < &a_magic[MAXARMORS]; mi++)
+		mi->mi_prob += (mi-1)->mi_prob;
+	badcheck("armor", a_magic);
+	/*
+	 * init weapon stuff
+	 */
+	for (mi = &w_magic[1]; mi < &w_magic[MAXWEAPONS]; mi++)
+		mi->mi_prob += (mi-1)->mi_prob;
+	badcheck("weapon", w_magic);
+}
+
+
+/*
+ * init_colors:
+ *	Initialize the potion color scheme for this time
+ */
+init_colors()
+{
+	reg int i, j;
+	reg char *str;
+	bool used[NCOLORS];
+
+	for (i = 0; i < NCOLORS; i++)
+		used[i] = FALSE;
+	for (i = 0; i < MAXPOTIONS; i++) {
+		do {
+			j = rnd(NCOLORS);
+		} until (!used[j]);
+		used[j] = TRUE;
+		p_colors[i] = rainbow[j];
+		p_know[i] = FALSE;
+		p_guess[i] = NULL;
+		if (i > 0)
+			p_magic[i].mi_prob += p_magic[i-1].mi_prob;
+	}
+	badcheck("potions", p_magic);
+}
+
+
+/*
+ * init_names:
+ *	Generate the names of the various scrolls
+ */
+init_names()
+{
+	reg int nsyl;
+	reg char *cp, *sp;
+	reg int i, nwords;
+
+	for (i = 0; i < MAXSCROLLS; i++) {
+		cp = prbuf;
+		nwords = rnd(3)+1;
+		while(nwords--)	{
+			nsyl = rnd(3)+2;
+			while(nsyl--) {
+				sp = sylls[rnd(NSYLS)];
+				while(*sp)
+					*cp++ = *sp++;
+			}
+			*cp++ = ' ';
+		}
+		*--cp = '\0';
+		s_names[i] = new(strlen(prbuf)+1);
+		s_know[i] = FALSE;
+		s_guess[i] = NULL;
+		strcpy(s_names[i], prbuf);
+		if (i > 0)
+			s_magic[i].mi_prob += s_magic[i-1].mi_prob;
+	}
+	badcheck("scrolls", s_magic);
+}
+
+/*
+ * init_stones:
+ *	Initialize the ring stone setting scheme for this time
+ */
+
+init_stones()
+{
+	reg int i, j;
+	reg char *str;
+	bool used[NSTONES];
+
+	for (i = 0; i < NSTONES; i++)
+		used[i] = FALSE;
+
+	for (i = 0; i < MAXRINGS; i++) {
+		do {
+			j = rnd(NSTONES);
+		} until (!used[j]);
+		used[j] = TRUE;
+		r_stones[i] = stones[j];
+		r_know[i] = FALSE;
+		r_guess[i] = NULL;
+		if (i > 0)
+			r_magic[i].mi_prob += r_magic[i-1].mi_prob;
+	}
+	badcheck("rings", r_magic);
+}
+
+/*
+ * init_materials:
+ *	Initialize the construction materials for wands and staffs
+ */
+
+init_materials()
+{
+	int i, j;
+	char *str;
+	struct rod *rd;
+	bool metused[NMETAL], woodused[NWOOD];
+
+	for (i = 0; i < NWOOD; i++)
+		woodused[i] = FALSE;
+	for (i = 0; i < NMETAL; i++)
+		metused[i] = FALSE;
+
+	for (i = 0; i < MAXSTICKS; i++) {
+		rd = &ws_stuff[i];
+		for (;;)  {
+			if (rnd(100) > 50) {
+				j = rnd(NMETAL);
+				if (!metused[j]) {
+					str = metal[j];
+					rd->ws_type = "wand";
+					rd->ws_vol = V_WS_WAND;
+					rd->ws_wght = W_WS_WAND;
+					metused[j] = TRUE;
+					break;
+				}
+			}
+			else {
+				j = rnd(NWOOD);
+				if (!woodused[j]) {
+					str = wood[j];
+					rd->ws_type = "staff";
+					rd->ws_vol = V_WS_STAFF;
+					rd->ws_wght = W_WS_WAND;
+					woodused[j] = TRUE;
+					break;
+				}
+			}
+		} 
+		ws_stuff[i].ws_made = str;
+		ws_know[i] = FALSE;
+		ws_guess[i] = NULL;
+		if (i > 0)
+			ws_magic[i].mi_prob += ws_magic[i-1].mi_prob;
+	}
+	badcheck("sticks", ws_magic);
+}
+
+badcheck(name, magic)
+char *name;
+struct magic_item *magic;
+{
+	struct magic_item *mg;
+
+	for (mg = magic; mg->mi_name != NULL; mg++)
+		;
+	if ((mg - 1)->mi_prob == 1000)
+		return;
+	printf("\nBad percentages for %s:\n", name);
+	for (mg = magic; mg->mi_name != NULL; mg++)
+		printf("%4d%% %s\n", mg->mi_prob, mg->mi_name);
+	printf("%s", retstr);
+	fflush(stdout);
+	while (getchar() != '\n')
+		continue;
+}
+
+
+/*
+ * init_player:
+ *	roll up the rogue
+ */
+
+init_player()
+{
+	player.t_nomove = 0;
+	player.t_nocmd = 0;
+	him = &player.t_stats;
+	him->s_lvl = 1;
+	him->s_exp = 0L;
+	him->s_maxhp = him->s_hpt = pinit();		/* hit points */
+	him->s_re.a_str = pinit();		/* strength */
+	him->s_re.a_dex = pinit();		/* dexterity */
+	him->s_re.a_wis = pinit();		/* wisdom */
+	him->s_re.a_con = pinit();		/* constitution */
+	him->s_ef = him->s_re;			/* effective = real */
+	strcpy(him->s_dmg, "1d4");
+	him->s_arm = NORMAC;
+	him->s_carry = totalenc();
+	him->s_pack = 0;
+	pack = NULL;				/* empty pack so far */
+	max_stats = *him;
+}
+
+
+/*
+ * pinit:
+ *	Returns the best 3 of 4 on a 6-sided die
+ */
+pinit()
+{
+	int best[4];
+	reg int i, min, minind, dicetot;
+
+	for (i = 0 ; i < 4 ; i++)
+		best[i] = roll(1,6);	/* populate array */
+	min = best[0];				/* assume that 1st entry */
+	minind = 0;					/* is the lowest */
+	for (i = 1 ; i < 4 ; i++) {	/* find the lowest */
+		if (best[i] < min) {	/* if < minimum then update */
+			min = best[i];
+			minind = i;			/* point to lowest value */
+		}
+	}
+	dicetot = 0;				/* start with nothing */
+	for (i = 0 ; i < 4 ; i++) {
+		if (i != minind)		/* if not minimum, then add it */
+			dicetot += best[i];
+	}
+	return(dicetot);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/srogue/io.c	Thu Nov 25 12:21:41 2010 +0000
@@ -0,0 +1,328 @@
+/*
+ * Various input/output functions
+ *
+ * @(#)io.c	9.0	(rdk)	 7/17/84
+ *
+ * Super-Rogue
+ * Copyright (C) 1984 Robert D. Kindelberger
+ * All rights reserved.
+ *
+ * Based on "Rogue: Exploring the Dungeons of Doom"
+ * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
+ * All rights reserved.
+ *
+ * See the file LICENSE.TXT for full copyright and licensing information.
+ */
+
+#include <stdarg.h>
+#include <ctype.h>
+#include "rogue.h"
+#include "rogue.ext"
+
+/*
+ * msg:
+ *	Display a message at the top of the screen.
+ */
+static char msgbuf[BUFSIZ];
+static int newpos = 0;
+
+msg(char *fmt, ...)
+{
+	va_list ap;
+	/*
+	 * if the string is "", just clear the line
+	 */
+	if (*fmt == '\0') {
+		wmove(cw, 0, 0);
+		wclrtoeol(cw);
+		mpos = 0;
+		return;
+	}
+	/*
+	 * otherwise add to the message and flush it out
+	 */
+	va_start(ap, fmt);
+	doadd(fmt, ap);
+	va_end(ap);
+	endmsg();
+}
+
+/*
+ * addmsg:
+ *	Add things to the current message
+ */
+addmsg(char *fmt, ...)
+{
+	va_list ap;
+
+	va_start(ap, fmt);
+	doadd(fmt, ap);
+	va_end(ap);
+}
+
+/*
+ * endmsg:
+ * 	Display a new msg, giving him a chance to see the
+ *	previous one if it is up there with the --More--
+ */
+endmsg()
+{
+	strcpy(huh, msgbuf);
+	if (mpos > 0) {
+		wmove(cw, 0, mpos);
+		waddstr(cw, morestr);
+		draw(cw);
+		wait_for(cw, ' ');
+	}
+	mvwaddstr(cw, 0, 0, msgbuf);
+	wclrtoeol(cw);
+	mpos = newpos;
+	newpos = 0;
+	draw(cw);
+}
+
+/*
+ * doadd:
+ *	Perform a printf into a buffer
+ */
+doadd(char *fmt, va_list ap)
+{
+	vsprintf(&msgbuf[newpos], fmt, ap);
+	newpos = strlen(msgbuf);
+}
+
+/*
+ * step_ok:
+ *	Returns TRUE if it is ok to step on ch
+ */
+step_ok(ch)
+unsigned char ch;
+{
+	if (dead_end(ch))
+		return FALSE;
+	else if (ch >= 32 && ch <= 127 && !isalpha(ch))
+		return TRUE;
+	return FALSE;
+}
+
+
+/*
+ * dead_end:
+ *	Returns TRUE if you cant walk through that character
+ */
+dead_end(ch)
+char ch;
+{
+	if (ch == '-' || ch == '|' || ch == ' ' || ch == SECRETDOOR)
+		return TRUE;
+	else
+		return FALSE;
+}
+
+
+/*
+ * readchar:
+ *	flushes stdout so that screen is up to date and then returns
+ *	getchar.
+ */
+
+readchar()
+{
+	char c;
+
+	fflush(stdout);
+        return( wgetch(cw) );
+}
+
+char *hungstr[] = {
+	"",
+	"  HUNGRY",
+	"  STARVING",
+	"  FAINTING",
+};
+
+/*
+ * status:
+ *	Display the important stats line.  Keep the cursor where it was.
+ */
+status(fromfuse)
+int fromfuse;
+{
+	reg int totwght, carwght;
+	reg struct real *stef, *stre, *stmx;
+	reg char *pb;
+	int oy, ox, ch;
+	static char buf[LINLEN];
+	static char hwidth[] = { "%2d(%2d)" };
+
+	/*
+	 * If nothing has changed since the last time, then done
+	 */
+	if (nochange)
+		return;
+	nochange = TRUE;
+	updpack();					/* get all weight info */
+	stef = &player.t_stats.s_ef;
+	stre = &player.t_stats.s_re;
+	stmx = &max_stats.s_re;
+	totwght = him->s_carry / 10;
+	carwght = him->s_pack / 10;
+	getyx(cw, oy, ox);
+	if (him->s_maxhp >= 100) {
+		hwidth[1] = '3';	/* if hit point >= 100	*/
+		hwidth[5] = '3';	/* change %2d to %3d	*/
+	}
+	if (stre->a_str < stmx->a_str)
+		ch = '*';
+	else
+		ch = ' ';
+	sprintf(buf, "Str: %2d(%c%2d)", stef->a_str, ch, stre->a_str);
+	pb = &buf[strlen(buf)];
+	if (stre->a_dex < stmx->a_dex)
+		ch = '*';
+	else
+		ch = ' ';
+	sprintf(pb, "  Dex: %2d(%c%2d)", stef->a_dex, ch, stre->a_dex);
+	pb = &buf[strlen(buf)];
+	if (stre->a_wis < stmx->a_wis)
+		ch = '*';
+	else
+		ch = ' ';
+	sprintf(pb, "  Wis: %2d(%c%2d)", stef->a_wis, ch, stre->a_wis);
+	pb = &buf[strlen(buf)];
+	if (stre->a_con < stmx->a_con)
+		ch = '*';
+	else
+		ch = ' ';
+	sprintf(pb, "  Con: %2d(%c%2d)", stef->a_con, ch, stre->a_con);
+	pb = &buf[strlen(buf)];
+	sprintf(pb, "  Carry: %3d(%3d)", carwght, totwght);
+	mvwaddstr(cw, LINES - 1, 0, buf);
+	sprintf(buf, "Level: %d  Gold: %5d  Hp: ",level, purse);
+	pb = &buf[strlen(buf)];
+	sprintf(pb, hwidth, him->s_hpt, him->s_maxhp);
+	pb = &buf[strlen(buf)];
+	sprintf(pb,"  Ac: %-2d  Exp: %d/%ld",cur_armor == NULL ? him->s_arm :
+	  cur_armor->o_ac, him->s_lvl, him->s_exp);
+	carwght = (packvol * 100) / V_PACK;
+	pb = &buf[strlen(buf)];
+	sprintf(pb, "  Vol: %3d%%", carwght);
+	mvwaddstr(cw, LINES - 2, 0, buf);
+	waddstr(cw, hungstr[hungry_state]);
+	wclrtoeol(cw);
+	wmove(cw, oy, ox);
+}
+
+/*
+ * dispmax:
+ *	Display the hero's maximum status
+ */
+dispmax()
+{
+	reg struct real *hmax;
+
+	hmax = &max_stats.s_re;
+	msg("Maximums:  Str = %d  Dex = %d  Wis = %d  Con = %d",
+		hmax->a_str, hmax->a_dex, hmax->a_wis, hmax->a_con);
+}
+
+/*
+ * illeg_ch:
+ * 	Returns TRUE if a char shouldn't show on the screen
+ */
+illeg_ch(ch)
+unsigned char ch;
+{
+	if (ch < 32 || ch > 127)
+		return TRUE;
+	if (ch >= '0' && ch <= '9')
+		return TRUE;
+	return FALSE;
+}
+
+/*
+ * wait_for:
+ *	Sit around until the guy types the right key
+ */
+wait_for(win,ch)
+WINDOW *win;
+char ch;
+{
+	register char c;
+
+	if (ch == '\n')
+	    while ((c = wgetch(win)) != '\n' && c != '\r')
+			continue;
+	else
+	    while (wgetch(win) != ch)
+			continue;
+}
+
+#ifdef NEED_GETTIME
+#include <stdio.h>
+#include <pwd.h>
+
+/*
+ * gettime:
+ *	This routine returns the current time as a string
+ */
+#ifdef ATT
+#include <time.h>
+#endif
+#ifdef BSD
+#include <sys/time.h>
+#endif
+
+char *
+gettime()
+{
+	register char *timeptr;
+	char *ctime();
+	long int now, time();
+
+	time(&now);		/* get current time */
+	timeptr = ctime(&now);	/* convert to string */
+	return timeptr;		/* return the string */
+}
+#endif
+
+
+/*
+ * dbotline:
+ *	Displays message on bottom line and waits for a space to return
+ */
+dbotline(scr,message)
+WINDOW *scr;
+char *message;
+{
+	mvwaddstr(scr,LINES-1,0,message);
+	draw(scr);
+	wait_for(scr,' ');	
+}
+
+
+/*
+ * restscr:
+ *	Restores the screen to the terminal
+ */
+restscr(scr)
+WINDOW *scr;
+{
+	clearok(scr,TRUE);
+	touchwin(scr);
+}
+
+/*
+ * npch:
+ *	Get the next char in line for inventories
+ */
+npch(ch)
+char ch;
+{
+	reg char nch;
+	if (ch >= 'z')
+		nch = 'A';
+	else
+		nch = ch + 1;
+	return nch;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/srogue/list.c	Thu Nov 25 12:21:41 2010 +0000
@@ -0,0 +1,110 @@
+/*
+ * Functions for dealing with linked lists of goodies
+ *
+ * @(#)list.c	9.0	(rdk)	 7/17/84
+ *
+ * Super-Rogue
+ * Copyright (C) 1984 Robert D. Kindelberger
+ * All rights reserved.
+ *
+ * Based on "Rogue: Exploring the Dungeons of Doom"
+ * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
+ * All rights reserved.
+ *
+ * See the file LICENSE.TXT for full copyright and licensing information.
+ */
+
+#include <stdlib.h>
+#include "rogue.h"
+#include "rogue.ext"
+
+/*
+ * detach:
+ *	Takes an item out of whatever linked list it might be in
+ */
+
+_detach(list, item)
+struct linked_list **list, *item;
+{
+	if (*list == item)
+		*list = next(item);
+	if (prev(item) != NULL)
+		item->l_prev->l_next = next(item);
+	if (next(item) != NULL)
+		item->l_next->l_prev = prev(item);
+	item->l_next = NULL;
+	item->l_prev = NULL;
+}
+
+/*
+ * _attach:	add an item to the head of a list
+ */
+_attach(list, item)
+struct linked_list **list, *item;
+{
+	if (*list != NULL) 	{
+		item->l_next = *list;
+		(*list)->l_prev = item;
+		item->l_prev = NULL;
+	}
+	else 	{
+		item->l_next = NULL;
+		item->l_prev = NULL;
+	}
+	*list = item;
+}
+
+/*
+ * _free_list:	Throw the whole blamed thing away
+ */
+_free_list(ptr)
+struct linked_list **ptr;
+{
+	register struct linked_list *item;
+
+	while (*ptr != NULL) {
+		item = *ptr;
+		*ptr = next(item);
+		discard(item);
+	}
+}
+
+/*
+ * discard:  free up an item
+ */
+discard(item)
+struct linked_list *item;
+{
+	total -= 2;
+	FREE(item->l_data);
+	FREE(item);
+}
+
+/*
+ * new_item:	get a new item with a specified size
+ */
+struct linked_list *
+new_item(size)
+int size;
+{
+	register struct linked_list *item;
+
+	item = (struct linked_list *) new(sizeof *item);
+	item->l_data = new(size);
+	item->l_next = item->l_prev = NULL;
+	return item;
+}
+
+char *
+new(size)
+int size;
+{
+	register char *space = ALLOC(size);
+
+	if (space == NULL) {
+		sprintf(prbuf,"Rogue ran out of memory (%d).",sbrk(0));
+		fatal(prbuf);
+	}
+	total++;
+	return space;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/srogue/main.c	Thu Nov 25 12:21:41 2010 +0000
@@ -0,0 +1,472 @@
+/*
+ * Rogue
+ * Exploring the dungeons of doom
+ *
+ * @(#)main.c	9.0	(rdk)	 7/17/84
+ *
+ * Super-Rogue
+ * Copyright (C) 1984 Robert D. Kindelberger
+ * All rights reserved.
+ *
+ * Based on "Rogue: Exploring the Dungeons of Doom"
+ * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
+ * All rights reserved.
+ *
+ * See the file LICENSE.TXT for full copyright and licensing information.
+ */
+
+#include <time.h>
+#include <termios.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <signal.h>
+#include <pwd.h>
+#include <limits.h>
+#include <sys/stat.h>
+#include "rogue.h"
+
+#ifdef ATT
+#include <time.h>
+#endif
+
+#ifdef BSD
+#define srand48(seed)	srandom(seed)
+#define lrand48()	random()
+#include <sys/time.h>
+#endif
+
+#include "rogue.ext"
+
+struct termios terminal;
+
+main(argc, argv, envp)
+char **argv;
+char **envp;
+{
+	register char *env;
+	register struct linked_list *item;
+	register struct object *obj;
+	struct passwd *pw;
+	struct passwd *getpwuid();
+	char alldone, wpt;
+	char *getpass(), *xcrypt(), *strrchr();
+	int lowtime;
+	time_t now;
+        char *roguehome();
+	char *homedir = roguehome();
+
+#ifdef __DJGPP__
+	_fmode = O_BINARY;
+#endif
+
+	if (homedir == NULL)
+        	homedir = "";
+
+	playuid = getuid();
+
+	if (setuid(playuid) < 0) {
+		printf("Cannot change to effective uid: %d\n", playuid);
+		exit(1);
+	}
+	playgid = getgid();
+
+	/* check for print-score option */
+
+	strcpy(scorefile, homedir);
+
+	if (*scorefile)
+		strcat(scorefile,"/");
+	strcat(scorefile, "srogue.scr");
+
+	if(argc >= 2 && strcmp(argv[1], "-s") == 0)
+	{
+		showtop(0);
+		exit(0);
+	}
+
+	if (argc >= 2 && author() && strcmp(argv[1],"-a") == 0)
+	{
+		wizard = TRUE;
+		argv++;
+		argc--;
+	}
+
+	/* Check to see if he is a wizard */
+
+	if (argc >= 2 && strcmp(argv[1],"-w") == 0)
+	{
+		if (strcmp(PASSWD, xcrypt(getpass(wizstr),"mT")) == 0)
+		{
+			wizard = TRUE;
+			argv++;
+			argc--;
+		}
+	}
+	time(&now);
+	lowtime = (int) now;
+
+	/* get home and options from environment */
+
+	if ((env = getenv("HOME")) != NULL)
+		strcpy(home, env);
+	else if ((pw = getpwuid(playuid)) != NULL)
+		strcpy(home, pw->pw_dir);
+	else
+		home[0] = '\0';
+
+        if (strcmp(home,"/") == 0)
+		home[0] = '\0';
+
+        if ((strlen(home) > 0) && (home[strlen(home)-1] != '/'))
+		strcat(home, "/");
+
+	strcpy(file_name, home);
+	strcat(file_name, "srogue.sav");
+
+	if ((env = getenv("ROGUEOPTS")) != NULL)
+		parse_opts(env);
+
+	if (env == NULL || whoami[0] == '\0')
+	{
+		if((pw = getpwuid(playuid)) == NULL)
+		{
+			printf("Say, who are you?\n");
+			exit(1);
+		}
+		else
+			strucpy(whoami, pw->pw_name, strlen(pw->pw_name));
+	}
+
+	if (env == NULL || fruit[0] == '\0')
+		strcpy(fruit, "juicy-fruit");
+
+	if (argc == 2)
+		if(!restore(argv[1], envp)) /* NOTE: NEVER RETURNS */
+			exit(1);
+
+	dnum = (wizard && getenv("SEED") != NULL ?
+		atoi(getenv("SEED")) : lowtime + getpid());
+
+	if(wizard)
+		printf("Hello %s, welcome to dungeon #%d\n", whoami, dnum);
+	else
+		printf("Hello %s, One moment while I open the door to the dungeon...\n", whoami);
+
+	fflush(stdout);
+	seed = dnum;
+	srand48(seed);			/* init rnd number gen */
+
+	signal(SIGINT, byebye);		/* just in case */
+	signal(SIGQUIT ,byebye);
+
+	init_everything();
+
+#ifdef __INTERIX
+        setenv("TERM","interix");
+#endif
+
+	initscr();			/* Start up cursor package */
+
+	if (strcmp(termname(),"dumb") == 0)
+	{
+		endwin();
+		printf("ERROR in terminal parameters.\n");
+		printf("Check TERM in environment.\n");
+		byebye(1);
+	}
+
+	if (LINES < 24 || COLS < 80) {
+		endwin();
+		printf("ERROR: screen size too small\n");
+		byebye(1);
+	}
+
+	if ((whoami == NULL) || (*whoami == '\0') || (strcmp(whoami,"dosuser")==0))
+	{
+		echo();
+		mvaddstr(23,2,"Rogue's Name? ");
+		wgetnstr(stdscr,whoami,MAXSTR);
+		noecho();
+	}
+
+	if ((whoami == NULL) || (*whoami == '\0'))
+		strcpy(whoami,"Rodney");
+	
+	setup();
+
+	/* Set up windows */
+
+	cw = newwin(0, 0, 0, 0);
+	mw = newwin(0, 0, 0, 0);
+	hw = newwin(0, 0, 0, 0);
+	waswizard = wizard;
+
+	/* Draw current level */
+
+	new_level(NORMLEV);
+
+	/* Start up daemons and fuses */
+
+	daemon(status, TRUE, BEFORE);
+	daemon(doctor, TRUE, BEFORE);
+	daemon(stomach, TRUE, BEFORE);
+	daemon(runners, TRUE, AFTER);
+	fuse(swander, TRUE, WANDERTIME);
+
+	/* Give the rogue his weaponry */
+
+	do {
+		wpt = pick_one(w_magic);
+		switch (wpt)
+		{
+			case MACE:	case SWORD:	case TWOSWORD:
+			case SPEAR:	case TRIDENT:	case SPETUM:
+			case BARDICHE:	case PIKE:	case BASWORD:
+			case HALBERD:
+				alldone = TRUE;
+			otherwise:
+				alldone = FALSE;
+		}
+	} while(!alldone);
+
+	item = new_thing(FALSE, WEAPON, wpt);
+	obj = OBJPTR(item);
+	obj->o_hplus = rnd(3);
+	obj->o_dplus = rnd(3);
+	obj->o_flags = ISKNOW;
+	add_pack(item, TRUE);
+	cur_weapon = obj;
+
+	/* Now a bow */
+
+	item = new_thing(FALSE, WEAPON, BOW);
+	obj = OBJPTR(item);
+	obj->o_hplus = rnd(3);
+	obj->o_dplus = rnd(3);
+	obj->o_flags = ISKNOW;
+	add_pack(item, TRUE);
+
+	/* Now some arrows */
+
+	item = new_thing(FALSE, WEAPON, ARROW);
+	obj = OBJPTR(item);
+	obj->o_count = 25 + rnd(15);
+	obj->o_hplus = rnd(2);
+	obj->o_dplus = rnd(2);
+	obj->o_flags = ISKNOW;
+	add_pack(item, TRUE);
+
+	/* And his suit of armor */
+
+	wpt = pick_one(a_magic);
+	item = new_thing(FALSE, ARMOR, wpt);
+	obj = OBJPTR(item);
+	obj->o_flags = ISKNOW;
+	obj->o_ac = armors[wpt].a_class - rnd(4);
+	cur_armor = obj;
+	add_pack(item, TRUE);
+	
+	/* Give him some food */
+
+	item = new_thing(FALSE, FOOD, 0);
+	add_pack(item, TRUE);
+
+	playit();
+}
+
+
+/*
+ * endit:
+ *	Exit the program abnormally.
+ */
+void
+endit(int a)
+{
+	fatal("Ok, if you want to exit that badly, I'll have to allow it");
+}
+
+/*
+ * fatal:
+ *	Exit the program, printing a message.
+ */
+
+fatal(s)
+char *s;
+{
+	clear();
+	refresh();
+	endwin();
+	fprintf(stderr,"%s\n\r",s);
+	fflush(stderr);
+	byebye(2);
+}
+
+/*
+ * byebye:
+ *	Exit here and reset the users terminal parameters
+ *	to the way they were when he started
+ */
+
+void
+byebye(how)
+int how;
+{
+	if (!isendwin())
+		endwin();
+
+	exit(how);		/* exit like flag says */
+}
+
+
+/*
+ * rnd:
+ *	Pick a very random number.
+ */
+rnd(range)
+int range;
+{
+	reg int wh;
+
+	if (range == 0)
+		wh = 0;
+	else {
+		wh = lrand48() % range;
+		wh &= 0x7FFFFFFF;
+	}
+	return wh;
+}
+
+/*
+ * roll:
+ *	roll a number of dice
+ */
+roll(number, sides)
+int number, sides;
+{
+	reg int dtotal = 0;
+
+	while(number-- > 0)
+		dtotal += rnd(sides)+1;
+	return dtotal;
+}
+
+
+/*
+** setup: 	Setup signal catching functions
+*/
+setup()
+{
+	signal(SIGHUP, auto_save);
+	signal(SIGINT, auto_save);
+	signal(SIGQUIT,  byebye);
+	signal(SIGILL, game_err);
+	signal(SIGTRAP, game_err);
+#ifdef SIGIOT
+	signal(SIGIOT, game_err);
+#endif
+#ifdef SIGEMT
+	signal(SIGEMT, game_err);
+#endif
+	signal(SIGFPE, game_err);
+#ifdef SIGBUS
+	signal(SIGBUS, game_err);
+#endif
+	signal(SIGSEGV, game_err);
+#ifdef SIGSYS
+	signal(SIGSYS, game_err);
+#endif
+	signal(SIGPIPE, game_err);
+	signal(SIGTERM, game_err);
+
+	cbreak();
+	noecho();
+}
+
+/*
+** playit:	The main loop of the program.  Loop until the game is over,
+**		refreshing things and looking at the proper times.
+*/
+
+playit()
+{
+	reg char *opts;
+
+	tcgetattr(0,&terminal);
+
+
+	/* parse environment declaration of options */
+
+	if ((opts = getenv("ROGUEOPTS")) != NULL)
+		parse_opts(opts);
+
+	player.t_oldpos = hero;
+	oldrp = roomin(&hero);
+	nochange = FALSE;
+	while (playing)
+		command();		/* Command execution */
+	endit(0);
+}
+
+
+/*
+** author:	See if a user is an author of the program
+*/
+author()
+{
+	switch (playuid) {
+		case 100:
+		case 0:
+			return TRUE;
+		default:
+			return FALSE;
+	}
+}
+
+int
+directory_exists(char *dirname)
+{
+    struct stat sb;
+
+    if (stat(dirname, &sb) == 0) /* path exists */
+        return (S_ISDIR (sb.st_mode));
+
+    return(0);
+}
+
+char *
+roguehome()
+{
+    static char path[1024];
+    char *end,*home;
+
+    if ( (home = getenv("ROGUEHOME")) != NULL)
+    {
+        if (*home)
+        {
+            strncpy(path, home, PATH_MAX - 20);
+
+            end = &path[strlen(path)-1];
+
+
+            while( (end >= path) && ((*end == '/') || (*end == '\\')))
+                *end-- = '\0';
+
+            if (directory_exists(path))
+                return(path);
+        }
+    }
+
+    if (directory_exists("/var/games/roguelike"))
+        return("/var/games/roguelike");
+    if (directory_exists("/var/lib/roguelike"))
+        return("/var/lib/roguelike");
+    if (directory_exists("/var/roguelike"))
+        return("/var/roguelike");
+    if (directory_exists("/usr/games/lib"))
+        return("/usr/games/lib");
+    if (directory_exists("/games/roguelik"))
+        return("/games/roguelik");
+
+    return(NULL);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/srogue/makevers.c	Thu Nov 25 12:21:41 2010 +0000
@@ -0,0 +1,102 @@
+/*
+ * Change the version number of rogue
+ *
+ * The version must be in the file in the format of:
+ *
+ * " * @(#)filename\tVERSION\t ..."
+ *
+ * Where VERSION is a 3 character string, i.e., "8.2"
+ *
+ * Super-Rogue
+ * Copyright (C) 1984 Robert D. Kindelberger
+ * All rights reserved.
+ *
+ * See the file LICENSE.TXT for full copyright and licensing information.
+ */
+
+#include <stdio.h>
+#include <time.h>
+
+long clock;
+struct tm *tp;
+char who[100];
+
+char *strrchr(), *strchr(), *fgets();
+
+main(argc, argv)
+int argc;
+char **argv;
+{
+	register int i;
+	register char *ptr;
+	char ts[30];
+	FILE *fp;
+
+	strcpy(who, argv[0]);
+	if (argc < 3) {
+		fprintf(stderr,"Usage: %s VERSION c_files\n", who);
+		exit(1);
+	}
+	if (strlen(argv[1]) != 3) {
+		fprintf(stderr,"%s: VERSION must be length 3\n", who);
+		exit(1);
+	}
+	time(&clock);
+	tp = localtime(&clock);
+	sprintf(ts,"%2d/%2d/%2d",tp->tm_mon + 1,tp->tm_mday,tp->tm_year);
+	for (i = 2; i < argc; i++) {
+		ptr = strrchr(argv[i], '.');
+		/*
+		 * make sure that files end in ".c" or ".h"
+		 */
+		if (ptr != NULL) {
+			++ptr;
+			if (*ptr == 'c' || *ptr == 'h')
+				updvers(argv[1], argv[i]);
+		}
+	}
+	/*
+	 * now install new "version.c" file
+	 */
+	fp = fopen("vers.c", "w");
+	if (fp == NULL) {
+		fprintf(stderr,"%s: cant write version.c file\n",who);
+		exit(1);
+	}
+	fprintf(fp, "/*\n * version number.\n */\n");
+	fprintf(fp, "char version[] = ");
+	fprintf(fp, "%c@(#)vers.c\t%3s\t(rdk)\t%s%c;\n", '"',
+		argv[1], ts, '"');
+	fprintf(fp, "char *release = \"%s (%s)\";\n", argv[1],ts);
+	fclose(fp);
+	exit(0);
+}
+
+#define LINESIZ	132
+
+updvers(vers, fname)
+char *fname;
+char *vers;
+{
+	register FILE *fp;
+	register char *ptr, *c;
+	char line[LINESIZ];
+
+	if ((fp = fopen(fname, "r+")) == NULL) {
+		fprintf(stderr,"%s: Not able to update %s\n", who, fname);
+		return;
+	}
+	while ((c = fgets(line, LINESIZ, fp)) != NULL) {
+		if (line[1] == '*' && line[3] == '@' && line[5] == '#') {
+			ptr = strchr(line, '\t');
+			if (ptr != NULL) {
+				fseek(fp, -strlen(line), 1);
+				sprintf(ptr, "\t%3s\t(rdk)\t%2d/%2d/%2d\n", vers,
+					tp->tm_mon + 1, tp->tm_mday, tp->tm_year);
+				fprintf(fp, "%s", line);
+				break;
+			}
+		}
+	}
+	fclose(fp);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/srogue/misc.c	Thu Nov 25 12:21:41 2010 +0000
@@ -0,0 +1,401 @@
+/*
+ * all sorts of miscellaneous routines
+ *
+ * @(#)misc.c	9.0	(rdk)	 7/17/84
+ *
+ * Super-Rogue
+ * Copyright (C) 1984 Robert D. Kindelberger
+ * All rights reserved.
+ *
+ * Based on "Rogue: Exploring the Dungeons of Doom"
+ * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
+ * All rights reserved.
+ *
+ * See the file LICENSE.TXT for full copyright and licensing information.
+ */
+
+#include "rogue.h"
+#include <ctype.h>
+#include "rogue.ext"
+
+/*
+ * waste_time:
+ *	Do nothing but let other things happen
+ */
+waste_time()
+{
+	if (inwhgt)		/* if from wghtchk, then done */
+	     return;
+	do_daemons(BEFORE);
+	do_daemons(AFTER);
+	do_fuses();
+}
+
+/*
+ * getindex:
+ *	Convert a type into an index for the things structures
+ */
+getindex(what)
+char what;
+{
+	int index = -1;
+
+	switch (what) {
+		case POTION:	index = TYP_POTION;
+		when SCROLL:	index = TYP_SCROLL;
+		when FOOD:		index = TYP_FOOD;
+		when RING:		index = TYP_RING;
+		when AMULET:	index = TYP_AMULET;
+		when ARMOR:		index = TYP_ARMOR;
+		when WEAPON:	index = TYP_WEAPON;
+		when STICK:		index = TYP_STICK;
+	}
+	return index;
+}
+
+/*
+ * tr_name:
+ *	print the name of a trap
+ */
+char *
+tr_name(ch)
+char ch;
+{
+	reg char *s;
+
+	switch (ch) {
+		case TRAPDOOR:
+			s = "A trapdoor.";
+		when BEARTRAP:
+			s = "A beartrap.";
+		when SLEEPTRAP:
+			s = "A sleeping gas trap.";
+		when ARROWTRAP:
+			s = "An arrow trap.";
+		when TELTRAP:
+			s = "A teleport trap.";
+		when DARTTRAP:
+			s = "A dart trap.";
+		when POOL:
+			s = "A magic pool.";
+		when POST:
+			s = "A trading post.";
+		when MAZETRAP:
+			s = "A maze trap.";
+	otherwise:
+		s = "A bottomless pit.";		/* shouldn't get here */
+	}
+	return s;
+}
+
+/*
+ * Look:
+ *	A quick glance all around the player
+ */
+look(wakeup)
+bool wakeup;
+{
+	reg char ch;
+	reg int oldx, oldy, y, x;
+	reg struct room *rp;
+	int ey, ex, oex, oey;
+	int passcount = 0;
+	bool inpass, blind;
+
+	getyx(cw, oldy, oldx);
+	oex = player.t_oldpos.x;
+	oey = player.t_oldpos.y;
+	blind = pl_on(ISBLIND);
+	if ((oldrp != NULL && rf_on(oldrp,ISDARK)) || blind) {
+		for (x = oex - 1; x <= oex + 1; x += 1)
+			for (y = oey - 1; y <= oey + 1; y += 1)
+				if ((y != hero.y || x != hero.x) && show(y, x) == FLOOR)
+					mvwaddch(cw, y, x, ' ');
+	}
+	rp = player.t_room;
+	inpass = (rp == NULL);				/* TRUE when not in a room */
+	ey = hero.y + 1;
+	ex = hero.x + 1;
+	for (x = hero.x - 1; x <= ex; x += 1) {
+		if (x >= 0 && x <= COLS - 1) {
+			for (y = hero.y - 1; y <= ey; y += 1) {
+				if (y <= 0 || y >= LINES - 2)
+					continue;
+				if (isalpha(mvwinch(mw, y, x))) {
+					reg struct linked_list *it;
+					reg struct thing *tp;
+
+					if (wakeup || (!inpass && rf_on(rp, ISTREAS)))
+						it = wake_monster(y, x);
+					else
+						it = find_mons(y, x);
+					if (it == NULL)				/* lost monster */
+						mvaddch(y, x, FLOOR);
+					else {
+						tp = THINGPTR(it);
+						if (isatrap(tp->t_oldch = mvinch(y, x))) {
+							struct trap *trp;
+
+							if ((trp = trap_at(y,x)) == NULL)
+								break;
+							if (trp->tr_flags & ISFOUND)
+								tp->t_oldch = trp->tr_type;
+							else
+								tp->t_oldch = FLOOR;
+						}
+						if (tp->t_oldch == FLOOR && rf_on(rp,ISDARK))
+							if (!blind)
+								tp->t_oldch = ' ';
+					}
+				}
+				/*
+				 * Secret doors show as walls
+				 */
+				if ((ch = show(y, x)) == SECRETDOOR) {
+					if (inpass || y == rp->r_pos.y || y == rp->r_pos.y + rp->r_max.y - 1)
+						ch = '-';
+					else
+						ch = '|';
+				}
+				/*
+				 * Don't show room walls if he is in a passage
+				 */
+				if (!blind) {
+					if ((y == hero.y && x == hero.x) || (inpass && (ch == '-' || ch == '|')))
+						continue;
+				}
+				else
+					ch = ' ';
+				wmove(cw, y, x);
+				waddch(cw, ch);
+				if (door_stop && !firstmove && running) {
+					switch (runch) {
+						case 'h':
+							if (x == ex)
+								continue;
+						when 'j':
+							if (y == hero.y - 1)
+								continue;
+						when 'k':
+							if (y == ey)
+								continue;
+						when 'l':
+							if (x == hero.x - 1)
+								continue;
+						when 'y':
+							if ((x + y) - (hero.x + hero.y) >= 1)
+								continue;
+						when 'u':
+							if ((y - x) - (hero.y - hero.x) >= 1)
+								continue;
+						when 'n':
+							if ((x + y) - (hero.x + hero.y) <= -1)
+								continue;
+						when 'b':
+							if ((y - x) - (hero.y - hero.x) <= -1)
+								continue;
+					}
+					switch (ch) {
+						case DOOR:
+							if (x == hero.x || y == hero.y)
+								running = FALSE;
+							break;
+						case PASSAGE:
+							if (x == hero.x || y == hero.y)
+								passcount += 1;
+							break;
+						case FLOOR:
+						case '|':
+						case '-':
+						case ' ':
+							break;
+						default:
+							running = FALSE;
+							break;
+					}
+				}
+			}
+		}
+	}
+	if (door_stop && !firstmove && passcount > 1)
+		running = FALSE;
+	mvwaddch(cw, hero.y, hero.x, PLAYER);
+	wmove(cw, oldy, oldx);
+	player.t_oldpos = hero;
+	oldrp = rp;
+}
+
+/*
+ * find_obj:
+ *	find the unclaimed object at y, x
+ */
+struct linked_list *
+find_obj(y, x)
+int y, x;
+{
+	reg struct linked_list *obj;
+	reg struct object *op;
+
+	for (obj = lvl_obj; obj != NULL; obj = next(obj)) {
+		op = OBJPTR(obj);
+		if (op->o_pos.y == y && op->o_pos.x == x)
+			return obj;
+	}
+	return NULL;
+}
+
+/*
+ * eat:
+ *	Let the hero eat some food.
+ */
+eat()
+{
+	reg struct linked_list *item;
+	reg struct object *obj;
+	reg int goodfood, cursed;
+
+	if ((item = get_item("eat", FOOD)) == NULL)
+		return;
+	obj = OBJPTR(item);
+	if (obj->o_type != FOOD) {
+		msg("That's Inedible!");
+		after = FALSE;
+		return;
+	}
+	cursed = 1;
+	if (o_on(obj, ISCURSED))
+		cursed += 1;
+	else if (o_on(obj, ISBLESS))
+		cursed -= 1;
+	if (obj->o_which == FRUITFOOD) {
+		msg("My, that was a yummy %s.", fruit);
+		goodfood = 100;
+	}
+	else {
+		if (rnd(100) > 80 || o_on(obj, ISCURSED)) {
+			msg("Yuk, this food tastes like ARA.");
+			goodfood = 300;
+			him->s_exp += 1;
+			check_level();
+		}
+		else {
+			msg("Yum, that tasted good.");
+			goodfood = 200;
+		}
+	}
+	goodfood *= cursed;
+	if ((food_left += HUNGERTIME + rnd(400) - goodfood) > STOMACHSIZE)
+		food_left = STOMACHSIZE;
+	hungry_state = F_OKAY;
+	updpack();					/* update pack */
+	if (obj == cur_weapon)
+		cur_weapon = NULL;
+	del_pack(item);		/* get rid of the food */
+}
+
+/*
+ * aggravate:
+ *	aggravate all the monsters on this level
+ */
+aggravate()
+{
+	reg struct linked_list *mi;
+
+	for (mi = mlist; mi != NULL; mi = next(mi))
+		runto(&(THINGPTR(mi))->t_pos, &hero);
+}
+
+/*
+ * vowelstr:
+ * 	If string starts with a vowel, return "n" for an "an"
+ */
+char *
+vowelstr(str)
+char *str;
+{
+	switch (tolower(*str)) {
+		case 'a':
+		case 'e':
+		case 'i':
+		case 'o':
+		case 'u':
+			return "n";
+		default:
+			return "";
+	}
+}
+
+/* 
+ * is_current:
+ *	See if the object is one of the currently used items
+ */
+is_current(obj)
+struct object *obj;
+{
+	if (obj == NULL)
+		return FALSE;
+	if (obj == cur_armor || obj == cur_weapon || obj == cur_ring[LEFT]
+	  || obj == cur_ring[RIGHT]) {
+		msg("Already in use.");
+		return TRUE;
+	}
+	return FALSE;
+}
+
+/*
+ * get_dir:
+ *	Set up the direction coordinates
+ */
+get_dir()
+{
+	reg char *prompt;
+	reg bool gotit;
+
+	prompt = "Direction: ";
+	do {
+		gotit = TRUE;
+		switch (readchar()) {
+			case 'h': case'H': delta.y =  0; delta.x = -1;
+			when 'j': case'J': delta.y =  1; delta.x =  0;
+			when 'k': case'K': delta.y = -1; delta.x =  0;
+			when 'l': case'L': delta.y =  0; delta.x =  1;
+			when 'y': case'Y': delta.y = -1; delta.x = -1;
+			when 'u': case'U': delta.y = -1; delta.x =  1;
+			when 'b': case'B': delta.y =  1; delta.x = -1;
+			when 'n': case'N': delta.y =  1; delta.x =  1;
+			when ESCAPE: return FALSE;
+			otherwise:
+				mpos = 0;
+				msg(prompt);
+				gotit = FALSE;
+		}
+	} until (gotit);
+	if (pl_on(ISHUH) && rnd(100) > 80) {
+		do {
+			delta.y = rnd(3) - 1;
+			delta.x = rnd(3) - 1;
+		} while (delta.y == 0 && delta.x == 0);
+	}
+	mpos = 0;
+	return TRUE;
+}
+
+/*
+ * initfood:
+ *	Set up stuff for a food-type object
+ */
+initfood(what)
+struct object *what;
+{
+	what->o_type = FOOD;
+	what->o_group = NORMFOOD;
+	if (rnd(100) < 15)
+		what->o_group = FRUITFOOD;
+	what->o_which = what->o_group;
+	what->o_count = 1 + extras();
+	what->o_flags = ISKNOW;
+	what->o_weight = things[TYP_FOOD].mi_wght;
+	what->o_typname = things[TYP_FOOD].mi_name;
+	what->o_hplus = what->o_dplus = 0;
+	what->o_vol = itemvol(what);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/srogue/monsters.c	Thu Nov 25 12:21:41 2010 +0000
@@ -0,0 +1,386 @@
+/*
+ * File with various monster functions in it
+ *
+ * @(#)monsters.c	9.0	(rdk)	 7/17/84
+ *
+ * Super-Rogue
+ * Copyright (C) 1984 Robert D. Kindelberger
+ * All rights reserved.
+ *
+ * Based on "Rogue: Exploring the Dungeons of Doom"
+ * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
+ * All rights reserved.
+ *
+ * See the file LICENSE.TXT for full copyright and licensing information.
+ */
+
+#include "rogue.h"
+#include <ctype.h>
+#include "rogue.ext"
+
+/*
+ * rnd_mon:
+ *	Pick a monster to show up.  The lower the level,
+ *	the meaner the monster.
+ */
+rnd_mon(wander,baddie)
+bool wander;
+bool baddie;		/* TRUE when from a polymorph stick */
+{
+	reg int i, ok, cnt;
+
+	cnt = 0;
+	if (levcount == 0)			/* if only asmodeus possible */
+		return(MAXMONS);
+	if (baddie) {
+		while (1) {
+			i = rnd(MAXMONS);					/* pick ANY monster */
+			if (monsters[i].m_lev.l_lev < 0)	/* skip genocided ones */
+				continue;
+			return i;
+		}
+	}
+	ok = FALSE;
+	do {
+		/*
+		 * get a random monster from this range
+		 */
+		i = rnd(levcount);
+		/*
+		 * Only create a wandering monster if we want one
+		 * (or the count is exceeded)
+		 */
+		if (!wander || mtlev[i]->m_lev.d_wand || ++cnt > 500)
+			ok = TRUE;
+	} while(!ok);
+	return (midx(mtlev[i]->m_show));
+}
+
+/*
+ * lev_mon:
+ *	This gets all monsters possible on this level
+ */
+lev_mon()
+{
+	reg int i;
+	reg struct monster *mm;
+
+	levcount = 0;
+	for (i = 0; i < MAXMONS; i++) {
+		mm = &monsters[i];
+		if (mm->m_lev.h_lev >= level && mm->m_lev.l_lev <= level) {
+			mtlev[levcount] = mm;
+			if (++levcount >= MONRANGE)
+				break;
+		}
+	}
+	if (levcount == 0)					/* if no monsters are possible */
+		mtlev[0] = &monsters[MAXMONS];	/* then asmodeus 'A' */
+}
+
+/*
+ * new_monster:
+ *	Pick a new monster and add it to the list
+ */
+struct linked_list *
+new_monster(type, cp, treas)
+struct coord *cp;
+bool treas;
+char type;
+{
+	reg struct linked_list *item;
+	reg struct thing *tp;
+	reg struct monster *mp;
+	reg struct stats *st;
+	float killexp;		/* experience gotten for killing him */
+
+	item = new_item(sizeof(struct thing));
+	attach(mlist, item);
+	tp = THINGPTR(item);
+	st = &tp->t_stats;
+	mp = &monsters[type];		/* point to this monsters structure */
+	tp->t_type = mp->m_show;
+	tp->t_indx = type;
+	tp->t_pos = *cp;
+	tp->t_room = roomin(cp);
+	tp->t_oldch = mvwinch(cw, cp->y, cp->x);
+	tp->t_nomove = 0;
+	tp->t_nocmd = 0;
+	mvwaddch(mw, cp->y, cp->x, tp->t_type);
+
+	/*
+	 * copy monster data
+	 */
+	tp->t_stats = mp->m_stats;
+
+	/*
+	 * If below amulet level, make the monsters meaner the
+	 * deeper the hero goes.
+	 */
+	if (level > AMLEVEL)
+		st->s_lvl += ((level - AMLEVEL) / 4);
+
+	/*
+	 * If monster in treasure room, then tougher.
+	 */
+	if (treas)
+		st->s_lvl += 1;
+	if (levtype == MAZELEV)
+		st->s_lvl += 1;
+	/*
+	 * If the hero is going back up, then the monsters are more
+	 * prepared for him, so tougher.
+	 */
+	if (goingup())
+		st->s_lvl += 1;
+
+	/*
+	 * Get hit points for monster depending on his experience
+	 */
+	st->s_hpt = roll(st->s_lvl, 8);
+	st->s_maxhp = st->s_hpt;
+	/*
+	 * Adjust experience point we get for killing it by the
+	 *  strength of this particular monster by ~~ +- 50%
+	 */
+	killexp = mp->m_stats.s_exp * (0.47 + (float)st->s_hpt /
+		(8 * (float)st->s_lvl));
+
+	st->s_exp = killexp;			/* use float for accuracy */
+	if(st->s_exp < 1)
+		st->s_exp = 1;				/* minimum 1 experience point */
+	tp->t_flags = mp->m_flags;
+	/*
+	 * If monster in treasure room, then MEAN
+	 */
+	if (treas || levtype == MAZELEV)
+		tp->t_flags |= ISMEAN;
+	tp->t_turn = TRUE;
+	tp->t_pack = NULL;
+	/*
+	 * Dont wander if treas room
+	 */
+	if (iswearing(R_AGGR) && !treas)
+		runto(cp, &hero);
+	if (tp->t_type == 'M') {
+		char mch;
+
+		if (tp->t_pack != NULL)
+			mch = (OBJPTR(tp->t_pack))->o_type;
+		else {
+			switch (rnd(level >= AMLEVEL ? 9 : 8)) {
+				case 0: mch = GOLD;
+				when 1: mch = POTION;
+				when 2: mch = SCROLL;
+				when 3: mch = STAIRS;
+				when 4: mch = WEAPON;
+				when 5: mch = ARMOR;
+				when 6: mch = RING;
+				when 7: mch = STICK;
+				when 8: mch = AMULET;
+			}
+		}
+		if (treas)
+			mch = 'M';		/* no disguise in treasure room */
+		tp->t_disguise = mch;
+	}
+	return item;
+}
+
+/*
+ * wanderer:
+ *	A wandering monster has awakened and is headed for the player
+ */
+wanderer()
+{
+	reg int ch;
+	reg struct room *rp, *hr = player.t_room;
+	reg struct linked_list *item;
+	reg struct thing *tp;
+	struct coord mp;
+
+	do {
+		rp = &rooms[rnd_room()];
+		if (rp != hr || levtype == MAZELEV) {
+			mp = *rnd_pos(rp);
+			ch = mvinch(mp.y, mp.x);
+		}
+	} while (!step_ok(ch));
+	item = new_monster(rnd_mon(TRUE,FALSE), &mp, FALSE);
+	tp = THINGPTR(item);
+	tp->t_flags |= ISRUN;
+	tp->t_dest = &hero;
+}
+
+/*
+ * wake_monster:
+ *	What to do when the hero steps next to a monster
+ */
+struct linked_list *
+wake_monster(y, x)
+int y, x;
+{
+	reg struct thing *tp;
+	reg struct linked_list *it;
+	reg struct room *rp;
+	reg char ch;
+	bool treas = FALSE;
+
+	if ((it = find_mons(y, x)) == NULL)
+		return NULL;
+	tp = THINGPTR(it);
+	ch = tp->t_type;
+	/*
+	 * Every time he sees mean monster, it might start chasing him
+	 */
+	rp = player.t_room;
+	if (rp != NULL && rf_on(rp,ISTREAS)) {
+		tp->t_flags &= ~ISHELD;
+		treas = TRUE;
+	}
+	if (treas || (rnd(100) > 33 && on(*tp,ISMEAN) && off(*tp,ISHELD) &&
+	  !iswearing(R_STEALTH))) {
+		tp->t_dest = &hero;
+		tp->t_flags |= ISRUN;
+	}
+	if (ch == 'U' && pl_off(ISBLIND)) {
+		if ((rp != NULL && !rf_on(rp,ISDARK) && levtype != MAZELEV)
+		  || DISTANCE(y, x, hero.y, hero.x) < 3) {
+			if (off(*tp,ISFOUND) && !save(VS_PETRIFICATION)
+			  && !iswearing(R_SUSAB) && pl_off(ISINVINC)) {
+				msg("The umber hulk's gaze has confused you.");
+				if (pl_on(ISHUH))
+					lengthen(unconfuse,rnd(20)+HUHDURATION);
+				else
+					fuse(unconfuse,TRUE,rnd(20)+HUHDURATION);
+				player.t_flags |= ISHUH;
+			}
+			tp->t_flags |= ISFOUND;
+		}
+	}
+	/*
+	 * Hide invisible monsters
+	 */
+	if ((tp->t_flags & ISINVIS) && pl_off(CANSEE))
+		ch = mvinch(y, x);
+	/*
+	 * Let greedy ones guard gold
+	 */
+	if (on(*tp, ISGREED) && off(*tp, ISRUN)) {
+		if (rp != NULL && rp->r_goldval) {
+			tp->t_dest = &rp->r_gold;
+			tp->t_flags |= ISRUN;
+		}
+	}
+	return it;
+}
+
+/*
+ * genocide:
+ *	Eradicate a monster forevermore
+ */
+genocide()
+{
+	reg struct linked_list *ip, *nip;
+	reg struct thing *mp;
+	struct monster *mm;
+	reg int i, ii, c;
+
+	if (levcount == 0) {
+		mpos = 0;
+		msg("You cannot genocide Asmodeus !!");
+		return;
+	}
+tryagain:
+	i = TRUE;		/* assume an error now */
+	while (i) {
+		msg("Which monster (remember UPPER & lower case)?");
+		c = readchar();		/* get a char */
+		if (c == ESCAPE) {	/* he can abort (the fool) */
+			msg("");
+			return;
+		}
+		if (isalpha(c))		/* valid char here */
+			i = FALSE;		/* exit the loop */
+		else {				/* he didn't type a letter */
+			mpos = 0;
+			msg("Please specify a letter between 'A' and 'z'");
+		}
+	}
+	i = midx(c);						/* get index to monster */
+	mm = &monsters[i];
+	if (mm->m_lev.l_lev < 0) {
+		mpos = 0;
+		msg("You have already eliminated the %s.",mm->m_name);
+		goto tryagain;
+	}
+	for (ip = mlist; ip != NULL; ip = nip) {
+		mp = THINGPTR(ip);
+		nip = next(ip);
+		if (mp->t_type == c)
+			remove_monster(&mp->t_pos, ip);
+	}
+	mm->m_lev.l_lev = -1;				/* get rid of it */
+	mm->m_lev.h_lev = -1;
+	lev_mon();							/* redo monster list */
+	mpos = 0;
+	msg("You have wiped out the %s.",mm->m_name);
+}
+
+/*
+ * unhold:
+ *	Release the player from being held
+ */
+unhold(whichmon)
+char whichmon;
+{
+	switch (whichmon) {
+		case 'F':
+			fung_hit = 0;
+			strcpy(monsters[midx('F')].m_stats.s_dmg, "000d0");
+		case 'd':
+			player.t_flags &= ~ISHELD;
+	}
+}
+
+/*
+ * midx:
+ *	This returns an index to 'whichmon'
+ */
+midx(whichmon)
+char whichmon;
+{
+	if (isupper(whichmon))
+		return(whichmon - 'A');			/* 0 to 25 for uppercase */
+	else if (islower(whichmon))
+		return(whichmon - 'a' + 26);	/* 26 to 51 for lowercase */
+	else
+		return(MAXMONS);				/* 52 for Asmodeus */
+}
+
+/*
+ * monhurt:
+ *	See when monster should run or fight. Return
+ *	TRUE if hit points less than acceptable.
+ */
+monhurt(th)
+struct thing *th;
+{
+	reg int ewis, crithp, f1, f2;
+	reg struct stats *st;
+
+	st = &th->t_stats;
+	ewis = st->s_ef.a_wis;
+	if (ewis <= MONWIS)				/* stupid monsters dont know */
+		return FALSE;
+	f1 = st->s_maxhp / 4;			/* base hpt for being hurt */
+	f2 = (ewis - MONWIS) * 5 / 3;	/* bonus for smart monsters */
+	if (th->t_flags & ISWOUND)		/* if recovering from being */
+		f1 *= 2;					/* wounded, then double the base */
+	crithp = f1 + f2;				/* get critical hpt for hurt */
+	if (crithp > st->s_maxhp)		/* only up to max hpt */
+		crithp = st->s_maxhp;
+	if (st->s_hpt < crithp)			/* if < critical, then still hurt */
+		return TRUE;
+	return FALSE;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/srogue/move.c	Thu Nov 25 12:21:41 2010 +0000
@@ -0,0 +1,740 @@
+/*
+ * Hero movement commands
+ *
+ * @(#)move.c	9.0	(rdk)	 7/17/84
+ *
+ * Super-Rogue
+ * Copyright (C) 1984 Robert D. Kindelberger
+ * All rights reserved.
+ *
+ * Based on "Rogue: Exploring the Dungeons of Doom"
+ * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
+ * All rights reserved.
+ *
+ * See the file LICENSE.TXT for full copyright and licensing information.
+ */
+
+#include <ctype.h>
+#include "rogue.h"
+#include "rogue.ext"
+
+/*
+ * Used to hold the new hero position
+ */
+
+struct coord nh;
+
+/*
+ * do_run:
+ *	Start the hero running
+ */
+
+do_run(ch)
+char ch;
+{
+	running = TRUE;
+	after = FALSE;
+	runch = ch;
+}
+
+/*
+ * do_move:
+ *	Check to see that a move is legal.  If it is handle the
+ *	consequences (fighting, picking up, etc.)
+ */
+
+do_move(dy, dx)
+int dy, dx;
+{
+	reg int ch;
+	reg struct room *rp;
+
+	firstmove = FALSE;
+	curprice = -1;
+	inpool = FALSE;
+
+	if (player.t_nomove > 0) {
+		player.t_nomove -= 1;
+		msg("You are still stuck in the bear trap.");
+		return;
+	}
+	/*
+	 * Do a confused move (maybe)
+	 */
+	if ((rnd(100) < 80 && pl_on(ISHUH)) ||
+	  (iswearing(R_DELUS) && rnd(100) < 25))
+		nh = *rndmove(&player);
+	else {
+		nh.y = hero.y + dy;
+		nh.x = hero.x + dx;
+	}
+	/*
+	 * Check if he tried to move off the screen or make
+	 *  an illegal diagonal move, and stop him if he did.
+	 */
+	if (!cordok(nh.y, nh.x) ||
+	  (pl_off(ISETHER) && !diag_ok(&hero, &nh))) {
+		after = running = FALSE;
+		return;
+	}
+	if (running) {
+		ch = winat(nh.y, nh.x);
+		if (dead_end(ch)) {
+			reg int gox, goy, apsg, whichway;
+
+			gox = goy = apsg = 0;
+			if (dy == 0) {
+				ch = show(hero.y+1,hero.x);
+				if (ch == PASSAGE) {
+					apsg += 1;
+					goy = 1;
+				}
+				ch = show(hero.y-1,hero.x);
+				if (ch == PASSAGE) {
+					apsg += 1;
+					goy = -1;
+				}
+			}
+			else if (dx == 0) {
+				ch = show(hero.y,hero.x+1);
+				if (ch == PASSAGE) {
+					gox = 1;
+					apsg += 1;
+				}
+				ch = show(hero.y,hero.x-1);
+				if (ch == PASSAGE) {
+					gox = -1;
+					apsg += 1;
+				}
+			}
+			if (apsg != 1) {
+				running = after = FALSE;
+				return;
+			}
+			else {			/* can still run here */
+				nh.y = hero.y + goy;
+				nh.x = hero.x + gox;
+				whichway = (goy + 1) * 3 + gox + 1;
+				switch(whichway) {
+					case 0: runch = 'y';
+					when 1: runch = 'k';
+					when 2: runch = 'u';
+					when 3: runch = 'h';
+					when 4: runch = '.';	/* shouldn't do */
+					when 5: runch = 'l';
+					when 6: runch = 'b';
+					when 7: runch = 'j';
+					when 8: runch = 'n';
+				}
+			}
+		}
+	}
+	if (running && ce(hero, nh))
+		after = running = FALSE;
+	ch = winat(nh.y, nh.x);
+	if (pl_on(ISHELD) && ch != 'F' && ch != 'd') {
+		msg("You are being held.");
+		return;
+	}
+	if (pl_off(ISETHER)) {
+		if (isatrap(ch)) {
+			ch = be_trapped(&nh, &player);
+			if (nlmove) {
+				nlmove = FALSE;
+				return;
+			}
+			else if (ch == POOL)
+				inpool = TRUE;
+		}
+	 	else if (dead_end(ch)) {
+			after = running = FALSE;
+			return;
+		}
+		else {
+			switch(ch) {
+				case GOLD:	case POTION:	case SCROLL:
+				case FOOD:	case WEAPON:	case ARMOR:
+				case RING:	case AMULET:	case STICK:
+					running = FALSE;
+					take = ch;
+				default:
+					if (illeg_ch(ch)) {
+						running = FALSE;
+						mvaddch(nh.y, nh.x, FLOOR);
+						teleport(rndspot, &player);
+						light(&nh);
+						msg("The spatial warp disappears !");
+						return;
+					}
+			}
+		}
+	}
+	rp = roomin(&nh);
+	if (ch == DOOR) {		/* just stepped on a door */
+		running = FALSE;
+		if (rp != NULL && rf_on(rp, ISTREAS)) {
+			struct linked_list *item;
+			struct thing *tp;
+
+			for (item = mlist; item != NULL; item = next(item)) {
+				tp = THINGPTR(item);
+				if (tp->t_room == rp)
+					runto(&tp->t_pos, &hero);
+			}
+		}
+	}
+	else if (ch == STAIRS && pl_off(ISETHER))
+		running = FALSE;
+	else if (isalpha(ch) && pl_off(ISETHER)) {
+		running = FALSE;
+		fight(&nh, cur_weapon, FALSE);
+		return;
+	}
+	if (rp == NULL && player.t_room != NULL)
+		light(&hero);		/* exiting a room */
+	else if (rp != NULL && player.t_room == NULL)
+		light(&nh);			/* just entering a room */
+	if (pl_on(ISBLIND))
+		ch = ' ';
+	else
+		ch = player.t_oldch;
+	mvwaddch(cw, hero.y, hero.x, ch);
+	mvwaddch(cw, nh.y, nh.x, PLAYER);
+	hero = nh;
+	player.t_room = rp;
+	player.t_oldch = mvinch(hero.y, hero.x);
+}
+
+/*
+ * Called to illuminate a room.
+ * If it is dark, remove anything that might move.
+ */
+light(cp)
+struct coord *cp;
+{
+	reg struct room *rp;
+	reg int j, k, x, y;
+	reg char ch, rch;
+	reg struct linked_list *item;
+
+	rp = roomin(cp);
+	if (rp == NULL)
+		return;
+	if (pl_on(ISBLIND)) {
+		for (j = 0; j < rp->r_max.y; j += 1) {
+			for (k = 0; k < rp->r_max.x; k += 1) {
+				y = rp->r_pos.y + j;
+				x = rp->r_pos.x + k;
+				mvwaddch(cw, y, x, ' ');
+			}
+		}
+		look(FALSE);
+		return;
+	}
+	if (iswearing(R_LIGHT))
+		rp->r_flags &= ~ISDARK;
+	for (j = 0; j < rp->r_max.y; j += 1) {
+		for (k = 0; k < rp->r_max.x; k += 1) {
+			y = rp->r_pos.y + j;
+			x = rp->r_pos.x + k;
+			if (levtype == MAZELEV && !cansee(y, x))
+				continue;
+			ch = show(y, x);
+			wmove(cw, y, x);
+			/*
+			 * Figure out how to display a secret door
+			 */
+			if (ch == SECRETDOOR) {
+				if (j == 0 || j == rp->r_max.y - 1)
+					ch = '-';
+				else
+					ch = '|';
+			}
+			if (isalpha(ch)) {
+				struct thing *mit;
+
+				item = wake_monster(y, x);
+				if (item == NULL) {
+					ch = FLOOR;
+					mvaddch(y, x, ch);
+				}
+				else {
+					mit = THINGPTR(item);
+					if (mit->t_oldch == ' ')
+						if (!rf_on(rp,ISDARK))
+							mit->t_oldch = mvinch(y, x);
+					if (levtype == MAZELEV)
+						ch = mvinch(y, x);
+				}
+			}
+			if (rf_on(rp,ISDARK)) {
+				rch = mvwinch(cw, y, x);
+				if (isatrap(rch)) {
+					ch = rch;			/* if its a trap */
+				}
+				else {					/* try other things */
+					switch (rch) {
+						case DOOR:	case STAIRS:	case '|':
+						case '-':
+							ch = rch;
+						otherwise:
+							ch = ' ';
+					}
+				}
+			}
+			mvwaddch(cw, y, x, ch);
+		}
+	}
+}
+
+/*
+ * show:
+ *	returns what a certain thing will display as to the un-initiated
+ */
+show(y, x)
+int y, x;
+{
+	reg char ch = winat(y, x);
+	reg struct linked_list *it;
+	reg struct thing *tp;
+	reg struct trap *ta;
+
+	if (isatrap(ch)) {
+		if ((ta = trap_at(y, x)) == NULL)
+			return FLOOR;
+		if (iswearing(R_FTRAPS))
+			ta->tr_flags |= ISFOUND;
+		return ((ta->tr_flags & ISFOUND) ? ta->tr_type : FLOOR);
+	}
+	if (ch == SECRETDOOR && iswearing(R_FTRAPS)) {
+		mvaddch(y,x,DOOR);
+		return DOOR;
+	}
+	if ((it = find_mons(y, x)) != NULL) {	/* maybe a monster */
+		tp = THINGPTR(it);
+		if (ch == 'M' || (tp->t_flags & ISINVIS)) {
+			if (ch == 'M')
+				ch = tp->t_disguise;
+			else if (pl_off(CANSEE)) {
+				if (ch == 's')
+					ch = ' ';		/* shadows show as a blank */
+				else
+					ch = mvinch(y, x);	/* hide invisibles */
+			}
+		}
+	}
+	return ch;
+}
+
+/*
+ * be_trapped:
+ *	Hero or monster stepped on a trap.
+ */
+be_trapped(tc, th)
+struct thing *th;
+struct coord *tc;
+{
+	reg struct trap *trp;
+	reg int ch, ishero;
+	struct linked_list *mon;
+	char stuckee[35], seeit, sayso;
+
+	if ((trp = trap_at(tc->y, tc->x)) == NULL)
+		return;
+	ishero = (th == &player);
+	if (ishero) {
+		strcpy(stuckee, "You");
+		count = running = FALSE;
+	}
+	else {
+		sprintf(stuckee, "The %s", monsters[th->t_indx].m_name);
+	}
+	seeit = cansee(tc->y, tc->x);
+	if (seeit)
+		mvwaddch(cw, tc->y, tc->x, trp->tr_type);
+	trp->tr_flags |= ISFOUND;
+	sayso = TRUE;
+	switch (ch = trp->tr_type) {
+		case POST:
+			if (ishero) {
+				nlmove = TRUE;
+				new_level(POSTLEV);
+			}
+			else
+				goto goner;
+		when MAZETRAP:
+			if (ishero) {
+				nlmove = TRUE;
+				level += 1;
+				new_level(MAZELEV);
+				msg("You are surrounded by twisty passages!");
+			}
+			else
+				goto goner;
+		when TELTRAP:
+			nlmove = TRUE;
+			teleport(trp->tr_goto, th);
+		when TRAPDOOR:
+			if (ishero) {
+				level += 1;
+				new_level(NORMLEV);
+			}
+			else {		/* monsters get lost */
+goner:
+				ch = GONER;
+			}
+			nlmove = TRUE;
+			if (seeit && sayso)
+				msg("%s fell into a trap!", stuckee);
+		when BEARTRAP:
+			th->t_nomove += BEARTIME;
+			if (seeit) {
+				strcat(stuckee, (ishero ? " are" : " is"));
+				msg("%s caught in a bear trap.", stuckee);
+			}
+		when SLEEPTRAP:
+			if (ishero && pl_on(ISINVINC))
+				msg("You feel momentarily dizzy.");
+			else {
+				if (ishero)
+					th->t_nocmd += SLEEPTIME;
+				else
+					th->t_nomove += SLEEPTIME;
+				if (seeit)
+					msg("%s fall%s asleep in a strange white mist.",
+					  stuckee, (ishero ? "":"s"));
+			}
+		when ARROWTRAP: {
+			int resist, ac;
+			struct stats *it;
+
+			stuckee[0] = tolower(stuckee[0]);
+			it = &th->t_stats;
+			if (ishero && cur_armor != NULL)
+				ac = cur_armor->o_ac;
+			else
+				ac = it->s_arm;
+			resist = ac + getpdex(it, FALSE);
+			if (ishero && pl_on(ISINVINC))
+				resist = -100;		/* invincible is impossible to hit */
+			if (swing(3 + (level / 4), resist, 1)) {
+				if (seeit)
+					msg("%sAn arrow shot %s.", (ishero ? "Oh no! " : ""),
+					  stuckee);
+				if (ishero)
+					chg_hpt(-roll(1,6),FALSE,K_ARROW);
+				else {
+					it->s_hpt -= roll(1,6);
+					if (it->s_hpt < 1) {
+						sayso = FALSE;
+						goto goner;
+					}
+				}
+			}
+			else {
+				struct linked_list *item;
+				struct object *arrow;
+
+				if (seeit)
+					msg("An arrow shoots past %s.", stuckee);
+				item = new_thing(FALSE, WEAPON, ARROW);
+				arrow = OBJPTR(item);
+				arrow->o_hplus = 3;
+				arrow->o_dplus = rnd(2);
+				arrow->o_count = 1;
+		 		arrow->o_pos = th->t_pos;
+				fall(item, FALSE);
+			}
+		}
+		when DARTTRAP: {
+			int resist, ac;
+			struct stats *it;
+
+			stuckee[0] = tolower(stuckee[0]);
+			it = &th->t_stats;
+			if (ishero && cur_armor != NULL)
+				ac = cur_armor->o_ac;
+			else
+				ac = it->s_arm;
+			resist = ac + getpdex(it, FALSE);
+			if (ishero && pl_on(ISINVINC))
+				resist = -100;		/* invincible is impossible to hit */
+			if (swing(3 + (level / 4), resist, 0)) {
+				if (seeit)
+					msg("A small dart just hit %s.", stuckee);
+				if (ishero) {
+					if (!save(VS_POISON))
+						chg_abil(CON,-1,TRUE);
+					if (!iswearing(R_SUSTSTR))
+						chg_abil(STR,-1,TRUE);
+					chg_hpt(-roll(1, 4),FALSE,K_DART);
+				}
+				else {
+					if (!save_throw(VS_POISON, th))
+						it->s_ef.a_str -= 1;
+					it->s_hpt -= roll(1, 4);
+					if (it->s_hpt < 1) {
+						sayso = FALSE;
+						goto goner;
+					}
+				}
+			}
+			else if (seeit)
+				msg("A small dart whizzes by %s.", stuckee);
+		}
+	    when POOL:
+			if (!ishero && rnd(100) < 10) {
+				if (seeit)
+					msg("The %s drowns !!", stuckee);
+				goto goner;
+			}
+			if ((trp->tr_flags & ISGONE) && rnd(100) < 10) {
+				nlmove = TRUE;
+				if (rnd(100) < 15)
+					teleport(rndspot);	   /* teleport away */
+				else if(rnd(100) < 15 && level > 2) {
+					level -= rnd(2) + 1;
+					new_level(NORMLEV);
+					msg("You here a faint groan from below.");
+				}
+				else if(rnd(100) < 40) {
+					level += rnd(4);
+					new_level(NORMLEV);
+					msg("You find yourself in strange surroundings.");
+				}
+				else if(rnd(100) < 6 && pl_off(ISINVINC)) {
+					msg("Oh no!!! You drown in the pool!!! --More--");
+					wait_for(cw, ' ');
+					death(K_POOL);
+				}
+				else
+					 nlmove = FALSE;
+		}
+	}
+	flushinp();		/* flush typeahead */
+	return ch;
+}
+
+/*
+ * dip_it:
+ *	Dip an object into a magic pool
+ */
+dip_it()
+{
+	reg struct linked_list *what;
+	reg struct object *ob;
+	reg struct trap *tp;
+	reg int wh;
+
+	tp = trap_at(hero.y,hero.x);
+	if (tp == NULL || inpool == FALSE || (tp->tr_flags & ISGONE))
+		return;
+
+	if ((what = get_item("dip",0)) == NULL)
+		return;
+	ob = OBJPTR(what);
+	mpos = 0;
+	/*
+	 * If hero is trying to dip an object OTHER than his
+	 * current weapon, make sure that he could drop his
+	 * current weapon
+	 */
+	if (ob != cur_weapon) {
+		if (cur_weapon != NULL && o_on(cur_weapon, ISCURSED)) {
+			msg("You are unable to release your weapon.");
+			after = FALSE;
+			return;
+		}
+	}
+	if (ob == cur_armor) {
+		msg("You have to take off your armor before you can dip it.");
+		after = FALSE;
+		return;
+	}
+	else if (ob == cur_ring[LEFT] || ob == cur_ring[RIGHT]) {
+		msg("You have to take that ring off before you can dip it.");
+		after = FALSE;
+		return;
+	}
+	wh = ob->o_which;
+	tp->tr_flags |= ISGONE;
+	if (ob != NULL && o_off(ob,ISPROT)) {
+		setoflg(ob,ISKNOW);
+		switch(ob->o_type) {
+		case WEAPON:
+			if(rnd(100) < 20) {		/* enchant weapon here */
+				if (o_off(ob,ISCURSED)) {
+					ob->o_hplus += 1;
+					ob->o_dplus += 1;
+				}
+				else {		/* weapon was prev cursed here */
+					ob->o_hplus = rnd(2);
+					ob->o_dplus = rnd(2);
+				}
+				resoflg(ob,ISCURSED);
+			}
+			else if(rnd(100) < 10) {	/* curse weapon here */
+				if (o_off(ob,ISCURSED)) {
+					ob->o_hplus = -(rnd(2)+1);
+					ob->o_dplus = -(rnd(2)+1);
+				}
+				else {			/* if already cursed */
+					ob->o_hplus--;
+					ob->o_dplus--;
+				}
+				setoflg(ob,ISCURSED);
+			}			
+			msg("The %s glows for a moment.",w_magic[wh].mi_name);
+		when ARMOR:
+			if (rnd(100) < 30) {			/* enchant armor */
+				if(o_off(ob,ISCURSED))
+					ob->o_ac -= rnd(2) + 1;
+				else
+					ob->o_ac = -rnd(3)+ armors[wh].a_class;
+				resoflg(ob,ISCURSED);
+			}
+			else if(rnd(100) < 15){			/* curse armor */
+				if (o_off(ob,ISCURSED))
+					ob->o_ac = rnd(3)+ armors[wh].a_class;
+				else
+					ob->o_ac += rnd(2) + 1;
+				setoflg(ob,ISCURSED);
+			}
+			msg("The %s glows for a moment.",a_magic[wh].mi_name);
+		when STICK: {
+			int i;
+			struct rod *rd;
+
+			i = rnd(8) + 1;
+			if(rnd(100) < 25)		/* add charges */
+				ob->o_charges += i;
+			else if(rnd(100) < 10) {	/* remove charges */
+				if ((ob->o_charges -= i) < 0)
+					ob->o_charges = 0;
+			}
+			ws_know[wh] = TRUE;
+			rd = &ws_stuff[wh];
+			msg("The %s %s glows for a moment.",rd->ws_made,rd->ws_type);
+		}
+		when SCROLL:
+			s_know[wh] = TRUE;
+			msg("The '%s' scroll unfurls.",s_names[wh]);
+		when POTION:
+			p_know[wh] = TRUE;
+			msg("The %s potion bubbles for a moment.",p_colors[wh]);
+		when RING:
+			r_know[wh] = TRUE;
+			if (magring(ob)) {
+				if(rnd(100) < 25) {	 		/* enchant ring */
+					if (o_off(ob,ISCURSED))
+						ob->o_ac += rnd(2) + 1;
+					else
+						ob->o_ac = rnd(2) + 1;
+					resoflg(ob,ISCURSED);
+				}
+				else if(rnd(100) < 10) {	 /* curse ring */
+					if (o_off(ob,ISCURSED))
+						ob->o_ac = -(rnd(2) + 1);
+					else
+						ob->o_ac -= (rnd(2) + 1);
+					setoflg(ob,ISCURSED);
+				}
+			}
+			msg("The %s ring vibrates for a moment.",r_stones[wh]);
+		otherwise:
+			msg("The pool bubbles for a moment.");
+		}
+	}
+	cur_weapon = ob;	/* hero has to weild item to dip it */
+}
+
+
+/*
+ * trap_at:
+ *	Find the trap at (y,x) on screen.
+ */
+struct trap *
+trap_at(y, x)
+int y, x;
+{
+	reg struct trap *tp, *ep;
+
+	ep = &traps[ntraps];
+	for (tp = traps; tp < ep; tp += 1)
+		if (tp->tr_pos.y == y && tp->tr_pos.x == x)
+			break;
+	if (tp >= ep)
+		tp = NULL;
+	return tp;
+}
+
+/*
+ * rndmove:
+ *	move in a random direction if the monster/person is confused
+ */
+struct coord *
+rndmove(who)
+struct thing *who;
+{
+	reg int x, y, ex, ey, ch;
+	int nopen = 0;
+	struct linked_list *item;
+	static struct coord ret;  /* what we will be returning */
+	static struct coord dest;
+
+	ret = who->t_pos;
+	/*
+	 * Now go through the spaces surrounding the player and
+	 * set that place in the array to true if the space can be
+	 * moved into
+	 */
+	ey = ret.y + 1;
+	ex = ret.x + 1;
+	for (y = who->t_pos.y - 1; y <= ey; y += 1) {
+		for (x = who->t_pos.x - 1; x <= ex; x += 1) {
+			if (!cordok(y, x))
+				continue;
+			ch = winat(y, x);
+			if (step_ok(ch)) {
+				dest.y = y;
+				dest.x = x;
+				if (!diag_ok(&who->t_pos, &dest))
+					continue;
+				if (ch == SCROLL && who != &player) {
+					/*
+					 * check for scare monster scrolls
+					 */
+					item = find_obj(y, x);
+					if (item != NULL && (OBJPTR(item))->o_which == S_SCARE)
+						continue;
+				}
+				if (rnd(++nopen) == 0)
+					ret = dest;
+			}
+		}
+	}
+	return &ret;
+}
+
+/*
+ * isatrap:
+ *	Returns TRUE if this character is some kind of trap
+ */
+isatrap(ch)
+char ch;
+{
+	switch(ch) {
+		case POST:
+		case DARTTRAP:
+		case POOL:
+		case TELTRAP:
+		case TRAPDOOR:
+		case ARROWTRAP:
+		case SLEEPTRAP:
+		case BEARTRAP:
+		case MAZETRAP:
+			return TRUE;
+		default:
+			return FALSE;
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/srogue/ncx.h	Thu Nov 25 12:21:41 2010 +0000
@@ -0,0 +1,38 @@
+/*
+ * Super-Rogue
+ * Copyright (C) 1984 Robert D. Kindelberger
+ * All rights reserved.
+ *
+ * See the file LICENSE.TXT for full copyright and licensing information.
+ */
+
+/*
+# define	CBREAK 	FALSE
+# define	_IOSTRG 01
+*/
+
+/*
+ * mv functions
+ */
+#define	mvwaddch(win,y,x,ch)	VOID(wmove(win,y,x)==ERR?ERR:waddch(win,ch))
+#define	mvwgetch(win,y,x,ch)	VOID(wmove(win,y,x)==ERR?ERR:wgetch(win,ch))
+#define	mvwaddstr(win,y,x,str)	VOID(wmove(win,y,x)==ERR?ERR:waddstr(win,str))
+#define	mvwgetstr(win,y,x,str)	VOID(wmove(win,y,x)==ERR?ERR:wgetstr(win,str))
+#define	mvwinch(win,y,x)	VOID(wmove(win,y,x) == ERR ? ERR : winch(win))
+#define	mvaddch(y,x,ch)		mvwaddch(stdscr,y,x,ch)
+#define	mvgetch(y,x,ch)		mvwgetch(stdscr,y,x,ch)
+#define	mvaddstr(y,x,str)	mvwaddstr(stdscr,y,x,str)
+#define	mvgetstr(y,x,str)	mvwgetstr(stdscr,y,x,str)
+#define	mvinch(y,x)		mvwinch(stdscr,y,x)
+
+/*
+ * psuedo functions
+ */
+
+#define	clearok(win,bf)	 (win->_clear = bf)
+#define	leaveok(win,bf)	 (win->_leave = bf)
+#define	scrollok(win,bf) (win->_scroll = bf)
+#define	getyx(win,y,x)	 y = win->_cury, x = win->_curx
+#define	winch(win)	 (win->_y[win->_cury][win->_curx])
+
+WINDOW	*initscr(), *newwin();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/srogue/new_leve.c	Thu Nov 25 12:21:41 2010 +0000
@@ -0,0 +1,253 @@
+/*
+ * Do anything associated with a new dungeon level
+ *
+ * @(#)new_level.c	9.0	(rdk)	 7/17/84
+ *
+ * Super-Rogue
+ * Copyright (C) 1984 Robert D. Kindelberger
+ * All rights reserved.
+ *
+ * Based on "Rogue: Exploring the Dungeons of Doom"
+ * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
+ * All rights reserved.
+ *
+ * See the file LICENSE.TXT for full copyright and licensing information.
+ */
+
+#include "rogue.h"
+#include "rogue.ext"
+
+/*
+ * new_level:
+ *	Dig and draw a new level 
+ */
+new_level(ltype)
+int ltype;
+{
+	register i;
+	register char ch;
+	struct coord traploc;
+	struct room *rp;
+
+	if (level > max_level)
+		max_level = level;
+
+	wclear(cw);
+	wclear(mw);
+	clear();
+
+	isfight = FALSE;
+	levtype = ltype;
+
+	free_list(mlist);			/* free monster list */
+
+	if (levtype == POSTLEV)
+		do_post();
+	else {
+		lev_mon();			/* fill in monster list */
+
+		if (levtype == MAZELEV)
+			do_maze();
+		else {				/* normal levels */
+			do_rooms();		/* Draw rooms */
+			do_passages();		/* Draw passages */
+		}
+		no_food++;
+		put_things();			/* Place objects (if any) */
+	}
+	/*
+	 * Place the staircase down.
+	 */
+	stairs = *rnd_pos(&rooms[rnd_room()]);
+	mvaddch(stairs.y, stairs.x, STAIRS);
+	ntraps = 0;
+
+	if (levtype == NORMLEV)
+	{
+		struct trap *trp, *maxtrp;
+
+		/* Place the traps for normal levels only */
+
+		if (rnd(10) < level)
+		{
+			ntraps = rnd(level / 4) + 1;
+
+			if (ntraps > MAXTRAPS)
+				ntraps = MAXTRAPS;
+
+			maxtrp = &traps[ntraps];
+			for (trp = &traps[0]; trp < maxtrp; trp++)
+			{
+again:
+				switch(rnd(TYPETRAPS + 1))
+				{
+					case 0:
+						if (rnd(100) > 25)
+							goto again;
+						else
+							ch = POST;
+
+					when 1: ch = TRAPDOOR;
+					when 2: ch = BEARTRAP;
+					when 3: ch = SLEEPTRAP;
+					when 4: ch = ARROWTRAP;
+					when 5: ch = TELTRAP;
+					when 6: ch = DARTTRAP;
+					when 7: ch = MAZETRAP;
+					when 8:
+					case 9:
+						if (rnd(100) > 80)
+							goto again;
+						else
+							ch = POOL;
+				}
+				trp->tr_flags = 0;
+				traploc = *rnd_pos(&rooms[rnd_room()]);
+				mvaddch(traploc.y,traploc.x,ch);
+				trp->tr_type = ch;
+				trp->tr_pos = traploc;
+
+				if (ch == POOL || ch == POST)
+					trp->tr_flags |= ISFOUND;
+
+				if (ch==TELTRAP && rnd(100)<20 && trp<maxtrp-1)
+				{
+					struct coord newloc;
+
+					newloc = *rnd_pos(&rooms[rnd_room()]);
+					trp->tr_goto = newloc;
+					trp++;
+					trp->tr_goto = traploc;
+					trp->tr_type = TELTRAP;
+					trp->tr_pos = newloc;
+					mvaddch(newloc.y, newloc.x, TELTRAP);
+				}
+				else
+					trp->tr_goto = rndspot;
+			}
+		}
+	}
+	do
+	{
+		rp = &rooms[rnd_room()];
+		hero = *rnd_pos(rp);
+	} while(levtype==MAZELEV&&DISTANCE(hero.y,hero.x,stairs.y,stairs.x)<10);
+
+	player.t_room = rp;
+	player.t_oldch = mvinch(hero.y, hero.x);
+	light(&hero);
+	mvwaddch(cw,hero.y,hero.x,PLAYER);
+	nochange = FALSE;
+}
+
+
+/*
+ * rnd_room:
+ *	Pick a room that is really there
+ */
+rnd_room()
+{
+	register rm;
+
+	if (levtype != NORMLEV)
+		rm = 0;
+	else
+	{
+		do {
+			rm = rnd(MAXROOMS);
+		} while (rf_on(&rooms[rm],ISGONE));
+	}
+	return rm;
+}
+
+
+/*
+ * put_things:
+ *	put potions and scrolls on this level
+ */
+
+put_things()
+{
+	register i, cnt, rm;
+	struct linked_list *item;
+	struct object *cur;
+	struct coord tp;
+
+	/* Throw away stuff left on the previous level (if anything) */
+
+	free_list(lvl_obj);
+
+	/* The only way to get new stuff is to go down into the dungeon. */
+
+	if (goingup())
+		return;
+
+	/* Do MAXOBJ attempts to put things on a level */
+
+	for (i = 0; i < MAXOBJ; i++)
+	{
+		if (rnd(100) < 40)
+		{
+			item = new_thing(FALSE, ANYTHING);
+			attach(lvl_obj, item);
+			cur = OBJPTR(item);
+			cnt = 0;
+			do {
+				/* skip treasure rooms */
+				rm = rnd_room();
+				if (++cnt > 500)
+					break;
+			} while(rf_on(&rooms[rm],ISTREAS) && levtype!=MAZELEV);
+
+			tp = *rnd_pos(&rooms[rm]);
+			mvaddch(tp.y, tp.x, cur->o_type);
+			cur->o_pos = tp;
+		}
+	}
+	/*
+	 * If he is really deep in the dungeon and he hasn't found the
+	 * amulet yet, put it somewhere on the ground
+	 */
+	if (level >= AMLEVEL && !amulet && rnd(100) < 70)
+	{
+		item = new_thing(FALSE, AMULET, 0);
+		attach(lvl_obj, item);
+		cur = OBJPTR(item);
+		rm = rnd_room();
+		tp = *rnd_pos(&rooms[rm]);
+		mvaddch(tp.y, tp.x, cur->o_type);
+		cur->o_pos = tp;
+	}
+
+	for (i = 0; i < MAXROOMS; i++)		/* loop through all */
+	{
+		if (rf_on(&rooms[i],ISTREAS))	/* treasure rooms */
+		{
+			int numthgs, isfood;
+
+			numthgs = rnd(level / 3) + 6;
+			while (numthgs-- >= 0)
+			{
+				isfood = TRUE;
+				do {
+					item = new_thing(TRUE, ANYTHING);
+					cur = OBJPTR(item);
+
+					/* dont create food for */
+					if (cur->o_type == FOOD)
+						discard(item);
+
+					/* treasure rooms */
+					else
+						isfood = FALSE;
+
+				} while (isfood);
+
+				attach(lvl_obj, item);
+				tp = *rnd_pos(&rooms[i]);
+				mvaddch(tp.y, tp.x, cur->o_type);
+				cur->o_pos = tp;
+			}
+		}
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/srogue/newterm.c	Thu Nov 25 12:21:41 2010 +0000
@@ -0,0 +1,122 @@
+/*
+ * Super-Rogue
+ * Copyright (C) 1984 Robert D. Kindelberger
+ * All rights reserved.
+ *
+ * See the file LICENSE.TXT for full copyright and licensing information.
+ */
+
+#include "rogue.h"
+
+extern SGTTY _tty, _res_flg;
+extern bool NONL;
+
+raw()
+{
+/*
+	VERSION 5.0
+	_tty.c_lflag &= ~ICANON;
+	_tty.c_cc[VMIN] = 1;
+	_tty.c_cc[VTIME] = 255;
+	_tty.c_oflag &= ~OPOST;
+*/
+	_rawmode = TRUE;
+	_tty.sg_flags |= CBREAK;
+	ioctl(_tty_ch, TIOCSETP, &_tty);
+}
+
+
+noraw()
+{
+/*
+	VERSION 5.0
+	_tty.c_lflag |= ICANON;
+	_tty.c_cc[VMIN] = _res_flg.c_cc[VMIN];
+	_tty.c_cc[VTIME] = _res_flg.c_cc[VTIME];
+	_tty.c_oflag |= OPOST;
+*/
+	_rawmode = FALSE;
+	_tty.sg_flags &= ~CBREAK;
+	ioctl(_tty_ch, TIOCSETP, &_tty);
+}
+
+
+crmode()
+{
+/*
+	VERSION 5.0
+	_tty.c_lflag &= ~ICANON;
+	_tty.c_oflag |= ONLCR;
+	_tty.c_cc[VMIN] = 1;
+	_tty.c_cc[VTIME]=255;
+*/
+	_rawmode = TRUE;
+	_tty.sg_flags |= (CBREAK | CRMOD);
+	ioctl(_tty_ch, TIOCSETP, &_tty);
+}
+
+
+nocrmode()
+{
+/*
+	_tty.c_lflag |= ICANON;
+	_tty.c_cc[VMIN]=_res_flg.c_cc[VMIN];
+	_tty.c_cc[VTIME]=_res_flg.c_cc[VTIME];
+*/
+	_rawmode = FALSE;
+	_tty.sg_flags &= ~CBREAK;
+	ioctl(_tty_ch, TIOCSETP, &_tty);
+}
+
+
+echo()
+{
+	_tty.sg_flags |= ECHO;
+	_echoit=TRUE;
+	ioctl(_tty_ch, TIOCSETP, &_tty);
+}
+
+noecho()
+{
+	_tty.sg_flags &= ~ECHO;
+	_echoit = FALSE;
+	ioctl(_tty_ch, TIOCSETP, &_tty);
+}
+
+
+nl()
+{
+/*
+	VERSION 5.0
+	_tty.c_iflag |= ICRNL;
+	_tty.c_oflag |= ONLCR;
+*/
+	_tty.sg_flags |= CRMOD;
+	NONL = TRUE;
+	ioctl(_tty_ch, TIOCSETP, &_tty);
+}
+
+
+nonl()
+{
+/*
+	VERSION 5.0
+	_tty.c_iflag &= ~ICRNL;
+	_tty.c_oflag &= ~ONLCR;
+*/
+	_tty.sg_flags &= ~CRMOD;
+	NONL = FALSE;
+	ioctl(_tty_ch, TIOCSETP, &_tty);
+}
+
+savetty()
+{
+	ioctl(_tty_ch, TIOCGETP, &_tty);
+	_res_flg = _tty;
+}
+
+resetty()
+{
+	_tty = _res_flg;
+	ioctl(_tty_ch, TIOCSETP, &_tty);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/srogue/options.c	Thu Nov 25 12:21:41 2010 +0000
@@ -0,0 +1,230 @@
+/*
+ * This file has all the code for the option command.
+ *
+ * @(#)options.c	9.0	(rdk)	 7/17/84
+ *
+ * Super-Rogue
+ * Copyright (C) 1984 Robert D. Kindelberger
+ * All rights reserved.
+ *
+ * Based on "Rogue: Exploring the Dungeons of Doom"
+ * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
+ * All rights reserved.
+ *
+ * See the file LICENSE.TXT for full copyright and licensing information.
+ */
+
+#include <termios.h>
+#include <ctype.h>
+#include "rogue.h"
+#include "rogue.ext"
+
+extern struct termios terminal;
+
+/*
+ * description of an option and what to do with it
+ */
+struct optstruct {
+	char	*o_name;	/* option name */
+	char	*o_prompt;	/* prompt for interactive entry */
+	char	*o_opt;		/* pointer to thing to set */
+};
+
+typedef struct optstruct	OPTION;
+
+int	put_str(), get_str();
+
+OPTION	optlist[] = {
+	{ "name",	"Name: ",		whoami },
+	{ "fruit",	"Fruit: ",		fruit },
+	{ "file", 	"Save file: ",	file_name }
+};
+#define	NUM_OPTS	(sizeof optlist / sizeof (OPTION))
+
+/*
+ * print and then set options from the terminal
+ */
+option()
+{
+	reg OPTION	*op;
+	reg int	wh;
+
+	wclear(hw);
+	touchwin(hw);
+	/*
+	 * Display current values of options
+	 */
+	for (op = optlist; op < &optlist[NUM_OPTS]; op++) {
+		wh = op - optlist;
+		mvwaddstr(hw, wh, 0, op->o_prompt);
+		mvwaddstr(hw, wh, 16, op->o_opt);
+	}
+	/*
+	 * Set values
+	 */
+	wmove(hw, 0, 0);
+	for (op = optlist; op < &optlist[NUM_OPTS]; op++) {
+		wmove(hw, op - optlist, 16);
+		if ((wh = get_str(op->o_opt, hw))) {
+			if (wh == QUIT)
+				break;
+			else if (op > optlist) {
+				wmove(hw, op - optlist, 0);
+				op -= 2;
+			}
+			else {
+				putchar(7);
+				wmove(hw, 0, 0);
+				op -= 1;
+			}
+		}
+	}
+	/*
+	 * Switch back to original screen
+	 */
+	dbotline(hw,spacemsg);
+	restscr(cw);
+	after = FALSE;
+}
+
+
+/*
+ * get_str:
+ *	Set a string option
+ */
+#define CTRLB	2
+get_str(opt, awin)
+char *opt;
+WINDOW *awin;
+{
+	reg char *sp;
+	reg int c, oy, ox;
+	char buf[LINLEN];
+
+	draw(awin);
+	getyx(awin, oy, ox);
+	/*
+	 * loop reading in the string, and put it in a temporary buffer
+	 */
+	for (sp = buf; (c=wgetch(awin)) != '\n' && c != '\r' && c != ESCAPE;
+	  wclrtoeol(awin), draw(awin)) {
+		if (( (int)sp - (int)buf ) >= 50) {
+			*sp = '\0';			/* line was too long */
+			strucpy(opt,buf,strlen(buf));
+			mvwaddstr(awin, 0, 0, "Name was truncated --More--");
+			wclrtoeol(awin);
+			draw(awin);
+			wait_for(awin, ' ');
+			mvwprintw(awin, 0, 0, "Called: %s",opt);
+			draw(awin);
+			return NORM;
+		}
+		if (c == -1)
+			continue;
+		else if(c == terminal.c_cc[VERASE])	{	/* process erase char */
+			if (sp > buf) {
+				reg int i;
+	
+				sp--;
+				for (i = strlen(unctrl(*sp)); i; i--)
+					waddch(awin, '\b');
+			}
+			continue;
+		}
+		else if (c == terminal.c_cc[VKILL]) {   /* process kill character */
+			sp = buf;
+			wmove(awin, oy, ox);
+			continue;
+		}
+		else if (sp == buf) {
+			if (c == CTRLB)			/* CTRL - B */
+				break;
+			if (c == '~') {
+				strcpy(buf, home);
+				waddstr(awin, home);
+				sp += strlen(home);
+				continue;
+			}
+		}
+		*sp++ = c;
+		waddstr(awin, unctrl(c));
+	}
+	*sp = '\0';
+	if (sp > buf)	/* only change option if something was typed */
+		strucpy(opt, buf, strlen(buf));
+	wmove(awin, oy, ox);
+	waddstr(awin, opt);
+	waddstr(awin, "\n\r");
+	draw(awin);
+	if (awin == cw)
+		mpos += sp - buf;
+	if (c == CTRLB)
+		return MINUS;
+	if (c == ESCAPE)
+		return QUIT;
+	return NORM;
+}
+
+/*
+ * parse_opts:
+ *	Parse options from string, usually taken from the environment.
+ *	the string is a series of comma seperated values, with strings
+ *	being "name=....", with the string being defined up to a comma
+ *	or the end of the entire option string.
+ */
+
+parse_opts(str)
+char *str;
+{
+	reg char *sp;
+	reg OPTION *op;
+	reg int len;
+
+	while (*str) {
+		for (sp = str; isalpha(*sp); sp++)	/* get option name */
+			continue;
+		len = sp - str;
+		for (op = optlist; op < &optlist[NUM_OPTS]; op++) {
+			if (EQSTR(str, op->o_name, len)) {
+				reg char *start;
+	
+				for (str = sp + 1; *str == '='; str++)
+					continue;
+				if (*str == '~') {
+					strcpy(op->o_opt, home);
+					start = op->o_opt + strlen(home);
+					while (*++str == '/')
+						continue;
+				}
+				else
+					start = (char *) op->o_opt;
+				for (sp = str + 1; *sp && *sp != ','; sp++)
+					continue;
+				strucpy(start, str, sp - str);
+			}
+		}
+		/*
+		 * skip to start of next option name
+		 */
+		while (*sp && !isalpha(*sp))
+			sp++;
+		str = sp;
+	}
+}
+
+/*
+ * copy string using unctrl for things
+ */
+strucpy(s1, s2, len)
+char *s1, *s2;
+int len;
+{
+	reg char *sp;
+
+	while (len-- > 0) {
+		strcpy(s1, (sp = unctrl(*s2)));
+		s1 += strlen(sp);
+		s2++;
+	}
+	*s1 = '\0';
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/srogue/pack.c	Thu Nov 25 12:21:41 2010 +0000
@@ -0,0 +1,475 @@
+/*
+ * Routines to deal with the pack
+ *
+ * @(#)pack.c	9.0	(rdk)	 7/17/84
+ *
+ * Super-Rogue
+ * Copyright (C) 1984 Robert D. Kindelberger
+ * All rights reserved.
+ *
+ * Based on "Rogue: Exploring the Dungeons of Doom"
+ * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
+ * All rights reserved.
+ *
+ * See the file LICENSE.TXT for full copyright and licensing information.
+ */
+
+#include <ctype.h>
+#include "rogue.h"
+#include "rogue.ext"
+
+/*
+ * add_pack:
+ * Pick up an object and add it to the pack.  If the argument
+ * is non-null use it as the linked_list pointer instead of
+ * getting it off the ground.
+ */
+add_pack(item, silent)
+struct linked_list *item;
+bool silent;
+{
+	reg struct linked_list *ip, *lp;
+	reg struct object *obj, *op;
+	bool from_floor;
+	char delchar;
+
+	if (player.t_room == NULL)
+		delchar = PASSAGE;
+	else
+		delchar = FLOOR;
+	if (item == NULL) {
+		from_floor = TRUE;
+		if ((item = find_obj(hero.y, hero.x)) == NULL) {
+			mpos = 0;
+			msg("That object must have been an illusion.");
+			mvaddch(hero.y, hero.x, delchar);
+			return FALSE;
+		}
+		/*
+		 * Check for scare monster scrolls
+		 */
+		obj = OBJPTR(item);
+		if (obj->o_type == SCROLL && obj->o_which == S_SCARE) {
+			if (o_on(obj,ISFOUND)) {
+				msg("The scroll turns to dust as you pick it up.");
+				detach(lvl_obj, item);
+				discard(item);
+				mvaddch(hero.y, hero.x, delchar);	
+				return FALSE;
+			}
+		}
+	}
+	else
+		from_floor = FALSE;
+	obj = OBJPTR(item);
+	/*
+	 * See if this guy can carry any more weight
+	 */
+	if (itemweight(obj) + him->s_pack > him->s_carry) {
+		msg("You can't carry that %s.", obj->o_typname);
+		return FALSE;
+	}
+	/*
+	 * Check if there is room
+	 */
+	if (packvol + obj->o_vol > V_PACK) {
+		msg("That %s won't fit in your pack.", obj->o_typname);
+		return FALSE;
+	}
+	if (from_floor) {
+		detach(lvl_obj, item);
+		mvaddch(hero.y, hero.x, delchar);
+	}
+	item->l_prev = NULL;
+	item->l_next = NULL;
+	setoflg(obj, ISFOUND);
+	/*
+	 * start looking thru pack to find the start of items
+	 * with the same type.
+	 */
+	lp = pack;
+	for (ip = pack; ip != NULL; ip = next(ip)) {
+		op = OBJPTR(ip);
+		/*
+		 * If we find a matching type then quit.
+		 */
+		if (op->o_type == obj->o_type)
+			break;
+		if (next(ip) != NULL)
+			lp = next(lp);		/* update "previous" entry */
+	}
+	/*
+	 * If the pack was empty, just stick the item in it.
+	 */
+	if (pack == NULL) {
+		pack = item;
+		item->l_prev = NULL;
+	}
+	/*
+	 * If we looked thru the pack, but could not find an
+	 * item of the same type, then stick it at the end,
+	 * unless it was food, then put it in front.
+	 */
+	else if (ip == NULL) {
+		if (obj->o_type == FOOD) {	/* insert food at front */
+			item->l_next = pack;
+			pack->l_prev = item;
+			pack = item;
+			item->l_prev = NULL;
+		}
+		else {						/* insert other stuff at back */
+			lp->l_next = item;
+			item->l_prev = lp;
+		}
+	}
+	/*
+	 * Here, we found at least one item of the same type.
+	 * Look thru these items to see if there is one of the
+	 * same group. If so, increment the count and throw the
+	 * new item away. If not, stick it at the end of the
+	 * items with the same type. Also keep all similar
+	 * objects near each other, like all identify scrolls, etc.
+	 */
+	else {
+		struct linked_list **save;
+
+		while (ip != NULL && op->o_type == obj->o_type) {
+			if (op->o_group == obj->o_group) {
+				if (op->o_flags == obj->o_flags) {
+					op->o_count++;
+					discard(item);
+					item = ip;
+					goto picked_up;
+				}
+				else {
+					goto around;
+				}
+			}
+			if (op->o_which == obj->o_which) {
+				if (obj->o_type == FOOD)
+					ip = next(ip);
+				break;
+			}
+around:
+			ip = next(ip);
+			if (ip != NULL) {
+				op = OBJPTR(ip);
+				lp = next(lp);
+			}
+		}
+		/*
+		 * If inserting into last of group at end of pack,
+		 * just tack on the end.
+		 */
+		if (ip == NULL) {
+			lp->l_next = item;
+			item->l_prev = lp;
+		}
+		/*
+		 * Insert into the last of a group of objects
+		 * not at the end of the pack.
+		 */
+		else {
+			save = &((ip->l_prev)->l_next);
+			item->l_next = ip;
+			item->l_prev = ip->l_prev;
+			ip->l_prev = item;
+			*save = item;
+		}
+	}
+picked_up:
+	obj = OBJPTR(item);
+	if (!silent)
+		msg("%s (%c)",inv_name(obj,FALSE),pack_char(obj));
+	if (obj->o_type == AMULET)
+		amulet = TRUE;
+	updpack();				/* new pack weight & volume */
+	return TRUE;
+}
+
+/*
+ * inventory:
+ *	Show what items are in a specific list
+ */
+inventory(list, type)
+struct linked_list *list;
+int type;
+{
+	reg struct linked_list *pc;
+	reg struct object *obj;
+	reg char ch;
+	reg int cnt;
+
+	if (list == NULL) {			/* empty list */
+		msg(type == 0 ? "Empty handed." : "Nothing appropriate.");
+		return FALSE;
+	}
+	else if (next(list) == NULL) {	/* only 1 item in list */
+		obj = OBJPTR(list);
+		msg("a) %s", inv_name(obj, FALSE));
+		return TRUE;
+	}
+	cnt = 0;
+	wclear(hw);
+	for (ch = 'a', pc = list; pc != NULL; pc = next(pc), ch = npch(ch)) {
+		obj = OBJPTR(pc);
+		wprintw(hw,"%c) %s\n\r",ch,inv_name(obj, FALSE));
+		if (++cnt > LINES - 2 && next(pc) != NULL) {
+			dbotline(hw, morestr);
+			cnt = 0;
+			wclear(hw);
+		} 
+	}
+	dbotline(hw,spacemsg);
+	restscr(cw);
+	return TRUE;
+}
+
+/*
+ * pick_up:
+ *	Add something to characters pack.
+ */
+pick_up(ch)
+char ch;
+{
+	nochange = FALSE;
+	switch(ch) {
+		case GOLD:
+			money();
+		when ARMOR:
+		case POTION:
+		case FOOD:
+		case WEAPON:
+		case SCROLL:	
+		case AMULET:
+		case RING:
+		case STICK:
+			add_pack(NULL, FALSE);
+		otherwise:
+			msg("That item is ethereal !!!");
+	}
+}
+
+/*
+ * picky_inven:
+ *	Allow player to inventory a single item
+ */
+picky_inven()
+{
+	reg struct linked_list *item;
+	reg char ch, mch;
+
+	if (pack == NULL)
+		msg("You aren't carrying anything.");
+	else if (next(pack) == NULL)
+		msg("a) %s", inv_name(OBJPTR(pack), FALSE));
+	else {
+		msg("Item: ");
+		mpos = 0;
+		if ((mch = readchar()) == ESCAPE) {
+			msg("");
+			return;
+		}
+		for (ch='a',item=pack; item != NULL; item=next(item),ch=npch(ch))
+			if (ch == mch) {
+				msg("%c) %s",ch,inv_name(OBJPTR(item), FALSE));
+				return;
+			}
+		if (ch == 'A')
+			ch = 'z';
+		else
+			ch -= 1;
+		msg("Range is 'a' to '%c'", ch);
+	}
+}
+
+/*
+ * get_item:
+ *	pick something out of a pack for a purpose
+ */
+struct linked_list *
+get_item(purpose, type)
+char *purpose;
+int type;
+{
+	reg struct linked_list *obj, *pit, *savepit;
+	struct object *pob;
+	int ch, och, anr, cnt;
+
+	if (pack == NULL) {
+		msg("You aren't carrying anything.");
+		return NULL;
+	}
+	if (type != WEAPON && (type != 0 || next(pack) == NULL)) {
+		/*
+		 * see if we have any of the type requested
+		 */
+		pit = pack;
+		anr = 0;
+		for (ch = 'a'; pit != NULL; pit = next(pit), ch = npch(ch)) {
+			pob = OBJPTR(pit);
+			if (type == pob->o_type || type == 0) {
+				++anr;
+				savepit = pit;	/* save in case of only 1 */
+			}
+		}
+		if (anr == 0) {
+			msg("Nothing to %s",purpose);
+			after = FALSE;
+			return NULL;
+		}
+		else if (anr == 1) {	/* only found one of 'em */
+			do {
+				struct object *opb;
+
+				opb = OBJPTR(savepit);
+				msg("%s what (* for the item)?",purpose);
+				och = readchar();
+				if (och == '*') {
+					mpos = 0;
+					msg("%c) %s",pack_char(opb),inv_name(opb,FALSE));
+					continue;
+				}
+				if (och == ESCAPE) {
+					msg("");
+					after = FALSE;
+					return NULL;
+				}
+				if (isalpha(och) && och != pack_char(opb)) {
+					mpos = 0;
+					msg("You can't %s that !!", purpose);
+					after = FALSE;
+					return NULL;
+				}
+			} while(!isalpha(och));
+			mpos = 0;
+			return savepit;		/* return this item */
+		}
+	}
+	for (;;) {
+		msg("%s what? (* for list): ",purpose);
+		ch = readchar();
+		mpos = 0;
+		if (ch == ESCAPE) {		/* abort if escape hit */
+			after = FALSE;
+			msg("");			/* clear display */
+			return NULL;
+		}
+		if (ch == '*') {
+			wclear(hw);
+			pit = pack;		/* point to pack */
+			cnt = 0;
+			for (ch='a'; pit != NULL; pit=next(pit), ch=npch(ch)) {
+				pob = OBJPTR(pit);
+				if (type == 0 || type == pob->o_type) {
+					wprintw(hw,"%c) %s\n\r",ch,inv_name(pob,FALSE));
+					if (++cnt > LINES - 2 && next(pit) != NULL) {
+						cnt = 0;
+						dbotline(hw, morestr);
+						wclear(hw);
+					}
+				}
+			}
+			wmove(hw, LINES - 1,0);
+			wprintw(hw,"%s what? ",purpose);
+			draw(hw);		/* write screen */
+			anr = FALSE;
+			do {
+				ch = readchar();
+				if (isalpha(ch) || ch == ESCAPE)
+					anr = TRUE; 
+			} while(!anr);		/* do till we got it right */
+			restscr(cw);		/* redraw orig screen */
+			if (ch == ESCAPE) {
+				after = FALSE;
+				msg("");		/* clear top line */
+				return NULL;	/* all done if abort */
+			}
+			/* ch has item to get from pack */
+		}
+		for (obj=pack,och='a';obj!=NULL;obj=next(obj),och=npch(och))
+			if (ch == och)
+				break;
+		if (obj == NULL) {
+			if (och == 'A')
+				och = 'z';
+			else
+				och -= 1;
+			msg("Please specify a letter between 'a' and '%c'",och);
+			continue;
+		}
+		else 
+			return obj;
+	}
+}
+
+/*
+ * pack_char:
+ *	Get the character of a particular item in the pack
+ */
+char
+pack_char(obj)
+struct object *obj;
+{
+	reg struct linked_list *item;
+	reg char c;
+
+	c = 'a';
+	for (item = pack; item != NULL; item = next(item))
+		if (OBJPTR(item) == obj)
+			return c;
+		else
+			c = npch(c);
+	return '%';
+}
+
+/*
+ * idenpack:
+ *	Identify all the items in the pack
+ */
+idenpack()
+{
+	reg struct linked_list *pc;
+
+	for (pc = pack ; pc != NULL ; pc = next(pc))
+		whatis(pc);
+}
+
+
+/* 
+ * del_pack:
+ *	Take something out of the hero's pack
+ */
+del_pack(what)
+struct linked_list *what;
+{
+	reg struct object *op;
+
+	op = OBJPTR(what);
+	cur_null(op);		/* check for current stuff */
+	if (op->o_count > 1) {
+		op->o_count--;
+	}
+	else {
+		detach(pack,what);
+		discard(what);
+	}
+	updpack();
+}
+
+/*
+ * cur_null:
+ *	This updates cur_weapon etc for dropping things
+ */
+cur_null(op)
+struct object *op;
+{
+	if (op == cur_weapon)
+		cur_weapon = NULL;
+	else if (op == cur_armor)
+		cur_armor = NULL;
+	else if (op == cur_ring[LEFT])
+		cur_ring[LEFT] = NULL;
+	else if (op == cur_ring[RIGHT])
+		cur_ring[RIGHT] = NULL;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/srogue/passages.c	Thu Nov 25 12:21:41 2010 +0000
@@ -0,0 +1,281 @@
+/*
+ * Draw the connecting passages
+ *
+ * @(#)passages.c	9.0	(rdk)	 7/17/84
+ *
+ * Super-Rogue
+ * Copyright (C) 1984 Robert D. Kindelberger
+ * All rights reserved.
+ *
+ * Based on "Rogue: Exploring the Dungeons of Doom"
+ * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
+ * All rights reserved.
+ *
+ * See the file LICENSE.TXT for full copyright and licensing information.
+ */
+
+#include "rogue.h"
+#include "rogue.ext"
+
+/*
+ * do_passages:
+ *	Draw all the passages on a level.
+ */
+
+do_passages()
+{
+	reg struct rdes *r1, *r2;
+	reg int i, j;
+	reg int roomcount;
+	static struct rdes {
+		bool conn[MAXROOMS];		/* possible to connect to room i */
+		bool isconn[MAXROOMS];		/* connection was made to room i */
+		bool	ingraph;			/* this room in graph already? */
+	} rdes[MAXROOMS] = {
+		{{ 0, 1, 0, 1, 0, 0, 0, 0, 0 },{ 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 },
+		{{ 1, 0, 1, 0, 1, 0, 0, 0, 0 },{ 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 },
+		{{ 0, 1, 0, 0, 0, 1, 0, 0, 0 },{ 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 },
+		{{ 1, 0, 0, 0, 1, 0, 1, 0, 0 },{ 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 },
+		{{ 0, 1, 0, 1, 0, 1, 0, 1, 0 },{ 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 },
+		{{ 0, 0, 1, 0, 1, 0, 0, 0, 1 },{ 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 },
+		{{ 0, 0, 0, 1, 0, 0, 0, 1, 0 },{ 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 },
+		{{ 0, 0, 0, 0, 1, 0, 1, 0, 1 },{ 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 },
+		{{ 0, 0, 0, 0, 0, 1, 0, 1, 0 },{ 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 },
+	};
+
+	/*
+	 * reinitialize room graph description
+	 */
+	for (r1 = rdes; r1 < &rdes[MAXROOMS]; r1++) {
+		for (j = 0; j < MAXROOMS; j++)
+			r1->isconn[j] = FALSE;
+		r1->ingraph = FALSE;
+	}
+
+	/*
+	 * starting with one room, connect it to a random adjacent room and
+	 * then pick a new room to start with.
+	 */
+	roomcount = 1;
+	r1 = &rdes[rnd(MAXROOMS)];
+	r1->ingraph = TRUE;
+	do {
+		/*
+		 * find a room to connect with
+		 */
+		j = 0;
+		for (i = 0; i < MAXROOMS; i++)
+			if (r1->conn[i] && !rdes[i].ingraph && rnd(++j) == 0)
+				r2 = &rdes[i];
+		/*
+		 * if no adjacent rooms are outside the graph, pick a new room
+		 * to look from
+		 */
+		if (j == 0) {
+			do {
+				r1 = &rdes[rnd(MAXROOMS)];
+			} until (r1->ingraph);
+		}
+		/*
+		 * otherwise, connect new room to the graph, and draw a tunnel
+		 * to it
+		 */
+		else {
+			r2->ingraph = TRUE;
+			i = r1 - rdes;
+			j = r2 - rdes;
+			conn(i, j);
+			r1->isconn[j] = TRUE;
+			r2->isconn[i] = TRUE;
+			roomcount++;
+		}
+	} while (roomcount < MAXROOMS);
+
+	/*
+	 * attempt to add passages to the graph a random number of times so
+	 * that there isn't just one unique passage through it.
+	 */
+	for (roomcount = rnd(5); roomcount > 0; roomcount--) {
+		r1 = &rdes[rnd(MAXROOMS)];	/* a random room to look from */
+		/*
+		 * find an adjacent room not already connected
+		 */
+		j = 0;
+		for (i = 0; i < MAXROOMS; i++)
+			if (r1->conn[i] && !r1->isconn[i] && rnd(++j) == 0)
+				r2 = &rdes[i];
+		/*
+		 * if there is one, connect it and look for the next added
+		 * passage
+		 */
+		if (j != 0) {
+			i = r1 - rdes;
+			j = r2 - rdes;
+			conn(i, j);
+			r1->isconn[j] = TRUE;
+			r2->isconn[i] = TRUE;
+		}
+	}
+}
+
+/*
+ * conn:
+ *	Cconnect two rooms.
+ */
+
+conn(r1, r2)
+int r1, r2;
+{
+	reg struct room *rpf, *rpt;
+	reg char rmt, direc;
+	reg int distance, turn_spot, turn_distance, rm;
+	struct coord curr, turn_delta, spos, epos;
+
+	if (r1 < r2) {
+		rm = r1;
+		if (r1 + 1 == r2)
+			direc = 'r';
+		else
+			direc = 'd';
+	}
+	else {
+		rm = r2;
+		if (r2 + 1 == r1)
+			direc = 'r';
+		else
+			direc = 'd';
+	}
+	rpf = &rooms[rm];
+	/*
+	 * Set up the movement variables, in two cases:
+	 * first drawing one down.
+	 */
+	if (direc == 'd') {
+		rmt = rm + 3;				/* room # of dest */
+		rpt = &rooms[rmt];			/* room pointer of dest */
+		delta.x = 0;				/* direction of move */
+		delta.y = 1;
+		spos.x = rpf->r_pos.x;			/* start of move */
+		spos.y = rpf->r_pos.y;
+		epos.x = rpt->r_pos.x;			/* end of move */
+		epos.y = rpt->r_pos.y;
+		if (!rf_on(rpf,ISGONE)) {		/* if not gone pick door pos */
+			spos.x += rnd(rpf->r_max.x-2)+1;
+			spos.y += rpf->r_max.y-1;
+		}
+		if (!rf_on(rpt,ISGONE))
+			epos.x += rnd(rpt->r_max.x-2)+1;
+		distance = abs(spos.y - epos.y) - 1;	/* distance to move */
+		turn_delta.y = 0;						/* direction to turn */
+		turn_delta.x = (spos.x < epos.x ? 1 : -1);
+		turn_distance = abs(spos.x - epos.x);	/* how far to turn */
+		turn_spot = rnd(distance-1) + 1;		/* where turn starts */
+	}
+	else if (direc == 'r') {		/* setup for moving right */
+		rmt = rm + 1;
+		rpt = &rooms[rmt];
+		delta.x = 1;
+		delta.y = 0;
+		spos.x = rpf->r_pos.x;
+		spos.y = rpf->r_pos.y;
+		epos.x = rpt->r_pos.x;
+		epos.y = rpt->r_pos.y;
+		if (!rf_on(rpf,ISGONE)) {
+			spos.x += rpf->r_max.x-1;
+			spos.y += rnd(rpf->r_max.y-2)+1;
+		}
+		if (!rf_on(rpt,ISGONE))
+			epos.y += rnd(rpt->r_max.y-2)+1;
+		distance = abs(spos.x - epos.x) - 1;
+		turn_delta.y = (spos.y < epos.y ? 1 : -1);
+		turn_delta.x = 0;
+		turn_distance = abs(spos.y - epos.y);
+		turn_spot = rnd(distance-1) + 1;
+	}
+	else {
+		msg("Error in connection tables.");
+	}
+	/*
+	 * Draw in the doors on either side of the passage
+	 * or just put #'s if the rooms are gone. Set up
+	 * pointers to the connected room.
+	 */
+	rpf->r_ptr[rpf->r_nexits] = rpt;
+	if (rf_on(rpf,ISGONE)) {
+		cmov(spos);
+		addch('#');		/* gone "from" room */
+	}
+	else
+		door(rpf, &spos);	/* add the door */
+	rpt->r_ptr[rpt->r_nexits] = rpf;
+	if (rf_on(rpt,ISGONE)) {
+		cmov(epos);
+		addch('#');		/* gone "to" room */
+	}
+	else
+		door(rpt, &epos);	/* add door */
+	/*
+	 * Get ready to move...
+	 */
+	curr.x = spos.x;
+	curr.y = spos.y;
+	while(distance > 0) {
+		/*
+		 * Move to new position
+		 */
+		curr.x += delta.x;
+		curr.y += delta.y;
+		/*
+		 * Check if we are at the turn place, if so do the turn
+		 */
+		if (distance == turn_spot && turn_distance > 0) {
+			while(turn_distance-- > 0) {
+				cmov(curr);
+				addch(PASSAGE);
+				curr.x += turn_delta.x;
+				curr.y += turn_delta.y;
+			}
+		}
+		/*
+		 * Continue digging along
+		 */
+		cmov(curr);
+		addch(PASSAGE);
+		distance--;
+	}
+	curr.x += delta.x;
+	curr.y += delta.y;
+	if (!ce(curr, epos)) {
+		msg("Warning, connectivity problem on this level.");
+	}
+}
+
+/*
+ * Add a door or possibly a secret door
+ * also enters the door in the exits array of the room.
+ */
+
+door(rm, cp)
+struct room *rm;
+struct coord *cp;
+{
+	cmov(*cp);
+	addch(rnd(10) < level - 1 && rnd(100) < 20 ? SECRETDOOR : DOOR);
+	rm->r_exit[rm->r_nexits++] = *cp;
+}
+
+
+/*
+ * add_pass:
+ *	add the passages to the current window (wizard command)
+ */
+add_pass()
+{
+	reg int y, x, ch;
+
+	for (y = 1; y < LINES - 3; y++)
+		for (x = 0; x < COLS; x++)
+			if ((ch = mvinch(y, x)) == PASSAGE || ch == DOOR ||
+			  ch == SECRETDOOR)
+				mvwaddch(cw, y, x, ch);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/srogue/potions.c	Thu Nov 25 12:21:41 2010 +0000
@@ -0,0 +1,323 @@
+/*
+ * Functions for dealing with potions
+ *
+ * @(#)potions.c	9.0	(rdk)	 7/17/84
+ *
+ * Super-Rogue
+ * Copyright (C) 1984 Robert D. Kindelberger
+ * All rights reserved.
+ *
+ * Based on "Rogue: Exploring the Dungeons of Doom"
+ * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
+ * All rights reserved.
+ *
+ * See the file LICENSE.TXT for full copyright and licensing information.
+ */
+
+#include "rogue.h"
+#include "rogue.ext"
+
+/*
+ * quaff:
+ *	Let the hero drink a potion
+ */
+quaff()
+{
+	reg struct object *obj;
+	reg struct linked_list *item, *titem;
+	reg struct thing *th;
+	reg int wh;
+	char buf[LINLEN];
+	bool bless, curse;
+
+	/*
+	 * Make certain that it is somethings that we want to drink
+	 */
+	if ((item = get_item("quaff", POTION)) == NULL)
+		return;
+	obj = OBJPTR(item);
+	if (obj->o_type != POTION) {
+		msg("That's undrinkable!");
+		after = FALSE;
+		return;
+	}
+	wh = obj->o_which;
+	bless = o_on(obj, ISBLESS);
+	curse = o_on(obj, ISCURSED);
+	del_pack(item);		/* get rid of it */
+
+	/*
+	 * Calculate the effect it has on the poor guy.
+	 */
+	switch(wh) {
+	case P_CONFUSE:
+		if (!bless) {
+			if (pl_on(ISINVINC))
+				msg("You remain level-headed.");
+			else {
+				chg_abil(WIS,-1,TRUE);		/* confuse his mind */
+				if (pl_off(ISHUH)) {
+					msg("Wait, what's going on here. Huh? What? Who?");
+					if (pl_on(ISHUH))
+						lengthen(unconfuse,rnd(8)+HUHDURATION);
+					else
+						fuse(unconfuse,TRUE,rnd(8)+HUHDURATION);
+					player.t_flags |= ISHUH;
+				}
+			}
+			p_know[P_CONFUSE] = TRUE;
+		}
+	when P_POISON:
+		if (!bless) {
+			if (pl_off(ISINVINC) && !iswearing(R_SUSTSTR) &&
+			  !iswearing(R_SUSAB)) {
+				chg_abil(CON,-1,TRUE);		
+				chg_abil(STR,-(rnd(3)+1),TRUE);
+				msg("You feel very sick now.");
+			}
+			else
+				msg("You feel momentarily sick.");
+			p_know[P_POISON] = TRUE;
+		}
+	when P_HEALING:
+		if (!curse) {
+			heal_self(4, TRUE);
+			msg("You begin to feel better.");
+			if (!iswearing(R_SLOW))
+				notslow(FALSE);
+			sight(FALSE);
+			p_know[P_HEALING] = TRUE;
+		}
+	when P_STRENGTH:
+		if (!curse) {
+			msg("You feel stronger, now.  What bulging muscles!");
+			chg_abil(STR,1,TRUE);
+			p_know[P_STRENGTH] = TRUE;
+		}
+	when P_MFIND:
+		/*
+		 * Potion of monster detection - find all monsters
+		 */
+		if (mlist != NULL && !curse) {
+			dispmons();
+			mpos = 0;
+			msg("You begin to sense the presence of monsters--More--");
+			p_know[P_MFIND] = TRUE;
+			wait_for(cw,' ');
+			msg("");		/* clear line */
+		}
+		else
+			msg("You have a strange feeling for a moment, then it passes.");
+	when P_TFIND:
+		/*
+		 * Potion of magic detection.  Show the potions and scrolls
+		 */
+		if (lvl_obj != NULL && !curse) {
+			struct linked_list *mobj;
+			struct object *tp;
+			bool show;
+
+			show = FALSE;
+			wclear(hw);
+			for (mobj = lvl_obj; mobj != NULL; mobj = next(mobj)) {
+				tp = OBJPTR(mobj);
+				if (is_magic(tp)) {
+					show = TRUE;
+					mvwaddch(hw, tp->o_pos.y, tp->o_pos.x, MAGIC);
+				}
+			}
+			for(titem = mlist; titem != NULL; titem = next(titem)) {
+				reg struct linked_list *pitem;
+
+				th = THINGPTR(titem);
+				for(pitem=th->t_pack;pitem!=NULL;pitem=next(pitem)) {
+					if (is_magic(ldata(pitem))) {
+						show = TRUE;
+						mvwaddch(hw,th->t_pos.y, th->t_pos.x, MAGIC);
+					}
+				}
+			}
+			if (show) {
+				msg("You begin to sense the presence of magic.");
+				overlay(hw,cw);
+				p_know[P_TFIND] = TRUE;
+				break;
+			}
+		}
+		msg("You have a strange feeling for a moment, then it passes.");
+	when P_PARALYZE:
+		if (!bless) {
+			if (pl_on(ISINVINC))
+				msg("You feel numb for a moment.");
+			else {
+				msg("You can't move.");
+				player.t_nocmd = HOLDTIME;
+			}
+			p_know[P_PARALYZE] = TRUE;
+		}
+	when P_SEEINVIS:
+		if (!curse) {
+			int invlen = roll(40,20);
+
+			msg("This potion tastes like %s juice.", fruit);
+			if (pl_off(CANSEE)) {
+				player.t_flags |= CANSEE;
+				fuse(unsee, TRUE, invlen);
+				light(&hero);
+			}
+			else
+				lengthen(unsee, invlen);
+			sight(FALSE);
+		}
+	when P_RAISE:
+		if (!curse) {
+			msg("You suddenly feel much more skillful.");
+			p_know[P_RAISE] = TRUE;
+			chg_abil(DEX,1,TRUE);
+			chg_abil(WIS,1,TRUE);
+			chg_abil(CON,1,TRUE);
+			raise_level();
+		}
+	when P_XHEAL:
+		if (!curse) {
+			heal_self(8, TRUE);
+			if (rnd(100) < 50)
+				chg_abil(CON,1,TRUE);
+			msg("You begin to feel much better.");
+			p_know[P_XHEAL] = TRUE;
+			if (!iswearing(R_SLOW))
+				notslow(FALSE);
+			unconfuse();
+			extinguish(unconfuse);
+			sight(FALSE);
+		}
+	when P_HASTE:
+		if (!curse) {
+			add_haste(TRUE);
+			msg("You feel yourself moving much faster.");
+			p_know[P_HASTE] = TRUE;
+		}
+	when P_INVINC:
+		if (!curse) {
+			int time = rnd(400) + 350;
+
+			msg("You feel invincible.");
+			if (player.t_flags & ISINVINC)
+				lengthen(notinvinc,time);
+			else
+				fuse(notinvinc,TRUE,time);
+			player.t_flags |= ISINVINC;
+			p_know[P_INVINC] = TRUE;
+		}
+	when P_SMART:
+		if (!curse) {
+			msg("You feel more perceptive.");
+			p_know[P_SMART] = TRUE;
+			chg_abil(WIS,1,TRUE);
+		}
+	when P_RESTORE:
+		if (!curse) {
+			msg("Hey, this tastes great. You feel warm all over.");
+			him->s_re = max_stats.s_re;
+			him->s_ef = max_stats.s_re;
+			ringabil();				/* add in rings */
+			updpack();				/* update weight */
+			p_know[P_RESTORE] = TRUE;
+			extinguish(rchg_str);	/* kill restore in from ulodyte */
+		}
+	when P_BLIND:
+		if (!bless) {
+			if (pl_on(ISINVINC))
+				msg("The light dims for a moment.");
+			else {
+				chg_abil(WIS,-1,TRUE);
+				msg("A cloak of darkness falls around you.");
+				if (pl_off(ISBLIND)) {
+					player.t_flags |= ISBLIND;
+					fuse(sight, TRUE, rnd(400) + 450);
+					light(&hero);
+				}
+			}
+			p_know[P_BLIND] = TRUE;
+		}
+	when P_ETH:
+		if (!curse) {
+			int ethlen = roll(40,20);
+
+			msg("You feel more vaporous.");
+			if (pl_on(ISETHER))
+				lengthen(noteth,ethlen);
+			else
+				fuse(noteth,TRUE,ethlen);
+			player.t_flags |= ISETHER;
+			p_know[P_ETH] = TRUE;
+		}
+	when P_NOP:
+		msg("This potion tastes extremely dull.");
+	when P_DEX:
+		if (!curse) {
+			chg_abil(DEX,1,TRUE);		/* increase dexterity */
+			p_know[P_DEX] = TRUE;
+			msg("You feel much more agile.");
+		}
+	when P_REGEN:
+		if (!curse) {
+			int reglen = rnd(450) + 450;
+
+			if (pl_on(ISREGEN))
+				lengthen(notregen, reglen);
+			else
+				fuse(notregen, TRUE, reglen);
+			player.t_flags |= ISREGEN;
+			msg("You feel yourself improved.");
+			p_know[P_REGEN] = TRUE;
+		}
+	when P_DECREP:
+	case P_SUPHERO: {
+		int howmuch = rnd(3) + 1;
+
+		if (wh == P_DECREP) {
+			if (!bless) {
+				if (iswearing(R_SUSAB) || pl_on(ISINVINC)) {
+					msg("You feel momentarily woozy.");
+					howmuch = 0;
+				}
+				else {
+					msg("You feel crippled.");
+					howmuch = -howmuch;
+					if (!iswearing(R_SUSTSTR))
+						chg_abil(STR,howmuch,TRUE);
+				}
+			}
+			else
+				howmuch = 0;
+		}
+		else {			/* potion of superhero */
+			if (curse)
+				howmuch = 0;
+			msg("You feel invigorated.");
+			chg_abil(STR,howmuch,TRUE);
+		}
+		chg_abil(CON,howmuch,TRUE);
+		chg_abil(DEX,howmuch,TRUE);
+		chg_abil(WIS,howmuch,TRUE);		/* change abilities */
+		p_know[wh] = TRUE;
+	}
+	otherwise:
+		msg("What an odd tasting potion!");
+		return;
+	}
+	nochange = FALSE;
+	if (p_know[wh] && p_guess[wh]) {
+		free(p_guess[wh]);
+		p_guess[wh] = NULL;
+	}
+	else if(!p_know[wh] && p_guess[wh] == NULL) {
+		strcpy(buf, p_colors[wh]);
+		msg(callit);
+		if (get_str(buf, cw) == NORM) {
+			p_guess[wh] = new(strlen(buf) + 1);
+			strcpy(p_guess[wh], buf);
+		}
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/srogue/pstats.c	Thu Nov 25 12:21:41 2010 +0000
@@ -0,0 +1,377 @@
+/*
+ * Players status routines
+ *
+ * @(#)pstats.c	9.0	(rdk)	 7/17/84
+ *
+ * Super-Rogue
+ * Copyright (C) 1984 Robert D. Kindelberger
+ * All rights reserved.
+ *
+ * See the file LICENSE.TXT for full copyright and licensing information.
+ */
+
+#include "rogue.h"
+#include "rogue.ext"
+
+
+/*
+ * chg_hpt:
+ *	Changes players hit points
+ */
+chg_hpt(howmany, alsomax, what)
+int howmany;
+bool alsomax;
+char what;
+{
+	nochange = FALSE;
+	if(alsomax)
+		him->s_maxhp += howmany;
+	him->s_hpt += howmany;
+	if (him->s_hpt < 1) {
+		msg(" ");
+		death(what);
+	}
+}
+
+
+/*
+ * rchg_str:
+ *	Update the players real strength 
+ */
+rchg_str(amt)
+int amt;
+{
+	chg_abil(STR,amt,TRUE);
+}
+
+/*
+ * chg_abil:
+ *	Used to modify the hero's abilities
+ */
+chg_abil(what,amt,how)
+int amt, what, how;
+{
+	if (amt == 0)
+		return;
+	if (how == TRUE) {			/* real (must be 1st) */
+		updabil(what,amt,&pstats.s_re,TRUE);
+		how = FALSE;
+	}
+	updabil(what,amt,&pstats.s_ef,how);	/* effective */
+	updpack();
+	wghtchk(FALSE);
+}
+
+/*
+ * updabil:
+ *	Do the actual abilities updating
+ */
+updabil(what, amt, pst, how)
+struct real *pst;
+int what, amt, how;
+{
+	register int *wh, *mx, *mr;
+	struct real *mst, *msr;
+	bool is_str = FALSE;
+	int rtype;
+
+	msr = &him->s_re;
+	if (how == TRUE)				/* max real abilities */
+		mst = &max_stats.s_re;
+	else							/* max effective abil */
+		mst = &max_stats.s_ef;
+	switch (what) {
+		case STR:
+			is_str = TRUE;
+			wh = &pst->a_str;
+			mx = &mst->a_str;
+			mr = &msr->a_str;
+			rtype = R_ADDSTR;
+		when DEX:
+			wh = &pst->a_dex;
+			mx = &mst->a_dex;
+			mr = &msr->a_dex;
+			rtype = R_DEX;
+		when CON:
+			wh = &pst->a_con;
+			mx = &mst->a_con;
+			mr = &msr->a_con;
+			rtype = R_CONST;
+		when WIS:
+			wh = &pst->a_wis;
+			mx = &mst->a_wis;
+			mr = &msr->a_wis;
+			rtype = R_KNOW;
+		otherwise:
+			return;
+	}
+	*wh += amt;						/* update by amt */
+	if (amt < 0) {					/* if decrement */
+		if (*wh < MINABIL)			/* minimum = 3 */
+			*wh = MINABIL;
+		if (how == FALSE) {
+			if (*wh < *mr)			/* if less than real abil */
+				*wh = *mr;			/* make equal to real */
+		}
+	}
+	else {							/* increment */
+		int themax;
+
+		themax = MAXOTHER;				/* default maximum */
+		if (is_str)
+			themax = MAXSTR;			/* strength maximum */
+		if (how != TRUE)
+			themax += ringex(rtype);	/* get ring extra */
+		if (*wh > themax) {				/* see if > max (if real) */
+			*wh = themax;				/* max = 18  (24 if str) */
+		}
+		/*
+		 * Check for updating the max player stats.
+		 */
+		if (*wh > *mx)
+			*mx = *wh;
+	}
+}
+
+
+/*
+ * add_haste:
+ *	add a haste to the player
+ */
+add_haste(potion)
+bool potion;
+{
+	if (pl_on(ISHASTE)) {
+		msg("You faint from exhaustion.");
+		player.t_nocmd += rnd(8);
+		player.t_flags &= ~ISHASTE;
+		extinguish(nohaste);
+	}
+	else {
+		player.t_flags |= ISHASTE;
+		if (potion)
+			fuse(nohaste, TRUE, roll(10,10));
+		else
+			fuse(nohaste, TRUE, roll(40,20));
+	}
+}
+
+/*
+ * getpdex:
+ *	Gets players added dexterity for fighting
+ */
+getpdex(who, heave)
+struct stats *who;
+bool heave;
+{
+	reg int edex;
+
+	edex = who->s_ef.a_dex;
+	if (heave) {				/* an object was thrown here */
+		if (edex > 18)
+			return (edex - 15);
+		switch(edex) {
+			case 18: return 3;
+			case 17: return 2;
+			case 16: return 1;
+			case 15:
+			case 14:
+			case 13:
+			case 12:
+			case 11:
+			case 10:
+			case 9:
+			case 8:
+			case 7:
+			case 6: return 0;
+			case 5: return -1;
+			case 4: return -2;
+			default: return -3;
+		}
+	}
+	else {		/* object NOT thrown here (affects armor class) */
+		if (edex > 18)
+			return (14 - edex);
+		switch(edex) {
+			case 18: return -4;
+			case 17: return -3;
+			case 16: return -2;
+			case 15: return -1;
+			case 14:
+			case 13:
+			case 12:
+			case 11:
+			case 10:
+			case 9:
+			case 8: 
+			case 7: return 0;
+			case 6: return 1;
+			case 5: return 2;
+			case 4: return 3;
+			default: return 4;
+		}
+	}
+}
+
+/*
+ * getpwis:
+ *	Get a players wisdom for fighting
+ */
+getpwis(who)
+struct stats *who;
+{
+	reg int ewis;
+
+	ewis = who->s_ef.a_wis;
+	if (ewis > 18)
+		return (ewis - 14);
+	switch(ewis) {
+		case 18: return 4;
+		case 17: return 3;
+		case 16: return 2;
+		case 15: return 1;
+		case 14:
+		case 13:
+		case 12:
+		case 11:
+		case 10:
+		case 9:
+		case 8: return 0;
+		case 7:
+		case 6: return -1;
+		case 5:
+		case 4: return -2;
+		default: return -3;
+	}
+}
+
+/*
+ * getpcon:
+ *	Get added hit points from players constitution
+ */
+getpcon(who)
+struct stats *who;
+{
+	reg int econ;
+
+	econ = who->s_ef.a_con;
+	if (econ > 18)
+		return (econ - 14);
+	switch(econ) {
+		case 18: return 4;
+		case 17: return 3;
+		case 16: return 2;
+		case 15: return 1;
+		case 14:
+		case 13:
+		case 12:
+		case 11:
+		case 10:
+		case 9:
+		case 8:
+		case 7: return 0;
+		case 6:
+		case 5:
+		case 4: return -1;
+		default: return -2;
+	}
+}
+
+
+/*
+ * str_plus:
+ *	compute bonus/penalties for strength on the "to hit" roll
+ */
+str_plus(who)
+struct stats *who;
+{
+	reg int hitplus, str;
+
+	hitplus = 0;
+	str = who->s_ef.a_str;
+	if (str > 24)			/* > 24 */
+		hitplus = str - 21;
+	else if (str == 24)		/* 24 */
+		hitplus = 3;
+	else if (str > 20)		/* 21 to 23 */
+		hitplus = 2;
+	else if(str >= 17)		/* 17 to 20 */
+		hitplus = 1;
+	else if(str > 7)		/* 8 to 16 */
+		hitplus = 0;
+	else if(str > 5)		/* 6 to 7 */
+		hitplus = -1;
+	else if(str > 3)		/* 4 to 5 */
+		hitplus = -2;
+	else
+		hitplus = -3;		/* < 4 */
+	if (who == him)			/* add pack weight if hero */
+		hitplus += hitweight();
+	return hitplus;
+}
+
+
+/*
+ * add_dam:
+ *	Compute additional damage done depending on strength
+ */
+add_dam(who)
+struct stats *who;
+{
+	reg int exdam, str;
+
+	exdam = 0;
+	str = who->s_ef.a_str;
+	if (str > 24)			/* > 24 */
+		exdam = str - 18;
+	else if (str == 24)		/* 24 */
+		exdam = 6;
+	else if (str == 23)		/* 23 */
+		exdam = 5;
+	else if (str > 20)		/* 21 to 22 */
+		exdam = 4;
+	else if (str > 18)		/* 19 to 20 */
+		exdam = 3;
+	else if (str == 18)		/* 18 */
+		exdam = 2;
+	else if (str > 15)		/* 16 to 17 */
+		exdam = 1;
+	else if (str > 6)		/* 7 to 14 */
+		exdam = 0;
+	else
+		exdam = -1;			/* 3 to 6 */
+	if (who == him)
+		exdam += hungdam();		/* add hungry state if hero */
+	return exdam;
+}
+
+
+/*
+ * hungdam:
+ *	Calculate damage depending on players hungry state
+ */
+hungdam()
+{
+	switch (hungry_state) {
+		case F_OKAY:
+		case F_HUNGRY:	return 0;
+		when F_WEAK:	return -1;
+		when F_FAINT:	return -2;
+	}
+}
+
+/*
+ * heal_self:
+ *	Heal the hero.
+ */
+heal_self(factor, updmaxhp)
+int factor;
+bool updmaxhp;
+{
+	him->s_hpt += roll(him->s_lvl + getpcon(him), factor);
+	if (updmaxhp)
+		him->s_maxhp += 1;
+	if (him->s_hpt > him->s_maxhp)
+		him->s_hpt = him->s_maxhp;
+	nochange = FALSE;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/srogue/rdk.h	Thu Nov 25 12:21:41 2010 +0000
@@ -0,0 +1,10 @@
+/*
+ * Super-Rogue
+ * Copyright (C) 1984 Robert D. Kindelberger
+ * All rights reserved.
+ *
+ * See the file LICENSE.TXT for full copyright and licensing information.
+ */
+
+extern bool My_term,	/* user specied terminal	*/
+extern int _tty_ch;	/* channel with tty on it	*/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/srogue/rgdata.c	Thu Nov 25 12:21:41 2010 +0000
@@ -0,0 +1,229 @@
+/*
+ * Super-Rogue
+ * Copyright (C) 1984 Robert D. Kindelberger
+ * All rights reserved.
+ *
+ * See the file LICENSE.TXT for full copyright and licensing information.
+ */
+
+#include "global.c"
+
+main(argc,argv)
+char **argv;
+int argc;
+{
+	char *ptr;
+	int i, j, k;
+	struct magic_item *mi;
+	struct init_weps *wp;
+	struct init_armor *ar;
+	struct monster *mo;
+	FILE *fo;
+
+	/*
+	 * write to desired output file
+	 */
+	if (argc > 1) {
+		fo = fopen(argv[1], "w");
+		if (fo == NULL) {
+		printf("%s: %s not writable\n",argv[0],argv[1]);
+		exit(1);
+		}
+	}
+	else
+		fo = stdout;
+
+	/*
+	 * print total chances for armor, weapons, food, scrolls, etc
+	 */
+	fprintf(fo,"\n\n\n\n\n\n");
+	fprintf(fo,"\t	ITEM GENERAL INFO\n\n\n");
+	fprintf(fo,"NAME\t\tCHANCE\t\tWEIGHT\n\n");
+	for (mi = &things[0]; mi < &things[NUMTHINGS]; mi++) {
+		fprintf(fo,"%s\t\t",mi->mi_name);
+		i = mi->mi_prob / 10;
+		j = mi->mi_prob % 10;
+		fprintf(fo,"%2d.%1d %%\t\t",i,j);
+		i = mi->mi_wght / 10;
+		j = mi->mi_wght % 10;
+		if (i == 0 && j == 0)
+			fprintf(fo,"%3s\n","*");
+		else
+			fprintf(fo,"%3d.%1d lbs\n",i,j);
+	}
+	fprintf(fo,"\n\n\n\n\n\n\nNOTES - * means that weight depends on which one of that item type\n");
+	fprintf(fo,"	  - All items weigh 20%% more when cursed\n");
+
+	/*
+	 * print stuff about potions
+	 */
+	fprintf(fo,"\n\n\n\n\n\n");
+	fprintf(fo,"\t\t  POTION INFO\n\n\n");
+	fprintf(fo,"NAME\t\t\t\tCHANCE\t\tWORTH\n\n");
+	for (mi = &p_magic[0]; mi < &p_magic[MAXPOTIONS]; mi++) {
+		fprintf(fo,"%s\t",mi->mi_name);
+		k = strlen(mi->mi_name);
+		if (k < 8)
+			ptr = "\t\t\t";
+		else if (k >= 16)
+			ptr = "\t";
+		else
+			ptr = "\t\t";
+		fprintf(fo,"%s", ptr);
+		i = mi->mi_prob / 10;
+		j = mi->mi_prob % 10;
+		fprintf(fo,"%2d.%1d %%\t\t",i,j);
+		fprintf(fo,"%3d\n",mi->mi_worth);
+	}
+	fprintf(fo,"\n\n\n\n\nNOTE - All potions weigh 0.5 lbs\n");
+	
+
+	/*
+	 * print stuff about scrolls
+	 */
+	fprintf(fo,"\n\n\n\n\n\n");
+	fprintf(fo,"\t\t  SCROLL INFO\n\n\n");
+	fprintf(fo,"NAME\t\t\t\tCHANCE\t\tWORTH\n\n");
+	for (mi = &s_magic[0]; mi < &s_magic[MAXSCROLLS]; mi++) {
+		fprintf(fo,"%s\t",mi->mi_name);
+		k = strlen(mi->mi_name);
+		if (k < 8)
+			ptr = "\t\t\t";
+		else if (k >= 16)
+			ptr = "\t";
+		else
+			ptr = "\t\t";
+		fprintf(fo,"%s", ptr);
+		i = mi->mi_prob / 10;
+		j = mi->mi_prob % 10;
+		fprintf(fo,"%2d.%1d %%\t\t",i,j);
+		fprintf(fo,"%3d\n",mi->mi_worth);
+	}
+	fprintf(fo,"\n\n\n\n\nNOTE - All scrolls weigh 3.0 lbs\n");
+
+
+	/*
+	 * print stuff about rings
+	 */
+	fprintf(fo,"\n\n\n\n\n\n");
+	fprintf(fo,"\t\t  RING INFO\n\n\n");
+	fprintf(fo,"NAME\t\t\t\tCHANCE\t\tWORTH\n\n");
+	for (mi = &r_magic[0]; mi < &r_magic[MAXRINGS]; mi++) {
+		fprintf(fo,"%s\t",mi->mi_name);
+		k = strlen(mi->mi_name);
+		if (k < 8)
+			ptr = "\t\t\t";
+		else if (k >= 16)
+			ptr = "\t";
+		else
+			ptr = "\t\t";
+		fprintf(fo,"%s", ptr);
+		i = mi->mi_prob / 10;
+		j = mi->mi_prob % 10;
+		fprintf(fo,"%2d.%1d %%\t\t",i,j);
+		fprintf(fo,"%3d\n",mi->mi_worth);
+	}
+	fprintf(fo,"\n\n\n\n\nNOTE - All rings weigh 0.5 lbs\n");
+
+
+	/*
+	 * print stuff about sticks
+	 */
+	fprintf(fo,"\n\n\n\n\n\n");
+	fprintf(fo,"\t\t  STAFF/WAND INFO\n\n\n");
+	fprintf(fo,"NAME\t\t\t\tCHANCE\t\tWORTH\n\n");
+	for (mi = &ws_magic[0]; mi < &ws_magic[MAXSTICKS]; mi++) {
+		fprintf(fo,"%s\t",mi->mi_name);
+		k = strlen(mi->mi_name);
+		if (k < 8)
+			ptr = "\t\t\t";
+		else if (k >= 16)
+			ptr = "\t";
+		else
+			ptr = "\t\t";
+		fprintf(fo,"%s", ptr);
+		i = mi->mi_prob / 10;
+		j = mi->mi_prob % 10;
+		fprintf(fo,"%2d.%1d %%\t\t",i,j);
+		fprintf(fo,"%3d\n",mi->mi_worth);
+	}
+	fprintf(fo,"\n\n\n\n\nNOTES - All wands weigh 6.0 lbs\n");
+	fprintf(fo,"	  - All staffs weigh 10.0 lbs\n");
+	fprintf(fo,"	  - Wands contain from 4 to 8 charges\n");
+	fprintf(fo,"	  - Staffs contain from 5 to 12 charges\n");
+	fprintf(fo,"	  - Sticks of light have an additional 7 to 15 charges\n");
+
+
+	/*
+	 * print armor info
+	 */
+	fprintf(fo,"\n\n\n\n\n\n");
+	fprintf(fo,"\t\t\t\tARMOR INFO\n\n\n");
+	fprintf(fo,"NAME\t\t\t\tAC\tCHANCE\t\tWORTH\t\tWEIGHT\n\n");
+	for (ar = &armors[0]; ar < &armors[MAXARMORS]; ar++) {
+		fprintf(fo,"%s\t",ar->a_name);
+		k = strlen(ar->a_name);
+		if (k < 8)
+			ptr = "\t\t\t";
+		else if (k >= 16)
+			ptr = "\t";
+		else
+			ptr = "\t\t";
+		fprintf(fo,"%s", ptr);
+		fprintf(fo,"%2d\t",ar->a_class);
+		fprintf(fo,"%2d %%\t\t",ar->a_prob);
+		fprintf(fo,"%3d\t\t",ar->a_worth);
+		fprintf(fo,"%2d lbs\n",ar->a_wght / 10);
+	}
+	fprintf(fo,"\n\n\n\n\nNOTE - All armor becomes 50%% lighter when blessed\n");
+
+
+	/*
+	 * print stuff about weapons
+	 */
+	fprintf(fo,"\n\n\n\n\n\n");
+	fprintf(fo,"\t\t\t\t\tWEAPON INFO\n\n\n");
+	fprintf(fo,
+	   "NAME\t\t\tHIT DAMAGE\tHURL DAMAGE\tWORTH\t\tWEIGHT\n\n");
+	for (wp = &weaps[0]; wp < &weaps[MAXWEAPONS]; wp++) {
+		fprintf(fo,"%s\t",wp->w_name);
+		k = strlen(wp->w_name);
+		if (k < 8)
+			ptr = "\t\t";
+		else if (k >= 16)
+			ptr = "";
+		else
+			ptr = "\t";
+		fprintf(fo,"%s", ptr);
+		ptr = wp->w_dam;
+		i = *ptr - '0';
+		j = 0;
+		ptr += 2;
+		while (*ptr != NULL) {
+			j = j * 10 + (*ptr - '0');
+			++ptr;
+		}
+		j *= i;
+		fprintf(fo,"  %d to %d\t",i,j);
+		ptr = wp->w_hrl;
+		i = *ptr - '0';
+		j = 0;
+		ptr += 2;
+		while (*ptr != NULL) {
+			j = j * 10 + (*ptr - '0');
+			++ptr;
+		}
+		j *= i;
+		fprintf(fo,"  %d to %d\t",i,j);
+		fprintf(fo,"%4d\t\t",wp->w_worth);
+		i = wp->w_wght / 10;
+		j = wp->w_wght % 10;
+		fprintf(fo,"%2d.%1d lbs\n",i,j);
+	}
+	fprintf(fo,"\n\n\n\n\nNOTE - All weapons become 50%% lighter when blessed\n");
+
+
+	/*
+	 * print stuff about the monsters
+	 */
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/srogue/rings.c	Thu Nov 25 12:21:41 2010 +0000
@@ -0,0 +1,492 @@
+/*
+ * routines dealing specifically with rings
+ *
+ * @(#)rings.c	9.0	(rdk)	 7/17/84
+ *
+ * Super-Rogue
+ * Copyright (C) 1984 Robert D. Kindelberger
+ * All rights reserved.
+ *
+ * Based on "Rogue: Exploring the Dungeons of Doom"
+ * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
+ * All rights reserved.
+ *
+ * See the file LICENSE.TXT for full copyright and licensing information.
+ */
+
+#include "rogue.h"
+#include "rogue.ext"
+
+/*
+ * ring_on:
+ *	Put on a ring
+ */
+ring_on()
+{
+	reg struct object *obj;
+	reg struct linked_list *item;
+	reg int ring, wh;
+	char buf[LINLEN];
+	bool okring;
+
+	if (cur_ring[LEFT] != NULL && cur_ring[RIGHT] != NULL) {
+		msg("Already wearing two rings.");
+		after = FALSE;
+		return;
+	}
+	/*
+	 * Make certain that it is somethings that we want to wear
+	 */
+	if ((item = get_item("put on", RING)) == NULL)
+		return;
+	obj = OBJPTR(item);
+	if (obj->o_type != RING) {
+		msg("That won't fit on your finger.");
+		return;
+	}
+	/*
+	 * find out which hand to put it on
+	 */
+	if (is_current(obj))
+		return;
+	if (cur_ring[LEFT] == NULL && cur_ring[RIGHT] == NULL) {
+		if ((ring = gethand(FALSE)) < 0)
+			return;
+	}
+	else if (cur_ring[LEFT] == NULL)
+		ring = LEFT;
+	else
+		ring = RIGHT;
+	cur_ring[ring] = obj;
+	wh = obj->o_which;
+	/*
+	 * okring = FALSE when:
+	 * 1) ring is cursed and benefit = plus
+	 * 2) ring is blessed and benefit = minus
+	 */
+	okring = !((obj->o_ac > 0 && o_on(obj, ISCURSED)) ||
+	          (obj->o_ac < 0 && o_on(obj, ISBLESS)));
+	/*
+	 * Calculate the effect it has on the poor guy (if possible).
+	 */
+	if (okring) {
+		switch (wh) {
+			case R_SPEED:
+				if (--obj->o_ac < 0) {
+					obj->o_ac = 0;
+					setoflg(obj,ISCURSED);
+				}
+				else {
+					add_haste(FALSE);
+					msg("You find yourself moving must faster.");
+				}
+			when R_GIANT:				/* to 24 */
+				him->s_ef.a_str = MAXSTR;
+			when R_ADDSTR:
+				chg_abil(STR,obj->o_ac,FROMRING);
+			when R_KNOW:
+				chg_abil(WIS,obj->o_ac,FROMRING);
+			when R_DEX:
+				chg_abil(DEX,obj->o_ac,FROMRING);
+			when R_CONST:
+				chg_abil(CON,obj->o_ac,FROMRING);
+			when R_SEEINVIS:
+				player.t_flags |= CANSEE;
+				light(&hero);
+				mvwaddch(cw, hero.y, hero.x, PLAYER);
+			when R_AGGR:
+				aggravate();
+			when R_HEAVY:
+				updpack();			/* new pack weight */
+			when R_BLIND:
+				r_know[R_BLIND] = TRUE;
+				player.t_flags |= ISBLIND;
+				look(FALSE);
+			when R_SLOW:
+				player.t_flags |= ISSLOW;
+			when R_SAPEM:
+				fuse(sapem,TRUE,150);
+			when R_LIGHT: {
+				struct room *rop;
+
+				r_know[R_LIGHT] = TRUE;
+				if ((rop = player.t_room) != NULL) {
+					rop->r_flags &= ~ISDARK;
+					light(&hero);
+					mvwaddch(cw, hero.y, hero.x, PLAYER);
+				}
+			}
+		}
+	}
+	if (r_know[wh] && r_guess[wh]) {
+		free(r_guess[wh]);
+		r_guess[wh] = NULL;
+	}
+	else if(!r_know[wh] && r_guess[wh] == NULL) {
+		mpos = 0;
+		strcpy(buf, r_stones[wh]);
+		msg(callit);
+		if (get_str(buf, cw) == NORM) {
+			r_guess[wh] = new(strlen(buf) + 1);
+			strcpy(r_guess[wh], buf);
+		}
+	}
+	mpos = 0;
+	msg("Now wearing %s",inv_name(obj,TRUE));
+	ringfood = ring_eat();
+	nochange = FALSE;
+}
+
+
+/*
+ * ring_off:
+ *	Take off some ring
+ */
+ring_off()
+{
+	reg int ring;
+	reg struct object *obj;
+	
+	if (cur_ring[LEFT] == NULL && cur_ring[RIGHT] == NULL) {
+		msg("You're not wearing any rings.");
+		return;
+	}
+	else if (cur_ring[LEFT] == NULL)
+		ring = RIGHT;
+	else if (cur_ring[RIGHT] == NULL)
+		ring = LEFT;
+	else
+		if ((ring = gethand(TRUE)) < 0)
+			return;
+	mpos = 0;
+	obj = cur_ring[ring];
+	if (obj == NULL) {
+		msg("Not wearing such a ring.");
+		return;
+	}
+	if (dropcheck(obj)) {
+		msg("Was wearing %s", inv_name(obj, TRUE));
+		nochange = FALSE;
+		ringfood = ring_eat();
+	}
+}
+
+
+/*
+ * toss_ring:
+ *	Remove a ring and stop its effects
+ */
+toss_ring(what)
+struct object *what;
+{
+	bool okring;
+
+	/*
+	 * okring = FALSE when:
+	 * 1) ring is cursed and benefit = plus
+	 * 2) ring is blessed and benefit = minus
+	 */
+	okring = !((what->o_ac > 0 && o_on(what, ISCURSED)) ||
+	          (what->o_ac < 0 && o_on(what, ISBLESS)));
+
+	cur_ring[what == cur_ring[LEFT] ? LEFT : RIGHT] = NULL;
+	if (okring) {
+		switch (what->o_which) {
+			case R_SPEED:
+				extinguish(nohaste);
+				nohaste(FALSE);
+			when R_BLIND:
+				sight(FALSE);
+			when R_SLOW:
+				player.t_flags &= ~ISSLOW;
+			when R_SAPEM:
+				extinguish(sapem);
+			when R_GIANT:
+				him->s_ef = him->s_re;
+				ringabil();
+			when R_ADDSTR:
+				chg_abil(STR,-what->o_ac,FALSE);
+			when R_KNOW:
+				chg_abil(WIS,-what->o_ac,FALSE);
+			when R_DEX:
+				chg_abil(DEX,-what->o_ac,FALSE);
+			when R_CONST:
+				chg_abil(CON,-what->o_ac,FALSE);
+			when R_SEEINVIS:
+				player.t_flags &= ~CANSEE;
+				extinguish(unsee);
+				light(&hero);
+				mvwaddch(cw, hero.y, hero.x, PLAYER);
+		}
+	}
+}
+
+
+/*
+ * gethand:
+ *	Get a hand to wear a ring
+ */
+gethand(isrmv)
+bool isrmv;
+{
+	reg int c;
+	char *ptr;
+	struct object *obj;
+
+	while(1) {
+		addmsg("Left or Right ring");
+		if (isrmv)
+			addmsg(starlist);
+		addmsg("? ");
+		endmsg();
+		c = readchar();
+		if (isupper(c))
+			c = tolower(c);
+		if (c == '*' && isrmv) {
+			wclear(hw);
+			obj = cur_ring[LEFT];
+			if (obj != NULL)
+				ptr = inv_name(obj, TRUE);
+			else
+				ptr = "none";
+			wprintw(hw, "L)  %s\n\r",ptr);
+			obj = cur_ring[RIGHT];
+			if (obj != NULL)
+				ptr = inv_name(obj, TRUE);
+			else
+				ptr = "none";
+			wprintw(hw, "R)  %s\n\r", ptr);
+			wprintw(hw, "\n\r\nWhich hand? ");
+			draw(hw);
+			c = readchar();
+			if (isupper(c))
+				c = tolower(c);
+			restscr(cw);
+		}
+		if (c == 'l')
+			return LEFT;
+		else if (c == 'r')
+			return RIGHT;
+		else if (c == ESCAPE)
+			return -1;
+		mpos = 0;
+		msg("L or R");
+	}
+}
+
+/*
+ * ring_eat:
+ *	How much food do the hero's rings use up?
+ */
+ring_eat()
+{
+	reg struct object *lb;
+	reg int hand, i, howmuch;
+	bool addit;
+
+	howmuch = 0;
+	addit = TRUE;
+	for (i = LEFT; i <= RIGHT ; i += 1) {
+		lb = cur_ring[i];
+		if (lb != NULL) {
+			switch (lb->o_which) {
+				case R_REGEN:
+				case R_GIANT:
+					howmuch += 2;
+				when R_SPEED:
+				case R_SUSTSTR:
+				case R_SUSAB:
+					howmuch += 1;
+				when R_SEARCH:
+					howmuch += (rnd(100) < 33);
+				when R_DIGEST:
+					switch(lb->o_ac) {
+						case -3: if (rnd(100) < 25)
+									howmuch += 3;
+						when -2: if (rnd(100) < 50)
+									howmuch += 2;
+						when -1: howmuch += 1;
+						when  0: howmuch -= (rnd(100) < 50);
+						when  3: if (rnd(100) < 25)
+									howmuch -= 3;
+						when  2: if (rnd(100) < 50)
+									howmuch -= 2;
+						default: howmuch -= 1;
+					}
+				otherwise:
+					addit = FALSE;
+			}
+			if (addit) {
+				if (o_on(lb, ISBLESS))
+					howmuch -= 1;
+				else if (o_on(lb, ISCURSED))
+					howmuch += 1;
+			}
+		}
+	}
+	return howmuch;
+}
+
+
+/*
+ * ring_num:
+ *	Print ring bonuses
+ */
+char *
+ring_num(what)
+struct object *what;
+{
+	static char number[5];
+
+	number[0] = '\0';
+	if (o_on(what,ISKNOW) || o_on(what,ISPOST)) {
+		if (magring(what)) {	/* only rings with numbers */
+			number[0] = ' ';
+			strcpy(&number[1], num(what->o_ac, 0));
+		}
+	}
+	return number;
+}
+
+
+/*
+ * magring:
+ *	Returns TRUE if a ring has a number, i.e. +2
+ */
+magring(what)
+struct object *what;
+{
+	switch(what->o_which) {
+		case R_SPEED:
+		case R_ADDSTR:
+		case R_PROTECT:
+		case R_ADDHIT:
+		case R_ADDDAM:
+		case R_DIGEST:
+		case R_CONST:
+		case R_KNOW:
+		case R_DEX:
+			return TRUE;
+		default:
+			return FALSE;
+	}
+}
+
+
+/*
+ * ringabil:
+ *	Compute effective abilities due to rings
+ */
+ringabil()
+{
+	reg struct object *rptr;
+	reg int i;
+
+	for(i = LEFT; i <= RIGHT; i++) {
+		rptr = cur_ring[i];
+		if (rptr != NULL) {
+			switch(rptr->o_which) {
+				case R_ADDSTR:
+					chg_abil(STR,rptr->o_ac,FROMRING);
+				when R_DEX: 
+					chg_abil(DEX,rptr->o_ac,FROMRING);
+				when R_KNOW:
+					chg_abil(WIS,rptr->o_ac,FROMRING);
+				when R_CONST:
+					chg_abil(CON,rptr->o_ac,FROMRING);
+			}
+		}
+	}
+}
+
+
+/*
+ * init_ring:
+ *	Initialize a ring
+ */
+init_ring(what,fromwiz)
+struct object *what;
+bool fromwiz;			/* TRUE when from wizards */
+{
+	reg int much;
+
+	switch (what->o_which) {
+		case R_DIGEST:		/* -3 to +3 rings */
+		case R_ADDSTR:
+		case R_PROTECT:
+		case R_ADDHIT:
+		case R_ADDDAM:
+		case R_DEX:
+		case R_KNOW:
+		case R_CONST:
+			if (fromwiz) {
+				much = getbless();		/* get wizards response */
+			}
+			else {						/* normal users */
+				if (rnd(100) < 25)
+					much = -rnd(3) - 1;
+				else
+					much = rnd(3) + 1;
+			}
+			what->o_ac = much;
+			if (much < 0)
+				setoflg(what,ISCURSED);
+		when R_SPEED:
+			what->o_ac = rnd(4) + 1;
+		when R_AGGR:
+		case R_DELUS:
+		case R_HEAVY:
+		case R_BLIND:
+		case R_SLOW:
+		case R_SAPEM:
+		case R_TELEPORT:
+			what->o_ac = 0;
+			setoflg(what,ISCURSED);	
+		when R_GIANT:
+			what->o_ac = 25;		/* lots !! of STR */
+		otherwise:
+			what->o_ac = 1;
+	}
+	what->o_type = RING;
+	what->o_weight = things[TYP_RING].mi_wght;
+	what->o_typname = things[TYP_RING].mi_name;
+	what->o_vol = itemvol(what);
+}
+
+/*
+ * ringex:
+ *	Get extra gains from rings
+ */
+ringex(rtype)
+int rtype;
+{
+	reg int howmuch = 0;
+
+	if (isring(LEFT, rtype))
+		howmuch += cur_ring[LEFT]->o_ac;
+	if (isring(RIGHT, rtype))
+		howmuch += cur_ring[RIGHT]->o_ac;
+	return howmuch;
+}
+
+/*
+ * iswearing:
+ *	Returns TRUE when the hero is wearing a certain type of ring
+ */
+iswearing(ring)
+int ring;
+{
+	return (isring(LEFT,ring) || isring(RIGHT,ring));
+}
+
+/*
+ * isring:
+ *	Returns TRUE if a ring is on a hand
+ */
+isring(hand,ring)
+int hand, ring;
+{
+	if (cur_ring[hand] != NULL && cur_ring[hand]->o_which == ring)
+		return TRUE;
+	return FALSE;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/srogue/rip.c	Thu Nov 25 12:21:41 2010 +0000
@@ -0,0 +1,371 @@
+/*
+ * File for the fun, ends in death or a total win
+ *
+ * @(#)rip.c	9.0	(rdk)	 7/17/84
+ *
+ * Super-Rogue
+ * Copyright (C) 1984 Robert D. Kindelberger
+ * All rights reserved.
+ *
+ * Based on "Rogue: Exploring the Dungeons of Doom"
+ * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
+ * All rights reserved.
+ *
+ * See the file LICENSE.TXT for full copyright and licensing information.
+ */
+
+#include <signal.h>
+#include <ctype.h>
+#include <sys/types.h>
+#include <pwd.h>
+#include <fcntl.h>
+#include "rogue.h"
+#include "rogue.ext"
+
+static char scoreline[100];
+
+static char *rip[] = {
+"                          ____________________",
+"                         /                    \\",
+"                        /  Bob Kindelberger's  \\",
+"                       /       Graveyard        \\",
+"                      /                          \\",
+"                     /       REST IN PEACE        \\",
+"                    /                              \\",
+"                    |                              |",
+"                    |                              |",
+"                    |        Destroyed by a        |",
+"                    |                              |",
+"                    |                              |",
+"                    |                              |",
+"                    |                              |",
+"                    |                              |",
+"                    |                              |",
+"                    |                              |",
+"                   *|     *     *     *     *      |*",
+"          ________)\\\\//\\//\\)/\\//\\)/\\//\\)/\\//\\)/\\//\\//(________",
+};
+
+#define RIP_LINES (sizeof rip / (sizeof (char *)))
+
+char	*killname();
+
+/*
+ * death:
+ *	Do something really fun when he dies
+ */
+
+#include <time.h>
+death(monst)
+char monst;
+{
+	reg char dp, *killer;
+	struct tm *lt;
+	time_t date;
+	char buf[LINLEN];
+	struct tm *localtime();
+
+	time(&date);
+	lt = localtime(&date);
+	clear();
+	move(3, 0);
+	for (dp = 0; dp < RIP_LINES; dp++)
+		printw("%s\n", rip[dp]);
+	mvaddstr(10, 36 - ((strlen(whoami) + 1) / 2), whoami);
+	killer = killname(monst);
+	mvaddstr(12, 43, vowelstr(killer));
+	mvaddstr(14, 36 - ((strlen(killer) + 1) / 2), killer);
+	purse -= purse/10;
+	sprintf(buf, "%d Gold Pieces", purse);
+	mvaddstr(16, 36 - ((strlen(buf) + 1) / 2), buf);
+	sprintf(prbuf, "%d/%d/%d", lt->tm_mon + 1, lt->tm_mday, 1900+lt->tm_year);
+	mvaddstr(18, 32, prbuf);
+	move(LINES-1, 0);
+	refresh();
+	score(purse, KILLED, monst);
+	byebye(0);
+}
+
+/*
+ * top ten entry structure
+ */
+static struct sc_ent {
+	int sc_score;			/* gold */
+	char sc_name[LINLEN];		/* players name */
+	int sc_flags;			/* reason for being here */
+	int sc_level;			/* dungeon level */
+	int sc_uid;			/* user ID */
+	unsigned char sc_monster;       /* killer */
+	int sc_explvl;			/* experience level */
+	long int sc_exppts;		/* experience points */
+	time_t sc_date;			/* time this score was posted */
+} top_ten[10];
+
+char *reason[] = {
+	"Killed",
+	"Chickened out",
+	"A Total Winner"
+};
+int oldpurse;
+
+/*
+ * score:
+ *	Figure score and post it.
+ */
+score(amount, aflag, monst)
+char monst;
+int amount, aflag;
+{
+	reg struct sc_ent *scp, *sc2;
+	reg int i, fd, prflags = 0;
+	reg FILE *outf;
+	char *packend;
+
+	signal(SIGINT, byebye);
+	signal(SIGQUIT, byebye);
+	if (aflag != WINNER) {
+		if (aflag == CHICKEN)
+			packend = "when you chickened out";
+		else
+			packend = "at your untimely demise";
+		mvaddstr(LINES - 1, 0, retstr);
+		refresh();
+		wgetnstr(stdscr,prbuf,80);
+		oldpurse = purse;
+		showpack(FALSE, packend);
+	}
+	/*
+	 * Open file and read list
+	 */
+	if ((fd = open(scorefile, O_RDWR | O_CREAT, 0666)) < 0)
+		return;
+	outf = (FILE *) fdopen(fd, "w");
+	for (scp = top_ten; scp <= &top_ten[9]; scp++) {
+		scp->sc_score = 0;
+		for (i = 0; i < 80; i++)
+			scp->sc_name[i] = rnd(255);
+		scp->sc_flags = rnd(255);
+		scp->sc_level = rnd(255);
+		scp->sc_monster = rnd(255);
+		scp->sc_uid = rnd(255);
+		scp->sc_date = rnd(255);
+	}
+	mvaddstr(LINES - 1, 0, retstr);
+	refresh();
+	wgetnstr(stdscr,prbuf,80);
+	if (author() || wizard)
+		if (strcmp(prbuf, "names") == 0)
+			prflags = 1;
+        for(i = 0; i < 10; i++)
+        {
+            unsigned int mon;
+
+            encread((char *) &top_ten[i].sc_name, LINLEN, fd);
+            encread((char *) scoreline, 100, fd);
+            sscanf(scoreline, " %d %d %d %d %u %d %ld %lx \n",
+                &top_ten[i].sc_score,   &top_ten[i].sc_flags,
+                &top_ten[i].sc_level,   &top_ten[i].sc_uid,
+                &mon,                   &top_ten[i].sc_explvl,
+                &top_ten[i].sc_exppts,  &top_ten[i].sc_date);
+            top_ten[i].sc_monster = mon;
+        }
+	/*
+	 * Insert it in list if need be
+	 */
+	if (!waswizard) {
+		for (scp = top_ten; scp <= &top_ten[9]; scp++)
+			if (amount > scp->sc_score)
+				break;
+			if (scp <= &top_ten[9]) {
+				for (sc2 = &top_ten[9]; sc2 > scp; sc2--)
+					*sc2 = *(sc2-1);
+				scp->sc_score = amount;
+				strcpy(scp->sc_name, whoami);
+				scp->sc_flags = aflag;
+				if (aflag == WINNER)
+					scp->sc_level = max_level;
+				else
+					scp->sc_level = level;
+				scp->sc_monster = monst;
+				scp->sc_uid = playuid;
+				scp->sc_explvl = him->s_lvl;
+				scp->sc_exppts = him->s_exp;
+				time(&scp->sc_date);
+		}
+	}
+	ignore();
+	fseek(outf, 0L, 0);
+        for(i = 0; i < 10; i++)
+        {
+            memset(scoreline,0,100);
+            encwrite((char *) top_ten[i].sc_name, LINLEN, outf);
+            sprintf(scoreline, " %d %d %d %d %u %d %ld %lx \n",
+                top_ten[i].sc_score, top_ten[i].sc_flags,
+                top_ten[i].sc_level, top_ten[i].sc_uid,
+                top_ten[i].sc_monster, top_ten[i].sc_explvl,
+                top_ten[i].sc_exppts, top_ten[i].sc_date);
+            encwrite((char *) scoreline, 100, outf);
+        }
+	fclose(outf);
+	signal(SIGINT, byebye);
+	signal(SIGQUIT, byebye);
+	clear();
+	refresh();
+	endwin();
+	showtop(prflags);		/* print top ten list */
+}
+
+/*
+ * showtop:
+ *	Display the top ten on the screen
+ */
+showtop(showname)
+int showname;
+{
+	reg int fd, i;
+	char *killer;
+	struct sc_ent *scp;
+
+	if ((fd = open(scorefile, O_RDONLY)) < 0)
+		return FALSE;
+       
+        for(i = 0; i < 10; i++)
+        {
+            unsigned int mon;
+            encread((char *) &top_ten[i].sc_name, LINLEN, fd);
+            encread((char *) scoreline, 100, fd);
+            sscanf(scoreline, " %d %d %d %d %u %d %ld %lx \n",
+                &top_ten[i].sc_score,   &top_ten[i].sc_flags,
+                &top_ten[i].sc_level,   &top_ten[i].sc_uid,
+                &mon,                   &top_ten[i].sc_explvl,
+                &top_ten[i].sc_exppts,  &top_ten[i].sc_date);
+            top_ten[i].sc_monster = mon;
+        }
+	close(fd);
+	printf("Top Ten Adventurers:\nRank\tScore\tName\n");
+	for (scp = top_ten; scp <= &top_ten[9]; scp++) {
+		if (scp->sc_score > 0) {
+			printf("%d\t%d\t%s: %s\t\t--> %s on level %d",
+			  scp - top_ten + 1, scp->sc_score, scp->sc_name,
+			  ctime(&scp->sc_date), reason[scp->sc_flags],
+			  scp->sc_level);
+			if (scp->sc_flags == KILLED) {
+				killer = killname(scp->sc_monster);
+				printf(" by a%s %s",vowelstr(killer), killer);
+			}
+			printf(" [Exp: %d/%ld]",scp->sc_explvl,scp->sc_exppts);
+			if (showname) {
+				struct passwd *pp, *getpwuid();
+
+				if ((pp = getpwuid(scp->sc_uid)) == NULL)
+					printf(" (%d)\n", scp->sc_uid);
+				else
+					printf(" (%s)\n", pp->pw_name);
+			}
+			else
+				printf("\n");
+		}
+	}
+	return TRUE;
+}
+
+/*
+ * total_winner:
+ *	The hero made it back out alive
+ */
+total_winner()
+{
+	clear();
+addstr("                                                               \n");
+addstr("  @   @               @   @           @          @@@  @     @  \n");
+addstr("  @   @               @@ @@           @           @   @     @  \n");
+addstr("  @   @  @@@  @   @   @ @ @  @@@   @@@@  @@@      @  @@@    @  \n");
+addstr("   @@@@ @   @ @   @   @   @     @ @   @ @   @     @   @     @  \n");
+addstr("      @ @   @ @   @   @   @  @@@@ @   @ @@@@@     @   @     @  \n");
+addstr("  @   @ @   @ @  @@   @   @ @   @ @   @ @         @   @  @     \n");
+addstr("   @@@   @@@   @@ @   @   @  @@@@  @@@@  @@@     @@@   @@   @  \n");
+addstr("                                                               \n");
+addstr("     Congratulations, you have made it to the light of day!    \n");
+addstr("\nYou have joined the elite ranks of those who have escaped the\n");
+addstr("Dungeons of Doom alive.  You journey home and sell all your loot at\n");
+addstr("a great profit and are admitted to the fighters guild.\n");
+
+	mvaddstr(LINES - 1, 0,spacemsg);
+	refresh();
+	wait_for(stdscr, ' ');
+	clear();
+	oldpurse = purse;
+	showpack(TRUE, NULL);
+	score(purse, WINNER, 0);
+	byebye(0);
+}
+
+/*
+ * showpack:
+ *	Display the contents of the hero's pack
+ */
+showpack(winner, howso)
+bool winner;
+char *howso;
+{
+	reg char *iname;
+	reg int cnt, worth, ch;
+	reg struct linked_list *item;
+	reg struct object *obj;
+
+	idenpack();
+	cnt = 1;
+	clear();
+	if (winner)
+		mvaddstr(0, 0, "   Worth  Item");
+	else
+		mvprintw(0, 0, "Contents of your pack %s:\n",howso);
+	ch = 'a';
+	for (item = pack; item != NULL; item = next(item)) {
+		obj = OBJPTR(item);
+		iname = inv_name(obj, FALSE);
+		if (winner) {
+			worth = get_worth(obj);
+			worth *= obj->o_count;
+			mvprintw(cnt, 0, "  %6d  %s",worth,iname);
+			purse += worth;
+		}
+		else {
+			mvprintw(cnt, 0, "%c) %s\n",ch,iname);
+			ch = npch(ch);
+		}
+		if (++cnt >= LINES - 2 && next(item) != NULL) {
+			cnt = 1;
+			mvaddstr(LINES - 1, 0, morestr);
+			refresh();
+			wait_for(stdscr, ' ');
+			clear();
+		}
+	}
+	mvprintw(cnt + 1,0,"--- %d  Gold Pieces ---",oldpurse);
+	refresh();
+}
+
+/*
+ * killname:
+ *	Returns what the hero was killed by.
+ */
+char *
+killname(monst)
+unsigned char monst;
+{
+	if (monst < MAXMONS + 1)
+		return monsters[monst].m_name;
+	else		/* things other than monsters */
+		switch (monst) {
+			case K_ARROW:	return "crooked arrow";
+			case K_DART:	return "sharp dart";
+			case K_BOLT:	return "jagged bolt";
+			case K_POOL:	return "magic pool";
+			case K_ROD:	return "exploding rod";
+			case K_SCROLL:	return "burning scroll";
+			case K_STONE: 	return "transmogrification to stone";
+			case K_STARVE:	return "starvation";
+	}
+	return "Bob Kindelberger";
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/srogue/rogue.ext	Thu Nov 25 12:21:41 2010 +0000
@@ -0,0 +1,48 @@
+EXTTHG player;
+EXTWEP weaps[];
+EXTARM armors[];
+EXTMON monsters[], *mtlev[];
+EXTTRAP *trap_at(), traps[];
+EXTROOM *roomin(), *oldrp, rooms[];
+EXTCORD *rndmove(), *rnd_pos(), delta, stairs, oldpos, rndspot;
+EXTLKL *mlist, *lvl_obj, *new_item(), *new_thing(), *new_monster();
+EXTLKL *find_mons(), *wake_monster(), *find_obj(), *get_item();
+EXTOBJ *cur_armor, *cur_weapon, *cur_ring[];
+EXTMAG r_magic[], s_magic[], ws_magic[], p_magic[];
+EXTMAG things[], a_magic[], w_magic[];
+EXTINT max_hp, quiet, food_left, hungry_state, level, max_level;
+EXTINT foodlev, total, count, demoncnt, fung_hit, ntraps;
+EXTINT lastscore, purse, mpos, seed, dnum, no_food, packvol, playuid;
+EXTINT curprice, trader, group, levcount, levtype, ringfood, playgid;
+EXTINT chkstairs(), rollwand(), swander(), notslow(), notfight(), rnd();
+EXTINT rchg_str(), wghtchk(), stomach(), doctor(), runners(), status(), sight();
+extern void quit(), auto_save(), endit(), byebye(), game_err();
+EXTINT prntfile(), unconfuse(), sapem();
+EXTINT noteth(), notregen(), notinvinc(), unsee(), nohaste(), npch();
+EXTBOOL running, nochange, after, inwhgt, isfight, firstmove, nlmove;
+EXTBOOL wizard, waswizard, in_shell, amulet, door_stop, playing;
+EXTBOOL notify, ws_know[], p_know[], s_know[], r_know[], inpool;
+EXTCHAR home[], file_name[], whoami[], fruit[], curpurch[], scorefile[];
+EXTCHAR *r_stones[], *p_colors[], *s_names[], *ws_type[], *ws_made[];
+EXTCHAR *ws_guess[], *s_guess[], *r_guess[], *p_guess[];/*, *unctrl();*/
+EXTCHAR morestr[], prbuf[], huh[], *identify(), *vowelstr();
+EXTCHAR *new(), *strcpy(), *strcat(), *inv_name(), pack_char(), *prname();
+EXTCHAR *num(), *getenv(), *tr_name(), *release, take, runch;
+EXTCHAR retstr[], wizstr[], spacemsg[], illegal[], callit[], starlist[];
+EXTSTAT max_stats, *him;
+extern struct magic_info thnginfo[];
+extern struct real re_stats;
+extern long e_levels[];
+extern struct rod ws_stuff[];
+extern struct sgttyb _tty;
+
+extern struct coord nh;
+extern struct delayed_action d_list[MAXDAEMONS];
+extern int between;
+
+extern char *rainbow[NCOLORS];
+extern char *sylls[NSYLS];
+extern char *stones[NSTONES];
+extern char *wood[NWOOD];
+extern char *metal[NMETAL];
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/srogue/rogue.h	Thu Nov 25 12:21:41 2010 +0000
@@ -0,0 +1,701 @@
+/*
+ * Rogue definitions and variable declarations
+ *
+ * @(#)rogue.h	9.0	(rdk)	 7/17/84
+ *
+ * Super-Rogue
+ * Copyright (C) 1984 Robert D. Kindelberger
+ * All rights reserved.
+ *
+ * Based on "Rogue: Exploring the Dungeons of Doom"
+ * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
+ * All rights reserved.
+ *
+ * See the file LICENSE.TXT for full copyright and licensing information.
+ */
+
+#ifdef BSD
+#include "cx.h"
+#endif
+
+
+#include <ctype.h>
+#include <curses.h>
+
+#ifdef ATT
+#define	CBREAK	FALSE
+#define _IOSTRG	01
+#endif
+
+#define reg     register        /* register abbr.       */
+
+/*
+ * Maximum number of different things
+ */
+
+#define NCOLORS		32
+#define NSYLS       159
+#define NSTONES     35
+#define NWOOD       24
+#define NMETAL      15
+
+#define MAXDAEMONS 20
+
+#define TYPETRAPS	9	/* max types of traps */
+#define MAXROOMS	9	/* max rooms per level */
+#define MAXTHINGS	9	/* max things on each level */
+#define MAXOBJ		9	/* max goodies on each level */	
+#define MAXPACK		23	/* max things this hero can carry */
+#define MAXTRAPS	10	/* max traps per level */
+#define MAXMONS		52	/* max available monsters */
+#define MONRANGE	20	/* max # of monsters avail each level */
+#define AMLEVEL		35	/* earliest level that amulet can appear */
+#define MAXPURCH	4	/* max purchases in trading post */
+#define MINABIL		3	/* minimum for any ability */
+#define MAXSTR		24	/* maximum strength */
+#define MAXOTHER	18	/* maximum wis, dex, con */
+#define NORMAC		10	/* normal hero armor class (no armor) */
+#define MONWIS		10	/* monsters standard wisdom */
+
+#define NORMLEV		0	/* normal level */
+#define POSTLEV		1	/* trading post level */
+#define MAZELEV		2	/* maze level */
+
+#define NORMFOOD	0	/* normal food's group no. */
+#define FRUITFOOD	1	/* fruit's group no. */
+#define NEWGROUP	2	/* start of group no. other than food */
+
+#define	NUMTHINGS	8	/* types of goodies for hero */
+#define TYP_POTION	0
+#define TYP_SCROLL	1
+#define TYP_FOOD	2
+#define TYP_WEAPON	3
+#define TYP_ARMOR	4
+#define TYP_RING	5
+#define TYP_STICK	6
+#define TYP_AMULET	7
+
+#define V_PACK		3600	/* max volume in pack */
+#define V_POTION	50		/* volume of potion */
+#define V_SCROLL	80		/* volume of scroll */
+#define V_FOOD		35		/* volume of food */
+#define V_WEAPON	0		/* volume of weapon (depends on wep) */
+#define V_ARMOR		0		/* volume of armor (depends on armor) */
+#define V_RING		20		/* volume of ring */
+#define V_STICK		0		/* volume of stick (depends on staff/wand) */
+#define V_AMULET	30		/* volume of amulet */
+
+#define V_WS_STAFF	200		/* volume of a staff */
+#define V_WS_WAND	110		/* volume of a wand */
+#define W_WS_STAFF	100		/* weight of a staff */
+#define W_WS_WAND	 60		/* weight of a wand */
+
+#define FROMRING	2
+#define DONTCARE	-1
+#define ANYTHING	-1,-1	/* DONTCARE, DONTCARE */
+
+#define K_ARROW		240		/* killed by an arrow */
+#define K_DART		241		/* killed by a dart */
+#define K_BOLT		242		/* killed by a bolt */
+#define K_POOL		243		/* killed by drowning */
+#define K_ROD		244		/* killed by an exploding rod */
+#define K_SCROLL	245		/* killed by a burning scroll */
+#define K_STONE		246		/* killed by materializing in rock */
+#define K_STARVE	247		/* killed by starvation */
+/*
+ * return values for get functions
+ */
+
+#define	NORM	0		/* normal exit */
+#define	QUIT	1		/* quit option setting */
+#define	MINUS	2		/* back up one option */
+
+/*
+ * Return values for games end
+ */
+#define KILLED	0		/* hero was killed */
+#define CHICKEN	1		/* hero chickened out (quit) */
+#define WINNER	2		/* hero was a total winner */
+
+/*
+ * return values for chase routines
+ */
+#define CHASE	0		/* continue chasing hero */
+#define FIGHT	1		/* fight the hero */
+#define GONER	2		/* chaser fell into a trap */
+
+/*
+ * All the fun defines
+ */
+#define next(ptr)	(*ptr).l_next
+#define prev(ptr)	(*ptr).l_prev
+#define ldata(ptr)	(*ptr).l_data
+#define OBJPTR(what)	(struct object *)((*what).l_data)
+#define THINGPTR(what)	(struct thing *)((*what).l_data)
+
+#define inroom(rp, cp) (\
+	(cp)->x <= (rp)->r_pos.x + ((rp)->r_max.x - 1) && \
+	(rp)->r_pos.x <= (cp)->x && (cp)->y <= (rp)->r_pos.y + \
+	((rp)->r_max.y - 1) && (rp)->r_pos.y <= (cp)->y)
+
+#define unc(cp) (cp).y, (cp).x
+#define cmov(xy) move((xy).y, (xy).x)
+#define DISTANCE(y1,x1,y2,x2) ((x2 - x1)*(x2 - x1) + (y2 - y1)*(y2 - y1))
+#define when break;case
+#define otherwise break;default
+#define until(expr) while(!(expr))
+
+#define ce(a, b) ((a).x == (b).x && (a).y == (b).y)
+#define draw(window) wrefresh(window)
+
+#define hero player.t_pos
+#define pstats player.t_stats
+#define pack player.t_pack
+
+#define herowis() (getpwis(him))
+#define herodex() (getpdex(him,FALSE))
+#define herostr() (pstats.s_ef.a_str)
+#define herocon() (pstats.s_ef.a_con)
+
+#define attach(a,b) _attach(&a,b)
+#define detach(a,b) _detach(&a,b)
+#define free_list(a) _free_list(&a)
+#ifndef max
+#define max(a, b) ((a) > (b) ? (a) : (b))
+#endif
+#define goingup() (level < max_level)
+
+#define on(thing, flag) (((thing).t_flags & flag) != 0)
+#define off(thing, flag) (((thing).t_flags & flag) == 0)
+#undef CTRL
+#define CTRL(ch) (ch & 0x1F)
+
+#define ALLOC(x) malloc((unsigned int) x)
+#define FREE(x) free((char *) x)
+#define	EQSTR(a, b, c)	(strncmp(a, b, c) == 0)
+#define GOLDCALC (rnd(50 + 10 * level) + 2)
+#define ISMULT(type) (type == POTION || type == SCROLL || type == FOOD)
+
+#define newgrp() ++group
+#define o_charges o_ac
+
+
+/*
+ * Things that appear on the screens
+ */
+#define PASSAGE		'#'
+#define DOOR		'+'
+#define FLOOR		'.'
+#define PLAYER		'@'
+#define POST		'^'
+#define MAZETRAP	'\\'
+#define TRAPDOOR	'>'
+#define ARROWTRAP	'{'
+#define SLEEPTRAP	'$'
+#define BEARTRAP	'}'
+#define TELTRAP		'~'
+#define DARTTRAP	'`'
+#define POOL		'"'
+#define SECRETDOOR	'&'
+#define STAIRS		'%'
+#define GOLD		'*'
+#define POTION		'!'
+#define SCROLL		'?'
+#define MAGIC		'$'
+#define FOOD		':'
+#define WEAPON		')'
+#define ARMOR		']'
+#define AMULET		','
+#define RING		'='
+#define STICK		'/'
+#define CALLABLE	-1
+
+
+/*
+ *	stuff to do with encumberence 
+ */
+#define NORMENCB 1500	/* normal encumberence */
+#define SOMTHERE 5		/* something is in the way for dropping */
+#define CANTDROP 6		/* cant drop it cause its cursed */
+#define F_OKAY	 0		/* have plenty of food in stomach */
+#define F_HUNGRY 1		/* player is hungry */
+#define F_WEAK	 2		/* weak from lack of food */
+#define F_FAINT	 3		/* fainting from lack of food */
+
+
+/*
+ * Various constants
+ */
+#define	PASSWD		"mTuZ7WUV9RWkQ"
+#define BEARTIME	3
+#define SLEEPTIME	5
+#define HEALTIME	30
+#define HOLDTIME	2
+#define STPOS		0
+#define WANDERTIME	70
+#define BEFORE		1
+#define AFTER		2
+#define HUHDURATION	20
+#define SEEDURATION	850
+#define HUNGERTIME	1300
+#define WEAKTIME	150
+#define HUNGTIME	300		/* 2 * WEAKTIME */
+#define STOMACHSIZE	2000
+#define ESCAPE		27
+#define LEFT		0
+#define RIGHT		1
+#define BOLT_LENGTH	6
+
+#define STR		1
+#define DEX		2
+#define CON		3
+#define WIS		4
+
+/*
+ * Save against things
+ */
+#define VS_POISON			00
+#define VS_PARALYZATION		00
+#define VS_DEATH			00
+#define VS_PETRIFICATION	01
+#define VS_BREATH			02
+#define VS_MAGIC			03
+
+
+/*
+ * Various flag bits
+ */
+#define ISSTUCK 0000001		/* monster can't run (violet fungi) */
+#define ISDARK	0000001		/* room is dark */
+#define ISCURSED 000001		/* object is cursed */
+#define ISBLIND 0000001		/* hero is blind */
+#define ISPARA  0000002		/* monster is paralyzed */
+#define ISGONE	0000002		/* room is gone */
+#define ISKNOW  0000002		/* object is known */
+#define ISRUN	0000004		/* Hero & monsters are running */
+#define ISTREAS 0000004		/* room is a treasure room */
+#define ISPOST  0000004		/* object is in a trading post */
+#define ISFOUND 0000010		/* trap is found */
+#define ISINVINC 000010		/* player is invincible */
+#define ISINVIS 0000020		/* monster is invisible */
+#define ISPROT	0000020		/* object is protected somehow */
+#define ISMEAN  0000040		/* monster is mean */
+#define ISBLESS 0000040		/* object is blessed */
+#define ISGREED 0000100		/* monster is greedy */
+#define ISWOUND 0000200		/* monster is wounded */
+#define ISHELD  0000400		/* hero is held fast */
+#define ISHUH   0001000		/* hero | monster is confused */
+#define ISREGEN 0002000		/* monster is regenerative */
+#define CANHUH  0004000		/* hero can confuse monsters */
+#define CANSEE  0010000		/* hero can see invisible monsters */
+#define WASHIT	0010000		/* hero has hit monster at least once */
+#define ISMISL  0020000		/* object is normally thrown in attacks */
+#define ISCANC	0020000		/* monsters special attacks are canceled */
+#define ISMANY  0040000		/* objects are found in a group (> 1) */
+#define ISSLOW	0040000		/* hero | monster is slow */
+#define ISHASTE 0100000		/* hero | monster is fast */
+#define ISETHER	0200000		/* hero is thin as air */
+#define NONE	100			/* equal to 'd' (used for weaps) */
+
+
+/*
+ * Potion types
+ */
+#define P_CONFUSE	0		/* confusion */
+#define P_PARALYZE	1		/* paralysis */
+#define P_POISON	2		/* poison */
+#define P_STRENGTH	3		/* gain strength */
+#define P_SEEINVIS	4		/* see invisible */
+#define P_HEALING	5		/* healing */
+#define P_MFIND		6		/* monster detection */
+#define P_TFIND		7		/* magic detection */
+#define P_RAISE		8		/* raise level */
+#define P_XHEAL		9		/* extra healing */
+#define P_HASTE		10		/* haste self */
+#define P_RESTORE	11		/* restore strength */
+#define P_BLIND		12		/* blindness */
+#define P_NOP		13		/* thirst quenching */
+#define P_DEX		14		/* increase dexterity */
+#define P_ETH		15		/* etherealness */
+#define P_SMART		16		/* wisdom */
+#define P_REGEN		17		/* regeneration */
+#define P_SUPHERO	18		/* super ability */
+#define P_DECREP	19		/* decrepedness */
+#define P_INVINC	20		/* invicibility */
+#define MAXPOTIONS	21		/* types of potions */
+
+
+/*
+ * Scroll types
+ */
+#define S_CONFUSE	0		/* monster confusion */
+#define S_MAP		1		/* magic mapping */
+#define S_LIGHT		2		/* light */
+#define S_HOLD		3		/* hold monster */
+#define S_SLEEP		4		/* sleep */
+#define S_ARMOR		5		/* enchant armor */
+#define S_IDENT		6		/* identify */
+#define S_SCARE		7		/* scare monster */
+#define S_GFIND		8		/* gold detection */
+#define S_TELEP		9		/* teleportation */
+#define S_ENCH		10		/* enchant weapon */
+#define S_CREATE	11		/* create monster */
+#define S_REMOVE	12		/* remove curse */
+#define S_AGGR		13		/* aggravate monster */
+#define S_NOP		14		/* blank paper */
+#define S_GENOCIDE	15		/* genocide */
+#define S_KNOWALL	16		/* item knowledge */
+#define S_PROTECT	17		/* item protection */
+#define S_DCURSE	18		/* demons curse */
+#define S_DLEVEL	19		/* transport */
+#define S_ALLENCH	20		/* enchantment */
+#define S_BLESS		21		/* gods blessing */
+#define S_MAKEIT	22		/* aquirement */
+#define S_BAN		23		/* banishment */
+#define S_CWAND		24		/* charge wands */
+#define S_LOCTRAP	25		/* locate traps */
+#define MAXSCROLLS	26		/* types of scrolls */
+
+
+/*
+ * Weapon types
+ */
+#define MACE		0		/* mace */
+#define SWORD		1		/* long sword */
+#define BOW			2		/* short bow */
+#define ARROW		3		/* arrow */
+#define DAGGER		4		/* dagger */
+#define ROCK		5		/* rocks */
+#define TWOSWORD	6		/* two-handed sword */
+#define SLING		7		/* sling */
+#define DART		8		/* darts */
+#define CROSSBOW	9		/* crossbow */
+#define BOLT		10		/* crossbow bolt */
+#define SPEAR		11		/* spear */
+#define TRIDENT		12		/* trident */
+#define SPETUM		13		/* spetum */
+#define BARDICHE	14 		/* bardiche */
+#define PIKE		15		/* pike */
+#define BASWORD		16		/* bastard sword */
+#define HALBERD		17		/* halberd */
+#define MAXWEAPONS	18		/* types of weapons */
+
+
+/*
+ * Armor types
+ */
+#define LEATHER		0		/* leather */
+#define RINGMAIL	1		/* ring */
+#define STUDDED		2		/* studded leather */
+#define SCALE		3		/* scale */
+#define PADDED		4		/* padded */
+#define CHAIN		5		/* chain */
+#define SPLINT		6		/* splint */
+#define BANDED		7		/* banded */
+#define PLATEMAIL	8		/* plate mail */
+#define PLATEARMOR	9		/* plate armor */
+#define MAXARMORS	10		/* types of armor */
+
+
+/*
+ * Ring types
+ */
+#define R_PROTECT	0		/* protection */
+#define R_ADDSTR	1		/* add strength */
+#define R_SUSTSTR	2		/* sustain strength */
+#define R_SEARCH	3		/* searching */
+#define R_SEEINVIS	4		/* see invisible */
+#define R_CONST		5		/* constitution */
+#define R_AGGR		6		/* aggravate monster */
+#define R_ADDHIT	7		/* agility */
+#define R_ADDDAM	8		/* increase damage */
+#define R_REGEN		9		/* regeneration */
+#define R_DIGEST	10		/* slow digestion */
+#define R_TELEPORT	11		/* teleportation */
+#define R_STEALTH	12		/* stealth */
+#define R_SPEED		13		/* speed */
+#define R_FTRAPS	14		/* find traps */
+#define R_DELUS		15		/* delusion */
+#define R_SUSAB		16		/* sustain ability */
+#define R_BLIND		17		/* blindness */
+#define R_SLOW		18		/* lethargy */
+#define R_GIANT		19		/* ogre strength */
+#define R_SAPEM		20		/* enfeeblement */
+#define R_HEAVY		21		/* burden */
+#define R_LIGHT		22		/* illumination */
+#define R_BREATH	23		/* fire protection */
+#define R_KNOW		24		/* wisdom */
+#define R_DEX		25		/* dexterity */
+#define MAXRINGS	26		/* types of rings */
+
+
+/*
+ * Rod/Wand/Staff types
+ */
+
+#define WS_LIGHT	0		/* light */
+#define WS_HIT		1		/* striking */
+#define WS_ELECT	2		/* lightning */
+#define WS_FIRE		3		/* fire */
+#define WS_COLD		4		/* cold */
+#define WS_POLYM	5		/* polymorph */
+#define WS_MISSILE	6		/* magic missile */
+#define WS_HASTE_M	7		/* haste monster */
+#define WS_SLOW_M	8		/* slow monster */
+#define WS_DRAIN	9		/* drain life */
+#define WS_NOP		10		/* nothing */
+#define WS_TELAWAY	11		/* teleport away */
+#define WS_TELTO	12		/* teleport to */
+#define WS_CANCEL	13		/* cancellation */
+#define WS_SAPLIFE	14		/* sap life */
+#define WS_CURE		15		/* curing */
+#define WS_PYRO		16		/* pyromania */
+#define WS_ANNIH	17		/* annihilate monster */
+#define WS_PARZ		18		/* paralyze monster */
+#define WS_HUNGER	19		/* food absorption */
+#define WS_MREG		20		/* regenerate monster */
+#define WS_MINVIS	21		/* hide monster */
+#define WS_ANTIM	22		/* anti-matter */
+#define WS_MOREMON	23		/* clone monster */
+#define WS_CONFMON	24		/* confuse monster */
+#define WS_MDEG		25		/* degenerate monster */
+#define MAXSTICKS	26		/* max types of sticks */
+
+#define MAXAMULETS	1		/* types of amulets */
+#define MAXFOODS	1		/* types of food */
+
+
+/*
+ * Now we define the structures and types
+ */
+
+struct delayed_action {
+	int d_type;
+	int (*d_func)();
+	int d_arg;
+	int d_time;
+};
+
+/*
+ * Help list
+ */
+struct h_list {
+	char h_ch;
+	char *h_desc;
+};
+
+
+/*
+ * Coordinate data type
+ */
+struct coord {
+	int x;			/* column position */
+	int y;			/* row position */
+};
+
+struct monlev {
+	int l_lev;		/* lowest level for a monster */
+	int h_lev;		/* highest level for a monster */
+	bool d_wand;	/* TRUE if monster wanders */
+};
+
+/*
+ * Linked list data type
+ */
+struct linked_list {
+	struct linked_list *l_next;
+	struct linked_list *l_prev;
+	char *l_data;			/* Various structure pointers */
+};
+
+
+/*
+ * Stuff about magic items
+ */
+#define mi_wght mi_worth
+struct magic_item {
+	char *mi_name;			/* name of item */
+	int mi_prob;			/* probability of getting item */
+	int mi_worth;			/* worth of item */
+};
+
+struct magic_info {
+	int mf_max;						/* max # of this type */
+	int	mf_vol;						/* volume of this item */
+	char mf_show;					/* appearance on screen */
+	struct magic_item *mf_magic;	/* pointer to magic tables */
+};
+
+/*
+ * staff/wand stuff
+ */
+struct rod {
+	char *ws_type;		/* either "staff" or "wand" */
+	char *ws_made;		/* "mahogany", etc */
+	int	 ws_vol;		/* volume of this type stick */
+	int  ws_wght;		/* weight of this type stick */
+};
+
+/*
+ * armor structure 
+ */
+struct init_armor {
+	int a_class;		/* normal armor class */
+	int a_wght;			/* weight of armor */
+	int a_vol;			/* volume of armor */
+};
+
+/*
+ * weapon structure
+ */
+struct init_weps {
+    char *w_dam;		/* hit damage */
+    char *w_hrl;		/* hurl damage */
+    int  w_flags;		/* flags */
+    int  w_wght;		/* weight of weapon */
+	int  w_vol;			/* volume of weapon */
+    char w_launch;		/* need to launch it */
+};
+
+
+/*
+ * Room structure
+ */
+struct room {
+	struct coord r_pos;		/* Upper left corner */
+	struct coord r_max;		/* Size of room */
+	struct coord r_gold;	/* Where the gold is */
+	struct coord r_exit[4];	/* Where the exits are */
+	struct room *r_ptr[4];	/* this exits' link to next rm */
+	int r_goldval;			/* How much the gold is worth */
+	int r_flags;			/* Info about the room */
+	int r_nexits;			/* Number of exits */
+};
+
+/*
+ * Array of all traps on this level
+ */
+struct trap {
+	struct coord tr_pos;	/* Where trap is */
+	struct coord tr_goto;	/* where trap tranports to (if any) */
+	int tr_flags;			/* Info about trap */
+	char tr_type;			/* What kind of trap */
+};
+
+/*
+ * structure for describing true abilities
+ */
+struct real {
+	int a_str;			/* strength (3-24) */
+	int a_dex;			/* dexterity (3-18) */
+	int a_wis;			/* wisdom (3-18) */
+	int a_con;			/* constitution (3-18) */
+};
+
+/*
+ * Structure describing a fighting being
+ */
+struct stats {
+	struct real s_re;	/* True ability */
+	struct real s_ef;	/* Effective ability */
+	long s_exp;			/* Experience */
+	int s_lvl;			/* Level of mastery */
+	int s_arm;			/* Armor class */
+	int s_hpt;			/* Hit points */
+	int s_maxhp;		/* max value of hit points */
+	int s_pack;			/* current weight of his pack */
+	int s_carry;		/* max weight he can carry */
+	char s_dmg[16];		/* String describing damage done */
+};
+
+/*
+ * Structure for monsters and player
+ */
+struct thing {
+	struct stats t_stats;		/* Physical description */
+	struct coord t_pos;			/* Position */
+	struct coord t_oldpos;		/* last spot of it */
+	struct coord *t_dest;		/* Where it is running to */
+	struct linked_list *t_pack;	/* What the thing is carrying */
+	struct room *t_room;		/* Room this thing is in */
+	long t_flags;				/* State word */
+	int t_indx;					/* Index into monster structure */
+	int t_nomove;				/* # turns you cant move */
+	int t_nocmd;				/* # turns you cant do anything */
+	bool t_turn;				/* If slow, is it a turn to move */
+	char t_type;				/* What it is */
+	char t_disguise;			/* What mimic looks like */
+	char t_oldch;				/* Char that was where it was */
+	char t_reserved;
+};
+
+/*
+ * Array containing information on all the various types of mosnters
+ */
+struct monster {
+	char *m_name;			/* What to call the monster */
+	char m_show;			/* char that monster shows */
+	short m_carry;			/* Probability of having an item */
+	struct monlev m_lev;	/* level stuff */
+	long m_flags;			/* Things about the monster */
+	struct stats m_stats;	/* Initial stats */
+};
+
+/*
+ * Structure for a thing that the rogue can carry
+ */
+struct object {
+	struct coord o_pos;		/* Where it lives on the screen */
+	char o_damage[8];		/* Damage if used like sword */
+	char o_hurldmg[8];		/* Damage if thrown */
+	char *o_typname;		/* name this thing is called */
+	int o_type;				/* What kind of object it is */
+	int o_count;			/* Count for plural objects */
+	int o_which;			/* Which object of a type it is */
+	int o_hplus;			/* Plusses to hit */
+	int o_dplus;			/* Plusses to damage */
+	int o_ac;				/* Armor class or charges */
+	int o_flags;			/* Information about objects */
+	int o_group;			/* Group number for this object */
+	int o_weight;			/* weight of this object */
+	int o_vol;				/* volume of this object */
+	char o_launch;			/* What you need to launch it */
+};
+
+extern WINDOW *cw, *hw, *mw;
+
+#define LINLEN	80			/* length of buffers */
+
+#define EXTLKL	extern struct linked_list
+#define EXTTHG	extern struct thing
+#define EXTOBJ	extern struct object
+#define EXTSTAT extern struct stats
+#define EXTCORD	extern struct coord
+#define EXTMON	extern struct monster
+#define EXTARM	extern struct init_armor
+#define EXTWEP	extern struct init_weps
+#define EXTMAG	extern struct magic_item
+#define EXTROOM	extern struct room
+#define EXTTRAP	extern struct trap
+#define EXTINT	extern int
+#define EXTBOOL	extern bool
+#define EXTCHAR	extern char
+
+#ifdef BSD
+#define flushout()	ioctl(_tty_ch, TIOCFLUSH, 0)
+#endif
+
+#ifdef ATT
+
+struct sgttyb {
+	char	sg_ispeed;		/* input speed */
+	char	sg_ospeed;		/* output speed */
+	char	sg_erase;		/* erase character */
+	char	sg_kill;		/* kill character */
+	int	sg_flags;		/* mode flags */
+};
+
+struct sgttyb _tty;
+#define flushout()	ioctl(2, TCFLSH, 0)
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/srogue/rogue.nr	Thu Nov 25 12:21:41 2010 +0000
@@ -0,0 +1,636 @@
+.PH
+.fp 9 CR
+.nr Hu 1
+.nr Pt 0
+.SA 1
+.S +4 C
+.ad c
+.B "Super-Rogue Version 9.0"
+.br
+.ad b
+.SP 0.45
+.S -4 C
+.ad c
+.I "Robert D. Kindelberger"
+.br
+.ad b
+.SP 2.6
+.ad c
+.I "A Tutorial on the Visual Game of Rogue - Version 9.0"
+.br
+.ad b
+.SP 2
+.P
+Rogue is a visual CRT based fantasy game which runs
+under the UNIX\*F
+.FS
+UNIX is a trademark of AT&T Bell Laboratories.
+.FE
+timesharing system.  This paper describes
+how to play rogue and gives a few hints for those who might
+otherwise get lost (or killed) in the Dungeons of Doom.
+.SP 5
+.PH "''- % -''"
+.H 1 INTRODUCTION
+.P
+You have just finished your years as a student
+at the local fighter's guild.
+After much practice and sweat you have finally completed your training and
+are ready to embark upon a perilous adventure.  As a test of your skills,
+the local guildmasters have sent you into the Dungeons of Doom.  Your
+task is to return with the Amulet of Yendor.  
+Your reward for the completion
+of this task will be a full membership in the local guild. 
+In addition, you are
+allowed to keep all the loot you bring back from the dungeons.
+.P
+In preparation for your journey, you are given an enchanted weapon, taken
+from a dragon's hoard in the far off Dark Mountains.  
+You are also outfitted
+with elf-crafted armor and given enough food to reach the dungeons.  You
+say good-bye to family and friends for what may be the last time and head
+up the road.
+.P
+You set out on your way to the dungeons and after 
+several days of uneventful
+travel, you see the ancient ruins that mark the entrance to the Dungeons
+of Doom.  It is late at night so you make camp at the entrance and spend
+the night sleeping under the open skies.  In the morning you gather
+your weapon, put on your armor, eat what is almost your last food and enter
+the dungeons.
+.H 1 "WHAT IS GOING ON HERE?"
+.P 
+You have just begun a game of rogue.  
+Your goal is to grab as much treasure
+as you can, find the \f3Amulet of Yendor\f1, and get out of the Dungeons
+of Doom alive.  
+On the screen, a map of where you have been and what you have seen on
+the current dungeon level is kept.  As you explore more of the level,
+it appears on the screen in front of you.
+.P
+Rogue differs from most computer fantasy games in that it is screen
+oriented.  Commands are all one or two keystrokes\*F
+.FS
+As opposed to pseudo English sentences.
+.FE
+and the results of your commands are displayed
+graphically on the screen rather than being explained in words.
+.P
+Another major difference between rogue and other computer fantasy games
+is that once you have solved all the puzzles in a standard fantasy game,
+it has lost most of its excitement and it ceases to be fun.  Rogue on the
+other hand generates a new dungeon every time you play it and
+even the author finds it an entertaining and exciting game.
+.H 1 "WHAT DO ALL THOSE THINGS ON THE SCREEN MEAN?"
+.P
+In order to understand what is going on in rogue you have to first get
+some grasp of what rogue is doing with the screen.
+The rogue screen is intended to replace the \f3You can see ...\f1 descriptions
+of standard fantasy games.  Here is a sample of what a rogue screen might
+look like:
+.SP
+.DS
+\f9
+                  ---------------------
+                  |...................+###########+
+                  |...@...........[...|
+                  |........H..........|
+                  |...................|
+                  --------+------------
+                          ####
+                             +
+
+Level: 1   Gold: 0    Hp:12(12)  Ac: 6      Exp:1/0    Vol:36%
+Str:16(16) Exp:12(12) Dex:11(11) Wis:14(14) Con:18(18) Carry:50/170
+\f1
+.DE
+.H 1 "THE BOTTOM LINES"
+At the bottom line of the screen is a few pieces of cryptic information,
+describing your current status.  Here is an explanation of what these
+things mean:
+.SP
+.H 2 "LEVEL"
+.SP
+This number indicates how deep you have gone in the dungeon.  It starts
+at one and goes up forever.\*F
+.FS
+Or until you get killed or decide to quit.  Level 500 is really the
+maximum, but almost impossible.
+.FE
+.SP
+.H 2 "GOLD"
+.SP
+The number of gold pieces you have managed to attain.
+.SP
+.H 2 "HP"
+.SP
+Your current and maximum hit points.  Hit points indicate how much
+damage you can take before you die.  The more you get hit in a
+fight, the lower they
+get.  You can regain hit points by moving around. The number in
+parentheses is the maximum number of hit points you can regain.
+.SP
+.H 2 "AC"
+.SP
+Your current armor class.  This number indicates how effective
+your armor is in stopping blows from unfriendly creatures.  The lower
+this number is, the more effective the armor.  Armor class can get
+lower than zero.
+.SP
+.H 2 "EXP"
+.SP
+These two numbers give your current experience level and experience points.
+As you kill monsters, you gain experience points.  At certain experience
+point totals, you gain an experience level.  The more experienced you are,
+the better you are able to fight and to withstand magical attacks. You
+must gain 10 experience points to advance to the 2nd experience level.
+Now you must double the previous experience point total to advance
+to the next experience level. (i.e. 20 to get to level 3, 40 to 4...)
+Every time you advance to a new experience level, your hit points
+will increase.  This is random, so don't expect a lot every time.
+.SP
+.H 2 "VOL"
+.SP
+This is the percentage of what your pack contains.  \f3100%\f1
+means that your pack is full.
+.SP
+.H 2 "STR"
+.SP
+Your current strength.  This can be any integer from 0 to 24.
+The larger the number, the stronger you are.
+.SP
+.H 2 "DEX"
+.SP
+This is your dexterity.  Dexterity gives you the ability to dodge arrow
+and dart traps more effectively.  It also gives you the ability to dodge
+attacks from monters (maximum of 18).
+.SP
+.H 2 "WIS"
+.SP
+This is your wisdom.  If you are smarter than the monsters,
+then you have a better chance of defeating them (maximum of 18).
+.SP
+.H 2 "CON"
+.SP
+This is your constitution.  Constitution makes up your ability to
+regain your hit points, once you have been battered.  The higher
+your constitution (maximum of 18), the faster you will gain back
+the hit points you have lost.
+.SP
+.H 2 "CARRY"
+.SP
+This is similar to your volume, but tells you the maximum of what
+you can carry and what you are currently carrying in weight.
+.H 1 "THE TOP LINE"
+.P
+The top line of the screen is reserved for printing messages that describe
+things that are impossible to represent visually.  If you see a
+\f3-- More --\f1 on the top line, this means that rogue wants to print another
+message on the screen, but it wants to make certain that you have read
+the one that is there first.  To read the next message, just press a
+space.
+.H 1 "THE REST OF THE SCREEN"
+.P
+The rest of the screen is the map of the level
+as you have explored it so far.
+Each symbol on the screen represents something.  Here is a list of what
+the various symbols mean:
+.bp
+.DS
+.B "@   " "This symbol represents you, the adventurer."
+
+.B "|   " "A wall running north/south."
+
+.B "-   " "A wall running east/west."
+
+.B "+   " "A door to/from a room."
+
+.B "\.   " "The floor of a room."
+
+.B "#   " "The floor of a passage between rooms."
+
+.B "*   " "A pile or pot of gold."
+
+.B ")   " "A weapon of some sort."
+
+.B "]   " "A suit of armor."
+
+.B "!   " "A flask containing a magic potion."
+
+.B "?   " "A piece of paper, usually a magic scroll."
+
+.B "/   " "A wand or staff of magic."
+
+.B "=   " "A magical ring.  Can be good or bad."
+
+.B "{   " "An arrow trap.  Loss of hit points."
+
+.B "}   " "A bear trap.  Holds you for awhile."
+
+.B "~   " "A teleportation trap.  Teleports you to a random room."
+
+.B "`   " "A dart trap.  Loss of strength."
+
+.B "$   " "A sleeping gas trap, watch out for these."
+
+.B ">   " "A trap door leading down to the next level."
+
+.B "^   " "A flee market to exchange gold for objects, or vice-versa."
+
+.B "\e   " "A trap door that leads down to an invisible maze."
+
+\f3"\f1   A magical pool that does strange things to wielded objects.
+
+.B "%   " "The staircase leading down to the next level."
+
+.B ":   " "A piece of food or zany fruit."
+
+.B ",   AMULET OF YENDOR."
+
+.B "a-Z " "There are 52 inhabitants of the Dungeons of Doom."
+.DE
+.bp
+.H 1 COMMANDS
+.P
+Commands are given to rogue by pressing single letters.  Some commands can
+be preceded by a count to repeat them 
+(i.e. typing \f310s\f1 will do ten searches)
+The list of commands is rather long, but it can be read at any time during
+the game with the \f3?\f1 command.  Here it is for reference, with a short
+explanation of each command:
+.SP
+.DS
+\f3?\f1       The help command.  Asks for a character to give help on.
+        If you type a \f3*\f1, it will list all the commands, otherwise
+        it will explain what the character you type does.
+
+\f3/\f1       This is the \f3What is that on the screen\f1? command.
+        A \f3/\f1 followed by any character that you see on the level,
+        will tell you what that character is.  For instance, typing
+        \f3/@\f1 will tell you that the \f3@\f1 symbol represents you,
+        the player.
+
+\f3h, H\f1    Move left.  You move one space to the left.  If you use
+        upper case, \f3H,\f1 you will continue to move left until you
+        run into something.  This works for all movement commands.
+        (i.e. \f3L\f1 means run in direction \f3l\f1)
+
+.B "j, J    " "Move down."
+
+.B "k, K    " "Move up."
+
+.B "l, L    " "Move right."
+
+.B "y, Y    " "Move diagonally up and left."
+
+.B "u, U    " "Move diagonally up and right."
+
+.B "b, B    " "Move diagonally down and left."
+
+.B "n, N    " "Move diagonally down and right."
+
+\f3f\f1       Find prefix.  When followed by a direction it means to
+        continue moving in the specified direction until you pass
+        something interesting or run into a wall.
+
+\f3t\f1       Throw an object.  This is a prefix command.  Follow it
+        with a direction and you throw an object in the specified
+        direction.  (i.e. type \f3th\f1 to throw something left.)
+
+\f3p\f1       Zap an object with a staff or wand.  This is a prefix
+        command.  Follow it with a direction and you will zap in the
+        specified direction.  (i.e. type \f3ph\f1 to zap something left.)
+.DE
+.bp
+.DS
+\f3z\f1       Zap an object with no direction.  This means that you
+        could be zapped with it as well.
+
+.B "D       " "Dip an object in the magic pool."
+
+\f3>\f1       If you are standing over the passage down to the next
+        level, this command means to climb down.
+
+\f3<\f1       If you have found the \f3Amulet of Yendor\f1, then
+        you have the ability to climb back up a level, hopefully on
+        your way out.
+
+\f3s\f1       Search for traps and secret doors.  Examine each space
+        immediately adjacent to you for the existence of a trap or
+        secret door.  There is a large chance that even if there is
+        something there, you won't find it so you might have to
+        search a while before you find something.
+
+.B "\.       " "Rest.  This is the \f3do nothing\f1 command.  This is
+        good for waiting and healing."
+
+.B "i       " "Inventory.  List what you are carrying in your pack."
+
+\f3I\f1       Selective inventory.  Tells you what a single item in
+        your pack is.
+
+.B "q       " "Quaff.  Drink one of the potions you are carrying."
+
+.B "r       " "Read.  Read one of the scrolls in your pack."
+
+.B "e       " "Eat food.  Take some food out of your pack and eat it."
+
+\f3w\f1       Wield a weapon. Take a weapon out of your pack and carry
+        it.  You must be wielding a weapon to use it (except to
+        throw things).  To fire an arrow, you must wield the bow.
+        You can only wield one weapon at a time.
+
+\f3W\f1       Wear armor.  Take a piece of armor out of your pack and
+        put it on.  You can only wear one suit of armor at a time.
+
+.B "T       " "Take armor off.  You can't remove armor that is cursed."
+
+\f3P\f1       Put a ring on your finger.  You can only wear two rings
+        at a time.
+
+\f3R\f1       Remove a ring from your finger.  Cursed rings are hard
+        to remove.
+
+\f3d\f1       Drop an object.  Take something out of your pack and
+        leave it lying on the floor.  Only one object can occupy
+        each space.
+.DE
+.bp
+.DS
+\f3O\f1       Examine and set options.  This command is further
+        explained in the section on options.
+
+\f3^l\f1      Redraws the screen.  Useful if spurious messages or
+        transmission errors have messed up the display.
+
+\f3^r\f1      Repeat last message.  Useful when a message disappears
+        before you can read it.
+
+.B "^[      " "This is the escape key.  This will cancel the last command."
+
+\f3a\f1       Reports your encumbrance.  This is the weight factor of
+        your pack.  The heavier your pack is weighted down with
+        objects, the less effective you are in an attack and the
+        more food you'll eat.
+
+.B "c       " "Call an object.  You can call an object anything you like."
+
+.B "v       " "Prints the program version number."
+
+.B "Q       " "Quit.  Leave the game.  This is the chicken-way out."
+
+\f3!\f1       This is the shell escape key.  Use this to get back to
+        shell level.  To get back to the game, just hit \f3^d\f1.
+
+\f3S\f1       Save the current game in a file.  Rogue won't let
+        you start up a copy of a saved game, and it removes the
+        save file as soon as you start up a restored game.  This
+        is to prevent people from saving a game just before a
+        dangerous position and then restarting it, if they die.
+        Sorry no linking, copying, moving, or anything.
+.DE
+.bp
+.H 1 "DEALING WITH OBJECTS"
+.P
+When you find something in the dungeon, it is common to want to pick the
+object up.  This is accomplished in rogue by walking over the object.
+If you are carrying too many things, you won't be able to pick the
+object up.  Otherwise, the object will be added to your pack and you
+will be notified of what you just picked up.
+.P
+Many of the commands that operate on objects must prompt you to find
+out which object you want to use.  
+If you change your mind and don't want to
+do that command after all, just press an \f3escape\f1 key and the command
+will be aborted.
+.H 1 ROOMS
+.P
+Rooms in the dungeons are either lit or dark.  
+If you walk into a lit room,
+the entire room will be drawn on the screen as soon as you enter.  If you
+walk into a dark room, you will only be able to see the spaces immediately
+next to you.
+Upon leaving a dark room, all objects inside the room are
+removed from the screen.
+.H 1 FIGHTING
+.P
+If you see a monster and you wish to fight it, just attempt to run into it.
+You also may throw things at it or zap it with a wand or staff.
+Many times a monster you find will mind its own business unless you attack
+it.  It is often the case that discretion is the better part of valor.
+.P
+Smart monsters have the ability to run when they realize that their
+lives are endangered.  This will be denoted that you have wounded
+the monster.
+.P
+Monsters will avoid lit traps.  You can use this to your
+advantage, if you figure out how.  If the traps are not lit, they can
+fall through them as you would.  The hard part is trying to get them to
+fall through a trap that you don't know is there.
+.bp
+.H 1 ARMOR
+.P
+There are various sorts of armor lying around in the dungeon.  Some of it
+is enchanted, some is cursed and some is just normal.  Different armor
+types have different armor classes.  The lower the armor class, the
+more protection the armor affords against the blows of monsters.
+If a piece of armor is enchanted or
+cursed, its armor class will be higher or lower than normal.  Here is
+a list of the various armor types and their normal armor class:
+.DS 3
+.TS
+box;
+c|c
+l|l.
+TYPE	CLASS
+=
+LEATHER ARMOR	8
+RING MAIL	7
+STUDDED LEATHER ARMOR	7
+SCALE MAIL	6
+PADDED ARMOR	6
+CHAIN MAIL	5
+SPLINT MAIL	4
+BANDED MAIL	4
+PLATE MAIL	3
+PLATE ARMOR	2
+.TE
+.DE
+.H 1 WEAPONS
+.P
+There may be many different types of weapons lying around in the dungeon,
+probably left there when their previous owners ran into a monster they
+couldn't handle.  In order to fire arrows and crossbow bolts you must be
+wielding the bow or the crossbow.  Rocks are effective when thrown but
+can be even more dangerous when hurled with a sling.  Daggers can be used
+as stabbing weapons or they can be thrown.  Beware of cursed weapons,
+they will not work as well as normal or enchanted weapons and once you
+wield them, you will be stuck with them until you can get the curse
+removed.  Staffs and wands are special weapons.  They need not be
+wielded for you to use them.
+.bp
+.H 1 "POTIONS AND SCROLLS"
+.P
+Left by the wizard Yendor, the potions and scrolls found in the dungeon
+constitute a mixed blessing.  By drinking or reading these magical items,
+the intelligent adventurer can greatly increase his chances of survival.
+A few of them can backfire on the unwary rogue, causing everything from
+a weakening sickness to the creation of an angry monster.
+.H 1 OPTIONS
+.P
+Due to variations in personal tastes and conceptions of the way rogue
+should do things, there are a set of options you can set that cause
+rogue to behave in various different ways.
+.H 2 "SETTING THE OPTIONS"
+.P
+There are basically two ways to set the options.  The first is with the
+\f3O\f1 command of rogue, the second is with the \f3ROGUEOPTS\f1 environment
+variable.
+.H 2 "USING THE O COMMAND"
+.P
+When you press \f3O\f1 in rogue, it clears the screen and displays the
+current settings for all the options.  
+It then places the cursor by the value of the
+first option and waits for you to type.  
+You can type a \f3RETURN\f1 which means to
+go to the next option, a \f3-\f1 which means to go to the previous option,
+an escape which means to return to the game, or you can give the option a
+value.  For string options, type the new value followed by a return.
+.H 2 "USING THE ROGUEOPTS VARIABLE"
+.P
+The \f3ROGUEOPTS\f1 variable is a string containing a comma
+separated list of initial values for the various options.
+Thus to set up an environment variable so that the name is
+set to \f3Rapid Robert\f1, the fruit is \f3cherry\f1, 
+and your save file is \f3fun\f1, use the command:
+.SP 2
+.DS
+ROGUEOPTS="name=Rapid Robert,fruit=cherry,file=fun"
+export ROGUEOPTS
+.DE
+.bp
+.H 2 "OPTION LIST"
+.P
+Here is a list of the options and an explanation for each one.
+The default value for each is enclosed in square brackets:
+.BL
+.LI
+.B "NAME [LOGIN NAME]"
+This is the name of your character.  It is used if you get on the top ten
+scorer's list.  It should be less than eighty characters long.
+.LI
+.B "FRUIT [JUICY-FRUIT]"
+This should hold the name of a 
+fruit that you enjoy eating.  It is basically
+a whimsy that the program uses in a couple of places.
+.LI
+.B "FILE [.ROGUE.SAVE]"
+The default file name for saving the game.  If your phone is hung up by
+accident, rogue will automatically save the game in this file.  The
+file name may contain the special character \f3~\f1 which expands to be
+your home directory.
+.LE
+.H 1 "SAVED GAMES"
+.P
+This is how one would restore a saved game:
+.SP
+.DS 1
+.B "rogue .rogue.save"
+.DE
+.SP
+This is how one would read the top ten score list of rogue:
+.SP
+.DS 1
+.B "rogue -s"
+.DE
+.SP
+.bp
+.H 1 SYNOPSIS
+.B Rogue
+is a video oriented game with the object being to survive the attacks
+of various monsters and gather a lot of gold.
+To get started, you really only need to know two commands.  The command
+.B ?
+will give you a list of the available commands and the command
+.B /
+will identify the things you see on the screen.
+.P
+To win the game (as opposed to merely playing to beat other people high
+scores) you must locate the
+.B "Amulet of Yendor"
+which is somewhere below
+the \f335th\f1 level of the dungeon and get it out.
+.P
+When the game ends, either by your death, when you chicken-out by
+quitting, or if you (by some miracle) manage to win,
+.B rogue
+will give you a list of what was in your pack and
+will give you a list of the top ten scorers.  The scoring is based
+upon how much gold you get.
+If for some reason you manage to win, then the stuff in your
+pack is also worth points.  The better the stuff, the more points you'll
+get.  There is a \f310%\f1 penalty for getting yourself killed.
+.H 1 ACKNOWLEDGEMENTS
+Rogue was originally conceived of by Glenn Wichman and Michael Toy.  The
+version of Super-Rogue 9.0 has been established
+through the persistence of a co-worker, who would like to remain nameless.
+He conceived the idea of 52 monsters, magic pools, the Flea Market,
+and mazes.  Many bug fixes and joys of Super-Rogue 9.0 wouldn't
+be here without the savage attack that he has put on this game.
+.H 1 FILES
+.BL
+.LI
+\f3srogue:\f1             Rogue game (object)
+.LI
+\f3Rogue score file search for as follows:\f1
+\f3$ROGUEHOME/srogue.scr \f1
+.br 
+\f3/var/games/roguelike/srogue.scr \f1
+.br 
+\f3/var/lib/roguelike/srogue.scr \f1
+.br 
+\f3/var/roguelike/srogue.scr \f1
+.br  .br 
+\f3/usr/games/lib/srogue.scr \f1
+.br 
+\f3/games/roguelik/srogue.scr \f1
+.br 
+\f3srogue.scr:\f1 
+.LI
+\f3srogue.sav (user defineable):\f1    Rogue save file
+.LE
+.H 1 BUGS
+As of the release of this memo, there are no known bugs.
+Going past level 500 would be suicidal.
+.bp
+.H 1 "SHORT REFERENCE OF COMMANDS"
+.DS
+\f9
+ ?       prints help               /       identify object
+ h       left                      H       run left
+ j       down                      J       run down
+ k       up                        K       run up
+ l       right                     L       run right
+ y       up & left                 Y       run up & left
+ u       up & right                U       run up & right
+ b       down & left               B       run down & left
+ n       down & right              N       run down & right
+ i       inventory pack            I       one item inventory
+ w       wield a weapon            W       wear armor
+ a       encumbrance               O       examine/set options
+ c       call object               R       remove ring
+ d       drop object               P       put on ring
+ e       eat food                  T       take armor off
+ q       quaff potion              Q       quit game
+ r       read a scroll             S       save game
+ v       program version number    D       dip object in magic pool 
+ z       zap a wand or staff       s       search for traps
+ t <dir> throw something           f <dir> forward until find
+ p <dir> directional zap           \.       rest for a while
+ >       go down a staircase       <       go up a staircase
+^r       repeat last message      ^l       redraw screen
+^[       cancel last command      ^d       return from shell
+ !       escape to shell          
+\f1
+.DE
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/srogue/rooms.c	Thu Nov 25 12:21:41 2010 +0000
@@ -0,0 +1,257 @@
+/*
+ * Draw the nine rooms on the screen
+ *
+ * @(#)rooms.c	9.0	(rdk)	 7/17/84
+ *
+ * Super-Rogue
+ * Copyright (C) 1984 Robert D. Kindelberger
+ * All rights reserved.
+ *
+ * Based on "Rogue: Exploring the Dungeons of Doom"
+ * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
+ * All rights reserved.
+ *
+ * See the file LICENSE.TXT for full copyright and licensing information.
+ */
+
+#include "rogue.h"
+#include "rogue.ext"
+
+/*
+ * do_rooms:
+ *	Place the rooms in the dungeon
+ */
+do_rooms()
+{
+	int mloops, mchance, nummons, left_out, roomtries;
+	bool treas = FALSE;
+	reg int i;
+	reg struct room *rp;
+	reg struct linked_list *item;
+	reg struct thing *tp;
+	struct coord top, bsze, mp;
+
+	/*
+	 * bsze is the maximum room size
+	 */
+	bsze.x = COLS / 3;
+	bsze.y = (LINES - 1) / 3;
+	/*
+	 * Clear things for a new level
+	 */
+	for (rp = rooms; rp < &rooms[MAXROOMS]; rp++)
+		rp->r_goldval = rp->r_nexits = rp->r_flags = 0;
+	/*
+	 * Put the gone rooms, if any, on the level
+	 */
+	left_out = rnd(4);
+	for (i = 0; i < left_out; i++)
+		rooms[rnd_room()].r_flags |= ISGONE;
+	/*
+	 * dig and populate all the rooms on the level
+	 */
+	for (i = 0, rp = rooms; i < MAXROOMS; rp++, i++) {
+		/*
+		 * Find upper left corner of box that this room goes in
+		 */
+		top.x = (i%3) * bsze.x + 1;
+		top.y = i/3 * bsze.y;
+		if (rf_on(rp,ISGONE)) {
+			/*
+			 * Place a gone room.  Make certain that there is a
+			 * blank line for passage drawing.
+			 */
+			roomtries = 0;
+			do {
+				rp->r_pos.x = top.x + rnd(bsze.x-2) + 1;
+				rp->r_pos.y = top.y + rnd(bsze.y-2) + 1;
+				rp->r_max.x = -COLS;
+				rp->r_max.x = -LINES;
+				if (++roomtries > 250)
+					fatal("failed to place a gone room");
+			} until(rp->r_pos.y > 0 && rp->r_pos.y < LINES-2);
+			continue;
+		}
+		if (rnd(10) < level-1)
+			rp->r_flags |= ISDARK;
+		/*
+		 * Find a place and size for a random room
+		 */
+		roomtries = 0;	
+		do {
+			rp->r_max.x = rnd(bsze.x - 4) + 4;
+			rp->r_max.y = rnd(bsze.y - 4) + 4;
+			rp->r_pos.x = top.x + rnd(bsze.x - rp->r_max.x);
+			rp->r_pos.y = top.y + rnd(bsze.y - rp->r_max.y);
+			if (++roomtries > 250) {
+				fatal("failed to place a good room");
+			}
+		} until (rp->r_pos.y != 0);
+		if (level < max_level)
+			mchance = 30;	/* 30% when going up (all monsters) */
+		else
+			mchance = 3;	/* 3% when going down */
+		treas = FALSE;
+		if (rnd(100) < mchance && (rp->r_max.x * rp->r_max.y) >
+		  ((bsze.x * bsze.y * 55) / 100)) {
+			treas = TRUE;
+			rp->r_flags |= ISTREAS;
+			rp->r_flags |= ISDARK;
+		}
+		/*
+		 * Put the gold in
+		 */
+		if ((rnd(100) < 50 || treas) && (!amulet || level >= max_level)) {
+			rp->r_goldval = GOLDCALC;
+			if (treas)
+				rp->r_goldval += 200 + (15 * (rnd(level) + 2));
+			rp->r_gold.y = rp->r_pos.y + rnd(rp->r_max.y - 2) + 1;
+			rp->r_gold.x = rp->r_pos.x + rnd(rp->r_max.x - 2) + 1;
+		}
+		draw_room(rp);
+		/*
+		 * Put the monster in
+		 */
+		if (treas) {
+			mloops = rnd(level / 3) + 6;
+			mchance = 1;
+		}
+		else {
+			mloops = 1;
+			mchance = 100;
+		}
+		for (nummons = 0; nummons < mloops; nummons++) {
+			if (rnd(mchance) < (rp->r_goldval > 0 ? 80 : 25))
+				add_mon(rp, treas);
+		}
+	}
+}
+
+/*
+ * add_mon:
+ *	Add a monster to a room
+ */
+add_mon(rm, treas)
+struct room *rm;
+bool treas;
+{
+	reg struct thing *tp;
+	reg struct linked_list *item;
+	struct coord mp;
+	int chance;
+
+	mp = *rnd_pos(rm);
+	item = new_monster(rnd_mon(FALSE,FALSE), &mp, treas);
+	tp = THINGPTR(item);
+	chance = rnd(100);
+	if (levtype == MAZELEV)
+		chance = rnd(50);
+	/*
+	 * See if monster has a treasure
+	 */
+	if (levtype == MAZELEV && rnd(100) < 20) {
+		reg struct linked_list *fd;
+
+		fd = new_thing(FALSE, FOOD, 0);
+		attach(tp->t_pack, fd);
+	}
+	else {
+		if (chance < monsters[tp->t_indx].m_carry)
+			attach(tp->t_pack, new_thing(FALSE, ANYTHING));
+	}
+}
+
+/*
+ * draw_room:
+ *	Draw a box around a room
+ */
+draw_room(rp)
+struct room *rp;
+{
+	reg int j, k;
+
+	move(rp->r_pos.y, rp->r_pos.x+1);
+	vert(rp->r_max.y-2);			/* Draw left side */
+	move(rp->r_pos.y+rp->r_max.y-1, rp->r_pos.x);
+	horiz(rp->r_max.x);				/* Draw bottom */
+	move(rp->r_pos.y, rp->r_pos.x);
+	horiz(rp->r_max.x);				/* Draw top */
+	vert(rp->r_max.y-2);			/* Draw right side */
+	/*
+	 * Put the floor down
+	 */
+	for (j = 1; j < rp->r_max.y - 1; j++) {
+		move(rp->r_pos.y + j, rp->r_pos.x + 1);
+		for (k = 1; k < rp->r_max.x - 1; k++) {
+			addch(FLOOR);
+		}
+	}
+	/*
+	 * Put the gold there
+	 */
+	if (rp->r_goldval > 0)
+		mvaddch(rp->r_gold.y, rp->r_gold.x, GOLD);
+}
+
+/*
+ * horiz:
+ *	draw a horizontal line
+ */
+horiz(cnt)
+int cnt;
+{
+	while (cnt-- > 0)
+	addch('-');
+}
+
+
+/*
+ * vert:
+ *	draw a vertical line
+ */
+vert(cnt)
+int cnt;
+{
+	reg int x, y;
+
+	getyx(stdscr, y, x);
+	x--;
+	while (cnt-- > 0) {
+		move(++y, x);
+		addch('|');
+	}
+}
+
+
+/*
+ * rnd_pos:
+ *	pick a random spot in a room
+ */
+struct coord *
+rnd_pos(rp)
+struct room *rp;
+{
+	reg int y, x, i;
+	static struct coord spot;
+
+	i = 0;
+	do {
+		x = rp->r_pos.x + rnd(rp->r_max.x - 2) + 1;
+		y = rp->r_pos.y + rnd(rp->r_max.y - 2) + 1;
+		i += 1;
+	} while(winat(y, x) != FLOOR && i < 1000);
+	spot.x = x;
+	spot.y = y;
+	return &spot;
+}
+
+/*
+ * rf_on:
+ * 	Returns TRUE if flag is set for room stuff
+ */
+rf_on(rm, bit)
+struct room *rm;
+long bit;
+{
+	return (rm->r_flags & bit);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/srogue/save.c	Thu Nov 25 12:21:41 2010 +0000
@@ -0,0 +1,339 @@
+/*
+ * save and restore routines
+ *
+ * @(#)save.c	9.0	(rdk)	 7/17/84
+ *
+ * Super-Rogue
+ * Copyright (C) 1984 Robert D. Kindelberger
+ * All rights reserved.
+ *
+ * Based on "Rogue: Exploring the Dungeons of Doom"
+ * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
+ * All rights reserved.
+ *
+ * See the file LICENSE.TXT for full copyright and licensing information.
+ */
+
+#include <unistd.h>
+#include <ctype.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <signal.h>
+#include <errno.h>
+#include "rogue.h"
+#include "rogue.ext"
+
+#ifdef BSD
+#define srand48(seed)	srandom(seed)
+#endif
+
+EXTCHAR version[];
+EXTCHAR *ctime();
+
+typedef struct stat STAT;
+STAT sbuf;
+
+/*
+ * ignore:
+ *	Ignore ALL signals possible
+ */
+ignore()
+{
+	int i;
+
+	for (i = 0; i < NSIG; i++)
+		signal(i, SIG_IGN);
+}
+
+/*
+ * save_game:
+ *	Save the current game
+ */
+save_game()
+{
+	reg FILE *savef;
+	reg int c;
+	char buf[LINLEN];
+
+	mpos = 0;
+	if (file_name[0] != '\0') {
+		msg("Save file (%s)? ", file_name);
+		do {
+			c = wgetch(cw);
+			if(c == ESCAPE) {
+				msg("");
+				return FALSE;
+			}
+		} while (c != 'n' && c != 'y');
+		mpos = 0;
+		if (c == 'y')
+			goto gotfile;
+	}
+	msg("File name: ");
+	mpos = 0;
+	buf[0] = '\0';
+	if (get_str(buf, cw) == QUIT) {
+		msg("");
+		return FALSE;
+	}
+	msg("");
+	strcpy(file_name, buf);
+gotfile:
+	c = dosave();		/* try to save this game */
+	if (c == FALSE)
+		msg("Could not save game to file %s", file_name);
+	return c;
+}
+
+/*
+ * auto_save:
+ *	Automatically save a game
+ */
+void
+auto_save(int a)
+{
+	dosave();		/* save this game */
+	byebye(1);		/* so long for now */
+}
+
+/*
+ * game_err:
+ *	When an error occurs. Set error flag and save game.
+ */
+void
+game_err(int a)
+{
+	int ok;
+
+	ok = dosave();			/* try to save this game */
+	clear();
+	refresh();
+	endwin();
+
+	printf("\nInternal error !!!\n\nYour game was ");
+	if (ok)
+		printf("saved.");
+	else
+		printf("NOT saveable.");
+
+	fflush(stdout);
+
+#ifdef SIGIOT
+	signal(SIGIOT, SIG_DFL);	/* allow core dump signal */
+#endif
+
+	abort();			/* cause core dump */
+	byebye(3);
+}
+
+/*
+ * dosave:
+ *	Set UID back to user and save the game
+ */
+dosave()
+{
+	FILE *savef;
+
+	ignore();
+	setuid(playuid);
+	setgid(playgid);
+	umask(022);
+
+	if (file_name[0] != '\0') {
+		if ((savef = fopen(file_name,"w")) != NULL)
+		{
+			save_file(savef);
+			return TRUE;
+		}
+	}
+	return FALSE;
+}
+
+/*
+ * save_file:
+ *	Do the actual save of this game to a file
+ */
+save_file(savef)
+FILE *savef;
+{
+	reg int fnum;
+	int slines = LINES;
+	int scols = COLS;
+
+#ifdef __DJGPP__                      /* st_ino w/ DJGPP under WinXP broken */
+        _djstat_flags |= _STAT_INODE; /* so turn off computing it for now   */
+#endif
+
+	/*
+	 * force allocation of the buffer now so that inodes, etc
+	 * can be checked when restoring saved games.
+	 */
+	fnum = fileno(savef);
+	fstat(fnum, &sbuf);
+	write(fnum, "RDK", 4);
+	lseek(fnum, 0L, 0);
+	encwrite(version,strlen(version)+1,savef);
+	encwrite(&sbuf.st_ino,sizeof(sbuf.st_ino),savef);
+	encwrite(&sbuf.st_dev,sizeof(sbuf.st_dev),savef);
+	encwrite(&sbuf.st_ctime,sizeof(sbuf.st_ctime),savef);
+	encwrite(&sbuf.st_mtime,sizeof(sbuf.st_mtime),savef);
+	encwrite(&slines,sizeof(slines),savef);
+	encwrite(&scols,sizeof(scols),savef);
+	msg("");
+	rs_save_file(savef);
+	close(fnum);
+	signal(SIGINT, byebye);
+	signal(SIGQUIT, byebye);
+	wclear(cw);
+	draw(cw);
+}
+
+/*
+ * restore:
+ *	Restore a saved game from a file
+ */
+restore(file, envp)
+char *file, **envp;
+{
+	register inf, pid;
+	int ret_status;
+#ifndef _AIX
+	extern char **environ;
+#endif
+#ifdef __DJGPP__                      /* st_ino w/ DJGPP under WinXP broken */
+        _djstat_flags |= _STAT_INODE; /* so turn off computing it for now   */
+#endif
+	char buf[LINLEN];
+	STAT sbuf2;
+	int slines, scols;
+
+	if ((inf = open(file, O_RDONLY)) < 0) {
+		printf("Cannot read save game %s\n",file);
+		return FALSE;
+	}
+
+	encread(buf, strlen(version) + 1, inf);
+
+	if (strcmp(buf, version) != 0) {
+		printf("Sorry, saved game version is out of date.\n");
+		return FALSE;
+	}
+
+	fstat(inf, &sbuf2);
+
+	encread(&sbuf.st_ino,sizeof(sbuf.st_ino), inf);
+	encread(&sbuf.st_dev,sizeof(sbuf.st_dev), inf);
+	encread(&sbuf.st_ctime,sizeof(sbuf.st_ctime), inf);
+	encread(&sbuf.st_mtime,sizeof(sbuf.st_mtime), inf);
+	encread(&slines,sizeof(slines),inf);
+	encread(&scols,sizeof(scols),inf);
+
+	/*
+	 * we do not close the file so that we will have a hold of the
+	 * inode for as long as possible
+	 */
+
+	if (!wizard)
+	{
+		if(sbuf2.st_ino!=sbuf.st_ino || sbuf2.st_dev!=sbuf.st_dev) {
+			printf("Sorry, saved game is not in the same file.\n");
+			return FALSE;
+		}
+	}
+
+#ifdef __INTERIX
+	setenv("TERM","interix");
+#endif
+
+	initscr();
+
+	if (slines > LINES)
+	{
+		endwin();
+		printf("Sorry, original game was played on a screen with %d lines.\n",slines);
+		printf("Current screen only has %d lines. Unable to restore game\n",LINES);
+		return(FALSE);
+	}
+
+	if (scols > COLS)
+	{
+		endwin();
+		printf("Sorry, original game was played on a screen with %d columns.\n", scols);
+		printf("Current screen only has %d columns. Unable to restore game\n",COLS);
+		return(FALSE);
+	}
+
+	cw = newwin(LINES, COLS, 0, 0);
+	mw = newwin(LINES, COLS, 0, 0);
+	hw = newwin(LINES, COLS, 0, 0);
+
+	mpos = 0;
+	mvwprintw(cw, 0, 0, "%s: %s", file, ctime(&sbuf2.st_mtime));
+
+	/* defeat multiple restarting from the same place */
+
+	if (!wizard)
+	{
+		if (sbuf2.st_nlink != 1)
+		{
+                        endwin();
+			printf("Cannot restore from a linked file\n");
+			return FALSE;
+		}
+	}
+
+	if (rs_restore_file(inf) == FALSE)
+	{
+		endwin();
+		printf("Cannot restore file\n");
+		return(FALSE);
+	}
+
+#if defined(__CYGWIN__) || defined(__DJGPP__)
+	close(inf);
+#endif
+	if (!wizard)
+	{
+#ifndef __DJGPP__
+			endwin();
+			while((pid = fork()) < 0)
+				sleep(1);
+
+			/* set id to unlink file */
+			if(pid == 0)
+			{
+				setuid(playuid);
+				setgid(playgid);
+				unlink(file);
+				exit(0);
+			}
+			/* wait for unlink to finish */
+			else
+			{
+				while(wait(&ret_status) != pid)
+					continue;
+				if (ret_status < 0)
+				{
+					printf("Cannot unlink file\n");
+					return FALSE;
+				}
+			}
+#else
+		if (unlink(file) < 0)
+		{
+			printf("Cannot unlink file\n");
+			return FALSE;
+		}
+#endif
+
+	}
+
+	environ = envp;
+
+	strcpy(file_name, file);
+	setup();
+	restscr(cw);
+	srand48(getpid());
+	playit();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/srogue/scrolls.c	Thu Nov 25 12:21:41 2010 +0000
@@ -0,0 +1,463 @@
+/*
+ * Read a scroll and let it happen
+ *
+ * @(#)scrolls.c	9.0	(rdk)	 7/17/84
+ *
+ * Super-Rogue
+ * Copyright (C) 1984 Robert D. Kindelberger
+ * All rights reserved.
+ *
+ * Based on "Rogue: Exploring the Dungeons of Doom"
+ * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
+ * All rights reserved.
+ *
+ * See the file LICENSE.TXT for full copyright and licensing information.
+ */
+
+#include <ctype.h>
+#include "rogue.h"
+#include "rogue.ext"
+
+/*
+ * read_scroll:
+ *	Let the hero read a scroll
+ */
+read_scroll()
+{
+	reg struct object *obj;
+	reg struct linked_list *item;
+	reg int i, j, wh;
+	reg char ch, nch;
+	struct room *rp;
+	struct linked_list *titem;
+	char buf[LINLEN];
+	bool bless, curse;
+
+	if ((item = get_item("read", SCROLL)) == NULL)
+		return;
+	obj = OBJPTR(item);
+	if (obj->o_type != SCROLL) {
+		msg("Nothing to read.");
+		after = FALSE;
+		return;
+	}
+	msg("As you read the scroll, it vanishes.");
+	wh = obj->o_which;
+	bless = o_on(obj, ISBLESS);
+	curse = o_on(obj, ISCURSED);
+	del_pack(item);		/* Get rid of the thing */
+
+	/*
+	 * Calculate the effect it has on the hero
+	 */
+	switch(wh) {
+	case S_KNOWALL:
+		if (!curse) {
+			idenpack();				/* identify all the pack */
+			msg("You feel more knowledgable.");
+			chg_abil(WIS,1,TRUE);
+			s_know[S_KNOWALL] = TRUE;
+		}
+	when S_CONFUSE:
+		if (!curse) {
+			/*
+			 * Scroll of monster confusion.  Give him that power.
+			 */
+			msg("Your hands begin to glow red.");
+			player.t_flags |= CANHUH;
+			s_know[S_CONFUSE] = TRUE;
+		}
+	when S_LIGHT:
+		rp = player.t_room;
+		if (!curse) {
+			if (rp == NULL) {
+				s_know[S_LIGHT] = TRUE;
+				msg("The corridor glows and then fades.");
+			}
+			else {
+				if (rf_on(rp,ISDARK)) {
+					s_know[S_LIGHT] = TRUE;
+					msg("The room is lit.");
+					rp->r_flags &= ~ISDARK;
+				}
+				light(&hero);
+				mvwaddch(cw, hero.y, hero.x, PLAYER);
+			}
+		}
+	when S_ARMOR:
+		if (!curse) {
+			if (cur_armor != NULL && o_off(cur_armor,ISPROT)) {
+				s_know[S_ARMOR] = TRUE;
+				msg("Your armor glows faintly for a moment.");
+				if (o_on(cur_armor,ISCURSED))
+					cur_armor->o_ac = armors[cur_armor->o_which].a_class;
+				else
+					cur_armor->o_ac--;
+				resoflg(cur_armor,ISCURSED);
+			}
+		}
+	when S_HOLD:
+		if (!curse) {
+			/*
+			 * Hold monster scroll.  Stop all monsters within 3 spaces
+			 * from chasing after the hero.
+			 */
+			reg int x,y;
+			reg struct linked_list *mon;
+
+			for (x = hero.x - 3; x <= hero.x + 3; x++) {
+				for (y = hero.y - 3; y <= hero.y + 3; y++) {
+					if (y > 0 && x > 0 && isalpha(mvwinch(mw, y, x))) {
+						if ((mon = find_mons(y, x)) != NULL) {
+							reg struct thing *th;
+
+							th = THINGPTR(mon);
+							th->t_flags &= ~ISRUN;
+							th->t_flags |= ISHELD;
+							th->t_flags |= ISSTUCK;
+						}
+					}
+				}
+			}
+		}
+	when S_SLEEP:
+		/*
+		 * Scroll which makes you fall asleep
+		 */
+		if (!bless) {
+			s_know[S_SLEEP] = TRUE;
+			msg("You fall asleep.");
+			player.t_nocmd += 4 + rnd(SLEEPTIME);
+		}
+	when S_CREATE:
+		if (!bless) {
+			if (makemons(mtlev[rnd(levcount)]->m_show))
+				s_know[S_CREATE] = TRUE;
+			else
+				msg("You hear a faint cry of anguish in the distance.");
+		}
+	when S_IDENT:
+		if (!curse) {
+			msg("This scroll is an identify scroll");
+			s_know[S_IDENT] = TRUE;
+			whatis(NULL);
+		}
+	when S_MAP:
+		if (curse)
+			break;
+		s_know[S_MAP] = TRUE;
+		addmsg("Oh, now this scroll has a ");
+		if (rnd(100) < 10 || bless) {
+			addmsg("very detailed map on it.");
+			endmsg();
+			displevl();
+		}
+		else {
+			addmsg("map on it.");
+			endmsg();
+			overwrite(stdscr, hw);
+			for (i = 1; i < LINES - 2; i++) {
+				for (j = 0; j < COLS; j++) {
+					switch (nch = ch = mvwinch(hw, i, j)) {
+						case SECRETDOOR:
+							nch = DOOR;
+							mvaddch(i, j, nch);
+						case '-':
+						case '|':
+						case DOOR:
+						case PASSAGE:
+						case ' ':
+						case STAIRS:
+							if (mvwinch(mw, i, j) != ' ') {
+								struct thing *it;
+								struct linked_list *blah;
+
+								blah = find_mons(i, j);
+								if (blah != NULL) {
+									it = THINGPTR(blah);
+									if (it->t_oldch == ' ')
+										it->t_oldch = nch;
+								}
+							}
+							break;
+						default:
+							nch = ' ';
+					}
+					if (nch != ch)
+						waddch(hw, nch);
+				}
+			}
+			overlay(cw, hw);
+			overwrite(hw, cw);
+		}
+	when S_GFIND:
+		if (!curse) {
+			int gtotal = 0;
+			struct room *rp;
+
+			wclear(hw);
+			for (rp = rooms; rp < &rooms[MAXROOMS]; rp++) {
+				gtotal += rp->r_goldval;
+				if (rp->r_goldval != 0 &&
+				  mvinch(rp->r_gold.y,rp->r_gold.x) == GOLD)
+					mvwaddch(hw,rp->r_gold.y,rp->r_gold.x,GOLD);
+			}
+			if (gtotal) {
+				s_know[S_GFIND] = TRUE;
+				msg("You begin to feel greedy and sense gold.");
+				overlay(hw,cw);
+			}
+			else
+				msg("You begin to feel a pull downward.");
+		}
+	when S_TELEP:
+		if (!curse) {
+			int rm;
+			struct room *cur_room;
+
+			cur_room = player.t_room;
+			rm = teleport(rndspot, &player);
+			if (cur_room != &rooms[rm])
+				s_know[S_TELEP] = TRUE;
+		}
+	when S_ENCH:
+		if (!curse) {
+			if (cur_weapon == NULL || (cur_weapon != NULL &&
+			  (o_on(cur_weapon,ISPROT) || cur_weapon->o_type != WEAPON)))
+				msg("You feel a strange sense of loss.");
+			else {
+				s_know[S_ENCH] = TRUE;
+				if (o_on(cur_weapon,ISCURSED)) {
+					resoflg(cur_weapon,ISCURSED);
+					cur_weapon->o_hplus = rnd(2);
+					cur_weapon->o_dplus = rnd(2);
+				}
+				else {		/* weapon was not cursed here */
+					if (rnd(100) < 50)
+						cur_weapon->o_hplus += 1;
+					else
+						cur_weapon->o_dplus += 1;
+				}
+				setoflg(cur_weapon, ISKNOW);
+				msg("Your %s glows blue for a moment.",
+				  w_magic[cur_weapon->o_which].mi_name);
+			}
+		}
+	when S_SCARE:
+		/*
+		 * A monster will refuse to step on a scare monster scroll
+		 * if it is dropped.  Thus reading it is a mistake and produces
+		 * laughter at the poor rogue's boo boo.
+		 */
+		msg("You hear maniacal laughter in the distance.");
+	when S_REMOVE:
+		if (!curse) {
+			if (cur_armor != NULL && o_off(cur_armor,ISPROT))
+				resoflg(cur_armor,ISCURSED);
+			if (cur_weapon != NULL && o_off(cur_weapon,ISPROT))
+				resoflg(cur_weapon,ISCURSED);
+			if (cur_ring[LEFT]!=NULL && o_off(cur_ring[LEFT],ISPROT))
+				resoflg(cur_ring[LEFT],ISCURSED);
+			if (cur_ring[RIGHT]!=NULL && o_off(cur_ring[RIGHT],ISPROT))
+				resoflg(cur_ring[RIGHT],ISCURSED);
+			msg("You feel as if somebody is watching over you.");
+			s_know[S_REMOVE] = TRUE;
+		}
+	when S_AGGR:
+		if (!bless) {
+			if (mlist != NULL) {
+				aggravate();
+				msg("You hear a high pitched humming noise.");
+				s_know[S_AGGR] = TRUE;
+			}
+		}
+	when S_NOP:
+		msg("This scroll seems to be blank.");
+	when S_GENOCIDE:
+		if (!curse) {
+			msg("You have been granted the boon of genocide.");
+			genocide();
+			s_know[S_GENOCIDE] = TRUE;
+		}
+	when S_DCURSE:
+		if (!bless) {
+			struct linked_list *ll;
+			struct object *lb;
+
+			msg("Your pack shudders.");
+			for (ll = pack ; ll != NULL ; ll = next(ll)) {
+				lb = OBJPTR(ll);
+				if (o_off(lb,ISPROT)) {
+					resoflg(lb, ISBLESS);
+					setoflg(lb, ISCURSED);
+				}
+			}
+		}
+	when S_DLEVEL:
+		if (!bless) {
+			int much = rnd(9) - 4;
+
+			if (much != 0) {
+				level += much;
+				if (level < 1)
+					level = 1;
+				mpos = 0;
+				new_level(NORMLEV);		/* change levels */
+				msg("You are whisked away to another region.");
+				s_know[S_DLEVEL] = TRUE;
+			}
+		}
+	when S_PROTECT:
+		if (!curse) {
+			struct linked_list *ll;
+			struct object *lb;
+
+			msg("You are granted the power of protection.");
+			if ((ll = get_item("protect",0)) != NULL) {
+				lb = OBJPTR(ll);
+				setoflg(lb,ISPROT);
+				mpos = 0;
+				msg("Protected %s.",inv_name(lb,TRUE));
+			}
+			s_know[S_PROTECT] = TRUE;
+		}
+	when S_ALLENCH:
+		if (!curse) {
+			struct linked_list *ll;
+			struct object *lb;
+			int howmuch, ac, good;
+
+			msg("You are granted the power of enchantment.");
+			good = TRUE;
+			if ((ll = get_item("enchant",0)) != NULL) {
+				lb = OBJPTR(ll);
+				resoflg(lb,ISCURSED);
+				resoflg(lb,ISPROT);
+				howmuch = rnd(3) + 1;
+				switch(lb->o_type) {
+					case RING:
+						if (lb->o_ac < 0)
+							lb->o_ac = 0;
+						lb->o_ac += howmuch;
+					when ARMOR:
+						ac = armors[lb->o_which].a_class;
+						if (lb->o_ac > ac)
+							lb->o_ac = ac;
+						lb->o_ac -= howmuch;
+					when STICK:
+						lb->o_charges += howmuch + 10;
+					when WEAPON:
+						if (lb->o_dplus < 0)
+							lb->o_dplus = 0;
+						if (lb->o_hplus < 0)
+							lb->o_hplus = 0;
+						lb->o_hplus += howmuch;
+						lb->o_dplus += howmuch;
+					otherwise:
+						msg("You are injured as the scroll flashes & bursts into flames !!!");
+						chg_hpt(-roll(6,6),FALSE,K_SCROLL);
+						good = FALSE;
+				}
+				if (good) {
+					mpos = 0;
+					msg("Enchanted %s.",inv_name(lb,TRUE));
+				}
+			}
+			s_know[S_ALLENCH] = TRUE;
+		}
+	when S_BLESS:
+		if (!curse) {
+			struct linked_list *ll;
+			struct object *lb;
+
+			msg("Your pack glistens brightly.");
+			for (ll = pack ; ll != NULL ; ll = next(ll)) {
+				whatis(ll);
+				lb = OBJPTR(ll);
+				resoflg(lb,ISCURSED);
+				setoflg(lb,ISBLESS);
+			}
+		}
+	when S_MAKEIT:
+		if (!curse) {
+			msg("You have been endowed with the power of creation.");
+			s_know[S_MAKEIT] = TRUE;
+			create_obj(TRUE);
+		}
+	when S_BAN: {
+		int howdeep;
+		char *ptr;
+
+		if (bless) {
+			if (level > 6) {
+				howdeep = 1 + rnd(5);
+				ptr = "elevated to the upper";
+			}
+			else {
+				howdeep = -1;
+				bless = FALSE;
+			}
+		}
+		else {
+			howdeep = level + 10 + rnd(20) + (curse * 20);
+			ptr = "banished to the lower";
+		}
+		if ((!bless && level < howdeep) || bless) {
+			level = howdeep;
+			new_level(NORMLEV);
+			mpos = 0;
+			msg("You are %s regions.", ptr);
+			s_know[S_BAN] = TRUE;
+		}
+	}
+	when S_CWAND:
+		if (!curse) {
+			struct linked_list *ll;
+			struct object *lb;
+			bool wands = FALSE;
+
+			for (ll = pack ; ll != NULL ; ll = next(ll)) {
+				lb = OBJPTR(ll);
+				if (lb->o_type == STICK) {
+					whatis(ll);
+					setoflg(lb, ISKNOW);
+					resoflg(lb, ISCURSED);
+					lb->o_charges += rnd(11) + 5;
+					wands = TRUE;
+				}
+			}
+			if (wands) {
+				msg("Your sticks gleam.");
+				s_know[wh] = TRUE;
+			}
+		}
+	when S_LOCTRAP: {
+		struct trap *trp;
+
+		if (ntraps > 0) {
+			for (trp = &traps[0]; trp < &traps[ntraps]; trp++)
+				trp->tr_flags |= ISFOUND;
+			look(FALSE);
+			msg("You now recognize pitfalls.");
+			s_know[S_LOCTRAP] = TRUE;
+		}
+	}
+	otherwise:
+		msg("What a puzzling scroll!");
+		return;
+	}
+	look(TRUE);
+	nochange = FALSE;
+	if (s_know[wh] && s_guess[wh]) {
+		free(s_guess[wh]);
+		s_guess[wh] = NULL;
+	}
+	else if (!s_know[wh] && s_guess[wh] == NULL) {
+		strcpy(buf, s_names[wh]);
+		msg(callit);
+		if (get_str(buf, cw) == NORM) {
+			s_guess[wh] = new(strlen(buf) + 1);
+			strcpy(s_guess[wh], buf);
+		}
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/srogue/state.c	Thu Nov 25 12:21:41 2010 +0000
@@ -0,0 +1,2320 @@
+/*
+    state.c - Portable Rogue Save State Code
+
+    Copyright (C) 1999, 2000, 2005 Nicholas J. Kisseberth
+
+    Redistribution and use in source and binary forms, with or without
+    modification, are permitted provided that the following conditions
+    are met:
+    1. Redistributions of source code must retain the above copyright
+       notice, this list of conditions and the following disclaimer.
+    2. Redistributions in binary form must reproduce the above copyright
+       notice, this list of conditions and the following disclaimer in the
+       documentation and/or other materials provided with the distribution.
+    3. Neither the name(s) of the author(s) nor the names of other contributors
+       may be used to endorse or promote products derived from this software
+       without specific prior written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) AND CONTRIBUTORS ``AS IS'' AND
+    ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+    IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+    ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR(S) OR CONTRIBUTORS BE LIABLE
+    FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+    DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+    OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+    HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+    LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+    OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+    SUCH DAMAGE.
+*/
+
+/************************************************************************/
+/* Save State Code                                                      */
+/************************************************************************/
+
+#define RSID_STATS        0xABCD0001
+#define RSID_THING        0xABCD0002
+#define RSID_THING_NULL   0xDEAD0002
+#define RSID_OBJECT       0xABCD0003
+#define RSID_MAGICITEMS   0xABCD0004
+#define RSID_KNOWS        0xABCD0005
+#define RSID_GUESSES      0xABCD0006
+#define RSID_OBJECTLIST   0xABCD0007
+#define RSID_BAGOBJECT    0xABCD0008
+#define RSID_MONSTERLIST  0xABCD0009
+#define RSID_MONSTERSTATS 0xABCD000A
+#define RSID_MONSTERS     0xABCD000B
+#define RSID_TRAP         0xABCD000C
+#define RSID_WINDOW       0xABCD000D
+#define RSID_DAEMONS      0xABCD000E
+#define RSID_IWEAPS       0xABCD000F
+#define RSID_IARMOR       0xABCD0010
+#define RSID_SPELLS       0xABCD0011
+#define RSID_ILIST        0xABCD0012
+#define RSID_HLIST        0xABCD0013
+#define RSID_DEATHTYPE    0xABCD0014
+#define RSID_CTYPES       0XABCD0015
+#define RSID_COORDLIST    0XABCD0016
+#define RSID_ROOMS        0XABCD0017
+
+
+#include <curses.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include "rogue.h"
+#include "rogue.ext"
+
+#define READSTAT ((format_error == 0) && (read_error == 0))
+#define WRITESTAT (write_error == 0)
+
+int read_error   = FALSE;
+int write_error  = FALSE;
+int format_error = FALSE;
+int end_of_file  = FALSE;
+int big_endian   = 0;
+const char *fmterr = "";
+
+char encstr[] = "\354\251\243\332A\201|\301\321p\210\251\327\"\257\365t\341%3\271^`~\203z{\341};\f\341\231\222e\234\351]\321";
+
+/*
+ * perform an encrypted write
+ */
+encwrite(starta, size, outf)
+register void *starta;
+unsigned int size;
+register FILE *outf;
+{
+    register char *ep;
+    register char *start = starta;
+
+    ep = encstr;
+
+    while (size--)
+    {
+        putc(*start++ ^ *ep++, outf);
+        if (*ep == '\0')
+            ep = encstr;
+    }
+}
+
+/*
+ * perform an encrypted read
+ */
+encread(starta, size, inf)
+register void *starta;
+unsigned int size;
+register int inf;
+{
+    register char *ep;
+    register int read_size;
+    register char *start = starta;
+
+    if ((read_size = read(inf, start, size)) == -1 || read_size == 0)
+        return read_size;
+
+    ep = encstr;
+
+    while (size--)
+    {
+        *start++ ^= *ep++;
+        if (*ep == '\0')
+            ep = encstr;
+    }
+    return read_size;
+}
+
+void *
+get_list_item(struct linked_list *l, int i)
+{
+    int count = 0;
+
+    while(l != NULL)
+    {   
+        if (count == i)
+            return(l->l_data);
+                        
+        l = l->l_next;
+        
+        count++;
+    }
+    
+    return(NULL);
+}
+
+int
+find_list_ptr(struct linked_list *l, void *ptr)
+{
+    int count = 0;
+
+    while(l != NULL)
+    {
+        if (l->l_data == ptr)
+            return(count);
+            
+        l = l->l_next;
+        count++;
+    }
+    
+    return(-1);
+}
+
+int
+list_size(struct linked_list *l)
+{
+    int count = 0;
+    
+    while(l != NULL)
+    {
+        if (l->l_data == NULL)
+            return(count);
+            
+        count++;
+        
+        l = l->l_next;
+    }
+    
+    return(count);
+}
+
+int
+rs_write(FILE *savef, void *ptr, int size)
+{
+    if (!write_error)
+        encwrite(ptr,size,savef);
+
+    if (0)
+        write_error = TRUE;
+        
+    assert(write_error == 0);
+
+    return(WRITESTAT);
+}
+
+int
+rs_write_char(FILE *savef, char c)
+{
+    rs_write(savef, &c, 1);
+    
+    return(WRITESTAT);
+}
+
+int
+rs_write_boolean(FILE *savef, bool c)
+{
+    unsigned char buf = (c == 0) ? 0 : 1;
+    
+    rs_write(savef, &buf, 1);
+
+    return(WRITESTAT);
+}
+
+int
+rs_write_booleans(FILE *savef, bool *c, int count)
+{
+    int n = 0;
+
+    rs_write_int(savef,count);
+    
+    for(n = 0; n < count; n++)
+        rs_write_boolean(savef,c[n]);
+
+    return(WRITESTAT);
+}
+
+int
+rs_write_shint(FILE *savef, unsigned char c)
+{
+    unsigned char buf = c;
+
+    rs_write(savef, &buf, 1);
+
+    return(WRITESTAT);
+}
+
+int
+rs_write_short(FILE *savef, short c)
+{
+    unsigned char bytes[2];
+    unsigned char *buf = (unsigned char *) &c;
+
+    if (big_endian)
+    {
+        bytes[1] = buf[0];
+        bytes[0] = buf[1];
+        buf = bytes;
+    }
+
+    rs_write(savef, buf, 2);
+
+    return(WRITESTAT);
+}
+
+int
+rs_write_shorts(FILE *savef, short *c, int count)
+{
+    int n = 0;
+
+    rs_write_int(savef,count);
+    
+    for(n = 0; n < count; n++)
+        rs_write_short(savef,c[n]);
+
+    return(WRITESTAT);
+}
+
+int
+rs_write_ushort(FILE *savef, unsigned short c)
+{
+    unsigned char bytes[2];
+    unsigned char *buf = (unsigned char *) &c;
+
+    if (big_endian)
+    {
+        bytes[1] = buf[0];
+        bytes[0] = buf[1];
+        buf = bytes;
+    }
+
+    rs_write(savef, buf, 2);
+
+    return(WRITESTAT);
+}
+
+int
+rs_write_int(FILE *savef, int c)
+{
+    unsigned char bytes[4];
+    unsigned char *buf = (unsigned char *) &c;
+
+    if (big_endian)
+    {
+        bytes[3] = buf[0];
+        bytes[2] = buf[1];
+        bytes[1] = buf[2];
+        bytes[0] = buf[3];
+        buf = bytes;
+    }
+    
+    rs_write(savef, buf, 4);
+
+    return(WRITESTAT);
+}
+
+int
+rs_write_ints(FILE *savef, int *c, int count)
+{
+    int n = 0;
+
+    rs_write_int(savef,count);
+    
+    for(n = 0; n < count; n++)
+        rs_write_int(savef,c[n]);
+
+    return(WRITESTAT);
+}
+
+int
+rs_write_uint(FILE *savef, unsigned int c)
+{
+    unsigned char bytes[4];
+    unsigned char *buf = (unsigned char *) &c;
+
+    if (big_endian)
+    {
+        bytes[3] = buf[0];
+        bytes[2] = buf[1];
+        bytes[1] = buf[2];
+        bytes[0] = buf[3];
+        buf = bytes;
+    }
+    
+    rs_write(savef, buf, 4);
+
+    return(WRITESTAT);
+}
+
+int
+rs_write_long(FILE *savef, long c)
+{
+    int c2;
+    unsigned char bytes[4];
+    unsigned char *buf = (unsigned char *)&c;
+
+    if (sizeof(long) == 8)
+    {
+        c2 = c;
+        buf = (unsigned char *) &c2;
+    }
+
+    if (big_endian)
+    {
+        bytes[3] = buf[0];
+        bytes[2] = buf[1];
+        bytes[1] = buf[2];
+        bytes[0] = buf[3];
+        buf = bytes;
+    }
+    
+    rs_write(savef, buf, 4);
+
+    return(WRITESTAT);
+}
+
+int
+rs_write_longs(FILE *savef, long *c, int count)
+{
+    int n = 0;
+
+    rs_write_int(savef,count);
+    
+    for(n = 0; n < count; n++)
+        rs_write_long(savef,c[n]);
+
+    return(WRITESTAT);
+}
+
+int
+rs_write_ulong(FILE *savef, unsigned long c)
+{
+    unsigned int c2;
+    unsigned char bytes[4];
+    unsigned char *buf = (unsigned char *)&c;
+
+    if ( (sizeof(long) == 8) && (sizeof(int) == 4) )
+    {
+        c2 = c;
+        buf = (unsigned char *) &c2;
+    }
+
+    if (big_endian)
+    {
+        bytes[3] = buf[0];
+        bytes[2] = buf[1];
+        bytes[1] = buf[2];
+        bytes[0] = buf[3];
+        buf = bytes;
+    }
+    
+    rs_write(savef, buf, 4);
+
+    return(WRITESTAT);
+}
+
+int
+rs_write_ulongs(FILE *savef, unsigned long *c, int count)
+{
+    int n = 0;
+
+    rs_write_int(savef,count);
+    
+    for(n = 0; n < count; n++)
+        rs_write_ulong(savef,c[n]);
+
+    return(WRITESTAT);
+}
+
+int
+rs_write_string(FILE *savef, char *s)
+{
+    int len = 0;
+
+    len = (s == NULL) ? 0 : strlen(s) + 1;
+
+    rs_write_int(savef, len);
+    rs_write(savef, s, len);
+            
+    return(WRITESTAT);
+}
+
+int
+rs_write_string_index(FILE *savef, char *master[], int max, char *str)
+{
+    int i;
+
+    for(i = 0; i < max; i++)
+    {
+        if (str == master[i])
+        {
+            rs_write_int(savef,i);
+            return(WRITESTAT);
+        }
+    }
+
+    rs_write_int(savef,-1);
+
+    return(WRITESTAT);
+}
+
+int
+rs_write_strings(FILE *savef, char *s[], int count)
+{
+    int len = 0;
+    int n = 0;
+
+    rs_write_int(savef,count);
+
+    for(n = 0; n < count; n++)
+    {
+        len = (s[n] == NULL) ? 0L : strlen(s[n]) + 1;
+        rs_write_int(savef, len);
+        rs_write(savef, s[n], len);
+    }
+    
+    return(WRITESTAT);
+}
+
+int
+rs_read(int inf, void *ptr, int size)
+{
+    int actual;
+
+    end_of_file = FALSE;
+
+    if (!read_error && !format_error)
+    {
+        actual = encread(ptr, size, inf);
+
+        if ((actual == 0) && (size != 0))
+           end_of_file = TRUE;
+    }
+       
+    if (read_error)
+    {
+        printf("read error has occurred. restore short-circuited.\n");
+        abort();
+    }
+
+    if (format_error)
+    {
+        printf("format error: %s\r\n", fmterr);
+        printf("game format invalid. restore short-circuited.\n");
+        abort();
+    }
+
+    return(READSTAT);
+}
+
+int
+rs_read_char(int inf, char *c)
+{
+    rs_read(inf, c, 1);
+    
+    return(READSTAT);
+}
+
+int
+rs_read_boolean(int inf, bool *i)
+{
+    unsigned char buf;
+    
+    rs_read(inf, &buf, 1);
+    
+    *i = (bool) buf;
+    
+    return(READSTAT);
+}
+
+int
+rs_read_booleans(int inf, bool *i, int count)
+{
+    int n = 0, value = 0;
+    
+    if (rs_read_int(inf,&value) != 0)
+    {
+        if (value != count)
+        {
+            printf("Invalid booleans block. %d != requested %d\n",value,count); 
+            format_error = TRUE;
+        }
+        else
+        {
+            for(n = 0; n < value; n++)
+                rs_read_boolean(inf, &i[n]);
+        }
+    }
+    
+    return(READSTAT);
+}
+
+int
+rs_read_shint(int inf, unsigned char *i)
+{
+    unsigned char buf;
+    
+    rs_read(inf, &buf, 1);
+    
+    *i = (unsigned char) buf;
+    
+    return(READSTAT);
+}
+
+int
+rs_read_short(int inf, short *i)
+{
+    unsigned char bytes[2];
+    short  input;
+    unsigned char *buf = (unsigned char *)&input;
+    
+    rs_read(inf, &input, 2);
+
+    if (big_endian)
+    {
+        bytes[1] = buf[0];
+        bytes[0] = buf[1];
+        buf = bytes;
+    }
+    
+    *i = *((short *) buf);
+
+    return(READSTAT);
+} 
+
+int
+rs_read_shorts(int inf, short *i, int count)
+{
+    int n = 0, value = 0;
+
+    if (rs_read_int(inf,&value) != 0)
+    {
+        if (value != count)
+            format_error = TRUE;
+        else
+        {
+            for(n = 0; n < value; n++)
+                rs_read_short(inf, &i[n]);
+        }
+    }
+    
+    return(READSTAT);
+}
+
+int
+rs_read_ushort(int inf, unsigned short *i)
+{
+    unsigned char bytes[2];
+    unsigned short  input;
+    unsigned char *buf = (unsigned char *)&input;
+    
+    rs_read(inf, &input, 2);
+
+    if (big_endian)
+    {
+        bytes[1] = buf[0];
+        bytes[0] = buf[1];
+        buf = bytes;
+    }
+    
+    *i = *((unsigned short *) buf);
+
+    return(READSTAT);
+} 
+
+int
+rs_read_int(int inf, int *i)
+{
+    unsigned char bytes[4];
+    int  input;
+    unsigned char *buf = (unsigned char *)&input;
+    
+    rs_read(inf, &input, 4);
+
+    if (big_endian)
+    {
+        bytes[3] = buf[0];
+        bytes[2] = buf[1];
+        bytes[1] = buf[2];
+        bytes[0] = buf[3];
+        buf = bytes;
+    }
+    
+    *i = *((int *) buf);
+
+    return(READSTAT);
+}
+
+int
+rs_read_ints(int inf, int *i, int count)
+{
+    int n = 0, value = 0;
+    
+    if (rs_read_int(inf,&value) != 0)
+    {
+        if (value != count)
+            format_error = TRUE;
+        else
+        {
+            for(n = 0; n < value; n++)
+                rs_read_int(inf, &i[n]);
+        }
+    }
+    
+    return(READSTAT);
+}
+
+int
+rs_read_uint(int inf, unsigned int *i)
+{
+    unsigned char bytes[4];
+    int  input;
+    unsigned char *buf = (unsigned char *)&input;
+    
+    rs_read(inf, &input, 4);
+
+    if (big_endian)
+    {
+        bytes[3] = buf[0];
+        bytes[2] = buf[1];
+        bytes[1] = buf[2];
+        bytes[0] = buf[3];
+        buf = bytes;
+    }
+    
+    *i = *((unsigned int *) buf);
+
+    return(READSTAT);
+}
+
+int
+rs_read_long(int inf, long *i)
+{
+    unsigned char bytes[4];
+    long input;
+    unsigned char *buf = (unsigned char *) &input;
+    
+    rs_read(inf, &input, 4);
+
+    if (big_endian)
+    {
+        bytes[3] = buf[0];
+        bytes[2] = buf[1];
+        bytes[1] = buf[2];
+        bytes[0] = buf[3];
+        buf = bytes;
+    }
+    
+    *i = *((long *) buf);
+
+    return(READSTAT);
+}
+
+int
+rs_read_longs(int inf, long *i, int count)
+{
+    int n = 0, value = 0;
+    
+    if (rs_read_int(inf,&value) != 0)
+    {
+        if (value != count)
+            format_error = TRUE;
+        else
+        {
+            for(n = 0; n < value; n++)
+                rs_read_long(inf, &i[n]);
+        }
+    }
+    
+    return(READSTAT);
+}
+
+int
+rs_read_ulong(int inf, unsigned long *i)
+{
+    unsigned char bytes[4];
+    unsigned long input;
+    unsigned char *buf = (unsigned char *) &input;
+    
+    rs_read(inf, &input, 4);
+
+    if (big_endian)
+    {
+        bytes[3] = buf[0];
+        bytes[2] = buf[1];
+        bytes[1] = buf[2];
+        bytes[0] = buf[3];
+        buf = bytes;
+    }
+    
+    *i = *((unsigned long *) buf);
+
+    return(READSTAT);
+}
+
+int
+rs_read_ulongs(int inf, unsigned long *i, int count)
+{
+    int n = 0, value = 0;
+    
+    if (rs_read_int(inf,&value) != 0)
+    {
+        if (value != count)
+            format_error = TRUE;
+        else
+        {
+            for(n = 0; n < value; n++)
+                rs_read_ulong(inf, &i[n]);
+        }
+    }
+    
+    return(READSTAT);
+}
+
+int
+rs_read_string(int inf, char *s, int max)
+{
+    int len = 0;
+
+    if (rs_read_int(inf, &len) != FALSE)
+    {
+        if (len > max)
+        {
+            printf("String too long to restore. %d > %d\n",len,max);
+            printf("Sorry, invalid save game format\n");
+            format_error = TRUE;
+        }
+    
+        rs_read(inf, s, len);
+    }
+    
+    return(READSTAT);
+}
+
+int
+rs_read_new_string(int inf, char **s)
+{
+    int len=0;
+    char *buf=0;
+
+    if (rs_read_int(inf, &len) != 0)
+    {
+        if (len == 0)
+            *s = NULL;
+        else
+        { 
+            buf = malloc(len);
+
+            if (buf == NULL)            
+                read_error = TRUE;
+            else
+            {
+                rs_read(inf, buf, len);
+                *s = buf;
+            }
+        }
+    }
+
+    return(READSTAT);
+}
+
+int
+rs_read_string_index(int inf, char *master[], int maxindex, char **str)
+{
+    int i;
+
+    if (rs_read_int(inf,&i) != 0)
+    {
+        if (i > maxindex)
+        {
+            printf("String index is out of range. %d > %d\n", i, maxindex);
+            printf("Sorry, invalid save game format\n");
+            format_error = TRUE;
+        }
+        else if (i >= 0)
+            *str = master[i];
+        else
+            *str = NULL;
+    }
+
+    return(READSTAT);
+}
+
+int
+rs_read_strings(int inf, char **s, int count, int max)
+{
+    int len   = 0;
+    int n     = 0;
+    int value = 0;
+    
+    if (rs_read_int(inf,&value) != 0)
+    {
+        if (value != count)
+        {
+            printf("Incorrect number of strings in block. %d > %d.", 
+                value, count);
+            printf("Sorry, invalid save game format");
+            format_error = TRUE;
+        }
+        else
+        {
+            for(n = 0; n < value; n++)
+            {
+                rs_read_string(inf, s[n], max);
+            }
+        }
+    }
+    
+    return(READSTAT);
+}
+
+int
+rs_read_new_strings(int inf, char **s, int count)
+{
+    int len   = 0;
+    int n     = 0;
+    int value = 0;
+    
+    if (rs_read_int(inf,&value) != 0)
+    {
+        if (value != count)
+        {
+            printf("Incorrect number of new strings in block. %d > %d.",
+                value,count);abort();
+            printf("Sorry, invalid save game format");
+            format_error = TRUE;
+        }
+        else
+            for(n=0; n<value; n++)
+            {
+                rs_read_int(inf, &len);
+            
+                if (len == 0)
+                    s[n]=0;
+                else 
+                {
+                    s[n] = malloc(len);
+                    rs_read(inf,s[n],len);
+                }
+            }
+    }
+    
+    return(READSTAT);
+}
+
+/******************************************************************************/
+
+int
+rs_write_coord(FILE *savef, struct coord c)
+{
+    rs_write_int(savef, c.x);
+    rs_write_int(savef, c.y);
+    
+    return(WRITESTAT);
+}
+
+int
+rs_read_coord(int inf, struct coord *c)
+{
+    rs_read_int(inf,&c->x);
+    rs_read_int(inf,&c->y);
+    
+    return(READSTAT);
+}
+
+int
+rs_write_window(FILE *savef, WINDOW *win)
+{
+    int row,col,height,width;
+    width = getmaxx(win);
+    height = getmaxy(win);
+
+    rs_write_int(savef,RSID_WINDOW);
+    rs_write_int(savef,height);
+    rs_write_int(savef,width);
+    
+    for(row=0;row<height;row++)
+        for(col=0;col<width;col++)
+            rs_write_int(savef, mvwinch(win,row,col));
+}
+
+int
+rs_read_window(int inf, WINDOW *win)
+{
+    int id,row,col,maxlines,maxcols,value,width,height;
+    
+    width = getmaxx(win);
+    height = getmaxy(win);
+
+    if (rs_read_int(inf, &id) != 0)
+    {
+        if (id != RSID_WINDOW)
+        {
+            printf("Invalid head id. %x != %x(RSID_WINDOW)\n", id, RSID_WINDOW);
+            printf("Sorry, invalid save game format");
+            format_error = TRUE;
+        }   
+        else
+        {
+            rs_read_int(inf,&maxlines);
+            rs_read_int(inf,&maxcols);
+            if (maxlines > height)
+               abort();
+            if (maxcols > width)
+               abort();
+               
+            for(row=0;row<maxlines;row++)
+                for(col=0;col<maxcols;col++)
+                {
+                    rs_read_int(inf, &value);
+                    mvwaddch(win,row,col,value);
+                }
+        }
+    }
+        
+    return(READSTAT);
+}
+
+int
+rs_write_daemons(FILE *savef, struct delayed_action *d_list, int count)
+{
+    int i = 0;
+    int func = 0;
+        
+    rs_write_int(savef, RSID_DAEMONS);
+    rs_write_int(savef, count);
+        
+    for(i = 0; i < count; i++)
+    {
+        if (d_list[i].d_func == rollwand)
+            func = 1;
+        else if (d_list[i].d_func == doctor)
+            func = 2;
+        else if (d_list[i].d_func == stomach)
+            func = 3;
+        else if (d_list[i].d_func == runners)
+            func = 4;
+        else if (d_list[i].d_func == swander)
+            func = 5;
+        else if (d_list[i].d_func == nohaste)
+            func = 6;
+        else if (d_list[i].d_func == unconfuse)
+            func = 7;
+        else if (d_list[i].d_func == unsee)
+            func = 8;
+        else if (d_list[i].d_func == sight)
+            func = 9;
+        else if (d_list[i].d_func == noteth)
+            func = 10;
+        else if (d_list[i].d_func == sapem)
+            func = 11;
+        else if (d_list[i].d_func == notslow)
+            func = 12;
+        else if (d_list[i].d_func == notregen)
+            func = 13;
+        else if (d_list[i].d_func == notinvinc)
+            func = 14;
+        else if (d_list[i].d_func == rchg_str)
+            func = 15;
+        else if (d_list[i].d_func == wghtchk)
+            func = 16;
+        else if (d_list[i].d_func == status)
+            func = 17;
+        else
+            func = 0;
+
+        rs_write_int(savef, d_list[i].d_type);
+        rs_write_int(savef, func);
+        rs_write_int(savef, d_list[i].d_arg);
+        rs_write_int(savef, d_list[i].d_time);
+    }
+    
+    return(WRITESTAT);
+}       
+
+int
+rs_read_daemons(int inf, struct delayed_action *d_list, int count)
+{
+    int i = 0;
+    int func = 0;
+    int value = 0;
+    int id = 0;
+    
+    if (d_list == NULL)
+        printf("HELP THERE ARE NO DAEMONS\n");
+    
+    if (rs_read_int(inf, &id) != 0)
+    {
+        if (id != RSID_DAEMONS)
+        {
+            printf("Invalid id. %x != %x(RSID_DAEMONS)\n", id, RSID_DAEMONS);
+            printf("Sorry, invalid save game format");
+            format_error = TRUE;
+        }
+        else if (rs_read_int(inf, &value) != 0)
+        {
+            if (value > count)
+            {
+                printf("Incorrect number of daemons in block. %d > %d.",
+                    value, count);
+                printf("Sorry, invalid save game format");
+                format_error = TRUE;
+            }
+            else
+            {
+                for(i=0; i < value; i++)
+                {
+                    func = 0;
+                    rs_read_int(inf, &d_list[i].d_type);
+                    rs_read_int(inf, &func);
+                    rs_read_int(inf, &d_list[i].d_arg);
+                    rs_read_int(inf, &d_list[i].d_time);
+                    
+                    switch(func)
+                    {
+                        case 1: d_list[i].d_func = rollwand;
+                                break;
+                        case 2: d_list[i].d_func = doctor;
+                                break;
+                        case 3: d_list[i].d_func = stomach;
+                                break;
+                        case 4: d_list[i].d_func = runners;
+                                break;
+                        case 5: d_list[i].d_func = swander;
+                                break;
+                        case 6: d_list[i].d_func = nohaste;
+                                break;
+                        case 7: d_list[i].d_func = unconfuse;
+                                break;
+                        case 8: d_list[i].d_func = unsee;
+                                break;
+                        case 9: d_list[i].d_func = sight;
+                                break;
+                        case 10: d_list[i].d_func = noteth;
+                                break;
+                        case 11: d_list[i].d_func = sapem;
+                                break;
+                        case 12: d_list[i].d_func = notslow;
+                                break;
+                        case 13: d_list[i].d_func = notregen;
+                                break;
+                        case 14: d_list[i].d_func = notinvinc;
+                                break;
+                        case 15: d_list[i].d_func = rchg_str;
+                                break;
+                        case 16: d_list[i].d_func = wghtchk;
+                                break;
+                        case 17: d_list[i].d_func = status;
+                                break;
+                        default: d_list[i].d_func = NULL;
+                                break;
+                    }   
+                }
+            }
+        }
+    }
+    
+    return(READSTAT);
+}                 
+
+int
+rs_write_room_reference(FILE *savef, struct room *rp)
+{
+    int i, room = -1;
+    
+    for (i = 0; i < MAXROOMS; i++)
+        if (&rooms[i] == rp)
+            room = i;
+
+    rs_write_int(savef, room);
+
+    return(WRITESTAT);
+}
+
+int
+rs_read_room_reference(int inf, struct room **rp)
+{
+    int i;
+    
+    rs_read_int(inf, &i);
+
+    *rp = &rooms[i];
+            
+    return(READSTAT);
+}
+
+int
+rs_write_rooms(FILE *savef, struct room r[], int count)
+{
+    int n = 0;
+
+    rs_write_int(savef, count);
+    
+    for(n=0; n<count; n++)
+    {
+        rs_write_coord(savef, r[n].r_pos);
+        rs_write_coord(savef, r[n].r_max);
+        rs_write_coord(savef, r[n].r_gold);
+        rs_write_coord(savef, r[n].r_exit[0]);
+        rs_write_coord(savef, r[n].r_exit[1]);
+        rs_write_coord(savef, r[n].r_exit[2]);
+        rs_write_coord(savef, r[n].r_exit[3]);
+        rs_write_room_reference(savef,r[n].r_ptr[0]);
+        rs_write_room_reference(savef,r[n].r_ptr[1]);
+        rs_write_room_reference(savef,r[n].r_ptr[2]);
+        rs_write_room_reference(savef,r[n].r_ptr[3]);
+        rs_write_int(savef, r[n].r_goldval);
+        rs_write_int(savef, r[n].r_flags);
+        rs_write_int(savef, r[n].r_nexits);
+    }
+    
+    return(WRITESTAT);
+}
+
+int
+rs_read_rooms(int inf, struct room *r, int count)
+{
+    int value = 0, n = 0;
+
+    if (rs_read_int(inf,&value) != 0)
+    {
+        if (value > count)
+        {
+            printf("Incorrect number of rooms in block. %d > %d.",
+                value,count);
+            printf("Sorry, invalid save game format");
+            format_error = TRUE;
+        }
+        else
+            for(n = 0; n < value; n++)
+            {
+                rs_read_coord(inf,&r[n].r_pos);
+                rs_read_coord(inf,&r[n].r_max);
+                rs_read_coord(inf,&r[n].r_gold);
+                rs_read_coord(inf,&r[n].r_exit[0]);
+                rs_read_coord(inf,&r[n].r_exit[1]);
+                rs_read_coord(inf,&r[n].r_exit[2]);
+                rs_read_coord(inf,&r[n].r_exit[3]);
+                rs_read_room_reference(inf,&r[n].r_ptr[0]);
+                rs_read_room_reference(inf,&r[n].r_ptr[1]);
+                rs_read_room_reference(inf,&r[n].r_ptr[2]);
+                rs_read_room_reference(inf,&r[n].r_ptr[3]);
+                rs_read_int(inf,&r[n].r_goldval);
+                rs_read_int(inf,&r[n].r_flags);
+                rs_read_int(inf,&r[n].r_nexits);
+            }
+    }
+
+    return(READSTAT);
+}
+
+int
+rs_write_monlev(FILE *savef, struct monlev m)
+{
+    rs_write_int(savef, m.l_lev);
+    rs_write_int(savef, m.h_lev);
+    rs_write_boolean(savef, m.d_wand);
+
+    return(WRITESTAT);
+}
+
+int
+rs_read_monlev(int inf, struct monlev *m)
+{
+    rs_read_int(inf, &m->l_lev);
+    rs_read_int(inf, &m->h_lev);
+    rs_read_boolean(inf, &m->d_wand);
+
+    return(READSTAT);
+}
+
+int
+rs_write_magic_items(FILE *savef, struct magic_item *i, int count)
+{
+    int n;
+    
+    rs_write_int(savef, RSID_MAGICITEMS);
+    rs_write_int(savef, count);
+
+    for(n = 0; n < count; n++)
+    {
+        /* mi_name is constant, defined at compile time in all cases */
+        rs_write_int(savef,i[n].mi_prob);
+    }
+    
+    return(WRITESTAT);
+}
+
+int
+rs_read_magic_items(int inf, struct magic_item *mi, int count)
+{
+    int id;
+    int n;
+    int value;
+
+    if (rs_read_int(inf, &id) != 0)
+    {
+        if (id != RSID_MAGICITEMS)
+        {
+            printf("Invalid id. %x != %x(RSID_MAGICITEMS)\n",
+                id, RSID_MAGICITEMS);
+            printf("Sorry, invalid save game format");
+            format_error = TRUE;
+        }   
+        else if (rs_read_int(inf, &value) != 0)
+        {
+            if (value > count)
+            {
+                printf("Incorrect number of magic items in block. %d > %d.",
+                    value, count);
+                printf("Sorry, invalid save game format");
+                format_error = TRUE;
+            }
+            else
+            {
+                for(n = 0; n < value; n++)
+                {
+                    rs_read_int(inf,&mi[n].mi_prob);
+                }
+            }
+        }
+    }
+    
+    return(READSTAT);
+}
+
+
+int
+rs_write_real(FILE *savef, struct real r)
+{
+    rs_write_int(savef, r.a_str);
+    rs_write_int(savef, r.a_dex);
+    rs_write_int(savef, r.a_wis);
+    rs_write_int(savef, r.a_con);
+
+    return(WRITESTAT);
+}
+
+int
+rs_read_real(int inf, struct real *r)
+{
+    rs_read_int(inf,&r->a_str);
+    rs_read_int(inf,&r->a_dex);
+    rs_read_int(inf,&r->a_wis);
+    rs_read_int(inf,&r->a_con);
+
+    return(READSTAT);
+}
+
+int
+rs_write_stats(FILE *savef, struct stats *s)
+{
+    rs_write_int(savef, RSID_STATS);
+    rs_write_real(savef, s->s_re);
+    rs_write_real(savef, s->s_ef);
+    rs_write_long(savef, s->s_exp);
+    rs_write_int(savef, s->s_lvl);
+    rs_write_int(savef, s->s_arm);
+    rs_write_int(savef, s->s_hpt);
+    rs_write_int(savef, s->s_maxhp);
+    rs_write_int(savef, s->s_pack);
+    rs_write_int(savef, s->s_carry);
+    rs_write(savef, s->s_dmg, sizeof(s->s_dmg));
+
+    return(WRITESTAT);
+}
+
+int
+rs_read_stats(int inf, struct stats *s)
+{
+    int id;
+
+    rs_read_int(inf, &id);
+    rs_read_real(inf, &s->s_re);
+    rs_read_real(inf, &s->s_ef);
+
+    rs_read_long(inf,&s->s_exp);
+    rs_read_int(inf,&s->s_lvl);
+    rs_read_int(inf,&s->s_arm);
+    rs_read_int(inf,&s->s_hpt);
+    rs_read_int(inf,&s->s_maxhp);
+    rs_read_int(inf,&s->s_pack);
+    rs_read_int(inf,&s->s_carry);
+
+    rs_read(inf,s->s_dmg,sizeof(s->s_dmg));
+    
+    return(READSTAT);
+}
+
+int
+rs_write_monster_reference(FILE *savef, struct monster *m)
+{
+    int i, mon = -1;
+    
+    for (i = 0; i < (MAXMONS+1); i++)
+        if (&monsters[i] == m)
+            mon = i;
+
+    rs_write_int(savef, mon);
+
+    return(WRITESTAT);
+}
+
+int
+rs_read_monster_reference(int inf, struct monster **mp)
+{
+    int i;
+    
+    rs_read_int(inf, &i);
+
+    if (i < 0)
+        *mp = NULL;
+    else
+        *mp = &monsters[i];
+            
+    return(READSTAT);
+}
+
+int
+rs_write_monster_references(FILE *savef, struct monster *marray[], int count)
+{
+    int i;
+
+    for(i = 0; i < count; i++)
+        rs_write_monster_reference(savef, marray[i]);
+}
+
+int 
+rs_read_monster_references(int inf, struct monster *marray[], int count)
+{
+    int i;
+
+    for(i = 0; i < count; i++)
+        rs_read_monster_reference(inf, &marray[i]);
+}
+
+int
+rs_write_object(FILE *savef, struct object *o)
+{
+    rs_write_int(savef, RSID_OBJECT);
+    rs_write_coord(savef, o->o_pos);
+    rs_write(savef, o->o_damage, sizeof(o->o_damage));
+    rs_write(savef, o->o_hurldmg, sizeof(o->o_hurldmg));
+
+    if (o->o_type == ARMOR)
+        assert( strcmp(o->o_typname,things[TYP_ARMOR].mi_name) == 0 );
+    else if (o->o_type == FOOD)
+        assert( strcmp(o->o_typname,things[TYP_FOOD].mi_name) == 0 );
+    else if (o->o_type == RING)
+        assert( strcmp(o->o_typname,things[TYP_RING].mi_name) == 0 );
+    else if (o->o_type == WEAPON)
+        assert( strcmp(o->o_typname,things[TYP_WEAPON].mi_name) == 0 );
+    else if (o->o_type == POTION)
+        assert( strcmp(o->o_typname,things[TYP_POTION].mi_name) == 0 );
+    else if (o->o_type == SCROLL)
+        assert( strcmp(o->o_typname,things[TYP_SCROLL].mi_name) == 0 );
+    else if (o->o_type == STICK)
+        assert( strcmp(o->o_typname,things[TYP_STICK].mi_name) == 0 );
+    else if (o->o_type == AMULET)
+        assert( strcmp(o->o_typname,things[TYP_AMULET].mi_name) == 0 );
+    else
+        assert(0 == 1);
+
+    rs_write_int(savef, o->o_type);
+    rs_write_int(savef, o->o_count);
+    rs_write_int(savef, o->o_which);
+    rs_write_int(savef, o->o_hplus);
+    rs_write_int(savef, o->o_dplus);
+    rs_write_int(savef, o->o_ac);
+    rs_write_int(savef, o->o_flags);
+    rs_write_int(savef, o->o_group);
+    rs_write_int(savef, o->o_weight);
+    rs_write_int(savef, o->o_vol);
+
+    rs_write_char(savef, o->o_launch);
+
+    return(WRITESTAT);
+}
+
+int
+rs_read_object(int inf, struct object *o)
+{
+    int id;
+
+    if (rs_read_int(inf, &id) != 0)
+    {
+        if (id != RSID_OBJECT)
+        {
+            printf("Invalid id. %x != %x(RSID_OBJECT)\n",
+                id,RSID_OBJECT);
+            printf("Sorry, invalid save game format");
+            format_error = TRUE;
+        }
+        else
+        {
+            rs_read_coord(inf, &o->o_pos);
+            rs_read(inf, &o->o_damage, sizeof(o->o_damage));
+            rs_read(inf, &o->o_hurldmg, sizeof(o->o_hurldmg));
+            rs_read_int(inf, &o->o_type);
+
+            if (o->o_type == ARMOR)
+                o->o_typname = things[TYP_ARMOR].mi_name;
+            else if (o->o_type == FOOD)
+                o->o_typname = things[TYP_FOOD].mi_name;
+            else if (o->o_type == RING)
+                o->o_typname = things[TYP_RING].mi_name;
+            else if (o->o_type == WEAPON)
+                o->o_typname = things[TYP_WEAPON].mi_name;
+            else if (o->o_type == POTION)
+                o->o_typname = things[TYP_POTION].mi_name;
+            else if (o->o_type == SCROLL)
+                o->o_typname = things[TYP_SCROLL].mi_name;
+            else if (o->o_type == STICK)
+                o->o_typname = things[TYP_STICK].mi_name;
+            else if (o->o_type == AMULET)
+                o->o_typname = things[TYP_AMULET].mi_name;
+            else
+                assert(0 == 1);
+
+            rs_read_int(inf, &o->o_count);
+            rs_read_int(inf, &o->o_which);
+            rs_read_int(inf, &o->o_hplus);
+            rs_read_int(inf, &o->o_dplus);
+            rs_read_int(inf, &o->o_ac);
+            rs_read_int(inf, &o->o_flags);
+            rs_read_int(inf, &o->o_group);
+            rs_read_int(inf, &o->o_weight);
+            rs_read_int(inf, &o->o_vol);
+            rs_read_char(inf, &o->o_launch);
+        }
+    }
+    
+    return(READSTAT);
+}
+
+int
+rs_read_object_list(int inf, struct linked_list **list)
+{
+    int id;
+    int i, cnt;
+    struct linked_list *l = NULL, *previous = NULL, *head = NULL;
+
+    if (rs_read_int(inf,&id) != 0)
+    {
+        if (rs_read_int(inf,&cnt) != 0)
+        {
+            for (i = 0; i < cnt; i++) 
+            {
+                l = new_item(sizeof(struct object));
+                memset(l->l_data,0,sizeof(struct object));
+                l->l_prev = previous;
+                if (previous != NULL)
+                    previous->l_next = l;
+                rs_read_object(inf,(struct object *) l->l_data);
+                if (previous == NULL)
+                    head = l;
+                previous = l;
+            }
+            
+            if (l != NULL)
+                l->l_next = NULL;
+    
+            *list = head;
+        }
+        else
+            format_error = TRUE;
+    }
+    else
+        format_error = TRUE;
+
+
+    return(READSTAT);
+}
+
+int
+rs_write_object_list(FILE *savef, struct linked_list *l)
+{
+    rs_write_int(savef, RSID_OBJECTLIST);
+    rs_write_int(savef, list_size(l));
+
+    while (l != NULL) 
+    {
+        rs_write_object(savef, (struct object *) l->l_data);
+        l = l->l_next;
+    }
+    
+    return(WRITESTAT);
+}
+
+int
+rs_write_traps(FILE *savef, struct trap *trap,int count)
+{
+    int n;
+
+    rs_write_int(savef, RSID_TRAP);
+    rs_write_int(savef, count);
+    
+    for(n=0; n<count; n++)
+    {
+        rs_write_coord(savef, trap[n].tr_pos);
+        rs_write_coord(savef, trap[n].tr_goto);
+        rs_write_int(savef, trap[n].tr_flags);
+        rs_write_char(savef, trap[n].tr_type);
+    }
+}
+
+rs_read_traps(int inf, struct trap *trap, int count)
+{
+    int id = 0, value = 0, n = 0;
+
+    if (rs_read_int(inf,&id) != 0)
+    {
+        if (id != RSID_TRAP)
+        {
+            printf("Invalid id. %x != %x(RSID_TRAP)\n",
+                id,RSID_TRAP);
+            printf("Sorry, invalid save game format");
+            format_error = TRUE;
+        }
+        else if (rs_read_int(inf,&value) != 0)
+        {
+            if (value > count)
+            {
+                printf("Incorrect number of traps in block. %d > %d.",
+                    value,count);
+                printf("Sorry, invalid save game format\n");
+                format_error = TRUE;
+            }
+            else
+            {
+                for(n=0;n<value;n++)
+                {   
+                    rs_read_coord(inf,&trap[n].tr_pos);
+                    rs_read_coord(inf,&trap[n].tr_goto);
+                    rs_read_int(inf,&trap[n].tr_flags);
+                    rs_read_char(inf,&trap[n].tr_type);
+                }
+            }
+        }
+        else
+            format_error = TRUE;
+    }
+    
+    return(READSTAT);
+}
+
+int
+rs_write_monsters(FILE * savef, struct monster * m, int count)
+{
+    int n;
+    
+    rs_write_int(savef, RSID_MONSTERS);
+    rs_write_int(savef, count);
+
+    for(n=0;n<count;n++)
+    {
+        rs_write_monlev(savef, m[n].m_lev);
+        rs_write_stats(savef, &m[n].m_stats);
+    }
+    
+    return(WRITESTAT);
+}
+
+int
+rs_read_monsters(int inf, struct monster *m, int count)
+{
+    int id = 0, value = 0, n = 0;
+    
+    if (rs_read_int(inf, &id) != 0)
+    {
+        if (id != RSID_MONSTERS)
+        {
+            printf("Invalid id. %x != %x(RSID_MONSTERS)\n",
+                id,RSID_MONSTERS);
+            printf("Sorry, invalid save game format");
+            format_error = TRUE;
+        }
+        else if (rs_read_int(inf, &value) != 0)
+        {
+            for(n=0;n<value;n++)
+            {
+                rs_read_monlev(inf, &m[n].m_lev);
+                rs_read_stats(inf, &m[n].m_stats);
+            }
+        }
+        else
+            format_error = TRUE;
+    }
+    
+    return(READSTAT);
+}
+
+int
+find_thing_coord(struct linked_list *monlist, struct coord *c)
+{
+    struct linked_list *mitem;
+    struct thing *tp;
+    int i = 0;
+
+    for(mitem = monlist; mitem != NULL; mitem = mitem->l_next)
+    {
+        tp = THINGPTR(mitem);
+        if (c == &tp->t_pos)
+            return(i);
+        i++;
+    }
+
+    return(-1);
+}
+
+int
+find_object_coord(struct linked_list *objlist, struct coord *c)
+{
+    struct linked_list *oitem;
+    struct object *obj;
+    int i = 0;
+
+    for(oitem = objlist; oitem != NULL; oitem = oitem->l_next)
+    {
+        obj = OBJPTR(oitem);
+        if (c == &obj->o_pos)
+            return(i);
+        i++;
+    }
+
+    return(-1);
+}
+
+void
+rs_fix_thing(struct thing *t)
+{
+    struct linked_list *item;
+    struct thing *tp;
+
+    if (t->t_reserved < 0)
+        return;
+
+    item = get_list_item(mlist,t->t_reserved);
+
+    if (item != NULL)
+    {
+        tp = THINGPTR(item);
+        t->t_dest = &tp->t_pos;
+    }
+}
+
+int
+find_room_coord(struct room *rmlist, struct coord *c, int n)
+{
+    int i = 0;
+    
+    for(i=0; i < n; i++)
+        if(&rmlist[i].r_gold == c)
+            return(i);
+    
+    return(-1);
+}
+
+int
+rs_write_thing(FILE *savef, struct thing *t)
+{
+    int i = -1;
+    
+    if (t == NULL)
+    {
+        rs_write_int(savef, RSID_THING_NULL);
+        return(WRITESTAT);
+    }
+    
+    rs_write_int(savef, RSID_THING);
+
+    rs_write_stats(savef, &t->t_stats);
+    rs_write_coord(savef, t->t_pos);
+    rs_write_coord(savef, t->t_oldpos);
+
+    /* 
+        t_dest can be:
+        0,0: NULL
+        0,1: location of hero
+        0,3: global coord 'delta'
+        1,i: location of a thing (monster)
+        2,i: location of an object
+        3,i: location of gold in a room
+
+        We need to remember what we are chasing rather than 
+        the current location of what we are chasing.
+    */
+
+    if (t->t_dest == &hero)
+    {
+        rs_write_int(savef,0);
+        rs_write_int(savef,1);
+    }
+    else if (t->t_dest != NULL)
+    {
+        i = find_thing_coord(mlist, t->t_dest);
+            
+        if (i >=0 )
+        {
+            rs_write_int(savef,1);
+            rs_write_int(savef,i);
+        }
+        else
+        {
+            i = find_object_coord(lvl_obj, t->t_dest);
+            
+            if (i >= 0)
+            {
+                rs_write_int(savef,2);
+                rs_write_int(savef,i);
+            }
+            else
+            {
+                i = find_room_coord(rooms, t->t_dest, MAXROOMS);
+        
+                if (i >= 0) 
+                {
+                    rs_write_int(savef,3);
+                    rs_write_int(savef,i);
+                }
+                else 
+                {
+                    rs_write_int(savef, 0);
+                    rs_write_int(savef,1); /* chase the hero anyway */
+                }
+            }
+        }
+    }
+    else
+    {
+        rs_write_int(savef,0);
+        rs_write_int(savef,0);
+    }
+    
+    rs_write_object_list(savef, t->t_pack);
+    rs_write_room_reference(savef, t->t_room);
+    rs_write_long(savef, t->t_flags);
+    rs_write_int(savef, t->t_indx);
+    rs_write_int(savef, t->t_nomove);
+    rs_write_int(savef, t->t_nocmd);
+    rs_write_boolean(savef, t->t_turn);
+    rs_write_char(savef, t->t_type);
+    rs_write_char(savef, t->t_disguise);
+    rs_write_char(savef, t->t_oldch);
+    
+    return(WRITESTAT);
+}
+
+int
+rs_read_thing(int inf, struct thing *t)
+{
+    int id;
+    int listid = 0, index = -1;
+    struct linked_list *item;
+        
+    if (rs_read_int(inf, &id) != 0)
+    {
+        if ((id != RSID_THING) && (id != RSID_THING_NULL)) {
+            fmterr = "RSID_THING mismatch";
+            format_error = TRUE;
+        }
+        else if (id == RSID_THING_NULL)
+        {
+            printf("NULL Thing?\n\r");
+        }
+        else
+        {
+            rs_read_stats(inf, &t->t_stats);
+            rs_read_coord(inf, &t->t_pos);
+            rs_read_coord(inf, &t->t_oldpos);
+
+            /* 
+                t_dest can be (listid,index):
+                0,0: NULL
+                0,1: location of hero
+                1,i: location of a thing (monster)
+                2,i: location of an object
+                3,i: location of gold in a room
+
+                We need to remember what we are chasing rather than 
+                the current location of what we are chasing.
+            */
+            
+            rs_read_int(inf, &listid);
+            rs_read_int(inf, &index);
+            t->t_reserved = -1;
+
+            if (listid == 0) /* hero or NULL */
+            {
+                if (index == 1)
+                    t->t_dest = &hero;
+                else
+                    t->t_dest = NULL;
+            }
+            else if (listid == 1) /* monster/thing */
+            {
+                t->t_dest     = NULL;
+                t->t_reserved = index;
+            }
+            else if (listid == 2) /* object */
+            {
+                struct object *obj;
+
+                item = get_list_item(lvl_obj, index);
+
+                if (item != NULL)
+                {
+                    obj = OBJPTR(item);
+                    t->t_dest = &obj->o_pos;
+                }
+            }
+            else if (listid == 3) /* gold */
+            {
+                t->t_dest = &rooms[index].r_gold;
+            }
+            else
+                t->t_dest = NULL;
+
+            rs_read_object_list(inf, &t->t_pack);
+            rs_read_room_reference(inf, &t->t_room);
+            rs_read_long(inf, &t->t_flags);
+            rs_read_int(inf, &t->t_indx);
+            rs_read_int(inf, &t->t_nomove);
+            rs_read_int(inf, &t->t_nocmd);
+            rs_read_boolean(inf, &t->t_turn);
+            rs_read_char(inf, &t->t_type);
+            rs_read_char(inf, &t->t_disguise);
+            rs_read_char(inf, &t->t_oldch);
+        }
+    }
+    else format_error = TRUE;
+    
+    return(READSTAT);
+}
+
+rs_fix_monster_list(list)
+struct linked_list *list;
+{
+    struct linked_list *item;
+
+    for(item = list; item != NULL; item = item->l_next)
+        rs_fix_thing(THINGPTR(item));
+}
+
+int
+rs_write_monster_list(FILE *savef, struct linked_list *l)
+{
+    int cnt = 0;
+    
+    rs_write_int(savef, RSID_MONSTERLIST);
+
+    cnt = list_size(l);
+
+    rs_write_int(savef, cnt);
+
+    if (cnt < 1)
+        return(WRITESTAT);
+
+    while (l != NULL) {
+        rs_write_thing(savef, (struct thing *)l->l_data);
+        l = l->l_next;
+    }
+    
+    return(WRITESTAT);
+}
+
+int
+rs_read_monster_list(int inf, struct linked_list **list)
+{
+    int id;
+    int i, cnt;
+    struct linked_list *l = NULL, *previous = NULL, *head = NULL;
+
+    if (rs_read_int(inf,&id) != 0)
+    {
+        if (id != RSID_MONSTERLIST)
+        {
+            printf("Invalid id. %x != %x(RSID_MONSTERLIST)\n",
+                id,RSID_MONSTERLIST);
+            printf("Sorry, invalid save game format");
+            format_error = TRUE;
+        }
+        else if (rs_read_int(inf,&cnt) != 0)
+        {
+            for (i = 0; i < cnt; i++) 
+            {
+                l = new_item(sizeof(struct thing));
+                l->l_prev = previous;
+                if (previous != NULL)
+                    previous->l_next = l;
+                rs_read_thing(inf,(struct thing *)l->l_data);
+                if (previous == NULL)
+                    head = l;
+                previous = l;
+            }
+        
+
+            if (l != NULL)
+                l->l_next = NULL;
+
+            *list = head;
+        }
+    }
+    else format_error = TRUE;
+    
+    return(READSTAT);
+}
+
+int
+rs_write_object_reference(FILE *savef, struct linked_list *list, 
+    struct object *item)
+{
+    int i;
+    
+    i = find_list_ptr(list, item);
+    rs_write_int(savef, i);
+
+    return(WRITESTAT);
+}
+
+rs_read_object_reference(int inf, struct linked_list *list, 
+    struct object **item)
+{
+    int i;
+    
+    rs_read_int(inf, &i);
+    *item = get_list_item(list,i);
+            
+    return(READSTAT);
+}
+
+
+
+int
+rs_read_scrolls(int inf)
+{
+    int i;
+
+    for(i = 0; i < MAXSCROLLS; i++)
+    {
+        rs_read_new_string(inf,&s_names[i]);
+        rs_read_boolean(inf,&s_know[i]);
+        rs_read_new_string(inf,&s_guess[i]);
+    }
+
+    return(READSTAT);
+}
+
+int
+rs_write_scrolls(FILE *savef)
+{
+    int i;
+
+    for(i = 0; i < MAXSCROLLS; i++)
+    {
+        rs_write_string(savef,s_names[i]);
+        rs_write_boolean(savef,s_know[i]);
+        rs_write_string(savef,s_guess[i]);
+    }
+    return(READSTAT);
+}
+
+int
+rs_read_potions(int inf)
+{
+    int i;
+
+    for(i = 0; i < MAXPOTIONS; i++)
+    {
+        rs_read_string_index(inf,rainbow,NCOLORS,&p_colors[i]);
+        rs_read_boolean(inf,&p_know[i]);
+        rs_read_new_string(inf,&p_guess[i]);
+    }
+
+    return(READSTAT);
+}
+
+int
+rs_write_potions(FILE *savef)
+{
+    int i;
+
+    for(i = 0; i < MAXPOTIONS; i++)
+    {
+        rs_write_string_index(savef,rainbow,NCOLORS,p_colors[i]);
+        rs_write_boolean(savef,p_know[i]);
+        rs_write_string(savef,p_guess[i]);
+    }
+
+    return(WRITESTAT);
+}
+
+int
+rs_read_rings(int inf)
+{
+    int i;
+
+    for(i = 0; i < MAXRINGS; i++)
+    {
+        rs_read_string_index(inf,stones,NSTONES,&r_stones[i]);
+        rs_read_boolean(inf,&r_know[i]);
+        rs_read_new_string(inf,&r_guess[i]);
+    }
+
+    return(READSTAT);
+}
+
+int
+rs_write_rings(FILE *savef)
+{
+    int i;
+
+    for(i = 0; i < MAXRINGS; i++)
+    {
+        rs_write_string_index(savef,stones,NSTONES,r_stones[i]);
+        rs_write_boolean(savef,r_know[i]);
+        rs_write_string(savef,r_guess[i]);
+    }
+
+    return(WRITESTAT);
+}
+
+int
+rs_write_sticks(FILE *savef)
+{
+    int i;
+
+    for (i = 0; i < MAXSTICKS; i++)
+    {
+        if (strcmp(ws_stuff[i].ws_type,"staff") == 0)
+        {
+            rs_write_int(savef,0);
+            rs_write_string_index(savef, wood, NWOOD, ws_stuff[i].ws_made);
+        }
+        else
+        {
+            rs_write_int(savef,1);
+            rs_write_string_index(savef, metal, NMETAL, ws_stuff[i].ws_made);
+        }
+        rs_write_int(savef, ws_stuff[i].ws_vol);
+        rs_write_int(savef, ws_stuff[i].ws_wght);
+        rs_write_boolean(savef, ws_know[i]);
+        rs_write_string(savef, ws_guess[i]);
+    }
+
+    return(WRITESTAT);
+}
+
+int
+rs_read_sticks(int inf)
+{
+    int i = 0, list = 0;
+
+    for(i = 0; i < MAXSTICKS; i++)
+    {
+        rs_read_int(inf,&list);
+        if (list == 0)
+        {
+            rs_read_string_index(inf,wood,NWOOD,&ws_stuff[i].ws_made);
+            ws_stuff[i].ws_type = "staff";
+        }
+        else
+        {
+            rs_read_string_index(inf,metal,NMETAL,&ws_stuff[i].ws_made);
+            ws_stuff[i].ws_type = "wand";
+        }
+        rs_read_int(inf, &ws_stuff[i].ws_vol);
+        rs_read_int(inf, &ws_stuff[i].ws_wght);
+
+        rs_read_boolean(inf, &ws_know[i]);
+        rs_read_new_string(inf, &ws_guess[i]);
+    }
+
+    return(READSTAT);
+}
+
+int
+rs_save_file(FILE *savef)
+{
+    int endian = 0x01020304;
+    big_endian = ( *((char *)&endian) == 0x01 );
+
+    rs_write_daemons(savef, d_list, MAXDAEMONS);
+    rs_write_int(savef, between);
+    rs_write_rooms(savef, rooms, MAXROOMS);
+    rs_write_room_reference(savef, oldrp);
+    rs_write_monster_list(savef, mlist);
+    rs_write_thing(savef, &player);
+    rs_write_stats(savef,&max_stats);                   
+    rs_write_object_list(savef, lvl_obj);
+    rs_write_object_reference(savef, player.t_pack, cur_weapon); 
+    rs_write_object_reference(savef, player.t_pack, cur_armor);
+    rs_write_object_reference(savef, player.t_pack, cur_ring[0]);
+    rs_write_object_reference(savef, player.t_pack, cur_ring[1]);
+    assert(him == &player.t_stats);
+    rs_write_traps(savef, traps, MAXTRAPS);             
+    rs_write_int(savef, level);
+    rs_write_int(savef, levcount);
+    rs_write_int(savef, levtype);
+    rs_write_int(savef, trader);
+    rs_write_int(savef, curprice);
+    rs_write_int(savef, purse);
+    rs_write_int(savef, ntraps);
+    rs_write_int(savef, packvol);
+    rs_write_int(savef, demoncnt);
+    rs_write_int(savef, lastscore);
+    rs_write_int(savef, no_food);
+    rs_write_int(savef, seed);
+    rs_write_int(savef, dnum);
+    rs_write_int(savef, count);
+    rs_write_int(savef, fung_hit);
+    rs_write_int(savef, quiet);
+    rs_write_int(savef, max_level);
+    rs_write_int(savef, food_left);
+    rs_write_int(savef, group);
+    rs_write_int(savef, hungry_state);
+    rs_write_int(savef, foodlev);
+    rs_write_int(savef, ringfood);
+    rs_write_char(savef, take);
+    rs_write_char(savef, runch);
+    rs_write(savef, curpurch, 15);
+
+    rs_write(savef, prbuf, LINLEN);
+    rs_write(savef, whoami, LINLEN);
+    rs_write(savef, fruit, LINLEN);
+    
+    rs_write_boolean(savef, isfight); 
+    rs_write_boolean(savef, nlmove);
+    rs_write_boolean(savef, inpool);
+    rs_write_boolean(savef, inwhgt);
+    rs_write_boolean(savef, running);
+    rs_write_boolean(savef, playing);
+#ifdef WIZARD
+    rs_write_boolean(savef, wizard);
+#else 
+    rs_write_boolean(savef, 0);
+#endif
+    rs_write_boolean(savef, after);
+    rs_write_boolean(savef, door_stop);
+    rs_write_boolean(savef, firstmove);
+    rs_write_boolean(savef, waswizard);
+    rs_write_boolean(savef, amulet);
+    rs_write_boolean(savef, in_shell);
+    rs_write_boolean(savef, nochange);
+    
+    rs_write_coord(savef, oldpos);
+    rs_write_coord(savef, delta);
+    rs_write_coord(savef, stairs);
+    rs_write_coord(savef, rndspot);
+
+    rs_write_monsters(savef, monsters, MAXMONS+1);
+    rs_write_monster_references(savef, mtlev, MONRANGE);
+
+    rs_write_scrolls(savef);
+    rs_write_potions(savef);
+    rs_write_rings(savef);
+    rs_write_sticks(savef);
+
+    rs_write_magic_items(savef, things, NUMTHINGS+1);
+    rs_write_magic_items(savef, a_magic, MAXARMORS+1);
+    rs_write_magic_items(savef, w_magic, MAXWEAPONS+1);
+    rs_write_magic_items(savef, s_magic, MAXSCROLLS+1);
+    rs_write_magic_items(savef, p_magic, MAXPOTIONS+1);
+    rs_write_magic_items(savef, r_magic, MAXRINGS+1);
+    rs_write_magic_items(savef, ws_magic, MAXSTICKS+1);
+
+    rs_write_window(savef, cw);
+    rs_write_window(savef, mw);
+    rs_write_window(savef, stdscr);
+
+    fflush(savef);
+
+    return(WRITESTAT);
+}
+
+rs_restore_file(int inf)
+{
+    bool junk;
+    int endian = 0x01020304;
+    big_endian = ( *((char *)&endian) == 0x01 );
+    
+    rs_read_daemons(inf, d_list, MAXDAEMONS);
+    rs_read_int(inf, &between);
+    rs_read_rooms(inf, rooms, MAXROOMS);
+    rs_read_room_reference(inf, &oldrp);
+    rs_read_monster_list(inf, &mlist);
+    rs_read_thing(inf, &player);
+    rs_read_stats(inf,&max_stats);                   
+    rs_read_object_list(inf, &lvl_obj);
+    rs_read_object_reference(inf, player.t_pack, &cur_weapon); 
+    rs_read_object_reference(inf, player.t_pack, &cur_armor);
+    rs_read_object_reference(inf, player.t_pack, &cur_ring[0]);
+    rs_read_object_reference(inf, player.t_pack, &cur_ring[1]);
+    him = &player.t_stats;
+    rs_read_traps(inf, traps, MAXTRAPS);             
+
+    rs_read_int(inf, &level);
+    rs_read_int(inf, &levcount);
+    rs_read_int(inf, &levtype);
+    rs_read_int(inf, &trader);
+    rs_read_int(inf, &curprice);
+    rs_read_int(inf, &purse);
+    rs_read_int(inf, &ntraps);
+    rs_read_int(inf, &packvol);
+    rs_read_int(inf, &demoncnt);
+    rs_read_int(inf, &lastscore);
+    rs_read_int(inf, &no_food);
+    rs_read_int(inf, &seed);
+    rs_read_int(inf, &dnum);
+    rs_read_int(inf, &count);
+    rs_read_int(inf, &fung_hit);
+    rs_read_int(inf, &quiet);
+    rs_read_int(inf, &max_level);
+    rs_read_int(inf, &food_left);
+    rs_read_int(inf, &group);
+    rs_read_int(inf, &hungry_state);
+    rs_read_int(inf, &foodlev);
+    rs_read_int(inf, &ringfood);
+    rs_read_char(inf, &take);
+    rs_read_char(inf, &runch);
+    rs_read(inf, curpurch, 15);
+
+    rs_read(inf, prbuf, LINLEN);
+    rs_read(inf, whoami, LINLEN);
+    rs_read(inf, fruit, LINLEN);
+    
+    rs_read_boolean(inf, &isfight); 
+    rs_read_boolean(inf, &nlmove);
+    rs_read_boolean(inf, &inpool);
+    rs_read_boolean(inf, &inwhgt);
+    rs_read_boolean(inf, &running);
+    rs_read_boolean(inf, &playing);
+#ifdef WIZARD
+    rs_read_boolean(inf, &wizard);
+#else
+    rs_read_boolean(inf, &junk);
+#endif
+    rs_read_boolean(inf, &after);
+    rs_read_boolean(inf, &door_stop);
+    rs_read_boolean(inf, &firstmove);
+    rs_read_boolean(inf, &waswizard);
+    rs_read_boolean(inf, &amulet);
+    rs_read_boolean(inf, &in_shell);
+    rs_read_boolean(inf, &nochange);
+    
+    rs_read_coord(inf, &oldpos);
+    rs_read_coord(inf, &delta);
+    rs_read_coord(inf, &stairs);
+    rs_read_coord(inf, &rndspot);
+
+    rs_read_monsters(inf, monsters, MAXMONS+1);
+    rs_read_monster_references(inf, mtlev, MONRANGE);
+
+    rs_read_scrolls(inf);
+    rs_read_potions(inf);
+    rs_read_rings(inf);
+    rs_read_sticks(inf);
+
+    rs_read_magic_items(inf, things, NUMTHINGS+1);
+    rs_read_magic_items(inf, a_magic, MAXARMORS+1);
+    rs_read_magic_items(inf, w_magic, MAXWEAPONS+1);
+    rs_read_magic_items(inf, s_magic, MAXSCROLLS+1);
+    rs_read_magic_items(inf, p_magic, MAXPOTIONS+1);
+    rs_read_magic_items(inf, r_magic, MAXRINGS+1);
+    rs_read_magic_items(inf, ws_magic, MAXSTICKS+1);
+
+    rs_read_window(inf, cw);
+    rs_read_window(inf, mw);
+    rs_read_window(inf, stdscr);
+
+    return(READSTAT);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/srogue/sticks.c	Thu Nov 25 12:21:41 2010 +0000
@@ -0,0 +1,592 @@
+/*
+ * Functions to deal with the various sticks one
+ * might find while wandering around the dungeon.
+ *
+ * @(#)sticks.c	9.0	(rdk)	 7/17/84
+ *
+ * Super-Rogue
+ * Copyright (C) 1984 Robert D. Kindelberger
+ * All rights reserved.
+ *
+ * Based on "Rogue: Exploring the Dungeons of Doom"
+ * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
+ * All rights reserved.
+ *
+ * See the file LICENSE.TXT for full copyright and licensing information.
+ */
+
+#include <ctype.h>
+#include "rogue.h"
+#include "rogue.ext"
+
+/*
+ * fix_stick:
+ *	Init a stick for the hero
+ */
+fix_stick(cur)
+struct object *cur;
+{
+	struct rod *rd;
+
+	cur->o_type = STICK;
+	cur->o_charges = 4 + rnd(5);
+	strcpy(cur->o_hurldmg, "1d1");
+	rd = &ws_stuff[cur->o_which];
+	cur->o_weight = rd->ws_wght;
+	cur->o_vol = rd->ws_vol;
+	if (strcmp(rd->ws_type, "staff") == 0) {
+		strcpy(cur->o_damage, "2d3");
+		cur->o_charges += rnd(5) + 3;
+	}
+	else {
+		strcpy(cur->o_damage, "1d1");
+	}
+	switch (cur->o_which) {
+		case WS_HIT:
+			if(rnd(100) < 15) {
+				cur->o_hplus = 9;
+				cur->o_dplus = 9;
+				strcpy(cur->o_damage,"3d8");
+			}
+			else {
+				cur->o_hplus = 3;
+				cur->o_dplus = 3;
+				strcpy(cur->o_damage,"1d8");
+			}
+		when WS_LIGHT:
+			cur->o_charges += 7 + rnd(9);
+	}
+}
+
+/*
+ * do_zap:
+ *	Zap a stick at something
+ */
+do_zap(gotdir)
+bool gotdir;
+{
+	reg struct linked_list *item;
+	reg struct object *obj;
+	reg struct thing *tp;
+	reg int y, x, wh;
+	struct room *rp;
+	bool bless, curse;
+	int better = 0;
+
+	if ((item = get_item("zap with", STICK)) == NULL)
+		return;
+	obj = OBJPTR(item);
+	wh = obj->o_which;
+	bless = o_on(obj, ISBLESS);
+	curse = o_on(obj, ISCURSED);
+	if (obj->o_type != STICK) {
+		msg("You can't zap with that!");
+		after = FALSE;
+		return;
+	}
+	if (obj->o_charges == 0) {
+		msg("Nothing happens.");
+		return;
+	}
+	if (!gotdir)
+	do {
+		delta.y = rnd(3) - 1;
+		delta.x = rnd(3) - 1;
+	} while (delta.y == 0 && delta.x == 0);
+	rp = player.t_room;
+	if (bless)
+		better = 3;
+	else if (curse)
+		better = -3;
+	switch (wh) {
+	case WS_SAPLIFE:
+		if (!bless) {
+			if (him->s_hpt > 1)
+			him->s_hpt /= 2;	/* zap half his hit points */
+		}
+	when WS_CURE:
+		if (!curse) {
+			ws_know[WS_CURE] = TRUE;
+			heal_self(6, FALSE);
+			unconfuse(FALSE);
+			notslow(FALSE);
+			sight(FALSE);
+		}
+	when WS_PYRO:
+		if (!bless) {
+			msg("The rod explodes !!!");
+			chg_hpt(-roll(6,6), FALSE, K_ROD);
+			ws_know[WS_PYRO] = TRUE;
+			del_pack(item);		/* throw it away */
+		}
+	when WS_HUNGER:
+		if (!bless) {
+			struct linked_list *ip;
+			struct object *lb;
+
+			food_left /= 3;
+			if ((ip = pack) != NULL) {
+				lb = OBJPTR(ip);
+				if (lb->o_type == FOOD) {
+					if ((lb->o_count -= roll(1,4)) < 1)
+						del_pack(ip);
+				}
+			}
+		}
+	when WS_PARZ:
+	case WS_MREG:
+	case WS_MDEG:
+	case WS_ANNIH: {
+		struct linked_list *mitem;
+		struct thing *it;
+		reg int i,j;
+
+		for (i = hero.y - 3; i <= hero.y + 3; i++) {
+			for (j = hero.x - 3; j <= hero.x + 3; j++) {
+				if (!cordok(i, j))
+					continue;
+				if (isalpha(mvwinch(mw,i,j))) {
+					mitem = find_mons(i, j);
+					if (mitem == NULL)
+						continue;
+					it = THINGPTR(mitem);
+					switch(wh) {
+						case WS_ANNIH:
+							if (!curse)
+								killed(mitem,FALSE);
+						when WS_MREG:
+							if (!bless)
+								it->t_stats.s_hpt *= 2;
+						when WS_MDEG:
+							if (!curse) {
+								it->t_stats.s_hpt /= 2;
+								if (it->t_stats.s_hpt < 2)
+									killed(mitem,FALSE);
+							}
+						when WS_PARZ:
+							if (!curse) {
+								it->t_flags |= ISPARA;
+								it->t_flags &= ~ISRUN;
+							}
+						}
+					}
+				}
+			}
+		}
+	when WS_LIGHT:
+		if (!curse) {
+			ws_know[WS_LIGHT] = TRUE;
+			if (rp == NULL)
+				msg("The corridor glows and then fades.");
+			else {
+				msg("The room is lit.");
+				rp->r_flags &= ~ISDARK;
+				light(&hero);
+				mvwaddch(cw, hero.y, hero.x, PLAYER);
+			}
+		}
+	when WS_DRAIN:
+		/*
+		 * Take away 1/2 of hero's hit points, then take it away
+		 * evenly from the monsters in the room (or next to hero
+		 * if he is in a passage)
+		 */
+		if (him->s_hpt < 2) {
+			msg("You are too weak to use it.");
+			return;
+		}
+		else if (!curse) {
+			if (rp == NULL)
+				drain(hero.y-1, hero.y+1, hero.x-1, hero.x+1);
+			else
+				drain(rp->r_pos.y, rp->r_pos.y+rp->r_max.y,
+				  rp->r_pos.x, rp->r_pos.x+rp->r_max.x);
+		}
+	when WS_POLYM:
+	case WS_TELAWAY:
+	case WS_TELTO:
+	case WS_CANCEL:
+	case WS_MINVIS:
+	{
+		reg char monster, oldch;
+
+		y = hero.y;
+		x = hero.x;
+		do {
+			y += delta.y;
+			x += delta.x;
+		} while (step_ok(winat(y, x)));
+		if (isalpha(monster = mvwinch(mw, y, x))) {
+			int omonst;
+
+			if (wh != WS_MINVIS)
+				unhold(monster);
+			item = find_mons(y, x);
+			if (item == NULL)
+				break;
+			tp = THINGPTR(item);
+			omonst = tp->t_indx;
+			if (wh == WS_POLYM && !curse) {
+				detach(mlist, item);
+				discard(item);
+				oldch = tp->t_oldch;
+				delta.y = y;
+				delta.x = x;
+				monster = rnd_mon(FALSE, TRUE);
+				item = new_monster(monster, &delta, FALSE);
+				if (!(tp->t_flags & ISRUN))
+					runto(&delta, &hero);
+				if (isalpha(mvwinch(cw, y, x)))
+					mvwaddch(cw, y, x, monsters[monster].m_show);
+				tp->t_oldch = oldch;
+				ws_know[WS_POLYM] |= (monster != omonst);
+			}
+			else if (wh == WS_MINVIS && !bless) {
+				tp->t_flags |= ISINVIS;
+				mvwaddch(cw,y,x,tp->t_oldch);	/* hide em */
+				runto(&tp->t_pos, &hero);
+			}
+			else if (wh == WS_CANCEL && !curse) {
+				tp->t_flags |= ISCANC;
+				tp->t_flags &= ~ISINVIS;
+			}
+			else {
+				if (wh == WS_TELAWAY) {
+					if (curse)
+						break;
+					tp->t_pos = *rnd_pos(&rooms[rnd_room()]);
+				}
+				else {					/* WS_TELTO */
+					if (bless)
+						break;
+					tp->t_pos.y = hero.y + delta.y;
+					tp->t_pos.x = hero.x + delta.x;
+				}
+				if (isalpha(mvwinch(cw, y, x)))
+					mvwaddch(cw, y, x, tp->t_oldch);
+				tp->t_dest = &hero;
+				tp->t_flags |= ISRUN;
+				mvwaddch(mw, y, x, ' ');
+				mvwaddch(mw, tp->t_pos.y, tp->t_pos.x, monster);
+				tp->t_oldch = mvwinch(cw,tp->t_pos.y,tp->t_pos.x);
+			}
+		}
+	}
+	when WS_MISSILE:
+	{
+		struct coord *whe;
+		static struct object bolt = {
+			{0, 0}, "", "6d6", "", '*', 0, 0, 1000, 0, 0, 0, 0, 0, 0,
+		};
+
+		if (curse)
+			strcpy(bolt.o_hurldmg,"3d3");
+		else if (bless)
+			strcpy(bolt.o_hurldmg,"9d9");
+		ws_know[WS_MISSILE] = TRUE;
+		do_motion(&bolt, delta.y, delta.x);
+		whe = &bolt.o_pos;
+		if (isalpha(mvwinch(mw, whe->y, whe->x))) {
+			struct linked_list *it;
+
+			runto(whe, &hero);
+			it = find_mons(whe->y, whe->x);
+			if (it != NULL) {
+				if (!save_throw(VS_MAGIC + better, THINGPTR(it))) {
+					hit_monster(whe, &bolt);
+					break;
+				}
+			}
+		}
+		msg("Missle vanishes.");
+	}
+	when WS_NOP:
+		msg("Your %s flickers momentarily and then fades",
+			ws_stuff[wh].ws_type);
+	when WS_HIT: {
+		char ch;
+
+		delta.y += hero.y;
+		delta.x += hero.x;
+		ch = winat(delta.y, delta.x);
+		if (curse) {				/* decrease for cursed */
+			strcpy(obj->o_damage,"1d1");
+			obj->o_hplus = obj->o_dplus = 0;
+		}
+		else if (bless) {			/* increase for blessed */
+			strcpy(obj->o_damage,"5d8");
+			obj->o_hplus = obj->o_dplus = 12;
+		}
+		if (isalpha(ch))
+			fight(&delta, obj, FALSE);
+	}
+	when WS_HASTE_M:
+	case WS_CONFMON:
+	case WS_SLOW_M:
+	case WS_MOREMON: {
+		reg int m1,m2;
+		struct coord mp;
+		struct linked_list *titem;
+
+		y = hero.y;
+		x = hero.x;
+		do {
+			y += delta.y;
+			x += delta.x;
+		} while (step_ok(winat(y, x)));
+		if (isalpha(mvwinch(mw, y, x))) {
+			item = find_mons(y, x);
+			if (item == NULL)
+				break;
+			tp = THINGPTR(item);
+			if (wh == WS_HASTE_M && !bless) {			/* haste it */
+				if (on(*tp, ISSLOW))
+					tp->t_flags &= ~ISSLOW;
+				else
+					tp->t_flags |= ISHASTE;
+			}
+			else if (wh == WS_CONFMON && !curse) {		/* confuse it */
+				tp->t_flags |= ISHUH;
+				if (pl_on(ISHELD) && tp->t_type == 'd')
+					player.t_flags &= ~ISHELD;
+			}
+			else if (wh == WS_SLOW_M && !curse) {		/* slow it */
+				if (on(*tp, ISHASTE))
+					tp->t_flags &= ~ISHASTE;
+				else
+					tp->t_flags |= ISSLOW;
+				tp->t_turn = TRUE;
+			}
+			else if (!bless) {	/* WS_MOREMON: multiply it */
+				char ch;
+				struct thing *th;
+
+				for (m1 = tp->t_pos.x-1; m1 <= tp->t_pos.x+1; m1++) {
+					for(m2 = tp->t_pos.y-1; m2 <= tp->t_pos.y+1; m2++) {
+						if (hero.x == m1 && hero.y == m2)
+							continue;
+						ch = winat(m2,m1);
+						if (step_ok(ch)) {
+							mp.x = m1;			/* create it */
+							mp.y = m2;
+							titem = new_monster(tp->t_indx, &mp, FALSE);
+							th = THINGPTR(titem);
+							th->t_flags |= ISMEAN;
+							runto(&mp, &hero);
+						}
+					}
+				}
+			}
+			delta.y = y;
+			delta.x = x;
+			runto(&delta, &hero);
+		}
+	}
+	when WS_ELECT:
+	case WS_FIRE:
+	case WS_COLD: {
+		reg char dirch, ch, *name;
+		reg bool bounced, used;
+		int boingcnt, boltlen;
+		struct coord pos;
+		struct coord spotpos[BOLT_LENGTH * 2];
+		static struct object bolt =	{
+			{0, 0}, "", "6d6", "", '*', 0, 0, 1000, 0, 0, 0, 0, 0, 0,
+		};
+
+		boltlen = BOLT_LENGTH;
+		if (curse) {
+			strcpy(bolt.o_hurldmg,"3d3");
+			boltlen -= 3;
+		}
+		else if (bless) {
+			strcpy(bolt.o_hurldmg,"9d9");
+			boltlen += 3;
+		}
+		switch (delta.y + delta.x) {
+			case 0: dirch = '/';
+			when 1: case -1: dirch = (delta.y == 0 ? '-' : '|');
+			when 2: case -2: dirch = '\\';
+		}
+		pos = hero;
+		bounced = FALSE;
+		boingcnt = 0;
+		used = FALSE;
+		if (wh == WS_ELECT)
+			name = "bolt";
+		else if (wh == WS_FIRE)
+			name = "flame";
+		else
+			name = "ice";
+		for (y = 0; y < boltlen && !used; y++) {
+			ch = winat(pos.y, pos.x);
+			spotpos[y] = pos;
+			switch (ch) {
+				case SECRETDOOR:
+				case '|':
+				case '-':
+				case ' ':
+					bounced = TRUE;
+					if (++boingcnt > 6) 
+						used = TRUE;	/* only so many bounces */
+					delta.y = -delta.y;
+					delta.x = -delta.x;
+					y--;
+					msg("The bolt bounces");
+					break;
+				default:
+					if (isalpha(ch)) {
+						struct linked_list *it;
+
+						it = find_mons(pos.y, pos.x);
+						runto(&pos, &hero);
+						if (it != NULL) {
+							if (!save_throw(VS_MAGIC+better,THINGPTR(it))) {
+								bolt.o_pos = pos;
+								hit_monster(&pos, &bolt);
+								used = TRUE;
+							}
+							else if(ch != 'M' || show(pos.y,pos.x)=='M') {
+								msg("%s misses", name);
+							}
+						}
+					}
+					else if(bounced && pos.y==hero.y && pos.x==hero.x) {
+						bounced = FALSE;
+						if (!save(VS_MAGIC + better)) {
+							msg("The %s hits you.", name);
+							chg_hpt(-roll(6, 6),FALSE,K_BOLT);
+							used = TRUE;
+						}
+						else
+							msg("The %s whizzes by you.", name);
+					}
+					mvwaddch(cw, pos.y, pos.x, dirch);
+					draw(cw);
+				}
+				pos.y += delta.y;
+				pos.x += delta.x;
+			}
+			for (x = 0; x < y; x++)
+				mvwaddch(cw, spotpos[x].y, spotpos[x].x,
+				  show(spotpos[x].y, spotpos[x].x));
+			ws_know[wh] = TRUE;
+		}
+	when WS_ANTIM: {
+		reg int m1, m2, x1, y1;
+		struct linked_list *ll;
+		struct thing *lt;
+		int ch, radius;
+
+		y1 = hero.y;
+		x1 = hero.x;
+		do {
+			y1 += delta.y;
+			x1 += delta.x;
+			ch = winat(y1, x1);
+		} while (ch == PASSAGE || ch == FLOOR);
+		if (curse)
+			radius = 2;
+		else if (bless)
+			radius = 0;
+		else
+			radius = 1;
+		for (m1 = x1 - radius; m1 <= x1 + radius; m1++) {
+			for (m2 = y1 - radius; m2 <= y1 + radius; m2++) {
+				if (!cordok(m2, m1))
+					continue;
+				ch = winat(m2, m1);
+				if (m1 == hero.x && m2 == hero.y)
+					continue;
+				if (ch == ' ')
+					continue;
+				ll = find_obj(m2,m1);
+				if (ll != NULL) {
+					detach(lvl_obj,ll);
+					discard(ll);
+				}
+				ll = find_mons(m2,m1);
+				if (ll != NULL) {
+					lt = THINGPTR(ll);
+					him->s_exp += lt->t_stats.s_exp;
+					unhold(lt->t_type);
+					/*
+					 * throw away anything that the monster
+					 * was carrying in its pack
+					 */
+					free_list(lt->t_pack);
+					detach(mlist,ll);
+					discard(ll);
+					mvwaddch(mw,m2,m1,' ');
+				}
+				mvaddch(m2,m1,' ');
+				mvwaddch(cw,m2,m1,' ');
+			}
+		}
+		touchwin(cw);
+		touchwin(mw);
+		check_level();
+	}
+	otherwise:
+		msg("What a bizarre schtick!");
+	}
+	obj->o_charges--;
+}
+
+/*
+ * drain:
+ *	Do drain hit points from player stick
+ */
+drain(ymin, ymax, xmin, xmax)
+int ymin, ymax, xmin, xmax;
+{
+	reg int i, j, cnt;
+	reg struct thing *ick;
+	reg struct linked_list *item;
+
+	/*
+	 * First count how many things we need to spread the hit points among
+	 */
+	cnt = 0;
+	for (i = ymin; i <= ymax; i++)
+		for (j = xmin; j <= xmax; j++)
+			if (isalpha(mvwinch(mw, i, j)))
+				cnt++;
+	if (cnt == 0) {
+		msg("You have a tingling feeling.");
+		return;
+	}
+	cnt = him->s_hpt / cnt;
+	him->s_hpt /= 2;
+	/*
+	 * Now zot all of the monsters
+	 */
+	for (i = ymin; i <= ymax; i++) {
+		for (j = xmin; j <= xmax; j++) {
+			if(isalpha(mvwinch(mw, i, j))) {
+				item = find_mons(i, j);
+				if (item == NULL)
+					continue;
+				ick = THINGPTR(item);
+				if ((ick->t_stats.s_hpt -= cnt) < 1)
+					killed(item,cansee(i,j) && !(ick->t_flags & ISINVIS));
+			}
+		}
+	}
+}
+
+/*
+ * charge_str:
+ *	Return number of charges left in a stick
+ */
+char *
+charge_str(obj)
+struct object *obj;
+{
+	static char buf[20];
+
+	buf[0] = '\0';
+	if (o_on(obj,ISKNOW) || o_on(obj,ISPOST))
+		sprintf(buf, " [%d]", obj->o_charges);
+	return buf;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/srogue/things.c	Thu Nov 25 12:21:41 2010 +0000
@@ -0,0 +1,460 @@
+/*
+ * Contains functions for dealing with things like
+ * potions and scrolls
+ *
+ * @(#)things.c	9.0	(rdk)	 7/17/84
+ *
+ * Super-Rogue
+ * Copyright (C) 1984 Robert D. Kindelberger
+ * All rights reserved.
+ *
+ * Based on "Rogue: Exploring the Dungeons of Doom"
+ * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
+ * All rights reserved.
+ *
+ * See the file LICENSE.TXT for full copyright and licensing information.
+ */
+
+#include <ctype.h>
+#include "rogue.h"
+#include "rogue.ext"
+
+
+/*
+ * inv_name:
+ *	Return the name of something as it would appear in an inventory.
+ */
+char *
+inv_name(obj, drop)
+struct object *obj;
+bool drop;
+{
+	reg char *pb, *tn, *pl;
+	reg int wh, knowit;
+	char nm[3], *inm, *q;
+
+	wh = obj->o_which;
+	knowit = FALSE;
+	if (obj->o_count > 1)
+		pl = "s";
+	else
+		pl = "";
+	if (obj->o_count > 1)
+		sprintf(nm, "%d", obj->o_count);
+	else
+		strcpy(nm, "A");
+	tn = obj->o_typname;
+	q = "";
+	switch(obj->o_type) {
+	case SCROLL:
+		sprintf(prbuf, "%s %s%s ", nm, tn, pl);
+		pb = &prbuf[strlen(prbuf)];
+		if (s_know[wh] || o_on(obj,ISPOST)) {
+			knowit = TRUE;
+			sprintf(pb, "of %s", s_magic[wh].mi_name);
+		}
+		else if (s_guess[wh])
+			sprintf(pb, "called %s", s_guess[wh]);
+		else
+			sprintf(pb, "titled '%s'", s_names[wh]);
+    when POTION:
+		sprintf(prbuf, "%s %s%s ", nm, tn, pl);
+		pb = &prbuf[strlen(prbuf)];
+		if (p_know[wh] || o_on(obj, ISPOST)) {
+			sprintf(pb, "of %s", p_magic[wh].mi_name);
+			knowit = TRUE;
+			if (p_know[wh]) {
+				pb = &prbuf[strlen(prbuf)];
+				sprintf(pb,"(%s)",p_colors[wh]);
+			}
+		}
+		else if (p_guess[wh])
+			sprintf(pb,"called %s(%s)", p_guess[wh],p_colors[wh]);
+		else
+			sprintf(prbuf,"%s%s %s %s%s", nm, vowelstr(p_colors[wh]),
+				p_colors[wh], tn, pl);
+	when FOOD:
+		if (wh == 1) {
+			if (obj->o_count == 1)
+				q = vowelstr(fruit);
+			sprintf(prbuf, "%s%s %s%s", nm, q, fruit, pl);
+		}
+		else {
+			if (obj->o_count == 1)
+				sprintf(prbuf, "Some %s", tn);
+			else
+				sprintf(prbuf, "%s rations of %s", nm, tn);
+		}
+		knowit = TRUE;
+	when WEAPON:
+		inm = w_magic[wh].mi_name;
+		strcpy(prbuf, nm);
+		if (obj->o_count == 1)
+			q = vowelstr(inm);
+		pb = &prbuf[strlen(prbuf)];
+		if (o_on(obj,ISKNOW | ISPOST)) {
+			knowit = TRUE;
+			sprintf(pb, " %s %s", num(obj->o_hplus, obj->o_dplus), inm);
+		}
+		else
+			sprintf(pb, "%s %s", q, inm);
+		strcat(prbuf, pl);
+	when ARMOR:
+		inm = a_magic[wh].mi_name;
+		if (o_on(obj,ISKNOW | ISPOST)) {
+			knowit = TRUE;
+			sprintf(prbuf, "%s %s",num(armors[wh].a_class - obj->o_ac, 0),
+				inm);
+		}
+		else
+			sprintf(prbuf, "%s", inm);
+	when AMULET:
+		strcpy(prbuf, "The Amulet of Yendor");
+	when STICK: {
+		struct rod *rd;
+
+		rd = &ws_stuff[wh];
+		sprintf(prbuf, "A %s ", rd->ws_type);
+		pb = &prbuf[strlen(prbuf)];
+		if (ws_know[wh] || o_on(obj, ISPOST)) {
+			knowit = TRUE;
+			sprintf(pb,"of %s%s",ws_magic[wh].mi_name,charge_str(obj));
+			if (ws_know[wh]) {
+				pb = &prbuf[strlen(prbuf)];
+				sprintf(pb,"(%s)",rd->ws_made);
+			}
+		}
+		else if (ws_guess[wh])
+			sprintf(pb, "called %s(%s)", ws_guess[wh], rd->ws_made);
+		else
+			sprintf(prbuf, "A%s %s %s", vowelstr(rd->ws_made),
+				rd->ws_made, rd->ws_type);
+	}
+    when RING:
+		if (r_know[wh] || o_on(obj, ISPOST)) {
+			knowit = TRUE;
+			sprintf(prbuf, "A%s %s of %s", ring_num(obj), tn,
+			  r_magic[wh].mi_name);
+			if (r_know[wh]) {
+				pb = &prbuf[strlen(prbuf)];
+				sprintf(pb,"(%s)", r_stones[wh]);
+			}
+		}
+		else if (r_guess[wh])
+			sprintf(prbuf,"A %s called %s(%s)",tn, r_guess[wh],
+				r_stones[wh]);
+		else
+			sprintf(prbuf,"A%s %s %s",vowelstr(r_stones[wh]), 
+				r_stones[wh], tn);
+	otherwise:
+		sprintf(prbuf,"Something bizarre %s", unctrl(obj->o_type));
+	}
+	if (obj == cur_armor)
+		strcat(prbuf, " (being worn)");
+	if (obj == cur_weapon)
+		strcat(prbuf, " (weapon in hand)");
+	if (obj == cur_ring[LEFT])
+		strcat(prbuf, " (on left hand)");
+	else if (obj == cur_ring[RIGHT])
+		strcat(prbuf, " (on right hand)");
+	if (drop && isupper(prbuf[0]))
+		prbuf[0] = tolower(prbuf[0]);
+	else if (!drop && islower(*prbuf))
+		*prbuf = toupper(*prbuf);
+	if (o_on(obj, ISPROT))
+		strcat(prbuf, " [!]");
+	if (o_on(obj, ISPOST))
+		strcat(prbuf, " [$]");
+	if (knowit) {
+		if (o_on(obj, ISCURSED))
+			strcat(prbuf, " [-]");
+		else if (o_on(obj, ISBLESS))
+			strcat(prbuf, " [+]");
+	}
+	if (!drop)
+		strcat(prbuf, ".");
+	return prbuf;
+}
+
+/*
+ * money:
+ *	Add to characters purse
+ */
+money()
+{
+	reg struct room *rp;
+	reg struct linked_list *item;
+	reg struct thing *tp;
+
+	rp = player.t_room;
+	if (rp != NULL && ce(hero, rp->r_gold)) {
+		msg("%d gold pieces.", rp->r_goldval);
+		purse += rp->r_goldval;
+		rp->r_goldval = 0;
+		cmov(rp->r_gold);
+		addch(FLOOR);
+		/*
+		 * once gold is taken, all monsters will chase him
+		 */
+		for (item = mlist; item != NULL; item = next(item)) {
+			tp = THINGPTR(item);
+			if (rnd(100) < 70 && tp->t_room == rp && !iswearing(R_STEALTH)
+			  && ((tp->t_flags & (ISMEAN | ISGREED)) || rnd(1000) < 20))
+				runto(&tp->t_pos, &hero);
+		}
+	}
+	else
+		msg("That gold must have been counterfeit.");
+}
+
+
+/*
+ * drop:
+ *	put something down
+ */
+drop(item)
+struct linked_list *item;
+{
+	reg char ch;
+	reg struct linked_list *ll, *nll;
+	reg struct object *op;
+
+	if (item == NULL) {
+		ch = mvinch(hero.y, hero.x);
+		if (ch != FLOOR && ch != PASSAGE && ch != POOL) {
+			msg("There is something there already.");
+			after = FALSE;
+			return SOMTHERE;
+		}
+		if ((ll = get_item("drop", 0)) == NULL)
+			return FALSE;
+	}
+	else {
+		ll = item;
+	}
+	op = OBJPTR(ll);
+	if (!dropcheck(op))
+		return CANTDROP;
+	/*
+	 * Take it out of the pack
+	 */
+	if (op->o_count >= 2 && op->o_type != WEAPON) {
+		nll = new_item(sizeof *op);
+		op->o_count--;
+		op->o_vol = itemvol(op);
+		op = OBJPTR(nll);
+		*op = *(OBJPTR(ll));
+		op->o_count = 1;
+		op->o_vol = itemvol(op);
+		ll = nll;
+	}
+	else {
+		detach(pack, ll);
+	}
+	if (ch == POOL) {
+		msg("%s sinks out of sight.",inv_name(op, TRUE));
+		discard(ll);
+	}
+	else {			/* put on dungeon floor */
+		if (levtype == POSTLEV) {
+			op->o_pos = hero;	/* same place as hero */
+			fall(ll,FALSE);
+			if (item == NULL)	/* if item wasn't sold */
+				msg("Thanks for your donation to the Fiend's flea market.");
+		}
+		else {
+			attach(lvl_obj, ll);
+			mvaddch(hero.y, hero.x, op->o_type);
+			op->o_pos = hero;
+			msg("Dropped %s", inv_name(op, TRUE));
+		}
+	}
+	updpack();			/* new pack weight */
+	return TRUE;
+}
+
+
+/*
+ * dropcheck:
+ *	Do special checks for dropping or unweilding|unwearing|unringing
+ */
+dropcheck(op)
+struct object *op;
+{
+	if (op == NULL)
+		return TRUE;
+	if (levtype == POSTLEV) {
+		if (o_on(op,ISCURSED) && o_on(op,ISKNOW)) {
+			msg("The trader does not accept shoddy merchandise.");
+			return FALSE;
+		}
+		else {
+			cur_null(op);	/* update cur_weapon, etc */
+			return TRUE;
+		}
+	}
+	if (op != cur_armor && op != cur_weapon
+	  && op != cur_ring[LEFT] && op != cur_ring[RIGHT])
+		return TRUE;
+	if (o_on(op,ISCURSED)) {
+		msg("You can't.  It appears to be cursed.");
+		return FALSE;
+	}
+	if (op == cur_weapon)
+		cur_weapon = NULL;
+	else if (op == cur_armor) {
+		waste_time();
+		cur_armor = NULL;
+	}
+	else if (op == cur_ring[LEFT] || op == cur_ring[RIGHT])
+		toss_ring(op);
+	return TRUE;
+}
+
+
+/*
+ * new_thing:
+ *	Return a new thing
+ */
+struct linked_list *
+new_thing(treas, type, which)
+int type, which;
+bool treas;
+{
+	struct linked_list *item;
+	struct magic_item *mi;
+	struct object *cur;
+	int chance, whi;
+
+	item = new_item(sizeof *cur);
+	cur = OBJPTR(item);
+	basic_init(cur);
+	if (type == DONTCARE) {
+		if (++no_food > 4 && !treas)
+			whi = TYP_FOOD;
+		else
+			whi = pick_one(things);
+	}
+	else {
+		whi = getindex(type);
+	}
+	mi = thnginfo[whi].mf_magic;
+	if (which == DONTCARE) {
+		which = 0;
+		if (mi != NULL)
+			which = pick_one(mi);
+	}
+	cur->o_typname = things[whi].mi_name;
+	cur->o_weight = things[whi].mi_wght;
+	switch (whi) {
+		case TYP_AMULET:
+			cur->o_type = AMULET;
+			cur->o_hplus = 500;
+			strcpy(cur->o_hurldmg,"80d8");	/* if thrown, WOW!!! */
+			cur->o_vol = itemvol(cur);
+		when TYP_POTION:
+			cur->o_type = POTION;
+			cur->o_which = which;
+			cur->o_count += extras();
+			cur->o_vol = itemvol(cur);
+		when TYP_SCROLL:
+			cur->o_type = SCROLL;
+			cur->o_which = which;
+			cur->o_count += extras();
+			cur->o_vol = itemvol(cur);
+		when TYP_FOOD:
+			no_food = 0;
+			initfood(cur);
+		when TYP_WEAPON:
+			cur->o_which = which;
+			init_weapon(cur, which);
+			if ((chance = rnd(100)) < 10) {
+				setoflg(cur,ISCURSED);
+				cur->o_hplus -= rnd(3)+1;
+				cur->o_dplus -= rnd(3)+1;
+			}
+			else if (chance < 15) {
+				cur->o_hplus += rnd(3)+1;
+				cur->o_dplus += rnd(3)+1;
+			}
+		when TYP_ARMOR:
+			cur->o_which = which;
+			initarmor(cur, which);
+			if ((chance = rnd(100)) < 20) {
+				setoflg(cur,ISCURSED);
+				cur->o_ac += rnd(3)+1;
+			}
+			else if (chance < 30)
+				cur->o_ac -= rnd(3)+1;
+		when TYP_RING:
+			cur->o_which = which;
+			init_ring(cur, FALSE);
+		when TYP_STICK:
+		default:
+			cur->o_which = which;
+			fix_stick(cur);
+	}
+	return item;
+}
+
+/*
+ * basic_init:
+ *	Set all params of an object to the basic values.
+ */
+basic_init(cur)
+struct object *cur;
+{
+	cur->o_ac = 11;
+	cur->o_count = 1;
+	cur->o_launch = 0;
+	cur->o_typname = NULL;
+	cur->o_group = newgrp();
+	cur->o_weight = cur->o_vol = 0;
+	cur->o_hplus = cur->o_dplus = 0;
+	strcpy(cur->o_damage,"0d0");
+	strcpy(cur->o_hurldmg,"0d0");
+	cur->o_flags = cur->o_type = cur->o_which = 0;
+}
+
+/*
+ * extras:
+ *	Return the number of extra items to be created
+ */
+extras()
+{
+	reg int i;
+
+	i = rnd(100);
+	if (i < 4)			/* 4% for 2 more */
+		return 2;
+	else if (i < 11)	/* 7% for 1 more */
+		return 1;
+	else				/* otherwise no more */
+		return 0;
+}
+
+
+/*
+ * pick_one:
+ * 	Pick an item out of a list of nitems possible magic items
+ */
+pick_one(mag)
+struct magic_item *mag;
+{
+	reg struct magic_item *start;
+	reg int i;
+
+	start = mag;
+	for (i = rnd(1000); mag->mi_name != NULL; mag++) {
+		if (i < mag->mi_prob)
+			break;
+		if (mag->mi_name == NULL) {
+			if (author() || wizard) {
+				for (mag = start; mag->mi_name != NULL; mag++)
+					msg("%s: %d%%", mag->mi_name, mag->mi_prob);
+			}
+			mag = start;
+		}
+	}
+	return mag - start;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/srogue/trader.c	Thu Nov 25 12:21:41 2010 +0000
@@ -0,0 +1,497 @@
+/*
+ * Anything to do with trading posts & mazes
+ *
+ * @(#)trader.c	9.0	(rdk)	 7/17/84
+ *
+ * Super-Rogue
+ * Copyright (C) 1984 Robert D. Kindelberger
+ * All rights reserved.
+ *
+ * See the file LICENSE.TXT for full copyright and licensing information.
+ */
+
+#include <stdlib.h>
+#include "rogue.h"
+#include "rogue.ext"
+
+#define NOTPRICED -1
+
+/*
+ * do_post:
+ *	Put a trading post room and stuff on the screen
+ */
+do_post()
+{
+	struct coord tp;
+	reg int i;
+	reg struct room *rp;
+	reg struct object *op;
+	reg struct linked_list *ll;
+
+	free_list(lvl_obj);		/* throw old items away */
+
+	for (rp = rooms; rp < &rooms[MAXROOMS]; rp++) {
+		rp->r_goldval = 0;			/* no gold */
+		rp->r_nexits = 0;			/* no exits */
+		rp->r_flags = ISGONE;		/* kill all rooms */
+	}
+	rp = &rooms[0];					/* point to only room */
+	rp->r_flags = 0;				/* this room NOT gone */
+	rp->r_max.x = 40;
+	rp->r_max.y = 10;				/* 10 * 40 room */
+	rp->r_pos.x = (COLS - rp->r_max.x) / 2;	/* center horizontal */
+	rp->r_pos.y = 1;				/* 2nd line */
+	draw_room(rp);					/* draw the only room */
+	i = roll(4,10);					/* 10 to 40 items */
+	for (; i > 0 ; i--) {			/* place all the items */
+		ll = new_thing(FALSE, ANYTHING);		/* get something */
+		attach(lvl_obj, ll);
+		op = OBJPTR(ll);
+		setoflg(op, ISPOST);		/* object in trading post */
+		tp = *rnd_pos(rp);
+		op->o_pos = tp;
+		mvaddch(tp.y,tp.x,op->o_type);
+	}
+	trader = 0;
+	wmove(cw,12,0);
+	waddstr(cw,"Welcome to Friendly Fiend's Flea Market\n\r");
+	waddstr(cw,"=======================================\n\r");
+	waddstr(cw,"$: Prices object that you stand upon.\n\r");
+	waddstr(cw,"#: Buys the object that you stand upon.\n\r");
+	waddstr(cw,"%: Trades in something in your pack for gold.\n\r");
+	trans_line();
+}
+
+/*
+ * price_it:
+ *	Price the object that the hero stands on
+ */
+price_it()
+{
+	static char *bargain[] = {
+		"great bargain",
+		"quality product",
+		"exceptional find",
+	};
+	reg struct linked_list *item;
+	reg struct object *obj;
+	reg int worth;
+
+	if (!open_market())		/* after buying hours */
+		return FALSE;
+	if ((item = find_obj(hero.y,hero.x)) == NULL)
+		return FALSE;
+	obj = OBJPTR(item);
+	if (curprice == NOTPRICED) {
+		worth = get_worth(obj);
+		worth += 50 - rnd(100);
+		if (worth < 25)
+			worth = 25;
+		worth *= 3;							/* slightly expensive */
+		curprice = worth;					/* save price */
+		strcpy(curpurch, obj->o_typname);	/* save item */
+	}
+	msg("That %s is a %s for only %d pieces of gold", curpurch,
+	  bargain[rnd(3)], curprice);
+	return TRUE;
+}
+
+/*
+ * buy_it:
+ *	Buy the item on which the hero stands
+ */
+buy_it()
+{
+	reg int wh;
+
+	if (purse <= 0) {
+		msg("You have no money.");
+		return;
+	}
+	if (curprice < 0) {		/* if not yet priced */
+		wh = price_it();
+		if (!wh)			/* nothing to price */
+			return;
+		msg("Do you want to buy it? ");
+		do {
+			wh = readchar();
+			if (isupper(wh))
+				wh = tolower(wh);
+			if (wh == ESCAPE || wh == 'n') {
+				msg("");
+				return;
+			}
+		} until(wh == 'y');
+	}
+	mpos = 0;
+	if (curprice > purse) {
+		msg("You can't afford to buy that %s !",curpurch);
+		return;
+	}
+	/*
+	 * See if the hero has done all his transacting
+	 */
+	if (!open_market())
+		return;
+	/*
+	 * The hero bought the item here
+	 */
+	mpos = 0;
+	wh = add_pack(NULL,FALSE);	/* try to put it in his pack */
+	if (wh) {					/* he could get it */
+		purse -= curprice;		/* take his money */
+		++trader;				/* another transaction */
+		trans_line();			/* show remaining deals */
+		curprice = NOTPRICED;
+		curpurch[0] = '\0';
+	}
+}
+
+/*
+ * sell_it:
+ *	Sell an item to the trading post
+ */
+sell_it()
+{
+	reg struct linked_list *item;
+	reg struct object *obj;
+	reg int wo, ch;
+
+	if (!open_market())		/* after selling hours */
+		return;
+
+	if ((item = get_item("sell",0)) == NULL)
+		return;
+	obj = OBJPTR(item);
+	wo = get_worth(obj);
+	if (wo <= 0) {
+		mpos = 0;
+		msg("We don't buy those.");
+		return;
+	}
+	if (wo < 25)
+		wo = 25;
+	msg("Your %s is worth %d pieces of gold.", obj->o_typname, wo);
+	msg("Do you want to sell it? ");
+	do {
+		ch = readchar();
+		if (isupper(ch))
+			ch = tolower(ch);
+		if (ch == ESCAPE || ch == 'n') {
+			msg("");
+			return;
+		}
+	} until (ch == 'y');
+	mpos = 0;
+	if (drop(item) == TRUE) {		/* drop this item */	
+		nochange = FALSE;		/* show gold value */
+		purse += wo;			/* give him his money */
+		++trader;			/* another transaction */
+		wo = obj->o_count;
+		obj->o_count = 1;
+		msg("Sold %s",inv_name(obj,TRUE));
+		obj->o_count = wo;
+		trans_line();			/* show remaining deals */
+	}
+}
+
+/*
+ * open_market:
+ *	Retruns TRUE when ok do to transacting
+ */
+open_market()
+{
+	if (trader >= MAXPURCH) {
+		msg("The market is closed. The stairs are that-a-way.");
+		return FALSE;
+	}
+	else
+		return TRUE;
+}
+
+/*
+ * get_worth:
+ *	Calculate an objects worth in gold
+ */
+get_worth(obj)
+struct object *obj;
+{
+	reg int worth, wh;
+
+	worth = 0;
+	wh = obj->o_which;
+	switch (obj->o_type) {
+	case FOOD:
+		worth = 2;
+	when WEAPON:
+		if (wh < MAXWEAPONS) {
+			worth = w_magic[wh].mi_worth;
+			worth *= (2 + (4 * obj->o_hplus + 4 * obj->o_dplus));
+		}
+	when ARMOR:
+		if (wh < MAXARMORS) {
+			worth = a_magic[wh].mi_worth;
+			worth *= (1 + (10 * (armors[wh].a_class - obj->o_ac)));
+		}
+	when SCROLL:
+		if (wh < MAXSCROLLS)
+			worth = s_magic[wh].mi_worth;
+	when POTION:
+		if (wh < MAXPOTIONS)
+			worth = p_magic[wh].mi_worth;
+	when RING:
+		if (wh < MAXRINGS) {
+			worth = r_magic[wh].mi_worth;
+			if (magring(obj)) {
+				if (obj->o_ac > 0)
+					worth += obj->o_ac * 40;
+				else
+					worth = 50;
+			}
+		}
+	when STICK:
+		if (wh < MAXSTICKS) {
+			worth = ws_magic[wh].mi_worth;
+			worth += 20 * obj->o_charges;
+		}
+	when AMULET:
+		worth = 1000;
+	otherwise:
+		worth = 0;
+	}
+	if (worth < 0)
+		worth = 0;
+	if (o_on(obj, ISPROT))		/* 300% more for protected */
+		worth *= 3;
+	if (o_on(obj, ISBLESS))		/* 50% more for blessed */
+		worth = worth * 3 / 2;
+	return worth;
+}
+
+/*
+ * trans_line:
+ *	Show how many transactions the hero has left
+ */
+trans_line()
+{
+	sprintf(prbuf,"You have %d transactions remaining.",MAXPURCH-trader);
+	mvwaddstr(cw, LINES - 4, 0, prbuf);
+}
+
+/*
+ * domaze:
+ *	Draw the maze on this level.
+ */
+do_maze()
+{
+	struct coord tp;
+	reg int i, least;
+	reg struct room *rp;
+	bool treas;
+
+	for (rp = rooms; rp < &rooms[MAXROOMS]; rp++) {
+		rp->r_goldval = 0;
+		rp->r_nexits = 0;			/* no exits */
+		rp->r_flags = ISGONE;		/* kill all rooms */
+	}
+	rp = &rooms[0];					/* point to only room */
+	rp->r_flags = ISDARK;			/* mazes always dark */
+	rp->r_pos.x = 0;				/* room fills whole screen */
+	rp->r_pos.y = 1;
+	rp->r_max.x = COLS - 1;
+	rp->r_max.y = LINES - 2;
+	rp->r_goldval = 500 + (rnd(10) + 1) * GOLDCALC;
+	draw_maze();				/* put maze into window */
+	rp->r_gold = *rnd_pos(rp);
+	mvaddch(rp->r_gold.y, rp->r_gold.x, GOLD);
+	if (rnd(100) < 3) {			/* 3% for treasure maze level */
+		treas = TRUE;
+		least = 6;
+		rp->r_flags |= ISTREAS;
+	}
+	else {						/* normal maze level */
+		least = 1;
+		treas = FALSE;
+	}
+	for (i = 0; i < level + least; i++)
+		if (treas || rnd(100) < 50)		/* put in some little buggers */
+			add_mon(rp, treas);
+}
+
+struct cell {
+	char y_pos;
+	char x_pos;
+};
+struct bordercells {
+	char num_pos;			/* number of frontier cells next to you */
+	struct cell conn[4];	/* the y,x position of above cell */
+} mborder;
+
+char *frontier, *bits;
+char *moffset(), *foffset();
+int tlines, tcols;
+
+/*
+ * draw_maze:
+ *	Generate and draw the maze on the screen
+ */
+draw_maze()
+{
+	reg int i, j, more;
+	reg char *ptr;
+
+	tlines = (LINES - 3) / 2;
+	tcols = (COLS - 1) / 2;
+	bits = ALLOC((LINES - 3) * (COLS - 1));
+	frontier = ALLOC(tlines * tcols);
+	ptr = frontier;
+	while (ptr < (frontier + (tlines * tcols)))
+		*ptr++ = TRUE;
+	for (i = 0; i < LINES - 3; i++) {
+		for (j = 0; j < COLS - 1; j++) {
+			if (i % 2 == 1 && j % 2 == 1)
+				*moffset(i, j) = FALSE;		/* floor */
+			else
+				*moffset(i, j) = TRUE;		/* wall */
+		}
+	}
+	for (i = 0; i < tlines; i++) {
+		for (j = 0; j < tcols; j++) {
+			do
+				more = findcells(i,j);
+			while(more != 0);
+		}
+	}
+	crankout();
+	FREE(frontier);
+	FREE(bits);
+}
+
+/*
+ * moffset:
+ *	Calculate memory address for bits
+ */
+char *
+moffset(y, x)
+int y, x;
+{
+	char *ptr;
+
+	ptr = bits + (y * (COLS - 1)) + x;
+	return ptr;
+}
+
+/*
+ * foffset:
+ *	Calculate memory address for frontier
+ */
+char *
+foffset(y, x)
+int y, x;
+{
+	char *ptr;
+
+	ptr = frontier + (y * tcols) + x;
+	return ptr;
+}
+
+/*
+ * findcells:
+ *	Figure out cells to open up 
+ */
+findcells(y,x)
+int x, y;
+{
+	reg int rtpos, i;
+
+	*foffset(y, x) = FALSE;
+	mborder.num_pos = 0;
+	if (y < tlines - 1) {				/* look below */
+		if (*foffset(y + 1, x)) {
+			mborder.conn[mborder.num_pos].y_pos = y + 1;
+			mborder.conn[mborder.num_pos].x_pos = x;
+			mborder.num_pos += 1;
+		}
+	}
+	if (y > 0) {						/* look above */
+		if (*foffset(y - 1, x)) {
+			mborder.conn[mborder.num_pos].y_pos = y - 1;
+			mborder.conn[mborder.num_pos].x_pos = x;
+			mborder.num_pos += 1;
+
+		}
+	}
+	if (x < tcols - 1) {					/* look right */
+		if (*foffset(y, x + 1)) {
+			mborder.conn[mborder.num_pos].y_pos = y;
+			mborder.conn[mborder.num_pos].x_pos = x + 1;
+			mborder.num_pos += 1;
+		}
+	}
+	if (x > 0) {						/* look left */
+		if (*foffset(y, x - 1)) {
+			mborder.conn[mborder.num_pos].y_pos = y;
+			mborder.conn[mborder.num_pos].x_pos = x - 1;
+			mborder.num_pos += 1;
+
+		}
+	}
+	if (mborder.num_pos == 0)			/* no neighbors available */
+		return 0;
+	else {
+		i = rnd(mborder.num_pos);
+		rtpos = mborder.num_pos - 1;
+		rmwall(mborder.conn[i].y_pos, mborder.conn[i].x_pos, y, x);
+		return rtpos;
+	}
+}
+
+/*
+ * rmwall:
+ *	Removes appropriate walls from the maze
+ */
+rmwall(newy, newx, oldy, oldx)
+int newy, newx, oldy, oldx;
+{
+	reg int xdif,ydif;
+	
+	xdif = newx - oldx;
+	ydif = newy - oldy;
+
+	*moffset((oldy * 2) + ydif + 1, (oldx * 2) + xdif + 1) = FALSE;
+	findcells(newy, newx);
+}
+
+
+/*
+ * crankout:
+ *	Does actual drawing of maze to window
+ */
+crankout()
+{
+	reg int x, y, i;
+
+	for (y = 0; y < LINES - 3; y++) {
+		move(y + 1, 0);
+		for (x = 0; x < COLS - 1; x++) {
+			if (*moffset(y, x)) {				/* here is a wall */
+				if (y == 0 || y == LINES - 4)	/* top or bottom line */
+					addch('-');
+				else if (x == 0 || x == COLS - 2)	/* left | right side */
+					addch('|');
+				else if (y % 2 == 0 && x % 2 == 0) {
+					if (*moffset(y, x - 1) || *moffset(y, x + 1))
+						addch('-');
+					else
+						addch('|');
+				}
+				else if (y % 2 == 0)
+					addch('-');
+				else
+					addch('|');
+			}
+			else
+				addch(FLOOR);
+		}
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/srogue/vers.c	Thu Nov 25 12:21:41 2010 +0000
@@ -0,0 +1,16 @@
+/*
+ * version number.
+ *
+ * Super-Rogue
+ * Copyright (C) 1984 Robert D. Kindelberger
+ * All rights reserved.
+ *
+ * Based on "Rogue: Exploring the Dungeons of Doom"
+ * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
+ * All rights reserved.
+ *
+ * See the file LICENSE.TXT for full copyright and licensing information.
+ */
+
+char version[] = "@(#)vers.c	9.0	(rdk)	 7/17/84";
+char *release = "9.0 RDK 7/17/84";
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/srogue/weapons.c	Thu Nov 25 12:21:41 2010 +0000
@@ -0,0 +1,265 @@
+/*
+ * Functions for dealing with weapons
+ *
+ * @(#)weapons.c	9.0	(rdk)	 7/17/84
+ *
+ * Super-Rogue
+ * Copyright (C) 1984 Robert D. Kindelberger
+ * All rights reserved.
+ *
+ * Based on "Rogue: Exploring the Dungeons of Doom"
+ * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
+ * All rights reserved.
+ *
+ * See the file LICENSE.TXT for full copyright and licensing information.
+ */
+
+#include <ctype.h>
+#include "rogue.h"
+#include "rogue.ext"
+
+/*
+ * missile:
+ *	Fire a missile in a given direction
+ */
+missile(ydelta, xdelta)
+int ydelta, xdelta;
+{
+	reg struct object *obj, *nowwield;
+	reg struct linked_list *item, *nitem;
+
+	/*
+	 * Get which thing we are hurling
+	 */
+	nowwield = cur_weapon;		/* must save current weap */
+	if ((item = get_item("throw", WEAPON)) == NULL)
+		return;
+	obj = OBJPTR(item);
+	if (!dropcheck(obj) || is_current(obj))
+		return;
+	if (obj == nowwield || obj->o_type != WEAPON) {
+		reg int c;
+
+		msg("Do you want to throw that %s? (y or n)",obj->o_typname);
+		do {
+			c = readchar();
+			if (isupper(c))
+				c = tolower(c);
+			if (c == ESCAPE || c == 'n') {
+				msg("");
+				cur_weapon = nowwield;
+				after = FALSE;		/* ooops, a mistake */
+				return;
+			}
+		} while (c != 'y');	/* keep looking for good ans */
+	}
+	/*
+	 * Get rid of the thing.  If it is a non-multiple item object, or
+	 * if it is the last thing, just drop it.  Otherwise, create a new
+	 * item with a count of one.
+	 */
+	if (obj->o_count < 2) {
+		detach(pack, item);
+	}
+	else {
+		obj->o_count--;
+		obj->o_vol = itemvol(obj);
+		nitem = new_item(sizeof *obj);
+		obj = OBJPTR(nitem);
+		*obj = *(OBJPTR(item));
+		obj->o_count = 1;
+		obj->o_vol = itemvol(obj);
+		item = nitem;
+	}
+	updpack();						/* new pack weight */
+	do_motion(obj, ydelta, xdelta);
+	if (!isalpha(mvwinch(mw, obj->o_pos.y, obj->o_pos.x))
+	  || !hit_monster(&obj->o_pos, obj))
+		fall(item, TRUE);
+	mvwaddch(cw, hero.y, hero.x, PLAYER);
+}
+
+/*
+ * do the actual motion on the screen done by an object traveling
+ * across the room
+ */
+do_motion(obj, ydelta, xdelta)
+struct object *obj;
+int ydelta, xdelta;
+{
+	reg int ch, y, x;
+
+	obj->o_pos = hero;
+	while (1) {
+		y = obj->o_pos.y;
+		x = obj->o_pos.x;
+		if (!ce(obj->o_pos, hero) && cansee(unc(obj->o_pos)) &&
+		  mvwinch(cw, y, x) != ' ')
+			mvwaddch(cw, y, x, show(y, x));
+		/*
+		 * Get the new position
+		 */
+		obj->o_pos.y += ydelta;
+		obj->o_pos.x += xdelta;
+		y = obj->o_pos.y;
+		x = obj->o_pos.x;
+		ch = winat(y, x);
+		if (step_ok(ch) && ch != DOOR) {
+			if (cansee(unc(obj->o_pos)) && mvwinch(cw, y, x) != ' ') {
+				mvwaddch(cw, y, x, obj->o_type);
+				draw(cw);
+			}
+			continue;
+		}
+		break;
+	}
+}
+
+/*
+ * fall:
+ *	Drop an item someplace around here.
+ */
+
+fall(item, pr)
+struct linked_list *item;
+bool pr;
+{
+	reg struct object *obj;
+	reg struct room *rp;
+	static struct coord fpos;
+
+	obj = OBJPTR(item);
+	if (fallpos(&obj->o_pos, &fpos, TRUE)) {
+		mvaddch(fpos.y, fpos.x, obj->o_type);
+		obj->o_pos = fpos;
+		rp = player.t_room;
+		if (rp != NULL && !rf_on(rp,ISDARK)) {
+			light(&hero);
+			mvwaddch(cw, hero.y, hero.x, PLAYER);
+		}
+		attach(lvl_obj, item);
+		return;
+	}
+
+	if (pr)
+        if (obj->o_type == WEAPON) /* BUGFIX: Identification trick */
+            msg("Your %s vanishes as it hits the ground.", w_magic[obj->o_which].mi_name);
+        else
+            msg("%s vanishes as it hits the ground.", inv_name(obj,TRUE));
+
+	discard(item);
+}
+
+/*
+ * init_weapon:
+ *	Set up the initial goodies for a weapon
+ */
+
+init_weapon(weap, type)
+struct object *weap;
+int type;
+{
+	reg struct init_weps *iwp;
+
+	weap->o_type = WEAPON;
+	weap->o_which = type;
+	iwp = &weaps[type];
+	strcpy(weap->o_damage,iwp->w_dam);
+	strcpy(weap->o_hurldmg,iwp->w_hrl);
+	weap->o_launch = iwp->w_launch;
+	weap->o_flags = iwp->w_flags;
+	weap->o_weight = iwp->w_wght;
+	weap->o_typname = things[TYP_WEAPON].mi_name;
+	if (o_on(weap,ISMANY))
+		weap->o_count = rnd(8) + 8;
+	else
+		weap->o_count = 1;
+	weap->o_group = newgrp();
+	weap->o_vol = itemvol(weap);
+}
+
+/*
+ * hit_monster:
+ *	Does the missile hit the monster
+ */
+hit_monster(mp, obj)
+struct coord *mp;
+struct object *obj;
+{
+	return fight(mp, obj, TRUE);
+}
+
+/*
+ * num:
+ *	Figure out the plus number for armor/weapons
+ */
+char *
+num(n1, n2)
+int n1, n2;
+{
+	static char numbuf[LINLEN];
+
+	if (n1 == 0 && n2 == 0)
+		return "+0";
+	if (n2 == 0)
+		sprintf(numbuf, "%s%d", n1 < 0 ? "" : "+", n1);
+	else
+		sprintf(numbuf,"%s%d,%s%d",n1<0 ? "":"+",n1,n2<0 ? "":"+",n2);  
+	return numbuf;
+}
+
+/*
+ * wield:
+ *	Pull out a certain weapon
+ */
+wield()
+{
+	reg struct linked_list *item;
+	reg struct object *obj, *oweapon;
+
+	oweapon = cur_weapon;
+	if (!dropcheck(cur_weapon)) {
+		cur_weapon = oweapon;
+		return;
+	}
+	cur_weapon = oweapon;
+	if ((item = get_item("wield", WEAPON)) == NULL)
+		return;
+	obj = OBJPTR(item);
+	if (is_current(obj)) {
+		after = FALSE;
+		return;
+	}
+	msg("Wielding %s", inv_name(obj, TRUE));
+	cur_weapon = obj;
+}
+
+/*
+ * fallpos:
+ *	Pick a random position around the give (y, x) coordinates
+ */
+fallpos(pos, newpos, passages)
+struct coord *pos, *newpos;
+bool passages;
+{
+	reg int y, x, ch;
+
+	for (y = pos->y - 1; y <= pos->y + 1; y++) {
+		for (x = pos->x - 1; x <= pos->x + 1; x++) {
+			/*
+			 * check to make certain the spot is empty, if it is,
+			 * put the object there, set it in the level list
+			 * and re-draw the room if he can see it
+			 */
+			if (y == hero.y && x == hero.x)
+				continue;
+			ch = winat(y, x);
+			if (ch == FLOOR || (passages && ch == PASSAGE)) {
+				newpos->y = y;
+				newpos->x = x;
+				return TRUE;
+			}
+		}
+	}
+	return FALSE;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/srogue/wizard.c	Thu Nov 25 12:21:41 2010 +0000
@@ -0,0 +1,369 @@
+/*
+ * Mostly wizard commands. Sometimes used by players.
+ *
+ * @(#)wizard.c	9.0	(rdk)	 7/17/84
+ *
+ * Super-Rogue
+ * Copyright (C) 1984 Robert D. Kindelberger
+ * All rights reserved.
+ *
+ * Based on "Rogue: Exploring the Dungeons of Doom"
+ * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
+ * All rights reserved.
+ *
+ * See the file LICENSE.TXT for full copyright and licensing information.
+ */
+
+#include <termios.h>
+#include <ctype.h>
+#include "rogue.h"
+#include <pwd.h>
+#include "rogue.ext"
+
+extern struct termios terminal;
+
+/*
+ * whatis:
+ *	What a certain object is
+ */
+whatis(what)
+struct linked_list *what;
+{
+	reg struct object *obj;
+	reg struct linked_list *item;
+	reg int wh;
+
+	if (what == NULL) {				/* we need to ask */
+		if ((item = get_item("identify", 0)) == NULL)
+			return;
+	}
+	else							/* no need to ask */
+		item = what;
+	obj = OBJPTR(item);
+	setoflg(obj, ISKNOW);
+	wh = obj->o_which;
+	switch (obj->o_type) {
+		case SCROLL:
+			s_know[wh] = TRUE;
+			if (s_guess[wh]) {
+				free(s_guess[wh]);
+				s_guess[wh] = NULL;
+			}
+	    when POTION:
+			p_know[wh] = TRUE;
+			if (p_guess[wh]) {
+				free(p_guess[wh]);
+				p_guess[wh] = NULL;
+			}
+		when STICK:
+			ws_know[wh] = TRUE;
+			if (ws_guess[wh]) {
+				free(ws_guess[wh]);
+			ws_guess[wh] = NULL;
+			}
+	    when RING:
+			r_know[wh] = TRUE;
+			if (r_guess[wh]) {
+				free(r_guess[wh]);
+				r_guess[wh] = NULL;
+			}
+	}
+	if (what == NULL)
+		msg(inv_name(obj, FALSE));
+}
+
+
+/*
+ * create_obj:
+ *	Create any object for wizard or scroll (almost)
+ */
+create_obj(fscr)
+bool fscr;
+{
+	reg struct linked_list *item;
+	reg struct object *obj;
+	reg int wh, ch, otype;
+	char newitem, newtype, msz, *oname;
+	struct magic_info *mf;
+	bool nogood = TRUE, inhw = FALSE;
+
+	if (fscr)
+		msg(" ");
+	else if (wizard) {
+		msg("Create what?%s: ", starlist);
+		ch = readchar();
+		mpos = 0;
+		if (ch == ESCAPE)
+			return;
+		else if (ch != '*')
+			nogood = FALSE;
+	}
+	if (nogood) {
+		inhw = TRUE;
+		wclear(hw);
+		wprintw(hw,"Item\tKey\n\n");
+		for (otype = 0; otype < NUMTHINGS; otype++) {
+			if (otype != TYP_AMULET || wizard) {
+				mf = &thnginfo[otype];
+				wprintw(hw,"%s\t %c\n",things[otype].mi_name,mf->mf_show);
+			}
+		}
+		if (wizard)
+			waddstr(hw,"monster\t (A-z)");
+		wprintw(hw,"\n\nWhat do you want to create? ");
+		draw(hw);
+		do {
+			ch = readchar();
+			if (ch == ESCAPE) {
+				after = FALSE;
+				restscr(cw);
+				return;
+			}
+			switch (ch) {
+				case RING:		case STICK:	case POTION:
+				case SCROLL:	case ARMOR:	case WEAPON:
+				case FOOD:		case AMULET:
+					nogood = FALSE;
+					break;
+				default:
+					if (isalpha(ch))
+						nogood = FALSE;
+			}
+		} while (nogood);
+	}
+	if (isalpha(ch)) {
+		if (inhw)
+			restscr(cw);
+		makemons(ch);		/* make monster & be done with it */
+		return;
+	}
+	otype = getindex(ch);
+	if (otype == -1 || (otype == AMULET && !wizard)) {
+		if (inhw)
+			restscr(cw);
+		mpos = 0;
+		msg("You can't create that !!");
+		return;
+	}
+	newitem = ch;
+	mf = &thnginfo[otype];
+	oname = things[otype].mi_name;
+	msz = mf->mf_max;
+	nogood = TRUE;
+	if (msz == 1) {		/* if only one type of item */
+		ch = 'a';
+		nogood = FALSE;
+	}
+	else if (!fscr && wizard) {
+		if (!inhw) {
+			msg("Which %s?%s: ", oname, starlist);
+			ch = readchar();
+			if (ch == ESCAPE)
+				return;
+			if (ch != '*')
+				nogood = FALSE;
+		}
+	}
+	if (nogood) {
+		struct magic_item *wmi;
+		int ii;
+
+		mpos = 0;
+		inhw = TRUE;
+		switch(newitem) {
+			case POTION:	wmi = &p_magic[0];
+			when SCROLL:	wmi = &s_magic[0];
+			when RING:		wmi = &r_magic[0];
+			when STICK:		wmi = &ws_magic[0];
+			when WEAPON:	wmi = &w_magic[0];
+			otherwise:		wmi = &a_magic[0];
+		}
+		wclear(hw);
+		for (ii = 0 ; ii < msz ; ii++) {
+			mvwaddch(hw,ii % 13,ii > 12 ? COLS/2 : 0, ii + 'a');
+			waddstr(hw,") ");
+			waddstr(hw,wmi->mi_name);
+			wmi++;
+		}
+		sprintf(prbuf,"Which %s? ", oname);
+		mvwaddstr(hw,LINES - 1, 0, prbuf);
+		draw(hw);
+		do {
+			ch = readchar();
+			if (ch == ESCAPE) {
+				restscr(cw);
+				msg("");
+				return;
+			}
+		} while (!isalpha(ch));
+	}
+	if (inhw)			/* restore screen if need be */
+		restscr(cw);
+
+	newtype = tolower(ch) - 'a';
+	if (newtype < 0 || newtype >= msz) {	/* if an illegal value */
+		mpos = 0;
+		after = FALSE;
+		if (inhw)
+			restscr(cw);
+		msg("There is no such %s", oname);
+		return;
+	}
+	mpos = 0;
+	item = new_thing(FALSE, newitem, newtype);
+	obj = OBJPTR(item);
+	wh = obj->o_type;
+	if (wh == WEAPON || wh == ARMOR || wh == RING) {
+		if (fscr)					/* users get +3 to -3 */
+			ch = rnd(7) - 3;
+		else {						/* wizard gets to choose */
+			if (wh == RING)
+				init_ring(obj, TRUE);
+			else
+				ch = getbless();
+		}
+		if (wh == WEAPON)
+			obj->o_hplus = obj->o_dplus = ch;
+		else if (wh == ARMOR)
+			obj->o_ac = armors[obj->o_which].a_class - ch;
+		if (ch < 0)
+			setoflg(obj, ISCURSED);
+		else
+			resoflg(obj, ISCURSED);
+	}
+	mpos = 0;
+	if (fscr)
+		whatis(item);			/* identify for aquirement scroll */
+	wh = add_pack(item, FALSE);
+	if (wh == FALSE)			/* won't fit in pack */
+		discard(item);
+}
+
+
+/*
+ * getbless:
+ *	Get a blessing for a wizards object
+ */
+getbless()
+{
+	int bless;
+
+	msg("Blessing: ");
+	prbuf[0] = '\0';
+	bless = get_str(prbuf, cw);
+	if (bless == NORM)
+		bless = atoi(prbuf);
+	else
+		bless = 0;
+	return bless;
+}
+
+/*
+ * makemons:
+ *	Make a monster
+ */
+makemons(what)
+int what;
+{
+	reg int x, y, oktomake = FALSE, appear = 1;
+	struct coord mp;
+
+	oktomake = FALSE;
+	for (x = hero.x - 1 ; x <= hero.x + 1 ; x++) {
+		for (y = hero.y - 1 ; y <= hero.y + 1 ; y++) {
+			if (x != hero.x || y != hero.y) {
+				if (step_ok(winat(y, x)) && rnd(++appear) == 0) {
+					mp.x = x;
+					mp.y = y;
+					oktomake = TRUE;
+					break;
+				}
+			}
+		}
+	}
+	if (oktomake) {
+		new_monster(midx(what), &mp, FALSE);
+		look(FALSE);
+	}
+	return oktomake;
+}
+
+/*
+ * telport:
+ *	Bamf the thing someplace else
+ */
+teleport(spot, th)
+struct coord spot;
+struct thing *th;
+{
+	reg int rm, y, x;
+	struct coord oldspot;
+	struct room *rp;
+	bool ishero;
+
+	ishero = (th == &player);
+	oldspot = th->t_pos;
+	y = th->t_pos.y;
+	x = th->t_pos.x;
+	mvwaddch(cw, y, x, th->t_oldch); 
+	if (!ishero)
+		mvwaddch(mw, y, x, ' ');
+	rp = roomin(&spot);
+	if (spot.y < 0 || !step_ok(winat(spot.y, spot.x))) {
+		rp = &rooms[rnd_room()];
+		th->t_pos = *rnd_pos(rp);
+	}
+	else
+		th->t_pos = spot;
+	rm = rp - &rooms[0];
+	th->t_room = rp;
+	th->t_oldch = mvwinch(cw, th->t_pos.y, th->t_pos.x);
+	light(&oldspot);
+	th->t_nomove = 0;
+	if (ishero) {
+		light(&hero);
+		mvwaddch(cw, hero.y, hero.x, PLAYER);
+		/*
+		 * turn off ISHELD in case teleportation was done
+		 * while fighting a Fungi or Bone Devil.
+		 */
+		if (pl_on(ISHELD))
+			unhold('F');
+		count = 0;
+		running = FALSE;
+		flushinp();			/* flush typeahead */
+		nochange = FALSE;
+	}
+	else
+		mvwaddch(mw, th->t_pos.y, th->t_pos.x, th->t_type);
+	return rm;
+}
+
+/*
+ * passwd:
+ *	See if user knows password
+ */
+passwd()
+{
+	reg char *sp, c;
+	bool passok;
+	char buf[LINLEN], *xcrypt();
+
+	msg(wizstr);
+	mpos = 0;
+	sp = buf;
+	while ((c = getchar()) != '\n' && c != '\r' && c != ESCAPE)
+	if (c == terminal.c_cc[VKILL])
+		sp = buf;
+	else if (c == terminal.c_cc[VERASE] && sp > buf)
+		sp--;
+	else
+		*sp++ = c;
+	if (sp == buf)
+		passok = FALSE;
+	else {
+		*sp = '\0';
+		passok = (strcmp(PASSWD, xcrypt(buf, "mT")) == 0);
+	}
+	return passok;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/srogue/xcrypt.c	Thu Nov 25 12:21:41 2010 +0000
@@ -0,0 +1,696 @@
+/*
+ * FreeSec: libcrypt
+ *
+ * Copyright (C) 1994 David Burren
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name(s) of the author(s) nor the names of other contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR(S) OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *
+ * This is an original implementation of the DES and the crypt(3) interfaces
+ * by David Burren <davidb@werj.com.au>.
+ *
+ * An excellent reference on the underlying algorithm (and related
+ * algorithms) is:
+ *
+ *	B. Schneier, Applied Cryptography: protocols, algorithms,
+ *	and source code in C, John Wiley & Sons, 1994.
+ *
+ * Note that in that book's description of DES the lookups for the initial,
+ * pbox, and final permutations are inverted (this has been brought to the
+ * attention of the author).  A list of errata for this book has been
+ * posted to the sci.crypt newsgroup by the author and is available for FTP.
+ *
+ * NOTE:
+ * This file has a static version of des_setkey() so that crypt.o exports
+ * only the crypt() interface. This is required to make binaries linked
+ * against crypt.o exportable or re-exportable from the USA.
+ */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <pwd.h>
+#include <string.h>
+
+#ifdef DEBUG
+# include <stdio.h>
+#endif
+#define _PASSWORD_EFMT1 '_'
+
+static unsigned char	IP[64] = {
+	58, 50, 42, 34, 26, 18, 10,  2, 60, 52, 44, 36, 28, 20, 12,  4,
+	62, 54, 46, 38, 30, 22, 14,  6, 64, 56, 48, 40, 32, 24, 16,  8,
+	57, 49, 41, 33, 25, 17,  9,  1, 59, 51, 43, 35, 27, 19, 11,  3,
+	61, 53, 45, 37, 29, 21, 13,  5, 63, 55, 47, 39, 31, 23, 15,  7
+};
+
+static unsigned char	inv_key_perm[64];
+static unsigned char	key_perm[56] = {
+	57, 49, 41, 33, 25, 17,  9,  1, 58, 50, 42, 34, 26, 18,
+	10,  2, 59, 51, 43, 35, 27, 19, 11,  3, 60, 52, 44, 36,
+	63, 55, 47, 39, 31, 23, 15,  7, 62, 54, 46, 38, 30, 22,
+	14,  6, 61, 53, 45, 37, 29, 21, 13,  5, 28, 20, 12,  4
+};
+
+static unsigned char	key_shifts[16] = {
+	1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1
+};
+
+static unsigned char	inv_comp_perm[56];
+static unsigned char	comp_perm[48] = {
+	14, 17, 11, 24,  1,  5,  3, 28, 15,  6, 21, 10,
+	23, 19, 12,  4, 26,  8, 16,  7, 27, 20, 13,  2,
+	41, 52, 31, 37, 47, 55, 30, 40, 51, 45, 33, 48,
+	44, 49, 39, 56, 34, 53, 46, 42, 50, 36, 29, 32
+};
+
+/*
+ *	No E box is used, as it's replaced by some ANDs, shifts, and ORs.
+ */
+
+static unsigned char	u_sbox[8][64];
+static unsigned char	sbox[8][64] = {
+	{
+		14,  4, 13,  1,  2, 15, 11,  8,  3, 10,  6, 12,  5,  9,  0,  7,
+		 0, 15,  7,  4, 14,  2, 13,  1, 10,  6, 12, 11,  9,  5,  3,  8,
+		 4,  1, 14,  8, 13,  6,  2, 11, 15, 12,  9,  7,  3, 10,  5,  0,
+		15, 12,  8,  2,  4,  9,  1,  7,  5, 11,  3, 14, 10,  0,  6, 13
+	},
+	{
+		15,  1,  8, 14,  6, 11,  3,  4,  9,  7,  2, 13, 12,  0,  5, 10,
+		 3, 13,  4,  7, 15,  2,  8, 14, 12,  0,  1, 10,  6,  9, 11,  5,
+		 0, 14,  7, 11, 10,  4, 13,  1,  5,  8, 12,  6,  9,  3,  2, 15,
+		13,  8, 10,  1,  3, 15,  4,  2, 11,  6,  7, 12,  0,  5, 14,  9
+	},
+	{
+		10,  0,  9, 14,  6,  3, 15,  5,  1, 13, 12,  7, 11,  4,  2,  8,
+		13,  7,  0,  9,  3,  4,  6, 10,  2,  8,  5, 14, 12, 11, 15,  1,
+		13,  6,  4,  9,  8, 15,  3,  0, 11,  1,  2, 12,  5, 10, 14,  7,
+		 1, 10, 13,  0,  6,  9,  8,  7,  4, 15, 14,  3, 11,  5,  2, 12
+	},
+	{
+		 7, 13, 14,  3,  0,  6,  9, 10,  1,  2,  8,  5, 11, 12,  4, 15,
+		13,  8, 11,  5,  6, 15,  0,  3,  4,  7,  2, 12,  1, 10, 14,  9,
+		10,  6,  9,  0, 12, 11,  7, 13, 15,  1,  3, 14,  5,  2,  8,  4,
+		 3, 15,  0,  6, 10,  1, 13,  8,  9,  4,  5, 11, 12,  7,  2, 14
+	},
+	{
+		 2, 12,  4,  1,  7, 10, 11,  6,  8,  5,  3, 15, 13,  0, 14,  9,
+		14, 11,  2, 12,  4,  7, 13,  1,  5,  0, 15, 10,  3,  9,  8,  6,
+		 4,  2,  1, 11, 10, 13,  7,  8, 15,  9, 12,  5,  6,  3,  0, 14,
+		11,  8, 12,  7,  1, 14,  2, 13,  6, 15,  0,  9, 10,  4,  5,  3
+	},
+	{
+		12,  1, 10, 15,  9,  2,  6,  8,  0, 13,  3,  4, 14,  7,  5, 11,
+		10, 15,  4,  2,  7, 12,  9,  5,  6,  1, 13, 14,  0, 11,  3,  8,
+		 9, 14, 15,  5,  2,  8, 12,  3,  7,  0,  4, 10,  1, 13, 11,  6,
+		 4,  3,  2, 12,  9,  5, 15, 10, 11, 14,  1,  7,  6,  0,  8, 13
+	},
+	{
+		 4, 11,  2, 14, 15,  0,  8, 13,  3, 12,  9,  7,  5, 10,  6,  1,
+		13,  0, 11,  7,  4,  9,  1, 10, 14,  3,  5, 12,  2, 15,  8,  6,
+		 1,  4, 11, 13, 12,  3,  7, 14, 10, 15,  6,  8,  0,  5,  9,  2,
+		 6, 11, 13,  8,  1,  4, 10,  7,  9,  5,  0, 15, 14,  2,  3, 12
+	},
+	{
+		13,  2,  8,  4,  6, 15, 11,  1, 10,  9,  3, 14,  5,  0, 12,  7,
+		 1, 15, 13,  8, 10,  3,  7,  4, 12,  5,  6, 11,  0, 14,  9,  2,
+		 7, 11,  4,  1,  9, 12, 14,  2,  0,  6, 10, 13, 15,  3,  5,  8,
+		 2,  1, 14,  7,  4, 10,  8, 13, 15, 12,  9,  0,  3,  5,  6, 11
+	}
+};
+
+static unsigned char	un_pbox[32];
+static unsigned char	pbox[32] = {
+	16,  7, 20, 21, 29, 12, 28, 17,  1, 15, 23, 26,  5, 18, 31, 10,
+	 2,  8, 24, 14, 32, 27,  3,  9, 19, 13, 30,  6, 22, 11,  4, 25
+};
+
+static unsigned int bits32[32] =
+{
+	0x80000000, 0x40000000, 0x20000000, 0x10000000,
+	0x08000000, 0x04000000, 0x02000000, 0x01000000,
+	0x00800000, 0x00400000, 0x00200000, 0x00100000,
+	0x00080000, 0x00040000, 0x00020000, 0x00010000,
+	0x00008000, 0x00004000, 0x00002000, 0x00001000,
+	0x00000800, 0x00000400, 0x00000200, 0x00000100,
+	0x00000080, 0x00000040, 0x00000020, 0x00000010,
+	0x00000008, 0x00000004, 0x00000002, 0x00000001
+};
+
+static unsigned char	bits8[8] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 };
+
+static unsigned int saltbits;
+static int	old_salt;
+static unsigned int *bits28, *bits24;
+static unsigned char	init_perm[64], final_perm[64];
+static unsigned int en_keysl[16], en_keysr[16];
+static unsigned int de_keysl[16], de_keysr[16];
+static int	des_initialised = 0;
+static unsigned char	m_sbox[4][4096];
+static unsigned int psbox[4][256];
+static unsigned int ip_maskl[8][256], ip_maskr[8][256];
+static unsigned int fp_maskl[8][256], fp_maskr[8][256];
+static unsigned int key_perm_maskl[8][128], key_perm_maskr[8][128];
+static unsigned int comp_maskl[8][128], comp_maskr[8][128];
+static unsigned int old_rawkey0, old_rawkey1;
+
+static unsigned char	ascii64[] =
+	 "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
+/*	  0000000000111111111122222222223333333333444444444455555555556666 */
+/*	  0123456789012345678901234567890123456789012345678901234567890123 */
+
+static __inline int
+ascii_to_bin(ch)
+	char ch;
+{
+	if (ch > 'z')
+		return(0);
+	if (ch >= 'a')
+		return(ch - 'a' + 38);
+	if (ch > 'Z')
+		return(0);
+	if (ch >= 'A')
+		return(ch - 'A' + 12);
+	if (ch > '9')
+		return(0);
+	if (ch >= '.')
+		return(ch - '.');
+	return(0);
+}
+
+static void
+des_init()
+{
+	int	i, j, b, k, inbit, obit;
+	unsigned int	*p, *il, *ir, *fl, *fr;
+
+	old_rawkey0 = old_rawkey1 = 0;
+	saltbits = 0;
+	old_salt = 0;
+	bits24 = (bits28 = bits32 + 4) + 4;
+
+	/*
+	 * Invert the S-boxes, reordering the input bits.
+	 */
+	for (i = 0; i < 8; i++)
+		for (j = 0; j < 64; j++) {
+			b = (j & 0x20) | ((j & 1) << 4) | ((j >> 1) & 0xf);
+			u_sbox[i][j] = sbox[i][b];
+		}
+
+	/*
+	 * Convert the inverted S-boxes into 4 arrays of 8 bits.
+	 * Each will handle 12 bits of the S-box input.
+	 */
+	for (b = 0; b < 4; b++)
+		for (i = 0; i < 64; i++)
+			for (j = 0; j < 64; j++)
+				m_sbox[b][(i << 6) | j] =
+					(u_sbox[(b << 1)][i] << 4) |
+					u_sbox[(b << 1) + 1][j];
+
+	/*
+	 * Set up the initial & final permutations into a useful form, and
+	 * initialise the inverted key permutation.
+	 */
+	for (i = 0; i < 64; i++) {
+		init_perm[final_perm[i] = IP[i] - 1] = i;
+		inv_key_perm[i] = 255;
+	}
+
+	/*
+	 * Invert the key permutation and initialise the inverted key
+	 * compression permutation.
+	 */
+	for (i = 0; i < 56; i++) {
+		inv_key_perm[key_perm[i] - 1] = i;
+		inv_comp_perm[i] = 255;
+	}
+
+	/*
+	 * Invert the key compression permutation.
+	 */
+	for (i = 0; i < 48; i++) {
+		inv_comp_perm[comp_perm[i] - 1] = i;
+	}
+
+	/*
+	 * Set up the OR-mask arrays for the initial and final permutations,
+	 * and for the key initial and compression permutations.
+	 */
+	for (k = 0; k < 8; k++) {
+		for (i = 0; i < 256; i++) {
+			*(il = &ip_maskl[k][i]) = 0;
+			*(ir = &ip_maskr[k][i]) = 0;
+			*(fl = &fp_maskl[k][i]) = 0;
+			*(fr = &fp_maskr[k][i]) = 0;
+			for (j = 0; j < 8; j++) {
+				inbit = 8 * k + j;
+				if (i & bits8[j]) {
+					if ((obit = init_perm[inbit]) < 32)
+						*il |= bits32[obit];
+					else
+						*ir |= bits32[obit-32];
+					if ((obit = final_perm[inbit]) < 32)
+						*fl |= bits32[obit];
+					else
+						*fr |= bits32[obit - 32];
+				}
+			}
+		}
+		for (i = 0; i < 128; i++) {
+			*(il = &key_perm_maskl[k][i]) = 0;
+			*(ir = &key_perm_maskr[k][i]) = 0;
+			for (j = 0; j < 7; j++) {
+				inbit = 8 * k + j;
+				if (i & bits8[j + 1]) {
+					if ((obit = inv_key_perm[inbit]) == 255)
+						continue;
+					if (obit < 28)
+						*il |= bits28[obit];
+					else
+						*ir |= bits28[obit - 28];
+				}
+			}
+			*(il = &comp_maskl[k][i]) = 0;
+			*(ir = &comp_maskr[k][i]) = 0;
+			for (j = 0; j < 7; j++) {
+				inbit = 7 * k + j;
+				if (i & bits8[j + 1]) {
+					if ((obit=inv_comp_perm[inbit]) == 255)
+						continue;
+					if (obit < 24)
+						*il |= bits24[obit];
+					else
+						*ir |= bits24[obit - 24];
+				}
+			}
+		}
+	}
+
+	/*
+	 * Invert the P-box permutation, and convert into OR-masks for
+	 * handling the output of the S-box arrays setup above.
+	 */
+	for (i = 0; i < 32; i++)
+		un_pbox[pbox[i] - 1] = i;
+
+	for (b = 0; b < 4; b++)
+		for (i = 0; i < 256; i++) {
+			*(p = &psbox[b][i]) = 0;
+			for (j = 0; j < 8; j++) {
+				if (i & bits8[j])
+					*p |= bits32[un_pbox[8 * b + j]];
+			}
+		}
+
+	des_initialised = 1;
+}
+
+static void
+setup_salt(salt)
+	int salt;
+{
+	unsigned int	obit, saltbit;
+	int	i;
+
+	if (salt == old_salt)
+		return;
+	old_salt = salt;
+
+	saltbits = 0;
+	saltbit = 1;
+	obit = 0x800000;
+	for (i = 0; i < 24; i++) {
+		if (salt & saltbit)
+			saltbits |= obit;
+		saltbit <<= 1;
+		obit >>= 1;
+	}
+}
+
+static int
+des_setkey(key)
+	const char *key;
+{
+	unsigned int k0, k1, rawkey0, rawkey1;
+	int	shifts, round;
+
+	if (!des_initialised)
+		des_init();
+
+	rawkey0 = ntohl(*(unsigned int *) key);
+	rawkey1 = ntohl(*(unsigned int *) (key + 4));
+
+	if ((rawkey0 | rawkey1)
+	    && rawkey0 == old_rawkey0
+	    && rawkey1 == old_rawkey1) {
+		/*
+		 * Already setup for this key.
+		 * This optimisation fails on a zero key (which is weak and
+		 * has bad parity anyway) in order to simplify the starting
+		 * conditions.
+		 */
+		return(0);
+	}
+	old_rawkey0 = rawkey0;
+	old_rawkey1 = rawkey1;
+
+	/*
+	 *	Do key permutation and split into two 28-bit subkeys.
+	 */
+	k0 = key_perm_maskl[0][rawkey0 >> 25]
+	   | key_perm_maskl[1][(rawkey0 >> 17) & 0x7f]
+	   | key_perm_maskl[2][(rawkey0 >> 9) & 0x7f]
+	   | key_perm_maskl[3][(rawkey0 >> 1) & 0x7f]
+	   | key_perm_maskl[4][rawkey1 >> 25]
+	   | key_perm_maskl[5][(rawkey1 >> 17) & 0x7f]
+	   | key_perm_maskl[6][(rawkey1 >> 9) & 0x7f]
+	   | key_perm_maskl[7][(rawkey1 >> 1) & 0x7f];
+	k1 = key_perm_maskr[0][rawkey0 >> 25]
+	   | key_perm_maskr[1][(rawkey0 >> 17) & 0x7f]
+	   | key_perm_maskr[2][(rawkey0 >> 9) & 0x7f]
+	   | key_perm_maskr[3][(rawkey0 >> 1) & 0x7f]
+	   | key_perm_maskr[4][rawkey1 >> 25]
+	   | key_perm_maskr[5][(rawkey1 >> 17) & 0x7f]
+	   | key_perm_maskr[6][(rawkey1 >> 9) & 0x7f]
+	   | key_perm_maskr[7][(rawkey1 >> 1) & 0x7f];
+	/*
+	 *	Rotate subkeys and do compression permutation.
+	 */
+	shifts = 0;
+	for (round = 0; round < 16; round++) {
+		unsigned int	t0, t1;
+
+		shifts += key_shifts[round];
+
+		t0 = (k0 << shifts) | (k0 >> (28 - shifts));
+		t1 = (k1 << shifts) | (k1 >> (28 - shifts));
+
+		de_keysl[15 - round] =
+		en_keysl[round] = comp_maskl[0][(t0 >> 21) & 0x7f]
+				| comp_maskl[1][(t0 >> 14) & 0x7f]
+				| comp_maskl[2][(t0 >> 7) & 0x7f]
+				| comp_maskl[3][t0 & 0x7f]
+				| comp_maskl[4][(t1 >> 21) & 0x7f]
+				| comp_maskl[5][(t1 >> 14) & 0x7f]
+				| comp_maskl[6][(t1 >> 7) & 0x7f]
+				| comp_maskl[7][t1 & 0x7f];
+
+		de_keysr[15 - round] =
+		en_keysr[round] = comp_maskr[0][(t0 >> 21) & 0x7f]
+				| comp_maskr[1][(t0 >> 14) & 0x7f]
+				| comp_maskr[2][(t0 >> 7) & 0x7f]
+				| comp_maskr[3][t0 & 0x7f]
+				| comp_maskr[4][(t1 >> 21) & 0x7f]
+				| comp_maskr[5][(t1 >> 14) & 0x7f]
+				| comp_maskr[6][(t1 >> 7) & 0x7f]
+				| comp_maskr[7][t1 & 0x7f];
+	}
+	return(0);
+}
+
+static int
+do_des(l_in, r_in, l_out, r_out, count)
+	unsigned int l_in, r_in, *l_out, *r_out;
+	int count;
+{
+	/*
+	 *	l_in, r_in, l_out, and r_out are in pseudo-"big-endian" format.
+	 */
+	unsigned int	l, r, *kl, *kr, *kl1, *kr1;
+	unsigned int	f, r48l, r48r;
+	int		round;
+
+	if (count == 0) {
+		return(1);
+	} else if (count > 0) {
+		/*
+		 * Encrypting
+		 */
+		kl1 = en_keysl;
+		kr1 = en_keysr;
+	} else {
+		/*
+		 * Decrypting
+		 */
+		count = -count;
+		kl1 = de_keysl;
+		kr1 = de_keysr;
+	}
+
+	/*
+	 *	Do initial permutation (IP).
+	 */
+	l = ip_maskl[0][l_in >> 24]
+	  | ip_maskl[1][(l_in >> 16) & 0xff]
+	  | ip_maskl[2][(l_in >> 8) & 0xff]
+	  | ip_maskl[3][l_in & 0xff]
+	  | ip_maskl[4][r_in >> 24]
+	  | ip_maskl[5][(r_in >> 16) & 0xff]
+	  | ip_maskl[6][(r_in >> 8) & 0xff]
+	  | ip_maskl[7][r_in & 0xff];
+	r = ip_maskr[0][l_in >> 24]
+	  | ip_maskr[1][(l_in >> 16) & 0xff]
+	  | ip_maskr[2][(l_in >> 8) & 0xff]
+	  | ip_maskr[3][l_in & 0xff]
+	  | ip_maskr[4][r_in >> 24]
+	  | ip_maskr[5][(r_in >> 16) & 0xff]
+	  | ip_maskr[6][(r_in >> 8) & 0xff]
+	  | ip_maskr[7][r_in & 0xff];
+
+	while (count--) {
+		/*
+		 * Do each round.
+		 */
+		kl = kl1;
+		kr = kr1;
+		round = 16;
+		while (round--) {
+			/*
+			 * Expand R to 48 bits (simulate the E-box).
+			 */
+			r48l	= ((r & 0x00000001) << 23)
+				| ((r & 0xf8000000) >> 9)
+				| ((r & 0x1f800000) >> 11)
+				| ((r & 0x01f80000) >> 13)
+				| ((r & 0x001f8000) >> 15);
+
+			r48r	= ((r & 0x0001f800) << 7)
+				| ((r & 0x00001f80) << 5)
+				| ((r & 0x000001f8) << 3)
+				| ((r & 0x0000001f) << 1)
+				| ((r & 0x80000000) >> 31);
+			/*
+			 * Do salting for crypt() and friends, and
+			 * XOR with the permuted key.
+			 */
+			f = (r48l ^ r48r) & saltbits;
+			r48l ^= f ^ *kl++;
+			r48r ^= f ^ *kr++;
+			/*
+			 * Do sbox lookups (which shrink it back to 32 bits)
+			 * and do the pbox permutation at the same time.
+			 */
+			f = psbox[0][m_sbox[0][r48l >> 12]]
+			  | psbox[1][m_sbox[1][r48l & 0xfff]]
+			  | psbox[2][m_sbox[2][r48r >> 12]]
+			  | psbox[3][m_sbox[3][r48r & 0xfff]];
+			/*
+			 * Now that we've permuted things, complete f().
+			 */
+			f ^= l;
+			l = r;
+			r = f;
+		}
+		r = l;
+		l = f;
+	}
+	/*
+	 * Do final permutation (inverse of IP).
+	 */
+	*l_out	= fp_maskl[0][l >> 24]
+		| fp_maskl[1][(l >> 16) & 0xff]
+		| fp_maskl[2][(l >> 8) & 0xff]
+		| fp_maskl[3][l & 0xff]
+		| fp_maskl[4][r >> 24]
+		| fp_maskl[5][(r >> 16) & 0xff]
+		| fp_maskl[6][(r >> 8) & 0xff]
+		| fp_maskl[7][r & 0xff];
+	*r_out	= fp_maskr[0][l >> 24]
+		| fp_maskr[1][(l >> 16) & 0xff]
+		| fp_maskr[2][(l >> 8) & 0xff]
+		| fp_maskr[3][l & 0xff]
+		| fp_maskr[4][r >> 24]
+		| fp_maskr[5][(r >> 16) & 0xff]
+		| fp_maskr[6][(r >> 8) & 0xff]
+		| fp_maskr[7][r & 0xff];
+	return(0);
+}
+
+static int
+des_cipher(in, out, salt, count)
+	const char *in;
+	char *out;
+	int salt;
+	int count;
+{
+	unsigned int l_out, r_out, rawl, rawr;
+	unsigned int x[2];
+	int	retval;
+
+	if (!des_initialised)
+		des_init();
+
+	setup_salt(salt);
+
+	memcpy(x, in, sizeof x);
+	rawl = ntohl(x[0]);
+	rawr = ntohl(x[1]);
+	retval = do_des(rawl, rawr, &l_out, &r_out, count);
+
+	x[0] = htonl(l_out);
+	x[1] = htonl(r_out);
+	memcpy(out, x, sizeof x);
+	return(retval);
+}
+
+char *
+xcrypt(key, setting)
+	const char *key;
+	const char *setting;
+{
+	int		i;
+	unsigned int	count, salt, l, r0, r1, keybuf[2];
+	unsigned char		*p, *q;
+	static unsigned char	output[21];
+
+	if (!des_initialised)
+		des_init();
+
+	/*
+	 * Copy the key, shifting each character up by one bit
+	 * and padding with zeros.
+	 */
+	q = (unsigned char *) keybuf;
+	while ((q - (unsigned char *) keybuf) < sizeof(keybuf)) {
+		if ((*q++ = *key << 1))
+			key++;
+	}
+	if (des_setkey((unsigned char *) keybuf))
+		return(NULL);
+
+	if (*setting == _PASSWORD_EFMT1) {
+		/*
+		 * "new"-style:
+		 *	setting - underscore, 4 bytes of count, 4 bytes of salt
+		 *	key - unlimited characters
+		 */
+		for (i = 1, count = 0; i < 5; i++)
+			count |= ascii_to_bin(setting[i]) << (i - 1) * 6;
+
+		for (i = 5, salt = 0; i < 9; i++)
+			salt |= ascii_to_bin(setting[i]) << (i - 5) * 6;
+
+		while (*key) {
+			/*
+			 * Encrypt the key with itself.
+			 */
+			if (des_cipher((unsigned char*)keybuf, (unsigned char*)keybuf, 0, 1))
+				return(NULL);
+			/*
+			 * And XOR with the next 8 characters of the key.
+			 */
+			q = (unsigned char *) keybuf;
+			while (((q - (unsigned char *) keybuf) < sizeof(keybuf)) &&
+					*key)
+				*q++ ^= *key++ << 1;
+
+			if (des_setkey((unsigned char *) keybuf))
+				return(NULL);
+		}
+		strncpy((char *)output, setting, 9);
+
+		/*
+		 * Double check that we weren't given a short setting.
+		 * If we were, the above code will probably have created
+		 * wierd values for count and salt, but we don't really care.
+		 * Just make sure the output string doesn't have an extra
+		 * NUL in it.
+		 */
+		output[9] = '\0';
+		p = output + strlen((const char *)output);
+	} else {
+		/*
+		 * "old"-style:
+		 *	setting - 2 bytes of salt
+		 *	key - up to 8 characters
+		 */
+		count = 25;
+
+		salt = (ascii_to_bin(setting[1]) << 6)
+		     |  ascii_to_bin(setting[0]);
+
+		output[0] = setting[0];
+		/*
+		 * If the encrypted password that the salt was extracted from
+		 * is only 1 character long, the salt will be corrupted.  We
+		 * need to ensure that the output string doesn't have an extra
+		 * NUL in it!
+		 */
+		output[1] = setting[1] ? setting[1] : output[0];
+
+		p = output + 2;
+	}
+	setup_salt(salt);
+	/*
+	 * Do it.
+	 */
+	if (do_des(0, 0, &r0, &r1, count))
+		return(NULL);
+	/*
+	 * Now encode the result...
+	 */
+	l = (r0 >> 8);
+	*p++ = ascii64[(l >> 18) & 0x3f];
+	*p++ = ascii64[(l >> 12) & 0x3f];
+	*p++ = ascii64[(l >> 6) & 0x3f];
+	*p++ = ascii64[l & 0x3f];
+
+	l = (r0 << 16) | ((r1 >> 16) & 0xffff);
+	*p++ = ascii64[(l >> 18) & 0x3f];
+	*p++ = ascii64[(l >> 12) & 0x3f];
+	*p++ = ascii64[(l >> 6) & 0x3f];
+	*p++ = ascii64[l & 0x3f];
+
+	l = r1 << 2;
+	*p++ = ascii64[(l >> 12) & 0x3f];
+	*p++ = ascii64[(l >> 6) & 0x3f];
+	*p++ = ascii64[l & 0x3f];
+	*p = 0;
+
+	return((char *)output);
+}