changeset 133:e6179860cb76

Import XRogue 8.0 from the Roguelike Restoration Project (r1490)
author John "Elwin" Edwards
date Tue, 21 Apr 2015 08:55:20 -0400
parents d10fc4a065ac
children cfa9d1609b78
files xrogue/LICENSE.TXT xrogue/Makefile xrogue/README.TXT xrogue/actions.c xrogue/bolt.c xrogue/chase.c xrogue/command.c xrogue/daemon.c xrogue/daemons.c xrogue/eat.c xrogue/effects.c xrogue/encumb.c xrogue/fight.c xrogue/help.c xrogue/init.c xrogue/io.c xrogue/list.c xrogue/mach_dep.h xrogue/main.c xrogue/maze.c xrogue/misc.c xrogue/mons_def.c xrogue/monsters.c xrogue/move.c xrogue/n_level.c xrogue/network.h xrogue/options.c xrogue/outside.c xrogue/pack.c xrogue/passages.c xrogue/player.c xrogue/potions.c xrogue/rings.c xrogue/rip.c xrogue/rogue.c xrogue/rogue.h xrogue/rooms.c xrogue/save.c xrogue/scrolls.c xrogue/state.c xrogue/sticks.c xrogue/things.c xrogue/trader.c xrogue/util.c xrogue/vers.c xrogue/weapons.c xrogue/wear.c xrogue/wizard.c xrogue/xcrypt.c xrogue/xrogue.sln xrogue/xrogue.vcproj
diffstat 51 files changed, 37250 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xrogue/LICENSE.TXT	Tue Apr 21 08:55:20 2015 -0400
@@ -0,0 +1,178 @@
+Copyright (C) 1991 Robert Pietkivitch
+Portions Copyright (C) 1985 Michael Morgan, Ken Dalka and AT&T
+Portions Copyright (C) 1981 Michael Toy, Ken Arnold and Glenn Wichman
+Portions Copyright (C) 2000 Nicholas J. Kisseberth
+Portions Copyright (C) 1994 David Burren
+All rights reserved.
+
+===========================================================================
+
+XRogue: Expeditions into the Dungeons of Doom
+Copyright (C) 1991 Robert Pietkivitch
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+1. Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+3. Neither the name(s) of the author(s) nor the names of other contributors
+   may be used to endorse or promote products derived from this software
+   without specific prior written permission.
+4. The name "XRogue" must not be used to endorse or promote products 
+   derived from this software without prior written permission.
+5. Products derived from this software may not be called "XRogue",
+   nor may "XRogue" appear in their name, without prior written
+   permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) AND CONTRIBUTORS ``AS IS'' AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR(S) OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGE.
+
+===========================================================================
+
+Portions of this software are based on the work of Michael Morgan and 
+Ken Dalka. Used under license:
+
+Advanced Rogue
+Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka and AT&T
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+1. Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+3. Neither the name(s) of the author(s) nor the names of other contributors
+   may be used to endorse or promote products derived from this software
+   without specific prior written permission.
+4. The name "Advanced Rogue" and "ARogue" must not be used to endorse or
+   promote products derived from this software without prior written
+   permission.
+5. Products derived from this software may not be called "Advanced Rogue" or
+   "ARogue", nor may "Advanced Rogue" or "ARogue" appear in their name,
+   without prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) AND CONTRIBUTORS ``AS IS'' AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR(S) OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGE.
+
+===========================================================================
+
+Portions of this software are based on the work of Michael Toy, Ken Arnold
+and Glenn Wichman. Used under license:
+
+Rogue: Exploring the Dungeons of Doom
+Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+1. Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+3. Neither the name(s) of the author(s) nor the names of other contributors
+   may be used to endorse or promote products derived from this software
+   without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) AND CONTRIBUTORS ``AS IS'' AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR(S) OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGE.
+
+===========================================================================
+
+Portions of this software (save/restore game state) are based on the work 
+of Nicholas J. Kisseberth. Used under license:
+
+Copyright (C) 2000 Nicholas J. Kisseberth
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+1. Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+3. Neither the name(s) of the author(s) nor the names of other contributors
+   may be used to endorse or promote products derived from this software
+   without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) AND CONTRIBUTORS ``AS IS'' AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR(S) OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGE.
+
+===========================================================================
+
+Portions of this software (encryption) are based on the work 
+of David Burren. Used under license:
+
+FreeSec: libcrypt
+
+Copyright (C) 1994 David Burren
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+1. Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+3. Neither the name(s) of the author(s) nor the names of other contributors
+   may be used to endorse or promote products derived from this software
+   without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) AND CONTRIBUTORS ``AS IS'' AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR(S) OR CONTRIBUTORS BE LIABLE
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGE.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xrogue/Makefile	Tue Apr 21 08:55:20 2015 -0400
@@ -0,0 +1,115 @@
+#   XRogue: Expeditions into the Dungeons of Doom
+#   Copyright (C) 1991 Robert Pietkivitch
+#   All rights reserved.
+#
+#   Based on "Advanced Rogue"
+#   Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka and AT&T
+#   All rights reserved.
+#
+#   Based on "Rogue: Exploring the Dungeons of Doom"
+#   Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
+#   All rights reserved.
+#
+#   See the file LICENSE.TXT for full copyright and licensing information.
+
+DISTNAME=xrogue8.0.3
+PROGRAM=xrogue
+
+O=o
+
+HDRS  =	rogue.h mach_dep.h network.h
+
+OBJS1 =	vers.$(O) actions.$(O) bolt.$(O) chase.$(O) command.$(O) daemon.$(O) \
+        daemons.$(O) eat.$(O) effects.$(O) fight.$(O) encumb.$(O) help.$(O) \
+        init.$(O) io.$(O) list.$(O) main.$(O) maze.$(O) misc.$(O) monsters.$(O)
+OBJS2 = mons_def.$(O) move.$(O) n_level.$(O) options.$(O) outside.$(O) pack.$(O) \
+        passages.$(O) player.$(O) potions.$(O) rings.$(O) rip.$(O) rooms.$(O) \
+        save.$(O) scrolls.$(O) sticks.$(O) things.$(O) trader.$(O) util.$(O) \
+        weapons.$(O) wear.$(O) wizard.$(O) rogue.$(O) state.$(O) xcrypt.$(O)
+OBJS  = $(OBJS1) $(OBJS2)
+
+CFILES=	vers.c actions.c bolt.c chase.c command.c daemon.c daemons.c eat.c \
+	effects.c fight.c encumb.c help.c init.c io.c list.c main.c maze.c \
+	misc.c monsters.c mons_def.c move.c n_level.c options.c outside.c \
+	pack.c passages.c player.c potions.c rings.c rip.c rooms.c save.c \
+	scrolls.c sticks.c things.c trader.c util.c weapons.c wear.c wizard.c \
+	rogue.c state.c xcrypt.c
+
+MISC  = Makefile README.TXT LICENSE.TXT $(PROGRAM).sln $(PROGRAM).vcproj
+
+CC    = gcc
+CFLAGS= -O3
+CRLIB = -lcurses
+RM    = rm -f
+TAR   = tar 
+.SUFFIXES: .obj
+
+.c.obj:
+	$(CC) $(CFLAGS) /c $*.c
+
+$(PROGRAM): $(HDRS) $(OBJS)
+	$(CC) $(CFLAGS) $(LDFLAGS) $(OBJS) $(CRLIB) -o $@
+
+clean:
+	$(RM) $(OBJS1)
+	$(RM) $(OBJS2)
+	$(RM) core a.exe a.out a.exe.stackdump $(PROGRAM) $(PROGRAM).exe $(PROGRAM).tar $(PROGRAM).tar.gz $(PROGRAM).zip
+
+dist.src:
+	make clean
+	tar cf $(DISTNAME)-src.tar $(CFILES) $(HDRS) $(MISC)
+	gzip -f $(DISTNAME)-src.tar
+
+dist.irix:
+	make clean
+	make CC=cc CFLAGS="-woff 1116 -O3" $(PROGRAM)
+	tar cf $(DISTNAME)-irix.tar $(PROGRAM) README.TXT LICENSE.TXT
+	gzip -f $(DISTNAME)-irix.tar
+
+dist.aix:
+	make clean
+	make CC=xlc CFLAGS="-qmaxmem=16768 -O3 -qstrict" $(PROGRAM)
+	tar cf $(DISTNAME)-aix.tar $(PROGRAM) README.TXT LICENSE.TXT
+	gzip -f $(DISTNAME)-aix.tar
+
+dist.linux:
+	make clean
+	make $(PROGRAM)
+	tar cf $(DISTNAME)-linux.tar $(PROGRAM) README.TXT LICENSE.TXT
+	gzip -f $(DISTNAME)-linux.tar
+	
+dist.interix:
+	make clean
+	make $(PROGRAM)
+	tar cf $(DISTNAME)-interix.tar $(PROGRAM) README.TXT LICENSE.TXT
+	gzip -f $(DISTNAME)-interix.tar
+	
+dist.cygwin:
+	make clean
+	make $(PROGRAM)
+	tar cf $(DISTNAME)-cygwin.tar $(PROGRAM).exe README.TXT LICENSE.TXT
+	gzip -f $(DISTNAME)-cygwin.tar
+	
+dist.mingw32:
+	$(MAKE) RM="cmd /c del" clean
+	$(MAKE) CRLIB="-lpdcurses -lWs2_32" $(PROGRAM)
+	cmd /c del $(DISTNAME)-mingw32.zip
+	zip $(DISTNAME)-mingw32.zip $(PROGRAM).exe README.TXT LICENSE.TXT
+	
+dist.msys:
+	$(MAKE) clean
+	$(MAKE) CRLIB="-lcurses -lWs2_32" $(PROGRAM)
+	tar cf $(DISTNAME)-msys.tar $(PROGRAM).exe README.TXT LICENSE.TXT
+	gzip -f $(DISTNAME)-msys.tar
+	
+dist.djgpp:
+	make clean
+	make LDFLAGS="-L$(DJDIR)/LIB" CRLIB="-lpdcurses" $(PROGRAM)
+	rm -f $(DISTNAME)-djgpp.zip
+	zip $(DISTNAME)-djgpp.zip $(PROGRAM) README.TXT LICENSE.TXT
+
+dist.win32:
+	nmake O="obj" RM="-del" clean
+	nmake O="obj" CC="CL" CRLIB="..\pdcurses.lib shell32.lib user32.lib Advapi32.lib Ws2_32.lib" CFLAGS="-DPDC_STATIC_BUILD -nologo -I.. -Ox -wd4033 -wd4716" $(PROGRAM)
+	-del $(DISTNAME)-win32.zip
+	zip $(DISTNAME)-win32.zip $(PROGRAM).exe README.TXT LICENSE.TXT
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xrogue/README.TXT	Tue Apr 21 08:55:20 2015 -0400
@@ -0,0 +1,646 @@
+    Welcome to XRogue
+    http://roguelike.sourceforge.net/xrogue
+
+    XRogue: Expeditions into the Dungeons of Doom
+    Copyright (C) 1991 Robert Pietkivitch
+    All rights reserved.
+    
+    Based on "Advanced Rogue"
+    Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka and AT&T
+    All rights reserved.
+
+    Based on "Rogue: Exploring the Dungeons of Doom"
+    Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
+    All rights reserved.
+    
+    See the file LICENSE.TXT for full copyright and licensing information.
+
+
+XRogue: Expeditions into the Dungeons of Doom
+---------------------------------------------
+
+Introduction:
+
+Rogue was introduced at the University of California at Berkeley as a
+screen-oriented fantasy game.  The game had 26 types of monsters that
+the player could meet while exploring a Dungeon generated by the computer.
+Scrolls, potions, rings, wands, staves, armor, and weapons helped the
+player to battle these monsters and to gain gold, the basis for scoring.
+
+The version of rogue described in this guide has been expanded to include
+over 200 monsters with many new capabilities and has been renamed xrogue.
+Many of the monsters are intelligent and they, like the player, must avoid
+traps and decide when it is better to fight or to run.  There are also a
+number of new commands in this version not found in previous versions.
+
+The game contains monsters, spells, weapons, armor, potions, and other
+magical items that you will discover during your quest.  The Dungeon's
+geography changes with every game and although many magical items have
+certain identifiable properties, such as turning the player invisible,
+the physical manifestation of the magic changes each game.  A red potion,
+for example, will cause the same reaction throughout a given game but
+it may be a completely different potion in a new game.
+
+Entering the Dungeon with only a little food, armor, and a weapon, the
+player must develop a good strategy of when to fight, when to run, and
+how to best use any magical item found in the Dungeon.  To make things
+interesting the player has a quest to return one of several unique and
+magical artifacts which are rumored to lie deep within the Dungeon.
+Returning with this artifact to the surface brings great honor.
+
+However, after finding the artifact, the player may wish to continue
+his quest deeper into the Dungeon to match wits with an arch-devil, a
+demon-prince, or perhaps Charon the Boatman.  Defeating such a creature
+will gain the player many experience points which is the basis for
+scoring in xrogue.  It is very difficult to return from the Dungeons
+of Doom alive.  Very few players have won this game.
+
+Character Classes:
+
+Before placing the player in the Dungeon, the game requests that you
+select what type of character they would like to be: Fighter, Paladin,
+Ranger, Magic-User, Cleric, Thief, Assassin, Druid, or Monk.
+
+    The Fighter
+
+A Fighter has the best odds at winning battles with monsters.  At high
+experience levels, the Fighter is able to attack his opponent multiple
+times in a single turn.  Strength is the main attribute of the Fighter.
+
+    The Magic-User
+
+A Magic-User is able to cast spells.  Intelligence is the main attribute.
+The number of spells a Magic-User can cast increases as he gains in
+experience points and in intelligence.  His spell casting ability allows
+him to identify any item in the Dungeon.  16 spells.
+
+    The Cleric
+
+A Cleric is able to pray for assistance in battle.  Wisdom is the main
+attribute.  The number of prayers granted to the Cleric increases as he
+gains in experience points and in wisdom.  Clerics can affect (turn) the
+undead monsters to avoid battle.  Ie., zombies, ghouls, etc.  If the
+Cleric is very powerful relative to the undead monster, turning it will
+utterly destroy it.  16 prayers.
+
+    The Paladin
+
+A Paladin is a type of holy warrior, being a cross between a Cleric
+and a Fighter.  He is able to pray and affect the undead like the Cleric
+and fight like the Fighter, but both to a lesser extent.  He is on the
+side of all that is righteous and good and would never attack a monster
+that has not attacked him first.  If he happens to kill such a monster,
+inadvertantly or otherwise, he will begin to feel increasingly uneasy.
+If he kills too many such monsters, he will face karmic retaliation and
+be reduced to a mere Fighter, minus all of the Cleric's ability.
+Charisma is the main attribute with Wisdom second.
+
+    The Ranger
+
+A Ranger is a type of mystical warrior, being a cross between the
+Magic-User and Fighter.  Like the Paladin, he is on the side of all
+that is righteous and good and would never attack a monster that
+has not attacked him first.  A Ranger is able to cast spells like the
+Magic-User and fight like the Fighter, but both to a lesser extent.
+Charisma is the main attribute with Intelligence second.
+
+    The Thief
+
+A Thief is exceptionally dexterous and has great skill at being able
+to set a traps for and/or rob (steal) items from monsters.  Thieves have
+the ability to detect all the gold and hidden traps on each level of
+the Dungeon.  Their dexterous nature gives Thieves the ability to move
+very quietly, so they are not as likely as to wake up sleeping monsters
+as are the other character types.  If a Thief manages to sneak up on a
+creature without waking it he may be able to backstab the monster.  The
+damage from a backstab is greatly increased based upon the experience
+level.  Dexterity is the main attribute.
+
+    The Assassin
+
+An Assassin is a person trained in the art of killing monsters by
+surprise.  He has some of the abilities of the Thief, but he cannot
+sense traps or backstab.  Instead, the Assassin has the chance to kill
+an opponent outright with one deadly blow.  He can recognize and use
+poison found in the Dungeon on his weapon, thereby, making his next
+attack exceptionally lethal.  Dexterity is the main attribute.
+
+    The Druid
+
+A Druid is a type of magical warrior, being a cross between the Cleric
+and the Magic-User.  A Druid can chant both spells and prayers plus a
+few of his own.  The number of chants available to the Druid increases
+as he gains in experience points and in Wisdom.  Wisdom is the main
+attribute.  16 chants.
+
+    The Monk
+
+A Monk is trained in the martial arts.  He wears no armor and does not
+need a weapon (although using them is not forbidden).  As the Monk gains
+in experience points his natural defense or ability to dodge attackers
+increases.  The Mong is a cross between the Druid and Fighter, so he
+can chant and also fight like the Fighter, but both to a lesser extent.
+Constitution is the main attribute, with wisdom second.
+
+Attributes Of The Charaters:
+
+Strength - The primary attribute for encumberance.
+
+Intelligence - The primary attribute for casting spells.
+
+Wisdom - The primary attribute for prayers and chanting.
+
+Dexterity - The primary attribute for stealthiness.
+
+Charisma - The primary attribute for good will.  High Charisma also
+           affects the cost of objects when making transactions.
+
+Constitution - The primary attribute for health.  High Constitution
+               affects the amount of hit points you receive when
+               moving up in experience levels.
+
+Note: The Ranger, Paladin, and Monk do not receive their "special"
+magical abilities until they have advanced a few experience levels.
+
+Experience Levels:
+
+Characters gain experience points mostly from killing monsters.  Other
+actions, such as stealing items from monsters, backstabbing, and turning
+monsters, also add extra experience points.  Each character type gains
+experience points and moves up in experience levels at different rates.
+Moving up in experience levels adds extra hit points to the character
+which determines how many "hits" he can take before being killed.
+
+Allocating Attribute Points To The Characters:
+
+A player starts with 75 attribute points to distribute in to the character
+he has chosen to play.  When you are prompted to distribute the attribute
+points, the screen displays the minimum and maximum allowable values for
+that particular attribute.  The player can type a backspace (Ctrl-H) to go
+back and change a previous value and typing an escape (ESC) sets all the
+remaining attributes to the maximum value possible, given the number of
+remaining attribute points to be distributed.
+
+THE SCREEN
+
+During the normal course of play, the screen consists of three separate
+sections:  the top line, the bottom two lines, and the remaining screen
+in the middle.  The top line reports actions which occur during the game,
+the middle section depicts the Dungeon, and the bottom two lines describe
+the player's current condition.
+
+Whenever anything happens to the player, such as finding a scroll, hitting
+a monster, or being hit by a monster, a short report appears on the top
+line of the screen.  When you see the word 'More' on the top line, that
+means you must press the space key to continue.
+
+The following items may be found within the Dungeon. Some of them have
+more than one interpretation, depending upon whether your character
+recognizes them or not.
+
+|  A wall of a room.
+-  A wall of a room.
+*  A pile of gold.
+%  A way to another level.
++  A doorway.
+.  The floor in a room.
+#  The floor in a passageway.
+    Solid rock (denoted by a space).
+^  The entrance to a Trading Post
+@  The player.
+_  The player, when invisible.
+:  Some food.
+!  A flask containing a potion.
+?  A sealed scroll.
+=  A ring.
+)  A weapon.
+]  Some armor.
+;  A miscellaneous magic item
+,  An artifact
+/  A wand or a staff.
+ >  A trapdoor leading to the next level
+{  An arrow trap
+$  A sleeping gas trap
+}  A beartrap
+~  A trap that teleports you somewhere else
+`  A poison dart trap
+"  A shimmering magic pool
+'  An entrance to a maze
+$  Any magical item. (During magic detection)
+ >  A blessed magical item. (During magic detection)
+<  A cursed magical item. (During magic detection)
+
+Monsters are depicted as letters of the alphabet.  Note that all letters
+denote multiple monsters, depending on which level of the Dungeon you are
+on.  The player may identify a current monster by using the identify
+command ('/') or the clarify command ('=').
+
+The bottom two lines of the screen describe the player's current status.
+The first line gives the player's characteristics:
+
+Intelligence, Strength, Wisdom, Dexterity, Charisma, and Constitution
+all have a normal maximum value of 50 points, but they can go higher if
+augmented by a ring.  Encumberance is a measurement of how much the player
+can carry versus how much he is currently carrying. The more you carry
+relative to your maximum encumberance causes you to use more food.  The
+attribute of Strength fortifies one's encumberance.
+
+The player's current number of hit points are denoted as (Hp) and it is
+followed in parentheses by the player's current maximum hit points.  Hit
+points express the player's survivability.  As a player heals by resting,
+using potions, or spells, the player's current hit points gradually increase
+until they reach the current maximum.  This maximum number will be increased
+each time a player goes up an experience level.  If the player's current hit
+points reach 0, the player becomes "metabolically challenged".
+
+The player's armor class is denoted as (Ac).  This number describes the
+amount of protection provided by the armor, cloaks, and/or rings currently
+worn by the player. It is also affected by high or low dexterity.  Wearing
+no armor is equivalent to an armor class of 10 (Monk excepted).  The lower
+the armor class number, the better.
+
+The player's current experience level is denoted as (Exp), followed by
+the player's experience points.  A new experience level brings extra hit
+points and possibly added abilities, such as new spells for a Magic-user,
+new prayers for a Cleric, and new chants for a Druid.  There are a total
+of 26 experience levels per character.
+
+Commands:
+
+A player can invoke most commands by typing in a single character.
+Some commands, however, require a direction, in which case the player
+types the command character followed by a directional letter.  Many
+commands can be prefaced by a number, indicating how many times the
+command should be executed.
+
+When the player invokes a command referring to an item in the player's
+pack (such as reading a scroll), the game prompts for the item.  The
+player can then type the letter associated with the item.  Typing a '*'
+will produce a list of eligible items.
+
+A list of basic games commands:
+
+?  Preceding a command by a '?' produces a brief explanation of the
+    command.  The command '?*' gives an explanation of all the commands.
+    A '?@' gives information on things you encounter (rock, forest, etc).
+/  Preceding a symbol by a '/' identifies the symbol.
+=  Clarify.  After typing an '=' sign, the player can use the movement
+    keys to position the cursor anywhere on the current level.  As long
+    as the player can normally see the selected position, the game will
+    identify whatever is there.
+h  Move one position to the left.
+j  Move one position down.
+k  Move one position up.
+l  Move one position to the right.
+y  Move one position to the top left.
+u  Move one position to the top right.
+b  Move one position to the bottom left.
+n  Move one position to the bottom right.
+H  Run to the left until reaching something interesting.
+J  Run down until reaching something interesting.
+K  Run up until reaching something interesting.
+L  Run to the right until reaching something interesting.
+Y  Run to the top left until reaching something interesting.
+U  Run to the top right until reaching something interesting.
+B  Run to the bottom left until reaching something interesting.
+N  Run to the bottom right until reaching something interesting.
+
+ >  Go down the stairs to the next level or enter the outer region if you
+    are standing upon the wormhole trap (must be "flying" for this to work).
+<  Go up the stairs to the next level or enter the outer region if you are
+    standing upon the wormhole trap (must be "flying" for this to work).
+
+*  Count the gold in the player's pack.
+!  Escape to the shell level.
+$  Price an item at the Trading Post.
+#  Buy an item at the Trading Post.
+%  Sell an item at the Trading Post.
+.  This command (a period) causes the player to rest one turn.
+^  This command sets traps and is limited to Thieves and Assassins.  If the
+    command is successful the game will ask the player for the trap type and
+    sets it where the player is standing.
+a  Affect the undead.  This command is restricted to Clerics and Paladins
+    and must be followed by a directional letter.
+A  Choose your quest item (at game startup only!).
+c  This command is restricted to Druids and Monks and it produces a list of
+    available chants.  The player can select one of the displayed chants and
+    if the player's energy level is sufficiently high, "chant" it.  The more
+    complicated the spell, the more energy it will take.
+C  This command is restricted to Magic-Users and Rangers and it produces a
+    list of available spells.  The player can select one of the displayed
+    spells and if the player's energy level is sufficiently high, "cast" it.
+    The more complicated the spell, the more energy it will take.
+d  Drop an item from the player's pack.
+D  Dip something into a magic pool.
+e  Eat some food from the player's pack.
+f  When this command is preceded with a directional command, the player will
+    move in the specified direction until he crosses something interesting.
+F  Frighten a monster.  Not available to all characters.  This command
+    loses it's power at around level 10.
+g  Give away or trade a slime-mold for food with a monster.
+G  This command is restricted to Thieves and Assassins.  It causes the game
+    to display all of the gold on the current level.
+i  Display an inventory of the player's pack.
+I  This command prompts for an item from the player's pack and displays
+    the inventory information for that item.
+m  When the player types this command, you are prompted to mark an item
+    with a one-line name.
+o  Typing this command causes the game to display all the settable options.
+    The player can then examine them or change (some of) them
+O  Display your current character type and quest item.
+p  This command is restricted to Clerics and Paladins and it produces a
+    list of available prayers.  The player can then select one of the
+    displayed prayers and if the player's energy level is sufficiently high,
+    "pray" it.  The more complicated the prayer, the more energy it will 
+take.
+P  Pick up the items currently under the player.
+q  Quaff a potion from the player's pack.
+Q  Quit without saving the game.
+r  Read a scroll from the player's pack.
+s  Search for a secret door or a trap in the circle surrounding the player.
+S  Save your game to play at a later time.
+t  This command prompts for an object from the players pack.  The player
+    then can throw the object in the specified direction.
+T  Take off whatever the player is wearing.
+v  Print the current xrogue version number.
+w  Wield a weapon from the player's pack.
+W  Wear some armor, ring, or a miscellaneous magic item from the player's
+    pack.  The player can wear a maximum of 8 rings.
+X  This command is restricted to Thieves only.  It causes the game to 
+display
+    all of the hidden traps on the current level.
+z  This command prompts for a wand or staff from the player's pack and zaps
+    it in the specified direction.
++  Fortune cookie! (Note: if you play xrogue over a modem, typing three
+    consecutive '+' will tell your modem to enter "command" mode.  See your
+    modem manual on how to return from this mode).
+
+Escape  Pressing the Escape key will cancel the current command.
+Ctrl-B  Check your current score.  Scoring is based on experience points
+         and gold.  However, gold is not that important and 10% is hacked
+         off if a player is killed.
+Ctrl-E  Check your current food level.  This command is used when you want
+         to see just how much food you have remaining in your stomach.  A
+         full stomach is measured to be about 2000(2100).  As you play the
+         game, this level drops until you become hungry at about 200(2100).
+         A food level over 2000(2100) makes the character satiated, and a
+         level under 200(2100) makes the character hungry, then weak, and
+         finally fainting.  A level of 2000(2100) is the most the character
+         can eat, a full, satisfied stomach!
+Ctrl-L  Redraw the screen.
+Ctrl-N  When the player types this command, the game prompts you to type a
+         one-line name for a monster or for an item in the player's pack
+         To name a monster, position the cursor over the desired monster and
+         rename it.
+Ctrl-O  Display the current "affects" on the player (such as slow, phased,
+         confused, extra sight, flying, dancing, etc.).
+Ctrl-R  Repeat last message displayed on the top line of the screen.
+Ctrl-T  This command is restricted to Thieves and Assassins.  It must be
+         followed by a directional letter.  If a monster is standing next to
+         the player in the specified direction, the effect is to steal an
+         item from the monster's pack.  If successful, the monster does not
+         notice anything, but if the player is unsuccessful, there is a 
+chance
+         the monster will suddenly wake up and attack.
+Ctrl-U  Use a magic item in the player's pack.
+
+There is no explicit attack command.  If a player wishes to do battle with a
+monster, the player simply moves onto the spot where the monster is 
+standing.
+Whatever the player is wielding will be used as the player's weapon.
+
+As the player moves across items, the game automatically picks them up and
+places them into the player's pack.  If there is no room left in the pack,
+the item is left on the floor.  Setting the "pickup" option to "NO" will
+allow the player to pick up items at will using the 'P' command.
+
+All actions except for bookkeeping commands, such as taking an inventory,
+take time.  The amount of time varies with the command.  Swinging a weapon,
+for example, takes more time than simply moving; so a monster could move
+several spaces in the time it takes the player to make one attack.  The
+time it takes to swing a weapon also varies based on the bulk of the weapon,
+and the time it takes to simply move one space varies with the type of armor
+worn and the player's level of encumberance.  Movement is always faster when
+the player is "flying".
+
+Actions also take time and some of them can be disrupted.  If the player is
+casting a spell for example, and gets hit before finishing it, the spell is
+lost.  Similarly, the player might choke if hit while trying to eat.  These
+same rules apply to monsters as well.
+
+Some of the rooms in the Dungeon possess a natural light source.  In most
+other rooms and in corridors, the player can see only those things within
+a one-space radius around the player.  Dark rooms can be lit with magical
+light or by fire beetles and other monsters.
+
+The player can wield only one weapon at a time.  When a player attacks
+a monster, the amount of damage depends on the particular weapon he is
+wielding.  To fire a projectile weapon, such as a crossbow or a short bow,
+the player should wield the bow and throw the bolt or arrow at the monster.
+
+A weapon may be cursed or blessed which will affect the likelihood of you
+hitting a monster with it and the damage that it will inflict on the 
+monster.
+If the player has identified the weapon he is using, the "to hit" and the
+"to damage" bonuses appear (in that order) before the weapons name in the
+inventory listing.  A positive bonus indicates a blessed weapon, and a
+negative bonus usually indicates a cursed or misguided weapon.  A player
+cannot release a cursed weapon until a remove curse scroll is read or cast
+by magical means.
+
+After the player has identified a suit of armor, the protection bonus 
+appears
+before the armors name in the inventory listing.  If the bonus is positive
+the armor is blessed but if it is negative, the armor is probably cursed.
+The player cannot remove a cursed suit of armor until a remove curse scroll
+is read or cast by magical means.
+
+Some monsters can corrode your armor!  If such a monster hits a player
+when the player is wearing metal armor, the armor will lose some of its
+protective value.  This same corrosive property also applies to weapons
+when a player hits a monster with this ability.  Search for a scroll of
+"protection" to guard against corrosion of your armor and weapon.
+
+A player will find many potions and scrolls in the Dungeon.  Reading a
+scroll or quaffing a potion will usually cause some magical occurrence.
+Potions and scrolls may be either cursed or blessed.  In this version of
+xrogue, Monster Confusion scrolls will turn your hands a variety of colors.
+A blessed Magic Mapping scroll shows very detailed maps.  A scroll of
+Genocide works within the dungeon as well as in the outer region.  A
+scroll of blessed Teleportation will teleport you "upward" a few levels.
+Blessed Remove Curse will cause certain monsters to panic if the scroll
+is read near them.  Charm Monster will let you charm several monsters.
+
+The player can wear a maximum of eight rings.  Some of them have a magical
+effect on the player as long as they are worn.  Some rings also speed up
+the player's metabolism, making the player require food more often.  Rings
+can be cursed or blessed and the player cannot remove a cursed ring until
+a remove curse scroll is read or cast.
+
+Wands, rods, and staves help a player in battle and affect the Dungeon.
+A player uses the "z" (zap) command to use a wand either to shoot at a
+monster, teleport, or to light up a dark room.  Wands can be cursed or
+blessed.
+
+A player must be frugal with his food.  Both moving and searching through
+the Dungeon, and fighting monsters, consumes energy.  Starving results in
+the player's fainting for increasingly longer periods of time, during which
+any nearby monster can attack the player at will.  Food comes in the form
+of standard rations and as a variety of berries.  Some berries have side
+effects in addition to satisfying one's hunger.  Slime-Molds are monster
+food and if you have one, you may be able to trade it for a regular food
+ration, if the monster is of "friendly" persuasion.
+
+Gold has a couple of uses in the Dungeon.  The first use of gold is to buy
+things, either at a Trading Post or from a Quartermaster.  The Trading Post
+when found, is entered via the '>' command, like going down a stairway.
+A Quartermaster ('q') is a Dungeon vendor who appears at certain times and
+will try to sell the player some of his wares.  The Quartermaster's wares
+are never cursed but they can be blessed, though blessed goods do cost more
+than normal goods.  If the player chooses to buy something offered by a
+Quartermaster, he will make the transaction for the specified amount of gold
+and then disappear.  Attacking a Quartermaster causes him to vanish in
+haste!  You can sometimes find gold at the bottom of "magic pools".  Use
+the ">" command to dive for the gold, but be careful you don't drown!
+
+When beginning a new game, a player is placed in the Trading Post with
+an allotment of gold based upon the type of character chosen to play.
+There are some restrictions on the use of certain items by character.
+For example, only Fighters, Paladins, and Rangers can wield two-handed
+swords while Thieves and Assassins can not wear certain types of armor.
+However, the Trading Post (and Quartermaster) will happily sell a player
+anything that he can afford, whether you need it or not.
+
+Miscellaneous magical items such as a Pair of Boots or a Book are numerous
+within the Dungeon.  These items are usually used to a player's advantage,
+assuming they are not cursed.  Some of these items can be worn, such as a
+Cloak, while others are to be used, such as a Book, Beaker, or Ointment.
+The Medicine Crystal will heal you, remove all curses, heal you, and may
+cause panic in some monsters.
+
+There are a number of unique monsters deep within the depths of the Dungeon
+that carry very special magical items or artifacts.  When you begin the 
+game,
+you are asked to choose a "quest item" to retrieve from the Dungeon.  Most
+of these items can be used to the player's advantage, even if they are not
+one's own personal quest item during the game.  However, care must be taken
+when handling some of them for they have intelligence and some will reject
+mishandling or abuse.  These items consume your food (and your gold) so
+carrying them around results in increased food use.  Some of these items 
+will
+kill you outright if you happen to pick them up while wielding another
+artifact as your weapon.  Don't be too greedy with the artifacts!  Quest
+items begin appearing in xrogue between levels 40-50.  The less traumatic
+quest items appear earlier while the more severe ones appear later.  Once
+a unique monster is killed, you will not encounter another one like it in
+the Dungeon.
+
+A variety of traps exist within the Dungeon, including trap doors, bear
+traps, and sleeping traps.  Sometimes they are hidden from sight until
+sprung by a monster or by the player.  A sprung trap continues to function,
+but since it is visible, an intelligent monster is not likely to tread on 
+it.
+A trap called the Wormhole trap, will transport you to the "outer region"
+of the dungeon.  There you will fight strange dinosaurs until you can make
+your way back to a starwell, and promptly return from whence you came.
+
+Each monster except for the Quartermaster appears in a limited range of
+Dungeon levels.  All monsters of the same type share the same abilities.
+All giant rats, for example, can give the player a disease, and all
+jackalweres can put the player to sleep.  Monsters of the same type will
+vary however, in strength and intelligence.  For example, one kobold may
+be much more difficult to kill off than another.  In general, the more
+difficult it is to kill a monster, the more experience points the monster
+is worth.
+
+Most monsters attack by biting and clawing, but some monsters carry weapons
+and can use their breath as a weapon.  Some monsters can even use magical
+items, such as wands and artifacts.  Monsters with distance weapons or magic
+can sometimes attack a player from across a room or from down a corridor.
+
+Some monsters are more intelligent than others, and the more intelligent
+a monster is, the more likely it will run away if it is about to die.
+A fleeing monster will not attack the player unless it is cornered.
+
+It is sometimes possible to enlist a monster's aid.  Reading a charm monster
+scroll, for example, or singing a charm monster chants can make a monster
+believe that the player is its friend.  A charmed monster will fight hostile
+monsters for the player as long as they are not of its own race.  Be sure
+your charmed monsters are in the same room with you when you enter the next
+level, or they will be lost.
+
+Options:
+
+The game has several options, some of which can only be set by the player
+at the beginning of the game and others during the course of play.
+
+      default - Play the character with "default" attribute settings.
+        terse - Shorten messages at top of screen.
+         jump - Speed up the display of the player's movement
+         step - Lists all inventories one line at a time.
+      overlay - Allows listings of inventories to overlay the currnt screen.
+        flush - Supposed to flush all typed-ahead characters.
+        askme - Prompt the player to name new types of scrolls, potions, 
+etc.
+       pickup - Pick up items automatically as you move across them
+         name - The player's name.
+         file - Saved game filename.  Defaults to xrogue.sav.
+        score - Identifies the location of the game scorefile.
+         type - Specifies the character type (unchangable).
+quested item - Set at start up (unchangeable).
+
+A player can set the game options at the beginning of a game via the
+ROGUEOPTS environment variable.
+
+Some examples:
+
+  ROGUEOPTS="default nopickup, nooverlay, name=Corwin, class=magician"
+  ROGUEOPTS="pickup, overlay, file=xrg.sav, score=/home/games/scorefile"
+
+The player may change an option at any time during the game via the 'o'
+(option) command.  On the options menu, typing a new value changes the
+option and a RETURN moves to the next option in the list.  Typing an '-'
+moves you to the previous option and an ESCAPE returns you to the Dungeon.
+
+A new option called "default" was added in xrogue.  When you put the word
+"default" into your ROGUEOPTS environment variable your character will be
+created with "default" attribute settings, armor, weapon, quest item, and
+some food.
+
+Setting "default" will force the game to skip over the beginning screen
+where you can choose/distribute your attribute points and it also skips
+over the beginning "equippage screen" where you can choose your armor,
+weapon, quest item, and etc.
+
+If you use the "class" option with "default" in ROGUEOPTS, you will
+start the game immediately at level 1 with the default selections
+for your character.
+
+Here is a list of the main and secondary attributes, special ability,
+and quest item ("default" settings) for each character type:
+
+  Character Main Attr.    Secondary     Specialties       Def. Quest Item
+  -------------------------------------------------------------------------
+  Fighter   strength      constitution  sense gold        Axe of Aklad
+  Ranger    charisma      intelligence  cast spells       Mandolin of Brian
+  Paladin   charisma      wisdom        affect undead     Ankh of Heil
+  Cleric    wisdom        dexterity     prayer spells     Horn of Geryon
+  Magician  intelligence  dexterity     cast spells       Stonebones Amulet
+  Thief     dexterity     strength      sense traps       Musty Daggers
+  Assassin  dexterity     strength      steal/use poison  Eye of Vecna
+  Druid     wisdom        dexterity     chant spells      Quill of Nagrom
+  Monk      constitution  dexterity     chant spells      Emori Cloak
+
+A different quest item may be chosen ONLY while you are in the beginning
+Trading Post (if you have NOT set the "default" option via ROGUEOPTS).
+
+When a player is killed, his score will be equal to the amount of his
+experience points gained, plus his gold (minus 10%).  A player that
+quits the game will not lose 10% of his gold.  If a player makes it back
+up and out of the Dungeon alive, his score will be equal to the amount
+of experience points, plus the gold, plus additional gold received from
+selling all of the items in his pack.
+
+The game maintains a top-twenty player scorefile.  As an installation
+option, the game may be compiled so as to record only three entries per
+character type and name.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xrogue/actions.c	Tue Apr 21 08:55:20 2015 -0400
@@ -0,0 +1,1074 @@
+/*
+    actions.c  -  functions for dealing with monster actions
+   
+    XRogue: Expeditions into the Dungeons of Doom
+    Copyright (C) 1991 Robert Pietkivitch
+    All rights reserved.
+    
+    Based on "Advanced Rogue"
+    Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka and AT&T
+    All rights reserved.
+
+    Based on "Rogue: Exploring the Dungeons of Doom"
+    Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
+    All rights reserved.
+    
+    See the file LICENSE.TXT for full copyright and licensing information.
+*/
+
+#include <ctype.h>
+#include <curses.h>
+#include <limits.h>
+#include "rogue.h"
+
+int mf_count = 0;       /* move_free counter - see actions.c(m_act()) */
+int mf_jmpcnt = 0;      /* move_free counter for # of jumps           */
+
+/* 
+ * Did we disrupt a spell? 
+ */
+dsrpt_monster(tp, always, see_him)
+register struct thing *tp;
+bool always, see_him;
+{
+    switch (tp->t_action) {
+    case A_SUMMON:
+    case A_MISSILE:
+    case A_SLOW:
+        tp->t_action = A_NIL;   /* Just make the old fellow start over again */
+        tp->t_no_move = movement(tp);
+        tp->t_using = NULL; /* Just to be on the safe side */
+        turn_on(*tp, WASDISRUPTED);
+        if (see_him)
+            msg("%s's spell has been disrupted.",prname(monster_name(tp),TRUE));
+        /*
+         * maybe choose something else to do next time since player
+         * is disrupting us
+         */
+        tp->t_summon *= 2;
+        tp->t_cast /= 2;
+        return;
+    }
+
+    /* We may want to disrupt other actions, too */
+    if (always) {
+        tp->t_action = A_NIL; /* Just make the old fellow start over again */
+        tp->t_no_move = movement(tp);
+        tp->t_using = NULL;/* Just to be on the safe side */
+    }
+}
+
+dsrpt_player()
+{
+    int which, action;
+    struct linked_list *item;
+    struct object *obj;
+    
+    action = player.t_action;
+    which = player.t_selection;
+
+    switch (action) {
+    case C_CAST: /* Did we disrupt a spell? */
+    case C_PRAY:
+    case C_CHANT:
+    {
+        msg("Your %s was disrupted!", action == C_CAST ? "spell" : "prayer");
+
+        /* Charge him 1/4 anyway */
+        if (action == C_CAST)
+            spell_power += magic_spells[which].s_cost / 4;
+        else if (action == C_PRAY)
+            pray_time += cleric_spells[which].s_cost / 4;
+        else if (action == C_CHANT)
+            chant_time += druid_spells[which].s_cost / 4;
+    }
+    when C_COUNT: /* counting of gold? */
+    {
+        if (purse > 0) {
+            msg("Your gold goes flying everywhere!");
+            do {
+                item = spec_item(GOLD, NULL, NULL, NULL);
+                obj = OBJPTR(item);
+                obj->o_count = min(purse, rnd(20)+1);
+                purse -= obj->o_count;
+                obj->o_pos = hero;
+                fall(item, FALSE);
+            } while (purse > 0 && rnd(25) != 1);
+        }
+    }
+    when C_EAT:
+        msg("Ack!  You gag on your food for a moment. ");
+        del_pack(player.t_using);
+        
+    when A_PICKUP:
+        msg("You drop what you are picking up! ");
+
+    when C_SEARCH:      /* searching for traps and secret doors... */
+        msg("Ouch!  You decide to stop searching. ");
+        count = 0;      /* don't search again */
+
+    when C_SETTRAP:
+        msg("Ouch!  You can't set a trap right now. ");
+
+    when A_NIL:
+    default:
+        return;
+    }
+    player.t_no_move = movement(&player); /* disoriented for a while */
+    player.t_action = A_NIL;
+    player.t_selection = 0;
+}
+
+/*
+ * m_act:
+ *      If the critter isn't doing anything, choose an action for it.
+ *      Otherwise, let it perform its chosen action.
+ */
+
+m_act(tp)
+register struct thing *tp;
+{
+    struct object *obj;
+    bool flee;          /* Are we scared? */
+
+    /* What are we planning to do? */
+    switch (tp->t_action) {
+        default:
+            /* An unknown action! */
+            msg("Unknown monster action (%d)", tp->t_action);
+
+            /* Fall through */
+
+        case A_NIL:
+            /* If the monster is fairly intelligent and about to die, it
+             * may turn tail and run.  But if we are a FRIENDLY creature
+             * in the hero's service, don't run.
+             */
+            if (off(*tp, ISFLEE)                                        &&
+                tp->t_stats.s_hpt < tp->maxstats.s_hpt                  &&
+                tp->t_stats.s_hpt < max(10, tp->maxstats.s_hpt/6)       &&
+                (off(*tp, ISFRIENDLY) || tp->t_dest != &hero)           &&
+                rnd(25) < tp->t_stats.s_intel) {
+                    turn_on(*tp, ISFLEE);
+
+                    /* It is okay to turn tail */
+                    tp->t_oldpos = tp->t_pos;
+                }
+
+            /* Should the monster run away? */
+            flee = on(*tp, ISFLEE) ||
+                ((tp->t_dest == &hero) && on(player, ISINWALL) &&
+                 off(*tp, CANINWALL));
+
+            m_select(tp, flee); /* Select an action */
+            return;
+
+        when A_ATTACK:
+            /* 
+             * We're trying to attack the player or monster at t_newpos 
+             * if the prey moved, do nothing
+             */
+            obj = tp->t_using ? OBJPTR(tp->t_using) : NULL;
+            if (ce(tp->t_newpos, hero)) {
+                attack(tp, obj, FALSE);
+            }
+            else if (mvwinch(mw, tp->t_newpos.y, tp->t_newpos.x) &&
+                     step_ok(tp->t_newpos.y, tp->t_newpos.x, FIGHTOK, tp)) {
+                skirmish(tp, &tp->t_newpos, obj, FALSE);
+            }
+
+        when A_SELL:
+                /* Is the quartermaster still next to us? */
+            if (ce(tp->t_newpos, hero)) sell(tp);
+
+                /* The quartermaster moved away */
+            else if (off(player, ISBLIND) && cansee(unc(tp->t_pos)) &&
+                (off(*tp, ISINVIS)     || on(player, CANSEE)) &&
+                (off(*tp, ISSHADOW)    || on(player, CANSEE)) &&
+                (off(*tp, CANSURPRISE) || ISWEARING(R_ALERT)) &&
+        (rnd(12) < 4))
+                msg("%s grunts with frustration",prname(monster_name(tp),TRUE));
+
+        when A_MOVE:
+            /* Let's try to move */
+            do_chase(tp);
+
+            /* If t_no_move > 0, we found that we have to fight! */
+            if (tp->t_no_move > 0) return;
+
+        when A_BREATHE:
+            /* Breathe on the critter */
+            m_breathe(tp);
+
+        when A_SLOW:
+            /* make him move slower */
+            add_slow();
+            turn_off(*tp, CANSLOW);
+
+        when A_MISSILE:
+            /* Start up a magic missile spell */
+            m_spell(tp);
+
+        when A_SONIC:
+            /* Let out a sonic blast! */
+            m_sonic(tp);
+
+        when A_THROW:
+            /* We're throwing something (like an arrow) */
+            missile(tp->t_newpos.y, tp->t_newpos.x, tp->t_using, tp);
+
+        when A_SUMMON:
+            /* We're summoning help */
+            m_summon(tp);
+
+        when A_USERELIC:
+            /* Use our relic */
+            m_use_relic(tp);
+
+        when A_USEWAND:
+            /* use the wand we have */
+            m_use_wand(tp);
+    }
+
+    /* Can we in fact move?  (we might have solidified in solid rock) */
+    if (!step_ok(hero.y, hero.x, NOMONST, &player)) {
+
+         if (move_free > 1) goto jump_over;   /* avoid messages */
+         if (mf_count > 2)  goto jump_over;   /* limit messages */
+
+         if (pstats.s_hpt < 1) {
+         pstats.s_hpt = -1;
+             msg("You have merged into the surroundings!  --More--");
+             wait_for(' ');
+             death(D_PETRIFY);
+         }
+         else {
+             mf_count += 1;  /* count number of times we are here */
+             pstats.s_hpt -= rnd(2)+1;
+             if (pstats.s_hpt < 1) {
+          pstats.s_hpt = -1;
+                  msg("You have merged into the surroundings!  --More--");
+                  wait_for(' ');
+                  death(D_PETRIFY);
+             }
+         }
+         switch (rnd(51)) {
+             case 0: msg("Arrrggghhhhh!! ");
+             when 5: msg("You can't move! "); 
+             when 10: msg("You motion angrily! "); 
+             when 15: msg("You feel so weird! ");
+             when 20: msg("If only you could phase. ");
+             when 25: msg("The rock maggots are closing in! ");
+             when 30: msg("You wrench and wrench and wrench... ");
+             when 35: msg("You wish you could teleport out of here! ");
+             when 40: msg("Your feel your life force ebbing away... ");
+             when 45: msg("You partially regain your senses. ");
+             when 50: msg("The rock maggots have found you!!! "); 
+             otherwise: pstats.s_hpt -= rnd(4)+1;
+         }
+         if (pstats.s_hpt < 1) {
+          pstats.s_hpt = -1;
+              msg("You lose the urge to live...  --More--");
+              wait_for(' ');
+              death(D_PETRIFY);
+     }
+        jump_over:
+        mf_jmpcnt++;          /* count this jump */
+        if (mf_jmpcnt > 9) {  /* take a few turns, then reset it */
+            mf_jmpcnt = 0;
+            mf_count  = 0;
+        }
+    }
+
+    /* No action now */
+    tp->t_action = A_NIL;
+    tp->t_using = NULL;
+}
+
+/*
+ * m_breathe:
+ *      Breathe in the chosen direction.
+ */
+
+m_breathe(tp)
+register struct thing *tp;
+{
+    register int damage;
+    register char *breath = NULL;
+
+    damage = tp->t_stats.s_hpt;
+    turn_off(*tp, CANSURPRISE);
+
+    /* Will it breathe at random */
+    if (on(*tp, CANBRANDOM)) {
+        /* Turn off random breath */
+        turn_off(*tp, CANBRANDOM);
+
+        /* Select type of breath */
+        switch (rnd(10)) {
+            case 0: breath = "acid";
+                    turn_on(*tp, NOACID);
+            when 1: breath = "flame";
+                    turn_on(*tp, NOFIRE);
+            when 2: breath = "lightning bolt";
+                    turn_on(*tp, NOBOLT);
+            when 3: breath = "chlorine gas";
+                    turn_on(*tp, NOGAS);
+            when 4: breath = "ice";
+                    turn_on(*tp, NOCOLD);
+            when 5: breath = "nerve gas";
+                    turn_on(*tp, NOPARALYZE);
+            when 6: breath = "sleeping gas";
+                    turn_on(*tp, NOSLEEP);
+            when 7: breath = "slow gas";
+                    turn_on(*tp, NOSLOW);
+            when 8: breath = "confusion gas";
+                    turn_on(*tp, ISCLEAR);
+            when 9: breath = "fear gas";
+                    turn_on(*tp, NOFEAR);
+        }
+    }
+
+    /* Or can it breathe acid? */
+    else if (on(*tp, CANBACID)) {
+        turn_off(*tp, CANBACID);
+        breath = "acid";
+    }
+
+    /* Or can it breathe fire */
+    else if (on(*tp, CANBFIRE)) {
+        turn_off(*tp, CANBFIRE);
+        breath = "flame";
+    }
+
+    /* Or can it breathe electricity? */
+    else if (on(*tp, CANBBOLT)) {
+        turn_off(*tp, CANBBOLT);
+        breath = "lightning bolt";
+    }
+
+    /* Or can it breathe gas? */
+    else if (on(*tp, CANBGAS)) {
+        turn_off(*tp, CANBGAS);
+        breath = "chlorine gas";
+    }
+
+    /* Or can it breathe ice? */
+    else if (on(*tp, CANBICE)) {
+        turn_off(*tp, CANBICE);
+        breath = "ice";
+    }
+
+    else if (on(*tp, CANBPGAS)) {
+        turn_off(*tp, CANBPGAS);
+        breath = "nerve gas";
+    }
+
+    /* can it breathe sleeping gas */
+    else if (on(*tp, CANBSGAS)) {
+        turn_off(*tp, CANBSGAS);
+        breath = "sleeping gas";
+    }
+
+    /* can it breathe slow gas */
+    else if (on(*tp, CANBSLGAS)) {
+        turn_off(*tp, CANBSLGAS);
+        breath = "slow gas";
+    }
+
+    /* can it breathe confusion gas */
+    else if (on(*tp, CANBCGAS)) {
+        turn_off(*tp, CANBCGAS);
+        breath = "confusion gas";
+    }
+
+    /* can it breathe fear gas */
+    else {
+        turn_off(*tp, CANBFGAS);
+        breath = "fear gas";
+    }
+
+    /* Now breathe */
+    shoot_bolt(tp, tp->t_pos, tp->t_newpos, FALSE, 
+                    tp->t_index, breath, damage);
+
+    running = FALSE;
+    if (fight_flush) flushinp();
+}
+
+/*
+ * m_select:
+ *      Select an action for the monster.
+ */
+
+m_select(th, flee)
+register struct thing *th;
+register bool flee; /* True if running away or player is inaccessible in wall */
+{
+    register struct room *rer, *ree;    /* room of chaser, room of chasee */
+    int dist = INT_MIN;
+    int mindist = INT_MAX, maxdist = INT_MIN;
+    bool rundoor;                       /* TRUE means run to a door */
+    char sch;
+    coord *last_door=0,                 /* Door we just came from */
+           this;                        /* Temporary destination for chaser */
+
+    rer = roomin(&th->t_pos);   /* Find room of chaser */
+    ree = roomin(th->t_dest);   /* Find room of chasee */
+
+    /* First see if we want to use an ability or weapon */
+    if (m_use_it(th, flee, rer, ree)) return;
+
+    /*
+     * We don't count monsters on doors as inside rooms here because when
+     * a monster is in a room and the player is not in that room, the
+     * monster looks for the best door out.  If we counted doors as part
+     * of the room, the monster would already be on the best door out;
+     * so he would never move.
+     */
+    if ((sch = mvwinch(stdscr, th->t_pos.y, th->t_pos.x)) == DOOR ||
+        sch == SECRETDOOR || sch == PASSAGE) {
+        rer = NULL;
+    }
+    this = *th->t_dest;
+
+    /*
+     * If we are in a room heading for the player and the player is not
+     * in the room with us, we run to the "best" door.
+     * If we are in a room fleeing from the player, then we run to the
+     * "best" door if he IS in the same room.
+     *
+     * Note:  We don't bother with doors in mazes or if we can walk
+     * through walls.
+     */
+    if (rer != NULL && levtype != MAZELEV && off(*th, CANINWALL)) {
+        if (flee) rundoor = (rer == ree);
+        else rundoor = (rer != ree);
+    }
+    else rundoor = FALSE;
+
+    if (rundoor) {
+        register struct linked_list *exitptr;   /* For looping through exits */
+        coord *exit,                            /* A particular door */
+              *entrance;                        /* Place just inside doorway */
+        int exity, exitx;                       /* Door's coordinates */
+        char dch='\0';                          /* Door character */
+
+        if ((th->t_doorgoal.x != -1) && (th->t_doorgoal.y != -1))
+            dch = mvwinch(stdscr, th->t_doorgoal.y, th->t_doorgoal.x);
+            
+        /* Do we have a valid goal? */
+        if ((dch == PASSAGE || dch == DOOR) &&  /* A real door */
+            (!flee || !ce(th->t_doorgoal, *th->t_dest))) { /* Prey should not
+                                                             * be at door if
+                                                             * we are running
+                                                             * away
+                                                             */
+            /* Make sure the player is not in the doorway, either */
+            entrance = doorway(rer, &th->t_doorgoal);
+            if (!flee || entrance == NULL || !ce(*entrance, *th->t_dest)) {
+                this = th->t_doorgoal;
+                dist = 0;       /* Indicate that we have our door */
+            }
+        }
+
+        /* Go through all the doors */
+        else for (exitptr = rer->r_exit; exitptr; exitptr = next(exitptr)) {
+            exit = DOORPTR(exitptr);
+            exity = exit->y;
+            exitx = exit->x;
+
+            /* Make sure it is a real door */
+            dch = mvwinch(stdscr, exity, exitx);
+            if (dch == PASSAGE || dch == DOOR) {
+                /* Don't count a door if we are fleeing from someone and
+                 * he is standing on it.  Also, don't count it if he is
+                 * standing in the doorway.
+                 */
+                if (flee) {
+                    if (ce(*exit, *th->t_dest)) continue;
+
+                    entrance = doorway(rer, exit);
+                    if (entrance != NULL && ce(*entrance, *th->t_dest))
+                        continue;
+                }
+                
+                /* Were we just on this door? */
+                if (ce(*exit, th->t_oldpos)) last_door = exit;
+
+                else {
+                    dist = DISTANCE(th->t_dest->y, th->t_dest->x, exity, exitx);
+
+                    /* If fleeing, we want to maximize distance from door to
+                     * what we flee, and minimize distance from door to us.
+                     */
+                    if (flee)
+                       dist -= DISTANCE(th->t_pos.y, th->t_pos.x, exity, exitx);
+
+                    /* Maximize distance if fleeing, otherwise minimize it */
+                    if ((flee && (dist > maxdist)) ||
+                        (!flee && (dist < mindist))) {
+                        th->t_doorgoal = *exit;  /* Use this door */
+                        this = *exit;
+                        mindist = maxdist = dist;
+                    }
+                }
+            }
+        }
+
+        /* Could we not find a door? */
+        if (dist == INT_MIN) {
+            /* If we were on a door, go ahead and use it */
+            if (last_door) {
+                th->t_doorgoal = *last_door;
+                this = th->t_oldpos;
+                dist = 0;       /* Indicate that we found a door */
+            }
+            else th->t_doorgoal.x = th->t_doorgoal.y = -1; /* No more door goal */
+        }
+
+        /* Indicate that we do not want to flee from the door */
+        if (dist != INT_MIN) flee = FALSE;
+    }
+    else th->t_doorgoal.x = th->t_doorgoal.y = -1;    /* Not going to any door */
+
+    /* Now select someplace to go and start the action */
+    chase(th, &this, rer, ree, flee);
+}
+
+/*
+ * m_sonic:
+ *      The monster is sounding a sonic blast.
+ */
+
+m_sonic(tp)
+register struct thing *tp;
+{
+    register int damage;
+    struct object blast =
+    {
+        MISSILE, {0, 0}, 0, "", "150" , NULL, 0, 0, 0, 0
+    };
+
+    turn_off(*tp, CANSONIC);
+    turn_off(*tp, CANSURPRISE);
+    do_motion(&blast, tp->t_newpos.y, tp->t_newpos.x, tp);
+    damage = rnd(61)+40;
+    if (save(VS_BREATH, &player, -3))
+        damage /= 2;
+    msg ("%s's ultra-sonic blast hits you", prname(monster_name(tp), TRUE));
+    if ((pstats.s_hpt -= damage) <= 0) {
+    pstats.s_hpt = -1;
+        death(tp->t_index);
+    }
+    running = FALSE;
+    if (fight_flush) flushinp();
+    dsrpt_player();
+}
+
+/*
+ * m_spell:
+ *      The monster casts a spell.  Currently this is limited to
+ *      magic missile.
+ */
+m_spell(tp)
+register struct thing *tp;
+{
+    struct object missile =
+    {
+        MISSILE, {0, 0}, 0, "", "0d4 " , NULL, 0, WS_MISSILE, 100, 1
+    };
+
+    sprintf(missile.o_hurldmg, "%dd4", tp->t_stats.s_lvl);
+    do_motion(&missile, tp->t_newpos.y, tp->t_newpos.x, tp);
+    hit_monster(unc(missile.o_pos), &missile, tp);
+    turn_off(*tp, CANMISSILE);
+    turn_off(*tp, CANSURPRISE);
+
+    running = FALSE;
+    if (fight_flush) flushinp();
+}
+
+/*
+ * m_summon:
+ *      Summon aid.
+ */
+
+m_summon(tp)
+register struct thing *tp;
+{
+    register char *helpname, *mname;
+    int fail, numsum;
+    register int which, i;
+
+    /* Let's make sure our prey is still here */
+    if (!cansee(unc(tp->t_pos)) || fallpos(&hero, FALSE, 2) == NULL) return;
+
+    /*
+     * Non-uniques can only summon once.  Uniques get fewer
+     * creatures with each successive summoning. Also, the
+     * probability of summoning goes down
+     */
+    if (off(*tp, ISUNIQUE))
+            turn_off(*tp, CANSUMMON);
+
+    turn_off(*tp, CANSURPRISE);
+    mname = monster_name(tp);
+    helpname = monsters[tp->t_index].m_typesum;
+    which = findmindex(helpname);
+
+    if ((off(*tp, ISINVIS)     || on(player, CANSEE)) &&
+        (off(*tp, ISSHADOW)    || on(player, CANSEE)) &&
+        (off(*tp, CANSURPRISE) || ISWEARING(R_ALERT))) {
+        if (monsters[which].m_normal == FALSE) { /* genocided? */
+            msg("%s appears dismayed", prname(mname, TRUE));
+            monsters[tp->t_index].m_numsum = 0;
+        }
+        else {
+            msg("%s summons %ss for help", prname(mname, TRUE), helpname);
+        }
+    }
+    else {
+        if (monsters[which].m_normal == FALSE) /* genocided? */
+            monsters[tp->t_index].m_numsum = 0;
+        else {
+            msg("%ss seem to appear from nowhere!", helpname);
+        }
+    }
+    numsum = monsters[tp->t_index].m_numsum;
+    if (numsum && on(*tp, ISUNIQUE)) {   /* UNIQUEs summon less each time */
+        monsters[tp->t_index].m_numsum--; 
+        tp->t_summon *= 2; /* cut probability in half */
+    }
+
+    /*
+     * try to make all the creatures around player but remember
+     * if unsuccessful
+     */
+    for (i=0, fail=0; i<numsum; i++) {
+         if (!creat_mons(&player, which, FALSE))
+             fail++;    /* remember the failures */
+    }
+
+    /*
+     * try once again to make the buggers
+     */
+    for (i=0; i<fail; i++)
+         creat_mons(tp, which, FALSE);
+    
+    /* Now let the poor fellow see all the trouble */
+    light(&hero);
+    turn_on(*tp, HASSUMMONED);
+}
+
+/*
+ * m_use_it:
+ *      See if the monster (tp) has anything useful it can do
+ *      (ie. an ability or a weapon) other than just move.
+ */
+
+bool
+m_use_it(tp, flee, rer, ree)
+register struct thing *tp;
+bool flee;
+register struct room *rer, *ree;
+{
+    int dist;
+    register coord *ee = tp->t_dest, *er = &tp->t_pos; 
+    coord *shoot_dir = NULL;
+    coord straight_dir;
+    int   straight_shot = FALSE;
+    struct thing *prey;
+    bool dest_player;   /* Are we after the player? */
+
+    /*
+     * If we are fleeing, there's a chance, depending on our
+     * intelligence, that we'll just run in terror.
+     */
+    if (flee && rnd(25) >= tp->t_stats.s_intel) return(FALSE);
+
+    /*
+     * Make sure that we have a living destination, and record whether
+     * it is the player.
+     */
+    if (ee != NULL) {
+        if (ce(*ee, hero)) {
+            dest_player = TRUE;
+            prey = &player;
+        }
+        else {
+            struct linked_list *item;
+
+            dest_player = FALSE;
+
+            /* What is the monster we're chasing? */
+            item = find_mons(ee->y, ee->x);
+            if (item != NULL) prey = THINGPTR(item);
+            else return(FALSE);
+        }
+    }
+    else return(FALSE);
+
+    /*
+     * If we are friendly to the hero, we don't do anything.
+     */
+    if (on(*tp, ISFRIENDLY) && dest_player) return(FALSE);
+
+    /*
+     * Also, for now, if our prey is in a wall, we won't do
+     * anything.  The prey must be in the same room as we are OR
+     * we must have a straight shot at him.  Note that
+     * shoot_dir must get set before rer is checked so
+     * that we get a valid value.
+     */
+ 
+    if (can_shoot(er, ee, &straight_dir) == 0)
+        shoot_dir = &straight_dir;
+    else
+        shoot_dir = NULL;
+
+    if (on(*prey, ISINWALL) ||
+        ( (shoot_dir == NULL) && (rer == NULL || rer != ree)))
+        return(FALSE);
+
+    /*
+     * If we can't see the prey then forget it
+     */
+    if (on(*prey, ISINVIS) && off(*tp, CANSEE))
+        return(FALSE);
+
+    /* How far are we from our prey? */
+    dist = DISTANCE(er->y, er->x, ee->y, ee->x);
+
+    /* 
+     * Shall we summon aid so we don't have to get our hands dirty? 
+     * For now, we will only summon aid against the player.
+     * We'll wait until he's within 2 dots of a missile length.
+     */
+    if (on(*tp, CANSUMMON) && dest_player                       &&
+        dist < (BOLT_LENGTH+2)*(BOLT_LENGTH+2)                  &&
+        rnd(tp->t_summon) < tp->t_stats.s_lvl                   &&
+        monsters[tp->t_index].m_numsum > 0                      &&
+        fallpos(&hero, FALSE, 2) != NULL) {
+        tp->t_action = A_SUMMON;        /* We're going to summon help */
+        tp->t_no_move = movement(tp); /* It takes time! */
+        return(TRUE);
+    }
+
+    /*
+     * If the creature can cast a slow spell and if the prey is within
+     * 2 dots of a missile fire, then see whether we will cast it.
+     * if next to player, lessen chance because we don't like being
+     * disrupted
+     */
+    if (on(*tp, CANSLOW) && dest_player                 && 
+        dist < (BOLT_LENGTH+5)*(BOLT_LENGTH+5)          &&
+        rnd(100) < (dist > 3 ? tp->t_cast : tp->t_cast/2)) {
+            tp->t_action = A_SLOW;              /* We're going to slow him */
+            tp->t_no_move = 3 * movement(tp);   /* Takes time! */
+            debug("casting slow spell!");
+            return(TRUE);
+    }
+
+    /*
+     * If we have a special magic item, we might use it.  We will restrict
+     * this options to uniques with relics and creatures with wands for now.  
+     * Also check for the quartermaster. Don't want him shooting wands....
+     */
+    if ((on(*tp, ISUNIQUE) || on(*tp, CARRYSTICK)) && 
+        off(*tp, CANSELL) && dest_player           &&
+        m_use_pack(tp, ee, dist, shoot_dir)) {
+            return(TRUE);
+    }
+
+    /* From now on, we must have a direct shot at the prey */
+    if (!straight_shot) return(FALSE);
+
+    /* We may use a sonic blast if we can, only on the player */
+    if (on(*tp, CANSONIC)               && 
+        dest_player                     &&
+        (dist < BOLT_LENGTH*2)          &&
+        (rnd(100) < tp->t_breathe)) {
+        tp->t_newpos = *shoot_dir;      /* Save the direction */
+        tp->t_action = A_SONIC; /* We're going to sonic blast */
+        tp->t_no_move = 2 * movement(tp); /* Takes 2 movement periods */
+    }
+
+    /* If we can breathe, we may do so */
+    else if (on(*tp, CANBREATHE)                &&
+         (dist < BOLT_LENGTH*BOLT_LENGTH)       &&
+         (rnd(100) < tp->t_breathe)) {
+            tp->t_newpos = *shoot_dir;  /* Save the direction */
+            tp->t_action = A_BREATHE;   /* We're going to breathe */
+            tp->t_no_move = movement(tp); /* It takes 1 movement period */
+    }
+
+    /* 
+     * We may shoot missiles if we can 
+     * if next to player, lessen chance so we don't get disrupted as often
+     */
+    else if (on(*tp,CANMISSILE) && 
+             rnd(100) < (dist > 3 ? tp->t_cast : tp->t_cast/2)){
+            tp->t_newpos = *shoot_dir;  /* Save the direction */
+            tp->t_action = A_MISSILE;   /* We're going to shoot MM's */
+            tp->t_no_move = 3 * movement(tp); /* Takes time! */
+    }
+
+    /* 
+     * If we can shoot or throw something, we might do so.
+     * If next to player, then forget it
+     */
+    else if ((on(*tp,CANSHOOT)          || on(*tp,CARRYWEAPON) || 
+              on(*tp,CARRYDAGGER)       || on(*tp, CARRYAXE))           &&
+              dist > 3                                                  &&
+              off(*tp, CANSELL)                                         &&
+             (get_hurl(tp) != NULL)) {
+            tp->t_newpos = *shoot_dir;  /* Save the direction */
+            tp->t_action = A_THROW;     /* We're going to throw something */
+            tp->t_using = get_hurl(tp);       /* Save our weapon */
+            tp->t_no_move = 2 * movement(tp); /* Takes 2 movement periods */
+    }
+    
+    /* We couldn't find anything to do */
+    else return(FALSE);
+
+    return(TRUE);
+
+}
+
+reap()
+{
+    _t_free_list(&rlist);
+}
+
+/*
+ * runners:
+ *      Make all the awake monsters try to do something.
+ */
+
+runners(segments)
+int segments;    /* Number of segments since last called */
+{
+    register struct linked_list *item;
+    register struct thing *tp = NULL;
+    register int min_time = 20;     /* Minimum time until a monster can act */
+
+    /*
+     * loop thru the list of running (wandering) monsters and see what
+     * each one will do this time. 
+     *
+     * Note: the special case that one of this buggers kills another.
+     *       if this happens than we have to see if the monster killed
+     *       himself or someone else. In case its himself we have to get next
+     *       one immediately. If it wasn't we have to get next one at very
+     *       end in case he killed the next one.
+     */
+    for (item = mlist; item != NULL; item = item->l_next)
+    {
+        tp = THINGPTR(item);
+        turn_on(*tp, NEEDSTOACT);
+    }
+
+    for(;;)
+    {
+        for (item = mlist; item != NULL; item = item->l_next)
+        {
+            tp = THINGPTR(item);
+
+            if (on(*tp, NEEDSTOACT))
+                break;
+        }
+
+        if (item == NULL)
+            break;
+
+        turn_off(*tp, NEEDSTOACT);
+
+        /* If we are not awake, just skip us */
+
+        if (off(*tp, ISRUN) && off(*tp, ISHELD))
+            continue;
+
+        /* See if it's our turn */
+
+        tp->t_no_move -= segments;
+
+        if (tp->t_no_move > 0)
+        {
+            if (tp->t_no_move < min_time) min_time = tp->t_no_move;
+                continue;
+        }
+
+        /* If we were frozen, we're moving now */
+
+        if (tp->t_action == A_FREEZE)
+            tp->t_action = A_NIL;
+
+        if (on(*tp, ISHELD))
+        {
+            /* Make sure the action and using are nil */
+
+            tp->t_action = A_NIL;
+            tp->t_using = NULL;
+
+            /* Can we break free? */
+
+            if (rnd(tp->t_stats.s_lvl) > 11)
+            {
+                turn_off(*tp, ISHELD);
+
+                runto(tp, &hero);
+
+                if (cansee(tp->t_pos.y, tp->t_pos.x))
+                    msg("%s breaks free from the hold spell", 
+                        prname(monster_name(tp), TRUE));
+            }
+            else /* Too bad -- try again later */
+                tp->t_no_move = movement(tp);
+        }
+
+        /* Heal the creature if it's not in the middle of some action */
+
+        if (tp->t_action == A_NIL)
+           doctor(tp);
+
+        while (off(*tp, ISELSEWHERE) &&
+               off(*tp, ISDEAD) &&
+               tp->t_no_move <= 0 &&
+               off(*tp, ISHELD) &&
+               on(*tp, ISRUN)       )
+        {
+            /* Let's act (or choose an action if t_action = A_NIL) */
+
+            m_act(tp);
+        }
+
+        if ( off(*tp,ISELSEWHERE) && off(*tp,ISDEAD) )
+        {
+            if (tp->t_no_move < min_time)
+               min_time = tp->t_no_move;
+
+            if (tp->t_quiet < 0)
+               tp->t_quiet = 0;
+        }
+    }
+
+    return(min_time);
+}
+
+/*
+ * See if a monster has some magic it can use.  Return TRUE if so.
+ * Only care about relics and wands for now.
+ */
+bool
+m_use_pack(monster, defend_pos, dist, shoot_dir)
+register struct thing *monster;
+coord *defend_pos;
+register int dist;
+register coord *shoot_dir;
+{
+    register struct object *obj;
+    register struct linked_list *pitem, *relic, *stick;
+    register int units = -1;
+
+    relic = stick = NULL;
+
+    for (pitem=monster->t_pack; pitem; pitem=next(pitem)) {
+        obj = OBJPTR(pitem);
+        if (obj->o_flags & ISCURSED) continue;
+        if (obj->o_type == RELIC) {
+            switch (obj->o_which) {
+                case MING_STAFF:
+                    if (shoot_dir != NULL) {
+                        units = 2;      /* Use 2 time units */
+                        relic = pitem;
+                    }
+
+                when EMORI_CLOAK:
+                    if (obj->o_charges != 0     && 
+                        shoot_dir != NULL) {
+                            units = 2;  /* Use 2 time units */
+                            relic = pitem;
+                    }
+
+                when ASMO_ROD:
+                    /* The bolt must be able to reach the defendant */
+                    if (shoot_dir != NULL                       && 
+                        dist < BOLT_LENGTH * BOLT_LENGTH) {
+                        units = 2;      /* Use 2 time units */
+                        relic = pitem;
+                    }
+
+                when BRIAN_MANDOLIN:
+                    /* The defendant must be the player and within 4 spaces */
+                    if (ce(*defend_pos, hero)           && 
+                        dist < 25                       &&
+                        player.t_action != A_FREEZE) {
+                        units = 4;
+                        relic = pitem;
+                    }
+
+                when GERYON_HORN:
+                    /* The defendant must be the player and within 5 spaces */
+                    if (ce(*defend_pos, hero)                                &&
+                        dist < 25                                            &&
+                        (off(player,ISFLEE)|| player.t_dest!=&monster->t_pos)) {
+                        units = 3;
+                        relic = pitem;
+                    }
+            }
+        }
+        if (obj->o_type == STICK) {
+            if (obj->o_charges < 1) continue;
+            switch(obj->o_which) {
+                case WS_ELECT:
+                case WS_FIRE:
+                case WS_COLD:
+                    /* The bolt must be able to reach the defendant */
+                    if (shoot_dir != NULL                       && 
+                        dist < BOLT_LENGTH * BOLT_LENGTH) {
+                            units = 3;
+                            stick = pitem;
+                    }
+
+                when WS_MISSILE:
+                case WS_SLOW_M:
+                case WS_CONFMON:
+                case WS_PARALYZE:
+                case WS_MDEG:
+                case WS_FEAR:
+                    if (shoot_dir != NULL) {
+                        units = 3;
+                        stick = pitem;
+                    }
+                
+                otherwise:
+                    break;
+            }
+        }
+    }
+
+    /* use relics in preference to all others */
+    if (relic) debug("chance to use relic = %d%%", monster->t_artifact);
+    if (stick) debug("chance to use stick = %d%%", monster->t_wand);
+    if (relic && rnd(100) < monster->t_artifact)  {
+        monster->t_action = A_USERELIC;
+        pitem = relic;
+    }
+    else if (stick && rnd(100) < monster->t_wand) {
+        /*
+         * see if the monster will use the wand 
+         */
+        pitem = stick;
+        monster->t_action = A_USEWAND;
+    }
+    else {
+        return(FALSE);
+    }
+
+    monster->t_no_move = units * movement(monster);
+    monster->t_using = pitem;
+    monster->t_newpos = *shoot_dir;
+    return(TRUE);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xrogue/bolt.c	Tue Apr 21 08:55:20 2015 -0400
@@ -0,0 +1,401 @@
+/*
+    bolt.c  -  functions shooting an object across the room
+        
+    XRogue: Expeditions into the Dungeons of Doom
+    Copyright (C) 1991 Robert Pietkivitch
+    All rights reserved.
+    
+    Based on "Advanced Rogue"
+    Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka and AT&T
+    All rights reserved.
+
+    Based on "Rogue: Exploring the Dungeons of Doom"
+    Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
+    All rights reserved.
+    
+    See the file LICENSE.TXT for full copyright and licensing information.
+*/
+
+#include <curses.h>
+#include <ctype.h>
+#include "rogue.h"
+
+/*
+ * shoot_bolt fires a bolt from the given starting point in the
+ *            given direction
+ */
+
+shoot_bolt(shooter, start, dir, get_points, reason, name, damage)
+struct thing *shooter;
+coord start, dir;
+bool get_points;
+short reason;
+char *name;
+int damage;
+{
+    unsigned char dirch = 0, ch;
+    bool used, change, see_him;
+    short y, x, bounces;
+    coord pos;
+    struct linked_list *target=NULL;
+    struct {
+        coord place;
+        char oldch;
+    } spotpos[BOLT_LENGTH];
+
+    switch (dir.y + dir.x) {
+        case 0: dirch = '/';
+        when 1: case -1: dirch = (dir.y == 0 ? '-' : '|');
+        when 2: case -2: dirch = '\\';
+    }
+    pos.y = start.y + dir.y;
+    pos.x = start.x + dir.x;
+    used = FALSE;
+    change = FALSE;
+
+    bounces = 0;        /* No bounces yet */
+    nofont(cw);
+    for (y = 0; y < BOLT_LENGTH && !used; y++) {
+        ch = winat(pos.y, pos.x);
+        spotpos[y].place = pos;
+        spotpos[y].oldch = mvwinch(cw, pos.y, pos.x);
+
+        /* Are we at hero? */
+        if (ce(pos, hero)) goto at_hero;
+
+        switch (ch) {
+            case SECRETDOOR:
+            case VERTWALL:
+            case HORZWALL:
+            case ' ':
+                if (dirch == '-' || dirch == '|') {
+                    dir.y = -dir.y;
+                    dir.x = -dir.x;
+                }
+                else {
+                    unsigned char chx = mvinch(pos.y-dir.y, pos.x),
+                         chy = mvinch(pos.y, pos.x-dir.x);
+                    bool anychange = FALSE; /* Did we change anthing */
+
+                    if (chy == WALL || chy == SECRETDOOR ||
+                        chy == HORZWALL || chy == VERTWALL) {
+                        dir.y = -dir.y;
+                        change ^= TRUE; /* Change at least one direction */
+                        anychange = TRUE;
+                    }
+                    if (chx == WALL || chx == SECRETDOOR ||
+                        chx == HORZWALL || chx == VERTWALL) {
+                        dir.x = -dir.x;
+                        change ^= TRUE; /* Change at least one direction */
+                        anychange = TRUE;
+                    }
+
+                    /* If we didn't make any change, make both changes */
+                    if (!anychange) {
+                        dir.x = -dir.x;
+                        dir.y = -dir.y;
+                    }
+                }
+
+                /* Do we change how the bolt looks? */
+                if (change) {
+                    change = FALSE;
+                    if (dirch == '\\') dirch = '/';
+                    else if (dirch == '/') dirch = '\\';
+                }
+
+                y--;    /* The bounce doesn't count as using up the bolt */
+
+                /* Make sure we aren't in an infinite bounce */
+                if (++bounces > BOLT_LENGTH) used = TRUE;
+                msg("The %s bounces", name);
+                break;
+            default:
+                if (isalpha(ch)) {
+                    register struct linked_list *item;
+                    struct thing *tp;
+                    register char *mname;
+                    bool see_monster = cansee(pos.y, pos.x);
+
+                    item = find_mons(unc(pos));
+                    assert(item != NULL);
+                    tp = THINGPTR(item);
+                    mname = monster_name(tp);
+
+                    /*
+                     * If our prey shot this, let's record the fact that
+                     * he can shoot, regardless of whether he hits us.
+                     */
+                    if (tp->t_dest != NULL && ce(*tp->t_dest, shooter->t_pos)) 
+                        tp->t_wasshot = TRUE;
+
+                    if (!save(VS_BREATH, tp, -(shooter->t_stats.s_lvl/10))) {
+                        if (see_monster) {
+                            if (on(*tp, ISDISGUISE) &&
+                                (tp->t_type != tp->t_disguise)) {
+                                msg("Wait! That's a %s!", mname);
+                                turn_off(*tp, ISDISGUISE);
+                            }
+
+                            turn_off(*tp, CANSURPRISE);
+                            msg("The %s hits %s", name, prname(mname, FALSE));
+                        }
+
+                        /* Should we start to chase the shooter? */
+                        if (shooter != &player                  &&
+                            shooter != tp                       &&
+                            shooter->t_index != tp->t_index     &&
+                            (tp->t_dest == NULL || rnd(100) < 25)) {
+                            /*
+                             * If we're intelligent enough to realize that this
+                             * is a friendly monster, we will attack the hero
+                             * instead.
+                             */
+                            if (on(*shooter, ISFRIENDLY) &&
+                                 roll(3,6) < tp->t_stats.s_intel)
+                                 runto(tp, &hero);
+
+                            /* Otherwise, let's chase the monster */
+                            else runto(tp, &shooter->t_pos);
+                        }
+                        else if (shooter == &player) {
+                            runto(tp, &hero);
+
+                            /*
+                             * If the player shot a charmed monster, it may
+                             * not like being shot at.
+                             */
+                            if (on(*tp, ISCHARMED) && save(VS_MAGIC, tp, 0)) {
+                                msg("The eyes of %s turn clear.", 
+                                    prname(mname, FALSE));
+                                turn_off(*tp, ISCHARMED);
+                                mname = monster_name(tp);
+                            }
+                        }
+
+                        /*
+                         * Let the defender know that the attacker has
+                         * missiles!
+                         */
+                        if (ce(*tp->t_dest, shooter->t_pos))
+                            tp->t_wasshot = TRUE;
+
+                        used = TRUE;
+
+                        /* Hit the monster -- does it do anything? */
+                        if ((EQUAL(name,"ice")           && on(*tp, NOCOLD))  ||
+                            (EQUAL(name,"flame")         && on(*tp, NOFIRE))  ||
+                            (EQUAL(name,"acid")          && on(*tp, NOACID))  ||
+                            (EQUAL(name,"lightning bolt")&& on(*tp,NOBOLT))   ||
+                            (EQUAL(name,"nerve gas")     &&on(*tp,NOPARALYZE))||
+                            (EQUAL(name,"sleeping gas")  &&
+                             (on(*tp, NOSLEEP) || on(*tp, ISUNDEAD)))         ||
+                            (EQUAL(name,"slow gas")      && on(*tp,NOSLOW))   ||
+                            (EQUAL(name,"fear gas")      && on(*tp,NOFEAR))   ||
+                            (EQUAL(name,"confusion gas") && on(*tp,ISCLEAR))  ||
+                            (EQUAL(name,"chlorine gas")  && on(*tp,NOGAS))) {
+                            if (see_monster)
+                                msg("The %s has no effect on %s.",
+                                        name, prname(mname, FALSE));
+                        }
+
+                        else {
+                            see_him = !invisible(tp);
+                           
+                            /* Did a spell get disrupted? */
+                            dsrpt_monster(tp, FALSE, see_him);
+
+                            /* 
+                             * Check for gas with special effects 
+                             */
+                            if (EQUAL(name, "nerve gas")) {
+                                tp->t_no_move = movement(tp) * FREEZETIME;
+                                tp->t_action = A_FREEZE;
+                            }
+                            else if (EQUAL(name, "sleeping gas")) {
+                                tp->t_no_move = movement(tp) * SLEEPTIME;
+                                tp->t_action = A_FREEZE;
+                            }
+                            else if (EQUAL(name, "slow gas")) {
+                                if (on(*tp, ISHASTE))
+                                    turn_off(*tp, ISHASTE);
+                                else
+                                    turn_on(*tp, ISSLOW);
+                            }
+                            else if (EQUAL(name, "fear gas")) {
+                                turn_on(*tp, ISFLEE);
+                                tp->t_dest = &hero;
+
+                                /* It is okay to turn tail */
+                                tp->t_oldpos = tp->t_pos;
+                            }
+                            else if (EQUAL(name, "confusion gas")) {
+                                turn_on(*tp, ISHUH);
+                                tp->t_dest = &hero;
+                            }
+                            else if ((EQUAL(name, "lightning bolt")) &&
+                                     on(*tp, BOLTDIVIDE)) {
+                                    if (creat_mons(tp, tp->t_index, FALSE)) {
+                                      if (see_monster)
+                                       msg("The %s divides %s.",
+                                           name,prname(mname, FALSE));
+                                      light(&hero);
+                                    }
+                                    else if (see_monster)
+                                        msg("The %s has no effect on %s.",
+                                            name, prname(mname, FALSE));
+                            }
+                            else {
+                                if (save(VS_BREATH, tp,
+                                         -(shooter->t_stats.s_lvl/10)))
+                                    damage /= 2;
+
+                                /* The poor fellow got killed! */
+                                if ((tp->t_stats.s_hpt -= damage) <= 0) {
+                                    if (see_monster)
+                                        msg("The %s kills %s", 
+                                            name, prname(mname, FALSE));
+                                    else
+                                     msg("You hear a faint groan in the distance");
+                                    /*
+                                     * Instead of calling killed() here, we
+                                     * will record that the monster was killed
+                                     * and call it at the end of the routine,
+                                     * after we restore what was under the bolt.
+                                     * We have to do this because in the case
+                                     * of a bolt that first misses the monster
+                                     * and then gets it on the bounce.  If we
+                                     * call killed here, the 'missed' space in
+                                     * spotpos puts the monster back on the
+                                     * screen
+                                     */
+                                    target = item;
+                                }
+                                else {  /* Not dead, so just scream */
+                                     if (!see_monster)
+                                       msg("You hear a scream in the distance");
+                                }
+                            }
+                        }
+                    }
+                    else if (isalpha(show(pos.y, pos.x))) {
+                        if (see_monster) {
+                            if (terse)
+                                msg("%s misses", name);
+                            else
+                                msg("The %s whizzes past %s",
+                                            name, prname(mname, FALSE));
+                        }
+                        if (get_points) runto(tp, &hero);
+                    }
+                }
+                else if (pos.y == hero.y && pos.x == hero.x) {
+at_hero:            if (!save(VS_BREATH, &player,
+                                -(shooter->t_stats.s_lvl/10))){
+                        if (terse)
+                            msg("The %s hits you", name);
+                        else
+                            msg("You are hit by the %s", name);
+                        used = TRUE;
+
+                        /* 
+                         * The Amulet of Yendor protects against all "breath" 
+                         *
+                         * The following two if statements could be combined 
+                         * into one, but it makes the compiler barf, so split 
+                         * it up
+                         */
+                        if (cur_relic[YENDOR_AMULET]                        ||
+                            (EQUAL(name,"chlorine gas")&&on(player, NOGAS)) ||
+                            (EQUAL(name,"acid")&&on(player, NOACID))        ||
+                            (EQUAL(name,"sleeping gas")&&ISWEARING(R_ALERT))){
+                             msg("The %s has no effect", name);
+                        }
+                        else if((EQUAL(name, "flame") && on(player, NOFIRE)) ||
+                                (EQUAL(name, "ice")   && on(player, NOCOLD)) ||
+                                (EQUAL(name,"lightning bolt")&& 
+                                                         on(player,NOBOLT))  ||
+                                (EQUAL(name,"fear gas")&&ISWEARING(R_HEROISM))){
+                             msg("The %s has no effect", name);
+                        }
+
+                        else {
+                            dsrpt_player();
+
+                            /* 
+                             * Check for gas with special effects 
+                             */
+                            if (EQUAL(name, "nerve gas")) {
+                                msg("The nerve gas paralyzes you.");
+                                player.t_no_move +=
+                                        movement(&player) * FREEZETIME;
+                                player.t_action = A_FREEZE;
+                            }
+                            else if (EQUAL(name, "sleeping gas")) {
+                                msg("The sleeping gas puts you to sleep.");
+                                player.t_no_move +=
+                                        movement(&player) * SLEEPTIME;
+                                player.t_action = A_FREEZE;
+                            }
+                            else if (EQUAL(name, "confusion gas")) {
+                                if (off(player, ISCLEAR)) {
+                                    if (on(player, ISHUH))
+                                        lengthen(unconfuse,
+                                                 rnd(20)+HUHDURATION);
+                                    else {
+                                        turn_on(player, ISHUH);
+                                        fuse(unconfuse, (VOID *)NULL,
+                                             rnd(20)+HUHDURATION, AFTER);
+                                        msg("The confusion gas has confused you.");
+                                    }
+                                }
+                                else msg("You feel dizzy for a moment, but it quickly passes.");
+                            }
+                            else if (EQUAL(name, "slow gas")) {
+                                add_slow();
+                            }
+                            else if (EQUAL(name, "fear gas")) {
+                                turn_on(player, ISFLEE);
+                                player.t_dest = &shooter->t_pos;
+                                msg("The fear gas terrifies you.");
+                            }
+                            else {
+                                if (EQUAL(name, "acid")                 &&
+                                    cur_armor != NULL                   &&
+                                    !(cur_armor->o_flags & ISPROT)      &&
+                                    !save(VS_BREATH, &player, -2)       &&
+                                    cur_armor->o_ac < pstats.s_arm+1) {
+                                       msg("Your armor corrodes from the acid");
+                                       cur_armor->o_ac++;
+                                }
+                                if (save(VS_BREATH, &player,
+                                         -(shooter->t_stats.s_lvl/10))  &&
+                                         off(player, NOACID))
+                                    damage /= 2;
+                                if ((pstats.s_hpt -= damage) <= 0) 
+                                    death(reason);
+                            }
+                        }
+                    }
+                    else
+                        msg("The %s whizzes by you", name);
+                }
+
+                mvwaddch(cw, pos.y, pos.x, dirch);
+                draw(cw);
+        }
+
+        pos.y += dir.y;
+        pos.x += dir.x;
+    }
+
+    /* Restore what was under the bolt */
+    newfont(cw);
+    for (x = y - 1; x >= 0; x--)
+        mvwaddch(cw, spotpos[x].place.y, spotpos[x].place.x, spotpos[x].oldch);
+
+    /* If we killed something, do so now.  This will also blank the monster. */
+    if (target) killed(target, FALSE, get_points, TRUE);
+    return;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xrogue/chase.c	Tue Apr 21 08:55:20 2015 -0400
@@ -0,0 +1,936 @@
+/*
+    chase.c  -  Code for one object to chase another
+
+    XRogue: Expeditions into the Dungeons of Doom
+    Copyright (C) 1991 Robert Pietkivitch
+    All rights reserved.
+    
+    Based on "Advanced Rogue"
+    Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka and AT&T
+    All rights reserved.
+
+    Based on "Rogue: Exploring the Dungeons of Doom"
+    Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
+    All rights reserved.
+    
+    See the file LICENSE.TXT for full copyright and licensing information.
+*/
+
+#include <ctype.h>
+#include <curses.h>
+#include <limits.h>
+#include "rogue.h"
+
+/*
+ * Canblink checks if the monster can teleport (blink).  If so, it will
+ * try to blink the monster next to the player.
+ */
+
+bool
+can_blink(tp)
+register struct thing *tp;
+{
+    register int y, x, index=9;
+    coord tryp; /* To hold the coordinates for use in diag_ok */
+    bool spots[9], found_one=FALSE;
+
+    /*
+     * First, can the monster even blink?  And if so, there is only a 50%
+     * chance that it will do so.  And it won't blink if it is running or
+     * held.
+     */
+    if (off(*tp, CANBLINK) || (on(*tp, ISHELD)) ||
+        on(*tp, ISFLEE) ||
+        tp->t_action == A_FREEZE ||
+        (rnd(12) < 6)) return(FALSE);
+
+
+    /* Initialize the spots as illegal */
+    do {
+        spots[--index] = FALSE;
+    } while (index > 0);
+
+    /* Find a suitable spot next to the player */
+    for (y=hero.y-1; y<hero.y+2; y++)
+        for (x=hero.x-1; x<hero.x+2; x++, index++) {
+            /* Make sure x coordinate is in range and that we are
+             * not at the player's position
+             */
+            if (x<0 || x >= cols || index == 4) continue;
+
+            /* Is it OK to move there? */
+            if (step_ok(y, x, NOMONST, tp) &&
+                (!isatrap(mvwinch(cw, y, x)) ||
+                  rnd(10) >= tp->t_stats.s_intel ||
+                  on(*tp, ISFLY))) {
+                /* OK, we can go here.  But don't go there if
+                 * monster can't get at player from there
+                 */
+                tryp.y = y;
+                tryp.x = x;
+                if (diag_ok(&tryp, &hero, tp)) {
+                    spots[index] = TRUE;
+                    found_one = TRUE;
+                }
+            }
+        }
+
+    /* If we found one, go to it */
+    if (found_one) {
+        unsigned char rch;       /* What's really where the creatures moves to */
+
+        /* Find a legal spot */
+        while (spots[index=rnd(9)] == FALSE) continue;
+
+        /* Get the coordinates */
+        y = hero.y + (index/3) - 1;
+        x = hero.x + (index % 3) - 1;
+
+        /* Move the monster from the old space */
+        mvwaddch(cw, tp->t_pos.y, tp->t_pos.x, tp->t_oldch);
+
+        /* Move it to the new space */
+        tp->t_oldch = mvwinch(cw, y, x);
+
+        /* Display the creature if our hero can see it */
+        if (cansee(y, x) &&
+            off(*tp, ISINWALL) &&
+            !invisible(tp))
+            mvwaddch(cw, y, x, tp->t_type);
+
+        /* Fix the monster window */
+        mvwaddch(mw, tp->t_pos.y, tp->t_pos.x, ' '); /* Clear old position */
+        mvwaddch(mw, y, x, tp->t_type);
+
+        /* Record the new position */
+        tp->t_pos.y = y;
+        tp->t_pos.x = x;
+
+        /* If the monster is on a trap, trap it */
+        rch = mvinch(y, x);
+        if (isatrap(rch)) {
+            if (cansee(y, x)) tp->t_oldch = rch;
+            be_trapped(tp, &(tp->t_pos));
+        }
+    }
+
+    return(found_one);
+}
+
+/* 
+ * Can_shoot determines if the monster (er) has a direct line of shot 
+ * at the prey (ee).  If so, it returns the direction in which to shoot.
+ */
+
+int
+can_shoot(er, ee, shoot_dir)
+register coord *er, *ee, *shoot_dir;
+{
+    /* 
+     * They must be in the same room or very close (at door)
+     */
+    if (roomin(er) != roomin(ee) && DISTANCE(er->y,er->x,ee->y,ee->x) > 1)
+    {
+        shoot_dir->x = shoot_dir->y = 0;
+        return(-1);
+    }
+
+    /* Do we have a straight shot? */
+    if (!straight_shot(er->y, er->x, ee->y, ee->x, shoot_dir)) 
+    {
+        shoot_dir->x = shoot_dir->y = 0;
+        return(-2);
+    }
+    else 
+        return(0);
+}
+
+/*
+ * chase:
+ *      Find the spot for the chaser(er) to move closer to the
+ *      chasee(ee).  Rer is the room of the chaser, and ree is the
+ *      room of the creature being chased (chasee).
+ */
+
+chase(tp, ee, rer, ree, flee)
+register struct thing *tp;
+register coord *ee;
+register struct room *rer, *ree;
+bool flee; /* True if destination (ee) is player and monster is running away
+            * or the player is in a wall and the monster can't get to it
+            */
+{
+    int dist, thisdist, monst_dist = INT_MAX; 
+    register coord *er = &tp->t_pos; 
+    struct thing *prey;                 /* What we are chasing */
+    coord ch_ret;                       /* Where chasing takes you */
+    unsigned char ch, mch;
+    bool next_player = FALSE;
+
+    /* 
+     * set the distance from the chas(er) to the chas(ee) here and then
+     * we won't have to reset it unless the chas(er) moves (instead of shoots)
+     */
+    dist = DISTANCE(er->y, er->x, ee->y, ee->x);
+
+    /*
+     * See if our destination is a monster or player.  If so, make "prey" point
+     * to it.
+     */
+    if (ce(hero, *ee)) prey = &player;  /* Is it the player? */
+    else if (tp->t_dest && ce(*(tp->t_dest), *ee)) {    /* Is it a monster? */
+        struct linked_list *item;
+
+        /* What is the monster we're chasing? */
+        item = find_mons(ee->y, ee->x);
+        if (item != NULL) prey = THINGPTR(item);
+        else prey = NULL;
+    }
+    else prey = NULL;
+
+    /* We will use at least one movement period */
+    tp->t_no_move = movement(tp);
+    if (on(*tp, ISFLY)) /* If the creature is flying, speed it up */
+        tp->t_no_move /= 2;
+
+    /*
+     * If the thing is confused or it can't see the player,
+     * let it move randomly. 
+     */
+    if ((on(*tp, ISHUH) && rnd(10) < 8) ||
+        (prey && on(*prey, ISINVIS) && off(*tp, CANSEE))) { /* invisible prey */
+        /*
+         * get a valid random move
+         */
+        tp->t_newpos = rndmove(tp);
+        dist = DISTANCE(tp->t_newpos.y, tp->t_newpos.x, ee->y, ee->x);
+    }
+
+    /*
+     * Otherwise, find the empty spot next to the chaser that is
+     * closest to the chasee.
+     */
+    else {
+        register int ey, ex, x, y;
+        int dist_to_old = INT_MIN; /* Dist from goal to old position */
+
+        /*
+         * This will eventually hold where we move to get closer
+         * If we can't find an empty spot, we stay where we are.
+         */
+        dist = flee ? 0 : INT_MAX;
+        ch_ret = *er;
+
+        /* Are we at our goal already? */
+        if (!flee && ce(ch_ret, *ee)) {
+            turn_off(*tp, ISRUN);       /* So stop running! */
+            return;
+        }
+
+        ey = er->y + 1;
+        ex = er->x + 1;
+
+        /* Check all possible moves */
+        for (x = er->x - 1; x <= ex; x++) {
+            if (x < 0 || x >= cols) /* Don't try off the board */
+                continue;
+            for (y = er->y - 1; y <= ey; y++) {
+                coord tryp;
+
+                if ((y < 1) || (y >= lines - 2)) /* Don't try off the board */
+                    continue;
+
+                /* Don't try the player if not going after the player */
+                if ((flee || !ce(hero, *ee) || on(*tp, ISFRIENDLY)) &&
+                    x == hero.x && y == hero.y) {
+                    next_player = TRUE;
+                    continue;
+                }
+
+                tryp.x = x;
+                tryp.y = y;
+
+                /* Is there a monster on this spot closer to our goal?
+                 * Don't look in our spot or where we were.
+                 */
+                if (!ce(tryp, *er) && !ce(tryp, tp->t_oldpos) &&
+                    isalpha(mch = mvwinch(mw, y, x))) {
+                    int test_dist;
+
+                    test_dist = DISTANCE(y, x, ee->y, ee->x);
+                    if (test_dist <= 25 &&   /* Let's be fairly close */
+                        test_dist < monst_dist) {
+                        /* Could we really move there? */
+                        mvwaddch(mw, y, x, ' '); /* Temporarily blank monst */
+                        if (diag_ok(er, &tryp, tp)) monst_dist = test_dist;
+                        mvwaddch(mw, y, x, mch); /* Restore monster */
+                    }
+                }
+
+                /* Can we move onto the spot? */        
+                if (!diag_ok(er, &tryp, tp)) continue;
+
+                ch = mvwinch(cw, y, x); /* Screen character */
+
+                /*
+                 * Stepping on player is NOT okay if we are fleeing.
+                 * If we are friendly to the player and there is a monster
+                 * in the way that is not of our race, it is okay to move
+                 * there.
+                 */
+                if (step_ok(y, x, FIGHTOK, tp) &&
+                    (off(*tp, ISFLEE) || ch != PLAYER))
+                {
+                    /*
+                     * If it is a trap, an intelligent monster may not
+                     * step on it (unless our hero is on top!)
+                     */
+                    if ((isatrap(ch))                   && 
+                        (rnd(10) < tp->t_stats.s_intel) &&
+                        (!on(*tp, ISFLY))               &&
+                        (y != hero.y || x != hero.x)) 
+                            continue;
+
+                    /*
+                     * OK -- this place counts
+                     */
+                    thisdist = DISTANCE(y, x, ee->y, ee->x);
+
+                    /* Adjust distance if we are being shot at */
+                    if (tp->t_wasshot && tp->t_stats.s_intel > 5 &&
+                        prey != NULL) {
+                        /* Move out of line of sight */
+                        if (straight_shot(tryp.y, tryp.x, ee->y, ee->x, (coord *)NULL)) {
+                            if (flee) thisdist -= SHOTPENALTY;
+                            else thisdist += SHOTPENALTY;
+                        }
+
+                        /* But do we want to leave the room? */
+                        else if (rer && rer == ree && ch == DOOR)
+                            thisdist += DOORPENALTY;
+                    }
+
+                    /* Don't move to the last position if we can help it
+                     * (unless out prey just moved there)
+                     */
+                    if (ce(tryp, tp->t_oldpos) && (flee || !ce(tryp, hero)))
+                        dist_to_old = thisdist;
+
+                    else if ((flee && (thisdist > dist)) ||
+                        (!flee && (thisdist < dist)))
+                    {
+                        ch_ret = tryp;
+                        dist = thisdist;
+                    }
+                }
+            }
+        }
+
+        /* If we aren't trying to get the player, but he is in our way,
+         * hit him (unless we have been turned or are friendly).  next_player
+         * being TRUE -> we are next to the player but don't want to hit him.
+         *
+         * If we are friendly to the player, following him, and standing next
+         * to him, we will try to help him out in battle.
+         */
+        if (next_player && off(*tp, WASTURNED)) {
+            if (off(*tp, ISFRIENDLY) &&
+                ((flee && ce(ch_ret, *er)) ||
+                 (!flee && DISTANCE(er->y, er->x, ee->y, ee->x) < dist)) &&
+                step_ok(tp->t_dest->y, tp->t_dest->x, NOMONST, tp)) {
+                /* Okay to hit player */
+                debug("Switching to hero.");
+                tp->t_newpos = hero;
+                tp->t_action = A_MOVE;
+                return;
+            }
+            else if (on(*tp, ISFRIENDLY) && !flee && ce(*ee, hero)) {
+                /*
+                 * Look all around the player.  If there is a fightable
+                 * creature next to both of us, hit it.  Otherwise, if
+                 * there is a fightable creature next to the player, try
+                 * to move next to it.
+                 */
+                dist = INT_MAX;
+                for (x = hero.x - 1; x <= hero.x + 1; x++) {
+                    if (x < 0 || x >= cols) /* Don't try off the board */
+                        continue;
+                    for (y = hero.y - 1; y <= hero.y + 1; y++) {
+                        if ((y < 1) || (y >= lines - 2)) /* Stay on the board */
+                            continue;
+
+                        /* Is there a fightable monster here? */
+                        if (isalpha(mvwinch(mw, y, x)) &&
+                            step_ok(y, x, FIGHTOK, tp) &&
+                            off(*tp, ISSTONE)) {
+                            thisdist = DISTANCE(er->y, er->x, y, x);
+                            if (thisdist < dist) {
+                                dist = thisdist;
+                                ch_ret.y = y;
+                                ch_ret.x = x;
+                            }
+                        }
+                    }
+                }
+
+                /* Are we next to a bad guy? */
+                if (dist <= 2) {        /* Get him! */
+                    tp->t_newpos = ch_ret;
+                    tp->t_action = A_MOVE;
+                }
+
+                /* Try to move to the bad guy */
+                else if (dist < INT_MAX)
+                    chase(tp, &ch_ret,
+                          roomin(&tp->t_pos), roomin(&ch_ret), FALSE);
+
+                else tp->t_action = A_NIL;
+
+                return;
+            }
+        }
+
+        /*
+         * If we have decided that we can move onto a monster (we are
+         * friendly to the player, go to it.
+         */
+        if (!ce(ch_ret, *er) && isalpha(mvwinch(mw, ch_ret.y, ch_ret.x))) {
+            debug("Attack monster");
+            tp->t_newpos = ch_ret;
+            tp->t_action = A_MOVE;
+            return;
+        }
+
+        /* If we can't get closer to the player (if that's our goal)
+         * because other monsters are in the way, just stay put
+         */
+        if (!flee && ce(hero, *ee) && monst_dist < INT_MAX &&
+            DISTANCE(er->y, er->x, hero.y, hero.x) < dist) {
+                tp->t_action = A_NIL; /* do nothing for awhile */
+                return;
+        }
+
+        /* Do we want to go back to the last position? */
+        else if (dist_to_old != INT_MIN &&      /* It is possible to move back */
+            ((flee && dist == 0) ||     /* No other possible moves */
+             (!flee && dist == INT_MAX))) {
+            /* Do we move back or just stay put (default)? */
+            dist = DISTANCE(er->y, er->x, ee->y, ee->x); /* Current distance */
+            if (!flee || (flee && (dist_to_old > dist))) ch_ret = tp->t_oldpos;
+        }
+
+        /* Record the new destination */
+        tp->t_newpos = ch_ret;
+    }
+
+    /*
+     * Do we want to fight or move?  If our selected destination (ch_ret)
+     * is our hero, then we want to fight.  Otherwise, we want to move.
+     */
+    if (ce(tp->t_newpos, hero)) {
+        /* Fight! (or sell) */
+        if (on(*tp, CANSELL)) {
+            tp->t_action = A_SELL;
+            tp->t_no_move += movement(tp); /* takes a little time to sell */
+        }
+        else {
+            tp->t_action = A_ATTACK;
+
+            /*
+             * Try to find a weapon to wield.  Wield_weap will return a
+             * projector if weapon is a projectile (eg. bow for arrow).
+             * If weapon is NULL (the case here), it will try to find
+             * a suitable weapon.
+             *
+             *          Add in rest of time. Fight is 
+             *          movement() + weap_move() + FIGHTBASE
+             */
+            tp->t_using = wield_weap((struct object *)NULL, tp);
+            if (tp->t_using == NULL)
+                tp->t_no_move += weap_move(tp, (struct object *)NULL);
+            else
+                tp->t_no_move += weap_move(tp, OBJPTR(tp->t_using));
+
+            if (on(*tp, ISHASTE))
+                    tp->t_no_move += FIGHTBASE/2;
+            else if (on(*tp, ISSLOW))
+                    tp->t_no_move += FIGHTBASE*2;
+            else
+                    tp->t_no_move += FIGHTBASE;
+        }
+    }
+    else {
+        /* Move */
+        tp->t_action = A_MOVE;
+
+        /*
+         * Check if the creature is not next to the player.  If it
+         * is not and has held or suffocated the player, then stop it!
+         * Note that this code should more appropriately appear in
+         * the area that actually moves the monster, but for now it
+         * is okay here because the player can't move while held or
+         * suffocating.
+         */
+        if (dist > 2) {
+            if (on(*tp, DIDHOLD)) {
+                 turn_off(*tp, DIDHOLD);
+                 turn_on(*tp, CANHOLD);
+                 if (--hold_count == 0) 
+                     turn_off(player, ISHELD);
+            }
+
+            /* If monster was suffocating, stop it */
+            if (on(*tp, DIDSUFFOCATE)) {
+                turn_off(*tp, DIDSUFFOCATE);
+                turn_on(*tp, CANSUFFOCATE);
+                extinguish(suffocate);
+                msg("You can breathe again.....Whew!");
+            }
+        }
+    }
+}
+
+/*
+ * do_chase:
+ *      Make one thing chase another.
+ */
+
+do_chase(th)
+register struct thing *th;
+{
+    register struct room *orig_rer,     /* Original room of chaser */
+                         *new_room;     /* new room of monster */
+    unsigned char floor, rch, sch;
+    coord old_pos,                      /* Old position of monster */
+          ch_ret;                       /* Where we want to go */
+
+    if (on(*th, NOMOVE)) return;
+
+    ch_ret = th->t_newpos;      /* Record our desired new position */
+
+    /*
+     * Make sure we have an open spot (no other monster's gotten in our way,
+     * someone didn't just drop a scare monster there, our prey didn't just
+     * get there, etc.)
+     */
+    if (!step_ok(th->t_newpos.y, th->t_newpos.x, FIGHTOK, th)) {
+        /*
+         * Most monsters get upset now.  Guardians are all friends,
+         * and we don't want to see 50 messages in a row!
+         */
+        if (th->t_stats.s_intel > 4 &&
+            off(*th, ISUNDEAD)      &&
+            off(*th, ISGUARDIAN)    &&
+            off(*th, AREMANY)       &&
+            off(*th, ISHUH)         &&
+            off(*th, ISCHARMED)     &&
+            off(player, ISBLIND)    &&
+            cansee(unc(th->t_pos))  &&
+        !invisible(th) && (rnd(15) < 5)) {
+            switch (rnd(10)) {
+              case 0: case 1:
+            msg("%s lashes out at you! ",prname(monster_name(th),TRUE));
+          when 2: case 3:
+            msg("%s scrambles around. ",prname(monster_name(th), TRUE));
+                  otherwise:
+            msg("%s motions angrily. ", prname(monster_name(th), TRUE));
+            }
+    }
+        return;
+    }
+    else if (ce(th->t_newpos, hero) ||  /* Player just got in our way */
+             isalpha(mvwinch(mw, th->t_newpos.y, th->t_newpos.x))) {
+        bool fightplayer = ce(th->t_newpos, hero);
+
+        /* If we were turned or are friendly, we just have to sit here! */
+        if (fightplayer && (on(*th, WASTURNED) || on(*th, ISFRIENDLY))) return;
+
+        /* Do we want to sell something? */
+        if (fightplayer && on(*th, CANSELL)) {
+            th->t_action = A_SELL;
+            th->t_no_move += movement(th); /* takes a little time to sell */
+            return;
+        }
+
+        /* Let's hit him */
+        th->t_action = A_ATTACK;
+
+        /*
+         * Try to find a weapon to wield.  Wield_weap will return a
+         * projector if weapon is a projectile (eg. bow for arrow).
+         * If weapon is NULL (the case here), it will try to find
+         * a suitable weapon.
+         */
+        th->t_using = wield_weap((struct object *)NULL, th);
+        /*
+         * add in rest of time
+         */
+        if (th->t_using == NULL)
+            th->t_no_move += weap_move(th, (struct object *)NULL);
+        else
+            th->t_no_move += weap_move(th, OBJPTR(th->t_using));
+        if (on(*th, ISHASTE))
+                th->t_no_move += FIGHTBASE/2;
+        else if (on(*th, ISSLOW))
+                th->t_no_move += FIGHTBASE*2;
+        else
+                th->t_no_move += FIGHTBASE;
+        return;
+    }
+
+    /*
+     * Blank out the old position and record the new position --
+     * the blanking must be done first in case the positions are the same.
+     */
+    mvwaddch(mw, th->t_pos.y, th->t_pos.x, ' ');
+    mvwaddch(mw, ch_ret.y, ch_ret.x, th->t_type);
+
+    /* Get new and old rooms of monster */
+    new_room = roomin(&ch_ret);
+    orig_rer = roomin(&th->t_pos);
+
+    /* Store the critter's old position and update the current one */
+    old_pos = th->t_pos;
+    th->t_pos = ch_ret;
+    floor = (roomin(&ch_ret) == NULL) ? PASSAGE : FLOOR;
+
+    /* If we have a scavenger, it can pick something up */
+    if (off(*th, ISGUARDIAN)) {
+        register struct linked_list *n_item, *o_item;
+        register int item_count = 0;
+        bool want_something = FALSE;
+
+        while ((n_item = find_obj(ch_ret.y, ch_ret.x)) != NULL) {
+            register struct object *n_obj, *o_obj;
+            bool wants_it;
+
+            /* Does this monster want anything? */
+            if (want_something == FALSE) {
+                if (on(*th, ISSCAVENGE)  || on(*th, CARRYFOOD)   ||
+                    on(*th, CARRYGOLD)   || on(*th, CARRYSCROLL) ||
+                    on(*th, CARRYPOTION) || on(*th, CARRYRING)   ||
+                    on(*th, CARRYSTICK)  || on(*th, CARRYMISC)   ||
+                    on(*th, CARRYWEAPON) || on(*th, CARRYARMOR)  ||
+                    on(*th, CARRYDAGGER))  {
+                        want_something = TRUE;
+
+                        /*
+                         * Blank the area.  We have to do it only before the
+                         * first item in case an item gets dropped in same
+                         * place.  We don't want to blank it out after it get
+                         * dropped.
+                         */
+                        mvaddch(ch_ret.y, ch_ret.x, floor);
+
+                        /* Were we specifically after something here? */
+                        if (ce(*th->t_dest, ch_ret)) {
+                            /* If we're mean, we go after the hero */
+                            if (on(*th, ISMEAN)) runto(th, &hero);
+
+                            /* Otherwise just go back to sleep */
+                            else {
+                                turn_off(*th, ISRUN);
+                                th->t_dest = NULL;
+                            }
+                        }
+                }
+                else break;
+            }
+
+            item_count++;       /* Count the number of items */
+
+            /*
+             * see if he's got one of this group already
+             */
+            o_item = NULL;
+            n_obj = OBJPTR(n_item);
+            detach(lvl_obj, n_item);
+
+            /* See if he wants it */
+            if (n_obj->o_type == SCROLL && n_obj->o_which == S_SCARE &&
+                th->t_stats.s_intel < 16)
+                wants_it = FALSE; /* Most monsters don't want a scare monster */
+            else if (on(*th, ISSCAVENGE)) wants_it = TRUE;
+            else {
+                wants_it = FALSE;       /* Default case */
+                switch (n_obj->o_type) {
+                    case FOOD:  if(on(*th, CARRYFOOD))   wants_it = TRUE;
+                    when GOLD:  if(on(*th, CARRYGOLD))   wants_it = TRUE;
+                    when SCROLL:if(on(*th, CARRYSCROLL)) wants_it = TRUE;
+                    when POTION:if(on(*th, CARRYPOTION)) wants_it = TRUE;
+                    when RING:  if(on(*th, CARRYRING))   wants_it = TRUE;
+                    when STICK: if(on(*th, CARRYSTICK))  wants_it = TRUE;
+                    when MM:    if(on(*th, CARRYMISC))   wants_it = TRUE;
+                    when ARMOR: if(on(*th, CARRYARMOR))  wants_it = TRUE;
+                    when WEAPON:if(on(*th, CARRYWEAPON) ||
+                                  (on(*th,CARRYDAGGER)&&n_obj->o_which==DAGGER))
+                                        wants_it = TRUE;
+                }
+            }
+            /*
+             * The quartermaster doesn't sell cursed stuff so he won't
+             * pick it up
+             */
+            if (on(*th, CANSELL) && (n_obj->o_flags & ISCURSED))
+                wants_it = FALSE;
+
+            /* If he doesn't want it, throw it away */
+            if (wants_it == FALSE) {
+                fall(n_item, FALSE);
+                continue;
+            }
+
+            /* Otherwise, let's pick it up */
+            if (n_obj->o_group) {
+                for(o_item = th->t_pack; o_item != NULL; o_item = next(o_item)){
+                    o_obj = OBJPTR(o_item);
+                    if (o_obj->o_group == n_obj->o_group) {
+                        o_obj->o_count += n_obj->o_count;
+                        o_discard(n_item);
+                        break;
+                    }
+                }
+            }
+            if (o_item == NULL) {       /* didn't find it */
+                attach(th->t_pack, n_item);
+            }
+        }
+
+        /* If there was anything here, we may have to update the screen */
+        if (item_count) {
+            if (cansee(ch_ret.y, ch_ret.x))
+                mvwaddch(cw, ch_ret.y, ch_ret.x, mvinch(ch_ret.y, ch_ret.x));
+            updpack(TRUE, th); /* Update the monster's encumberance, too */
+        }
+    }
+
+    rch = mvwinch(stdscr, old_pos.y, old_pos.x); 
+    if (th->t_oldch == floor && rch != floor && !isatrap(rch))
+        mvwaddch(cw, old_pos.y, old_pos.x, rch);
+    else
+        mvwaddch(cw, old_pos.y, old_pos.x, th->t_oldch);
+    sch = mvwinch(cw, ch_ret.y, ch_ret.x); /* What player sees */
+    rch = mvwinch(stdscr, ch_ret.y, ch_ret.x); /* What's really there */
+
+    /* If we have a tunneling monster, it may be making a tunnel */
+    if (on(*th, CANTUNNEL)      &&
+        (rch==SECRETDOOR || rch==WALL || rch==VERTWALL || rch==HORZWALL)) {
+        unsigned char nch;       /* The new look to the tunnel */
+
+        if (rch == WALL && levtype == OUTSIDE) nch = FLOOR;
+        else if (rch == WALL) nch = PASSAGE;
+        else if (levtype == MAZELEV || levtype == OUTSIDE) nch = FLOOR;
+        else nch = DOOR;
+        addch(nch);
+
+        if (cansee(ch_ret.y, ch_ret.x)) sch = nch; /* Can player see this? */
+
+        /* Does this make a new exit? */
+        if (rch == VERTWALL || rch == HORZWALL) {
+            struct linked_list *newroom;
+            coord *exit;
+
+            newroom = new_item(sizeof(coord));
+            exit = DOORPTR(newroom);
+            *exit = ch_ret;
+            attach(new_room->r_exit, newroom);
+        }
+    }
+
+    /* Mark if the monster is inside a wall */
+    if (isrock(mvinch(ch_ret.y, ch_ret.x))) turn_on(*th, ISINWALL);
+    else turn_off(*th, ISINWALL);
+
+    /* If the monster can illuminate rooms, check for a change */
+    if (on(*th, HASFIRE)) {
+        register struct linked_list *fire_item;
+
+        /* Is monster entering a room? */
+        if (orig_rer != new_room && new_room != NULL) {
+            fire_item = creat_item();   /* Get an item-only structure */
+            ldata(fire_item) = (char *) th;
+
+            attach(new_room->r_fires, fire_item);
+            new_room->r_flags |= HASFIRE;
+
+            if (cansee(ch_ret.y, ch_ret.x) && next(new_room->r_fires) == NULL)
+                light(&hero);
+        }
+
+        /* Is monster leaving a room? */
+        if (orig_rer != new_room && orig_rer != NULL) {
+            /* Find the bugger in the list and delete him */
+            for (fire_item = orig_rer->r_fires; fire_item != NULL;
+                 fire_item = next(fire_item)) {
+                if (THINGPTR(fire_item) == th)  {       /* Found him! */
+                    detach(orig_rer->r_fires, fire_item);
+                    destroy_item(fire_item);
+                    if (orig_rer->r_fires == NULL) {
+                        orig_rer->r_flags &= ~HASFIRE;
+                        if (cansee(old_pos.y, old_pos.x))
+                            light(&old_pos);
+                    }
+                    break;
+                }
+            }
+        }
+    }
+
+    /* If monster is entering player's room and player can see it,
+     * stop the player's running.
+     */
+    if (new_room != orig_rer && new_room != NULL  &&
+        new_room == roomin(th->t_dest) && cansee(unc(ch_ret))    &&
+        (off(*th, ISINVIS)     || on(player, CANSEE)) &&
+        (off(*th, ISSHADOW)    || on(player, CANSEE)) &&
+        (off(*th, CANSURPRISE) || ISWEARING(R_ALERT))) {
+                running = FALSE;
+                if (fight_flush) flushinp();
+    }
+
+    th->t_oldch = sch;
+
+    /* Let's display those creatures that we can see. */
+    if (cansee(unc(ch_ret)) &&
+        off(*th, ISINWALL) &&
+        !invisible(th))
+        mvwaddch(cw, ch_ret.y, ch_ret.x, th->t_type);
+
+    /* Record monster's last position (if new one is different) */
+    if (!ce(ch_ret, old_pos)) th->t_oldpos = old_pos;
+
+    /* If the monster is on a trap, trap it */
+    sch = mvinch(ch_ret.y, ch_ret.x);
+    if (isatrap(sch)) {
+        if (cansee(ch_ret.y, ch_ret.x)) th->t_oldch = sch;
+        be_trapped(th, &ch_ret);
+    }
+}
+
+/* 
+ * Get_hurl returns the weapon that the monster will "throw" if he has one 
+ */
+
+struct linked_list *
+get_hurl(tp)
+register struct thing *tp;
+{
+    struct linked_list *arrow=NULL, *bolt=NULL, *rock=NULL,
+        *spear = NULL, *dagger=NULL, *dart=NULL, *aklad=NULL;
+    register struct linked_list *pitem;
+    register struct object *obj;
+    bool bow=FALSE, crossbow=FALSE, sling=FALSE;
+
+    for (pitem=tp->t_pack; pitem; pitem=next(pitem)) {
+        obj = OBJPTR(pitem);
+        if (obj->o_type == WEAPON)
+            switch (obj->o_which) {
+                case BOW:       bow = TRUE;
+                when CROSSBOW:  crossbow = TRUE;
+                when SLING:     sling = TRUE;
+                when ROCK:      rock = pitem;
+                when ARROW:     arrow = pitem;
+                when BOLT:      bolt = pitem;
+                when SPEAR:     spear = pitem;
+                when DAGGER:
+                    /* Don't throw the dagger if it's our last one */
+                    if (obj->o_count > 1) dagger = pitem;
+                when DART:      dart = pitem;
+            }
+        else if (obj->o_type == RELIC &&
+                 obj->o_which == AXE_AKLAD)
+                    aklad = pitem;
+    }
+    
+    /* Do we have that all-powerful Aklad Axe? */
+    if (aklad) return(aklad);
+
+    /* Use crossbow bolt if possible */
+    if (crossbow && bolt) return(bolt);
+    if (bow && arrow) return(arrow);
+    if (spear) return(spear);
+    if (dagger) return(dagger);
+    if (sling && rock) return(rock);
+    if (dart) return(dart);
+    return(NULL);
+}
+
+/*
+ * runto:
+ *      Set a monster running after something
+ */
+
+runto(runner, spot)
+register struct thing *runner;
+coord *spot;
+{
+    if (on(*runner, ISSTONE))
+        return;
+
+    /* If we are chasing a new creature, forget about thrown weapons */
+    if (runner->t_dest && !ce(*runner->t_dest, *spot)) runner->t_wasshot=FALSE;
+
+    /*
+     * Start the beastie running
+     */
+    runner->t_dest = spot;
+    turn_on(*runner, ISRUN);
+    turn_off(*runner, ISDISGUISE);
+}
+
+/*
+ * straight_shot:
+ *      See if there is a straight line of sight between the two
+ *      given coordinates.  If shooting is not NULL, it is a pointer
+ *      to a structure which should be filled with the direction
+ *      to shoot (if there is a line of sight).  If shooting, monsters
+ *      get in the way.  Otherwise, they do not.
+ */
+
+bool
+straight_shot(ery, erx, eey, eex, shooting)
+register int ery, erx, eey, eex;
+register coord *shooting;
+{
+    register int dy, dx;        /* Deltas */
+    unsigned char ch;
+
+    /* Does the monster have a straight shot at prey */
+    if ((ery != eey) && (erx != eex) &&
+        (abs(ery - eey) != abs(erx - eex))) return(FALSE);
+
+    /* Get the direction to shoot */
+    if (eey > ery) dy = 1;
+    else if (eey == ery) dy = 0;
+    else dy = -1;
+
+    if (eex > erx) dx = 1;
+    else if (eex == erx) dx = 0;
+    else dx = -1;
+
+    /* Make sure we have free area all the way to the player */
+    ery += dy;
+    erx += dx;
+    while ((ery != eey) || (erx != eex)) {
+        switch (ch = winat(ery, erx)) {
+            case VERTWALL:
+            case HORZWALL:
+            case WALL:
+            case DOOR:
+            case SECRETDOOR:
+            case FOREST:
+                return(FALSE);
+            default:
+                if (shooting && isalpha(ch)) return(FALSE);
+        }
+        ery += dy;
+        erx += dx;
+    }
+
+    if (shooting) {     /* If we are shooting -- put in the directions */
+        shooting->y = dy;
+        shooting->x = dx;
+    }
+    return(TRUE);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xrogue/command.c	Tue Apr 21 08:55:20 2015 -0400
@@ -0,0 +1,1305 @@
+/*
+    command.c  -  Read and execute the user commands
+ 
+    XRogue: Expeditions into the Dungeons of Doom
+    Copyright (C) 1991 Robert Pietkivitch
+    All rights reserved.
+    
+    Based on "Advanced Rogue"
+    Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka and AT&T
+    All rights reserved.
+
+    Based on "Rogue: Exploring the Dungeons of Doom"
+    Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
+    All rights reserved.
+    
+    See the file LICENSE.TXT for full copyright and licensing information.
+*/
+
+#include <curses.h>
+#include <ctype.h>
+#include <signal.h>
+#include "mach_dep.h"
+#include "rogue.h"
+
+/*
+ * command:
+ *      Process the user commands
+ */
+
+command()
+{
+    unsigned int ch;
+    struct linked_list *item;
+    unsigned int countch = 0, direction = 0, newcount = FALSE;
+    int segment = 1;
+    int monst_limit, monst_current;
+
+    monst_limit = monst_current = 1;
+    while (playing) {
+        /*
+         * Let the daemons start up, but only do them once a round
+         * (round = 10 segments).
+         */
+        if (segment >= 10) {
+            do_daemons(BEFORE);
+            do_fuses(BEFORE);
+        }
+
+        after = TRUE;
+        do {
+            /* One more tick of the clock. */
+            if (segment >= 10 && after && (++turns % DAYLENGTH) == 0) {
+                daytime ^= TRUE;
+                if (levtype == OUTSIDE) {
+                    if (daytime) msg("A bright star flares above the horizon.");
+                    else msg("The bright star travels beyond the horizon.");
+                }
+                light(&hero);
+            }
+
+            /*
+             * Don't bother with these updates unless the player's going
+             * to do something.
+             */
+            if (player.t_action == A_NIL && player.t_no_move <= 1) {
+                look(after, FALSE);
+                lastscore = purse;
+                wmove(cw, hero.y, hero.x);
+                if (!((running || count) && jump)) {
+                    status(FALSE);
+                }
+            }
+
+            /* Draw the screen */
+            if (!((running || count) && jump)) {
+                wmove(cw, hero.y, hero.x);
+                draw(cw);
+            }
+
+            after = TRUE;
+
+            /*
+             * Read command or continue run
+             */
+            if (--player.t_no_move <= 0) {
+                take = 0;               /* Nothing here to start with */
+                player.t_no_move = 0;   /* Be sure we don't go too negative */
+                if (!running) door_stop = FALSE;
+
+                /* Was the player being held? */
+                if (player.t_action == A_FREEZE) {
+                    player.t_action = A_NIL;
+                    msg("You can move again.");
+                }
+
+                if (player.t_action != A_NIL) ch = player.t_action;
+                else if (running) {
+                    char scratch;
+
+                    /* If in a corridor or maze, if we are at a turn with
+                     * only one way to go, turn that way.
+                     */
+                    scratch = winat(hero.y, hero.x);
+                    if ((scratch==PASSAGE||scratch==DOOR||levtype==MAZELEV)  &&
+                        off(player, ISHUH)                                   && 
+                        off(player, ISBLIND)) {
+                        int y, x;
+                        if (getdelta(runch, &y, &x) == TRUE) {
+                            corr_move(y, x);
+                        }
+                    }
+                    ch = runch;
+                }
+                else if (count) ch = countch;
+                else {
+                    ch = wgetch(cw);
+                    if (mpos != 0 && !running)  /* Erase message if its there */
+                        msg("");
+                }
+
+                /*
+                 * check for prefixes
+                 */
+                if (isascii(ch) && isdigit(ch))
+                {
+                    count = 0;
+                    newcount = TRUE;
+                    while (isascii(ch) && isdigit(ch))
+                    {
+                        count = count * 10 + (ch - '0');
+                        ch = wgetch(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 C_SEARCH: case '.':
+                            break;
+                        default:
+                            count = 0;
+                    }
+                }
+
+                /* Save current direction */
+                if (!running) { /* If running, it is already saved */
+                    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':
+                            runch = tolower(ch);
+                    }
+                }
+
+                /* Perform the action */
+                switch (ch) {
+                    case 'f':
+                        if (!on(player, ISBLIND))
+                        {
+                            door_stop = TRUE;
+                            firstmove = TRUE;
+                        }
+                        if (count && !newcount)
+                            ch = direction;
+                        else
+                            ch = wgetch(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();
+                    case KEY_LEFT       : do_move(0, -1);
+                    when KEY_DOWN       : do_move(1, 0);
+                    when KEY_UP         : do_move(-1, 0);
+                    when KEY_RIGHT      : do_move(0, 1);
+                    when KEY_HOME       : do_move(-1, -1);
+                    when KEY_A1         : do_move(-1, -1);
+                    when KEY_PPAGE      : do_move(-1, 1);
+                    when KEY_A3         : do_move(-1, 1);
+                    when KEY_END         : do_move(1, -1);
+                    when KEY_C1         : do_move(1, -1);
+                    when KEY_NPAGE      : do_move(1, 1);
+                    when KEY_C3         : do_move(1, 1);
+#ifdef CTL_RIGHT
+                    when CTL_RIGHT      : do_run('l');
+                    when CTL_LEFT       : do_run('h');
+                    when CTL_UP         : do_run('k');
+                    when CTL_DOWN       : do_run('j');
+                    when CTL_HOME       : do_run('y');
+                    when CTL_PGUP       : do_run('u');
+                    when CTL_END        : do_run('b');
+                    when CTL_PGDN       : do_run('n');
+#endif
+                    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 A_ATTACK:
+                        /* Is our attackee still there? */
+                        if (isalpha(winat(player.t_newpos.y,
+                                          player.t_newpos.x))) {
+                            /* Our friend is still here */
+                            player.t_action = A_NIL;
+                            fight(&player.t_newpos, cur_weapon, FALSE);
+                        }
+                        else {  /* Our monster has moved */
+                            player.t_action = A_NIL;
+                        }
+                    when A_PICKUP:
+                        player.t_action = A_NIL;
+                        if (add_pack((struct linked_list *)NULL, FALSE)) {
+                            char tch;
+                            tch = mvwinch(stdscr, hero.y, hero.x);
+                            if (tch != FLOOR && tch != PASSAGE) {
+                                player.t_action = A_PICKUP; /*get more */
+                                player.t_no_move += 2 * movement(&player);
+                            }
+                        }
+                    when A_THROW:
+                        if (player.t_action == A_NIL) {
+                            item = get_item(pack, "throw", ALL, FALSE, FALSE);
+                            if (item != NULL && get_dir(&player.t_newpos)) {
+                                player.t_action = A_THROW;
+                                player.t_using = item;
+                                player.t_no_move = 2 * movement(&player);
+                            }
+                            else
+                                after = FALSE;
+                        }
+                        else {
+                            missile(player.t_newpos.y, player.t_newpos.x, 
+                                    player.t_using, &player);
+                            player.t_action = A_NIL;
+                            player.t_using = 0;
+                        }
+                    when 'a' :
+                        if (player.t_action == A_NIL) {
+                            if (get_dir(&player.t_newpos)) {
+                                player.t_action = 'a';
+                                player.t_no_move = 1 + movement(&player);
+                            }
+                            else
+                                after = FALSE;
+                        }
+                        else {
+                            affect();
+                            player.t_action = A_NIL;
+                        }
+                    when 'A' : choose_qst();  
+                    when 'F' : /* frighten a monster */
+                        if (player.t_action == A_NIL) {
+                            player.t_action = 'F';
+                            player.t_no_move = 2*movement(&player);
+                        }
+                        else {
+                after = FALSE;
+                            player.t_action = A_NIL;
+                            fright();
+                        }
+                    when 'g' : /* Give command: give slime-molds to monsters */
+                        if (player.t_action == A_NIL) {
+                            player.t_action = 'g';
+                            player.t_no_move = 2*movement(&player);
+                        }
+                        else {
+                after = FALSE;
+                            player.t_action = A_NIL;
+                            give();
+                        }
+                    when 'G' :
+                        if (player.t_action == A_NIL) {
+                            player.t_action = 'G';
+                            player.t_no_move = movement(&player);
+                        }
+                        else {
+                            player.t_action = A_NIL;
+                            gsense();
+                        }
+                    when 'i' : after = FALSE; inventory(pack, ALL);
+                    when 'I' : after = FALSE; picky_inven();
+                    when 'm' : nameitem((struct linked_list *)NULL, TRUE);
+                    when 'o' : option();
+                    when 'O' : msg("Charactor type: %s    Quest item: %s", char_class[char_type].name, rel_magic[quest_item].mi_name);
+                    when ',' :
+                    case 'P' :
+                        if (levtype != POSTLEV) {
+                            /* We charge 2 movement units per item */
+                            player.t_no_move =
+                                2 * grab(hero.y, hero.x) * movement(&player);
+                        }
+                        else {
+                            /* Let's quote the wise guy a price */
+                            buy_it();
+                            after = FALSE;
+                        }
+                    when 'Q' : after = FALSE; quit(0);
+                    when 'S' : 
+                        after = FALSE;
+                        if (save_game())
+                            exit_game(EXIT_CLS | EXIT_ENDWIN);
+                    when 'v' : after = FALSE;
+                               msg("Advanced xrogue, Version %s  ", release);
+                    when 'X' :  /* trap sense */
+            after = FALSE;
+                        if (player.t_action == A_NIL) {
+                            player.t_action = 'X';
+                            player.t_no_move = movement(&player);
+                        }
+                        else {
+                            xsense();
+                            player.t_action = A_NIL;
+                        }
+                    when '.' :
+                        player.t_no_move = movement(&player);  /* Rest */
+                        player.t_action = A_NIL;
+                    when ' ' : after = FALSE;   /* Do Nothing */
+                    when '>' : after = FALSE; d_level();
+                    when '<' : after = FALSE; u_level();
+                    when '=' : after = FALSE; display();
+                    when '?' : after = FALSE; help();
+
+            /* no character descriptions yet until updated (help.c) */
+            /* when '\\' : after = FALSE; ident_hero(); */
+            when '\\' : msg("Charon (the Boatman) looks at you... ");
+
+                    when '/' : after = FALSE; identify(NULL);
+                    when C_COUNT : count_gold();
+                    when C_DIP : dip_it();
+                    when C_DROP : player.t_action = C_DROP; 
+                                  drop((struct linked_list *)NULL);
+                    when C_EAT : eat();
+                    when C_QUAFF : quaff(-1, NULL, NULL, TRUE);
+                    when C_READ : read_scroll(-1, NULL, TRUE);
+                    when C_SETTRAP : set_trap(&player, hero.y, hero.x);
+                    when C_SEARCH :
+                        if (player.t_action == A_NIL) {
+                            player.t_action = C_SEARCH;
+                            player.t_no_move = 2 + movement(&player);
+                        }
+                        else {
+                            search(FALSE, FALSE);
+                            player.t_action = A_NIL;
+                        }
+                    when C_TAKEOFF : take_off();
+                    when C_USE : use_mm(-1);
+                    when C_WEAR : wear();
+                    when C_WIELD : wield();
+                    when C_ZAP : if (!player_zap(NULL, FALSE)) after=FALSE;
+                    when C_CAST : cast();
+                    when C_CHANT : chant();
+                    when C_PRAY : pray();
+                    when CTRL('B') : msg("Current score: %d",
+                    pstats.s_exp + (long) purse);
+                    when CTRL('E') : msg("Current food level: %d(2000)",
+                    food_left);
+                    when CTRL('L') : after = FALSE; clearok(curscr, TRUE);
+                                    touchwin(cw);
+                    when CTRL('N') : nameit();
+                    when CTRL('O') : after = FALSE; opt_player();
+                    when CTRL('R') : after = FALSE; msg(huh);
+                    when CTRL('T') :
+                        if (player.t_action == A_NIL) {
+                            if (get_dir(&player.t_newpos)) {
+                                player.t_action = CTRL('T');
+                                player.t_no_move = 2 * movement(&player);
+                            }
+                            else
+                                after = FALSE;
+                        }
+                        else {
+                            steal();
+                            player.t_action = A_NIL;
+                        }
+                    when ESC :  /* Escape */
+                        door_stop = FALSE;
+                        count = 0;
+                        after = FALSE;
+                    when '#':
+                        if (levtype == POSTLEV)         /* buy something */
+                            buy_it();
+                        after = FALSE;
+                    when '$':
+                        if (levtype == POSTLEV)         /* price something */
+                            price_it();
+                        after = FALSE;
+                    when '%':
+                        if (levtype == POSTLEV)         /* sell something */
+                            sell_it();
+                        after = FALSE;
+            when '+':   /* instant karma! */
+            switch (rnd(100)) {
+                case 0:  msg("You waste some time. ");
+                when 5:  msg("An oak tree in the garden. ");
+                when 10: msg("Character is what you become in the dark. ");
+                when 15: msg("May you live all the days of your life. ");
+                when 20: msg("A hero is no braver than an ordinary man, but he is brave five minutes longer. ");
+                when 25: msg("Get down! ");
+                when 30: msg("Go back to sleep. ");
+                when 35: msg("Be here now. ");
+                when 40: msg("Choose the rock that feels right to you. ");
+                when 45: msg("Wait... ");
+                when 50: msg("You take a break (yawn)... ");
+                when 55: msg("Without danger there is no pleasure. ");
+                when 60: msg("Define meaningless? ");
+                when 65: msg("Don't push your luck! ");
+                when 70: msg("Gung ho. ");
+                when 75: msg("You are inside a computer. ");
+                when 80: msg("Directive is now required... ");
+                when 85: msg("Charon (the Boatman) awaits you... ");
+                when 95: msg(nothing);
+                otherwise: msg("");
+            }
+            after = FALSE;
+                    when CTRL('P') :
+                        after = FALSE;
+                        if (wizard)
+                        {
+                            wizard = FALSE;
+                            trader = 0;
+                            msg("Not wizard any more");
+                        }
+                        else
+                        {
+                            if (waswizard || passwd())
+                            {
+                                msg("Welcome, O Mighty Wizard! ");
+                                wizard = waswizard = TRUE;
+                            }
+                            else
+                                msg("Sorry");
+                        }
+
+                    otherwise :
+                        after = FALSE;
+                        if (wizard) switch (ch) {
+                            case 'M' : create_obj(TRUE, 0, 0);
+                            when 'V' : msg("vlevel = %d  turns = %d",
+                                           vlevel, turns);
+                            when CTRL('A') : activity();
+                            when CTRL('C') : do_teleport();
+                            when CTRL('D') : level++;
+                                           take_with();
+                                           new_level(NORMLEV);
+                            when CTRL('F') : overlay(stdscr,cw);
+                            when CTRL('G') :
+                            {
+                                item=get_item(pack,"charge",STICK,FALSE,FALSE);
+                                if (item != NULL) {
+                                    (OBJPTR(item))->o_charges=10000;
+                                }
+                            }
+                            when CTRL('H') :
+                            {
+                                register int i, j;
+                                register struct object *obj;
+
+                                for (i = 0; i < 9; i++)
+                                    raise_level();
+                                /*
+                                 * Give the rogue a sword 
+                                 */
+                                if (cur_weapon==NULL || cur_weapon->o_type !=
+                                    RELIC) {
+                                if (player.t_ctype == C_THIEF   ||
+                                    player.t_ctype == C_ASSASSIN ||
+                                    player.t_ctype == C_MONK)
+                                      item = spec_item(WEAPON, BASWORD, 20, 20);
+                                else
+                                      item = spec_item(WEAPON,TWOSWORD, 20, 20);
+                                    if (add_pack(item, TRUE))
+                                    {
+                                        cur_weapon = OBJPTR(item);
+                                        (OBJPTR(item))->o_flags |= (ISKNOW|ISPROT);
+                                    }
+                                    else
+                                        o_discard(item);
+                                /*
+                                 * And his suit of armor
+                                 */
+                                if (player.t_ctype == C_THIEF   ||
+                                    player.t_ctype == C_ASSASSIN ||
+                                    player.t_ctype == C_MONK)
+                                      j = PADDED_ARMOR;
+                                else
+                                      j = PLATE_ARMOR;
+                                    item = spec_item(ARMOR, j, 20, 0);
+                                    obj = OBJPTR(item);
+                                    obj->o_flags |= (ISKNOW | ISPROT);
+                                    obj->o_weight = armors[j].a_wght;
+                                    if (add_pack(item, TRUE))
+                                        cur_armor = obj;
+                                    else
+                                        o_discard(item);
+                                }
+                                purse += 20000;
+                            }
+                            when CTRL('I') : inventory(lvl_obj, ALL);
+                            when CTRL('J') : teleport();
+                            when CTRL('K') : whatis((struct linked_list *)NULL);
+                            when CTRL('W') : wanderer();
+                            when CTRL('X') : overlay(mw,cw);
+                            when CTRL('Y') : msg("food left: %d\tfood level: %d", 
+                                                    food_left, foodlev);
+                            otherwise :
+                                msg("Illegal wizard command '%s'.", unctrl(ch));
+                                count = 0;
+                        }
+                        else
+                        {
+                            msg("Illegal command '%s'.", unctrl(ch));
+                            count = 0;
+                            after = FALSE;
+                        }
+                }
+
+                /*
+                 * If he ran into something to take, let him pick it up.
+                 * unless it's a trading post
+                 */
+                if (auto_pickup && take != 0 && levtype != POSTLEV) {
+                    /* get ready to pick it up */
+                    player.t_action = A_PICKUP;
+                    player.t_no_move += 2 * movement(&player);
+                }
+            }
+
+            /* If he was fighting, let's stop (for now) */
+            if (player.t_quiet < 0) player.t_quiet = 0;
+
+            if (!running)
+                door_stop = FALSE;
+
+            if (after && segment >= 10) {
+                /*
+                 * Kick off the rest if the daemons and fuses
+                 */
+
+                /* 
+                 * If player is infested, take off a hit point 
+                 */
+                if (on(player, HASINFEST)) {
+            pstats.s_hpt -= infest_dam;
+                    if (pstats.s_hpt == 50 || pstats.s_hpt == 25)
+            msg("You feel yourself withering away... ");
+                    if (pstats.s_hpt < 1) {
+            msg("You die a festering mass.  --More--");
+            wait_for(' ');
+            pstats.s_hpt = -1;
+            death(D_INFESTATION);
+            }
+                }
+
+                /*
+                 * The eye of Vecna is a constant drain on the player
+                 */
+                if (cur_relic[EYE_VECNA]) {
+            pstats.s_hpt -= 1;
+                    if (pstats.s_hpt == 50 || pstats.s_hpt == 25)
+            msg("You feel Vecna's eye looking about. ");
+                    if (pstats.s_hpt <= 10 && pstats.s_hpt >= 3)
+            msg("Vecna's eye moves about very quickly. ");
+                    if (pstats.s_hpt < 1) {
+            msg("Vecna's curse is upon you!  --More--");
+            wait_for(' ');
+            pstats.s_hpt = -1;
+            death(D_RELIC);
+            }
+                }
+
+                /* 
+                 * if player has body rot then take off three hits 
+                 */
+                if (on(player, DOROT)) {
+             pstats.s_hpt -= rnd(3)+1;
+                     if (pstats.s_hpt == 50 || pstats.s_hpt == 25) 
+             msg("Something really begins to stink and smell! ");
+                     if (pstats.s_hpt < 1) {
+             msg("You keel over with rot.  --More--");
+             wait_for(' ');
+             pstats.s_hpt = -1;
+             death(D_ROT);
+             }
+                }
+                do_daemons(AFTER);
+                do_fuses(AFTER);
+            }
+        } while (after == FALSE);
+
+        /* Make the monsters go */
+        if (--monst_current <= 0)
+            monst_current = monst_limit = runners(monst_limit);
+
+        if (++segment > 10) segment = 1;
+        reap(); /* bury all the dead monsters */
+    }
+}
+
+/*
+ * display
+ *      tell the player what is at a certain coordinates assuming
+ *      it can be seen.
+ */
+display()
+{
+    coord c;
+    struct linked_list *item;
+    struct thing *tp;
+    int what;
+
+    msg("What do you want to display (* for help)?");
+    c = get_coordinates();
+    mpos = 0;
+    if (!cansee(c.y, c.x)) {
+        msg("You can't see what is there.");
+        return;
+    }
+    what = mvwinch(cw, c.y, c.x);
+    if (isalpha(what)) {
+        item = find_mons(c.y, c.x);
+        tp = THINGPTR(item);
+        msg("%s", monster_name(tp));
+        return;
+    }
+    if ((item = find_obj(c.y, c.x)) != NULL) {
+        msg("%s", inv_name(OBJPTR(item), FALSE));
+        return;
+    }
+    identify(what);
+}
+
+/*
+ * quit:
+ *      Have player make certain, then exit.
+ */
+
+/*UNUSED*/
+void
+quit(sig)
+int sig;
+{
+    register int oy, ox;
+
+	NOOP(sig);
+
+    /*
+     * Reset the signal in case we got here via an interrupt
+     */
+
+    if ((VOID(*)())signal(SIGINT, quit) != (VOID(*)())quit)
+        mpos = 0;
+
+    getyx(cw, oy, ox);
+    if (level < 1) {    /* if not down in the dungeon proper; exit the game */
+        wclear(hw);
+        wmove(hw, lines-1, 0);
+        draw(hw);
+        wmove(hw, 12, 30);
+        wprintw(hw, "Good-bye!");
+        draw(hw);
+        exit_game(EXIT_ENDWIN);
+    }
+    msg("Really quit? <yes or no> ");   /* otherwise ask about quitting */
+    draw(cw);
+    prbuf[0] = '\0';
+    if ((get_str(prbuf, msgw) == NORM) && strcmp(prbuf, "yes") == 0) {
+        clear();
+        move(lines-1, 0);
+        draw(stdscr);
+        score(pstats.s_exp + (long) purse, CHICKEN, 0);
+        exit_game(EXIT_ENDWIN);
+    }
+    else {
+        signal(SIGINT, quit);
+        wmove(msgw, 0, 0);
+        wclrtoeol(msgw);
+        draw(msgw);
+        status(FALSE);
+        wmove(cw, oy, ox);
+        draw(cw);
+        mpos = 0;
+        count = 0;
+        running = FALSE;
+    }
+}
+
+/*
+ * bugkill:
+ *      killed by a program bug instead of voluntarily.
+ */
+
+bugkill(sig)
+int sig;
+{
+    signal(sig, quit);      /* If we get it again, give up */
+    if (levtype == OUTSIDE) {
+        msg("Oh no!  You walk right into a flying swarm of nasty little bugs!! ");
+        msg("One of them penetrates your brain!!!  --More--");
+    }
+    else {
+        msg("Charon (the Boatman) has finally come for you...  --More--");
+    }
+    wait_for(' ');
+    pstats.s_hpt = -1;
+    death(D_SIGNAL);    /* Killed by a bug */
+}
+
+/*
+ * search:
+ *      Player gropes about him to find hidden things.
+ */
+
+search(is_thief, door_chime)
+register bool is_thief, door_chime;
+{
+    register int x, y;
+    register char ch,   /* The trap or door character */
+                 sch;   /* Trap or door character (as seen on screen) */
+    register unsigned char mch;   /* Monster, if a monster is on the trap or door */
+    register struct linked_list *item;
+    register struct thing *mp; /* Status on surrounding monster */
+
+    /*
+     * 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++)
+        {
+            if (y==hero.y && x==hero.x)
+                continue;
+
+            if (x < 0 || y < 0 || x >= cols || y >= lines)
+                continue;
+
+            /* Mch and ch will be the same unless there is a monster here */
+            mch = winat(y, x);
+            ch = mvwinch(stdscr, y, x);
+            sch = mvwinch(cw, y, x);    /* What's on the screen */
+
+            if (door_chime == FALSE && isatrap(ch)) {
+                    register struct trap *tp;
+
+                    /* Is there a monster on the trap? */
+                    if (mch != ch && (item = find_mons(y, x)) != NULL) {
+                        mp = THINGPTR(item);
+                        if (sch == mch) sch = mp->t_oldch;
+                    }
+                    else mp = NULL;
+
+                    /* 
+                     * is this one found already?
+                     */
+                    if (isatrap(sch)) 
+                        continue;       /* give him chance for other traps */
+                    tp = trap_at(y, x);
+                    /* 
+                     * if the thief set it then don't display it.
+                     * if its not a thief he has 50/50 shot
+                     */
+                    if((tp->tr_flags&ISTHIEFSET) || (!is_thief && rnd(100)>50))
+                        continue;       /* give him chance for other traps */
+                    tp->tr_flags |= ISFOUND;
+
+                    /* Let's update the screen */
+                    if (mp != NULL && mvwinch(cw, y, x) == mch)
+                        mp->t_oldch = ch; /* Will change when monst moves */
+                    else mvwaddch(cw, y, x, ch);
+
+                    count = 0;
+                    running = FALSE;
+
+                    /* Stop what we were doing */
+                    player.t_no_move = movement(&player);
+                    player.t_action = A_NIL;
+                    player.t_using = NULL;
+
+                    if (fight_flush) flushinp();
+                    msg(tr_name(tp->tr_type));
+            }
+            else if (ch == SECRETDOOR) {
+                if (door_chime == TRUE || (!is_thief && rnd(100) < 20)) {
+                    struct room *rp;
+                    coord cp;
+
+                    /* Is there a monster on the door? */
+                    if (mch != ch && (item = find_mons(y, x)) != NULL) {
+                        mp = THINGPTR(item);
+
+                        /* Screen will change when monster moves */
+                        if (sch == mch) mp->t_oldch = ch;
+                    }
+                    mvaddch(y, x, DOOR);
+                    count = 0;
+                    /*
+                     * if its the entrance to a treasure room, wake it up
+                     */
+                    cp.y = y;
+                    cp.x = x;
+                    rp = roomin(&cp);
+                    if (rp->r_flags & ISTREAS)
+                        wake_room(rp);
+
+                    /* Make sure we don't shoot into the room */
+                    if (door_chime == FALSE) {
+                        count = 0;
+                        running = FALSE;
+
+                        /* Stop what we were doing */
+                        player.t_no_move = movement(&player);
+                        player.t_action = A_NIL;
+                        player.t_using = NULL;
+                    }
+                }
+            }
+        }
+}
+
+/*
+ * d_level:
+ *      He wants to go down a level
+ */
+
+d_level()
+{
+    bool no_phase=FALSE;
+    char position = winat(hero.y, hero.x);
+    int au;
+
+
+    /* If we are on a trading post, go to a trading post level. */
+    if (position == POST) {
+        take_with();   /* Take charmed monsters with you while shopping */
+        new_level(POSTLEV);
+        return;
+    }
+
+    /* Dive for gold */
+    if (position == POOL) {
+        if (rnd(300) < 2) {
+            msg("Oh no!!!  You drown in the pool!!!  --More--");
+            pstats.s_hpt = -1;
+            wait_for(' ');
+            death(D_DROWN);
+        }
+        else if (rnd(125) < 25) {
+            au = rnd(350) + (level * 10);
+            msg("You dive under the water momentarily.. ");
+            msg("You found %d gold pieces! ", au);
+            purse = purse + au;
+            return;
+        }
+        else return;  /* doesn't happen all of the time */
+    }
+
+    /* Going down traps is hazardous */
+    switch (position) {
+    case WORMHOLE:
+    case TRAPDOOR:
+    case MAZETRAP:
+    case DARTTRAP:
+    case SLEEPTRAP:
+    case ARROWTRAP:
+    case BEARTRAP:
+    case TELTRAP:
+        msg ("You find yourself in some sort of quicksand!? ");
+        msg ("Hey!  There are rock maggots in here!! ");
+        player.t_no_move += movement(&player) * FREEZETIME;
+        player.t_action = A_FREEZE;
+        msg("You can't move. ");                   /* spare monks */
+        if (!ISWEARING(R_HEALTH) && player.t_ctype != C_MONK) {
+            turn_on(player, DOROT);
+            msg("You feel your skin starting to rot and peel away!! ");
+            }
+        return;
+    }
+
+    /* If we are at a top-level trading post, we probably can't go down */
+    if (levtype == POSTLEV && level == 0 && position != STAIRS) {
+        msg("I see no way down.");
+        return;
+    }
+
+    if (winat(hero.y, hero.x) != STAIRS) {
+        if (off(player, CANINWALL) ||   /* Must use stairs if can't phase */
+            (levtype == OUTSIDE && rnd(100) < 90)) {
+            msg("I see no way down.");
+            return;
+        }
+    if (levtype == OUTSIDE) {
+            level++;
+            take_with();
+            new_level(NORMLEV);
+            if (no_phase) unphase();
+            return;
+        }
+
+        /* Is there any dungeon left below? */
+        if (level >= nfloors) {
+            msg("There is only solid rock below.");
+            return;
+        }
+
+        extinguish(unphase);    /* Using phase to go down gets rid of it */
+        no_phase = TRUE;
+    }
+
+    /* Is this the bottom? */
+    if (level >= nfloors) {
+        msg("The stairway only goes up.");
+        return;
+    }
+
+    level++;
+    take_with();
+    new_level(NORMLEV);
+    if (no_phase) unphase();
+}
+
+/*
+ * u_level:
+ *      He wants to go up a level
+ */
+
+u_level()
+{
+    bool no_phase = FALSE;
+    register struct linked_list *item;
+    char position = winat(hero.y, hero.x);
+    struct thing *tp;
+    struct object *obj;
+
+    /* You can go up into the outside if standing on top of a worm hole */
+    if (position == WORMHOLE) {
+            prev_max = 1000;
+        level--;
+        if (level <= 0) level = 1;
+            msg("You find yourself in strange surroundings... ");
+        if (wizard) addmsg("Going up through a worm hole. ");
+            take_with();
+            new_level(OUTSIDE);
+            return;
+   }
+
+    if (winat(hero.y, hero.x) != STAIRS) {
+        if (off(player, CANINWALL)) {   /* Must use stairs if can't phase */
+            msg("I see no way up.");
+            return;
+        }
+
+        extinguish(unphase);
+        no_phase = TRUE;
+    }
+
+    if (position != STAIRS) return;
+
+    if (level == 0 || levtype == OUTSIDE) {
+        msg("The stairway only goes down.");
+        return;
+    }
+
+    /*
+     * does he have the item he was quested to get?
+     */
+    if (level == 1) {
+        for (item = pack; item != NULL; item = next(item)) {
+            obj = OBJPTR(item);
+            if (obj->o_type == RELIC && obj->o_which == quest_item)
+                total_winner();
+        }
+    }
+    /*
+     * check to see if he trapped a UNIQUE, If he did then put it back
+     * in the monster table for next time
+     */
+    for (item = tlist; item != NULL; item = next(item)) {
+        tp = THINGPTR(item);
+        if (on(*tp, ISUNIQUE)) 
+            monsters[tp->t_index].m_normal = TRUE;
+    }
+    t_free_list(tlist); /* Monsters that fell below are long gone! */
+
+    if (levtype != POSTLEV)
+    level--;
+    if (level > 0) {
+        take_with();
+        new_level(NORMLEV);
+    }
+    else if (cur_max > level) {
+        prev_max = 1000;    /* flag used in n_level.c */
+    level--;
+        if (level <= 0) level = 1;
+        msg("You emerge into the %s. ", daytime ? "eerie light" : "dark night");
+    if (wizard) msg("Going up: cur_max=%d level=%d. ", cur_max, level);
+        take_with();
+        new_level(OUTSIDE);     /* Leaving the dungeon for outside */
+    return;
+ }
+    else {
+        prev_max = 1;   /* flag used in n_level.c */
+        level = -1;     /* Indicate that we are new to the outside */
+        msg("You emerge into the %s. ", daytime ? "eerie light" : "dark night");
+    if (wizard) msg("Going up: cur_max=%d level=%d. ", cur_max, level);
+        take_with();
+        new_level(OUTSIDE); 
+    return;
+    }
+
+    if (no_phase) unphase();
+}
+
+/*
+ * Let him escape for a while
+ */
+
+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(retstr);
+    fflush(stdout);
+    noecho();
+    crmode();
+    in_shell = FALSE;
+    wait_for('\n');
+	restscr(cw);
+}
+
+/*
+ * see what we want to name -- an item or a monster.
+ */
+nameit()
+{
+    char answer;
+
+    msg("Name monster or item (m or i)? ");
+    answer = wgetch(cw);
+    mpos = 0;
+
+    while (answer != 'm' && answer != 'i' && answer != ESC) {
+        mpos = 0;
+        msg("Please specify m or i, for monster or item - ");
+        answer = wgetch(cw);
+    }
+
+    switch (answer) {
+        case 'm': namemonst();
+        when 'i': nameitem((struct linked_list *)NULL, FALSE);
+    }
+}
+
+/*
+ * allow a user to call a potion, scroll, or ring something
+ */
+
+nameitem(item, mark)
+struct linked_list *item;
+bool mark;
+{
+    register struct object *obj;
+    register char **guess = NULL, *elsewise = NULL;
+    register bool *know;
+
+    if (item == NULL) {
+        if (mark) item = get_item(pack, "mark", ALL, FALSE, FALSE);
+        else      item = get_item(pack, "name", CALLABLE, FALSE, FALSE);
+        if (item == NULL) return;
+    }
+    /*
+     * Make certain that it is somethings that we want to wear
+     */
+    obj = OBJPTR(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]);
+        when MM:
+            guess = m_guess;
+            know = m_know;
+            elsewise = (m_guess[obj->o_which] != NULL ?
+                        m_guess[obj->o_which] : "nothing");
+        otherwise:
+            if (!mark) {
+                msg("You can't call that anything.");
+                return;
+            }
+            else know = (bool *) 0;
+    }
+    if ((obj->o_flags & ISPOST) || (know && know[obj->o_which]) && !mark) {
+        msg("That has already been identified.");
+        return;
+    }
+    if (mark) {
+        if (obj->o_mark[0]) {
+            addmsg(terse ? "M" : "Was m");
+            msg("arked \"%s\"", obj->o_mark);
+        }
+        msg(terse ? "Mark it: " : "What do you want to mark it? ");
+        prbuf[0] = '\0';
+    }
+    else {
+        if (elsewise) {
+            addmsg(terse ? "N" : "Was n");
+            msg("amed \"%s\"", elsewise);
+            strcpy(prbuf, elsewise);
+        }
+        else prbuf[0] = '\0';
+        msg(terse ? "Name it: " : "What do you want to name it? ");
+    }
+    if (get_str(prbuf, msgw) == NORM) {
+        if (mark) {
+            strncpy((char *)obj->o_mark, prbuf, MARKLEN-1);
+            obj->o_mark[MARKLEN-1] = '\0';
+        }
+        else if (prbuf[0] != '\0') {
+            if (guess[obj->o_which] != NULL)
+                free(guess[obj->o_which]);
+            guess[obj->o_which] = new((unsigned int) strlen(prbuf) + 1);
+            strcpy(guess[obj->o_which], prbuf);
+        }
+    }
+}
+
+/* Name a monster */
+
+namemonst()
+{
+    register struct thing *tp;
+    struct linked_list *item;
+    coord c;
+
+    /* Find the monster */
+    msg("Choose the monster (* for help)");
+    c = get_coordinates();
+
+    /* Make sure we can see it and that it is a monster. */
+    mpos = 0;
+    if (!cansee(c.y, c.x)) {
+        msg("You can't see what is there.");
+        return;
+    }
+    
+    if (isalpha(mvwinch(cw, c.y, c.x))) {
+        item = find_mons(c.y, c.x);
+        if (item != NULL) {
+            tp = THINGPTR(item);
+            if (tp->t_name == NULL)
+                strcpy(prbuf, monsters[tp->t_index].m_name);
+            else
+                strcpy(prbuf, tp->t_name);
+
+            addmsg(terse ? "N" : "Was n");
+            msg("amed \"%s\"", prbuf);
+            msg(terse ? "Name it: " : "What do you want to name it? ");
+
+            if (get_str(prbuf, msgw) == NORM) {
+                if (prbuf[0] != '\0') {
+                    if (tp->t_name != NULL)
+                        free(tp->t_name);
+                    tp->t_name = new((unsigned int) strlen(prbuf) + 1);
+                    strcpy(tp->t_name, prbuf);
+                }
+            }
+            return;
+        }
+    }
+
+    msg("There is no monster there to name.");
+}
+
+count_gold()
+{
+        if (player.t_action != C_COUNT) {
+            msg("You take a break to count your money.. ");
+            player.t_using = NULL;
+            player.t_action = C_COUNT;  /* We are counting */
+            if (purse > 500000) msg("This may take some time... 10, 20, 30...");
+            player.t_no_move = (purse/75000 + 1) * movement(&player);
+            return;
+        }
+        if (purse > 10000)
+                msg("You have %ld pieces of gold. ", purse);
+        else if (purse == 1)
+                msg("You have 1 piece of gold. ");
+        else
+                msg("You have %ld gold pieces. ", purse);
+        player.t_action = A_NIL;
+}
+
+/* 
+ * Teleport somewhere, anywhere...
+ */
+
+do_teleport()
+{
+    int tlev;
+    prbuf[0] = '\0';
+    msg("To which level do you wish to teleport? ");
+    if(get_str(prbuf,msgw) == NORM) {
+        tlev = atoi(prbuf);
+    if (quest_item == ALTERAN_CARD || wizard) {
+            if (wizard && (tlev < 1 || tlev > LEVEL)) {  /* wizard */
+                mpos = 0;
+                msg("The power of teleportation does have its limitations. ");
+            return;
+            }
+        else if (!wizard && (tlev < 10 || tlev > LEVEL)) {
+                mpos = 0;
+                msg("The power of teleportation does have its limitations. ");
+            return;
+            }
+            else if (tlev >= LEVEL-100 && tlev < LEVEL-50) {
+                levtype = OUTSIDE;
+                level = LEVEL-100;
+            prev_max = 1000; /* a flag for going outside */
+            } 
+            else if (tlev >= LEVEL-150 && tlev < LEVEL-100) {
+                levtype = MAZELEV;
+                level = LEVEL-150;
+            } 
+            else if (tlev >= LEVEL-200 && tlev < LEVEL-150) {
+                levtype = POSTLEV;
+                level = LEVEL-200;
+            }
+            else {
+                levtype = NORMLEV;
+                level = tlev;
+            }
+    }
+    else if (tlev < 40 || tlev > 399) {  /* not quest item or wizard */
+            mpos = 0;
+            msg("The power of teleportation does have its limitations. ");
+        return;
+        }
+    else {
+        levtype = NORMLEV;
+        level = tlev;
+    }
+
+    /* okay, now send him off */
+    cur_max = level;  /* deepest he's been */
+    new_level(levtype);
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xrogue/daemon.c	Tue Apr 21 08:55:20 2015 -0400
@@ -0,0 +1,264 @@
+/*
+    daemon.c - functions for dealing with things that happen in the future
+ 
+    XRogue: Expeditions into the Dungeons of Doom
+    Copyright (C) 1991 Robert Pietkivitch
+    All rights reserved.
+    
+    Based on "Advanced Rogue"
+    Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka and AT&T
+    All rights reserved.
+
+    Based on "Rogue: Exploring the Dungeons of Doom"
+    Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
+    All rights reserved.
+    
+    See the file LICENSE.TXT for full copyright and licensing information.
+*/
+
+#include <curses.h>
+#include "rogue.h"
+
+#define EMPTY           0
+#define DAEMON          -1
+
+#define _X_ { EMPTY }
+
+struct delayed_action {
+        int d_type;
+        int (*d_func)();
+        VOID *d_arg;
+        int d_time;
+} ;
+struct delayed_action d_list[MAXDAEMONS] = {
+        _X_, _X_, _X_, _X_, _X_, _X_, _X_, _X_, _X_, _X_
+};
+struct delayed_action f_list[MAXFUSES] = {
+        _X_, _X_, _X_, _X_, _X_, _X_, _X_, _X_, _X_, _X_,
+        _X_, _X_, _X_, _X_, _X_, _X_, _X_, _X_, _X_, _X_
+};
+
+int demoncnt = 0;        /* number of active daemons */
+int fusecnt = 0;
+
+
+/*
+ * d_slot:
+ *      Find an empty slot in the daemon list
+ */
+struct delayed_action *
+d_slot()
+{
+        reg int i;
+        reg struct delayed_action *dev;
+
+        for (i = 0, dev = d_list; i < MAXDAEMONS; i++, dev++)
+                if (dev->d_type == EMPTY)
+                        return dev;
+        return NULL;
+}
+
+/*
+ * f_slot:
+ *      Find an empty slot in the fuses list
+ */
+struct delayed_action *
+f_slot()
+{
+        reg int i;
+        reg struct delayed_action *dev;
+
+        for (i = 0, dev = f_list; i < MAXFUSES; i++, dev++)
+                if (dev->d_type == EMPTY)
+                        return dev;
+        return NULL;
+}
+
+/*
+ * find_slot:
+ *      Find a particular slot in the table
+ */
+
+struct delayed_action *
+find_slot(func)
+reg int (*func)();
+{
+        reg int i;
+        reg struct delayed_action *dev;
+
+        for (i = 0, dev = f_list; i < MAXFUSES; i++, dev++)
+                if (dev->d_type != EMPTY && func == dev->d_func)
+                        return dev;
+        return NULL;
+}
+
+/*
+ * daemon:
+ *      Start a daemon, takes a function.
+ */
+
+daemon(dfunc, arg, type)
+reg VOID  *arg;
+reg int type, (*dfunc)();
+{
+        reg struct delayed_action *dev;
+
+        dev = d_slot();
+        if (dev != NULL) {
+                dev->d_type = type;
+                dev->d_func = dfunc;
+                dev->d_arg = arg;
+                dev->d_time = DAEMON;
+                demoncnt += 1;                  /* update count */
+        }
+}
+
+/*
+ * kill_daemon:
+ *      Remove a daemon from the list
+ */
+
+kill_daemon(dfunc)
+reg int (*dfunc)();
+{
+        reg struct delayed_action *dev;
+        reg int i;
+
+        for (i = 0, dev = d_list; i < MAXDAEMONS; i++, dev++) {
+                if (dev->d_type != EMPTY && dfunc == dev->d_func)
+                        break;
+        }
+        if (i >= MAXDAEMONS) return; /* if not found, forget it */
+        /*
+         * Take it out of the list
+         */
+        dev->d_type = EMPTY;
+		dev->d_arg  = NULL;
+		dev->d_func = NULL;
+		dev->d_time = 0;
+
+        demoncnt -= 1;                  /* update count */
+}
+
+/*
+ * do_daemons:
+ *      Run all the daemons that are active with the current flag,
+ *      passing the argument to the function.
+ */
+
+do_daemons(flag)
+reg int flag;
+{
+        struct delayed_action *dev;
+        int i;
+
+        /*
+         * Loop through the devil list
+         */
+        for (i = 0; i < MAXDAEMONS; i++)
+        {
+            dev = &d_list[i];
+        /*
+         * Executing each one, giving it the proper arguments
+         */
+                if ((dev->d_type == flag) && (dev->d_time == DAEMON) && (dev->d_func != NULL))
+                        (*dev->d_func)(dev->d_arg);
+        }
+}
+
+/*
+ * fuse:
+ *      Start a fuse to go off in a certain number of turns
+ */
+
+fuse(dfunc, arg, time, type)
+VOID *arg;
+reg int (*dfunc)(), time, type;
+{
+        reg struct delayed_action *wire;
+
+        wire = f_slot();
+        if (wire != NULL) {
+                wire->d_type = type;
+                wire->d_func = dfunc;
+                wire->d_arg = arg;
+                wire->d_time = time;
+                fusecnt += 1;                   /* update count */
+        }
+}
+
+/*
+ * lengthen:
+ *      Increase the time until a fuse goes off
+ */
+
+lengthen(dfunc, xtime)
+reg int (*dfunc)(), xtime;
+{
+        reg struct delayed_action *wire;
+
+        if ((wire = find_slot(dfunc)) == NULL)
+                return;
+        wire->d_time += xtime;
+}
+
+/*
+ * extinguish:
+ *      Put out a fuse
+ */
+
+extinguish(dfunc)
+reg int (*dfunc)();
+{
+        reg struct delayed_action *wire;
+
+        if ((wire = find_slot(dfunc)) == NULL)
+                return;
+        wire->d_type = EMPTY;
+		wire->d_func = NULL;
+		wire->d_arg = NULL;
+		wire->d_time = 0;
+        fusecnt -= 1;
+}
+
+/*
+ * do_fuses:
+ *      Decrement counters and start needed fuses
+ */
+
+do_fuses(flag)
+reg int flag;
+{
+        struct delayed_action *wire;
+        int i;
+
+        /*
+         * Step though the list
+         */
+        for (i = 0; i < MAXFUSES; i++) {
+            wire = &f_list[i];
+        /*
+         * 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;
+				if (wire->d_func != NULL)
+					(*wire->d_func)(wire->d_arg);
+                fusecnt -= 1;
+            }
+        }
+}
+
+/*
+ * activity:
+ *      Show wizard number of demaons and memory blocks used
+ */
+
+activity()
+{
+        msg("Daemons = %d : Fuses = %d : Memory Items = %d : Memory Used = %d",
+            demoncnt,fusecnt,total,md_memused());
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xrogue/daemons.c	Tue Apr 21 08:55:20 2015 -0400
@@ -0,0 +1,731 @@
+/*
+    daemons.c - All the daemon and fuse functions are in here
+  
+    XRogue: Expeditions into the Dungeons of Doom
+    Copyright (C) 1991 Robert Pietkivitch
+    All rights reserved.
+    
+    Based on "Advanced Rogue"
+    Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka and AT&T
+    All rights reserved.
+
+    Based on "Rogue: Exploring the Dungeons of Doom"
+    Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
+    All rights reserved.
+    
+    See the file LICENSE.TXT for full copyright and licensing information.
+*/
+
+#include <curses.h>
+#include "rogue.h"
+
+/*
+ * doctor:
+ *      A healing daemon that restors hit points after rest
+ */
+
+doctor(tp)
+register struct thing *tp;
+{
+    register int ohp;
+    register int limit, new_points;
+    register struct stats *curp; /* current stats pointer */
+    register struct stats *maxp; /* max stats pointer */
+
+    curp = &(tp->t_stats);
+    maxp = &(tp->maxstats);
+    if (curp->s_hpt == maxp->s_hpt) {
+        tp->t_quiet = 0;
+        return;
+    }
+    tp->t_quiet++;
+    switch (tp->t_ctype) {
+        case C_MAGICIAN:
+            limit = 10 - curp->s_lvl;
+            new_points = curp->s_lvl - 2;
+        when C_CLERIC:
+        case C_DRUID:
+            limit = 12 - curp->s_lvl;
+            new_points = curp->s_lvl - 3;
+        when C_THIEF:
+        case C_ASSASSIN:
+            limit = 14 - curp->s_lvl;
+            new_points = curp->s_lvl - 4;
+        when C_MONK:
+            limit = 16 - curp->s_lvl;
+            new_points = curp->s_lvl - 5;
+        when C_RANGER:
+        case C_PALADIN:
+            limit = 18 - curp->s_lvl;
+            new_points = curp->s_lvl - 6;
+        when C_FIGHTER:
+            limit = 20 - curp->s_lvl;
+            new_points = curp->s_lvl - 7;
+        when C_MONSTER:
+            limit = 15 - curp->s_lvl;
+            new_points = curp->s_lvl - 5;
+        otherwise:
+            debug("what a strange character you are!");
+            return;
+    }
+    ohp = curp->s_hpt;
+    if (off(*tp, HASDISEASE) && off(*tp, DOROT)) {
+        if (curp->s_lvl < 8) {
+            if (tp->t_quiet > limit) {
+                curp->s_hpt++;
+                tp->t_quiet = 0;
+            }
+        }
+        else {
+            if (tp->t_quiet >= 3) {
+                curp->s_hpt += rnd(new_points)+1;
+                tp->t_quiet = 0;
+            }
+        }
+    }
+    if (tp == &player) {
+        if (ISRING(LEFT_1, R_REGEN)) curp->s_hpt++;
+        if (ISRING(LEFT_2, R_REGEN)) curp->s_hpt++;
+        if (ISRING(LEFT_3, R_REGEN)) curp->s_hpt++;
+        if (ISRING(LEFT_4, R_REGEN)) curp->s_hpt++;
+        if (ISRING(RIGHT_1, R_REGEN)) curp->s_hpt++;
+        if (ISRING(RIGHT_2, R_REGEN)) curp->s_hpt++;
+        if (ISRING(RIGHT_3, R_REGEN)) curp->s_hpt++;
+        if (ISRING(RIGHT_4, R_REGEN)) curp->s_hpt++;
+    }
+    if (on(*tp, ISREGEN))
+        curp->s_hpt += curp->s_lvl/10 + 1;
+    if (ohp != curp->s_hpt) {
+        if (curp->s_hpt >= maxp->s_hpt) {
+            curp->s_hpt = maxp->s_hpt;
+            if (off(*tp, WASTURNED) && on(*tp, ISFLEE) && tp != &player) {
+                turn_off(*tp, ISFLEE);
+                tp->t_oldpos = tp->t_pos;       /* Start our trek over */
+            }
+        }
+    }
+}
+
+/*
+ * Swander:
+ *      Called when it is time to start rolling for wandering monsters
+ */
+
+swander()
+{
+    daemon(rollwand, (VOID *)NULL, BEFORE);
+}
+
+/*
+ * rollwand:
+ *      Called to roll to see if a wandering monster starts up
+ */
+
+int between = 0;
+
+rollwand()
+{
+
+    if (++between >= 4)
+    {
+        /* Theives may not awaken a monster */
+        if ((roll(1, 6) == 4) &&
+           ((player.t_ctype != C_THIEF && player.t_ctype != C_ASSASSIN) || 
+            (rnd(30) >= dex_compute()))) {
+            if (levtype != POSTLEV)
+                wanderer();
+            kill_daemon(rollwand);
+            fuse(swander, (VOID *)NULL, WANDERTIME, BEFORE);
+        }
+        between = 0;
+    }
+}
+
+/*
+ * this function is a daemon called each turn when the character is a thief
+ */
+
+trap_look()
+{
+    if (rnd(100) < (2*dex_compute() + 5*pstats.s_lvl))
+        search(TRUE, FALSE);
+}
+
+/*
+ * unconfuse:
+ *      Release the poor player from his confusion
+ */
+
+unconfuse()
+{
+    turn_off(player, ISHUH);
+    msg("You feel less confused now");
+}
+
+/*
+ * unsee:
+ *      He lost his see invisible power
+ */
+
+unsee()
+{
+    if (!ISWEARING(R_SEEINVIS)) {
+        turn_off(player, CANSEE);
+        msg("The tingling feeling leaves your eyes");
+    }
+}
+
+/*
+ * unstink:
+ *      Remove to-hit handicap from player
+ */
+
+unstink()
+{
+    turn_off(player, HASSTINK);
+}
+
+/*
+ * unclrhead:
+ *      Player is no longer immune to confusion
+ */
+
+unclrhead()
+{
+    turn_off(player, ISCLEAR);
+    msg("The blue aura about your head fades away.");
+}
+
+/*
+ * unphase:
+ *      Player can no longer walk through walls
+ */
+
+unphase()
+{
+    turn_off(player, CANINWALL);
+    msg("Your dizzy feeling leaves you.");
+    if (!step_ok(hero.y, hero.x, NOMONST, &player)) 
+        msg("You begin to feel weird.. ");
+}
+
+/*
+ * land:
+ *      Player can no longer fly
+ */
+
+int
+land()
+{
+    turn_off(player, ISFLY);
+    msg("You regain your normal weight");
+    running = FALSE;
+    return(0);
+}
+
+/*
+ * sight:
+ *      He gets his sight back
+ */
+
+sight()
+{
+    if (on(player, ISBLIND))
+    {
+        extinguish(sight);
+        turn_off(player, ISBLIND);
+        light(&hero);
+        msg("The veil of darkness lifts");
+    }
+}
+
+/*
+ * res_strength:
+ *      Restore player's strength
+ */
+
+int
+res_strength(howmuch)
+long howmuch;
+{
+
+    /* If lost_str is non-zero, restore that amount of strength,
+     * else all of it 
+     */
+    if (lost_str) {
+        chg_str(lost_str);
+        lost_str = 0;
+    }
+
+    /* Now, add in the restoral, but no greater than maximum strength */
+    if (howmuch > 0)
+        pstats.s_str =
+            min(pstats.s_str + howmuch, max_stats.s_str + ring_value(R_ADDSTR));
+
+    updpack(TRUE, &player);
+    return(0);
+}
+
+/*
+ * nohaste:
+ *      End the hasting
+ */
+
+nohaste()
+{
+    turn_off(player, ISHASTE);
+    msg("You feel yourself slowing down.");
+}
+
+/*
+ * noslow:
+ *      End the slowing
+ */
+
+noslow()
+{
+    turn_off(player, ISSLOW);
+    msg("You feel yourself speeding up.");
+}
+
+/*
+ * suffocate:
+ *      If this gets called, the player has suffocated
+ */
+
+suffocate()
+{
+    pstats.s_hpt = -1;
+    death(D_SUFFOCATION);
+}
+
+/*
+ * digest the hero's food
+ */
+
+stomach()
+{
+    register int oldfood, old_hunger, food_use, i;
+
+    /* 
+     * avoid problems of fainting while eating by just not saying it
+     * takes food to eat food
+     */
+    if (player.t_action == C_EAT) 
+        return;
+
+    old_hunger = hungry_state;
+    if (food_left <= 0)
+    {
+        /*
+         * the hero is fainting
+         */
+        if (player.t_action == A_FREEZE)
+                return;
+        if (rnd(100) > 12)
+            return;
+        if (hungry_state == F_FAINT && rnd(28) == 7) /*must have fainted once*/
+    {
+        pstats.s_hpt = -1;
+        msg("You starve to death!!  --More-- ");
+        wait_for(' ');
+                death(D_STARVATION);
+    }
+        player.t_action = A_FREEZE;
+        player.t_no_move = movement(&player) * (rnd(8) + 3);
+        if (!terse)
+            addmsg("You feel too weak from the lack of food. ");
+        msg("You faint");
+        running = FALSE;
+        if (fight_flush) flushinp();
+        count = 0;
+        hungry_state = F_FAINT;
+    }
+    else
+    {
+        oldfood = food_left;
+        food_use = 0;
+        for (i=0; i<MAXRELIC; i++) { /* each relic eats an additional food */
+            if (cur_relic[i])
+                food_use++;
+        }
+        /* Charge for wearing rings */
+        food_use +=    (ring_eat(LEFT_1)  + ring_eat(LEFT_2)  +
+                        ring_eat(LEFT_3)  + ring_eat(LEFT_4)  +
+                        ring_eat(RIGHT_1) + ring_eat(RIGHT_2) +
+            ring_eat(RIGHT_3) + ring_eat(RIGHT_4) +
+                        foodlev);
+        if (food_use < 1)
+            food_use = 1;
+        food_left -= food_use;
+        if (food_left < MORETIME && oldfood >= MORETIME) {
+            msg("You are starting to feel weak");
+            running = FALSE;
+            if (fight_flush) flushinp();
+            count = 0;
+            hungry_state = F_WEAK;
+        }
+        else if (food_left < 2 * MORETIME && oldfood >= 2 * MORETIME)
+        {
+            msg(terse ? "Getting hungry" : "You are starting to get hungry");
+            running = FALSE;
+            hungry_state = F_HUNGRY;
+        }
+        else if(food_left<STOMACHSIZE-MORETIME && oldfood>=STOMACHSIZE-MORETIME)
+        {
+            hungry_state = F_OKAY;
+        }
+    }
+    if (old_hunger != hungry_state)  {
+        updpack(TRUE, &player);
+        status(TRUE);
+    }
+    wghtchk();
+}
+
+/*
+ * daemon for curing the diseased
+ */
+
+cure_disease()
+{
+    turn_off(player, HASDISEASE);
+    if (off (player, HASINFEST))
+        msg(terse ? "You feel yourself improving"
+                : "You begin to feel yourself improving again");
+}
+
+/*
+ * appear:
+ *      Become visible again
+ */
+ 
+appear()
+{
+    turn_off(player, ISINVIS);
+    PLAYER = VPLAYER;
+    msg("The tingling feeling leaves your body");
+    light(&hero);
+}
+
+/*
+ * dust_appear:
+ *      dust of disappearance wears off
+ */
+ 
+dust_appear()
+{
+    turn_off(player, ISINVIS);
+    PLAYER = VPLAYER;
+    msg("You become visible again");
+    light(&hero);
+}
+
+/*
+ * unchoke:
+ *      the effects of "dust of choking and sneezing" wear off
+ */
+ 
+unchoke()
+{
+    if (!find_slot(unconfuse))
+        turn_off(player, ISHUH);
+    if (!find_slot(sight))
+        turn_off(player, ISBLIND);
+    light(&hero);
+    msg("Your throat and eyes return to normal");
+}
+
+/*
+ * make some potion for the guy in the Alchemy jug
+ */
+ 
+alchemy(obj)
+register struct object *obj;
+{
+    register struct object *tobj = NULL;
+    register struct linked_list *item;
+
+    /*
+     * verify that the object pointer we have still points to an alchemy
+     * jug (hopefully the right one!) because the hero could have thrown
+     * it away
+     */
+    for (item = pack; item != NULL; item = next(item)) {
+        tobj = OBJPTR(item);
+        if (tobj         == obj         && 
+            tobj->o_type == MM          && 
+            tobj->o_which== MM_JUG      &&
+            tobj->o_ac   == JUG_EMPTY   )
+                break;
+    }
+    if (item == NULL) {         /* not in the pack, check the level */
+        for (item = lvl_obj; item != NULL; item = next(item)) {
+            tobj = OBJPTR(item);
+            if (tobj         == obj             && 
+                tobj->o_type == MM              && 
+                tobj->o_which== MM_JUG          &&
+                tobj->o_ac   == JUG_EMPTY       )
+                    break;
+        }
+    }
+    if (item == NULL)   /* can't find it.....too bad */
+        return;
+    
+    switch(rnd(11)) {
+        case 0: tobj->o_ac = P_PHASE;
+        when 1: tobj->o_ac = P_CLEAR;
+        when 2: tobj->o_ac = P_SEEINVIS;
+        when 3: tobj->o_ac = P_HEALING;
+        when 4: tobj->o_ac = P_MFIND;
+        when 5: tobj->o_ac = P_TFIND;
+        when 6: tobj->o_ac = P_HASTE;
+        when 7: tobj->o_ac = P_RESTORE;
+        when 8: tobj->o_ac = P_FLY;
+        when 9: tobj->o_ac = P_SKILL;
+        when 10:tobj->o_ac = P_FFIND;
+    }
+}
+
+/*
+ * otto's irresistable dance wears off 
+ */
+ 
+int
+undance()
+{
+    turn_off(player, ISDANCE);
+    msg ("Your feet take a break.....whew!");
+    return(0);
+}
+
+/* 
+ * if he has our favorite necklace of strangulation then take damage every turn
+ */
+ 
+strangle()
+{
+     if ((pstats.s_hpt -= 6) <= 0) {
+     pstats.s_hpt = -1;
+     death(D_STRANGLE);
+     }
+}
+
+/*
+ * if he has on the gauntlets of fumbling he might drop his weapon each turn
+ */
+ 
+fumble()
+{
+    register struct linked_list *item;
+
+    if (cur_weapon!=NULL                        &&
+        !(cur_weapon->o_flags & ISCURSED)       &&
+        cur_weapon->o_type != RELIC             &&
+        rnd(100)<3) {
+        for (item = pack; item != NULL; item = next(item)) {
+            if (OBJPTR(item) == cur_weapon)
+                break;
+        }
+        if (item != NULL) {
+            switch(mvwinch(stdscr, hero.y, hero.x)) {
+            case PASSAGE: 
+            case SCROLL:
+            case POTION:
+            case WEAPON:
+            case FLOOR:
+            case STICK:
+            case ARMOR:
+            case POOL:
+            case RELIC:
+            case GOLD:
+            case FOOD:
+            case RING:
+            case MM:
+                drop(item);
+                running = FALSE;
+                break;
+            default:
+                break;
+            }
+        }
+    }
+}
+
+/*
+ * This is called each turn the hero has the ring of searching on
+ * it's a lot like trap_look() 
+ */
+ 
+ring_search()
+{
+    if (rnd(75) < (2*dex_compute() + 5*pstats.s_lvl)) search(TRUE, FALSE);
+    else search(FALSE, FALSE);
+}
+
+/*
+ * this is called each turn the hero has the ring of teleportation on
+ */
+ 
+ring_teleport()
+{
+    if (rnd(100) < 3) teleport();
+}
+
+/* 
+ * this is called to charge up the quill of Nagrom
+ */
+ 
+quill_charge()
+{
+    register struct object *tobj = NULL;
+    register struct linked_list *item;
+
+    /*
+     * find the Quill of Nagrom in the hero's pack. It should still be there
+     * because it can't be dropped. If its not then don't do anything.
+     */
+    for (item = pack; item != NULL; item = next(item)) {
+        tobj = OBJPTR(item);
+        if (tobj->o_type == RELIC && tobj->o_which == QUILL_NAGROM)
+                break;
+    }
+    if (item == NULL)
+        return;
+    if (tobj->o_charges < QUILLCHARGES)
+        tobj->o_charges++;
+    fuse (quill_charge, (VOID *)NULL, player.t_ctype == C_MAGICIAN ? 4 : 8, AFTER);
+}
+
+/*
+ * take the skills away gained (or lost) by the potion of skills
+ */
+ 
+unskill()
+{
+    if (pstats.s_lvladj != 0) {
+        pstats.s_lvl -= pstats.s_lvladj;
+        pstats.s_lvladj = 0;
+        msg("You feel your normal skill level return.");
+        status(TRUE);
+    }
+}
+
+/*
+ * charge up the cloak of Emori
+ */
+ 
+int
+cloak_charge(obj)
+register struct object *obj;
+{
+    if (obj->o_charges < 1)
+        obj->o_charges = 1;
+    return(0);
+}
+
+/*
+ * nofire:
+ *      He lost his fire resistance
+ */
+ 
+nofire()
+{
+    if (!ISWEARING(R_FIRE)) {
+        turn_off(player, NOFIRE);
+        msg("Your feeling of fire resistance leaves you");
+    }
+}
+
+/*
+ * nocold:
+ *      He lost his cold resistance
+ */
+ 
+nocold()
+{
+    if (!ISWEARING(R_WARMTH)) {
+        turn_off(player, NOCOLD);
+        msg("Your feeling of warmth leaves you");
+    }
+}
+
+/*
+ * nobolt:
+ *      He lost his protection from lightning
+ */
+ 
+nobolt()
+{
+    turn_off(player, NOBOLT);
+    msg("Your skin loses its bluish tint");
+}
+
+/*
+ * eat_gold:
+ *      an artifact eats gold 
+ */
+ 
+eat_gold(obj)
+register struct object *obj;
+{
+    if (purse == 250)
+        msg("%s.. Bids you to find some more gold. ", inv_name(obj, FALSE));
+    if (purse == 100)
+        msg("%s.. Demands that you find more gold! ", inv_name(obj, FALSE));
+    if (purse == 50)
+        msg("%s.. Commands you to find more gold!! ", inv_name(obj, FALSE));
+    if (purse == 0) {
+    if (rnd(10) >= 7)
+        msg("You feel the artifact gnawing away... ");
+        if (--pstats.s_hpt < 1) {
+        pstats.s_hpt = -1;
+            death(D_RELIC);
+    }
+    }
+    else
+        purse--;
+}
+
+/*
+ * give the hero back some spell points
+ */
+ 
+spell_recovery()
+{
+    int time;
+
+    time = SPELLTIME - max(17-pstats.s_intel, 0);
+    time = max(time, 5);
+    if (spell_power > 0) spell_power--;
+    fuse(spell_recovery, (VOID *)NULL, time, AFTER);
+}
+
+/*
+ * give the hero back some prayer points
+ */
+ 
+prayer_recovery()
+{
+    int time;
+
+    time = SPELLTIME - max(17-pstats.s_wisdom, 0);
+    time = max(time, 5);
+    if (pray_time > 0) pray_time--;
+    fuse(prayer_recovery, (VOID *)NULL, time, AFTER);
+}
+
+/*
+ * give the hero back some chant points
+ */
+ 
+chant_recovery()
+{
+    int time;
+
+    time = SPELLTIME - max(17-pstats.s_wisdom, 0);
+    time = max(time, 5);
+    if (chant_time > 0) chant_time--;
+    fuse(chant_recovery, (VOID *)NULL, time, AFTER);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xrogue/eat.c	Tue Apr 21 08:55:20 2015 -0400
@@ -0,0 +1,166 @@
+/*
+    eat.c  -  Functions for dealing with digestion
+
+    XRogue: Expeditions into the Dungeons of Doom
+    Copyright (C) 1991 Robert Pietkivitch
+    All rights reserved.
+    
+    Based on "Advanced Rogue"
+    Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka and AT&T
+    All rights reserved.
+
+    Based on "Rogue: Exploring the Dungeons of Doom"
+    Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
+    All rights reserved.
+    
+    See the file LICENSE.TXT for full copyright and licensing information.
+*/
+
+#include <curses.h>
+#include "rogue.h"
+
+/*
+ * eat:
+ *      He wants to eat something, so let him try
+ */
+
+eat()
+{
+    register struct linked_list *item;
+    int which;
+    unsigned long temp;
+
+    if (player.t_action != C_EAT) {
+        if ((item = get_item(pack, "eat", FOOD, FALSE, FALSE)) == NULL)
+            return;
+
+        player.t_using = item;  /* Remember what it is */
+        player.t_action = C_EAT;        /* We are eating */
+        which = (OBJPTR(item))->o_which;
+        player.t_no_move = max(foods[which].mi_food/100, 1) * movement(&player);
+        return;
+    }
+
+    /* We have waited our time, let's eat the food */
+    item = player.t_using;
+    player.t_using = NULL;
+    player.t_action = A_NIL;
+
+    which = (OBJPTR(item))->o_which;
+    if ((food_left += foods[which].mi_food) > STOMACHSIZE)
+        food_left = STOMACHSIZE;
+    del_pack(item);
+    if (hungry_state == F_SATIATED && food_left == STOMACHSIZE && rnd(4) == 1) {
+        pstats.s_hpt = -1;
+        msg ("Cough!  Ack!  You choke on all that food and die!  --More--");
+        wait_for(' ');
+        death(D_FOOD_CHOKE);
+    }
+    if (food_left >= STOMACHSIZE-MORETIME) {
+        hungry_state = F_SATIATED;
+        msg ("You have trouble getting that food down!");
+        msg ("Your stomach feels like it's about to burst!");
+    }
+    else if (which != E_SLIMEMOLD) {
+        hungry_state = F_OKAY;
+        switch (rnd(10)) {
+        case 0: msg("Yuck, what a foul tasting %s! ", foods[which].mi_name);
+        when 1: msg("Mmmm, what a tasty %s. ", foods[which].mi_name);
+        when 2: msg("Wow, what a scrumptious %s! ", foods[which].mi_name);
+        when 3: msg("Hmmm, %s heaven! ", foods[which].mi_name);
+        when 4: msg("You've eaten better %s. ", foods[which].mi_name);
+        when 5: msg("You smack your lips ");
+        when 6: msg("Yum-yum-yum ");
+        when 7: msg("Gulp! ");
+        when 8: msg("Your tongue flips out! ");
+        when 9: msg("You lick your chin ");
+        }
+    }
+    updpack(TRUE, &player);
+    switch(which) {
+    case E_WHORTLEBERRY:    /* add 1 to intelligence */
+        (*add_abil[A_INTELLIGENCE])(1);
+    when E_SWEETSOP:    /* add 1 to strength */
+    case E_SOURSOP: /* add 1 to strength */
+        (*add_abil[A_STRENGTH])(1);
+    when E_SAPODILLA:   /* add 1 to wisdom */
+        (*add_abil[A_WISDOM])(1);
+    when E_APPLE:   /* add 1 to dexterity */
+        (*add_abil[A_DEXTERITY])(1);
+    when E_PRICKLEY:    /* add 1 to constitution */
+        (*add_abil[A_CONSTITUTION])(1);
+    when E_PEACH:   /* add 1 to charisma */
+        (*add_abil[A_CHARISMA])(1);
+    when E_PITANGA: /* add 1 hit point */
+        max_stats.s_hpt++;
+        pstats.s_hpt = max_stats.s_hpt;
+        msg("You feel a bit tougher now. ");
+    when E_HAGBERRY:    /* armor class */
+    case E_JABOTICABA:  /* armor class */
+        pstats.s_arm--;
+        msg("Your skin feels more resilient now. ");
+    when E_STRAWBERRY:  /* add 10% experience points */
+    case E_RAMBUTAN:    /* add 10% experience points */
+        temp = pstats.s_exp/100 + 10;
+        pstats.s_exp += temp;
+        msg("You feel slightly more experienced now. ");
+        check_level();
+    when E_DEWBERRY:    /* encourage him to do more magic */
+        if (chant_time > 0) {
+            chant_time -= 80;
+            if (chant_time < 0)
+                chant_time = 0;
+            msg("You feel you have more chant ability. ");
+        }
+        if (pray_time > 0) {
+            pray_time -= 80;
+            if (pray_time < 0)
+                pray_time = 0;
+            msg("You feel you have more prayer ability. ");
+        }
+        if (spell_power > 0) {
+            spell_power -= 80;
+            if (spell_power < 0)
+                spell_power = 0;
+            msg("You feel you have more spell casting ability. ");
+        }
+    when E_CANDLEBERRY: /* cure him */
+        if (on(player, HASINFEST) || 
+            on(player, HASDISEASE)|| 
+            on(player, DOROT)) {
+            if (on(player, HASDISEASE)) {
+                extinguish(cure_disease);
+                cure_disease();
+            }
+            if (on(player, HASINFEST)) {
+                msg("You feel yourself improving. ");
+                turn_off(player, HASINFEST);
+                infest_dam = 0;
+            }
+            if (on(player, DOROT)) {
+                msg("You feel your skin returning to normal. ");
+                turn_off(player, DOROT);
+            }
+        }
+    when E_SLIMEMOLD: /* monster food */
+    msg("The slime-mold quivers around in your mouth. ");
+        player.t_no_move = 3*movement(&player);
+        if (off(player, HASDISEASE)) {
+            if (ISWEARING(R_HEALTH) || player.t_ctype == C_PALADIN ||
+                player.t_ctype == C_RANGER) {
+        msg("You feel lousy. ");
+            }
+            else {
+                turn_on(player, HASDISEASE);
+                fuse(cure_disease, (VOID *)NULL, roll(HEALTIME,SICKTIME),AFTER);
+                msg("You become ill. ");
+            }
+    }
+        pstats.s_const -= rnd(2)+1;
+    if (pstats.s_const <= 3) pstats.s_const = 3;
+    
+    otherwise: /* not all the foods have to do something */
+        break;
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xrogue/effects.c	Tue Apr 21 08:55:20 2015 -0400
@@ -0,0 +1,721 @@
+/*
+    effects.c  -  functions for dealing with appllying effects to monsters
+
+    XRogue: Expeditions into the Dungeons of Doom
+    Copyright (C) 1991 Robert Pietkivitch
+    All rights reserved.
+    
+    Based on "Advanced Rogue"
+    Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka and AT&T
+    All rights reserved.
+
+    Based on "Rogue: Exploring the Dungeons of Doom"
+    Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
+    All rights reserved.
+    
+    See the file LICENSE.TXT for full copyright and licensing information.
+*/
+
+#include <curses.h>
+#include "rogue.h"
+
+/*
+ * effect:
+ *      Check for effects of one thing hitting another thing.  Return
+ *      the reason code if the defender is killed.  Otherwise return 0.
+ */
+
+effect(att, def, weap, thrown, see_att, see_def)
+register struct thing *att, *def;
+struct object *weap;
+bool thrown;
+register bool see_att, see_def;
+{
+    register bool att_player, def_player;
+    char attname[LINELEN+1], defname[LINELEN+1];
+
+    /* See if the attacker or defender is the player */
+    att_player = (att == &player);
+    def_player = (def == &player);
+
+    /*
+     * If the player could see the attacker or defender, they can't
+     * surprise anymore (don't bother checking if they could).
+     */
+    if (see_att) turn_off(*att, CANSURPRISE);
+    if (see_def) turn_off(*def, CANSURPRISE);
+
+    /* What are the attacker and defender names? */
+    if (att_player) strcpy(attname, "you");
+    else {
+        if (see_att) strcpy(attname, monster_name(att));
+        else strcpy(attname, "something");
+    }
+
+    if (def_player) strcpy(defname, "you");
+    else {
+        if (see_def) strcpy(defname, monster_name(def));
+        else strcpy(defname, "something");
+    }
+
+    /*
+     * See what happens to the attacker first.  We can skip this
+     * whole section, however, if the defender is the player.
+     * Nothing happens (yet) to anyone just for hitting the player.
+     */
+    if (!def_player) {
+        if (!thrown) {  /* Some things require a direct hit. */
+            /*
+             * If the attacker hits a rusting monster, The weapon
+             * may be damaged
+             */
+            if (on(*def, CANRUST)       && weap                         &&
+                weap->o_type != RELIC   && (weap->o_flags & ISMETAL)    &&
+                !(weap->o_flags & ISPROT)) {
+                    if ((weap->o_hplus < 1 && weap->o_dplus < 1) ||
+                        roll(1,20) < weap->o_hplus+weap->o_dplus+10) {
+                            if (rnd(100) < 50) weap->o_hplus--;
+                            else               weap->o_dplus--;
+                            if (att_player)
+                                msg(terse ? "Your %s weakens!"
+                                          : "Your %s gets weaker!",
+                                    weaps[weap->o_which].w_name);
+                    }
+            }
+        }
+                
+        /* If the attacker hit something that shrieks, wake the dungeon */
+        if (on(*def, CANSHRIEK)) {
+            if (see_def)
+                msg("%s emits an ear piercing shriek! ", prname(defname, TRUE));
+            else
+                msg("You hear an ear piercing shriek!");
+
+            /* Friendly charactors should be immune */
+            if (player.t_ctype == C_PALADIN ||
+                player.t_ctype == C_RANGER  || player.t_ctype == C_MONK)
+                    aggravate(TRUE, FALSE);
+            else
+                aggravate(TRUE, TRUE);
+        }
+
+        /*
+         * does the creature explode when hit?
+         */
+        if (on(*def, CANEXPLODE)) {
+            if (see_def) msg("%s explodes!", prname(defname, TRUE));
+            else msg("You hear a tremendous explosion!");
+            explode(def);
+            if (pstats.s_hpt < 1) {
+        pstats.s_hpt = -1;
+                death(def->t_index);
+        }
+        }
+    }
+
+    /*
+     * Now let's see what happens to the defender.  Start out with
+     * the things that everyone can do.  Then exit if the attacker
+     * is the player.
+     */
+    if (!thrown) {
+        /* 
+         * Can the player confuse? 
+         */
+        if (on(*att, CANHUH) && att_player) {
+            msg("Your hands return to normal. ");
+            if (off(*def, ISCLEAR) && 
+               (off(*def, ISUNIQUE) || !save(VS_MAGIC, def, 0))) {
+                if (see_def) msg("%s appears confused!", prname(defname, TRUE));
+                turn_on(*def, ISHUH);
+            }
+            turn_off(*att, CANHUH);
+        }
+
+        /* Return now if the attacker is the player. */
+        if (att_player) return(0);
+
+        /*
+         * Some monsters may take half your hit points
+         */
+        if (on(*att, CANSUCK) && !save(VS_MAGIC, def, 0)) {
+            if (def->t_stats.s_hpt == 1) return(att->t_index); /* Killed! */
+            else {
+                def->t_stats.s_hpt /= 2;
+                if (def_player)
+                    msg("Your life force is being drained out of you.");
+            }
+        }
+
+        /*
+         * If a hugging monster hits, it may SQUEEEEEEEZE.
+         */
+        if (on(*att, CANHUG)) {
+            if (roll(1,20) >= 18 || roll(1,20) >= 18) {
+                if (def_player)
+                    msg("%s squeezes itself nastily against you!",
+                                prname(attname, TRUE));
+                else if (see_att)
+                    msg("%s squeezes real hard!", prname(attname, TRUE));
+
+                if ((def->t_stats.s_hpt -= roll(2,8)) <= 0)
+                    return(att->t_index);
+            }
+        }
+
+        /*
+         * Some monsters have poisonous bites.
+         */
+        if (on(*att, CANPOISON) && !save(VS_POISON, def, 0)) {
+            if (def_player) {
+                if (ISWEARING(R_SUSABILITY))
+                    msg(terse ? "Sting has no effect."
+                              : "A sting momentarily weakens your arm.");
+                else {
+                    chg_str(-1);
+                    msg(terse ? "A sting has weakened you." :
+                    "You get stung in the arm!  You feel weaker. ");
+                }
+            }
+            else {
+                /* Subtract a strength point and see if it kills it */
+                if (--def->t_stats.s_str <= 0) return(D_STRENGTH);
+            }
+        }
+
+        /*
+         * Turning to stone:
+         */
+        if (on(*att, TOUCHSTONE)) {
+            if (def_player) turn_off(*att, TOUCHSTONE);
+            if (on(*def, CANINWALL)) {
+                if (def_player)
+                    msg("%s's touch has no effect.", prname(attname, TRUE));
+            }
+            else {
+                if (!save(VS_PETRIFICATION, def, 0) && rnd(100) < 10) {
+                    if (def_player) {
+                        msg("Your body begins to solidify.. ");
+                        msg("You are transformed into stone!! --More--");
+                        wait_for(' ');
+                        return(D_PETRIFY);
+                    }
+                    else {
+                        /* The monster got stoned! */
+                        turn_on(*def, ISSTONE);
+                        turn_off(*def, ISRUN);
+                        turn_off(*def, ISINVIS);
+                        turn_off(*def, ISDISGUISE);
+                        if (def->t_stats.s_intel > 15)
+                            msg("%s staggers.. ", prname(defname, TRUE));
+                        else if (see_def)
+                            msg("%s turns to stone! ", prname(defname, TRUE));
+                        else if (cansee(unc(def->t_pos)))
+                            msg("A statue appears out of nowhere! ");
+                    }
+                }
+                else if (def->t_action != A_FREEZE) {
+                    if (def_player)
+                        msg("%s's touch stiffens your limbs.",
+                                        prname(attname, TRUE));
+                    else if (see_def)
+                        msg("%s appears to freeze over.", prname(defname, TRUE));
+
+                    def->t_no_move += movement(def) * STONETIME;
+                    def->t_action = A_FREEZE;
+                }
+            }
+        }
+
+        /*
+         * Wraiths might drain energy levels
+         */
+        if ((on(*att, CANDRAIN) || on(*att, DOUBLEDRAIN)) && 
+            !save(VS_POISON, def, 3-(att->t_stats.s_lvl/5))) {
+            if (def_player) {
+                lower_level(att->t_index);
+                if (on(*att, DOUBLEDRAIN)) lower_level(att->t_index);
+                turn_on(*att, DIDDRAIN);  
+            }
+            else {
+                def->t_stats.s_hpt -= roll(1, 8);
+                def->t_stats.s_lvl--;
+                if (on(*att, DOUBLEDRAIN)) {
+                    def->t_stats.s_hpt -= roll(1, 8);
+                    def->t_stats.s_lvl--;
+                }
+                if (see_def)
+                    msg("%s appears less skillful.", prname(defname, TRUE));
+
+                /* Did it kill it? */
+                if (def->t_stats.s_hpt <= 0 ||
+                    def->t_stats.s_lvl <= 0)
+                    return(att->t_index);
+            }
+        }
+
+        /*
+         * Paralyzation:
+         */
+        if (on(*att, CANPARALYZE) && def->t_action != A_FREEZE) {
+            if (def_player) turn_off(*att, CANPARALYZE);
+            if (!save(VS_PARALYZATION, def, 0)) {
+                if (on(*def, CANINWALL)) {
+                    if (def_player)
+                        msg("%s's touch has no effect.", prname(attname, TRUE));
+                }
+                else {
+                    if (def_player)
+                        msg("%s's touch paralyzes you.", prname(attname, TRUE));
+                    else if (see_def)
+                        msg("%s appears to freeze over!", prname(defname, TRUE));
+
+                    def->t_no_move += movement(def) * FREEZETIME;
+                    def->t_action = A_FREEZE;
+                }
+            }
+        }
+
+        /*
+         * Painful wounds make the defendant faint
+         */
+         if (on(*att, CANPAIN) && def->t_action != A_FREEZE) {
+            if (def_player) turn_off(*att, CANPAIN);
+            if (!ISWEARING(R_ALERT) && !save(VS_POISON, def, 0)) {
+                    if (def_player)
+                        msg("You faint from the painful wound!");
+                    else if (see_def)
+                        msg("%s appears to faint!", prname(defname, TRUE));
+
+                    def->t_no_move += movement(def) * PAINTIME;
+                    def->t_action = A_FREEZE;
+            }
+        }
+
+        /*
+         * Some things currently affect only the player.  Let's make
+         * a check here so we don't have to check for each thing.
+         */
+        if (def_player) {
+        /*
+         * Stinking monsters make the defender weaker (to hit).  For now
+         * this will only affect the player.  We may later add the HASSTINK
+         * effect to monsters, too.
+         */
+            if (on(*att, CANSTINK)) {
+                turn_off(*att, CANSTINK);
+                if (!save(VS_POISON, def, 0)) {
+                    msg("The stench of %s sickens you.  Blech!",
+                                prname(attname, FALSE));
+                    if (on(player, HASSTINK)) lengthen(unstink, STINKTIME);
+                    else {
+                        turn_on(player, HASSTINK);
+                        fuse(unstink, (VOID *)NULL, STINKTIME, AFTER);
+                    }
+                }
+            }
+
+            /*
+             * Chilling monster reduces strength each time.  This only
+             * affects the player for now because of its temporary nature.
+             */
+            if (on(*att, CANCHILL)) {
+                if (!ISWEARING(R_SUSABILITY) && !save(VS_POISON, def, 0)) {
+                    msg("You cringe at %s's chilling touch.",
+                                prname(attname, FALSE));
+                    chg_str(-1);
+                    if (lost_str++ == 0)
+                        fuse(res_strength, (VOID *)NULL, CHILLTIME, AFTER);
+                    else lengthen(res_strength, CHILLTIME);
+                }
+            }
+
+            /*
+             * Itching monsters reduce dexterity (temporarily).  This only
+             * affects the player for now because of its temporary nature.
+             */
+            if (on(*att, CANITCH) && !save(VS_POISON, def, 0)) {
+                msg("The claws of %s scratch you!", prname(attname, FALSE));
+                if (ISWEARING(R_SUSABILITY)) {
+                    msg("The scratch has no effect.");
+                }
+                else {
+                    (*add_abil[A_DEXTERITY])(-1);
+                }
+            }
+
+            /*
+             * If a disease-carrying monster hits, there is a chance the
+             * defender will catch the disease.  This only applies to the
+             * player for now because of the temporary nature. Don't affect
+             * the Ranger or Paladin.
+             */
+            if (on(*att, CANDISEASE) &&
+                (rnd(def->t_stats.s_const) < att->t_stats.s_lvl) &&
+                off(*def, HASDISEASE)) {
+                    if (ISWEARING(R_HEALTH)             ||
+                        player.t_ctype == C_PALADIN     ||
+                        player.t_ctype == C_RANGER) {
+                            msg("The wound heals quickly.");
+                    }
+                    else {
+                        turn_on(*def, HASDISEASE);
+                        fuse(cure_disease, (VOID *)NULL, roll(HEALTIME,SICKTIME), AFTER);
+                        msg(terse ? "You have been diseased!"
+                            : "You have contracted an annoying disease!");
+                    }
+            }
+
+            /*
+             * If a rusting monster hits, you lose armor.  This only applies to
+             * the player because monsters don't wear armor (for now).
+             */
+            if (on(*att, CANRUST)) { 
+                if (cur_armor != NULL                           &&
+                    cur_armor->o_which != LEATHER               &&
+                    cur_armor->o_which != STUDDED_LEATHER       &&
+                    cur_armor->o_which != PADDED_ARMOR          &&
+                    !(cur_armor->o_flags & ISPROT)              &&
+                    cur_armor->o_ac < def->t_stats.s_arm+1) {
+                        msg(terse ? "Your armor weakens."
+                            : "Your armor becomes weaker.");
+                        cur_armor->o_ac++;
+                }
+                if (cur_misc[WEAR_BRACERS] != NULL              &&
+                    cur_misc[WEAR_BRACERS]->o_ac > 0            &&
+                    !(cur_misc[WEAR_BRACERS]->o_flags & ISPROT)) {
+                        cur_misc[WEAR_BRACERS]->o_ac--;
+                        if (cur_misc[WEAR_BRACERS]->o_ac == 0) {
+                            register struct linked_list *item;
+
+                            for (item=pack; item!=NULL; item=next(item)) {
+                                if (OBJPTR(item) == cur_misc[WEAR_BRACERS]) {
+                                    detach(pack, item);
+                                    o_discard(item);
+                                    break;
+                                }
+                            }
+                            msg ("Your bracers crumble apart!");
+                            cur_misc[WEAR_BRACERS] = NULL;
+                            inpack--;
+                        }
+                        else {
+                            msg("Your bracers weaken!");
+                        }
+                }
+            }
+
+            /*
+             * If can dissolve and hero has leather type armor.  This
+             * also only applies to the player for now because of the
+             * armor.
+             */
+            if (on(*att, CANDISSOLVE) && cur_armor != NULL &&
+                (cur_armor->o_which == LEATHER            ||
+                 cur_armor->o_which == STUDDED_LEATHER    ||
+                 cur_armor->o_which == PADDED_ARMOR)      &&
+                !(cur_armor->o_flags & ISPROT) &&
+                cur_armor->o_ac < def->t_stats.s_arm+1) {
+                msg(terse ? "Your armor dissolves!"
+                    : "Your armor appears to have dissolved!");
+                cur_armor->o_ac++;
+            }
+
+            /*
+             * If an infesting monster hits you, you get a parasite or rot.
+             * This will only affect the player until we figure out how to
+             * make it affect monsters.  Don't affect the Monk.
+             */
+            if (on(*att, CANINFEST) &&
+                rnd(def->t_stats.s_const) < att->t_stats.s_lvl) {
+                if (ISWEARING(R_HEALTH) || player.t_ctype == C_MONK) {
+                        msg("The wound heals quickly.");
+                }
+                else {
+                    turn_off(*att, CANINFEST);
+                    msg(terse ? "You have been infested."
+                        : "You have contracted a parasitic infestation!");
+                    infest_dam++;
+                    turn_on(*def, HASINFEST);
+                }
+            }
+
+            /*
+             * Does it take wisdom away?  This currently affects only
+             * the player because of its temporary nature.
+             */
+            if (on(*att, TAKEWISDOM)            && 
+                !save(VS_MAGIC, def, 0) &&
+                !ISWEARING(R_SUSABILITY)) {
+                        (*add_abil[A_WISDOM])(-1);
+            }
+
+            /*
+             * Does it take intelligence away?  This currently affects
+             * only the player because of its temporary nature.
+             */
+            if (on(*att, TAKEINTEL)             && 
+                !save(VS_MAGIC, &player, 0)     &&
+                !ISWEARING(R_SUSABILITY)) {
+                        (*add_abil[A_INTELLIGENCE])(-1);
+            }
+
+            /*
+             * Cause fear by touching.  This currently affects only
+             * the player until we figure out how we want it to
+             * affect monsters.
+             */
+            if (on(*att, TOUCHFEAR)) {
+                turn_off(*att, TOUCHFEAR);
+                if (!ISWEARING(R_HEROISM)       &&
+                    !save(VS_WAND, def, 0)      &&
+                    !(on(*def, ISFLEE) && (def->t_dest == &att->t_pos))) {
+                        turn_on(*def, ISFLEE);
+                        def->t_dest = &att->t_pos;
+                        msg("%s's touch terrifies you!", prname(attname, TRUE));
+
+                        /* It is okay to turn tail */
+                        if (!def_player) def->t_oldpos = def->t_pos;
+                }
+            }
+
+            /*
+             * Make the hero dance (as in otto's irresistable dance)
+             * This should be fairly easy to do to monsters, but
+             * we'll restrict it to players until we decide what to
+             * do about the temporary nature.
+             */
+            if (on(*att, CANDANCE)              && 
+                !on(*def, ISDANCE)              &&
+                def->t_action != A_FREEZE       &&
+                !save(VS_MAGIC, def, -4)) {
+                    turn_off(*att, CANDANCE);
+                    turn_on(*def, ISDANCE);
+                    msg("You begin to dance uncontrollably!");
+                    fuse(undance, (VOID *)NULL, roll(2,4), AFTER);
+            }
+
+            /*
+             * Suffocating our hero.  Monsters don't get suffocated.
+             * That's too hard for now.
+             */
+            if (on(*att, CANSUFFOCATE)          && 
+                !ISWEARING(R_FREEDOM)           && 
+                rnd(100) < 30                   &&
+                (find_slot(suffocate) == 0)) {
+                turn_on(*att, DIDSUFFOCATE);
+                msg("%s is beginning to suffocate you!", prname(attname, TRUE));
+                fuse(suffocate, (VOID *)NULL, roll(9,3), AFTER);
+            }
+
+            /*
+             * some creatures stops the poor guy from moving.
+             * How can we do this to a monster?
+             */
+            if (on(*att,CANHOLD) && off(*att,DIDHOLD) && !ISWEARING(R_FREEDOM)){
+                turn_on(*def, ISHELD);
+                turn_on(*att, DIDHOLD);
+                hold_count++;
+            }
+
+            /*
+             * Sucker will suck blood and run.  This
+             * should be easy to have happen to a monster,
+             * but we have to decide how to handle the fleeing.
+             */
+            if (on(*att, CANDRAW)) {
+                turn_off(*att, CANDRAW);
+                turn_on(*att, ISFLEE);
+                msg("%s sates itself with your blood!", prname(attname, TRUE));
+                if ((def->t_stats.s_hpt -= 12) <= 0) return(att->t_index);
+
+                /* It is okay to turn tail */
+                att->t_oldpos = att->t_pos;
+            }
+
+            /*
+             * Bad smell will force a reduction in strength.
+             * This will happen only to the player because of
+             * the temporary nature.
+             */
+            if (on(*att, CANSMELL)) {
+                turn_off(*att, CANSMELL);
+                if (save(VS_MAGIC, def, 0) || ISWEARING(R_SUSABILITY)) {
+                    if (terse)
+                        msg("Pheww!");
+                    else
+                        msg("You smell an unpleasant odor.  Phew!");
+                    }
+
+                else {
+                    int odor_str = -(rnd(6)+1);
+
+                    msg("You are overcome by a foul odor!");
+                    if (lost_str == 0) {
+                        chg_str(odor_str);
+                        fuse(res_strength, (VOID *)NULL, SMELLTIME, AFTER);
+                        lost_str -= odor_str;
+                    }
+                    else lengthen(res_strength, SMELLTIME);
+                }
+            }
+
+            /*
+             * The monsters touch slows the defendant down.
+             */
+             if (on(*att, TOUCHSLOW)) {
+                turn_off(*att, TOUCHSLOW);
+                if (!save(VS_PARALYZATION, def, 0)) 
+                        add_slow();
+            }
+
+            /*
+             * Rotting only affects the player.  Don't affect the Monk,
+             * Paladin, or Ranger.
+             */
+            if (on(*att, CANROT)) {
+                if (!ISWEARING(R_HEALTH)        && 
+                    player.t_ctype != C_MONK    &&
+                    player.t_ctype != C_RANGER  &&
+                    player.t_ctype != C_PALADIN &&
+                    !save(VS_POISON, def, 0)    && 
+                    off(*def, DOROT)) {
+                    turn_on(*def, DOROT);
+                    msg("You feel your skin starting to rot and peel away!");
+                }
+            }
+
+            /*
+             * Monsters should be able to steal gold from anyone,
+             * but until this is rewritten, they will only steal
+             * from the player (tough break).
+             */
+            if (on(*att, STEALGOLD)) {
+                /*
+                 * steal some gold
+                 */
+                register long lastpurse;
+                register struct linked_list *item;
+                register struct object *obj;
+
+                lastpurse = purse;
+                purse -= (GOLDCALC * 2);
+                if (!save(VS_MAGIC, def, att->t_stats.s_lvl/10)) {
+                    if (on(*att, ISUNIQUE))
+                        purse -= (GOLDCALC * 5);
+                    else
+            purse -= (GOLDCALC * 3);
+                }
+                if (purse < 0)
+                    purse = 0;
+                if (purse != lastpurse) {
+                    msg("You lost some gold! ");
+
+                    /* Give the gold to the thief */
+                    for (item=att->t_pack; item != NULL; item=next(item)) {
+                        obj = OBJPTR(item);
+                        if (obj->o_type == GOLD) {
+                            obj->o_count += lastpurse - purse;
+                            break;
+                        }
+                    }
+
+                    /* Did we do it? */
+                    if (item == NULL) { /* Then make some */
+                        item = new_item(sizeof *obj);
+                        obj = OBJPTR(item);
+                        obj->o_type = GOLD;
+                        obj->o_count = lastpurse - purse;
+                        obj->o_hplus = obj->o_dplus = 0;
+                        strcpy(obj->o_damage,"0d0");
+                        strcpy(obj->o_hurldmg,"0d0");
+                        obj->o_ac = 11;
+                        obj->contents = NULL;
+                        obj->o_group = 0;
+                        obj->o_flags = 0;
+                        obj->o_mark[0] = '\0';
+                        obj->o_pos = att->t_pos;
+
+                        attach(att->t_pack, item);
+                    }
+                }
+
+                turn_on(*att, ISFLEE);
+                turn_on(*att, ISINVIS);
+
+                /* It is okay to turn tail */
+                att->t_oldpos = att->t_pos;
+            }
+        }
+
+        /*
+         * Stealing happens last since the monster disappears
+         * after the act.
+         */
+        if (on(*att, STEALMAGIC)) {
+            register struct linked_list *list, *steal;
+            register struct object *obj;
+            register int nobj;
+
+            /*
+             * steal a magic item, look through the pack
+             * and pick out one we like.
+             */
+            steal = NULL;
+            for (nobj = 0, list = def->t_pack; list != NULL; list = next(list))
+            {
+                obj = OBJPTR(list);
+                if (!is_current(obj)     &&
+                    list != def->t_using &&
+                    obj->o_type != RELIC &&
+                    is_magic(obj)        && 
+                    rnd(++nobj) == 0)
+                        steal = list;
+            }
+            if (steal != NULL)
+            {
+                register struct object *obj;
+                struct linked_list *item;
+
+                obj = OBJPTR(steal);
+                if (on(*att, ISUNIQUE))
+                    monsters[att->t_index].m_normal = TRUE;
+                item = find_mons(att->t_pos.y, att->t_pos.x);
+
+                killed(item, FALSE, FALSE, FALSE); /* Remove the attacker */
+
+                if (obj->o_count > 1 && obj->o_group == 0) {
+                    register int oc;
+
+                    oc = --(obj->o_count);
+                    obj->o_count = 1;
+                    if (def_player)
+                        msg("%s stole %s!", prname(attname, TRUE),
+                                        inv_name(obj, TRUE));
+                    obj->o_count = oc;
+                }
+                else {
+                    if (def_player) {
+                        msg("%s stole %s!", prname(attname, TRUE),
+                                        inv_name(obj, TRUE));
+
+                        /* If this is a relic, clear its holding field */
+                        if (obj->o_type == RELIC)
+                            cur_relic[obj->o_which] = 0;
+
+                        inpack--;
+                    }
+
+                    detach(def->t_pack, steal);
+                    o_discard(steal);
+                }
+
+                updpack(FALSE, def);
+            }
+        }
+    }
+
+    /* Didn't kill the defender */
+    return(0);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xrogue/encumb.c	Tue Apr 21 08:55:20 2015 -0400
@@ -0,0 +1,202 @@
+/*
+    encumb.c - Stuff to do with encumberance
+    
+    XRogue: Expeditions into the Dungeons of Doom
+    Copyright (C) 1991 Robert Pietkivitch
+    All rights reserved.
+    
+    Based on "Advanced Rogue"
+    Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka and AT&T
+    All rights reserved.
+
+    See the file LICENSE.TXT for full copyright and licensing information.
+*/
+
+#include <curses.h>
+#include "rogue.h"
+
+/*
+ * updpack:
+ *      Update his pack weight and adjust fooduse accordingly
+ */
+
+updpack(getmax, tp)
+int getmax;
+struct thing *tp;
+{
+
+        reg int topcarry, curcarry;
+
+        if (getmax)
+            tp->t_stats.s_carry = totalenc(tp); /* get total encumb */
+        curcarry = packweight(tp);              /* get pack weight */
+
+        /* Only update food use for the player (for now) */
+        if (tp == &player) {
+            topcarry = tp->t_stats.s_carry / 5; /* 20% of total carry */
+            if(curcarry > 4 * topcarry) {
+                if(rnd(100) < 80)
+                    foodlev = 3;                        /* > 80% of pack */
+            } else if(curcarry > 3 * topcarry) {
+                if(rnd(100) < 60)
+                    foodlev = 2;                        /* > 60% of pack */
+            } else
+                foodlev = 1;                    /* <= 60% of pack */
+        }
+        tp->t_stats.s_pack = curcarry;          /* update pack weight */
+}
+
+
+/*
+ * packweight:
+ *      Get the total weight of the hero's pack
+ */
+
+packweight(tp)
+register struct thing *tp;
+{
+        reg struct object *obj;
+        reg struct linked_list *pc;
+        reg int weight;
+
+        weight = 0;
+        for (pc = tp->t_pack ; pc != NULL ; pc = next(pc)) {
+            obj = OBJPTR(pc);
+            weight += itemweight(obj);
+        }
+        if (weight < 0)         /* in case of amulet */
+             weight = 0;
+
+        /* If this is the player, is he wearing a ring of carrying? */
+        if (tp == &player && ISWEARING(R_CARRY)) {
+            register int temp, i;
+
+            temp = 0;
+            for (i=0; i<NUM_FINGERS; i++) {
+                if (cur_ring[i] != NULL && cur_ring[i]->o_which == R_CARRY) {
+                    if (cur_ring[i]->o_flags & ISCURSED) temp--;
+                    else temp += 2;
+                }
+            }
+            weight -= (temp * weight) / 4;
+        }
+
+        return(weight);
+}
+
+/*
+ * itemweight:
+ *      Get the weight of an object
+ */
+
+itemweight(wh)
+reg struct object *wh;
+{
+        reg int weight;
+        reg int ac;
+
+        weight = wh->o_weight;          /* get base weight */
+        switch(wh->o_type) {
+            case ARMOR:
+                /*
+                 * subtract 10% for each enchantment
+                 * this will add weight for negative items
+                 */
+                ac = armors[wh->o_which].a_class - wh->o_ac;
+                weight = ((weight*10) - (weight*ac)) / 10;
+                if (weight < 0) weight = 0;
+            when WEAPON:
+                if ((wh->o_hplus + wh->o_dplus) > 0)
+                        weight /= 2;
+        }
+        if(wh->o_flags & ISCURSED)
+                weight += weight / 5;   /* 20% more for cursed */
+        weight *= wh->o_count;
+        return(weight);
+}
+
+/*
+ * playenc:
+ *      Get hero's carrying ability above norm
+ */
+
+playenc(tp)
+register struct thing *tp;
+{
+        register int strength;
+
+        if (tp == &player) strength = str_compute();
+        else strength = tp->t_stats.s_str;
+
+        return ((strength-8)*50);
+}
+
+/*
+ * totalenc:
+ *      Get total weight that the hero can carry
+ */
+
+totalenc(tp)
+register struct thing *tp;
+{
+        reg int wtotal;
+
+        wtotal = NORMENCB + playenc(tp);
+        if (tp == &player) switch(hungry_state) {
+                case F_SATIATED:
+                case F_OKAY:
+                case F_HUNGRY:  ;                       /* no change */
+                when F_WEAK:    wtotal -= wtotal / 10;  /* 10% off weak */
+                when F_FAINT:   wtotal /= 2;            /* 50% off faint */
+        }
+        return(wtotal);
+}
+
+/*
+ * whgtchk:
+ *      See if the hero can carry his pack
+ */
+
+wghtchk()
+{
+        reg int dropchk, err = TRUE;
+        reg char ch;
+        int wghtchk();
+
+        inwhgt = TRUE;
+        if (pstats.s_pack > pstats.s_carry) {
+            ch = mvwinch(stdscr, hero.y, hero.x);
+            if((ch != FLOOR && ch != PASSAGE)) {
+                extinguish(wghtchk);
+                fuse(wghtchk, (VOID *)NULL, 1, AFTER);
+                inwhgt = FALSE;
+                return;
+            }
+            extinguish(wghtchk);
+            msg("Your pack is far too heavy for you.. ");
+            do {
+                dropchk = drop((struct linked_list *)NULL);
+                if(dropchk == 0) {
+                    mpos = 0;
+                    msg("You must drop something");
+                }
+                if(dropchk == TRUE)
+                    err = FALSE;
+            } while(err);
+        }
+        inwhgt = FALSE;
+}
+
+/*
+ * hitweight:
+ *      Gets the fighting ability according to current weight
+ *      This returns a  +1 hit for light pack weight
+ *                       0 hit for medium pack weight
+ *                      -1 hit for heavy pack weight
+ */
+
+hitweight()
+{
+        return(2 - foodlev);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xrogue/fight.c	Tue Apr 21 08:55:20 2015 -0400
@@ -0,0 +1,1473 @@
+/*
+    fight.c - All the fighting gets done here
+    
+    XRogue: Expeditions into the Dungeons of Doom
+    Copyright (C) 1991 Robert Pietkivitch
+    All rights reserved.
+    
+    Based on "Advanced Rogue"
+    Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka and AT&T
+    All rights reserved.
+
+    Based on "Rogue: Exploring the Dungeons of Doom"
+    Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
+    All rights reserved.
+    
+    See the file LICENSE.TXT for full copyright and licensing information.
+*/ 
+
+#include <curses.h>
+#include <ctype.h>
+#include <string.h>
+#include "rogue.h"
+
+#define CONF_DAMAGE     -1
+#define PARAL_DAMAGE    -2
+#define DEST_DAMAGE     -3
+#define DRAIN_DAMAGE    -4
+
+int killed_chance = 0;  /* cumulative chance for goodies to loose it */
+
+/*
+ * returns true if player has a any chance to hit the monster
+ */
+
+player_can_hit(tp, weap)
+register struct thing *tp;
+register struct object *weap;
+{
+    if (off(*tp, CMAGICHIT) && off(*tp, BMAGICHIT) && off(*tp, MAGICHIT))
+        return(TRUE);
+    if (weap && weap->o_type == RELIC)
+        return(TRUE);
+    if (on(*tp, CMAGICHIT) && weap && (weap->o_hplus>2 || weap->o_dplus>2))
+        return(TRUE);
+    if (on(*tp, BMAGICHIT) && weap && (weap->o_hplus>1 || weap->o_dplus>1))
+        return(TRUE);
+    if (on(*tp,  MAGICHIT) && weap && (weap->o_hplus>0 || weap->o_dplus>0))
+        return(TRUE);
+    if (player.t_ctype == C_MONK) {
+        if (on(*tp, CMAGICHIT) && pstats.s_lvl > 15)
+            return(TRUE);
+        if (on(*tp, BMAGICHIT) && pstats.s_lvl > 10)
+            return(TRUE);
+        if (on(*tp,  MAGICHIT) && pstats.s_lvl > 5)
+            return(TRUE);
+    }
+    return(FALSE);
+}
+
+/*
+ * fight:
+ *      The player attacks the monster.
+ */
+
+fight(mp, weap, thrown)
+register coord *mp;
+struct object *weap;
+bool thrown;
+{
+    register struct thing *tp;
+    register struct linked_list *item;
+    register bool did_hit = TRUE;
+    bool see_def, back_stab = FALSE;
+    register char *mname;
+
+    /*
+     * Find the monster we want to fight
+     */
+    if ((item = find_mons(mp->y, mp->x)) == NULL) {
+        return(FALSE); /* must have killed him already */
+    }
+    tp = THINGPTR(item);
+
+    /*
+     * Since we are fighting, things are not quiet so no healing takes
+     * place.  The -1 also tells us that we are in a fight.
+     */
+    player.t_quiet = -1;
+    tp->t_quiet = -1;
+
+    see_def = ((off(*tp, ISINVIS)     || on(player, CANSEE)) &&
+               (off(*tp, ISSHADOW)    || on(player, CANSEE)) &&
+               (!thrown || cansee(unc(tp->t_pos))));
+
+    mname = see_def ? monster_name(tp) : "something";
+
+    /*
+     * if its in the wall, we can't hit it
+     */
+    if (on(*tp, ISINWALL) && off(player, CANINWALL))
+        return(FALSE);
+
+    if (on(*tp, ISSTONE)) {
+        killed(item, FALSE, FALSE, FALSE);
+        if (see_def) 
+            msg("%s shatters into a million pieces!", prname(mname, TRUE));
+        count = 0;
+        return (TRUE);
+    }
+    /*
+     * Let him know it was really a mimic (if it was one).
+     */
+    if (on(*tp, ISDISGUISE) && (tp->t_type != tp->t_disguise) &&
+        off(player, ISBLIND))
+    {
+        if (see_def) {
+            msg("Wait! That's a %s!", mname);
+            turn_off(*tp, ISDISGUISE);
+        }
+        did_hit = thrown;
+    }
+    if (on(*tp, CANSURPRISE) && off(player, ISBLIND) && !ISWEARING(R_ALERT)) {
+        if (see_def) {
+            msg("Wait! There's a %s!", mname);
+            turn_off(*tp, CANSURPRISE);
+        }
+        did_hit = thrown;
+    }
+
+    /*
+     * if he's a thief or assassin and the creature is asleep then he gets 
+     * a chance for a backstab
+     */
+    if ((player.t_ctype == C_THIEF || player.t_ctype == C_ASSASSIN) &&
+        !thrown          &&
+        !on(*tp, NOSTAB) &&
+        !invisible(tp)   &&
+        (!on(*tp, ISRUN) || on(*tp, ISHELD) || tp->t_action == A_FREEZE))
+            back_stab = TRUE;
+
+    /*
+     * assassins get an assassination chance, if it fails then its normal
+     * damage
+     */
+    if (back_stab && player.t_ctype == C_ASSASSIN) {
+        int chance;
+
+        chance = 50 + (pstats.s_lvl - tp->t_stats.s_lvl) * 5;
+        if (cur_weapon && (cur_weapon->o_flags & ISPOISON))
+            chance += 20;
+        if (roll(1,100) > chance || on(*tp, ISUNIQUE))
+            back_stab = FALSE;
+    }
+
+    runto(tp, &hero);
+
+    /* Let the monster know that the player has missiles! */
+    if (thrown) tp->t_wasshot = TRUE;
+
+    if (did_hit)
+    {
+
+        did_hit = FALSE;
+        if (!can_blink(tp)              && 
+            player_can_hit(tp, weap)    &&
+            roll_em(&player, tp, weap, thrown, cur_weapon, back_stab))
+        {
+            did_hit = TRUE;
+
+            if (on(*tp, NOMETAL) && weap != NULL &&
+                weap->o_type != RELIC && weap->o_flags & ISMETAL) {
+                msg("Your %s passes right through %s!",
+                    weaps[weap->o_which].w_name, prname(mname, FALSE));
+            }
+            else if (weap != NULL && weap->o_type == MISSILE && on(*tp, CARRYBAMULET)) {
+                    msg("The magic missile has no effect on %s. ",
+                        prname(mname, FALSE));
+            }
+            else {
+                hit(thrown ? (struct object *)NULL : weap,
+                    TRUE, see_def,
+                    thrown ? weap_name(weap) : NULL,
+                    mname, back_stab, thrown, terse);
+
+                /* See if there are any special effects */
+                if (effect(&player, tp, weap, thrown, TRUE, see_def) != 0)
+                    killed(item, FALSE, FALSE, TRUE);
+    
+                /* 
+                 * Merchants just disappear if hit 
+                 */
+                else if (on(*tp, CANSELL)) {
+                    if (see_def)
+                        msg("%s disappears with his wares in a flash! ",
+                            prname(mname, FALSE));
+                    killed(item, FALSE, FALSE, FALSE);
+                }
+    
+                else if (tp->t_stats.s_hpt <= 0)
+                    killed(item, TRUE, TRUE, TRUE);
+    
+                else {
+                    /* If the victim was charmed, it now gets a saving throw! */
+                    if (on(*tp, ISCHARMED) && save(VS_MAGIC, tp, 0)) {
+                        msg("The eyes of %s turn clear.", prname(mname, FALSE));
+                        turn_off(*tp, ISCHARMED);
+                    }
+
+                    dsrpt_monster(tp, FALSE, see_def); /* Disrupt a spell? */
+                }
+            }
+        }
+        else {
+            miss(thrown ? (struct object *)NULL : weap,
+                 TRUE, see_def,
+                 thrown ? weap_name(weap) : (char *)NULL,
+                 mname, thrown, terse);
+        }
+    }
+    count = 0;
+    return did_hit;
+}
+
+/*
+ * attack:
+ *      The monster attacks the player
+ */
+
+attack(mp, weapon, thrown)
+register struct thing *mp;
+register struct object *weapon;
+bool thrown;
+{
+    register char *mname;
+    register bool see_att, did_hit = FALSE;
+    register struct object *wielded;    /* The wielded weapon */
+    struct linked_list *get_wield;      /* Linked list header for wielded */
+
+    /*
+     * Since this is an attack, stop running and any healing that was
+     * going on at the time.  The -1 also tells us that we're fighting.
+     */
+    running = FALSE;
+    player.t_quiet = -1;
+    mp->t_quiet = -1;
+
+    if (on(*mp, ISDISGUISE) && off(player, ISBLIND))
+        turn_off(*mp, ISDISGUISE);
+
+    see_att = ((off(*mp, ISINVIS)     || on(player, CANSEE)) &&
+               (off(*mp, ISSHADOW)    || on(player, CANSEE)) &&
+               (!thrown || cansee(unc(mp->t_pos))));
+
+    mname = see_att ? monster_name(mp) : "something";
+
+    /*
+     * Try to find a weapon to wield.  Wield_weap will return a
+     * projector if weapon is a projectile (eg. bow for arrow).
+     * If weapon is NULL, it will try to find a suitable weapon.
+     */
+    get_wield = wield_weap(weapon, mp);
+    if (get_wield) wielded = OBJPTR(get_wield);
+    else wielded = NULL;
+
+    /* If we aren't wielding a weapon, wield what we found (could be NULL) */
+    if (weapon == NULL) weapon = wielded;
+
+    if (roll_em(mp, &player, weapon, thrown, wielded, FALSE)) {
+        int death_type; /* From one of the effects of getting hit */
+
+        did_hit = TRUE;
+
+        if (weapon != NULL && weapon->o_type == MISSILE && cur_relic[STONEBONES_AMULET]) {
+            hit(weapon, see_att, TRUE, mname, (char *)NULL, FALSE, thrown, terse);
+            msg("Your amulet absorbs the magic missile. ");
+        }
+        else {
+            hit(weapon, see_att, TRUE, mname, (char *)NULL, FALSE, thrown, terse);
+            dsrpt_player();     /* see if we disrupted some activity */
+            if (pstats.s_hpt <= 0)
+                death(mp->t_index);     /* Bye bye life ... */
+            death_type = effect(mp, &player, weapon, thrown, see_att, TRUE);
+            if (death_type != 0) {
+        pstats.s_hpt = -1;
+        death(death_type);
+        }
+        }
+
+    }
+    else {
+        /* If the thing was trying to surprise, no good */
+        if (on(*mp, CANSURPRISE)) turn_off(*mp, CANSURPRISE);
+
+        /* If it couldn't surprise, let's tell the player. */
+        else miss(weapon, see_att, TRUE, mname, (char *)NULL, thrown, terse);
+    }
+    if (fight_flush) flushinp();
+    count = 0;
+    status(FALSE);
+    return(did_hit);
+}
+
+/*
+ * swing:
+ *      returns true if the swing hits
+ */
+
+swing(class, at_lvl, op_arm, wplus)
+short class;
+int at_lvl, op_arm, wplus;
+{
+    register int res = rnd(20)+1;
+    register int need;
+
+    need = char_class[class].base -
+           char_class[class].factor *
+           ((min(at_lvl, char_class[class].max_lvl) -
+            char_class[class].offset)/char_class[class].range) +
+           (10 - op_arm);
+    if (need > 20 && need <= 25) need = 20;
+
+    return (res+wplus >= need);
+}
+
+/*
+ * roll_em:
+ *      Roll several attacks
+ */
+
+roll_em(att_er, def_er, weap, hurl, cur_weapon, back_stab)
+struct thing *att_er, *def_er;
+struct object *weap;
+bool hurl;
+struct object *cur_weapon;
+bool back_stab;
+{
+    register struct stats *att, *def;
+    register char *cp = NULL;
+    register int ndice, nsides, nplus, def_arm;
+    char dmgbuf[20];
+    bool did_hit = FALSE;
+    int prop_hplus, prop_dplus;
+    int vampiric_damage;
+
+    /* Get statistics */
+    att = &att_er->t_stats;
+    def = &def_er->t_stats;
+
+    prop_hplus = prop_dplus = 0;
+    if (weap == NULL) {
+        /*
+         * monks damage grows with level
+         */
+        if (att == &pstats && player.t_ctype == C_MONK) {
+            sprintf(dmgbuf, "%dd4", att->s_lvl/3+2);
+            cp = dmgbuf;
+        }
+        else
+            cp = att->s_dmg;
+    }
+    else if (weap->o_type == RELIC) {
+        switch (weap->o_which) {
+            case MUSTY_DAGGER:
+            if (player.t_ctype == C_THIEF) 
+            cp = "4d8+2/4d8+2";
+        else
+                cp = "4d8/4d8";
+            when YEENOGHU_FLAIL:
+            cp = "4d8+3/paralyze/confuse";
+            when HRUGGEK_MSTAR:
+            cp = "4d8+3";
+            when AXE_AKLAD:
+            if (player.t_ctype == C_FIGHTER) {
+            if (hurl)
+            cp = "4d8+6/drain";
+                    else
+            cp = "4d8+4/drain";
+        }
+        else {
+            if (hurl)
+            cp = "4d8+4/drain";
+                    else
+            cp = "4d8+2/drain";
+                }
+            when MING_STAFF:
+                cp = "4d8+4";
+            when ASMO_ROD:
+                cp = "4d8/4d8";
+            when ORCUS_WAND:
+            cp = "4d8/destroy";
+        }
+    }
+    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,"4d8");
+            weap->o_hplus = weap->o_dplus = 0;
+        }
+    }
+    /*
+     * If defender is wearing a cloak of displacement -- no damage
+     * the first time. (unless its a hurled magic missile or the
+     * attacker is very smart and can see thru the illusion)
+     */
+    if ((weap == NULL || weap->o_type != MISSILE)       &&
+        def == &pstats                                  &&      
+        off(*att_er, MISSEDDISP)                        &&
+        att->s_intel < 21                               &&
+        ((cur_misc[WEAR_CLOAK]!=NULL && 
+          cur_misc[WEAR_CLOAK]->o_which==MM_DISP) ||
+          cur_relic[EMORI_CLOAK])) {
+        turn_on(*att_er, MISSEDDISP);
+        if (cansee(att_er->t_pos.y, att_er->t_pos.x) && !invisible(att_er))
+            msg("%s looks amazed! ", prname(monster_name(att_er), TRUE));
+        return (FALSE);
+    }
+    if (on(*def_er, CARRYCLOAK)                         && 
+        def != &pstats                                  && 
+        (weap == NULL || weap->o_type != MISSILE)       && 
+        off (*att_er, MISSEDDISP)                       &&
+        pstats.s_intel < 21) {
+            turn_on(*att_er, MISSEDDISP);
+            msg("You feel amazed! ");
+            return(FALSE);
+    }
+    for (;;)
+    {
+        int damage;
+        int hplus = prop_hplus;
+        int dplus = prop_dplus;
+
+        if (weap != NULL && weap->o_type == RELIC) {
+            switch (weap->o_which) {
+                case MUSTY_DAGGER:
+                    if (att != &pstats || /* Not player or good stats */
+                        (str_compute() > 15 && dex_compute() > 15)) {
+
+                        hplus += 6;
+                        dplus += 6;
+
+                        /* Give an additional strength and dex bonus */
+                        if (att == &pstats) {
+                            hplus += str_plus(str_compute()) +
+                                     dext_plus(dex_compute());
+                            dplus += dext_plus(dex_compute()) +
+                                     add_dam(str_compute());
+                        }
+                        else {
+                            hplus += str_plus(att->s_str) +
+                                     dext_plus(att->s_dext);
+                            dplus += dext_plus(att->s_dext) +
+                                     add_dam(att->s_str);
+                        }
+                    }
+                    else {
+                        hplus -= 3;
+                        dplus -= 3;
+                    }
+                when YEENOGHU_FLAIL:
+                case HRUGGEK_MSTAR:
+                    hplus += 3;
+                    dplus += 3;
+                when MING_STAFF:
+                    hplus += 2;
+                    dplus += 2;
+                when AXE_AKLAD:
+                    hplus += 5;
+                    dplus += 5;
+            }
+        }
+        else if (weap != NULL) {
+            hplus += weap->o_hplus;
+            dplus += weap->o_dplus;
+        }
+
+        /* Is attacker weak? */
+        if (on(*att_er, HASSTINK)) hplus -= 2;
+
+        if (att == &pstats)     /* Is the attacker the player? */
+        {
+            hplus += hitweight();       /* adjust for encumberence */
+            dplus += hung_dam();        /* adjust damage for hungry player */
+            dplus += ring_value(R_ADDDAM);
+        }
+        if (back_stab || (weap && att != &pstats && on(*att_er, CANBSTAB)))
+            hplus += 4; /* add in pluses for backstabbing */
+
+        /* Get the damage */
+        while (isspace(*cp)) cp++;
+        if (!isdigit(*cp)) {
+            if (strncmp(cp, "confuse", 7) == 0) ndice = CONF_DAMAGE;
+            else if (strncmp(cp, "paralyze", 8) == 0) ndice = PARAL_DAMAGE;
+            else if (strncmp(cp, "destroy", 6) == 0) ndice = DEST_DAMAGE;
+            else if (strncmp(cp, "drain", 5) == 0) ndice = DRAIN_DAMAGE;
+            else ndice = 0;
+            nsides = 0;
+            nplus = 0;
+        }
+        else {
+            char *oldcp;
+
+            /* Get the number of damage dice */
+            ndice = atoi(cp);
+            if ((cp = strchr(cp, 'd')) == NULL)
+                break;
+
+            /* Skip the 'd' and get the number of sides per die */
+            nsides = atoi(++cp);
+
+            /* Check for an addition -- save old place in case none is found */
+            oldcp = cp;
+            if ((cp = strchr(cp, '+')) != NULL) nplus = atoi(++cp);
+            else {
+                nplus = 0;
+                cp = oldcp;
+            }
+        }
+
+        if (def == &pstats) { /* Monster attacks player */
+            if (on(*att_er, NOMETAL))
+                def_arm = ac_compute(TRUE) - dext_prot(dex_compute());
+            else
+                def_arm = ac_compute(FALSE) - dext_prot(dex_compute());
+            hplus += str_plus(att->s_str)+dext_plus(att->s_dext);
+        }
+        else if (att == &pstats) {      /* Player attacks monster */
+            def_arm = def->s_arm - dext_prot(def->s_dext);
+            if (player.t_ctype == C_MONK) /* no strength bonus for monk */
+                if (weap == NULL) 
+                    hplus += att->s_lvl/5; /* monks hplus varies with level */
+            else
+                hplus += str_plus(str_compute())+dext_plus(dex_compute());
+        }
+        else {  /* Monster attacks monster */
+            def_arm = def->s_arm - dext_prot(def->s_dext);
+            hplus += str_plus(att->s_str)+dext_plus(att->s_dext);
+        }
+
+        if (swing(att_er->t_ctype, att->s_lvl, def_arm, hplus)) {
+            register int proll;
+
+            /* Take care of special effects */
+            switch (ndice) {
+              case CONF_DAMAGE:
+                if (def == &pstats) { /* Monster attacks player */
+                    if (!save(VS_MAGIC, &player, 0) && off(player, ISCLEAR)) {
+                        msg("You feel disoriented.");
+                        if (find_slot(unconfuse))
+                            lengthen(unconfuse, HUHDURATION);
+                        else
+                            fuse(unconfuse, (VOID *)NULL, HUHDURATION, AFTER);
+                        turn_on(player, ISHUH);
+                    }
+                    else msg("You feel dizzy, but it quickly passes.");
+                }
+                /* Player or monster hits monster */
+                else if (!save(VS_MAGIC, def_er, 0) && off(*def_er, ISCLEAR)) { 
+                    if (att == &pstats) {
+            if (rnd(10) > 6)
+                            msg("The artifact warms you with pleasure! ");
+            }
+                    turn_on(*def_er, ISHUH);
+                }
+                did_hit = TRUE;
+              when PARAL_DAMAGE:
+                if (def == &pstats) { /* Monster attacks player */
+                    if (!save(VS_MAGIC, &player, 0) && off(player, CANINWALL)) {
+                        msg("You stiffen up.");
+                        player.t_no_move += movement(&player) * FREEZETIME;
+                        player.t_action = A_FREEZE;
+                    }
+                }
+                else if (!save(VS_MAGIC, def_er, 0)) { /* Player hits monster */
+                    if (att == &pstats) {
+            if (rnd(10) > 6)
+                msg("The artifact hums happily! ");
+            }
+                    turn_off(*def_er, ISRUN);
+                    turn_on(*def_er, ISHELD);
+                }
+                did_hit = TRUE;
+              when DEST_DAMAGE:
+                if (def == &pstats) {   /* Monster attacks player */
+            if (rnd(10) > 5)
+                        msg("You feel a tug at your life force.");
+                    if (!save(VS_MAGIC, &player, -4)) {
+                        msg("The wand devours your soul!  --More--");
+            wait_for(' ');
+                        def->s_hpt = -1;
+            death(D_RELIC);
+                    }
+                }
+                /* Player hits monster */
+                else if (!save(VS_MAGIC, def_er, -4)) {
+                    if (att == &pstats) {
+            if (rnd(10) > 4)
+                            msg("The artifact draws some energy.");
+                     }
+                    /* The player loses some major hit pts  */
+                    att->s_hpt -= (att->s_hpt/5)+1;
+            if (att->s_hpt <= 0) {
+            msg("The wand has devoured your soul!  --More--");
+            wait_for(' ');
+            att->s_hpt = -1;
+            death(D_RELIC);
+            }
+                    /* Kill the monster */
+                    def->s_hpt = 0;
+                }
+                did_hit = TRUE;
+            when DRAIN_DAMAGE:
+                if (def == &pstats) {       /* Monster attacks player */
+                    if (!save(VS_MAGIC, &player, -4)) {
+                        lower_level(att_er->t_index);
+                    }
+                }
+                /* Player hits monster */
+                else if (!save(VS_MAGIC, def_er, -4)) {
+                    def->s_hpt -= roll(1, 8);
+                    def->s_lvl--;
+                    if (def->s_lvl <= 0)
+                        def->s_hpt = 0;     /* he's dead */
+                    if (att == &pstats) {
+            if (rnd(10) > 7)
+                        msg("The artifact cackles with laughter! ");
+            }
+                }
+                did_hit = TRUE;
+              otherwise:
+                /* Heil's ankh always gives maximum damage */
+                if (att == &pstats && cur_relic[HEIL_ANKH])
+                    proll = ndice * nsides;
+                else proll = roll(ndice, nsides);
+
+                if (ndice + nsides > 0 && proll < 1)
+                    debug("Damage for %dd%d came out %d.",
+                                ndice, nsides, proll);
+                damage = dplus + proll + nplus;
+                if (att == &pstats) {
+                    /*
+                     * Monks do not get strength bonus on damage.  Instead,
+                     * if they are wielding a weapon, they get at extra
+                     * 1/2 point per level of damage.
+                     */
+                    if(player.t_ctype == C_MONK) {
+                        /* Bonus does not apply for hands. */
+                        if (weap != NULL) damage += att->s_lvl / 2;
+                    }
+                    else
+                        damage += add_dam(str_compute());
+                }
+                else
+                    damage += add_dam(att->s_str);
+
+                /* Check for half damage monsters */
+                if (on(*def_er, HALFDAMAGE)) damage /= 2;
+
+                /* add in multipliers for backstabbing */
+                if (back_stab || 
+                    (weap && att != &pstats && on(*att_er, CANBSTAB))) {
+                    int mult = 2 + (att->s_lvl-1)/4; /* Normal multiplier */
+
+                    if (mult > 5)
+                        mult = 5;
+                    if (weap->o_type == RELIC && weap->o_which == MUSTY_DAGGER)
+                        mult++;
+                    damage *= mult;
+                }
+                if (att == &pstats) {
+                    if (cur_weapon && (cur_weapon->o_flags & ISPOISON)) {
+                        cur_weapon->o_flags &= ~ISPOISON;
+                        if (save(VS_POISON, def_er, -2))
+                            damage += def->s_hpt/4;
+                        else
+                            damage += def->s_hpt/2;
+                    }
+                    if (back_stab && player.t_ctype == C_ASSASSIN)
+                        damage = def->s_hpt + 1;
+                }
+                /* Check for no-damage and division */
+                if (on(*def_er, BLOWDIVIDE)) {
+                    damage = 0;
+                    creat_mons(def_er, def_er->t_index, FALSE);
+                    if (cansee(unc(def_er->t_pos))) light(&hero);
+                }
+                /* check for immunity to metal -- RELICS are always bad */
+                if (on(*def_er, NOMETAL) && weap != NULL &&
+                    weap->o_type != RELIC && weap->o_flags & ISMETAL) {
+                    damage = 0;
+                }
+                if (weap != NULL && weap->o_type == MISSILE) {
+                    if ((def == &pstats && cur_relic[STONEBONES_AMULET]) ||
+                        (att == &pstats && on(*def_er, CARRYBAMULET))) {
+                        damage = 0;
+                    }
+                }
+                def->s_hpt -= max(0, damage);   /* Do the damage */
+                did_hit = TRUE;
+                vampiric_damage = damage;
+                if (def->s_hpt < 0)     /* only want REAL damage inflicted */
+                    vampiric_damage += def->s_hpt;
+                if (vampiric_damage < 0)
+                    vampiric_damage = 0;
+                if (att == &pstats && ISWEARING(R_VAMPREGEN) && !hurl) {
+                    if ((pstats.s_hpt += vampiric_damage/2) > max_stats.s_hpt)
+                        pstats.s_hpt = max_stats.s_hpt;
+                }
+        if (hplus < 0) hplus = 0;
+        if (damage < 0) damage = 0;
+                debug ("hplus=%d dmg=%d", hplus, damage);
+            }
+        }
+        if ((cp = strchr(cp, '/')) == NULL)
+            break;
+        cp++;
+    }
+    return did_hit;
+}
+
+/*
+ * prname:
+ *      The print name of a combatant
+ */
+
+char *
+prname(who, upper)
+register char *who;
+bool upper;
+{
+    static char tbuf[LINELEN];
+
+    *tbuf = '\0';
+    if (who == 0)
+        strcpy(tbuf, "you"); 
+    else if (on(player, ISBLIND) || strcmp(who, "something") == 0)
+        strcpy(tbuf, "something");
+    else
+    {
+        /* If we have a name (starts with a capital), don't use a "the" */
+        if (islower(*who)) strcpy(tbuf, "the ");
+        strcat(tbuf, who);
+    }
+    if (upper)
+        *tbuf = toupper(*tbuf);
+    return tbuf;
+}
+
+/*
+ * hit:
+ *      Print a message to indicate a succesful hit
+ */
+
+hit(weapon, see_att, see_def, er, ee, back_stab, thrown, short_msg)
+register struct object *weapon;
+bool see_att, see_def;
+register char *er, *ee;
+bool back_stab, thrown, short_msg;
+{
+    register char *s = NULL;
+    char          att_name[LINELEN],    /* Name of attacker */
+                  def_name[LINELEN]; /* Name of defender */
+
+    /* If we can't see either the attacker or defender, don't say anything */
+    if (!see_att && !see_def) return;
+
+    /* What do we call the attacker? */
+    strcpy(att_name, see_att ? prname(er, TRUE) : "Something");
+    if (er) {   /* A monster is attacking */
+
+        /* If the monster is using a weapon and we can see it, report it */
+        if (weapon != NULL && (see_att || thrown)) {
+            strcat(att_name, "'s ");
+            strcat(att_name, weap_name(weapon));
+        }
+    }
+
+    /* What do we call the defender? */
+    strcpy(def_name, see_def ? prname(ee, FALSE) : "something");
+
+    addmsg(att_name);
+    if (short_msg) {
+        if (back_stab) {
+            if (player.t_ctype == C_ASSASSIN)
+                s = (er == 0 ? " assassinate!" : " assassinates!");
+            else
+                s = (er == 0 ? " backstab!" : " backstabs!");
+        }
+        else
+            s = " hit.";
+    }
+    else {
+        if (back_stab) {
+            if (player.t_ctype == C_ASSASSIN)
+                s = (er == 0 ? " have assassinated " : " has assassinated ");
+            else
+                s = (er == 0 ? " have backstabbed " : " has backstabbed ");
+        }
+        else {
+            switch (rnd(thrown ? 2 : 3))
+            {
+                case 0: s = " hit ";
+                when 1: s = " injured ";
+                when 2: s = " smacked ";
+            }
+        }
+    }
+    if (short_msg) addmsg(s);
+    else addmsg("%s%s.", s, def_name);
+    endmsg();
+}
+
+/*
+ * miss:
+ *      Print a message to indicate a poor swing
+ */
+
+miss(weapon, see_att, see_def, er, ee, thrown, short_msg)
+register struct object *weapon;
+bool see_att, see_def;
+register char *er, *ee;
+bool thrown, short_msg;
+{
+    register char *s = NULL;
+    char          att_name[LINELEN],    /* Name of attacker */
+                  def_name[LINELEN];    /* Name of defender */
+
+    /* If we can't see either the attacker or defender, don't say anything */
+    if (!see_att && !see_def) return;
+
+    /* What do we call the attacker? */
+    strcpy(att_name, see_att ? prname(er, TRUE) : "Something");
+    if (er) {   /* A monster is attacking */
+
+        /* If the monster is using a weapon and we can see it, report it */
+        if (weapon != NULL && (see_att || thrown)) {
+            strcat(att_name, "'s ");
+            strcat(att_name, weap_name(weapon));
+        }
+    }
+
+    /* What do we call the defender? */
+    strcpy(def_name, see_def ? prname(ee, FALSE) : "something");
+
+    addmsg(att_name);
+    switch (short_msg ? 0 : rnd(thrown ? 3 : 2))
+    {
+        case 0: s = (er == 0 ? " miss" : " misses");
+        when 1: s = (er == 0 ? " don't hit" : " doesn't hit");
+        when 2: s = (" whizzes by");
+    }
+    if (short_msg) addmsg("%s.", s);
+    else addmsg("%s %s.", s, def_name);
+    endmsg();
+}
+
+/*
+ * dext_plus:
+ *      compute to-hit bonus for dexterity
+ */
+
+dext_plus(dexterity)
+register int dexterity;
+{
+        return (dexterity > 10 ? (dexterity-13)/3 : (dexterity-10)/3);
+}
+
+
+/*
+ * dext_prot:
+ *      compute armor class bonus for dexterity
+ */
+
+dext_prot(dexterity)
+register int dexterity;
+{
+    return ((dexterity-10)/2);
+}
+
+/*
+ * str_plus:
+ *      compute bonus/penalties for strength on the "to hit" roll
+ */
+
+str_plus(str)
+register short str;
+{
+    return((str-10)/3);
+}
+
+/*
+ * add_dam:
+ *      compute additional damage done for exceptionally high or low strength
+ */
+
+add_dam(str)
+register short str;
+{
+    return((str-9)/2);
+}
+
+/*
+ * hung_dam:
+ *      Calculate damage depending on players hungry state
+ */
+
+hung_dam()
+{
+        reg int howmuch = 0;
+
+        switch(hungry_state) {
+                case F_SATIATED:
+                case F_OKAY:
+                case F_HUNGRY:  howmuch = 0;
+                when F_WEAK:    howmuch = -1;
+                when F_FAINT:   howmuch = -2;
+        }
+        return howmuch;
+}
+
+/*
+ * is_magic:
+ *      Returns true if an object radiates magic
+ */
+
+is_magic(obj)
+register struct object *obj;
+{
+    switch (obj->o_type)
+    {
+        case ARMOR:
+            return obj->o_ac != armors[obj->o_which].a_class;
+        when WEAPON:
+            return obj->o_hplus != 0 || obj->o_dplus != 0;
+        when POTION:
+        case SCROLL:
+        case STICK:
+        case RING:
+        case MM:
+        case RELIC:
+            return TRUE;
+    }
+    return FALSE;
+}
+
+/*
+ * killed:
+ *      Called to put a monster to death
+ */
+
+killed(item, pr, points, treasure)
+register struct linked_list *item;
+bool pr, points, treasure;
+{
+    register struct thing *tp, *mp;
+    register struct linked_list *pitem, *nexti, *mitem;
+    char *monst;
+    int adj;    /* used for hit point adj. below. */
+    long temp;
+
+    tp = THINGPTR(item);
+
+    if (pr)
+    {
+        addmsg(terse ? "Defeated " : "You have defeated ");
+        if (on(player, ISBLIND))
+            msg("it.");
+        else
+        {
+            if (cansee(tp->t_pos.y, tp->t_pos.x) && !invisible(tp))
+                monst = monster_name(tp);
+            else {
+                if (terse) monst = "something";
+                else monst = "thing";
+            }
+            if (!terse)
+                addmsg("the ");
+            msg("%s.", monst);
+        }
+    }
+
+    /* Take care of any residual effects of the monster */
+    check_residue(tp);
+
+    /* Make sure that no one is still chasing us */
+    for (mitem = mlist; mitem != NULL; mitem = next(mitem)) {
+        mp = THINGPTR(mitem);
+        if (mp->t_dest == &tp->t_pos) {
+            mp->t_dest = &hero;
+            mp->t_wasshot = FALSE;
+            turn_off(*mp, ISFLEE);      /* Be sure we aren't running away! */
+        }
+    }
+    if (points) {   /* you feel uneasy for a moment */
+        if ((off(*tp, ISMEAN) || on(*tp, ISFRIENDLY)) &&
+            (player.t_ctype == C_RANGER || player.t_ctype == C_PALADIN ||
+             player.t_ctype == C_MONK)) {
+                if (tp->t_stats.s_exp > pstats.s_exp)
+                    pstats.s_exp = 0;
+                else
+                    pstats.s_exp -= tp->t_stats.s_exp;
+                /* Take care of hit points. */
+                if (level <= 12) adj = rnd(2)+1;
+                else if (level <= 25) adj = rnd(3)+2;
+                else if (level <= 50) adj = rnd(4)+3;
+                else if (level <= 80) adj = rnd(5)+4;
+                else adj = rnd(6)+5;
+        /* adjust hit points */
+                max_stats.s_hpt -= adj;
+                pstats.s_hpt -= adj;
+                /* Are hit points now too low? */
+                if (pstats.s_hpt <= 0) {
+            pstats.s_hpt = -1;
+            death(D_STRENGTH);
+        }
+                killed_chance += rnd(3)+1;
+                if (on(*tp, ISUNIQUE)) /* real bad news to kill a diety */
+                    killed_chance += 25;
+                if (roll(1,100) < killed_chance) {
+            msg("You had a feeling this was going to happen... ");
+                    msg("**POOF**  ");
+                    temp = C_ASSASSIN;  /* make him pay */
+                    changeclass(&temp);
+                }
+                else {
+                    switch (rnd(9)) {
+                    case 0:
+            msg("You become solid and stiff for a while. ");
+                        player.t_no_move += (5*movement(&player)*FREEZETIME);
+                        player.t_action = A_FREEZE;
+                    when 1:
+            msg("You collapse, losing it totally. ");
+                        player.t_no_move += (2*movement(&player)*FREEZETIME);
+                        player.t_action = A_FREEZE;
+                    when 2:
+            msg("Your face changes shape!  ARGGHH!!!! ");
+                        pstats.s_charisma -= rnd(8)+3;
+                        if (pstats.s_charisma <= 3) pstats.s_charisma = 3;
+                    when 3:
+            case 4:
+            msg("You cry out, I didn't mean to do that!  Honest!! ");
+                        player.t_no_move += (movement(&player)*FREEZETIME);
+            msg("The Great Old Ones grant you a reprieve. ");
+                    otherwise: msg("You feel uneasy for a moment.. ");
+                    }
+        }
+        }
+        else {
+                unsigned long test;      /* For overflow check */
+                /* 
+                 * Do an overflow check before increasing experience 
+                 */
+                test = pstats.s_exp + tp->t_stats.s_exp;
+                if (test > pstats.s_exp) 
+                        pstats.s_exp = test;
+        }
+
+        /*
+         * Do adjustments if he went up a level
+         */
+        check_level();
+    }
+
+    /*
+     * Empty the monsters pack
+     */
+    pitem = tp->t_pack;
+
+    /*
+     * Get rid of the monster.
+     */
+    mvwaddch(mw, tp->t_pos.y, tp->t_pos.x, ' ');
+    mvwaddch(cw, tp->t_pos.y, tp->t_pos.x, tp->t_oldch);
+    detach(mlist, item);
+    if (on(*tp, AREMANY) && levtype == NORMLEV) /* AREMANYs stick together */
+        wake_room(roomin(&tp->t_pos));
+    /*
+     * empty his pack
+     */
+    while (pitem != NULL)
+    {
+        nexti = next(pitem);
+        (OBJPTR(pitem))->o_pos = tp->t_pos;
+        detach(tp->t_pack, pitem);
+        if (treasure) 
+            fall(pitem, FALSE);
+        else 
+            o_discard(pitem);
+        pitem = nexti;
+    }
+
+    turn_on(*tp,ISDEAD);
+    attach(rlist,item);
+}
+
+/*
+ * Returns a pointer to the weapon the monster is wielding corresponding to
+ * the given thrown weapon.  If no thrown item is given, try to find any
+ * decent weapon.
+ */
+
+struct linked_list *
+wield_weap(thrown, mp)
+struct object *thrown;
+struct thing *mp;
+{
+    int look_for = 0,   /* The projectile weapon we are looking for */
+        new_rate,       /* The rating of a prospective weapon */
+        cand_rate = -1; /* Rating of current candidate -- higher is better */
+    register struct linked_list *pitem, *candidate = NULL;
+    register struct object *obj;
+
+    if (thrown != NULL) {       /* Using a projectile weapon */
+      switch (thrown->o_which) {
+        case BOLT:      look_for = CROSSBOW;    /* Find the crossbow */
+        when ARROW:     look_for = BOW;         /* Find the bow */
+        when ROCK:      look_for = SLING;       /* find the sling */
+        otherwise:      return(NULL);
+      }
+    }
+    else if (off(*mp, ISUNIQUE) && off(*mp, CARRYWEAPON)) return(NULL);
+
+    for (pitem=mp->t_pack; pitem; pitem=next(pitem)) {
+        obj = OBJPTR(pitem);
+
+        /*
+         * If we have a thrown weapon, just return the first match
+         * we come to.
+         */
+        if (thrown != NULL && obj->o_type == WEAPON && obj->o_which == look_for)
+            return(pitem);
+
+        /* If we have a usable RELIC, return it */
+        if (thrown == NULL && obj->o_type == RELIC) {
+            switch (obj->o_which) {
+                case MUSTY_DAGGER:
+                case YEENOGHU_FLAIL:
+                case HRUGGEK_MSTAR:
+                case AXE_AKLAD:
+                case MING_STAFF:
+                case ASMO_ROD:
+                case ORCUS_WAND:
+                    return(pitem);
+            }
+        }
+
+        /* Otherwise if it's a usable weapon, it is a good candidate */
+        else if (thrown == NULL && obj->o_type == WEAPON) {
+            switch (obj->o_which) {
+                case DAGGER:
+                case SPEAR:
+                    new_rate = 0;
+                when BATTLEAXE:
+                    new_rate = 1;
+                when MACE:
+                    new_rate = 2;
+                when SWORD:
+                    new_rate = 3;
+                when PIKE:
+                    new_rate = 4;
+                when HALBERD:
+                case SPETUM:
+                    new_rate = 6;
+                when BARDICHE:
+                    new_rate = 7;
+                when TRIDENT:
+                    new_rate = 8;
+                when BASWORD:
+                    new_rate = 9;
+                when TWOSWORD:
+                    new_rate = 10;
+                otherwise:
+                    new_rate = -1;
+            }
+
+            /* Only switch if this is better than the current candidate */
+            if (new_rate > cand_rate) {
+                cand_rate = new_rate;
+                candidate = pitem;
+            }
+        }
+    }
+
+    return(candidate);
+}
+explode(tp)
+register struct thing *tp;
+{
+
+    register int x,y, damage;
+    struct linked_list *item;
+    struct thing *th;
+
+    /*
+     * check to see if it got the hero
+     */
+     if (off(player, ISINWALL) &&
+         DISTANCE(hero.x, hero.y, tp->t_pos.x, tp->t_pos.y) <= 25) {
+        msg("The explosion hits you! ");
+        damage = roll(6,6);
+        if (save(VS_WAND, &player, 0))
+            damage /= 2;
+        pstats.s_hpt -= damage;
+    }
+
+    /*
+     * now check for monsters in vicinity
+     */
+     for (x = tp->t_pos.x-5; x<=tp->t_pos.x+5; x++) {
+         if (x < 0 || x > cols - 1) 
+             continue;
+         for (y = tp->t_pos.y-5; y<=tp->t_pos.y+5; y++) {
+            if (y < 1 || y > lines - 3)
+                continue;
+            if (isalpha(mvwinch(mw, y, x))) {
+                if ((item = find_mons(y, x)) != NULL) {
+                    th = THINGPTR(item);
+                    if (th == tp || /* don't count gas spore */
+                        on(*th, ISINWALL)) /* Don't count monsters in wall */
+                        continue;
+                    damage = roll(6, 6);
+                    if (save(VS_WAND, th, 0))
+                        damage /= 2;
+                    runto(th, &hero);
+                    if ((th->t_stats.s_hpt -= damage) <= 0) {
+                        msg("The explosion kills %s! ", 
+                            prname(monster_name(th), FALSE));
+                        killed(item, FALSE, FALSE, TRUE);
+                    }
+                }
+            }
+        }
+    }
+}
+
+/*
+ * skirmish:
+ *      Called when one monster attacks another monster.
+ */
+
+skirmish(attacker, mp, weap, thrown)
+register struct thing *attacker;
+register coord *mp;
+struct object *weap;
+bool thrown;
+{
+    register struct thing *defender;
+    register struct linked_list *item;
+    register bool did_hit = TRUE, see_att, see_def;
+    char attname[LINELEN+1], defname[LINELEN+1];
+    struct object *wielded;     /* The wielded weapon */
+    struct linked_list *get_wield;      /* Linked list header for wielded */
+
+    /*
+     * Find the monster we want to fight
+     */
+    if ((item = find_mons(mp->y, mp->x)) == NULL) {
+        return(FALSE); /* must have killed him already */
+    }
+    defender = THINGPTR(item);
+
+    /* Can the player see either of the fighters? */
+    see_att = (cansee(unc(attacker->t_pos)) &&
+               (off(*attacker, ISINVIS)     || on(player, CANSEE)) &&
+               (off(*attacker, ISSHADOW)    || on(player, CANSEE)));
+    see_def = (cansee(unc(defender->t_pos)) &&
+               (off(*defender, ISINVIS)     || on(player, CANSEE)) &&
+               (off(*defender, ISSHADOW)    || on(player, CANSEE)));
+
+    /*
+     * Since we are fighting, things are not quiet so no healing takes
+     * place.  The -1 also tells us that we are in a fight.
+     */
+    attacker->t_quiet = -1;
+    defender->t_quiet = -1;
+
+    if (see_att) strcpy(attname, monster_name(attacker));
+    else strcpy(attname, "something");
+
+    if (see_def) strcpy(defname, monster_name(defender));
+    else strcpy(defname, "something");
+
+    /*
+     * if its in the wall, we can't hit it
+     */
+    if (on(*defender, ISINWALL) && off(*attacker, CANINWALL))
+        return(FALSE);
+
+    if (on(*defender, ISSTONE)) {
+        killed(item, FALSE, FALSE, FALSE);
+        if (see_def)
+            msg("%s shatters into a million pieces!", prname(defname, TRUE));
+        return (TRUE);
+    }
+
+    /*
+     * Let him know it was really a mimic (if it was one).
+     */
+    if (see_def && on(*defender, ISDISGUISE) &&
+        (defender->t_type != defender->t_disguise)) {
+        msg("Wait!  There's a %s!", defname);
+        turn_off(*defender, ISDISGUISE);
+        did_hit = thrown;
+    }
+
+    if (see_def && on(*defender, CANSURPRISE) && !ISWEARING(R_ALERT)) {
+        msg("Wait!  There's a %s!", defname);
+        turn_off(*defender, CANSURPRISE);
+        did_hit = thrown;
+    }
+
+    if (did_hit) {
+
+        did_hit = FALSE;
+
+        /*
+         * Try to find a weapon to wield.  Wield_weap will return a
+         * projector if weapon is a projectile (eg. bow for arrow).
+         * If weapon is NULL, it will try to find a suitable weapon.
+         */
+        get_wield = wield_weap(weap, attacker);
+        if (get_wield) wielded = OBJPTR(get_wield);
+        else wielded = NULL;
+
+#ifdef DOBLINK
+        /*
+         * For now Blink Dogs will not blink away from monsters.  We
+         * have to fix can_blink so it isn't dependant on the player
+         * before we can add it.
+         */
+        if (!can_blink(defender) &&
+#endif
+        if (((weap && weap->o_type == RELIC) ||
+             ((off(*defender, MAGICHIT) ||
+               attacker->t_stats.s_lvl > 4 ||
+               (weap && (weap->o_hplus > 0 || weap->o_dplus > 0))) &&
+              (off(*defender, BMAGICHIT) ||
+               attacker->t_stats.s_lvl > 6 ||
+               (weap && (weap->o_hplus > 1 || weap->o_dplus > 1))) &&
+              (off(*defender, CMAGICHIT) ||
+               attacker->t_stats.s_lvl > 8 ||
+               (weap && (weap->o_hplus > 2 || weap->o_dplus > 2)))))
+            && roll_em(attacker, defender, weap, thrown, wielded, FALSE))
+        {
+            did_hit = TRUE;
+
+            /* Should we start to chase this creature? */
+            if (attacker->t_index != defender->t_index  &&
+                (off(*defender, ISRUN) || rnd(100) < 50)) {
+                /*
+                 * If we're intelligent enough to realize that this
+                 * is a friendly monster, we will attack the hero instead.
+                 */
+                if (on(*attacker, ISFRIENDLY) &&
+                    roll(3,6) < defender->t_stats.s_intel) {
+                    runto(defender, &hero);
+                    debug("%s attacking %s's hero", defname, attname);
+                }
+
+                /* Otherwise, let's chase the monster */
+                else {
+                    runto(defender, &attacker->t_pos);
+                    debug("%s now attacking %s", defname, attname);
+                }
+            }
+            else if (off(*defender, ISRUN)) runto(defender, &hero);
+
+            /* Let the defender know that the attacker has missiles! */
+            if ((defender->t_dest == &attacker->t_pos) && thrown)
+                defender->t_wasshot = TRUE;
+
+            if (on(*defender, NOMETAL) && weap != NULL &&
+                weap->o_type != RELIC && weap->o_flags & ISMETAL) {
+                if (see_def && see_att)
+                    msg("The %s passes right through %s!",
+                        weaps[weap->o_which].w_name, prname(defname, FALSE));
+            }
+            else {
+                hit(weap, see_att, see_def,
+                    attname, defname, FALSE, thrown, FALSE);
+            }
+
+            /* See if there are any special effects */
+            if (effect(attacker, defender,
+                       weap, thrown, see_att, see_def) != 0) {
+                killed(item, FALSE, FALSE, TRUE);
+                if (see_def) msg("%s dies.", prname(defname, TRUE));
+                else msg("You hear a blood-curdling scream! ");
+            }
+
+            /* 
+             * Merchants just disappear if hit 
+             */
+            else if (on(*defender, CANSELL)) {
+                if (see_def)
+                    msg("%s disappears with his wares in a flash! ",
+                            prname(defname, TRUE));
+                killed(item, FALSE, FALSE, FALSE);
+            }
+
+            else if (defender->t_stats.s_hpt <= 0) {
+                killed(item, FALSE, FALSE, TRUE);
+                if (see_def) msg("%s dies.", prname(defname, TRUE));
+                else msg("You hear a blood-curdling scream! ");
+            }
+
+            else {
+                /* Did we disrupt a spell?                              */
+                /* Don't turn on WASDISRUPTED since player didn't do it */
+                if (defender->t_action == A_SUMMON ||
+                    defender->t_action == A_MISSILE) {
+                    /* Just make the old fellow start over again */
+                    defender->t_action = A_NIL;
+                    defender->t_no_move = movement(defender);
+                    defender->t_using = NULL;
+
+                    if (see_def)
+                        msg("%s was disrupted.", prname(defname, TRUE));
+                }
+
+#ifdef FLEEMONST
+                /*
+                 * If the monster is fairly intelligent and about to die,
+                 * it may turn tail and run.
+                 */
+                if ((tp->t_stats.s_hpt < max(10, tp->maxstats.s_hpt/10)) &&
+                    (rnd(21) < tp->t_stats.s_intel)) {
+                        turn_on(*tp, ISFLEE);
+
+                    /* If monster was suffocating, stop it */
+                    if (on(*tp, DIDSUFFOCATE)) {
+                        turn_off(*tp, DIDSUFFOCATE);
+                        extinguish(suffocate);
+                    }
+
+                    /* If monster held us, stop it */
+                    if (on(*tp, DIDHOLD) && (--hold_count == 0))
+                            turn_off(player, ISHELD);
+                    turn_off(*tp, DIDHOLD);
+
+                    /* It is okay to turn tail */
+                    tp->t_oldpos = tp->t_pos;
+                }
+#endif
+            }
+        }
+        else {
+            /* If the thing was trying to surprise, no good */
+            if (on(*attacker, CANSURPRISE)) {
+                /* If we can't see it, it keeps surprise (from us) */
+                if (see_att) turn_off(*attacker, CANSURPRISE);
+            }
+
+            miss(weap, see_att, see_def, attname, defname, thrown, FALSE);
+        }
+    }
+    return did_hit;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xrogue/help.c	Tue Apr 21 08:55:20 2015 -0400
@@ -0,0 +1,651 @@
+/*
+    help.c  -  Routines having to do with help
+    
+    XRogue: Expeditions into the Dungeons of Doom
+    Copyright (C) 1991 Robert Pietkivitch
+    All rights reserved.
+    
+    Based on "Advanced Rogue"
+    Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka and AT&T
+    All rights reserved.
+
+    Based on "Rogue: Exploring the Dungeons of Doom"
+    Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
+    All rights reserved.
+    
+    See the file LICENSE.TXT for full copyright and licensing information.
+*/
+
+#include <curses.h>
+#include <ctype.h>
+#include "mach_dep.h"
+#include "rogue.h"
+
+/*
+ * Give character descripts
+ */
+
+static char *game_fighter = "Strength is the main attribute of the Fighter.  \
+He can wield any weapon and the two-handed sword is his weapon of choice.  He \
+can also wear any type of armor.  Plate armor being the best choice and \
+leather armor the worst.  The Fighter is  able to sense both traps and gold \
+at higher experience levels.  His natural     quest item is the Axe of Aklad.  \
+Due to his superior form, the Fighter usually  receives more hit-points per \
+new experience level than the other characters.    The Fighter is neither good \
+or evil; he is a neutral character.  The default    attribute values of the \
+Fighter are: Int=7, Str=16, Wis=7, Dxt=16, Con=17, and  Chr=11.  Default gold \
+amount is 2000 pieces and default hit-points are 24.";
+
+static char *game_thief = "Dexterity is the main attribute of the Thief.  His \
+stealth allows him to move   quietly, thus disturbing less monsters.  He can \
+sense traps and gold and can    take (steal) things from the monsters.  The \
+Thief can not wield the two-handed  sword so the bastard sword is his weapon \
+of choice.  He can only wear studded   leather armor.  The Thief's natural \
+quest item is the Daggers of Musty Doit.    With higher dexterity the Thief \
+is able to \"backstab\" monsters, thereby killing them with a single blow.  \
+His character type fluctuates between that of good,   neutral, and evil.  The \
+default attribute values of the Thief are:  Int=7,      Str=14, Wis=7, Dxt=18, \
+Con=17, and Chr=11.  Default gold amount is 2000 pieces  and default \
+hit-points are 23.";
+
+static char *game_assassin = "Dexterity is the main attribute of the \
+Assassin.  Like the Thief, he moves with an extra degree of stealth.  He can \
+sense gold and steal things from monsters.  The ability to sense traps comes \
+at higher experience levels.  The Assassin can not wield the two-handed sword \
+and he can only wear studded leather armor.  The natural quest item of the \
+Assassin is the Eye of Vecna.  He is also skilled in  the use of poison.  \
+Higher dexterity enables him to \"assassinate\" monsters with a single blow.  \
+The Assassin is aligned with the powers of evil.  The default   attribute \
+values of the Assassin are: Int=7, Str=14, Wis=7, Dxt=18, Con=17, and \
+Chr=11.  Default gold amount is 2000 pieces and default hit-points are 23.";
+
+static char *game_ranger = "Charisma is the main attribute of the Ranger who \
+also has a secondary attribute of Intelligence.  Like the Magician, this \
+gives him the ability to cast spells  which increases as he attains higher \
+experience levels.  Like the Fighter, he   can wield any weapon and wear any \
+armor.  The Ranger's natural quest item is    the Mandolin of Brian.  He is \
+aligned with the powers of good.  Therefore, he   can be made to suffer and \
+even become cursed by the very powers that allow him  to cast spells if he \
+happens to cause the demise of a likewise good creature.   The default \
+attribute values of the Ranger are: Int=11, Str=11, Wis=7, Dxt=16,  Con=16, \
+and Chr=13.  Default gold amount is 2000 pieces and default hit-points  \
+are 22.";
+
+static char *game_paladin = "Charisma is the main attribute of the Paladin \
+who has a secondary attribute of  Wisdom.  Like the Cleric, this gives him \
+the ability to offer prayers, receive  what his heart desires, and an ability \
+to turn the undead.  This ability will   increase as he gains higher \
+experience levels.  Like the Fighter, he can wield  any weapon and wear any \
+armor.  The Ankh of Heil is the Paladin's natural quest item.  Like the \
+Ranger, the Paladin is aligned with the powers of good.  This   can cause \
+him to suffer and become cursed if he brings ruin to a likewise good  \
+creature.  The default attribute values of the Paladin are:  Int=7, \
+Str=11,     Wis=11, Dxt=16, Con=16, and Chr=13.  Default gold amount is \
+2000 pieces and     default hit-points are 22.";
+
+static char *game_druid = "Wisdom is the main attribute of the Druid.  This \
+gives him the ability to chant secret words and mantras, which is much \
+greater than that of the Monk.  The     Druid can not wield the two-handed or \
+bastard swords but he can wear any armor. His natural quest item is the Quill \
+of Nagrom.  Like the Magician and Cleric,   the Druid is aligned neutral.  He \
+therefore, must rely upon his Wisdom and his  chanting ability in order to \
+remain alive.  Likewise, he does not receive as    many new hit-points per \
+new experience level.  The default attribute values of  the Druid are: Int=7, \
+Str=10, Wis=14, Dxt=16, Con=15, and Chr=12.  Default gold amount is 2000 \
+pieces and default hit-points are 21.";
+
+static char *game_monk = "Constitution is the main attribute of the Monk who \
+has a secondary aspect of    Wisdom.  Like the Druid, this gives him the \
+ability to chant mantras which will increase as he gains higher experience.  \
+The Monk can not wield the two-handed  sword and he can not wear any armor.  \
+The Cloak of Emori is the Monk's natural  quest item.  The Monk can also \
+sense traps, though much less than the Thief or  Assassin.  He is the most \
+healthy character.  Like the Ranger and Paladin, he   is aligned with the \
+powers of good.  Therefore, he is made to suffer and can    become cursed if \
+he kills a likewise good creature.  The default attribute      values of the \
+Monk are: Int=7, Str=11, Wis=11, Dxt=16, Con=18, and Chr=11.      Default \
+gold amount is 2000 pieces and default hit-points are 22.";
+
+static char *game_magician = "Intelligence is the main attribute of the \
+Magician.  The Magician's ability to  cast spells is much greater than that \
+of the Ranger.  He can not wield the two- handed or bastard swords, but he \
+can wear any kind of armor.  His natural quest item is the Amulet of \
+Stonebones.  The Magician is aligned neutral.  He must    rely upon his \
+Intelligence and spell casting abilities to remain alive.  There- fore, he \
+does not receive as many new hit-points per new experience level.  The \
+default attribute values of the Magician are: Int=14, Str=10, Wis=7, \
+Dxt=16,    Con=15, and Chr=12.  Default gold amount is 2000 pieces and \
+default hit-points  are 21.";
+
+static char *game_cleric = "Wisdom is the main attribute of the Cleric.  The \
+Cleric's ability to give or    offer prayers, receive their due, and affect \
+the undead are much greater than   that of the Paladin.  Like the Magician, \
+the Cleric can not wield the two-      handed or bastard swords, but he can \
+wear any armor.  His natural quest item is the Horn of Geryon.  The Cleric \
+is aligned neutral  and he must rely upon his   Wisdom and prayer ability to \
+remain alive.  He therefore, does not receive as   many new hit-points per \
+new experience level.  The default attribute values of  the Cleric are: Int=7, \
+Str=10, Wis=14, Dxt=16, Con=15, and Chr=12.  The default gold amount is 2000 \
+pieces and default hit-points are 21.";
+
+
+static char *game_food ="There are three types of food, regular food rations, \
+various fruits, and slime- molds.  Eating regular food will add 750 points to \
+your current food level      [see the CTRL(E) command].  Eating fruit adds \
+300 points.  Certain fruits also  cure you, add an attribute point, add a \
+hit-point, increase your armor, give    you additional prayer, chant, or spell \
+casting abilities, or add experience     points.  Eating slime-mold (monster \
+food) can make you ill, but they will add   100 points to your current food \
+level.  If your food level points drop below    100 you will become weak.  You \
+will faint and might die if they drop to 0 or    below.  At the other extreme, \
+if your food level points reach 2000 (and above)  you will become satiated.  \
+Risk eating more and you could choke to death.";
+
+/*
+static char *game_monst ="To be updated.";
+static char *game_potion ="To be updated...";
+static char *game_scroll ="To be updated...";
+static char *game_ring ="To be updated...";
+static char *game_stick ="To be updated...";
+static char *game_weapon ="To be updated...";
+static char *game_armor ="To be updated...";
+static char *game_miscm ="To be updated...";
+static char *game_qitems ="To be updated...";
+static char *game_dungeon ="To be updated...";
+static char *game_traps ="To be updated...";
+static char *game_mazes ="To be updated...";
+static char *game_option ="To be updated...";
+static char *game_begin ="To be updated...";
+*/
+
+/* help list */
+static struct h_list helpstr[] = {
+    '?',     "    Print help",
+    '/',     "    Identify object",
+    '=',     "    Identify a screen character",
+    ' ',     "",
+    'h',     "    Move left",
+    'j',     "    Move down",
+    'k',     "    Move up",
+    'l',     "    Move right",
+    'y',      "    Move up and left",
+    'u',        "    Move up and right",
+    'b',        "    Move down and left",
+    'n',        "    Move down and 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",
+    ' ',        "",
+    '>',        "    Go down a staircase",
+    '<',        "    Go up a staircase",
+    '\\',        "  Game descriptions",
+    '.',        "   Rest for a while",
+    '*',        "   Count gold pieces",
+    'a',        "   Affect the undead",
+    'A',        "   Choose artifact (equipage)",
+    'c',        "   Chant a mantra",
+    'C',        "   Cast a spell",
+    'd',        "   Drop something",
+    'D',        "   Dip something (into a pool)",
+    'e',        "   Eat food or fruit",
+    'f',        "<dir>  Forward until find something",
+    'F',        "   Frighten a monster",
+    'g',        "   Give food to monster",
+    'G',        "   Sense for gold",
+    'i',        "   Inventory",
+    'I',        "   Inventory (single item)",
+    'm',        "   Mark an object (specific)",
+    'o',        "   Examine and/or set options",
+    'O',        "   Character type and quest item",
+    'p',        "   Pray to the powers that be",
+    'P',        "   Pick up object(s)",
+    'q',        "   Quaff a potion",
+    'Q',        "   Quit the game",
+    'r',        "   Read a scroll",
+    's',        "   Search for a trap/secret door",
+    'S',        "   Save your game",
+    't',        "<dir>  Throw something",
+    'T',        "   Take off something",
+    'v',        "   Print program version",
+    'w',        "   Wield a weapon",
+    'W',        "   Wear something",
+    'X',        "   Sense for traps",
+    'z',        "<dir>  Zap a wand or staff",
+    ' ',        "",
+    '^',        "   Set a trap",
+    '$',        "   Price an item (trading post)",
+    '#',        "   Buy an item   (trading post)",
+    '%',        "   Sell an item  (trading post)",
+    '!',        "   Shell escape",
+    ESC,        "   Cancel command (Esc)",
+    ' ',        "",
+    CTRL('B'),    " Current score (if you win)",
+    CTRL('E'),    " Current food level",
+    CTRL('L'),    " Redraw the screen",
+    CTRL('N'),    " Name an object or a monster",
+    CTRL('O'),    " Character affect status",
+    CTRL('R'),    " Repeat last message",
+    CTRL('T'),    "<dir>    Take (steal) from (direction)",
+    CTRL('U'),    " Use a magic item",
+    0, 0
+} ;
+
+/* wizard help list */
+static struct h_list wiz_help[] = {
+    ' ',        "",
+    '+',        "   Random fortunes",
+    'M',        "   Make an object",
+    'V',        "   Display vlevel and turns",
+    CTRL('A'),    " System activity",
+    CTRL('C'),    " Move to another dungeon level",
+    CTRL('D'),    " Go down 1 dungeon level",
+    CTRL('F'),    " Display the entire level",
+    CTRL('G'),    " Charge wands and staffs",
+    CTRL('H'),    " Jump 9 experience levels",
+    CTRL('I'),    " Inventory of level",
+    CTRL('J'),    " Teleport somewhere",
+    CTRL('K'),    " Identify an object",
+    CTRL('M'),    " Recharge wand or staff",
+    CTRL('P'),    " Toggle wizard status",
+    CTRL('X'),    " Detect monsters",
+    CTRL('Y'),    " Display food levels",
+    0, 0
+};
+
+/* item help list */
+static struct item_list item_help[] = {
+    '@',   "   You (visible)",
+    '_',   "   You (invisible)",
+    ' ',   "",
+    ':',   "   Food ration or fruit (eat)",
+    '!',   "   Potion (quaff)",
+    '?',   "   Scroll (read)",
+    '=',   "   Ring (wear)",
+    ')',   "   Weapon (wield)",
+    ']',   "   Armor (wear)",
+    '/',   "   Wand or staff (zap)",
+    ';',   "   Magic item (use)",
+    ',',   "   Artifact (quest item)",
+    '*',   "   Gold or zapped missile",
+    ' ',   "",
+    '$',   "   Magical item in room",
+    '>',   "   Blessed magical item",
+    '<',   "   Cursed magical item",
+    ' ',   " ",
+    '`',   "   Dart trap",
+    '{',   "   Arrow trap",
+    '}',   "   Bear trap",
+    '~',   "   Teleport trap",
+    '$',   "   Sleeping gas trap",
+    '>',   "   Trap door",
+    '<',   "   Outer region entrance",
+    '\'',   "   Maze entrance",
+    '^',   "   Trading post entrance",
+    '"',   "   Magic pool or lake",
+    ' ',   "   Solid rock or mountain",
+    '.',   "   Floor of a room or meadow",
+    '%',   "   Stairs (up or down)",
+    '+',   "   Doorway",
+    '&',   "   Secret doorway",
+    '#',   "   Passage between rooms",
+    '\\',   "   Forest",
+    HORZWALL,   "   Horizontal wall of a room",
+    VERTWALL,   "   Vertical wall of a room",
+    0, 0
+};
+
+ident_hero()
+{
+    bool doit = TRUE;
+
+    wclear(hw);
+    wprintw(hw, "Characters, Items, and Game Descriptions:\n");
+    wprintw(hw, "-----------------------------------------\n");
+    wprintw(hw, "a) Fighter        m) Scrolls\n");
+    wprintw(hw, "b) Thief          n) Rings\n");
+    wprintw(hw, "c) Assassin       o) Wands and Staffs\n");
+    wprintw(hw, "d) Ranger         p) Weapons\n");
+    wprintw(hw, "e) Paladin        q) Armors\n");
+    wprintw(hw, "f) Monk           r) Miscellaneous Magic Items\n");
+    wprintw(hw, "g) Magician       s) Quest Items (Artifacts and Relics)\n");
+    wprintw(hw, "h) Cleric         t) The Dungeon\n");
+    wprintw(hw, "i) Druid          u) Traps\n");
+    wprintw(hw, "j) Monsters       v) Mazes and Outer Regions\n");
+    wprintw(hw, "k) Foods          w) Setting game options\n");
+    wprintw(hw, "l) Potions        x) Starting out\n");
+    wprintw(hw, "\nEnter a letter: ");
+    draw(hw);
+    while (doit) {
+    switch (wgetch(cw)) {
+       case EOF:
+       case ESC:
+        doit = FALSE;
+       when 'a':
+            wclear(hw);
+            wprintw(hw, "Fighter Characteristics:");
+            mvwaddstr(hw, 2, 0, game_fighter);
+        draw(hw);
+        doit = FALSE;
+       when 'b':
+            wclear(hw);
+            wprintw(hw, "Thief Characteristics:");
+            mvwaddstr(hw, 2, 0, game_thief);
+        draw(hw);
+        doit = FALSE;
+       when 'c':
+            wclear(hw);
+            wprintw(hw, "Assassin Characteristics:");
+            mvwaddstr(hw, 2, 0, game_assassin);
+            draw(hw);
+        doit = FALSE;
+        when 'd':
+            wclear(hw);
+            wprintw(hw, "Ranger Characteristics:");
+            mvwaddstr(hw, 2, 0, game_ranger);
+            draw(hw);
+        doit = FALSE;
+        when 'e':
+            wclear(hw);
+            wprintw(hw, "Paladin Characteristics:");
+            mvwaddstr(hw, 2, 0, game_paladin);
+            draw(hw);
+        doit = FALSE;
+        when 'f':
+            wclear(hw);
+            wprintw(hw, "Monk Characteristics:");
+            mvwaddstr(hw, 2, 0, game_monk);
+            draw(hw);
+        doit = FALSE;
+        when 'g':
+            wclear(hw);
+            wprintw(hw, "Magician Characteristics:");
+            mvwaddstr(hw, 2, 0, game_magician);
+            draw(hw);
+        doit = FALSE;
+        when 'h':
+            wclear(hw);
+            wprintw(hw, "Cleric Characteristics:");
+            mvwaddstr(hw, 2, 0, game_cleric);
+            draw(hw);
+        doit = FALSE;
+        when 'i':
+            wclear(hw);
+            wprintw(hw, "Druid Characteristics:");
+            mvwaddstr(hw, 2, 0, game_druid);
+            draw(hw);
+        doit = FALSE;
+        when 'j':
+            wclear(hw);
+            wprintw(hw, "Monster Characteristics:");
+            draw(hw);
+        doit = FALSE;
+        when 'k':
+            wclear(hw);
+            wprintw(hw, "Foods:");
+            mvwaddstr(hw, 2, 0, game_food);
+            draw(hw);
+        doit = FALSE;
+        when 'l':
+            wclear(hw);
+            wprintw(hw, "Potions:");
+            draw(hw);
+        doit = FALSE;
+        when 'm':
+            wclear(hw);
+            wprintw(hw, "Scrolls:");
+            draw(hw);
+        doit = FALSE;
+        when 'n':
+            wclear(hw);
+            wprintw(hw, "Rings:");
+            draw(hw);
+        doit = FALSE;
+        when 'o':
+            wclear(hw);
+            wprintw(hw, "Wands and Staffs:");
+            draw(hw);
+        doit = FALSE;
+        when 'p':
+            wclear(hw);
+            wprintw(hw, "Weapons:");
+            draw(hw);
+        doit = FALSE;
+        when 'q':
+            wclear(hw);
+            wprintw(hw, "Armors:");
+            draw(hw);
+        doit = FALSE;
+        when 'r':
+            wclear(hw);
+            wprintw(hw, "Miscellaneous Magic Items:");
+            draw(hw);
+        doit = FALSE;
+        when 's':
+            wclear(hw);
+            wprintw(hw, "Quest Items (Artifacts and Relics):");
+            draw(hw);
+        doit = FALSE;
+        when 't':
+            wclear(hw);
+            wprintw(hw, "The Dungeon:");
+            draw(hw);
+        doit = FALSE;
+        when 'u':
+            wclear(hw);
+            wprintw(hw, "Traps:");
+            draw(hw);
+        doit = FALSE;
+        when 'v':
+            wclear(hw);
+            wprintw(hw, "Mazes and Outer Regions:");
+            draw(hw);
+        doit = FALSE;
+        when 'w':
+            wclear(hw);
+            wprintw(hw, "Setting game options:");
+            draw(hw);
+        doit = FALSE;
+        when 'x':
+            wclear(hw);
+            wprintw(hw, "Starting out:");
+            draw(hw);
+        doit = FALSE;
+        otherwise:
+        doit = TRUE;
+    }
+    }
+    wmove(hw, lines-1, 0);
+    wprintw(hw, spacemsg);
+    draw(hw);
+    wait_for(' ');
+    wclear(hw);
+    draw(hw);
+    wmove(cw, 0, 0);
+    wclrtoeol(cw);
+    status(FALSE);
+    touchwin(cw);
+}
+
+/*
+ * Real Help
+ */
+
+help()
+{
+    register struct h_list *strp = helpstr;
+    register struct item_list *itemp = item_help;
+    struct h_list *wizp = wiz_help;
+    register char helpch;
+    register int cnt;
+
+    msg("Character you want help for (* for commands, @ for items): ");
+    helpch = wgetch(cw);
+    mpos = 0;
+    /*
+     * If it's not a *, @, or +, then just print help string
+     * for the character entered.  
+     */
+    if (helpch != '*' && helpch != '@' && helpch != '+') {
+        wmove(msgw, 0, 0);
+        while (strp->h_ch) {
+            if (strp->h_ch == helpch) {
+                msg("%s%s", unctrl(strp->h_ch), strp->h_desc);
+                return;
+            }
+            strp++;
+        }
+        if (wizard) {
+            while (wizp->h_ch) {
+                if (wizp->h_ch == helpch) {
+                    msg("%s%s", unctrl(wizp->h_ch), wizp->h_desc);
+                    return;
+                }
+                wizp++;
+            }
+        }
+        msg("Unknown command '%s'", unctrl(helpch));
+        return;
+    }
+
+    /* fortunes - but let's not say so - explicitly */
+    if (helpch == '+') {
+    msg("Meaningless command '+'");
+    return;
+    }
+
+    /*
+     * Print help for everything else
+     */
+    if (helpch == '*') {
+        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);
+            strp++;
+            if (++cnt >= 46 && strp->h_ch) {
+                wmove(hw, lines-1, 0);
+                wprintw(hw, morestr);
+                draw(hw);
+                wait_for(' ');
+                wclear(hw);
+                cnt = 0;
+            }
+        }
+        if (wizard) {
+            while (wizp->h_ch) {
+                mvwaddstr(hw, cnt % 23, cnt > 22 ? 40 : 0, unctrl(wizp->h_ch));
+                waddstr(hw, wizp->h_desc);
+                wizp++;
+                if (++cnt >= 46 && wizp->h_ch) {
+                    wmove(hw, lines-1, 0);
+                    wprintw(hw, morestr);
+                    draw(hw);
+                    wait_for(' ');
+                    wclear(hw);
+                    cnt = 0;
+                }
+            }
+        }
+    }
+    if (helpch == '@') {
+        wclear(hw);
+        cnt = 0;
+        while (itemp->item_ch) {
+            mvwaddstr(hw, cnt % 23, cnt > 22 ? 40 : 0, unctrl(itemp->item_ch));
+            waddstr(hw, itemp->item_desc);
+            itemp++;
+            if (++cnt >= 46 && itemp->item_ch) {
+                wmove(hw, lines-1, 0);
+                wprintw(hw, morestr);
+                draw(hw);
+                wait_for(' ');
+                wclear(hw);
+                cnt = 0;
+            }
+        }
+    }
+    wmove(hw, lines-1, 0);
+    wprintw(hw, spacemsg);
+    draw(hw);
+    wait_for(' ');
+    wclear(hw);
+    draw(hw);
+    wmove(cw, 0, 0);
+    wclrtoeol(cw);
+    status(FALSE);
+    touchwin(cw);
+}
+
+/*
+ * identify:
+ *      Tell the player what a certain thing is.
+ */
+
+identify(ch)
+register unsigned char ch;
+{
+    register char *str = NULL;
+
+    if (ch == 0) {
+        msg("What do you want identified? ");
+        ch = wgetch(cw);
+        mpos = 0;
+        if (ch == ESC)
+        {
+            msg("");
+            return;
+        }
+    }
+    if (isalpha(ch))
+        msg("Use the \"=\" command to identify monsters. ");
+    else switch(ch)
+    {
+        case VPLAYER:   str = "You (visibly)";
+        when IPLAYER:   str = "You (invisibly)";
+        when GOLD:      str = "Gold";
+        when STAIRS:    str = (levtype == OUTSIDE) ? "Entrance to the dungeon"
+                                                   : "Stairway";
+        when DOOR:      str = "Doorway";
+        when SECRETDOOR:str = "Secret door";
+        when FLOOR:     str = (levtype == OUTSIDE) ? "Meadow" : "Room floor";
+        when PASSAGE:   str = "Passage";
+        when VERTWALL:
+        case HORZWALL:
+            str = (levtype == OUTSIDE) ? "Boundary of sector"
+                                       : "Wall of a room";
+        when POST:      str = "Trading post";
+        when POOL:      str = (levtype == OUTSIDE) ? "Lake"
+                                                   : "A shimmering pool";
+        when TRAPDOOR:  str = "Trap door";
+        when ARROWTRAP: str = "Arrow trap";
+        when SLEEPTRAP: str = "Sleeping gas trap";
+        when BEARTRAP:  str = "Bear trap";
+        when TELTRAP:   str = "Teleport trap";
+        when DARTTRAP:  str = "Dart trap";
+        when MAZETRAP:  str = "Entrance to a maze";
+        when WORMHOLE:  str = "Entrance to a worm hole";
+        when FOREST:    str = "Forest";
+        when ' ' :      str = (levtype == OUTSIDE) ? "Mountain"
+                                                   : "Solid rock";
+        when FOOD:      str = "Food";
+        when POTION:    str = "Potion";
+        when SCROLL:    str = "Scroll";
+        when RING:      str = "Ring";
+        when WEAPON:    str = "Weapon";
+        when ARMOR:     str = "Armor";
+        when MM:        str = "Miscellaneous magic";
+        when STICK:     str = "Wand or staff";
+        when RELIC:     str = "Artifact";
+        otherwise:      str = "Unknown character";
+    }
+    if (!isalpha(ch))
+        msg("%s     %s", unctrl(ch), str);
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xrogue/init.c	Tue Apr 21 08:55:20 2015 -0400
@@ -0,0 +1,825 @@
+/*
+    init.c - global variable initializaton
+ 
+    XRogue: Expeditions into the Dungeons of Doom
+    Copyright (C) 1991 Robert Pietkivitch
+    All rights reserved.
+    
+    Based on "Advanced Rogue"
+    Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka and AT&T
+    All rights reserved.
+
+    Based on "Rogue: Exploring the Dungeons of Doom"
+    Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
+    All rights reserved.
+    
+    See the file LICENSE.TXT for full copyright and licensing information.
+*/ 
+
+#include <curses.h>
+#include <ctype.h>
+#include "rogue.h"
+#include "mach_dep.h"
+
+/*
+ * If there is any news, put it in a character string and assign it to
+ * rogue_news.  Otherwise, assign NULL to rogue_news.
+ */
+
+static char *rogue_news = "Enter a number within the minimum and maximum \
+range.  When satisfied with your  choices, enter a 'y'.  For help at any \
+other time enter a '?' or a '='.";
+
+/* replace the above line with this when descriptions are done  */
+/* other time enter a '?' or a '='.         For character and item descriptions \
+enter a '\\' on any other screen.";
+*/
+
+struct words rainbow[NCOLORS] = {
+"Amber",                "Aquamarine",           "Beige",
+"Black",                "Blue",                 "Brown",
+"Clear",                "Crimson",              "Ecru",
+"Gold",                 "Green",                "Grey",
+"Indigo",               "Khaki",                "Lavender",
+"Magenta",              "Orange",               "Pink",
+"Plaid",                "Purple",               "Red",
+"Silver",               "Saffron",              "Scarlet",
+"Tan",                  "Tangerine",            "Topaz",
+"Turquoise",            "Vermilion",            "Violet",
+"White",                "Yellow",
+};
+
+struct words sylls[NSYLLS] = {
+    "a",   "ae",  "ak",  "an",  "ax",  "ach", "ano", "ars", "bha", "bar", "bre",
+    "cha", "cre", "cum", "cow", "duh", "dha", "e",   "ea",  "em",  "et",  "ey",
+    "eck", "etk", "egg", "exl", "fu",  "fen", "fid", "gan", "gle", "h",   "ha",
+    "hr",  "ht",  "how", "hex", "hip", "hoc", "i",   "ia",  "ig",  "it",  "iz",
+    "ion", "ink", "ivi", "iss", "je",  "jin", "jha", "jyr", "ka",  "kho", "kal",
+    "kli", "lu",  "lre", "lta", "lri", "m",   "ma",  "mh",  "mi",  "mr",  "mar",
+    "myr", "moh", "mul", "nep", "nes", "o",   "oc",  "om",  "oq",  "ox",  "orn",
+    "oxy", "olm", "ode", "po",  "pie", "pod", "pot", "qar", "que", "ran", "rah",
+    "rok", "sa",  "sat", "sha", "sol", "sri", "ti",  "tem", "tar", "tki", "tch",
+    "tox", "u",   "ub",  "uh",  "ur",  "uv",  "unk", "uwh", "ugh", "uyr", "va",
+    "vil", "vit", "vom", "vux", "wah", "wex", "xu",  "xed", "xen", "ya",  "yep",
+    "yih", "zef", "zen", "zil", "zym", "-"
+};
+
+struct words stones[NSTONES] = {
+        "Agate",                "Alexandrite",          "Amethyst",
+        "Azurite",              "Bloodstone",           "Cairngorm",
+        "Carnelian",            "Chalcedony",           "Chrysoberyl",
+        "Chrysolite",           "Chrysoprase",          "Citrine",
+        "Coral",                "Diamond",              "Emerald",
+        "Garnet",               "Heliotrope",           "Hematite",
+        "Hyacinth",             "Jacinth",              "Jade",
+        "Jargoon",              "Jasper",               "Kryptonite",
+        "Lapis lazuli",         "Malachite",            "Mocca stone",
+        "Moonstone",            "Obsidian",             "Olivine",
+        "Onyx",                 "Opal",                 "Pearl",
+        "Peridot",              "Quartz",               "Rhodochrosite",
+        "Rhodolite",            "Ruby",                 "Sapphire",
+        "Sardonyx",             "Serpentine",           "Spinel",
+        "Tiger eye",            "Topaz",                "Tourmaline",
+        "Turquoise",            "Zircon",
+};
+
+struct words wood[NWOOD] = {
+        "Avocado wood", "Balsa",        "Banyan",       "Birch",
+        "Cedar",        "Cherry",       "Cinnabar",     "Dogwood",
+        "Driftwood",    "Ebony",        "Eucalyptus",   "Hemlock",
+        "Ironwood",     "Mahogany",     "Manzanita",    "Maple",
+        "Oak",          "Pine",         "Redwood",      "Rosewood",
+        "Teak",         "Walnut",       "Aloe",         "Sandalwood",
+};
+
+struct words metal[NMETAL] = {
+        "Aluminium",    "Bone",         "Brass",        "Bronze",
+        "Copper",       "Chromium",     "Iron",         "Lead",
+        "Magnesium",    "Pewter",       "Platinum",     "Silver",
+        "Steel",        "Tin",          "Titanium",     "Zinc",
+};
+
+/*
+ * make sure all the percentages specified in the tables add up to the
+ * right amounts
+ */
+
+badcheck(name, magic, bound)
+char *name;
+register struct magic_item *magic;
+register int bound;
+{
+    register struct magic_item *end;
+
+    if (magic[bound - 1].mi_prob == 1000)
+        return;
+    printf("\nBad percentages for %s:\n", name);
+    for (end = &magic[bound] ; magic < end ; magic++)
+        printf("%4d%% %s\n", magic->mi_prob, magic->mi_name);
+    printf(retstr);
+    fflush(stdout);
+    while (getchar() != '\n')
+        continue;
+}
+
+/*
+ * init_colors:
+ *      Initialize the potion color scheme for this time
+ */
+
+init_colors()
+{
+    register int i;
+    register char *str;
+
+    for (i = 0 ; i < MAXPOTIONS ; i++)
+    {
+        do
+            str = rainbow[rnd(NCOLORS)].w_string;
+        until (isupper(*str));
+        *str = tolower(*str);
+        p_colors[i] = str;
+        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);
+}
+
+/*
+ * do any initialization for food
+ */
+
+init_foods()
+{
+    register int i;
+
+    for (i=0; i < MAXFOODS; i++) {
+        if (i > 0)
+            foods[i].mi_prob += foods[i-1].mi_prob;
+    }
+    badcheck("foods", foods, MAXFOODS);
+}
+
+/*
+ * init_materials:
+ *      Initialize the construction materials for wands and staffs
+ */
+
+init_materials()
+{
+    register int i;
+    register char *str;
+
+    for (i = 0 ; i < MAXSTICKS ; i++)
+    {
+        do
+            if (rnd(100) > 50)
+            {
+                str = metal[rnd(NMETAL)].w_string;
+                if (isupper(*str))
+                        ws_type[i] = "wand";
+            }
+            else
+            {
+                str = wood[rnd(NWOOD)].w_string;
+                if (isupper(*str))
+                        ws_type[i] = "staff";
+            }
+        until (isupper(*str));
+        *str = tolower(*str);
+        ws_made[i] = str;
+        ws_know[i] = FALSE;
+        ws_guess[i] = NULL;
+        if (i > 0)
+                ws_magic[i].mi_prob += ws_magic[i-1].mi_prob;
+    }
+    badcheck("sticks", ws_magic, MAXSTICKS);
+}
+
+/*
+ * do any initialization for miscellaneous magic
+ */
+
+init_misc()
+{
+    register int i;
+
+    for (i=0; i < MAXMM; i++) {
+        m_know[i] = FALSE;
+        m_guess[i] = NULL;
+        if (i > 0)
+            m_magic[i].mi_prob += m_magic[i-1].mi_prob;
+    }
+    badcheck("miscellaneous magic", m_magic, MAXMM);
+}
+
+/*
+ * init_names:
+ *      Generate the names of the various scrolls
+ */
+
+init_names()
+{
+    register int nsyl;
+    register char *cp, *sp;
+    register int i, nwords;
+
+    for (i = 0 ; i < MAXSCROLLS ; i++)
+    {
+        cp = prbuf;
+        nwords = rnd(cols/20) + 1 + (cols > 40 ? 1 : 0);
+        while(nwords--)
+        {
+            nsyl = rnd(5)+1;
+            while(nsyl--)
+            {
+                sp = sylls[rnd(NSYLLS)].w_string;
+                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_player:
+ *      roll up the rogue
+ */
+
+init_player()
+{
+    int stat_total, round = 0, minimum, maximum, ch, i, j = 0;
+    short do_escape, *our_stats[NUMABILITIES-1];
+    struct linked_list  *weap_item, *armor_item, *food_item;
+    struct object *obj;
+
+    weap_item = armor_item = food_item = NULL;
+
+    if (char_type == -1) {  /* not set via options */
+        /* See what type character will be */
+        wclear(hw);
+        touchwin(hw);
+        wmove(hw,2,0);
+        for(i=1; i<=NUM_CHARTYPES-1; i++) {
+            wprintw(hw,"[%d] %s\n",i,char_class[i-1].name);
+        }
+        mvwaddstr(hw, 0, 0, "What character class do you desire? ");
+        draw(hw);
+        char_type = (wgetch(hw) - '0');
+        while (char_type < 1 || char_type > NUM_CHARTYPES-1) {
+            wmove(hw,0,0);
+            wprintw(hw,"Please enter a character type between 1 and %d: ",
+                    NUM_CHARTYPES-1);
+            draw(hw);
+            char_type = (wgetch(hw) - '0');
+        }
+        char_type--;
+    }
+    player.t_ctype = char_type;
+    player.t_quiet = 0;
+    pack = NULL;
+
+    /* Select the gold */
+    purse = 3000;
+    switch (player.t_ctype) {
+        case C_FIGHTER:
+            purse += 200;
+        when C_MAGICIAN:
+        case C_CLERIC:
+        case C_DRUID:
+            purse += 100;
+        when C_THIEF:
+        case C_ASSASSIN:
+        purse += 0;
+        when C_RANGER:
+        case C_PALADIN:
+            purse -= 100;
+        when C_MONK:
+            purse -= 200;
+    }
+    /* 
+     * allow me to describe a super character 
+     */
+        /* let's lessen the restrictions on this okay? */
+    if (wizard && strcmp(getenv("SUPER"),"YES") == 0) {
+        pstats.s_str = MAXATT;
+        pstats.s_intel = MAXATT;
+        pstats.s_wisdom = MAXATT;
+        pstats.s_dext = MAXATT;
+        pstats.s_const = MAXATT;
+        pstats.s_charisma = MAXATT;
+        pstats.s_exp = 10000000L;
+        pstats.s_lvl = 1;
+        pstats.s_lvladj = 0;
+        pstats.s_hpt = 500;
+        pstats.s_carry = totalenc(&player);
+        strcpy(pstats.s_dmg,"4d8");
+        check_level();
+        wmove(hw,0,0);
+        wclrtoeol(hw);
+        draw(hw);
+        mpos = 0;
+
+    /* set quest item */
+    if(player.t_ctype == C_FIGHTER)  quest_item = AXE_AKLAD;
+    if(player.t_ctype == C_RANGER)   quest_item = BRIAN_MANDOLIN;
+    if(player.t_ctype == C_PALADIN)  quest_item = HEIL_ANKH;
+    if(player.t_ctype == C_MAGICIAN) quest_item = STONEBONES_AMULET;
+    if(player.t_ctype == C_CLERIC)   quest_item = GERYON_HORN;
+    if(player.t_ctype == C_THIEF)    quest_item = MUSTY_DAGGER;
+    if(player.t_ctype == C_ASSASSIN) quest_item = EYE_VECNA;
+    if(player.t_ctype == C_DRUID)    quest_item = QUILL_NAGROM;
+    if(player.t_ctype == C_MONK)     quest_item = EMORI_CLOAK;
+
+    /* armor */
+        if (player.t_ctype == C_THIEF || player.t_ctype == C_ASSASSIN)
+            j = STUDDED_LEATHER;
+        else if (player.t_ctype == C_MONK) {
+        armor_item = spec_item(MM, MM_BRACERS, 20, 0);
+        obj = OBJPTR(armor_item);
+            obj->o_weight = things[TYP_MM].mi_wght;
+        whatis (armor_item);  /* identify it */
+            obj->o_flags |= (ISKNOW | ISPROT);
+            add_pack(armor_item, TRUE);
+            cur_misc[WEAR_BRACERS] = obj;
+        goto w_armorjmp; 
+    }
+        else j =  PLATE_ARMOR;
+
+        armor_item = spec_item(ARMOR, j, 20, 0);
+        obj = OBJPTR(armor_item);
+        obj->o_weight = armors[j].a_wght;
+        obj->o_flags |= (ISKNOW | ISPROT);
+        add_pack(armor_item, TRUE);
+        cur_armor = obj;
+
+    w_armorjmp:  /* monk doesn't wear armor */
+
+        /* weapons */
+        if (player.t_ctype == C_THIEF || player.t_ctype == C_ASSASSIN ||
+            player.t_ctype == C_MONK) 
+        j = BASWORD;
+        else if (player.t_ctype == C_FIGHTER || player.t_ctype == C_RANGER ||
+        player.t_ctype == C_PALADIN)
+        j = TWOSWORD;
+    else j = TRIDENT;
+
+        weap_item = spec_item(WEAPON, j, 20, 20);
+        obj = OBJPTR(weap_item);
+        obj->o_flags |= (ISKNOW | ISPROT);
+        obj->o_weight = weaps[j].w_wght;
+        add_pack(weap_item, TRUE);
+        cur_weapon = obj;
+
+    /* food */
+        food_item = spec_item(FOOD, E_RATION, 0, 0);
+        obj = OBJPTR(food_item);
+        obj->o_flags |= ISKNOW;
+        obj->o_weight = foods[TYP_FOOD].mi_wght;
+        add_pack(food_item, TRUE); /* just one */
+
+    /* give wizard plenty gold */
+        purse = 50000;
+    }
+    else 
+    /* default attributes checked */
+    {
+    if (def_attr == TRUE) {  /* "default" option used in ROGUEOPTS */
+    switch(player.t_ctype) {
+        /* set "default attributes" option and quest items here */
+        case C_FIGHTER:
+        case C_MONK:
+                pstats.s_intel = 7;
+                pstats.s_dext = 16;
+                pstats.s_charisma = 11;
+            if (player.t_ctype == C_FIGHTER) {
+                    pstats.s_str = 16;
+                    pstats.s_wisdom = 7;
+                    pstats.s_const = 17;
+                quest_item = AXE_AKLAD;
+        }
+        else {
+                    pstats.s_str = 11;
+                    pstats.s_wisdom = 11;
+                    pstats.s_const = 18;
+                quest_item = EMORI_CLOAK;
+        }
+        when C_RANGER:
+        case C_PALADIN:
+                pstats.s_str = 11;
+                pstats.s_dext = 16;
+                pstats.s_const = 16;
+                pstats.s_charisma = 13;
+            /* intelligence or wisdom */
+            if (player.t_ctype == C_RANGER) {
+                    pstats.s_intel = 11;
+                    pstats.s_wisdom = 7;
+                quest_item = BRIAN_MANDOLIN;
+            }
+            else {
+                    pstats.s_intel = 7;
+                    pstats.s_wisdom = 11;
+                quest_item = HEIL_ANKH;
+            }
+        when C_THIEF:
+        case C_ASSASSIN:
+                pstats.s_intel = 7;
+                pstats.s_str = 14;
+                pstats.s_wisdom = 7;
+                pstats.s_dext = 18;
+                pstats.s_const = 17;
+                pstats.s_charisma = 11;
+            if (player.t_ctype == C_THIEF) 
+                quest_item = MUSTY_DAGGER;
+            else
+                quest_item = EYE_VECNA;
+        when C_MAGICIAN:
+        case C_CLERIC:
+        case C_DRUID:
+                pstats.s_str = 10;
+                pstats.s_dext = 16;
+                pstats.s_const = 15;
+                pstats.s_charisma = 12;
+            /* intelligence & wisdom */
+            if (player.t_ctype == C_MAGICIAN) {
+                    pstats.s_intel = 14;
+                    pstats.s_wisdom = 7;
+            }
+            else {
+                    pstats.s_intel = 7;
+                    pstats.s_wisdom = 14;
+            }
+            if (player.t_ctype == C_MAGICIAN) 
+                quest_item = STONEBONES_AMULET;
+            else if (player.t_ctype == C_CLERIC) 
+                quest_item = GERYON_HORN;
+            else
+                quest_item = QUILL_NAGROM;
+    }
+        /* Intialize */
+        pstats.s_exp = 0L;
+        pstats.s_lvl = 1;
+        pstats.s_lvladj = 0;
+        pstats.s_exp = 0L;
+        strcpy(pstats.s_dmg,"2d4");
+        pstats.s_carry = totalenc(&player);
+        check_level();
+        wmove(hw,0,0);
+        wclrtoeol(hw);
+        draw(hw);
+        mpos = 0;
+
+        /* Get the hit points. */
+        pstats.s_hpt = 12 + const_bonus();  /* Base plus bonus */
+
+        /* Add in the component that varies according to class */
+        pstats.s_hpt += char_class[player.t_ctype].hit_pts;
+
+        /* dole out some armor */
+        if (player.t_ctype == C_THIEF || player.t_ctype == C_ASSASSIN)
+        j = STUDDED_LEATHER;
+        else if (player.t_ctype == C_FIGHTER || player.t_ctype == C_RANGER ||
+             player.t_ctype == C_PALADIN) {
+         switch (rnd(4)) {
+             case 0:         j = PLATE_ARMOR;
+             when 1:         j = PLATE_MAIL;
+             when 2: case 3: j = BANDED_MAIL;
+        }
+    }
+        else if (player.t_ctype == C_MONK) {
+        if (rnd(3) == 0) j = MM_PROTECT;
+        else j = MM_BRACERS;
+        armor_item = spec_item(MM, j, rnd(125)/60+3, 0);
+        obj = OBJPTR(armor_item);
+            obj->o_weight = things[TYP_MM].mi_wght;
+        whatis (armor_item);  /* identify it */
+            obj->o_flags |= ISKNOW;
+            add_pack(armor_item, TRUE);
+        goto p_armorjmp;
+    }
+    else {  /* other characters */
+        switch (rnd(7)) {
+        case 0:         j = PLATE_MAIL;
+        when 1: case 2: j = BANDED_MAIL;
+        when 3: case 4: j = SPLINT_MAIL;
+        when 5: case 6: j = PADDED_ARMOR;
+        }
+    }
+        armor_item = spec_item(ARMOR, j, rnd(100)/85, 0);
+        obj = OBJPTR(armor_item);
+        obj->o_weight = armors[j].a_wght;
+        obj->o_flags |= ISKNOW;
+        add_pack(armor_item, TRUE);
+
+    p_armorjmp:  /* monk doesn't wear armor */
+
+        /* give him a weapon */
+        if (player.t_ctype == C_THIEF || player.t_ctype == C_ASSASSIN ||
+            player.t_ctype == C_MONK) {
+        switch (rnd(5)) {
+        case 0:         j = BASWORD;
+        when 1: case 2: j = TRIDENT;
+        when 3: case 4: j = BARDICHE;
+        }
+    }
+        else if (player.t_ctype == C_FIGHTER || player.t_ctype == C_RANGER ||
+        player.t_ctype == C_PALADIN) {
+        switch (rnd(5)) {
+        case 0:         j= TWOSWORD;
+        when 1: case 2: j= TRIDENT;
+        when 3: case 4: j= SWORD;
+        }
+    }
+        else {
+        switch (rnd(7)) {
+        case 0:         j = TRIDENT;
+        when 1: case 2: j = SWORD;
+        when 3: case 4: j = BARDICHE;
+        when 5:         j = MACE;
+        when 6:         j = SPETUM;
+        }
+    }
+        weap_item = spec_item(WEAPON, j, rnd(155)/75, rnd(165)/80);
+        obj = OBJPTR(weap_item);
+        obj->o_weight = weaps[j].w_wght;
+        obj->o_flags |= ISKNOW;
+        add_pack(weap_item, TRUE);
+
+        /* food rations */
+        food_item = spec_item(FOOD, E_RATION, 0, 0);
+        obj = OBJPTR(food_item);
+        obj->o_weight = foods[TYP_FOOD].mi_wght;
+        obj->o_flags |= ISKNOW;
+        add_pack(food_item, TRUE);
+
+    /* give him some fruit - coose from those w/o special effects */
+    switch (rnd(6)) {
+        case 0: j = E_BANANA;
+        when 1: j = E_BLUEBERRY;
+        when 2: j = E_ELDERBERRY;
+        when 3: j = E_GUANABANA;
+        when 4: j = E_CAPRIFIG;
+        when 5: j = E_GOOSEBERRY;
+    }
+        food_item = spec_item(FOOD, j, 0, 0);
+        obj = OBJPTR(food_item);
+        obj->o_weight = foods[TYP_FOOD].mi_wght;
+        obj->o_flags |= ISKNOW;
+        add_pack(food_item, TRUE);
+
+    /* adjust purse */
+    purse = 2000;
+    }
+    else {  /* select attibutes */
+        switch(player.t_ctype) {
+            case C_FIGHTER:     round = A_STRENGTH;
+            when C_RANGER:      round = A_CHARISMA;
+            when C_PALADIN:     round = A_CHARISMA;
+            when C_MAGICIAN:    round = A_INTELLIGENCE;
+            when C_CLERIC:      round = A_WISDOM;
+            when C_THIEF:       round = A_DEXTERITY;
+            when C_ASSASSIN:    round = A_DEXTERITY;
+            when C_DRUID:       round = A_WISDOM;
+            when C_MONK:        round = A_CONSTITUTION;
+        }
+
+        do {
+            wclear(hw);
+
+            /* If there is any news, display it */
+            if (rogue_news) {
+                register int i;
+
+                /* Print a separator line */
+                wmove(hw, 12, 0);
+                for (i=0; i<cols; i++) waddch(hw, '-');
+
+                /* Print the news */
+                mvwaddstr(hw, 14, 0, rogue_news);
+            }
+
+            stat_total = MAXSTATS;
+            do_escape = FALSE;  /* No escape seen yet */
+
+            /* Initialize abilities */
+            pstats.s_intel = 0;
+            pstats.s_str = 0;
+            pstats.s_wisdom = 0;
+            pstats.s_dext = 0;
+            pstats.s_const = 0;
+            pstats.s_charisma = 0;
+
+            /* Initialize pointer into abilities */
+            our_stats[A_INTELLIGENCE] = &pstats.s_intel;
+            our_stats[A_STRENGTH] = &pstats.s_str;
+            our_stats[A_WISDOM] = &pstats.s_wisdom;
+            our_stats[A_DEXTERITY] = &pstats.s_dext;
+            our_stats[A_CONSTITUTION] = &pstats.s_const;
+
+            /* Let player distribute attributes */
+            for (i=0; i<NUMABILITIES-1; i++) {
+                wmove(hw, 2, 0);
+                wprintw(hw, "You are creating a %s with %2d attribute points.",
+                                char_class[player.t_ctype].name, stat_total);
+
+                /*
+                 * Player must have a minimum of 7 in any attribute and 11 in
+                 * the player's primary attribute.
+                 */
+                minimum = (round == i ? 11 : 7);
+
+                /* Subtract out remaining minimums */
+                maximum = stat_total - (7 * (NUMABILITIES-1 - i));
+
+                /* Subtract out remainder of profession minimum (11 - 7) */
+                if (round > i) maximum -= 4;
+
+                /* Maximum can't be greater than 18 */
+                if (maximum > 18) maximum = 18;
+
+                wmove(hw, 4, 0);
+                wprintw(hw,
+                   "Minimum: %2d;  Maximum: %2d  (%s corrects previous entry)",
+                   minimum, maximum, unctrl('\b'));
+
+                wmove(hw, 6, 0);
+                wprintw(hw, "    Int: %-2d", pstats.s_intel);
+                wprintw(hw, "    Str: %-2d", pstats.s_str);
+                wprintw(hw, "    Wis: %-2d", pstats.s_wisdom); 
+                wprintw(hw, "    Dex: %-2d", pstats.s_dext);
+                wprintw(hw, "    Con: %-2d", pstats.s_const);
+                wprintw(hw, "    Cha: %-2d", pstats.s_charisma);
+                wclrtoeol(hw);
+                wmove(hw, 6, 11*i + 9);
+                if (do_escape == FALSE) draw(hw);
+
+                /* Get player's input */
+                if (do_escape || maximum == minimum) {
+                    *our_stats[i] = maximum;
+                    stat_total -= maximum;
+                }
+                else for (;;) {
+                    ch = wgetch(hw);
+                    if (ch == '\b') {   /* Backspace */
+                        if (i == 0) continue;   /* Can't move back */
+                        else {
+                            stat_total += *our_stats[i-1];
+                            *our_stats[i] = 0;
+                            *our_stats[i-1] = 0;
+                            i -= 2;     /* Back out */
+                            break;
+                        }
+                    }
+                    if (ch == '\033') { /* Escape */
+                        /*
+                         * Escape will result in using all maximums for
+                         * remaining abilities.
+                         */
+                        do_escape = TRUE;
+                        *our_stats[i] = maximum;
+                        stat_total -= maximum;
+                        break;
+                    }
+
+                    /* Do we have a legal digit? */
+                    if (ch >= '0' && ch <= '9') {
+                        ch -= '0';      /* Convert it to a number */
+                        *our_stats[i] = 10 * *our_stats[i] + ch;
+
+                        /* Is the number in range? */
+                        if (*our_stats[i] >= minimum &&
+                            *our_stats[i] <= maximum) {
+                            stat_total -= *our_stats[i];
+                            break;
+                        }
+
+                        /*
+                         * If it's too small, get more - 1x is the only
+                         * allowable case.
+                         */
+                        if (*our_stats[i] < minimum && *our_stats[i] == 1) {
+                            /* Print the player's one */
+                            waddch(hw, '1');
+                            draw(hw);
+                            continue;
+                        }
+                    }
+
+                    /* Error condition */
+                    putchar('\007');
+                    *our_stats[i] = 0;
+                    i--;        /* Rewind */
+                    break;
+                }
+            }
+
+            /* Discard extra points over 18 */
+            if (stat_total > 18) stat_total = 18;
+
+            /* Charisma gets what's left */
+            pstats.s_charisma = stat_total;
+
+            /* Intialize constants */
+            pstats.s_lvl = 1;
+            pstats.s_lvladj = 0;
+            pstats.s_exp = 0L;
+            strcpy(pstats.s_dmg,"2d4");
+            pstats.s_carry = totalenc(&player);
+
+            /* Get the hit points. */
+            pstats.s_hpt = 12 + const_bonus();  /* Base plus bonus */
+
+            /* Add in the component that varies according to class */
+            pstats.s_hpt += char_class[player.t_ctype].hit_pts;
+
+            /* Display the character */
+            wmove(hw, 2, 0);
+            wprintw(hw,"You are creating a %s.",
+                        char_class[player.t_ctype].name);
+            wclrtoeol(hw);
+
+            /* Get rid of max/min line */
+            wmove(hw, 4, 0);
+            wclrtoeol(hw);
+
+            wmove(hw, 6, 0);
+            wprintw(hw, "    Int: %2d", pstats.s_intel);
+            wprintw(hw, "    Str: %2d", pstats.s_str);
+            wprintw(hw, "    Wis: %2d", pstats.s_wisdom); 
+            wprintw(hw, "    Dex: %2d", pstats.s_dext);
+            wprintw(hw, "    Con: %2d", pstats.s_const);
+            wprintw(hw, "    Cha: %2d", pstats.s_charisma);
+            wclrtoeol(hw);
+
+            wmove(hw, 8, 0);
+            wprintw(hw, "    Hp: %2d", pstats.s_hpt);
+            wclrtoeol(hw);
+
+            wmove(hw, 10, 0);
+            wprintw(hw, "    Gold: %ld", purse);
+
+            mvwaddstr(hw, 0, 0, "Is this character okay? ");
+            draw(hw);
+        } while(wgetch(hw) != 'y');
+      }
+    }
+    pstats.s_arm = 10;
+    max_stats = pstats;
+    /* Set up initial movement rate */
+    player.t_action = A_NIL;
+    player.t_movement = 6;
+    player.t_no_move = 0;
+    player.t_using = NULL;
+    wclear(hw);
+}
+
+/*
+ * init_stones:
+ *      Initialize the ring stone setting scheme for this time
+ */
+
+init_stones()
+{
+    register int i;
+    register char *str;
+
+    for (i = 0 ; i < MAXRINGS ; i++)
+    {
+        do
+            str = stones[rnd(NSTONES)].w_string;
+        until (isupper(*str));
+        *str = tolower(*str);
+        r_stones[i] = str;
+        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_things
+ *      Initialize the probabilities for types of things
+ */
+
+init_things()
+{
+    register struct magic_item *mp;
+
+    for (mp = &things[1] ; mp < &things[NUMTHINGS] ; mp++)
+        mp->mi_prob += (mp-1)->mi_prob;
+    badcheck("things", things, NUMTHINGS);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xrogue/io.c	Tue Apr 21 08:55:20 2015 -0400
@@ -0,0 +1,563 @@
+/*
+    io.c - Various input/output functions
+
+    XRogue: Expeditions into the Dungeons of Doom
+    Copyright (C) 1991 Robert Pietkivitch
+    All rights reserved.
+    
+    Based on "Advanced Rogue"
+    Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka and AT&T
+    All rights reserved.
+
+    Based on "Rogue: Exploring the Dungeons of Doom"
+    Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
+    All rights reserved.
+    
+    See the file LICENSE.TXT for full copyright and licensing information.
+*/  
+
+#include <curses.h>
+#include <ctype.h>
+#include <stdarg.h>
+#include "rogue.h"
+
+/*
+ * msg:
+ *      Display a message at the top of the screen.
+ */
+
+static char msgbuf[BUFSIZ];
+static int newpos = 0;
+
+/* VARARGS */
+void
+msg(char *fmt, ...)
+{
+    va_list ap;
+    /*
+     * if the string is "", just clear the line
+     */
+    if (*fmt == '\0')
+    {
+        wclear(msgw);
+        overwrite(cw, msgw);
+        wmove(msgw, 0, 0);
+        clearok(msgw, FALSE);
+        draw(msgw);
+        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
+ */
+
+/* VARARGS */
+void
+addmsg(char *fmt, ...)
+{
+    va_list ap;
+
+    va_start(ap, fmt);
+    doadd(fmt, ap);
+    va_end(ap);
+}
+
+/*
+ * If there is no current message, do nothing.  Otherwise, prompt the
+ * player with the --More-- string.  Then erase the message.
+ */
+
+rmmsg()
+{
+    if (mpos) {
+        wclear(msgw);
+        overwrite(cw, msgw);
+        mvwaddstr(msgw, 0, 0, huh);
+        waddstr(msgw, morestr);
+        clearok(msgw, FALSE);
+        draw(msgw);
+        wait_for(' ');
+        msg("");
+    }
+}
+
+/*
+ * Display a new msg (giving him a chance to see the previous one if it
+ * is up there with the --More--)
+ */
+
+endmsg()
+{
+    /* Needed to track where we are for 5.0 (PC) curses */
+    register int x, y;
+
+    if (mpos) {
+        /*
+         * If this message will fit on the line (plus space for --More--)
+         * then just add it (only during combat).
+         */
+        if (player.t_quiet < 0 && mpos + newpos + strlen(morestr) + 5 < cols) {
+            wmove(msgw, 0, mpos + 5);
+            newpos += mpos + 5;
+            strcat(huh, "  ");
+        }
+        else {
+            wclear(msgw);
+            overwrite(cw, msgw);
+            mvwaddstr(msgw, 0, 0, huh);
+            waddstr(msgw, morestr);
+            clearok(msgw, FALSE);
+            draw(msgw);
+            wait_for(' ');
+            wclear(msgw);
+            overwrite(cw, msgw);
+            wmove(msgw, 0, 0);
+            huh[0] = '\0';
+        }
+    }
+    else {
+        wclear(msgw);
+        overwrite(cw, msgw);
+        wmove(msgw, 0, 0);
+        huh[0] = '\0';
+    }
+    strcat(huh, msgbuf);
+    mvwaddstr(msgw, 0, 0, huh);
+    getyx(msgw, y, x);
+    mpos = newpos;
+    newpos = 0;
+    wmove(msgw, y, x);
+    clearok(msgw, FALSE);
+    draw(msgw);
+}
+
+doadd(char *fmt, va_list ap)
+{
+    vsprintf((char *) &msgbuf[newpos], fmt, ap);
+    newpos = strlen(msgbuf);
+}
+
+/*
+ * step_ok:
+ *      returns true if it is ok for type to step on ch
+ *      flgptr will be NULL if we don't know what the monster is yet!
+ */
+
+step_ok(y, x, can_on_monst, flgptr)
+register int y, x, can_on_monst;
+register struct thing *flgptr;
+{
+    /* can_on_monst = MONSTOK if all we care about are physical obstacles */
+    register struct linked_list *item;
+    register struct thing *tp;
+    unsigned char ch;
+
+    /* What is here?  Don't check monster window if MONSTOK is set */
+    if (can_on_monst == MONSTOK) ch = mvinch(y, x);
+    else ch = winat(y, x);
+
+    if (can_on_monst == FIGHTOK && isalpha(ch) &&
+        (item = find_mons(y, x)) != NULL) {
+        tp = THINGPTR(item);    /* What monster is here? */
+
+        /* We can hit it if we're after it */
+        if (flgptr->t_dest == &tp->t_pos) return TRUE;
+
+        /*
+         * Otherwise, if we're friendly we'll hit it unless it is also
+         * friendly or is our race.
+         */
+        if (off(*flgptr, ISFRIENDLY)    ||
+            on(*tp, ISFRIENDLY)         ||
+            flgptr->t_index == tp->t_index) return FALSE;
+        else return TRUE;
+    }
+    else switch (ch)
+    {
+        case ' ':
+        case VERTWALL:
+        case HORZWALL:
+        case SECRETDOOR:
+            if (flgptr && on(*flgptr, CANINWALL)) return(TRUE);
+            return FALSE;
+        when SCROLL:
+            if (can_on_monst == MONSTOK) {      /* Not a real obstacle */
+                move_free = 0;                  /* check free movement */
+                return(TRUE);
+            }
+            /*
+             * 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 (flgptr && flgptr->t_ctype == C_MONSTER) {
+                move_free = 1;
+                item = find_obj(y, x);
+                if (item != NULL &&
+                    (OBJPTR(item))->o_which==S_SCARE &&
+                    (flgptr == NULL || flgptr->t_stats.s_intel < 17)) {
+                        move_free = 2;
+                        return(FALSE); /* All but smart ones are scared */
+                }
+            }
+            return(TRUE);
+        otherwise:
+            return (!isalpha(ch));
+    }
+    /* return(FALSE); */
+    /*NOTREACHED*/
+}
+
+/*
+ * shoot_ok:
+ *      returns true if it is ok for type to shoot over ch
+ */
+
+shoot_ok(int ch)
+{
+    switch (ch)
+    {
+        case ' ':
+        case VERTWALL:
+        case HORZWALL:
+        case SECRETDOOR:
+        case FOREST:
+            return FALSE;
+        default:
+            return (!isalpha(ch));
+    }
+}
+
+/*
+ * status:
+ *      Display the important stats line.  Keep the cursor where it was.
+ */
+
+status(display)
+bool display;   /* is TRUE, display unconditionally */
+{
+    register struct stats *stat_ptr, *max_ptr;
+    register int oy = 0, ox = 0, temp;
+    register char *pb;
+    char buf[LINELEN];
+    static int hpwidth = 0, s_hungry = -1;
+    static int s_lvl = -1, s_hp = -1, s_str, maxs_str, 
+                s_ac = 0;
+    static short s_intel, s_dext, s_wisdom, s_const, s_charisma;
+    static short maxs_intel, maxs_dext, maxs_wisdom, maxs_const, maxs_charisma;
+    static unsigned long s_exp = 0;
+    static int s_carry, s_pack;
+    bool first_line=FALSE;
+
+    /* Go to English mode */
+    nofont(cw);
+
+    stat_ptr = &pstats;
+    max_ptr  = &max_stats;
+
+    /*
+     * If nothing has changed in the first line, then skip it
+     */
+    if (!display                                &&
+        s_lvl == level                          && 
+        s_intel == stat_ptr->s_intel            &&
+        s_wisdom == stat_ptr->s_wisdom          &&
+        s_dext == dex_compute()                 && 
+        s_const == stat_ptr->s_const            &&
+        s_charisma == stat_ptr->s_charisma      &&
+        s_str == str_compute()                  && 
+        s_hungry == hungry_state                &&
+        maxs_intel == max_ptr->s_intel          && 
+        maxs_wisdom == max_ptr->s_wisdom        &&
+        maxs_dext == max_ptr->s_dext            && 
+        maxs_const == max_ptr->s_const          &&
+        maxs_charisma == max_ptr->s_charisma    &&
+        maxs_str == max_ptr->s_str              ) goto line_two;
+
+    /* Display the first line */
+    first_line = TRUE;
+    getyx(cw, oy, ox);
+    sprintf(buf, "Int:%d(%d)  Str:%d", stat_ptr->s_intel,
+        max_ptr->s_intel, str_compute());
+
+    /* Maximum strength */
+    pb = &buf[strlen(buf)];
+    sprintf(pb, "(%d)", max_ptr->s_str);
+
+    pb = &buf[strlen(buf)];
+    sprintf(pb, "  Wis:%d(%d)  Dxt:%d(%d)  Con:%d(%d)  Cha:%d(%d)",
+        stat_ptr->s_wisdom,max_ptr->s_wisdom,dex_compute(),max_ptr->s_dext,
+        stat_ptr->s_const,max_ptr->s_const,stat_ptr->s_charisma,
+        max_ptr->s_charisma);
+
+    /* Update first line status */
+    s_intel = stat_ptr->s_intel;
+    s_wisdom = stat_ptr->s_wisdom;
+    s_dext = dex_compute();
+    s_const = stat_ptr->s_const;
+    s_charisma = stat_ptr->s_charisma;
+    s_str = str_compute();
+    maxs_intel = max_ptr->s_intel;
+    maxs_wisdom = max_ptr->s_wisdom;
+    maxs_dext = max_ptr->s_dext;
+    maxs_const = max_ptr->s_const;
+    maxs_charisma = max_ptr->s_charisma;
+    maxs_str = max_ptr->s_str;
+
+    /* Print the line */
+    mvwaddstr(cw, lines-2, 0, buf);
+    switch (hungry_state) {
+        case F_SATIATED:
+            waddstr(cw, "  Satiated");
+        when F_OKAY: ;
+        when F_HUNGRY:
+            waddstr(cw, "  Hungry");
+        when F_WEAK:
+            waddstr(cw, "  Weak");
+        when F_FAINT:
+            waddstr(cw, "  Fainting");
+    }
+    wclrtoeol(cw);
+    s_hungry = hungry_state;
+
+    /*
+     * If nothing has changed since the last status, don't
+     * bother.
+     */
+line_two: 
+    if (!display                                        &&
+        s_lvl == level                                  && 
+        s_hp == stat_ptr->s_hpt                         && 
+        s_ac == ac_compute(FALSE) - dext_prot(s_dext)   &&
+        s_pack == stat_ptr->s_pack                      &&
+        s_carry == stat_ptr->s_carry                    &&
+        s_exp == stat_ptr->s_exp                        ) {
+        newfont(cw);
+        return;
+    }
+        
+    if (!first_line) getyx(cw, oy, ox);
+    if (s_hp != max_ptr->s_hpt) {
+        temp = s_hp = max_ptr->s_hpt;
+        for (hpwidth = 0; temp; hpwidth++)
+            temp /= 10;
+    }
+    sprintf(buf, "Lvl:%d  Hp:%*d(%*d)  Ac:%d  Carry:%d(%d)  Exp:%d/%lu  %s",
+        level, hpwidth, stat_ptr->s_hpt, hpwidth, max_ptr->s_hpt,
+        ac_compute(FALSE) - dext_prot(s_dext),stat_ptr->s_pack/10,
+        stat_ptr->s_carry/10, stat_ptr->s_lvl, stat_ptr->s_exp, 
+        cnames[player.t_ctype][min(stat_ptr->s_lvl-1, NUM_CNAMES-1)]);
+
+    /*
+     * Save old status
+     */
+    s_lvl = level;
+    s_hp = stat_ptr->s_hpt;
+    s_ac = ac_compute(FALSE) - dext_prot(s_dext);
+    s_pack = stat_ptr->s_pack;
+    s_carry = stat_ptr->s_carry;
+    s_exp = stat_ptr->s_exp; 
+    mvwaddstr(cw, lines-1, 0, buf);
+    wclrtoeol(cw);
+    newfont(cw);
+    wmove(cw, oy, ox);
+}
+
+/*
+ * wait_for
+ *      Sit around until the guy types the right key
+ */
+
+wait_for(ch)
+register char ch;
+{
+    register char c;
+
+    clearok(msgw, FALSE);
+    if (ch == '\n') {
+        while ((c = wgetch(msgw)) != '\n' && c != '\r') {
+            continue;
+        }
+    }
+    else {
+        while (wgetch(msgw) != ch) {
+            continue;
+        }
+    }
+}
+
+
+/*
+ * over_win:
+ *      Given a current window, a new window, and the max y and x of the
+ *      new window, paint the new window on top of the old window without
+ *      destroying any of the old window.  Current window and new window
+ *      are assumed to have lines lines and cols columns (max y and max x
+ *      pertain only the the useful information to be displayed.
+ *      If redraw is non-zero, we wait for the character "redraw" to be
+ *      typed and then redraw the starting screen.
+ */
+
+over_win(oldwin, newin, maxy, maxx, cursory, cursorx, redraw)
+WINDOW *oldwin, *newin;
+int maxy, maxx, cursory, cursorx;
+char redraw;
+{
+    char blanks[LINELEN+1];
+    register int line, i;
+    WINDOW *ow; /* Overlay window */
+
+    /* Create a blanking line */
+    for (i=0; i<maxx && i<cols && i<LINELEN; i++) blanks[i] = ' ';
+    blanks[i] = '\0';
+
+    /* Create the window we will display */
+    ow = newwin(lines, cols, 0, 0);
+
+    /* Blank out the area we want to use */
+    if (oldwin == cw) {
+        msg("");
+        line = 1;
+    }
+    else line = 0;
+
+    overwrite(oldwin, ow);      /* Get a copy of the old window */
+
+    /* Do the remaining blanking */
+    for (; line < maxy; line++) mvwaddstr(ow, line, 0, blanks);
+
+    overlay(newin, ow); /* Overlay our new window */
+
+    /* Move the cursor to the specified location */
+    wmove(ow, cursory, cursorx);
+
+    clearok(ow, FALSE);         /* Draw inventory without clearing */
+    draw(ow);
+
+    if (redraw) {
+        wait_for(redraw);
+
+        clearok(oldwin, FALSE);         /* Setup to redraw current screen */
+        touchwin(oldwin);               /* clearing first */
+        draw(oldwin);
+    }
+
+    delwin(ow);
+}
+
+
+/*
+ * show_win:
+ *      function used to display a window and wait before returning
+ */
+
+show_win(scr, message)
+register WINDOW *scr;
+char *message;
+{
+    mvwaddstr(scr, 0, 0, message);
+    touchwin(scr);
+    wmove(scr, hero.y, hero.x);
+    draw(scr);
+    wait_for(' ');
+    restscr(cw);
+}
+
+/*
+ * dbotline:
+ *      Displays message on bottom line and waits for a space to return
+ */
+
+dbotline(scr,message)
+WINDOW *scr;
+char *message;
+{
+        mvwaddstr(scr,lines-1,0,message);
+        draw(scr);
+        wait_for(' ');  
+}
+
+/*
+ * restscr:
+ *      Restores the screen to the terminal
+ */
+
+restscr(scr)
+WINDOW *scr;
+{
+        clearok(scr,TRUE);
+        touchwin(scr);
+        draw(scr);
+}
+
+/*
+ * netread:
+ *      Read a byte, short, or long machine independently
+ *      Always returns the value as an unsigned long.
+ */
+
+unsigned long
+netread(error, size, stream)
+int *error;
+int size;
+FILE *stream;
+{
+    unsigned long result = 0L,  /* What we read in */
+                  partial;      /* Partial value */
+    int nextc,  /* The next byte */
+        i;      /* To index through the result a byte at a time */
+
+    /* Be sure we have a right sized chunk */
+    if (size < 1 || size > 4) {
+        *error = 1;
+        return(0L);
+    }
+
+    for (i=0; i<size; i++) {
+        nextc = getc(stream);
+        if (nextc == EOF) {
+            *error = 1;
+            return(0L);
+        }
+        else {
+            partial = (unsigned long) (nextc & 0xff);
+            partial <<= 8*i;
+            result |= partial;
+        }
+    }
+
+    *error = 0;
+    return(result);
+}
+
+/*
+ * netwrite:
+ *      Write out a byte, short, or long machine independently.
+ */
+
+netwrite(value, size, stream)
+unsigned long value;    /* What to write */
+int size;       /* How much to write out */
+FILE *stream;   /* Where to write it */
+{
+    int i;      /* Goes through value one byte at a time */
+    char outc;  /* The next character to be written */
+
+    /* Be sure we have a right sized chunk */
+    if (size < 1 || size > 4) return(0);
+
+    for (i=0; i<size; i++) {
+        outc = (char) ((value >> (8 * i)) & 0xff);
+        putc(outc, stream);
+    }
+    return(size);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xrogue/list.c	Tue Apr 21 08:55:20 2015 -0400
@@ -0,0 +1,246 @@
+/*
+    list.c - Functions for dealing with linked lists of goodies
+   
+    XRogue: Expeditions into the Dungeons of Doom
+    Copyright (C) 1991 Robert Pietkivitch
+    All rights reserved.
+    
+    Based on "Advanced Rogue"
+    Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka and AT&T
+    All rights reserved.
+
+    Based on "Rogue: Exploring the Dungeons of Doom"
+    Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
+    All rights reserved.
+    
+    See the file LICENSE.TXT for full copyright and licensing information.
+*/
+
+#include <stdlib.h>
+#include <curses.h>
+#include "rogue.h"
+
+/*
+ * detach:
+ *      Takes an item out of whatever linked list it might be in
+ */
+
+_detach(list, item)
+register struct linked_list **list, *item;
+{
+    if (*list == item)
+        *list = next(item);
+    if (prev(item) != NULL) item->l_prev->l_next = next(item);
+    if (next(item) != NULL) item->l_next->l_prev = prev(item);
+    item->l_next = NULL;
+    item->l_prev = NULL;
+}
+
+/*
+ * _attach:
+ *      add an item to the head of a list
+ */
+
+_attach(list, item)
+register struct linked_list **list, *item;
+{
+    if (*list != NULL)
+    {
+        item->l_next = *list;
+        (*list)->l_prev = item;
+        item->l_prev = NULL;
+    }
+    else
+    {
+        item->l_next = NULL;
+        item->l_prev = NULL;
+    }
+
+    *list = item;
+}
+
+/*
+ * o_free_list:
+ *      Throw the whole object list away
+ */
+
+_o_free_list(ptr)
+register struct linked_list **ptr;
+{
+    register struct linked_list *item;
+
+    while (*ptr != NULL)
+    {
+        item = *ptr;
+        *ptr = next(item);
+        o_discard(item);
+    }
+}
+
+/*
+ * o_discard:
+ *      free up an item and its object(and maybe contents)
+ */
+
+o_discard(item)
+register struct linked_list *item;
+{
+    register struct object *obj;
+
+    obj = OBJPTR(item);
+    if (obj->contents != NULL)
+        o_free_list(obj->contents);
+    total -= 2;
+    FREE(obj);
+    FREE(item);
+}
+
+/*
+   r_free_fire_list
+       Throw the whole list of fire monsters away. But don't
+       discard the item (monster) itself as that belong to mlist.
+*/
+
+_r_free_fire_list(ptr)
+register struct linked_list **ptr;
+{
+    register struct linked_list *item;
+
+        while (*ptr != NULL)
+        {
+            item = *ptr;
+            *ptr = next(item);
+            free(item);
+        }
+}
+/*
+ * r_free_list:
+ *      Throw the whole list of room exits away
+ */
+
+_r_free_list(ptr)
+register struct linked_list **ptr;
+{
+    register struct linked_list *item;
+
+    while (*ptr != NULL)
+    {
+        item = *ptr;
+        *ptr = next(item);
+        r_discard(item);
+    }
+}
+
+/*
+ * r_discard:
+ *      free up an item and its room
+ */
+
+r_discard(item)
+register struct linked_list *item;
+{
+    total -= 2;
+    FREE(DOORPTR(item));
+    FREE(item);
+}
+
+/*
+ * t_free_list:
+ *      Throw the whole thing list away
+ */
+
+_t_free_list(ptr)
+register struct linked_list **ptr;
+{
+    register struct linked_list *item;
+
+    while (*ptr != NULL)
+    {
+        item = *ptr;
+        *ptr = next(item);
+        t_discard(item);
+    }
+}
+
+/*
+ * t_discard:
+ *      free up an item and its thing
+ */
+
+t_discard(item)
+register struct linked_list *item;
+{
+    register struct thing *tp;
+
+    total -= 2;
+    tp = THINGPTR(item);
+    if (tp->t_name != NULL) FREE(tp->t_name);
+    if (tp->t_pack != NULL)
+        o_free_list(tp->t_pack);
+    FREE(tp);
+    FREE(item);
+}
+
+/*
+ * destroy_item:
+ *      get rid of an item structure -- don't worry about contents
+ */
+
+destroy_item(item)
+register struct linked_list *item;
+{
+    total--;
+    FREE(item);
+}
+
+/*
+ * new_item
+ *      get a new item with a specified size
+ */
+
+struct linked_list *
+new_item(size)
+int size;
+{
+    register struct linked_list *item;
+
+    if ((item = (struct linked_list *) new(sizeof *item)) == NULL)
+        msg("Ran out of memory for header after %d items", total);
+    if ((item->l_data = new(size)) == NULL)
+        msg("Ran out of memory for data after %d items", total);
+    item->l_next = item->l_prev = NULL;
+    memset(item->l_data,0,size);
+    return item;
+}
+
+/*
+ * creat_item:
+ *      Create just an item structure -- don't make any contents
+ */
+
+struct linked_list *
+creat_item()
+{
+    register struct linked_list *item;
+
+    if ((item = (struct linked_list *) new(sizeof *item)) == NULL)
+        msg("Ran out of memory for header after %d items", total);
+    item->l_next = item->l_prev = NULL;
+    return item;
+}
+
+char *
+new(size)
+int size;
+{
+    register char *space = ALLOC(size);
+
+    if (space == NULL) {
+        sprintf(prbuf,"Rogue ran out of memory (used = %d, wanted = %d).",
+                md_memused(), size);
+        fatal(prbuf);
+    }
+    total++;
+    return space;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xrogue/mach_dep.h	Tue Apr 21 08:55:20 2015 -0400
@@ -0,0 +1,58 @@
+/*
+    mach_dep.h  -  machine dependents
+
+    XRogue: Expeditions into the Dungeons of Doom
+    Copyright (C) 1991 Robert Pietkivitch
+    All rights reserved.
+    
+    Based on "Advanced Rogue"
+    Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka and AT&T
+    All rights reserved.
+
+    Based on "Rogue: Exploring the Dungeons of Doom"
+    Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
+    All rights reserved.
+    
+    See the file LICENSE.TXT for full copyright and licensing information.
+*/
+
+/*
+ * define/undefine that the wizard commands exist
+ */
+
+#if defined(_WIN32)
+#define fstat _fstat
+#define stat _stat
+#define open _open
+#define popen _popen
+#define pclose _pclose
+#if !defined(__MINGW32__)
+#define PATH_MAX _MAX_PATH
+#endif
+#endif
+
+#define NOOP(x) (x += 0)
+
+extern char *md_getusername();
+extern char *md_gethomedir();
+extern char *md_getroguedir();
+extern void md_flushinp();
+extern char *md_getshell();
+extern char *md_gethostname();
+extern void md_dobinaryio();
+extern char *md_getpass();
+extern void md_init();
+extern char *xcrypt();
+
+/*
+ * define if you want to limit scores to one per class per userid
+ */
+
+/* #define LIMITSCORE 1*/
+#undef LIMITSCORE
+
+/* 
+ * fudge factor allowed in time for saved game
+ */
+
+#define FUDGE_TIME      200
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xrogue/main.c	Tue Apr 21 08:55:20 2015 -0400
@@ -0,0 +1,438 @@
+/*
+    main.c  -  setup code
+    
+    XRogue: Expeditions into the Dungeons of Doom
+    Copyright (C) 1991 Robert Pietkivitch
+    All rights reserved.
+    
+    Based on "Advanced Rogue"
+    Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka and AT&T
+    All rights reserved.
+
+    Based on "Rogue: Exploring the Dungeons of Doom"
+    Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
+    All rights reserved.
+    
+    See the file LICENSE.TXT for full copyright and licensing information.
+*/
+ 
+#include <curses.h>
+#include <signal.h>
+#include <time.h>
+
+#include "mach_dep.h"
+#include "network.h"
+#include "rogue.h"
+
+main(argc, argv, envp)
+char **argv;
+char **envp;
+{
+    register char *env;
+    time_t now;
+
+    md_init();
+
+    /*
+     * get home and options from environment
+     */
+
+    strncpy(home, md_gethomedir(), LINELEN);
+
+    /* Get default save file */
+    strcpy(file_name, home);
+    strcat(file_name, "xrogue.sav");
+
+    /* Get default score file */
+    strcpy(score_file, md_getroguedir());
+
+    if (*score_file)
+        strcat(score_file,"/");
+
+    strcat(score_file, "xrogue.scr");
+
+    if ((env = getenv("ROGUEOPTS")) != NULL)
+        parse_opts(env);
+    
+    if (whoami[0] == '\0')
+        strucpy(whoami, md_getusername(), strlen(md_getusername()));
+
+    /*
+     * check for print-score option
+     */
+    if (argc == 2 && strcmp(argv[1], "-s") == 0)
+    {
+        waswizard = TRUE;
+        score((long)0, SCOREIT, (short)0);
+        exit_game(0);
+    }
+
+    /*
+     * Check for a network update
+     */
+    if (argc == 2 && strcmp(argv[1], "-u") == 0) {
+        int errcheck, errors = 0;
+        unsigned long amount;
+        short monster;
+
+        /* Read in the amount and monster values to pass to score */
+        amount = netread(&errcheck, sizeof(unsigned long), stdin);
+        if (errcheck) errors++;
+
+        monster = (short) netread(&errcheck, sizeof(short), stdin);
+        if (errcheck) errors++;
+
+        /* Now do the update if there were no errors */
+        if (errors) exit_game(0);
+        else {
+            score((long)amount, UPDATE, (short)monster);
+            exit_game(0);
+        }
+    }
+
+    /*
+     * Check to see if he is a wizard
+     */
+    if (argc >= 2 && argv[1][0] == '\0')
+        if (strcmp(PASSWD, xcrypt(md_getpass("Wizard's password: "), "mT")) == 0)
+        {
+            wizard = TRUE;
+            argv++;
+            argc--;
+        }
+
+    if (betaover())
+    {
+        printf("Sorry, %s, but the test period of this prerelease version\n",whoami);
+        printf("of xrogue is over. Please acquire a new version. Sorry.\n");
+        exit_game(0);
+    }
+
+    if (!wizard && !author() && !playtime()) {
+        printf("Sorry, %s, but you can't play during working hours.\n", whoami);
+        printf("Try again later.\n");
+        exit_game(0);
+    }
+    if (!wizard && !author() && too_much()) {
+        printf("Sorry, %s, but the system is too loaded now.\n", whoami);
+        printf("Try again later.\n");
+        exit_game(0);
+    }
+
+    if (argc == 2)
+        if (!restore(argv[1], envp)) /* Note: restore will never return */
+            exit_game(0);
+
+    if (wizard && getenv("SEED") != NULL) {
+        seed = atoi(getenv("SEED")); 
+    }
+    else {
+        seed = (int) time(&now) + getpid();
+    }
+    if (wizard)
+        printf("Hello %s, welcome to dungeon #%d", whoami, seed);
+    else
+        printf("Hello %s, just a moment while I dig the dungeon...", whoami);
+    fflush(stdout);
+   
+    md_srand(seed);
+
+    init_things();                      /* Set up probabilities of things */
+    init_colors();                      /* Set up colors of potions */
+    init_stones();                      /* Set up stone settings of rings */
+    init_materials();                   /* Set up materials of wands */
+    init_names();                       /* Set up names of scrolls */
+    init_misc();                        /* Set up miscellaneous magic */
+    init_foods();                       /* set up the food table */
+
+    initscr();                          /* Start up cursor package */
+
+    typeahead(-1);          /* turn off 3.2/4.0 curses feature */
+
+    if (COLS < MINCOLS)
+    {
+        printf("\n\nSorry, %s, but your terminal window has too few columns.\n", whoami);
+        printf("Your terminal has %d columns, needs 70.\n",COLS);
+        byebye(0);
+    }
+    if (LINES < MINLINES)
+    {
+        printf("\n\nSorry, %s, but your terminal window has too few lines.\n", whoami);
+        printf("Your terminal has %d lines, needs 22.\n",LINES);
+        byebye(0);
+    }
+    
+    cols  = COLS;
+    lines = LINES;
+
+    if ( cols % 2 != 0)  cols -=1;          /* must be even for maze code */
+    if (lines % 2 != 0) lines -=1;          /* must be even for maze code */
+
+    /*
+     * Now that we have cols and lines, we can update our window
+     * structure for non-hardware windows.
+     */
+    setup();
+    /*
+     * Set up windows
+     */
+    cw = newwin(lines, cols, 0, 0);
+    mw = newwin(lines, cols, 0, 0);
+    hw = newwin(lines, cols, 0, 0);
+    msgw = newwin(4, cols, 0, 0);
+    if (cw == NULL || hw == NULL || mw == NULL || msgw == NULL) {
+        exit_game(EXIT_CLS | EXIT_ENDWIN);
+    }
+
+    keypad(cw, TRUE);
+    keypad(hw, TRUE);
+
+    init_player();                      /* Roll up the rogue */
+    waswizard = wizard;
+
+    draw(cw);
+    /* A super wizard doesn't have to get equipped */
+    /* Check if "" option is TRUE and get environment flag */
+    if (wizard && strcmp(getenv("SUPER"),"YES") == 0 ||
+    def_attr == TRUE) {
+        level = 1;
+        new_level(NORMLEV);
+    }
+    else 
+        new_level(STARTLEV);            /* Draw current level */
+
+    /*
+     * Start up daemons and fuses
+     */
+    daemon(doctor, &player, AFTER);
+    fuse(swander, (VOID *)NULL, WANDERTIME, AFTER);
+    /* Give characters their innate abilities */
+    if (player.t_ctype == C_MAGICIAN || player.t_ctype == C_RANGER)
+            fuse(spell_recovery, (VOID *)NULL, SPELLTIME, AFTER);
+    if (player.t_ctype == C_DRUID    || player.t_ctype == C_MONK)
+            fuse(chant_recovery, (VOID *)NULL, SPELLTIME, AFTER);
+    if (player.t_ctype == C_CLERIC   || player.t_ctype == C_PALADIN)
+            fuse(prayer_recovery, (VOID *)NULL, SPELLTIME, AFTER);
+    daemon(stomach, (VOID *)NULL, AFTER);
+    if (player.t_ctype == C_THIEF    ||
+        player.t_ctype == C_ASSASSIN ||
+        player.t_ctype == C_MONK)
+            daemon(trap_look, (VOID *)NULL, AFTER);
+
+    /* Does this character have any special knowledge? */
+    switch (player.t_ctype) {
+        case C_ASSASSIN:
+            /* Assassins automatically recognize poison */
+            p_know[P_POISON] = TRUE;
+        when C_FIGHTER:
+            /* Fighters automatically recognize skill */
+            p_know[P_SKILL] = TRUE;
+    }
+
+    /* Choose an initial quest item */
+    if (!wizard) {
+    if (def_attr == FALSE)
+        quest_item = rnd(MAXRELIC);
+    }
+    mpos = 0;
+    draw(cw);
+    msg("You have been quested to retrieve the %s....",
+         rel_magic[quest_item].mi_name);
+    mpos = 0;
+    playit();
+}
+
+/*
+ * endit:
+ *      Exit the program abnormally.
+ */
+
+/*UNUSED*/
+void
+endit(sig)
+int sig;
+{
+	NOOP(sig);
+    fatal("Ok, if you want to exit that badly, I'll have to allow it\n");
+}
+
+/*
+ * fatal:
+ *      Exit the program, printing a message.
+ */
+
+fatal(s)
+char *s;
+{
+    clear();
+    move(lines-2, 0);
+    printw("%s", s);
+    draw(stdscr);
+    printf("\n");       /* So the curser doesn't stop at the end of the line */
+    exit_game(EXIT_ENDWIN);
+}
+
+/*
+ * rnd:
+ *      Pick a very random number.
+ */
+
+rnd(range)
+register int range;
+{
+    return( md_rand(range) );
+}
+
+/*
+ * roll:
+ *      roll a number of dice
+ */
+
+roll(number, sides)
+register int number, sides;
+{
+    register int dtotal = 0;
+
+    while(number--)
+        dtotal += rnd(sides)+1;
+    return dtotal;
+}
+
+setup()
+{
+	md_setup();
+}
+
+/*
+ * playit:
+ *      The main loop of the program.  Loop until the game is over,
+ * refreshing things and looking at the proper times.
+ */
+
+playit()
+{
+    register char *opts;
+
+    /*
+     * parse environment declaration of options
+     */
+    if ((opts = getenv("ROGUEOPTS")) != NULL)
+        parse_opts(opts);
+
+    player.t_oldpos = hero;
+    oldrp = roomin(&hero);
+    after = TRUE;
+    command();                  /* Command execution */
+    endit(-1);
+}
+
+/*
+ * see if the system is being used too much for this game
+ */
+
+too_much()
+{
+    /* we no longer do load checking or user counts */
+    return(FALSE);
+}
+
+/*
+ * author:
+ *      See if a user is an author of the program
+ */
+
+author()
+{
+        switch (md_getuid()) {
+                case 0: /* always OK for root to play */
+                        return TRUE;
+                default:
+                        return FALSE;
+        }
+}
+
+/*
+ * playtime:
+ *      Returns TRUE when it is a good time to play rogue
+ */
+
+playtime()
+{
+        /* we no longer do playtime checking */
+
+        return TRUE;
+}
+
+/*
+ * betaover:
+ *      Returns TRUE if the test period of this version of the game is over
+ */
+
+betaover()
+{
+     return(FALSE);
+}
+
+
+exit_game(flag)
+int flag;
+{
+    int i;
+
+    if (flag & EXIT_CLS)  /* Clear Screen    */
+    {
+        wclear(cw);
+        draw(cw);
+    }
+
+    if (flag & EXIT_ENDWIN)  /* Shutdown Curses */
+    {
+        keypad(cw,FALSE);
+        keypad(hw,FALSE);
+        delwin(cw);
+        delwin(mw);
+        delwin(hw);
+        delwin(msgw);
+        if (!isendwin())
+            endwin();
+    }
+    o_free_list(player.t_pack);
+    t_free_list(mlist);
+    t_free_list(rlist);
+    t_free_list(tlist);
+    o_free_list(lvl_obj);               /* Free up previous objects (if any) */
+    for (i = 0; i < MAXROOMS; i++)
+    {
+        r_free_list(rooms[i].r_exit);        /* Free up the exit lists */ 
+        _r_free_fire_list(&rooms[i].r_fires);
+    }
+
+    for(i=0; i<MAXSCROLLS; i++)
+    {
+        if (s_names[i] != NULL)
+            free( s_names[i] );
+        if (s_guess[i] != NULL)
+            free( s_guess[i] );
+    }
+
+    for(i=0; i<MAXPOTIONS; i++)
+    {
+        if (p_guess[i] != NULL)
+            free( p_guess[i] );
+    }
+
+    for(i=0; i<MAXRINGS; i++)
+    {
+        if (r_guess[i] != NULL)
+            free( r_guess[i] );
+    }
+
+    for(i=0; i<MAXSTICKS; i++)
+    {
+        if (ws_guess[i] != NULL)
+            free( ws_guess[i] );
+    }
+
+    exit(0);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xrogue/maze.c	Tue Apr 21 08:55:20 2015 -0400
@@ -0,0 +1,385 @@
+/*
+    maze.c  -  functions for dealing with mazes
+    
+    XRogue: Expeditions into the Dungeons of Doom
+    Copyright (C) 1991 Robert Pietkivitch
+    All rights reserved.
+    
+    Based on "Advanced Rogue"
+    Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka and AT&T
+    All rights reserved.
+
+    See the file LICENSE.TXT for full copyright and licensing information.
+*/
+
+#include <stdlib.h>
+#include <curses.h>
+#include "rogue.h"
+
+struct cell {
+        char y_pos;
+        char x_pos;
+};
+struct b_cellscells {
+        char num_pos;           /* number of frontier cells next to you */
+        struct cell conn[4];    /* the y,x position of above cell */
+} b_cells;
+
+static char     *maze_frontier, *maze_bits;
+static int      maze_lines, maze_cols;
+static char     *moffset(), *foffset();
+static int      rmwall(),findcells(),crankout(),draw_maze();
+
+/*
+ * crankout:
+ *      Does actual drawing of maze to window
+ */
+
+static
+crankout()
+{
+    reg int x, y;
+
+    for (y = 0; y < lines - 3; y++) {
+        move(y + 1, 0);
+        for (x = 0; x < cols - 1; x++) {
+            if (*moffset(y, x)) {           /* here is a wall */
+                if(y==0 || y==lines-4) /* top or bottom line */
+                    addch(HORZWALL);
+                else if(x==0 || x==cols-2) /* left | right side */
+                    addch(VERTWALL);
+                else if (y % 2 == 0 && x % 2 == 0) {
+                    if(*moffset(y, x-1) || *moffset(y, x+1))
+                        addch(HORZWALL);
+                    else
+                        addch(VERTWALL);
+                }
+                else if (y % 2 == 0)
+                    addch(HORZWALL);
+                else
+                    addch(VERTWALL);
+            }
+            else
+                addch(FLOOR);
+        }
+    }
+}
+
+/*
+ * domaze:
+ *      Draw the maze on this level.
+ */
+
+do_maze()
+{
+        reg int least;
+        reg struct room *rp;
+        reg struct linked_list *item;
+        reg struct object *obj;
+        int cnt;
+        bool treas;
+        coord tp;
+
+        for (rp = rooms; rp < &rooms[MAXROOMS]; rp++) {
+                rp->r_flags = ISGONE;           /* kill all rooms */
+                rp->r_fires = NULL;             /* no fires */
+        }
+        rp = &rooms[0];                         /* point to only room */
+        rp->r_flags = ISDARK;                   /* mazes always dark */
+        rp->r_pos.x = 0;                        /* room fills whole screen */
+        rp->r_pos.y = 1;
+        rp->r_max.x = cols - 1;
+        rp->r_max.y = lines - 3;
+        draw_maze();                            /* put maze into window */
+        /*
+         * add some gold to make it worth looking for 
+         */
+        item = spec_item(GOLD, NULL, NULL, NULL);
+        obj = OBJPTR(item);
+        obj->o_count *= (rnd(50) + 50);         /* add in one large hunk */
+        attach(lvl_obj, item);
+        cnt = 0;
+        do {
+            rnd_pos(rp, &tp);
+        } until (mvinch(tp.y, tp.x) == FLOOR || cnt++ > 2500);
+        mvaddch(tp.y, tp.x, GOLD);
+        obj->o_pos = tp;
+        /*
+         * add in some food to make sure he has enough
+         */
+        item = spec_item(FOOD, NULL, NULL, NULL);
+        obj = OBJPTR(item);
+        attach(lvl_obj, item);
+        do {
+            rnd_pos(rp, &tp);
+        } until (mvinch(tp.y, tp.x) == FLOOR || cnt++ > 2500);
+        mvaddch(tp.y, tp.x, FOOD);
+        obj->o_pos = tp;
+
+        /* it doesn't mater if it's a treasure maze or a normal maze,
+         * more than enough monsters will be genned. 
+         */
+        least = rnd(11)+5;
+        if (least < 6) {
+        least = 7;
+        treas = FALSE;
+    }
+    else treas = TRUE;
+        genmonsters(least, treas);
+
+        /* sometimes they're real angry */
+        if (rnd(100) < 65) {
+            /* protect the good charactors */
+            if (player.t_ctype == C_PALADIN ||
+                player.t_ctype == C_RANGER  || player.t_ctype == C_MONK) {
+                aggravate(TRUE, FALSE);
+            }
+            else {
+                aggravate(TRUE, TRUE);
+            }
+        }
+}
+
+/*
+ * draw_maze:
+ *      Generate and draw the maze on the screen
+ */
+
+static
+draw_maze()
+{
+        reg int i, j, more;
+        reg char *ptr;
+
+        maze_lines = (lines - 3) / 2;
+        maze_cols = (cols - 1) / 2;
+        maze_bits = ALLOC((lines - 3) * (cols - 1));
+        maze_frontier = ALLOC(maze_lines * maze_cols);
+        ptr = maze_frontier;
+        while (ptr < (maze_frontier + (maze_lines * maze_cols)))
+                *ptr++ = TRUE;
+        for (i = 0; i < lines - 3; i++) {
+                for (j = 0; j < cols - 1; j++) {
+                        if (i % 2 == 1 && j % 2 == 1)
+                                *moffset(i, j) = FALSE;         /* floor */
+                        else
+                                *moffset(i, j) = TRUE;          /* wall */
+                }
+        }
+        for (i = 0; i < maze_lines; i++) {
+                for (j = 0; j < maze_cols; j++) {
+                        do
+                                more = findcells(i,j);
+                        while(more != 0);
+                }
+        }
+        crankout();
+        FREE(maze_frontier);
+        FREE(maze_bits);
+}
+
+/*
+ * findcells:
+ *      Figure out cells to open up 
+ */
+
+static findcells(y,x)
+reg int x, y;
+{
+        reg int rtpos, i;
+
+        *foffset(y, x) = FALSE;
+        b_cells.num_pos = 0;
+        if (y < maze_lines - 1) {                               /* look below */
+                if (*foffset(y + 1, x)) {
+                        b_cells.conn[b_cells.num_pos].y_pos = y + 1;
+                        b_cells.conn[b_cells.num_pos].x_pos = x;
+                        b_cells.num_pos += 1;
+                }
+        }
+        if (y > 0) {                                    /* look above */
+                if (*foffset(y - 1, x)) {
+                        b_cells.conn[b_cells.num_pos].y_pos = y - 1;
+                        b_cells.conn[b_cells.num_pos].x_pos = x;
+                        b_cells.num_pos += 1;
+
+                }
+        }
+        if (x < maze_cols - 1) {                                /* look right */
+                if (*foffset(y, x + 1)) {
+                        b_cells.conn[b_cells.num_pos].y_pos = y;
+                        b_cells.conn[b_cells.num_pos].x_pos = x + 1;
+                        b_cells.num_pos += 1;
+                }
+        }
+        if (x > 0) {                                    /* look left */
+                if (*foffset(y, x - 1)) {
+                        b_cells.conn[b_cells.num_pos].y_pos = y;
+                        b_cells.conn[b_cells.num_pos].x_pos = x - 1;
+                        b_cells.num_pos += 1;
+
+                }
+        }
+        if (b_cells.num_pos == 0)               /* no neighbors available */
+                return 0;
+        else {
+                i = rnd(b_cells.num_pos);
+                rtpos = b_cells.num_pos - 1;
+                rmwall(b_cells.conn[i].y_pos, b_cells.conn[i].x_pos, y, x);
+                return rtpos;
+        }
+}
+
+/*
+ * foffset:
+ *      Calculate memory address for frontier
+ */
+
+static char *
+foffset(y, x)
+int y, x;
+{
+
+        return (maze_frontier + (y * maze_cols) + x);
+}
+
+
+/*
+ * Maze_view:
+ *      Returns true if the player can see the specified location within
+ *      the confines of a maze (within one column or row)
+ */
+
+bool
+maze_view(y, x)
+int y, x;
+{
+    register int start, goal, delta, ycheck = 0, xcheck = 0, absy, absx, see_radius;
+    register bool row;
+
+    /* Get the absolute value of y and x differences */
+    absy = hero.y - y;
+    absx = hero.x - x;
+    if (absy < 0) absy = -absy;
+    if (absx < 0) absx = -absx;
+
+    /* If we are standing in a wall, we can see a bit more */
+    switch (winat(hero.y, hero.x)) {
+        case VERTWALL:
+        case HORZWALL:
+        case WALL:
+        case SECRETDOOR:
+        case DOOR:
+            see_radius = 2;
+        otherwise:
+            see_radius = 1;
+    }
+
+    /* Must be within one or two rows or columns */
+    if (absy > see_radius && absx > see_radius) return(FALSE);
+
+    if (absx > see_radius) {            /* Go along row */
+        start = hero.x;
+        goal = x;
+        ycheck = hero.y;
+        row = TRUE;
+    }
+    else {                      /* Go along column */
+        start = hero.y;
+        goal = y;
+        xcheck = hero.x;
+        row = FALSE;
+    }
+
+    if (start <= goal) delta = 1;
+    else delta = -1;
+
+    /* Start one past where we are standing */
+    if (start != goal) start += delta;
+
+    /* If we are in a wall, we want to look in the area outside the wall */
+    if (see_radius > 1) {
+        if (row) {
+            /* See if above us it okay first */
+            switch (winat(ycheck, start)) {
+                case VERTWALL:
+                case HORZWALL:
+                case WALL:
+                case DOOR:
+                case SECRETDOOR:
+                    /* No good, try one up */
+                    if (y > hero.y) ycheck++;
+                    else ycheck--;
+                otherwise:
+                    see_radius = 1;     /* Just look straight over the row */
+            }
+        }
+        else {
+            /* See if above us it okay first */
+            switch (winat(start, xcheck)) {
+                case VERTWALL:
+                case HORZWALL:
+                case WALL:
+                case DOOR:
+                case SECRETDOOR:
+                    /* No good, try one over */
+                    if (x > hero.x) xcheck++;
+                    else xcheck--;
+                otherwise:
+                    see_radius = 1;     /* Just look straight up the column */
+            }
+        }
+    }
+
+    /* Check boundary again */
+    if (absy > see_radius && absx > see_radius) return(FALSE);
+
+    while (start != goal) {
+        if (row) xcheck = start;
+        else     ycheck = start;
+
+        if (xcheck < 0 || ycheck < 0)
+            return FALSE;
+        switch (winat(ycheck, xcheck)) {
+            case VERTWALL:
+            case HORZWALL:
+            case WALL:
+            case DOOR:
+            case SECRETDOOR:
+                return(FALSE);
+        }
+        start += delta;
+    }
+    return(TRUE);
+}
+
+
+/*
+ * moffset:
+ *      Calculate memory address for bits
+ */
+
+static char *
+moffset(y, x)
+int y, x;
+{
+    return (maze_bits + (y * (cols - 1)) + x);
+}
+
+/*
+ * rmwall:
+ *      Removes appropriate walls from the maze
+ */
+static
+rmwall(newy, newx, oldy, oldx)
+int newy, newx, oldy, oldx;
+{
+        reg int xdif,ydif;
+        
+        xdif = newx - oldx;
+        ydif = newy - oldy;
+
+        *moffset((oldy * 2) + ydif + 1, (oldx * 2) + xdif + 1) = FALSE;
+        findcells(newy, newx);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xrogue/misc.c	Tue Apr 21 08:55:20 2015 -0400
@@ -0,0 +1,1296 @@
+/*
+    misc.c - routines dealing specifically with miscellaneous magic
+    
+    XRogue: Expeditions into the Dungeons of Doom
+    Copyright (C) 1991 Robert Pietkivitch
+    All rights reserved.
+    
+    Based on "Advanced Rogue"
+    Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka and AT&T
+    All rights reserved.
+
+    See the file LICENSE.TXT for full copyright and licensing information.
+*/
+
+#include <curses.h>
+#include <ctype.h>
+#include "rogue.h"
+
+/*
+ * changeclass:
+ *      Change the player's class to the specified one.
+ */
+
+changeclass(newclass)
+long *newclass;
+{
+    if (*newclass == player.t_ctype) {
+        msg("You feel more skillful.");
+        raise_level();
+    }
+    else {
+        /*
+         * reset his class and then use check_level to reset hit
+         * points and the right level for his exp pts
+         * drop exp pts by 10%
+         */
+        long save;
+
+        msg("You are transformed into a %s! ", char_class[*newclass].name);
+
+        /*
+         * if he becomes a thief or an assassin give him studded leather armor
+         */
+        if ((*newclass == C_THIEF || *newclass == C_ASSASSIN) &&
+            cur_armor != NULL && cur_armor->o_which != STUDDED_LEATHER)
+                cur_armor->o_which = STUDDED_LEATHER;
+        /*
+         * if he becomes a monk he can't wear any armor
+     * so give him a cloak of protection
+         */
+        if (*newclass == C_MONK && cur_armor != NULL) {
+                cur_armor->o_ac = armors[cur_armor->o_which].a_class - 
+                                  cur_armor->o_ac;
+                cur_armor->o_type = MM;
+                cur_armor->o_which = MM_PROTECT;
+                cur_armor->o_flags &= ~(ISPROT | ISKNOW);
+                cur_misc[WEAR_CLOAK] = cur_armor;
+                cur_armor = NULL;
+        }
+    /*
+     * otherwise give him plate armor
+     */
+        if ((*newclass != C_THIEF ||
+         *newclass != C_ASSASSIN || *newclass != C_MONK) &&
+         cur_armor != NULL && cur_armor->o_which != PLATE_ARMOR) 
+                cur_armor->o_which = PLATE_ARMOR;
+
+        /*
+         * if he used to be a spell caster of some sort, kill the fuse
+         */
+        if (player.t_ctype == C_MAGICIAN || player.t_ctype == C_RANGER)
+                extinguish(spell_recovery);
+        if (player.t_ctype == C_DRUID || player.t_ctype == C_MONK)
+                extinguish(chant_recovery);
+        if ((player.t_ctype == C_CLERIC || player.t_ctype == C_PALADIN) &&
+             !cur_relic[HEIL_ANKH])
+                extinguish(prayer_recovery);
+
+        /*
+         * if he becomes a spell caster of some kind, give him a fuse
+         */
+        if (*newclass == C_MAGICIAN || *newclass == C_RANGER)
+                fuse(spell_recovery, (VOID *)NULL, SPELLTIME, AFTER);
+        if (*newclass == C_DRUID || *newclass == C_MONK)
+                fuse(chant_recovery, (VOID *)NULL, SPELLTIME, AFTER);
+        if ((*newclass==C_CLERIC || *newclass==C_PALADIN) && !cur_misc[HEIL_ANKH])
+                fuse(prayer_recovery, (VOID *)NULL, SPELLTIME, AFTER);
+        /*
+         * if he's changing from a fighter, ranger, or paladin then we
+     * may have to change his sword since only these types can wield
+     * the two-handed sword.
+         */
+        if ((player.t_ctype == C_FIGHTER ||
+        player.t_ctype == C_RANGER   ||
+            player.t_ctype == C_PALADIN) &&
+        cur_weapon != NULL && cur_weapon->o_type == WEAPON &&
+            (cur_weapon->o_which == BASWORD  ||
+        cur_weapon->o_which == TWOSWORD) &&
+            !(*newclass == C_FIGHTER || *newclass == C_RANGER ||
+            *newclass == C_PALADIN)  &&
+        cur_weapon->o_which == TWOSWORD)
+                cur_weapon->o_which = SWORD;
+
+        /*
+         * if he's changing from a thief, assassin, fighter, or monk
+     * then we may have to change his sword again since only these
+     * types can wield the bastard sword.
+         */
+        if ((player.t_ctype == C_THIEF  || player.t_ctype == C_ASSASSIN ||
+            player.t_ctype == C_FIGHTER || player.t_ctype == C_MONK)    &&
+        cur_weapon != NULL && cur_weapon->o_type == WEAPON &&
+            (cur_weapon->o_which == BASWORD  ||
+            cur_weapon->o_which == TWOSWORD) &&
+            !(*newclass == C_THIEF || *newclass == C_ASSASSIN ||
+            *newclass == C_MONK)   &&
+        cur_weapon->o_which == BASWORD)
+                cur_weapon->o_which = SWORD;
+
+        /*
+         * if he was a thief, assassin, or monk then take out
+     * the trap_look() daemon
+         */
+        if (player.t_ctype == C_THIEF || player.t_ctype == C_MONK ||
+            player.t_ctype == C_ASSASSIN)
+                kill_daemon(trap_look);
+
+        /*
+         * if he becomes a thief, assassin, or monk then add 
+     * the trap_look() daemon
+         */
+        if (*newclass == C_THIEF || *newclass == C_ASSASSIN ||
+        *newclass == C_MONK)
+                daemon(trap_look, (VOID *)NULL, AFTER);
+
+    /* adjust stats */
+        char_type = player.t_ctype = *newclass;
+        save = pstats.s_hpt;
+        max_stats.s_hpt = pstats.s_hpt = 0;
+        max_stats.s_lvl = pstats.s_lvl = 0; 
+        max_stats.s_lvladj = pstats.s_lvladj = 0; 
+        max_stats.s_exp = pstats.s_exp + rnd(4);
+        check_level();
+        if (pstats.s_hpt > save) /* don't add to current hits */
+            pstats.s_hpt = save;
+    }
+    dsrpt_player(); /* this should disrupt whatever we were doing */
+}
+
+/*
+ * Use the relic that our monster is wielding.
+ */
+
+m_use_relic(monster)
+register struct thing *monster;
+{
+    register struct object *obj;
+
+    /* Make sure we really have it */
+    if (monster->t_using) obj = OBJPTR(monster->t_using);
+    else {
+        debug("Relic not set!");
+        monster->t_action = A_NIL;
+        return;
+    }
+
+    /* Now let's see what we're using */
+    if (obj->o_type == RELIC) switch (obj->o_which) {
+        case MING_STAFF: {
+            static struct object missile = {
+              MISSILE, {0,0}, 0, "", "0d4 " , NULL, 0, WS_MISSILE, 100, 1
+            };
+
+            debug("Firing Ming's staff");
+            sprintf(missile.o_hurldmg, "%dd4", monster->t_stats.s_lvl);
+            do_motion(&missile,
+                       monster->t_newpos.y, monster->t_newpos.x, monster);
+            hit_monster(unc(missile.o_pos), &missile, monster);
+            monster->t_artifact = monster->t_artifact * 4 / 5;
+        }
+        when EMORI_CLOAK:
+            debug("stunning with Emori's cloak");
+            do_zap(monster, obj, &monster->t_newpos, WS_PARALYZE, NULL);
+            obj->o_charges = 0;
+
+        when ASMO_ROD: {
+            char *name;
+
+            switch (rnd(3)) { /* Select a function */
+                case 0:    name = "lightning bolt";
+                when 1:    name = "flame";
+                otherwise: name = "ice";
+            }
+            shoot_bolt( monster, 
+                        monster->t_pos, 
+                        monster->t_newpos, 
+                        FALSE, 
+                        monster->t_index, 
+                        name, 
+                        roll(monster->t_stats.s_lvl,6));
+            monster->t_artifact /= 2;
+        }
+        when BRIAN_MANDOLIN:
+            /* Make sure the defendant is still around */
+            if (DISTANCE(monster->t_pos.y, monster->t_pos.x,
+                         hero.y, hero.x) < 25) {
+                if (!save(VS_MAGIC, &player, -4) &&
+                    !ISWEARING(R_ALERT)) {
+                    msg("Some beautiful music enthralls you.");
+                    player.t_no_move += movement(&player) * FREEZETIME;
+                    player.t_action = A_FREEZE;
+                    monster->t_artifact = monster->t_artifact * 2 / 3;
+                }
+                else {
+                    msg("You wince at a sour note.");
+                    monster->t_artifact /= 3;
+                }
+            }
+        when GERYON_HORN:
+            /* Make sure the defendant is still around */
+            if (DISTANCE(monster->t_pos.y, monster->t_pos.x,
+                         hero.y, hero.x) < 25) {
+                if (!ISWEARING(R_HEROISM) &&
+                    !save(VS_MAGIC, &player, -4)) {
+                        turn_on(player, ISFLEE);
+                        player.t_dest = &monster->t_pos;
+                        msg("A shrill blast terrifies you.");
+                        monster->t_artifact = monster->t_artifact * 3 / 4;
+                }
+                else  {
+                    msg("A shrill blast sends chills up your spine! ");
+                    monster->t_artifact /= 3;
+                }
+            }
+
+        otherwise:
+            /* Unknown RELIC! */
+            debug("Unknown wielded relic %d", obj->o_which);
+    }
+    else debug("Declared relic is %d", obj->o_type);
+
+    turn_off(*monster, CANSURPRISE);
+    /* Reset the monsters actions */
+    monster->t_action = A_NIL;
+    monster->t_using = NULL;
+}
+ 
+/*
+ * add something to the contents of something else
+ */
+
+put_contents(bag, item)
+register struct object *bag;            /* the holder of the items */
+register struct linked_list *item;      /* the item to put inside  */
+{
+    register struct linked_list *titem;
+    register struct object *tobj;
+
+    bag->o_ac++;
+    tobj = OBJPTR(item);
+    for (titem = bag->contents; titem != NULL; titem = next(titem)) {
+        if ((OBJPTR(titem))->o_which == tobj->o_which)
+            break;
+    }
+    if (titem == NULL) {        /* if not a duplicate put at beginning */
+        attach(bag->contents, item);
+    }
+    else {
+        item->l_prev = titem;
+        item->l_next = titem->l_next;
+        if (next(titem) != NULL) 
+            (titem->l_next)->l_prev = item;
+        titem->l_next = item;
+    }
+}
+
+/*
+ * remove something from something else
+ */
+
+take_contents(bag, item)
+register struct object *bag;            /* the holder of the items */
+register struct linked_list *item;
+{
+
+    if (bag->o_ac <= 0) {
+        msg("Nothing to take out");
+        return;
+    }
+    bag->o_ac--;
+    detach(bag->contents, item);
+    if (!add_pack(item, FALSE))
+        put_contents(bag, item);
+}
+
+
+do_bag(item)
+register struct linked_list *item;
+{
+
+    register struct linked_list *titem = NULL;
+    register struct object *obj, *tobj;
+    bool doit = TRUE;
+
+    obj = OBJPTR(item);
+    while (doit) {
+        msg("What do you want to do? (* for a list): ");
+        mpos = 0;
+        switch (wgetch(cw)) {
+            case EOF:
+            case ESC:
+                msg ("");
+                doit = FALSE;
+            when '1':
+                inventory(obj->contents, ALL);
+
+            when '2':
+                if (obj->o_ac >= MAXCONTENTS) {
+                    msg("the %s is full", m_magic[obj->o_which].mi_name);
+                    break;
+                }
+                switch (obj->o_which) {
+                case MM_BEAKER:
+                    titem = get_item(pack, "put in", POTION, FALSE, FALSE);
+                when MM_BOOK:
+                    titem = get_item(pack, "put in", SCROLL, FALSE, FALSE);
+                }
+                if (titem == NULL)
+                    break;
+                detach(pack, titem);
+                inpack--;
+                put_contents(obj, titem);
+            
+            when '3':
+                titem = get_item(obj->contents,"take out",ALL,FALSE,FALSE);
+                if (titem == NULL)
+                    break;
+                take_contents(obj, titem);
+                
+            when '4': 
+                switch (obj->o_which) {
+                case MM_BEAKER:
+                    titem = get_item(obj->contents,"quaff",ALL,FALSE,FALSE);
+                    if (titem == NULL)
+                        break;
+                    tobj = OBJPTR(titem);
+                    obj->o_ac--;
+                    detach(obj->contents, titem);
+                    quaff(tobj->o_which, 
+                          tobj->o_kind,
+                          tobj->o_flags,
+                          TRUE);
+                    if (p_know[tobj->o_which] && p_guess[tobj->o_which])
+                    {
+                        free(p_guess[tobj->o_which]);
+                        p_guess[tobj->o_which] = NULL;
+                    }
+                    else if (!p_know[tobj->o_which]             && 
+                             askme                              &&
+                             (tobj->o_flags & ISKNOW) == 0      &&
+                             (tobj->o_flags & ISPOST) == 0      &&
+                             p_guess[tobj->o_which] == NULL) {
+                        nameitem(titem, FALSE);
+                    }
+                    o_discard(titem);
+                when MM_BOOK:   
+                    if (on(player, ISBLIND)) {
+                        msg("You can't see to read anything! ");
+                        break;
+                    }
+                    titem = get_item(obj->contents,"read",ALL,FALSE,FALSE);
+                    if (titem == NULL)
+                        break;
+                    tobj = OBJPTR(titem);
+                    obj->o_ac--;
+                    detach(obj->contents, titem);
+                    read_scroll(tobj->o_which, 
+                                tobj->o_flags & (ISCURSED|ISBLESSED),
+                                TRUE);
+                    if (s_know[tobj->o_which] && s_guess[tobj->o_which])
+                    {
+                        free(s_guess[tobj->o_which]);
+                        s_guess[tobj->o_which] = NULL;
+                    }
+                    else if (!s_know[tobj->o_which]             && 
+                             askme                              &&
+                             (tobj->o_flags & ISKNOW) == 0      &&
+                             (tobj->o_flags & ISPOST) == 0      &&
+                             s_guess[tobj->o_which] == NULL) {
+                        nameitem(titem, FALSE);
+                    }
+                    o_discard(titem);
+                }
+                doit = FALSE;
+
+            otherwise:
+                wclear(hw);
+                touchwin(hw);
+                mvwaddstr(hw,0,0,"The following operations are available:");
+                mvwaddstr(hw,2,0,"[1]\tInventory\n");
+                wprintw(hw,"[2]\tPut something in the %s\n",
+                        m_magic[obj->o_which].mi_name);
+                wprintw(hw,"[3]\tTake something out of the %s\n",
+                        m_magic[obj->o_which].mi_name);
+                switch(obj->o_which) {
+                    case MM_BEAKER: waddstr(hw,"[4]\tQuaff a potion\n");
+                    when MM_BOOK:   waddstr(hw,"[4]\tRead a scroll\n");
+                }
+        /* this is confusing! <press space to continue> */
+                /* waddstr(hw,"[ESC]\tLeave this menu\n"); */
+                mvwaddstr(hw, lines-1, 0, spacemsg);
+                draw(hw);
+                wait_for (' ');
+                restscr(cw);
+        }
+    }
+}
+
+do_panic(who)
+int who;        /* Kind of monster to panic (all if who is NULL) */
+{
+    register int x,y;
+    register struct linked_list *mon, *item;
+    register struct thing *th;
+
+    for (x = hero.x-2; x <= hero.x+2; x++) {
+        for (y = hero.y-2; y <= hero.y+2; y++) {
+            if (y < 1 || x < 0 || y > lines - 3  || x > cols - 1) 
+                continue;
+            if (isalpha(mvwinch(mw, y, x))) {
+
+                if ((mon = find_mons(y, x)) != NULL) {
+                    th = THINGPTR(mon);
+
+                    /* Is this the right kind of monster to panic? */
+                    if (who && th->t_index != who) continue;
+
+                    if ((who && th->t_stats.s_intel < 14) || 
+                        (!on(*th, ISUNDEAD) && !save(VS_MAGIC, th, 0) &&
+              off(*th, WASTURNED))) {
+                          msg("%s %s.", prname(monster_name(th), TRUE),
+                            terse ? "panics" : "turns to run in panic");
+
+                        turn_on(*th, ISFLEE);
+                        turn_on(*th, WASTURNED);
+                        turn_off(*th, CANSURPRISE);
+
+                        /* Disrupt what it was doing */
+                        dsrpt_monster(th, TRUE, TRUE);
+
+                        /* If monster was suffocating, stop it */
+                        if (on(*th, DIDSUFFOCATE)) {
+                            turn_off(*th, DIDSUFFOCATE);
+                            extinguish(suffocate);
+                        }
+
+                        /* If monster held us, stop it */
+                        if (on(*th, DIDHOLD) && (--hold_count == 0))
+                                turn_off(player, ISHELD);
+                        turn_off(*th, DIDHOLD);
+
+                        /*
+                         * if he has something he might drop it
+                         */
+                        if ((item = th->t_pack) != NULL         && 
+                            (OBJPTR(item))->o_type != RELIC     && 
+                            rnd(100) < 67) {
+                                detach(th->t_pack, item);
+                                fall(item, FALSE);
+                        }
+
+                        /* It is okay to turn tail */
+                        th->t_oldpos = th->t_pos;
+                    }
+                    runto(th, &hero);
+                }
+            }
+        }
+    }
+}
+
+/*
+ * print miscellaneous magic bonuses
+ */
+
+int
+misc_name(str,obj)
+char *str;
+register struct object *obj;
+{
+    char buf1[LINELEN];
+
+    *str = 0;
+    buf1[0] = 0;
+
+    if (!(obj->o_flags & ISKNOW))
+    {
+        strcat(str,m_magic[obj->o_which].mi_name);
+        return(0);
+    }
+
+    switch (obj->o_which) 
+    {
+        case MM_BRACERS:
+        case MM_PROTECT:
+            strcat(str, num(obj->o_ac, 0));
+            strcat(str, " ");
+    }
+    switch (obj->o_which) {
+    case MM_CRYSTAL:
+            if (obj->o_flags & ISBLESSED)
+                strcat(str, "glowing ");
+    }
+    switch (obj->o_which) {
+        case MM_G_OGRE:
+        case MM_G_DEXTERITY:
+        case MM_JEWEL:
+        case MM_STRANGLE:
+        case MM_R_POWERLESS:
+        case MM_DANCE:
+            if (obj->o_flags & ISCURSED)
+                strcat(str, "cursed ");
+        when MM_CRYSTAL:
+            if (obj->o_flags & ISCURSED)
+                strcat(str, "opaque ");
+    }
+    strcat(str, m_magic[obj->o_which].mi_name);
+
+    switch (obj->o_which) 
+    {
+        case MM_JUG:
+            if (obj->o_ac == JUG_EMPTY)
+                strcat(buf1, " [empty]");
+            else if (p_know[obj->o_ac])
+                sprintf(buf1, " [containing a potion of %s (%s)]",
+                        p_magic[obj->o_ac].mi_name,
+                        p_colors[obj->o_ac]);
+            else sprintf(buf1, " [containing a%s %s liquid]", 
+                        vowelstr(p_colors[obj->o_ac]),
+                        p_colors[obj->o_ac]);
+        when MM_BEAKER:         
+        case MM_BOOK: {
+            sprintf(buf1, " [containing %d]", obj->o_ac);
+        }
+        when MM_OPEN:
+        case MM_HUNGER:
+            sprintf(buf1, " [%d ring%s]", obj->o_charges, 
+                          obj->o_charges == 1 ? "" : "s");
+        when MM_DRUMS:
+            sprintf(buf1, " [%d beat%s]", obj->o_charges, 
+                          obj->o_charges == 1 ? "" : "s");
+        when MM_DISAPPEAR:
+        case MM_CHOKE:
+            sprintf(buf1, " [%d pinch%s]", obj->o_charges, 
+                          obj->o_charges == 1 ? "" : "es");
+        when MM_KEOGHTOM:
+            sprintf(buf1, " [%d application%s]", obj->o_charges, 
+                          obj->o_charges == 1 ? "" : "s");
+        when MM_SKILLS:
+            sprintf(buf1, " [%s]", char_class[obj->o_ac].name);
+    }
+    strcat(str, buf1);
+    
+    return(0);
+}
+
+use_emori()
+{
+    char selection;     /* Cloak function */
+    int state = 0;      /* Menu state */
+
+    msg("What do you want to do? (* for a list): ");
+    do {
+        selection = wgetch(cw);
+        switch (selection) {
+            case '*':
+              if (state != 1) {
+                wclear(hw);
+                touchwin(hw);
+                mvwaddstr(hw, 2, 0,  "[1] Fly\n[2] Stop flying\n");
+                waddstr(hw,          "[3] Turn invisible\n[4] Turn Visible\n");
+                mvwaddstr(hw, 0, 0, "What do you want to do? ");
+                draw(hw);
+                state = 1;      /* Now in prompt window */
+              }
+              break;
+
+            case ESC:
+                if (state == 1) {
+                    restscr(cw);
+                }
+                msg("");
+
+                after = FALSE;
+                return;
+
+            when '1':
+            case '2':
+            case '3':
+            case '4':
+                if (state == 1) {       /* In prompt window */
+                    restscr(cw);
+                }
+
+                msg("");
+
+                state = 2;      /* Finished */
+                break;
+
+            default:
+                if (state == 1) {       /* In the prompt window */
+                    mvwaddstr(hw, 0, 0,
+                                "Please enter a selection between 1 and 4:  ");
+                    draw(hw);
+                }
+                else {  /* Normal window */
+                    mpos = 0;
+                    msg("Please enter a selection between 1 and 4:  ");
+                }
+        }
+    } while (state != 2);
+
+    /* We now must have a selection between 1 and 4 */
+    switch (selection) {
+        case '1':       /* Fly */
+            if (on(player, ISFLY)) {
+                extinguish(land);       /* Extinguish in case of potion */
+                msg("%slready flying.", terse ? "A" : "You are a");
+            }
+            else {
+                msg("You feel lighter than air!");
+                turn_on(player, ISFLY);
+            }
+        when '2':       /* Stop flying */
+            if (off(player, ISFLY))
+                msg("%sot flying.", terse ? "N" : "You are n");
+            else {
+                if (find_slot(land))
+                    msg("%sot flying by the cloak.",
+                        terse ? "N" : "You are n");
+                else land();
+            }
+        when '3':       /* Turn invisible */
+            if (off(player, ISINVIS)) {
+                turn_on(player, ISINVIS);
+                msg("You have a tingling feeling all over your body. ");
+                PLAYER = IPLAYER;
+                light(&hero);
+            }
+            else {
+                extinguish(appear);     /* Extinguish in case of potion */
+                extinguish(dust_appear);/* dust of disappearance        */
+                msg("%slready invisible.", terse ? "A" : "You are a");
+            }
+        when '4':       /* Turn visible */
+            if (off(player, ISINVIS))
+                msg("%sot invisible.", terse ? "N" : "You are n");
+            else {
+                if (find_slot(appear) || find_slot(dust_appear))
+                    msg("%sot invisible by the cloak.",
+                        terse ? "N" : "You are n");
+                else appear();
+            }
+    }
+}
+
+/*
+ * try to write a scroll with the quill of Nagrom
+ */
+
+use_quill(obj)
+struct object *obj;
+{
+    struct linked_list  *item;
+    register int        i,
+                        scroll_ability;
+    int                 which_scroll,
+                        curlen,
+                        maxlen = 0,
+                        dummy = 0;
+    bool                nohw = FALSE;
+
+    i = which_scroll = 0;
+    scroll_ability = obj->o_charges;
+
+    /* Prompt for scrolls */
+    msg("Which scroll are you writing? (* for list): ");
+
+    which_scroll = (int) (wgetch(cw) - 'a');
+    msg("");    /* Get rid of the prompt */
+    if (which_scroll == (int) ESC - (int) 'a') {
+        after = FALSE;
+        return;
+    }
+    if (which_scroll >= 0 && which_scroll < MAXQUILL) nohw = TRUE;
+
+    else if (slow_invent) {
+        register char c;
+
+        nohw = TRUE;
+        do {
+            for (i=0; i<MAXQUILL; i++) {
+                msg("");
+                mvwaddch(msgw, 0, 0, '[');
+                waddch(msgw, (char) ((int) 'a' + i));
+                waddstr(msgw, "] A scroll of ");
+                waddstr(msgw, s_magic[quill_scrolls[i].s_which].mi_name);
+                waddstr(msgw, morestr);
+                clearok(msgw, FALSE);
+                draw(msgw);
+                do {
+                    c = wgetch(cw);
+                } while (c != ' ' && c != ESC);
+                if (c == ESC)
+                    break;
+            }
+            msg("");
+            mvwaddstr(msgw, 0, 0, "Which scroll are you writing? ");
+            clearok(msgw, FALSE);
+            draw(msgw);
+
+            which_scroll = (int) (wgetch(cw) - 'a');
+        } while (which_scroll != (int) (ESC - 'a') &&
+                 (which_scroll < 0 || which_scroll >= MAXQUILL));
+
+        if (which_scroll == (int) (ESC - 'a')) {
+            mpos = 0;
+            msg("");
+            after = FALSE;
+            return;
+        }
+    }
+    else {
+        /* Now display the possible scrolls */
+        wclear(hw);
+        touchwin(hw);
+        mvwaddstr(hw, 2, 0, "   Cost            Scroll");
+        mvwaddstr(hw, 3, 0,
+                "-----------------------------------------------");
+        maxlen = 47;    /* Maximum width of header */
+
+        for (i=0; i<MAXQUILL; i++) {
+            wmove(hw, i+4, 0);
+            sprintf(prbuf, "[%c]        %3d     A scroll of %s",
+                    (char) ((int) 'a' + i),
+                    quill_scrolls[i].s_cost,
+                    s_magic[quill_scrolls[i].s_which].mi_name);
+            waddstr(hw, prbuf);
+
+            /* Get the length of the line */
+            getyx(hw, dummy, curlen);
+            if (maxlen < curlen) maxlen = curlen;
+        }
+
+        sprintf(prbuf, "[Current scroll power = %d]", scroll_ability);
+        mvwaddstr(hw, 0, 0, prbuf);
+        waddstr(hw, " Which scroll are you writing? ");
+        getyx(hw, dummy, curlen);
+        if (maxlen < curlen) maxlen = curlen;
+
+        /* Should we overlay? */
+        if (menu_overlay && MAXQUILL + 3 < lines - 3) {
+            over_win(cw, hw, MAXQUILL + 5, maxlen + 3, 0, curlen, NULL);
+        }
+        else draw(hw);
+    }
+
+    if (!nohw) {
+        which_scroll = (int) (wgetch(cw) - 'a');
+        while (which_scroll < 0 || which_scroll >= MAXQUILL) {
+            if (which_scroll == (int) ESC - (int) 'a') {
+                after = FALSE;
+
+                /* Restore the screen */
+                if (MAXQUILL + 3 < lines / 2) {
+                    clearok(cw, FALSE);
+                    touchwin(cw);
+                }
+                else restscr(cw);
+                return;
+            }
+            wmove(hw, 0, 0);
+            wclrtoeol(hw);
+            waddstr(hw, "Please enter one of the listed scrolls. ");
+            getyx(hw, dummy, curlen);
+            if (maxlen < curlen) maxlen = curlen;
+
+            /* Should we overlay? */
+            if (menu_overlay && MAXQUILL + 3 < lines - 3) {
+                over_win(cw, hw, MAXQUILL + 5, maxlen + 3,
+                            0, curlen, NULL);
+            }
+            else draw(hw);
+
+            which_scroll = (int) (wgetch(cw) - 'a');
+        }
+    }
+
+    /* Now restore the screen if we have to */
+    if (!nohw) {
+        if (MAXQUILL + 3 < lines / 2) {
+            touchwin(cw);
+            clearok(cw, FALSE);
+        }
+        else restscr(cw);
+    }
+
+    /* We've waited our required time. */
+    player.t_using = NULL;
+    player.t_action = A_NIL;
+
+    if (quill_scrolls[which_scroll].s_cost > scroll_ability) {
+        msg("Your attempt fails.");
+        return;
+    }
+
+    obj->o_charges -= quill_scrolls[which_scroll].s_cost;
+    item = spec_item(SCROLL, quill_scrolls[which_scroll].s_which, 0, 0);
+    if (add_pack(item, FALSE) == FALSE) {
+        (OBJPTR(item))->o_pos = hero;
+        fall(item, TRUE);
+    }
+
+    which_scroll = dummy; /* Hack to stop IRIX complaint about dummy not */
+                          /* being used */
+}
+
+/*
+ * Use something
+ */
+
+use_mm(which)
+int which;
+{
+    register struct object *obj = NULL;
+    register struct linked_list *item = NULL;
+    bool is_mm;
+
+    is_mm = FALSE;
+
+    if (which < 0) {    /* A real miscellaneous magic item  */
+        /* This is miscellaneous magic.  It takes 3 movement periods to use */
+        if (player.t_action != C_USE) {
+            int units;  /* Number of movement units for the item */
+
+            item = get_item(pack, "use", USEABLE, FALSE, FALSE);
+
+            /*
+             * Make certain that it is a micellaneous magic item
+             */
+            if (item == NULL)
+                return;
+
+            units = usage_time(item);
+            if (units < 0) return;
+
+            player.t_using = item;      /* Remember what it is */
+            player.t_action = C_USE;    /* We are quaffing */
+            player.t_no_move = units * movement(&player);
+            return;
+        }
+
+        /* We have waited our time, let's use the item */
+        item = player.t_using;
+        player.t_using = NULL;
+        player.t_action = A_NIL;
+
+        is_mm = TRUE;
+
+        obj = OBJPTR(item);
+        which = obj->o_which;
+    }
+
+    if (obj->o_type == POTION) {                /* A potion */
+        is_mm = FALSE;
+        inpack--;
+        detach (pack, item);
+        switch (obj->o_which) {
+            case P_POISON:
+                if (cur_weapon) {
+                    if (cur_weapon->o_type == RELIC) {
+                        msg("The poison burns off %s", 
+                            inv_name(cur_weapon,FALSE));
+                    }
+                    else {
+                        cur_weapon->o_flags |= ISPOISON;
+                        msg("Your weapon has %s gooey stuff on it",
+                            p_colors[cur_weapon->o_which]);
+                    }
+                }
+                else 
+                    msg("The poison pours on the floor and disappears!");
+        }
+        o_discard(item);
+    }
+    else if (obj->o_type == RELIC) {            /* An artifact */
+        is_mm = FALSE;
+        switch (obj->o_which) {
+            case EMORI_CLOAK:
+                use_emori();
+            when QUILL_NAGROM:
+                use_quill(obj);
+            when BRIAN_MANDOLIN:
+                /* Put monsters around us to sleep */
+                read_scroll(S_HOLD, 0, FALSE);
+            when GERYON_HORN:
+                /* Chase close monsters away */
+                msg("The horn blasts a shrill tone.");
+                do_panic(NULL);
+            when EYE_VECNA:
+                msg("The pain slowly subsides.. ");
+            when HEIL_ANKH:
+                msg("Your hand grows very warm. ");
+            when YENDOR_AMULET:
+                msg("Your chest glows! ");
+                do_panic(findmindex("frost giant"));
+            when STONEBONES_AMULET:
+                msg("Your chest glows! ");
+                do_panic(findmindex("storm giant"));
+            when SURTUR_RING:
+                do_panic(findmindex("fire giant"));
+            when ALTERAN_CARD:  /* the card allows you to teleport anywhere */
+        do_teleport();
+        }
+    }
+    else switch (which) {               /* Miscellaneous Magic */
+        /*
+         * the jug of alchemy manufactures potions when you drink
+         * the potion it will make another after a while
+         */
+        case MM_JUG:
+            if (obj->o_ac == JUG_EMPTY) {
+                msg("The jug is empty");
+                break;
+            }
+            quaff (obj->o_ac, NULL, NULL, FALSE);
+            obj->o_ac = JUG_EMPTY;
+            fuse (alchemy, obj, ALCHEMYTIME, AFTER);
+            if (!(obj->o_flags & ISKNOW))
+                whatis(item);
+
+        /*
+         * the beaker of plentiful potions is used to hold potions
+         * the book of infinite spells is used to hold scrolls
+         */
+        when MM_BEAKER:
+        case MM_BOOK:
+            do_bag(item);
+
+        /*
+         * the chime of opening opens up secret doors
+         */
+        when MM_OPEN:
+        {
+            register struct linked_list *exit;
+            register struct room *rp;
+            register coord *cp;
+
+            if (obj->o_charges <= 0) {
+                msg("The chime is cracked!");
+                break;
+            }
+            obj->o_charges--;
+            msg("chime... chime... hime... ime... me... e...");
+            if ((rp = roomin(&hero)) == NULL) {
+                search(FALSE, TRUE); /* Non-failing search for door */
+                break;
+            }
+            for (exit = rp->r_exit; exit != NULL; exit = next(exit)) {
+                cp = DOORPTR(exit);
+                if (winat(cp->y, cp->x) == SECRETDOOR) {
+                    mvaddch (cp->y, cp->x, DOOR);
+                    if (cansee (cp->y, cp->x))
+                        mvwaddch(cw, cp->y, cp->x, DOOR);
+                }
+            }
+        }
+
+        /*
+         * the chime of hunger just makes the hero hungry
+         */
+        when MM_HUNGER:
+            if (obj->o_charges <= 0) {
+                msg("The chime is spent. ");
+                break;
+            }
+            obj->o_charges--;
+            if (food_left >= MORETIME + 5) {
+                food_left = MORETIME + 5;
+                msg("A strange sensation comes over you.. ");
+                msg(terse? "Getting hungry" : "You are starting to get hungry");
+                hungry_state = F_HUNGRY;
+            }
+            if (player.t_ctype == C_PALADIN ||
+                player.t_ctype == C_RANGER  || player.t_ctype == C_MONK) {
+                    msg("You feel a chilling sensation!");
+                    aggravate(TRUE, FALSE);
+            }
+            else {
+                aggravate(TRUE, TRUE);
+            }
+
+        /*
+         * the drums of panic make all creatures within two squares run
+         * from the hero in panic unless they save or they are mindless
+         * undead
+         */
+        when MM_DRUMS:
+            if (obj->o_charges <= 0) {
+                msg("The drum is broken.");
+                break;
+            }
+            obj->o_charges--;
+            do_panic(NULL);
+        return;
+        /*
+         * dust of disappearance makes the player invisible for a while
+         */
+        when MM_DISAPPEAR:
+            m_know[MM_DISAPPEAR] = TRUE;
+            if (obj->o_charges <= 0) {
+                msg("No more dust!");
+                break;
+            }
+            obj->o_charges--;
+            if (terse) msg("You sneeze! ");
+            else msg("Ahh.. Ahh... Choo!! ");
+            if (!find_slot(dust_appear)) {
+                turn_on(player, ISINVIS);
+                fuse(dust_appear, (VOID *)NULL, DUSTTIME, AFTER);
+                PLAYER = IPLAYER;
+                light(&hero);
+            }
+            else lengthen(dust_appear, DUSTTIME);
+
+        /*
+         * dust of choking and sneezing can kill the hero if he misses
+         * the save
+         */
+        when MM_CHOKE:
+            m_know[MM_CHOKE] = TRUE;
+            if (obj->o_charges <= 0) {
+                msg("No more dust!");
+                break;
+            }
+            obj->o_charges--;
+            if (terse) msg("You snort! ");
+            else msg("aaAAACHOOOooo. Cough. Cough. Sneeze. Sneeze.");
+            if (!cur_relic[SURTUR_RING] && !save(VS_POISON, &player, 0)) {
+                msg ("You choke to death!!!  --More--");
+                wait_for(' ');
+                pstats.s_hpt = -1;  /* in case he hangs up the phone! */
+                death(D_CHOKE);
+            }
+            else {
+                msg("You begin to cough and choke uncontrollably! ");
+                if (find_slot(unchoke))
+                    lengthen(unchoke, DUSTTIME);
+                else
+                    fuse(unchoke, (VOID *)NULL, DUSTTIME, AFTER);
+                turn_on(player, ISHUH);
+                turn_on(player, ISBLIND);
+                light(&hero);
+            }
+                
+        when MM_KEOGHTOM:
+            /*
+             * this is a very powerful healing ointment
+             * but it takes a while to put on...
+             */
+            obj->o_charges--;
+            if (on(player, HASDISEASE)) {
+                extinguish(cure_disease);
+                cure_disease();
+                msg(terse ? "You feel yourself improving."
+                          : "You begin to feel yourself improving again.");
+            }
+            if (on(player, HASINFEST)) {
+                turn_off(player, HASINFEST);
+                infest_dam = 0;
+                msg(terse ? "You feel yourself improving."
+                          : "You begin to feel yourself improving again.");
+            }
+            if (on(player, DOROT)) {
+                msg("You feel your skin returning to normal.");
+                turn_off(player, DOROT);
+            }
+            pstats.s_hpt += roll(pstats.s_lvl, 6);
+            if (pstats.s_hpt > max_stats.s_hpt)
+                pstats.s_hpt = max_stats.s_hpt;
+            sight();
+            msg("You begin to feel much better.");
+                
+        /*
+         * The book has a character class associated with it.
+         * if your class matches that of the book, it will raise your 
+         * level by one. If your class does not match the one of the book, 
+         * it change your class to that of book.
+         * Note that it takes a while to read.
+         */
+        when MM_SKILLS:
+            detach (pack, item);
+            inpack--;
+            changeclass(&obj->o_ac);
+    when MM_CRYSTAL:
+    {
+        register char *str;
+
+            detach (pack, item);
+            inpack--;
+            if (obj->o_flags & ISCURSED) {
+            if (is_mm && !m_know[MM_CRYSTAL])
+                str = "rock in a curious sort of way";
+        else
+            str = "crystal briefly";
+        msg("You rub the %s and yell out in agony! ", str);
+          /* curse his pack */
+        read_scroll(S_REMOVE, obj->o_flags & ISCURSED, FALSE);
+          /* aggravate monsters */
+        read_scroll(S_HOLD, obj->o_flags & ISCURSED, FALSE);
+                player.t_no_move += (2 * movement(&player) * FREEZETIME);
+                player.t_action = A_FREEZE;
+          /* loss of 1/4 total hit points */
+        pstats.s_hpt -= ((max_stats.s_hpt / 4));
+                max_stats.s_hpt -= rnd(3)+3;
+        if (pstats.s_hpt > max_stats.s_hpt) 
+                pstats.s_hpt = max_stats.s_hpt;
+                if ((pstats.s_hpt < 1) || (max_stats.s_hpt < 1)) {
+            pstats.s_hpt = -1;
+            msg("The crystal has absorbed you...  --More--");
+            wait_for(' ');
+                    death(D_CRYSTAL);
+        }
+        }
+        else {  /* if normal, give him a bonus */
+            if (is_mm && !m_know[MM_CRYSTAL])
+                    str = "flashes brightly";
+        else
+            str = "vibrates softly";
+        msg("You rub the crystal and it %s...  ", str);
+          /* cure him */
+        read_scroll(S_CURING, NULL, FALSE);
+          /* give him weird hands */
+                turn_on(player, CANHUH);
+        msg("Your fingertips turn blue.  ");
+          /* add intelligence */
+                if (player.t_ctype == C_MAGICIAN) {
+                max_stats.s_intel += 1;
+                pstats.s_intel += 1;
+        }
+          /* add strength */
+                if (player.t_ctype == C_FIGHTER) {
+            max_stats.s_str += 1;
+                pstats.s_str += 1;
+        }
+          /* add wisdom */
+                if (player.t_ctype == C_CLERIC || player.t_ctype == C_PALADIN) {
+                    max_stats.s_wisdom += 1;
+                    pstats.s_wisdom += 1;
+        }
+          /* add dexterity */
+                if (player.t_ctype == C_THIEF || player.t_ctype == C_ASSASSIN) {
+                    max_stats.s_dext += 1;
+                    pstats.s_dext += 1;
+        }
+              /* add constitution */
+                if (player.t_ctype == C_MONK) {
+                    max_stats.s_const += 1;
+                    pstats.s_const += 1;
+        }
+          /* add charisma */
+                if (player.t_ctype == C_RANGER || player.t_ctype == C_PALADIN) {
+                max_stats.s_charisma += 1;
+                pstats.s_charisma += 1;
+        }
+        }
+            if (obj->o_flags & ISBLESSED) {  /* if blessed */
+            if (is_mm && !m_know[MM_CRYSTAL])
+            msg("The crystal disappears from your hands.  ");
+        else
+            msg("Your hands absorb the medicine crystal.  ");
+            /* set hit points to at least 50 */
+        if (max_stats.s_hpt < 50) {
+            max_stats.s_hpt = 50;
+                    pstats.s_hpt = max_stats.s_hpt;
+        }
+        else {  /* or just add 10% */
+            max_stats.s_hpt += (max_stats.s_hpt / 10);
+                    pstats.s_hpt = max_stats.s_hpt;
+        }
+            /* heck, really make it memorable */
+        read_scroll(S_REMOVE, obj->o_flags & ISBLESSED, FALSE);
+        }
+    }
+        otherwise:
+            msg("What a strange magic item you have!");
+    }
+    status(FALSE);
+    if (is_mm && m_know[which] && m_guess[which]) {
+        free(m_guess[which]);
+        m_guess[which] = NULL;
+    }
+    else if (is_mm && !m_know[which] && askme &&
+             (obj->o_flags & ISKNOW) == 0 &&
+             m_guess[which] == NULL) {
+        nameitem(item, FALSE);
+    }
+    if (item != NULL && (which == MM_SKILLS || which == MM_CRYSTAL))
+        o_discard(item);
+    updpack(TRUE, &player);
+}
+
+/*
+ * usage_time:
+ *      Return how long it takes to use an item.  For now we only give time
+ *      for MM, RELIC, SCROLL, and POTION items.
+ */
+
+int
+usage_time(item)
+struct linked_list *item;
+{
+    register struct object *obj;
+    register int units = -1;
+
+    obj = OBJPTR(item);
+    switch (obj->o_type) {
+        case SCROLL:    units = 4;
+        when POTION:    units = 3;
+        when RELIC:                     /* An artifact */
+            switch (obj->o_which) {
+                case BRIAN_MANDOLIN:
+                case GERYON_HORN:       units = 4;
+                when QUILL_NAGROM:
+                case EMORI_CLOAK:
+                case HEIL_ANKH:         units = 3;
+                when YENDOR_AMULET:
+                case STONEBONES_AMULET: units = 2;
+                when EYE_VECNA:         units = 6;
+                    /* The eye will do nothing other than give a headache */
+                    pstats.s_hpt -= rnd(25)+1;
+                    msg("You feel a sharp pain shoot through your forehead!");
+                    if (pstats.s_hpt < 1) {
+               pstats.s_hpt = -1;
+                       msg ("The pain is too much for you to bear!  --More--");
+                       wait_for(' ');
+                       death(D_RELIC);
+                    }
+                when SURTUR_RING:
+                    units = 3;
+                    msg("Your nose tickles a bit.");
+        when ALTERAN_CARD:
+            units = 2;
+            msg("You gaze intently at the card... ");
+            }
+        when MM:
+            switch (obj->o_which) {     /* Miscellaneous Magic */
+                case MM_JUG:
+                    if (obj->o_ac == JUG_EMPTY) {
+                        msg("The jug is empty");
+                        return (-1);
+                    }
+                    units = 2;
+                when MM_BEAKER:
+                case MM_BOOK:
+                    /* This is a strange case because it can go forever */
+                    units = 1;
+                case MM_CHOKE: /* Dust */
+                when MM_HUNGER: /* Chimes */
+                    units = 3;
+                when MM_OPEN:
+                case MM_DRUMS:
+                case MM_DISAPPEAR:
+                    units = 4;
+                when MM_KEOGHTOM:
+            /* Ointment */
+                    if (obj->o_charges <= 0) {
+                        msg("The jar is empty!");
+                        return (-1);
+                    }
+                    units = 5;
+                when MM_SKILLS:
+                    /* A whole book! */
+                    units = 15;
+                when MM_CRYSTAL:
+            /* Enhance player's quest */
+            units = 5;
+                otherwise:
+                    /* What is it? */
+                    units = -1;
+            }
+        otherwise:      units = -1;
+    }
+
+    return (units);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xrogue/mons_def.c	Tue Apr 21 08:55:20 2015 -0400
@@ -0,0 +1,1660 @@
+/*
+    mons_def.c - monster data initializer
+    
+    XRogue: Expeditions into the Dungeons of Doom
+    Copyright (C) 1991 Robert Pietkivitch
+    All rights reserved.
+    
+    Based on "Advanced Rogue"
+    Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka and AT&T
+    All rights reserved.
+
+    Based on "Rogue: Exploring the Dungeons of Doom"
+    Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
+    All rights reserved.
+    
+    See the file LICENSE.TXT for full copyright and licensing information.
+*/
+
+#include <ctype.h>
+#include <curses.h>
+#include "rogue.h"
+
+#define HPT(x) x
+
+struct monster monsters[NUMMONST+1] = {
+/* {"Name",
+                CARRY,  NORMAL, WANDER, APPEAR, INTEL,
+                {ATTRIBUTES},
+                "SUMMONED_CREATURE", NUMBER_SUMMONED,
+                ADDED_EXPERIENCE/HIT_POINT,
+                {str    dex,    move,   exp,    level,  "armor", hit_points,
+                "damage"}}, */
+{"unknown",
+                0,      FALSE,  FALSE,  '\0',   "",
+                {0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+                "", 0,
+                0,
+                {0,     0,      0,      0,      0,      0,      HPT(""),
+                ""}},
+{"giant rat",
+                0,      TRUE,   TRUE,   'R',    "2-6",
+                {ISMEAN, CANDISEASE},
+                "", 0,
+                0,
+                {10,    10,     6,      5,      1,      7,      HPT("1d4"),
+                "1d3"}},
+{"kobold",
+                50,     TRUE,   TRUE,   'K',    "8-12",
+                {ISMEAN, CANSHOOT, CARRYWEAPON},
+                "", 0,
+                2,
+                {9,     9,      5,      8,      2,      7,      HPT("1d4"),
+                "1d4"}},
+{"bat",
+                0,      TRUE,   TRUE,   'b',    "2-6",
+                {ISMEAN, AREMANY, CANDISEASE, ISFLY},
+                "", 0,
+                0,
+                {5,     5,      6,      5,      1,      10,     HPT("1d2"),
+                "1d2"}},
+{"gnome",
+                50,     TRUE,   FALSE,  'G',    "10-15",
+                {CANSHOOT, CARRYPOTION, CARRYWEAPON, NOSTAB},
+                "", 0,
+                3,
+                {10,    10,     6,      8,      1,      5,      HPT("1d6"),
+                "1d6"}},
+{"halfling",
+                50,     TRUE,   FALSE,  'H',    "11-16",
+                {CANSHOOT, CARRYSCROLL, CARRYWEAPON, NOSTAB},
+                "", 0,
+                3,
+                {8,     10,     6,      10,     1,      4,      HPT("1d8"),
+                "1d6"}},
+{"xvart",
+                50,     TRUE,   TRUE,   'x',    "4-14",
+                {ISMEAN, AREMANY, CARRYDAGGER, CANTELEPORT},
+                "", 0,
+                1,
+                {8,     10,     7,      8,      1,      7,      HPT("1d2"),
+                "1d3"}},
+{"manes",
+                0,      TRUE,   TRUE,   'M',    "2-8",
+                {ISMEAN, ISUNDEAD, TURNABLE, CANDISEASE},
+                "", 0,
+                0,
+                {5,     5,      5,      15,     2,      7,      HPT("1d8"),
+                "1d2/1d2/1d4"}},
+{"rot grub",
+                0,      TRUE,   TRUE,   'r',    "10",
+                {ISMEAN, CANDISEASE, CANINFEST, CANSMELL},
+                "", 0,
+                0,
+                {10,    10,     8,      8,      1,      8,      HPT("1d6"),
+                "1d6"}},
+{"giant ant",
+                0,      TRUE,   TRUE,   'A',    "1",
+                {ISMEAN, CANPOISON},
+                "", 0,
+                3,
+                {10,    10,     6,      30,     3,      3,      HPT("2d8"),
+                "1d6/1d6"}},
+{"orc",
+                50,     TRUE,   TRUE,   'O',    "8",
+                {ISMEAN, CANSHOOT, CARRYFOOD},
+                "", 0,
+                2,
+                {12,    12,     5,      15,     4,      6,      HPT("2d8"),
+                "1d8"}},
+{"dwarf",
+                50,     TRUE,   FALSE,  'D',    "10-14",
+                {CARRYSCROLL, CARRYGOLD, CARRYDAGGER, NOSTAB},
+                "", 0,
+                4,
+                {10,    10,     6,      20,     1,      4,      HPT("2d8"),
+                "1d8"}},
+{"elf",
+                50,     TRUE,   FALSE,  'E',    "10-14",
+                {CARRYPOTION, CARRYWEAPON, NOSTAB, CARRYFOOD},
+                "", 0,
+                4,
+                {12,    10,     6,      20,     1,      4,      HPT("2d8+2"),
+                "1d10"}},
+{"hobgoblin",
+                50,     TRUE,   TRUE,   'h',    "8-10",
+                {ISMEAN, CANSHOOT, NOSLOW},
+                "", 0,
+                3,
+                {14,    14,     4,      30,     4,      5,      HPT("1d8"),
+                "1d8"}},
+{"urchin",
+                50,      TRUE,   TRUE,   'u',    "6-15",
+                {ISMEAN, ISGREED, CARRYGOLD, CARRYRING},
+                "", 0,
+                1,
+                {10,    10,     6,      25,     1,      3,      HPT("2d8"),
+                "1d6"}},
+{"fire beetle", 
+                0,      TRUE,   TRUE,   'B',    "10",
+                {ISMEAN, HASFIRE},
+                "", 0,
+                2,
+                {10,    10,     6,      20,     1,      4,      HPT("1d8+2"),
+                "2d4"}},
+{"ear seeker",
+                0,      TRUE,   TRUE,   'e',    "0",
+                {ISMEAN, AREMANY, CANINFEST, CANSURPRISE},
+                "", 0,
+                0,
+                {10,    10,     5,      10,     1,      8,      HPT("1d2"),
+                "1d1"}},
+{"shrieker",
+                0,      TRUE,   TRUE,  'S',    "0",
+                {ISMEAN, CANSHRIEK, NOMOVE, NOSTAB},
+                "", 0,
+                4,
+                {10,    10,     7,      20,     2,      7,      HPT("3d8"),
+                "0d0"}},
+{"stirge",
+                0,      TRUE,   TRUE,   's',    "1",
+                {ISMEAN, CANDRAW, ISFLY},
+                "", 0,
+                2,
+                {10,    10,     4,      30,     1,      8,      HPT("2d6"),
+                "1d3"}},
+{"troglodyte",
+                50,     TRUE,   TRUE,   'T',    "5-15",
+                {ISMEAN, CANSMELL, CANSTINK, CANSHOOT, HASFIRE},
+                "", 0,
+                3,
+                {10,    10,     6,      30,     5,      4,      HPT("2d8"),
+                "1d6/2d6"}},
+{"zombie",
+                0,      TRUE,   TRUE,   'Z',    "0",
+                {ISMEAN, ISUNDEAD, TURNABLE, CANSURPRISE, ISSHADOW, NOSLEEP},
+                "", 0,
+                6,
+                {10,    10,     5,      60,     1,      0,      HPT("2d8+5"),
+                "2d8"}},
+{"gas spore",
+                0,      TRUE,   TRUE,  'a',    "0",
+                {ISMEAN, CANEXPLODE, CANINFEST, ISFLY},
+                "", 0,
+                5,
+                {10,    10,     8,     30,     2,      5,      HPT("2d8"),
+                "1d2/1d4"}},
+{"giant tick",
+                0,      TRUE,   TRUE,   't',    "0",
+                {ISMEAN, CANPOISON, CANROT},
+                "", 0,
+                1,
+                {10,    10,     7,      70,     2,      4,      HPT("1d8"),
+                "1d4"}},
+{"lemure",
+                0,      TRUE,   TRUE,   'L',    "5-10",
+                {ISMEAN, ISREGEN, CANSUMMON, NOBOLT},
+                "bat", 5,
+                6,
+                {12,    12,     5,      45,     4,      2,      HPT("3d8"),
+                "1d6"}},
+{"zoo spore",
+                0,      TRUE,   TRUE,   'z',    "8-20",
+                {ISMEAN, CANDISEASE, CANEXPLODE, TURNABLE, ISUNDEAD, ISFLY},
+                "", 0,
+                10,
+                {20,    20,     4,      80,     2,      0,      HPT("2d8+6"),
+                "1d8"}},
+{"bugbear",
+                30,     TRUE,   TRUE,   'b',    "5-12",
+                {ISMEAN, CANSHOOT, CANSURPRISE, ISGREED},
+                "", 0,
+                3,
+                {16,    10,     6,      60,     2,      5,      HPT("3d8+4"),
+                "2d4"}},
+{"gray ooze", 
+                0,      TRUE,   TRUE,  'o',    "1",
+                {ISMEAN, CANRUST, NOCOLD, NOFIRE, NOSTAB},
+                "", 0,
+                1,
+                {10,    10,     9,     100,    2,      8,      HPT("1d8"),
+                "1d8"}},
+{"lonchu",
+                50,     TRUE,   TRUE,   'l',    "6",
+                {ISMEAN, CANTELEPORT, CARRYARMOR, NOBOLT},
+                "", 0,
+                3,
+                {10,    10,     6,      120,    2,      3,      HPT("3d8+4"),
+                "2d6"}},
+{"wererat",
+                50,     TRUE,   TRUE,   'r',    "10-15",
+                {ISMEAN, CARRYPOTION, CANSUMMON, CANDRAW, NOSTAB},
+                "giant rat", 3,
+                5,
+                {10,    10,     5,      70,     5,      4,      HPT("3d8+6"),
+                "2d8"}},
+{"ghoul",
+                50,     TRUE,   TRUE,  'g',    "12-15",
+                {ISMEAN, CARRYFOOD, CANPARALYZE, ISUNDEAD, TURNABLE, CANDRAW,
+                 AREMANY},
+                "", 0,
+                7,
+                {12,    12,     5,      75,     2,      2,      HPT("4d4"),
+                "1d4/1d6"}},
+{"leprechaun",
+                75,     TRUE,   FALSE,  'l',    "10-16",
+                {CARRYGOLD, STEALGOLD, ISGREED, CARRYSCROLL, CARRYPOTION,
+                 NOSTAB},
+                "", 0,
+                9,
+                {15,    15,     3,      100,     7,      0,      HPT("3d8"),
+                "1d1/3d6"}},
+{"junk monster", 
+                100,    TRUE,   TRUE,   'j',    "10-14",
+                {ISMEAN, CANSTINK, CANSMELL, ISSCAVENGE, ISGREED, CANDRAW,
+                 ISREGEN, CANSHOOT, CARRYSTICK},
+                "", 0,
+                7,
+                {12,    12,     5,      100,    2,      4,      HPT("3d8+3"),
+                "1d6/2d8"}},
+{"jacaranda",
+                40,     TRUE,   TRUE,   'j',     "8-18",
+                {ISMEAN, ISUNIQUE, ISREGEN, CANSUMMON, NOCOLD, NOFIRE, NOBOLT,
+                 CANDANCE, CARRYGOLD, CANTELEPORT, CANBLIND, ISSHADOW, NOSTAB,
+                 ISGREED, STEALGOLD, CARRYFOOD},
+                "zombie", 4,
+                20,
+                {18,    18,     2,      40000,   10,    -15,    HPT("6d8+40"),
+                "1d6/2d6/3d6"}},
+{"gnoll",
+                0,      TRUE,   TRUE,   'n',    "10-16",
+                {ISMEAN, CANINFEST, CANROT, ISREGEN, TURNABLE},
+                "", 0,
+        4,
+                {10,    10,     6,      140,    2,      4,      HPT("6d8"),
+                "2d8"}},
+{"fire toad", 
+                0,      TRUE,   TRUE,   'f',    "5-7",
+                {ISMEAN, CANBFIRE, NOFIRE, NOBOLT},
+                "", 0,
+                4,
+                {10,    10,     6,      200,    2,      5,      HPT("5d8"),
+                "1d8"}},
+{"gelatinous cube", 
+                50,     TRUE,   TRUE,   'c',    "0",
+                {ISMEAN, CANPARALYZE, CARRYFOOD, NOCOLD},
+                "", 0,
+                4,
+                {10,    10,     7,      160,    2,      1,      HPT("4d8"),
+                "2d8"}},
+{"moon dog",
+                0,      TRUE,   TRUE,  'm',    "10-12",
+                {ISMEAN, ISFLY, NOCOLD, NOFIRE, CANDRAW},
+                "", 0,
+                6,
+                {12,    12,     4,     250,    2,      3,      HPT("3d8+3"),
+                "2d10"}},
+{"violet fungi", 
+                0,      TRUE,   TRUE,   'F',    "0",
+                {ISMEAN, CANSHRIEK, CANSUMMON, CANHOLD, NOMOVE, CANROT},
+                "violet fungi", 1,
+                5,
+                {10,    10,     5,      150,    9,      0,      HPT("4d6+10"),
+                "1d8/2d8/3d8"}},
+{"ogre",
+                50,     TRUE,   TRUE,   'O',    "7-12",
+                {ISMEAN, CARRYGOLD, CARRYDAGGER, NOBOLT},
+                "", 0,
+                7,
+                {18,    10,     6,      170,    3,      3,      HPT("4d8+8"),
+                "2d10"}},
+{"centaur",
+                50,     TRUE,   FALSE,  'C',    "5-15",
+                {STEALGOLD, CARRYGOLD, CARRYRING, NOSLEEP, NOSTAB},
+                "", 0,
+                9,
+                {10,    10,     4,      180,    2,      4,      HPT("4d8+10"),
+                "1d8/2d6"}},
+{"nymph",
+                75,     TRUE,   FALSE,  'N',    "10-16",
+                {STEALMAGIC, CARRYSCROLL, CARRYPOTION, CARRYSTICK, NOSTAB,
+                 CARRYFOOD, NOSLOW},
+                "", 0,
+                8,
+                {16,    16,     3,      190,    5,      3,      HPT("3d8+10"),
+                "1d1"}},
+{"blindheim",
+                0,      TRUE,   TRUE,   'b',    "10",
+                {ISMEAN, CANBLIND, NOSLOW},
+                "", 0,
+                5,
+                {8,     8,      5,      260,    3,      1,      HPT("4d8+6"),
+                "2d10"}},
+{"blink dog",
+                0,      TRUE,   TRUE,   'B',    "8-10",
+                {ISMEAN, CANBLINK, CANSEE, CANINFEST},
+                "", 0,
+                9,
+                {10,    10,     6,      220,    3,      5,      HPT("4d8+4"),
+                "1d8/2d4"}},
+{"ghast",
+                50,     TRUE,   TRUE,   'G',    "10-12",
+                {ISMEAN, CANPARALYZE, CANSTINK, ISUNDEAD, TURNABLE, AREMANY,
+                 NOBOLT},
+                "", 0,
+                10,
+                {10,    10,     4,      250,    1,      1,      HPT("5d8+6"),
+                "2d4/2d6"}},
+{"rust monster", 
+                0,      TRUE,   TRUE,   'R',    "1",
+                {ISMEAN, CANRUST, CANDISEASE},
+                "", 0,
+                6,
+                {10,    10,     7,      200,    4,      6,      HPT("2d8+6"),
+                "1d1/1d1"}},
+{"imp", 
+                0,      TRUE,   TRUE,   'I',    "8-10",
+                {ISMEAN, ISREGEN, CANPAIN, CANTELEPORT, NOCOLD, NOFIRE},
+                "", 0,
+                9,
+                {10,    10,     6,      300,    3,      2,      HPT("3d8+12"),
+                "2d8"}},
+{"doppelganger", 
+                50,     TRUE,   TRUE,   'D',    "10-15",
+                {ISMEAN, CANSURPRISE, CARRYPOTION, NOSTAB, NOSLOW},
+                "", 0,
+                8,
+                {10,    10,     5,      360,    5,      3,      HPT("7d8"),
+                "1d12+2"}},
+{"shadow",
+                0,      TRUE,   TRUE,   'S',    "13",
+                {ISMEAN, ISSHADOW, CANCHILL, ISUNDEAD, TURNABLE, CANINWALL},
+                "", 0,
+                9,
+                {13,    13,     5,      370,    6,      1,      HPT("3d8+10"),
+                "2d4/2d4"}},
+{"very young dragon", 
+                50,     TRUE,   TRUE,   'd',    "12-16",
+                {ISMEAN, MAGICHIT, ISGREED, CARRYPOTION, CARRYGOLD, NOSTAB,
+                 CANBRANDOM, CARRYMISC, NOBOLT},
+                "", 0,
+                11,
+                {16,    16,     6,      300,    8,      -2,     HPT("4d8+20"),
+                "2d4/1d6/1d8"}},
+{"yeti",        
+                0,      TRUE,   TRUE,   'Y',    "8-16",
+                {ISMEAN, CANPARALYZE, CANSURPRISE, NOBOLT, NOSTAB, NOCOLD},
+                "", 0,
+                9,
+                {13,    10,     5,      400,    3,      6,      HPT("5d8+6"),
+                "1d8/2d8"}},
+{"ice weasel",
+                0,      TRUE,   TRUE,   'i',    "10-16",
+                {ISMEAN, AREMANY, ISSHADOW, CANPAIN, NOCOLD, NOSLEEP},
+                "", 0,
+                7,
+                {10,    10,     4,      400,   6,      1,      HPT("10d8+10"),
+                "1d10"}},
+{"mimic",
+                50,     TRUE,   TRUE,  'M',    "2-16",
+                {ISMEAN, ISDISGUISE, NODETECT, CANHOLD, NOMOVE, NOSTAB, NOBOLT,
+                 CARRYRING},
+                "", 0,
+                12,
+                {10,    10,     6,      500,    4,      8,      HPT("10d8"),
+                "3d4"}},
+{"owlbear",
+                50,     TRUE,   TRUE,   'O',    "8-12",
+                {ISMEAN, CANHUG, NOFEAR, NOSTAB, CARRYFOOD},
+                "", 0,
+                10,
+                {10,    10,     3,      340,    3,      2,      HPT("5d8+10"),
+                "1d6/1d6/2d6"}},
+{"otyugh",
+                50,     TRUE,   TRUE,   'o',    "5-10",
+                {ISMEAN, ISFLY, CARRYARMOR, NOSLOW, NOFIRE},
+                "", 0,
+                11,
+                {10,    10,     5,      750,   4,      4,      HPT("4d8+15"),
+                "1d8/1d8/1d4+4"}},
+{"gargoyle",
+                50,     TRUE,   TRUE,   'g',    "5-7",
+                {ISMEAN, MAGICHIT, CARRYWEAPON, NOSTAB},
+                "", 0,
+                9,
+                {10,    10,     4,      290,    3,      5,      HPT("4d8+6"),
+                "1d6/2d6"}},
+{"su-monster",
+                50,     TRUE,   TRUE,   's',    "8-10",
+                {ISMEAN, CARRYGOLD, ISGREED, HASFIRE, CANSUMMON, CARRYSCROLL,
+                 NOFEAR},
+                "moon dog", 4,
+                12,
+                {10,    10,     5,      450,    4,      3,      HPT("5d8+10"),
+                "2d4/2d4"}},
+{"leucrotta", 
+                0,      TRUE,   TRUE,   'L',    "8-10",
+                {ISMEAN, NOFEAR, NOSLOW, NOSTAB, CANSEE},
+                "", 0,
+                10,      
+                {10,    10,     2,      470,    3,      4,      HPT("6d8+10"),
+                "3d6/1d6/1d6"}},
+{"cockatrice", 
+                50,      TRUE,   TRUE,   'C',    "1",
+                {ISMEAN, CARRYSTICK, TOUCHSTONE, NOSTAB},
+                "", 0,
+                15,
+                {12,    12,     5,      500,    6,      4,      HPT("5d8+8"),
+                "4d4"}},
+{"wight",
+                0,      TRUE,   TRUE,   'W',    "8-10",
+                {ISMEAN, CANDRAIN, MAGICHIT, NOSTONE, ISUNDEAD, TURNABLE,
+                 NOBOLT},
+                "", 0,
+                12,
+                {10,    10,     6,    550,    4,      2,      HPT("4d8+15"),
+                "2d8"}},
+{"phibian",
+                0,      TRUE,   TRUE,   'p',    "2-16",
+                {ISMEAN, NOBOLT, CANFRIGHTEN, TURNABLE, NOSLOW},
+                "", 0,
+                13,
+                {10,    10,     2,     600,   8,      -2,     HPT("6d8"),
+                "1d20"}},
+{"fireworm",
+                0,      TRUE,   TRUE,  'z',    "7-10",
+                {ISMEAN, AREMANY, CANEXPLODE, NOFIRE, ISFLY, NOSLEEP},
+                "", 0,
+                15,
+                {10,    10,     5,     500,    2,      0,      HPT("1d8"),
+                "1d4"}},
+{"flumph",
+                50,      TRUE,   TRUE,   'f',    "10-16",
+                {ISMEAN, AREMANY, CARRYGOLD, STEALGOLD, NOMOVE},
+                "", 0,
+                13,
+                {12,    12,     3,      320,    3,      -7,      HPT("5d8+8"),
+                "2d8"}},
+{"treant",
+                50,     TRUE,   TRUE,  't',    "10-14",
+                {ISMEAN, CANSUMMON, CARRYGOLD, ISGREED, CANSTINK, CANSMELL},
+                "treant", 1,
+                16,
+                {12,    12,     4,      1500,   2,      0,      HPT("5d8+10"),
+                "3d8"}},
+{"troll",
+                50,     TRUE,   FALSE,  'T',    "10-15",
+                {ISREGEN, CANSHOOT, CARRYGOLD, CARRYSCROLL, NOSTAB},
+                "", 0,
+                18,
+                {18,    18,     6,      600,    7,      3,      HPT("6d8+10"),
+                "1d4+4/1d4+4/2d6+2"}},
+{"ettin",
+                50,     TRUE,   TRUE,   'e',    "1-18",
+                {ISMEAN, AREMANY, CARRYWEAPON, NOFIRE, CANROT},
+                "", 0,
+                10,
+                {10,    10,     3,      1000,   3,      1,      HPT("8d8+8"),
+                "2d8/2d6/2d6"}},
+{"lava child", 
+                0,      TRUE,   TRUE,   'l',    "8-10",
+                {ISMEAN, NOMETAL, NOFIRE, NOBOLT, NOSTAB},
+                "", 0,
+                9,      
+                {10,    10,     5,      700,    2,      4,      HPT("5d8+10"),
+                "2d12"}},
+{"erinyes",
+                0,      TRUE,   TRUE,   'E',    "8-10",
+                {ISMEAN, CANFRIGHTEN, TURNABLE, ISUNDEAD, CANPAIN, NOFIRE},
+                "", 0, 
+                11,
+                {10,    10,     6,      750,    4,      3,      HPT("6d8+4"),
+                "6d2+4"}},
+{"ulodyte",
+                0,      TRUE,   TRUE,   'u',    "9-13",
+                {ISMEAN, CANSMELL, CANHUG, TURNABLE, NOSTAB, CANSURPRISE},
+                "", 0,
+                12,
+                {10,    8,      6,      2000,   5,      3,      HPT("6d8+10"),
+                "3d4/2d6"}},
+{"wraith",
+                0,      TRUE,   TRUE,   'w',    "10-14",
+                {ISMEAN, CANDRAIN, MAGICHIT, ISUNDEAD, TURNABLE, NOBOLT,
+                 NOSTAB, AREMANY},
+                "", 0,
+                16,
+                {10,    10,     8,      800,    3,      2,      HPT("5d8+10"),
+                "2d6/1d8"}},
+{"jackalwere", 
+                50,     TRUE,   TRUE,   'J',    "10-15",
+                {ISMEAN, CANSMELL, CANSNORE, MAGICHIT},
+                "", 0,
+                10,
+                {10,    10,     4,      900,    6,      3,      HPT("5d8+20"),
+                "2d4/2d4"}},
+{"basilisk",
+                50,     TRUE,   TRUE,  'B',    "1",
+                {ISMEAN, LOOKSTONE, CARRYSCROLL, NOSTAB, NOFIRE},
+                "", 0,
+                10,
+                {10,    10,     6,      1000,   5,      4,      HPT("6d8+20"),
+                "2d10"}},
+{"vrock",
+                0,      TRUE,   TRUE,   'v',    "10-12",
+                {ISMEAN, CANSEE, TURNABLE, CANTELEPORT, CANDRAW},
+                "", 0, 
+                12,
+                {10,    10,     6,      2300,   5,      1,      HPT("7d8+25"),
+                "1d4/1d4/1d8/1d8/1d6/1d6"}},
+{"hezrou",
+                50,     TRUE,   TRUE,   'h',    "5-13",
+                {ISMEAN, CANFRIGHTEN, TURNABLE, CANTELEPORT, CARRYSTICK},
+                "", 0, 
+                12,
+                {10,    10,     6,      3000,   6,      -1,     HPT("9d8+10"),
+                "1d4/2d4/4d4"}},
+{"glabrezu",
+                50,     TRUE,   TRUE,   'G',    "8-10",
+                {ISMEAN, CANFRIGHTEN, CANSEE, TURNABLE, CANTELEPORT,
+                 CARRYWEAPON, CARRYPOTION},
+                "", 0, 
+                12,
+                {10,    10,     6,      2500,   6,      -4,     HPT("10d8+6"),
+                "2d6/2d6/1d6/1d6"}},
+{"wyvern",
+                50,     TRUE,   TRUE,   'w',    "10-16",
+                {ISMEAN, CANPAIN, CARRYGOLD, CANSUMMON, CANINFEST, NODETECT},
+                "fireworm", 4,
+                15,
+                {10,    10,     5,      2200,   4,      -2,      HPT("8d8+10"),
+                "2d8/2d8"}},
+{"specter",
+                0,      TRUE,   TRUE,   'S',    "10-16",
+                {ISMEAN, DOUBLEDRAIN, ISUNDEAD, TURNABLE, NOFIRE, NOCOLD,
+                NOSTAB, NOACID, NOGAS},
+                "", 0,
+                17,
+                {12,    12,     6,      2000,   7,      1,      HPT("7d8+20"),
+                "1d8/1d8"}},
+{"mummy",
+                0,      TRUE,   TRUE,   'm',    "5-14",
+                {ISMEAN, CANROT, MAGICHIT, CANFRIGHTEN, HALFDAMAGE, ISUNDEAD,
+                 NOGAS, NOACID, NOSTAB, TURNABLE},
+                "", 0,
+                18,
+                {10,    10,     5,      2000,   5,      2,      HPT("8d8+10"),
+                "1d12"}},
+{"chimera",
+                0,      TRUE,   TRUE,   'c',    "10-16",
+                {ISMEAN, BMAGICHIT, NOFEAR, NOCOLD, ISREGEN, CANITCH},
+                "", 0,
+                19,
+                {10,    10,     6,      2300,   5,      0,      HPT("6d8+25"),
+                "1d3/1d3/1d4/1d4/2d4/2d4"}},
+{"neo-otyugh",
+                50,      TRUE,   TRUE,   'N',    "10-12",
+                {ISMEAN, CARRYPOTION, CANINFEST, NOCOLD, NOFEAR, MAGICHIT},
+                "", 0,
+                17,
+                {12,    10,     6,      2500,   6,      0,      HPT("12d8"),
+                "2d8/2d6/1d3"}},
+{"adult dragon", 
+                80,     TRUE,   TRUE,   'd',    "12-16",
+                {ISMEAN, CANBRANDOM, ISGREED, CANFRIGHTEN, NOSTAB, NOCOLD,
+                 CARRYPOTION, CARRYMISC, CARRYRING, CANSURPRISE},
+                "", 0,
+                20,
+                {18,    18,     5,      2600,   7,      -3,     HPT("7d8+20"),
+                "2d6/2d6/2d6"}},
+{"horned devil", 
+                0,      TRUE,   TRUE,   'H',    "10-14",
+                {ISMEAN, CANPOISON, NOBOLT, CANTELEPORT},
+                "", 0, 
+                17,
+                {10,    10,     6,      2200,   5,      -2,     HPT("5d8+30"),
+                "1d4/1d6/1d8"}},
+{"barbed devil", 
+                0,      TRUE,   TRUE,   'B',    "10-16",
+                {ISMEAN, TOUCHFEAR, NOBOLT, CANHOLD, TURNABLE, NOFIRE},
+                "", 0,
+                17,
+                {10,    10,     6,      2200,   5,      0,      HPT("8d8+20"),
+                "2d4/2d4/3d4"}},
+{"ice devil",
+                0,      TRUE,   TRUE,   'I',    "12-15",
+                {ISMEAN, ISREGEN, CANBICE, NOCOLD, NOBOLT},
+                "", 0,
+                17,
+                {12,    10,     6,      2500,   6,      -4,     HPT("10d8+10"),
+                "1d4/2d4/3d4"}},
+{"bone devil",
+                0,      TRUE,   TRUE,   'b',    "12-15",
+                {ISMEAN, CANSURPRISE, CANCHILL, CANSEE, NOFIRE, NOACID,
+                 NOGAS, CANFRIGHTEN, NOSTAB, NOCOLD, CANTELEPORT},
+                "", 0, 
+                17,
+                {12,    12,     5,      3500,   8,      -1,     HPT("10d8+20"),
+                "2d4/3d6"}},
+{"rhinosphynx",
+                80,     TRUE,   TRUE,   'r',    "13-18",
+                {ISMEAN, CANPOISON, CANSURPRISE, CANCHILL, NOCOLD, CARRYGOLD,
+                 ISGREED},
+                "", 0, 
+                18,
+                {12,    12,     6,      3000,   7,      -1,     HPT("9d8+10"),
+                "4d6"}},
+{"lamia", 
+                80,     TRUE,   TRUE,   'L',    "10-17",
+                {ISMEAN, TAKEWISDOM, CARRYSTICK, NOFEAR, NOCOLD},
+                "", 0,
+                16,     
+                {16,    16,     3,      2500,   7,      -2,     HPT("9d8+15"),
+                "2d4/2d6"}},
+{"intellect devourer",
+                0,      TRUE,   TRUE,   'D',    "12-16",
+                {ISMEAN, TAKEINTEL, BMAGICHIT, CANSURPRISE, NOBOLT, NOSTAB},
+                "", 0,
+                16,
+                {16,    16,     3,      2500,   9,      -2,     HPT("10d8+15"), 
+                "1d6/2d6/3d6"}},
+{"quasit",
+                80,     TRUE,   TRUE,   'Q',    "10-15",
+                {ISMEAN, ISREGEN, BMAGICHIT, CANSURPRISE, CANITCH, NOGAS,
+                 NOACID, CARRYSCROLL, CARRYPOTION, NOCOLD, NOBOLT},
+                "", 0,
+                20,
+                {10,    10,     6,      3000,   6,      -2,     HPT("6d8+20"),
+                "2d6/1d8/2d6"}},
+{"will-o-wisp",
+                80,     TRUE,   TRUE,   'W',    "12-16",
+                {ISMEAN, CANSURPRISE, ISFLY, CARRYMISC, NOSTAB, NOBOLT},
+                "", 0,
+                20,
+                {10,    10,     5,      4000,   6,      -5,     HPT("9d8+20"),
+                "2d14"}},
+{"invisible stalker", 
+                0,      TRUE,   TRUE,   'i',    "12-16",
+                {ISMEAN, ISINVIS, ISSHADOW, NOBOLT, CANINWALL, NOGAS, NOSTAB,
+                 NOACID, TOUCHFEAR},
+                "", 0,
+                20,
+                {10,    10,     4,      3800,   5,      -2,     HPT("8d8+20"),
+                "2d12"}},
+{"hellmaid",
+                80,     TRUE,   TRUE,  'h',    "10-20",
+                {ISMEAN, AREMANY, CANBRANDOM, CARRYFOOD, NOBOLT, NOGAS,
+                 NOACID, NOCOLD, NOFIRE},
+                "", 0,
+                20,
+                {12,   12,     7,      4000,   4,      1,      HPT("8d8+12"),
+                "2d8/2d8"}},
+{"shadow dragon",
+                80,      TRUE,   TRUE,   'S',    "16-20",
+                {ISMEAN, TURNABLE, CANDRAW, NOSTAB, HASFIRE, CANSMELL,
+                 CARRYGOLD, STEALGOLD, ISINVIS, ISSHADOW, NOSLOW},
+                "", 0,
+                25,
+                {10,    10,     2,      4800,   3,      -7,     HPT("8d8+18"),
+                "3d4/2d8"}},
+{"umber hulk",
+                80,     TRUE,   TRUE,   'U',    "8-16",
+                {ISMEAN, CANHUH, CANINWALL, CANTUNNEL, CARRYSCROLL, NOSTAB,
+                 NOACID, NOGAS, BMAGICHIT, NOBOLT},
+                "", 0,
+                22,
+                {14,    14,     5,      5000,   8,      -3,     HPT("10d8+20"),
+                "3d4/3d4/3d4"}},
+{"xorn",
+                0,      TRUE,   TRUE,   'X',    "8-18",
+                {ISMEAN, CANINWALL, NOFIRE, CANSURPRISE, NOBOLT, NOSTAB, NOGAS,
+                 NOACID},
+                "", 0,
+                23,
+                {13,    13,     4,      5000,   8,      -4,     HPT("7d8+25"),
+                "2d6/4d6"}},
+{"xenolith", 
+                80,     TRUE,   TRUE,   'x',    "12-18",
+                {ISMEAN, NOSTAB, NOFIRE, NOBOLT, NOCOLD, CANTELEPORT,
+                 STEALGOLD, CARRYGOLD, ISGREED},
+                "", 0,
+                24,
+                {12,    12,     4,      3500,   6,      -2,     HPT("9d8+20"),
+                "2d8/2d10"}},
+{"shambling mound", 
+                80,    TRUE,   TRUE,   's',    "5-7",
+                {ISMEAN, CANSUFFOCATE, NOCOLD, CANHOLD, CARRYGOLD, CANSUMMON,
+                 NOGAS, NOSTAB, NOACID, CARRYPOTION, CARRYSCROLL, ISSCAVENGE},
+                "mummy", 3,
+                20,
+                {10,    10,     5,      4500,   5,      0,      HPT("9d8+15"),
+                "2d8/2d10"}},
+{"black pudding", 
+                80,     TRUE,   TRUE,  'P',    "0",
+                {ISMEAN, CANRUST, NOCOLD, BOLTDIVIDE, BLOWDIVIDE, ISSCAVENGE, 
+                 NOSTAB, NOGAS, CARRYRING},
+                "", 0,
+                20,
+                {10,    10,     6,      4500,   6,      5,      HPT("10d8+10"),
+                "3d8"}},
+{"vampire",
+                0,      TRUE,   TRUE,   'V',    "5-16",
+                {ISMEAN, ISREGEN, CANSUCK, CANDRAW, CANDRAIN, ISUNDEAD,
+                 NOACID, TURNABLE, TOUCHFEAR, NOGAS, NOSTAB, NOBOLT},
+                "", 0,
+                23,
+                {16,    16,     5,      5000,   7,      -4,     HPT("8d8+25"),
+                "2d6+6"}},
+{"morkoth",
+                80,     TRUE,   TRUE,  'm',    "10-18",
+                {ISMEAN, ISSHADOW, CANSEE, HALFDAMAGE, CARRYARMOR, NOGAS,
+         CANSUMMON, NOMETAL},
+                "wyvern", 2,
+                21,
+                {11,    11,     8,      7000,   6,      -1,     HPT("12d8+10"),
+                "4d8/4d8"}},
+{"white pudding", 
+                80,     TRUE,   TRUE,  'w',    "0",
+                {ISMEAN, CANDISSOLVE, NOFIRE, BOLTDIVIDE, BLOWDIVIDE, NOGAS,
+                 ISSCAVENGE, NOSTAB, CARRYMISC},
+                "", 0,
+                20,
+                {10,    10,     4,      8000,   8,      5,      HPT("10d8+10"),
+                "4d8"}},
+{"purple worm", 
+                0,      TRUE,   TRUE,   'p',    "10",
+                {ISMEAN, CANPOISON, CANINWALL, CANTUNNEL, NOSTAB, NOFEAR,
+                 NOBOLT, NOACID, CMAGICHIT, NOGAS},
+                "", 0,
+                25,
+                {10,    10,     5,      9000,   8,      -3,     HPT("12d8+20"),
+                "2d12/2d8+4"}},
+{"pit fiend",
+                80,     TRUE,   TRUE,   'f',    "12-18",
+                {ISMEAN, CANSEE, BMAGICHIT, CANFRIGHTEN, CANHOLD, HASFIRE,
+                 CARRYRING, CARRYSTICK, NOACID, NOGAS, NOSTAB},
+                "", 0,
+                26,
+                {16,    16,     5,      10000,  6,      -2,     HPT("12d8+25"),
+                "2d6+4/2d6+8"}},
+{"ghost",       
+                0,      TRUE,   TRUE,   'g',    "14-16",
+                {ISMEAN, CANFRIGHTEN, CANAGE, ISUNDEAD, TURNABLE, BMAGICHIT,
+                 NOGAS, NOACID, CANINWALL, CANSUMMON, NOSTAB, ISREGEN},
+                "invisible stalker", 3,
+                28,
+                {13,    13,     5,      9500,   5,      -4,     HPT("10d8+25"),
+                "2d10/2d4"}},
+{"ancient black dragon", 
+                80,     TRUE,   TRUE,   'a',    "12-16",
+                {ISMEAN, CANBACID, NOSTAB, NOACID, ISGREED, CARRYGOLD, NOSLEEP,
+                 CANMISSILE, CANTELEPORT, NOBOLT, NOCOLD, NOGAS, NOFIRE},
+                "", 0,
+                30,
+                {14,    14,     6,      11000,  7,      -4,     HPT("10d8+50"),
+                "2d6/3d4/4d6"}},
+{"ancient blue dragon", 
+                80,     TRUE,   TRUE,   'u',    "12-16",
+                {ISMEAN, CANBBOLT, CANSEE, NOBOLT, CARRYMISC, NOSTAB, CANBPGAS,
+                 NOACID, NOGAS, NOFIRE, NOCOLD, CANTELEPORT, NOFIRE, NOSLEEP},
+                "", 0,
+                30,
+                {14,    14,     4,      11000,  7,      -6,     HPT("10d8+50"),
+                "4d4/4d6/4d8"}},
+{"ancient red dragon", 
+                80,     TRUE,   TRUE,   'R',    "12-16",
+                {ISMEAN, CANMISSILE, CANSEE, NOFIRE, CARRYRING, NOGAS, NOBOLT,
+                 NOSTAB, CANBFIRE, NOFEAR, NOCOLD, NOFIRE, NOACID, CANTELEPORT},
+                "", 0,
+                30,
+                {14,    14,     6,      11000,  7,      -8,     HPT("10d8+50"),
+                "4d6/3d8/5d8"}},
+{"ancient brass dragon", 
+                80,     TRUE,   FALSE,  'r',    "12-16",
+                {CANBFGAS, CANSEE, NOSLEEP, CANBSGAS, NOGAS, NOSTAB,
+                 CANTELEPORT, NOACID, NOFIRE, CARRYSTICK, NOBOLT, NOCOLD},
+                "", 0,
+                30,
+                {14,    14,     6,      11000,  7,      -4,     HPT("10d8+50"),
+                "2d6/3d4/4d6"}},
+{"frost giant",
+                80,     TRUE,   TRUE,   'F',    "5-16",
+                {ISMEAN, NOCOLD, CARRYGOLD, AREMANY, CANBICE, NOGAS, CANCHILL,
+                 CANSMELL, NOCOLD, NOACID, ISGREED},
+                "", 0,
+                35,
+                {18,    18,     4,      12000,  8,      0,      HPT("8d8+30"),
+                "6d8"}},
+{"lich",
+                80,     TRUE,   TRUE,   'l',    "12-18",
+                {ISMEAN, CANSEE, CANPARALYZE, CANFRIGHTEN, CMAGICHIT, NOSTAB,
+                 NOBOLT, CANMISSILE, CARRYGOLD, CARRYSCROLL, CARRYPOTION,
+         CARRYRING, NOCOLD, NOFIRE, NOACID, NOGAS},
+                "", 0,
+                35,
+                {12,    12,     4,      14000,  8,      -5,     HPT("10d8+60"),
+                "2d10/3d8"}},
+{"ancient green dragon", 
+                80,     TRUE,   TRUE,   'E',    "12-16",
+                {ISMEAN,CANBGAS, ISGREED, CANSEE, CARRYGOLD, NOSTAB, NOGAS,
+                 NOACID, CANMISSILE, NOBOLT, NOSLEEP, CANTELEPORT, NOFIRE},
+                "", 0,
+                40,
+                {16,    16,     6,      16000,  8,      -6,     HPT("10d8+60"),
+                "4d4/4d6/4d8"}},
+{"ancient white dragon", 
+                80,     TRUE,   TRUE,   'W',    "12-16",
+                {ISMEAN, CANSEE, NOGAS, NOSTAB, CARRYSCROLL, CANTELEPORT,
+                 NOACID, NOFIRE, CANBICE, CANMISSILE, NOBOLT, NOCOLD, NOSLEEP},
+                "", 0,
+                40,
+                {16,    16,     4,      16000,  8,      -4,     HPT("10d8+60"),
+                "2d6/3d4/4d6"}},
+{"ancient bronze dragon", 
+                80,     TRUE,   FALSE,  'L',    "12-16",
+                {CANBBOLT, CANSEE, NOBOLT, NOSTAB, CANBCGAS, NOFIRE,
+                 CARRYSCROLL, CARRYSTICK, NOCOLD, NOSLEEP, NOGAS, NOACID},
+                "", 0,
+                40,
+                {16,    16,     8,      16000,  8,      -6,     HPT("10d8+60"),
+                "4d4/4d6/4d8"}},
+{"ancient copper dragon", 
+                80,     TRUE,   FALSE,  'c',    "12-16",
+                {NOACID, CANBSLGAS, CANSEE, NOFIRE, NOBOLT, NOSLEEP, NOCOLD,
+                 CARRYMISC, CARRYPOTION, CANTELEPORT, NOSTAB, CANBACID, NOGAS},
+                "", 0,
+                40,
+                {16,    16,     5,      16000,  8,      -6,     HPT("10d8+60"),
+                "4d4/4d6/4d8"}},
+{"fire giant",
+                80,      TRUE,   TRUE,   'f',    "15-18",
+                {ISMEAN, AREMANY, CARRYGOLD, ISGREED, NOSLOW, NOGAS, NOBOLT,
+                 NOFIRE, CANSTINK, NOACID},
+                "", 0,
+                45,
+                {15,    15,     3,      15000,  9,      -1,     HPT("8d8+30"),
+                "8d6"}},
+{"nemesis", 
+                80,     TRUE,   TRUE,   'n',    "10-18",
+                {ISMEAN, ISGREED, CANSEE, NOBOLT, STEALGOLD, CMAGICHIT, NOGAS,
+                 NODETECT, CARRYFOOD, CANBLINK, NOCOLD},
+                "", 0,
+                45,
+                {13,    13,     6,      18000,  9,      -7,     HPT("10d8+70"),
+                "3d6/3d8/3d10"}},
+{"ancient amethyst dragon", 
+                80,     TRUE,   TRUE,   'y',    "12-16",
+                {ISMEAN, CANSTINK, CANMISSILE, ISGREED, NOBOLT, NOGAS, NOSLEEP,
+                 NOFIRE, NOCOLD, CARRYSCROLL, CANTELEPORT, NOSTAB, NOACID},
+                "", 0,
+                50,
+                {18,    18,     4,      20000,  9,      -8,     HPT("10d8+70"),
+                "4d6/3d8/5d8"}},
+{"ancient silver dragon", 
+                80,     TRUE,   FALSE,  'S',    "12-16",
+                {CANBPGAS, NOSLEEP, CANBICE, NOCOLD, NOPARALYZE, NOGAS,
+                 NOFIRE, NOACID, CARRYSTICK, NOSTAB, CANTELEPORT},
+                "", 0,
+                50,
+                {18,    18,     8,      20000,  9,      -8,     HPT("10d8+70"),
+                "4d6/3d8/5d8"}},
+{"ancient saphire dragon", 
+                80,     TRUE,   TRUE,   'H',    "12-16",
+                {ISMEAN, NOBOLT, CANSEE, CARRYRING, NOSTAB, NOACID, CANSONIC,
+                 CANTELEPORT, NOFIRE, NOCOLD, NOGAS, NOSLEEP},
+                "", 0,
+                50,
+                {18,    18,     6,      20000,  9,      -6,     HPT("10d8+20"),
+                "2d6/3d4/4d6"}},
+{"ancient gold dragon", 
+                80,     TRUE,   FALSE,  'G',    "12-16",
+                {CANBGAS, ISGREED, NOACID, NOFIRE, NOGAS, CARRYGOLD,
+                 CANBFIRE, CANTELEPORT, NOBOLT, NOSTAB, NOCOLD, NOSLEEP},
+                "", 0,
+                50,
+                {18,    18,     5,      20000,  9,      -8,     HPT("10d8+70"),
+                "4d6/3d8/5d8"}},
+{"titan",
+                80,     TRUE,   TRUE,   't',    "13-18",
+                {ISMEAN, ISSHADOW, CANSEE, CARRYPOTION, NOSTAB, CANTELEPORT,
+                 TOUCHFEAR, CANROT, NOGAS, NOACID, NOFEAR, NOBOLT},
+                "", 0,
+                55,
+                {16,    16,     5,      22000,  10,     -5,     HPT("8d8+70"),
+                "8d8"}},
+{"storm giant",
+                80,      TRUE,   TRUE,   's',    "10-16",
+                {ISMEAN, NOBOLT, CANBBOLT, CANPAIN, NOGAS, NOSTAB, NOACID,
+                 CARRYGOLD, ISGREED, CANBBOLT, NOBOLT, CANSUMMON},
+                "shadow dragon", 2,
+                55,
+                {14,    14,     6,      20000,  10,     -7,     HPT("10d8+60"),
+                "7d8/5d10"}},
+{"lesser god (Hruggek)",
+                100,     TRUE,   FALSE,  'H',    "20",
+                {ISMEAN, ISUNIQUE, CARRYMSTAR, ISREGEN, MAGICHIT, CANSEE, NOGAS,
+         NOFIRE, NOSTAB, CANMISSILE, CANTELEPORT, NOBOLT, CARRYFOOD},
+                "", 0,
+                60,
+                {18,    18,     5,      40000,  10,     -5,     HPT("10d8+100"),
+                "5d10/5d10"}},
+{"lesser god (Surtur)",
+                100,     TRUE,   FALSE,  'S',    "20",
+                {ISMEAN, ISUNIQUE, CARRYSURTURRING, ISREGEN, MAGICHIT, CANSEE,
+         NOFIRE, NOSTAB, CANMISSILE, CANTELEPORT, NOBOLT, CARRYRING},
+                "", 0,
+                60,
+                {18,    18,     4,      40000,  10,     -5,     HPT("10d8+100"),
+                "5d10/5d10"}},
+{"demon prince (Yeenoghu)",
+                100,     TRUE,   FALSE,   'Y',    "20",
+                {ISMEAN, ISUNIQUE, CARRYFLAIL, CMAGICHIT, CANPOISON, NOBOLT,
+         CANBBOLT, CANTELEPORT, NOFIRE, NOSTAB, NOGAS, CARRYSCROLL,
+         NOCOLD, NOSLOW},
+                "", 0,
+                60,
+                {18,    18,     5,      50000,  11,     -6,     HPT("10d8+100"),
+                "2d8+4/2d6+8"}},
+{"demon prince (Orcus)", 
+                100,     TRUE,   FALSE,   'O',    "20",
+                {ISMEAN, ISUNIQUE, CARRYWAND, CMAGICHIT, CANFRIGHTEN, CANSEE,
+         CANBBOLT, NOBOLT, CANTELEPORT, NOFIRE, CARRYPOTION, NOSTAB},
+                "", 0, 
+                60,
+                {18,    18,     5,      30000,  10,     -6,     HPT("10d8+90"),
+                "2d8+4/2d6+8"}},
+{"arch devil (Geryon)", 
+                100,     TRUE,   FALSE,   'g',    "20",
+                {ISMEAN, ISUNIQUE, CARRYHORN, BMAGICHIT, NOGAS, NOBOLT, NOSTAB,
+         ISINVIS, CANTELEPORT, NOCOLD, NOFIRE, CARRYSTICK, CARRYHORN},
+                "", 0,
+                60,
+                {18,    18,     5,      30000,  10,     -4,     HPT("10d8+90"),
+                "3d6/3d8/3d10"}},
+{"arch devil (Asmodeus)", 
+                100,     TRUE,   FALSE,   'A',    "20",
+                {ISMEAN, ISUNIQUE, CARRYROD, BMAGICHIT, NOGAS, NOBOLT, ISINVIS,
+         NOSTAB, CANFRIGHTEN, CANTELEPORT, NOCOLD, NOFIRE, CARRYMISC},
+                "", 0,
+                60,
+                {20,    20,     5,      40000,  10,     -4,     HPT("10d8+100"),
+                "3d6/3d8/3d10"}},
+{"poet (Brian)",
+                100,     TRUE,   FALSE,   'p',    "20",
+                {ISMEAN, ISUNIQUE, CARRYMANDOLIN, STEALGOLD, ISSHADOW, ISREGEN,
+         NOCOLD, NOBOLT, NOFIRE, NOFEAR, CANTUNNEL, CANSEE, NOSTAB,
+         CANINWALL, ISCLEAR, CARRYPOTION, NOGAS},
+                "", 0,
+                60,
+                {20,    20,     4,      40000,  10,     -8,     HPT("10d8+100"),
+                "4d4+20/4d4+20"}},
+{"witch (Emori)",
+                100,     TRUE,   FALSE,   'w',    "20",
+                {ISMEAN, ISUNIQUE, CARRYCLOAK, CANMISSILE, ISINVIS, CANBBOLT,
+         CANSEE, CANSUMMON, CANSNORE, ISFLY, NOBOLT, NOFIRE, NOSTAB,
+         ISCLEAR, CARRYSTICK, NOSLOW, NOGAS},
+                "nemesis", 4,
+                60,
+                {20,    20,     4,      50000,  11,     -8,     HPT("10d8+100"),
+                "4d4+20/4d4+20"}},
+{"hero (aklad)",
+                100,     TRUE,   FALSE,  'k',    "20",
+                {ISMEAN, ISUNIQUE, CARRYAXE, ISREGEN, NOBOLT, NOSLOW, NOGAS,
+         CANSEE, ISCLEAR, CANBLINK, CARRYMISC, CANMISSILE, NOSTAB},
+                "", 0,
+                60,
+                {20,    20,     5,      50000,  11,     -9,     HPT("10d8+100"),
+                "2d8+15/2d8+15/1d6+15/1d6+15"}},
+{"cleric of thoth (Heil)",
+                100,     TRUE,   FALSE,   'h',    "20",
+                {ISMEAN, ISUNIQUE, CARRYANKH, CARRYRING, CANSEE, NOFEAR,
+         ISREGEN, CANHOLD, NOSTAB, DOUBLEDRAIN, NOCOLD, CANMISSILE,
+         TAKEWISDOM, ISINVIS, NOGAS},
+                "", 0,
+                60,
+                {20,   20,     4,      50000,  11,     -8,     HPT("10d8+100"),
+                "3d6+10"}},
+{"magician/thief (Nagrom)",
+                100,     TRUE,   FALSE,   'N',    "20",
+                {ISMEAN, ISUNIQUE, CARRYQUILL, STEALMAGIC, ISINVIS, ISREGEN,
+         NOSTAB, NOGAS, CANMISSILE, CANSEE, CARRYRING, CANBSTAB, NOBOLT,
+         CANBBOLT, CANSURPRISE, NODETECT, CANTELEPORT, CANSLOW},
+                "", 0,
+                60,
+                {20,    20,     5,      60000,  12,     -8,     HPT("10d8+100"),
+                "7d10/7d10"}},
+{"magician (Tsoming Zen)",
+                100,     TRUE,   FALSE,   'z',    "20",
+                {ISMEAN, ISUNIQUE, CARRYSTAFF, ISINVIS, ISREGEN, CANBFIRE,
+         CANBICE, NOSTAB, CANBBOLT, NOFIRE, NOCOLD, NOBOLT, CANHOLD,
+         NOGAS, CANPAIN, NOSLOW, CARRYPOTION},
+                "", 0,
+                60,
+                {20,   20,     4,      60000,  11,      -5,    HPT("10d8+100"),
+                "2d8+10/2d8+10/2d8+10/2d8+10"}},
+{"dwarven thief (Musty Doit)",
+                100,     TRUE,   FALSE,   'm',    "20",
+                {ISMEAN, ISUNIQUE, CARRYMDAGGER, NOFIRE, NOGAS, NOSTAB,
+         STEALGOLD, STEALMAGIC, CANPAIN, CARRYGOLD, CANSURPRISE,
+         NOBOLT, CARRYPOTION, CARRYSCROLL, ISSCAVENGE},
+                "", 0,
+                60,
+                {20,    20,     5,      70000,  11,     -8,     HPT("10d8+100"),
+                "4d8+10/4d8+10"}},
+{"ruler of titans (Yendor)",
+                100,     TRUE,   FALSE,   'y',     "20",
+                {ISMEAN, ISUNIQUE, CARRYYAMULET, CANINWALL, BMAGICHIT, NOCOLD,
+         CANSUMMON, CANMISSILE, CANFRIGHTEN, NOFIRE, NOGAS, NOSTAB, 
+         TOUCHFEAR, ISSHADOW, NOBOLT, CARRYSTICK, CARRYSCROLL},
+                "titan", 4,
+                60,
+                {20,    20,     5,      70000,  12,     -10,    HPT("10d8+100"),
+                "2d10+5/2d10+5"}},
+{"maker of rock (Stonebones)",
+                100,     TRUE,   FALSE,   'b',    "20",
+                {ISMEAN, ISUNIQUE, CARRYBAMULET, ISREGEN, CMAGICHIT, CANSEE,
+         NOFIRE, NOSTAB, CANFRIGHTEN, CANMISSILE, CANTELEPORT, NOBOLT,
+         CANITCH, NOGAS, CANINWALL, CANSONIC, CARRYSTICK},
+                "", 0,
+                60,
+                {20,    20,     4,      70000,  12,     -10,    HPT("10d8+100"),
+                "6d10/6d10"}},
+{"creator of liches (Vecna)",
+                100,     TRUE,   FALSE,   'V',     "20",
+                {ISMEAN, ISUNIQUE, CARRYEYE, ISREGEN, CMAGICHIT, NOSTAB, NOGAS,
+         CANSNORE, CANSUMMON, CANMISSILE, CANFRIGHTEN, NOFIRE, CANBBOLT,
+         NOBOLT, CANSEE, ISINVIS, HALFDAMAGE, CARRYRING, LOOKSTONE},
+                "lich", 4,
+                60,
+                {20,    20,     4,      70000,  12,     -10,    HPT("10d8+100"),
+                "6d10/6d10"}},
+{"lesser god (Thrym)",
+                0,     TRUE,   TRUE,   'T',    "15-20",
+                {ISMEAN, ISUNIQUE, ISREGEN, MAGICHIT, CANSEE, NOFIRE, NOSTAB,
+                 CANMISSILE, CANTELEPORT, NOBOLT, CANITCH, NOGAS},
+                "", 0,
+                60,
+                {18,    18,     5,      60000,  11,     -5,     HPT("10d8+100"),
+                "5d10/5d10"}},
+{"lesser god (Kurtulmak)",
+                0,     TRUE,   TRUE,  'K',    "15-20",
+                {ISMEAN, ISUNIQUE, ISREGEN, MAGICHIT, CANSEE, NOFIRE, NOSTAB,
+                 CANMISSILE, CANTELEPORT, NOBOLT, NOGAS, CANITCH},
+                "", 0,
+                60,
+                {18,    18,     5,      60000,  10,     -5,     HPT("10d8+100"),
+                "5d10/5d10"}},
+{"lesser god (\"The Destroyer\")",
+                0,     TRUE,   TRUE,   'v',    "15-20",
+                {ISMEAN, ISUNIQUE, ISREGEN, MAGICHIT, CANSEE, NOFIRE, NOSTAB,
+                 CANMISSILE, CANTELEPORT, NOBOLT, CANITCH, NOGAS},
+                "", 0,
+                60,
+                {18,    18,     5,      70000,  12,     -6,     HPT("10d8+100"),
+                "5d10/5d10"}},
+{"lesser god (Antar)", 
+                100,     TRUE,   TRUE,   'A',    "17-25",
+                {ISMEAN, ISUNIQUE, ISREGEN, NOCOLD, NOFIRE, NOBOLT, NOSTAB,
+                 CANDANCE, CANTELEPORT, CANBLIND, CANSEE, ISSHADOW, NOSLOW,
+                 ISGREED, CANSUMMON, CARRYFOOD, CANBRANDOM, CANINWALL, ISFLY},
+                "ancient black dragon", 4,
+                60,
+                {22,    22,     2,      90000,  10,     -15,    HPT("10d8+100"),
+                "6d10/6d10"}},
+{"demon prince (Jubilex)", 
+                0,     TRUE,   TRUE,   'J',    "15-20",
+                {ISMEAN, ISUNIQUE, CMAGICHIT, CANPOISON, CANFRIGHTEN, CANBBOLT,
+                 NOBOLT, CANTELEPORT, NOFIRE, NOSTAB, NOGAS},
+                "", 0, 
+                60,
+                {18,    18,     5,      70000,  11,     -6,     HPT("10d8+100"),
+                "2d8+4/2d6+8"}},
+{"demon prince (Bone)", 
+                0,     TRUE,   TRUE,   'B',    "15-20",
+                {ISMEAN, ISUNIQUE, CMAGICHIT, CANPOISON, CANFRIGHTEN, CANBBOLT,
+                 NOBOLT, CANTELEPORT, NOFIRE, NOSTAB},
+                "", 0, 
+                60,
+                {18,    18,     5,      50000,  10,     -6,     HPT("10d8+90"),
+                "2d8+4/2d6+8"}},
+{"demon prince (Graz'zt)", 
+                0,     TRUE,   TRUE,   'g',    "15-20",
+                {ISMEAN, ISUNIQUE, CMAGICHIT, CANPOISON, CANFRIGHTEN, 
+                 NOBOLT, CANTELEPORT, NOFIRE, NOSTAB, NOGAS},
+                "", 0,
+                60,
+                {18,    18,     3,      60000,  11,     -6,     HPT("10d8+100"),
+                "2d8+4/2d6+8"}},
+{"demon prince (Demogorgon)", 
+                0,     TRUE,   TRUE,  'D',    "15-20",
+                {ISMEAN, ISUNIQUE, CMAGICHIT, CANPOISON, CANFRIGHTEN, CANBBOLT,
+                 NOBOLT, CANTELEPORT, NOFIRE, NOSTAB, NOGAS},
+                "", 0, 
+                70,
+                {18,    18,     5,      60000,  12,     -6,     HPT("10d8+120"),
+                "2d8+4/2d6+8"}},
+{"arch devil (Mammon)", 
+                0,     TRUE,   TRUE,   'M',    "15-20",
+                {ISMEAN, ISUNIQUE, BMAGICHIT, NOGAS, NOBOLT, ISINVIS, NOSTAB,
+                 CANFRIGHTEN, CANPAIN, CANTELEPORT, NOCOLD, NOFIRE},
+                "", 0, 
+                60,
+                {18,    18,     5,      80000,  10,     -4,     HPT("10d8+90"),
+                "3d6/3d8/3d10"}},
+{"arch devil (Baalzebul)", 
+                0,     TRUE,   TRUE,   'B',    "15-20",
+                {ISMEAN, ISUNIQUE, BMAGICHIT, NOGAS, NOBOLT, ISINVIS, NOSTAB,
+                 CANFRIGHTEN, CANPAIN, CANTELEPORT, NOCOLD},
+                "", 0, 
+                60,
+                {18,    18,     6,      80000,  11,     -4,     HPT("10d8+100"),
+                "3d6/3d8/3d10"}},
+{"arch devil (Moloch)", 
+                100,     TRUE,   TRUE,   'M',    "15-20",
+                {ISMEAN, ISUNIQUE, BMAGICHIT, NOGAS, NOBOLT, ISINVIS, ISGREED,
+                 CANFRIGHTEN, CANPAIN, CANTELEPORT, NOCOLD, CARRYGOLD, NOSTAB},
+                "", 0, 
+                70,
+                {18,    18,     6,      80000,  12,     -7,     HPT("10d8+120"),
+                "3d6/3d8/3d10"}},
+{"arch devil (Dispater)", 
+                100,     TRUE,   TRUE,   'd',    "15-20",
+                {ISMEAN, ISUNIQUE, BMAGICHIT, NOGAS, NOBOLT, ISINVIS, ISGREED,
+                 CANFRIGHTEN, CANPAIN, CANTELEPORT, NOCOLD, CARRYGOLD, NOSTAB},
+                "", 0, 
+                70,
+                {18,    18,     6,      80000,  12,     -7,     HPT("10d8+120"),
+                "3d6/3d8/3d10"}},
+{"platinum dragon (Bahamut)", 
+                0,     TRUE,   FALSE,  'P',    "20",
+                {ISUNIQUE, CANBGAS, CANBBOLT, NOBOLT, NOCOLD, NOFIRE, NOGAS,
+         CANMISSILE, CANSUMMON, CANBACID, CANFRIGHTEN, NOACID, NOSTAB},
+                "frost giant", 6,
+                70,
+                {20,    20,     5,      90000,  12,     -6,     HPT("10d8+120"),
+                "2d10+10/2d10+10"}},
+{"diablero (Prithivi)", 
+                100,     TRUE,   TRUE,   'o',    "15-20",
+                {ISMEAN, ISUNIQUE, ISREGEN, ISSHADOW, CANBACID, NOACID, NOGAS,
+                 ISINVIS, ISSCAVENGE, CANDRAW, MAGICHIT, NOSTAB},
+                "", 0,
+                70,
+                {18,    18,     3,      90000,  12,     -5,     HPT("10d8+120"),
+                "3d12/4d8+6"}},
+{"diablero (Apas)", 
+                100,     TRUE,   TRUE,   'o',    "15-20",
+                {ISMEAN, ISUNIQUE, ISREGEN, ISSHADOW, CANBACID, NOACID, NOGAS,
+                 ISINVIS, ISSCAVENGE, CANDRAW, MAGICHIT, NOSTAB},
+                "", 0,
+                70,
+                {18,    18,     3,      90000,  13,     -5,     HPT("10d8+120"),
+                "3d12/4d8+6"}},
+{"chromatic dragon (Tiamat)", 
+                0,     TRUE,   FALSE,  'C',    "20",
+                {ISUNIQUE, CANBGAS, CANBBOLT, NOBOLT, NOCOLD, NOFIRE, NOGAS,
+         CANMISSILE, CANSUMMON, CANBACID, CANFRIGHTEN, NOACID, NOSTAB},
+                "fire giant", 6,
+                70,
+                {20,    20,     5,      90000,  13,     -6,     HPT("10d8+120"),
+                "2d10+10/2d10+10"}},
+{"diablero (Vayu)", 
+                100,     TRUE,   TRUE,   'o',    "15-20",
+                {ISMEAN, ISUNIQUE, ISREGEN, ISSHADOW, CANBACID, NOACID, NOGAS,
+                 ISINVIS, ISSCAVENGE, CANDRAW, MAGICHIT, NOSTAB},
+                "", 0,
+                70,
+                {18,    18,     2,      90000,  13,     -7,     HPT("10d8+120"),
+                "3d12/4d8+6"}},
+{"diablero (Tejas)", 
+                100,     TRUE,   TRUE,   'o',    "15-20",
+                {ISMEAN, ISUNIQUE, ISREGEN, ISSHADOW, CANBACID, NOACID, NOGAS,
+                 ISINVIS, ISSCAVENGE, CANDRAW, MAGICHIT, NOSTAB},
+                "", 0,
+                70,
+                {18,    18,     2,      90000,  13,     -7,     HPT("10d8+120"),
+                "3d12/4d8+6"}},
+{"etheric dragon (Ishtar)", 
+                0,     TRUE,   FALSE,   'E',    "20",
+                {ISUNIQUE, CANBGAS, CANBBOLT, NOBOLT, NOCOLD, NOFIRE, NOGAS,
+         CANMISSILE, CANSUMMON, CANBACID, CANFRIGHTEN, NOACID, NOSTAB},
+                "storm giant", 6,
+                70,
+                {20,    20,     5,      90000,  13,     -8,     HPT("10d8+120"),
+                "2d10+10/2d10+10"}},
+{"diablero (Akasa)",
+                100,     TRUE,   TRUE,   'o',    "15-20",
+                {ISMEAN, ISUNIQUE, ISREGEN, ISSHADOW, CANBACID, NOACID, NOGAS,
+                 ISINVIS, ISSCAVENGE, CANDRAW, MAGICHIT, NOSTAB},
+                "", 0,
+                70,
+                {18,    18,     2,      90000,  13,     -8,     HPT("10d8+120"),
+                "3d12/4d8+6"}},
+{"greater god (Maglubiyet)",
+                100,     TRUE,   FALSE,  'm',    "20",
+                {ISMEAN, ISUNIQUE, CMAGICHIT, ISREGEN, CANINWALL, NOGAS,
+                 CANBBOLT, NOBOLT, ISCLEAR, CARRYRING, CARRYFOOD, CARRYPOTION,
+         CARRYSCROLL, NOSTAB, NOFIRE, NOCOLD},
+                "", 0,
+                80,
+                {18,    18,     5,      100000, 13,     -12,    HPT("10d8+120"),
+                "6d10/6d10"}},
+{"greater god (Gruumsh)",
+                100,     TRUE,   FALSE,  'G',    "20",
+                {ISMEAN, ISUNIQUE, CMAGICHIT, ISREGEN, NOGAS, CANINWALL,
+                 CANBBOLT, NOBOLT, ISCLEAR, CARRYMISC, CARRYSCROLL, CARRYFOOD,
+         CARRYPOTION, NOSTAB, NOFIRE, NOCOLD},
+                "", 0,
+                80,
+                {18,    18,     5,      100000, 13,     -12,    HPT("10d8+120"),
+                "6d10/6d10"}},
+{"semi-demon (Cambion)",
+                0,     TRUE,   TRUE,   'c',    "15-20",
+                {ISMEAN, ISUNIQUE, BMAGICHIT, ISREGEN, CANBGAS, NOGAS, NOSTAB,
+                 CANTELEPORT, CANFRIGHTEN, CANBRANDOM, NOBOLT},
+                "", 0,
+                80,
+                {18,    18,     6,      100000, 13,     -5,     HPT("10d8+150"),
+                "5d8/5d8"}},
+{"minor demon (Dretch)",
+                0,     TRUE,   TRUE,   'd',    "15-20",
+                {ISMEAN, ISUNIQUE, BMAGICHIT, ISREGEN, CANBGAS, NOGAS, NOSTAB,
+                 CANTELEPORT, CANFRIGHTEN, CANBRANDOM, NOBOLT},
+                "", 0,
+                80,
+                {18,    18,     6,      100000, 13,     -6,     HPT("10d8+150"),
+                "3d12/3d12"}},
+{"major demon (Nabassu)",
+                0,     TRUE,   TRUE,   'n',    "15-20",
+                {ISMEAN, ISUNIQUE, BMAGICHIT, ISREGEN, CANBGAS, NOGAS, NOSTAB,
+                 CANTELEPORT, CANFRIGHTEN, CANBRANDOM, NOBOLT},
+                "", 0,
+                80,
+                {18,    18,     6,      110000, 14,     -7,     HPT("10d8+150"),
+                "4d10/4d10"}},
+{"demon lord (Baphomet)",
+                0,     TRUE,   TRUE,   'B',    "20",
+                {ISMEAN, ISUNIQUE, BMAGICHIT, ISREGEN, CANBGAS, NOGAS, NOSTAB,
+                 CANSUMMON, CANTELEPORT, CANFRIGHTEN, CANBRANDOM, NOBOLT},
+                "ancient blue dragon", 2,
+                90,
+                {20,    20,     5,      110000, 14,     -8,     HPT("10d8+150"),
+                "5d10/5d10"}},
+{"incubus (Ravana)",
+                0,     TRUE,   TRUE,   'R',    "10-20",
+                {ISMEAN, ISUNIQUE, LOOKSTONE, NOFEAR, ISUNDEAD, TURNABLE,
+                 CANBRANDOM, TOUCHFEAR, NOCOLD, NOSTAB, NOGAS},
+                "", 0,
+                90,
+                {18,    18,     6,      120000, 14,     -7,     HPT("10d8+150"),
+                "3d10/3d10"}},
+{"succubus (Azazel)",
+                0,     TRUE,   TRUE,   'a',    "10-20",
+                {ISMEAN, ISUNIQUE, LOOKSTONE, NOFEAR, ISUNDEAD, TURNABLE,
+                 CANBRANDOM, TOUCHFEAR, NOFIRE, NOSTAB, NOGAS},
+                "", 0,
+                90,
+                {18,    18,     6,      120000, 14,     -9,     HPT("10d8+150"),
+                "3d10/3d10"}},
+{"incubus (Putana)",
+                0,     TRUE,   TRUE,   'P',    "10-20",
+                {ISMEAN, ISUNIQUE, LOOKSTONE, NOFEAR, ISUNDEAD, TURNABLE,
+                 CANBRANDOM, TOUCHFEAR, NOCOLD, NOSTAB, NOGAS},
+                "", 0,
+                90,
+                {18,    18,     6,      120000, 14,     -9,     HPT("10d8+150"),
+                "3d10/3d10"}},
+{"succubus (Sammael)",
+                0,     TRUE,   TRUE,   'S',    "10-20",
+                {ISMEAN, ISUNIQUE, LOOKSTONE, NOFEAR, ISUNDEAD, TURNABLE,
+                 CANBRANDOM, TOUCHFEAR, NOFIRE, NOGAS, NOSTAB},
+                "", 0,
+                90,
+                {18,    18,     6,      120000, 14,     -7,     HPT("10d8+150"),
+                "3d10/3d10"}},
+{"incubus (Aeshma)",
+                0,     TRUE,   TRUE,   'A',    "10-20",
+                {ISMEAN, ISUNIQUE, LOOKSTONE, NOFEAR, ISUNDEAD, TURNABLE,
+                 CANBRANDOM, TOUCHFEAR, NOCOLD, NOSTAB, NOGAS},
+                "", 0,
+                90,
+                {18,    18,     6,      120000, 14,     -8,     HPT("10d8+150"),
+                "3d10/3d10"}},
+{"succubus (Belial)",
+                0,     TRUE,   TRUE,   'b',    "10-20",
+                {ISMEAN, ISUNIQUE, LOOKSTONE, NOFEAR, ISUNDEAD, TURNABLE,
+                 CANBRANDOM, TOUCHFEAR, NOFIRE, NOSTAB, NOGAS},
+                "", 0,
+                90,
+                {18,    18,     6,      120000, 14,     -8,     HPT("10d8+150"),
+                "3d10/3d10"}},
+{"prince of hell (Hutijin)",
+                0,     TRUE,   FALSE,   'h',    "15-20",
+                {ISMEAN, ISUNIQUE, CMAGICHIT, ISREGEN, CANSUMMON, CANBCGAS,
+                 NOGAS, CANINWALL, CANFRIGHTEN, CANBRANDOM, NOBOLT, ISFLY,
+                 NOSTAB, NOFIRE},
+                "ancient green dragon", 2,
+                90,
+                {18,    18,     3,      130000, 14,     -10,    HPT("10d8+150"),
+                "4d12+8/4d12+8"}},
+{"princess of hell (Glasya)",
+                0,     TRUE,   FALSE,   'G',    "15-20",
+                {ISMEAN, ISUNIQUE, CMAGICHIT, ISREGEN, CANSUMMON, CANBCGAS,
+                 NOGAS, CANINWALL, CANFRIGHTEN, CANBRANDOM, NOBOLT, ISFLY,
+                 NOSTAB, NOCOLD},
+                "ancient red dragon", 2,
+                90,
+                {18,    18,     3,      130000, 14,     -10,    HPT("10d8+150"),
+                "4d12+8/4d12+8"}},
+{"prince of hell (Titivilus)",
+                0,     TRUE,   FALSE,   't',    "15-20",
+                {ISMEAN, ISUNIQUE, CMAGICHIT, ISREGEN, CANSUMMON, CANBCGAS,
+                 NOGAS, CANINWALL, CANFRIGHTEN, CANBRANDOM, NOBOLT, ISFLY,
+                 NOSTAB, NOFIRE},
+                "ancient white dragon", 2,
+                90,
+                {18,    18,     3,      130000, 15,     -10,    HPT("10d8+150"),
+                "4d12+8/4d12+8"}},
+{"lesser daemon (Pisco)",
+                0,     TRUE,   TRUE,   'P',    "15-20",
+                {ISMEAN, ISUNIQUE, BMAGICHIT, ISREGEN, CANBGAS, NOGAS, NOSTAB,
+                 TOUCHSTONE, CANPAIN, NOSLOW, NOBOLT},
+                "", 0,
+                90,
+                {18,    18,     5,      140000, 15,     -8,     HPT("10d8+160"),
+                "10d12"}},
+{"lesser daemon (Dergho)",
+                0,     TRUE,   TRUE,   'd',    "15-20",
+                {ISMEAN, ISUNIQUE, BMAGICHIT, ISREGEN, CANBGAS, NOGAS, NOSTAB,
+                 TOUCHSTONE, CANPAIN, NOSLOW, NOBOLT},
+                "", 0,
+                90,
+                {18,    18,     5,      140000, 15,     -8,     HPT("10d8+160"),
+                "10d12"}},
+{"greater daemon (Ultro)",
+                0,     TRUE,   TRUE,   'U',    "15-20",
+                {ISMEAN, ISUNIQUE, BMAGICHIT, ISREGEN, CANBGAS, NOGAS, NOSTAB,
+                 TOUCHSTONE, CANAGE, NOSLOW, NOBOLT},
+                "", 0,
+                90,
+                {18,    18,     5,      140000, 15,     -9,     HPT("10d8+160"),
+                "10d10+10"}},
+{"lesser daemon (Hydro)",
+                0,     TRUE,   TRUE,   'H',    "15-20",
+                {ISMEAN, ISUNIQUE, BMAGICHIT, ISREGEN, CANBGAS, NOGAS, NOSTAB,
+                 TOUCHSTONE, CANPAIN, NOSLOW, NOBOLT},
+                "", 0,
+                90,
+                {18,    18,     5,      140000, 15,     -8,     HPT("10d8+160"),
+                "10d12"}},
+{"lesser daemon (Yagno)",
+                0,     TRUE,   TRUE,   'y',    "15-20",
+                {ISMEAN, ISUNIQUE, BMAGICHIT, ISREGEN, CANBGAS, NOGAS, NOSTAB,
+                 TOUCHSTONE, CANPAIN, NOSLOW, NOBOLT},
+                "", 0,
+                90,
+                {18,    18,     5,      140000, 15,     -8,     HPT("10d8+160"),
+                "10d12"}},
+{"greater daemon (Arcana)",
+                0,     TRUE,   TRUE,   'a',    "15-20",
+                {ISMEAN, ISUNIQUE, BMAGICHIT, ISREGEN, CANBGAS, NOGAS, NOSTAB,
+                 TOUCHSTONE, CANAGE, NOSLOW, NOBOLT},
+                "", 0,
+                90,
+                {18,    18,     5,      140000, 15,     -9,     HPT("10d8+160"),
+                "10d10+10"}},
+{"oino daemon (Anthraxus)",
+                0,     TRUE,   FALSE,   'O',    "20",
+                {ISMEAN, ISUNIQUE, BMAGICHIT, ISREGEN, CANBGAS, NOGAS, NOBOLT,
+                 TOUCHSTONE, CANFRIGHTEN, CANPAIN, CANAGE, NOFIRE, CANMISSILE,
+         CANHOLD, HALFDAMAGE, CANSUMMON, CANBBOLT, NOCOLD, NOSTAB},
+                "ancient amethyst dragon", 4,
+                90,
+                {20,    20,     3,      150000, 15,     -12,    HPT("10d8+170"),
+                "10d10+20"}},
+{"ipsissimus (Alteran)",
+                100,     TRUE,   FALSE,  'i',    "25",
+                {ISUNIQUE, CARRYCARD, CARRYFOOD, CMAGICHIT, ISREGEN, NOGAS,
+         CANINWALL, CANFRIGHTEN, CANBACID, NOACID, NOBOLT, ISCLEAR,
+         NOSLOW, NOFEAR, NODETECT, NOFIRE, NOCOLD, NOSTAB, CANSONIC},
+                "", 0,
+                100,
+                {25,    25,     2,      250000, 16,     -30,    HPT("10d8+200"),
+                "10d10/10d10"}},
+{"boatman (Charon)",
+                0,     TRUE,   FALSE,   'c',    "20",
+                {ISMEAN, ISUNIQUE, CMAGICHIT, ISREGEN, CANSUMMON, NOGAS, NOBOLT,
+                 CANTELEPORT, CANFRIGHTEN, CANBRANDOM, NOSTAB, NOBOLT, NOFEAR,
+                 CANPAIN, DOUBLEDRAIN, CANPOISON, CANHOLD, CANINWALL},
+                "ancient saphire dragon", 4,
+                100,
+                {20,    20,     2,      250000, 18,     -20,    HPT("10d8+200"),
+                "12d12/12d12"}},
+{"anole", 
+                0,      TRUE,   TRUE,   'a',    "10-15",
+                {ISMEAN, CANDISEASE},
+                "", 0, 
+                1,
+                {10,    10,     3,      10,      1,      5,      HPT("1d8+5"),
+                "1d4"}},
+{"creodont", 
+                50,     TRUE,   TRUE,   'c',    "12-14",
+                {ISMEAN, CANSTINK, NOSLOW},
+                "", 0, 
+                1,
+                {10,    10,     6,      10,      1,      3,      HPT("2d8+5"),
+                "1d4"}},
+{"gorgosaur", 
+                0,      TRUE,   TRUE,   'g',    "8-14",
+                {ISMEAN, CANTELEPORT, CANINFEST, NOSTAB},
+                "", 0, 
+                3,
+                {10,    10,     9,      30,      1,      2,      HPT("3d8+5"),
+                "1d4/1d6"}},
+{"giant cicada", 
+                0,      TRUE,   TRUE,   'C',    "4",
+                {ISMEAN, AREMANY, ISUNDEAD, TURNABLE, CANPOISON, NOSTAB},
+                "", 0, 
+                3,
+                {10,    10,     6,      30,      2,      4,      HPT("4d8+5"),
+                "1d6"}},
+{"elasmosaurus", 
+                50,      TRUE,   TRUE,   'e',    "10-15",
+                {ISMEAN, CANDRAW, CANPARALYZE, CANSMELL},
+                "", 0, 
+                5,
+                {10,    10,     12,      40,      2,      8,      HPT("2d8+10"),
+                "2d8"}},
+{"trilobite", 
+                0,      TRUE,   TRUE,   't',    "10-20",
+                {ISMEAN, AREMANY, NOFIRE, NOCOLD, CANINWALL},
+                "", 0, 
+                2,
+                {12,    14,     3,      50,      2,      6,      HPT("2d8+20"),
+                "2d8"}},
+{"mammoth", 
+                50,     TRUE,   TRUE,   'M',    "15",
+                {ISMEAN, AREMANY, CANTELEPORT, CANSTINK, CARRYARMOR},
+                "", 0,
+                7,
+                {12,    12,     15,      80,     3,      0,      HPT("3d8+50"),
+                "2d4/2d6"}},
+{"ichthyosaur", 
+                50,     TRUE,   TRUE,   'i',    "10-14",
+                {ISMEAN, CARRYWEAPON, CANPOISON, CANINFEST},
+                "", 0, 
+                4,
+                {12,    12,     6,      70,      3,      2,      HPT("2d8+30"),
+                "2d6"}},
+{"grig", 
+                50,     TRUE,   TRUE,   'g',    "8-16",
+                {ISMEAN, CANBFIRE, CANCHILL, NOFIRE, NOCOLD},
+                "", 0, 
+                5,
+                {12,    12,     3,      100,     3,      -1,     HPT("3d8+20"),
+                "1d4/4d6"}},
+{"saber-tooth", 
+                0,      TRUE,   TRUE,   's',    "10-17",
+                {ISMEAN, CANBICE, ISSHADOW, NOSTAB, NOBOLT, CANHUG, CANTUNNEL},
+                "", 0,
+                8,
+                {12,    12,     6,      100,     4,      -2,     HPT("3d8+50"),
+                "2d8/1d12"}},
+{"merychippus", 
+                0,      TRUE,   TRUE,   'm',    "16",
+                {ISMEAN, CANSHRIEK, CANBLIND, CANHUG, CANSNORE},
+                "", 0, 
+                6,
+                {12,    12,     9,      150,     4,      0,      HPT("3d8+30"),
+                "4d8"}},
+{"nematode", 
+                100,    TRUE,   TRUE,   'n',    "8-14",
+                {ISMEAN, CANINWALL, CANTELEPORT, NOSTAB, ISSCAVENGE, CARRYFOOD},
+                "", 0, 
+                10,
+                {12,    12,     3,      150,     4,      3,      HPT("3d8+20"),
+                "2d12"}},
+{"tussah", 
+                0,      TRUE,   TRUE,   't',    "12-18",
+                {ISMEAN, CANBICE, NOCOLD, NOBOLT, NOSTAB, CANPAIN, NOFEAR},
+                "", 0, 
+                9,
+                {12,    12,     4,       200,    4,      -3,     HPT("4d8+30"),
+                "3d8"}},
+{"theropod", 
+                0,      TRUE,   TRUE,   'T',    "15-20",
+                {ISMEAN, ISFLY, CANROT, CANSTINK, CANBFIRE, CANEXPLODE},
+                "", 0, 
+                8,
+                {14,    14,     12,       200,    5,      0,      HPT("4d8+10"),
+                "3d8+2"}},
+{"mastodon", 
+                0,      TRUE,   TRUE,   'm',    "10-15",
+                {ISMEAN, CANBFIRE, NOBOLT, NOFIRE, NOCOLD, TURNABLE, NOSTAB},
+                "", 0, 
+                10,
+                {14,    14,     15,      500,    5,      -10,    HPT("4d8+50"),
+                "4d8"}},
+{"sloth", 
+                0,      TRUE,   TRUE,   'S',    "10-18",
+                {ISMEAN, NOSTAB, CANSMELL, CANSTINK, NOCOLD, CANSUMMON,
+         TOUCHSTONE},
+                "trilobite", 4, 
+                11,
+                {14,    14,     18,       300,    5,     -1,     HPT("4d8+60"),
+                "4d8"}},
+{"pterodactyl", 
+                0,      TRUE,   TRUE,   'P',    "15-20",
+                {ISMEAN, AREMANY, ISFLY, NOSLOW, NOBOLT, NOSTAB, CANPAIN},
+                "", 0, 
+                9,
+                {14,    14,     3,       250,    5,      0,      HPT("4d8+30"),
+                "2d8/3d8/4d8"}},
+{"brontosaurus", 
+                0,      TRUE,   TRUE,   'b',    "1",
+                {ISMEAN, NOFIRE, CANBFIRE, ISREGEN, CANHOLD, NOBOLT, NOSTAB},
+                "", 0, 
+                12,
+                {14,    14,     12,      900,     5,      -3,     HPT("8d8+50"),
+                "6d8"}},
+{"sauropod", 
+                0,      TRUE,   TRUE,   's',    "10-18",
+                {ISMEAN, CANSONIC, NOPARALYZE, NOCOLD, NOSTAB, CANSUMMON,
+         NOFIRE},
+                "grig", 6,
+                10,
+                {14,    16,     6,       800,    6,      -4,      HPT("4d8+30"),
+                "3d8"}},
+{"wooly mammoth", 
+                0,      TRUE,   TRUE,   'w',    "15-20",
+                {ISMEAN, AREMANY, NOBOLT, NOGAS, NOFIRE, NOACID, CANHUH,
+                 TAKEINTEL, NOSTAB},
+                "", 0, 
+                13,
+                {14,    14,     12,     1000,    6,      -7,     HPT("8d8+60"),
+                "4d8/6d8"}},
+{"brontops", 
+                0,      TRUE,   TRUE,  'B',    "10-14",
+                {ISMEAN, NOGAS, NOFIRE, NOBOLT, NOFEAR, CANDRAW, TAKEWISDOM},
+                "", 0, 
+                12,
+                {14,    14,     18,       900,    7,      -1,     HPT("8d8+80"),
+                "8d8+2"}},
+{"tricerotops", 
+                0,      TRUE,   TRUE,   'T',    "15-20",
+                {ISMEAN, CANSURPRISE, CANMISSILE, CANPOISON, NOBOLT, NOFIRE},
+                "", 0, 
+                8,
+                {14,    14,     6,      1000,    7,      -2,     HPT("8d8+70"),
+                "8d8/6d8"}},
+{"sinanthropus", 
+                50,     TRUE,   TRUE,   's',    "12-20",
+                {ISMEAN, CANBACID, NOACID, NOBOLT, CANDRAW, NOFEAR, NOGAS,
+                 CANFRIGHTEN, BMAGICHIT},
+                "", 0, 
+                13,
+                {15,    15,     6,      2000,    8,      -8,     HPT("8d8+100"),
+                "8d8+5"}},
+{"stegosaurus", 
+                0,      TRUE,   TRUE,   's',    "15-20",
+                {ISMEAN, CANBGAS, CANROT, NOFEAR, NOGAS, CANTUNNEL, NOACID,
+                 NOSTAB, CANBCGAS},
+                "", 0,
+                14,
+                {16,    16,     4,      2500,    8,      -10,    HPT("8d8+75"),
+                "8d8+7"}},
+{"plesiosaurus", 
+                0,      TRUE,   TRUE,   'p',    "8-15",
+                {ISMEAN, NOGAS, NOSTAB, DOUBLEDRAIN, NOBOLT},
+                "", 0, 
+                11,
+                {18,    18,     9,      2000,    8,      -8,     HPT("8d8+40"),
+                "1d4/8d8"}},
+{"tyranosaurus rex", 
+                0,     TRUE,   TRUE,   'R',    "10-20",
+                {ISMEAN, ISREGEN, CANTUNNEL, NOSTAB, NOGAS, NOFIRE, NOBOLT,
+         AREMANY, CMAGICHIT, CANFRIGHTEN},
+                "", 0,
+                15,
+                {18,    18,     2,      3000,    8,     -10,    HPT("10d8+100"),
+                "6d8/8d8"}},
+{"anaconda", 
+                80,     TRUE,   TRUE,   'A',    "12-20",
+                {ISMEAN, NOGAS, CANSUMMON, CARRYGOLD, STEALGOLD, NOSTAB,
+                 NOFIRE, NOBOLT, CANAGE, CANFRIGHTEN},
+                "nematode", 6,
+                20,
+                {18,    18,     4,      4000,   9,     -8,    HPT("10d8+150"),
+                "8d8/8d8"}},
+{"imperial mammoth", 
+                0,      TRUE,   TRUE,   'I',    "15-20",
+                {ISMEAN, AREMANY, NOFEAR, ISREGEN, CANHUH, NOCOLD, CANSURPRISE,
+                 NOSTAB, CANBGAS, NOGAS, NOFIRE, NOACID, CANBACID},
+                "", 0, 
+                20,
+                {18,    18,     12,     5000,    9,    -10,     HPT("10d8+200"),
+                "6d8+10"}},
+{"zinjanthropus", 
+                80,     TRUE,   TRUE,   'Z',    "18-20",
+                {ISMEAN, NOSLOW, CANBICE, CANBFIRE, CANSUMMON, LOOKSTONE,
+         NOSTAB, NOBOLT, NOACID, NOCOLD, NOFIRE, NOSLOW},
+                "mastodon", 6,
+                20,
+                {18,    18,     3,      5000,    9,     -15,    HPT("10d8+250"),
+                "8d8+10"}},
+{"positron", 
+                0,      TRUE,   TRUE,   'X',    "1-18",
+                {ISMEAN, CANEXPLODE, ISFLY, TURNABLE, ISUNDEAD, BLOWDIVIDE,
+                 NOSLOW, HASFIRE, NOFIRE, NOBOLT, CANFRIGHTEN},
+                "", 0, 
+                25,
+                {18,    18,     10,      10000,   9,    -1,     HPT("10d8+250"),
+                "4d8/6d8"}},
+{"quartermaster", 
+                80,      FALSE,  TRUE,   'q',    "25",
+                {CANSELL, ISCLEAR, CANTELEPORT, ISFLY, NOSLOW, NOSTAB, NOBOLT,
+         NOSLEEP, NOFIRE, NOCOLD, NOFEAR, CANINWALL},
+                "", 0,
+                30,
+                {25,    25,     5,      1000,    7,      -6,     HPT("2d8+20"),
+                "8d10"}},
+};
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xrogue/monsters.c	Tue Apr 21 08:55:20 2015 -0400
@@ -0,0 +1,865 @@
+/*
+    monsters.c - File with various monster functions in it
+    
+    XRogue: Expeditions into the Dungeons of Doom
+    Copyright (C) 1991 Robert Pietkivitch
+    All rights reserved.
+    
+    Based on "Advanced Rogue"
+    Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka and AT&T
+    All rights reserved.
+
+    Based on "Rogue: Exploring the Dungeons of Doom"
+    Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
+    All rights reserved.
+    
+    See the file LICENSE.TXT for full copyright and licensing information.
+*/
+
+#include <curses.h>
+#include <ctype.h>
+#include <string.h>
+#include "rogue.h"
+
+/*
+ * Check_residue takes care of any effect of the monster 
+ */
+
+check_residue(tp)
+register struct thing *tp;
+{
+    /*
+     * Take care of special abilities
+     */
+    if (on(*tp, DIDHOLD) && (--hold_count == 0)) {
+        turn_off(player, ISHELD);
+        turn_off(*tp, DIDHOLD);
+    }
+
+    /* If frightened of this monster, stop */
+    if (on(player, ISFLEE) &&
+        player.t_dest == &tp->t_pos) turn_off(player, ISFLEE);
+
+    /* If monster was suffocating player, stop it */
+    if (on(*tp, DIDSUFFOCATE)) {
+        extinguish(suffocate);
+        turn_off(*tp, DIDSUFFOCATE);
+    }
+
+    /* If something with fire, may darken */
+    if (on(*tp, HASFIRE)) {
+        register struct room *rp=roomin(&tp->t_pos);
+        register struct linked_list *fire_item;
+
+        if (rp) {
+            for (fire_item = rp->r_fires; fire_item != NULL;
+                 fire_item = next(fire_item)) {
+                if (THINGPTR(fire_item) == tp) {
+                    detach(rp->r_fires, fire_item);
+                    destroy_item(fire_item);
+                    if (rp->r_fires == NULL) {
+                        rp->r_flags &= ~HASFIRE;
+                        if (cansee(tp->t_pos.y, tp->t_pos.x)) light(&hero);
+                    }
+                    break;
+                }
+            }
+        }
+    }
+}
+
+/*
+ * Creat_mons creates the specified monster -- any if 0 
+ */
+
+bool
+creat_mons(person, monster, report)
+struct thing *person;   /* Where to create next to */
+short monster;
+bool report;
+{
+    struct linked_list *nitem;
+    register struct thing *tp;
+    struct room *rp;
+    coord *mp;
+
+    if (levtype == POSTLEV)
+        return(FALSE);
+    if ((mp = fallpos(&(person->t_pos), FALSE, 2)) != NULL) {
+        nitem = new_item(sizeof (struct thing));
+        new_monster(nitem,
+                    monster == 0 ? randmonster(FALSE, FALSE)
+                                 : monster,
+                    mp,
+                    TRUE);
+        tp = THINGPTR(nitem);
+        runto(tp, &hero);
+        carry_obj(tp, monsters[tp->t_index].m_carry/2); /* only half chance */
+
+        /* since it just got here, it is disoriented */
+        tp->t_no_move = 2 * movement(tp);
+
+        if (on(*tp, HASFIRE)) {
+            rp = roomin(&tp->t_pos);
+            if (rp) {
+                register struct linked_list *fire_item;
+
+                /* Put the new fellow in the room list */
+                fire_item = creat_item();
+                ldata(fire_item) = (char *) tp;
+                attach(rp->r_fires, fire_item);
+
+                rp->r_flags |= HASFIRE;
+            }
+        }
+
+        /* 
+         * If we can see this monster, set oldch to ' ' to make light()
+         * think the creature used to be invisible (ie. not seen here)
+         */
+        if (cansee(tp->t_pos.y, tp->t_pos.x)) tp->t_oldch = ' ';
+        return(TRUE);
+    }
+    if (report) msg("You hear a faint cry of anguish in the distance.. ");
+    return(FALSE);
+}
+
+/*
+ * Genmonsters:
+ *      Generate at least 'least' monsters for this single room level.
+ *      'Treas' indicates whether this is a "treasure" level.
+ */
+
+void
+genmonsters(least, treas)
+register int least;
+bool treas;
+{
+    reg int i;
+    reg struct room *rp = &rooms[0];
+    reg struct linked_list *item;
+    reg struct thing *mp;
+    coord tp;
+
+    for (i = 0; i < (max(50, level) + least); i++) {
+            if (!treas && rnd(100) < 65)        /* put in some little buggers */
+                continue;
+
+            /*
+             * Put the monster in
+             */
+            item = new_item(sizeof *mp);
+            mp = THINGPTR(item);
+            do {
+                    rnd_pos(rp, &tp);
+            } until(mvwinch(stdscr, tp.y, tp.x) == FLOOR);
+
+            new_monster(item, randmonster(FALSE, FALSE), &tp, FALSE);
+            /*
+             * See if we want to give it a treasure to carry around.
+             */
+            carry_obj(mp, monsters[mp->t_index].m_carry);
+
+            /* Calculate a movement rate */
+            mp->t_no_move = movement(mp);
+
+            /* Is it going to give us some light? */
+            if (on(*mp, HASFIRE)) {
+                register struct linked_list *fire_item;
+
+                fire_item = creat_item();
+                ldata(fire_item) = (char *) mp;
+                attach(rp->r_fires, fire_item);
+                rp->r_flags |= HASFIRE;
+            }
+    }
+}
+
+/*
+ * id_monst returns the index of the monster given its letter
+ */
+
+short
+id_monst(monster)
+register char monster;
+{
+    register short result;
+
+    if (levtype == OUTSIDE) {
+        result = NLEVMONS*vlevel + (NUMMONST-NUMDINOS-1);
+        if (result > NUMMONST) result = NUMMONST;
+    }
+    else {  
+        result = NLEVMONS*vlevel;
+        if (result > NUMMONST-NUMDINOS) result = NUMMONST-NUMDINOS;
+    }
+
+    if (levtype == OUTSIDE) {
+        for(; result>(NUMMONST-NUMDINOS-1); result--)
+            if (monsters[result].m_appear == monster) return(result);
+        for (result=(NLEVMONS*vlevel)+1; result <= NUMMONST-NUMDINOS; result++)
+            if (monsters[result].m_appear == monster) return(result);
+    }
+    else {
+        for(; result>0; result--)
+            if (monsters[result].m_appear == monster) return(result);
+        for (result=(NLEVMONS*vlevel)+1; result <= NUMMONST; result++)
+            if (monsters[result].m_appear == monster) return(result);
+    }
+    return(0);
+}
+
+
+/*
+ * new_monster:
+ *      Pick a new monster and add it to the list
+ */
+
+new_monster(item, type, cp, max_monster)
+struct linked_list *item;
+short type;
+coord *cp;
+bool max_monster;
+{
+    register struct thing *tp;
+    register struct monster *mp;
+    register char *ip, *hitp;
+    register int i, min_intel, max_intel;
+    register int num_dice, num_sides=8, num_extra=0;
+
+    attach(mlist, item);
+    tp = THINGPTR(item);
+    tp->t_pack = NULL;
+    tp->t_index = type;
+    tp->t_wasshot = FALSE;
+    tp->t_type = monsters[type].m_appear;
+    tp->t_ctype = C_MONSTER;
+    tp->t_action = A_NIL;
+    tp->t_doorgoal.x = tp->t_doorgoal.y = -1;
+    tp->t_quiet = 0;
+    tp->t_dest = NULL;
+    tp->t_name = NULL;
+    tp->t_pos = tp->t_oldpos = *cp;
+    tp->t_oldch = mvwinch(cw, cp->y, cp->x);
+    mvwaddch(mw, cp->y, cp->x, tp->t_type);
+    mp = &monsters[tp->t_index];
+
+    /* Figure out monster's hit points */
+    hitp = mp->m_stats.ms_hpt;
+    num_dice = atoi(hitp);
+    if ((hitp = strchr(hitp, 'd')) != NULL) {
+        num_sides = atoi(++hitp);
+        if ((hitp = strchr(hitp, '+')) != NULL)
+            num_extra = atoi(++hitp);
+    }
+
+    tp->t_stats.s_lvladj = 0;
+    tp->t_stats.s_lvl = mp->m_stats.ms_lvl;
+    tp->t_stats.s_arm = mp->m_stats.ms_arm;
+    strcpy(tp->t_stats.s_dmg,mp->m_stats.ms_dmg);
+    tp->t_stats.s_str = mp->m_stats.ms_str;
+    tp->t_stats.s_dext = mp->m_stats.ms_dex;
+    tp->t_movement = mp->m_stats.ms_move;
+    if (vlevel > HARDER) { /* the deeper, the meaner we get */
+         tp->t_stats.s_lvl += (vlevel - HARDER);
+         num_dice += (vlevel - HARDER)/2;
+         tp->t_stats.s_arm -= (vlevel - HARDER) / 4;
+    }
+    if (max_monster)
+        tp->t_stats.s_hpt = num_dice * num_sides + num_extra;
+    else
+        tp->t_stats.s_hpt = roll(num_dice, num_sides) + num_extra;
+    tp->t_stats.s_exp = mp->m_stats.ms_exp + mp->m_add_exp*tp->t_stats.s_hpt;
+
+    /*
+     * just initailize others values to something reasonable for now
+     * maybe someday will *really* put these in monster table
+     */
+    tp->t_stats.s_wisdom = 8 + rnd(7);
+    tp->t_stats.s_const = 8 + rnd(7);
+    tp->t_stats.s_charisma = 8 + rnd(7);
+
+    /* Set the initial flags */
+    for (i=0; i<16; i++) tp->t_flags[i] = 0;
+    for (i=0; i<MAXFLAGS; i++)
+        turn_on(*tp, mp->m_flags[i]);
+
+    /*
+     * these are the base chances that a creatures will do something
+     * assuming it can. These are(or can be) modified at runtime
+     * based on what the creature experiences
+     */
+    tp->t_breathe = 70;         /* base chance of breathing */
+    tp->t_artifact = 90;        /* base chance of using artifact */
+    tp->t_summon = 50;          /* base chance of summoning */
+    tp->t_cast = 70;            /* base chance of casting a spell */
+    tp->t_wand = on(*tp, ISUNIQUE) ? 35 : 50;   /* base chance of using wands */
+
+    /* suprising monsters don't always surprise you */
+    if (!max_monster            && on(*tp, CANSURPRISE) && 
+        off(*tp, ISUNIQUE)      && rnd(100) < 25)
+            turn_off(*tp, CANSURPRISE);
+
+    /* If this monster is unique, gen it */
+    if (on(*tp, ISUNIQUE)) mp->m_normal = FALSE;
+
+    /* 
+     * If it is the quartermaster, then compute his level and exp pts
+     * based on the level. This will make it fair when thieves try to
+     * steal and give them reasonable experience if they succeed.
+     * Then fill his pack with his wares.
+     */
+    if (on(*tp, CANSELL)) {     
+        tp->t_stats.s_exp = vlevel * 100;
+        tp->t_stats.s_lvl = vlevel/2 + 1;
+        make_sell_pack(tp);
+    }
+
+    /* Normally scared monsters have a chance to not be scared */
+    if (on(*tp, ISFLEE) && (rnd(4) == 0)) turn_off(*tp, ISFLEE);
+
+    /* Figure intelligence */
+    min_intel = atoi(mp->m_intel);
+    if ((ip = (char *) strchr(mp->m_intel, '-')) == NULL)
+        tp->t_stats.s_intel = min_intel;
+    else {
+        max_intel = atoi(++ip);
+        if (max_monster)
+            tp->t_stats.s_intel = max_intel;
+        else
+            tp->t_stats.s_intel = min_intel + rnd(max_intel - min_intel);
+    }
+    if (vlevel > HARDER) 
+         tp->t_stats.s_intel += ((vlevel - HARDER)/2);
+    tp->maxstats = tp->t_stats;
+
+    /* If the monster can shoot, it may have a weapon */
+    if (on(*tp, CANSHOOT) && ((rnd(100) < (20 + vlevel)) || max_monster)) {
+        struct linked_list *item1;
+        register struct object *cur, *cur1;
+
+        item = new_item(sizeof *cur);
+        item1 = new_item(sizeof *cur1);
+        cur = OBJPTR(item);
+        cur1 = OBJPTR(item1);
+        cur->o_hplus = (rnd(4) < 3) ? 0
+                                    : (rnd(3) + 1) * ((rnd(3) < 2) ? 1 : -1);
+        cur->o_dplus = (rnd(4) < 3) ? 0
+                                    : (rnd(3) + 1) * ((rnd(3) < 2) ? 1 : -1);
+        cur1->o_hplus = (rnd(4) < 3) ? 0
+                                    : (rnd(3) + 1) * ((rnd(3) < 2) ? 1 : -1);
+        cur1->o_dplus = (rnd(4) < 3) ? 0
+                                    : (rnd(3) + 1) * ((rnd(3) < 2) ? 1 : -1);
+        strcpy(cur->o_damage,"0d0");
+        strcpy(cur->o_hurldmg,"0d0");
+        strcpy(cur1->o_damage,"0d0");
+        strcpy(cur1->o_hurldmg,"0d0");
+        cur->o_ac = cur1->o_ac = 11;
+        cur->o_count = cur1->o_count = 1;
+        cur->o_group = cur1->o_group = 0;
+        cur->contents = cur1->contents = NULL;
+        if ((cur->o_hplus <= 0) && (cur->o_dplus <= 0)) cur->o_flags = ISCURSED;
+        if ((cur1->o_hplus <= 0) && (cur1->o_dplus <= 0))
+            cur1->o_flags = ISCURSED;
+        cur->o_flags = cur1->o_flags = 0;
+        cur->o_type = cur1->o_type = WEAPON;
+        cur->o_mark[0] = cur1->o_mark[0] = '\0';
+
+        /* The monster may use a crossbow, sling, or an arrow */
+        i = rnd(100);
+        if (i < 35) {
+            cur->o_which = CROSSBOW;
+            cur1->o_which = BOLT;
+            init_weapon(cur, CROSSBOW);
+            init_weapon(cur1, BOLT);
+        }
+        else if (i < 70) {
+            cur->o_which = BOW;
+            cur1->o_which = ARROW;
+            init_weapon(cur, BOW);
+            init_weapon(cur1, ARROW);
+        }
+        else {
+            cur->o_which = SLING;
+            cur1->o_which = ROCK;
+            init_weapon(cur, SLING);
+            init_weapon(cur1, ROCK);
+        }
+
+        attach(tp->t_pack, item);
+        attach(tp->t_pack, item1);
+    }
+
+
+    /* Calculate the initial movement rate */
+    updpack(TRUE, tp);
+    tp->t_no_move = movement(tp);
+
+    if (ISWEARING(R_AGGR))
+        runto(tp, &hero);
+
+    if (on(*tp, ISDISGUISE))
+    {
+        char mch = 0;
+
+        if (tp->t_pack != NULL)
+            mch = (OBJPTR(tp->t_pack))->o_type;
+        else
+            switch (rnd(10)) {
+                case 0: mch = GOLD;
+                when 1: mch = POTION;
+                when 2: mch = SCROLL;
+                when 3: mch = FOOD;
+                when 4: mch = WEAPON;
+                when 5: mch = ARMOR;
+                when 6: mch = RING;
+                when 7: mch = STICK;
+                when 8: mch = monsters[randmonster(FALSE, FALSE)].m_appear;
+                when 9: mch = MM;
+            }
+        tp->t_disguise = mch;
+    }
+}
+
+/*
+ * randmonster:
+ *      Pick a monster to show up.  The lower the level,
+ *      the meaner the monster.
+ */
+
+short
+randmonster(wander, no_unique)
+register bool wander, no_unique;
+{
+    register int d, cur_level, range, i; 
+
+    /* 
+     * Do we want a merchant? Merchant is always in place 'NUMMONST' 
+     */
+    if (wander && monsters[NUMMONST].m_wander && rnd(100) < pstats.s_charisma/3)
+        return NUMMONST;
+
+    cur_level = vlevel;
+    range = (4*NLEVMONS)+1;  /* range is 0 thru 12 */
+    i = 0;
+    do
+    {
+        if (i++ > NUMMONST-1) {    /* in case all have be genocided */
+            i = 0;
+            if (--cur_level <= 0)
+                fatal("rogue: Could not find a monster to make! ");
+        }
+        if (levtype == OUTSIDE) {                 /* create DINOSUARS */
+            d = (cur_level - rnd(range/2)) + (NUMMONST-NUMDINOS-1);
+            if (d < NUMMONST-NUMDINOS)
+                d = (NUMMONST-NUMDINOS) + rnd(range/2);
+            if (d > NUMMONST-1)
+                d = (NUMMONST-NUMDINOS) + rnd(NUMDINOS);
+        }
+        else {           /* Create NORMALs and UNIQs here */
+            d = (NLEVMONS*(cur_level-1) + rnd(range) - (range-NLEVMONS-1));
+            if (d < 1) d = rnd(6)+1;
+
+            if (d > NUMMONST-NUMDINOS-1) {    /* Entire range NORMs + UNIQs */
+        if (no_unique)   /* Choose from last 12 NORMAL monsters */
+                    d = (NUMMONST-NUMDINOS-NUMUNIQUE-1) - rnd(NUMUNIQUE/5);
+        else             /* Choose from entire UNIQ monsters + range */
+            d = (NUMMONST-NUMDINOS-1) - rnd(NUMUNIQUE+range);
+            }
+                     /* Half-way into the UNIQs now */
+            else if (d > (NUMMONST-NUMDINOS-(NUMUNIQUE/2)-1)) {
+        if (no_unique)   /* Choose from last 15 NORMAL monsters */
+                    d = (NUMMONST-NUMDINOS-NUMUNIQUE-1) - rnd(NUMUNIQUE/4);
+        else             /* Choose from entire UNIQ monsters + range */
+                    d = (NUMMONST-NUMDINOS-1) - rnd(NUMUNIQUE+range);
+        }
+                     /* End NORMALs and begin relic bearing UNIQs */
+            else if (d > (NUMMONST-NUMDINOS-NUMUNIQUE-1)) {
+        if (no_unique)   /* Choose from last 20 NORMAL monsters */
+                    d = (NUMMONST-NUMDINOS-NUMUNIQUE-1) - rnd(NUMUNIQUE/3);
+        else             /* Choose from first 20 UNIQ monsters */
+                    d = (NUMMONST-NUMDINOS-NUMUNIQUE-1) + rnd(NUMUNIQUE/3);
+        }
+        }
+    }
+    while  (wander ? !monsters[d].m_wander || !monsters[d].m_normal 
+                   : !monsters[d].m_normal);
+    return d;
+}
+
+/* Sell displays a menu of goods from which the player may choose
+ * to purchase something.
+ */
+
+sell(tp)
+register struct thing *tp;
+{
+    register struct linked_list *item, *seller;
+    register struct linked_list *sellpack;
+    register struct object *obj;
+    register long worth, min_worth;
+    char buffer[LINELEN];
+
+    /*
+     * Get a linked_list pointer to the seller.  We need this in case
+     * he disappears so we can set him ISDEAD.
+     */
+    seller = find_mons(tp->t_pos.y, tp->t_pos.x);
+
+    sellpack = tp->t_pack;
+    if (sellpack == NULL) {
+        msg("%s looks puzzled and departs.", prname(monster_name(tp), TRUE));
+
+        /* Get rid of the monster */
+        killed(seller, FALSE, FALSE, FALSE);
+        return;
+    }
+
+    /* See how much the minimum pack item is worth */
+    min_worth = 100000;
+    for (item = sellpack; item != NULL; item = next(item)) {
+        obj = OBJPTR(item);
+        obj->o_flags |= ISPOST; /* Force a long description of the item */
+        worth = get_worth(obj);
+        if (worth < min_worth) min_worth = worth;
+    }
+
+    /* See if player can afford an item */
+    if (min_worth > purse) {
+        msg("%s eyes your small purse and departs.", 
+            prname(monster_name(tp), TRUE));
+
+        /* Get rid of the monster */
+        killed(seller, FALSE, FALSE, FALSE);
+        return;
+    }
+
+    /* Announce our intentions */
+    msg("%s opens his pack.  --More--", prname(monster_name(tp), TRUE));
+    wait_for(' ');
+
+    /* Try to sell something */
+    sprintf(buffer, "You got %ld gold pieces.  Buy", purse);
+    item = get_item(sellpack, buffer, ALL, TRUE, TRUE);
+
+    /* Get rid of the monster */
+    if (item != NULL) detach(tp->t_pack, item); /* Take it out of the pack */
+    killed(seller, FALSE, FALSE, FALSE);
+
+    if (item == NULL) return;
+
+    /* Can he afford the selected item? */
+    obj = OBJPTR(item);
+
+    worth = get_worth(obj);
+    if (worth > purse) {
+        msg("You cannot afford it.");
+        o_discard(item);
+        return;
+    }
+
+    /* Charge him through the nose */
+    purse -= worth;
+
+    /* If a stick or ring, let player know the type */
+    switch (obj->o_type) {
+        case RING:   r_know[obj->o_which]  = TRUE;
+        when POTION: p_know[obj->o_which]  = TRUE;
+        when SCROLL: s_know[obj->o_which]  = TRUE;
+        when STICK:  ws_know[obj->o_which] = TRUE;
+        when MM:     m_know[obj->o_which]  = TRUE;
+
+    }
+
+    /* identify it */
+    whatis (item);
+
+    /* Remove the POST flag that we used for get_item() */
+    obj->o_flags &= ~ISPOST;
+
+    if (add_pack(item, FALSE) == FALSE) {
+        obj->o_pos = hero;
+        fall(item, TRUE);
+    }
+}
+
+/*
+ * what to do when the hero steps next to a monster
+ */
+
+struct linked_list *
+wake_monster(y, x)
+int y, x;
+{
+    register struct thing *tp;
+    register struct linked_list *it;
+    register struct room *trp;
+    register char *mname;
+    bool nasty; /* Will the monster "attack"? */
+
+    if ((it = find_mons(y, x)) == NULL) {
+        msg("Wake:  can't find monster in show (%d, %d)", y, x);
+        return (NULL);
+    }
+    tp = THINGPTR(it);
+    if (on(*tp, ISSTONE)) /* if stoned, don't do anything */
+        return it;
+
+    /*
+     * For now, if we are a friendly monster, we won't do any of
+     * our special effects.
+     */
+    if (on(*tp, ISFRIENDLY)) return it;
+
+    trp = roomin(&tp->t_pos); /* Current room for monster */
+
+    /*
+     * Let greedy ones in a room guard gold
+     * (except in a maze where lots of creatures would all go for the 
+     * same piece of gold)
+     */
+    if (on(*tp, ISGREED) && off(*tp, ISRUN) && levtype != MAZELEV &&
+    trp != NULL && lvl_obj != NULL) {
+            register struct linked_list *item;
+            register struct object *cur;
+
+            for (item = lvl_obj; item != NULL; item = next(item)) {
+                cur = OBJPTR(item);
+                if ((cur->o_type == GOLD) && (roomin(&cur->o_pos) == trp)) {
+                    /* Run to the gold */
+                    runto(tp, &cur->o_pos);
+
+                    /* Make it worth protecting */
+                    cur->o_count += GOLDCALC + GOLDCALC;
+                    break;
+                }
+            }
+    }
+
+    /*
+     * Every time he sees mean monster, it might start chasing him
+     */
+    if (on(*tp, ISMEAN)  && 
+        off(*tp, ISHELD) && 
+        off(*tp, ISRUN)  && 
+        rnd(100) > 35    && 
+        (!is_stealth(&player) || (on(*tp, ISUNIQUE) && rnd(100) > 35)) &&
+        (off(player, ISINVIS) || on(*tp, CANSEE)) ||
+        (trp != NULL && (trp->r_flags & ISTREAS))) {
+        runto(tp, &hero);
+    }
+
+    /*
+     * Get the name; we don't want to do it until here because we need to
+     * know whether the monster is still sleeping or not.
+     */
+    mname = monster_name(tp);
+
+    /* See if the monster will bother the player */
+    nasty = (on(*tp, ISRUN) && cansee(tp->t_pos.y, tp->t_pos.x));
+
+    /*
+     * if the creature is awake and can see the player and the
+     * player has the dreaded "eye of vecna" then see if the
+     * creature is turned to stone
+     */
+    if (cur_relic[EYE_VECNA] && nasty && off(*tp, NOSTONE) &&
+        (off(player, ISINVIS) || on(*tp, CANSEE))) {
+        turn_on(*tp, NOSTONE);  /* only have to save once */
+        if (!save(VS_PETRIFICATION, tp, -2)) {
+                turn_on(*tp, ISSTONE);
+                turn_off(*tp, ISRUN);
+                turn_off(*tp, ISINVIS);
+                turn_off(*tp, CANSURPRISE);
+                turn_off(*tp, ISDISGUISE);
+                msg("%s is turned to stone!", prname(mname, TRUE));
+                return it;
+        }
+    }
+
+    /* 
+     * Handle monsters that can gaze and do things while running
+     * Player must be able to see the monster and the monster must 
+     * not be asleep 
+     */
+    if (nasty && !invisible(tp)) {
+        /*
+         * Confusion
+         */
+        if (on(*tp, CANHUH)                              &&
+           (off(*tp, ISINVIS)     || on(player, CANSEE)) &&
+           (off(*tp, CANSURPRISE) || ISWEARING(R_ALERT))) {
+            if (!save(VS_MAGIC, &player, 0)) {
+                if (off(player, ISCLEAR)) {
+                    if (find_slot(unconfuse))
+                        lengthen(unconfuse, HUHDURATION);
+                    else {
+                        fuse(unconfuse, (VOID *)NULL, HUHDURATION, AFTER);
+                        msg("%s's gaze has confused you.",prname(mname, TRUE));
+                        turn_on(player, ISHUH);
+                    }
+                }
+                else msg("You feel dizzy for a moment, but it quickly passes.");
+            }
+            else if (rnd(100) < 67)
+                turn_off(*tp, CANHUH); /* Once you save, maybe that's it */
+        }
+
+        /* Sleep */
+        if(on(*tp, CANSNORE) &&  
+           player.t_action != A_FREEZE && 
+           !save(VS_PARALYZATION, &player, 0)) {
+            if (ISWEARING(R_ALERT))
+                msg("You feel drowsy for a moment.. ");
+            else {
+                msg("%s's gaze puts you to sleep! ", prname(mname, TRUE));
+                player.t_no_move += movement(&player) * SLEEPTIME;
+                player.t_action = A_FREEZE;
+                if (rnd(100) < 50) turn_off(*tp, CANSNORE);
+            }
+        }
+
+        /* Fear */
+        if (on(*tp, CANFRIGHTEN) && !on(player, ISFLEE)) {
+            turn_off(*tp, CANFRIGHTEN);
+            if (!ISWEARING(R_HEROISM) && 
+                !save(VS_WAND, &player, -(tp->t_stats.s_lvl/10))) {
+                    turn_on(player, ISFLEE);
+                    player.t_dest = &tp->t_pos;
+                    msg("The sight of %s terrifies you!", prname(mname, FALSE));
+            }
+        }
+
+        /* blinding creatures */
+        if(on(*tp, CANBLIND) && !find_slot(sight)) {
+            turn_off(*tp, CANBLIND);
+            if (!save(VS_WAND, &player, 0)) {
+                msg("The gaze of %s blinds you! ", prname(mname, FALSE));
+                turn_on(player, ISBLIND);
+                fuse(sight, (VOID *)NULL, rnd(30)+20, AFTER);
+                light(&hero);
+            }
+        }
+
+        /* the sight of the ghost can age you! */
+        if (on(*tp, CANAGE)) { 
+            turn_off (*tp, CANAGE);
+            if (!save(VS_MAGIC, &player, 0)) {
+                msg ("The sight of %s ages you!", prname(mname, FALSE));
+                pstats.s_const--;
+                /* max_stats.s_const--; */
+                if (pstats.s_const < 1) {
+            pstats.s_hpt = -1;
+                    death (D_CONSTITUTION);
+        }
+            }
+        }
+
+        /* Turning to stone */
+        if (on(*tp, LOOKSTONE)) {
+            turn_off(*tp, LOOKSTONE);
+
+            if (on(player, CANINWALL))
+                msg("The gaze of %s has no effect.", prname(mname, FALSE));
+            else {
+                if (!save(VS_PETRIFICATION, &player, 0) && rnd(100) < 5) {
+                    pstats.s_hpt = -1;
+                    msg("The gaze of %s petrifies you!", prname(mname, FALSE));
+                    msg("You are turned to stone!!!  --More--");
+                    wait_for(' ');
+                    death(D_PETRIFY);
+                }
+                else {
+                    msg("The gaze of %s stiffens your limbs.", 
+                        prname(mname, FALSE));
+                    player.t_no_move += movement(&player) * STONETIME;
+                    player.t_action = A_FREEZE;
+                }
+            }
+        }
+    }
+
+    return it;
+}
+/*
+ * wanderer:
+ *      A wandering monster has awakened and is headed for the player
+ */
+
+wanderer()
+{
+    register int i;
+    register struct room *hr = roomin(&hero);
+    register struct linked_list *item;
+    register struct thing *tp;
+    register long *attr;        /* Points to monsters' attributes */
+    int carry;  /* Chance of wanderer carrying anything */
+    short rmonst;       /* Our random wanderer */
+    bool canteleport = FALSE,   /* Can the monster teleport? */
+         seehim;        /* Is monster within sight? */
+    coord cp;
+
+    rmonst = randmonster(TRUE, FALSE);  /* Choose a random wanderer */
+    attr = &monsters[rmonst].m_flags[0]; /* Start of attributes */
+    for (i=0; i<MAXFLAGS; i++)
+        if (*attr++ == CANTELEPORT) {
+            canteleport = TRUE;
+            break;
+        }
+
+    /* Find a place for it -- avoid the player's room if can't teleport */
+    do {
+        do {
+            i = rnd_room();
+        } until (canteleport || hr != &rooms[i] || levtype == MAZELEV ||
+                 levtype == OUTSIDE);
+
+        /* Make sure the monster does not teleport on top of the player */
+        do {
+            rnd_pos(&rooms[i], &cp);
+        } while (hr == &rooms[i] && ce(cp, hero));
+    } until (step_ok(cp.y, cp.x, NOMONST, (struct thing *)NULL));
+
+    /* Create a new wandering monster */
+    item = new_item(sizeof *tp);
+    new_monster(item, rmonst, &cp, FALSE);
+    tp = THINGPTR(item);
+    runto(tp, &hero);
+    tp->t_pos = cp;     /* Assign the position to the monster */
+    seehim = cansee(tp->t_pos.y, tp->t_pos.x);
+    if (on(*tp, HASFIRE)) {
+        register struct room *rp;
+
+        rp = roomin(&tp->t_pos);
+        if (rp) {
+            register struct linked_list *fire_item;
+
+            fire_item = creat_item();
+            ldata(fire_item) = (char *) tp;
+            attach(rp->r_fires, fire_item);
+
+            rp->r_flags |= HASFIRE;
+            if (seehim && next(rp->r_fires) == NULL)
+                light(&hero);
+        }
+    }
+
+    /* See if we give the monster anything */
+    carry = monsters[tp->t_index].m_carry;
+    if (off(*tp, ISUNIQUE)) carry /= 2; /* Non-unique has only a half chance */
+    carry_obj(tp, carry);
+
+    /* Calculate its movement rate */
+    tp->t_no_move = movement(tp);
+
+    /* Alert the player if a monster just teleported in */
+    if (hr == &rooms[i] && canteleport && seehim && !invisible(tp)) {
+        msg("A %s just teleported in", monster_name(tp));
+        light(&hero);
+        running = FALSE;
+    }
+
+    if (wizard)
+        msg("Started a wandering %s", monster_name(tp));
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xrogue/move.c	Tue Apr 21 08:55:20 2015 -0400
@@ -0,0 +1,1910 @@
+/*
+    move.c - Hero movement commands
+
+    XRogue: Expeditions into the Dungeons of Doom
+    Copyright (C) 1991 Robert Pietkivitch
+    All rights reserved.
+    
+    Based on "Advanced Rogue"
+    Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka and AT&T
+    All rights reserved.
+
+    Based on "Rogue: Exploring the Dungeons of Doom"
+    Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
+    All rights reserved.
+    
+    See the file LICENSE.TXT for full copyright and licensing information.
+*/
+
+#include <curses.h>
+#include <ctype.h>
+#include "rogue.h"
+
+/*
+ * Used to hold the new hero position
+ */
+
+coord move_nh;
+
+static char Moves[3][3] = {
+    { 'y', 'k', 'u' },
+    { 'h', '.', 'l' },
+    { 'b', 'j', 'n' }
+};
+
+/*
+ * be_trapped:
+ *      The guy stepped on a trap.... Make him pay.
+ */
+
+be_trapped(th, tc)
+register struct thing *th;
+register coord *tc;
+{
+    register struct trap *tp;
+    register char ch, *mname = NULL;
+    register bool is_player = (th == &player),
+                  can_see;
+    register struct linked_list *mitem = NULL;
+    register struct thing *mp;
+
+
+    /* Can the player see the creature? */
+    can_see = cansee(tc->y, tc->x);
+    can_see &= (is_player || !invisible(th));
+
+    tp = trap_at(tc->y, tc->x);
+    /*
+     * if he's wearing boots of elvenkind, he won't set off the trap
+     * unless its a magic pool (they're not really traps)
+     */
+    if (is_player                                       &&
+        cur_misc[WEAR_BOOTS] != NULL                    &&
+        cur_misc[WEAR_BOOTS]->o_which == MM_ELF_BOOTS   &&
+        tp->tr_type != POOL)
+            return '\0';
+
+    /*
+     * if the creature is flying then it won't set off the trap
+     */
+     if (on(*th, ISFLY))
+        return '\0';
+
+    tp->tr_flags |= ISFOUND;
+
+    if (!is_player) {
+        mitem = find_mons(th->t_pos.y, th->t_pos.x);
+        mname = monster_name(th);
+    }
+    else {
+        count = running = FALSE;
+        mvwaddch(cw, tp->tr_pos.y, tp->tr_pos.x, tp->tr_type);
+    }
+    switch (ch = tp->tr_type) {
+        case TRAPDOOR:
+            if (is_player) {
+                level++;
+                pstats.s_hpt -= roll(1, 10);
+                msg("You fell through a trap! ");
+                if (pstats.s_hpt < 1) {
+            pstats.s_hpt = -1;
+            death(D_FALL);
+        }
+        wclear(cw);
+        wclear(mw);
+                new_level(NORMLEV);
+            }
+            else {
+                if (can_see) msg("%s fell into a trap!", prname(mname, TRUE));
+
+                /* 
+                 * See if the fall killed the monster 
+                 * don't let a UNIQUE die since it might have an artifact
+                 * that we need
+                 */
+                if (off(*th,ISUNIQUE) && (th->t_stats.s_hpt-=roll(1,10)) <= 0){
+                    killed(mitem, FALSE, FALSE, FALSE);
+                }
+                else {  /* Just move monster to next level */
+                    check_residue(th);
+
+                    /* Erase the monster from the old position */
+                    if (isalpha(mvwinch(cw, th->t_pos.y, th->t_pos.x)))
+                        mvwaddch(cw, th->t_pos.y, th->t_pos.x, th->t_oldch);
+                    mvwaddch(mw, th->t_pos.y, th->t_pos.x, ' ');
+
+                    /* let him summon on next lvl */
+                    if (on (*th, HASSUMMONED)) {
+                            turn_off(*th, HASSUMMONED); 
+                            turn_on(*th, CANSUMMON);
+                    }
+                    turn_on(*th,ISELSEWHERE);
+                    detach(mlist, mitem);
+                    attach(tlist, mitem);       /* remember him next level */
+
+                    /* Make sure that no one is still chasing us */
+                    for (mitem = mlist; mitem != NULL; mitem = next(mitem)) {
+                        mp = THINGPTR(mitem);
+                        if (mp->t_dest == &th->t_pos) {
+                            mp->t_dest = &hero;
+                            mp->t_wasshot = FALSE;
+                            turn_off(*mp, ISFLEE);      /* Don't run away! */
+                        }
+                    }
+
+                    /* Make sure we were not chasing a monster here */
+                    th->t_dest = &hero;
+                    if (on(*th, ISFRIENDLY)) turn_off(*th, ISFLEE);
+                }
+            }
+        /* worm hole trap to OUTSIDE */
+        when WORMHOLE:
+            if (is_player) {
+                prev_max = 1000;    /* flag used in n_level.c */
+        level++;
+                msg("You suddenly find yourself in strange surroundings! ");
+                pstats.s_hpt -= roll(1, 10);
+                if (pstats.s_hpt < 1) {
+            pstats.s_hpt = -1;
+            death(D_FALL);
+        }
+                new_level(OUTSIDE);
+        return(ch);
+            }
+            else {
+                if (can_see) msg("%s fell into the worm hole! ", prname(mname, TRUE));
+
+                /* 
+                 * See if the fall killed the monster 
+                 * don't let a UNIQUE die since it might have an artifact
+                 * that we need
+                 */
+                if (off(*th,ISUNIQUE) && (th->t_stats.s_hpt-=roll(1,10)) <= 0){
+                    killed(mitem, FALSE, FALSE, FALSE);
+                }
+                else {  /* Just move monster to next level */
+                    check_residue(th);
+
+                    /* Erase the monster from the old position */
+                    if (isalpha(mvwinch(cw, th->t_pos.y, th->t_pos.x)))
+                        mvwaddch(cw, th->t_pos.y, th->t_pos.x, th->t_oldch);
+                    mvwaddch(mw, th->t_pos.y, th->t_pos.x, ' ');
+
+                    /* let him summon on next lvl */
+                    if (on (*th, HASSUMMONED)) {
+                            turn_off(*th, HASSUMMONED); 
+                            turn_on(*th, CANSUMMON);
+                    }
+
+                    turn_on(*th,ISELSEWHERE);
+                    detach(mlist, mitem);
+                    attach(tlist, mitem);       /* remember him next level */
+
+                    /* Make sure that no one is still chasing us */
+                    for (mitem = mlist; mitem != NULL; mitem = next(mitem)) {
+                        mp = THINGPTR(mitem);
+                        if (mp->t_dest == &th->t_pos) {
+                            mp->t_dest = &hero;
+                            mp->t_wasshot = FALSE;
+                            turn_off(*mp, ISFLEE);      /* Don't run away! */
+                        }
+                    }
+
+                    /* Make sure we were not chasing a monster here */
+                    th->t_dest = &hero;
+                    if (on(*th, ISFRIENDLY)) turn_off(*th, ISFLEE);
+                }
+            }
+        when BEARTRAP:
+            if (is_stealth(th)) {
+                if (is_player) msg("You pass a bear trap.");
+                else if (can_see) msg("%s passes a bear trap.", 
+                                      prname(mname, TRUE));
+            }
+            else {
+                th->t_no_move += movement(&player) * BEARTIME;
+                th->t_action = A_FREEZE;
+                if (is_player) msg("You are caught in a bear trap.");
+                else if (can_see) msg("%s is caught in a bear trap.",
+                                        prname(mname, TRUE));
+            }
+        when SLEEPTRAP:
+            if (is_player) {
+                if (!ISWEARING(R_ALERT)) {
+                    msg("A strange white mist envelops you.  You fall asleep. ");
+                    player.t_no_move += movement(&player) * SLEEPTIME;
+                    player.t_action = A_FREEZE;
+                }
+        else {
+            msg("The white mist invigorates you. ");
+        }
+            }
+            else {
+                if (can_see) 
+                    msg("A strange white mist envelops %s. ",
+                        prname(mname, FALSE));
+                if (on(*th, ISUNDEAD)) {
+                    if (can_see) 
+                        msg("The mist doesn't seem to affect %s.",
+                           prname(mname, FALSE));
+                }
+                else {
+                    th->t_no_move += movement(th) * SLEEPTIME;
+                    th->t_action = A_FREEZE;
+                }
+            }
+        when ARROWTRAP:
+            if (swing(th->t_ctype, th->t_stats.s_lvl-1, th->t_stats.s_arm, 1))
+            {
+                if (is_player) {
+                    msg("Oh no! An arrow shot you.");
+                    if ((pstats.s_hpt -= roll(1, 8)) < 1) {
+            pstats.s_hpt = -1;
+                        msg("The arrow killed you.  --More--");
+            wait_for(' ');
+                        death(D_ARROW);
+                    }
+                }
+                else {
+                    if (can_see) 
+                        msg("An arrow shot %s.", prname(mname, FALSE));
+                    if ((th->t_stats.s_hpt -= roll(1, 8)) < 1) {
+                        if (can_see) 
+                            msg("The arrow killed %s.", prname(mname, FALSE));
+                        killed(mitem, FALSE, FALSE, TRUE);
+                    }
+                }
+            }
+            else
+            {
+                register struct linked_list *item;
+                register struct object *arrow;
+
+                if (is_player) msg("An arrow shoots past you.");
+                else if (can_see) 
+                      msg("An arrow shoots by %s.", prname(mname, FALSE));
+                item = new_item(sizeof *arrow);
+                arrow = OBJPTR(item);
+                arrow->o_type = WEAPON;
+                arrow->contents = NULL;
+                arrow->o_which = ARROW;
+                arrow->o_hplus = rnd(7) - 1;
+                arrow->o_dplus = rnd(7) - 1;
+                init_weapon(arrow, ARROW);
+                arrow->o_count = 1;
+                arrow->o_pos = *tc;
+                arrow->o_mark[0] = '\0';
+                fall(item, FALSE);
+            }
+        when TELTRAP:
+            if (is_player) teleport();
+            else {
+                register int rm;
+                struct room *old_room;  /* old room of monster */
+
+                /* 
+                 * Erase the monster from the old position 
+                 */
+                if (isalpha(mvwinch(cw, th->t_pos.y, th->t_pos.x)))
+                    mvwaddch(cw, th->t_pos.y, th->t_pos.x, th->t_oldch);
+                mvwaddch(mw, th->t_pos.y, th->t_pos.x, ' ');
+                /*
+                 * check to see if room should go dark
+                 */
+                if (on(*th, HASFIRE)) {
+                    old_room=roomin(&th->t_pos);
+                    if (old_room != NULL) {
+                        register struct linked_list *fire_item;
+
+                        for (fire_item = old_room->r_fires; fire_item != NULL;
+                             fire_item = next(fire_item)) {
+                            if (THINGPTR(fire_item) == th) {
+                                detach(old_room->r_fires, fire_item);
+                                destroy_item(fire_item);
+
+                                if (old_room->r_fires == NULL) {
+                                    old_room->r_flags &= ~HASFIRE;
+                                    if (can_see) light(&hero);
+                                }
+                            }
+                        }
+                    }
+                }
+
+                /* Get a new position */
+                do {
+                    rm = rnd_room();
+                    rnd_pos(&rooms[rm], &th->t_pos);
+                } until(winat(th->t_pos.y, th->t_pos.x) == FLOOR);
+
+                /* Put it there */
+                mvwaddch(mw, th->t_pos.y, th->t_pos.x, th->t_type);
+                th->t_oldch = mvwinch(cw, th->t_pos.y, th->t_pos.x);
+                /*
+                 * check to see if room that creature appears in should
+                 * light up
+                 */
+                if (on(*th, HASFIRE)) {
+                    register struct linked_list *fire_item;
+
+                    fire_item = creat_item();
+                    ldata(fire_item) = (char *) th;
+                    attach(rooms[rm].r_fires, fire_item);
+
+                    rooms[rm].r_flags |= HASFIRE;
+                    if(cansee(th->t_pos.y, th->t_pos.x) && 
+                       next(rooms[rm].r_fires) == NULL)
+                        light(&hero);
+                }
+                if (can_see) 
+                    msg("%s seems to have disappeared!", prname(mname, TRUE));
+            }
+        when DARTTRAP:
+            if (swing(th->t_ctype, th->t_stats.s_lvl+1, th->t_stats.s_arm, 1)) {
+                if (is_player) {
+                    msg("A small dart just hit you. ");
+                    if ((pstats.s_hpt -= roll(1, 8)) < 1) {
+            pstats.s_hpt = -1;
+                        msg("The dart killed you.");
+            wait_for(' ');
+                        death(D_DART);
+                    }
+
+                    /* Now the poison */
+                    if (!save(VS_POISON, &player, 0)) {
+                        /* 75% chance it will do point damage - else strength */
+                        if (rnd(100) < 75) {
+                            pstats.s_hpt /= 2;
+                            if (pstats.s_hpt < 1) {
+                pstats.s_hpt = -1;
+                death(D_POISON);
+                }
+                        }
+                        else if (!ISWEARING(R_SUSABILITY))
+                                chg_str(-1);
+                    }
+                }
+                else {
+                    if (can_see)
+                        msg("A small dart stabs the %s. ",
+                                prname(mname, FALSE));
+                    if ((th->t_stats.s_hpt -= roll(1,8)) < 1) {
+                        if (can_see) 
+                            msg("The dart killed %s.", prname(mname, FALSE));
+                        killed(mitem, FALSE, FALSE, TRUE);
+                    }
+                    if (!save(VS_POISON, th, 0)) {
+                        th->t_stats.s_hpt /= 2 + level;
+                        if (th->t_stats.s_hpt < 1) {
+                            if (can_see) 
+                                msg("The dart killed %s.", prname(mname,FALSE));
+                            killed(mitem, FALSE, FALSE, TRUE);
+                        }
+                    }
+                }
+            }
+            else {
+                if (is_player)
+                    msg("A small dart whizzes by your ear and vanishes.");
+                else if (can_see)
+                    msg("A small dart whizzes by %s's ear and vanishes.",
+                        prname(mname, FALSE));
+            }
+        when POOL: {
+            register int i;
+
+            i = rnd(100);
+            if (is_player) {
+                if ((tp->tr_flags & ISGONE)) {
+                    if (i < 56) {
+                        teleport();        /* teleport away */
+                        pool_teleport = TRUE;
+                    }
+                    else if((i < 72) && level > 4) {
+                        level -= rnd(4) + 1;
+                        cur_max = level;
+                        new_level(NORMLEV);
+                        pool_teleport = TRUE;
+                        msg("You here a faint groan from below.");
+                    }
+                    else if(i < 85) {
+                        level += rnd(4) + 1;
+                        new_level(NORMLEV);
+                        pool_teleport = TRUE;
+                        msg("You find yourself in strange surroundings.");
+                    }
+                    else if(i > 96) {
+                        msg("Oh no!!! You drown in the pool!!!  --More--");
+                        wait_for(' ');
+            pstats.s_hpt = -1;
+                        death(D_DROWN);
+                    }
+            else {
+            new_level(NORMLEV);
+            pool_teleport = TRUE;
+            msg("You are whisked away to another region.");
+            }
+                }
+            }
+            else {
+                if (i < 60) {
+                    if (can_see) {
+                        /* Drowns */
+                        if (i < 50) 
+                            msg("%s drowned in the pool!", prname(mname, TRUE));
+
+                        /* Teleported to another level */
+                        else msg("%s disappeared!", prname(mname, TRUE));
+                    }
+                    killed(mitem, FALSE, FALSE, TRUE);
+                }
+            }
+        }
+    when MAZETRAP:
+        if (is_player) {
+            pstats.s_hpt -= roll(1, 10);
+            level++;
+            if (pstats.s_hpt < 1) {
+        pstats.s_hpt = -1;
+        death(D_FALL);
+        }
+        wclear(cw);
+        wclear(mw);
+            new_level(MAZELEV);
+            msg("You are surrounded by twisty passages! ");
+        }
+        else {
+            if (can_see) msg("%s fell into a maze trap!", prname(mname, TRUE));
+            if (on(*th, ISUNIQUE)) {
+                    check_residue(th);
+
+                    /* Erase the monster from the old position */
+                    if (isalpha(mvwinch(cw, th->t_pos.y, th->t_pos.x)))
+                        mvwaddch(cw, th->t_pos.y, th->t_pos.x, th->t_oldch);
+                    mvwaddch(mw, th->t_pos.y, th->t_pos.x, ' ');
+
+                    /* let him summon on next lvl */
+                    if (on (*th, HASSUMMONED)) {
+                            turn_off(*th, HASSUMMONED); 
+                            turn_on(*th, CANSUMMON);
+                    }
+                    turn_on(*th,ISELSEWHERE);
+                    detach(mlist, mitem);
+                    attach(tlist, mitem);       /* remember him next level */
+
+                    /* Make sure that no one is still chasing us */
+                    for (mitem = mlist; mitem != NULL; mitem = next(mitem)) {
+                        mp = THINGPTR(mitem);
+                        if (mp->t_dest == &th->t_pos) {
+                            mp->t_dest = &hero;
+                            mp->t_wasshot = FALSE;
+                            turn_off(*mp, ISFLEE);      /* Don't run away! */
+                        }
+                    }
+
+                    /* Make sure we were not chasing a monster here */
+                    th->t_dest = &hero;
+                    if (on(*th, ISFRIENDLY)) turn_off(*th, ISFLEE);
+            }
+            else
+                    killed(mitem, FALSE, FALSE, FALSE);
+        }
+    }
+
+    /* Move the cursor back onto the hero */
+    wmove(cw, hero.y, hero.x);
+
+    flushinp();
+    return(ch);
+}
+
+/*
+ * blue_light:
+ *      magically light up a room (or level or make it dark)
+ */
+
+bool
+blue_light(blessed, cursed)
+bool blessed, cursed;
+{
+    register struct room *rp;
+    bool ret_val=FALSE; /* Whether or not affect is known */
+
+    rp = roomin(&hero); /* What room is hero in? */
+
+    /* Darken the room if the magic is cursed */
+    if (cursed) {
+        if ((rp == NULL) || !lit_room(rp)) msg(nothing);
+        else {
+            rp->r_flags |= ISDARK;
+            if (!lit_room(rp) && (levtype != OUTSIDE || !daytime) &&
+        !ISWEARING(R_LIGHT)) 
+                msg("The %s suddenly goes dark.",
+                    levtype == OUTSIDE ? "area" : "room");
+            else msg(nothing);
+            ret_val = TRUE;
+        }
+    }
+    else {
+        ret_val = TRUE;
+        if (rp && !lit_room(rp) &&
+            (levtype != OUTSIDE || !daytime)) {
+            addmsg("The %s is lit", levtype == OUTSIDE ? "area" : "room");
+            addmsg(" by a %s blue light.", blessed ? "bright" : "shimmering");
+            endmsg();
+        }
+        else if (winat(hero.y, hero.x) == PASSAGE)
+            msg("The corridor glows %sand then fades",
+                    blessed ? "brightly " : "");
+        else {
+            ret_val = FALSE;
+            msg(nothing);
+        }
+        if (blessed) {
+            register int i;     /* Index through rooms */
+
+            for (i=0; i<MAXROOMS; i++)
+                rooms[i].r_flags &= ~ISDARK;
+        }
+        else if (rp) rp->r_flags &= ~ISDARK;
+    }
+
+    /*
+     * Light the room and put the player back up
+     */
+    light(&hero);
+    mvwaddch(cw, hero.y, hero.x, PLAYER);
+    return(ret_val);
+}
+
+/*
+ * corr_move:
+ *      Check to see that a move is legal.  If so, return correct character.
+ *      If not, if player came from a legal place, then try to turn him.
+ */
+
+corr_move(dy, dx)
+int dy, dx;
+{
+    int legal=0;                /* Number of legal alternatives */
+    register int y, x,          /* Indexes though possible positions */
+                 locy = 0, locx = 0;    /* Hold delta of chosen location */
+
+    /* New position */
+    move_nh.y = hero.y + dy;
+    move_nh.x = hero.x + dx;
+
+    /* If it is a legal move, just return */
+    if (move_nh.x >= 0 && move_nh.x < cols && move_nh.y > 0 && move_nh.y < lines - 2) {
+        
+        switch (winat(move_nh.y, move_nh.x)) {
+            case WALL:
+            case VERTWALL:
+            case HORZWALL:
+                break;
+            default:
+                if (diag_ok(&hero, &move_nh, &player))
+                        return;
+        }
+    }
+
+    /* Check legal places surrounding the player -- ignore previous position */
+    for (y = hero.y - 1; y <= hero.y + 1; y++) {
+        if (y < 1 || y > lines - 3)
+            continue;
+        for (x = hero.x - 1; x <= hero.x + 1; x++) {
+            /* Ignore borders of the screen */
+            if (x < 0 || x > cols - 1)
+                continue;
+            
+            /* 
+             * Ignore where we came from, where we are, and where we couldn't go
+             */
+            if ((x == hero.x - dx && y == hero.y - dy) ||
+                (x == hero.x + dx && y == hero.y + dy) ||
+                (x == hero.x && y == hero.y))
+                continue;
+
+            switch (winat(y, x)) {
+                case WALL:
+                case VERTWALL:
+                case HORZWALL:
+                    break;
+                default:
+                    move_nh.y = y;
+                    move_nh.x = x;
+                    if (diag_ok(&hero, &move_nh, &player)) {
+                        legal++;
+                        locy = y - (hero.y - 1);
+                        locx = x - (hero.x - 1);
+                    }
+            }
+        }
+    }
+
+    /* If we have 2 or more legal moves, make no change */
+    if (legal != 1) {
+        return;
+    }
+
+    runch = Moves[locy][locx];
+
+    /*
+     * For mazes, pretend like it is the beginning of a new run at each turn
+     * in order to get the lighting correct.
+     */
+    if (levtype == MAZELEV) firstmove = TRUE;
+    return;
+}
+
+/*
+ * dip_it:
+ *      Dip an object into a magic pool
+ */
+
+dip_it()
+{
+        reg struct linked_list *what;
+        reg struct object *ob;
+        reg struct trap *tp;
+        reg int wh, i;
+
+        tp = trap_at(hero.y,hero.x);
+        if (tp == NULL || tp->tr_type != POOL) {
+            msg("I see no shimmering pool here");
+            return;
+        }
+        if (tp->tr_flags & ISGONE) {
+            msg("This shimmering pool appears to have been used once already.");
+            return;
+        }
+
+        /* It takes 3 movement periods to dip something */
+        if (player.t_action != C_DIP) {
+            if ((what = get_item(pack, "dip", ALL, FALSE, FALSE)) == NULL) {
+                msg("");
+                after = FALSE;
+                return;
+            }
+
+            ob = OBJPTR(what);
+            if (ob == cur_armor               || 
+                ob == cur_misc[WEAR_BOOTS]    ||
+                ob == cur_misc[WEAR_JEWEL]    ||
+                ob == cur_misc[WEAR_GAUNTLET] ||
+                ob == cur_misc[WEAR_CLOAK]    ||
+                ob == cur_misc[WEAR_BRACERS]  ||
+                ob == cur_misc[WEAR_NECKLACE] ||
+                ob == cur_ring[LEFT_1]  || ob == cur_ring[LEFT_2]  ||
+                ob == cur_ring[LEFT_3]  || ob == cur_ring[LEFT_4]  ||
+                ob == cur_ring[RIGHT_1] || ob == cur_ring[RIGHT_2] ||
+        ob == cur_ring[RIGHT_3] || ob == cur_ring[RIGHT_4]) {
+                mpos = 0;
+                msg("You'll have to take it off first.");
+                return;
+            }
+
+            player.t_using = what;      /* Remember what it is */
+            player.t_action = C_DIP;    /* We are dipping */
+            player.t_no_move = 3 * movement(&player);
+            return;
+        }
+
+        /* We have waited our time, let's dip it */
+        what = player.t_using;
+        player.t_using = NULL;
+        player.t_action = A_NIL;
+
+        ob = OBJPTR(what);
+
+        tp->tr_flags |= ISGONE;
+        if (ob != NULL) {
+            wh = ob->o_which;
+            ob->o_flags |= ISKNOW;
+            i = rnd(100);
+            if (ob->o_group != 0)
+                ob->o_group = newgrp(); /* change the group */
+            switch(ob->o_type) {
+                case WEAPON:
+                    if(i < 60) {                /* enchant weapon here */
+                        if ((ob->o_flags & ISCURSED) == 0) {
+                                ob->o_hplus += 1;
+                                ob->o_dplus += 1;
+                        }
+                        else {          /* weapon was prev cursed here */
+                                ob->o_hplus = rnd(2);
+                                ob->o_dplus = rnd(2);
+                        }
+                        ob->o_flags &= ~ISCURSED;
+                        msg("The %s glows blue for a moment.",weaps[wh].w_name);
+                    }
+                    else if(i < 75) {   /* curse weapon here */
+                        if ((ob->o_flags & ISCURSED) == 0) {
+                                ob->o_hplus = -(rnd(2)+1);
+                                ob->o_dplus = -(rnd(2)+1);
+                        }
+                        else {                  /* if already cursed */
+                                ob->o_hplus--;
+                                ob->o_dplus--;
+                        }
+                        ob->o_flags |= ISCURSED;
+                        msg("The %s glows red for a moment.",weaps[wh].w_name);
+                    }                   
+                    else
+                        msg(nothing);
+                when ARMOR:
+                    if (i < 60) {       /* enchant armor */
+                        if((ob->o_flags & ISCURSED) == 0)
+                            ob->o_ac -= rnd(2) + 1;
+                        else
+                            ob->o_ac = -rnd(3)+ armors[wh].a_class;
+                        ob->o_flags &= ~ISCURSED;
+                        msg("The %s glows blue for a moment",armors[wh].a_name);
+                    }
+                    else if(i < 75){    /* curse armor */
+                        if ((ob->o_flags & ISCURSED) == 0)
+                            ob->o_ac = rnd(3)+ armors[wh].a_class;
+                        else
+                            ob->o_ac += rnd(2) + 1;
+                        ob->o_flags |= ISCURSED;
+                        msg("The %s glows red for a moment.",armors[wh].a_name);
+                    }
+                    else
+                        msg(nothing);
+                when STICK: {
+                    int j;
+                    j = rnd(14) + 1;
+                    if(i < 60) {                /* add charges */
+                        ob->o_charges += j;
+                        ws_know[wh] = TRUE;
+                        if (ob->o_flags & ISCURSED)
+                            ob->o_flags &= ~ISCURSED;
+                        msg("The %s %s glows blue for a moment.",
+                            ws_made[wh],ws_type[wh]);
+                    }
+                    else if(i < 75) {   /* remove charges */
+                        if ((ob->o_charges -= i) < 0)
+                            ob->o_charges = 0;
+                        ws_know[wh] = TRUE;
+                        if (ob->o_flags & ISBLESSED)
+                            ob->o_flags &= ~ISBLESSED;
+                        else
+                            ob->o_flags |= ISCURSED;
+                        msg("The %s %s glows red for a moment.",
+                            ws_made[wh],ws_type[wh]);
+                    }
+                    else 
+                        msg(nothing);
+                }
+                when SCROLL:
+                    s_know[wh] = TRUE;
+                    msg("The '%s' scroll unfurls.",s_names[wh]);
+                when POTION:
+                    p_know[wh] = TRUE;
+                    msg("The %s potion bubbles for a moment.. ",p_colors[wh]);
+                when RING:
+                    if(i < 60) {         /* enchant ring */
+                        if ((ob->o_flags & ISCURSED) == 0)
+                            ob->o_ac += rnd(2) + 1;
+                        else
+                            ob->o_ac = rnd(2) + 1;
+                        ob->o_flags &= ~ISCURSED;
+                    }
+                    else if(i < 75) { /* curse ring */
+                        if ((ob->o_flags & ISCURSED) == 0)
+                            ob->o_ac = -(rnd(2) + 1);
+                        else
+                            ob->o_ac -= (rnd(2) + 1);
+                        ob->o_flags |= ISCURSED;
+                    }
+                    r_know[wh] = TRUE;
+                    msg("The %s ring vibrates for a moment.",r_stones[wh]);
+                when MM:
+                    m_know[wh] = TRUE;
+                    switch (ob->o_which) {
+                    case MM_BRACERS:
+                    case MM_PROTECT:
+                        if(i < 60) {     /* enchant item */
+                            if ((ob->o_flags & ISCURSED) == 0)
+                                ob->o_ac += rnd(2) + 1;
+                            else
+                                ob->o_ac = rnd(2) + 1;
+                            ob->o_flags &= ~ISCURSED;
+                        }
+                        else if(i < 75) { /* curse item */
+                            if ((ob->o_flags & ISCURSED) == 0)
+                                ob->o_ac = -(rnd(2) + 1);
+                            else
+                                ob->o_ac -= (rnd(2) + 1);
+                            ob->o_flags |= ISCURSED;
+                        }
+                        msg("The item vibrates for a moment.");
+                    when MM_CHOKE:
+                    case MM_DISAPPEAR:
+                        ob->o_ac = 0;
+                        msg ("The dust dissolves in the pool!");
+                    }
+                otherwise:
+                msg("The pool bubbles up for a moment.. ");
+            }
+            updpack(FALSE, &player);
+        }
+        else
+            msg(nothing);
+}
+
+/*
+ * do_move:
+ *      Check to see that a move is legal.  If it is handle the
+ * consequences (fighting, picking up, etc.)
+ */
+
+do_move(dy, dx)
+int dy, dx;
+{
+    register struct room *rp, *orp;
+    register unsigned char ch;
+    struct linked_list *item;
+    register struct thing *tp = NULL;
+    coord old_hero;
+    register int wasfirstmove, moved, num_hits;
+    bool changed=FALSE;   /* Did we switch places with a friendly monster? */
+
+    wasfirstmove = firstmove;
+    firstmove = FALSE;
+    curprice = -1;        /* if in trading post, we've moved off obj */
+
+    /*
+     * Do a confused move (maybe)
+     */
+    if (player.t_action == A_NIL &&
+        ((on(player, ISHUH) && rnd(100) < 80)   || 
+         (on(player, ISDANCE) && rnd(100) < 90) || 
+         (ISWEARING(R_DELUSION) && rnd(100) < 70)))
+    {
+        /* Get a random move */
+        move_nh = rndmove(&player);
+        dy = move_nh.y - hero.y;
+        dx = move_nh.x - hero.x;
+    }
+    else {
+        move_nh.y = hero.y + dy;
+        move_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 (move_nh.x < 0 || move_nh.x > cols-1 || move_nh.y < 1 || move_nh.y >= lines - 2
+        || !diag_ok(&hero, &move_nh, &player))
+    {
+        after = running = FALSE;
+        player.t_action = A_NIL;
+        return;
+    }
+    if (running && ce(hero, move_nh))
+        after = running = FALSE;
+    ch = winat(move_nh.y, move_nh.x);
+
+    /* Take care of hero trying to move close to something frightening */
+    if (on(player, ISFLEE)) {
+        if (rnd(100) < 12) {
+            turn_off(player, ISFLEE);
+            msg("You regain your composure.");
+        }
+        else if (DISTANCE(move_nh.y, move_nh.x, player.t_dest->y, player.t_dest->x) <
+                 DISTANCE(hero.y, hero.x, player.t_dest->y, player.t_dest->x)) {
+                        running = FALSE;
+                        msg("You are too terrified to move that way");
+                        player.t_action = A_NIL;
+                        player.t_no_move = movement(&player);
+                        return;
+        }
+    }
+
+    /* If we want to move to a monster, see what it is */
+    if (isalpha(ch)) {
+        item = find_mons(move_nh.y, move_nh.x);
+        if (item == NULL) {
+            debug("Cannot find monster in move.");
+            player.t_action = A_NIL;
+            return;
+        }
+        tp = THINGPTR(item);
+    }
+
+    /*
+     * Take care of hero being held.  If the player is being held, he
+     * can't move unless he is either attacking a non-friendly monster
+     * or attacking a friendly monster that can't move.
+     */
+    if (on(player, ISHELD) &&
+        (!isalpha(ch) || (on(*tp, ISFRIENDLY) && off(*tp, ISHELD)))) {
+        msg("You are being held.");
+        player.t_action = A_NIL;
+        return;
+    }
+
+    /* See if we have to wait for our movement rate */
+    if (player.t_action == A_NIL) {
+        after = FALSE;
+        firstmove = wasfirstmove;       /* Remember if this is first move */
+        player.t_no_move = movement(&player);
+        if (player.t_ctype == C_MONK)
+            player.t_no_move -= pstats.s_lvl/6;
+        if (on(player, ISFLY)) 
+            player.t_no_move /= 2; /* If flying, speed him up */
+
+        if (player.t_no_move < 1) player.t_no_move = 1;
+
+        /* Remember our action */
+        player.t_action = Moves[dy+1][dx+1];
+        return;
+    }
+
+    /* Now let's forget the old move and just do it */
+    player.t_action = A_NIL;
+
+    /* If we're moving onto a friendly monster, let's change places. */
+    if (isalpha(ch) && on(*tp, ISFRIENDLY) && off(*tp, ISHELD)) {
+        coord tpos,     /* Where monster may have been going */
+              current;  /* Current hero position */
+        int action;     /* The monster's action */
+
+        current = hero;
+        tpos = tp->t_newpos;
+        action = tp->t_action;
+
+        /* Disrupt whatever our friend was doing */
+        tp->t_action = A_NIL;
+
+        /* Tentatively move us to where he is */
+        hero = tp->t_pos;
+
+        /* See if we can move him to where we were */
+        tp->t_newpos = current;
+        do_chase(tp);
+
+        /* Did we succeed? */
+        if (ce(tp->t_pos, current)) {
+            /* Reset our idea of what ch is */
+            ch = winat(move_nh.y, move_nh.x);
+
+            /* Let it be known that we made the switch */
+            changed = TRUE;
+            old_hero = current;
+
+            /* Make the monster think it didn't move */
+            tp->t_oldpos = current;
+            tp->t_doorgoal.x = tp->t_doorgoal.y = -1;
+
+            /* Let the player know something funny happened. */
+            msg("What a sidestep!");
+        }
+        else {
+            /* Restore things -- we couldn't move */
+            hero = current;
+            tp->t_newpos = tpos;
+            tp->t_action = action;
+        }
+    }
+
+    /* assume he's not in a wall */
+    if (!isalpha(ch)) turn_off(player, ISINWALL);
+
+    switch (ch) {
+        case VERTWALL:
+        case HORZWALL:
+            if (levtype == OUTSIDE) {
+                hero = move_nh;
+                new_level(OUTSIDE);
+                return;
+            }
+        case WALL:
+        case SECRETDOOR:
+            if (off(player, CANINWALL) || running) {
+                after = running = FALSE;
+
+                /* Light if finishing run */
+                if (levtype == MAZELEV && lit_room(&rooms[0]))
+                    look(FALSE, TRUE);
+
+                after = running = FALSE;
+
+                return;
+            }
+            turn_on(player, ISINWALL);
+            break;
+        case POOL:
+            if (levtype == OUTSIDE) {
+                /* lake_check(&move_nh); */  /* not implemented yet */
+                running = FALSE;
+                break;
+            }
+        case MAZETRAP:
+            if (levtype == OUTSIDE) {
+            running = FALSE;
+            break;
+        }
+        case TRAPDOOR:
+        case TELTRAP:
+        case BEARTRAP:
+        case SLEEPTRAP:
+        case ARROWTRAP:
+        case DARTTRAP:
+        case WORMHOLE:
+            ch = be_trapped(&player, &move_nh);
+            if (ch == TRAPDOOR || ch == TELTRAP || 
+                pool_teleport  || ch == MAZETRAP) {
+                pool_teleport = FALSE;
+                return;
+            }
+            break;
+        case GOLD:
+        case POTION:
+        case SCROLL:
+        case FOOD:
+        case WEAPON:
+        case ARMOR:
+        case RING:
+        case MM:
+        case RELIC:
+        case STICK:
+            running = FALSE;
+            take = ch;
+            break;
+        case DOOR:
+        case STAIRS:
+        case POST:
+            running = FALSE;
+            break;
+        default:
+            break;
+    }
+
+    if (isalpha(ch)) { /* if its a monster then fight it */
+        /*
+         * If we were running down a corridor and didn't start right
+         * next to the critter, don't do anything.
+         */
+        if (running && wasfirstmove == FALSE && roomin(&hero) == NULL) {
+            struct linked_list *item;
+
+            item = find_mons(move_nh.y, move_nh.x);
+            if (item != NULL && !invisible(THINGPTR(item))) {
+                after = running = FALSE;
+                return;
+            }
+        }
+
+        /* We have to add time because we're attacking */
+        player.t_no_move = FIGHTBASE;
+        player.t_no_move += weap_move(&player, cur_weapon);
+        if (on(player, ISHASTE))
+                player.t_no_move /= 2;
+        else if (on(player, ISSLOW))
+                player.t_no_move *= 2;
+
+        /* We may attack faster if we're high enough level 
+         * and the right class
+         */
+        switch(player.t_ctype) {
+            case C_FIGHTER: num_hits = player.t_stats.s_lvl/25 + 1;
+            when C_PALADIN: num_hits = player.t_stats.s_lvl/35 + 1;
+            when C_RANGER:  num_hits = player.t_stats.s_lvl/35 + 1;
+            when C_MONK:  if(cur_weapon) num_hits = player.t_stats.s_lvl/40 + 1;
+                          else     num_hits = player.t_stats.s_lvl/30 + 1;
+            otherwise:      num_hits = player.t_stats.s_lvl/60 + 1;
+        }
+
+        /*
+         * The player has already moved the initial movement period.
+         * Let's add that in, do our division, and then subtract it
+         * out so that the total time is divided, not just the
+         * additional attack time.
+         */
+        moved = movement(&player),
+        player.t_no_move += moved;
+        player.t_no_move /= num_hits;
+        player.t_no_move -= moved;
+        running = FALSE;
+
+        /* Mark that we are attacking and save the attack coordinate */
+        player.t_action = A_ATTACK;
+        player.t_newpos = move_nh;
+        runch = Moves[dy+1][dx+1];      /* Remember the direction */
+
+        if (player.t_no_move <= 0) after = FALSE;
+        return;
+    }
+
+    /*
+     * if not fighting then move the hero
+     */
+    if (changed == FALSE) {
+        old_hero = hero;        /* Save hero's old position */
+        hero = move_nh;              /* Move the hero */
+    }
+    rp = roomin(&hero);
+    orp = roomin(&old_hero);
+
+    /* Unlight any possible cross-corridor */
+    if (levtype == MAZELEV) {
+        register bool call_light = FALSE;
+        register unsigned char wall_check;
+
+        if (wasfirstmove && lit_room(&rooms[0])) {
+            /* Are we moving out of a corridor? */
+            switch (runch) {
+                case 'h':
+                case 'l':
+                    if (old_hero.y + 1 < lines - 2) {
+                        wall_check = winat(old_hero.y + 1, old_hero.x);
+                        if (!isrock(wall_check)) call_light = TRUE;
+                    }
+                    if (old_hero.y - 1 > 0) {
+                        wall_check = winat(old_hero.y - 1, old_hero.x);
+                        if (!isrock(wall_check)) call_light = TRUE;
+                    }
+                    break;
+                case 'j':
+                case 'k':
+                    if (old_hero.x + 1 < cols) {
+                        wall_check = winat(old_hero.y, old_hero.x + 1);
+                        if (!isrock(wall_check)) call_light = TRUE;
+                    }
+                    if (old_hero.x - 1 >= 0) {
+                        wall_check = winat(old_hero.y, old_hero.x - 1);
+                        if (!isrock(wall_check)) call_light = TRUE;
+                    }
+                    break;
+                default:
+                    call_light = TRUE;
+            }
+            player.t_oldpos = old_hero;
+            if (call_light) light(&old_hero);
+        }
+    }
+
+    else if (orp != NULL && rp == NULL) {    /* Leaving a room -- darken it */
+        orp->r_flags |= FORCEDARK;      /* Fake darkness */
+        light(&old_hero);
+        orp->r_flags &= ~FORCEDARK;     /* Restore light state */
+    }
+    else if (rp != NULL && orp == NULL){/* Entering a room */
+        light(&hero);
+        if (rp->r_flags & ISTREAS)
+            wake_room(rp);
+    }
+    ch = winat(old_hero.y, old_hero.x);
+    wmove(cw, unc(old_hero));
+    waddch(cw, ch);
+    wmove(cw, unc(hero));
+    waddch(cw, PLAYER);
+}
+
+/*
+ * do_run:
+ *      Start the hero running
+ */
+
+do_run(ch)
+char ch;
+{
+    firstmove = TRUE;
+    running = TRUE;
+    after = FALSE;
+    runch = ch;
+}
+
+/*
+ * getdelta:
+ *      Takes a movement character (eg. h, j, k, l) and returns the
+ *      y and x delta corresponding to it in the remaining arguments.
+ *      Returns TRUE if it could find it, FALSE otherwise.
+ */
+
+bool
+getdelta(match, dy, dx)
+char match;
+int *dy, *dx;
+{
+    register int y, x;
+
+    for (y = 0; y < 3; y++)
+        for (x = 0; x < 3; x++)
+            if (Moves[y][x] == match) {
+                *dy = y - 1;
+                *dx = x - 1;
+                return(TRUE);
+            }
+
+    return(FALSE);
+}
+
+/*
+ * isatrap:
+ *      Returns TRUE if this character is some kind of trap
+ */
+
+isatrap(ch)
+reg char ch;
+{
+        switch(ch) {
+                case WORMHOLE:
+                case DARTTRAP:
+                case TELTRAP:
+                case TRAPDOOR:
+                case ARROWTRAP:
+                case SLEEPTRAP:
+                case BEARTRAP:  return(TRUE);
+                case MAZETRAP:
+                case POOL:      return(levtype != OUTSIDE);
+                default:        return(FALSE);
+        }
+}
+
+/*
+ * Called to illuminate a room.
+ * If it is dark, remove anything that might move.
+ */
+
+light(cp)
+coord *cp;
+{
+    register struct room *rp;
+    register int j, k, x, y;
+    register unsigned char ch, rch, sch;
+    register struct linked_list *item;
+    int jlow, jhigh, klow, khigh;       /* Boundaries of lit area */
+
+    if ((rp = roomin(cp)) != NULL) {
+        /*
+         * is he wearing ring of illumination? 
+         */
+        if (&hero == cp && ISWEARING(R_LIGHT)) /* Must be hero's room */
+            rp->r_flags &= ~ISDARK;
+        
+        /* If we are in a maze, don't look at the whole room (level) */
+        if (levtype == MAZELEV) {
+            int see_radius;
+
+            see_radius = 1;
+
+            /* If we are looking at the hero in a rock, broaden our sights */
+            if (&hero == cp || &player.t_oldpos == cp) {
+                ch = winat(hero.y, hero.x);
+                if (isrock(ch)) see_radius = 2;
+                ch = winat(player.t_oldpos.y, player.t_oldpos.x);
+                if (isrock(ch)) see_radius = 2;
+            }
+
+            jlow = max(0, cp->y - see_radius - rp->r_pos.y);
+            jhigh = min(rp->r_max.y, cp->y + see_radius + 1 - rp->r_pos.y);
+            klow = max(0, cp->x - see_radius - rp->r_pos.x);
+            khigh = min(rp->r_max.x, cp->x + see_radius + 1 - rp->r_pos.x);
+        }
+        else {
+            jlow = klow = 0;
+            jhigh = rp->r_max.y;
+            khigh = rp->r_max.x;
+        }
+        for (j = 0; j < rp->r_max.y; j++)
+        {
+            for (k = 0; k < rp->r_max.x; k++)
+            {
+                bool see_here = 0, see_before = 0;
+
+                /* Is this in the give area -- needed for maze */
+                if ((j < jlow || j >= jhigh) && (k < klow || k >= khigh))
+                    continue;
+
+                y = rp->r_pos.y + j;
+                x = rp->r_pos.x + k;
+
+                /*
+                 * If we are in a maze do not look at this area unless
+                 * we can see it from where we are or where we last were
+                 * (for erasing purposes).
+                 */
+                if (levtype == MAZELEV) {
+                    /* If we can't see it from here, could we see it before? */
+                    if ((see_here = maze_view(y, x)) == FALSE) {
+                        coord savhero;
+
+                        /* Could we see it from where we were? */
+                        savhero = hero;
+                        hero = player.t_oldpos;
+                        see_before = maze_view(y, x);
+                        hero = savhero;
+
+                        if (!see_before) continue;
+                    }
+                }
+
+                ch = show(y, x);
+                wmove(cw, y, x);
+                /*
+                 * Figure out how to display a secret door
+                 */
+                if (ch == SECRETDOOR) {
+                    if (j == 0 || j == rp->r_max.y - 1)
+                        ch = HORZWALL;
+                    else
+                        ch = VERTWALL;
+                }
+                /* For monsters, if they were previously not seen and
+                 * now can be seen, or vice-versa, make sure that will
+                 * happen.  This is for dark rooms as opposed to invisibility.
+                 *
+                 * Call winat() in the test because ch will not reveal
+                 * invisible monsters.
+                 */
+                if (isalpha(winat(y, x))) {
+                    struct thing *tp;   /* The monster */
+
+                    item = wake_monster(y, x);
+                    tp = THINGPTR(item);
+
+                    /* Previously not seen -- now can see it */
+                    if (tp->t_oldch == ' ' && cansee(tp->t_pos.y, tp->t_pos.x)) 
+                        tp->t_oldch = mvinch(y, x);
+
+                    /* Previously seen -- now can't see it */
+                    else if (!cansee(tp->t_pos.y, tp->t_pos.x) &&
+                             roomin(&tp->t_pos) != NULL)
+                        switch (tp->t_oldch) {
+                            /*
+                             * Only blank it out if it is in a room and not
+                             * the border (or other wall) of the room.
+                             */
+                             case DOOR:
+                             case SECRETDOOR:
+                             case HORZWALL:
+                             case VERTWALL:
+                                break;
+
+                             otherwise:
+                                tp->t_oldch = ' ';
+                        }
+                }
+
+                /*
+                 * If the room is a dark room, we might want to remove
+                 * monsters and the like from it (since they might
+                 * move).
+                 * A dark room.
+                 */
+                if ((!lit_room(rp) && (levtype != OUTSIDE)) ||
+                    (levtype == OUTSIDE && !daytime) ||
+                    on(player, ISBLIND)         ||
+                    (rp->r_flags & FORCEDARK)   ||
+                    (levtype == MAZELEV && !see_here && see_before)) {
+                    sch = mvwinch(cw, y, x);    /* What's seen */
+                    rch = mvinch(y, x); /* What's really there */
+                    switch (rch) {
+                        case DOOR:
+                        case SECRETDOOR:
+                        case STAIRS:
+                        case TRAPDOOR:
+                        case WORMHOLE:
+                        case TELTRAP:
+                        case BEARTRAP:
+                        case SLEEPTRAP:
+                        case ARROWTRAP:
+                        case DARTTRAP:
+                        case MAZETRAP:
+                        case POOL:
+                        case POST:
+                        case VERTWALL:
+                        case HORZWALL:
+                        case WALL:
+                            if (isalpha(sch)) ch = rch;
+                            else if (sch != FLOOR) ch = sch;
+                            else ch = ' '; /* Hide undiscoverd things */
+                        when FLOOR:
+                            ch = ' ';
+                        otherwise:
+                            ch = ' ';
+                    }
+                    /* Take care of our magic bookkeeping. */
+                    switch (sch) {
+                        case MAGIC:
+                        case BMAGIC:
+                        case CMAGIC:
+                            ch = sch;
+                    }
+                }
+                mvwaddch(cw, y, x, ch);
+            }
+        }
+    }
+}
+
+/*
+ * lit_room:
+ *      Called to see if the specified room is lit up or not.
+ */
+
+bool
+lit_room(rp)
+register struct room *rp;
+{
+    register struct linked_list *fire_item;
+    register struct thing *fire_creature;
+
+    if (!(rp->r_flags & ISDARK)) return(TRUE);  /* A definitely lit room */
+
+    /* Is it lit by fire light? */
+    if (rp->r_flags & HASFIRE) {
+        switch ((int)levtype) {
+            case MAZELEV:
+                /* See if a fire creature is in line of sight */
+                for (fire_item = rp->r_fires; fire_item != NULL;
+                     fire_item = next(fire_item)) {
+                    fire_creature = THINGPTR(fire_item);
+                    if (maze_view(fire_creature->t_pos.y,
+                                  fire_creature->t_pos.x)) return(TRUE);
+                }
+
+                /* Couldn't find any in line-of-sight */
+                return(FALSE);
+
+            /* We should probably do something special for the outside */
+            otherwise:
+                return TRUE;
+        }
+    }
+    return(FALSE);
+}
+
+/*
+ * movement:
+ *      Given a pointer to a player/monster structure, calculate the
+ *      movement rate for that character.
+ */
+
+short
+movement(tp)
+register struct thing *tp;
+{
+    register int result;
+    register int carry;         /* Percentage carried */
+
+    result = 0;
+
+    /* Adjust for armor (player only) */
+    if (tp == &player && cur_armor) {
+        int diff;  /* Now armor class differs from normal one of same type */
+
+        /* Blessed armor adds less */
+        diff = cur_armor->o_ac - armors[cur_armor->o_which].a_class;
+        switch (cur_armor->o_which) {
+            case LEATHER:
+            case RING_MAIL:
+            case CHAIN_MAIL:
+            case SCALE_MAIL:
+            case PADDED_ARMOR:
+                diff += 1;
+            when STUDDED_LEATHER:
+            case SPLINT_MAIL:
+            case BANDED_MAIL:
+            case PLATE_MAIL:
+                diff += 2;
+            when PLATE_ARMOR:
+                diff += 3;
+            otherwise:
+                debug("forgot an armor in movement()");
+        }
+        if (diff < 0) diff = 0;
+        result += diff;
+
+    }
+
+    /* Adjust for the pack */
+    carry = 100 * tp->t_stats.s_pack / tp->t_stats.s_carry;
+    if (carry > 75) result++;
+
+    /* Get a bonus for dexterity */
+    result -= dext_plus(tp == &player ? dex_compute() : tp->t_stats.s_dext);
+
+    /* only allow adjust for the minus's */
+    if (result < 0) result = 0;
+    result += tp->t_movement; /* now add in movement rate */
+
+    /* Is the character slowed? */
+    if (on(*tp, ISSLOW) || on(*tp, ISDANCE)) result *= 2;
+
+    /* Is the character hasted? */
+    if (on(*tp, ISHASTE)) result /= 2;
+
+    /* We have a minimum of 1 */
+    if (result < 1) result = 1;
+
+    return(result);
+}
+
+/*
+ * rndmove:
+ *      move in a random direction if the monster/person is confused
+ */
+
+coord 
+rndmove(who)
+struct thing *who;
+{
+    register int x, y;
+    register int ex, ey, nopen = 0;
+    coord ret;  /* what we will be returning */
+    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 - 2)
+            for (x = who->t_pos.x - 1; x <= ex; x++)
+            {
+                if (x < 0 || x >= cols)
+                    continue;
+                if (step_ok(y, x, NOMONST, who) == TRUE)
+                {
+                    dest.y = y;
+                    dest.x = x;
+                    if (!diag_ok(&who->t_pos, &dest, who))
+                        continue;
+                    if (rnd(++nopen) == 0)
+                        ret = dest;
+                }
+            }
+    return ret;
+}
+
+#define TRAPTYPES 9             /* 9 total trap types that can be set */
+#define WIZARDTRAPS 3           /* Only wizards can set the last 3 */
+                /* CTRL(C) to level 400 for POST level */
+static const char *trap_types[TRAPTYPES] = {
+    "Trap Door",
+    "Bear Trap",
+    "Sleep Trap",
+    "Arrow Trap",
+    "Teleport Trap",
+    "Dart Trap",
+    "Magic pool",
+    "Maze Trap",
+    "Worm Hole"
+};
+
+/*
+ * set_trap:
+ *      set a trap at (y, x) on screen.
+ */
+
+set_trap(tp, y, x)
+register struct thing *tp;
+register int y, x;
+{
+    register bool is_player = (tp == &player);
+    register int selection = rnd(TRAPTYPES-WIZARDTRAPS) + '1';
+    register int i, num_traps;
+    register unsigned char ch = 0, och;
+    int thief_bonus = 0;
+    int s_dext;
+
+    /* let wizard in on this too */
+    if (wizard) goto can_traps;
+    if (is_player && player.t_ctype != C_THIEF && player.t_ctype !=C_ASSASSIN) {
+        msg("Only thieves and assassins can set traps. ");
+        return;
+    }
+    can_traps:
+    switch (och = mvinch(y, x)) {
+        case WALL:
+        case FLOOR:
+        case PASSAGE:
+            break;
+        default:
+            if (is_player) msg("The trap failed!");
+            return;
+    }
+
+    if (is_player) {
+        int state = 0, /* 0 -> current screen, 1 -> prompt screen, 2 -> done */
+            units;     /* Number of movement units for the given trap */
+
+        if (player.t_action == C_SETTRAP) {
+            selection = player.t_selection;
+            player.t_selection = 0;
+            player.t_action = A_NIL;
+        }
+        else {
+            msg("Which kind of trap do you wish to set? (* for a list): ");
+            num_traps = TRAPTYPES - (wizard ? 0 : WIZARDTRAPS);
+            do {
+                selection = wgetch(cw);
+                switch (selection) {
+                    case '*':
+                      if (state != 1) {
+                        wclear(hw);
+                        touchwin(hw);
+                        for (i=0; i<num_traps; i++) {
+                            wmove(hw, i+2, 0);
+                            wprintw(hw, "[%d] %s", i+1, trap_types[i]);
+                        }
+                        mvwaddstr(hw, 0, 0,
+                                "Which kind of trap do you wish to set? ");
+
+                        if (menu_overlay)
+                            /*
+                             * Put out the selection.  The longest line is
+                             * the prompt line (39 characters long).
+                             */
+                            over_win(cw, hw, num_traps + 3, 41, 0, 39, NULL);
+                        else
+                            draw(hw);
+                        state = 1;      /* Now in prompt window */
+                      }
+                      break;
+
+                    case ESC:
+                        if (state == 1) {
+                            clearok(cw, FALSE);
+                            touchwin(cw);
+                        }
+                        msg("");
+
+                        trap_tries--;   /* Don't count this one */
+                        after = FALSE;
+                        return;
+
+                    case '1':
+                    case '2':
+                    case '3':
+                    case '4':
+                    case '5':
+                    case '6':
+                    case '7':
+                    case '8':
+                    case '9':
+                        if (selection < '7' || wizard) {
+                            if (state == 1) {   /* In prompt window */
+                                clearok(cw, FALSE); /* Set up for redraw */
+                                touchwin(cw);
+                            }
+
+                            msg("");
+
+                            /*
+                             * Make sure there is a floor below us for trap
+                             * doors.
+                             */
+                            if (selection == '1' && level >= nfloors) {
+                                if (state == 1) draw(cw);
+                                msg("There is no level below this one.");
+                                return;
+                            }
+                            state = 2;  /* Finished */
+                            break;
+                        }
+
+                        /* Fall through for non-wizard, unusual trap case */
+                    default:
+                        if (state == 1) {       /* In the prompt window */
+                            wmove(hw, 0, 0);
+                            wprintw(hw, 
+                                "Please enter a selection between 1 and %d:  ",
+                                num_traps);
+                            if (menu_overlay)
+                                /*
+                                 * Put out the selection.  The longest line is
+                                 * the prompt line (43 characters long).
+                                 */
+                                over_win(cw, hw, num_traps+3, 45, 0, 43, NULL);
+                            else 
+                                draw(hw);
+                        }
+                        else {  /* Normal window */
+                            mpos = 0;
+                            msg("Please enter a selection between 1 and %d:  ",
+                                num_traps);
+                        }
+                }
+            } while (state != 2);
+
+            player.t_selection = selection;
+
+            switch (selection) {
+                case '1': units = 10;   /* Trap door */
+                when '2': units = 5;    /* Bear trap */
+                when '3': units = 7;    /* Sleeping gas trap */
+                when '4': units = 5;    /* Arrow trap */
+                when '5': units = 10;   /* Teleport trap */
+                when '6': units = 7;    /* Dart trap */
+                otherwise: units = 5;   /* Unknown trap */
+            }
+            player.t_no_move = units * movement(&player);
+            player.t_action = C_SETTRAP;
+            return;
+        }
+    }
+
+    if (is_player && player.t_ctype == C_THIEF)   thief_bonus = 20;
+    if (is_player && player.t_ctype == C_ASSASSIN) thief_bonus = 15;
+    if (is_player && player.t_ctype == C_FIGHTER) thief_bonus = 10;
+
+    s_dext = (tp == &player) ? dex_compute() : tp->t_stats.s_dext;
+
+    if (ntraps >= MAXTRAPS || ++trap_tries >= MAXTRPTRY ||
+        levtype == POSTLEV || levtype == OUTSIDE ||
+        rnd(80) >= (s_dext + tp->t_stats.s_lvl/2 + thief_bonus)) {
+        if (is_player) msg("The trap failed!");
+        return;
+    }
+
+    switch (selection) {
+        case '1': ch = TRAPDOOR;
+        when '2': ch = BEARTRAP;
+        when '3': ch = SLEEPTRAP;
+        when '4': ch = ARROWTRAP;
+        when '5': ch = TELTRAP;
+        when '6': ch = DARTTRAP;
+        when '7': ch = POOL;
+        when '8': ch = MAZETRAP;
+        when '9': ch = WORMHOLE;
+    }
+
+    mvaddch(y, x, ch);
+    traps[ntraps].tr_show = och;
+    traps[ntraps].tr_type = ch;
+    traps[ntraps].tr_pos.y = y;
+    traps[ntraps].tr_pos.x = x;
+    if (is_player) 
+        traps[ntraps].tr_flags = ISTHIEFSET;
+    if (ch == POOL || ch == POST) {
+        traps[ntraps].tr_flags |= ISFOUND;
+    }
+
+    ntraps++;
+}
+
+/*
+ * show:
+ *      returns what a certain thing will display as to the un-initiated
+ */
+
+show(y, x)
+register int y, x;
+{
+    register unsigned char ch = winat(y, x);
+    register struct linked_list *it;
+    register struct thing *tp;
+
+    if (isatrap(ch)) {
+        register struct trap *trp = trap_at(y, x);
+
+        return (trp->tr_flags & ISFOUND) ? ch : trp->tr_show;
+    }
+    else if (isalpha(ch)) {
+        if ((it = find_mons(y, x)) == NULL) {
+            msg("Show:  Can't find monster in show (%d, %d)", y, x);
+            return(mvwinch(stdscr, y, x));
+        }
+        tp = THINGPTR(it);
+
+        if (on(*tp, ISDISGUISE)) ch = tp->t_disguise; /* As a mimic */
+
+        /* Hide invisible creatures */
+        else if (invisible(tp)) {
+            /* We can't see surprise-type creatures through "see invisible" */
+            if (off(player,CANSEE) || on(*tp,CANSURPRISE))
+                ch = mvwinch(stdscr, y, x); /* Invisible */
+        }
+        else if (on(*tp, CANINWALL)) {
+            if (isrock(mvwinch(stdscr, y, x))) ch = winch(stdscr); /* As Xorn */
+        }
+    }
+    return ch;
+}
+
+
+/*
+ * trap_at:
+ *      find the trap at (y,x) on screen.
+ */
+
+struct trap *
+trap_at(y, x)
+register int y, x;
+{
+    register 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)
+        debug((sprintf(prbuf, "Trap at %d,%d not in array", y, x), prbuf));
+    return tp;
+}
+
+/*
+ * weap_move:
+ *      Calculate how many segments it will take to swing the given
+ *      weapon (note that the weapon may actually be a stick or
+ *      even something else).
+ */
+
+weap_move(wielder, weap)
+register struct thing *wielder; /* Who's wielding the weapon */
+register struct object *weap;   /* The weapon */
+{
+    register int weap_rate;
+    int          dexterity;
+    int          strength;
+
+    if (weap == NULL) return(1); /* hand, claw, bite attacks are quick */
+
+    switch (weap->o_type) {
+        case STICK:
+            if (EQUAL(ws_type[weap->o_which], "staff"))
+                weap_rate = 2;
+            else weap_rate = 1; /* A wand */
+
+        when WEAPON:
+            weap_rate = weaps[weap->o_which].w_rate;
+
+            /* Adjust for blessed or cursed weapon */
+            if (weap->o_hplus < 0)      /* Cursed */
+                weap_rate -= (weap->o_hplus - 2) / 3;
+            else if (weap_rate > 0)     /* Blessed */
+                weap_rate -= (2*weap->o_hplus + weap_rate - 1) / weap_rate;
+
+        when RELIC:
+            switch (weap->o_which) {
+                case MUSTY_DAGGER:
+                case HRUGGEK_MSTAR:
+                case AXE_AKLAD:
+                case YEENOGHU_FLAIL:
+                case MING_STAFF:
+                case ORCUS_WAND:
+                case ASMO_ROD:
+                    /* These operate in the blink of an eye */
+                    weap_rate = 1;
+                otherwise:
+                    /* What is it? */
+                    weap_rate = 10;
+                    debug("unknown weapon in weap_move()");
+            }
+        otherwise:
+            /* What is it? */
+            weap_rate = 10;
+            debug("unknown weapon in weap_move()");
+    }
+
+    /* Put in a dexterity bonus */
+    if (wielder == &player) dexterity = dex_compute();
+    else dexterity = wielder->t_stats.s_dext;
+    weap_rate -= dext_plus(dexterity) / 2;
+
+    /* Put in a strength bonus */
+    if (wielder == &player) strength = str_compute();
+    else strength = wielder->t_stats.s_str;
+    weap_rate -= str_plus(strength) / 2;
+
+    /* It can't speed you up and it must take SOME time */
+    if (weap_rate <= 0) weap_rate = 1;
+
+    /* Do we need to adjust for fast/slow movement? */
+    if (on(*wielder, ISSLOW) || on(*wielder, ISDANCE)) weap_rate *= 2;
+    if (on(*wielder, ISHASTE)) weap_rate /= 2;
+
+    /* Return the result */
+    return(weap_rate);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xrogue/n_level.c	Tue Apr 21 08:55:20 2015 -0400
@@ -0,0 +1,672 @@
+/*
+    n_level.c - Dig and draw a new level
+    
+    XRogue: Expeditions into the Dungeons of Doom
+    Copyright (C) 1991 Robert Pietkivitch
+    All rights reserved.
+    
+    Based on "Advanced Rogue"
+    Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka and AT&T
+    All rights reserved.
+
+    Based on "Rogue: Exploring the Dungeons of Doom"
+    Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
+    All rights reserved.
+    
+    See the file LICENSE.TXT for full copyright and licensing information.
+*/
+
+#include <curses.h>
+#include "rogue.h"
+#define TERRASAVE 3
+
+/*
+ * new_level:
+ *      Dig and draw a new level
+ */
+
+new_level(ltype)
+LEVTYPE ltype;          /* designates type of level to create */
+{
+    register int rm = 0, i, cnt;
+    register unsigned char ch;
+    register struct linked_list *item;
+    register struct thing *tp;
+    register struct object *obj;
+    int waslit = 0;     /* Was the previous outside level lit? */
+    int starty = 0, startx = 0, deltay = 0, deltax = 0;
+    bool fresh=TRUE, vert = 0, top;
+    struct room *rp;
+    struct linked_list *nitem, *savmonst=NULL, *savitems=NULL;
+	coord stairs = {0,0};
+
+    if (wizard) {
+        msg("Turns: %ld", turns);       /* Number of turns for last level */
+        mpos = 0;
+    }
+
+    /* Start player off right */
+    turn_off(player, ISHELD);
+    turn_off(player, ISFLEE);
+    extinguish(suffocate);
+    hold_count = 0;
+    trap_tries = 0;
+
+    /* Are we just entering a dungeon?  If so, how big is it? */
+    if (ltype != OUTSIDE && nfloors < 0) nfloors = HARDER+20 + rnd(51);
+
+    if (level > max_level)
+        max_level = level;
+
+    /* Are we starting a new outside level? */
+    if (ltype == OUTSIDE) {
+        register int i, j;
+
+        /* Save some information prior to clearing the screen */
+        if (level == -1 || mvinch(hero.y, hero.x) == HORZWALL) vert = TRUE;
+        else vert = FALSE;
+        
+        if (level < 1) {
+                fresh = TRUE;
+                starty = 2;
+                startx = 1;
+                deltay = deltax = 1;
+                level = max_level;      /* Restore level to deepest attempt */
+                prev_max = level;   /* reset for boundary crossings below */
+        }
+        else if (level >= 1 && prev_max == 1000) {
+                fresh = TRUE;
+                starty = 2;
+                startx = 1;
+                deltay = deltax = 1;
+                prev_max = level;   /* reset for boundary crossings below */
+        }
+        else {  /* Copy several lines of the terrain to the other end */
+
+            unsigned char cch;   /* Copy character */
+
+            if (wizard) msg("Crossing sector boundary ");
+
+            /* Was the area dark (not magically lit)? */
+            if (!(rooms[0].r_flags & ISDARK)) waslit = 1;
+
+            fresh = FALSE;
+            if ((vert && hero.y == 1) || (!vert && hero.x == 0)) top = TRUE;
+            else top = FALSE;
+            for (i=0; i<TERRASAVE; i++) {
+                if (vert)
+                    for (j=1; j<cols-1; j++) {
+                        if (top) {
+                            cch = mvinch(i+2, j);
+                            mvaddch(lines-6+i, j, cch);
+                        }
+                        else {
+                            cch = mvinch(lines-4-i, j);
+                            mvaddch(4-i, j, cch);
+                        }
+                    }
+                else
+                    for (j=2; j<lines-3; j++) {
+                        if (top) {
+                            cch = mvinch(j, i+1);
+                            mvaddch(j, cols-4+i, cch);
+                        }
+                        else {
+                            cch = mvinch(j, cols-2-i);
+                            mvaddch(j, 3-i, cch);
+                        }
+                    }
+            }
+
+            if (vert) {
+                startx = deltax = 1;
+                if (top) {
+                    starty = lines-4-TERRASAVE;
+                    deltay = -1;
+                }
+                else {
+                    starty = TERRASAVE + 2;
+                    deltay = 1;
+                }
+            }
+            else {
+                starty = 2;
+                deltay = 1;
+                if (top) {
+                    startx = cols-2-TERRASAVE;
+                    deltax = -1;
+                }
+                else {
+                    deltax = 1;
+                    startx = TERRASAVE + 1;
+                }
+            }
+
+            /* Check if any monsters should be saved */
+            for (item = mlist; item != NULL; item = nitem) {
+                nitem = next(item);
+                tp = THINGPTR(item);
+                if (vert) {
+                    if (top) {
+                        if (tp->t_pos.y < TERRASAVE + 2)
+                            tp->t_pos.y += lines - 5 - TERRASAVE;
+                        else continue;
+                    }
+                    else {
+                        if (tp->t_pos.y > lines - 4 - TERRASAVE)
+                            tp->t_pos.y += 5 + TERRASAVE - lines;
+                        else continue;
+                    }
+                }
+                else {
+                    if (top) {
+                        if (tp->t_pos.x < TERRASAVE + 1)
+                            tp->t_pos.x += cols - 2 - TERRASAVE;
+                        else continue;
+                    }
+                    else {
+                        if (tp->t_pos.x > cols - 2 - TERRASAVE)
+                            tp->t_pos.x += 2 + TERRASAVE - cols;
+                        else continue;
+                    }
+                }
+
+                /*
+                 * If the monster is busy chasing another monster, don't save
+                 * it
+                 */
+                if (tp->t_dest && tp->t_dest != &hero) continue;
+
+                /* Outside has plenty of monsters, don't need these.
+                 * detach(mlist, item);
+                 * attach(savmonst, item);
+                 */
+            }
+
+            /* Check if any treasure should be saved */
+            for (item = lvl_obj; item != NULL; item = nitem) {
+                nitem = next(item);
+                obj = OBJPTR(item);
+                if (vert) {
+                    if (top) {
+                        if (obj->o_pos.y < TERRASAVE + 2)
+                            obj->o_pos.y += lines - 5 - TERRASAVE;
+                        else continue;
+                    }
+                    else {
+                        if (obj->o_pos.y > lines - 4 - TERRASAVE)
+                            obj->o_pos.y += 5 + TERRASAVE - lines;
+                        else continue;
+                    }
+                }
+                else {
+                    if (top) {
+                        if (obj->o_pos.x < TERRASAVE + 1)
+                            obj->o_pos.x += cols - 2 - TERRASAVE;
+                        else continue;
+                    }
+                    else {
+                        if (obj->o_pos.x > cols - 2 - TERRASAVE)
+                            obj->o_pos.x += 2 + TERRASAVE - cols;
+                        else continue;
+                    }
+                }
+                detach(lvl_obj, item);
+                attach(savitems, item);
+            }
+        }
+    }
+
+    wclear(cw);
+    wclear(mw);
+    if (fresh || levtype != OUTSIDE) clear();
+    /*
+     * check to see if he missed a UNIQUE, If he did then put it back
+     * in the monster table for next time
+     */
+     for (item = mlist; item != NULL; item = next(item)) {
+        tp = THINGPTR(item);
+        if (on(*tp, ISUNIQUE)) 
+            monsters[tp->t_index].m_normal = TRUE;
+     }
+    /*
+     * Free up the monsters on the last level
+     */
+    t_free_list(mlist);
+    o_free_list(lvl_obj);               /* Free up previous objects (if any) */
+    for (rp = rooms; rp < &rooms[MAXROOMS]; rp++)
+        r_free_list(rp->r_exit);        /* Free up the exit lists */
+
+    levtype = ltype;
+    foods_this_level = 0;               /* food for hero this level */
+
+    /* What kind of level are we on? */
+    if (ltype == POSTLEV || ltype == STARTLEV) {
+        if (ltype == POSTLEV)
+        do_post(FALSE);  /* Trading post */
+        else
+        do_post(TRUE);  /* Equipage */
+
+        levtype = ltype = POSTLEV;
+    }
+    else if (ltype == MAZELEV) {
+        do_maze();
+        no_food++;
+        put_things(ltype);              /* Place objects (if any) */
+    }
+    else if (ltype == OUTSIDE) {
+        /* Move the cursor back onto the hero */
+        wmove(cw, hero.y, hero.x);
+        init_terrain();
+        do_terrain(starty, startx, deltay, deltax, (bool) (fresh || !vert));
+        no_food++;
+        put_things(ltype);
+
+        /* Should we magically light this area? */
+        if (waslit) rooms[0].r_flags &= ~ISDARK;
+    }
+    else {
+        do_rooms();                     /* Draw rooms */
+        do_passages();                  /* Draw passages */
+        no_food++;
+        put_things(ltype);              /* Place objects (if any) */
+    }
+    /*
+     * Place the staircase down.  Only a small chance for an outside stairway.
+     */
+    if (ltype != OUTSIDE || roll(1, 5) == 5) {
+        cnt = 0;
+        do {
+            rm = rnd_room();
+            rnd_pos(&rooms[rm], &stairs);
+        } until (mvinch(stairs.y, stairs.x) == FLOOR || cnt++ > 2500);
+        addch(STAIRS);
+    }
+    /*
+     * maybe add a trading post 
+     */
+    if (level > 5 && rnd(10) == 7 && ltype == NORMLEV) {
+        cnt = 0;
+        do {
+            rm = rnd_room();
+            if (rooms[rm].r_flags & ISTREAS)
+                continue;
+            rnd_pos(&rooms[rm], &stairs);
+        } until (winat(stairs.y, stairs.x) == FLOOR || cnt++ > 2500);
+        addch(POST);
+    }
+    if (ltype != POSTLEV) {     /* Add monsters that fell through */
+        nitem = tlist;
+        while (nitem != NULL) {
+            item = nitem;
+            nitem = next(item); /* because detach and attach mess up ptrs */
+            tp = THINGPTR(item);
+            cnt = 0;
+            do {
+                rm = rnd_room();
+                rnd_pos(&rooms[rm], &tp->t_pos);
+            } until (cnt++ > 2500 || winat(tp->t_pos.y, tp->t_pos.x) == FLOOR);
+            mvwaddch(mw, tp->t_pos.y, tp->t_pos.x, tp->t_type);
+            tp->t_oldch = mvwinch(cw, tp->t_pos.y, tp->t_pos.x);
+
+            /*
+             * If it has a fire, mark it
+             */
+            if (on(*tp, HASFIRE)) {
+                register struct linked_list *fire_item;
+
+                fire_item = creat_item();
+                ldata(fire_item) = (char *) tp;
+                attach(rooms[rm].r_fires, fire_item);
+                rooms[rm].r_flags |= HASFIRE;
+            }
+
+            detach(tlist, item);
+            turn_off(*tp,ISELSEWHERE);
+            attach(mlist, item);
+        }
+    }
+
+    /* Restore any saved monsters */
+    for (item = savmonst; item != NULL; item = nitem) {
+        nitem = next(item);
+        tp = THINGPTR(item);
+        mvwaddch(mw, tp->t_pos.y, tp->t_pos.x, tp->t_type);
+        tp->t_oldch = mvwinch(cw, tp->t_pos.y, tp->t_pos.x);
+
+        /*
+         * If it has a fire, mark it
+         */
+        if (on(*tp, HASFIRE)) {
+            register struct linked_list *fire_item;
+
+            fire_item = creat_item();
+            ldata(fire_item) = (char *) tp;
+            attach(rooms[rm].r_fires, fire_item);
+            rooms[rm].r_flags |= HASFIRE;
+        }
+
+        detach(savmonst, item);
+        attach(mlist, item);
+    }
+
+    /* Restore any saved objects */
+        for(item = savitems; item != NULL; item = nitem) {
+            nitem = next(item);
+            obj = OBJPTR(item);
+            mvaddch(obj->o_pos.y, obj->o_pos.x, obj->o_type);
+            detach(savitems, item);
+            attach(lvl_obj, item);
+        }
+
+    /*
+     * Place the traps (except for trading post)
+     */
+    ntraps = 0; /* No traps yet */
+    if (levtype == NORMLEV) {
+        if (rnd(10) < vlevel) {
+            ntraps = rnd(vlevel/4)+2;
+            if (ntraps > MAXTRAPS)
+                ntraps = MAXTRAPS;
+            i = ntraps;
+            while (i--)
+            {
+                cnt = 0;
+                do {
+                    rm = rnd_room();
+                    if (rooms[rm].r_flags & ISTREAS)
+                        continue;
+                    rnd_pos(&rooms[rm], &stairs);
+                } until (winat(stairs.y, stairs.x) == FLOOR || cnt++ > 2500);
+
+                traps[i].tr_flags = 0;
+
+                /* If we are at the bottom, we can't set a trap door */
+                if (level >= nfloors) ch = (unsigned char) rnd(8) + 1;
+                else ch = (unsigned char) rnd(9);
+
+                switch((int) ch) {
+                    case 0: ch = TRAPDOOR;
+                    when 1: ch = BEARTRAP;
+                    when 2: ch = SLEEPTRAP;
+                    when 3: ch = ARROWTRAP;
+                    when 4: ch = TELTRAP;
+                    when 5: ch = DARTTRAP;
+                    when 6: ch = POOL;
+                            traps[i].tr_flags = ISFOUND;
+                    when 7: ch = MAZETRAP;
+                    when 8: ch = WORMHOLE;
+                }
+                addch(ch);
+                traps[i].tr_type = ch;
+                traps[i].tr_show = FLOOR;
+                traps[i].tr_pos = stairs;
+            }
+        }
+    }
+    if (fresh) {        /* A whole new picture */
+        /* 
+         * try to find a room for the hero. The objective here is to:
+         * --> don't put him in a treasure room
+         * --> don't put him on an object 
+         * --> try not to put him next to the stairs
+         */
+        cnt = 2500;
+        do {
+            if (ltype != OUTSIDE) rm = rnd_room();
+            else continue;
+
+            if (rooms[rm].r_flags & ISTREAS)
+                continue;
+
+            rnd_pos(&rooms[rm], &hero);
+        } until(    cnt-- == 0  ||
+                    (winat(hero.y, hero.x) == FLOOR &&
+                     DISTANCE(hero.y, hero.x, stairs.y, stairs.x) > cnt/10));
+    }
+    else {              /* We're extending into an adjacent outside plane */
+        rm = 0;
+        if (vert) {
+            if (hero.y == 1) hero.y = lines - 3 - TERRASAVE; /* Top to bottom */
+            else hero.y = TERRASAVE + 1;        /* Bottom to top */
+        }
+        else {
+            if (hero.x == 0) hero.x = cols - 1 - TERRASAVE; /* Right to left */
+            else hero.x = TERRASAVE;    /* Left to right */
+        }
+    }
+    oldrp = &rooms[rm];         /* Set the current room */
+    player.t_oldpos = player.t_pos;     /* Set the current position */
+
+    if (ISWEARING(R_AGGR) || 
+        (cur_misc[WEAR_JEWEL] != NULL && 
+         cur_misc[WEAR_JEWEL]->o_which == MM_JEWEL))
+        aggravate(TRUE, TRUE);  /* affect all charactors */
+
+    /*
+     * If player is moving up or above his deepest point, wake up any
+     * non-uniques
+     */
+    else if (level < cur_max) {
+            aggravate(FALSE, FALSE);
+    }
+
+    light(&hero);
+    wmove(cw, hero.y, hero.x);
+    waddch(cw, PLAYER);
+
+    if (level > cur_max)
+        cur_max = level;
+
+    draw(cw);
+
+    status(TRUE);
+
+    /* Do we sense any food on this level? */
+    if (cur_relic[SURTUR_RING])
+        quaff(P_FFIND, NULL, NULL, FALSE);
+}
+
+/*
+ * Pick a room that is really there
+ */
+
+rnd_room()
+{
+    register int rm;
+
+    if (levtype != NORMLEV)
+        rm = 0;
+    else do
+        {
+            rm = rnd(MAXROOMS);
+        } while (rooms[rm].r_flags & ISGONE);
+    return rm;
+}
+
+/*
+ * put_things:
+ *      put potions and scrolls on this level
+ */
+
+put_things(ltype)
+LEVTYPE ltype;          /* designates type of level to create */
+{
+    register int i, rm, cnt;
+    register struct object *cur;
+    register struct linked_list *item, *nextitem, *exitptr;
+    int length, width;
+    int ITEMS = 0;      /* number of items to place */
+    coord tp, *exit;
+
+    /*
+     * The only way to get new stuff is to go down into the dungeon.
+     */
+    if (level < cur_max) {
+        if (ltype == NORMLEV)
+        return;
+    }
+
+    if (ltype == OUTSIDE) goto jmp_here;  /* a jump for outside */
+
+    /* 
+     * There is a chance that there is a Treasure Room on this level 
+     */
+    if (ltype == NORMLEV && rnd(150) < level) {
+        register int j;
+        register struct room *rp;
+
+        /* Count the number of free spaces */
+        i = 0;  /* 0 tries */
+        do {
+            rp = &rooms[rnd_room()];
+            width = rp->r_max.y - 2;
+            length = rp->r_max.x - 2;
+        } until ((width*length >= MAXTREAS) || (i++ > MAXROOMS*4));
+
+        /* Mark the room as a treasure room */
+        rp->r_flags |= ISTREAS;
+
+        /* Make all the doors secret doors */
+        for (exitptr = rp->r_exit; exitptr; exitptr = next(exitptr)) {
+            exit = DOORPTR(exitptr);
+            move(exit->y, exit->x);
+            addch(SECRETDOOR);
+        }
+
+        /*
+         * check to see if there are any monsters in room already
+         */
+        for (item = mlist; item != NULL; item = nextitem) {
+            register struct thing *tp;
+
+            tp = THINGPTR(item);
+            nextitem = next(item);
+            if (rp == roomin(&tp->t_pos)) {
+                /*
+                 * Don't let nice creatures be generated in a treasure
+                 * room.
+                 */
+                if ((player.t_ctype==C_PALADIN || player.t_ctype==C_RANGER ||
+                     player.t_ctype==C_MONK) && off(*tp, ISMEAN)) {
+                    int index;
+
+                    if (on(*tp, ISUNIQUE)) index = tp->t_index;
+                    else index = -1;
+
+                    /* Get rid of the monster */
+                    killed(item, FALSE, FALSE, FALSE);
+
+                    /* Restore uniques back in the table */
+                    if (index != -1) monsters[index].m_normal = TRUE;
+
+                    continue;
+                }
+                turn_on(*tp, ISMEAN);
+                turn_on(*tp, ISGUARDIAN);
+            }
+        }
+
+        /* Put in the monsters and treasures */
+        for (j=1; j<rp->r_max.y-1; j++)
+            for (i=1; i<rp->r_max.x-1; i++) {
+                coord trp;
+
+                trp.y = rp->r_pos.y+j;
+                trp.x = rp->r_pos.x+i;
+
+                /* Monsters */
+                if ((rnd(100) < (MAXTREAS*100)/(width*length)) &&
+                    (mvwinch(mw, rp->r_pos.y+j, rp->r_pos.x+i) == ' ')) {
+                    register struct thing *tp;
+
+                    /* 
+                     * Put it there and leave it asleep. Wake the monsters
+                     * when the player enters the room. Hopefully, all bases
+                     * are covered as far as the ways to get in. This way
+                     * cpu time is not wasted on the awake monsters that
+                     * can't get to the player anyway.
+                     * try not to put any UNIQUEs in a treasure room.
+                     * note that they may have put put in already by the 
+                     * non-treasure room code.
+                     * also, try not to put ISMEAN monsters in a treasure
+                     * room as these are supposed to be non-hostile until
+                     * attacked. It also makes life simpler for the ranger,
+                     * paladin, and monk.
+                     */
+                    for(;;) {
+                        item = new_item(sizeof *tp); /* Make a monster */
+                        tp = THINGPTR(item);
+                        new_monster(item,randmonster(FALSE, TRUE),&trp,TRUE);
+                        if (on(*tp, HASFIRE)) {
+                            register struct linked_list *fire_item;
+
+                            fire_item = creat_item();
+                            ldata(fire_item) = (char *) tp;
+                            attach(rp->r_fires, fire_item);
+                            rp->r_flags |= HASFIRE;
+                        }
+                        /*
+                         * only picky for these classes
+                         */
+                        if (player.t_ctype != C_RANGER  &&
+                            player.t_ctype != C_PALADIN &&
+                            player.t_ctype != C_MONK)
+                            break;
+                        if (on(*tp, ISMEAN))
+                            break;
+                        killed (item, FALSE, FALSE, FALSE);
+                    }
+                    if (on(*tp, ISUNIQUE)) { /* just in case */
+                        carry_obj(tp, monsters[tp->t_index].m_carry);
+                        tp->t_no_move = movement(tp);
+                    }
+                    turn_on(*tp, ISGUARDIAN);
+
+                }
+
+                /* Treasures */
+                if ((rnd(100) < (MAXTREAS*100)/(width*length)) &&
+                    (mvinch(rp->r_pos.y+j, rp->r_pos.x+i) == FLOOR)) {
+                    item = new_thing(ALL, TRUE);
+                    attach(lvl_obj, item);
+                    cur = OBJPTR(item);
+        
+                    mvaddch(trp.y, trp.x, cur->o_type);
+                    cur->o_pos = trp;
+                }
+            }
+    }
+
+    jmp_here:   /* outside jumper for equippage */
+
+    /*
+     * Do ITEMS attempts to put things in dungeon, maze, or outside
+     */
+
+    if (ltype == OUTSIDE) ITEMS = rnd(15)+1;
+    else if (ltype == MAZELEV) ITEMS = rnd(20)+1;
+    else ITEMS = MAXOBJ + rnd(4);
+
+    for (i = 0; i < ITEMS; i++)
+        if (rnd(100) < 65) {
+            /*
+             * Pick a new object and link it in the list
+             */
+            item = new_thing(ALL, TRUE);
+            attach(lvl_obj, item);
+            cur = OBJPTR(item);
+            /*
+             * Put it somewhere
+             */
+            cnt = 0;
+            do {
+                if (ltype == OUTSIDE) rm = 0;
+                else rm = rnd_room();
+                rnd_pos(&rooms[rm], &tp);
+            } until (winat(tp.y, tp.x) == FLOOR || cnt++ > 2500);
+            mvaddch(tp.y, tp.x, cur->o_type);
+            cur->o_pos = tp;
+        }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xrogue/network.h	Tue Apr 21 08:55:20 2015 -0400
@@ -0,0 +1,35 @@
+/*
+    network.h  -  networking setup
+    
+    XRogue: Expeditions into the Dungeons of Doom
+    Copyright (C) 1991 Robert Pietkivitch
+    All rights reserved.
+    
+    Based on "Advanced Rogue"
+    Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka and AT&T
+    All rights reserved.
+
+    See the file LICENSE.TXT for full copyright and licensing information.
+*/
+
+/*
+ * Note that networking is set up for machines that can communicate
+ * via some system such as uucp.  The mechanism listed here uses uux
+ * and assumes that the target machine allows access to the game via
+ * the uux command.  NETCOMMAND must be defined if networking is desired.
+ */
+
+/* #undef  NETCOMMAND "uux - -n '%s!%s -u' >/dev/null 2>&1" */
+/* #define NETCOMMAND "usend -s -d%s -uNoLogin -!'%s -u' - 2>/dev/null" */
+#define NETCOMMAND ""
+
+/* Networking information -- should not vary among networking machines */
+
+struct network {
+    char *system;
+    char *rogue;
+};
+extern struct network Network[];
+extern unsigned long netread();
+extern unsigned long netwrite();
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xrogue/options.c	Tue Apr 21 08:55:20 2015 -0400
@@ -0,0 +1,501 @@
+/*
+    options.c - This file has all the code for the option command
+    
+    XRogue: Expeditions into the Dungeons of Doom
+    Copyright (C) 1991 Robert Pietkivitch
+    All rights reserved.
+    
+    Based on "Advanced Rogue"
+    Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka and AT&T
+    All rights reserved.
+
+    Based on "Rogue: Exploring the Dungeons of Doom"
+    Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
+    All rights reserved.
+    
+    See the file LICENSE.TXT for full copyright and licensing information.
+*/  
+    
+ /*
+ * I would rather this command were not necessary, but
+ * it is the only way to keep the wolves off of my back.
+ */
+
+#include <curses.h>
+#include <ctype.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 */
+    int         *o_opt;         /* pointer to thing to set */
+    int         (*o_putfunc)(); /* function to print value */
+    int         (*o_getfunc)(); /* function to get value interactively */
+};
+
+typedef struct optstruct        OPTION;
+
+int     put_bool(), 
+        get_bool(),
+        put_str(),
+        get_str(),
+        put_abil(),
+        get_abil(),
+        get_quest(),
+        put_quest(),
+    get_default();
+
+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        },
+    {"pickup",  "Pick things up automatically: ",
+                (int *) &auto_pickup,   put_bool,       get_bool        },
+    {"overlay", "Overlay menu: ",
+                (int *) &menu_overlay,  put_bool,       get_bool        },
+    {"name",    "Name: ",
+                (int *) whoami,         put_str,        get_str         },
+    {"file",    "Save file: ",
+                (int *) file_name,      put_str,        get_str         },
+    {"score",   "Score file: ",
+                (int *) score_file,     put_str,        get_str         },
+    {"class",   "Character type: ",
+                (int *) &char_type,     put_abil,       get_abil        },
+    {"quest",   "Quest item: ",
+                (int *) &quest_item,    put_quest,      get_quest       },
+    {"default", "Default Attributes: ",
+                (int *) &def_attr,      put_bool,    get_default     }
+};
+
+/*
+ * The default attribute field is read-only
+ */
+
+get_default(bp, win)
+bool *bp;
+WINDOW *win;
+{
+    register int oy, ox;
+
+    getyx(win, oy, ox);
+    put_bool(bp, win);
+    get_ro(win, oy, ox);
+}
+
+/*
+ * The ability (class) field is read-only
+ */
+
+get_abil(abil, win)
+int *abil;
+WINDOW *win;
+{
+    register int oy, ox;
+
+    getyx(win, oy, ox);
+    put_abil(abil, win);
+    get_ro(win, oy, ox);
+}
+
+/*
+ * The quest field is read-only
+ */
+
+get_quest(quest, win)
+int *quest;
+WINDOW *win;
+{
+    register int oy, ox;
+
+    getyx(win, oy, ox);
+    waddstr(win, rel_magic[*quest].mi_name);
+    get_ro(win, oy, ox);
+}
+
+/*
+ * get_ro:
+ *      "Get" a read-only value.
+ */
+
+get_ro(win, oy, ox)
+WINDOW *win;
+register int oy, ox;
+{
+    register int ny, nx;
+    register bool op_bad;
+    
+    op_bad = TRUE;
+    getyx(win, ny, nx);
+    while(op_bad)       
+    {
+        wmove(win, oy, ox);
+        draw(win);
+        switch (wgetch(win))
+        {
+            case '\n':
+            case '\r':
+                op_bad = FALSE;
+                break;
+            case '\033':
+            case '\007':
+                return QUIT;
+            case '-':
+                return MINUS;
+            default:
+                mvwaddstr(win, ny, nx + 5, "(no change allowed)");
+        }
+    }
+    wmove(win, ny, nx + 5);
+    wclrtoeol(win);
+    wmove(win, ny, nx);
+    waddch(win, '\n');
+    return NORM;
+}
+
+/*
+ * allow changing a boolean option and print it out
+ */
+
+get_bool(bp, win)
+bool *bp;
+WINDOW *win;
+{
+    register int oy, ox;
+    register bool op_bad;
+
+    op_bad = TRUE;
+    getyx(win, oy, ox);
+    waddstr(win, *bp ? "True" : "False");
+    while(op_bad)       
+    {
+        wmove(win, oy, ox);
+        draw(win);
+        switch (wgetch(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);
+    wclrtoeol(win);
+    waddstr(win, *bp ? "True" : "False");
+    waddch(win, '\n');
+    return NORM;
+}
+
+/*
+ * set a string option
+ */
+
+get_str(opt, win)
+register char *opt;
+WINDOW *win;
+{
+    register char *sp;
+    register int c, oy, ox;
+    char buf[LINELEN];
+
+    draw(win);
+    getyx(win, oy, ox);
+    /*
+     * loop reading in the string, and put it in a temporary buffer
+     */
+    for (sp = buf;
+        (c = wgetch(win)) != '\n'       && 
+        c != '\r'                       && 
+        c != '\033'                     && 
+        c != '\007'                     &&
+        sp < &buf[LINELEN-1];
+        wclrtoeol(win), draw(win))
+    {
+        if (c == -1)
+            continue;
+        else if (c == erasechar()) /* process erase character */
+        {
+            if (sp > buf)
+            {
+                register int i;
+
+                sp--;
+                for (i = strlen(unctrl(*sp)); i; i--)
+                    waddch(win, '\b');
+            }
+            continue;
+        }
+        else if (c == killchar()) /* process kill character */
+        {
+            sp = buf;
+            wmove(win, oy, ox);
+            continue;
+        }
+        else if (sp == buf)
+            if (c == '-' && win == hw)  /* To move back a line in hw */
+                break;
+            else if (c == '~')
+            {
+                strcpy(buf, home);
+                waddstr(win, home);
+                sp += strlen(home);
+                continue;
+            }
+        *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 == msgw)
+        mpos += sp - buf;
+    if (c == '-')
+        return MINUS;
+    else if (c == '\033' || c == '\007')
+        return QUIT;
+    else
+        return NORM;
+}
+
+/*
+ * print and then set options from the terminal
+ */
+
+option()
+{
+    register OPTION     *op;
+    register int        retval;
+
+    wclear(hw);
+    touchwin(hw);
+    /*
+     * Display current values of options
+     */
+    for (op = optlist; op < &optlist[NUM_OPTS]; op++)
+    {
+        waddstr(hw, op->o_prompt);
+        (*op->o_putfunc)(op->o_opt, hw);
+        waddch(hw, '\n');
+    }
+    /*
+     * Set values
+     */
+    wmove(hw, 0, 0);
+    for (op = optlist; op < &optlist[NUM_OPTS]; op++)
+    {
+        waddstr(hw, op->o_prompt);
+
+		retval = (*op->o_getfunc)(op->o_opt, hw);
+
+        if (retval)
+            if (retval == QUIT)
+                break;
+            else if (op > optlist) {    /* MINUS */
+                wmove(hw, (op - optlist) - 1, 0);
+                op -= 2;
+            }
+            else        /* trying to back up beyond the top */
+            {
+                putchar('\007');
+                wmove(hw, 0, 0);
+                op--;
+            }
+    }
+    /*
+     * Switch back to original screen
+     */
+    mvwaddstr(hw, lines-1, 0, spacemsg);
+    draw(hw);
+    wait_for(' ');
+    restscr(cw);
+    after = FALSE;
+}
+
+/*
+ * parse options from string, usually taken from the environment.
+ * the string is a series of comma seperated values, with booleans
+ * being stated as "name" (true) or "noname" (false), and strings
+ * being "name=....", with the string being defined up to a comma
+ * or the end of the entire option string.
+ */
+
+parse_opts(str)
+register char *str;
+{
+    register char *sp;
+    register OPTION *op;
+    register int len;
+
+    if (*str == '\"')
+       str++;
+
+    while (*str)
+    {
+        /*
+         * Get option name
+         */
+
+        for (sp = str; isalpha(*sp); sp++)
+            continue;
+        len = (char *)sp - str;
+        /*
+         * Look it up and deal with it
+         */
+        for (op = optlist; op < &optlist[NUM_OPTS]; op++)
+            if (EQSTR(str, op->o_name, len))
+            {
+                if (op->o_putfunc == put_bool)  /* if option is a boolean */
+                    *(bool *)op->o_opt = TRUE;
+                else                            /* string option */
+                {
+                    register char *start;
+                    char value[LINELEN];
+
+                    /*
+                     * Skip to start of string value
+                     */
+                    for (str = sp + 1; *str == '=' || *str == ':'; str++)
+                        continue;
+
+                    if (*str == '~')
+                    {
+                        strcpy((char *) value, home);
+                        start = (char *) value + strlen(home);
+                        while (*++str == '/')
+                            continue;
+                    }
+                    else
+                        start = (char *) value;
+                    /*
+                     * Skip to end of string value
+                     */
+                    for (sp = str + 1; *sp && *sp != ',' && *sp != '\"'; sp++)
+                        continue;
+                    strucpy(start, str, (char *) sp - str);
+
+                    /* Put the value into the option field */
+                    if (op->o_putfunc != put_abil) 
+                        strcpy((char *)op->o_opt, value);
+
+                    else if (*op->o_opt == -1) { /* Only init ability once */
+                        register int len = strlen(value);
+                        register int i;
+
+                        for (i=0; i<NUM_CHARTYPES-1; i++) {
+                            if (EQSTR(value, char_class[i].name, len)) {
+                                *op->o_opt = i;
+                                break;
+                            }
+                        }
+                    }
+                }
+                break;
+            }
+            /*
+             * check for "noname" for booleans
+             */
+            else if (op->o_putfunc == put_bool
+              && EQSTR(str, "no", 2) && EQSTR(str + 2, op->o_name, len - 2))
+            {
+                *(bool *)op->o_opt = FALSE;
+                break;
+            }
+
+        /*
+         * skip to start of next option name
+         */
+        while (*sp && !isalpha(*sp))
+            sp++;
+        str = sp;
+    }
+}
+
+
+/*
+ * print the default attributes
+ */
+
+/* put_default(b, win)
+ * bool *b;
+ * WINDOW *win;
+ * {
+ *     waddstr(win, *b ? "True" : "False");
+ * }
+ */
+
+/*
+ * print the character type
+ */
+
+put_abil(ability, win)
+int *ability;
+WINDOW *win;
+{
+    waddstr(win, char_class[*ability].name);
+}
+
+/*
+ * print out the quest
+ */
+
+put_quest(quest, win)
+int *quest;
+WINDOW *win;
+{
+    waddstr(win, rel_magic[*quest].mi_name);
+}
+
+/*
+ * put out a boolean
+ */
+
+put_bool(b, win)
+bool    *b;
+WINDOW *win;
+{
+    waddstr(win, *b ? "True" : "False");
+}
+
+/*
+ * put out a string
+ */
+
+put_str(str, win)
+char *str;
+WINDOW *win;
+{
+    waddstr(win, str);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xrogue/outside.c	Tue Apr 21 08:55:20 2015 -0400
@@ -0,0 +1,226 @@
+/*
+    outside.c  -  functions for dealing with the "outside" level
+
+    XRogue: Expeditions into the Dungeons of Doom
+    Copyright (C) 1991 Robert Pietkivitch
+    All rights reserved.
+    
+    Based on "Advanced Rogue"
+    Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka and AT&T
+    All rights reserved.
+
+    See the file LICENSE.TXT for full copyright and licensing information.
+*/
+
+#include <curses.h>
+#include "rogue.h"
+
+extern char rnd_terrain(), get_terrain();
+
+/*
+ * init_terrain:
+ *      Get the single "outside room" set up correctly
+ */
+
+void
+init_terrain()
+{
+    register struct room *rp;
+
+    for (rp = rooms; rp < &rooms[MAXROOMS]; rp++) {
+            rp->r_flags = ISGONE;       /* kill all rooms */
+            rp->r_fires = NULL;         /* no fires */
+    }
+    rp = &rooms[0];                     /* point to only room */
+    rp->r_flags = ISDARK;               /* outside is always dark */
+    rp->r_pos.x = 0;                    /* room fills whole screen */
+    rp->r_pos.y = 1;
+    rp->r_max.x = cols;
+    rp->r_max.y = lines - 3;
+}
+
+void
+do_terrain(basey, basex, deltay, deltax, fresh)
+int basey, basex, deltay, deltax;
+bool fresh;
+{
+    register int cury, curx;        /* Current y and x positions */
+
+    /* Lay out the boundary */
+    for (cury=1; cury<lines-2; cury++) {        /* Vertical "walls" */
+        mvaddch(cury, 0, VERTWALL);
+        mvaddch(cury, cols-1, VERTWALL);
+    }
+    for (curx=0; curx<cols; curx++) {           /* Horizontal "walls" */
+        mvaddch(1, curx, HORZWALL);
+        mvaddch(lines-3, curx, HORZWALL);
+    }
+
+    /* If we are not continuing, let's start out with a line of terrain */
+    if (fresh) {
+        char ch;        /* Next char to add */
+
+        /* Move to the starting point (should be (1, 0)) */
+        move(basey, basex);
+        curx = basex;
+
+        /* Start with some random terrain */
+        if (basex == 0) {
+            ch = rnd_terrain();
+            addch(ch);
+        }
+        else ch = mvinch(basey, basex);
+
+        curx += deltax;
+
+        /* Fill in the rest of the line */
+        while (curx > 0 && curx < cols-1) {
+            /* Put in the next piece */
+            ch = get_terrain(ch, '\0', '\0', '\0');
+            mvaddch(basey, curx, ch);
+            curx += deltax;
+        }
+
+        basey++;        /* Advance to next line */
+    }
+
+    /* Fill in the rest of the lines */
+    cury = basey;
+    while (cury > 1 && cury < lines - 3) {
+        curx = basex;
+        while (curx > 0 && curx < cols-1) {
+            register char left, top_left, top, top_right;
+            register int left_pos, top_pos;
+
+            /* Get the surrounding terrain */
+            left_pos = curx - deltax;
+            top_pos = cury - deltay;
+
+            left = mvinch(cury, left_pos);
+            top_left = mvinch(top_pos, left_pos);
+            top = mvinch(top_pos, curx);
+            top_right = mvinch(top_pos, curx + deltax);
+
+            /* Put the piece of terrain on the map */
+            mvaddch(cury, curx, get_terrain(left, top_left, top, top_right));
+
+            /* Get the next x coordinate */
+            curx += deltax;
+        }
+
+        /* Get the next y coordinate */
+        cury += deltay;
+    }
+        /* The deeper we go.. */
+        if (level > 40)         genmonsters(20, (bool) 0);
+        else if (level > 10)    genmonsters(15, (bool) 0);
+        else                    genmonsters(10, (bool) 0);
+
+        /* sometimes they're real angry */
+        if (rnd(100) < 65) {
+            /* protect good guys */
+            if (player.t_ctype == C_PALADIN ||
+                player.t_ctype == C_RANGER  || player.t_ctype == C_MONK) {
+                    aggravate(TRUE, FALSE);
+            }
+            else {
+                aggravate(TRUE, TRUE);
+            }
+        }
+}
+
+/*
+ * do_paths:
+ *      draw at least a single path-way through the terrain
+ */
+
+/*
+ * rnd_terrain:
+ *      return a weighted, random type of outside terrain
+ */
+
+char
+rnd_terrain()
+{
+    int chance = rnd(100);
+
+    /* Meadow is most likely */
+    if (chance < 40) return(FLOOR);
+
+    /* Next comes forest */
+    if (chance < 65) return(FOREST);
+
+    /* Then comes lakes */
+    if (chance < 85) return(POOL);
+
+    /* Finally, mountains */
+    return(WALL);
+}
+
+
+/*
+ * get_terrain:
+ *      return a terrain weighted by what is surrounding
+ */
+
+char
+get_terrain(one, two, three, four)
+char one, two, three, four;
+{
+    register int i;
+    int forest = 0, mountain = 0, lake = 0, meadow = 0, total = 0;
+    char surrounding[4];
+
+    surrounding[0] = one;
+    surrounding[1] = two;
+    surrounding[2] = three;
+    surrounding[3] = four;
+
+    for (i=0; i<4; i++) 
+        switch (surrounding[i]) {
+            case FOREST:
+                forest++;
+                total++;
+            
+            when WALL:
+                mountain++;
+                total++;
+
+            when POOL:
+                lake++;
+                total++;
+
+            when FLOOR:
+                meadow++;
+                total++;
+        }
+
+    /* Should we continue mountain? */
+    if (rnd(total+1) < mountain) return(WALL);
+
+    /* Should we continue lakes? */
+    if (rnd(total+1) < lake) return(POOL);
+
+    /* Should we continue meadow? */
+    if (rnd(total+1) < meadow) return(FLOOR);
+
+    /* Should we continue forest? */
+    if (rnd(total+2) < forest) return(FOREST);
+
+    /* Return something random */
+    return(rnd_terrain());
+}
+
+/*
+ * lake_check:
+ *      Determine if the player would drown
+ */
+
+/*UNUSED*/
+/* void
+ * lake_check(place)
+ * register coord *place;
+ * {
+ * }
+ */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xrogue/pack.c	Tue Apr 21 08:55:20 2015 -0400
@@ -0,0 +1,1582 @@
+/*
+    pack.c - Routines to deal with the pack.
+    
+    XRogue: Expeditions into the Dungeons of Doom
+    Copyright (C) 1991 Robert Pietkivitch
+    All rights reserved.
+    
+    Based on "Advanced Rogue"
+    Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka and AT&T
+    All rights reserved.
+
+    Based on "Rogue: Exploring the Dungeons of Doom"
+    Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
+    All rights reserved.
+    
+    See the file LICENSE.TXT for full copyright and licensing information.
+*/
+
+#include <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.
+ */
+
+bool
+add_pack(item, silent)
+register struct linked_list *item;
+bool silent;
+{
+    register struct linked_list *ip, *lp = NULL, *ap;
+    register struct object *obj, *op = NULL;
+    register bool exact, from_floor;
+    bool giveflag = 0;
+    static long cleric   = C_CLERIC,
+        monk     = C_MONK,
+        magician = C_MAGICIAN,
+        assassin = C_ASSASSIN,
+        druid    = C_DRUID,
+        thief    = C_THIEF,
+        fighter  = C_FIGHTER,
+        ranger   = C_RANGER,
+        paladin  = C_PALADIN;
+
+    if (item == NULL)
+    {
+        from_floor = TRUE;
+        if ((item = find_obj(hero.y, hero.x)) == NULL)
+            return(FALSE);
+    }
+    else
+        from_floor = FALSE;
+    obj = OBJPTR(item);
+    /*
+     * If it is gold, just add its value to rogue's purse and get rid
+     * of it.
+     */
+    if (obj->o_type == GOLD) {
+        register struct linked_list *mitem;
+        register struct thing *tp;
+
+        if (!silent) {
+            if (!terse) addmsg("You found ");
+            msg("%d gold pieces.", obj->o_count);
+        }
+
+        /* First make sure no greedy monster is after this gold.
+         * If so, make the monster run after the rogue instead.
+         */
+         for (mitem = mlist; mitem != NULL; mitem = next(mitem)) {
+            tp = THINGPTR(mitem);
+            if (tp->t_dest == &obj->o_pos) tp->t_dest = &hero;
+        }
+
+        purse += obj->o_count;
+        if (from_floor) {
+            detach(lvl_obj, item);
+            if ((ap = find_obj(hero.y, hero.x)) == NULL)
+                mvaddch(hero.y,hero.x,(roomin(&hero)==NULL ? PASSAGE : FLOOR));
+            else 
+                mvaddch(hero.y,hero.x,(OBJPTR(ap))->o_type);
+        }
+        o_discard(item);
+        return(TRUE);
+    }
+
+    /*
+     * see if he can carry any more weight
+     */
+    if (itemweight(obj) + pstats.s_pack > pstats.s_carry) {
+        msg("Too much for you to carry.");
+        return FALSE;
+    }
+    /*
+     * Link it into the pack.  Search the pack for a object of similar type
+     * if there isn't one, stuff it at the beginning, if there is, look for one
+     * that is exactly the same and just increment the count if there is.
+     * it  that.  Food is always put at the beginning for ease of access, but
+     * is not ordered so that you can't tell good food from bad.  First check
+     * to see if there is something in thr same group and if there is then
+     * increment the count.
+     */
+    if (obj->o_group)
+    {
+        for (ip = pack; ip != NULL; ip = next(ip))
+        {
+            op = OBJPTR(ip);
+            if (op->o_group == obj->o_group)
+            {
+                /*
+                 * Put it in the pack and notify the user
+                 */
+                op->o_count += obj->o_count;
+                if (from_floor)
+                {
+                    detach(lvl_obj, item);
+                    if ((ap = find_obj(hero.y, hero.x)) == NULL)
+                        mvaddch(hero.y,hero.x,
+                                (roomin(&hero)==NULL ? PASSAGE : FLOOR));
+                    else 
+                        mvaddch(hero.y,hero.x,(OBJPTR(ap))->o_type);
+                }
+                o_discard(item);
+                item = ip;
+                goto picked_up;
+            }
+        }
+    }
+
+    /*
+     * Check for and deal with scare monster scrolls
+     */
+    if (obj->o_type == SCROLL && obj->o_which == S_SCARE)
+        if (obj->o_flags & ISCURSED)
+        {
+            msg("The scroll turns to dust as you pick it up.");
+            detach(lvl_obj, item);
+            if ((ap = find_obj(hero.y, hero.x)) == NULL)
+                mvaddch(hero.y,hero.x,(roomin(&hero)==NULL ? PASSAGE : FLOOR));
+            else 
+                mvaddch(hero.y,hero.x,(OBJPTR(ap))->o_type);
+            return(TRUE);
+        }
+
+    /*
+     * Search for an object of the same type
+     */
+    exact = FALSE;
+    for (ip = pack; ip != NULL; ip = next(ip))
+    {
+        op = OBJPTR(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 = OBJPTR(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 = OBJPTR(ip);
+        }
+    }
+    /*
+     * Check if there is room
+     */
+    if (ip == NULL || !exact || !ISMULT(obj->o_type)) {
+        if (inpack == MAXPACK-1) {
+            msg(terse ? "No room." : "You can't carry anything else.");
+            return(FALSE);
+        }
+    }
+    inpack++;
+    if (from_floor)
+    {
+        detach(lvl_obj, item);
+        if ((ap = find_obj(hero.y, hero.x)) == NULL)
+            mvaddch(hero.y,hero.x,(roomin(&hero)==NULL ? PASSAGE : FLOOR));
+        else 
+            mvaddch(hero.y,hero.x,(OBJPTR(ap))->o_type);
+    }
+    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 food,
+         * increase the count, otherwise put it with its clones.
+         */
+        if (exact && ISMULT(obj->o_type))
+        {
+            op->o_count += obj->o_count;
+            inpack--;                   /* adjust for previous addition */
+            o_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 = OBJPTR(item);
+    if (!silent)
+    {
+        if (!terse)
+            addmsg("You now have ");
+        msg("%s (%c)", inv_name(obj, !terse), pack_char(pack, obj));
+    }
+
+    /* Relics do strange things when you pick them up */
+    if (obj->o_type == RELIC) {
+        switch (obj->o_which) {
+            /* the ankh of Heil gives you prayers */
+            case HEIL_ANKH:
+                msg("The ankh welds itself into your hand. ");
+                if (player.t_ctype != C_CLERIC && player.t_ctype != C_PALADIN)
+                    fuse(prayer_recovery, (VOID *)NULL, SPELLTIME, AFTER);
+        /* start a fuse to change player into a paladin */
+        if (quest_item != HEIL_ANKH) {
+            msg("You hear a strange, distant hypnotic calling... ");
+            if (player.t_ctype != C_PALADIN && obj->o_which ==HEIL_ANKH)
+                        fuse(changeclass, &paladin, roll(8, 8), AFTER);
+        }
+
+            /* A cloak must be worn. */
+            when EMORI_CLOAK:
+                if (cur_armor != NULL || cur_misc[WEAR_CLOAK]) {
+                    msg("The cloak insists you remove your current garments.");
+                    if (!dropcheck(cur_armor != NULL ? cur_armor
+                                                     : cur_misc[WEAR_CLOAK])) {
+                        pstats.s_hpt = -1;
+                        msg("The cloak constricts around you...");
+                        msg("It draws your life force from you!!!  --More--");
+                        wait_for(' ');
+                        death(D_RELIC);
+                    }
+                }
+                if (obj->o_charges < 0) /* should never happen, but.... */
+                    obj->o_charges = 0;
+                if (obj->o_charges == 0)
+                        fuse(cloak_charge, obj, CLOAK_TIME, AFTER);
+        /* start a fuse to change player into a monk */
+        if (quest_item != EMORI_CLOAK) {
+            msg("You suddenly become calm and quiet. ");
+            if (player.t_ctype != C_MONK && obj->o_which == EMORI_CLOAK)
+                        fuse(changeclass, &monk, roll(8, 8), AFTER);
+        }
+
+            /* The amulet must be worn. */
+            when STONEBONES_AMULET:
+            case YENDOR_AMULET:
+                if (cur_misc[WEAR_JEWEL] || cur_relic[STONEBONES_AMULET] ||
+                    cur_relic[YENDOR_AMULET]) {
+                        msg("You have an urge to remove your current amulet.");
+                }
+                if((cur_misc[WEAR_JEWEL] && !dropcheck(cur_misc[WEAR_JEWEL])) ||
+                    cur_relic[STONEBONES_AMULET] || cur_relic[YENDOR_AMULET]) {
+                        pstats.s_hpt = -1;
+                        msg("The %s begins pulsating... ",inv_name(obj, TRUE));
+                        msg("It fades completely away!  --More--");
+                        wait_for(' ');
+                        death(D_RELIC);
+                }
+                msg("The %s welds itself into your chest. ",inv_name(obj,TRUE));
+        /* start a fuse to change into a magician */
+        if (quest_item != STONEBONES_AMULET) {
+            if (player.t_ctype != C_MAGICIAN &&
+            obj->o_which == STONEBONES_AMULET) {
+                msg("You sense approaching etheric forces... ");
+                        fuse(changeclass, &magician, roll(8, 8), AFTER);
+            }
+        }
+
+            /* The eye is now inserted in forehead */
+            when EYE_VECNA:
+                msg("The eye forces itself into your forehead! ");
+                pstats.s_hpt -= (rnd(80)+21);
+                if (pstats.s_hpt <= 0) {
+                       pstats.s_hpt = -1;
+                       msg ("The pain is too much for you to bear!  --More--");
+                       wait_for(' ');
+                       death(D_RELIC);
+                }
+                waste_time();
+                msg("The excruciating pain slowly turns into a dull throb.");
+        /* start a fuse to change player into an assassin */
+        if (quest_item != EYE_VECNA) {
+            msg("Your blood rushes and you begin to sweat profusely... ");
+            if (player.t_ctype != C_ASSASSIN && obj->o_which == EYE_VECNA)
+                        fuse(changeclass, &assassin, roll(8, 8), AFTER);
+        }
+                
+            when QUILL_NAGROM:
+                fuse(quill_charge,(VOID *)NULL, 8, AFTER);
+        /* start a fuse to change player into a druid */
+        if (quest_item != QUILL_NAGROM) {
+            msg("You begin to see things differently... ");
+            if (player.t_ctype != C_DRUID && obj->o_which == QUILL_NAGROM)
+                        fuse(changeclass, &druid, roll(8, 8), AFTER);
+        }
+
+            /* Weapons will insist on being wielded. */
+            when MUSTY_DAGGER:
+            case HRUGGEK_MSTAR:
+            case YEENOGHU_FLAIL:
+            case AXE_AKLAD:
+                /* set a daemon to eat gold for daggers and axe */
+        if (obj->o_which == MUSTY_DAGGER || obj->o_which == AXE_AKLAD) {
+                    if (purse > 0) msg("Your purse feels lighter! ");
+                    else purse = 1; /* fudge to get right msg from eat_gold() */
+
+                    eat_gold(obj);
+                    daemon(eat_gold, obj, AFTER);
+                }
+        /* start a fuse to change player into a thief */
+        if (quest_item != MUSTY_DAGGER) {
+            if (player.t_ctype != C_THIEF &&
+            obj->o_which == MUSTY_DAGGER) {
+                msg("You look about furtively. ");
+                        fuse(changeclass, &thief, roll(8, 8), AFTER);
+            }
+        }
+        /* start a fuse to change player into a fighter */
+        if (quest_item != AXE_AKLAD) {
+            if (player.t_ctype != C_FIGHTER &&
+            obj->o_which == AXE_AKLAD) {
+                msg("Your bones feel strengthened. ");
+                        fuse(changeclass, &fighter, roll(8, 8), AFTER);
+            }
+                }
+                if (cur_weapon != NULL) {
+                    msg("The artifact insists you release your current weapon!");
+                    if (!dropcheck(cur_weapon)) {
+                        pstats.s_hpt = -1;
+                        msg("The artifact forces your weapon into your heart! ");
+                        msg("It hums with satisfaction!  --More--");
+                        wait_for(' ');
+                        death(D_RELIC);
+                    }
+                }
+                cur_weapon = obj;
+
+        /* acquire a sense of smell */
+            when SURTUR_RING:
+                msg("The ring forces itself through your nose!");
+                pstats.s_hpt -= rnd(40)+1;
+                if (pstats.s_hpt < 0) {
+            pstats.s_hpt = -1;
+                        msg("The pain is too much for you to bear!  --More--");
+                        wait_for(' ');
+                        death(D_RELIC);
+                }
+                waste_time();
+                turn_on(player, NOFIRE);
+                msg("The pain slowly subsides.. ");
+
+        /* become a wandering musician */
+        when BRIAN_MANDOLIN:
+        msg("You hear an ancient haunting sound... ");
+        /* start a fuse to change player into a ranger */
+        if (quest_item != BRIAN_MANDOLIN) {
+            msg("You are transfixed with empathy. ");
+            if (player.t_ctype != C_RANGER && obj->o_which == BRIAN_MANDOLIN)
+                        fuse(changeclass, &ranger, roll(8, 8), AFTER);
+        }
+
+        /* add to the music */
+        when GERYON_HORN:
+        msg("You begin to hear trumpets!");
+        /* start a fuse to change player into a cleric */
+        if (quest_item != GERYON_HORN) {
+            msg("You follow their calling. ");
+            if (player.t_ctype != C_CLERIC && obj->o_which == GERYON_HORN)
+                        fuse(changeclass, &cleric, roll(8, 8), AFTER);
+        }
+
+        /* the card can not be picked up, it must be traded for */
+        when ALTERAN_CARD:
+                if (giveflag == FALSE) {
+            if (!wizard) {
+            msg("You look at the dark card and it chills you to the bone!!  ");
+                msg("You stand for a moment, face to face with death...  --More--");
+                        wait_for(' ');
+                pstats.s_hpt = -1;
+                        death(D_CARD);
+            }
+            else {
+            msg("Got it! ");
+                        if (purse > 0) msg("Your purse feels lighter! ");
+                        else purse = 1; /* fudge to get right msg */
+
+                        eat_gold(obj);
+                        daemon(eat_gold, obj, AFTER);
+            }
+        }
+        else {
+            msg("You accept it hesitantly...  ");
+                    if (purse > 0) msg("Your purse feels lighter! ");
+                    else purse = 1; /* fudge to get right msg */
+
+                    eat_gold(obj);
+                    daemon(eat_gold, obj, AFTER);
+                }
+
+        otherwise:
+                break;
+        }
+        cur_relic[obj->o_which]++;      /* Note that we have it */
+    }
+
+    updpack(FALSE, &player);
+    return(TRUE);
+}
+
+/*
+ * inventory:
+ *      list what is in the pack
+ */
+
+inventory(list, type)
+register struct linked_list *list;
+register int type;
+{
+    register struct object *obj;
+    register char ch;
+    register int n_objs, cnt, maxx = 0, curx;
+    char inv_temp[2*LINELEN+1];
+
+    cnt = 0;
+    n_objs = 0;
+    for (ch = 'a'; list != NULL; ch++, list = next(list)) {
+        obj = OBJPTR(list);
+        if (!is_type(obj, type))
+            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');
+
+                    maxx = strlen(inv_temp);    /* Length of the listing */
+                }
+            /*
+             * Print the line for this object
+             */
+            default:
+                if (ch > 'z')
+                    ch = 'A';
+                if (slow_invent)
+                    msg("%c) %s", ch, inv_name(obj, FALSE));
+                else {
+                    if (++cnt >= lines - 2) { /* if bottom of screen */
+                        dbotline(hw, morestr);
+                        cnt = 0;
+                        wclear(hw);
+                    }
+                    sprintf(inv_temp, "%c) %s\n", ch, inv_name(obj, FALSE));
+                    curx = strlen(inv_temp) - 1; /* Don't count new-line */
+                    if (curx > maxx) maxx = curx;
+                    waddstr(hw, inv_temp);
+                }
+        }
+    }
+    if (n_objs == 0) {
+        if (terse)
+            msg(type == ALL ? "Empty-handed." :
+                            "Nothing appropriate");
+        else
+            msg(type == ALL ? "You are empty-handed." :
+                            "You don't have anything appropriate");
+        return FALSE;
+    }
+    if (n_objs == 1) {
+        msg(inv_temp);
+        return TRUE;
+    }
+    if (!slow_invent)
+    {
+        waddstr(hw, spacemsg);
+        curx = strlen(spacemsg);
+        if (curx > maxx) maxx = curx;
+
+        /*
+         * If we have fewer than half a screenful, don't clear the screen.
+         * Leave an extra blank line at the bottom and 3 blank columns
+         * to he right.
+         */
+        if (menu_overlay && n_objs < lines - 3) {
+            over_win(cw, hw, n_objs + 2, maxx + 3, n_objs, curx, ' ');
+            return TRUE;
+        }
+
+        draw(hw);
+        wait_for(' ');
+        restscr(cw);
+    }
+    return TRUE;
+}
+
+/*
+ * picky_inven:
+ *      Allow player to inventory a single item
+ */
+
+void
+picky_inven()
+{
+    register struct linked_list *item;
+    register char ch, mch;
+
+    if (pack == NULL)
+        msg("You aren't carrying anything");
+    else if (next(pack) == NULL)
+        msg("a) %s", inv_name(OBJPTR(pack), FALSE));
+    else
+    {
+        msg(terse ? "Item: " : "Which item do you wish to inventory: ");
+        mpos = 0;
+        if ((mch = wgetch(cw)) == ESC)
+        {
+            msg("");
+            return;
+        }
+
+        /* Check for a special character */
+        switch (mch) {
+            case FOOD:
+            case SCROLL:
+            case POTION:
+            case RING:
+            case STICK:
+            case RELIC:
+            case ARMOR:
+            case WEAPON:
+            case MM:
+                msg("");
+                if (get_item(pack, (char *)NULL, mch, FALSE, FALSE) == NULL) {
+                    if (terse) msg("No '%c' in your pack.", mch);
+                    else msg("You have no '%c' in your pack.", mch);
+                }
+                return;
+        }
+
+        for (ch = 'a', item = pack; item != NULL; item = next(item), ch++)
+            if (ch == mch)
+            {
+                msg("%c) %s",ch,inv_name(OBJPTR(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(list, purpose, type, askfirst, showcost)
+reg struct linked_list *list;
+char *purpose;  /* NULL if we should be silent (no prompts) */
+int type;
+bool askfirst, showcost;
+{
+    reg struct linked_list *item;
+    reg struct object *obj;
+    reg int cnt, pagecnt, ch, och, maxx, curx, confused;
+    struct linked_list *saveitem = NULL;
+    char description[2*LINELEN+1];
+    char cost[LINELEN/2];
+    char cap_purpose[LINELEN];  /* capitalize the "doings" */
+
+    cap_purpose[0] = '\0';
+
+    /* Get a capitalized purpose for starting sentences */
+    if (purpose) {
+            strcpy(cap_purpose, purpose);
+            cap_purpose[0] = toupper(cap_purpose[0]);
+    }
+
+    /*
+     * If this is the player's pack and the player is confused, we
+     * might just take anything.
+     */
+    if (list == player.t_pack && on(player, ISHUH) && rnd(100) < 70)
+        confused = 1;
+    else confused = 0;
+
+    cnt = 0;
+    if (list == NULL) {
+        msg("You aren't carrying anything.");
+        return NULL;
+    }
+    /* see if we have any of the type requested */
+    for(ch = 'a',item = list ; item != NULL ; item = next(item), ch++) {
+        obj = OBJPTR(item);
+        if (is_type(obj, type)) {
+            cnt++;
+            saveitem = item;
+        }
+    }
+    if (cnt == 0) {
+        if (purpose) msg("Nothing to %s", purpose);
+        after = FALSE;
+        return NULL;
+    }
+    else if (cnt == 1) {        /* only found one of 'em */
+        obj = OBJPTR(saveitem);
+        for(;;)  {
+            if (purpose) {      /* Should we prompt the player? */
+                msg("%s what (* for the item)?", cap_purpose);
+                ch = wgetch(cw);
+            }
+            else {
+                ch = pack_char(list, obj);
+                msg("%c) %s", ch, inv_name(obj,FALSE));
+            }
+
+            if (ch == '*') {
+                mpos = 0;
+                msg("%c) %s",pack_char(list, obj),inv_name(obj,FALSE));
+                continue;
+            }
+            if (ch == ESC) {
+                msg("");
+                after = FALSE;
+                return NULL;
+            }
+            for(item = list,och = 'a'; item != NULL; item = next(item),och++) {
+                if (ch == och) break;
+                if (och == 'z') och = 'A' - 1;
+            }
+            if (item == NULL) {
+                msg("Please specify a letter between 'a' and '%c'",
+                    och == 'A' ? 'z' : och-1);
+                continue;
+            }
+            if (is_type (OBJPTR(item), type)) {
+                if (purpose) mpos = 0;
+                return item;
+            }
+            else
+                msg ("You can't %s that!", purpose);
+
+        } 
+    }
+    for(;;) {
+        if (!askfirst && purpose) {
+            msg("%s what? (* for list): ", cap_purpose);
+            ch = wgetch(cw);
+        }
+        else ch = '*';
+
+        mpos = 0;
+        if (ch == ESC) {                /* abort if escape hit */
+            after = FALSE;
+            msg("");            /* clear display */
+            return NULL;
+        }
+
+        if (ch == '*') {
+            wclear(hw);
+            pagecnt = 0;
+            maxx = 0;
+            for(item = list,ch = 'a'; item != NULL ; item = next(item), ch++) {
+                obj = OBJPTR(item);
+                if (!is_type(OBJPTR(item), type))
+                    continue;
+                cost[0] = '\0';
+                if (showcost) {
+                    sprintf(description, "[%ld] ", get_worth(obj));
+                    sprintf(cost, "%8.8s", description);
+                }
+                sprintf(description,"%c) %s%s\n\r",ch,cost,inv_name(obj,FALSE));
+                waddstr(hw, description);
+                curx = strlen(description) - 2; /* Don't count \n or \r */
+                if (maxx < curx) maxx = curx;
+                if (++pagecnt >= lines - 2 && next(item) != NULL) {
+                    pagecnt = 0;
+                    dbotline(hw, spacemsg);
+                    wclear(hw);
+                }
+                if (ch == 'z') ch = 'A' - 1;
+            }
+
+            /* Put in the prompt */
+            if (purpose) sprintf(description, "%s what? ", cap_purpose);
+            else strcpy(description, spacemsg);
+            waddstr(hw, description);
+            curx = strlen(description);
+            if (maxx < curx) maxx = curx;
+
+            /* Write the screen */
+            if ((menu_overlay && cnt < lines - 3) || cnt == 1) {
+                over_win(cw, hw, cnt + 2, maxx + 3, cnt, curx, NULL);
+                cnt = -1;       /* Indicate we used over_win */
+            }
+            else draw(hw);
+
+            if (purpose) {
+                do {
+                    ch = wgetch(cw);
+                } until (isalpha(ch) || ch == ESC);
+            }
+            else {
+                ch = pack_char(list, OBJPTR(saveitem)); /* Pick a valid item */
+                wait_for(' ');
+            }
+
+            /* Redraw original screen */
+            if (cnt < 0) {
+                clearok(cw, FALSE);     /* Setup to redraw current screen */
+                touchwin(cw);   /* clearing first */
+                draw(cw);
+            }
+            else restscr(cw);
+
+            if(ch == ESC) {
+                after = FALSE;
+                msg("");                /* clear top line */
+                return NULL;    /* all done if abort */
+            }
+            /* ch has item to get from list */
+        }
+
+        for (item = list,och = 'a'; item != NULL; item = next(item),och++) {
+            if (confused) {
+                /*
+                 * Confused is incremented each time so that if the rnd(cnt)
+                 * clause keeps failing, confused will equal cnt for the
+                 * last item of the correct type and rnd(cnt) < cnt will
+                 * have to be true.
+                 */
+                if (is_type(OBJPTR(item), type) && rnd(cnt) < confused++)
+                    break;
+            }
+            else if (ch == och) break;
+            if (och == 'z') och = 'A' - 1;
+        }
+
+        if (item == NULL) {
+            msg("Please specify a letter between 'a' and '%c'  ",
+                och == 'A' ? 'z' : och-1);
+            continue;
+        }
+
+        if (is_type(OBJPTR(item), type))
+            return (item);
+        else
+            msg ("You can't %s that!", purpose);
+    }
+}
+
+pack_char(list, obj)
+register struct object *obj;
+struct linked_list *list;
+{
+    register struct linked_list *item;
+    register char c;
+
+    c = 'a';
+    for (item = list; item != NULL; item = next(item)) {
+        if (OBJPTR(item) == obj)
+            return c;
+        else {
+            if (c == 'z') c = 'A';
+            else c++;
+        }
+    }
+    return 'z';
+}
+
+/*
+ * cur_null:
+ *      This updates cur_weapon etc for dropping things
+ */
+
+cur_null(op)
+reg struct object *op;
+{
+        if (op == cur_weapon)             cur_weapon = NULL;
+        else if (op == cur_armor)         cur_armor = NULL;
+        else if (op == cur_ring[LEFT_1])  cur_ring[LEFT_1] = NULL;
+        else if (op == cur_ring[LEFT_2])  cur_ring[LEFT_2] = NULL;
+        else if (op == cur_ring[LEFT_3])  cur_ring[LEFT_3] = NULL;
+        else if (op == cur_ring[LEFT_4])  cur_ring[LEFT_4] = NULL;
+        else if (op == cur_ring[RIGHT_1]) cur_ring[RIGHT_1] = NULL;
+        else if (op == cur_ring[RIGHT_2]) cur_ring[RIGHT_2] = NULL;
+        else if (op == cur_ring[RIGHT_3]) cur_ring[RIGHT_3] = NULL;
+        else if (op == cur_ring[RIGHT_4]) cur_ring[RIGHT_4] = NULL;
+        else if (op == cur_misc[WEAR_BOOTS])    cur_misc[WEAR_BOOTS] = NULL;
+        else if (op == cur_misc[WEAR_JEWEL])    cur_misc[WEAR_JEWEL] = NULL;
+        else if (op == cur_misc[WEAR_GAUNTLET]) cur_misc[WEAR_GAUNTLET] = NULL;
+        else if (op == cur_misc[WEAR_CLOAK])    cur_misc[WEAR_CLOAK] = NULL;
+        else if (op == cur_misc[WEAR_BRACERS])  cur_misc[WEAR_BRACERS] = NULL;
+        else if (op == cur_misc[WEAR_NECKLACE]) cur_misc[WEAR_NECKLACE] = NULL;
+}
+
+/*
+ * idenpack:
+ *      Identify all the items in the pack
+ */
+
+idenpack()
+{
+        reg struct linked_list *pc;
+
+        for (pc = pack ; pc != NULL ; pc = next(pc))
+                whatis(pc);
+}
+
+is_type (obj, type)
+register struct object *obj;
+register int type;
+{
+    register bool current;
+
+    if (type == obj->o_type)
+        return (TRUE);
+
+    switch (type) {
+        case ALL:
+            return (TRUE);
+        when READABLE:
+            if (obj->o_type == SCROLL ||
+                (obj->o_type == MM && obj->o_which == MM_SKILLS))
+                    return (TRUE);
+        when QUAFFABLE:
+            if (obj->o_type == POTION ||
+                (obj->o_type == MM && obj->o_which == MM_JUG))
+                    return (TRUE);
+        when ZAPPABLE:
+            if (obj->o_type == STICK) return (TRUE);
+            if (obj->o_type == RELIC)
+                switch (obj->o_which) {
+                    case MING_STAFF:
+                    case ASMO_ROD:
+                    case ORCUS_WAND:
+                    case EMORI_CLOAK:
+                        return (TRUE);
+                }
+        when WEARABLE:
+        case REMOVABLE:
+            current = is_current(obj);
+
+            /*
+             * Don't wear thing we are already wearing or remove things
+             * we aren't wearing.
+             */
+            if (type == WEARABLE && current) return (FALSE);
+            else if (type == REMOVABLE && !current) return (FALSE);
+
+            switch (obj->o_type) {
+                case RELIC:
+                    switch (obj->o_which) {
+                        case HEIL_ANKH:
+                        case EMORI_CLOAK:
+                            return (TRUE);
+                    }
+                when MM:
+                    switch (obj->o_which) {
+                        case MM_ELF_BOOTS:
+                        case MM_DANCE:
+                        case MM_BRACERS:
+                        case MM_DISP:
+                        case MM_PROTECT:
+                        case MM_G_DEXTERITY:
+                        case MM_G_OGRE:
+                        case MM_JEWEL:
+                        case MM_R_POWERLESS:
+                        case MM_FUMBLE:
+                        case MM_STRANGLE:
+                        case MM_ADAPTION:
+                            return (TRUE);
+                    }
+                when ARMOR:
+                case RING:
+                    return (TRUE);
+            }
+        when CALLABLE:
+            switch (obj->o_type) {
+            case RING:          if (!r_know[obj->o_which]) return(TRUE);
+            when POTION:        if (!p_know[obj->o_which]) return(TRUE);
+            when STICK:         if (!ws_know[obj->o_which]) return(TRUE);
+            when SCROLL:        if (!s_know[obj->o_which]) return(TRUE);
+            when MM:            if (!m_know[obj->o_which]) return(TRUE);
+            }
+        when WIELDABLE:
+            switch (obj->o_type) {
+                case STICK:
+                case WEAPON:
+                    return(TRUE);
+                when RELIC:
+                    switch (obj->o_which) {
+                        case MUSTY_DAGGER:
+                        case HRUGGEK_MSTAR:
+                        case YEENOGHU_FLAIL:
+                        case AXE_AKLAD:
+                        case MING_STAFF:
+                        case ORCUS_WAND:
+                        case ASMO_ROD:
+                            return(TRUE);
+                    }
+            }
+        when IDENTABLE:
+            if (!(obj->o_flags & ISKNOW) && obj->o_type != FOOD)
+                return (TRUE);
+            if (obj->o_type == MM) {
+              switch (obj->o_which) {
+                case MM_JUG:
+                    /* Can still identify a jug if we don't know the potion */
+                    if (obj->o_ac != JUG_EMPTY && !p_know[obj->o_ac])
+                        return (TRUE);
+              }
+            }
+        when USEABLE:
+            if (obj->o_type == MM) {
+                switch(obj->o_which) {
+                case MM_BEAKER:
+                case MM_BOOK:
+                case MM_OPEN:
+                case MM_HUNGER:
+                case MM_DRUMS:
+                case MM_DISAPPEAR:
+                case MM_CHOKE:
+                case MM_KEOGHTOM:
+                case MM_CRYSTAL:
+                    return (TRUE);
+                }
+            }
+            else if (obj->o_type == RELIC) {
+                switch (obj->o_which) {
+                    case EMORI_CLOAK:
+                    case BRIAN_MANDOLIN:
+                    case HEIL_ANKH:
+                    case YENDOR_AMULET:
+                    case STONEBONES_AMULET:
+                    case GERYON_HORN:
+                    case EYE_VECNA:
+                    case QUILL_NAGROM:
+                    case SURTUR_RING:
+                    case ALTERAN_CARD:
+                        return (TRUE);
+                }
+            }
+            else if (obj->o_type == POTION) {
+                /*
+                 * only assassins can use poison
+                 */
+                if (player.t_ctype == C_ASSASSIN && obj->o_which == P_POISON)
+                    return(TRUE);
+            }
+        when PROTECTABLE:
+            switch (obj->o_type) {
+                case WEAPON:
+                    if ((obj->o_flags & ISMETAL) == 0) return (FALSE);
+
+                    /* Fall through */
+                case ARMOR:
+                    return (TRUE);
+
+                when MM:
+                    if (obj->o_which == MM_BRACERS) return (TRUE);
+            }
+    }
+    return(FALSE);
+}
+
+del_pack(item)
+register struct linked_list *item;
+{
+    register struct object *obj;
+
+    obj = OBJPTR(item);
+    if (obj->o_count > 1) {
+        obj->o_count--;
+    }
+    else {
+        cur_null(obj);
+        detach(pack, item);
+        o_discard(item);
+        inpack--;
+    }
+}
+
+/*
+ * carry_obj:
+ *      Check to see if a monster is carrying something and, if so, give
+ * it to him.
+ */
+
+carry_obj(mp, chance)
+register struct thing *mp;
+int chance;
+{
+    reg struct linked_list *item;
+    reg struct object *obj;
+
+    /* 
+     * If there is no chance, just return.
+     * Note that this means there must be a "chance" in order for
+     * the creature to carry a relic.
+     */
+    if (chance <= 0) return;
+
+    /* 
+     * check for the relic/artifacts 
+     * Do the relics first so they end up last in the pack. Attach()
+     * always adds things to the beginning. This way they will be the
+     * last things dropped when the creature is killed. This will ensure
+     * the relic will be on top if there is a stack of item lying on the
+     * floor and so the hero will know where it is if he's trying to
+     * avoid it. Note that only UNIQUEs carry relics.
+     */
+    if (on(*mp, ISUNIQUE)) {
+        if (on(*mp, CARRYMDAGGER)) {
+            item = spec_item(RELIC, MUSTY_DAGGER, NULL, NULL);
+            obj = OBJPTR(item);
+            obj->o_pos = mp->t_pos;
+            attach(mp->t_pack, item);
+        }
+
+        if (on(*mp, CARRYCLOAK)) {
+            item = spec_item(RELIC, EMORI_CLOAK, NULL, NULL);
+            obj = OBJPTR(item);
+            obj->o_pos = mp->t_pos;
+            attach(mp->t_pack, item);
+        }
+
+        if (on(*mp, CARRYANKH)) {
+            item = spec_item(RELIC, HEIL_ANKH, NULL, NULL);
+            obj = OBJPTR(item);
+            obj->o_pos = mp->t_pos;
+            attach(mp->t_pack, item);
+        }
+
+        if (on(*mp, CARRYSTAFF)) {
+            item = spec_item(RELIC, MING_STAFF, NULL, NULL);
+            obj = OBJPTR(item);
+            obj->o_pos = mp->t_pos;
+            attach(mp->t_pack, item);
+        }
+
+        if (on(*mp, CARRYWAND)) {
+            item = spec_item(RELIC, ORCUS_WAND, NULL, NULL);
+            obj = OBJPTR(item);
+            obj->o_pos = mp->t_pos;
+            attach(mp->t_pack, item);
+        }
+
+        if (on(*mp, CARRYROD)) {
+            item = spec_item(RELIC, ASMO_ROD, NULL, NULL);
+            obj = OBJPTR(item);
+            obj->o_pos = mp->t_pos;
+            attach(mp->t_pack, item);
+        }
+
+        if (on(*mp, CARRYYAMULET)) {
+            item = spec_item(RELIC, YENDOR_AMULET, NULL, NULL);
+            obj = OBJPTR(item);
+            obj->o_pos = mp->t_pos;
+            attach(mp->t_pack, item);
+        }
+
+        if (on(*mp, CARRYBAMULET)) {
+            item = spec_item(RELIC, STONEBONES_AMULET, NULL, NULL);
+            obj = OBJPTR(item);
+            obj->o_pos = mp->t_pos;
+            attach(mp->t_pack, item);
+        }
+
+        if (on(*mp, CARRYMANDOLIN)) {
+            item = spec_item(RELIC, BRIAN_MANDOLIN, NULL, NULL);
+            obj = OBJPTR(item);
+            obj->o_pos = mp->t_pos;
+            attach(mp->t_pack, item);
+        }
+        if (on(*mp, CARRYEYE)) {
+            item = spec_item(RELIC, EYE_VECNA, NULL, NULL);
+            obj = OBJPTR(item);
+            obj->o_pos = mp->t_pos;
+            attach(mp->t_pack, item);
+        }
+        if (on(*mp, CARRYAXE)) {
+            item = spec_item(RELIC, AXE_AKLAD, NULL, NULL);
+            obj = OBJPTR(item);
+            obj->o_pos = mp->t_pos;
+            attach(mp->t_pack, item);
+        }
+        if (on(*mp, CARRYQUILL)) {
+            register int i, howmany;
+
+            item = spec_item(RELIC, QUILL_NAGROM, NULL, NULL);
+            obj = OBJPTR(item);
+            obj->o_pos = mp->t_pos;
+            obj->o_charges = rnd(QUILLCHARGES);
+            attach(mp->t_pack, item);
+            howmany = roll(4,3);
+            for (i=0; i<howmany; i++) {
+                /*
+                 * the quill writes scrolls so give him a bunch
+                 */
+                item = new_thing(TYP_SCROLL, FALSE);
+                obj = OBJPTR(item);
+                obj->o_pos = mp->t_pos;
+                attach(mp->t_pack, item);
+            }
+        }
+        if (on(*mp, CARRYMSTAR)) {
+            item = spec_item(RELIC, HRUGGEK_MSTAR, NULL, NULL);
+            obj = OBJPTR(item);
+            obj->o_pos = mp->t_pos;
+            attach(mp->t_pack, item);
+        }
+        if (on(*mp, CARRYFLAIL)) {
+            item = spec_item(RELIC, YEENOGHU_FLAIL, NULL, NULL);
+            obj = OBJPTR(item);
+            obj->o_pos = mp->t_pos;
+            attach(mp->t_pack, item);
+        }
+        if (on(*mp, CARRYHORN)) {
+            item = spec_item(RELIC, GERYON_HORN, NULL, NULL);
+            obj = OBJPTR(item);
+            obj->o_pos = mp->t_pos;
+            attach(mp->t_pack, item);
+        }
+        if (on(*mp, CARRYSURTURRING)) {
+            item = spec_item(RELIC, SURTUR_RING, NULL, NULL);
+            obj = OBJPTR(item);
+            obj->o_pos = mp->t_pos;
+            attach(mp->t_pack, item);
+        }
+        if (on(*mp, CARRYCARD)) {
+            item = spec_item(RELIC, ALTERAN_CARD, NULL, NULL);
+            obj = OBJPTR(item);
+            obj->o_pos = mp->t_pos;
+            attach(mp->t_pack, item);
+        }
+    }
+    /*
+     * If it carries gold, give it some
+     */
+    if (on(*mp, CARRYGOLD) && rnd(100) < chance) {
+            item = spec_item(GOLD, NULL, NULL, NULL);
+            obj = OBJPTR(item);
+            obj->o_count = GOLDCALC + GOLDCALC;
+            obj->o_pos = mp->t_pos;
+            attach(mp->t_pack, item);
+    }
+
+    /*
+     * If it carries food, give it some
+     */
+    if (on(*mp, CARRYFOOD) && rnd(100) < chance) {
+        int type;
+        switch (rnd(41)) {
+            case 3:  type = E_APPLE;
+            when 6:  type = E_HAGBERRY;
+            when 9:  type = E_SOURSOP;
+            when 12: type = E_RAMBUTAN;
+            when 15: type = E_DEWBERRY;
+            when 18: type = E_CANDLEBERRY;
+            when 21: type = E_BANANA;
+            when 24: type = E_CAPRIFIG;
+            when 27: type = E_STRAWBERRY;
+            when 30: type = E_GOOSEBERRY;
+            when 33: type = E_ELDERBERRY;
+            when 36: type = E_BLUEBERRY;
+            when 40: type = E_SLIMEMOLD;  /* monster food */
+            otherwise: type = E_RATION;
+        }
+        item = spec_item(FOOD, type, NULL, NULL);
+        obj = OBJPTR(item);
+        obj->o_weight = things[TYP_FOOD].mi_wght;
+        obj->o_pos = mp->t_pos;
+        attach(mp->t_pack, item);
+    }
+
+    /*
+     * If it carries a weapon, give it one
+     */
+    if (on(*mp, CARRYWEAPON) && rnd(100) < chance) {
+        int type, hit, dam;
+
+        /* Get the "bonuses" */
+        hit = rnd(5 + (vlevel / 5)) - 2;
+        dam = rnd(5 + (vlevel / 5)) - 2;
+
+        /* Only choose an appropriate type of weapon */
+        switch (rnd(12)) {
+            case 0: type = DAGGER;
+            when 1: type = BATTLEAXE;
+            when 2: type = MACE;
+            when 3: type = SWORD;
+            when 4: type = PIKE;
+            when 5: type = HALBERD;
+            when 6: type = SPETUM;
+            when 7: type = BARDICHE;
+            when 8: type = TRIDENT;
+            when 9: type = BASWORD;
+            when 10:type = DART;
+            otherwise: type = TWOSWORD;
+        }
+
+        /* Create the item */
+        item = spec_item(WEAPON, type, hit, dam);
+        obj = OBJPTR(item);
+        obj->o_pos = mp->t_pos;
+        attach(mp->t_pack, item);
+    }
+
+    /*
+     * If it carries a dagger, give it one
+     */
+    if (on(*mp, CARRYDAGGER) && rnd(100) < chance) {
+        int hit, dam;
+
+        /* Get the "bonuses" */
+        hit = rnd(3 + (vlevel / 5)) - 1;
+        dam = rnd(3 + (vlevel / 5)) - 1;
+
+        /* Create the item */
+        item = spec_item(WEAPON, DAGGER, hit, dam);
+        obj = OBJPTR(item);
+        obj->o_pos = mp->t_pos;
+        attach(mp->t_pack, item);
+    }
+
+    /*
+     * If it carries a scroll, give it one
+     */
+    if (on(*mp, CARRYSCROLL) && rnd(100) < chance) {
+        item = new_thing(TYP_SCROLL, TRUE);
+        obj = OBJPTR(item);
+        obj->o_pos = mp->t_pos;
+
+        /* Can the monster carry this scroll? */
+        if (obj->o_which == S_SCARE && mp->t_stats.s_intel < 16)
+            fall(item, FALSE);  /* This would scare us! */
+        else attach(mp->t_pack, item);
+    }
+
+    /*
+     * If it carries a potion, give it one
+     */
+    if (on(*mp, CARRYPOTION) && rnd(100) < chance) {
+        item = new_thing(TYP_POTION, TRUE);
+        obj = OBJPTR(item);
+        obj->o_pos = mp->t_pos;
+        attach(mp->t_pack, item);
+    }
+
+    /*
+     * If it carries a ring, give it one
+     */
+    if (on(*mp, CARRYRING) && rnd(100) < chance) {
+        item = new_thing(TYP_RING, TRUE);
+        obj = OBJPTR(item);
+        obj->o_pos = mp->t_pos;
+        attach(mp->t_pack, item);
+    }
+
+    /*
+     * If it carries a wand or staff, give it one
+     */
+    if (on(*mp, CARRYSTICK) && rnd(100) < chance) {
+        item = new_thing(TYP_STICK, TRUE);
+        obj = OBJPTR(item);
+        obj->o_pos = mp->t_pos;
+        attach(mp->t_pack, item);
+    }
+
+    /*
+     * If it carries any miscellaneous magic, give it one
+     */
+    if (on(*mp, CARRYMISC) && rnd(100) < chance) {
+        item = new_thing(TYP_MM, TRUE);
+        obj = OBJPTR(item);
+        obj->o_pos = mp->t_pos;
+        attach(mp->t_pack, item);
+    }
+
+    /* Update the monster's encumberance */
+    updpack(TRUE, mp);
+}
+
+
+/*
+ * grab():
+ *      See what is on the spot where the player is standing.  If
+ *      nothing is there, do nothing.  If there is one thing, pick it
+ *      up.  If there are multiple things, prompt the player for what
+ *      he wants (* means everything).
+ */
+
+grab(y, x)
+register int y, x;
+{
+    register struct linked_list *next_item, *item;
+    register struct object *obj;
+    register int cnt, pagecnt;
+    int num_there = 0, ch, och;
+
+    /*
+     * Count how many objects there are and move them to the front
+     * of the level list.
+     */
+    for (item = lvl_obj; item != NULL; item = next_item) {
+        obj = OBJPTR(item);
+        next_item = next(item);
+        if (obj->o_pos.y == y && obj->o_pos.x == x) {
+            num_there++;
+            detach(lvl_obj, item);      /* Remove it from the list */
+            attach(lvl_obj, item);      /* Place it at the front of the list */
+        }
+    }
+
+    /* Nothing there. */
+    if (num_there < 1) msg("Nothing %s", terse ? "there." : "to pick up.");
+
+    /* Something or things there */
+    else {
+        char linebuf[2*LINELEN+1];
+        int curlen, maxlen = 0;
+
+        wclear(hw);
+        cnt = 0;
+        pagecnt = 0;
+        for (item = lvl_obj, ch = 'a'; item != NULL && cnt < num_there;
+             item = next(item), ch++, cnt++) {
+            obj = OBJPTR(item);
+            /* Construct how the line will look */
+            sprintf(linebuf, "%c) %s\n\r", ch, inv_name(obj,FALSE));
+
+            /* See how long it is */
+            curlen = strlen(linebuf) - 2; /* Don't count \n or \r */
+            if (maxlen < curlen) maxlen = curlen;
+
+            /* Draw it in the window */
+            waddstr(hw, linebuf);
+
+            if (++pagecnt >= lines - 2 && next(item) != NULL) {
+                pagecnt = 0;
+                maxlen = 0;
+                dbotline(hw, spacemsg);
+                wclear(hw);
+            }
+            if (ch == 'z') ch = 'A' - 1;
+        }
+
+        strcpy(linebuf, "Pick up what? (* for all): ");
+
+        /* See how long it is */
+        curlen = strlen(linebuf); /* Don't count \n or \r */
+        if (maxlen < curlen) maxlen = curlen;
+
+        /* Draw it in the window */
+        waddstr(hw, linebuf);
+
+        /*
+         * If we have fewer than half a screenful, don't clear the screen.
+         * Leave 3 blank lines at the bottom and 3 blank columns to he right.
+         */
+        if (menu_overlay && num_there < lines - 3) {
+          over_win(cw, hw, num_there + 2, maxlen + 3, num_there, curlen, NULL);
+          pagecnt = -1; /* Indicate we used over_win */
+        }
+        else draw(hw);          /* write screen */
+
+        for (;;) {
+            do {
+                ch = wgetch(cw);
+            } until (isalpha(ch) || ch == '*' || ch == ESC);
+
+            /* Redraw original screen */
+            if (pagecnt < 0) {
+                clearok(cw, FALSE);     /* Setup to redraw current screen */
+                touchwin(cw);           /* clearing first */
+                draw(cw);
+            }
+            else restscr(cw);
+
+            if (ch == ESC) {
+                after = FALSE;
+                msg("");                /* clear top line */
+                break;
+            }
+            if (ch == '*') {
+                player.t_action = A_PICKUP;
+                return(1); /* set action to PICKUP and delay for first one */
+            }
+            /* ch has item to get from list */
+
+            cnt = 0;
+            for (item = lvl_obj, och = 'a'; item != NULL && cnt < num_there;
+                 item = next(item), och++, cnt++) {
+                if (ch == och)
+                    break;
+                if (och == 'z') och = 'A' - 1;
+            }
+            if (item == NULL || cnt >= num_there) {
+                wmove(hw, pagecnt < 0 ? num_there : pagecnt, 25);
+                wprintw(hw, " [between 'a' and '%c']: ",
+                    och == 'A' ? 'z' : och-1);
+                if (maxlen < 49) maxlen = 49;
+
+                /*
+                 * If we have fewer than half a screenful, don't clear the
+                 * screen.  Leave an extra blank line at the bottom and
+                 * 3 blank columns to the right.
+                 */
+                if (menu_overlay && num_there < lines - 3) {
+                    over_win(cw, hw, num_there + 2, maxlen + 3,
+                                num_there, 49, NULL);
+                    cnt = -1;   /* Indicate we used over_win */
+                }
+                else draw(hw);          /* write screen */
+                continue;
+            }
+            else {
+                detach(lvl_obj, item);
+                if (add_pack(item, FALSE)) {
+                    /*
+                     * We make sure here that the dungeon floor gets 
+                     * updated with what's left on the vacated spot.
+                     */
+                    if ((item = find_obj(y, x)) == NULL) {
+                        coord roomcoord;        /* Needed to pass to roomin() */
+
+                        roomcoord.y = y;
+                        roomcoord.x = x;
+                        mvaddch(y, x,
+                                (roomin(&roomcoord) == NULL ? PASSAGE : FLOOR));
+                    }
+                    else mvaddch(y, x, (OBJPTR(item))->o_type);
+                    return(1);
+                }
+                else attach(lvl_obj, item);     /* Couldn't pick it up! */
+                break;
+            }
+        }
+    }
+
+    return(0);
+}
+
+/*
+ * make_sell_pack:
+ *
+ *      Create a pack for sellers (a la quartermaster)
+ */
+
+make_sell_pack(tp)
+struct thing *tp;
+{
+    reg struct linked_list *item;
+    reg struct object *obj;
+    reg int sell_type = 0, nitems, i;
+
+    /* Select the items */
+    nitems = rnd(5) + 7;
+
+    switch (rnd(14)) {
+        /* Armor */
+        case 0:
+        case 1:
+            turn_on(*tp, CARRYARMOR);
+            sell_type = TYP_ARMOR;
+            break;
+
+        /* Weapon */
+        when 2:
+        case 3:
+            turn_on(*tp, CARRYWEAPON);
+            sell_type = TYP_WEAPON;
+            break;
+
+        /* Staff or wand */
+        when 4:
+        case 5:
+            turn_on(*tp, CARRYSTICK);
+            sell_type = TYP_STICK;
+            break;
+
+        /* Ring */
+        when 6:
+        case 7:
+            turn_on(*tp, CARRYRING);
+            sell_type = TYP_RING;
+            break;
+
+        /* scroll */
+        when 8:
+        case 9:
+            turn_on(*tp, CARRYSCROLL);
+            sell_type = TYP_SCROLL;
+            break;
+
+        /* potions */
+        when 10:
+        case 11:
+            turn_on(*tp, CARRYPOTION);
+            sell_type = TYP_POTION;
+            break;
+
+        /* Miscellaneous magic */ 
+        when 12:
+        case 13:
+            turn_on(*tp, CARRYMISC);
+            sell_type = TYP_MM;
+            break;
+    }
+    for (i=0; i<nitems; i++) {
+        item = new_thing(sell_type, FALSE);
+        obj = OBJPTR(item);
+        obj->o_pos = tp->t_pos;
+        attach(tp->t_pack, item);
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xrogue/passages.c	Tue Apr 21 08:55:20 2015 -0400
@@ -0,0 +1,370 @@
+/*
+    passages.c - Draw the connecting passages
+    
+    XRogue: Expeditions into the Dungeons of Doom
+    Copyright (C) 1991 Robert Pietkivitch
+    All rights reserved.
+    
+    Based on "Advanced Rogue"
+    Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka and AT&T
+    All rights reserved.
+
+    Based on "Rogue: Exploring the Dungeons of Doom"
+    Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
+    All rights reserved.
+    
+    See the file LICENSE.TXT for full copyright and licensing information.
+*/
+
+#include <curses.h>
+#include "rogue.h"
+
+/*
+ * do_passages:
+ *      Draw all the passages on a level.
+ */
+
+do_passages()
+{
+    register struct rdes *r1, *r2 = NULL;
+    register int i, j;
+    register int roomcount;
+    static struct rdes
+    {
+        bool    conn[MAXROOMS];         /* possible to connect to room i? */
+        bool    isconn[MAXROOMS];       /* connection been made to room i? */
+        bool    ingraph;                /* this room in graph already? */
+    } rdes[MAXROOMS] = {
+        { { 0, 1, 0, 1, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 },
+        { { 1, 0, 1, 0, 1, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 },
+        { { 0, 1, 0, 0, 0, 1, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 },
+        { { 1, 0, 0, 0, 1, 0, 1, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 },
+        { { 0, 1, 0, 1, 0, 1, 0, 1, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 },
+        { { 0, 0, 1, 0, 1, 0, 0, 0, 1 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 },
+        { { 0, 0, 0, 1, 0, 0, 0, 1, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 },
+        { { 0, 0, 0, 0, 1, 0, 1, 0, 1 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 },
+        { { 0, 0, 0, 0, 0, 1, 0, 1, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 },
+    };
+
+    /*
+     * reinitialize room graph description
+     */
+    for (i = 0; i < MAXROOMS; i++)
+    {
+        r1 = &rdes[i];
+        for (j = 0; j < MAXROOMS; j++)
+            r1->isconn[j] = FALSE;
+        r1->ingraph = FALSE;
+    }
+
+    /*
+     * starting with one room, connect it to a random adjacent room and
+     * then pick a new room to start with.
+     */
+    roomcount = 1;
+    r1 = &rdes[rnd(MAXROOMS)];
+    r1->ingraph = TRUE;
+    do
+    {
+        /*
+         * find a room to connect with
+         */
+        j = 0;
+        for (i = 0; i < MAXROOMS; i++)
+            if (r1->conn[i] && !rdes[i].ingraph && rnd(++j) == 0)
+                r2 = &rdes[i];
+        /*
+         * if no adjacent rooms are outside the graph, pick a new room
+         * to look from
+         */
+        if (j == 0)
+        {
+            do
+                r1 = &rdes[rnd(MAXROOMS)];
+            until (r1->ingraph);
+        }
+        /*
+         * otherwise, connect new room to the graph, and draw a tunnel
+         * to it
+         */
+        else
+        {
+            r2->ingraph = TRUE;
+            i = r1 - rdes;
+            j = r2 - rdes;
+            conn(i, j);
+            r1->isconn[j] = TRUE;
+            r2->isconn[i] = TRUE;
+            roomcount++;
+        }
+    } while (roomcount < MAXROOMS);
+
+    /*
+     * attempt to add passages to the graph a random number of times so
+     * that there isn't just one unique passage through it.
+     */
+    for (roomcount = rnd(5); roomcount > 0; roomcount--)
+    {
+        r1 = &rdes[rnd(MAXROOMS)];      /* a random room to look from */
+        /*
+         * find an adjacent room not already connected
+         */
+        j = 0;
+        for (i = 0; i < MAXROOMS; i++)
+            if (r1->conn[i] && !r1->isconn[i] && rnd(++j) == 0)
+                r2 = &rdes[i];
+        /*
+         * if there is one, connect it and look for the next added
+         * passage
+         */
+        if (j != 0)
+        {
+            i = r1 - rdes;
+            j = r2 - rdes;
+            conn(i, j);
+            r1->isconn[j] = TRUE;
+            r2->isconn[i] = TRUE;
+        }
+    }
+}
+
+/*
+ * conn:
+ *      Draw a corridor from a room in a certain direction.
+ */
+
+conn(r1, r2)
+int r1, r2;
+{
+    register struct room *rpf, *rpt = NULL;
+    register char rmt;
+    register int distance = 0, max_diag, offset = 0, i;
+    register int rm;
+    int turns[3], turn_dist[3];
+    register char direc;
+	coord delta = {0, 0}, curr, turn_delta = {0,0}, spos = {0,0}, epos = {0,0};
+
+    if (r1 < r2)
+    {
+        rm = r1;
+        if (r1 + 1 == r2)
+            direc = 'r';
+        else
+            direc = 'd';
+    }
+    else
+    {
+        rm = r2;
+        if (r2 + 1 == r1)
+            direc = 'r';
+        else
+            direc = 'd';
+    }
+    rpf = &rooms[rm];
+    /*
+     * Set up the movement variables, in two cases:
+     * first drawing one down.
+     */
+    if (direc == 'd')
+    {
+        rmt = rm + 3;                           /* room # of dest */
+        rpt = &rooms[rmt];                      /* room pointer of dest */
+        delta.x = 0;                            /* direction of move */
+        delta.y = 1;
+        spos.x = rpf->r_pos.x;                  /* start of move */
+        spos.y = rpf->r_pos.y;
+        epos.x = rpt->r_pos.x;                  /* end of move */
+        epos.y = rpt->r_pos.y;
+        if (!(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);
+        offset = abs(spos.x - epos.x);  /* how far to turn */
+    }
+    else if (direc == 'r')                      /* setup for moving right */
+    {
+        rmt = rm + 1;
+        rpt = &rooms[rmt];
+        delta.x = 1;
+        delta.y = 0;
+        spos.x = rpf->r_pos.x;
+        spos.y = rpf->r_pos.y;
+        epos.x = rpt->r_pos.x;
+        epos.y = rpt->r_pos.y;
+        if (!(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;
+        offset = abs(spos.y - epos.y);
+    }
+    else
+        debug("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('#');
+    }
+
+    /* How far can we move diagonally? */
+    max_diag = min(distance, offset);
+
+    /*
+     * Decide how many turns we will have.
+     */
+    for (i=0; i<3; i++) turn_dist[i] = 0;       /* Init distances */
+    if (max_diag > 0) {
+        int nturns;
+
+        for (i=0, nturns=0; i<3; i++) {
+            if (rnd(3 - i + nturns) == 0) {
+                nturns++;
+                turns[i] = 0;
+            }
+            else turns[i] = -1;
+        }
+    }
+    else {
+        /* Just use a straight line (middle turn) */
+        turns[0] = turns[2] = -1;
+        turns[1] = 0;
+    }
+
+    /*
+     * Now decide how long each turn will be (for those selected above).
+     */
+    while (max_diag > 0) {
+        for (i=0; i<3; i++) {
+            if (turns[i] >= 0 && max_diag > 0 && rnd(2) == 0) {
+                turn_dist[i]++;
+                max_diag--;
+            }
+        }
+    }
+    
+    /*
+     * If we have extra offset space, add it to the straight turn.
+     */
+    if (offset > distance) turn_dist[1] += offset - distance;
+
+    /*
+     * Decide where we want to make our turns.
+     * First calculate the offsets, then use those offsets to calculate
+     * the exact position relative to "distance."
+     */
+    turns[0] = rnd(distance - turn_dist[0] - turn_dist[2]);
+    turns[2] = rnd(distance - turn_dist[0] - turn_dist[2] - turns[0]);
+    turns[1] = rnd(distance - turn_dist[0] - turn_dist[2] -
+                   turns[0] - turns[2]);
+
+    turns[0] = distance - turns[0];
+    turns[1] = turns[0] - turn_dist[0] - turns[1];
+    turns[2] = turns[1] - turns[2];
+
+    /*
+     * Get ready to move...
+     */
+    curr.x = spos.x;
+    curr.y = spos.y;
+    while (distance > 0) {
+        /*
+         * Move to next row/column
+         */
+        curr.x += delta.x;
+        curr.y += delta.y;
+
+        /*
+         * Check if we are at a turn place; if so make a turn
+         */
+        for (i=0; i<3; i++) {
+            if (distance == turns[i] && turn_dist[i] > 0) {
+                /*
+                 * If this is the start of a straight path,
+                 * we might put in a right-angle turn (33% chance).
+                 */
+                if (i == 1 && rnd(3) == 0) {
+                    cmov(curr);
+                    addch(PASSAGE);
+                }
+
+                /* Now dig the turn */
+                while (turn_dist[i]--) {
+                    curr.x += turn_delta.x;
+                    curr.y += turn_delta.y;
+                    cmov(curr);
+                    addch(PASSAGE);
+                    if (i != 1) {       /* A diagonal */
+                        if (--distance > 0) {
+                            curr.x += delta.x;
+                            curr.y += delta.y;
+                        }
+                    }
+                }
+            }
+        }
+
+        if (distance > 0) {
+            /*
+             * Dig the passage.
+             */
+            cmov(curr);
+            addch(PASSAGE);
+            distance--;
+        }
+    }
+    curr.x += delta.x;
+    curr.y += delta.y;
+    if (!ce(curr, epos))
+        msg("Warning, connectivity problem (%d, %d) to (%d, %d).",
+            curr.y, curr.x, epos.y, epos.x);
+}
+
+/*
+ * Add a door or possibly a secret door
+ * also enters the door in the exits array of the room.
+ */
+
+door(rm, cp)
+register struct room *rm;
+register coord *cp;
+{
+    struct linked_list *newroom;
+    coord *exit;
+
+    cmov(*cp);
+
+	if (rnd(10) < (level - 1) && rnd(100) < 20)
+		addch(SECRETDOOR);
+	else
+		addch(DOOR);
+
+    /* Insert the new room into the linked list of rooms */
+    newroom = new_item(sizeof(coord));
+    exit = DOORPTR(newroom);
+    *exit = *cp;
+    attach(rm->r_exit, newroom);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xrogue/player.c	Tue Apr 21 08:55:20 2015 -0400
@@ -0,0 +1,1478 @@
+/*
+    player.c - functions for dealing with special player abilities
+
+    XRogue: Expeditions into the Dungeons of Doom
+    Copyright (C) 1991 Robert Pietkivitch
+    All rights reserved.
+    
+    Based on "Advanced Rogue"
+    Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka and AT&T
+    All rights reserved.
+
+    See the file LICENSE.TXT for full copyright and licensing information.
+*/
+
+#include <ctype.h>
+#include <curses.h>
+#include "rogue.h"
+
+/*
+ * affect:
+ *      cleric affecting undead
+ */
+
+affect()
+{
+    register struct linked_list *item;
+    register struct thing *tp;
+    register char *mname;
+    bool see;
+    coord new_pos;
+    int lvl;
+
+    if (!(player.t_ctype == C_CLERIC  ||
+          (player.t_ctype == C_PALADIN && pstats.s_lvl > 4) ||
+          cur_relic[HEIL_ANKH] != 0)) {
+        msg("You cannot affect undead.");
+        return;
+    }
+
+    new_pos.y = hero.y + player.t_newpos.y;
+    new_pos.x = hero.x + player.t_newpos.x;
+
+    if (cansee(new_pos.y, new_pos.x)) see = TRUE;
+    else see = FALSE;
+
+    /* Anything there? */
+    if (new_pos.y < 0 || new_pos.y > lines-3 ||
+        new_pos.x < 0 || new_pos.x > cols-1 ||
+        mvwinch(mw, new_pos.y, new_pos.x) == ' ') {
+        msg("Nothing to affect.");
+        return;
+    }
+
+    if ((item = find_mons(new_pos.y, new_pos.x)) == 0) {
+        debug("Affect what @ %d,%d?", new_pos.y, new_pos.x);
+        return;
+    }
+    tp = THINGPTR(item);
+    mname = monster_name(tp);
+
+    if (on(player, ISINVIS) && off(*tp, CANSEE)) {
+        msg("%s%s cannot see you", see ? "The " : "It",
+            see ? mname : "");
+        return;
+    }
+
+    if (off(*tp, TURNABLE) || on(*tp, WASTURNED)) 
+        goto annoy;
+    turn_off(*tp, TURNABLE);
+
+    lvl = pstats.s_lvl;
+    if (player.t_ctype == C_PALADIN && cur_relic[HEIL_ANKH] == 0) {
+        lvl -= 4;
+    }
+    /* Can cleric kill it? */
+    if (lvl >= 3 * tp->t_stats.s_lvl) {
+        unsigned long test;      /* For overflow check */
+
+        msg("You have destroyed %s%s.", see ? "the " : "it", see ? mname : "");
+        test = pstats.s_exp + tp->t_stats.s_exp;
+
+        /* Be sure there is no overflow before increasing experience */
+        if (test > pstats.s_exp) pstats.s_exp = test;
+        killed(item, FALSE, TRUE, TRUE);
+        check_level();
+        return;
+    }
+
+    /* Can cleric turn it? */
+    if (rnd(100) + 1 >
+         (100 * ((2 * tp->t_stats.s_lvl) - lvl)) / lvl) {
+        unsigned long test;      /* Overflow test */
+
+        /* Make the monster flee */
+        turn_on(*tp, WASTURNED);        /* No more fleeing after this */
+        turn_on(*tp, ISFLEE);
+        runto(tp, &hero);
+
+        /* Disrupt it */
+        dsrpt_monster(tp, TRUE, TRUE);
+
+        /* Let player know */
+        msg("You have turned %s%s.", see ? "the " : "it", see ? mname : "");
+
+        /* get points for turning monster -- but check overflow first */
+        test = pstats.s_exp + tp->t_stats.s_exp/2;
+        if (test > pstats.s_exp) pstats.s_exp = test;
+        check_level();
+
+        /* If monster was suffocating, stop it */
+        if (on(*tp, DIDSUFFOCATE)) {
+            turn_off(*tp, DIDSUFFOCATE);
+            extinguish(suffocate);
+        }
+
+        /* If monster held us, stop it */
+        if (on(*tp, DIDHOLD) && (--hold_count == 0))
+                turn_off(player, ISHELD);
+        turn_off(*tp, DIDHOLD);
+
+        /* It is okay to turn tail */
+        tp->t_oldpos = tp->t_pos;
+
+        return;
+    }
+
+    /* Otherwise -- no go */
+annoy:
+    if (see && tp->t_stats.s_intel > 16)
+        msg("%s laughs at you...", prname(mname, TRUE));
+    else
+        msg("You do not affect %s%s.", see ? "the " : "it", see ? mname : "");
+
+    /* Annoy monster */
+   if (off(*tp, ISFLEE)) runto(tp, &hero);
+}
+
+/* 
+ * the cleric asks his deity for a spell
+ */
+
+pray()
+{
+    register int num_prayers, prayer_ability, which_prayer;
+
+    which_prayer = num_prayers = prayer_ability =  0;
+
+    if (player.t_ctype != C_CLERIC  && player.t_ctype != C_PALADIN &&
+        cur_relic[HEIL_ANKH] == 0) {
+            msg("You are not permitted to pray.");
+            return;
+    }
+    if (cur_misc[WEAR_CLOAK] != NULL &&
+        cur_misc[WEAR_CLOAK]->o_which == MM_R_POWERLESS) {
+        msg("You can't seem to pray!");
+        return;
+    }
+
+    prayer_ability = pstats.s_lvl * pstats.s_wisdom - 5;
+    if (player.t_ctype != C_CLERIC)
+        prayer_ability /= 2;
+
+    if (cur_relic[HEIL_ANKH]) prayer_ability += 75;
+
+    if (player.t_action != C_PRAY) {
+        num_prayers = 0;
+
+        /* Get the number of avilable prayers */
+        if (pstats.s_wisdom > 16) 
+            num_prayers += pstats.s_wisdom - 16;
+
+        num_prayers += pstats.s_lvl;
+        if (cur_relic[HEIL_ANKH])
+            num_prayers += pstats.s_wisdom - 18;
+
+        if (player.t_ctype != C_CLERIC) 
+            num_prayers /= 2;
+
+        if (num_prayers > MAXPRAYERS) 
+            num_prayers = MAXPRAYERS;
+        if (num_prayers < 1) {
+            msg("You are not permitted to pray yet.");
+            return;
+        }
+
+        /* Prompt for prayer */
+        if (pick_spell( cleric_spells, 
+                        prayer_ability, 
+                        num_prayers, 
+                        pray_time,
+                        "offer",
+                        "prayer"))
+            player.t_action = C_PRAY;
+
+        return;
+    }
+
+    /* We've waited our required praying time. */
+    which_prayer = player.t_selection;
+    player.t_selection = 0;
+    player.t_action = A_NIL;
+
+    if (cleric_spells[which_prayer].s_cost + pray_time > prayer_ability) {
+        msg("Your prayer fails.");
+        return;
+    }
+
+    msg("Your prayer has been granted. ");
+
+    if (cleric_spells[which_prayer].s_type == TYP_POTION)
+        quaff(          cleric_spells[which_prayer].s_which,
+                        NULL,
+                        cleric_spells[which_prayer].s_flag,
+                        FALSE);
+    else if (cleric_spells[which_prayer].s_type == TYP_SCROLL)
+        read_scroll(    cleric_spells[which_prayer].s_which,
+                        cleric_spells[which_prayer].s_flag,
+                        FALSE);
+    else if (cleric_spells[which_prayer].s_type == TYP_STICK) {
+         if (!player_zap(cleric_spells[which_prayer].s_which,
+                         cleric_spells[which_prayer].s_flag)) {
+             after = FALSE;
+             return;
+         }
+    }
+    pray_time += cleric_spells[which_prayer].s_cost;
+}
+
+/*
+ * the magician is going to try and cast a spell
+ */
+
+cast()
+{
+    register int spell_ability, which_spell, num_spells;
+
+    if (player.t_ctype != C_MAGICIAN && player.t_ctype != C_RANGER) {
+        msg("You are not permitted to cast spells.");
+        return;
+    }
+    if (cur_misc[WEAR_CLOAK] != NULL &&
+        cur_misc[WEAR_CLOAK]->o_which == MM_R_POWERLESS) {
+        msg("You can't seem to cast spells!");
+        return;
+    }
+    spell_ability = pstats.s_lvl * pstats.s_intel - 5;
+    if (player.t_ctype != C_MAGICIAN)
+        spell_ability /= 2;
+
+    if (player.t_action != C_CAST) {
+        /* 
+         * Get the number of avilable spells 
+         */
+        num_spells = 0;
+        if (pstats.s_intel > 16) 
+            num_spells += pstats.s_intel - 16;
+
+        num_spells += pstats.s_lvl;
+        if (player.t_ctype != C_MAGICIAN) 
+            num_spells /= 2;
+        if (num_spells > MAXSPELLS)
+            num_spells = MAXSPELLS;
+        if (num_spells < 1) {
+            msg("You are not allowed to cast spells yet.");
+            return;
+        }
+
+    /* prompt for spell */
+        if (pick_spell( magic_spells, 
+                        spell_ability, 
+                        num_spells, 
+                        spell_power,
+                        "cast",
+                        "spell"))
+            player.t_action = C_CAST;
+        return;
+    }
+
+    /* We've waited our required casting time. */
+    which_spell = player.t_selection;
+    player.t_selection = 0;
+    player.t_action = A_NIL;
+
+    if ((spell_power + magic_spells[which_spell].s_cost) > spell_ability) {
+        msg("Your attempt fails.");
+        return;
+    }
+
+    msg("Your spell is successful. ");
+
+    if (magic_spells[which_spell].s_type == TYP_POTION)
+        quaff(  magic_spells[which_spell].s_which,
+                NULL,
+                magic_spells[which_spell].s_flag,
+                FALSE);
+    else if (magic_spells[which_spell].s_type == TYP_SCROLL)
+        read_scroll(    magic_spells[which_spell].s_which,
+                        magic_spells[which_spell].s_flag,
+                        FALSE);
+    else if (magic_spells[which_spell].s_type == TYP_STICK) {
+         if (!player_zap(magic_spells[which_spell].s_which,
+                         magic_spells[which_spell].s_flag)) {
+             after = FALSE;
+             return;
+         }
+    }
+    spell_power += magic_spells[which_spell].s_cost;
+}
+
+/* 
+ * the druid asks his deity for a spell
+ */
+
+chant()
+{
+    register int num_chants, chant_ability, which_chant;
+
+    which_chant = num_chants = chant_ability = 0;
+
+    if (player.t_ctype != C_DRUID && player.t_ctype != C_MONK) {
+        msg("You are not permitted to chant.");
+        return;
+    }
+    if (cur_misc[WEAR_CLOAK] != NULL &&
+        cur_misc[WEAR_CLOAK]->o_which == MM_R_POWERLESS) {
+        msg("You can't seem to chant!");
+        return;
+    }
+    chant_ability = pstats.s_lvl * pstats.s_wisdom - 5;
+    if (player.t_ctype != C_DRUID)
+        chant_ability /= 2;
+
+    if (player.t_action != C_CHANT) {
+        num_chants = 0;
+
+        /* Get the number of avilable chants */
+        if (pstats.s_wisdom > 16) 
+            num_chants += pstats.s_wisdom - 16;
+
+        num_chants += pstats.s_lvl;
+
+        if (player.t_ctype != C_DRUID) 
+            num_chants /= 2;
+
+        if (num_chants > MAXCHANTS) 
+            num_chants = MAXCHANTS;
+
+        if (num_chants < 1) {
+            msg("You are not permitted to chant yet.");
+            return;
+        }
+
+        /* Prompt for chant */
+        if (pick_spell( druid_spells, 
+                        chant_ability, 
+                        num_chants, 
+                        chant_time,
+                        "sing",
+                        "chant"))
+            player.t_action = C_CHANT;
+
+        return;
+    }
+
+    /* We've waited our required chanting time. */
+    which_chant = player.t_selection;
+    player.t_selection = 0;
+    player.t_action = A_NIL;
+
+    if (druid_spells[which_chant].s_cost + chant_time > chant_ability) {
+        msg("Your chant fails.");
+        return;
+    }
+
+    msg("Your chant has been granted. ");
+
+    if (druid_spells[which_chant].s_type == TYP_POTION)
+        quaff(          druid_spells[which_chant].s_which,
+                        NULL,
+                        druid_spells[which_chant].s_flag,
+                        FALSE);
+    else if (druid_spells[which_chant].s_type == TYP_SCROLL)
+        read_scroll(    druid_spells[which_chant].s_which,
+                        druid_spells[which_chant].s_flag,
+                        FALSE);
+    else if (druid_spells[which_chant].s_type == TYP_STICK) {
+         if (!player_zap(druid_spells[which_chant].s_which,
+                         druid_spells[which_chant].s_flag)) {
+             after = FALSE;
+             return;
+         }
+    }
+    chant_time += druid_spells[which_chant].s_cost;
+}
+
+/* Constitution bonus */
+
+const_bonus()   /* Hit point adjustment for changing levels */
+{
+    register int bonus;
+    if (pstats.s_const > 9 && pstats.s_const < 18) 
+        bonus = 0;
+    else if (pstats.s_const >= 18 && pstats.s_const < 20) 
+        bonus = 1;
+    else if (pstats.s_const >= 20 && pstats.s_const < 26) 
+        bonus = 2;
+    else if (pstats.s_const >= 26 && pstats.s_const < 36) 
+        bonus = 3;
+    else if (pstats.s_const >= 36) 
+        bonus = 4;
+    else if (pstats.s_const > 7) 
+        bonus = -1;
+    else
+        bonus = -2;
+    switch(player.t_ctype) {
+        case C_FIGHTER:         bonus = min(bonus, 11);
+        when C_RANGER:          bonus = min(bonus,  9);
+        when C_PALADIN:         bonus = min(bonus,  9);
+        when C_MAGICIAN:        bonus = min(bonus,  8);
+        when C_CLERIC:          bonus = min(bonus,  8);
+        when C_THIEF:           bonus = min(bonus, 10);
+        when C_ASSASSIN:        bonus = min(bonus, 10);
+        when C_DRUID:           bonus = min(bonus,  8);
+        when C_MONK:            bonus = min(bonus,  9);
+        otherwise:              bonus = min(bonus,  7);
+    }
+    return(bonus);
+}
+
+/*
+ * Give away slime-molds to monsters.  If monster is friendly, 
+ * it will give you a "regular" food ration in return.  You have
+ * to give a slime-mold to Alteran (a unique monster) in order to 
+ * get the special "Card of Alteran" quest item.  There's no other
+ * way to get this artifact and remain alive.
+ */
+
+give(th)
+register struct thing *th;
+{
+    /*
+     * Find any monster within one space of you
+     */
+    struct linked_list *ll;
+    struct object *lb;
+    register int x,y;
+    register struct linked_list *mon = NULL;
+    bool gotone = FALSE;
+
+    if (levtype != POSTLEV) {  /* no monsters at trading post  */
+        for (x = hero.x-1; x <= hero.x+1; x++) {
+            for (y = hero.y-1; y <= hero.y+1; y++) {
+                if (y < 1 || x < 0 || y > lines - 3 || x > cols - 1)
+                    continue;
+                if (isalpha(mvwinch(mw, y, x))) {
+                    if ((mon = find_mons(y, x)) != NULL) {
+                        gotone = TRUE;  /* found a monster to give away to */
+                        th = THINGPTR(mon);
+                    }
+                }
+            }
+        }
+    }
+    if (gotone) {
+        if ((ll=get_item(pack, "give away", ALL, FALSE, FALSE)) != NULL) {
+            lb = OBJPTR(ll);
+            mpos = 0;
+            switch(lb->o_type) {
+                case FOOD:
+                    switch (lb->o_which) {
+                        case E_SLIMEMOLD:   /* only slime-molds for now */
+                if (on(*th, CANSELL)) {  /* quartermaster */
+                msg("%s laughs at you. ");
+                return;
+                }
+                if ((on(*th, ISFRIENDLY) || off(*th, ISMEAN)) &&
+                off(*th, ISUNIQUE) && off(*th, CANSELL)) {
+                turn_on(*th, ISRUN); /* we want him awake */
+                                msg("%s accepts and promptly eats your gift of food.  --More--", prname(monster_name(th), TRUE));
+                wait_for(' ');
+                    del_pack(ll); /* delete slime-mold */
+                          /* and add a food ration */
+                create_obj(FALSE, FOOD, E_RATION);
+                msg("%s gives you food in return and nods off to sleep. ", prname(monster_name(th), TRUE));
+                turn_off(*th, ISRUN); /* put him to sleep */
+                return;
+                }
+                else if (on(*th, CARRYCARD) && on(*th, ISUNIQUE)) {
+                /* Now you get the Card of Alteran */
+                msg("%s gives you a strange rectangular card. --More--", prname(monster_name(th), TRUE));
+                wait_for(' ');
+                    del_pack(ll); /* get rid of slime-mold */
+                create_obj(FALSE, RELIC, ALTERAN_CARD);
+                msg("%s bids you farewell. ", prname(monster_name(th), TRUE));
+                killed(mon, FALSE, FALSE, FALSE);
+                return;
+                }
+                else if (on(*th, ISUNIQUE) && off(*th, ISMEAN)) {
+                /* Dragons */
+                msg("%s is set free by your generosity. ", prname(monster_name(th), TRUE));
+                    del_pack(ll);  /* get rid of it */
+                /* just let him roam around */
+                turn_on(*th, ISRUN);
+                if (on(*th, ISFLEE)) turn_off(*th, ISFLEE);
+                runto(th, &player);
+                th->t_action = A_NIL;
+                return;
+                }
+                else if (on(*th, ISRUN) && off(*th, ISUNIQUE)) {
+                /* if NOT sleeping and not a unique */
+                switch (rnd(2)) {
+                    case 0: msg("%s ignores you. ", prname(monster_name(th), TRUE));
+                    when 1: {
+                    msg("%s nips at your hand. ", prname(monster_name(th), TRUE));
+                    if (rnd(100) < 10) { 
+                                del_pack(ll); /* delete it */
+                        if (off(*th, ISMEAN)) {
+                        msg("The slime-mold makes %s sleepy. ", prname(monster_name(th), TRUE));
+                        /* put him to sleep */
+                        turn_off(*th, ISRUN);
+                        return;
+                        }
+                        else {  
+                        switch (rnd(2)) {
+                            case 0: msg("%s's eyes roll back. ", prname(monster_name(th), TRUE));
+                                when 1: msg("%s becomes wanderlust. ", prname(monster_name(th), TRUE));
+                        }
+                        /* just let him roam around */
+                            turn_on(*th, ISRUN);
+                        if (on(*th, ISFLEE))
+                                        turn_off(*th, ISFLEE);
+                        runto(th, &player);
+                        th->t_action = A_NIL;
+                        return;
+                        }
+                    }
+                    }
+                }
+                }
+                else {
+                msg("%s's mouth waters. ", prname(monster_name(th), TRUE));
+                /* this wakes him up */
+                if (off(*th, ISUNIQUE)) turn_on(*th, ISRUN);
+                return;
+                }
+                otherwise:
+                switch (rnd(3)) {  /* mention food (hint hint) */
+                    case 0: msg("You cannot give away the %s! ", foods[lb->o_which].mi_name);
+                    when 1: msg("The %s looks rancid! ", foods[lb->o_which].mi_name);
+                    when 2: msg("You change your mind. ");
+                }
+                return;
+                    }
+            otherwise:
+            switch (rnd(3)) {  /* do not mention other items */
+                    case 0: msg("You feel foolish. ");
+                    when 1: msg("You change your mind. ");
+                    when 2: msg("%s ignores you. ", prname(monster_name(th), TRUE));
+            }
+
+        return;
+            }
+        }
+    }
+    else msg("Your efforts are futile. ");
+    return;
+}
+
+/*
+ * Frighten a monster.  Useful for the 'good' characters.
+ */
+
+fright(th)
+register struct thing *th;
+{
+    /*
+     * Find any monster within one space of you
+     */
+    register int x,y;
+    register struct linked_list *mon;
+    bool gotone = FALSE;
+
+    if (levtype != POSTLEV) {  /* no monsters at trading post  */
+        for (x = hero.x-1; x <= hero.x+1; x++) {
+            for (y = hero.y-1; y <= hero.y+1; y++) {
+                if (y < 1 || x < 0 || y > lines - 3 || x > cols - 1)
+                    continue;
+                if (isalpha(mvwinch(mw, y, x))) {
+                    if ((mon = find_mons(y, x)) != NULL) {
+                        gotone = TRUE;  /* found a monster to give away to */
+                        th = THINGPTR(mon);
+                    }
+                }
+            }
+        }
+    }
+    if (gotone) {  /* If 'good' character or is wearing a ring of fear */
+        if (player.t_ctype == C_RANGER || player.t_ctype == C_PALADIN ||
+            player.t_ctype == C_MONK   || ISWEARING(R_FEAR) != 0) { 
+
+            player.t_action = A_NIL;
+            player.t_no_move = movement(&player);
+            switch (player.t_ctype) {
+                case C_FIGHTER:   /* loss of strength */
+                    pstats.s_str--;
+                    if (pstats.s_str < 3) pstats.s_str = 3;
+                when C_RANGER:    /* loss of charisma */
+        case C_PALADIN:
+                    pstats.s_charisma--;
+                    if (pstats.s_charisma < 3) pstats.s_charisma = 3;
+                when C_CLERIC:    /* loss of wisdom */
+        case C_DRUID:
+                    pstats.s_wisdom--;
+                    if (pstats.s_wisdom < 3) pstats.s_wisdom = 3;
+                when C_MAGICIAN:  /* loss of wisdom intelligence */
+            pstats.s_intel--;
+                    if (pstats.s_intel < 3) pstats.s_intel = 3;
+                when C_THIEF:     /* loss of dexterity */
+                case C_ASSASSIN:
+                    pstats.s_dext--;
+                    if (pstats.s_dext < 3) pstats.s_dext = 3;
+                when C_MONK:      /* loss of constitution */
+                    pstats.s_const--;
+                    if (pstats.s_const < 3) pstats.s_const = 3;
+                otherwise:        /* this msg can induce great fear */
+                    msg("You miss. ");
+        }
+
+        /* Cause a panic.  Good thru level 16. */
+            if (level < 17) { 
+        msg("You wave your arms and yell! ");
+                do_panic(th->t_index);
+                pstats.s_hpt -= (pstats.s_hpt/2)+1;
+        if (pstats.s_hpt < 25) msg("You heart quivers... ");
+                if (pstats.s_hpt < 1) {
+            msg("Your heart stops!!  --More--");
+            wait_for(' ');
+            pstats.s_hpt = -1;
+            death(D_FRIGHT);
+        }
+            return;
+        }
+        else {
+        /* He can't do it after level 16 */
+        switch (rnd(20)) { 
+            case 0: case 2:
+            msg("You stamp your foot!! ");
+            when 4: case 8:
+            msg("%s laughs at you! ",prname(monster_name(th),TRUE));
+            when 10: case 12:
+            msg("You forget what you are doing? ");
+                otherwise:
+                msg(nothing);
+        }
+            return;
+        }
+    }
+        else {
+        switch (rnd(25)) {
+        case 0: case 2: case 4:
+        msg("You motion angrily! ");
+        when 6: case 8: case 10:
+        msg("You can't frighten anything. ");
+        when 12: case 14: case 16:
+        msg("Your puff up your face. ");
+        otherwise:
+        msg(nothing);
+        }
+    return;
+    }
+    }
+    else {
+    msg("There is nothing to fear but fear itself. ");
+    return;
+    }
+}
+
+/* Routines for thieves */
+
+/*
+ * gsense: Sense gold
+ */
+
+gsense()
+{
+    /* Thief & assassin can do this, but fighter & ranger can later */
+    if (player.t_ctype == C_THIEF     || player.t_ctype == C_ASSASSIN ||
+        ((player.t_ctype == C_FIGHTER || player.t_ctype == C_RANGER)  &&
+    pstats.s_lvl >= 12)) {
+          read_scroll(S_GFIND, NULL, FALSE);
+    }
+    else msg("You seem to have no gold sense.");
+    return;
+}
+
+/*
+ * xsense: Sense traps
+ */
+
+xsense()
+{
+    /* Only thief can do this, but assassin, fighter, & monk can later */
+    if (player.t_ctype == C_THIEF   || ((player.t_ctype == C_ASSASSIN ||
+    player.t_ctype == C_FIGHTER || player.t_ctype == C_MONK)      &&
+    pstats.s_lvl >= 14)) {
+        read_scroll(S_FINDTRAPS, NULL, FALSE);
+    }
+    else msg("You seem not to be able to sense traps.");
+    return;
+}
+
+/*
+ * steal:
+ *      Steal in direction given in delta
+ */
+
+steal()
+{
+    register struct linked_list *item;
+    register struct thing *tp;
+    register char *mname;
+    coord new_pos;
+    int thief_bonus = -50;
+    bool isinvisible = FALSE;
+
+
+    /* let the fighter steal after level 15 */
+    if (player.t_ctype == C_FIGHTER && pstats.s_lvl < 15) {
+        msg(nothing);
+        return;
+    }
+    else if (player.t_ctype != C_THIEF    &&
+        player.t_ctype  != C_ASSASSIN &&
+            player.t_ctype  != C_FIGHTER) {
+            msg("Only thieves and assassins can steal.");
+            return;
+    }
+    if (on(player, ISBLIND)) {
+        msg("You can't see anything.");
+        return;
+    }
+
+    new_pos.y = hero.y + player.t_newpos.y;
+    new_pos.x = hero.x + player.t_newpos.x;
+
+    /* Anything there? */
+    if (new_pos.y < 0 || new_pos.y > lines-3 ||
+        new_pos.x < 0 || new_pos.x > cols-1 ||
+        mvwinch(mw, new_pos.y, new_pos.x) == ' ') {
+        msg("Nothing to steal from.");
+        return;
+    }
+
+    if ((item = find_mons(new_pos.y, new_pos.x)) == NULL)
+        debug("Steal from what @ %d,%d?", new_pos.y, new_pos.x);
+    tp = THINGPTR(item);
+    if (on(*tp, ISSTONE)) {
+        msg ("You can't steal from stone!");
+        return;
+    }
+
+    if (on(*tp, ISFLEE)) {
+        msg("You can't get your hand in anywhere! ");
+        return;
+    }
+
+    isinvisible = invisible(tp);
+    if (isinvisible) mname = "creature";
+    else mname = monster_name(tp);
+
+    /* Can player steal something unnoticed? */
+    if (player.t_ctype == C_THIEF)    thief_bonus = 9;
+    if (player.t_ctype == C_ASSASSIN) thief_bonus = 6;
+    if (player.t_ctype == C_FIGHTER)  thief_bonus = 3;
+    if (on(*tp, ISUNIQUE)) thief_bonus -= 15;
+    if (isinvisible) thief_bonus -= 20;
+    if (on(*tp, ISINWALL) && off(player, CANINWALL)) thief_bonus -= 50;
+
+    if (on(*tp, ISHELD) || tp->t_action == A_FREEZE ||
+        rnd(100) <
+        (thief_bonus + 2*dex_compute() + 5*pstats.s_lvl -
+         5*(tp->t_stats.s_lvl - 3))) {
+        register struct linked_list *s_item, *pack_ptr;
+        int count = 0;
+        unsigned long test;      /* Overflow check */
+
+        s_item = NULL;  /* Start stolen goods out as nothing */
+
+        /* Find a good item to take */
+        for (pack_ptr=tp->t_pack; pack_ptr != NULL; pack_ptr=next(pack_ptr))
+            if ((OBJPTR(pack_ptr))->o_type != RELIC &&
+                pack_ptr != tp->t_using &&  /* Monster can't be using it */
+                rnd(++count) == 0)
+                s_item = pack_ptr;
+
+        /* 
+         * Find anything?
+         */
+        if (s_item == NULL) {
+            msg("%s apparently has nothing to steal.", prname(mname, TRUE));
+            return;
+        }
+
+        /* Take it from monster */
+        if (tp->t_pack) detach(tp->t_pack, s_item);
+
+        /* Recalculate the monster's encumberance */
+        updpack(TRUE, tp);
+
+        /* Give it to player */
+        if (add_pack(s_item, FALSE) == FALSE) {
+           (OBJPTR(s_item))->o_pos = hero;
+           fall(s_item, TRUE);
+        }
+
+        /* Get points for stealing -- but first check for overflow */
+        test = pstats.s_exp + tp->t_stats.s_exp/2;
+        if (test > pstats.s_exp) pstats.s_exp = test;
+
+        /*
+         * Do adjustments if player went up a level
+         */
+        check_level();
+    }
+
+    else {
+        msg("Your attempt fails.");
+
+        /* Annoy monster (maybe) */
+        if (rnd(40) >= dex_compute() + thief_bonus) {
+            /*
+             * If this is a charmed creature, there is a chance it
+             * will become uncharmed.
+             */
+            if (on(*tp, ISCHARMED) && save(VS_MAGIC, tp, 0)) {
+                msg("The eyes of %s turn clear.", prname(mname, FALSE));
+                turn_off(*tp, ISCHARMED);
+            }
+            if (on(*tp, CANSELL)) {
+                turn_off(*tp, CANSELL);
+                tp->t_action = A_NIL;
+                tp->t_movement = 0;
+                if (rnd(100) < 50) /* make him steal something */
+                    turn_on(*tp, STEALMAGIC);
+                else
+                    turn_on(*tp, STEALGOLD);
+                if (!isinvisible)
+                    msg("%s looks insulted.", prname(mname, TRUE));
+            }
+            runto(tp, &hero);
+        }
+    }
+}
+
+/*
+ * Take charmed monsters with you via up or down commands.
+ */
+
+take_with()
+{
+    register struct thing *tp;
+    register struct linked_list *item;
+    struct linked_list *nitem;
+    register int t;
+
+    t = 0;
+    for (item = mlist; item != NULL; item = nitem) {
+    nitem = next(item);
+    t++;
+    if (t > 5) break;
+    tp = THINGPTR(item);
+        if (on(*tp, ISCHARMED)) {
+            monsters[tp->t_index].m_normal = TRUE;
+            turn_on(*tp, ISELSEWHERE);
+            detach(mlist, item);
+            attach(tlist, item);         /* remember him next level */
+            check_residue(tp);
+            continue;
+        }
+    }
+}
+
+/*
+ * this routine lets the player pick the spell that they
+ * want to cast regardless of character class
+ */
+
+pick_spell(spells, ability, num_spells, power, prompt, type)
+struct spells   spells[];       /* spell list                            */
+int             ability;        /* spell ability                         */
+int             num_spells;     /* number of spells that can be cast     */
+int             power;          /* spell power                           */
+const char      *prompt;        /* prompt for spell list                 */
+const char      *type;          /* type of thing--> spell, prayer, chant */
+{
+    bool                nohw = FALSE;
+    register int        i;
+    int                 curlen,
+                        maxlen = 0,
+                        dummy = 0,
+                        which_spell,
+                        spell_left;
+    if (cur_misc[WEAR_CLOAK] != NULL &&
+        cur_misc[WEAR_CLOAK]->o_which == MM_R_POWERLESS) {
+        msg("You can't seem to start a %s!", type);
+        return(FALSE);
+    }
+
+    /* Prompt for spells */
+    msg("Which %s are you %sing? (* for list): ", type, prompt);
+
+    which_spell = (int) (wgetch(cw) - 'a');
+    msg("");    /* Get rid of the prompt */
+    if (which_spell == (int) ESC - (int) 'a') {
+        after = FALSE;
+        return(FALSE);
+    }
+    if (which_spell >= 0 && which_spell < num_spells) nohw = TRUE;
+
+    else if (slow_invent) {
+        register char c;
+
+        nohw = TRUE;
+        do {
+            for (i=0; i<num_spells; i++) {
+                msg("");
+                mvwaddch(msgw, 0, 0, '[');
+                waddch(msgw, (char) ((int) 'a' + i));
+                wprintw(msgw, "] A %s of ", type);
+                if (spells[i].s_type == TYP_POTION)
+                    waddstr(msgw, p_magic[spells[i].s_which].mi_name);
+                else if (spells[i].s_type == TYP_SCROLL)
+                    waddstr(msgw, s_magic[spells[i].s_which].mi_name);
+                else if (spells[i].s_type == TYP_STICK)
+                    waddstr(msgw, ws_magic[spells[i].s_which].mi_name);
+                waddstr(msgw, morestr);
+                wclrtobot(msgw);
+                clearok(msgw, FALSE);
+                draw(msgw);
+                do {
+                    c = wgetch(cw);
+                } while (c != ' ' && c != ESC);
+                if (c == ESC)
+                    break;
+            }
+            msg("");
+            wmove(msgw, 0, 0);
+            wprintw(msgw, "Which %s are you %sing? ", type, prompt);
+            clearok(msgw, FALSE);
+            draw(msgw);
+
+            which_spell = (int) (wgetch(cw) - 'a');
+        } while (which_spell != (int) (ESC - 'a') &&
+                 (which_spell < 0 || which_spell >= num_spells));
+
+        if (which_spell == (int) (ESC - 'a')) {
+            mpos = 0;
+            msg("");
+            after = FALSE;
+            return(FALSE);
+        }
+    }
+    else {
+        /* Now display the possible spells */
+        wclear(hw);
+        touchwin(hw);
+        wmove(hw, 2, 0);
+        wprintw(hw, "   Cost    %c%s", toupper(*type),type+1);
+        mvwaddstr(hw, 3, 0,
+                "-----------------------------------------------");
+        maxlen = 47;    /* Maximum width of header */
+
+        for (i=0; i<num_spells; i++) {
+            sprintf(prbuf, "[%c]        %3d     A %s of ",
+                        (char) ((int) 'a' + i), spells[i].s_cost, type);
+            if (spells[i].s_type == TYP_POTION)
+                strcat(prbuf, p_magic[spells[i].s_which].mi_name);
+            else if (spells[i].s_type == TYP_SCROLL)
+                strcat(prbuf, s_magic[spells[i].s_which].mi_name);
+            else if (spells[i].s_type == TYP_STICK)
+                strcat(prbuf, ws_magic[spells[i].s_which].mi_name);
+            mvwaddstr(hw, i+4, 0, prbuf);
+
+            /* Get the length of the line */
+            getyx(hw, dummy, curlen);
+            if (maxlen < curlen) maxlen = curlen;
+        }
+
+        spell_left = ability - power;
+        if (spell_left < 0) {
+            spell_left = 0;
+            if (spell_left < -20) power = ability + 20;
+        }
+        sprintf(prbuf, "[Current %s power = %d]", type, spell_left);
+
+        mvwaddstr(hw, 0, 0, prbuf);
+        wprintw(hw, " Which %s are you %sing? ", type, prompt);
+        getyx(hw, dummy, curlen);
+        if (maxlen < curlen) maxlen = curlen;
+
+        /* Should we overlay? */
+        if (menu_overlay && num_spells + 3 < lines - 3) {
+            over_win(cw, hw, num_spells + 5, maxlen + 3, 0, curlen, NULL);
+        }
+        else draw(hw);
+    }
+
+    if (!nohw) {
+        which_spell = (int) (wgetch(cw) - 'a');
+        while (which_spell < 0 || which_spell >= num_spells) {
+            if (which_spell == (int) ESC - (int) 'a') {
+                after = FALSE;
+
+                /* Restore the screen */
+                if (num_spells + 3 < lines / 2) {
+                    clearok(cw, FALSE);
+                    touchwin(cw);
+                }
+                else restscr(cw);
+                return(FALSE);
+            }
+            wmove(hw, 0, 0);
+            wclrtoeol(hw);
+            wprintw(hw, "Please enter one of the listed %ss. ", type);
+            getyx(hw, dummy, curlen);
+            if (maxlen < curlen) maxlen = curlen;
+
+            /* Should we overlay? */
+            if (menu_overlay && num_spells + 3 < lines - 3) {
+                over_win(cw, hw, num_spells + 5, maxlen + 3,
+                            0, curlen, NULL);
+            }
+            else draw(hw);
+
+            which_spell = (int) (wgetch(cw) - 'a');
+        }
+    }
+
+    /* Now restore the screen if we have to */
+    if (!nohw) {
+        if (num_spells + 3 < lines / 2) {
+            touchwin(cw);
+            clearok(cw, FALSE);
+        }
+        else {
+            restscr(cw);
+        }
+    }
+
+    if (spells[which_spell].s_type == TYP_STICK && 
+        need_dir(STICK, spells[which_spell].s_which)) {
+            if (!get_dir(&player.t_newpos)) {
+                after = FALSE;
+                return(FALSE);
+            }
+    }
+    player.t_selection = which_spell;
+    player.t_no_move = (which_spell/3 + 1) * movement(&player);
+
+    spell_left = dummy; /* hack to stop IRIX complaint about dummy */
+                        /* not being used.                         */
+    return(TRUE);
+}
+
+/*
+ * opt_player:
+ * Let the player know what's happening with himself
+ */
+
+opt_player()
+{
+    int i = 1;  /* initialize counters */
+    int j = 2;
+
+    wclear(hw);
+    wmove(hw, 0, 0);
+    wprintw(hw, "Current player effects:");
+    wmove(hw, 2, 0);
+
+        /*   Print a list of what is happening.
+     *   If longer than 16 lines, make it two columns.
+     *   Currently, a maximum of 32 (out of 39) "effects"
+     *   can be happening all at once to a player.
+     */
+
+    /* 1 - Sense gold */
+    if (player.t_ctype == C_THIEF    || player.t_ctype == C_ASSASSIN ||
+        ((player.t_ctype == C_FIGHTER || player.t_ctype == C_RANGER) &&
+    pstats.s_lvl >= 12)) { 
+    wprintw(hw, "You can sense gold\n");
+    i++;
+    }
+    /* 2 - Sense traps */
+    if (player.t_ctype == C_THIEF   || ((player.t_ctype == C_ASSASSIN ||
+        player.t_ctype == C_FIGHTER || player.t_ctype == C_MONK)      &&
+    pstats.s_lvl >= 14)) {
+    wprintw(hw, "You can sense traps\n");
+    i++;
+    }
+    /* 3 - Steal */
+    if (player.t_ctype == C_THIEF    || player.t_ctype == C_ASSASSIN || 
+        (player.t_ctype == C_FIGHTER && pstats.s_lvl >= 15)) { 
+    wprintw(hw, "You can steal\n");
+    i++;
+    }
+    /* 4 - Cast spells */
+    if (player.t_ctype == C_MAGICIAN ||
+        (player.t_ctype == C_RANGER  && pstats.s_lvl > 1)) { 
+    wprintw(hw, "You can cast spells\n");
+    i++;
+    }
+    /* 5 - Make chants */
+    if (player.t_ctype == C_DRUID ||
+        (player.t_ctype == C_MONK && pstats.s_lvl > 1)) {
+    wprintw(hw, "You can chant\n");
+    i++;
+    }
+    /* 6 - Give prayers */
+    if (cur_relic[HEIL_ANKH] != 0 || player.t_ctype == C_CLERIC ||
+        (player.t_ctype == C_PALADIN && pstats.s_lvl > 1)) {
+    wprintw(hw, "You can pray\n");
+    i++;
+    }
+    /* 7 - Affect the undead */
+    if (cur_relic[HEIL_ANKH] != 0 || player.t_ctype == C_CLERIC ||
+        (player.t_ctype == C_PALADIN && pstats.s_lvl > 4)) { 
+    wprintw(hw, "You can affect the undead\n");
+    i++;
+    }
+    /* 8 - Cause fear */
+    if (ISWEARING(R_FEAR) != 0   || ((player.t_ctype == C_RANGER ||
+        player.t_ctype == C_PALADIN || player.t_ctype == C_MONK)    &&
+        pstats.s_lvl > 1)) {
+    wprintw(hw, "You are fearful\n");
+    i++;
+    }
+    /* 9 - Confuse monster */
+    if (on(player, CANHUH) != 0) {
+    wprintw(hw, "You have multi-colored hands\n");
+    i++;
+    }
+    /* 10 - Confused yourself */
+    if (on(player, ISHUH) != 0) {
+    wprintw(hw, "You are confused\n");
+    i++;
+    }                  /* really ISHUH or ISCLEAR */
+    /* 11 - Clear thought */
+    if (on(player, ISCLEAR) != 0) {
+    wprintw(hw, "You are clear headed\n");
+    i++;
+    }
+    /* 12 - Slow */
+    if (on(player, ISSLOW) != 0) {
+    wprintw(hw, "You are moving slow\n");
+    i++;
+    }                 /* really ISSLOW or ISHASTE */
+    /* 13 - Haste */
+    if (on(player, ISHASTE) != 0) {
+    wprintw(hw, "You are moving fast\n");
+    i++;
+    }
+    /* 14 - Flying */
+    if (on(player, ISFLY) != 0) {
+    wprintw(hw, "You are flying\n");
+    i++;
+    }
+    /* 15 - Blind */
+    if (on(player, ISBLIND) != 0) {
+    wprintw(hw, "You are blind\n");
+    i++;
+    }                 /* really ISBLIND or CANSEE */
+    /* 16 - Extra sight */
+    if (on(player, CANSEE) != 0) {
+    wprintw(hw, "You have extra sight\n");
+    i++;
+    }
+    /* 17 - Invisibility */
+    if (on(player, ISINVIS) != 0) {
+    /* Okay, start a second column of effects to the screen. */
+        if (i > 16) {
+            mvwaddstr(hw, j, 37, "You are invisible");
+        j++;
+        }
+    else {
+        wprintw(hw, "You are invisible\n");
+        i++;
+    }
+    }
+    /* 18 - Regeneration and vampiric regen */
+    if (ISWEARING(R_VAMPREGEN) != 0 || ISWEARING(R_REGEN) != 0) {
+        if (i > 16) {
+            mvwaddstr(hw, j, 37, "You have regenerative powers");
+        j++;
+        }
+    else {
+        wprintw(hw, "You have regenerative powers\n");
+        i++;
+    }
+    }
+    /* 19 - Phasing */
+    if (on(player, CANINWALL) != 0) {
+        if (i > 16) {
+            mvwaddstr(hw, j, 37, "You can walk through walls");
+        j++;
+        }
+    else {
+        wprintw(hw, "You can walk through walls\n");
+        i++;
+    }
+    }
+    /* 20 - Skill (good or bad, it won't last) */
+    if (find_slot(unskill) != 0) {
+        if (i > 16) {
+            mvwaddstr(hw, j, 37, "You feel skillful");
+        j++;
+        }
+    else {
+        wprintw(hw, "You feel skillful\n");
+        i++;
+    }
+    }
+    /* 21 - Stealthy */
+    if (ISWEARING(R_STEALTH) != 0) {
+        if (i > 16) {
+            mvwaddstr(hw, j, 37, "You have stealth");
+        j++;
+        }
+    else {
+        wprintw(hw, "You have stealth\n");
+        i++;
+    }
+    }
+    /* 22 - Alertness */
+    if (ISWEARING(R_ALERT) != 0) {  
+        if (i > 16) {
+            mvwaddstr(hw, j, 37, "You are awake and alert");
+        j++;
+        }
+    else {
+        wprintw(hw, "You are awake and alert\n");
+        i++;
+    }
+    }
+    /* 23 - Free action */
+    if (ISWEARING(R_FREEDOM) != 0) {
+        if (i > 16) {
+            mvwaddstr(hw, j, 37, "You feel free");
+        j++;
+        }
+    else {
+        wprintw(hw, "You feel free\n");
+        i++;
+    }
+    }
+    /* 24 - Heroism */
+    if (ISWEARING(R_HEROISM) != 0) {
+        if (i > 16) {
+            mvwaddstr(hw, j, 37, "You are brave");
+        j++;
+        }
+    else {
+        wprintw(hw, "You are brave\n");
+        i++;
+    }
+    }
+    /* 25 - Ice protection */
+    if (on(player, NOCOLD) != 0) {
+        if (i > 16) {
+            mvwaddstr(hw, j, 37, "You are protected from ice");
+        j++;
+        }
+    else {
+        wprintw(hw, "You are protected from ice\n");
+        i++;
+    }
+    }
+    /* 26 - Fire protection */
+    if (on(player, NOFIRE) != 0) {
+        if (i > 16) {
+            mvwaddstr(hw, j, 37, "You are protected from fire");
+        j++;
+        }
+    else {
+        wprintw(hw, "You are protected from fire\n");
+        i++;
+    }
+    }
+    /* 27 - Lightning protection */
+    if (on(player, NOBOLT) != 0) {
+        if (i > 16) {
+            mvwaddstr(hw, j, 37, "You are protected from lightning");
+        j++;
+        }
+    else {
+        wprintw(hw, "You are protected from lightning\n");
+        i++;
+    }
+    }
+    /* 28 - Gas protection */
+    if (on(player, NOGAS) != 0) {
+        if (i > 16) {
+            mvwaddstr(hw, j, 37, "You are protected from gas");
+        j++;
+        }
+    else {
+        wprintw(hw, "You are protected from gas\n");
+        i++;
+    }
+    }
+    /* 29 - Acid protection */
+    if (on(player, NOACID) != 0) { 
+        if (i > 16) {
+            mvwaddstr(hw, j, 37, "You are protected from acid");
+        j++;
+        }
+    else {
+        wprintw(hw, "You are protected from acid\n");
+        i++;
+    }
+    }
+    /* 30 - Breath protection */
+    if (cur_relic[YENDOR_AMULET] != 0) {
+        if (i > 16) {
+            mvwaddstr(hw, j, 37, "You are protected from monster breath");
+        j++;
+        }
+    else {
+        wprintw(hw, "You are protected from monster breath\n");
+        i++;
+    }             /* really only YENDOR or STONEBONES */
+    }           
+    /* 31 - Magic missile protection */
+    if (cur_relic[STONEBONES_AMULET] != 0) { 
+        if (i > 16) {
+            mvwaddstr(hw, j, 37, "You are protected from magic missiles");
+        j++;
+        }
+    else {
+        wprintw(hw, "You are protected from magic missiles\n");
+        i++;
+    }
+    }
+    /* 32 - Sustain health */
+    if (ISWEARING(R_HEALTH) != 0 && (off(player, HASDISEASE) &&
+    off(player, HASINFEST) && off(player, DOROT))) {  
+        if (i > 16) {     /* he's really healthy */
+            mvwaddstr(hw, j, 37, "You are in good health");
+        j++;
+        }
+    else {
+        wprintw(hw, "You are in good health\n"); 
+        i++;
+    }
+    }
+    /* 33 - Being held */
+    if (on(player, ISHELD) != 0) {
+        if (i > 16) {
+            mvwaddstr(hw, j, 37, "You are being held");
+        j++;
+        }
+    else {
+        wprintw(hw, "You are being held\n");
+        i++;
+    }
+    }
+    /* 34 - Stinks */
+    if (on(player, HASSTINK) != 0) {
+        if (i > 16) {
+            mvwaddstr(hw, j, 37, "You are affronted by a bad smell");
+        j++;
+        }
+    else {
+        wprintw(hw, "You are affronted by a bad smell\n");
+        i++;
+    }
+    }
+    /* 35 - Any attribute that is down */
+    if (pstats.s_intel    < max_stats.s_intel  ||
+        pstats.s_str      < max_stats.s_str    ||
+        pstats.s_wisdom   < max_stats.s_wisdom ||
+        pstats.s_dext     < max_stats.s_dext   ||
+        pstats.s_const    < max_stats.s_const  ||
+        pstats.s_charisma < max_stats.s_charisma) {
+        if (i > 16) {
+            mvwaddstr(hw, j, 37, "You are afflicted");
+        j++;
+        }
+    else {
+        wprintw(hw, "You are afflicted\n");
+        i++;
+    }
+    }
+    /* 36 - Diseased */
+    if (on(player, HASDISEASE) != 0) {  
+        if (i > 16) {
+            mvwaddstr(hw, j, 37, "You have a disease");
+        j++;
+        }
+    else {
+        wprintw(hw, "You have a disease\n");
+        i++;
+    }
+    }
+    /* 37 - Infested */
+    if (on(player, HASINFEST) != 0) {  
+        if (i > 16) {
+            mvwaddstr(hw, j, 37, "You have an infestation");
+        j++;
+        }
+    else {
+        wprintw(hw, "You have an infestation\n");
+        i++;
+    }
+    }
+    /* 38 - Body rot */
+    if (on(player, DOROT) != 0) {  
+        if (i > 16) {
+            mvwaddstr(hw, j, 37, "You have body rot");
+        j++;
+        }
+    else {
+        wprintw(hw, "You have body rot\n");
+        i++;
+    }
+    }
+    /* 39 - Dancing */
+    if (on(player, ISDANCE) != 0) {  
+        if (i > 16) {
+            mvwaddstr(hw, j, 37, "You are a dancing fool");
+        j++;
+        }
+    else {
+        wprintw(hw, "You are a dancing fool\n");
+        i++;
+    }
+    }
+    if (i == 1) {
+    wclear(hw);
+        msg("No player effects. ");
+    return;
+    }
+    else {
+    if (i > 1 && i < 17) {
+        j = 39;
+            if (menu_overlay) {     /* Print the list. */
+                wmove(hw, i+2, 0);
+                wprintw(hw, spacemsg);
+                over_win(cw, hw, i+3, j, i+2, 27, NULL);
+        }
+            else {
+                wmove(hw, i+2, 0);
+                wprintw(hw, spacemsg);
+            draw(hw);
+        }
+    }
+    else {
+        i = 17;
+            if (menu_overlay) {     /* Print the list. */
+                wmove(hw, i+2, 0);
+                wprintw(hw, spacemsg);
+        if (j > 2) j = 78;
+        else j = 39;
+                over_win(cw, hw, i+3, j, i+2, 27, NULL);
+        }
+            else {
+                wmove(hw, i+2, 0);
+                wprintw(hw, spacemsg);
+            draw(hw);
+        }
+    }
+        wait_for(' ');
+    wclear(hw);
+    status(FALSE);
+    touchwin(cw);
+        return;
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xrogue/potions.c	Tue Apr 21 08:55:20 2015 -0400
@@ -0,0 +1,1058 @@
+/*
+    potions.c - Functions for dealing with potions
+
+    XRogue: Expeditions into the Dungeons of Doom
+    Copyright (C) 1991 Robert Pietkivitch
+    All rights reserved.
+    
+    Based on "Advanced Rogue"
+    Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka and AT&T
+    All rights reserved.
+
+    Based on "Rogue: Exploring the Dungeons of Doom"
+    Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
+    All rights reserved.
+    
+    See the file LICENSE.TXT for full copyright and licensing information.
+*/
+
+#include <curses.h>
+#include "rogue.h"
+
+/*
+ * add_abil is an array of functions used to change attributes.  It must be
+ * ordered according to the attribute definitions in rogue.h.
+ */
+
+int (*add_abil[NUMABILITIES])() = {
+    add_intelligence, add_strength, add_wisdom, add_dexterity,
+    add_constitution, add_charisma
+};
+
+/*
+ * res_abil is an array of functions used to change attributes.  It must be
+ * ordered according to the attribute definitions in rogue.h.
+ */
+
+int (*res_abil[NUMABILITIES])() = {
+    res_intelligence, res_strength, res_wisdom, res_dexterity,
+    res_constitution, res_charisma
+};
+
+/*
+ * Increase player's constitution
+ */
+
+int
+add_constitution(change)
+int change;
+{
+    /* Do the potion */
+    if (change < 0) {
+        msg("You feel less healthy now.");
+        pstats.s_const += change;
+        if (pstats.s_const < 1) {
+        pstats.s_hpt = -1;
+        msg("You collapse!  --More--");
+        wait_for(' ');
+            death(D_CONSTITUTION);
+    }
+    }
+    else {
+        msg("You feel healthier now.");
+        pstats.s_const = min(pstats.s_const + change, MAXATT);
+    }
+
+    /* Adjust the maximum */
+    if (max_stats.s_const < pstats.s_const)
+        max_stats.s_const = pstats.s_const;
+
+    return(0);
+}
+
+/*
+ * Increase player's charisma
+ */
+
+int
+add_charisma(change)
+int change;
+{
+    /* Do the potion */
+    if (change < 0) msg("You feel less attractive now.");
+    else msg("You feel more attractive now.");
+
+    pstats.s_charisma += change;
+    if (pstats.s_charisma > MAXATT) pstats.s_charisma = MAXATT;
+    else if (pstats.s_charisma < 3) pstats.s_charisma = 3;
+
+    /* Adjust the maximum */
+    if (max_stats.s_charisma < pstats.s_charisma)
+        max_stats.s_charisma = pstats.s_charisma;
+
+    return(0);
+}
+
+/*
+ * Increase player's dexterity
+ */
+
+int
+add_dexterity(change)
+int change;
+{
+    int ring_str;       /* Value of ring strengths */
+
+    /* Undo any ring changes */
+    ring_str = ring_value(R_ADDHIT);
+    pstats.s_dext -= ring_str;
+
+    /* Now do the potion */
+    if (change < 0) msg("You feel less dextrous now.");
+    else msg("You feel more dextrous now.  Watch those hands!");
+
+    pstats.s_dext += change;
+    if (pstats.s_dext > MAXATT) pstats.s_dext = MAXATT;
+    else if (pstats.s_dext < 3) pstats.s_dext = 3;
+
+    /* Adjust the maximum */
+    if (max_stats.s_dext < pstats.s_dext)
+        max_stats.s_dext = pstats.s_dext;
+
+    /* Now put back the ring changes */
+    if (ring_str)
+        pstats.s_dext += ring_str;
+
+    return(0);
+}
+
+/*
+ * add_haste:
+ *      add a haste to the player
+ */
+
+add_haste(blessed)
+bool blessed;
+{
+    int hasttime;
+
+    if (player.t_ctype == C_MONK) { /* monks cannot be slowed or hasted */
+        msg(nothing);
+        return;
+    }
+
+    if (blessed) hasttime = HASTETIME*2;
+    else hasttime = HASTETIME;
+
+    if (on(player, ISSLOW)) { /* Is person slow? */
+        extinguish(noslow);
+        noslow();
+
+        if (blessed) hasttime = HASTETIME/2;
+        else return;
+    }
+
+    if (on(player, ISHASTE)) {
+        msg("You faint from exhaustion.");
+        player.t_no_move += movement(&player) * rnd(hasttime);
+        player.t_action = A_FREEZE;
+        lengthen(nohaste, roll(hasttime,hasttime));
+    }
+    else {
+        msg("You feel yourself moving %sfaster.", blessed ? "much " : "");
+        turn_on(player, ISHASTE);
+        fuse(nohaste, (VOID *)NULL, roll(hasttime, hasttime), AFTER);
+    }
+}
+
+/*
+ * Increase player's intelligence
+ */
+
+int
+add_intelligence(change)
+int change;
+{
+    int ring_str;       /* Value of ring strengths */
+
+    /* Undo any ring changes */
+    ring_str = ring_value(R_ADDINTEL);
+    pstats.s_intel -= ring_str;
+
+    /* Now do the potion */
+    if (change < 0) msg("You feel slightly less intelligent now.");
+    else msg("You feel more intelligent now.  What a mind!");
+
+    pstats.s_intel += change;
+    if (pstats.s_intel > MAXATT) pstats.s_intel = MAXATT;
+    else if (pstats.s_intel < 3) pstats.s_intel = 3;
+
+    /* Adjust the maximum */
+    if (max_stats.s_intel < pstats.s_intel)
+            max_stats.s_intel = pstats.s_intel;
+
+    /* Now put back the ring changes */
+    if (ring_str)
+        pstats.s_intel += ring_str;
+
+    return(0);
+}
+
+/*
+ * this routine makes the hero move slower 
+ */
+
+add_slow()
+{
+    /* monks cannot be slowed or hasted */
+    if (player.t_ctype == C_MONK || ISWEARING(R_FREEDOM)) { 
+        msg(nothing);
+        return;
+    }
+
+    if (on(player, ISHASTE)) { /* Already sped up */
+        extinguish(nohaste);
+        nohaste();
+    }
+    else {
+        msg("You feel yourself moving %sslower.",
+                on(player, ISSLOW) ? "even " : "");
+        if (on(player, ISSLOW))
+            lengthen(noslow, roll(HASTETIME,HASTETIME));
+        else {
+            turn_on(player, ISSLOW);
+            fuse(noslow, (VOID *)NULL, roll(HASTETIME,HASTETIME), AFTER);
+        }
+    }
+}
+
+/*
+ * Increase player's strength
+ */
+
+int
+add_strength(change)
+int change;
+{
+
+    if (change < 0) {
+        msg("You feel slightly weaker now.");
+        chg_str(change);
+    }
+    else {
+        msg("You feel stronger now.  What bulging muscles!");
+        chg_str(change);
+    }
+    return(0);
+}
+
+/*
+ * Increase player's wisdom
+ */
+
+int
+add_wisdom(change)
+int change;
+{
+    int ring_str;       /* Value of ring strengths */
+
+    /* Undo any ring changes */
+    ring_str = ring_value(R_ADDWISDOM);
+    pstats.s_wisdom -= ring_str;
+
+    /* Now do the potion */
+    if (change < 0) msg("You feel slightly less wise now.");
+    else msg("You feel wiser now.  What a sage!");
+
+    pstats.s_wisdom += change;
+    if (pstats.s_wisdom > MAXATT) pstats.s_wisdom = MAXATT;
+    else if (pstats.s_wisdom < 3) pstats.s_wisdom = 3;
+
+    /* Adjust the maximum */
+    if (max_stats.s_wisdom < pstats.s_wisdom)
+        max_stats.s_wisdom = pstats.s_wisdom;
+
+    /* Now put back the ring changes */
+    if (ring_str)
+        pstats.s_wisdom += ring_str;
+
+    return(0);
+}
+
+quaff(which, kind, flags, is_potion)
+int which;
+int kind;
+int flags;
+bool is_potion;
+{
+    register struct object *obj;
+    register struct linked_list *item, *titem;
+    register struct thing *th;
+    bool cursed, blessed;
+
+    blessed = FALSE;
+    cursed = FALSE;
+    item = NULL;
+
+    if (which < 0) {    /* figure out which ourselves */
+        /* This is a potion.  */
+        if (player.t_action != C_QUAFF) {
+            int units;
+
+            item = get_item(pack, "quaff", QUAFFABLE, FALSE, FALSE);
+
+            /*
+             * Make certain that it is somethings that we want to drink
+             */
+            if (item == NULL)
+                return;
+
+            /* How long does it take to quaff? */
+            units = usage_time(item);
+            if (units < 0) return;
+
+            player.t_using = item;      /* Remember what it is */
+            player.t_no_move = units * movement(&player);
+            if ((OBJPTR(item))->o_type == POTION) player.t_action = C_QUAFF;
+            else player.t_action = C_USE;
+            return;
+        }
+
+        /* We have waited our time, let's quaff the potion */
+        item = player.t_using;
+        player.t_using = NULL;
+        player.t_action = A_NIL;
+
+        obj = OBJPTR(item);
+        /* remove it from the pack */
+        inpack--;
+        detach(pack, item);
+
+        flags = obj->o_flags;
+        which = obj->o_which;
+        kind = obj->o_kind;
+    }
+    cursed = flags & ISCURSED;
+    blessed = flags & ISBLESSED;
+
+    switch(which) {
+        case P_CLEAR:
+            if (cursed) {
+                confus_player();
+            }
+            else {
+                if (blessed) {  /* Make player immune for the whole game */
+                    extinguish(unclrhead);  /* If we have a fuse, put it out */
+                    msg("A strong blue aura surrounds your head.");
+                }
+                else {  /* Just light a fuse for how long player is safe */
+                    if (off(player, ISCLEAR)) {
+                        fuse(unclrhead, (VOID *)NULL, CLRDURATION, AFTER);
+                        msg("A faint blue aura surrounds your head.");
+                    }
+                    else {  /* If we have a fuse lengthen it, else we
+                             * are permanently clear.
+                             */
+                        if (find_slot(unclrhead) == 0)
+                            msg("Your blue aura continues to glow strongly.");
+                        else {
+                            lengthen(unclrhead, CLRDURATION);
+                            msg("Your blue aura brightens for a moment.");
+                        }
+                    }
+                }
+                turn_on(player, ISCLEAR);
+                /* If player is confused, unconfuse him */
+                if (on(player, ISHUH)) {
+                    extinguish(unconfuse);
+                    unconfuse();
+                }
+            }
+        when P_HEALING:
+            if (cursed) {
+                msg("You feel worse now.");
+                pstats.s_hpt -= roll(pstats.s_lvl, char_class[player.t_ctype].hit_pts);
+                if (pstats.s_hpt < 1) {
+            pstats.s_hpt = -1;
+            msg("You're life passes before your eyes..  --More--");
+            wait_for(' ');
+                    death(D_POTION);
+        }
+            }
+            else {
+                if (blessed) {
+                    pstats.s_hpt += roll(pstats.s_lvl+1, char_class[player.t_ctype].hit_pts);
+                    if (pstats.s_hpt > max_stats.s_hpt) {
+                        pstats.s_hpt = ++max_stats.s_hpt;
+                        pstats.s_hpt = ++max_stats.s_hpt;
+            }
+                    if (on(player, ISHUH)) {
+                        extinguish(unconfuse);
+                        unconfuse();
+                    }
+                }
+                else {
+                    pstats.s_hpt += roll(pstats.s_lvl+1, char_class[player.t_ctype].hit_pts/2);
+                    if (pstats.s_hpt > max_stats.s_hpt)
+                        pstats.s_hpt = ++max_stats.s_hpt;
+                }
+                msg("You begin to feel %sbetter.",
+                        blessed ? "much " : "");
+                sight();
+                if (is_potion) p_know[P_HEALING] = TRUE;
+            }
+        when P_ABIL:
+            /* If it is cursed, we take a point away */
+            if (cursed) {
+                if (ISWEARING(R_SUSABILITY)) {
+                    msg(nothing);
+                    break;
+                }
+                else (*add_abil[kind])(-1);
+            }
+
+            /* Otherwise we add points */
+            else (*add_abil[kind])(blessed ? 3 : 1);
+
+            if (is_potion) p_know[P_ABIL] = TRUE;
+        when P_MFIND:
+            /*
+             * Potion of monster detection, if there are monters, detect them
+             */
+            if (mlist != NULL)
+            {
+                register struct thing *tp;
+                register struct linked_list *item;
+
+                wclear(hw);
+                for (item=mlist; item!=NULL; item=next(item)) {
+                    tp = THINGPTR(item);
+                    if (on(*tp, NODETECT))
+                        continue;
+                    if (off(*tp, ISRUN))/* turn off only on sleeping ones */
+                        turn_off(*tp, CANSURPRISE);
+                    mvwaddch(hw, tp->t_pos.y, tp->t_pos.x, 
+                             monsters[tp->t_index].m_appear);
+                }
+                rmmsg();
+                overlay(hw,cw);
+                draw(cw);
+                msg("You begin to sense the presence of monsters.");
+                if (is_potion) 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
+             */
+            {
+                register struct linked_list *mobj;
+                register struct object *tp;
+                bool show;
+
+                show = FALSE;
+                wclear(hw);
+                for (mobj = lvl_obj; mobj != NULL; mobj = next(mobj)) {
+                    tp = OBJPTR(mobj);
+                    if (is_magic(tp)) {
+                        char mag_type=MAGIC;
+
+                        /* Mark cursed items or bad weapons */
+                        if ((tp->o_flags & ISCURSED) ||
+                            (tp->o_type == WEAPON &&
+                             (tp->o_hplus < 0 || tp->o_dplus < 0)))
+                                mag_type = CMAGIC;
+                        else if ((tp->o_flags & ISBLESSED) ||
+                                 (tp->o_type == WEAPON &&
+                                  (tp->o_hplus > 0 || tp->o_dplus > 0)))
+                                        mag_type = BMAGIC;
+                        show = TRUE;
+                        mvwaddch(hw, tp->o_pos.y, tp->o_pos.x, mag_type);
+                    }
+                }
+                for (titem = mlist; titem != NULL; titem = next(titem)) {
+                    register struct linked_list *pitem;
+
+                    th = THINGPTR(titem);
+                    if (on(*th, NODETECT)) continue;
+                    for(pitem = th->t_pack; pitem != NULL; pitem = next(pitem)){
+                        tp = OBJPTR(pitem);
+                        if (is_magic(tp)) {
+                            char mag_type=MAGIC;
+
+                            /* Mark cursed items or bad weapons */
+                            if ((tp->o_flags & ISCURSED) ||
+                                (tp->o_type == WEAPON &&
+                                 (tp->o_hplus < 0 || tp->o_dplus < 0)))
+                                    mag_type = CMAGIC;
+                            else if ((tp->o_flags & ISBLESSED) ||
+                                     (tp->o_type == WEAPON &&
+                                      (tp->o_hplus > 0 || tp->o_dplus > 0)))
+                                            mag_type = BMAGIC;
+                            show = TRUE;
+                            mvwaddch(hw, th->t_pos.y, th->t_pos.x, mag_type);
+                        }
+                    }
+                }
+                if (show) {
+                    if (is_potion) p_know[P_TFIND] = TRUE;
+                    rmmsg();
+                    overlay(hw,cw);
+                    draw(cw);
+                    msg("You sense the presence of magic on this level.");
+                    break;
+                }
+                else
+                    msg("You have a strange feeling for a moment, then it passes.");
+            }
+        when P_SEEINVIS:
+            if (cursed) {
+                if (!find_slot(sight))
+                {
+                    msg("A cloak of darkness falls around you.");
+                    turn_on(player, ISBLIND);
+                    fuse(sight, (VOID *)NULL, SEEDURATION, AFTER);
+                    light(&hero);
+                }
+                else
+                    msg("The darkness around you thickens. ");
+                    lengthen(sight, SEEDURATION);
+            }
+            else {
+                if (off(player, CANSEE)) {
+                    turn_on(player, CANSEE);
+                    msg("Your eyes begin to tingle.");
+                    fuse(unsee, (VOID *)NULL, blessed ? SEEDURATION*3 :SEEDURATION, AFTER);
+                    light(&hero);
+                }
+                else if (find_slot(unsee) != 0) {
+                    msg("You eyes continue to tingle.");
+                    lengthen(unsee, blessed ? SEEDURATION*3 : SEEDURATION);
+        }
+                sight();
+            }
+        when P_PHASE:
+            if (cursed) {
+                msg("You can't move.");
+                player.t_no_move = movement(&player) * FREEZETIME;
+                player.t_action = A_FREEZE;
+            }
+            else {
+                int duration;
+
+                if (blessed) duration = 3;
+                else duration = 1;
+
+                if (on(player, CANINWALL))
+                    lengthen(unphase, duration*PHASEDURATION);
+                else {
+                    fuse(unphase, (VOID *)NULL, duration*PHASEDURATION, AFTER);
+                    turn_on(player, CANINWALL);
+                }
+                msg("You feel %slight-headed!",
+                    blessed ? "very " : "");
+            }
+        when P_FLY: {
+            int duration;
+            bool say_message;
+
+            say_message = TRUE;
+
+            if (blessed) duration = 3;
+            else duration = 1;
+
+            if (on(player, ISFLY)) {
+                if (find_slot(land))
+                    lengthen(land, duration*FLYTIME);
+                else {
+                    msg("Nothing happens.");    /* Flying by cloak */
+                    say_message = FALSE;
+                }
+            }
+            else {
+                fuse(land, (VOID *)NULL, duration*FLYTIME, AFTER);
+                turn_on(player, ISFLY);
+            }
+            if (say_message) {
+                if (is_potion) p_know[P_FLY] = TRUE;
+                msg("You feel %slighter than air!", blessed ? "much " : "");
+            }
+        }
+        when P_RAISE:
+            if (cursed) lower_level(D_POTION);
+            else {
+                msg("You suddenly feel %smore skillful",
+                        blessed ? "much " : "");
+                p_know[P_RAISE] = TRUE;
+                raise_level();
+                do_panic(NULL);         /* this startles them */
+                if (blessed) raise_level();
+            }
+        when P_HASTE:
+            if (cursed) {       /* Slow player down */
+                add_slow();
+            }
+            else {
+                add_haste(blessed);
+                if (is_potion) p_know[P_HASTE] = TRUE;
+            }
+        when P_RESTORE: {
+            register int i, howmuch, strength_tally;
+
+            msg("Hey, this tastes great.  It make you feel %swarm all over.",
+                blessed ? "really " : "");
+            howmuch = blessed ? 3 : 1;
+
+            for (i=0; i<NUMABILITIES; i++) {
+                if (i == A_STRENGTH) {
+                    if (lost_str) {
+                        if (lost_str > howmuch) {
+                            lost_str -= howmuch;
+
+                            /*
+                             * Save the lost strength.  We have to set
+                             * temporarilty set it to 0 so that res_strength
+                             * will not restore it.
+                             */
+                            strength_tally = lost_str;
+                            lost_str = 0;
+                            res_strength(howmuch);
+                            lost_str = strength_tally;
+                        }
+                        else {
+                        lost_str = 0;
+                            extinguish(res_strength);
+                            res_strength(howmuch);
+                        }
+                    }
+                    else res_strength(howmuch);
+                }
+                else (*res_abil[i])(howmuch);
+            }
+        }
+        when P_INVIS:
+            if (off(player, ISINVIS)) {
+                turn_on(player, ISINVIS);
+                msg("You have a tingling feeling all over your body");
+                fuse(appear, (VOID *)NULL, blessed ? GONETIME*3 : GONETIME, AFTER);
+                PLAYER = IPLAYER;
+                light(&hero);
+            }
+            else {
+                if (find_slot(appear)) {
+                    msg("Your tingling feeling surges.");
+                    lengthen(appear, blessed ? GONETIME*3 : GONETIME);
+                }
+                else msg("Nothing happens.");   /* Using cloak */
+            }
+
+        when P_FFIND:
+            {
+                register struct linked_list *nitem;
+                register struct object *nobj;
+                bool show;
+
+                show = FALSE;
+                wclear(hw);
+                for (nitem = lvl_obj; nitem != NULL; nitem = next(nitem)) {
+                    nobj = OBJPTR(nitem);
+                    if (nobj->o_type == FOOD) {
+                        show = TRUE;
+                        mvwaddch(hw, nobj->o_pos.y, nobj->o_pos.x, FOOD);
+                    }
+                }
+                for (nitem = mlist; nitem != NULL; nitem = next(nitem)) {
+                    register struct linked_list *pitem;
+                    register struct thing *th;
+
+                    th = THINGPTR(nitem);
+                    if (on(*th, NODETECT)) continue;
+                    for(pitem = th->t_pack; pitem != NULL; pitem = next(pitem)){
+                        nobj = OBJPTR(pitem);
+                        if (nobj->o_type == FOOD) {
+                            show = TRUE;
+                            mvwaddch(hw, th->t_pos.y, th->t_pos.x, FOOD);
+                        }
+                    }
+                }
+                if (is_potion) p_know[P_FFIND] = TRUE;
+                if (show) {
+                    rmmsg();
+                    msg("Your nose tingles.");
+                    rmmsg();
+                    overlay(hw,cw);
+                    draw(cw);
+                    msg("You sense the presence of food on this level.");
+                }
+                else
+                    msg("You have a strange feeling for a moment, then it passes.");
+            }
+
+        when P_SKILL:
+            if (cursed) {
+                msg("You feel less skillful.");
+
+                /* Does he currently have an artifical skill? */
+                if (!find_slot(unskill)) {      /* No skill */
+                    pstats.s_lvladj = -2;
+                    pstats.s_lvl += pstats.s_lvladj;
+                    fuse(unskill, (VOID *)NULL, SKILLDURATION, AFTER);
+                }
+                else {  /* Has an artifical skill */
+                    /* Is the skill beneficial? */
+                    if (pstats.s_lvladj > 0) {
+                        /* Decrease the previous skill advantage */
+                        pstats.s_lvl -= 2;
+                        pstats.s_lvladj -= 2;
+
+                        /* If there is now a negative skill, lengthen time */
+                        if (pstats.s_lvladj < 0)
+                            lengthen(unskill, SKILLDURATION);
+
+                        /* If there is no skill advantage, unfuse us */
+                        else if (pstats.s_lvladj == 0) extinguish(unskill);
+                    }
+                    else {      /* Already bad */
+                        /* Make it a little worse, and lengthen it */
+                        pstats.s_lvl--;
+                        pstats.s_lvladj--;
+                        lengthen(unskill, SKILLDURATION);
+                    }
+                }
+
+                /* Is our level too low now? */
+                if (pstats.s_lvl < 1) {
+            pstats.s_hpt = -1;
+            msg("You cough, choke, and finally die.  --More--");
+            wait_for(' ');
+            death(D_POTION);
+        }
+            }
+            else {
+                int adjust;
+
+                msg("You feel more skillful.");
+                max_stats.s_hpt++;
+                pstats.s_hpt++;
+
+                /* Get the adjustment */
+                if (blessed)
+                    adjust = rnd(4) + 2;
+                else
+                    adjust = rnd(2) + 1;
+
+        /* The Fighter likes this */
+            if (player.t_ctype == C_FIGHTER) {
+                    max_stats.s_hpt++;
+                    pstats.s_hpt++;
+                    adjust = rnd(2) + 1;
+            }
+
+                /* Does he currently have an artifical skill? */
+                if (!find_slot(unskill)) {
+                    pstats.s_lvladj = adjust;
+                    pstats.s_lvl += pstats.s_lvladj;
+                    fuse(unskill, (VOID *)NULL, 
+                         blessed ? SKILLDURATION*2 : SKILLDURATION, AFTER);
+                }
+                else {  /* Has an artifical skill */
+                    /* Is the skill detrimental? */
+                    if (pstats.s_lvladj < 0) {
+                        /* Decrease the previous skill advantage */
+                        pstats.s_lvl += adjust;
+                        pstats.s_lvladj += adjust;
+
+                        /* If there is now a positive skill, lengthen time */
+                        if (pstats.s_lvladj < 0)
+                            lengthen(unskill, SKILLDURATION);
+
+                        /* If there is no skill advantage, unfuse us */
+                        else if (pstats.s_lvladj == 0) extinguish(unskill);
+                    }
+                    else {      /* Already good */
+                        /*
+                         * Make the skill the maximum of the current good
+                         * skill and what the adjust would give him.
+                         */
+                        pstats.s_lvl -= pstats.s_lvladj;
+                        pstats.s_lvladj = max(pstats.s_lvladj, adjust);
+                        pstats.s_lvl += pstats.s_lvladj;
+                        lengthen(unskill,
+                                 blessed ? SKILLDURATION*2 : SKILLDURATION);
+                    }
+                }
+            }
+
+        when P_FIRE: {
+            int duration;
+            bool say_message;
+
+            say_message = TRUE;
+
+            if (blessed) duration = 8;
+            else duration = 3;
+
+            if (on(player, NOFIRE)) {
+            if (cursed) {
+            msg("You quench your thirst. ");
+            say_message = FALSE;
+            }
+                else if (find_slot(nofire)) {
+                    lengthen(nofire, duration*FIRETIME);
+            msg("Your feeling of fire resistance increases. ");
+            say_message = FALSE;
+        }
+                else {
+                    msg("You experience heat waves. ");    /* has on a ring */
+                    say_message = FALSE;
+                }
+            }
+        else if (cursed) {
+        msg("You quench your thirst. ");
+        say_message = FALSE;
+        }
+            else {
+                fuse(nofire, (VOID *)NULL, duration*FIRETIME, AFTER);
+                turn_on(player, NOFIRE);
+            }
+            if (say_message)  {
+                if (is_potion) p_know[P_FIRE] = TRUE;
+                msg("You feel %sfire resistant", blessed ? "very " : "");
+            }
+        }
+        when P_COLD: {
+            int duration;
+            bool say_message;
+
+            say_message = TRUE;
+
+            if (blessed) duration = 8;
+            else duration = 3;
+
+            if (on(player, NOCOLD)) {
+            if (cursed) {
+            msg("You quench your thirst. ");
+            say_message = FALSE;
+            }
+                else if (find_slot(nocold)) {
+                    lengthen(nocold, duration*COLDTIME);
+            msg("Your feeling of cold resistance increases. ");
+            say_message = FALSE;
+        }
+                else {
+                    msg("You feel a cold chill. ");    /* has on a ring */
+                    say_message = FALSE;
+                }
+            }
+        else if (cursed) {
+        msg("You quench your thirst. ");
+        say_message = FALSE;
+        }
+            else {
+                fuse(nocold, (VOID *)NULL, duration*COLDTIME, AFTER);
+                turn_on(player, NOCOLD);
+            }
+            if (say_message)  {
+                if (is_potion) p_know[P_COLD] = TRUE;
+                msg("You feel %scold resistant", blessed ? "very " : "");
+            }
+        }
+        when P_LIGHTNING: {
+            int duration;
+            bool say_message;
+
+            say_message = TRUE;
+
+            if (blessed) duration = 8;
+            else duration = 3;
+
+            if (on(player, NOBOLT)) {
+            if (cursed) {
+            msg("You quench your thirst. ");
+            say_message = FALSE;
+            }
+                else if (find_slot(nobolt)) {
+                    lengthen(nobolt, duration*BOLTTIME);
+            msg("Your blue skin deepens in hue. ");
+            say_message = FALSE;
+        }
+        else msg(nothing);
+            }
+        else if (cursed) {
+        msg("You quench your thirst. ");
+        say_message = FALSE;
+        }
+            else {
+                fuse(nobolt, (VOID *)NULL, duration*BOLTTIME, AFTER);
+                turn_on(player, NOBOLT);
+            }
+            if (say_message) {
+                if (is_potion) p_know[P_LIGHTNING] = TRUE;
+                msg("Your skin turns %sblue!", blessed ? "very " : "");
+        }
+        }
+        when P_POISON:
+            if (!save(VS_POISON, &player, -2)) {
+                msg("You feel very sick now.");
+                pstats.s_hpt /= 2;
+                if (!ISWEARING(R_SUSABILITY))
+                    pstats.s_const--;
+            }
+            else {
+                msg("You feel sick now.");
+                pstats.s_hpt -= (pstats.s_hpt / 3);
+            }
+            if (pstats.s_const < 1 || pstats.s_hpt < 1) {
+        pstats.s_hpt = -1;
+        msg("You didn't survive!  --More--");
+        wait_for(' ');
+                death(D_POISON);
+        }
+        otherwise:
+            msg("What an odd tasting potion!");
+            return;
+    }
+    status(FALSE);
+    if (is_potion && item && p_know[which] && p_guess[which])
+    {
+        free(p_guess[which]);
+        p_guess[which] = NULL;
+    }
+    else if (is_potion                  && 
+             !p_know[which]             && 
+             item                       &&
+             askme                      &&
+             (flags & ISKNOW) == 0      &&
+             (flags & ISPOST) == 0      &&
+             p_guess[which] == NULL) {
+        nameitem(item, FALSE);
+    }
+    if (item != NULL) o_discard(item);
+    updpack(TRUE, &player);
+}
+
+
+/*
+ * res_dexterity:
+ *      Restore player's dexterity
+ *      if called with zero the restore fully
+ */
+
+int
+res_dexterity(howmuch)
+int howmuch;
+{
+    short save_max;
+    int ring_str;
+
+    if (howmuch < 0) return(0);
+
+    /* Discount the ring value */
+    ring_str = ring_value(R_ADDHIT);
+    pstats.s_dext -= ring_str;
+
+    if (pstats.s_dext < max_stats.s_dext ) {
+        if (howmuch == 0)
+            pstats.s_dext = max_stats.s_dext;
+        else
+            pstats.s_dext = min(pstats.s_dext+howmuch, max_stats.s_dext);
+    }
+
+    /* Redo the rings */
+    if (ring_str) {
+        save_max = max_stats.s_dext;
+        pstats.s_dext += ring_str;
+        max_stats.s_dext = save_max;
+    }
+    return(0);
+}
+
+/*
+ * res_intelligence:
+ *      Restore player's intelligence
+ */
+
+int
+res_intelligence(howmuch)
+int howmuch;
+{
+    short save_max;
+    int ring_str;
+
+    if (howmuch <= 0) return(0);
+
+    /* Discount the ring value */
+    ring_str = ring_value(R_ADDINTEL);
+    pstats.s_intel -= ring_str;
+
+    pstats.s_intel = min(pstats.s_intel + howmuch, max_stats.s_intel);
+
+    /* Redo the rings */
+    if (ring_str) {
+        save_max = max_stats.s_intel;
+        pstats.s_intel += ring_str;
+        max_stats.s_intel = save_max;
+    }
+    return(0);
+}
+
+/*
+ * res_wisdom:
+ *      Restore player's wisdom
+ */
+
+int
+res_wisdom(howmuch)
+int howmuch;
+{
+    short save_max;
+    int ring_str;
+
+    if (howmuch <= 0) return(0);
+
+    /* Discount the ring value */
+    ring_str = ring_value(R_ADDWISDOM);
+    pstats.s_wisdom -= ring_str;
+
+    pstats.s_wisdom = min(pstats.s_wisdom + howmuch, max_stats.s_wisdom);
+
+    /* Redo the rings */
+    if (ring_str) {
+        save_max = max_stats.s_wisdom;
+        pstats.s_wisdom += ring_str;
+        max_stats.s_wisdom = save_max;
+    }
+    return(0);
+}
+
+/*
+ * res_constitution:
+ *      Restore the players constitution.
+ */
+
+int
+res_constitution(howmuch)
+int howmuch;
+{
+    if (howmuch > 0)
+        pstats.s_const = min(pstats.s_const + howmuch, max_stats.s_const);
+
+    return(0);
+}
+
+/*
+ * res_charisma:
+ *      Restore the players charisma.
+ */
+
+int
+res_charisma(howmuch)
+int howmuch;
+{
+    if (howmuch > 0)
+        pstats.s_charisma =
+            min(pstats.s_charisma + howmuch, max_stats.s_charisma);
+
+    return(0);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xrogue/rings.c	Tue Apr 21 08:55:20 2015 -0400
@@ -0,0 +1,173 @@
+/*
+    rings.c - Routines dealing specificaly with rings
+    
+    XRogue: Expeditions into the Dungeons of Doom
+    Copyright (C) 1991 Robert Pietkivitch
+    All rights reserved.
+    
+    Based on "Advanced Rogue"
+    Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka and AT&T
+    All rights reserved.
+
+    Based on "Rogue: Exploring the Dungeons of Doom"
+    Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
+    All rights reserved.
+    
+    See the file LICENSE.TXT for full copyright and licensing information.
+*/
+
+#include <curses.h>
+#include "rogue.h"
+
+/*
+ * routines dealing specifically with rings
+ */
+
+/*
+ * how much food does this ring use up?
+ */
+
+ring_eat(hand)
+register int hand;
+{
+    if (cur_ring[hand] == NULL)
+        return 0;
+    switch (cur_ring[hand]->o_which) {
+        case R_VAMPREGEN:
+            return 3;
+        case R_REGEN:
+        case R_SUSABILITY:
+            return 2;
+        case R_HEALTH:
+            return 1;
+        case R_SEARCH:
+        case R_SEEINVIS:
+            return (rnd(100) < 50);  /* 0 or 1 */
+        case R_DIGEST:
+            if (cur_ring[hand]->o_ac >= 0)
+                return (-(cur_ring[hand]->o_ac)-1);
+            else
+                return (-(cur_ring[hand]->o_ac));
+    }
+    return 0;
+}
+
+ring_on(item)
+register struct linked_list *item;
+{
+    register struct object *obj;
+    register int save_max;
+
+    obj = OBJPTR(item);
+
+    /*
+     * 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;
+        when R_ADDHIT:
+            pstats.s_dext += obj->o_ac;
+        when R_ADDINTEL:
+            pstats.s_intel += obj->o_ac;
+        when R_ADDWISDOM:
+            pstats.s_wisdom += obj->o_ac;
+        when R_SEEINVIS:
+        if (on(player, CANSEE)) msg("Your eyes sparkle.");
+        else msg("Your eyes begin to tingle.");
+            turn_on(player, CANSEE);
+            light(&hero);
+            mvwaddch(cw, hero.y, hero.x, PLAYER);
+        when R_AGGR:
+            aggravate(TRUE, TRUE);  /* all charactors are affected*/
+        when R_WARMTH:
+        if (on(player, NOCOLD)) msg("You feel warm all over.");
+        else msg("You begin to feel warm.");
+            turn_on(player, NOCOLD);
+        when R_FIRE:
+        if (on(player, NOFIRE)) msg("You feel quite fire proof now.");
+        else msg("You begin to feel fire proof.");
+            turn_on(player, NOFIRE);
+        when R_LIGHT: {
+            if(roomin(&hero) != NULL) {
+                light(&hero);
+                mvwaddch(cw, hero.y, hero.x, PLAYER);
+            }
+    }
+        when R_SEARCH:
+            daemon(ring_search, (VOID *)NULL, AFTER);
+        when R_TELEPORT:
+            daemon(ring_teleport, (VOID *)NULL, AFTER);
+    }
+    status(FALSE);
+    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 && 
+             (obj->o_flags & ISKNOW) == 0 &&
+             r_guess[obj->o_which] == NULL) {
+        nameitem(item, FALSE);
+    }
+}
+
+/*
+ * print ring bonuses
+ */
+
+char *
+ring_num(obj)
+register 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:
+        case R_ADDINTEL:
+        case R_ADDWISDOM:
+        case R_DIGEST:
+            buf[0] = ' ';
+            strcpy(&buf[1], num(obj->o_ac, 0));
+        when R_AGGR:
+        case R_LIGHT:
+        case R_CARRY:
+        case R_TELEPORT:
+            if (obj->o_flags & ISCURSED)
+                return " cursed";
+            else
+                return "";
+        otherwise:
+            return "";
+    }
+    return buf;
+}
+
+/* 
+ * Return the effect of the specified ring 
+ */
+
+ring_value(type)
+{
+    int result = 0;
+
+    if (ISRING(LEFT_1, type))  result += cur_ring[LEFT_1]->o_ac;
+    if (ISRING(LEFT_2, type))  result += cur_ring[LEFT_2]->o_ac;
+    if (ISRING(LEFT_3, type))  result += cur_ring[LEFT_3]->o_ac;
+    if (ISRING(LEFT_4, type))  result += cur_ring[LEFT_4]->o_ac;
+    if (ISRING(RIGHT_1, type)) result += cur_ring[RIGHT_1]->o_ac;
+    if (ISRING(RIGHT_2, type)) result += cur_ring[RIGHT_2]->o_ac;
+    if (ISRING(RIGHT_3, type)) result += cur_ring[RIGHT_3]->o_ac;
+    if (ISRING(RIGHT_4, type)) result += cur_ring[RIGHT_4]->o_ac;
+    return(result);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xrogue/rip.c	Tue Apr 21 08:55:20 2015 -0400
@@ -0,0 +1,763 @@
+/*
+    rip.c - File for the fun ends Death or a total win
+    
+    XRogue: Expeditions into the Dungeons of Doom
+    Copyright (C) 1991 Robert Pietkivitch
+    All rights reserved.
+    
+    Based on "Advanced Rogue"
+    Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka and AT&T
+    All rights reserved.
+
+    Based on "Rogue: Exploring the Dungeons of Doom"
+    Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
+    All rights reserved.
+    
+    See the file LICENSE.TXT for full copyright and licensing information.
+*/
+
+#define REALLIFE 1      /* Print out machine and logname */
+#define EDITSCORE 2     /* Edit the current score file */
+#define ADDSCORE 3      /* Add a new score */
+
+#include <curses.h>
+#include <time.h>
+#include <signal.h>
+#include <ctype.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include "mach_dep.h"
+#include "network.h"
+#include "rogue.h"
+
+/* Network machines (for mutual score keeping) */
+struct network Network[] = {
+    { "", "" },
+};
+
+static char *rip[] = {
+"                      ___________",
+"                     /           \\",
+"                    /             \\",
+"                   /    R. I. P.   \\",
+"                  /                 \\",
+"                 /                   \\",
+"                 |                   |",
+"                 |                   |",
+"                 |     killed by     |",
+"                 |                   |",
+"                 |                   |",
+"                 |                   |",
+"                *|      *  *  *      |*",
+"       _________)|//\\\\///\\///\\//\\//\\/|(_________",
+NULL
+};
+
+char    *killname();
+
+/*UNUSED*/
+void
+byebye(sig)
+int sig;
+{
+	NOOP(sig);
+    exit_game(EXIT_ENDWIN);
+}
+
+
+/*
+ * death:
+ *      Do something really fun when he dies
+ */
+
+death(monst)
+register short monst;
+{
+    register char **dp = rip, *killer;
+    register struct tm *lt;
+    time_t date;
+    char buf[LINELEN];
+    struct tm *localtime();
+
+    time(&date);
+    lt = localtime(&date);
+    clear();
+    move(8, 0);
+    while (*dp)
+        printw("%s\n", *dp++);
+    mvaddstr(14, 28-((strlen(whoami)+1)/2), whoami);
+    sprintf(buf, "%lu Points", pstats.s_exp );
+    mvaddstr(15, 28-((strlen(buf)+1)/2), buf);
+    killer = killname(monst);
+    mvaddstr(17, 28-((strlen(killer)+1)/2), killer);
+    mvaddstr(18, 25, (sprintf(prbuf, "%4d", 1900+lt->tm_year), prbuf));
+    move(lines-1, 0);
+    refresh();
+    score(pstats.s_exp, KILLED, monst);
+    exit_game(EXIT_ENDWIN);
+}
+
+char *
+killname(monst)
+register short monst;
+{
+    static char mons_name[LINELEN/2];
+    int i;
+
+    if (monst > NUMMONST) return("a strange monster");
+
+    if (monst >= 0) {
+        switch (monsters[monst].m_name[0]) {
+            case 'a':
+            case 'e':
+            case 'i':
+            case 'o':
+            case 'u':
+                sprintf(mons_name, "an %s", monsters[monst].m_name);
+                break;
+            default:
+                sprintf(mons_name, "a %s", monsters[monst].m_name);
+        }
+        return(mons_name);
+    }
+    for (i = 0; i< DEATHNUM; i++) {
+        if (deaths[i].reason == monst)
+            break;
+    }
+    if (i >= DEATHNUM)
+        return ("strange death");
+    return (deaths[i].name);
+}
+
+/*
+ * score -- figure score and post it.
+ */
+
+/* VARARGS2 */
+score(amount, flags, monst)
+unsigned long amount;
+int flags;
+short monst;
+{
+    struct sc_ent top_ten[NUMSCORE];
+    register struct sc_ent *scp;
+    register int i;
+    register struct sc_ent *sc2;
+    register FILE *outf;
+    register char *killer;
+    register int prflags = 0;
+    short upquest=0, wintype=0, uplevel=0, uptype=0;    /* For network updating */
+    char upsystem[SYSLEN], uplogin[LOGLEN];
+    char *thissys;      /* Holds the name of this system */
+
+#define REASONLEN 3
+    static char *reason[] = {
+        "killed",
+        "quit",
+        "A total winner",
+        "somehow left",
+    };
+    char *packend;
+
+    memset(top_ten,0,sizeof(top_ten));
+
+    signal(SIGINT, byebye);
+    if (level == 0 && max_level == 0) 
+        amount = 0; /*don't count if quit early */
+    if (flags != WINNER && flags != SCOREIT && flags != UPDATE) {
+        if (flags == CHICKEN) {
+            packend = "when you quit";
+        amount = amount / 100;
+        }
+        else
+            packend = "at your untimely demise";
+        mvaddstr(lines - 1, 0, retstr);
+        refresh();
+        getstr(prbuf);
+        showpack(packend);
+    }
+    purse = 0;  /* Steal all the gold */
+
+    /*
+     * Open file and read list
+     */
+
+    if ((outf = fopen(score_file, "rb+")) == NULL)
+    {
+        if ((outf = fopen(score_file, "wb+")) == NULL)
+        {
+            mvprintw(lines - 1, 0, "Unable to open or create score file: %s",score_file);
+            refresh();
+            return;
+        }
+    }
+
+	thissys = md_gethostname();
+
+    /*
+     * If this is a SCOREIT optin (rogue -s), don't call byebye.  The
+     * endwin() calls in byebye() will and this results in a core dump.
+     */
+    if (flags == SCOREIT) signal(SIGINT, SIG_DFL);
+    else signal(SIGINT, byebye);
+
+    if (flags != SCOREIT && flags != UPDATE)
+    {
+        mvaddstr(lines - 1, 0, retstr);
+        refresh();
+        fflush(stdout);
+        getstr(prbuf);
+    }
+
+    /* Check for special options */
+    if (strcmp(prbuf, "names") == 0)
+        prflags = REALLIFE;
+    else if (wizard) {
+        if (strcmp(prbuf, "edit") == 0) prflags = EDITSCORE;
+        else if (strcmp(prbuf, "add") == 0) {
+            prflags = ADDSCORE;
+            waswizard = FALSE;  /* We want the new score recorded */
+        }
+    }
+
+    /* Read the score and convert it to a compatible format */
+
+    fseek(outf, 0, SEEK_SET);
+    rs_read_scorefile(outf, top_ten, NUMSCORE);
+
+    /* Get some values if this is an update */
+    if (flags == UPDATE) {
+        int errcheck, errors = 0;
+
+        upquest = (short) netread(&errcheck, sizeof(short), stdin);
+        if (errcheck) errors++;
+
+        if (fread(whoami, 1, NAMELEN, stdin) != NAMELEN) errors++;
+
+        wintype = (short) netread(&errcheck, sizeof(short), stdin);
+        if (errcheck) errors++;
+
+        uplevel = (short) netread(&errcheck, sizeof(short), stdin);
+        if (errcheck) errors++;
+
+        uptype = (short) netread(&errcheck, sizeof(short), stdin);
+        if (errcheck) errors++;
+
+        if (fread(upsystem, 1, SYSLEN, stdin) != SYSLEN)
+                errors++;
+        if (fread(uplogin, 1, LOGLEN, stdin) != LOGLEN)
+                errors++;
+        
+        if (errors) {
+            fclose(outf);
+            return;
+        }
+    }
+
+    /*
+     * Insert player in list if need be
+     */
+    if (!waswizard) {
+        char *login= NULL;
+
+        if (flags != UPDATE) {
+			login = md_getusername();
+            
+            if ((login == NULL) || (*login == 0))
+                login = "another rogue fiend";
+        }
+
+        if (flags == UPDATE)
+            (void) update(top_ten, amount, upquest, whoami, wintype,
+                   uplevel, monst, uptype, upsystem, uplogin);
+        else {
+            if (prflags == ADDSCORE) {  /* Overlay characteristic by new ones */
+                char buffer[LINELEN];
+
+                clear();
+                mvaddstr(1, 0, "Score: ");
+                mvaddstr(2, 0, "Quest (number): ");
+                mvaddstr(3, 0, "Name: ");
+                mvaddstr(4, 0, "System: ");
+                mvaddstr(5, 0, "Login: ");
+                mvaddstr(6, 0, "Level: ");
+                mvaddstr(7, 0, "Char type: ");
+                mvaddstr(8, 0, "Result: ");
+
+                /* Get the score */
+                move(1, 7);
+                get_str(buffer, stdscr);
+                amount = atol(buffer);
+
+                /* Get the character's quest -- must be a number */
+                move(2, 16);
+                get_str(buffer, stdscr);
+                quest_item = atoi(buffer);
+
+                /* Get the character's name */
+                move(3, 6);
+                get_str(buffer, stdscr);
+                strncpy(whoami, buffer, NAMELEN);
+
+                /* Get the system */
+                move(4, 8);
+                get_str(buffer, stdscr);
+                strncpy(thissys, buffer, SYSLEN);
+
+                /* Get the login */
+                move(5, 7);
+                get_str(buffer, stdscr);
+                strncpy(login, buffer, LOGLEN);
+
+                /* Get the level */
+                move(6, 7);
+                get_str(buffer, stdscr);
+                level = max_level = (short) atoi(buffer);
+
+                /* Get the character type */
+                move(7, 11);
+                get_str(buffer, stdscr);
+                for (i=0; i<NUM_CHARTYPES; i++) {
+                    if (EQSTR(buffer, char_class[i].name, strlen(buffer)))
+                        break;
+                }
+                player.t_ctype = i;
+
+                /* Get the win type */
+                move(8, 8);
+                get_str(buffer, stdscr);
+                switch (buffer[0]) {
+                    case 'W':
+                    case 'w':
+                    case 'T':
+                    case 't':
+                        flags = WINNER;
+                        break;
+
+                    case 'Q':
+                    case 'q':
+                        flags = CHICKEN;
+                        break;
+
+                    case 'k':
+                    case 'K':
+                    default:
+                        flags = KILLED;
+                        break;
+                }
+
+                /* Get the monster if player was killed */
+                if (flags == KILLED) {
+                    mvaddstr(9, 0, "Death type: ");
+                    get_str(buffer, stdscr);
+                    if (buffer[0] == 'M' || buffer[0] == 'm')
+                        do {
+                            monst = makemonster(TRUE, "choose");
+                        } while (monst < 0); /* Force a choice */
+                    else monst = getdeath();
+                }
+            }
+
+            if (update(top_ten, amount, (short) quest_item, whoami, flags,
+                    (flags == WINNER) ? (short) max_level : (short) level,
+                    monst, player.t_ctype, thissys, login)
+                ) {
+                /* Send this update to the other systems in the network */
+                int i, j;
+                char cmd[256];  /* Command for remote execution */
+                FILE *rmf, *popen();    /* For input to remote command */
+
+                for (i=0; Network[i].system[0] != 0; i++)
+                    if (Network[i].system[0] != '!' &&
+                        strcmp(Network[i].system, thissys)) {
+                        sprintf(cmd, NETCOMMAND,
+                                Network[i].system, Network[i].rogue);
+
+                        /* Execute the command */
+                        if ((rmf=popen(cmd, "w")) != NULL) {
+                            unsigned long temp; /* Temporary value */
+
+                            /* Write out the parameters */
+                            (void) netwrite((unsigned long) amount,
+                                          sizeof(unsigned long), rmf);
+
+                            (void) netwrite((unsigned long) monst,
+                                          sizeof(short), rmf);
+
+                            (void) netwrite((unsigned long) quest_item,
+                                        sizeof(short), rmf);
+
+                            (void) fwrite(whoami, 1, strlen(whoami), rmf);
+                            for (j=strlen(whoami); j<NAMELEN; j++)
+                                putc('\0', rmf);
+
+                            (void) netwrite((unsigned long) flags,
+                                          sizeof(short), rmf);
+
+                            temp = (unsigned long)
+                                (flags==WINNER ? max_level : level);
+                            (void) netwrite(temp, sizeof(short), rmf);
+
+                            (void) netwrite((unsigned long) player.t_ctype,
+                                          sizeof(short), rmf);
+
+                            (void) fwrite(thissys, 1,
+                                                strlen(thissys), rmf);
+                            for (j=strlen(thissys); j<SYSLEN; j++)
+                                putc('\0', rmf);
+
+                            (void) fwrite(login, 1, strlen(login), rmf);
+                            for (j=strlen(login); j<LOGLEN; j++)
+                                putc('\0', rmf);
+
+                            /* Close off the command */
+                            (void) pclose(rmf);
+                        }
+                    }
+            }
+        }
+    }
+
+    /*
+     * SCOREIT -- rogue -s option.  Never started curses if this option.
+     * UPDATE -- network scoring update.  Never started curses if this option.
+     * EDITSCORE -- want to delete or change a score.
+     */
+/*   if (flags != SCOREIT && flags != UPDATE && prflags != EDITSCORE)
+        endwin();       */
+
+    if (flags != UPDATE) {
+        if (flags != SCOREIT) {
+            clear();
+            refresh();
+            endwin();
+        }
+        /*
+        * Print the list
+        */
+        printf("\nTop %d Adventurers:\nRank     Score\tName\n",
+                NUMSCORE);
+        for (scp = top_ten; scp < &top_ten[NUMSCORE]; scp++) {
+            char *class;
+
+            if (scp->sc_score != 0) {
+                class = char_class[scp->sc_ctype].name;
+
+                /* Make sure we have an in-bound reason */
+                if (scp->sc_flags > REASONLEN) scp->sc_flags = REASONLEN;
+
+                printf("%3d %10lu\t%s (%s)", scp - top_ten + 1,
+                    scp->sc_score, scp->sc_name, class);
+                    
+                if (prflags == REALLIFE) printf(" [in real life %.*s!%.*s]",
+                                SYSLEN, scp->sc_system, LOGLEN, scp->sc_login);
+
+                printf(":\n\t\t%s on level %d", reason[scp->sc_flags],
+                            scp->sc_level);
+
+                switch (scp->sc_flags) {
+                    case KILLED:
+                        printf(" by");
+                        killer = killname(scp->sc_monster);
+                        printf(" %s", killer);
+                        break;
+
+                    case WINNER:
+                        printf(" with the %s",
+                                rel_magic[scp->sc_quest].mi_name);
+                        break;
+                }
+
+                if (prflags == EDITSCORE)
+                {
+                    fflush(stdout);
+                    getstr(prbuf);
+                    printf("\n");
+                    if (prbuf[0] == 'd') {
+                        for (sc2 = scp; sc2 < &top_ten[NUMSCORE-1]; sc2++)
+                            *sc2 = *(sc2 + 1);
+                        top_ten[NUMSCORE-1].sc_score = 0;
+                        for (i = 0; i < NAMELEN; i++)
+                            top_ten[NUMSCORE-1].sc_name[i] = rnd(255);
+                        top_ten[NUMSCORE-1].sc_flags = RN;
+                            top_ten[NUMSCORE-1].sc_level = RN;
+                            top_ten[NUMSCORE-1].sc_monster = RN;
+                            scp--;
+                    }
+                    else if (prbuf[0] == 'e') {
+                        printf("Death type: ");
+                        getstr(prbuf);
+                        if (prbuf[0] == 'M' || prbuf[0] == 'm')
+                            do {
+                                scp->sc_monster =
+                                    makemonster(TRUE, "choose");
+                            } while (scp->sc_monster < 0); /* Force a choice */
+                        else scp->sc_monster = getdeath();
+                        clear();
+                        refresh();
+                    }
+                }
+                else printf("\n");
+            }
+        }
+/*      if (prflags == EDITSCORE) endwin();*/     /* End editing windowing */
+    }
+    fseek(outf, 0L, SEEK_SET);
+
+    if (flags != SCOREIT)
+        rs_write_scorefile(outf,top_ten,NUMSCORE);
+    fclose(outf);
+}
+
+/*
+ * showpack:
+ *      Display the contents of the hero's pack
+ */
+
+showpack(howso)
+char *howso;
+{
+        reg char *iname;
+        reg int cnt, packnum;
+        reg struct linked_list *item;
+        reg struct object *obj;
+
+        idenpack();
+        cnt = 1;
+        clear();
+        mvprintw(0, 0, "Contents of your pack %s:\n",howso);
+        packnum = 'a';
+        for (item = pack; item != NULL; item = next(item)) {
+                obj = OBJPTR(item);
+                iname = inv_name(obj, FALSE);
+                mvprintw(cnt, 0, "%c) %s\n",packnum++,iname);
+                if (++cnt >= lines - 2 && 
+                    next(item) != NULL) {
+                        cnt = 1;
+                        mvaddstr(lines - 1, 0, morestr);
+                        refresh();
+                        wait_for(' ');
+                        clear();
+                }
+        }
+        mvprintw(cnt + 1,0,"--- %ld  Gold Pieces ---",purse);
+        refresh();
+}
+
+total_winner()
+{
+    register struct linked_list *item;
+    register struct object *obj;
+    register long worth;
+    register char c;
+    register long 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 appointed ");
+    switch (player.t_ctype) {
+        case C_FIGHTER: addstr("Leader of the Fighter's Guild.\n");
+        when C_RANGER:  addstr("King of the Northern Land.\n");
+        when C_PALADIN: addstr("King of the Southern Land.\n");
+        when C_MAGICIAN:addstr("High Wizard of the Sorcerer's Guild.\n");
+        when C_CLERIC:  addstr("Bishop of the Monastery.\n");
+        when C_THIEF:   addstr("Leader of the Thief's Guild.\n");
+        when C_MONK:    addstr("Master of the Temple.\n");
+        when C_ASSASSIN: addstr("Leader of the Assassin's Guild.\n");
+        when C_DRUID:   addstr("High Priest of the Monastery.\n");
+        otherwise:      addstr("Town Drunk in the Tavern.\n");
+    }
+    mvaddstr(lines - 1, 0, spacemsg);
+    refresh();
+    wait_for(' ');
+    clear();
+    mvaddstr(0, 0, "   Worth  Item");
+    oldpurse = purse;
+    for (c = 'a', item = pack; item != NULL; c++, item = next(item))
+    {
+        obj = OBJPTR(item);
+        worth = get_worth(obj);
+        if (obj->o_group == 0)
+            worth *= obj->o_count;
+        whatis(item);
+        mvprintw(c-'a'+1, 0, "%c) %6ld  %s", c, worth, inv_name(obj, FALSE));
+        purse += worth;
+    }
+    mvprintw(c - 'a' + 1, 0,"   %5ld  Gold Pieces          ", oldpurse);
+    refresh();
+    score(pstats.s_exp + (long) purse, WINNER, '\0');
+    exit_game(EXIT_ENDWIN);
+}
+
+
+void
+delete_score(top_ten, idx)
+struct sc_ent top_ten[NUMSCORE];
+int idx;
+{
+    for(;idx < NUMSCORE-1;idx++)
+        top_ten[idx] = top_ten[idx+1];
+
+    top_ten[NUMSCORE-1].sc_score = 0L;
+}
+
+int
+insert_score(top_ten, sc)
+struct sc_ent top_ten[NUMSCORE];
+struct sc_ent *sc;
+{
+    int i,j;
+
+    if (top_ten[NUMSCORE-1].sc_score > 0)
+        return(-1); /* no room */
+  
+    for(i = 0; i < NUMSCORE; i++) {
+        if (sc->sc_score > top_ten[i].sc_score) {
+            for(j = NUMSCORE-1; j > i; j--)
+                top_ten[j] = top_ten[j-1];
+            top_ten[i] = *sc;
+            return(i);
+        }
+    }
+
+    return(-1);
+}
+
+/* PCS = player-class-system (used to determines uniqueness of player) */
+
+int
+is_pcs_match(sc1,sc2)
+struct sc_ent *sc1;
+struct sc_ent *sc2;
+{
+    return( (strcmp(sc1->sc_name,sc2->sc_name) == 0) &&
+         (sc1->sc_ctype == sc2->sc_ctype) &&
+         (strcmp(sc1->sc_system, sc2->sc_system)==0) );
+}
+
+int
+count_pcs_matches(top_ten,sc,lowest)
+struct sc_ent top_ten[NUMSCORE];
+struct sc_ent *sc;
+int *lowest;
+{
+    int i, matches = 0;
+
+    *lowest = -1;
+
+    for(i = 0; i < NUMSCORE; i++) {
+        if (is_pcs_match(sc,&top_ten[i])) {
+            matches++;
+            *lowest = i;
+        }
+    }
+    return(matches);
+}
+
+int
+find_most_pcs_matches(top_ten,sc,num,idx)
+struct sc_ent top_ten[NUMSCORE];
+struct sc_ent *sc;
+int *num, *idx;
+{
+    int i, matches, max_match=0, max_match_idx=-1, lowest;
+    
+    for(i = NUMSCORE-1; i > 0; i--) {
+        matches = count_pcs_matches(top_ten,&top_ten[i],&lowest);
+
+        if (matches > max_match) {
+            max_match     = matches;
+            max_match_idx = lowest;
+        }
+    }        
+
+    matches = count_pcs_matches(top_ten,sc,&lowest) + 1;
+
+    if (matches > max_match) {
+        *num = matches;
+        *idx = lowest;
+    }
+    else {
+        *num = max_match;
+        *idx = max_match_idx;
+    }
+
+    return(0);
+}
+
+
+int
+add_score(top_ten,sc)
+struct sc_ent top_ten[NUMSCORE];
+struct sc_ent *sc;
+{
+    int idx, count;
+      
+    if (insert_score(top_ten,sc) == -1) { 
+    /* Simple insert if space available in table */
+
+        find_most_pcs_matches(top_ten,sc,&count,&idx);
+
+        /* EVERY ENTRY UNIQUE,                  */
+        /* INSERT IF SCORE > LOWEST MATCH SCORE */
+        if (count == 1) {                               
+            if (sc->sc_score > top_ten[idx].sc_score) {
+                delete_score(top_ten,idx);
+                insert_score(top_ten,sc);
+            }
+        }
+        /* CURRENT PCS HAS HIGHEST DUPE COUNT   */
+        /* INSERT IF SCORE > LOWEST MATCH SCORE */
+        else if (is_pcs_match(sc,&top_ten[idx])) {
+            if (sc->sc_score > top_ten[idx].sc_score) {
+                delete_score(top_ten,idx);
+                insert_score(top_ten,sc);
+            }
+        }
+        /* UNRELATED PCS HAS HIGHEST DUPE COUNT         */
+        /* DELETE LOWEST DUPE TO MAKE ROOM AND INSERT   */
+        else {                                          
+            delete_score(top_ten,idx); 
+            insert_score(top_ten,sc);
+        }
+    }    
+}
+
+update(top_ten, amount, quest, whoami, flags, level, monst, ctype, system, login)
+struct sc_ent top_ten[];
+unsigned long amount;
+short quest, flags, level, monst, ctype;
+char *whoami, *system, *login;
+{
+    struct sc_ent sc;
+
+    sc.sc_score = amount;
+    sc.sc_quest = quest;
+    strncpy(sc.sc_name, whoami, NAMELEN);
+    sc.sc_name[NAMELEN-1] = 0;
+    sc.sc_flags = flags;
+    sc.sc_level = level;
+    sc.sc_monster = monst;
+    sc.sc_ctype = ctype;
+    strncpy(sc.sc_system, system, SYSLEN);
+    sc.sc_system[SYSLEN - 1] = 0;
+    strncpy(sc.sc_login, login, LOGLEN);
+    sc.sc_login[LOGLEN-1] = 0;
+
+    add_score(top_ten, &sc);
+    return(1);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xrogue/rogue.c	Tue Apr 21 08:55:20 2015 -0400
@@ -0,0 +1,658 @@
+/*
+    rogue.c  -  Global game variables
+    
+    XRogue: Expeditions into the Dungeons of Doom
+    Copyright (C) 1991 Robert Pietkivitch
+    All rights reserved.
+    
+    Based on "Advanced Rogue"
+    Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka and AT&T
+    All rights reserved.
+
+    Based on "Rogue: Exploring the Dungeons of Doom"
+    Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
+    All rights reserved.
+    
+    See the file LICENSE.TXT for full copyright and licensing information.
+*/
+
+#include <ctype.h>
+#include <curses.h>
+#include "rogue.h"
+
+/*
+ * Now all the global variables
+ */
+
+struct trap traps[MAXTRAPS];
+struct room rooms[MAXROOMS];            /* One for each room -- A level */
+struct room *oldrp;                     /* Roomin(&player.t_oldpos) */
+struct thing player;                    /* The rogue */
+struct object *cur_armor;               /* What a well dresssed rogue wears */
+struct object *cur_ring[NUM_FINGERS];   /* Which rings are being worn */
+struct object  *cur_misc[NUM_MM];       /* which MM's are in use */
+int cur_relic[MAXRELIC];                /* Currently used relics */
+struct linked_list *lvl_obj = NULL; 
+struct linked_list *mlist = NULL;
+struct linked_list *rlist = NULL;       /* list of dead monsters to be reaped */
+struct linked_list *tlist = NULL;       /* list of monsters fallen down traps */
+struct linked_list *monst_dead = NULL;  /* monster killed by monster    */
+struct object *cur_weapon = NULL;
+int char_type = -1;                     /* what type of character is player */
+int foodlev = 1;                        /* how fast he eats food */
+int ntraps;                             /* Number of traps on this level */
+int trader = 0;                         /* no. of purchases */
+int curprice = -1;                      /* current price of item */
+int seed;                               /* Random number seed */
+int max_level;                          /* Deepest player has gone ever */
+int cur_max;                            /* Deepest player has gone currently */
+int prev_max;                           /* A flag indicating worm hole */
+int move_free = 0;                      /* Movement check (io.c & actions.c) */
+int mpos = 0;
+int level = 0;
+long purse = 0;
+int inpack = 0;
+int total = 0;
+int no_food = 0;                        /* how long has he gone with no food */
+int foods_this_level = 0;               /* foods made per level */
+int count = 0;
+int food_left = STOMACHSIZE-MORETIME-1;
+int group = 1;
+int hungry_state = F_OKAY;
+int infest_dam=0;
+int lost_str=0;
+int lastscore = -1;
+int hold_count = 0;
+int trap_tries = 0;
+int chant_time = 0;
+int pray_time = 0;
+int spell_power = 0;
+long turns = 0;                         /* Number of turns player has taken */
+int quest_item = 0;                     /* Item player is looking for */
+int cols = 0;                           /* number of columns in terminal */
+int lines = 0;                          /* number of lines on the terminal */
+int nfloors = -1;                       /* Number of floors in this dungeon */
+char curpurch[LINELEN];                 /* name of item ready to buy */
+char PLAYER = VPLAYER;                  /* what the player looks like */
+char take;                              /* Thing the rogue is taking */
+char prbuf[LINELEN*2];                  /* Buffer for sprintfs */
+char runch;                             /* Direction player is running */
+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 *ws_made[MAXSTICKS];               /* What sticks are made of */
+char whoami[LINELEN];                   /* Name of player */
+char huh[LINELEN];                       /* The last message printed */
+char *s_guess[MAXSCROLLS];              /* Players guess at what scroll is */
+char *p_guess[MAXPOTIONS];              /* Players guess at what potion is */
+char *r_guess[MAXRINGS];                /* Players guess at what ring is */
+char *ws_guess[MAXSTICKS];              /* Players guess at what wand is */
+char *m_guess[MAXMM];                   /* Players guess at what MM is */
+char *ws_type[MAXSTICKS];               /* Is it a wand or a staff */
+char file_name[LINELEN];                /* Save file name */
+char score_file[LINELEN];               /* Score file name */
+char home[LINELEN];                     /* User's home directory */
+WINDOW *cw;                             /* Window that the player sees */
+WINDOW *hw;                             /* Used for the help command */
+WINDOW *mw;                             /* Used to store monsters */
+WINDOW *msgw;                           /* Used to display messages */
+bool pool_teleport = FALSE;             /* just teleported from a pool */
+bool inwhgt = FALSE;                    /* true if from wghtchk() */
+bool after;                             /* True if we want after daemons */
+bool waswizard;                         /* Was a wizard sometime */
+bool s_know[MAXSCROLLS];                /* Does he know what a scroll does */
+bool p_know[MAXPOTIONS];                /* Does he know what a potion does */
+bool r_know[MAXRINGS];                  /* Does he know what a ring does */
+bool ws_know[MAXSTICKS];                /* Does he know what a stick does */
+bool m_know[MAXMM];                     /* Does he know what a MM does */
+
+/* options */
+bool playing = TRUE;        /* Defaults */
+bool running = FALSE; 
+bool wizard = FALSE;
+bool notify = TRUE; 
+bool fight_flush = FALSE;
+bool terse = FALSE; 
+bool auto_pickup = FALSE;
+bool def_attr = FALSE;      /* default attributes */
+bool menu_overlay = TRUE;
+bool door_stop = TRUE;
+bool jump = TRUE; 
+bool slow_invent = FALSE; 
+bool firstmove = FALSE; 
+bool askme = TRUE;
+bool in_shell = FALSE; 
+bool daytime = TRUE;
+bool funfont = FALSE;
+
+LEVTYPE levtype;           /* what type of level am i'm on? */
+
+char *nothing  =  "Nothing seems to happen. ";
+char *spacemsg =  "--Press space to continue--";
+char *morestr  =  " --More--";
+char *retstr   =  "[Press return to continue]";
+
+/* 
+ * This lays out all the class specific details
+ *
+ * Here are the beginning experience levels for all players.
+ * All further experience levels are computed by muliplying by 2
+ * up through MAXDOUBLE. Then exp pts are calculated by adding
+ * in the cap figure. You must change MAXDOUBLE if you change the 
+ * cap figure. 
+ */
+
+struct character_types char_class[NUM_CHARTYPES] = {
+/* name         exppts  cap     hitpts  Base   Maxlvl, Factor, Offset, Range */
+{ "fighter",    90,    1310720,  13,    10,     30,     2,      1,      3 },
+{ "ranger",     110,   2293760,  10,    10,     22,     2,      1,      2 },
+{ "paladin",    110,   1966080,  10,    10,     23,     2,      1,      2 },
+{ "magician",   105,   2129920,   9,    10,     24,     2,      1,      2 },
+{ "cleric",     105,   1802240,   9,    10,     24,     2,      1,      2 },
+{ "thief",      95,    1228800,  11,    10,     28,     2,      1,      3 },
+{ "assassin",   95,    1392640,  11,    10,     26,     2,      1,      3 },
+{ "druid",      105,   1638400,   9,    10,     24,     2,      1,      2 },
+{ "monk",       100,   1556480,  10,    10,     25,     2,      1,      2 },
+{ "monster",    0,     0,         8,    10,     20,     1,      0,      2 },
+};
+
+/*
+ * This array lists the names of the character's abilities.  It must be ordered
+ * according to the ability definitions in rogue.h.
+ */
+
+struct words abilities[NUMABILITIES] = {
+  "Intelligence", "Strength", "Wisdom", "Dexterity", "Constitution", "Charisma"
+};
+
+/*
+ * NOTE: the ordering of the points in this array is critical. They MUST
+ *       be listed in the following sequence:
+ *
+ *              7   4   6
+ *              1   0   2
+ *              5   3   8
+ */
+
+coord grid[9] = {{0,0},
+                 { 0,-1}, { 0, 1}, {-1, 0}, { 1, 0},
+                 {-1,-1}, { 1, 1}, { 1,-1}, {-1, 1}
+                };
+
+struct death_type deaths[DEATHNUM] = {
+    { D_ARROW,          "an arrow"},
+    { D_DART,           "a dart"},
+    { D_BOLT,           "a bolt"},
+    { D_POISON,         "poison"},
+    { D_POTION,         "a cursed potion"},
+    { D_PETRIFY,        "petrification"},
+    { D_SUFFOCATION,    "suffocation"},
+    { D_INFESTATION,    "a parasite"},
+    { D_DROWN,          "drowning"},
+    { D_ROT,            "body rot"},
+    { D_CONSTITUTION,   "poor health"},
+    { D_STRENGTH,       "being too weak"},
+    { D_SIGNAL,         "a bug"},
+    { D_CHOKE,          "dust of choking"},
+    { D_STRANGLE,       "strangulation"},
+    { D_FALL,           "a fall"},
+    { D_RELIC,          "an artifact's wrath"},
+    { D_STARVATION,     "starvation"},
+    { D_FOOD_CHOKE,     "choking on food"},
+    { D_SCROLL,         "reading a scroll"},
+    { D_FRIGHT,         "being too frightened"},
+    { D_CRYSTAL,        "being absorbed"},
+    { D_CARD,           "the face of death"},
+};
+
+/*
+ * weapons and their attributes
+ */
+
+struct init_weps weaps[MAXWEAPONS] = {
+    { "mace",           "2d10","2d10", NONE,     ISMETAL, 6, 150, 15 },
+    { "long sword",     "3d4",  "2d8", NONE,     ISMETAL, 5, 200, 25 },
+    { "short bow",      "1d1",  "1d1", NONE,     0, 8, 50, 4 },
+    { "arrow",          "2d4",  "1d6", BOW,      ISMANY|ISMISL, 1, 5, 4 },
+    { "dagger",         "2d8",  "1d6", NONE,     ISMETAL|ISMISL|ISMANY, 2,10,7},
+    { "rock",           "2d4",  "1d6", SLING,    ISMANY|ISMISL, 1, 20, 3 },
+    { "two-handed sword","3d10","3d8", NONE,     ISMETAL, 4, 250, 40 },
+    { "sling",          "1d1",  "1d1", NONE,     0, 8, 25, 3 },
+    { "dart",           "2d4",  "2d6", NONE,     ISMANY|ISMISL, 2, 15, 7 },
+    { "crossbow",       "1d1",  "1d1", NONE,     0, 8, 75, 5 },
+    { "crossbow bolt",  "2d4",  "2d4", CROSSBOW, ISMANY|ISMISL, 1, 10, 5 },
+    { "spear",          "2d6", "3d10", NONE,     ISMISL,  7, 100, 15 },
+    { "trident",        "3d6",  "3d4", NONE,     ISMETAL, 4, 200, 30 },
+    { "spetum",         "2d6",  "2d8", NONE,     ISMETAL, 6, 150, 20 },
+    { "bardiche",       "3d4", "2d10", NONE,     ISMETAL, 5, 150, 25 },
+    { "pike",           "2d8",  "2d8", NONE,     ISMETAL, 7, 100, 15 },
+    { "bastard sword",  "3d8",  "3d6", NONE,     ISMETAL, 4, 175, 30 },
+    { "halberd",        "2d8",  "2d4", NONE,     ISMETAL, 6, 100, 10 },
+    { "battle axe",     "2d8",  "3d8", NONE,     ISMETAL, 5, 150, 15 },
+} ;
+ 
+struct init_armor armors[MAXARMORS] = {
+        { "leather armor",          10, 8, 200, 100 },
+        { "ring mail",              20, 7, 250, 200 },
+        { "studded leather armor",  30, 5, 320, 250 },
+        { "scale mail",             40, 7, 280, 250 },
+        { "padded armor",           50, 6, 350, 300 },
+        { "chain mail",             60, 6, 350, 600 },
+        { "splint mail",            70, 5, 370, 400 },
+        { "banded mail",            80, 5, 370, 350 },
+        { "plate mail",             90, 4, 400, 400 },
+        { "plate armor",           100, 3, 500, 450 },
+};
+
+struct magic_item things[NUMTHINGS] = {
+    { "potion",                 220,   10 },    /* potion               */
+    { "scroll",                 220,   30 },    /* scroll               */
+    { "food",                   190,   20 },    /* food                 */
+    { "weapon",                  90,    0 },    /* weapon               */
+    { "armor",                   90,    0 },    /* armor                */
+    { "ring",                    70,    5 },    /* ring                 */
+    { "stick",                   70,    0 },    /* stick                */
+    { "miscellaneous magic",     50,   50 },    /* miscellaneous magic  */
+    { "artifact",                 0,   10 },    /* artifact             */
+};
+
+struct magic_item s_magic[MAXSCROLLS] = {
+    { "monster confusion",       40, 125,  0,  0 },
+    { "magic mapping",           60, 150,  0,  5 },
+    { "light",                   60, 100, 15, 15 },
+    { "hold monster",            30, 200, 20, 20 },
+    { "sleep",                   20, 150, 25,  0 },
+    { "enchantment",            130, 200, 15, 15 },
+    { "identify",               170, 100,  0, 20 },
+    { "scare monster",           40, 250, 20, 30 },
+    { "gold detection",          30, 110,  0,  0 },
+    { "teleportation",           60, 165, 20, 20 },
+    { "create monster",          20,  75,  0,  0 },
+    { "remove curse",            80, 120, 15, 15 },
+    { "petrification",           30, 185,  0,  0 },
+    { "genocide",                10, 300,  0,  0 },
+    { "cure disease",            80, 160,  0,  0 },
+    { "acquirement",             10, 700,  0,  5 },
+    { "protection",              30, 190, 10,  0 },
+    { "trap finding",            50, 180,  0,  0 },
+    { "runes",                   20,  50,  0,  0 },
+    { "charm monster",           30, 275,  0, 20 },
+};
+
+struct magic_item p_magic[MAXPOTIONS] = {
+    { "clear thought",           50, 180, 10,  5 },
+    { "gain ability",           160, 210, 10, 10 },
+    { "see invisible",           40, 150, 20, 20 },
+    { "healing",                140, 130, 15, 15 },
+    { "monster detection",       40, 120,  0,  0 },
+    { "magic detection",         70, 105,  0,  0 },
+    { "raise level",             10, 450, 10,  5 },
+    { "haste self",              50, 180, 20,  5 },
+    { "restore abilities",      130, 140,  0, 15 },
+    { "phasing",                 60, 210, 10, 10 },
+    { "invisibility",            20, 230,  0, 10 },
+    { "flying",                  50, 130,  0, 15 },
+    { "food detection",          20, 150,  0,  0 },
+    { "skill",                   10, 200, 20,  5 },
+    { "fire resistance",         40, 250, 10,  5 },
+    { "cold resistance",         40, 250, 10,  5 },
+    { "lightning protection",    40, 250, 20,  5 },
+    { "poison",                  30, 205, 25,  0 },
+};
+
+struct magic_item r_magic[MAXRINGS] = {
+    { "protection",              60, 200,  25, 25 },
+    { "add strength",            50, 200,  25, 25 },
+    { "sustain ability",         50, 500,   0,  0 },
+    { "searching",               40, 400,   0,  0 },
+    { "extra sight",             60, 350,   0,  0 },
+    { "alertness",               40, 380,   0,  0 },
+    { "aggravate monster",       30, 100, 100,  0 },
+    { "dexterity",               50, 220,  25, 25 },
+    { "increase damage",         60, 220,  25, 25 },
+    { "regeneration",            40, 600,   0,  0 },
+    { "slow digestion",          50, 240,  20, 20 },
+    { "teleportation",           20, 100,  90,  0 },
+    { "stealth",                 20, 300,   0,  0 },
+    { "add intelligence",        50, 240,  25, 25 },
+    { "increase wisdom",         40, 220,  25, 25 },
+    { "sustain health",          80, 500,   0,  0 },
+    { "carrying",                10, 100,  90,  0 },
+    { "illumination",            30, 520,   0,  0 },
+    { "delusion",                10, 100, 100,  0 },
+    { "fear",                    20, 100,  75,  0 },
+    { "heroism",                 50, 390,   0,  0 },
+    { "fire resistance",         40, 400,   0,  0 },
+    { "warmth",                  40, 400,   0,  0 },
+    { "vampiric regeneration",   10,1000,   0,  0 },
+    { "free action",             40, 370,   0,  0 },
+    { "teleport control",        10, 700,   0,  0 },
+};
+
+struct magic_item ws_magic[MAXSTICKS] = {
+    { "light",                   80, 120, 15, 15 },
+    { "striking",                50, 115,  0,  0 },
+    { "lightning",               40, 200,  0,  0 },
+    { "fire",                    30, 200,  0,  0 },
+    { "cold",                    30, 200,  0,  0 },
+    { "polymorph",               80, 150,  0,  0 },
+    { "magic missile",           90, 170,  0,  0 },
+    { "slow",                    70, 220, 20, 10 },
+    { "drain life",              50, 210, 20,  0 },
+    { "charging",                70, 400,  0,  0 },
+    { "teleport",                90, 140, 20, 10 },
+    { "cancellation",            50, 130,  0,  0 },
+    { "confusion",               30, 100, 20,  0 },
+    { "disintegration",          20, 300, 25,  0 },
+    { "petrification",           30, 240,  0,  0 },
+    { "paralyzation",            30, 180, 10,  0 },
+    { "degeneration",            30, 250, 20,  0 },
+    { "curing",                  50, 250, 20,  5 },
+    { "wonder",                  40, 110, 20, 20 },
+    { "fear",                    40, 180,  0,  0 },
+};
+
+/*
+ * WARNING: unique miscellaneous magic items must be put at the end
+ *          of this list. They MUST be the last items. The function
+ *          create_obj() in wizard.c depends on it.
+ */
+
+struct magic_item m_magic[MAXMM] = {
+    { "alchemy jug",               40,  240,   0,  0 },
+    { "beaker of potions",         60,  300,   0,  0 },
+    { "book of spells",            60,  300,   0,  0 },
+    { "boots of elvenkind",        50,  500,   0,  0 },
+    { "bracers of defense",        80,  400,  20, 10 },
+    { "chime of opening",          30,  250,   0,  0 },
+    { "chime of hunger",           20,  100, 100,  0 },
+    { "cloak of displacement",     60,  500,   0,  0 },
+    { "cloak of protection",       80,  400,  20, 10 },
+    { "drums of panic",            60,  350,   0,  0 },
+    { "dust of disappearance",     30,  300,   0,  0 },
+    { "dust of choking",           30,  100, 100,  0 },
+    { "gauntlets of dexterity",    40,  600,  25,  0 },
+    { "gauntlets of ogre power",   40,  600,  25,  0 },
+    { "jewel of attacks",          50,  150, 100,  0 },
+    { "keoghtoms ointment",        60,  350,   0,  0 },
+    { "robe of powerlessness",     20,  100, 100,  0 },
+    { "gauntlets of fumbling",     30,  100, 100,  0 },
+    { "necklace of adaptation",    50,  500,   0,  0 },
+    { "necklace of strangulation", 30,  110, 100,  0 },
+    { "boots of dancing",          40,  120, 100,  0 },
+    { "book of skills",            30,  650,   0,  0 },
+    { "medicine crystal",          10,  800,  25,  5 },
+};
+
+struct magic_item rel_magic[MAXRELIC] = {
+    { "Daggers of Musty Doit",     0, 50000,  0, 0},
+    { "Cloak of Emori",            0, 50000,  0, 0},
+    { "Ankh of Heil",              0, 50000,  0, 0},
+    { "Staff of Ming",             0, 50000,  0, 0},
+    { "Wand of Orcus",             0, 50000,  0, 0},
+    { "Rod of Asmodeus",           0, 50000,  0, 0},
+    { "Amulet of Yendor",          0, 50000,  0, 0},
+    { "Mandolin of Brian",         0, 50000,  0, 0},
+    { "Horn of Geryon",            0, 50000,  0, 0},
+    { "Morning Star of Hruggek",   0, 50000,  0, 0},
+    { "Flail of Yeenoghu",         0, 50000,  0, 0},
+    { "Eye of Vecna",              0, 50000,  0, 0},
+    { "Axe of Aklad",              0, 50000,  0, 0},
+    { "Quill of Nagrom",           0, 50000,  0, 0},
+    { "Amulet of Stonebones",      0, 50000,  0, 0},
+    { "Ring of Surtur",            0, 50000,  0, 0},
+    { "Card of Alteran",           0, 50000,  0, 0},
+};
+
+/*
+ * food and fruits that you get
+ */
+struct magic_item foods[MAXFOODS] = {
+
+    { "food ration",    690, 50, 750,  0},
+    { "apple",           10, 20, 300,  0},
+    { "banana",          30, 20, 300,  0},
+    { "blueberry",       30, 20, 300,  0},
+    { "candleberry",     10, 20, 300,  0},
+    { "caprifig",        20, 20, 300,  0},
+    { "dewberry",        10, 20, 300,  0},
+    { "elderberry",      30, 20, 300,  0},
+    { "gooseberry",      20, 20, 300,  0},
+    { "guanabana",       30, 20, 300,  0},
+    { "hagberry",        10, 20, 300,  0},
+    { "jaboticaba",      10, 20, 300,  0},
+    { "peach",           10, 20, 300,  0},
+    { "pitanga",         10, 20, 300,  0},
+    { "prickly pear",    10, 20, 300,  0},
+    { "rambutan",        10, 20, 300,  0},
+    { "sapodilla",       10, 20, 300,  0},
+    { "soursop",         10, 20, 300,  0},
+    { "strawberry",      10, 20, 300,  0},
+    { "sweetsop",        10, 20, 300,  0},
+    { "whortleberry",    10, 20, 300,  0},
+    { "slime-mold",      10, 10, 100,  0},
+};
+
+/*
+ * these are the spells that a magician can cast
+ */
+
+struct spells magic_spells[MAXSPELLS] = {
+        { P_TFIND,         3,     TYP_POTION,   0         },
+        { S_IDENT,         5,     TYP_SCROLL,   0         },
+        { S_LIGHT,         7,     TYP_SCROLL,   ISBLESSED },
+        { S_REMOVE,       10,     TYP_SCROLL,   0         },
+        { S_FINDTRAPS,    15,     TYP_SCROLL,   0         },
+        { P_FLY,          20,     TYP_POTION,   0         },
+        { S_TELEP,        25,     TYP_SCROLL,   0         },
+        { S_SLEEP,        30,     TYP_SCROLL,   0         },
+        { P_SEEINVIS,     35,     TYP_POTION,   ISBLESSED },
+        { P_CLEAR,        40,     TYP_POTION,   0         },
+        { WS_COLD,        45,     TYP_STICK,    0         },
+        { P_PHASE,        50,     TYP_POTION,   0         },
+        { WS_FIRE,        55,     TYP_STICK,    0         },
+        { P_HASTE,        60,     TYP_POTION,   ISBLESSED },
+        { WS_ELECT,       65,     TYP_STICK,    0         },
+        { S_HOLD,         70,     TYP_SCROLL,   ISBLESSED },
+};
+
+/*
+ * these are the spells that a cleric can cast
+ */
+
+struct spells cleric_spells[MAXPRAYERS] = {
+        { P_MFIND,         3,     TYP_POTION,   0         },
+        { P_TFIND,         5,     TYP_POTION,   0         },
+        { S_LIGHT,         7,     TYP_SCROLL,   ISBLESSED },
+        { S_REMOVE,       10,     TYP_SCROLL,   0         },
+        { P_FFIND,        15,     TYP_POTION,   0         },
+        { P_FLY,          20,     TYP_POTION,   0         },
+        { P_HEALING,      25,     TYP_POTION,   0         },
+        { S_CURING,       30,     TYP_SCROLL,   0         },
+        { P_RESTORE,      35,     TYP_POTION,   0         },
+        { S_MAP,          40,     TYP_SCROLL,   0         },
+        { P_SEEINVIS,     45,     TYP_POTION,   ISBLESSED },
+        { P_CLEAR,        50,     TYP_POTION,   0         },
+        { P_PHASE,        55,     TYP_POTION,   0         },
+        { WS_CURING,      60,     TYP_STICK,    ISBLESSED },
+        { WS_PARALYZE,    65,     TYP_STICK,    0         },
+        { S_ALLENCH,      70,     TYP_SCROLL,   0         },
+};
+
+/*
+ * these are the spells that a druid can chant
+ */
+
+struct spells druid_spells[MAXCHANTS] = {
+        { P_MFIND,         3,     TYP_POTION,   0         },
+        { P_TFIND,         5,     TYP_POTION,   0         },
+        { S_LIGHT,         7,     TYP_SCROLL,   ISBLESSED },
+        { S_REMOVE,       10,     TYP_SCROLL,   0         },
+        { S_FINDTRAPS,    15,     TYP_SCROLL,   0         },
+        { S_CONFUSE,      20,     TYP_SCROLL,   0         },
+        { P_FFIND,        25,     TYP_POTION,   0         },
+        { P_HEALING,      30,     TYP_POTION,   0         },
+        { S_MAP,          35,     TYP_SCROLL,   0         },
+        { P_CLEAR,        40,     TYP_POTION,   0         },
+        { P_COLD,         45,     TYP_POTION,   0         },
+        { P_FIRE,         50,     TYP_POTION,   0         },
+        { P_PHASE,        55,     TYP_POTION,   0         },
+        { P_LIGHTNING,    60,     TYP_POTION,   0         },
+        { S_CHARM,        65,     TYP_SCROLL,   ISBLESSED },
+        { S_HOLD,         70,     TYP_SCROLL,   ISBLESSED },
+};
+
+/*
+ * these are the scrolls that a quill can write
+ */
+
+struct spells quill_scrolls[MAXQUILL] = {
+        { S_GFIND,       5,   },
+        { S_IDENT,       10,  },
+        { S_LIGHT,       10,  },
+        { S_REMOVE,      15,  },
+        { S_MAP,         20,  },
+        { S_CONFUSE,     25,  },
+        { S_SLEEP,       30,  },
+        { S_CURING,      40,  },
+        { S_TELEP,       50,  },
+        { S_SCARE,       60,  },
+        { S_HOLD,        70,  },
+        { S_PETRIFY,     80,  },
+        { S_PROTECT,     90,  },
+        { S_ALLENCH,     100, },
+};
+
+/*
+ * Experience-level names of each character  (see NUM_CNAMES in rogue.h)
+ */
+
+const char *cnames[NUM_CHARTYPES-1][NUM_CNAMES] = {
+{       "Veteran",                      "Fighter",              /* Fighter */
+        "Ruffian",                      "Tussler",
+        "Swordsman",                    "Hero",
+        "Bravo",                        "Picador",
+        "Stalwart",                     "Bashar",
+        "Swashbuckler",                 "Myrmidon",
+        "Fusileer",                     "Pugilist",
+        "Champion",                     "Superhero",
+        "Warrior",                      "Lord",
+        "Lord I",                       "Lord II",
+        "Lord III",                     "Lord IV",
+        "Lord V",                       "Lord VI",
+        "Lord VII",                     "Warrior Lord"
+},
+{       "Runner",                       "Strider",              /* Ranger */
+        "Warden",                       "Steward",
+        "Scout",                        "Courser",
+        "Tracker",                      "Guide",
+        "Protector",                    "Bartizan",
+        "Gendarme",                     "Sentinel",
+        "Vigilant",                     "Pathfinder",
+        "Guardian",                     "Overseer",
+        "Castellan",                    "Ranger",
+        "Lord Ranger I",                "Lord Ranger II",
+        "Lord Ranger III",              "Lord Ranger IV",
+        "Lord Ranger V",                "Lord Ranger VI",
+        "Lord Ranger VII",              "Master Ranger"
+},
+{       "Gallant",                      "Keeper",               /* Paladin */
+        "Bravado",                      "Brazen",
+        "Protector",                    "Defender",
+        "Warder",                       "Guardian",
+        "Champion",                     "Bulwark",
+        "Venturist",                    "Inspirator",
+        "Chevalier",                    "Justiciar",
+        "Undaunteer",                   "Plautus",
+        "Knight",                       "Paladin",
+        "Paladin I",                    "Paladin II",
+        "Paladin III",                  "Paladin IV",
+        "Paladin V",                    "Paladin VI",
+        "Paladin VII",                  "Lord Paladin"
+},
+{       "Prestidigitator",              "Evoker",               /* Magic User */
+        "Summoner",                     "Invoker",
+        "Conjurer",                     "Theurgist",
+        "Illusionist",                  "Diviner",
+        "Thaumaturgist",                "Magician",
+        "Thelemist",                    "Magus",
+        "Enchanter",                    "Warlock",
+        "Witch",                        "Shaman",
+        "Sorcerer",                     "Wizard",
+        "Wizard I",                     "Wizard II",
+        "Wizard III",                   "Wizard IV",
+        "Wizard V",                     "Wizard VI",
+        "Wizard VII",                   "Lord Magus"
+},
+{       "Acolyte",                      "Adept",                /* Cleric */
+        "Charmer",                      "Friar",
+        "Priest",                       "Curate",
+        "Vicar",                        "Deacon",
+        "Sabiast",                      "Cabalist",
+        "Prefect",                      "Canon",
+        "Minister",                     "Cardinal",
+        "Bishop",                       "Patriarch",
+        "Exorcist",                     "Archdeacon",
+        "High Priest I",                "High Priest II",
+        "High Priest III",              "High Priest IV",
+        "High Priest V",                "High Priest VI",
+        "High Priest VII",              "Reverend Lord"
+},
+{       "Rogue",                        "Footpad",              /* Thief */
+        "Cutpurse",                     "Robber",
+        "Vagrant",                      "Truant",
+        "Burglar",                      "Filcher",
+        "Sharper",                      "Magsman",
+        "Racketeer",                    "Prowler",
+        "Crook",                        "Bounder",
+        "Quisling",                     "Malfeasor",
+        "Swindler",                     "Thief",
+        "Master Thief I",               "Master Thief II",
+        "Master Thief III",             "Master Thief IV",
+        "Master Thief V",               "Master Thief VI",
+        "Master Thief VII",             "Master Rogue"
+},
+{       "Bravo",                        "Rutterkin",            /* Assassin */
+        "Waghalter",                    "Murderer",
+        "Butcher",                      "Desperado",
+        "Thug",                         "Killer",
+        "Cutthroat",                    "Executioner",
+        "Eradicator",                   "Obliterator",
+        "Mechanic",                     "Wiseguy",
+        "Nihilist",                     "Berserker",
+        "Assassin",                     "Expert Assassin",
+        "Prime Assassin I",             "Prime Assassin II",
+        "Prime Assassin III",           "Prime Assassin IV",
+        "Prime Assassin V",             "Prime Assassin VI",
+        "Prime Assassin VII",           "Master Assassin"
+},
+{       "Aspirant",                     "Ovate",                /* Druid */
+        "Practitioner",                 "Devoutist",
+        "Initiate 1st Circle",          "Initiate 2nd Circle",
+        "Initiate 3rd Circle",          "Initiate 4th Circle",
+        "Initiate 5th Circle",          "Initiate 6th Circle",
+        "Initiate 7th Circle",          "Initiate 8th Circle",
+        "Initiate 9th Circle",          "Illuminati",
+        "Lesser Druid",                 "Arch Druid",
+        "Druid",                        "Master Druid",
+        "Master Druid I",               "Master Druid II",
+        "Master Druid III",             "Master Druid IV",
+        "Master Druid V",               "Master Druid VI",
+        "Master Druid VII",             "Lord Druid"
+},
+{       "Novice",                       "Initiate",             /* Monk */
+        "Brother",                      "Disciple",
+        "Canon",                        "Elder",
+        "Precept",                      "Lama",
+        "Immaculate",                   "Wizard",
+        "Shaman",                       "Master",
+        "Superior Master",              "Master of Dragons",
+        "Master of North Wind",         "Master of West Wind",
+        "Master of South Wind",         "Master of East Wind",
+        "Grand Master I",               "Grand Master II",
+        "Grand Master III",             "Grand Master IV",
+        "Grand Master V",               "Grand Master VI",
+        "Grand Master VII",             "Lord Monk"
+}
+};
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xrogue/rogue.h	Tue Apr 21 08:55:20 2015 -0400
@@ -0,0 +1,1405 @@
+/*
+    rogue.h - Rogue definitions and variable declarations
+    
+    XRogue: Expeditions into the Dungeons of Doom
+    Copyright (C) 1991 Robert Pietkivitch
+    All rights reserved.
+    
+    Based on "Advanced Rogue"
+    Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka and AT&T
+    All rights reserved.
+
+    Based on "Rogue: Exploring the Dungeons of Doom"
+    Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
+    All rights reserved.
+    
+    See the file LICENSE.TXT for full copyright and licensing information.
+*/ 
+
+/*
+ * some compiler don't handle void pointers well so
+ */
+#include <assert.h>
+#define reg  register
+#define VOID long
+#undef lines
+#define ENCREAD encread
+#define ENCWRITE encwrite
+#undef SCROLL   /* UNIX/370 defines SCROLL for some bizarre reason */
+#define exfork fork     /* Standard fork with no paging available */
+
+/*
+ * Maximum number of different things
+ */
+
+#define MINCOLS         70
+#define MINLINES        22
+#define MAXROOMS        9
+#define MAXTHINGS       9
+#define MAXOBJ          9
+#define MAXSTATS        74      /* max total of all stats at startup */
+#define MAXPACK         27      /* max number of items in pack */
+#define MAXDOUBLE       14      /* max number of times exppts is doubled */
+#define MAXCONTENTS     20      /* max number of things beaker/book can hold */
+#define MAXENCHANT      30      /* max number of enchantments on an item */
+#define MAXTREAS        25      /* number monsters/treasure in treasure room */
+#define MAXTRAPS        20      /* max number of traps that may be on level */
+#define MAXTRPTRY       15      /* attempts/level allowed for setting traps */
+#define MAXDOORS        4       /* maximum doors to a room */
+#define MAXCHANTS       16      /* maximum number of chants for a druid */
+#define MAXPRAYERS      16      /* maximum number of prayers for cleric */
+#define MAXSPELLS       16      /* maximum number of spells for magician */
+#define MAXQUILL        14      /* scrolls the Quill of Nagrom can write */
+#define QUILLCHARGES    300     /* max num of charges in the Quill of Nagrom */
+#define NUM_CNAMES      26      /* number of names per character level */
+#define NUMMONST        211     /* current number of monsters */
+#define NUMUNIQUE       60      /* number of UNIQUEs (minus jacaranda) */
+#define NUMDINOS        30      /* number of dinosaurs (for OUTSIDE level) */
+#define NLEVMONS        3       /* number of new monsters per level */
+#define NUMSCORE        20      /* number of entries in score file */
+#define HARDER          40      /* at this level start making things harder */
+#define LINELEN         256     /* characters in a buffer */
+#define JUG_EMPTY       -1      /* signifys that the alchemy jug is empty */
+#define MAXPURCH        (pstats.s_charisma/3) /* num of purchases at t.post */
+#define MAXATT          50      /* charactor's attribute maximum number */
+
+/* Movement penalties */
+#define BACKPENALTY 3
+#define SHOTPENALTY 2           /* In line of sight of missile */
+#define DOORPENALTY 1           /* Moving out of current room */
+
+/*
+ * these defines are used in calls to get_item() to signify what
+ * it is we want
+ */
+
+#define ALL             -1
+#define WEARABLE        -2
+#define CALLABLE        -3
+#define WIELDABLE       -4
+#define USEABLE         -5
+#define IDENTABLE       -6
+#define REMOVABLE       -7
+#define PROTECTABLE     -8
+#define ZAPPABLE        -9
+#define READABLE        -10
+#define QUAFFABLE       -11
+
+/*
+ * stuff to do with encumberance
+ */
+
+#define NORMENCB        1400    /* normal encumberance */
+#define F_SATIATED       0      /* player's stomach is very full */
+#define F_OKAY           1      /* have plenty of food in stomach */
+#define F_HUNGRY         2      /* player is hungry */
+#define F_WEAK           3      /* weak from lack of food */
+#define F_FAINT          4      /* fainting from lack of food */
+
+/*
+ * actions a player/monster will take
+ */
+
+#define A_MOVE          0200    /* normal movement */
+#define A_FREEZE        0201    /* frozen in place */
+#define A_ATTACK        0202    /* trying to hit */
+#define A_SELL          0203    /* trying to sell goods */
+#define A_NIL           0204    /* not doing anything */
+#define A_BREATHE       0205    /* breathing */
+#define A_MISSILE       0206    /* Firing magic missiles */
+#define A_SONIC         0207    /* Sounding a sonic blast */
+#define A_SUMMON        0210    /* Summoning help */
+#define A_USERELIC      0211    /* Monster uses a relic */
+#define A_SLOW          0212    /* monster slows the player */
+#define A_ZAP           0213    /* monster shoots a wand */
+#define A_PICKUP        0214    /* player is picking something up */
+#define A_USEWAND       0215    /* monster is shooting a wand */
+#define A_THROW         't'
+#define C_CAST          'C'
+#define C_COUNT         '*'
+#define C_DIP           'D'
+#define C_DROP          'd'
+#define C_EAT           'e'
+#define C_PRAY          'p'
+#define C_CHANT         'c'
+#define C_QUAFF         'q'
+#define C_READ          'r'
+#define C_SEARCH        's'
+#define C_SETTRAP       '^'
+#define C_TAKEOFF       'T'
+#define C_USE           CTRL('U')
+#define C_WEAR          'W'
+#define C_WIELD         'w'
+#define C_ZAP           'z'
+
+/* Possible ways for the hero to move */
+
+#define H_TELEPORT 0
+
+/*
+ * return values for get functions
+ */
+
+#define NORM    0       /* normal exit */
+#define QUIT    1       /* quit option setting */
+#define MINUS   2       /* back up one option */
+
+/* 
+ * The character types
+ */
+
+#define C_FIGHTER       0
+#define C_RANGER        1
+#define C_PALADIN       2
+#define C_MAGICIAN      3
+#define C_CLERIC        4
+#define C_THIEF         5
+#define C_ASSASSIN      6
+#define C_DRUID         7
+#define C_MONK          8
+#define C_MONSTER       9
+#define NUM_CHARTYPES   10
+
+/*
+ * define the ability types
+ */
+
+#define A_INTELLIGENCE  0
+#define A_STRENGTH      1
+#define A_WISDOM        2
+#define A_DEXTERITY     3
+#define A_CONSTITUTION  4
+#define A_CHARISMA      5
+#define NUMABILITIES    6
+
+/*
+ * values for games end
+ */
+
+#define UPDATE  -2
+#define SCOREIT -1
+#define KILLED   0
+#define CHICKEN  1
+#define WINNER   2
+
+/*
+ * definitions for function step_ok:
+ *      MONSTOK indicates it is OK to step on a monster -- it
+ *      is only OK when stepping diagonally AROUND a monster;
+ *      it is also OK if the stepper is a friendly monster and
+ *      is in a fighting mood.
+ */
+
+#define MONSTOK 1
+#define NOMONST 2
+#define FIGHTOK 3
+
+/*
+ * used for ring stuff
+ */
+
+#define LEFT_1          0
+#define LEFT_2          1
+#define LEFT_3          2
+#define LEFT_4          3
+#define RIGHT_1         4
+#define RIGHT_2         5
+#define RIGHT_3         6
+#define RIGHT_4         7
+#define NUM_FINGERS     8
+
+/*
+ * used for micellaneous magic (MM) stuff
+ */
+
+#define WEAR_BOOTS      0
+#define WEAR_BRACERS    1
+#define WEAR_CLOAK      2
+#define WEAR_GAUNTLET   3
+#define WEAR_JEWEL      4
+#define WEAR_NECKLACE   5
+#define NUM_MM          6
+
+/*
+    How to exit flags:
+*/
+
+#define EXIT_CLS        1    /* Clear screen first */
+#define EXIT_ENDWIN     2    /* Shutdown Curses    */
+
+
+/*
+ * 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 DOORPTR(what)   (coord *)((*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 newfont(window) if (funfont) wattron(window, A_ALTCHARSET);
+#define nofont(window) if (funfont) wattroff(window, A_ALTCHARSET);
+#define hero player.t_pos
+#define pstats player.t_stats
+#define max_stats player.maxstats
+#define pack player.t_pack
+#define attach(a, b) _attach(&a, b)
+#define detach(a, b) _detach(&a, b)
+#define o_free_list(a) _o_free_list(&a)
+#define r_free_list(a) _r_free_list(&a)
+#define t_free_list(a) _t_free_list(&a)
+#undef min
+#undef max
+#define max(a, b) ((a) > (b) ? (a) : (b))
+#define min(a, b) ((a) < (b) ? (a) : (b))
+#define on(thing, flag) \
+    (((thing).t_flags[(flag >> FLAGSHIFT) & FLAGINDEX] & flag) != 0)
+#define off(thing, flag) \
+    (((thing).t_flags[(flag >> FLAGSHIFT) & FLAGINDEX] & flag) == 0)
+#define turn_on(thing, flag) \
+    ((thing).t_flags[(flag >> FLAGSHIFT) & FLAGINDEX] |= (flag & ~FLAGMASK))
+#define turn_off(thing, flag) \
+    ((thing).t_flags[(flag >> FLAGSHIFT) & FLAGINDEX] &= ~flag)
+
+/* define the control character */
+
+#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 EQUAL(a, b)     (strcmp(a, b) == 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_1, r)  || ISRING(LEFT_2, r)  ||\
+                         ISRING(LEFT_3, r)  || ISRING(LEFT_4, r)  ||\
+                         ISRING(RIGHT_1, r) || ISRING(RIGHT_2, r) ||\
+             ISRING(RIGHT_3, r) || ISRING(RIGHT_4, r))
+#define newgrp() ++group
+#define o_charges o_ac
+#define o_kind o_ac
+#define ISMULT(type) (type == FOOD)
+#define isrock(ch) ((ch == WALL) || (ch == HORZWALL) || (ch == VERTWALL) || (ch == SECRETDOOR))
+#define is_stealth(tp) \
+    (rnd(25) < (tp)->t_stats.s_dext || (tp == &player && ISWEARING(R_STEALTH)))
+
+#define has_light(rp) (((rp)->r_flags & HASFIRE) || ISWEARING(R_LIGHT))
+
+#define mi_wght mi_worth
+#define mi_food mi_curse
+
+/*
+ * Ways to die
+ */
+
+#define D_PETRIFY       -1
+#define D_ARROW         -2
+#define D_DART          -3
+#define D_POISON        -4
+#define D_BOLT          -5
+#define D_SUFFOCATION   -6
+#define D_POTION        -7
+#define D_INFESTATION   -8
+#define D_DROWN         -9
+#define D_ROT           -10
+#define D_CONSTITUTION  -11
+#define D_STRENGTH      -12
+#define D_SIGNAL        -13
+#define D_CHOKE         -14
+#define D_STRANGLE      -15
+#define D_FALL          -16
+#define D_RELIC         -17
+#define D_STARVATION    -18
+#define D_FOOD_CHOKE    -19
+#define D_SCROLL        -20
+#define D_FRIGHT        -21
+#define D_CRYSTAL       -22
+#define D_CARD          -23
+#define DEATHNUM         23      /* number of ways to die */
+
+/*
+ * Things that appear on the screens
+ */
+
+#define WALL            ' '
+#define PASSAGE         '#'
+#define DOOR            '+'
+#define FLOOR           '.'
+#define HORZWALL        '-'
+#define VERTWALL        '|'
+#define VPLAYER         '@'
+#define IPLAYER         '_'
+#define POST            '^'
+#define TRAPDOOR        '>'
+#define ARROWTRAP       '{'
+#define SLEEPTRAP       '$'
+#define BEARTRAP        '}'
+#define TELTRAP         '~'
+#define DARTTRAP        '`'
+#define WORMHOLE        '<'
+#define POOL            '"'
+#define MAZETRAP        '\''
+#define SECRETDOOR      '&'
+#define STAIRS          '%'
+#define GOLD            '*'
+#define POTION          '!'
+#define SCROLL          '?'
+#define MAGIC           '$'
+#define BMAGIC          '>'     /*      Blessed magic   */
+#define CMAGIC          '<'     /*      Cursed  magic   */
+#define FOOD            ':'
+#define WEAPON          ')'
+#define MISSILE         '*'     /*      Magic Missile   */
+#define ARMOR           ']'
+#define MM              ';'
+#define RELIC           ','
+#define RING            '='
+#define STICK           '/'
+#define FOREST          '\\'
+
+/*
+ * Various constants
+ * Crypt() returns a different string on the PC for some silly reason
+ */
+
+#define PASSWD          "mT5uKwhm5WDRs"
+#define FIGHTBASE       10
+#define BEFORE          1
+#define AFTER           2
+#define ESC             27
+#define BOLT_LENGTH     12
+#define MARKLEN         20
+#define SLEEPTIME       (roll(15, 2))
+#define BEARTIME        (roll(15, 2))
+#define FREEZETIME      30
+#define HEALTIME        40
+#define SICKTIME        40
+#define MORETIME        80
+#define STOMACHSIZE     2100
+#define PAINTIME        (roll(15, 2))
+#define CLOAK_TIME      (roll(15, 2))
+#define CHILLTIME       (roll(15, 2))
+#define STONETIME       (roll(15, 2))
+#define SMELLTIME       (50+rnd(30))
+#define DUSTTIME        (50+rnd(30))
+#define STINKTIME       (50+rnd(30))
+#define HASTETIME       (50+rnd(30))
+#define HUHDURATION     (50+rnd(30))
+#define GONETIME        (50+rnd(30)) 
+#define SKILLDURATION   (50+rnd(30))
+#define SEEDURATION     (150+rnd(50))
+#define CLRDURATION     (150+rnd(50))
+#define FLYTIME         (150+rnd(50))
+#define PHASEDURATION   (150+rnd(50))
+#define ALCHEMYTIME     (250+rnd(100))
+#define FIRETIME        (180+roll(20, 2))
+#define COLDTIME        (180+roll(20, 2))
+#define BOLTTIME        (180+roll(20, 2))
+#define DAYLENGTH       700
+#define LEVEL           700  /* make depth of dungeon equal to DAYLENGTH */
+#define WANDERTIME      (max(5, (HARDER+rnd(25))-rnd(vlevel*2)))
+#define SPELLTIME       ((max(30-pstats.s_lvl,5)))
+#define vlevel          (max(level, turns/LEVEL + 1))
+
+/*
+ * Save against things
+ */
+
+#define VS_POISON               00
+#define VS_PARALYZATION         00
+#define VS_DEATH                00
+#define VS_PETRIFICATION        01
+#define VS_WAND                 02
+#define VS_BREATH               03
+#define VS_MAGIC                04
+
+/*
+ * attributes for treasures in dungeon
+ */
+
+#define ISCURSED               01
+#define ISKNOW                 02
+#define ISPOST                 04       /* object is in a trading post */
+#define ISMETAL               010
+#define ISPROT                020       /* object is protected */
+#define ISBLESSED             040
+#define ISPOISON             0100
+#define ISMISL             020000
+#define ISMANY             040000
+
+/*
+ * Various flag bits
+ */
+
+#define ISDARK                 01
+#define ISGONE                 02
+#define ISTREAS                04
+#define ISFOUND               010
+#define ISTHIEFSET            020
+#define FORCEDARK             040
+
+/*
+ * 1st set of creature flags (this might include player)
+ */
+
+#define ISBLIND         0x00000001
+#define ISINWALL        0x00000002
+#define ISRUN           0x00000004
+#define ISFLEE          0x00000008
+#define ISINVIS         0x00000010
+#define ISMEAN          0x00000020
+#define ISGREED         0x00000040
+#define CANSHOOT        0x00000080
+#define ISHELD          0x00000100
+#define ISHUH           0x00000200
+#define ISREGEN         0x00000400
+#define CANHUH          0x00000800
+#define CANSEE          0x00001000
+#define HASFIRE         0x00002000
+#define ISSLOW          0x00004000
+#define ISHASTE         0x00008000
+#define ISCLEAR         0x00010000
+#define CANINWALL       0x00020000
+#define ISDISGUISE      0x00040000
+#define CANBLINK        0x00080000
+#define CANSNORE        0x00100000
+#define HALFDAMAGE      0x00200000
+#define CANSUCK         0x00400000
+#define CANRUST         0x00800000
+#define CANPOISON       0x01000000
+#define CANDRAIN        0x02000000
+#define ISUNIQUE        0x04000000
+#define STEALGOLD       0x08000000
+
+/* 
+ * Second set of flags 
+ */
+
+#define STEALMAGIC      0x10000001
+#define CANDISEASE      0x10000002
+#define HASDISEASE      0x10000004
+#define CANSUFFOCATE    0x10000008
+#define DIDSUFFOCATE    0x10000010
+#define BOLTDIVIDE      0x10000020
+#define BLOWDIVIDE      0x10000040
+#define NOCOLD          0x10000080
+#define TOUCHFEAR       0x10000100
+#define BMAGICHIT       0x10000200
+#define NOFIRE          0x10000400
+#define NOBOLT          0x10000800
+#define CARRYGOLD       0x10001000
+#define CANITCH         0x10002000
+#define HASITCH         0x10004000
+#define DIDDRAIN        0x10008000
+#define WASTURNED       0x10010000
+#define CANSELL         0x10020000
+#define CANBLIND        0x10040000
+#define NOACID          0x10080000
+#define NOSLOW          0x10100000
+#define NOFEAR          0x10200000
+#define NOSLEEP         0x10400000
+#define NOPARALYZE      0x10800000
+#define NOGAS           0x11000000
+#define CANMISSILE      0x12000000
+#define CMAGICHIT       0x14000000
+#define CANPAIN         0x18000000
+
+/* 
+ * Third set of flags 
+ */
+
+#define CANSLOW         0x20000001
+#define CANTUNNEL       0x20000002
+#define TAKEWISDOM      0x20000004
+#define NOMETAL         0x20000008
+#define MAGICHIT        0x20000010
+#define CANINFEST       0x20000020
+#define HASINFEST       0x20000040
+#define NOMOVE          0x20000080
+#define CANSHRIEK       0x20000100
+#define CANDRAW         0x20000200
+#define CANSMELL        0x20000400
+#define CANPARALYZE     0x20000800
+#define CANROT          0x20001000
+#define ISSCAVENGE      0x20002000
+#define DOROT           0x20004000
+#define CANSTINK        0x20008000
+#define HASSTINK        0x20010000
+#define ISSHADOW        0x20020000
+#define CANCHILL        0x20040000
+#define CANHUG          0x20080000
+#define CANSURPRISE     0x20100000
+#define CANFRIGHTEN     0x20200000
+#define CANSUMMON       0x20400000
+#define TOUCHSTONE      0x20800000
+#define LOOKSTONE       0x21000000
+#define CANHOLD         0x22000000
+#define DIDHOLD         0x24000000
+#define DOUBLEDRAIN     0x28000000
+
+/* 
+ * Fourth set of flags 
+ */
+
+#define CANBRANDOM      0x30000001      /* Types of breath */
+#define CANBACID        0x30000002      /* acid */
+#define CANBFIRE        0x30000004      /* Fire */
+#define CANBCGAS        0x30000008      /* confusion gas */
+#define CANBBOLT        0x30000010      /* lightning bolt */
+#define CANBGAS         0x30000020      /* chlorine gas */
+#define CANBICE         0x30000040      /* ice */
+#define CANBFGAS        0x30000080      /* Fear gas */
+#define CANBPGAS        0x30000100      /* Paralyze gas */
+#define CANBSGAS        0x30000200      /* Sleeping gas */
+#define CANBSLGAS       0x30000400      /* Slow gas */
+#define CANBREATHE      0x300007ff      /* Can it breathe at all? */
+
+/*
+ * Fifth set of flags
+ */
+
+#define ISUNDEAD        0x40000001
+#define CANSONIC        0x40000002
+#define TURNABLE        0x40000004
+#define TAKEINTEL       0x40000008
+#define NOSTAB          0x40000010
+#define CANDISSOLVE     0x40000020
+#define ISFLY           0x40000040      /* creature can fly */
+#define CANTELEPORT     0x40000080      /* creature can teleport */
+#define CANEXPLODE      0x40000100      /* creature explodes when hit */
+#define CANDANCE        0x40000200      /* creature can make hero "dance" */
+#define ISDANCE         0x40000400      /* creature (hero) is dancing */
+#define CARRYFOOD       0x40000800
+#define CARRYSCROLL     0x40001000
+#define CARRYPOTION     0x40002000
+#define CARRYRING       0x40004000
+#define CARRYSTICK      0x40008000
+#define CARRYMISC       0x40010000
+#define CARRYMDAGGER    0x40020000      /* Dagger of Musty */
+#define CARRYCLOAK      0x40040000      /* Cloak of Emori */
+#define CARRYANKH       0x40080000      /* Ankh of Heil */
+#define CARRYSTAFF      0x40100000      /* Staff of Ming */
+#define CARRYWAND       0x40200000      /* Wand of Orcus */
+#define CARRYROD        0x40400000      /* Rod of Asmodeus */
+#define CARRYYAMULET    0x40800000      /* Amulet of Yendor */
+#define CARRYMANDOLIN   0x41000000      /* Mandolin of Brian */
+#define MISSEDDISP      0x42000000      /* Missed Cloak of Displacement */
+#define CANBSTAB        0x44000000      /* Can backstab */
+#define ISGUARDIAN      0x48000000      /* Guardian of a treasure room */
+
+/*
+ * Sixth set of flags
+ */
+
+#define CARRYHORN       0x50000001      /* Horn of Geryon */
+#define CARRYMSTAR      0x50000002      /* Morning Star of Hruggek */
+#define CARRYFLAIL      0x50000004      /* Flail of Yeenoghu */
+#define CARRYWEAPON     0x50000008      /* A generic weapon */
+#define CANAGE          0x50000010      /* can age you */
+#define CARRYDAGGER     0x50000020      /* carry's a dumb old dagger */
+#define AREMANY         0x50000040      /* they come in droves */
+#define CARRYEYE        0x50000080      /* has the eye of Vecna */
+#define HASSUMMONED     0x50000100      /* has already summoned */
+#define ISSTONE         0x50000200      /* has been turned to stone */
+#define NODETECT        0x50000400      /* detect monster will not show him */
+#define NOSTONE         0x50000800      /* creature made its save vrs stone */
+#define CARRYQUILL      0x50001000      /* has the quill of Nagrom */
+#define CARRYAXE        0x50002000      /* has the axe of Aklad */
+#define TOUCHSLOW       0x50004000      /* touch will slow hero */
+#define WASDISRUPTED    0x50008000      /* creature was disrupted by player */
+#define CARRYARMOR      0x50010000      /* creature will pick up armor */
+#define CARRYBAMULET    0x50020000      /* amulet of skoraus stonebones */
+#define CARRYSURTURRING 0x50040000      /* ring of Surtur */
+#define CARRYCARD       0x50080000      /* carry the card of Alteran */
+#define ISCHARMED       0x50100000      /* is the monster charmed? */
+#define ISFRIENDLY      0x50100000      /* monster friendly for any reason? */
+
+#define NEEDSTOACT      0x60000001      /* monster ready to act this turn n */
+#define ISDEAD          0x60000002      /* monster is dead                  */
+#define ISELSEWHERE     0x60000004      /* monster has been whisked away    */
+
+/* Masks for choosing the right flag */
+
+#define FLAGMASK     0xf0000000
+#define FLAGINDEX    0x0000000f
+#define FLAGSHIFT    28
+#define MAXFLAGS     25                 /* max initial flags per creature */
+
+/* 
+ * Mask for cancelling special abilities 
+ * The flags listed here will be the ones left on after the
+ * cancellation takes place
+ */
+
+#define CANC0MASK (     ISBLIND         | ISINWALL      | ISRUN         | \
+                        ISFLEE          | ISMEAN        | ISGREED       | \
+                        CANSHOOT        | ISHELD        | ISHUH         | \
+                        ISSLOW          | ISHASTE       | ISCLEAR       | \
+                        ISUNIQUE )
+#define CANC1MASK (     HASDISEASE      | DIDSUFFOCATE  | CARRYGOLD     | \
+                        HASITCH         | CANSELL       | DIDDRAIN      | \
+                        WASTURNED )
+#define CANC2MASK (     HASINFEST       | NOMOVE        | ISSCAVENGE    | \
+                        DOROT           | HASSTINK      | DIDHOLD )
+#define CANC3MASK (     CANBREATHE )
+#define CANC4MASK (     ISUNDEAD        | CANSONIC      | NOSTAB        | \
+                        ISFLY           | CARRYFOOD     | CANEXPLODE    | \
+                        ISDANCE         | CARRYSCROLL   | CARRYPOTION   | \
+                        CARRYRING       | CARRYSTICK    | CARRYMISC     | \
+                        CARRYMDAGGER    | CARRYCLOAK    | CARRYANKH     | \
+                        CARRYSTAFF      | CARRYWAND     | CARRYROD      | \
+                        CARRYYAMULET    | CARRYMANDOLIN | ISGUARDIAN )
+#define CANC5MASK (     CARRYHORN       | CARRYMSTAR    | CARRYFLAIL    | \
+                        CARRYEYE        | CARRYDAGGER   | HASSUMMONED   | \
+                        AREMANY         | CARRYWEAPON   | NOSTONE       | \
+                        CARRYQUILL      | CARRYAXE      | WASDISRUPTED  | \
+                        CARRYARMOR      | CARRYBAMULET  | CARRYSURTURRING )
+#define CANC6MASK (     CARRYCARD )
+#define CANC7MASK ( 0 )
+#define CANC8MASK ( 0 )
+#define CANC9MASK ( 0 )
+#define CANCAMASK ( 0 )
+#define CANCBMASK ( 0 )
+#define CANCCMASK ( 0 )
+#define CANCDMASK ( 0 )
+#define CANCEMASK ( 0 )
+#define CANCFMASK ( 0 )
+
+/* types of things */
+
+#define TYP_POTION      0
+#define TYP_SCROLL      1
+#define TYP_FOOD        2
+#define TYP_WEAPON      3
+#define TYP_ARMOR       4
+#define TYP_RING        5
+#define TYP_STICK       6
+#define TYP_MM          7
+#define TYP_RELIC       8
+#define NUMTHINGS       9
+
+/*
+ * food types
+ */
+
+#define E_RATION        0
+#define E_APPLE         1
+#define E_BANANA        2
+#define E_BLUEBERRY     3
+#define E_CANDLEBERRY   4
+#define E_CAPRIFIG      5
+#define E_DEWBERRY      6
+#define E_ELDERBERRY    7
+#define E_GOOSEBERRY    8
+#define E_GUANABANA     9
+#define E_HAGBERRY      10
+#define E_JABOTICABA    11
+#define E_PEACH         12
+#define E_PITANGA       13
+#define E_PRICKLEY      14
+#define E_RAMBUTAN      15
+#define E_SAPODILLA     16
+#define E_SOURSOP       17
+#define E_STRAWBERRY    18
+#define E_SWEETSOP      19
+#define E_WHORTLEBERRY  20
+#define E_SLIMEMOLD     21
+#define MAXFOODS        22
+
+/*
+ * Potion types
+ */
+
+#define P_CLEAR         0
+#define P_ABIL          1
+#define P_SEEINVIS      2
+#define P_HEALING       3
+#define P_MFIND         4
+#define P_TFIND         5
+#define P_RAISE         6
+#define P_HASTE         7
+#define P_RESTORE       8
+#define P_PHASE         9
+#define P_INVIS         10
+#define P_FLY           11
+#define P_FFIND         12
+#define P_SKILL         13
+#define P_FIRE          14
+#define P_COLD          15
+#define P_LIGHTNING     16
+#define P_POISON        17
+#define MAXPOTIONS      18
+
+/*
+ * Scroll types
+ */
+
+#define S_CONFUSE       0
+#define S_MAP           1
+#define S_LIGHT         2
+#define S_HOLD          3
+#define S_SLEEP         4
+#define S_ALLENCH       5
+#define S_IDENT         6
+#define S_SCARE         7
+#define S_GFIND         8
+#define S_TELEP         9
+#define S_CREATE        10
+#define S_REMOVE        11
+#define S_PETRIFY       12
+#define S_GENOCIDE      13
+#define S_CURING        14
+#define S_MAKEIT        15
+#define S_PROTECT       16
+#define S_FINDTRAPS     17
+#define S_RUNES         18
+#define S_CHARM         19
+#define MAXSCROLLS      20
+
+/*
+ * Weapon types
+ */
+
+#define MACE            0               /* mace */
+#define SWORD           1               /* long sword */
+#define BOW             2               /* short bow */
+#define ARROW           3               /* arrow */
+#define DAGGER          4               /* dagger */
+#define ROCK            5               /* rocks */
+#define TWOSWORD        6               /* two-handed sword */
+#define SLING           7               /* sling */
+#define DART            8               /* darts */
+#define CROSSBOW        9               /* crossbow */
+#define BOLT            10              /* crossbow bolt */
+#define SPEAR           11              /* spear */
+#define TRIDENT         12              /* trident */
+#define SPETUM          13              /* spetum */
+#define BARDICHE        14              /* bardiche */
+#define PIKE            15              /* pike */
+#define BASWORD         16              /* bastard sword */
+#define HALBERD         17              /* halberd */
+#define BATTLEAXE       18              /* battle axe */
+#define MAXWEAPONS      19              /* types of weapons */
+#define NONE            100             /* no weapon */
+
+/*
+ * Armor types
+ */
+ 
+#define LEATHER         0
+#define RING_MAIL       1
+#define STUDDED_LEATHER 2
+#define SCALE_MAIL      3
+#define PADDED_ARMOR    4
+#define CHAIN_MAIL      5
+#define SPLINT_MAIL     6
+#define BANDED_MAIL     7
+#define PLATE_MAIL      8
+#define PLATE_ARMOR     9
+#define MAXARMORS       10
+
+/*
+ * Ring types
+ */
+ 
+#define R_PROTECT       0
+#define R_ADDSTR        1
+#define R_SUSABILITY    2
+#define R_SEARCH        3
+#define R_SEEINVIS      4
+#define R_ALERT         5
+#define R_AGGR          6
+#define R_ADDHIT        7
+#define R_ADDDAM        8
+#define R_REGEN         9
+#define R_DIGEST        10
+#define R_TELEPORT      11
+#define R_STEALTH       12
+#define R_ADDINTEL      13
+#define R_ADDWISDOM     14
+#define R_HEALTH        15
+#define R_CARRY         16
+#define R_LIGHT         17
+#define R_DELUSION      18
+#define R_FEAR          19
+#define R_HEROISM       20
+#define R_FIRE          21
+#define R_WARMTH        22
+#define R_VAMPREGEN     23
+#define R_FREEDOM       24
+#define R_TELCONTROL    25
+#define MAXRINGS        26
+
+/*
+ * 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_SLOW_M       7
+#define WS_DRAIN        8
+#define WS_CHARGE       9
+#define WS_TELMON       10
+#define WS_CANCEL       11
+#define WS_CONFMON      12
+#define WS_DISINTEGRATE 13
+#define WS_PETRIFY      14
+#define WS_PARALYZE     15
+#define WS_MDEG         16
+#define WS_CURING       17
+#define WS_WONDER       18
+#define WS_FEAR         19
+#define MAXSTICKS       20
+
+/*
+ * miscellaneous magic items
+ */
+ 
+#define MM_JUG          0
+#define MM_BEAKER       1
+#define MM_BOOK         2
+#define MM_ELF_BOOTS    3
+#define MM_BRACERS      4
+#define MM_OPEN         5
+#define MM_HUNGER       6
+#define MM_DISP         7
+#define MM_PROTECT      8
+#define MM_DRUMS        9
+#define MM_DISAPPEAR    10
+#define MM_CHOKE        11
+#define MM_G_DEXTERITY  12
+#define MM_G_OGRE       13
+#define MM_JEWEL        14
+#define MM_KEOGHTOM     15
+#define MM_R_POWERLESS  16
+#define MM_FUMBLE       17
+#define MM_ADAPTION     18
+#define MM_STRANGLE     19
+#define MM_DANCE        20
+#define MM_SKILLS       21
+#define MM_CRYSTAL      22
+#define MAXMM           23
+
+/*
+ * Relic types
+ */
+ 
+#define MUSTY_DAGGER            0
+#define EMORI_CLOAK             1
+#define HEIL_ANKH               2
+#define MING_STAFF              3
+#define ORCUS_WAND              4
+#define ASMO_ROD                5
+#define YENDOR_AMULET           6
+#define BRIAN_MANDOLIN          7
+#define GERYON_HORN             8
+#define HRUGGEK_MSTAR           9
+#define YEENOGHU_FLAIL          10
+#define EYE_VECNA               11
+#define AXE_AKLAD               12
+#define QUILL_NAGROM            13
+#define STONEBONES_AMULET       14
+#define SURTUR_RING             15
+#define ALTERAN_CARD            16
+#define MAXRELIC                17
+
+#define MAXDAEMONS      10
+#define MAXFUSES        20
+
+extern struct delayed_action d_list[MAXDAEMONS];
+extern struct delayed_action f_list[MAXFUSES];
+extern int demoncnt;        /* number of active daemons */
+extern int fusecnt;
+
+/* Now define the structures and types */
+
+/*
+ * character types
+ */
+ 
+struct character_types {
+    char        name[40];       /* name of character class              */
+    long        start_exp;      /* starting exp pts for 2nd level       */
+    long        cap;            /* stop doubling here                   */
+    int         hit_pts;        /* hit pts gained per level             */
+    int         base;           /* Base to-hit value (AC 10)            */
+    int         max_lvl;        /* Maximum level for changing value     */
+    int         factor;         /* Amount base changes each time        */
+    int         offset;         /* What to offset level                 */
+    int         range;          /* Range of levels for each offset      */
+};
+
+/*
+ * level types
+ */
+ 
+typedef enum {
+        NORMLEV,        /* normal level */
+        POSTLEV,        /* trading post level */
+        MAZELEV,        /* maze level */
+        OUTSIDE,        /* outside region */
+        STARTLEV        /* beginning of the game */
+} LEVTYPE;
+
+/*
+ * Help lists
+ */
+ 
+struct h_list {
+    char h_ch;
+    char h_desc[40];
+};
+
+struct item_list {
+    unsigned char item_ch;
+    char item_desc[40];
+};
+
+/*
+ * Coordinate data type
+ */
+ 
+typedef struct {
+    int x;
+    int y;
+} coord;
+
+/*
+ * structure for the ways to die
+ */
+ 
+struct death_type {
+    int reason;
+    char name[30];
+};
+
+/*
+ * 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;
+    int  mi_curse;
+    int  mi_bless;
+};
+
+/*
+ * Room structure
+ */
+ 
+struct room {
+    coord r_pos;                        /* Upper left corner */
+    coord r_max;                        /* Size of room */
+    long r_flags;                       /* Info about the room */
+    struct linked_list *r_fires;        /* List of fire creatures in room */
+    struct linked_list *r_exit;         /* Linked list of exits */
+};
+
+/*
+ * Array of all traps on this level
+ */
+ 
+struct trap {
+    unsigned char tr_type;              /* What kind of trap */
+    unsigned char tr_show;              /* Where disguised trap looks like */
+    coord tr_pos;                       /* Where trap is */
+    long tr_flags;                      /* Info about trap (i.e. ISFOUND) */
+};
+
+/*
+ * Structure describing a fighting being
+ */
+ 
+struct stats {
+    short s_str;                        /* Strength */
+    short s_intel;                      /* Intelligence */
+    short s_wisdom;                     /* Wisdom */
+    short s_dext;                       /* Dexterity */
+    short s_const;                      /* Constitution */
+    short s_charisma;                   /* Charisma */
+    unsigned long s_exp;                /* Experience */
+    int s_lvladj;                       /* how much level is adjusted */
+    int s_lvl;                          /* Level of mastery */
+    int s_arm;                          /* Armor class */
+    int s_hpt;                          /* Hit points */
+    int s_pack;                         /* current weight of his pack */
+    int s_carry;                        /* max weight he can carry */
+    char s_dmg[30];                      /* String describing damage done */
+};
+
+/*
+ * Structure describing a fighting being (monster at initialization)
+ */
+ 
+struct mstats {
+    short ms_str;                        /* Strength */
+    short ms_dex;                        /* dexterity */
+    short ms_move;                       /* movement rate */
+    unsigned long ms_exp;                /* Experience */
+    short ms_lvl;                        /* Level of mastery */
+    short ms_arm;                        /* Armor class */
+    char ms_hpt[9];                        /* Hit points */
+    char ms_dmg[30];                      /* String describing damage done */
+};
+
+/*
+ * Structure for monsters and player
+ */
+ 
+struct thing {
+    bool t_wasshot;                     /* Was character shot last round? */
+    unsigned char t_type;                        /* What it is */
+    unsigned char t_disguise;                    /* What mimic looks like */
+    unsigned char t_oldch;                       /* Character that was where it was */
+    short t_ctype;                      /* Character type */
+    short t_index;                      /* Index into monster table */
+    short t_no_move;                    /* How long the thing can't move */
+    short t_quiet;                      /* used in healing */
+    short t_movement;                   /* Base movement rate */
+    short t_action;                     /* Action we're waiting to do */
+    short t_artifact;                   /* base chance of using artifact */
+    short t_wand;                       /* base chance of using wands */
+    short t_summon;                     /* base chance of summoning */
+    short t_cast;                       /* base chance of casting a spell */
+    short t_breathe;                    /* base chance to swing at player */
+    char  *t_name;                      /* name player gave his pet */
+    coord t_doorgoal;                   /* What door are we heading to? */
+    coord *t_dest;                      /* Where it is running to */
+    coord t_pos;                        /* Position */
+    coord t_oldpos;                     /* Last position */
+    coord t_newpos;                     /* Where we want to go */
+    unsigned long t_flags[16];          /* State word */
+    struct linked_list *t_pack;         /* What the thing is carrying */
+	struct linked_list *t_using;        /* What the thing is using */
+	int t_selection;
+    struct stats t_stats;               /* Physical description */
+    struct stats maxstats;              /* maximum(or initial) stats */
+    int    t_reserved;                  /* reserved for save/restore code */
+};
+
+/*
+ * Array containing information on all the various types of monsters
+ */
+ 
+struct monster {
+    char m_name[30];                    /* What to call the monster */
+    short m_carry;                      /* Probability of carrying something */
+    bool m_normal;                      /* Does monster exist? */
+    bool m_wander;                      /* Does monster wander? */
+    char m_appear;                      /* What does monster look like? */
+    char m_intel[8];                    /* Intelligence range */
+    long m_flags[MAXFLAGS];             /* Things about the monster */
+    char m_typesum[30];                 /* type of creature can he summon */
+    short m_numsum;                     /* how many creatures can he summon */
+    short m_add_exp;                    /* Added experience per hit point */
+    struct mstats 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 */
+    char o_launch;                      /* What you need to launch it */
+    char o_damage[8];                   /* Damage if used like sword */
+    char o_hurldmg[8];                  /* Damage if thrown */
+    struct linked_list *contents;       /* contents of this object */
+    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 */
+    long o_flags;                       /* Information about objects */
+    int o_group;                        /* Group number for this object */
+    int o_weight;                       /* weight of this object */
+    unsigned char o_mark[MARKLEN];               /* Mark the specific object */
+};
+
+/*
+ * weapon structure
+ */
+ 
+struct init_weps {
+    char w_name[20];            /* name of weapon */
+    char w_dam[8];              /* hit damage */
+    char w_hrl[8];              /* hurl damage */
+    char w_launch;              /* need to launch it */
+    int  w_flags;               /* flags */
+    int  w_rate;                /* rate of fire */
+    int  w_wght;                /* weight of weapon */
+    int  w_worth;               /* worth of this weapon */
+};
+
+/*
+ * armor structure 
+ */
+ 
+struct init_armor {
+        char a_name[30];        /* name of armor */
+        int  a_prob;            /* chance of getting armor */
+        int  a_class;           /* normal armor class */
+        int  a_worth;           /* worth of armor */
+        int  a_wght;            /* weight of armor */
+};
+
+struct spells {
+    short s_which;              /* which scroll or potion */
+    short s_cost;               /* cost of casting spell */
+    short s_type;               /* scroll or potion */
+    int   s_flag;               /* is the spell blessed/cursed? */
+};
+
+struct words
+{
+    char w_string[30];
+};
+
+#define NAMELEN 80
+#define SYSLEN 10
+#define LOGLEN 9
+
+struct sc_ent {
+    unsigned long       sc_score;
+    char        sc_name[NAMELEN];
+    char        sc_system[SYSLEN];
+    char        sc_login[LOGLEN];
+    short       sc_flags;
+    short       sc_level;
+    short       sc_ctype;
+    short       sc_monster;
+    short       sc_quest;
+};
+
+/*
+ * Other structures
+ */
+ 
+struct linked_list  *find_mons(), *find_obj(), *get_item(), *new_item(),
+                    *new_thing(), *wake_monster(), *get_hurl(), *spec_item(),
+                    *creat_item(), *wield_weap();
+
+struct room         *roomin();
+struct trap         *trap_at();
+
+char *getenv(), *tr_name(), *new(), *vowelstr(),
+    *inv_name(), *num(),
+    *ring_num(), *misc_num(), *blesscurse(), *p_kind(), *typ_name(),
+    *prname(), *monster_name(), *weap_name();
+
+coord   rndmove(), *fallpos(), *doorway(), get_coordinates();
+int can_shoot(),misc_name();
+
+short   randmonster(), id_monst(), movement();
+
+int bugkill(), nohaste(), spell_recovery(), doctor(), runners(), swander(),
+    unconfuse(), unsee(), fumble(), unclrhead(), unphase(), noslow(),
+    rollwand(), stomach(), sight(), unstink(), suffocate(), cure_disease(),
+    shoot_bolt(), changeclass(), appear(), dust_appear(), unchoke(),
+    alchemy(), trap_look(), strangle(), ring_teleport(), ring_search(),
+    grab(), dsrpt_player(), quill_charge(), make_sell_pack(), unskill(),
+    findmindex(), nobolt(), nofire(), nocold(), usage_time(), eat_gold(),
+    chant_recovery(), prayer_recovery(), dsrpt_monster(), opt_player();
+
+bool    blue_light(), can_blink(), creat_mons(), add_pack(), invisible(),
+    straight_shot(), maze_view(), lit_room(), getdelta(), save_file(),
+    save_game(), m_use_it(), m_use_pack(), get_dir(), need_dir(),passwd();
+
+long    check_level();
+long    encread();
+long    get_worth();
+long    encwrite();
+
+void    byebye(int sig), genmonsters(), quit(int sig),
+    auto_save(int sig), endit(int sig), tstp();
+
+void    teleport();
+    
+int undance(), land(), cloak_charge(), wghtchk();
+
+int add_intelligence(), add_strength(), add_wisdom(), add_dexterity(),
+    add_constitution(), add_charisma(), res_intelligence(), res_strength(),
+    res_wisdom(), res_dexterity(), res_constitution(), res_charisma();
+
+/*
+ * Now all the global variables
+ */
+ 
+extern struct trap traps[];
+extern struct character_types char_class[];  /* character classes */
+extern struct room rooms[];             /* One for each room -- A level */
+extern struct room *oldrp;              /* Roomin(&oldpos) */
+extern struct linked_list *mlist;       /* List of monsters on the level */
+extern struct linked_list *tlist;       /* list of monsters fallen down traps */
+extern struct linked_list *rlist;       /* list of monsters that have died    */
+extern struct death_type deaths[];      /* all the ways to die */
+extern struct thing player;             /* The rogue */
+extern struct monster monsters[NUMMONST+1];       /* The initial monster states */
+extern struct linked_list *lvl_obj;     /* List of objects on this level */
+extern struct linked_list *monst_dead;  /* Indicates monster that got killed */
+extern struct object *cur_weapon;       /* Which weapon he is weilding */
+extern struct object *cur_armor;        /* What a well dresssed rogue wears */
+extern struct object *cur_ring[];       /* Which rings are being worn */
+extern struct object *cur_misc[];       /* which MM's are in use */
+extern struct magic_item things[];      /* Chances for each type of item */
+extern struct magic_item s_magic[];     /* Names and chances for scrolls */
+extern struct magic_item p_magic[];     /* Names and chances for potions */
+extern struct magic_item r_magic[];     /* Names and chances for rings */
+extern struct magic_item ws_magic[];    /* Names and chances for sticks */
+extern struct magic_item m_magic[];     /* Names and chances for MM */
+extern struct magic_item rel_magic[];   /* Names and chances for relics */
+extern struct magic_item foods[];       /* Names and chances for foods */
+extern struct spells magic_spells[];    /* spells for magicians */
+extern struct spells cleric_spells[];   /* spells for clerics */
+extern struct spells druid_spells[];    /* spells for druids */
+extern struct spells quill_scrolls[];   /* scrolls for quill */
+extern const char *cnames[][NUM_CNAMES];      /* Character level names */
+extern struct words abilities[NUMABILITIES];   /* Names of the various abilities */
+extern char curpurch[];                 /* name of item ready to buy */
+extern char PLAYER;                     /* what the player looks like */
+extern int nfloors;                     /* Number of floors in this dungeon */
+extern int cols;                        /* number of columns on terminal */
+extern int lines;                       /* number of lines in terminal */
+extern int char_type;                   /* what type of character is player */
+extern int foodlev;                     /* how fast he eats food */
+extern int level;                       /* What level rogue is on */
+extern int trader;                      /* number of purchases */
+extern int curprice;                    /* price of an item */
+extern long purse;                      /* How much gold the rogue has */
+extern int mpos;                        /* Where cursor is on top line */
+extern int ntraps;                      /* Number of traps on this level */
+extern int inpack;                      /* Number of things in pack */
+extern int total;                       /* Total dynamic memory bytes */
+extern int lastscore;                   /* Score before this turn */
+extern int no_food;                     /* Number of levels without food */
+extern int foods_this_level;            /* num of foods this level */
+extern int seed;                        /* Random number seed */
+extern int count;                       /* Number of times to repeat command */
+extern int max_level;                   /* Deepest player has gone */
+extern int cur_max;                     /* Deepest player has gone currently */
+extern int prev_max;                    /* A flag for worm hole */
+extern int move_free;                   /* Free movement check */
+extern int food_left;                   /* Amount of food in hero's stomach */
+extern int group;                       /* Current group number */
+extern int hungry_state;                /* How hungry is he */
+extern int infest_dam;                  /* Damage from parasites */
+extern int lost_str;                    /* Amount of strength lost */
+extern int hold_count;                  /* Number of monsters holding player */
+extern int trap_tries;                  /* Number of attempts to set traps */
+extern int chant_time;                  /* Number of chant points/exp level */
+extern int pray_time;                   /* Number of prayer points/exp level */
+extern int spell_power;                 /* Spell power left at this level */
+extern long turns;                      /* Number of turns player has taken */
+extern int quest_item;                  /* Item hero is looking for */
+extern int cur_relic[];                 /* Current relics */
+extern char take;                       /* Thing the rogue is taking */
+extern char prbuf[];                    /* Buffer for sprintfs */
+extern char outbuf[];                   /* Output buffer for stdout */
+extern char runch;                      /* Direction player is running */
+extern char *s_names[];                 /* Names of the scrolls */
+extern char *p_colors[];                /* Colors of the potions */
+extern char *r_stones[];                /* Stone settings of the rings */
+extern struct init_weps weaps[];        /* weapons and attributes */
+extern struct init_armor armors[];      /* armors and attributes */
+extern char *ws_made[];                 /* What sticks are made of */
+extern char *release;                   /* Release number of rogue */
+extern char whoami[];                   /* Name of player */
+extern char fruit[];                    /* Favorite fruit */
+extern char huh[];                      /* The last message printed */
+extern char *s_guess[];                 /* Players guess at what scroll is */
+extern char *p_guess[];                 /* Players guess at what potion is */
+extern char *r_guess[];                 /* Players guess at what ring is */
+extern char *ws_guess[];                /* Players guess at what wand is */
+extern char *m_guess[];                 /* Players guess at what MM is */
+extern char *ws_type[];                 /* Is it a wand or a staff */
+extern char file_name[];                /* Save file name */
+extern char score_file[];               /* Score file name */
+extern char home[];                     /* User's home directory */
+extern WINDOW *cw;                      /* Window that the player sees */
+extern WINDOW *hw;                      /* Used for the help command */
+extern WINDOW *mw;                      /* Used to store mosnters */
+extern WINDOW *msgw;                    /* Message window */
+extern bool pool_teleport;              /* just teleported from a pool */
+extern bool inwhgt;                     /* true if from wghtchk() */
+extern bool running;                    /* True if player is running */
+extern bool playing;                    /* True until he quits */
+extern bool wizard;                     /* True if allows wizard commands */
+extern bool after;                      /* True if we want after daemons */
+extern bool notify;                     /* True if player wants to know */
+extern bool fight_flush;                /* True if toilet input */
+extern bool terse;                      /* True if we should be short */
+extern bool auto_pickup;                /* Pick up things automatically? */
+extern bool menu_overlay;               /* Use overlay type menu */
+extern bool door_stop;                  /* Stop running when we pass a door */
+extern bool jump;                       /* Show running as series of jumps */
+extern bool slow_invent;                /* Inventory one line at a time */
+extern bool def_attr;                   /* True for default attributes */
+extern bool firstmove;                  /* First move after setting door_stop */
+extern bool waswizard;                  /* Was a wizard sometime */
+extern bool askme;                      /* Ask about unidentified things */
+extern bool s_know[];                   /* Does he know what a scroll does */
+extern bool p_know[];                   /* Does he know what a potion does */
+extern bool r_know[];                   /* Does he know what a ring does */
+extern bool ws_know[];                  /* Does he know what a stick does */
+extern bool m_know[];                   /* Does he know what a MM does */
+extern bool in_shell;                   /* True if executing a shell */
+extern bool daytime;                    /* Indicates whether it is daytime */
+extern bool funfont;                    /* Is fun font available? */
+extern coord oldpos;                    /* Position before last look() call */
+extern coord grid[];                    /* used for random pos generation */
+extern char *nothing;                   /* "Nothing seems to happen." */
+extern char *spacemsg;
+extern char *morestr;
+extern char *retstr;
+extern LEVTYPE levtype;
+extern int (*add_abil[NUMABILITIES])(); /* Functions to change abilities */
+extern int (*res_abil[NUMABILITIES])(); /* Functions to change abilities */
+extern int mf_count;       /* move_free counter - see actions.c(m_act()) */
+extern int mf_jmpcnt;      /* move_free counter for # of jumps        */
+extern int killed_chance;  /* cumulative chance for goodies to loose it, fight.c */
+extern coord move_nh;        /* move.c */
+#define NCOLORS 32
+#define NSYLLS  127
+#define NSTONES 47
+#define NWOOD 24
+#define NMETAL 16
+extern struct words rainbow[NCOLORS];
+extern struct words sylls[NSYLLS];
+extern struct words stones[NSTONES];
+extern struct words wood[NWOOD];
+extern struct words metal[NMETAL];
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xrogue/rooms.c	Tue Apr 21 08:55:20 2015 -0400
@@ -0,0 +1,295 @@
+/*
+    rooms.c - Draw the nine rooms on the screen
+    
+    XRogue: Expeditions into the Dungeons of Doom
+    Copyright (C) 1991 Robert Pietkivitch
+    All rights reserved.
+    
+    Based on "Advanced Rogue"
+    Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka and AT&T
+    All rights reserved.
+
+    Based on "Rogue: Exploring the Dungeons of Doom"
+    Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
+    All rights reserved.
+    
+    See the file LICENSE.TXT for full copyright and licensing information.
+*/
+
+#include <curses.h>
+#include "rogue.h"
+
+do_rooms()
+{
+    register int i;
+    register struct room *rp;
+    register struct linked_list *item;
+    register struct thing *tp;
+    int left_out;
+    int num_monsters;
+    int which_monster;
+    int j;
+    coord top;
+    coord bsze;
+    coord mp;
+    coord *np;
+
+    /*
+     * bsze is the maximum room size
+     */
+    bsze.x = cols/3;
+    bsze.y = (lines-2)/3;
+    /*
+     * Clear things for a new level
+     */
+    for (rp = rooms; rp < &rooms[MAXROOMS]; rp++) {
+        rp->r_flags = 0;
+        _r_free_fire_list(&rp->r_fires);
+    }
+    /*
+     * 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++)
+    {
+        bool has_gold=FALSE;
+
+        /*
+         * Find upper left corner of box that this room goes in
+         */
+        top.x = (i%3)*bsze.x;
+        top.y = i/3*bsze.y + 1;
+        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-2);
+            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);
+
+        /* Draw the room */
+        draw_room(rp);
+
+        /*
+         * Put the gold in
+         */
+        if (rnd(100) < 55 && level >= cur_max)
+        {
+            register struct linked_list *item;
+            register struct object *cur;
+            coord tp;
+
+            has_gold = TRUE;    /* This room has gold in it */
+
+            item = spec_item(GOLD, NULL, NULL, NULL);
+            cur = OBJPTR(item);
+
+            /* Put the gold into the level list of items */
+            attach(lvl_obj, item);
+
+            /* Put it somewhere */
+            rnd_pos(rp, &tp);
+            mvaddch(tp.y, tp.x, GOLD);
+            cur->o_pos = tp;
+            if (roomin(&tp) != rp) {
+                endwin();
+                abort();
+            }
+        }
+
+        /*
+         * Put the monster in
+         */
+        if (rnd(100) < (has_gold ? 80 : 25) + vlevel/2)
+        {
+            do
+            {
+                rnd_pos(rp, &mp);
+            } until(mvwinch(stdscr, mp.y, mp.x) == FLOOR);
+            which_monster = randmonster(FALSE, FALSE);
+            num_monsters = 1;
+            /*
+             * see if we should make a whole bunch
+             */
+            for (j=0; j<MAXFLAGS; j++) {
+                if (monsters[which_monster].m_flags[j] == AREMANY)
+                        num_monsters = roll(7,2);
+            }
+            for (j=0; j<num_monsters; j++) {
+                    if ((np = fallpos(&mp, FALSE, 2)) != NULL &&
+                         mvwinch(stdscr, np->y, np->x) == FLOOR) {
+                            item = new_item(sizeof *tp);
+                            tp = THINGPTR(item);
+                            new_monster(item, which_monster, np, FALSE);
+                            /*
+                             * See if we want to give it a treasure to 
+                             * carry around.
+                             */
+                            carry_obj(tp, monsters[tp->t_index].m_carry);
+                            tp->t_no_move = movement(tp);
+
+                            /*
+                             * If it has a fire, mark it
+                             */
+                            if (on(*tp, HASFIRE)) {
+                                register struct linked_list *fire_item;
+
+                                fire_item = creat_item();
+                                ldata(fire_item) = (char *) tp;
+                                attach(rp->r_fires, fire_item);
+                                rp->r_flags |= HASFIRE;
+                            }
+                    }
+            }
+        }
+    }
+}
+
+/*
+ * Given a room pointer and a pointer to a door, supposedly in that room,
+ * return the coordinates of the entrance to the doorway.
+ */
+
+coord *
+doorway(rp, door)
+register struct room *rp;
+register coord *door;
+{
+    register int misses = 0;
+    static coord answer;
+
+    /* Do we have decent parameters? */
+    if (rp == NULL || door == NULL) return(NULL);
+
+    /* Initialize the answer to be the door, then calculate the offset */
+    answer = *door;
+
+    /* Calculate the x-offset */
+    if (door->x == rp->r_pos.x) answer.x++;
+    else if (door->x == rp->r_pos.x + rp->r_max.x - 1) answer.x--;
+    else misses++;
+
+    /* Calculate the y-offset */
+    if (door->y == rp->r_pos.y) answer.y++;
+    else if (door->y == rp->r_pos.y + rp->r_max.y - 1) answer.y--;
+    else misses++;
+
+    if (misses <= 1) return(&answer);
+    else return(NULL);
+}
+
+/*
+ * Draw a box around a room
+ */
+
+draw_room(rp)
+register struct room *rp;
+{
+    register 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);
+    }
+}
+
+/*
+ * horiz:
+ *      draw a horizontal line
+ */
+
+horiz(cnt)
+register int cnt;
+{
+    while (cnt--)
+        addch(HORZWALL);
+}
+
+/*
+ * rnd_pos:
+ *      pick a random spot in a room
+ */
+
+rnd_pos(rp, cp)
+register struct room *rp;
+register coord *cp;
+{
+    cp->x = rp->r_pos.x + rnd(rp->r_max.x-2) + 1;
+    cp->y = rp->r_pos.y + rnd(rp->r_max.y-2) + 1;
+}
+
+
+
+/*
+ * roomin:
+ *      Find what room some coordinates are in. NULL means they aren't
+ *      in any room.
+ */
+
+struct room *
+roomin(cp)
+register coord *cp;
+{
+    register struct room *rp;
+
+    for (rp = rooms; rp < &rooms[MAXROOMS]; rp++)
+        if (inroom(rp, cp))
+            return rp;
+    return NULL;
+}
+
+/*
+ * vert:
+ *      draw a vertical line
+ */
+
+vert(cnt)
+register int cnt;
+{
+    register int x, y;
+
+    getyx(stdscr, y, x);
+    x--;
+    while (cnt--) {
+        move(++y, x);
+        addch(VERTWALL);
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xrogue/save.c	Tue Apr 21 08:55:20 2015 -0400
@@ -0,0 +1,304 @@
+/*
+    save.c - save and restore routines
+
+    XRogue: Expeditions into the Dungeons of Doom
+    Copyright (C) 1991 Robert Pietkivitch
+    All rights reserved.
+    
+    Based on "Advanced Rogue"
+    Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka and AT&T
+    All rights reserved.
+
+    Based on "Rogue: Exploring the Dungeons of Doom"
+    Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
+    All rights reserved.
+    
+    See the file LICENSE.TXT for full copyright and licensing information.
+*/
+
+#include <curses.h>
+#include <ctype.h>
+#include <sys/types.h>
+#include <signal.h>
+#include <fcntl.h>
+#include <errno.h>
+#include "rogue.h"
+#include "mach_dep.h"
+
+extern char version[];
+extern unsigned char encstr[];
+extern int big_endian;
+
+bool
+save_game()
+{
+    register FILE *savef;
+    register int c;
+    char buf[LINELEN];
+
+    /*
+     * get file name
+     */
+    mpos = 0;
+    if (file_name[0] != '\0')
+    {
+        msg("Save file (%s)? ", file_name);
+        do
+        {
+            c = wgetch(cw);
+            if (c == ESC) return(0);
+        } while (c != 'n' && c != 'N' && c != 'y' && c != 'Y');
+        mpos = 0;
+        if (c == 'y' || c == 'Y')
+        {
+            msg("File name: %s", file_name);
+            goto gotfile;
+        }
+    }
+    else
+        goto gotfile; /* must save to file restored from */
+
+    do
+    {
+        msg("File name: ");
+        mpos = 0;
+        buf[0] = '\0';
+        if (get_str(buf, msgw) == QUIT)
+        {
+            msg("");
+            return FALSE;
+        }
+        strcpy(file_name, buf);
+gotfile:
+
+        if ((savef = fopen(file_name, "wb")) == NULL)
+             msg(strerror(errno));
+    } while (savef == NULL);
+
+    msg("");
+    /*
+     * write out encrpyted file
+     */
+    if (save_file(savef) == FALSE) {
+        fclose(savef);
+        msg("Cannot create save file.");
+        unlink(file_name);
+        return(FALSE);
+    }
+    fclose(savef);
+    return(TRUE);
+}
+
+/*
+ * automatically save a file.  This is used if a HUP signal is recieved
+ */
+
+void
+auto_save(int sig)
+{
+    register FILE *savef = NULL;
+    register int i;
+	NOOP(sig);
+    for (i = 0; i < NSIG; i++)
+        signal(i, SIG_IGN);
+    if (file_name[0] != '\0'    && 
+        pstats.s_hpt > 0        &&
+        ((savef = fopen(file_name, "wb")) != NULL))
+        save_file(savef);
+    fclose(savef);
+    exit_game(EXIT_ENDWIN);
+}
+
+/*
+ * write the saved game on the file
+ */
+
+bool
+save_file(savef)
+register FILE *savef;
+{
+    int slines = LINES;
+    int scols = COLS;
+    int ret = FALSE;
+    int endian = 0x01020304;
+    big_endian = ( *((char *)&endian) == 0x01 );
+
+    wmove(cw, LINES-1, 0);
+    draw(cw);
+
+    encwrite(version,strlen(version)+1,savef);
+    rs_write_int(savef,slines);
+    rs_write_int(savef,scols);
+
+    ret = rs_save_file(savef);
+
+    return(ret);
+}
+
+restore(file, envp)
+register char *file;
+char **envp;
+{
+    register int inf;
+    extern char **environ;
+    char buf[LINELEN];
+    int endian = 0x01020304;
+    big_endian = ( *((char *)&endian) == 0x01 );
+
+    if (strcmp(file, "-r") == 0)
+        file = file_name;
+
+    if ((inf = open(file, O_RDONLY)) < 0)
+    {
+        perror(file);
+        return(-1);
+    }
+
+    fflush(stdout);
+
+    encread(buf, strlen(version) + 1, inf);
+
+    if (strcmp(buf, version) != 0)
+    {
+        printf("Sorry, saved game is out of date.\n");
+        return FALSE;
+    }
+
+    fflush(stdout);
+
+    rs_read_int(inf,&lines);
+    rs_read_int(inf,&cols);
+
+    initscr();
+
+    if (lines > LINES)
+    {
+        endwin();
+        printf("Sorry, original game was played on a screen with %d lines.\n",lines);
+        printf("Current screen only has %d lines. Unable to restore game\n",LINES);
+        return(FALSE);
+    }
+    if (cols > COLS)
+    {
+        endwin();
+        printf("Sorry, original game was played on a screen with %d columns.\n",cols);
+        printf("Current screen only has %d columns. Unable to restore game\n",COLS);
+        return(FALSE);
+    }
+
+    typeahead(-1);
+    setup();
+    cw = newwin(LINES, COLS, 0, 0);
+    mw = newwin(LINES, COLS, 0, 0);
+    hw = newwin(LINES, COLS, 0, 0);
+    msgw = newwin(4, cols, 0, 0);
+
+    keypad(cw, TRUE);
+    keypad(hw, TRUE);
+
+    if (rs_restore_file(inf) == FALSE)
+    {
+        endwin();
+        printf("Cannot restore file\n");
+        close(inf);
+        return(FALSE);
+    }
+
+    close(inf);
+
+    if (!wizard)
+        unlink(file);
+ 
+    mpos = 0;
+    environ = envp;
+    strcpy(file_name, file);
+    clearok(curscr, TRUE);
+    touchwin(cw);
+    wrefresh(cw);
+    msg("Welcome back!  --More-- ");
+    wait_for(' ');
+    msg("");
+    playit();
+
+    /*NOTREACHED*/
+	return(1);
+}
+
+#define ENCWBSIZ        1024
+
+/*
+ * perform an encrypted write
+ */
+
+long
+encwrite(start, size, outf)
+register char *start;
+register unsigned long size;
+register FILE *outf;
+{
+    register unsigned char *ep;
+    register int i = 0;
+    unsigned long num_written = 0;
+    char buf[ENCWBSIZ];
+    int ret;
+
+    ep = encstr;
+
+    while (size--)
+    {
+        buf[i++] = *start++ ^ *ep++;
+        if (*ep == '\0')
+           ep = encstr;
+
+        if (i == ENCWBSIZ || size == 0)
+        {
+            ret = (unsigned int) fwrite(buf, 1, i, outf);
+            if (ret > 0)
+               num_written += ret;
+
+            if (ret < i)
+                 return(num_written);
+
+            i = 0;
+        }
+    }
+    return(num_written);
+}
+
+#define ENCRBSIZ        32768
+
+/*
+ * perform an encrypted read
+ */
+
+long
+encread(start, size, inf)
+register char *start;
+register unsigned long size;
+int inf;
+{
+    register unsigned char *ep;
+    register int rd_siz;
+    register unsigned long total_read;
+
+    total_read = 0;
+    while (total_read < size) {
+        rd_siz = ENCRBSIZ;
+        rd_siz = ((size-total_read) > ENCRBSIZ) ? ENCRBSIZ : (size-total_read);
+        rd_siz = read(inf,&start[total_read],rd_siz);
+        if(rd_siz==-1 || rd_siz==0)
+                break;
+        total_read += rd_siz;
+    }
+    ep = encstr;
+
+    size = total_read;
+    while (size--)
+    {
+        *start++ ^= *ep++;
+        if (*ep == '\0')
+            ep = encstr;
+    }
+    return total_read;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xrogue/scrolls.c	Tue Apr 21 08:55:20 2015 -0400
@@ -0,0 +1,901 @@
+/*
+    scrolls.c - Functions for dealing with scrolls
+
+    XRogue: Expeditions into the Dungeons of Doom
+    Copyright (C) 1991 Robert Pietkivitch
+    All rights reserved.
+    
+    Based on "Advanced Rogue"
+    Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka and AT&T
+    All rights reserved.
+
+    Based on "Rogue: Exploring the Dungeons of Doom"
+    Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
+    All rights reserved.
+    
+    See the file LICENSE.TXT for full copyright and licensing information.
+*/
+
+#include <curses.h>
+#include <ctype.h>
+#include "rogue.h"
+
+/*
+ * let the hero get rid of some type of monster 
+ */
+
+genocide()
+{
+    register struct linked_list *ip;
+    register struct thing *mp;
+    register struct linked_list *nip;
+                             /* cannot genocide any uniques */
+    register int num_monst = NUMMONST-NUMUNIQUE-NUMDINOS;
+    register int which_monst;
+
+    which_monst = makemonster(FALSE, "wipe out");
+    if (which_monst <= 0 || which_monst >= num_monst) {
+        msg("");
+        return;
+    }
+
+    /* Remove this monster from the present level */
+    for (ip = mlist; ip; ip = nip) {
+        mp = THINGPTR(ip);
+        nip = next(ip);
+        if (mp->t_index == which_monst) {
+            killed(ip, FALSE, FALSE, TRUE);
+        }
+    }
+
+    /* Remove from available monsters */
+    monsters[which_monst].m_normal = FALSE;
+    monsters[which_monst].m_wander = FALSE;
+    mpos = 0;
+    msg("You have wiped out the %s.", monsters[which_monst].m_name);
+}
+
+read_scroll(which, flag, is_scroll)
+register int which;
+int flag;
+bool is_scroll;
+{
+    register struct object *obj = NULL, *nobj;
+    register struct linked_list *item, *nitem;
+    register int i,j;
+    register unsigned char ch, nch;
+    bool cursed, blessed;
+
+    blessed = FALSE;
+    cursed = FALSE;
+    item = NULL;
+
+    if (which < 0) {
+        if (on(player, ISBLIND)) {
+            msg("You can't see to read anything!");
+            return;
+        }
+        if (on(player, ISINWALL)) {
+            msg("You can't see the scroll while inside rock!");
+            return;
+        }
+
+        /* This is a scroll or book. */
+        if (player.t_action != C_READ) {
+            int units;
+
+            item = get_item(pack, "read", READABLE, FALSE, FALSE);
+
+            /*
+             * Make certain that it is somethings that we want to read
+             */
+            if (item == NULL)
+                return;
+
+            /* How long does it take to read? */
+            units = usage_time(item);
+            if (units < 0) return;
+
+            player.t_using = item;      /* Remember what it is */
+            player.t_no_move = units * movement(&player);
+            if ((OBJPTR(item))->o_type == SCROLL) player.t_action = C_READ;
+            else player.t_action = C_USE;
+            return;
+        }
+
+        /* We have waited our time, let's quaff the potion */
+        item = player.t_using;
+        player.t_using = NULL;
+        player.t_action = A_NIL;
+
+        obj = OBJPTR(item);
+        /* remove it from the pack */
+        inpack--;
+        detach(pack, item);
+
+        msg("As you read the scroll, it vanishes.");
+        cursed = obj->o_flags & ISCURSED;
+        blessed = obj->o_flags & ISBLESSED;
+
+        which = obj->o_which;
+    }
+    else {
+        cursed = flag & ISCURSED;
+        blessed = flag & ISBLESSED;
+    }
+
+    switch (which) {
+        case S_CONFUSE: /* Scroll of monster confusion. Give him that power. */
+    {
+        register char *str;
+
+        switch (rnd(5)) {
+        case 0:
+            str = "glow red";
+        when 1:
+            str = "vibrate";
+        when 2:
+            str = "glow blue";
+        when 3:
+            str = "radiate green";
+        otherwise:
+            str = "itch with a strange desire";
+        }
+            msg("Your hands begin to %s. ", str);
+            turn_on(player, CANHUH);
+    }
+        when S_CURING:
+            /*
+             * A cure disease spell
+             */
+            if (on(player, HASINFEST) || 
+                on(player, HASDISEASE)|| 
+                on(player, DOROT)) {
+                if (on(player, HASDISEASE)) {
+                    extinguish(cure_disease);
+                    cure_disease();
+                }
+                if (on(player, HASINFEST)) {
+                    msg(terse ? "You feel yourself improving."
+                              : "You begin to feel yourself improving.");
+                    turn_off(player, HASINFEST);
+                    infest_dam = 0;
+                }
+                if (on(player, DOROT)) {
+                    msg("You feel your skin returning to normal.");
+                    turn_off(player, DOROT);
+                }
+            }
+            else {
+                /* msg(nothing); */
+                break;
+            }
+            if (is_scroll) s_know[S_CURING] = TRUE;
+        when S_LIGHT:
+            if (blue_light(blessed, cursed) && is_scroll)
+                s_know[S_LIGHT] = TRUE;
+        when S_HOLD:
+            if (cursed) {
+                /*
+                 * This scroll aggravates all the monsters on the current
+                 * level and sets them running towards the hero
+                 */
+                msg("You hear a high-pitched humming noise.");
+                /* protect good charactors */
+                if (player.t_ctype == C_PALADIN ||
+                    player.t_ctype == C_RANGER  || player.t_ctype == C_MONK) {
+                        msg("A chill runs up your spine! ");
+                        aggravate(TRUE, FALSE);
+                }
+                else {
+                    aggravate(TRUE, TRUE);
+                }
+            }
+            else if (blessed) { /* Hold all monsters on level */
+                if (mlist == NULL) msg(nothing);
+                else {
+                    register struct linked_list *mon;
+                    register struct thing *th;
+
+                    for (mon = mlist; mon != NULL; mon = next(mon)) {
+                        th = THINGPTR(mon);
+                        turn_off(*th, ISRUN);
+                        turn_on(*th, ISHELD);
+                        turn_off(*th, ISCHARMED);
+                    }
+                    if (levtype == OUTSIDE)
+                        msg("A sudden peace comes over the land.. ");
+                    else
+                        msg("A sudden peace comes over the dungeon.. ");
+                }
+            }
+            else {
+                /*
+                 * Hold monster scroll.  Stop all monsters within two spaces
+                 * from chasing after the hero.
+                 */
+                    register int x,y;
+                    register struct linked_list *mon;
+                    bool gotone=FALSE;
+
+                    for (x = hero.x-2; x <= hero.x+2; x++) {
+                        for (y = hero.y-2; y <= hero.y+2; y++) {
+                            if (y < 1 || x < 0 || y > lines - 3 || x > cols - 1)
+                                continue;
+                            if (isalpha(mvwinch(mw, y, x))) {
+                                if ((mon = find_mons(y, x)) != NULL) {
+                                    register struct thing *th;
+
+                                    gotone = TRUE;
+                                    th = THINGPTR(mon);
+                                    turn_off(*th, ISRUN);
+                                    turn_on(*th, ISHELD);
+                                    turn_off(*th, ISCHARMED);
+                                }
+                            }
+                        }
+                    }
+                    if (gotone) msg("A sudden peace surrounds you.");
+                    else msg(nothing);
+            }
+        when S_SLEEP:
+            /*
+             * if cursed, you fall asleep
+             */
+            if (is_scroll) s_know[S_SLEEP] = TRUE;
+            if (cursed) {
+                if (ISWEARING(R_ALERT))
+                    msg("You feel drowsy for a moment.");
+                else {
+                    msg("You fall asleep.");
+                    player.t_no_move += movement(&player)*(4 + rnd(SLEEPTIME));
+                    player.t_action = A_FREEZE;
+                }
+            }
+            else {
+                /*
+                 * sleep monster scroll.  
+                 * puts all monsters within 2 spaces asleep
+                 */
+                    register int x,y;
+                    register struct linked_list *mon;
+                    bool gotone=FALSE;
+
+                    for (x = hero.x-2; x <= hero.x+2; x++) {
+                        for (y = hero.y-2; y <= hero.y+2; y++) {
+                            if (y < 1 || x < 0 || y > lines - 3 || x > cols - 1)
+                                continue;
+                            if (isalpha(mvwinch(mw, y, x))) {
+                                if ((mon = find_mons(y, x)) != NULL) {
+                                    register struct thing *th;
+
+                                    th = THINGPTR(mon);
+                                    if (on(*th, ISUNDEAD))
+                                        continue;
+                                    th->t_no_move += movement(th)*(SLEEPTIME+4);
+                                    th->t_action = A_FREEZE;
+                                    gotone = TRUE;
+                                }
+                            }
+                        }
+                    }
+                    if (gotone) 
+                        msg("The monster(s) around you seem to have fallen asleep!");
+                    else 
+                        msg(nothing);
+            }
+        when S_CREATE:
+            /*
+             * Create a monster
+             * First look in a circle around him, next try his room
+             * otherwise give up
+             */
+            creat_mons(&player, (short) 0, TRUE);
+            light(&hero);
+        when S_IDENT:
+            /* 
+             * if its blessed then identify everything in the pack
+             */
+            if (blessed) {
+                msg("You feel more Knowledgeable!");
+                idenpack();
+            }
+            else {
+                /*
+                 * Identify, let the rogue figure something out
+                 */
+                if (is_scroll && s_know[S_IDENT] != TRUE) {
+                    msg("This scroll is an identify scroll");
+                }
+                whatis((struct linked_list *)NULL);
+            }
+            if (is_scroll) s_know[S_IDENT] = TRUE;
+        when S_MAP:
+            /*
+             * Scroll of magic mapping.
+             */
+            if (blessed) {
+                register int i;
+
+                if (is_scroll && s_know[S_MAP] != TRUE)
+                    s_know[S_MAP] = TRUE;
+                  /* light rooms */
+                for (i=0; i<MAXROOMS; i++){
+                    rooms[i].r_flags &= ~ISDARK;
+                }
+
+                msg("This scroll has a very detailed map on it!  --More--");
+                wait_for(' ');
+                overwrite(stdscr, hw);
+                overlay(stdscr, cw);    /* wizard CTRL(F) */
+                overlay(mw, cw);        /* wizard CTRL(X) */
+                draw(cw);
+                goto map_jump;          /* skip over regular mapping routine */
+            }
+            if (is_scroll && s_know[S_MAP] != TRUE) {
+                msg("Oh, now this scroll has a map on it.");
+                s_know[S_MAP] = TRUE;
+            }
+            overwrite(stdscr, hw);
+            /*
+             * Take all the things we want to keep hidden out of the window
+             */
+            for (i = 1; i < lines-2; i++)
+                for (j = 0; j < cols; j++)
+                {
+                    switch (nch = ch = mvwinch(hw, i, j))
+                    {
+                        case SECRETDOOR:
+                            nch = secretdoor (i, j);
+                            break;
+                        case HORZWALL:
+                        case VERTWALL:
+                        case DOOR:
+                        case PASSAGE:
+                        case ' ':
+                        case STAIRS:
+                            if (mvwinch(mw, i, j) != ' ')
+                            {
+                                register struct thing *it;
+
+                                it = THINGPTR(find_mons(i, j));
+                                if (it && 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);
+            map_jump:           /* blessed map jump from above */
+        when S_GFIND:
+            /*
+             * Scroll of gold detection
+             */
+            {
+                int gtotal = 0;
+
+                if (is_scroll) s_know[S_GFIND] = TRUE;
+                wclear(hw);
+                for (nitem = lvl_obj; nitem != NULL; nitem = next(nitem)) {
+                    nobj = OBJPTR(nitem);
+                    if (nobj->o_type == GOLD) {
+                        gtotal += nobj->o_count;
+                        mvwaddch(hw, nobj->o_pos.y, nobj->o_pos.x, GOLD);
+                    }
+                }
+                for (nitem = mlist; nitem != NULL; nitem = next(nitem)) {
+                    register struct linked_list *gitem;
+                    register struct thing *th;
+
+                    th = THINGPTR(nitem);
+                    if (on(*th, NODETECT)) continue;
+                    for(gitem = th->t_pack; gitem != NULL; gitem = next(gitem)){
+                        nobj = OBJPTR(gitem);
+                        if (nobj->o_type == GOLD) {
+                            gtotal += nobj->o_count;
+                            mvwaddch(hw, th->t_pos.y, th->t_pos.x, GOLD);
+                        }
+                    }
+                }
+                if (gtotal) {
+                    rmmsg();
+                    overlay(hw,cw);
+                    draw(cw);
+                    msg("You begin to feel greedy.  You sense gold!");
+                    break;
+                }
+            }
+            msg("You begin to feel a pull downward..");
+        when S_TELEP:
+            /*
+             * Scroll of teleportation:
+             * Make him disappear and reappear
+             */
+            if (cursed) {
+                int old_max = cur_max;
+
+                turns = (vlevel * NLEVMONS) * LEVEL;
+                /* if (turns > 42000) turns = 42000; limit turns */
+                debug ("vlevel = %d  turns = %d", vlevel, turns);
+
+                level = rnd(201)+80;   /* cursed teleport range */
+
+                msg("You are banished to the lower regions! ");
+                new_level(NORMLEV);
+
+                status(TRUE);
+                mpos = 0;
+                if (old_max == cur_max) { /* if he's been here make it harder */
+                /* protect good charactors */
+                if (player.t_ctype == C_PALADIN ||
+                    player.t_ctype == C_RANGER  || player.t_ctype == C_MONK) {
+                        aggravate(TRUE, FALSE);
+                }
+                else {
+                    aggravate(TRUE, TRUE);
+                }
+                }
+            }
+            else if (blessed) {
+                int     old_level, 
+                        much = rnd(6) - 7;
+
+                old_level = level;
+                if (much != 0) {
+                    level += much;
+                    if (level < 1)
+                        level = 1;
+                    mpos = 0;
+                    cur_max = level;
+                    turns += much*LEVEL;
+                    if (turns < 0)
+                        turns = 0;
+                    new_level(NORMLEV);         /* change levels */
+                    if (level == old_level)
+                        status(TRUE);
+                    msg("You are whisked away to another region!");
+                }
+            }
+            else {
+                teleport();
+            }
+            if (is_scroll) s_know[S_TELEP] = TRUE;
+        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 (cursed) { /* curse all player's possessions */
+                for (nitem = pack; nitem != NULL; nitem = next(nitem)) {
+                    nobj = OBJPTR(nitem);
+                    if (nobj->o_flags & ISBLESSED) 
+                        nobj->o_flags &= ~ISBLESSED;
+                    else 
+                        nobj->o_flags |= ISCURSED;
+                }
+                msg("The smell of fire and brimstone fills the air!");
+        /* return; leaks item, go through end of function */
+            }
+            else if (blessed) {
+                for (nitem = pack; nitem != NULL; nitem = next(nitem)) {
+                    nobj = OBJPTR(nitem);
+                    nobj->o_flags &= ~ISCURSED;
+                }
+                msg("Your pack glistens brightly!");
+                do_panic(NULL);         /* this startles them */
+        /* return; leaks item, go through end of function */
+            }
+            else {
+                nitem = get_item(pack, "remove the curse on",ALL,FALSE,FALSE);
+                if (nitem != NULL) {
+                    nobj = OBJPTR(nitem);
+                    nobj->o_flags &= ~ISCURSED;
+                    msg("Removed the curse from %s",inv_name(nobj,TRUE));
+                }
+            }
+            if (is_scroll) s_know[S_REMOVE] = TRUE;
+        when S_PETRIFY:
+            switch (mvinch(hero.y, hero.x)) {
+                case WORMHOLE:
+                case TRAPDOOR:
+                case DARTTRAP:
+                case TELTRAP:
+                case ARROWTRAP:
+                case SLEEPTRAP:
+                case BEARTRAP:
+                    {
+                        register int i;
+
+                        /* Find the right trap */
+                        for (i=0; i<ntraps && !ce(traps[i].tr_pos, hero); i++);
+                        ntraps--;
+
+                        if (!ce(traps[i].tr_pos, hero))
+                            msg("What a strange trap!");
+                        else {
+                            while (i < ntraps) {
+                                traps[i] = traps[i + 1];
+                                i++;
+                            }
+                        }
+                    }
+                    goto pet_message;
+                case DOOR:
+                case SECRETDOOR:
+                case FLOOR:
+                case PASSAGE:
+pet_message:        msg("The dungeon begins to rumble and shake!");
+                    addch(WALL);
+
+                    /* If the player is phased, unphase him */
+                    if (on(player, CANINWALL)) {
+                        extinguish(unphase);
+                        turn_off(player, CANINWALL);
+                        msg("The dizzy feeling leaves you.");
+                    }
+
+                    /* Mark the player as in a wall */
+                    turn_on(player, ISINWALL);
+                    break;
+                default:
+                    msg(nothing);
+            }
+        when S_GENOCIDE:
+            msg("You have been granted the boon of genocide!  --More--");
+            wait_for(' ');
+            msg("");
+            genocide();
+            if (is_scroll) s_know[S_GENOCIDE] = TRUE;
+        when S_PROTECT: {
+            struct linked_list *ll;
+            struct object *lb;
+            bool did_it = FALSE;
+            msg("You are granted the power of protection.");
+            if ((ll=get_item(pack,"protect",PROTECTABLE,FALSE,FALSE)) != NULL) {
+                lb = OBJPTR(ll);
+                mpos = 0;
+                if (cursed) {
+                    switch(lb->o_type) {        /* ruin it completely */
+                        case RING: if (lb->o_ac > 0) {
+                                    if (is_current(lb)) {
+                                        switch (lb->o_which) {
+                                            case R_ADDWISDOM:
+                                                pstats.s_wisdom -= lb->o_ac;
+                                            when R_ADDINTEL:  
+                                                pstats.s_intel -= lb->o_ac;
+                                            when R_ADDSTR:
+                                                pstats.s_str -= lb->o_ac;
+                                            when R_ADDHIT:
+                                                pstats.s_dext -= lb->o_ac;
+                                        }
+                                    }
+                                    did_it = TRUE;
+                                        lb->o_ac = 0;
+                                }
+                        when ARMOR: if (lb->o_ac > 10) {
+                                        did_it = TRUE;
+                                        lb->o_ac = 10;
+                                    }
+                        when STICK: if (lb->o_charges > 0) {
+                                        did_it = TRUE;
+                                        lb->o_charges = 0;
+                                    }
+                        when WEAPON:if (lb->o_hplus > 0) {
+                                        did_it = TRUE;
+                                        lb->o_hplus = 0;
+                                    }
+                                    if (lb->o_dplus > 0) {
+                                        did_it = TRUE;
+                                        lb->o_dplus = 0;
+                                    }
+                    }
+                    if (lb->o_flags & ISPROT) {
+                        did_it = TRUE;
+                        lb->o_flags &= ~ISPROT;
+                    }
+                    if (lb->o_flags & ISBLESSED) {
+                        did_it = TRUE;
+                        lb->o_flags &= ~ISBLESSED;
+                    }
+                    if (did_it)
+                        msg("Your %s glows red for a moment",inv_name(lb,TRUE));
+                    else {
+                        msg(nothing);
+                        break;
+                    }
+                }
+                else  {
+                    lb->o_flags |= ISPROT;
+                    msg("Protected %s.",inv_name(lb,TRUE));
+                }
+            }
+            if (is_scroll) s_know[S_PROTECT] = TRUE;
+        }
+        when S_MAKEIT:
+            msg("You have been endowed with the power of creation!");
+            if (is_scroll) s_know[S_MAKEIT] = TRUE;
+            create_obj(TRUE, 0, 0);
+        when S_ALLENCH: {
+            struct linked_list *ll;
+            struct object *lb;
+            int howmuch, flags;
+            if (is_scroll && s_know[S_ALLENCH] == FALSE) {
+                msg("You are granted the power of enchantment.");
+                msg("You may enchant anything (weapon, ring, armor, scroll, potion)");
+            }
+            if ((ll = get_item(pack, "enchant", ALL, FALSE, FALSE)) != NULL) {
+                lb = OBJPTR(ll);
+                lb->o_flags &= ~ISCURSED;
+                if (blessed) {
+                    howmuch = 2;
+                    flags = ISBLESSED;
+                }
+                else if (cursed) {
+                    howmuch = -1;
+                    flags = ISCURSED;
+                }
+                else {
+                    howmuch = 1;
+                    flags = ISBLESSED;
+                }
+                switch(lb->o_type) {
+                    case RING:
+                        if (lb->o_ac + howmuch > MAXENCHANT) {
+                            msg("The enchantment doesn't seem to work!");
+                            break;
+                        }
+                        lb->o_ac += howmuch;
+                        if (lb==cur_ring[LEFT_1]  || lb==cur_ring[LEFT_2]  ||
+                            lb==cur_ring[LEFT_3]  || lb==cur_ring[LEFT_4]  ||
+                            lb==cur_ring[RIGHT_1] || lb==cur_ring[RIGHT_2] ||
+                lb==cur_ring[RIGHT_3] || lb==cur_ring[RIGHT_4]) {
+                            switch (lb->o_which) {
+                                case R_ADDWISDOM: pstats.s_wisdom += howmuch;
+                                when R_ADDINTEL:  pstats.s_intel  += howmuch;
+                                when R_ADDSTR:    pstats.s_str    += howmuch;
+                                when R_ADDHIT:    pstats.s_dext   += howmuch;
+                            }
+                        }
+                        msg("Enchanted %s.",inv_name(lb,TRUE));
+                    when ARMOR:
+                        if ((armors[lb->o_which].a_class - lb->o_ac) +
+                            howmuch > MAXENCHANT) {
+                            msg("The enchantment doesn't seem to work!");
+                            break;
+                        }
+                        else
+                            lb->o_ac -= howmuch;
+                        msg("Enchanted %s.",inv_name(lb,TRUE));
+                    when STICK:
+                        lb->o_charges += rnd(16)+10;
+                        if (lb->o_charges < 0)
+                            lb->o_charges = 0;
+                        if (EQUAL(ws_type[lb->o_which], "staff")) {
+                            if (lb->o_charges > 200) 
+                                lb->o_charges = 200;
+                        }
+                        else {
+                            if (lb->o_charges > 200)  /* make em the same */
+                                lb->o_charges = 200;
+                        }
+                        msg("Enchanted %s.",inv_name(lb,TRUE));
+                    when WEAPON:
+                        if(lb->o_hplus+lb->o_dplus+howmuch > MAXENCHANT * 2){
+                            msg("The enchantment doesn't seem to work!");
+                            break;
+                        }
+                        if (rnd(100) < 50)
+                            lb->o_hplus += howmuch;
+                        else
+                            lb->o_dplus += howmuch;
+                        msg("Enchanted %s.",inv_name(lb,TRUE));
+                    when MM:
+                        switch (lb->o_which) {
+                            case MM_BRACERS:
+                                if (lb->o_ac + howmuch > MAXENCHANT) {
+                                   msg("The enchantment doesn't seem to work!");
+                                   break;
+                                }
+                                else lb->o_ac += howmuch;
+                                msg("Enchanted %s.",inv_name(lb,TRUE));
+                            when MM_PROTECT:
+                                if (lb->o_ac + howmuch > MAXENCHANT) {
+                                   msg("The enchantment doesn't seem to work!");
+                                   break;
+                                }
+                                else lb->o_ac += howmuch;
+                                msg("Enchanted %s.",inv_name(lb,TRUE));
+                        }
+                        lb->o_flags |= flags;
+                    when POTION:
+                    case SCROLL:
+                    default:
+                        lb->o_flags |= flags;
+                    msg("Enchanted %s.",inv_name(lb,TRUE));
+                }
+            }
+            if (is_scroll) s_know[S_ALLENCH] = TRUE;
+
+            /* If gotten here via prayer or Ankh, dock his wisdom. */
+            if (!is_scroll) {
+                pstats.s_wisdom--;
+        if (pstats.s_wisdom < 3) pstats.s_wisdom = 3;
+                msg("You feel a drain on your system. ");
+            }
+        }
+        when S_FINDTRAPS:
+            for (i=0; i<ntraps; i++) {
+                if (!(traps[i].tr_flags & ISFOUND)) {
+                    traps[i].tr_flags |= ISFOUND;
+                    if (cansee(traps[i].tr_pos.y, traps[i].tr_pos.x))
+                        mvwaddch(cw,traps[i].tr_pos.y,traps[i].tr_pos.x,
+                                 traps[i].tr_type);
+                }
+            }
+            if (ntraps > 0) {
+                msg("You sense the presence of traps.");
+                if (is_scroll) s_know[S_FINDTRAPS] = TRUE;
+            }
+            else
+                msg(nothing);
+
+        when S_RUNES:
+        {
+                register struct linked_list *sitem;
+
+                msg("The scroll explodes in a ball of fire!");
+                if (on(player, NOFIRE)) {
+                        msg("The fire does not seem to affect you.");
+                        break;
+                }
+                explode(&player);
+                if (pstats.s_hpt <= 0) {
+            pstats.s_hpt = -1;
+                    death(D_SCROLL);
+        }
+                for (sitem = pack; sitem != NULL; sitem = nitem) {
+                    nitem = next(sitem); /* in case we delete it */
+                    nobj = OBJPTR(sitem);
+                    /*
+                     * check for loss of all scrolls and give them
+                     * a save versus fire
+                     */
+                    if (nobj->o_type == SCROLL && roll(1,20) < 17) {
+                        msg("%s burns up!", inv_name(nobj, TRUE));
+                        inpack--;
+                        detach(pack, sitem);
+                        o_discard(sitem);
+                    }
+                }
+        }
+
+        when S_CHARM:
+        {
+            bool spots[9];
+            int x, y, spot, count, numcharmed, something, bonus;
+            struct linked_list *item;
+            register struct thing *tp;
+
+            /* Initialize the places where we look around us */
+            for (i=0; i<9; i++) spots[i] = FALSE;
+            count = 0;  /* No spots tried yet */
+            numcharmed = 0;     /* Nobody charmed yet */
+            something = 0;      /* Nothing has been seen yet */
+            bonus = 0;          /* no bonus yet */
+
+            /* Now look around us randomly for a charmee */
+            while (count < 9) {
+                do {
+                    spot = rnd(9);
+                } while (spots[spot] == TRUE);
+
+                /* We found a place */
+                count++;
+                spots[spot] = TRUE;
+                y = hero.y - 1 + (spot / 3);
+                x = hero.x - 1 + (spot % 3);
+
+                /* Be sure to stay on the board! */
+                if (x < 0 || x >= cols || (y < 1) || (y >= lines - 2))
+                        continue;
+
+                /* Is there a monster here? */
+                if (!isalpha(mvwinch(mw, y, x))) continue;
+
+                /* What kind is it? */
+                item = find_mons(y, x);
+                if (item == NULL) continue;
+
+                tp = THINGPTR(item);
+                if (on(*tp,ISCHARMED) || on(*tp,ISUNIQUE) || on(*tp,ISUNDEAD)) 
+                    continue;
+
+                /* Will the monster be charmed? */
+                if (blessed) bonus -= 3;
+                bonus -= (pstats.s_charisma - 12) / 3;
+                if ((player.t_ctype==C_PALADIN || player.t_ctype==C_RANGER) &&
+                    off(*tp, ISMEAN))
+                        bonus -= 3;
+                if (save(VS_MAGIC, tp, bonus)) continue;
+
+                /* We got him! */
+                numcharmed++;
+
+                /* Let the player know (maybe) */
+                if ((off(*tp, ISINVIS)     || on(player, CANSEE)) &&
+                    (off(*tp, ISSHADOW)    || on(player, CANSEE)) &&
+                    cansee(y, x)) {
+                        if (on(*tp, CANSURPRISE)) {
+                            turn_off(*tp, CANSURPRISE);
+                            msg("What the !? ");
+                        }
+                        msg("The eyes of %s glaze over!",
+                            prname(monster_name(tp), FALSE));
+                        something++;
+                }
+
+                /* Charm him and turn off any side effects */
+                turn_on(*tp, ISCHARMED);
+                runto(tp, &hero);
+                tp->t_action = A_NIL;
+
+                /* If monster was suffocating us, stop it */
+                if (on(*tp, DIDSUFFOCATE)) {
+                    turn_off(*tp, DIDSUFFOCATE);
+                    extinguish(suffocate);
+                }
+
+                /* If monster held us, stop it */
+                if (on(*tp, DIDHOLD) && (--hold_count == 0))
+                        turn_off(player, ISHELD);
+                turn_off(*tp, DIDHOLD);
+
+                /* If frightened of this monster, stop */
+                if (on(player, ISFLEE) &&
+                    player.t_dest == &tp->t_pos) turn_off(player, ISFLEE);
+
+                if ((blessed && numcharmed >= 5) || numcharmed > 0) break;
+            }
+
+            if (something == 0) msg(nothing);
+        }
+
+        otherwise:
+            msg("What a puzzling scroll!");
+            if (item != NULL) o_discard(item);
+            return;
+    }
+    look(TRUE, FALSE);  /* put the result of the scroll on the screen */
+    status(FALSE);
+    if (is_scroll && item && s_know[which] && s_guess[which])
+    {
+        free(s_guess[which]);
+        s_guess[which] = NULL;
+    }
+    else if (is_scroll                          && 
+             !s_know[which]                     && 
+             item                               &&
+             askme                              &&
+             (obj->o_flags & ISKNOW) == 0       &&
+             (obj->o_flags & ISPOST) == 0       &&
+             s_guess[which] == NULL) {
+        nameitem(item, FALSE);
+    }
+    if (item != NULL) o_discard(item);
+    updpack(TRUE, &player);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xrogue/state.c	Tue Apr 21 08:55:20 2015 -0400
@@ -0,0 +1,3366 @@
+/*
+    state.c - Portable Rogue Save State Code
+    
+    Copyright (C) 2000 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.
+*/
+
+#define RSXR_STATS        0xABCD0001
+#define RSXR_THING        0xABCD0002
+#define RSXR_OBJECT       0xABCD0003
+#define RSXR_MAGICITEMS   0xABCD0004
+#define RSXR_KNOWS        0xABCD0005
+#define RSXR_GUESSES      0xABCD0006
+#define RSXR_OBJECTLIST   0xABCD0007
+#define RSXR_BAGOBJECT    0xABCD0008
+#define RSXR_MONSTERLIST  0xABCD0009
+#define RSXR_MONSTERSTATS 0xABCD000A
+#define RSXR_MONSTERS     0xABCD000B
+#define RSXR_TRAP         0xABCD000C
+#define RSXR_WINDOW       0xABCD000D
+#define RSXR_DAEMONS      0xABCD000E
+#define RSXR_IWEAPS       0xABCD000F
+#define RSXR_IARMOR       0xABCD0010
+#define RSXR_SPELLS       0xABCD0011
+#define RSXR_ILIST        0xABCD0012
+#define RSXR_HLIST        0xABCD0013
+#define RSXR_DEATHTYPE    0xABCD0014
+#define RSXR_CTYPES       0XABCD0015
+#define RSXR_COORDLIST    0XABCD0016
+#define RSXR_ROOMS        0XABCD0017
+
+#if defined(_WIN32)
+#include <Windows.h>
+#include <Lmcons.h>
+#include <process.h>
+#include <shlobj.h>
+#include <Shlwapi.h>
+#undef VOID
+#undef MOUSE_MOVED
+#elif defined(__DJGPP__)
+#include <process.h>
+#else
+#include <pwd.h>
+#include <sys/utsname.h>
+#include <unistd.h>
+#endif
+
+#include <stdlib.h>
+#include <curses.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <assert.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <time.h>
+#include <signal.h>
+#include "rogue.h"
+#include "mach_dep.h"
+
+
+#define READSTAT ((format_error == 0) && (read_error == 0))
+#define WRITESTAT (write_error == 0)
+
+int read_error   = FALSE;
+int write_error  = FALSE;
+int format_error = FALSE;
+
+int save_debug = FALSE;
+#define DBG(x)   {if (save_debug) rsPrintf x;}
+
+int
+rsPrintf(char *fmt, ...)
+{
+    va_list ap;
+
+    va_start(ap, fmt);
+    vfprintf(stderr,fmt, ap);
+    va_end(ap); 
+
+    return(0);
+}
+
+
+void *
+get_list_item(struct linked_list *l, int i)
+{
+    int count = 0;
+
+    while(l != NULL)
+    {   
+        if (count == i)
+            return(l->l_data);
+                        
+        l = l->l_next;
+        
+        count++;
+    }
+    
+    return(NULL);
+}
+
+rs_write(FILE *savef, void *ptr, size_t size)
+{
+    size_t i = 0;
+    
+    if (!write_error)
+        i = ENCWRITE(ptr,size,savef);
+    if (i != size)
+        write_error = TRUE;
+
+    assert(write_error == 0);
+    return(WRITESTAT);
+}
+
+int end_of_file = FALSE;
+
+rs_read(int inf, void *ptr, size_t size)
+{
+    int actual;
+    end_of_file =FALSE;
+    if (!read_error && !format_error)
+    {
+        actual = ENCREAD(ptr, size, inf);
+
+        if ((actual == 0) && (size != 0))
+           end_of_file = TRUE;
+    }
+       
+    if (read_error){
+        printf("read error has occurred. restore short-circuited.\n");abort();}
+    if (format_error)
+        {printf("game format invalid. restore short-circuited.\n");abort();}
+
+    return(READSTAT);
+}
+
+int big_endian = 0;
+
+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);
+
+    return(WRITESTAT);
+}
+
+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);
+
+    return(WRITESTAT);
+}
+
+rs_write_ulong(FILE *savef, unsigned long 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);
+
+    return(WRITESTAT);
+}
+
+rs_write_long(FILE *savef, long 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);
+
+    return(WRITESTAT);
+}
+
+rs_write_boolean(FILE *savef, bool c)
+{
+    char buf;
+    
+    if (c == 0)
+        buf = 0;
+    else
+        buf = 1;
+    
+    rs_write(savef, &buf, 1);
+
+    return(WRITESTAT);
+}
+
+rs_read_int(int inf, int *i)
+{
+    char bytes[4];
+    int  input;
+    char *buf = (char *)&input;
+    
+    rs_read(inf, &input, 4);
+
+    if (big_endian)
+    {
+        bytes[3] = buf[0];
+        bytes[2] = buf[1];
+        bytes[1] = buf[2];
+        bytes[0] = buf[3];
+        buf = bytes;
+    }
+    
+    *i = *((int *) buf);
+
+    return(READSTAT);
+}
+
+rs_read_uint(int inf, unsigned int *i)
+{
+    char bytes[4];
+    int  input;
+    char *buf = (char *)&input;
+    
+    rs_read(inf, &input, 4);
+
+    if (big_endian)
+    {
+        bytes[3] = buf[0];
+        bytes[2] = buf[1];
+        bytes[1] = buf[2];
+        bytes[0] = buf[3];
+        buf = bytes;
+    }
+    
+    *i = *((int *) buf);
+
+    return(READSTAT);
+}
+
+rs_read_ulong(int inf, unsigned long *i)
+{
+    char bytes[4];
+    unsigned long input;
+    char *buf = (char *) &input;
+    
+    rs_read(inf, &input, 4);
+
+    if (big_endian)
+    {
+        bytes[3] = buf[0];
+        bytes[2] = buf[1];
+        bytes[1] = buf[2];
+        bytes[0] = buf[3];
+        buf = bytes;
+    }
+    
+    *i = *((unsigned long *) buf);
+    return(READSTAT);
+}
+
+rs_read_long(int inf, long *i)
+{
+    char bytes[4];
+    long input;
+    char *buf = (char *) &input;
+    
+    rs_read(inf, &input, 4);
+
+    if (big_endian)
+    {
+        bytes[3] = buf[0];
+        bytes[2] = buf[1];
+        bytes[1] = buf[2];
+        bytes[0] = buf[3];
+        buf = bytes;
+    }
+    
+    *i = *((long *) buf);
+    return(READSTAT);
+}
+
+rs_read_boolean(int inf, bool *i)
+{
+    char buf;
+    
+    rs_read(inf, &buf, 1);
+    
+    *i = buf;
+    
+    return(READSTAT);
+}
+
+rs_write_ints(FILE *savef, int *c, int count)
+{
+    int n=0;
+
+    rs_write_int(savef,count);
+    
+    for(n=0;n<count;n++)
+        rs_write_int(savef,c[n]);
+
+    return(WRITESTAT);
+}
+
+rs_write_short(FILE *savef, short c)
+{
+    char bytes[2];
+    char *buf = (char *) &c;
+    
+    if (big_endian)
+    {
+        bytes[1] = buf[0];
+        bytes[0] = buf[1];
+        buf = bytes;
+    }
+    
+    rs_write(savef, buf, 2);
+
+    return(WRITESTAT);
+}
+
+rs_read_short(int inf, short *s)
+{
+    char  bytes[2];
+    short input;
+    char *buf = (char *)&input;
+    
+    rs_read(inf, &input, 2);
+
+    if (big_endian)
+    {
+        bytes[1] = buf[0];
+        bytes[0] = buf[1];
+        buf = bytes;
+    }
+    
+    *s = *((short *) buf);
+    return(READSTAT);
+}
+
+
+rs_write_shorts(FILE *savef, short *c, int count)
+{
+    int n=0;
+
+    rs_write_int(savef,count);
+    
+    for(n=0;n<count;n++)
+        rs_write_short(savef,c[n]);
+
+    return(WRITESTAT);
+}
+
+rs_write_longs(FILE *savef, long *c, int count)
+{
+    int n=0;
+
+    rs_write_int(savef,count);
+    
+    for(n=0;n<count;n++)
+        rs_write_long(savef,c[n]);
+
+    return(WRITESTAT);
+}
+
+rs_write_ulongs(FILE *savef, unsigned long *c, int count)
+{
+    int n=0;
+
+    rs_write_int(savef,count);
+    
+    for(n=0;n<count;n++)
+        rs_write_ulong(savef,c[n]);
+
+    return(WRITESTAT);
+}
+
+rs_write_booleans(FILE *savef, bool *c, int count)
+{
+    int n=0;
+
+    rs_write_int(savef,count);
+    
+    for(n=0;n<count;n++)
+        rs_write_boolean(savef,c[n]);
+
+    return(WRITESTAT);
+}
+
+rs_read_ints(int inf, int *i, int count)
+{
+    int n=0,value=0;
+    
+    if (rs_read_int(inf,&value) != 0)
+    {
+        if (value != count)
+            format_error = TRUE;
+        else
+        {
+            for(n=0;n<value;n++)
+                rs_read_int(inf, &i[n]);
+        }
+    }
+    
+    return(READSTAT);
+}
+
+rs_read_shorts(int inf, short *i, int count)
+{
+    int n=0,value=0;
+    
+    if (rs_read_int(inf,&value) != 0)
+    {
+        if (value != count)
+            format_error = TRUE;
+        else
+        {
+            for(n=0;n<value;n++)
+                rs_read_short(inf, &i[n]);
+        }
+    }
+    
+    return(READSTAT);
+}
+
+rs_read_longs(int inf, long *i, int count)
+{
+    int n=0,value=0;
+    
+    if (rs_read_int(inf,&value) != 0)
+    {
+        if (value != count)
+            format_error = TRUE;
+        else
+        {
+            for(n=0;n<value;n++)
+                rs_read_long(inf, &i[n]);
+        }
+    }
+    
+    return(READSTAT);
+}
+
+rs_read_ulongs(int inf, unsigned long *i, int count)
+{
+    int n=0,value=0;
+    
+    if (rs_read_int(inf,&value) != 0)
+    {
+        if (value != count)
+            format_error = TRUE;
+        else
+        {
+            for(n=0;n<value;n++)
+                rs_read_ulong(inf, &i[n]);
+        }
+    }
+    
+    return(READSTAT);
+}
+
+rs_read_booleans(int inf, bool *i, int count)
+{
+    int n=0,value=0;
+    
+    if (rs_read_int(inf,&value) != 0)
+    {
+        if (value != count)
+            format_error = TRUE;
+        else
+        {
+            for(n=0;n<value;n++)
+                rs_read_boolean(inf, &i[n]);
+        }
+    }
+    
+    return(READSTAT);
+}
+
+rs_write_levtype(FILE *savef, LEVTYPE c)
+{
+    int lt;
+    
+    switch(c)
+    {
+        case NORMLEV: lt = 1; break;
+        case POSTLEV: lt = 2; break;
+        case MAZELEV: lt = 3; break;
+        case OUTSIDE: lt = 4; break;
+        case STARTLEV: lt = 5; break;
+        default: lt = -1; break;
+    }
+    
+    rs_write_int(savef,lt);
+        
+    return(WRITESTAT);
+}
+
+rs_read_levtype(int inf, LEVTYPE *l)
+{
+    int lt;
+    
+    rs_read_int(inf, &lt);
+    
+    switch(lt)
+    {
+        case 1: *l = NORMLEV; break;
+        case 2: *l = POSTLEV; break;
+        case 3: *l = MAZELEV; break;
+        case 4: *l = OUTSIDE; break;
+        case 5: *l = STARTLEV; break;
+        default: *l = NORMLEV; break;
+    }
+    
+    return(READSTAT);
+}
+
+rs_write_char(FILE *savef, char c)
+{
+    rs_write(savef, &c, 1);
+    DBG(("%c",c));    
+    
+    return(WRITESTAT);
+}
+
+rs_read_char(int inf, char *c)
+{
+    rs_read(inf, c, 1);
+    
+    return(READSTAT);
+}
+
+rs_write_uchar(FILE *savef, unsigned char c)
+{
+    rs_write(savef, &c, 1);
+    DBG(("%c",c));    
+    
+    return(WRITESTAT);
+}
+
+rs_read_uchar(int inf, unsigned char *c)
+{
+    rs_read(inf, c, 1);
+    
+    return(READSTAT);
+}
+
+rs_write_string(FILE *savef, char *s)
+{
+    int len = 0;
+
+    len = (s == NULL) ? 0 : (int) strlen(s) + 1;
+
+    rs_write_uint(savef, (unsigned int) len);
+    rs_write(savef, s, len);
+            
+    return(WRITESTAT);
+}
+
+rs_read_string_index(int inf, struct words master[], int maxindex, char **str)
+{
+    int i;
+
+    if (rs_read_int(inf,&i) != 0)
+    {
+        if (i > maxindex)
+        {
+            printf("String index is out of range. %d > %d\n",      
+                i, maxindex);
+            printf("Sorry, invalid save game format\n");
+            format_error = TRUE;
+        }
+        else if (i >= 0)
+            *str = master[i].w_string;
+        else
+            *str = NULL;
+    }
+    return(READSTAT);
+}
+
+rs_write_string_index(FILE *savef, struct words master[], int maxindex, char *str)
+{
+    int i;
+
+    for(i = 0; i < maxindex; i++)
+    {
+        if (str == master[i].w_string)
+        {
+            rs_write_int(savef,i);
+            return(WRITESTAT);
+        }
+    }
+
+    rs_write_int(savef,-1);
+    return(WRITESTAT);
+}
+ 
+rs_read_scrolls(int inf)
+{
+    int i;
+
+    for(i = 0; i < MAXSCROLLS; i++)
+    {
+        rs_read_new_string(inf,&s_names[i]);
+        rs_read_boolean(inf,&s_know[i]);
+        rs_read_new_string(inf,&s_guess[i]);
+    }
+
+    return(READSTAT);
+}
+
+rs_write_scrolls(FILE *savef)
+{
+    int i;
+
+    for(i = 0; i < MAXSCROLLS; i++)
+    {
+        rs_write_string(savef,s_names[i]);
+        rs_write_boolean(savef,s_know[i]);
+        rs_write_string(savef,s_guess[i]);
+    }
+    return(READSTAT);
+}
+
+rs_read_potions(int inf)
+{
+    int i;
+
+    for(i = 0; i < MAXPOTIONS; i++)
+    {
+        rs_read_string_index(inf,rainbow,NCOLORS,&p_colors[i]);
+        rs_read_boolean(inf,&p_know[i]);
+        rs_read_new_string(inf,&p_guess[i]);
+    }
+
+    return(READSTAT);
+}
+
+rs_write_potions(FILE *savef)
+{
+    int i;
+
+    for(i = 0; i < MAXPOTIONS; i++)
+    {
+        rs_write_string_index(savef,rainbow,NCOLORS,p_colors[i]);
+        rs_write_boolean(savef,p_know[i]);
+        rs_write_string(savef,p_guess[i]);
+    }
+
+    return(WRITESTAT);
+}
+
+rs_read_rings(int inf)
+{
+    int i;
+
+    for(i = 0; i < MAXRINGS; i++)
+    {
+        rs_read_string_index(inf,stones,NSTONES,&r_stones[i]);
+        rs_read_boolean(inf,&r_know[i]);
+        rs_read_new_string(inf,&r_guess[i]);
+    }
+
+    return(READSTAT);
+}
+
+rs_write_rings(FILE *savef)
+{
+    int i;
+
+    for(i = 0; i < MAXRINGS; i++)
+    {
+        rs_write_string_index(savef,stones,NSTONES,r_stones[i]);
+        rs_write_boolean(savef,r_know[i]);
+        rs_write_string(savef,r_guess[i]);
+    }
+
+    return(WRITESTAT);
+}
+
+rs_read_misc(int inf)
+{
+    int i;
+
+    for(i = 0; i < MAXMM; i++)
+    {
+        rs_read_boolean(inf,&m_know[i]);
+        rs_read_new_string(inf,&m_guess[i]);
+    }
+
+    return(READSTAT);
+}
+
+rs_write_misc(FILE *savef)
+{
+    int i;
+
+    for(i = 0; i < MAXMM; i++)
+    {
+        rs_write_boolean(savef,m_know[i]);
+        rs_write_string(savef,m_guess[i]);
+    }
+
+    return(WRITESTAT);
+}
+
+rs_write_sticks(FILE *savef)
+{
+    int i;
+
+    for (i = 0; i < MAXSTICKS; i++)
+    {
+        if (strcmp(ws_type[i],"staff") == 0)
+        {
+            rs_write_int(savef,0);
+            rs_write_string_index(savef, wood, NWOOD, ws_made[i]);
+        }
+        else
+        {
+            rs_write_int(savef,1);
+            rs_write_string_index(savef, metal, NMETAL, ws_made[i]);
+        }
+        rs_write_boolean(savef, ws_know[i]);
+        rs_write_string(savef, ws_guess[i]);
+    }
+ 
+    return(WRITESTAT);
+}
+        
+rs_read_sticks(int inf)
+{
+    int i = 0, list = 0;
+
+    for(i = 0; i < MAXSTICKS; i++)
+    { 
+        rs_read_int(inf,&list);
+        if (list == 0)
+        {
+            rs_read_string_index(inf,wood,NWOOD,&ws_made[i]);
+            ws_type[i] = "staff";
+        }
+        else 
+        {
+            rs_read_string_index(inf,metal,NMETAL,&ws_made[i]);
+            ws_type[i] = "wand";
+        }
+        rs_read_boolean(inf, &ws_know[i]);
+        rs_read_new_string(inf, &ws_guess[i]);
+    }
+
+    return(READSTAT);
+}
+    
+rs_read_string(int inf, char *s, int max)
+{
+    int len = 0;
+
+    if (rs_read_int(inf, &len) != FALSE)
+    {
+        if (len > max)
+        {
+            printf("String too long to restore. %d > %d\n",len,max);
+            printf("Sorry, invalid save game format\n");
+            format_error = TRUE;
+        }
+    
+        rs_read(inf, s, len);
+    }
+    
+    return(READSTAT);
+}
+
+rs_read_new_string(int inf, char **s)
+{
+    int len=0;
+    char *buf=0;
+
+    if (rs_read_int(inf, &len) != 0)
+    {
+        if (len == 0)
+            *s = NULL;
+        else
+        { 
+            buf = malloc(len);
+
+            if (buf == NULL)            
+                read_error = TRUE;
+            else
+            {
+                rs_read(inf, buf, len);
+                *s = buf;
+            }
+        }
+    }
+
+    return(READSTAT);
+}
+
+rs_write_strings(FILE *savef, char *s[], int count)
+{
+    int len = 0;
+    int n = 0;
+
+    rs_write_int(savef,count);
+
+    for(n = 0; n < count; n++)
+    {
+        len = (s[n] == NULL) ? 0L : (int) strlen(s[n]) + 1;
+        rs_write_int(savef, len);
+        rs_write(savef, s[n], len);
+        DBG(("%s",s[n]));
+    }
+    
+    return(WRITESTAT);
+}
+
+rs_write_words(FILE *savef, struct words *w, int count)
+{
+    int n = 0;
+
+    rs_write_int(savef,count);
+
+    for(n = 0; n < count; n++)
+    {
+        rs_write(savef, w[n].w_string, sizeof(w[n].w_string));
+        DBG(("%s",w[n].w_string));
+    }
+    
+    return(WRITESTAT);
+}
+
+rs_read_words(int inf, struct words *w, int count)
+{
+    int n = 0;
+    int value = 0;
+
+    rs_read_int(inf,&value);
+
+    if (value != count)
+    {
+        printf("Incorrect number of words in block. %d != %d.",
+                value,count);
+        printf("Sorry, invalid save game format");
+        format_error = TRUE;
+    }
+    else for(n = 0; n < count; n++)
+    {
+        rs_read(inf, w[n].w_string, sizeof(w[n].w_string));
+    }
+    
+    return(READSTAT);
+}
+
+rs_read_new_strings(int inf, char **s, int count)
+{
+    int len   = 0;
+    int n     = 0;
+    int value = 0;
+    
+    if (rs_read_int(inf,&value) != 0)
+    {
+        if (value != count)
+        {
+            printf("Incorrect number of strings in block. %d > %d.",
+                value,count);
+            printf("Sorry, invalid save game format");
+            format_error = TRUE;
+        }
+        else
+            for(n=0; n<value; n++)
+            {
+                rs_read_int(inf, &len);
+            
+                if (len == 0)
+                    s[n]=0;
+                else 
+                {
+                    s[n] = malloc(len);
+                    rs_read(inf,s[n],len);
+                }
+            }
+    }
+    
+    return(READSTAT);
+}
+
+rs_write_coord(FILE *savef, coord *c)
+{
+    DBG(("X ="));
+    rs_write_int(savef, c->x);
+    DBG(("Y ="));
+    rs_write_int(savef, c->y);
+    
+    return(WRITESTAT);
+}
+
+rs_read_coord(int inf, coord *c)
+{
+    rs_read_int(inf,&c->x);
+    rs_read_int(inf,&c->y);
+    
+    return(READSTAT);
+}
+
+struct delayed_action {
+    int d_type;
+    int (*d_func)();
+	union {
+		VOID *vp;
+		int  i;
+	} d_arg;
+    int d_time;
+};
+
+rs_write_daemons(FILE *savef, struct delayed_action *d_list,int count)
+{
+    int i = 0;
+    int func = 0;
+        
+    DBG(("Daemons\n"));
+    rs_write_int(savef, RSXR_DAEMONS);
+    rs_write_int(savef, count);
+        
+    for(i=0; i < count; i++)
+    {
+        if (d_list[i].d_func == rollwand)
+            func = 1;
+        else if (d_list[i].d_func == doctor)
+            func = 2;
+        else if (d_list[i].d_func == stomach)
+            func = 3;
+        else if (d_list[i].d_func == trap_look)
+            func = 4;
+        else if (d_list[i].d_func == eat_gold)
+            func = 5;
+        else if (d_list[i].d_func == ring_search)
+            func = 6;
+        else if (d_list[i].d_func == ring_teleport)
+            func = 7;
+        else if (d_list[i].d_func == fumble)
+            func = 8;
+        else if (d_list[i].d_func == strangle)
+            func = 9;
+        else if (d_list[i].d_func == unconfuse)
+            func = 10;
+        else if (d_list[i].d_func == swander)
+            func = 11;
+        else if (d_list[i].d_func == spell_recovery)
+            func = 12;
+        else if (d_list[i].d_func == chant_recovery)
+            func = 13;
+        else if (d_list[i].d_func == prayer_recovery)
+            func = 14;
+        else if (d_list[i].d_func == cure_disease)
+            func = 15;
+        else if (d_list[i].d_func == unstink)
+            func = 16;
+        else if (d_list[i].d_func == res_strength)
+            func = 17;
+        else if (d_list[i].d_func == undance)
+            func = 18;
+        else if (d_list[i].d_func == suffocate)
+            func = 19;
+        else if (d_list[i].d_func == wghtchk)
+            func = 20;
+        else if (d_list[i].d_func == dust_appear)
+            func = 21;
+        else if (d_list[i].d_func == unchoke)
+            func = 22;
+        else if (d_list[i].d_func == sight)
+            func = 23;
+        else if (d_list[i].d_func == changeclass)
+            func = 24;
+        else if (d_list[i].d_func == cloak_charge)
+            func = 25;
+        else if (d_list[i].d_func == quill_charge)
+            func = 26;
+        else if (d_list[i].d_func == nohaste)
+            func = 27;
+        else if (d_list[i].d_func == noslow)
+            func = 28;
+        else if (d_list[i].d_func == unclrhead)
+            func = 29;
+        else if (d_list[i].d_func == unsee)
+            func = 30;
+        else if (d_list[i].d_func == unphase)
+            func = 31;
+        else if (d_list[i].d_func == land)
+            func = 32;
+        else if (d_list[i].d_func == appear)
+            func = 33;
+        else if (d_list[i].d_func == unskill)
+            func = 34;
+        else if (d_list[i].d_func == nofire)
+            func = 35;
+        else if (d_list[i].d_func == nocold)
+            func = 36;
+        else if (d_list[i].d_func == nobolt)
+            func = 37;
+        else if (d_list[i].d_func == NULL)
+            func = 0;
+        else
+            func = -1;
+
+        rs_write_int(savef, d_list[i].d_type);
+        rs_write_int(savef, func);
+
+        if (d_list[i].d_func == doctor)
+           rs_write_int(savef, 1);
+        else if (d_list[i].d_func == eat_gold)
+        {
+            int index;
+            index = find_list_ptr(player.t_pack,d_list[i].d_arg.vp);
+            rs_write_int(savef,index);
+        }
+        else if (d_list[i].d_func == changeclass)
+        {
+            rs_write_int(savef, d_list[i].d_arg.i);
+        }
+        else if (d_list[i].d_func == cloak_charge)
+        {
+            int index;
+            index = find_list_ptr(player.t_pack,d_list[i].d_arg.vp);
+            rs_write_int(savef,index);
+        }
+        else
+            rs_write_int(savef, d_list[i].d_arg.i);
+
+		rs_write_int(savef, d_list[i].d_time);
+    }
+    
+    return(WRITESTAT);
+}       
+
+rs_read_daemons(int inf, struct delayed_action *d_list, int count)
+{
+    int i = 0;
+    int func = 0;
+    int value = 0;
+    int id = 0;
+    int dummy = 0;
+    
+    if (d_list == NULL)
+        printf("HELP THERE ARE NO DAEMONS\n");
+    
+    if (rs_read_int(inf, &id) != 0)
+    {
+        if (id != RSXR_DAEMONS)
+        {
+            printf("Invalid id. %x != %x(RSXR_DAEMONS)\n",
+                id,RSXR_DAEMONS);
+            printf("Sorry, invalid save game format");
+            format_error = TRUE;
+        }
+        else if (rs_read_int(inf, &value) != 0)
+        {
+            if (value > count)
+            {
+                printf("Incorrect number of daemons in block. %d > %d.",
+                    value,count);
+                printf("Sorry, invalid save game format");
+                format_error = TRUE;
+            }
+            else
+            {
+                for(i=0; i < value; i++)
+                {
+                    func = 0;
+                    rs_read_int(inf, &d_list[i].d_type);
+                    rs_read_int(inf, &func);
+                    
+                    switch(func)
+                    {
+                        case  1: d_list[i].d_func = rollwand;
+                                 break;
+                        case  2: d_list[i].d_func = doctor;
+                                 break;
+                        case  3: d_list[i].d_func = stomach;
+                                 break;
+                        case  4: d_list[i].d_func = trap_look;
+                                 break;
+                        case  5: d_list[i].d_func = eat_gold;
+                                 break;
+                        case  6: d_list[i].d_func = ring_search;
+                                 break;
+                        case  7: d_list[i].d_func = ring_teleport;
+                                 break;
+                        case  8: d_list[i].d_func = fumble;
+                                 break;
+                        case  9: d_list[i].d_func = strangle;
+                                 break;
+                        case 10: d_list[i].d_func = unconfuse;
+                                 break;
+                        case 11: d_list[i].d_func = swander;
+                                 break;
+                        case 12: d_list[i].d_func = spell_recovery;
+                                 break;
+                        case 13: d_list[i].d_func = chant_recovery;
+                                 break;
+                        case 14: d_list[i].d_func = prayer_recovery;
+                                 break;
+                        case 15: d_list[i].d_func = cure_disease;
+                                 break;
+                        case 16: d_list[i].d_func = unstink;
+                                 break;
+                        case 17: d_list[i].d_func = res_strength;
+                                 break;
+                        case 18: d_list[i].d_func = undance;
+                                 break;
+                        case 19: d_list[i].d_func = suffocate;
+                                 break;
+                        case 20: d_list[i].d_func = wghtchk;
+                                 break;
+                        case 21: d_list[i].d_func = dust_appear;
+                                 break;
+                        case 22: d_list[i].d_func = unchoke;
+                                 break;
+                        case 23: d_list[i].d_func = sight;
+                                 break;
+                        case 24: d_list[i].d_func = changeclass;
+                                 break;
+                        case 25: d_list[i].d_func = cloak_charge;
+                                 break;
+                        case 26: d_list[i].d_func = quill_charge;
+                                 break;
+                        case 27: d_list[i].d_func = nohaste;
+                                 break;
+                        case 28: d_list[i].d_func = noslow;
+                                 break;
+                        case 29: d_list[i].d_func = unclrhead;
+                                 break;
+                        case 30: d_list[i].d_func = unsee;
+                                 break;
+                        case 31: d_list[i].d_func = unphase;
+                                 break;
+                        case 32: d_list[i].d_func = land;
+                                 break;
+                        case 33: d_list[i].d_func = appear;
+                                 break;
+                        case 34: d_list[i].d_func = unskill;
+                                 break;
+                        case 35: d_list[i].d_func = nofire;
+                                 break;
+                        case 36: d_list[i].d_func = nocold;
+                                 break;
+                        case 37: d_list[i].d_func = nobolt;
+                                 break;
+						case 0:
+						case -1:
+                        default: d_list[i].d_func = NULL;
+                                 break;
+                    }
+
+                    if (d_list[i].d_func == doctor)
+                    {
+                        rs_read_int(inf, &dummy);
+                        d_list[i].d_arg.vp = (void *)&player;
+                    }
+                    else if (d_list[i].d_func == eat_gold)
+                    {
+                        rs_read_int(inf, &dummy);
+                        d_list[i].d_arg.vp = get_list_item(player.t_pack,dummy);
+                        if (d_list[i].d_arg.vp == NULL)
+                            d_list[i].d_type = 0;
+                    }
+                    else if (d_list[i].d_func == changeclass)
+                    {
+                        rs_read_int(inf, &d_list[i].d_arg.i);
+                    }
+                    else if (d_list[i].d_func == cloak_charge)
+                    {
+                        rs_read_int(inf, &dummy);
+                        d_list[i].d_arg.vp = get_list_item(player.t_pack,dummy);
+                        if (d_list[i].d_arg.vp == NULL)
+                            d_list[i].d_type = 0;
+                    }
+                    else
+                        rs_read_int(inf, &d_list[i].d_arg.i);
+
+                    rs_read_int(inf, &d_list[i].d_time);
+
+					if (d_list[i].d_func == NULL) 
+					{
+						d_list[i].d_time = 0;
+						d_list[i].d_arg.vp = NULL;
+						d_list[i].d_type = 0;
+					}
+
+                }
+            }
+        }
+    }
+    
+    return(READSTAT);
+}       
+        
+rs_write_rooms(FILE *savef, struct room r[], int count)
+{
+    int n = 0,i = -1;
+    struct linked_list *l;
+
+    DBG(("Rooms\n"));
+    rs_write_int(savef, RSXR_ROOMS);
+    rs_write_int(savef, count);
+    
+    for(n=0; n<count; n++)
+    {
+        rs_write_coord(savef, &r[n].r_pos);
+        rs_write_coord(savef, &r[n].r_max);
+        rs_write_long(savef, r[n].r_flags);
+        rs_write_coord_list(savef, r[n].r_exit);
+
+        l = r[n].r_fires;
+        i = list_size(l);
+        
+        rs_write_int(savef, i);
+
+        if (i >0)
+            while (l != NULL)
+            {
+                i = find_list_ptr(mlist,l->l_data);
+                rs_write_int(savef,i);
+                l = l->l_next;
+            }
+    }
+    return(WRITESTAT);
+}
+
+rs_read_rooms(int inf, struct room *r, int count)
+{
+    int value = 0, n = 0, i = 0, index = 0, id = 0;
+    struct linked_list *fires=NULL, *item = NULL;
+
+    if (rs_read_int(inf,&id) != 0)
+    {
+        if (id != RSXR_ROOMS)
+        {
+            printf("Invalid id. %x != %x(RSXR_ROOMS)\n",
+                id,RSXR_ROOMS);
+            printf("Sorry, invalid save game format");
+            format_error = TRUE;
+        }
+        else if (rs_read_int(inf,&value) != 0)
+        {
+            if (value != count)
+            {
+                printf("Incorrect number of rooms in block. %d > %d.",
+                    value,count);
+                printf("Sorry, invalid save game format");
+                format_error = TRUE;
+            }
+            else
+            {
+                for(n=0; n<value; n++)
+                {   
+                    rs_read_coord(inf,&r[n].r_pos);
+                    rs_read_coord(inf,&r[n].r_max);
+                    rs_read_long(inf,&r[n].r_flags);
+                    rs_read_coord_list(inf, &r[n].r_exit);
+
+                    rs_read_int(inf, &i);
+                    fires = NULL;
+                    while (i>0)
+                    {
+                        rs_read_int(inf,&index);
+                        
+                        if (index >= 0)
+                        {
+                            void *data;
+                            data = get_list_item(mlist,index);
+                            item = creat_item();
+                            item->l_data = data;
+                            if (fires == NULL)
+                                fires = item;
+                            else
+                                attach(fires,item);
+                        }
+                        i--;
+                    }
+                    r[n].r_fires=fires; 
+                }
+            }
+        }
+    }
+
+    return(READSTAT);
+}
+
+rs_write_object(FILE *savef, struct object *o)
+{
+    rs_write_int(savef, RSXR_OBJECT);
+    rs_write_int(savef, o->o_type);
+    rs_write_coord(savef, &o->o_pos);
+    rs_write_char(savef, o->o_launch);
+    rs_write(savef, o->o_damage, sizeof(o->o_damage));
+    rs_write(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_long(savef, o->o_flags);
+    rs_write_int(savef, o->o_group);
+    rs_write_int(savef, o->o_weight);
+    rs_write(savef, o->o_mark, MARKLEN);
+
+    DBG(("Object\n"));
+    DBG(("    SaveID  : %X\n",RSXR_OBJECT));
+    DBG(("    Type    : %d\n",o->o_type));
+    DBG(("    Pos     : %d %d\n",o->o_pos.x,o->o_pos.y));
+    DBG(("    Launch  : %c\n",o->o_launch));
+    DBG(("    Damage  : %s\n",o->o_damage));
+    DBG(("    Hurl    : %s\n",o->o_hurldmg));
+    DBG(("    Count   : %d\n",o->o_count));
+    DBG(("    Which   : %d\n",o->o_which));
+    DBG(("    HPlus   : %d\n",o->o_hplus));
+    DBG(("    DPlus   : %d\n",o->o_dplus));
+    DBG(("    AC      : %d\n",o->o_ac));
+    DBG(("    Flags   : %X\n",o->o_flags));
+    DBG(("    Group   : %d\n",o->o_group));
+    DBG(("    Weight  : %d\n",o->o_weight));
+    DBG(("    Mark    : %s\n",o->o_mark));
+    if (o->contents == NULL)
+    {
+        DBG(("    Contents: None\n"));
+    }
+    else
+    {
+        DBG(("    CONTENTS\n"));
+    }
+        
+    rs_write_object_list(savef, o->contents);
+    
+    if (o->contents != NULL)
+        DBG(("    END_CONTENTS\n"));
+    
+    return(WRITESTAT);
+}
+
+rs_read_object(int inf, struct object *o)
+{
+    int id;
+
+    if (rs_read_int(inf, &id) != 0)
+    {
+        if (id != RSXR_OBJECT)
+        {
+            printf("Invalid id. %x != %x(RSXR_OBJECT)\n", id,RSXR_OBJECT);
+            printf("Sorry, invalid save game format");
+            format_error = TRUE;
+        }
+        else
+        {
+            rs_read_int(inf, &o->o_type);
+            rs_read_coord(inf, &o->o_pos);
+            rs_read_char(inf, &o->o_launch);
+            rs_read(inf, o->o_damage,sizeof(o->o_damage));
+            rs_read(inf, o->o_hurldmg,sizeof(o->o_hurldmg));
+            rs_read_int(inf, &o->o_count);
+            rs_read_int(inf, &o->o_which);
+            rs_read_int(inf, &o->o_hplus);
+            rs_read_int(inf, &o->o_dplus);
+            rs_read_int(inf,&o->o_ac);
+            rs_read_long(inf,&o->o_flags);
+            rs_read_int(inf,&o->o_group);
+            rs_read_int(inf, &o->o_weight);
+            rs_read(inf, o->o_mark, MARKLEN);
+            rs_read_object_list(inf,&o->contents);
+
+        }
+    }
+
+    return(READSTAT);
+}
+
+rs_write_stats(FILE *savef, struct stats *s)
+{
+    DBG(("Stats\n"));
+    rs_write_int(savef, RSXR_STATS);
+    
+    rs_write_short(savef, s->s_str);
+    rs_write_short(savef, s->s_intel);
+    rs_write_short(savef, s->s_wisdom);
+    rs_write_short(savef, s->s_dext);
+    rs_write_short(savef, s->s_const);
+    rs_write_short(savef, s->s_charisma);
+    rs_write_ulong(savef, s->s_exp);
+    rs_write_int(savef, s->s_lvladj);
+    rs_write_int(savef, s->s_lvl);
+    rs_write_int(savef, s->s_arm);
+    rs_write_int(savef, s->s_hpt);
+    rs_write_int(savef, s->s_pack);
+    rs_write_int(savef, s->s_carry);
+    rs_write(savef, s->s_dmg, sizeof(s->s_dmg));
+
+    return(WRITESTAT);
+}
+
+rs_read_stats(int inf, struct stats *s)
+{
+    int id;
+
+    if (rs_read_int(inf, &id) != 0)
+    {
+        if (id != RSXR_STATS)
+        {
+            printf("Invalid id. %x != %x(RSXR_STATS)\n", id,RSXR_STATS);
+            printf("Sorry, invalid save game format");
+            format_error = TRUE;
+        }
+        else
+        {
+            rs_read_short(inf,&s->s_str);
+            rs_read_short(inf,&s->s_intel);
+            rs_read_short(inf,&s->s_wisdom);
+            rs_read_short(inf,&s->s_dext);
+            rs_read_short(inf,&s->s_const);
+            rs_read_short(inf,&s->s_charisma);
+            rs_read_ulong(inf,&s->s_exp);
+            rs_read_int(inf,&s->s_lvladj);
+            rs_read_int(inf,&s->s_lvl);
+            rs_read_int(inf,&s->s_arm);
+            rs_read_int(inf,&s->s_hpt);
+            rs_read_int(inf,&s->s_pack);
+            rs_read_int(inf,&s->s_carry);
+            rs_read(inf,s->s_dmg,sizeof(s->s_dmg));
+        }
+    }
+        
+    return(READSTAT);
+}
+
+rs_write_mstats(FILE *savef, struct mstats *s)
+{
+    DBG(("M-Stats\n"));
+    rs_write_int(savef, RSXR_STATS);
+    rs_write_short(savef, s->ms_str);
+    /*printf("    Strength: %d\n",s->ms_str);*/
+    rs_write_short(savef, s->ms_dex);
+    rs_write_short(savef, s->ms_move);
+    rs_write_ulong(savef, s->ms_exp);
+    rs_write_short(savef, s->ms_lvl);
+    rs_write_short(savef, s->ms_arm);
+    rs_write(savef, s->ms_hpt, sizeof(s->ms_hpt));
+    rs_write(savef, s->ms_dmg, sizeof(s->ms_dmg));
+    /*printf("    Damage: %s\n",s->ms_dmg);*/
+
+    return(WRITESTAT);
+}
+
+rs_read_mstats(int inf, struct mstats *s)
+{
+    int id;
+
+    if (rs_read_int(inf, &id) != 0)
+    {
+        if (id != RSXR_STATS)
+        {
+            printf("Invalid id. %x != %x(RSXR_STATS)\n", id,RSXR_STATS);
+            printf("Sorry, invalid save game format");
+            format_error = TRUE;
+        }
+        else
+        {
+            rs_read_short(inf,&s->ms_str);
+            /*printf("    Strength: %d\n",s->ms_str);*/
+            rs_read_short(inf,&s->ms_dex);
+            /*printf("    Dexterity: %d\n",s->ms_dex);*/
+            rs_read_short(inf,&s->ms_move);
+            /*printf("    Moves: %d\n",s->ms_move);*/
+            rs_read_ulong(inf,&s->ms_exp);
+            /*printf("    Experience: %d\n",s->ms_exp);*/
+            rs_read_short(inf,&s->ms_lvl);
+            /*printf("    Level: %d\n",s->ms_lvl);*/
+            rs_read_short(inf,&s->ms_arm);
+            /*printf("    Armor: %d\n",s->ms_arm);*/
+            rs_read(inf,s->ms_hpt,sizeof(s->ms_hpt));
+            /*printf("    HP: %s\n",s->ms_hpt);*/
+            rs_read(inf,s->ms_dmg,sizeof(s->ms_dmg));
+            /*printf("    Damage: %s\n",s->ms_dmg);*/
+        }
+    }
+    
+    return(READSTAT);
+}
+
+rs_write_init_weps(FILE *savef, struct init_weps *w, int count)
+{
+    int i;
+
+    DBG(("Init-Weps\n"));
+    rs_write_int(savef, RSXR_IWEAPS);
+    rs_write_int(savef, count);
+
+    for(i=0;i<count;i++)
+    {
+        rs_write(savef, w[i].w_name, sizeof(w[i].w_name));
+        rs_write(savef, w[i].w_dam, sizeof(w[i].w_dam));
+        rs_write(savef, w[i].w_hrl, sizeof(w[i].w_hrl));
+        rs_write_char(savef, w[i].w_launch);
+        rs_write_int(savef, w[i].w_flags);
+        rs_write_int(savef, w[i].w_rate);
+        rs_write_int(savef, w[i].w_wght);
+        rs_write_int(savef, w[i].w_worth);
+    }
+    return(WRITESTAT);
+}
+
+rs_read_init_weps(int inf, struct init_weps *w,int count)
+{
+    int id,value,i;
+
+    rs_read_int(inf, &id);
+    rs_read_int(inf, &value);
+
+    if (value != count)
+    {
+        printf("Incorrect number of init_weps in block. %d != %d.",
+                    value,count);
+        printf("Sorry, invalid save game format");
+        format_error = TRUE;
+    }
+    else for (i = 0; i < count; i++)
+    {
+        rs_read(inf, w[i].w_name, sizeof(w[i].w_name));
+        rs_read(inf, w[i].w_dam, sizeof(w[i].w_dam));
+        rs_read(inf, w[i].w_hrl, sizeof(w[i].w_hrl));
+        rs_read_char(inf, &w[i].w_launch);
+        rs_read_int(inf, &w[i].w_flags);
+        rs_read_int(inf, &w[i].w_rate);
+        rs_read_int(inf, &w[i].w_wght);
+        rs_read_int(inf, &w[i].w_worth);
+    }
+    return(READSTAT);
+}
+
+rs_write_init_armor(FILE *savef, struct init_armor *a, int count)
+{
+    int i;
+    DBG(("Init-Armor\n"));
+    rs_write_int(savef, RSXR_IARMOR);
+    rs_write_int(savef, count);
+    for(i=0;i<count;i++)
+    {
+        rs_write(savef, a[i].a_name, sizeof(a[i].a_name));
+        rs_write_int(savef, a[i].a_prob);
+        rs_write_int(savef, a[i].a_class);
+        rs_write_int(savef, a[i].a_worth);
+        rs_write_int(savef, a[i].a_wght);
+    }
+    return(WRITESTAT);
+}
+
+rs_read_init_armor(int inf, struct init_armor *a,int count)
+{
+    int id,value,i;
+
+    rs_read_int(inf, &id);
+    rs_read_int(inf, &value);
+
+    for(i=0;i<count;i++)
+    {
+        rs_read(inf, a[i].a_name, sizeof(a[i].a_name));
+        rs_read_int(inf, &a[i].a_prob);
+        rs_read_int(inf, &a[i].a_class);
+        rs_read_int(inf, &a[i].a_worth);
+        rs_read_int(inf, &a[i].a_wght);
+    }
+
+    return(READSTAT);
+}
+
+rs_write_spells(FILE *savef, struct spells *s, int count)
+{
+    int i;
+    DBG(("Spells\n"));
+    rs_write_int(savef, RSXR_SPELLS);
+    rs_write_int(savef, count);
+    for(i=0;i<count;i++)
+    {
+        rs_write_short(savef, s[i].s_which);
+        rs_write_short(savef, s[i].s_cost);
+        rs_write_short(savef, s[i].s_type);
+        rs_write_int(savef, s[i].s_flag);
+    }
+    return(WRITESTAT);
+}
+
+rs_read_spells(int inf, struct spells *s,int count)
+{
+    int id,value,i;
+
+    rs_read_int(inf, &id);
+    rs_read_int(inf, &value);
+
+    for(i=0;i<count;i++)
+    {
+        rs_read_short(inf, &s[i].s_which);
+        rs_read_short(inf, &s[i].s_cost);
+        rs_read_short(inf, &s[i].s_type);
+        rs_read_int(inf, &s[i].s_flag);
+    }
+    return(READSTAT);
+}
+
+rs_write_item_list(FILE *savef, struct item_list *i)
+{
+    DBG(("Item List\n"));
+    rs_write_int(savef, RSXR_ILIST);
+    rs_write_char(savef, i->item_ch);
+    rs_write(savef, i->item_desc, sizeof(i->item_desc));
+    return(WRITESTAT);
+}
+rs_read_item_list(int inf, struct item_list *i)
+{
+    int id;
+
+    rs_read_int(inf, &id);
+
+    rs_read_uchar(inf, &i->item_ch); 
+    rs_read(inf, i->item_desc,sizeof(i->item_desc));
+    return(READSTAT); 
+}
+
+rs_write_h_list(FILE *savef, struct h_list *h)
+{
+    DBG(("H List\n"));
+    rs_write_int(savef, RSXR_HLIST);
+    rs_write_char(savef, h->h_ch);
+    rs_write(savef, h->h_desc, sizeof(h->h_desc));
+    return(WRITESTAT);
+}
+
+rs_read_h_list(int inf, struct h_list *h)
+{
+    int id;
+
+    rs_read_int(inf, &id);
+
+    rs_read_char(inf, &h->h_ch);
+    rs_read(inf, h->h_desc,sizeof(h->h_desc));
+    return(READSTAT);
+}
+
+rs_write_death_types(FILE *savef, struct death_type *d,int count)
+{
+    int i;
+
+    DBG(("Death Types\n"));
+    rs_write_int(savef, RSXR_DEATHTYPE);
+    rs_write_int(savef, count);
+
+    for(i=0; i < count; i++)
+    {
+        rs_write_int(savef, d[i].reason);
+        rs_write(savef, d[i].name, sizeof(d[i].name));
+    }
+    return(WRITESTAT);
+}
+rs_read_death_types(int inf, struct death_type *d, int count)
+{
+    int id,value,i;
+
+    rs_read_int(inf, &id);
+    rs_read_int(inf, &value);
+    if (value != count)
+    {
+        printf("Incorrect number of death_types in block. %d > %d.",
+               value,count);
+        printf("Sorry, invalid save game format");
+        format_error = TRUE;
+    }
+    else for(i=0;i < count;i++)
+    {
+        rs_read_int(inf, &d[i].reason);
+        rs_read(inf, d[i].name,sizeof(d[i].name));
+    }
+    return(READSTAT);
+}
+
+rs_write_character_types(FILE *savef, struct character_types *c, int count)
+{
+    int i;
+
+    DBG(("Character Types\n"));
+    rs_write_int(savef, RSXR_CTYPES);
+    rs_write_int(savef,count);
+
+    for(i=0;i<count;i++)
+    {
+        rs_write(savef, c[i].name, sizeof(c[i].name));
+        rs_write_long(savef, c[i].start_exp);
+        rs_write_long(savef, c[i].cap);
+        rs_write_int(savef, c[i].hit_pts);
+        rs_write_int(savef, c[i].base);
+        rs_write_int(savef, c[i].max_lvl);
+        rs_write_int(savef, c[i].factor);
+        rs_write_int(savef, c[i].offset);
+        rs_write_int(savef, c[i].range);
+    }
+    return(WRITESTAT);
+}
+
+rs_read_character_types(int inf, struct character_types *c,int count)
+{
+    int id,value,i;
+
+    rs_read_int(inf, &id);
+    rs_read_int(inf, &value);
+
+    if (value != count)
+    {
+        printf("Incorrect number of character types in block. %d > %d.",
+               value,count);
+        printf("Sorry, invalid save game format");
+        format_error = TRUE;
+    }
+    else for (i = 0; i < count; i++)
+    {
+        rs_read(inf, c[i].name,sizeof(c[i].name));
+        rs_read_long(inf, &c[i].start_exp);
+        rs_read_long(inf, &c[i].cap);
+        rs_read_int(inf, &c[i].hit_pts);
+        rs_read_int(inf, &c[i].base);
+        rs_read_int(inf, &c[i].max_lvl);
+        rs_read_int(inf, &c[i].factor);
+        rs_read_int(inf, &c[i].offset);
+        rs_read_int(inf, &c[i].range);
+    }
+    return(READSTAT);
+}
+
+rs_write_traps(FILE *savef, struct trap *trap,int count)
+{
+    int n;
+
+    DBG(("Traps\n"));
+    rs_write_int(savef, RSXR_TRAP);
+    rs_write_int(savef, count);
+    
+    for(n=0; n<count; n++)
+    {
+        rs_write_char(savef, trap[n].tr_type);
+        rs_write_char(savef, trap[n].tr_show);
+        rs_write_coord(savef, &trap[n].tr_pos);
+        rs_write_long(savef, trap[n].tr_flags);
+    }
+}
+
+rs_read_traps(int inf, struct trap *trap, int count)
+{
+    int id = 0, value = 0, n = 0;
+
+    if (rs_read_int(inf,&id) != 0)
+    {
+        if (id != RSXR_TRAP)
+        {
+            printf("Invalid id. %x != %x(RSXR_TRAP)\n",
+                id,RSXR_TRAP);
+            printf("Sorry, invalid save game format");
+            format_error = TRUE;
+        }
+        else if (rs_read_int(inf,&value) != 0)
+        {
+            if (value != count)
+            {
+                printf("Incorrect number of traps in block. %d > %d.",
+                    value,count);
+                printf("Sorry, invalid save game format\n");
+                format_error = TRUE;
+            }
+            else
+            {
+                for(n=0;n<value;n++)
+                {   
+                    rs_read_uchar(inf,&trap[n].tr_type);
+                    rs_read_uchar(inf,&trap[n].tr_show);
+                    rs_read_coord(inf,&trap[n].tr_pos);
+                    rs_read_long(inf,&trap[n].tr_flags);
+                }
+            }
+        }
+        else
+            format_error = TRUE;
+    }
+    
+    return(READSTAT);
+}
+
+rs_write_monsters(FILE * savef, struct monster * m, int count)
+{
+    int n;
+    
+    DBG(("Monsters\n"));
+    rs_write_int(savef, RSXR_MONSTERS);
+    rs_write_int(savef, count);
+
+    for(n=0;n<count;n++)
+    {
+        rs_write(savef, m[n].m_name, sizeof(m[n].m_name));
+        /*printf("Monster: %s/%d/%d\n",m[n].m_name,sizeof(m[n].m_name),strlen(m[n].m_name));*/
+        rs_write_short(savef, m[n].m_carry);
+        rs_write_boolean(savef, m[n].m_normal);
+        rs_write_boolean(savef, m[n].m_wander);
+        rs_write_char(savef, m[n].m_appear);
+        rs_write(savef, m[n].m_intel,sizeof(m[n].m_intel));
+        rs_write_longs(savef, m[n].m_flags, MAXFLAGS);
+        rs_write(savef, m[n].m_typesum,sizeof(m[n].m_typesum));
+        rs_write_short(savef, m[n].m_numsum);
+        rs_write_short(savef, m[n].m_add_exp);
+
+        rs_write_mstats(savef, &m[n].m_stats);
+    }
+    
+    return(WRITESTAT);
+}
+
+rs_read_monsters(int inf, struct monster *m, int count)
+{
+    int id = 0, value = 0, n = 0;
+    char buffer[1024];
+
+    if (rs_read_int(inf, &id) != 0)
+    {
+        if (id != RSXR_MONSTERS)
+        {
+            printf("Invalid id. %x != %x(RSXR_MONSTERS)\n",
+                id,RSXR_MONSTERS);
+            printf("Sorry, invalid save game format");
+            format_error = TRUE;
+        }
+        else if (rs_read_int(inf, &value) != 0)
+        {
+            if (value != count)
+            {   printf("Incorrect number of monsters in block. %d != %d.",
+                    value,count);
+                printf("Sorry, invalid save game format\n");
+                format_error = TRUE;
+
+            }
+            else for(n=0;n<value;n++)
+            {
+                rs_read(inf, buffer,sizeof(m[n].m_name));
+                assert( strcmp(buffer,m[n].m_name) == 0);
+                /*printf("Monster: %s\n",m[n].m_name);*/
+                rs_read_short(inf, &m[n].m_carry);
+                /*printf("    Carry: %d\n",m[n].m_carry); */
+                rs_read_boolean(inf, &m[n].m_normal);
+                /*printf("    Normal: %d\n",m[n].m_normal);*/
+                rs_read_boolean(inf, &m[n].m_wander);
+                /*printf("    Wander: %d\n",m[n].m_wander);*/
+                rs_read_char(inf, &m[n].m_appear);
+                /*printf("    Appears: %c\n",m[n].m_appear);*/
+                rs_read(inf, m[n].m_intel,sizeof(m[n].m_intel));
+                /*printf("    Intelligence: %s\n",m[n].m_intel);*/
+                rs_read_longs(inf, m[n].m_flags, MAXFLAGS);
+                /*printf("    Flags: %X\n",m[n].m_flags);*/
+                rs_read(inf, m[n].m_typesum, sizeof(m[n].m_typesum));
+                /*printf("    Summons: %s\n",m[n].m_typesum);*/
+                rs_read_short(inf, &m[n].m_numsum);
+                /*printf("    # Summons: %d\n",m[n].m_numsum);*/
+                rs_read_short(inf, &m[n].m_add_exp);
+                /*printf("    Experience: %d\n",m[n].m_add_exp);*/
+                rs_read_mstats(inf, &m[n].m_stats);
+
+             }
+        }
+        else
+            format_error = TRUE;
+    }
+    
+    return(READSTAT);
+}
+
+/*****************************************************************************/
+
+rs_write_coord_list(FILE *savef, struct linked_list *l)
+{
+    DBG(("Coordinate List\n"));
+    rs_write_int(savef, RSXR_COORDLIST);
+    rs_write_int(savef, list_size(l));
+
+    while (l != NULL) 
+    {
+        rs_write_coord(savef, (coord *) l->l_data);
+        l = l->l_next;
+    }
+    
+    return(WRITESTAT);
+}
+
+rs_read_coord_list(int inf, struct linked_list **list)
+{
+    int id;
+    int i, cnt;
+    struct linked_list *l = NULL, *previous = NULL, *head = NULL;
+
+    if (rs_read_int(inf,&id) != 0)
+    {
+        if (id != RSXR_COORDLIST)
+        {
+            printf("Invalid id. %x != %x(RSXR_COORDLIST)\n",
+                id,RSXR_COORDLIST);
+            printf("Sorry, invalid save game format");
+            format_error = TRUE;
+        }
+    else if (rs_read_int(inf,&cnt) != 0)
+        {
+            for (i = 0; i < cnt; i++)
+            {
+                l = new_item(sizeof(coord));
+                l->l_prev = previous;
+                if (previous != NULL)
+                    previous->l_next = l;
+                rs_read_coord(inf,(coord *) l->l_data);
+                if (previous == NULL)
+                    head = l;
+                previous = l;
+            }
+            
+            if (l != NULL)
+                l->l_next = NULL;
+    
+            *list = head;
+        }
+        else
+            format_error = TRUE;
+    }
+    else
+        format_error = TRUE;
+
+    return(READSTAT);
+}
+
+rs_write_object_list(FILE *savef, struct linked_list *l)
+{
+    DBG(("Object List\n"));
+    rs_write_int(savef, RSXR_OBJECTLIST);
+    rs_write_int(savef, list_size(l));
+
+    while (l != NULL) 
+    {
+        rs_write_object(savef, (struct object *) l->l_data);
+        l = l->l_next;
+    }
+    
+    return(WRITESTAT);
+}
+
+rs_read_object_list(int inf, struct linked_list **list)
+{
+    int id;
+    int i, cnt;
+    struct linked_list *l = NULL, *previous = NULL, *head = NULL;
+
+    if (rs_read_int(inf,&id) != 0)
+    {
+        if (rs_read_int(inf,&cnt) != 0)
+        {
+            for (i = 0; i < cnt; i++) 
+            {
+                l = new_item(sizeof(struct object));
+                memset(l->l_data,0,sizeof(struct object));
+                l->l_prev = previous;
+                if (previous != NULL)
+                    previous->l_next = l;
+                rs_read_object(inf,(struct object *) l->l_data);
+                if (previous == NULL)
+                    head = l;
+                previous = l;
+            }
+            
+            if (l != NULL)
+                l->l_next = NULL;
+    
+            *list = head;
+        }
+        else
+            format_error = TRUE;
+    }
+    else
+        format_error = TRUE;
+
+
+    return(READSTAT);
+}
+
+int
+find_thing_coord(monlist, c)
+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(objlist, c)
+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);
+}
+
+rs_write_thing(FILE *savef, struct thing *t)
+{
+    int i = -1;
+
+    DBG(("Thing\n"));
+    rs_write_int(savef, RSXR_THING);
+    rs_write_boolean(savef,t->t_wasshot);
+    rs_write_char(savef, t->t_type);
+    rs_write_char(savef, t->t_disguise);
+    rs_write_char(savef, t->t_oldch);
+    rs_write_short(savef, t->t_ctype);
+    rs_write_short(savef, t->t_index);
+    rs_write_short(savef, t->t_no_move);
+    rs_write_short(savef, t->t_quiet);
+    rs_write_short(savef, t->t_movement);
+    rs_write_short(savef, t->t_action);
+    rs_write_short(savef, t->t_artifact);
+    rs_write_short(savef, t->t_wand);
+    rs_write_short(savef, t->t_summon);
+    rs_write_short(savef, t->t_cast);
+    rs_write_short(savef, t->t_breathe);
+
+    rs_write_string(savef,t->t_name);
+    rs_write_coord(savef, &t->t_doorgoal);
+
+    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
+            {
+                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_coord(savef, &t->t_pos);
+    rs_write_coord(savef, &t->t_oldpos);
+    rs_write_coord(savef, &t->t_newpos);
+    rs_write_ulongs(savef, t->t_flags, 16);
+
+    DBG(("Thing\n"));
+    DBG(("    SaveID  : %X\n",RSXR_THING));
+    DBG(("    Name    : %s\n",t->t_name));
+    DBG(("    WasShot : %d\n",t->t_wasshot));
+    DBG(("    Type    : %c(%d)\n",t->t_type,t->t_type));
+    DBG(("    Disguise: %c(%d)\n",t->t_disguise,t->t_disguise));
+    DBG(("    OldCh   : %c(%d)\n",t->t_oldch,t->t_oldch));
+    DBG(("    CType   : %d\n",t->t_ctype));
+    DBG(("    Index   : %d\n",t->t_index));
+    DBG(("    NoMove  : %d\n",t->t_no_move));
+    DBG(("    Quiet   : %d\n",t->t_quiet));
+    DBG(("    Movement: %d\n",t->t_movement));
+    DBG(("    Action  : %d\n",t->t_action));
+    DBG(("    Artifact: %d\n",t->t_artifact));
+    DBG(("    Wand    : %d\n",t->t_wand));
+    DBG(("    Summon  : %d\n",t->t_summon));
+    DBG(("    Cast    : %d\n",t->t_cast));
+    DBG(("    Breathe : %d\n",t->t_breathe));
+    DBG(("    DoorGoal: %d %d\n",t->t_doorgoal.x,t->t_doorgoal.y));
+    if (t->t_dest)
+    {
+        DBG(("    Dest    : %d %d\n",t->t_dest->x,t->t_dest->y));
+    }
+    else
+    {
+        DBG(("    Dest    : None\n"));
+    }
+    DBG(("    Pos     : %d %d\n",t->t_pos.x,t->t_pos.y));
+    DBG(("    OldPos  : %d %d\n",t->t_oldpos.x,t->t_oldpos.y));
+    DBG(("    NewPos  : %d %d\n",t->t_newpos.x,t->t_newpos.y));
+    DBG(("    Flags   : "));
+    { int i; for(i=0;i<16;i++) {DBG(("%d ",t->t_flags[i]));} DBG(("\n")); }
+
+    rs_write_object_list(savef, t->t_pack);
+    i = -1;
+    if (t->t_using != NULL)
+        i = find_list_ptr(t->t_pack, t->t_using->l_data);
+    rs_write_int(savef, i);
+    rs_write_stats(savef, &t->t_stats);
+    rs_write_stats(savef, &t->maxstats);
+    
+    return(WRITESTAT);
+}
+
+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;
+    }
+}
+
+rs_read_thing(int inf, struct thing *t)
+{
+    int id;
+    int listid = 0, index = -1;
+    struct linked_list *item;
+    
+    if (rs_read_int(inf, &id) != 0)
+    {
+        if (id != RSXR_THING)
+            format_error = TRUE;
+        else
+        {
+            rs_read_boolean(inf,&t->t_wasshot);
+            rs_read_uchar(inf, &t->t_type);
+            rs_read_uchar(inf, &t->t_disguise);
+            rs_read_uchar(inf, &t->t_oldch);
+            rs_read_short(inf, &t->t_ctype);
+            rs_read_short(inf, &t->t_index);
+            rs_read_short(inf, &t->t_no_move);
+            rs_read_short(inf, &t->t_quiet);
+            rs_read_short(inf, &t->t_movement);
+            rs_read_short(inf, &t->t_action);
+            rs_read_short(inf, &t->t_artifact);
+            rs_read_short(inf, &t->t_wand);
+            rs_read_short(inf, &t->t_summon);
+            rs_read_short(inf, &t->t_cast);
+            rs_read_short(inf, &t->t_breathe);
+            rs_read_new_string(inf,&t->t_name);
+            rs_read_coord(inf,&t->t_doorgoal);
+
+            rs_read_int(inf,&listid);
+            rs_read_int(inf,&index);
+            t->t_reserved = -1;
+            if (listid == 0)
+            {
+                if (index == 1)
+                    t->t_dest = &hero;
+                else
+                    t->t_dest = NULL;
+            }
+            else if (listid == 1)
+            {
+                t->t_dest     = NULL;
+                t->t_reserved = index;
+            }
+            else if (listid == 2)
+            {
+                struct object *obj;
+                item = get_list_item(lvl_obj,index);
+                if (item != NULL)
+                {
+                    obj = OBJPTR(item);
+                    t->t_dest = &obj->o_pos;
+                }
+            }
+            else
+                t->t_dest = NULL;
+
+            rs_read_coord(inf,&t->t_pos);
+            rs_read_coord(inf,&t->t_oldpos);
+            rs_read_coord(inf,&t->t_newpos);
+            rs_read_ulongs(inf,t->t_flags,16);
+            rs_read_object_list(inf,&t->t_pack);
+            rs_read_int(inf,&index);
+            t->t_using = get_list_item(t->t_pack, index);
+            rs_read_stats(inf,&t->t_stats);
+            rs_read_stats(inf,&t->maxstats);
+        }
+    }
+    else format_error = TRUE;
+    
+    return(READSTAT);
+}
+
+int
+find_list_ptr(struct linked_list *l, void *ptr)
+{
+    int count = 0;
+
+    while(l != NULL)
+    {
+        if (l->l_data == ptr)
+            return(count);
+            
+        l = l->l_next;
+        count++;
+    }
+    
+    return(-1);
+}
+
+
+int
+list_size(struct linked_list *l)
+{
+    int count = 0;
+    
+    while(l != NULL)
+    {
+        if (l->l_data == NULL)
+            return(count);
+            
+        count++;
+        
+        l = l->l_next;
+    }
+    
+    return(count);
+}
+
+
+rs_write_monster_list(FILE *savef, struct linked_list *l)
+{
+    int cnt = 0;
+    
+    DBG(("Monster List\n"));
+    rs_write_int(savef, RSXR_MONSTERLIST);
+
+    cnt = list_size(l);
+
+    rs_write_int(savef, cnt);
+
+    if (cnt < 1)
+        return(WRITESTAT);
+
+    while (l != NULL) {
+        rs_write_thing(savef, (struct thing *)l->l_data);
+        l = l->l_next;
+    }
+    
+    return(WRITESTAT);
+}
+
+rs_fix_monster_list(list)
+struct linked_list *list;
+{
+    struct linked_list *item;
+
+    for(item = list; item != NULL; item = item->l_next)
+        rs_fix_thing(THINGPTR(item));
+}
+
+rs_read_monster_list(int inf, struct linked_list **list)
+{
+    int id;
+    int i, cnt;
+    struct linked_list *l = NULL, *previous = NULL, *head = NULL;
+
+    if (rs_read_int(inf,&id) != 0)
+    {
+        if (id != RSXR_MONSTERLIST)
+        {
+            printf("Invalid id. %x != %x(RSXR_MONSTERLIST)\n",
+                id,RSXR_MONSTERLIST);
+            printf("Sorry, invalid save game format");
+            format_error = TRUE;
+        }
+        else if (rs_read_int(inf,&cnt) != 0)
+        {
+            for (i = 0; i < cnt; i++) 
+            {
+                l = new_item(sizeof(struct thing));
+                l->l_prev = previous;
+                if (previous != NULL)
+                    previous->l_next = l;
+                rs_read_thing(inf,(struct thing *)l->l_data);
+                if (previous == NULL)
+                    head = l;
+                previous = l;
+            }
+        
+
+            if (l != NULL)
+                l->l_next = NULL;
+
+            *list = head;
+        }
+    }
+    else format_error = TRUE;
+    
+    return(READSTAT);
+}
+
+rs_write_magic_items(FILE *savef, struct magic_item *i, int count)
+{
+    int n;
+    
+    DBG(("Magic Items\n"));
+    rs_write_int(savef, RSXR_MAGICITEMS);
+    rs_write_int(savef, count);
+
+    for(n=0;n<count;n++)
+    {
+        rs_write(savef,i[n].mi_name,sizeof(i[n].mi_name));
+        rs_write_int(savef,i[n].mi_prob);
+        rs_write_int(savef,i[n].mi_worth);
+        rs_write_int(savef,i[n].mi_curse);
+        rs_write_int(savef,i[n].mi_bless);
+    }
+    
+    return(WRITESTAT);
+}
+
+rs_read_magic_items(int inf, struct magic_item *mi, int count)
+{
+    int id;
+    int n;
+    int value;
+
+    if (rs_read_int(inf, &id) != 0)
+    {
+        if (id != RSXR_MAGICITEMS)
+        {
+            printf("Invalid id. %x != %x(RSXR_MAGICITEMS)\n",
+                id,RSXR_MAGICITEMS);
+            printf("Sorry, invalid save game format");
+            format_error = TRUE;
+        }   
+        else if (rs_read_int(inf, &value) != 0)
+        {
+            if (value > count)
+            {
+                printf("Incorrect number of magic items in block. %d > %d.",
+                    value,count);
+                printf("Sorry, invalid save game format");
+                format_error = TRUE;
+            }
+            else
+            {
+                for(n = 0; n < value; n++)
+                {
+                    rs_read(inf,mi[n].mi_name,sizeof(mi[n].mi_name));
+                    rs_read_int(inf,&mi[n].mi_prob);
+                    rs_read_int(inf,&mi[n].mi_worth);
+                    rs_read_int(inf,&mi[n].mi_curse);
+                    rs_read_int(inf,&mi[n].mi_bless);
+                }
+            }
+        }
+    }
+    
+    return(READSTAT);
+}
+
+rs_write_window(FILE *savef, WINDOW *win)
+{
+    int row,col,height,width;
+    width = getmaxx(win);
+    height = getmaxy(win);
+    DBG(("Window\n"));
+    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));
+}
+
+rs_read_window(int inf, WINDOW *win)
+{
+    int row,col,maxlines,maxcols,value,width,height;
+    
+    width = getmaxx(win);
+    height = getmaxy(win);
+
+    rs_read_int(inf,&maxlines);
+    rs_read_int(inf,&maxcols);
+    if (maxlines > height)
+       abort();
+    if (maxcols > width)
+       abort();
+    
+    for(row=0;row<maxlines;row++)
+        for(col=0;col<maxcols;col++)
+        {
+            rs_read_int(inf, &value);
+            if ((value == '-') || (value == 196))
+                value = HORZWALL;
+            else if ((value == '|') || (value == 179))
+                value = VERTWALL;
+            mvwaddch(win,row,col,value);
+        }
+
+    return(READSTAT);
+}
+
+rs_save_file(FILE *savef)
+{
+    int i, weapon, armor, ring, misc, room = -1;
+    int endian = 0x01020304;
+    big_endian = ( *((char *)&endian) == 0x01 );
+
+    rs_write_thing(savef, &player);                     /* rogue.c          */
+    rs_write_object_list(savef, lvl_obj);               /* rogue.c          */
+    rs_write_monster_list(savef, mlist);                /* rogue.c          */
+    rs_write_monster_list(savef, tlist);                /* rogue.c          */
+ 
+    rs_write_traps(savef, traps, MAXTRAPS);             /* rogue.c          */
+
+    armor = find_list_ptr(player.t_pack, cur_armor);
+    rs_write_int(savef, armor);                         /* rogue.c          */
+
+    for (i = 0; i < NUM_FINGERS; i++)
+    {
+        ring = find_list_ptr(player.t_pack, cur_ring[i]);
+        rs_write_int(savef, ring);                      /* rogue.c          */
+    }
+
+    for (i = 0; i < NUM_MM; i++)
+    {
+        misc = find_list_ptr(player.t_pack, cur_misc[i]);
+        rs_write_int(savef, misc);                      /* rogue.c          */
+    }
+
+    for (i=0; i<MAXRELIC; i++)
+       rs_write_int(savef,cur_relic[i]);                /* rogue.c          */
+
+
+    rs_write_rooms(savef, rooms, MAXROOMS);             /* rogue.c          */
+
+    for (i = 0; i < MAXROOMS; i++)
+        if (&rooms[i] == oldrp)
+            room = i;
+    rs_write_int(savef, room);                          /* rogue.c          */
+
+    weapon = find_list_ptr(player.t_pack, cur_weapon);
+    rs_write_int(savef, weapon);                        /* rogue..c         */
+    rs_write_int(savef,char_type);
+    rs_write_int(savef,foodlev);
+    rs_write_int(savef,ntraps);
+    rs_write_int(savef,trader);
+    rs_write_int(savef,curprice);
+    rs_write_int(savef,seed);
+    rs_write_int(savef,max_level);
+    rs_write_int(savef,cur_max);
+    rs_write_int(savef,prev_max);
+    rs_write_int(savef,move_free);
+    rs_write_int(savef,mpos);
+    rs_write_int(savef,level);
+    rs_write_long(savef,purse);
+    rs_write_int(savef,inpack);
+    rs_write_int(savef,total);
+    rs_write_int(savef,no_food);
+    rs_write_int(savef,foods_this_level);
+    rs_write_int(savef,count);
+    rs_write_int(savef,food_left);
+    rs_write_int(savef,group);
+    rs_write_int(savef,hungry_state);
+    rs_write_int(savef,infest_dam);
+    rs_write_int(savef,lost_str);
+    rs_write_int(savef,lastscore);
+    rs_write_int(savef,hold_count);
+    rs_write_int(savef,trap_tries);
+    rs_write_int(savef,chant_time);
+    rs_write_int(savef,pray_time);
+    rs_write_int(savef,spell_power);
+    rs_write_long(savef,turns);
+    rs_write_int(savef,quest_item);
+    rs_write_int(savef,cols);
+    rs_write_int(savef,lines);
+    rs_write_int(savef,nfloors);
+    rs_write(savef,curpurch,LINELEN);
+    rs_write_char(savef,PLAYER);
+    rs_write_char(savef,take);
+    rs_write_int(savef,1234);/*checkpoint*/
+    rs_write(savef,prbuf,LINELEN*2);
+    rs_write_int(savef,1234);/*checkpoint*/
+    rs_write_char(savef,runch);
+    rs_write_int(savef,1234);/*checkpoint*/
+    rs_write_scrolls(savef);
+    rs_write_potions(savef);
+    rs_write_rings(savef);
+    rs_write_sticks(savef);
+    rs_write_misc(savef);
+    rs_write_int(savef,1234);/*checkpoint*/
+    rs_write(savef,whoami,LINELEN);
+    rs_write_window(savef, cw);
+    rs_write_window(savef, hw);
+    rs_write_window(savef, mw);
+    rs_write_window(savef, msgw);
+    rs_write_window(savef, stdscr);
+    rs_write_boolean(savef,pool_teleport);
+    rs_write_boolean(savef,inwhgt);
+    rs_write_boolean(savef,after);
+    rs_write_boolean(savef,waswizard);
+    rs_write_boolean(savef, playing);                       /* rogue.h/init.c   */
+    rs_write_boolean(savef, running);                       /* rogue.h/init.c   */
+    rs_write_boolean(savef, wizard);                        /* rogue.h/init.c   */
+    rs_write_boolean(savef, notify);                        /* rogue.h/init.c   */
+    rs_write_boolean(savef, fight_flush);                   /* rogue.h/init.c   */
+    rs_write_boolean(savef, terse);                         /* rogue.h/init.c   */
+    rs_write_boolean(savef, auto_pickup);                     /* rogue.h/init.c   */
+    rs_write_boolean(savef, def_attr);                     /* rogue.h/init.c   */
+    rs_write_boolean(savef, menu_overlay);                     /* rogue.h/init.c   */
+    rs_write_boolean(savef, door_stop);                     /* rogue.h/init.c   */
+    rs_write_boolean(savef, jump);                          /* rogue.h/init.c   */
+    rs_write_boolean(savef, slow_invent);                   /* rogue.h/init.c   */
+    rs_write_boolean(savef, firstmove);                     /* rogue.h/init.c   */
+    rs_write_boolean(savef, askme);                         /* rogue.h/init.c   */
+    rs_write_boolean(savef, in_shell);                      /* rogue.h/init.c   */
+    rs_write_boolean(savef, daytime);                      /* rogue.h/init.c   */
+    rs_write_boolean(savef, funfont);                      /* rogue.h/init.c   */
+    rs_write_levtype(savef,levtype); 
+    rs_write_character_types(savef,char_class,NUM_CHARTYPES);
+    rs_write_words(savef,abilities,NUMABILITIES);
+    for(i=0;i<9;i++)
+        rs_write_coord(savef,&grid[i]);
+    rs_write_death_types(savef,deaths,DEATHNUM);
+    rs_write_init_weps(savef,weaps,MAXWEAPONS);
+    rs_write_init_armor(savef,armors,MAXARMORS);
+    rs_write_magic_items(savef, things,   NUMTHINGS);   /* rogue.h/init.c   */
+    rs_write_magic_items(savef, s_magic,  MAXSCROLLS);  /* rogue.h/init.c   */
+    rs_write_magic_items(savef, p_magic,  MAXPOTIONS);  /* rogue.h/init.c   */
+    rs_write_magic_items(savef, r_magic,  MAXRINGS);    /* rogue.h/init.c   */
+    rs_write_magic_items(savef, ws_magic, MAXSTICKS);   /* rogue.h/init.c   */   
+    rs_write_magic_items(savef, m_magic, MAXMM);   /* rogue.h/init.c   */
+    rs_write_magic_items(savef, rel_magic, MAXRELIC);   /* rogue.h/init.c   */
+    rs_write_magic_items(savef, foods, MAXFOODS);   /* rogue.h/init.c   */
+    rs_write_spells(savef,magic_spells,MAXSPELLS);
+    rs_write_spells(savef,cleric_spells,MAXPRAYERS);
+    rs_write_spells(savef,druid_spells,MAXCHANTS);
+    rs_write_spells(savef,quill_scrolls,MAXQUILL);
+
+    rs_write_int(savef,mf_count);                           /* actions.c        */
+    rs_write_int(savef,mf_jmpcnt);                          /* actions.c        */
+    rs_write_daemons(savef, d_list, MAXDAEMONS);            /* daemon.c         */
+    rs_write_daemons(savef, f_list, MAXFUSES);              /* daemon.c         */
+    rs_write_int(savef,demoncnt);                           /* daemon.c         */
+    rs_write_int(savef,fusecnt);                            /* daemon.c         */
+    rs_write_int(savef,killed_chance);                      /* fight.c          */
+    rs_write_words(savef,rainbow,NCOLORS);                  /* init.c   */
+    rs_write_words(savef,sylls,NSYLLS);                     /* init.c   */
+    rs_write_words(savef,stones,NSTONES);                   /* init.c   */
+    rs_write_words(savef,wood,NWOOD);                       /* init.c   */
+    rs_write_words(savef,metal,NMETAL);                     /* init.c   */
+    rs_write_monsters(savef,monsters,
+        sizeof(monsters)/sizeof(struct monster));           /* mons_def.c       */
+    rs_write_coord(savef,&move_nh);                         /* move.c           */
+    return(WRITESTAT);
+}
+
+rs_restore_file(int inf)
+{
+    int weapon, armor, ring, misc, room = -1,i,checkpoint;
+    int endian = 0x01020304;
+    big_endian = ( *((char *)&endian) == 0x01 );
+    
+    rs_read_thing(inf, &player);                        /* rogue.h          */
+    rs_read_object_list(inf, &lvl_obj);                 /* rogue.h/init.c   */
+    rs_read_monster_list(inf, &mlist);                  /* rogue.h/init.c   */
+    rs_read_monster_list(inf, &tlist);                  /* rogue.h/init.c   */
+    rs_fix_thing(&player);
+    rs_fix_monster_list(mlist);
+    rs_read_traps(inf, traps, MAXTRAPS);
+
+
+    rs_read_int(inf, &armor);                           /* rogue.h          */
+    cur_armor = get_list_item(player.t_pack,armor);
+
+    for(i = 0; i < NUM_FINGERS; i++)
+    {
+        rs_read_int(inf,&ring);
+        cur_ring[i] = get_list_item(player.t_pack,ring);
+    }
+
+    for(i = 0; i < NUM_MM; i++)
+    {
+        rs_read_int(inf,&misc);
+        cur_misc[i] = get_list_item(player.t_pack,misc);
+    }
+
+    for(i=0;i<MAXRELIC;i++)
+        rs_read_int(inf,&cur_relic[i]);
+
+    rs_read_rooms(inf, rooms, MAXROOMS);
+    rs_read_int(inf, &room);
+    
+    oldrp = &rooms[room];
+
+    rs_read_int(inf,&weapon);   
+    cur_weapon = get_list_item(player.t_pack,weapon);
+
+    rs_read_int(inf,&char_type);
+    rs_read_int(inf,&foodlev);
+    rs_read_int(inf,&ntraps);
+    rs_read_int(inf,&trader);
+    rs_read_int(inf,&curprice);
+    rs_read_int(inf,&seed);
+    rs_read_int(inf,&max_level);
+    rs_read_int(inf,&cur_max);
+    rs_read_int(inf,&prev_max);
+    rs_read_int(inf,&move_free);
+    rs_read_int(inf,&mpos);
+    rs_read_int(inf,&level);
+    rs_read_long(inf,&purse);
+    rs_read_int(inf,&inpack);
+    rs_read_int(inf,&total);
+    rs_read_int(inf,&no_food);
+    rs_read_int(inf,&foods_this_level);
+    rs_read_int(inf,&count);
+    rs_read_int(inf,&food_left);
+    rs_read_int(inf,&group);
+    rs_read_int(inf,&hungry_state);
+    rs_read_int(inf,&infest_dam);
+    rs_read_int(inf,&lost_str);
+    rs_read_int(inf,&lastscore);
+    rs_read_int(inf,&hold_count);
+    rs_read_int(inf,&trap_tries);
+    rs_read_int(inf,&chant_time);
+    rs_read_int(inf,&pray_time);
+    rs_read_int(inf,&spell_power);
+    rs_read_long(inf,&turns);
+    rs_read_int(inf,&quest_item);
+    rs_read_int(inf,&cols);
+    rs_read_int(inf,&lines);
+    rs_read_int(inf,&nfloors);
+    rs_read(inf,curpurch,LINELEN);
+    rs_read_char(inf,&PLAYER);
+    rs_read_char(inf,&take);
+    rs_read_int(inf,&checkpoint);
+    if (checkpoint != 1234){printf("Checkpoint failed");abort();}
+    rs_read(inf,prbuf,LINELEN*2);
+    rs_read_int(inf,&checkpoint);
+    if (checkpoint != 1234){printf("Checkpoint failed");abort();}
+    rs_read_char(inf,&runch);
+    rs_read_int(inf,&checkpoint);
+    if (checkpoint != 1234){printf("Checkpoint failed");abort();}
+    rs_read_scrolls(inf);
+    rs_read_potions(inf);
+    rs_read_rings(inf);
+    rs_read_sticks(inf);
+    rs_read_misc(inf);
+    rs_read_int(inf,&checkpoint);
+    if (checkpoint != 1234){printf("Checkpoint failed");abort();}
+    rs_read(inf,whoami,LINELEN);
+    rs_read_window(inf, cw);
+    rs_read_window(inf, hw);
+    rs_read_window(inf, mw);
+    rs_read_window(inf, msgw);
+    rs_read_window(inf, stdscr);
+    rs_read_boolean(inf,&pool_teleport);
+    rs_read_boolean(inf,&inwhgt);
+    rs_read_boolean(inf,&after);
+    rs_read_boolean(inf,&waswizard);
+    rs_read_boolean(inf, &playing);                       /* rogue.h/init.c   */
+    rs_read_boolean(inf, &running);                       /* rogue.h/init.c   */
+    rs_read_boolean(inf, &wizard);                        /* rogue.h/init.c   */
+    rs_read_boolean(inf, &notify);                        /* rogue.h/init.c   */
+    rs_read_boolean(inf, &fight_flush);                   /* rogue.h/init.c   */
+    rs_read_boolean(inf, &terse);                         /* rogue.h/init.c   */
+    rs_read_boolean(inf, &auto_pickup);                     /* rogue.h/init.c   */
+    rs_read_boolean(inf, &def_attr);                     /* rogue.h/init.c   */
+    rs_read_boolean(inf, &menu_overlay);                     /* rogue.h/init.c   */
+    rs_read_boolean(inf, &door_stop);                     /* rogue.h/init.c   */
+    rs_read_boolean(inf, &jump);                          /* rogue.h/init.c   */
+    rs_read_boolean(inf, &slow_invent);                   /* rogue.h/init.c   */
+    rs_read_boolean(inf, &firstmove);                     /* rogue.h/init.c   */
+    rs_read_boolean(inf, &askme);                         /* rogue.h/init.c   */
+    rs_read_boolean(inf, &in_shell);                      /* rogue.h/init.c   */
+    rs_read_boolean(inf, &daytime);                      /* rogue.h/init.c   */
+    rs_read_boolean(inf, &funfont);                      /* rogue.h/init.c   */
+    rs_read_levtype(inf,&levtype);
+    rs_read_character_types(inf,char_class,NUM_CHARTYPES);
+    rs_read_words(inf,abilities,NUMABILITIES);
+    for(i=0;i<9;i++)
+        rs_read_coord(inf,&grid[i]);
+    rs_read_death_types(inf,deaths,DEATHNUM);
+    rs_read_init_weps(inf,weaps,MAXWEAPONS);
+    rs_read_init_armor(inf,armors,MAXARMORS);
+    rs_read_magic_items(inf, things,NUMTHINGS);         /* rogue.h/init.c   */
+    rs_read_magic_items(inf, s_magic,MAXSCROLLS);       /* rogue.h/init.c   */
+    rs_read_magic_items(inf, p_magic,MAXPOTIONS);       /* rogue.h/init.c   */
+    rs_read_magic_items(inf, r_magic,MAXRINGS);         /* rogue.h/init.c   */
+    rs_read_magic_items(inf, ws_magic,MAXSTICKS);       /* rogue.h/init.c   */
+    rs_read_magic_items(inf, m_magic,MAXMM);       /* rogue.h/init.c   */
+    rs_read_magic_items(inf, rel_magic,MAXRELIC);       /* rogue.h/init.c   */
+    rs_read_magic_items(inf, foods,MAXFOODS);       /* rogue.h/init.c   */
+    rs_read_spells(inf,magic_spells,MAXSPELLS);
+    rs_read_spells(inf,cleric_spells,MAXPRAYERS);
+    rs_read_spells(inf,druid_spells,MAXCHANTS);
+    rs_read_spells(inf,quill_scrolls,MAXQUILL);
+
+    rs_read_int(inf,&mf_count);                             /* actions.c        */
+    rs_read_int(inf,&mf_jmpcnt);                            /* actions.c        */
+    rs_read_daemons(inf, d_list, MAXDAEMONS);               /* daemon.c         */
+    rs_read_daemons(inf, f_list, MAXFUSES);                 /* daemon.c         */
+    rs_read_int(inf,&demoncnt);                             /* daemon.c         */
+    rs_read_int(inf,&fusecnt);                              /* daemon.c         */
+    rs_read_int(inf,&killed_chance);                        /* fight.c          */
+    rs_read_words(inf,rainbow,NCOLORS);                     /* init.c   */
+    rs_read_words(inf,sylls,NSYLLS);                        /* init.c   */
+    rs_read_words(inf,stones,NSTONES);                      /* init.c   */
+    rs_read_words(inf,wood,NWOOD);                          /* init.c   */
+    rs_read_words(inf,metal,NMETAL);                        /* init.c   */
+
+    rs_read_monsters(inf,monsters,
+        sizeof(monsters)/sizeof(struct monster));           /* mons_def.c       */
+    rs_read_coord(inf,&move_nh);                            /* move.c           */
+
+    return(READSTAT);
+}
+
+rs_write_scorefile(FILE *savef, struct sc_ent *entries, int count)
+{
+    int i;
+
+    rs_write_int(savef, count);
+    for(i = 0; i < count; i++)
+    {
+        rs_write_ulong(savef, entries[i].sc_score);
+        rs_write(savef, entries[i].sc_name, sizeof(entries[i].sc_name));
+        rs_write(savef, entries[i].sc_system, sizeof(entries[i].sc_system));
+        rs_write(savef, entries[i].sc_login, sizeof(entries[i].sc_login));
+        rs_write_short(savef, entries[i].sc_flags);
+        rs_write_short(savef, entries[i].sc_level);
+        rs_write_short(savef, entries[i].sc_ctype);
+        rs_write_short(savef, entries[i].sc_monster);
+        rs_write_short(savef, entries[i].sc_quest);
+    }
+}
+
+rs_read_scorefile(FILE *savef, struct sc_ent *entries, int count)
+{
+    int i,available = 0;
+
+    rs_read_int(fileno(savef), &available);
+
+    if (end_of_file)
+       return(-1);
+
+    if (available != count)
+       return(-2);
+
+    for(i = 0; i < count; i++)
+    {
+        rs_read_ulong(fileno(savef), &entries[i].sc_score);
+        rs_read(fileno(savef), entries[i].sc_name, sizeof(entries[i].sc_name));
+        rs_read(fileno(savef), entries[i].sc_system, sizeof(entries[i].sc_system));
+        rs_read(fileno(savef), entries[i].sc_login, sizeof(entries[i].sc_login));
+        rs_read_short(fileno(savef), &entries[i].sc_flags);
+        rs_read_short(fileno(savef), &entries[i].sc_level);
+        rs_read_short(fileno(savef), &entries[i].sc_ctype);
+        rs_read_short(fileno(savef), &entries[i].sc_monster);
+        rs_read_short(fileno(savef), &entries[i].sc_quest);
+    }
+
+    return(0);
+}
+
+
+
+rs_print_thing(FILE *outf, struct thing *thing, char *prefix, int list, int index)
+{
+    int i;
+
+    fprintf(outf,"%sList Ident : %d\n", prefix, list);
+    fprintf(outf,"%sList Index : %d\n", prefix, index);
+    fprintf(outf,"%st_wasshot  : %d\n", prefix, thing->t_wasshot);
+    fprintf(outf,"%st_type     : %c\n", prefix, thing->t_type);
+    fprintf(outf,"%st_disguise : %c\n", prefix, thing->t_disguise);
+    fprintf(outf,"%st_oldch    : %c\n", prefix, thing->t_oldch);
+    fprintf(outf,"%st_ctype    : %d\n", prefix, thing->t_ctype);
+    fprintf(outf,"%st_index    : %d\n", prefix, thing->t_index);
+    fprintf(outf,"%st_no_move  : %d\n", prefix, thing->t_no_move);
+    fprintf(outf,"%st_quiet    : %d\n", prefix, thing->t_quiet);
+    fprintf(outf,"%st_movement : %d\n", prefix, thing->t_movement);
+    fprintf(outf,"%st_action   : %d\n", prefix, thing->t_action);
+    fprintf(outf,"%st_artificat: %d\n", prefix, thing->t_artifact);
+    fprintf(outf,"%st_wand     : %d\n", prefix, thing->t_wand);
+    fprintf(outf,"%st_summon   : %d\n", prefix, thing->t_summon);
+    fprintf(outf,"%st_cast     : %d\n", prefix, thing->t_cast);
+    fprintf(outf,"%st_breathe  : %d\n", prefix, thing->t_breathe);
+    fprintf(outf,"%st_name     : %s\n", prefix, (thing->t_name == NULL) ? "none" :
+                                                thing->t_name);
+    fprintf(outf,"%st_doorgoal : %d %d\n", prefix, thing->t_doorgoal.x, thing->t_doorgoal.y);
+    fprintf(outf,"%st_dest     : %p\n", prefix, thing->t_dest);
+    fprintf(outf,"%st_pos      : %d %d (%p)\n", prefix, thing->t_pos.x, thing->t_pos.y,&thing->t_pos);
+    fprintf(outf,"%st_oldpos   : %d %d\n", prefix, thing->t_oldpos.x, thing->t_oldpos.y);
+    fprintf(outf,"%st_newpos   : %d %d\n", prefix, thing->t_newpos.x, thing->t_newpos.y);
+    fprintf(outf,"%st_flags    : ", prefix);
+
+    for(i = 0; i<16; i++)
+        fprintf(outf,"%X ",thing->t_flags[i]);
+    fprintf(outf,"\n");
+
+    fprintf(outf,"%st_pack     : %p\n",prefix,thing->t_pack);
+    fprintf(outf,"%st_using    : %p\n",prefix,thing->t_using);
+    fprintf(outf,"%st_stats    : Not Implemented\n",prefix);
+    fprintf(outf,"%st_maxstats : Not Implemented\n",prefix);
+    fprintf(outf,"%st_reserved : %d\n",prefix,thing->t_reserved);
+}
+
+rs_print_game_state(FILE *outf)
+{
+    fprintf(outf, "Player\n");
+
+    rs_print_thing(outf, &player, "    ", 0, 0);
+}
+
+/****
+ Machine Dependent Functions
+
+ md_getuid()
+ md_memused()
+ md_getusername()
+ md_gethostname()
+ md_gethomedir()
+ md_getroguedir()
+ md_getshell()
+ md_shellescape()
+ md_getpass()
+ md_crypt()
+ md_htons()
+ md_nstoh()
+ md_unlink()
+ md_isdir()
+ md_ntohl()
+ md_htonl()
+
+****/
+
+int
+md_rand(range)
+register int range;
+{
+#ifdef _WIN32
+    return(range <= 0 ? 0 : rand() % range);
+#else
+    return(range <= 0 ? 0 : random() % range);
+#endif
+}
+
+int
+md_srand(seed)
+register int seed;
+{
+#ifdef _WIN32
+    srand(seed);
+#else
+    srandom(seed);
+#endif
+}
+
+void 
+md_flushinp()
+{
+    /* ioctl(0,TIOCFLUSH) */
+    /* ioctl(_tty_ch,TCFLSH,0) */
+    flushinp();
+}
+
+int
+md_getuid()
+{
+#ifdef _WIN32
+    return(42);
+#else
+    return(getuid());
+#endif
+}
+
+long
+md_memused()
+{
+#ifdef _WIN32
+    MEMORYSTATUS stat;
+
+    GlobalMemoryStatus(&stat);
+
+    return((long)stat.dwTotalPageFile);
+#else
+    return( (long)sbrk(0) );
+#endif
+}
+
+char *
+md_getusername()
+{
+    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;
+#endif
+#if !defined(_WIN32) && !defined(DJGPP)
+    struct passwd *pw;
+
+    pw = getpwuid(getuid());
+
+    l = pw->pw_name;
+#endif
+
+    if ((l == NULL) || (*l == '\0'))
+        if ( (l = getenv("USERNAME")) == NULL )
+            if ( (l = getenv("LOGNAME")) == NULL )
+                if ( (l = getenv("USER")) == NULL )
+                    l = "nobody";
+
+    strncpy(login,l,80);
+    login[79] = 0;
+
+    return(login);
+}
+
+char *
+md_gethomedir()
+{
+    static char homedir[PATH_MAX];
+    char *h = NULL;
+    size_t len;
+#if defined(_WIN32)
+    TCHAR szPath[MAX_PATH];
+#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);
+}
+
+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_getroguedir()
+{
+    static char path[1024];
+    char *end,*home;
+
+    if ( (home = getenv("ROGUEHOME")) != NULL)
+    {
+        if (*home)
+        {
+            strncpy(path, home, PATH_MAX - 20);
+
+            end = &path[strlen(path)-1];
+
+
+            while( (end >= path) && ((*end == '/') || (*end == '\\')))
+                *end-- = '\0';
+
+            if (directory_exists(path))
+                return(path);
+        }
+    }
+
+    if (directory_exists("/var/games/roguelike"))
+        return("/var/games/roguelike");
+    if (directory_exists("/var/lib/roguelike"))
+        return("/var/lib/roguelike");
+    if (directory_exists("/var/roguelike"))
+        return("/var/roguelike");
+    if (directory_exists("/usr/games/lib"))
+        return("/usr/games/lib");
+    if (directory_exists("/games/roguelik"))
+        return("/games/roguelik");
+
+    return("");
+}
+
+char *
+md_getshell()
+{
+    static char shell[PATH_MAX];
+    char *s = NULL;
+#ifdef _WIN32
+    char *def = "C:\\WINDOWS\\SYSTEM32\\CMD.EXE";
+#elif defined(__DJGPP__)
+    char *def = "C:\\COMMAND.COM";
+#else
+    char *def = "/bin/sh";
+    struct passwd *pw;
+    pw = getpwuid(getuid());
+    s = pw->pw_shell;
+#endif
+    if ((s == NULL) || (*s == '\0'))
+        if ( (s = getenv("COMSPEC")) == NULL) 
+            if ( (s = getenv("SHELL")) == NULL) 
+                if ( (s = getenv("SystemRoot")) == NULL)
+                    s = def;
+
+    strncpy(shell,s,PATH_MAX);
+    shell[PATH_MAX-1] = 0;
+
+    return(shell);
+}
+
+char *
+md_gethostname()
+{
+    static char nodename[80];
+    char *n = NULL;
+#if !defined(_WIN32) && !defined(__DJGPP__)
+    struct utsname ourname;
+
+    if (uname(&ourname) == 0)
+        n = ourname.nodename;
+#endif
+    if ((n == NULL) || (*n == '\0'))
+        if ( (n = getenv("COMPUTERNAME")) == NULL)
+            if ( (n = getenv("HOSTNAME")) == NULL)
+                n = "localhost";
+
+    strncpy(nodename, n, 80);
+    nodename[79] = 0;
+
+    return(nodename);
+}
+
+int
+md_shellescape()
+{
+#if (!defined(_WIN32) && !defined(__DJGPP__))
+    int ret_status;
+	int pid;
+#endif
+    char *sh;
+
+	sh = md_getshell();
+
+#if defined(_WIN32) 
+    return(_spawnl(_P_WAIT,sh,"shell",NULL,0));
+#elif defined(__DJGPP__)
+    return ( spawnl(P_WAIT,sh,"shell",NULL,0) );
+#else
+    while((pid = fork()) < 0)
+        sleep(1);
+
+    if (pid == 0) /* Shell Process */
+    {
+        /*
+         * Set back to original user, just in case
+         */
+        setuid(getuid());
+        setgid(getgid());
+        execl(sh == NULL ? "/bin/sh" : sh, "shell", "-i", 0);
+        perror("No shelly");
+        _exit(-1);
+    }
+    else /* Application */
+    {
+        while (wait(&ret_status) != pid)
+            continue;
+    }
+
+    return(ret_status);
+#endif
+}
+
+int
+md_erasechar()
+{
+/*
+    return(_tty.sg_erase);
+    return(_tty.c_cc[VERASE]);
+*/
+    return(erasechar());
+}
+
+int
+md_killchar()
+{
+/*
+    return(_tty.sg_kill);
+    return(_tty.c_cc[VKILL]);
+*/
+    return(killchar());
+}
+
+long
+md_ntohl(netlong)
+long netlong;
+{
+    return( ntohl(netlong) );
+}
+
+long
+md_htonl(netlong)
+long netlong;
+{
+    return(htonl(netlong));
+}
+
+void
+md_init()
+{
+#ifdef __INTERIX
+    char *term;
+
+    term = getenv("TERM");
+
+    if (term == NULL)
+        setenv("TERM","interix");
+#endif
+#if defined(__DJGPP__) || defined(_WIN32)
+    _fmode = _O_BINARY;
+#endif
+}
+
+char *
+md_getpass(prompt)
+char *prompt;
+{
+#ifdef _WIN32
+    static char password_buffer[9];
+    char *p = password_buffer;
+    int c, count = 0;
+    int max_length = 9;
+
+    fflush(stdout);
+    /* If we can't prompt, abort */
+    if (fputs(prompt, stderr) < 0)
+    {
+        *p = '\0';
+        return NULL;
+    }
+
+    for(;;)
+    {
+        /* Get a character with no echo */
+        c = _getch();
+
+        /* Exit on interrupt (^c or ^break) */
+        if (c == '\003' || c == 0x100)
+            exit(1);
+
+        /* Terminate on end of line or file (^j, ^m, ^d, ^z) */
+        if (c == '\r' || c == '\n' || c == '\004' || c == '\032')
+            break;
+
+        /* Back up on backspace */
+        if (c == '\b')
+        {
+            if (count)
+                count--;
+            else if (p > password_buffer)
+	        p--;
+            continue;
+        }
+
+        /* Ignore DOS extended characters */
+        if ((c & 0xff) != c)
+            continue;
+
+        /* Add to password if it isn't full */
+        if (p < password_buffer + max_length - 1)
+            *p++ = c;
+        else
+            count++;
+    }
+   *p = '\0';
+
+   fputc('\n', stderr);
+
+   return password_buffer;
+#else
+   return( (char *) getpass(prompt) );
+#endif
+}
+
+#ifdef SIGTSTP
+
+/*
+ * handle stop and start signals
+ */
+
+/*UNUSED*/
+void 
+tstp(a)
+int a;
+{
+    mvcur(0, cols - 1, lines - 1, 0);
+    fflush(stdout);
+    kill(0, SIGTSTP);
+    signal(SIGTSTP, tstp);
+    crmode();
+    noecho();
+    clearok(curscr, TRUE);
+    touchwin(cw);
+    draw(cw);
+    flushinp();
+}
+#endif
+
+int
+md_setup()
+{
+#ifdef SIGTSTP
+    signal(SIGTSTP, tstp);
+#endif
+#ifdef SIGHUP
+    signal(SIGHUP, auto_save);
+#endif
+    signal(SIGTERM, auto_save);
+    signal(SIGINT, quit);
+#ifdef SIGQUIT
+    signal(SIGQUIT, endit);
+#endif
+#if defined(__CYGWIN__) || defined(__MSYS__)
+    ESCDELAY = 250;
+#endif
+    crmode();                        /* Cbreak mode */
+    noecho();                           /* Echo off */
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xrogue/sticks.c	Tue Apr 21 08:55:20 2015 -0400
@@ -0,0 +1,896 @@
+/*
+    sticks.c - Functions to implement the various sticks one might find
+    
+    XRogue: Expeditions into the Dungeons of Doom
+    Copyright (C) 1991 Robert Pietkivitch
+    All rights reserved.
+    
+    Based on "Advanced Rogue"
+    Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka and AT&T
+    All rights reserved.
+
+    Based on "Rogue: Exploring the Dungeons of Doom"
+    Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
+    All rights reserved.
+    
+    See the file LICENSE.TXT for full copyright and licensing information.
+*/ 
+
+#include <curses.h>
+#include <ctype.h>
+#include "rogue.h"
+
+/*
+ * zap a stick and see what happens
+ */
+
+do_zap(zapper, obj, direction, which, flags)
+struct thing *zapper;
+struct object *obj;
+coord *direction;
+int which;
+int flags;
+{
+    register struct linked_list *item = NULL;
+    register struct thing *tp;
+    register int y = 0, x = 0, bonus;
+    struct linked_list *nitem;
+    struct object *nobj;
+    bool cursed, blessed, is_player = FALSE;
+    char *mname = NULL;
+
+    cursed = flags & ISCURSED;
+    blessed = flags & ISBLESSED;
+
+    if (obj && obj->o_type != RELIC) { /* all relics are chargeless */
+        if (obj->o_charges < 1) {
+            msg(nothing);
+            return;
+        }
+        obj->o_charges--;
+    }
+    if (which == WS_WONDER) {
+        switch (rnd(19)) {
+            case  0: which = WS_ELECT;
+            when  1: which = WS_FIRE;
+            when  2: which = WS_COLD;
+            when  3: which = WS_POLYMORPH;
+            when  4: which = WS_MISSILE;
+            when  5: which = WS_SLOW_M;
+            when  6: which = WS_TELMON;
+            when  7: which = WS_CANCEL;
+            when  8: which = WS_CONFMON;
+            when  9: which = WS_DISINTEGRATE;
+            when 10: which = WS_PETRIFY;
+            when 11: which = WS_PARALYZE;
+            when 12: which = WS_MDEG;
+            when 13: which = WS_FEAR;
+            when 14: which = WS_CURING;
+            when 15: which = WS_LIGHT;
+            when 16: which = WS_HIT;
+            when 17: which = WS_DRAIN;
+            when 18: which = WS_CHARGE;
+        }
+        if(ws_magic[which].mi_curse>0 && rnd(100)<=ws_magic[which].mi_curse){
+            cursed = TRUE;
+            blessed = FALSE;
+        }
+    }
+
+    tp = NULL;
+    switch (which) {
+        case WS_POLYMORPH:
+        case WS_SLOW_M:
+        case WS_TELMON:
+        case WS_CANCEL:
+        case WS_CONFMON:
+        case WS_DISINTEGRATE:
+        case WS_PETRIFY:
+        case WS_PARALYZE:
+        case WS_MDEG:
+        case WS_FEAR:
+            y = zapper->t_pos.y;
+            x = zapper->t_pos.x;
+
+            do {
+                y += direction->y;
+                x += direction->x;
+            }
+            while (shoot_ok(winat(y, x)) && !(y == hero.y && x == hero.x));
+
+            if (y == hero.y && x == hero.x)
+                is_player = TRUE;
+            else if (isalpha(mvwinch(mw, y, x))) {
+                item = find_mons(y, x);
+                tp = THINGPTR(item);
+                runto(tp, &hero);
+                turn_off(*tp, CANSURPRISE);
+                mname = monster_name(tp);
+                is_player = FALSE;
+
+                /* The monster may not like being shot at */
+                if ((zapper == &player) &&
+                    on(*tp, ISCHARMED)  &&
+                    save(VS_MAGIC, tp, 0)) {
+                    msg("The eyes of %s turn clear.", prname(mname, FALSE));
+                    turn_off(*tp, ISCHARMED);
+                    mname = monster_name(tp);
+                }
+            }
+            else {
+                /*
+                 * if monster misses player because the player dodged then lessen
+                 * the chances he will use the wand again since the player appears
+                 * to be rather dextrous
+                 */
+                if (zapper != &player) 
+                    zapper->t_wand = zapper->t_wand * 3 / 5;
+            }
+    }
+    switch (which) {
+        case WS_LIGHT:
+            /*
+             * Reddy Kilowat wand.  Light up the room
+             */
+            blue_light(blessed, cursed);
+        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 (but leave the monsters alone
+             * if the stick is cursed)
+             */
+            if (pstats.s_hpt < 2) {
+                msg("You are too weak to use it.");
+            }
+            else if (cursed)
+                pstats.s_hpt /= 2;
+        if (pstats.s_hpt <= 0) {
+            pstats.s_hpt = -1;
+            msg("You drain your own life away.  --More--");
+            death(D_STRENGTH);
+        }
+            else
+                drain(hero.y-1, hero.y+1, hero.x-1, hero.x+1);
+
+        when WS_POLYMORPH:
+        {
+            register char oldch;
+            register struct room *rp;
+            register struct linked_list *pitem;
+            coord delta;
+
+            if (tp == NULL)
+                break;
+            if (save(VS_MAGIC, tp, 0)) {
+                msg(nothing);
+                break;
+            }
+            rp = roomin(&tp->t_pos);
+            check_residue(tp);
+            delta.x = x;
+            delta.y = y;
+            detach(mlist, item);
+            oldch = tp->t_oldch;
+            pitem = tp->t_pack; /* save his pack */
+            tp->t_pack = NULL;
+
+            if (levtype == OUTSIDE) 
+                new_monster(item,rnd(NUMDINOS)+NUMMONST-NUMDINOS,&delta,FALSE);
+            else
+                new_monster(item,rnd(NUMMONST-NUMUNIQUE-NUMDINOS-1)+1,&delta,FALSE);
+
+            if (tp->t_pack != NULL) 
+                o_free_list (tp->t_pack);
+            tp->t_pack = pitem;
+            if (isalpha(mvwinch(cw, y, x)))
+                mvwaddch(cw, y, x, tp->t_type);
+            tp->t_oldch = oldch;
+            /*
+             * should the room light up?
+             */
+            if (on(*tp, HASFIRE)) {
+                if (rp) {
+                    register struct linked_list *fire_item;
+
+                    fire_item = creat_item();
+                    ldata(fire_item) = (char *) tp;
+                    attach(rp->r_fires, fire_item);
+                    rp->r_flags |= HASFIRE;
+                    if (cansee(tp->t_pos.y,tp->t_pos.x) &&
+                        next(rp->r_fires) == NULL) light(&hero);
+                }
+            }
+            runto(tp, &hero);
+            msg(terse ? "A new %s!" 
+                      : "You have created a new %s!",
+                      monster_name(tp));
+        }
+
+        when WS_PETRIFY:
+            if (tp == NULL)
+                break;
+            if (save(VS_MAGIC, tp, 0)) {
+                msg(nothing);
+                break;
+            }
+            check_residue(tp);
+            turn_on(*tp, ISSTONE);
+            turn_on(*tp, NOSTONE);
+            turn_off(*tp, ISRUN);
+            turn_off(*tp, ISINVIS);
+            turn_off(*tp, CANSURPRISE);
+            turn_off(*tp, ISDISGUISE);
+            tp->t_action = A_NIL;
+            tp->t_no_move = 0;
+            msg("%s is turned to stone!",prname(mname, TRUE));
+
+        when WS_TELMON:
+        {
+            register int rm;
+            register struct room *rp;
+
+            if (tp == NULL)
+                break;
+            if (save(VS_MAGIC, tp, 0)) {
+                msg(nothing);
+                break;
+            }
+            rp = NULL;
+            check_residue(tp);
+            tp->t_action = A_FREEZE; /* creature is disoriented */
+            tp->t_no_move = 2;
+            if (cursed) {       /* Teleport monster to player */
+                if ((y == (hero.y + direction->y)) &&
+                    (x == (hero.x + direction->x)))
+                        msg(nothing);
+                else {
+                    tp->t_pos.y = hero.y + direction->y;
+                    tp->t_pos.x = hero.x + direction->x;
+                }
+            }
+            else if (blessed) { /* Get rid of monster */
+                killed(item, FALSE, TRUE, TRUE);
+                return;
+            }
+            else {
+                register int i=0;
+
+                do {    /* Move monster to another room */
+                    rm = rnd_room();
+                    rnd_pos(&rooms[rm], &tp->t_pos);
+                }until(winat(tp->t_pos.y,tp->t_pos.x)==FLOOR ||i++>500);
+                rp = &rooms[rm];
+            }
+
+            /* Now move the monster */
+            if (isalpha(mvwinch(cw, y, x)))
+                mvwaddch(cw, y, x, tp->t_oldch);
+            mvwaddch(mw, y, x, ' ');
+            mvwaddch(mw, tp->t_pos.y, tp->t_pos.x, tp->t_type);
+            if (tp->t_pos.y != y || tp->t_pos.x != x)
+                tp->t_oldch = mvwinch(cw, tp->t_pos.y, tp->t_pos.x);
+            /*
+             * check to see if room that creature appears in should
+             * light up
+             */
+            if (on(*tp, HASFIRE)) {
+                if (rp) {
+                    register struct linked_list *fire_item;
+
+                    fire_item = creat_item();
+                    ldata(fire_item) = (char *) tp;
+                    attach(rp->r_fires, fire_item);
+                    rp->r_flags |= HASFIRE;
+                    if(cansee(tp->t_pos.y, tp->t_pos.x) && 
+                       next(rp->r_fires) == NULL)
+                        light(&hero);
+                }
+            }
+        }
+        when WS_CANCEL:
+            if (tp == NULL)
+                break;
+            if (save(VS_MAGIC, tp, 0)) {
+                msg(nothing);
+                break;
+            }
+            check_residue(tp);
+            tp->t_flags[0] &= CANC0MASK;
+            tp->t_flags[1] &= CANC1MASK;
+            tp->t_flags[2] &= CANC2MASK;
+            tp->t_flags[3] &= CANC3MASK;
+            tp->t_flags[4] &= CANC4MASK;
+            tp->t_flags[5] &= CANC5MASK;
+            tp->t_flags[6] &= CANC6MASK;
+            tp->t_flags[7] &= CANC7MASK;
+            tp->t_flags[8] &= CANC8MASK;
+            tp->t_flags[9] &= CANC9MASK;
+            tp->t_flags[10] &= CANCAMASK;
+            tp->t_flags[11] &= CANCBMASK;
+            tp->t_flags[12] &= CANCCMASK;
+            tp->t_flags[13] &= CANCDMASK;
+            tp->t_flags[14] &= CANCEMASK;
+            tp->t_flags[15] &= CANCFMASK;
+
+        when WS_MISSILE:
+        {
+            int dice;
+            static struct object bolt =
+            {
+                MISSILE , {0, 0}, 0, "", "1d4 " , NULL, 0, WS_MISSILE, 50, 1
+            };
+
+            if (!obj)
+                dice = zapper->t_stats.s_lvl;
+            if (obj->o_type == RELIC)
+                 dice = 15;
+            else if (EQUAL(ws_type[which], "staff"))
+                 dice = 10;
+            else
+                 dice = 6;
+            sprintf(bolt.o_hurldmg, "%dd4", dice);
+            do_motion(&bolt, direction->y, direction->x, zapper);
+            if (!hit_monster(unc(bolt.o_pos), &bolt, zapper))
+               msg("The missile vanishes with a puff of smoke");
+        }
+        when WS_HIT:
+        {
+            register unsigned char ch;
+            struct object strike; /* don't want to change sticks attributes */
+
+            direction->y += hero.y;
+            direction->x += hero.x;
+            ch = winat(direction->y, direction->x);
+            if (isalpha(ch))
+            {
+                strike = *obj;
+                strike.o_hplus  = 7;
+                if (EQUAL(ws_type[which], "staff"))
+                    strcpy(strike.o_damage,"3d8");
+                else
+                    strcpy(strike.o_damage,"2d8");
+                fight(direction, &strike, FALSE);
+            }
+        }
+        when WS_SLOW_M:
+            if (is_player) {
+                add_slow();
+                break;
+            }
+            if (tp == NULL)
+                break;
+            if (cursed) {
+                if (on(*tp, ISSLOW))
+                    turn_off(*tp, ISSLOW);
+                else
+                    turn_on(*tp, ISHASTE);
+                break;
+            }
+            if ((on(*tp,ISUNIQUE) && save(VS_MAGIC,tp,0)) || on(*tp,NOSLOW)) {
+                msg(nothing);
+                break;
+            }
+            else if (blessed) {
+                turn_off(*tp, ISRUN);
+                turn_on(*tp, ISHELD);
+            }
+            /*
+             * always slow in case he breaks free of HOLD
+             */
+            if (on(*tp, ISHASTE))
+                turn_off(*tp, ISHASTE);
+            else
+                turn_on(*tp, ISSLOW);
+
+        when WS_CHARGE:
+            if (ws_know[WS_CHARGE] != TRUE && obj)
+                msg("This is a wand of charging.");
+            nitem = get_item(pack, "charge", STICK, FALSE, FALSE);
+            if (nitem != NULL) {
+                nobj = OBJPTR(nitem);
+                if ((++(nobj->o_charges) == 1) && (nobj->o_which == WS_HIT))
+                    fix_stick(nobj);
+                if (blessed) ++(nobj->o_charges);
+                if (EQUAL(ws_type[nobj->o_which], "staff")) {
+                    if (nobj->o_charges > 200) 
+                        nobj->o_charges = 200;
+                }
+                else {
+                    if (nobj->o_charges > 200)
+                        nobj->o_charges = 200;
+                }
+            }
+        when WS_ELECT:
+            shoot_bolt( zapper, zapper->t_pos, *direction, TRUE, D_BOLT, 
+                        "lightning bolt", roll(zapper->t_stats.s_lvl,6));
+
+        when WS_FIRE:
+            shoot_bolt( zapper, zapper->t_pos, *direction, TRUE, D_BOLT, 
+                        "flame", roll(zapper->t_stats.s_lvl,6));
+
+        when WS_COLD:
+            shoot_bolt( zapper, zapper->t_pos, *direction, TRUE, D_BOLT, 
+                        "ice", roll(zapper->t_stats.s_lvl,6));
+
+        when WS_CONFMON:
+            if (cursed || is_player) { 
+                if (!save(VS_WAND, &player, 0)) {
+                    dsrpt_player();
+                    confus_player();
+                }
+                else {
+                    if (zapper != &player) zapper->t_wand /= 2;
+                    msg(nothing);
+                }
+            }
+            else {
+                if (tp == NULL)
+                    break;
+                if (save(VS_MAGIC, tp, 0) || on(*tp, ISCLEAR))
+                     msg(nothing);
+                else
+                     turn_on (*tp, ISHUH);
+            }
+        when WS_PARALYZE:
+            if (is_player || cursed) {
+                if ((obj && obj->o_type==RELIC) || !save(VS_WAND, &player, 0)){
+                    player.t_no_move += 2 * movement(&player) * FREEZETIME;
+                    player.t_action = A_FREEZE;
+                    msg("You can't move.");
+                }
+                else {
+                    if (zapper != &player) zapper->t_wand /= 2;
+                    msg(nothing);
+                }
+            }
+            else {
+                if (tp == NULL)
+                    break;
+                bonus = 0;
+                if (blessed) bonus = -3;
+                if (((obj && obj->o_type==RELIC) || !save(VS_WAND,tp,bonus)) &&
+                    off(*tp, NOPARALYZE)) {
+                    tp->t_no_move += 2 * movement(tp) * FREEZETIME;
+                    tp->t_action = A_FREEZE;
+                }
+                else {
+                    msg(nothing);
+                }
+            }
+        when WS_FEAR:
+            if (is_player) {
+                if (!on(player, ISFLEE)         || 
+                    ISWEARING(R_HEROISM)        || 
+                    save(VS_WAND, &player, 0)) {
+                        msg(nothing);
+                        zapper->t_wand /= 2;
+                }
+                else {
+                    turn_on(player, ISFLEE);
+                    player.t_dest = &zapper->t_pos;
+                    msg("The sight of %s terrifies you.", prname(mname, FALSE));
+                }
+                break;
+            }
+            if (tp == NULL)
+                break;
+            bonus = 0;
+            if (blessed) bonus = -3;
+            if(save(VS_WAND, tp,bonus) || on(*tp,ISUNDEAD) || on(*tp,NOFEAR)){
+                    msg(nothing);
+                    break;
+            }
+            turn_on(*tp, ISFLEE);
+            turn_on(*tp, WASTURNED);
+
+            /* Stop it from attacking us */
+            dsrpt_monster(tp, TRUE, cansee(tp->t_pos.y, tp->t_pos.x));
+
+            /* If monster was suffocating, stop it */
+            if (on(*tp, DIDSUFFOCATE)) {
+                turn_off(*tp, DIDSUFFOCATE);
+                extinguish(suffocate);
+            }
+
+            /* If monster held us, stop it */
+            if (on(*tp, DIDHOLD) && (--hold_count == 0))
+                    turn_off(player, ISHELD);
+            turn_off(*tp, DIDHOLD);
+
+            /* It is okay to turn tail */
+            tp->t_oldpos = tp->t_pos;
+
+        when WS_MDEG:
+            if (is_player) {
+                if (save(VS_WAND, &player, 0)) {
+                    msg (nothing);
+                    zapper->t_wand /= 2;
+                    break;
+                }
+                pstats.s_hpt /= 2;
+                if (pstats.s_hpt <= 0) {
+            pstats.s_hpt = -1;
+                    msg("Your life has been sucked out from you!  --More--");
+                    wait_for(' ');
+                    death(zapper);
+                }
+                else
+                    msg("You feel a great drain on your system.");
+            }
+            if (tp == NULL)
+                break;
+            if (cursed) {
+                 tp->t_stats.s_hpt *= 2;
+                 msg("%s appears to be stronger now!", prname(mname, TRUE));
+            }
+            else if (on(*tp, ISUNIQUE) && save(VS_WAND, tp, 0))
+                 msg (nothing);
+            else {
+                 tp->t_stats.s_hpt /= 2;
+                 msg("%s appears to be weaker now", prname(mname, TRUE));
+            }
+            if (tp->t_stats.s_hpt < 1)
+                 killed(item, TRUE, TRUE, TRUE);
+        when WS_DISINTEGRATE:
+            if (tp == NULL)
+                break;
+            if (cursed) {
+                register int m1, m2;
+                coord mp;
+                struct linked_list *titem;
+                char ch;
+                struct thing *th;
+
+                if (on(*tp, ISUNIQUE) || on(*tp, CANSELL)) {
+                    msg (nothing);
+                    break;
+                }
+                for (m1=tp->t_pos.x-1 ; m1 <= tp->t_pos.x+1 ; m1++) {
+                    for(m2=tp->t_pos.y-1 ; m2<=tp->t_pos.y+1 ; m2++) {
+                        if (m1 == hero.x && m2 == hero.y)
+                            continue;
+                        ch = winat(m2,m1);
+                        if (shoot_ok(ch)) {
+                            mp.x = m1;  /* create it */
+                            mp.y = m2;
+                            titem = new_item(sizeof(struct thing));
+                            new_monster(titem,(short)tp->t_index,&mp,FALSE);
+                            th = THINGPTR(titem);
+                            turn_on (*th, ISMEAN);
+                            runto(th,&hero);
+                            if (on(*th, HASFIRE)) {
+                                register struct room *rp;
+
+                                rp = roomin(&th->t_pos);
+                                if (rp) {
+                                    register struct linked_list *fire_item;
+
+                                    fire_item = creat_item();
+                                    ldata(fire_item) = (char *) th;
+                                    attach(rp->r_fires, fire_item);
+                                    rp->r_flags |= HASFIRE;
+                                    if (cansee(th->t_pos.y, th->t_pos.x) &&
+                                        next(rp->r_fires) == NULL)
+                                        light(&hero);
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+            else { /* if its a UNIQUE it might still live */
+                if (on(*tp, ISUNIQUE) && save(VS_MAGIC, tp, 0)) {
+                    tp->t_stats.s_hpt /= 2;
+                    if (tp->t_stats.s_hpt < 1) {
+                         killed(item, FALSE, TRUE, TRUE);
+                         msg("You have disintegrated %s", prname(mname, FALSE));
+                    }
+                    else {
+                        msg("%s appears wounded", prname(mname, TRUE));
+                    }
+                }
+                else {
+                    msg("You have disintegrated %s", prname(mname, FALSE));
+                    killed (item, FALSE, TRUE, TRUE);
+                }
+            }
+        when WS_CURING:
+            if (cursed) {
+        bool sick = FALSE;
+                if (!save(VS_POISON, &player, 0)) {
+                    msg("You feel extremely sick. ");
+            sick = TRUE;
+                    pstats.s_hpt -= (pstats.s_hpt/3)+1;
+                    if (pstats.s_hpt == 0)  {
+            pstats.s_hpt = -1;
+            msg("You die!  --More--");
+            wait_for(' ');
+            death (D_POISON);
+            }
+                }
+                if (!save(VS_WAND, &player, 0) && !ISWEARING(R_HEALTH)) {
+                    turn_on(player, HASDISEASE);
+                    turn_on(player, HASINFEST);
+                    turn_on(player, DOROT);
+                    fuse(cure_disease, (VOID *)NULL, roll(HEALTIME,SICKTIME), AFTER);
+                    infest_dam++;
+                }
+        else if (sick == FALSE) msg("You feel momentarily sick");
+            }
+            else {
+                if (on(player, HASDISEASE) || on(player, HASINFEST)) {
+                    extinguish(cure_disease);
+                    turn_off(player, HASINFEST);
+                    infest_dam = 0;
+                    cure_disease(); /* this prints message */
+                }
+                if (on(player, DOROT)) {
+                    msg("You feel your skin returning to normal.");
+                    turn_off(player, DOROT);
+                }
+                pstats.s_hpt += roll(pstats.s_lvl, blessed ? 9 : 6);
+                if (pstats.s_hpt > max_stats.s_hpt)
+                    pstats.s_hpt = max_stats.s_hpt;
+                msg("You begin to feel %sbetter.", blessed ? "much " : "");
+                    
+            }
+        otherwise:
+            msg("What a bizarre schtick!");
+    }
+}
+
+
+/*
+ * drain:
+ *      Do drain hit points from player shtick
+ */
+
+drain(ymin, ymax, xmin, xmax)
+int ymin, ymax, xmin, xmax;
+{
+    register int i, j, count;
+    register struct thing *ick;
+    register struct linked_list *item;
+
+    /*
+     * First count how many things we need to spread the hit points among
+     */
+    count = 0;
+    for (i = ymin; i <= ymax; i++) {
+        if (i < 1 || i > lines - 3)
+            continue;
+        for (j = xmin; j <= xmax; j++) {
+            if (j < 0 || j > cols - 1)
+                continue;
+            if (isalpha(mvwinch(mw, i, j)))
+                count++;
+        }
+    }
+    if (count == 0)
+    {
+        msg("You have a tingling feeling.");
+        return;
+    }
+    count = pstats.s_hpt / count;
+    pstats.s_hpt /= 2;
+    if (pstats.s_hpt <= 0) {
+    pstats.s_hpt = -1;
+    msg("Aarrgghhh!!  --More--");
+    wait_for(' ');
+    death(D_STRENGTH);
+    }
+    /*
+     * Now zot all of the monsters
+     */
+    for (i = ymin; i <= ymax; i++) {
+        if (i < 1 || i > lines - 3)
+            continue;
+        for (j = xmin; j <= xmax; j++) {
+            if (j < 0 || j > cols - 1)
+                continue;
+            if (isalpha(mvwinch(mw, i, j)) &&
+                ((item = find_mons(i, j)) != NULL)) {
+                ick = THINGPTR(item);
+                if (on(*ick, ISUNIQUE) && save(VS_MAGIC, ick, 0)) 
+                    ick->t_stats.s_hpt -= count / 2;
+                else
+                    ick->t_stats.s_hpt -= count;
+                if (ick->t_stats.s_hpt < 1)
+                    killed(item, 
+                           cansee(i,j)&&(!on(*ick,ISINVIS)||on(player,CANSEE)),
+                           TRUE, TRUE);
+                else {
+                    runto(ick, &hero);
+
+                    /* 
+                     * The monster may not like being shot at.  Since the
+                     * shot is not aimed directly at the monster, we will
+                     * give him a poorer save.
+                     */
+                    if (on(*ick, ISCHARMED) && save(VS_MAGIC, ick, -2)) {
+                        msg("The eyes of %s turn clear.",
+                            prname(monster_name(ick), FALSE));
+                        turn_off(*ick, ISCHARMED);
+                    }
+                    if (cansee(i,j) && (!on(*ick,ISINVIS)||on(player,CANSEE)))
+                            msg("%s appears wounded", 
+                                prname(monster_name(ick), TRUE));
+                }
+            }
+        }
+    }
+}
+
+/*
+ * initialize a stick
+ */
+
+fix_stick(cur)
+register struct object *cur;
+{
+    if (EQUAL(ws_type[cur->o_which], "staff")) {
+        cur->o_weight = 100;
+        cur->o_charges = 5 + rnd(11);
+        strcpy(cur->o_damage,"3d4");
+        cur->o_hplus = 1;
+        cur->o_dplus = 0;
+        switch (cur->o_which) {
+            case WS_HIT:
+                cur->o_hplus = 3;
+                cur->o_dplus = 3;
+                strcpy(cur->o_damage,"2d8");
+            when WS_LIGHT:
+                cur->o_charges = 15 + rnd(11);
+            }
+    }
+    else {
+        strcpy(cur->o_damage,"2d3");
+        cur->o_weight = 75;
+        cur->o_hplus = 1;
+        cur->o_dplus = 0;
+        cur->o_charges = 5 + rnd(11);
+        switch (cur->o_which) {
+            case WS_HIT:
+                cur->o_hplus = 3;
+                cur->o_dplus = 3;
+                strcpy(cur->o_damage,"2d8");
+            when WS_LIGHT:
+                cur->o_charges = 15 + rnd(11);
+            }
+    }
+    strcpy(cur->o_hurldmg,"3d3");
+
+}
+
+/*
+ * Use the wand that our monster is wielding.
+ */
+
+m_use_wand(monster)
+register struct thing *monster;
+{
+    register struct object *obj;
+
+    /* Make sure we really have it */
+    if (monster->t_using) 
+        obj = OBJPTR(monster->t_using);
+    else {
+        debug("Stick not set!");
+        monster->t_action = A_NIL;
+        return;
+    }
+
+    if (obj->o_type != STICK) {
+        debug("Stick not selected!");
+        monster->t_action = A_NIL;
+        return;
+    }
+    /*
+     * shoot the stick!
+     * assume all blessed sticks are normal for now. 
+     * Note that we don't get here if the wand is cursed.
+     */
+    msg("%s points a %s at you!", prname(monster_name(monster), TRUE),
+        ws_type[obj->o_which]);
+    do_zap(monster, obj, &monster->t_newpos, obj->o_which, NULL);
+    monster->t_wand /= 2; /* chance lowers with each use */
+}
+
+bool
+need_dir(type, which)
+int     type,           /* type of item, NULL means stick */
+        which;          /* which item                     */
+{
+    if (type == STICK || type == 0) {
+        switch (which) {
+            case WS_LIGHT:
+            case WS_DRAIN: 
+            case WS_CHARGE:
+            case WS_CURING:
+                return(FALSE);
+            default:
+                return(TRUE);
+        }
+    }
+    else if (type == RELIC) {
+        switch (which) {
+            case MING_STAFF:
+            case ASMO_ROD:
+            case EMORI_CLOAK:
+                return(TRUE);
+            default:
+                return(FALSE);
+        }
+    }
+return (FALSE); /* hope we don't get here */
+}
+
+/*
+ * let the player zap a stick and see what happens
+ */
+
+player_zap(which, flag)
+int which;
+int flag;
+{
+    register struct linked_list *item;
+    register struct object *obj;
+
+    obj = NULL;
+    if (which == 0) {
+        /* This is a stick.  It takes 2 movement periods to zap it */
+        if (player.t_action != C_ZAP) {
+            if ((item = get_item(pack,"zap with",ZAPPABLE,FALSE,FALSE)) == NULL)
+                return(FALSE);
+
+            obj = OBJPTR(item);
+
+            if (need_dir(obj->o_type, obj->o_which)) {
+                if (!get_dir(&player.t_newpos))
+                    return(FALSE);
+            }
+            player.t_using = item;      /* Remember what it is */
+            player.t_action = C_ZAP;    /* We are quaffing */
+            player.t_no_move = 2 * movement(&player);
+            return(TRUE);
+        }
+
+        item = player.t_using;
+        /* We've waited our time, let's shoot 'em up! */
+        player.t_using = NULL;
+        player.t_action = A_NIL;
+
+        obj = OBJPTR(item);
+
+        /* Handle relics specially here */
+        if (obj->o_type == RELIC) {
+            switch (obj->o_which) {
+                case ORCUS_WAND:
+            /* msg(nothing); */
+            read_scroll(S_PETRIFY, NULL, FALSE);
+            return(TRUE);
+                when MING_STAFF:
+                    which = WS_MISSILE;
+                when EMORI_CLOAK:
+                    which = WS_PARALYZE;
+                    obj->o_charges = 0; /* one zap/day (whatever that is) */
+                    fuse(cloak_charge, obj, CLOAK_TIME, AFTER);
+                when ASMO_ROD:
+                    switch (rnd(3)) {
+                        case 0:         which = WS_ELECT;
+                        when 1:         which = WS_COLD;
+                        otherwise:      which = WS_FIRE;
+                    }
+            }
+        }
+        else {
+            which = obj->o_which;
+            ws_know[which] = TRUE;
+            flag = obj->o_flags;
+        }
+    }
+    do_zap(&player, obj, &player.t_newpos, which, flag);
+    return(TRUE);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xrogue/things.c	Tue Apr 21 08:55:20 2015 -0400
@@ -0,0 +1,951 @@
+/*
+    things.c - functions for dealing with things like potions and scrolls
+    
+    XRogue: Expeditions into the Dungeons of Doom
+    Copyright (C) 1991 Robert Pietkivitch
+    All rights reserved.
+    
+    Based on "Advanced Rogue"
+    Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka and AT&T
+    All rights reserved.
+
+    Based on "Rogue: Exploring the Dungeons of Doom"
+    Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
+    All rights reserved.
+    
+    See the file LICENSE.TXT for full copyright and licensing information.
+*/
+
+#include <curses.h>
+#include <ctype.h>
+#include "rogue.h"
+
+/*
+ * print out the number of charges on a stick
+ */
+
+char *
+charge_str(obj)
+register 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;
+}
+
+/*
+ * inv_name:
+ *      return the name of something as it would appear in an
+ *      inventory.
+ */
+
+char *
+inv_name(obj, drop)
+register struct object *obj;
+bool drop;
+{
+    register char *pb;
+
+    pb = prbuf;
+    pb[0] = '\0';
+    switch(obj->o_type) {
+        case SCROLL:
+            if (obj->o_count == 1)
+                 sprintf(pb, "A %sscroll ", blesscurse(obj->o_flags));
+            else
+                 sprintf(pb, "%d %sscrolls ", 
+                        obj->o_count, blesscurse(obj->o_flags));
+            pb = &pb[strlen(pb)];
+            if (s_know[obj->o_which] || (obj->o_flags & ISPOST))
+                sprintf(pb, "of %s", s_magic[obj->o_which].mi_name);
+            else if (s_guess[obj->o_which])
+                sprintf(pb, "named %s", s_guess[obj->o_which]);
+            else
+                sprintf(pb, "titled '%s'", s_names[obj->o_which]);
+        when POTION:
+            if (obj->o_count == 1)
+                 sprintf(pb, "A %spotion ", blesscurse(obj->o_flags));
+            else
+                 sprintf(pb, "%d %spotions ", 
+                        obj->o_count, blesscurse(obj->o_flags));
+            pb = &pb[strlen(pb)];
+            if (p_know[obj->o_which])
+                sprintf(pb, "of %s (%s)", p_magic[obj->o_which].mi_name,
+                    p_kind(obj));
+            else if (obj->o_flags & ISPOST)
+                sprintf(pb, "of %s", p_magic[obj->o_which].mi_name);
+            else if (p_guess[obj->o_which])
+                sprintf(pb, "named %s (%s)", p_guess[obj->o_which],
+                    p_colors[obj->o_which]);
+            else {
+                pb = prbuf;
+                if (obj->o_count == 1)
+                    sprintf(pb, "A%s %s potion",
+                            vowelstr(p_colors[obj->o_which]),
+                            p_colors[obj->o_which]);
+                else
+                    sprintf(pb, "%d %s potions",
+                            obj->o_count, p_colors[obj->o_which]);
+            }
+        when FOOD:
+            if (obj->o_count == 1)
+                sprintf(pb, "A%s %s", vowelstr(foods[obj->o_which].mi_name), 
+                        foods[obj->o_which].mi_name);
+            else
+                sprintf(pb, "%d %ss", obj->o_count,foods[obj->o_which].mi_name);
+        when WEAPON:
+            if (obj->o_count > 1)
+                sprintf(pb, "%d ", obj->o_count);
+            else
+                strcpy(pb, "A ");
+            pb = &pb[strlen(pb)];
+            if (obj->o_flags & ISKNOW) {
+                strcat(pb, num(obj->o_hplus, obj->o_dplus));
+                strcat (pb, " ");
+            }
+            strcat(pb, weaps[obj->o_which].w_name);
+            if (obj->o_count > 1)
+                strcat(pb, "s");
+            if (obj == cur_weapon)
+                strcat(pb, " (weapon in hand)");
+            if (obj->o_flags & ISPOISON)
+                strcat(pb, " {Poisoned}");
+        when ARMOR:
+            if (obj->o_flags & ISKNOW) {
+                strcat(pb, num(armors[obj->o_which].a_class - obj->o_ac, 0));
+                strcat(pb, " ");
+            }
+            strcat(pb, armors[obj->o_which].a_name);
+            if (obj == cur_armor)
+                strcat(pb, " (being worn)");
+        when STICK:
+            sprintf(pb, "A %s%s ", 
+                blesscurse(obj->o_flags), ws_type[obj->o_which]);
+            pb = &pb[strlen(pb)];
+            if (ws_know[obj->o_which] || obj->o_flags & ISKNOW)
+                sprintf(pb, "of %s%s (%s)", ws_magic[obj->o_which].mi_name,
+                    charge_str(obj), ws_made[obj->o_which]);
+            else if (obj->o_flags & ISPOST)
+                sprintf(pb, "of %s", ws_magic[obj->o_which].mi_name);
+            else if (ws_guess[obj->o_which])
+                sprintf(pb, "named %s (%s)", ws_guess[obj->o_which],
+                    ws_made[obj->o_which]);
+            else {
+                pb = prbuf;
+                sprintf(pb, "A %s %s", ws_made[obj->o_which],
+                    ws_type[obj->o_which]);
+            }
+            if (obj == cur_weapon)
+                strcat(prbuf, " (weapon in hand)");
+        when RING:
+            if (r_know[obj->o_which] || obj->o_flags & ISKNOW)
+                sprintf(pb, "A%s ring of %s (%s)", ring_num(obj),
+                    r_magic[obj->o_which].mi_name, r_stones[obj->o_which]);
+            else if (obj->o_flags & ISPOST)
+                sprintf(pb, "A ring of %s", r_magic[obj->o_which].mi_name);
+            else if (r_guess[obj->o_which])
+                sprintf(pb, "A ring named %s (%s)",
+                    r_guess[obj->o_which], r_stones[obj->o_which]);
+            else
+                sprintf(pb, "A%s %s ring", vowelstr(r_stones[obj->o_which]),
+                    r_stones[obj->o_which]);
+            if     (obj == cur_ring[LEFT_1] || obj == cur_ring[LEFT_2]  ||
+                    obj == cur_ring[LEFT_3] || obj == cur_ring[LEFT_4])
+            strcat(pb, " (on left hand)");
+            if     (obj == cur_ring[RIGHT_1] || obj == cur_ring[RIGHT_2]  ||
+                    obj == cur_ring[RIGHT_3] || obj == cur_ring[RIGHT_4])
+            strcat(pb, " (on right hand)");
+        when RELIC:
+            if (obj->o_flags & ISKNOW)
+                switch(obj->o_which) {
+                case QUILL_NAGROM:
+                    sprintf(pb, "%s%s", rel_magic[obj->o_which].mi_name, 
+                            charge_str(obj));
+                otherwise:
+                    strcpy(pb, rel_magic[obj->o_which].mi_name);
+            }
+            else switch(obj->o_which) {
+                case MUSTY_DAGGER:
+                    strcpy(pb, "Two very fine daggers marked MDDE");
+                when EMORI_CLOAK:
+                    strcpy(pb, "A silk cloak");
+                when HEIL_ANKH:
+                    strcpy(pb, "A golden ankh");
+                when MING_STAFF:
+                    strcpy(pb, "A finely carved staff");
+                when ORCUS_WAND:
+                    strcpy(pb, "A sparkling ivory wand");
+                when ASMO_ROD:
+                    strcpy(pb, "A glistening ebony rod");
+                when YENDOR_AMULET:
+                    strcpy(pb, "A silver amulet");
+                when STONEBONES_AMULET:
+                    strcpy(pb, "A stone amulet");
+                when BRIAN_MANDOLIN:
+                    strcpy(pb, "A gleaming mandolin");
+                when HRUGGEK_MSTAR:
+                    strcpy(pb, "A silvery morning star");
+                when AXE_AKLAD:
+                    strcpy(pb, "A jewel encrusted axe");
+                when QUILL_NAGROM:
+                    strcpy(pb, "A bright white feather");
+                when GERYON_HORN:
+                    strcpy(pb, "A jet black horn");
+                when YEENOGHU_FLAIL:
+                    strcpy(pb, "A shimmering flail");
+                when SURTUR_RING:
+                    strcpy(pb, "A fiery red ring");
+                when ALTERAN_CARD:
+                    strcpy(pb, "A rectangular piece of wood");
+                otherwise:
+                    strcpy(pb, "A wholly magical item");
+            }
+
+            /* Take care of wielding and wearing */
+            switch (obj->o_which) {
+                case EMORI_CLOAK:
+                    if (cur_armor == NULL && cur_misc[WEAR_CLOAK] == NULL)
+                        strcat(pb, " (being worn)");
+                    if (obj->o_charges)
+                        strcat(pb, " [charged]");
+                    else
+                        strcat(pb, " [discharged]");
+                when HEIL_ANKH:
+                    if (cur_relic[HEIL_ANKH]) strcat(pb, " (in palm)");
+                when EYE_VECNA:
+                    if (cur_relic[EYE_VECNA]) strcat(pb, " (in forehead)");
+                when STONEBONES_AMULET:
+                    if (cur_relic[STONEBONES_AMULET])
+                        strcat(pb, " (in chest)");
+                when YENDOR_AMULET:
+                    if (cur_relic[YENDOR_AMULET])
+                        strcat(pb, " (in chest)");
+                when MUSTY_DAGGER:
+                case HRUGGEK_MSTAR:
+                case AXE_AKLAD:
+                case YEENOGHU_FLAIL:
+                case MING_STAFF:
+                case ASMO_ROD:
+                case ORCUS_WAND:
+                    if (cur_weapon == obj) strcat(pb, " (weapon in hand)");
+                when SURTUR_RING:
+                    if (cur_relic[SURTUR_RING])
+                        strcat(pb, " (in nose)");
+            }
+        when MM:
+            if (m_know[obj->o_which])
+            { 
+                misc_name(pb,obj);
+            }
+            else {
+                switch (obj->o_which) {
+                    case MM_JUG:
+                    case MM_BEAKER:
+                    case MM_KEOGHTOM:
+                        strcpy(pb, "A crystalline jar");
+                    when MM_BOOK:
+                    case MM_SKILLS:
+                        strcpy(pb, "A dusty book");
+                    when MM_ELF_BOOTS:
+                    case MM_DANCE:
+                        strcpy(pb, "A pair of old boots");
+                    when MM_BRACERS:
+                        strcpy(pb, "A set of bracers");
+                    when MM_OPEN:
+                    case MM_HUNGER:
+                        strcpy(pb, "A mysterious chime");
+                    when MM_DISP:
+                    case MM_R_POWERLESS:
+                    case MM_PROTECT:
+                        strcpy(pb, "A dark looking cloak");
+                    when MM_DRUMS:
+                        strcpy(pb, "A drum set");
+                    when MM_DISAPPEAR:
+                    case MM_CHOKE:
+                        strcpy(pb, "A small pouch of dust");
+                    when MM_G_DEXTERITY:
+                    case MM_G_OGRE:
+                    case MM_FUMBLE:
+                        strcpy(pb, "A set of gauntlets");
+                    when MM_ADAPTION:
+                    case MM_JEWEL:
+                    case MM_STRANGLE:
+                        strcpy(pb, "A little necklace");
+            when MM_CRYSTAL:
+            strcpy(pb, "An unusual looking rock");
+                    otherwise:
+                        strcpy(pb, "A magical item");
+                }
+                if (m_guess[obj->o_which]) {
+                    strcat(pb, " named: ");
+                    strcat(pb, m_guess[obj->o_which]);
+                }
+            }
+            if (obj == cur_misc[WEAR_BOOTS]     ||
+                obj == cur_misc[WEAR_BRACERS]   ||
+                obj == cur_misc[WEAR_CLOAK]     ||
+                obj == cur_misc[WEAR_GAUNTLET]  ||
+                obj == cur_misc[WEAR_NECKLACE]  ||
+                obj == cur_misc[WEAR_JEWEL]) 
+                    strcat(pb, " (being worn)");
+        when GOLD:
+                sprintf(pb, "%d Pieces of Gold", obj->o_count);
+        otherwise:
+            debug("Picked up something funny");
+            sprintf(pb, "Something totally bizarre %s", unctrl(obj->o_type));
+        wait_for(' ');
+    }
+
+    /* Is it marked? */
+    if (obj->o_mark[0]) {
+        pb = &pb[strlen(pb)];
+        sprintf(pb, " <%s>", obj->o_mark);
+    }
+
+    if (obj->o_flags & ISPROT)
+        strcat(pb, " [protected]");
+    if (drop && isupper(prbuf[0]))
+        prbuf[0] = tolower(prbuf[0]);
+    else if (!drop && islower(*prbuf))
+        *prbuf = toupper(*prbuf);
+    if (!drop)
+        strcat(pb, ".");
+    /* 
+     * Truncate if long. Use cols-4 to offset the "pack letter" of a normal
+     * inventory listing.
+     */
+    prbuf[cols-4] = '\0';       
+    return prbuf;
+}
+
+/*
+ * weap_name:
+ *      Return the name of a weapon.
+ */
+
+char *
+weap_name(obj)
+register struct object *obj;
+{
+    switch (obj->o_type) {
+        case WEAPON:
+            return(weaps[obj->o_which].w_name);
+        when MISSILE:
+            return(ws_magic[obj->o_which].mi_name);
+        when RELIC:
+            switch (obj->o_which) {
+                case MUSTY_DAGGER:
+                    return("daggers");
+                when YEENOGHU_FLAIL:
+                    return("flail");
+                when AXE_AKLAD:
+                    return("axe");
+                when HRUGGEK_MSTAR:
+                    return("morning star");
+                when MING_STAFF:
+                    return("staff");
+                when ORCUS_WAND:
+                    return("wand");
+                when ASMO_ROD:
+                    return("rod");
+            }
+    }
+    return("weapon");
+}
+
+/*
+ * drop:
+ *      put something down
+ */
+
+drop(item)
+struct linked_list *item;
+{
+    register char ch = 0;
+    register struct linked_list *obj, *nobj;
+    register struct object *op;
+
+    if (item == NULL) {
+        /* We charge 2 movement times to drop something */
+        if (player.t_action == C_DROP && player.t_using != NULL) {
+            obj = player.t_using;
+            player.t_using = NULL;
+            player.t_action = A_NIL;
+        }
+
+        /* t_action == C_DROP always when called from command() */
+        else {
+            if ((obj = get_item(pack, "drop", ALL, FALSE, FALSE)) == NULL) {
+                player.t_action = A_NIL;
+                player.t_using = NULL;
+                return(FALSE);
+            }
+            if (player.t_action == C_DROP) {
+                player.t_using = obj;
+                player.t_no_move = 2 * movement(&player);
+                return(FALSE);  /* We'll come back after we've waited */
+            }
+        }
+
+        switch(ch = mvwinch(stdscr, hero.y, hero.x)) {
+        case PASSAGE: 
+        case SCROLL:
+        case POTION:
+        case WEAPON:
+        case FLOOR:
+        case STICK:
+        case ARMOR:
+        case POOL:
+        case RELIC:
+        case GOLD:
+        case FOOD:
+        case RING:
+        case MM:
+            break;
+        default:
+            msg("You can't leave it here");
+            return(FALSE);
+        }
+    }
+    else {
+        obj = item;
+    }
+    op = OBJPTR(obj);
+    if (!dropcheck(op))
+        return(FALSE);
+
+    /*
+     * If it is a scare monster scroll, curse it
+     */
+    if (op->o_type == SCROLL && op->o_which == S_SCARE) {
+        if (op->o_flags & ISBLESSED)
+            op->o_flags &= ~ISBLESSED;
+        else op->o_flags |= ISCURSED;
+    }
+
+    /*
+     * Take it out of the pack
+     */
+    if (op->o_count >= 2 && op->o_group == 0)
+    {
+        nobj = new_item(sizeof *op);
+        op->o_count--;
+        op = OBJPTR(nobj);
+        *op = *(OBJPTR(obj));
+        op->o_count = 1;
+        obj = nobj;
+    }
+    else {
+        detach(pack, obj);
+        inpack--;
+    }
+    if(ch == POOL) {
+        msg("Gloop... Your %s sinks out of sight. ",inv_name(op,TRUE));
+        o_discard(obj);
+    }
+    else if (levtype == POSTLEV) {
+        op->o_pos = hero;       /* same place as hero */
+        fall(obj,FALSE);
+        if (item == NULL)       /* if item wasn't sold */
+            msg("Thanks for your donation to the Fiend's flea market.");
+    }
+    else {
+        /*
+         * 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));
+    }
+    updpack(FALSE, &player);
+    return (TRUE);
+}
+
+/*
+ * do special checks for dropping or unweilding|unwearing|unringing
+ */
+
+dropcheck(op)
+register struct object *op;
+{
+    int save_max;
+
+    if (op == NULL)
+        return TRUE;
+    if (levtype == POSTLEV) {
+        if ((op->o_flags & ISCURSED) && (op->o_flags & ISKNOW)) {
+            msg("The trader does not accept shoddy merchandise.");
+            return(FALSE);
+        }
+    }
+
+    /* Player will not drop a relic */
+    if (op->o_type == RELIC) {
+        /*
+         * There is a 1% cumulative chance per relic that trying to get
+         * rid of it will cause the relic to turn on the player.
+         */
+        if (rnd(150) < cur_relic[op->o_which]++) {
+            msg("The artifact turns on you! ");
+            msg("It crushes your mind!!!  --More--");
+            pstats.s_hpt = -1;
+            wait_for (' ');
+            death(D_RELIC);
+        }
+        else {
+            if (terse) msg("You can't release it.");
+            else msg("You cannot bring yourself to release it.");
+            return FALSE;
+        }
+    }
+
+    /* If we aren't wearing it, we can drop it */
+    if (!is_current(op)) return TRUE;
+
+    /* At this point, we know we are wearing the item */
+    if (op->o_flags & ISCURSED) {
+        msg("You can't.  It appears to be cursed.");
+        return FALSE;
+    }
+    if (op->o_type == RING && cur_misc[WEAR_GAUNTLET] != NULL) {
+        msg ("You have to remove your gauntlets first!");
+        return FALSE;
+    }
+    cur_null(op);       /* set current to NULL */
+    if (op->o_type == RING) {
+        switch (op->o_which) {
+        case R_ADDSTR:    save_max = max_stats.s_str;
+                          chg_str(-op->o_ac);
+                          max_stats.s_str = save_max;
+        when R_ADDHIT:    pstats.s_dext -= op->o_ac;
+        when R_ADDINTEL:  pstats.s_intel -= op->o_ac;
+        when R_ADDWISDOM: pstats.s_wisdom -= op->o_ac;
+        when R_SEEINVIS:  if (!ISWEARING(R_SEEINVIS) &&
+                              find_slot(unsee) == 0) {
+                                turn_off(player, CANSEE);
+                                msg("The tingling feeling leaves your eyes. ");
+                          }
+                          light(&hero);
+                          mvwaddch(cw, hero.y, hero.x, PLAYER);
+        when R_WARMTH:    if (!ISWEARING(R_WARMTH) && !find_slot(nocold)) 
+                                turn_off(player, NOCOLD);
+        when R_FIRE:      if (!ISWEARING(R_FIRE)        && 
+                              !cur_relic[SURTUR_RING]   &&
+                              !find_slot(nofire))
+                                turn_off(player, NOFIRE);
+        when R_LIGHT: {
+                          if(roomin(&hero) != NULL) {
+                                light(&hero);
+                                mvwaddch(cw, hero.y, hero.x, PLAYER);
+                          }
+                      }
+        when R_SEARCH:    kill_daemon(ring_search);
+        when R_TELEPORT:  kill_daemon(ring_teleport);
+        }
+    }
+    else if (op->o_type == MM) {
+        switch (op->o_which) {
+            case MM_ADAPTION:
+                turn_off(player, NOGAS);
+                turn_off(player, NOACID);
+
+            when MM_STRANGLE:
+                msg("You can breathe again.....whew!");
+                kill_daemon(strangle);
+
+            when MM_DANCE:
+                turn_off(player, ISDANCE);
+                msg ("Your feet take a break.....whew!");
+
+            when MM_FUMBLE:
+                kill_daemon(fumble);
+
+            when MM_G_OGRE:
+            case MM_G_DEXTERITY:
+                save_max = max_stats.s_str;
+                chg_str(-op->o_ac);
+                max_stats.s_str = save_max;
+        }
+    }
+    return TRUE;
+}
+
+/*
+ * return a new thing
+ */
+
+struct linked_list *
+new_thing(thing_type, allow_curse)
+int thing_type;
+bool allow_curse;
+{
+    register struct linked_list *item;
+    register struct object *cur;
+    register int j;
+    register int blesschance, cursechance;
+
+    item = new_item(sizeof *cur);
+    cur = OBJPTR(item);
+    cur->o_hplus = cur->o_dplus = 0;
+    strcpy(cur->o_damage,"0d0");
+    strcpy(cur->o_hurldmg,"0d0");
+    cur->o_ac = 0;
+    cur->o_count = 1;
+    cur->o_group = 0;
+    cur->contents = NULL;
+    cur->o_flags = 0;
+    cur->o_weight = 0;
+    cur->o_mark[0] = '\0';
+    /*
+     * Decide what kind of object it will be
+     * If we haven't had food for a while, let it be food.
+     */
+    blesschance = rnd(100);
+    if (allow_curse) cursechance = rnd(100);
+    else cursechance = 100;     /* No chance of curse */
+
+    /* Get the type of item (pick one if 'any' is specified) */
+    if (thing_type == ALL) j = pick_one(things, NUMTHINGS);
+    else j = thing_type;
+
+    /* 
+     * make sure he gets his vitamins 
+     */
+    if (thing_type == ALL && no_food > 4)
+        j = 2;  
+    /*
+     * limit the number of foods on a level because it sometimes
+     * gets out of hand in the "deep" levels where there is a 
+     * treasure room on most every level with lots of food in it
+     */
+    while (thing_type == ALL && levtype != POSTLEV && foods_this_level > 1 &&
+           j == 2)
+        j = pick_one(things, NUMTHINGS);        /* not too many.... */
+    switch (j)
+    {
+        case TYP_POTION:
+            cur->o_type = POTION;
+            do {
+                cur->o_which = pick_one(p_magic, MAXPOTIONS);
+            } while (!allow_curse && p_magic[cur->o_which].mi_curse == 100);
+            cur->o_weight = things[TYP_POTION].mi_wght;
+            if (cursechance < p_magic[cur->o_which].mi_curse)
+                cur->o_flags |= ISCURSED;
+            else if (blesschance < p_magic[cur->o_which].mi_bless)
+                cur->o_flags |= ISBLESSED;
+
+            /* If we made a gain ability potion, see what kind it is */
+            if (cur->o_which == P_ABIL) cur->o_kind = rnd(NUMABILITIES);
+
+        when TYP_SCROLL:
+            cur->o_type = SCROLL;
+            do {
+                cur->o_which = pick_one(s_magic, MAXSCROLLS);
+            } while (!allow_curse && s_magic[cur->o_which].mi_curse == 100);
+            cur->o_weight = things[TYP_SCROLL].mi_wght;
+            if (cursechance < s_magic[cur->o_which].mi_curse)
+                cur->o_flags |= ISCURSED;
+            else if (blesschance < s_magic[cur->o_which].mi_bless)
+                cur->o_flags |= ISBLESSED;
+        when TYP_FOOD:
+            no_food = 0;
+            cur->o_type = FOOD;
+            cur->o_weight = things[TYP_FOOD].mi_wght;
+            cur->o_count += extras();
+            foods_this_level += cur->o_count;
+            cur->o_which = pick_one(foods, MAXFOODS);
+        when TYP_WEAPON:
+            cur->o_type = WEAPON;
+            cur->o_which = rnd(MAXWEAPONS);
+            init_weapon(cur, cur->o_which);
+            if (cursechance < 20)
+            {
+
+                cur->o_flags |= ISCURSED;
+                cur->o_hplus -= rnd(3) + 1;
+                cur->o_dplus -= rnd(3) + 1;
+            }
+            else if (blesschance < 50) {
+
+                cur->o_hplus += rnd(5) + 1;
+                cur->o_dplus += rnd(5) + 1;
+            }
+        when TYP_ARMOR:
+            cur->o_type = ARMOR;
+            for (j = 0; j < MAXARMORS; j++)
+                if (blesschance < armors[j].a_prob)
+                    break;
+            if (j == MAXARMORS)
+            {
+                debug("Picked a bad armor %d", blesschance);
+        wait_for(' ');
+                j = 0;
+            }
+            cur->o_which = j;
+            cur->o_ac = armors[j].a_class;
+            cur->o_weight = armors[j].a_wght;
+            if (cursechance < 20)
+            {
+                cur->o_flags |= ISCURSED;
+                cur->o_ac += rnd(4)+1;
+            }
+            else if (blesschance < 40)
+                cur->o_ac -= rnd(3)+1;
+        when TYP_RING:
+            cur->o_type = RING;
+            do {
+                cur->o_which = pick_one(r_magic, MAXRINGS);
+            } while (!allow_curse && r_magic[cur->o_which].mi_curse == 100);
+            cur->o_weight = things[TYP_RING].mi_wght;
+            if (cursechance < r_magic[cur->o_which].mi_curse)
+                cur->o_flags |= ISCURSED;
+            switch (cur->o_which)
+            {
+                case R_ADDSTR:
+                case R_ADDWISDOM:
+                case R_ADDINTEL:
+                case R_PROTECT:
+                case R_ADDHIT:
+                case R_ADDDAM:
+                    cur->o_ac = rnd(2) + 1;
+                    if (cur->o_flags & ISCURSED)
+                        cur->o_ac = -cur->o_ac;
+                    if (blesschance < r_magic[cur->o_which].mi_bless)
+                        cur->o_ac+=rnd(vlevel/10)+1;
+                when R_DIGEST:
+                    if (cur->o_flags & ISCURSED) 
+                        cur->o_ac = -1;
+                    else if (blesschance < r_magic[cur->o_which].mi_bless)
+                        cur->o_ac = 2;
+                    else cur->o_ac = 1;
+            }
+        when TYP_STICK:
+            cur->o_type = STICK;
+            do {
+                cur->o_which = pick_one(ws_magic, MAXSTICKS);
+            } while (!allow_curse && ws_magic[cur->o_which].mi_curse == 100);
+            fix_stick(cur);
+            if (cursechance < ws_magic[cur->o_which].mi_curse)
+                cur->o_flags |= ISCURSED;
+            else if (blesschance < ws_magic[cur->o_which].mi_bless)
+                cur->o_flags |= ISBLESSED;
+        when TYP_MM:
+            cur->o_type = MM;
+            do {
+                cur->o_which = pick_one(m_magic, MAXMM);
+            } while (!allow_curse && m_magic[cur->o_which].mi_curse == 100);
+            cur->o_weight = things[TYP_MM].mi_wght;
+            if (cursechance < m_magic[cur->o_which].mi_curse)
+                cur->o_flags |= ISCURSED;
+            else if (blesschance < m_magic[cur->o_which].mi_bless)
+                cur->o_flags |= ISBLESSED;
+            switch (cur->o_which) {
+                case MM_JUG:
+                    switch(rnd(11)) {
+                        case 0: cur->o_ac = P_PHASE;
+                        when 1: cur->o_ac = P_CLEAR;
+                        when 2: cur->o_ac = P_SEEINVIS;
+                        when 3: cur->o_ac = P_HEALING;
+                        when 4: cur->o_ac = P_MFIND;
+                        when 5: cur->o_ac = P_TFIND;
+                        when 6: cur->o_ac = P_HASTE;
+                        when 7: cur->o_ac = P_RESTORE;
+                        when 8: cur->o_ac = P_FLY;
+                        when 9: cur->o_ac = P_SKILL;
+                        when 10:cur->o_ac = P_FFIND;
+                    }
+                when MM_HUNGER:
+                case MM_CHOKE:
+                    cur->o_ac = (2 + rnd(2)) * 3;
+                when MM_OPEN:
+                case MM_DRUMS:
+                case MM_DISAPPEAR:
+                case MM_KEOGHTOM:
+                    cur->o_ac = (5 + rnd(6)) * 3;
+                when MM_BRACERS:
+                    if (cur->o_flags & ISCURSED) 
+                        cur->o_ac = -(rnd(5)+1);
+                    else
+                        cur->o_ac = rnd(5)+1;
+                when MM_PROTECT:
+                    if (cur->o_flags & ISCURSED) 
+                        cur->o_ac = -(rnd(5)+1);
+                    else
+                        cur->o_ac = rnd(5)+1;
+                when MM_DISP:
+                    cur->o_ac = 3;
+                when MM_SKILLS: /*  set it to a character class */
+                    cur->o_ac = rnd(NUM_CHARTYPES-1);
+        when MM_CRYSTAL:
+            cur->o_ac = 1;   /* Use it just once */
+                otherwise:
+                    cur->o_ac = 0;
+            }
+        otherwise:
+            debug("Picked a bad kind of object");
+            wait_for(' ');
+    }
+    return item;
+}
+
+/*
+ * provide a new item tailored to specification
+ */
+
+struct linked_list *
+spec_item(type, which, hit, damage)
+int type, which, hit, damage;
+{
+    register struct linked_list *item;
+    register struct object *obj;
+
+    item = new_item(sizeof *obj);
+    obj = OBJPTR(item);
+    obj->o_count = 1;
+    obj->o_group = 0;
+    obj->contents = NULL;
+    obj->o_type = type;
+    obj->o_which = which;
+    strcpy(obj->o_damage,"0d0");
+    strcpy(obj->o_hurldmg,"0d0");
+    obj->o_hplus = 0;
+    obj->o_dplus = 0;
+    obj->o_flags = 0;
+    obj->o_mark[0] = '\0';
+    obj->o_launch = 0;
+    obj->o_weight = 0;
+
+    /* Handle special characteristics */
+    switch (type) {
+        case WEAPON:
+            init_weapon(obj, which);
+            obj->o_hplus = hit;
+            obj->o_dplus = damage;
+            obj->o_ac = 10;
+
+            if (hit < 0 || damage < 0) obj->o_flags |= ISCURSED;
+
+        when ARMOR:
+            obj->o_ac = armors[which].a_class - hit;
+            if (hit < 0) obj->o_flags |= ISCURSED;
+
+        when RING:
+            obj->o_ac = hit;
+            switch (obj->o_which) {
+                case R_ADDSTR:
+                case R_ADDWISDOM:
+                case R_ADDINTEL:
+                case R_PROTECT:
+                case R_ADDHIT:
+                case R_ADDDAM:
+                case R_DIGEST:
+                    if (hit < 0) obj->o_flags |= ISCURSED;
+            }
+
+        when STICK:
+            fix_stick(obj);
+            obj->o_charges = hit;
+
+        when GOLD:
+            obj->o_type = GOLD;
+            obj->o_count = GOLDCALC;
+            obj->o_ac = 11;
+        
+        when MM:
+            obj->o_type = MM;
+            obj->o_ac = hit;
+
+        when RELIC:
+            /* Handle weight here since these are all created uniquely */
+            obj->o_weight = things[TYP_RELIC].mi_wght;
+            if (obj->o_which == EMORI_CLOAK)
+                obj->o_charges = 1;
+
+    }
+    return(item);
+}
+
+/*
+ * pick an item out of a list of nitems possible magic items
+ */
+
+pick_one(magic, nitems)
+register struct magic_item *magic;
+int nitems;
+{
+    register struct magic_item *end;
+    register int i;
+    register struct magic_item *start;
+
+    start = magic;
+    for (end = &magic[nitems], i = rnd(1000); 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 magic - start;
+}
+
+
+/* blesscurse returns whether, according to the flag, the object is
+ * blessed, cursed, or neither
+ */
+
+char *
+blesscurse(flags)
+int flags;
+{
+    if (flags & ISKNOW)  {
+        if (flags & ISCURSED) return("cursed ");
+        if (flags & ISBLESSED) return("blessed ");
+        return("normal ");
+    }
+    return("");
+}
+
+/*
+ * p_kind returns the type of potion for some types of identified potions;
+ * otherwise, it returns the color.
+ */
+
+char *
+p_kind(obj)
+struct object *obj;     /* We assume that obj points to a potion */
+{
+    if (obj->o_which == P_ABIL) return(abilities[obj->o_kind].w_string);
+    else return(p_colors[obj->o_which]);
+}
+
+/*
+ * extras:
+ *      Return the number of extra items to be created
+ */
+
+extras()
+{
+        reg int i;
+
+        i = rnd(100);
+        if (i < 3)              /* 3% for 2 more */
+            return (2);
+        else if (i < 6)         /* 6% for 1 more */
+            return (1);
+        else                    /* otherwise no more */
+            return (0);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xrogue/trader.c	Tue Apr 21 08:55:20 2015 -0400
@@ -0,0 +1,498 @@
+/*
+    trader.c - Anything to do with trading posts
+    
+    XRogue: Expeditions into the Dungeons of Doom
+    Copyright (C) 1991 Robert Pietkivitch
+    All rights reserved.
+    
+    Based on "Advanced Rogue"
+    Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka and AT&T
+    All rights reserved.
+
+    See the file LICENSE.TXT for full copyright and licensing information.
+*/
+
+#include <curses.h>
+#include "rogue.h"
+
+/*
+ * buy_it:
+ *      Buy the item on which the hero stands
+ */
+
+buy_it()
+{
+        reg int wh;
+        struct linked_list *item = NULL;
+        struct object *obj = NULL;
+        int wasfood = FALSE;
+
+        if (purse <= 0) {
+            msg("You have no money.");
+            return;
+        }
+        if (curprice < 0) {             /* if not yet priced */
+            wh = price_it();
+            if (!wh)                    /* nothing to price */
+                return;
+            msg("Do you want to buy it? ");
+            do {
+                wh = wgetch(cw);
+                if (wh == ESC || wh == 'n') {
+                    msg("");
+                    return;
+                }
+            } until(wh == 'y');
+        }
+        mpos = 0;
+        if (curprice > purse) {
+            msg("You can't afford it!");
+            return;
+        }
+        /*
+         * See if the hero has done all his transacting
+         */
+        if (!open_market())
+            return;
+        /*
+         * The hero bought the item here
+         */
+        item = find_obj(hero.y, hero.x);
+        obj = OBJPTR(item);
+        mpos = 0;
+        wasfood = ISMULT(obj->o_type);
+        if (add_pack((struct linked_list *)NULL,TRUE)) {/* try to put it in his pack */
+            purse -= curprice;          /* take his money */
+            ++trader;                   /* another transaction */
+            trans_line();               /* show remaining deals */
+            curprice = -1;              /* reset stuff */
+            curpurch[0] = 0;
+            if (!wasfood) /* if it was food then the object has been deleted */
+            {
+                whatis (item);              /* identify it */
+                obj = OBJPTR(item);
+                obj->o_flags &= ~ISPOST; /* turn off ISPOST */
+                obj->o_flags |= ISKNOW;  /* he knows the item */
+                msg("%s", inv_name(obj, TRUE));
+            }
+            else
+                msg("a food ration.");
+        }
+}
+
+/*
+ * do_post:
+ *      Put a trading post room and stuff on the screen
+ */
+
+do_post(startup)
+bool startup;   /* True if equipping the player at the beginning of the game */
+{
+        coord tp;
+        reg int i, j = 0, k;
+        reg struct room *rp;
+        reg struct object *op;
+        reg struct linked_list *ll;
+
+        o_free_list(lvl_obj);           /* throw old items away */
+
+        for (rp = rooms; rp < &rooms[MAXROOMS]; rp++)
+            rp->r_flags = ISGONE;               /* kill all rooms */
+
+        rp = &rooms[0];                         /* point to only room */
+        rp->r_flags = 0;                        /* this room NOT gone */
+        rp->r_max.x = 40;
+        rp->r_max.y = 10;                       /* 10 * 40 room */
+        rp->r_pos.x = (cols - rp->r_max.x) / 2; /* center horizontal */
+        rp->r_pos.y = 1;                        /* 2nd line */
+        draw_room(rp);                          /* draw the only room */
+
+        /* Are we equipping the player? */
+        if (startup) {
+            int wpt;
+
+            /*
+             * Give the rogue some weaponry.  
+         * Create every kind of weapon there is.
+             */
+            for (wpt=0; wpt<MAXWEAPONS; wpt++) {
+                ll = spec_item(WEAPON, wpt, rnd(100)/80+1, rnd(121)/60);
+                attach(lvl_obj, ll);
+                op = OBJPTR(ll);
+                op->o_flags |= (ISPOST | ISKNOW);
+                do {
+                    rnd_pos(rp,&tp);
+                } until (mvinch(tp.y, tp.x) == FLOOR);
+                op->o_pos = tp;
+                mvaddch(tp.y,tp.x,op->o_type);
+            }
+
+            /*
+             * Suit of armor.
+         * Create every kind of armor there is.
+             */
+            for (i=0; i<MAXARMORS; i++) {
+                ll = spec_item(ARMOR, i, rnd(100)/75, 0);
+                attach(lvl_obj, ll);
+                op = OBJPTR(ll);
+                op->o_flags |= (ISPOST | ISKNOW);
+                op->o_weight = armors[i].a_wght;
+                do {
+                    rnd_pos(rp,&tp);
+                } until (mvinch(tp.y, tp.x) == FLOOR);
+                op->o_pos = tp;
+                mvaddch(tp.y,tp.x,op->o_type);
+            }
+
+            /* Now create some rods/wands/staffs */
+            for (i=rnd(4)+2; i>0; i--) {
+                if (i == 1 && player.t_ctype != C_FIGHTER) j = WS_HIT;
+                else if (i == 5 && (player.t_ctype == C_RANGER  ||
+                    player.t_ctype == C_PALADIN ||
+                    player.t_ctype == C_MONK)) j = WS_FEAR;
+                else switch (rnd(8)) {
+                    case 0: j = WS_SLOW_M;
+                    when 1: j = WS_TELMON;
+                    when 2: j = WS_CONFMON;
+                    when 3: j = WS_PARALYZE;
+                    when 4: j = WS_MDEG;
+                    when 5: j = WS_WONDER;
+                    when 6: j = WS_LIGHT;
+                    when 7: j = WS_CANCEL;
+                }
+                ll = spec_item(STICK, j, 0, 0);
+                attach(lvl_obj, ll);
+                op = OBJPTR(ll);
+
+                /* Let clerics and MU'S know what kind they are */
+                switch (player.t_ctype) {
+                    case C_MAGICIAN:
+                    case C_CLERIC:
+                    case C_DRUID:
+                        op->o_flags |= (ISPOST | ISKNOW);
+                    otherwise:
+                        op->o_flags |= ISPOST;
+                }
+                fix_stick(op);
+                do {
+                    rnd_pos(rp,&tp);
+                } until (mvinch(tp.y, tp.x) == FLOOR);
+                op->o_pos = tp;
+                mvaddch(tp.y,tp.x,op->o_type);
+            }
+
+            /* Now let's make some rings */
+            for (i=rnd(5)+3; i>0; i--) {
+                k = 0;
+                if (i == 6 && player.t_ctype != C_MONK) j = R_HEALTH;
+                else if (i == 7) j = R_HEROISM;
+                else switch (rnd(21)) {
+                    case 0:  j = R_ADDINTEL;   k = roll(1,3);
+                    when 1:  j = R_ADDSTR;     k = roll(1,3);
+                    when 2:  j = R_ADDWISDOM;  k = roll(1,3);
+                    when 3:  j = R_ADDHIT;     k = roll(1,3);
+                    when 4:  j = R_ADDDAM;     k = roll(1,3);
+                    when 5:  j = R_PROTECT;    k = roll(1,3);
+                    when 6:  j = R_DIGEST;     k = 1;
+                    when 7:  j = R_SUSABILITY;
+                    when 8:  j = R_SEEINVIS;
+                    when 9:  j = R_ALERT;
+                    when 10: j = R_FIRE;
+                    when 11: j = R_WARMTH;
+                    when 12: j = R_FREEDOM;
+                    when 13: j = R_STEALTH;
+                    when 14: j = R_CARRY;
+                    when 15: j = R_LIGHT;
+                    when 16: j = R_TELCONTROL;
+                    when 17: j = R_DELUSION;
+                    when 18: j = R_FEAR;
+                    when 19: j = R_AGGR;
+            when 20: j = R_SEARCH;
+                }
+                ll = spec_item(RING, j, k, 0);
+                attach(lvl_obj, ll);
+                op = OBJPTR(ll);
+
+                /*
+                 * Let fighters, thieves, and monks know what kind
+                 * of rings these are.
+                 */
+                switch (player.t_ctype) {
+                    case C_FIGHTER:
+                    case C_THIEF:
+                    case C_MONK:
+                        op->o_flags |= (ISPOST | ISKNOW);
+                    otherwise:
+                        op->o_flags |= ISPOST;
+                }
+                do {
+                    rnd_pos(rp,&tp);
+                } until (mvinch(tp.y, tp.x) == FLOOR);
+                op->o_pos = tp;
+                mvaddch(tp.y,tp.x,op->o_type);
+            }
+
+            /* Let's offer some potions */
+            for (i=rnd(4)+3; i>0; i--) {
+                if (i == 1 && player.t_ctype == C_ASSASSIN) j = P_POISON;
+                else if (i == 6) j = P_PHASE;
+                else switch (rnd(11)) {
+                    case 0:   j = P_CLEAR;
+                    when 1:   j = P_HEALING;
+                    when 2:   j = P_MFIND;
+                    when 3:   j = P_HASTE;
+                    when 4:   j = P_RESTORE;
+                    when 5:   j = P_FLY;
+                    when 6:   j = P_FFIND;
+                    when 7:   j = P_SEEINVIS;
+            when 8:   j = P_TFIND;
+                    when 9:   j = P_INVIS;
+                    when 10:  j = P_SKILL;
+                }
+
+                /* Make the potion */
+                ll = spec_item(POTION, j, 0, 0);
+                attach(lvl_obj, ll);
+                op = OBJPTR(ll);
+                op->o_flags |= ISPOST;
+
+                /* Place the potion */
+                do {
+                    rnd_pos(rp,&tp);
+                } until (mvinch(tp.y, tp.x) == FLOOR);
+                op->o_pos = tp;
+                mvaddch(tp.y,tp.x,op->o_type);
+            }
+
+            /* Let's offer some scrolls */
+            for (i=rnd(4)+3; i>0; i--) {
+                if (i == 1 && player.t_ctype != C_MONK) j = S_CURING;
+                else if (i == 6 && player.t_ctype != C_THIEF) j = S_FINDTRAPS;
+                else switch (rnd(11)) {
+                    case 0:   j = S_CONFUSE;
+                    when 1:   j = S_MAP;
+                    when 2:   j = S_LIGHT;
+                    when 3:   j = S_SLEEP;
+                    when 4:   j = S_IDENT;
+                    when 5:   j = S_GFIND;
+                    when 6:   j = S_REMOVE;
+                    when 7:   j = S_HOLD;
+                    when 8:   j = S_PETRIFY;
+                    when 9:   j = S_SCARE;
+                    when 10:  j = S_TELEP;
+                }
+
+                /* Make the scroll */
+                ll = spec_item(SCROLL, j, 0, 0);
+                attach(lvl_obj, ll);
+                op = OBJPTR(ll);
+                op->o_flags |= ISPOST;
+
+                /* Place the scroll */
+                do {
+                    rnd_pos(rp,&tp);
+                } until (mvinch(tp.y, tp.x) == FLOOR);
+                op->o_pos = tp;
+                mvaddch(tp.y,tp.x,op->o_type);
+            }
+
+            /* And finally, let's get some food */
+            for (i=rnd(3)+2; i>0; i--) {
+                ll = spec_item(FOOD, 0, 0, 0);
+                attach(lvl_obj, ll);
+                op = OBJPTR(ll);
+                op->o_weight = things[TYP_FOOD].mi_wght;
+                op->o_flags |= ISPOST;
+                do {
+                    rnd_pos(rp,&tp);
+                } until (mvinch(tp.y, tp.x) == FLOOR);
+                op->o_pos = tp;
+                mvaddch(tp.y,tp.x,op->o_type);
+            }
+        }
+        else {  /* in trading post itself */
+            i = roll(10, 4);                    /* 10 to 40 items */
+            for (; i > 0 ; i--) {               /* place all the items */
+                ll = new_thing(ALL, TRUE);      /* get something */
+                attach(lvl_obj, ll);
+                op = OBJPTR(ll);
+                op->o_flags |= ISPOST;          /* object in trading post */
+                do {
+                    rnd_pos(rp,&tp);
+                } until (mvinch(tp.y, tp.x) == FLOOR);
+                op->o_pos = tp;
+                mvaddch(tp.y,tp.x,op->o_type);
+            }
+        }
+        wmove(cw,12,0);
+        nofont(cw);
+        trader = 0;
+        if (startup) {
+            waddstr(cw,"Welcome to Friendly Fiend's Equipage\n\r");
+            waddstr(cw,"====================================\n\r");
+        }
+        else {
+            waddstr(cw,"Welcome to Friendly Fiend's Flea Market\n\r");
+            waddstr(cw,"=======================================\n\r");
+        }
+        waddstr(cw,"$: Prices object that you stand upon.\n\r");
+        waddstr(cw,"#: Buys the object that you stand upon.\n\r");
+        waddstr(cw,"%: Trades in something in your pack for gold.\n\r");
+        newfont(cw);
+        trans_line();
+}
+
+/*
+ * open_market:
+ *      Retruns TRUE when ok do to transacting
+ */
+ 
+open_market()
+{
+        if (trader >= MAXPURCH && !wizard && level != 0) {
+            msg("The market is closed. The stairs are that-a-way! ");
+            return FALSE;
+        }
+        else {
+            return TRUE;
+        }
+}
+
+/*
+ * price_it:
+ *      Price the object that the hero stands on
+ */
+ 
+price_it()
+{
+        reg struct linked_list *item;
+        reg struct object *obj;
+        reg int worth;
+        reg char *str;
+
+        if (!open_market())             /* after buying hours */
+            return FALSE;
+        if ((item = find_obj(hero.y,hero.x)) == NULL) {
+            debug("Can't find the item");
+            return FALSE;
+        }
+        obj = OBJPTR(item);
+        worth = get_worth(obj);
+        if (worth < 0) {
+            msg("That's not for sale.");
+            return FALSE;
+        }
+        if (worth < 25)
+            worth = 25;
+
+        /* Our shopkeeper is affected by the person's charisma */
+        if (pstats.s_charisma > 24)     /* but don't give it away! */
+            worth = (int) ((float) worth * (18. / (float)24));
+        else
+            worth = (int) ((float) worth * (18. / (float)pstats.s_charisma));
+
+        str = inv_name(obj, TRUE);
+        msg("%s for only %d pieces of gold", str, worth);
+        curprice = worth;               /* save price */
+        strcpy(curpurch,str);           /* save item */
+        return TRUE;
+}
+
+/*
+ * sell_it:
+ *      Sell an item to the trading post
+ */
+ 
+sell_it()
+{
+        reg struct linked_list *item;
+        reg struct object *obj;
+        reg int wo, ch;
+
+        if (!open_market())             /* after selling hours */
+            return;
+
+        if ((item = get_item(pack, "sell", ALL, FALSE, FALSE)) == NULL)
+            return;
+        obj = OBJPTR(item);
+        wo = get_worth(obj);
+        if (wo <= 0) {
+            mpos = 0;
+            msg("We don't buy those.");
+            return;
+        }
+        if (wo < 25)
+            wo = 25;
+        msg("Your %s is worth %d pieces of gold.",typ_name(obj),wo);
+        msg("Do you want to sell it? ");
+        do {
+            ch = wgetch(cw);
+            if (ch == ESC || ch == 'n') {
+                msg("");
+                return;
+            }
+        } until (ch == 'y');
+        mpos = 0;
+        if (drop(item) == TRUE) {               /* drop this item */    
+            purse += wo;                        /* give him his money */
+            ++trader;                           /* another transaction */
+            wo = obj->o_count;
+            if (obj->o_group == 0)              /* dropped one at a time */
+                obj->o_count = 1;
+            msg("Sold %s",inv_name(obj,TRUE));
+            obj->o_count = wo;
+            trans_line();                       /* show remaining deals */
+        }
+}
+
+/*
+ * trans_line:
+ *      Show how many transactions the hero has left
+ */
+ 
+trans_line()
+{
+        if (level == 0)
+            sprintf(prbuf, "You are welcome to spend whatever gold you have.");
+        else if (!wizard)
+            sprintf(prbuf,"You have %d transactions remaining.",
+                    MAXPURCH - trader);
+        else
+            sprintf(prbuf,
+                "You have infinite transactions remaining oh great wizard.");
+        nofont(cw);
+        mvwaddstr(cw,lines - 4,0,prbuf);
+        newfont(cw);
+}
+
+/*
+ * typ_name:
+ *      Return the name for this type of object
+ */
+ 
+char *
+typ_name(obj)
+reg struct object *obj;
+{
+        static char buff[20];
+        reg int wh;
+
+        switch (obj->o_type) {
+                case POTION:  wh = TYP_POTION;
+                when SCROLL:  wh = TYP_SCROLL;
+                when STICK:   wh = TYP_STICK;
+                when RING:    wh = TYP_RING;
+                when ARMOR:   wh = TYP_ARMOR;
+                when WEAPON:  wh = TYP_WEAPON;
+                when MM:      wh = TYP_MM;
+                when FOOD:    wh = TYP_FOOD;
+                when RELIC:   wh = TYP_RELIC;
+                otherwise:    wh = -1;
+        }
+        if (wh < 0)
+                strcpy(buff,"unknown");
+        else
+                strcpy(buff,things[wh].mi_name);
+        return (buff);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xrogue/util.c	Tue Apr 21 08:55:20 2015 -0400
@@ -0,0 +1,1313 @@
+/*
+    util.c  -  all sorts of miscellaneous routines
+
+    XRogue: Expeditions into the Dungeons of Doom
+    Copyright (C) 1991 Robert Pietkivitch
+    All rights reserved.
+    
+    Based on "Advanced Rogue"
+    Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka and AT&T
+    All rights reserved.
+
+    Based on "Rogue: Exploring the Dungeons of Doom"
+    Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
+    All rights reserved.
+    
+    See the file LICENSE.TXT for full copyright and licensing information.
+*/
+
+#include <curses.h>
+#include <ctype.h>
+#include "rogue.h"
+
+/*
+ * this routine computes the players current AC without dex bonus's
+ */
+
+int 
+ac_compute(ignoremetal)
+bool ignoremetal;
+{
+    register int ac;
+
+    ac = pstats.s_arm; /* base armor of "skin" */
+    if (cur_armor) {
+        if (!ignoremetal || 
+             (cur_armor->o_which != LEATHER             && 
+              cur_armor->o_which != STUDDED_LEATHER     && 
+              cur_armor->o_which != PADDED_ARMOR))
+                ac -= (10 - cur_armor->o_ac);
+    }
+    if (player.t_ctype == C_MONK)
+        ac -= pstats.s_lvl * 3 / 5;
+    ac -= ring_value(R_PROTECT);
+    if (cur_misc[WEAR_BRACERS] != NULL)
+        ac -= cur_misc[WEAR_BRACERS]->o_ac;
+    if (cur_misc[WEAR_CLOAK] != NULL)
+        ac -= cur_misc[WEAR_CLOAK]->o_ac;
+
+    /* If player has the cloak, must be wearing it */
+    if (cur_relic[EMORI_CLOAK]) ac -= 15;
+
+    if (ac > 25)
+        ac = 25;
+    return(ac);
+}
+
+/*
+ * aggravate:
+ *      aggravate all the monsters on this level
+ */
+
+aggravate(do_uniques, do_good)
+bool do_uniques, do_good;
+{
+    register struct linked_list *mi;
+    register struct thing *thingptr;
+
+    for (mi = mlist; mi != NULL; mi = next(mi)) {
+        thingptr = THINGPTR(mi);
+        if (do_good == FALSE && off(*thingptr, ISMEAN)) continue;
+        if (do_uniques || off(*thingptr, ISUNIQUE)) runto(thingptr, &hero);
+    }
+}
+
+/*
+ * cansee:
+ *      returns true if the hero can see a certain coordinate.
+ */
+
+cansee(y, x)
+register int y, x;
+{
+    register struct room *rer;
+    register int radius;
+    coord tp;
+
+    if (on(player, ISBLIND))
+        return FALSE;
+
+    tp.y = y;
+    tp.x = x;
+    rer = roomin(&tp);
+
+    /* How far can we see? */
+    if (levtype == OUTSIDE) {
+        if (daytime) radius = 36;
+        else if (lit_room(rer)) radius = 9;
+        else radius = 3;
+    }
+    else radius = 3;
+
+    /*
+     * 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 && 
+             levtype != OUTSIDE &&
+             (levtype != MAZELEV ||     /* Maze level needs direct line */
+              maze_view(tp.y, tp.x)) &&
+             rer == roomin(&hero) &&
+             lit_room(rer)) ||
+            DISTANCE(y, x, hero.y, hero.x) < radius);
+}
+
+/*
+ * check_level:
+ *      Check to see if the guy has gone up a level.
+ *
+ *      Return points needed to obtain next level.
+ *
+ * These are certain beginning experience levels for all players.
+ * All further experience levels are computed by muliplying by 2
+ * up through MAXDOUBLE. Then the cap is added in to compute
+ * further levels
+ */
+
+long
+check_level()
+{
+    register int i, j, add = 0;
+    register unsigned long exp;
+    long retval;        /* Return value */
+    int nsides;
+
+    pstats.s_lvl -= pstats.s_lvladj; /* correct for level adjustment */
+    /* See if we are past the doubling stage */
+    exp = char_class[player.t_ctype].cap;
+    if (pstats.s_exp >= exp) {
+        i = pstats.s_exp/exp;   /* First get amount above doubling area */
+        retval = exp + i * exp; /* Compute next higher boundary */
+        i += MAXDOUBLE; /* Add in the previous doubled levels */
+    }
+    else {
+        i = 0;
+        exp = char_class[player.t_ctype].start_exp;
+        while (exp <= pstats.s_exp) {
+            i++;
+            exp <<= 1;
+        }
+        retval = exp;
+    }
+    if (++i > pstats.s_lvl) {
+        nsides = char_class[player.t_ctype].hit_pts;
+        for (j=0; j<(i-pstats.s_lvl); j++) /* Take care of multi-level jumps */
+            add += max(1, roll(1,nsides) + const_bonus());
+        max_stats.s_hpt += add;
+        if ((pstats.s_hpt += add) > max_stats.s_hpt)
+            pstats.s_hpt = max_stats.s_hpt;
+        msg("Welcome, %s, to level %d",
+            cnames[player.t_ctype][min(i-1, NUM_CNAMES-1)], i);
+    }
+    pstats.s_lvl = i;
+    pstats.s_lvl += pstats.s_lvladj; /* correct for level adjustment */
+    return(retval);
+}
+
+/*
+ * Used to modify the players strength
+ * it keeps track of the highest it has been, just in case
+ */
+
+chg_str(amt)
+register int amt;
+{
+    register int ring_str;              /* ring strengths */
+    register struct stats *ptr;         /* for speed */
+
+    ptr = &pstats;
+    ring_str = ring_value(R_ADDSTR);
+    ptr->s_str -= ring_str;
+    ptr->s_str += amt;
+    if (ptr->s_str > MAXATT) ptr->s_str = MAXATT;
+    if (ptr->s_str > max_stats.s_str)
+        max_stats.s_str = ptr->s_str;
+    ptr->s_str += ring_str;
+    if (ptr->s_str <= 0) {
+    pstats.s_hpt = -1;
+        death(D_STRENGTH);
+    }
+    updpack(TRUE, &player);
+}
+
+/*
+ * let's confuse the player
+ */
+
+confus_player()
+{
+    if (off(player, ISCLEAR))
+    {
+        msg("Wait, what's going on here!  Huh? What? Who?");
+        if (find_slot(unconfuse))
+            lengthen(unconfuse, HUHDURATION);
+        else
+            fuse(unconfuse, (VOID *)NULL, HUHDURATION, AFTER);
+        turn_on(player, ISHUH);
+    }
+    else msg("You feel dizzy for a moment, but it quickly passes.");
+}
+
+/*
+ * this routine computes the players current dexterity
+ */
+
+dex_compute()
+{
+    if (cur_misc[WEAR_GAUNTLET] != NULL         &&
+        cur_misc[WEAR_GAUNTLET]->o_which == MM_G_DEXTERITY) {
+        if (cur_misc[WEAR_GAUNTLET]->o_flags & ISCURSED)
+            return (3);
+        else
+            return (21);
+    }
+    else
+            return (pstats.s_dext);
+}
+
+/*
+ * diag_ok:
+ *      Check to see if the move is legal if it is diagonal
+ */
+
+diag_ok(sp, ep, flgptr)
+register coord *sp, *ep;
+struct thing *flgptr;
+{
+    register int numpaths = 0;
+
+    /* Horizontal and vertical moves are always ok */
+    if (ep->x == sp->x || ep->y == sp->y)
+        return TRUE;
+
+    /* Diagonal moves are not allowed if there is a horizontal or
+     * vertical path to the destination
+     */
+    if (step_ok(ep->y, sp->x, MONSTOK, flgptr)) numpaths++;
+    if (step_ok(sp->y, ep->x, MONSTOK, flgptr)) numpaths++;
+    return(numpaths != 1);
+}
+
+/*
+ * pick a random position around the give (y, x) coordinates
+ */
+
+coord *
+fallpos(pos, be_clear, range)
+register coord *pos;
+bool be_clear;
+int range;
+{
+        register int tried, i, j;
+        register char ch;
+        static coord ret;
+        static short masks[] = {
+                0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x100 };
+
+/*
+ * Pick a spot at random centered on the position given by 'pos' and
+ * up to 'range' squares away from 'pos'
+ *
+ * If 'be_clear' is TRUE, the spot must be either FLOOR or PASSAGE
+ * inorder to be considered valid
+ *
+ * Generate a number from 0 to 8, representing the position to pick.
+ * Note that this DOES include the positon 'pos' itself
+ *
+ * If this position is not valid, mark it as 'tried', and pick another.
+ * Whenever a position is picked that has been tried before,
+ * sequentially find the next untried position. This eliminates costly
+ * random number generation
+ */
+
+        tried = 0;
+        while( tried != 0x1ff ) {
+                i = rnd(9);
+                while( tried & masks[i] )
+                        i = (i + 1) % 9;
+
+                tried |= masks[i];
+
+                for( j = 1; j <= range; j++ ) {
+                        ret.x = pos->x + j*grid[i].x;
+                        ret.y = pos->y + j*grid[i].y;
+
+                        if (ret.x == hero.x && ret.y == hero.y)
+                                continue; /* skip the hero */
+
+                        if (ret.x < 0 || ret.x > cols - 1 ||
+                            ret.y < 1 || ret.y > lines - 3)
+                                continue; /* off the screen? */
+
+                        ch = winat(ret.y, ret.x);
+
+                        /*
+                         * Check to make certain the spot is valid
+                         */
+                        switch( ch ) {
+                        case FLOOR:
+                        case PASSAGE:
+                                return( &ret );
+                        case GOLD:
+                        case SCROLL:
+                        case POTION:
+                        case STICK:
+                        case RING:
+                        case WEAPON:
+                        case ARMOR:
+                        case MM:
+                        case FOOD:
+                                if(!be_clear && levtype != POSTLEV)
+                                        return( &ret );
+                        default:
+                                break;
+                        }
+                }
+        }
+        return( NULL );
+}
+
+/*
+ * findmindex:
+ *      Find the index into the monster table of a monster given its name.
+ */
+
+findmindex(name)
+char *name;
+{
+    int which;
+
+    for (which=1; which<NUMMONST; which++) {
+         if (strcmp(name, monsters[which].m_name) == 0)
+             break;
+    }
+    if (which >= NUMMONST) {
+         debug("couldn't find monster index");
+         which = 1;
+    }
+    return(which);
+}
+
+/*
+ * find_mons:
+ *      Find the monster from his coordinates
+ */
+
+struct linked_list *
+find_mons(y, x)
+register int y;
+register int x;
+{
+    register struct linked_list *item;
+    register struct thing *th;
+
+    for (item = mlist; item != NULL; item = next(item))
+    {
+        th = THINGPTR(item);
+        if (th->t_pos.y == y && th->t_pos.x == x)
+            return item;
+    }
+    return NULL;
+}
+
+/*
+ * find_obj:
+ *      find the unclaimed object at y, x
+ */
+
+struct linked_list *
+find_obj(y, x)
+register int y;
+register int x;
+{
+    register struct linked_list *obj;
+    register struct object *op;
+
+    for (obj = lvl_obj; obj != NULL; obj = next(obj))
+    {
+        op = OBJPTR(obj);
+        if (op->o_pos.y == y && op->o_pos.x == x)
+                return obj;
+    }
+    return NULL;
+}
+
+/*
+ * get coordinates from the player using the cursor keys (or mouse)
+ */
+
+coord 
+get_coordinates()
+{
+    register int which;
+    coord c;
+
+    c = hero;
+    wmove(cw, hero.y, hero.x);
+    draw(cw);
+    for (;;) {
+        which = (wgetch(cw) & 0177);
+        switch(which) {
+            case ESC:
+                c = hero;
+                wmove(cw, c.y, c.x);
+                draw(cw);
+            case '\n':
+            case '\r':
+                return(c);
+            when 'h':
+            case 'H':
+                c.x--;
+            when 'j':
+            case 'J':
+                c.y++;
+            when 'k':
+            case 'K':
+                c.y--;
+            when 'l':
+            case 'L':
+                c.x++;
+            when 'y':
+            case 'Y':
+                c.x--; c.y--;
+            when 'u':
+            case 'U':
+                c.x++; c.y--;
+            when 'b':
+            case 'B':
+                c.x--; c.y++;
+            when 'n':
+            case 'N':
+                c.x++; c.y++;
+            when '*':
+               mpos = 0;
+               msg("Use h,j,k,l,y,u,b,n to position cursor, then press enter.");
+        }
+        c.y = max(c.y, 1);
+        c.y = min(c.y, lines - 3);
+        c.x = max(c.x, 0);
+        c.x = min(c.x, cols - 1);
+        wmove(cw, c.y, c.x);
+        draw(cw);
+    } 
+}
+
+/*
+ * set up the direction co_ordinate for use in various "prefix" commands
+ */
+
+bool
+get_dir(direction)
+coord *direction;
+{
+    register char *prompt;
+    register bool gotit;
+    int x,y;
+
+    prompt = terse ? "Direction?" :  "Which direction? ";
+    msg(prompt);
+    do
+    {
+        gotit = TRUE;
+        switch (wgetch(msgw))
+        {
+            case 'h': case'H': direction->y =  0; direction->x = -1;
+            when 'j': case'J': direction->y =  1; direction->x =  0;
+            when 'k': case'K': direction->y = -1; direction->x =  0;
+            when 'l': case'L': direction->y =  0; direction->x =  1;
+            when 'y': case'Y': direction->y = -1; direction->x = -1;
+            when 'u': case'U': direction->y = -1; direction->x =  1;
+            when 'b': case'B': direction->y =  1; direction->x = -1;
+            when 'n': case'N': direction->y =  1; direction->x =  1;
+            when ESC: return (FALSE);
+            otherwise:
+                mpos = 0;
+                msg(prompt);
+                gotit = FALSE;
+        }
+    } until (gotit);
+    if ((on(player, ISHUH) || on(player, ISDANCE)) && rnd(100) > 20) {
+        do
+        {
+            *direction = grid[rnd(9)];
+        } while (direction->y == 0 && direction->x == 0);
+    }
+    else if (on(player, ISFLEE)) {
+            y = hero.y;
+            x = hero.x;
+            while (shoot_ok(winat(y, x))) {
+                y += direction->y;
+                x += direction->x;
+            }
+            if (isalpha(mvwinch(mw, y, x))) {
+                if (y == player.t_dest->y && x == player.t_dest->x) {
+                    mpos = 0;
+                    msg("You are too frightened to!");
+                    return(FALSE);
+            }
+        }
+    }
+    mpos = 0;
+    return TRUE;
+}
+
+
+/*
+ * get_worth:
+ *      Calculate an objects worth in gold
+ */
+
+long
+get_worth(obj)
+reg struct object *obj;
+{
+        reg long worth, wh;
+
+        worth = 0;
+        wh = obj->o_which;
+        switch (obj->o_type) {
+            case FOOD:
+                worth = 2;
+            when WEAPON:
+                if (wh < MAXWEAPONS) {
+                    worth = weaps[wh].w_worth;
+                    worth += s_magic[S_ALLENCH].mi_worth * 
+                                 (obj->o_hplus + obj->o_dplus);
+                }
+            when ARMOR:
+                if (wh < MAXARMORS) {
+                    worth = armors[wh].a_worth;
+                    worth += s_magic[S_ALLENCH].mi_worth * 
+                                (armors[wh].a_class - obj->o_ac);
+                }
+            when SCROLL:
+                if (wh < MAXSCROLLS)
+                    worth = s_magic[wh].mi_worth;
+            when POTION:
+                if (wh < MAXPOTIONS)
+                    worth = p_magic[wh].mi_worth;
+            when RING:
+                if (wh < MAXRINGS) {
+                    worth = r_magic[wh].mi_worth;
+                    worth += obj->o_ac * 40;
+                }
+            when STICK:
+                if (wh < MAXSTICKS) {
+                    worth = ws_magic[wh].mi_worth;
+                    worth += 20 * obj->o_charges;
+                }
+            when MM:
+                if (wh < MAXMM) {
+                    worth = m_magic[wh].mi_worth;
+                    switch (wh) {
+                        case MM_BRACERS:        worth += 40  * obj->o_ac;
+                        when MM_PROTECT:        worth += 60  * obj->o_ac;
+                        when MM_DISP:           /* ac already figured in price*/
+                        otherwise:              worth += 20  * obj->o_ac;
+                    }
+                }
+            when RELIC:
+                if (wh < MAXRELIC) {
+                    worth = rel_magic[wh].mi_worth;
+                    if (wh == quest_item) worth *= 10;
+                }
+            otherwise:
+                worth = 0;
+        }
+        if (obj->o_flags & ISPROT)      /* 300% more for protected */
+            worth *= 3;
+        if (obj->o_flags &  ISBLESSED)  /* 50% more for blessed */
+            worth = worth * 3 / 2;
+        if (obj->o_flags & ISCURSED)    /* half for cursed */
+            worth /= 2;
+        if (worth < 0)
+            worth = 0;
+        return worth;
+}
+
+/*
+ *      invisible()
+ */
+
+bool
+invisible(monst)
+register struct thing *monst;
+{
+        register bool   ret_code;
+
+        ret_code  = on(*monst, CANSURPRISE);
+        ret_code &= !ISWEARING(R_ALERT);
+        ret_code |= (on(*monst, ISINVIS) ||     
+                        (on(*monst, ISSHADOW) && rnd(100) < 90)) &&
+                        off(player, CANSEE);
+        return( ret_code );
+}
+
+/* 
+ * see if the object is one of the currently used items
+ */
+
+is_current(obj)
+register struct object *obj;
+{
+    if (obj == NULL)
+        return FALSE;
+    if (obj == cur_armor         || obj == cur_weapon        || 
+        obj == cur_ring[LEFT_1]  || obj == cur_ring[LEFT_2]  ||
+        obj == cur_ring[LEFT_3]  || obj == cur_ring[LEFT_4]  ||
+        obj == cur_ring[RIGHT_1] || obj == cur_ring[RIGHT_2] ||
+    obj == cur_ring[RIGHT_3] || obj == cur_ring[RIGHT_4] ||
+        obj == cur_misc[WEAR_BOOTS]    || obj == cur_misc[WEAR_JEWEL] ||
+        obj == cur_misc[WEAR_BRACERS]  || obj == cur_misc[WEAR_CLOAK] ||
+        obj == cur_misc[WEAR_GAUNTLET] || obj == cur_misc[WEAR_NECKLACE]) {
+
+        return TRUE;
+    }
+
+    /* Is it a "current" relic? */
+    if (obj->o_type == RELIC) {
+        switch (obj->o_which) {
+            case MUSTY_DAGGER:
+            case EMORI_CLOAK:
+            case HEIL_ANKH:
+            case YENDOR_AMULET:
+            case STONEBONES_AMULET:
+            case HRUGGEK_MSTAR:
+            case AXE_AKLAD:
+            case YEENOGHU_FLAIL:
+            case SURTUR_RING:
+                if (cur_relic[obj->o_which]) return TRUE;
+        }
+    }
+
+    return FALSE;
+}
+
+
+/*
+ * Look:
+ *      A quick glance all around the player
+ */
+
+look(wakeup, runend)
+bool wakeup;    /* Should we wake up monsters */
+bool runend;    /* At end of a run -- for mazes */
+{
+    register int x, y, radius;
+    register unsigned char ch, och;
+    register int oldx, oldy;
+    register bool inpass, horiz, vert, do_light = FALSE, do_blank = FALSE;
+    register int passcount = 0, curfloorcount = 0, nextfloorcount = 0;
+    register struct room *rp;
+    register int ey, ex;
+
+    inpass = ((rp = roomin(&hero)) == NULL); /* Are we in a passage? */
+
+    /* Are we moving vertically or horizontally? */
+    if (runch == 'h' || runch == 'l') horiz = TRUE;
+    else horiz = FALSE;
+    if (runch == 'j' || runch == 'k') vert = TRUE;
+    else vert = FALSE;
+
+    /* How far around himself can the player see? */
+    if (levtype == OUTSIDE) {
+        if (daytime) radius = 9;
+        else if (lit_room(rp)) radius = 3;
+        else radius = 1;
+    }
+    else radius = 1;
+
+    getyx(cw, oldy, oldx);      /* Save current position */
+
+    /* Blank out the floor around our last position and check for
+     * moving out of a corridor in a maze.
+     */
+    if (levtype == OUTSIDE) do_blank = !daytime;
+    else if (oldrp != NULL && !lit_room(oldrp) && off(player, ISBLIND))
+            do_blank = TRUE;
+
+    /* Now move around the old position and blank things out */
+    ey = player.t_oldpos.y + radius;
+    ex = player.t_oldpos.x + radius;
+    for (x = player.t_oldpos.x - radius; x <= ex; x++)
+      if (x >= 0 && x < cols)
+        for (y = player.t_oldpos.y - radius; y <= ey; y++) {
+            struct linked_list *it;
+            coord here;         /* Current <x,y> coordinate */
+            unsigned char savech;        /* Saves character in monster window */
+            bool in_room;       /* Are we in a room? */
+
+            if (y < 1 || y > lines - 3) continue;
+
+            /* See what's there -- ignore monsters, just see what they're on */
+            savech = mvwinch(mw, y, x);
+            waddch(mw, ' ');
+            ch = show(y, x);
+            mvwaddch(mw, y, x, savech); /* Restore monster */
+
+            /*
+             * If we have a monster that we can't see anymore, make sure
+             * that we can note that fact.
+             */
+            if (isalpha(savech) &&
+                (y < hero.y - radius || y > hero.y + radius ||
+                 x < hero.x - radius || x > hero.x + radius)) {
+                /* Find the monster */
+                it = find_mons(y, x);
+            }
+            else it = NULL;
+
+            /* Are we in a room? */
+            here.y = y;
+            here.x = x;
+            in_room = (roomin(&here) != NULL);
+
+            if ((do_blank || !in_room) && (y != hero.y || x != hero.x))
+                switch (ch) {
+                    case DOOR:
+                    case SECRETDOOR:
+                    case PASSAGE:
+                    case STAIRS:
+                    case TRAPDOOR:
+                    case TELTRAP:
+                    case BEARTRAP:
+                    case SLEEPTRAP:
+                    case ARROWTRAP:
+                    case DARTTRAP:
+                    case WORMHOLE:
+                    case MAZETRAP:
+                    case POOL:
+                    case POST:
+                    case VERTWALL:
+                    case HORZWALL:
+                    case WALL:
+                        /* If there was a monster showing, make it disappear */
+                        if (isalpha(savech)) {
+                            mvwaddch(cw, y, x, ch);
+
+                            /* 
+                             * If we found it (we should!), set it to
+                             * the right character!
+                             */
+                            if (it) (THINGPTR(it))->t_oldch = ch;
+                        }
+                        break;
+                    when FLOOR:
+                    case FOREST:
+                    default:
+                        mvwaddch(cw, y, x, in_room ? ' ' : PASSAGE);
+
+                        /* If we found a monster, set it to darkness! */
+                        if (it) (THINGPTR(it))->t_oldch = mvwinch(cw, y, x);
+                }
+                
+            /* Moving out of a corridor? */
+            if (levtype == MAZELEV && !ce(hero, player.t_oldpos) &&
+                !running && !isrock(ch) &&  /* Not running and not a wall */
+                ((vert && x != player.t_oldpos.x && y==player.t_oldpos.y) ||
+                 (horiz && y != player.t_oldpos.y && x==player.t_oldpos.x)))
+                    do_light = off(player, ISBLIND);
+        }
+
+    /* Take care of unlighting a corridor */
+    if (do_light && lit_room(rp)) light(&player.t_oldpos);
+
+    /* Are we coming or going between a wall and a corridor in a maze? */
+    och = show(player.t_oldpos.y, player.t_oldpos.x);
+    ch = show(hero.y, hero.x);
+    if (levtype == MAZELEV &&
+        ((isrock(och) && !isrock(ch)) || (isrock(ch) && !isrock(och)))) {
+        do_light = off(player, ISBLIND); /* Light it up if not blind */
+
+        /* Unlight what we just saw */
+        if (do_light && lit_room(&rooms[0])) light(&player.t_oldpos);
+    }
+
+    /* Look around the player */
+    ey = hero.y + radius;
+    ex = hero.x + radius;
+    for (x = hero.x - radius; x <= ex; x++)
+        if (x >= 0 && x < cols) for (y = hero.y - radius; y <= ey; y++) {
+            if (y < 1 || y >= lines - 2)
+                continue;
+            if (isalpha(mvwinch(mw, y, x)))
+            {
+                register struct linked_list *it;
+                register struct thing *tp;
+
+                if (wakeup)
+                    it = wake_monster(y, x);
+                else
+                    it = find_mons(y, x);
+
+                if (it) {
+                    tp = THINGPTR(it);
+                    tp->t_oldch = mvinch(y, x);
+                    if (isatrap(tp->t_oldch)) {
+                        register struct trap *trp = trap_at(y, x);
+
+                        tp->t_oldch = (trp->tr_flags & ISFOUND) ? tp->t_oldch
+                                                                : trp->tr_show;
+                    }
+                    if (tp->t_oldch == FLOOR && !lit_room(rp) &&
+                        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 and
+             * check for maze turns
+             */
+            if (off(player, ISBLIND))
+            {
+                if (y == hero.y && x == hero.x
+                    || (inpass && (ch == HORZWALL || ch == VERTWALL)))
+                        continue;
+
+                /* Did we come to a crossroads in a maze? */
+                if (levtype == MAZELEV &&
+                    (runend || !ce(hero, player.t_oldpos)) &&
+                    !isrock(ch) &&      /* Not a wall */
+                    ((vert && x != hero.x && y == hero.y) ||
+                     (horiz && y != hero.y && x == hero.x)))
+                        /* Just came to a turn */
+                        do_light = off(player, ISBLIND);
+            }
+            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 == hero.x + 1)
+                            continue;
+                    when 'j':
+                        if (y == hero.y - 1)
+                            continue;
+                    when 'k':
+                        if (y == hero.y + 1)
+                            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:
+                        /* Stop by new passages in a maze (floor next to us) */
+                        if ((levtype == MAZELEV) &&
+                            !(hero.y == y && hero.x == x)) {
+                            if (vert) { /* Moving vertically */
+                                /* We have a passage on our row */
+                                if (y == hero.y) curfloorcount++;
+
+                                /* Some passage on the next row */
+                                else if (y != player.t_oldpos.y)
+                                    nextfloorcount++;
+                            }
+                            else {      /* Moving horizontally */
+                                /* We have a passage on our column */
+                                if (x == hero.x) curfloorcount++;
+
+                                /* Some passage in the next column */
+                                else if (x != player.t_oldpos.x)
+                                    nextfloorcount++;
+                            }
+                        }
+                    case VERTWALL:
+                    case HORZWALL:
+                    case ' ':
+                        break;
+                    default:
+                        running = FALSE;
+                        break;
+                }
+            }
+        }
+
+    /* Have we passed a side passage, with multiple choices? */
+    if (curfloorcount > 0 && nextfloorcount > 0) running = FALSE;
+
+    else if (door_stop && !firstmove && passcount > 1)
+        running = FALSE;
+
+    /* Do we have to light up the area (just stepped into a new corridor)? */
+    if (do_light && !running && lit_room(rp)) light(&hero);
+
+    mvwaddch(cw, hero.y, hero.x, PLAYER);
+    wmove(cw, oldy, oldx);
+    if (!ce(player.t_oldpos, hero)) {
+        player.t_oldpos = hero; /* Don't change if we didn't move */
+        oldrp = rp;
+    }
+}
+
+/* 
+ * Lower a level of experience 
+ */
+
+lower_level(who)
+short who;
+{
+    int fewer, nsides;
+	unsigned long exp;
+
+    msg("You suddenly feel less skillful.");
+    if (--pstats.s_lvl == 0) {
+    pstats.s_hpt = -1;
+        death(who);             /* All levels gone */
+    }
+    if (pstats.s_lvladj > 0) { /* lose artificial levels first */
+        pstats.s_lvladj--;
+        return;
+    }
+    exp = char_class[player.t_ctype].cap;
+    if (pstats.s_exp >= exp*2)
+        pstats.s_exp -= exp;
+    else
+        pstats.s_exp /= 2;
+
+    nsides = char_class[player.t_ctype].hit_pts;
+    fewer = max(1, roll(1,nsides) + const_bonus());
+    pstats.s_hpt -= fewer;
+    max_stats.s_hpt -= fewer;
+    if (max_stats.s_hpt <= 0)
+    max_stats.s_hpt = 0;
+    if (pstats.s_hpt <= 0) {
+        pstats.s_hpt = -1;
+        death(who);
+    }
+}
+
+/*
+ * print out the name of a monster
+ */
+
+char *
+monster_name(tp)
+register struct thing *tp;
+{
+    prbuf[0] = '\0';
+    if (on(*tp, ISFLEE) || on(*tp, WASTURNED))
+        strcat(prbuf, "terrified ");
+    if (on(*tp, ISHUH))
+        strcat(prbuf, "confused ");
+    if (on(*tp, ISCHARMED))
+        strcat(prbuf, "charmed ");
+    else if (on(*tp, ISFLY))
+        strcat(prbuf, "flying ");
+
+    /* If it is sleeping or stoned, write over any of the above attributes */
+    if (off(*tp, ISRUN))
+        strcpy(prbuf, "sleeping ");
+    if (on(*tp, ISSTONE))
+        strcpy(prbuf, "petrified ");
+
+    if (tp->t_name) strcat(prbuf, tp->t_name);
+    else strcat(prbuf, monsters[tp->t_index].m_name);
+
+    return(prbuf);
+}
+
+/*
+ * move_hero:
+ *      Try to move the hero somplace besides next to where he is.  We ask him
+ *      where.  There can be restrictions based on why he is moving.
+ */
+
+bool
+move_hero(why)
+int why;
+{
+    char *action = NULL;
+    unsigned char which;
+    coord c;
+
+    switch (why) {
+        case H_TELEPORT:
+            action = "teleport";
+    }
+
+    msg("Where do you wish to %s to? (* for help) ", action);
+    c = get_coordinates();
+    mpos = 0;
+    which = winat(c.y, c.x);
+    switch (which) {
+        default:
+            if (!isrock(which) || off(player, CANINWALL)) break;
+
+        case FLOOR:
+        case PASSAGE:
+        case DOOR:
+        case STAIRS:
+        case POST:
+        case GOLD:
+        case POTION:
+        case SCROLL:
+        case FOOD:
+        case WEAPON:
+        case ARMOR:
+        case RING:
+        case MM:
+        case RELIC:
+        case STICK:
+            hero = c;
+            return(TRUE);
+    }
+    return(FALSE);
+}
+
+/*
+ * raise_level:
+ *      The guy just magically went up a level.
+ */
+
+raise_level()
+{
+    unsigned long test;  /* Next level -- be sure it is not an overflow */
+
+    test = check_level();       /* Get next boundary */
+
+    /* Be sure it is higher than what we have no -- else overflow */
+    if (test > pstats.s_exp) pstats.s_exp = test;
+    check_level();
+
+    /* Give him a bonus */
+    switch (player.t_ctype) {
+        case C_FIGHTER:
+            (*add_abil[A_STRENGTH])(1);
+        when C_RANGER:
+        case C_PALADIN:
+            (*add_abil[A_CHARISMA])(1);
+        when C_MAGICIAN:
+            (*add_abil[A_INTELLIGENCE])(1);
+        when C_CLERIC:
+        case C_DRUID:
+            (*add_abil[A_WISDOM])(1);
+        when C_THIEF:
+        case C_ASSASSIN:
+            (*add_abil[A_DEXTERITY])(1);
+        when C_MONK:
+            (*add_abil[A_CONSTITUTION])(1);
+    }
+}
+
+/*
+ * saving throw matrix for character saving throws
+ * this table is indexed by char type and saving throw type
+ */
+
+static const char st_matrix[NUM_CHARTYPES][5] = {
+/* Poison,      Petrify,        wand,           Breath,         Magic */
+{ 13,           14,             15,             16,             17 },
+{ 13,           14,             15,             16,             17 },
+{ 13,           14,             15,             16,             17 },
+{ 11,           12,             13,             14,             15 },
+{ 11,           12,             13,             14,             15 },
+{ 12,           13,             14,             15,             16 },
+{ 12,           13,             14,             15,             16 },
+{ 11,           12,             12,             14,             15 },
+{ 12,           13,             14,             15,             16 },
+{ 13,           14,             15,             16,             17 }
+};
+
+/*
+ * save:
+ *      See if a creature saves against something
+ */
+
+save(which, who, adj)
+int which;              /* which type of save */
+struct thing *who;      /* who is saving */
+int adj;                /* saving throw adjustment */
+{
+    register int need, level, protect;
+
+    protect = 0;
+    level = who->t_stats.s_lvl;
+    need = st_matrix[who->t_ctype][which];
+    switch (who->t_ctype) {
+    case C_FIGHTER:
+    case C_RANGER:
+    case C_PALADIN:
+        need -= (2 * (level-1) / 5) - 1;        /* for level 61; -= 25 */
+    when C_THIEF:
+    case C_ASSASSIN:
+    case C_MONK:
+    case C_MONSTER:
+        need -= (2 * (level-1) / 5) - 3;        /* for level 61; -= 27 */
+    when C_MAGICIAN:
+    case C_CLERIC:
+    case C_DRUID:
+        need -= (2 * (level-1) / 5) - 5;        /* for level 61; -= 29 */
+    }
+    /* 
+     * add in pluses against poison for execeptional constitution 
+     */
+    if (which == VS_POISON && who->t_stats.s_const > 18)
+        need -= (who->t_stats.s_const - 17) / 2;
+    if (who == &player) {
+        /*
+         * does the player have a ring of protection on?
+         */
+        protect +=  ring_value(R_PROTECT);
+        /*
+         * does the player have a cloak of protection on?
+         */
+        if (cur_misc[WEAR_CLOAK])
+            protect += cur_misc[WEAR_CLOAK]->o_ac;
+
+        protect = min(protect, 10);/* limit protection to +10 */
+        need -= protect;
+    }
+    need -= adj;
+    /*
+     * always miss or save on a 1 (except for UNIQUEs
+     */
+    if (who == &player || off(*who, ISUNIQUE))
+        need = max(need, 2);
+    need = min(20, need); /* always make our save on a 20 */
+    debug("need a %d to save", need);
+    return (roll(1, 20) >= need);
+}
+
+/*
+ * secret_door:
+ *      Figure out what a secret door looks like.
+ */
+
+secretdoor(y, x)
+register int y, x;
+{
+    register int i;
+    register struct room *rp;
+    register 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(HORZWALL);
+            else
+                return(VERTWALL);
+
+    return('p');
+}
+
+/*
+ * this routine computes the players current strength
+ */
+
+str_compute()
+{
+    if (cur_misc[WEAR_GAUNTLET] != NULL         &&
+        cur_misc[WEAR_GAUNTLET]->o_which == MM_G_OGRE) {
+        if (cur_misc[WEAR_GAUNTLET]->o_flags & ISCURSED)
+            return (3);
+        else
+            return (21);
+    }
+    else
+            return (pstats.s_str);
+}
+
+/*
+ * copy string using unctrl for things
+ */
+
+strucpy(s1, s2, len)
+register char *s1, *s2;
+register int len;
+{
+    register char *sp;
+    while (len--)
+    {
+        strcpy(s1, (sp = unctrl(*s2)));
+        s1 += strlen(sp);
+        s2++;
+    }
+    *s1 = '\0';
+}
+
+/*
+ * tr_name:
+ *      print the name of a trap
+ */
+
+char *
+tr_name(ch)
+char ch;
+{
+    register char *s = NULL;
+
+    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.";
+        when POOL:
+            s = terse ? "A shimmering pool." : "You found a shimmering pool";
+        when MAZETRAP:
+            s = terse ? "A maze entrance." : "You found a maze entrance";
+        when WORMHOLE:
+            s = terse ? "A worm hole." : "You found a worm hole entrance";
+    }
+    return s;
+}
+
+/*
+ * for printfs: if string starts with a vowel, return "n" for an "an"
+ */
+
+char *
+vowelstr(str)
+register char *str;
+{
+    switch (*str)
+    {
+        case 'a':
+        case 'e':
+        case 'i':
+        case 'o':
+        case 'u':
+            return "n";
+        default:
+            return "";
+    }
+}
+
+/*
+ * wake up a room full (hopefully) of creatures
+ */
+
+wake_room(rp)
+register struct room *rp;
+{
+        register struct linked_list *item;
+        register struct thing *tp;
+
+        for (item=mlist; item!=NULL; item=next(item)) {
+            tp = THINGPTR(item);
+            if (off(*tp,ISRUN) && on(*tp,ISMEAN) && roomin(&tp->t_pos) == rp)
+                runto(tp, &hero);
+        }
+}
+                
+
+/*
+ * waste_time:
+ *      Do nothing but let other things happen
+ */
+
+waste_time()
+{
+    if (inwhgt)                 /* if from wghtchk then done */
+        return;
+    do_daemons(BEFORE);
+    do_fuses(BEFORE);
+    do_daemons(AFTER);
+    do_fuses(AFTER);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xrogue/vers.c	Tue Apr 21 08:55:20 2015 -0400
@@ -0,0 +1,21 @@
+/*
+    vers.c - version number
+
+    XRogue: Expeditions into the Dungeons of Doom
+    Copyright (C) 1991 Robert Pietkivitch
+    All rights reserved.
+    
+    Based on "Advanced Rogue"
+    Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka and AT&T
+    All rights reserved.
+
+    Based on "Rogue: Exploring the Dungeons of Doom"
+    Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
+    All rights reserved.
+    
+    See the file LICENSE.TXT for full copyright and licensing information.
+*/
+
+unsigned 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    8.0.3 - 12/10/2005";
+char *release = "8.0.3";
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xrogue/weapons.c	Tue Apr 21 08:55:20 2015 -0400
@@ -0,0 +1,428 @@
+/*
+    weapons.c - Functions for dealing with problems brought about by weapons
+    
+    XRogue: Expeditions into the Dungeons of Doom
+    Copyright (C) 1991 Robert Pietkivitch
+    All rights reserved.
+    
+    Based on "Advanced Rogue"
+    Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka and AT&T
+    All rights reserved.
+
+    Based on "Rogue: Exploring the Dungeons of Doom"
+    Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
+    All rights reserved.
+    
+    See the file LICENSE.TXT for full copyright and licensing information.
+*/
+
+#include <curses.h>
+#include <ctype.h>
+#include "rogue.h"
+
+boomerang(ydelta, xdelta, item, tp)
+int ydelta, xdelta;
+register struct linked_list *item;
+register struct thing *tp;
+{
+        register struct object *obj;
+        struct thing midpoint;
+        coord oldpos;
+
+        obj = OBJPTR(item);
+        oldpos = obj->o_pos;
+
+        /*
+         * make it appear to fly at the target
+         */
+        do_motion(obj, ydelta, xdelta, tp);
+        hit_monster(unc(obj->o_pos), obj, tp);
+
+        /*
+         * Now let's make it fly back to the wielder.  We need to
+         * use midpoint to fool do_motion into thinking the action
+         * starts there.  Do_motion only looks at the t_pos field.
+         */
+        midpoint.t_pos = obj->o_pos;    /* Simulate a new start position */
+        do_motion(obj, -ydelta, -xdelta, &midpoint);
+
+        obj->o_pos = oldpos;
+}
+
+/*
+ * do the actual motion on the screen done by an object traveling
+ * across the room.  Note that we should not look at any field in
+ * tp other than t_pos unless we change boomerang().
+ */
+
+do_motion(obj, ydelta, xdelta, tp)
+register struct object *obj;
+register int ydelta, xdelta;
+register struct thing *tp;
+{
+
+    /*
+    * Come fly with us ...
+    */
+    obj->o_pos = tp->t_pos;
+    for (;;) {
+        register int ch;
+        /*
+        * Erase the old one
+        */
+        if (!ce(obj->o_pos, tp->t_pos) &&
+            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 (shoot_ok(ch = winat(obj->o_pos.y, obj->o_pos.x)) && ch != DOOR && !ce(obj->o_pos, hero)) {
+                /*
+                * 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) != ' ') {
+                        if (obj->o_type == MISSILE) nofont(cw);
+                        mvwaddch(cw, obj->o_pos.y, obj->o_pos.x, obj->o_type);
+                        newfont(cw);
+                        draw(cw);
+                }
+                continue;
+        }
+
+        /*
+         * Did we stop because of a monster or the hero?  If we did 
+         * not, we want to move our position back one because we could
+         * not actually make it this far.
+         */
+        if (!isalpha(ch) && 
+            !(obj->o_pos.y == hero.y && obj->o_pos.x == hero.x)) {
+                obj->o_pos.y -= ydelta;
+                obj->o_pos.x -= xdelta;
+        }
+
+        break;
+    }
+}
+
+
+/*
+ * fall:
+ *      Drop an item someplace around here.
+ */
+
+fall(item, pr)
+register struct linked_list *item;
+bool pr;
+{
+        register struct object *obj;
+        register struct room *rp;
+        register int i;
+        struct object *tobj;
+        struct linked_list *titem;
+        coord *fpos = NULL;
+
+        obj = OBJPTR(item);
+        /*
+         * try to drop the item, look up to 3 squares away for now
+         */
+        for (i=1; i<4; i++) {
+            if ((fpos = fallpos(&obj->o_pos, FALSE, i)) != NULL)
+                break;
+        }
+
+        if (fpos != NULL) {
+                if (obj->o_group) { /* try to add groups together */
+                    for(titem=lvl_obj; titem!=NULL; titem=next(titem)) {
+                        tobj = OBJPTR(titem);
+                        if (tobj->o_group == obj->o_group       &&
+                            tobj->o_pos.y == fpos->y            &&
+                            tobj->o_pos.x == fpos->x) {
+                                tobj->o_count += obj->o_count;
+                                o_discard(item);
+                                return;
+                        }
+                    }
+                }
+                mvaddch(fpos->y, fpos->x, obj->o_type);
+                obj->o_pos = *fpos;
+                if ((rp = roomin(&hero)) != NULL &&
+                    lit_room(rp)) {
+                        light(&hero);
+                        mvwaddch(cw, hero.y, hero.x, PLAYER);
+                }
+                attach(lvl_obj, item);
+                return;
+        }
+        if (pr) {
+            msg("The %s vanishes as it hits the ground.",
+                weaps[obj->o_which].w_name);            
+        }
+        o_discard(item);
+}
+
+/*
+ * Does the missile hit the monster
+ */
+
+hit_monster(y, x, obj, tp)
+register int y, x;
+struct object *obj;
+register struct thing *tp;
+{
+        static coord mp;
+
+        mp.y = y;
+        mp.x = x;
+        if (tp == &player) {
+                /* Make sure there is a monster where it landed */
+                if (!isalpha(mvwinch(mw, y, x))) {
+                        return(FALSE);
+                }
+
+                /* Player hits monster */
+                return(fight(&mp, obj, TRUE));
+        } else {
+                if (!ce(mp, hero)) {
+                    /* Monster hits monster */
+                    return(skirmish(tp, &mp, obj, TRUE));
+                }
+
+                /* Monster hits player */
+                return(attack(tp, obj, TRUE));
+        }
+}
+
+/*
+ * init_weapon:
+ *      Set up the initial goodies for a weapon
+ */
+
+init_weapon(weap, type)
+register struct object *weap;
+char type;
+{
+        register struct init_weps *iwp;
+
+        iwp = &weaps[type];
+        strcpy(weap->o_damage,iwp->w_dam);
+        strcpy(weap->o_hurldmg,iwp->w_hrl);
+        weap->o_launch = iwp->w_launch;
+        weap->o_flags = iwp->w_flags;
+        weap->o_weight = iwp->w_wght;
+        if (weap->o_flags & ISMANY) {
+                weap->o_count = rnd(8) + 8;
+                weap->o_group = newgrp();
+        } else {
+                weap->o_count = 1;
+        }
+}
+
+/*
+ * missile:
+ *      Fire a missile in a given direction
+ */
+
+missile(ydelta, xdelta, item, tp)
+int ydelta, xdelta;
+register struct linked_list *item;
+register struct thing *tp;
+{
+        register struct object *obj;
+        register struct linked_list *nitem;
+        char ch;
+
+        /*
+        * Get which thing we are hurling
+        */
+        if (item == NULL) {
+                return;
+        }
+        obj = OBJPTR(item);
+        if (obj->o_type == RELIC && obj->o_which == AXE_AKLAD) {
+            boomerang(ydelta, xdelta, item, tp);
+            return;
+        }
+
+        if (!dropcheck(obj)) return;    /* Can we get rid of it? */
+
+        if(!(obj->o_flags & ISMISL)) {
+            for(;;) {
+                msg(terse ? "Really throw? (y or n): "
+                          : "Do you really want to throw %s? (y or n): ",
+                                inv_name(obj, TRUE));
+                mpos = 0;
+                ch = wgetch(cw);
+                if (ch == 'n' || ch == ESC) {
+                    after = FALSE;
+                    return;
+                }
+                if (ch == 'y')
+                    break;
+            }
+        }
+        /*
+         * 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(tp->t_pack, item);
+                if (tp->t_pack == pack) {
+                        inpack--;
+                }
+        } 
+        else {
+                obj->o_count--;
+                nitem = (struct linked_list *) new_item(sizeof *obj);
+                obj = OBJPTR(nitem);
+                *obj = *(OBJPTR(item));
+                obj->o_count = 1;
+                item = nitem;
+        }
+        updpack(FALSE, tp);
+        do_motion(obj, ydelta, xdelta, tp);
+        /*
+        * AHA! Here it has hit something. If it is a wall or a door,
+        * or if it misses (combat) the monster, put it on the floor
+        */
+        if (!hit_monster(unc(obj->o_pos), obj, tp)) {
+                fall(item, TRUE);
+        }
+        else
+            o_discard(item);
+
+        mvwaddch(cw, hero.y, hero.x, PLAYER);
+        
+}
+
+/*
+ * num:
+ *      Figure out the plus number for armor/weapons
+ */
+
+char *
+num(n1, n2)
+register int n1, n2;
+{
+        static char numbuf[LINELEN/2];
+
+        if (n1 == 0 && n2 == 0) {
+                return "+0";
+        }
+        if (n2 == 0) {
+                sprintf(numbuf, "%s%d", n1 < 0 ? "" : "+", n1);
+        } else {
+                sprintf(numbuf, "%s%d, %s%d", n1 < 0 ? "" : "+", n1, n2 < 0 ? "" : "+", n2);
+        }
+        return(numbuf);
+}
+
+/*
+ * wield:
+ *      Pull out a certain weapon
+ */
+
+wield()
+{
+        register struct linked_list *item;
+        register struct object *obj, *oweapon;
+
+        /*
+         * It takes 2 movement periods to unwield a weapon and 2 movement
+         * periods to wield a weapon.
+         */
+        if (player.t_action != C_WIELD) {
+            player.t_action = C_WIELD;
+            player.t_using = NULL;      /* Make sure this is NULL! */
+            if (cur_weapon != NULL) {
+                player.t_no_move = 2 * movement(&player);
+                return;
+            }
+        }
+
+        if ((oweapon = cur_weapon) != NULL) {
+            /* At this point we have waited at least 2 units */
+            if (!dropcheck(cur_weapon)) {
+                    cur_weapon = oweapon;
+                    player.t_action = A_NIL;
+                    return;
+            }
+            if (terse)
+                addmsg("Was ");
+            else
+                addmsg("You were ");
+            msg("wielding %s", inv_name(oweapon, TRUE));
+        }
+
+        /* We we have something picked out? */
+        if (player.t_using == NULL) {
+            /* Now, what does he want to wield? */
+            if ((item = get_item(pack, "wield", WIELDABLE, FALSE, FALSE)) == NULL) {
+                    player.t_action = A_NIL;
+                    after = FALSE;
+                    return;
+            }
+            player.t_using = item;
+            player.t_no_move = 2 * movement(&player);
+            return;
+        }
+
+        /* We have waited our time, let's wield the weapon */
+        item = player.t_using;
+        player.t_using = NULL;
+        player.t_action = A_NIL;
+
+        obj = OBJPTR(item);
+
+        if (is_current(obj)) {
+                msg("Item in use.");
+                after = FALSE;
+                return;
+        }
+        if (player.t_ctype != C_FIGHTER && 
+            player.t_ctype != C_RANGER  &&
+            player.t_ctype != C_PALADIN &&
+            obj->o_type == WEAPON       &&
+            obj->o_which == TWOSWORD) {
+                switch (rnd(3)) {
+                case 0:
+                   msg("Only fighter types can wield the two-handed sword.");
+                when 1:
+                   msg("Your hand does not fit the two-handed sword.");
+                otherwise:
+                   msg("You can not wield the two-handed sword.");
+                }
+                return;
+        }
+        if (player.t_ctype != C_FIGHTER && 
+            player.t_ctype != C_ASSASSIN &&
+            player.t_ctype != C_THIEF   &&
+            player.t_ctype != C_MONK    &&
+            obj->o_type == WEAPON       &&
+            obj->o_which == BASWORD) {
+                switch (rnd(3)) {
+                case 0:
+                   msg("Only thief types can wield the bastard sword.");
+                when 1:
+                   msg("Your hand does not fit the bastard sword.");
+                otherwise:
+                   msg("You can not wield the bastard sword.");
+                }
+                return;
+        }
+           
+        if (terse) {
+                addmsg("W");
+        } else {
+                addmsg("You are now w");
+        }
+        msg("ielding %s", inv_name(obj, TRUE));
+        cur_weapon = obj;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xrogue/wear.c	Tue Apr 21 08:55:20 2015 -0400
@@ -0,0 +1,438 @@
+/*
+    wear.c  -  functions for dealing with armor
+    
+    XRogue: Expeditions into the Dungeons of Doom
+    Copyright (C) 1991 Robert Pietkivitch
+    All rights reserved.
+    
+    Based on "Advanced Rogue"
+    Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka and AT&T
+    All rights reserved.
+
+    Based on "Rogue: Exploring the Dungeons of Doom"
+    Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
+    All rights reserved.
+    
+    See the file LICENSE.TXT for full copyright and licensing information.
+*/
+
+#include <curses.h>
+#include "rogue.h"
+
+/*
+ * take_off:
+ *      Get the armor off of the players back
+ */
+
+take_off()
+{
+    register struct object *obj;
+    register struct linked_list *item;
+
+    /* It takes time to take things off */
+    if (player.t_action != C_TAKEOFF) {
+        /* What does player want to take off? */
+        if ((item = get_item(pack, "take off", REMOVABLE, FALSE, FALSE))==NULL)
+            return;
+
+        obj = OBJPTR(item);
+        if (!is_current(obj)) {
+            msg("Not wearing %c) %s", pack_char(pack, obj),inv_name(obj, TRUE));
+            return;
+        }
+
+        player.t_using = item;        /* Remember what it is */
+        player.t_action = C_TAKEOFF;  /* We are taking something off */
+
+        /* Cursed items take almost no time */
+        if (obj->o_flags & ISCURSED) player.t_no_move = movement(&player);
+        else player.t_no_move = dress_units(item) * movement(&player);
+        return;
+    }
+
+    /* We have waited our time, let's take off our item */
+    item = player.t_using;
+    player.t_using = NULL;
+    player.t_action = A_NIL;
+
+    obj = OBJPTR(item);
+    if (!is_current(obj)) {     /* Just to be on the safe side */
+        msg("Not wearing %c) %s", pack_char(pack, obj),inv_name(obj, TRUE));
+        return;
+    }
+
+    /* Can the player remove the item? */
+    if (!dropcheck(obj)) return;
+    updpack(TRUE, &player);
+
+    msg("Was wearing %c) %s", pack_char(pack, obj),inv_name(obj,TRUE));
+}
+
+/*
+ * wear:
+ *      The player wants to wear something, so let him/her put it on.
+ */
+
+wear()
+{
+    register struct linked_list *item;
+    register struct object *obj;
+    register int i;
+
+    /* It takes time to put things on */
+    if (player.t_action != C_WEAR) {
+        /* What does player want to wear? */
+        if ((item = get_item(pack, "wear", WEARABLE, FALSE, FALSE)) == NULL)
+            return;
+
+        obj = OBJPTR(item);
+
+        switch (obj->o_type) {
+            case ARMOR:
+                if (cur_armor != NULL) {
+                    addmsg("You are already wearing armor");
+                    if (!terse) addmsg(".  You'll have to take it off first.");
+                    endmsg();
+                    after = FALSE;
+                    return;
+                }
+                if (player.t_ctype == C_MONK) {
+                    msg("Monks can't wear armor!");
+                    return;
+                }
+                if (cur_misc[WEAR_BRACERS] != NULL) {
+                    msg("You can't wear armor with bracers of defense.");
+                    return;
+                }
+                if (cur_misc[WEAR_CLOAK] != NULL || cur_relic[EMORI_CLOAK]) {
+                    msg("You can't wear armor with a cloak.");
+                    return;
+                }
+                if (player.t_ctype == C_THIEF   &&
+                    (obj->o_which != LEATHER    &&
+                     obj->o_which != STUDDED_LEATHER)) {
+                    if (terse) msg("Thieves can't wear that type of armor.");
+                    else
+                 msg("Thieves can wear leather and studded leather armor.");
+                    return;
+                }
+                if (player.t_ctype == C_ASSASSIN &&
+                    (obj->o_which != LEATHER    &&
+                     obj->o_which != STUDDED_LEATHER)) {
+                    if (terse) msg("Assassins can't wear that type of armor.");
+                    else
+                 msg("Assassins can wear leather and studded leather armor.");
+                    return;
+                }
+
+            when MM:
+                switch (obj->o_which) {
+                /*
+                 * when wearing the boots of elvenkind the player will not
+                 * set off any traps
+                 */
+                case MM_ELF_BOOTS:
+                    if (cur_misc[WEAR_BOOTS] != NULL) {
+                        msg("Already wearing a pair of boots. ");
+                        return;
+                    }
+                /*
+                 * when wearing the boots of dancing the player will dance
+                 * uncontrollably
+                 */
+                when MM_DANCE:
+                    if (cur_misc[WEAR_BOOTS] != NULL) {
+                        msg("Already wearing a pair of boots.");
+                        return;
+                    }
+                /*
+                 * bracers give the hero protection in he same way armor does.
+                 * they cannot be used with armor but can be used with cloaks
+                 */
+                when MM_BRACERS:
+                    if (cur_misc[WEAR_BRACERS] != NULL) {
+                        msg("Already wearing bracers.");
+                        return;
+                    }
+                    else {
+                        if (cur_armor != NULL) {
+                           msg("You can't wear bracers of defense with armor.");
+                           return;
+                        }
+                    }
+
+                /*
+                 * The robe (cloak) of powerlessness disallows any spell casting
+                 */
+                when MM_R_POWERLESS:
+                /*
+                 * the cloak of displacement gives the hero an extra +2 on AC
+                 * and saving throws. Cloaks cannot be used with armor.
+                 */
+                case MM_DISP:
+                /*
+                 * the cloak of protection gives the hero +n on AC and saving
+                 * throws with a max of +3 on saves
+                 */
+                case MM_PROTECT:
+                    if (cur_misc[WEAR_CLOAK] != NULL ||
+                        cur_relic[EMORI_CLOAK]) {
+                        msg("%slready wearing a cloak.", terse ? "A"
+                                                               : "You are a");
+                        return;
+                    }
+                    else {
+                        if (cur_armor != NULL) {
+                            msg("You can't wear a cloak with armor.");
+                            return;
+                        }
+                    }
+                /*
+                 * the gauntlets of dexterity and ogre power give the hero
+                 * a dexterity of 21, the gauntlets of fumbling cause the
+                 * hero to drop his weapon.
+                 */
+                when MM_G_DEXTERITY:
+                case MM_G_OGRE:
+                case MM_FUMBLE:
+                    if (cur_misc[WEAR_GAUNTLET] != NULL) {
+                        msg("Already wearing a pair of gauntlets.");
+                        return;
+                    }
+                /*
+                 * the jewel of attacks does an aggavate monster
+                 */
+                when MM_JEWEL:
+                    if (cur_misc[WEAR_JEWEL] != NULL    ||
+                        cur_relic[YENDOR_AMULET]        ||
+                        cur_relic[STONEBONES_AMULET]) {
+                        msg("Already wearing an amulet.");
+                        return;
+                    }
+                /*
+                 * the necklace of adaption makes the hero immune to
+                 * chlorine gas and acid breath.
+                 */
+                when MM_ADAPTION:
+                    if (cur_misc[WEAR_NECKLACE] != NULL) {
+                        msg("Already wearing a necklace.");
+                        return;
+                    }
+                /*
+                 * the necklace of stragulation will try to strangle the
+                 * hero to death
+                 */
+                when MM_STRANGLE:
+                    if (cur_misc[WEAR_NECKLACE] != NULL) {
+                        msg("Already wearing a necklace.");
+                        return;
+                    }
+                otherwise:
+                    msg("What a strange item you have!");
+                    return;
+                }
+
+            when RING:
+                if (cur_misc[WEAR_GAUNTLET] != NULL) {
+                    msg ("You have to remove your gauntlets first!");
+                    return;
+                }
+
+                /* Is there room to put the ring on */
+                for (i=0; i<NUM_FINGERS; i++)
+                    if (cur_ring[i] == NULL) {
+                        break;
+                    }
+                if (i == NUM_FINGERS) { /* Not enough fingers */
+                    if (terse) msg("Wearing enough rings.");
+                    else msg("You are already wearing eight rings.");
+                    return;
+                }
+        }
+
+        player.t_using = item;      /* Remember what it is */
+        player.t_action = C_WEAR;   /* We are taking something off */
+        player.t_no_move = dress_units(item) * movement(&player);
+        return;
+    }
+
+    /* We have waited our time, let's put on our item */
+    item = player.t_using;
+    player.t_using = NULL;
+    player.t_action = A_NIL;
+
+    obj = OBJPTR(item);
+
+    switch (obj->o_type) {
+        case ARMOR:
+            obj->o_flags |= ISKNOW;
+            cur_armor = obj;
+            addmsg(terse ? "W" : "You are now w");
+            msg("earing %s.", armors[obj->o_which].a_name);
+
+        when MM:
+            switch (obj->o_which) {
+            /*
+             * when wearing the boots of elvenkind the player will not
+             * set off any traps
+             */
+            case MM_ELF_BOOTS:
+                msg("Wearing %s",inv_name(obj,TRUE));
+                cur_misc[WEAR_BOOTS] = obj;
+            /*
+             * when wearing the boots of dancing the player will dance
+             * uncontrollably
+             */
+            when MM_DANCE:
+                msg("Wearing %s",inv_name(obj,TRUE));
+                cur_misc[WEAR_BOOTS] = obj;
+                msg("You begin to dance uncontrollably!");
+                turn_on(player, ISDANCE);
+            /*
+             * bracers give the hero protection in he same way armor does.
+             * they cannot be used with armor but can be used with cloaks
+             */
+            when MM_BRACERS:
+                msg("wearing %s",inv_name(obj,TRUE));
+                cur_misc[WEAR_BRACERS] = obj;
+
+            /*
+             * The robe (cloak) of powerlessness disallows any spell casting
+             */
+            when MM_R_POWERLESS:
+            /*
+             * the cloak of displacement gives the hero an extra +2 on AC
+             * and saving throws. Cloaks cannot be used with armor.
+             */
+            case MM_DISP:
+            /*
+             * the cloak of protection gives the hero +n on AC and saving
+             * throws with a max of +3 on saves
+             */
+            case MM_PROTECT:
+                msg("wearing %s",inv_name(obj,TRUE));
+                cur_misc[WEAR_CLOAK] = obj;
+            /*
+             * the gauntlets of dexterity and ogre power give the hero
+             * a dexterity of 21, the gauntlets of fumbling cause the
+             * hero to drop his weapon.
+             */
+            when MM_G_DEXTERITY:
+            case MM_G_OGRE:
+            case MM_FUMBLE:
+                msg("Wearing %s", inv_name(obj,TRUE));
+                cur_misc[WEAR_GAUNTLET] = obj;
+                if (obj->o_which == MM_FUMBLE)
+                    daemon(fumble, (VOID *)NULL, AFTER);
+            /*
+             * the jewel of attacks does an aggavate monster
+             */
+            when MM_JEWEL:
+                msg("Wearing %s",inv_name(obj,TRUE));
+                cur_misc[WEAR_JEWEL] = obj;
+                aggravate(TRUE, TRUE); /* affect all charactors */
+                if (player.t_ctype == C_PALADIN ||
+                    player.t_ctype == C_RANGER  || player.t_ctype == C_MONK)
+                        msg("A chill runs down your spine! ");
+
+            /*
+             * the necklace of adaption makes the hero immune to
+             * chlorine gas and acid
+             */
+            when MM_ADAPTION:
+                msg("Wearing %s",inv_name(obj,TRUE));
+                cur_misc[WEAR_NECKLACE] = obj;
+                turn_on(player, NOGAS);
+                turn_on(player, NOACID);
+
+            /*
+             * the necklace of stragulation will try to strangle the
+             * hero to death
+             */
+            when MM_STRANGLE:
+                msg("Wearing %s",inv_name(obj,TRUE));
+                cur_misc[WEAR_NECKLACE] = obj;
+                msg("The necklace is beginning to strangle you!");
+                daemon(strangle, (VOID *)NULL, AFTER);
+            otherwise:
+                msg("What a strange item you have!");
+            }
+            status(FALSE);
+            if (m_know[obj->o_which] && m_guess[obj->o_which]) {
+                free(m_guess[obj->o_which]);
+                m_guess[obj->o_which] = NULL;
+            }
+            else if (!m_know[obj->o_which] && 
+                     askme &&
+                     (obj->o_flags & ISKNOW) == 0  &&
+                     m_guess[obj->o_which] == NULL) {
+                nameitem(item, FALSE);
+            }
+
+        when RING:
+            /* If there is room, put on the ring */
+            for (i=0; i<NUM_FINGERS; i++)
+                if (cur_ring[i] == NULL) {
+                    cur_ring[i] = obj;
+                    break;
+                }
+            if (i == NUM_FINGERS) {     /* Not enough fingers */
+                if (terse) msg("Wearing enough rings.");
+                else msg("You are already wearing eight rings.");
+                return;
+            }
+
+            /* Calculate the effect of the ring */
+            ring_on(item);
+    }
+    updpack(TRUE, &player);
+}
+
+/*
+ * dress_units:
+ *      How many movements periods does it take to put on or remove the
+ *      given item of "clothing"?
+ */
+
+dress_units(item)
+struct linked_list *item;
+{
+    register struct object *obj;
+
+    obj = OBJPTR(item);
+
+    switch (obj->o_type) {
+        case ARMOR:
+            return(10-armors[obj->o_which].a_class);
+        when RING:
+            return(2);
+        when MM:
+            switch (obj->o_which) {
+                case MM_ELF_BOOTS:
+                case MM_DANCE:
+                    /* Boots */
+                    return(5);
+                when MM_R_POWERLESS:
+                case MM_DISP:
+                case MM_PROTECT:
+                    /* Robes */
+                    return(4);
+                when MM_BRACERS:
+                case MM_G_DEXTERITY:
+                case MM_G_OGRE:
+                case MM_FUMBLE:
+                    /* Hand garments */
+                    return(3);
+                when MM_JEWEL:
+                case MM_ADAPTION:
+                case MM_STRANGLE:
+                    /* Jewelry */
+                    return(2);
+                otherwise:
+                    return(1);  /* What is it? */
+        }
+        otherwise:
+            return(1);  /* What is it? */
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xrogue/wizard.c	Tue Apr 21 08:55:20 2015 -0400
@@ -0,0 +1,819 @@
+/*
+    wizard.c - Special wizard commands
+    
+    XRogue: Expeditions into the Dungeons of Doom
+    Copyright (C) 1991 Robert Pietkivitch
+    All rights reserved.
+    
+    Based on "Advanced Rogue"
+    Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka and AT&T
+    All rights reserved.
+
+    Based on "Rogue: Exploring the Dungeons of Doom"
+    Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
+    All rights reserved.
+    
+    See the file LICENSE.TXT for full copyright and licensing information.
+*/
+
+/*
+ * Special wizard commands (some of which are also non-wizard commands
+ * under strange circumstances)
+ */
+
+#include <curses.h>
+#include <ctype.h>
+#include <string.h>
+#include "rogue.h"
+#include "mach_dep.h"
+
+/*
+ * create_obj:
+ *      Create any object for wizard, scroll, magician, or cleric
+ */
+
+create_obj(prompt, which_item, which_type)
+bool prompt;
+int which_item, which_type;
+{
+    reg struct linked_list *item;
+    reg struct object *obj;
+    reg int wh;
+    char *pt;
+    reg int ch, whc, newtype = 0, msz, newitem;
+    WINDOW *thiswin;
+
+    thiswin = cw;
+    if (prompt) {
+        bool nogood = TRUE;
+
+        thiswin = hw;
+        wclear(hw);
+        wprintw(hw,"Item\t\t\tKey\n\n");
+        wprintw(hw,"%s\t\t\t%c\n%s\t\t\t%c\n",things[TYP_RING].mi_name,RING,
+                things[TYP_STICK].mi_name,STICK);
+        wprintw(hw,"%s\t\t\t%c\n%s\t\t\t%c\n",things[TYP_POTION].mi_name,POTION,
+                things[TYP_SCROLL].mi_name,SCROLL);
+        wprintw(hw,"%s\t\t\t%c\n%s\t\t\t%c\n",things[TYP_ARMOR].mi_name,ARMOR,
+                things[TYP_WEAPON].mi_name,WEAPON);
+        wprintw(hw,"%s\t%c\n",things[TYP_MM].mi_name,MM);
+        wprintw(hw,"%s\t\t\t%c\n",things[TYP_FOOD].mi_name,FOOD);
+        if (wizard) {
+            wprintw(hw,"%s\t\t%c\n",things[TYP_RELIC].mi_name,RELIC);
+            wprintw(hw,"monster\t\t\tm");
+        }
+        wprintw(hw,"\n\nWhat do you want to create? ");
+        draw(hw);
+        do {
+            ch = wgetch(hw);
+            if (ch == ESC) {
+                restscr(cw);
+                return;
+            }
+            switch (ch) {
+                case RING:
+                case STICK:     
+                case POTION:
+                case SCROLL:    
+                case ARMOR:     
+                case WEAPON:
+                case FOOD:
+                case MM:
+                    nogood = FALSE;
+                    break;
+                case RELIC:
+                case 'm':
+                    if (wizard) 
+                        nogood = FALSE;
+                    break;
+                default:
+                    nogood = TRUE;
+            }
+        } while (nogood);
+        newitem = ch;
+    }
+    else
+        newitem = which_item;
+
+    pt = "those";
+    msz = 0;
+    if(newitem == 'm') {
+        /* make monster and be done with it */
+        wh = makemonster(TRUE, "create");
+        if (wh > 0) {
+            creat_mons (&player, wh, TRUE);
+            light(&hero);
+        }
+        return;
+    }
+    if(newitem == GOLD) pt = "gold";
+    else if(isatrap(newitem)) pt = "traps";
+
+    switch(newitem) {
+        case POTION:    whc = TYP_POTION;       msz = MAXPOTIONS;
+        when SCROLL:    whc = TYP_SCROLL;       msz = MAXSCROLLS;
+        when WEAPON:    whc = TYP_WEAPON;       msz = MAXWEAPONS;
+        when ARMOR:     whc = TYP_ARMOR;        msz = MAXARMORS;
+        when RING:      whc = TYP_RING;         msz = MAXRINGS;
+        when STICK:     whc = TYP_STICK;        msz = MAXSTICKS;
+        when MM:        whc = TYP_MM;           msz = MAXMM;
+        when RELIC:     whc = TYP_RELIC;        msz = MAXRELIC;
+        when FOOD:      whc = TYP_FOOD;         msz = MAXFOODS;
+        otherwise:
+            if (thiswin == hw)
+                restscr(cw);
+            mpos = 0;
+            msg("Even wizards can't create %s !!",pt);
+            return;
+    }
+    if(msz == 1) {              /* if only one type of item */
+        ch = 'a';
+    }
+    else if (prompt) {
+        register struct magic_item *wmi;
+        char wmn;
+        register int ii;
+        int old_prob;
+
+        mpos = 0;
+        wmi = NULL;
+        wmn = 0;
+        switch(newitem) {
+                case POTION:    wmi = &p_magic[0];
+                when SCROLL:    wmi = &s_magic[0];
+                when RING:      wmi = &r_magic[0];
+                when STICK:     wmi = &ws_magic[0];
+                when MM:        wmi = &m_magic[0];
+                when RELIC:     wmi = &rel_magic[0];
+                when FOOD:      wmi = &foods[0];
+                when WEAPON:    wmn = 1;
+                when ARMOR:     wmn = 2;
+        }
+        wclear(hw);
+        thiswin = hw;
+        if (wmi != NULL) {
+            ii = old_prob = 0;
+            while (ii < msz) {
+                if(wmi->mi_prob == old_prob && wizard == FALSE) { 
+                    msz--; /* can't make a unique item */
+                }
+                else {
+                    mvwaddch(hw,ii % 13,ii > 12 ? cols/2 : 0, ii + 'a');
+                    waddstr(hw,") ");
+                    waddstr(hw,wmi->mi_name);
+                    ii++;
+                }
+                old_prob = wmi->mi_prob;
+                wmi++;
+            }
+        }
+        else if (wmn != 0) {
+            for(ii = 0 ; ii < msz ; ii++) {
+                mvwaddch(hw,ii % 13,ii > 12 ? cols/2 : 0, ii + 'a');
+                waddstr(hw,") ");
+                if(wmn == 1)
+                    waddstr(hw,weaps[ii].w_name);
+                else
+                    waddstr(hw,armors[ii].a_name);
+            }
+        }
+        sprintf(prbuf,"Which %s? ",things[whc].mi_name);
+        mvwaddstr(hw,lines - 1, 0, prbuf);
+        draw(hw);
+        do {
+            ch = wgetch(hw);
+            if (ch == ESC) {
+                restscr(cw);
+                msg("");
+                return;
+            }
+        } until (isalpha(ch));
+        if (thiswin == hw)                      /* restore screen if need be */
+            restscr(cw);
+        newtype = ch - 'a';
+        if(newtype < 0 || newtype >= msz) {     /* if an illegal value */
+            mpos = 0;
+            msg("There is no such %s",things[whc].mi_name);
+            return;
+        }
+    }
+    else 
+        newtype = which_type;
+    item = new_item(sizeof *obj);       /* get some memory */
+    obj = OBJPTR(item);
+    obj->o_type = newitem;              /* store the new items */
+    obj->o_mark[0] = '\0';
+    obj->o_which = newtype;
+    obj->o_group = 0;
+    obj->contents = NULL;
+    obj->o_count = 1;
+    obj->o_flags = 0;
+    obj->o_dplus = obj->o_hplus = 0;
+    obj->o_weight = 0;
+    wh = obj->o_which;
+    mpos = 0;
+    if (!wizard)                /* users get 0 to +5 */
+        whc = rnd(6);
+    else                        /* wizard gets to choose */
+        whc = getbless();
+    if (whc < 0)
+        obj->o_flags |= ISCURSED;
+    switch (obj->o_type) {
+        case WEAPON:
+        case ARMOR:
+            if (obj->o_type == WEAPON) {
+                init_weapon(obj, wh);
+                obj->o_hplus += whc;
+                if (!wizard) whc = rnd(6);
+                obj->o_dplus += whc;
+            }
+            else {                              /* armor here */
+                obj->o_weight = armors[wh].a_wght;
+                obj->o_ac = armors[wh].a_class - whc;
+            }
+        when RING:
+            r_know[wh] = TRUE;
+            switch(wh) {
+                case R_ADDSTR:
+                case R_ADDWISDOM:
+                case R_ADDINTEL:
+                case R_PROTECT:
+                case R_ADDHIT:
+                case R_ADDDAM:
+                case R_DIGEST:
+                    obj->o_ac = whc + 2;
+                    break;
+                default: 
+                    obj->o_ac = 0;
+            }
+            obj->o_weight = things[TYP_RING].mi_wght;
+        when MM:
+            if (whc > 1 && m_magic[wh].mi_bless != 0)
+                obj->o_flags |= ISBLESSED;
+            m_know[wh] = TRUE;
+            switch(wh) {
+                case MM_JUG:
+                    switch(rnd(11)) {
+                        case 0: obj->o_ac = P_PHASE;
+                        when 1: obj->o_ac = P_CLEAR;
+                        when 2: obj->o_ac = P_SEEINVIS;
+                        when 3: obj->o_ac = P_HEALING;
+                        when 4: obj->o_ac = P_MFIND;
+                        when 5: obj->o_ac = P_TFIND;
+                        when 6: obj->o_ac = P_HASTE;
+                        when 7: obj->o_ac = P_RESTORE;
+                        when 8: obj->o_ac = P_FLY;
+                        when 9: obj->o_ac = P_SKILL;
+                        when 10:obj->o_ac = P_FFIND;
+                    }
+                when MM_HUNGER:
+                case MM_CHOKE:
+            if (whc < 0 )
+            whc = -whc;     /* cannot be negative */
+            obj->o_ac = (whc + 1) * 2;
+            break;
+                when MM_OPEN:
+                case MM_DRUMS:
+                case MM_DISAPPEAR:
+                case MM_KEOGHTOM:
+                    if (whc < 0)
+                        whc = -whc;     /* these cannot be negative */
+                    obj->o_ac = (whc + 3) * 5;
+                    break;
+                when MM_BRACERS:
+                    obj->o_ac = whc + 4;
+                when MM_DISP:
+                    obj->o_ac = 3;
+                when MM_PROTECT:
+                    obj->o_ac = whc + 4;
+                when MM_SKILLS:
+                    if (whc < 2)
+                        obj->o_ac = rnd(NUM_CHARTYPES-1);
+                    else
+                        obj->o_ac = player.t_ctype;
+        when MM_CRYSTAL:
+            obj->o_ac = 1;
+                otherwise: 
+                    obj->o_ac = 0;
+            }
+            obj->o_weight = things[TYP_MM].mi_wght;
+        when STICK:
+            if (whc > 1 && ws_magic[wh].mi_bless != 0)
+                obj->o_flags |= ISBLESSED;
+            ws_know[wh] = TRUE;
+            fix_stick(obj);
+        when SCROLL:
+            if (whc > 3 && s_magic[wh].mi_bless != 0)
+                obj->o_flags |= ISBLESSED;
+            obj->o_weight = things[TYP_SCROLL].mi_wght;
+            s_know[wh] = TRUE;
+        when POTION:
+            if (whc > 3 && p_magic[wh].mi_bless != 0)
+                obj->o_flags |= ISBLESSED;
+            obj->o_weight = things[TYP_POTION].mi_wght;
+            if (wh == P_ABIL) obj->o_kind = rnd(NUMABILITIES);
+            p_know[wh] = TRUE;
+        when RELIC:
+            obj->o_weight = things[TYP_RELIC].mi_wght;
+            switch (obj->o_which) {
+                case QUILL_NAGROM: obj->o_charges = QUILLCHARGES;
+                when EMORI_CLOAK:  obj->o_charges = 1;
+                otherwise: break;
+            }
+        when FOOD:
+            obj->o_weight = things[TYP_FOOD].mi_wght;
+    }
+    mpos = 0;
+    obj->o_flags |= ISKNOW;
+    if (add_pack(item, FALSE) == FALSE) {
+        obj->o_pos = hero;
+        fall(item, TRUE);
+    }
+}
+
+/*
+ * getbless:
+ *      Get a blessing for a wizards object
+ */
+
+int
+getbless()
+{
+        reg char bless;
+
+        msg("Blessing? (+,-,n)");
+        bless = wgetch(msgw);
+        if (bless == '+')
+                return (15);
+        else if (bless == '-')
+                return (-1);
+        else
+                return (0);
+}
+
+/*
+ * get a non-monster death type
+ */
+
+getdeath()
+{
+    register int i;
+    int which_death;
+    char label[80];
+
+    clear();
+    for (i=0; i<DEATHNUM; i++) {
+        sprintf(label, "[%d] %s", i+1, deaths[i].name);
+        mvaddstr(i+2, 0, label);
+    }
+    mvaddstr(0, 0, "Which death? ");
+    refresh();
+
+    /* Get the death */
+    for (;;) {
+        get_str(label, stdscr);
+        which_death = atoi(label);
+        if ((which_death < 1 || which_death > DEATHNUM)) {
+            mvaddstr(0, 0, "Please enter a number in the displayed range -- ");
+            refresh();
+        }
+        else break;
+    }
+    return(deaths[which_death-1].reason);
+}
+
+/*
+ * make a monster for the wizard
+ */
+
+makemonster(showall, action) 
+bool showall;   /* showall -> show uniques and genocided creatures */
+char *action;
+{
+    register int i;
+    register short which_monst;
+    register int num_monst = NUMMONST, pres_monst=1, num_lines=2*(lines-3);
+    int max_monster;
+    char monst_name[40];
+
+    /* If we're not showing all, subtract UNIQUES, DINOS, and quartermaster */
+    if (!showall) num_monst -= NUMUNIQUE + NUMDINOS + 1;
+    max_monster = num_monst;
+
+    /* Print out the monsters */
+
+    if (levtype == OUTSIDE) {
+        num_monst = NUMDINOS;
+        max_monster = NUMMONST - 1;
+        pres_monst = (pres_monst + NUMMONST - NUMDINOS - 1);
+    }
+
+    while (num_monst > 0) {
+        register int left_limit;
+
+        if (num_monst < num_lines) left_limit = (num_monst+1)/2;
+        else left_limit = num_lines/2;
+
+        wclear(hw);
+        touchwin(hw);
+
+        /* Print left column */
+        wmove(hw, 2, 0);
+        for (i=0; i<left_limit; i++) {
+            sprintf(monst_name, "[%d] %c%s\n",
+                                pres_monst,
+                                (showall || monsters[pres_monst].m_normal)
+                                    ? ' '
+                                    : '*',
+                                monsters[pres_monst].m_name);
+            waddstr(hw, monst_name);
+            pres_monst++;
+        }
+
+        /* Print right column */
+        for (i=0; i<left_limit && pres_monst<=max_monster; i++) {
+            sprintf(monst_name, "[%d] %c%s",
+                                pres_monst,
+                                (showall || monsters[pres_monst].m_normal)
+                                    ? ' '
+                                    : '*',
+                                monsters[pres_monst].m_name);
+            wmove(hw, i+2, cols/2);
+            waddstr(hw, monst_name);
+            pres_monst++;
+        }
+
+        if ((num_monst -= num_lines) > 0) {
+            mvwaddstr(hw, lines-1, 0, morestr);
+            draw(hw);
+            wait_for(' ');
+        }
+
+        else {
+            mvwaddstr(hw, 0, 0, "Which monster");
+            if (!terse) {
+                waddstr(hw, " do you wish to ");
+                waddstr(hw, action);
+            }
+            waddstr(hw, "? ");
+            draw(hw);
+        }
+    }
+
+get_monst:
+    get_str(monst_name, hw);
+    which_monst = atoi(monst_name);
+    if (levtype == OUTSIDE)
+    if ((which_monst < NUMMONST-NUMDINOS || which_monst > max_monster)) {
+        mvwaddstr(hw, 0, 0, "Please enter a number in the displayed range -- ");
+        draw(hw);
+        goto get_monst;
+    }
+    if ((which_monst < 1 || which_monst > max_monster)) {
+        mvwaddstr(hw, 0, 0, "Please enter a number in the displayed range -- ");
+        draw(hw);
+        goto get_monst;
+    }
+    restscr(cw);
+    return(which_monst);
+}
+
+/*
+ * passwd:
+ *      see if user knows password
+ */
+
+bool
+passwd()
+{
+    register char *sp, c;
+    char buf[LINELEN];
+
+    msg("Wizard's Password:");
+    mpos = 0;
+    sp = buf;
+    while ((c = wgetch(cw)) != '\n' && c != '\r' && c != '\033') {
+        if (c == killchar())
+            sp = buf;
+        else if (c == erasechar() && sp > buf)
+            sp--;
+        else
+            *sp++ = c;
+    }
+    if (sp == buf)
+        return FALSE;
+    *sp = '\0';
+    return (strcmp(PASSWD, xcrypt(buf, "mT")) == 0);
+
+    /* don't mess with the password here or elsewhere.
+     *
+     * If anyone goes wizard they forfeit being placed in the scorefile.
+     * So, no need to be secretive about it.  Let them have it!
+     *
+     * Additionally, you can begin the game as wizard by starting it
+     * with a null argument, as in: xrogue ""
+     */
+}
+
+/*
+ * teleport:
+ *      Bamf the hero someplace else
+ */
+
+void
+teleport()
+{
+    register struct room *new_rp = NULL, *old_rp = roomin(&hero);
+    register int rm, which;
+    coord old;
+    bool got_position = FALSE;
+
+    /* Disrupt whatever the hero was doing */
+    dsrpt_player();
+
+    /*
+     * If the hero wasn't doing something disruptable, NULL out his
+     * action anyway and let him know about it.  We don't want him
+     * swinging or moving into his old place.
+     */
+    if (player.t_action != A_NIL) {
+        player.t_action = A_NIL;
+        msg("You feel momentarily disoriented.");
+    }
+
+    old = hero;
+    mvwaddch(cw, hero.y, hero.x, mvwinch(stdscr, hero.y, hero.x));
+    if (ISWEARING(R_TELCONTROL) || wizard) {
+        got_position = move_hero(H_TELEPORT);
+        if (!got_position)
+            msg("Your attempt fails.");
+        else {
+            new_rp = roomin(&hero);
+            msg("You teleport successfully.");
+        }
+    }
+    if (!got_position) {
+        do {
+            rm = rnd_room();
+            rnd_pos(&rooms[rm], &hero);
+        } until(winat(hero.y, hero.x) == FLOOR);
+        new_rp = &rooms[rm];
+    }
+    player.t_oldpos = old;      /* Save last position */
+
+    /* If hero gets moved, darken old room */
+    if (old_rp && old_rp != new_rp) {
+        old_rp->r_flags |= FORCEDARK;   /* Fake darkness */
+        light(&old);
+        old_rp->r_flags &= ~FORCEDARK; /* Restore light state */
+    }
+
+    /* Darken where we just came from */
+    else if (levtype == MAZELEV) light(&old);
+
+    light(&hero);
+    mvwaddch(cw, hero.y, hero.x, PLAYER);
+    /* if entering a treasure room, wake everyone up......Surprise! */
+    if (new_rp->r_flags & ISTREAS)
+        wake_room(new_rp);
+
+    /* Reset current room and position */
+    oldrp = new_rp;     /* Used in look() */
+    player.t_oldpos = hero;
+    /*
+     * make sure we set/unset the ISINWALL on a teleport
+     */
+    which = winat(hero.y, hero.x);
+    if (isrock(which)) turn_on(player, ISINWALL);
+    else turn_off(player, ISINWALL);
+
+    /*
+     * turn off ISHELD in case teleportation was done while fighting
+     * something that holds you
+     */
+    if (on(player, ISHELD)) {
+        register struct linked_list *ip, *nip;
+        register struct thing *mp;
+
+        turn_off(player, ISHELD);
+        hold_count = 0;
+        for (ip = mlist; ip; ip = nip) {
+            mp = THINGPTR(ip);
+            nip = next(ip);
+            if (on(*mp, DIDHOLD)) {
+                turn_off(*mp, DIDHOLD);
+                turn_on(*mp, CANHOLD);
+            }
+            turn_off(*mp, DIDSUFFOCATE); /* Suffocation -- see below */
+        }
+    }
+
+    /* Make sure player does not suffocate */
+    extinguish(suffocate);
+
+    count = 0;
+    running = FALSE;
+    flushinp();
+}
+
+/*
+ * whatis:
+ *      What a certin object is
+ */
+
+whatis(what)
+struct linked_list *what;
+{
+    register struct object *obj;
+    register struct linked_list *item;
+
+    if (what == NULL) {         /* do we need to ask which one? */
+        if ((item = get_item(pack, "identify", IDENTABLE, FALSE, FALSE))==NULL)
+            return;
+    }
+    else
+        item = what;
+    obj = OBJPTR(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;
+            if (ws_guess[obj->o_which]) {
+                free(ws_guess[obj->o_which]);
+                ws_guess[obj->o_which] = NULL;
+            }
+        when RING:
+            r_know[obj->o_which] = TRUE;
+            if (r_guess[obj->o_which]) {
+                free(r_guess[obj->o_which]);
+                r_guess[obj->o_which] = NULL;
+            }
+        when MM:
+            /* If it's an identified jug, identify its potion */
+            if (obj->o_which == MM_JUG && (obj->o_flags & ISKNOW)) {
+                if (obj->o_ac != JUG_EMPTY)
+                    p_know[obj->o_ac] = TRUE;
+                break;
+            }
+
+            m_know[obj->o_which] = TRUE;
+            if (m_guess[obj->o_which]) {
+                free(m_guess[obj->o_which]);
+                m_guess[obj->o_which] = NULL;
+            }
+        otherwise:
+            break;
+    }
+    obj->o_flags |= ISKNOW;
+    if (what == NULL)
+        msg(inv_name(obj, FALSE));
+}
+
+/* 
+ *  Choose a quest item
+ *      (if on STARTLEV equipage level = 0)
+ */
+
+choose_qst()
+{
+    bool doit = TRUE;
+    bool escp = TRUE;
+
+    /* let wizard in on this too */
+    if (waswizard == TRUE || (levtype == POSTLEV && level == 0)) {
+        wclear(hw);
+    touchwin(hw);
+        wmove(hw, 2, 0);
+        wprintw(hw, "a) Cloak of Emori\n");
+        wprintw(hw, "b) Ankh of Heil\n");
+        wprintw(hw, "c) Quill of Nagrom\n");
+        wprintw(hw, "d) Eye of Vecna\n");
+        wprintw(hw, "e) Ring of Surtur\n");
+        wprintw(hw, "f) Staff of Ming\n");
+        wprintw(hw, "g) Wand of Orcus\n");
+        wprintw(hw, "h) Rod of Asmodeus\n");
+        wprintw(hw, "i) Amulet of Yendor\n");
+        wprintw(hw, "j) Amulet of Stonebones\n");
+        wprintw(hw, "k) Mandolin of Brian\n"); 
+        wprintw(hw, "l) Horn of Geryon\n");
+        wprintw(hw, "m) Daggers of Musty Doit\n");
+        wprintw(hw, "n) Axe of Aklad\n");
+        wprintw(hw, "o) Morning Star of Hruggek\n");
+        wprintw(hw, "p) Flail of Yeenoghu\n");
+        wprintw(hw, "q) Card of Alteran\n");
+        mvwaddstr(hw, 0, 0, "Select a quest item: "); /* prompt */
+
+        if (menu_overlay)  /* Print the selections.  The longest line is
+                * Hruggek (26 characters).  The prompt is 21.
+                */
+            over_win(cw, hw, 20, 29, 0, 21, NULL);
+        else
+            draw(hw);
+
+        while (doit) {
+        switch (wgetch(cw)) {
+            case EOF:
+            case ESC:
+                escp = FALSE;   /* used below */
+            doit = FALSE;
+            when 'a':
+                quest_item = EMORI_CLOAK;
+            doit = FALSE;
+            when 'b':
+                quest_item = HEIL_ANKH;
+            doit = FALSE;
+            when 'c':
+                quest_item = QUILL_NAGROM;
+            doit = FALSE;
+            when 'd':
+                quest_item = EYE_VECNA;
+            doit = FALSE;
+            when 'e':
+                quest_item = SURTUR_RING;
+            doit = FALSE;
+            when 'f':
+                quest_item = MING_STAFF;
+            doit = FALSE;
+            when 'g':
+                quest_item = ORCUS_WAND;
+            doit = FALSE;
+            when 'h':
+                quest_item = ASMO_ROD;
+            doit = FALSE;
+            when 'i':
+                quest_item = YENDOR_AMULET;
+            doit = FALSE;
+            when 'j':
+                quest_item = STONEBONES_AMULET;
+            doit = FALSE;
+            when 'k':
+                quest_item = BRIAN_MANDOLIN;
+            doit = FALSE;
+            when 'l':
+                quest_item = GERYON_HORN;
+            doit = FALSE;
+            when 'm':
+                quest_item = MUSTY_DAGGER;
+            doit = FALSE;
+            when 'n':
+                quest_item = AXE_AKLAD;
+            doit = FALSE;
+            when 'o':
+                quest_item = HRUGGEK_MSTAR;
+            doit = FALSE;
+            when 'p':
+                quest_item = YEENOGHU_FLAIL;
+            doit = FALSE;
+            when 'q':
+                quest_item = ALTERAN_CARD;
+            doit = FALSE;
+            otherwise:
+            doit = TRUE;
+        }
+    }
+    if (menu_overlay) {
+            status(FALSE);
+            touchwin(cw);
+        if (escp == TRUE) {
+                msg("Your quest item is the %s.  --More--",
+             rel_magic[quest_item].mi_name);
+            wait_for(' ');
+        }
+        return;
+    }
+    else {
+        if (escp == TRUE) {
+                wmove(hw, lines-4, 0);
+                wprintw(hw, "Your quest item is the %s.",
+                    rel_magic[quest_item].mi_name);
+        }
+            wmove(hw, lines-1, 0);
+            wprintw(hw, spacemsg);
+            draw(hw);
+            wait_for(' ');
+            wclear(hw);
+            draw(hw);
+            wmove(cw, 0, 0);
+            wclrtoeol(cw);
+            status(FALSE);
+            touchwin(cw);
+        return;
+    }
+    }
+    else {
+        msg("You can no longer select a quest item. ");
+        return;
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xrogue/xcrypt.c	Tue Apr 21 08:55:20 2015 -0400
@@ -0,0 +1,691 @@
+/*
+ * FreeSec: libcrypt
+ *
+ * Copyright (C) 1994 David Burren
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name(s) of the author(s) nor the names of other contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR(S) OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *
+ * This is an original implementation of the DES and the crypt(3) interfaces
+ * by David Burren <davidb@werj.com.au>.
+ *
+ * An excellent reference on the underlying algorithm (and related
+ * algorithms) is:
+ *
+ *  B. Schneier, Applied Cryptography: protocols, algorithms,
+ *  and source code in C, John Wiley & Sons, 1994.
+ *
+ * Note that in that book's description of DES the lookups for the initial,
+ * pbox, and final permutations are inverted (this has been brought to the
+ * attention of the author).  A list of errata for this book has been
+ * posted to the sci.crypt newsgroup by the author and is available for FTP.
+ *
+ * NOTE:
+ * This file has a static version of des_setkey() so that crypt.o exports
+ * only the crypt() interface. This is required to make binaries linked
+ * against crypt.o exportable or re-exportable from the USA.
+ */
+
+#include <sys/types.h>
+#include <string.h>
+
+#define _PASSWORD_EFMT1 '_'
+
+static unsigned char    IP[64] = {
+    58, 50, 42, 34, 26, 18, 10,  2, 60, 52, 44, 36, 28, 20, 12,  4,
+    62, 54, 46, 38, 30, 22, 14,  6, 64, 56, 48, 40, 32, 24, 16,  8,
+    57, 49, 41, 33, 25, 17,  9,  1, 59, 51, 43, 35, 27, 19, 11,  3,
+    61, 53, 45, 37, 29, 21, 13,  5, 63, 55, 47, 39, 31, 23, 15,  7
+};
+
+static unsigned char    inv_key_perm[64];
+static unsigned char    key_perm[56] = {
+    57, 49, 41, 33, 25, 17,  9,  1, 58, 50, 42, 34, 26, 18,
+    10,  2, 59, 51, 43, 35, 27, 19, 11,  3, 60, 52, 44, 36,
+    63, 55, 47, 39, 31, 23, 15,  7, 62, 54, 46, 38, 30, 22,
+    14,  6, 61, 53, 45, 37, 29, 21, 13,  5, 28, 20, 12,  4
+};
+
+static unsigned char    key_shifts[16] = {
+    1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1
+};
+
+static unsigned char    inv_comp_perm[56];
+static unsigned char    comp_perm[48] = {
+    14, 17, 11, 24,  1,  5,  3, 28, 15,  6, 21, 10,
+    23, 19, 12,  4, 26,  8, 16,  7, 27, 20, 13,  2,
+    41, 52, 31, 37, 47, 55, 30, 40, 51, 45, 33, 48,
+    44, 49, 39, 56, 34, 53, 46, 42, 50, 36, 29, 32
+};
+
+/*
+ *  No E box is used, as it's replaced by some ANDs, shifts, and ORs.
+ */
+
+static unsigned char    u_sbox[8][64];
+static unsigned char    sbox[8][64] = {
+    {
+        14,  4, 13,  1,  2, 15, 11,  8,  3, 10,  6, 12,  5,  9,  0,  7,
+         0, 15,  7,  4, 14,  2, 13,  1, 10,  6, 12, 11,  9,  5,  3,  8,
+         4,  1, 14,  8, 13,  6,  2, 11, 15, 12,  9,  7,  3, 10,  5,  0,
+        15, 12,  8,  2,  4,  9,  1,  7,  5, 11,  3, 14, 10,  0,  6, 13
+    },
+    {
+        15,  1,  8, 14,  6, 11,  3,  4,  9,  7,  2, 13, 12,  0,  5, 10,
+         3, 13,  4,  7, 15,  2,  8, 14, 12,  0,  1, 10,  6,  9, 11,  5,
+         0, 14,  7, 11, 10,  4, 13,  1,  5,  8, 12,  6,  9,  3,  2, 15,
+        13,  8, 10,  1,  3, 15,  4,  2, 11,  6,  7, 12,  0,  5, 14,  9
+    },
+    {
+        10,  0,  9, 14,  6,  3, 15,  5,  1, 13, 12,  7, 11,  4,  2,  8,
+        13,  7,  0,  9,  3,  4,  6, 10,  2,  8,  5, 14, 12, 11, 15,  1,
+        13,  6,  4,  9,  8, 15,  3,  0, 11,  1,  2, 12,  5, 10, 14,  7,
+         1, 10, 13,  0,  6,  9,  8,  7,  4, 15, 14,  3, 11,  5,  2, 12
+    },
+    {
+         7, 13, 14,  3,  0,  6,  9, 10,  1,  2,  8,  5, 11, 12,  4, 15,
+        13,  8, 11,  5,  6, 15,  0,  3,  4,  7,  2, 12,  1, 10, 14,  9,
+        10,  6,  9,  0, 12, 11,  7, 13, 15,  1,  3, 14,  5,  2,  8,  4,
+         3, 15,  0,  6, 10,  1, 13,  8,  9,  4,  5, 11, 12,  7,  2, 14
+    },
+    {
+         2, 12,  4,  1,  7, 10, 11,  6,  8,  5,  3, 15, 13,  0, 14,  9,
+        14, 11,  2, 12,  4,  7, 13,  1,  5,  0, 15, 10,  3,  9,  8,  6,
+         4,  2,  1, 11, 10, 13,  7,  8, 15,  9, 12,  5,  6,  3,  0, 14,
+        11,  8, 12,  7,  1, 14,  2, 13,  6, 15,  0,  9, 10,  4,  5,  3
+    },
+    {
+        12,  1, 10, 15,  9,  2,  6,  8,  0, 13,  3,  4, 14,  7,  5, 11,
+        10, 15,  4,  2,  7, 12,  9,  5,  6,  1, 13, 14,  0, 11,  3,  8,
+         9, 14, 15,  5,  2,  8, 12,  3,  7,  0,  4, 10,  1, 13, 11,  6,
+         4,  3,  2, 12,  9,  5, 15, 10, 11, 14,  1,  7,  6,  0,  8, 13
+    },
+    {
+         4, 11,  2, 14, 15,  0,  8, 13,  3, 12,  9,  7,  5, 10,  6,  1,
+        13,  0, 11,  7,  4,  9,  1, 10, 14,  3,  5, 12,  2, 15,  8,  6,
+         1,  4, 11, 13, 12,  3,  7, 14, 10, 15,  6,  8,  0,  5,  9,  2,
+         6, 11, 13,  8,  1,  4, 10,  7,  9,  5,  0, 15, 14,  2,  3, 12
+    },
+    {
+        13,  2,  8,  4,  6, 15, 11,  1, 10,  9,  3, 14,  5,  0, 12,  7,
+         1, 15, 13,  8, 10,  3,  7,  4, 12,  5,  6, 11,  0, 14,  9,  2,
+         7, 11,  4,  1,  9, 12, 14,  2,  0,  6, 10, 13, 15,  3,  5,  8,
+         2,  1, 14,  7,  4, 10,  8, 13, 15, 12,  9,  0,  3,  5,  6, 11
+    }
+};
+
+static unsigned char    un_pbox[32];
+static unsigned char    pbox[32] = {
+    16,  7, 20, 21, 29, 12, 28, 17,  1, 15, 23, 26,  5, 18, 31, 10,
+     2,  8, 24, 14, 32, 27,  3,  9, 19, 13, 30,  6, 22, 11,  4, 25
+};
+
+static unsigned int bits32[32] =
+{
+    0x80000000, 0x40000000, 0x20000000, 0x10000000,
+    0x08000000, 0x04000000, 0x02000000, 0x01000000,
+    0x00800000, 0x00400000, 0x00200000, 0x00100000,
+    0x00080000, 0x00040000, 0x00020000, 0x00010000,
+    0x00008000, 0x00004000, 0x00002000, 0x00001000,
+    0x00000800, 0x00000400, 0x00000200, 0x00000100,
+    0x00000080, 0x00000040, 0x00000020, 0x00000010,
+    0x00000008, 0x00000004, 0x00000002, 0x00000001
+};
+
+static unsigned char    bits8[8] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 };
+
+static unsigned int saltbits;
+static int  old_salt;
+static unsigned int *bits28, *bits24;
+static unsigned char    init_perm[64], final_perm[64];
+static unsigned int en_keysl[16], en_keysr[16];
+static unsigned int de_keysl[16], de_keysr[16];
+static int  des_initialised = 0;
+static unsigned char    m_sbox[4][4096];
+static unsigned int psbox[4][256];
+static unsigned int ip_maskl[8][256], ip_maskr[8][256];
+static unsigned int fp_maskl[8][256], fp_maskr[8][256];
+static unsigned int key_perm_maskl[8][128], key_perm_maskr[8][128];
+static unsigned int comp_maskl[8][128], comp_maskr[8][128];
+static unsigned int old_rawkey0, old_rawkey1;
+
+static unsigned char    ascii64[] =
+     "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
+/*    0000000000111111111122222222223333333333444444444455555555556666 */
+/*    0123456789012345678901234567890123456789012345678901234567890123 */
+
+static __inline int
+ascii_to_bin(ch)
+    char ch;
+{
+    if (ch > 'z')
+        return(0);
+    if (ch >= 'a')
+        return(ch - 'a' + 38);
+    if (ch > 'Z')
+        return(0);
+    if (ch >= 'A')
+        return(ch - 'A' + 12);
+    if (ch > '9')
+        return(0);
+    if (ch >= '.')
+        return(ch - '.');
+    return(0);
+}
+
+static void
+des_init()
+{
+    int i, j, b, k, inbit, obit;
+    unsigned int    *p, *il, *ir, *fl, *fr;
+
+    old_rawkey0 = old_rawkey1 = 0;
+    saltbits = 0;
+    old_salt = 0;
+    bits24 = (bits28 = bits32 + 4) + 4;
+
+    /*
+     * Invert the S-boxes, reordering the input bits.
+     */
+    for (i = 0; i < 8; i++)
+        for (j = 0; j < 64; j++) {
+            b = (j & 0x20) | ((j & 1) << 4) | ((j >> 1) & 0xf);
+            u_sbox[i][j] = sbox[i][b];
+        }
+
+    /*
+     * Convert the inverted S-boxes into 4 arrays of 8 bits.
+     * Each will handle 12 bits of the S-box input.
+     */
+    for (b = 0; b < 4; b++)
+        for (i = 0; i < 64; i++)
+            for (j = 0; j < 64; j++)
+                m_sbox[b][(i << 6) | j] =
+                    (u_sbox[(b << 1)][i] << 4) |
+                    u_sbox[(b << 1) + 1][j];
+
+    /*
+     * Set up the initial & final permutations into a useful form, and
+     * initialise the inverted key permutation.
+     */
+    for (i = 0; i < 64; i++) {
+        init_perm[final_perm[i] = IP[i] - 1] = i;
+        inv_key_perm[i] = 255;
+    }
+
+    /*
+     * Invert the key permutation and initialise the inverted key
+     * compression permutation.
+     */
+    for (i = 0; i < 56; i++) {
+        inv_key_perm[key_perm[i] - 1] = i;
+        inv_comp_perm[i] = 255;
+    }
+
+    /*
+     * Invert the key compression permutation.
+     */
+    for (i = 0; i < 48; i++) {
+        inv_comp_perm[comp_perm[i] - 1] = i;
+    }
+
+    /*
+     * Set up the OR-mask arrays for the initial and final permutations,
+     * and for the key initial and compression permutations.
+     */
+    for (k = 0; k < 8; k++) {
+        for (i = 0; i < 256; i++) {
+            *(il = &ip_maskl[k][i]) = 0;
+            *(ir = &ip_maskr[k][i]) = 0;
+            *(fl = &fp_maskl[k][i]) = 0;
+            *(fr = &fp_maskr[k][i]) = 0;
+            for (j = 0; j < 8; j++) {
+                inbit = 8 * k + j;
+                if (i & bits8[j]) {
+                    if ((obit = init_perm[inbit]) < 32)
+                        *il |= bits32[obit];
+                    else
+                        *ir |= bits32[obit-32];
+                    if ((obit = final_perm[inbit]) < 32)
+                        *fl |= bits32[obit];
+                    else
+                        *fr |= bits32[obit - 32];
+                }
+            }
+        }
+        for (i = 0; i < 128; i++) {
+            *(il = &key_perm_maskl[k][i]) = 0;
+            *(ir = &key_perm_maskr[k][i]) = 0;
+            for (j = 0; j < 7; j++) {
+                inbit = 8 * k + j;
+                if (i & bits8[j + 1]) {
+                    if ((obit = inv_key_perm[inbit]) == 255)
+                        continue;
+                    if (obit < 28)
+                        *il |= bits28[obit];
+                    else
+                        *ir |= bits28[obit - 28];
+                }
+            }
+            *(il = &comp_maskl[k][i]) = 0;
+            *(ir = &comp_maskr[k][i]) = 0;
+            for (j = 0; j < 7; j++) {
+                inbit = 7 * k + j;
+                if (i & bits8[j + 1]) {
+                    if ((obit=inv_comp_perm[inbit]) == 255)
+                        continue;
+                    if (obit < 24)
+                        *il |= bits24[obit];
+                    else
+                        *ir |= bits24[obit - 24];
+                }
+            }
+        }
+    }
+
+    /*
+     * Invert the P-box permutation, and convert into OR-masks for
+     * handling the output of the S-box arrays setup above.
+     */
+    for (i = 0; i < 32; i++)
+        un_pbox[pbox[i] - 1] = i;
+
+    for (b = 0; b < 4; b++)
+        for (i = 0; i < 256; i++) {
+            *(p = &psbox[b][i]) = 0;
+            for (j = 0; j < 8; j++) {
+                if (i & bits8[j])
+                    *p |= bits32[un_pbox[8 * b + j]];
+            }
+        }
+
+    des_initialised = 1;
+}
+
+static void
+setup_salt(salt)
+    int salt;
+{
+    unsigned int    obit, saltbit;
+    int i;
+
+    if (salt == old_salt)
+        return;
+    old_salt = salt;
+
+    saltbits = 0;
+    saltbit = 1;
+    obit = 0x800000;
+    for (i = 0; i < 24; i++) {
+        if (salt & saltbit)
+            saltbits |= obit;
+        saltbit <<= 1;
+        obit >>= 1;
+    }
+}
+
+static int
+des_setkey(key)
+    const char *key;
+{
+    unsigned int k0, k1, rawkey0, rawkey1;
+    int shifts, round;
+
+    if (!des_initialised)
+        des_init();
+
+    rawkey0 = md_ntohl(*(unsigned int *) key);
+    rawkey1 = md_ntohl(*(unsigned int *) (key + 4));
+
+    if ((rawkey0 | rawkey1)
+        && rawkey0 == old_rawkey0
+        && rawkey1 == old_rawkey1) {
+        /*
+         * Already setup for this key.
+         * This optimisation fails on a zero key (which is weak and
+         * has bad parity anyway) in order to simplify the starting
+         * conditions.
+         */
+        return(0);
+    }
+    old_rawkey0 = rawkey0;
+    old_rawkey1 = rawkey1;
+
+    /*
+     *  Do key permutation and split into two 28-bit subkeys.
+     */
+    k0 = key_perm_maskl[0][rawkey0 >> 25]
+       | key_perm_maskl[1][(rawkey0 >> 17) & 0x7f]
+       | key_perm_maskl[2][(rawkey0 >> 9) & 0x7f]
+       | key_perm_maskl[3][(rawkey0 >> 1) & 0x7f]
+       | key_perm_maskl[4][rawkey1 >> 25]
+       | key_perm_maskl[5][(rawkey1 >> 17) & 0x7f]
+       | key_perm_maskl[6][(rawkey1 >> 9) & 0x7f]
+       | key_perm_maskl[7][(rawkey1 >> 1) & 0x7f];
+    k1 = key_perm_maskr[0][rawkey0 >> 25]
+       | key_perm_maskr[1][(rawkey0 >> 17) & 0x7f]
+       | key_perm_maskr[2][(rawkey0 >> 9) & 0x7f]
+       | key_perm_maskr[3][(rawkey0 >> 1) & 0x7f]
+       | key_perm_maskr[4][rawkey1 >> 25]
+       | key_perm_maskr[5][(rawkey1 >> 17) & 0x7f]
+       | key_perm_maskr[6][(rawkey1 >> 9) & 0x7f]
+       | key_perm_maskr[7][(rawkey1 >> 1) & 0x7f];
+    /*
+     *  Rotate subkeys and do compression permutation.
+     */
+    shifts = 0;
+    for (round = 0; round < 16; round++) {
+        unsigned int    t0, t1;
+
+        shifts += key_shifts[round];
+
+        t0 = (k0 << shifts) | (k0 >> (28 - shifts));
+        t1 = (k1 << shifts) | (k1 >> (28 - shifts));
+
+        de_keysl[15 - round] =
+        en_keysl[round] = comp_maskl[0][(t0 >> 21) & 0x7f]
+                | comp_maskl[1][(t0 >> 14) & 0x7f]
+                | comp_maskl[2][(t0 >> 7) & 0x7f]
+                | comp_maskl[3][t0 & 0x7f]
+                | comp_maskl[4][(t1 >> 21) & 0x7f]
+                | comp_maskl[5][(t1 >> 14) & 0x7f]
+                | comp_maskl[6][(t1 >> 7) & 0x7f]
+                | comp_maskl[7][t1 & 0x7f];
+
+        de_keysr[15 - round] =
+        en_keysr[round] = comp_maskr[0][(t0 >> 21) & 0x7f]
+                | comp_maskr[1][(t0 >> 14) & 0x7f]
+                | comp_maskr[2][(t0 >> 7) & 0x7f]
+                | comp_maskr[3][t0 & 0x7f]
+                | comp_maskr[4][(t1 >> 21) & 0x7f]
+                | comp_maskr[5][(t1 >> 14) & 0x7f]
+                | comp_maskr[6][(t1 >> 7) & 0x7f]
+                | comp_maskr[7][t1 & 0x7f];
+    }
+    return(0);
+}
+
+static int
+do_des(l_in, r_in, l_out, r_out, count)
+    unsigned int l_in, r_in, *l_out, *r_out;
+    int count;
+{
+    /*
+     *  l_in, r_in, l_out, and r_out are in pseudo-"big-endian" format.
+     */
+    unsigned int    l, r, *kl, *kr, *kl1, *kr1;
+    unsigned int    f = 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(in, out, salt, count)
+    const char *in;
+    char *out;
+    int salt;
+    int count;
+{
+    unsigned int l_out, r_out, rawl, rawr;
+    unsigned int x[2];
+    int retval;
+
+    if (!des_initialised)
+        des_init();
+
+    setup_salt(salt);
+
+    memcpy(x, in, sizeof x);
+    rawl = md_ntohl(x[0]);
+    rawr = md_ntohl(x[1]);
+    retval = do_des(rawl, rawr, &l_out, &r_out, count);
+
+    x[0] = md_htonl(l_out);
+    x[1] = md_htonl(r_out);
+    memcpy(out, x, sizeof x);
+    return(retval);
+}
+
+char *
+xcrypt(key, setting)
+    const char *key;
+    const char *setting;
+{
+    int     i;
+    unsigned int    count, salt, l, r0, r1, keybuf[2];
+    unsigned char       *p, *q;
+    static unsigned char    output[21];
+
+    if (!des_initialised)
+        des_init();
+
+    /*
+     * Copy the key, shifting each character up by one bit
+     * and padding with zeros.
+     */
+    q = (unsigned char *) keybuf;
+    while ((q - (unsigned char *) keybuf) < sizeof(keybuf)) {
+        if ((*q++ = *key << 1))
+            key++;
+    }
+    if (des_setkey((unsigned char *) keybuf))
+        return(NULL);
+
+    if (*setting == _PASSWORD_EFMT1) {
+        /*
+         * "new"-style:
+         *  setting - underscore, 4 bytes of count, 4 bytes of salt
+         *  key - unlimited characters
+         */
+        for (i = 1, count = 0; i < 5; i++)
+            count |= ascii_to_bin(setting[i]) << (i - 1) * 6;
+
+        for (i = 5, salt = 0; i < 9; i++)
+            salt |= ascii_to_bin(setting[i]) << (i - 5) * 6;
+
+        while (*key) {
+            /*
+             * Encrypt the key with itself.
+             */
+            if (des_cipher((unsigned char*)keybuf, (unsigned char*)keybuf, 0, 1))
+                return(NULL);
+            /*
+             * And XOR with the next 8 characters of the key.
+             */
+            q = (unsigned char *) keybuf;
+            while (((q - (unsigned char *) keybuf) < sizeof(keybuf)) &&
+                    *key)
+                *q++ ^= *key++ << 1;
+
+            if (des_setkey((unsigned char *) keybuf))
+                return(NULL);
+        }
+        strncpy((char *)output, setting, 9);
+
+        /*
+         * Double check that we weren't given a short setting.
+         * If we were, the above code will probably have created
+         * wierd values for count and salt, but we don't really care.
+         * Just make sure the output string doesn't have an extra
+         * NUL in it.
+         */
+        output[9] = '\0';
+        p = output + strlen((const char *)output);
+    } else {
+        /*
+         * "old"-style:
+         *  setting - 2 bytes of salt
+         *  key - up to 8 characters
+         */
+        count = 25;
+
+        salt = (ascii_to_bin(setting[1]) << 6)
+             |  ascii_to_bin(setting[0]);
+
+        output[0] = setting[0];
+        /*
+         * If the encrypted password that the salt was extracted from
+         * is only 1 character long, the salt will be corrupted.  We
+         * need to ensure that the output string doesn't have an extra
+         * NUL in it!
+         */
+        output[1] = setting[1] ? setting[1] : output[0];
+
+        p = output + 2;
+    }
+    setup_salt(salt);
+    /*
+     * Do it.
+     */
+    if (do_des(0, 0, &r0, &r1, count))
+        return(NULL);
+    /*
+     * Now encode the result...
+     */
+    l = (r0 >> 8);
+    *p++ = ascii64[(l >> 18) & 0x3f];
+    *p++ = ascii64[(l >> 12) & 0x3f];
+    *p++ = ascii64[(l >> 6) & 0x3f];
+    *p++ = ascii64[l & 0x3f];
+
+    l = (r0 << 16) | ((r1 >> 16) & 0xffff);
+    *p++ = ascii64[(l >> 18) & 0x3f];
+    *p++ = ascii64[(l >> 12) & 0x3f];
+    *p++ = ascii64[(l >> 6) & 0x3f];
+    *p++ = ascii64[l & 0x3f];
+
+    l = r1 << 2;
+    *p++ = ascii64[(l >> 12) & 0x3f];
+    *p++ = ascii64[(l >> 6) & 0x3f];
+    *p++ = ascii64[l & 0x3f];
+    *p = 0;
+
+    return((char *)output);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xrogue/xrogue.sln	Tue Apr 21 08:55:20 2015 -0400
@@ -0,0 +1,21 @@
+Microsoft Visual Studio Solution File, Format Version 7.00
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "xrogue", "xrogue.vcproj", "{ABD49D61-EFA9-41BA-9EA1-8DE4B4FA4FF6}"
+EndProject
+Global
+	GlobalSection(SolutionConfiguration) = preSolution
+		ConfigName.0 = Debug
+		ConfigName.1 = Release
+	EndGlobalSection
+	GlobalSection(ProjectDependencies) = postSolution
+	EndGlobalSection
+	GlobalSection(ProjectConfiguration) = postSolution
+		{ABD49D61-EFA9-41BA-9EA1-8DE4B4FA4FF6}.Debug.ActiveCfg = Debug|Win32
+		{ABD49D61-EFA9-41BA-9EA1-8DE4B4FA4FF6}.Debug.Build.0 = Debug|Win32
+		{ABD49D61-EFA9-41BA-9EA1-8DE4B4FA4FF6}.Release.ActiveCfg = Release|Win32
+		{ABD49D61-EFA9-41BA-9EA1-8DE4B4FA4FF6}.Release.Build.0 = Release|Win32
+	EndGlobalSection
+	GlobalSection(ExtensibilityGlobals) = postSolution
+	EndGlobalSection
+	GlobalSection(ExtensibilityAddIns) = postSolution
+	EndGlobalSection
+EndGlobal
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xrogue/xrogue.vcproj	Tue Apr 21 08:55:20 2015 -0400
@@ -0,0 +1,278 @@
+<?xml version="1.0" encoding = "Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="7.00"
+	Name="xrogue"
+	ProjectGUID="{ABD49D61-EFA9-41BA-9EA1-8DE4B4FA4FF6}"
+	Keyword="Win32Proj">
+	<Platforms>
+		<Platform
+			Name="Win32"/>
+	</Platforms>
+	<Configurations>
+		<Configuration
+			Name="Debug|Win32"
+			OutputDirectory="Debug"
+			IntermediateDirectory="Debug"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				InlineFunctionExpansion="0"
+				OptimizeForWindowsApplication="TRUE"
+				AdditionalIncludeDirectories=".."
+				PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;PDC_STATIC_BUILD"
+				StringPooling="TRUE"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				SmallerTypeCheck="TRUE"
+				RuntimeLibrary="5"
+				BufferSecurityCheck="TRUE"
+				EnableFunctionLevelLinking="TRUE"
+				DisableLanguageExtensions="FALSE"
+				ForceConformanceInForLoopScope="TRUE"
+				UsePrecompiledHeader="0"
+				BrowseInformation="1"
+				WarningLevel="4"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"
+				CompileAs="1"
+				DisableSpecificWarnings="4033;4716;4013;4131;4244;4201"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="Ws2_32.lib pdcurses.lib"
+				OutputFile="$(OutDir)/xrogue.exe"
+				LinkIncremental="2"
+				SuppressStartupBanner="TRUE"
+				AdditionalLibraryDirectories=".."
+				IgnoreAllDefaultLibraries="FALSE"
+				IgnoreDefaultLibraryNames="LIBC.LIB"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/xrogue.pdb"
+				SubSystem="1"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+		</Configuration>
+		<Configuration
+			Name="Release|Win32"
+			OutputDirectory="Release"
+			IntermediateDirectory="Release"
+			ConfigurationType="1"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="2"
+				InlineFunctionExpansion="1"
+				OmitFramePointers="TRUE"
+				PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS"
+				StringPooling="TRUE"
+				RuntimeLibrary="4"
+				EnableFunctionLevelLinking="TRUE"
+				UsePrecompiledHeader="3"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="3"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				OutputFile="$(OutDir)/xrogue.exe"
+				LinkIncremental="1"
+				GenerateDebugInformation="TRUE"
+				SubSystem="2"
+				OptimizeReferences="2"
+				EnableCOMDATFolding="2"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+		</Configuration>
+	</Configurations>
+	<Files>
+		<Filter
+			Name="Source Files"
+			Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm">
+			<File
+				RelativePath="actions.c">
+			</File>
+			<File
+				RelativePath="bolt.c">
+			</File>
+			<File
+				RelativePath="chase.c">
+			</File>
+			<File
+				RelativePath="command.c">
+			</File>
+			<File
+				RelativePath="daemon.c">
+			</File>
+			<File
+				RelativePath="daemons.c">
+			</File>
+			<File
+				RelativePath="eat.c">
+			</File>
+			<File
+				RelativePath="effects.c">
+			</File>
+			<File
+				RelativePath="encumb.c">
+			</File>
+			<File
+				RelativePath="fight.c">
+			</File>
+			<File
+				RelativePath="help.c">
+			</File>
+			<File
+				RelativePath="init.c">
+			</File>
+			<File
+				RelativePath="io.c">
+			</File>
+			<File
+				RelativePath="list.c">
+			</File>
+			<File
+				RelativePath="main.c">
+			</File>
+			<File
+				RelativePath="maze.c">
+			</File>
+			<File
+				RelativePath="misc.c">
+			</File>
+			<File
+				RelativePath="mons_def.c">
+			</File>
+			<File
+				RelativePath="monsters.c">
+			</File>
+			<File
+				RelativePath="move.c">
+			</File>
+			<File
+				RelativePath="n_level.c">
+			</File>
+			<File
+				RelativePath="options.c">
+			</File>
+			<File
+				RelativePath="outside.c">
+			</File>
+			<File
+				RelativePath="pack.c">
+			</File>
+			<File
+				RelativePath="passages.c">
+			</File>
+			<File
+				RelativePath="player.c">
+			</File>
+			<File
+				RelativePath="potions.c">
+			</File>
+			<File
+				RelativePath="rings.c">
+			</File>
+			<File
+				RelativePath="rip.c">
+			</File>
+			<File
+				RelativePath="rogue.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="trader.c">
+			</File>
+			<File
+				RelativePath="util.c">
+			</File>
+			<File
+				RelativePath="vers.c">
+			</File>
+			<File
+				RelativePath="weapons.c">
+			</File>
+			<File
+				RelativePath="wear.c">
+			</File>
+			<File
+				RelativePath="wizard.c">
+			</File>
+			<File
+				RelativePath="xcrypt.c">
+			</File>
+		</Filter>
+		<Filter
+			Name="Header Files"
+			Filter="h;hpp;hxx;hm;inl;inc">
+			<File
+				RelativePath="mach_dep.h">
+			</File>
+			<File
+				RelativePath="network.h">
+			</File>
+			<File
+				RelativePath="rogue.h">
+			</File>
+		</Filter>
+		<Filter
+			Name="Resource Files"
+			Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe">
+		</Filter>
+		<File
+			RelativePath="LICENSE.TXT">
+		</File>
+		<File
+			RelativePath="Makefile">
+		</File>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>