changeset 0:527e2150eaf0

Import Rogue 3.6 from the Roguelike Restoration Project (r1490)
author edwarj4
date Tue, 13 Oct 2009 13:33:34 +0000
parents
children b4856d4d4c4e
files rogue3/LICENSE.TXT rogue3/Makefile rogue3/armor.c rogue3/chase.c rogue3/command.c rogue3/daemon.c rogue3/daemons.c rogue3/fight.c rogue3/init.c rogue3/io.c rogue3/list.c rogue3/machdep.h rogue3/main.c rogue3/mdport.c rogue3/mdport.h rogue3/misc.c rogue3/monsters.c rogue3/move.c rogue3/newlevel.c rogue3/options.c rogue3/pack.c rogue3/passages.c rogue3/potions.c rogue3/readme36.html rogue3/rings.c rogue3/rip.c rogue3/rogue.6 rogue3/rogue.h rogue3/rogue.r rogue3/rogue36.cat rogue3/rogue36.doc rogue3/rogue36.html rogue3/rogue36.sln rogue3/rogue36.vcproj rogue3/rooms.c rogue3/save.c rogue3/scrolls.c rogue3/state.c rogue3/sticks.c rogue3/things.c rogue3/vers.c rogue3/weapons.c rogue3/wizard.c rogue3/xcrypt.c
diffstat 44 files changed, 15930 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rogue3/LICENSE.TXT	Tue Oct 13 13:33:34 2009 +0000
@@ -0,0 +1,92 @@
+Rogue: Exploring the Dungeons of Doom
+Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+1. Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+3. Neither the name(s) of the author(s) nor the names of other contributors
+   may be used to endorse or promote products derived from this software
+   without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) AND CONTRIBUTORS ``AS IS'' AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR(S) OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGE.
+
+===========================================================================
+
+Portions of this software (state.c/mdport.c/mdport.h) are based on the work 
+of Nicholas J. Kisseberth. Used under license:
+
+Copyright (C) 1999, 2000, 2006, 2007, 2008 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 (xcrypt.c) 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/rogue3/Makefile	Tue Oct 13 13:33:34 2009 +0000
@@ -0,0 +1,151 @@
+#
+# Makefile for rogue
+# %W% (Berkeley) %G%
+#
+# Rogue: Exploring the Dungeons of Doom
+# Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
+# All rights reserved.
+#
+# See the file LICENSE.TXT for full copyright and licensing information.
+#
+
+DISTNAME=rogue3.6.4
+PROGRAM=rogue
+
+O=o
+
+HDRS= 	rogue.h machdep.h
+
+OBJS1 = vers.$(O) armor.$(O) chase.$(O) command.$(O) daemon.$(O) daemons.$(O) \
+        fight.$(O) init.$(O) io.$(O) list.$(O) main.$(O) mdport.$(O) \
+	misc.$(O) monsters.$(O) move.$(O) newlevel.$(O) options.$(O) 
+OBJS2 =	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)
+OBJS  = $(OBJS1) $(OBJS2)
+
+CFILES= vers.c armor.c chase.c command.c daemon.c daemons.c fight.c \
+	init.c io.c list.c main.c mdport.c misc.c monsters.c move.c newlevel.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 xcrypt.c
+
+
+MISC_C=
+DOCSRC= rogue.6 rogue.r
+DOCS  = $(PROGRAM).doc $(PROGRAM).cat $(PROGRAM).html readme36.html
+MISC  =	Makefile $(MISC_C) LICENSE.TXT $(PROGRAM).sln $(PROGRAM).vcproj $(DOCS)\
+	$(DOCSRC)
+
+CC    = gcc
+ROPTS =
+COPTS = -O3
+CFLAGS= $(COPTS) $(ROPTS) -DSCOREFILE=\"rogue36.scr\"
+LIBS  = -lcurses
+RM    = rm -f
+LD    = $(CC)
+LDOUT = -o 
+
+.SUFFIXES: .obj
+
+.c.obj:
+	$(CC) $(CFLAGS) /c $*.c
+
+$(PROGRAM)$(EXE): $(HDRS) $(OBJS)
+	$(LD) $(LDFLAGS) $(OBJS) $(LIBS) $(LDOUT)$@
+
+clean:
+	$(RM) $(OBJS1)
+	$(RM) $(OBJS2)
+	$(RM) core $(PROGRAM) $(PROGRAM).exe $(DISTNAME).tar $(DISTNAME).tar.gz 
+	$(RM) $(DISTNAME).zip
+
+dist.src:
+	make clean
+	tar cf $(DISTNAME)-src.tar $(CFILES) $(HDRS) $(MISC) $(DOCS)
+	gzip -f $(DISTNAME)-src.tar
+
+dist.irix:
+	@$(MAKE) clean
+	@$(MAKE) CC=cc CFLAGS="-woff 1116 -O3" $(PROGRAM)
+#	tbl rogue.r | nroff -ms | colcrt - > $(PROGRAM).doc
+#	nroff -man rogue.6 | colcrt - > $(PROGRAM).cat
+	tar cf $(DISTNAME)-irix.tar $(PROGRAM) LICENSE.TXT $(DOCS)
+	gzip -f $(DISTNAME)-irix.tar
+
+dist.aix:
+	@$(MAKE) clean
+	@$(MAKE) CC=xlc CFLAGS="-qmaxmem=16768 -O3 -qstrict" $(PROGRAM)
+#	tbl rogue.r | nroff -ms | colcrt - > $(ROGUE).doc
+#	nroff -man rogue.6 | colcrt - > $(ROGUE).cat
+	tar cf $(DISTNAME)-aix.tar $(PROGRAM) LICENSE.TXT $(DOCS)
+	gzip -f $(DISTNAME)-aix.tar
+
+dist.linux:
+	@$(MAKE) clean
+	@$(MAKE) $(PROGRAM)
+#	groff -P-c -t -ms -Tascii rogue.r | sed -e 's/.\x08//g' > $(PROGRAM).doc
+#	groff -man rogue.6 | sed -e 's/.\x08//g' > $(PROGRAM).cat
+	tar cf $(DISTNAME)-linux.tar $(PROGRAM) LICENSE.TXT $(DOCS)
+	gzip -f $(DISTNAME)-linux.tar
+	
+debug.linux:
+	@$(MAKE) clean
+	@$(MAKE) COPTS="-g" $(PROGRAM)
+#	groff -P-c -t -ms -Tascii rogue.r | sed -e 's/.\x08//g' > $(PROGRAM).doc
+#	groff -man rogue.6 | sed -e 's/.\x08//g' > $(PROGRAM).cat
+	
+dist.interix: 
+	@$(MAKE) clean
+	@$(MAKE) COPTS="-ansi" $(PROGRAM)
+#	groff -P-b -P-u -t -ms -Tascii rogue.r > $(PROGRAM).doc
+#	groff -P-b -P-u -man -Tascii rogue.6 > $(PROGRAM).cat
+	tar cf $(DISTNAME)-interix.tar $(PROGRAM) LICENSE.TXT $(DOCS)
+	gzip -f $(DISTNAME)-interix.tar	
+
+dist.cygwin:
+	@$(MAKE) --no-print-directory clean
+	@$(MAKE) COPTS="-I/usr/include/ncurses" --no-print-directory $(PROGRAM)
+#	groff -P-c -t -ms -Tascii rogue.r | sed -e 's/.\x08//g' > $(PROGRAM).doc
+#	groff -P-c -man -Tascii rogue.6 | sed -e 's/.\x08//g' > $(PROGRAM).cat
+	tar cf $(DISTNAME)-cygwin.tar $(PROGRAM).exe LICENSE.TXT $(DOCS)
+	gzip -f $(DISTNAME)-cygwin.tar
+
+#
+# Use MINGW32-MAKE to build this target
+#
+dist.mingw32:
+	@$(MAKE) --no-print-directory RM="cmd /c del" clean
+	@$(MAKE) --no-print-directory COPTS="-I../pdcurses" LIBS="../pdcurses/pdcurses.a" $(PROGRAM)
+	cmd /c del $(DISTNAME)-mingw32.zip
+	zip $(DISTNAME)-mingw32.zip $(PROGRAM).exe LICENSE.TXT $(DOCS)
+	
+#
+# Seperate doc targets for DJGPP prevent strange SIGSEGV in groff
+# in that environment.
+#
+doc.djgpp:
+	groff -t -ms -Tascii rogue.r | sed -e 's/.\x08//g' > $(PROGRAM).doc
+
+cat.djgpp:
+	groff -man -Tascii rogue.6 | sed -e 's/.\x08//g' > $(PROGRAM).cat
+
+dist.djgpp: 
+	@$(MAKE) --no-print-directory clean
+	@$(MAKE) --no-print-directory LDFLAGS="-L$(DJDIR)/LIB" \
+		LIBS="-lpdcur" $(PROGRAM)
+#	@$(MAKE) --no-print-directory doc.djgpp
+#	@$(MAKE) --no-print-directory cat.djgpp
+	rm -f $(DISTNAME)-djgpp.zip
+	zip $(DISTNAME)-djgpp.zip $(PROGRAM) LICENSE.TXT $(DOCS)
+
+#
+# Use NMAKE to build this target
+#
+dist.win32:
+	@$(MAKE) /NOLOGO O="obj" RM="-del" clean
+	@$(MAKE) /NOLOGO O="obj" CC="@CL" LD="link" LDOUT="/OUT:" EXE=".exe"\
+	    LIBS="/NODEFAULTLIB:LIBC ..\pdcurses\pdcurses.lib shell32.lib user32.lib Advapi32.lib" \
+	    COPTS="-nologo -D_CRT_SECURE_NO_DEPRECATE -I..\pdcurses \
+	    -Ox -wd4033 -wd4716" $(PROGRAM).exe
+	-del $(DISTNAME)-win32.zip
+	zip $(DISTNAME)-win32.zip $(PROGRAM).exe LICENSE.TXT $(DOCS)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rogue3/armor.c	Tue Oct 13 13:33:34 2009 +0000
@@ -0,0 +1,93 @@
+/*
+ * This file contains misc functions for dealing with armor
+ * @(#)armor.c	3.9 (Berkeley) 6/15/81
+ * 
+ * Rogue: Exploring the Dungeons of Doom
+ * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
+ * All rights reserved.
+ *
+ * See the file LICENSE.TXT for full copyright and licensing information.
+ */
+
+#include "curses.h"
+#include "rogue.h"
+
+/*
+ * wear:
+ *	The player wants to wear something, so let him/her put it on.
+ */
+
+void
+wear()
+{
+    register struct linked_list *item;
+    register struct object *obj;
+
+    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 ((item = get_item("wear", ARMOR)) == NULL)
+	return;
+    obj = (struct object *) ldata(item);
+    if (obj->o_type != ARMOR)
+    {
+	msg("You can't wear that.");
+	return;
+    }
+    waste_time();
+    if (!terse)
+	addmsg("You are now w");
+    else
+	addmsg("W");
+    msg("earing %s.", a_names[obj->o_which]);
+    cur_armor = obj;
+    obj->o_flags |= ISKNOW;
+}
+
+/*
+ * take_off:
+ *	Get the armor off of the players back
+ */
+
+void
+take_off()
+{
+    register struct object *obj;
+
+    if ((obj = cur_armor) == NULL)
+    {
+	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
+ */
+
+void
+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/rogue3/chase.c	Tue Oct 13 13:33:34 2009 +0000
@@ -0,0 +1,319 @@
+/*
+ * Code for one object to chase another
+ *
+ * @(#)chase.c	3.17 (Berkeley) 6/15/81
+ *
+ * Rogue: Exploring the Dungeons of Doom
+ * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
+ * All rights reserved.
+ *
+ * See the file LICENSE.TXT for full copyright and licensing information.
+ */
+
+#include "curses.h"
+#include "rogue.h"
+
+coord ch_ret;				/* Where chasing takes you */
+
+/*
+ * runners:
+ *	Make all the running monsters move.
+ */
+
+void
+runners()
+{
+    struct linked_list *item;
+    struct thing *tp;
+
+    for (item = mlist; item != NULL;)
+    {
+	tp = (struct thing *) ldata(item);
+        item = next(item);
+	if (off(*tp, ISHELD) && on(*tp, ISRUN))
+	{
+	    if (off(*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.
+ */
+
+int
+do_chase(struct thing *th)
+{
+    struct room *rer, *ree;	/* room of chaser, room of chasee */
+    int mindist = 32767, i, dist;
+    int stoprun = FALSE;	/* TRUE means we are there */
+    int sch;
+    coord this;				/* Temporary destination for chaser */
+
+    rer = roomin(&th->t_pos);	/* Find room of chaser */
+    ree = roomin(th->t_dest);	/* Find room of chasee */
+    /*
+     * We don't count doors as inside rooms for this routine
+     */
+    if (mvwinch(stdscr, th->t_pos.y, th->t_pos.x) == DOOR)
+	rer = NULL;
+    this = *th->t_dest;
+    /*
+     * If the object of our desire is in a different room, 
+     * than we are and we ar not in a corridor, run to the
+     * door nearest to our goal.
+     */
+    if (rer != NULL && 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)			/* minimize distance */
+	    {
+		this = rer->r_exit[i];
+		mindist = dist;
+	    }
+	}
+    /*
+     * 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 (th->t_type != 'F')
+	    stoprun = TRUE;
+    }
+    else if (th->t_type == 'F')
+	return(0);
+    mvwaddch(cw, th->t_pos.y, th->t_pos.x, th->t_oldch);
+    sch = mvwinch(cw, ch_ret.y, ch_ret.x);
+    if (rer != NULL && (rer->r_flags & ISDARK) && sch == FLOOR
+	&& DISTANCE(ch_ret.y, ch_ret.x, th->t_pos.y, th->t_pos.x) < 3
+	&& off(player, ISBLIND))
+	    th->t_oldch = ' ';
+    else
+	th->t_oldch = sch;
+
+    if (cansee(unc(ch_ret)) && !on(*th, ISINVIS))
+        mvwaddch(cw, ch_ret.y, ch_ret.x, th->t_type);
+    mvwaddch(mw, th->t_pos.y, th->t_pos.x, ' ');
+    mvwaddch(mw, ch_ret.y, ch_ret.x, th->t_type);
+    th->t_pos = ch_ret;
+    /*
+     * And stop running if need be
+     */
+    if (stoprun && ce(th->t_pos, *(th->t_dest)))
+	th->t_flags &= ~ISRUN;
+
+    return(0);
+}
+
+/*
+ * runto:
+ *	Set a mosnter running after something
+ *	or stop it from running (for when it dies)
+ */
+
+void
+runto(coord *runner, coord *spot)
+{
+    struct linked_list *item;
+    struct thing *tp;
+
+    /*
+     * If we couldn't find him, something is funny
+     */
+    if ((item = find_mons(runner->y, runner->x)) == NULL)
+    {
+	msg("CHASER '%s'", unctrl(winat(runner->y, runner->x)));
+	return;
+    }
+    tp = (struct thing *) ldata(item);
+    /*
+     * Start the beastie running
+     */
+    tp->t_dest = spot;
+    tp->t_flags |= ISRUN;
+    tp->t_flags &= ~ISHELD;
+}
+
+/*
+ * 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.
+ */
+
+int
+chase(struct thing *tp, coord *ee)
+{
+    int x, y;
+    int dist, thisdist;
+    struct linked_list *item;
+    struct object *obj;
+    coord *er = &tp->t_pos;
+    int ch;
+
+    /*
+     * 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(10) < 8) || (tp->t_type == 'I' && rnd(100) < 20)
+	|| (tp->t_type == 'B' && rnd(100) < 50))
+    {
+	/*
+	 * 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(1000) < 50)
+	    tp->t_flags &= ~ISHUH;
+    }
+    /*
+     * Otherwise, find the empty spot next to the chaser that is
+     * closest to the chasee.
+     */
+    else
+    {
+	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 (item = lvl_obj; item != NULL; item = next(item))
+			{
+			    obj = (struct object *) ldata(item);
+			    if (y == obj->o_pos.y && x == obj->o_pos.x)
+				break;
+			}
+			if (item != NULL && obj->o_which == S_SCARE)
+			    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)
+		    {
+			ch_ret = tryp;
+			dist = thisdist;
+		    }
+		}
+	    }
+    }
+    return (dist != 0);
+}
+
+/*
+ * roomin:
+ *	Find what room some coordinates are in. NULL means they aren't
+ *	in any room.
+ */
+
+struct room *
+roomin(coord *cp)
+{
+    struct room *rp;
+
+    for (rp = rooms; rp <= &rooms[MAXROOMS-1]; rp++)
+	if (inroom(rp, cp))
+	    return rp;
+    return NULL;
+}
+
+/*
+ * find_mons:
+ *	Find the monster from his corrdinates
+ */
+
+struct linked_list *
+find_mons(int y, int x)
+{
+    struct linked_list *item;
+    struct thing *th;
+
+    for (item = mlist; item != NULL; item = next(item))
+    {
+	th = (struct thing *) ldata(item);
+	if (th->t_pos.y == y && th->t_pos.x == x)
+	    return item;
+    }
+    return NULL;
+}
+
+/*
+ * diag_ok:
+ *	Check to see if the move is legal if it is diagonal
+ */
+
+int
+diag_ok(coord *sp, coord *ep)
+{
+    if (ep->x == sp->x || ep->y == sp->y)
+	return TRUE;
+    return (step_ok(mvinch(ep->y, sp->x)) && step_ok(mvinch(sp->y, ep->x)));
+}
+
+/*
+ * cansee:
+ *	returns true if the hero can see a certain coordinate.
+ */
+
+int
+cansee(int y, int x)
+{
+    struct room *rer;
+    coord tp;
+
+    if (on(player, ISBLIND))
+	return FALSE;
+    tp.y = y;
+    tp.x = x;
+    rer = roomin(&tp);
+    /*
+     * We can only see if the hero in the same room as
+     * the coordinate and the room is lit or if it is close.
+     */
+    return (rer != NULL && rer == roomin(&hero) && !(rer->r_flags&ISDARK)) ||
+	    DISTANCE(y, x, hero.y, hero.x) < 3;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rogue3/command.c	Tue Oct 13 13:33:34 2009 +0000
@@ -0,0 +1,645 @@
+/*
+ * Read and execute the user commands
+ *
+ * @(#)command.c	3.45 (Berkeley) 6/15/81
+ *
+ * Rogue: Exploring the Dungeons of Doom
+ * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
+ * All rights reserved.
+ *
+ * See the file LICENSE.TXT for full copyright and licensing information.
+ */
+
+#include <stdlib.h>
+#include <ctype.h>
+#include <signal.h>
+#include <string.h>
+#include "curses.h"
+#include "machdep.h"
+#include "rogue.h"
+
+/*
+ * command:
+ *	Process the user commands
+ */
+
+void
+command()
+{
+    int ch;
+    int ntimes = 1;			/* Number of player moves */
+    static int countch, direction, newcount = FALSE;
+
+
+    if (on(player, ISHASTE)) ntimes++;
+    /*
+     * Let the daemons start up
+     */
+    do_daemons(BEFORE);
+    do_fuses(BEFORE);
+    while (ntimes--)
+    {
+	look(TRUE);
+	if (!running)
+	    door_stop = FALSE;
+	status();
+	lastscore = purse;
+	wmove(cw, hero.y, hero.x);
+	if (!((running || count) && jump))
+	    draw(cw);			/* Draw screen */
+	take = 0;
+	after = TRUE;
+	/*
+	 * Read command or continue run
+	 */
+	if (wizard)
+	    waswizard = TRUE;
+	if (!no_command)
+	{
+	    if (running) ch = runch;
+	    else if (count) ch = countch;
+	    else
+	    {
+		ch = readchar(cw);
+		if (mpos != 0 && !running)	/* Erase message if its there */
+		    msg("");
+	    }
+	}
+	else ch = ' ';
+	if (no_command)
+	{
+	    if (--no_command == 0)
+		msg("You can move again.");
+	}
+	else
+	{
+	    /*
+	     * check for prefixes
+	     */
+	    if (isdigit(ch))
+	    {
+		count = 0;
+		newcount = TRUE;
+		while (isdigit(ch))
+		{
+		    count = count * 10 + (ch - '0');
+		    ch = readchar(cw);
+		}
+		countch = ch;
+		/*
+		 * turn off count for commands which don't make sense
+		 * to repeat
+		 */
+		switch (ch) {
+		    case 'h': case 'j': case 'k': case 'l':
+		    case 'y': case 'u': case 'b': case 'n':
+		    case 'H': case 'J': case 'K': case 'L':
+		    case 'Y': case 'U': case 'B': case 'N':
+		    case 'q': case 'r': case 's': case 'f':
+		    case 't': case 'C': case 'I': case ' ':
+		    case 'z': case 'p':
+			break;
+		    default:
+			count = 0;
+		}
+	    }
+	    switch (ch)
+	    {
+		case 'f':
+		    if (!on(player, ISBLIND))
+		    {
+			door_stop = TRUE;
+			firstmove = TRUE;
+		    }
+		    if (count && !newcount)
+			ch = direction;
+		    else
+			ch = readchar(cw);
+		    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(0);
+		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();
+		when 'c' : call();
+		when '>' : after = FALSE; d_level();
+		when '<' : after = FALSE; u_level();
+		when '?' : after = FALSE; help();
+		when '/' : after = FALSE; identify();
+		when 's' : search();
+		when 'z' : do_zap(FALSE);
+		when 'p':
+		    if (get_dir())
+			do_zap(TRUE);
+		    else
+			after = FALSE;
+		when 'v' : msg("Rogue version %s. (mctesq was here)", release);
+		when CTRL('L') : after = FALSE; clearok(curscr,TRUE);draw(curscr);
+		when CTRL('R') : after = FALSE; msg(huh);
+		when 'S' : 
+		    after = FALSE;
+		    if (save_game())
+		    {
+			wmove(cw, LINES-1, 0); 
+			wclrtoeol(cw);
+			draw(cw);
+			endwin();
+			exit(0);
+		    }
+		when ' ' : ;			/* Rest command */
+		when CTRL('P') :
+		    after = FALSE;
+		    if (wizard)
+		    {
+			wizard = FALSE;
+			msg("Not wizard any more");
+		    }
+		    else
+		    {
+			if (wizard = passwd())
+			{
+			    msg("You are suddenly as smart as Ken Arnold in dungeon #%d", dnum);
+ 			    wizard = TRUE;
+			    waswizard = TRUE;
+			}
+			else
+			    msg("Sorry");
+		    }
+		when ESCAPE :	/* Escape */
+		    door_stop = FALSE;
+		    count = 0;
+		    after = FALSE;
+		otherwise :
+		    after = FALSE;
+		    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();
+			when CTRL('D') : level++; new_level();
+			when CTRL('U') : level--; new_level();
+			when CTRL('F') : show_win(stdscr, "--More (level map)--");
+			when CTRL('X') : show_win(mw, "--More (monsters)--");
+			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('C') : add_pass();
+			when CTRL('N') :
+			{
+			    struct linked_list *item;
+
+			    if ((item = get_item("charge", STICK)) != NULL)
+				((struct object *) ldata(item))->o_charges = 10000;
+			}
+			when CTRL('H') :
+			{
+			    int i;
+			    struct linked_list *item;
+			    struct object *obj;
+
+			    for (i = 0; i < 9; i++)
+				raise_level();
+			    /*
+			     * Give the rogue a sword (+1,+1)
+			     */
+			    item = new_item(sizeof *obj);
+			    obj = (struct object *) ldata(item);
+			    obj->o_type = WEAPON;
+			    obj->o_which = TWOSWORD;
+			    init_weapon(obj, SWORD);
+			    obj->o_hplus = 1;
+			    obj->o_dplus = 1;
+			    add_pack(item, TRUE);
+			    cur_weapon = obj;
+			    /*
+			     * And his suit of armor
+			     */
+			    item = new_item(sizeof *obj);
+			    obj = (struct object *) ldata(item);
+			    obj->o_type = ARMOR;
+			    obj->o_which = PLATE_MAIL;
+			    obj->o_ac = -5;
+			    obj->o_flags |= ISKNOW;
+			    cur_armor = obj;
+			    add_pack(item, TRUE);
+			}
+			otherwise :
+			    msg("Illegal command '%s'.", unctrl(ch));
+			    count = 0;
+		    }
+		    else
+		    {
+			msg("Illegal command '%s'.", unctrl(ch));
+			count = 0;
+		    }
+	    }
+	    /*
+	     * 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++;
+    }
+    /*
+     * Kick off the rest if the daemons and fuses
+     */
+    if (after)
+    {
+	look(FALSE);
+	do_daemons(AFTER);
+	do_fuses(AFTER);
+	if (ISRING(LEFT, R_SEARCH))
+	    search();
+	else if (ISRING(LEFT, R_TELEPORT) && rnd(100) < 2)
+	    teleport();
+	if (ISRING(RIGHT, R_SEARCH))
+	    search();
+	else if (ISRING(RIGHT, R_TELEPORT) && rnd(100) < 2)
+	    teleport();
+    }
+}
+
+/*
+ * quit:
+ *	Have player make certain, then exit.
+ */
+
+void
+quit(int p)
+{
+    /*
+     * Reset the signal in case we got here via an interrupt
+     */
+    if (signal(SIGINT, quit) != &quit)
+	mpos = 0;
+    msg("Really quit?");
+    draw(cw);
+    if (readchar(cw) == 'y')
+    {
+	clear();
+	move(LINES-1, 0);
+	draw(stdscr);
+	endwin();
+	score(purse, 1, 0);
+	exit(0);
+    }
+    else
+    {
+	signal(SIGINT, quit);
+	wmove(cw, 0, 0);
+	wclrtoeol(cw);
+	status();
+	draw(cw);
+	mpos = 0;
+	count = 0;
+    }
+}
+
+/*
+ * search:
+ *	Player gropes about him to find hidden things.
+ */
+
+void
+search()
+{
+    int x, y;
+    int ch;
+
+    /*
+     * Look all around the hero, if there is something hidden there,
+     * give him a chance to find it.  If its found, display it.
+     */
+    if (on(player, ISBLIND))
+	return;
+    for (x = hero.x - 1; x <= hero.x + 1; x++)
+	for (y = hero.y - 1; y <= hero.y + 1; y++)
+	{
+	    ch = winat(y, x);
+	    switch (ch)
+	    {
+		case SECRETDOOR:
+		    if (rnd(100) < 20) {
+			mvaddch(y, x, DOOR);
+			count = 0;
+		    }
+		    break;
+		case TRAP:
+		{
+		    struct trap *tp;
+
+		    if (mvwinch(cw, y, x) == TRAP)
+			break;
+		    if (rnd(100) > 50)
+			break;
+		    tp = trap_at(y, x);
+		    tp->tr_flags |= ISFOUND;
+		    mvwaddch(cw, y, x, TRAP);
+		    count = 0;
+		    running = FALSE;
+		    msg(tr_name(tp->tr_type));
+		}
+	    }
+	}
+}
+
+/*
+ * help:
+ *	Give single character help, or the whole mess if he wants it
+ */
+
+void
+help()
+{
+    struct h_list *strp = helpstr;
+    int helpch;
+    int cnt;
+
+    msg("Character you want help for (* for all): ");
+    helpch = readchar(cw);
+    mpos = 0;
+    /*
+     * If its not a *, print the right help string
+     * or an error if he typed a funny character.
+     */
+    if (helpch != '*')
+    {
+	wmove(cw, 0, 0);
+	while (strp->h_ch)
+	{
+	    if (strp->h_ch == helpch)
+	    {
+		msg("%s%s", unctrl(strp->h_ch), strp->h_desc);
+		break;
+	    }
+	    strp++;
+	}
+	if (strp->h_ch != helpch)
+	    msg("Unknown character '%s'", unctrl(helpch));
+	return;
+    }
+    /*
+     * Here we print help for everything.
+     * Then wait before we return to command mode
+     */
+    wclear(hw);
+    cnt = 0;
+    while (strp->h_ch)
+    {
+	mvwaddstr(hw, cnt % 23, cnt > 22 ? 40 : 0, unctrl(strp->h_ch));
+	waddstr(hw, strp->h_desc);
+	cnt++;
+	strp++;
+    }
+    wmove(hw, LINES-1, 0);
+    wprintw(hw, "--Press space to continue--");
+    draw(hw);
+    wait_for(hw,' ');
+    wclear(hw);
+    draw(hw);
+    wmove(cw, 0, 0);
+    wclrtoeol(cw);
+    status();
+    touchwin(cw);
+}
+
+/*
+ * identify:
+ *	Tell the player what a certain thing is.
+ */
+
+void
+identify()
+{
+    int ch;
+    char *str;
+
+    msg("What do you want identified? ");
+    ch = readchar(cw);
+    mpos = 0;
+    if (ch == ESCAPE)
+    {
+	msg("");
+	return;
+    }
+    if (isalpha(ch) && 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 = "passage leading down";
+	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", unctrl(ch), str);
+}
+
+/*
+ * d_level:
+ *	He wants to go down a level
+ */
+
+void
+d_level()
+{
+    if (winat(hero.y, hero.x) != STAIRS)
+	msg("I see no way down.");
+    else
+    {
+	level++;
+	new_level();
+    }
+}
+
+/*
+ * u_level:
+ *	He wants to go up a level
+ */
+
+void
+u_level()
+{
+    if (winat(hero.y, hero.x) == STAIRS)
+    {
+	if (amulet)
+	{
+	    level--;
+	    if (level == 0)
+		total_winner();
+	    new_level();
+	    msg("You feel a wrenching sensation in your gut.");
+	    return;
+	}
+    }
+    msg("I see no way up.");
+}
+
+/*
+ * Let him escape for a while
+ */
+
+void
+shell()
+{
+    /*
+     * Set the terminal back to original mode
+     */
+    wclear(hw);
+    wmove(hw, LINES-1, 0);
+    draw(hw);
+    endwin();
+    in_shell = TRUE;
+    fflush(stdout);
+
+    md_shellescape();
+
+    printf("\n[Press return to continue]");
+    fflush(stdout);
+    noecho();
+    crmode();
+    in_shell = FALSE;
+    wait_for(cw,'\n');
+    clearok(cw, TRUE);
+    touchwin(cw);
+    draw(cw);
+}
+
+/*
+ * allow a user to call a potion, scroll, or ring something
+ */
+void
+call()
+{
+    struct object *obj;
+    struct linked_list *item;
+    char **guess, *elsewise;
+    int *know;
+
+    item = get_item("call", CALLABLE);
+    /*
+     * Make certain that it is somethings that we want to wear
+     */
+    if (item == NULL)
+	return;
+    obj = (struct object *) ldata(item);
+    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("C");
+    else
+	addmsg("Was c");
+    msg("alled \"%s\"", elsewise);
+    if (terse)
+	msg("Call it: ");
+    else
+	msg("What do you want to call it? ");
+    strcpy(prbuf, elsewise);
+    if (get_str(prbuf, cw) == NORM)
+    {
+        if (guess[obj->o_which] != NULL)
+	    free(guess[obj->o_which]);
+	guess[obj->o_which] = malloc((unsigned int) strlen(prbuf) + 1);
+	if (guess[obj->o_which] != NULL)
+	    strcpy(guess[obj->o_which], prbuf);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rogue3/daemon.c	Tue Oct 13 13:33:34 2009 +0000
@@ -0,0 +1,199 @@
+/*
+ * Contains functions for dealing with things that happen in the
+ * future.
+ *
+ * @(#)daemon.c	3.3 (Berkeley) 6/15/81
+ *
+ * Rogue: Exploring the Dungeons of Doom
+ * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
+ * All rights reserved.
+ *
+ * See the file LICENSE.TXT for full copyright and licensing information.
+ */
+
+#include "curses.h"
+#include "rogue.h"
+
+#define EMPTY 0
+#define DAEMON -1
+#define MAXDAEMONS 20
+
+#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;
+    debug("Ran out of fuse slots");
+    return NULL;
+}
+
+/*
+ * find_slot:
+ *	Find a particular slot in the table
+ */
+
+struct delayed_action *
+find_slot(void (*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.
+ */
+
+void
+start_daemon(void (*func)(), int arg, int type)
+{
+    register struct delayed_action *dev;
+
+    dev = d_slot();
+ 
+    if (dev != NULL) 
+    {
+        dev->d_type = type;
+        dev->d_func = func;
+        dev->d_arg = arg;
+        dev->d_time = DAEMON;
+    }
+}
+
+/*
+ * kill_daemon:
+ *	Remove a daemon from the list
+ */
+
+void
+kill_daemon(void (*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.
+ */
+
+void
+do_daemons(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
+ */
+
+void
+fuse(void (*func)(), int arg, int time, int type)
+{
+    register struct delayed_action *wire;
+
+    wire = d_slot();
+
+    if (wire != NULL)
+    {
+        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
+ */
+
+void
+lengthen(void (*func)(), int xtime)
+{
+    register struct delayed_action *wire;
+
+    if ((wire = find_slot(func)) == NULL)
+	return;
+    wire->d_time += xtime;
+}
+
+/*
+ * extinguish:
+ *	Put out a fuse
+ */
+
+void
+extinguish(void (*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
+ */
+
+void
+do_fuses(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/rogue3/daemons.c	Tue Oct 13 13:33:34 2009 +0000
@@ -0,0 +1,177 @@
+/*
+ * All the daemon and fuse functions are in here
+ *
+ * @(#)daemons.c	3.7 (Berkeley) 6/15/81
+ *
+ * Rogue: Exploring the Dungeons of Doom
+ * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
+ * All rights reserved.
+ *
+ * See the file LICENSE.TXT for full copyright and licensing information.
+ */
+
+#include "curses.h"
+#include "rogue.h"
+
+/*
+ * doctor:
+ *	A healing daemon that restors hit points after rest
+ */
+
+void
+doctor()
+{
+    register int lv, ohp;
+
+    lv = pstats.s_lvl;
+    ohp = pstats.s_hpt;
+    quiet++;
+    if (lv < 8)
+    {
+	if (quiet > 20 - lv*2)
+	    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
+ */
+
+void
+swander()
+{
+    start_daemon(rollwand, 0, BEFORE);
+}
+
+/*
+ * rollwand:
+ *	Called to roll to see if a wandering monster starts up
+ */
+
+int between = 0;
+
+void
+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
+ */
+
+void
+unconfuse()
+{
+    player.t_flags &= ~ISHUH;
+    msg("You feel less confused now");
+}
+
+
+/*
+ * unsee:
+ *	He lost his see invisible power
+ */
+
+void
+unsee()
+{
+    player.t_flags &= ~CANSEE;
+}
+
+/*
+ * sight:
+ *	He gets his sight back
+ */
+
+void
+sight()
+{
+    if (on(player, ISBLIND))
+    {
+	extinguish(sight);
+	player.t_flags &= ~ISBLIND;
+	light(&hero);
+	msg("The veil of darkness lifts");
+    }
+}
+
+/*
+ * nohaste:
+ *	End the hasting
+ */
+
+void
+nohaste()
+{
+    player.t_flags &= ~ISHASTE;
+    msg("You feel yourself slowing down.");
+}
+
+/*
+ * digest the hero's food
+ */
+void
+stomach()
+{
+    register int oldfood;
+
+    if (food_left <= 0)
+    {
+	/*
+	 * the hero is fainting
+	 */
+	if (no_command || rnd(100) > 20)
+	    return;
+	no_command = rnd(8)+4;
+	if (!terse)
+	    addmsg("You feel too weak from lack of food.  ");
+	msg("You faint");
+	running = FALSE;
+	count = 0;
+	hungry_state = 3;
+    }
+    else
+    {
+	oldfood = food_left;
+	food_left -= ring_eat(LEFT) + ring_eat(RIGHT) + 1 - amulet;
+
+	if (food_left < MORETIME && oldfood >= MORETIME)
+	{
+	    msg("You are starting to feel weak");
+	    hungry_state = 2;
+	}
+	else if (food_left < 2 * MORETIME && oldfood >= 2 * MORETIME)
+	{
+	    if (!terse)
+		msg("You are starting to get hungry");
+	    else
+		msg("Getting hungry");
+	    hungry_state = 1;
+	}
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rogue3/fight.c	Tue Oct 13 13:33:34 2009 +0000
@@ -0,0 +1,737 @@
+/*
+ * All the fighting gets done here
+ *
+ * @(#)fight.c	3.28 (Berkeley) 6/15/81
+ *
+ * Rogue: Exploring the Dungeons of Doom
+ * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
+ * All rights reserved.
+ *
+ * See the file LICENSE.TXT for full copyright and licensing information.
+ */
+
+#include "curses.h"
+#include <ctype.h>
+#include <string.h>
+#include <stdlib.h>
+#include "rogue.h"
+
+int e_levels[] = {
+    10,20,40,80,160,320,640,1280,2560,5120,10240,20480,
+    40920, 81920, 163840, 327680, 655360, 1310720, 2621440, 0 };
+
+/*
+ * fight:
+ *	The player attacks the monster.
+ */
+
+int
+fight(coord *mp, int mn, struct object *weap, int thrown)
+{
+    struct thing *tp;
+    struct linked_list *item;
+    int did_hit = TRUE;
+
+    /*
+     * Find the monster we want to fight
+     */
+    if ((item = find_mons(mp->y, mp->x)) == NULL)
+    {
+	debug("Fight what @ %d,%d", mp->y, mp->x);
+	return(0);
+    }
+    tp = (struct thing *) ldata(item);
+    /*
+     * Since we are fighting, things are not quiet so no healing takes
+     * place.
+     */
+    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' && off(player, ISBLIND))
+    {
+	msg("Wait! That's a mimic!");
+	tp->t_disguise = 'M';
+	did_hit = thrown;
+    }
+    if (did_hit)
+    {
+	char *mname;
+
+	did_hit = FALSE;
+	if (on(player, ISBLIND))
+	    mname = "it";
+	else
+	    mname = monsters[mn-'A'].m_name;
+	if (roll_em(&pstats, &tp->t_stats, weap, thrown))
+	{
+	    did_hit = TRUE;
+	    if (thrown)
+		thunk(weap, mname);
+	    else
+		hit(NULL, mname);
+	    if (on(player, CANHUH))
+	    {
+		msg("Your hands stop glowing red");
+		msg("The %s appears confused.", mname);
+		tp->t_flags |= ISHUH;
+		player.t_flags &= ~CANHUH;
+	    }
+	    if (tp->t_stats.s_hpt <= 0)
+		killed(item, TRUE);
+	}
+	else
+	    if (thrown)
+		bounce(weap, mname);
+	    else
+		miss(NULL, mname);
+    }
+    count = 0;
+    return did_hit;
+}
+
+/*
+ * attack:
+ *	The monster attacks the player
+ */
+
+int
+attack(struct thing *mp)
+{
+    char *mname;
+
+    /*
+     * Since this is an attack, stop running and any healing that was
+     * going on at the time.
+     */
+    running = FALSE;
+    quiet = 0;
+    if (mp->t_type == 'M' && off(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->t_stats, &pstats, NULL, FALSE))
+    {
+	if (mp->t_type != 'E')
+	    hit(mname, NULL);
+	if (pstats.s_hpt <= 0)
+	    death(mp->t_type);	/* Bye bye life ... */
+	if (off(*mp, ISCANC))
+	    switch (mp->t_type)
+	    {
+		case 'R':
+		    /*
+		     * If a rust monster hits, you lose armor
+		     */
+		    if (cur_armor != NULL && cur_armor->o_ac < 9)
+		    {
+			if (!terse)
+			    msg("Your armor appears to be weaker now. Oh my!");
+			else
+			    msg("Your armor weakens");
+			cur_armor->o_ac++;
+		    }
+		when 'E':
+		    /*
+		     * The gaze of the floating eye hypnotizes you
+		     */
+		    if (on(player, ISBLIND))
+			break;
+		    if (!no_command)
+		    {
+			addmsg("You are transfixed");
+			if (!terse)
+			    addmsg(" by the gaze of the floating eye.");
+			endmsg();
+		    }
+		    no_command += rnd(2)+2;
+		    if (no_command > 100 && food_left <= 0)
+		    	death('E');
+		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':
+		    /*
+		     * Wraiths might drain energy levels
+		     */
+		    if (rnd(100) < 15)
+		    {
+			int fewer;
+
+			if (pstats.s_exp == 0)
+			    death('W');		/* All levels gone */
+			msg("You suddenly feel weaker.");
+			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);
+			pstats.s_hpt -= fewer;
+			max_hp -= fewer;
+			if (pstats.s_hpt < 1)
+			    pstats.s_hpt = 1;
+			if (max_hp < 1)
+			    death('W');
+		    }
+		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
+		     */
+		    int lastpurse;
+
+		    lastpurse = purse;
+		    purse -= GOLDCALC;
+		    if (!save(VS_MAGIC))
+			purse -= GOLDCALC + GOLDCALC + GOLDCALC + GOLDCALC;
+		    if (purse < 0)
+			purse = 0;
+		    if (purse != lastpurse)
+			msg("Your purse feels lighter");
+		    remove_monster(&mp->t_pos, find_mons(mp->t_pos.y, mp->t_pos.x));
+		    mp = NULL;
+		}
+		when 'N':
+		{
+		    struct linked_list *list, *steal;
+		    struct object *obj;
+		    int nobj;
+
+		    /*
+		     * Nymph's steal a magic item, look through the pack
+		     * and pick out one we like.
+		     */
+		    steal = NULL;
+		    for (nobj = 0, list = pack; list != NULL; list = next(list))
+		    {
+			obj = (struct object *) ldata(list);
+			if (obj != cur_armor && 
+                            obj != cur_weapon &&
+                            obj != cur_ring[LEFT] &&
+                            obj != cur_ring[RIGHT] && /* Nymph bug fix */
+			    is_magic(obj) && 
+                            rnd(++nobj) == 0)
+				steal = list;
+		    }
+		    if (steal != NULL)
+		    {
+			struct object *sobj;
+
+			sobj = (struct object *) ldata(steal);
+			remove_monster(&mp->t_pos, find_mons(mp->t_pos.y, mp->t_pos.x));
+			mp = NULL;
+			if (sobj->o_count > 1 && sobj->o_group == 0)
+			{
+			    int oc;
+
+			    oc = sobj->o_count;
+			    sobj->o_count = 1;
+			    msg("She stole %s!", inv_name(sobj, TRUE));
+			    sobj->o_count = oc - 1;
+			}
+			else
+			{
+			    msg("She stole %s!", inv_name(sobj, TRUE));
+			    detach(pack, steal);
+			    discard(steal);
+			}
+			inpack--;
+		    }
+		}
+		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);
+    }
+    /*
+     * Check to see if this is a regenerating monster and let it heal if
+     * it is.
+     */
+    if ((mp != NULL) && (on(*mp, ISREGEN) && rnd(100) < 33))
+	mp->t_stats.s_hpt++;
+    if (fight_flush)
+    {
+	flush_type();	/* flush typeahead */
+    }
+    count = 0;
+    status();
+
+    if (mp == NULL)
+        return(-1);
+    else
+        return(0);
+}
+
+/*
+ * swing:
+ *	returns true if the swing hits
+ */
+
+int
+swing(int at_lvl, int op_arm, int wplus)
+{
+    int res = rnd(20)+1;
+    int need = (21-at_lvl)-op_arm;
+
+    return (res+wplus >= need);
+}
+
+/*
+ * check_level:
+ *	Check to see if the guy has gone up a level.
+ */
+
+void
+check_level()
+{
+    int i, add;
+
+    for (i = 0; e_levels[i] != 0; i++)
+	if (e_levels[i] > pstats.s_exp)
+	    break;
+    i++;
+    if (i > pstats.s_lvl)
+    {
+	add = roll(i-pstats.s_lvl,10);
+	max_hp += add;
+	if ((pstats.s_hpt += add) > max_hp)
+	    pstats.s_hpt = max_hp;
+	msg("Welcome to level %d", i);
+    }
+    pstats.s_lvl = i;
+}
+
+/*
+ * roll_em:
+ *	Roll several attacks
+ */
+
+int
+roll_em(struct stats *att, struct stats *def, struct object *weap, int hurl)
+{
+    char *cp;
+    int ndice, nsides, def_arm;
+    int did_hit = FALSE;
+    int prop_hplus, prop_dplus;
+
+    prop_hplus = prop_dplus = 0;
+    if (weap == NULL)
+	cp = att->s_dmg;
+    else if (hurl)
+	if ((weap->o_flags&ISMISL) && cur_weapon != NULL &&
+	  cur_weapon->o_which == weap->o_launch)
+	{
+	    cp = weap->o_hurldmg;
+	    prop_hplus = cur_weapon->o_hplus;
+	    prop_dplus = cur_weapon->o_dplus;
+	}
+	else
+	    cp = (weap->o_flags&ISMISL ? weap->o_damage : weap->o_hurldmg);
+    else
+    {
+	cp = weap->o_damage;
+	/*
+	 * Drain a staff of striking
+	 */
+	if (weap->o_type == STICK && weap->o_which == WS_HIT
+	    && weap->o_charges == 0)
+		{
+		    strcpy(weap->o_damage,"0d0");
+		    weap->o_hplus = weap->o_dplus = 0;
+		}
+    }
+    for (;;)
+    {
+	int damage;
+	int hplus = prop_hplus + (weap == NULL ? 0 : weap->o_hplus);
+	int dplus = prop_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;
+	}
+	ndice = atoi(cp);
+	if ((cp = strchr(cp, 'd')) == NULL)
+	    break;
+	nsides = atoi(++cp);
+	if (def == &pstats)
+	{
+	    if (cur_armor != NULL)
+		def_arm = cur_armor->o_ac;
+	    else
+		def_arm = def->s_arm;
+	    if (ISRING(LEFT, R_PROTECT))
+		def_arm -= cur_ring[LEFT]->o_ac;
+	    else if (ISRING(RIGHT, R_PROTECT))
+		def_arm -= cur_ring[RIGHT]->o_ac;
+	}
+	else
+	    def_arm = def->s_arm;
+	if (swing(att->s_lvl, def_arm, hplus+str_plus(&att->s_str)))
+	{
+	    int proll;
+
+	    proll = roll(ndice, nsides);
+	    if (ndice + nsides > 0 && proll < 1)
+		debug("Damage for %dd%d came out %d.", ndice, nsides, proll);
+	    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)
+char *who;
+int upper;
+{
+    static char tbuf[80];
+
+    *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
+ */
+
+void
+hit(char *er, char *ee)
+{
+    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
+ */
+
+void
+miss(char *er, char *ee)
+{
+    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
+ */
+int
+save_throw(int which, struct thing *tp)
+{
+    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
+ */
+
+int
+save(int which)
+{
+    return save_throw(which, &player);
+}
+
+/*
+ * str_plus:
+ *	compute bonus/penalties for strength on the "to hit" roll
+ */
+
+int
+str_plus(str_t *str)
+{
+    if (str->st_str == 18)
+    {
+	if (str->st_add == 100)
+	    return 3;
+	if (str->st_add > 50)
+	    return 2;
+    }
+    if (str->st_str >= 17)
+	return 1;
+    if (str->st_str > 6)
+	return 0;
+    return str->st_str - 7;
+}
+
+/*
+ * add_dam:
+ *	compute additional damage done for exceptionally high or low strength
+ */
+
+ int
+ add_dam(str_t *str)
+ {
+    if (str->st_str == 18)
+    {
+	if (str->st_add == 100)
+	    return 6;
+	if (str->st_add > 90)
+	    return 5;
+	if (str->st_add > 75)
+	    return 4;
+	if (str->st_add != 0)
+	    return 3;
+	return 2;
+    }
+    if (str->st_str > 15)
+	return 1;
+    if (str->st_str > 6)
+	return 0;
+    return str->st_str - 7;
+}
+
+/*
+ * raise_level:
+ *	The guy just magically went up a level.
+ */
+
+void
+raise_level()
+{
+    pstats.s_exp = e_levels[pstats.s_lvl-1] + 1L;
+    check_level();
+}
+
+/*
+ * thunk:
+ *	A missile hits a monster
+ */
+
+void
+thunk(struct object *weap, char *mname)
+{
+    if (weap->o_type == WEAPON)
+	msg("The %s hits the %s", w_names[weap->o_which], mname);
+    else
+	msg("You hit the %s.", mname);
+}
+
+/*
+ * bounce:
+ *	A missile misses a monster
+ */
+
+void
+bounce(struct object *weap, char *mname)
+{
+    if (weap->o_type == WEAPON)
+	msg("The %s misses the %s", w_names[weap->o_which], mname);
+    else
+	msg("You missed the %s.", mname);
+}
+
+/*
+ * remove a monster from the screen
+ */
+void
+remove_monster(coord *mp, struct linked_list *item)
+{
+    mvwaddch(mw, mp->y, mp->x, ' ');
+    mvwaddch(cw, mp->y, mp->x, ((struct thing *) ldata(item))->t_oldch);
+    detach(mlist, item);
+    discard(item);
+}
+
+/*
+ * is_magic:
+ *	Returns true if an object radiates magic
+ */
+
+int
+is_magic(struct object *obj)
+{
+    switch (obj->o_type)
+    {
+	case ARMOR:
+	    return obj->o_ac != a_class[obj->o_which];
+	when WEAPON:
+	    return obj->o_hplus != 0 || obj->o_dplus != 0;
+	when POTION:
+	case SCROLL:
+	case STICK:
+	case RING:
+	case AMULET:
+	    return TRUE;
+    }
+    return FALSE;
+}
+
+/*
+ * killed:
+ *	Called to put a monster to death
+ */
+
+void
+killed(struct linked_list *item, int pr)
+{
+    struct thing *tp;
+    struct linked_list *pitem, *nexti;
+
+    tp = (struct thing *) ldata(item);
+    if (pr)
+    {
+	addmsg(terse ? "Defeated " : "You have defeated ");
+	if (on(player, ISBLIND))
+	    msg("it.");
+	else
+	{
+	    if (!terse)
+		addmsg("the ");
+	    msg("%s.", monsters[tp->t_type-'A'].m_name);
+	}
+    }
+    pstats.s_exp += tp->t_stats.s_exp;
+    /*
+     * Do adjustments if he went up a level
+     */
+    check_level();
+    /*
+     * 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':
+	{
+	    struct room *rp;
+
+	    if ((rp = roomin(&tp->t_pos)) == NULL)
+		break;
+	    if (rp->r_goldval != 0 || fallpos(&tp->t_pos,&rp->r_gold,FALSE))
+	    {
+		rp->r_goldval += GOLDCALC;
+		if (save(VS_MAGIC))
+		    rp->r_goldval += GOLDCALC + GOLDCALC
+				   + GOLDCALC + GOLDCALC;
+		mvwaddch(stdscr, rp->r_gold.y, rp->r_gold.x, GOLD);
+		if (!(rp->r_flags & ISDARK))
+		{
+		    light(&hero);
+		    mvwaddch(cw, hero.y, hero.x, PLAYER);
+		}
+	    }
+	}
+    }
+    /*
+     * Empty the monsters pack
+     */
+    pitem = tp->t_pack;
+    while (pitem != NULL)
+    {
+	struct object *obj;
+
+	nexti = next(tp->t_pack);
+	obj = (struct object *) ldata(pitem);
+	obj->o_pos = tp->t_pos;
+	detach(tp->t_pack, pitem);
+	fall(pitem, FALSE);
+	pitem = nexti;
+    }
+    /*
+     * Get rid of the monster.
+     */
+    remove_monster(&tp->t_pos, item);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rogue3/init.c	Tue Oct 13 13:33:34 2009 +0000
@@ -0,0 +1,596 @@
+/*
+ * global variable initializaton
+ *
+ * @(#)init.c	3.33 (Berkeley) 6/15/81
+ *
+ * Rogue: Exploring the Dungeons of Doom
+ * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
+ * All rights reserved.
+ *
+ * See the file LICENSE.TXT for full copyright and licensing information.
+ */
+
+#include "curses.h"
+#include <ctype.h>
+#include <string.h>
+#include <stdlib.h>
+#include "machdep.h"
+#include "rogue.h"
+
+int playing = TRUE, running = FALSE, wizard = FALSE;
+int notify = TRUE, fight_flush = FALSE, terse = FALSE, door_stop = FALSE;
+int jump = FALSE, slow_invent = FALSE, firstmove = FALSE, askme = FALSE;
+int amulet = FALSE;
+int in_shell = FALSE;
+struct linked_list *lvl_obj = NULL, *mlist = NULL;
+struct object *cur_weapon = NULL;
+int mpos = 0, no_move = 0, no_command = 0, level = 1, purse = 0, inpack = 0;
+int total = 0, no_food = 0, count = 0, fung_hit = 0, quiet = 0;
+int food_left = HUNGERTIME, group = 1, hungry_state = 0;
+int lastscore = -1;
+
+struct thing player;
+struct room rooms[MAXROOMS];
+struct room *oldrp;
+struct stats max_stats; 
+struct object *cur_armor;
+struct object *cur_ring[2];
+int after;
+int waswizard;
+coord oldpos;                            /* Position before last look() call */
+coord delta;                             /* Change indicated to get_dir()    */
+
+int s_know[MAXSCROLLS];         /* Does he know what a scroll does */
+int p_know[MAXPOTIONS];         /* Does he know what a potion does */
+int r_know[MAXRINGS];                   /* Does he know what a ring does
+ */
+int ws_know[MAXSTICKS];         /* Does he know what a stick does */
+
+int  take;                               /* Thing the rogue is taking */
+int  runch;                              /* Direction player is running */
+char whoami[80];                 /* Name of player */
+char fruit[80];                          /* Favorite fruit */
+char huh[80];                            /* The last message printed */
+int dnum;                                /* Dungeon number */
+char *s_names[MAXSCROLLS];               /* Names of the scrolls */
+char *p_colors[MAXPOTIONS];              /* Colors of the potions */
+char *r_stones[MAXRINGS];                /* Stone settings of the rings */
+char *a_names[MAXARMORS];                /* Names of armor types */
+char *ws_made[MAXSTICKS];                /* What sticks are made of */
+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[80];                      /* Save file name */
+char home[PATH_MAX];                     /* User's home directory */
+unsigned char prbuf[80];                 /* Buffer for sprintfs */
+int max_hp;                              /* Player's max hit points */
+int ntraps;                              /* Number of traps on this level */
+int max_level;                           /* Deepest player has gone */
+int seed;                                /* Random number seed */
+
+struct trap  traps[MAXTRAPS];
+
+
+#define ___ 1
+#define _x {1,1}
+struct monster monsters[26] = {
+	/* Name		 CARRY	FLAG    str, exp, lvl, amr, hpt, dmg */
+	{ "giant ant",	 0,	ISMEAN,	{ _x, 10,   2,   3, ___, "1d6" } },
+	{ "bat",	 0,	0,	{ _x,  1,   1,   3, ___, "1d2" } },
+	{ "centaur",	 15,	0,	{ _x, 15,   4,   4, ___, "1d6/1d6" } },
+	{ "dragon",	 100,	ISGREED,{ _x,9000, 10,  -1, ___, "1d8/1d8/3d10" } },
+	{ "floating eye",0,	0,	{ _x,  5,   1,   9, ___, "0d0" } },
+	{ "violet fungi",0,	ISMEAN,	{ _x, 85,   8,   3, ___, "000d0" } },
+	{ "gnome",	 10,	0,	{ _x,  8,   1,   5, ___, "1d6" } },
+	{ "hobgoblin",	 0,	ISMEAN,	{ _x,  3,   1,   5, ___, "1d8" } },
+	{ "invisible stalker",0,ISINVIS,{ _x,120,   8,   3, ___, "4d4" } },
+	{ "jackal",	 0,	ISMEAN,	{ _x,  2,   1,   7, ___, "1d2" } },
+	{ "kobold",	 0,	ISMEAN,	{ _x,  1,   1,   7, ___, "1d4" } },
+	{ "leprechaun",	 0,	0,	{ _x, 10,   3,   8, ___, "1d1" } },
+	{ "mimic",	 30,	0,	{ _x,140,   7,   7, ___, "3d4" } },
+	{ "nymph",	 100,	0,	{ _x, 40,   3,   9, ___, "0d0" } },
+	{ "orc",	 15,	ISBLOCK,{ _x,  5,   1,   6, ___, "1d8" } },
+	{ "purple worm", 70,	0,	{ _x,7000, 15,   6, ___, "2d12/2d4" } },
+	{ "quasit",	 30,	ISMEAN,	{ _x, 35,   3,   2, ___, "1d2/1d2/1d4" } },
+	{ "rust monster",0,	ISMEAN,	{ _x, 25,   5,   2, ___, "0d0/0d0" } },
+	{ "snake",	 0,	ISMEAN,	{ _x,  3,   1,   5, ___, "1d3" } },
+	{ "troll",	 50,	ISREGEN|ISMEAN,{ _x, 55,   6,   4, ___, "1d8/1d8/2d6" } },
+	{ "umber hulk",	 40,	ISMEAN,	{ _x,130,   8,   2, ___, "3d4/3d4/2d5" } },
+	{ "vampire",	 20,	ISREGEN|ISMEAN,{ _x,380,   8,   1, ___, "1d10" } },
+	{ "wraith",	 0,	0,	{ _x, 55,   5,   4, ___, "1d6" } },
+	{ "xorn",	 0,	ISMEAN,	{ _x,120,   7,  -2, ___, "1d3/1d3/1d3/4d6" } },
+	{ "yeti",	 30,	0,	{ _x, 50,   4,   6, ___, "1d6/1d6" } },
+	{ "zombie",	 0,	ISMEAN,	{ _x,  7,   2,   8, ___, "1d8" } }
+};
+#undef ___
+
+/*
+ * init_player:
+ *	roll up the rogue
+ */
+
+void
+init_player()
+{
+    pstats.s_lvl = 1;
+    pstats.s_exp = 0L;
+    max_hp = pstats.s_hpt = 12;
+    if (rnd(100) == 7)
+    {
+	pstats.s_str.st_str = 18;
+	pstats.s_str.st_add = rnd(100) + 1;
+    }
+    else
+    {
+	pstats.s_str.st_str = 16;
+	pstats.s_str.st_add = 0;
+    }
+    strcpy(pstats.s_dmg,"1d4");
+    pstats.s_arm = 10;
+    max_stats = pstats;
+    pack = NULL;
+}
+
+/*
+ * Contains defintions and functions for dealing with things like
+ * potions and scrolls
+ */
+
+char *rainbow[] = {
+    "red",
+    "blue",
+    "green",
+    "yellow",
+    "black",
+    "brown",
+    "orange",
+    "pink",
+    "purple",
+    "grey",
+    "white",
+    "silver",
+    "gold",
+    "violet",
+    "clear",
+    "vermilion",
+    "ecru",
+    "turquoise",
+    "magenta",
+    "amber",
+    "topaz",
+    "plaid",
+    "tan",
+    "tangerine"
+};
+
+#define NCOLORS (sizeof rainbow / sizeof (char *))
+int cNCOLORS = NCOLORS;
+
+char *sylls[] = {
+    "a", "ab", "ag", "aks", "ala", "an", "ankh", "app", "arg", "arze",
+    "ash", "ban", "bar", "bat", "bek", "bie", "bin", "bit", "bjor",
+    "blu", "bot", "bu", "byt", "comp", "con", "cos", "cre", "dalf",
+    "dan", "den", "do", "e", "eep", "el", "eng", "er", "ere", "erk",
+    "esh", "evs", "fa", "fid", "for", "fri", "fu", "gan", "gar",
+    "glen", "gop", "gre", "ha", "he", "hyd", "i", "ing", "ion", "ip",
+    "ish", "it", "ite", "iv", "jo", "kho", "kli", "klis", "la", "lech",
+    "man", "mar", "me", "mi", "mic", "mik", "mon", "mung", "mur",
+    "nej", "nelg", "nep", "ner", "nes", "nes", "nih", "nin", "o", "od",
+    "ood", "org", "orn", "ox", "oxy", "pay", "pet", "ple", "plu", "po",
+    "pot", "prok", "re", "rea", "rhov", "ri", "ro", "rog", "rok", "rol",
+    "sa", "san", "sat", "see", "sef", "seh", "shu", "ski", "sna",
+    "sne", "snik", "sno", "so", "sol", "sri", "sta", "sun", "ta",
+    "tab", "tem", "ther", "ti", "tox", "trol", "tue", "turs", "u",
+    "ulk", "um", "un", "uni", "ur", "val", "viv", "vly", "vom", "wah",
+    "wed", "werg", "wex", "whon", "wun", "xo", "y", "yot", "yu",
+    "zant", "zap", "zeb", "zim", "zok", "zon", "zum",
+};
+
+char *stones[] = {
+    "agate",
+    "alexandrite",
+    "amethyst",
+    "carnelian",
+    "diamond",
+    "emerald",
+    "granite",
+    "jade",
+    "kryptonite",
+    "lapus lazuli",
+    "moonstone",
+    "obsidian",
+    "onyx",
+    "opal",
+    "pearl",
+    "ruby",
+    "saphire",
+    "tiger eye",
+    "topaz",
+    "turquoise",
+};
+
+#define NSTONES (sizeof stones / sizeof (char *))
+int cNSTONES = NSTONES;
+
+char *wood[] = {
+    "avocado wood",
+    "balsa",
+    "banyan",
+    "birch",
+    "cedar",
+    "cherry",
+    "cinnibar",
+    "driftwood",
+    "ebony",
+    "eucalyptus",
+    "hemlock",
+    "ironwood",
+    "mahogany",
+    "manzanita",
+    "maple",
+    "oak",
+    "persimmon wood",
+    "redwood",
+    "rosewood",
+    "teak",
+    "walnut",
+    "zebra wood",
+};
+
+#define NWOOD (sizeof wood / sizeof (char *))
+int cNWOOD = NWOOD;
+
+char *metal[] = {
+    "aluminium",
+    "bone",
+    "brass",
+    "bronze",
+    "copper",
+    "iron",
+    "lead",
+    "pewter",
+    "steel",
+    "tin",
+    "zinc",
+};
+
+#define NMETAL (sizeof metal / sizeof (char *))
+int cNMETAL = NMETAL;
+
+struct magic_item things[NUMTHINGS] = {
+    { "",			27 },	/* potion */
+    { "",			27 },	/* scroll */
+    { "",			18 },	/* food */
+    { "",			 9 },	/* weapon */
+    { "",			 9 },	/* armor */
+    { "",			 5 },	/* ring */
+    { "",			 5 },	/* stick */
+};
+
+struct magic_item s_magic[MAXSCROLLS] = {
+    { "monster confusion",	 8, 170 },
+    { "magic mapping",		 5, 180 },
+    { "light",			10, 100 },
+    { "hold monster",		 2, 200 },
+    { "sleep",			 5,  50 },
+    { "enchant armor",		 8, 130 },
+    { "identify",		21, 100 },
+    { "scare monster",		 4, 180 },
+    { "gold detection",		 4, 110 },
+    { "teleportation",		 7, 175 },
+    { "enchant weapon",		10, 150 },
+    { "create monster",		 5,  75 },
+    { "remove curse",		 8, 105 },
+    { "aggravate monsters",	 1,  60 },
+    { "blank paper",		 1,  50 },
+    { "genocide",		 1, 200 },
+};
+
+struct magic_item p_magic[MAXPOTIONS] = {
+    { "confusion",		 8,  50 },
+    { "paralysis",		10,  50 },
+    { "poison",			 8,  50 },
+    { "gain strength",		15, 150 },
+    { "see invisible",		 2, 170 },
+    { "healing",		15, 130 },
+    { "monster detection",	 6, 120 },
+    { "magic detection",	 6, 105 },
+    { "raise level",		 2, 220 },
+    { "extra healing",		 5, 180 },
+    { "haste self",		 4, 200 },
+    { "restore strength",	14, 120 },
+    { "blindness",		 4,  50 },
+    { "thirst quenching",	 1,  50 },
+};
+
+struct magic_item r_magic[MAXRINGS] = {
+    { "protection",		 9, 200 },
+    { "add strength",		 9, 200 },
+    { "sustain strength",	 5, 180 },
+    { "searching",		10, 200 },
+    { "see invisible",		10, 175 },
+    { "adornment",		 1, 100 },
+    { "aggravate monster",	11, 100 },
+    { "dexterity",		 8, 220 },
+    { "increase damage",	 8, 220 },
+    { "regeneration",		 4, 260 },
+    { "slow digestion",		 9, 240 },
+    { "teleportation",		 9, 100 },
+    { "stealth",		 7, 100 },
+};
+
+struct magic_item ws_magic[MAXSTICKS] = {
+    { "light",			12, 120 },
+    { "striking",		 9, 115 },
+    { "lightning",		 3, 200 },
+    { "fire",			 3, 200 },
+    { "cold",			 3, 200 },
+    { "polymorph",		15, 210 },
+    { "magic missile",		10, 170 },
+    { "haste monster",		 9,  50 },
+    { "slow monster",		11, 220 },
+    { "drain life",		 9, 210 },
+    { "nothing",		 1,  70 },
+    { "teleport away",		 5, 140 },
+    { "teleport to",		 5,  60 },
+    { "cancellation",		 5, 130 },
+};
+
+int a_class[MAXARMORS] = {
+    8,
+    7,
+    7,
+    6,
+    5,
+    4,
+    4,
+    3,
+};
+
+char *a_names[MAXARMORS] = {
+    "leather armor",
+    "ring mail",
+    "studded leather armor",
+    "scale mail",
+    "chain mail",
+    "splint mail",
+    "banded mail",
+    "plate mail",
+};
+
+int a_chances[MAXARMORS] = {
+    20,
+    35,
+    50,
+    63,
+    75,
+    85,
+    95,
+    100
+};
+
+#define MAX3(a,b,c)     (a > b ? (a > c ? a : c) : (b > c ? b : c))
+static int used[MAX3(NCOLORS, NSTONES, NWOOD)];
+
+/*
+ * init_things
+ *	Initialize the probabilities for types of things
+ */
+void
+init_things()
+{
+    struct magic_item *mp;
+
+    for (mp = &things[1]; mp <= &things[NUMTHINGS-1]; mp++)
+	mp->mi_prob += (mp-1)->mi_prob;
+    badcheck("things", things, NUMTHINGS);
+}
+
+/*
+ * init_colors:
+ *	Initialize the potion color scheme for this time
+ */
+
+void
+init_colors()
+{
+    int i, j;
+
+    for (i = 0; i < NCOLORS; i++)
+	used[i] = 0;
+    for (i = 0; i < MAXPOTIONS; i++)
+    {
+	do
+	    j = rnd(NCOLORS);
+	until (!used[j]);
+	used[j] = TRUE;
+	p_colors[i] = rainbow[j];
+	p_know[i] = FALSE;
+	p_guess[i] = NULL;
+	if (i > 0)
+		p_magic[i].mi_prob += p_magic[i-1].mi_prob;
+    }
+    badcheck("potions", p_magic, MAXPOTIONS);
+}
+
+/*
+ * init_names:
+ *	Generate the names of the various scrolls
+ */
+
+void
+init_names()
+{
+    int nsyl;
+    char *cp, *sp;
+    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 *)))];
+		while(*sp)
+		    *cp++ = *sp++;
+	    }
+	    *cp++ = ' ';
+	}
+	*--cp = '\0';
+	s_names[i] = (char *) _new(strlen(prbuf)+1);
+	s_know[i] = FALSE;
+	s_guess[i] = NULL;
+	strcpy(s_names[i], prbuf);
+	if (i > 0)
+		s_magic[i].mi_prob += s_magic[i-1].mi_prob;
+    }
+    badcheck("scrolls", s_magic, MAXSCROLLS);
+}
+
+/*
+ * init_stones:
+ *	Initialize the ring stone setting scheme for this time
+ */
+
+void
+init_stones()
+{
+    int i, j;
+
+    for (i = 0; i < NSTONES; i++)
+	used[i] = FALSE;
+    for (i = 0; i < MAXRINGS; i++)
+    {
+	do
+	    j = rnd(NSTONES);
+	until (!used[j]);
+	used[j] = TRUE;
+	r_stones[i] = stones[j];
+	r_know[i] = FALSE;
+	r_guess[i] = NULL;
+	if (i > 0)
+		r_magic[i].mi_prob += r_magic[i-1].mi_prob;
+    }
+    badcheck("rings", r_magic, MAXRINGS);
+}
+
+/*
+ * init_materials:
+ *	Initialize the construction materials for wands and staffs
+ */
+
+void
+init_materials()
+{
+    int i, j;
+    static int metused[NMETAL];
+
+    for (i = 0; i < NWOOD; i++)
+	used[i] = FALSE;
+    for (i = 0; i < NMETAL; i++)
+	metused[i] = FALSE;
+
+    for (i = 0; i < MAXSTICKS; i++)
+    {
+	for (;;)
+	    if (rnd(100) > 50)
+	    {
+		j = rnd(NMETAL);
+		if (!metused[j])
+		{
+		    metused[j] = TRUE;
+		    ws_made[i] = metal[j];
+		    ws_type[i] = "wand";
+		    break;
+		}
+	    }
+	    else
+	    {
+		j = rnd(NWOOD);
+		if (!used[j])
+		{
+		    used[j] = TRUE;
+		    ws_made[i] = wood[j];
+		    ws_type[i] = "staff";
+		    break;
+		}
+	    }
+
+	ws_know[i] = FALSE;
+	ws_guess[i] = NULL;
+	if (i > 0)
+		ws_magic[i].mi_prob += ws_magic[i-1].mi_prob;
+    }
+    badcheck("sticks", ws_magic, MAXSTICKS);
+}
+
+void
+badcheck(char *name, struct magic_item *magic, int bound)
+{
+    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;
+}
+
+struct h_list helpstr[] = {
+    '?',	"	prints help",
+    '/',	"	identify object",
+    'h',	"	left",
+    'j',	"	down",
+    'k',	"	up",
+    'l',	"	right",
+    'y',	"	up & left",
+    'u',	"	up & right",
+    'b',	"	down & left",
+    'n',	"	down & right",
+    'H',	"	run left",
+    'J',	"	run down",
+    'K',	"	run up",
+    'L',	"	run right",
+    'Y',	"	run up & left",
+    'U',	"	run up & right",
+    'B',	"	run down & left",
+    'N',	"	run down & right",
+    't',	"<dir>	throw something",
+    'f',	"<dir>	forward until find something",
+    'p',	"<dir>	zap a wand in a direction",
+    'z',	"	zap a wand or staff",
+    '>',	"	go down a staircase",
+    's',	"	search for trap/secret door",
+    ' ',	"	(space) 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",
+    'o',	"	examine/set options",
+    CTRL('L'),	"	redraw screen",
+    CTRL('R'),	"	repeat last message",
+    ESCAPE,	"	cancel command",
+    'v',	"	print program version number",
+    '!',	"	shell escape",
+    'S',	"	save game",
+    'Q',	"	quit",
+    0, 0
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rogue3/io.c	Tue Oct 13 13:33:34 2009 +0000
@@ -0,0 +1,248 @@
+/*
+ * Various input/output functions
+ *
+ * @(#)io.c	3.10 (Berkeley) 6/15/81
+ *
+ * Rogue: Exploring the Dungeons of Doom
+ * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
+ * All rights reserved.
+ *
+ * See the file LICENSE.TXT for full copyright and licensing information.
+ */
+
+#include <stdlib.h>
+#include "curses.h"
+#include <ctype.h>
+#include <stdarg.h>
+#include <string.h>
+#include "machdep.h"
+#include "rogue.h"
+
+/*
+ * msg:
+ *	Display a message at the top of the screen.
+ */
+
+static char msgbuf[BUFSIZ];
+static int newpos = 0;
+
+/*VARARGS1*/
+void
+msg(char *fmt, ...)
+{
+    va_list ap;
+    /*
+     * if the string is "", just clear the line
+     */
+    if (*fmt == '\0')
+    {
+	wmove(cw, 0, 0);
+	wclrtoeol(cw);
+	mpos = 0;
+	return;
+    }
+    /*
+     * otherwise add to the message and flush it out
+     */
+    va_start(ap, fmt);
+    doadd(fmt, ap);
+    va_end(ap);
+    endmsg();
+}
+
+/*
+ * add things to the current message
+ */
+void
+addmsg(char *fmt, ...)
+{
+    va_list ap;
+
+    va_start(ap, fmt);
+    doadd(fmt, ap);
+    va_end(ap);
+}
+
+/*
+ * Display a new msg (giving him a chance to see the previous one if it
+ * is up there with the --More--)
+ */
+void
+endmsg()
+{
+    strncpy(huh, msgbuf, 80);
+    huh[79] = 0;
+
+    if (mpos)
+    {
+	wmove(cw, 0, mpos);
+	waddstr(cw, "--More--");
+	draw(cw);
+	wait_for(cw,' ');
+    }
+    mvwaddstr(cw, 0, 0, msgbuf);
+    wclrtoeol(cw);
+    mpos = newpos;
+    newpos = 0;
+    draw(cw);
+}
+
+void
+doadd(char *fmt, va_list ap)
+{
+    vsprintf(&msgbuf[newpos], fmt, ap);
+    newpos = (int) strlen(msgbuf);
+}
+
+/*
+ * step_ok:
+ *	returns true if it is ok to step on ch
+ */
+
+int
+step_ok(int ch)
+{
+    switch (ch)
+    {
+	case ' ':
+	case '|':
+	case '-':
+	case SECRETDOOR:
+	    return FALSE;
+	default:
+	    return (!isalpha(ch));
+    }
+}
+
+/*
+ * readchar:
+ *	flushes stdout so that screen is up to date and then returns
+ *	getchar.
+ */
+
+int
+readchar(WINDOW *win)
+{
+    int ch;
+
+    ch = md_readchar(win);
+
+    if ((ch == 3) || (ch == 0))
+    {
+	quit(0);
+        return(27);
+    }
+
+    return(ch);
+}
+
+/*
+ * status:
+ *	Display the important stats line.  Keep the cursor where it was.
+ */
+
+void
+status()
+{
+    int oy, ox, temp;
+    char *pb;
+    static char buf[80];
+    static int hpwidth = 0, s_hungry = -1;
+    static int s_lvl = -1, s_pur, s_hp = -1, s_str, s_add, s_ac = 0;
+    static long s_exp = 0;
+
+    /*
+     * 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.st_str && s_add == pstats.s_str.st_add
+	&& s_lvl == level && s_hungry == hungry_state)
+	    return;
+	
+    getyx(cw, oy, ox);
+    if (s_hp != max_hp)
+    {
+	temp = s_hp = max_hp;
+	for (hpwidth = 0; temp; hpwidth++)
+	    temp /= 10;
+    }
+    sprintf(buf, "Level: %d  Gold: %-5d  Hp: %*d(%*d)  Str: %-2d",
+	level, purse, hpwidth, pstats.s_hpt, hpwidth, max_hp,
+	pstats.s_str.st_str);
+    if (pstats.s_str.st_add != 0)
+    {
+	pb = &buf[strlen(buf)];
+	sprintf(pb, "/%d", pstats.s_str.st_add);
+    }
+    pb = &buf[strlen(buf)];
+    sprintf(pb, "  Ac: %-2d  Exp: %d/%d",
+	cur_armor != NULL ? cur_armor->o_ac : pstats.s_arm, pstats.s_lvl,
+	pstats.s_exp);
+    /*
+     * Save old status
+     */
+    s_lvl = level;
+    s_pur = purse;
+    s_hp = pstats.s_hpt;
+    s_str = pstats.s_str.st_str;
+    s_add = pstats.s_str.st_add;
+    s_exp = pstats.s_exp; 
+    s_ac = (cur_armor != NULL ? cur_armor->o_ac : pstats.s_arm);
+    mvwaddstr(cw, LINES - 1, 0, buf);
+    switch (hungry_state)
+    {
+	case 0: ;
+	when 1:
+	    waddstr(cw, "  Hungry");
+	when 2:
+	    waddstr(cw, "  Weak");
+	when 3:
+	    waddstr(cw, "  Fainting");
+    }
+    wclrtoeol(cw);
+    s_hungry = hungry_state;
+    wmove(cw, oy, ox);
+}
+
+/*
+ * wait_for
+ *	Sit around until the guy types the right key
+ */
+
+void
+wait_for(WINDOW *win, int ch)
+{
+    int c;
+
+    if (ch == '\n')
+        while ((c = readchar(win)) != '\n' && c != '\r')
+	    continue;
+    else
+        while (readchar(win) != ch)
+	    continue;
+}
+
+/*
+ * show_win:
+ *	function used to display a window and wait before returning
+ */
+
+void
+show_win(WINDOW *scr, char *message)
+{
+    mvwaddstr(scr, 0, 0, message);
+    touchwin(scr);
+    wmove(scr, hero.y, hero.x);
+    draw(scr);
+    wait_for(scr,' ');
+    clearok(cw, TRUE);
+    touchwin(cw);
+}
+
+void
+flush_type()
+{
+	flushinp();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rogue3/list.c	Tue Oct 13 13:33:34 2009 +0000
@@ -0,0 +1,129 @@
+/*
+ * Functions for dealing with linked lists of goodies
+ *
+ * @(#)list.c	3.3 (Berkeley) 6/15/81
+ *
+ * Rogue: Exploring the Dungeons of Doom
+ * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
+ * All rights reserved.
+ *
+ * See the file LICENSE.TXT for full copyright and licensing information.
+ */
+
+#include "curses.h"
+#include <stdlib.h>
+#include <string.h>
+#include "machdep.h"
+#include "rogue.h"
+
+/*
+ * detach:
+ *	Takes an item out of whatever linked list it might be in
+ */
+
+void
+_detach(struct linked_list **list, struct linked_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
+ */
+
+void
+_attach(struct linked_list **list, struct linked_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
+ */
+
+void
+_free_list(struct linked_list **ptr)
+{
+    struct linked_list *item;
+
+    while (*ptr != NULL)
+    {
+	item = *ptr;
+	*ptr = next(item);
+	discard(item);
+    }
+}
+
+/*
+ * discard:
+ *	free up an item
+ */
+
+void
+discard(struct linked_list *item)
+{
+    total -= 2;
+    FREE(item->l_data);
+    FREE(item);
+}
+
+/*
+ * new_item
+ *	get a new item with a specified size
+ */
+
+struct linked_list *
+new_item(int size)
+{
+    struct linked_list *item;
+
+    if ((item = (struct linked_list *) _new(sizeof *item)) == NULL)
+    {
+	msg("Ran out of memory for header after %d items", total);
+	return NULL;
+    }
+
+    if ((item->l_data = _new(size)) == NULL)
+    {
+	msg("Ran out of memory for data after %d items", total);
+	free(item);
+	return NULL;
+    }
+
+    item->l_next = item->l_prev = NULL;
+    memset(item->l_data,0,size);
+    return item;
+}
+
+char *
+_new(size_t size)
+{
+    char *space = ALLOC(size);
+
+    if (space == NULL)
+    {
+	sprintf(prbuf, "Rogue ran out of memory (%d).  Fatal error!", md_memused());
+        fatal(prbuf);
+    }
+    total++;
+    return space;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rogue3/machdep.h	Tue Oct 13 13:33:34 2009 +0000
@@ -0,0 +1,21 @@
+/*
+ * machine dependicies
+ *
+ * %G% (Berkeley) %W%
+ *
+ * Rogue: Exploring the Dungeons of Doom
+ * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
+ * All rights reserved.
+ *
+ * See the file LICENSE.TXT for full copyright and licensing information.
+ */
+
+/*
+ * Variables for checking to make sure the system isn't too loaded
+ * for people to play
+ */
+
+#define AUTHORUID        0
+#define	MAXUSERS	25	/* max number of users for this game */
+#define	MAXLOAD		40	/* 10 * max 15 minute load average */
+#define	CHECKTIME	15	/* number of minutes between load checks */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rogue3/main.c	Tue Oct 13 13:33:34 2009 +0000
@@ -0,0 +1,475 @@
+/*
+ * @(#)main.c	3.27 (Berkeley) 6/15/81
+ *
+ * Rogue: Exploring the Dungeons of Doom
+ * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
+ * All rights reserved.
+ *
+ * See the file LICENSE.TXT for full copyright and licensing information.
+ */
+
+#include "curses.h"
+#include <time.h>
+#include <signal.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include "machdep.h"
+#include "rogue.h"
+
+int num_checks = 0;			/* times we've gone over in checkout() */
+WINDOW *cw;                              /* Window that the player sees */
+WINDOW *hw;                              /* Used for the help command */
+WINDOW *mw;                              /* Used to store mosnters */
+FILE   *scoreboard = NULL;
+
+main(argc, argv, envp)
+char **argv;
+char **envp;
+{
+    char *env;
+    struct linked_list *item;
+    struct object *obj;
+    int lowtime;
+    time_t now;
+
+    md_init(MD_STRIP_CTRL_KEYPAD);
+
+    open_score();
+
+    /* 
+     * Drop setuid/setgid after opening the scoreboard file. 
+     */
+
+    md_normaluser();
+
+    /*
+     * check for print-score option
+     */
+    if (argc == 2 && strcmp(argv[1], "-s") == 0)
+    {
+	waswizard = TRUE;
+	score(0, -1, 0);
+	exit(0);
+    }
+    /*
+     * Check to see if he is a wizard
+     */
+    if (argc >= 2 && argv[1][0] == '\0')
+	if (strcmp(PASSWD, crypt(md_getpass("Wizard's password: "), "mT")) == 0)
+	{
+	    wizard = TRUE;
+	    argv++;
+	    argc--;
+	}
+
+    /*
+     * get home and options from environment
+     */
+    strcpy(home, md_gethomedir());
+    
+    if (strlen(home) > PATH_MAX - strlen("rogue.save") - 1)
+        *home = 0;
+    
+    strcpy(file_name, home);
+    strcat(file_name, "rogue.save");
+
+    if ((env = getenv("ROGUEOPTS")) != NULL)
+	parse_opts(env);
+    if (env == NULL || whoami[0] == '\0')
+	strucpy(whoami, md_getusername(), strlen(md_getusername()));
+    if (env == NULL || fruit[0] == '\0')
+	strcpy(fruit, "slime-mold");
+
+    if (too_much() && !wizard && !author())
+    {
+	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);
+	exit(1);
+    }
+
+    if (argc == 2)
+	if (!restore(argv[1], envp)) /* Note: restore will never return */
+	    exit(1);
+
+    time(&now);
+    lowtime = (int) now;
+
+    env = getenv("SEED");
+
+    if (env)
+        seed = atoi(env);
+    else
+        seed = 0;
+
+    if (seed > 0)
+    {
+        waswizard = 1; /* don't save scores if SEED specified */
+        dnum = seed;
+    }
+    else
+        dnum = lowtime + md_getpid();
+
+    if (wizard || env)
+	printf("Hello %s, welcome to dungeon #%d", whoami, dnum);
+    else
+	printf("Hello %s, just a moment while I dig the dungeon...", whoami);
+
+    fflush(stdout);
+    seed = dnum;
+    init_player();			/* Roll up the rogue */
+    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)
+    {
+	endwin();
+	printf("\n\nSorry, %s, but your terminal window has too few columns.\n", whoami);
+	printf("Your terminal has %d columns, needs 70.\n",COLS);
+	exit(1);
+    }
+    if (LINES < 22)
+    {
+	endwin();
+	printf("\n\nSorry, %s, but your terminal window has too few lines.\n", whoami);
+	printf("Your terminal has %d lines, needs 22.\n",LINES);
+	exit(1);
+    }
+    
+
+    setup();
+    /*
+     * Set up windows
+     */
+    cw = newwin(LINES, COLS, 0, 0);
+    mw = newwin(LINES, COLS, 0, 0);
+    hw = newwin(LINES, COLS, 0, 0);
+    keypad(cw,1);
+    waswizard = wizard;
+    new_level();			/* Draw current level */
+    /*
+     * Start up daemons and fuses
+     */
+    start_daemon(doctor, 0, AFTER);
+    fuse(swander, 0, WANDERTIME, AFTER);
+    start_daemon(stomach, 0, AFTER);
+    start_daemon(runners, 0, AFTER);
+    /*
+     * Give the rogue his weaponry.  First a mace.
+     */
+    item = new_item(sizeof *obj);
+    obj = (struct object *) ldata(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;
+    add_pack(item, TRUE);
+    cur_weapon = obj;
+    /*
+     * Now a +1 bow
+     */
+    item = new_item(sizeof *obj);
+    obj = (struct object *) ldata(item);
+    obj->o_type = WEAPON;
+    obj->o_which = BOW;
+    init_weapon(obj, BOW);
+    obj->o_hplus = 1;
+    obj->o_dplus = 0;
+    obj->o_flags |= ISKNOW;
+    add_pack(item, TRUE);
+    /*
+     * Now some arrows
+     */
+    item = new_item(sizeof *obj);
+    obj = (struct object *) ldata(item);
+    obj->o_type = WEAPON;
+    obj->o_which = ARROW;
+    init_weapon(obj, ARROW);
+    obj->o_count = 25+rnd(15);
+    obj->o_hplus = obj->o_dplus = 0;
+    obj->o_flags |= ISKNOW;
+    add_pack(item, TRUE);
+    /*
+     * And his suit of armor
+     */
+    item = new_item(sizeof *obj);
+    obj = (struct object *) ldata(item);
+    obj->o_type = ARMOR;
+    obj->o_which = RING_MAIL;
+    obj->o_ac = a_class[RING_MAIL] - 1;
+    obj->o_flags |= ISKNOW;
+    cur_armor = obj;
+    add_pack(item, TRUE);
+    /*
+     * Give him some food too
+     */
+    item = new_item(sizeof *obj);
+    obj = (struct object *) ldata(item);
+    obj->o_type = FOOD;
+    obj->o_count = 1;
+    obj->o_which = 0;
+    add_pack(item, TRUE);
+    playit();
+}
+
+/*
+ * endit:
+ *	Exit the program abnormally.
+ */
+
+void
+endit(int p)
+{
+    fatal("Ok, if you want to exit that badly, I'll have to allow it\n");
+}
+
+/*
+ * fatal:
+ *	Exit the program, printing a message.
+ */
+
+void
+fatal(char *s)
+{
+    clear();
+    move(LINES-2, 0);
+    printw("%s", s);
+    draw(stdscr);
+    endwin();
+    exit(0);
+}
+
+/*
+ * rnd:
+ *	Pick a very random number.
+ */
+
+int
+rnd(int range)
+{
+    return range == 0 ? 0 : abs(RN) % range;
+}
+
+/*
+ * roll:
+ *	roll a number of dice
+ */
+
+int
+roll(int number, int sides)
+{
+    int dtotal = 0;
+
+    while(number--)
+	dtotal += rnd(sides)+1;
+    return dtotal;
+}
+/*
+ * handle stop and start signals
+ */
+
+void
+tstp(int p)
+{
+#ifdef SIGTSTP
+    signal(SIGTSTP, SIG_IGN);
+#endif
+    mvcur(0, COLS - 1, LINES - 1, 0);
+    endwin();
+    fflush(stdout);
+#ifdef SIGTSTP
+    signal(SIGTSTP, SIG_DFL);
+    kill(0, SIGTSTP);
+    signal(SIGTSTP, tstp);
+#endif
+    crmode();
+    noecho();
+    clearok(curscr, TRUE);
+    touchwin(cw);
+    draw(cw);
+    flush_type();	/* flush input */
+}
+
+void
+setup()
+{
+#ifdef SIGHUP
+    signal(SIGHUP, auto_save);
+#endif
+    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
+#ifdef SIGPIPE
+    signal(SIGPIPE, auto_save);
+#endif
+    signal(SIGTERM, auto_save);
+    signal(SIGINT, quit);
+#ifdef SIGQUIT
+    signal(SIGQUIT, endit);
+#endif
+#ifdef SIGTSTP
+    signal(SIGTSTP, tstp);
+#endif
+
+    if (!author())
+    {
+#ifdef SIGALRM
+	signal(SIGALRM, checkout);
+	alarm(CHECKTIME * 60);
+#endif
+	num_checks = 0;
+    }
+
+    crmode();				/* Cbreak mode */
+    noecho();				/* Echo off */
+}
+
+/*
+ * playit:
+ *	The main loop of the program.  Loop until the game is over,
+ * refreshing things and looking at the proper times.
+ */
+
+void
+playit()
+{
+    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(-1);
+}
+
+/*
+ * see if the system is being used too much for this game
+ */
+int
+too_much()
+{
+    double avec[3];
+
+    if (md_loadav(avec) == 0)
+    	return (avec[2] > (MAXLOAD / 10.0));
+    else
+        return (md_ucount() > MAXUSERS);
+}
+
+/*
+ * see if a user is an author of the program
+ */
+int
+author()
+{
+    switch (md_getuid())
+    {
+	case AUTHORUID:
+	    return TRUE;
+	default:
+	    return FALSE;
+    }
+}
+
+void
+checkout(int p)
+{
+    static char *msgs[] = {
+	"The load is too high to be playing.  Please leave in %d minutes",
+	"Please save your game.  You have %d minutes",
+	"Last warning.  You have %d minutes to leave",
+    };
+    int checktime;
+#ifdef SIGALRM
+    signal(SIGALRM, checkout);
+#endif
+    if (too_much())
+    {
+	if (num_checks >= 3)
+	    fatal("Sorry.  You took to long.  You are dead\n");
+	checktime = CHECKTIME / (num_checks + 1);
+	if (num_checks < 3)
+		chmsg(msgs[num_checks++], checktime);
+#ifdef SIGALRM
+	alarm(checktime * 60);
+#endif
+    }
+    else
+    {
+	if (num_checks)
+	{
+	    chmsg("The load has dropped back down.  You have a reprieve.");
+	    num_checks = 0;
+	}
+#ifdef SIGALRM
+	alarm(CHECKTIME * 60);
+#endif
+    }
+}
+
+/*
+ * 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.
+ */
+void
+chmsg(char *fmt, ...)
+{
+    va_list args;
+
+    if (in_shell)
+    {
+	va_start(args, fmt);
+	vprintf(fmt, args);
+	va_end(args);
+	putchar('\n');
+	fflush(stdout);
+    }
+    else
+    {
+        va_start(args, fmt);
+        doadd(fmt, args);
+        va_end(args);
+	endmsg();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rogue3/mdport.c	Tue Oct 13 13:33:34 2009 +0000
@@ -0,0 +1,1603 @@
+/*
+    mdport.c - Machine Dependent Code for Porting Unix/Curses games
+
+    Copyright (C) 2005 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.
+*/
+
+#include <stdlib.h>
+#include <string.h>
+
+#if defined(_WIN32)
+#include <Windows.h>
+#include <io.h>
+#include <sys/locking.h>
+#include <Lmcons.h>
+#include <conio.h>
+#pragma warning( disable: 4201 ) 
+#include <shlobj.h>
+#pragma warning( default: 4201 ) 
+#include <Shlwapi.h>
+#undef MOUSE_MOVED
+#endif
+
+#include <curses.h>
+
+#include "mdport.h"
+
+#if defined(HAVE_SYS_TYPES)
+#include <sys/types.h>
+#endif
+
+#if defined(HAVE_PROCESS_H)
+#include <process.h>
+#endif
+
+#if defined(HAVE_PWD_H)
+#include <pwd.h>
+#endif
+
+#if defined(HAVE_SYS_UTSNAME)
+#include <sys/utsname.h>
+#endif
+
+#if defined(HAVE_ARPA_INET_H)
+#include <arpa/inet.h> /* Solaris 2.8 required this for htonl() and ntohl() */
+#endif
+
+#if defined(HAVE_TERMIOS_H)
+#include <termios.h>
+#endif
+
+#if defined(HAVE_UNISTD_H)
+#ifndef __USE_GNU
+#define __USE_GNU
+#include <unistd.h>
+#undef __USE_GNU
+#else
+#include <unistd.h>
+#endif
+#endif
+
+#if defined(HAVE_TERM_H)
+#include <term.h>
+#elif defined(HAVE_NCURSES_TERM_H)
+#include <ncurses/term.h>
+#endif
+
+#if defined(HAVE_WORKING_FORK)
+#include <sys/wait.h>
+#endif
+
+#ifdef HAVE_UTMPX_H
+#include <utmpx.h>
+#endif
+
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+
+#include <ctype.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <sys/stat.h>
+#include <signal.h>
+
+#define NOOP(x) (x += 0)
+
+static int pass_ctrl_keypad = 1;
+
+void
+md_init(int options)
+{
+#if defined(__INTERIX)
+    char *term;
+
+    term = getenv("TERM");
+
+    if (term == NULL)
+        setenv("TERM","interix");
+#elif defined(__DJGPP__)
+    _fmode = _O_BINARY;
+#elif defined(_WIN32)
+    _fmode = _O_BINARY;
+#endif
+
+#if defined(HAVE_ESCDELAY) || defined(NCURSES_VERSION)
+    ESCDELAY=64;
+#endif
+
+#if defined(DUMP)
+    md_onsignal_default();
+#else
+    md_onsignal_exit();
+#endif
+
+    if (options & MD_STRIP_CTRL_KEYPAD)
+        pass_ctrl_keypad = 0;
+    else
+        pass_ctrl_keypad = 1;
+}
+
+void
+md_onsignal_default(void)
+{
+#ifdef SIGHUP
+    signal(SIGHUP, SIG_DFL);
+#endif
+#ifdef SIGQUIT
+    signal(SIGQUIT, SIG_DFL);
+#endif
+#ifdef SIGILL
+    signal(SIGILL, SIG_DFL);
+#endif
+#ifdef SIGTRAP
+    signal(SIGTRAP, SIG_DFL);
+#endif
+#ifdef SIGIOT
+    signal(SIGIOT, SIG_DFL);
+#endif
+#ifdef SIGEMT
+    signal(SIGEMT, SIG_DFL);
+#endif
+#ifdef SIGFPE
+    signal(SIGFPE, SIG_DFL);
+#endif
+#ifdef SIGBUS
+    signal(SIGBUS, SIG_DFL);
+#endif
+#ifdef SIGSEGV
+    signal(SIGSEGV, SIG_DFL);
+#endif
+#ifdef SIGSYS
+    signal(SIGSYS, SIG_DFL);
+#endif
+#ifdef SIGTERM
+    signal(SIGTERM, SIG_DFL);
+#endif
+}
+
+void
+md_onsignal_exit(void)
+{
+#ifdef SIGHUP
+    signal(SIGHUP, SIG_DFL);
+#endif
+#ifdef SIGQUIT
+    signal(SIGQUIT, exit);
+#endif
+#ifdef SIGILL
+    signal(SIGILL, exit);
+#endif
+#ifdef SIGTRAP
+    signal(SIGTRAP, exit);
+#endif
+#ifdef SIGIOT
+    signal(SIGIOT, exit);
+#endif
+#ifdef SIGEMT
+    signal(SIGEMT, exit);
+#endif
+#ifdef SIGFPE
+    signal(SIGFPE, exit);
+#endif
+#ifdef SIGBUS
+    signal(SIGBUS, exit);
+#endif
+#ifdef SIGSEGV
+    signal(SIGSEGV, exit);
+#endif
+#ifdef SIGSYS
+    signal(SIGSYS, exit);
+#endif
+#ifdef SIGTERM
+    signal(SIGTERM, exit);
+#endif
+}
+
+extern void auto_save(int sig);
+extern void endit(int sig);
+extern void quit(int sig);
+
+void
+md_onsignal_autosave(void)
+{
+
+#ifdef SIGHUP
+    signal(SIGHUP, auto_save);
+#endif
+#ifdef SIGQUIT
+	signal(SIGQUIT, endit);
+#endif
+#ifdef SIGILL
+    signal(SIGILL, auto_save);
+#endif
+#ifdef SIGTRAP
+    signal(SIGTRAP, auto_save);
+#endif
+#ifdef SIGIOT
+    signal(SIGIOT, auto_save);
+#endif
+#ifdef SIGEMT
+    signal(SIGEMT, auto_save);
+#endif
+#ifdef SIGFPE
+    signal(SIGFPE, auto_save);
+#endif
+#ifdef SIGBUS
+    signal(SIGBUS, auto_save);
+#endif
+#ifdef SIGSEGV
+    signal(SIGSEGV, auto_save);
+#endif
+#ifdef SIGSYS
+    signal(SIGSYS, auto_save);
+#endif
+#ifdef SIGTERM
+    signal(SIGTERM, auto_save);
+#endif
+#ifdef SIGINT
+    signal(SIGINT, quit);
+#endif
+}
+
+int
+md_hasclreol(void)
+{
+#if defined(clr_eol)
+#ifdef NCURSES_VERSION
+    if (cur_term == NULL)
+	return(0);
+    if (cur_term->type.Strings == NULL)
+	return(0);
+#endif
+    return((clr_eol != NULL) && (*clr_eol != 0));
+#elif defined(__PDCURSES__)
+    return(TRUE);
+#else
+    return((CE != NULL) && (*CE != 0));
+#endif
+}
+
+void
+md_putchar(int c)
+{
+    putchar(c);
+}
+
+#ifdef _WIN32
+static int md_standout_mode = 0;
+#endif
+
+void
+md_raw_standout(void)
+{
+#ifdef _WIN32
+    CONSOLE_SCREEN_BUFFER_INFO csbiInfo; 
+    HANDLE hStdout;
+    WORD 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(void)
+{
+#ifdef _WIN32
+    CONSOLE_SCREEN_BUFFER_INFO csbiInfo; 
+    HANDLE hStdout;
+    WORD 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(const char *file, FILE *inf)
+{
+#ifdef _WIN32
+    fclose(inf);
+    (void) _chmod(file, 0600);
+    return( _unlink(file) );
+#else
+    return(unlink(file));
+#endif
+}
+
+int
+md_unlink(char *file)
+{
+#ifdef _WIN32
+    (void) _chmod(file, 0600);
+    return( _unlink(file) );
+#else
+    return(unlink(file));
+#endif
+}
+
+int
+md_chmod(const char *filename, int mode)
+{
+#ifdef _WIN32
+    return( _chmod(filename, mode) );
+#else
+    return( chmod(filename, mode) );
+#endif
+}
+
+void
+md_normaluser(void)
+{
+#if defined(HAVE_GETGID) && defined(HAVE_GETUID)
+	gid_t realgid = getgid();
+	uid_t realuid = getuid();
+
+#if defined(HAVE_SETRESGID)
+    if (setresgid(-1, realgid, realgid) != 0) {
+#elif defined (HAVE_SETREGID) 
+    if (setregid(realgid, realgid) != 0) {
+#elif defined (HAVE_SETGID)
+	if (setgid(realgid) != 0) {
+#else
+	if (0) {
+#endif
+		perror("Could not drop setgid privileges.  Aborting.");
+		exit(1);
+    }
+
+#if defined(HAVE_SETRESUID)
+    if (setresuid(-1, realuid, realuid) != 0) {
+#elif defined(HAVE_SETREUID)
+    if (setreuid(realuid, realuid) != 0) {
+#elif defined(HAVE_SETUID)
+	if (setuid(realuid) != 0) {
+#else
+	if (0) {
+#endif
+	perror("Could not drop setuid privileges.  Aborting.");
+	exit(1);
+    }
+#endif
+}
+
+uid_t
+md_getuid(void)
+{
+#ifdef HAVE_GETUID
+    return( getuid() );
+#else
+    return(42);
+#endif
+}
+
+pid_t
+md_getpid(void)
+{
+#ifdef _WIN32
+    return( _getpid() );
+#else
+    return( getpid() );
+#endif
+}
+
+char *
+md_getusername(void)
+{
+    static char login[80];
+    char *l = NULL;
+#ifdef _WIN32
+    LPSTR mybuffer;
+    DWORD size = UNLEN + 1;
+    TCHAR buffer[UNLEN + 1];
+
+    mybuffer = buffer;
+    GetUserName(mybuffer,&size);
+    l = mybuffer;
+#elif defined(HAVE_GETPWUID)&& !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("LOGNAME")) == NULL )
+                if ( (l = getenv("USER")) == NULL )
+                    l = "nobody";
+
+    strncpy(login,l,80);
+    login[79] = 0;
+
+    return(login);
+}
+
+char *
+md_gethomedir(void)
+{
+    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 )
+	{
+            if ( (h = getenv("HOMEDRIVE")) == NULL)
+                h = "";
+            else
+            {
+                strncpy(homedir,h,PATH_MAX-1);
+                homedir[PATH_MAX-1] = 0;
+
+                if ( (h = getenv("HOMEPATH")) == NULL)
+                    h = "";
+            }
+	}
+    }
+
+
+    len = strlen(homedir);
+    strncat(homedir,h,PATH_MAX-len-1);
+    len = strlen(homedir);
+
+    if ((len > 0) && (homedir[len-1] != slash)) {
+        homedir[len] = slash;
+        homedir[len+1] = 0;
+    }
+
+    return(homedir);
+}
+
+void
+md_sleep(int s)
+{
+#ifdef _WIN32
+    Sleep(s);
+#else
+    sleep(s);
+#endif
+}
+
+char *
+md_getshell(void)
+{
+    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);
+}
+
+int
+md_shellescape(void)
+{
+#if defined(HAVE_WORKING_FORK)
+    int ret_status;
+    int pid;
+    void (*myquit)(int);
+    void (*myend)(int);
+    char *sh;
+
+    sh = md_getshell();
+
+    while((pid = fork()) < 0)
+        sleep(1);
+
+    if (pid == 0) /* Shell Process */
+    {
+        /*
+         * Set back to original user, just in case
+         */
+        md_normaluser();
+        execl(sh == NULL ? "/bin/sh" : sh, "shell", "-i", NULL);
+        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);
+#elif defined(HAVE__SPAWNL) 
+    return((int)_spawnl(_P_WAIT,md_getshell(),"shell",NULL,0));
+#elif defined(HAVE_SPAWNL)
+    return ( spawnl(P_WAIT,md_getshell(),"shell",NULL,0) );
+#else
+	return(0);
+#endif
+}
+
+int
+directory_exists(char *dirname)
+{
+    struct stat sb;
+
+    if (stat(dirname, &sb) == 0) /* path exists */
+        return (sb.st_mode & S_IFDIR);
+
+    return(0);
+}
+
+char *
+md_getrealname(uid_t 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
+}
+
+char *
+md_getpass(char *prompt)
+{
+#ifndef HAVE_GETPASS
+    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++ = (char) c;
+        else
+            count++;
+    }
+   *p = '\0';
+
+   fputc('\n', stderr);
+
+   return password_buffer;
+#else
+   return( getpass(prompt) );
+#endif
+}
+
+int
+md_erasechar(void)
+{
+#ifdef HAVE_ERASECHAR
+    return( erasechar() ); /* process erase character */
+#elif defined(VERASE)
+    return(_tty.c_cc[VERASE]); /* process erase character */
+#else
+    return(_tty.sg_erase); /* process erase character */
+#endif
+}
+
+int
+md_killchar(void)
+{
+#ifdef HAVE_KILLCHAR
+    return( killchar() );
+#elif defined(VKILL)
+    return(_tty.c_cc[VKILL]);
+#else
+    return(_tty.sg_kill);
+#endif
+}
+
+int
+md_dsuspchar(void)
+{
+#if defined(VDSUSP)			/* POSIX has priority */
+    struct termios attr;
+    tcgetattr(STDIN_FILENO, &attr);
+    return( attr.c_cc[VDSUSP] );
+#elif defined(TIOCGLTC)
+    struct ltchars ltc;
+    ioctl(1, TIOCGLTC, &ltc);
+    return(ltc.t_dsuspc);
+#elif defined(_POSIX_VDISABLE)
+    return(_POSIX_VDISABLE);
+#else
+    return(0);
+#endif
+}
+
+int
+md_setdsuspchar(int c)
+{
+#if defined(VDSUSP)			/* POSIX has priority */
+    struct termios attr;
+    tcgetattr(STDIN_FILENO, &attr);
+    attr.c_cc[VDSUSP] = c;
+    tcgetattr(STDIN_FILENO, &attr);
+#elif defined(TIOCSLTC)
+    struct ltchars ltc;
+    ioctl(1, TIOCGLTC, &ltc);
+    ltc.t_dsuspc = c;
+    ioctl(1, TIOCSLTC, &ltc);
+#else
+    NOOP(c);
+#endif
+    return(0);
+}
+
+int
+md_suspchar(void)
+{
+#if defined(VSUSP)			/* POSIX has priority */
+    struct termios attr;
+    tcgetattr(STDIN_FILENO, &attr);
+    return( attr.c_cc[VSUSP] );
+#elif defined(TIOCGLTC)
+    struct ltchars ltc;
+    ioctl(1, TIOCGLTC, &ltc);
+    return(ltc.t_suspc);
+#elif defined(_POSIX_VDISABLE)
+    return(_POSIX_VDISABLE);
+#else
+    return(0);
+#endif
+}
+
+int
+md_setsuspchar(int c)
+{
+#if defined(VSUSP)			/* POSIX has priority */
+    struct termios attr;
+    tcgetattr(STDIN_FILENO, &attr);
+    attr.c_cc[VSUSP] = c;
+    tcgetattr(STDIN_FILENO, &attr);
+#elif defined(TIOCSLTC)
+    struct ltchars ltc;
+    ioctl(1, TIOCGLTC, &ltc);
+    ltc.t_suspc = c;
+    ioctl(1, TIOCSLTC, &ltc);
+#else
+    NOOP(c);
+#endif
+
+    return(0);
+}
+
+/*
+    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
+
+#ifndef CTRL
+#define CTRL(ch) (ch & 0x1F)
+#endif
+
+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 wch = 0;
+    int mode = M_NORMAL;
+    int mode2 = M_NORMAL;
+    int nodelayf = 0;
+    int count = 0;
+
+    for(;;)
+    {
+        if (mode == M_NORMAL && uindex >= 0)
+        {
+	    wch = ch = reread();
+	    break;
+	}
+
+	wch = 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 = CTRL( 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 = CTRL( 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 = CTRL('H'); break;
+		case KEY_RIGHT: ch = CTRL('L'); break;
+		case KEY_UP   : ch = CTRL('K'); break;
+		case KEY_DOWN : ch = CTRL('J'); break;
+		case KEY_HOME : ch = CTRL('Y'); break;
+		case KEY_PPAGE: ch = CTRL('U'); break;
+		case KEY_NPAGE: ch = CTRL('N'); break;
+		case KEY_END  : ch = CTRL('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 = CTRL('H'); break;	/* Shift-Left	    */
+		case   '$': ch = CTRL('L'); break;	/* Shift-Right	    */
+
+		/* ESC [ - Interix Console codes */
+		case   'H': ch = 'y'; break;		/* Home		    */
+		case     1: ch = CTRL('K'); break;	/* Ctl-Keypad Up    */
+		case     2: ch = CTRL('J'); break;	/* Ctl-Keypad Down  */
+		case     3: ch = CTRL('L'); break;	/* Ctl-Keypad Right */
+		case     4: ch = CTRL('H'); break;	/* Ctl-Keypad Left  */
+		case   263: ch = CTRL('Y'); break;	/* Ctl-Keypad Home  */
+		case    19: ch = CTRL('U'); break;	/* Ctl-Keypad PgUp  */
+		case    20: ch = CTRL('N'); break;	/* Ctl-Keypad PgDn  */
+		case    21: ch = CTRL('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 = CTRL('H'); break;
+		case   'C': ch = CTRL('L'); break;
+		case   'A': ch = CTRL('K'); break;
+		case   'B': ch = CTRL('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 = CTRL('L'); break;
+	    case KEY_SLEFT   : ch = CTRL('H'); break;
+#ifdef KEY_SUP
+	    case KEY_SUP     : ch = CTRL('K'); break;
+	    case KEY_SDOWN   : ch = CTRL('J'); break;
+#endif
+	    case KEY_SHOME   : ch = CTRL('Y'); break;
+	    case KEY_SPREVIOUS:ch = CTRL('U'); break;
+	    case KEY_SEND    : ch = CTRL('B'); break;
+	    case KEY_SNEXT   : ch = CTRL('N'); break;
+#endif
+	    case 0x146       : ch = CTRL('K'); break; 	/* Shift-Up	*/
+	    case 0x145       : ch = CTRL('J'); break; 	/* Shift-Down	*/
+
+#ifdef CTL_RIGHT
+	    case CTL_RIGHT   : ch = CTRL('L'); break;
+	    case CTL_LEFT    : ch = CTRL('H'); break;
+	    case CTL_UP      : ch = CTRL('K'); break;
+	    case CTL_DOWN    : ch = CTRL('J'); break;
+	    case CTL_HOME    : ch = CTRL('Y'); break;
+	    case CTL_PGUP    : ch = CTRL('U'); break;
+	    case CTL_END     : ch = CTRL('B'); break;
+	    case CTL_PGDN    : ch = CTRL('N'); break;
+#endif
+#ifdef KEY_EOL
+	    case KEY_EOL     : ch = CTRL('B'); break;
+#endif
+
+#ifndef CTL_PAD1
+	    /* MSYS rxvt console */
+	    case 511	     : ch = CTRL('J'); break; /* Shift Dn */
+	    case 512         : ch = CTRL('J'); break; /* Ctl Down */
+	    case 514	     : ch = CTRL('H'); break; /* Ctl Left */
+	    case 516	     : ch = CTRL('L'); break; /* Ctl Right*/
+	    case 518	     : ch = CTRL('K'); break; /* Shift Up */
+	    case 519	     : ch = CTRL('K'); break; /* Ctl Up   */
+#endif
+
+#ifdef CTL_PAD1
+	    case CTL_PAD1   : ch = CTRL('B'); break;
+	    case CTL_PAD2   : ch = CTRL('J'); break;
+	    case CTL_PAD3   : ch = CTRL('N'); break;
+	    case CTL_PAD4   : ch = CTRL('H'); break;
+	    case CTL_PAD5   : ch = '.'; break;
+	    case CTL_PAD6   : ch = CTRL('L'); break;
+	    case CTL_PAD7   : ch = CTRL('Y'); break;
+	    case CTL_PAD8   : ch = CTRL('K'); break;
+	    case CTL_PAD9   : ch = CTRL('U'); break;
+#endif
+
+#ifdef ALT_RIGHT
+	    case ALT_RIGHT  : ch = CTRL('L'); break;
+	    case ALT_LEFT   : ch = CTRL('H'); break;
+	    case ALT_DOWN   : ch = CTRL('J'); break;
+	    case ALT_HOME   : ch = CTRL('Y'); break;
+	    case ALT_PGUP   : ch = CTRL('U'); break;
+	    case ALT_END    : ch = CTRL('B'); break;
+	    case ALT_PGDN   : ch = CTRL('N'); break;
+#endif
+
+#ifdef ALT_PAD1
+	    case ALT_PAD1   : ch = CTRL('B'); break;
+	    case ALT_PAD2   : ch = CTRL('J'); break;
+	    case ALT_PAD3   : ch = CTRL('N'); break;
+	    case ALT_PAD4   : ch = CTRL('H'); break;
+	    case ALT_PAD5   : ch = '.'; break;
+	    case ALT_PAD6   : ch = CTRL('L'); break;
+	    case ALT_PAD7   : ch = CTRL('Y'); break;
+	    case ALT_PAD8   : ch = CTRL('K'); break;
+	    case ALT_PAD9   : ch = CTRL('U'); break;
+#endif
+#ifdef KEY_BACKSPACE /* NCURSES in Keypad mode sends this for Ctrl-H */
+            case KEY_BACKSPACE: ch = CTRL('H'); break;
+#endif
+	}
+
+	break;
+    }
+
+
+    if (nodelayf)
+        nodelay(win,0);
+
+    uindex = -1;
+
+    if (!pass_ctrl_keypad && (ch != wch))
+        switch(ch) 
+        {
+	    case CTRL('H'):
+	    case CTRL('L'):
+	    case CTRL('K'):
+	    case CTRL('J'):
+	    case CTRL('Y'):
+	    case CTRL('U'):
+	    case CTRL('N'):
+	    case CTRL('B'):
+                return(ch + 0x40);
+        }
+
+    return(ch & 0x7F);
+}
+
+#if defined(LOADAV) && defined(HAVE_NLIST_H) && defined(HAVE_NLIST)
+/*
+ * loadav:
+ *	Looking up load average in core (for system where the loadav()
+ *	system call isn't defined
+ */
+
+#include <nlist.h>
+
+struct nlist avenrun = {
+    "_avenrun"
+};
+
+int
+md_loadav(double *avg)
+{
+    int kmem;
+
+    if ((kmem = open("/dev/kmem", 0)) < 0)
+	goto bad;
+    nlist(NAMELIST, &avenrun);
+    if (avenrun.n_type == 0)
+    {
+	close(kmem);
+bad:
+	avg[0] = 0.0;
+	avg[1] = 0.0;
+	avg[2] = 0.0;
+	return -1;
+    }
+
+    lseek(kmem, avenrun.n_value, 0);
+    read(kmem, (char *) avg, 3 * sizeof (double));
+    close(kmem);
+    return 0;
+}
+#else
+int
+md_loadav(double *avg)
+{
+#if defined(HAVE_LOADAV)
+    loadav(avg);
+    return(0);
+#elif defined(HAVE_GETLOADAVG)
+    int ret;
+    ret = getloadavg(avg,3);
+    return (ret == 3) ? 0 : -1;
+#else
+    avg[0] = avg[1] = avg[2] = 0;
+    return(-1);
+#endif
+}
+#endif
+
+#ifndef NSIG
+#define NSIG 32
+#endif
+
+void
+md_ignoreallsignals(void)
+{
+	int i;
+
+	for (i = 0; i < NSIG; i++)
+		signal(i, SIG_IGN);
+}
+
+void
+md_tstphold(void)
+{
+#ifdef SIGTSTP
+    /*
+     * If a process can be suspended, this code wouldn't work
+     */
+# ifdef SIG_HOLD
+    signal(SIGTSTP, SIG_HOLD);
+# else
+    signal(SIGTSTP, SIG_IGN);
+# endif
+#endif
+}
+
+void
+md_tstpresume(void (*tstp)(int))
+{
+#ifdef SIGTSTP
+    signal(SIGTSTP, tstp);
+#endif
+}
+
+void
+md_tstpsignal(void)
+{
+#ifdef SIGTSTP
+    kill(0, SIGTSTP);		/* send actual signal and suspend process */
+#endif
+}
+
+#if defined(CHECKTIME)
+void
+md_start_checkout_timer(int time)
+{
+    int  checkout();
+
+#if defined(HAVE_ALARM) && defined(SIGALRM)
+    signal(SIGALRM, checkout);
+	alarm(time);
+#endif
+}
+
+void
+md_stop_checkout_timer(void)
+{
+#if defined(SIGALRM)
+    signal(SIGALRM, SIG_IGN);
+#endif
+}
+#endif
+
+long
+md_memused()
+{
+#ifdef _WIN32
+    MEMORYSTATUS stat;
+
+    GlobalMemoryStatus(&stat);
+
+    return((long)stat.dwTotalPageFile);
+#else
+    return( (long)sbrk(0) );
+#endif
+}
+
+int
+md_ucount()
+{
+#if defined(HAVE_UTMPX_H)
+    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);
+#else
+   return(1)
+#endif
+}
+
+int
+md_lockfile(FILE *fp)
+{
+    int fd;
+    int ret;
+
+    fflush(fp);
+    rewind(fp);
+
+#ifdef _WIN32
+    fd = _fileno(fp);
+    ret = _locking(fd,_LK_LOCK,1);
+#else
+    fd = fileno(fp);
+
+    while((ret = lockf(fd, F_LOCK, 1)) == -1)
+	if (errno != EINTR)
+            break;
+#endif
+
+    return ret;
+}
+
+int
+md_unlockfile(FILE *fp)
+{
+    int fd;
+    int ret;
+
+    fflush(fp);
+    rewind(fp);
+
+
+#ifdef _WIN32
+    fd = _fileno(fp);
+    ret = _locking(fd,_LK_UNLCK,1);
+#else
+    fd = fileno(fp);
+    
+    while( (ret = lockf(fd, F_ULOCK, 1)) == -1)
+        if (errno != EINTR)
+            break;
+#endif
+
+    return ret;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rogue3/mdport.h	Tue Oct 13 13:33:34 2009 +0000
@@ -0,0 +1,193 @@
+/*
+    mdport.h - Machine Dependent Code for Porting Unix/Curses games
+
+    Copyright (C) 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.
+*/
+
+#ifdef HAVE_CONFIG_H
+#ifdef PDCURSES
+#undef HAVE_UNISTD_H
+#undef HAVE_LIMITS_H
+#undef HAVE_MEMORY_H
+#undef HAVE_STRING_H
+#endif
+#include "config.h"
+
+#elif defined(__DJGPP__)
+#define HAVE_SYS_TYPES_H 1
+#define HAVE_PROCESS_H 1
+#define HAVE_PWD_H 1
+#define HAVE_TERMIOS_H 1
+#define HAVE_SETGID 1
+#define HAVE_GETGID 1
+#define HAVE_SETUID 1
+#define HAVE_GETUID 1
+#define HAVE_GETPASS 1
+#define HAVE_SPAWNL 1
+#define HAVE_ALARM 1
+#define HAVE_ERASECHAR 1
+#define HAVE_KILLCHAR 1
+#define HAVE_CRYPT
+
+#elif defined(_WIN32)
+#define HAVE_CURSES_H
+#define HAVE_TERM_H
+#define HAVE__SPAWNL
+#define HAVE_SYS_TYPES_H
+#define HAVE_PROCESS_H
+#define HAVE_ERASECHAR 1
+#define HAVE_KILLCHAR 1
+#ifndef uid_t
+typedef unsigned int uid_t;
+#endif
+#ifndef pid_t
+typedef unsigned int pid_t;
+#endif
+
+#elif defined(__CYGWIN__)
+#define HAVE_SYS_TYPES_H 1
+#define HAVE_PWD_H 1
+#define HAVE_PWD_H 1
+#define HAVE_SYS_UTSNAME_H 1
+#define HAVE_ARPA_INET_H 1
+#define HAVE_UNISTD_H 1
+#define HAVE_TERMIOS_H 1
+#define HAVE_NCURSES_TERM_H 1
+#define HAVE_ESCDELAY
+#define HAVE_SETGID 1
+#define HAVE_GETGID 1
+#define HAVE_SETUID 1
+#define HAVE_GETUID 1
+#define HAVE_GETPASS 1
+#define HAVE_GETPWUID 1
+#define HAVE_WORKING_FORK 1
+#define HAVE_ALARM 1
+#define HAVE_SPAWNL 1
+#define HAVE__SPAWNL 1
+#define HAVE_ERASECHAR 1
+#define HAVE_KILLCHAR 1
+#define HAVE_CRYPT 1
+
+#else /* standards based unix */
+#define HAVE_SYS_TYPES_H 1
+#define HAVE_PWD_H 1
+#define HAVE_SYS_UTSNAME_H 1
+#define HAVE_ARPA_INET_H 1
+#define HAVE_UNISTD_H 1
+#define HAVE_CRYPT_H 1
+#define HAVE_LIMITS_H 1
+#define HAVE_TERMIOS_H 1
+#define HAVE_UTMPX_H 1
+#define HAVE_ERRNO_H 1
+#define HAVE_TERM_H 1
+#define HAVE_SETGID 1
+#define HAVE_GETGID 1
+#define HAVE_SETUID 1
+#define HAVE_GETUID 1
+#define HAVE_SETREUID 1
+#define HAVE_SETREGID 1
+#define HAVE_CRYPT 1
+#define HAVE_GETPASS 1
+#define HAVE_GETPWUID 1
+#define HAVE_WORKING_FORK 1
+#define HAVE_ERASECHAR 1
+#define HAVE_KILLCHAR 1
+#ifndef _AIX
+#define HAVE_GETLOADAVG 1
+#endif
+#define HAVE_ALARM 1
+#endif
+
+#ifdef __DJGPP__
+#undef HAVE_GETPWUID /* DJGPP's limited version doesn't even work as documented */
+#endif
+
+#define MD_STRIP_CTRL_KEYPAD 1
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#ifdef HAVE_LIMITS_H
+#include <limits.h>
+#endif
+
+#if !defined(PATH_MAX) && defined(_MAX_PATH)
+#define PATH_MAX _MAX_PATH
+#endif
+
+#if !defined(PATH_MAX) && defined(_PATH_MAX)
+#define PATH_MAX _PATH_MAX
+#endif
+
+#ifndef HAVE_CRYPT
+char *	crypt(const char *key, const char *setting);
+#else
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_CRYPT_H
+#include <crypt.h>
+#endif
+#endif
+
+int	md_chmod(const char *filename, int mode);
+int	md_dsuspchar(void);
+int	md_erasechar(void);
+char *	md_gethomedir(void);
+char *	md_getusername(void);
+uid_t	md_getuid(void);
+char *	md_getpass(char *prompt);
+pid_t	md_getpid(void);
+char *	md_getrealname(uid_t uid);
+void	md_init(int options);
+int	md_killchar(void);
+void	md_normaluser(void);
+void	md_raw_standout(void);
+void	md_raw_standend(void);
+int	md_readchar(WINDOW *win);
+int	md_setdsuspchar(int c);
+int	md_shellescape(void);
+void	md_sleep(int s);
+int	md_suspchar(void);
+int	md_hasclreol(void);
+int	md_unlink(char *file);
+int	md_unlink_open_file(const char *file, FILE *inf);
+void	md_tstpsignal(void);
+void	md_tstphold(void);
+void	md_tstpresume(void (*tstp)(int));
+void	md_ignoreallsignals(void);
+void	md_onsignal_autosave(void);
+void	md_onsignal_exit(void);
+void	md_onsignal_default(void);
+int	md_issymlink(char *sp);
+int     md_loadav(double *avg);
+long    md_memused(void);
+int     md_ucount(void);
+int     md_unlockfile(FILE *fp);
+int     md_lockfile(FILE *fp);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rogue3/misc.c	Tue Oct 13 13:33:34 2009 +0000
@@ -0,0 +1,431 @@
+/*
+ * all sorts of miscellaneous routines
+ *
+ * @(#)misc.c	3.13 (Berkeley) 6/15/81
+ *
+ * Rogue: Exploring the Dungeons of Doom
+ * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
+ * All rights reserved.
+ *
+ * See the file LICENSE.TXT for full copyright and licensing information.
+ */
+
+#include "curses.h"
+#include "rogue.h"
+#include <ctype.h>
+
+/*
+ * tr_name:
+ *	print the name of a trap
+ */
+
+char *
+tr_name(int ch)
+{
+    char *s = "";
+
+    switch (ch)
+    {
+	case TRAPDOOR:
+	    s = terse ? "A trapdoor." : "You found a trapdoor.";
+	when BEARTRAP:
+	    s = terse ? "A beartrap." : "You found a beartrap.";
+	when SLEEPTRAP:
+	    s = terse ? "A sleeping gas trap.":"You found a sleeping gas trap.";
+	when ARROWTRAP:
+	    s = terse ? "An arrow trap." : "You found an arrow trap.";
+	when TELTRAP:
+	    s = terse ? "A teleport trap." : "You found a teleport trap.";
+	when DARTTRAP:
+	    s = terse ? "A dart trap." : "You found a poison dart trap.";
+    }
+    return s;
+}
+
+/*
+ * Look:
+ *	A quick glance all around the player
+ */
+
+void
+look(int wakeup)
+{
+    int x, y;
+    int ch;
+    int oldx, oldy;
+    int inpass;
+    int passcount = 0;
+    struct room *rp;
+    int ey, ex;
+
+    getyx(cw, oldy, oldx);
+    if (oldrp != NULL && (oldrp->r_flags & ISDARK) && off(player, ISBLIND))
+    {
+	for (x = oldpos.x - 1; x <= oldpos.x + 1; x++)
+	    for (y = oldpos.y - 1; y <= oldpos.y + 1; y++)
+		if ((y != hero.y || x != hero.x) && show(y, x) == FLOOR)
+		    mvwaddch(cw, y, x, ' ');
+    }
+    inpass = ((rp = roomin(&hero)) == NULL);
+    ey = hero.y + 1;
+    ex = hero.x + 1;
+    for (x = hero.x - 1; x <= ex; x++)
+	if (x >= 0 && x < COLS) for (y = hero.y - 1; y <= ey; y++)
+	{
+	    if (y <= 0 || y >= LINES - 1)
+		continue;
+	    if (isupper(mvwinch(mw, y, x)))
+	    {
+		struct linked_list *it;
+		struct thing *tp;
+
+		if (wakeup)
+		    it = wake_monster(y, x);
+		else
+		    it = find_mons(y, x);
+		tp = (struct thing *) ldata(it);
+		if ((tp->t_oldch = mvinch(y, x)) == TRAP)
+		    tp->t_oldch =
+			(trap_at(y,x)->tr_flags&ISFOUND) ? TRAP : FLOOR;
+		if (tp->t_oldch == FLOOR && (rp != NULL) && (rp->r_flags & ISDARK)
+		    && off(player, ISBLIND))
+			tp->t_oldch = ' ';
+	    }
+	    /*
+	     * Secret doors show as walls
+	     */
+	    if ((ch = show(y, x)) == SECRETDOOR)
+		ch = secretdoor(y, x);
+	    /*
+	     * Don't show room walls if he is in a passage
+	     */
+	    if (off(player, ISBLIND))
+	    {
+		if (y == hero.y && x == hero.x
+		 || (inpass && (ch == '-' || ch == '|')))
+			continue;
+	    }
+	    else if (y != hero.y || x != hero.x)
+		continue;
+	    wmove(cw, y, x);
+	    waddch(cw, ch);
+	    if (door_stop && !firstmove && running)
+	    {
+		switch (runch)
+		{
+		    case 'h':
+			if (x == ex)
+			    continue;
+		    when 'j':
+			if (y == hero.y - 1)
+			    continue;
+		    when 'k':
+			if (y == ey)
+			    continue;
+		    when 'l':
+			if (x == hero.x - 1)
+			    continue;
+		    when 'y':
+			if ((x + y) - (hero.x + hero.y) >= 1)
+			    continue;
+		    when 'u':
+			if ((y - x) - (hero.y - hero.x) >= 1)
+			    continue;
+		    when 'n':
+			if ((x + y) - (hero.x + hero.y) <= -1)
+			    continue;
+		    when 'b':
+			if ((y - x) - (hero.y - hero.x) <= -1)
+			    continue;
+		}
+		switch (ch)
+		{
+		    case DOOR:
+			if (x == hero.x || y == hero.y)
+			    running = FALSE;
+			break;
+		    case PASSAGE:
+			if (x == hero.x || y == hero.y)
+			    passcount++;
+			break;
+		    case FLOOR:
+		    case '|':
+		    case '-':
+		    case ' ':
+			break;
+		    default:
+			running = FALSE;
+			break;
+		}
+	    }
+	}
+    if (door_stop && !firstmove && passcount > 1)
+	running = FALSE;
+    mvwaddch(cw, hero.y, hero.x, PLAYER);
+    wmove(cw, oldy, oldx);
+    oldpos = hero;
+    oldrp = rp;
+}
+
+/*
+ * secret_door:
+ *	Figure out what a secret door looks like.
+ */
+
+int
+secretdoor(int y, int x)
+{
+    int i;
+    struct room *rp;
+    coord *cpp;
+    static coord cp;
+
+    cp.y = y;
+    cp.x = x;
+    cpp = &cp;
+    for (rp = rooms, i = 0; i < MAXROOMS; rp++, i++)
+	if (inroom(rp, cpp))
+	    if (y == rp->r_pos.y || y == rp->r_pos.y + rp->r_max.y - 1)
+		return('-');
+	    else
+		return('|');
+
+    return('p');
+}
+
+/*
+ * find_obj:
+ *	find the unclaimed object at y, x
+ */
+
+struct linked_list *
+find_obj(int y, int x)
+{
+    struct linked_list *obj;
+    struct object *op;
+
+    for (obj = lvl_obj; obj != NULL; obj = next(obj))
+    {
+	op = (struct object *) ldata(obj);
+	if (op->o_pos.y == y && op->o_pos.x == x)
+		return obj;
+    }
+    sprintf(prbuf, "Non-object %d,%d", y, x);
+    debug(prbuf);
+    return NULL;
+}
+
+/*
+ * eat:
+ *	She wants to eat something, so let her try
+ */
+
+void
+eat()
+{
+    struct linked_list *item;
+    struct object *obj;
+
+    if ((item = get_item("eat", FOOD)) == NULL)
+	return;
+    obj = (struct object *) ldata(item);
+    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 (obj->o_which == 1)
+	msg("My, that was a yummy %s", fruit);
+    else
+	if (rnd(100) > 70)
+	{
+	    msg("Yuk, this food tastes awful");
+	    pstats.s_exp++;
+	    check_level();
+	}
+	else
+	    msg("Yum, that tasted good");
+    if ((food_left += HUNGERTIME + rnd(400) - 200) > STOMACHSIZE)
+	food_left = STOMACHSIZE;
+    hungry_state = 0;
+    if (obj == cur_weapon)
+	cur_weapon = NULL;
+    if (--obj->o_count < 1)
+    {
+	detach(pack, item);
+	discard(item);
+    }
+}
+
+/*
+ * Used to modify the playes strength
+ * it keeps track of the highest it has been, just in case
+ */
+
+void
+chg_str(int amt)
+{
+    if (amt == 0)
+	return;
+    if (amt > 0)
+    {
+	while (amt--)
+	{
+	    if (pstats.s_str.st_str < 18)
+		pstats.s_str.st_str++;
+	    else if (pstats.s_str.st_add == 0)
+		pstats.s_str.st_add = rnd(50) + 1;
+	    else if (pstats.s_str.st_add <= 50)
+		pstats.s_str.st_add = 51 + rnd(24);
+	    else if (pstats.s_str.st_add <= 75)
+		pstats.s_str.st_add = 76 + rnd(14);
+	    else if (pstats.s_str.st_add <= 90)
+		pstats.s_str.st_add = 91;
+	    else if (pstats.s_str.st_add < 100)
+		pstats.s_str.st_add++;
+	}
+	if (pstats.s_str.st_str > max_stats.s_str.st_str ||
+	    (pstats.s_str.st_str == 18 &&
+	     pstats.s_str.st_add > max_stats.s_str.st_add))
+		max_stats.s_str = pstats.s_str;
+    }
+    else
+    {
+	while (amt++)
+	{
+	    if (pstats.s_str.st_str < 18 || pstats.s_str.st_add == 0)
+		pstats.s_str.st_str--;
+	    else if (pstats.s_str.st_add < 51)
+		pstats.s_str.st_add = 0;
+	    else if (pstats.s_str.st_add < 76)
+		pstats.s_str.st_add = 1 + rnd(50);
+	    else if (pstats.s_str.st_add < 91)
+		pstats.s_str.st_add = 51 + rnd(25);
+	    else if (pstats.s_str.st_add < 100)
+		pstats.s_str.st_add = 76 + rnd(14);
+	    else
+		pstats.s_str.st_add = 91 + rnd(8);
+	}
+	if (pstats.s_str.st_str < 3)
+	    pstats.s_str.st_str = 3;
+    }
+}
+
+/*
+ * add_haste:
+ *	add a haste to the player
+ */
+
+void
+add_haste(int potion)
+{
+    if (on(player, ISHASTE))
+    {
+	msg("You faint from exhaustion.");
+	no_command += rnd(8);
+	extinguish(nohaste);
+    }
+    else
+    {
+	player.t_flags |= ISHASTE;
+	if (potion)
+	    fuse(nohaste, 0, rnd(4)+4, AFTER);
+    }
+}
+
+/*
+ * aggravate:
+ *	aggravate all the monsters on this level
+ */
+
+void
+aggravate()
+{
+    struct linked_list *mi;
+
+    for (mi = mlist; mi != NULL; mi = next(mi))
+	runto(&((struct thing *) ldata(mi))->t_pos, &hero);
+}
+
+/*
+ * for printfs: if string starts with a vowel, return "n" for an "an"
+ */
+char *
+vowelstr(char *str)
+{
+    switch (*str)
+    {
+	case 'a':
+	case 'e':
+	case 'i':
+	case 'o':
+	case 'u':
+	    return "n";
+	default:
+	    return "";
+    }
+}
+
+/* 
+ * see if the object is one of the currently used items
+ */
+int
+is_current(struct object *obj)
+{
+    if (obj == NULL)
+	return FALSE;
+    if (obj == cur_armor || obj == cur_weapon || obj == cur_ring[LEFT]
+	|| obj == cur_ring[RIGHT])
+    {
+	msg(terse ? "In use." : "That's already in use.");
+	return TRUE;
+    }
+    return FALSE;
+}
+
+/*
+ * set up the direction co_ordinate for use in varios "prefix" commands
+ */
+int
+get_dir()
+{
+    char *prompt;
+    int gotit;
+
+    if (!terse)
+	msg(prompt = "Which direction? ");
+    else
+	prompt = "Direction: ";
+    do
+    {
+	gotit = TRUE;
+	switch (readchar(cw))
+	{
+	    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(100) > 80)
+	do
+	{
+	    delta.y = rnd(3) - 1;
+	    delta.x = rnd(3) - 1;
+	} while (delta.y == 0 && delta.x == 0);
+    mpos = 0;
+    return TRUE;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rogue3/monsters.c	Tue Oct 13 13:33:34 2009 +0000
@@ -0,0 +1,243 @@
+/*
+ * File with various monster functions in it
+ *
+ * @(#)monsters.c	3.18 (Berkeley) 6/15/81
+ *
+ * Rogue: Exploring the Dungeons of Doom
+ * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
+ * All rights reserved.
+ *
+ * See the file LICENSE.TXT for full copyright and licensing information.
+ */
+
+#include "curses.h"
+#include "rogue.h"
+#include <string.h>
+#include <ctype.h>
+
+/*
+ * List of monsters in rough order of vorpalness
+ */
+char lvl_mons[27] =  "KJBSHEAOZGLCRQNYTWFIXUMVDP";
+char wand_mons[27] = "KJBSH AOZG CRQ Y W IXU V  ";
+
+/*
+ * randmonster:
+ *	Pick a monster to show up.  The lower the level,
+ *	the meaner the monster.
+ */
+
+int
+randmonster(int wander)
+{
+    int d;
+    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
+ */
+
+void
+new_monster(struct linked_list *item, int type, coord *cp)
+{
+    struct thing *tp;
+    struct monster *mp;
+
+    attach(mlist, item);
+    tp = (struct thing *) ldata(item);
+    tp->t_type = type;
+    tp->t_pos = *cp;
+    tp->t_oldch = mvwinch(cw, cp->y, cp->x);
+    mvwaddch(mw, cp->y, cp->x, tp->t_type);
+    mp = &monsters[tp->t_type-'A'];
+    tp->t_stats.s_hpt = roll(mp->m_stats.s_lvl, 8);
+    tp->t_stats.s_lvl = mp->m_stats.s_lvl;
+    tp->t_stats.s_arm = mp->m_stats.s_arm;
+    strcpy(tp->t_stats.s_dmg,mp->m_stats.s_dmg);
+    tp->t_stats.s_exp = mp->m_stats.s_exp;
+    tp->t_stats.s_str.st_str = 10;
+    tp->t_flags = mp->m_flags;
+    tp->t_turn = TRUE;
+    tp->t_pack = NULL;
+    if (ISWEARING(R_AGGR))
+	runto(cp, &hero);
+    if (type == 'M')
+    {
+	int mch = 0;
+
+	if (tp->t_pack != NULL)
+	    mch = ((struct object *) ldata(tp->t_pack))->o_type;
+	else
+	    switch (rnd(level > 25 ? 9 : 8))
+	    {
+		case 0: mch = GOLD;
+		when 1: mch = POTION;
+		when 2: mch = SCROLL;
+		when 3: mch = STAIRS;
+		when 4: mch = WEAPON;
+		when 5: mch = ARMOR;
+		when 6: mch = RING;
+		when 7: mch = STICK;
+		when 8: mch = AMULET;
+	    }
+	tp->t_disguise = mch;
+    }
+}
+
+/*
+ * wanderer:
+ *	A wandering monster has awakened and is headed for the player
+ */
+
+void
+wanderer()
+{
+    int i, ch;
+    struct room *rp, *hr = roomin(&hero);
+    struct linked_list *item;
+    struct thing *tp;
+    coord cp;
+
+    item = new_item(sizeof *tp);
+    do
+    {
+	i = rnd_room();
+	if ((rp = &rooms[i]) == hr)
+	    continue;
+	rnd_pos(rp, &cp);
+	if ((ch = mvwinch(stdscr, cp.y, cp.x)) == ERR)
+	{
+	    debug("Routine wanderer: mvwinch failed to %d,%d", cp.y, cp.x);
+	    if (wizard)
+		wait_for(cw,'\n');
+	    return;
+	}
+    } until(hr != rp && step_ok(ch));
+    new_monster(item, randmonster(TRUE), &cp);
+    tp = (struct thing *) ldata(item);
+    tp->t_flags |= ISRUN;
+    tp->t_pos = cp;
+    tp->t_dest = &hero;
+    if (wizard)
+	msg("Started a wandering %s", monsters[tp->t_type-'A'].m_name);
+}
+
+/*
+ * what to do when the hero steps next to a monster
+ */
+struct linked_list *
+wake_monster(int y, int x)
+{
+    struct thing *tp;
+    struct linked_list *it;
+    struct room *rp;
+    int ch;
+
+    if ((it = find_mons(y, x)) == NULL)
+    {
+	fatal("Can't find monster in wake");
+	return NULL;
+    }
+        
+    tp = (struct thing *) ldata(it);
+    ch = tp->t_type;
+    /*
+     * Every time he sees mean monster, it might start chasing him
+     */
+    if (rnd(100) > 33 && on(*tp, ISMEAN) && off(*tp, ISHELD)
+	&& !ISWEARING(R_STEALTH))
+    {
+	tp->t_dest = &hero;
+	tp->t_flags |= ISRUN;
+    }
+    if (ch == 'U' && off(player, ISBLIND))
+    {
+        rp = roomin(&hero);
+	if ((rp != NULL && !(rp->r_flags&ISDARK))
+	    || DISTANCE(y, x, hero.y, hero.x) < 3)
+	{
+	    if (off(*tp, ISFOUND) && !save(VS_MAGIC))
+	    {
+		msg("The umber hulk's gaze has confused you.");
+		if (on(player, ISHUH))
+		    lengthen(unconfuse, rnd(20)+HUHDURATION);
+		else
+		    fuse(unconfuse, 0, rnd(20)+HUHDURATION, AFTER);
+		player.t_flags |= ISHUH;
+	    }
+	    tp->t_flags |= ISFOUND;
+	}
+    }
+    /*
+     * Hide invisible monsters
+     */
+    if (on(*tp, ISINVIS) && off(player, CANSEE))
+	ch = mvwinch(stdscr, y, x);
+    /*
+     * Let greedy ones guard gold
+     */
+    if (on(*tp, ISGREED) && off(*tp, ISRUN))
+    {
+        rp = roomin(&hero);
+
+	if (rp != NULL && rp->r_goldval)
+	{
+	    tp->t_dest = &rp->r_gold;
+	    tp->t_flags |= ISRUN;
+	}
+    }
+
+    return it;
+}
+
+void
+genocide()
+{
+    struct linked_list *ip;
+    struct thing *mp;
+    int c;
+    int i;
+    struct linked_list *nip;
+
+    addmsg("Which monster");
+    if (!terse)
+	addmsg(" do you wish to wipe out");
+    msg("? ");
+    while (!isalpha(c = readchar(cw)))
+	if (c == ESCAPE)
+	    return;
+	else
+	{
+	    mpos = 0;
+	    msg("Please specify a letter between 'A' and 'Z'");
+	}
+    if (islower(c))
+	c = toupper(c);
+    for (ip = mlist; ip; ip = nip)
+    {
+	mp = (struct thing *) ldata(ip);
+	nip = next(ip);
+	if (mp->t_type == c)
+	    remove_monster(&mp->t_pos, ip);
+    }
+    for (i = 0; i < 26; i++)
+	if (lvl_mons[i] == c)
+	{
+	    lvl_mons[i] = ' ';
+	    wand_mons[i] = ' ';
+	    break;
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rogue3/move.c	Tue Oct 13 13:33:34 2009 +0000
@@ -0,0 +1,384 @@
+/*
+ * Hero movement commands
+ *
+ * @(#)move.c	3.26 (Berkeley) 6/15/81
+ *
+ * Rogue: Exploring the Dungeons of Doom
+ * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
+ * All rights reserved.
+ *
+ * See the file LICENSE.TXT for full copyright and licensing information.
+ */
+
+#include "curses.h"
+#include <ctype.h>
+#include "rogue.h"
+
+/*
+ * Used to hold the new hero position
+ */
+
+coord nh;
+
+/*
+ * do_run:
+ *	Start the hero running
+ */
+
+void
+do_run(int 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.)
+ */
+
+void
+do_move(int dy, int dx)
+{
+    int ch;
+
+    firstmove = FALSE;
+    if (no_move)
+    {
+	no_move--;
+	msg("You are still stuck in the bear trap");
+	return;
+    }
+    /*
+     * Do a confused move (maybe)
+     */
+    if (rnd(100) < 80 && on(player, ISHUH))
+	nh = *rndmove(&player);
+    else
+    {
+	nh.y = hero.y + dy;
+	nh.x = hero.x + dx;
+    }
+
+    /*
+     * Check if he tried to move off the screen or make an illegal
+     * diagonal move, and stop him if he did.
+     */
+    if (nh.x < 0 || nh.x > COLS-1 || nh.y < 0 || nh.y > LINES - 1
+	|| !diag_ok(&hero, &nh))
+    {
+	after = FALSE;
+	running = FALSE;
+	return;
+    }
+    if (running && ce(hero, nh))
+	after = running = FALSE;
+    ch = winat(nh.y, nh.x);
+    if (on(player, ISHELD) && ch != 'F')
+    {
+	msg("You are being held");
+	return;
+    }
+    switch(ch)
+    {
+	case ' ':
+	case '|':
+	case '-':
+	case SECRETDOOR:
+	    after = running = FALSE;
+	    return;
+	case TRAP:
+	    ch = be_trapped(&nh);
+	    if (ch == TRAPDOOR || ch == TELTRAP)
+		return;
+	    goto move_stuff;
+	case GOLD:
+	case POTION:
+	case SCROLL:
+	case FOOD:
+	case WEAPON:
+	case ARMOR:
+	case RING:
+	case AMULET:
+	case STICK:
+	    running = FALSE;
+	    take = ch;
+	default:
+move_stuff:
+	    if (ch == PASSAGE && winat(hero.y, hero.x) == DOOR)
+		light(&hero);
+	    else if (ch == DOOR)
+	    {
+		running = FALSE;
+		if (winat(hero.y, hero.x) == PASSAGE)
+		    light(&nh);
+	    }
+	    else if (ch == STAIRS)
+		running = FALSE;
+	    else if (isupper(ch))
+	    {
+		running = FALSE;
+		fight(&nh, ch, cur_weapon, FALSE);
+		return;
+	    }
+	    ch = winat(hero.y, hero.x);
+	    wmove(cw, unc(hero));
+	    waddch(cw, ch);
+	    hero = nh;
+	    wmove(cw, unc(hero));
+	    waddch(cw, PLAYER);
+    }
+}
+
+/*
+ * Called to illuminate a room.
+ * If it is dark, remove anything that might move.
+ */
+
+void
+light(coord *cp)
+{
+    struct room *rp;
+    int j, k;
+    int ch;
+    int rch;
+    struct linked_list *item;
+
+    if ((rp = roomin(cp)) != NULL && !on(player, ISBLIND))
+    {
+	for (j = 0; j < rp->r_max.y; j++)
+	{
+	    for (k = 0; k < rp->r_max.x; k++)
+	    {
+		ch = show(rp->r_pos.y + j, rp->r_pos.x + k);
+		wmove(cw, rp->r_pos.y + j, rp->r_pos.x + k);
+		/*
+		 * Figure out how to display a secret door
+		 */
+		if (ch == SECRETDOOR)
+		{
+		    if (j == 0 || j == rp->r_max.y - 1)
+			ch = '-';
+		    else
+			ch = '|';
+		}
+		/*
+		 * If the room is a dark room, we might want to remove
+		 * monsters and the like from it (since they might
+		 * move)
+		 */
+		if (isupper(ch))
+		{
+		    item = wake_monster(rp->r_pos.y+j, rp->r_pos.x+k);
+		    if (((struct thing *) ldata(item))->t_oldch == ' ')
+			if (!(rp->r_flags & ISDARK))
+			    ((struct thing *) ldata(item))->t_oldch =
+				mvwinch(stdscr, rp->r_pos.y+j, rp->r_pos.x+k);
+		}
+		if (rp->r_flags & ISDARK)
+		{
+		    rch = mvwinch(cw, rp->r_pos.y+j, rp->r_pos.x+k);
+		    switch (rch)
+		    {
+			case DOOR:
+			case STAIRS:
+			case TRAP:
+			case '|':
+			case '-':
+			case ' ':
+			    ch = rch;
+			when FLOOR:
+			    ch = (on(player, ISBLIND) ? FLOOR : ' ');
+			otherwise:
+			    ch = ' ';
+		    }
+		}
+		mvwaddch(cw, rp->r_pos.y+j, rp->r_pos.x+k, ch);
+	    }
+	}
+    }
+}
+
+/*
+ * show:
+ *	returns what a certain thing will display as to the un-initiated
+ */
+
+int
+show(int y, int x)
+{
+    int ch = winat(y, x);
+    struct linked_list *it;
+    struct thing *tp;
+
+    if (ch == TRAP)
+	return (trap_at(y, x)->tr_flags & ISFOUND) ? TRAP : FLOOR;
+    else if (ch == 'M' || ch == 'I')
+    {
+	if ((it = find_mons(y, x)) == NULL)
+	    fatal("Can't find monster in show");
+	tp = (struct thing *) ldata(it);
+	if (ch == 'M')
+	    ch = tp->t_disguise;
+	/*
+	 * Hide invisible monsters
+	 */
+	else if (off(player, CANSEE))
+	    ch = mvwinch(stdscr, y, x);
+    }
+    return ch;
+}
+
+/*
+ * be_trapped:
+ *	The guy stepped on a trap.... Make him pay.
+ */
+
+int
+be_trapped(coord *tc)
+{
+    struct trap *tp;
+    int ch;
+
+    tp = trap_at(tc->y, tc->x);
+    count = running = FALSE;
+    mvwaddch(cw, tp->tr_pos.y, tp->tr_pos.x, TRAP);
+    tp->tr_flags |= ISFOUND;
+    switch (ch = tp->tr_type)
+    {
+	case TRAPDOOR:
+	    level++;
+	    new_level();
+	    msg("You fell into a trap!");
+	when BEARTRAP:
+	    no_move += BEARTIME;
+	    msg("You are caught in a bear trap");
+	when SLEEPTRAP:
+	    no_command += SLEEPTIME;
+	    msg("A strange white mist envelops you and you fall asleep");
+	when ARROWTRAP:
+	    if (swing(pstats.s_lvl-1, pstats.s_arm, 1))
+	    {
+		msg("Oh no! An arrow shot you");
+		if ((pstats.s_hpt -= roll(1, 6)) <= 0)
+		{
+		    msg("The arrow killed you.");
+		    death('a');
+		}
+	    }
+	    else
+	    {
+		struct linked_list *item;
+		struct object *arrow;
+
+		msg("An arrow shoots past you.");
+		item = new_item(sizeof *arrow);
+		arrow = (struct object *) ldata(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; /* "arrow bug" FIX */
+		fall(item, FALSE);
+	    }
+	when TELTRAP:
+	    teleport();
+	when DARTTRAP:
+	    if (swing(pstats.s_lvl+1, pstats.s_arm, 1))
+	    {
+		msg("A small dart just hit you in the shoulder");
+		if ((pstats.s_hpt -= roll(1, 4)) <= 0)
+		{
+		    msg("The dart killed you.");
+		    death('d');
+		}
+		if (!ISWEARING(R_SUSTSTR))
+		    chg_str(-1);
+	    }
+	    else
+		msg("A small dart whizzes by your ear and vanishes.");
+    }
+    flush_type();	/* flush typeahead */
+    return(ch);
+}
+
+/*
+ * trap_at:
+ *	find the trap at (y,x) on screen.
+ */
+
+struct trap *
+trap_at(int y, int x)
+{
+    struct trap *tp, *ep;
+
+    ep = &traps[ntraps];
+    for (tp = traps; tp < ep; tp++)
+	if (tp->tr_pos.y == y && tp->tr_pos.x == x)
+	    break;
+    if (tp == ep)
+    {
+	sprintf(prbuf, "Trap at %d,%d not in array", y, x);
+	fatal(prbuf);
+    }
+    return tp;
+}
+
+/*
+ * rndmove:
+ *	move in a random direction if the monster/person is confused
+ */
+
+coord *
+rndmove(struct thing *who)
+{
+    int x, y;
+    int ch;
+    int ex, ey, nopen = 0;
+    struct linked_list *item;
+    struct object *obj;
+    static coord ret;  /* what we will be returning */
+    static coord dest;
+
+    ret = who->t_pos;
+    /*
+     * Now go through the spaces surrounding the player and
+     * set that place in the array to true if the space can be
+     * moved into
+     */
+    ey = ret.y + 1;
+    ex = ret.x + 1;
+    for (y = who->t_pos.y - 1; y <= ey; y++)
+	if (y >= 0 && y < LINES)
+	    for (x = who->t_pos.x - 1; x <= ex; x++)
+	    {
+		if (x < 0 || x >= COLS)
+		    continue;
+		ch = winat(y, x);
+		if (step_ok(ch))
+		{
+		    dest.y = y;
+		    dest.x = x;
+		    if (!diag_ok(&who->t_pos, &dest))
+			continue;
+		    if (ch == SCROLL)
+		    {
+			item = NULL;
+			for (item = lvl_obj; item != NULL; item = next(item))
+			{
+			    obj = (struct object *) ldata(item);
+			    if (y == obj->o_pos.y && x == obj->o_pos.x)
+				break;
+			}
+			if (item != NULL && obj->o_which == S_SCARE)
+			    continue;
+		    }
+		    if (rnd(++nopen) == 0)
+			ret = dest;
+		}
+	    }
+    return &ret;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rogue3/newlevel.c	Tue Oct 13 13:33:34 2009 +0000
@@ -0,0 +1,176 @@
+/*
+ * new_level:
+ *	Dig and draw a new level
+ *
+ * @(#)new_level.c	3.7 (Berkeley) 6/2/81
+ *
+ * Rogue: Exploring the Dungeons of Doom
+ * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
+ * All rights reserved.
+ *
+ * See the file LICENSE.TXT for full copyright and licensing information.
+ */
+
+#include "curses.h"
+#include "rogue.h"
+
+#include <string.h>
+
+void
+new_level()
+{
+    int rm, i;
+    int ch = 0;
+    coord stairs;
+
+    if (level > max_level)
+	max_level = level;
+    wclear(cw);
+    wclear(mw);
+    clear();
+    status();
+    /*
+     * Free up the monsters on the last level
+     */
+    free_list(mlist);
+    do_rooms();				/* Draw rooms */
+    do_passages();			/* Draw passages */
+    no_food++;
+    put_things();			/* Place objects (if any) */
+    /*
+     * Place the staircase down.
+     */
+    do {
+        rm = rnd_room();
+	rnd_pos(&rooms[rm], &stairs);
+    } until (winat(stairs.y, stairs.x) == FLOOR);
+    addch(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);
+	    } until (winat(stairs.y, stairs.x) == FLOOR);
+	    switch(rnd(6))
+	    {
+		case 0: ch = TRAPDOOR;
+		when 1: ch = BEARTRAP;
+		when 2: ch = SLEEPTRAP;
+		when 3: ch = ARROWTRAP;
+		when 4: ch = TELTRAP;
+		when 5: ch = DARTTRAP;
+	    }
+	    addch(TRAP);
+	    traps[i].tr_type = ch;
+	    traps[i].tr_flags = 0;
+	    traps[i].tr_pos = stairs;
+	}
+    }
+    do
+    {
+	rm = rnd_room();
+	rnd_pos(&rooms[rm], &hero);
+    }
+    until(winat(hero.y, hero.x) == FLOOR);
+    light(&hero);
+    wmove(cw, hero.y, hero.x);
+    waddch(cw, PLAYER);
+}
+
+/*
+ * Pick a room that is really there
+ */
+
+int
+rnd_room()
+{
+    int rm;
+
+    do
+    {
+	rm = rnd(MAXROOMS);
+    } while (rooms[rm].r_flags & ISGONE);
+    return rm;
+}
+
+/*
+ * put_things:
+ *	put potions and scrolls on this level
+ */
+
+void
+put_things()
+{
+    int i;
+    struct linked_list *item;
+    struct object *cur;
+    int rm;
+    coord tp;
+
+    /*
+     * Throw away stuff left on the previous level (if anything)
+     */
+    free_list(lvl_obj);
+    /*
+     * 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;
+    /*
+     * 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
+	     */
+	    item = new_thing();
+	    attach(lvl_obj, item);
+	    cur = (struct object *) ldata(item);
+	    /*
+	     * Put it somewhere
+	     */
+	    do {
+	        rm = rnd_room();
+		rnd_pos(&rooms[rm], &tp);
+	    } until (winat(tp.y, tp.x) == FLOOR);
+	    mvaddch(tp.y, tp.x, cur->o_type);
+	    cur->o_pos = tp;
+	}
+    /*
+     * If he is really deep in the dungeon and he hasn't found the
+     * amulet yet, put it somewhere on the ground
+     */
+    if (level > 25 && !amulet)
+    {
+	item = new_item(sizeof *cur);
+	attach(lvl_obj, item);
+	cur = (struct object *) ldata(item);
+	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);
+	mvaddch(tp.y, tp.x, cur->o_type);
+	cur->o_pos = tp;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rogue3/options.c	Tue Oct 13 13:33:34 2009 +0000
@@ -0,0 +1,353 @@
+/*
+ * 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	3.3 (Berkeley) 5/25/81
+ *
+ * Rogue: Exploring the Dungeons of Doom
+ * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
+ * All rights reserved.
+ *
+ * See the file LICENSE.TXT for full copyright and licensing information.
+ */
+
+#include <stdlib.h>
+#include "curses.h"
+#include <ctype.h>
+#include <string.h>
+#include "machdep.h"
+#include "rogue.h"
+
+#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 */
+    void	*o_opt;		/* pointer to thing to set */
+    void	(*o_putfunc)();	/* function to print value */
+    int		(*o_getfunc)();	/* function to get value interactively */
+};
+
+typedef struct optstruct	OPTION;
+
+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	},
+    {"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		}
+};
+
+/*
+ * print and then set options from the terminal
+ */
+void
+option()
+{
+    OPTION	*op;
+    int	retval;
+
+    wclear(hw);
+    touchwin(hw);
+    /*
+     * Display current values of options
+     */
+    for (op = optlist; op <= &optlist[NUM_OPTS-1]; 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-1]; 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, (int)(op - optlist) - 1, 0);
+		op -= 2;
+	    }
+	    else	/* trying to back up beyond the top */
+	    {
+		beep();
+		wmove(hw, 0, 0);
+		op--;
+	    }
+    }
+    /*
+     * Switch back to original screen
+     */
+    mvwaddstr(hw, LINES-1, 0, "--Press space to continue--");
+    draw(hw);
+    wait_for(hw,' ');
+    clearok(cw, TRUE);
+    touchwin(cw);
+    after = FALSE;
+}
+
+/*
+ * put out a boolean
+ */
+void
+put_bool(void *b)
+{
+    waddstr(hw, *(int *)b ? "True" : "False");
+}
+
+/*
+ * put out a string
+ */
+void
+put_str(void *str)
+{
+    waddstr(hw, (char *) str);
+}
+
+/*
+ * allow changing a boolean option and print it out
+ */
+
+int
+get_bool(void *vp, WINDOW *win)
+{
+    int *bp = (int *) vp;
+    int oy, ox;
+    int op_bad;
+
+    op_bad = TRUE;
+    getyx(win, oy, ox);
+    waddstr(win, *bp ? "True" : "False");
+    while(op_bad)	
+    {
+	wmove(win, oy, ox);
+	draw(win);
+	switch (readchar(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;
+}
+
+/*
+ * set a string option
+ */
+int
+get_str(void *vopt, WINDOW *win)
+{
+    char *opt = (char *) vopt;
+    char *sp;
+    int c, oy, ox;
+    char buf[80];
+
+    draw(win);
+    getyx(win, oy, ox);
+    /*
+     * loop reading in the string, and put it in a temporary buffer
+     */
+    for (sp = buf;
+	(c = readchar(win)) != '\n' && c != '\r' && c != '\033' && c != '\007';
+	wclrtoeol(win), draw(win))
+    {
+	if (c == -1)
+	    continue;
+	else if (c == md_erasechar())	/* process erase character */
+	{
+	    if (sp > buf)
+	    {
+		int i;
+		int myx, myy;
+
+		sp--;
+
+		for (i = (int) strlen(unctrl(*sp)); i; i--)
+		{
+		    getyx(win,myy,myx);
+		    if ((myx == 0)&& (myy > 0))
+		    {
+			wmove(win,myy-1,getmaxx(win)-1);
+			waddch(win,' ');
+			wmove(win,myy-1,getmaxx(win)-1);
+		    }
+		    else
+			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 == '-')
+		break;
+	    else if (c == '~')
+	    {
+		strcpy(buf, home);
+		waddstr(win, home);
+		sp += strlen(home);
+		continue;
+	    }
+
+	if ((sp - buf) < 78) /* Avoid overflow */
+	{
+	    *sp++ = c;
+	    waddstr(win, unctrl(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');
+    draw(win);
+    if (win == cw)
+	mpos += (int)(sp - buf);
+    if (c == '-')
+	return MINUS;
+    else if (c == '\033' || c == '\007')
+	return QUIT;
+    else
+	return NORM;
+}
+
+/*
+ * 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.
+ */
+
+void
+parse_opts(char *str)
+{
+    char *sp;
+    OPTION *op;
+    int len;
+
+    while (*str)
+    {
+	/*
+	 * Get option name
+	 */
+	for (sp = str; isalpha(*sp); sp++)
+	    continue;
+	len = (int)(sp - str);
+	/*
+	 * Look it up and deal with it
+	 */
+	for (op = optlist; op <= &optlist[NUM_OPTS-1]; op++)
+	    if (EQSTR(str, op->o_name, len))
+	    {
+		if (op->o_putfunc == put_bool)	/* if option is a boolean */
+		    *(int *)op->o_opt = TRUE;
+		else				/* string option */
+		{
+		    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))
+	    {
+		*(int *)op->o_opt = FALSE;
+		break;
+	    }
+
+	/*
+	 * skip to start of next option name
+	 */
+	while (*sp && !isalpha(*sp))
+	    sp++;
+	str = sp;
+    }
+}
+
+/*
+ * copy string using unctrl for things
+ */
+void
+strucpy(char *s1, char *s2, size_t len)
+{
+    const char *sp;
+
+    while (len--)
+    {
+    	sp = unctrl(*s2);
+	strcpy(s1, sp);
+	s1 += strlen(sp);
+	s2++;
+    }
+    *s1 = '\0';
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rogue3/pack.c	Tue Oct 13 13:33:34 2009 +0000
@@ -0,0 +1,399 @@
+/*
+ * Routines to deal with the pack
+ *
+ * @(#)pack.c	3.6 (Berkeley) 6/15/81
+ *
+ * Rogue: Exploring the Dungeons of Doom
+ * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
+ * All rights reserved.
+ *
+ * See the file LICENSE.TXT for full copyright and licensing information.
+ */
+
+#include "curses.h"
+#include <ctype.h>
+#include "rogue.h"
+
+/*
+ * 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.
+ */
+void
+add_pack(struct linked_list *item, int silent)
+{
+    struct linked_list *ip, *lp;
+    struct object *obj, *op;
+    int exact, from_floor;
+
+    if (item == NULL)
+    {
+	from_floor = TRUE;
+	if ((item = find_obj(hero.y, hero.x)) == NULL)
+	    return;
+    }
+    else
+	from_floor = FALSE;
+    obj = (struct object *) ldata(item);
+    /*
+     * 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.
+     */
+    if (obj->o_group)
+    {
+	for (ip = pack; ip != NULL; ip = next(ip))
+	{
+	    op = (struct object *) ldata(ip);
+	    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, item);
+		    mvaddch(hero.y, hero.x,
+			(roomin(&hero) == NULL ? PASSAGE : FLOOR));
+		}
+		discard(item);
+		item = ip;
+		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)
+	{
+	    msg("The scroll turns to dust as you pick it up.");
+	    detach(lvl_obj, item);
+	    mvaddch(hero.y, hero.x, FLOOR);
+	    return;
+	}
+	else
+	    obj->o_flags |= ISFOUND;
+
+    inpack++;
+    if (from_floor)
+    {
+	detach(lvl_obj, item);
+	mvaddch(hero.y, hero.x, (roomin(&hero) == NULL ? PASSAGE : FLOOR));
+    }
+    /*
+     * Search for an object of the same type
+     */
+    exact = FALSE;
+    for (ip = pack; ip != NULL; ip = next(ip))
+    {
+	op = (struct object *) ldata(ip);
+	if (obj->o_type == op->o_type)
+	    break;
+    }
+    if (ip == NULL)
+    {
+	/*
+	 * Put it at the end of the pack since it is a new type
+	 */
+	for (ip = pack; ip != NULL; ip = next(ip))
+	{
+	    op = (struct object *) ldata(ip);
+	    if (op->o_type != FOOD)
+		break;
+	    lp = ip;
+	}
+    }
+    else
+    {
+	/*
+	 * Search for an object which is exactly the same
+	 */
+	while (ip != NULL && op->o_type == obj->o_type)
+	{
+	    if (op->o_which == obj->o_which)
+	    {
+		exact = TRUE;
+		break;
+	    }
+	    lp = ip;
+	    if ((ip = next(ip)) == NULL)
+		break;
+	    op = (struct object *) ldata(ip);
+	}
+    }
+    if (ip == NULL)
+    {
+	/*
+	 * Didn't find an exact match, just stick it here
+	 */
+	if (pack == NULL)
+	    pack = item;
+	else
+	{
+	    lp->l_next = item;
+	    item->l_prev = lp;
+	    item->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++;
+	    discard(item);
+	    item = ip;
+	    goto picked_up;
+	}
+	if ((item->l_prev = prev(ip)) != NULL)
+	    item->l_prev->l_next = item;
+	else
+	    pack = item;
+	item->l_next = ip;
+	ip->l_prev = item;
+    }
+picked_up:
+    /*
+     * Notify the user
+     */
+    obj = (struct object *) ldata(item);
+    if (notify && !silent)
+    {
+	if (!terse)
+	    addmsg("You now have ");
+	msg("%s (%c)", inv_name(obj, !terse), pack_char(obj));
+    }
+    if (obj->o_type == AMULET)
+	amulet = TRUE;
+}
+
+/*
+ * inventory:
+ *	list what is in the pack
+ */
+int
+inventory(struct linked_list *list, int type)
+{
+    struct object *obj;
+    int ch;
+    int n_objs;
+    char inv_temp[80];
+
+    n_objs = 0;
+    for (ch = 'a'; list != NULL; ch++, list = next(list))
+    {
+	obj = (struct object *) ldata(list);
+	if (type && type != obj->o_type && !(type == CALLABLE &&
+	    (obj->o_type == SCROLL || obj->o_type == POTION ||
+	     obj->o_type == RING || obj->o_type == STICK)))
+		continue;
+	switch (n_objs++)
+	{
+	    /*
+	     * For the first thing in the inventory, just save the string
+	     * in case there is only one.
+	     */
+	    case 0:
+		sprintf(inv_temp, "%c) %s", ch, inv_name(obj, FALSE));
+		break;
+	    /*
+	     * If there is more than one, clear the screen, print the
+	     * saved message and fall through to ...
+	     */
+	    case 1:
+		if (slow_invent)
+		    msg(inv_temp);
+		else
+		{
+		    wclear(hw);
+		    waddstr(hw, inv_temp);
+		    waddch(hw, '\n');
+		}
+	    /*
+	     * Print the line for this object
+	     */
+	    default:
+		if (slow_invent)
+		    msg("%c) %s", ch, inv_name(obj, FALSE));
+		else
+		    wprintw(hw, "%c) %s\n", ch, inv_name(obj, 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;
+    }
+    if (n_objs == 1)
+    {
+	msg(inv_temp);
+	return TRUE;
+    }
+    if (!slow_invent)
+    {
+	mvwaddstr(hw, LINES-1, 0, "--Press space to continue--");
+	draw(hw);
+	wait_for(hw,' ');
+	clearok(cw, TRUE);
+	touchwin(cw);
+    }
+    return TRUE;
+}
+
+/*
+ * pick_up:
+ *	Add something to characters pack.
+ */
+void
+pick_up(int ch)
+{
+    switch(ch)
+    {
+	case GOLD:
+	    money();
+	    break;
+	default:
+	    debug("Where did you pick that up???");
+	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
+ */
+void
+picky_inven()
+{
+    struct linked_list *item;
+    int ch, mch;
+
+    if (pack == NULL)
+	msg("You aren't carrying anything");
+    else if (next(pack) == NULL)
+	msg("a) %s", inv_name((struct object *) ldata(pack), FALSE));
+    else
+    {
+	msg(terse ? "Item: " : "Which item do you wish to inventory: ");
+	mpos = 0;
+	if ((mch = readchar(cw)) == ESCAPE)
+	{
+	    msg("");
+	    return;
+	}
+	for (ch = 'a', item = pack; item != NULL; item = next(item), ch++)
+	    if (ch == mch)
+	    {
+		msg("%c) %s",ch,inv_name((struct object *) ldata(item), FALSE));
+		return;
+	    }
+	if (!terse)
+	    msg("'%s' not in pack", unctrl(mch));
+	msg("Range is 'a' to '%c'", --ch);
+    }
+}
+
+/*
+ * get_item:
+ *	pick something out of a pack for a purpose
+ */
+struct linked_list *
+get_item(char *purpose, int type)
+{
+    struct linked_list *obj;
+    int 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(cw);
+	    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;
+}
+
+int
+pack_char(struct object *obj)
+{
+    struct linked_list *item;
+    int c;
+
+    c = 'a';
+    for (item = pack; item != NULL; item = next(item))
+	if ((struct object *) ldata(item) == obj)
+	    return c;
+	else
+	    c++;
+    return 'z';
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rogue3/passages.c	Tue Oct 13 13:33:34 2009 +0000
@@ -0,0 +1,289 @@
+/*
+ * Draw the connecting passages
+ *
+ * @(#)passages.c	3.4 (Berkeley) 6/15/81
+ *
+ * Rogue: Exploring the Dungeons of Doom
+ * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
+ * All rights reserved.
+ *
+ * See the file LICENSE.TXT for full copyright and licensing information.
+ */
+
+#include <stdlib.h>
+#include "curses.h"
+#include "rogue.h"
+
+/*
+ * do_passages:
+ *	Draw all the passages on a level.
+ */
+
+void
+do_passages()
+{
+    struct rdes *r1, *r2;
+    int i, j;
+    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 = (int)(r1 - rdes);
+	    j = (int)(r2 - rdes);
+	    conn(i, j);
+	    r1->isconn[j] = TRUE;
+	    r2->isconn[i] = TRUE;
+	    roomcount++;
+	}
+    } while (roomcount < MAXROOMS);
+
+    /*
+     * attempt to add passages to the graph a random number of times so
+     * that there isn't just one unique passage through it.
+     */
+    for (roomcount = rnd(5); roomcount > 0; roomcount--)
+    {
+	r1 = &rdes[rnd(MAXROOMS)];	/* a random room to look from */
+	/*
+	 * find an adjacent room not already connected
+	 */
+	j = 0;
+	for (i = 0; i < MAXROOMS; i++)
+	    if (r1->conn[i] && !r1->isconn[i] && rnd(++j) == 0)
+		r2 = &rdes[i];
+	/*
+	 * if there is one, connect it and look for the next added
+	 * passage
+	 */
+	if (j != 0)
+	{
+	    i = (int)(r1 - rdes);
+	    j = (int)(r2 - rdes);
+	    conn(i, j);
+	    r1->isconn[j] = TRUE;
+	    r2->isconn[i] = TRUE;
+	}
+    }
+}
+
+/*
+ * conn:
+ *	Draw a corridor from a room in a certain direction.
+ */
+
+void
+conn(int r1, int r2)
+{
+    struct room *rpf, *rpt;
+    int rmt;
+    int distance, turn_spot, turn_distance;
+    int rm;
+    int direc;
+    coord pdelta, curr, turn_delta, spos, epos;
+
+    if (r1 < r2)
+    {
+	rm = r1;
+	if (r1 + 1 == r2)
+	    direc = 'r';
+	else
+	    direc = 'd';
+    }
+    else
+    {
+	rm = r2;
+	if (r2 + 1 == r1)
+	    direc = 'r';
+	else
+	    direc = 'd';
+    }
+    rpf = &rooms[rm];
+    /*
+     * Set up the movement variables, in two cases:
+     * first drawing one down.
+     */
+    if (direc == 'd')
+    {
+	rmt = rm + 3;				/* room # of dest */
+	rpt = &rooms[rmt];			/* room pointer of dest */
+	pdelta.x = 0;				/* direction of move */
+	pdelta.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];
+	pdelta.x = 1;
+	pdelta.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;
+    }
+    else
+	fatal("error in connection tables");
+    /*
+     * 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
+    {
+	cmov(spos);
+	addch('#');
+    }
+    if (!(rpt->r_flags & ISGONE)) door(rpt, &epos);
+    else
+    {
+	cmov(epos);
+	addch('#');
+    }
+    /*
+     * Get ready to move...
+     */
+    curr.x = spos.x;
+    curr.y = spos.y;
+    while(distance)
+    {
+	/*
+	 * Move to new position
+	 */
+	curr.x += pdelta.x;
+	curr.y += pdelta.y;
+	/*
+	 * Check if we are at the turn place, if so do the turn
+	 */
+	if (distance == turn_spot && turn_distance > 0)
+	    while(turn_distance--)
+	    {
+		cmov(curr);
+		addch(PASSAGE);
+		curr.x += turn_delta.x;
+		curr.y += turn_delta.y;
+	    }
+	/*
+	 * Continue digging along
+	 */
+	cmov(curr);
+	addch(PASSAGE);
+	distance--;
+    }
+    curr.x += pdelta.x;
+    curr.y += pdelta.y;
+    if (!ce(curr, epos))
+	msg("Warning, connectivity problem on this level.");
+}
+
+/*
+ * Add a door or possibly a secret door
+ * also enters the door in the exits array of the room.
+ */
+
+void
+door(struct room *rm, coord *cp)
+{
+    cmov(*cp);
+    addch( (rnd(10) < level - 1 && rnd(100) < 20 ? SECRETDOOR : DOOR) );
+    rm->r_exit[rm->r_nexits++] = *cp;
+}
+
+/*
+ * add_pass:
+ *	add the passages to the current window (wizard command)
+ */
+
+void
+add_pass()
+{
+    int y, x, ch;
+
+    for (y = 1; y < LINES - 2; y++)
+	for (x = 0; x < COLS; x++)
+	    if ((ch=mvinch(y, x)) == PASSAGE || ch == DOOR || ch == SECRETDOOR)
+		mvwaddch(cw, y, x, ch);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rogue3/potions.c	Tue Oct 13 13:33:34 2009 +0000
@@ -0,0 +1,212 @@
+/*
+ * 	@(#)potions.c	3.1	3.1	5/7/81
+ * Function(s) for dealing with potions
+ *
+ * Rogue: Exploring the Dungeons of Doom
+ * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
+ * All rights reserved.
+ *
+ * See the file LICENSE.TXT for full copyright and licensing information.
+ */
+
+#include "curses.h"
+#include <stdlib.h>
+#include <string.h>
+#include "rogue.h"
+
+void
+quaff()
+{
+    struct object *obj;
+    struct linked_list *item, *titem;
+    struct thing *th;
+    char buf[80];
+
+    item = get_item("quaff", POTION);
+    /*
+     * Make certain that it is somethings that we want to drink
+     */
+    if (item == NULL)
+	return;
+    obj = (struct object *) ldata(item);
+    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:
+	    if (off(player, ISHUH))
+		msg("Wait, what's going on here. Huh? What? Who?");
+
+	    if (on(player, ISHUH))
+		lengthen(unconfuse, rnd(8)+HUHDURATION);
+	    else
+	        fuse(unconfuse, 0, rnd(8)+HUHDURATION, AFTER);
+
+	    player.t_flags |= ISHUH;
+	    p_know[P_CONFUSE] = TRUE;
+	when P_POISON:
+	    if (!ISWEARING(R_SUSTSTR))
+	    {
+		chg_str(-(rnd(3)+1));
+		msg("You feel very sick now.");
+	    }
+	    else
+		msg("You feel momentarily sick");
+	    p_know[P_POISON] = TRUE;
+	when P_HEALING:
+	    if ((pstats.s_hpt += roll(pstats.s_lvl, 4)) > max_hp)
+		pstats.s_hpt = ++max_hp;
+	    msg("You begin to feel better.");
+	    sight();
+	    p_know[P_HEALING] = TRUE;
+	when P_STRENGTH:
+	    msg("You feel stronger, now.  What bulging muscles!");
+	    chg_str(1);
+	    p_know[P_STRENGTH] = TRUE;
+	when P_MFIND:
+	    /*
+	     * Potion of monster detection, if there are monters, detect them
+	     */
+	    if (mlist != NULL)
+	    {
+		wclear(hw);
+		overwrite(mw, hw);
+		show_win(hw,
+		    "You begin to sense the presence of monsters.--More--");
+		p_know[P_MFIND] = TRUE;
+	    }
+	    else
+		msg("You have a strange feeling for a moment, then it passes.");
+	when P_TFIND:
+	    /*
+	     * Potion of magic detection.  Show the potions and scrolls
+	     */
+	    if (lvl_obj != NULL)
+	    {
+		struct linked_list *mobj;
+		struct object *tp;
+		int show;
+
+		show = FALSE;
+		wclear(hw);
+		for (mobj = lvl_obj; mobj != NULL; mobj = next(mobj))
+		{
+		    tp = (struct object *) ldata(mobj);
+		    if (is_magic(tp))
+		    {
+			show = TRUE;
+			mvwaddch(hw, tp->o_pos.y, tp->o_pos.x, MAGIC);
+		    }
+		    p_know[P_TFIND] = TRUE;
+		}
+		for (titem = mlist; titem != NULL; titem = next(titem))
+		{
+		    struct linked_list *pitem;
+
+		    th = (struct thing *) ldata(titem);
+		    for (pitem = th->t_pack; pitem != NULL; pitem = next(pitem))
+		    {
+			if (is_magic(OBJPTR(pitem)))
+			{
+			    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:
+	    msg("You can't move.");
+	    no_command = HOLDTIME;
+	    p_know[P_PARALYZE] = TRUE;
+	when P_SEEINVIS:
+	    msg("This potion tastes like %s juice.", fruit);
+	    if (off(player, CANSEE))
+	    {
+		player.t_flags |= CANSEE;
+		fuse(unsee, 0, SEEDURATION, AFTER);
+		light(&hero);
+	    }
+	    sight();
+	when P_RAISE:
+	    msg("You suddenly feel much more skillful");
+	    p_know[P_RAISE] = TRUE;
+	    raise_level();
+	when P_XHEAL:
+	    if ((pstats.s_hpt += roll(pstats.s_lvl, 8)) > max_hp)
+		pstats.s_hpt = ++max_hp;
+	    msg("You begin to feel much better.");
+	    p_know[P_XHEAL] = TRUE;
+	    sight();
+	when P_HASTE:
+	    add_haste(TRUE);
+	    msg("You feel yourself moving much faster.");
+	    p_know[P_HASTE] = TRUE;
+	when P_RESTORE:
+	    msg("Hey, this tastes great.  It make you feel warm all over.");
+	    if (pstats.s_str.st_str < max_stats.s_str.st_str ||
+		(pstats.s_str.st_str == 18 &&
+		 pstats.s_str.st_add < max_stats.s_str.st_add))
+	    pstats.s_str = max_stats.s_str;
+	when P_BLIND:
+	    msg("A cloak of darkness falls around you.");
+	    if (off(player, ISBLIND))
+	    {
+		player.t_flags |= ISBLIND;
+		fuse(sight, 0, SEEDURATION, AFTER);
+		look(FALSE);
+	    }
+	    p_know[P_BLIND] = TRUE;
+	when P_NOP:
+	    msg("This potion tastes extremely dull.");
+	otherwise:
+	    msg("What an odd tasting potion!");
+	    return;
+    }
+    status();
+    if (p_know[obj->o_which] && p_guess[obj->o_which])
+    {
+	free(p_guess[obj->o_which]);
+	p_guess[obj->o_which] = NULL;
+    }
+    else if (!p_know[obj->o_which] && askme && p_guess[obj->o_which] == NULL)
+    {
+	msg(terse ? "Call it: " : "What do you want to call it? ");
+	if (get_str(buf, cw) == NORM)
+	{
+	    p_guess[obj->o_which] = malloc((unsigned int) strlen(buf) + 1);
+	    if (p_guess[obj->o_which] != NULL)
+		strcpy(p_guess[obj->o_which], buf);
+	}
+    }
+    /*
+     * Throw the item away
+     */
+    inpack--;
+    if (obj->o_count > 1)
+	obj->o_count--;
+    else
+    {
+	detach(pack, item);
+        discard(item);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rogue3/readme36.html	Tue Oct 13 13:33:34 2009 +0000
@@ -0,0 +1,78 @@
+<html>
+<head>
+<title>ROGUE</title>
+</head>
+<body>
+
+<h1 align=center>ROGUE 3.6</h1>
+
+<hr>
+
+<h2>NAME</h2>
+<blockquote>
+	<p>rogue36 &minus; Exploring The Dungeons of Doom</p>
+</blockquote>
+
+<h2>SYNOPSIS</h2>
+<blockquote>
+	<p><b>rogue36</b> [ <i>save_file</i> ]</p>
+</blockquote>
+
+<h2>DESCRIPTION</h2>
+<blockquote>
+
+	<p align="justify"><u>Rogue</u> 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.</p>
+
+	<p align="justify">To get started you really only need to know two commands. 
+	The command ? will give you a list of the available commands and the command /
+	will identify the things you see on the screen.</p>
+
+	<p align="justify">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.</p>
+
+	<p align="justify">When the game ends, either by your death, when you quit, 
+	or if you (by some miracle) manage to win, <u>rogue</u> will give you a list 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.</p>
+
+	<p align="justify">For more detailed directions, read the document A Guide 
+	to the Dungeons of Doom.</p>
+
+</blockquote>
+
+<h2>FILES</h2>
+<blockquote>
+	<table border="0" id="table1">
+		<tr>
+			<td>rogue36.scr</td>
+			<td width="50">&nbsp;</td>
+			<td>Score file</td>
+		</tr>
+		<tr>
+			<td>rogue36.sav</td>
+			<td>&nbsp;</td>
+			<td>Default save file</td>
+		</tr>
+	</table>
+</blockquote>
+
+<h2>SEE ALSO</h2>
+<p>Michael C. Toy, <u>A Guide to the Dungeons of Doom</u></p>
+
+<h2>BUGS</h2>
+<p>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.</p>
+
+<h2>COPYRIGHT</h2>
+Rogue: Exploring the Dungeons of Doom<br>
+Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman <br>
+All rights reserved.
+
+</body>
+</html>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rogue3/rings.c	Tue Oct 13 13:33:34 2009 +0000
@@ -0,0 +1,213 @@
+/*
+ * routines dealing specifically with rings
+ *
+ * @(#)rings.c	3.17 (Berkeley) 6/15/81
+ *
+ * Rogue: Exploring the Dungeons of Doom
+ * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
+ * All rights reserved.
+ *
+ * See the file LICENSE.TXT for full copyright and licensing information.
+ */
+
+#include "curses.h"
+#include <stdlib.h>
+#include <string.h>
+#include "rogue.h"
+
+void
+ring_on()
+{
+    struct object *obj;
+    struct linked_list *item;
+    int ring;
+    str_t save_max;
+    char buf[80];
+
+    item = get_item("put on", RING);
+    /*
+     * Make certain that it is somethings that we want to wear
+     */
+    if (item == NULL)
+	return;
+    obj = (struct object *) ldata(item);
+    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:
+	    save_max = max_stats.s_str;
+	    chg_str(obj->o_ac);
+	    max_stats.s_str = save_max;
+	    break;
+	case R_SEEINVIS:
+	    player.t_flags |= CANSEE;
+	    light(&hero);
+	    mvwaddch(cw, hero.y, hero.x, PLAYER);
+	    break;
+	case R_AGGR:
+	    aggravate();
+	    break;
+    }
+    status();
+
+    if (obj->o_which >= MAXRINGS)
+        return;
+
+    if (r_know[obj->o_which] && r_guess[obj->o_which])
+    {
+	free(r_guess[obj->o_which]);
+	r_guess[obj->o_which] = NULL;
+    }
+    else if (!r_know[obj->o_which] && askme && r_guess[obj->o_which] == NULL)
+    {
+	mpos = 0;
+	msg(terse ? "Call it: " : "What do you want to call it? ");
+	if (get_str(buf, cw) == NORM)
+	{
+	    r_guess[obj->o_which] = malloc(strlen(buf) + 1);
+	    if (r_guess[obj->o_which] != NULL)
+		strcpy(r_guess[obj->o_which], buf);
+	}
+	msg("");
+    }
+}
+
+void
+ring_off()
+{
+    int ring;
+    struct object *obj;
+
+    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;
+    }
+    if (dropcheck(obj))
+	msg("Was wearing %s", inv_name(obj, TRUE));
+}
+
+int
+gethand()
+{
+    int c;
+
+    for (;;)
+    {
+	if (terse)
+	    msg("Left or Right ring? ");
+	else
+	    msg("Left hand or right hand? ");
+	if ((c = readchar(cw)) == 'l' || c == 'L')
+	    return LEFT;
+	else if (c == 'r' || c == 'R')
+	    return RIGHT;
+	else if (c == ESCAPE)
+	    return -1;
+	mpos = 0;
+	if (terse)
+	    msg("L or R");
+	else
+	    msg("Please type L or R");
+    }
+}
+
+/*
+ * how much food does this ring use up?
+ */
+int
+ring_eat(int hand)
+{
+    if (cur_ring[hand] == NULL)
+	return 0;
+    switch (cur_ring[hand]->o_which)
+    {
+	case R_REGEN:
+	    return 2;
+	case R_SUSTSTR:
+	    return 1;
+	case R_SEARCH:
+	    return (rnd(100) < 33);
+	case R_DIGEST:
+	    return -(rnd(100) < 50);
+	default:
+	    return 0;
+    }
+}
+
+/*
+ * print ring bonuses
+ */
+char *
+ring_num(struct object *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));
+	otherwise:
+	    return "";
+    }
+    return buf;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rogue3/rip.c	Tue Oct 13 13:33:34 2009 +0000
@@ -0,0 +1,407 @@
+/*
+ * File for the fun ends
+ * Death or a total win
+ *
+ * @(#)rip.c	3.13 (Berkeley) 6/16/81
+ *
+ * Rogue: Exploring the Dungeons of Doom
+ * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
+ * All rights reserved.
+ *
+ * See the file LICENSE.TXT for full copyright and licensing information.
+ */
+
+#include <stdlib.h>
+#include <errno.h>
+#include <time.h>
+#include <signal.h>
+#include <ctype.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <string.h>
+#include "curses.h"
+#include "machdep.h"
+#include "rogue.h"
+
+static char *rip[] = {
+"                       __________",
+"                      /          \\",
+"                     /    REST    \\",
+"                    /      IN      \\",
+"                   /     PEACE      \\",
+"                  /                  \\",
+"                  |                  |",
+"                  |                  |",
+"                  |   killed by a    |",
+"                  |                  |",
+"                  |       1980       |",
+"                 *|     *  *  *      | *",
+"         ________)/\\\\_//(\\/(/\\)/\\//\\/|_)_______",
+    0
+};
+
+char	*killname();
+
+/*
+ * death:
+ *	Do something really fun when he dies
+ */
+
+void
+death(int monst)
+{
+    char **dp = rip, *killer;
+    struct tm *lt;
+    time_t date;
+    char buf[80];
+
+    time(&date);
+    lt = localtime(&date);
+    clear();
+    move(8, 0);
+    while (*dp)
+	printw("%s\n", *dp++);
+    mvaddstr(14, 28-(((int)strlen(whoami)+1)/2), whoami);
+    purse -= purse/10;
+    sprintf(buf, "%d Au", purse);
+    mvaddstr(15, 28-(((int)strlen(buf)+1)/2), buf);
+    killer = killname(monst);
+    mvaddstr(17, 28-(((int)strlen(killer)+1)/2), killer);
+    mvaddstr(16, 33, vowelstr(killer));
+    sprintf(prbuf, "%4d", 1900+lt->tm_year);
+    mvaddstr(18, 26, prbuf);
+    move(LINES-1, 0);
+    draw(stdscr);
+    score(purse, 0, monst);
+    exit(0);
+}
+
+/*
+ * score -- figure score and post it.
+ */
+
+void
+open_score(void)
+{
+#ifdef SCOREFILE
+    char *scorefile = SCOREFILE;
+
+    if (scoreboard != NULL) {
+        rewind(scoreboard);
+        return;
+    }
+
+    scoreboard = fopen(scorefile, "r+");
+
+    if ((scoreboard == NULL) && (errno == ENOENT))
+    {
+        scoreboard = fopen(scorefile, "w+");
+        md_chmod(scorefile,0664);
+    }
+
+    if (scoreboard == NULL) {
+         fprintf(stderr, "Could not open %s for writing: %s\n", scorefile, strerror(errno));
+         fflush(stderr);
+    }
+#else
+    scoreboard = NULL;
+#endif
+}
+
+/* VARARGS2 */
+void
+score(int amount, int flags, int monst)
+{
+    static struct sc_ent {
+	int sc_score;
+	char sc_name[80];
+	int sc_flags;
+	int sc_level;
+	char sc_login[8];
+	int sc_monster;
+    } top_ten[10];
+    struct sc_ent *scp;
+    int i;
+    struct sc_ent *sc2;
+    FILE *outf;
+    char *killer;
+    int prflags = 0;
+    static char *reason[] = {
+	"killed",
+	"quit",
+	"A total winner",
+    };
+    char scoreline[100];
+    int rogue_ver = 0, scorefile_ver = 0;
+
+    /*
+     * Open file and read list
+     */
+
+    if (scoreboard == NULL)
+        return;
+    
+    outf = scoreboard;
+
+    for (scp = top_ten; scp <= &top_ten[9]; scp++)
+    {
+	scp->sc_score = 0;
+	for (i = 0; i < 80; i++)
+	    scp->sc_name[i] = rnd(255);
+	scp->sc_flags = RN;
+	scp->sc_level = RN;
+	scp->sc_monster = RN;
+	scp->sc_login[0] = '\0';
+    }
+
+    signal(SIGINT, SIG_DFL);
+    if ((flags != -1) && (flags != 1))
+    {
+	mvaddstr(LINES-1, 0, "[Press return to continue]");
+	draw(stdscr);
+	prbuf[0] = 0;
+	get_str(prbuf, stdscr);
+	endwin();
+    }
+    if (wizard)
+	if (strcmp(prbuf, "names") == 0)
+	    prflags = 1;
+	else if (strcmp(prbuf, "edit") == 0)
+	    prflags = 2;
+
+    md_lockfile(outf);
+
+    encread(scoreline, 100, outf);
+    (void) sscanf(scoreline, "R%d %d\n", &rogue_ver, &scorefile_ver);
+
+    if ((rogue_ver == 36) && (scorefile_ver == 2))
+        for(i = 0; i < 10; i++)
+	{
+	    encread(&top_ten[i].sc_name, 80, outf);
+	    encread(&top_ten[i].sc_login, 8, outf);
+	    encread(scoreline, 100, outf);
+	    (void) sscanf(scoreline, " %d %d %d %d \n",
+		&top_ten[i].sc_score,  &top_ten[i].sc_flags,
+		&top_ten[i].sc_level,  &top_ten[i].sc_monster);
+	}
+
+    /*
+     * Insert her in list if need be
+     */
+    if (!waswizard)
+    {
+	for (scp = top_ten; scp <= &top_ten[9]; scp++)
+	    if (amount > scp->sc_score)
+		break;
+	if (scp <= &top_ten[9])
+	{
+	    for (sc2 = &top_ten[9]; sc2 > scp; sc2--)
+		*sc2 = *(sc2-1);
+	    scp->sc_score = amount;
+	    strcpy(scp->sc_name, whoami);
+	    scp->sc_flags = flags;
+	    if (flags == 2)
+		scp->sc_level = max_level;
+	    else
+		scp->sc_level = level;
+	    scp->sc_monster = monst;
+	    strncpy(scp->sc_login, md_getusername(), 8);
+	}
+    }
+    /*
+     * Print the list
+     */
+    if (flags != -1)
+	printf("\n\n\n");
+    printf("Top Ten Adventurers:\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 a");
+		killer = killname(scp->sc_monster);
+		if (*killer == 'a' || *killer == 'e' || *killer == 'i' ||
+		    *killer == 'o' || *killer == 'u')
+			putchar('n');
+		printf(" %s", killer);
+	    }
+	    if (prflags == 1)
+	    {
+		printf(" (%s)", scp->sc_login);
+		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 < 80; 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");
+	}
+    }
+
+    /*
+     * Update the list file
+     */
+
+    rewind(outf);
+
+    strcpy(scoreline, "R36 2\n");
+    encwrite(scoreline, 100, outf);
+
+    for(i = 0; i < 10; i++)
+    {
+        encwrite(&top_ten[i].sc_name, 80, outf);
+        encwrite(&top_ten[i].sc_login, 8, outf);
+        sprintf(scoreline, " %d %d %d %d \n",
+            top_ten[i].sc_score,  top_ten[i].sc_flags,
+            top_ten[i].sc_level,  top_ten[i].sc_monster);
+        encwrite(scoreline, 100, outf);
+    }
+
+    md_unlockfile(outf);
+
+    fclose(outf);
+}
+
+void 
+total_winner()
+{
+    struct linked_list *item;
+    struct object *obj;
+    int worth = 0;
+    int c;
+    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(stdscr, ' ');
+    clear();
+    mvaddstr(0, 0, "   Worth  Item");
+    oldpurse = purse;
+    for (c = 'a', item = pack; item != NULL; c++, item = next(item))
+    {
+	obj = (struct object *) ldata(item);
+	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 BOW: worth = 75;
+		    when ARROW: worth = 1;
+		    when DAGGER: worth = 2;
+		    when ROCK: worth = 1;
+		    when TWOSWORD: worth = 30;
+		    when SLING: worth = 1;
+		    when DART: worth = 1;
+		    when CROSSBOW: worth = 15;
+		    when BOLT: worth = 1;
+		    when SPEAR: worth = 2;
+		    otherwise: worth = 0;
+		}
+		worth *= (1 + (10 * obj->o_hplus + 10 * obj->o_dplus));
+		worth *= obj->o_count;
+		obj->o_flags |= ISKNOW;
+	    when ARMOR:
+		switch (obj->o_which)
+		{
+		    case LEATHER: worth = 5;
+		    when RING_MAIL: worth = 30;
+		    when STUDDED_LEATHER: worth = 15;
+		    when SCALE_MAIL: worth = 3;
+		    when CHAIN_MAIL: worth = 75;
+		    when SPLINT_MAIL: worth = 80;
+		    when BANDED_MAIL: worth = 90;
+		    when PLATE_MAIL: worth = 400;
+		    otherwise: worth = 0;
+		}
+		if (obj->o_which >= MAXARMORS)
+                    break;
+		worth *= (1 + (10 * (a_class[obj->o_which] - obj->o_ac)));
+		obj->o_flags |= ISKNOW;
+	    when SCROLL:
+		s_know[obj->o_which] = TRUE;
+		worth = s_magic[obj->o_which].mi_worth;
+		worth *= obj->o_count;
+	    when POTION:
+		p_know[obj->o_which] = TRUE;
+		worth = p_magic[obj->o_which].mi_worth;
+		worth *= obj->o_count;
+	    when RING:
+		obj->o_flags |= ISKNOW;
+		r_know[obj->o_which] = TRUE;
+		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 * 20;
+			else
+			    worth = 50;
+	    when STICK:
+		obj->o_flags |= ISKNOW;
+		ws_know[obj->o_which] = TRUE;
+		worth = ws_magic[obj->o_which].mi_worth;
+		worth += 20 * obj->o_charges;
+	    when AMULET:
+		worth = 1000;
+	}
+	mvprintw(c - 'a' + 1, 0, "%c) %5d  %s", c, worth, inv_name(obj, FALSE));
+	purse += worth;
+    }
+    mvprintw(c - 'a' + 1, 0,"   %5d  Gold Peices          ", oldpurse);
+    refresh();
+    score(purse, 2, 0);
+    exit(0);
+}
+
+char *
+killname(int monst)
+{
+    if (isupper(monst))
+	return monsters[monst-'A'].m_name;
+    else
+	switch (monst)
+	{
+	    case 'a':
+		return "arrow";
+	    case 'd':
+		return "dart";
+	    case 'b':
+		return "bolt";
+	}
+    return("");
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rogue3/rogue.6	Tue Oct 13 13:33:34 2009 +0000
@@ -0,0 +1,58 @@
+.TH ROGUE 6
+.UC
+.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
+.ta 2i
+rogue36.scr                  Score file
+.br
+~/rogue36.sav                Default save file
+.DT
+.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.
+.SH COPYRIGHT
+Rogue: Exploring the Dungeons of Doom
+.br
+Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
+.br
+All rights reserved.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rogue3/rogue.h	Tue Oct 13 13:33:34 2009 +0000
@@ -0,0 +1,685 @@
+/*
+ * Rogue definitions and variable declarations
+ *
+ * @(#)rogue.h	3.38 (Berkeley) 6/15/81
+ *
+ * Rogue: Exploring the Dungeons of Doom
+ * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
+ * All rights reserved.
+ *
+ * See the file LICENSE.TXT for full copyright and licensing information.
+ */
+
+#include "mdport.h"
+
+/*
+ * Maximum number of different things
+ */
+#define MAXROOMS 9
+#define MAXTHINGS 9
+#define MAXOBJ 9
+#define MAXPACK 23
+#define MAXTRAPS 10
+#define	NUMTHINGS 7	/* number of types of things (scrolls, rings, etc.) */
+
+/*
+ * 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 next(ptr) (*ptr).l_next
+#define prev(ptr) (*ptr).l_prev
+#define ldata(ptr) (*ptr).l_data
+#define inroom(rp, cp) (\
+    (cp)->x <= (rp)->r_pos.x + ((rp)->r_max.x - 1) && (rp)->r_pos.x <= (cp)->x \
+ && (cp)->y <= (rp)->r_pos.y + ((rp)->r_max.y - 1) && (rp)->r_pos.y <= (cp)->y)
+#define winat(y, x) (mvwinch(mw,y,x)==' '?mvwinch(stdscr,y,x):winch(mw))
+#define debug if (wizard) msg
+#define RN (((seed = seed*11109+13849) & 0x7fff) >> 1)
+#define unc(cp) (cp).y, (cp).x
+#define cmov(xy) move((xy).y, (xy).x)
+#define DISTANCE(y1, x1, y2, x2) ((x2 - x1)*(x2 - x1) + (y2 - y1)*(y2 - y1))
+#define OBJPTR(what)    (struct object *)((*what).l_data)
+#define THINGPTR(what)  (struct thing *)((*what).l_data)
+#define when break;case
+#define otherwise break;default
+#define until(expr) while(!(expr))
+#define ce(a, b) ((a).x == (b).x && (a).y == (b).y)
+#define draw(window) wrefresh(window)
+#define hero player.t_pos
+#define pstats player.t_stats
+#define pack player.t_pack
+#define 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)
+#define off(thing, flag) (((thing).t_flags & flag) == 0)
+#undef  CTRL
+#define CTRL(ch) (ch & 037)
+#define ALLOC(x) malloc((unsigned int) x)
+#define FREE(x) free((char *) x)
+#define	EQSTR(a, b, c)	(strncmp(a, b, c) == 0)
+#define GOLDCALC (rnd(50 + 10 * level) + 2)
+#define ISRING(h,r) (cur_ring[h] != NULL && cur_ring[h]->o_which == r)
+#define ISWEARING(r) (ISRING(LEFT, r) || ISRING(RIGHT, r))
+#define newgrp() ++group
+#define o_charges o_ac
+#define ISMULT(type) (type == POTION || type == SCROLL || type == FOOD)
+
+/*
+ * Things that appear on the screens
+ */
+#define PASSAGE '#'
+#define DOOR '+'
+#define FLOOR '.'
+#define PLAYER '@'
+#define TRAP '^'
+#define TRAPDOOR '>'
+#define ARROWTRAP '{'
+#define SLEEPTRAP '$'
+#define BEARTRAP '}'
+#define TELTRAP '~'
+#define DARTTRAP '`'
+#define SECRETDOOR '&'
+#define STAIRS '%'
+#define GOLD '*'
+#define POTION '!'
+#define SCROLL '?'
+#define MAGIC '$'
+#define FOOD ':'
+#define WEAPON ')'
+#define ARMOR ']'
+#define AMULET ','
+#define RING '='
+#define STICK '/'
+#define CALLABLE -1
+
+/*
+ * Various constants
+ */
+#define	PASSWD		"mTBellIQOsLNA"
+#define BEARTIME 3
+#define SLEEPTIME 5
+#define HEALTIME 30
+#define HOLDTIME 2
+#define STPOS 0
+#define WANDERTIME 70
+#define BEFORE 1
+#define AFTER 2
+#define HUHDURATION 20
+#define SEEDURATION 850
+#define HUNGERTIME 1300
+#define MORETIME 150
+#define STOMACHSIZE 2000
+#define ESCAPE 27
+#define LEFT 0
+#define RIGHT 1
+#define BOLT_LENGTH 6
+
+/*
+ * Save against things
+ */
+#define VS_POISON 00
+#define VS_PARALYZATION 00
+#define VS_DEATH 00
+#define VS_PETRIFICATION 01
+#define VS_BREATH 02
+#define VS_MAGIC  03
+
+/*
+ * Various flag bits
+ */
+#define ISDARK	0000001
+#define ISCURSED 000001
+#define ISBLIND 0000001
+#define ISGONE	0000002
+#define ISKNOW  0000002
+#define ISRUN	0000004
+#define ISFOUND 0000010
+#define ISINVIS 0000020
+#define ISMEAN  0000040
+#define ISGREED 0000100
+#define ISBLOCK 0000200
+#define ISHELD  0000400
+#define ISHUH   0001000
+#define ISREGEN 0002000
+#define CANHUH  0004000
+#define CANSEE  0010000
+#define ISMISL  0020000
+#define ISCANC	0020000
+#define ISMANY  0040000
+#define ISSLOW	0040000
+#define ISHASTE 0100000
+
+/*
+ * 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_LIGHT 2
+#define S_HOLD 3
+#define S_SLEEP 4
+#define S_ARMOR 5
+#define S_IDENT 6
+#define S_SCARE 7
+#define S_GFIND 8
+#define S_TELEP 9
+#define S_ENCH 10
+#define S_CREATE 11
+#define S_REMOVE 12
+#define S_AGGR 13
+#define S_NOP 14
+#define S_GENOCIDE 15
+#define MAXSCROLLS 16
+
+/*
+ * Weapon types
+ */
+#define MACE 0
+#define SWORD 1
+#define BOW 2
+#define ARROW 3
+#define DAGGER 4
+#define ROCK 5
+#define TWOSWORD 6
+#define SLING 7
+#define DART 8
+#define CROSSBOW 9
+#define BOLT 10
+#define SPEAR 11
+#define MAXWEAPONS 12
+
+/*
+ * 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 MAXRINGS 13
+
+/*
+ * 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 {
+    int h_ch;
+    char *h_desc;
+};
+
+extern struct h_list helpstr[];
+
+/*
+ * Coordinate data type
+ */
+typedef struct {
+    int x;
+    int y;
+} coord;
+
+typedef struct {
+    int st_str;
+    int st_add;
+} str_t;
+
+/*
+ * Linked list data type
+ */
+struct linked_list {
+    struct linked_list *l_next;
+    struct linked_list *l_prev;
+    char *l_data;			/* Various structure pointers */
+};
+
+/*
+ * Stuff about magic items
+ */
+
+struct magic_item {
+    char mi_name[30];
+    int mi_prob;
+    int 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 */
+    int r_flags;			/* Info about the room */
+    int r_nexits;			/* Number of exits */
+    coord r_exit[4];			/* Where the exits are */
+};
+
+/*
+ * Array of all traps on this level
+ */
+struct trap {
+    coord tr_pos;			/* Where trap is */
+    int tr_type;			/* What kind of trap */
+    int tr_flags;			/* Info about trap (i.e. ISFOUND) */
+};
+
+extern struct trap  traps[MAXTRAPS];
+
+/*
+ * Structure describing a fighting being
+ */
+struct stats {
+    str_t s_str;			/* Strength */
+    int s_exp;				/* Experience */
+    int s_lvl;				/* Level of mastery */
+    int s_arm;				/* Armor class */
+    int s_hpt;				/* Hit points */
+    char s_dmg[30];			/* String describing damage done */
+};
+
+/*
+ * Structure for monsters and player
+ */
+struct thing {
+    coord t_pos;			/* Position */
+    int t_turn;			/* If slowed, is it a turn to move */
+    int t_type;			/* What it is */
+    int t_disguise;			/* What mimic looks like */
+    int t_oldch;			/* Character that was where it was */
+    coord *t_dest;			/* Where it is running to */
+    int t_flags;			/* State word */
+    struct stats t_stats;		/* Physical description */
+    struct linked_list *t_pack;		/* What the thing is carrying */
+	int t_reserved;         /* reserved for save/restore code */
+};
+
+/*
+ * Array containing information on all the various types of mosnters
+ */
+struct monster {
+    char m_name[20];			/* What to call the monster */
+    int m_carry;			/* Probability of carrying something */
+    int m_flags;			/* Things about the monster */
+    struct stats m_stats;		/* Initial stats */
+};
+
+/*
+ * Structure for a thing that the rogue can carry
+ */
+
+struct object {
+    int o_type;				/* What kind of object it is */
+    coord o_pos;			/* Where it lives on the screen */
+    int o_launch;			/* What you need to launch it */
+    char o_damage[8];			/* Damage if used like sword */
+    char o_hurldmg[8];			/* Damage if thrown */
+    int o_count;			/* Count for plural objects */
+    int o_which;			/* Which object of a type it is */
+    int o_hplus;			/* Plusses to hit */
+    int o_dplus;			/* Plusses to damage */
+    int o_ac;				/* Armor class */
+    int o_flags;			/* Information about objects */
+    int o_group;			/* Group number for this object */
+};
+
+struct delayed_action {
+    int d_type;
+    void (*d_func)();
+    int d_arg;
+    int d_time;
+};
+
+/*
+ * Now all the global variables
+ */
+
+extern int                   a_chances[MAXARMORS];	/* Probabilities for armor */
+extern int                   a_class[MAXARMORS];	/* Armor class for various armors */
+extern char *                a_names[MAXARMORS];	/* Names of armor types */
+extern int                   after;			/* True if we want after daemons */
+extern int                   amulet;			/* He found the amulet */
+extern int                   askme;			/* Ask about unidentified things */
+extern int                   between;
+extern coord                 ch_ret;
+extern int                   count;			/* Number of times to repeat command */
+extern int                   cNCOLORS;
+extern int                   cNMETAL;
+extern int                   cNSTONES;
+extern int                   cNWOOD;
+extern struct object *       cur_armor;			/* What a well dresssed rogue wears */
+extern struct object *       cur_ring[2];		/* Which rings are being worn */
+extern struct object *       cur_weapon;		/* Which weapon he is weilding */
+extern WINDOW *              cw;			/* Window that the player sees */
+extern coord                 delta;			/* Change indicated to get_dir() */
+extern int                   dnum;			/* Dungeon number */
+extern int                   door_stop;			/* Stop running when we pass a door */
+extern struct delayed_action d_list[20];
+extern int                   fight_flush;		/* True if toilet input */
+extern char                  file_name[80];		/* Save file name */
+extern int                   firstmove;			/* First move after setting door_stop */
+extern int                   food_left;			/* Amount of food in hero's stomach */
+extern char                  fruit[80];			/* Favorite fruit */
+extern int                   fung_hit;			/* Number of time fungi has hit */
+extern int                   group;			/* Current group number */
+extern char                  home[];			/* User's home directory */
+extern WINDOW *              hw;			/* Used for the help command */
+extern char                  huh[80];			/* The last message printed */
+extern int                   hungry_state;		/* How hungry is he */
+extern int                   in_shell;			/* True if executing a shell */
+extern int                   inpack;			/* Number of things in pack */
+extern int                   jump;			/* Show running as series of jumps */
+extern int                   lastscore;			/* Score before this turn */
+extern int                   level;			/* What level rogue is on */
+extern char                  lvl_mons[27];
+extern struct linked_list *  lvl_obj;			/* List of objects on this level */
+extern int                   max_hp;			/* Player's max hit points */
+extern int                   max_level;			/* Deepest player has gone */
+extern struct stats          max_stats;			/* The maximum for the player */
+extern char *                metal[];
+extern struct linked_list *  mlist;			/* List of monsters on the level */
+extern struct monster        monsters[26];		/* The initial monster states */
+extern int                   mpos;			/* Where cursor is on top line */
+extern WINDOW *              mw;			/* Used to store mosnters */
+extern coord                 nh;
+extern int                   no_command;		/* Number of turns asleep */
+extern int                   no_food;			/* Number of levels without food */
+extern int                   no_move;			/* Number of turns held in place */
+extern int                   notify;			/* True if player wants to know */
+extern int                   ntraps;			/* Number of traps on this level */
+extern int                   num_checks;
+extern coord                 oldpos;			/* Position before last look() call */
+extern struct room *         oldrp;			/* Roomin(&oldpos) */
+extern char *                p_colors[MAXPOTIONS];	/* Colors of the potions */
+extern char *                p_guess[MAXPOTIONS];	/* Players guess at what potion is */
+extern int                   p_know[MAXPOTIONS];	/* Does he know what a potion does */
+extern struct magic_item     p_magic[MAXPOTIONS];	/* Names and chances for potions */
+extern struct thing          player;			/* The rogue */
+extern int                   playing;			/* True until he quits */
+extern unsigned char         prbuf[80];			/* Buffer for sprintfs */
+extern int                   purse;			/* How much gold the rogue has */
+extern int                   quiet;			/* Number of quiet turns */
+extern char *                r_guess[MAXRINGS];		/* Players guess at what ring is */
+extern int                   r_know[MAXRINGS];		/* Does he know what a ring does */
+extern struct magic_item     r_magic[MAXRINGS];		/* Names and chances for rings */
+extern char *                r_stones[MAXRINGS];	/* Stone settings of the rings */
+extern char *                rainbow[];
+extern char *                release;			/* Release number of rogue */
+extern struct room           rooms[MAXROOMS];		/* One for each room -- A level */
+extern int                   runch;			/* Direction player is running */
+extern int                   running;			/* True if player is running */
+extern int                   seed;			/* Random number seed */
+extern char *                s_guess[MAXSCROLLS];	/* Players guess at what scroll is */
+extern int                   s_know[MAXSCROLLS];	/* Does he know what a scroll does */
+extern struct magic_item     s_magic[MAXSCROLLS];	/* Names and chances for scrolls */
+extern char *                s_names[MAXSCROLLS];	/* Names of the scrolls */
+extern FILE *                scoreboard;
+extern int                   slow_invent;		/* Inventory one line at a time */
+extern char *                stones[];
+extern int                   take;			/* Thing the rogue is taking */
+extern int                   terse;			/* True if we should be int */
+extern struct magic_item     things[NUMTHINGS];		/* Chances for each type of item */
+extern int                   total;			/* Total dynamic memory bytes */
+extern char *                w_names[MAXWEAPONS];	/* Names of the various weapons */
+extern char                  wand_mons[27];
+extern int                   waswizard;			/* Was a wizard sometime */
+extern char                  whoami[80];		/* Name of player */
+extern int                   wizard;			/* True if allows wizard commands */
+extern char *                wood[];
+extern char *                ws_guess[MAXSTICKS];	/* Players guess at what wand is */
+extern int                   ws_know[MAXSTICKS];	/* Does he know what a stick does */
+extern char *                ws_made[MAXSTICKS];	/* What sticks are made of */
+extern struct magic_item     ws_magic[MAXSTICKS];	/* Names and chances for sticks */
+extern char *                ws_type[MAXSTICKS];	/* Is it a wand or a staff */
+
+void                    _attach(struct linked_list **list, struct linked_list *item);
+void                    _detach(struct linked_list **list, struct linked_list *item);
+void                    _free_list(struct linked_list **ptr);
+char *                  _new(size_t size);
+int                     add_dam(str_t *str);
+void                    add_haste(int potion);
+void                    add_pack(struct linked_list *item, int silent);
+void                    add_pass(void);
+void                    addmsg(char *fmt, ...);
+void                    aggravate(void);
+int                     attack(struct thing *mp);
+int                     author(void);
+void                    auto_save(int p);
+void                    badcheck(char *name, struct magic_item *magic, int bound);
+int                     be_trapped(coord *tc);
+void                    bounce(struct object *weap, char *mname);
+void                    call(void);
+int                     cansee(int y, int x);
+char *                  charge_str(struct object *obj);
+int                     chase(struct thing *tp, coord *ee);
+void                    check_level(void);
+void                    checkout(int p);
+void                    chg_str(int amt);
+void                    chmsg(char *fmt, ...);
+void                    command(void);
+void                    conn(int r1, int r2);
+void                    create_obj(void);
+void                    death(int monst);
+int                     diag_ok(coord *sp, coord *ep);
+void                    discard(struct linked_list *item);
+void                    d_level(void);
+int                     do_chase(struct thing *th);
+void                    do_daemons(int flag);
+void                    do_fuses(int flag);
+void                    do_motion(struct object *obj, int ydelta, int xdelta);
+void                    do_move(int dy, int dx);
+void                    do_passages(void);
+void                    do_rooms(void);
+void                    do_run(int ch);
+void                    do_zap(int gotdir);
+void                    doadd(char *fmt, va_list ap);
+void                    doctor(void);
+void                    door(struct room *rm, coord *cp);
+void                    drain(int ymin, int ymax, int xmin, int xmax);
+void                    draw_room(struct room *rp);
+void                    drop(void);
+int                     dropcheck(struct object *op);
+void                    eat(void);
+int	                encerror(void);
+void                    encseterr(int err);
+int                     encclearerr(void);
+size_t                  encread(void *buf, size_t size, FILE *inf);
+size_t                  encwrite(const void *buf, size_t size, FILE *outf);
+void                    endmsg(void);
+void                    extinguish(void (*func)());
+void                    fall(struct linked_list *item, int pr);
+int                     fallpos(coord *pos, coord *newpos, int passages);
+void                    fatal(char *s);
+struct linked_list *    find_mons(int y, int x);
+struct linked_list *    find_obj(int y, int x);
+struct delayed_action * find_slot(void (*func)());
+int                     fight(coord *mp, int mn, struct object *weap, int thrown);
+void                    fix_stick(struct object *cur);
+void                    flush_type(void);
+void                    fuse(void (*func)(), int arg, int time, int type);
+void                    genocide(void);
+int                     get_bool(void *vp, WINDOW *win);
+int                     get_dir(void);
+struct linked_list *    get_item(char *purpose, int type);
+int                     get_str(void *vopt, WINDOW *win);
+int                     gethand(void);
+void                    help(void);
+void                    hit(char *er, char *ee);
+int                     hit_monster(int y, int x, struct object *obj);
+void                    horiz(int cnt);
+void                    identify(void);
+void                    init_colors(void);
+void                    init_materials(void);
+void                    init_names(void);
+void                    init_player(void);
+void                    init_stones(void);
+void                    init_things(void);
+void                    init_weapon(struct object *weap, int type);
+char *                  inv_name(struct object *obj, int drop);
+int                     inventory(struct linked_list *list, int type);
+int                     is_current(struct object *obj);
+int                     is_magic(struct object *obj);
+void                    kill_daemon(void (*func)());
+void                    killed(struct linked_list *item, int pr);
+char *                  killname(int monst);
+void                    lengthen(void (*func)(), int xtime);
+void                    light(coord *cp);
+void                    look(int wakeup);
+void                    miss(char *er, char *ee);
+void                    missile(int ydelta, int xdelta);
+void                    money(void);
+void                    msg(char *fmt, ...);
+void                    new_level(void);
+struct linked_list *    new_item(int size);
+void                    new_monster(struct linked_list *item, int type, coord *cp);
+struct linked_list *    new_thing(void);
+char *                  num(int n1, int n2);
+void                    nohaste(void);
+void                    open_score(void);
+void                    option(void);
+int                     pack_char(struct object *obj);
+void                    parse_opts(char *str);
+int                     passwd(void);
+int                     pick_one(struct magic_item *magic, int nitems);
+void                    pick_up(int ch);
+void                    picky_inven(void);
+void                    playit(void);
+void                    put_bool(void *b);
+void                    put_str(void *str);
+void                    put_things(void);
+int                     readchar(WINDOW *win);
+int                     restore(char *file, char **envp);
+int                     roll(int number, int sides);
+struct room *           roomin(coord *cp);
+int                     step_ok(int ch);
+void                    strucpy(char *s1, char *s2, size_t len);
+void                    swander(void);
+void                    take_off(void);
+void                    tstp(int p);
+void                    quaff(void);
+void                    quit(int p);
+void                    raise_level(void);
+int                     randmonster(int wander);
+void                    read_scroll(void);
+void                    remove_monster(coord *mp, struct linked_list *item);
+int                     ring_eat(int hand);
+void                    ring_off(void);
+void                    ring_on(void);
+char *                  ring_num(struct object *obj);
+int                     rnd(int range);
+void                    rnd_pos(struct room *rp, coord *cp);
+int                     rnd_room(void);
+coord *                 rndmove(struct thing *who);
+int                     roll_em(struct stats *att, struct stats *def, struct object *weap, int hurl);
+void                    rollwand(void);
+int                     rs_save_file(FILE *savef);
+int                     rs_restore_file(FILE *inf);
+void                    runners(void);
+void                    runto(coord *runner, coord *spot);
+int                     save(int which);
+int                     save_file(FILE *savef);
+int                     save_game(void);
+int                     save_throw(int which, struct thing *tp);
+void                    score(int amount, int flags, int monst);
+void                    shell(void);
+int                     show(int y, int x);
+void                    sight(void);
+void                    search(void);
+int                     secretdoor(int y, int x);
+void                    setup(void);
+void                    show_win(WINDOW *scr, char *message);
+void                    start_daemon(void (*func)(), int arg, int type);
+void                    status(void);
+void                    stomach(void);
+int                     str_plus(str_t *str);
+int                     swing(int at_lvl, int op_arm, int wplus);
+int                     teleport(void);
+int                     too_much(void);
+void                    total_winner(void);
+char *                  tr_name(int ch);
+struct trap *           trap_at(int y, int x);
+void                    thunk(struct object *weap, char *mname);
+void                    u_level(void);
+void                    unconfuse(void);
+void                    unsee(void);
+void                    vert(int cnt);
+char *                  vowelstr(char *str);
+void                    wait_for(WINDOW *win, int ch);
+struct linked_list *    wake_monster(int y, int x);
+void                    wanderer(void);
+void                    waste_time(void);
+void                    wear(void);
+void                    whatis(void);
+void                    wield(void);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rogue3/rogue.r	Tue Oct 13 13:33:34 2009 +0000
@@ -0,0 +1,411 @@
+.RP
+.ds RH A Guide to the Dungeons of Doom
+.ds CH
+.ds CF - % -
+.TL
+A Guide to the Dungeons of Doom
+.AU
+Michael C. Toy
+.AI
+Computer Systems Research Group
+Department of Electrical Engineering and Computer Science
+University of California
+Berkeley, California  94720
+.AB
+Rogue is a visual CRT based fantasy game which runs
+under the UNIX timesharing system.  This paper describes
+how to play rogue and gives a few hints for those who might
+otherwise get lost in the Dungeons of Doom.
+.AE
+.NH
+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 sword, 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 sword, put on your armor, eat what is almost your last food and enter
+the dungeons.
+.NH
+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\(dg
+.FS
+\(dgAs opposed to pseudo English sentences.
+.FE
+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.
+.NH
+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 "You can see ..." descriptions
+of standard fantasy games.  Here is a sample of what a rogue screen might
+look like.
+.in +1i
+.nf
+.cs R 15
+                  ---------------------
+                  |...................+
+                  |...@...........[...|
+                  |........B..........|
+                  |...................|
+                  --------+------------
+
+
+.cs R
+Level: 1  Gold: 0      Hp: 12(12)  Str: 16  Ac: 6  Exp: 1/0
+.fi
+.in 0
+.NH 2
+The bottom line
+.PP
+At the bottom line of the screen is a few pieces of cryptic information,
+describing your current status.  Here is an explanation of what these
+things mean:
+.IP Level 8
+This number indicates how deep you have gone in the dungeon.  It starts
+at one and goes up forever\(dg.
+.FS
+\(dgOr until you get killed or decide to quit.
+.FE
+.IP Gold
+The number of gold pieces you have managed to find and keep with
+you so far.
+.IP Hp
+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
+Your current strength.  This can be any integer less than or
+equal to eighteen.  The higher the number, the stronger you are.
+.IP Ac
+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
+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.
+.NH 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
+"--More--" on the top line, this means that rogue wants to print another
+message on the screen, but it wants to make certain that you have read
+the one that is there first.  To read the next message, just press a
+space.
+.NH 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 "-|" 6
+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 trap, watch out for these.
+.IP %
+The passage leading down to the next level.
+.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 mean.
+.NH
+Commands
+.PP
+Commands are given to rogue by pressing single letters.  Most commands can
+be preceded by a count to repeat them (e.g. typing "10s" will do ten searches)
+The list of commands is rather long, but it can be read at any time during
+the game with the ? command.  Here it is for reference, with a short
+explanation of each command.
+.IP ? 6
+The help command.  Asks for a character to give help on.  If you type
+a "*", it will list all the commands, otherwise it will explain what the
+character you typed does.
+.IP /
+This is the "What is that on the screen?" command. A "/" followed by any
+character that you see on the level, will tell you what that character
+is.  For instance, typing "/@" will tell you that the @ symbol represents
+you, the player.
+.IP "h , H"
+Move left.  You move one space to the left.  If you use upper case
+h, you will continue to move left until you run into something.  This
+works for all movement commands (e.g. "L" means run in direction "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 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.
+.IP t
+Throw an object.  This is a prefix command.  Follow it with a direction and
+you throw an object in the specified direction.  (e.g. type "th" to throw
+something left.)
+.IP >
+If you are standing over the passage down to the next level, this command
+means to climb down.
+.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 " "
+(space) Rest.  This is the "do nothing" 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.  Drink one of the potions you are carrying.
+.IP r
+Read.  Read one of the scrolls in your pack.
+.IP e
+Eat food.  Take some food out of your pack and eat it.
+.IP w
+Wield a weapon.  Take a weapon out of your pack and carry it.  You must be
+wielding  weapon to use it (except to throw things).  To fire an arrow,
+you must wield the bow.  You can only wield one weapon at a time.
+.IP W
+Wear armor.  Take a piece of armor out of your pack and put it on.  You can
+only wear one suit of armor at a time.
+.IP T
+Take armor off.  You can't remove armor that is cursed.
+This takes extra time.
+.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.
+.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 v
+Prints the program version number.
+.IP Q
+Quit.  Leave the game.
+.IP R
+Repeat last message.  Useful when a message disappears before you can
+read it.
+.IP S
+Save the current game in a file.  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 save_file
+.NH
+Dealing with objects
+.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 if the notify
+option is set, 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 press an escape and the command will be
+aborted.
+.NH
+Light
+.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 dark room, all objects inside the room which might move are
+removed from the screen.  In the darkness you can only see one space
+in all directions around you.
+.NH
+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.
+.NH
+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.
+If a piece of armor is enchanted or
+cursed, its armor class will be higher or lower than normal.  Here is
+a list of the various armor types and their normal armor class.
+.TS
+center box;
+c c
+l | c.
+Type	Class
+=
+Leather armor	8
+Studded leather / Ring mail	7
+Scale mail	6
+Chain mail	5
+Banded mail / Splint mail	4
+Plate mail	3
+.TE
+.NH
+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.
+.NH 2
+Setting the options
+.PP
+There are basically two ways to set the options.  The first is with the
+"o" command of rogue, the second is with the ROGUEOPTS environment
+variable.  On Version 6 systems, there is no equivalent of
+the ROGUEOPTS feature.
+.NH 3
+Using the "o" command
+.PP
+When you press "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 RETURN which means to
+go to the next option, a "\-" which means to go to the previous option, an
+escape which means to return to the game, or you can give the option a
+value.  For boolean options this merely involves pressing "t" for true or
+"f" for false.  For string options, type the new value followed by a
+return.
+.NH 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 and turned off by putting a "no" in front of the
+name.  Thus to set up an environment variable so that jump is on, terse is
+off, the name is set to "Conan the Barbarian" and the fruit is "mango",
+use the command
+.nf
+.nf
+.ti +3
+% setenv ROGUEOPTS "jump,noterse,name=Conan the Barbarian,fruit=mango" \(dg
+.fi
+.ti +3
+% setenv ROGUEOPTS "jump,noterse,name=Conan the Barbarian,fruit=mango" \(dg
+.fi
+.FS
+\(dgFor those of you who use the bourne shell, the commands would be
+.in +3
+.nf
+$ ROGUEOPTS="jump,noterse,name=Conan the Barbarian,fruit=mango"
+$ export ROGUEOPTS
+.fi
+.in +0
+.FE
+.NH 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.
+.IP "terse [noterse]" 25
+Useful for those who are tired of the sometimes lengthy messages of rogue.
+This is a useful option for those on slow terminals.  This option defaults to
+on if your are on a slow (under 1200 baud) terminal.
+.IP "jump [nojump]"
+If this option is set, running moves will not be displayed until you
+reach the end of the move.  This saves considerable cpu time and
+display time.  This option defaults to on if you are using a slow terminal.
+.IP "step [nostep]
+When step is set, lists of things, like inventories or "*" responses to
+"Which item do you wish to xxxx? " 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 "flush [noflush]"
+If flush is set, all typeahead is thrown away after each round of battle.
+This is useful for those who type way ahead and watch to their dismay as
+a Kobold kills them.
+.IP "askme [noaskme]"
+Upon reading a scroll or quaffing a potion which does not automatically
+identify it upon use, rogue will ask you what to name it so you can
+recognize it in the future.
+.IP "name [account name]"
+This is the name of your character.  It is used if you get on the top ten
+scorer's list.  It should be less than eighty characters long.
+.IP "fruit [slime-mold]"
+This should hold the name of a fruit that you enjoy eating.  It is basically
+a whimsy that the program uses in a couple of places.
+.IP "file [rogue.save]"
+The default file name for saving the game.  If your phone is hung up by
+accident, rogue will automatically save the game in this file.  The
+file name may contain the special character "~" which expands to be
+your home directory.
+.NH
+Acknowledgements
+.PP
+Rogue was originally conceived of by Glenn Wichman and Michael Toy.  The
+help of Ken Arnold in making the program easier to use and putting the
+finishing touches on is greatly appreciated.  I would also like to thank
+Marty McNary, Scott Nelson, Daniel Jensen, Kipp Hickman, Joe Kalash,
+Steve Maurer, Bill Joy, Mark Horton and Jan Miller for their ideas
+and assistance.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rogue3/rogue36.cat	Tue Oct 13 13:33:34 2009 +0000
@@ -0,0 +1,54 @@
+ROGUE(6)                                                              ROGUE(6)
+
+
+
+NAME
+       rogue - Exploring The Dungeons of Doom
+
+SYNOPSIS
+       rogue [ save_file ]
+
+DESCRIPTION
+       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  mon-
+       sters and get a lot of gold, rather than the puzzle solving orientation
+       of most computer fantasy games.
+
+       To get started you really only need to know two commands.  The  command
+       ?   will  give  you  a list of the available commands and the command /
+       will identify the things you see on the screen.
+
+       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.
+
+       When the game ends, either by your death, when you quit, or if you  (by
+       some  miracle)  manage to win, 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.
+
+       For more detailed directions, read the document A Guide to the Dungeons
+       of Doom.
+
+FILES
+       rogue36.scr                  Score file
+       ~/rogue36.sav                Default save file
+
+SEE ALSO
+       Michael C. Toy, A Guide to the Dungeons of Doom
+
+BUGS
+       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.
+
+COPYRIGHT
+       Rogue: Exploring the Dungeons of Doom
+       Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
+       All rights reserved.
+
+
+
+3rd Berkeley Distribution                                             ROGUE(6)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rogue3/rogue36.doc	Tue Oct 13 13:33:34 2009 +0000
@@ -0,0 +1,660 @@
+
+
+
+
+
+
+
+
+
+              A Guide to the Dungeons of Doom
+
+                       Michael C. Toy
+              Computer Systems Research Group
+ Department of Electrical Engineering and Computer Science
+                  University of California
+                Berkeley, California  94720
+
+
+
+                          ABSTRACT
+
+          Rogue  is  a  visual  CRT  based fantasy game
+     which runs  under  the  UNIX  timesharing  system.
+     This paper describes how to play rogue and gives a
+     few hints for those who might otherwise  get  lost
+     in the Dungeons of Doom.
+
+
+
+11 July 2006
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+              A Guide to the Dungeons of Doom
+
+                       Michael C. Toy
+              Computer Systems Research Group
+ Department of Electrical Engineering and Computer Science
+                  University of California
+                Berkeley, California  94720
+
+
+1.  Introduction
+
+     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 mem-
+bership in the local guild. In addition, you are allowed  to
+keep all the loot you bring back from the dungeons.
+
+     In  preparation  for  your  journey,  you  are given an
+enchanted sword, 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.
+
+     You set out on your way to the dungeons and after  sev-
+eral  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  sword,  put  on your armor, eat what is almost
+your last food and enter the dungeons.
+
+2.  What is going on here?
+
+     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.
+
+     Rogue  differs from most computer fantasy games in that
+it  is  screen  oriented.   Commands  are  all  one  or  two
+keystrokes  and  the  results of your commands are displayed
+graphically on the screen rather  than  being  explained  in
+-----------
+As opposed to pseudo English sentences.
+
+
+
+                            - 1 -
+
+
+
+
+
+                             A Guide to the Dungeons of Doom
+
+
+words.
+
+     Another  major  difference between rogue and other com-
+puter 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.
+
+3.  What do all those things on the screen mean?
+
+     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  "You
+can  see  ..." descriptions of standard fantasy games.  Here
+is a sample of what a rogue screen might look like.
+                            ---------------------
+                            |...................+
+                            |...@...........[...|
+                            |........B..........|
+                            |...................|
+                            --------+------------
+
+
+          Level: 1  Gold: 0      Hp: 12(12)  Str: 16  Ac: 6  Exp: 1/0
+
+3.1.  The bottom line
+
+     At the bottom line of the screen is  a  few  pieces  of
+cryptic  information,  describing your current status.  Here
+is an explanation of what these things mean:
+
+Level   This number indicates how deep you have gone in  the
+        dungeon.  It starts at one and goes up forever.
+
+Gold    The  number  of gold pieces you have managed to find
+        and keep with you so far.
+
+Hp      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.
+
+Str     Your current strength.  This can be any integer less
+        than or equal to eighteen.  The higher  the  number,
+        the stronger you are.
+
+Ac      Your current armor class.  This number indicates how
+        effective your  armor  is  in  stopping  blows  from
+        unfriendly creatures.  The lower this number is, the
+-----------
+Or until you get killed or decide to quit.
+
+
+
+                            - 2 -
+
+
+
+
+
+                             A Guide to the Dungeons of Doom
+
+
+        more effective the armor.
+
+Exp     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.
+
+3.2.  The top line
+
+     The  top  line  of  the screen is reserved for printing
+messages that describe things that are impossible to  repre-
+sent  visually.   If  you  see a "--More--" on the top line,
+this means that rogue wants to print another message on  the
+screen,  but it wants to make certain that you have read the
+one that is there first.  To read  the  next  message,  just
+press a space.
+
+3.3.  The rest of the screen
+
+     The  rest  of the screen is the map of the level as you
+have explored it so far.  Each symbol on the  screen  repre-
+sents something.  Here is a list of what the various symbols
+mean:
+
+@    This symbol represents you, the adventurer.
+
+-|    These symbols represent the walls of rooms.
+
++     A door to/from a room.
+
+.     The floor of a room.
+
+#     The floor of a passage between rooms.
+
+*     A pile or pot of gold.
+
+)     A weapon of some sort.
+
+]     A piece of armor.
+
+!     A flask containing a magic potion.
+
+?     A piece of paper, usually a magic scroll.
+
+^     A trap, watch out for these.
+
+%     The passage leading down to the next level.
+
+:     A piece of food.
+
+A-Z   The uppercase letters represent  the  various  inhabi-
+      tants of the Dungeons of Doom.  Watch out, they can be
+
+
+
+                            - 3 -
+
+
+
+
+
+                             A Guide to the Dungeons of Doom
+
+
+      mean.
+
+4.  Commands
+
+     Commands are given to rogue by pressing single letters.
+Most  commands  can  be  preceded  by a count to repeat them
+(e.g. typing "10s" will do ten searches) The  list  of  com-
+mands  is rather long, but it can be read at any time during
+the game with the ? command.  Here it is for reference, with
+a short explanation of each command.
+
+?     The  help  command.  Asks for a character to give help
+      on.  If you type a "*", it will list all the commands,
+      otherwise it will explain what the character you typed
+      does.
+
+/     This is the "What is that on the screen?"  command.  A
+      "/"  followed  by  any  character  that you see on the
+      level, will tell you  what  that  character  is.   For
+      instance,  typing "/@" will tell you that the @ symbol
+      represents you, the player.
+
+h , H Move left.  You move one space to the  left.   If  you
+      use upper case h, you will continue to move left until
+      you run into something.  This works for  all  movement
+      commands (e.g. "L" means run in direction "l")
+
+j     Move down.
+
+k     Move up.
+
+l     Move right.
+
+y     Move diagonally up and left.
+
+u     Move diagonally up and right.
+
+b     Move diagonally down and left.
+
+n     Move diagonally down and right.
+
+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.
+
+t     Throw an object.  This is a prefix command.  Follow it
+      with a direction and you throw an object in the speci-
+      fied  direction.   (e.g.  type "th" to throw something
+      left.)
+
+>     If you are standing over the passage down to the  next
+      level, this command means to climb down.
+
+
+
+
+
+                            - 4 -
+
+
+
+
+
+                             A Guide to the Dungeons of Doom
+
+
+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 some-
+      thing.
+
+      (space) Rest.  This is the "do nothing" command.  This
+      is good for waiting and healing.
+
+i     Inventory.  List what you are carrying in your pack.
+
+I     Selective  inventory.  Tells you what a single item in
+      your pack is.
+
+q     Quaff.  Drink one of the potions you are carrying.
+
+r     Read.  Read one of the scrolls in your pack.
+
+e     Eat food.  Take some food out of your pack and eat it.
+
+w     Wield  a  weapon.   Take a weapon out of your pack and
+      carry it.  You must be  wielding   weapon  to  use  it
+      (except  to throw things).  To fire an arrow, you must
+      wield the bow.  You can only wield  one  weapon  at  a
+      time.
+
+W     Wear  armor.   Take  a piece of armor out of your pack
+      and put it on.  You can only wear one suit of armor at
+      a time.
+
+T     Take  armor  off.   You  can't  remove  armor  that is
+      cursed.  This takes extra time.
+
+d     Drop an object.  Take something out of your  pack  and
+      leave  it  lying  on  the  floor.  Only one object can
+      occupy each space.
+
+o     Examine and set  options.   This  command  is  further
+      explained in the section on options.
+
+^L    REdraws  the  screen.  Useful  if spurious messages or
+      transmission errors have messed up the display.
+
+v     Prints the program version number.
+
+Q     Quit.  Leave the game.
+
+R     Repeat last message.  Useful when a message disappears
+      before you can read it.
+
+S     Save  the current game in a file.  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
+
+
+
+                            - 5 -
+
+
+
+
+
+                             A Guide to the Dungeons of Doom
+
+
+      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
+                % rogue save_file
+
+5.  Dealing with objects
+
+     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 if the
+notify option is set, tell you what you just picked up.
+
+     Many of the  commands  that  operate  on  objects  must
+prompt you to find out which object you want to use.  If you
+change your mind and don't want to  do  that  command  after
+all, just press an escape and the command will be aborted.
+
+6.  Light
+
+     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
+dark  room, all objects inside the room which might move are
+removed from the screen.  In the darkness you can  only  see
+one space in all directions around you.
+
+7.  Fighting
+
+     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.
+
+8.  Armor
+
+     There are various sorts of armor lying  around  in  the
+dungeon.   Some  of it is enchanted, some is cursed and some
+is just normal.  Different armor types have different  armor
+classes.  The lower the armor class, the more protection the
+armor affords against the blows of monsters.  If a piece  of
+armor is enchanted or cursed, its armor class will be higher
+or lower than normal.  Here is a list of the  various  armor
+types and their normal armor class.
+
+
+
+
+
+
+
+
+
+
+                            - 6 -
+
+
+
+
+
+                             A Guide to the Dungeons of Doom
+
+
+           +------------------------------------+
+           |           Type               Class |
+           +----------------------------+-------+
+           |Leather armor               |   8   |
+           |Studded leather / Ring mail |   7   |
+           |Scale mail                  |   6   |
+           |Chain mail                  |   5   |
+           |Banded mail / Splint mail   |   4   |
+           |Plate mail                  |   3   |
+           +----------------------------+-------+
+
+9.  Options
+
+     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.
+
+9.1.  Setting the options
+
+     There are basically two ways to set the  options.   The
+first  is  with the "o" command of rogue, the second is with
+the ROGUEOPTS environment variable.  On Version  6  systems,
+there is no equivalent of the ROGUEOPTS feature.
+
+9.1.1.  Using the "o" command
+
+     When  you  press "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 RETURN which means to go to
+the  next  option,  a  "-" which means to go to the previous
+option, an escape which means to return to the game, or  you
+can  give  the  option  a  value.   For boolean options this
+merely involves pressing "t" for true or "f" for false.  For
+string options, type the new value followed by a return.
+
+9.1.2.  Using the ROGUEOPTS variable
+
+     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 and
+turned off by putting a "no" in front of the name.  Thus  to
+set  up an environment variable so that jump is on, terse is
+off, the name is set to "Conan the Barbarian" and the  fruit
+is "mango", use the command
+   % setenv ROGUEOPTS "jump,noterse,name=Conan the Barbarian,fruit=mango"
+   %  setenv  ROGUEOPTS "jump,noterse,name=Conan the Barbar-
+ian,fruit=mango"
+
+-----------
+For those of you who use  the  bourne  shell,  the
+commands would be
+   $ ROGUEOPTS="jump,noterse,name=Conan the Barbarian,fruit=mango"
+
+
+
+                            - 7 -
+
+
+
+
+
+                             A Guide to the Dungeons of Doom
+
+
+9.2.  Option list
+
+     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.
+
+terse [noterse]          Useful  for  those who are tired of
+                         the sometimes lengthy  messages  of
+                         rogue.  This is a useful option for
+                         those  on  slow  terminals.    This
+                         option  defaults  to on if your are
+                         on a slow (under 1200 baud)  termi-
+                         nal.
+
+jump [nojump]            If  this  option  is  set,  running
+                         moves will not be  displayed  until
+                         you  reach  the  end  of  the move.
+                         This saves  considerable  cpu  time
+                         and   display  time.   This  option
+                         defaults to on if you are  using  a
+                         slow terminal.
+
+step [nostep]            When  step is set, lists of things,
+                         like inventories or  "*"  responses
+                         to "Which item do you wish to xxxx?
+                         " questions, are displayed one item
+                         at a time on the top of the screen,
+                         rather than  clearing  the  screen,
+                         displaying  the  list, then re-dis-
+                         playing the dungeon level.
+
+flush [noflush]          If flush is set, all  typeahead  is
+                         thrown  away  after  each  round of
+                         battle.  This is useful  for  those
+                         who  type  way  ahead  and watch to
+                         their  dismay  as  a  Kobold  kills
+                         them.
+
+askme [noaskme]          Upon reading a scroll or quaffing a
+                         potion which does not automatically
+                         identify  it  upon  use, rogue will
+                         ask you what to name it so you  can
+                         recognize it in the future.
+
+name [account name]      This is the name of your character.
+                         It is used if you get  on  the  top
+                         ten  scorer's  list.   It should be
+                         less than eighty characters long.
+
+fruit [slime-mold]       This should  hold  the  name  of  a
+                         fruit that you enjoy eating.  It is
+                         basically a whimsy that the program
+-----------
+   $ export ROGUEOPTS
+
+
+
+                            - 8 -
+
+
+
+
+
+                             A Guide to the Dungeons of Doom
+
+
+                         uses in a couple of places.
+
+file [rogue.save]        The  default  file  name for saving
+                         the game.  If your phone is hung up
+                         by  accident,  rogue will automati-
+                         cally save the game in  this  file.
+                         The  file name may contain the spe-
+                         cial character "~" which expands to
+                         be your home directory.
+
+10.  Acknowledgements
+
+     Rogue  was originally conceived of by Glenn Wichman and
+Michael Toy.  The help of Ken Arnold in making  the  program
+easier  to  use  and  putting  the  finishing  touches on is
+greatly appreciated.  I  would  also  like  to  thank  Marty
+McNary,  Scott  Nelson,  Daniel  Jensen,  Kipp  Hickman, Joe
+Kalash, Steve Maurer, Bill Joy, Mark Horton and  Jan  Miller
+for their ideas and assistance.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+                            - 9 -
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rogue3/rogue36.html	Tue Oct 13 13:33:34 2009 +0000
@@ -0,0 +1,633 @@
+<html>
+<head>
+<title></title>
+</head>
+<body>
+
+<h1 align=center><b>A Guide to the Dungeons of Doom</b></h1>
+
+<h2 align=center><i>Michael C. Toy</i></h2>
+
+<h3 align=center>
+Computer Systems Research Group<br>
+Department of Electrical Engineering and Computer Science<br>
+University of California<br>
+Berkeley, California 94720</h3>
+
+<h2 align=center><i>ABSTRACT</i></h2>
+
+<blockquote>
+	<blockquote>
+		<p align="justify"><font size="2">Rogue is a visual CRT based fantasy game which runs under the 
+		UNIX timesharing system. This paper describes how to play rogue, and gives a few hints for 
+		those who might otherwise get 
+		lost in the Dungeons of Doom.</font></p>
+	</blockquote>
+</blockquote>
+
+<h2 align="justify"><b>1. Introduction</b></h2>
+
+<p align="justify">You have just finished your years as a
+student at the local fighter&rsquo;s guild. After much
+practice and sweat you have finally completed your training
+and are ready to embark upon a perilous adventure. As a test
+of your skills, the local guildmasters have sent you into
+the Dungeons of Doom. Your task is to return with the Amulet
+of Yendor. Your reward for the completion of this task will
+be a full membership in the local guild. In addition, you
+are allowed to keep all the loot you bring back from the
+dungeons.</p>
+
+<p align="justify">In preparation for your journey, you are
+given an enchanted sword, taken
+from a dragon&rsquo;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.</p>
+
+<p align="justify">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 sword, put on your armor, eat what
+is almost your last food and enter the
+dungeons.</p>
+
+<h2 align="justify"><b>2. What is going on here?</b></h2>
+
+<p align="justify">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.</p>
+
+<p align="justify">Rogue differs from most computer fantasy
+games in that it is screen oriented. Commands are all one or
+two keystrokes<sup>1 </sup>and the
+results of your commands are displayed graphically on the
+screen rather than being explained in words<sup>2</sup>.</p>
+
+<p align="justify">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.</p>
+
+<h2 align="justify"><b>3. What do all those things on the screen mean?</b></h2>
+
+<p align="justify">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 &ldquo;You can see ...&rdquo; descriptions of
+standard fantasy games. Here is a sample of what a 
+rogue screen might look like.</p>
+
+<div align="center"><pre>
+                  ---------------------
+                  |...................+
+                  |...@...........[...|
+                  |........B..........|
+                  |...................|
+                  --------+------------
+
+Level: 1  Gold: 0      Hp: 12(12)  Str: 16  Ac: 6  Exp: 1/0
+</pre></div>
+
+<h3 align="justify"><b>3.1. The bottom line</b></h3>
+
+<p align="justify">At the bottom line of the screen is a few
+pieces of cryptic information describing your current
+status. Here is an explanation of what these things
+mean:</p>
+
+<table border="0" width="100%" id="table1" cellspacing="3" cellpadding="3">
+	<tr>
+		<td><p align="justify">Level&nbsp;&nbsp;</p></td>
+		<td><p align="justify">This number indicates how deep you have gone in the 
+		dungeon. It starts at one and goes up forever<sup>2</sup>.</p></td>
+	</tr>
+	<tr>
+		<td><p align="justify">Gold</p></td>
+		<td><p align="justify">The number of gold pieces you have managed to find 
+		and keep with you so far.</td>
+	</tr>
+	<tr>
+		<td><p align="justify">Hp</p></td>
+		<td><p align="justify">Your current and maximum hit points.
+		Health 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 health points by resting. The number in
+		parentheses is the maximum number your hit points can
+		reach.</p></td>
+	</tr>
+	<tr>
+		<td><p align="justify">Str</p></td>
+		<td><p align="justify">Your current strength. This can be any 
+		integer less than or equal to eighteen. The higher the number, 
+		the stronger you are.</td>
+	</tr>
+	<tr>
+		<td><p align="justify">Ac</p></td>
+		<td><p align="justify">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.</p></td>
+	</tr>
+	<tr>
+		<td><p align="justify">Exp</p></td>
+		<td><p align="justify">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.</p></td>
+	</tr>
+</table>
+
+<h3 align="justify"><b>3.2. The top line</b></h3>
+
+<p align="justify">The top line of the screen is reserved for
+printing messages that describe things that are impossible
+to represent visually. If you see a &ldquo;--More--&rdquo;
+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.</p>
+
+<h3 align="justify"><b>3.3. The rest of the screen</b></h3>
+
+<p align="justify">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:</p>
+
+<table border="0" width="100%" id="table2" cellspacing="3" cellpadding="3">
+	<tr>
+		<td>@</td>
+		<td><p align="justify">This symbol represents you, the adventurer.</p></td>
+	</tr>
+	<tr>
+		<td>- |</td>
+		<td><p align="justify">These symbols represent the walls of rooms.</p></td>
+	</tr>
+	<tr>
+		<td>+</td>
+		<td>
+		<p align="justify">A door to/from a room.</p></td>
+	</tr>
+	<tr>
+		<td>.</td>
+		<td><p align="justify">The floor of a room.</p></td>
+	</tr>
+	<tr>
+		<td>#</td>
+		<td><p align="justify">The floor of a passage between rooms.</p></td>
+	</tr>
+	<tr>
+		<td>*</td>
+		<td><p align="justify">A pile or pot of gold.</p></td>
+	</tr>
+	<tr>
+		<td>)</td>
+		<td><p align="justify">A weapon of some sort.</p></td>
+	</tr>
+	<tr>
+		<td>]</td>
+		<td><p align="justify">A piece of armor.</p></td>
+	</tr>
+	<tr>
+		<td>!</td>
+		<td><p align="justify">A flask containing a magic potion.</p></td>
+	</tr>
+	<tr>
+		<td>?</td>
+		<td><p align="justify">A piece of paper, usually a magic scroll.</p></td>
+	</tr>
+	<tr>
+		<td>^</td>
+		<td><p align="justify">A trap, watch out for these.</p></td>
+	</tr>
+	<tr>
+		<td>%</td>
+		<td><p align="justify">The passage leading down to the next level.</p></td>
+	</tr>
+	<tr>
+		<td>:</td>
+		<td><p align="justify">A piece of food.</p></td>
+	</tr>
+	<tr>
+		<td>A-Z&nbsp;&nbsp;</td>
+		<td><p align="justify">The uppercase letters represent the various 
+		inhabitants of the Dungeons of Doom. Watch out, they can be mean.</p></td>
+	</tr>
+</table>
+
+<h2 align="justify"><b>4. Commands</b></h2>
+
+<p align="justify">Commands are given to rogue by pressing single letters.
+Most commands can be preceded by a count to repeat them
+(e.g. typing &quot;10s&quot; will do ten searches) The list
+of commands is rather long, but it can be read at any time
+during the game with the ? command. Here it is for
+reference, with a short explanation of each command.</p>
+
+<div align="center">
+<table border="0" cellspacing="3" cellpadding="3" id="table3">
+	<tr>
+		<td>?</td>
+		<td><p align="justify">The help command. Asks for a character to give help 
+		on. If you type a &quot;*&quot;, it will list all the commands,
+		otherwise it will explain what the character you typed
+		does.</p></td>
+	</tr>
+	<tr>
+		<td>/</td>
+		<td align="justify"><p>This is the &quot;What is that on the screen?&quot;
+		command. A &quot;/&quot; followed by any character that you
+		see on the level, will tell you what that character is. For
+		instance, typing &quot;/@&quot; will tell you that the @
+		symbol represents you, the player.</p></td>
+	</tr>
+	<tr>
+		<td colspan="2">h, H</td>
+	</tr>
+	<tr>
+		<td>&nbsp;</td>
+		<td><p align="justify">Move left. You move one space to the left. If you use
+		upper case h, you will continue to move left until you run into something. 
+		This works for all movement commands (e.g. &quot;L&quot; means run in direction
+		&quot;l&quot;)</p></td>
+	</tr>
+	<tr>
+		<td>j</td>
+		<td><p align="justify">Move down.</p></td>
+	</tr>
+	<tr>
+		<td>k</td>
+		<td><p align="justify">Move up.</p></td>
+	</tr>
+	<tr>
+		<td>l</td>
+		<td><p align="justify">Move right.</p></td>
+	</tr>
+	<tr>
+		<td>y</td>
+		<td><p align="justify">Move diagonally up and left.</p></td>
+	</tr>
+	<tr>
+		<td>u</td>
+		<td><p align="justify">Move diagonally up and right.</p></td>
+	</tr>
+	<tr>
+		<td>b</td>
+		<td><p align="justify">Move diagonally down and left.</p></td>
+	</tr>
+	<tr>
+		<td>n</td>
+		<td><p align="justify">Move diagonally down and right.</p></td>
+	</tr>
+	<tr>
+		<td>t</td>
+		<td><p align="justify">Throw an object. This is a prefix command. When 
+		followed with a direction it throws an object in the specified direction. 
+		(e.g. type &ldquo;th&rdquo; to throw something to the left.)</p></td>
+	</tr>
+	<tr>
+		<td>f</td>
+		<td><p align="justify">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.</p></td>
+	</tr>
+	<tr>
+		<td>t</td>
+		<td><p align="justify">Throw an object. This is a prefix command. Follow it
+		with a direction and you throw an object in the specified
+		direction. (e.g. type &quot;th&quot; to throw something
+		left.)</p></td>
+	</tr>
+	<tr>
+		<td>&gt;</td>
+		<td><p align="justify">If you are standing over the passage down to the next
+		level, this command means to climb down.</p></td>
+		</tr>
+	<tr>
+		<td>s</td>
+		<td><p align="justify">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&rsquo;t find it so you might have
+		to search a while before you find something.</p></td>
+	</tr>
+	<tr>
+		<td>&nbsp;</td>
+		<td><p align="justify">(space) Rest. This is the &quot;do nothing&quot;
+		command. This is good for waiting and healing.</p></td>
+	</tr>
+	<tr>
+		<td align="left" valign="top">
+		<p>i</td>
+		<td align="justify">
+		<p>Inventory. List what you are carrying in your pack.</td>
+	</tr>
+	<tr>
+		<td>I</td>
+		<td><p align="justify">Selective inventory. Tells you what a single item in
+		your pack is.</p></td>
+	</tr>
+	<tr>
+		<td>q</td>
+		<td><p align="justify">Quaff. Drink one of the potions you are 
+		carrying.</p></td>
+	</tr>
+	<tr>
+		<td>r</td>
+		<td><p align="justify">Read. Read one of the scrolls in your pack.</p></td>
+	</tr>
+	<tr>
+		<td>e</td>
+		<td><p align="justify">Eat food. Take some food out of your pack and eat
+		it.</p></td>
+	</tr>
+	<tr>
+		<td>w</td>
+		<td><p align="justify">Wield a weapon. Take a weapon out of your pack and 
+		carry it. You must be wielding weapon to use it (except to throw
+		things). To fire an arrow, you must wield the bow. You can
+		only wield one weapon at a time.</p></td>
+	</tr>
+	<tr>
+		<td>W</td>
+		<td><p align="justify">Wear armor. Take a piece of armor out of your pack
+		and put it on. You can only wear one suit of armor at a time.</td>
+	</tr>
+	<tr>
+		<td>T</td>
+		<td><p align="justify">Take armor off. You can&rsquo;t remove armor that is
+		cursed. This takes extra time.</p></td>
+	</tr>
+	<tr>
+		<td>d</td>
+		<td><p align="justify">Drop an object. Take something out of your pack and
+		leave it lying on the floor. Only one object can occupy each
+		space.</p></td>
+	</tr>
+	<tr>
+		<td>o</td>
+		<td><p align="justify">Examine and set options. This command is further
+		explained in the section on options.</p></td>
+	</tr>
+	<tr>
+		<td>^L</td>
+		<td><p align="justify">Redraws the screen. Useful if spurious messages or
+		transmission errors have messed up the display.</p></td>
+	</tr>
+	<tr>
+		<td>v</td>
+		<td><p align="justify">Prints the program version number.</p></td>
+	</tr>
+	<tr>
+		<td>Q</td>
+		<td><p align="justify">Quit. Leave the game.</p></td>
+	</tr>
+	<tr>
+		<td>R</td>
+		<td><p align="justify">Repeat last message. Useful when a message disappears
+		before you can read it.</p></td>
+	</tr>
+	<tr>
+		<td>S</td>
+		<td><p align="justify">Save the current game in a file. Caveat: Rogue
+		won&rsquo;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 % rogue36 save_file</p></td>
+	</tr>
+</table>
+</div>
+
+<h2 align="justify"><b>5. Dealing with objects</b></h2>
+
+<p align="justify">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&rsquo;t pick up
+the object, otherwise it will add it to your pack and if the
+notify option is set, tell you what you just picked up.</p>
+
+<p align="justify">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&rsquo;t want to do that command after all,
+just press an escape and the command will be aborted.</p>
+
+<h2 align="justify"><b>6. Light</b></h2>
+
+<p align="justify">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
+dark room, all objects inside the room which might move are
+removed from the screen. In the darkness you can only see
+one space in all directions around you.</p>
+
+<h2 align="justify"><b>7. Fighting</b></h2>
+<p align="justify">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.</p>
+
+<h2 align="justify">8<b>. Armor</b></h2>
+
+<p align="justify">There are various sorts of armor lying around in the
+dungeon. Some of it is enchanted, some is cursed and some is
+just normal. Different armor types have different armor
+classes. The lower the armor class, the more protection the
+armor affords against the blows of monsters. If a piece of
+armor is enchanted or cursed, its armor class will be higher
+or lower than normal. Here is a list of the various armor
+types and their normal armor class.</p>
+
+<div align="center">
+	<table border="1" cellspacing="3" cellpadding="3" id="table4" style="border-collapse: collapse">
+		<tr>
+			<th><i>Type</i></th>
+			<th><i>Class</i></th>
+		</tr>
+		<tr>
+			<td>Leather armor</td>
+			<td align="center">8</td>
+		</tr>
+		<tr>
+			<td>Studded leather / Ring mail</td>
+			<td align="center">7</td>
+		</tr>
+		<tr>
+			<td>Scale mail </td>
+			<td align="center">6</td>
+		</tr>
+		<tr>
+			<td>Chain mail&nbsp; </td>
+			<td align="center">5</td>
+		</tr>
+		<tr>
+			<td>Banded mail / Splint mail</td>
+			<td align="center">4</td>
+		</tr>
+		<tr>
+			<td>Plate mail</td>
+			<td align="center">3</td>
+		</tr>
+	</table>
+</div>
+
+<h2 align="justify">9<b>. Options</b></h2>
+
+<p align="justify">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.</p>
+
+<h3 align="justify"><b>9.1 Setting the options</b></h3>
+
+<p align="justify">There are basically two ways to set the options. The
+first is with the &quot;o&quot; command of rogue, the second
+is with the ROGUEOPTS environment variable. On Version 6
+systems, there is no equivalent of the ROGUEOPTS
+feature.</p>
+
+<h3 align="justify"><b>9.1.1. Using the &quot;o&quot; command</b></h3>
+
+<p align="justify">When you press &quot;o&quot; 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 RETURN
+which means to go to the next option, a &quot;&minus;&quot;
+which means to go to the previous option, an escape which
+means to return to the game, or you can give the option a
+value. For boolean options this merely involves pressing
+&quot;t&quot; for true or &quot;f&quot; for false. For
+string options, type the new value followed by a return.</p>
+
+<h3 align="justify">9<b>.1.2. Using the ROGUEOPTS variable</b></h3>
+
+<p align="justify">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 and
+turned off by putting a &quot;no&quot; in front of the name.
+Thus to set up an environment variable so that jump is on,
+terse is off, the name is set to &quot;Conan the
+Barbarian&quot; and the fruit is &quot;mango&quot;, use the
+command</p>
+
+<div align="justify"><pre>
+   % setenv ROGUEOPTS &quot;jump,noterse,name=Conan the Barbarian,fruit=mango&quot;<sup>3</sup>
+</pre></div>
+
+<h3 align="justify"><b>9.2. Option list</b></h3>
+
+<p align="justify">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.</p>
+
+<p align="justify"><b>terse</b>[<i>noterse</i>]</p>
+<blockquote>
+	<p align="justify">
+	Useful for those who are tired of the sometimes lengthy
+	messages of rogue. This is a useful option for those on slow
+	terminals. This option defaults to on if your are on a slow
+	(under 1200 baud) terminal.</p>
+</blockquote>
+
+<p align="justify"><b>jump</b>[<i>nojump</i>]</p>
+<blockquote>
+	<p align="justify">If this option is set, running moves will not be
+	displayed until you reach the end of the move. This saves
+	considerable cpu time and display time. This option defaults
+	to on if you are using a slow terminal.</p>
+</blockquote>
+
+<p align="justify"><b>step</b>[<i>nostep</i>]</p>
+<blockquote>
+	<p align="justify">When step is set, lists of things, like inventories or
+	&quot;*&quot; responses to &quot;Which item do you wish to
+	xxxx? &quot; 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.</p>
+</blockquote>
+
+<p align="justify"><b>flush</b>[<i>noflush</i>]</p>
+<blockquote>
+	<p align="justify">If flush is set, all typeahead is thrown away after each
+	round of battle. This is useful for those who type way ahead
+	and watch to their dismay as a Kobold kills them.</p>
+</blockquote>
+
+<p align="justify"><b>askme</b>[<i>noaskme</i>]</p>
+<blockquote>
+	<p align="justify">Upon reading a scroll or quaffing a potion which does
+	not automatically identify it upon use, rogue will ask you
+	what to name it so you can recognize it in the future.</p>
+</blockquote>
+
+<p align="justify"><b>name</b> [account name]</p>
+<blockquote>
+	<p align="justify">This is the name of your character. It is used if you
+	get on the top ten scorer&rsquo;s list. It should be less
+	than eighty characters long.</p>
+</blockquote>
+
+<p align="justify"><b>fruit</b>[<i>slime-mold</i>]</p>
+<blockquote>
+	<p align="justify">This should hold the name of a fruit that you enjoy
+	eating. It is basically a whimsy that the program uses in a
+	couple of places.</p>
+</blockquote>
+
+<p align="justify"><b>file</b>[<i>rogue.save</i>]</p>
+<blockquote>
+	<p align="justify">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 &quot;~&quot; which expands to be your home
+	directory.</p>
+</blockquote>
+
+<h2 align="justify"><br>
+
+<b>10. Acknowledgements</b></h2>
+
+<p align="justify">Rogue was originally conceived of by Glenn Wichman and
+Michael Toy. The help of Ken Arnold in making the program
+easier to use and putting the finishing touches on is
+greatly appreciated. I would also like to thank Marty
+McNary, Scott Nelson, Daniel Jensen, Kipp Hickman, Joe
+Kalash, Steve Maurer, Bill Joy, Mark Horton and Jan Miller
+for their ideas and assistance.</p>
+
+<table border="0" width="100%" cellspacing="3" cellpadding="0" id="table5">
+	<tr>
+		<td align="center"><sup>1</sup></td>
+		<td>As opposed to pseudo English sentences.</td>
+	</tr>
+	<tr>
+		<td align="center"><sup>2</sup></td>
+		<td>Or until you get killed or decide to quit.</td>
+	</tr>
+	<tr>
+		<td align="center"><sup>3</sup>&nbsp;&nbsp;</td>
+		<td><p>For those of you who use the Bourne shell, the commands would be</p>
+<pre>    $ ROGUEOPTS=&quot;jump,noterse,name=Conan the Barbarian,fruit=mango&quot;
+    $ export ROGUEOPTS</pre>
+		</td>
+	</tr>
+</table>
+
+</body>
+</html>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rogue3/rogue36.sln	Tue Oct 13 13:33:34 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}") = "rogue36", "rogue36.vcproj", "{B986AB16-E9C2-4299-A772-F02B28620521}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Win32 = Debug|Win32
+		Release|Win32 = Release|Win32
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{B986AB16-E9C2-4299-A772-F02B28620521}.Debug|Win32.ActiveCfg = Debug|Win32
+		{B986AB16-E9C2-4299-A772-F02B28620521}.Debug|Win32.Build.0 = Debug|Win32
+		{B986AB16-E9C2-4299-A772-F02B28620521}.Release|Win32.ActiveCfg = Release|Win32
+		{B986AB16-E9C2-4299-A772-F02B28620521}.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/rogue3/rogue36.vcproj	Tue Oct 13 13:33:34 2009 +0000
@@ -0,0 +1,360 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="8.00"
+	Name="rogue36"
+	ProjectGUID="{B986AB16-E9C2-4299-A772-F02B28620521}"
+	RootNamespace="rogue36"
+	Keyword="Win32Proj"
+	>
+	<Platforms>
+		<Platform
+			Name="Win32"
+		/>
+	</Platforms>
+	<ToolFiles>
+	</ToolFiles>
+	<Configurations>
+		<Configuration
+			Name="Debug|Win32"
+			OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+			IntermediateDirectory="$(ConfigurationName)"
+			ConfigurationType="1"
+			CharacterSet="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../pdcurses"
+				PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE;$(NOINHERIT)"
+				MinimalRebuild="false"
+				ExceptionHandling="0"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="0"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="3"
+				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"
+				LinkIncremental="1"
+				AdditionalLibraryDirectories="../pdcurses"
+				IgnoreDefaultLibraryNames="LIBC.LIB"
+				GenerateDebugInformation="true"
+				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="$(SolutionDir)$(ConfigurationName)"
+			IntermediateDirectory="$(ConfigurationName)"
+			ConfigurationType="1"
+			CharacterSet="1"
+			WholeProgramOptimization="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
+				RuntimeLibrary="2"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				LinkIncremental="1"
+				GenerateDebugInformation="true"
+				SubSystem="1"
+				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;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+			UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+			>
+			<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=".\fight.c"
+				>
+			</File>
+			<File
+				RelativePath=".\init.c"
+				>
+			</File>
+			<File
+				RelativePath=".\io.c"
+				>
+			</File>
+			<File
+				RelativePath=".\list.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=".\newlevel.c"
+				>
+			</File>
+			<File
+				RelativePath=".\options.c"
+				>
+			</File>
+			<File
+				RelativePath=".\pack.c"
+				>
+			</File>
+			<File
+				RelativePath=".\passages.c"
+				>
+			</File>
+			<File
+				RelativePath=".\potions.c"
+				>
+			</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>
+		</Filter>
+		<Filter
+			Name="Header Files"
+			Filter="h;hpp;hxx;hm;inl;inc;xsd"
+			UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+			>
+			<File
+				RelativePath=".\machdep.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;resx;tiff;tif;png;wav"
+			UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+			>
+		</Filter>
+		<File
+			RelativePath=".\LICENSE.TXT"
+			>
+		</File>
+		<File
+			RelativePath=".\Makefile"
+			>
+		</File>
+		<File
+			RelativePath=".\readme36.html"
+			>
+		</File>
+		<File
+			RelativePath=".\rogue.r"
+			>
+		</File>
+		<File
+			RelativePath=".\rogue36.cat"
+			>
+		</File>
+		<File
+			RelativePath=".\rogue36.doc"
+			>
+		</File>
+		<File
+			RelativePath=".\rogue36.html"
+			>
+		</File>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rogue3/rooms.c	Tue Oct 13 13:33:34 2009 +0000
@@ -0,0 +1,186 @@
+/*
+ * Draw the nine rooms on the screen
+ *
+ * @(#)rooms.c	3.8 (Berkeley) 6/15/81
+ *
+ * Rogue: Exploring the Dungeons of Doom
+ * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
+ * All rights reserved.
+ *
+ * See the file LICENSE.TXT for full copyright and licensing information.
+ */
+
+#include <stdlib.h>
+#include "curses.h"
+#include "rogue.h"
+
+void
+do_rooms()
+{
+    int i;
+    struct room *rp;
+    struct linked_list *item;
+    struct thing *tp;
+    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-1]; 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.y = -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(100) < 50 && (!amulet || level >= max_level))
+	{
+	    rp->r_goldval = GOLDCALC;
+	    rnd_pos(rp, &rp->r_gold);
+	    if (roomin(&rp->r_gold) != rp)
+		endwin(), abort();
+	}
+	draw_room(rp);
+	/*
+	 * Put the monster in
+	 */
+	if (rnd(100) < (rp->r_goldval > 0 ? 80 : 25))
+	{
+	    item = new_item(sizeof *tp);
+	    tp = (struct thing *) ldata(item);
+	    do
+	    {
+		rnd_pos(rp, &mp);
+	    } until(mvwinch(stdscr, mp.y, mp.x) == FLOOR);
+	    new_monster(item, randmonster(FALSE), &mp);
+	    /*
+	     * See if we want to give it a treasure to carry around.
+	     */
+	    if (rnd(100) < monsters[tp->t_type-'A'].m_carry)
+		attach(tp->t_pack, new_thing());
+	}
+    }
+}
+
+/*
+ * Draw a box around a room
+ */
+
+void
+draw_room(struct room *rp)
+{
+    int j, k;
+
+    move(rp->r_pos.y, rp->r_pos.x+1);
+    vert(rp->r_max.y-2);				/* Draw left side */
+    move(rp->r_pos.y+rp->r_max.y-1, rp->r_pos.x);
+    horiz(rp->r_max.x);					/* Draw bottom */
+    move(rp->r_pos.y, rp->r_pos.x);
+    horiz(rp->r_max.x);					/* Draw top */
+    vert(rp->r_max.y-2);				/* Draw right side */
+    /*
+     * Put the floor down
+     */
+    for (j = 1; j < rp->r_max.y-1; j++)
+    {
+	move(rp->r_pos.y + j, rp->r_pos.x+1);
+	for (k = 1; k < rp->r_max.x-1; k++)
+	    addch(FLOOR);
+    }
+    /*
+     * Put the gold there
+     */
+    if (rp->r_goldval)
+	mvaddch(rp->r_gold.y, rp->r_gold.x, GOLD);
+}
+
+/*
+ * horiz:
+ *	draw a horizontal line
+ */
+
+void
+horiz(int cnt)
+{
+    while (cnt--)
+	addch('-');
+}
+
+/*
+ * vert:
+ *	draw a vertical line
+ */
+
+void
+vert(int cnt)
+{
+    int x, y;
+
+    getyx(stdscr, y, x);
+    x--;
+    while (cnt--) {
+	move(++y, x);
+	addch('|');
+    }
+}
+
+/*
+ * rnd_pos:
+ *	pick a random spot in a room
+ */
+
+void
+rnd_pos(struct room *rp, 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;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rogue3/save.c	Tue Oct 13 13:33:34 2009 +0000
@@ -0,0 +1,297 @@
+/*
+ * save and restore routines
+ *
+ * @(#)save.c	3.9 (Berkeley) 6/16/81
+ *
+ * Rogue: Exploring the Dungeons of Doom
+ * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
+ * All rights reserved.
+ *
+ * See the file LICENSE.TXT for full copyright and licensing information.
+ */
+
+#include "curses.h"
+#include <ctype.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <signal.h>
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+#include "machdep.h"
+#include "rogue.h"
+
+typedef struct stat STAT;
+
+extern char version[], encstr[];
+
+STAT sbuf;
+
+int
+save_game()
+{
+    FILE *savef;
+    int c;
+    char buf[80];
+
+    /*
+     * get file name
+     */
+    mpos = 0;
+    if (file_name[0] != '\0')
+    {
+	msg("Save file (%s)? ", file_name);
+	do
+	{
+	    c = readchar(cw);
+	} while (c != 'n' && c != 'N' && c != 'y' && c != 'Y');
+	mpos = 0;
+	if (c == 'y' || c == 'Y')
+	{
+	    msg("File name: %s", file_name);
+	    goto gotfile;
+	}
+    }
+
+    do
+    {
+	msg("File name: ");
+	mpos = 0;
+	buf[0] = '\0';
+	if (get_str(buf, cw) == QUIT)
+	{
+	    msg("");
+	    return FALSE;
+	}
+	strcpy(file_name, buf);
+gotfile:
+	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
+     */
+    if (save_file(savef) != 0)
+    {
+        msg("Save game failed!");
+        return FALSE;
+    }
+    return TRUE;
+}
+
+/*
+ * automatically save a file.  This is used if a HUP signal is
+ * recieved
+ */
+void
+auto_save(int p)
+{
+    FILE *savef;
+    int i;
+
+    for (i = 0; i < NSIG; i++)
+	signal(i, SIG_IGN);
+    if (file_name[0] != '\0' && (savef = fopen(file_name, "w")) != NULL)
+	save_file(savef);
+    endwin();
+    exit(1);
+}
+
+/*
+ * write the saved game on the file
+ */
+int
+save_file(FILE *savef)
+{
+    char buf[80];
+    int ret;
+
+    wmove(cw, LINES-1, 0);
+    draw(cw);
+    (void) fseek(savef, 0L, 0);
+
+    memset(buf,0,80);
+    strcpy(buf,version);
+    encwrite(buf,80,savef);
+    memset(buf,0,80);
+    strcpy(buf,"R36 2\n");
+    encwrite(buf,80,savef);
+    memset(buf,0,80);
+    sprintf(buf,"%d x %d\n", LINES, COLS);
+    encwrite(buf,80,savef);
+
+    ret = rs_save_file(savef);
+
+    fclose(savef);
+
+    return(ret);
+}
+
+int
+restore(char *file, char **envp)
+{
+    FILE *inf;
+    extern char **environ;
+    char buf[80];
+    int slines, scols;
+    int rogue_version = 0, savefile_version = 0;
+
+    if (strcmp(file, "-r") == 0)
+	file = file_name;
+
+    if ((inf = fopen(file, "r")) == NULL)
+    {
+	perror(file);
+	return FALSE;
+    }
+
+    fflush(stdout);
+    encread(buf, 80, inf);
+
+    if (strcmp(buf, version) != 0)
+    {
+	printf("Sorry, saved game is out of date.\n");
+	return FALSE;
+    }
+
+    encread(buf, 80, inf);
+    (void) sscanf(buf, "R%d %d\n", &rogue_version, &savefile_version);
+
+    if ((rogue_version != 36) && (savefile_version != 2))
+    {
+	printf("Sorry, saved game format is out of date.\n");
+	return FALSE;
+    }
+
+    encread(buf,80,inf);
+    (void) sscanf(buf,"%d x %d\n",&slines, &scols);
+
+    /*
+     * 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)
+    {
+	endwin();
+	printf("Sorry, original game was played on a screen with %d lines.\n",slines);
+	printf("Current screen only has %d lines. Unable to restore game\n",LINES);
+	return(FALSE);
+    }
+	
+    if (scols > COLS)
+    {
+	endwin();
+	printf("Sorry, original game was played on a screen with %d columns.\n",scols);
+	printf("Current screen only has %d columns. Unable to restore game\n",COLS);
+	return(FALSE);
+    }
+    
+    cw = newwin(LINES, COLS, 0, 0);
+    mw = newwin(LINES, COLS, 0, 0);
+    hw = newwin(LINES, COLS, 0, 0);
+    nocrmode();
+    keypad(cw,1);
+    mpos = 0;
+    mvwprintw(cw, 0, 0, "%s", file);
+
+    if (rs_restore_file(inf) != 0)
+    {
+	endwin();
+	printf("Cannot restore file\n");
+    	return(FALSE);
+    }
+	
+    if (!wizard && (md_unlink_open_file(file, inf) < 0))
+    {
+	endwin();
+    	printf("Cannot unlink file\n");
+	return FALSE;
+    }
+
+    environ = envp;
+    strcpy(file_name, file);
+    setup();
+    clearok(curscr, TRUE);
+    touchwin(cw);
+    srand(md_getpid());
+    status();
+    playit();
+    /*NOTREACHED*/
+    return(0);
+}
+
+static int encerrno = 0;
+
+int
+encerror()
+{
+    return encerrno;
+}
+
+void
+encseterr(int err)
+{
+    encerrno = err;
+}
+
+int
+encclearerr()
+{
+    int n = encerrno;
+
+    encerrno = 0;
+
+    return(n);
+}
+
+/*
+ * perform an encrypted write
+ */
+size_t
+encwrite(const void *buf, size_t size, FILE *outf)
+{
+    char *ep;
+    const char *start = buf;
+    size_t o_size = size;
+    ep = encstr;
+
+    while (size)
+    {
+	if (putc(*start++ ^ *ep++, outf) == EOF)
+	    return(o_size - size);
+	if (*ep == '\0')
+	    ep = encstr;
+	size--;
+    }
+
+    return(o_size - size);
+}
+
+/*
+ * perform an encrypted read
+ */
+size_t
+encread(void *buf, size_t size, FILE *inf)
+{
+    char *ep;
+    size_t read_size;
+    char *start = buf;
+
+    if ((read_size = fread(start,1,size,inf)) == 0)
+	return 0;
+
+    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/rogue3/scrolls.c	Tue Oct 13 13:33:34 2009 +0000
@@ -0,0 +1,317 @@
+
+/*
+ * Read a scroll and let it happen
+ *
+ * @(#)scrolls.c	3.5 (Berkeley) 6/15/81
+ *
+ * Rogue: Exploring the Dungeons of Doom
+ * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
+ * All rights reserved.
+ *
+ * See the file LICENSE.TXT for full copyright and licensing information.
+ */
+
+#include "curses.h"
+#include <stdlib.h>
+#include <ctype.h>
+#include <string.h>
+#include "rogue.h"
+
+void
+read_scroll()
+{
+    struct object *obj;
+    struct linked_list *item;
+    struct room *rp;
+    int i,j;
+    int ch, nch;
+    struct linked_list *titem;
+    char buf[80];
+
+    item = get_item("read", SCROLL);
+    if (item == NULL)
+	return;
+    obj = (struct object *) ldata(item);
+    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.
+	     */
+	    msg("Your hands begin to glow red");
+	    player.t_flags |= CANHUH;
+	when S_LIGHT:
+	    s_know[S_LIGHT] = TRUE;
+	    if ((rp = roomin(&hero)) == NULL)
+		msg("The corridor glows and then fades");
+	    else
+	    {
+		addmsg("The room is lit");
+		if (!terse)
+		    addmsg(" by a shimmering blue light.");
+		endmsg();
+		rp->r_flags &= ~ISDARK;
+		/*
+		 * Light the room and put the player back up
+		 */
+		light(&hero);
+		mvwaddch(cw, hero.y, hero.x, PLAYER);
+	    }
+	when S_ARMOR:
+	    if (cur_armor != NULL)
+	    {
+		msg("Your armor glows faintly for a moment");
+		cur_armor->o_ac--;
+		cur_armor->o_flags &= ~ISCURSED;
+	    }
+	when S_HOLD:
+	    /*
+	     * Hold monster scroll.  Stop all monsters within two spaces
+	     * from chasing after the hero.
+	     */
+	    {
+		int x,y;
+		struct linked_list *mon;
+
+		for (x = hero.x-2; x <= hero.x+2; x++)
+		    for (y = hero.y-2; y <= hero.y+2; y++)
+			if (y > 0 && x > 0 && isupper(mvwinch(mw, y, x)))
+			    if ((mon = find_mons(y, x)) != NULL)
+			    {
+				struct thing *th;
+
+				th = (struct thing *) ldata(mon);
+				th->t_flags &= ~ISRUN;
+				th->t_flags |= ISHELD;
+			    }
+	    }
+	when S_SLEEP:
+	    /*
+	     * Scroll which makes you fall asleep
+	     */
+	    s_know[S_SLEEP] = TRUE;
+	    msg("You fall asleep.");
+	    no_command += 4 + rnd(SLEEPTIME);
+	when S_CREATE:
+	    /*
+	     * Create a monster
+	     * First look in a circle around him, next try his room
+	     * otherwise give up
+	     */
+	    {
+		int x, y;
+		int 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
+			 */
+			if (step_ok(winat(y, x)))
+			{
+			    if (rnd(++appear) == 0)
+			    {
+				mp.y = y;
+				mp.x = x;
+			    }
+			}
+		    }
+		if (appear)
+		{
+		    titem = new_item(sizeof (struct thing));
+		    new_monster(titem, 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
+	     */
+	    msg("This scroll is an identify scroll");
+	    s_know[S_IDENT] = TRUE;
+	    whatis();
+	when S_MAP:
+	    /*
+	     * Scroll of magic mapping.
+	     */
+	    s_know[S_MAP] = TRUE;
+	    msg("Oh, now this scroll has a map on it.");
+	    overwrite(stdscr, hw);
+	    /*
+	     * Take all the things we want to keep hidden out of the window
+	     */
+	    for (i = 0; i < LINES; i++)
+		for (j = 0; j < COLS; j++)
+		{
+		    switch (nch = ch = mvwinch(hw, i, j))
+		    {
+			case SECRETDOOR:
+                            nch = DOOR;
+			    mvaddch(i, j, nch);
+			case '-':
+			case '|':
+			case DOOR:
+			case PASSAGE:
+			case ' ':
+			case STAIRS:
+			    if (mvwinch(mw, i, j) != ' ')
+			    {
+				struct thing *it;
+
+				it = (struct thing *) ldata(find_mons(i, j));
+				if ((it != NULL) && (it->t_oldch == ' '))
+				    it->t_oldch = nch;
+			    }
+			    break;
+			default:
+			    nch = ' ';
+		    }
+		    if (nch != ch)
+			waddch(hw, nch);
+		}
+	    /*
+	     * Copy in what he has discovered
+	     */
+	    overlay(cw, hw);
+	    /*
+	     * And set up for display
+	     */
+	    overwrite(hw, cw);
+	when S_GFIND:
+	    /*
+	     * Potion of gold detection
+	     */
+	    {
+		int gtotal = 0;
+
+		wclear(hw);
+		for (i = 0; i < MAXROOMS; i++)
+		{
+		    gtotal += rooms[i].r_goldval;
+		    if (rooms[i].r_goldval != 0 &&
+			mvwinch(stdscr, rooms[i].r_gold.y, rooms[i].r_gold.x)
+			== GOLD)
+			mvwaddch(hw,rooms[i].r_gold.y,rooms[i].r_gold.x,GOLD);
+		}
+		if (gtotal)
+		{
+		    s_know[S_GFIND] = TRUE;
+		    show_win(hw,
+			"You begin to feel greedy and you sense gold.--More--");
+		}
+		else msg("You begin to feel a pull downward");
+	    }
+	when S_TELEP:
+	    /*
+	     * Scroll of teleportation:
+	     * Make him dissapear and reappear
+	     */
+	    {
+		int rm;
+		struct room *cur_room;
+
+		cur_room = roomin(&hero);
+		rm = teleport();
+		if (cur_room != &rooms[rm])
+		    s_know[S_TELEP] = TRUE;
+	    }
+	when S_ENCH:
+	    if (cur_weapon == NULL)
+		msg("You feel a strange sense of loss.");
+	    else
+	    {
+		cur_weapon->o_flags &= ~ISCURSED;
+		if (rnd(100) > 50)
+		    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:
+	    /*
+	     * A monster will refuse to step on a scare monster scroll
+	     * if it is dropped.  Thus reading it is a mistake and produces
+	     * laughter at the poor rogue's boo boo.
+	     */
+	    msg("You hear maniacal laughter in the distance.");
+	when S_REMOVE:
+	    if (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:
+	    msg("You have been granted the boon of genocide");
+	    genocide();
+	    s_know[S_GENOCIDE] = TRUE;
+	otherwise:
+	    msg("What a puzzling scroll!");
+	    return;
+    }
+    look(TRUE);	/* put the result of the scroll on the screen */
+    status();
+    if (s_know[obj->o_which] && s_guess[obj->o_which])
+    {
+	free(s_guess[obj->o_which]);
+	s_guess[obj->o_which] = NULL;
+    }
+    else if (!s_know[obj->o_which] && askme && s_guess[obj->o_which] == NULL)
+    {
+	msg(terse ? "Call it: " : "What do you want to call it? ");
+	if (get_str(buf, cw) == NORM)
+	{
+	    s_guess[obj->o_which] = malloc((unsigned int) strlen(buf) + 1);
+	    if (s_guess[obj->o_which] != NULL)
+		strcpy(s_guess[obj->o_which], buf);
+	}
+    }
+    /*
+     * Get rid of the thing
+     */
+    inpack--;
+    if (obj->o_count > 1)
+	obj->o_count--;
+    else
+    {
+	detach(pack, item);
+        discard(item);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rogue3/state.c	Tue Oct 13 13:33:34 2009 +0000
@@ -0,0 +1,1385 @@
+/*
+    state.c - Portable Rogue Save State Code
+
+    Copyright (C) 1999, 2000, 2005, 2007, 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.
+*/
+
+#include <stdlib.h>
+#include <string.h>
+#include <curses.h>
+#include <errno.h>
+#include "rogue.h"
+
+/************************************************************************/
+/* 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
+
+#define READSTAT (format_error || read_error )
+#define WRITESTAT (write_error)
+
+static int read_error   = FALSE;
+static int write_error  = FALSE;
+static int format_error = FALSE;
+static int endian = 0x01020304;
+#define  big_endian ( *((char *)&endian) == 0x01 )
+
+void
+rs_write(FILE *savef, const void *ptr, size_t size)
+{
+    encwrite(ptr, size, savef);
+}
+
+void
+rs_read(FILE *savef, void *ptr, size_t size)
+{
+    encread(ptr, size, savef);
+}
+
+void
+rs_write_int(FILE *savef, int c)
+{
+    char bytes[4];
+    char *buf = (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);
+}
+
+void
+rs_read_int(FILE *savef, int *i)
+{
+    char bytes[4];
+    int input = 0;
+    char *buf = (char *)&input;
+    
+    rs_read(savef, &input, 4);
+
+    if (encerror())
+	return;
+
+    if (big_endian)
+    {
+        bytes[3] = buf[0];
+        bytes[2] = buf[1];
+        bytes[1] = buf[2];
+        bytes[0] = buf[3];
+        buf = bytes;
+    }
+    
+    *i = *((int *) buf);
+}
+
+void
+rs_write_uint(FILE *savef, unsigned int c)
+{
+    char bytes[4];
+    char *buf = (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);
+}
+
+void
+rs_read_uint(FILE *savef, unsigned int *i)
+{
+    char bytes[4];
+    int input = 0;
+    char *buf = (char *)&input;
+    
+    rs_read(savef, &input, 4);
+
+    if (encerror())
+	return;
+
+    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);
+}
+
+void
+rs_write_chars(FILE *savef, const char *c, int cnt)
+{
+    rs_write_int(savef, cnt);
+    rs_write(savef, c, cnt);
+}
+
+void
+rs_read_chars(FILE *savef, char *i, int cnt)
+{
+    int value = 0;  
+
+    rs_read_int(savef, &value);
+    
+    if (!encerror() && (value != cnt))
+	encseterr(EILSEQ);
+
+    rs_read(savef, i, cnt);
+}
+
+void
+rs_write_ints(FILE *savef, int *c, int cnt)
+{
+    int n = 0;
+
+    rs_write_int(savef, cnt);
+
+    for(n = 0; n < cnt; n++)
+        rs_write_int(savef,c[n]);
+}
+
+void
+rs_read_ints(FILE *savef, int *i, int cnt)
+{
+    int n, value;
+    
+    rs_read_int(savef,&value);
+
+    if (!encerror() && (value != cnt))
+	encseterr(EILSEQ);
+
+    for(n = 0; n < cnt; n++)
+        rs_read_int(savef, &i[n]);
+}
+
+void
+rs_write_marker(FILE *savef, int id)
+{
+    rs_write_int(savef, id);
+}
+
+void
+rs_read_marker(FILE *savef, int id)
+{
+    int nid;
+
+    rs_read_int(savef, &nid);
+
+    if (!encerror() && (id != nid))
+	encseterr(EILSEQ);
+}
+
+/******************************************************************************/
+
+void
+rs_write_string(FILE *savef, const char *s)
+{
+    int len = 0;
+
+    len = (s == NULL) ? 0 : (int) strlen(s) + 1;
+
+    rs_write_int(savef, len);
+    rs_write_chars(savef, s, len);
+}
+
+void
+rs_read_string(FILE *savef, char *s, int max)
+{
+    int len = 0;
+
+    rs_read_int(savef, &len);
+
+    if (!encerror() && (len > max))
+	encseterr(EILSEQ);
+
+    rs_read_chars(savef, s, len);
+}
+
+void
+rs_read_new_string(FILE *savef, char **s)
+{
+    int len=0;
+    char *buf=0;
+
+    rs_read_int(savef, &len);
+
+    if (encerror())
+	return;
+
+    if (len == 0)
+        buf = NULL;
+    else
+    { 
+        buf = malloc(len);
+
+        if (buf == NULL)            
+            encseterr(ENOMEM);
+    }
+
+    rs_read_chars(savef, buf, len);
+
+    *s = buf;
+}
+
+void
+rs_write_string_index(FILE *savef, char *master[], int max, char *str)
+{
+    int i;
+
+    for(i = 0; i < max; i++)
+        if (str == master[i])
+        {
+            rs_write_int(savef, i);
+            return;
+        }
+
+    rs_write_int(savef,-1);
+}
+
+void
+rs_read_string_index(FILE *savef, char *master[], int maxindex, char **str)
+{
+    int i;
+
+    rs_read_int(savef, &i);
+
+    if (!encerror() && (i > maxindex))
+        encseterr(EILSEQ);
+    else if (i >= 0)
+        *str = master[i];
+    else
+        *str = NULL;
+}
+
+void
+rs_write_coord(FILE *savef, coord c)
+{
+    rs_write_int(savef, c.x);
+    rs_write_int(savef, c.y);
+}
+
+void
+rs_read_coord(FILE *savef, coord *c)
+{
+    coord in;
+
+    rs_read_int(savef,&in.x);
+    rs_read_int(savef,&in.y);
+
+    if (!encerror()) 
+    {
+        c->x = in.x;
+        c->y = in.y;
+    }
+}
+
+void
+rs_write_str_t(FILE *savef, str_t str)
+{
+    rs_write_int(savef, str.st_str);
+    rs_write_int(savef, str.st_add);
+}
+
+void
+rs_read_str_t(FILE *savef, str_t *str)
+{
+    str_t in;
+
+    rs_read_int(savef,&in.st_str);
+    rs_read_int(savef,&in.st_add);
+
+    if (!encerror()) 
+    {
+        str->st_str = in.st_str;
+	str->st_add = in.st_add;
+    }
+}
+
+void
+rs_write_window(FILE *savef, WINDOW *win)
+{
+    int row,col,height,width;
+
+    width  = getmaxx(win);
+    height = getmaxy(win);
+
+    rs_write_marker(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));
+}
+
+void
+rs_read_window(FILE *savef, WINDOW *win)
+{
+    int row,col,maxlines,maxcols,value,width,height;
+    
+    width  = getmaxx(win);
+    height = getmaxy(win);
+
+    rs_read_marker(savef, RSID_WINDOW);
+
+    rs_read_int(savef, &maxlines);
+    rs_read_int(savef, &maxcols);
+
+    if (encerror())
+	return;
+
+    for(row = 0; row < maxlines; row++)
+        for(col = 0; col < maxcols; col++)
+        {
+            rs_read_int(savef, &value);
+
+            if ((row < height) && (col < width))
+                mvwaddch(win,row,col,value);
+        }
+}
+
+/******************************************************************************/
+
+void *
+get_list_item(struct linked_list *l, int i)
+{
+    int cnt;
+
+    for(cnt = 0; l != NULL; cnt++, l = l->l_next)
+        if (cnt == i)
+            return(l->l_data);
+    
+    return(NULL);
+}
+
+int
+find_list_ptr(struct linked_list *l, void *ptr)
+{
+    int cnt;
+
+    for(cnt = 0; l != NULL; cnt++, l = l->l_next)
+        if (l->l_data == ptr)
+            return(cnt);
+               
+    return(-1);
+}
+
+int
+list_size(struct linked_list *l)
+{
+    int cnt;
+    
+    for(cnt = 0; l != NULL; cnt++, l = l->l_next)
+        if (l->l_data == NULL)
+            return(cnt);
+    
+    return(cnt);
+}
+
+/******************************************************************************/
+
+void
+rs_write_stats(FILE *savef, struct stats *s)
+{
+    rs_write_marker(savef, RSID_STATS);
+    rs_write_str_t(savef, s->s_str);
+    rs_write_int(savef, s->s_exp);
+    rs_write_int(savef, s->s_lvl);
+    rs_write_int(savef, s->s_arm);
+    rs_write_int(savef, s->s_hpt);
+    rs_write_chars(savef, s->s_dmg, sizeof(s->s_dmg));
+}
+
+
+void
+rs_read_stats(FILE *savef, struct stats *s)
+{
+    rs_read_marker(savef, RSID_STATS);
+    rs_read_str_t(savef,&s->s_str);
+    rs_read_int(savef,&s->s_exp);
+    rs_read_int(savef,&s->s_lvl);
+    rs_read_int(savef,&s->s_arm);
+    rs_read_int(savef,&s->s_hpt);
+    rs_read_chars(savef,s->s_dmg,sizeof(s->s_dmg));
+}
+
+        
+void
+rs_write_scrolls(FILE *savef)
+{
+    int i;
+
+    for(i = 0; i < MAXSCROLLS; i++)
+    {
+        rs_write_string(savef,s_names[i]);
+        rs_write_int(savef,s_know[i]);
+        rs_write_string(savef,s_guess[i]);
+    }
+}
+
+void
+rs_read_scrolls(FILE *savef)
+{
+    int i;
+
+    for(i = 0; i < MAXSCROLLS; i++)
+    {
+        rs_read_new_string(savef,&s_names[i]);
+        rs_read_int(savef,&s_know[i]);
+        rs_read_new_string(savef,&s_guess[i]);
+    }
+}
+
+void
+rs_write_potions(FILE *savef)
+{
+    int i;
+
+    for(i = 0; i < MAXPOTIONS; i++)
+    {
+        rs_write_string_index(savef, rainbow, cNCOLORS, p_colors[i]);
+        rs_write_int(savef,p_know[i]);
+        rs_write_string(savef,p_guess[i]);
+    }
+}
+
+void
+rs_read_potions(FILE *savef)
+{
+    int i;
+
+    for(i = 0; i < MAXPOTIONS; i++)
+    {
+        rs_read_string_index(savef, rainbow, cNCOLORS, &p_colors[i]);
+        rs_read_int(savef,&p_know[i]);
+        rs_read_new_string(savef,&p_guess[i]);
+    }
+}
+
+void
+rs_write_rings(FILE *savef)
+{
+    int i;
+
+    for(i = 0; i < MAXRINGS; i++)
+    {
+        rs_write_string_index(savef, stones, cNSTONES, r_stones[i]);
+        rs_write_int(savef,r_know[i]);
+        rs_write_string(savef,r_guess[i]);
+    }
+}
+
+void
+rs_read_rings(FILE *savef)
+{
+    int i;
+
+    for(i = 0; i < MAXRINGS; i++)
+    {
+        rs_read_string_index(savef, stones, cNSTONES, &r_stones[i]);
+        rs_read_int(savef,&r_know[i]);
+        rs_read_new_string(savef,&r_guess[i]);
+    }
+}
+
+void
+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, cNWOOD, ws_made[i]);
+        }
+        else
+        {
+            rs_write_int(savef,1);
+            rs_write_string_index(savef, metal, cNMETAL, ws_made[i]);
+        }
+        rs_write_int(savef, ws_know[i]);
+        rs_write_string(savef, ws_guess[i]);
+    }
+}
+
+void
+rs_read_sticks(FILE *savef)
+{
+    int i = 0, list = 0;
+
+    for(i = 0; i < MAXSTICKS; i++)
+    { 
+        rs_read_int(savef,&list);
+
+	if (list == 0)
+        {
+            rs_read_string_index(savef, wood, cNWOOD, &ws_made[i]);
+            ws_type[i] = "staff";
+        }
+        else 
+        {
+            rs_read_string_index(savef, metal, cNMETAL, &ws_made[i]);
+            ws_type[i] = "wand";
+        }
+        rs_read_int(savef, &ws_know[i]);
+        rs_read_new_string(savef, &ws_guess[i]);
+    }
+}
+
+void
+rs_write_daemons(FILE *savef, struct delayed_action *dlist, int cnt)
+{
+    int i = 0;
+    int func = 0;
+        
+    rs_write_marker(savef, RSID_DAEMONS);
+    rs_write_int(savef, cnt);
+        
+    for(i = 0; i < cnt; i++)
+    {
+        if (dlist[i].d_func == rollwand)
+            func = 1;
+        else if (dlist[i].d_func == doctor)
+            func = 2;
+        else if (dlist[i].d_func == stomach)
+            func = 3;
+        else if (dlist[i].d_func == runners)
+            func = 4;
+        else if (dlist[i].d_func == swander)
+            func = 5;
+        else if (dlist[i].d_func == nohaste)
+            func = 6;
+        else if (dlist[i].d_func == unconfuse)
+            func = 7;
+        else if (dlist[i].d_func == unsee)
+            func = 8;
+        else if (dlist[i].d_func == sight)
+            func = 9;
+        else if (dlist[i].d_func == NULL)
+            func = 0;
+        else
+            func = -1;
+
+        rs_write_int(savef, dlist[i].d_type);
+        rs_write_int(savef, func);
+        rs_write_int(savef, dlist[i].d_arg);
+        rs_write_int(savef, dlist[i].d_time);
+    }
+}       
+
+void
+rs_read_daemons(FILE *savef, struct delayed_action *dlist, int cnt)
+{
+    int i = 0;
+    int func = 0;
+    int value = 0;
+
+    rs_read_marker(savef, RSID_DAEMONS);
+    rs_read_int(savef, &value);
+
+    if (!encerror() && (value > cnt))
+    {
+	encseterr(EILSEQ);
+	return;
+    }
+
+    for(i=0; i < cnt; i++)
+    {
+	func = 0;
+        rs_read_int(savef, &dlist[i].d_type);
+        rs_read_int(savef, &func);
+        rs_read_int(savef, &dlist[i].d_arg);
+        rs_read_int(savef, &dlist[i].d_time);
+
+	if (encerror())
+	    return;
+                    
+        switch(func)
+        {
+	    case 1: dlist[i].d_func = rollwand;
+		    break;
+	    case 2: dlist[i].d_func = doctor;
+                    break;
+            case 3: dlist[i].d_func = stomach;
+                    break;
+            case 4: dlist[i].d_func = runners;
+                    break;
+            case 5: dlist[i].d_func = swander;
+                    break;
+            case 6: dlist[i].d_func = nohaste;
+                    break;
+            case 7: dlist[i].d_func = unconfuse;
+                    break;
+            case 8: dlist[i].d_func = unsee;
+                    break;
+            case 9: dlist[i].d_func = sight;
+                    break;
+            default:dlist[i].d_func = NULL;
+                    break;
+	}   
+    }
+
+    if (dlist[i].d_func == NULL)
+    {
+        dlist[i].d_type = 0;
+        dlist[i].d_arg = 0;
+        dlist[i].d_time = 0;
+    } 
+}       
+
+void
+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_int(savef, r->r_flags);
+    rs_write_int(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]);
+}
+
+void
+rs_read_room(FILE *savef, struct room *r)
+{
+    rs_read_coord(savef,&r->r_pos);
+    rs_read_coord(savef,&r->r_max);
+    rs_read_coord(savef,&r->r_gold);
+    rs_read_int(savef,&r->r_goldval);
+    rs_read_int(savef,&r->r_flags);
+    rs_read_int(savef,&r->r_nexits);
+    rs_read_coord(savef,&r->r_exit[0]);
+    rs_read_coord(savef,&r->r_exit[1]);
+    rs_read_coord(savef,&r->r_exit[2]);
+    rs_read_coord(savef,&r->r_exit[3]);
+}
+
+void
+rs_write_rooms(FILE *savef, struct room r[], int cnt)
+{
+    int n = 0;
+
+    rs_write_int(savef, cnt);
+    
+    for(n = 0; n < cnt; n++)
+        rs_write_room(savef, &r[n]);
+}
+
+void
+rs_read_rooms(FILE *savef, struct room *r, int cnt)
+{
+    int value = 0, n = 0;
+
+    rs_read_int(savef,&value);
+
+    if (!encerror() && (value > cnt))
+        encseterr(EILSEQ);
+    else
+        for(n = 0; n < value; n++)
+            rs_read_room(savef,&r[n]);
+}
+
+void
+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);
+}
+
+void
+rs_read_room_reference(FILE *savef, struct room **rp)
+{
+    int i;
+    
+    rs_read_int(savef, &i);
+
+    if (!encerror())
+        *rp = &rooms[i];
+}
+
+void
+rs_write_object(FILE *savef, struct object *o)
+{
+    rs_write_marker(savef, RSID_OBJECT);
+    rs_write_int(savef, o->o_type);
+    rs_write_coord(savef, o->o_pos);
+    rs_write_int(savef, o->o_launch);
+    rs_write_chars(savef, o->o_damage, sizeof(o->o_damage));
+    rs_write_chars(savef, o->o_hurldmg, sizeof(o->o_hurldmg));
+    rs_write_int(savef, o->o_count);
+    rs_write_int(savef, o->o_which);
+    rs_write_int(savef, o->o_hplus);
+    rs_write_int(savef, o->o_dplus);
+    rs_write_int(savef, o->o_ac);
+    rs_write_int(savef, o->o_flags);
+    rs_write_int(savef, o->o_group);
+}
+
+void
+rs_read_object(FILE *savef, struct object *o)
+{
+    rs_read_marker(savef, RSID_OBJECT);
+    rs_read_int(savef, &o->o_type);
+    rs_read_coord(savef, &o->o_pos);
+    rs_read_int(savef, &o->o_launch);
+    rs_read_chars(savef, o->o_damage, sizeof(o->o_damage));
+    rs_read_chars(savef, o->o_hurldmg, sizeof(o->o_hurldmg));
+    rs_read_int(savef, &o->o_count);
+    rs_read_int(savef, &o->o_which);
+    rs_read_int(savef, &o->o_hplus);
+    rs_read_int(savef, &o->o_dplus);
+    rs_read_int(savef,&o->o_ac);
+    rs_read_int(savef,&o->o_flags);
+    rs_read_int(savef,&o->o_group);
+}
+
+void
+rs_write_object_list(FILE *savef, struct linked_list *l)
+{
+    rs_write_marker(savef, RSID_OBJECTLIST);
+    rs_write_int(savef, list_size(l));
+
+    for( ;l != NULL; l = l->l_next) 
+        rs_write_object(savef, (struct object *) l->l_data);  
+}
+
+void
+rs_read_object_list(FILE *savef, struct linked_list **list)
+{
+    int i, cnt;
+    struct linked_list *l = NULL, *previous = NULL, *head = NULL;
+
+    rs_read_marker(savef, RSID_OBJECTLIST);
+    rs_read_int(savef, &cnt);
+
+    if (encerror())
+	return;
+
+    for (i = 0; i < cnt; i++) 
+    {
+	l = new_item(sizeof(struct object));
+
+        memset(l->l_data,0,sizeof(struct object));
+
+        l->l_prev = previous;
+
+        if (previous != NULL)
+	    previous->l_next = l;
+
+        rs_read_object(savef,(struct object *) l->l_data);
+
+        if (previous == NULL)
+	    head = l;
+
+        previous = l;
+    }
+            
+    if (l != NULL)
+	l->l_next = NULL;
+    
+    *list = head;
+}
+
+void
+rs_write_object_reference(FILE *savef, struct linked_list *list, struct object *item)
+{
+    int i;
+    
+    i = find_list_ptr(list, item);
+
+    rs_write_int(savef, i);
+}
+
+void
+rs_read_object_reference(FILE *savef, struct linked_list *list, struct object **item)
+{
+    int i;
+    
+    rs_read_int(savef, &i);
+
+    if (!encerror())
+	*item = get_list_item(list,i);
+    else
+	*item = NULL;
+}
+
+int
+find_room_coord(const struct room *rmlist, const 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_thing_coord(struct linked_list *monlist, coord *c)
+{
+    struct linked_list *mitem;
+    struct thing *tp;
+    int i = 0;
+
+    for(mitem = monlist; mitem != NULL; mitem = mitem->l_next)
+    {
+        tp = THINGPTR(mitem);
+
+        if (c == &tp->t_pos)
+            return(i);
+
+        i++;
+    }
+
+    return(-1);
+}
+
+int
+find_object_coord(struct linked_list *objlist, coord *c)
+{
+    struct linked_list *oitem;
+    struct object *obj;
+    int i = 0;
+
+    for(oitem = objlist; oitem != NULL; oitem = oitem->l_next)
+    {
+        obj = OBJPTR(oitem);
+
+        if (c == &obj->o_pos)
+            return(i);
+
+        i++;
+    }
+
+    return(-1);
+}
+
+void
+rs_write_thing(FILE *savef, struct thing *t)
+{
+    int i = -1;
+
+    rs_write_marker(savef, RSID_THING);
+
+    if (t == NULL)
+    {
+        rs_write_int(savef, 0);
+        return;
+    }
+
+    rs_write_int(savef, 1);
+    rs_write_coord(savef, t->t_pos);
+    rs_write_int(savef, t->t_turn);
+    rs_write_int(savef, t->t_type);
+    rs_write_int(savef, t->t_disguise);
+    rs_write_int(savef, 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_int(savef, t->t_flags);
+    rs_write_stats(savef, &t->t_stats);
+    rs_write_object_list(savef, t->t_pack);
+}
+
+void
+rs_read_thing(FILE *savef, struct thing *t)
+{
+    int listid = 0, index = -1;
+    struct linked_list *item;
+        
+    rs_read_marker(savef, RSID_THING);
+    rs_read_int(savef, &index);
+
+    if (encerror())
+	return;
+
+    if (index == 0)
+        return;
+
+    rs_read_coord(savef,&t->t_pos);
+    rs_read_int(savef,&t->t_turn);
+    rs_read_int(savef,&t->t_type);
+    rs_read_int(savef,&t->t_disguise);
+    rs_read_int(savef,&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(savef, &listid);
+    rs_read_int(savef, &index);
+    t->t_reserved = -1;
+
+    if (encerror())
+	return;
+
+    if (listid == 0) /* hero or NULL */
+    {
+	if (index == 1)
+	    t->t_dest = &hero;
+        else
+	    t->t_dest = NULL;
+    }
+    else if (listid == 1) /* monster/thing */
+    {
+	t->t_dest     = NULL;
+        t->t_reserved = index;
+    }
+    else if (listid == 2) /* object */
+    {
+	struct object *obj;
+
+        item = get_list_item(lvl_obj,index);
+
+        if (item != NULL)
+	{
+	    obj = OBJPTR(item);
+            t->t_dest = &obj->o_pos;	
+	}
+    }
+    else if (listid == 3) /* gold */
+    {
+	t->t_dest = &rooms[index].r_gold;
+    }
+    else
+	t->t_dest = NULL;
+            
+    rs_read_int(savef,&t->t_flags);
+    rs_read_stats(savef,&t->t_stats);
+    rs_read_object_list(savef,&t->t_pack);
+}
+
+void
+rs_fix_thing(struct thing *t)
+{
+    struct linked_list *item;
+    struct thing *tp;
+
+    if (t->t_reserved < 0)
+        return;
+
+    item = get_list_item(mlist,t->t_reserved);
+
+    if (item != NULL)
+    {
+        tp = THINGPTR(item);
+        t->t_dest = &tp->t_pos;
+    }
+}
+
+void
+rs_write_thing_list(FILE *savef, struct linked_list *l)
+{
+    int cnt = 0;
+    
+    rs_write_marker(savef, RSID_MONSTERLIST);
+
+    cnt = list_size(l);
+
+    rs_write_int(savef, cnt);
+
+    if (cnt < 1)
+        return;
+
+    while (l != NULL) {
+        rs_write_thing(savef, (struct thing *)l->l_data);
+        l = l->l_next;
+    }
+}
+
+void
+rs_read_thing_list(FILE *savef, struct linked_list **list)
+{
+    int i, cnt;
+    struct linked_list *l = NULL, *previous = NULL, *head = NULL;
+
+    rs_read_marker(savef, RSID_MONSTERLIST);
+    rs_read_int(savef, &cnt);
+
+    if (encerror())
+	return;
+
+    for (i = 0; i < cnt; i++) 
+    {
+	l = new_item(sizeof(struct thing));
+
+        l->l_prev = previous;
+        
+	if (previous != NULL)
+	    previous->l_next = l;
+
+	rs_read_thing(savef,(struct thing *)l->l_data);
+
+	if (previous == NULL)
+	    head = l;
+
+	previous = l;
+    }
+      
+    if (l != NULL)
+	l->l_next = NULL;
+
+    *list = head;
+}
+
+void
+rs_fix_thing_list(struct linked_list *list)
+{
+    struct linked_list *item;
+
+    for(item = list; item != NULL; item = item->l_next)
+        rs_fix_thing(THINGPTR(item));
+}
+
+void
+rs_fix_magic_items(struct magic_item *mi, int cnt)
+{
+    int i;
+
+    for (i = 0; i < cnt; i++)
+	if (i > 0)
+	    mi[i].mi_prob += mi[i-1].mi_prob;
+}
+
+void
+rs_fix_monsters(struct monster mons[26])
+{
+    sprintf(mons['F'-'A'].m_stats.s_dmg,"%dd1",fung_hit);
+}
+
+void
+rs_write_trap(FILE *savef, struct trap *trap)
+{
+    rs_write_coord(savef, trap->tr_pos);
+    rs_write_int(savef, trap->tr_type);
+    rs_write_int(savef, trap->tr_flags);
+}
+
+void
+rs_read_trap(FILE *savef, struct trap *trap)
+{
+    rs_read_coord(savef,&trap->tr_pos);
+    rs_read_int(savef,&trap->tr_type);
+    rs_read_int(savef,&trap->tr_flags);
+}
+
+void
+rs_write_traps(FILE *savef, struct trap t[], int cnt)
+{
+    int n = 0;
+
+    rs_write_marker(savef, RSID_MONSTERS);
+    rs_write_int(savef, cnt);
+    
+    for(n = 0; n < cnt; n++)
+        rs_write_trap(savef, &t[n]);
+}
+
+void
+rs_read_traps(FILE *savef, struct trap *t, int cnt)
+{
+    int value = 0, n = 0;
+
+    rs_read_marker(savef, RSID_MONSTERS);
+
+    rs_read_int(savef,&value);
+
+    if (!encerror() && (value > cnt))
+        encseterr(EILSEQ);
+
+    for(n = 0; n < value; n++)
+        rs_read_trap(savef,&t[n]);
+}
+
+int
+rs_save_file(FILE *savef)
+{
+    encclearerr();
+
+    rs_write_thing(savef, &player);                     
+    rs_write_object_list(savef, lvl_obj);               
+    rs_write_thing_list(savef, mlist);                
+    rs_write_traps(savef, traps, MAXTRAPS);             
+    rs_write_rooms(savef, rooms, MAXROOMS);             
+    rs_write_room_reference(savef, oldrp);              
+    rs_write_stats(savef,&max_stats);                   
+    rs_write_object_reference(savef, player.t_pack, cur_weapon); 
+    rs_write_object_reference(savef, player.t_pack, cur_armor);
+    rs_write_object_reference(savef, player.t_pack, cur_ring[0]);
+    rs_write_object_reference(savef, player.t_pack, cur_ring[1]);
+    rs_write_int(savef, level);                         
+    rs_write_int(savef, purse);                         
+    rs_write_int(savef, mpos);                          
+    rs_write_int(savef, ntraps);                        
+    rs_write_int(savef, no_move);                       
+    rs_write_int(savef, no_command);                    
+    rs_write_int(savef, inpack);                        
+    rs_write_int(savef, max_hp);                        
+    rs_write_int(savef, total);                         
+    rs_write_int(savef, lastscore);                     
+    rs_write_int(savef, no_food);                       
+    rs_write_int(savef, seed);                          
+    rs_write_int(savef, count);                         
+    rs_write_int(savef, dnum);                          
+    rs_write_int(savef, fung_hit);                      
+    rs_write_int(savef, quiet);                         
+    rs_write_int(savef, max_level);                     
+    rs_write_int(savef, food_left);                     
+    rs_write_int(savef, group);                         
+    rs_write_int(savef, hungry_state);                  
+    rs_write_int(savef, take);
+    rs_write_int(savef, runch);
+    rs_write_scrolls(savef);
+    rs_write_potions(savef);
+    rs_write_rings(savef);
+    rs_write_sticks(savef);
+    rs_write_chars(savef,whoami,80);
+    rs_write_chars(savef,fruit,80);
+    rs_write_window(savef, cw);
+    rs_write_window(savef, mw);
+    rs_write_window(savef, stdscr);
+    rs_write_int(savef, running);                   
+    rs_write_int(savef, playing);                   
+    rs_write_int(savef, wizard);                    
+    rs_write_int(savef, after);
+    rs_write_int(savef, notify);                    
+    rs_write_int(savef, fight_flush);               
+    rs_write_int(savef, terse);                     
+    rs_write_int(savef, door_stop);                 
+    rs_write_int(savef, jump);                      
+    rs_write_int(savef, slow_invent);               
+    rs_write_int(savef, firstmove);                 
+    rs_write_int(savef, waswizard);                 
+    rs_write_int(savef, askme);                     
+    rs_write_int(savef, amulet);                    
+    rs_write_int(savef, in_shell);                  
+    rs_write_coord(savef, oldpos);                      
+    rs_write_coord(savef, delta);                       
+    rs_write_coord(savef, ch_ret);                      /* chase.c      */
+    rs_write_daemons(savef, &d_list[0], 20);            /* daemon.c     */
+    rs_write_int(savef,between);                        /* daemons.c    */
+    rs_write_int(savef,num_checks);                     /* main.c       */
+    rs_write_chars(savef,lvl_mons,sizeof(lvl_mons));    /* monsters.c   */
+    rs_write_chars(savef,wand_mons,sizeof(wand_mons));	/* monsters.c   */
+
+    return( encclearerr() );
+}
+
+int
+rs_restore_file(FILE *savef)
+{
+    encclearerr();
+
+    rs_read_thing(savef, &player);                        
+    rs_read_object_list(savef, &lvl_obj);                 
+    rs_read_thing_list(savef, &mlist);                  
+    rs_fix_thing(&player);
+    rs_fix_thing_list(mlist);
+    rs_read_traps(savef, traps, MAXTRAPS);
+    rs_read_rooms(savef, rooms, MAXROOMS);
+    rs_read_room_reference(savef, &oldrp);
+    rs_read_stats(savef,&max_stats);                      
+    rs_read_object_reference(savef, player.t_pack, &cur_weapon);
+    rs_read_object_reference(savef, player.t_pack, &cur_armor);
+    rs_read_object_reference(savef, player.t_pack, &cur_ring[0]);
+    rs_read_object_reference(savef, player.t_pack, &cur_ring[1]);
+    rs_fix_magic_items(things,NUMTHINGS);         
+    rs_fix_magic_items(s_magic,MAXSCROLLS);       
+    rs_fix_magic_items(p_magic,MAXPOTIONS);       
+    rs_fix_magic_items(r_magic,MAXRINGS);         
+    rs_fix_magic_items(ws_magic,MAXSTICKS);       
+    rs_read_int(savef, &level);                           
+    rs_read_int(savef, &purse);                           
+    rs_read_int(savef, &mpos);                            
+    rs_read_int(savef, &ntraps);                          
+    rs_read_int(savef, &no_move);                         
+    rs_read_int(savef, &no_command);                      
+    rs_read_int(savef, &inpack);                          
+    rs_read_int(savef, &max_hp);                          
+    rs_read_int(savef, &total);                           
+    rs_read_int(savef, &lastscore);                       
+    rs_read_int(savef, &no_food);                         
+    rs_read_int(savef, &seed);                            
+    rs_read_int(savef, &count);                           
+    rs_read_int(savef, &dnum);                            
+    rs_read_int(savef, &fung_hit);                        
+    rs_read_int(savef, &quiet);                           
+    rs_read_int(savef, &max_level);                       
+    rs_read_int(savef, &food_left);                       
+    rs_read_int(savef, &group);                           
+    rs_read_int(savef, &hungry_state);                    
+    rs_read_int(savef, &take);
+    rs_read_int(savef, &runch);
+    rs_read_scrolls(savef);
+    rs_read_potions(savef);
+    rs_read_rings(savef);
+    rs_read_sticks(savef);
+    rs_read_chars(savef,whoami,80);
+    rs_read_chars(savef,fruit,80);
+    rs_read_window(savef, cw);
+    rs_read_window(savef, mw);
+    rs_read_window(savef, stdscr);
+    rs_read_int(savef, &running);                     
+    rs_read_int(savef, &playing);                     
+    rs_read_int(savef, &wizard);                      
+    rs_read_int(savef, &after);
+    rs_read_int(savef, &notify);                      
+    rs_read_int(savef, &fight_flush);                 
+    rs_read_int(savef, &terse);                       
+    rs_read_int(savef, &door_stop);                   
+    rs_read_int(savef, &jump);                        
+    rs_read_int(savef, &slow_invent);                 
+    rs_read_int(savef, &firstmove);                   
+    rs_read_int(savef, &waswizard);                   
+    rs_read_int(savef, &askme);                       
+    rs_read_int(savef, &amulet);                      
+    rs_read_int(savef, &in_shell);                    
+    rs_read_coord(savef,&oldpos);                         
+    rs_read_coord(savef,&delta);                          
+    rs_read_coord(savef, &ch_ret);                        /* chase.c      */
+    rs_read_daemons(savef, d_list, 20);                   /* daemon.c     */
+    rs_read_int(savef,&between);                          /* daemons.c    */
+    rs_read_int(savef,&num_checks);                       /* main.c       */
+    rs_read_chars(savef, lvl_mons, sizeof(lvl_mons));     /* monsters.c   */
+    rs_read_chars(savef, wand_mons, sizeof(wand_mons));	/* monsters.c   */
+    rs_fix_monsters(monsters);    
+
+    return( encclearerr() );
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rogue3/sticks.c	Tue Oct 13 13:33:34 2009 +0000
@@ -0,0 +1,401 @@
+/*
+ * Functions to implement the various sticks one might find
+ * while wandering around the dungeon.
+ *
+ * @(#)sticks.c	3.14 (Berkeley) 6/15/81
+ *
+ * Rogue: Exploring the Dungeons of Doom
+ * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
+ * All rights reserved.
+ *
+ * See the file LICENSE.TXT for full copyright and licensing information.
+ */
+
+#include "curses.h"
+#include <ctype.h>
+#include <string.h>
+#include "rogue.h"
+
+void
+fix_stick(struct object *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 = 3;
+	    cur->o_dplus = 3;
+	    strcpy(cur->o_damage,"1d8");
+	when WS_LIGHT:
+	    cur->o_charges = 10 + rnd(10);
+    }
+}
+
+void
+do_zap(int gotdir)
+{
+    struct linked_list *item;
+    struct object *obj;
+    struct room *rp;
+    struct thing *tp;
+    int y, x;
+
+    if ((item = get_item("zap with", STICK)) == NULL)
+	return;
+    obj = (struct object *) ldata(item);
+    if (obj->o_type != STICK)
+    {
+	msg("You can't zap with that!");
+	after = FALSE;
+	return;
+    }
+    if (obj->o_charges == 0)
+    {
+	msg("Nothing happens.");
+	return;
+    }
+    if (!gotdir)
+	do {
+	    delta.y = rnd(3) - 1;
+	    delta.x = rnd(3) - 1;
+	} while (delta.y == 0 && delta.x == 0);
+    switch (obj->o_which)
+    {
+	case WS_LIGHT:
+	    /*
+	     * Reddy Kilowat wand.  Light up the room
+	     */
+	    ws_know[WS_LIGHT] = TRUE;
+	    if ((rp = roomin(&hero)) == NULL)
+		msg("The corridor glows and then fades");
+	    else
+	    {
+		addmsg("The room is lit");
+		if (!terse)
+		    addmsg(" by a shimmering blue light.");
+		endmsg();
+		rp->r_flags &= ~ISDARK;
+		/*
+		 * Light the room and put the player back up
+		 */
+		light(&hero);
+		mvwaddch(cw, hero.y, hero.x, PLAYER);
+	    }
+	when WS_DRAIN:
+	    /*
+	     * Take away 1/2 of hero's hit points, then take it away
+	     * evenly from the monsters in the room (or next to hero
+	     * if he is in a passage)
+	     */
+	    if (pstats.s_hpt < 2)
+	    {
+		msg("You are too weak to use it.");
+		return;
+	    }
+	    else if ((rp = roomin(&hero)) == NULL)
+		drain(hero.y-1, hero.y+1, hero.x-1, hero.x+1);
+	    else
+		drain(rp->r_pos.y, rp->r_pos.y+rp->r_max.y,
+		    rp->r_pos.x, rp->r_pos.x+rp->r_max.x);
+	when WS_POLYMORPH:
+	case WS_TELAWAY:
+	case WS_TELTO:
+	case WS_CANCEL:
+	{
+	    int monster;
+	    int oldch;
+	    int rm;
+
+	    y = hero.y;
+	    x = hero.x;
+	    while (step_ok(winat(y, x)))
+	    {
+		y += delta.y;
+		x += delta.x;
+	    }
+	    if (isupper(monster = mvwinch(mw, y, x)))
+	    {
+		int omonst = monster;
+
+		if (monster == 'F')
+		    player.t_flags &= ~ISHELD;
+		item = find_mons(y, x);
+		tp = (struct thing *) ldata(item);
+		if (obj->o_which == WS_POLYMORPH)
+		{
+		    detach(mlist, item);
+		    oldch = tp->t_oldch;
+		    delta.y = y;
+		    delta.x = x;
+		    new_monster(item, monster = rnd(26) + 'A', &delta);
+		    if (!(tp->t_flags & ISRUN))
+			runto(&delta, &hero);
+		    if (isupper(mvwinch(cw, y, x)))
+			mvwaddch(cw, y, x, monster);
+		    tp->t_oldch = oldch;
+		    ws_know[WS_POLYMORPH] |= (monster != omonst);
+		}
+		else if (obj->o_which == WS_CANCEL)
+		{
+		    tp->t_flags |= ISCANC;
+		    tp->t_flags &= ~ISINVIS;
+		}
+		else
+		{
+		    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);
+		    }
+		    else
+		    {
+			tp->t_pos.y = hero.y + delta.y;
+			tp->t_pos.x = hero.x + delta.x;
+		    }
+		    if (isupper(mvwinch(cw, y, x)))
+			mvwaddch(cw, y, x, tp->t_oldch);
+		    tp->t_dest = &hero;
+		    tp->t_flags |= ISRUN;
+		    mvwaddch(mw, y, x, ' ');
+		    mvwaddch(mw, tp->t_pos.y, tp->t_pos.x, monster);
+		    if (tp->t_pos.y != y || tp->t_pos.x != x)
+			tp->t_oldch = mvwinch(cw, tp->t_pos.y, tp->t_pos.x);
+		}
+	    }
+	}
+	when WS_MISSILE:
+	{
+	    static struct object bolt =
+	    {
+		'*' , {0, 0}, 0, "", "1d4" , 0, 0, 100, 1, 0, 0, 0
+	    };
+
+	    do_motion(&bolt, delta.y, delta.x);
+	    if (isupper(mvwinch(mw, bolt.o_pos.y, bolt.o_pos.x))
+		&& !save_throw(VS_MAGIC, THINGPTR(find_mons(unc(bolt.o_pos)))))
+		    hit_monster(unc(bolt.o_pos), &bolt);
+	    else if (terse)
+		msg("Missile vanishes");
+	    else
+		msg("The missile vanishes with a puff of smoke");
+	    ws_know[WS_MISSILE] = TRUE;
+	}
+	when WS_HIT:
+	{
+	    int ch;
+
+	    delta.y += hero.y;
+	    delta.x += hero.x;
+	    ch = winat(delta.y, delta.x);
+	    if (isupper(ch))
+	    {
+		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, ch, 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 (isupper(mvwinch(mw, y, x)))
+	    {
+		item = find_mons(y, x);
+		tp = (struct thing *) ldata(item);
+		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:
+	{
+	    int dirch;
+	    char *name;
+	    int ch;
+	    int bounced, used;
+	    coord pos;
+	    coord spotpos[BOLT_LENGTH];
+	    static struct object bolt =
+	    {
+		'*' , {0, 0}, 0, "", "6d6" , 0, 0, 100, 0, 0, 0 ,0
+	    };
+
+
+	    switch (delta.y + delta.x)
+	    {
+		case 0: dirch = '/';
+		when 1: case -1: dirch = (delta.y == 0 ? '-' : '|');
+		when 2: case -2: dirch = '\\';
+	    }
+	    pos = hero;
+	    bounced = FALSE;
+	    used = FALSE;
+	    if (obj->o_which == WS_ELECT)
+		name = "bolt";
+	    else if (obj->o_which == WS_FIRE)
+		name = "flame";
+	    else
+		name = "ice";
+	    for (y = 0; y < BOLT_LENGTH && !used; y++)
+	    {
+		ch = winat(pos.y, pos.x);
+		spotpos[y] = pos;
+		switch (ch)
+		{
+		    case DOOR:
+		    case SECRETDOOR:
+		    case '|':
+		    case '-':
+		    case ' ':
+			bounced = TRUE;
+			delta.y = -delta.y;
+			delta.x = -delta.x;
+			y--;
+			msg("The bolt bounces");
+			break;
+		    default:
+			if (!bounced && isupper(ch))
+			{
+			    if (!save_throw(VS_MAGIC, THINGPTR(find_mons(unc(pos)))))
+			    {
+				bolt.o_pos = pos;
+				hit_monster(unc(pos), &bolt);
+				used = TRUE;
+			    }
+			    else if (ch != 'M' || show(pos.y, pos.x) == 'M')
+			    {
+				if (terse)
+				    msg("%s misses", name);
+				else
+				    msg("The %s whizzes past the %s", name, monsters[ch-'A'].m_name);
+				runto(&pos, &hero);
+			    }
+			}
+			else if (bounced && pos.y == hero.y && pos.x == hero.x)
+			{
+			    bounced = FALSE;
+			    if (!save(VS_MAGIC))
+			    {
+				if (terse)
+				    msg("The %s hits", name);
+				else
+				    msg("You are hit by the %s", name);
+				if ((pstats.s_hpt -= roll(6, 6)) <= 0)
+				    death('b');
+				used = TRUE;
+			    }
+			    else
+				msg("The %s whizzes by you", name);
+			}
+			mvwaddch(cw, pos.y, pos.x, dirch);
+			draw(cw);
+		}
+		pos.y += delta.y;
+		pos.x += delta.x;
+	    }
+	    for (x = 0; x < y; x++)
+		mvwaddch(cw, spotpos[x].y, spotpos[x].x, show(spotpos[x].y, spotpos[x].x));
+	    ws_know[obj->o_which] = TRUE;
+	}
+	when WS_NOP:
+	otherwise:
+	    msg("What a bizarre schtick!");
+    }
+    obj->o_charges--;
+}
+
+/*
+ * drain:
+ *	Do drain hit points from player shtick
+ */
+
+void
+drain(int ymin, int ymax, int xmin, int xmax)
+{
+    int i, j, cnt;
+    struct thing *ick;
+    struct linked_list *item;
+
+    /*
+     * First count how many things we need to spread the hit points among
+     */
+    cnt = 0;
+    for (i = ymin; i <= ymax; i++)
+	for (j = xmin; j <= xmax; j++)
+	    if (isupper(mvwinch(mw, i, j)))
+		cnt++;
+    if (cnt == 0)
+    {
+	msg("You have a tingling feeling");
+	return;
+    }
+    cnt = pstats.s_hpt / cnt;
+    pstats.s_hpt /= 2;
+    /*
+     * Now zot all of the monsters
+     */
+    for (i = ymin; i <= ymax; i++)
+	for (j = xmin; j <= xmax; j++)
+	    if (isupper(mvwinch(mw, i, j)) &&
+	        ((item = find_mons(i, j)) != NULL))
+	    {
+		ick = (struct thing *) ldata(item);
+		if ((ick->t_stats.s_hpt -= cnt) < 1)
+		    killed(item, cansee(i, j) && !on(*ick, ISINVIS));
+	    }
+}
+
+/*
+ * charge a wand for wizards.
+ */
+char *
+charge_str(struct object *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/rogue3/things.c	Tue Oct 13 13:33:34 2009 +0000
@@ -0,0 +1,381 @@
+/*
+ * Contains functions for dealing with things like
+ * potions and scrolls
+ *
+ * @(#)things.c	3.37 (Berkeley) 6/15/81
+ *
+ * Rogue: Exploring the Dungeons of Doom
+ * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
+ * All rights reserved.
+ *
+ * See the file LICENSE.TXT for full copyright and licensing information.
+ */
+
+#include "curses.h"
+#include <ctype.h>
+#include <string.h>
+#include "rogue.h"
+
+/*
+ * inv_name:
+ *	return the name of something as it would appear in an
+ *	inventory.
+ */
+char *
+inv_name(struct object *obj, int drop)
+{
+    char *pb;
+
+    switch(obj->o_type)
+    {
+	case SCROLL:
+	    if (obj->o_count == 1)
+		strcpy(prbuf, "A scroll ");
+	    else
+		sprintf(prbuf, "%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(prbuf, "A potion ");
+	    else
+		sprintf(prbuf, "%d potions ", obj->o_count);
+	    pb = &prbuf[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(prbuf, "A%s %s", vowelstr(fruit), fruit);
+		else
+		    sprintf(prbuf, "%d %ss", obj->o_count, fruit);
+	    else
+		if (obj->o_count == 1)
+		    strcpy(prbuf, "Some food");
+		else
+		    sprintf(prbuf, "%d rations of food", obj->o_count);
+	when WEAPON:
+	    if (obj->o_count > 1)
+		sprintf(prbuf, "%d ", obj->o_count);
+	    else
+		strcpy(prbuf, "A ");
+	    pb = &prbuf[strlen(prbuf)];
+	    if (obj->o_flags & ISKNOW)
+		sprintf(pb, "%s %s", num(obj->o_hplus, obj->o_dplus),
+		    w_names[obj->o_which]);
+	    else
+		sprintf(pb, "%s", w_names[obj->o_which]);
+	    if (obj->o_count > 1)
+		strcat(prbuf, "s");
+	when ARMOR:
+	    if (obj->o_flags & ISKNOW)
+		sprintf(prbuf, "%s %s",
+		    num(a_class[obj->o_which] - obj->o_ac, 0),
+		    a_names[obj->o_which]);
+	    else
+		sprintf(prbuf, "%s", a_names[obj->o_which]);
+	when AMULET:
+	    strcpy(prbuf, "The Amulet of Yendor");
+	when STICK:
+	    sprintf(prbuf, "A %s ", 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(&prbuf[2], "%s %s", ws_made[obj->o_which],
+		    ws_type[obj->o_which]);
+        when RING:
+	    if (r_know[obj->o_which])
+		sprintf(prbuf, "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(prbuf, "A ring called %s(%s)",
+		    r_guess[obj->o_which], r_stones[obj->o_which]);
+	    else
+		sprintf(prbuf, "A%s %s ring", vowelstr(r_stones[obj->o_which]),
+		    r_stones[obj->o_which]);
+	otherwise:
+	    debug("Picked up something funny");
+	    sprintf(prbuf, "Something bizarre %s", unctrl(obj->o_type));
+    }
+    if (obj == cur_armor)
+	strcat(prbuf, " (being worn)");
+    if (obj == cur_weapon)
+	strcat(prbuf, " (weapon in hand)");
+    if (obj == cur_ring[LEFT])
+	strcat(prbuf, " (on left hand)");
+    else if (obj == cur_ring[RIGHT])
+	strcat(prbuf, " (on right hand)");
+    if (drop && isupper(prbuf[0]))
+	prbuf[0] = tolower(prbuf[0]);
+    else if (!drop && islower(*prbuf))
+	*prbuf = toupper(*prbuf);
+    if (!drop)
+	strcat(prbuf, ".");
+    return prbuf;
+}
+
+/*
+ * money:
+ *	Add to characters purse
+ */
+void
+money()
+{
+    struct room *rp;
+
+    for (rp = rooms; rp <= &rooms[MAXROOMS-1]; rp++)
+	if (ce(hero, rp->r_gold))
+	{
+	    if (notify)
+	    {
+		if (!terse)
+		    addmsg("You found ");
+		msg("%d gold pieces.", rp->r_goldval);
+	    }
+	    purse += rp->r_goldval;
+	    rp->r_goldval = 0;
+	    cmov(rp->r_gold);
+	    addch(FLOOR);
+	    return;
+	}
+    msg("That gold must have been counterfeit");
+}
+
+/*
+ * drop:
+ *	put something down
+ */
+void
+drop()
+{
+    int ch;
+    struct linked_list *obj, *nobj;
+    struct object *op;
+
+    ch = mvwinch(stdscr, hero.y, hero.x);
+    if (ch != FLOOR && ch != PASSAGE)
+    {
+	msg("There is something there already");
+	return;
+    }
+    if ((obj = get_item("drop", 0)) == NULL)
+	return;
+    op = (struct object *) ldata(obj);
+    if (!dropcheck(op))
+	return;
+    /*
+     * Take it out of the pack
+     */
+    if (op->o_count >= 2 && op->o_type != WEAPON)
+    {
+	nobj = new_item(sizeof *op);
+	op->o_count--;
+	op = (struct object *) ldata(nobj);
+	*op = *((struct object *) ldata(obj));
+	op->o_count = 1;
+	obj = nobj;
+	if (op->o_group != 0)
+		inpack++;
+    }
+    else
+	detach(pack, obj);
+    inpack--;
+    /*
+     * Link it into the level object list
+     */
+    attach(lvl_obj, obj);
+    mvaddch(hero.y, hero.x, op->o_type);
+    op->o_pos = hero;
+    msg("Dropped %s", inv_name(op, TRUE));
+}
+
+/*
+ * do special checks for dropping or unweilding|unwearing|unringing
+ */
+int
+dropcheck(struct object *op)
+{
+    str_t save_max;
+
+    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 if (op == cur_ring[LEFT] || op == cur_ring[RIGHT])
+    {
+	switch (op->o_which)
+	{
+	    case R_ADDSTR:
+		save_max = max_stats.s_str;
+		chg_str(-op->o_ac);
+		max_stats.s_str = save_max;
+		break;
+	    case R_SEEINVIS:
+		player.t_flags &= ~CANSEE;
+		extinguish(unsee);
+		light(&hero);
+		mvwaddch(cw, hero.y, hero.x, PLAYER);
+		break;
+	}
+	cur_ring[op == cur_ring[LEFT] ? LEFT : RIGHT] = NULL;
+    }
+    return TRUE;
+}
+
+/*
+ * return a new thing
+ */
+struct linked_list *
+new_thing()
+{
+    struct linked_list *item;
+    struct object *cur;
+    int j, k;
+
+    item = new_item(sizeof *cur);
+    cur = (struct object *) ldata(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);
+	when 2:
+	    no_food = 0;
+	    cur->o_type = FOOD;
+	    if (rnd(100) > 10)
+		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;
+	    if (j == MAXARMORS)
+	    {
+		debug("Picked a bad armor %d", k);
+		j = 0;
+	    }
+	    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);
+	otherwise:
+	    debug("Picked a bad kind of object");
+	    wait_for(stdscr, ' ');
+    }
+    return item;
+}
+
+/*
+ * pick an item out of a list of nitems possible magic items
+ */
+int
+pick_one(struct magic_item *magic, int nitems)
+{
+    struct magic_item *end;
+    int i;
+    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)
+    {
+	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);
+	}
+	magic = start;
+    }
+    return (int) (magic - start);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rogue3/vers.c	Tue Oct 13 13:33:34 2009 +0000
@@ -0,0 +1,16 @@
+/*
+ * version number.  Whenever a new version number is desired, use
+ * sccs to get vers.c.  Environ and encstr are declared here to
+ * force them to be loaded before the version number, and therefore
+ * not to be written in saved games.
+ *
+ * Rogue: Exploring the Dungeons of Doom
+ * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
+ * All rights reserved.
+ *
+ * See the file LICENSE.TXT for full copyright and licensing information.
+ */
+
+char encstr[] = "\354\251\243\332A\201|\301\321p\210\251\327\"\257\365t\341%3\271^`~\203z{\341};\f\341\231\222e\234\351]\321";
+char version[] = "@(#)vers.c	3.6 (Berkeley) 4/21/81";
+char *release = "3.6.4";
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rogue3/weapons.c	Tue Oct 13 13:33:34 2009 +0000
@@ -0,0 +1,311 @@
+/*
+ * Functions for dealing with problems brought about by weapons
+ *
+ * @(#)weapons.c	3.17 (Berkeley) 6/15/81
+ *
+ * Rogue: Exploring the Dungeons of Doom
+ * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
+ * All rights reserved.
+ *
+ * See the file LICENSE.TXT for full copyright and licensing information.
+ */
+
+#include "curses.h"
+#include <ctype.h>
+#include <string.h>
+#include "rogue.h"
+
+#define NONE 100
+
+char *w_names[MAXWEAPONS] = {
+    "mace",
+    "long sword",
+    "int bow",
+    "arrow",
+    "dagger",
+    "rock",
+    "two handed sword",
+    "sling",
+    "dart",
+    "crossbow",
+    "crossbow bolt",
+    "spear",
+};
+
+static struct init_weps {
+    char *iw_dam;
+    char *iw_hrl;
+    int iw_launch;
+    int iw_flags;
+} init_dam[MAXWEAPONS] = {
+    "2d4", "1d3", NONE, 0,		/* Mace */
+    "1d10", "1d2", NONE,0,		/* Long sword */
+    "1d1", "1d1", NONE,	0,		/* Bow */
+    "1d1", "1d6", BOW,	ISMANY|ISMISL,	/* Arrow */
+    "1d6", "1d4", NONE,	ISMISL,		/* Dagger */
+    "1d2", "1d4", SLING,ISMANY|ISMISL,	/* Rock */
+    "3d6", "1d2", NONE,	0,		/* 2h sword */
+    "0d0", "0d0", NONE, 0,		/* Sling */
+    "1d1", "1d3", NONE,	ISMANY|ISMISL,	/* Dart */
+    "1d1", "1d1", NONE, 0,		/* Crossbow */
+    "1d2", "1d10", CROSSBOW, ISMANY|ISMISL,/* Crossbow bolt */
+    "1d8", "1d6", NONE, ISMISL,		/* Spear */
+};
+
+/*
+ * missile:
+ *	Fire a missile in a given direction
+ */
+
+void
+missile(int ydelta, int xdelta)
+{
+    struct object *obj;
+    struct linked_list *item, *nitem;
+
+    /*
+     * Get which thing we are hurling
+     */
+    if ((item = get_item("throw", WEAPON)) == NULL)
+	return;
+    obj = (struct object *) ldata(item);
+    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, item);
+	inpack--;
+    }
+    else
+    {
+	obj->o_count--;
+	if (obj->o_group == 0)
+	    inpack--;
+	nitem = (struct linked_list *) new_item(sizeof *obj);
+	obj = (struct object *) ldata(nitem);
+	*obj = *((struct object *) ldata(item));
+	obj->o_count = 1;
+	item = 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 mosnter, put it on the floor
+     */
+    if (!isupper(mvwinch(mw, obj->o_pos.y, obj->o_pos.x))
+	|| !hit_monster(unc(obj->o_pos), obj))
+	    fall(item, TRUE);
+    mvwaddch(cw, hero.y, hero.x, PLAYER);
+}
+
+/*
+ * do the actual motion on the screen done by an object traveling
+ * across the room
+ */
+void
+do_motion(struct object *obj, int ydelta, int xdelta)
+{
+    /*
+     * Come fly with us ...
+     */
+    obj->o_pos = hero;
+    for (;;)
+    {
+	int ch;
+
+	/*
+	 * Erase the old one
+	 */
+	if (!ce(obj->o_pos, hero) && cansee(unc(obj->o_pos)) &&
+	    mvwinch(cw, obj->o_pos.y, obj->o_pos.x) != ' ')
+		    mvwaddch(cw, obj->o_pos.y, obj->o_pos.x,
+			    show(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)) &&
+		mvwinch(cw, obj->o_pos.y, obj->o_pos.x) != ' ')
+	    {
+		mvwaddch(cw, obj->o_pos.y, obj->o_pos.x, obj->o_type);
+		draw(cw);
+	    }
+	    continue;
+	}
+	break;
+    }
+}
+
+/*
+ * fall:
+ *	Drop an item someplace around here.
+ */
+
+void
+fall(struct linked_list *item, int pr)
+{
+    struct object *obj;
+    struct room *rp;
+    static coord fpos;
+
+    obj = (struct object *) ldata(item);
+    if (fallpos(&obj->o_pos, &fpos, TRUE))
+    {
+	mvaddch(fpos.y, fpos.x, obj->o_type);
+	obj->o_pos = fpos;
+	if ((rp = roomin(&hero)) != NULL && !(rp->r_flags & ISDARK))
+	{
+	    light(&hero);
+	    mvwaddch(cw, hero.y, hero.x, PLAYER);
+	}
+	attach(lvl_obj, item);
+	return;
+    }
+    if (pr)
+        if (obj->o_type == WEAPON) /* BUGFUX: Identification trick */
+            msg("Your %s vanishes as it hits the ground.", w_names[obj->o_which]);
+        else
+            msg("%s vanishes as it hits the ground.", inv_name(obj,TRUE));
+    discard(item);
+}
+
+/*
+ * init_weapon:
+ *	Set up the initial goodies for a weapon
+ */
+
+void
+init_weapon(struct object *weap, int type)
+{
+    struct init_weps *iwp;
+
+    iwp = &init_dam[type];
+    strcpy(weap->o_damage,iwp->iw_dam);
+    strcpy(weap->o_hurldmg,iwp->iw_hrl);
+    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 = newgrp();
+    }
+    else
+	weap->o_count = 1;
+}
+
+/*
+ * Does the missile hit the monster
+ */
+
+int
+hit_monster(int y, int x, struct object *obj)
+{
+    static coord mp;
+
+    mp.y = y;
+    mp.x = x;
+    return fight(&mp, winat(y, x), obj, TRUE);
+}
+
+/*
+ * num:
+ *	Figure out the plus number for armor/weapons
+ */
+
+char *
+num(int n1, int n2)
+{
+    static char numbuf[80];
+
+    if (n1 == 0 && n2 == 0)
+	return "+0";
+    if (n2 == 0)
+	sprintf(numbuf, "%s%d", n1 < 0 ? "" : "+", n1);
+    else
+        sprintf(numbuf, "%s%d,%s%d",
+				n1 < 0 ? "" : "+", n1, n2 < 0 ? "" : "+", n2);
+    return numbuf;
+}    
+
+/*
+ * wield:
+ *	Pull out a certain weapon
+ */
+
+void
+wield()
+{
+    struct linked_list *item;
+    struct object *obj, *oweapon;
+
+    oweapon = cur_weapon;
+    if (!dropcheck(cur_weapon))
+    {
+	cur_weapon = oweapon;
+	return;
+    }
+    cur_weapon = oweapon;
+    if ((item = get_item("wield", WEAPON)) == NULL)
+    {
+bad:
+	after = FALSE;
+	return;
+    }
+
+    obj = (struct object *) ldata(item);
+    if (obj->o_type == ARMOR)
+    {
+	msg("You can't wield armor");
+	goto bad;
+    }
+    if (is_current(obj))
+        goto bad;
+
+    if (terse)
+	addmsg("W");
+    else
+	addmsg("You are now w");
+    msg("ielding %s", inv_name(obj, TRUE));
+    cur_weapon = obj;
+}
+
+/*
+ * pick a random position around the give (y, x) coordinates
+ */
+int
+fallpos(coord *pos, coord *newpos, int passages)
+{
+    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 = winat(y, x)) == FLOOR || (passages && 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/rogue3/wizard.c	Tue Oct 13 13:33:34 2009 +0000
@@ -0,0 +1,204 @@
+
+/*
+ * Special wizard commands (some of which are also non-wizard commands
+ * under strange circumstances)
+ *
+ * @(#)wizard.c	3.8 (Berkeley) 6/3/81
+ *
+ * Rogue: Exploring the Dungeons of Doom
+ * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
+ * All rights reserved.
+ *
+ * See the file LICENSE.TXT for full copyright and licensing information.
+ */
+
+#include "curses.h"
+#include <ctype.h>
+#include <string.h>
+#include <stdlib.h>
+#include "machdep.h"
+#include "rogue.h"
+
+/*
+ * whatis:
+ *	What a certin object is
+ */
+
+void
+whatis()
+{
+    struct object *obj;
+    struct linked_list *item;
+
+    if ((item = get_item("identify", 0)) == NULL)
+	return;
+    obj = (struct object *) ldata(item);
+    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));
+}
+
+/*
+ * create_obj:
+ *	Wizard command for getting anything he wants
+ */
+
+void
+create_obj()
+{
+    struct linked_list *item;
+    struct object *obj;
+    int bless;
+    int ch;
+
+    item = new_item(sizeof *obj);
+    obj = (struct object *) ldata(item);
+    msg("Type of item: ");
+    obj->o_type = readchar(cw);
+    mpos = 0;
+    msg("Which %c do you want? (0-f)", obj->o_type);
+    obj->o_which = (isdigit((ch = readchar(cw))) ? 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(cw);
+	mpos = 0;
+	if (obj->o_type == WEAPON)
+	{
+	    init_weapon(obj, obj->o_which);
+	    if (bless == '-') {
+		obj->o_hplus -= rnd(3)+1;
+		obj->o_flags |= ISCURSED;
+	    }
+	    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;
+		obj->o_flags |= ISCURSED;
+	    }
+	    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(cw);
+		mpos = 0;
+		if (bless == '-')
+		    obj->o_flags |= ISCURSED;
+		obj->o_ac = (bless == '-' ? -1 : rnd(2) + 1);
+	}
+    else if (obj->o_type == STICK)
+	fix_stick(obj);
+    add_pack(item, FALSE);
+}
+
+/*
+ * telport:
+ *	Bamf the hero someplace else
+ */
+
+int
+teleport()
+{
+    int rm;
+    coord c;
+
+    c = hero;
+    mvwaddch(cw, hero.y, hero.x, mvwinch(stdscr, hero.y, hero.x));
+    do
+    {
+	rm = rnd_room();
+	rnd_pos(&rooms[rm], &hero);
+    } until(winat(hero.y, hero.x) == FLOOR);
+    light(&c);
+    light(&hero);
+    mvwaddch(cw, 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");
+    }
+    count = 0;
+    running = FALSE;
+    flush_type();		/* flush typeahead */
+    return rm;
+}
+
+/*
+ * passwd:
+ *	see if user knows password
+ */
+
+int
+passwd()
+{
+    char *sp, c;
+    char buf[80];
+
+    msg("Wizard's Password:");
+    mpos = 0;
+    sp = buf;
+    while ((c = readchar(cw)) != '\n' && c != '\r' && c != '\033')
+	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, crypt(buf, "mT")) == 0);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rogue3/xcrypt.c	Tue Oct 13 13:33:34 2009 +0000
@@ -0,0 +1,688 @@
+/*
+ *  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.
+ */
+#ifndef HAVE_CRYPT
+#include <sys/types.h>
+#include <string.h>
+
+static unsigned int _endian = 1;
+static char *_le = (char *) &_endian;
+
+#define xntohl(x) (!*_le?(x):((x)&0xffU)<<24|((x)&0xff00U)<<8|((x)&0xff0000U)>>8|((x)&0xff000000U)>>24)
+#define xhtonl(x) (!*_le?(x):((x)&0xffU)<<24|((x)&0xff00U)<<8|((x)&0xff0000U)>>8|((x)&0xff000000U)>>24)
+
+#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(int 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(void)
+{
+	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] = (unsigned char) 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] = (unsigned char) i;
+		inv_comp_perm[i] = 255;
+	}
+
+	/*
+	 * Invert the key compression permutation.
+	 */
+	for (i = 0; i < 48; i++) {
+		inv_comp_perm[comp_perm[i] - 1] = (unsigned char) 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] = (unsigned char) 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 char *key)
+{
+	unsigned int k0, k1, rawkey0, rawkey1;
+	int	shifts, round;
+
+	if (!des_initialised)
+		des_init();
+
+	rawkey0 = xntohl(*(unsigned int *) key);
+	rawkey1 = xntohl(*(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 char *in, char *out, int salt, int count)
+{
+	unsigned int l_out, r_out, rawl, rawr;
+	unsigned int x[2];
+	int	retval;
+
+	if (!des_initialised)
+		des_init();
+
+	setup_salt(salt);
+
+	memcpy(x, in, sizeof x);
+	rawl = xntohl(x[0]);
+	rawr = xntohl(x[1]);
+	retval = do_des(rawl, rawr, &l_out, &r_out, count);
+
+	x[0] = xhtonl(l_out);
+	x[1] = xhtonl(r_out);
+	memcpy(out, x, sizeof x);
+	return(retval);
+}
+
+char *
+crypt(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((const 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((const char*)keybuf, (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((const 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);
+}
+#endif