changeset 12:9535a08ddc39

Import Rogue 5.2 from the Roguelike Restoration Project (r1490)
author edwarj4
date Sat, 24 Oct 2009 16:52:52 +0000
parents 949d558c2162
children 63b9fd7d70ce
files rogue4/LICENSE.TXT rogue4/Makefile rogue4/armor.c rogue4/chase.c rogue4/command.c rogue4/daemon.c rogue4/daemons.c rogue4/extern.c rogue4/extern.h rogue4/fight.c rogue4/findpw.c rogue4/init.c rogue4/io.c rogue4/list.c rogue4/mach_dep.c rogue4/main.c rogue4/mdport.c rogue4/misc.c rogue4/monsters.c rogue4/move.c rogue4/new_level.c rogue4/options.c rogue4/pack.c rogue4/passages.c rogue4/potions.c rogue4/prob.c rogue4/rings.c rogue4/rip.c rogue4/rogue.6 rogue4/rogue.h rogue4/rogue.me rogue4/rogue52.sln rogue4/rogue52.vcproj rogue4/rooms.c rogue4/save.c rogue4/scrolls.c rogue4/state.c rogue4/sticks.c rogue4/things.c rogue4/vers.c rogue4/weapons.c rogue4/wizard.c rogue4/xcrypt.c rogue4/xstr.c
diffstat 44 files changed, 16770 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rogue4/LICENSE.TXT	Sat Oct 24 16:52:52 2009 +0000
@@ -0,0 +1,92 @@
+Rogue: Exploring the Dungeons of Doom
+Copyright (C) 1980, 1981, 1982 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) 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.
+
+===========================================================================
+
+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/rogue4/Makefile	Sat Oct 24 16:52:52 2009 +0000
@@ -0,0 +1,147 @@
+#
+# Makefile for rogue
+# @(#)Makefile	4.13 (Berkeley) 1/23/82
+#
+# Rogue: Exploring the Dungeons of Doom
+# Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman
+# All rights reserved.
+#
+# See the file LICENSE.TXT for full copyright and licensing information.
+#
+
+DISTNAME=rogue5.2.2
+
+HDRS=	rogue.h extern.h
+DOBJS=	vers.o extern.o armor.o chase.o command.o daemon.o daemons.o \
+	fight.o init.o io.o list.o main.o misc.o monsters.o move.o \
+	new_level.o options.o pack.o passages.o potions.o rings.o rip.o \
+	rooms.o save.o scrolls.o state.o sticks.o things.o weapons.o wizard.o\
+        xcrypt.o mdport.o
+OBJS=	$(DOBJS) mach_dep.o
+CFILES=	vers.c extern.c armor.c chase.c command.c daemon.c daemons.c \
+	fight.c init.c io.c list.c main.c misc.c monsters.c move.c \
+	new_level.c options.c pack.c passages.c potions.c rings.c rip.c \
+	rooms.c save.c scrolls.c state.c sticks.c things.c weapons.c wizard.c \
+	mach_dep.c xcrypt.c mdport.c
+MISC=	Makefile LICENSE.TXT rogue.6 rogue.me
+
+CC    = gcc
+CFLAGS= -O3
+CRLIB = -lcurses
+RM    = rm -f
+TAR   = tar
+
+SCOREFILE=
+SF=-DSCOREFILE=\"rogue52.scr\" -DLOCKFILE=\"rogue52.lck\"
+NAMELIST=
+NL=
+#MACHDEP=	-DMAXLOAD=40 -DLOADAV -DCHECKTIME=4
+MACHDEP=
+
+.c.o:
+	@echo $(CC) -c $(CFLAGS) $*.c
+	@$(CC) -c $(CFLAGS) $*.c -o $*.o
+#	@cpp -P $(CFLAGS) $*.c | ./xstr -v -c -
+#	@cc -c $(CFLAGS) x.c
+#	@mv x.o $*.o
+
+rogue: $(HDRS) $(OBJS) # xs.o
+#	@rm -f x.c
+#	$(CC) $(LDFLAGS) xs.o $(OBJS) $(CRLIB) 
+	$(CC) $(LDFLAGS) $(OBJS) $(CRLIB) -o $@
+
+vers.o:
+	$(CC) -c $(CFLAGS) vers.c
+
+mach_dep.o: mach_dep.c
+	$(CC) -c $(CFLAGS) $(SF) $(NL) $(MACHDEP) mach_dep.c
+
+xs.o: strings
+	./xstr
+	$(CC) -c $(CFLAGS) xs.c
+
+xstr: xstr.c
+	$(CC) -s -O -o xstr xstr.c
+
+findpw: findpw.c xcrypt.c
+	$(CC) -s -o findpw findpw.c xcrypt.c
+
+prob: prob.o extern.o xs.o
+	$(CC) -O -o prob prob.o extern.o xs.o
+
+prob.o: prob.c rogue.h
+	$(CC) -O -c prob.c
+
+clean:
+	rm -f $(POBJS) $(OBJS) core a.out p.out rogue strings make.out rogue.tar vgrind.* x.c x.o xs.c xs.o linterrs findpw distmod.o xs.po xstr rogue rogue.exe rogue.tar.gz rogue.cat rogue.doc xstr.exe
+
+dist.src:
+	make clean
+	tar cf $(DISTNAME)-src.tar $(CFILES) $(HDRS) $(MISC)
+	gzip -f $(DISTNAME)-src.tar
+
+debug.irix:
+	make clean
+	make CC=cc CFLAGS="-woff 1116 -g -DWIZARD" rogue
+dist.irix:
+	make clean
+	make CC=cc CFLAGS="-woff 1116 -O3" rogue
+	tbl rogue.me | nroff -me | colcrt - > rogue.doc
+	nroff -man rogue.6 | colcrt - > rogue.cat
+	tar cf $(DISTNAME)-irix.tar rogue LICENSE.TXT rogue.cat rogue.doc
+	gzip -f $(DISTNAME)-irix.tar
+
+debug.aix:
+	make clean
+	make CC=xlc CFLAGS="-qmaxmem=16768 -g -qstrict -DWIZARD" rogue
+dist.aix:
+	make clean
+	make CC=xlc CFLAGS="-qmaxmem=16768 -O3 -qstrict" rogue
+	tbl rogue.me | nroff -me | colcrt - > rogue.doc
+	nroff -man rogue.6 | colcrt - > rogue.cat
+	tar cf $(DISTNAME)-aix.tar rogue LICENSE.TXT rogue.cat rogue.doc
+	gzip -f $(DISTNAME)-aix.tar
+
+debug.linux:
+	make clean
+	make CFLAGS="-g3 -DWIZARD" rogue
+dist.linux:
+	make clean
+	make rogue
+	groff -P-c -t -me -Tascii rogue.me | sed -e 's/.\x08//g' > rogue.doc
+	groff -man rogue.6 | sed -e 's/.\x08//g' > rogue.cat
+	tar cf $(DISTNAME)-linux.tar rogue LICENSE.TXT rogue.cat rogue.doc
+	gzip -f $(DISTNAME)-linux.tar
+	
+debug.interix:
+	make clean
+	make CFLAGS="-g3 -DWIZARD" rogue
+dist.interix: 
+	make clean
+	make rogue
+	groff -P-b -P-u -t -me -Tascii rogue.me > rogue.doc
+	groff -P-b -P-u -man -Tascii rogue.6 > rogue.cat
+	tar cf $(DISTNAME)-interix.tar rogue LICENSE.TXT rogue.cat rogue.doc
+	gzip -f $(DISTNAME)-interix.tar
+	
+debug.cygwin:
+	make clean
+	make CFLAGS="-g3 -DWIZARD" rogue
+dist.cygwin:
+	make clean
+	make rogue
+	groff -P-c -t -me -Tascii rogue.me | sed -e 's/.\x08//g' > rogue.doc
+	groff -P-c -man -Tascii rogue.6 | sed -e 's/.\x08//g' > rogue.cat
+	tar cf $(DISTNAME)-cygwin.tar rogue.exe LICENSE.TXT rogue.cat rogue.doc
+	gzip -f $(DISTNAME)-cygwin.tar
+	
+debug.djgpp:
+	make clean
+	make CFLAGS="-g3 -DWIZARD" LDFLAGS="-L$(DJDIR)/LIB" CRLIB="-lpdcurses" rogue
+dist.djgpp: 
+	make clean
+	make CFLAGS="-O3" LDFLAGS="-L$(DJDIR)/LIB" CRLIB="-lpdcurses" rogue
+	groff -t -me -Tascii rogue.me | sed -e 's/.\x08//g' > rogue.doc
+	groff -man -Tascii rogue.6 | sed -e 's/.\x08//g' > rogue.cat
+	rm -f $(DISTNAME)-djgpp.zip
+	zip $(DISTNAME)-djgpp.zip rogue.exe LICENSE.TXT rogue.cat rogue.doc
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rogue4/armor.c	Sat Oct 24 16:52:52 2009 +0000
@@ -0,0 +1,86 @@
+/*
+ * This file contains misc functions for dealing with armor
+ * @(#)armor.c	4.8 (Berkeley) 4/6/82
+ *
+ * Rogue: Exploring the Dungeons of Doom
+ * Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman
+ * All rights reserved.
+ *
+ * See the file LICENSE.TXT for full copyright and licensing information.
+ */
+
+#include <curses.h>
+#include "rogue.h"
+
+/*
+ * wear:
+ *	The player wants to wear something, so let him/her put it on.
+ */
+wear()
+{
+    register THING *obj;
+    register char *sp;
+
+    if (cur_armor != NULL)
+    {
+	addmsg("you are already wearing some");
+	if (!terse)
+	    addmsg(".  You'll have to take it off first");
+	endmsg();
+	after = FALSE;
+	return;
+    }
+    if ((obj = get_item("wear", ARMOR)) == NULL)
+	return;
+    if (obj->o_type != ARMOR)
+    {
+	msg("you can't wear that");
+	return;
+    }
+    waste_time();
+    obj->o_flags |= ISKNOW;
+    sp = inv_name(obj, TRUE);
+    cur_armor = obj;
+    if (!terse)
+	addmsg("you are now ");
+    msg("wearing %s", sp);
+}
+
+/*
+ * take_off:
+ *	Get the armor off of the players back
+ */
+take_off()
+{
+    register THING *obj;
+
+    if ((obj = cur_armor) == NULL)
+    {
+	after = FALSE;
+	if (terse)
+		msg("not wearing armor");
+	else
+		msg("you aren't wearing any armor");
+	return;
+    }
+    if (!dropcheck(cur_armor))
+	return;
+    cur_armor = NULL;
+    if (terse)
+	addmsg("was");
+    else
+	addmsg("you used to be ");
+    msg(" wearing %c) %s", pack_char(obj), inv_name(obj, TRUE));
+}
+
+/*
+ * waste_time:
+ *	Do nothing but let other things happen
+ */
+waste_time()
+{
+    do_daemons(BEFORE);
+    do_fuses(BEFORE);
+    do_daemons(AFTER);
+    do_fuses(AFTER);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rogue4/chase.c	Sat Oct 24 16:52:52 2009 +0000
@@ -0,0 +1,424 @@
+/*
+ * Code for one creature to chase another
+ *
+ * @(#)chase.c	4.25 (Berkeley) 5/5/82
+ *
+ * Rogue: Exploring the Dungeons of Doom
+ * Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman
+ * All rights reserved.
+ *
+ * See the file LICENSE.TXT for full copyright and licensing information.
+ */
+
+#include <curses.h>
+#include "rogue.h"
+
+#define DRAGONSHOT  5	/* one chance in DRAGONSHOT that a dragon will flame */
+
+coord ch_ret;				/* Where chasing takes you */
+
+/*
+ * runners:
+ *	Make all the running monsters move.
+ */
+runners()
+{
+    register THING *tp;
+	register THING *ntp;
+
+    for (tp = mlist; tp != NULL; tp = ntp)
+    {
+	ntp = next(tp);
+	if (!on(*tp, ISHELD) && on(*tp, ISRUN))
+	{
+	    if (!on(*tp, ISSLOW) || tp->t_turn)
+		if (do_chase(tp) == -1)
+			continue;
+	    if (on(*tp, ISHASTE))
+		if (do_chase(tp) == -1)
+			continue;
+	    tp->t_turn ^= TRUE;
+	}
+    }
+}
+
+/*
+ * do_chase:
+ *	Make one thing chase another.
+ */
+do_chase(th)
+register THING *th;
+{
+    register struct room *rer, *ree;	/* room of chaser, room of chasee */
+    register int mindist = 32767, i, dist;
+    register bool stoprun = FALSE;	/* TRUE means we are there */
+    register char sch;
+    register bool door;
+    register THING *obj;
+    register struct room *oroom;
+    coord this;				/* Temporary destination for chaser */
+
+    rer = th->t_room;		/* Find room of chaser */
+    if (on(*th, ISGREED) && rer->r_goldval == 0)
+	th->t_dest = &hero;	/* If gold has been taken, run after hero */
+    if (th->t_dest == &hero)	/* Find room of chasee */
+	ree = proom;
+    else
+	ree = roomin(th->t_dest);
+    /*
+     * We don't count doors as inside rooms for this routine
+     */
+    door = (chat(th->t_pos.y, th->t_pos.x) == DOOR);
+    /*
+     * If the object of our desire is in a different room,
+     * and we are not in a corridor, run to the door nearest to
+     * our goal.
+     */
+over:
+    if (rer != ree)
+    {
+	for (i = 0; i < rer->r_nexits; i++)	/* loop through doors */
+	{
+	    dist = DISTANCE(th->t_dest->y, th->t_dest->x,
+			    rer->r_exit[i].y, rer->r_exit[i].x);
+	    if (dist < mindist)
+	    {
+		this = rer->r_exit[i];
+		mindist = dist;
+	    }
+	}
+	if (door)
+	{
+	    rer = &passages[flat(th->t_pos.y, th->t_pos.x) & F_PNUM];
+	    door = FALSE;
+	    goto over;
+	}
+    }
+    else
+    {
+	this = *th->t_dest;
+	/*
+	 * For dragons check and see if (a) the hero is on a straight
+	 * line from it, and (b) that it is within shooting distance,
+	 * but outside of striking range.
+	 */
+	if (th->t_type == 'D' && (th->t_pos.y == hero.y || th->t_pos.x == hero.x
+	    || abs(th->t_pos.y - hero.y) == abs(th->t_pos.x - hero.x))
+	    && DISTANCE(th->t_pos.y, th->t_pos.x, hero.y, hero.x) <= BOLT_LENGTH * BOLT_LENGTH
+	    && !on(*th, ISCANC) && rnd(DRAGONSHOT) == 0)
+	{
+	    delta.y = sign(hero.y - th->t_pos.y);
+	    delta.x = sign(hero.x - th->t_pos.x);
+	    fire_bolt(&th->t_pos, &delta, "flame");
+	    running = FALSE;
+	    count = quiet = 0;
+	    return 0;
+	}
+    }
+    /*
+     * 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))
+    {
+	if (ce(this, hero))
+	{
+	    return ( attack(th) );
+	}
+	else if (ce(this, *th->t_dest))
+	{
+	    for (obj = lvl_obj; obj != NULL; obj = next(obj))
+		if (th->t_dest == &obj->o_pos)
+		{
+		    detach(lvl_obj, obj);
+		    attach(th->t_pack, obj);
+		    chat(obj->o_pos.y, obj->o_pos.x) =
+			(th->t_room->r_flags & ISGONE) ? PASSAGE : FLOOR;
+		    th->t_dest = find_dest(th);
+		    break;
+		}
+	    if (th->t_type != 'F')
+		stoprun = TRUE;
+	}
+    }
+    else if (th->t_type == 'F')
+	return(0);
+    mvaddch(th->t_pos.y, th->t_pos.x, th->t_oldch);
+    if (!ce(ch_ret, th->t_pos))
+    {
+	sch = mvinch(ch_ret.y, ch_ret.x);
+	if (sch == FLOOR && (th->t_room->r_flags & ISDARK)
+	    && DISTANCE(th->t_pos.y, th->t_pos.x, hero.y, hero.x)
+	    && !on(player, ISBLIND))
+		th->t_oldch = ' ';
+	else
+	    th->t_oldch = sch;
+	oroom = th->t_room;
+	th->t_room = roomin(&ch_ret);
+	if (oroom != th->t_room)
+	    th->t_dest = find_dest(th);
+
+	moat(th->t_pos.y, th->t_pos.x) = NULL;
+	moat(ch_ret.y, ch_ret.x) = th;
+	th->t_pos = ch_ret;
+    }
+    if (see_monst(th))
+	mvaddch(ch_ret.y, ch_ret.x, th->t_disguise);
+    else if (on(player, SEEMONST))
+    {
+	standout();
+	mvaddch(ch_ret.y, ch_ret.x, th->t_type);
+	standend();
+    }
+    /*
+     * And stop running if need be
+     */
+    if (stoprun && ce(th->t_pos, *(th->t_dest)))
+	th->t_flags &= ~ISRUN;
+    
+    return(0);
+}
+
+/*
+ * see_monst:
+ *	Return TRUE if the hero can see the monster
+ */
+see_monst(mp)
+register THING *mp;
+{
+    if (on(player, ISBLIND))
+	return FALSE;
+    if (on(*mp, ISINVIS) && !on(player, CANSEE))
+	return FALSE;
+    if (DISTANCE(mp->t_pos.y, mp->t_pos.x, hero.y, hero.x) < LAMPDIST)
+	return TRUE;
+    if (mp->t_room != proom)
+	return FALSE;
+    return (!(mp->t_room->r_flags & ISDARK));
+}
+
+/*
+ * runto:
+ *	Set a mosnter running after something or stop it from running
+ *	(for when it dies)
+ */
+runto(runner, spot)
+register coord *runner;
+coord *spot;
+{
+    register THING *tp;
+
+    /*
+     * If we couldn't find him, something is funny
+     */
+#ifdef WIZARD
+    if ((tp = moat(runner->y, runner->x)) == NULL)
+	msg("couldn't find monster in runto at (%d,%d)", runner->y, runner->x);
+#else
+    tp = moat(runner->y, runner->x);
+#endif
+    /*
+     * Start the beastie running
+     */
+    if (tp == NULL)
+        return;
+    tp->t_flags |= ISRUN;
+    tp->t_flags &= ~ISHELD;
+    tp->t_dest = find_dest(tp);
+}
+
+/*
+ * chase:
+ *	Find the spot for the chaser(er) to move closer to the
+ *	chasee(ee).  Returns TRUE if we want to keep on chasing later
+ *	FALSE if we reach the goal.
+ */
+chase(tp, ee)
+THING *tp;
+coord *ee;
+{
+    register int x, y;
+    register int dist, thisdist;
+    register THING *obj;
+    register coord *er = &tp->t_pos;
+    register char ch;
+    register int plcnt = 1;
+
+    /*
+     * If the thing is confused, let it move randomly. Invisible
+     * Stalkers are slightly confused all of the time, and bats are
+     * quite confused all the time
+     */
+    if ((on(*tp, ISHUH) && rnd(5) != 0) || (tp->t_type == 'I' && rnd(5) == 0)
+	|| (tp->t_type == 'B' && rnd(2) == 0))
+    {
+	/*
+	 * get a valid random move
+	 */
+	ch_ret = *rndmove(tp);
+	dist = DISTANCE(ch_ret.y, ch_ret.x, ee->y, ee->x);
+	/*
+	 * Small chance that it will become un-confused 
+	 */
+	if (rnd(20) == 0)
+	    tp->t_flags &= ~ISHUH;
+    }
+    /*
+     * Otherwise, find the empty spot next to the chaser that is
+     * closest to the chasee.
+     */
+    else
+    {
+	register int ey, ex;
+	/*
+	 * This will eventually hold where we move to get closer
+	 * If we can't find an empty spot, we stay where we are.
+	 */
+	dist = DISTANCE(er->y, er->x, ee->y, ee->x);
+	ch_ret = *er;
+
+	ey = er->y + 1;
+	ex = er->x + 1;
+	for (x = er->x - 1; x <= ex; x++)
+	    for (y = er->y - 1; y <= ey; y++)
+	    {
+		coord tryp;
+
+		tryp.x = x;
+		tryp.y = y;
+		if (!diag_ok(er, &tryp))
+		    continue;
+		ch = winat(y, x);
+		if (step_ok(ch))
+		{
+		    /*
+		     * If it is a scroll, it might be a scare monster scroll
+		     * so we need to look it up to see what type it is.
+		     */
+		    if (ch == SCROLL)
+		    {
+			for (obj = lvl_obj; obj != NULL; obj = next(obj))
+			{
+			    if (y == obj->o_pos.y && x == obj->o_pos.x)
+				break;
+			}
+			if (obj != NULL && obj->o_which == S_SCARE)
+			    continue;
+		    }
+		    /*
+		     * It can also be a Mimic, which we shouldn't step on
+		     */
+		    if ((obj = moat(y, x)) != NULL && obj->t_type == 'M')
+		        continue;
+		    /*
+		     * If we didn't find any scrolls at this place or it
+		     * wasn't a scare scroll, then this place counts
+		     */
+		    thisdist = DISTANCE(y, x, ee->y, ee->x);
+		    if (thisdist < dist)
+		    {
+			plcnt = 1;
+			ch_ret = tryp;
+			dist = thisdist;
+		    }
+		    else if (thisdist == dist && rnd(++plcnt) == 0)
+		    {
+			ch_ret = tryp;
+			dist = thisdist;
+		    }
+		}
+	    }
+    }
+    return (dist != 0 && !ce(ch_ret, hero));
+}
+
+/*
+ * roomin:
+ *	Find what room some coordinates are in. NULL means they aren't
+ *	in any room.
+ */
+struct room *
+roomin(cp)
+register coord *cp;
+{
+    register struct room *rp;
+    register char *fp;
+
+    for (rp = rooms; rp < &rooms[MAXROOMS]; rp++)
+	if (cp->x < rp->r_pos.x + rp->r_max.x && rp->r_pos.x <= cp->x
+	 && cp->y < rp->r_pos.y + rp->r_max.y && rp->r_pos.y <= cp->y)
+	    return rp;
+    fp = &flat(cp->y, cp->x);
+    if (*fp & F_PASS)
+	return &passages[*fp & F_PNUM];
+    msg("in some bizarre place (%d, %d)", unc(*cp));
+    return NULL;
+}
+
+/*
+ * diag_ok:
+ *	Check to see if the move is legal if it is diagonal
+ */
+diag_ok(sp, ep)
+register coord *sp, *ep;
+{
+    if (ep->x == sp->x || ep->y == sp->y)
+	return TRUE;
+    return (step_ok(chat(ep->y, sp->x)) && step_ok(chat(sp->y, ep->x)));
+}
+
+/*
+ * cansee:
+ *	Returns true if the hero can see a certain coordinate.
+ */
+cansee(y, x)
+register int y, x;
+{
+    register struct room *rer;
+    coord tp;
+
+    if (on(player, ISBLIND))
+	return FALSE;
+    if (DISTANCE(y, x, hero.y, hero.x) < LAMPDIST)
+	return TRUE;
+    /*
+     * We can only see if the hero in the same room as
+     * the coordinate and the room is lit or if it is close.
+     */
+    tp.y = y;
+    tp.x = x;
+    return ((rer = roomin(&tp)) == proom && !(rer->r_flags & ISDARK));
+}
+
+/*
+ * find_dest:
+ *	find the proper destination for the monster
+ */
+coord *
+find_dest(tp)
+register THING *tp;
+{
+    register THING *obj;
+    register int prob;
+    register struct room *rp;
+
+    if ((prob = monsters[tp->t_type - 'A'].m_carry) <= 0 || tp->t_room == proom
+	|| see_monst(tp))
+	    return &hero;
+    rp = tp->t_room;
+    for (obj = lvl_obj; obj != NULL; obj = next(obj))
+    {
+	if (obj->o_type == SCROLL && obj->o_which == S_SCARE)
+	    continue;
+	if (roomin(&obj->o_pos) == rp && rnd(100) < prob)
+	{
+	    for (tp = mlist; tp != NULL; tp = next(tp))
+		if (tp->t_dest == &obj->o_pos)
+		    break;
+	    if (tp == NULL)
+		return &obj->o_pos;
+	}
+    }
+    return &hero;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rogue4/command.c	Sat Oct 24 16:52:52 2009 +0000
@@ -0,0 +1,600 @@
+/*
+ * Read and execute the user commands
+ *
+ * @(#)command.c	4.31 (Berkeley) 4/6/82
+ *
+ * Rogue: Exploring the Dungeons of Doom
+ * Copyright (C) 1980, 1981, 1982 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 <curses.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+#include "rogue.h"
+
+char countch, direction, newcount = FALSE;
+
+/*
+ * command:
+ *	Process the user commands
+ */
+command()
+{
+    register char ch;
+    register int ntimes = 1;			/* Number of player moves */
+    char *unctrol();
+
+    if (on(player, ISHASTE))
+	ntimes++;
+    /*
+     * Let the daemons start up
+     */
+    do_daemons(BEFORE);
+    do_fuses(BEFORE);
+    while (ntimes--)
+    {
+	/*
+	 * these are illegal things for the player to be, so if any are
+	 * set, someone's been poking in memeory
+	 */
+	if (on(player, ISSLOW|ISCANC|ISGREED|ISINVIS|ISMEAN|ISREGEN))
+	    auto_save(-1);
+
+	look(TRUE);
+	if (!running)
+	    door_stop = FALSE;
+	status();
+	lastscore = purse;
+	move(hero.y, hero.x);
+	if (!((running || count) && jump))
+	    refresh();			/* Draw screen */
+	take = 0;
+	after = TRUE;
+	/*
+	 * Read command or continue run
+	 */
+#ifdef WIZARD
+	if (wizard)
+	    noscore = TRUE;
+#endif
+	if (!no_command)
+	{
+	    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 (no_command)
+	{
+	    if (--no_command == 0)
+	    {
+		player.t_flags |= ISRUN;
+		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':
+#ifdef WIZARD
+		    case CTRL('D'): case CTRL('U'):
+#endif
+			break;
+		    default:
+			count = 0;
+		}
+	    }
+	    switch (ch)
+	    {
+		case 'f':
+		    if (!on(player, 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();
+		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();
+		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(); after = FALSE;
+		when 'c' : call(); after = FALSE;
+		when '>' : after = FALSE; d_level();
+		when '<' : after = FALSE; u_level();
+		when '?' : after = FALSE; help();
+		when '/' : after = FALSE; identify();
+		when 's' : search();
+		when 'z':
+		    if (get_dir())
+			do_zap();
+		    else
+			after = FALSE;
+		when 'D': after = FALSE; discovered();
+		when CTRL('R') : after = FALSE; msg(huh);
+		when CTRL('L') :
+		    after = FALSE;
+		    clearok(curscr,TRUE);
+		    wrefresh(curscr);
+		when 'v' :
+		    after = FALSE;
+		    msg("rogue version %s. (mctesq was here)", release);
+		when 'S' : 
+		    after = FALSE;
+		    if (save_game())
+		    {
+			move(LINES-1, 0); 
+			clrtoeol();
+			refresh();
+			endwin();
+			exit(0);
+		    }
+		when '.' : ;			/* Rest command */
+		when ' ' : after = FALSE;	/* "Legal" illegal command */
+		when '^' :
+		    after = FALSE;
+		    if (get_dir()) {
+			delta.y += hero.y;
+			delta.x += hero.x;
+			if (chat(delta.y, delta.x) != TRAP)
+			    msg("no trap there");
+			else
+			    msg(tr_name(flat(delta.y, delta.x) & F_TMASK));
+		    }
+#ifdef WIZARD
+		when CTRL('P') :
+		    after = FALSE;
+		    if (wizard)
+		    {
+			wizard = FALSE;
+			turn_see(TRUE);
+			msg("not wizard any more");
+		    }
+		    else
+		    {
+			if (wizard = passwd())
+			{
+			    noscore = TRUE;
+			    turn_see(FALSE);
+			    msg("you are suddenly as smart as Ken Arnold in dungeon #%d", dnum);
+			}
+			else
+			    msg("sorry");
+		    }
+#endif
+		when ESCAPE :	/* Escape */
+		    door_stop = FALSE;
+		    count = 0;
+		    after = FALSE;
+		otherwise :
+		    after = FALSE;
+#ifdef WIZARD
+		    if (wizard) switch (ch)
+		    {
+			case '@' : msg("@ %d,%d", hero.y, hero.x);
+			when 'C' : create_obj();
+			when CTRL('I') : inventory(lvl_obj, 0);
+			when CTRL('W') : whatis(FALSE);
+			when CTRL('D') : level++; new_level();
+			when CTRL('U') : if (level > 1) level--; new_level();
+			when CTRL('F') : show_map();
+			when CTRL('T') : teleport();
+			when CTRL('E') : msg("food left: %d", food_left);
+			when CTRL('A') : msg("%d things in your pack", inpack);
+			when CTRL('K') : add_pass();
+			when CTRL('X') : turn_see(on(player, SEEMONST));
+			when CTRL('N') :
+			{
+			    register THING *item;
+
+			    if ((item = get_item("charge", STICK)) != NULL)
+				item->o_charges = 10000;
+			}
+			when CTRL('H') :
+			{
+			    register int i;
+			    register THING *obj;
+
+			    for (i = 0; i < 9; i++)
+				raise_level();
+			    /*
+			     * Give the rogue a sword (+1,+1)
+			     */
+			    obj = new_item();
+			    obj->o_type = WEAPON;
+			    obj->o_which = TWOSWORD;
+			    init_weapon(obj, SWORD);
+			    obj->o_hplus = 1;
+			    obj->o_dplus = 1;
+			    obj->o_count = 1;
+			    obj->o_group = 0;
+			    add_pack(obj, TRUE);
+			    cur_weapon = obj;
+			    /*
+			     * And his suit of armor
+			     */
+			    obj = new_item();
+			    obj->o_type = ARMOR;
+			    obj->o_which = PLATE_MAIL;
+			    obj->o_ac = -5;
+			    obj->o_flags |= ISKNOW;
+			    obj->o_count = 1;
+			    obj->o_group = 0;
+			    cur_armor = obj;
+			    add_pack(obj, TRUE);
+			}
+			otherwise :
+			    illcom(ch);
+		    }
+		    else
+#endif
+			illcom(ch);
+	    }
+	    /*
+	     * turn off flags if no longer needed
+	     */
+	    if (!running)
+		door_stop = FALSE;
+	}
+	/*
+	 * If he ran into something to take, let him pick it up.
+	 */
+	if (take != 0)
+	    pick_up(take);
+	if (!running)
+	    door_stop = FALSE;
+	if (!after)
+	    ntimes++;
+    }
+    do_daemons(AFTER);
+    do_fuses(AFTER);
+    if (ISRING(LEFT, R_SEARCH))
+	search();
+    else if (ISRING(LEFT, R_TELEPORT) && rnd(50) == 0)
+	teleport();
+    if (ISRING(RIGHT, R_SEARCH))
+	search();
+    else if (ISRING(RIGHT, R_TELEPORT) && rnd(50) == 0)
+	teleport();
+}
+
+/*
+ * illcom:
+ *	What to do with an illegal command
+ */
+illcom(ch)
+char ch;
+{
+    save_msg = FALSE;
+    count = 0;
+    msg("illegal command '%s'", unctrol(ch));
+    save_msg = TRUE;
+}
+
+/*
+ * search:
+ *	Player gropes about him to find hidden things.
+ */
+search()
+{
+    register int y, x;
+    register char *fp;
+    register int ey, ex;
+
+    if (on(player, ISBLIND))
+	return;
+    ey = hero.y + 1;
+    ex = hero.x + 1;
+    for (y = hero.y - 1; y <= ey; y++) 
+	for (x = hero.x - 1; x <= ex; x++)
+	{
+	    if (y == hero.y && x == hero.x)
+		continue;
+	    fp = &flat(y, x);
+	    if (!(*fp & F_REAL))
+		switch (chat(y, x))
+		{
+		    case '|':
+		    case '-':
+			if (rnd(5) != 0)
+			    break;
+			chat(y, x) = DOOR;
+			*fp |= F_REAL;
+			count = running = FALSE;
+			break;
+		    case FLOOR:
+			if (rnd(2) != 0)
+			    break;
+			chat(y, x) = TRAP;
+			*fp |= F_REAL;
+			count = running = FALSE;
+			msg("%s%s", terse ? "" : "you found ", tr_name(*fp & F_TMASK));
+			break;
+		}
+	}
+}
+
+/*
+ * help:
+ *	Give single character help, or the whole mess if he wants it
+ */
+help()
+{
+    register const struct h_list *strp = helpstr;
+    register char helpch;
+    register int cnt;
+
+    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 != '*')
+    {
+	move(0, 0);
+	while (strp->h_ch)
+	{
+	    if (strp->h_ch == helpch)
+	    {
+		msg("%s%s", unctrol(strp->h_ch), strp->h_desc);
+		break;
+	    }
+	    strp++;
+	}
+	if (strp->h_ch != helpch)
+	    msg("unknown character '%s'", unctrol(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, unctrol(strp->h_ch));
+	waddstr(hw, strp->h_desc);
+	cnt++;
+	strp++;
+    }
+    wmove(hw, LINES-1, 0);
+    wprintw(hw, "--Press space to continue--");
+    wrefresh(hw);
+    w_wait_for(hw,' ');
+    wmove(stdscr, 0, 0);
+    wclrtoeol(stdscr);
+    touchwin(stdscr);
+    clearok(stdscr, TRUE);
+    refresh();
+}
+
+/*
+ * identify:
+ *	Tell the player what a certain thing is.
+ */
+identify()
+{
+    register char ch;
+    register const char *str;
+
+    msg("what do you want identified? ");
+    ch = readchar();
+    mpos = 0;
+    if (ch == ESCAPE)
+    {
+	msg("");
+	return;
+    }
+    if (isupper(ch))
+	str = monsters[ch-'A'].m_name;
+    else switch (ch)
+    {
+	case '|':
+	case '-':
+	    str = "wall of a room";
+	when GOLD: str = "gold";
+	when STAIRS : str = "a staircase";
+	when DOOR: str = "door";
+	when FLOOR: str = "room floor";
+	when PLAYER: str = "you";
+	when PASSAGE: str = "passage";
+	when TRAP: str = "trap";
+	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: str = "unknown character";
+    }
+    msg("'%s': %s", unctrol(ch), str);
+}
+
+/*
+ * d_level:
+ *	He wants to go down a level
+ */
+d_level()
+{
+    if (chat(hero.y, hero.x) != STAIRS)
+	msg("I see no way down");
+    else
+    {
+	level++;
+	new_level();
+    }
+}
+
+/*
+ * u_level:
+ *	He wants to go up a level
+ */
+u_level()
+{
+    if (chat(hero.y, hero.x) == STAIRS)
+	if (amulet)
+	{
+	    level--;
+	    if (level == 0)
+		total_winner();
+	    new_level();
+	    msg("you feel a wrenching sensation in your gut");
+	}
+	else
+	    msg("your way is magically blocked");
+    else
+	msg("I see no way up");
+}
+
+/*
+ * call:
+ *	Allow a user to call a potion, scroll, or ring something
+ */
+call()
+{
+    register THING *obj;
+    register char **guess;
+    const char *elsewise;
+    register bool *know;
+
+    obj = get_item("call", CALLABLE);
+    /*
+     * Make certain that it is somethings that we want to wear
+     */
+    if (obj == NULL)
+	return;
+    switch (obj->o_type)
+    {
+	case RING:
+	    guess = r_guess;
+	    know = r_know;
+	    elsewise = (r_guess[obj->o_which] != NULL ?
+			r_guess[obj->o_which] : r_stones[obj->o_which]);
+	when POTION:
+	    guess = p_guess;
+	    know = p_know;
+	    elsewise = (p_guess[obj->o_which] != NULL ?
+			p_guess[obj->o_which] : p_colors[obj->o_which]);
+	when SCROLL:
+	    guess = s_guess;
+	    know = s_know;
+	    elsewise = (s_guess[obj->o_which] != NULL ?
+			s_guess[obj->o_which] : s_names[obj->o_which]);
+	when STICK:
+	    guess = ws_guess;
+	    know = ws_know;
+	    elsewise = (ws_guess[obj->o_which] != NULL ?
+			ws_guess[obj->o_which] : ws_made[obj->o_which]);
+	otherwise:
+	    msg("you can't call that anything");
+	    return;
+    }
+    if (know[obj->o_which])
+    {
+	msg("that has already been identified");
+	return;
+    }
+    if (!terse)
+	addmsg("Was ");
+    msg("called \"%s\"", elsewise);
+    if (terse)
+	msg("call it: ");
+    else
+	msg("what do you want to call it? ");
+    if (guess[obj->o_which] != NULL)
+	free(guess[obj->o_which]);
+    strcpy(prbuf, elsewise);
+    if (get_str(prbuf, stdscr) == NORM)
+    {
+	guess[obj->o_which] = malloc((unsigned int) strlen(prbuf) + 1);
+	strcpy(guess[obj->o_which], prbuf);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rogue4/daemon.c	Sat Oct 24 16:52:52 2009 +0000
@@ -0,0 +1,186 @@
+/*
+ * Contains functions for dealing with things that happen in the
+ * future.
+ *
+ * @(#)daemon.c	4.4 (Berkeley) 1/12/82
+ *
+ * Rogue: Exploring the Dungeons of Doom
+ * Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman
+ * All rights reserved.
+ *
+ * See the file LICENSE.TXT for full copyright and licensing information.
+ */
+
+#include <curses.h>
+#include "rogue.h"
+
+#define EMPTY 0
+#define DAEMON -1
+
+#define _X_ { EMPTY }
+
+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_slot:
+ *	Find an empty slot in the daemon/fuse list
+ */
+struct delayed_action *
+d_slot()
+{
+    register int i;
+    register struct delayed_action *dev;
+
+    for (i = 0, dev = d_list; i < MAXDAEMONS; i++, dev++)
+	if (dev->d_type == EMPTY)
+	    return dev;
+#ifdef WIZARD
+    debug("Ran out of fuse slots");
+#endif
+    return NULL;
+}
+
+/*
+ * find_slot:
+ *	Find a particular slot in the table
+ */
+struct delayed_action *
+find_slot(func)
+register int (*func)();
+{
+    register int i;
+    register struct delayed_action *dev;
+
+    for (i = 0, dev = d_list; i < MAXDAEMONS; i++, 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 (*func)(), arg, type;
+{
+    register struct delayed_action *dev;
+
+    dev = d_slot();
+    dev->d_type = type;
+    dev->d_func = func;
+    dev->d_arg = arg;
+    dev->d_time = DAEMON;
+}
+
+/*
+ * kill_daemon:
+ *	Remove a daemon from the list
+ */
+kill_daemon(func)
+int (*func)();
+{
+    register struct delayed_action *dev;
+
+    if ((dev = find_slot(func)) == NULL)
+	return;
+    /*
+     * Take it out of the list
+     */
+    dev->d_type = EMPTY;
+}
+
+/*
+ * do_daemons:
+ *	Run all the daemons that are active with the current flag,
+ *	passing the argument to the function.
+ */
+do_daemons(flag)
+register int flag;
+{
+    register struct delayed_action *dev;
+
+    /*
+     * Loop through the devil list
+     */
+    for (dev = d_list; dev <= &d_list[MAXDAEMONS-1]; dev++)
+	/*
+	 * Executing each one, giving it the proper arguments
+	 */
+	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, type)
+int (*func)(), arg, time, type;
+{
+    register struct delayed_action *wire;
+
+    wire = d_slot();
+    wire->d_type = type;
+    wire->d_func = func;
+    wire->d_arg = arg;
+    wire->d_time = time;
+}
+
+/*
+ * lengthen:
+ *	Increase the time until a fuse goes off
+ */
+lengthen(func, xtime)
+int (*func)();
+int xtime;
+{
+    register struct delayed_action *wire;
+
+    if ((wire = find_slot(func)) == NULL)
+	return;
+    wire->d_time += xtime;
+}
+
+/*
+ * extinguish:
+ *	Put out a fuse
+ */
+extinguish(func)
+int (*func)();
+{
+    register struct delayed_action *wire;
+
+    if ((wire = find_slot(func)) == NULL)
+	return;
+    wire->d_type = EMPTY;
+}
+
+/*
+ * do_fuses:
+ *	Decrement counters and start needed fuses
+ */
+do_fuses(flag)
+register int flag;
+{
+    register struct delayed_action *wire;
+
+    /*
+     * Step though the list
+     */
+    for (wire = d_list; wire <= &d_list[MAXDAEMONS-1]; wire++)
+    {
+	/*
+	 * Decrementing counters and starting things we want.  We also need
+	 * to remove the fuse from the list once it has gone off.
+	 */
+	if (flag == wire->d_type && wire->d_time > 0 && --wire->d_time == 0)
+	{
+	    wire->d_type = EMPTY;
+	    (*wire->d_func)(wire->d_arg);
+	}
+     }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rogue4/daemons.c	Sat Oct 24 16:52:52 2009 +0000
@@ -0,0 +1,174 @@
+/*
+ * All the daemon and fuse functions are in here
+ *
+ * @(#)daemons.c	4.10 (Berkeley) 4/6/82
+ *
+ * Rogue: Exploring the Dungeons of Doom
+ * Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman
+ * All rights reserved.
+ *
+ * See the file LICENSE.TXT for full copyright and licensing information.
+ */
+
+#include <curses.h>
+#include "rogue.h"
+
+int between = 0;
+
+/*
+ * doctor:
+ *	A healing daemon that restors hit points after rest
+ */
+doctor()
+{
+    register int lv, ohp;
+
+    lv = pstats.s_lvl;
+    ohp = pstats.s_hpt;
+    quiet++;
+    if (lv < 8)
+    {
+	if (quiet + (lv << 1) > 20)
+	    pstats.s_hpt++;
+    }
+    else
+	if (quiet >= 3)
+	    pstats.s_hpt += rnd(lv - 7) + 1;
+    if (ISRING(LEFT, R_REGEN))
+	pstats.s_hpt++;
+    if (ISRING(RIGHT, R_REGEN))
+	pstats.s_hpt++;
+    if (ohp != pstats.s_hpt)
+    {
+	if (pstats.s_hpt > max_hp)
+	    pstats.s_hpt = max_hp;
+	quiet = 0;
+    }
+}
+
+/*
+ * Swander:
+ *	Called when it is time to start rolling for wandering monsters
+ */
+swander()
+{
+    daemon(rollwand, 0, BEFORE);
+}
+
+/*
+ * rollwand:
+ *	Called to roll to see if a wandering monster starts up
+ */
+rollwand()
+{
+    if (++between >= 4)
+    {
+	if (roll(1, 6) == 4)
+	{
+	    wanderer();
+	    kill_daemon(rollwand);
+	    fuse(swander, 0, WANDERTIME, BEFORE);
+	}
+	between = 0;
+    }
+}
+
+/*
+ * unconfuse:
+ *	Release the poor player from his confusion
+ */
+unconfuse()
+{
+    player.t_flags &= ~ISHUH;
+    msg("you feel less confused now");
+}
+
+/*
+ * unsee:
+ *	Turn off the ability to see invisible
+ */
+unsee()
+{
+    register THING *th;
+
+    for (th = mlist; th != NULL; th = next(th))
+	if (on(*th, ISINVIS) && see_monst(th))
+	{
+	    move(th->t_pos.y, th->t_pos.x);
+	    addch(th->t_oldch);
+	}
+    player.t_flags &= ~CANSEE;
+}
+
+/*
+ * sight:
+ *	He gets his sight back
+ */
+sight()
+{
+    if (on(player, ISBLIND))
+    {
+	extinguish(sight);
+	player.t_flags &= ~ISBLIND;
+	if (!(proom->r_flags & ISGONE))
+	    enter_room(&hero);
+	msg("the veil of darkness lifts");
+    }
+}
+
+/*
+ * nohaste:
+ *	End the hasting
+ */
+nohaste()
+{
+    player.t_flags &= ~ISHASTE;
+    msg("you feel yourself slowing down");
+}
+
+/*
+ * stomach:
+ *	Digest the hero's food
+ */
+stomach()
+{
+    register int oldfood;
+
+    if (food_left <= 0)
+    {
+	if (food_left-- < -STARVETIME)
+	    death('s');
+	/*
+	 * the hero is fainting
+	 */
+	if (no_command || rnd(5) != 0)
+	    return;
+	no_command += rnd(8) + 4;
+	player.t_flags &= ~ISRUN;
+	running = FALSE;
+	count = 0;
+	hungry_state = 3;
+	if (!terse)
+	    addmsg("you feel too weak from lack of food.  ");
+	msg("You faint");
+    }
+    else
+    {
+	oldfood = food_left;
+	food_left -= ring_eat(LEFT) + ring_eat(RIGHT) + 1 - amulet;
+
+	if (food_left < MORETIME && oldfood >= MORETIME)
+	{
+	    hungry_state = 2;
+	    msg("you are starting to feel weak");
+	}
+	else if (food_left < 2 * MORETIME && oldfood >= 2 * MORETIME)
+	{
+	    hungry_state = 1;
+	    if (!terse)
+		msg("you are starting to get hungry");
+	    else
+		msg("getting hungry");
+	}
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rogue4/extern.c	Sat Oct 24 16:52:52 2009 +0000
@@ -0,0 +1,325 @@
+/*
+ * global variable initializaton
+ *
+ * @(#)extern.c	4.32 (Berkeley) 4/1/82
+ *
+ * Rogue: Exploring the Dungeons of Doom
+ * Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman
+ * All rights reserved.
+ *
+ * See the file LICENSE.TXT for full copyright and licensing information.
+ */
+
+#include <curses.h>
+#include "rogue.h"
+
+bool after;				/* True if we want after daemons */
+bool noscore;				/* Was a wizard sometime */
+bool s_know[MAXSCROLLS];		/* Does he know what a scroll does */
+bool p_know[MAXPOTIONS];		/* Does he know what a potion does */
+bool r_know[MAXRINGS];			/* Does he know what a ring does */
+bool ws_know[MAXSTICKS];		/* Does he know what a stick does */
+bool amulet = FALSE;			/* He found the amulet */
+bool askme = FALSE;			/* Ask about unidentified things */
+bool door_stop = FALSE;			/* Stop running when we pass a door */
+bool fight_flush = FALSE;		/* True if toilet input */
+bool firstmove = FALSE;			/* First move after setting door_stop */
+bool in_shell = FALSE;			/* True if executing a shell */
+bool jump = FALSE;			/* Show running as series of jumps */
+bool passgo = FALSE;			/* Follow passages */
+bool playing = TRUE;			/* True until he quits */
+bool running = FALSE;			/* True if player is running */
+bool save_msg = TRUE;			/* Remember last msg */
+bool slow_invent = FALSE;		/* Inventory one line at a time */
+bool terse = FALSE;			/* True if we should be short */
+#ifdef WIZARD
+bool wizard = FALSE;			/* True if allows wizard commands */
+#endif
+
+char take;				/* Thing the rogue is taking */
+char prbuf[MAXSTR];			/* Buffer for sprintfs */
+char outbuf[BUFSIZ];			/* Output buffer for stdout */
+char runch;				/* Direction player is running */
+char *s_names[MAXSCROLLS];		/* Names of the scrolls */
+const char *p_colors[MAXPOTIONS];		/* Colors of the potions */
+const char *r_stones[MAXRINGS];		/* Stone settings of the rings */
+const char *w_names[MAXWEAPONS + 1] = {	/* Names of the various weapons */
+    "mace",
+    "long sword",
+    "short bow",
+    "arrow",
+    "dagger",
+    "two handed sword",
+    "dart",
+    "crossbow",
+    "crossbow bolt",
+    "spear",
+    NULL				/* fake entry for dragon's breath */
+};
+const char *a_names[MAXARMORS] = {		/* Names of armor types */
+    "leather armor",
+    "ring mail",
+    "studded leather armor",
+    "scale mail",
+    "chain mail",
+    "splint mail",
+    "banded mail",
+    "plate mail",
+};
+const char *ws_made[MAXSTICKS];		/* What sticks are made of */
+char *release;				/* Release number of rogue */
+char whoami[MAXSTR];			/* Name of player */
+char fruit[MAXSTR];			/* Favorite fruit */
+char huh[MAXSTR];			/* The last message printed */
+char *s_guess[MAXSCROLLS];		/* Players guess at what scroll is */
+char *p_guess[MAXPOTIONS];		/* Players guess at what potion is */
+char *r_guess[MAXRINGS];		/* Players guess at what ring is */
+char *ws_guess[MAXSTICKS];		/* Players guess at what wand is */
+char *ws_type[MAXSTICKS];		/* Is it a wand or a staff */
+char file_name[MAXSTR];			/* Save file name */
+char home[MAXSTR];			/* User's home directory */
+char _level[MAXLINES*MAXCOLS];		/* Level map */
+char _flags[MAXLINES*MAXCOLS];		/* Flags for each space on the map */
+
+int max_level;				/* Deepest player has gone */
+int ntraps;				/* Number of traps on this level */
+int dnum;				/* Dungeon number */
+int level = 1;				/* What level rogue is on */
+int purse = 0;				/* How much gold the rogue has */
+int mpos = 0;				/* Where cursor is on top line */
+int no_move = 0;			/* Number of turns held in place */
+int no_command = 0;			/* Number of turns asleep */
+int inpack = 0;				/* Number of things in pack */
+int total = 0;				/* Total dynamic memory bytes */
+int lastscore = -1;			/* Score before this turn */
+int no_food = 0;			/* Number of levels without food */
+int count = 0;				/* Number of times to repeat command */
+int fung_hit = 0;			/* Number of time fungi has hit */
+int quiet = 0;				/* Number of quiet turns */
+int food_left;				/* Amount of food in hero's stomach */
+int group = 2;				/* Current group number */
+int hungry_state = 0;			/* How hungry is he */
+int fd;					/* File descriptor for score file */
+int a_chances[MAXARMORS] = {		/* Chance for each armor type */
+    20,
+    35,
+    50,
+    63,
+    75,
+    85,
+    95,
+    100
+};
+int a_class[MAXARMORS] = {		/* Armor class for each armor type */
+    8,
+    7,
+    7,
+    6,
+    5,
+    4,
+    4,
+    3,
+};
+
+long seed;				/* Random number seed */
+
+coord oldpos;				/* Position before last look() call */
+coord delta;				/* Change indicated to get_dir() */
+
+THING player;				/* The rogue */
+THING *cur_armor;			/* What a well dresssed rogue wears */
+THING *cur_weapon;			/* Which weapon he is weilding */
+THING *cur_ring[2];			/* Which rings are being worn */
+THING *lvl_obj = NULL;			/* List of objects on this level */
+THING *mlist = NULL;			/* List of monsters on the level */
+THING *_monst[MAXLINES*MAXCOLS];	/* Pointers for monsters at each spot */
+
+WINDOW *hw;				/* Used as a scratch window */
+
+#define INIT_STATS { 16, 0, 1, 10, 12, "1d4", 12 }
+
+struct stats max_stats = INIT_STATS;	/* The maximum for the player */
+
+struct room *oldrp;			/* Roomin(&oldpos) */
+struct room rooms[MAXROOMS];		/* One for each room -- A level */
+struct room passages[MAXPASS] =		/* One for each passage */
+{
+    { {0, 0}, {0, 0}, {0, 0}, 0, ISGONE|ISDARK, 0, 0 },
+    { {0, 0}, {0, 0}, {0, 0}, 0, ISGONE|ISDARK, 0, 0 },
+    { {0, 0}, {0, 0}, {0, 0}, 0, ISGONE|ISDARK, 0, 0 },
+    { {0, 0}, {0, 0}, {0, 0}, 0, ISGONE|ISDARK, 0, 0 },
+    { {0, 0}, {0, 0}, {0, 0}, 0, ISGONE|ISDARK, 0, 0 },
+    { {0, 0}, {0, 0}, {0, 0}, 0, ISGONE|ISDARK, 0, 0 },
+    { {0, 0}, {0, 0}, {0, 0}, 0, ISGONE|ISDARK, 0, 0 },
+    { {0, 0}, {0, 0}, {0, 0}, 0, ISGONE|ISDARK, 0, 0 },
+    { {0, 0}, {0, 0}, {0, 0}, 0, ISGONE|ISDARK, 0, 0 },
+    { {0, 0}, {0, 0}, {0, 0}, 0, ISGONE|ISDARK, 0, 0 },
+    { {0, 0}, {0, 0}, {0, 0}, 0, ISGONE|ISDARK, 0, 0 },
+    { {0, 0}, {0, 0}, {0, 0}, 0, ISGONE|ISDARK, 0, 0 }
+};
+
+#define ___ 1
+#define XX 10
+struct monster monsters[26] =
+{
+	/* Name		 CARRY	FLAG    str, exp, lvl, amr, hpt, dmg */
+	{ "giant ant",	 0,	ISMEAN,	{ XX,  9,   2,   3, ___, "1d6" } },
+	{ "bat",	 0,	0,	{ XX,  1,   1,   3, ___, "1d2" } },
+	{ "centaur",	 15,	0,	{ XX, 15,   4,   4, ___, "1d6/1d6" } },
+	{ "dragon",	 100,	ISMEAN,	{ XX,6800, 10,  -1, ___, "1d8/1d8/3d10" } },
+	{ "floating eye",0,	0,	{ XX,  5,   1,   9, ___, "0d0" } },
+		/* NOTE: the damage is %%% so that xstr won't merge this */
+		/* string with others, since it is written on in the program */
+	{ "violet fungi",0,	ISMEAN,	{ XX, 80,   8,   3, ___, "%%%d0" } },
+	{ "gnome",	 10,	0,	{ XX,  7,   1,   5, ___, "1d6" } },
+	{ "hobgoblin",	 0,	ISMEAN,	{ XX,  3,   1,   5, ___, "1d8" } },
+	{ "invisible stalker",0,ISINVIS,{ XX,120,   8,   3, ___, "4d4" } },
+	{ "jackal",	 0,	ISMEAN,	{ XX,  2,   1,   7, ___, "1d2" } },
+	{ "kobold",	 0,	ISMEAN,	{ XX,  1,   1,   7, ___, "1d4" } },
+	{ "leprechaun",	 0,	0,	{ XX, 10,   3,   8, ___, "1d1" } },
+	{ "mimic",	 30,	0,	{ XX,100,   7,   7, ___, "3d4" } },
+	{ "nymph",	 100,	0,	{ XX, 37,   3,   9, ___, "0d0" } },
+	{ "orc",	 15,	ISGREED,{ XX,  5,   1,   6, ___, "1d8" } },
+	{ "purple worm", 70,	0,	{ XX,4000, 15,   6, ___, "2d12/2d4" } },
+	{ "quasit",	 30,	ISMEAN,	{ XX, 32,   3,   2, ___, "1d2/1d2/1d4" } },
+	{ "rust monster",0,	ISMEAN,	{ XX, 20,   5,   2, ___, "0d0/0d0" } },
+	{ "snake",	 0,	ISMEAN,	{ XX,  2,   1,   5, ___, "1d3" } },
+	{ "troll",	 50,	ISREGEN|ISMEAN,{ XX, 120, 6, 4, ___, "1d8/1d8/2d6" } },
+	{ "umber hulk",	 40,	ISMEAN,	{ XX,200,   8,   2, ___, "3d4/3d4/2d5" } },
+	{ "vampire",	 20,	ISREGEN|ISMEAN,{ XX,350,   8,   1, ___, "1d10" } },
+	{ "wraith",	 0,	0,	{ XX, 55,   5,   4, ___, "1d6" } },
+	{ "xorn",	 0,	ISMEAN,	{ XX,190,   7,  -2, ___, "1d3/1d3/1d3/4d6" } },
+	{ "yeti",	 30,	0,	{ XX, 50,   4,   6, ___, "1d6/1d6" } },
+	{ "zombie",	 0,	ISMEAN,	{ XX,  6,   2,   8, ___, "1d8" } }
+};
+#undef ___
+#undef XX
+
+struct magic_item things[NUMTHINGS] = {
+    { 0,			27 },	/* potion */
+    { 0,			30 },	/* scroll */
+    { 0,			17 },	/* food */
+    { 0,			 8 },	/* weapon */
+    { 0,			 8 },	/* armor */
+    { 0,			 5 },	/* ring */
+    { 0,			 5 },	/* stick */
+};
+
+struct magic_item s_magic[MAXSCROLLS] = {
+    { "monster confusion",	 8, 140 },
+    { "magic mapping",		 5, 150 },
+    { "hold monster",		 3, 180 },
+    { "sleep",			 5,   5 },
+    { "enchant armor",		 8, 160 },
+    { "identify",		27, 100 },
+    { "scare monster",		 4, 200 },
+    { "gold detection",		 4,  50 },
+    { "teleportation",		 7, 165 },
+    { "enchant weapon",		10, 150 },
+    { "create monster",		 5,  75 },
+    { "remove curse",		 8, 105 },
+    { "aggravate monsters",	 4,  20 },
+    { "blank paper",		 1,   5 },
+    { "genocide",		 1, 300 },
+};
+
+struct magic_item p_magic[MAXPOTIONS] = {
+    { "confusion",		 8,   5 },
+    { "paralysis",		10,   5 },
+    { "poison",			 8,   5 },
+    { "gain strength",		15, 150 },
+    { "see invisible",		 2, 100 },
+    { "healing",		15, 130 },
+    { "monster detection",	 6, 130 },
+    { "magic detection",	 6, 105 },
+    { "raise level",		 2, 250 },
+    { "extra healing",		 5, 200 },
+    { "haste self",		 4, 190 },
+    { "restore strength",	14, 130 },
+    { "blindness",		 4,   5 },
+    { "thirst quenching",	 1,   5 },
+};
+
+struct magic_item r_magic[MAXRINGS] = {
+    { "protection",		 9, 400 },
+    { "add strength",		 9, 400 },
+    { "sustain strength",	 5, 280 },
+    { "searching",		10, 420 },
+    { "see invisible",		10, 310 },
+    { "adornment",		 1,  10 },
+    { "aggravate monster",	10,  10 },
+    { "dexterity",		 8, 440 },
+    { "increase damage",	 8, 400 },
+    { "regeneration",		 4, 460 },
+    { "slow digestion",		 9, 240 },
+    { "teleportation",		 5,  30 },
+    { "stealth",		 7, 470 },
+    { "maintain armor",		 5, 380 },
+};
+
+struct magic_item ws_magic[MAXSTICKS] = {
+    { "light",			12, 250 },
+    { "striking",		 9,  75 },
+    { "lightning",		 3, 330 },
+    { "fire",			 3, 330 },
+    { "cold",			 3, 330 },
+    { "polymorph",		15, 310 },
+    { "magic missile",		10, 170 },
+    { "haste monster",		 9,   5 },
+    { "slow monster",		11, 350 },
+    { "drain life",		 9, 300 },
+    { "nothing",		 1,   5 },
+    { "teleport away",		 5, 340 },
+    { "teleport to",		 5,  50 },
+    { "cancellation",		 5, 280 },
+};
+
+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",
+    'z',	"<dir>	zap a wand in a direction",
+    '^',	"<dir>	identify trap type",
+    's',	"	search for trap/secret door",
+    '>',	"	go down a staircase",
+    '<',	"	go up a staircase",
+    '.',	"	rest for a while",
+    'i',	"	inventory",
+    'I',	"	inventory single item",
+    'q',	"	quaff potion",
+    'r',	"	read paper",
+    '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",
+    'D',	"	recall what's been discovered",
+    'o',	"	examine/set options",
+    CTRL('L'),	"	redraw screen",
+    CTRL('R'),	"	repeat last message",
+    ESCAPE,	"	cancel command",
+    '!',	"	shell escape",
+    'S',	"	save game",
+    'Q',	"	quit",
+    0, 0
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rogue4/extern.h	Sat Oct 24 16:52:52 2009 +0000
@@ -0,0 +1,91 @@
+/*
+ * Defines for things used in mach_dep.c
+ *
+ * @(#)extern.h	4.3 (Berkeley) 4/2/82
+ *
+ * Rogue: Exploring the Dungeons of Doom
+ * Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman
+ * All rights reserved.
+ *
+ * See the file LICENSE.TXT for full copyright and licensing information.
+ */
+
+/*
+ * Don't change the constants, since they are used for sizes in many
+ * places in the program.
+ */
+
+#define MAXSTR		80	/* maximum length of strings */
+#define MAXLINES	32	/* maximum number of screen lines used */
+#define MAXCOLS		80	/* maximum number of screen columns used */
+
+#define RN		(((seed = seed*11109+13849) >> 16) & 0xffff)
+
+/*
+ * Now all the global variables
+ */
+
+extern bool	after, amulet, askme, door_stop, fight_flush,
+		firstmove, in_shell, jump, noscore, p_know[], passgo,
+		playing, r_know[], running, s_know[], save_msg,
+		slow_invent, terse, wizard, ws_know[];
+
+
+extern const char *p_colors[], *r_stones[], *w_names[], 
+                  *a_names[], *ws_made[];
+extern char	_flags[], _level[], file_name[], fruit[],
+		home[], huh[], outbuf[], *p_guess[],
+		prbuf[], *r_guess[], *release, runch,
+		*s_guess[], *s_names[], take, whoami[],
+		*ws_guess[], *ws_type[];
+
+extern int	a_chances[], a_class[], count, dnum, food_left,
+		fung_hit, fd, group, hungry_state, inpack, lastscore,
+		level, max_level, mpos, no_command, no_food, no_move,
+		ntraps, purse, quiet, total;
+
+extern long	seed;
+
+extern WINDOW	*hw;
+
+/*
+ * Function types
+ */
+
+char	*charge_str(), *ctime(), *getenv(), *inv_name(),
+	*killname(), *nothing(), *num(), *ring_num(),
+	*tr_name(),
+	*unctrol(), *vowelstr();
+
+void    leave(int), quit(int), tstp(), auto_save(int), endit(int);
+int	doctor(), nohaste(),
+	rollwand(), runners(), sight(), stomach(), swander(),
+	turn_see(), unconfuse(), unsee();
+
+void	checkout();
+
+long	lseek();
+
+extern coord ch_ret;
+extern shint countch;
+extern shint direction;
+extern shint newcount;
+extern int   between;
+extern int   num_checks;
+extern char  lvl_mons[27];
+extern char  wand_mons[27];
+extern coord nh;
+extern bool  got_genocide;
+
+#if defined(__GLIBC__) || defined(__INTERIX)
+/*
+   O_BINARY flag not provided in Interix/SFU or some versions of Linux. 
+   It is the same as default behavior so we just zero define it here
+   to make source code compatible.
+*/
+#define O_BINARY 0
+#endif
+
+extern FILE *md_fdopen(int fd, char *mode);
+extern char *md_getusername(int uid);
+extern char *md_gethomedir();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rogue4/fight.c	Sat Oct 24 16:52:52 2009 +0000
@@ -0,0 +1,738 @@
+/*
+ * All the fighting gets done here
+ *
+ * @(#)fight.c	4.30 (Berkeley) 4/6/82
+ *
+ * Rogue: Exploring the Dungeons of Doom
+ * Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman
+ * All rights reserved.
+ *
+ * See the file LICENSE.TXT for full copyright and licensing information.
+ */
+
+#include <curses.h>
+#include <ctype.h>
+#include <string.h>
+#include "rogue.h"
+
+long e_levels[] = {
+    10L,20L,40L,80L,160L,320L,640L,1280L,2560L,5120L,10240L,20480L,
+    40920L, 81920L, 163840L, 327680L, 655360L, 1310720L, 2621440L, 0L
+};
+
+/*
+ * fight:
+ *	The player attacks the monster.
+ */
+fight(mp, mn, weap, thrown)
+register coord *mp;
+char mn;
+register THING *weap;
+bool thrown;
+{
+    register THING *tp;
+    register bool did_hit = TRUE;
+    register const char *mname;
+
+    /*
+     * Find the monster we want to fight
+     */
+#ifdef WIZARD
+    if ((tp = moat(mp->y, mp->x)) == NULL)
+	debug("Fight what @ %d,%d", mp->y, mp->x);
+#else
+    tp = moat(mp->y, mp->x);
+#endif
+    /*
+     * Since we are fighting, things are not quiet so no healing takes
+     * place.
+     */
+    count = quiet = 0;
+    runto(mp, &hero);
+    /*
+     * Let him know it was really a mimic (if it was one).
+     */
+    if (tp->t_type == 'M' && tp->t_disguise != 'M' && !on(player, ISBLIND))
+    {
+	tp->t_disguise = 'M';
+	if (!thrown)
+	    return FALSE;
+	msg("wait! That's a mimic!");
+    }
+    did_hit = FALSE;
+    if (on(player, ISBLIND))
+	mname = "it";
+    else
+	mname = monsters[mn-'A'].m_name;
+    if (roll_em(&player, tp, weap, thrown))
+    {
+	did_hit = FALSE;
+	if (thrown)
+	    thunk(weap, mname);
+	else
+	    hit(NULL, mname);
+	if (on(player, CANHUH))
+	{
+	    did_hit = TRUE;
+	    tp->t_flags |= ISHUH;
+	    player.t_flags &= ~CANHUH;
+	    msg("your hands stop glowing red");
+	}
+	if (tp->t_stats.s_hpt <= 0)
+	    killed(tp, TRUE);
+	else if (did_hit && !on(player, ISBLIND))
+	    msg("the %s appears confused", mname);
+	did_hit = TRUE;
+    }
+    else
+	if (thrown)
+	    bounce(weap, mname);
+	else
+	    miss(NULL, mname);
+    return did_hit;
+}
+
+/*
+ * attack:
+ *	The monster attacks the player
+ */
+attack(mp)
+register THING *mp;
+{
+    register const char *mname;
+
+    /*
+     * Since this is an attack, stop running and any healing that was
+     * going on at the time.
+     */
+    running = FALSE;
+    count = quiet = 0;
+    if (mp->t_type == 'M' && !on(player, ISBLIND))
+	mp->t_disguise = 'M';
+    if (on(player, ISBLIND))
+	mname = "it";
+    else
+	mname = monsters[mp->t_type-'A'].m_name;
+    if (roll_em(mp, &player, NULL, FALSE))
+    {
+	if (mp->t_type != 'E')
+	    hit(mname, NULL);
+	if (pstats.s_hpt <= 0)
+	    death(mp->t_type);	/* Bye bye life ... */
+	if (!on(*mp, ISCANC))
+	    switch (mp->t_type)
+	    {
+		case 'R':
+		    /*
+		     * If a rust monster hits, you lose armor, unless
+		     * that armor is leather or there is a magic ring
+		     */
+		    if (cur_armor != NULL && cur_armor->o_ac < 9
+			&& cur_armor->o_which != LEATHER)
+			    if (ISWEARING(R_SUSTARM))
+				msg("The rust vanishes instantly");
+			    else
+			    {
+				cur_armor->o_ac++;
+				if (!terse)
+				    msg("your armor appears to be weaker now. Oh my!");
+				else
+				    msg("your armor weakens");
+			    }
+		when 'E':
+		    /*
+		     * The gaze of the floating eye hypnotizes you
+		     */
+		    if (on(player, ISBLIND))
+			break;
+		    player.t_flags &= ~ISRUN;
+		    if (!no_command)
+		    {
+			addmsg("you are transfixed");
+			if (!terse)
+			    addmsg(" by the gaze of the floating eye");
+			endmsg();
+		    }
+		    no_command += rnd(2) + 2;
+		when 'A':
+		    /*
+		     * Ants have poisonous bites
+		     */
+		    if (!save(VS_POISON))
+			if (!ISWEARING(R_SUSTSTR))
+			{
+			    chg_str(-1);
+			    if (!terse)
+				msg("you feel a sting in your arm and now feel weaker");
+			    else
+				msg("a sting has weakened you");
+			}
+			else
+			    if (!terse)
+				msg("a sting momentarily weakens you");
+			    else
+				msg("sting has no effect");
+		when 'W':
+		case 'V':
+		    /*
+		     * Wraiths might drain energy levels, and Vampires
+		     * can steal max_hp
+		     */
+		    if (rnd(100) < (mp->t_type == 'W' ? 15 : 30))
+		    {
+			register int fewer;
+
+			if (mp->t_type == 'W')
+			{
+			    if (pstats.s_exp == 0)
+				death('W');		/* All levels gone */
+			    if (--pstats.s_lvl == 0)
+			    {
+				pstats.s_exp = 0;
+				pstats.s_lvl = 1;
+			    }
+			    else
+				pstats.s_exp = e_levels[pstats.s_lvl-1]+1;
+			    fewer = roll(1, 10);
+			}
+			else
+			    fewer = roll(1, 5);
+			pstats.s_hpt -= fewer;
+			max_hp -= fewer;
+			if (pstats.s_hpt < 1)
+			    pstats.s_hpt = 1;
+			if (max_hp < 1)
+			    death(mp->t_type);
+			msg("you suddenly feel weaker");
+		    }
+		when 'F':
+		    /*
+		     * Violet fungi stops the poor guy from moving
+		     */
+		    player.t_flags |= ISHELD;
+		    sprintf(monsters['F'-'A'].m_stats.s_dmg,"%dd1",++fung_hit);
+		when 'L':
+		{
+		    /*
+		     * Leperachaun steals some gold
+		     */
+		    register long lastpurse;
+
+		    lastpurse = purse;
+		    purse -= GOLDCALC;
+		    if (!save(VS_MAGIC))
+			purse -= GOLDCALC + GOLDCALC + GOLDCALC + GOLDCALC;
+		    if (purse < 0)
+			purse = 0;
+		    remove_monster(&mp->t_pos, mp, FALSE);
+			mp = NULL;
+		    if (purse != lastpurse)
+			msg("your purse feels lighter");
+		}
+		when 'N':
+		{
+		    register THING *obj, *steal;
+		    register int nobj;
+
+		    /*
+		     * Nymph's steal a magic item, look through the pack
+		     * and pick out one we like.
+		     */
+		    steal = NULL;
+		    for (nobj = 0, obj = pack; obj != NULL; obj = next(obj))
+			if (obj != cur_armor && obj != cur_weapon
+			    && obj != cur_ring[LEFT] && obj != cur_ring[RIGHT]
+			    && is_magic(obj) && rnd(++nobj) == 0)
+				steal = obj;
+		    if (steal != NULL)
+		    {
+			remove_monster(&mp->t_pos, moat(mp->t_pos.y, mp->t_pos.x), FALSE);
+			mp = NULL;
+			inpack--;
+			if (steal->o_count > 1 && steal->o_group == 0)
+			{
+			    register int oc;
+
+			    oc = steal->o_count--;
+			    steal->o_count = 1;
+			    msg("she stole %s!", inv_name(steal, TRUE));
+			    steal->o_count = oc;
+			}
+			else
+			{
+			    detach(pack, steal);
+			    msg("she stole %s!", inv_name(steal, TRUE));
+			    discard(steal);
+			}
+		    }
+		}
+		otherwise:
+		    break;
+	    }
+    }
+    else if (mp->t_type != 'E')
+    {
+	if (mp->t_type == 'F')
+	{
+	    pstats.s_hpt -= fung_hit;
+	    if (pstats.s_hpt <= 0)
+		death(mp->t_type);	/* Bye bye life ... */
+	}
+	miss(mname, NULL);
+    }
+    if (fight_flush)
+	flush_type();
+    count = 0;
+    status();
+
+	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;
+{
+    register int res = rnd(20);
+    register int need = (20 - at_lvl) - op_arm;
+
+    return (res + wplus >= need);
+}
+
+/*
+ * check_level:
+ *	Check to see if the guy has gone up a level.
+ */
+check_level()
+{
+    register int i, add, olevel;
+
+    for (i = 0; e_levels[i] != 0; i++)
+	if (e_levels[i] > pstats.s_exp)
+	    break;
+    i++;
+    olevel = pstats.s_lvl;
+    pstats.s_lvl = i;
+    if (i > olevel)
+    {
+	add = roll(i - olevel, 10);
+	max_hp += add;
+	if ((pstats.s_hpt += add) > max_hp)
+	    pstats.s_hpt = max_hp;
+	msg("welcome to level %d", i);
+    }
+}
+
+/*
+ * roll_em:
+ *	Roll several attacks
+ */
+roll_em(thatt, thdef, weap, hurl)
+THING *thatt, *thdef, *weap;
+bool hurl;
+{
+    register struct stats *att, *def;
+    register char *cp;
+    register int ndice, nsides, def_arm;
+    register bool did_hit = FALSE;
+    register int hplus;
+    register int dplus;
+    register int damage;
+
+    att = &thatt->t_stats;
+    def = &thdef->t_stats;
+    if (weap == NULL)
+    {
+	cp = att->s_dmg;
+	dplus = 0;
+	hplus = 0;
+    }
+    else
+    {
+	hplus = (weap == NULL ? 0 : weap->o_hplus);
+	dplus = (weap == NULL ? 0 : weap->o_dplus);
+	if (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;
+	}
+	if (hurl)
+	    if ((weap->o_flags&ISMISL) && cur_weapon != NULL &&
+	      cur_weapon->o_which == weap->o_launch)
+	    {
+		cp = weap->o_hurldmg;
+		hplus += cur_weapon->o_hplus;
+		dplus += cur_weapon->o_dplus;
+	    }
+	    else
+		cp = 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");
+		cp = weap->o_damage;
+		weap->o_hplus = weap->o_dplus = 0;
+		weap->o_charges = 0;
+	    }
+	}
+    }
+    /*
+     * If the creature being attacked is not running (alseep or held)
+     * then the attacker gets a plus four bonus to hit.
+     */
+    if (!on(*thdef, ISRUN))
+	hplus += 4;
+    def_arm = def->s_arm;
+    if (def == &pstats)
+    {
+	if (cur_armor != NULL)
+	    def_arm = cur_armor->o_ac;
+	if (ISRING(LEFT, R_PROTECT))
+	    def_arm -= cur_ring[LEFT]->o_ac;
+	if (ISRING(RIGHT, R_PROTECT))
+	    def_arm -= cur_ring[RIGHT]->o_ac;
+    }
+    for (;;)
+    {
+	ndice = atoi(cp);
+	if ((cp = strchr(cp, 'd')) == NULL)
+	    break;
+	nsides = atoi(++cp);
+	if (swing(att->s_lvl, def_arm, hplus + str_plus(att->s_str)))
+	{
+	    register int proll;
+
+	    proll = roll(ndice, nsides);
+#ifdef WIZARD
+	    if (ndice + nsides > 0 && proll < 1)
+		debug("Damage for %dd%d came out %d, dplus = %d, add_dam = %d, def_arm = %d", ndice, nsides, proll, dplus, add_dam(att->s_str), def_arm);
+#endif
+	    damage = dplus + proll + add_dam(att->s_str);
+	    def->s_hpt -= max(0, damage);
+	    did_hit = TRUE;
+	}
+	if ((cp = strchr(cp, '/')) == NULL)
+	    break;
+	cp++;
+    }
+    return did_hit;
+}
+
+/*
+ * prname:
+ *	The print name of a combatant
+ */
+char *
+prname(who, upper)
+register char *who;
+bool upper;
+{
+    static char tbuf[MAXSTR];
+
+    *tbuf = '\0';
+    if (who == 0)
+	strcpy(tbuf, "you"); 
+    else if (on(player, 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, ee)
+register char *er, *ee;
+{
+    register char *s = "";
+
+    addmsg(prname(er, TRUE));
+    if (terse)
+	s = " hit";
+    else
+	switch (rnd(4))
+	{
+	    case 0: s = " scored an excellent hit on ";
+	    when 1: s = " hit ";
+	    when 2: s = (er == 0 ? " have injured " : " has injured ");
+	    when 3: s = (er == 0 ? " swing and hit " : " swings and hits ");
+	}
+    addmsg(s);
+    if (!terse)
+	addmsg(prname(ee, FALSE));
+    endmsg();
+}
+
+/*
+ * miss:
+ *	Print a message to indicate a poor swing
+ */
+miss(er, ee)
+register char *er, *ee;
+{
+    register char *s = "";
+
+    addmsg(prname(er, TRUE));
+    switch (terse ? 0 : rnd(4))
+    {
+	case 0: s = (er == 0 ? " miss" : " misses");
+	when 1: s = (er == 0 ? " swing and miss" : " swings and misses");
+	when 2: s = (er == 0 ? " barely miss" : " barely misses");
+	when 3: s = (er == 0 ? " don't hit" : " doesn't hit");
+    }
+    addmsg(s);
+    if (!terse)
+	addmsg(" %s", prname(ee, FALSE));
+    endmsg();
+}
+
+/*
+ * save_throw:
+ *	See if a creature save against something
+ */
+save_throw(which, tp)
+int which;
+THING *tp;
+{
+    register int need;
+
+    need = 14 + which - tp->t_stats.s_lvl / 2;
+    return (roll(1, 20) >= need);
+}
+
+/*
+ * save:
+ *	See if he saves against various nasty things
+ */
+save(which)
+register int which;
+{
+    if (which == VS_MAGIC)
+    {
+	if (ISRING(LEFT, R_PROTECT))
+	    which -= cur_ring[LEFT]->o_ac;
+	if (ISRING(RIGHT, R_PROTECT))
+	    which -= cur_ring[RIGHT]->o_ac;
+    }
+    return save_throw(which, &player);
+}
+
+/*
+ * str_plus:
+ *	Compute bonus/penalties for strength on the "to hit" roll
+ */
+str_plus(str)
+register str_t str;
+{
+    if (str == 31)
+	return 3;
+    if (str > 20)
+	return 2;
+    if (str > 16)
+	return 1;
+    if (str > 6)
+	return 0;
+    return str - 7;
+}
+
+/*
+ * add_dam:
+ *	Compute additional damage done for exceptionally high or low strength
+ */
+ add_dam(str)
+ register str_t str;
+ {
+    if (str == 31)
+	return 6;
+    if (str > 21)
+	return 5;
+    if (str == 21)
+	return 4;
+    if (str > 18)
+	return 3;
+    if (str == 18)
+	return 2;
+    if (str > 15)
+	return 1;
+    if (str > 6)
+	return 0;
+    return str - 7;
+}
+
+/*
+ * raise_level:
+ *	The guy just magically went up a level.
+ */
+raise_level()
+{
+    pstats.s_exp = e_levels[pstats.s_lvl-1] + 1L;
+    check_level();
+}
+
+/*
+ * thunk:
+ *	A missile hits a monster
+ */
+thunk(weap, mname)
+register THING *weap;
+register const char *mname;
+{
+    if (weap->o_type == WEAPON)
+	addmsg("the %s hits ", w_names[weap->o_which]);
+    else
+	addmsg("you hit ");
+    if (on(player, ISBLIND))
+	msg("it");
+    else
+	msg("the %s", mname);
+}
+
+/*
+ * bounce:
+ *	A missile misses a monster
+ */
+bounce(weap, mname)
+register THING *weap;
+register const char *mname;
+{
+    if (weap->o_type == WEAPON)
+	addmsg("the %s misses ", w_names[weap->o_which]);
+    else
+	addmsg("you missed ");
+    if (on(player, ISBLIND))
+	msg("it");
+    else
+	msg("the %s", mname);
+}
+
+/*
+ * remove:
+ *	Remove a monster from the screen
+ */
+remove_monster(mp, tp, waskill)
+register coord *mp;
+register THING *tp;
+bool waskill;
+{
+    register THING *obj, *nexti;
+
+    for (obj = tp->t_pack; obj != NULL; obj = nexti)
+    {
+	nexti = next(obj);
+	obj->o_pos = tp->t_pos;
+	detach(tp->t_pack, obj);
+	if (waskill)
+	    fall(obj, FALSE);
+	else
+	    discard(obj);
+    }
+    moat(mp->y, mp->x) = NULL;
+    mvaddch(mp->y, mp->x, tp->t_oldch);
+    detach(mlist, tp);
+    discard(tp);
+}
+
+/*
+ * is_magic:
+ *	Returns true if an object radiates magic
+ */
+is_magic(obj)
+register THING *obj;
+{
+    switch (obj->o_type)
+    {
+	case ARMOR:
+	    return obj->o_ac != a_class[obj->o_which];
+	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(tp, pr)
+register THING *tp;
+bool pr;
+{
+    pstats.s_exp += tp->t_stats.s_exp;
+    /*
+     * If the monster was a violet fungi, un-hold him
+     */
+    switch (tp->t_type)
+    {
+	case 'F':
+	    player.t_flags &= ~ISHELD;
+	    fung_hit = 0;
+	    strcpy(monsters['F'-'A'].m_stats.s_dmg, "000d0");
+	when 'L':
+	{
+	    register THING *gold;
+
+	    if (fallpos(&tp->t_pos, &tp->t_room->r_gold, TRUE))
+	    {
+		gold = new_item();
+		gold->o_type = GOLD;
+		gold->o_goldval = GOLDCALC;
+		if (save(VS_MAGIC))
+		    gold->o_goldval += GOLDCALC + GOLDCALC
+				     + GOLDCALC + GOLDCALC;
+		attach(tp->t_pack, gold);
+	    }
+	}
+    }
+    /*
+     * Get rid of the monster.
+     */
+    if (pr)
+    {
+	if (!terse)
+	    addmsg("you have ");
+	addmsg("defeated ");
+	if (on(player, ISBLIND))
+	    msg("it");
+	else
+	{
+	    if (!terse)
+		addmsg("the ");
+	    msg("%s", monsters[tp->t_type-'A'].m_name);
+	}
+    }
+    remove_monster(&tp->t_pos, tp, TRUE);
+    /*
+     * Do adjustments if he went up a level
+     */
+    check_level();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rogue4/findpw.c	Sat Oct 24 16:52:52 2009 +0000
@@ -0,0 +1,23 @@
+/*
+ * print out an encrypted password on the standard output
+ *
+ * @(#)findpw.c	1.1 (Berkeley) 12/20/81
+ *
+ * Rogue: Exploring the Dungeons of Doom
+ * Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman
+ * All rights reserved.
+ *
+ * See the file LICENSE.TXT for full copyright and licensing information.
+ */
+
+#include <stdio.h>
+
+main()
+{
+    char buf[80];
+
+    fprintf(stderr, "Password: ");
+    fgets(buf, 80, stdin);
+    buf[strlen(buf) - 1] = '\0';
+    printf("%s\n", xcrypt(buf, "mT"));
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rogue4/init.c	Sat Oct 24 16:52:52 2009 +0000
@@ -0,0 +1,422 @@
+/*
+ * global variable initializaton
+ *
+ * @(#)init.c	4.16 (Berkeley) 3/30/82
+ *
+ * Rogue: Exploring the Dungeons of Doom
+ * Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman
+ * All rights reserved.
+ *
+ * See the file LICENSE.TXT for full copyright and licensing information.
+ */
+
+#include <curses.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+#include "rogue.h"
+
+/*
+ * init_player:
+ *	Roll up the rogue
+ */
+init_player()
+{
+    register THING *obj;
+
+    pstats = max_stats;
+    food_left = HUNGERTIME;
+    /*
+     * Give the rogue his weaponry.  First a mace.
+     */
+    obj = new_item();
+    obj->o_type = WEAPON;
+    obj->o_which = MACE;
+    init_weapon(obj, MACE);
+    obj->o_hplus = 1;
+    obj->o_dplus = 1;
+    obj->o_flags |= ISKNOW;
+    obj->o_count = 1;
+    obj->o_group = 0;
+    add_pack(obj, TRUE);
+    cur_weapon = obj;
+    /*
+     * Now a +1 bow
+     */
+    obj = new_item();
+    obj->o_type = WEAPON;
+    obj->o_which = BOW;
+    init_weapon(obj, BOW);
+    obj->o_hplus = 1;
+    obj->o_dplus = 0;
+    obj->o_count = 1;
+    obj->o_group = 0;
+    obj->o_flags |= ISKNOW;
+    add_pack(obj, TRUE);
+    /*
+     * Now some arrows
+     */
+    obj = new_item();
+    obj->o_type = WEAPON;
+    obj->o_which = ARROW;
+    init_weapon(obj, ARROW);
+    obj->o_count = rnd(15) + 25;
+    obj->o_hplus = obj->o_dplus = 0;
+    obj->o_flags |= ISKNOW;
+    add_pack(obj, TRUE);
+    /*
+     * And his suit of armor
+     */
+    obj = new_item();
+    obj->o_type = ARMOR;
+    obj->o_which = RING_MAIL;
+    obj->o_ac = a_class[RING_MAIL] - 1;
+    obj->o_flags |= ISKNOW;
+    obj->o_count = 1;
+    obj->o_group = 0;
+    cur_armor = obj;
+    add_pack(obj, TRUE);
+    /*
+     * Give him some food too
+     */
+    obj = new_item();
+    obj->o_type = FOOD;
+    obj->o_count = 1;
+    obj->o_which = 0;
+    obj->o_group = 0;
+    add_pack(obj, TRUE);
+}
+
+/*
+ * Contains defintions and functions for dealing with things like
+ * potions and scrolls
+ */
+
+const char *rainbow[NCOLORS] = {
+    "amber",
+    "aquamarine",
+    "black",
+    "blue",
+    "brown",
+    "clear",
+    "crimson",
+    "cyan",
+    "ecru",
+    "gold",
+    "green",
+    "grey",
+    "magenta",
+    "orange",
+    "pink",
+    "plaid",
+    "purple",
+    "red",
+    "silver",
+    "tan",
+    "tangerine",
+    "topaz",
+    "turquoise",
+    "vermilion",
+    "violet",
+    "white",
+    "yellow",
+};
+
+const char *sylls[NSYLLS] = {
+    "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",
+};
+
+const STONE stones[NSTONES] = {
+    { "agate",		 25},
+    { "alexandrite",	 40},
+    { "amethyst",	 50},
+    { "carnelian",	 40},
+    { "diamond",	300},
+    { "emerald",	300},
+    { "germanium",	225},
+    { "granite",	  5},
+    { "garnet",		 50},
+    { "jade",		150},
+    { "kryptonite",	300},
+    { "lapis lazuli",	 50},
+    { "moonstone",	 50},
+    { "obsidian",	 15},
+    { "onyx",		 60},
+    { "opal",		200},
+    { "pearl",		220},
+    { "peridot",	 63},
+    { "ruby",		350},
+    { "saphire",	285},
+    { "stibotantalite",	200},
+    { "tiger eye",	 50},
+    { "topaz",		 60},
+    { "turquoise",	 70},
+    { "taaffeite",	300},
+    { "zircon",	 	 80},
+};
+
+const char *wood[NWOOD] = {
+    "avocado wood",
+    "balsa",
+    "bamboo",
+    "banyan",
+    "birch",
+    "cedar",
+    "cherry",
+    "cinnibar",
+    "cypress",
+    "dogwood",
+    "driftwood",
+    "ebony",
+    "elm",
+    "eucalyptus",
+    "fall",
+    "hemlock",
+    "holly",
+    "ironwood",
+    "kukui wood",
+    "mahogany",
+    "manzanita",
+    "maple",
+    "oaken",
+    "persimmon wood",
+    "pecan",
+    "pine",
+    "poplar",
+    "redwood",
+    "rosewood",
+    "spruce",
+    "teak",
+    "walnut",
+    "zebrawood",
+};
+
+const char *metal[NMETAL] = {
+    "aluminum",
+    "beryllium",
+    "bone",
+    "brass",
+    "bronze",
+    "copper",
+    "electrum",
+    "gold",
+    "iron",
+    "lead",
+    "magnesium",
+    "mercury",
+    "nickel",
+    "pewter",
+    "platinum",
+    "steel",
+    "silver",
+    "silicon",
+    "tin",
+    "titanium",
+    "tungsten",
+    "zinc",
+};
+
+/*
+ * init_things
+ *	Initialize the probabilities for types of things
+ */
+init_things()
+{
+    register struct magic_item *mp;
+
+    for (mp = &things[1]; mp <= &things[NUMTHINGS-1]; mp++)
+	mp->mi_prob += (mp-1)->mi_prob;
+#ifdef WIZARD
+    badcheck("things", things, NUMTHINGS);
+#endif
+}
+
+/*
+ * init_colors:
+ *	Initialize the potion color scheme for this time
+ */
+init_colors()
+{
+    register int i, j;
+    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;
+    }
+#ifdef WIZARD
+    badcheck("potions", p_magic, MAXPOTIONS);
+#endif
+}
+
+/*
+ * init_names:
+ *	Generate the names of the various scrolls
+ */
+#define MAXNAME	40	/* Max number of characters in a name */
+
+init_names()
+{
+    register int nsyl;
+    register char *cp;
+    const char *sp;
+    register int i, nwords;
+
+    for (i = 0; i < MAXSCROLLS; i++)
+    {
+	cp = prbuf;
+	nwords = rnd(4) + 2;
+	while (nwords--)
+	{
+	    nsyl = rnd(3) + 1;
+	    while (nsyl--)
+	    {
+		sp = sylls[rnd((sizeof sylls) / (sizeof (char *)))];
+		if (&cp[strlen(sp)] > &prbuf[MAXNAME])
+			break;
+		while (*sp)
+		    *cp++ = *sp++;
+	    }
+	    *cp++ = ' ';
+	}
+	*--cp = '\0';
+	s_names[i] = (char *) malloc((unsigned) 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;
+    }
+#ifdef WIZARD
+    badcheck("scrolls", s_magic, MAXSCROLLS);
+#endif
+}
+
+/*
+ * init_stones:
+ *	Initialize the ring stone setting scheme for this time
+ */
+init_stones()
+{
+    register int i, j;
+    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].st_name;
+	r_know[i] = FALSE;
+	r_guess[i] = NULL;
+	if (i > 0)
+	    r_magic[i].mi_prob += r_magic[i-1].mi_prob;
+	r_magic[i].mi_worth += stones[j].st_value;
+    }
+#ifdef WIZARD
+    badcheck("rings", r_magic, MAXRINGS);
+#endif
+}
+
+/*
+ * init_materials:
+ *	Initialize the construction materials for wands and staffs
+ */
+init_materials()
+{
+    register int i, j;
+    register const char *str;
+    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++)
+    {
+	for (;;)
+	    if (rnd(2) == 0)
+	    {
+		j = rnd(NMETAL);
+		if (!metused[j])
+		{
+		    ws_type[i] = "wand";
+		    str = metal[j];
+		    metused[j] = TRUE;
+		    break;
+		}
+	    }
+	    else
+	    {
+		j = rnd(NWOOD);
+		if (!woodused[j])
+		{
+		    ws_type[i] = "staff";
+		    str = wood[j];
+		    woodused[j] = TRUE;
+		    break;
+		}
+	    }
+	ws_made[i] = str;
+	ws_know[i] = FALSE;
+	ws_guess[i] = NULL;
+	if (i > 0)
+	    ws_magic[i].mi_prob += ws_magic[i-1].mi_prob;
+    }
+#ifdef WIZARD
+    badcheck("sticks", ws_magic, MAXSTICKS);
+#endif
+}
+
+#ifdef WIZARD
+/*
+ * badcheck:
+ *	Check to see if a series of probabilities sums to 100
+ */
+badcheck(name, magic, bound)
+char *name;
+register struct magic_item *magic;
+register int bound;
+{
+    register struct magic_item *end;
+
+    if (magic[bound - 1].mi_prob == 100)
+	return;
+    printf("\nBad percentages for %s:\n", name);
+    for (end = &magic[bound]; magic < end; magic++)
+	printf("%3d%% %s\n", magic->mi_prob, magic->mi_name);
+    printf("[hit RETURN to continue]");
+    fflush(stdout);
+    while (getchar() != '\n')
+	continue;
+}
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rogue4/io.c	Sat Oct 24 16:52:52 2009 +0000
@@ -0,0 +1,253 @@
+/*
+ * Various input/output functions
+ *
+ * @(#)io.c	4.13 (Berkeley) 2/25/82
+ *
+ * Rogue: Exploring the Dungeons of Doom
+ * Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman
+ * All rights reserved.
+ *
+ * See the file LICENSE.TXT for full copyright and licensing information.
+ */
+
+#include <curses.h>
+#include <ctype.h>
+#include <string.h>
+#include "rogue.h"
+#include <stdarg.h>
+
+/*
+ * 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')
+    {
+	move(0, 0);
+	clrtoeol();
+	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()
+{
+    if (save_msg)
+    {
+	strncpy(huh, msgbuf, 80);
+	huh[79] = 0;
+    }
+
+    if (mpos)
+    {
+	look(FALSE);
+	move(0, mpos);
+	addstr("--More--");
+	refresh();
+	wait_for(' ');
+    }
+    /*
+     * All messages should start with uppercase, except ones that
+     * start with a pack addressing character
+     */
+    if (islower(msgbuf[0]) && msgbuf[1] != ')')
+	msgbuf[0] = toupper(msgbuf[0]);
+    mvaddstr(0, 0, msgbuf);
+    clrtoeol();
+    mpos = newpos;
+    newpos = 0;
+    refresh();
+}
+
+/*
+ * doadd:
+ *	Perform an add onto the message 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)
+{
+    switch (ch)
+    {
+	case ' ':
+	case '|':
+	case '-':
+	    return FALSE;
+	default:
+	    return (!isalpha(ch));
+    }
+}
+
+/*
+ * readchar:
+ *	Flushes stdout so that screen is up to date and then returns
+ *	getchar().
+ */
+readcharw(win)
+WINDOW *win;
+{
+    int ch;
+
+    ch = md_readchar(win);
+
+    if ((ch == 3) || (ch == 0))
+    {
+	quit(0);
+	return(27);
+    }
+
+    return(ch);
+}
+
+readchar()
+{
+    return( readcharw(stdscr) );
+}
+
+char *
+unctrol(ch)
+char ch;
+{
+    return( (char *) unctrl(ch) );
+}
+
+/*
+ * status:
+ *	Display the important stats line.  Keep the cursor where it was.
+ */
+status()
+{
+    register int oy, ox, temp;
+    static int hpwidth = 0, s_hungry;
+    static int s_lvl, s_pur = -1, s_hp, s_ac = 0;
+    static str_t s_str;
+    static long s_exp = 0;
+    static char *state_name[] =
+    {
+	"", "Hungry", "Weak", "Faint"
+    };
+
+    /*
+     * If nothing has changed since the last status, don't
+     * bother.
+     */
+    if (s_hp == pstats.s_hpt && s_exp == pstats.s_exp && s_pur == purse
+	&& s_ac == (cur_armor != NULL ? cur_armor->o_ac : pstats.s_arm)
+	&& s_str == pstats.s_str && s_lvl == level && s_hungry == hungry_state)
+	    return;
+	
+    getyx(stdscr, oy, ox);
+    if (s_hp != max_hp)
+    {
+	temp = s_hp = max_hp;
+	for (hpwidth = 0; temp; hpwidth++)
+	    temp /= 10;
+    }
+    move(LINES - 1, 0);
+    printw("Level: %d  Gold: %-5d  Hp: %*d(%*d)  Str: %2d(%d)  Ac: %-2d  Exp: %d/%ld  %s",
+	    level, purse, hpwidth, pstats.s_hpt, hpwidth, max_hp, pstats.s_str,
+	    max_stats.s_str,
+	    cur_armor != NULL ? cur_armor->o_ac : pstats.s_arm, pstats.s_lvl,
+	    pstats.s_exp, state_name[hungry_state]);
+
+    clrtoeol();
+    /*
+     * Save old status
+     */
+    s_lvl = level;
+    s_pur = purse;
+    s_hp = pstats.s_hpt;
+    s_str = pstats.s_str;
+    s_exp = pstats.s_exp; 
+    s_ac = (cur_armor != NULL ? cur_armor->o_ac : pstats.s_arm);
+    s_hungry = hungry_state;
+    move(oy, ox);
+}
+
+/*
+ * wait_for
+ *	Sit around until the guy types the right key
+ */
+
+
+
+wait_for(ch)
+register char ch;
+{
+    w_wait_for(stdscr, ch);
+}
+
+w_wait_for(win,ch)
+WINDOW *win;
+register char ch;
+{
+    register char c;
+
+    if (ch == '\n')
+        while ((c = readcharw(win)) != '\n' && c != '\r')
+	    continue;
+    else
+        while (readcharw(win) != ch)
+	    continue;
+}
+
+/*
+ * show_win:
+ *	Function used to display a window and wait before returning
+ */
+show_win(scr, message)
+register WINDOW *scr;
+char *message;
+{
+    mvwaddstr(scr, 0, 0, message);
+    touchwin(scr);
+    wmove(scr, hero.y, hero.x);
+    wrefresh(scr);
+    w_wait_for(scr,' ');
+    clearok(curscr, TRUE);
+    touchwin(stdscr);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rogue4/list.c	Sat Oct 24 16:52:52 2009 +0000
@@ -0,0 +1,96 @@
+/*
+ * Functions for dealing with linked lists of goodies
+ *
+ * @(#)list.c	4.7 (Berkeley) 12/19/81
+ *
+ * Rogue: Exploring the Dungeons of Doom
+ * Copyright (C) 1980, 1981, 1982 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 <curses.h>
+#include "rogue.h"
+
+/*
+ * detach:
+ *	Takes an item out of whatever linked list it might be in
+ */
+_detach(list, item)
+register THING **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)
+register THING **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)
+register THING **ptr;
+{
+    register THING *item;
+
+    while (*ptr != NULL)
+    {
+	item = *ptr;
+	*ptr = next(item);
+	discard(item);
+    }
+}
+
+/*
+ * discard:
+ *	Free up an item
+ */
+discard(item)
+register THING *item;
+{
+    total--;
+    free((char *) item);
+}
+
+/*
+ * new_item
+ *	Get a new item with a specified size
+ */
+THING *
+new_item()
+{
+    register THING *item;
+
+    if ((item = calloc(1, sizeof *item)) == NULL)
+	msg("ran out of memory after %d items", total);
+    else
+	total++;
+    item->l_next = item->l_prev = NULL;
+    return item;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rogue4/mach_dep.c	Sat Oct 24 16:52:52 2009 +0000
@@ -0,0 +1,365 @@
+/*
+ * Various installation dependent routines
+ *
+ * @(#)mach_dep.c	4.23 (Berkeley) 5/19/82
+ *
+ * Rogue: Exploring the Dungeons of Doom
+ * Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman
+ * All rights reserved.
+ *
+ * See the file LICENSE.TXT for full copyright and licensing information.
+ */
+
+/*
+ * The various tuneable defines are:
+ *
+ *	SCOREFILE	Where/if the score file should live.
+ *	MAXLOAD		What (if any) the maximum load average should be
+ *			when people are playing.  If defined, then
+ *	LOADAV		Should rogue define it's own routine to
+ *			get the load average?
+ *	NAMELIST	If so, where does the system namelist hide?
+ *	MAXUSERS	What (if any) the maximum user count should be
+ *			when people are playing.  If defined, then
+ *	UCOUNT		Should rogue define it's own routine to
+ *			count users?
+ *	UTMP		If so, where does the user list hide?
+ *	CHECKTIME	How often/if rogue should check during the game
+ *			for high load average.
+ */
+
+#include <limits.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <curses.h>
+#include <time.h>
+#include <signal.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <string.h>
+#include "rogue.h"
+
+int num_checks;		/* times we've gone over in checkout() */
+
+#ifdef SCOREFILE
+#ifdef LOCKFILE
+static char *lockfile = LOCKFILE;
+#endif
+#endif
+
+/*
+ * init_check:
+ *	Check out too see if it is proper to play the game now
+ */
+init_check()
+{
+    if (too_much())
+    {
+	printf("Sorry, %s, but the system is too loaded now.\n", whoami);
+	printf("Try again later.  Meanwhile, why not enjoy a%s %s?\n",
+	    vowelstr(fruit), fruit);
+	if (author())
+	    printf("However, since you're a good guy, it's up to you\n");
+	else
+	    exit(1);
+    }
+}
+
+/*
+ * open_score:
+ *	Open up the score file for future use, and then
+ *	setuid(getuid()) in case we are running setuid.
+ */
+open_score()
+{
+#ifdef SCOREFILE
+    fd = open(SCOREFILE, O_RDWR | O_CREAT, 0666 );
+#else
+    fd = -1;
+#endif
+    md_normaluser();
+}
+
+/*
+ * setup:
+ *	Get starting setup for all games
+ */
+setup()
+{
+    void  auto_save(), quit(), endit(), tstp();
+#ifdef CHECKTIME
+    int  checkout();
+#endif
+
+    /*
+     * make sure that large terminals don't overflow the bounds
+     * of the program
+     */
+    if (LINES > MAXLINES)
+	LINES = MAXLINES;
+    if (COLS > MAXCOLS)
+	COLS = MAXCOLS;
+
+#ifdef SIGHUP
+    signal(SIGHUP, auto_save);
+#endif
+#ifndef DUMP
+    signal(SIGILL, auto_save);
+#ifdef SIGTRAP
+    signal(SIGTRAP, auto_save);
+#endif
+#ifdef SIGIOT
+    signal(SIGIOT, auto_save);
+#endif
+#ifdef SIGEMT
+    signal(SIGEMT, auto_save);
+#endif
+    signal(SIGFPE, auto_save);
+#ifdef SIGBUS
+    signal(SIGBUS, auto_save);
+#endif
+    signal(SIGSEGV, auto_save);
+#ifdef SIGSYS
+    signal(SIGSYS, auto_save);
+#endif
+    signal(SIGTERM, auto_save);
+#endif
+
+    signal(SIGINT, quit);
+#ifndef DUMP
+#ifdef SIGQUIT
+    signal(SIGQUIT, endit);
+#endif
+#endif
+#ifdef CHECKTIME
+    signal(SIGALRM, checkout);
+    alarm(CHECKTIME * 60);
+    num_checks = 0;
+#endif
+    crmode();				/* Cbreak mode */
+    noecho();				/* Echo off */
+}
+
+/*
+ * start_score:
+ *	Start the scoring sequence
+ */
+start_score()
+{
+#ifdef SIGALRM
+    signal(SIGALRM, SIG_IGN);
+#endif
+}
+
+/*
+ * issymlink:
+ *	See if the file has a symbolic link
+ */
+issymlink(sp)
+char *sp;
+{
+#ifdef S_IFLNK
+    struct stat sbuf2;
+
+    if (lstat(sp, &sbuf2) < 0)
+	return FALSE;
+    else
+	return ((sbuf2.st_mode & S_IFMT) != S_IFREG);
+#else
+    return FALSE;
+#endif
+}
+
+/*
+ * too_much:
+ *	See if the system is being used too much for this game
+ */
+too_much()
+{
+#ifdef MAXLOAD
+    double avec[3];
+    
+    if (md_getloadavg(avec) == 0)
+        if (avec[2] > (MAXLOAD / 10.0))
+	    return(1);
+#endif
+#ifdef MAXUSERS
+    if (md_ucount() > MAXUSERS)
+	return(1) ;
+#endif
+    return(0);
+}
+
+/*
+ * author:
+ *	See if a user is an author of the program
+ */
+author()
+{
+#ifdef WIZARD
+    if (wizard)
+	return TRUE;
+#endif
+    switch (md_getuid())
+    {
+	case 0:
+	    return TRUE;
+	default:
+	    return FALSE;
+    }
+}
+
+/*
+ * checkout:
+ *	Check each CHECKTIME seconds to see if the load is too high
+ */
+void
+checkout(int s)
+{
+    static char *msgs[] = {
+	"The load is too high to be playing.  Please leave in %0.1f minutes",
+	"Please save your game.  You have %0.1f minutes",
+	"Last warning.  You have %0.1f minutes to leave",
+    };
+    int checktime = 0;
+
+#ifdef SIGALRM
+    signal(SIGALRM, checkout);
+#endif
+
+    if (too_much())
+    {
+	if (author())
+	{
+	    num_checks = 1;
+	    chmsg("The load is rather high, O exaulted one");
+	}
+	else if (num_checks++ == 3)
+	    fatal("Sorry.  You took to long.  You are dead\n");
+
+#ifdef CHECKTIME
+	checktime = (CHECKTIME * 60) / num_checks;
+#endif
+#ifdef SIGALRM
+	alarm(checktime);
+#endif
+
+	chmsg(msgs[num_checks - 1], ((double) checktime / 60.0));
+    }
+    else
+    {
+	if (num_checks)
+	{
+	    num_checks = 0;
+	    chmsg("The load has dropped back down.  You have a reprieve");
+	}
+#ifdef CHECKTIME
+#ifdef SIGALRM
+	alarm(CHECKTIME * 60);
+#endif
+#endif
+    }
+}
+
+/*
+ * chmsg:
+ *	checkout()'s version of msg.  If we are in the middle of a
+ *	shell, do a printf instead of a msg to avoid the refresh.
+ */
+chmsg(fmt, arg)
+char *fmt;
+int arg;
+{
+    if (in_shell)
+    {
+	printf(fmt, arg);
+	putchar('\n');
+	fflush(stdout);
+    }
+    else
+	msg(fmt, arg);
+}
+
+/*
+ * lock_sc:
+ *	lock the score file.  If it takes too long, ask the user if
+ *	they care to wait.  Return TRUE if the lock is successful.
+ */
+lock_sc()
+{
+#ifdef SCOREFILE
+#ifdef LOCKFILE
+    register int cnt;
+    static struct stat sbuf;
+
+over:
+    if (creat(lockfile, 0000) > 0)
+	return TRUE;
+    for (cnt = 0; cnt < 5; cnt++)
+    {
+	md_sleep(1);
+	if (creat(lockfile, 0000) > 0)
+	    return TRUE;
+    }
+    if (stat(lockfile, &sbuf) < 0)
+    {
+	creat(lockfile, 0000);
+	return TRUE;
+    }
+    if (time(NULL) - sbuf.st_mtime > 10)
+    {
+	if (md_unlink(lockfile) < 0)
+	    return FALSE;
+	goto over;
+    }
+    else
+    {
+	printf("The score file is very busy.  Do you want to wait longer\n");
+	printf("for it to become free so your score can get posted?\n");
+	printf("If so, type \"y\"\n");
+	fgets(prbuf, MAXSTR, stdin);
+	if (prbuf[0] == 'y')
+	    for (;;)
+	    {
+		if (creat(lockfile, 0000) > 0)
+		    return TRUE;
+		if (stat(lockfile, &sbuf) < 0)
+		{
+		    creat(lockfile, 0000);
+		    return TRUE;
+		}
+		if (time(NULL) - sbuf.st_mtime > 10)
+		{
+		    if (md_unlink(lockfile) < 0)
+			return FALSE;
+		}
+		md_sleep(1);
+	    }
+	else
+	    return FALSE;
+    }
+#endif
+#endif
+}
+
+/*
+ * unlock_sc:
+ *	Unlock the score file
+ */
+unlock_sc()
+{
+#ifdef SCOREFILE
+#ifdef LOCKFILE
+    md_unlink(lockfile);
+#endif
+#endif
+}
+
+/*
+ * flush_type:
+ *	Flush typeahead for traps, etc.
+ */
+flush_type()
+{
+    flushinp();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rogue4/main.c	Sat Oct 24 16:52:52 2009 +0000
@@ -0,0 +1,373 @@
+/*
+ * #     #
+ * #    #   #    #  #   ##  #    #   # 
+ *		         #
+ *
+ * @(#)main.c	4.26 (Berkeley) 2/4/82
+ *
+ * Rogue: Exploring the Dungeons of Doom
+ * Copyright (C) 1980, 1981, 1982 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 <curses.h>
+#include <signal.h>
+#include <limits.h>
+#include <string.h>
+#include "rogue.h"
+
+/*
+ * main:
+ *	The main program, of course
+ */
+main(argc, argv, envp)
+char **argv;
+char **envp;
+{
+    register char *env;
+    int lowtime;
+
+    md_init();
+
+#ifndef DUMP
+#ifdef SIGQUIT
+    signal(SIGQUIT, exit);
+#endif
+    signal(SIGILL, exit);
+#ifdef SIGTRAP
+    signal(SIGTRAP, exit);
+#endif
+#ifdef SIGIOT
+    signal(SIGIOT, exit);
+#endif
+#ifdef SIGEMT
+    signal(SIGEMT, exit);
+#endif
+    signal(SIGFPE, exit);
+#ifdef SIGBUS
+    signal(SIGBUS, exit);
+#endif
+    signal(SIGSEGV, exit);
+#ifdef SIGSYS
+    signal(SIGSYS, exit);
+#endif
+#endif
+
+#ifdef WIZARD
+    /*
+     * Check to see if he is a wizard
+     */
+    if (argc >= 2 && argv[1][0] == '\0')
+	if (strcmp(PASSWD, xcrypt(md_getpass("Wizard's password: "), "mT")) == 0)
+	{
+	    wizard = TRUE;
+	    player.t_flags |= SEEMONST;
+	    argv++;
+	    argc--;
+	}
+#endif
+
+    /*
+     * get home and options from environment
+     */
+    strncpy(home, md_gethomedir(), PATH_MAX);
+    strcpy(file_name, home);
+    strcat(file_name, "rogue52.sav");
+
+    if ((env = getenv("ROGUEOPTS")) != NULL)
+	parse_opts(env);
+    if (env == NULL || whoami[0] == '\0')
+	strucpy(whoami, md_getusername(md_getuid()), strlen(md_getusername(md_getuid())));
+    if (env == NULL || fruit[0] == '\0')
+	strcpy(fruit, "slime-mold");
+
+    /*
+     * check for print-score option
+     */
+    open_score();
+    if (argc == 2 && strcmp(argv[1], "-s") == 0)
+    {
+	noscore = TRUE;
+	score(0, -1);
+	exit(0);
+    }
+    init_check();			/* check for legal startup */
+    if (argc == 2)
+	if (!restore(argv[1], envp))	/* Note: restore will never return */
+	{
+		endwin();
+	    exit(1);
+	}
+    lowtime = (int) time(NULL);
+
+#ifdef WIZARD
+    noscore = wizard;
+#endif
+    if (getenv("SEED") != NULL)
+    {
+	dnum = atoi(getenv("SEED"));
+	noscore = TRUE;
+    }
+    else
+	dnum = lowtime + getpid();
+#ifdef WIZARD
+    if (wizard)
+	printf("Hello %s, welcome to dungeon #%d", whoami, dnum);
+    else
+#endif
+	printf("Hello %s, just a moment while I dig the dungeon...\n\n",whoami);
+    fflush(stdout);
+    seed = dnum;
+
+    init_player();			/* Set up initial player stats */
+    init_things();			/* Set up probabilities of things */
+    init_names();			/* Set up names of scrolls */
+    init_colors();			/* Set up colors of potions */
+    init_stones();			/* Set up stone settings of rings */
+    init_materials();			/* Set up materials of wands */
+
+    initscr();				/* Start up cursor package */
+
+    if (COLS < 70) 
+    { 
+	printf("\n\nSorry, but your terminal window has too few columns.\n");
+        printf("Your terminal has %d columns, needs 70.\n",COLS); 
+        endwin(); 
+        exit(1); 
+	} 
+
+    if (LINES < 22) 
+    { 
+        printf("\n\nSorry, but your terminal window has too few lines.\n"); 
+        printf("Your terminal has %d lines, needs 22.\n",LINES); 
+        endwin(); 
+        exit(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
+     */
+    hw = newwin(LINES, COLS, 0, 0);
+    keypad(stdscr,1);
+    new_level();			/* Draw current level */
+    /*
+     * Start up daemons and fuses
+     */
+    daemon(doctor, 0, AFTER);
+    fuse(swander, 0, WANDERTIME, AFTER);
+    daemon(stomach, 0, AFTER);
+    daemon(runners, 0, AFTER);
+    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\n");
+}
+
+/*
+ * fatal:
+ *	Exit the program, printing a message.
+ */
+fatal(s)
+char *s;
+{
+    clear();
+    move(LINES-2, 0);
+    printw("%s", s);
+    refresh();
+    endwin();
+    (void) exit(0);
+}
+
+/*
+ * rnd:
+ *	Pick a very random number.
+ */
+rnd(range)
+register int range;
+{
+    return range == 0 ? 0 : abs((int) RN) % range;
+}
+
+/*
+ * roll:
+ *	Roll a number of dice
+ */
+roll(number, sides)
+register int number, sides;
+{
+    register int dtotal = 0;
+
+    while (number--)
+	dtotal += rnd(sides)+1;
+    return dtotal;
+}
+
+/*
+ * tstp:
+ *	Handle stop and start signals
+ */
+void
+tstp(int a)
+{
+    register int y, x;
+    register int oy, ox;
+
+    getyx(curscr, oy, ox);
+    mvcur(0, COLS - 1, LINES - 1, 0);
+    endwin();
+    clearok(curscr, TRUE);
+    fflush(stdout);
+#ifdef SIGTSTP
+    signal(SIGTSTP, SIG_DFL);
+    kill(0, SIGTSTP);
+    signal(SIGTSTP, tstp);
+#endif
+    crmode();
+    noecho();
+    clearok(curscr, TRUE);
+    wrefresh(curscr);
+    getyx(curscr, y, x);
+    mvcur(y, x, oy, ox);
+    fflush(stdout);
+    curscr->_cury = oy;
+    curscr->_curx = ox;
+}
+
+/*
+ * playit:
+ *	The main loop of the program.  Loop until the game is over,
+ *	refreshing things and looking at the proper times.
+ */
+playit()
+{
+    register char *opts;
+
+    /*
+     * set up defaults for slow terminals
+     */
+
+    if (baudrate() < 1200)
+    {
+        terse = TRUE;
+        jump = TRUE;
+    }
+
+    /*
+     * parse environment declaration of options
+     */
+    if ((opts = getenv("ROGUEOPTS")) != NULL)
+	parse_opts(opts);
+
+
+    oldpos = hero;
+    oldrp = roomin(&hero);
+    while (playing)
+	command();			/* Command execution */
+    endit(0);
+}
+
+/*
+ * quit:
+ *	Have player make certain, then exit.
+ */
+void
+quit(int a)
+{
+    register int oy, ox;
+
+    /*
+     * Reset the signal in case we got here via an interrupt
+     */
+
+    if (signal(SIGINT, quit) != quit)
+	mpos = 0;
+    getyx(curscr, oy, ox);
+    msg("really quit?");
+    if (readchar() == 'y')
+    {
+	signal(SIGINT, leave);
+	clear();
+	mvprintw(LINES - 2, 0, "You quit with %d gold pieces", purse);
+	move(LINES - 1, 0);
+	refresh();
+	score(purse, 1);
+	exit(0);
+    }
+    else
+    {
+	move(0, 0);
+	clrtoeol();
+	status();
+	move(oy, ox);
+	refresh();
+	mpos = 0;
+	count = 0;
+    }
+}
+
+/*
+ * leave:
+ *	Leave quickly, but curteously
+ */
+void
+leave(int sig)
+{
+/*
+    if (!_endwin)
+    {*/
+	mvcur(0, COLS - 1, LINES - 1, 0);
+	endwin();
+    /* } */
+    putchar('\n');
+    exit(0);
+}
+
+/*
+ * shell:
+ *	Let him escape for a while
+ */
+shell()
+{
+    /*
+     * Set the terminal back to original mode
+     */
+    move(LINES-1, 0);
+    refresh();
+    endwin();
+    putchar('\n');
+    putchar('\n');
+    in_shell = TRUE;
+    after = FALSE;
+
+    md_shellescape();
+
+    noecho();
+    crmode();
+    in_shell = FALSE;
+    clearok(stdscr, TRUE);
+    touchwin(stdscr);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rogue4/mdport.c	Sat Oct 24 16:52:52 2009 +0000
@@ -0,0 +1,1309 @@
+/*
+    mdport.c - Machine Dependent
+
+    Copyright (C) 2005-2008 Nicholas J. Kisseberth
+    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.
+*/
+
+#if defined(_WIN32)
+#include <Windows.h>
+#include <Lmcons.h>
+#include <process.h>
+#include <shlobj.h>
+#include <sys/types.h>
+#include <io.h>
+#include <conio.h>
+#undef MOUSE_MOVED
+#elif defined(__DJGPP__)
+#include <process.h>
+#else
+#include <pwd.h>
+#include <sys/utsname.h>
+#include <unistd.h>
+#include <utmpx.h>
+#endif
+
+#ifdef __INTERIX
+char *strdup(const char *s);
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+
+#if defined(_WIN32) && !defined(__MINGW32__)
+#define PATH_MAX MAX_PATH
+#endif
+
+#include <curses.h>
+#if !defined(DJGPP)
+#include <term.h>
+#endif
+
+#include <stdio.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <sys/stat.h>
+#include <signal.h>
+
+#define MOD_MOVE(c) (toupper(c) )
+
+void
+md_init()
+{
+#ifdef __INTERIX
+    char *term;
+
+    term = getenv("TERM");
+
+    if (term == NULL)
+        setenv("TERM","interix",1);
+#endif
+#if defined(__DJGPP__) || defined(_WIN32)
+    _fmode = _O_BINARY;
+#endif
+#if defined(__CYGWIN__) || defined(__MSYS__)
+    ESCDELAY=250;
+#endif
+}
+
+int
+md_hasclreol()
+{
+#ifdef CE
+    return((CE != NULL) && (*CE != 0));
+#elif defined (clr_eol)
+    return((clr_eol != NULL) && (*clr_eol != 0));
+#elif !defined(__PDCURSES__)
+    return(clr_eol != NULL);
+#else
+    return(TRUE);
+#endif
+}
+
+void
+md_putchar(int c)
+{
+    putchar(c);
+}
+
+static int md_standout_mode = 0;
+
+void
+md_raw_standout()
+{
+#ifdef _WIN32
+    CONSOLE_SCREEN_BUFFER_INFO csbiInfo; 
+    HANDLE hStdout;
+    int fgattr,bgattr;
+
+    if (md_standout_mode == 0)
+    {
+        hStdout = GetStdHandle(STD_OUTPUT_HANDLE); 
+        GetConsoleScreenBufferInfo(hStdout, &csbiInfo);
+        fgattr = (csbiInfo.wAttributes & 0xF);
+        bgattr = (csbiInfo.wAttributes & 0xF0);
+        SetConsoleTextAttribute(hStdout,(fgattr << 4) | (bgattr >> 4));
+        md_standout_mode = 1;
+    }
+#elif defined(SO)
+    tputs(SO,0,md_putchar);
+    fflush(stdout);
+#endif
+}
+
+void
+md_raw_standend()
+{
+#ifdef _WIN32
+    CONSOLE_SCREEN_BUFFER_INFO csbiInfo; 
+    HANDLE hStdout;
+    int fgattr,bgattr;
+
+    if (md_standout_mode == 1)
+    {
+        hStdout = GetStdHandle(STD_OUTPUT_HANDLE); 
+        GetConsoleScreenBufferInfo(hStdout, &csbiInfo);
+        fgattr = (csbiInfo.wAttributes & 0xF);
+        bgattr = (csbiInfo.wAttributes & 0xF0);
+        SetConsoleTextAttribute(hStdout,(fgattr << 4) | (bgattr >> 4));
+        md_standout_mode = 0;
+    }
+#elif defined(SE)
+    tputs(SE,0,md_putchar);
+    fflush(stdout);
+#endif
+}
+
+int
+md_unlink_open_file(char *file, int inf)
+{
+#ifdef _WIN32
+    _close(inf);
+    _chmod(file, 0600);
+    return( _unlink(file) );
+#else
+    return(unlink(file));
+#endif
+}
+
+int
+md_unlink(char *file)
+{
+#ifdef _WIN32
+    _chmod(file, 0600);
+    return( _unlink(file) );
+#else
+    return(unlink(file));
+#endif
+}
+
+FILE *
+md_fdopen(int fd, char *mode)
+{
+#ifdef _WIN32
+    return( _fdopen(fd, mode) );
+#else
+    return( fdopen(fd, mode) );
+#endif
+}
+
+int
+md_fileno(FILE *fp)
+{
+#ifdef _WIN32
+    return( _fileno(fp) );
+#else
+    return( fileno(fp) );
+#endif
+}
+
+int
+md_creat(char *file, int mode)
+{
+    int fd;
+#ifdef _WIN32
+    mode = _S_IREAD | _S_IWRITE;
+    fd = _open(file,O_CREAT | O_EXCL | O_WRONLY, mode);
+#else
+    fd = open(file,O_CREAT | O_EXCL | O_WRONLY, mode);
+#endif
+
+    return(fd);
+}
+
+
+void
+md_normaluser()
+{
+#ifndef _WIN32
+    setuid(getuid());
+    setgid(getgid());
+#endif
+}
+
+int
+md_getuid()
+{
+#ifndef _WIN32
+    return( getuid() );
+#else
+    return(42);
+#endif
+}
+
+char *
+md_getusername(int uid)
+{
+    static char login[80];
+    char *l = NULL;
+
+    /* POSIX Shell has priority, then O/S specific methods */
+    if ( (uid == md_getuid()) && ((l = getenv("LOGNAME")) != NULL) )
+    {
+        strncpy(login,l,80);
+        login[79] = 0;
+        return(login);
+    }
+
+#ifdef _WIN32
+    LPSTR mybuffer;
+    DWORD size = UNLEN + 1;
+    TCHAR buffer[UNLEN + 1];
+
+    mybuffer = buffer;
+    if (uid != md_getuid())
+	strcpy(mybuffer, "someone");
+    else
+	GetUserName(mybuffer,&size);
+    l = mybuffer;
+#endif
+#if !defined(_WIN32) && !defined(DJGPP)
+    struct passwd *pw;
+
+    pw = getpwuid(getuid());
+
+    l = pw->pw_name;
+#endif
+
+    if ((l == NULL) || (*l == '\0'))
+        if ( (l = getenv("USERNAME")) == NULL )
+                if ( (l = getenv("USER")) == NULL )
+                    l = "nobody";
+
+    strncpy(login,l,80);
+    login[79] = 0;
+
+    return(login);
+}
+
+char *
+md_gethomedir()
+{
+    static char homedir[PATH_MAX];
+    char *h = NULL;
+    size_t len;
+#if defined(_WIN32)
+    TCHAR szPath[PATH_MAX];
+#endif
+#if defined(_WIN32) || defined(DJGPP)
+    char slash = '\\';
+#else
+    char slash = '/';
+    struct passwd *pw;
+    pw = getpwuid(getuid());
+
+    h = pw->pw_dir;
+
+    if (strcmp(h,"/") == 0)
+        h = NULL;
+#endif
+    homedir[0] = 0;
+#ifdef _WIN32
+    if(SUCCEEDED(SHGetFolderPath(NULL, CSIDL_PERSONAL, NULL, 0, szPath)))
+        h = szPath;
+#endif
+
+    if ( (h == NULL) || (*h == '\0') )
+        if ( (h = getenv("HOME")) == NULL )
+                h = "";
+
+    strncpy(homedir,h,PATH_MAX-1);
+    len = strlen(homedir);
+
+    if ((len > 0) && (homedir[len-1] == slash))
+	homedir[len-1] = 0;
+
+    return(homedir);
+}
+
+void
+md_sleep(int s)
+{
+#ifdef _WIN32
+    Sleep(s);
+#else
+    sleep(s);
+#endif
+}
+
+char *
+md_getshell()
+{
+    static char shell[PATH_MAX];
+    char *s = NULL;
+#ifdef _WIN32
+    char *def = "C:\\WINDOWS\\SYSTEM32\\CMD.EXE";
+#elif defined(__DJGPP__)
+    char *def = "C:\\COMMAND.COM";
+#else
+    char *def = "/bin/sh";
+    struct passwd *pw;
+    pw = getpwuid(getuid());
+    s = pw->pw_shell;
+#endif
+    if ((s == NULL) || (*s == '\0'))
+        if ( (s = getenv("COMSPEC")) == NULL)
+            if ( (s = getenv("SHELL")) == NULL)
+                if ( (s = getenv("SystemRoot")) == NULL)
+                    s = def;
+
+    strncpy(shell,s,PATH_MAX);
+    shell[PATH_MAX-1] = 0;
+
+    return(shell);
+}
+
+void
+md_ignore_signals()
+{
+#ifndef _WIN32
+    int i;
+    for (i = 0; i < NSIG; i++)
+        signal(i, SIG_IGN);
+#else
+    signal(SIGABRT, SIG_IGN);
+    signal(SIGFPE, SIG_IGN);
+    signal(SIGILL, SIG_IGN);
+    signal(SIGINT, SIG_IGN);
+    signal(SIGSEGV, SIG_IGN);
+    signal(SIGTERM, SIG_IGN);
+#endif
+}
+
+int
+md_shellescape()
+{
+#if (!defined(_WIN32) && !defined(__DJGPP__))
+    int ret_status;
+    int pid;
+    void (*myquit)(int);
+    void (*myend)(int);
+#endif
+    char *sh;
+
+    sh = md_getshell();
+
+#if defined(_WIN32)
+    return((int)_spawnl(_P_WAIT,sh,"shell",NULL,0));
+#elif defined(__DJGPP__)
+    return ( spawnl(P_WAIT,sh,"shell",NULL,0) );
+#else
+    while((pid = fork()) < 0)
+        sleep(1);
+
+    if (pid == 0) /* Shell Process */
+    {
+        /*
+         * Set back to original user, just in case
+         */
+        setuid(getuid());
+        setgid(getgid());
+        execl(sh == NULL ? "/bin/sh" : sh, "shell", "-i", 0);
+        perror("No shelly");
+        _exit(-1);
+    }
+    else /* Application */
+    {
+	myend = signal(SIGINT, SIG_IGN);
+#ifdef SIGQUIT
+        myquit = signal(SIGQUIT, SIG_IGN);
+#endif  
+        while (wait(&ret_status) != pid)
+            continue;
+	    
+        signal(SIGINT, myquit);
+#ifdef SIGQUIT
+        signal(SIGQUIT, myend);
+#endif
+    }
+
+    return(ret_status);
+#endif
+}
+
+char *
+md_getrealname(int uid)
+{
+    static char uidstr[20];
+#if !defined(_WIN32) && !defined(DJGPP)
+    struct passwd *pp;
+
+	if ((pp = getpwuid(uid)) == NULL)
+    {
+        sprintf(uidstr,"%d", uid);
+        return(uidstr);
+    }
+	else
+	    return(pp->pw_name);
+#else
+   sprintf(uidstr,"%d", uid);
+   return(uidstr);
+#endif
+}
+
+extern char *xcrypt(char *key, char *salt);
+
+char *
+md_crypt(char *key, char *salt)
+{
+    return( xcrypt(key,salt) );
+}
+
+char *
+md_getpass(char *prompt)
+{
+#ifdef _WIN32
+    static char password_buffer[9];
+    char *p = password_buffer;
+    int c, count = 0;
+    int max_length = 9;
+
+    fflush(stdout);
+    /* If we can't prompt, abort */
+    if (fputs(prompt, stderr) < 0)
+    {
+        *p = '\0';
+        return NULL;
+    }
+
+    for(;;)
+    {
+        /* Get a character with no echo */
+        c = _getch();
+
+        /* Exit on interrupt (^c or ^break) */
+        if (c == '\003' || c == 0x100)
+            exit(1);
+
+        /* Terminate on end of line or file (^j, ^m, ^d, ^z) */
+        if (c == '\r' || c == '\n' || c == '\004' || c == '\032')
+            break;
+
+        /* Back up on backspace */
+        if (c == '\b')
+        {
+            if (count)
+                count--;
+            else if (p > password_buffer)
+                p--;
+            continue;
+        }
+
+        /* Ignore DOS extended characters */
+        if ((c & 0xff) != c)
+            continue;
+
+        /* Add to password if it isn't full */
+        if (p < password_buffer + max_length - 1)
+            *p++ = c;
+        else
+            count++;
+    }
+   *p = '\0';
+
+   fputc('\n', stderr);
+
+   return password_buffer;
+#else
+   return( (char *) getpass(prompt) );
+#endif
+}
+
+
+int md_endian = 0x01020304;
+
+unsigned long int
+md_ntohl(unsigned long int x)
+{
+#ifdef _WIN32
+    if ( *((char *)&md_endian) == 0x01 )
+        return(x);
+    else
+        return( ((x & 0x000000ffU) << 24) |
+                ((x & 0x0000ff00U) <<  8) |
+                ((x & 0x00ff0000U) >>  8) |
+                ((x & 0xff000000U) >> 24) );
+#else
+    return( ntohl(x) );
+#endif
+}
+
+unsigned long int
+md_htonl(unsigned long int x)
+{
+#ifdef _WIN32
+    if ( *((char *)&md_endian) == 0x01 )
+        return(x);
+    else
+        return( ((x & 0x000000ffU) << 24) |
+                ((x & 0x0000ff00U) <<  8) |
+                ((x & 0x00ff0000U) >>  8) |
+                ((x & 0xff000000U) >> 24) );
+#else
+    return( htonl(x) );
+#endif
+}
+
+int
+md_ucount()
+{
+#ifdef __DJGPP__
+    return(1);
+#elif defined(_WIN32)
+    return(1);
+#else
+    struct utmpx *up=NULL;
+    int count=0;
+
+    setutxent();    
+    do
+    {
+	up = getutxent();
+	if (up && up->ut_type == USER_PROCESS)
+	    count++;
+    } while(up != NULL);
+   
+   endutxent();
+
+   return(count);
+#endif
+}
+
+int
+md_getloadavg(double *avg)
+{
+#if defined(__GLIBC__) || defined(_BSD)
+    if (getloadavg(avg, 3) == -1)
+#endif
+    {
+	avg[0] = avg[1] = avg[2] = 0.0;
+	return -1;
+    }
+}
+
+long
+md_random()
+{
+#ifdef _WIN32
+    return(rand());
+#else
+    return( random() );
+#endif
+}
+
+void
+md_srandom(unsigned x)
+{
+#ifdef _WIN32
+    srand(x);
+#else
+    srandom(x);
+#endif
+}
+
+int
+md_rand()
+{
+#ifdef _WIN32
+    return(rand());
+#else
+    return(lrand48() & 0x7fffffff);
+#endif
+}
+
+void
+md_srand(int seed)
+{
+#ifdef _WIN32
+    srand(seed);
+#else
+    srand48(seed);
+#endif
+}
+
+char *
+md_strdup(const char *s)
+{
+#ifdef _WIN32
+    return( _strdup(s) );
+#else
+    return(strdup(s));
+#endif
+}
+
+long
+md_memused()
+{
+#ifdef _WIN32
+    MEMORYSTATUS stat;
+
+    GlobalMemoryStatus(&stat);
+
+    return((long)stat.dwTotalPageFile);
+#else
+    return( (long)sbrk(0) );
+#endif
+}
+
+char *
+md_gethostname()
+{
+    static char nodename[80];
+    char *n = NULL;
+#if !defined(_WIN32) && !defined(__DJGPP__)
+    struct utsname ourname;
+
+    if (uname(&ourname) == 0)
+        n = ourname.nodename;
+#endif
+    if ((n == NULL) || (*n == '\0'))
+        if ( (n = getenv("COMPUTERNAME")) == NULL)
+            if ( (n = getenv("HOSTNAME")) == NULL)
+                n = "localhost";
+
+    strncpy(nodename, n, 80);
+    nodename[79] = 0;
+
+    return(nodename);
+}
+
+int
+md_erasechar()
+{
+#ifdef BSD
+    return(_tty.sg_erase); /* process erase character */
+#elif defined(USG5_0)
+    return(_tty.c_cc[VERASE]); /* process erase character */
+#else /* USG5_2 .... curses */
+    return( erasechar() ); /* process erase character */
+#endif
+}
+
+int
+md_killchar()
+{
+#ifdef BSD
+    return(_tty.sg_kill);
+#elif defined(USG5_0)
+    return(_tty.c_cc[VKILL]);
+#else /* USG5_2 ..... curses */
+    return( killchar() );
+#endif
+}
+
+/*
+ * unctrl:
+ *	Print a readable version of a certain character
+ */
+
+char *
+md_unctrl(char ch)
+{
+#if USG5_0
+    extern char *_unctrl[];		/* Defined in curses library */
+
+    return _unctrl[ch&0177];
+#else
+    return( (char *) unctrl(ch) );
+#endif
+}
+
+void
+md_flushinp()
+{
+#ifdef BSD
+    ioctl(0, TIOCFLUSH);
+#elif defined(USG5_0)
+    ioctl(_tty_ch,TCFLSH,0)
+#else /* USG5_2.... curses */
+    flushinp();
+#endif
+}
+
+/*
+    Cursor/Keypad Support
+
+    Sadly Cursor/Keypad support is less straightforward than it should be.
+
+    The various terminal emulators/consoles choose to differentiate the
+    cursor and keypad keys (with modifiers) in different ways (if at all!).
+    Furthermore they use different code set sequences for each key only
+    a subset of which the various curses libraries recognize. Partly due
+    to incomplete termcap/terminfo entries and partly due to inherent
+    limitations of those terminal capability databases.
+
+    I give curses first crack at decoding the sequences. If it fails to decode
+    it we check for common ESC-prefixed sequences.
+
+    All cursor/keypad results are translated into standard rogue movement
+    commands.
+
+    Unmodified keys are translated to walk commands: hjklyubn
+    Modified (shift,control,alt) are translated to run commands: HJKLYUBN
+
+    Console and supported (differentiated) keys
+    Interix:  Cursor Keys, Keypad, Ctl-Keypad
+    Cygwin:   Cursor Keys, Keypad, Alt-Cursor Keys
+    MSYS:     Cursor Keys, Keypad, Ctl-Cursor Keys, Ctl-Keypad
+    Win32:    Cursor Keys, Keypad, Ctl/Shift/Alt-Cursor Keys, Ctl/Alt-Keypad
+    DJGPP:    Cursor Keys, Keypad, Ctl/Shift/Alt-Cursor Keys, Ctl/Alt-Keypad
+
+    Interix Console (raw, ncurses)
+    ==============================
+    normal      shift           ctrl        alt
+    ESC [D,     ESC F^,         ESC [D,     ESC [D          /# Left         #/
+    ESC [C,     ESC F$,         ESC [C,     ESC [C          /# Right        #/
+    ESC [A,     ESC F-,         local win,  ESC [A          /# Up           #/
+    ESC [B,     ESC F+,         local win,  ESC [B          /# Down         #/
+    ESC [H,     ESC [H,         ESC [H,     ESC [H          /# Home         #/
+    ESC [S,     local win,      ESC [S,     ESC [S          /# Page Up      #/
+    ESC [T,     local win,      ESC [T,     ESC [T          /# Page Down    #/
+    ESC [U,     ESC [U,         ESC [U,     ESC [U          /# End          #/
+    ESC [D,     ESC F^,         ESC [D,     O               /# Keypad Left  #/
+    ESC [C,     ESC F$,         ESC [C,     O               /# Keypad Right #/
+    ESC [A,     ESC [A,         ESC [-1,    O               /# Keypad Up    #/
+    ESC [B,     ESC [B,         ESC [-2,    O               /# Keypad Down  #/
+    ESC [H,     ESC [H,         ESC [-263,  O               /# Keypad Home  #/
+    ESC [S,     ESC [S,         ESC [-19,   O               /# Keypad PgUp  #/
+    ESC [T,     ESC [T,         ESC [-20,   O               /# Keypad PgDn  #/
+    ESC [U,     ESC [U,         ESC [-21,   O               /# Keypad End   #/
+    nothing,    nothing,        nothing,    O               /# Kaypad 5     #/
+
+    Interix Console (term=interix, ncurses)
+    ==============================
+    KEY_LEFT,   ESC F^,         KEY_LEFT,   KEY_LEFT        /# Left         #/
+    KEY_RIGHT,  ESC F$,         KEY_RIGHT,  KEY_RIGHT       /# Right        #/
+    KEY_UP,     0x146,          local win,  KEY_UP          /# Up           #/
+    KEY_DOWN,   0x145,          local win,  KEY_DOWN        /# Down         #/
+    ESC [H,     ESC [H,         ESC [H,     ESC [H          /# Home         #/
+    KEY_PPAGE,  local win,      KEY_PPAGE,  KEY_PPAGE       /# Page Up      #/
+    KEY_NPAGE,  local win,      KEY_NPAGE,  KEY_NPAGE       /# Page Down    #/
+    KEY_LL,     KEY_LL,         KEY_LL,     KEY_LL          /# End          #/
+    KEY_LEFT,   ESC F^,         ESC [-4,    O               /# Keypad Left  #/
+    KEY_RIGHT,  ESC F$,         ESC [-3,    O               /# Keypad Right #/
+    KEY_UP,     KEY_UP,         ESC [-1,    O               /# Keypad Up    #/
+    KEY_DOWN,   KEY_DOWN,       ESC [-2,    O               /# Keypad Down  #/
+    ESC [H,     ESC [H,         ESC [-263,  O               /# Keypad Home  #/
+    KEY_PPAGE,  KEY_PPAGE,      ESC [-19,   O               /# Keypad PgUp  #/
+    KEY_NPAGE,  KEY_NPAGE,      ESC [-20,   O               /# Keypad PgDn  #/
+    KEY_LL,     KEY_LL,         ESC [-21,   O               /# Keypad End   #/
+    nothing,    nothing,        nothing,    O               /# Keypad 5     #/
+
+    Cygwin Console (raw, ncurses)
+    ==============================
+    normal      shift           ctrl        alt
+    ESC [D,     ESC [D,         ESC [D,     ESC ESC [D      /# Left         #/
+    ESC [C,     ESC [C,         ESC [C,     ESC ESC [C      /# Rght         #/
+    ESC [A,     ESC [A,         ESC [A,     ESC ESC [A      /# Up           #/
+    ESC [B,     ESC [B,         ESC [B,     ESC ESC [B      /# Down         #/
+    ESC [1~,    ESC [1~,        ESC [1~,    ESC ESC [1~     /# Home         #/
+    ESC [5~,    ESC [5~,        ESC [5~,    ESC ESC [5~     /# Page Up      #/
+    ESC [6~,    ESC [6~,        ESC [6~,    ESC ESC [6~     /# Page Down    #/
+    ESC [4~,    ESC [4~,        ESC [4~,    ESC ESC [4~     /# End          #/
+    ESC [D,     ESC [D,         ESC [D,     ESC ESC [D,O    /# Keypad Left  #/
+    ESC [C,     ESC [C,         ESC [C,     ESC ESC [C,O    /# Keypad Right #/
+    ESC [A,     ESC [A,         ESC [A,     ESC ESC [A,O    /# Keypad Up    #/
+    ESC [B,     ESC [B,         ESC [B,     ESC ESC [B,O    /# Keypad Down  #/
+    ESC [1~,    ESC [1~,        ESC [1~,    ESC ESC [1~,O   /# Keypad Home  #/
+    ESC [5~,    ESC [5~,        ESC [5~,    ESC ESC [5~,O   /# Keypad PgUp  #/
+    ESC [6~,    ESC [6~,        ESC [6~,    ESC ESC [6~,O   /# Keypad PgDn  #/
+    ESC [4~,    ESC [4~,        ESC [4~,    ESC ESC [4~,O   /# Keypad End   #/
+    ESC [-71,   nothing,        nothing,    O               /# Keypad 5     #/
+
+    Cygwin Console (term=cygwin, ncurses)
+    ==============================
+    KEY_LEFT,   KEY_LEFT,       KEY_LEFT,   ESC-260         /# Left         #/
+    KEY_RIGHT,  KEY_RIGHT,      KEY_RIGHT,  ESC-261         /# Rght         #/
+    KEY_UP,     KEY_UP,         KEY_UP,     ESC-259         /# Up           #/
+    KEY_DOWN,   KEY_DOWN,       KEY_DOWN,   ESC-258         /# Down         #/
+    KEY_HOME,   KEY_HOME,       KEY_HOME,   ESC-262         /# Home         #/
+    KEY_PPAGE,  KEY_PPAGE,      KEY_PPAGE,  ESC-339         /# Page Up      #/
+    KEY_NPAGE,  KEY_NPAGE,      KEY_NPAGE,  ESC-338         /# Page Down    #/
+    KEY_END,    KEY_END,        KEY_END,    ESC-360         /# End          #/
+    KEY_LEFT,   KEY_LEFT,       KEY_LEFT,   ESC-260,O       /# Keypad Left  #/
+    KEY_RIGHT,  KEY_RIGHT,      KEY_RIGHT,  ESC-261,O       /# Keypad Right #/
+    KEY_UP,     KEY_UP,         KEY_UP,     ESC-259,O       /# Keypad Up    #/
+    KEY_DOWN,   KEY_DOWN,       KEY_DOWN,   ESC-258,O       /# Keypad Down  #/
+    KEY_HOME,   KEY_HOME,       KEY_HOME,   ESC-262,O       /# Keypad Home  #/
+    KEY_PPAGE,  KEY_PPAGE,      KEY_PPAGE,  ESC-339,O       /# Keypad PgUp  #/
+    KEY_NPAGE,  KEY_NPAGE,      KEY_NPAGE,  ESC-338,O       /# Keypad PgDn  #/
+    KEY_END,    KEY_END,        KEY_END,    ESC-360,O       /# Keypad End   #/
+    ESC [G,     nothing,        nothing,    O               /# Keypad 5     #/
+
+    MSYS Console (raw, ncurses)
+    ==============================
+    normal      shift           ctrl        alt
+    ESC OD,     ESC [d,         ESC Od      nothing         /# Left         #/
+    ESC OE,     ESC [e,         ESC Oe,     nothing         /# Right        #/
+    ESC OA,     ESC [a,         ESC Oa,     nothing         /# Up           #/
+    ESC OB,     ESC [b,         ESC Ob,     nothing         /# Down         #/
+    ESC [7~,    ESC [7$,        ESC [7^,    nothing         /# Home         #/
+    ESC [5~,    local window,   ESC [5^,    nothing         /# Page Up      #/
+    ESC [6~,    local window,   ESC [6^,    nothing         /# Page Down    #/
+    ESC [8~,    ESC [8$,        ESC [8^,    nothing         /# End          #/
+    ESC OD,     ESC [d,         ESC Od      O               /# Keypad Left  #/
+    ESC OE,     ESC [c,         ESC Oc,     O               /# Keypad Right #/
+    ESC OA,     ESC [a,         ESC Oa,     O               /# Keypad Up    #/
+    ESC OB,     ESC [b,         ESC Ob,     O               /# Keypad Down  #/
+    ESC [7~,    ESC [7$,        ESC [7^,    O               /# Keypad Home  #/
+    ESC [5~,    local window,   ESC [5^,    O               /# Keypad PgUp  #/
+    ESC [6~,    local window,   ESC [6^,    O               /# Keypad PgDn  #/
+    ESC [8~,    ESC [8$,        ESC [8^,    O               /# Keypad End   #/
+    11,         11,             11,         O               /# Keypad 5     #/
+
+    MSYS Console (term=rxvt, ncurses)
+    ==============================
+    normal      shift           ctrl        alt
+    KEY_LEFT,   KEY_SLEFT,      514         nothing         /# Left         #/
+    KEY_RIGHT,  KEY_SRIGHT,     516,        nothing         /# Right        #/
+    KEY_UP,     518,            519,        nothing         /# Up           #/
+    KEY_DOWN,   511,            512,        nothing         /# Down         #/
+    KEY_HOME,   KEY_SHOME,      ESC [7^,    nothing         /# Home         #/
+    KEY_PPAGE,  local window,   ESC [5^,    nothing         /# Page Up      #/
+    KEY_NPAGE,  local window,   ESC [6^,    nothing         /# Page Down    #/
+    KEY_END,    KEY_SEND,       KEY_EOL,    nothing         /# End          #/
+    KEY_LEFT,   KEY_SLEFT,      514         O               /# Keypad Left  #/
+    KEY_RIGHT,  KEY_SRIGHT,     516,        O               /# Keypad Right #/
+    KEY_UP,     518,            519,        O               /# Keypad Up    #/
+    KEY_DOWN,   511,            512,        O               /# Keypad Down  #/
+    KEY_HOME,   KEY_SHOME,      ESC [7^,    O               /# Keypad Home  #/
+    KEY_PPAGE,  local window,   ESC [5^,    O               /# Keypad PgUp  #/
+    KEY_NPAGE,  local window,   ESC [6^,    O               /# Keypad PgDn  #/
+    KEY_END,    KEY_SEND,       KEY_EOL,    O               /# Keypad End   #/
+    11,         11,             11,         O               /# Keypad 5     #/
+
+    Win32 Console (raw, pdcurses)
+   DJGPP Console (raw, pdcurses)
+   ==============================
+   normal      shift           ctrl        alt
+   260,        391,            443,        493             /# Left         #/
+   261,        400,            444,        492             /# Right        #/
+   259,        547,            480,        490             /# Up           #/
+   258,        548,            481,        491             /# Down         #/
+   262,        388,            447,        524             /# Home         #/
+   339,        396,            445,        526             /# Page Up      #/
+   338,        394,            446,        520             /# Page Down    #/
+   358,        384,            448,        518             /# End          #/
+   452,        52('4'),        511,        521             /# Keypad Left  #/
+   454,        54('6'),        513,        523             /# Keypad Right #/
+   450,        56('8'),        515,        525             /# Keypad Up    #/
+   456,        50('2'),        509,        519             /# Keypad Down  #/
+   449,        55('7'),        514,        524             /# Keypad Home  #/
+   451,        57('9'),        516,        526             /# Keypad PgUp  #/
+   457,        51('3'),        510,        520             /# Keypad PgDn  #/
+   455,        49('1'),        508,        518             /# Keypad End   #/
+   453,        53('5'),        512,        522             /# Keypad 5     #/
+
+   Win32 Console (pdcurses, MSVC/MingW32)
+   DJGPP Console (pdcurses)
+   ==============================
+   normal      shift           ctrl        alt
+   KEY_LEFT,   KEY_SLEFT,      CTL_LEFT,   ALT_LEFT        /# Left         #/
+   KEY_RIGHT,  KEY_SRIGHT,     CTL_RIGHT,  ALT_RIGHT       /# Right        #/
+   KEY_UP,     KEY_SUP,        CTL_UP,     ALT_UP          /# Up           #/
+   KEY_DOWN,   KEY_SDOWN,      CTL_DOWN,   ALT_DOWN        /# Down         #/
+   KEY_HOME,   KEY_SHOME,      CTL_HOME,   ALT_HOME        /# Home         #/
+   KEY_PPAGE,  KEY_SPREVIOUS,  CTL_PGUP,   ALT_PGUP        /# Page Up      #/
+   KEY_NPAGE,  KEY_SNEXTE,     CTL_PGDN,   ALT_PGDN        /# Page Down    #/
+   KEY_END,    KEY_SEND,       CTL_END,    ALT_END         /# End          #/
+   KEY_B1,     52('4'),        CTL_PAD4,   ALT_PAD4        /# Keypad Left  #/
+   KEY_B3,     54('6'),        CTL_PAD6,   ALT_PAD6        /# Keypad Right #/
+   KEY_A2,     56('8'),        CTL_PAD8,   ALT_PAD8        /# Keypad Up    #/
+   KEY_C2,     50('2'),        CTL_PAD2,   ALT_PAD2        /# Keypad Down  #/
+   KEY_A1,     55('7'),        CTL_PAD7,   ALT_PAD7        /# Keypad Home  #/
+   KEY_A3,     57('9'),        CTL_PAD9,   ALT_PAD9        /# Keypad PgUp  #/
+   KEY_C3,     51('3'),        CTL_PAD3,   ALT_PAD3        /# Keypad PgDn  #/
+   KEY_C1,     49('1'),        CTL_PAD1,   ALT_PAD1        /# Keypad End   #/
+   KEY_B2,     53('5'),        CTL_PAD5,   ALT_PAD5        /# Keypad 5     #/
+
+   Windows Telnet (raw)
+   ==============================
+   normal      shift           ctrl        alt
+   ESC [D,     ESC [D,         ESC [D,     ESC [D          /# Left         #/
+   ESC [C,     ESC [C,         ESC [C,     ESC [C          /# Right        #/
+   ESC [A,     ESC [A,         ESC [A,     ESC [A          /# Up           #/
+   ESC [B,     ESC [B,         ESC [B,     ESC [B          /# Down         #/
+   ESC [1~,    ESC [1~,        ESC [1~,    ESC [1~         /# Home         #/
+   ESC [5~,    ESC [5~,        ESC [5~,    ESC [5~         /# Page Up      #/
+   ESC [6~,    ESC [6~,        ESC [6~,    ESC [6~         /# Page Down    #/
+   ESC [4~,    ESC [4~,        ESC [4~,    ESC [4~         /# End          #/
+   ESC [D,     ESC [D,         ESC [D,     ESC [D          /# Keypad Left  #/
+   ESC [C,     ESC [C,         ESC [C,     ESC [C          /# Keypad Right #/
+   ESC [A,     ESC [A,         ESC [A,     ESC [A          /# Keypad Up    #/
+   ESC [B,     ESC [B,         ESC [B,     ESC [B          /# Keypad Down  #/
+   ESC [1~,    ESC [1~,        ESC [1~,    ESC [1~         /# Keypad Home  #/
+   ESC [5~,    ESC [5~,        ESC [5~,    ESC [5~         /# Keypad PgUp  #/
+   ESC [6~,    ESC [6~,        ESC [6~,    ESC [6~         /# Keypad PgDn  #/
+   ESC [4~,    ESC [4~,        ESC [4~,    ESC [4~         /# Keypad End   #/
+   nothing,    nothing,        nothing,    nothing         /# Keypad 5     #/
+
+   Windows Telnet (term=xterm)
+   ==============================
+   normal      shift           ctrl        alt
+   KEY_LEFT,   KEY_LEFT,       KEY_LEFT,   KEY_LEFT        /# Left         #/
+   KEY_RIGHT,  KEY_RIGHT,      KEY_RIGHT,  KEY_RIGHT       /# Right        #/
+   KEY_UP,     KEY_UP,         KEY_UP,     KEY_UP          /# Up           #/
+   KEY_DOWN,   KEY_DOWN,       KEY_DOWN,   KEY_DOWN        /# Down         #/
+   ESC [1~,    ESC [1~,        ESC [1~,    ESC [1~         /# Home         #/
+   KEY_PPAGE,  KEY_PPAGE,      KEY_PPAGE,  KEY_PPAGE       /# Page Up      #/
+   KEY_NPAGE,  KEY_NPAGE,      KEY_NPAGE,  KEY_NPAGE       /# Page Down    #/
+   ESC [4~,    ESC [4~,        ESC [4~,    ESC [4~         /# End          #/
+    KEY_LEFT,   KEY_LEFT,       KEY_LEFT,   O               /# Keypad Left  #/
+    KEY_RIGHT,  KEY_RIGHT,      KEY_RIGHT,  O               /# Keypad Right #/
+    KEY_UP,     KEY_UP,         KEY_UP,     O               /# Keypad Up    #/
+    KEY_DOWN,   KEY_DOWN,       KEY_DOWN,   O               /# Keypad Down  #/
+    ESC [1~,    ESC [1~,        ESC [1~,    ESC [1~         /# Keypad Home  #/
+    KEY_PPAGE,  KEY_PPAGE,      KEY_PPAGE,  KEY_PPAGE       /# Keypad PgUp  #/
+    KEY_NPAGE,  KEY_NPAGE,      KEY_NPAGE,  KEY_NPAGE       /# Keypad PgDn  #/
+    ESC [4~,    ESC [4~,        ESC [4~,    O               /# Keypad End   #/
+    ESC [-71,   nothing,        nothing,    O               /# Keypad 5     #/
+
+    PuTTY
+    ==============================
+    normal      shift           ctrl        alt
+    ESC [D,     ESC [D,         ESC OD,     ESC [D          /# Left         #/
+    ESC [C,     ESC [C,         ESC OC,     ESC [C          /# Right        #/
+    ESC [A,     ESC [A,         ESC OA,     ESC [A          /# Up           #/
+    ESC [B,     ESC [B,         ESC OB,     ESC [B          /# Down         #/
+    ESC [1~,    ESC [1~,        local win,  ESC [1~         /# Home         #/
+    ESC [5~,    local win,      local win,  ESC [5~         /# Page Up      #/
+    ESC [6~,    local win,      local win,  ESC [6~         /# Page Down    #/
+    ESC [4~,    ESC [4~,        local win,  ESC [4~         /# End          #/
+    ESC [D,     ESC [D,         ESC [D,     O               /# Keypad Left  #/
+    ESC [C,     ESC [C,         ESC [C,     O               /# Keypad Right #/
+    ESC [A,     ESC [A,         ESC [A,     O               /# Keypad Up    #/
+    ESC [B,     ESC [B,         ESC [B,     O               /# Keypad Down  #/
+    ESC [1~,    ESC [1~,        ESC [1~,    O               /# Keypad Home  #/
+    ESC [5~,    ESC [5~,        ESC [5~,    O               /# Keypad PgUp  #/
+    ESC [6~,    ESC [6~,        ESC [6~,    O               /# Keypad PgDn  #/
+    ESC [4~,    ESC [4~,        ESC [4~,    O               /# Keypad End   #/
+    nothing,    nothing,        nothing,    O               /# Keypad 5     #/
+
+    PuTTY
+    ==============================
+    normal      shift           ctrl        alt
+    KEY_LEFT,   KEY_LEFT,       ESC OD,     ESC KEY_LEFT    /# Left         #/
+    KEY_RIGHT   KEY_RIGHT,      ESC OC,     ESC KEY_RIGHT   /# Right        #/
+    KEY_UP,     KEY_UP,         ESC OA,     ESC KEY_UP      /# Up           #/
+    KEY_DOWN,   KEY_DOWN,       ESC OB,     ESC KEY_DOWN    /# Down         #/
+    ESC [1~,    ESC [1~,        local win,  ESC ESC [1~     /# Home         #/
+    KEY_PPAGE   local win,      local win,  ESC KEY_PPAGE   /# Page Up      #/
+    KEY_NPAGE   local win,      local win,  ESC KEY_NPAGE   /# Page Down    #/
+    ESC [4~,    ESC [4~,        local win,  ESC ESC [4~     /# End          #/
+    ESC Ot,     ESC Ot,         ESC Ot,     O               /# Keypad Left  #/
+    ESC Ov,     ESC Ov,         ESC Ov,     O               /# Keypad Right #/
+    ESC Ox,     ESC Ox,         ESC Ox,     O               /# Keypad Up    #/
+    ESC Or,     ESC Or,         ESC Or,     O               /# Keypad Down  #/
+    ESC Ow,     ESC Ow,         ESC Ow,     O               /# Keypad Home  #/
+    ESC Oy,     ESC Oy,         ESC Oy,     O               /# Keypad PgUp  #/
+    ESC Os,     ESC Os,         ESC Os,     O               /# Keypad PgDn  #/
+    ESC Oq,     ESC Oq,         ESC Oq,     O               /# Keypad End   #/
+    ESC Ou,     ESC Ou,         ESC Ou,     O               /# Keypad 5     #/
+*/
+
+#define M_NORMAL 0
+#define M_ESC    1
+#define M_KEYPAD 2
+#define M_TRAIL  3
+
+int undo[5];
+int uindex = -1;
+
+int
+reread()
+{
+    int redo;
+
+    if (uindex < 0)
+        return 0;
+
+    redo = undo[0];
+    undo[0] = undo[1];
+    undo[1] = undo[2];
+    undo[2] = undo[3];
+    undo[3] = undo[4];
+    uindex--;
+    return redo;
+}
+
+void
+unread(int c)
+{
+    if (uindex >= 4)
+        abort();
+
+    undo[++uindex] = c;
+}
+
+int
+md_readchar(WINDOW *win)
+{
+    int ch = 0;
+    int lastch = 0;
+    int mode = M_NORMAL;
+    int mode2 = M_NORMAL;
+    int nodelayf = 0;
+    int count = 0;
+
+    for(;;)
+    {
+        if (mode == M_NORMAL && uindex >= 0)
+	{
+	    ch = reread();
+	    break;
+	}
+
+        ch = wgetch(win);
+
+        if (ch == ERR) /* timed out  or error */
+        {
+            if (nodelayf)               /* likely timed out, switch to */
+            {                           /* normal mode and block on    */
+                mode = M_NORMAL;        /* next read                   */
+                nodelayf = 0;
+                nodelay(win,0);
+            }
+            else if (count > 10)        /* after 10 errors assume      */
+                auto_save(0);           /* input stream is broken and  */
+            else                        /* auto save and exit          */
+                count++;
+
+            continue;
+        }
+
+        count = 0;                      /* reset input error count     */
+
+        if (mode == M_TRAIL)
+        {
+            if (ch == '^')              /* msys console  : 7,5,6,8: modified*/
+                ch = MOD_MOVE( toupper(lastch) );
+            else if (ch == '~')              /* cygwin console: 1,5,6,4: normal  */
+                ch = tolower(lastch);   /* windows telnet: 1,5,6,4: normal  */
+                                        /* msys console  : 7,5,6,8: normal  */
+            else if (mode2 == M_ESC)         /* cygwin console: 1,5,6,4: modified*/
+                ch = MOD_MOVE( toupper(ch) );
+	    else
+	    {
+		mode = M_NORMAL;
+		unread(ch);
+		continue;
+            }
+
+            break;
+        }
+
+        if (mode == M_ESC)
+        {
+            if (ch == 27)
+            {
+                mode2 = M_ESC;
+                unread(ch);
+                continue;
+            }
+
+            if ((ch == 'F') || (ch == 'O') || (ch == '['))
+            {
+                mode = M_KEYPAD;
+                unread(ch);
+                continue;
+            }
+
+
+            switch(ch)
+            {
+                /* Cygwin Console   */
+                /* PuTTY            */
+                case KEY_LEFT : ch = MOD_MOVE('H'); break;
+                case KEY_RIGHT: ch = MOD_MOVE('L'); break;
+                case KEY_UP   : ch = MOD_MOVE('K'); break;
+                case KEY_DOWN : ch = MOD_MOVE('J'); break;
+                case KEY_HOME : ch = MOD_MOVE('Y'); break;
+                case KEY_PPAGE: ch = MOD_MOVE('U'); break;
+                case KEY_NPAGE: ch = MOD_MOVE('N'); break;
+                case KEY_END  : ch = MOD_MOVE('B'); break;
+
+                default: mode = M_NORMAL;
+                         mode2 = M_NORMAL;
+                         unread(ch);
+                         continue;
+            }
+
+            break;
+        }
+
+        if (mode == M_KEYPAD)
+        {
+            switch(ch)
+            {
+                /* ESC F - Interix Console codes */
+                case   '^': ch = MOD_MOVE('H'); break;      /* Shift-Left       */
+                case   '$': ch = MOD_MOVE('L'); break;      /* Shift-Right      */
+
+                /* ESC [ - Interix Console codes */
+                case   'H': ch = 'y'; break;            /* Home             */
+                case     1: ch = MOD_MOVE('K'); break;      /* Ctl-Keypad Up    */
+                case     2: ch = MOD_MOVE('J'); break;      /* Ctl-Keypad Down  */
+                case     3: ch = MOD_MOVE('L'); break;      /* Ctl-Keypad Right */
+                case     4: ch = MOD_MOVE('H'); break;      /* Ctl-Keypad Left  */
+                case   263: ch = MOD_MOVE('Y'); break;      /* Ctl-Keypad Home  */
+                case    19: ch = MOD_MOVE('U'); break;      /* Ctl-Keypad PgUp  */
+                case    20: ch = MOD_MOVE('N'); break;      /* Ctl-Keypad PgDn  */
+                case    21: ch = MOD_MOVE('B'); break;      /* Ctl-Keypad End   */
+
+                /* ESC [ - Cygwin Console codes */
+                case   'G': ch = '.'; break;            /* Keypad 5         */
+                case   '7': lastch = 'Y'; mode=M_TRAIL; break;  /* Ctl-Home */
+                case   '5': lastch = 'U'; mode=M_TRAIL; break;  /* Ctl-PgUp */
+                case   '6': lastch = 'N'; mode=M_TRAIL; break;  /* Ctl-PgDn */
+
+                /* ESC [ - Win32 Telnet, PuTTY */
+                case   '1': lastch = 'y'; mode=M_TRAIL; break;  /* Home     */
+                case   '4': lastch = 'b'; mode=M_TRAIL; break;  /* End      */
+
+                /* ESC O - PuTTY */
+                case   'D': ch = MOD_MOVE('H'); break;
+                case   'C': ch = MOD_MOVE('L'); break;
+                case   'A': ch = MOD_MOVE('K'); break;
+                case   'B': ch = MOD_MOVE('J'); break;
+                case   't': ch = 'h'; break;
+                case   'v': ch = 'l'; break;
+                case   'x': ch = 'k'; break;
+                case   'r': ch = 'j'; break;
+                case   'w': ch = 'y'; break;
+                case   'y': ch = 'u'; break;
+                case   's': ch = 'n'; break;
+                case   'q': ch = 'b'; break;
+                case   'u': ch = '.'; break;
+            }
+
+            if (mode != M_KEYPAD)
+	    {
+		unread(ch);
+		continue;
+	    }
+        }
+
+        if (ch == 27)
+        {
+            nodelay(win,1);
+            mode = M_ESC;
+            nodelayf = 1;
+            unread(ch);
+            continue;
+        }
+
+        switch(ch)
+        {
+            case KEY_LEFT   : ch = 'h'; break;
+            case KEY_DOWN   : ch = 'j'; break;
+            case KEY_UP     : ch = 'k'; break;
+            case KEY_RIGHT  : ch = 'l'; break;
+            case KEY_HOME   : ch = 'y'; break;
+            case KEY_PPAGE  : ch = 'u'; break;
+            case KEY_END    : ch = 'b'; break;
+#ifdef KEY_LL
+            case KEY_LL     : ch = 'b'; break;
+#endif
+            case KEY_NPAGE  : ch = 'n'; break;
+
+#ifdef KEY_B1
+            case KEY_B1     : ch = 'h'; break;
+            case KEY_C2     : ch = 'j'; break;
+            case KEY_A2     : ch = 'k'; break;
+            case KEY_B3     : ch = 'l'; break;
+#endif
+            case KEY_A1     : ch = 'y'; break;
+            case KEY_A3     : ch = 'u'; break;
+            case KEY_C1     : ch = 'b'; break;
+            case KEY_C3     : ch = 'n'; break;
+            /* next should be '.', but for problem with putty/linux */
+            case KEY_B2     : ch = 'u'; break;
+
+#ifdef KEY_SLEFT
+            case KEY_SRIGHT  : ch = MOD_MOVE('L'); break;
+            case KEY_SLEFT   : ch = MOD_MOVE('H'); break;
+#ifdef KEY_SUP
+            case KEY_SUP     : ch = MOD_MOVE('K'); break;
+            case KEY_SDOWN   : ch = MOD_MOVE('J'); break;
+#endif
+            case KEY_SHOME   : ch = MOD_MOVE('Y'); break;
+            case KEY_SPREVIOUS:ch = MOD_MOVE('U'); break;
+            case KEY_SEND    : ch = MOD_MOVE('B'); break;
+            case KEY_SNEXT   : ch = MOD_MOVE('N'); break;
+#endif
+            case 0x146       : ch = MOD_MOVE('K'); break;   /* Shift-Up     */
+            case 0x145       : ch = MOD_MOVE('J'); break;   /* Shift-Down   */
+
+#ifdef CTL_RIGHT
+            case CTL_RIGHT   : ch = MOD_MOVE('L'); break;
+            case CTL_LEFT    : ch = MOD_MOVE('H'); break;
+            case CTL_UP      : ch = MOD_MOVE('K'); break;
+            case CTL_DOWN    : ch = MOD_MOVE('J'); break;
+            case CTL_HOME    : ch = MOD_MOVE('Y'); break;
+            case CTL_PGUP    : ch = MOD_MOVE('U'); break;
+            case CTL_END     : ch = MOD_MOVE('B'); break;
+            case CTL_PGDN    : ch = MOD_MOVE('N'); break;
+#endif
+#ifdef KEY_EOL
+            case KEY_EOL     : ch = MOD_MOVE('B'); break;
+#endif
+
+#ifndef CTL_PAD1
+            /* MSYS rxvt console */
+            case 511         : ch = MOD_MOVE('J'); break; /* Shift Dn */
+            case 512         : ch = MOD_MOVE('J'); break; /* Ctl Down */
+            case 514         : ch = MOD_MOVE('H'); break; /* Ctl Left */
+            case 516         : ch = MOD_MOVE('L'); break; /* Ctl Right*/
+            case 518         : ch = MOD_MOVE('K'); break; /* Shift Up */
+            case 519         : ch = MOD_MOVE('K'); break; /* Ctl Up   */
+#endif
+
+#ifdef CTL_PAD1
+            case CTL_PAD1   : ch = MOD_MOVE('B'); break;
+            case CTL_PAD2   : ch = MOD_MOVE('J'); break;
+            case CTL_PAD3   : ch = MOD_MOVE('N'); break;
+            case CTL_PAD4   : ch = MOD_MOVE('H'); break;
+            case CTL_PAD5   : ch = '.'; break;
+            case CTL_PAD6   : ch = MOD_MOVE('L'); break;
+            case CTL_PAD7   : ch = MOD_MOVE('Y'); break;
+            case CTL_PAD8   : ch = MOD_MOVE('K'); break;
+            case CTL_PAD9   : ch = MOD_MOVE('U'); break;
+#endif
+
+#ifdef ALT_RIGHT
+            case ALT_RIGHT  : ch = MOD_MOVE('L'); break;
+            case ALT_LEFT   : ch = MOD_MOVE('H'); break;
+            case ALT_DOWN   : ch = MOD_MOVE('J'); break;
+            case ALT_HOME   : ch = MOD_MOVE('Y'); break;
+            case ALT_PGUP   : ch = MOD_MOVE('U'); break;
+            case ALT_END    : ch = MOD_MOVE('B'); break;
+            case ALT_PGDN   : ch = MOD_MOVE('N'); break;
+#endif
+
+#ifdef ALT_PAD1
+            case ALT_PAD1   : ch = MOD_MOVE('B'); break;
+            case ALT_PAD2   : ch = MOD_MOVE('J'); break;
+            case ALT_PAD3   : ch = MOD_MOVE('N'); break;
+            case ALT_PAD4   : ch = MOD_MOVE('H'); break;
+            case ALT_PAD5   : ch = '.'; break;
+            case ALT_PAD6   : ch = MOD_MOVE('L'); break;
+            case ALT_PAD7   : ch = MOD_MOVE('Y'); break;
+            case ALT_PAD8   : ch = MOD_MOVE('K'); break;
+            case ALT_PAD9   : ch = MOD_MOVE('U'); break;
+#endif
+        }
+
+        break;
+    }
+
+    if (nodelayf)
+        nodelay(win,0);
+
+    uindex = -1;
+
+    return(ch & 0x7F);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rogue4/misc.c	Sat Oct 24 16:52:52 2009 +0000
@@ -0,0 +1,474 @@
+/*
+ * All sorts of miscellaneous routines
+ *
+ * @(#)misc.c	4.30 (Berkeley) 4/6/82
+ *
+ * Rogue: Exploring the Dungeons of Doom
+ * Copyright (C) 1980, 1981, 1982 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 <curses.h>
+#include <ctype.h>
+#include <string.h>
+#include "rogue.h"
+
+/*
+ * tr_name:
+ *	Print the name of a trap
+ */
+char *
+tr_name(type)
+char type;
+{
+    switch (type)
+    {
+	case T_DOOR:
+	    return terse ? "a trapdoor" : "you found a trapdoor";
+	case T_BEAR:
+	    return terse ? "a beartrap" : "you found a beartrap";
+	case T_SLEEP:
+	    return terse ? "a sleeping gas trap":"you found a sleeping gas trap";
+	case T_ARROW:
+	    return terse ? "an arrow trap" : "you found an arrow trap";
+	case T_TELEP:
+	    return terse ? "a teleport trap" : "you found a teleport trap";
+	case T_DART:
+	    return terse ? "a dart trap" : "you found a poison dart trap";
+    }
+    msg("wierd trap: %d", type);
+    return NULL;
+}
+
+/*
+ * look:
+ *	A quick glance all around the player
+ */
+look(wakeup)
+bool wakeup;
+{
+    register int x, y;
+    register unsigned char ch;
+    register int index;
+    register THING *tp;
+    register struct room *rp;
+    register int ey, ex;
+    register int passcount = 0;
+    register char pfl, *fp, pch;
+    register int sy, sx, sumhero = 0, diffhero = 0;
+    register int oldx, oldy;
+
+    getyx(stdscr, oldy, oldx);
+    rp = proom;
+    if (!ce(oldpos, hero))
+    {
+	if ((oldrp->r_flags & (ISGONE|ISDARK)) == ISDARK && !on(player,ISBLIND))
+	{
+	    ey = oldpos.y + 1;
+	    ex = oldpos.x + 1;
+	    sy = oldpos.y - 1;
+	    for (x = oldpos.x - 1; x <= ex; x++)
+		for (y = sy; y <= ey; y++)
+		{
+		    if (y == hero.y && x == hero.x)
+			continue;
+		    move(y, x);
+		    if (inch() == FLOOR)
+			addch(' ');
+		}
+	}
+	oldpos = hero;
+	oldrp = rp;
+    }
+    ey = hero.y + 1;
+    ex = hero.x + 1;
+    sx = hero.x - 1;
+    sy = hero.y - 1;
+    if (door_stop && !firstmove && running)
+    {
+	sumhero = hero.y + hero.x;
+	diffhero = hero.y - hero.x;
+    }
+    index = INDEX(hero.y, hero.x);
+    pfl = _flags[index];
+    pch = _level[index];
+    for (y = sy; y <= ey; y++)
+	if (y > 0 && y < LINES - 1) for (x = sx; x <= ex; x++)
+	{
+	    if (x <= 0 || x >= COLS)
+		continue;
+	    if (!on(player, ISBLIND))
+	    {
+		if (y == hero.y && x == hero.x)
+		    continue;
+	    }
+	    else if (y != hero.y || x != hero.x)
+		continue;
+
+	    index = INDEX(y, x);
+	    /*
+	     * THIS REPLICATES THE moat() MACRO.  IF MOAT IS CHANGED,
+	     * THIS MUST BE CHANGED ALSO
+	     */
+	    fp = &_flags[index];
+	    ch = _level[index];
+	    if (pch != DOOR && ch != DOOR)
+		if ((pfl & F_PASS) != (*fp & F_PASS))
+		    continue;
+		else if ((*fp & F_PASS) && (*fp & F_PNUM) != (pfl & F_PNUM))
+		    continue;
+
+	    if ((tp = _monst[index]) != NULL)
+		if (on(player, SEEMONST) && on(*tp, ISINVIS))
+		{
+		    if (door_stop && !firstmove)
+			running = FALSE;
+		    continue;
+		}
+		else
+		{
+		    if (wakeup)
+			wake_monster(y, x);
+		    if (tp->t_oldch != ' ' ||
+			(!(rp->r_flags & ISDARK) && !on(player, ISBLIND)))
+			    tp->t_oldch = _level[index];
+		    if (see_monst(tp))
+			ch = tp->t_disguise;
+		}
+
+	    move(y, x);
+	    if (ch != inch())
+		addch(ch);
+
+	    if (door_stop && !firstmove && running)
+	    {
+		switch (runch)
+		{
+		    case 'h':
+			if (x == ex)
+			    continue;
+		    when 'j':
+			if (y == sy)
+			    continue;
+		    when 'k':
+			if (y == ey)
+			    continue;
+		    when 'l':
+			if (x == sx)
+			    continue;
+		    when 'y':
+			if ((y + x) - sumhero >= 1)
+			    continue;
+		    when 'u':
+			if ((y - x) - diffhero >= 1)
+			    continue;
+		    when 'n':
+			if ((y + x) - sumhero <= -1)
+			    continue;
+		    when 'b':
+			if ((y - x) - diffhero <= -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++;
+			break;
+		    case FLOOR:
+		    case '|':
+		    case '-':
+		    case ' ':
+			break;
+		    default:
+			running = FALSE;
+			break;
+		}
+	    }
+	}
+    if (door_stop && !firstmove && passcount > 1)
+	running = FALSE;
+    move(hero.y, hero.x);
+    addch(PLAYER);
+}
+
+/*
+ * find_obj:
+ *	Find the unclaimed object at y, x
+ */
+THING *
+find_obj(y, x)
+register int y, x;
+{
+    register THING *op;
+
+    for (op = lvl_obj; op != NULL; op = next(op))
+    {
+	if (op->o_pos.y == y && op->o_pos.x == x)
+		return op;
+    }
+#ifdef WIZARD
+    sprintf(prbuf, "Non-object %d,%d", y, x);
+    debug(prbuf);
+#endif
+    return NULL;
+}
+
+/*
+ * eat:
+ *	She wants to eat something, so let her try
+ */
+eat()
+{
+    register THING *obj;
+
+    if ((obj = get_item("eat", FOOD)) == NULL)
+	return;
+    if (obj->o_type != FOOD)
+    {
+	if (!terse)
+	    msg("ugh, you would get ill if you ate that");
+	else
+	    msg("that's Inedible!");
+	return;
+    }
+    inpack--;
+    
+    if (food_left < 0)
+	food_left = 0;
+    if ((food_left += HUNGERTIME - 200 + rnd(400)) > STOMACHSIZE)
+	food_left = STOMACHSIZE;
+    hungry_state = 0;
+    if (obj == cur_weapon)
+	cur_weapon = NULL;
+    if (obj->o_which == 1)
+	msg("my, that was a yummy %s", fruit);
+    else
+	if (rnd(100) > 70)
+	{
+	    pstats.s_exp++;
+	    msg("yuk, this food tastes awful");
+	    check_level();
+	}
+	else
+	    msg("yum, that tasted good");
+
+	if (--obj->o_count < 1)
+    {
+	detach(pack, obj);
+	discard(obj);
+    }
+}
+
+/*
+ * chg_str:
+ *	Used to modify the playes strength.  It keeps track of the
+ *	highest it has been, just in case
+ */
+chg_str(amt)
+register int amt;
+{
+    str_t comp;
+
+    if (amt == 0)
+	return;
+    add_str(&pstats.s_str, amt);
+    comp = pstats.s_str;
+    if (ISRING(LEFT, R_ADDSTR))
+	add_str(&comp, -cur_ring[LEFT]->o_ac);
+    if (ISRING(RIGHT, R_ADDSTR))
+	add_str(&comp, -cur_ring[RIGHT]->o_ac);
+    if (comp > max_stats.s_str)
+	max_stats.s_str = comp;
+}
+
+/*
+ * add_str:
+ *	Perform the actual add, checking upper and lower bound limits
+ */
+add_str(sp, amt)
+register str_t *sp;
+int amt;
+{
+    if ((*sp += amt) < 3)
+	*sp = 3;
+    else if (*sp > 31)
+	*sp = 31;
+}
+
+/*
+ * add_haste:
+ *	Add a haste to the player
+ */
+add_haste(potion)
+bool potion;
+{
+    if (on(player, ISHASTE))
+    {
+	no_command += rnd(8);
+	player.t_flags &= ~ISRUN;
+	extinguish(nohaste);
+	player.t_flags &= ~ISHASTE;
+	msg("you faint from exhaustion");
+	return FALSE;
+    }
+    else
+    {
+	player.t_flags |= ISHASTE;
+	if (potion)
+	    fuse(nohaste, 0, rnd(4)+4, AFTER);
+	return TRUE;
+    }
+}
+
+/*
+ * aggravate:
+ *	Aggravate all the monsters on this level
+ */
+aggravate()
+{
+    register THING *mi;
+
+    for (mi = mlist; mi != NULL; mi = next(mi))
+	runto(&mi->t_pos, &hero);
+}
+
+/*
+ * vowelstr:
+ *      For printfs: if string starts with a vowel, return "n" for an
+ *	"an".
+ */
+char *
+vowelstr(str)
+register char *str;
+{
+    switch (*str)
+    {
+	case 'a': case 'A':
+	case 'e': case 'E':
+	case 'i': case 'I':
+	case 'o': case 'O':
+	case 'u': case 'U':
+	    return "n";
+	default:
+	    return "";
+    }
+}
+
+/* 
+ * is_current:
+ *	See if the object is one of the currently used items
+ */
+is_current(obj)
+register THING *obj;
+{
+    if (obj == NULL)
+	return FALSE;
+    if (obj == cur_armor || obj == cur_weapon || obj == cur_ring[LEFT]
+	|| obj == cur_ring[RIGHT])
+    {
+	if (!terse)
+	    addmsg("That's already ");
+	msg("in use");
+	return TRUE;
+    }
+    return FALSE;
+}
+
+/*
+ * get_dir:
+ *      Set up the direction co_ordinate for use in varios "prefix"
+ *	commands
+ */
+get_dir()
+{
+    register char *prompt;
+    register bool gotit;
+
+    if (!terse)
+	msg(prompt = "which direction? ");
+    else
+	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 (on(player, ISHUH) && rnd(5) == 0)
+	do
+	{
+	    delta.y = rnd(3) - 1;
+	    delta.x = rnd(3) - 1;
+	} while (delta.y == 0 && delta.x == 0);
+    mpos = 0;
+    return TRUE;
+}
+
+/*
+ * sign:
+ *	Return the sign of the number
+ */
+sign(nm)
+register int nm;
+{
+    if (nm < 0)
+	return -1;
+    else
+	return (nm > 0);
+}
+
+/*
+ * spread:
+ *	Give a spread around a given number (+/- 10%)
+ */
+spread(nm)
+register int nm;
+{
+    return nm - nm / 10 + rnd(nm / 5);
+}
+
+/*
+ * call_it:
+ *	Call an object something after use.
+ */
+call_it(know, guess)
+register bool know;
+register char **guess;
+{
+    if (know && *guess)
+    {
+	free(*guess);
+	*guess = NULL;
+    }
+    else if (!know && askme && *guess == NULL)
+    {
+	msg(terse ? "call it: " : "what do you want to call it? ");
+	if (get_str(prbuf, stdscr) == NORM)
+	{
+	    *guess = malloc((unsigned int) strlen(prbuf) + 1);
+	    strcpy(*guess, prbuf);
+	}
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rogue4/monsters.c	Sat Oct 24 16:52:52 2009 +0000
@@ -0,0 +1,278 @@
+/*
+ * File with various monster functions in it
+ *
+ * @(#)monsters.c	4.24 (Berkeley) 4/6/82
+ *
+ * Rogue: Exploring the Dungeons of Doom
+ * Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman
+ * All rights reserved.
+ *
+ * See the file LICENSE.TXT for full copyright and licensing information.
+ */
+
+#include <curses.h>
+#include <string.h>
+#include <ctype.h>
+#include "rogue.h"
+
+/*
+ * List of monsters in rough order of vorpalness
+ *
+ * NOTE: This not initialized using strings so that xstr doesn't set up
+ * the string not to be saved.  Otherwise genocide is lost through
+ * saving a game.
+ */
+char lvl_mons[] =  {
+    'K', 'J', 'B', 'S', 'H', 'E', 'A', 'O', 'Z', 'G', 'L', 'C', 'R',
+    'Q', 'N', 'Y', 'T', 'W', 'F', 'I', 'X', 'U', 'M', 'V', 'P', 'D',
+    '\0'
+};
+
+char wand_mons[] = {
+    'K', 'J', 'B', 'S', 'H', ' ', 'A', 'O', 'Z', 'G', ' ', 'C', 'R',
+    'Q', ' ', 'Y', 'T', 'W', ' ', 'I', 'X', 'U', ' ', 'V', 'P', ' ',
+    '\0'
+};
+
+/*
+ * randmonster:
+ *	Pick a monster to show up.  The lower the level,
+ *	the meaner the monster.
+ */
+randmonster(wander)
+bool wander;
+{
+    register int d;
+    register char *mons;
+
+    mons = wander ? wand_mons : lvl_mons;
+    do
+    {
+	d = level + (rnd(10) - 5);
+	if (d < 1)
+	    d = rnd(5) + 1;
+	if (d > 26)
+	    d = rnd(5) + 22;
+    } while (mons[--d] == ' ');
+    return mons[d];
+}
+
+/*
+ * new_monster:
+ *	Pick a new monster and add it to the list
+ */
+new_monster(tp, type, cp)
+register THING *tp;
+char type;
+register coord *cp;
+{
+    register struct monster *mp;
+    register int lev_add;
+
+    if ((lev_add = level - AMULETLEVEL) < 0)
+	lev_add = 0;
+    attach(mlist, tp);
+    tp->t_type = type;
+    tp->t_disguise = type;
+    tp->t_pos = *cp;
+    tp->t_oldch = mvinch(cp->y, cp->x);
+    tp->t_room = roomin(cp);
+    moat(cp->y, cp->x) = tp;
+    mp = &monsters[tp->t_type-'A'];
+    tp->t_stats.s_lvl = mp->m_stats.s_lvl + lev_add;
+    tp->t_stats.s_maxhp = tp->t_stats.s_hpt = roll(tp->t_stats.s_lvl, 8);
+    tp->t_stats.s_arm = mp->m_stats.s_arm - lev_add;
+    strncpy(tp->t_stats.s_dmg,mp->m_stats.s_dmg,16);
+    tp->t_stats.s_str = mp->m_stats.s_str;
+    tp->t_stats.s_exp = mp->m_stats.s_exp + lev_add * 10 + exp_add(tp);
+    tp->t_flags = mp->m_flags;
+    tp->t_turn = TRUE;
+    tp->t_pack = NULL;
+    if (ISWEARING(R_AGGR))
+	runto(cp, &hero);
+    if (type == 'M')
+	switch (rnd(level > 25 ? 9 : 8))
+	{
+	    case 0: tp->t_disguise = GOLD;
+	    when 1: tp->t_disguise = POTION;
+	    when 2: tp->t_disguise = SCROLL;
+	    when 3: tp->t_disguise = STAIRS;
+	    when 4: tp->t_disguise = WEAPON;
+	    when 5: tp->t_disguise = ARMOR;
+	    when 6: tp->t_disguise = RING;
+	    when 7: tp->t_disguise = STICK;
+	    when 8: tp->t_disguise = AMULET;
+	}
+}
+
+/*
+ * expadd:
+ *	Experience to add for this monster's level/hit points
+ */
+exp_add(tp)
+register THING *tp;
+{
+    register int mod;
+
+    if (tp->t_stats.s_lvl == 1)
+	mod = tp->t_stats.s_maxhp / 8;
+    else
+	mod = tp->t_stats.s_maxhp / 6;
+    if (tp->t_stats.s_lvl > 9)
+	mod *= 20;
+    else if (tp->t_stats.s_lvl > 6)
+	mod *= 4;
+    return mod;
+}
+
+/*
+ * wanderer:
+ *	Create a new wandering monster and aim it at the player
+ */
+wanderer()
+{
+    register int i;
+    register struct room *rp;
+    register THING *tp;
+    coord cp = {0,0};
+    register int cnt = 0;
+
+    tp = new_item();
+    do
+    {
+        /* Avoid endless loop when all rooms are filled with monsters
+	 * and the player room is not accessible to the monsters.
+	 */
+	if (cnt++ >= 500)
+	{
+	    discard(tp);
+	    return;
+	}
+	i = rnd_room();
+	if ((rp = &rooms[i]) == proom)
+	    continue;
+	rnd_pos(rp, &cp);
+    } until (rp != proom && step_ok(winat(cp.y, cp.x)));
+    new_monster(tp, randmonster(TRUE), &cp);
+    runto(&tp->t_pos, &hero);
+#ifdef WIZARD
+    if (wizard)
+	msg("started a wandering %s", monsters[tp->t_type-'A'].m_name);
+#endif
+}
+
+/*
+ * wake_monster:
+ *	What to do when the hero steps next to a monster
+ */
+THING *
+wake_monster(y, x)
+int y, x;
+{
+    register THING *tp;
+    register struct room *rp;
+    register char ch;
+
+#ifdef WIZARD
+    if ((tp = moat(y, x)) == NULL)
+	msg("can't find monster in wake_monster");
+#else
+    tp = moat(y, x);
+#endif
+    ch = tp->t_type;
+    /*
+     * Every time he sees mean monster, it might start chasing him
+     */
+    if (!on(*tp, ISRUN) && rnd(3) != 0 && on(*tp, ISMEAN) && !on(*tp, ISHELD)
+	&& !ISWEARING(R_STEALTH))
+    {
+	tp->t_dest = &hero;
+	tp->t_flags |= ISRUN;
+    }
+    if (ch == 'U' && !on(player, ISBLIND) && !on(*tp, ISFOUND)
+	&& !on(*tp, ISCANC) && on(*tp, ISRUN))
+    {
+        rp = proom;
+	if ((rp != NULL && !(rp->r_flags & ISDARK))
+	    || DISTANCE(y, x, hero.y, hero.x) < LAMPDIST)
+	{
+	    tp->t_flags |= ISFOUND;
+	    if (!save(VS_MAGIC))
+	    {
+		if (on(player, ISHUH))
+		    lengthen(unconfuse, rnd(20) + HUHDURATION);
+		else
+		    fuse(unconfuse, 0, rnd(20) + HUHDURATION, AFTER);
+		player.t_flags |= ISHUH;
+		msg("the umber hulk's gaze has confused you");
+	    }
+	}
+    }
+    /*
+     * Let greedy ones guard gold
+     */
+    if (on(*tp, ISGREED) && !on(*tp, ISRUN))
+    {
+	tp->t_flags |= ISRUN;
+	if (proom->r_goldval)
+	    tp->t_dest = &proom->r_gold;
+	else
+	    tp->t_dest = &hero;
+    }
+    return tp;
+}
+
+/*
+ * genocide:
+ *	Wipe one monster out of existence (for now...)
+ */
+genocide()
+{
+    register THING *mp;
+    register char c;
+    register int i;
+    register THING *nmp;
+
+    addmsg("which monster");
+    if (!terse)
+	addmsg(" do you wish to wipe out");
+    msg("? ");
+    while (!isalpha(c = readchar()))
+	if (c == ESCAPE)
+	    return;
+	else
+	{
+	    mpos = 0;
+	    msg("please specifiy a letter between 'A' and 'Z'");
+	}
+    mpos = 0;
+    if (islower(c))
+	c = toupper(c);
+    for (mp = mlist; mp; mp = nmp)
+    {
+	nmp = next(mp);
+	if (mp->t_type == c)
+	    remove_monster(&mp->t_pos, mp, FALSE);
+    }
+    for (i = 0; i < 26; i++)
+	if (lvl_mons[i] == c)
+	{
+	    lvl_mons[i] = ' ';
+	    wand_mons[i] = ' ';
+	    break;
+	}
+    if (!terse)
+	addmsg("there will be ");
+    msg("no more %ss", monsters[c - 'A'].m_name);
+}
+
+/*
+ * give_pack:
+ *	Give a pack to a monster if it deserves one
+ */
+give_pack(tp)
+register THING *tp;
+{
+    if (rnd(100) < monsters[tp->t_type-'A'].m_carry)
+	attach(tp->t_pack, new_thing());
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rogue4/move.c	Sat Oct 24 16:52:52 2009 +0000
@@ -0,0 +1,358 @@
+/*
+ * Hero movement commands
+ *
+ * @(#)move.c	4.24 (Berkeley) 5/12/82
+ *
+ * Rogue: Exploring the Dungeons of Doom
+ * Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman
+ * All rights reserved.
+ *
+ * See the file LICENSE.TXT for full copyright and licensing information.
+ */
+
+#include <curses.h>
+#include <ctype.h>
+#include "rogue.h"
+
+/*
+ * Used to hold the new hero position
+ */
+
+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;
+{
+    register char ch, fl;
+
+    firstmove = FALSE;
+    if (no_move)
+    {
+	no_move--;
+	msg("you are still stuck in the bear trap");
+	return;
+    }
+    /*
+     * Do a confused move (maybe)
+     */
+    if (on(player, ISHUH) && rnd(5) != 0)
+    {
+	nh = *rndmove(&player);
+	if (ce(nh, hero))
+	{
+	    after = FALSE;
+	    running = FALSE;
+	    return;
+	}
+    }
+    else
+    {
+over:
+	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 (nh.x < 0 || nh.x > COLS-1 || nh.y < 1 || nh.y > LINES - 2)
+	goto hit_bound;
+    if (!diag_ok(&hero, &nh))
+    {
+	after = FALSE;
+	running = FALSE;
+	return;
+    }
+    if (running && ce(hero, nh))
+	after = running = FALSE;
+    fl = flat(nh.y, nh.x);
+    ch = winat(nh.y, nh.x);
+    if (!(fl & F_REAL) && ch == FLOOR)
+    {
+	chat(nh.y, nh.x) = ch = TRAP;
+	flat(nh.y, nh.x) |= F_REAL;
+    }
+    else
+    if (on(player, ISHELD) && ch != 'F')
+    {
+	msg("you are being held");
+	return;
+    }
+    switch (ch)
+    {
+	case ' ':
+	case '|':
+	case '-':
+hit_bound:
+	    if (passgo && running && (proom->r_flags & ISGONE)
+		&& !on(player, ISBLIND))
+	    {
+		register bool	b1, b2;
+
+		switch (runch)
+		{
+		    case 'h':
+		    case 'l':
+			b1 = (((flat(hero.y - 1, hero.x) & F_PASS) || chat(hero.y - 1, hero.x) == DOOR) && hero.y != 1);
+			b2 = (((flat(hero.y + 1, hero.x) & F_PASS) || chat(hero.y + 1, hero.x) == DOOR) && hero.y != LINES - 2);
+			if (!(b1 ^ b2))
+			    break;
+			if (b1)
+			{
+			    runch = 'k';
+			    dy = -1;
+			}
+			else
+			{
+			    runch = 'j';
+			    dy = 1;
+			}
+			dx = 0;
+			turnref();
+			goto over;
+		    case 'j':
+		    case 'k':
+			b1 = (((flat(hero.y, hero.x - 1) & F_PASS) || chat(hero.y, hero.x - 1) == DOOR) && hero.x != 0);
+			b2 = (((flat(hero.y, hero.x + 1) & F_PASS) || chat(hero.y, hero.x + 1) == DOOR) && hero.x != COLS - 1);
+			if (!(b1 ^ b2))
+			    break;
+			if (b1)
+			{
+			    runch = 'h';
+			    dx = -1;
+			}
+			else
+			{
+			    runch = 'l';
+			    dx = 1;
+			}
+			dy = 0;
+			turnref();
+			goto over;
+		}
+	    }
+	    after = running = FALSE;
+	    break;
+	case DOOR:
+	    running = FALSE;
+	    if (flat(hero.y, hero.x) & F_PASS)
+		enter_room(&nh);
+	    goto move_stuff;
+	case TRAP:
+	    ch = be_trapped(&nh);
+	    if (ch == T_DOOR || ch == T_TELEP)
+		return;
+	    goto move_stuff;
+	case PASSAGE:
+	    goto move_stuff;
+	case FLOOR:
+	    if (!(fl & F_REAL))
+		be_trapped(&hero);
+	    goto move_stuff;
+	default:
+	    running = FALSE;
+	    if (isupper(ch) || moat(nh.y, nh.x))
+		fight(&nh, ch, cur_weapon, FALSE);
+	    else
+	    {
+		running = FALSE;
+		if (ch != STAIRS)
+		    take = ch;
+move_stuff:
+		mvaddch(hero.y, hero.x, chat(hero.y, hero.x));
+		if ((fl & F_PASS) && chat(oldpos.y, oldpos.x) == DOOR)
+		    leave_room(&nh);
+		hero = nh;
+	    }
+    }
+}
+
+/*
+ * turnref:
+ *	Decide whether to refresh at a passage turning or not
+ */
+turnref()
+{
+    register int index;
+
+    index = INDEX(hero.y, hero.x);
+    if (!(_flags[index] & F_SEEN))
+    {
+	if (jump)
+	{
+	    leaveok(stdscr, TRUE);
+	    refresh();
+	    leaveok(stdscr, FALSE);
+	}
+	_flags[index] |= F_SEEN;
+    }
+}
+
+/*
+ * door_open:
+ *	Called to illuminate a room.  If it is dark, remove anything
+ *	that might move.
+ */
+door_open(rp)
+struct room *rp;
+{
+    register int j, k;
+    register char ch;
+    register THING *item;
+
+    if (!(rp->r_flags & ISGONE) && !on(player, ISBLIND))
+	for (j = rp->r_pos.y; j < rp->r_pos.y + rp->r_max.y; j++)
+	    for (k = rp->r_pos.x; k < rp->r_pos.x + rp->r_max.x; k++)
+	    {
+		ch = winat(j, k);
+		move(j, k);
+		if (isupper(ch))
+		{
+		    item = wake_monster(j, k);
+		    if (item->t_oldch == ' ' && !(rp->r_flags & ISDARK)
+			&& !on(player, ISBLIND))
+			    item->t_oldch = chat(j, k);
+		}
+	    }
+}
+
+/*
+ * be_trapped:
+ *	The guy stepped on a trap.... Make him pay.
+ */
+be_trapped(tc)
+register coord *tc;
+{
+    register char tr;
+    register int index;
+
+    count = running = FALSE;
+    index = INDEX(tc->y, tc->x);
+    _level[index] = TRAP;
+    tr = _flags[index] & F_TMASK;
+    switch (tr)
+    {
+	case T_DOOR:
+	    level++;
+	    new_level();
+	    msg("you fell into a trap!");
+	when T_BEAR:
+	    no_move += BEARTIME;
+	    msg("you are caught in a bear trap");
+	when T_SLEEP:
+	    no_command += SLEEPTIME;
+	    player.t_flags &= ~ISRUN;
+	    msg("a strange white mist envelops you and you fall asleep");
+	when T_ARROW:
+	    if (swing(pstats.s_lvl-1, pstats.s_arm, 1))
+	    {
+		pstats.s_hpt -= roll(1, 6);
+		if (pstats.s_hpt <= 0)
+		{
+		    msg("an arrow killed you");
+		    death('a');
+		}
+		else
+		    msg("oh no! An arrow shot you");
+	    }
+	    else
+	    {
+		register THING *arrow;
+
+		arrow = new_item();
+		arrow->o_type = WEAPON;
+		arrow->o_which = ARROW;
+		init_weapon(arrow, ARROW);
+		arrow->o_count = 1;
+		arrow->o_pos = hero;
+		arrow->o_hplus = arrow->o_dplus = 0;
+		fall(arrow, FALSE);
+		msg("an arrow shoots past you");
+	    }
+	when T_TELEP:
+	    teleport();
+	    mvaddch(tc->y, tc->x, TRAP); /* since the hero's leaving, look()
+					    won't put it on for us */
+	when T_DART:
+	    if (swing(pstats.s_lvl+1, pstats.s_arm, 1))
+	    {
+		pstats.s_hpt -= roll(1, 4);
+		if (pstats.s_hpt <= 0)
+		{
+		    msg("a poisoned dart killed you");
+		    death('d');
+		}
+		if (!ISWEARING(R_SUSTSTR) && !save(VS_POISON))
+		    chg_str(-1);
+		msg("a small dart just hit you in the shoulder");
+	    }
+	    else
+		msg("a small dart whizzes by your ear and vanishes");
+    }
+    flush_type();
+    return tr;
+}
+
+/*
+ * rndmove:
+ *	Move in a random direction if the monster/person is confused
+ */
+coord *
+rndmove(who)
+THING *who;
+{
+    register int x, y;
+    register char ch;
+    register THING *obj;
+    static coord ret;  /* what we will be returning */
+
+    y = ret.y = who->t_pos.y + rnd(3) - 1;
+    x = ret.x = who->t_pos.x + rnd(3) - 1;
+    /*
+     * Now check to see if that's a legal move.  If not, don't move.
+     * (I.e., bump into the wall or whatever)
+     */
+    if (y == who->t_pos.y && x == who->t_pos.x)
+	return &ret;
+    if ((y < 0 || y >= LINES - 1) || (x < 0 || x >= COLS))
+	goto bad;
+    else if (!diag_ok(&who->t_pos, &ret))
+	goto bad;
+    else
+    {
+	ch = winat(y, x);
+	if (!step_ok(ch))
+	    goto bad;
+	if (ch == SCROLL)
+	{
+	    for (obj = lvl_obj; obj != NULL; obj = next(obj))
+		if (y == obj->o_pos.y && x == obj->o_pos.x)
+		    break;
+	    if (obj != NULL && obj->o_which == S_SCARE)
+		goto bad;
+	}
+    }
+    return &ret;
+
+bad:
+    ret = who->t_pos;
+    return &ret;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rogue4/new_level.c	Sat Oct 24 16:52:52 2009 +0000
@@ -0,0 +1,254 @@
+/*
+ * new_level:
+ *	Dig and draw a new level
+ *
+ * @(#)new_level.c	4.19 (Berkeley) 1/12/82
+ *
+ * Rogue: Exploring the Dungeons of Doom
+ * Copyright (C) 1980, 1981, 1982 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 <curses.h>
+#include <string.h>
+#include "rogue.h"
+
+#define TREAS_ROOM 20	/* one chance in TREAS_ROOM for a treasure room */
+#define MAXTREAS 10	/* maximum number of treasures in a treasure room */
+#define MINTREAS 2	/* minimum number of treasures in a treasure room */
+
+new_level()
+{
+    register int rm, i;
+    register THING *tp;
+    register char *sp;
+    register THING **mp;
+    register int index;
+    coord stairs;
+
+    player.t_flags &= ~ISHELD;	/* unhold when you go down just in case */
+    if (level > max_level)
+	max_level = level;
+    /*
+     * Clean things off from last level
+     */
+    clear();
+    for (sp = _level; sp < &_level[MAXCOLS*MAXLINES]; )
+	*sp++ = ' ';
+    for (sp = _flags; sp < &_flags[MAXCOLS*MAXLINES]; )
+	*sp++ = F_REAL;
+    for (mp = _monst; mp < &_monst[MAXCOLS*MAXLINES]; )
+	*mp++ = NULL;
+    clear();
+    /*
+     * Free up the monsters on the last level
+     */
+    for (tp = mlist; tp != NULL; tp = next(tp))
+	free_list(tp->t_pack);
+    free_list(mlist);
+    /*
+     * Throw away stuff left on the previous level (if anything)
+     */
+    free_list(lvl_obj);
+    do_rooms();				/* Draw rooms */
+    do_passages();			/* Draw passages */
+    no_food++;
+    put_things();			/* Place objects (if any) */
+    /*
+     * Place the staircase down.
+     */
+    i = 0;
+    do {
+        rm = rnd_room();
+	rnd_pos(&rooms[rm], &stairs);
+	index = INDEX(stairs.y, stairs.x);
+	if (i++ > 100)
+	{
+	    i = 0;
+	    srand(getpid() + (int) time((time_t *) NULL));
+	}
+    } until (_level[index] == FLOOR);
+    _level[index] = STAIRS;
+    /*
+     * Place the traps
+     */
+    if (rnd(10) < level)
+    {
+	ntraps = rnd(level / 4) + 1;
+	if (ntraps > MAXTRAPS)
+	    ntraps = MAXTRAPS;
+	i = ntraps;
+	while (i--)
+	{
+	    do
+	    {
+		rm = rnd_room();
+		rnd_pos(&rooms[rm], &stairs);
+		index = INDEX(stairs.y, stairs.x);
+	    } until (_level[index] == FLOOR && (_flags[index] & F_REAL));
+	    sp = &_flags[index];
+	    *sp &= ~(F_REAL | F_TMASK);
+	    *sp |= rnd(NTRAPS);
+	}
+    }
+    do
+    {
+	rm = rnd_room();
+	rnd_pos(&rooms[rm], &hero);
+	index = INDEX(hero.y, hero.x);
+    } until (_level[index] == FLOOR && (_flags[index] & F_REAL)
+	&& _monst[index] == NULL);
+    enter_room(&hero);
+    move(hero.y, hero.x);
+    addch(PLAYER);
+    if (on(player, SEEMONST))
+	turn_see(FALSE);
+}
+
+/*
+ * rnd_room:
+ *	Pick a room that is really there
+ */
+rnd_room()
+{
+    register int rm;
+
+    do
+    {
+	rm = rnd(MAXROOMS);
+    } while (rooms[rm].r_flags & ISGONE);
+    return rm;
+}
+
+/*
+ * put_things:
+ *	Put potions and scrolls on this level
+ */
+put_things()
+{
+    register int i;
+    register THING *cur;
+    register int rm;
+    coord tp;
+
+    /*
+     * Once you have found the amulet, the only way to get new stuff is
+     * go down into the dungeon.
+     */
+    if (amulet && level < max_level)
+	return;
+    /*
+     * check for treasure rooms, and if so, put it in.
+     */
+    if (rnd(TREAS_ROOM) == 0)
+	treas_room();
+    /*
+     * Do MAXOBJ attempts to put things on a level
+     */
+    for (i = 0; i < MAXOBJ; i++)
+	if (rnd(100) < 35)
+	{
+	    /*
+	     * Pick a new object and link it in the list
+	     */
+	    cur = new_thing();
+	    attach(lvl_obj, cur);
+	    /*
+	     * Put it somewhere
+	     */
+	    do {
+	        rm = rnd_room();
+		rnd_pos(&rooms[rm], &tp);
+	    } until (chat(tp.y, tp.x) == FLOOR);
+	    chat(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 >= AMULETLEVEL && !amulet)
+    {
+	cur = new_item();
+	attach(lvl_obj, cur);
+	cur->o_hplus = cur->o_dplus = 0;
+	strcpy(cur->o_damage,"0d0");
+	strcpy(cur->o_hurldmg,"0d0");
+	cur->o_ac = 11;
+	cur->o_type = AMULET;
+	/*
+	 * Put it somewhere
+	 */
+	do {
+	    rm = rnd_room();
+	    rnd_pos(&rooms[rm], &tp);
+	} until (winat(tp.y, tp.x) == FLOOR);
+	chat(tp.y, tp.x) = AMULET;
+	cur->o_pos = tp;
+    }
+}
+
+/*
+ * treas_room:
+ *	Add a treasure room
+ */
+#define MAXTRIES 10	/* max number of tries to put down a monster */
+
+treas_room()
+{
+    register int nm, index;
+    register THING *tp;
+    register struct room *rp;
+    register int spots, num_monst;
+    coord mp;
+
+    rp = &rooms[rnd_room()];
+    spots = (rp->r_max.y - 2) * (rp->r_max.x - 2) - MINTREAS;
+    if (spots > (MAXTREAS - MINTREAS))
+	spots = (MAXTREAS - MINTREAS);
+    num_monst = nm = rnd(spots) + MINTREAS;
+    while (nm--)
+    {
+	do
+	{
+	    rnd_pos(rp, &mp);
+	    index = INDEX(mp.y, mp.x);
+	} until (_level[index] == FLOOR);
+	tp = new_thing();
+	tp->o_pos = mp;
+	attach(lvl_obj, tp);
+	_level[index] = tp->o_type;
+    }
+
+    /*
+     * fill up room with monsters from the next level down
+     */
+
+    if ((nm = rnd(spots) + MINTREAS) < num_monst + 2)
+	nm = num_monst + 2;
+    spots = (rp->r_max.y - 2) * (rp->r_max.x - 2);
+    if (nm > spots)
+	nm = spots;
+    level++;
+    while (nm--)
+    {
+	spots = 0;
+	do
+	{
+	    rnd_pos(rp, &mp);
+	    index = INDEX(mp.y, mp.x);
+	    spots++;
+	} until (_monst[index] == NULL || spots > MAXTRIES);
+	if (_monst[index] == NULL)
+	{
+	    tp = new_item();
+	    new_monster(tp, randmonster(FALSE), &mp);
+	    tp->t_flags |= ISMEAN;	/* no sloughers in THIS room */
+	    give_pack(tp);
+	}
+    }
+    level--;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rogue4/options.c	Sat Oct 24 16:52:52 2009 +0000
@@ -0,0 +1,370 @@
+/*
+ * This file has all the code for the option command.  I would rather
+ * this command were not necessary, but it is the only way to keep the
+ * wolves off of my back.
+ *
+ * @(#)options.c	4.12 (Berkeley) 3/2/82
+ *
+ * Rogue: Exploring the Dungeons of Doom
+ * Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman
+ * All rights reserved.
+ *
+ * See the file LICENSE.TXT for full copyright and licensing information.
+ */
+
+#include <curses.h>
+#include <ctype.h>
+#include <string.h>
+#include "rogue.h"
+
+#define	EQSTR(a, b, c)	(strncmp(a, b, c) == 0)
+
+#define	NUM_OPTS	(sizeof optlist / sizeof (OPTION))
+
+/*
+ * description of an option and what to do with it
+ */
+struct optstruct {
+    char	*o_name;	/* option name */
+    char	*o_prompt;	/* prompt for interactive entry */
+    int		*o_opt;		/* pointer to thing to set */
+    int		(*o_putfunc)();	/* function to print value */
+    int		(*o_getfunc)();	/* function to get value interactively */
+};
+
+typedef struct optstruct	OPTION;
+
+int	put_bool(), get_bool(), put_str(), get_str();
+
+OPTION	optlist[] = {
+    {"terse",	 "Terse output: ",
+		 (int *) &terse,	put_bool,	get_bool	},
+    {"flush",	 "Flush typeahead during battle: ",
+		(int *) &fight_flush,	put_bool,	get_bool	},
+    {"jump",	 "Show position only at end of run: ",
+		(int *) &jump,		put_bool,	get_bool	},
+    {"step",	"Do inventories one line at a time: ",
+		(int *) &slow_invent,	put_bool,	get_bool	},
+    {"askme",	"Ask me about unidentified things: ",
+		(int *) &askme,		put_bool,	get_bool	},
+    {"passgo",	"Follow turnings in passageways: ",
+		(int *) &passgo,	put_bool,	get_bool	},
+    {"name",	 "Name: ",
+		(int *) whoami,		put_str,	get_str		},
+    {"fruit",	 "Fruit: ",
+		(int *) fruit,		put_str,	get_str		},
+    {"file",	 "Save file: ",
+		(int *) file_name,	put_str,	get_str		}
+};
+
+/*
+ * option:
+ *	Print and then set options from the terminal
+ */
+option()
+{
+    register OPTION	*op;
+    register int	retval;
+
+    wclear(hw);
+    /*
+     * Display current values of options
+     */
+    for (op = optlist; op < &optlist[NUM_OPTS]; op++)
+    {
+	waddstr(hw, op->o_prompt);
+	(*op->o_putfunc)(op->o_opt);
+	waddch(hw, '\n');
+    }
+    /*
+     * Set values
+     */
+    wmove(hw, 0, 0);
+    for (op = optlist; op < &optlist[NUM_OPTS]; op++)
+    {
+	waddstr(hw, op->o_prompt);
+	if ((retval = (*op->o_getfunc)(op->o_opt, hw)))
+	    if (retval == QUIT)
+		break;
+	    else if (op > optlist) {	/* MINUS */
+		wmove(hw, (op - optlist) - 1, 0);
+		op -= 2;
+	    }
+	    else	/* trying to back up beyond the top */
+	    {
+		putchar('\007');
+		wmove(hw, 0, 0);
+		op--;
+	    }
+    }
+    /*
+     * Switch back to original screen
+     */
+    mvwaddstr(hw, LINES-1, 0, "--Press space to continue--");
+    wrefresh(hw);
+    wait_for(' ');
+    clearok(curscr, TRUE);
+    touchwin(stdscr);
+    after = FALSE;
+}
+
+/*
+ * put_bool
+ *	Put out a boolean
+ */
+put_bool(b)
+bool	*b;
+{
+    waddstr(hw, *b ? "True" : "False");
+}
+
+/*
+ * put_str:
+ *	Put out a string
+ */
+put_str(str)
+char *str;
+{
+    waddstr(hw, str);
+}
+
+/*
+ * get_bool:
+ *	Allow changing a boolean option and print it out
+ */
+get_bool(bp, win)
+bool *bp;
+WINDOW *win;
+{
+    register int oy, ox;
+    register bool op_bad;
+
+    op_bad = TRUE;
+    getyx(win, oy, ox);
+    waddstr(win, *bp ? "True" : "False");
+    while (op_bad)	
+    {
+	wmove(win, oy, ox);
+	wrefresh(win);
+	switch (readcharw(win))
+	{
+	    case 't':
+	    case 'T':
+		*bp = TRUE;
+		op_bad = FALSE;
+		break;
+	    case 'f':
+	    case 'F':
+		*bp = FALSE;
+		op_bad = FALSE;
+		break;
+	    case '\n':
+	    case '\r':
+		op_bad = FALSE;
+		break;
+	    case '\033':
+	    case '\007':
+		return QUIT;
+	    case '-':
+		return MINUS;
+	    default:
+		mvwaddstr(win, oy, ox + 10, "(T or F)");
+	}
+    }
+    wmove(win, oy, ox);
+    waddstr(win, *bp ? "True" : "False");
+    waddch(win, '\n');
+    return NORM;
+}
+
+/*
+ * get_str:
+ *	Set a string option
+ */
+#define MAXINP	50	/* max string to read from terminal or environment */
+
+get_str(opt, win)
+register char *opt;
+WINDOW *win;
+{
+    register char *sp;
+    register int c, oy, ox;
+    char buf[MAXSTR];
+
+    getyx(win, oy, ox);
+    wrefresh(win);
+    /*
+     * loop reading in the string, and put it in a temporary buffer
+     */
+    for (sp = buf; (c = readcharw(win)) != '\n' && c != '\r' && c != '\033';
+	wclrtoeol(win), wrefresh(win))
+    {
+	if (c == -1)
+	    continue;
+	else if (c == md_erasechar())	/* process erase character */
+	{
+	    if (sp > buf)
+	    {
+		register int i;
+
+		sp--;
+		for (i = strlen(unctrol(*sp)); i; i--)
+		    waddch(win, '\b');
+	    }
+	    continue;
+	}
+	else if (c == md_killchar())     /* process kill character */
+	{
+	    sp = buf;
+	    wmove(win, oy, ox);
+	    continue;
+	}
+	else if (sp == buf)
+	{
+	    if (c == '-' && win != stdscr)
+		break;
+	    else if (c == '~')
+	    {
+		strcpy(buf, home);
+		waddstr(win, home);
+		sp += strlen(home);
+		continue;
+	    }
+	}
+	if (sp >= &buf[MAXINP] || !(isprint(c) || c == ' '))
+	    putchar(CTRL('G'));
+	else
+	{
+	    *sp++ = c;
+	    waddstr(win, unctrol(c));
+	}
+    }
+    *sp = '\0';
+    if (sp > buf)	/* only change option if something has been typed */
+	strucpy(opt, buf, strlen(buf));
+    wmove(win, oy, ox);
+    waddstr(win, opt);
+    waddch(win, '\n');
+    wrefresh(win);
+    if (win == stdscr)
+	mpos += sp - buf;
+    if (c == '-')
+	return MINUS;
+    else if (c == '\033' || c == '\007')
+	return QUIT;
+    else
+	return NORM;
+}
+
+#ifdef WIZARD
+/*
+ * get_num:
+ *	Get a numeric option
+ */
+get_num(opt, win)
+short *opt;
+WINDOW *win;
+{
+    register int i;
+    char buf[MAXSTR];
+
+    if ((i = get_str(buf, win)) == NORM)
+	*opt = atoi(buf);
+    return i;
+}
+#endif
+
+/*
+ * parse_opts:
+ *	Parse options from string, usually taken from the environment.
+ *	The string is a series of comma seperated values, with booleans
+ *	being stated as "name" (true) or "noname" (false), and strings
+ *	being "name=....", with the string being defined up to a comma
+ *	or the end of the entire option string.
+ */
+parse_opts(str)
+register char *str;
+{
+    register char *sp;
+    register OPTION *op;
+    register int len;
+
+    while (*str)
+    {
+	/*
+	 * Get option name
+	 */
+	for (sp = str; isalpha(*sp); sp++)
+	    continue;
+	len = sp - str;
+	/*
+	 * Look it up and deal with it
+	 */
+	for (op = optlist; op < &optlist[NUM_OPTS]; op++)
+	    if (EQSTR(str, op->o_name, len))
+	    {
+		if (op->o_putfunc == put_bool)	/* if option is a boolean */
+		    *(bool *)op->o_opt = TRUE;
+		else				/* string option */
+		{
+		    register char *start;
+		    /*
+		     * Skip to start of string value
+		     */
+		    for (str = sp + 1; *str == '='; str++)
+			continue;
+		    if (*str == '~')
+		    {
+			strcpy((char *) op->o_opt, home);
+			start = (char *) op->o_opt + strlen(home);
+			while (*++str == '/')
+			    continue;
+		    }
+		    else
+			start = (char *) op->o_opt;
+		    /*
+		     * Skip to end of string value
+		     */
+		    for (sp = str + 1; *sp && *sp != ','; sp++)
+			continue;
+		    strucpy(start, str, sp - str);
+		}
+		break;
+	    }
+	    /*
+	     * check for "noname" for booleans
+	     */
+	    else if (op->o_putfunc == put_bool
+	      && EQSTR(str, "no", 2) && EQSTR(str + 2, op->o_name, len - 2))
+	    {
+		*(bool *)op->o_opt = FALSE;
+		break;
+	    }
+
+	/*
+	 * skip to start of next option name
+	 */
+	while (*sp && !isalpha(*sp))
+	    sp++;
+	str = sp;
+    }
+}
+
+/*
+ * strucpy:
+ *	Copy string using unctrol for things
+ */
+strucpy(s1, s2, len)
+register char *s1, *s2;
+register int len;
+{
+    if (len > MAXINP)
+	len = MAXINP;
+    while (len--)
+    {
+	if (isprint(*s2) || *s2 == ' ')
+	    *s1++ = *s2;
+	s2++;
+    }
+    *s1 = '\0';
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rogue4/pack.c	Sat Oct 24 16:52:52 2009 +0000
@@ -0,0 +1,421 @@
+/*
+ * Routines to deal with the pack
+ *
+ * @(#)pack.c	4.15 (Berkeley) 4/6/82
+ *
+ * Rogue: Exploring the Dungeons of Doom
+ * Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman
+ * All rights reserved.
+ *
+ * See the file LICENSE.TXT for full copyright and licensing information.
+ */
+
+#include <curses.h>
+#include <ctype.h>
+#include "rogue.h"
+
+/*
+ * update_mdest:
+ *	Called after picking up an object, before discarding it.
+ *	If this was the object of something's desire, that monster will
+ *	get mad and run at the hero
+ */
+update_mdest(obj)
+register THING *obj;
+{
+    register THING *mp;
+
+    for (mp = mlist; mp != NULL; mp = next(mp))
+	if (mp->t_dest == &obj->o_pos)
+     mp->t_dest = &hero;
+}
+
+/*
+ * 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 gettting
+ *	it off the ground.
+ */
+add_pack(obj, silent)
+register THING *obj;
+bool silent;
+{
+    register THING *op, *lp = NULL;
+    register bool exact, from_floor;
+    register char floor;
+    int discarded = 0;
+
+    if (obj == NULL)
+    {
+	from_floor = TRUE;
+	if ((obj = find_obj(hero.y, hero.x)) == NULL)
+	    return;
+    }
+    else
+	from_floor = FALSE;
+    /*
+     * Link it into the pack.  Search the pack for a object of similar type
+     * if there isn't one, stuff it at the beginning, if there is, look for one
+     * that is exactly the same and just increment the count if there is.
+     * it  that.  Food is always put at the beginning for ease of access, but
+     * is not ordered so that you can't tell good food from bad.  First check
+     * to see if there is something in thr same group and if there is then
+     * increment the count.
+     */
+/*    floor = (proom->r_flags & ISGONE) ? PASSAGE : FLOOR; */
+    if (proom) floor = (proom->r_flags & ISGONE) ? PASSAGE : FLOOR;
+    else floor = FLOOR;
+    if (obj->o_group)
+    {
+	for (op = pack; op != NULL; op = next(op))
+	{
+	    if (op->o_group == obj->o_group)
+	    {
+		/*
+		 * Put it in the pack and notify the user
+		 */
+		op->o_count++;
+		if (from_floor)
+		{
+		    detach(lvl_obj, obj);
+		    mvaddch(hero.y, hero.x, floor);
+		    chat(hero.y, hero.x) = floor;
+		}
+		update_mdest(obj);
+		discard(obj);
+		obj = op;
+		discarded = 1;
+		goto picked_up;
+	    }
+	}
+    }
+    /*
+     * Check if there is room
+     */
+    if (inpack == MAXPACK-1)
+    {
+	msg("you can't carry anything else");
+	return;
+    }
+    /*
+     * Check for and deal with scare monster scrolls
+     */
+    if (obj->o_type == SCROLL && obj->o_which == S_SCARE)
+	if (obj->o_flags & ISFOUND)
+	{
+	    detach(lvl_obj, obj);
+	    mvaddch(hero.y, hero.x, floor);
+	    chat(hero.y, hero.x) = floor;
+	    msg("the scroll turns to dust as you pick it up");
+	    return;
+	}
+	else
+	    obj->o_flags |= ISFOUND;
+
+    inpack++;
+    if (from_floor)
+    {
+	detach(lvl_obj, obj);
+	mvaddch(hero.y, hero.x, floor);
+	chat(hero.y, hero.x) = floor;
+    }
+    /*
+     * Search for an object of the same type
+     */
+    exact = FALSE;
+    for (op = pack; op != NULL; op = next(op))
+	if (obj->o_type == op->o_type)
+	    break;
+    if (op == NULL)
+    {
+	/*
+	 * Put it at the end of the pack since it is a new type
+	 */
+	for (op = pack; op != NULL; op = next(op))
+	{
+	    if (op->o_type != FOOD)
+		break;
+	    lp = op;
+	}
+    }
+    else
+    {
+	/*
+	 * Search for an object which is exactly the same
+	 */
+	while (op->o_type == obj->o_type)
+	{
+	    if (op->o_which == obj->o_which)
+	    {
+		exact = TRUE;
+		break;
+	    }
+	    lp = op;
+	    if ((op = next(op)) == NULL)
+		break;
+	}
+    }
+    if (op == NULL)
+    {
+	/*
+	 * Didn't find an exact match, just stick it here
+	 */
+	if (pack == NULL)
+	    pack = obj;
+	else
+	{
+	    lp->l_next = obj;
+	    obj->l_prev = lp;
+	    obj->l_next = NULL;
+	}
+    }
+    else
+    {
+	/*
+	 * If we found an exact match.  If it is a potion, food, or a 
+	 * scroll, increase the count, otherwise put it with its clones.
+	 */
+	if (exact && ISMULT(obj->o_type))
+	{
+	    op->o_count++;
+	    update_mdest(obj);
+	    discard(obj);
+	    obj = op;
+	    discarded = 1;
+	    goto picked_up;
+	}
+	if ((obj->l_prev = prev(op)) != NULL)
+	    obj->l_prev->l_next = obj;
+	else
+	    pack = obj;
+	obj->l_next = op;
+	op->l_prev = obj;
+    }
+picked_up:
+    /*
+     * If this was the object of something's desire, that monster will
+     * get mad and run at the hero
+     */
+    if (!discarded)
+        update_mdest(obj);
+
+    if (obj->o_type == AMULET)
+	amulet = TRUE;
+    /*
+     * Notify the user
+     */
+    if (!silent)
+    {
+	if (!terse)
+	    addmsg("you now have ");
+	msg("%s (%c)", inv_name(obj, !terse), pack_char(obj));
+    }
+}
+
+/*
+ * inventory:
+ *	List what is in the pack
+ */
+inventory(list, type)
+THING *list;
+int type;
+{
+    register char ch;
+    register int n_objs;
+    char inv_temp[MAXSTR];
+
+    n_objs = 0;
+    for (ch = 'a'; list != NULL; ch++, list = next(list))
+    {
+	if (type && type != list->o_type && !(type == CALLABLE &&
+	    (list->o_type == SCROLL || list->o_type == POTION ||
+	     list->o_type == RING || list->o_type == STICK)))
+		continue;
+	n_objs++;
+	sprintf(inv_temp, "%c) %%s", ch);
+	add_line(inv_temp, inv_name(list, FALSE));
+    }
+    if (n_objs == 0)
+    {
+	if (terse)
+	    msg(type == 0 ? "empty handed" :
+			    "nothing appropriate");
+	else
+	    msg(type == 0 ? "you are empty handed" :
+			    "you don't have anything appropriate");
+	return FALSE;
+    }
+    end_line();
+    return TRUE;
+}
+
+/*
+ * pick_up:
+ *	Add something to characters pack.
+ */
+pick_up(ch)
+char ch;
+{
+    register THING *obj, *mp;
+
+    switch (ch)
+    {
+	case GOLD:
+	    if ((obj = find_obj(hero.y, hero.x)) == NULL)
+		return;
+	    money(obj->o_goldval);
+	    detach(lvl_obj, obj);
+	    update_mdest(obj);
+	    discard(obj);
+	    proom->r_goldval = 0;
+	    break;
+	default:
+#ifdef WIZARD
+	    debug("Where did you pick a '%s' up???", unctrol(ch));
+#endif
+	case ARMOR:
+	case POTION:
+	case FOOD:
+	case WEAPON:
+	case SCROLL:	
+	case AMULET:
+	case RING:
+	case STICK:
+	    add_pack(NULL, FALSE);
+	    break;
+    }
+}
+
+/*
+ * picky_inven:
+ *	Allow player to inventory a single item
+ */
+picky_inven()
+{
+    register THING *obj;
+    register char ch, mch;
+
+    if (pack == NULL)
+	msg("you aren't carrying anything");
+    else if (next(pack) == NULL)
+	msg("a) %s", inv_name(pack, FALSE));
+    else
+    {
+	msg(terse ? "item: " : "which item do you wish to inventory: ");
+	mpos = 0;
+	if ((mch = readchar()) == ESCAPE)
+	{
+	    msg("");
+	    return;
+	}
+	for (ch = 'a', obj = pack; obj != NULL; obj = next(obj), ch++)
+	    if (ch == mch)
+	    {
+		msg("%c) %s",ch,inv_name(obj, FALSE));
+		return;
+	    }
+	if (!terse)
+	    msg("'%s' not in pack", unctrol(mch));
+	msg("range is 'a' to '%c'", --ch);
+    }
+}
+
+/*
+ * get_item:
+ *	Pick something out of a pack for a purpose
+ */
+THING *
+get_item(purpose, type)
+char *purpose;
+int type;
+{
+    register THING *obj;
+    register char ch, och;
+
+    if (pack == NULL)
+	msg("you aren't carrying anything");
+    else
+    {
+	for (;;)
+	{
+	    if (!terse)
+		addmsg("which object do you want to ");
+	    addmsg(purpose);
+	    if (terse)
+		addmsg(" what");
+	    msg("? (* for list): ");
+	    ch = readchar();
+	    mpos = 0;
+	    /*
+	     * Give the poor player a chance to abort the command
+	     */
+	    if (ch == ESCAPE || ch == CTRL('G'))
+	    {
+		after = FALSE;
+		msg("");
+		return NULL;
+	    }
+	    if (ch == '*')
+	    {
+		mpos = 0;
+		if (inventory(pack, type) == 0)
+		{
+		    after = FALSE;
+		    return NULL;
+		}
+		continue;
+	    }
+	    for (obj = pack, och = 'a'; obj != NULL; obj = next(obj), och++)
+		if (ch == och)
+		    break;
+	    if (obj == NULL)
+	    {
+		msg("please specify a letter between 'a' and '%c'", och-1);
+		continue;
+	    }
+	    else 
+		return obj;
+	}
+    }
+    return NULL;
+}
+
+/*
+ * pack_char:
+ *	Return which character would address a pack object
+ */
+pack_char(obj)
+register THING *obj;
+{
+    register THING *item;
+    register char c;
+
+    c = 'a';
+    for (item = pack; item != NULL; item = next(item))
+	if (item == obj)
+	    return c;
+	else
+	    c++;
+    return '?';
+}
+
+/*
+ * money:
+ *	Add or subtract gold from the pack
+ */
+money(value)
+register int value;
+{
+    register char floor;
+
+    floor = (proom->r_flags & ISGONE) ? PASSAGE : FLOOR;
+    purse += value;
+    mvaddch(hero.y, hero.x, floor);
+    chat(hero.y, hero.x) = floor;
+    if (value > 0)
+    {
+	if (!terse)
+	    addmsg("you found ");
+	msg("%d gold pieces", value);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rogue4/passages.c	Sat Oct 24 16:52:52 2009 +0000
@@ -0,0 +1,368 @@
+/*
+ * Draw the connecting passages
+ *
+ * @(#)passages.c	4.8 (Berkeley) 1/27/82
+ *
+ * Rogue: Exploring the Dungeons of Doom
+ * Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman
+ * All rights reserved.
+ *
+ * See the file LICENSE.TXT for full copyright and licensing information.
+ */
+
+#include <curses.h>
+#include "rogue.h"
+
+/*
+ * do_passages:
+ *	Draw all the passages on a level.
+ */
+do_passages()
+{
+    register struct rdes *r1, *r2 = NULL;
+    register int i, j;
+    register int roomcount;
+    static struct rdes
+    {
+	bool	conn[MAXROOMS];		/* possible to connect to room i? */
+	bool	isconn[MAXROOMS];	/* connection been 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-1]; 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 always 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;
+	}
+    }
+    passnum();
+}
+
+/*
+ * conn:
+ *	Draw a corridor from a room in a certain direction.
+ */
+conn(r1, r2)
+int r1, r2;
+{
+    register struct room *rpf, *rpt = NULL;
+    register char rmt;
+    register int distance = 0, turn_spot = 0, turn_distance = 0, index;
+    register int rm;
+    register char direc;
+    coord del = {0,0}, curr, turn_delta = {0,0}, spos = {0,0}, epos = {0,0};
+
+    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 */
+	del.x = 0;				/* direction of move */
+	del.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 (!(rpf->r_flags & ISGONE))		/* if not gone pick door pos */
+	{
+	    spos.x += rnd(rpf->r_max.x - 2) + 1;
+	    spos.y += rpf->r_max.y - 1;
+	}
+	if (!(rpt->r_flags & 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];
+	del.x = 1;
+	del.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 (!(rpf->r_flags & ISGONE))
+	{
+	    spos.x += rpf->r_max.x-1;
+	    spos.y += rnd(rpf->r_max.y-2)+1;
+	}
+	if (!(rpt->r_flags & 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;
+    }
+#ifdef WIZARD
+    else
+	debug("error in connection tables");
+#endif
+    /*
+     * Draw in the doors on either side of the passage or just put #'s
+     * if the rooms are gone.
+     */
+    if (!(rpf->r_flags & ISGONE))
+	door(rpf, &spos);
+    else
+    {
+	index = INDEX(spos.y, spos.x);
+	_level[index] = PASSAGE;
+	_flags[index] |= F_PASS;
+    }
+    if (!(rpt->r_flags & ISGONE))
+	door(rpt, &epos);
+    else
+    {
+	index = INDEX(epos.y, epos.x);
+	_level[index] = PASSAGE;
+	_flags[index] |= F_PASS;
+    }
+    /*
+     * Get ready to move...
+     */
+    curr.x = spos.x;
+    curr.y = spos.y;
+    while (distance)
+    {
+	/*
+	 * Move to new position
+	 */
+	curr.x += del.x;
+	curr.y += del.y;
+	/*
+	 * Check if we are at the turn place, if so do the turn
+	 */
+	if (distance == turn_spot)
+	    while (turn_distance--)
+	    {
+		index = INDEX(curr.y, curr.x);
+		_level[index] = PASSAGE;
+		_flags[index] |= F_PASS;
+		curr.x += turn_delta.x;
+		curr.y += turn_delta.y;
+	    }
+	/*
+	 * Continue digging along
+	 */
+	index = INDEX(curr.y, curr.x);
+	_level[index] = PASSAGE;
+	_flags[index] |= F_PASS;
+	distance--;
+    }
+    curr.x += del.x;
+    curr.y += del.y;
+    if (!ce(curr, epos))
+	msg("warning, connectivity problem on this level");
+}
+
+/*
+ * door:
+ *	Add a door or possibly a secret door.  Also enters the door in
+ *	the exits array of the room.
+ */
+door(rm, cp)
+register struct room *rm;
+register coord *cp;
+{
+    register int index;
+
+    index = INDEX(cp->y, cp->x);
+    if (rnd(10) + 1 < level && rnd(5) == 0)
+    {
+	_level[index] = (cp->y == rm->r_pos.y || cp->y == rm->r_pos.y + rm->r_max.y - 1) ? '-' : '|';
+	_flags[index] &= ~F_REAL;
+    }
+    else
+	_level[index] = DOOR;
+    rm->r_exit[rm->r_nexits++] = *cp;
+}
+
+#ifdef WIZARD
+/*
+ * add_pass:
+ *	Add the passages to the current window (wizard command)
+ */
+add_pass()
+{
+    register int y, x, ch;
+
+    for (y = 1; y < LINES - 1; y++)
+	for (x = 0; x < COLS; x++)
+	    if ((ch = chat(y, x)) == DOOR || ch == PASSAGE)
+		mvaddch(y, x, ch);
+}
+#endif
+
+/*
+ * passnum:
+ *	Assign a number to each passageway
+ */
+static int pnum;
+static bool newpnum;
+
+passnum()
+{
+    register struct room *rp;
+    register int i;
+
+    pnum = 0;
+    newpnum = FALSE;
+    for (rp = passages; rp < &passages[MAXPASS]; rp++)
+	rp->r_nexits = 0;
+    for (rp = rooms; rp < &rooms[MAXROOMS]; rp++)
+	for (i = 0; i < rp->r_nexits; i++)
+	{
+	    newpnum++;
+	    numpass(rp->r_exit[i].y, rp->r_exit[i].x);
+	}
+}
+
+/*
+ * numpass:
+ *	Number a passageway square and its brethren
+ */
+numpass(y, x)
+register int y, x;
+{
+    register char *fp;
+    register struct room *rp;
+    register char ch;
+
+    fp = &flat(y, x);
+    if (*fp & F_PNUM)
+	return;
+    if (newpnum)
+    {
+	pnum++;
+	newpnum = FALSE;
+    }
+    /*
+     * check to see if it is a door or secret door, i.e., a new exit,
+     * or a numerable type of place
+     */
+    if ((ch = chat(y, x)) == DOOR || (!(*fp & F_REAL) && ch != FLOOR))
+    {
+	rp = &passages[pnum];
+	rp->r_exit[rp->r_nexits].y = y;
+	rp->r_exit[rp->r_nexits++].x = x;
+    }
+    else if (!(*fp & F_PASS))
+	return;
+    *fp |= pnum;
+    /*
+     * recurse on the surrounding places
+     */
+    numpass(y + 1, x);
+    numpass(y - 1, x);
+    numpass(y, x + 1);
+    numpass(y, x - 1);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rogue4/potions.c	Sat Oct 24 16:52:52 2009 +0000
@@ -0,0 +1,256 @@
+/*
+ * Function(s) for dealing with potions
+ *
+ * @(#)potions.c	4.24 (Berkeley) 4/6/82
+ *
+ * Rogue: Exploring the Dungeons of Doom
+ * Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman
+ * All rights reserved.
+ *
+ * See the file LICENSE.TXT for full copyright and licensing information.
+ */
+
+#include <curses.h>
+#include "rogue.h"
+
+/*
+ * quaff:
+ *	Quaff a potion from the pack
+ */
+quaff()
+{
+    register THING *obj, *th;
+    register bool discardit = FALSE;
+
+    obj = get_item("quaff", POTION);
+    /*
+     * Make certain that it is somethings that we want to drink
+     */
+    if (obj == NULL)
+	return;
+    if (obj->o_type != POTION)
+    {
+	if (!terse)
+	    msg("yuk! Why would you want to drink that?");
+	else
+	    msg("that's undrinkable");
+	return;
+    }
+    if (obj == cur_weapon)
+	cur_weapon = NULL;
+
+    /*
+     * Calculate the effect it has on the poor guy.
+     */
+    switch (obj->o_which)
+    {
+	case P_CONFUSE:
+	    p_know[P_CONFUSE] = TRUE;
+	    if (!on(player, ISHUH))
+	    {
+		if (on(player, ISHUH))
+		    lengthen(unconfuse, rnd(8)+HUHDURATION);
+		else
+		    fuse(unconfuse, 0, rnd(8)+HUHDURATION, AFTER);
+		player.t_flags |= ISHUH;
+		msg("wait, what's going on here. Huh? What? Who?");
+	    }
+	when P_POISON:
+	    p_know[P_POISON] = TRUE;
+	    if (!ISWEARING(R_SUSTSTR))
+	    {
+		chg_str(-(rnd(3)+1));
+		msg("you feel very sick now");
+	    }
+	    else
+		msg("you feel momentarily sick");
+	when P_HEALING:
+	    p_know[P_HEALING] = TRUE;
+	    if ((pstats.s_hpt += roll(pstats.s_lvl, 4)) > max_hp)
+		pstats.s_hpt = ++max_hp;
+	    sight();
+	    msg("you begin to feel better");
+	when P_STRENGTH:
+	    p_know[P_STRENGTH] = TRUE;
+	    chg_str(1);
+	    msg("you feel stronger, now.  What bulging muscles!");
+	when P_MFIND:
+	    player.t_flags |= SEEMONST;
+	    fuse(turn_see, TRUE, HUHDURATION, AFTER);
+	    if (mlist == NULL)
+		msg("you have a strange feeling for a moment");
+	    else
+		p_know[P_MFIND] |= turn_see(FALSE);
+	when P_TFIND:
+	    /*
+	     * Potion of magic detection.  Show the potions and scrolls
+	     */
+	    if (lvl_obj != NULL)
+	    {
+		register THING *tp;
+		register bool show;
+
+		show = FALSE;
+		wclear(hw);
+		for (tp = lvl_obj; tp != NULL; tp = next(tp))
+		{
+		    if (is_magic(tp))
+		    {
+			show = TRUE;
+			mvwaddch(hw, tp->o_pos.y, tp->o_pos.x, MAGIC);
+			p_know[P_TFIND] = TRUE;
+		    }
+		}
+		for (th = mlist; th != NULL; th = next(th))
+		{
+		    for (tp = th->t_pack; tp != NULL; tp = next(tp))
+		    {
+			if (is_magic(tp))
+			{
+			    show = TRUE;
+			    mvwaddch(hw, th->t_pos.y, th->t_pos.x, MAGIC);
+			    p_know[P_TFIND] = TRUE;
+			}
+		    }
+		}
+		if (show)
+		{
+		    show_win(hw, 
+			"You sense the presence of magic on this level.--More--");
+		    break;
+		}
+	    }
+	    msg("you have a strange feeling for a moment, then it passes");
+	when P_PARALYZE:
+	    p_know[P_PARALYZE] = TRUE;
+	    no_command = HOLDTIME;
+	    player.t_flags &= ~ISRUN;
+	    msg("you can't move");
+	when P_SEEINVIS:
+	    if (!on(player, CANSEE))
+	    {
+		fuse(unsee, 0, SEEDURATION, AFTER);
+		look(FALSE);
+		invis_on();
+	    }
+	    sight();
+	    msg("this potion tastes like %s juice", fruit);
+	when P_RAISE:
+	    p_know[P_RAISE] = TRUE;
+	    msg("you suddenly feel much more skillful");
+	    raise_level();
+	when P_XHEAL:
+	    p_know[P_XHEAL] = TRUE;
+	    if ((pstats.s_hpt += roll(pstats.s_lvl, 8)) > max_hp)
+	    {
+		if (pstats.s_hpt > max_hp + pstats.s_lvl + 1)
+		    ++max_hp;
+		pstats.s_hpt = ++max_hp;
+	    }
+	    sight();
+	    msg("you begin to feel much better");
+	when P_HASTE:
+	    p_know[P_HASTE] = TRUE;
+	    if (add_haste(TRUE))
+		msg("you feel yourself moving much faster");
+	when P_RESTORE:
+	    if (ISRING(LEFT, R_ADDSTR))
+		add_str(&pstats.s_str, -cur_ring[LEFT]->o_ac);
+	    if (ISRING(RIGHT, R_ADDSTR))
+		add_str(&pstats.s_str, -cur_ring[RIGHT]->o_ac);
+	    if (pstats.s_str < max_stats.s_str)
+		pstats.s_str = max_stats.s_str;
+	    if (ISRING(LEFT, R_ADDSTR))
+		add_str(&pstats.s_str, cur_ring[LEFT]->o_ac);
+	    if (ISRING(RIGHT, R_ADDSTR))
+		add_str(&pstats.s_str, cur_ring[RIGHT]->o_ac);
+	    msg("hey, this tastes great.  It make you feel warm all over");
+	when P_BLIND:
+	    p_know[P_BLIND] = TRUE;
+	    if (!on(player, ISBLIND))
+	    {
+		player.t_flags |= ISBLIND;
+		fuse(sight, 0, SEEDURATION, AFTER);
+		look(FALSE);
+	    }
+	    msg("a cloak of darkness falls around you");
+	when P_NOP:
+	    msg("this potion tastes extremely dull");
+	otherwise:
+	    msg("what an odd tasting potion!");
+	    return;
+    }
+    status();
+    /*
+     * Throw the item away
+     */
+    inpack--;
+    if (obj->o_count > 1)
+	obj->o_count--;
+    else
+    {
+	detach(pack, obj);
+        discardit = TRUE;
+    }
+
+    call_it(p_know[obj->o_which], &p_guess[obj->o_which]);
+
+    if (discardit)
+	discard(obj);
+}
+
+/*
+ * invis_on:
+ *	Turn on the ability to see invisible
+ */
+invis_on()
+{
+    register THING *th;
+
+    player.t_flags |= CANSEE;
+    for (th = mlist; th != NULL; th = next(th))
+	if (on(*th, ISINVIS) && see_monst(th))
+	{
+	    move(th->t_pos.y, th->t_pos.x);
+	    addch(th->t_disguise);
+	}
+}
+
+/*
+ * see_monst:
+ *	Put on or off seeing monsters on this level
+ */
+turn_see(turn_off)
+register bool turn_off;
+{
+    register THING *mp;
+    register bool can_see, add_new;
+
+    add_new = FALSE;
+    for (mp = mlist; mp != NULL; mp = next(mp))
+    {
+	move(mp->t_pos.y, mp->t_pos.x);
+	can_see = (see_monst(mp) || inch() == (unsigned char)mp->t_type);
+	if (turn_off)
+	{
+	    if (!can_see)
+		addch(mp->t_oldch);
+	}
+	else
+	{
+	    if (!can_see)
+		standout();
+	    addch(mp->t_type);
+	    if (!can_see)
+	    {
+		standend();
+		add_new++;
+	    }
+	}
+    }
+    if (turn_off)
+	player.t_flags &= ~SEEMONST;
+    else
+	player.t_flags |= SEEMONST;
+    return add_new;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rogue4/prob.c	Sat Oct 24 16:52:52 2009 +0000
@@ -0,0 +1,96 @@
+/*
+ *
+ * Rogue: Exploring the Dungeons of Doom
+ * Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman
+ * All rights reserved.
+ *
+ * See the file LICENSE.TXT for full copyright and licensing information.
+ */
+
+# include	<curses.h>
+# include	"rogue.h"
+
+# undef	max
+
+# define	TRIES	10000
+
+static char *sccsid = "@(#)prob.c	1.3 (Berkeley) 12/17/81";
+
+main(ac, av)
+int	ac;
+char	**av;
+{
+	register unsigned int	prob, prob2, exp;
+	register struct monster	*mp;
+	register unsigned int	max, min, i;
+	register unsigned int	max2, min2;
+
+	printf("%17.17s  ----experience--- ----hit points---\n", "");
+	printf("%17.17s  %7s %4s %4s %7s %4s %4s lvl\n", "monster", "avg", "min", "max", "avg", "min", "max", "max hp");
+	seed = 0;
+	for (mp = monsters; mp < &monsters[26]; mp++) {
+		i = TRIES;
+		prob2 = prob = 0;
+		min2 = min = 30000;
+		max2 = max = 0;
+		while (i--) {
+			if ((exp = roll(mp->m_stats.s_lvl, 8)) < min2)
+				min2 = exp;
+			if (exp > max2)
+				max2 = exp;
+			prob2 += exp;
+			mp->m_stats.s_maxhp = exp;
+			if ((exp = mp->m_stats.s_exp + exp_add(mp)) < min)
+				min = exp;
+			if (exp > max)
+				max = exp;
+			prob += exp;
+		}
+		printf("%17.17s: %7.2f %4d %4d %7.2f %4d %4d %3d\n", mp->m_name, ((double) prob) / TRIES, min, max, ((double) prob2) / TRIES, min2, max2, mp->m_stats.s_lvl);
+		fflush(stdout);
+	}
+}
+
+exp_add(mp)
+register struct monster *mp;
+{
+    register unsigned int mod;
+
+    if (mp->m_stats.s_lvl == 1)
+	mod = mp->m_stats.s_maxhp / 8;
+    else
+	mod = mp->m_stats.s_maxhp / 6;
+    if (mp->m_stats.s_lvl > 9)
+	mod *= 20;
+    else if (mp->m_stats.s_lvl > 6)
+	mod *= 4;
+    return mod;
+}
+
+/*
+ * roll:
+ *	roll a number of dice
+ */
+roll(number, sides)
+register unsigned int number, sides;
+{
+    register unsigned int dtotal = 0;
+
+    dtotal = number;
+    while (number--)
+	dtotal += rnd(sides);
+    return dtotal;
+}
+
+/*
+ * rnd:
+ *	Pick a very random number.
+ */
+
+
+rnd(range)
+register unsigned int range;
+{
+
+    return RN % range;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rogue4/rings.c	Sat Oct 24 16:52:52 2009 +0000
@@ -0,0 +1,208 @@
+/*
+ * Routines dealing specifically with rings
+ *
+ * @(#)rings.c	4.13 (Berkeley) 1/28/82
+ *
+ * Rogue: Exploring the Dungeons of Doom
+ * Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman
+ * All rights reserved.
+ *
+ * See the file LICENSE.TXT for full copyright and licensing information.
+ */
+
+#include <curses.h>
+#include <string.h>
+#include "rogue.h"
+
+/*
+ * ring_on:
+ *	Put a ring on a hand
+ */
+ring_on()
+{
+    register THING *obj;
+    register int ring;
+
+    obj = get_item("put on", RING);
+    /*
+     * Make certain that it is somethings that we want to wear
+     */
+    if (obj == NULL)
+	return;
+    if (obj->o_type != RING)
+    {
+	if (!terse)
+	    msg("it would be difficult to wrap that around a finger");
+	else
+	    msg("not a ring");
+	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()) < 0)
+	    return;
+    }
+    else if (cur_ring[LEFT] == NULL)
+	ring = LEFT;
+    else if (cur_ring[RIGHT] == NULL)
+	ring = RIGHT;
+    else
+    {
+	if (!terse)
+	    msg("you already have a ring on each hand");
+	else
+	    msg("wearing two");
+	return;
+    }
+    cur_ring[ring] = obj;
+
+    /*
+     * Calculate the effect it has on the poor guy.
+     */
+    switch (obj->o_which)
+    {
+	case R_ADDSTR:
+	    chg_str(obj->o_ac);
+	    break;
+	case R_SEEINVIS:
+	    invis_on();
+	    break;
+	case R_AGGR:
+	    aggravate();
+	    break;
+    }
+
+    if (!terse)
+	addmsg("you are now wearing ");
+    msg("%s (%c)", inv_name(obj, TRUE), pack_char(obj));
+}
+
+/*
+ * ring_off:
+ *	Take off a ring
+ */
+ring_off()
+{
+    register int ring;
+    register THING *obj;
+    register char packchar;
+
+    if (cur_ring[LEFT] == NULL && cur_ring[RIGHT] == NULL)
+    {
+	if (terse)
+	    msg("no rings");
+	else
+	    msg("you aren't wearing any rings");
+	return;
+    }
+    else if (cur_ring[LEFT] == NULL)
+	ring = RIGHT;
+    else if (cur_ring[RIGHT] == NULL)
+	ring = LEFT;
+    else
+	if ((ring = gethand()) < 0)
+	    return;
+    mpos = 0;
+    obj = cur_ring[ring];
+    if (obj == NULL)
+    {
+	msg("not wearing such a ring");
+	return;
+    }
+    packchar = pack_char(obj);
+    if (dropcheck(obj))
+	msg("was wearing %s(%c)", inv_name(obj, TRUE), packchar);
+}
+
+/*
+ * gethand:
+ *	Which hand is the hero interested in?
+ */
+gethand()
+{
+    register int c;
+
+    for (;;)
+    {
+	if (terse)
+	    msg("left or right ring? ");
+	else
+	    msg("left hand or right hand? ");
+	if ((c = readchar()) == ESCAPE)
+	    return -1;
+	mpos = 0;
+	if (c == 'l' || c == 'L')
+	    return LEFT;
+	else if (c == 'r' || c == 'R')
+	    return RIGHT;
+	if (terse)
+	    msg("L or R");
+	else
+	    msg("please type L or R");
+    }
+}
+
+/*
+ * ring_eat:
+ *	How much food does this ring use up?
+ */
+ring_eat(hand)
+register int hand;
+{
+    if (cur_ring[hand] == NULL)
+	return 0;
+    switch (cur_ring[hand]->o_which)
+    {
+	case R_REGEN:
+	    return 2;
+	case R_SUSTSTR:
+	case R_SUSTARM:
+	case R_PROTECT:
+	case R_ADDSTR:
+	case R_STEALTH:
+	    return 1;
+	case R_SEARCH:
+	case R_ADDHIT:
+	case R_ADDDAM:
+	    return (rnd(3) == 0);
+	case R_DIGEST:
+	    return -rnd(2);
+	case R_SEEINVIS:
+	    return (rnd(5) == 0);
+	default:
+	    return 0;
+    }
+}
+
+/*
+ * ring_num:
+ *	Print ring bonuses
+ */
+char *
+ring_num(obj)
+register THING *obj;
+{
+    static char buf[5];
+
+    if (!(obj->o_flags & ISKNOW))
+	return "";
+    switch (obj->o_which)
+    {
+	case R_PROTECT:
+	case R_ADDSTR:
+	case R_ADDDAM:
+	case R_ADDHIT:
+	    buf[0] = ' ';
+	    strcpy(&buf[1], num(obj->o_ac, 0, RING));
+	otherwise:
+	    return "";
+    }
+    return buf;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rogue4/rip.c	Sat Oct 24 16:52:52 2009 +0000
@@ -0,0 +1,433 @@
+/*
+ * File for the fun ends
+ * Death or a total win
+ *
+ * @(#)rip.c	4.28 (Berkeley) 4/12/82
+ *
+ * Rogue: Exploring the Dungeons of Doom
+ * Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman
+ * All rights reserved.
+ *
+ * See the file LICENSE.TXT for full copyright and licensing information.
+ */
+
+#include <curses.h>
+#include <time.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <string.h>
+#include <stdlib.h>
+#include "rogue.h"
+
+static char *rip[] = {
+"                       __________",
+"                      /          \\",
+"                     /    REST    \\",
+"                    /      IN      \\",
+"                   /     PEACE      \\",
+"                  /                  \\",
+"                  |                  |",
+"                  |                  |",
+"                  |   killed by a    |",
+"                  |                  |",
+"                  |       1980       |",
+"                 *|     *  *  *      | *",
+"         ________)/\\\\_//(\\/(/\\)/\\//\\/|_)_______",
+    0
+};
+
+/*
+ * score:
+ *	Figure score and post it.
+ */
+/* VARARGS2 */
+score(amount, flags, monst)
+int amount, flags;
+char monst;
+{
+    register struct sc_ent *scp;
+    register int i;
+    register struct sc_ent *sc2;
+    register FILE *outf;
+    register int prflags = 0;
+    register void (*fp)(int);
+    register int uid;
+    char scoreline[MAXSTR + 100];
+
+    static struct sc_ent {
+	char sc_name[MAXSTR];
+	unsigned int sc_flags;
+	unsigned int sc_uid;
+	unsigned short sc_monster;
+	unsigned short sc_score;
+	unsigned short sc_level;
+    } top_ten[10];
+    static char *reason[] = {
+	"killed",
+	"quit",
+	"A total winner",
+    };
+    void endit();
+
+    start_score();
+
+    if (fd >= 0)
+	outf = md_fdopen(fd, "wb");
+    else
+	return;
+
+    for (scp = top_ten; scp <= &top_ten[9]; scp++)
+    {
+	scp->sc_score = 0;
+	for (i = 0; i < MAXSTR; i++)
+	    scp->sc_name[i] = rnd(255);
+	scp->sc_flags = RN;
+	scp->sc_level = RN;
+	scp->sc_monster = RN;
+	scp->sc_uid = RN;
+    }
+
+    signal(SIGINT, SIG_DFL);
+    if (flags != -1
+#ifdef WIZARD
+	    || wizard
+#endif
+	)
+    {
+	mvaddstr(LINES - 1, 0 , "[Press return to continue]");
+        refresh();
+        wgetnstr(stdscr,prbuf,80);
+        move(LINES - 1, 0);
+        clrtoeol();
+        refresh();
+        endwin();
+    }
+#ifdef WIZARD
+    if (wizard)
+	if (strcmp(prbuf, "names") == 0)
+	    prflags = 1;
+	else if (strcmp(prbuf, "edit") == 0)
+	    prflags = 2;
+#endif
+    for(i=0; i<10; i++)
+    {
+        encread((char *) &top_ten[i].sc_name, MAXSTR, fd);
+	scoreline[0] = '\0';
+        encread((char *) scoreline, 100, fd);
+        sscanf(scoreline, "%d %d %hd %hd %hd", &top_ten[i].sc_flags, 
+            &top_ten[i].sc_uid, &top_ten[i].sc_monster, &top_ten[i].sc_score,
+            &top_ten[i].sc_level);
+    }
+    /*
+     * Insert her in list if need be
+     */
+    sc2 = NULL;
+    if (!noscore)
+    {
+	uid = md_getuid();
+
+	for (scp = top_ten; scp <= &top_ten[9]; scp++)
+	    if (amount > scp->sc_score)
+		break;
+#ifdef LIMIT_TOPTEN
+            else if (flags != 2 && scp->sc_uid == uid && scp->sc_flags != 2)
+		scp = &top_ten[9] + 1;	/* only one score per nowin uid */
+#endif
+	if (scp <= &top_ten[9])
+	{
+#ifdef LIMIT_TOPTEN
+	    if (flags != 2)
+		for (sc2 = scp; sc2 <= &top_ten[9]; sc2++)
+		{
+		    if (sc2->sc_uid == uid && sc2->sc_flags != 2)
+			break;
+		}
+	    else
+#endif
+		sc2 = &top_ten[9];
+	    while (sc2 > scp)
+	    {
+		*sc2 = sc2[-1];
+		sc2--;
+	    }
+	    scp->sc_score = amount;
+	    strncpy(scp->sc_name, whoami, MAXSTR);
+	    scp->sc_flags = flags;
+	    if (flags == 2)
+		scp->sc_level = max_level;
+	    else
+		scp->sc_level = level;
+	    scp->sc_monster = monst;
+	    scp->sc_uid = uid;
+	    sc2 = scp;
+	}
+    }
+    /*
+     * Print the list
+     */
+    printf("Top Ten Rogueists:\nRank\tScore\tName\n");
+    for (scp = top_ten; scp <= &top_ten[9]; scp++)
+    {
+	if (scp->sc_score) {
+	    printf("%d\t%d\t%s: %s on level %d", scp - top_ten + 1,
+		scp->sc_score, scp->sc_name, reason[scp->sc_flags],
+		scp->sc_level);
+	    if (scp->sc_flags == 0)
+		printf(" by %s", killname((char) scp->sc_monster, TRUE));
+	    if (prflags == 1)
+	    {
+		char *name;
+		name = md_getusername(scp->sc_uid);
+		   
+		if (name == NULL)
+		    printf(" (%d)", scp->sc_uid);
+		else
+		    printf(" (%s)", name);
+		putchar('\n');
+	    }
+	    else if (prflags == 2)
+	    {
+		fflush(stdout);
+          	fgets(prbuf,80,stdin);
+		if (prbuf[0] == 'd')
+		{
+		    for (sc2 = scp; sc2 < &top_ten[9]; sc2++)
+			*sc2 = *(sc2 + 1);
+		    top_ten[9].sc_score = 0;
+		    for (i = 0; i < MAXSTR; i++)
+			top_ten[9].sc_name[i] = rnd(255);
+		    top_ten[9].sc_flags = RN;
+		    top_ten[9].sc_level = RN;
+		    top_ten[9].sc_monster = RN;
+		    scp--;
+		}
+	    }
+	    else
+		printf(".\n");
+	}
+	else
+	    break;
+    }
+    fseek(outf, 0L, 0);
+    /*
+     * Update the list file
+     */
+    if (sc2 != NULL)
+    {
+	if (lock_sc())
+	{
+            int i;
+
+	    fp = signal(SIGINT, SIG_IGN);
+
+            for(i=0; i<10; i++)
+            {
+                encwrite((char *) &top_ten[i].sc_name, MAXSTR, outf);
+                sprintf(scoreline," %d %d %hd %hd %hd \n",
+                    top_ten[i].sc_flags, top_ten[i].sc_uid, 
+                    top_ten[i].sc_monster, top_ten[i].sc_score,
+                    top_ten[i].sc_level);
+                encwrite((char *) scoreline, 100, outf);
+            }
+	    unlock_sc();
+	    signal(SIGINT, fp);
+	}
+    }
+    fclose(outf);
+}
+
+/*
+ * death:
+ *	Do something really fun when he dies
+ */
+death(monst)
+register char monst;
+{
+    register char **dp = rip, *killer;
+    register struct tm *lt;
+    time_t date;
+    char buf[MAXSTR];
+    struct tm *localtime();
+
+    signal(SIGINT, SIG_IGN);
+    purse -= purse / 10;
+    signal(SIGINT, leave);
+    time(&date);
+    lt = localtime(&date);
+    clear();
+    move(8, 0);
+    while (*dp)
+	printw("%s\n", *dp++);
+    mvaddstr(14, 28-((strlen(whoami)+1)/2), whoami);
+    sprintf(buf, "%d Au", purse);
+    mvaddstr(15, 28-((strlen(buf)+1)/2), buf);
+    killer = killname(monst, FALSE);
+    mvaddstr(17, 28-((strlen(killer)+1)/2), killer);
+    if (monst == 's')
+	mvaddch(16, 32, ' ');
+    else
+	mvaddstr(16, 33, vowelstr(killer));
+    sprintf(prbuf, "%2d", 1900+lt->tm_year);
+    mvaddstr(18, 26, prbuf);
+    move(LINES-1, 0);
+    refresh();
+    score(purse, 0, monst);
+    exit(0);
+}
+
+/*
+ * total_winner:
+ *	Code for a winner
+ */
+total_winner()
+{
+    register THING *obj;
+    register int worth = 0;
+    register char c;
+    register int oldpurse;
+
+    clear();
+    standout();
+    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");
+    standend();
+    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, "--Press space to continue--");
+    refresh();
+    wait_for(' ');
+    clear();
+    mvaddstr(0, 0, "   Worth  Item");
+    oldpurse = purse;
+    for (c = 'a', obj = pack; obj != NULL; c++, obj = next(obj))
+    {
+	switch (obj->o_type)
+	{
+	    case FOOD:
+		worth = 2 * obj->o_count;
+	    when WEAPON:
+		switch (obj->o_which)
+		{
+		    case MACE: worth = 8;
+		    when SWORD: worth = 15;
+		    when CROSSBOW: worth = 30;
+		    when ARROW: worth = 1;
+		    when DAGGER: worth = 2;
+		    when TWOSWORD: worth = 75;
+		    when DART: worth = 1;
+		    when BOW: worth = 15;
+		    when BOLT: worth = 1;
+		    when SPEAR: worth = 5;
+		}
+		worth *= 3 * (obj->o_hplus + obj->o_dplus) + obj->o_count;
+		obj->o_flags |= ISKNOW;
+	    when ARMOR:
+		switch (obj->o_which)
+		{
+		    case LEATHER: worth = 20;
+		    when RING_MAIL: worth = 25;
+		    when STUDDED_LEATHER: worth = 20;
+		    when SCALE_MAIL: worth = 30;
+		    when CHAIN_MAIL: worth = 75;
+		    when SPLINT_MAIL: worth = 80;
+		    when BANDED_MAIL: worth = 90;
+		    when PLATE_MAIL: worth = 150;
+		}
+		worth += (9 - obj->o_ac) * 100;
+		worth += (10 * (a_class[obj->o_which] - obj->o_ac));
+		obj->o_flags |= ISKNOW;
+	    when SCROLL:
+		worth = s_magic[obj->o_which].mi_worth;
+		worth *= obj->o_count;
+		if (!s_know[obj->o_which])
+		    worth /= 2;
+		s_know[obj->o_which] = TRUE;
+	    when POTION:
+		worth = p_magic[obj->o_which].mi_worth;
+		worth *= obj->o_count;
+		if (!p_know[obj->o_which])
+		    worth /= 2;
+		p_know[obj->o_which] = TRUE;
+	    when RING:
+		worth = r_magic[obj->o_which].mi_worth;
+		if (obj->o_which == R_ADDSTR || obj->o_which == R_ADDDAM ||
+		    obj->o_which == R_PROTECT || obj->o_which == R_ADDHIT)
+			if (obj->o_ac > 0)
+			    worth += obj->o_ac * 100;
+			else
+			    worth = 10;
+		if (!(obj->o_flags & ISKNOW))
+		    worth /= 2;
+		obj->o_flags |= ISKNOW;
+		r_know[obj->o_which] = TRUE;
+	    when STICK:
+		worth = ws_magic[obj->o_which].mi_worth;
+		worth += 20 * obj->o_charges;
+		if (!(obj->o_flags & ISKNOW))
+		    worth /= 2;
+		obj->o_flags |= ISKNOW;
+		ws_know[obj->o_which] = TRUE;
+	    when AMULET:
+		worth = 1000;
+	}
+	if (worth < 0)
+	    worth = 0;
+	mvprintw(c - 'a' + 1, 0, "%c) %5d  %s", c, worth, inv_name(obj, FALSE));
+	purse += worth;
+    }
+    mvprintw(c - 'a' + 1, 0,"   %5d  Gold Pieces          ", oldpurse);
+    refresh();
+    score(purse, 2, 0);
+    exit(0);
+}
+
+/*
+ * killname:
+ *	Convert a code to a monster name
+ */
+char *
+killname(monst, doart)
+register char monst;
+bool doart;
+{
+    register const char *sp;
+    register bool article;
+
+    sp = prbuf;
+    article = TRUE;
+    switch (monst)
+    {
+	case 'a':
+	    sp = "arrow";
+	when 'b':
+	    sp = "bolt";
+	when 'd':
+	    sp = "dart";
+	when 's':
+	    sp = "starvation";
+	    article = FALSE;
+	otherwise:
+	    if (monst >= 'A' && monst <= 'Z')
+		sp = monsters[monst-'A'].m_name;
+	    else
+	    {
+		sp = "God";
+		article = FALSE;
+	    }
+    }
+    if (doart && article)
+	sprintf(prbuf, "a%s ", vowelstr(sp));
+    else
+	prbuf[0] = '\0';
+    strcat(prbuf, sp);
+    return prbuf;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rogue4/rogue.6	Sat Oct 24 16:52:52 2009 +0000
@@ -0,0 +1,67 @@
+.TH ROGUE 6 "1 April 1981"
+.UC 4
+.SH NAME
+rogue \- Exploring The Dungeons of Doom
+.SH SYNOPSIS
+.B rogue
+[
+.I save_file
+]
+.SH DESCRIPTION
+.PP
+.I Rogue
+is a computer fantasy game with a new twist.  It is crt oriented and the
+object of the game is to survive the attacks of various monsters and get
+a lot of gold, rather than the puzzle solving orientation of most computer
+fantasy games.
+.PP
+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.
+.PP
+To win the game (as opposed to merely playing to beat other people high
+scores) you must locate the Amulet of Yendor which is somewhere below
+the 20th level of the dungeon and get it out.  Nobody has achieved this
+yet and if somebody does, they will probably go down in history as a hero
+among heros.
+.PP
+When the game ends, either by your death, when you quit, or if you (by
+some miracle) manage to win,
+.I rogue
+will give you alist of the top-ten scorers.  The scoring is based entirely
+upon how much gold you get.  There is a 10% penalty for getting yourself
+killed.
+.PP
+For more detailed directions, read the document
+.I "A Guide to the Dungeons of Doom."
+.SH FILES
+.DT
+.B Score file is searched for in these directories:
+.PP
+$ROGUEHOME/rogue52.scr
+.br
+/var/games/roguelike/rogue52.scr
+.br
+/var/lib/roguelike/rogue52.scr
+.br
+/var/roguelike/rogue52.scr
+.br
+/usr/games/lib/rogue52.scr
+.br
+/games/roguelik/rogue52.scr
+.br
+rogue52.scr
+.PP
+.B Default save file
+.PP
+~/rogue.sav
+.SH SEE ALSO
+Michael C. Toy,
+.I "A guide to the Dungeons of Doom"
+.SH BUGS
+.PP
+Probably infinite.  Currently known bugs are: Sometimes you are still hungry
+even after you eat food and sometimes you get a monster on the screen in
+reverse video which may or may not cause a core dump.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rogue4/rogue.h	Sat Oct 24 16:52:52 2009 +0000
@@ -0,0 +1,486 @@
+/*
+ * Rogue definitions and variable declarations
+ *
+ * @(#)rogue.h	5.2 (Berkeley) 5/10/82
+ *
+ * Rogue: Exploring the Dungeons of Doom
+ * Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman
+ * All rights reserved.
+ *
+ * See the file LICENSE.TXT for full copyright and licensing information.
+ */
+
+typedef struct { 
+    const char *st_name;
+    const int   st_value;
+} STONE;
+   
+extern const char *rainbow[];
+extern const STONE stones[];
+extern const char *sylls[];
+extern const char *wood[];
+extern const char *metal[];
+
+#define NCOLORS 27
+#define NSYLLS  159
+#define NSTONES 26
+#define NWOOD   33
+#define NMETAL  22
+
+/*
+ * Maximum number of different things
+ */
+#define MAXDAEMONS  20
+#define MAXROOMS	9
+#define MAXTHINGS	9
+#define MAXOBJ		9
+#define MAXPACK		23
+#define MAXTRAPS	10
+#define AMULETLEVEL	26
+#define	NUMTHINGS	7	/* number of types of things */
+#define MAXPASS		13	/* upper limit on number of passages */
+
+/*
+ * return values for get functions
+ */
+#define	NORM	0	/* normal exit */
+#define	QUIT	1	/* quit option setting */
+#define	MINUS	2	/* back up one option */
+
+/*
+ * All the fun defines
+ */
+#define shint		char		/* short integer (for very small #s) */
+#define when		break;case
+#define otherwise	break;default
+#define until(expr)	while(!(expr))
+#define next(ptr)	(*ptr).l_next
+#define prev(ptr)	(*ptr).l_prev
+#define winat(y,x)	(moat(y,x) != NULL ? moat(y,x)->t_disguise : chat(y,x))
+#define DISTANCE(y1, x1, y2, x2) ((x2 - x1)*(x2 - x1) + (y2 - y1)*(y2 - y1))
+#define ce(a,b)		((a).x == (b).x && (a).y == (b).y)
+#define hero		player.t_pos
+#define pstats		player.t_stats
+#define pack		player.t_pack
+#define proom		player.t_room
+#define max_hp		player.t_stats.s_maxhp
+#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 on(thing,flag)	(((thing).t_flags & (flag)) != 0)
+#undef CTRL
+#define CTRL(ch)	(ch & 037)
+#define GOLDCALC	(rnd(50 + 10 * level) + 2)
+#define ISRING(h,r)	(cur_ring[h] != NULL && cur_ring[h]->o_which == r)
+#define ISWEARING(r)	(ISRING(LEFT, r) || ISRING(RIGHT, r))
+#define ISMULT(type) 	(type==POTION || type==SCROLL || type==FOOD || type==GOLD)
+#define INDEX(y,x)	(((x) << 5) + (y))
+#define chat(y,x)	(_level[((x) << 5) + (y)])
+#define flat(y,x)	(_flags[((x) << 5) + (y)])
+#define moat(y,x)	(_monst[((x) << 5) + (y)])
+#define unc(cp)		(cp).y, (cp).x
+#ifdef WIZARD
+#define debug		if (wizard) msg
+#endif
+
+/*
+ * Things that appear on the screens
+ */
+#define PASSAGE		'#'
+#define DOOR		'+'
+#define FLOOR		'.'
+#define PLAYER		'@'
+#define TRAP		'^'
+#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
+
+/*
+ * Various constants
+ */
+#define	PASSWD		"mTuZ7WUV9RWkQ"
+#define BEARTIME	spread(3)
+#define SLEEPTIME	spread(5)
+#define HEALTIME	spread(30)
+#define HOLDTIME	spread(2)
+#define WANDERTIME	spread(70)
+#define BEFORE		spread(1)
+#define AFTER		spread(2)
+#define HUHDURATION	spread(20)
+#define SEEDURATION	spread(850)
+#define HUNGERTIME	spread(1300)
+#define MORETIME	150
+#define STOMACHSIZE	2000
+#define STARVETIME	850
+#define ESCAPE		27
+#define LEFT		0
+#define RIGHT		1
+#define BOLT_LENGTH	6
+#define LAMPDIST	3
+
+/*
+ * Save against things
+ */
+#define VS_POISON	00
+#define VS_PARALYZATION	00
+#define VS_DEATH	00
+#define VS_BREATH	02
+#define VS_MAGIC	03
+
+/*
+ * Various flag bits
+ */
+/* flags for rooms */
+#define ISDARK	0000001		/* room is dark */
+#define ISGONE	0000002		/* room is gone (a corridor) */
+
+/* flags for objects */
+#define ISCURSED 000001		/* object is cursed */
+#define ISKNOW	0000002		/* player knows details about the object */
+#define ISMISL	0000004		/* object is a missile type */
+#define ISMANY	0000010		/* object comes in groups */
+
+/* flags for creatures */
+#define CANHUH	0000001		/* creature can confuse */
+#define CANSEE	0000002		/* creature can see invisible creatures */
+#define ISBLIND	0000004		/* creature is blind */
+#define ISCANC	0000010		/* creature has special qualities cancelled */
+#define ISFOUND	0000020		/* creature has been seen (used for objects) */
+#define ISGREED	0000040		/* creature runs to protect gold */
+#define ISHASTE	0000100		/* creature has been hastened */
+#define ISHELD	0000400		/* creature has been held */
+#define ISHUH	0001000		/* creature is confused */
+#define ISINVIS	0002000		/* creature is invisible */
+#define ISMEAN	0004000		/* creature can wake when player enters room */
+#define ISREGEN	0010000		/* creature can regenerate */
+#define ISRUN	0020000		/* creature is running at the player */
+#define SEEMONST 040000		/* hero can detect unseen monsters */
+#define ISSLOW	0100000		/* creature has been slowed */
+
+/*
+ * Flags for level map
+ */
+#define F_PASS		0x80		/* is a passageway */
+#define F_SEEN		0x40		/* have seen this corridor before */
+#define F_DROPPED	0x20		/* object was dropped here */
+#define F_LOCKED	0x20		/* door is locked */
+#define F_REAL		0x10		/* what you see is what you get */
+#define F_PNUM		0x0f		/* passage number mask */
+#define F_TMASK		0x07		/* trap number mask */
+
+/*
+ * Trap types
+ */
+#define T_DOOR	00
+#define T_ARROW	01
+#define T_SLEEP	02
+#define T_BEAR	03
+#define T_TELEP	04
+#define T_DART	05
+#define NTRAPS	6
+
+/*
+ * Potion types
+ */
+#define P_CONFUSE	0
+#define P_PARALYZE	1
+#define P_POISON	2
+#define P_STRENGTH	3
+#define P_SEEINVIS	4
+#define P_HEALING	5
+#define P_MFIND		6
+#define	P_TFIND 	7
+#define	P_RAISE		8
+#define P_XHEAL		9
+#define P_HASTE		10
+#define P_RESTORE	11
+#define P_BLIND		12
+#define P_NOP		13
+#define MAXPOTIONS	14
+
+/*
+ * Scroll types
+ */
+#define S_CONFUSE	0
+#define S_MAP		1
+#define S_HOLD		2
+#define S_SLEEP		3
+#define S_ARMOR		4
+#define S_IDENT		5
+#define S_SCARE		6
+#define S_GFIND		7
+#define S_TELEP		8
+#define S_ENCH		9
+#define S_CREATE	10
+#define S_REMOVE	11
+#define S_AGGR		12
+#define S_NOP		13
+#define S_GENOCIDE	14
+#define MAXSCROLLS	15
+
+/*
+ * Weapon types
+ */
+#define MACE		0
+#define SWORD		1
+#define BOW		2
+#define ARROW		3
+#define DAGGER		4
+#define TWOSWORD	5
+#define DART		6
+#define CROSSBOW	7
+#define BOLT		8
+#define SPEAR		9
+#define FLAME		10	/* fake entry for dragon breath (ick) */
+#define MAXWEAPONS	10	/* this should equal FLAME */
+
+/*
+ * Armor types
+ */
+#define LEATHER		0
+#define RING_MAIL	1
+#define STUDDED_LEATHER	2
+#define SCALE_MAIL	3
+#define CHAIN_MAIL	4
+#define SPLINT_MAIL	5
+#define BANDED_MAIL	6
+#define PLATE_MAIL	7
+#define MAXARMORS	8
+
+/*
+ * Ring types
+ */
+#define R_PROTECT	0
+#define R_ADDSTR	1
+#define R_SUSTSTR	2
+#define R_SEARCH	3
+#define R_SEEINVIS	4
+#define R_NOP		5
+#define R_AGGR		6
+#define R_ADDHIT	7
+#define R_ADDDAM	8
+#define R_REGEN		9
+#define R_DIGEST	10
+#define R_TELEPORT	11
+#define R_STEALTH	12
+#define R_SUSTARM	13
+#define MAXRINGS	14
+
+/*
+ * Rod/Wand/Staff types
+ */
+
+#define WS_LIGHT	0
+#define WS_HIT		1
+#define WS_ELECT	2
+#define WS_FIRE		3
+#define WS_COLD		4
+#define WS_POLYMORPH	5
+#define WS_MISSILE	6
+#define WS_HASTE_M	7
+#define WS_SLOW_M	8
+#define WS_DRAIN	9
+#define WS_NOP		10
+#define WS_TELAWAY	11
+#define WS_TELTO	12
+#define WS_CANCEL	13
+#define MAXSTICKS	14
+
+/*
+ * Now we define the structures and types
+ */
+
+/*
+ * Help list
+ */
+
+struct h_list {
+    char h_ch;
+    char *h_desc;
+};
+
+/*
+ * Coordinate data type
+ */
+typedef struct {
+    shint x;
+    shint y;
+} coord;
+
+/* daemon/fuse data type */
+
+struct delayed_action {
+    int d_type;
+    int (*d_func)();
+    int d_arg;
+    int d_time;
+};
+
+/**/
+
+typedef unsigned int str_t;
+
+/*
+ * Stuff about magic items
+ */
+
+struct magic_item {
+    const char *mi_name;
+    shint mi_prob;
+    short mi_worth;
+};
+
+/*
+ * Room structure
+ */
+struct room {
+    coord r_pos;			/* Upper left corner */
+    coord r_max;			/* Size of room */
+    coord r_gold;			/* Where the gold is */
+    int r_goldval;			/* How much the gold is worth */
+    short r_flags;			/* Info about the room */
+    shint r_nexits;			/* Number of exits */
+    coord r_exit[12];			/* Where the exits are */
+};
+
+/*
+ * Structure describing a fighting being
+ */
+struct stats {
+    str_t s_str;			/* Strength */
+    long s_exp;				/* Experience */
+    shint s_lvl;			/* Level of mastery */
+    shint s_arm;			/* Armor class */
+    short s_hpt;			/* Hit points */
+    char s_dmg[16];			/* String describing damage done */
+    shint s_maxhp;			/* Max hit points */
+};
+
+/*
+ * Structure for monsters and player
+ */
+union thing {
+    struct {
+	union thing *_l_next, *_l_prev;	/* Next pointer in link */
+	coord _t_pos;			/* Position */
+	bool _t_turn;			/* If slowed, is it a turn to move */
+	unsigned char _t_type;		/* What it is */
+	char _t_disguise;		/* What mimic looks like */
+	char _t_oldch;			/* Character that was where it was */
+	coord *_t_dest;			/* Where it is running to */
+	short _t_flags;			/* State word */
+	struct stats _t_stats;		/* Physical description */
+	struct room *_t_room;		/* Current room for thing */
+	union thing *_t_pack;		/* What the thing is carrying */
+    int  _t_reserved;
+    } _t;
+    struct {
+	union thing *_l_next, *_l_prev;	/* Next pointer in link */
+	shint _o_type;			/* What kind of object it is */
+	coord _o_pos;			/* Where it lives on the screen */
+	char *_o_text;			/* What it says if you read it */
+	char _o_launch;			/* What you need to launch it */
+	char _o_damage[8];		/* Damage if used like sword */
+	char _o_hurldmg[8];		/* Damage if thrown */
+	shint _o_count;			/* Count for plural objects */
+	shint _o_which;			/* Which object of a type it is */
+	shint _o_hplus;			/* Plusses to hit */
+	shint _o_dplus;			/* Plusses to damage */
+	short _o_ac;			/* Armor class */
+	short _o_flags;			/* Information about objects */
+	shint _o_group;			/* Group number for this object */
+    } _o;
+};
+
+typedef union thing THING;
+
+#define l_next		_t._l_next
+#define l_prev		_t._l_prev
+#define t_pos		_t._t_pos
+#define t_turn		_t._t_turn
+#define t_type		_t._t_type
+#define t_disguise	_t._t_disguise
+#define t_oldch		_t._t_oldch
+#define t_dest		_t._t_dest
+#define t_flags		_t._t_flags
+#define t_stats		_t._t_stats
+#define t_pack		_t._t_pack
+#define t_room		_t._t_room
+#define t_reserved      _t._t_reserved
+#define o_type		_o._o_type
+#define o_pos		_o._o_pos
+#define o_text		_o._o_text
+#define o_launch	_o._o_launch
+#define o_damage	_o._o_damage
+#define o_hurldmg	_o._o_hurldmg
+#define o_count		_o._o_count
+#define o_which		_o._o_which
+#define o_hplus		_o._o_hplus
+#define o_dplus		_o._o_dplus
+#define o_ac		_o._o_ac
+#define o_charges	o_ac
+#define o_goldval	o_ac
+#define o_flags		_o._o_flags
+#define o_group		_o._o_group
+#define o_reserved      _o._o_reserved
+
+/*
+ * Array containing information on all the various types of mosnters
+ */
+struct monster {
+    const char *m_name;			/* What to call the monster */
+    const shint m_carry;			/* Probability of carrying something */
+    const short m_flags;			/* Things about the monster */
+    struct stats m_stats;		/* Initial stats */
+};
+
+/*
+ * External variables
+ */
+
+extern struct delayed_action d_list[20];
+
+extern THING	*_monst[], *cur_armor, *cur_ring[], *cur_weapon,
+		*lvl_obj, *mlist, player;
+
+extern coord	delta, oldpos;
+
+extern struct h_list	helpstr[];
+
+extern struct room	*oldrp, passages[], rooms[];
+
+extern struct stats	max_stats;
+
+extern struct monster	monsters[];
+
+extern struct magic_item	p_magic[], r_magic[], s_magic[],
+				things[], ws_magic[];
+
+/*
+ * Function types
+ */
+
+coord	*find_dest(), *rndmove();
+
+THING	*find_mons(), *find_obj(), *get_item(), *new_item(),
+	*new_thing(), *wake_monster();
+
+struct room	*roomin();
+
+#include "extern.h"
+
+#ifndef PATH_MAX
+#define PATH_MAX _MAX_PATH
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rogue4/rogue.me	Sat Oct 24 16:52:52 2009 +0000
@@ -0,0 +1,787 @@
+.ds E \s-2<ESCAPE>\s0
+.ds R \s-2<RETURN>\s0
+.ds U \s-2UNIX\s0
+.ie t .ds _ \d\(mi\u
+.el .ds _ _
+.de Cs
+\&\\$3\*(lq\\$1\*(rq\\$2
+..
+.sp 5
+.ce 1000
+.ps +4
+.vs +4p
+.b
+A Guide to the Dungeons of Doom
+.r
+.vs
+.ps
+.sp 2
+.i
+Michael C. Toy
+Kenneth C. R. C. Arnold
+.r
+.sp 2
+Computer Systems Research Group
+Department of Electrical Engineering and Computer Science
+University of California
+Berkeley, California  94720
+.sp 4
+.i ABSTRACT
+.ce 0
+.(b I F
+.bi Rogue
+is a visual CRT based fantasy game
+which runs under the \*U\(dg timesharing system.
+.(f
+\fR\(dg\*U is a trademark of Bell Laboratories\fP
+.)f
+This paper describes how to play rogue,
+and gives a few hints
+for those who might otherwise get lost in the Dungeons of Doom.
+.)b
+.he '''\fBA Guide to the Dungeons of Doom\fP'
+.fo ''- % -''
+.bp 1
+.sh 1 Introduction
+.pp
+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.
+.pp
+In preparation for your journey,
+you are given an enchanted mace,
+a bow, and a quiver of arrows
+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 goodbye to family and friends for what may be the last time
+and head up the road.
+.pp
+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 mace,
+put on your armor,
+eat what is almost your last food,
+and enter the dungeons.
+.sh 1 "What is going on here?"
+.pp
+You have just begun a game of rogue.
+Your goal is to grab as much treasure as you can,
+find the Amulet of Yendor,
+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.
+.pp
+Rogue differs from most computer fantasy games in that it is screen oriented.
+Commands are all one or two keystrokes\**
+.(f
+\** As opposed to pseudo English sentences.
+.)f
+and the results of your commands
+are displayed graphically on the screen rather
+than being explained in words.
+.pp
+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.
+.sh 1 "What do all those things on the screen mean?"
+.pp
+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 \*(lqYou can see ...\*(rq descriptions
+of standard fantasy games.
+Figure 1 is a sample of what a rogue screen might look like.
+.(z
+.hl
+.nf
+.TS
+center;
+ce0 ce0 ce0 ce0 ce0 ce0 ce0 ce0 ce0 ce0 ce0 ce.
+-	-	-	-	-	-	-	-	-	-	-	-
+|	.	.	.	.	.	.	.	.	.	.	+
+|	.	.	@	.	.	.	.	]	.	.	|
+|	.	.	.	.	B	.	.	.	.	.	|
+|	.	.	.	.	.	.	.	.	.	.	|
+-	-	-	-	-	+	-	-	-	-	-	-
+.TE
+
+
+.ce 1000
+Level: 1  Gold: 0      Hp: 12(12)  Str: 16(16)  Ac: 6  Exp: 1/0
+
+Figure 1
+.ce
+.hl
+.)z
+.sh 2 "The bottom line"
+.pp
+At the bottom line of the screen
+are a few pieces of cryptic information
+describing your current status.
+Here is an explanation of what these things mean:
+.ip Level \w'Level\ \ 'u
+This number indicates how deep you have gone in the dungeon.
+It starts at one and goes up as you go deeper into the dungeon.
+.ip Gold \w'Level\ \ 'u
+The number of gold pieces you have managed to find
+and keep with you so far.
+.ip Hp \w'Level\ \ 'u
+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 resting.
+The number in parentheses
+is the maximum number your hit points can reach.
+.ip Str \w'Level\ \ 'u
+Your current strength and maximum ever strength.
+This can be any integer less than or equal to 31,
+or greater than or equal to three.
+The higher the number,
+the stronger you are.
+The number in the parentheses
+is the maximum strength you have attained so far this game.
+.ip Ac \w'Level\ \ 'u
+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.
+.ip Exp \w'Level\ \ 'u
+These two numbers give your current experience level
+and experience points.
+As you do things,
+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.
+.sh 2 "The top line"
+.pp
+The top line of the screen is reserved
+for printing messages that describe things
+that are impossible to represent visually.
+If you see a \*(lq--More--\*(rq 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 type a space.
+.sh 2 "The rest of the screen"
+.pp
+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:
+.ip @
+This symbol represents you, the adventurer.
+.ip "-\^|"
+These symbols represent the walls of rooms.
+.ip +
+A door to/from a room.
+.ip .
+The floor of a room.
+.ip #
+The floor of a passage between rooms.
+.ip *
+A pile or pot of gold.
+.ip )
+A weapon of some sort.
+.ip ]
+A piece of armor.
+.ip !
+A flask containing a magic potion.
+.ip ?
+A piece of paper, usually a magic scroll.
+.ip =
+A ring with magic properties
+.ip /
+A magical staff or wand
+.ip ^
+A trap, watch out for these.
+.ip %
+A staircase to other levels
+.ip :
+A piece of food.
+.ip A-Z
+The uppercase letters
+represent the various inhabitants of the Dungeons of Doom.
+Watch out, they can be nasty and vicious.
+.sh 1 Commands
+.pp
+Commands are given to rogue by typing one or two characters.
+Most commands can be preceded by a count to repeat them
+(e.g. typing 
+.Cs 10s
+will do ten searches).
+Commands for which counts make no sense
+have the count ignored.
+To cancel a count or a prefix,
+type \*E.
+The list of commands is rather long,
+but it can be read at any time during the game with the
+.Cs ?
+command.
+Here it is for reference,
+with a short explanation of each command.
+.ip ?
+The help command.
+Asks for a character to give help on.
+If you type a
+.Cs * ,
+it will list all the commands,
+otherwise it will explain what the character you typed does.
+.ip /
+This is the \*(lqWhat is that on the screen?\*(rq command.
+A
+.Cs /
+followed by any character that you see on the level,
+will tell you what that character is.
+For instance,
+typing
+.Cs /@
+will tell you that the
+.Cs @
+symbol represents you, the player.
+.ip "h, H"
+Move left.
+You move one space to the left.
+If you use upper case
+.Cs h ,
+you will continue to move left until you run into something.
+This works for all movement commands
+(e.g.
+.Cs L
+means run in direction 
+.Cs l )
+.ip j
+Move down.
+.ip k
+Move up.
+.ip l
+Move right.
+.ip y
+Move diagonally up and left.
+.ip u
+Move diagonally up and right.
+.ip b
+Move diagonally down and left.
+.ip n
+Move diagonally down and right.
+.ip t
+Throw an object.
+This is a prefix command.
+When followed with a direction
+it throws an object in the specified direction.
+(e.g. type
+.Cs th
+to throw
+something to the left.)
+.ip f
+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.
+You should experiment with this,
+since it is a very useful command,
+but very difficult to describe.
+.ip z
+Zap prefix.
+Point a staff or wand in a given direction
+and fire it.
+Even non-directional staves must be pointed in some direction
+to be used.
+.ip ^
+Identify trap command.
+If a trap is on your map
+and you can't remember what type it is,
+you can get rogue to remind you
+by getting next to it and typing
+.Cs ^
+followed by the direction that would move you on top of it.
+.ip s
+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.
+.ip >
+Climb down a staircase to the next level.
+Not surprisingly, this can only be done if you are standing on staircase.
+.ip <
+Climb up a staircase to the level above.
+This can't be done without the Amulet of Yendor in your posession.
+.ip "."
+Rest.
+This is the \*(lqdo nothing\*(rq command.
+This is good for waiting and healing.
+.ip i
+Inventory.
+List what you are carrying in your pack.
+.ip I
+Selective inventory.
+Tells you what a single item in your pack is.
+.ip q
+Quaff one of the potions you are carrying.
+.ip r
+Read one of the scrolls in your pack.
+.ip e
+Eat food from your pack.
+.ip w
+Wield a weapon.
+Take a weapon out of your pack and carry it for use in combat,
+replacing the one you are currently using (if any).
+.ip W
+Wear armor.
+You can only wear one suit of armor at a time.
+This takes extra time.
+.ip T
+Take armor off.
+You can't remove armor that is cursed.
+This takes extra time.
+.ip P
+Put on a ring.
+You can wear only two rings at a time
+(one on each hand).
+If you aren't wearing any rings,
+this command will ask you which hand you want to wear it on,
+otherwise, it will place it on the unused hand.
+The program assumes that you wield your sword in your right hand.
+.ip R
+Remove a ring.
+If you are only wearing one ring,
+this command takes it off.
+If you are wearing two,
+it will ask you which one you wish to remove,
+.ip d
+Drop an object.
+Take something out of your pack and leave it lying on the floor.
+Only one object can occupy each space.
+You cannot drop a cursed object at all
+if you are wielding or wearing it.
+.ip c
+Call an object something.
+If you have a type of object in your pack
+which you wish to remember something about,
+you can use the call command to give a name to that type of object.
+This is usually used when you figure out what a
+potion, scroll, ring, or staff is
+after you pick it up.
+(See the
+.Cs askme
+option below.)
+.ip D
+Print out which things you've discovered something about.
+This command will ask you what type of thing you are interested in.
+If you type the character for a given type of object
+(\fIe.g.\fP
+.Cs !
+for potion)
+it will tell you which kinds of that type of object you've discovered
+(\fIi.e.\fP, figured out what they are).
+This command works for potions, scrolls, rings, and staves and wands.
+.ip o
+Examine and set options.
+This command is further explained in the section on options.
+.ip ^L
+Redraws the screen.
+Useful if spurious messages or transmission errors
+have messed up the display.
+.ip ^R
+Repeat last message.
+Useful when a message disappears before you can read it.
+This only repeats the last message
+that was not a mistyped command
+so that you don't loose anything by accidentally typing
+the wrong character instead of ^R.
+.ip \*E
+Cancel a command, prefix, or count.
+.ip !
+Escape to a shell for some commands.
+.ip Q
+Quit.
+Leave the game.
+.ip S
+Save the current game in a file.
+It will ask you whether you wish to use the default save file.
+.i Caveat :
+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.
+To restore a saved game,
+give the file name as an argument to rogue.
+As in
+.ti +1i
+.nf
+% rogue \fIsave\*_file\fP
+.ip
+To restart from the default save file (see below),
+run
+.ti +1i
+.nf
+% rogue \-r
+.ip v
+Prints the program version number.
+.sh 1 Rooms
+.pp
+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,
+it will only be displayed as you explore it.
+Upon leaving a room,
+all objects inside the room which might move
+or be removed
+are erased from the screen.
+In the darkness you can only see one space
+in all directions around you.
+A corridor is always dark.
+.sh 1 Fighting
+.pp
+If you see a monster and you wish to fight it,
+just attempt to run into it.
+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.
+.sh 1 "Objects you can find"
+.pp
+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,
+the program will tell you and it won't pick up the object,
+otherwise it will add it to your pack
+and tell you what you just picked up.
+.pp
+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 type an \*E and the command will be aborted.
+.pp
+Some objects, like armor and weapons,
+are easily differentiated.
+Others, like scrolls and potions,
+are given labels which vary according to type.
+During a game,
+any two of the same kind of object
+with the same label
+are the same type.
+However,
+the labels will vary from game to game.
+.pp
+When you use one of these labeled objects,
+if its effect is obvious,
+rogue will remember what it is for you.
+If it's effect isn't extremely obvious, you can use the
+.Cs call
+command
+(see above)
+or the
+.Cs askme
+option
+(see below)
+to scribble down something about it
+so you will recognize it later.
+.sh 2 Weapons
+.pp
+Some weapons,
+like arrows,
+come in bunches,
+but most come one at a time.
+In order to use a weapon,
+you must wield it.
+To fire an arrow out of a bow,
+you must first wield the bow,
+then throw the arrow.
+You can only wield one weapon at a time,
+but you can't change weapons if the one
+you are currently wielding is cursed.
+.sh 2 Armor
+.pp
+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.
+Here is a list of the various armor types and their normal armor class:
+.(b
+.TS
+center;
+l r.
+Type	Class
+=
+None	10
+Leather armor	8
+Studded leather / Ring mail	7
+Scale mail	6
+Chain mail	5
+Banded mail / Splint mail	4
+Plate mail	3
+.TE
+.)b
+.lp
+If a piece of armor is enchanted,
+its armor class will be lower than normal.
+If a suit of armor is cursed,
+its armor class will be higher,
+and you will not be able to remove it.
+However, not all armor with a class that is higher than normal is cursed.
+.sh 2 Scrolls
+.pp
+Scrolls come with titles in an unknown tongue.
+After you read a scroll,
+it disappears from your pack.
+.sh 2 Potions
+.pp
+Potions are labeled by the color of the liquid inside the flask.
+They disappear after being quaffed.
+.sh 2 "Staves and Wands"
+.pp
+Staves and wands do the same kinds of things.
+Staves are identified by a type of wood;
+wands by a type of metal or bone.
+They are generally things you want to do to something
+over a long distance,
+so you must point them at what you wish to affect
+to use them.
+Some staves are not affected by the direction they are pointed, though.
+Staves come with multiple magic charges,
+the number being random,
+and when they are used up,
+the staff is just a piece of wood or metal.
+.sh 2 Rings
+.pp
+Rings are very useful items,
+since they are relatively permanent magic,
+unlike the usually fleeting effects of potions, scrolls, and staves.
+Of course,
+the bad rings are also more powerful.
+Most rings also cause you to use up food more rapidly,
+the rate varying with the type of ring.
+Rings are differentiated by their stone settings.
+.sh 1 Options
+.pp
+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.
+.sh 2 "Setting the options"
+.pp
+There are two ways to set the options.
+The first is with the
+.Cs o
+command of rogue;
+the second is with the
+.Cs ROGUEOPTS
+environment variable\**.
+.(f
+\** On Version 6 systems,
+there is no equivalent of the ROGUEOPTS feature.
+.br
+.)f
+.br
+.sh 3 "Using the `o' command"
+.pp
+When you type
+.Cs o
+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 \*R
+which means to go to the next option,
+a
+.Cs \-
+which means to go to the previous option,
+an \*E
+which means to return to the game,
+or you can give the option a value.
+For boolean options this merely involves typing
+.Cs t
+for true or
+.Cs f
+for false.
+For string options,
+type the new value followed by a \*R.
+.sh 3 "Using the ROGUEOPTS variable"
+.pp
+The ROGUEOPTS variable is a string
+containing a comma separated list of initial values
+for the various options.
+Boolean variables can be turned on by listing their name
+or turned off by putting a
+.Cs no
+in front of the name.
+Thus to set up an environment variable so that
+.b jump
+is on,
+.b terse
+is off,
+and the
+.b name
+is set to \*(lqBlue Meanie\*(rq,
+use the command
+.nf
+.ti +3n
+% setenv ROGUEOPTS "jump,noterse,name=Blue Meanie"\**
+.fi
+.(f
+\**
+For those of you who use the bourne shell, the commands would be
+.in +3
+.nf
+$ ROGUEOPTS="jump,noterse,name=Blue Meanie"
+$ export ROGUEOPTS
+.fi
+.in +0
+.)f
+.sh 2 "Option list"
+.pp
+Here is a list of the options
+and an explanation of what each one is for.
+The default value for each is enclosed in square brackets.
+For character string options,
+input over fifty characters will be ignored.
+.ip "\fBterse\fP [\fI\^noterse\^\fP]"
+Useful for those who are tired of the sometimes lengthy messages of rogue.
+This is a useful option for playing on slow terminals,
+so this option defaults to
+.b terse
+if your
+are on a slow (1200 baud or under) terminal.
+.ip "\fBjump\fP [\fI\^nojump\^\fP]"
+If this option is set,
+running moves will not be displayed
+until you reach the end of the move.
+This saves considerable cpu and display time.
+This option defaults to
+.b jump
+if you are using a slow terminal.
+.ip "\fBstep\fP [\fI\^nostep\^\fP]"
+When
+.b step
+is set,
+lists of things,
+like inventories or
+.Cs *
+responses to
+\*(lqWhich item do you wish to \fB. . .\fP? \*(rq questions,
+are displayed one item at a time on the top of the screen,
+rather than clearing the screen,
+displaying the list,
+then re-displaying the dungeon level.
+.ip "\fBflush\fP [\fI\^noflush\^\fP]"
+All typeahead is thrown away after each round of battle.
+This is useful for those who type far ahead
+and then watch in dismay as a Kobold kills them.
+.ip "\fBaskme\fP [\fI\^noaskme\^\fP]"
+Upon reading a scroll or quaffing a potion
+which does not automatically identify itself upon use,
+rogue will ask you what to name it
+so you can recognize it if you encounter it again.
+.ip "\fBpassgo\fP [\fI\^nopassgo\^\fP]"
+Follow turnings in passageways.
+If you run in a passage
+and you run into stone or a wall,
+rogue will see if it can turn to the right or left.
+If it can only turn one way,
+it will turn that way.
+If it can turn either or neither,
+it will stop.
+This is followed strictly,
+which can sometimes lead to slightly confusing occurrences
+(which is why it defaults to being off).
+The
+.Cs f
+prefix still works.
+.ip "\fBname\fP [account name]"
+This is the name of your character.
+It is used if you get on the top ten scorer's list.
+.ip "\fBfruit\fP [\fI\^slime-mold\^\fP]"
+This should hold the name of a fruit that you enjoy eating.
+It is basically a whimsey that the program uses in a couple of places.
+.ip "\fBfile\fP [\fI\^~/rogue.save\^\fP]"
+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
+.Cs ~
+which expands to be your home directory.
+.sh 1 Scoring
+.pp
+Rogue usually maintains a list
+of the top ten scoring people on your machine.
+Some installations limit each account on the machine
+to post only one non-winning score on this list, however
+this is no longer considered the default behavior.
+If you score higher than someone else on this list,
+or better your previous score on the list,
+you will be inserted in the proper place
+under your current name.
+.pp
+If you quit the game, you get out with all of your gold intact.
+If, however, you get killed in the Dungeons of Doom,
+your body is forwarded to your next-of-kin,
+along with 90% of your gold;
+ten percent of your gold is kept by the Dungeons' wizard as a fee.
+This should make you consider whether you want to take one last hit
+at that monster and possibly live,
+or quit and thus stop with whatever you have.
+If you quit, you do get all your gold,
+but if you swing and live, you might find more.
+.pp
+If you just want to see what the current top ten list is,
+you can type
+.ti +1i
+.nf
+% rogue \-s
+.br
+.sh 1 Acknowledgements
+.pp
+Rogue was originally conceived of by Glenn Wichman and Michael Toy.
+Ken Arnold and Michael Toy then smoothed out the user interface,
+and added jillions of new features.
+We would like to thank
+Bob Arnold,
+Michelle Busch,
+Andy Hatcher,
+Kipp Hickman,
+Mark Horton,
+Daniel Jensen,
+Bill Joy,
+Joe Kalash,
+Steve Maurer,
+Marty McNary,
+Jan Miller,
+and
+Scott Nelson
+for their ideas and assistance,
+and also the teeming multitudes
+who graciously ignored work, school, and social life to play rogue
+and send us bugs, complaints, suggestions, and just plain flames.
+And also Mom.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rogue4/rogue52.sln	Sat Oct 24 16:52:52 2009 +0000
@@ -0,0 +1,20 @@
+
+Microsoft Visual Studio Solution File, Format Version 9.00
+# Visual C++ Express 2005
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "rogue52", "rogue52.vcproj", "{8D92C587-9CBA-41FE-BB30-F0A7142AC625}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Win32 = Debug|Win32
+		Release|Win32 = Release|Win32
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{8D92C587-9CBA-41FE-BB30-F0A7142AC625}.Debug|Win32.ActiveCfg = Debug|Win32
+		{8D92C587-9CBA-41FE-BB30-F0A7142AC625}.Debug|Win32.Build.0 = Debug|Win32
+		{8D92C587-9CBA-41FE-BB30-F0A7142AC625}.Release|Win32.ActiveCfg = Release|Win32
+		{8D92C587-9CBA-41FE-BB30-F0A7142AC625}.Release|Win32.Build.0 = Release|Win32
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+EndGlobal
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rogue4/rogue52.vcproj	Sat Oct 24 16:52:52 2009 +0000
@@ -0,0 +1,405 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="8.00"
+	Name="rogue52"
+	ProjectGUID="{8D92C587-9CBA-41FE-BB30-F0A7142AC625}"
+	RootNamespace="rogue52"
+	Keyword="Win32Proj"
+	>
+	<Platforms>
+		<Platform
+			Name="Win32"
+		/>
+	</Platforms>
+	<ToolFiles>
+	</ToolFiles>
+	<Configurations>
+		<Configuration
+			Name="Debug|Win32"
+			OutputDirectory="Debug"
+			IntermediateDirectory="Debug"
+			ConfigurationType="1"
+			InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC70.vsprops"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				InlineFunctionExpansion="0"
+				AdditionalIncludeDirectories="../pdcurses"
+				PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_CRT_SECURE_NO_DEPRECATE;SCOREFILE;ALLSCORES"
+				StringPooling="true"
+				MinimalRebuild="true"
+				ExceptionHandling="0"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="1"
+				BufferSecurityCheck="true"
+				EnableFunctionLevelLinking="true"
+				DisableLanguageExtensions="false"
+				ForceConformanceInForLoopScope="true"
+				UsePrecompiledHeader="0"
+				BrowseInformation="0"
+				WarningLevel="4"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="4"
+				CompileAs="1"
+				DisableSpecificWarnings="4033;4716;4013;4131;4244;4201;4431;4127;4706;4100"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="Ws2_32.lib pdcurses.lib advapi32.lib shfolder.lib user32.lib"
+				OutputFile="$(OutDir)/rogue54.exe"
+				LinkIncremental="2"
+				AdditionalLibraryDirectories="../pdcurses"
+				IgnoreDefaultLibraryNames="LIBC.LIB"
+				GenerateDebugInformation="true"
+				ProgramDatabaseFile="$(OutDir)/rogue54.pdb"
+				SubSystem="1"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release|Win32"
+			OutputDirectory="Release"
+			IntermediateDirectory="Release"
+			ConfigurationType="1"
+			InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC70.vsprops"
+			CharacterSet="2"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="2"
+				InlineFunctionExpansion="1"
+				OmitFramePointers="true"
+				PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS"
+				StringPooling="true"
+				RuntimeLibrary="0"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				OutputFile="$(OutDir)/rogue54.exe"
+				LinkIncremental="1"
+				GenerateDebugInformation="true"
+				SubSystem="2"
+				OptimizeReferences="2"
+				EnableCOMDATFolding="2"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<Filter
+			Name="Source Files"
+			Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm"
+			>
+			<File
+				RelativePath="armor.c"
+				>
+			</File>
+			<File
+				RelativePath="chase.c"
+				>
+			</File>
+			<File
+				RelativePath="command.c"
+				>
+			</File>
+			<File
+				RelativePath="daemon.c"
+				>
+			</File>
+			<File
+				RelativePath="daemons.c"
+				>
+			</File>
+			<File
+				RelativePath="extern.c"
+				>
+			</File>
+			<File
+				RelativePath="fight.c"
+				>
+			</File>
+			<File
+				RelativePath="findpw.c"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="init.c"
+				>
+			</File>
+			<File
+				RelativePath="io.c"
+				>
+			</File>
+			<File
+				RelativePath="list.c"
+				>
+			</File>
+			<File
+				RelativePath="mach_dep.c"
+				>
+			</File>
+			<File
+				RelativePath="main.c"
+				>
+			</File>
+			<File
+				RelativePath="mdport.c"
+				>
+			</File>
+			<File
+				RelativePath="misc.c"
+				>
+			</File>
+			<File
+				RelativePath="monsters.c"
+				>
+			</File>
+			<File
+				RelativePath="move.c"
+				>
+			</File>
+			<File
+				RelativePath="new_level.c"
+				>
+			</File>
+			<File
+				RelativePath="options.c"
+				>
+			</File>
+			<File
+				RelativePath="pack.c"
+				>
+			</File>
+			<File
+				RelativePath="passages.c"
+				>
+			</File>
+			<File
+				RelativePath="potions.c"
+				>
+			</File>
+			<File
+				RelativePath=".\prob.c"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="rings.c"
+				>
+			</File>
+			<File
+				RelativePath="rip.c"
+				>
+			</File>
+			<File
+				RelativePath="rooms.c"
+				>
+			</File>
+			<File
+				RelativePath="save.c"
+				>
+			</File>
+			<File
+				RelativePath="scrolls.c"
+				>
+			</File>
+			<File
+				RelativePath="state.c"
+				>
+			</File>
+			<File
+				RelativePath="sticks.c"
+				>
+			</File>
+			<File
+				RelativePath="things.c"
+				>
+			</File>
+			<File
+				RelativePath="vers.c"
+				>
+			</File>
+			<File
+				RelativePath="weapons.c"
+				>
+			</File>
+			<File
+				RelativePath="wizard.c"
+				>
+			</File>
+			<File
+				RelativePath="xcrypt.c"
+				>
+			</File>
+			<File
+				RelativePath=".\xstr.c"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+			</File>
+		</Filter>
+		<Filter
+			Name="Header Files"
+			Filter="h;hpp;hxx;hm;inl;inc"
+			>
+			<File
+				RelativePath="extern.h"
+				>
+			</File>
+			<File
+				RelativePath="rogue.h"
+				>
+			</File>
+		</Filter>
+		<Filter
+			Name="Resource Files"
+			Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+			>
+		</Filter>
+		<File
+			RelativePath="LICENSE.TXT"
+			>
+		</File>
+		<File
+			RelativePath="Makefile"
+			>
+		</File>
+		<File
+			RelativePath="rogue.6"
+			>
+		</File>
+		<File
+			RelativePath="rogue.me"
+			>
+		</File>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rogue4/rooms.c	Sat Oct 24 16:52:52 2009 +0000
@@ -0,0 +1,275 @@
+/*
+ * Create the layout for the new level
+ *
+ * @(#)rooms.c	4.16 (Berkeley) 1/12/82
+ *
+ * Rogue: Exploring the Dungeons of Doom
+ * Copyright (C) 1980, 1981, 1982 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 <curses.h>
+#include "rogue.h"
+
+#define GOLDGRP 1
+
+/*
+ * do_rooms:
+ *	Create rooms and corridors with a connectivity graph
+ */
+do_rooms()
+{
+    register int i;
+    register struct room *rp;
+    register THING *tp;
+    register int left_out;
+    coord top;
+    coord bsze;
+    coord mp;
+
+    /*
+     * bsze is the maximum room size
+     */
+    bsze.x = COLS/3;
+    bsze.y = LINES/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 (rp->r_flags & ISGONE)
+	{
+	    /*
+	     * Place a gone room.  Make certain that there is a blank line
+	     * for passage drawing.
+	     */
+	    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;
+	    } until (rp->r_pos.y > 0 && rp->r_pos.y < LINES-1);
+	    continue;
+	}
+	if (rnd(10) < level - 1)
+	    rp->r_flags |= ISDARK;
+	/*
+	 * Find a place and size for a random room
+	 */
+	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);
+	} until (rp->r_pos.y != 0);
+	/*
+	 * Put the gold in
+	 */
+	if (rnd(2) == 0 && (!amulet || level >= max_level))
+	{
+	    register THING *gold;
+
+	    gold = new_item();
+	    gold->o_goldval = rp->r_goldval = GOLDCALC;
+	    rnd_pos(rp, &rp->r_gold);
+	    gold->o_pos = rp->r_gold;
+	    gold->o_flags = ISMANY;
+	    gold->o_group = GOLDGRP;
+	    gold->o_type = GOLD;
+	    attach(lvl_obj, gold);
+	}
+	draw_room(rp);
+	/*
+	 * Put the monster in
+	 */
+	if (rnd(100) < (rp->r_goldval > 0 ? 80 : 25))
+	{
+	    tp = new_item();
+	    do
+	    {
+		rnd_pos(rp, &mp);
+	    } until (winat(mp.y, mp.x) == FLOOR);
+	    new_monster(tp, randmonster(FALSE), &mp);
+	    give_pack(tp);
+	}
+    }
+}
+
+/*
+ * draw_room:
+ *	Draw a box around a room and lay down the floor
+ */
+draw_room(rp)
+register struct room *rp;
+{
+    register int y, x;
+
+    vert(rp, rp->r_pos.x);				/* Draw left side */
+    vert(rp, rp->r_pos.x + rp->r_max.x - 1);		/* Draw right side */
+    horiz(rp, rp->r_pos.y);				/* Draw top */
+    horiz(rp, rp->r_pos.y + rp->r_max.y - 1);		/* Draw bottom */
+    /*
+     * Put the floor down
+     */
+    for (y = rp->r_pos.y + 1; y < rp->r_pos.y + rp->r_max.y - 1; y++)
+	/*strrep(&chat(rp->r_pos.y + 1, j), FLOOR, rp->r_max.y - rp->r_pos.y - 2);*/
+	for (x = rp->r_pos.x + 1; x < rp->r_pos.x + rp->r_max.x - 1; x++)
+	    chat(y, x) = FLOOR;
+    /*
+     * Put the gold there
+     */
+    if (rp->r_goldval)
+	chat(rp->r_gold.y, rp->r_gold.x) = GOLD;
+}
+
+/*
+ * vert:
+ *	Draw a vertical line
+ */
+vert(rp, startx)
+register struct room *rp;
+register int startx;
+{
+    register int y;
+
+    for (y = rp->r_pos.y + 1; y <= rp->r_max.y + rp->r_pos.y - 1; y++)
+	chat(y, startx) = '|';
+}
+
+/*
+ * horiz:
+ *	Draw a horizontal line
+ */
+horiz(rp, starty)
+register struct room *rp;
+int starty;
+{
+    register int x;
+
+    for (x = rp->r_pos.x; x <= rp->r_pos.x + rp->r_max.x - 1; x++)
+	chat(starty, x) = '-';
+}
+
+/*
+ * rnd_pos:
+ *	Pick a random spot in a room
+ */
+rnd_pos(rp, cp)
+register struct room *rp;
+register coord *cp;
+{
+    cp->x = rp->r_pos.x + rnd(rp->r_max.x - 2) + 1;
+    cp->y = rp->r_pos.y + rnd(rp->r_max.y - 2) + 1;
+}
+
+/*
+ * enter_room:
+ *	Code that is executed whenver you appear in a room
+ */
+enter_room(cp)
+register coord *cp;
+{
+    register struct room *rp;
+    register int y, x;
+    register THING *tp;
+
+    rp = proom = roomin(cp);
+    if (rp->r_flags & ISGONE)
+    {
+	msg("in a gone room");
+	return;
+    }
+    door_open(rp);
+    if (!(rp->r_flags & ISDARK) && !on(player, ISBLIND))
+	for (y = rp->r_pos.y; y < rp->r_max.y + rp->r_pos.y; y++)
+	{
+	    move(y, rp->r_pos.x);
+	    for (x = rp->r_pos.x; x < rp->r_max.x + rp->r_pos.x; x++)
+	    {
+		tp = moat(y, x);
+		if (tp == NULL || !see_monst(tp))
+		    addch(chat(y, x));
+		else
+		    addch(tp->t_disguise);
+	    }
+	}
+}
+
+/*
+ * leave_room:
+ *	Code for when we exit a room
+ */
+leave_room(cp)
+register coord *cp;
+{
+    register int y, x;
+    register struct room *rp;
+    register char floor;
+    register char ch;
+
+    rp = proom;
+    proom = &passages[flat(cp->y, cp->x) & F_PNUM];
+    floor = ((rp->r_flags & ISDARK) && !on(player, ISBLIND)) ? ' ' : FLOOR;
+    for (y = rp->r_pos.y + 1; y < rp->r_max.y + rp->r_pos.y - 1; y++)
+	for (x = rp->r_pos.x + 1; x < rp->r_max.x + rp->r_pos.x - 1; x++)
+	    switch (ch = mvinch(y, x))
+	    {
+		case ' ':
+		case TRAP:
+		case STAIRS:
+		    break;
+		case FLOOR:
+		    if (floor == ' ')
+			addch(' ');
+		    break;
+		default:
+		    /*
+		     * to check for monster, we have to strip out
+		     * standout bit
+		     */
+		    if (isupper(toascii(ch)))
+			if (on(player, SEEMONST))
+			{
+			    standout();
+			    addch(ch);
+			    standend();
+			    break;
+			}
+			else
+                        {
+                            THING *tp = moat(y, x);
+
+                            if (tp != NULL)
+                                tp->t_oldch = floor;
+
+#ifdef WIZARD
+                            else
+                                msg("couldn't find monster in leave_room at (%d,%d)", y, x);
+#endif
+                        }
+
+		    addch(floor);
+	    }
+    door_open(rp);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rogue4/save.c	Sat Oct 24 16:52:52 2009 +0000
@@ -0,0 +1,342 @@
+/*
+ * save and restore routines
+ *
+ * @(#)save.c	4.15 (Berkeley) 5/10/82
+ *
+ * Rogue: Exploring the Dungeons of Doom
+ * Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman
+ * All rights reserved.
+ *
+ * See the file LICENSE.TXT for full copyright and licensing information.
+ */
+
+#include <curses.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+#define KERNEL
+#include <signal.h>
+#undef KERNEL
+#include "rogue.h"
+
+typedef struct stat STAT;
+
+extern char version[], encstr[];
+extern bool _endwin;
+
+STAT sbuf;
+
+/*
+ * save_game:
+ *	Implement the "save game" command
+ */
+save_game()
+{
+    register FILE *savef;
+    register int c;
+    char buf[MAXSTR];
+
+    /*
+     * get file name
+     */
+    mpos = 0;
+over:
+    if (file_name[0] != '\0')
+    {
+	for (;;)
+	{
+	    msg("save file (%s)? ", file_name);
+	    c = getchar();
+	    mpos = 0;
+	    if (c == ESCAPE)
+	    {
+		msg("");
+		return FALSE;
+	    }
+	    else if (c == 'n' || c == 'N' || c == 'y' || c == 'Y')
+		break;
+	    else
+		msg("please answer Y or N");
+	}
+	if (c == 'y' || c == 'Y')
+	{
+	    strcpy(buf, file_name);
+	    goto gotfile;
+	}
+    }
+
+    do
+    {
+	mpos = 0;
+	msg("file name: ");
+	buf[0] = '\0';
+	if (get_str(buf, stdscr) == QUIT)
+	{
+quit:
+	    msg("");
+	    return FALSE;
+	}
+	mpos = 0;
+gotfile:
+	/*
+	 * test to see if the file exists
+	 */
+	if (stat(buf, &sbuf) >= 0)
+	{
+	    for (;;)
+	    {
+		msg("File exists.  Do you wish to overwrite it?");
+		mpos = 0;
+		if ((c = readchar()) == ESCAPE)
+		    goto quit;
+		if (c == 'y' || c == 'Y')
+		    break;
+		else if (c == 'n' || c == 'N')
+		    goto over;
+		else
+		    msg("Please answer Y or N");
+	    }
+	    msg("file name: %s", buf);
+	}
+	strcpy(file_name, buf);
+	if ((savef = fopen(file_name, "w")) == NULL)
+	    msg(strerror(errno));	/* fake perror() */
+    } while (savef == NULL);
+
+    /*
+     * write out encrpyted file (after a stat)
+     * The fwrite is to force allocation of the buffer before the write
+     */
+    save_file(savef);
+    return TRUE;
+}
+
+/*
+ * auto_save:
+ *	Automatically save a file.  This is used if a HUP signal is
+ *	recieved
+ */
+void
+auto_save(int sig)
+{
+    register FILE *savef;
+
+    md_ignore_signals();
+
+    if (file_name[0] != '\0' && (savef = fopen(file_name, "w")) != NULL)
+	save_file(savef);
+    endwin();
+    exit(1);
+}
+
+/*
+ * save_file:
+ *	Write the saved game on the file
+ */
+save_file(savef)
+register FILE *savef;
+{
+    int slines = LINES;
+    int scols  = COLS;
+
+    /*
+     * close any open score file
+     */
+    close(fd);
+    move(LINES-1, 0);
+    refresh();
+    fstat(md_fileno(savef), &sbuf);
+    /*
+     * DO NOT DELETE.  This forces stdio to allocate the output buffer
+     * so that malloc doesn't get confused on restart
+     */
+    fwrite("junk", 1, 5, savef);
+
+    fseek(savef, 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);
+
+    fclose(savef);
+}
+
+/*
+ * restore:
+ *	Restore a saved game from a file with elaborate checks for file
+ *	integrity from cheaters
+ */
+restore(file, envp)
+register char *file;
+char **envp;
+{
+    register int inf;
+    register bool syml;
+    extern char **environ;
+    char buf[MAXSTR];
+    STAT sbuf2;
+    int slines, scols;
+
+    if (strcmp(file, "-r") == 0)
+	file = file_name;
+
+#ifdef SIGTSTP
+    /*
+     * If a process can be suspended, this code wouldn't work
+     */
+    signal(SIGTSTP, SIG_IGN);
+#endif
+
+    if ((inf = open(file, 0)) < 0)
+    {
+	perror(file);
+	return FALSE;
+    }
+
+    fflush(stdout);
+    encread(buf, strlen(version) + 1, inf);
+    if (strcmp(buf, version) != 0)
+    {
+        printf("Sorry, saved game is out of date.\n");
+        return FALSE;
+    }
+
+    fstat(inf, &sbuf2);
+    fflush(stdout);
+    syml = issymlink(file);
+    if (
+#ifdef WIZARD
+	!wizard &&
+#endif
+    md_unlink(file) < 0)
+    {
+	printf("Cannot unlink file\n");
+	return FALSE;
+    }
+
+    fflush(stdout);
+
+    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
+     */
+
+    initscr();
+
+    if (slines > LINES) 
+    { 
+        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) 
+    { 
+        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); 
+    }
+
+    hw = newwin(LINES, COLS, 0, 0);
+    keypad(stdscr,1);
+    
+    mpos = 0;
+    mvprintw(0, 0, "%s: %s", file, ctime(&sbuf2.st_mtime));
+
+    /*
+     * defeat multiple restarting from the same place
+     */
+#ifdef WIZARD
+    if (!wizard)
+#endif
+	if (sbuf2.st_nlink != 1 || syml)
+	{
+	    printf("Cannot restore from a linked file\n");
+	    return FALSE;
+	}
+
+    if (rs_restore_file(inf) == FALSE)
+    {
+	endwin();
+        printf("Cannot restore file\n");
+        return(FALSE);
+    }
+
+#ifdef SIGTSTP
+    signal(SIGTSTP, tstp);
+#endif
+    environ = envp;
+    strcpy(file_name, file);
+    setup();
+    clearok(curscr, TRUE);
+    touchwin(stdscr);
+    srand(getpid());
+    msg("file name: %s", file);
+	status();
+    playit();
+    return 0;
+}
+
+/*
+ * encwrite:
+ *	Perform an encrypted write
+ */
+encwrite(starta, size, outf)
+void *starta;
+unsigned int size;
+register FILE *outf;
+{
+    register char *ep;
+    register char *start = (char *) starta;
+    ep = encstr;
+
+    while (size--)
+    {
+	putc(*start++ ^ *ep++, outf);
+	if (*ep == '\0')
+	    ep = encstr;
+    }
+}
+
+/*
+ * encread:
+ *	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 = (char *) 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;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rogue4/scrolls.c	Sat Oct 24 16:52:52 2009 +0000
@@ -0,0 +1,269 @@
+/*
+ * Read a scroll and let it happen
+ *
+ * @(#)scrolls.c	4.21 (Berkeley) 4/6/82
+ *
+ * Rogue: Exploring the Dungeons of Doom
+ * Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman
+ * All rights reserved.
+ *
+ * See the file LICENSE.TXT for full copyright and licensing information.
+ */
+
+#include <curses.h>
+#include <ctype.h>
+#include "rogue.h"
+
+/*
+ * read_scroll:
+ *	Read a scroll from the pack and do the appropriate thing
+ */
+read_scroll()
+{
+    register THING *obj;
+    register int y, x;
+    register char ch;
+    register THING *op;
+    register int index;
+    register bool discardit = FALSE;
+
+    obj = get_item("read", SCROLL);
+    if (obj == NULL)
+	return;
+    if (obj->o_type != SCROLL)
+    {
+	if (!terse)
+	    msg("there is nothing on it to read");
+	else
+	    msg("nothing to read");
+	return;
+    }
+    msg("as you read the scroll, it vanishes");
+    /*
+     * Calculate the effect it has on the poor guy.
+     */
+    if (obj == cur_weapon)
+	cur_weapon = NULL;
+    switch (obj->o_which)
+    {
+	case S_CONFUSE:
+	    /*
+	     * Scroll of monster confusion.  Give him that power.
+	     */
+	    player.t_flags |= CANHUH;
+	    msg("your hands begin to glow red");
+	when S_ARMOR:
+	    if (cur_armor != NULL)
+	    {
+		cur_armor->o_ac--;
+		cur_armor->o_flags &= ~ISCURSED;
+		msg("your armor glows faintly for a moment");
+	    }
+	when S_HOLD:
+	    /*
+	     * Hold monster scroll.  Stop all monsters within two spaces
+	     * from chasing after the hero.
+	     */
+
+	    for (x = hero.x - 2; x <= hero.x + 2; x++)
+		if (x >= 0 && x < COLS)
+		    for (y = hero.y - 2; y <= hero.y + 2; y++)
+			if (y >= 0 && y <= LINES - 1)
+			    if ((op = moat(y, x)) != NULL)
+			    {
+				op->t_flags &= ~ISRUN;
+				op->t_flags |= ISHELD;
+			    }
+	when S_SLEEP:
+	    /*
+	     * Scroll which makes you fall asleep
+	     */
+	    s_know[S_SLEEP] = TRUE;
+	    no_command += rnd(SLEEPTIME) + 4;
+	    player.t_flags &= ~ISRUN;
+	    msg("you fall asleep");
+	when S_CREATE:
+	    /*
+	     * Create a monster
+	     * First look in a circle around him, next try his room
+	     * otherwise give up
+	     */
+	    {
+		register bool appear = 0;
+		coord mp;
+
+		/*
+		 * Search for an open place
+		 */
+		for (y = hero.y - 1; y <= hero.y + 1; y++)
+		    for (x = hero.x - 1; x <= hero.x + 1; x++)
+		    {
+			/*
+			 * Don't put a monster in top of the player.
+			 */
+			if (y == hero.y && x == hero.x)
+			    continue;
+			/*
+			 * Or anything else nasty
+			 * Also avoid a mimic which is disguised as scroll
+			 */
+			if (moat(y, x) == NULL && step_ok(ch = winat(y, x)))
+			{
+			    if (ch == SCROLL
+				&& find_obj(y, x)->o_which == S_SCARE)
+				    continue;
+			    if (rnd(++appear) == 0)
+			    {
+				mp.y = y;
+				mp.x = x;
+			    }
+			}
+		    }
+		if (appear)
+		{
+		    op = new_item();
+		    new_monster(op, randmonster(FALSE), &mp);
+		}
+		else
+		    msg("you hear a faint cry of anguish in the distance");
+	    }
+	when S_IDENT:
+	    /*
+	     * Identify, let the rogue figure something out
+	     */
+	    s_know[S_IDENT] = TRUE;
+	    msg("this scroll is an identify scroll");
+	    whatis(TRUE);
+	when S_MAP:
+	    /*
+	     * Scroll of magic mapping.
+	     */
+	    s_know[S_MAP] = TRUE;
+	    msg("oh, now this scroll has a map on it");
+	    /*
+	     * Take all the things we want to keep hidden out of the window
+	     */
+	    for (y = 1; y < LINES - 1; y++)
+		for (x = 0; x < COLS; x++)
+		{
+		    index = INDEX(y, x);
+		    switch (ch = _level[index])
+		    {
+			case '-':
+			case '|':
+			    if (!(_flags[index] & F_REAL))
+			    {
+				ch = _level[index] = DOOR;
+				_flags[index] &= ~F_REAL;
+			    }
+			case PASSAGE:
+			    _flags[index] |= F_SEEN;
+			case DOOR:
+			case STAIRS:
+			    if ((op = moat(y, x)) != NULL)
+				if (op->t_oldch == ' ')
+				    op->t_oldch = ch;
+			    break;
+			default:
+			    ch = ' ';
+		    }
+		    if (ch != ' ')
+			mvaddch(y, x, ch);
+		}
+	when S_GFIND:
+	    /*
+	     * Potion of gold detection
+	     */
+	    ch = FALSE;
+	    wclear(hw);
+	    for (op = lvl_obj; op != NULL; op = next(op))
+		if (op->o_type == GOLD)
+		{
+		    ch = TRUE;
+		    mvwaddch(hw, op->o_pos.y, op->o_pos.x, GOLD);
+		}
+	    if (ch)
+	    {
+		s_know[S_GFIND] = TRUE;
+		show_win(hw,
+		    "You begin to feel greedy and you sense gold.--More--");
+	    }
+	    else
+		msg("you feel a pull downward");
+	when S_TELEP:
+	    /*
+	     * Scroll of teleportation:
+	     * Make him dissapear and reappear
+	     */
+	    {
+		register struct room *cur_room;
+
+		cur_room = proom;
+		teleport();
+		if (cur_room != proom)
+		    s_know[S_TELEP] = TRUE;
+	    }
+	when S_ENCH:
+	    if (cur_weapon == NULL || cur_weapon->o_type != WEAPON)
+		msg("you feel a strange sense of loss");
+	    else
+	    {
+		cur_weapon->o_flags &= ~ISCURSED;
+		if (rnd(2) == 0)
+		    cur_weapon->o_hplus++;
+		else
+		    cur_weapon->o_dplus++;
+		msg("your %s glows blue for a moment", w_names[cur_weapon->o_which]);
+	    }
+	when S_SCARE:
+	    /*
+	     * 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 (cur_armor != NULL)
+		cur_armor->o_flags &= ~ISCURSED;
+	    if (cur_weapon != NULL)
+		cur_weapon->o_flags &= ~ISCURSED;
+	    if (cur_ring[LEFT] != NULL)
+		cur_ring[LEFT]->o_flags &= ~ISCURSED;
+	    if (cur_ring[RIGHT] != NULL)
+		cur_ring[RIGHT]->o_flags &= ~ISCURSED;
+	    msg("you feel as if somebody is watching over you");
+	when S_AGGR:
+	    /*
+	     * This scroll aggravates all the monsters on the current
+	     * level and sets them running towards the hero
+	     */
+	    aggravate();
+	    msg("you hear a high pitched humming noise");
+	when S_NOP:
+	    msg("this scroll seems to be blank");
+	when S_GENOCIDE:
+	    s_know[S_GENOCIDE] = TRUE;
+	    msg("you have been granted the boon of genocide");
+	    genocide();
+	otherwise:
+	    msg("what a puzzling scroll!");
+	    return;
+    }
+    look(TRUE);	/* put the result of the scroll on the screen */
+    status();
+    /*
+     * Get rid of the thing
+     */
+    inpack--;
+    if (obj->o_count > 1)
+	obj->o_count--;
+    else
+    {
+	detach(pack, obj);
+	discardit = TRUE;
+    }
+
+    call_it(s_know[obj->o_which], &s_guess[obj->o_which]);
+
+    if (discardit)
+	discard(obj);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rogue4/state.c	Sat Oct 24 16:52:52 2009 +0000
@@ -0,0 +1,2161 @@
+/*
+    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 <string.h>
+#include "rogue.h"
+
+#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;
+
+void *
+get_list_item(THING *l, int i)
+{
+    int count = 0;
+
+    while(l != NULL)
+    {   
+        if (count == i)
+            return(l);
+                        
+        l = l->l_next;
+        
+        count++;
+    }
+    
+    return(NULL);
+}
+
+int
+find_list_ptr(THING *l, void *ptr)
+{
+    int count = 0;
+
+    while(l != NULL)
+    {
+        if (l == ptr)
+            return(count);
+            
+        l = l->l_next;
+        count++;
+    }
+    
+    return(-1);
+}
+
+int
+list_size(THING *l)
+{
+    int count = 0;
+    
+    while(l != NULL)
+    {
+        if (l == 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, shint 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, const char *master[], int max, 
+                      const 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("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_uchar(int inf, unsigned 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, shint *i)
+{
+    unsigned char buf;
+    
+    rs_read(inf, &buf, 1);
+    
+    *i = (shint) 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, const char *master[], int maxindex, 
+                     const 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 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_str_t(FILE *savef, str_t st)
+{
+    rs_write_uint(savef,st);
+
+    return(WRITESTAT);
+}
+
+int
+rs_read_str_t(int inf, str_t *st)
+{
+    rs_read_uint(inf,st);
+    
+    return(READSTAT);
+}
+
+int
+rs_write_coord(FILE *savef, coord c)
+{
+    rs_write_shint(savef, c.x);
+    rs_write_shint(savef, c.y);
+    
+    return(WRITESTAT);
+}
+
+int
+rs_read_coord(int inf, coord *c)
+{
+    rs_read_shint(inf,&c->x);
+    rs_read_shint(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
+            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;
+                        default:d_list[i].d_func = NULL;
+                                break;
+                    }   
+                }
+            }
+        }
+    }
+    
+    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_shint(savef,i[n].mi_prob);
+        rs_write_short(savef,i[n].mi_worth);
+    }
+    
+    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++)
+                {
+                    /* mi_name is constant, defined at compile time in all cases */
+                    rs_read_shint(inf,&mi[n].mi_prob);
+                    rs_read_short(inf,&mi[n].mi_worth);
+                }
+            }
+        }
+    }
+    
+    return(READSTAT);
+}
+
+int
+rs_write_room(FILE *savef, struct room *r)
+{
+    rs_write_coord(savef, r->r_pos);
+    rs_write_coord(savef, r->r_max);
+    rs_write_coord(savef, r->r_gold);
+    rs_write_int(savef,   r->r_goldval);
+    rs_write_short(savef, r->r_flags);
+    rs_write_shint(savef, r->r_nexits);
+    rs_write_coord(savef, r->r_exit[0]);
+    rs_write_coord(savef, r->r_exit[1]);
+    rs_write_coord(savef, r->r_exit[2]);
+    rs_write_coord(savef, r->r_exit[3]);
+    rs_write_coord(savef, r->r_exit[4]);
+    rs_write_coord(savef, r->r_exit[5]);
+    rs_write_coord(savef, r->r_exit[6]);
+    rs_write_coord(savef, r->r_exit[7]);
+    rs_write_coord(savef, r->r_exit[8]);
+    rs_write_coord(savef, r->r_exit[9]);
+    rs_write_coord(savef, r->r_exit[10]);
+    rs_write_coord(savef, r->r_exit[11]);
+    
+    return(WRITESTAT);
+}
+
+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_room(savef, &r[n]);
+    
+    return(WRITESTAT);
+}
+
+int
+rs_read_room(int inf, struct room *r)
+{
+    rs_read_coord(inf,&r->r_pos);
+    rs_read_coord(inf,&r->r_max);
+    rs_read_coord(inf,&r->r_gold);
+    rs_read_int(inf,&r->r_goldval);
+    rs_read_short(inf,&r->r_flags);
+    rs_read_shint(inf,&r->r_nexits);
+    rs_read_coord(inf,&r->r_exit[0]);
+    rs_read_coord(inf,&r->r_exit[1]);
+    rs_read_coord(inf,&r->r_exit[2]);
+    rs_read_coord(inf,&r->r_exit[3]);
+    rs_read_coord(inf,&r->r_exit[4]);
+    rs_read_coord(inf,&r->r_exit[5]);
+    rs_read_coord(inf,&r->r_exit[6]);
+    rs_read_coord(inf,&r->r_exit[7]);
+    rs_read_coord(inf,&r->r_exit[8]);
+    rs_read_coord(inf,&r->r_exit[9]);
+    rs_read_coord(inf,&r->r_exit[10]);
+    rs_read_coord(inf,&r->r_exit[11]);
+
+    return(READSTAT);
+}
+
+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_room(inf,&r[n]);
+    }
+
+    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_stats(FILE *savef, struct stats *s)
+{
+    rs_write_int(savef, RSID_STATS);
+    rs_write_str_t(savef, s->s_str);
+    rs_write_long(savef, s->s_exp);
+    rs_write_shint(savef, s->s_lvl);
+    rs_write_shint(savef, s->s_arm);
+    rs_write_short(savef, s->s_hpt);
+    rs_write(savef, s->s_dmg, sizeof(s->s_dmg));
+    rs_write_shint(savef,s->s_maxhp);
+
+    return(WRITESTAT);
+}
+
+int
+rs_read_stats(int inf, struct stats *s)
+{
+    int id;
+
+    rs_read_int(inf, &id);
+
+    rs_read_str_t(inf,&s->s_str);
+    rs_read_long(inf,&s->s_exp);
+    rs_read_shint(inf,&s->s_lvl);
+    rs_read_shint(inf,&s->s_arm);
+    rs_read_short(inf,&s->s_hpt);
+    rs_read(inf,s->s_dmg,sizeof(s->s_dmg));
+    rs_read_shint(inf,&s->s_maxhp);
+
+    return(READSTAT);
+}
+
+int
+rs_write_object(FILE *savef, THING *o)
+{
+    rs_write_int(savef, RSID_OBJECT);
+    rs_write_shint(savef, o->_o._o_type); 
+    rs_write_coord(savef, o->_o._o_pos); 
+    rs_write_char(savef, o->_o._o_launch);
+    rs_write(savef, o->_o._o_damage, sizeof(o->_o._o_damage));
+    rs_write(savef, o->_o._o_hurldmg, sizeof(o->_o._o_hurldmg));
+    rs_write_shint(savef, o->_o._o_count);
+    rs_write_shint(savef, o->_o._o_which);
+    rs_write_shint(savef, o->_o._o_hplus);
+    rs_write_shint(savef, o->_o._o_dplus);
+    rs_write_short(savef, o->_o._o_ac);
+    rs_write_short(savef, o->_o._o_flags);
+    rs_write_shint(savef, o->_o._o_group);
+
+    return(WRITESTAT);
+}
+
+int
+rs_read_object(int inf, THING *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_shint(inf, &o->_o._o_type);
+            rs_read_coord(inf, &o->_o._o_pos);
+            rs_read_char(inf, &o->_o._o_launch);
+            rs_read(inf, &o->_o._o_damage, sizeof(o->_o._o_damage));
+            rs_read(inf, &o->_o._o_hurldmg, sizeof(o->_o._o_hurldmg));
+            rs_read_shint(inf, &o->_o._o_count);
+            rs_read_shint(inf, &o->_o._o_which);
+            rs_read_shint(inf, &o->_o._o_hplus);
+            rs_read_shint(inf, &o->_o._o_dplus);
+            rs_read_short(inf, &o->_o._o_ac);
+            rs_read_short(inf, &o->_o._o_flags);
+            rs_read_shint(inf, &o->_o._o_group);
+        }
+    }
+    
+    return(READSTAT);
+}
+
+int
+rs_write_object_list(FILE *savef, THING *l)
+{
+    rs_write_int(savef, RSID_OBJECTLIST);
+    rs_write_int(savef, list_size(l));
+
+    while (l != NULL) 
+    {
+        rs_write_object(savef, l);
+        l = l->l_next;
+    }
+    
+    return(WRITESTAT);
+}
+
+int
+rs_read_object_list(int inf, THING **list)
+{
+    int id;
+    int i, cnt;
+    THING *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(THING));
+                memset(l,0,sizeof(THING));
+                l->l_prev = previous;
+                if (previous != NULL)
+                    previous->l_next = l;
+                rs_read_object(inf,l);
+                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_reference(FILE *savef, THING *list, THING *item)
+{
+    int i;
+    
+    i = find_list_ptr(list, item);
+
+    rs_write_int(savef, i);
+
+    return(WRITESTAT);
+}
+
+int
+rs_read_object_reference(int inf, THING *list, THING **item)
+{
+    int i;
+    
+    rs_read_int(inf, &i);
+
+    *item = get_list_item(list,i);
+            
+    return(READSTAT);
+}
+
+int
+find_thing_coord(THING *monlist, coord *c)
+{
+    THING *mitem;
+    THING *tp;
+    int i = 0;
+
+    for(mitem = monlist; mitem != NULL; mitem = mitem->l_next)
+    {
+        tp = mitem;
+
+        if (c == &tp->t_pos)
+            return(i);
+
+        i++;
+    }
+
+    return(-1);
+}
+
+int
+find_room_coord(struct room *rmlist, coord *c, int n)
+{
+    int i = 0;
+    
+    for(i = 0; i < n; i++)
+        if(&rmlist[i].r_gold == c)
+            return(i);
+    
+    return(-1);
+}
+
+int
+find_object_coord(THING *objlist, coord *c)
+{
+    THING *oitem;
+    THING *obj;
+    int i = 0;
+
+    for(oitem = objlist; oitem != NULL; oitem = oitem->l_next)
+    {
+        obj = oitem;
+
+        if (c == &obj->o_pos)
+            return(i);
+
+        i++;
+    }
+
+    return(-1);
+}
+
+int
+rs_write_thing(FILE *savef, 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_coord(savef, t->_t._t_pos);
+    rs_write_boolean(savef, t->_t._t_turn);
+    rs_write_char(savef, t->_t._t_type);
+    rs_write_char(savef, t->_t._t_disguise);
+    rs_write_char(savef, t->_t._t_oldch);
+
+    /* 
+        t_dest can be:
+        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.
+    */
+
+    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_short(savef, t->_t._t_flags);
+    rs_write_stats(savef, &t->_t._t_stats);
+    rs_write_room_reference(savef, t->_t._t_room);
+    rs_write_object_list(savef, t->_t._t_pack);
+    
+    return(WRITESTAT);
+}
+
+int
+rs_fix_thing(THING *t)
+{
+    THING *item;
+    THING *tp;
+
+    if (t->t_reserved < 0)
+        return;
+
+    item = get_list_item(mlist,t->t_reserved);
+
+    if (item != NULL)
+    {
+        tp = item;
+        t->t_dest = &tp->t_pos;
+    }
+}
+
+int
+rs_fix_thing_list(THING *list)
+{
+    THING *item;
+
+    for(item = list; item != NULL; item = item->l_next)
+        rs_fix_thing(item);
+}
+
+int
+rs_read_thing(int inf, THING *t)
+{
+    int id;
+    int listid = 0, index = -1;
+    THING *item;
+        
+    if (rs_read_int(inf, &id) != 0)
+    {
+        if (id != RSID_THING)
+            format_error = TRUE;
+        else
+        {
+            rs_read_coord(inf,&t->_t._t_pos);
+            rs_read_boolean(inf,&t->_t._t_turn);
+            rs_read_uchar(inf,&t->_t._t_type);
+            rs_read_char(inf,&t->_t._t_disguise);
+            rs_read_char(inf,&t->_t._t_oldch);
+            
+            /* 
+                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._t_reserved = -1;
+
+            if (listid == 0) /* hero or NULL */
+            {
+                if (index == 1)
+                    t->_t._t_dest = &hero;
+                else
+                    t->_t._t_dest = NULL;
+            }
+            else if (listid == 1) /* monster/thing */
+            {
+                t->_t._t_dest     = NULL;
+                t->_t._t_reserved = index;
+            }
+            else if (listid == 2) /* object */
+            {
+                THING *obj;
+
+                item = get_list_item(lvl_obj, index);
+
+                if (item != NULL)
+                {
+                    obj = item;
+                    t->_t._t_dest = &obj->o_pos;
+                }
+            }
+            else if (listid == 3) /* gold */
+            {
+                t->_t._t_dest = &rooms[index].r_gold;
+            }
+            else
+                t->_t._t_dest = NULL;
+            
+            rs_read_short(inf,&t->_t._t_flags);
+            rs_read_stats(inf,&t->_t._t_stats);
+            rs_read_room_reference(inf, &t->_t._t_room);
+            rs_read_object_list(inf,&t->_t._t_pack);
+        }
+    }
+    else 
+        format_error = TRUE;
+    
+    return(READSTAT);
+}
+
+int
+rs_write_thing_list(FILE *savef, THING *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, l);
+        l = l->l_next;
+    }
+    
+    return(WRITESTAT);
+}
+
+int
+rs_read_thing_list(int inf, THING **list)
+{
+    int id;
+    int i, cnt;
+    THING *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();
+                l->l_prev = previous;
+                if (previous != NULL)
+                    previous->l_next = l;
+                rs_read_thing(inf,l);
+                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_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(savef, m[n].m_name, sizeof(m[n].m_name));
+        rs_write_char(savef, m[n].m_carry);
+        rs_write_short(savef, m[n].m_flags);
+        */
+        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(inf,m[n].m_name,sizeof(m[n].m_name));
+                rs_read_char(inf, &m[n].m_carry);
+                rs_read_short(inf, &m[n].m_flags);
+                */
+                rs_read_stats(inf, &m[n].m_stats);
+            }
+        }
+        else
+            format_error = TRUE;
+    }
+    
+    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_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_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_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_rings(FILE *savef)
+{
+    int i;
+    const char *stones_list[NSTONES];
+
+    for(i = 0; i < NSTONES; i++)
+        stones_list[i] = stones[i].st_name;
+
+    for(i = 0; i < MAXRINGS; i++)
+    {
+        rs_write_string_index(savef,stones_list,NSTONES,r_stones[i]);
+        rs_write_boolean(savef,r_know[i]);
+        rs_write_string(savef,r_guess[i]);
+    }
+
+    return(WRITESTAT);
+}
+
+int
+rs_read_rings(int inf)
+{
+    int i;
+    const char *stones_list[NSTONES];
+
+    for(i = 0; i < NSTONES; i++)
+        stones_list[i] = stones[i].st_name;
+
+    for(i = 0; i < MAXRINGS; i++)
+    {
+        rs_read_string_index(inf,stones_list,NSTONES,&r_stones[i]);
+        rs_read_boolean(inf,&r_know[i]);
+        rs_read_new_string(inf,&r_guess[i]);
+    }
+
+    return(READSTAT);
+}
+
+int
+rs_write_sticks(FILE *savef)
+{
+    int i;
+
+    for (i = 0; i < MAXSTICKS; i++)
+    {
+        if (strcmp(ws_type[i],"staff") == 0)
+        {
+            rs_write_int(savef,0);
+            rs_write_string_index(savef, wood, NWOOD, ws_made[i]);
+        }
+        else
+        {
+            rs_write_int(savef,1);
+            rs_write_string_index(savef, metal, NMETAL, ws_made[i]);
+        }
+        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_made[i]);
+            ws_type[i] = "staff";
+        }
+        else 
+        {
+            rs_read_string_index(inf,metal,NMETAL,&ws_made[i]);
+            ws_type[i] = "wand";
+        }
+        rs_read_boolean(inf, &ws_know[i]);
+        rs_read_new_string(inf, &ws_guess[i]);
+    }
+
+    return(READSTAT);
+}
+
+/******************************************************************************/
+int
+rs_write_thing_reference(FILE *savef, THING *list, THING *item)
+{
+    int i;
+
+    if (item == NULL)
+        rs_write_int(savef,-1);
+    else
+    {
+        i = find_list_ptr(list, item);
+
+        assert(i >= 0);
+
+        rs_write_int(savef, i);
+    }
+
+    return(WRITESTAT);
+}
+
+int
+rs_read_thing_reference(int inf, THING *list, THING **item)
+{
+    int i;
+    
+    rs_read_int(inf, &i);
+
+    if (i == -1)
+        *item = NULL;
+    else
+    {
+        *item = get_list_item(list,i);
+
+        assert(item != NULL);
+    }        
+
+    return(READSTAT);
+}
+
+int
+rs_write_thing_references(FILE *savef, THING *list, THING *items[], int count)
+{
+    int i;
+
+    for(i = 0; i < count; i++)
+        rs_write_thing_reference(savef,list,items[i]);
+
+    return(WRITESTAT);
+}
+
+int
+rs_read_thing_references(int inf, THING *list, THING *items[], int count)
+{
+    int i;
+
+    for(i = 0; i < count; i++)
+        rs_read_thing_reference(inf,list,&items[i]);
+
+    return(WRITESTAT);
+}
+
+int
+rs_save_file(FILE *savef)
+{
+    int endian = 0x01020304;
+    big_endian = ( *((char *)&endian) == 0x01 );
+
+    rs_write_boolean(savef, after);
+    rs_write_boolean(savef, noscore);
+    rs_write_boolean(savef, amulet);
+    rs_write_boolean(savef, askme);
+    rs_write_boolean(savef, door_stop);
+    rs_write_boolean(savef, fight_flush);
+    rs_write_boolean(savef, firstmove);
+    rs_write_boolean(savef, in_shell);
+    rs_write_boolean(savef, jump);
+    rs_write_boolean(savef, passgo);
+    rs_write_boolean(savef, playing);
+    rs_write_boolean(savef, running);
+    rs_write_boolean(savef, save_msg);
+    rs_write_boolean(savef, slow_invent);
+    rs_write_boolean(savef, terse);
+#ifdef WIZARD
+    rs_write_boolean(savef, wizard);
+#else
+    rs_write_boolean(savef, 0);
+#endif
+    rs_write_char(savef, take);
+    rs_write(savef, prbuf, MAXSTR);
+    rs_write_char(savef, runch);
+
+    rs_write_scrolls(savef);
+    rs_write_potions(savef);
+    rs_write_rings(savef);
+    rs_write_sticks(savef);
+
+    rs_write_string(savef, release);
+    rs_write(savef, whoami, MAXSTR);
+    rs_write(savef, fruit, MAXSTR);
+
+    rs_write(savef, _level, MAXLINES*MAXCOLS);
+    rs_write(savef, _flags, MAXLINES*MAXCOLS);
+
+    rs_write_int(savef, max_level);
+    rs_write_int(savef, ntraps);
+    rs_write_int(savef, dnum);
+    rs_write_int(savef, level);
+    rs_write_int(savef, purse);
+    rs_write_int(savef, no_move);
+    rs_write_int(savef, no_command);
+    rs_write_int(savef, inpack);
+    rs_write_int(savef, lastscore);
+    rs_write_int(savef, no_food);
+    rs_write_int(savef, count);
+    rs_write_int(savef, fung_hit);
+    rs_write_int(savef, quiet);
+    rs_write_int(savef, food_left);
+    rs_write_int(savef, group);
+    rs_write_int(savef, hungry_state);
+
+    /* rs_write_ints(savef, a_chances, MAXARMORS); *//* constant */
+    /* rs_write_ints(savef, a_class, MAXARMORS);   *//* constant */
+
+    rs_write_long(savef, seed);
+    rs_write_coord(savef, oldpos);
+    rs_write_coord(savef, delta);
+
+    rs_write_thing(savef, &player);                     
+    rs_write_object_reference(savef, player.t_pack, cur_armor);
+   	rs_write_object_reference(savef, player.t_pack, cur_weapon); 
+    rs_write_object_reference(savef, player.t_pack, cur_ring[0]);
+    rs_write_object_reference(savef, player.t_pack, cur_ring[1]); 
+
+    rs_write_object_list(savef, lvl_obj);               
+    rs_write_thing_list(savef, mlist);                
+    rs_write_thing_references(savef, mlist, _monst, MAXLINES*MAXCOLS);
+
+    rs_write_window(savef, stdscr);
+    rs_write_stats(savef,&max_stats); 
+
+    rs_write_rooms(savef, rooms, MAXROOMS);             
+    rs_write_room_reference(savef, oldrp);              
+    rs_write_rooms(savef, passages, MAXPASS);
+
+    rs_write_monsters(savef,monsters,26);               
+    rs_write_magic_items(savef, things,   NUMTHINGS);   
+    rs_write_magic_items(savef, s_magic,  MAXSCROLLS);  
+    rs_write_magic_items(savef, p_magic,  MAXPOTIONS);  
+    rs_write_magic_items(savef, r_magic,  MAXRINGS);    
+    rs_write_magic_items(savef, ws_magic, MAXSTICKS);      
+    
+    rs_write_coord(savef, ch_ret);                      /* 5.2-chase.c  */
+    rs_write_char(savef,countch);                       /* 5.2-command.c*/
+    rs_write_char(savef,direction);                     /* 5.2-command.c*/
+    rs_write_char(savef,newcount);                      /* 5.2-command.c*/
+    rs_write_daemons(savef, &d_list[0], 20);            /* 5.2-daemon.c */
+    rs_write_int(savef,between);                        /* 5.2-daemons.c*/
+    rs_write(savef,lvl_mons,sizeof(lvl_mons));          /* 5.2-monsters.c*/
+    rs_write(savef,wand_mons,sizeof(wand_mons));        /* 5.2-monsters.c*/
+    rs_write_coord(savef, nh);                          /* 5.2-move.c    */
+    rs_write_boolean(savef, got_genocide);              /* 5.2-things.c  */
+
+    return(WRITESTAT);
+}
+
+int
+rs_restore_file(int inf)
+{
+    bool junk;
+    int endian = 0x01020304;
+    big_endian = ( *((char *)&endian) == 0x01 );
+    
+    rs_read_boolean(inf, &after);
+    rs_read_boolean(inf, &noscore);
+    rs_read_boolean(inf, &amulet);
+    rs_read_boolean(inf, &askme);
+    rs_read_boolean(inf, &door_stop);
+    rs_read_boolean(inf, &fight_flush);
+    rs_read_boolean(inf, &firstmove);
+    rs_read_boolean(inf, &in_shell);
+    rs_read_boolean(inf, &jump);
+    rs_read_boolean(inf, &passgo);
+    rs_read_boolean(inf, &playing);
+    rs_read_boolean(inf, &running);
+    rs_read_boolean(inf, &save_msg);
+    rs_read_boolean(inf, &slow_invent);
+    rs_read_boolean(inf, &terse);
+#ifdef WIZARD
+    rs_read_boolean(inf, &wizard);
+#else
+    rs_read_boolean(inf, &junk);
+#endif
+    rs_read_char(inf, &take);
+    rs_read(inf, prbuf, MAXSTR);
+    rs_read_char(inf, &runch);
+
+    rs_read_scrolls(inf);
+    rs_read_potions(inf);
+    rs_read_rings(inf);
+    rs_read_sticks(inf);
+
+    rs_read_new_string(inf, &release);
+    rs_read(inf, whoami, MAXSTR);
+    rs_read(inf, fruit, MAXSTR);
+
+    rs_read(inf, _level, MAXLINES*MAXCOLS);
+    rs_read(inf, _flags, MAXLINES*MAXCOLS);
+
+    rs_read_int(inf, &max_level);
+    rs_read_int(inf, &ntraps);
+    rs_read_int(inf, &dnum);
+    rs_read_int(inf, &level);
+    rs_read_int(inf, &purse);
+    rs_read_int(inf, &no_move);
+    rs_read_int(inf, &no_command);
+    rs_read_int(inf, &inpack);
+    rs_read_int(inf, &lastscore);
+    rs_read_int(inf, &no_food);
+    rs_read_int(inf, &count);
+    rs_read_int(inf, &fung_hit);
+    rs_read_int(inf, &quiet);
+    rs_read_int(inf, &food_left);
+    rs_read_int(inf, &group);
+    rs_read_int(inf, &hungry_state);
+
+    rs_read_long(inf, &seed);
+    rs_read_coord(inf, &oldpos);
+    rs_read_coord(inf, &delta);
+
+    rs_read_thing(inf, &player); 
+    rs_read_object_reference(inf, player.t_pack, &cur_armor);
+    rs_read_object_reference(inf, player.t_pack, &cur_weapon);
+    rs_read_object_reference(inf, player.t_pack, &cur_ring[0]);
+    rs_read_object_reference(inf, player.t_pack, &cur_ring[1]);
+
+    rs_read_object_list(inf, &lvl_obj);                 
+    rs_read_thing_list(inf, &mlist);                  
+    rs_fix_thing(&player);
+    rs_fix_thing_list(mlist);
+    rs_read_thing_references(inf,mlist,_monst,MAXLINES*MAXCOLS);
+
+    rs_read_window(inf, stdscr);
+    rs_read_stats(inf, &max_stats);
+
+    rs_read_rooms(inf, rooms, MAXROOMS);
+    rs_read_room_reference(inf, &oldrp);
+    rs_read_rooms(inf, passages, MAXPASS);
+
+    rs_read_monsters(inf,monsters,26);                  
+    rs_read_magic_items(inf, things,   NUMTHINGS);         
+    rs_read_magic_items(inf, s_magic,  MAXSCROLLS);       
+    rs_read_magic_items(inf, p_magic,  MAXPOTIONS);       
+    rs_read_magic_items(inf, r_magic,  MAXRINGS);         
+    rs_read_magic_items(inf, ws_magic, MAXSTICKS);       
+
+    rs_read_coord(inf, &ch_ret);                        /* 5.2-chase.c      */
+    rs_read_char(inf,&countch);                         /* 5.2-command.c    */
+    rs_read_char(inf,&direction);                       /* 5.2-command.c    */
+    rs_read_char(inf,&newcount);                        /* 5.2-command.c    */
+    rs_read_daemons(inf, d_list, 20);                   /* 5.2-daemon.c     */
+    rs_read_int(inf,&between);                          /* 5.2-daemons.c    */
+    rs_read(inf, lvl_mons, sizeof(lvl_mons));           /* 5.2-monsters.c   */
+    rs_read(inf, wand_mons, sizeof(wand_mons));         /* 5.2-monsters.c   */
+    rs_read_coord(inf, &nh);                            /* 5.2-move.c       */
+    rs_read_boolean(inf, &got_genocide);                /* 5.2-things.c     */
+    
+    return(READSTAT);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rogue4/sticks.c	Sat Oct 24 16:52:52 2009 +0000
@@ -0,0 +1,461 @@
+/*
+ * Functions to implement the various sticks one might find
+ * while wandering around the dungeon.
+ *
+ * @(#)sticks.c	4.22 (Berkeley) 5/19/82
+ *
+ * Rogue: Exploring the Dungeons of Doom
+ * Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman
+ * All rights reserved.
+ *
+ * See the file LICENSE.TXT for full copyright and licensing information.
+ */
+
+#include <curses.h>
+#include <ctype.h>
+#include <string.h>
+#include "rogue.h"
+
+/*
+ * fix_stick:
+ *	Set up a new stick
+ */
+fix_stick(cur)
+register THING *cur;
+{
+    if (strcmp(ws_type[cur->o_which], "staff") == 0)
+	strcpy(cur->o_damage,"2d3");
+    else
+	strcpy(cur->o_damage,"1d1");
+    strcpy(cur->o_hurldmg,"1d1");
+
+    cur->o_charges = 3 + rnd(5);
+    switch (cur->o_which)
+    {
+	case WS_HIT:
+	    cur->o_hplus = 100;
+	    cur->o_dplus = 3;
+	    strcpy(cur->o_damage,"1d8");
+	when WS_LIGHT:
+	    cur->o_charges = 10 + rnd(10);
+    }
+}
+
+/*
+ * do_zap:
+ *	Perform a zap with a wand
+ */
+do_zap()
+{
+    register THING *obj, *tp;
+    register int y, x;
+    register char *name;
+
+    if ((obj = get_item("zap with", STICK)) == NULL)
+	return;
+    if (obj->o_type != STICK)
+    {
+	after = FALSE;
+	msg("you can't zap with that!");
+	return;
+    }
+    if (obj->o_charges == 0)
+    {
+	msg("nothing happens");
+	return;
+    }
+    switch (obj->o_which)
+    {
+	case WS_LIGHT:
+	    /*
+	     * Reddy Kilowat wand.  Light up the room
+	     */
+	    ws_know[WS_LIGHT] = TRUE;
+	    if (proom->r_flags & ISGONE)
+		msg("the corridor glows and then fades");
+	    else
+	    {
+		proom->r_flags &= ~ISDARK;
+		/*
+		 * Light the room and put the player back up
+		 */
+		enter_room(&hero);
+		addmsg("the room is lit");
+		if (!terse)
+		    addmsg(" by a shimmering blue light");
+		endmsg();
+	    }
+	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 (pstats.s_hpt < 2)
+	    {
+		msg("you are too weak to use it");
+		return;
+	    }
+	    else
+		drain();
+	when WS_POLYMORPH:
+	case WS_TELAWAY:
+	case WS_TELTO:
+	case WS_CANCEL:
+	{
+	    register char monster, oldch;
+	    register int rm;
+
+	    y = hero.y;
+	    x = hero.x;
+	    while (step_ok(winat(y, x)))
+	    {
+		y += delta.y;
+		x += delta.x;
+	    }
+	    if ((tp = moat(y, x)) != NULL)
+	    {
+		register char omonst;
+
+		omonst = monster = tp->t_type;
+		if (monster == 'F')
+		    player.t_flags &= ~ISHELD;
+		if (obj->o_which == WS_POLYMORPH)
+		{
+		    register THING *pp;
+
+		    pp = tp->t_pack;
+		    detach(mlist, tp);
+		    if (see_monst(tp))
+			mvaddch(y, x, chat(y, x));
+		    oldch = tp->t_oldch;
+		    delta.y = y;
+		    delta.x = x;
+		    new_monster(tp, monster = rnd(26) + 'A', &delta);
+		    if (see_monst(tp))
+			mvaddch(y, x, monster);
+		    tp->t_oldch = oldch;
+		    tp->t_pack = pp;
+		    ws_know[WS_POLYMORPH] |= (monster != omonst);
+		}
+		else if (obj->o_which == WS_CANCEL)
+		{
+		    tp->t_flags |= ISCANC;
+		    tp->t_flags &= ~(ISINVIS|CANHUH);
+		    tp->t_disguise = tp->t_type;
+		}
+		else
+		{
+		    if (isupper(toascii(mvinch(y,x))))
+			mvaddch(y, x, tp->t_oldch);
+		    if (obj->o_which == WS_TELAWAY)
+		    {
+			do
+			{
+			    rm = rnd_room();
+			    rnd_pos(&rooms[rm], &tp->t_pos);
+			} until (winat(tp->t_pos.y, tp->t_pos.x) == FLOOR);
+			tp->t_room = roomin(&tp->t_pos);
+			tp->t_oldch = mvinch(tp->t_pos.y, tp->t_pos.x);
+			if (see_monst(tp))
+			    mvaddch(tp->t_pos.y, tp->t_pos.x, tp->t_disguise);
+			else if (on(player, SEEMONST))
+			{
+			    standout();
+			    mvaddch(tp->t_pos.y, tp->t_pos.x, tp->t_disguise);
+			    standend();
+			}
+		    }
+		    else
+		    {
+			tp->t_pos.y = hero.y + delta.y;
+			tp->t_pos.x = hero.x + delta.x;
+		    
+		        if (tp->t_pos.y != y || tp->t_pos.x != x)
+			    tp->t_oldch = mvinch(tp->t_pos.y, tp->t_pos.x);
+		    }
+		    moat(y, x) = NULL;
+		    moat(tp->t_pos.y, tp->t_pos.x) = tp;
+		    if (tp->t_type == 'F')
+			player.t_flags &= ~ISHELD;
+		}
+		tp->t_dest = &hero;
+		tp->t_flags |= ISRUN;
+	    }
+	}
+	when WS_MISSILE:
+	{
+	    THING bolt;
+
+	    ws_know[WS_MISSILE] = TRUE;
+	    bolt.o_type = '*';
+	    strcpy(bolt.o_hurldmg,"1d4");
+	    bolt.o_hplus = 100;
+	    bolt.o_dplus = 1;
+	    bolt.o_flags = ISMISL;
+	    if (cur_weapon != NULL)
+		bolt.o_launch = cur_weapon->o_which;
+	    do_motion(&bolt, delta.y, delta.x);
+	    if ((tp = moat(bolt.o_pos.y, bolt.o_pos.x)) != NULL && !save_throw(VS_MAGIC, tp))
+		    hit_monster(unc(bolt.o_pos), &bolt);
+	    else if (terse)
+		msg("missle vanishes");
+	    else
+		msg("the missle vanishes with a puff of smoke");
+	}
+	when WS_HIT:
+	    delta.y += hero.y;
+	    delta.x += hero.x;
+	    if ((tp = moat(delta.y, delta.x)) != NULL)
+	    {
+		if (rnd(20) == 0)
+		{
+		    strcpy(obj->o_damage,"3d8");
+		    obj->o_dplus = 9;
+		}
+		else
+		{
+		    strcpy(obj->o_damage,"1d8");
+		    obj->o_dplus = 3;
+		}
+		fight(&delta, tp->t_type, obj, FALSE);
+	    }
+	when WS_HASTE_M:
+	case WS_SLOW_M:
+	    y = hero.y;
+	    x = hero.x;
+	    while (step_ok(winat(y, x)))
+	    {
+		y += delta.y;
+		x += delta.x;
+	    }
+	    if ((tp = moat(y, x)) != NULL)
+	    {
+		if (obj->o_which == WS_HASTE_M)
+		{
+		    if (on(*tp, ISSLOW))
+			tp->t_flags &= ~ISSLOW;
+		    else
+			tp->t_flags |= ISHASTE;
+		}
+		else
+		{
+		    if (on(*tp, ISHASTE))
+			tp->t_flags &= ~ISHASTE;
+		    else
+			tp->t_flags |= ISSLOW;
+		    tp->t_turn = TRUE;
+		}
+		delta.y = y;
+		delta.x = x;
+		runto(&delta, &hero);
+	    }
+	when WS_ELECT:
+	case WS_FIRE:
+	case WS_COLD:
+	    if (obj->o_which == WS_ELECT)
+		name = "bolt";
+	    else if (obj->o_which == WS_FIRE)
+		name = "flame";
+	    else
+		name = "ice";
+	    fire_bolt(&hero, &delta, name);
+	    ws_know[obj->o_which] = TRUE;
+	when WS_NOP:
+	otherwise:
+	    msg("what a bizarre schtick!");
+    }
+    obj->o_charges--;
+}
+
+/*
+ * drain:
+ *	Do drain hit points from player shtick
+ */
+drain()
+{
+    register THING *mp;
+    register int cnt;
+    register struct room *corp;
+    register THING **dp;
+    register bool inpass;
+    static THING *drainee[40];
+
+    /*
+     * First cnt how many things we need to spread the hit points among
+     */
+    cnt = 0;
+    if (chat(hero.y, hero.x) == DOOR)
+	corp = &passages[flat(hero.y, hero.x) & F_PNUM];
+    else
+	corp = NULL;
+    inpass = (proom->r_flags & ISGONE);
+    dp = drainee;
+    for (mp = mlist; mp != NULL; mp = next(mp))
+	if (mp->t_room == proom || mp->t_room == corp ||
+	    (inpass && chat(mp->t_pos.y, mp->t_pos.x) == DOOR &&
+	    &passages[flat(mp->t_pos.y, mp->t_pos.x) & F_PNUM] == proom))
+		*dp++ = mp;
+    if ((cnt = dp - drainee) == 0)
+    {
+	msg("you have a tingling feeling");
+	return;
+    }
+    *dp = NULL;
+    pstats.s_hpt /= 2;
+    cnt = pstats.s_hpt / cnt;
+    /*
+     * Now zot all of the monsters
+     */
+    for (dp = drainee; *dp; dp++)
+    {
+	mp = *dp;
+	if ((mp->t_stats.s_hpt -= cnt) <= 0)
+	    killed(mp, see_monst(mp));
+	else
+	    runto(&mp->t_pos, &hero);
+    }
+}
+
+/*
+ * fire_bolt:
+ *	Fire a bolt in a given direction from a specific starting place
+ */
+fire_bolt(start, dir, name)
+coord *start, *dir;
+char *name;
+{
+    register char dirch, ch;
+    register THING *tp;
+    register bool hit_hero, used, changed;
+    register int i, j;
+    coord pos;
+    coord spotpos[BOLT_LENGTH];
+    THING bolt;
+
+    bolt.o_type = WEAPON;
+    bolt.o_which = FLAME;
+    strcpy(bolt.o_hurldmg,"6d6");
+    bolt.o_hplus = 100;
+    bolt.o_dplus = 0;
+    bolt.o_flags = 0;
+    w_names[FLAME] = name;
+    switch (dir->y + dir->x)
+    {
+	case 0: dirch = '/';
+	when 1: case -1: dirch = (dir->y == 0 ? '-' : '|');
+	when 2: case -2: dirch = '\\';
+    }
+    pos = *start;
+    hit_hero = (start != &hero);
+    used = FALSE;
+    changed = FALSE;
+    for (i = 0; i < BOLT_LENGTH && !used; i++)
+    {
+	pos.y += dir->y;
+	pos.x += dir->x;
+	ch = winat(pos.y, pos.x);
+	spotpos[i] = pos;
+	switch (ch)
+	{
+	    case DOOR:
+		/*
+ 		 * this code is necessary if the hero is on a door
+ 		 * and he fires at the wall the door is in, it would
+ 		 * otherwise loop infinitely
+ 		 * It is also needed if a dragon flames at the hero.
+ 		 * If the hero is at a door, the dragon flame would bounce
+ 		 * and could kill other monsters inadvertly.
+ 		 */
+ 		if (ce(hero, pos))
+ 		    goto def;
+ 		/* FALLTHROUGH */
+
+	    case '|':
+	    case '-':
+	    case ' ':
+		if (!changed)
+		    hit_hero = !hit_hero;
+		changed = FALSE;
+		dir->y = -dir->y;
+		dir->x = -dir->x;
+		i--;
+		msg("the %s bounces", name);
+		break;
+	    default:
+def:
+		if (!hit_hero && (tp = moat(pos.y, pos.x)) != NULL)
+		{
+		    hit_hero = TRUE;
+		    changed = !changed;
+		    tp->t_oldch = chat(pos.y, pos.x);
+		    if (!save_throw(VS_MAGIC, tp))
+		    {
+			bolt.o_pos = pos;
+			used = TRUE;
+			if (tp->t_type == 'D' && strcmp(name, "flame") == 0)
+			{
+			    addmsg("the flame bounces");
+			    if (!terse)
+				msg("off the dragon");
+			    endmsg();
+			}
+			else
+			    hit_monster(unc(pos), &bolt);
+		    }
+		    else if (ch != 'M' || tp->t_disguise == 'M')
+		    {
+			if (start == &hero)
+			    runto(&pos, &hero);
+			if (terse)
+			    msg("%s misses", name);
+			else
+			    msg("the %s whizzes past the %s", name, monsters[ch-'A'].m_name);
+		    }
+		}
+		else if (hit_hero && ce(pos, hero))
+		{
+		    hit_hero = FALSE;
+		    changed = !changed;
+		    if (!save(VS_MAGIC))
+		    {
+			if ((pstats.s_hpt -= roll(6, 6)) <= 0)
+			    if (start == &hero)
+				death('b');
+			    else
+				death(moat(start->y, start->x)->t_type);
+			used = TRUE;
+			if (terse)
+			    msg("the %s hits", name);
+			else
+			    msg("you are hit by the %s", name);
+		    }
+		    else
+			msg("the %s whizzes by you", name);
+		}
+		mvaddch(pos.y, pos.x, dirch);
+		refresh();
+	}
+    }
+    for (j = 0; j < i; j++)
+	mvaddch(spotpos[j].y, spotpos[j].x, chat(spotpos[j].y, spotpos[j].x));
+}
+
+/*
+ * charge_str:
+ *	Return an appropriate string for a wand charge
+ */
+char *
+charge_str(obj)
+register THING *obj;
+{
+    static char buf[20];
+
+    if (!(obj->o_flags & ISKNOW))
+	buf[0] = '\0';
+    else if (terse)
+	sprintf(buf, " [%d]", obj->o_charges);
+    else
+	sprintf(buf, " [%d charges]", obj->o_charges);
+    return buf;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rogue4/things.c	Sat Oct 24 16:52:52 2009 +0000
@@ -0,0 +1,616 @@
+/*
+ * Contains functions for dealing with things like potions, scrolls,
+ * and other items.
+ *
+ * @(#)things.c	4.26 (Berkeley) 5/18/82
+ *
+ * Rogue: Exploring the Dungeons of Doom
+ * Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman
+ * All rights reserved.
+ *
+ * See the file LICENSE.TXT for full copyright and licensing information.
+ */
+
+#include <curses.h>
+#include <ctype.h>
+#include <string.h>
+#include "rogue.h"
+
+bool got_genocide = FALSE;
+
+/*
+ * inv_name:
+ *	Return the name of something as it would appear in an
+ *	inventory.
+ */
+char *
+inv_name(obj, drop)
+register THING *obj;
+register bool drop;
+{
+    register char *pb;
+
+    pb = prbuf;
+    switch (obj->o_type)
+    {
+	case SCROLL:
+	    if (obj->o_count == 1)
+	    {
+		strcpy(pb, "A scroll ");
+		pb = &prbuf[9];
+	    }
+	    else
+	    {
+		sprintf(pb, "%d scrolls ", obj->o_count);
+		pb = &prbuf[strlen(prbuf)];
+	    }
+	    if (s_know[obj->o_which])
+		sprintf(pb, "of %s", s_magic[obj->o_which].mi_name);
+	    else if (s_guess[obj->o_which])
+		sprintf(pb, "called %s", s_guess[obj->o_which]);
+	    else
+		sprintf(pb, "titled '%s'", s_names[obj->o_which]);
+        when POTION:
+	    if (obj->o_count == 1)
+	    {
+		strcpy(pb, "A potion ");
+		pb = &prbuf[9];
+	    }
+	    else
+	    {
+		sprintf(pb, "%d potions ", obj->o_count);
+		pb = &pb[strlen(prbuf)];
+	    }
+	    if (p_know[obj->o_which])
+		sprintf(pb, "of %s(%s)", p_magic[obj->o_which].mi_name,
+		    p_colors[obj->o_which]);
+	    else if (p_guess[obj->o_which])
+		sprintf(pb, "called %s(%s)", p_guess[obj->o_which],
+		    p_colors[obj->o_which]);
+	    else if (obj->o_count == 1)
+		sprintf(prbuf, "A%s %s potion", vowelstr(p_colors[obj->o_which]),
+		    p_colors[obj->o_which]);
+	    else
+		sprintf(prbuf, "%d %s potions", obj->o_count,
+		    p_colors[obj->o_which]);
+	when FOOD:
+	    if (obj->o_which == 1)
+		if (obj->o_count == 1)
+		    sprintf(pb, "A%s %s", vowelstr(fruit), fruit);
+		else
+		    sprintf(pb, "%d %ss", obj->o_count, fruit);
+	    else
+		if (obj->o_count == 1)
+		    strcpy(pb, "Some food");
+		else
+		    sprintf(pb, "%d rations of food", obj->o_count);
+	when WEAPON:
+	    if (obj->o_count > 1)
+		sprintf(pb, "%d ", obj->o_count);
+	    else
+		sprintf(pb, "A%s ", vowelstr(w_names[obj->o_which]));
+	    pb = &prbuf[strlen(prbuf)];
+	    if (obj->o_flags & ISKNOW)
+		sprintf(pb, "%s %s", num(obj->o_hplus, obj->o_dplus, WEAPON),
+		    w_names[obj->o_which]);
+	    else
+		sprintf(pb, "%s", w_names[obj->o_which]);
+	    if (obj->o_count > 1)
+		strcat(pb, "s");
+	when ARMOR:
+	    if (obj->o_flags & ISKNOW)
+	    {
+		sprintf(pb, "%s %s [",
+		    num(a_class[obj->o_which] - obj->o_ac, 0, ARMOR),
+		    a_names[obj->o_which]);
+		if (!terse)
+		    strcat(pb, "armor class ");
+		pb = &prbuf[strlen(prbuf)];
+		sprintf(pb, "%d]", obj->o_ac);
+	    }
+	    else
+		sprintf(pb, "%s", a_names[obj->o_which]);
+	when AMULET:
+	    strcpy(pb, "The Amulet of Yendor");
+	when STICK:
+	    sprintf(pb, "A%s %s ", vowelstr(ws_type[obj->o_which]),
+		ws_type[obj->o_which]);
+	    pb = &prbuf[strlen(prbuf)];
+	    if (ws_know[obj->o_which])
+		sprintf(pb, "of %s%s(%s)", ws_magic[obj->o_which].mi_name,
+		    charge_str(obj), ws_made[obj->o_which]);
+	    else if (ws_guess[obj->o_which])
+		sprintf(pb, "called %s(%s)", ws_guess[obj->o_which],
+		    ws_made[obj->o_which]);
+	    else
+		sprintf(pb = &prbuf[1], "%s %s %s",
+		    vowelstr(ws_made[obj->o_which]), ws_made[obj->o_which],
+		    ws_type[obj->o_which]);
+        when RING:
+	    if (r_know[obj->o_which])
+		sprintf(pb, "A%s ring of %s(%s)", ring_num(obj),
+		    r_magic[obj->o_which].mi_name, r_stones[obj->o_which]);
+	    else if (r_guess[obj->o_which])
+		sprintf(pb, "A ring called %s(%s)",
+		    r_guess[obj->o_which], r_stones[obj->o_which]);
+	    else
+		sprintf(pb, "A%s %s ring", vowelstr(r_stones[obj->o_which]),
+		    r_stones[obj->o_which]);
+	when GOLD:
+		sprintf(pb, "%d pieces of gold", obj->o_goldval);
+#ifdef WIZARD
+	otherwise:
+	    debug("Picked up something funny %s", unctrol(obj->o_type));
+	    sprintf(pb, "Something bizarre %s", unctrol(obj->o_type));
+#endif
+    }
+    if (obj == cur_armor)
+	strcat(pb, " (being worn)");
+    if (obj == cur_weapon)
+	strcat(pb, " (weapon in hand)");
+    if (obj == cur_ring[LEFT])
+	strcat(pb, " (on left hand)");
+    else if (obj == cur_ring[RIGHT])
+	strcat(pb, " (on right hand)");
+    if (drop && isupper(prbuf[0]))
+	prbuf[0] = tolower(prbuf[0]);
+    else if (!drop && islower(*prbuf))
+	*prbuf = toupper(*prbuf);
+    return prbuf;
+}
+
+/*
+ * drop:
+ *	Put something down
+ */
+drop()
+{
+    register char ch;
+    register THING *nobj, *op;
+
+    ch = chat(hero.y, hero.x);
+    if (ch != FLOOR && ch != PASSAGE)
+    {
+	after = FALSE;
+	msg("there is something there already");
+	return;
+    }
+    if ((op = get_item("drop", 0)) == NULL)
+	return;
+    if (!dropcheck(op))
+	return;
+    /*
+     * Take it out of the pack
+     */
+    if (op->o_count >= 2 && op->o_type != WEAPON)
+    {
+	op->o_count--;
+	nobj = new_item();
+	*nobj = *op;
+	nobj->o_count = 1;
+	op = nobj;
+	if (op->o_group != 0)
+		inpack++;
+    }
+    else
+	detach(pack, op);
+    inpack--;
+    /*
+     * Link it into the level object list
+     */
+    attach(lvl_obj, op);
+    chat(hero.y, hero.x) = op->o_type;
+    flat(hero.y, hero.x) |= F_DROPPED;
+    op->o_pos = hero;
+    if (op->o_type == AMULET)
+	amulet = FALSE;
+    msg("dropped %s", inv_name(op, TRUE));
+}
+
+/*
+ * dropcheck:
+ *	Do special checks for dropping or unweilding|unwearing|unringing
+ */
+dropcheck(op)
+register THING *op;
+{
+    if (op == NULL)
+	return TRUE;
+    if (op != cur_armor && op != cur_weapon
+	&& op != cur_ring[LEFT] && op != cur_ring[RIGHT])
+	    return TRUE;
+    if (op->o_flags & 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
+    {
+	cur_ring[op == cur_ring[LEFT] ? LEFT : RIGHT] = NULL;
+	switch (op->o_which)
+	{
+	    case R_ADDSTR:
+		chg_str(-op->o_ac);
+		break;
+	    case R_SEEINVIS:
+		unsee();
+		extinguish(unsee);
+		break;
+	}
+    }
+    return TRUE;
+}
+
+/*
+ * new_thing:
+ *	Return a new thing
+ */
+THING *
+new_thing()
+{
+    register THING *cur;
+    register int j, k;
+
+    cur = new_item();
+    cur->o_hplus = cur->o_dplus = 0;
+    strcpy(cur->o_damage,"0d0");
+    strcpy(cur->o_hurldmg,"0d0");
+    cur->o_ac = 11;
+    cur->o_count = 1;
+    cur->o_group = 0;
+    cur->o_flags = 0;
+    /*
+     * Decide what kind of object it will be
+     * If we haven't had food for a while, let it be food.
+     */
+    switch (no_food > 3 ? 2 : pick_one(things, NUMTHINGS))
+    {
+	case 0:
+	    cur->o_type = POTION;
+	    cur->o_which = pick_one(p_magic, MAXPOTIONS);
+	when 1:
+	    cur->o_type = SCROLL;
+	    cur->o_which = pick_one(s_magic, MAXSCROLLS);
+	    /*
+	     * Only one genocide scroll allowed per game, so if it's
+	     * the second one, then turn it into a identify scroll
+	     */
+	    if (cur->o_which == S_GENOCIDE)
+		if (got_genocide)
+		    cur->o_which = S_IDENT;
+		else
+		    got_genocide = TRUE;
+	when 2:
+	    no_food = 0;
+	    cur->o_type = FOOD;
+	    if (rnd(10) != 0)
+		cur->o_which = 0;
+	    else
+		cur->o_which = 1;
+	when 3:
+	    cur->o_type = WEAPON;
+	    cur->o_which = rnd(MAXWEAPONS);
+	    init_weapon(cur, cur->o_which);
+	    if ((k = rnd(100)) < 10)
+	    {
+		cur->o_flags |= ISCURSED;
+		cur->o_hplus -= rnd(3) + 1;
+	    }
+	    else if (k < 15)
+		cur->o_hplus += rnd(3) + 1;
+	when 4:
+	    cur->o_type = ARMOR;
+	    for (j = 0, k = rnd(100); j < MAXARMORS; j++)
+		if (k < a_chances[j])
+		    break;
+#ifdef WIZARD
+	    if (j == MAXARMORS)
+	    {
+		debug("Picked a bad armor %d", k);
+		j = 0;
+	    }
+#endif
+	    cur->o_which = j;
+	    cur->o_ac = a_class[j];
+	    if ((k = rnd(100)) < 20)
+	    {
+		cur->o_flags |= ISCURSED;
+		cur->o_ac += rnd(3) + 1;
+	    }
+	    else if (k < 28)
+		cur->o_ac -= rnd(3) + 1;
+	when 5:
+	    cur->o_type = RING;
+	    cur->o_which = pick_one(r_magic, MAXRINGS);
+	    switch (cur->o_which)
+	    {
+		case R_ADDSTR:
+		case R_PROTECT:
+		case R_ADDHIT:
+		case R_ADDDAM:
+		    if ((cur->o_ac = rnd(3)) == 0)
+		    {
+			cur->o_ac = -1;
+			cur->o_flags |= ISCURSED;
+		    }
+		when R_AGGR:
+		case R_TELEPORT:
+		    cur->o_flags |= ISCURSED;
+	    }
+	when 6:
+	    cur->o_type = STICK;
+	    cur->o_which = pick_one(ws_magic, MAXSTICKS);
+	    fix_stick(cur);
+#ifdef WIZARD
+	otherwise:
+	    debug("Picked a bad kind of object");
+	    wait_for(' ');
+#endif
+    }
+    return cur;
+}
+
+/*
+ * pick_one:
+ *	Pick an item out of a list of nitems possible magic items
+ */
+pick_one(magic, nitems)
+register struct magic_item *magic;
+int nitems;
+{
+    register struct magic_item *end;
+    register int i;
+    register struct magic_item *start;
+
+    start = magic;
+    for (end = &magic[nitems], i = rnd(100); magic < end; magic++)
+	if (i < magic->mi_prob)
+	    break;
+    if (magic == end)
+    {
+#ifdef WIZARD
+	if (wizard)
+	{
+	    msg("bad pick_one: %d from %d items", i, nitems);
+	    for (magic = start; magic < end; magic++)
+		msg("%s: %d%%", magic->mi_name, magic->mi_prob);
+	}
+#endif
+	magic = start;
+    }
+    return magic - start;
+}
+
+/*
+ * discovered:
+ *	list what the player has discovered in this game of a certain type
+ */
+static int line_cnt = 0;
+
+static bool newpage = FALSE;
+
+static char *lastfmt, *lastarg;
+
+discovered()
+{
+    register char ch;
+    register bool disc_list;
+
+    do {
+	disc_list = FALSE;
+	if (!terse)
+	    addmsg("for ");
+	addmsg("what type");
+	if (!terse)
+	    addmsg(" of object do you want a list");
+	msg("? (* for all)");
+	ch = readchar();
+	switch (ch)
+	{
+	    case ESCAPE:
+		msg("");
+		return;
+	    case POTION:
+	    case SCROLL:
+	    case RING:
+	    case STICK:
+	    case '*':
+		disc_list = TRUE;
+		break;
+	    default:
+		if (terse)
+		    msg("Not a type");
+		else
+		    msg("Please type one of %c%c%c%c (ESCAPE to quit)", POTION, SCROLL, RING, STICK);
+	}
+    } while (!disc_list);
+    if (ch == '*')
+    {
+	print_disc(POTION);
+	add_line("");
+	print_disc(SCROLL);
+	add_line("");
+	print_disc(RING);
+	add_line("");
+	print_disc(STICK);
+	end_line();
+    }
+    else
+    {
+	print_disc(ch);
+	end_line();
+    }
+}
+
+/*
+ * print_disc:
+ *	Print what we've discovered of type 'type'
+ */
+
+#define MAX(a,b,c,d)	(a > b ? (a > c ? (a > d ? a : d) : (c > d ? c : d)) : (b > c ? (b > d ? b : d) : (c > d ? c : d)))
+
+print_disc(type)
+char type;
+{
+    register bool *know = NULL;
+    register char **guess = NULL;
+    register int i, maxnum = 0, num_found;
+    static THING obj;
+    static short order[MAX(MAXSCROLLS, MAXPOTIONS, MAXRINGS, MAXSTICKS)];
+
+    switch (type)
+    {
+	case SCROLL:
+	    maxnum = MAXSCROLLS;
+	    know = s_know;
+	    guess = s_guess;
+	    break;
+	case POTION:
+	    maxnum = MAXPOTIONS;
+	    know = p_know;
+	    guess = p_guess;
+	    break;
+	case RING:
+	    maxnum = MAXRINGS;
+	    know = r_know;
+	    guess = r_guess;
+	    break;
+	case STICK:
+	    maxnum = MAXSTICKS;
+	    know = ws_know;
+	    guess = ws_guess;
+	    break;
+    }
+    set_order(order, maxnum);
+    obj.o_count = 1;
+    obj.o_flags = 0;
+    num_found = 0;
+    for (i = 0; i < maxnum; i++)
+	if (know[order[i]] || guess[order[i]])
+	{
+	    obj.o_type = type;
+	    obj.o_which = order[i];
+	    add_line("%s", inv_name(&obj, FALSE));
+	    num_found++;
+	}
+    if (num_found == 0)
+	add_line(nothing(type));
+}
+
+/*
+ * set_order:
+ *	Set up order for list
+ */
+set_order(order, numthings)
+short *order;
+int numthings;
+{
+    register int i, r, t;
+
+    for (i = 0; i< numthings; i++)
+	order[i] = i;
+
+    for (i = numthings; i > 0; i--)
+    {
+	r = rnd(i);
+	t = order[i - 1];
+	order[i - 1] = order[r];
+	order[r] = t;
+    }
+}
+
+/*
+ * add_line:
+ *	Add a line to the list of discoveries
+ */
+/* VARARGS1 */
+add_line(fmt, arg)
+char *fmt, *arg;
+{
+    if (line_cnt == 0)
+    {
+	    wclear(hw);
+	    if (slow_invent)
+		mpos = 0;
+    }
+    if (slow_invent)
+    {
+	if (*fmt != '\0')
+	    msg(fmt, arg);
+	line_cnt++;
+    }
+    else
+    {
+	if (line_cnt >= LINES - 1 || fmt == NULL)
+	{
+	    mvwaddstr(hw, LINES - 1, 0, "--Press space to continue--");
+	    wrefresh(hw);
+	    w_wait_for(hw,' ');
+	    clearok(curscr, TRUE);
+	    wclear(hw);
+            touchwin(stdscr);
+	    newpage = TRUE;
+	    line_cnt = 0;
+	}
+	if (fmt != NULL && !(line_cnt == 0 && *fmt == '\0'))
+	{
+	    mvwprintw(hw, line_cnt++, 0, fmt, arg);
+	    lastfmt = fmt;
+	    lastarg = arg;
+	}
+    }
+}
+
+/*
+ * end_line:
+ *	End the list of lines
+ */
+end_line()
+{
+    if (!slow_invent)
+	if (line_cnt == 1 && !newpage)
+	{
+	    mpos = 0;
+	    msg(lastfmt, lastarg);
+	}
+	else
+	    add_line(NULL);
+    line_cnt = 0;
+    newpage = FALSE;
+}
+
+/*
+ * nothing:
+ *	Set up prbuf so that message for "nothing found" is there
+ */
+char *
+nothing(type)
+register char type;
+{
+    register char *sp, *tystr = NULL;
+
+    if (terse)
+	sprintf(prbuf, "Nothing");
+    else
+	sprintf(prbuf, "Haven't discovered anything");
+    if (type != '*')
+    {
+	sp = &prbuf[strlen(prbuf)];
+	switch (type)
+	{
+	    case POTION: tystr = "potion";
+	    when SCROLL: tystr = "scroll";
+	    when RING: tystr = "ring";
+	    when STICK: tystr = "stick";
+	}
+	sprintf(sp, " about any %ss", tystr);
+    }
+    return prbuf;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rogue4/vers.c	Sat Oct 24 16:52:52 2009 +0000
@@ -0,0 +1,18 @@
+/*
+ * Rogue: Exploring the Dungeons of Doom
+ * Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman
+ * All rights reserved.
+ *
+ * See the file LICENSE.TXT for full copyright and licensing information.
+ */
+
+/* 
+ * Version number.  Whenever a new version number is desired, use sccs
+ * to get vers.c.  encstr is declared here to force it to be loaded
+ * before the version number, and therefore not to be written in saved
+ * games.
+ */
+
+char *release = "5.2";
+char encstr[] = "\211g\321_-\251b\324\237;\255\263\214g\"\327\224.,\252|9\265=\357+\343;\311]\341`\251\b\231)\266Y\325\251";
+char version[] = "@(#)vers.c	5.2 (Berkeley) 4/11/82";
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rogue4/weapons.c	Sat Oct 24 16:52:52 2009 +0000
@@ -0,0 +1,285 @@
+/*
+ * Functions for dealing with problems brought about by weapons
+ *
+ * @(#)weapons.c	4.14 (Berkeley) 4/6/82
+ *
+ * Rogue: Exploring the Dungeons of Doom
+ * Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman
+ * All rights reserved.
+ *
+ * See the file LICENSE.TXT for full copyright and licensing information.
+ */
+
+#include <curses.h>
+#include <ctype.h>
+#include <string.h>
+#include "rogue.h"
+
+#define NONE 100
+
+static struct init_weps {
+    char *iw_dam;	/* Damage when wielded */
+    char *iw_hrl;	/* Damage when thrown */
+    char iw_launch;	/* Launching weapon */
+    int iw_flags;	/* Miscellaneous flags */
+} init_dam[MAXWEAPONS] = {
+    "2d4",	"1d3",	NONE, 		0,		/* Mace */
+    "3d4",	"1d2",	NONE,		0,		/* Long sword */
+    "1d1",	"1d1",	NONE,		0,		/* Bow */
+    "1d1",	"2d3",	BOW,		ISMANY|ISMISL,	/* Arrow */
+    "1d6",	"1d4",	NONE,		ISMISL,		/* Dagger */
+    "4d4",	"1d2",	NONE,		0,		/* 2h sword */
+    "1d1",	"1d3",	NONE,		ISMANY|ISMISL,	/* Dart */
+    "1d1",	"1d1",	NONE,		0,		/* Crossbow */
+    "1d2",	"2d5",	CROSSBOW,	ISMANY|ISMISL,	/* Crossbow bolt */
+    "2d3",	"1d6",	NONE,		ISMISL,		/* Spear */
+};
+
+/*
+ * missile:
+ *	Fire a missile in a given direction
+ */
+missile(ydelta, xdelta)
+int ydelta, xdelta;
+{
+    register THING *obj, *nitem;
+
+    /*
+     * Get which thing we are hurling
+     */
+    if ((obj = get_item("throw", WEAPON)) == NULL)
+	return;
+    if (!dropcheck(obj) || is_current(obj))
+	return;
+    /*
+     * 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, obj);
+	inpack--;
+    }
+    else
+    {
+	obj->o_count--;
+	if (obj->o_group == 0)
+	    inpack--;
+	nitem = new_item();
+	*nitem = *obj;
+	nitem->o_count = 1;
+	obj = nitem;
+    }
+    do_motion(obj, ydelta, xdelta);
+    /*
+     * AHA! Here it has hit something.  If it is a wall or a door,
+     * or if it misses (combat) the monster, put it on the floor
+     */
+    if (moat(obj->o_pos.y, obj->o_pos.x) == NULL
+	|| !hit_monster(unc(obj->o_pos), obj))
+	    fall(obj, TRUE);
+}
+
+/*
+ * do_motion:
+ *	Do the actual motion on the screen done by an object traveling
+ *	across the room
+ */
+do_motion(obj, ydelta, xdelta)
+register THING *obj;
+register int ydelta, xdelta;
+{
+    /*
+     * Come fly with us ...
+     */
+    obj->o_pos = hero;
+    for (;;)
+    {
+	register int ch;
+
+	/*
+	 * Erase the old one
+	 */
+	if (!ce(obj->o_pos, hero) && cansee(unc(obj->o_pos)))
+	    mvaddch(obj->o_pos.y, obj->o_pos.x, chat(obj->o_pos.y, obj->o_pos.x));
+	/*
+	 * Get the new position
+	 */
+	obj->o_pos.y += ydelta;
+	obj->o_pos.x += xdelta;
+	if (step_ok(ch = winat(obj->o_pos.y, obj->o_pos.x)) && ch != DOOR)
+	{
+	    /*
+	     * It hasn't hit anything yet, so display it
+	     * If it alright.
+	     */
+	    if (cansee(unc(obj->o_pos)))
+	    {
+		mvaddch(obj->o_pos.y, obj->o_pos.x, obj->o_type);
+		refresh();
+	    }
+	    continue;
+	}
+	break;
+    }
+}
+
+/*
+ * fall:
+ *	Drop an item someplace around here.
+ */
+fall(obj, pr)
+register THING *obj;
+register bool pr;
+{
+    static coord fpos;
+    register int index;
+
+    if (fallpos(&obj->o_pos, &fpos, TRUE))
+    {
+	index = INDEX(fpos.y, fpos.x);
+	_level[index] = obj->o_type;
+	obj->o_pos = fpos;
+	if (cansee(fpos.y, fpos.x))
+	{
+	    mvaddch(fpos.y, fpos.x, obj->o_type);
+	    if (_monst[index] != NULL)
+		_monst[index]->t_oldch = obj->o_type;
+	}
+	attach(lvl_obj, obj);
+	return;
+    }
+
+    if (pr)
+		msg("the %s vanishes as it hits the ground", 
+			/* BUGFIX: Identification trick */
+			(obj->o_type==WEAPON) ? w_names[obj->o_which] : inv_name(obj,TRUE));
+
+	discard(obj);
+}
+
+/*
+ * init_weapon:
+ *	Set up the initial goodies for a weapon
+ */
+init_weapon(weap, type)
+register THING *weap;
+char type;
+{
+    register struct init_weps *iwp;
+
+    iwp = &init_dam[type];
+    strncpy(weap->o_damage, iwp->iw_dam, 8);
+    strncpy(weap->o_hurldmg, iwp->iw_hrl, 8);
+    weap->o_launch = iwp->iw_launch;
+    weap->o_flags = iwp->iw_flags;
+    if (weap->o_flags & ISMANY)
+    {
+	weap->o_count = rnd(8) + 8;
+	weap->o_group = group++;
+    }
+    else
+	weap->o_count = 1;
+}
+
+/*
+ * hit_monster:
+ *	Does the missile hit the monster?
+ */
+hit_monster(y, x, obj)
+register int y, x;
+THING *obj;
+{
+    static coord mp;
+
+    mp.y = y;
+    mp.x = x;
+    return fight(&mp, moat(y, x)->t_type, obj, TRUE);
+}
+
+/*
+ * num:
+ *	Figure out the plus number for armor/weapons
+ */
+char *
+num(n1, n2, type)
+register int n1, n2;
+register char type;
+{
+    static char numbuf[10];
+
+    sprintf(numbuf, "%s%d", n1 < 0 ? "" : "+", n1);
+    if (type == WEAPON)
+	sprintf(&numbuf[strlen(numbuf)], ",%s%d", n2 < 0 ? "" : "+", n2);
+    return numbuf;
+}
+
+/*
+ * wield:
+ *	Pull out a certain weapon
+ */
+wield()
+{
+    register THING *obj, *oweapon;
+    register char *sp;
+
+    oweapon = cur_weapon;
+    if (!dropcheck(cur_weapon))
+    {
+	cur_weapon = oweapon;
+	return;
+    }
+    cur_weapon = oweapon;
+    if ((obj = get_item("wield", WEAPON)) == NULL)
+    {
+bad:
+	after = FALSE;
+	return;
+    }
+
+    if (obj->o_type == ARMOR)
+    {
+	msg("you can't wield armor");
+	goto bad;
+    }
+    if (is_current(obj))
+        goto bad;
+
+    sp = inv_name(obj, TRUE);
+    cur_weapon = obj;
+    if (!terse)
+	addmsg("you are now ");
+    msg("wielding %s (%c)", sp, pack_char(obj));
+}
+
+/*
+ * fallpos:
+ *	Pick a random position around the give (y, x) coordinates
+ */
+fallpos(pos, newpos, pass)
+register coord *pos, *newpos;
+register bool pass;
+{
+    register int y, x, cnt, ch;
+
+    cnt = 0;
+    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;
+	    if (((ch = chat(y, x)) == FLOOR || (pass && ch == PASSAGE))
+					&& rnd(++cnt) == 0)
+	    {
+		newpos->y = y;
+		newpos->x = x;
+	    }
+	}
+    return (cnt != 0);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rogue4/wizard.c	Sat Oct 24 16:52:52 2009 +0000
@@ -0,0 +1,238 @@
+
+/*
+ * Special wizard commands (some of which are also non-wizard commands
+ * under strange circumstances)
+ *
+ * @(#)wizard.c	4.14 (Berkeley) 1/26/82
+ */
+
+#include <curses.h>
+#include <ctype.h>
+#include <string.h>
+#include "rogue.h"
+
+/*
+ * whatis:
+ *	What a certin object is
+ */
+whatis(insist)
+bool insist;
+{
+    register THING *obj;
+
+    if (pack == NULL)
+    {
+	msg("You don't have anything in your pack to identify");
+	return;
+    }
+
+    for (;;)
+	if ((obj = get_item("identify", 0)) == NULL && insist)
+	    msg("You must identify something");
+	else
+	    break;
+
+    if (!insist && obj == NULL)
+	return;
+
+    switch (obj->o_type)
+    {
+        case SCROLL:
+	    s_know[obj->o_which] = TRUE;
+	    if (s_guess[obj->o_which])
+	    {
+		free(s_guess[obj->o_which]);
+		s_guess[obj->o_which] = NULL;
+	    }
+        when POTION:
+	    p_know[obj->o_which] = TRUE;
+	    if (p_guess[obj->o_which])
+	    {
+		free(p_guess[obj->o_which]);
+		p_guess[obj->o_which] = NULL;
+	    }
+	when STICK:
+	    ws_know[obj->o_which] = TRUE;
+	    obj->o_flags |= ISKNOW;
+	    if (ws_guess[obj->o_which])
+	    {
+		free(ws_guess[obj->o_which]);
+		ws_guess[obj->o_which] = NULL;
+	    }
+        when WEAPON:
+        case ARMOR:
+	    obj->o_flags |= ISKNOW;
+        when RING:
+	    r_know[obj->o_which] = TRUE;
+	    obj->o_flags |= ISKNOW;
+	    if (r_guess[obj->o_which])
+	    {
+		free(r_guess[obj->o_which]);
+		r_guess[obj->o_which] = NULL;
+	    }
+    }
+    msg(inv_name(obj, FALSE));
+}
+
+#ifdef WIZARD
+/*
+ * create_obj:
+ *	Wizard command for getting anything he wants
+ */
+create_obj()
+{
+    register THING *obj;
+    register char ch, bless;
+
+    obj = new_item();
+    msg("type of item: ");
+    obj->o_type = readchar();
+    mpos = 0;
+    msg("which %c do you want? (0-f)", obj->o_type);
+    obj->o_which = (isdigit((ch = readchar())) ? ch - '0' : ch - 'a' + 10);
+    obj->o_group = 0;
+    obj->o_count = 1;
+    mpos = 0;
+    if (obj->o_type == WEAPON || obj->o_type == ARMOR)
+    {
+	msg("blessing? (+,-,n)");
+	bless = readchar();
+	mpos = 0;
+	if (bless == '-')
+	    obj->o_flags |= ISCURSED;
+	if (obj->o_type == WEAPON)
+	{
+	    init_weapon(obj, obj->o_which);
+	    if (bless == '-')
+		obj->o_hplus -= rnd(3)+1;
+	    if (bless == '+')
+		obj->o_hplus += rnd(3)+1;
+	}
+	else
+	{
+	    obj->o_ac = a_class[obj->o_which];
+	    if (bless == '-')
+		obj->o_ac += rnd(3)+1;
+	    if (bless == '+')
+		obj->o_ac -= rnd(3)+1;
+	}
+    }
+    else if (obj->o_type == RING)
+	switch (obj->o_which)
+	{
+	    case R_PROTECT:
+	    case R_ADDSTR:
+	    case R_ADDHIT:
+	    case R_ADDDAM:
+		msg("blessing? (+,-,n)");
+		bless = readchar();
+		mpos = 0;
+		if (bless == '-')
+		    obj->o_flags |= ISCURSED;
+		obj->o_ac = (bless == '-' ? -1 : rnd(2) + 1);
+	    when R_AGGR:
+	    case R_TELEPORT:
+		obj->o_flags |= ISCURSED;
+	}
+    else if (obj->o_type == STICK)
+	fix_stick(obj);
+    else if (obj->o_type == GOLD)
+    {
+	msg("how much?");
+	get_num(&obj->o_goldval, stdscr);
+    }
+    add_pack(obj, FALSE);
+}
+#endif
+
+/*
+ * telport:
+ *	Bamf the hero someplace else
+ */
+teleport()
+{
+    register int rm;
+    coord c;
+
+    mvaddch(hero.y, hero.x, chat(hero.y, hero.x));
+    do
+    {
+	rm = rnd_room();
+	rnd_pos(&rooms[rm], &c);
+    } until (step_ok(winat(c.y, c.x)));
+    if (&rooms[rm] != proom)
+    {
+	leave_room(&hero);
+	hero = c;
+	enter_room(&hero);
+    }
+    else
+    {
+	hero = c;
+	look(TRUE);
+    }
+    mvaddch(hero.y, hero.x, PLAYER);
+    /*
+     * turn off ISHELD in case teleportation was done while fighting
+     * a Fungi
+     */
+    if (on(player, ISHELD)) {
+	player.t_flags &= ~ISHELD;
+	fung_hit = 0;
+	strcpy(monsters['F'-'A'].m_stats.s_dmg, "000d0");
+    }
+    no_move = 0;
+    count = 0;
+    running = FALSE;
+    flush_type();
+    return rm;
+}
+
+#ifdef WIZARD
+/*
+ * passwd:
+ *	See if user knows password
+ */
+passwd()
+{
+    register char *sp, c;
+    char buf[MAXSTR], *xcrypt();
+
+    msg("wizard's Password:");
+    mpos = 0;
+    sp = buf;
+    while ((c = readchar()) != '\n' && c != '\r' && c != ESCAPE)
+	if (c == md_killchar())
+	    sp = buf;
+	else if (c == md_erasechar() && sp > buf)
+	    sp--;
+	else
+	    *sp++ = c;
+    if (sp == buf)
+	return FALSE;
+    *sp = '\0';
+    return (strcmp(PASSWD, xcrypt(buf, "mT")) == 0);
+}
+
+/*
+ * show_map:
+ *	Print out the map for the wizard
+ */
+show_map()
+{
+    register int y, x, real;
+
+    wclear(hw);
+    for (y = 1; y < LINES - 1; y++)
+	for (x = 0; x < COLS; x++)
+	{
+	    if (!(real = flat(y, x) & F_REAL))
+		wstandout(hw);
+	    wmove(hw, y, x);
+	    waddch(hw, chat(y, x));
+	    if (!real)
+		wstandend(hw);
+	}
+    show_win(hw, "---More (level map)---");
+}
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rogue4/xcrypt.c	Sat Oct 24 16:52:52 2009 +0000
@@ -0,0 +1,684 @@
+/*
+ * 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 <string.h>
+
+extern unsigned long int md_ntohl(unsigned long int x);
+extern unsigned long int md_htonl(unsigned long int x);
+
+#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(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(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(const unsigned char *key)
+{
+	unsigned int k0, k1, rawkey0, rawkey1;
+	int	shifts, round;
+
+	if (!des_initialised)
+		des_init();
+
+	rawkey0 = md_ntohl(*(unsigned int *) key);
+	rawkey1 = md_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(unsigned int l_in, unsigned int r_in, unsigned int *l_out, 
+       unsigned int *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 = 0, 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(const unsigned char *in, unsigned 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 = md_ntohl(x[0]);
+	rawr = md_ntohl(x[1]);
+	retval = do_des(rawl, rawr, &l_out, &r_out, count);
+
+	x[0] = md_htonl(l_out);
+	x[1] = md_htonl(r_out);
+	memcpy(out, x, sizeof x);
+	return(retval);
+}
+
+char *
+xcrypt(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);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rogue4/xstr.c	Sat Oct 24 16:52:52 2009 +0000
@@ -0,0 +1,436 @@
+/*
+ *
+ * Rogue: Exploring the Dungeons of Doom
+ * Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman
+ * All rights reserved.
+ *
+ * See the file LICENSE.TXT for full copyright and licensing information.
+ */
+
+static char *sccsid = "@(#)xstr.c	4.1 (Berkeley) 10/1/80";
+#include <stdio.h>
+#include <ctype.h>
+#include <sys/types.h>
+#include <signal.h>
+
+/*
+ * xstr - extract and hash strings in a C program
+ *
+ * Bill Joy UCB
+ * November, 1978
+ */
+
+#define	ignore(a)	(a)
+
+char	*calloc();
+off_t	tellpt;
+off_t	hashit();
+char	*mktemp();
+void	onintr(int);
+char	*savestr();
+char	*strcat();
+char	*strcpy();
+off_t	yankstr();
+
+off_t	mesgpt;
+char	*strings =	"strings";
+
+int	cflg;
+int	vflg;
+int	readstd;
+
+main(argc, argv)
+	int argc;
+	char *argv[];
+{
+
+	argc--, argv++;
+	while (argc > 0 && argv[0][0] == '-') {
+		register char *cp = &(*argv++)[1];
+
+		argc--;
+		if (*cp == 0) {
+			readstd++;
+			continue;
+		}
+		do switch (*cp++) {
+
+		case 'c':
+			cflg++;
+			continue;
+
+		case 'v':
+			vflg++;
+			continue;
+
+		default:
+			fprintf(stderr, "usage: xstr [ -v ] [ -c ] [ - ] [ name ... ]\n");
+		} while (*cp);
+	}
+	if (signal(SIGINT, SIG_IGN) == SIG_DFL)
+		signal(SIGINT, onintr);
+	if (cflg || argc == 0 && !readstd)
+		inithash();
+	else
+		strings = mktemp(savestr("/tmp/xstrXXXXXX"));
+	while (readstd || argc > 0) {
+		if (freopen("x.c", "w", stdout) == NULL)
+			perror("x.c"), exit(1);
+		if (!readstd && freopen(argv[0], "r", stdin) == NULL)
+			perror(argv[0]), exit(2);
+		process("x.c");
+		if (readstd == 0)
+			argc--, argv++;
+		else
+			readstd = 0;
+	};
+	flushsh();
+	if (cflg == 0)
+		xsdotc();
+	if (strings[0] == '/')
+		ignore(md_unlink(strings));
+	exit(0);
+}
+
+process(name)
+	char *name;
+{
+	char *cp;
+	char linebuf[BUFSIZ];
+	register int c;
+	register int incomm = 0;
+
+	printf("extern char\txstr[];\n");
+	for (;;) {
+		if (fgets(linebuf, sizeof linebuf, stdin) == NULL) {
+			if (ferror(stdin)) {
+				perror(name);
+				exit(3);
+			}
+			break;
+		}
+		if (linebuf[0] == '#') {
+			if (linebuf[1] == ' ' && isdigit(linebuf[2]))
+				printf("#line%s", &linebuf[1]);
+			else
+				printf("%s", linebuf);
+			continue;
+		}
+		for (cp = linebuf; c = *cp++;) switch (c) {
+			
+		case '"':
+			if (incomm)
+				goto def;
+			printf("(&xstr[%d])", (int) yankstr(&cp));
+			break;
+
+		case '\'':
+			if (incomm)
+				goto def;
+			putchar(c);
+			if (*cp)
+				putchar(*cp++);
+			break;
+
+		case '/':
+			if (incomm || *cp != '*')
+				goto def;
+			incomm = 1;
+			cp++;
+			printf("/*");
+			continue;
+
+		case '*':
+			if (incomm && *cp == '/') {
+				incomm = 0;
+				cp++;
+				printf("*/");
+				continue;
+			}
+			goto def;
+		
+def:
+		default:
+			putchar(c);
+			break;
+		}
+	}
+	if (ferror(stdout))
+		perror("x.c"), onintr(-1);
+}
+
+off_t
+yankstr(cpp)
+	register char **cpp;
+{
+	register char *cp = *cpp;
+	register int c, ch;
+	char dbuf[BUFSIZ];
+	register char *dp = dbuf;
+	register char *tp;
+
+	while (c = *cp++) {
+		switch (c) {
+
+		case '"':
+			cp++;
+			goto out;
+
+		case '\\':
+			c = *cp++;
+			if (c == 0)
+				break;
+			if (c == '\n')
+				continue;
+			for (tp = "b\bt\tr\rn\nf\f\\\\\"\""; ch = *tp++; tp++)
+				if (c == ch) {
+					c = *tp;
+					goto gotc;
+				}
+			if (!octdigit(c)) {
+				*dp++ = '\\';
+				break;
+			}
+			c -= '0';
+			if (!octdigit(*cp))
+				break;
+			c <<= 3, c += *cp++ - '0';
+			if (!octdigit(*cp))
+				break;
+			c <<= 3, c += *cp++ - '0';
+			break;
+		}
+gotc:
+		*dp++ = c;
+	}
+out:
+	*cpp = --cp;
+	*dp = 0;
+	return (hashit(dbuf, 1));
+}
+
+octdigit(c)
+	char c;
+{
+
+	return (isdigit(c) && c != '8' && c != '9');
+}
+
+inithash()
+{
+	char buf[BUFSIZ];
+	register FILE *mesgread = fopen(strings, "r");
+
+	if (mesgread == NULL)
+		return;
+	for (;;) {
+		mesgpt = tellpt;
+		if (fgetNUL(buf, sizeof buf, mesgread) == 0)
+			break;
+		hashit(buf, 0);
+	}
+	ignore(fclose(mesgread));
+}
+
+fgetNUL(obuf, rmdr, file)
+	char *obuf;
+	register int rmdr;
+	FILE *file;
+{
+	register c;
+	register char *buf = obuf;
+
+	while (--rmdr > 0 && (c = xgetc(file)) != 0 && c != EOF)
+		*buf++ = c;
+	*buf++ = 0;
+	return ((feof(file) || ferror(file)) ? 0 : 1);
+}
+
+xgetc(file)
+	FILE *file;
+{
+
+	tellpt++;
+	return (getc(file));
+}
+
+#define	BUCKETS	128
+
+struct	hash {
+	off_t	hpt;
+	char	*hstr;
+	struct	hash *hnext;
+	short	hnew;
+} bucket[BUCKETS];
+
+off_t
+hashit(str, new)
+	char *str;
+	int new;
+{
+	int i;
+	register struct hash *hp, *hp0;
+
+	hp = hp0 = &bucket[lastchr(str) & 0177];
+	while (hp->hnext) {
+		hp = hp->hnext;
+		i = istail(str, hp->hstr);
+		if (i >= 0)
+			return (hp->hpt + i);
+	}
+	hp = (struct hash *) calloc(1, sizeof (*hp));
+	hp->hpt = mesgpt;
+	hp->hstr = savestr(str);
+	mesgpt += strlen(hp->hstr) + 1;
+	hp->hnext = hp0->hnext;
+	hp->hnew = new;
+	hp0->hnext = hp;
+	return (hp->hpt);
+}
+
+flushsh()
+{
+	register int i;
+	register struct hash *hp;
+	register FILE *mesgwrit;
+	register int old = 0, new = 0;
+
+	for (i = 0; i < BUCKETS; i++)
+		for (hp = bucket[i].hnext; hp != NULL; hp = hp->hnext)
+			if (hp->hnew)
+				new++;
+			else
+				old++;
+	if (new == 0 && old != 0)
+		return;
+	mesgwrit = fopen(strings, old ? "a" : "w");
+	for (i = 0; i < BUCKETS; i++)
+		for (hp = bucket[i].hnext; hp != NULL; hp = hp->hnext) {
+			found(hp->hnew, hp->hpt, hp->hstr);
+			if (hp->hnew) {
+				fseek(mesgwrit, hp->hpt, 0);
+				ignore(fwrite(hp->hstr, strlen(hp->hstr) + 1, 1, mesgwrit));
+				if (ferror(mesgwrit))
+					perror(strings), exit(4);
+			}
+		}
+	ignore(fclose(mesgwrit));
+}
+
+found(new, off, str)
+	int new;
+	off_t off;
+	char *str;
+{
+	if (vflg == 0)
+		return;
+	if (!new)
+		fprintf(stderr, "found at %d:", (int) off);
+	else
+		fprintf(stderr, "new at %d:", (int) off);
+	prstr(str);
+	fprintf(stderr, "\n");
+}
+
+prstr(cp)
+	register char *cp;
+{
+	register int c;
+
+	while (c = (*cp++ & 0377))
+		if (c < ' ')
+			fprintf(stderr, "^%c", c + '`');
+		else if (c == 0177)
+			fprintf(stderr, "^?");
+		else if (c > 0200)
+			fprintf(stderr, "\\%03o", c);
+		else
+			fprintf(stderr, "%c", c);
+}
+
+xsdotc()
+{
+	register FILE *strf = fopen(strings, "r");
+	register FILE *xdotcf;
+
+	if (strf == NULL)
+		perror(strings), exit(5);
+	xdotcf = fopen("xs.c", "w");
+	if (xdotcf == NULL)
+		perror("xs.c"), exit(6);
+	fprintf(xdotcf, "char\txstr[] = {\n");
+	for (;;) {
+		register int i, c;
+
+		for (i = 0; i < 20; i++) {
+			c = getc(strf);
+			if (ferror(strf)) {
+				perror(strings);
+				onintr(-1);
+			}
+			if (feof(strf)) {
+				fprintf(xdotcf, "\n");
+				goto out;
+			}
+			fprintf(xdotcf, "%d,", c);
+		}
+		fprintf(xdotcf, "\n");
+	}
+out:
+	fprintf(xdotcf, "};\n");
+	ignore(fclose(xdotcf));
+	ignore(fclose(strf));
+}
+
+char *
+savestr(cp)
+	register char *cp;
+{
+	register char *dp = (char *) calloc(1, strlen(cp) + 1);
+
+	return (strcpy(dp, cp));
+}
+
+Ignore(void *a)
+{
+
+	a = a;
+}
+
+ignorf(a)
+void (*a)();
+{
+
+	a = a;
+}
+
+lastchr(cp)
+	register char *cp;
+{
+
+	while (cp[0] && cp[1])
+		cp++;
+	return (*cp);
+}
+
+istail(str, of)
+	register char *str, *of;
+{
+	register int d = strlen(of) - strlen(str);
+
+	if (d < 0 || strcmp(&of[d], str) != 0)
+		return (-1);
+	return (d);
+}
+
+void
+onintr(int sig)
+{
+
+	ignorf(signal(SIGINT, SIG_IGN));
+	if (strings[0] == '/')
+		ignore(md_unlink(strings));
+	ignore(md_unlink("x.c"));
+	ignore(md_unlink("xs.c"));
+	exit(7);
+}