diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/dat/Arch.des nethack/dat/Arch.des
--- nh_orig/dat/Arch.des	2003-12-07 18:39:12.000000000 -0500
+++ nethack/dat/Arch.des	2010-04-29 10:53:24.165721489 -0400
@@ -9,6 +9,8 @@
 #	and receive your quest assignment.
 #
-MAZE: "Arc-strt",' '
-FLAGS: noteleport,hardfloor
+LEVEL: "Arc-strt"
+FLAGS: noteleport,hardfloor,mazelevel
+INIT_MAP:solidfill,' '
+MON_GENERATION:86%, (80,'S'), (16,"human mummy"), (4,'M')
 GEOMETRY:center,center
 MAP
@@ -23,5 +25,5 @@
 ....................}|.|...............|.......+.|.......|}.................
 ....................}|.|...............---------.---------}.................
-....................}|.S.\.............+.................+..................
+....................}|.S...............+.................+..................
 ....................}|.|...............---------.---------}.................
 ....................}|.|...............|.......+.|.......|}.................
@@ -69,23 +71,46 @@
 DOOR:locked,(49,14)
 # Lord Carnarvon
-MONSTER:'@',"Lord Carnarvon",(25,10)
+OBJECT:('\',"throne"),(25,10)
+MONSTER:('@',"Lord Carnarvon"),(25,10) {
+  OBJECT:('[',"fedora"),+5
+  OBJECT:')',+4
+  OBJECT:random
+  OBJECT:random
+  OBJECT:random
+}
 # The treasure of Lord Carnarvon
-OBJECT:'(',"chest",(25,10)
+OBJECT:('(',"chest"),(25,10)
 # student guards for the audience chamber
-MONSTER:'@',"student",(26,09)
-MONSTER:'@',"student",(27,09)
-MONSTER:'@',"student",(28,09)
-MONSTER:'@',"student",(26,10)
-MONSTER:'@',"student",(28,10)
-MONSTER:'@',"student",(26,11)
-MONSTER:'@',"student",(27,11)
-MONSTER:'@',"student",(28,11)
+MONSTER:('@',"student"),(26,09) {
+  OBJECT:random
+}
+MONSTER:('@',"student"),(27,09) {
+  OBJECT:random
+}
+MONSTER:('@',"student"),(28,09) {
+  OBJECT:random
+}
+MONSTER:('@',"student"),(26,10) {
+  OBJECT:random
+}
+MONSTER:('@',"student"),(28,10) {
+  OBJECT:random
+}
+MONSTER:('@',"student"),(26,11) {
+  OBJECT:random
+}
+MONSTER:('@',"student"),(27,11) {
+  OBJECT:random
+}
+MONSTER:('@',"student"),(28,11) {
+  OBJECT:random
+}
 # city watch guards in the antechambers
-MONSTER:'@',"watchman",(50,06)
-MONSTER:'@',"watchman",(50,14)
+MONSTER:('@',"watchman"),(50,06)
+MONSTER:('@',"watchman"),(50,14)
 # Eels in the moat
-MONSTER:';',"giant eel",(20,10)
-MONSTER:';',"giant eel",(45,04)
-MONSTER:';',"giant eel",(33,16)
+MONSTER:(';',"giant eel"),(20,10)
+MONSTER:(';',"giant eel"),(45,04)
+MONSTER:(';',"giant eel"),(33,16)
 # Non diggable walls
 NON_DIGGABLE:(00,00,75,19)
@@ -98,16 +123,16 @@
 TRAP:random,random
 # Monsters on siege duty.
-MONSTER: 'S',random,(60,09)
-MONSTER: 'M',random,(60,10)
-MONSTER: 'S',random,(60,11)
-MONSTER: 'S',random,(60,12)
-MONSTER: 'M',random,(60,13)
-MONSTER: 'S',random,(61,10)
-MONSTER: 'S',random,(61,11)
-MONSTER: 'S',random,(61,12)
-MONSTER: 'S',random,(30,03)
-MONSTER: 'M',random,(20,17)
-MONSTER: 'S',random,(67,02)
-MONSTER: 'S',random,(10,19)
+MONSTER: 'S',(60,09)
+MONSTER: 'M',(60,10)
+MONSTER: 'S',(60,11)
+MONSTER: 'S',(60,12)
+MONSTER: 'M',(60,13)
+MONSTER: 'S',(61,10)
+MONSTER: 'S',(61,11)
+MONSTER: 'S',(61,12)
+MONSTER: 'S',(30,03)
+MONSTER: 'M',(20,17)
+MONSTER: 'S',(67,02)
+MONSTER: 'S',(10,19)
 
 #
@@ -118,6 +143,8 @@
 #
 
-MAZE: "Arc-loca",' '
-FLAGS: hardfloor
+LEVEL: "Arc-loca"
+FLAGS: hardfloor,mazelevel
+INIT_MAP:solidfill,' '
+MON_GENERATION:86%, (80,'S'), (16,"human mummy"), (4,'M')
 GEOMETRY:center,center
 MAP
@@ -185,19 +212,19 @@
 NON_DIGGABLE:(00,00,75,19)
 # Objects
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
+OBJECT:random,random
+OBJECT:random,random
+OBJECT:random,random
+OBJECT:random,random
+OBJECT:random,random
+OBJECT:random,random
+OBJECT:random,random
+OBJECT:random,random
+OBJECT:random,random
+OBJECT:random,random
+OBJECT:random,random
+OBJECT:random,random
+OBJECT:random,random
+OBJECT:random,random
+OBJECT:random,random
 # Treasure?
 ENGRAVING:random,engrave,"X marks the spot."
@@ -230,31 +257,31 @@
 TRAP:"rolling boulder",(40,16)
 # Random monsters.
-MONSTER:'S',random,random
-MONSTER:'S',random,random
-MONSTER:'S',random,random
-MONSTER:'S',random,random
-MONSTER:'S',random,random
-MONSTER:'S',random,random
-MONSTER:'S',random,random
-MONSTER:'S',random,random
-MONSTER:'S',random,random
-MONSTER:'S',random,random
-MONSTER:'S',random,random
-MONSTER:'S',random,random
-MONSTER:'S',random,random
-MONSTER:'S',random,random
-MONSTER:'S',random,random
-MONSTER:'S',random,random
-MONSTER:'S',random,random
-MONSTER:'S',random,random
-MONSTER:'M',random,random
-MONSTER:'M',"human mummy",random
-MONSTER:'M',"human mummy",random
-MONSTER:'M',"human mummy",random
-MONSTER:'M',"human mummy",random
-MONSTER:'M',"human mummy",random
-MONSTER:'M',"human mummy",random
-MONSTER:'M',"human mummy",random
-MONSTER:'M',random,random
+MONSTER:'S',random
+MONSTER:'S',random
+MONSTER:'S',random
+MONSTER:'S',random
+MONSTER:'S',random
+MONSTER:'S',random
+MONSTER:'S',random
+MONSTER:'S',random
+MONSTER:'S',random
+MONSTER:'S',random
+MONSTER:'S',random
+MONSTER:'S',random
+MONSTER:'S',random
+MONSTER:'S',random
+MONSTER:'S',random
+MONSTER:'S',random
+MONSTER:'S',random
+MONSTER:'S',random
+MONSTER:'M',random
+MONSTER:('M',"human mummy"),random
+MONSTER:('M',"human mummy"),random
+MONSTER:('M',"human mummy"),random
+MONSTER:('M',"human mummy"),random
+MONSTER:('M',"human mummy"),random
+MONSTER:('M',"human mummy"),random
+MONSTER:('M',"human mummy"),random
+MONSTER:'M',random
 
 #
@@ -266,5 +293,8 @@
 #
 
-MAZE: "Arc-goal", ' '
+LEVEL: "Arc-goal"
+FLAGS:mazelevel
+INIT_MAP:solidfill,' '
+MON_GENERATION:86%, (80,'S'), (16,"human mummy"), (4,'M')
 GEOMETRY:center,center
 MAP
@@ -322,19 +352,19 @@
 ALTAR:(50,14),chaos,altar
 # Objects
-OBJECT:'(',"crystal ball",(50,14),blessed,5,"The Orb of Detection"
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
+OBJECT:('(',"crystal ball"),(50,14),blessed,5,NAME:"The Orb of Detection"
+OBJECT:random,random
+OBJECT:random,random
+OBJECT:random,random
+OBJECT:random,random
+OBJECT:random,random
+OBJECT:random,random
+OBJECT:random,random
+OBJECT:random,random
+OBJECT:random,random
+OBJECT:random,random
+OBJECT:random,random
+OBJECT:random,random
+OBJECT:random,random
+OBJECT:random,random
 # Random traps
 TRAP:random,random
@@ -346,32 +376,37 @@
 TRAP:"rolling boulder",(46,14)
 # Random monsters.
-MONSTER:'&',"Minion of Huhetotl",(50,14)
-MONSTER:'S',random,random
-MONSTER:'S',random,random
-MONSTER:'S',random,random
-MONSTER:'S',random,random
-MONSTER:'S',random,random
-MONSTER:'S',random,random
-MONSTER:'S',random,random
-MONSTER:'S',random,random
-MONSTER:'S',random,random
-MONSTER:'S',random,random
-MONSTER:'S',random,random
-MONSTER:'S',random,random
-MONSTER:'S',random,random
-MONSTER:'S',random,random
-MONSTER:'S',random,random
-MONSTER:'S',random,random
-MONSTER:'S',random,random
-MONSTER:'S',random,random
-MONSTER:'M',"human mummy",random
-MONSTER:'M',"human mummy",random
-MONSTER:'M',"human mummy",random
-MONSTER:'M',"human mummy",random
-MONSTER:'M',"human mummy",random
-MONSTER:'M',"human mummy",random
-MONSTER:'M',"human mummy",random
-MONSTER:'M',"human mummy",random
-MONSTER:'M',random,random
+MONSTER:('&',"Minion of Huhetotl"),(50,14) {
+  OBJECT:('(', "Bell of Opening"),uncursed
+  OBJECT:random,cursed
+  OBJECT:random,cursed
+  OBJECT:random,cursed
+}
+MONSTER:'S',random
+MONSTER:'S',random
+MONSTER:'S',random
+MONSTER:'S',random
+MONSTER:'S',random
+MONSTER:'S',random
+MONSTER:'S',random
+MONSTER:'S',random
+MONSTER:'S',random
+MONSTER:'S',random
+MONSTER:'S',random
+MONSTER:'S',random
+MONSTER:'S',random
+MONSTER:'S',random
+MONSTER:'S',random
+MONSTER:'S',random
+MONSTER:'S',random
+MONSTER:'S',random
+MONSTER:('M',"human mummy"),random
+MONSTER:('M',"human mummy"),random
+MONSTER:('M',"human mummy"),random
+MONSTER:('M',"human mummy"),random
+MONSTER:('M',"human mummy"),random
+MONSTER:('M',"human mummy"),random
+MONSTER:('M',"human mummy"),random
+MONSTER:('M',"human mummy"),random
+MONSTER:'M',random
 
 #
@@ -385,76 +420,102 @@
 
 LEVEL: "Arc-fila"
+MON_GENERATION:86%, (80,'S'), (16,"human mummy"), (4,'M')
 #
 ROOM: "ordinary" , random, random, random, random
+{
 STAIR: random, up
-OBJECT: random,random,random
-MONSTER: 'S', random, random
+OBJECT: random,random
+MONSTER: 'S', random
+}
 
 ROOM: "ordinary" , random, random, random, random
-OBJECT: random, random, random
-OBJECT: random,random,random
-MONSTER: 'S', random, random
+{
+OBJECT: random, random
+OBJECT: random, random
+MONSTER: 'S', random
+}
 
 ROOM: "ordinary" , random, random, random, random
-OBJECT: random, random, random
+{
+OBJECT: random, random
 TRAP: random, random
-OBJECT: random,random,random
-MONSTER: 'S', random, random
+OBJECT: random, random
+MONSTER: 'S', random
+}
 
 ROOM: "ordinary" , random, random, random, random
+{
 STAIR: random, down
-OBJECT: random, random, random
+OBJECT: random, random
 TRAP: random, random
-MONSTER: 'S', random, random
-MONSTER: 'M', "human mummy", random
+MONSTER: 'S', random
+MONSTER: ('M', "human mummy"), random
+}
 
 ROOM: "ordinary" , random, random, random, random
-OBJECT: random, random, random
-OBJECT: random, random, random
+{
+OBJECT: random, random
+OBJECT: random, random
 TRAP: random, random
-MONSTER: 'S', random, random
+MONSTER: 'S', random
+}
 
 ROOM: "ordinary" , random, random, random, random
-OBJECT: random, random, random
+{
+OBJECT: random, random
 TRAP: random, random
-MONSTER: 'S', random, random
+MONSTER: 'S', random
+}
 
 RANDOM_CORRIDORS
 
 LEVEL: "Arc-filb"
+MON_GENERATION:86%, (80,'S'), (16,"human mummy"), (4,'M')
 #
 ROOM: "ordinary" , random, random, random, random
+{
 STAIR: random, up
-OBJECT: random,random,random
-MONSTER: 'M', random, random
+OBJECT: random,random
+MONSTER: 'M', random
+}
 
 ROOM: "ordinary" , random, random, random, random
-OBJECT: random, random, random
-OBJECT: random,random,random
-MONSTER: 'M', random, random
+{
+OBJECT: random, random
+OBJECT: random, random
+MONSTER: 'M', random
+}
 
 ROOM: "ordinary" , random, random, random, random
-OBJECT: random, random, random
+{
+OBJECT: random, random
 TRAP: random, random
-OBJECT: random,random,random
-MONSTER: 'M', random, random
+OBJECT: random,random
+MONSTER: 'M', random
+}
 
 ROOM: "ordinary" , random, random, random, random
+{
 STAIR: random, down
-OBJECT: random, random, random
+OBJECT: random, random
 TRAP: random, random
-MONSTER: 'S', random, random
-MONSTER: 'M', "human mummy", random
+MONSTER: 'S', random
+MONSTER: ('M', "human mummy"), random
+}
 
 ROOM: "ordinary" , random, random, random, random
-OBJECT: random, random, random
-OBJECT: random, random, random
+{
+OBJECT: random, random
+OBJECT: random, random
 TRAP: random, random
-MONSTER: 'S', random, random
+MONSTER: 'S', random
+}
 
 ROOM: "ordinary" , random, random, random, random
-OBJECT: random, random, random
+{
+OBJECT: random, random
 TRAP: random, random
-MONSTER: 'S', random, random
+MONSTER: 'S', random
+}
 
 RANDOM_CORRIDORS
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/dat/Barb.des nethack/dat/Barb.des
--- nh_orig/dat/Barb.des	2003-12-07 18:39:12.000000000 -0500
+++ nethack/dat/Barb.des	2010-08-16 13:20:13.632708508 -0400
@@ -9,6 +9,8 @@
 #	and receive your quest assignment.
 #
-MAZE: "Bar-strt",' '
-FLAGS: noteleport,hardfloor
+LEVEL: "Bar-strt"
+FLAGS: noteleport,hardfloor,mazelevel
+INIT_MAP:solidfill,' '
+MON_GENERATION:86%, (64,"ogre"), (16,'O'), (16,"troll"), (4,'T')
 GEOMETRY:center,center
 MAP
@@ -19,7 +21,7 @@
 ........--------------......-----....PPP....................................
 ........|...S........|......+...|...PPP.....................................
-........|----........|......|...|....PP.....................................
-........|.\..........+......-----...........................................
-........|----........|...............PP.....................................
+........|----........|......|...|...PPP.....................................
+........|............+......-----....PP.....................................
+........|----........|..............PPP.....................................
 ........|...S........|...-----.......PPP....................................
 ........--------------...+...|......PPPPP...................................
@@ -34,4 +36,13 @@
 ....................................PP....PP................................
 ENDMAP
+
+# the forest beyond the river
+REPLACE_TERRAIN:(37,0,75,19),'.','T', 10%
+REPLACE_TERRAIN:(60,0,75,19),'.','T', 20%
+REPLACE_TERRAIN:(65,0,75,19),'.','T', 40%
+REPLACE_TERRAIN:(70,0,75,19),'.','T', 80%
+TERRAIN: (randline (37,7)-(62,02),7), '.'
+TERRAIN:(62,02),'.'
+
 # Dungeon Description
 REGION:(00,00,75,19),lit,"ordinary"
@@ -59,36 +70,61 @@
 DOOR:open,(28,05)
 # Elder
-MONSTER:'@',"Pelias",(10,07)
+OBJECT:('\',"throne"),(10,07)
+MONSTER:('@',"Pelias"),(10,07) {
+  OBJECT:(')',"runesword"),1d5
+  OBJECT:'[',1d5
+}
 # The treasure of Pelias
-OBJECT:'(',"chest",(09,05)
+OBJECT:('(',"chest"),(09,05)
 # chieftain guards for the audience chamber
-MONSTER:'@',"chieftain",(10,05)
-MONSTER:'@',"chieftain",(10,09)
-MONSTER:'@',"chieftain",(11,05)
-MONSTER:'@',"chieftain",(11,09)
-MONSTER:'@',"chieftain",(14,05)
-MONSTER:'@',"chieftain",(14,09)
-MONSTER:'@',"chieftain",(16,05)
-MONSTER:'@',"chieftain",(16,09)
+MONSTER:('@',"chieftain"),(10,05) {
+  OBJECT:')'
+  OBJECT:'['
+}
+MONSTER:('@',"chieftain"),(10,09) {
+  OBJECT:')'
+  OBJECT:'['
+}
+MONSTER:('@',"chieftain"),(11,05) {
+  OBJECT:')'
+  OBJECT:'['
+}
+MONSTER:('@',"chieftain"),(11,09) {
+  OBJECT:')'
+  OBJECT:'['
+}
+MONSTER:('@',"chieftain"),(14,05) {
+  OBJECT:')'
+  OBJECT:'['
+}
+MONSTER:('@',"chieftain"),(14,09) {
+  OBJECT:')'
+  OBJECT:'['
+}
+MONSTER:('@',"chieftain"),(16,05) {
+  OBJECT:')'
+  OBJECT:'['
+}
+MONSTER:('@',"chieftain"),(16,09) {
+  OBJECT:')'
+  OBJECT:'['
+}
 # Non diggable walls
-NON_DIGGABLE:(00,00,75,19)
+NON_DIGGABLE:(00,00,35,19)
 # One trap to keep the ogres at bay.
 TRAP:"spiked pit",(37,07)
 # Eels in the river
-MONSTER:';',"giant eel",(36,01)
-MONSTER:';',"giant eel",(37,09)
-MONSTER:';',"giant eel",(39,15)
+MONSTER:(';',"giant eel"),(36,01)
+MONSTER:(';',"giant eel"),(37,09)
+MONSTER:(';',"giant eel"),(39,15)
 # Monsters on siege duty.
-MONSTER:'O',"ogre",(40,08),hostile
-MONSTER:'O',"ogre",(41,06),hostile
-MONSTER:'O',"ogre",(41,07),hostile
-MONSTER:'O',"ogre",(41,08),hostile
-MONSTER:'O',"ogre",(41,09),hostile
-MONSTER:'O',"ogre",(41,10),hostile
-MONSTER:'O',"ogre",(42,06),hostile
-MONSTER:'O',"ogre",(42,07),hostile
-MONSTER:'O',"ogre",(42,08),hostile
-MONSTER:'O',"ogre",(42,09),hostile
-MONSTER:'O',"ogre",(42,10),hostile
+REGION:(40,0,50,19),lit,"ordinary",unfilled {
+  LOOP [10 + 1d15] {
+    MONSTER:('O',"ogre"),random,hostile
+  }
+}
+
+# to cut down the trees
+OBJECT:"axe",random,eroded:1d3
 
 #
@@ -99,6 +135,8 @@
 #
 
-MAZE: "Bar-loca",' '
-FLAGS: hardfloor
+LEVEL: "Bar-loca"
+FLAGS: hardfloor,mazelevel
+INIT_MAP:solidfill,' '
+MON_GENERATION:86%, (64,"ogre"), (16,'O'), (16,"troll"), (4,'T')
 GEOMETRY:center,center
 MAP
@@ -147,19 +185,19 @@
 STAIR:(70,13),down
 # Objects
-OBJECT:random,random,(42,03)
-OBJECT:random,random,(42,03)
-OBJECT:random,random,(42,03)
-OBJECT:random,random,(41,03)
-OBJECT:random,random,(41,03)
-OBJECT:random,random,(41,03)
-OBJECT:random,random,(41,03)
-OBJECT:random,random,(41,08)
-OBJECT:random,random,(41,08)
-OBJECT:random,random,(42,08)
-OBJECT:random,random,(42,08)
-OBJECT:random,random,(42,08)
-OBJECT:random,random,(71,13)
-OBJECT:random,random,(71,13)
-OBJECT:random,random,(71,13)
+OBJECT:random,(42,03)
+OBJECT:random,(42,03)
+OBJECT:random,(42,03)
+OBJECT:random,(41,03)
+OBJECT:random,(41,03)
+OBJECT:random,(41,03)
+OBJECT:random,(41,03)
+OBJECT:random,(41,08)
+OBJECT:random,(41,08)
+OBJECT:random,(42,08)
+OBJECT:random,(42,08)
+OBJECT:random,(42,08)
+OBJECT:random,(71,13)
+OBJECT:random,(71,13)
+OBJECT:random,(71,13)
 # Random traps
 TRAP:"spiked pit",(10,13)
@@ -172,31 +210,31 @@
 TRAP:random,random
 # Random monsters.
-MONSTER:'O',"ogre",(12,09),hostile
-MONSTER:'O',"ogre",(18,11),hostile
-MONSTER:'O',"ogre",(45,05),hostile
-MONSTER:'O',"ogre",(45,06),hostile
-MONSTER:'O',"ogre",(47,05),hostile
-MONSTER:'O',"ogre",(46,05),hostile
-MONSTER:'O',"ogre",(56,03),hostile
-MONSTER:'O',"ogre",(56,04),hostile
-MONSTER:'O',"ogre",(56,05),hostile
-MONSTER:'O',"ogre",(56,06),hostile
-MONSTER:'O',"ogre",(57,03),hostile
-MONSTER:'O',"ogre",(57,04),hostile
-MONSTER:'O',"ogre",(57,05),hostile
-MONSTER:'O',"ogre",(57,06),hostile
-MONSTER:'O',"ogre",random,hostile
-MONSTER:'O',"ogre",random,hostile
-MONSTER:'O',"ogre",random,hostile
-MONSTER:'O',random,random,hostile
-MONSTER:'T',random,random,hostile
-MONSTER:'T',"rock troll",(46,06),hostile
-MONSTER:'T',"rock troll",(47,06),hostile
-MONSTER:'T',"rock troll",(56,07),hostile
-MONSTER:'T',"rock troll",(57,07),hostile
-MONSTER:'T',"rock troll",(70,13),hostile
-MONSTER:'T',"rock troll",random,hostile
-MONSTER:'T',"rock troll",random,hostile
-MONSTER:'T',random,random,hostile
+MONSTER:('O',"ogre"),(12,09),hostile
+MONSTER:('O',"ogre"),(18,11),hostile
+MONSTER:('O',"ogre"),(45,05),hostile
+MONSTER:('O',"ogre"),(45,06),hostile
+MONSTER:('O',"ogre"),(47,05),hostile
+MONSTER:('O',"ogre"),(46,05),hostile
+REGION:(56,03,57,04),unlit,"ordinary",unfilled,true {
+  LOOP [5 + 2d6] {
+    MONSTER:('O',"ogre"),random,hostile
+  }
+}
+
+LOOP [1d8 + 2] {
+  MONSTER:('O',"ogre"),random,hostile
+}
+MONSTER:'O',random,hostile
+MONSTER:'T',random,hostile
+REGION:(46,06,47,07),unlit,"ordinary",unfilled,true {
+  LOOP [1d8 + 2] {
+    MONSTER:('T',"rock troll"),random,hostile
+  }
+}
+
+LOOP [2 + 1d6] {
+  MONSTER:('T',"rock troll"),random,hostile
+}
+MONSTER:'T',random,hostile
 
 #
@@ -208,5 +246,8 @@
 #
 
-MAZE: "Bar-goal", ' '
+LEVEL: "Bar-goal"
+FLAGS:mazelevel
+INIT_MAP:solidfill,' '
+MON_GENERATION:86%, (64,"ogre"), (16,'O'), (16,"troll"), (4,'T')
 GEOMETRY:center,center
 MAP
@@ -243,55 +284,33 @@
 NON_DIGGABLE:(00,00,75,19)
 # Objects
-OBJECT:'*',"luckstone",(63,04),blessed,0,"The Heart of Ahriman"
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-# Random traps
-TRAP:random,random
-TRAP:random,random
-TRAP:random,random
-TRAP:random,random
-TRAP:random,random
+OBJECT:('*',"luckstone"),(63,04),blessed,0,NAME:"The Heart of Ahriman"
+#
+LOOP [5 + 2d6] {
+  OBJECT: random, random
+}
+#
+LOOP [5 + 1d6] {
 TRAP:random,random
+}
+#
 # Random monsters.
-MONSTER:'@',"Thoth Amon",(63,04),hostile
-MONSTER:'O',"ogre",random,hostile
-MONSTER:'O',"ogre",random,hostile
-MONSTER:'O',"ogre",random,hostile
-MONSTER:'O',"ogre",random,hostile
-MONSTER:'O',"ogre",random,hostile
-MONSTER:'O',"ogre",random,hostile
-MONSTER:'O',"ogre",random,hostile
-MONSTER:'O',"ogre",random,hostile
-MONSTER:'O',"ogre",random,hostile
-MONSTER:'O',"ogre",random,hostile
-MONSTER:'O',"ogre",random,hostile
-MONSTER:'O',"ogre",random,hostile
-MONSTER:'O',"ogre",random,hostile
-MONSTER:'O',"ogre",random,hostile
-MONSTER:'O',"ogre",random,hostile
-MONSTER:'O',"ogre",random,hostile
-MONSTER:'O',random,random,hostile
-MONSTER:'O',random,random,hostile
-MONSTER:'T',"rock troll",random,hostile
-MONSTER:'T',"rock troll",random,hostile
-MONSTER:'T',"rock troll",random,hostile
-MONSTER:'T',"rock troll",random,hostile
-MONSTER:'T',"rock troll",random,hostile
-MONSTER:'T',"rock troll",random,hostile
-MONSTER:'T',"rock troll",random,hostile
-MONSTER:'T',"rock troll",random,hostile
-MONSTER:'T',random,random,hostile
+MONSTER:('@',"Thoth Amon"),(63,04),hostile {
+  OBJECT:('(', "Bell of Opening"),uncursed
+  OBJECT:')',1d2
+  OBJECT:'['
+  OBJECT:random
+  OBJECT:random
+  OBJECT:random
+}
+
+LOOP [15 + 2d6] {
+  MONSTER:('O',"ogre"),random,hostile
+}
+MONSTER:'O',random,hostile
+MONSTER:'O',random,hostile
+LOOP [7 + 1d6] {
+  MONSTER:('T',"rock troll"),random,hostile
+}
+MONSTER:'T',random,hostile
 WALLIFY
 
@@ -305,6 +324,8 @@
 #
 
-MAZE: "Bar-fila" , ' '
-INIT_MAP: '.' , '.' , true , true , unlit , false
+LEVEL: "Bar-fila"
+FLAGS:mazelevel,noflip
+INIT_MAP: mines, '.' , '.' , true , true , unlit , false
+MON_GENERATION:86%, (64,"ogre"), (16,'O'), (16,"troll"), (4,'T')
 NOMAP
 #
@@ -312,25 +333,24 @@
 STAIR: random, down
 #
-OBJECT: random, random, random
-OBJECT: random, random, random
-OBJECT: random, random, random
-OBJECT: random, random, random
-OBJECT: random, random, random
-OBJECT: random, random, random
-OBJECT: random, random, random
-OBJECT: random, random, random
+LOOP [5 + 2d6] {
+  OBJECT: random, random
+}
 #
+LOOP [2 + 1d6] {
 TRAP: random, random
-TRAP: random, random
-TRAP: random, random
-TRAP: random, random
+}
 #
-MONSTER: 'O', "ogre", random, hostile
-MONSTER: 'O', "ogre", random, hostile
-MONSTER: 'O', random, random, hostile
-MONSTER: 'T', "rock troll", random, hostile
+LOOP [1d6] {
+  MONSTER: ('O', "ogre"), random, hostile
+}
+MONSTER: 'O', random, hostile
+LOOP [1d3] {
+  MONSTER: ('T', "rock troll"), random, hostile
+}
 
-MAZE: "Bar-filb" , ' '
-INIT_MAP: '.' , ' ' , true , true , unlit , true
+LEVEL: "Bar-filb"
+FLAGS:mazelevel,noflip
+INIT_MAP: mines, '.' , ' ' , true , true , unlit , true
+MON_GENERATION:86%, (64,"ogre"), (16,'O'), (16,"troll"), (4,'T')
 NOMAP
 #
@@ -338,31 +358,18 @@
 STAIR: random, down
 #
-OBJECT: random, random, random
-OBJECT: random, random, random
-OBJECT: random, random, random
-OBJECT: random, random, random
-OBJECT: random, random, random
-OBJECT: random, random, random
-OBJECT: random, random, random
-OBJECT: random, random, random
-OBJECT: random, random, random
-OBJECT: random, random, random
-OBJECT: random, random, random
+LOOP [5 + 2d6] {
+  OBJECT: random, random
+}
 #
+LOOP [2 + 1d6] {
 TRAP: random, random
-TRAP: random, random
-TRAP: random, random
-TRAP: random, random
+}
 #
-MONSTER: 'O', "ogre", random, hostile
-MONSTER: 'O', "ogre", random, hostile
-MONSTER: 'O', "ogre", random, hostile
-MONSTER: 'O', "ogre", random, hostile
-MONSTER: 'O', "ogre", random, hostile
-MONSTER: 'O', "ogre", random, hostile
-MONSTER: 'O', "ogre", random, hostile
-MONSTER: 'O', random , random, hostile
-MONSTER: 'T', "rock troll", random, hostile
-MONSTER: 'T', "rock troll", random, hostile
-MONSTER: 'T', "rock troll", random, hostile
-MONSTER: 'T', random , random, hostile
+LOOP [5 + 1d6] {
+  MONSTER: ('O', "ogre"), random, hostile
+}
+MONSTER: 'O', random, hostile
+LOOP [2 + 1d3] {
+  MONSTER: ('T', "rock troll"), random, hostile
+}
+MONSTER: 'T', random, hostile
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/dat/bigroom.des nethack/dat/bigroom.des
--- nh_orig/dat/bigroom.des	2003-12-07 18:39:12.000000000 -0500
+++ nethack/dat/bigroom.des	2010-05-13 09:22:22.244762620 -0400
@@ -7,5 +7,7 @@
 #
 
-MAZE:"bigrm-1",' '
+LEVEL:"bigrm-1"
+FLAGS:mazelevel
+INIT_MAP:solidfill,' '
 GEOMETRY:center,center
 MAP
@@ -29,4 +31,21 @@
 ---------------------------------------------------------------------------
 ENDMAP
+
+$terrains = TERRAIN:{'-', 'F', 'L', 'T', 'C'}
+SHUFFLE:$terrains
+
+IF [75%] {
+   TERRAIN:line (10,8)-(38, 8), $terrains[0]
+   TERRAIN:line (37,8)-(65, 8), $terrains[0]
+   TERRAIN:line (37,3)-(37, 8), $terrains[0]
+   TERRAIN:line (37,8)-(37,14), $terrains[0]
+} ELSE {
+   IF [99%] {
+      TERRAIN:rect (4,4,70,13), $terrains[0]
+      TERRAIN:line (25, 4)-(50, 4), '.'
+      TERRAIN:line (25,13)-(50,13), '.'
+   }
+}
+
 # Dungeon Description
 REGION:(01,01,73,16),lit,"ordinary"
@@ -37,59 +56,21 @@
 NON_DIGGABLE:(00,00,74,17)
 # Objects
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
+LOOP [15] {
+  OBJECT:random,random
+}
 # Random traps
+LOOP [6] {
 TRAP:random,random
-TRAP:random,random
-TRAP:random,random
-TRAP:random,random
-TRAP:random,random
-TRAP:random,random
+}
 # Random monsters.
-MONSTER:random,random,random
-MONSTER:random,random,random
-MONSTER:random,random,random
-MONSTER:random,random,random
-MONSTER:random,random,random
-MONSTER:random,random,random
-MONSTER:random,random,random
-MONSTER:random,random,random
-MONSTER:random,random,random
-MONSTER:random,random,random
-MONSTER:random,random,random
-MONSTER:random,random,random
-MONSTER:random,random,random
-MONSTER:random,random,random
-MONSTER:random,random,random
-MONSTER:random,random,random
-MONSTER:random,random,random
-MONSTER:random,random,random
-MONSTER:random,random,random
-MONSTER:random,random,random
-MONSTER:random,random,random
-MONSTER:random,random,random
-MONSTER:random,random,random
-MONSTER:random,random,random
-MONSTER:random,random,random
-MONSTER:random,random,random
-MONSTER:random,random,random
-MONSTER:random,random,random
+LOOP [28] {
+  MONSTER:random,random
+}
 
 #	Here, just play with the lighting...
 
-MAZE:"bigrm-2",' '
+LEVEL:"bigrm-2"
+FLAGS:mazelevel
+INIT_MAP:solidfill,' '
 GEOMETRY:center,center
 MAP
@@ -114,13 +95,30 @@
 ENDMAP
 # Dungeon Description
-REGION:(01,01,23,06),lit,"ordinary"
-REGION:(01,07,23,10),unlit,"ordinary"
-REGION:(01,11,23,16),lit,"ordinary"
-REGION:(24,01,50,06),unlit,"ordinary"
-REGION:(24,07,50,10),lit,"ordinary"
-REGION:(24,11,50,16),unlit,"ordinary"
-REGION:(51,01,73,06),lit,"ordinary"
-REGION:(51,07,73,10),unlit,"ordinary"
-REGION:(51,11,73,16),lit,"ordinary"
+REGION:(01,01,73,16),lit,"ordinary"
+
+IF [50%] {
+  REGION:(00,07,23,10),unlit,"ordinary"
+  REGION:(24,00,50,06),unlit,"ordinary"
+  REGION:(24,11,50,17),unlit,"ordinary"
+  REGION:(51,07,74,10),unlit,"ordinary"
+} ELSE {
+  REGION:(24,00,50,17),unlit,"ordinary"
+}
+
+IF [40%] {
+   $terrain = TERRAIN:{ 'L', '}', 'I' }
+   SHUFFLE:$terrain
+   TERRAIN: (randline random-random,20), $terrain[0]
+   IF [50%] {
+      TERRAIN: (randline random-random,25), $terrain[0]
+   }
+   IF [50%] {
+      TERRAIN: grow(north|west, randline random-random,25), $terrain[0]
+   }
+   IF [25%] {
+      TERRAIN: grow(randline random-random,25), $terrain[0]
+   }
+}
+
 # Stairs
 STAIR:random,up
@@ -129,59 +127,21 @@
 NON_DIGGABLE:(00,00,74,17)
 # Objects
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
+LOOP [15] {
+  OBJECT:random,random
+}
 # Random traps
+LOOP [6] {
 TRAP:random,random
-TRAP:random,random
-TRAP:random,random
-TRAP:random,random
-TRAP:random,random
-TRAP:random,random
+}
 # Random monsters.
-MONSTER:random,random,random
-MONSTER:random,random,random
-MONSTER:random,random,random
-MONSTER:random,random,random
-MONSTER:random,random,random
-MONSTER:random,random,random
-MONSTER:random,random,random
-MONSTER:random,random,random
-MONSTER:random,random,random
-MONSTER:random,random,random
-MONSTER:random,random,random
-MONSTER:random,random,random
-MONSTER:random,random,random
-MONSTER:random,random,random
-MONSTER:random,random,random
-MONSTER:random,random,random
-MONSTER:random,random,random
-MONSTER:random,random,random
-MONSTER:random,random,random
-MONSTER:random,random,random
-MONSTER:random,random,random
-MONSTER:random,random,random
-MONSTER:random,random,random
-MONSTER:random,random,random
-MONSTER:random,random,random
-MONSTER:random,random,random
-MONSTER:random,random,random
-MONSTER:random,random,random
+LOOP [28] {
+  MONSTER:random,random
+}
 
 #	Now, let's get fancy...
 
-MAZE:"bigrm-3",' '
+LEVEL:"bigrm-3"
+FLAGS:mazelevel
+INIT_MAP:solidfill,' '
 GEOMETRY:center,center
 MAP
@@ -205,4 +165,18 @@
 ---------------------------------------------------------------------------
 ENDMAP
+
+IF [30%] {
+   $outside = TERRAIN:{ 'L', 'T', '}', 'C' }
+   SHUFFLE: $outside
+   REPLACE_TERRAIN:(6,5, 68,11),'-',$outside[0],100%
+   REPLACE_TERRAIN:(6,5, 68,11),'|',$outside[0],100%
+   REPLACE_TERRAIN:(6,5, 68,11),' ',$outside[0],100%
+}
+
+IF [50%] {
+   REPLACE_TERRAIN:(1, 1, 73, 1),'|','F',100%
+   REPLACE_TERRAIN:(1,16, 73,16),'|','F',100%
+}
+
 # Dungeon Description
 REGION:(01,01,73,16),lit,"ordinary"
@@ -213,56 +187,44 @@
 NON_DIGGABLE:(00,00,74,17)
 # Objects
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
+LOOP [15] {
+  OBJECT:random,random
+}
 # Random traps
+LOOP [6] {
 TRAP:random,random
-TRAP:random,random
-TRAP:random,random
-TRAP:random,random
-TRAP:random,random
-TRAP:random,random
+}
 # Random monsters.
-MONSTER:random,random,(01,01)
-MONSTER:random,random,(13,01)
-MONSTER:random,random,(25,01)
-MONSTER:random,random,(37,01)
-MONSTER:random,random,(49,01)
-MONSTER:random,random,(61,01)
-MONSTER:random,random,(73,01)
-MONSTER:random,random,(07,07)
-MONSTER:random,random,(13,07)
-MONSTER:random,random,(25,07)
-MONSTER:random,random,(37,07)
-MONSTER:random,random,(49,07)
-MONSTER:random,random,(61,07)
-MONSTER:random,random,(67,07)
-MONSTER:random,random,(07,09)
-MONSTER:random,random,(13,09)
-MONSTER:random,random,(25,09)
-MONSTER:random,random,(37,09)
-MONSTER:random,random,(49,09)
-MONSTER:random,random,(61,09)
-MONSTER:random,random,(67,09)
-MONSTER:random,random,(01,16)
-MONSTER:random,random,(13,16)
-MONSTER:random,random,(25,16)
-MONSTER:random,random,(37,16)
-MONSTER:random,random,(49,16)
-MONSTER:random,random,(61,16)
-MONSTER:random,random,(73,16)
-MAZE:"bigrm-4",' '
+MONSTER:random,(01,01)
+MONSTER:random,(13,01)
+MONSTER:random,(25,01)
+MONSTER:random,(37,01)
+MONSTER:random,(49,01)
+MONSTER:random,(61,01)
+MONSTER:random,(73,01)
+MONSTER:random,(07,07)
+MONSTER:random,(13,07)
+MONSTER:random,(25,07)
+MONSTER:random,(37,07)
+MONSTER:random,(49,07)
+MONSTER:random,(61,07)
+MONSTER:random,(67,07)
+MONSTER:random,(07,09)
+MONSTER:random,(13,09)
+MONSTER:random,(25,09)
+MONSTER:random,(37,09)
+MONSTER:random,(49,09)
+MONSTER:random,(61,09)
+MONSTER:random,(67,09)
+MONSTER:random,(01,16)
+MONSTER:random,(13,16)
+MONSTER:random,(25,16)
+MONSTER:random,(37,16)
+MONSTER:random,(49,16)
+MONSTER:random,(61,16)
+MONSTER:random,(73,16)
+
+LEVEL:"bigrm-4"
+FLAGS:mazelevel
+INIT_MAP:solidfill,' '
 GEOMETRY:center,center
 MAP
@@ -286,4 +248,18 @@
 -----------                                                     -----------
 ENDMAP
+
+$corners = selection: (05,02) & (05,15) & (69,02) & (69,15)
+$terrain = TERRAIN:{ 'L', 'T', '{', '.' }
+SHUFFLE:$terrain
+TERRAIN:$corners, $terrain[0]
+
+IF [30%] {
+   $outside = TERRAIN:{ 'L', 'T', '}' }
+   SHUFFLE: $outside
+   REPLACE_TERRAIN:(0,0, 74,17),'-',$outside[0],100%
+   REPLACE_TERRAIN:(0,0, 74,17),'|',$outside[0],100%
+   REPLACE_TERRAIN:(0,0, 74,17),' ',$outside[0],100%
+}
+
 # Dungeon Description
 REGION:(01,01,73,16),lit,"ordinary"
@@ -293,65 +269,22 @@
 # Non diggable walls
 NON_DIGGABLE:(00,00,74,17)
-# Fountains
-FOUNTAIN:(05,02)
-FOUNTAIN:(05,15)
-FOUNTAIN:(69,02)
-FOUNTAIN:(69,15)
 # Objects
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
+LOOP [15] {
+  OBJECT:random,random
+}
 # Random traps
+LOOP [6] {
 TRAP:random,random
-TRAP:random,random
-TRAP:random,random
-TRAP:random,random
-TRAP:random,random
-TRAP:random,random
+}
 # Random monsters.
-MONSTER:random,random,random
-MONSTER:random,random,random
-MONSTER:random,random,random
-MONSTER:random,random,random
-MONSTER:random,random,random
-MONSTER:random,random,random
-MONSTER:random,random,random
-MONSTER:random,random,random
-MONSTER:random,random,random
-MONSTER:random,random,random
-MONSTER:random,random,random
-MONSTER:random,random,random
-MONSTER:random,random,random
-MONSTER:random,random,random
-MONSTER:random,random,random
-MONSTER:random,random,random
-MONSTER:random,random,random
-MONSTER:random,random,random
-MONSTER:random,random,random
-MONSTER:random,random,random
-MONSTER:random,random,random
-MONSTER:random,random,random
-MONSTER:random,random,random
-MONSTER:random,random,random
-MONSTER:random,random,random
-MONSTER:random,random,random
-MONSTER:random,random,random
-MONSTER:random,random,random
+LOOP [28] {
+  MONSTER:random,random
+}
 
 #	Try an oval room...
 
-MAZE:"bigrm-5",' '
+LEVEL:"bigrm-5"
+FLAGS:mazelevel
+INIT_MAP:solidfill,' '
 GEOMETRY:center,center
 MAP
@@ -378,4 +311,16 @@
 # Dungeon Description
 REGION:(00,00,72,18),lit,"ordinary"
+
+IF [33%] {
+   $terrain = TERRAIN:{ 'L', '}' }
+   SHUFFLE:$terrain
+   IF [50%] {
+      TERRAIN: grow(north|west, randline (37,0)-(37,18),20), $terrain[0]
+   } ELSE {
+      TERRAIN: grow(north|west, randline (0,10)-(73,10),20), $terrain[0]
+   }
+}
+
+
 # Stairs
 STAIR:random,up
@@ -383,54 +328,346 @@
 # Non diggable walls
 NON_DIGGABLE:(00,00,72,18)
-# Objects
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-# Random traps
+
+LOOP [15] {
+  OBJECT:random,random
+}
+
+LOOP [6] {
 TRAP:random,random
+}
+
+LOOP [28] {
+  MONSTER:random,random
+}
+
+
+# The Four Circles
+
+LEVEL:"bigrm-6"
+FLAGS:mazelevel
+INIT_MAP:solidfill,' '
+GEOMETRY:center,center
+MAP
+     ---------         ---------         ---------         ---------     
+   ---.......---     ---.......---     ---.......---     ---.......---   
+  --...........--   --...........--   --...........--   --...........--  
+ --.............-- --.............-- --.............-- --.............-- 
+ -...............- -...............- -...............- -...............- 
+|-...............---...............---...............---...............--
+|.................-.................-.................-.................|
+|........T.................T.................T.................T........|
+|.......................................................................|
+|......T.{.....................................................{.T......|
+|.......................................................................|
+|........T.................T.................T.................T........|
+|.................-.................-.................-.................|
+--...............---...............---...............---...............--
+ -...............- -...............- -...............- -...............- 
+ --.............-- --.............-- --.............-- --.............-- 
+  --...........--   --...........--   --...........--   --...........--  
+   ---.......---     ---.......---     ---.......---     ---.......---   
+     ---------         ---------         ---------         ---------     
+ENDMAP
+
+IF [20%] {
+  REPLACE_TERRAIN:(00,00,73,18),'T','{',100%
+}
+
+IF [20%] {
+  REPLACE_TERRAIN:(00,00,73,18),'-','T',100%
+  REPLACE_TERRAIN:(00,00,73,18),'|','T',100%
+}
+
+# Dungeon Description
+REGION:(01,01,72,17),lit,"ordinary"
+# Stairs
+STAIR:random,up
+STAIR:random,down
+# Non diggable walls
+NON_DIGGABLE:(00,00,72,18)
+
+LOOP [15] {
+  OBJECT:random,random
+}
+
+LOOP [6] {
 TRAP:random,random
+}
+
+LOOP [28] {
+  MONSTER:random,random
+}
+
+
+# Let's tilt it a bit
+
+LEVEL:"bigrm-7"
+FLAGS:mazelevel
+INIT_MAP:solidfill,' '
+GEOMETRY:center,center
+MAP
+                                                        -----              
+                                                ---------...---            
+                                        ---------.........L...---          
+                                ---------.......................---        
+                        ---------.................................---      
+                ---------...........................................---    
+        ---------.....................................................---  
+|--------...............................................................--|
+|.........................................................................|
+|.L.....................................................................L.|
+|.........................................................................|
+|--...............................................................--------|
+  ---.....................................................---------        
+    ---...........................................---------                
+      ---.................................---------                        
+        ---.......................---------                                
+          ---...L.........---------                                        
+            ---...---------                                                
+              -----                                                        
+ENDMAP
+
+$terrain = TERRAIN:{ 'L', 'T', '{', '.' }
+SHUFFLE:$terrain
+REPLACE_TERRAIN:(00,00,74,18),'L',$terrain[0],100%
+
+# Dungeon Description
+REGION:(01,01,73,17),lit,"ordinary"
+# Stairs
+STAIR:random,up
+STAIR:random,down
+# Non diggable walls
+NON_DIGGABLE:(00,00,74,18)
+
+LOOP [15] {
+  OBJECT:random,random
+}
+
+LOOP [6] {
 TRAP:random,random
+}
+
+LOOP [28] {
+  MONSTER:random,random
+}
+
+
+# Two streams
+
+LEVEL:"bigrm-8"
+FLAGS:mazelevel
+INIT_MAP:solidfill,' '
+GEOMETRY:center,center
+MAP
+        |------------------------       -------------------------        
+        |.......................|       |.......................|        
+        |.......................|       |................}}.....|        
+|-------|......}}}}.............|--------.....}}.}.....}}}}.....--------|
+|}}}......}}..}}}}}}..........}}}..........}}}..}.....}....}.}}..}}}}}}}|
+|}}}....}}.}}}.....}....}}...}...}}}....}.}...........}.....}}.}}....}}}|
+|}}}}}}}............}}}}..}}}.......}}}}}}}............}..............}}|
+|}}}}}...............}}...............}}...}............}...........}}}}|
+|-------|.......................|--------...}.........}}}.......--------|
+        |.......................|       |...}}......}}.}........|        
+|--------........LLLL....LL.....--------|....}}...}}............|-------|
+|LLL..........LLL.........LLL......LLL........}.}}}}.......LLL.........L|
+|LLLL........LLL.............L...LL..LLLLLL....}}.}.....LLL...LLL....LLL|
+|LLLLLLLL..LLL.LLLLLL.........LLL......LLLLL.........LLLL........LLLLLLL|
+|LLLLLL..LLL........LLL...LLLL............LLLLL..LLLL.LLLLL........LLLLL|
+|--------..............LLL......--------|.....LLL....LLLLLL.....|-------|
+        |.......................|       |...............LL......|        
+        |.......................|       |.......................|        
+        -------------------------       -------------------------        
+ENDMAP
+
+IF [40%] {
+   $terrain_from = TERRAIN:{ 'L', '}', 'I' }
+   $terrain_to   = TERRAIN:{ 'L', '}', 'I', '.' }
+   SHUFFLE:$terrain_from
+   SHUFFLE:$terrain_to
+   REPLACE_TERRAIN:(0,0,75,18),$terrain_from[0], $terrain_to[0], 100%
+   IF [50%] {
+      REPLACE_TERRAIN:(0,0,75,18),$terrain_from[1], $terrain_to[1], 100%
+   }
+}
+
+# Dungeon Description
+REGION:(01,01,72,17),lit,"ordinary"
+# Stairs
+STAIR:random,up
+STAIR:random,down
+#
+# Non diggable walls
+NON_DIGGABLE:(00,00,72,18)
+
+LOOP [15] {
+  OBJECT:random,random
+}
+
+LOOP [6] {
 TRAP:random,random
+}
+
+LOOP [28] {
+  MONSTER:random,random
+}
+
+
+# Slanted
+
+LEVEL:"bigrm-9"
+FLAGS:mazelevel
+INIT_MAP:solidfill,' '
+GEOMETRY:center,center
+MAP
+----------------------------------------------                             
+|............................................---                           
+--.............................................---                         
+ ---......................................FF.....---                       
+   ---...................................FF........---                     
+     ---................................FF...........---                   
+       ---.............................FF..............---                 
+         ---..........................FF.................---               
+           ---.......................FF....................---             
+             ---....................FF.......................---           
+               ---.................FF..........................---         
+                 ---..............FF.............................---       
+                   ---...........FF................................----    
+                     ---........FF...................................---   
+                       ---.....FF......................................--- 
+                         ---.............................................--
+                           ---............................................|
+                             ----------------------------------------------
+ENDMAP
+
+IF [40%] {
+   $terrain = TERRAIN:{ 'L', '}', 'T', '.', '-', 'C' }
+   SHUFFLE:$terrain
+   REPLACE_TERRAIN:(0,0,74,17),'F', $terrain[0], 100%
+}
+
+# Dungeon Description
+REGION:(01,01,73,16),lit,"ordinary"
+# Stairs
+STAIR:random,up
+STAIR:random,down
+# Non diggable walls
+NON_DIGGABLE:(00,00,74,17)
+
+LOOP [15] {
+  OBJECT:random,random
+}
+
+LOOP [6] {
 TRAP:random,random
+}
+
+LOOP [28] {
+  MONSTER:random,random
+}
+
+# The Eye
+
+LEVEL:"bigrm-10"
+INIT_MAP:solidfill,'}'
+GEOMETRY:center,center
+MAP
+}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}
+}}}}}}}}}}}}}}}}}}}}}}}}}}}}}................}}}}}}}}}}}}}}}}}}}}}}}}}}}}}
+}}}}}}}}}}}}}}}}}}}}}................................}}}}}}}}}}}}}}}}}}}}}
+}}}}}}}}}}}}}}}............................................}}}}}}}}}}}}}}}
+}}}}}}}}}}......................................................}}}}}}}}}}
+}}}}}}}............................................................}}}}}}}
+}}}}}.......................LLLLLLLLLLLLLLLLLL.......................}}}}}
+}}}....................LLLLLLLLLLLLLLLLLLLLLLLLLLL.....................}}}
+}....................LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL....................}
+}....................LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL....................}
+}....................LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL....................}
+}}}....................LLLLLLLLLLLLLLLLLLLLLLLLLLL.....................}}}
+}}}}}.......................LLLLLLLLLLLLLLLLLL.......................}}}}}
+}}}}}}}............................................................}}}}}}}
+}}}}}}}}}}......................................................}}}}}}}}}}
+}}}}}}}}}}}}}}}............................................}}}}}}}}}}}}}}}
+}}}}}}}}}}}}}}}}}}}}}................................}}}}}}}}}}}}}}}}}}}}}
+}}}}}}}}}}}}}}}}}}}}}}}}}}}}}................}}}}}}}}}}}}}}}}}}}}}}}}}}}}}
+}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}
+ENDMAP
+
+IF [33%] {
+    REPLACE_TERRAIN:(0,0,73,18), 'L', 'T', 100%
+    REPLACE_TERRAIN:(0,0,73,18), 'T', '.', 75%
+}
+
+# Unlit, except 3 mapgrids around the "pupil"
+REGION:(00,00,73,18),unlit,"ordinary"
+REGION:(26,04,47,14),lit,"ordinary"
+REGION:(21,05,51,13),lit,"ordinary"
+REGION:(19,06,54,12),lit,"ordinary"
+# Stairs
+STAIR:random,up
+STAIR:random,down
+
+LOOP [15] {
+  OBJECT:random,random
+}
+LOOP [6] {
 TRAP:random,random
-# Random monsters.
-MONSTER:random,random,random
-MONSTER:random,random,random
-MONSTER:random,random,random
-MONSTER:random,random,random
-MONSTER:random,random,random
-MONSTER:random,random,random
-MONSTER:random,random,random
-MONSTER:random,random,random
-MONSTER:random,random,random
-MONSTER:random,random,random
-MONSTER:random,random,random
-MONSTER:random,random,random
-MONSTER:random,random,random
-MONSTER:random,random,random
-MONSTER:random,random,random
-MONSTER:random,random,random
-MONSTER:random,random,random
-MONSTER:random,random,random
-MONSTER:random,random,random
-MONSTER:random,random,random
-MONSTER:random,random,random
-MONSTER:random,random,random
-MONSTER:random,random,random
-MONSTER:random,random,random
-MONSTER:random,random,random
-MONSTER:random,random,random
-MONSTER:random,random,random
-MONSTER:random,random,random
+}
+LOOP [28] {
+  MONSTER:random,random
+}
+
+
+# Fog Maze
+
+LEVEL:"bigrm-11"
+GEOMETRY:center,center
+MAP
+.......................................................................
+.......................................................................
+.......................................................................
+.......................................................................
+...C C C C C C C C C C C C C C C C C C C C C C C C C C C C C C C C C...
+...CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC...
+...C C C C C C C C C C C C C C C C C C C C C C C C C C C C C C C C C...
+...CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC...
+...C C C C C C C C C C C C C C C C C C C C C C C C C C C C C C C C C...
+...CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC...
+...C C C C C C C C C C C C C C C C C C C C C C C C C C C C C C C C C...
+...CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC...
+...C C C C C C C C C C C C C C C C C C C C C C C C C C C C C C C C C...
+...CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC...
+...C C C C C C C C C C C C C C C C C C C C C C C C C C C C C C C C C...
+.......................................................................
+.......................................................................
+.......................................................................
+.......................................................................
+ENDMAP
+
+IF [33%] {
+   # occasionally it's not a fog maze
+   $terrain = TERRAIN:{ 'L', '}', 'T', '-', 'F' }
+   SHUFFLE:$terrain
+   REPLACE_TERRAIN:(0,0,70,18),'C', $terrain[0], 100%
+}
+
+REGION:(00,00,70,18),lit,"ordinary"
+
+# when falling down on this level, never end up in the fog maze
+TELEPORT_REGION:(00,00,70,18),(02,03,68,15),down
+
+# Stairs up, not in the fog maze
+STAIR:(00,00,70,18),(02,03,68,15),up
+STAIR:random,down
+
+LOOP [15] {
+  OBJECT:random,random
+}
+LOOP [6] {
+  TRAP:random,random
+}
+LOOP [28] {
+  MONSTER:random,random
+}
+
+MAZEWALK:(4, 2), south
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/dat/castle.des nethack/dat/castle.des
--- nh_orig/dat/castle.des	2003-12-07 18:39:12.000000000 -0500
+++ nethack/dat/castle.des	2010-04-11 12:36:58.157750620 -0400
@@ -16,7 +16,11 @@
 # To motivate the player : there are 4 storerooms (armors, weapons, food and
 # gems) and a wand of wishing in one of the 4 towers...
+#
+# Castle level explicitly marked as graveyard to prevent getting
+# too many wraith corpses from VotD
 
-MAZE:"castle",random
-FLAGS: noteleport
+LEVEL:"castle"
+FLAGS: noteleport,mazelevel,graveyard
+INIT_MAP:mazegrid,'-'
 GEOMETRY:center,center
 MAP
@@ -25,13 +29,13 @@
 }|.....|-----------------------------------------------|.....|}
 }|.....+...............................................+.....|}
-}-------------------------------+-----------------------------}
-}}}}}}|........|..........+...........|.......S.S.......|}}}}}}
+}-FFF---------------------------+-------------------------FFF-}
+}}}}}}|........|..........+...........|.......|.|.......|}}}}}}
 .....}|........|..........|...........|.......|.|.......|}.....
 .....}|........------------...........---------S---------}.....
-.....}|...{....+..........+.........\.S.................+......
+.....}|...{....+..........+...........S.................+......
 .....}|........------------...........---------S---------}.....
 .....}|........|..........|...........|.......|.|.......|}.....
-}}}}}}|........|..........+...........|.......S.S.......|}}}}}}
-}-------------------------------+-----------------------------}
+}}}}}}|........|..........+...........|.......|.|.......|}}}}}}
+}-FFF---------------------------+-------------------------FFF-}
 }|.....+...............................................+.....|}
 }|.....|-----------------------------------------------|.....|}
@@ -40,20 +44,41 @@
 ENDMAP
 
+# Treasure room 1
+$place = { (46,05),(44,07),(38,06),(40,04) }
+SHUFFLE: $place
+TERRAIN:$place[0],'S'
+# Treasure room 2
+$place = { (48,05),(54,07),(51,04) }
+SHUFFLE: $place
+TERRAIN:$place[0],'S'
+# Treasure room 3
+$place = { (46,11),(44,12),(38,11),(40,09) }
+SHUFFLE: $place
+TERRAIN:$place[0],'S'
+# Treasure room 4
+$place = { (48,11),(54,09),(51,12) }
+SHUFFLE: $place
+TERRAIN:$place[0],'S'
+
 # Random registers initialisation
-RANDOM_OBJECTS:'[',')','*','%'
-RANDOM_PLACES:(04,02),(58,02),(04,14),(58,14)
-RANDOM_MONSTERS:'L','N','E','H','M','O','R','T','X','Z'
+$object = OBJECT: { '[',')','*','%' }
+$place = { (04,02),(58,02),(04,14),(58,14) }
+$monster = MONSTER:{ 'L','N','E','H','M','O','R','T','X','Z' }
+SHUFFLE: $place
+SHUFFLE: $object
+SHUFFLE: $monster
 
 TELEPORT_REGION:levregion(01,00,10,20),(1,1,61,15),down
-TELEPORT_REGION:levregion(69,00,79,20),(1,1,61,15),up
+TELEPORT_REGION:levregion(69,00,77,20),(1,1,61,15),up
 STAIR:levregion(01,00,10,20),(0,0,62,16),up
+BRANCH:levregion(69,00,77,20),(1,1,61,15)
 FOUNTAIN:(10,08)
 # Doors
-DOOR:closed,(07,03)
-DOOR:closed,(55,03)
+DOOR:locked,(07,03)
+DOOR:locked,(55,03)
 DOOR:locked,(32,04)
 DOOR:locked,(26,05)
-DOOR:locked,(46,05)
-DOOR:locked,(48,05)
+# DOOR:locked,(46,05)
+# DOOR:locked,(48,05)
 DOOR:locked,(47,07)
 DOOR:closed,(15,08)
@@ -63,78 +88,95 @@
 DOOR:locked,(47,09)
 DOOR:locked,(26,11)
-DOOR:locked,(46,11)
-DOOR:locked,(48,11)
+# DOOR:locked,(46,11)
+# DOOR:locked,(48,11)
 DOOR:locked,(32,12)
-DOOR:closed,(07,13)
-DOOR:closed,(55,13)
+DOOR:locked,(07,13)
+DOOR:locked,(55,13)
 # The drawbridge
 DRAWBRIDGE:(05,08),east,closed
 # Storeroom number 1
-OBJECT:object[0],random,(39,05)
-OBJECT:object[0],random,(40,05)
-OBJECT:object[0],random,(41,05)
-OBJECT:object[0],random,(42,05)
-OBJECT:object[0],random,(43,05)
-OBJECT:object[0],random,(44,05)
-OBJECT:object[0],random,(45,05)
-OBJECT:object[0],random,(39,06)
-OBJECT:object[0],random,(40,06)
-OBJECT:object[0],random,(41,06)
-OBJECT:object[0],random,(42,06)
-OBJECT:object[0],random,(43,06)
-OBJECT:object[0],random,(44,06)
-OBJECT:object[0],random,(45,06)
+OBJECT:$object[0],(39,05)
+OBJECT:$object[0],(40,05)
+OBJECT:$object[0],(41,05)
+OBJECT:$object[0],(42,05)
+OBJECT:$object[0],(43,05)
+OBJECT:$object[0],(44,05)
+OBJECT:$object[0],(45,05)
+OBJECT:$object[0],(39,06)
+OBJECT:$object[0],(40,06)
+OBJECT:$object[0],(41,06)
+OBJECT:$object[0],(42,06)
+OBJECT:$object[0],(43,06)
+OBJECT:$object[0],(44,06)
+OBJECT:$object[0],(45,06)
 # Storeroom number 2
-OBJECT:object[1],random,(49,05)
-OBJECT:object[1],random,(50,05)
-OBJECT:object[1],random,(51,05)
-OBJECT:object[1],random,(52,05)
-OBJECT:object[1],random,(53,05)
-OBJECT:object[1],random,(54,05)
-OBJECT:object[1],random,(55,05)
-OBJECT:object[1],random,(49,06)
-OBJECT:object[1],random,(50,06)
-OBJECT:object[1],random,(51,06)
-OBJECT:object[1],random,(52,06)
-OBJECT:object[1],random,(53,06)
-OBJECT:object[1],random,(54,06)
-OBJECT:object[1],random,(55,06)
+OBJECT:$object[1],(49,05)
+OBJECT:$object[1],(50,05)
+OBJECT:$object[1],(51,05)
+OBJECT:$object[1],(52,05)
+OBJECT:$object[1],(53,05)
+OBJECT:$object[1],(54,05)
+OBJECT:$object[1],(55,05)
+OBJECT:$object[1],(49,06)
+OBJECT:$object[1],(50,06)
+OBJECT:$object[1],(51,06)
+OBJECT:$object[1],(52,06)
+OBJECT:$object[1],(53,06)
+OBJECT:$object[1],(54,06)
+OBJECT:$object[1],(55,06)
 # Storeroom number 3
-OBJECT:object[2],random,(39,10)
-OBJECT:object[2],random,(40,10)
-OBJECT:object[2],random,(41,10)
-OBJECT:object[2],random,(42,10)
-OBJECT:object[2],random,(43,10)
-OBJECT:object[2],random,(44,10)
-OBJECT:object[2],random,(45,10)
-OBJECT:object[2],random,(39,11)
-OBJECT:object[2],random,(40,11)
-OBJECT:object[2],random,(41,11)
-OBJECT:object[2],random,(42,11)
-OBJECT:object[2],random,(43,11)
-OBJECT:object[2],random,(44,11)
-OBJECT:object[2],random,(45,11)
+OBJECT:$object[2],(39,10)
+OBJECT:$object[2],(40,10)
+OBJECT:$object[2],(41,10)
+OBJECT:$object[2],(42,10)
+OBJECT:$object[2],(43,10)
+OBJECT:$object[2],(44,10)
+OBJECT:$object[2],(45,10)
+OBJECT:$object[2],(39,11)
+OBJECT:$object[2],(40,11)
+OBJECT:$object[2],(41,11)
+OBJECT:$object[2],(42,11)
+OBJECT:$object[2],(43,11)
+OBJECT:$object[2],(44,11)
+OBJECT:$object[2],(45,11)
 # Storeroom number 4
-OBJECT:object[3],random,(49,10)
-OBJECT:object[3],random,(50,10)
-OBJECT:object[3],random,(51,10)
-OBJECT:object[3],random,(52,10)
-OBJECT:object[3],random,(53,10)
-OBJECT:object[3],random,(54,10)
-OBJECT:object[3],random,(55,10)
-OBJECT:object[3],random,(49,11)
-OBJECT:object[3],random,(50,11)
-OBJECT:object[3],random,(51,11)
-OBJECT:object[3],random,(52,11)
-OBJECT:object[3],random,(53,11)
-OBJECT:object[3],random,(54,11)
-OBJECT:object[3],random,(55,11)
+OBJECT:$object[3],(49,10)
+OBJECT:$object[3],(50,10)
+OBJECT:$object[3],(51,10)
+OBJECT:$object[3],(52,10)
+OBJECT:$object[3],(53,10)
+OBJECT:$object[3],(54,10)
+OBJECT:$object[3],(55,10)
+OBJECT:$object[3],(49,11)
+OBJECT:$object[3],(50,11)
+OBJECT:$object[3],(51,11)
+OBJECT:$object[3],(52,11)
+OBJECT:$object[3],(53,11)
+OBJECT:$object[3],(54,11)
+OBJECT:$object[3],(55,11)
 # THE WAND OF WISHING in 1 of the 4 towers
-CONTAINER:'(',"chest",place[0]
-OBJECT:'/',"wishing",contained
-# Prevent monsters from eating it.  (@'s never eat objects)
-ENGRAVING:place[0],burn,"Elbereth"
+CONTAINER:('(',"chest"),$place[0] {
+  OBJECT:('/',"wishing")
+}
+# THE NOT QUITE WANDS OF WISHING
+# ...since you can see the chest now through the bars,
+# we have to find a better way to disguise where the wand is
+CONTAINER:('(',"chest"),$place[1] {
+  OBJECT:('/',"secret door detection")
+}
+CONTAINER:('(',"chest"),$place[2] {
+  OBJECT:'/'
+}
+CONTAINER:('(',"chest"),$place[3] {
+  OBJECT:'/'
+}
+# Prevent monsters from eating them.  (@'s never eat objects)
+ENGRAVING:$place[0],burn,"Elbereth"
+ENGRAVING:$place[1],burn,"Elbereth"
+ENGRAVING:$place[2],burn,"Elbereth"
+ENGRAVING:$place[3],burn,"Elbereth"
 # The treasure of the lord
-OBJECT:'(',"chest",(37,08)
+OBJECT:('(',"chest"),(37,08)
+OBJECT:('\',"throne"),(36,08)
 # Traps
 TRAP:"trap door",(40,08)
@@ -144,64 +186,36 @@
 TRAP:"trap door",(55,08)
 # Soldiers guarding the entry hall
-MONSTER:'@',"soldier",(08,06)
-MONSTER:'@',"soldier",(09,05)
-MONSTER:'@',"soldier",(11,05)
-MONSTER:'@',"soldier",(12,06)
-MONSTER:'@',"soldier",(08,10)
-MONSTER:'@',"soldier",(09,11)
-MONSTER:'@',"soldier",(11,11)
-MONSTER:'@',"soldier",(12,10)
-MONSTER:'@',"lieutenant",(09,08)
+MONSTER:('@',"soldier"),(08,06)
+MONSTER:('@',"soldier"),(09,05)
+MONSTER:('@',"soldier"),(11,05)
+MONSTER:('@',"soldier"),(12,06)
+MONSTER:('@',"soldier"),(08,10)
+MONSTER:('@',"soldier"),(09,11)
+MONSTER:('@',"soldier"),(11,11)
+MONSTER:('@',"soldier"),(12,10)
+MONSTER:('@',"lieutenant"),(09,08)
 # Soldiers guarding the towers
-MONSTER:'@',"soldier",(03,02)
-MONSTER:'@',"soldier",(05,02)
-MONSTER:'@',"soldier",(57,02)
-MONSTER:'@',"soldier",(59,02)
-MONSTER:'@',"soldier",(03,14)
-MONSTER:'@',"soldier",(05,14)
-MONSTER:'@',"soldier",(57,14)
-MONSTER:'@',"soldier",(59,14)
+MONSTER:('@',"sergeant"),(03,02)
+MONSTER:('@',"sergeant"),(05,02)
+MONSTER:('@',"sergeant"),(57,02)
+MONSTER:('@',"sergeant"),(59,02)
+MONSTER:('@',"sergeant"),(03,14)
+MONSTER:('@',"sergeant"),(05,14)
+MONSTER:('@',"sergeant"),(57,14)
+MONSTER:('@',"sergeant"),(59,14)
 # The four dragons that are guarding the storerooms
-MONSTER:'D',random,(47,05)
-MONSTER:'D',random,(47,06)
-MONSTER:'D',random,(47,10)
-MONSTER:'D',random,(47,11)
+MONSTER:'D',(47,05)
+MONSTER:'D',(47,06)
+MONSTER:'D',(47,10)
+MONSTER:'D',(47,11)
 # Sea monsters in the moat
-MONSTER:';',"giant eel",(05,07)
-MONSTER:';',"giant eel",(05,09)
-MONSTER:';',"giant eel",(57,07)
-MONSTER:';',"giant eel",(57,09)
-MONSTER:';',"shark",(05,00)
-MONSTER:';',"shark",(05,16)
-MONSTER:';',"shark",(57,00)
-MONSTER:';',"shark",(57,16)
-# The throne room and the court monsters
-MONSTER:monster[0],random,(27,05)
-MONSTER:monster[1],random,(30,05)
-MONSTER:monster[2],random,(33,05)
-MONSTER:monster[3],random,(36,05)
-MONSTER:monster[4],random,(28,06)
-MONSTER:monster[5],random,(31,06)
-MONSTER:monster[6],random,(34,06)
-MONSTER:monster[7],random,(37,06)
-MONSTER:monster[8],random,(27,07)
-MONSTER:monster[9],random,(30,07)
-MONSTER:monster[0],random,(33,07)
-MONSTER:monster[1],random,(36,07)
-MONSTER:monster[2],random,(28,08)
-MONSTER:monster[3],random,(31,08)
-MONSTER:monster[4],random,(34,08)
-MONSTER:monster[5],random,(27,09)
-MONSTER:monster[6],random,(30,09)
-MONSTER:monster[7],random,(33,09)
-MONSTER:monster[8],random,(36,09)
-MONSTER:monster[9],random,(28,10)
-MONSTER:monster[0],random,(31,10)
-MONSTER:monster[1],random,(34,10)
-MONSTER:monster[2],random,(37,10)
-MONSTER:monster[3],random,(27,11)
-MONSTER:monster[4],random,(30,11)
-MONSTER:monster[5],random,(33,11)
-MONSTER:monster[6],random,(36,11)
+MONSTER:(';',"giant eel"),(05,07)
+MONSTER:(';',"giant eel"),(05,09)
+MONSTER:(';',"giant eel"),(57,07)
+MONSTER:(';',"giant eel"),(57,09)
+MONSTER:(';',"shark"),(05,00)
+MONSTER:(';',"shark"),(05,16)
+MONSTER:(';',"shark"),(57,00)
+MONSTER:(';',"shark"),(57,16)
 # MazeWalks
 MAZEWALK:(00,10),west
@@ -216,5 +230,34 @@
 REGION:(57,05,62,11),lit,"ordinary"
 #   Throne room
-REGION:(27,05,37,11),lit,"throne",unfilled
+REGION:(27,05,37,11),lit,"throne",unfilled {
+  # the court monsters
+  MONSTER:$monster[0],random
+  MONSTER:$monster[1],random
+  MONSTER:$monster[2],random
+  MONSTER:$monster[3],random
+  MONSTER:$monster[4],random
+  MONSTER:$monster[5],random
+  MONSTER:$monster[6],random
+  MONSTER:$monster[7],random
+  MONSTER:$monster[8],random
+  MONSTER:$monster[9],random
+  MONSTER:$monster[0],random
+  MONSTER:$monster[1],random
+  MONSTER:$monster[2],random
+  MONSTER:$monster[3],random
+  MONSTER:$monster[4],random
+  MONSTER:$monster[5],random
+  MONSTER:$monster[6],random
+  MONSTER:$monster[7],random
+  MONSTER:$monster[8],random
+  MONSTER:$monster[9],random
+  MONSTER:$monster[0],random
+  MONSTER:$monster[1],random
+  MONSTER:$monster[2],random
+  MONSTER:$monster[3],random
+  MONSTER:$monster[4],random
+  MONSTER:$monster[5],random
+  MONSTER:$monster[6],random
+}
 #   Antechamber
 REGION:(07,05,14,11),lit,"ordinary"
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/dat/Caveman.des nethack/dat/Caveman.des
--- nh_orig/dat/Caveman.des	2003-12-07 18:39:12.000000000 -0500
+++ nethack/dat/Caveman.des	2010-08-16 13:20:13.634708200 -0400
@@ -9,29 +9,40 @@
 #	and receive your quest assignment.
 #
-MAZE: "Cav-strt",' '
-FLAGS: noteleport,hardfloor
+LEVEL: "Cav-strt"
+FLAGS: noteleport,hardfloor,arboreal,mazelevel
+INIT_MAP:solidfill,' '
+MON_GENERATION:86%, (64,"tiger"), (16,'S'), (16,"ape"), (4,'f')
 GEOMETRY:center,center
 MAP
                                                                             
-  ......     ..........................       ...        ....  ......       
- ......       ..........................     ........       ....    .....   
-  ..BB      .............................    .........            ....  ..  
-     ..    ......................              .......      ..     ....  .. 
-     ..     ....................                     ..  .......    ..  ... 
-   ..              S   BB                .....     .......   ....      .... 
-    ..        ...  .   ..               ........  ..     ..   ..       ...  
-     ..      ......     ..             ............       ..          ...   
-       .      ....       ..             ........           ..  ...........  
-  ...   ..     ..        .............                  ................... 
- .....   .....            ...............................      ...........  
-  .....B................            ...                               ...   
-  .....     .  ..........        .... .      ...  ..........           ...  
-   ...     ..          .............  ..    ...................        .... 
-          BB       ..   .........      BB    ...  ..........  ..   ...  ... 
-       ......    .....  B          ........         ..         .. ....  ... 
-     ..........  ..........         ..... ...      .....        ........    
-       ..  ...    .  .....         ....    ..       ...            ..       
+  ......     ..........................       ... PP   P ....  ...... P     
+ ......       ..........................     .......P    PP .... PP .....P  
+  ..BB      ............................    P...P P...P      .P  P....  ..  
+     ..    ......................             P.......P  PP .. P  P....P .. 
+     ..  P BB...................         PP          ..  .......P  P.. P... 
+   ...   ...B      B                     ..... P  P....... PP....   PP .... 
+    ..P P.    ...  .  ...               ...P....P ..  PP ..   .. P     P..  
+     ..  .P  .......  ....            P...PPP...... P    PPPP P    PP ...   
+  PPP .. .    ....   ... . PP  P      P ........  P   P  P ..  ...........  
+  ... P...     ..   .... .B...........P  PP  PP  PP P  P.........PP........ 
+ .....  P.....             ..............................  PP  ...........P 
+P .PP..B..........PPP...   P  PPP   ... P P PPP  P  P PP     P  PPP   ...   
+  .....  PP .  ..........PP  PPP ....P.PP    ...  .......... PP       P...  
+  P...P    ..    PPP   .............  ..   P.........PPPP......     P P.... 
+          BB            .........PP    BB    ...  .....P....P .. PP... P... 
+       ......    .....  B     PP    .......   P PP P.. PPP   PP.. .P..  ... 
+     ..........  ..........        ...... ..      P.....   P    .........P  
+       ..  ...    .  .....         ....    ..       ...P       P   ..  P    
                                                                             
 ENDMAP
+
+REPLACE_TERRAIN:(40,1, 74,18), 'P', ' ', 25%
+REPLACE_TERRAIN:(40,1, 74,18), 'P', '.', 5%
+
+IF [90%] {
+   TERRAIN:(43,11),' '
+   TERRAIN:(40,10),'.'
+}
+
 # Dungeon Description
 REGION:(00,00,75,19),unlit,"ordinary"
@@ -43,49 +54,74 @@
 REGION:(05,17,14,18),lit,"ordinary",unfilled,true
 REGION:(17,16,23,18),lit,"ordinary",unfilled,true
-REGION:(35,16,44,18),lit,"ordinary",unfilled,true
+REGION:(37,16,44,18),lit,"ordinary",unfilled,true
 # Stairs
-STAIR:(02,03),down
+LADDER:(02,03),down
 # Portal arrival point
 BRANCH:(71,09,71,09),(0,0,0,0)
-# Doors
-DOOR:locked,(19,06)
 # The temple altar (this will force a priest(ess) to be created)
 ALTAR:(36,02),coaligned,shrine
 # Shaman Karnov
-MONSTER:'@',"Shaman Karnov",(35,02)
+MONSTER:('@',"Shaman Karnov"),(35,02) {
+  OBJECT:'[',1d6
+  OBJECT:')',1d6
+}
 # The treasure of Shaman Karnov
-OBJECT:'(',"chest",(34,02)
+OBJECT:('(',"chest"),(34,02)
 # neanderthal guards for the audience chamber
-MONSTER:'@',"neanderthal",(20,03)
-MONSTER:'@',"neanderthal",(20,02)
-MONSTER:'@',"neanderthal",(20,01)
-MONSTER:'@',"neanderthal",(21,03)
-MONSTER:'@',"neanderthal",(21,02)
-MONSTER:'@',"neanderthal",(21,01)
-MONSTER:'@',"neanderthal",(22,01)
-MONSTER:'@',"neanderthal",(26,09)
+MONSTER:('@',"neanderthal"),(20,03) {
+  OBJECT:')'
+}
+MONSTER:('@',"neanderthal"),(20,02) {
+  OBJECT:')'
+}
+MONSTER:('@',"neanderthal"),(20,01) {
+  OBJECT:')'
+}
+MONSTER:('@',"neanderthal"),(21,03) {
+  OBJECT:')'
+}
+MONSTER:('@',"neanderthal"),(21,02) {
+  OBJECT:')'
+}
+MONSTER:('@',"neanderthal"),(21,01) {
+  OBJECT:')'
+}
+MONSTER:('@',"neanderthal"),(22,01) {
+  OBJECT:')'
+}
+MONSTER:('@',"neanderthal"),(24,08) {
+  OBJECT:')'
+}
 # Non diggable walls
 NON_DIGGABLE:(00,00,75,19)
 # Random traps
-TRAP:"pit",(47,11)
-TRAP:"pit",(57,10)
-TRAP:random,random
-TRAP:random,random
-TRAP:random,random
-TRAP:random,random
-# Monsters on siege duty (in the outer caves).
-MONSTER: 'h',"bugbear",(47,02),hostile
-MONSTER: 'h',"bugbear",(48,03),hostile
-MONSTER: 'h',"bugbear",(49,04),hostile
-MONSTER: 'h',"bugbear",(67,03),hostile
-MONSTER: 'h',"bugbear",(69,04),hostile
-MONSTER: 'h',"bugbear",(51,13),hostile
-MONSTER: 'h',"bugbear",(53,14),hostile
-MONSTER: 'h',"bugbear",(55,15),hostile
-MONSTER: 'h',"bugbear",(63,10),hostile
-MONSTER: 'h',"bugbear",(65,09),hostile
-MONSTER: 'h',"bugbear",(67,10),hostile
-MONSTER: 'h',"bugbear",(69,11),hostile
-WALLIFY
+TRAP:"pit",random
+TRAP:"pit",random
+TRAP:"pit",random
+TRAP:"spiked pit",random
+TRAP:"spiked pit",random
+TRAP:"spiked pit",random
+TRAP:"bear",(19,13)
+TRAP:"bear",(46,11)
+TRAP:"bear",random
+TRAP:"bear",random
+TRAP:"bear",random
+TRAP:"bear",random
+# Random jungle stuff
+LOOP [5 + 1d10] {
+  MONSTER: (';',"giant eel"),random,hostile
+}
+LOOP [10 + 1d5] {
+  MONSTER: ('Y',"monkey"),random,hostile
+}
+LOOP [4 + 1d3] {
+  MONSTER: ('Y',"ape"),random,hostile
+}
+LOOP [3 + 1d3] {
+  MONSTER: ('S',"python"),random,hostile
+}
+LOOP [3 + 1d3] {
+  MONSTER: ('f',"panther"),random,hostile
+}
 
 #
@@ -96,91 +132,71 @@
 #
 
-MAZE: "Cav-loca",' '
-FLAGS: hardfloor
+LEVEL: "Cav-loca"
+FLAGS: noteleport,hardfloor,arboreal,mazelevel
+INIT_MAP:solidfill,' '
+MON_GENERATION:86%, (64,"tiger"), (16,'S'), (16,"ape"), (4,'f')
 GEOMETRY:center,center
 MAP
                                                                             
     .............                     ...........                           
-   ...............                   .............                          
-    .............                  ...............        ..........        
-     ...........                    .............      ...............      
-        ...                                    ...   ..................     
-         ...                ..........          ... ..................      
-          ...              ............          BBB...................     
+   ........PPP....                   .............                          
+    ......PPP....                  ...............        ..........        
            ...              ..........          ......................      
-            .....                 ..      .....B........................    
-  ....       ...............      .    ........B..........................  
- ......     .. .............S..............         ..................      
-  ....     ..                ...........             ...............        
-     ..  ...                                    ....................        
+        ....  PP                               ...   ..................     
+         ...                ..........          ... ..................      
+         P...              ....PPP.....          BBB...................     
+           ... P            ..........          ......................      
+   PP       ..... PP   P          ..      ....PB........................    
+  ....       ...............      .  P .......PB..........................  
+ ......     .. .............P..............         ..................      
+  ....     ..  P   PPP       ...........             ...............        
+     ..  ...                      PPP           ....................        
       ....                                      BB...................       
-         ..                 ..                 ..  ...............          
-          ..   .......     ....  .....  ....  ..     .......   S            
-           ............     ....... ..  .......       .....    ...  ....    
-               .......       .....   ......                      .......    
+      PP .. P               ..                 ..  ...............          
+          ..   .......     ....  .....  ....  ..     .......   P            
+         P ......PPP...     ....... ..  .......       .....    ...  ....    
+            P  .......       .....   ......                      .......    
                                                                             
 ENDMAP
+
+REPLACE_TERRAIN:(00,00,25,19), ' ', 'P', 10%
+
 # Dungeon Description
 REGION:(00,00,75,19),unlit,"ordinary"
 REGION:(52,06,73,15),lit,"ordinary",unfilled,true
-# Doors
-DOOR:locked,(28,11)
 # Stairs
-STAIR:(04,03),up
-STAIR:(73,10),down
+LADDER:(04,03),up
+LADDER:(73,10),down
 # Non diggable walls
 NON_DIGGABLE:(00,00,75,19)
 # Objects
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
+LOOP [10 + 2d5] {
+  OBJECT:random,random
+}
 # Random traps
-TRAP:random,random
-TRAP:random,random
-TRAP:random,random
-TRAP:random,random
-TRAP:random,random
-TRAP:random,random
-# Random monsters.
-MONSTER:'h',"bugbear",(02,10),hostile
-MONSTER:'h',"bugbear",(03,11),hostile
-MONSTER:'h',"bugbear",(04,12),hostile
-MONSTER:'h',"bugbear",(02,11),hostile
-MONSTER:'h',"bugbear",(16,16),hostile
-MONSTER:'h',"bugbear",(17,17),hostile
-MONSTER:'h',"bugbear",(18,18),hostile
-MONSTER:'h',"bugbear",(19,16),hostile
-MONSTER:'h',"bugbear",(30,06),hostile
-MONSTER:'h',"bugbear",(31,07),hostile
-MONSTER:'h',"bugbear",(32,08),hostile
-MONSTER:'h',"bugbear",(33,06),hostile
-MONSTER:'h',"bugbear",(34,07),hostile
-MONSTER:'h',"bugbear",random,hostile
-MONSTER:'h',"bugbear",random,hostile
-MONSTER:'h',"bugbear",random,hostile
-MONSTER:'h',"bugbear",random,hostile
-MONSTER:'h',random,random,hostile
-MONSTER:'H',random,random,hostile
-MONSTER:'H',"hill giant",(03,12),hostile
-MONSTER:'H',"hill giant",(20,17),hostile
-MONSTER:'H',"hill giant",(35,08),hostile
-MONSTER:'H',"hill giant",random,hostile
-MONSTER:'H',"hill giant",random,hostile
-MONSTER:'H',"hill giant",random,hostile
-MONSTER:'H',"hill giant",random,hostile
-MONSTER:'H',random,random,hostile
-WALLIFY
+LOOP [3 + 1d5] {
+  TRAP:"spiked pit",random
+}
+LOOP [4 + 1d5] {
+  TRAP:"bear",random
+}
+# Monsters...
+MONSTER:(';',"electric eel"),(28,11),hostile
+MONSTER:(';',"electric eel"),(46,09),hostile
+MONSTER:(';',"electric eel"),(46,10),hostile
+MONSTER:(';',"electric eel"),(63,16),hostile
+LOOP [3 + 1d6] {
+  MONSTER:(';',"giant eel"),random,hostile
+}
+LOOP [7 + 1d6] {
+  MONSTER:('Y',"carnivorous ape"),random,hostile
+}
+LOOP [3 + 1d5] {
+  MONSTER:('Y',"monkey"),random,hostile
+}
+LOOP [3 + 1d3] {
+  MONSTER:('S',"python"),random,hostile
+}
+# WALLIFY
 
 #
@@ -192,5 +208,8 @@
 #
 
-MAZE: "Cav-goal", ' '
+LEVEL: "Cav-goal"
+FLAGS:mazelevel
+INIT_MAP:solidfill,' '
+MON_GENERATION:86%, (64,"tiger"), (16,'S'), (16,"ape"), (4,'f')
 GEOMETRY:center,center
 MAP
@@ -219,31 +238,88 @@
 REGION:(00,00,75,19),lit,"ordinary"
 # Stairs
-STAIR:random,up
+LADDER:random,up
 # Non diggable walls
 NON_DIGGABLE:(00,00,75,19)
 # Objects
-OBJECT:')',"mace",(23,10),blessed,0,"The Sceptre of Might"
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
+OBJECT:(')',"mace"),(23,10),blessed,0,NAME:"The Sceptre of Might"
+LOOP [10 + 2d8] {
+  OBJECT:random,random
+}
 # monsters.
-MONSTER:'D',"Chromatic Dragon",(23,10),asleep
-MONSTER:'F',"shrieker",(26,13)
-MONSTER:'F',"shrieker",(25,8)
-MONSTER:'F',"shrieker",(45,11)
+MONSTER:('D',"Chromatic Dragon"),(23,10),asleep {
+  OBJECT:('(', "Bell of Opening"),uncursed
+  OBJECT:random
+  OBJECT:random
+  OBJECT:random
+  OBJECT:random
+  OBJECT:random
+}
+MONSTER:('F',"shrieker"),(26,13)
+MONSTER:('F',"shrieker"),(25,8)
+MONSTER:('F',"shrieker"),(45,11)
+LOOP [2 + 1d4] {
+  MONSTER:('Y',"carnivorous ape"),random,hostile
+  MONSTER[90%]:('f',"tiger"),random,hostile
+}
 WALLIFY
 
 #
+#	The level inbetween the original starting jungle and the lower levels
+#	where the actual caves are.
+#
+
+LEVEL: "Cav-fila"
+FLAGS: noteleport,hardfloor,arboreal,mazelevel
+INIT_MAP:solidfill,' '
+MON_GENERATION:86%, (64,"tiger"), (16,'S'), (16,"ape"), (4,'f')
+GEOMETRY: center,center
+MAP
+                                                                            
+                                          P                                 
+                                         PP                                 
+    ...                ....             .PP...            P  ....           
+   .....              ..PP...       ....PP.......          ........         
+   .....             ...PP...      .....PPP.........   P ..........         
+   .......           ........      .....PP..........................        
+     .....           .........      ...PPP............ P    ....P...        
+     ..P..         .....  ....       ..PP...     PPP        ...PPP..        
+     ..PP.         ....    ....       PPP                  P...PPP..        
+      .....        ...      ...       PP                    ....P...        
+      .....        ..       ...       P                    .........P       
+       ..... P     ..        ...                         ...........        
+       ......      ..        ...                  ..................        
+       ......      ..         .. P   PPP   .........PPPP...........P        
+        P  ...  PP ..         ..............................   PP           
+            ........               PPP    P   ..........                    
+             PPP                                                            
+                                                                            
+                                                                            
+ENDMAP
+#
+LADDER: (05,04), up
+LADDER: (36,05), down
+#
+REGION:(00,00,75,19),unlit,"ordinary"
+#
+NON_DIGGABLE:(00,00,75,19)
+#
+LOOP [5 + 1d5] {
+  OBJECT: random, random
+}
+#
+LOOP [2 + 1d3] {
+  TRAP[90%]: "pit", random
+  TRAP[90%]: "spiked pit", random
+  TRAP[90%]: "bear", random
+}
+TRAP: "bear", (37,15)
+#
+LOOP [5 + 1d10] {
+  MONSTER[90%]: ('f',"tiger"),random,hostile
+  MONSTER[90%]: ('S',"python"),random,hostile
+  MONSTER[90%]: ('Y',"carnivorous ape"),random,hostile
+}
+
+#
 #	The "fill" levels for the quest.
 #
@@ -253,64 +329,29 @@
 #	and goal levels.
 #
-
-MAZE: "Cav-fila" , ' '
-INIT_MAP: '.' , ' ' , true , true , random , true
-NOMAP
-#
-STAIR: random, up
-STAIR: random, down
-#
-OBJECT: random, random, random
-OBJECT: random, random, random
-OBJECT: random, random, random
-OBJECT: random, random, random
-OBJECT: random, random, random
-OBJECT: random, random, random
-OBJECT: random, random, random
-#
-TRAP: random, random
-TRAP: random, random
-TRAP: random, random
-TRAP: random, random
+#	Obviously, "fila" has been hijacked and moved above.  :)
 #
-MONSTER: 'h', "bugbear", random, hostile
-MONSTER: 'h', "bugbear", random, hostile
-MONSTER: 'h', "bugbear", random, hostile
-MONSTER: 'h', "bugbear", random, hostile
-MONSTER: 'h', "bugbear", random, hostile
-MONSTER: 'h', random, random, hostile
-MONSTER: 'H', "hill giant", random, hostile
 
-MAZE: "Cav-filb" , ' '
-INIT_MAP: '.' , ' ' , true , true , random , true
+LEVEL: "Cav-filb"
+FLAGS:mazelevel,noflip
+INIT_MAP: mines, '.' , ' ' , true , true , random , true
+MON_GENERATION:86%, (64,"tiger"), (16,'S'), (16,"ape"), (4,'f')
 NOMAP
 #
-STAIR: random, up
-STAIR: random, down
+LADDER: random, up
+LADDER: random, down
 #
-OBJECT: random, random, random
-OBJECT: random, random, random
-OBJECT: random, random, random
-OBJECT: random, random, random
-OBJECT: random, random, random
-OBJECT: random, random, random
-OBJECT: random, random, random
-OBJECT: random, random, random
-OBJECT: random, random, random
-OBJECT: random, random, random
-OBJECT: random, random, random
-OBJECT: random, random, random
+LOOP [5 + 1d5] {
+  OBJECT: random, random
+}
 #
-TRAP: random, random
-TRAP: random, random
-TRAP: random, random
-TRAP: random, random
+LOOP [2 + 1d3] {
+  TRAP[90%]: "pit", random
+  TRAP[90%]: "spiked pit", random
+  TRAP[90%]: "bear", random
+}
 #
-MONSTER: 'h', "bugbear", random, hostile
-MONSTER: 'h', "bugbear", random, hostile
-MONSTER: 'h', "bugbear", random, hostile
-MONSTER: 'h', "bugbear", random, hostile
-MONSTER: 'h', random, random, hostile
-MONSTER: 'h', random, random, hostile
-MONSTER: 'H', "hill giant", random, hostile
-MONSTER: 'H', "hill giant", random, hostile
+LOOP [5 + 1d10] {
+  MONSTER[90%]: ('f',"tiger"),random,hostile
+  MONSTER[90%]: ('S',"python"),random,hostile
+  MONSTER[90%]: ('Y',"carnivorous ape"),random,hostile
+}
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/dat/dungeon.def nethack/dat/dungeon.def
--- nh_orig/dat/dungeon.def	2003-12-07 18:39:13.000000000 -0500
+++ nethack/dat/dungeon.def	2010-04-23 14:27:35.945715831 -0400
@@ -22,11 +22,11 @@
 LEVALIGN:	neutral
 CHAINBRANCH:	"Sokoban" "oracle" + (1, 0) up
-RNDLEVEL:	"bigrm" "B" @ (10, 3) 40 5
+RNDLEVEL:	"bigrm" "B" @ (10, 3) 40 11
 CHAINBRANCH:	"The Quest" "oracle" + (6, 2) portal
 BRANCH:		"Fort Ludios" @ (18, 4) portal
-RNDLEVEL:	"medusa" "none" @ (-5, 4) 2
+RNDLEVEL:	"medusa" "none" @ (-5, 4) 4
 LEVALIGN:	chaotic
 LEVEL:		"castle" "none" @ (-1, 0)
-CHAINBRANCH:	"Gehennom" "castle" + (0, 0) no_down
+CHAINBRANCH:	"Gehennom" "castle" + (0, 0) down
 BRANCH:		"The Elemental Planes" @ (1, 0) no_down up
 
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/dat/endgame.des nethack/dat/endgame.des
--- nh_orig/dat/endgame.des	2003-12-07 18:39:13.000000000 -0500
+++ nethack/dat/endgame.des	2010-05-13 09:22:22.243714740 -0400
@@ -10,6 +10,7 @@
 # shrine.
 
-MAZE:"earth",' '
-FLAGS: noteleport,hardfloor,shortsighted
+LEVEL:"earth"
+FLAGS: noteleport,hardfloor,shortsighted,mazelevel
+INIT_MAP:solidfill,' '
 MESSAGE: "Well done, mortal!"
 MESSAGE: "But now thou must face the final Test..."
@@ -44,87 +45,93 @@
                                                                             
 ENDMAP
+
+REPLACE_TERRAIN:(0,0,75,19), ' ', ('.', unlit), 15%
+
+
 #  Since there are no stairs, this forces the hero's initial placement
 TELEPORT_REGION:(69,16,69,16),(0,0,0,0)
+TERRAIN:(69,16),'.'
 PORTAL:(0,0,75,19),(65,13,75,19),"air"
 #  Some helpful monsters.  Making sure a
 #  pick axe and at least one wand of digging
 #  are available.
-MONSTER:'@',"Elvenking",(67,16)
-MONSTER:'H',"minotaur",(67,14)
+MONSTER:('@',"Elvenking"),(67,16)
+MONSTER:('H',"minotaur"),(67,14)
 #  An assortment of earth-appropriate nasties
 #  in each cavern.
-MONSTER:'E',"earth elemental",(52,13),hostile
-MONSTER:'E',"earth elemental",(53,13),hostile
-MONSTER:'T',"rock troll",(53,12)
-MONSTER:'H',"stone giant",(54,12)
+MONSTER:('E',"earth elemental"),(52,13),hostile
+MONSTER:('E',"earth elemental"),(53,13),hostile
+MONSTER:('T',"rock troll"),(53,12)
+MONSTER:('H',"stone giant"),(54,12)
 #
-MONSTER:'S',"pit viper",(70,05)
-MONSTER:'&',"barbed devil",(69,06)
-MONSTER:'H',"stone giant",(69,08)
-MONSTER:''',"stone golem",(71,08)
-MONSTER:'&',"pit fiend",(70,09)
-MONSTER:'E',"earth elemental",(70,08),hostile
+MONSTER:('S',"pit viper"),(70,05)
+MONSTER:('&',"barbed devil"),(69,06)
+MONSTER:('H',"stone giant"),(69,08)
+MONSTER:(''',"stone golem"),(71,08)
+MONSTER:('&',"pit fiend"),(70,09)
+MONSTER:('E',"earth elemental"),(70,08),hostile
 #
-MONSTER:'E',"earth elemental",(60,03),hostile
-MONSTER:'H',"stone giant",(61,04)
-MONSTER:'E',"earth elemental",(62,04),hostile
-MONSTER:'E',"earth elemental",(61,05),hostile
-MONSTER:'s',"scorpion",(62,05)
-MONSTER:'p',"rock piercer",(63,05)
+MONSTER:('E',"earth elemental"),(60,03),hostile
+MONSTER:('H',"stone giant"),(61,04)
+MONSTER:('E',"earth elemental"),(62,04),hostile
+MONSTER:('E',"earth elemental"),(61,05),hostile
+MONSTER:('s',"scorpion"),(62,05)
+MONSTER:('p',"rock piercer"),(63,05)
 #
-MONSTER:'U',"umber hulk",(40,05)
-MONSTER:'v',"dust vortex",(42,05)
-MONSTER:'T',"rock troll",(38,06)
-MONSTER:'E',"earth elemental",(39,06),hostile
-MONSTER:'E',"earth elemental",(41,06),hostile
-MONSTER:'E',"earth elemental",(38,07),hostile
-MONSTER:'H',"stone giant",(39,07)
-MONSTER:'E',"earth elemental",(43,07),hostile
-MONSTER:''',"stone golem",(37,08)
-MONSTER:'S',"pit viper",(43,08)
-MONSTER:'S',"pit viper",(43,09)
-MONSTER:'T',"rock troll",(44,10)
+MONSTER:('U',"umber hulk"),(40,05)
+MONSTER:('v',"dust vortex"),(42,05)
+MONSTER:('T',"rock troll"),(38,06)
+MONSTER:('E',"earth elemental"),(39,06),hostile
+MONSTER:('E',"earth elemental"),(41,06),hostile
+MONSTER:('E',"earth elemental"),(38,07),hostile
+MONSTER:('H',"stone giant"),(39,07)
+MONSTER:('E',"earth elemental"),(43,07),hostile
+MONSTER:(''',"stone golem"),(37,08)
+MONSTER:('S',"pit viper"),(43,08)
+MONSTER:('S',"pit viper"),(43,09)
+MONSTER:('T',"rock troll"),(44,10)
 #
-MONSTER:'E',"earth elemental",(02,01),hostile
-MONSTER:'E',"earth elemental",(03,01),hostile
-MONSTER:''',"stone golem",(01,02)
-MONSTER:'E',"earth elemental",(02,02),hostile
-MONSTER:'T',"rock troll",(04,03)
-MONSTER:'T',"rock troll",(03,03)
-MONSTER:'&',"pit fiend",(03,04)
-MONSTER:'E',"earth elemental",(04,05),hostile
-MONSTER:'S',"pit viper",(05,06)
+MONSTER:('E',"earth elemental"),(02,01),hostile
+MONSTER:('E',"earth elemental"),(03,01),hostile
+MONSTER:(''',"stone golem"),(01,02)
+MONSTER:('E',"earth elemental"),(02,02),hostile
+MONSTER:('T',"rock troll"),(04,03)
+MONSTER:('T',"rock troll"),(03,03)
+MONSTER:('&',"pit fiend"),(03,04)
+MONSTER:('E',"earth elemental"),(04,05),hostile
+MONSTER:('S',"pit viper"),(05,06)
 #
-MONSTER:'E',"earth elemental",(21,02),hostile
-MONSTER:'E',"earth elemental",(21,03),hostile
-MONSTER:'H',"minotaur",(21,04)
-MONSTER:'E',"earth elemental",(21,05),hostile
-MONSTER:'T',"rock troll",(22,05)
-MONSTER:'E',"earth elemental",(22,06),hostile
-MONSTER:'E',"earth elemental",(23,06),hostile
+MONSTER:('E',"earth elemental"),(21,02),hostile
+MONSTER:('E',"earth elemental"),(21,03),hostile
+MONSTER:('H',"minotaur"),(21,04)
+MONSTER:('E',"earth elemental"),(21,05),hostile
+MONSTER:('T',"rock troll"),(22,05)
+MONSTER:('E',"earth elemental"),(22,06),hostile
+MONSTER:('E',"earth elemental"),(23,06),hostile
 #
-MONSTER:'S',"pit viper",(14,08)
-MONSTER:'&',"barbed devil",(14,09)
-MONSTER:'E',"earth elemental",(13,10),hostile
-MONSTER:'T',"rock troll",(12,11)
-MONSTER:'E',"earth elemental",(14,12),hostile
-MONSTER:'E',"earth elemental",(15,13),hostile
-MONSTER:'H',"stone giant",(17,13)
-MONSTER:''',"stone golem",(18,13)
-MONSTER:'&',"pit fiend",(18,12)
-MONSTER:'E',"earth elemental",(18,11),hostile
-MONSTER:'E',"earth elemental",(18,10),hostile
+MONSTER:('S',"pit viper"),(14,08)
+MONSTER:('&',"barbed devil"),(14,09)
+MONSTER:('E',"earth elemental"),(13,10),hostile
+MONSTER:('T',"rock troll"),(12,11)
+MONSTER:('E',"earth elemental"),(14,12),hostile
+MONSTER:('E',"earth elemental"),(15,13),hostile
+MONSTER:('H',"stone giant"),(17,13)
+MONSTER:(''',"stone golem"),(18,13)
+MONSTER:('&',"pit fiend"),(18,12)
+MONSTER:('E',"earth elemental"),(18,11),hostile
+MONSTER:('E',"earth elemental"),(18,10),hostile
 #
-MONSTER:'&',"barbed devil",(02,16)
-MONSTER:'E',"earth elemental",(03,16),hostile
-MONSTER:'T',"rock troll",(02,17)
-MONSTER:'E',"earth elemental",(04,17),hostile
-MONSTER:'E',"earth elemental",(04,18),hostile
+MONSTER:('&',"barbed devil"),(02,16)
+MONSTER:('E',"earth elemental"),(03,16),hostile
+MONSTER:('T',"rock troll"),(02,17)
+MONSTER:('E',"earth elemental"),(04,17),hostile
+MONSTER:('E',"earth elemental"),(04,18),hostile
 
-OBJECT:'`',"boulder",random
+OBJECT:('`',"boulder"),random
 
 
-MAZE:"air",' '
-FLAGS: noteleport,hardfloor,shortsighted
+LEVEL:"air"
+FLAGS: noteleport,hardfloor,shortsighted,mazelevel,stormy
+INIT_MAP:solidfill,' '
 # The following messages are somewhat obtuse, to make then
 # equally meaningful if the player can see or not.
@@ -138,25 +145,29 @@
 # is all "air".
 MAP
-AAAAAAAAAAAAAAAAAAAAAAAACCCCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
-AAAAAAAAAAAAAAAAAAAAAAACCCCCCAAAAAAAACCCCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
-AAAAAAAAAAAAAAAAAAAAACCAACCCCCAAAAAACCCCCCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
-AAAAAAAAAAAAAAAAAAAAACCACCCCCCCAAAAACCCCCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
-AAAAAAAAAAAAAAAAAAAAAACCCCCCCCCCAAAAACCCCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
-AAAAAAAAAAAAAAAAAAAAAAAACCCCAAACCAAACCCCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
-AAAAAAAAAAAAAAAAAAAAAAAAACCCCAAAAAACCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
-AAAAAAAAAAAAAAAAAAAAAAACCCCCCCAAAACCACCCCCCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
-AAAAAAAAAAAAAAAAAAAAAACCCCAAAAAAACCACAACCCCCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACCAACCCCCCCCCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAACCCCAAACCCCCCAAAAAAAAAAAAAAAAAAAAAAAAAAAA
-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAACACACCCCCAAACCCCCCCAAAAAAAAAAAAAAAAAAAAAAAAAAA
-AAAAAAAAAAAAAAAAAAAAAAAAAAAAACAACCCCCCCAAAACCCCCCCAAAAAAAAAAAAAAAAAAAAAAAAAA
-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAACACCCCCCCCAAACCCCCCCCAAAAAAAAAAAAAAAAAAAAAAAAA
-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACCCCCCCCCCAACCCCCCCCAAAAAAAAAAAAAAAAAAAAAAAAA
-AAAAAAAAAAAAAAAAAAAAAAAAAAAAACACCCCCCCCCCACCCCCCCCAAAAAAAAAAAAAAAAAAAAAAAAAA
-AAAAAAAAAAAAAAAAAAAAAAAAAAAAACAACCCCCCCCCCCCCCCCAAAAAAAAAAAAAAAAAAAAAAAAAAAA
-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAACCCCCCAAACCCCCAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
-AAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAACCAAAAAACCCCAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACCCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
 ENDMAP
+
+REPLACE_TERRAIN:(0,0,75,19), 'A', 'C', 35%
+REPLACE_TERRAIN:(25,0,50,19), 'A', 'C', 50%
+
 # Use up and down regions to partition the level into three parts;
 # teleportation can't cross from one part into another.
@@ -167,65 +178,66 @@
 PORTAL:levregion(57,01,78,19),(0,0,0,0),"fire"
 REGION:(00,00,75,19),lit,"ordinary"
-MONSTER:'E',"air elemental",random,hostile
-MONSTER:'E',"air elemental",random,hostile
-MONSTER:'E',"air elemental",random,hostile
-MONSTER:'E',"air elemental",random,hostile
-MONSTER:'E',"air elemental",random,hostile
-MONSTER:'E',"air elemental",random,hostile
-MONSTER:'E',"air elemental",random,hostile
-MONSTER:'E',"air elemental",random,hostile
-MONSTER:'E',"air elemental",random,hostile
-MONSTER:'E',"air elemental",random,hostile
-MONSTER:'E',"air elemental",random,hostile
+MONSTER:('E',"air elemental"),random,hostile
+MONSTER:('E',"air elemental"),random,hostile
+MONSTER:('E',"air elemental"),random,hostile
+MONSTER:('E',"air elemental"),random,hostile
+MONSTER:('E',"air elemental"),random,hostile
+MONSTER:('E',"air elemental"),random,hostile
+MONSTER:('E',"air elemental"),random,hostile
+MONSTER:('E',"air elemental"),random,hostile
+MONSTER:('E',"air elemental"),random,hostile
+MONSTER:('E',"air elemental"),random,hostile
+MONSTER:('E',"air elemental"),random,hostile
 
-MONSTER:'e',"floating eye",random,hostile
-MONSTER:'e',"floating eye",random,hostile
-MONSTER:'e',"floating eye",random,hostile
+MONSTER:('e',"floating eye"),random,hostile
+MONSTER:('e',"floating eye"),random,hostile
+MONSTER:('e',"floating eye"),random,hostile
 
-MONSTER:'y',"yellow light",random,hostile
-MONSTER:'y',"yellow light",random,hostile
-MONSTER:'y',"yellow light",random,hostile
+MONSTER:('y',"yellow light"),random,hostile
+MONSTER:('y',"yellow light"),random,hostile
+MONSTER:('y',"yellow light"),random,hostile
 
-MONSTER:'A',"couatl",random
+MONSTER:('A',"couatl"),random
 
-MONSTER:'D',random,random
-MONSTER:'D',random,random
-MONSTER:'D',random,random
-MONSTER:'D',random,random
-MONSTER:'D',random,random
+MONSTER:'D',random
+MONSTER:'D',random
+MONSTER:'D',random
+MONSTER:'D',random
+MONSTER:'D',random
 
-MONSTER:'E',random,random
-MONSTER:'E',random,random
-MONSTER:'E',random,random
-MONSTER:'J',random,random
-MONSTER:'J',random,random
+MONSTER:'E',random
+MONSTER:'E',random
+MONSTER:'E',random
+MONSTER:'J',random
+MONSTER:'J',random
 
-MONSTER:'&',"djinni",random,hostile
-MONSTER:'&',"djinni",random,hostile
-MONSTER:'&',"djinni",random,hostile
+MONSTER:('&',"djinni"),random,hostile
+MONSTER:('&',"djinni"),random,hostile
+MONSTER:('&',"djinni"),random,hostile
 
-MONSTER:'v',"fog cloud",random,hostile
-MONSTER:'v',"fog cloud",random,hostile
-MONSTER:'v',"fog cloud",random,hostile
-MONSTER:'v',"fog cloud",random,hostile
-MONSTER:'v',"fog cloud",random,hostile
-MONSTER:'v',"fog cloud",random,hostile
-MONSTER:'v',"fog cloud",random,hostile
-MONSTER:'v',"fog cloud",random,hostile
-MONSTER:'v',"fog cloud",random,hostile
-MONSTER:'v',"energy vortex",random,hostile
-MONSTER:'v',"energy vortex",random,hostile
-MONSTER:'v',"energy vortex",random,hostile
-MONSTER:'v',"energy vortex",random,hostile
-MONSTER:'v',"energy vortex",random,hostile
-MONSTER:'v',"steam vortex",random,hostile
-MONSTER:'v',"steam vortex",random,hostile
-MONSTER:'v',"steam vortex",random,hostile
-MONSTER:'v',"steam vortex",random,hostile
-MONSTER:'v',"steam vortex",random,hostile
+MONSTER:('v',"fog cloud"),random,hostile
+MONSTER:('v',"fog cloud"),random,hostile
+MONSTER:('v',"fog cloud"),random,hostile
+MONSTER:('v',"fog cloud"),random,hostile
+MONSTER:('v',"fog cloud"),random,hostile
+MONSTER:('v',"fog cloud"),random,hostile
+MONSTER:('v',"fog cloud"),random,hostile
+MONSTER:('v',"fog cloud"),random,hostile
+MONSTER:('v',"fog cloud"),random,hostile
+MONSTER:('v',"energy vortex"),random,hostile
+MONSTER:('v',"energy vortex"),random,hostile
+MONSTER:('v',"energy vortex"),random,hostile
+MONSTER:('v',"energy vortex"),random,hostile
+MONSTER:('v',"energy vortex"),random,hostile
+MONSTER:('v',"steam vortex"),random,hostile
+MONSTER:('v',"steam vortex"),random,hostile
+MONSTER:('v',"steam vortex"),random,hostile
+MONSTER:('v',"steam vortex"),random,hostile
+MONSTER:('v',"steam vortex"),random,hostile
 
 
-MAZE:"fire",' '
-FLAGS: noteleport,hardfloor,shortsighted
+LEVEL:"fire"
+FLAGS: noteleport,hardfloor,shortsighted,mazelevel
+INIT_MAP:solidfill,' '
 GEOMETRY:center,center
 # The player lands, upon arrival, in the
@@ -256,5 +268,8 @@
 .................................LL....................LL...................
 ENDMAP
+
+REPLACE_TERRAIN:(0,0,75,19), '.', 'L', 30%
 TELEPORT_REGION:(69,16,69,16),(0,0,0,0)
+TERRAIN:(69,16),'.'
 PORTAL:(0,0,75,19),(65,13,75,19),"water"
 
@@ -300,83 +315,84 @@
 TRAP:"fire",random
 #  An assortment of fire-appropriate nasties
-MONSTER:'D',"red dragon",random
-MONSTER:'&',"balrog",random
-MONSTER:'E',"fire elemental",random,hostile
-MONSTER:'E',"fire elemental",random,hostile
-MONSTER:'v',"fire vortex",random
-MONSTER:'d',"hell hound",random
+MONSTER:('D',"red dragon"),random
+MONSTER:('&',"balrog"),random
+MONSTER:('E',"fire elemental"),random,hostile
+MONSTER:('E',"fire elemental"),random,hostile
+MONSTER:('v',"fire vortex"),random
+MONSTER:('d',"hell hound"),random
 #
-MONSTER:'H',"fire giant",random
-MONSTER:'&',"barbed devil",random
-MONSTER:'d',"hell hound",random
-MONSTER:''',"stone golem",random
-MONSTER:'&',"pit fiend",random
-MONSTER:'E',"fire elemental",random,hostile
+MONSTER:('H',"fire giant"),random
+MONSTER:('&',"barbed devil"),random
+MONSTER:('d',"hell hound"),random
+MONSTER:(''',"stone golem"),random
+MONSTER:('&',"pit fiend"),random
+MONSTER:('E',"fire elemental"),random,hostile
 #
-MONSTER:'E',"fire elemental",random,hostile
-MONSTER:'d',"hell hound",random
-MONSTER:'E',"fire elemental",random,hostile
-MONSTER:'E',"fire elemental",random,hostile
-MONSTER:'s',"scorpion",random
-MONSTER:'H',"fire giant",random
+MONSTER:('E',"fire elemental"),random,hostile
+MONSTER:('d',"hell hound"),random
+MONSTER:('E',"fire elemental"),random,hostile
+MONSTER:('E',"fire elemental"),random,hostile
+MONSTER:('s',"scorpion"),random
+MONSTER:('H',"fire giant"),random
 #
-MONSTER:'d',"hell hound",random
-MONSTER:'v',"dust vortex",random
-MONSTER:'v',"fire vortex",random
-MONSTER:'E',"fire elemental",random,hostile
-MONSTER:'E',"fire elemental",random,hostile
-MONSTER:'E',"fire elemental",random,hostile
-MONSTER:'d',"hell hound",random
-MONSTER:'E',"fire elemental",random,hostile
-MONSTER:''',"stone golem",random
-MONSTER:'S',"pit viper",random
-MONSTER:'S',"pit viper",random
-MONSTER:'v',"fire vortex",random
+MONSTER:('d',"hell hound"),random
+MONSTER:('v',"dust vortex"),random
+MONSTER:('v',"fire vortex"),random
+MONSTER:('E',"fire elemental"),random,hostile
+MONSTER:('E',"fire elemental"),random,hostile
+MONSTER:('E',"fire elemental"),random,hostile
+MONSTER:('d',"hell hound"),random
+MONSTER:('E',"fire elemental"),random,hostile
+MONSTER:(''',"stone golem"),random
+MONSTER:('S',"pit viper"),random
+MONSTER:('S',"pit viper"),random
+MONSTER:('v',"fire vortex"),random
 #
-MONSTER:'E',"fire elemental",random,hostile
-MONSTER:'E',"fire elemental",random,hostile
-MONSTER:'H',"fire giant",random
-MONSTER:'E',"fire elemental",random,hostile
-MONSTER:'v',"fire vortex",random
-MONSTER:'v',"fire vortex",random
-MONSTER:'&',"pit fiend",random
-MONSTER:'E',"fire elemental",random,hostile
-MONSTER:'S',"pit viper",random
+MONSTER:('E',"fire elemental"),random,hostile
+MONSTER:('E',"fire elemental"),random,hostile
+MONSTER:('H',"fire giant"),random
+MONSTER:('E',"fire elemental"),random,hostile
+MONSTER:('v',"fire vortex"),random
+MONSTER:('v',"fire vortex"),random
+MONSTER:('&',"pit fiend"),random
+MONSTER:('E',"fire elemental"),random,hostile
+MONSTER:('S',"pit viper"),random
 #
-MONSTER:':',"salamander",random,hostile
-MONSTER:':',"salamander",random,hostile
-MONSTER:'H',"minotaur",random
-MONSTER:':',"salamander",random,hostile
-MONSTER:'v',"steam vortex",random
-MONSTER:':',"salamander",random,hostile
-MONSTER:':',"salamander",random,hostile
+MONSTER:(':',"salamander"),random,hostile
+MONSTER:(':',"salamander"),random,hostile
+MONSTER:('H',"minotaur"),random
+MONSTER:(':',"salamander"),random,hostile
+MONSTER:('v',"steam vortex"),random
+MONSTER:(':',"salamander"),random,hostile
+MONSTER:(':',"salamander"),random,hostile
 #
-MONSTER:'H',"fire giant",random
-MONSTER:'&',"barbed devil",random
-MONSTER:'E',"fire elemental",random,hostile
-MONSTER:'v',"fire vortex",random
-MONSTER:'E',"fire elemental",random,hostile
-MONSTER:'E',"fire elemental",random,hostile
-MONSTER:'d',"hell hound",random
-MONSTER:'H',"fire giant",random
-MONSTER:'&',"pit fiend",random
-MONSTER:'E',"fire elemental",random,hostile
-MONSTER:'E',"fire elemental",random,hostile
+MONSTER:('H',"fire giant"),random
+MONSTER:('&',"barbed devil"),random
+MONSTER:('E',"fire elemental"),random,hostile
+MONSTER:('v',"fire vortex"),random
+MONSTER:('E',"fire elemental"),random,hostile
+MONSTER:('E',"fire elemental"),random,hostile
+MONSTER:('d',"hell hound"),random
+MONSTER:('H',"fire giant"),random
+MONSTER:('&',"pit fiend"),random
+MONSTER:('E',"fire elemental"),random,hostile
+MONSTER:('E',"fire elemental"),random,hostile
 #
-MONSTER:'&',"barbed devil",random
-MONSTER:':',"salamander",random,hostile
-MONSTER:'v',"steam vortex",random
-MONSTER:':',"salamander",random,hostile
-MONSTER:':',"salamander",random,hostile
+MONSTER:('&',"barbed devil"),random
+MONSTER:(':',"salamander"),random,hostile
+MONSTER:('v',"steam vortex"),random
+MONSTER:(':',"salamander"),random,hostile
+MONSTER:(':',"salamander"),random,hostile
 
-OBJECT:'`',"boulder",random
-OBJECT:'`',"boulder",random
-OBJECT:'`',"boulder",random
-OBJECT:'`',"boulder",random
-OBJECT:'`',"boulder",random
+OBJECT:('`',"boulder"),random
+OBJECT:('`',"boulder"),random
+OBJECT:('`',"boulder"),random
+OBJECT:('`',"boulder"),random
+OBJECT:('`',"boulder"),random
 
 
-MAZE:"water",' '
-FLAGS: noteleport,hardfloor,shortsighted
+LEVEL:"water"
+FLAGS: noteleport,hardfloor,shortsighted,mazelevel,shroud
+INIT_MAP:solidfill,' '
 MESSAGE: "You find yourself suspended in an air bubble surrounded by water."
 GEOMETRY:center,center
@@ -411,69 +427,70 @@
 PORTAL:(51,0,75,19),(0,0,0,0),"astral"
 # A fisherman's dream...
-MONSTER:';',"giant eel",random
-MONSTER:';',"giant eel",random
-MONSTER:';',"giant eel",random
-MONSTER:';',"giant eel",random
-MONSTER:';',"giant eel",random
-MONSTER:';',"giant eel",random
-MONSTER:';',"giant eel",random
-MONSTER:';',"giant eel",random
-MONSTER:';',"electric eel",random
-MONSTER:';',"electric eel",random
-MONSTER:';',"electric eel",random
-MONSTER:';',"electric eel",random
-MONSTER:';',"electric eel",random
-MONSTER:';',"electric eel",random
-MONSTER:';',"electric eel",random
-MONSTER:';',"electric eel",random
-MONSTER:';',"kraken",random
-MONSTER:';',"kraken",random
-MONSTER:';',"kraken",random
-MONSTER:';',"kraken",random
-MONSTER:';',"kraken",random
-MONSTER:';',"kraken",random
-MONSTER:';',"kraken",random
-MONSTER:';',"kraken",random
-MONSTER:';',"kraken",random
-MONSTER:';',"shark",random
-MONSTER:';',"shark",random
-MONSTER:';',"shark",random
-MONSTER:';',"shark",random
-MONSTER:';',"piranha",random
-MONSTER:';',"piranha",random
-MONSTER:';',"piranha",random
-MONSTER:';',"piranha",random
-MONSTER:';',"jellyfish",random
-MONSTER:';',"jellyfish",random
-MONSTER:';',"jellyfish",random
-MONSTER:';',"jellyfish",random
-MONSTER:';',random,random
-MONSTER:';',random,random
-MONSTER:';',random,random
-MONSTER:';',random,random
+MONSTER:(';',"giant eel"),random
+MONSTER:(';',"giant eel"),random
+MONSTER:(';',"giant eel"),random
+MONSTER:(';',"giant eel"),random
+MONSTER:(';',"giant eel"),random
+MONSTER:(';',"giant eel"),random
+MONSTER:(';',"giant eel"),random
+MONSTER:(';',"giant eel"),random
+MONSTER:(';',"electric eel"),random
+MONSTER:(';',"electric eel"),random
+MONSTER:(';',"electric eel"),random
+MONSTER:(';',"electric eel"),random
+MONSTER:(';',"electric eel"),random
+MONSTER:(';',"electric eel"),random
+MONSTER:(';',"electric eel"),random
+MONSTER:(';',"electric eel"),random
+MONSTER:(';',"kraken"),random
+MONSTER:(';',"kraken"),random
+MONSTER:(';',"kraken"),random
+MONSTER:(';',"kraken"),random
+MONSTER:(';',"kraken"),random
+MONSTER:(';',"kraken"),random
+MONSTER:(';',"kraken"),random
+MONSTER:(';',"kraken"),random
+MONSTER:(';',"kraken"),random
+MONSTER:(';',"shark"),random
+MONSTER:(';',"shark"),random
+MONSTER:(';',"shark"),random
+MONSTER:(';',"shark"),random
+MONSTER:(';',"piranha"),random
+MONSTER:(';',"piranha"),random
+MONSTER:(';',"piranha"),random
+MONSTER:(';',"piranha"),random
+MONSTER:(';',"jellyfish"),random
+MONSTER:(';',"jellyfish"),random
+MONSTER:(';',"jellyfish"),random
+MONSTER:(';',"jellyfish"),random
+MONSTER:';',random
+MONSTER:';',random
+MONSTER:';',random
+MONSTER:';',random
 # These guys feel like home here
-MONSTER:'E',"water elemental",random,hostile
-MONSTER:'E',"water elemental",random,hostile
-MONSTER:'E',"water elemental",random,hostile
-MONSTER:'E',"water elemental",random,hostile
-MONSTER:'E',"water elemental",random,hostile
-MONSTER:'E',"water elemental",random,hostile
-MONSTER:'E',"water elemental",random,hostile
-MONSTER:'E',"water elemental",random,hostile
-MONSTER:'E',"water elemental",random,hostile
-MONSTER:'E',"water elemental",random,hostile
-MONSTER:'E',"water elemental",random,hostile
-MONSTER:'E',"water elemental",random,hostile
-MONSTER:'E',"water elemental",random,hostile
-MONSTER:'E',"water elemental",random,hostile
-MONSTER:'E',"water elemental",random,hostile
-MONSTER:'E',"water elemental",random,hostile
-MONSTER:'E',"water elemental",random,hostile
-MONSTER:'E',"water elemental",random,hostile
-MONSTER:'E',"water elemental",random,hostile
+MONSTER:('E',"water elemental"),random,hostile
+MONSTER:('E',"water elemental"),random,hostile
+MONSTER:('E',"water elemental"),random,hostile
+MONSTER:('E',"water elemental"),random,hostile
+MONSTER:('E',"water elemental"),random,hostile
+MONSTER:('E',"water elemental"),random,hostile
+MONSTER:('E',"water elemental"),random,hostile
+MONSTER:('E',"water elemental"),random,hostile
+MONSTER:('E',"water elemental"),random,hostile
+MONSTER:('E',"water elemental"),random,hostile
+MONSTER:('E',"water elemental"),random,hostile
+MONSTER:('E',"water elemental"),random,hostile
+MONSTER:('E',"water elemental"),random,hostile
+MONSTER:('E',"water elemental"),random,hostile
+MONSTER:('E',"water elemental"),random,hostile
+MONSTER:('E',"water elemental"),random,hostile
+MONSTER:('E',"water elemental"),random,hostile
+MONSTER:('E',"water elemental"),random,hostile
+MONSTER:('E',"water elemental"),random,hostile
 
 
-MAZE:"astral",' '
-FLAGS: noteleport,hardfloor,nommap,shortsighted
+LEVEL:"astral"
+FLAGS: noteleport,hardfloor,nommap,shortsighted,mazelevel
+INIT_MAP:solidfill,' '
 MESSAGE: "You arrive on the Astral Plane!"
 MESSAGE: "Here the High Temples of the aligned gods are located."
@@ -502,6 +519,23 @@
                              -----------------                             
 ENDMAP
+
+IF [75%] {
+  TERRAIN:fillrect (17,14, 30,18),'.'
+  TERRAIN:fillrect (44,14, 57,18),'.'
+  WALLIFY
+
+  $hall = selection:floodfill(37,18)
+  LOOP [6 + 3d4] {
+    MONSTER:('A',"Angel"),rndcoord($hall),noalign,hostile
+    MONSTER[50%]:random,rndcoord($hall),hostile
+  }
+
+  OBJECT:"brazier",(23,16)
+  OBJECT:"brazier",(51,16)
+}
+
 # Rider locations
-RANDOM_PLACES:(23,9),(37,14),(51,9)
+$place = { (23,9),(37,14),(51,9) }
+SHUFFLE:$place
 # Where the player will land on arrival
 TELEPORT_REGION:(29,15,45,15),(30,15,44,15)
@@ -534,27 +568,29 @@
 # Moloch's horde
 # West round room
-MONSTER:'@',"aligned priest",(18,09),noalign,hostile
-MONSTER:'@',"aligned priest",(19,08),noalign,hostile
-MONSTER:'@',"aligned priest",(19,09),noalign,hostile
-MONSTER:'@',"aligned priest",(19,10),noalign,hostile
-MONSTER:'A',"Angel",(20,09),noalign,hostile
-MONSTER:'A',"Angel",(20,10),noalign,hostile
-MONSTER:'&',"Pestilence",place[0],hostile
+MONSTER:('@',"aligned priest"),(18,09),noalign,hostile
+MONSTER:('@',"aligned priest"),(19,08),noalign,hostile
+MONSTER:('@',"aligned priest"),(19,09),noalign,hostile
+MONSTER:('@',"aligned priest"),(19,10),noalign,hostile
+MONSTER:('A',"Angel"),(20,09),noalign,hostile
+MONSTER:('A',"Angel"),(20,10),noalign,hostile
+MONSTER:('&',"Pestilence"),$place[0],hostile {
+  OBJECT:('!',"sickness")
+}
 # South-central round room
-MONSTER:'@',"aligned priest",(36,12),noalign,hostile
-MONSTER:'@',"aligned priest",(37,12),noalign,hostile
-MONSTER:'@',"aligned priest",(38,12),noalign,hostile
-MONSTER:'@',"aligned priest",(36,13),noalign,hostile
-MONSTER:'A',"Angel",(38,13),noalign,hostile
-MONSTER:'A',"Angel",(37,13),noalign,hostile
-MONSTER:'&',"Death",place[1],hostile
+MONSTER:('@',"aligned priest"),(36,12),noalign,hostile
+MONSTER:('@',"aligned priest"),(37,12),noalign,hostile
+MONSTER:('@',"aligned priest"),(38,12),noalign,hostile
+MONSTER:('@',"aligned priest"),(36,13),noalign,hostile
+MONSTER:('A',"Angel"),(38,13),noalign,hostile
+MONSTER:('A',"Angel"),(37,13),noalign,hostile
+MONSTER:('&',"Death"),$place[1],hostile
 # East round room
-MONSTER:'@',"aligned priest",(56,09),noalign,hostile
-MONSTER:'@',"aligned priest",(55,08),noalign,hostile
-MONSTER:'@',"aligned priest",(55,09),noalign,hostile
-MONSTER:'@',"aligned priest",(55,10),noalign,hostile
-MONSTER:'A',"Angel",(54,09),noalign,hostile
-MONSTER:'A',"Angel",(54,10),noalign,hostile
-MONSTER:'&',"Famine",place[2],hostile
+MONSTER:('@',"aligned priest"),(56,09),noalign,hostile
+MONSTER:('@',"aligned priest"),(55,08),noalign,hostile
+MONSTER:('@',"aligned priest"),(55,09),noalign,hostile
+MONSTER:('@',"aligned priest"),(55,10),noalign,hostile
+MONSTER:('A',"Angel"),(54,09),noalign,hostile
+MONSTER:('A',"Angel"),(54,10),noalign,hostile
+MONSTER:('&',"Famine"),$place[2],hostile
 #
 # The aligned horde
@@ -566,51 +602,51 @@
 #
 # West court
-MONSTER:'@',"aligned priest",(12,07),chaos,hostile
-MONSTER:'@',"aligned priest",(13,07),chaos,peaceful
-MONSTER:'@',"aligned priest",(14,07),law,hostile
-MONSTER:'@',"aligned priest",(12,11),law,peaceful
-MONSTER:'@',"aligned priest",(13,11),neutral,hostile
-MONSTER:'@',"aligned priest",(14,11),neutral,peaceful
-MONSTER:'A',"Angel",(11,05),chaos,hostile
-MONSTER:'A',"Angel",(12,05),chaos,peaceful
-MONSTER:'A',"Angel",(13,05),law,hostile
-MONSTER:'A',"Angel",(11,13),law,peaceful
-MONSTER:'A',"Angel",(12,13),neutral,hostile
-MONSTER:'A',"Angel",(13,13),neutral,peaceful
+MONSTER:('@',"aligned priest"),(12,07),chaos,hostile
+MONSTER:('@',"aligned priest"),(13,07),chaos,peaceful
+MONSTER:('@',"aligned priest"),(14,07),law,hostile
+MONSTER:('@',"aligned priest"),(12,11),law,peaceful
+MONSTER:('@',"aligned priest"),(13,11),neutral,hostile
+MONSTER:('@',"aligned priest"),(14,11),neutral,peaceful
+MONSTER:('A',"Angel"),(11,05),chaos,hostile
+MONSTER:('A',"Angel"),(12,05),chaos,peaceful
+MONSTER:('A',"Angel"),(13,05),law,hostile
+MONSTER:('A',"Angel"),(11,13),law,peaceful
+MONSTER:('A',"Angel"),(12,13),neutral,hostile
+MONSTER:('A',"Angel"),(13,13),neutral,peaceful
 # Central court
-MONSTER:'@',"aligned priest",(32,09),chaos,hostile
-MONSTER:'@',"aligned priest",(33,09),chaos,peaceful
-MONSTER:'@',"aligned priest",(34,09),law,hostile
-MONSTER:'@',"aligned priest",(40,09),law,peaceful
-MONSTER:'@',"aligned priest",(41,09),neutral,hostile
-MONSTER:'@',"aligned priest",(42,09),neutral,peaceful
-MONSTER:'A',"Angel",(31,08),chaos,hostile
-MONSTER:'A',"Angel",(32,08),chaos,peaceful
-MONSTER:'A',"Angel",(31,09),law,hostile
-MONSTER:'A',"Angel",(42,08),law,peaceful
-MONSTER:'A',"Angel",(43,08),neutral,hostile
-MONSTER:'A',"Angel",(43,09),neutral,peaceful
+MONSTER:('@',"aligned priest"),(32,09),chaos,hostile
+MONSTER:('@',"aligned priest"),(33,09),chaos,peaceful
+MONSTER:('@',"aligned priest"),(34,09),law,hostile
+MONSTER:('@',"aligned priest"),(40,09),law,peaceful
+MONSTER:('@',"aligned priest"),(41,09),neutral,hostile
+MONSTER:('@',"aligned priest"),(42,09),neutral,peaceful
+MONSTER:('A',"Angel"),(31,08),chaos,hostile
+MONSTER:('A',"Angel"),(32,08),chaos,peaceful
+MONSTER:('A',"Angel"),(31,09),law,hostile
+MONSTER:('A',"Angel"),(42,08),law,peaceful
+MONSTER:('A',"Angel"),(43,08),neutral,hostile
+MONSTER:('A',"Angel"),(43,09),neutral,peaceful
 # East court
-MONSTER:'@',"aligned priest",(60,07),chaos,hostile
-MONSTER:'@',"aligned priest",(61,07),chaos,peaceful
-MONSTER:'@',"aligned priest",(62,07),law,hostile
-MONSTER:'@',"aligned priest",(60,11),law,peaceful
-MONSTER:'@',"aligned priest",(61,11),neutral,hostile
-MONSTER:'@',"aligned priest",(62,11),neutral,peaceful
-MONSTER:'A',"Angel",(61,05),chaos,hostile
-MONSTER:'A',"Angel",(62,05),chaos,peaceful
-MONSTER:'A',"Angel",(63,05),law,hostile
-MONSTER:'A',"Angel",(61,13),law,peaceful
-MONSTER:'A',"Angel",(62,13),neutral,hostile
-MONSTER:'A',"Angel",(63,13),neutral,peaceful
+MONSTER:('@',"aligned priest"),(60,07),chaos,hostile
+MONSTER:('@',"aligned priest"),(61,07),chaos,peaceful
+MONSTER:('@',"aligned priest"),(62,07),law,hostile
+MONSTER:('@',"aligned priest"),(60,11),law,peaceful
+MONSTER:('@',"aligned priest"),(61,11),neutral,hostile
+MONSTER:('@',"aligned priest"),(62,11),neutral,peaceful
+MONSTER:('A',"Angel"),(61,05),chaos,hostile
+MONSTER:('A',"Angel"),(62,05),chaos,peaceful
+MONSTER:('A',"Angel"),(63,05),law,hostile
+MONSTER:('A',"Angel"),(61,13),law,peaceful
+MONSTER:('A',"Angel"),(62,13),neutral,hostile
+MONSTER:('A',"Angel"),(63,13),neutral,peaceful
 #
 # Assorted nasties
-MONSTER:'L',random,random,hostile
-MONSTER:'L',random,random,hostile
-MONSTER:'L',random,random,hostile
-MONSTER:'V',random,random,hostile
-MONSTER:'V',random,random,hostile
-MONSTER:'V',random,random,hostile
-MONSTER:'D',random,random,hostile
-MONSTER:'D',random,random,hostile
-MONSTER:'D',random,random,hostile
+MONSTER:'L',random,hostile
+MONSTER:'L',random,hostile
+MONSTER:'L',random,hostile
+MONSTER:'V',random,hostile
+MONSTER:'V',random,hostile
+MONSTER:'V',random,hostile
+MONSTER:'D',random,hostile
+MONSTER:'D',random,hostile
+MONSTER:'D',random,hostile
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/dat/functions.des nethack/dat/functions.des
--- nh_orig/dat/functions.des	1969-12-31 19:00:00.000000000 -0500
+++ nethack/dat/functions.des	2009-10-17 10:45:04.637430539 -0400
@@ -0,0 +1,21 @@
+
+FUNCTION soko_loot()
+{
+  # Random objects
+  OBJECT:'%',random,random
+  OBJECT:'%',random,random
+  OBJECT:'%',random,random
+  OBJECT:'%',random,random
+  OBJECT:'=',random,random
+  OBJECT:'/',random,random
+}
+
+FUNCTION soko_prize()
+{
+  IF [50%] {
+    OBJECT:'"',"amulet of reflection",place[0]
+  } ELSE {
+    OBJECT:'(',"bag of holding",place[0]
+  }
+  ENGRAVING:place[0],burn,"Elbereth"
+}
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/dat/gehennom.des nethack/dat/gehennom.des
--- nh_orig/dat/gehennom.des	2003-12-07 18:39:13.000000000 -0500
+++ nethack/dat/gehennom.des	2010-08-16 13:20:13.634708200 -0400
@@ -5,7 +5,10 @@
 #
 
-MAZE: "valley", ' '
-FLAGS: noteleport,hardfloor,nommap
+LEVEL: "valley"
+FLAGS: noteleport,hardfloor,nommap,mazelevel
+INIT_MAP:solidfill,' '
 GEOMETRY:center,center
+#         1         2         3         4         5         6         7
+#123456789012345678901234567890123456789012345678901234567890123456789012345
 MAP
 ----------------------------------------------------------------------------
@@ -13,28 +16,53 @@
 |---|.|.--.---.|  |......--- ----..........-----.-----....---........---.-.|
 |   |.|.|..| |.| --........| |.............|   |.......---| |-...........--|
-|   |...S..| |.| |.......-----.......------|   |--------..---......------- |
-|----------- |.| |-......| |....|...-- |...-----................----       |
-|.....S....---.| |.......| |....|...|  |..............-----------          |
-|.....|.|......| |.....--- |......---  |....---.......|                    |
-|.....|.|------| |....--   --....-- |-------- ----....---------------      |
-|.....|--......---BBB-|     |...--  |.......|    |..................|      |
-|..........||........-|    --...|   |.......|    |...||.............|      |
-|.....|...-||-........------....|   |.......---- |...||.............--     |
+|   |...S..| |.| |.......-----.......------|   |--------..--|......--...-- |
+|----------- |.| |-......| |....|...-- |...-----................----|...|  |
+|.....S....---.| |.......| |....|...|  |..............-----------   |...|  |
+|.....|.|......| |.....--- |......---  |....---.......|            -|...|  |
+|.....|.|------| |....--   --....-- |-------- ----BBBB--------------...--  |
+|.....|--......---BBB-|     |...--  |.......|    |...............B.....|   |
+|..........||........-|    --...|   |.......|    |...||..........B..----   |
+|.....|....||.........------....|   |.......---- |...||..........B..--     |
 |.....|--......---...........--------..........| |.......---------...--    |
 |.....| |------| |--.......--|   |..B......----- -----....| |.|  |....---  |
 |.....| |......--| ------..| |----..B......|       |.--------.-- |-.....---|
-|------ |........|  |.|....| |.....----BBBB---------...........---.........|
-|       |........|  |...|..| |.....|  |-.............--------...........---|
-|       --.....-----------.| |....-----.....----------     |.........----  |
-|        |..|..B...........| |.|..........|.|              |.|........|    |
+|-------|........|  |.|....| |.....----BBBB---------...........---.........|
+||....B.S........|  |...|..| |.....|  |-.............--------...........---|
+||....--|-.....-----------.| |....-----.....----------     |......... ---  |
+||....-  |..|..B...........| |.|..........|.|              |.|........|    |
 ----------------------------------------------------------------------------
 ENDMAP
+
+IF [50%] {
+   TERRAIN:line (50,8)-(53,8), '-'
+   TERRAIN:line (40,8)-(43,8), 'B'
+}
+
+IF [50%] {
+   TERRAIN:(27,12),'|'
+   TERRAIN:line (27,3)-(29,3), 'B'
+   TERRAIN:(28,2), '-'
+}
+
+IF [50%] {
+	TERRAIN:(60,5),'|'
+} ELSE {
+	TERRAIN:line (68,8)-(68,9),'|'
+}
+
+IF [50%] {
+   TERRAIN:line (16,10)-(16,11),'|'
+   TERRAIN:line (9,13)-(14,13), 'B'
+}
+
 # Dungeon Description
 # The shrine to Moloch.
-REGION:(01,06,05,14),lit,"temple"
+REGION:(01,06,05,14),unlit,"temple"
 # The Morgues
 REGION:(19,01,24,08),unlit,"morgue",filled,true
 REGION:(09,14,16,18),unlit,"morgue",filled,true
 REGION:(37,09,43,14),unlit,"morgue",filled,true
+REGION:(50,09,64,11),unlit,"morgue",filled,true
+REGION:(02,16,05,18),unlit,"morgue",filled,true
 # Stairs
 STAIR:(01,01),down
@@ -47,8 +75,13 @@
 DOOR:locked,(08,04)
 DOOR:locked,(06,06)
+DOOR:locked,(08,16)
 
 # The altar of Moloch.
 ALTAR:(03,10),noalign,shrine
 
+# Two sort-of light sources
+OBJECT:('\\',"brazier"),(03,06)
+OBJECT:('\\',"brazier"),(03,14)
+
 # Non diggable walls - everywhere!
 NON_DIGGABLE:(00,00,75,19)
@@ -59,58 +92,73 @@
 #       fate reserved for members of *those* classes.
 #
-OBJECT:'%',"corpse",random,"archeologist",0
-OBJECT:'%',"corpse",random,"archeologist",0
-OBJECT:'%',"corpse",random,"barbarian",0
-OBJECT:'%',"corpse",random,"barbarian",0
-OBJECT:'%',"corpse",random,"caveman",0
-OBJECT:'%',"corpse",random,"cavewoman",0
-OBJECT:'%',"corpse",random,"healer",0
-OBJECT:'%',"corpse",random,"healer",0
-OBJECT:'%',"corpse",random,"knight",0
-OBJECT:'%',"corpse",random,"knight",0
-OBJECT:'%',"corpse",random,"ranger",0
-OBJECT:'%',"corpse",random,"ranger",0
-OBJECT:'%',"corpse",random,"rogue",0
-OBJECT:'%',"corpse",random,"rogue",0
-OBJECT:'%',"corpse",random,"samurai",0
-OBJECT:'%',"corpse",random,"samurai",0
-OBJECT:'%',"corpse",random,"tourist",0
-OBJECT:'%',"corpse",random,"tourist",0
-OBJECT:'%',"corpse",random,"valkyrie",0
-OBJECT:'%',"corpse",random,"valkyrie",0
-OBJECT:'%',"corpse",random,"wizard",0
-OBJECT:'%',"corpse",random,"wizard",0
+OBJECT:('%',"corpse"),random,montype:"archeologist"
+OBJECT:('%',"corpse"),random,montype:"archeologist"
+OBJECT:('%',"corpse"),random,montype:"barbarian"
+OBJECT:('%',"corpse"),random,montype:"barbarian"
+OBJECT:('%',"corpse"),random,montype:"caveman"
+OBJECT:('%',"corpse"),random,montype:"cavewoman"
+OBJECT:('%',"corpse"),random,montype:"healer"
+OBJECT:('%',"corpse"),random,montype:"healer"
+OBJECT:('%',"corpse"),random,montype:"knight"
+OBJECT:('%',"corpse"),random,montype:"knight"
+OBJECT:('%',"corpse"),random,montype:"ranger"
+OBJECT:('%',"corpse"),random,montype:"ranger"
+OBJECT:('%',"corpse"),random,montype:"rogue"
+OBJECT:('%',"corpse"),random,montype:"rogue"
+OBJECT:('%',"corpse"),random,montype:"samurai"
+OBJECT:('%',"corpse"),random,montype:"samurai"
+OBJECT:('%',"corpse"),random,montype:"tourist"
+OBJECT:('%',"corpse"),random,montype:"tourist"
+OBJECT:('%',"corpse"),random,montype:"valkyrie"
+OBJECT:('%',"corpse"),random,montype:"valkyrie"
+OBJECT:('%',"corpse"),random,montype:"wizard"
+OBJECT:('%',"corpse"),random,montype:"wizard"
 #
 # Some random weapons and armor.
 #
-OBJECT:'[',random,random
-OBJECT:'[',random,random
-OBJECT:'[',random,random
-OBJECT:'[',random,random
-OBJECT:')',random,random
-OBJECT:')',random,random
-OBJECT:')',random,random
-OBJECT:')',random,random
+OBJECT:'[',random
+OBJECT:'[',random
+OBJECT:'[',random
+OBJECT:'[',random
+OBJECT:')',random
+OBJECT:')',random
+OBJECT:')',random
+OBJECT:')',random
 #
 # Some random loot.
 #
-OBJECT:'*',"ruby",random
-OBJECT:'*',random,random
-OBJECT:'*',random,random
-OBJECT:'!',random,random
-OBJECT:'!',random,random
-OBJECT:'!',random,random
-OBJECT:'?',random,random
-OBJECT:'?',random,random
-OBJECT:'?',random,random
-OBJECT:'/',random,random
-OBJECT:'/',random,random
-OBJECT:'=',random,random
-OBJECT:'=',random,random
-OBJECT:'+',random,random
-OBJECT:'+',random,random
-OBJECT:'(',random,random
-OBJECT:'(',random,random
-OBJECT:'(',random,random
+OBJECT:('*',"ruby"),random
+OBJECT:'*',random
+OBJECT:'*',random
+OBJECT:'!',random
+OBJECT:'!',random
+OBJECT:'!',random
+OBJECT:'?',random
+OBJECT:'?',random
+OBJECT:'?',random
+OBJECT:'/',random
+OBJECT:'/',random
+OBJECT:'=',random
+OBJECT:'=',random
+OBJECT:'+',random
+OBJECT:'+',random
+OBJECT:'(',random
+OBJECT:'(',random
+OBJECT:'(',random
+#
+# Some less random loot.
+#
+CONTAINER:('(',"iron safe"),(02,18) {
+	OBJECT:('*',"diamond")
+	OBJECT:('*',"diamond")
+	OBJECT:'*'
+	OBJECT:'*'
+	OBJECT:'='
+	OBJECT:'='
+	OBJECT:'+'
+	OBJECT:'+'
+}
+OBJECT:('(',"chest"),(02,17)
+OBJECT:('(',"chest"),(03,18)
 
 # (Not so) Random traps.
@@ -120,6 +168,6 @@
 TRAP:"board", (21,12)
 TRAP:"board", random
-TRAP:"dart", (60,01)
-TRAP:"dart", (26,17)
+TRAP:"magic", (60,01)
+TRAP:"board", (26,17)
 TRAP:"anti magic", random
 TRAP:"anti magic", random
@@ -129,34 +177,34 @@
 # Random monsters.
 # The ghosts.
-MONSTER:' ',"ghost",random
-MONSTER:' ',"ghost",random
-MONSTER:' ',"ghost",random
-MONSTER:' ',"ghost",random
-MONSTER:' ',"ghost",random
-MONSTER:' ',"ghost",random
+MONSTER:(' ',"ghost"),random
+MONSTER:(' ',"ghost"),random
+MONSTER:(' ',"ghost"),random
+MONSTER:(' ',"ghost"),random
+MONSTER:(' ',"ghost"),random
+MONSTER:(' ',"ghost"),random
 # Add a few bats for atmosphere.
-MONSTER:'B',"vampire bat",random
-MONSTER:'B',"vampire bat",random
-MONSTER:'B',"vampire bat",random
+MONSTER:('B',"vampire bat"),random
+MONSTER:('B',"vampire bat"),random
+MONSTER:('B',"vampire bat"),random
 # And a lich for good measure.
-MONSTER:'L',random,random
+MONSTER:'L',random
 # Some undead nasties for good measure
-MONSTER:'V',random,random
-MONSTER:'V',random,random
-MONSTER:'V',random,random
-MONSTER:'Z',random,random
-MONSTER:'Z',random,random
-MONSTER:'Z',random,random
-MONSTER:'Z',random,random
-MONSTER:'M',random,random
-MONSTER:'M',random,random
-MONSTER:'M',random,random
-MONSTER:'M',random,random
+MONSTER:'V',random
+MONSTER:'V',random
+MONSTER:'V',random
+MONSTER:'Z',random
+MONSTER:'Z',random
+MONSTER:'Z',random
+MONSTER:'Z',random
+MONSTER:'M',random
+MONSTER:'M',random
+MONSTER:'M',random
+MONSTER:'M',random
 #
 # The Juiblex level
 #
-MAZE:"juiblex",' '
-FLAGS:noteleport,shortsighted
-INIT_MAP:'.','}',true,true,unlit,false
+LEVEL:"juiblex"
+FLAGS:noteleport,shortsighted,mazelevel
+INIT_MAP:mines,'.','}',true,true,unlit,false
 # guarantee at least one open spot to ensure successful stair placement
 GEOMETRY:left,bottom
@@ -168,5 +216,5 @@
 }}}}}}}}
 ENDMAP
-OBJECT:'`',"boulder",random
+OBJECT:('`',"boulder"),random
 GEOMETRY:right,top
 MAP
@@ -177,5 +225,5 @@
 }}}}}}}}
 ENDMAP
-OBJECT:'`',"boulder",random
+OBJECT:('`',"boulder"),random
 # lair
 GEOMETRY:center,center
@@ -201,6 +249,7 @@
 ENDMAP
 # Random registers
-RANDOM_MONSTERS:'j','b','P','F'
-RANDOM_PLACES:(04,02),(46,02),(04,15),(46,15)
+$monster = MONSTER:{'j','b','P','F'}
+$place = { (04,02),(46,02),(04,15),(46,15) }
+SHUFFLE:$place
 # Dungeon description
 REGION:(00,00,50,17),unlit,"swamp"
@@ -212,55 +261,55 @@
 TELEPORT_REGION:levregion(01,00,11,20),(0,0,50,17),up
 TELEPORT_REGION:levregion(69,00,79,20),(0,0,50,17),down
-FOUNTAIN:place[0]
-MONSTER:'m',"giant mimic",place[1],m_feature "fountain"
-MONSTER:'m',"giant mimic",place[2],m_feature "fountain"
-MONSTER:'m',"giant mimic",place[3],m_feature "fountain"
+FOUNTAIN:$place[0]
+MONSTER:('m',"giant mimic"),$place[1],m_feature "fountain"
+MONSTER:('m',"giant mimic"),$place[2],m_feature "fountain"
+MONSTER:('m',"giant mimic"),$place[3],m_feature "fountain"
 # The demon of the swamp
-MONSTER:'&',"Juiblex",(25,08)
+MONSTER:('&',"Juiblex"),(25,08)
 # And a couple demons
-MONSTER:'i',"lemure",(43,08)
-MONSTER:'i',"lemure",(44,08)
-MONSTER:'i',"lemure",(45,08)
+MONSTER:('i',"lemure"),(43,08)
+MONSTER:('i',"lemure"),(44,08)
+MONSTER:('i',"lemure"),(45,08)
 # Some liquids and gems
-OBJECT:'*',random,(43,06)
-OBJECT:'*',random,(45,06)
-OBJECT:'!',random,(43,09)
-OBJECT:'!',random,(44,09)
-OBJECT:'!',random,(45,09)
+OBJECT:'*',(43,06)
+OBJECT:'*',(45,06)
+OBJECT:'!',(43,09)
+OBJECT:'!',(44,09)
+OBJECT:'!',(45,09)
 # And lots of blobby monsters
-MONSTER:monster[0],random,(25,06)
-MONSTER:monster[1],random,(24,07)
-MONSTER:monster[2],random,(26,07)
-MONSTER:monster[3],random,(23,08)
-MONSTER:monster[3],random,(27,08)
-MONSTER:monster[2],random,(24,09)
-MONSTER:monster[1],random,(26,09)
-MONSTER:monster[0],random,(25,10)
-MONSTER:'j',random,random
-MONSTER:'j',random,random
-MONSTER:'j',random,random
-MONSTER:'j',random,random
-MONSTER:'P',random,random
-MONSTER:'P',random,random
-MONSTER:'P',random,random
-MONSTER:'P',random,random
-MONSTER:'b',random,random
-MONSTER:'b',random,random
-MONSTER:'b',random,random
-MONSTER:'F',random,random
-MONSTER:'F',random,random
-MONSTER:'F',random,random
-MONSTER:'m',random,random
-MONSTER:'m',random,random
-MONSTER:';',"jellyfish",random
-MONSTER:';',"jellyfish",random
+MONSTER:$monster[0],(25,06)
+MONSTER:$monster[1],(24,07)
+MONSTER:$monster[2],(26,07)
+MONSTER:$monster[3],(23,08)
+MONSTER:$monster[3],(27,08)
+MONSTER:$monster[2],(24,09)
+MONSTER:$monster[1],(26,09)
+MONSTER:$monster[0],(25,10)
+MONSTER:'j',random
+MONSTER:'j',random
+MONSTER:'j',random
+MONSTER:'j',random
+MONSTER:'P',random
+MONSTER:'P',random
+MONSTER:'P',random
+MONSTER:'P',random
+MONSTER:'b',random
+MONSTER:'b',random
+MONSTER:'b',random
+MONSTER:'F',random
+MONSTER:'F',random
+MONSTER:'F',random
+MONSTER:'m',random
+MONSTER:'m',random
+MONSTER:(';',"jellyfish"),random
+MONSTER:(';',"jellyfish"),random
 # Some random objects
-OBJECT:'!',random,random
-OBJECT:'!',random,random
-OBJECT:'!',random,random
-OBJECT:'%',random,random
-OBJECT:'%',random,random
-OBJECT:'%',random,random
-OBJECT:'`',"boulder",random
+OBJECT:'!',random
+OBJECT:'!',random
+OBJECT:'!',random
+OBJECT:'%',random
+OBJECT:'%',random
+OBJECT:'%',random
+OBJECT:('`',"boulder"),random
 # Some traps
 TRAP:"sleep gas",random
@@ -273,6 +322,7 @@
 # The Orcus Level
 #
-MAZE:"orcus",random
-FLAGS: noteleport,shortsighted
+LEVEL:"orcus"
+FLAGS: noteleport,shortsighted,mazelevel
+INIT_MAP:mazegrid,'-'
 GEOMETRY:right,center
 # A ghost town
@@ -304,28 +354,33 @@
 TELEPORT_REGION:levregion(01,00,12,20),levregion(20,01,70,20)
 # Wall "ruins"
-OBJECT:'`',"boulder",(19,02)
-OBJECT:'`',"boulder",(20,02)
-OBJECT:'`',"boulder",(21,02)
-OBJECT:'`',"boulder",(36,02)
-OBJECT:'`',"boulder",(36,03)
-OBJECT:'`',"boulder",(06,04)
-OBJECT:'`',"boulder",(05,05)
-OBJECT:'`',"boulder",(06,05)
-OBJECT:'`',"boulder",(07,05)
-OBJECT:'`',"boulder",(39,05)
-OBJECT:'`',"boulder",(08,08)
-OBJECT:'`',"boulder",(09,08)
-OBJECT:'`',"boulder",(10,08)
-OBJECT:'`',"boulder",(11,08)
-OBJECT:'`',"boulder",(06,10)
-OBJECT:'`',"boulder",(05,11)
-OBJECT:'`',"boulder",(06,11)
-OBJECT:'`',"boulder",(07,11)
-OBJECT:'`',"boulder",(21,11)
-OBJECT:'`',"boulder",(21,12)
-OBJECT:'`',"boulder",(13,13)
-OBJECT:'`',"boulder",(14,13)
-OBJECT:'`',"boulder",(15,13)
-OBJECT:'`',"boulder",(14,14)
+OBJECT:('`',"boulder"),(19,02)
+OBJECT:('`',"boulder"),(20,02)
+OBJECT:('`',"boulder"),(21,02)
+OBJECT:('`',"boulder"),(36,02)
+OBJECT:('`',"boulder"),(36,03)
+OBJECT:('`',"boulder"),(06,04)
+OBJECT:('`',"boulder"),(05,05)
+OBJECT:('`',"boulder"),(06,05)
+OBJECT:('`',"boulder"),(07,05)
+OBJECT:('`',"boulder"),(39,05)
+OBJECT:('`',"boulder"),(08,08)
+OBJECT:('`',"boulder"),(09,08)
+OBJECT:('`',"boulder"),(10,08)
+OBJECT:('`',"boulder"),(11,08)
+OBJECT:('`',"boulder"),(06,10)
+OBJECT:('`',"boulder"),(05,11)
+OBJECT:('`',"boulder"),(06,11)
+OBJECT:('`',"boulder"),(07,11)
+OBJECT:('`',"boulder"),(21,11)
+OBJECT:('`',"boulder"),(21,12)
+OBJECT:('`',"boulder"),(13,13)
+OBJECT:('`',"boulder"),(14,13)
+OBJECT:('`',"boulder"),(15,13)
+OBJECT:('`',"boulder"),(14,14)
+# Special rooms
+ALTAR:(24,07),noalign,sanctum
+REGION:(22,12,25,16),unlit,"morgue"
+REGION:(32,09,37,12),lit,"shop"
+REGION:(12,00,15,04),lit,"shop"
 # Doors
 DOOR:closed,(23,02)
@@ -345,9 +400,4 @@
 DOOR:open,(26,14)
 DOOR:closed,(06,15)
-# Special rooms
-ALTAR:(24,07),noalign,sanctum
-REGION:(22,12,25,16),unlit,"morgue"
-REGION:(32,09,37,12),lit,"shop"
-REGION:(12,00,15,04),lit,"shop"
 # Some traps.
 TRAP:"spiked pit", random
@@ -360,59 +410,62 @@
 TRAP:"magic", random
 # Some random objects
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
+OBJECT:random,random
+OBJECT:random,random
+OBJECT:random,random
+OBJECT:random,random
+OBJECT:random,random
+OBJECT:random,random
+OBJECT:random,random
+OBJECT:random,random
+OBJECT:random,random
+OBJECT:random,random
 # The resident nasty
-MONSTER:'&',"Orcus",(33,15)
+MONSTER:('&',"Orcus"),(33,15) {
+  OBJECT:('/',"death")
+}
 # And its preferred companions
-MONSTER:'Z',"human zombie",(32,15)
-MONSTER:' ',"shade",(32,14)
-MONSTER:' ',"shade",(32,16)
-MONSTER:'V',"vampire",(35,16)
-MONSTER:'V',"vampire",(35,14)
-MONSTER:'V',"vampire lord",(36,14)
-MONSTER:'V',"vampire lord",(36,15)
+MONSTER:('Z',"human zombie"),(32,15)
+MONSTER:(' ',"shade"),(32,14)
+MONSTER:(' ',"shade"),(32,16)
+MONSTER:('V',"vampire"),(35,16)
+MONSTER:('V',"vampire"),(35,14)
+MONSTER:('V',"vampire lord"),(36,14)
+MONSTER:('V',"vampire lord"),(36,15)
 # Randomly placed companions
-MONSTER:'Z',"skeleton",random
-MONSTER:'Z',"skeleton",random
-MONSTER:'Z',"skeleton",random
-MONSTER:'Z',"skeleton",random
-MONSTER:'Z',"skeleton",random
-MONSTER:' ',"shade",random
-MONSTER:' ',"shade",random
-MONSTER:' ',"shade",random
-MONSTER:' ',"shade",random
-MONSTER:'Z',"giant zombie",random
-MONSTER:'Z',"giant zombie",random
-MONSTER:'Z',"giant zombie",random
-MONSTER:'Z',"ettin zombie",random
-MONSTER:'Z',"ettin zombie",random
-MONSTER:'Z',"ettin zombie",random
-MONSTER:'Z',"human zombie",random
-MONSTER:'Z',"human zombie",random
-MONSTER:'Z',"human zombie",random
-MONSTER:'V',"vampire",random
-MONSTER:'V',"vampire",random
-MONSTER:'V',"vampire",random
-MONSTER:'V',"vampire lord",random
-MONSTER:'V',"vampire lord",random
+MONSTER:('Z',"skeleton"),random
+MONSTER:('Z',"skeleton"),random
+MONSTER:('Z',"skeleton"),random
+MONSTER:('Z',"skeleton"),random
+MONSTER:('Z',"skeleton"),random
+MONSTER:(' ',"shade"),random
+MONSTER:(' ',"shade"),random
+MONSTER:(' ',"shade"),random
+MONSTER:(' ',"shade"),random
+MONSTER:('Z',"giant zombie"),random
+MONSTER:('Z',"giant zombie"),random
+MONSTER:('Z',"giant zombie"),random
+MONSTER:('Z',"ettin zombie"),random
+MONSTER:('Z',"ettin zombie"),random
+MONSTER:('Z',"ettin zombie"),random
+MONSTER:('Z',"human zombie"),random
+MONSTER:('Z',"human zombie"),random
+MONSTER:('Z',"human zombie"),random
+MONSTER:('V',"vampire"),random
+MONSTER:('V',"vampire"),random
+MONSTER:('V',"vampire"),random
+MONSTER:('V',"vampire lord"),random
+MONSTER:('V',"vampire lord"),random
 # A few more for the party
-MONSTER:random,random,random
-MONSTER:random,random,random
-MONSTER:random,random,random
-MONSTER:random,random,random
-MONSTER:random,random,random
+MONSTER:random,random
+MONSTER:random,random
+MONSTER:random,random
+MONSTER:random,random
+MONSTER:random,random
 #
 # The Asmodeus Level
 #
-MAZE:"asmodeus",random
-FLAGS: noteleport
+LEVEL:"asmodeus"
+FLAGS: noteleport,mazelevel
+INIT_MAP:mazegrid,'-'
 # First part
 GEOMETRY:half-left,center
@@ -446,16 +499,19 @@
 REGION:(01,01,20,10),unlit,"ordinary"
 # The fellow in residence
-MONSTER:'&',"Asmodeus",(12,07)
+MONSTER:('&',"Asmodeus"),(12,07) {
+  OBJECT:('/',"cold")
+  OBJECT:('/',"fire")
+}
 # Some random weapons and armor.
-OBJECT:'[',random,random
-OBJECT:'[',random,random
-OBJECT:')',random,random
-OBJECT:')',random,random
-OBJECT:'*',random,random
-OBJECT:'!',random,random
-OBJECT:'!',random,random
-OBJECT:'?',random,random
-OBJECT:'?',random,random
-OBJECT:'?',random,random
+OBJECT:'[',random
+OBJECT:'[',random
+OBJECT:')',random
+OBJECT:')',random
+OBJECT:'*',random
+OBJECT:'!',random
+OBJECT:'!',random
+OBJECT:'?',random
+OBJECT:'?',random
+OBJECT:'?',random
 # Some traps.
 TRAP:"spiked pit", (05,02)
@@ -467,11 +523,11 @@
 TRAP:"magic", random
 # Random monsters.
-MONSTER:' ',"ghost",(11,07)
-MONSTER:'&',"horned devil",(10,05)
-MONSTER:'L',random,random
+MONSTER:(' ',"ghost"),(11,07)
+MONSTER:('&',"horned devil"),(10,05)
+MONSTER:'L',random
 # Some Vampires for good measure
-MONSTER:'V',random,random
-MONSTER:'V',random,random
-MONSTER:'V',random,random
+MONSTER:'V',random
+MONSTER:'V',random
+MONSTER:'V',random
 # Second part
 GEOMETRY:half-right,center
@@ -487,7 +543,7 @@
 NON_DIGGABLE:(00,00,32,04)
 DOOR:closed,(32,02)
-MONSTER:'&',random,random
-MONSTER:'&',random,random
-MONSTER:'&',random,random
+MONSTER:'&',random
+MONSTER:'&',random
+MONSTER:'&',random
 TRAP:"anti magic", random
 TRAP:"fire", random
@@ -497,21 +553,31 @@
 # The Baalzebub level
 #
-MAZE:"baalz",random
-FLAGS: noteleport
-GEOMETRY:right,center
+LEVEL:"baalz"
+FLAGS: noteleport,mazelevel
+
+MON_GENERATION:80%, (5, 'a'), (1, 'P')
+
+$lvl = selection: fillrect(0,0,78,20)
+$sel = selection: filter(33%, $lvl)
+
+TERRAIN:$lvl, ('.',unlit)
+TERRAIN:$sel, ('}',unlit)
+
+
+GEOMETRY:center,center
 MAP
--------------------------------------------------
-|                    ---               ----      
-|          ----      |   ------------  |         
-| ------      |  --------|..........|---         
-| |....|  -------|...........--------------      
----....|--|..................S............|----  
-....--....S..----------------|............S...|  
----....|--|..................|............|----  
-| |....|  -------|...........-----S--------      
-| ------      |  --------|..........|---         
-|          ----     |    ------------  |         
-|                   ---                ----      
--------------------------------------------------
+xxxxxxxxxxxxxxxxxxxxxxxFxxxxxxxxxxxxxxxxxxFxxxxxx
+xxxxxxxxxxxFxxxxxxxxxFFFxxxxxxxxxxxxxxxFFFFxxxxxx
+xxxxxxxxxxxFFFFxxxxxxFxxx------------xxFxxxxxxxxx
+xxFFFFFFxxxxxxFxx--------|..........|FFFxxxxxxxxx
+xxF....Fxx-------|...........--------------xxxxxx
+---....|--|..................S............|----xx
+....--....S..----------------|............S...|xx
+---....|--|..................|............|----xx
+xxF....Fxx-------|...........-----S--------xxxxxx
+xxFFFFFFxxxxxxFxx--------|..........|FFFxxxxxxxxx
+xxxxxxxxxxxFFFFxxxxxFxxxx------------xxFxxxxxxxxx
+xxxxxxxxxxxFxxxxxxxxFFFxxxxxxxxxxxxxxxxFFFFxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxFxxxxxxxxxxxxxxxxxxFxxxxxx
 ENDMAP
 STAIR:levregion(01,00,15,20),levregion(15,1,70,16),up
@@ -519,19 +585,18 @@
 TELEPORT_REGION:levregion(01,00,15,20),levregion(15,1,70,16)
 NON_DIGGABLE:(00,00,46,12)
-MAZEWALK:(00,06),west
 STAIR:(44,06),down
 # The fellow in residence
-MONSTER:'&',"Baalzebub",(35,06)
+MONSTER:('&',"Baalzebub"),(35,06)
 # Some random weapons and armor.
-OBJECT:'[',random,random
-OBJECT:'[',random,random
-OBJECT:')',random,random
-OBJECT:')',random,random
-OBJECT:'*',random,random
-OBJECT:'!',random,random
-OBJECT:'!',random,random
-OBJECT:'?',random,random
-OBJECT:'?',random,random
-OBJECT:'?',random,random
+OBJECT:'[',random
+OBJECT:'[',random
+OBJECT:')',random
+OBJECT:')',random
+OBJECT:'*',random
+OBJECT:'!',random
+OBJECT:'!',random
+OBJECT:'?',random
+OBJECT:'?',random
+OBJECT:'?',random
 # Some traps.
 TRAP:"spiked pit", random
@@ -539,22 +604,31 @@
 TRAP:"sleep gas", random
 TRAP:"anti magic", random
-TRAP:"fire", random
+TRAP:"rust", random
 TRAP:"magic", random
 TRAP:"magic", random
 # Random monsters.
-MONSTER:' ',"ghost",(37,07)
-MONSTER:'&',"horned devil",(32,05)
-MONSTER:'&',"barbed devil",(38,07)
-MONSTER:'L',random,random
+MONSTER:(' ',"ghost"),(37,07)
+MONSTER:('&',"horned devil"),(32,05)
+MONSTER:('&',"barbed devil"),(38,07)
+MONSTER:'L',random
 # Some Vampires for good measure
-MONSTER:'V',random,random
-MONSTER:'V',random,random
-MONSTER:'V',random,random
+MONSTER:'V',random
+MONSTER:'V',random
+MONSTER:'V',random
+
+LOOP [ 10 + 4d7 ] {
+  MONSTER:'a',random
+  MONSTER[25%]:'P',random
+}
+
 #
 # The Sanctum Level
 #
-MAZE:"sanctum", ' '
-FLAGS: noteleport,hardfloor,nommap
+LEVEL:"sanctum"
+FLAGS: noteleport,hardfloor,nommap,mazelevel
+INIT_MAP:solidfill,' '
 GEOMETRY:center,center
+#         1         2         3         4         5         6         7
+#123456789012345678901234567890123456789012345678901234567890123456789012345
 MAP
 ----------------------------------------------------------------------------
@@ -579,5 +653,7 @@
 ----------------------------------------------------------------------------
 ENDMAP
-REGION:(15,07,21,10),lit,"temple"
+REGION:(15,07,21,10),lit,"temple" {
+  ROOMDOOR:true, locked, north|south|east|west, random
+}
 ALTAR:(18,08),noalign,sanctum
 REGION:(41,06,48,11),unlit,"morgue",filled,true
@@ -591,4 +667,9 @@
 DOOR:closed,(46,12)
 DOOR:closed,(53,10)
+# Some mood lighting
+OBJECT:('\\',"brazier"),(08,09)
+OBJECT:('\\',"brazier"),(18,15)
+OBJECT:('\\',"brazier"),(28,05)
+OBJECT:('\\',"brazier"),(28,13)
 # Surround the temple with fire
 TRAP:"fire",(13,05)
@@ -634,41 +715,144 @@
 TRAP:"magic", random
 # Some random objects
-OBJECT:'[',random,random
-OBJECT:'[',random,random
-OBJECT:'[',random,random
-OBJECT:'[',random,random
-OBJECT:')',random,random
-OBJECT:')',random,random
-OBJECT:'*',random,random
-OBJECT:'!',random,random
-OBJECT:'!',random,random
-OBJECT:'!',random,random
-OBJECT:'!',random,random
-OBJECT:'?',random,random
-OBJECT:'?',random,random
-OBJECT:'?',random,random
-OBJECT:'?',random,random
-OBJECT:'?',random,random
+OBJECT:'[',random
+OBJECT:'[',random
+OBJECT:'[',random
+OBJECT:'[',random
+OBJECT:')',random
+OBJECT:')',random
+OBJECT:'*',random
+OBJECT:'!',random
+OBJECT:'!',random
+OBJECT:'!',random
+OBJECT:'!',random
+OBJECT:'?',random
+OBJECT:'?',random
+OBJECT:'?',random
+OBJECT:'?',random
+OBJECT:'?',random
 # Some monsters.
-MONSTER:'&',"horned devil",(14,12),hostile
-MONSTER:'&',"barbed devil",(18,08),hostile
-MONSTER:'&',"erinys",(10,04),hostile
-MONSTER:'&',"marilith",(07,09),hostile
-MONSTER:'&',"nalfeshnee",(27,08),hostile
+MONSTER:('&',"horned devil"),(14,12),hostile
+MONSTER:('&',"barbed devil"),(18,08),hostile
+MONSTER:('&',"erinys"),(10,04),hostile
+MONSTER:('&',"marilith"),(07,09),hostile
+MONSTER:('&',"nalfeshnee"),(27,08),hostile
 # Moloch's horde
-MONSTER:'@',"aligned priest",(20,03),noalign,hostile
-MONSTER:'@',"aligned priest",(15,04),noalign,hostile
-MONSTER:'@',"aligned priest",(11,05),noalign,hostile
-MONSTER:'@',"aligned priest",(11,07),noalign,hostile
-MONSTER:'@',"aligned priest",(11,09),noalign,hostile
-MONSTER:'@',"aligned priest",(11,12),noalign,hostile
-MONSTER:'@',"aligned priest",(15,13),noalign,hostile
-MONSTER:'@',"aligned priest",(17,13),noalign,hostile
-MONSTER:'@',"aligned priest",(21,13),noalign,hostile
+MONSTER:('@',"aligned priest"),(20,03),noalign,hostile
+MONSTER:('@',"aligned priest"),(15,04),noalign,hostile
+MONSTER:('@',"aligned priest"),(11,05),noalign,hostile
+MONSTER:('@',"aligned priest"),(11,07),noalign,hostile
+MONSTER:('@',"aligned priest"),(11,09),noalign,hostile
+MONSTER:('@',"aligned priest"),(11,12),noalign,hostile
+MONSTER:('@',"aligned priest"),(15,13),noalign,hostile
+MONSTER:('@',"aligned priest"),(17,13),noalign,hostile
+MONSTER:('@',"aligned priest"),(21,13),noalign,hostile
 # A few nasties
-MONSTER:'L',random,random
-MONSTER:'L',random,random
-MONSTER:'V',random,random
-MONSTER:'V',random,random
-MONSTER:'V',random,random
+MONSTER:'L',random
+MONSTER:'L',random
+MONSTER:'V',random
+MONSTER:'V',random
+MONSTER:'V',random
 STAIR:(63,15),up
+
+
+#	The "fill" level for Gehennom
+#
+#	This level is used to fill out any levels not occupied by
+#	specific levels as defined above.
+#
+LEVEL: "hellfill"
+FLAGS:mazelevel,noflip
+INIT_MAP: mines,'.',' ',true,true,unlit,true,'L'
+TELEPORT_REGION:levregion(11,01,59,19),levregion(01,01,02,02)
+NOMAP
+#
+#  always put stairs relatively far apart
+#
+IF [50%] {
+  IF [50%] {
+    # Option 1: Up Left, Down Right
+    STAIR:levregion(01,01,20,20),levregion(40,10,44,12),up
+    STAIR:levregion(50,01,70,20),levregion(45,10,49,12),down
+  } ELSE {
+    # Option 2: Up Right, Down Left
+    STAIR:levregion(50,01,70,20),levregion(45,10,49,12),up
+    STAIR:levregion(01,01,20,20),levregion(40,10,44,12),down
+  }
+} ELSE {
+  IF [50%] {
+  # Option 3: Up Center, Down Elsewhere
+    STAIR:levregion(30,01,50,20),levregion(38,01,42,20),up
+    STAIR:levregion(01,01,70,20),levregion(30,01,50,20),down
+  } ELSE {
+  # Option 4: Down Center, Up Elsewhere
+    STAIR:levregion(01,01,70,20),levregion(30,01,50,20),up
+    STAIR:levregion(30,01,50,20),levregion(38,01,42,20),down
+  }
+}
+#
+$object = OBJECT:{ '(','/','=','+',')','[','?','*','%'}
+OBJECT: $object[0], random
+OBJECT: $object[0], random
+OBJECT: $object[1], random
+OBJECT: $object[2], random
+OBJECT: $object[3], random
+OBJECT: $object[4], random
+OBJECT: random, random
+OBJECT: random, random
+#
+$monster = MONSTER:{ 'V','D',' ','&','Z' }
+MONSTER:$monster[0],random,hostile
+MONSTER:$monster[0],random,hostile
+MONSTER:$monster[1],random,hostile
+MONSTER:$monster[1],random,hostile
+MONSTER:$monster[2],random,hostile
+MONSTER:$monster[3],random,hostile
+MONSTER:random,random,hostile
+MONSTER:'H',random,hostile
+# chance of evil critters
+IF [50%] {
+  MONSTER:'L',random,hostile
+} ELSE {
+  MONSTER:random,random,hostile
+}
+IF [66%] {
+# could be a snark now, so up the percentage a bit
+  MONSTER:'J',random,hostile
+} ELSE {
+  MONSTER:random,random,hostile
+}
+# chance of lava spillage, or maybe lava river?
+IF [50%] {
+	IF [60%] {
+	SPILL: random, 'L', north, 20
+	}
+	IF [60%] {
+	SPILL: random, 'L', south, 20
+	}
+	IF [60%] {
+	SPILL: random, 'L', east, 20
+	}
+	IF [60%] {
+	SPILL: random, 'L', west, 20
+	}
+} ELSE {
+	IF [50%] {
+		TERRAIN: grow(north|west, randline (30,00)-(50,19),10), 'L'
+	} ELSE {
+		TERRAIN: grow(north|west, randline (50,00)-(30,19),10), 'L'
+	}
+}
+
+TRAP: random, random
+TRAP: random, random
+TRAP: random, random
+TRAP: random, random
+TRAP: random, random
+TRAP: random, random
+TRAP: random, random
+TRAP: random, random
+TRAP: random, random
+TRAP: random, random
+TRAP: random, random
+TRAP: random, random
+#
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/dat/Healer.des nethack/dat/Healer.des
--- nh_orig/dat/Healer.des	2003-12-07 18:39:12.000000000 -0500
+++ nethack/dat/Healer.des	2010-08-16 13:20:13.634708200 -0400
@@ -9,6 +9,8 @@
 #	and receive your quest assignment.
 #
-MAZE: "Hea-strt",' '
-FLAGS: noteleport,hardfloor
+LEVEL: "Hea-strt"
+FLAGS: noteleport,hardfloor,mazelevel
+INIT_MAP:solidfill,' '
+MON_GENERATION:86%, (64,"giant rat"), (16,'r'), (16,"snake"), (4,'Y')
 GEOMETRY:center,center
 MAP
@@ -23,5 +25,5 @@
 PPPP..........PPPPP.....|.S.|......-----------|S|.|......PPPPPP.PPP.......PP
 PPPPPP......PPPPPP......|.|.|......|...|......|.|.|.....PPPPPP...PP.......PP
-PPPPPPPPPPPPPPPPPPP.....+.|.|......S.\.S......|.|.+......PPPPPP.PPPP.......P
+PPPPPPPPPPPPPPPPPPP.....+.|.|......S...S......|.|.+......PPPPPP.PPPP.......P
 PPP...PPPPP...PPPP......|.|.|......|...|......|.|.|.......PPPPPPPPPPP.....PP
 PP.....PPP.....PPP......|.|S|-----------......|.S.|......PPPPPPPPPPPPPPPPPPP
@@ -34,4 +36,7 @@
 PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP
 ENDMAP
+
+REPLACE_TERRAIN:(01,01,74,18), 'P', '.', 15%
+
 # Dungeon Description
 REGION:(00,00,75,19),lit,"ordinary"
@@ -56,49 +61,60 @@
 DOOR:locked,(50,10)
 # Hippocrates
-MONSTER:'@',"Hippocrates",(37,10)
+OBJECT:('\',"throne"),(37,10)
+MONSTER:('@',"Hippocrates"),(37,10) {
+  OBJECT:'/'
+  OBJECT:'/'
+  OBJECT:'/'
+  OBJECT:'/'
+  OBJECT:'?'
+  OBJECT:'?'
+  OBJECT:(')',"silver dagger"),1d4
+}
 # The treasure of Hippocrates
-OBJECT:'(',"chest",(37,10)
+OBJECT:('(',"chest"),(37,10)
 # intern guards for the audience chamber
-MONSTER:'@',"attendant",(29,08)
-MONSTER:'@',"attendant",(29,09)
-MONSTER:'@',"attendant",(29,10)
-MONSTER:'@',"attendant",(29,11)
-MONSTER:'@',"attendant",(40,09)
-MONSTER:'@',"attendant",(40,10)
-MONSTER:'@',"attendant",(40,11)
-MONSTER:'@',"attendant",(40,13)
+MONSTER:('@',"attendant"),(29,08) {
+  OBJECT[50%]:random
+}
+MONSTER:('@',"attendant"),(29,09) {
+  OBJECT[50%]:random
+}
+MONSTER:('@',"attendant"),(29,10) {
+  OBJECT[50%]:random
+}
+MONSTER:('@',"attendant"),(29,11) {
+  OBJECT[50%]:random
+}
+MONSTER:('@',"attendant"),(40,09) {
+  OBJECT[50%]:random
+}
+MONSTER:('@',"attendant"),(40,10) {
+  OBJECT[50%]:random
+}
+MONSTER:('@',"attendant"),(40,11) {
+  OBJECT[50%]:random
+}
+MONSTER:('@',"attendant"),(40,13) {
+  OBJECT[50%]:random
+}
 # Non diggable walls
 NON_DIGGABLE:(00,00,75,19)
 # Random traps
+LOOP [5 + 1d3] {
 TRAP:random,random
-TRAP:random,random
-TRAP:random,random
-TRAP:random,random
-TRAP:random,random
-TRAP:random,random
+}
 # Monsters on siege duty.
-MONSTER: 'r',"rabid rat",random
-MONSTER: 'r',"rabid rat",random
-MONSTER: 'r',"rabid rat",random
-MONSTER: 'r',"rabid rat",random
-MONSTER: 'r',"rabid rat",random
-MONSTER: 'r',"rabid rat",random
-MONSTER: 'r',"rabid rat",random
-MONSTER: 'r',"rabid rat",random
-MONSTER: 'r',"rabid rat",random
-MONSTER: 'r',"rabid rat",random
-MONSTER: ';',"giant eel",random
-MONSTER: ';',"shark",random
-MONSTER: ';', random, random
-MONSTER: 'D',random,random,hostile
-MONSTER: 'D',random,random,hostile
-MONSTER: 'D',random,random,hostile
-MONSTER: 'D',random,random,hostile
-MONSTER: 'D',random,random,hostile
-MONSTER: 'S',random,random,hostile
-MONSTER: 'S',random,random,hostile
-MONSTER: 'S',random,random,hostile
-MONSTER: 'S',random,random,hostile
-MONSTER: 'S',random,random,hostile
+LOOP [8 + 1d6] {
+  MONSTER: ('r',"rabid rat"),random
+}
+MONSTER: (';',"giant eel"),random
+MONSTER: (';',"shark"),random
+MONSTER: ';', random
+LOOP [3 + 1d5] {
+  MONSTER: 'D',random,hostile
+}
+LOOP [3 + 1d5] {
+  MONSTER: 'S',random,hostile
+}
 #
 #	The "locate" level for the quest.
@@ -108,8 +124,9 @@
 #
 
-MAZE: "Hea-loca",' '
-FLAGS: hardfloor
+LEVEL: "Hea-loca"
+FLAGS: hardfloor,mazelevel
 #
-INIT_MAP: '.' , 'P', true , true , lit , false
+INIT_MAP: mines, '.' , 'P', true , true , lit , false
+MON_GENERATION:86%, (64,"giant rat"), (16,'r'), (16,"snake"), (4,'Y')
 GEOMETRY:center,center
 MAP
@@ -141,62 +158,29 @@
 ALTAR:(13,05), chaos, shrine
 # Objects
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
+LOOP [10 + 2d5] {
+  OBJECT:random,random
+}
 # Random traps
+LOOP [4 + 2d3] {
 TRAP:random,random
-TRAP:random,random
-TRAP:random,random
-TRAP:random,random
-TRAP:random,random
-TRAP:random,random
+}
 # Random monsters.
-MONSTER:'r',"rabid rat",random
-MONSTER:'r',"rabid rat",random
-MONSTER:'r',"rabid rat",random
-MONSTER:'r',"rabid rat",random
-MONSTER:'r',"rabid rat",random
-MONSTER:'r',"rabid rat",random
-MONSTER:'r',"rabid rat",random
-MONSTER:'r',"rabid rat",random
-MONSTER:'r',random,random,hostile
-MONSTER:';',"giant eel",random
-MONSTER:';',"giant eel",random
-MONSTER:';',"giant eel",random
-MONSTER:';',"giant eel",random
-MONSTER:';',"giant eel",random
-MONSTER:';',"electric eel",random
-MONSTER:';',"electric eel",random
-MONSTER:';',"kraken",random
-MONSTER:';',"shark",random
-MONSTER:';',"shark",random
-MONSTER:';',random, random,hostile
-MONSTER:';',random, random,hostile
-MONSTER: 'D',random,random,hostile
-MONSTER: 'D',random,random,hostile
-MONSTER: 'D',random,random,hostile
-MONSTER: 'D',random,random,hostile
-MONSTER: 'D',random,random,hostile
-MONSTER: 'S',random,random,hostile
-MONSTER: 'S',random,random,hostile
-MONSTER: 'S',random,random,hostile
-MONSTER: 'S',random,random,hostile
-MONSTER: 'S',random,random,hostile
-MONSTER: 'S',random,random,hostile
-MONSTER: 'S',random,random,hostile
-MONSTER: 'S',random,random,hostile
-MONSTER: 'S',random,random,hostile
+LOOP [8 + 2d4] {
+  MONSTER:('r',"rabid rat"),random
+  MONSTER[50%]:(';',"giant eel"),random
+  MONSTER[30%]:(';',"electric eel"),random
+}
+MONSTER:'r',random,hostile
+MONSTER:(';',"kraken"),random
+MONSTER:(';',"shark"),random
+MONSTER:(';',"shark"),random
+MONSTER:';',random, hostile
+MONSTER:';',random, hostile
+LOOP [3 + 1d6] {
+  MONSTER: 'D',random,hostile
+}
+LOOP [8 + 2d3] {
+  MONSTER: 'S',random,hostile
+}
 
 #
@@ -208,7 +192,9 @@
 #
 
-MAZE: "Hea-goal", 'P'
+LEVEL: "Hea-goal"
+FLAGS:mazelevel
 #
-INIT_MAP: '.' , 'P' , false , true , lit , false
+INIT_MAP: mines, '.' , 'P' , false , true , lit , false
+MON_GENERATION:86%, (64,"giant rat"), (16,'r'), (16,"snake"), (4,'Y')
 GEOMETRY:center,center
 MAP
@@ -233,60 +219,38 @@
 NON_DIGGABLE:(00,00,40,11)
 # Objects
-OBJECT:')',"quarterstaff",(20,06),blessed,0,"The Staff of Aesculapius"
-OBJECT:'/',"lightning",(20,06)
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
+OBJECT:(')',"quarterstaff"),(20,06),blessed,0,NAME:"The Staff of Aesculapius"
+OBJECT:('/',"lightning"),(20,06)
+LOOP [10 + 1d5] {
+  OBJECT:random,random
+}
 # Random traps
+LOOP [3 + 2d3] {
 TRAP:random,random
-TRAP:random,random
-TRAP:random,random
-TRAP:random,random
-TRAP:random,random
-TRAP:random,random
+}
 # Random monsters.
-MONSTER:'H',"Cyclops",(20,06),hostile
-MONSTER:'r',"rabid rat",random
-MONSTER:'r',"rabid rat",random
-MONSTER:'r',"rabid rat",random
-MONSTER:'r',random,random,hostile
-MONSTER:'r',random,random,hostile
-MONSTER:';',"giant eel",random
-MONSTER:';',"giant eel",random
-MONSTER:';',"giant eel",random
-MONSTER:';',"giant eel",random
-MONSTER:';',"giant eel",random
-MONSTER:';',"giant eel",random
-MONSTER:';',"electric eel",random
-MONSTER:';',"electric eel",random
-MONSTER:';',"shark",random
-MONSTER:';',"shark",random
-MONSTER:';',random,random,hostile
-MONSTER: 'D',random,random,hostile
-MONSTER: 'D',random,random,hostile
-MONSTER: 'D',random,random,hostile
-MONSTER: 'D',random,random,hostile
-MONSTER: 'D',random,random,hostile
-MONSTER: 'S',random,random,hostile
-MONSTER: 'S',random,random,hostile
-MONSTER: 'S',random,random,hostile
-MONSTER: 'S',random,random,hostile
-MONSTER: 'S',random,random,hostile
-MONSTER: 'S',random,random,hostile
-MONSTER: 'S',random,random,hostile
-MONSTER: 'S',random,random,hostile
-MONSTER: 'S',random,random,hostile
-MONSTER: 'S',random,random,hostile
+MONSTER:('H',"Cyclops"),(20,06),hostile {
+  OBJECT:('(', "Bell of Opening"),uncursed
+  OBJECT:'[',1d3
+}
+MONSTER:('r',"rabid rat"),random
+MONSTER:('r',"rabid rat"),random
+MONSTER:('r',"rabid rat"),random
+MONSTER:'r',random,hostile
+MONSTER:'r',random,hostile
+MONSTER:(';',"giant eel"),random
+MONSTER:(';',"giant eel"),random
+MONSTER:(';',"giant eel"),random
+MONSTER:(';',"giant eel"),random
+MONSTER:(';',"giant eel"),random
+MONSTER:(';',"giant eel"),random
+MONSTER:(';',"electric eel"),random
+MONSTER:(';',"electric eel"),random
+MONSTER:(';',"shark"),random
+MONSTER:(';',"shark"),random
+MONSTER:';',random, hostile
+LOOP [5 + 2d5] {
+  MONSTER[90%]: 'D',random,hostile
+  MONSTER: 'S',random,hostile
+}
 
 #
@@ -299,6 +263,8 @@
 #
 
-MAZE: "Hea-fila" , 'P'
-INIT_MAP: '.' , 'P' , false , true , lit , false
+LEVEL: "Hea-fila"
+FLAGS:mazelevel,noflip
+INIT_MAP: mines, '.' , 'P' , false , true , lit , false
+MON_GENERATION:86%, (64,"giant rat"), (16,'r'), (16,"snake"), (4,'Y')
 NOMAP
 #
@@ -306,34 +272,27 @@
 STAIR: random, down
 #
-OBJECT: random, random, random
-OBJECT: random, random, random
-OBJECT: random, random, random
-OBJECT: random, random, random
-OBJECT: random, random, random
-OBJECT: random, random, random
-OBJECT: random, random, random
-OBJECT: random, random, random
+LOOP [5 + 1d10] {
+  OBJECT: random, random
+}
 #
-MONSTER: 'r', "rabid rat", random
-MONSTER: 'r', random, random,hostile
-MONSTER: 'r', random, random,hostile
-MONSTER: ';', "giant eel", random
-MONSTER: ';', "giant eel", random
-MONSTER: ';', "electric eel", random
-MONSTER: 'D',random,random,hostile
-MONSTER: 'D',random,random,hostile
-MONSTER: 'D',random,random,hostile
-MONSTER: 'D',random,random,hostile
-MONSTER: 'S',random,random,hostile
-MONSTER: 'S',random,random,hostile
-MONSTER: 'S',random,random,hostile
+MONSTER: ('r', "rabid rat"), random
+MONSTER: 'r', random, hostile
+MONSTER: 'r', random, hostile
+MONSTER: (';', "giant eel"), random
+MONSTER: (';', "giant eel"), random
+MONSTER: (';', "electric eel"), random
+LOOP [3 + 1d4] {
+  MONSTER: 'D',random,hostile
+  MONSTER[90%]: 'S',random,hostile
+}
 #
+LOOP [3 + 1d3] {
 TRAP: random, random
-TRAP: random, random
-TRAP: random, random
-TRAP: random, random
+}
 
-MAZE: "Hea-filb" , 'P'
-INIT_MAP: '.' , 'P' , false , true , lit , false
+LEVEL: "Hea-filb"
+FLAGS:mazelevel,noflip
+INIT_MAP: mines, '.' , 'P' , false , true , lit , false
+MON_GENERATION:86%, (64,"giant rat"), (16,'r'), (16,"snake"), (4,'Y')
 NOMAP
 #
@@ -341,37 +300,25 @@
 STAIR: random, down
 #
-OBJECT: random, random, random
-OBJECT: random, random, random
-OBJECT: random, random, random
-OBJECT: random, random, random
-OBJECT: random, random, random
-OBJECT: random, random, random
-OBJECT: random, random, random
-OBJECT: random, random, random
-OBJECT: random, random, random
-OBJECT: random, random, random
-OBJECT: random, random, random
+LOOP [5 + 1d10] {
+  OBJECT: random, random
+}
 #
-MONSTER: 'r', "rabid rat", random
-MONSTER: 'r', "rabid rat", random
-MONSTER: 'r', random, random,hostile
-MONSTER: 'r', random, random,hostile
-MONSTER: ';', "giant eel", random
-MONSTER: ';', "giant eel", random
-MONSTER: ';', "giant eel", random
-MONSTER: ';', "giant eel", random
-MONSTER: ';', "giant eel", random
-MONSTER: ';', "electric eel", random
-MONSTER: ';', "electric eel", random
-MONSTER: 'D',random,random,hostile
-MONSTER: 'D',random,random,hostile
-MONSTER: 'D',random,random,hostile
-MONSTER: 'D',random,random,hostile
-MONSTER: 'S',random,random,hostile
-MONSTER: 'S',random,random,hostile
-MONSTER: 'S',random,random,hostile
+MONSTER: ('r', "rabid rat"), random
+MONSTER: ('r', "rabid rat"), random
+MONSTER: 'r', random, hostile
+MONSTER: 'r', random, hostile
+MONSTER: (';', "giant eel"), random
+MONSTER: (';', "giant eel"), random
+MONSTER: (';', "giant eel"), random
+MONSTER: (';', "giant eel"), random
+MONSTER: (';', "giant eel"), random
+MONSTER: (';', "electric eel"), random
+MONSTER: (';', "electric eel"), random
+LOOP [3 + 1d5] {
+  MONSTER: 'D',random,hostile
+  MONSTER[90%]: 'S',random,hostile
+}
 #
+LOOP [3 + 1d3] {
 TRAP: random, random
-TRAP: random, random
-TRAP: random, random
-TRAP: random, random
+}
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/dat/help nethack/dat/help
--- nh_orig/dat/help	2003-12-07 18:39:13.000000000 -0500
+++ nethack/dat/help	2009-09-08 10:31:12.303292627 -0400
@@ -159,4 +159,6 @@
         *       Tell what equipment you are using; combines the preceding five.
         $       Count your gold pieces.
+        %       Set your chosen ranged weapon; this weapon will be auto-wielded
+                when you attempt to 'f'ire a missile.
         +       List the spells you know; also rearrange them if desired.
         \       Show what types of objects have been discovered.
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/dat/hh nethack/dat/hh
--- nh_orig/dat/hh	2003-12-07 18:39:13.000000000 -0500
+++ nethack/dat/hh	2009-09-08 10:30:53.085295913 -0400
@@ -73,4 +73,5 @@
 *               ask for combination of ),[,=,",( all at once
 $       gold    count your gold
+%       rwield  assign chosen ranged weapon
 +       spells  list the spells you know; also rearrange them if desired
 _       travel  move via a shortest-path algorithm to a point on the map 
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/dat/Knight.des nethack/dat/Knight.des
--- nh_orig/dat/Knight.des	2003-12-07 18:39:12.000000000 -0500
+++ nethack/dat/Knight.des	2010-08-16 13:20:13.635707386 -0400
@@ -9,8 +9,8 @@
 #	and receive your quest assignment.
 #
-MAZE: "Kni-strt",'.'
-FLAGS: noteleport,hardfloor
-# This is a kludge to init the level as a lit field.
-INIT_MAP: '.' , '.' , false , false , lit , false
+LEVEL: "Kni-strt"
+FLAGS: noteleport,hardfloor,mazelevel
+INIT_MAP: solidfill, ('.', lit)
+MON_GENERATION:86%, (64,"quasit"), (16,'i'), (16,"ochre jelly"), (4,'j')
 GEOMETRY:center,center
 MAP
@@ -22,5 +22,5 @@
 ...|.|-----------------|++|-----------------|.|...
 ...|.|.................|..|.........|.......|.|...
-...|.|...\.............+..+.........|.......|.|...
+...|.|.................+..+.........|.......|.|...
 ...|.|.................+..+.........+.......|.|...
 ...|.|.................|..|.........|.......|.|...
@@ -61,19 +61,53 @@
 DOOR:closed,(45,12)
 # King Arthur
-MONSTER:'@',"King Arthur",(09,07)
+OBJECT:('\',"throne"),(09,07)
+MONSTER:('@',"King Arthur"),(09,07) {
+  OBJECT:(')',"silver long sword"),1d4
+  OBJECT:'[',1d3
+}
 # The treasure of King Arthur
-OBJECT:'(',"chest",(09,07)
+OBJECT:('(',"chest"),(09,07)
 # knight guards for the watchrooms
-MONSTER:'@',"knight",(04,02),peaceful
-MONSTER:'@',"knight",(04,13),peaceful
-MONSTER:'@',"knight",(45,02),peaceful
-MONSTER:'@',"knight",(45,13),peaceful
+MONSTER:('@',"knight"),(04,02),peaceful {
+  OBJECT:')'
+  OBJECT:'['
+}
+MONSTER:('@',"knight"),(04,13),peaceful {
+  OBJECT:')'
+  OBJECT:'['
+}
+MONSTER:('@',"knight"),(45,02),peaceful {
+  OBJECT:')'
+  OBJECT:'['
+}
+MONSTER:('@',"knight"),(45,13),peaceful {
+  OBJECT:')'
+  OBJECT:'['
+}
 # page guards for the audience chamber
-MONSTER:'@',"page",(16,06)
-MONSTER:'@',"page",(18,06)
-MONSTER:'@',"page",(20,06)
-MONSTER:'@',"page",(16,09)
-MONSTER:'@',"page",(18,09)
-MONSTER:'@',"page",(20,09)
+MONSTER:('@',"page"),(16,06) {
+  OBJECT:')'
+  OBJECT:'?'
+}
+MONSTER:('@',"page"),(18,06) {
+  OBJECT:'?'
+  OBJECT:'['
+}
+MONSTER:('@',"page"),(20,06) {
+  OBJECT:'?'
+  OBJECT:'['
+}
+MONSTER:('@',"page"),(16,09) {
+  OBJECT:'?'
+  OBJECT:'?'
+}
+MONSTER:('@',"page"),(18,09) {
+  OBJECT:'?'
+  OBJECT:'?'
+}
+MONSTER:('@',"page"),(20,09) {
+  OBJECT:'?'
+  OBJECT:'['
+}
 # Non diggable walls
 NON_DIGGABLE:(00,00,49,15)
@@ -86,16 +120,16 @@
 TRAP:random,random
 # Monsters on siege duty.
-MONSTER: 'i',"quasit",(14,00),hostile
-MONSTER: 'i',"quasit",(16,00),hostile
-MONSTER: 'i',"quasit",(18,00),hostile
-MONSTER: 'i',"quasit",(20,00),hostile
-MONSTER: 'i',"quasit",(22,00),hostile
-MONSTER: 'i',"quasit",(24,00),hostile
-MONSTER: 'i',"quasit",(26,00),hostile
-MONSTER: 'i',"quasit",(28,00),hostile
-MONSTER: 'i',"quasit",(30,00),hostile
-MONSTER: 'i',"quasit",(32,00),hostile
-MONSTER: 'i',"quasit",(34,00),hostile
-MONSTER: 'i',"quasit",(36,00),hostile
+MONSTER: ('i',"quasit"),(14,00),hostile
+MONSTER: ('i',"quasit"),(16,00),hostile
+MONSTER: ('i',"quasit"),(18,00),hostile
+MONSTER: ('i',"quasit"),(20,00),hostile
+MONSTER: ('i',"quasit"),(22,00),hostile
+MONSTER: ('i',"quasit"),(24,00),hostile
+MONSTER: ('i',"quasit"),(26,00),hostile
+MONSTER: ('i',"quasit"),(28,00),hostile
+MONSTER: ('i',"quasit"),(30,00),hostile
+MONSTER: ('i',"quasit"),(32,00),hostile
+MONSTER: ('i',"quasit"),(34,00),hostile
+MONSTER: ('i',"quasit"),(36,00),hostile
 
 #
@@ -106,7 +140,8 @@
 #
 
-MAZE: "Kni-loca",' '
-FLAGS: hardfloor
-INIT_MAP: '.' , 'P' , false , true , lit , false
+LEVEL: "Kni-loca"
+FLAGS: hardfloor,mazelevel
+INIT_MAP: mines, '.' , 'P' , false , true , lit , false
+MON_GENERATION:86%, (64,"quasit"), (16,'i'), (16,"ochre jelly"), (4,'j')
 GEOMETRY:center,center
 MAP
@@ -135,19 +170,7 @@
 ALTAR:(17,05),neutral,shrine
 # Objects
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
+LOOP [10 + 2d5] {
+  OBJECT:random,random
+}
 # Random traps
 # All of the avenues are guarded by magic except for the East.
@@ -201,39 +224,17 @@
 TRAP:"magic",(32,00)
 # Even so, there are magic "sinkholes" around.
+LOOP [5 + 2d6] {
 TRAP:"anti magic",random
-TRAP:"anti magic",random
-TRAP:"anti magic",random
-TRAP:"anti magic",random
-TRAP:"anti magic",random
-TRAP:"anti magic",random
-TRAP:"anti magic",random
+}
 # Random monsters.
-MONSTER:'i',"quasit",random,hostile
-MONSTER:'i',"quasit",random,hostile
-MONSTER:'i',"quasit",random,hostile
-MONSTER:'i',"quasit",random,hostile
-MONSTER:'i',"quasit",random,hostile
-MONSTER:'i',"quasit",random,hostile
-MONSTER:'i',"quasit",random,hostile
-MONSTER:'i',"quasit",random,hostile
-MONSTER:'i',"quasit",random,hostile
-MONSTER:'i',"quasit",random,hostile
-MONSTER:'i',"quasit",random,hostile
-MONSTER:'i',"quasit",random,hostile
-MONSTER:'i',"quasit",random,hostile
-MONSTER:'i',"quasit",random,hostile
-MONSTER:'i',"quasit",random,hostile
-MONSTER:'i',"quasit",random,hostile
-MONSTER:'i',"quasit",random,hostile
-MONSTER:'i',random,random,hostile
-MONSTER:'j',random,random,hostile
-MONSTER:'j',"ochre jelly",random,hostile
-MONSTER:'j',"ochre jelly",random,hostile
-MONSTER:'j',"ochre jelly",random,hostile
-MONSTER:'j',"ochre jelly",random,hostile
-MONSTER:'j',"ochre jelly",random,hostile
-MONSTER:'j',"ochre jelly",random,hostile
-MONSTER:'j',"ochre jelly",random,hostile
-MONSTER:'j',random,random,hostile
+LOOP [10 + 3d8] {
+  MONSTER:('i',"quasit"),random,hostile
+}
+MONSTER:'i',random,hostile
+MONSTER:'j',random,hostile
+LOOP [5 + 2d5] {
+  MONSTER:('j',"ochre jelly"),random,hostile
+}
+MONSTER:'j',random,hostile
 
 #
@@ -245,5 +246,8 @@
 #
 
-MAZE: "Kni-goal", ' '
+LEVEL: "Kni-goal"
+FLAGS:mazelevel
+INIT_MAP:solidfill,' '
+MON_GENERATION:86%, (64,"quasit"), (16,'i'), (16,"ochre jelly"), (4,'j')
 GEOMETRY:center,center
 MAP
@@ -269,4 +273,7 @@
 .......PPPP...                                                              
 ENDMAP
+
+REPLACE_TERRAIN:(00,00,15,19), '.', 'P', 15%
+
 # Dungeon Description
 REGION:(00,00,14,19),lit,"ordinary"
@@ -277,64 +284,45 @@
 NON_DIGGABLE:(00,00,75,19)
 # Objects
-OBJECT:'(',"mirror",(50,06),blessed,0,"The Magic Mirror of Merlin"
-OBJECT:random,random,(33,01)
-OBJECT:random,random,(33,02)
-OBJECT:random,random,(33,03)
-OBJECT:random,random,(33,04)
-OBJECT:random,random,(33,05)
-OBJECT:random,random,(34,01)
-OBJECT:random,random,(34,02)
-OBJECT:random,random,(34,03)
-OBJECT:random,random,(34,04)
-OBJECT:random,random,(34,05)
-OBJECT:random,random,(35,01)
-OBJECT:random,random,(35,02)
-OBJECT:random,random,(35,03)
-OBJECT:random,random,(35,04)
-OBJECT:random,random,(35,05)
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
+OBJECT:('(',"mirror"),(50,06),blessed,0,NAME:"The Magic Mirror of Merlin"
+OBJECT:random,(33,01)
+OBJECT:random,(33,02)
+OBJECT:random,(33,03)
+OBJECT:random,(33,04)
+OBJECT:random,(33,05)
+OBJECT:random,(34,01)
+OBJECT:random,(34,02)
+OBJECT:random,(34,03)
+OBJECT:random,(34,04)
+OBJECT:random,(34,05)
+OBJECT:random,(35,01)
+OBJECT:random,(35,02)
+OBJECT:random,(35,03)
+OBJECT:random,(35,04)
+OBJECT:random,(35,05)
+LOOP [3 + 1d3] {
+  OBJECT:random,random
+}
 # Random traps
 TRAP:"spiked pit",(13,07)
 TRAP:"spiked pit",(12,08)
 TRAP:"spiked pit",(12,09)
+LOOP [2 + 2d2] {
 TRAP:random,random
-TRAP:random,random
-TRAP:random,random
-TRAP:random,random
-TRAP:random,random
+}
 # Random monsters.
-MONSTER:'D',"Ixoth",(50,06),hostile
-MONSTER:'i',"quasit",random,hostile
-MONSTER:'i',"quasit",random,hostile
-MONSTER:'i',"quasit",random,hostile
-MONSTER:'i',"quasit",random,hostile
-MONSTER:'i',"quasit",random,hostile
-MONSTER:'i',"quasit",random,hostile
-MONSTER:'i',"quasit",random,hostile
-MONSTER:'i',"quasit",random,hostile
-MONSTER:'i',"quasit",random,hostile
-MONSTER:'i',"quasit",random,hostile
-MONSTER:'i',"quasit",random,hostile
-MONSTER:'i',"quasit",random,hostile
-MONSTER:'i',"quasit",random,hostile
-MONSTER:'i',"quasit",random,hostile
-MONSTER:'i',"quasit",random,hostile
-MONSTER:'i',"quasit",random,hostile
-MONSTER:'i',random,random,hostile
-MONSTER:'i',random,random,hostile
-MONSTER:'j',"ochre jelly",random,hostile
-MONSTER:'j',"ochre jelly",random,hostile
-MONSTER:'j',"ochre jelly",random,hostile
-MONSTER:'j',"ochre jelly",random,hostile
-MONSTER:'j',"ochre jelly",random,hostile
-MONSTER:'j',"ochre jelly",random,hostile
-MONSTER:'j',"ochre jelly",random,hostile
-MONSTER:'j',"ochre jelly",random,hostile
-MONSTER:'j',random,random,hostile
+MONSTER:('D',"Ixoth"),(50,06),hostile {
+  OBJECT:('(', "Bell of Opening"),uncursed
+  OBJECT:'?'
+  OBJECT:'?'
+}
+LOOP [10 + 3d8] {
+  MONSTER:('i',"quasit"),random,hostile
+}
+MONSTER:'i',random,hostile
+MONSTER:'i',random,hostile
+LOOP [5 + 2d5] {
+  MONSTER:('j',"ochre jelly"),random,hostile
+}
+MONSTER:'j',random,hostile
 
 #
@@ -347,6 +335,8 @@
 #
 
-MAZE: "Kni-fila" , '.'
-INIT_MAP: '.' , 'P' , false , true , lit , false
+LEVEL: "Kni-fila"
+FLAGS:mazelevel,noflip
+INIT_MAP: mines, '.' , 'P' , false , true , lit , false
+MON_GENERATION:86%, (64,"quasit"), (16,'i'), (16,"ochre jelly"), (4,'j')
 NOMAP
 #
@@ -354,27 +344,22 @@
 STAIR: random, down
 #
-OBJECT: random, random, random
-OBJECT: random, random, random
-OBJECT: random, random, random
-OBJECT: random, random, random
-OBJECT: random, random, random
-OBJECT: random, random, random
-OBJECT: random, random, random
-OBJECT: random, random, random
+LOOP [6 + 2d4] {
+  OBJECT: random, random
+}
 #
-MONSTER: 'i', "quasit", random, hostile
-MONSTER: 'i', "quasit", random, hostile
-MONSTER: 'i', "quasit", random, hostile
-MONSTER: 'i', "quasit", random, hostile
-MONSTER: 'i', random, random, hostile
-MONSTER: 'j', "ochre jelly", random, hostile
+LOOP [3 + 1d4] {
+  MONSTER: ('i', "quasit"), random, hostile
+}
+MONSTER: 'i', random, hostile
+MONSTER: ('j', "ochre jelly"), random, hostile
 #
+LOOP [3 + 1d5] {
 TRAP: random, random
-TRAP: random, random
-TRAP: random, random
-TRAP: random, random
+}
 
-MAZE: "Kni-filb" , '.'
-INIT_MAP: '.' , 'P' , false , true , lit , false
+LEVEL: "Kni-filb"
+FLAGS:mazelevel,noflip
+INIT_MAP: mines, '.' , 'P' , false , true , lit , false
+MON_GENERATION:86%, (64,"quasit"), (16,'i'), (16,"ochre jelly"), (4,'j')
 NOMAP
 #
@@ -382,27 +367,17 @@
 STAIR: random, down
 #
-OBJECT: random, random, random
-OBJECT: random, random, random
-OBJECT: random, random, random
-OBJECT: random, random, random
-OBJECT: random, random, random
-OBJECT: random, random, random
-OBJECT: random, random, random
-OBJECT: random, random, random
-OBJECT: random, random, random
-OBJECT: random, random, random
-OBJECT: random, random, random
+LOOP [6 + 2d4] {
+  OBJECT: random, random
+}
 #
-MONSTER: 'i', "quasit", random, hostile
-MONSTER: 'i', "quasit", random, hostile
-MONSTER: 'i', "quasit", random, hostile
-MONSTER: 'i', "quasit", random, hostile
-MONSTER: 'i', random, random, hostile
-MONSTER: 'j', "ochre jelly", random, hostile
-MONSTER: 'j', "ochre jelly", random, hostile
-MONSTER: 'j', "ochre jelly", random, hostile
+LOOP [3 + 1d4] {
+  MONSTER: ('i', "quasit"), random, hostile
+}
+MONSTER: 'i', random, hostile
+LOOP [3 + 1d4] {
+  MONSTER: ('j', "ochre jelly"), random, hostile
+}
 #
+LOOP [3 + 1d5] {
 TRAP: random, random
-TRAP: random, random
-TRAP: random, random
-TRAP: random, random
+}
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/dat/knox.des nethack/dat/knox.des
--- nh_orig/dat/knox.des	2003-12-07 18:39:13.000000000 -0500
+++ nethack/dat/knox.des	2010-04-11 12:36:58.219625888 -0400
@@ -1,9 +1,10 @@
-#	SCCS Id: @(#)knox.des	3.4	1994/08/20
+#	SCCS37 Id: @(#)knox.des	3.4	1994/08/20
 #	Copyright (c) 1989 by Jean-Christophe Collet
 #	Copyright (c) 1992 by Izchak Miller
 # NetHack may be freely redistributed.  See license for details.
 #
-MAZE:"knox",' '
-FLAGS: noteleport
+LEVEL:"knox"
+FLAGS: noteleport,mazelevel
+INIT_MAP:solidfill,' '
 GEOMETRY:center,center
 MAP
@@ -18,5 +19,5 @@
 |     |..........}}}|...............|..........|}}}.................+...|..|
 | -------..........}|...............S..........|}...................|...|..|
-| |.....|..........}|...............|......\...S}...................|...|..|
+| |.....|..........}|...............|..........S}...................|...|..|
 | |.....+........}}}|...............|..........|}}}.................+...|..|
 | |.....|........}---S------------------------S---}.................|...|..|
@@ -34,6 +35,10 @@
 BRANCH:(08,16,08,16),(0,0,0,0)
 #   Throne room, with Croesus on the throne
+OBJECT:('\',"throne"),(43,10)
 REGION:(37,08,46,11),lit,"throne"
-MONSTER:'@',"Croesus",(43,10),hostile
+MONSTER:('@',"Croesus"),(43,10),hostile {
+  OBJECT:(')',"two-handed sword")
+  OBJECT:'['
+}
 #   The Vault
 #   Using unfilled morgue for
@@ -63,42 +68,42 @@
 DOOR:closed,(66,14)
 # Soldiers guarding the fort
-MONSTER:'@',"soldier",(12,14)
-MONSTER:'@',"soldier",(12,13)
-MONSTER:'@',"soldier",(11,10)
-MONSTER:'@',"soldier",(13,02)
-MONSTER:'@',"soldier",(14,03)
-MONSTER:'@',"soldier",(20,02)
-MONSTER:'@',"soldier",(30,02)
-MONSTER:'@',"soldier",(40,02)
-MONSTER:'@',"soldier",(30,16)
-MONSTER:'@',"soldier",(32,16)
-MONSTER:'@',"soldier",(40,16)
-MONSTER:'@',"soldier",(54,16)
-MONSTER:'@',"soldier",(54,14)
-MONSTER:'@',"soldier",(54,13)
-MONSTER:'@',"soldier",(57,10)
-MONSTER:'@',"soldier",(57,09)
-MONSTER:'@',"lieutenant",(15,08)
+MONSTER:('@',"soldier"),(12,14)
+MONSTER:('@',"soldier"),(12,13)
+MONSTER:('@',"soldier"),(11,10)
+MONSTER:('@',"soldier"),(13,02)
+MONSTER:('@',"soldier"),(14,03)
+MONSTER:('@',"soldier"),(20,02)
+MONSTER:('@',"soldier"),(30,02)
+MONSTER:('@',"soldier"),(40,02)
+MONSTER:('@',"soldier"),(30,16)
+MONSTER:('@',"soldier"),(32,16)
+MONSTER:('@',"soldier"),(40,16)
+MONSTER:('@',"soldier"),(54,16)
+MONSTER:('@',"soldier"),(54,14)
+MONSTER:('@',"soldier"),(54,13)
+MONSTER:('@',"soldier"),(57,10)
+MONSTER:('@',"soldier"),(57,09)
+MONSTER:('@',"lieutenant"),(15,08)
 # Four dragons guarding each side
-MONSTER:'D',random,(18,09)
-MONSTER:'D',random,(49,10)
-MONSTER:'D',random,(33,05)
-MONSTER:'D',random,(33,14)
+MONSTER:'D',(18,09)
+MONSTER:'D',(49,10)
+MONSTER:'D',(33,05)
+MONSTER:'D',(33,14)
 # Eels in the moat
-MONSTER:';',"giant eel",(17,08)
-MONSTER:';',"giant eel",(17,11)
-MONSTER:';',"giant eel",(48,08)
-MONSTER:';',"giant eel",(48,11)
+MONSTER:(';',"giant eel"),(17,08)
+MONSTER:(';',"giant eel"),(17,11)
+MONSTER:(';',"giant eel"),(48,08)
+MONSTER:(';',"giant eel"),(48,11)
 # The corner rooms treasures
-OBJECT:'*',"diamond",(19,06)
-OBJECT:'*',"diamond",(20,06)
-OBJECT:'*',"diamond",(21,06)
-OBJECT:'*',"emerald",(19,13)
-OBJECT:'*',"emerald",(20,13)
-OBJECT:'*',"emerald",(21,13)
-OBJECT:'*',"ruby",(46,06)
-OBJECT:'*',"ruby",(47,06)
-OBJECT:'*',"ruby",(48,06)
-OBJECT:'*',"amethyst",(46,13)
-OBJECT:'*',"amethyst",(47,13)
-OBJECT:'*',"amethyst",(48,13)
+OBJECT:('*',"diamond"),(19,06)
+OBJECT:('*',"diamond"),(20,06)
+OBJECT:('*',"diamond"),(21,06)
+OBJECT:('*',"emerald"),(19,13)
+OBJECT:('*',"emerald"),(20,13)
+OBJECT:('*',"emerald"),(21,13)
+OBJECT:('*',"ruby"),(46,06)
+OBJECT:('*',"ruby"),(47,06)
+OBJECT:('*',"ruby"),(48,06)
+OBJECT:('*',"amethyst"),(46,13)
+OBJECT:('*',"amethyst"),(47,13)
+OBJECT:('*',"amethyst"),(48,13)
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/dat/medusa.des nethack/dat/medusa.des
--- nh_orig/dat/medusa.des	2003-12-07 18:39:13.000000000 -0500
+++ nethack/dat/medusa.des	2010-04-11 12:36:58.163626289 -0400
@@ -7,6 +7,7 @@
 #
 
-MAZE:"medusa-1",' '
-FLAGS: noteleport
+LEVEL:"medusa-1"
+FLAGS: noteleport,mazelevel
+INIT_MAP:solidfill,' '
 GEOMETRY:center,center
 MAP
@@ -32,4 +33,7 @@
 }}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}
 ENDMAP
+
+REPLACE_TERRAIN:(01,01,73,18), '}', '.', 5%
+
 # Dungeon Description
 # (must maintain one room definition; `unfilled' forces its room to be kept)
@@ -54,26 +58,27 @@
 NON_DIGGABLE:(30,06,46,13)
 # Objects
-CONTAINER:'`',"statue",(36,10),uncursed,"knight",3,"Perseus"
-OBJECT[75%]:'[',"shield of reflection",contained,cursed,+0
-OBJECT[25%]:'[',"levitation boots",contained,random,+0
-OBJECT[50%]:')',"scimitar",contained,blessed,+2
-OBJECT[50%]:'(',"sack",contained
+CONTAINER:('`',"statue"),(36,10),uncursed,montype:"knight",3,NAME:"Perseus" {
+  OBJECT[25%]:('[',"shield of reflection"),cursed,+0
+  OBJECT[75%]:('[',"levitation boots"),+0
+  OBJECT[50%]:(')',"scimitar"),blessed,+2
+  OBJECT[50%]:('(',"sack")
+}
 # These aren't really containers, but specifying CONTAINER forces them to be
 # empty, since CONTAINERs contain only what is explicitly specified.
-CONTAINER:'`',"statue",random
-CONTAINER:'`',"statue",random
-CONTAINER:'`',"statue",random
-CONTAINER:'`',"statue",random
-CONTAINER:'`',"statue",random
-CONTAINER:'`',"statue",random
-CONTAINER:'`',"statue",random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
+CONTAINER:('`',"statue"),random { }
+CONTAINER:('`',"statue"),random { }
+CONTAINER:('`',"statue"),random { }
+CONTAINER:('`',"statue"),random { }
+CONTAINER:('`',"statue"),random { }
+CONTAINER:('`',"statue"),random { }
+CONTAINER:('`',"statue"),random { }
+OBJECT:random,random
+OBJECT:random,random
+OBJECT:random,random
+OBJECT:random,random
+OBJECT:random,random
+OBJECT:random,random
+OBJECT:random,random
+OBJECT:random,random
 # Random traps
 TRAP:random,random
@@ -85,28 +90,29 @@
 TRAP:"board",(38,12)
 # Random monsters
-MONSTER:'@',"Medusa",(36,10),asleep
-MONSTER:';',"giant eel",(11,06)
-MONSTER:';',"giant eel",(23,13)
-MONSTER:';',"giant eel",(29,02)
-MONSTER:';',"jellyfish",(02,02)
-MONSTER:';',"jellyfish",(00,08)
-MONSTER:';',"jellyfish",(04,18)
-MONSTER:'T',"water troll",(51,03)
-MONSTER:'T',"water troll",(64,11)
-MONSTER:'S',random,(38,07)
-MONSTER:'S',random,(38,12)
-MONSTER:random,random,random
-MONSTER:random,random,random
-MONSTER:random,random,random
-MONSTER:random,random,random
-MONSTER:random,random,random
-MONSTER:random,random,random
-MONSTER:random,random,random
-MONSTER:random,random,random
-MONSTER:random,random,random
-MONSTER:random,random,random
+MONSTER:('@',"Medusa"),(36,10),asleep
+MONSTER:(';',"giant eel"),(11,06)
+MONSTER:(';',"giant eel"),(23,13)
+MONSTER:(';',"giant eel"),(29,02)
+MONSTER:(';',"jellyfish"),(02,02)
+MONSTER:(';',"jellyfish"),(00,08)
+MONSTER:(';',"jellyfish"),(04,18)
+MONSTER:('T',"water troll"),(51,03)
+MONSTER:('T',"water troll"),(64,11)
+MONSTER:'S',(38,07)
+MONSTER:'S',(38,12)
+MONSTER:random,random
+MONSTER:random,random
+MONSTER:random,random
+MONSTER:random,random
+MONSTER:random,random
+MONSTER:random,random
+MONSTER:random,random
+MONSTER:random,random
+MONSTER:random,random
+MONSTER:random,random
 
-MAZE:"medusa-2",' '
-FLAGS: noteleport
+LEVEL:"medusa-2"
+FLAGS: noteleport,mazelevel
+INIT_MAP:solidfill,' '
 GEOMETRY:center,center
 MAP
@@ -132,4 +138,7 @@
 }}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}
 ENDMAP
+
+REPLACE_TERRAIN:(01,01,73,18), '}', '.', 5%
+
 # Dungeon Description
 REGION:(00,00,74,19),lit,"ordinary"
@@ -152,26 +161,27 @@
 NON_DIGGABLE:(60,02,73,17)
 # Objects
-CONTAINER:'`',"statue",(68,10),uncursed,"knight",3,"Perseus"
-OBJECT[25%]:'[',"shield of reflection",contained,cursed,+0
-OBJECT[75%]:'[',"levitation boots",contained,random,+0
-OBJECT[50%]:')',"scimitar",contained,blessed,+2
-OBJECT[50%]:'(',"sack",contained
-CONTAINER:'`',"statue",(64,08)
-CONTAINER:'`',"statue",(65,08)
-CONTAINER:'`',"statue",(64,09)
-CONTAINER:'`',"statue",(65,09)
-CONTAINER:'`',"statue",(64,10)
-CONTAINER:'`',"statue",(65,10)
-CONTAINER:'`',"statue",(64,11)
-CONTAINER:'`',"statue",(65,11)
-OBJECT:'`',"boulder",(04,04)
-OBJECT:'/',random,(52,09)
-OBJECT:'`',"boulder",(52,09)
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
+CONTAINER:('`',"statue"),(68,10),uncursed,montype:"knight",3,NAME:"Perseus" {
+  OBJECT[25%]:('[',"shield of reflection"),cursed,+0
+  OBJECT[75%]:('[',"levitation boots"),+0
+  OBJECT[50%]:(')',"scimitar"),blessed,+2
+  OBJECT[50%]:('(',"sack")
+}
+CONTAINER:('`',"statue"),(64,08) { }
+CONTAINER:('`',"statue"),(65,08) { }
+CONTAINER:('`',"statue"),(64,09) { }
+CONTAINER:('`',"statue"),(65,09) { }
+CONTAINER:('`',"statue"),(64,10) { }
+CONTAINER:('`',"statue"),(65,10) { }
+CONTAINER:('`',"statue"),(64,11) { }
+CONTAINER:('`',"statue"),(65,11) { }
+OBJECT:('`',"boulder"),(04,04)
+OBJECT:'/',(52,09)
+OBJECT:('`',"boulder"),(52,09)
+OBJECT:random,random
+OBJECT:random,random
+OBJECT:random,random
+OBJECT:random,random
+OBJECT:random,random
+OBJECT:random,random
 # Traps
 TRAP:"magic",(03,12)
@@ -181,35 +191,288 @@
 TRAP:random,random
 # Monsters.
-MONSTER:'@',"Medusa",(68,10),asleep
-MONSTER:'g',"gremlin",(02,14)
-MONSTER:'H',"titan",(02,05)
-MONSTER:';',"electric eel",(10,13)
-MONSTER:';',"electric eel",(11,13)
-MONSTER:';',"electric eel",(10,14)
-MONSTER:';',"electric eel",(11,14)
-MONSTER:';',"electric eel",(10,15)
-MONSTER:';',"electric eel",(11,15)
-MONSTER:';',"jellyfish",(01,01)
-MONSTER:';',"jellyfish",(00,08)
-MONSTER:';',"jellyfish",(04,19)
-MONSTER:''',"stone golem",(64,08),asleep
-MONSTER:''',"stone golem",(65,08),asleep
-MONSTER:''',"stone golem",(64,09),asleep
-MONSTER:''',"stone golem",(65,09),asleep
-MONSTER:'S',"cobra",(64,10),asleep
-MONSTER:'S',"cobra",(65,10),asleep
-MONSTER:'A',random,(72,08)
-MONSTER:'y',"yellow light",(72,11),asleep
-MONSTER:random,random,(17,07)
-MONSTER:random,random,(28,11)
-MONSTER:random,random,(32,13)
-MONSTER:random,random,(49,09)
-MONSTER:random,random,(48,07)
-MONSTER:random,random,(65,03)
-MONSTER:random,random,(70,04)
-MONSTER:random,random,(70,15)
-MONSTER:random,random,(65,16)
-MONSTER:random,random,random
-MONSTER:random,random,random
-MONSTER:random,random,random
-MONSTER:random,random,random
+MONSTER:('@',"Medusa"),(68,10),asleep
+MONSTER:('g',"gremlin"),(02,14)
+MONSTER:('H',"titan"),(02,05)
+MONSTER:(';',"electric eel"),(10,13)
+MONSTER:(';',"electric eel"),(11,13)
+MONSTER:(';',"electric eel"),(10,14)
+MONSTER:(';',"electric eel"),(11,14)
+MONSTER:(';',"electric eel"),(10,15)
+MONSTER:(';',"electric eel"),(11,15)
+MONSTER:(';',"jellyfish"),(01,01)
+MONSTER:(';',"jellyfish"),(00,08)
+MONSTER:(';',"jellyfish"),(04,19)
+MONSTER:(''',"stone golem"),(64,08),asleep
+MONSTER:(''',"stone golem"),(65,08),asleep
+MONSTER:(''',"stone golem"),(64,09),asleep
+MONSTER:(''',"stone golem"),(65,09),asleep
+MONSTER:('S',"cobra"),(64,10),asleep
+MONSTER:('S',"cobra"),(65,10),asleep
+MONSTER:'A',(72,08)
+MONSTER:('y',"yellow light"),(72,11),asleep
+MONSTER:random,(17,07)
+MONSTER:random,(28,11)
+MONSTER:random,(32,13)
+MONSTER:random,(49,09)
+MONSTER:random,(48,07)
+MONSTER:random,(65,03)
+MONSTER:random,(70,04)
+MONSTER:random,(70,15)
+MONSTER:random,(65,16)
+MONSTER:random,random
+MONSTER:random,random
+MONSTER:random,random
+MONSTER:random,random
+
+LEVEL:"medusa-3"
+FLAGS: noteleport,mazelevel
+INIT_MAP:solidfill,' '
+GEOMETRY:center,center
+#
+# Here you disturb ravens nesting in the trees.
+#
+MAP
+}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}
+}}}}}}}}}}.}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}.}}}}}}}}}}}}}}}}}}}}}}}}}}}}
+}}}}}}}}T..T.}}}}}}}}}}}}}}}}}}}}..}}}}}}}}.}}}...}}}}}}}.}}}}}......}}}}}}}
+}}}}}}.......T.}}}}}}}}}}}..}}}}..T.}}}}}}...T...T..}}...T..}}..-----..}}}}}
+}}}...-----....}}}}}}}}}}.T..}}}}}...}}}}}.....T..}}}}}......T..|...|.T..}}}
+}}}.T.|...|...T.}}}}}}}.T......}}}}..T..}}.}}}.}}...}}}}}.T.....+...|...}}}}
+}}}}..|...|.}}.}}}}}.....}}}T.}}}}.....}}}}}}.T}}}}}}}}}}}}}..T.|...|.}}}}}}
+}}}}}.|...|.}}}}}}..T..}}}}}}}}}}}}}T.}}}}}}}}..}}}}}}}}}}}.....-----.}}}}}}
+}}}}}.--+--..}}}}}}...}}}}}}}}}}}}}}}}}}}T.}}}}}}}}}}}}}}}}.T.}........}}}}}
+}}}}}.......}}}}}}..}}}}}}}}}.}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}.}}}.}}.T.}}}}}}
+}}.T...T...}}}}T}}}}}}}}}}}....}}}}}}}}}}T}}}}}.T}}...}}}}}}}}}}}}}}...}}}}}
+}}}...T}}}}}}}..}}}}}}}}}}}.T...}}}}}}}}.T.}.T.....T....}}}}}}}}}}}}}.}}}}}}
+}}}}}}}}}}}}}}}....}}}}}}}...}}.}}}}}}}}}}............T..}}}}}.T.}}}}}}}}}}}
+}}}}}}}}}}}}}}}}..T..}}}}}}}}}}}}}}..}}}}}..------+--...T.}}}....}}}}}}}}}}}
+}}}}.}..}}}}}}}.T.....}}}}}}}}}}}..T.}}}}.T.|...|...|....}}}}}.}}}}}...}}}}}
+}}}.T.}...}..}}}}T.T.}}}}}}.}}}}}}}....}}...|...+...|.}}}}}}}}}}}}}..T...}}}
+}}}}..}}}.....}}...}}}}}}}...}}}}}}}}}}}}}T.|...|...|}}}}}}}}}}}....T..}}}}}
+}}}}}..}}}.T..}}}.}}}}}}}}.T..}}}}}}}}}}}}}}---S-----}}}}}}}}}}}}}....}}}}}}
+}}}}}}}}}}}..}}}}}}}}}}}}}}}.}}}}}}}}}}}}}}}}}T..T}}}}}}}}}}}}}}}}}}}}}}}}}}
+}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}
+ENDMAP
+
+REPLACE_TERRAIN:(01,01,73,18), '}', '.', 5%
+
+$place = { (08,06),(66,05),(46,15) }
+SHUFFLE: $place
+REGION:(00,00,74,19),lit,"ordinary"
+REGION:(49,14,51,16),random,"ordinary",unfilled
+REGION:(07,05,09,07),unlit,"ordinary"
+REGION:(65,04,67,06),unlit,"ordinary"
+REGION:(45,14,47,16),unlit,"ordinary"
+# All places are accessible also with jumping, so don't bother
+# restricting the placement when teleporting from levels below this.
+TELEPORT_REGION:(33,02,38,07),(0,0,0,0),down
+STAIR:(32,01,39,07),(0,0,0,0),up
+STAIR:$place[0],down
+DOOR:locked,(08,08)
+DOOR:locked,(64,05)
+DOOR:random,(50,13)
+DOOR:locked,(48,15)
+# 
+FOUNTAIN:$place[1]
+#
+CONTAINER:('`',"statue"),$place[2],uncursed,montype:"knight",3,NAME:"Perseus" {
+  OBJECT[75%]:('[',"shield of reflection"),cursed,+0
+  OBJECT[25%]:('[',"levitation boots"),+0
+  OBJECT[50%]:(')',"scimitar"),blessed,+2
+  OBJECT[50%]:('(',"sack")
+}
+#
+CONTAINER:('`',"statue"),random { }
+CONTAINER:('`',"statue"),random { }
+CONTAINER:('`',"statue"),random { }
+CONTAINER:('`',"statue"),random { }
+CONTAINER:('`',"statue"),random { }
+CONTAINER:('`',"statue"),random { }
+CONTAINER:('`',"statue"),random { }
+OBJECT:random,random
+OBJECT:random,random
+OBJECT:random,random
+OBJECT:random,random
+OBJECT:random,random
+OBJECT:random,random
+OBJECT:random,random
+OBJECT:random,random
+OBJECT:('?',"blank paper"),(48,18)
+OBJECT:('?',"blank paper"),(48,18)
+#
+TRAP:"rust",random
+TRAP:"rust",random
+TRAP:"board",random
+TRAP:"board",random
+TRAP:random,random
+#
+MONSTER:('@',"Medusa"),$place[0]
+MONSTER:(';',"giant eel"),random
+MONSTER:(';',"giant eel"),random
+MONSTER:(';',"jellyfish"),random
+MONSTER:(';',"jellyfish"),random
+MONSTER:('n',"wood nymph"),random
+MONSTER:('n',"wood nymph"),random
+MONSTER:('n',"water nymph"),random
+MONSTER:('n',"water nymph"),random
+MONSTER:('B',"raven"),random,hostile
+MONSTER:('B',"raven"),random,hostile
+MONSTER:('B',"raven"),random,hostile
+MONSTER:('B',"raven"),random,hostile
+MONSTER:('B',"raven"),random,hostile
+MONSTER:('B',"raven"),random,hostile
+MONSTER:('B',"raven"),random,hostile
+MONSTER:('B',"raven"),random,hostile
+MONSTER:('B',"raven"),random,hostile
+MONSTER:('B',"raven"),random,hostile
+MONSTER:('B',"raven"),random,hostile
+MONSTER:('B',"raven"),random,hostile
+MONSTER:('B',"raven"),random,hostile
+MONSTER:('B',"raven"),random,hostile
+MONSTER:('B',"raven"),random,hostile
+MONSTER:('B',"raven"),random,hostile
+MONSTER:('B',"raven"),random,hostile
+MONSTER:('B',"raven"),random,hostile
+MONSTER:('B',"raven"),random,hostile
+MONSTER:('B',"raven"),random,hostile
+MONSTER:('B',"raven"),random,hostile
+MONSTER:('B',"raven"),random,hostile
+MONSTER:('B',"raven"),random,hostile
+MONSTER:('B',"raven"),random,hostile
+MONSTER:('B',"raven"),random,hostile
+MONSTER:('B',"raven"),random,hostile
+MONSTER:('B',"raven"),random,hostile
+MONSTER:('B',"raven"),random,hostile
+MONSTER:('B',"raven"),random,hostile
+MONSTER:('B',"raven"),random,hostile
+
+
+LEVEL:"medusa-4"
+FLAGS: noteleport,mazelevel
+INIT_MAP:solidfill,' '
+GEOMETRY:center,center
+#
+# Here the Medusa rules some slithery monsters from her 'palace', with
+# a yellow dragon nesting in the backyard.
+#
+MAP
+}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}
+}}}}}}}}}}}}}}........}}}}}}}}}}}}}}}}}}}}}}}..}}}.....}}}}}}}}}}}----|}}}}}
+}}}}}}..----------F-.....}}}}}}}}}}}}}}}}..---...}}}}....T.}}}}}}}....|}}}}}
+}}}.....|...F......S}}}}....}}}}}}}...}}.....|}}.}}}}}}}......}}}}|......}}}
+}}}.....+...|..{...|}}}}}}}}}}}}.....}}}}|...|}}}}}}}}}}}.}}}}}}}}----.}}}}}
+}}......|...|......|}}}}}}}}}......}}}}}}|.......}}}}}}}}}}}}}..}}}}}...}}}}
+}}|-+--F|-+--....|F|-|}}}}}....}}}....}}}-----}}.....}}}}}}}......}}}}.}}}}}
+}}|...}}|...|....|}}}|}}}}}}}..}}}}}}}}}}}}}}}}}}}}....}}}}}}}}....T.}}}}}}}
+}}|...}}F...+....F}}}}}}}..}}}}}}}}}}}}}}...}}}}}}}}}}}}}}}}}}}}}}....}}..}}
+}}|...}}|...|....|}}}|}....}}}}}}....}}}...}}}}}...}}}}}}}}}}}}}}}}}.....}}}
+}}--+--F|-+--....-F|-|....}}}}}}}}}}.T...}}}}....---}}}}}}}}}}}}}}}}}}}}}}}}
+}}......|...|......|}}}}}.}}}}}}}}}....}}}}}}}.....|}}}}}}}}}.}}}}}}}}}}}}}}
+}}}}....+...|..{...|.}}}}}}}}}}}}}}}}}}}}}}}}}}.|..|}}}}}}}......}}}}...}}}}
+}}}}}}..|...F......|...}}}}}}}}}}..---}}}}}}}}}}--.-}}}}}....}}}}}}....}}}}}
+}}}}}}}}-----S----F|....}}}}}}}}}|...|}}}}}}}}}}}}...}}}}}}...}}}}}}..}}}}}}
+}}}}}}}}}..............T...}}}}}.|.......}}}}}}}}}}}}}}..}...}.}}}}....}}}}}
+}}}}}}}}}}....}}}}...}...}}}}}.......|.}}}}}}}}}}}}}}.......}}}}}}}}}...}}}}
+}}}}}}}}}}..}}}}}}}}}}.}}}}}}}}}}-..--.}}}}}}}}..}}}}}}..T...}}}..}}}}}}}}}}
+}}}}}}}}}...}}}}}}}}}}}}}}}}}}}}}}}...}}}}}}}....}}}}}}}.}}}..}}}...}}}}}}}}
+}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}.}}}}}}....}}}}}}}}}}}}}}}}}}}...}}}}}}
+}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}
+ENDMAP
+
+REPLACE_TERRAIN:(01,01,73,18), '}', '.', 5%
+
+#
+$place = { (04,08),(10,04),(10,08),(10,12) }
+SHUFFLE: $place
+#
+REGION:(00,00,74,19),lit,"ordinary"
+REGION:(13,03,18,13),lit,"ordinary",unfilled
+#
+TELEPORT_REGION:(64,01,74,17),(0,0,0,0),down
+TELEPORT_REGION:(02,02,18,13),(0,0,0,0),up
+#
+STAIR:(67,01,74,20),(0,0,0,0),up
+STAIR:$place[0],down
+# 
+DOOR:locked,(04,06)
+DOOR:locked,(04,10)
+DOOR:locked,(08,04)
+DOOR:locked,(08,12)
+DOOR:locked,(10,06)
+DOOR:locked,(10,10)
+DOOR:locked,(12,08)
+#
+BRANCH:levregion(27,00,79,20),(0,0,0,0)
+#
+NON_DIGGABLE:(01,01,22,14)
+#
+OBJECT:('(',"crystal ball"),(07,08)
+#
+CONTAINER:('`',"statue"),$place[1],uncursed,montype:"knight",3,NAME:"Perseus" {
+  OBJECT[75%]:('[',"shield of reflection"),cursed,+0
+  OBJECT[25%]:('[',"levitation boots"),+0
+  OBJECT[50%]:(')',"scimitar"),blessed,+2
+  OBJECT[50%]:('(',"sack")
+}
+#
+CONTAINER:('`',"statue"),random { }
+CONTAINER:('`',"statue"),random { }
+CONTAINER:('`',"statue"),random { }
+CONTAINER:('`',"statue"),random { }
+CONTAINER:('`',"statue"),random { }
+CONTAINER:('`',"statue"),random { }
+CONTAINER:('`',"statue"),random { }
+OBJECT:random,random
+OBJECT:random,random
+OBJECT:random,random
+OBJECT:random,random
+OBJECT:random,random
+OBJECT:random,random
+OBJECT:random,random
+OBJECT:random,random
+# 
+TRAP:random,random
+TRAP:random,random
+TRAP:random,random
+TRAP:random,random
+TRAP:random,random
+TRAP:random,random
+TRAP:random,random
+#
+MONSTER:('@',"Medusa"),$place[0]
+MONSTER:(';',"kraken"),(07,07)
+#
+# the nesting dragon
+MONSTER:('D',"yellow dragon"), (05,04), asleep
+MONSTER[50%]:('D',"baby yellow dragon"), (04,04), asleep
+MONSTER[25%]:('D',"baby yellow dragon"), (04,05), asleep
+OBJECT:('%',"egg"), (05,04), montype:"yellow dragon"
+OBJECT[50%]:('%',"egg"), (05,04), montype:"yellow dragon"
+OBJECT[25%]:('%',"egg"), (05,04), montype:"yellow dragon"
+#
+MONSTER:(';',"giant eel"),random
+MONSTER:(';',"giant eel"),random
+MONSTER:(';',"jellyfish"),random
+MONSTER:(';',"jellyfish"),random
+MONSTER:'S',random
+MONSTER:'S',random
+MONSTER:'S',random
+MONSTER:'S',random
+MONSTER:'S',random
+MONSTER:'S',random
+MONSTER:'S',random
+MONSTER:'S',random
+MONSTER:'S',random
+MONSTER:'S',random
+MONSTER:'S',random
+MONSTER:'S',random
+MONSTER:'S',random
+MONSTER:'S',random
+MONSTER:('N',"black naga hatchling"), random
+MONSTER:('N',"black naga hatchling"), random
+MONSTER:('N',"black naga hatchling"), random
+MONSTER:('N',"black naga hatchling"), random
+MONSTER:('N',"black naga"), random
+MONSTER:('N',"black naga"), random
+MONSTER:('N',"black naga"), random
+MONSTER:('N',"black naga"), random
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/dat/mines.des nethack/dat/mines.des
--- nh_orig/dat/mines.des	2003-12-07 18:39:13.000000000 -0500
+++ nethack/dat/mines.des	2010-04-29 10:53:24.172715470 -0400
@@ -10,6 +10,7 @@
 #	specific levels as defined below.
 #
-MAZE: "minefill" , ' '
-INIT_MAP: '.' , ' ' , true , true , random , true
+LEVEL: "minefill"
+FLAGS:mazelevel,noflip
+INIT_MAP: mines, '.' , ' ' , true , true , random , true
 NOMAP
 #
@@ -17,114 +18,154 @@
 STAIR: random, down
 #
-OBJECT: '*', random, random
-OBJECT: '*', random, random
-OBJECT: '*', random, random
-OBJECT: '(', random, random
-OBJECT: random, random, random
-OBJECT: random, random, random
-OBJECT: random, random, random
+OBJECT: '*', random
+OBJECT: '*', random
+OBJECT: '*', random
+OBJECT: '(', random
+LOOP [2d2] {
+  OBJECT: random, random
+}
 #
-MONSTER: 'G', "gnome", random
-MONSTER: 'G', "gnome", random
-MONSTER: 'G', "gnome", random
-MONSTER: 'G', "gnome", random
-MONSTER: 'G', "gnome", random
-MONSTER: 'G', "gnome", random
-MONSTER: 'G', "gnome", random
-MONSTER: 'G', "gnome lord", random
-MONSTER: 'h', "dwarf", random
-MONSTER: 'h', "dwarf", random
-MONSTER: 'G', random, random
-MONSTER: 'G', random, random
-MONSTER: 'h', random, random
+LOOP [4 + 2d5] {
+  MONSTER: ('G', "gnome"), random
+}
+MONSTER: ('G', "gnome lord"), random
+MONSTER: ('h', "dwarf"), random
+MONSTER: ('h', "dwarf"), random
+MONSTER: 'G', random
+MONSTER: 'G', random
+MONSTER: 'h', random
 #
+LOOP [4 + 1d5] {
 TRAP: random, random
-TRAP: random, random
-TRAP: random, random
-TRAP: random, random
-TRAP: random, random
-TRAP: random, random
-
+}
 
 # Minetown variant 1
 # "Frontier Town"
 #
+# A tragic accident has occurred to Frontier Town....
+# 
+# Orcish Town - a variant of Frontier Town that has been
+# overrun by orcs.  Note the barricades (iron bars).
+#
 LEVEL: "minetn-1"
+FLAGS:mazelevel
+INIT_MAP:mines,'.',' ',true,true,random,true
+GEOMETRY:center,center
+MAP
+.....................................
+.----------------F------------------.
+.|.................................|.
+.|.-------------......------------.|.
+.|.|...|...|...|......|..|...|...|.|.
+.F.|...|...|...|......|..|...|...|.|.
+.|.|...|...|...|......|..|...|...|.F.
+.|.|...|...|----......------------.|.
+.|.---------.......................|.
+.|.................................|.
+.|.---------.....--...--...........|.
+.|.|...|...|----.|.....|.---------.|.
+.|.|...|...|...|.|.....|.|..|....|.|.
+.|.|...|...|...|.|.....|.|..|....|.|.
+.|.|...|...|...|.|.....|.|..|....|.|.
+.|.-------------.-------.---------.|.
+.|.................................F.
+.-----------F------------F----------.
+.....................................
+ENDMAP
 
-ROOM: "ordinary" , lit, (3,3), (center,center), (31,15)
-NAME: "town"
-FOUNTAIN: (13, 7)
-FOUNTAIN: (20, 7)
-
-# The Town Watch
-MONSTER: '@', "watchman", random, peaceful
-MONSTER: '@', "watchman", random, peaceful
-MONSTER: '@', "watchman", random, peaceful
-MONSTER: '@', "watchman", random, peaceful
-MONSTER: '@', "watch captain", random, peaceful
-
-SUBROOM: "shop" , lit, (2,2), (3,4), "town"
-CHANCE: 90
-DOOR: false, closed, south, random
-
-SUBROOM: "tool shop", lit, (2,9), (3,4), "town"
-CHANCE: 90
-DOOR: false, closed, north, random
-
-SUBROOM: "ordinary", unlit, (6,2), (3,4), "town"
-DOOR: false, closed, south, random
-
-SUBROOM: "ordinary", lit, (6,9), (3,4), "town"
-DOOR: false, closed, north, random
-
-SUBROOM: "food shop", lit, (10,2), (2,3), "town"
-CHANCE: 90
-DOOR: false, closed, south, random
+# Don't let the player fall into his likely death
+TELEPORT_REGION:levregion(01,01,20,19),levregion(20,00,70,19)
+REGION:(00,00,36,16),lit,"ordinary"
+STAIR:levregion(01,03,20,19),(00,00,36,15),up
+STAIR:levregion(61,03,75,19),(00,00,36,15),down
 
-SUBROOM: "candle shop", lit, (22,2), (3,3), "town"
-DOOR: false, closed, south, random
+# shame we can't make polluted fountains
+FOUNTAIN:(16,09)
+FOUNTAIN:(25,09)
 
-SUBROOM: "ordinary", unlit, (10,10), (2,3), "town"
-DOOR: false, locked, east, random
-MONSTER: 'G', "gnome", random
+# the altar's defiled; useful for BUC but never coaligned
+ALTAR:(20,13),noalign,shrine
 
-SUBROOM: "ordinary", lit, (19,2),  (2,3), "town"
-DOOR: false, locked, west, random
-MONSTER: 'G', "gnome", random
+# set up the shop doors; could be broken down
+DOOR:random,(5,8)
+DOOR:random,(9,8)
+DOOR:random,(13,7)
+DOOR:random,(22,5)
+DOOR:random,(27,7)
+DOOR:random,(31,7)
+DOOR:random,(5,10)
+DOOR:random,(9,10)
+DOOR:random,(15,13)
+DOOR:random,(25,13)
+DOOR:random,(31,11)
 
-SUBROOM: "temple", lit, (15,9), (4,4), "town"
-DOOR: false, closed, north, random
-ALTAR:(02,02),align[0],shrine
-MONSTER: 'G', "gnomish wizard", random
-MONSTER: 'G', "gnomish wizard", random
+# knock a few holes in the shop interior walls
+REPLACE_TERRAIN:(07,04,11,06),'|','.',18%
+REPLACE_TERRAIN:(25,04,29,06),'|','.',18%
+REPLACE_TERRAIN:(07,12,11,14),'|','.',18%
+REPLACE_TERRAIN:(28,12,28,14),'|','.',33%
 
-SUBROOM: "ordinary", lit, (22,10), (2,3), "town"
-DOOR: false, locked, west, random
+# One spot each in most shops...
+$place = { (05,04),(09,05),(13,04),(26,04),(31,05),(30,14),(05,14),(10,13),(26,14),(27,13) }
+SHUFFLE:$place
 
-SUBROOM: "ordinary", lit, (26,2), (3,3), "town"
-DOOR: false, closed, south, random
-MONSTER: 'G', "gnome lord", random
+# scatter some bodies
+OBJECT:('%',"corpse"),(20,12),montype:"aligned priest"
+OBJECT:('%',"corpse"),$place[0],montype:"shopkeeper"
+OBJECT:('%',"corpse"),$place[1],montype:"shopkeeper"
+OBJECT:('%',"corpse"),$place[2],montype:"shopkeeper"
+OBJECT:('%',"corpse"),$place[3],montype:"shopkeeper"
+OBJECT:('%',"corpse"),$place[4],montype:"shopkeeper"
+OBJECT:('%',"corpse"),random,montype:"watchman"
+OBJECT:('%',"corpse"),random,montype:"watchman"
+OBJECT:('%',"corpse"),random,montype:"watchman"
+OBJECT:('%',"corpse"),random,montype:"watchman"
+OBJECT:('%',"corpse"),random,montype:"watch captain"
 
-SUBROOM: "ordinary", unlit, (25,10), (4,3), "town"
-DOOR: false, closed, north, random
+# Rubble!
+LOOP [9 + 2d5] {
+  OBJECT[90%]:('`',"boulder"),random
+  OBJECT:('*',"rock"),random
+}
 
-ROOM: "ordinary" , random, random, random, random
-STAIR: random, up
+# Guarantee 7 candles since we won't have Izchak available
+OBJECT:('(',"wax candle"),$place[0],quantity:1d2
+OBJECT:('(',"wax candle"),$place[1],quantity:2d2
+OBJECT:('(',"wax candle"),$place[2],quantity:1d2
+OBJECT:('(',"tallow candle"),$place[3],quantity:1d3
+OBJECT:('(',"tallow candle"),$place[2],quantity:1d2
+OBJECT:('(',"tallow candle"),$place[0],quantity:1d2
 
-ROOM: "ordinary" , random, random, random, random
-STAIR: random, down
-TRAP: random, random
-MONSTER: 'G', "gnome", random
-MONSTER: 'G', "gnome", random
+# go ahead and leave a lamp next to one corpse to be suggestive
+# and some empty wands...
+OBJECT:('(',"oil lamp"),$place[2]
+OBJECT:('/',"striking"),$place[1],uncursed,0
+OBJECT:('/',"striking"),$place[3],uncursed,0
+OBJECT:('/',"striking"),$place[4],uncursed,0
+OBJECT:('/',"magic missile"),$place[4],uncursed,0
+OBJECT:('/',"magic missile"),$place[0],uncursed,0
 
-ROOM: "ordinary" , random, random, random, random
-MONSTER: 'h', "dwarf", random
+# the Orcish Army
 
-ROOM: "ordinary" , random, random, random, random
-TRAP: random, random
-MONSTER: 'G', "gnome", random
+$inside = selection: floodfill(18,8)
+$near_temple = selection: filter(fillrect(17,8, 23,14), $inside)
 
-RANDOM_CORRIDORS
+LOOP [5 + 1d10] {
+  MONSTER[50%]: ('o', "orc-captain"), rndcoord($inside), hostile
+  MONSTER[80%]: ('o', "Uruk-hai"), rndcoord($inside), hostile
+  MONSTER: ('o', "Mordor orc"), rndcoord($inside), hostile
+}
+# shamans can be hanging out in/near the temple
+LOOP [2d3] {
+  MONSTER: ('o', "orc shaman"), rndcoord($near_temple), hostile
+}
+# these are not such a big deal
+# to run into outside the bars
+LOOP [9 + 2d5] {
+  MONSTER[90%]: ('o', "hill orc"), random, hostile
+  MONSTER: ('o', "goblin"), random, hostile
+}
 
+WALLIFY:(1,0, 70,20)
 
 # Minetown variant 2
@@ -133,91 +174,156 @@
 LEVEL: "minetn-2"
 ROOM: "ordinary" , lit, (3,3), (center,center), (31,15)
-NAME: "town"
-FOUNTAIN: (17, 5)
-FOUNTAIN: (13, 8)
-
-# The Town Watch
-MONSTER: '@', "watchman", random, peaceful
-MONSTER: '@', "watchman", random, peaceful
-MONSTER: '@', "watchman", random, peaceful
-MONSTER: '@', "watchman", random, peaceful
-MONSTER: '@', "watch captain", random, peaceful
+{
 
-SUBROOM: "ordinary", random, (2,0), (2,2), "town"
-DOOR: false, closed, west, random
+IF [75%] {
+  SUBROOM: "ordinary", random, (2,0), (2,2)
+  {
+    ROOMDOOR: false, closed, west|south, random
+  }
+}
 
-SUBROOM: "ordinary", unlit, (5,0), (2,2), "town"
-DOOR: false, closed, south, random
+IF [75%] {
+  SUBROOM: "ordinary", unlit, (5,0), (2,2)
+  {
+    ROOMDOOR: false, closed, west|south, random
+  }
+}
 
-SUBROOM: "ordinary", random, (8,0), (2,2), "town"
-DOOR: false, closed, east, random
+IF [75%] {
+  SUBROOM: "ordinary", random, (8,0), (2,2)
+  {
+    ROOMDOOR: false, closed, east|south, random
+  }
+}
 
-SUBROOM: "ordinary", lit, (16,0), (2,2), "town"
-DOOR: false, closed, west, random
+IF [75%] {
+  SUBROOM: "ordinary", lit, (16,0), (2,2)
+  {
+    ROOMDOOR: false, closed, west|south, random
+  }
+}
 
-SUBROOM: "ordinary", unlit, (19,0), (2,2), "town"
-DOOR: false, closed, south, random
+IF [75%] {
+  SUBROOM: "ordinary", unlit, (19,0), (2,2)
+  {
+    ROOMDOOR: false, closed, west|south, random
+  }
+}
 
-SUBROOM: "ordinary", random, (22,0), (2,2), "town"
-DOOR: false, locked, south, random
-MONSTER: 'G', "gnome", random
+IF [75%] {
+  SUBROOM: "ordinary", random, (22,0), (2,2)
+  {
+    ROOMDOOR: false, locked, west|south, random
+    MONSTER: ('G', "gnome"), random
+  }
+}
 
-SUBROOM: "ordinary", unlit, (25,0), (2,2), "town"
-DOOR: false, closed, east, random
+IF [75%] {
+  SUBROOM: "ordinary", unlit, (25,0), (2,2)
+  {
+    ROOMDOOR: false, closed, east|south|west, random
+  }
+}
 
-SUBROOM: "ordinary", lit, (2,5), (2,2), "town"
-DOOR: false, closed, north, random
+IF [75%] {
+  SUBROOM: "ordinary", lit, (2,5), (2,2)
+  {
+    ROOMDOOR: false, closed, north|south|west, random
+  }
+}
 
-SUBROOM: "ordinary", lit, (5,5), (2,2), "town"
-DOOR: false, closed, south, random
+IF [75%] {
+  SUBROOM: "ordinary", random, (8,5), (2,2)
+  {
+    ROOMDOOR: false, locked, north|south|east, random
+    MONSTER: ('G', "gnome"), random
+  }
+}
 
-SUBROOM: "ordinary", random, (8,5), (2,2), "town"
-DOOR: false, locked, north, random
-MONSTER: 'G', "gnome", random
+IF [75%] {
+  SUBROOM: "ordinary", lit, (5,5), (2,2)
+  {
+    ROOMDOOR: false, closed, north|south|east|west, random
+  }
+}
 
-SUBROOM: "shop" , lit, (2,10), (4,3), "town"
-CHANCE: 90
-DOOR: false, closed, west, random
+SUBROOM: "shop" [90%] , lit, (2,10), (4,3)
+{
+ROOMDOOR: false, closed, north|south|west, random
+}
 
-SUBROOM: "tool shop", lit, (23,10), (4,3), "town"
-CHANCE: 90
-DOOR: false, closed, east, random
+SUBROOM: "tool shop" [90%], lit, (23,10), (4,3)
+{
+ROOMDOOR: false, closed, south|east, random
+}
 
-SUBROOM: "food shop", lit, (24,5), (3,4), "town"
-CHANCE: 90
-DOOR: false, closed, north, random
+SUBROOM: "food shop" [90%], lit, (24,5), (3,4)
+{
+ROOMDOOR: false, closed, north|east, random
+}
 
-SUBROOM: "candle shop", lit, (11,10), (4,3), "town"
-DOOR: false, closed, east, random
+SUBROOM: "candle shop", lit, (11,10), (4,3)
+{
+ROOMDOOR: false, closed, north|south|east, random
+}
 
-SUBROOM: "ordinary", unlit, (7,10), (3,3), "town"
-DOOR: false, locked, north, random
-MONSTER: 'G', "gnome", random
+IF [75%] {
+  SUBROOM: "ordinary", unlit, (7,10), (3,3)
+  {
+    ROOMDOOR: false, locked, north|south, random
+    MONSTER: ('G', "gnome"), random
+  }
+}
 
-SUBROOM: "temple", lit, (19,5), (4,4), "town"
-DOOR: false, closed, north, random
+SUBROOM: "temple", lit, (19,5), (4,4)
+{
+ROOMDOOR: false, closed, north|west, random
 ALTAR:(02,02),align[0],shrine
-MONSTER: 'G', "gnomish wizard", random
-MONSTER: 'G', "gnomish wizard", random
+MONSTER: ('G', "gnomish wizard"), random
+MONSTER: ('G', "gnomish wizard"), random
+}
 
-SUBROOM: "ordinary", lit, (18,10), (4,3), "town"
-DOOR: false, locked, west, random
-MONSTER: 'G', "gnome lord", random
+IF [75%] {
+  SUBROOM: "ordinary", lit, (18,10), (4,3)
+  {
+    ROOMDOOR: false, locked, south|west, random
+    MONSTER: ('G', "gnome lord"), random
+  }
+}
+
+FOUNTAIN: (17, 5)
+FOUNTAIN: (13, 8)
+
+# The Town Watch
+LOOP [2 + 1d7] {
+  MONSTER: ('@', "watchman"), random, peaceful
+}
+MONSTER: ('@', "watch captain"), random, peaceful
+
+}
 
 ROOM: "ordinary" , random, random, random, random
+{
 STAIR: random, up
+}
 
 ROOM: "ordinary" , random, random, random, random
+{
 STAIR: random, down
 TRAP: random, random
-MONSTER: 'G', "gnome", random
-MONSTER: 'G', "gnome", random
+MONSTER: ('G', "gnome"), random
+MONSTER: ('G', "gnome"), random
+}
 
 ROOM: "ordinary" , random, random, random, random
-MONSTER: 'h', "dwarf", random
+{
+MONSTER: ('h', "dwarf"), random
+}
 
 ROOM: "ordinary" , random, random, random, random
+{
 TRAP: random, random
-MONSTER: 'G', "gnome", random
+MONSTER: ('G', "gnome"), random
+}
 
 RANDOM_CORRIDORS
@@ -229,86 +335,142 @@
 LEVEL: "minetn-3"
 ROOM: "ordinary",lit,(3,3),(center,center),(31,15)
-NAME: "town"
-FOUNTAIN:(01,06)
-FOUNTAIN:(29,13)
-MONSTER: '@', "watchman", random, peaceful
-MONSTER: '@', "watchman", random, peaceful
-MONSTER: '@', "watchman", random, peaceful
-MONSTER: '@', "watchman", random, peaceful
-MONSTER: '@', "watch captain", random, peaceful
+{
 
-SUBROOM:"ordinary",random,(2,2),(2,2),"town"
-DOOR: false,closed,south,random
+IF [75%] {
+  SUBROOM:"ordinary",random,(2,2),(2,2)
+  {
+    ROOMDOOR: false,closed,north|south|west,random
+  }
+}
 
-SUBROOM:"tool shop",lit,(5,3),(2,3),"town"
-CHANCE: 30
-DOOR: false,closed,south,random
+SUBROOM:"tool shop" [30%],lit,(5,3),(2,3)
+{
+ROOMDOOR: false,closed,north|south|east,random
+}
 
-SUBROOM:"ordinary",random,(2,10),(2,3),"town"
-DOOR: false, locked, north, random
-MONSTER: 'G',random,random
+IF [75%] {
+  SUBROOM:"ordinary",random,(2,10),(2,3)
+  {
+    ROOMDOOR: false, locked, north|south|west, random
+    MONSTER: 'G',random
+  }
+}
 
-SUBROOM:"ordinary",random,(5,9),(2,2),"town"
-DOOR: false,closed,north,random
+IF [75%] {
+  SUBROOM:"ordinary",random,(5,9),(2,2)
+  {
+    ROOMDOOR: false,closed,north|south|east,random
+  }
+}
 
-SUBROOM:"temple",lit,(10,2),(3,4),"town"
-DOOR: false,closed,east,random
+SUBROOM:"temple",lit,(10,2),(3,4)
+{
+ROOMDOOR: false,closed,north|west|east,random
 ALTAR:(1,1),align[0],shrine
-MONSTER: 'G', "gnomish wizard", random
-MONSTER: 'G', "gnomish wizard", random
+MONSTER: ('G', "gnomish wizard"), random
+MONSTER: ('G', "gnomish wizard"), random
+}
 
-SUBROOM:"ordinary",random,(11,7),(2,2),"town"
-DOOR: false,closed,west,random
+IF [75%] {
+  SUBROOM:"ordinary",random,(11,7),(2,2)
+  {
+    ROOMDOOR: false,closed,west,random
+  }
+}
 
-SUBROOM:"shop",lit,(10,10),(3,3),"town"
-DOOR:false,closed,west,random
+SUBROOM:"shop",lit,(10,10),(3,3)
+{
+ROOMDOOR:false,closed,west|south,random
+}
 
-SUBROOM:"ordinary",random,(14,8),(2,2),"town"
-DOOR:false,locked,north,random
-MONSTER: 'G',random,random
+IF [75%] {
+  SUBROOM:"ordinary",random,(14,8),(2,2)
+  {
+    ROOMDOOR:false,locked,north,random
+    MONSTER: 'G',random
+  }
+}
 
-SUBROOM:"ordinary",random,(14,11),(2,2),"town"
-DOOR:false,closed,south,random
+IF [75%] {
+  SUBROOM:"ordinary",random,(14,11),(2,2)
+  {
+    ROOMDOOR:false,closed,north|south,random
+  }
+}
 
-SUBROOM:"tool shop",lit,(17,10),(3,3),"town"
-CHANCE:40
-DOOR:false,closed,north,random
+SUBROOM:"tool shop" [40%],lit,(17,10),(3,3)
+{
+ROOMDOOR:false,closed,north|south,random
+}
 
-SUBROOM:"ordinary",random,(21,11),(2,2),"town"
-DOOR:false,locked,east,random
-MONSTER:'G',random,random
+IF [75%] {
+  SUBROOM:"ordinary",random,(21,11),(2,2)
+  {
+    ROOMDOOR:false,locked,north|south|east,random
+    MONSTER:'G',random
+  }
+}
 
-SUBROOM:"food shop",lit,(26,8),(3,2),"town"
-CHANCE:90
-DOOR:false,closed,west,random
+SUBROOM:"food shop" [90%],lit,(26,8),(3,2)
+{
+ROOMDOOR:false,closed,north|south|east|west,random
+}
 
-SUBROOM:"ordinary",random,(16,2),(2,2),"town"
-DOOR:false,closed,west,random
+IF [75%] {
+  SUBROOM:"ordinary",random,(16,2),(2,2)
+  {
+    ROOMDOOR:false,closed,north|south|west,random
+  }
+}
 
-SUBROOM:"ordinary",random,(19,2),(2,2),"town"
-DOOR:false,closed,north,random
+IF [75%] {
+  SUBROOM:"ordinary",random,(19,2),(2,2)
+  {
+    ROOMDOOR:false,closed,north|east|west,random
+  }
+}
 
-SUBROOM:"wand shop",lit,(19,5),(3,2),"town"
-CHANCE:30
-DOOR:false,closed,west,random
+SUBROOM:"wand shop" [30%],lit,(19,5),(3,2)
+{
+ROOMDOOR:false,closed,south|east|west,random
+}
 
-SUBROOM: "candle shop",lit,(25,2),(3,3),"town"
-DOOR:false,closed,south,random
+SUBROOM: "candle shop",lit,(25,2),(3,3)
+{
+ROOMDOOR:false,closed,north|south|east|west,random
+}
+
+FOUNTAIN:(01,06)
+FOUNTAIN:(29,13)
+LOOP [2 + 1d7] {
+  MONSTER: ('@', "watchman"), random, peaceful
+}
+MONSTER: ('@', "watch captain"), random, peaceful
+
+}
 
 ROOM: "ordinary", random, random, random, random
+{
 STAIR: random, up
+}
 
 ROOM: "ordinary" , random, random, random, random
+{
 STAIR: random, down
 TRAP: random, random
-MONSTER: 'G', "gnome", random
-MONSTER: 'G', "gnome", random
+MONSTER: ('G', "gnome"), random
+MONSTER: ('G', "gnome"), random
+}
 
 ROOM: "ordinary" , random, random, random, random
-MONSTER: 'h', "dwarf", random
+{
+MONSTER: ('h', "dwarf"), random
+}
 
 ROOM: "ordinary" , random, random, random, random
+{
 TRAP: random, random
-MONSTER: 'G', "gnome", random
+MONSTER: ('G', "gnome"), random
+}
 
 RANDOM_CORRIDORS
@@ -320,77 +482,120 @@
 LEVEL: "minetn-4"
 ROOM: "ordinary",lit,(3,3),(center,center),(30,15)
-NAME: "town"
-FOUNTAIN:(08,07)
-FOUNTAIN:(18,07)
-MONSTER: '@', "watchman", random, peaceful
-MONSTER: '@', "watchman", random, peaceful
-MONSTER: '@', "watchman", random, peaceful
-MONSTER: '@', "watchman", random, peaceful
-MONSTER: '@', "watch captain", random, peaceful
+{
 
-SUBROOM:"book shop",lit,(4,2),(3,3),"town"
-DOOR: false,closed,south,random
+SUBROOM:"book shop",lit,(4,2),(3,3)
+{
+ROOMDOOR: false,closed,north|south|west,random
+}
 
-SUBROOM:"ordinary",random,(8,2),(2,2),"town"
-DOOR: false,closed,south,random
+IF [75%] {
+  SUBROOM:"ordinary",random,(8,2),(2,2)
+  {
+    ROOMDOOR: false,closed,north|south,random
+  }
+}
 
-SUBROOM:"temple",lit,(11,3),(5,4),"town"
-DOOR: false,closed,south,random
+SUBROOM:"temple",lit,(11,3),(5,4)
+{
+ROOMDOOR: false,closed,north|south|east,random
 ALTAR:(2,1),align[0],shrine
-MONSTER: 'G', "gnomish wizard", random
-MONSTER: 'G', "gnomish wizard", random
+MONSTER: ('G', "gnomish wizard"), random
+MONSTER: ('G', "gnomish wizard"), random
+}
 
-SUBROOM:"ordinary",random,(19,2),(2,2),"town"
-DOOR: false,closed,south,random
-MONSTER: 'G', random, random
+IF [75%] {
+  SUBROOM:"ordinary",random,(19,2),(2,2)
+  {
+    ROOMDOOR: false,closed,north|south|west,random
+    MONSTER: 'G', random
+  }
+}
 
-SUBROOM:"candle shop",lit,(22,2),(3,3),"town"
-DOOR:false,closed,south,random
+SUBROOM:"candle shop",lit,(22,2),(3,3)
+{
+ROOMDOOR:false,closed,north|south,random
+}
 
-SUBROOM:"ordinary",random,(26,2),(2,2),"town"
-DOOR:false,locked,east,random
-MONSTER: 'G',random,random
+IF [75%] {
+  SUBROOM:"ordinary",random,(26,2),(2,2)
+  {
+    ROOMDOOR:false,locked,north|south|east,random
+    MONSTER: 'G',random
+  }
+}
 
-SUBROOM:"tool shop",lit,(4,10),(3,3),"town"
-CHANCE:90
-DOOR:false,closed,north,random
+SUBROOM:"tool shop" [90%],lit,(4,10),(3,3)
+{
+ROOMDOOR:false,closed,north|south|west,random
+}
 
-SUBROOM:"ordinary",random,(8,11),(2,2),"town"
-DOOR:false,locked,south,random
-MONSTER: 'k',"kobold shaman",random
-MONSTER: 'k',"kobold shaman",random
-MONSTER: 'f',"kitten",random
-MONSTER: 'f',random,random
+IF [75%] {
+  SUBROOM:"ordinary",random,(8,11),(2,2)
+  {
+    ROOMDOOR:false,locked,north|south,random
+    MONSTER: ('k',"kobold shaman"),random
+    MONSTER: ('k',"kobold shaman"),random
+    MONSTER: ('f',"kitten"),random
+    MONSTER: 'f',random
+  }
+}
 
-SUBROOM:"food shop",lit,(11,11),(3,2),"town"
-CHANCE:90
-DOOR:false,closed,east,random
+SUBROOM:"food shop" [90%],lit,(11,11),(3,2)
+{
+ROOMDOOR:false,closed,north|south|east,random
+}
 
-SUBROOM:"ordinary",random,(17,11),(2,2),"town"
-DOOR:false,closed,west,random
+IF [75%] {
+  SUBROOM:"ordinary",random,(17,11),(2,2)
+  {
+    ROOMDOOR:false,closed,north|south|west,random
+  }
+}
 
-SUBROOM:"ordinary",random,(20,10),(2,2),"town"
-DOOR:false,locked,north,random
-MONSTER:'G',random,random
+IF [75%] {
+  SUBROOM:"ordinary",random,(20,10),(2,2)
+  {
+    ROOMDOOR:false,locked,north|south,random
+    MONSTER:'G',random
+  }
+}
 
-SUBROOM:"shop",lit,(23,10),(3,3),"town"
-CHANCE:90
-DOOR:false,closed,north,random
+SUBROOM:"shop" [90%],lit,(23,10),(3,3)
+{
+ROOMDOOR:false,closed,north|south|east,random
+}
+
+FOUNTAIN:(08,07)
+FOUNTAIN:(18,07)
+LOOP [2 + 1d7] {
+  MONSTER: ('@', "watchman"), random, peaceful
+}
+MONSTER: ('@', "watch captain"), random, peaceful
+
+}
 
 ROOM: "ordinary" , random, random, random, random
+{
 STAIR: random, up
+}
 
 ROOM: "ordinary" , random, random, random, random
+{
 STAIR: random, down
 TRAP: random, random
-MONSTER: 'G', "gnome", random
-MONSTER: 'G', "gnome", random
+MONSTER: ('G', "gnome"), random
+MONSTER: ('G', "gnome"), random
+}
 
 ROOM: "ordinary" , random, random, random, random
-MONSTER: 'h', "dwarf", random
+{
+MONSTER: ('h', "dwarf"), random
+}
 
 ROOM: "ordinary" , random, random, random, random
+{
 TRAP: random, random
-MONSTER: 'G', "gnome", random
+MONSTER: ('G', "gnome"), random
+}
 
 RANDOM_CORRIDORS
@@ -399,5 +604,7 @@
 # "Grotto Town" by Kelly Bailey
 #
-MAZE: "minetn-5",' '
+LEVEL: "minetn-5"
+FLAGS:mazelevel
+INIT_MAP:solidfill,' '
 GEOMETRY:center,center
 MAP
@@ -425,4 +632,34 @@
 ENDMAP
 
+IF [75%] {
+   IF [50%] {
+      TERRAIN:line (25,8)-(25,9), '|'
+   } ELSE {
+      TERRAIN:line (16,13)-(17,13), '-'
+   }
+}
+
+IF [75%] {
+   IF [50%] {
+      TERRAIN:line (36,10)-(36,11), '|'
+   } ELSE {
+      TERRAIN:line (32,15)-(33,15), '-'
+   }
+}
+
+IF [50%] {
+   TERRAIN:fillrect (21,4,22,5), '.'
+   TERRAIN:line (14,9)-(14,10), '|'
+}
+
+IF [50%] {
+   TERRAIN:(46,13), '|'
+   TERRAIN:line (43,5)-(47,5), '-'
+   TERRAIN:line (42,6)-(46,6), '.'
+   TERRAIN:(47,7), '.'
+}
+
+TERRAIN[50%]:fillrect (69,11,71,11), '-'
+
 STAIR:(01,01),up
 STAIR:(46,03),down
@@ -431,30 +668,26 @@
 FOUNTAIN:(66,18)
 
+OBJECT:('\\',"brazier"),(08,15)
+OBJECT:('\\',"brazier"),(12,15)
+OBJECT:('\\',"brazier"),(51,09)
+OBJECT:('\\',"brazier"),(65,18)
+OBJECT:('\\',"brazier"),(36,15)
+OBJECT:('\\',"brazier"),(40,15)
+
 REGION:(00,00,74,20),unlit,"ordinary"
-REGION:(09,13,11,17),lit,"ordinary"
-REGION:(08,14,12,16),lit,"ordinary"
-REGION:(49,07,51,11),lit,"ordinary"
-REGION:(48,08,52,10),lit,"ordinary"
-REGION:(64,17,68,19),lit,"ordinary"
-REGION:(37,13,39,17),lit,"ordinary"
-REGION:(36,14,40,17),lit,"ordinary"
 REGION:(59,02,72,10),lit,"ordinary"
 
-MONSTER: '@', "watchman", random, peaceful
-MONSTER: '@', "watchman", random, peaceful
-MONSTER: '@', "watchman", random, peaceful
-MONSTER: '@', "watchman", random, peaceful
-MONSTER: '@', "watch captain", random, peaceful
-MONSTER: 'G', "gnome", random
-MONSTER: 'G', "gnome", random
-MONSTER: 'G', "gnome", random
-MONSTER: 'G', "gnome", random
-MONSTER: 'G', "gnome", random
-MONSTER: 'G', "gnome", random
-MONSTER: 'G', "gnome lord", random
-MONSTER: 'G', "gnome lord", random
-MONSTER: 'h', "dwarf", random
-MONSTER: 'h', "dwarf", random
-MONSTER: 'h', "dwarf", random
+LOOP [2 + 1d7] {
+  MONSTER: ('@', "watchman"), random, peaceful
+}
+MONSTER: ('@', "watch captain"), random, peaceful
+LOOP [4 + 1d8] {
+  MONSTER: ('G', "gnome"), random
+}
+MONSTER: ('G', "gnome lord"), random
+MONSTER: ('G', "gnome lord"), random
+MONSTER: ('h', "dwarf"), random
+MONSTER: ('h', "dwarf"), random
+MONSTER: ('h', "dwarf"), random
 
 # The shops
@@ -470,12 +703,12 @@
 DOOR:closed,(04,14)
 DOOR:locked,(01,17)
-MONSTER: 'G', "gnomish wizard", (02,19)
+MONSTER: ('G', "gnomish wizard"), (02,19)
 DOOR:locked,(20,16)
-MONSTER: 'G', random, (20,18)
+MONSTER: 'G', (20,18)
 DOOR:random,(21,14)
 DOOR:random,(25,14)
 DOOR:random,(42,08)
 DOOR:locked,(40,05)
-MONSTER: 'G', random, (38,07)
+MONSTER: 'G', (38,07)
 DOOR:random,(59,03)
 DOOR:random,(58,06)
@@ -486,13 +719,13 @@
 DOOR:closed,(69,04)
 DOOR:closed,(67,16)
-MONSTER: 'G', "gnomish wizard", (67,14)
-OBJECT: '=', random, (70,14)
+MONSTER: ('G', "gnomish wizard"), (67,14)
+OBJECT: '=', (70,14)
 DOOR:locked,(69,18)
-MONSTER: 'G', "gnome lord", (71,19)
+MONSTER: ('G', "gnome lord"), (71,19)
 DOOR:locked,(73,18)
-OBJECT: '(', "chest", (73,19)
+OBJECT: ('(', "chest"), (73,19)
 DOOR:locked,(50,06)
-OBJECT: '(', random, (50,03)
-OBJECT: '`', "statue", (38,15), "gnome king", 1
+OBJECT: '(', (50,03)
+OBJECT: ('`', "statue"), (38,15), montype:"gnome king", 1
 # Temple
 REGION:(29,02,33,04),lit,"temple"
@@ -501,24 +734,27 @@
 
 
-# "Bustling Town" by Kelly Bailey
+# Screw Bustling Town.  Let's make a zoo.  --DSR
 #
-MAZE: "minetn-6",' '
-INIT_MAP:'.','-',true,true,lit,true
+LEVEL: "minetn-6"
+FLAGS:mazelevel
+INIT_MAP:mines,'.','-',true,true,lit,true
 GEOMETRY:center,top
+#         1         2         3         4         5         6         7
+#1234567890123456789012345678901234567890123456789012345678901234567890
 MAP
-.-----................----------------.-
-.|...|................|...|..|...|...|..
-.|...+..--+--.........|...|..|...|...|..
-.|...|..|...|..-----..|...|..|-+---+--..
-.-----..|...|--|...|..--+---+-.........|
-........|...|..|...+.............-----..
-........-----..|...|......--+-...|...|..
-.----...|...|+------..{...|..|...+...|..
+.-----...................-------------.-
+.|...|...................|...|...|...|..
+.|...+..--+--...-FFF+F...|...|...|...|..
+.|...|..|...|...|....F...|...|-+---+--..
+.-----..|...|...|....F...---+-.........|
+........|...|...|....F...........-----..
+........-----...------....--+-...|...|..
+.----...|...|.{........{..|..|...+...|..
 .|..+...|...|.............|..|...|...|..
-.|..|...|...|-+-.....---+-------------.|
-.----...--+--..|..-+-|..................
+.|..|...|...|---.....---+-------------.|
+.----...--+--..|..---|..................
 ...|........|..|..|..|----....---------.
-...|..T.....----..|..|...+....|......|-.
-...|-....{........|..|...|....+......|-.
+...|..T.....-+--..+..|...+....|......|-.
+...|-....T........|..|...|....+......|-.
 ...--..-....T.....--------....|......|-.
 .......--.....................----------
@@ -528,10 +764,11 @@
 STAIR:levregion(01,03,20,19),(0,0,39,15),up
 STAIR:levregion(61,03,75,19),(0,0,39,15),down
-FOUNTAIN:(22,07)
-FOUNTAIN:(09,13)
-REGION:(13,5,14,6),unlit,"ordinary"
+FOUNTAIN:(23,07)
+FOUNTAIN:(14,07)
+# protect the zoo against dwarves and inquisitive players
+NON_DIGGABLE:(13,0,24,8)
 REGION:(9,7,11,9),lit,"candle shop"
-REGION:(16,4,18,6),lit,"tool shop"
-REGION:(23,1,25,3),lit,"shop"
+REGION:(9,3,11,5),lit,"tool shop"
+REGION:(26,1,28,3),lit,"shop"
 REGION:(22,12,24,13),lit,"food shop"
 REGION:(31,12,36,14),lit,"temple"
@@ -542,8 +779,6 @@
 DOOR:closed,(10,2)
 DOOR:closed,(10,10)
-DOOR:locked,(13,7)
-DOOR:locked,(14,9)
-DOOR:closed,(19,5)
-DOOR:closed,(19,10)
+DOOR:locked,(13,12)
+DOOR:locked,(20,2)
 DOOR:closed,(24,4)
 DOOR:closed,(24,9)
@@ -556,24 +791,40 @@
 DOOR:closed,(33,7)
 
-MONSTER: 'G', "gnome", random
-MONSTER: 'G', "gnome", random
-MONSTER: 'G', "gnome", random
-MONSTER: 'G', "gnome", random
-MONSTER: 'G', "gnome", random
-MONSTER: 'G', "gnome", random
-MONSTER: 'G', "gnome", (14,6)
-MONSTER: 'G', "gnome lord", (14,5)
-MONSTER: 'G', "gnome", (27,8)
-MONSTER: 'G', "gnome lord", random
-MONSTER: 'G', "gnome lord", random
-MONSTER: 'h', "dwarf", random
-MONSTER: 'h', "dwarf", random
-MONSTER: 'h', "dwarf", random
-MONSTER: '@', "watchman", random, peaceful
-MONSTER: '@', "watchman", random, peaceful
-MONSTER: '@', "watchman", random, peaceful
-MONSTER: '@', "watch captain", random, peaceful
-MONSTER: '@', "watch captain", random, peaceful
+$in_zoo = selection: floodfill(18,4)
+$outside = selection: filter(floodfill(18,8), fillrect (1,0,37,15))
+
+LOOP [4 + 1d8] {
+  MONSTER: ('G', "gnome"), rndcoord($outside)
+}
+MONSTER: ('G', "gnome"), rndcoord($outside)
+MONSTER: ('G', "gnome lord"), rndcoord($outside)
+MONSTER: ('G', "gnome"), rndcoord($outside)
+MONSTER: ('G', "gnome lord"), rndcoord($outside)
+MONSTER: ('G', "gnome lord"), rndcoord($outside)
+MONSTER: ('G', "gnomish wizard"), rndcoord($outside)
+MONSTER: ('G', "gnomish wizard"), rndcoord($outside)
+MONSTER: ('h', "dwarf"), rndcoord($outside)
 
+MONSTER: ('@', "watchman"), rndcoord($outside), peaceful
+MONSTER: ('@', "watchman"), rndcoord($outside), peaceful
+MONSTER: ('@', "watchman"), rndcoord($outside), peaceful
+MONSTER: ('@', "watch captain"), rndcoord($outside), peaceful
+MONSTER: ('@', "watch captain"), rndcoord($outside), peaceful
+# The zoo needs some stuff...
+MONSTER: ('f', "tiger"), rndcoord($in_zoo), hostile
+MONSTER: ('f', "panther"), rndcoord($in_zoo), hostile
+MONSTER: ('f', "jaguar"), rndcoord($in_zoo), hostile
+MONSTER: ('q', "mastodon"), rndcoord($in_zoo), hostile
+# and a couple token handlers
+MONSTER: ('o', "Mordor orc"), rndcoord($in_zoo), hostile {
+  OBJECT:(')', "bullwhip")
+}
+MONSTER: ('o', "Mordor orc"), rndcoord($in_zoo), hostile {
+  OBJECT:(')', "bullwhip")
+}
+# and a couple shiny prizes as temptation (for the handlers to use, possibly?)
+OBJECT: '/', rndcoord($in_zoo)
+OBJECT: '/', rndcoord($in_zoo)
+OBJECT: '=', rndcoord($in_zoo)
 
 # "Bazaar Town" by Kelly Bailey
@@ -581,113 +832,179 @@
 LEVEL: "minetn-7"
 ROOM: "ordinary" , lit, (3,3), (center,center), (30,15)
-NAME: "town"
-FOUNTAIN: (12, 07)
-FOUNTAIN: (11, 13)
-
-MONSTER: '@', "watchman", random, peaceful
-MONSTER: '@', "watchman", random, peaceful
-MONSTER: '@', "watchman", random, peaceful
-MONSTER: '@', "watchman", random, peaceful
-MONSTER: '@', "watch captain", random, peaceful
-MONSTER:'G',"gnome",random
-MONSTER:'G',"gnome",random
-MONSTER:'G',"gnome",random
-MONSTER:'G',"gnome lord",random
-MONSTER:'Y',"monkey",random
-MONSTER:'Y',"monkey",random
+{
 
-SUBROOM: "ordinary", random, (2,2), (4,2), "town"
-DOOR: false, closed, south, random
+IF [75%] {
+  SUBROOM: "ordinary", random, (2,2), (4,2)
+  {
+    ROOMDOOR: false, closed, north|south|west, random
+  }
+}
 
-SUBROOM: "ordinary", random, (7,2), (2,2), "town"
-DOOR: false, closed, north, random
+IF [75%] {
+  SUBROOM: "ordinary", random, (7,2), (2,2)
+  {
+    ROOMDOOR: false, closed, north|west, random
+  }
+}
 
-SUBROOM: "ordinary", random, (7,5), (2,2), "town"
-DOOR: false, closed, south, random
+IF [75%] {
+  SUBROOM: "ordinary", random, (7,5), (2,2)
+  {
+    ROOMDOOR: false, closed, south|west, random
+  }
+}
 
-SUBROOM: "ordinary", lit, (10,2), (3,4), "town"
-MONSTER:'G',"gnome",random
-MONSTER:'Y',"monkey",random
-MONSTER:'Y',"monkey",random
-MONSTER:'Y',"monkey",random
-DOOR: false, closed, south, random
+IF [75%] {
+  SUBROOM: "ordinary", lit, (10,2), (3,4)
+  {
+    MONSTER:('G',"gnome"),random
+    MONSTER:('Y',"monkey"),random
+    MONSTER:('Y',"monkey"),random
+    MONSTER:('Y',"monkey"),random
+    ROOMDOOR: false, closed, north|south, random
+  }
+}
 
-SUBROOM: "ordinary", random, (14,2), (4,2), "town"
-DOOR: false, closed, south, 0
-MONSTER: 'n', random, random
+IF [75%] {
+  SUBROOM: "ordinary", random, (14,2), (4,2)
+  {
+    ROOMDOOR: false, closed, south, 0
+    MONSTER: 'n', random
+  }
+}
 
-SUBROOM: "ordinary", random, (16,5), (2,2), "town"
-DOOR: false, closed, south, random
+IF [75%] {
+  SUBROOM: "ordinary", random, (16,5), (2,2)
+  {
+    ROOMDOOR: false, closed, south|west, random
+  }
+}
 
-SUBROOM: "ordinary", unlit, (19,2), (2,2), "town"
-DOOR: false, locked, east, random
-MONSTER: 'G',"gnome king",random
+IF [75%] {
+  SUBROOM: "ordinary", unlit, (19,2), (2,2)
+  {
+    ROOMDOOR: false, locked, north|west|east, random
+    MONSTER: ('G',"gnome king"),random
+  }
+}
 
-SUBROOM: "food shop", lit, (19,5), (2,3), "town"
-CHANCE: 50
-DOOR: false, closed, south, random
+SUBROOM: "food shop" [50%], lit, (19,5), (2,3)
+{
+ROOMDOOR: false, closed, south|east, random
+}
 
-SUBROOM: "ordinary", random, (2,7), (2,2), "town"
-DOOR: false, closed, east, random
+IF [75%] {
+  SUBROOM: "ordinary", random, (2,7), (2,2)
+  {
+    ROOMDOOR: false, closed, north|west|east, random
+  }
+}
 
-SUBROOM: "tool shop", lit, (2,10), (2,3), "town"
-CHANCE: 50
-DOOR: false, closed, south, random
+SUBROOM: "tool shop" [50%], lit, (2,10), (2,3)
+{
+ROOMDOOR: false, closed, south|west, random
+}
 
-SUBROOM: "candle shop", lit, (5,10),(3,3), "town"
-DOOR: false, closed, north, random
+SUBROOM: "candle shop", lit, (5,10),(3,3)
+{
+ROOMDOOR: false, closed, north|south|east, random
+}
 
-SUBROOM: "ordinary", random, (11,10), (2,2), "town"
-DOOR: false, locked, west, random
-MONSTER: 'G',random,random
+IF [75%] {
+  SUBROOM: "ordinary", random, (11,10), (2,2)
+  {
+    ROOMDOOR: false, locked, north|south|west, random
+    MONSTER: 'G',random
+  }
+}
 
-SUBROOM: "shop", lit, (14,10), (2,3), "town"
-CHANCE: 60
-DOOR: false, closed, north, random
+SUBROOM: "shop" [60%], lit, (14,10), (2,3)
+{
+ROOMDOOR: false, closed, north|south, random
+}
 
-SUBROOM: "ordinary", random, (17,11), (4,2), "town"
-DOOR: false, closed, north, random
+IF [75%] {
+  SUBROOM: "ordinary", random, (17,11), (4,2)
+  {
+    ROOMDOOR: false, closed, north|south, random
+  }
+}
 
-SUBROOM: "ordinary", random, (22,11), (2,2), "town"
-DOOR: false, closed, south, random
+IF [75%] {
+  SUBROOM: "ordinary", random, (22,11), (2,2)
+  {
+    ROOMDOOR: false, closed, north|south|west, random
 SINK: (00,00)
+  }
+}
 
-SUBROOM: "food shop", lit, (25,11), (3,2), "town"
-CHANCE: 50
-DOOR: false, closed, east, random
+SUBROOM: "food shop" [50%], lit, (25,11), (3,2)
+{
+ROOMDOOR: false, closed, south|east, random
+}
 
-SUBROOM: "tool shop", lit, (25,2), (3,3), "town"
-CHANCE: 30
-DOOR: false, closed, west, random
+SUBROOM: "tool shop" [30%], lit, (25,2), (3,3)
+{
+ROOMDOOR: false, closed, north|west|east, random
+}
 
-SUBROOM: "temple", lit, (24,6), (4,4), "town"
-DOOR: false, closed, west, random
+SUBROOM: "temple", lit, (24,6), (4,4)
+{
+ROOMDOOR: false, closed, west, random
 ALTAR:(02,01),align[0],shrine
-MONSTER: 'G', "gnomish wizard", random
-MONSTER: 'G', "gnomish wizard", random
+MONSTER: ('G', "gnomish wizard"), random
+MONSTER: ('G', "gnomish wizard"), random
+}
+
+FOUNTAIN: (12, 07)
+FOUNTAIN: (11, 13)
+
+LOOP [2 + 1d7] {
+  MONSTER: ('@', "watchman"), random, peaceful
+}
+MONSTER: ('@', "watch captain"), random, peaceful
+LOOP [2 + 1d3] {
+  MONSTER:('G',"gnome"),random
+}
+MONSTER:('G',"gnome lord"),random
+MONSTER:('Y',"monkey"),random
+MONSTER:('Y',"monkey"),random
+
+}
 
 ROOM: "ordinary" , random, random, random, random
+{
 STAIR: random, up
+}
 
 ROOM: "ordinary" , random, random, random, random
+{
 STAIR: random, down
 TRAP: random, random
-MONSTER: 'G', "gnome", random
-MONSTER: 'G', "gnome", random
+MONSTER: ('G', "gnome"), random
+MONSTER: ('G', "gnome"), random
+}
 
 ROOM: "ordinary" , random, random, random, random
-MONSTER: 'h', "dwarf", random
+{
+MONSTER: ('h', "dwarf"), random
+}
   
 ROOM: "ordinary" , random, random, random, random
+{
 TRAP: random, random
-MONSTER: 'G', "gnome", random
+MONSTER: ('G', "gnome"), random
+}
 
 RANDOM_CORRIDORS
   
 
+
 # Mine end level variant 1
 # "Mimic of the Mines"
 #
-MAZE: "minend-1", ' '
+LEVEL: "minend-1"
+FLAGS:mazelevel
+INIT_MAP:solidfill,' '
 GEOMETRY:center,center
 #1234567890123456789012345678901234567890123456789012345678901234567890
@@ -714,5 +1031,6 @@
 
 # Dungeon Description
-RANDOM_PLACES:(08,16),(13,07),(21,08),(41,14),(50,04),(50,16),(66,01)
+$place = { (08,16),(13,07),(21,08),(41,14),(50,04),(50,16),(66,01) }
+SHUFFLE:$place
 REGION:(26,01,32,01),unlit,"ordinary",filled,true
 REGION:(20,08,21,08),unlit,"ordinary"
@@ -732,39 +1050,39 @@
 # Niches
 # Note: place[6] empty
-OBJECT:'*',"diamond",place[0]
-OBJECT:'*',"emerald",place[0]
-OBJECT:'*',"worthless piece of violet glass",place[0]
-MONSTER:'m',random,place[0], m_object "luckstone"
-OBJECT:'*',"worthless piece of white glass",place[1]
-OBJECT:'*',"emerald",place[1]
-OBJECT:'*',"amethyst",place[1]
-MONSTER:'m',random,place[1], m_object "loadstone"
-OBJECT:'*',"diamond",place[2]
-OBJECT:'*',"worthless piece of green glass",place[2]
-OBJECT:'*',"amethyst",place[2]
-MONSTER:'m',random,place[2], m_object "flint"
-OBJECT:'*',"worthless piece of white glass",place[3]
-OBJECT:'*',"emerald",place[3]
-OBJECT:'*',"worthless piece of violet glass",place[3]
-MONSTER:'m',random,place[3], m_object "touchstone"
-OBJECT:'*',"worthless piece of red glass",place[4]
-OBJECT:'*',"ruby",place[4]
-OBJECT:'*',"loadstone",place[4]
-OBJECT:'*',"ruby",place[5]
-OBJECT:'*',"worthless piece of red glass",place[5]
-OBJECT:'*',"luckstone",place[5]
+OBJECT:('*',"diamond"),$place[0]
+OBJECT:('*',"emerald"),$place[0]
+OBJECT:('*',"worthless piece of violet glass"),$place[0]
+MONSTER:'m', $place[0], m_object "luckstone"
+OBJECT:('*',"worthless piece of white glass"),$place[1]
+OBJECT:('*',"emerald"),$place[1]
+OBJECT:('*',"amethyst"),$place[1]
+MONSTER:'m', $place[1], m_object "loadstone"
+OBJECT:('*',"diamond"),$place[2]
+OBJECT:('*',"worthless piece of green glass"),$place[2]
+OBJECT:('*',"amethyst"),$place[2]
+MONSTER:'m', $place[2], m_object "flint"
+OBJECT:('*',"worthless piece of white glass"),$place[3]
+OBJECT:('*',"emerald"),$place[3]
+OBJECT:('*',"worthless piece of violet glass"),$place[3]
+MONSTER:'m', $place[3], m_object "touchstone"
+OBJECT:('*',"worthless piece of red glass"),$place[4]
+OBJECT:('*',"ruby"),$place[4]
+OBJECT:('*',"loadstone"),$place[4]
+OBJECT:('*',"ruby"),$place[5]
+OBJECT:('*',"worthless piece of red glass"),$place[5]
+OBJECT:('*',"luckstone"),$place[5]
 # Random objects
-OBJECT:'*',random,random
-OBJECT:'*',random,random
-OBJECT:'*',random,random
-OBJECT:'*',random,random
-OBJECT:'*',random,random
-OBJECT:'*',random,random
-OBJECT:'*',random,random
-OBJECT:'(',random,random
-OBJECT:'(',random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
+OBJECT:'*',random
+OBJECT:'*',random
+OBJECT:'*',random
+OBJECT:'*',random
+OBJECT:'*',random
+OBJECT:'*',random
+OBJECT:'*',random
+OBJECT:'(',random
+OBJECT:'(',random
+OBJECT:random,random
+OBJECT:random,random
+OBJECT:random,random
 # Random traps
 TRAP:random,random
@@ -775,25 +1093,20 @@
 TRAP:random,random
 # Random monsters
-MONSTER:'G',"gnome king",random
-MONSTER:'G',"gnome lord",random
-MONSTER:'G',"gnome lord",random
-MONSTER:'G',"gnome lord",random
-MONSTER:'G',"gnomish wizard",random
-MONSTER:'G',"gnomish wizard",random
-MONSTER:'G',"gnome",random
-MONSTER:'G',"gnome",random
-MONSTER:'G',"gnome",random
-MONSTER:'G',"gnome",random
-MONSTER:'G',"gnome",random
-MONSTER:'G',"gnome",random
-MONSTER:'G',"gnome",random
-MONSTER:'G',"gnome",random
-MONSTER:'G',"gnome",random
-MONSTER:'h',"hobbit",random
-MONSTER:'h',"hobbit",random
-MONSTER:'h',"dwarf",random
-MONSTER:'h',"dwarf",random
-MONSTER:'h',"dwarf",random
-MONSTER:'h',random,random
+MONSTER:('G',"gnome king"),random
+LOOP [2 + 1d4] {
+  MONSTER:('G',"gnome lord"),random
+}
+LOOP [1d4] {
+  MONSTER:('G',"gnomish wizard"),random
+}
+LOOP [5 + 1d8] {
+  MONSTER:('G',"gnome"),random
+}
+MONSTER:('h',"hobbit"),random
+MONSTER:('h',"hobbit"),random
+MONSTER:('h',"dwarf"),random
+MONSTER:('h',"dwarf"),random
+MONSTER:('h',"dwarf"),random
+MONSTER:'h',random
 
 
@@ -801,6 +1114,10 @@
 # "Gnome King's Wine Cellar"
 #
-MAZE: "minend-2", ' '
+LEVEL: "minend-2"
+FLAGS:mazelevel
+INIT_MAP:solidfill,' '
 GEOMETRY:center,center
+#         1         2         3         4         5         6         7
+#1234567890123456789012345678901234567890123456789012345678901234567890
 MAP
 ---------------------------------------------------------------------------
@@ -824,4 +1141,31 @@
 ENDMAP
 
+IF [50%] {
+   TERRAIN:(55,14),'-'
+   TERRAIN:(56,14),'-'
+   TERRAIN:(61,15),'|'
+   TERRAIN:(52,5), 'S'
+   DOOR:locked, (52,5)
+}
+
+IF [50%] {
+   TERRAIN:(18,1), '|'
+   TERRAIN:rect (7,12, 8,13), '.'
+}
+
+IF [50%] {
+   TERRAIN:(49,4), '|'
+   TERRAIN:(21,5), '.'
+}
+
+IF [50%] {
+   IF [50%] {
+      TERRAIN:(22,1), '|'
+   } ELSE {
+      TERRAIN:(50,7), '-'
+      TERRAIN:(51,7), '-'
+   }
+}
+
 # Dungeon Description
 FOUNTAIN:(14,13)
@@ -847,74 +1191,64 @@
 ENGRAVING:(12,03),engrave,"You are now entering the Gnome King's wine cellar."
 ENGRAVING:(12,04),engrave,"Trespassers will be persecuted!"
-OBJECT:'!',"booze",(10,07)
-OBJECT:'!',"booze",(10,07)
-OBJECT:'!',random,(10,07)
-OBJECT:'!',"booze",(10,08)
-OBJECT:'!',"booze",(10,08)
-OBJECT:'!',random,(10,08)
-OBJECT:'!',"booze",(10,09)
-OBJECT:'!',"booze",(10,09)
-OBJECT:'!',"object detection",(10,09)
+OBJECT:('!',"booze"),(10,07)
+OBJECT:('!',"booze"),(10,07)
+OBJECT:'!',(10,07)
+OBJECT:('!',"booze"),(10,08)
+OBJECT:('!',"booze"),(10,08)
+OBJECT:'!',(10,08)
+OBJECT:('!',"booze"),(10,09)
+OBJECT:('!',"booze"),(10,09)
+OBJECT:('!',"object detection"),(10,09)
 # Objects
 # The Treasure chamber...
-OBJECT:'*',"diamond",(69,04)
-OBJECT:'*',random,(69,04)
-OBJECT:'*',"diamond",(69,04)
-OBJECT:'*',random,(69,04)
-OBJECT:'*',"emerald",(70,04)
-OBJECT:'*',random,(70,04)
-OBJECT:'*',"emerald",(70,04)
-OBJECT:'*',random,(70,04)
-OBJECT:'*',"emerald",(69,05)
-OBJECT:'*',random,(69,05)
-OBJECT:'*',"ruby",(69,05)
-OBJECT:'*',random,(69,05)
-OBJECT:'*',"ruby",(70,05)
-OBJECT:'*',"amethyst",(70,05)
-OBJECT:'*',random,(70,05)
-OBJECT:'*',"amethyst",(70,05)
-OBJECT:'*',"luckstone",(70,05)
+OBJECT:('*',"diamond"),(69,04)
+OBJECT:'*',(69,04)
+OBJECT:('*',"diamond"),(69,04)
+OBJECT:'*',(69,04)
+OBJECT:('*',"emerald"),(70,04)
+OBJECT:'*',(70,04)
+OBJECT:('*',"emerald"),(70,04)
+OBJECT:'*',(70,04)
+OBJECT:('*',"emerald"),(69,05)
+OBJECT:'*',(69,05)
+OBJECT:('*',"ruby"),(69,05)
+OBJECT:'*',(69,05)
+OBJECT:('*',"ruby"),(70,05)
+OBJECT:('*',"amethyst"),(70,05)
+OBJECT:'*',(70,05)
+OBJECT:('*',"amethyst"),(70,05)
+OBJECT:('*',"luckstone"),(70,05)
 # Scattered gems...
-OBJECT:'*',random,random
-OBJECT:'*',random,random
-OBJECT:'*',random,random
-OBJECT:'*',random,random
-OBJECT:'*',random,random
-OBJECT:'*',random,random
-OBJECT:'*',random,random
-OBJECT:'(',random,random
-OBJECT:'(',random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
+LOOP [2 + 1d8] {
+  OBJECT:'*',random
+}
+OBJECT:'(',random
+OBJECT:'(',random
+OBJECT:random,random
+OBJECT:random,random
+OBJECT:random,random
 # Random traps
+LOOP [4 + 1d8] {
 TRAP:random,random
-TRAP:random,random
-TRAP:random,random
-TRAP:random,random
-TRAP:random,random
-TRAP:random,random
+}
 # Random monsters.
-MONSTER:'G',"gnome king",random
-MONSTER:'G',"gnome lord",random
-MONSTER:'G',"gnome lord",random
-MONSTER:'G',"gnome lord",random
-MONSTER:'G',"gnomish wizard",random
-MONSTER:'G',"gnomish wizard",random
-MONSTER:'G',"gnome",random
-MONSTER:'G',"gnome",random
-MONSTER:'G',"gnome",random
-MONSTER:'G',"gnome",random
-MONSTER:'G',"gnome",random
-MONSTER:'G',"gnome",random
-MONSTER:'G',"gnome",random
-MONSTER:'G',"gnome",random
-MONSTER:'G',"gnome",random
-MONSTER:'h',"hobbit",random
-MONSTER:'h',"hobbit",random
-MONSTER:'h',"dwarf",random
-MONSTER:'h',"dwarf",random
-MONSTER:'h',"dwarf",random
-MONSTER:'h',random,random
+MONSTER:('G',"gnome king"),(10,09),hostile
+MONSTER:('G',"gnomish wizard"),(11,09),hostile
+MONSTER:('G',"gnome king"),random
+LOOP [1 + 1d3] {
+  MONSTER:('G',"gnome lord"),random
+}
+LOOP [1d4] {
+  MONSTER:('G',"gnomish wizard"),random
+}
+LOOP [5 + 3d4] {
+  MONSTER:('G',"gnome"),random
+}
+MONSTER:('h',"hobbit"),random
+MONSTER:('h',"hobbit"),random
+MONSTER:('h',"dwarf"),random
+MONSTER:('h',"dwarf"),random
+MONSTER:('h',"dwarf"),random
+MONSTER:'h',random
 
 
@@ -922,6 +1256,7 @@
 # Relies on some very specific behavior of MAZEWALK.
 #
-MAZE:"minend-3",'-'
-FLAGS:nommap
+LEVEL:"minend-3"
+FLAGS:nommap,mazelevel
+INIT_MAP:solidfill,'-'
 GEOMETRY:center,bottom
 MAP
@@ -945,5 +1280,6 @@
 ENDMAP
 
-RANDOM_PLACES:(1,15),(68,6),(1,13)
+$place = { (1,15),(68,6),(1,13) }
+SHUFFLE:$place
 NON_DIGGABLE:(67,3,73,7)
 NON_DIGGABLE:(0,12,2,16)
@@ -960,61 +1296,50 @@
 
 # Objects
-OBJECT:'*',"diamond",random
-OBJECT:'*',random,random
-OBJECT:'*',"diamond",random
-OBJECT:'*',random,random
-OBJECT:'*',"emerald",random
-OBJECT:'*',random,random
-OBJECT:'*',"emerald",random
-OBJECT:'*',random,random
-OBJECT:'*',"emerald",random
-OBJECT:'*',random,random
-OBJECT:'*',"ruby",random
-OBJECT:'*',random,random
-OBJECT:'*',"ruby",random
-OBJECT:'*',"amethyst",random
-OBJECT:'*',random,random
-OBJECT:'*',"amethyst",random
-OBJECT:'*',"luckstone",place[0]
-OBJECT:'*',"flint",place[1]
-OBJECT:'?',random,random
-OBJECT:'?',random,random
-OBJECT:'?',random,random
-OBJECT:'?',random,random
-OBJECT:'?',random,random
-OBJECT:'+',random,random
-OBJECT:'+',random,random
-OBJECT:'+',random,random
-OBJECT:'+',random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-TRAP:random,random
-TRAP:random,random
-TRAP:random,random
-TRAP:random,random
-TRAP:random,random
-TRAP:random,random
+OBJECT:('*',"diamond"),random
+OBJECT:'*',random
+OBJECT:('*',"diamond"),random
+OBJECT:'*',random
+OBJECT:('*',"emerald"),random
+OBJECT:'*',random
+OBJECT:('*',"emerald"),random
+OBJECT:'*',random
+OBJECT:('*',"emerald"),random
+OBJECT:'*',random
+OBJECT:('*',"ruby"),random
+OBJECT:'*',random
+OBJECT:('*',"ruby"),random
+OBJECT:('*',"amethyst"),random
+OBJECT:'*',random
+OBJECT:('*',"amethyst"),random
+OBJECT:('*',"luckstone"),$place[0]
+OBJECT:('*',"flint"),$place[1]
+LOOP [3d3] {
+  OBJECT:'?',random
+}
+LOOP [3d2] {
+  OBJECT:'+',random
+}
+OBJECT:random,random
+OBJECT:random,random
+OBJECT:random,random
+LOOP [2 + 3d3] {
 TRAP:random,random
+}
 # One-time annoyance factor
-TRAP:"level teleport",place[0]
-TRAP:"level teleport",place[1]
-MONSTER:'M',random,random
-MONSTER:'M',random,random
-MONSTER:'M',random,random
-MONSTER:'M',random,random
-MONSTER:'M',random,random
-MONSTER:'M',"ettin mummy",random
-MONSTER:'V',random,random
-MONSTER:'Z',random,random
-MONSTER:'Z',random,random
-MONSTER:'Z',random,random
-MONSTER:'Z',random,random
-MONSTER:'Z',random,random
-MONSTER:'V',random,random
-MONSTER:'e',random,random
-MONSTER:'e',random,random
-MONSTER:'e',random,random
-MONSTER:'e',random,random
+TRAP:"level teleport",$place[0]
+TRAP:"level teleport",$place[1]
+LOOP [2 + 3d3] {
+  MONSTER:'M',random
+}
+MONSTER:('M',"ettin mummy"),random
+MONSTER:'V',random
+MONSTER:'V',random
+LOOP [3 + 3d3] {
+  MONSTER:'Z',random
+}
+MONSTER:'e',random
+MONSTER:'e',random
+MONSTER:'e',random
+MONSTER:'e',random
 
 
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/dat/Monk.des nethack/dat/Monk.des
--- nh_orig/dat/Monk.des	2003-12-07 18:39:12.000000000 -0500
+++ nethack/dat/Monk.des	2010-05-02 09:11:33.866715019 -0400
@@ -9,6 +9,8 @@
 #	and receive your quest assignment.
 #
-MAZE: "Mon-strt",' '
-FLAGS: noteleport,hardfloor
+LEVEL: "Mon-strt"
+FLAGS: noteleport,hardfloor,mazelevel
+INIT_MAP:solidfill,(' ', lit)
+MON_GENERATION:86%, (64,"earth elemental"), (16,'E'), (16,"xorn"), (4,'X')
 GEOMETRY:center,center
 MAP
@@ -20,10 +22,10 @@
 ....................|..------------..|--+-----+-----+--|....................
 ....................|..|..........|..|.................|....................
-....................|..|..........|..|+---+---+-----+--|....................
+....................|..|..........|..|+----------------|....................
 ..................---..|..........|......|...|...|.....|....................
 ..................+....|..........+......|...|...|.....|....................
 ..................+....|..........+......|...|...|.....|....................
 ..................---..|..........|......|...|...|.....|....................
-....................|..|..........|..|+-----+---+---+--|....................
+....................|..|..........|..|+----------------|....................
 ....................|..|..........|..|.................|....................
 ....................|..------------..|--+-----+-----+--|....................
@@ -37,5 +39,22 @@
 REGION:(00,00,75,19),lit,"ordinary"
 REGION:(24,06,33,13),lit,"temple"
+REGION:(42,08,44,11),lit,"ordinary",unfilled,true {
+  ROOMDOOR:false, closed, north|south|west|east, random
+  ROOMDOOR:false, locked, north|south|west|east, random
+}
+REGION:(46,08,48,11),lit,"ordinary",unfilled,true {
+  ROOMDOOR:false, closed, north|south|west|east, random
+  ROOMDOOR:false, locked, north|south|west|east, random
+}
+REGION:(50,08,54,11),lit,"ordinary",unfilled,true {
+  ROOMDOOR:false, closed, north|south|west, random
+  ROOMDOOR:false, locked, north|south|west, random
+}
+
+REPLACE_TERRAIN:(0,0,10,19),'.','T',10%
+REPLACE_TERRAIN:(65,0,75,19),'.','T',10%
+
 # Portal arrival point
+TERRAIN:(05,04),'.'
 BRANCH:(05,04,05,04),(0,0,0,0)
 # Stairs
@@ -50,11 +69,5 @@
 DOOR:closed,(52,05)
 DOOR:locked,(38,07)
-DOOR:closed,(42,07)
-DOOR:closed,(46,07)
-DOOR:closed,(52,07)
 DOOR:locked,(38,12)
-DOOR:closed,(44,12)
-DOOR:closed,(48,12)
-DOOR:closed,(52,12)
 DOOR:closed,(40,14)
 DOOR:closed,(46,14)
@@ -63,15 +76,38 @@
 ALTAR:(28,09),noalign,altar
 # The Grand Master
-MONSTER:'@',"Grand Master",(28,10)
+MONSTER:('@',"Grand Master"),(28,10) {
+  OBJECT:'?'
+  OBJECT:'?'
+  OBJECT:'?'
+  OBJECT:'?'
+  OBJECT:'?'
+  OBJECT:'?'
+}
 # No treasure chest!
 # guards for the audience chamber
-MONSTER:'@',"abbot",(32,07)
-MONSTER:'@',"abbot",(32,08)
-MONSTER:'@',"abbot",(32,11)
-MONSTER:'@',"abbot",(32,12)
-MONSTER:'@',"abbot",(33,07)
-MONSTER:'@',"abbot",(33,08)
-MONSTER:'@',"abbot",(33,11)
-MONSTER:'@',"abbot",(33,12)
+MONSTER:('@',"abbot"),(32,07) {
+  OBJECT[50%]:'?'
+}
+MONSTER:('@',"abbot"),(32,08) {
+  OBJECT[50%]:'?'
+}
+MONSTER:('@',"abbot"),(32,11) {
+  OBJECT[50%]:'?'
+}
+MONSTER:('@',"abbot"),(32,12) {
+  OBJECT[50%]:'?'
+}
+MONSTER:('@',"abbot"),(33,07) {
+  OBJECT[50%]:'?'
+}
+MONSTER:('@',"abbot"),(33,08) {
+  OBJECT[50%]:'?'
+}
+MONSTER:('@',"abbot"),(33,11) {
+  OBJECT[50%]:'?'
+}
+MONSTER:('@',"abbot"),(33,12) {
+  OBJECT[50%]:'?'
+}
 # Non diggable walls
 NON_DIGGABLE:(00,00,75,19)
@@ -84,16 +120,16 @@
 TRAP:random,random
 # Monsters on siege duty.
-MONSTER: 'E',"earth elemental",(37,01)
-MONSTER: 'E',"earth elemental",(37,18)
-MONSTER: 'E',"earth elemental",(03,03)
-MONSTER: 'E',"earth elemental",(65,04)
-MONSTER: 'E',"earth elemental",(12,11)
-MONSTER: 'E',"earth elemental",(60,12)
-MONSTER: 'E',"earth elemental",(14,08)
-MONSTER: 'E',"earth elemental",(55,00)
-MONSTER: 'X',"xorn",(18,18)
-MONSTER: 'X',"xorn",(59,10)
-MONSTER: 'X',"xorn",(13,09)
-MONSTER: 'X',"xorn",(01,17)
+MONSTER: ('E',"earth elemental"),(37,01)
+MONSTER: ('E',"earth elemental"),(37,18)
+MONSTER: ('E',"earth elemental"),(03,03)
+MONSTER: ('E',"earth elemental"),(65,04)
+MONSTER: ('E',"earth elemental"),(12,11)
+MONSTER: ('E',"earth elemental"),(60,12)
+MONSTER: ('E',"earth elemental"),(14,08)
+MONSTER: ('E',"earth elemental"),(55,00)
+MONSTER: ('X',"xorn"),(18,18)
+MONSTER: ('X',"xorn"),(59,10)
+MONSTER: ('X',"xorn"),(13,09)
+MONSTER: ('X',"xorn"),(01,17)
 
 #
@@ -104,5 +140,8 @@
 #
 
-MAZE: "Mon-loca",' '
+LEVEL: "Mon-loca"
+FLAGS:mazelevel
+INIT_MAP:solidfill,' '
+MON_GENERATION:86%, (64,"earth elemental"), (16,'E'), (16,"xorn"), (4,'X')
 GEOMETRY:center,center
 #         1         2         3         4         5         6         7 
@@ -132,5 +171,4 @@
 ENDMAP
 # Random Monsters
-RANDOM_MONSTERS: 'E', 'X'
 # Dungeon Description
 REGION:(00,00,75,20),lit,"ordinary"
@@ -141,50 +179,18 @@
 NON_DIGGABLE:(00,00,75,20)
 # Objects
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
+LOOP [10 + 1d10] {
+OBJECT:random,random
+}
 # Random traps
+LOOP [3 + 2d3] {
 TRAP:random,random
-TRAP:random,random
-TRAP:random,random
-TRAP:random,random
-TRAP:random,random
-TRAP:random,random
+}
 # Random monsters.
-MONSTER: 'E',"earth elemental",random
-MONSTER: 'E',"earth elemental",random
-MONSTER: 'E',"earth elemental",random
-MONSTER: 'E',"earth elemental",random
-MONSTER: 'E',"earth elemental",random
-MONSTER: 'E',"earth elemental",random
-MONSTER: 'E',"earth elemental",random
-MONSTER: 'E',"earth elemental",random
-MONSTER: 'E',"earth elemental",random
-MONSTER: 'E',"earth elemental",random
-MONSTER: 'E',"earth elemental",random
-MONSTER: 'E',"earth elemental",random
-MONSTER: 'E',"earth elemental",random
-MONSTER: 'E',"earth elemental",random
-MONSTER: 'X',"xorn",random
-MONSTER: 'X',"xorn",random
-MONSTER: 'X',"xorn",random
-MONSTER: 'X',"xorn",random
-MONSTER: 'X',"xorn",random
-MONSTER: 'X',"xorn",random
-MONSTER: 'X',"xorn",random
-MONSTER: 'X',"xorn",random
-MONSTER: 'X',"xorn",random
+LOOP [13 + 2d5] {
+  MONSTER: ('E',"earth elemental"),random
+}
+LOOP [8 + 1d6] {
+  MONSTER: ('X',"xorn"),random
+}
 
 #
@@ -196,6 +202,8 @@
 #
 
-MAZE: "Mon-goal", ' '
-INIT_MAP: 'L' , '.' , false , false , unlit , false
+LEVEL: "Mon-goal"
+FLAGS:mazelevel
+INIT_MAP: mines, 'L' , '.' , false , false , unlit , false
+MON_GENERATION:86%, (64,"earth elemental"), (16,'E'), (16,"xorn"), (4,'X')
 GEOMETRY:center,center
 MAP
@@ -213,52 +221,35 @@
 ENDMAP
 # Dungeon Description
-RANDOM_PLACES:(14,04),(13,07)
+$place = { (14,04),(13,07) }
+SHUFFLE:$place
 REGION:(00,00,25,10),unlit,"ordinary"
 # Stairs
 STAIR:(20,05),up
 # Objects
-OBJECT:'(',"lenses",place[0],blessed,0,"The Eyes of the Overworld"
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
+OBJECT:('(',"lenses"),$place[0],blessed,0,NAME:"The Eyes of the Overworld"
+LOOP [10 + 1d10] {
+  OBJECT:random,random
+}
 # Random traps
+LOOP [3 + 1d3] {
 TRAP:"fire",random
-TRAP:"fire",random
-TRAP:"fire",random
-TRAP:"fire",random
+}
 TRAP:random,random
 TRAP:random,random
 # Random monsters.
-MONSTER:'@',"Master Kaen",place[0]
-ALTAR:place[0],noalign,altar
-MONSTER: 'E',"earth elemental",random
-MONSTER: 'E',"earth elemental",random
-MONSTER: 'E',"earth elemental",random
-MONSTER: 'E',"earth elemental",random
-MONSTER: 'E',"earth elemental",random
-MONSTER: 'E',"earth elemental",random
-MONSTER: 'E',"earth elemental",random
-MONSTER: 'E',"earth elemental",random
-MONSTER: 'E',"earth elemental",random
-MONSTER: 'X',"xorn",random
-MONSTER: 'X',"xorn",random
-MONSTER: 'X',"xorn",random
-MONSTER: 'X',"xorn",random
-MONSTER: 'X',"xorn",random
-MONSTER: 'X',"xorn",random
-MONSTER: 'X',"xorn",random
-MONSTER: 'X',"xorn",random
-MONSTER: 'X',"xorn",random
+MONSTER:('@',"Master Kaen"),$place[0] {
+  OBJECT:('(', "Bell of Opening"),uncursed
+  OBJECT:')',1d4
+  OBJECT:'?'
+  OBJECT:'?'
+  OBJECT:'?'
+}
+ALTAR:$place[0],noalign,altar
+LOOP [10 + 1d6] {
+  MONSTER: ('E',"earth elemental"),random
+}
+LOOP [10 + 1d6] {
+  MONSTER: ('X',"xorn"),random
+}
 
 #
@@ -272,81 +263,105 @@
 
 LEVEL: "Mon-fila"
+MON_GENERATION:86%, (64,"earth elemental"), (16,'E'), (16,"xorn"), (4,'X')
 # Random Monsters
-RANDOM_MONSTERS: 'E', 'X'
 #
 ROOM: "ordinary" , random, random, random, random
+{
 STAIR: random, up
-OBJECT: random,random,random
-MONSTER: 'E', random, random, hostile
+OBJECT: random,random
+MONSTER: 'E', random, hostile
+}
 
 ROOM: "ordinary" , random, random, random, random
-OBJECT: random, random, random
-OBJECT: random,random,random
-MONSTER: 'E', random, random, hostile
+{
+OBJECT: random, random
+OBJECT: random, random
+MONSTER: 'E', random, hostile
+}
 
 ROOM: "ordinary" , random, random, random, random
-OBJECT: random, random, random
+{
+OBJECT: random, random
 TRAP: random, random
-OBJECT: random,random,random
-MONSTER: 'X', "xorn", random
-MONSTER: 'E', "earth elemental", random
+OBJECT: random, random
+MONSTER: ('X', "xorn"), random
+MONSTER: ('E', "earth elemental"), random
+}
 
 ROOM: "ordinary" , random, random, random, random
+{
 STAIR: random, down
-OBJECT: random, random, random
+OBJECT: random, random
 TRAP: random, random
-MONSTER: 'E', random, random, hostile
-MONSTER: 'E', "earth elemental", random
+MONSTER: 'E', random, hostile
+MONSTER: ('E', "earth elemental"), random
+}
 
 ROOM: "ordinary" , random, random, random, random
-OBJECT: random, random, random
-OBJECT: random, random, random
+{
+OBJECT: random, random
+OBJECT: random, random
 TRAP: random, random
-MONSTER: 'X', random, random, hostile
+MONSTER: 'X', random, hostile
+}
 
 ROOM: "ordinary" , random, random, random, random
-OBJECT: random, random, random
+{
+OBJECT: random, random
 TRAP: random, random
-MONSTER: 'E', "earth elemental", random
+MONSTER: ('E', "earth elemental"), random
+}
 
 RANDOM_CORRIDORS
 
 LEVEL: "Mon-filb"
+MON_GENERATION:86%, (64,"earth elemental"), (16,'E'), (16,"xorn"), (4,'X')
 # Random Monsters
-RANDOM_MONSTERS: 'E', 'X'
 #
 ROOM: "ordinary" , random, random, random, random
+{
 STAIR: random, up
-OBJECT: random,random,random
-MONSTER: 'X', random, random, hostile
+OBJECT: random,random
+MONSTER: 'X', random, hostile
+}
 
 ROOM: "ordinary" , random, random, random, random
-OBJECT: random, random, random
-OBJECT: random,random,random
-MONSTER: 'X', random, random, hostile
+{
+OBJECT: random, random
+OBJECT: random, random
+MONSTER: 'X', random, hostile
+}
 
 ROOM: "ordinary" , random, random, random, random
-OBJECT: random, random, random
+{
+OBJECT: random, random
 TRAP: random, random
-OBJECT: random,random,random
-MONSTER: 'E', random, random, hostile
+OBJECT: random, random
+MONSTER: 'E', random, hostile
+}
 
 ROOM: "ordinary" , random, random, random, random
+{
 STAIR: random, down
-OBJECT: random, random, random
+OBJECT: random, random
 TRAP: random, random
-MONSTER: 'E', random, random, hostile
-MONSTER: 'E', "earth elemental", random
+MONSTER: 'E', random, hostile
+MONSTER: ('E', "earth elemental"), random
+}
 
 ROOM: "ordinary" , random, random, random, random
-OBJECT: random, random, random
-OBJECT: random, random, random
+{
+OBJECT: random, random
+OBJECT: random, random
 TRAP: random, random
-MONSTER: 'X', random, random, hostile
+MONSTER: 'X', random, hostile
+}
 
 ROOM: "ordinary" , random, random, random, random
-OBJECT: random, random, random
+{
+OBJECT: random, random
 TRAP: random, random
-MONSTER: 'E', "earth elemental", random
+MONSTER: ('E', "earth elemental"), random
+}
 
 RANDOM_CORRIDORS
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/dat/opthelp nethack/dat/opthelp
--- nh_orig/dat/opthelp	2003-12-07 18:39:13.000000000 -0500
+++ nethack/dat/opthelp	2009-08-02 13:49:39.554408799 -0400
@@ -93,4 +93,7 @@
 disclose      the types of information you want offered at the end of the
               game  [ni na nv ng nc]
+dumpfile      the name of the file where to dump the disclosure information
+              when the game ends (only if the patch has been compiled in)
+              [none]
 fruit         the name of a fruit you enjoy eating  [slime mold]
               (basically a whimsy which NetHack uses from time to time).
@@ -121,4 +124,9 @@
               You choose a combination of top scores, scores around the top
               scores, and all of your own scores.  [!own/3 top/2 around]
+sortloot      controls the sortloot patch [none]:
+              full -- All pickup lists of items are sorted by item description
+              loot -- When inventory letters are shown, has no effect.
+                      Otherwise sorts by description
+              none -- Works the traditional way, like without the patch
 suppress_alert disable various version-specific warnings about changes
               in game play or the user interface, such as notification given
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/dat/oracle.des nethack/dat/oracle.des
--- nh_orig/dat/oracle.des	2003-12-07 18:39:13.000000000 -0500
+++ nethack/dat/oracle.des	2010-04-11 12:36:58.149750771 -0400
@@ -8,49 +8,67 @@
 
 ROOM: "ordinary" , lit, (3,3), (center,center), (11,9)
-NAME: "central"
-OBJECT:'`',"statue",(0,0),"forest centaur",1
-OBJECT:'`',"statue",(0,8),"mountain centaur",1
-OBJECT:'`',"statue",(10,0),"mountain centaur",1
-OBJECT:'`',"statue",(10,8),"forest centaur",1
-OBJECT:'`',"statue",(5,1),"plains centaur",1
-OBJECT:'`',"statue",(5,7),"plains centaur",1
-OBJECT:'`',"statue",(2,4),"plains centaur",1
-OBJECT:'`',"statue",(8,4),"plains centaur",1
-MONSTER: random, random, random
-MONSTER: random, random, random
+{
 
-SUBROOM: "delphi" , lit , (4,3) , (3,3), "central"
+SUBROOM: "delphi" , lit , (4,3) , (3,3)
+{
 FOUNTAIN: (0, 1)
 FOUNTAIN: (1, 0)
 FOUNTAIN: (1, 2)
 FOUNTAIN: (2, 1)
-MONSTER: '@', "Oracle", (1,1)
-DOOR: false , nodoor , random, random
+MONSTER: ('@', "Oracle"), (1,1) {
+  OBJECT:'!'
+  OBJECT:'?'
+}
+ROOMDOOR: false , nodoor , random, random
+}
+
+OBJECT:('`',"statue"),(0,0),montype:'C',1
+OBJECT:('`',"statue"),(0,8),montype:'C',1
+OBJECT:('`',"statue"),(10,0),montype:'C',1
+OBJECT:('`',"statue"),(10,8),montype:'C',1
+OBJECT:('`',"statue"),(5,1),montype:'C',1
+OBJECT:('`',"statue"),(5,7),montype:'C',1
+OBJECT:('`',"statue"),(2,4),montype:'C',1
+OBJECT:('`',"statue"),(8,4),montype:'C',1
+MONSTER: random, random
+MONSTER: random, random
+
+}
 
 ROOM: "ordinary" , random, random, random, random
+{
 STAIR: random, up
-OBJECT: random,random,random
+OBJECT: random,random
+}
 
 ROOM: "ordinary" , random, random, random, random
+{
 STAIR: random, down
-OBJECT: random, random, random
+OBJECT: random, random
 TRAP: random, random
-MONSTER: random, random, random
-MONSTER: random, random, random
+MONSTER: random, random
+MONSTER: random, random
+}
 
 ROOM: "ordinary" , random, random, random, random
-OBJECT: random, random, random
-OBJECT: random, random, random
-MONSTER: random, random, random
+{
+OBJECT: random, random
+OBJECT: random, random
+MONSTER: random, random
+}
 
 ROOM: "ordinary" , random, random, random, random
-OBJECT: random, random, random
+{
+OBJECT: random, random
 TRAP: random, random
-MONSTER: random, random, random
+MONSTER: random, random
+}
 
 ROOM: "ordinary" , random, random, random, random
-OBJECT: random, random, random
+{
+OBJECT: random, random
 TRAP: random, random
-MONSTER: random, random, random
+MONSTER: random, random
+}
 
 RANDOM_CORRIDORS
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/dat/Priest.des nethack/dat/Priest.des
--- nh_orig/dat/Priest.des	2003-12-07 18:39:12.000000000 -0500
+++ nethack/dat/Priest.des	2010-05-02 09:11:33.865714749 -0400
@@ -9,6 +9,11 @@
 #	and receive your quest assignment.
 #
-MAZE: "Pri-strt",' '
-FLAGS: noteleport,hardfloor
+# All Priest quest levels are explicitly marked as graveyards
+# so there's less chance for undead corpses.
+#
+LEVEL: "Pri-strt"
+FLAGS: noteleport,hardfloor,mazelevel,graveyard
+INIT_MAP:solidfill,('.',lit)
+MON_GENERATION:86%, (64,"human zombie"), (16,'Z'), (16,"wraith"), (4,'W')
 GEOMETRY:center,center
 MAP
@@ -20,10 +25,10 @@
 ....................|..------------..|--+-----+-----+--|....................
 ....................|..|..........|..|.................|....................
-....................|..|..........|..|+---+---+-----+--|....................
+....................|..|..........|..|+----------------|....................
 ..................---..|..........|......|...|...|.....|....................
 ..................+....|..........+......|...|...|.....|....................
 ..................+....|..........+......|...|...|.....|....................
 ..................---..|..........|......|...|...|.....|....................
-....................|..|..........|..|+-----+---+---+--|....................
+....................|..|..........|..|+----------------|....................
 ....................|..|..........|..|.................|....................
 ....................|..------------..|--+-----+-----+--|....................
@@ -37,5 +42,22 @@
 REGION:(00,00,75,19),lit,"ordinary"
 REGION:(24,06,33,13),lit,"temple"
+REGION:(42,08,44,11),lit,"ordinary",unfilled,true {
+  ROOMDOOR:false, closed, north|south|west|east, random
+  ROOMDOOR:false, locked, north|south|west|east, random
+}
+REGION:(46,08,48,11),lit,"ordinary",unfilled,true {
+  ROOMDOOR:false, closed, north|south|west|east, random
+  ROOMDOOR:false, locked, north|south|west|east, random
+}
+REGION:(50,08,54,11),lit,"ordinary",unfilled,true {
+  ROOMDOOR:false, closed, north|south|west, random
+  ROOMDOOR:false, locked, north|south|west, random
+}
+
+REPLACE_TERRAIN:(0,0,10,19),'.','T',10%
+REPLACE_TERRAIN:(65,0,75,19),'.','T',10%
+
 # Portal arrival point
+TERRAIN:(05,04),'.'
 BRANCH:(05,04,05,04),(0,0,0,0)
 # Stairs
@@ -50,11 +72,5 @@
 DOOR:closed,(52,05)
 DOOR:locked,(38,07)
-DOOR:closed,(42,07)
-DOOR:closed,(46,07)
-DOOR:closed,(52,07)
 DOOR:locked,(38,12)
-DOOR:closed,(44,12)
-DOOR:closed,(48,12)
-DOOR:closed,(52,12)
 DOOR:closed,(40,14)
 DOOR:closed,(46,14)
@@ -63,16 +79,40 @@
 ALTAR:(28,09),noalign,altar
 # High Priest
-MONSTER:'@',"Arch Priest",(28,10)
+MONSTER:('@',"Arch Priest"),(28,10) {
+  OBJECT:('[',"robe"),1d4
+  OBJECT:'?'
+  OBJECT:'?'
+  OBJECT:'?'
+  OBJECT:'?'
+  OBJECT:'+'
+  OBJECT:'+'
+}
 # The treasure of High Priest
-OBJECT:'(',"chest",(27,10)
+OBJECT:('(',"chest"),(27,10)
 # knight guards for the audience chamber
-MONSTER:'@',"acolyte",(32,07)
-MONSTER:'@',"acolyte",(32,08)
-MONSTER:'@',"acolyte",(32,11)
-MONSTER:'@',"acolyte",(32,12)
-MONSTER:'@',"acolyte",(33,07)
-MONSTER:'@',"acolyte",(33,08)
-MONSTER:'@',"acolyte",(33,11)
-MONSTER:'@',"acolyte",(33,12)
+MONSTER:('@',"acolyte"),(32,07) {
+  OBJECT:'?'
+}
+MONSTER:('@',"acolyte"),(32,08) {
+  OBJECT:'?'
+}
+MONSTER:('@',"acolyte"),(32,11) {
+  OBJECT:'?'
+}
+MONSTER:('@',"acolyte"),(32,12) {
+  OBJECT:'?'
+}
+MONSTER:('@',"acolyte"),(33,07) {
+  OBJECT:'?'
+}
+MONSTER:('@',"acolyte"),(33,08) {
+  OBJECT:'?'
+}
+MONSTER:('@',"acolyte"),(33,11) {
+  OBJECT:'?'
+}
+MONSTER:('@',"acolyte"),(33,12) {
+  OBJECT:'?'
+}
 # Non diggable walls
 NON_DIGGABLE:(00,00,75,19)
@@ -85,16 +125,16 @@
 TRAP:random,random
 # Monsters on siege duty.
-MONSTER: 'Z',"human zombie",(37,01)
-MONSTER: 'Z',"human zombie",(37,18)
-MONSTER: 'Z',"human zombie",(03,03)
-MONSTER: 'Z',"human zombie",(65,04)
-MONSTER: 'Z',"human zombie",(12,11)
-MONSTER: 'Z',"human zombie",(60,12)
-MONSTER: 'Z',"human zombie",(14,08)
-MONSTER: 'Z',"human zombie",(55,00)
-MONSTER: 'Z',"human zombie",(18,18)
-MONSTER: 'Z',"human zombie",(59,10)
-MONSTER: 'Z',"human zombie",(13,09)
-MONSTER: 'Z',"human zombie",(01,17)
+MONSTER: ('Z',"human zombie"),(37,01)
+MONSTER: ('Z',"human zombie"),(37,18)
+MONSTER: ('Z',"human zombie"),(03,03)
+MONSTER: ('Z',"human zombie"),(65,04)
+MONSTER: ('Z',"human zombie"),(12,11)
+MONSTER: ('Z',"human zombie"),(60,12)
+MONSTER: ('Z',"human zombie"),(14,08)
+MONSTER: ('Z',"human zombie"),(55,00)
+MONSTER: ('Z',"human zombie"),(18,18)
+MONSTER: ('Z',"human zombie"),(59,10)
+MONSTER: ('Z',"human zombie"),(13,09)
+MONSTER: ('Z',"human zombie"),(01,17)
 
 #
@@ -105,8 +145,8 @@
 #
 
-MAZE: "Pri-loca",' '
-FLAGS: hardfloor
-# This is a kludge to init the level as a lit field.
-INIT_MAP: '.' , '.' , false , false , lit , false
+LEVEL: "Pri-loca"
+FLAGS: hardfloor,mazelevel,graveyard
+INIT_MAP: solidfill, ('.', lit)
+MON_GENERATION:86%, (64,"human zombie"), (16,'Z'), (16,"wraith"), (4,'W')
 GEOMETRY:center,center
 MAP
@@ -134,5 +174,5 @@
 # The altar inside the temple
 ALTAR:(20,07),noalign,shrine
-MONSTER:'@',"aligned priest",(20,07),noalign,hostile
+MONSTER:('@',"aligned priest"),(20,07),noalign,hostile
 # Doors
 DOOR:locked,(10,06)
@@ -149,19 +189,19 @@
 NON_DIGGABLE:(10,02,30,13)
 # Objects (inside the antechambers).
-OBJECT:random,random,(14,03)
-OBJECT:random,random,(15,03)
-OBJECT:random,random,(16,03)
-OBJECT:random,random,(14,10)
-OBJECT:random,random,(15,10)
-OBJECT:random,random,(16,10)
-OBJECT:random,random,(17,10)
-OBJECT:random,random,(24,03)
-OBJECT:random,random,(25,03)
-OBJECT:random,random,(26,03)
-OBJECT:random,random,(27,03)
-OBJECT:random,random,(24,10)
-OBJECT:random,random,(25,10)
-OBJECT:random,random,(26,10)
-OBJECT:random,random,(27,10)
+OBJECT:random,(14,03)
+OBJECT:random,(15,03)
+OBJECT:random,(16,03)
+OBJECT:random,(14,10)
+OBJECT:random,(15,10)
+OBJECT:random,(16,10)
+OBJECT:random,(17,10)
+OBJECT:random,(24,03)
+OBJECT:random,(25,03)
+OBJECT:random,(26,03)
+OBJECT:random,(27,03)
+OBJECT:random,(24,10)
+OBJECT:random,(25,10)
+OBJECT:random,(26,10)
+OBJECT:random,(27,10)
 # Random traps
 TRAP:random,(15,04)
@@ -181,6 +221,8 @@
 #
 
-MAZE: "Pri-goal", ' '
-INIT_MAP: 'L' , '.' , false , false , unlit , false
+LEVEL: "Pri-goal"
+FLAGS:mazelevel,graveyard
+INIT_MAP: mines, 'L' , '.' , false , false , unlit , false
+MON_GENERATION:86%, (64,"human zombie"), (16,'Z'), (16,"wraith"), (4,'W')
 GEOMETRY:center,center
 MAP
@@ -198,24 +240,14 @@
 ENDMAP
 # Dungeon Description
-RANDOM_PLACES:(14,04),(13,07)
+$place = { (14,04),(13,07) }
+SHUFFLE: $place
 REGION:(00,00,25,10),unlit,"ordinary"
 # Stairs
 STAIR:(20,05),up
 # Objects
-OBJECT:'[',"helm of brilliance",place[0],blessed,0,"The Mitre of Holiness"
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
+OBJECT:('[',"helm of brilliance"),$place[0],blessed,0,NAME:"The Mitre of Holiness"
+LOOP [10 + 1d6] {
+  OBJECT:random,random
+}
 # Random traps
 TRAP:"fire",random
@@ -226,32 +258,18 @@
 TRAP:random,random
 # Random monsters.
-MONSTER:'&',"Nalzok",place[0]
-MONSTER:'Z',"human zombie",random
-MONSTER:'Z',"human zombie",random
-MONSTER:'Z',"human zombie",random
-MONSTER:'Z',"human zombie",random
-MONSTER:'Z',"human zombie",random
-MONSTER:'Z',"human zombie",random
-MONSTER:'Z',"human zombie",random
-MONSTER:'Z',"human zombie",random
-MONSTER:'Z',"human zombie",random
-MONSTER:'Z',"human zombie",random
-MONSTER:'Z',"human zombie",random
-MONSTER:'Z',"human zombie",random
-MONSTER:'Z',"human zombie",random
-MONSTER:'Z',"human zombie",random
-MONSTER:'Z',"human zombie",random
-MONSTER:'Z',"human zombie",random
-MONSTER:'Z',random,random
-MONSTER:'Z',random,random
-MONSTER:'W',"wraith",random
-MONSTER:'W',"wraith",random
-MONSTER:'W',"wraith",random
-MONSTER:'W',"wraith",random
-MONSTER:'W',"wraith",random
-MONSTER:'W',"wraith",random
-MONSTER:'W',"wraith",random
-MONSTER:'W',"wraith",random
-MONSTER:'W',random,random
+MONSTER:('&',"Nalzok"),$place[0] {
+  OBJECT:('(', "Bell of Opening"),uncursed
+  OBJECT:')',1d6
+  OBJECT:'[',1d3
+}
+LOOP [15 + 2d5] {
+  MONSTER:('Z',"human zombie"),random
+}
+MONSTER:'Z',random
+MONSTER:'Z',random
+LOOP [4 + 2d4] {
+  MONSTER:('W',"wraith"),random
+}
+MONSTER:'W',random
 
 #
@@ -265,73 +283,101 @@
 
 LEVEL: "Pri-fila"
+FLAGS:graveyard
+MON_GENERATION:86%, (64,"human zombie"), (16,'Z'), (16,"wraith"), (4,'W')
 #
 ROOM: "ordinary" , random, random, random, random
+{
 STAIR: random, up
-OBJECT: random,random,random
-MONSTER: 'Z', "human zombie", random
+OBJECT: random,random
+MONSTER: ('Z', "human zombie"), random
+}
 
 ROOM: "ordinary" , random, random, random, random
-OBJECT: random, random, random
-OBJECT: random,random,random
+{
+OBJECT: random, random
+OBJECT: random,random
+}
 
 ROOM: "ordinary" , random, random, random, random
-OBJECT: random, random, random
+{
+OBJECT: random, random
 TRAP: random, random
-OBJECT: random,random,random
-MONSTER: 'Z', "human zombie", random
+OBJECT: random,random
+MONSTER: ('Z', "human zombie"), random
+}
 
 ROOM: "morgue" , random, random, random, random
+{
 STAIR: random, down
-OBJECT: random, random, random
+OBJECT: random, random
 TRAP: random, random
+}
 
 ROOM: "ordinary" , random, random, random, random
-OBJECT: random, random, random
-OBJECT: random, random, random
+{
+OBJECT: random, random
+OBJECT: random, random
 TRAP: random, random
-MONSTER: 'W', "wraith", random
+MONSTER: ('W', "wraith"), random
+}
 
 ROOM: "morgue" , random, random, random, random
-OBJECT: random, random, random
+{
+OBJECT: random, random
 TRAP: random, random
+}
 
 RANDOM_CORRIDORS
 
 LEVEL: "Pri-filb"
+FLAGS:graveyard
+MON_GENERATION:86%, (64,"human zombie"), (16,'Z'), (16,"wraith"), (4,'W')
 #
 ROOM: "ordinary" , random, random, random, random
+{
 STAIR: random, up
-OBJECT: random,random,random
-MONSTER: 'Z', "human zombie", random
-MONSTER: 'W', "wraith", random
+OBJECT: random,random
+MONSTER: ('Z', "human zombie"), random
+MONSTER: ('W', "wraith"), random
+}
 
 ROOM: "morgue" , random, random, random, random
-OBJECT: random, random, random
-OBJECT: random, random, random
-OBJECT: random,random,random
+{
+OBJECT: random, random
+OBJECT: random, random
+OBJECT: random,random
+}
 
 ROOM: "ordinary" , random, random, random, random
-OBJECT: random, random, random
+{
+OBJECT: random, random
 TRAP: random, random
-OBJECT: random,random,random
-MONSTER: 'Z', "human zombie", random
-MONSTER: 'W', "wraith", random
+OBJECT: random,random
+MONSTER: ('Z', "human zombie"), random
+MONSTER: ('W', "wraith"), random
+}
 
 ROOM: "morgue" , random, random, random, random
+{
 STAIR: random, down
-OBJECT: random, random, random
-OBJECT: random, random, random
+OBJECT: random, random
+OBJECT: random, random
 TRAP: random, random
+}
 
 ROOM: "ordinary" , random, random, random, random
-OBJECT: random, random, random
-OBJECT: random, random, random
+{
+OBJECT: random, random
+OBJECT: random, random
 TRAP: random, random
-MONSTER: 'Z', "human zombie", random
-MONSTER: 'W', "wraith", random
+MONSTER: ('Z', "human zombie"), random
+MONSTER: ('W', "wraith"), random
+}
 
 ROOM: "morgue" , random, random, random, random
-OBJECT: random, random, random
+{
+OBJECT: random, random
 TRAP: random, random
+}
 
 RANDOM_CORRIDORS
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/dat/quest.txt nethack/dat/quest.txt
--- nh_orig/dat/quest.txt	2003-12-07 18:39:13.000000000 -0500
+++ nethack/dat/quest.txt	2009-08-02 13:49:39.540409141 -0400
@@ -360,5 +360,5 @@
 "Pah!  You have betrayed the gods, %p.  You will never attain
 the glory which you aspire to.  Your failure to follow the true path has
-closed this future to you.
+closed that future to you.
 
 "I will protect these people as best I can, but soon %n will overcome
@@ -560,10 +560,10 @@
 #
 %Cc Cav 00001
-You descend through a barely familiar stairwell that you remember
+You walk through a barely familiar overgrown path that you remember
 %l showing you when you embarked upon your vision quest.
 
-You arrive back at %H, but something seems
-wrong here.  The usual smoke and glowing light of the fires of the
-outer caves are absent, and an uneasy quiet fills the damp air.
+You arrive back at %H, ... but something seems
+wrong here.  The jungle has a tense aura about it, and the beasts
+are snarling and hostile.  An uneasy quiet fills the damp air.
 %E
 %Cp Cav 00002
@@ -620,6 +620,5 @@
 %E
 %Cc Cav 00018
-"%pC!  You have sealed our fate.  You seem unable to reform yourself,
-so I must select another to take your place.
+"%pC!  You have sealed our fate by being unable to reform yourself.
 
 "Begone from %H!  You have betrayed us by choosing
@@ -640,5 +639,5 @@
 %Cc Cav 00020
 "%pC!  You have deviated from my teachings.  You no longer follow
-the path of the %a as you should.  I banish you from these caves, to
+the path of the %a as you should.  I banish you from this temple, to
 go forth and purify yourself.  Then, you might be able to accomplish this
 quest."
@@ -648,5 +647,5 @@
 great suffering among your people:
 
-"Shortly after you left on your vision quest, the caves were invaded by
+"Shortly after you left on your vision quest, the jungle was invaded by
 the creatures sent against us by %n.
 
@@ -655,10 +654,13 @@
 minions of %n managed to steal %o.
 They took it to %i and there, none of our
-%g warriors have been able to go.
+%g warriors have been able to go.  Worse, she has invoked its power
+against us, and now conflict ravages our once-peaceful jungle.
 
 "You must find %i, and within it wrest
 %o from %n.  She guards it as
 jealously as she guards all treasures she attains.  But with it,
-we can make our caves safe once more.
+we can make our jungle safe once more.  Without it, the spirit of the
+jungle cries out in pain, and the animals are crazed and attack all
+who pass near.
 
 "Please, %p, recover %o for us, and return it here."
@@ -699,10 +701,10 @@
 %E
 %Cc Cav 00035
-You %x many large claw marks on the ground.  The tunnels ahead
-of you are larger than most of those in any cave complex you have
-ever been in before.
+You %x many large claw marks on the ground.  Your brief respite 
+from the narrow jungle confines appears to be over... many paths lead
+into the trees in all directions, and stagnant pools cover the ground.
 
-Your nose detects the smell of carrion from within, and bones litter
-the sides of the tunnels.
+Your nose detects the smell of carrion from somewhere deep within, and
+unidentifiable, gnawed bones litter the nearby underbrush.
 %E
 %Cp Cav 00036
@@ -713,5 +715,5 @@
 nevertheless show signs of being scorched by fire.
 
-Bones litter the floor, and there are objects scattered everywhere.
+Bones cover the floor, and there are objects scattered everywhere.
 The air is close with the stench of sulphurous fumes.
 
@@ -784,4 +786,10 @@
     own.
 
+He takes it from your hands and does something you cannot see. You 
+feel the very trees relax as the magic-induced hatred melts away from
+the land.
+
+He returns it to you and says:
+
     To prevent further trouble, I would like you, %p,
     to take %o away with you.  It will help you as you
@@ -1149,13 +1157,13 @@
 far is a credit to thy valor, but thou art yet unprepared for
 the demands required as Our Champion.  %rA, no matter how
-pure, could never hope to defeat the foul %n.
+brave, could never hope to defeat the foul %n.
 
 "Journey forth from this place, and hone thy skills.  Return to
-Our presence when thou hast attained the noble title of %R."
+Our presence when thou hast attained the title of %R."
 %E
 %Cc Kni 00020
-"Thou dishonourest Us, %p!  Thou hast strayed from the path of
-chivalry! Go from Our presence and do penance.  Only when thou art again
-pure mayst thou return hence."
+"Thou dishonourest Us, %p!  Thou hast strayed from thine chosen 
+path!  Go from Our presence and do penance.  Only when thou 
+hast regained thy soul's direction mayst thou return hence."
 %E
 %Cc Kni 00021
@@ -2139,8 +2147,6 @@
 "Well %gp, it looks like our friend has forgotten who is the boss
 around here.  Our friend seems to think that %rp have been put in
-charge.  Wrong.  DEAD WRONG!"
+charge.  Wrong.  DEAD wrong, in fact..."
 
-Your sudden shift in surroundings prevents you from hearing the end
-of %ls curse.
 %E
 %Cc Rog 00019
@@ -2885,6 +2891,6 @@
 %Cc Val 00018
 "No, %p.  Your fate is sealed.  I must cast about for another
-champion.  Begone from my presence, and never return.  Know this, that
-you shall never succeed in this life, and Valhalla is denied to you."
+champion.  Begone from my presence, and never return.  Know that
+Valhalla shall be denied to you."
 %E
 %Cc Val 00019
@@ -3463,10 +3469,9 @@
 have done.
 
-Leave this place.  You shall never set foot at %H again.
-That which you seek is now lost forever, for without the Bell of Opening, 
-you will never be able to enter the place where he who has the Amulet 
-resides.
+Leave this place. You shall never set foot beyond %H again as long as I
+draw breath... and without the Bell of Opening, you will never be able to 
+enter the place where he who has the Amulet resides.
 
-Go now!  You are banished from this place.
+Begone from my sight!"
 %E
 #
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/dat/Ranger.des nethack/dat/Ranger.des
--- nh_orig/dat/Ranger.des	2003-12-07 18:39:12.000000000 -0500
+++ nethack/dat/Ranger.des	2010-08-16 13:20:13.633706782 -0400
@@ -9,12 +9,14 @@
 #	and receive your quest assignment.
 #
-MAZE: "Ran-strt",'.'
-FLAGS: noteleport,hardfloor,arboreal
-INIT_MAP:'.','.',true,true,lit,false
-GEOMETRY:left,center
+LEVEL: "Ran-strt"
+FLAGS: noteleport,hardfloor,arboreal,mazelevel
+INIT_MAP:mines,'.','.',true,true,lit,false
+REPLACE_TERRAIN:(0,0,76,19),'.', 'T', 5%
+MON_GENERATION:86%, (64,"forest centaur"), (16,'C'), (16,"scorpion"), (4,'s')
+GEOMETRY:(0,1)
 #1234567890123456789012345678901234567890123456789012345678901234567890
 MAP
-                                       ..
-   ...................................  .
+                                       xx
+   ...................................  x
   ..                                 ..  
  ..  ...............F...............  .. 
@@ -34,6 +36,6 @@
  ..  ...............F...............  .. 
   ..                                 ..  
-   ...................................  .
-                                       ..
+   ...................................  x
+                                       xx
 ENDMAP
 # Dungeon Description
@@ -44,16 +46,56 @@
 BRANCH:levregion(51,2,77,18),(0,0,40,20)
 # Orion
-MONSTER:'@',"Orion",(20,10)
+MONSTER:('@',"Orion"),(20,10) {
+  OBJECT:('[',"leather armor"),1d4
+  OBJECT:(')',"yumi"),1d4
+  OBJECT:(')',"arrow"),1d4,quantity:10d5
+}
 # The treasure of Orion
-OBJECT:'(',"chest",(20,10)
+OBJECT:('(',"chest"),(20,10)
 # Guards for the audience chamber
-MONSTER:'@',"hunter",(19,09)
-MONSTER:'@',"hunter",(20,09)
-MONSTER:'@',"hunter",(21,09)
-MONSTER:'@',"hunter",(19,10)
-MONSTER:'@',"hunter",(21,10)
-MONSTER:'@',"hunter",(19,11)
-MONSTER:'@',"hunter",(20,11)
-MONSTER:'@',"hunter",(21,11)
+MONSTER:('@',"hunter"),(19,09) {
+  OBJECT[25%]:('[',"leather armor")
+  IF [50%] {
+    OBJECT:(')',"bow")
+    OBJECT:(')',"arrow")
+  }
+  OBJECT[15%]:')'
+}
+MONSTER:('@',"hunter"),(20,09) {
+  OBJECT[25%]:('[',"leather armor")
+  IF [50%] {
+    OBJECT:(')',"bow")
+    OBJECT:(')',"arrow")
+  }
+  OBJECT[15%]:')'
+}
+MONSTER:('@',"hunter"),(21,09) {
+  OBJECT[25%]:('[',"leather armor")
+  IF [50%] {
+    OBJECT:(')',"bow")
+    OBJECT:(')',"arrow")
+  }
+  OBJECT[15%]:')'
+}
+MONSTER:('@',"hunter"),(19,10) {
+  OBJECT[25%]:('[',"leather armor")
+  OBJECT[15%]:')'
+}
+MONSTER:('@',"hunter"),(21,10) {
+  OBJECT[25%]:('[',"leather armor")
+  OBJECT[15%]:')'
+}
+MONSTER:('@',"hunter"),(19,11) {
+  OBJECT[25%]:('[',"leather armor")
+  OBJECT[15%]:')'
+}
+MONSTER:('@',"hunter"),(20,11) {
+  OBJECT[25%]:('[',"leather armor")
+  OBJECT[15%]:')'
+}
+MONSTER:('@',"hunter"),(21,11) {
+  OBJECT[25%]:('[',"leather armor")
+  OBJECT[15%]:')'
+}
 # Non diggable walls
 NON_DIGGABLE:(00,00,40,20)
@@ -66,31 +108,28 @@
 TRAP:"bear",random
 # Monsters on siege duty.
-MONSTER: 'H',"minotaur",(33,09),hostile,asleep
-MONSTER: 'C',"forest centaur",(19,03),hostile
-MONSTER: 'C',"forest centaur",(19,04),hostile
-MONSTER: 'C',"forest centaur",(19,05),hostile
-MONSTER: 'C',"forest centaur",(21,03),hostile
-MONSTER: 'C',"forest centaur",(21,04),hostile
-MONSTER: 'C',"forest centaur",(21,05),hostile
-MONSTER: 'C',"forest centaur",(01,09),hostile
-MONSTER: 'C',"forest centaur",(02,09),hostile
-MONSTER: 'C',"forest centaur",(03,09),hostile
-MONSTER: 'C',"forest centaur",(01,11),hostile
-MONSTER: 'C',"forest centaur",(02,11),hostile
-MONSTER: 'C',"forest centaur",(03,11),hostile
-MONSTER: 'C',"forest centaur",(19,15),hostile
-MONSTER: 'C',"forest centaur",(19,16),hostile
-MONSTER: 'C',"forest centaur",(19,17),hostile
-MONSTER: 'C',"forest centaur",(21,15),hostile
-MONSTER: 'C',"forest centaur",(21,16),hostile
-MONSTER: 'C',"forest centaur",(21,17),hostile
-MONSTER: 'C',"plains centaur",random,hostile
-MONSTER: 'C',"plains centaur",random,hostile
-MONSTER: 'C',"plains centaur",random,hostile
-MONSTER: 'C',"plains centaur",random,hostile
-MONSTER: 'C',"plains centaur",random,hostile
-MONSTER: 'C',"plains centaur",random,hostile
-MONSTER: 's',"scorpion",random,hostile
-MONSTER: 's',"scorpion",random,hostile
+MONSTER: ('H',"minotaur"),(33,09),hostile,asleep
+MONSTER: ('C',"forest centaur"),(19,03),hostile
+MONSTER: ('C',"forest centaur"),(19,04),hostile
+MONSTER: ('C',"forest centaur"),(19,05),hostile
+MONSTER: ('C',"forest centaur"),(21,03),hostile
+MONSTER: ('C',"forest centaur"),(21,04),hostile
+MONSTER: ('C',"forest centaur"),(21,05),hostile
+MONSTER: ('C',"forest centaur"),(01,09),hostile
+MONSTER: ('C',"forest centaur"),(02,09),hostile
+MONSTER: ('C',"forest centaur"),(03,09),hostile
+MONSTER: ('C',"forest centaur"),(01,11),hostile
+MONSTER: ('C',"forest centaur"),(02,11),hostile
+MONSTER: ('C',"forest centaur"),(03,11),hostile
+MONSTER: ('C',"forest centaur"),(19,15),hostile
+MONSTER: ('C',"forest centaur"),(19,16),hostile
+MONSTER: ('C',"forest centaur"),(19,17),hostile
+MONSTER: ('C',"forest centaur"),(21,15),hostile
+MONSTER: ('C',"forest centaur"),(21,16),hostile
+MONSTER: ('C',"forest centaur"),(21,17),hostile
+LOOP [4 + 2d5] {
+  MONSTER: ('C',"plains centaur"),random,hostile
+}
+MONSTER: ('s',"scorpion"),random,hostile
+MONSTER: ('s',"scorpion"),random,hostile
 
 
@@ -102,6 +141,8 @@
 #
 
-MAZE: "Ran-loca",' '
-FLAGS: hardfloor
+LEVEL: "Ran-loca"
+FLAGS: hardfloor,mazelevel
+INIT_MAP:solidfill,' '
+MON_GENERATION:86%, (64,"forest centaur"), (16,'C'), (16,"scorpion"), (4,'s')
 GEOMETRY:center,center
 #1234567890123456789012345678901234567890123456789012345678901234567890
@@ -136,12 +177,12 @@
 NON_DIGGABLE:(00,00,54,19)
 # Objects
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
+OBJECT:random,random
+OBJECT:random,random
+OBJECT:random,random
+OBJECT:random,random
+OBJECT:random,random
+OBJECT:random,random
+OBJECT:random,random
+OBJECT:random,random
 # Random traps
 TRAP:"spiked pit",random
@@ -152,27 +193,14 @@
 TRAP:"arrow",random
 # Random monsters.
-MONSTER:'q',"wumpus",(27,18),hostile,asleep
-MONSTER:'B',"giant bat",random,hostile
-MONSTER:'B',"giant bat",random,hostile
-MONSTER:'B',"giant bat",random,hostile
-MONSTER:'B',"giant bat",random,hostile
-MONSTER:'C',"forest centaur",random,hostile
-MONSTER:'C',"forest centaur",random,hostile
-MONSTER:'C',"forest centaur",random,hostile
-MONSTER:'C',"forest centaur",random,hostile
-MONSTER:'C',"mountain centaur",random,hostile
-MONSTER:'C',"mountain centaur",random,hostile
-MONSTER:'C',"mountain centaur",random,hostile
-MONSTER:'C',"mountain centaur",random,hostile
-MONSTER:'C',"mountain centaur",random,hostile
-MONSTER:'C',"mountain centaur",random,hostile
-MONSTER:'C',"mountain centaur",random,hostile
-MONSTER:'C',"mountain centaur",random,hostile
-MONSTER:'s',"scorpion",random,hostile
-MONSTER:'s',"scorpion",random,hostile
-MONSTER:'s',"scorpion",random,hostile
-MONSTER:'s',"scorpion",random,hostile
-MONSTER:'s',random,random,hostile
-MONSTER:'s',random,random,hostile
+MONSTER:('q',"wumpus"),(27,18),hostile,asleep
+LOOP [2 + 1d6] {
+  MONSTER:('B',"giant bat"),random,hostile
+  MONSTER:('C',"forest centaur"),random,hostile
+  MONSTER:('s',"scorpion"),random,hostile
+  MONSTER:('C',"mountain centaur"),random,hostile
+  MONSTER:('C',"mountain centaur"),random,hostile
+}
+MONSTER:'s',random,hostile
+MONSTER:'s',random,hostile
 
 
@@ -185,5 +213,8 @@
 #
 
-MAZE: "Ran-goal", ' '
+LEVEL: "Ran-goal"
+FLAGS:mazelevel
+INIT_MAP:solidfill,' '
+MON_GENERATION:86%, (64,"forest centaur"), (16,'C'), (16,"scorpion"), (4,'s')
 GEOMETRY:center,center
 MAP
@@ -198,5 +229,5 @@
    .        S          .         .........   .S.    .S...............   .   
    .  ...   .     ...  .         .........          .                   .   
-   . ........    .....S.+.......+....\....+........+.                   .   
+   . ........    .....S.+.......+.........+........+.                   .   
    .  ...         ...    S       .........           ..      .....      .   
    .                    ..       .........            ..      ......    .   
@@ -216,26 +247,22 @@
 NON_DIGGABLE:(00,00,75,19)
 # Objects
-OBJECT:')',"bow",(37,10),blessed,0,"The Longbow of Diana"
-OBJECT:'(',"chest",(37,10)
-OBJECT:random,random,(36,09)
-OBJECT:random,random,(36,10)
-OBJECT:random,random,(36,11)
-OBJECT:random,random,(37,09)
-OBJECT:random,random,(37,11)
-OBJECT:random,random,(38,09)
-OBJECT:random,random,(38,10)
-OBJECT:random,random,(38,11)
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
+OBJECT:('\',"throne"),(37,10)
+OBJECT:(')',"bow"),(37,10),blessed,0,NAME:"The Longbow of Diana"
+OBJECT:('(',"chest"),(37,10)
+OBJECT:random,(36,09)
+OBJECT:random,(36,10)
+OBJECT:random,(36,11)
+OBJECT:random,(37,09)
+OBJECT:random,(37,11)
+OBJECT:random,(38,09)
+OBJECT:random,(38,10)
+OBJECT:random,(38,11)
+LOOP [3 + 1d3] {
+  OBJECT:random,random
+}
 # Random traps
+LOOP [4 + 1d5] {
 TRAP:random,random
-TRAP:random,random
-TRAP:random,random
-TRAP:random,random
-TRAP:random,random
-TRAP:random,random
+}
 # doors
 DOOR:locked,(12,08)
@@ -254,32 +281,38 @@
 DOOR:closed,(65,05)
 # Random monsters.
-MONSTER:'s',"Scorpius",(37,10),hostile
-MONSTER:'C',"forest centaur",(36,09),hostile
-MONSTER:'C',"forest centaur",(36,10),hostile
-MONSTER:'C',"forest centaur",(36,11),hostile
-MONSTER:'C',"forest centaur",(37,09),hostile
-MONSTER:'C',"forest centaur",(37,11),hostile
-MONSTER:'C',"forest centaur",(38,09),hostile
-MONSTER:'C',"mountain centaur",(38,10),hostile
-MONSTER:'C',"mountain centaur",(38,11),hostile
-MONSTER:'C',"mountain centaur",(02,02),hostile
-MONSTER:'C',"mountain centaur",(71,02),hostile
-MONSTER:'C',"mountain centaur",(02,16),hostile
-MONSTER:'C',"mountain centaur",(71,16),hostile
-MONSTER:'C',"forest centaur",random,hostile
-MONSTER:'C',"forest centaur",random,hostile
-MONSTER:'C',"mountain centaur",random,hostile
-MONSTER:'C',"mountain centaur",random,hostile
-MONSTER:'C',random,random,hostile
-MONSTER:'C',random,random,hostile
-MONSTER:'s',"scorpion",(03,02),hostile
-MONSTER:'s',"scorpion",(72,02),hostile
-MONSTER:'s',"scorpion",(03,17),hostile
-MONSTER:'s',"scorpion",(72,17),hostile
-MONSTER:'s',"scorpion",(41,10),hostile
-MONSTER:'s',"scorpion",(33,09),hostile
-MONSTER:'s',"scorpion",random,hostile
-MONSTER:'s',"scorpion",random,hostile
-MONSTER:'s',random,random,hostile
+MONSTER:('s',"Scorpius"),(37,10),hostile {
+  OBJECT:('(', "Bell of Opening"),uncursed
+  OBJECT:random
+  OBJECT:random
+  OBJECT:random
+  OBJECT:random
+  OBJECT:random
+  OBJECT:random
+}
+MONSTER:('C',"forest centaur"),(36,09),hostile
+MONSTER:('C',"forest centaur"),(36,10),hostile
+MONSTER:('C',"forest centaur"),(36,11),hostile
+MONSTER:('C',"forest centaur"),(37,09),hostile
+MONSTER:('C',"forest centaur"),(37,11),hostile
+MONSTER:('C',"forest centaur"),(38,09),hostile
+MONSTER:('C',"mountain centaur"),(38,10),hostile
+MONSTER:('C',"mountain centaur"),(38,11),hostile
+MONSTER:('C',"mountain centaur"),(02,02),hostile
+MONSTER:('C',"mountain centaur"),(71,02),hostile
+MONSTER:('C',"mountain centaur"),(02,16),hostile
+MONSTER:('C',"mountain centaur"),(71,16),hostile
+MONSTER:('s',"scorpion"),(03,02),hostile
+MONSTER:('s',"scorpion"),(72,02),hostile
+MONSTER:('s',"scorpion"),(03,17),hostile
+MONSTER:('s',"scorpion"),(72,17),hostile
+MONSTER:('s',"scorpion"),(41,10),hostile
+MONSTER:('s',"scorpion"),(33,09),hostile
+LOOP [2 + 1d5] {
+  MONSTER:('C',"forest centaur"),random,hostile
+  MONSTER:('C',"mountain centaur"),random,hostile
+  MONSTER:'C',random,hostile
+  MONSTER:('s',"scorpion"),random,hostile
+  MONSTER:'s',random,hostile
+}
 
 WALLIFY
@@ -294,6 +327,8 @@
 #
 
-MAZE: "Ran-fila" , ' '
-INIT_MAP: '.' , 'T', true, true, random, true
+LEVEL: "Ran-fila"
+FLAGS:mazelevel,noflip
+INIT_MAP: mines, '.' , 'T', true, true, random, true
+MON_GENERATION:86%, (64,"forest centaur"), (16,'C'), (16,"scorpion"), (4,'s')
 NOMAP
 #
@@ -301,27 +336,23 @@
 STAIR: random, down
 #
-OBJECT: random, random, random
-OBJECT: random, random, random
-OBJECT: random, random, random
-OBJECT: random, random, random
-OBJECT: random, random, random
-OBJECT: random, random, random
-OBJECT: random, random, random
+LOOP [5 + 1d5] {
+  OBJECT: random, random
+}
 #
+LOOP [3 + 1d4] {
 TRAP: random, random
-TRAP: random, random
-TRAP: random, random
-TRAP: random, random
+}
 #
-MONSTER: 'C', "mountain centaur", random, hostile
-MONSTER: 'C', "mountain centaur", random, hostile
-MONSTER: 'C', "forest centaur", random, hostile
-MONSTER: 'C', "forest centaur", random, hostile
-MONSTER: 'C', "forest centaur", random, hostile
-MONSTER: 'C', random, random, hostile
-MONSTER: 's', "scorpion", random, hostile
+LOOP [2 + 1d4] {
+  MONSTER: ('C', "mountain centaur"), random, hostile
+  MONSTER: ('C', "forest centaur"), random, hostile
+}
+MONSTER: 'C', random, hostile
+MONSTER: ('s', "scorpion"), random, hostile
 
-MAZE: "Ran-filb" , ' '
-INIT_MAP: '.' , ' ', true, true, random, true
+LEVEL: "Ran-filb"
+FLAGS:mazelevel,noflip
+INIT_MAP: mines, '.' , ' ', true, true, random, true
+MON_GENERATION:86%, (64,"forest centaur"), (16,'C'), (16,"scorpion"), (4,'s')
 NOMAP
 #
@@ -329,27 +360,16 @@
 STAIR: random, down
 #
-OBJECT: random, random, random
-OBJECT: random, random, random
-OBJECT: random, random, random
-OBJECT: random, random, random
-OBJECT: random, random, random
-OBJECT: random, random, random
-OBJECT: random, random, random
-OBJECT: random, random, random
-OBJECT: random, random, random
-OBJECT: random, random, random
-OBJECT: random, random, random
+LOOP [9 + 1d5] {
+  OBJECT: random, random
+}
 #
+LOOP [2 + 1d5] {
 TRAP: random, random
-TRAP: random, random
-TRAP: random, random
-TRAP: random, random
+}
 #
-MONSTER: 'C', "mountain centaur", random, hostile
-MONSTER: 'C', "mountain centaur", random, hostile
-MONSTER: 'C', "mountain centaur", random, hostile
-MONSTER: 'C', "mountain centaur", random, hostile
-MONSTER: 'C', random, random, hostile
-MONSTER: 's', "scorpion", random, hostile
-MONSTER: 's', "scorpion", random, hostile
+LOOP [3 + 1d5] {
+  MONSTER: ('C', "mountain centaur"), random, hostile
+  MONSTER: 'C', random, hostile
+  MONSTER: ('s', "scorpion"), random, hostile
+}
 
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/dat/Rogue.des nethack/dat/Rogue.des
--- nh_orig/dat/Rogue.des	2003-12-07 18:39:12.000000000 -0500
+++ nethack/dat/Rogue.des	2010-04-29 10:53:24.166715096 -0400
@@ -8,6 +8,8 @@
 #	and receive your quest assignment.
 #
-MAZE: "Rog-strt",' '
-FLAGS: noteleport, hardfloor, nommap
+LEVEL: "Rog-strt"
+FLAGS: noteleport, hardfloor, nommap, mazelevel
+INIT_MAP:solidfill,' '
+MON_GENERATION:86%, (64,"leprechaun"), (16,'n'), (16,"guardian naga"), (4,'N')
 GEOMETRY:center,center
 #         1         2         3         4         5         6         7
@@ -40,9 +42,13 @@
 # The down stairs is at one of the 4 "exits".  The others are mimics,
 # mimicing stairwells.
-RANDOM_PLACES: (33,0), (0,12), (25,20), (75,05)
-STAIR:place[0],down
-MONSTER:'m',"giant mimic", place[1], m_feature "staircase down"
-MONSTER:'m',"large mimic", place[2], m_feature "staircase down"
-MONSTER:'m',"small mimic", place[3], m_feature "staircase down"
+
+$streets = selection: floodfill(0,12)
+
+$place = { (33,0), (0,12), (25,20), (75,05) }
+SHUFFLE: $place
+STAIR:$place[0],down
+MONSTER:('m',"giant mimic"), $place[1], m_feature "staircase down"
+MONSTER:('m',"large mimic"), $place[2], m_feature "staircase down"
+MONSTER:('m',"small mimic"), $place[3], m_feature "staircase down"
 # Portal arrival point
 BRANCH:(19,09,19,09),(0,0,0,0)
@@ -97,73 +103,87 @@
 DOOR: closed, (68,18)
 # Master of Thieves
-MONSTER:'@',"Master of Thieves",(36,11)
+MONSTER:('@',"Master of Thieves"),(36,11) {
+  OBJECT:'['
+  OBJECT:')'
+  OBJECT:'!'
+  OBJECT:'!'
+  OBJECT:'!'
+  OBJECT:'!'
+}
 # The treasure of Master of Thieves
-OBJECT:'(',"chest",(36,11)
+OBJECT:('(',"chest"),(36,11)
 # thug guards, room #1
-MONSTER:'@',"thug",(28,10)
-MONSTER:'@',"thug",(29,11)
-MONSTER:'@',"thug",(30,09)
-MONSTER:'@',"thug",(31,07)
+MONSTER:('@',"thug"),(28,10) {
+  OBJECT[15%]:'['
+  OBJECT[15%]:')'
+}
+MONSTER:('@',"thug"),(29,11) {
+  OBJECT[15%]:'['
+  OBJECT[15%]:')'
+}
+MONSTER:('@',"thug"),(30,09) {
+  OBJECT[15%]:'['
+  OBJECT[15%]:')'
+}
+MONSTER:('@',"thug"),(31,07) {
+  OBJECT[15%]:'['
+  OBJECT[15%]:')'
+}
 # thug guards, room #2
-MONSTER:'@',"thug",(31,13)
-MONSTER:'@',"thug",(33,14)
-MONSTER:'@',"thug",(30,15)
+MONSTER:('@',"thug"),(31,13) {
+  OBJECT[15%]:'['
+  OBJECT[15%]:')'
+}
+MONSTER:('@',"thug"),(33,14) {
+  OBJECT[15%]:'['
+  OBJECT[15%]:')'
+}
+MONSTER:('@',"thug"),(30,15) {
+  OBJECT[15%]:'['
+  OBJECT[15%]:')'
+}
 #thug guards, room #3
-MONSTER:'@',"thug",(35,09)
-MONSTER:'@',"thug",(36,13)
+MONSTER:('@',"thug"),(35,09) {
+  OBJECT[15%]:'['
+  OBJECT[15%]:')'
+}
+MONSTER:('@',"thug"),(36,13) {
+  OBJECT[15%]:'['
+  OBJECT[15%]:')'
+}
 # Non diggable walls
 NON_DIGGABLE:(00,00,75,20)
 # Random traps
+LOOP [15 + 1d10] {
 TRAP:random,random
-TRAP:random,random
-TRAP:random,random
-TRAP:random,random
-TRAP:random,random
-TRAP:random,random
-TRAP:random,random
-TRAP:random,random
-TRAP:random,random
-TRAP:random,random
-TRAP:random,random
-TRAP:random,random
-TRAP:random,random
-TRAP:random,random
-TRAP:random,random
-TRAP:random,random
+}
 #
 # Monsters to get in the way.
 #
 # West exit
-MONSTER: 'l',"leprechaun",(01,12),hostile
-MONSTER: 'n',"water nymph",(02,12),hostile
+MONSTER: ('l',"leprechaun"),(01,12),hostile
+MONSTER: ('n',"water nymph"),(02,12),hostile
 # North exit
-MONSTER: 'n',"water nymph",(33,01),hostile
-MONSTER: 'l',"leprechaun",(33,02),hostile
+MONSTER: ('n',"water nymph"),(33,01),hostile
+MONSTER: ('l',"leprechaun"),(33,02),hostile
 # East exit
-MONSTER: 'n',"water nymph",(74,05),hostile
-MONSTER: 'l',"leprechaun",(74,04),hostile
+MONSTER: ('n',"water nymph"),(74,05),hostile
+MONSTER: ('l',"leprechaun"),(74,04),hostile
 # South exit
-MONSTER: 'l',"leprechaun",(25,19),hostile
-MONSTER: 'n',"water nymph",(25,18),hostile
-# Wandering the streets.  What I'd really like for this is a random
-# location, but make sure we're on a given type, e.g. street (if they
-# existed, of course).
-MONSTER: 'n',"water nymph",(07,05),hostile
-MONSTER: 'l',"leprechaun",(28,06),hostile
-MONSTER: 'n',"water nymph",(38,07),hostile
-MONSTER: 'l',"leprechaun",(45,01),hostile
-MONSTER: 'n',"water nymph",(59,07),hostile
-MONSTER: 'l',"leprechaun",(62,14),hostile
-MONSTER: 'n',"water nymph",(71,14),hostile
-MONSTER: 'l',"leprechaun",(39,13),hostile
-MONSTER: 'n',"water nymph",(18,14),hostile
-MONSTER: ':',"chameleon",(19,08),hostile
-MONSTER: ':',"chameleon",(22,08),hostile
-MONSTER: ':',"chameleon",(16,08),hostile
-MONSTER: ':',"chameleon",random,hostile
-MONSTER: ':',"chameleon",random,hostile
-MONSTER: ':',"chameleon",random,hostile
-MONSTER: ':',"chameleon",random,hostile
-MONSTER: ':',"chameleon",random,hostile
+MONSTER: ('l',"leprechaun"),(25,19),hostile
+MONSTER: ('n',"water nymph"),(25,18),hostile
+# Wandering the streets.
+LOOP [3 + 2d2] {
+  MONSTER: ('n',"water nymph"),rndcoord($streets),hostile
+}
+LOOP [1 + 2d2] {
+  MONSTER: ('l',"leprechaun"),rndcoord($streets),hostile
+}
+LOOP [2d2] {
+  MONSTER: (':',"chameleon"),rndcoord($streets),hostile
+}
+LOOP [3 + 1d7] {
+  MONSTER: (':',"chameleon"),rndcoord($streets),hostile
+}
 
 #
@@ -174,5 +194,8 @@
 #
 
-MAZE: "Rog-loca",' '
+LEVEL: "Rog-loca"
+FLAGS:mazelevel
+INIT_MAP:solidfill,' '
+MON_GENERATION:86%, (64,"leprechaun"), (16,'n'), (16,"guardian naga"), (4,'N')
 GEOMETRY:center,center
 #         1         2         3         4         5         6         7
@@ -211,60 +234,26 @@
 NON_DIGGABLE:(00,00,75,20)
 # Objects
-OBJECT:'?',"teleportation",(11,18),cursed,0
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
+OBJECT:('?',"teleportation"),(11,18),cursed,0
+LOOP [10 + 1d6] {
+  OBJECT:random,random
+}
 # Random traps
+LOOP [ 5 + 1d6] {
 TRAP:random,random
-TRAP:random,random
-TRAP:random,random
-TRAP:random,random
-TRAP:random,random
-TRAP:random,random
+}
 # Random monsters.
-MONSTER:'l',"leprechaun",random,hostile
-MONSTER:'l',"leprechaun",random,hostile
-MONSTER:'l',"leprechaun",random,hostile
-MONSTER:'l',"leprechaun",random,hostile
-MONSTER:'l',"leprechaun",random,hostile
-MONSTER:'l',"leprechaun",random,hostile
-MONSTER:'l',"leprechaun",random,hostile
-MONSTER:'l',"leprechaun",random,hostile
-MONSTER:'l',"leprechaun",random,hostile
-MONSTER:'l',"leprechaun",random,hostile
-MONSTER:'l',"leprechaun",random,hostile
-MONSTER:'l',"leprechaun",random,hostile
-MONSTER:'l',"leprechaun",random,hostile
-MONSTER:'l',"leprechaun",random,hostile
-MONSTER:'l',"leprechaun",random,hostile
-MONSTER:'l',"leprechaun",random,hostile
-MONSTER:'l',"leprechaun",random,hostile
-MONSTER:'l',random,random,hostile
-MONSTER:'N',"guardian naga",random,hostile
-MONSTER:'N',"guardian naga",random,hostile
-MONSTER:'N',"guardian naga",random,hostile
-MONSTER:'N',"guardian naga",random,hostile
-MONSTER:'N',"guardian naga",random,hostile
-MONSTER:'N',"guardian naga",random,hostile
-MONSTER:'N',"guardian naga",random,hostile
-MONSTER:'N',random,random,hostile
-MONSTER:'N',random,random,hostile
-MONSTER:'N',random,random,hostile
-MONSTER: ':',"chameleon",random,hostile
-MONSTER: ':',"chameleon",random,hostile
-MONSTER: ':',"chameleon",random,hostile
-MONSTER: ':',"chameleon",random,hostile
-MONSTER: ':',"chameleon",random,hostile
+LOOP [15 + 2d6] {
+  MONSTER:('l',"leprechaun"),random,hostile
+}
+MONSTER:'l',random,hostile
+LOOP [5 + 1d6] {
+  MONSTER:('N',"guardian naga"),random,hostile
+}
+MONSTER:'N',random,hostile
+MONSTER:'N',random,hostile
+MONSTER:'N',random,hostile
+LOOP [4 + 1d3] {
+  MONSTER: (':',"chameleon"),random,hostile
+}
 
 #
@@ -276,6 +265,8 @@
 #	arrival point and his location.
 #
-MAZE: "Rog-goal", ' '
-FLAGS: noteleport
+LEVEL: "Rog-goal"
+FLAGS: noteleport,mazelevel
+INIT_MAP:solidfill,' '
+MON_GENERATION:86%, (64,"leprechaun"), (16,'n'), (16,"guardian naga"), (4,'N')
 GEOMETRY:center,center
 #         1         2         3         4         5         6         7
@@ -314,71 +305,39 @@
 TRAP:"spiked pit",(37,07)
 # Objects
-OBJECT:'(',"skeleton key",(38,10),blessed,0,"The Master Key of Thievery"
-OBJECT:'%',"tin",(26,12),"chameleon",0
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
+OBJECT:('(',"skeleton key"),(38,10),blessed,0,NAME:"The Master Key of Thievery"
+OBJECT:('%',"tin"),(26,12),montype:"chameleon",0
+LOOP [10 + 1d8] {
+  OBJECT:random,random
+}
 # Random traps
+LOOP [7 + 1d6] {
 TRAP:random,random
-TRAP:random,random
-TRAP:random,random
-TRAP:random,random
-TRAP:random,random
-TRAP:random,random
-TRAP:random,random
-TRAP:random,random
-TRAP:random,random
-TRAP:random,random
-TRAP:random,random
+}
 # Random monsters.
-MONSTER:'@',"Master Assassin",(38,10),hostile
-MONSTER:'l',"leprechaun",random,hostile
-MONSTER:'l',"leprechaun",random,hostile
-MONSTER:'l',"leprechaun",random,hostile
-MONSTER:'l',"leprechaun",random,hostile
-MONSTER:'l',"leprechaun",random,hostile
-MONSTER:'l',"leprechaun",random,hostile
-MONSTER:'l',"leprechaun",random,hostile
-MONSTER:'l',"leprechaun",random,hostile
-MONSTER:'l',"leprechaun",random,hostile
-MONSTER:'l',"leprechaun",random,hostile
-MONSTER:'l',"leprechaun",random,hostile
-MONSTER:'l',"leprechaun",random,hostile
-MONSTER:'l',"leprechaun",random,hostile
-MONSTER:'l',"leprechaun",random,hostile
-MONSTER:'l',"leprechaun",random,hostile
-MONSTER:'l',"leprechaun",random,hostile
-MONSTER:'l',random,random,hostile
-MONSTER:'l',random,random,hostile
-MONSTER:'N',"guardian naga",random,hostile
-MONSTER:'N',"guardian naga",random,hostile
-MONSTER:'N',"guardian naga",random,hostile
-MONSTER:'N',"guardian naga",random,hostile
-MONSTER:'N',"guardian naga",random,hostile
-MONSTER:'N',"guardian naga",random,hostile
-MONSTER:'N',"guardian naga",random,hostile
-MONSTER:'N',"guardian naga",random,hostile
-MONSTER:'N',random,random,hostile
-MONSTER:'N',random,random,hostile
-MONSTER:'N',random,random,hostile
-MONSTER: ':',"chameleon",random,hostile
-MONSTER: ':',"chameleon",random,hostile
-MONSTER: ':',"chameleon",random,hostile
-MONSTER: ':',"chameleon",random,hostile
-MONSTER: ':',"chameleon",random,hostile
-MONSTER:';',"shark",(51,14),hostile
-MONSTER:';',"shark",(53,09),hostile
-MONSTER:';',"shark",(55,15),hostile
-MONSTER:';',"shark",(58,10),hostile
+MONSTER:('@',"Master Assassin"),(38,10),hostile {
+  OBJECT:('(', "Bell of Opening"),uncursed
+  OBJECT:'['
+  OBJECT:')'
+  OBJECT:'?'
+  OBJECT:'!'
+}
+LOOP [13 + 2d6] {
+  MONSTER:('l',"leprechaun"),random,hostile
+}
+MONSTER:'l',random,hostile
+MONSTER:'l',random,hostile
+LOOP [5 + 2d3] {
+  MONSTER:('N',"guardian naga"),random,hostile
+}
+MONSTER:'N',random,hostile
+MONSTER:'N',random,hostile
+MONSTER:'N',random,hostile
+LOOP [4 + 1d3] {
+  MONSTER: (':',"chameleon"),random,hostile
+}
+MONSTER:(';',"shark"),(51,14),hostile
+MONSTER:(';',"shark"),(53,09),hostile
+MONSTER:(';',"shark"),(55,15),hostile
+MONSTER:(';',"shark"),(58,10),hostile
 
 #
@@ -389,44 +348,57 @@
 #
 LEVEL: "Rog-fila"
+MON_GENERATION:86%, (64,"leprechaun"), (16,'n'), (16,"guardian naga"), (4,'N')
 #
 ROOM: "ordinary" , random, random, random, random
+{
 STAIR: random, up
-OBJECT: random,random,random
-MONSTER: 'l', "leprechaun", random, hostile
+OBJECT: random,random
+MONSTER: ('l', "leprechaun"), random, hostile
+}
 
 ROOM: "ordinary" , random, random, random, random
-OBJECT: random, random, random
-OBJECT: random,random,random
-MONSTER: 'l', "leprechaun", random, hostile
-MONSTER: 'N', "guardian naga", random, hostile
+{
+OBJECT: random, random
+OBJECT: random,random
+MONSTER: ('l', "leprechaun"), random, hostile
+MONSTER: ('N', "guardian naga"), random, hostile
+}
 
 ROOM: "ordinary" , random, random, random, random
-OBJECT: random, random, random
+{
+OBJECT: random, random
 TRAP: random, random
 TRAP: random, random
-OBJECT: random,random,random
-MONSTER: 'n', "water nymph", random, hostile
+OBJECT: random,random
+MONSTER: ('n', "water nymph"), random, hostile
+}
 
 ROOM: "ordinary" , random, random, random, random
+{
 STAIR: random, down
-OBJECT: random, random, random
+OBJECT: random, random
 TRAP: random, random
 TRAP: random, random
-MONSTER: 'l', random, random, hostile
-MONSTER: 'N', "guardian naga", random, hostile
+MONSTER: 'l', random, hostile
+MONSTER: ('N', "guardian naga"), random, hostile
+}
 
 ROOM: "ordinary" , random, random, random, random
-OBJECT: random, random, random
-OBJECT: random, random, random
+{
+OBJECT: random, random
+OBJECT: random, random
 TRAP: random, random
 TRAP: random, random
-MONSTER: 'l', "leprechaun", random, hostile
+MONSTER: ('l', "leprechaun"), random, hostile
+}
 
 ROOM: "ordinary" , random, random, random, random
-OBJECT: random, random, random
+{
+OBJECT: random, random
 TRAP: random, random
 TRAP: random, random
-MONSTER: 'l', "leprechaun", random, hostile
-MONSTER: 'n', "water nymph", random, hostile
+MONSTER: ('l', "leprechaun"), random, hostile
+MONSTER: ('n', "water nymph"), random, hostile
+}
 
 RANDOM_CORRIDORS
@@ -436,44 +408,57 @@
 #
 LEVEL: "Rog-filb"
+MON_GENERATION:86%, (64,"leprechaun"), (16,'n'), (16,"guardian naga"), (4,'N')
 #
 ROOM: "ordinary" , random, random, random, random
+{
 STAIR: random, up
-OBJECT: random,random,random
-MONSTER: 'l', "leprechaun", random, hostile
+OBJECT: random,random
+MONSTER: ('l', "leprechaun"), random, hostile
+}
 
 ROOM: "ordinary" , random, random, random, random
-OBJECT: random, random, random
-OBJECT: random,random,random
-MONSTER: 'l', "leprechaun", random, hostile
-MONSTER: 'N', "guardian naga", random, hostile
+{
+OBJECT: random, random
+OBJECT: random,random
+MONSTER: ('l', "leprechaun"), random, hostile
+MONSTER: ('N', "guardian naga"), random, hostile
+}
 
 ROOM: "ordinary" , random, random, random, random
-OBJECT: random, random, random
+{
+OBJECT: random, random
 TRAP: random, random
 TRAP: random, random
-OBJECT: random,random,random
-MONSTER: 'n', "water nymph", random, hostile
+OBJECT: random,random
+MONSTER: ('n', "water nymph"), random, hostile
+}
 
 ROOM: "ordinary" , random, random, random, random
+{
 STAIR: random, down
-OBJECT: random, random, random
+OBJECT: random, random
 TRAP: random, random
 TRAP: random, random
-MONSTER: 'l', random, random, hostile
-MONSTER: 'N', "guardian naga", random, hostile
+MONSTER: 'l', random, hostile
+MONSTER: ('N', "guardian naga"), random, hostile
+}
 
 ROOM: "ordinary" , random, random, random, random
-OBJECT: random, random, random
-OBJECT: random, random, random
+{
+OBJECT: random, random
+OBJECT: random, random
 TRAP: random, random
 TRAP: random, random
-MONSTER: 'l', "leprechaun", random, hostile
+MONSTER: ('l', "leprechaun"), random, hostile
+}
 
 ROOM: "ordinary" , random, random, random, random
-OBJECT: random, random, random
+{
+OBJECT: random, random
 TRAP: random, random
 TRAP: random, random
-MONSTER: 'l', "leprechaun", random, hostile
-MONSTER: 'n', "water nymph", random, hostile
+MONSTER: ('l', "leprechaun"), random, hostile
+MONSTER: ('n', "water nymph"), random, hostile
+}
 
 RANDOM_CORRIDORS
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/dat/Samurai.des nethack/dat/Samurai.des
--- nh_orig/dat/Samurai.des	2003-12-07 18:39:12.000000000 -0500
+++ nethack/dat/Samurai.des	2010-08-16 13:20:13.635707386 -0400
@@ -9,6 +9,8 @@
 #	and receive your quest assignment.
 #
-MAZE: "Sam-strt",' '
-FLAGS: noteleport,hardfloor
+LEVEL: "Sam-strt"
+FLAGS: noteleport,hardfloor,mazelevel
+INIT_MAP:solidfill,' '
+MON_GENERATION:86%, (64,"wolf"), (16,'d'), (16,"stalker"), (4,'E')
 GEOMETRY:center,center
 MAP
@@ -53,39 +55,64 @@
 DOOR:closed,(50,06)
 # Lord Sato
-MONSTER:'@',"Lord Sato",(20,04)
+MONSTER:('@',"Lord Sato"),(20,04) {
+  OBJECT:('[',"splint mail"),1d4
+  OBJECT:(')',"katana"),1d4
+  OBJECT:'?'
+}
 # The treasure of Lord Sato
-OBJECT:'(',"chest",(20,04)
+OBJECT:('(',"chest"),(20,04)
 # roshi guards for the audience chamber
-MONSTER:'@',"roshi",(18,04)
-MONSTER:'@',"roshi",(18,05)
-MONSTER:'@',"roshi",(18,06)
-MONSTER:'@',"roshi",(18,07)
-MONSTER:'@',"roshi",(26,04)
-MONSTER:'@',"roshi",(26,05)
-MONSTER:'@',"roshi",(26,06)
-MONSTER:'@',"roshi",(26,07)
+MONSTER:('@',"roshi"),(18,04) {
+  OBJECT[25%]:('[',"splint mail")
+  OBJECT[25%]:(')',"katana")
+}
+MONSTER:('@',"roshi"),(18,05) {
+  OBJECT[25%]:('[',"splint mail")
+  OBJECT[25%]:(')',"katana")
+}
+MONSTER:('@',"roshi"),(18,06) {
+  OBJECT[25%]:('[',"splint mail")
+  OBJECT[25%]:(')',"katana")
+}
+MONSTER:('@',"roshi"),(18,07) {
+  OBJECT[25%]:('[',"splint mail")
+  OBJECT[25%]:(')',"katana")
+}
+MONSTER:('@',"roshi"),(26,04) {
+  OBJECT[25%]:('[',"splint mail")
+  OBJECT[25%]:(')',"katana")
+}
+MONSTER:('@',"roshi"),(26,05) {
+  OBJECT[25%]:('[',"splint mail")
+  OBJECT[25%]:(')',"katana")
+}
+MONSTER:('@',"roshi"),(26,06) {
+  OBJECT[25%]:('[',"splint mail")
+  OBJECT[25%]:(')',"katana")
+}
+MONSTER:('@',"roshi"),(26,07) {
+  OBJECT[25%]:('[',"splint mail")
+  OBJECT[25%]:(')',"katana")
+}
 # Non diggable walls
 NON_DIGGABLE:(00,00,75,19)
 # Random traps
+LOOP [4 + 1d6] {
 TRAP:random,random
-TRAP:random,random
-TRAP:random,random
-TRAP:random,random
-TRAP:random,random
-TRAP:random,random
+}
 # Monsters on siege duty.
-MONSTER: '@',"ninja",(64,00),hostile
-MONSTER: 'd',"wolf",(65,01)
-MONSTER: '@',"ninja",(67,02),hostile
-MONSTER: '@',"ninja",(69,05),hostile
-MONSTER: '@',"ninja",(69,06),hostile
-MONSTER: 'd',"wolf",(69,07)
-MONSTER: '@',"ninja",(70,06),hostile
-MONSTER: '@',"ninja",(70,07),hostile
-MONSTER: '@',"ninja",(72,01),hostile
-MONSTER: 'd',"wolf",(75,09)
-MONSTER: '@',"ninja",(73,05),hostile
-MONSTER: '@',"ninja",(68,02),hostile
-MONSTER:'E',"stalker",random
+MONSTER: ('@',"ninja"),(64,00),hostile
+MONSTER: ('d',"wolf"),(65,01)
+MONSTER: ('@',"ninja"),(67,02),hostile
+MONSTER: ('@',"ninja"),(69,05),hostile
+MONSTER: ('@',"ninja"),(69,06),hostile
+MONSTER: ('d',"wolf"),(69,07)
+MONSTER: ('@',"ninja"),(70,06),hostile
+MONSTER: ('@',"ninja"),(70,07),hostile
+MONSTER: ('@',"ninja"),(72,01),hostile
+MONSTER: ('d',"wolf"),(75,09)
+MONSTER: ('@',"ninja"),(73,05),hostile
+MONSTER: ('@',"ninja"),(68,02),hostile
+MONSTER:('E',"stalker"),random
 
 #
@@ -96,6 +123,8 @@
 #
 
-MAZE: "Sam-loca",' '
-FLAGS: hardfloor
+LEVEL: "Sam-loca"
+FLAGS: hardfloor,mazelevel
+INIT_MAP:solidfill,' '
+MON_GENERATION:86%, (64,"wolf"), (16,'d'), (16,"stalker"), (4,'E')
 GEOMETRY:center,center
 MAP
@@ -154,81 +183,72 @@
 NON_DIGGABLE:(00,00,75,19)
 # Objects
-OBJECT:'*',random,(25,05)
-OBJECT:'*',random,(26,05)
-OBJECT:'*',random,(27,05)
-OBJECT:'*',random,(28,05)
-OBJECT:'*',random,(25,06)
-OBJECT:'*',random,(26,06)
-OBJECT:'*',random,(27,06)
-OBJECT:'*',random,(28,06)
+OBJECT:'*',(25,05)
+OBJECT:'*',(26,05)
+OBJECT:'*',(27,05)
+OBJECT:'*',(28,05)
+OBJECT:'*',(25,06)
+OBJECT:'*',(26,06)
+OBJECT:'*',(27,06)
+OBJECT:'*',(28,06)
 #
-OBJECT:'[',random,(40,05)
-OBJECT:'[',random,(41,05)
-OBJECT:'[',random,(42,05)
-OBJECT:'[',random,(43,05)
-OBJECT:'[',random,(40,06)
-OBJECT:'[',random,(41,06)
-OBJECT:'[',random,(42,06)
-OBJECT:'[',random,(43,06)
+OBJECT:'[',(40,05)
+OBJECT:'[',(41,05)
+OBJECT:'[',(42,05)
+OBJECT:'[',(43,05)
+OBJECT:'[',(40,06)
+OBJECT:'[',(41,06)
+OBJECT:'[',(42,06)
+OBJECT:'[',(43,06)
 #
-OBJECT:')',random,(27,13)
-OBJECT:')',random,(28,13)
-OBJECT:')',random,(29,13)
-OBJECT:')',random,(30,13)
-OBJECT:')',random,(27,14)
-OBJECT:')',random,(28,14)
-OBJECT:')',random,(29,14)
-OBJECT:')',random,(30,14)
+OBJECT:')',(27,13)
+OBJECT:')',(28,13)
+OBJECT:')',(29,13)
+OBJECT:')',(30,13)
+OBJECT:')',(27,14)
+OBJECT:')',(28,14)
+OBJECT:')',(29,14)
+OBJECT:')',(30,14)
 #
-OBJECT:'(',random,(37,13)
-OBJECT:'(',random,(38,13)
-OBJECT:'(',random,(39,13)
-OBJECT:'(',random,(40,13)
-OBJECT:'(',random,(37,14)
-OBJECT:'(',random,(38,14)
-OBJECT:'(',random,(39,14)
-OBJECT:'(',random,(40,14)
+OBJECT:'(',(37,13)
+OBJECT:'(',(38,13)
+OBJECT:'(',(39,13)
+OBJECT:'(',(40,13)
+OBJECT:'(',(37,14)
+OBJECT:'(',(38,14)
+OBJECT:'(',(39,14)
+OBJECT:'(',(40,14)
 # Random traps
+LOOP [4 + 1d6] {
 TRAP:random,random
-TRAP:random,random
-TRAP:random,random
-TRAP:random,random
-TRAP:random,random
-TRAP:random,random
+}
 # Random monsters.
-MONSTER:'@',"ninja",(15,05),hostile
-MONSTER:'@',"ninja",(16,05),hostile
-MONSTER:'d',"wolf",(17,05)
-MONSTER:'d',"wolf",(18,05)
-MONSTER:'@',"ninja",(19,05),hostile
-MONSTER:'d',"wolf",(15,14)
-MONSTER:'d',"wolf",(16,14)
-MONSTER:'@',"ninja",(17,14),hostile
-MONSTER:'@',"ninja",(18,14),hostile
-MONSTER:'d',"wolf",(56,05)
-MONSTER:'@',"ninja",(57,05),hostile
-MONSTER:'d',"wolf",(58,05)
-MONSTER:'d',"wolf",(59,05)
-MONSTER:'@',"ninja",(56,14),hostile
-MONSTER:'d',"wolf",(57,14)
-MONSTER:'@',"ninja",(58,14),hostile
-MONSTER:'d',random,(59,14)
-MONSTER:'d',"wolf",(60,14)
-MONSTER:'E',"stalker",random
-MONSTER:'E',"stalker",random
-MONSTER:'E',"stalker",random
-MONSTER:'E',"stalker",random
-MONSTER:'E',"stalker",random
-MONSTER:'E',"stalker",random
-MONSTER:'E',"stalker",random
-MONSTER:'E',"stalker",random
-MONSTER:'E',"stalker",random
+MONSTER:('@',"ninja"),(15,05),hostile
+MONSTER:('@',"ninja"),(16,05),hostile
+MONSTER:('d',"wolf"),(17,05)
+MONSTER:('d',"wolf"),(18,05)
+MONSTER:('@',"ninja"),(19,05),hostile
+MONSTER:('d',"wolf"),(15,14)
+MONSTER:('d',"wolf"),(16,14)
+MONSTER:('@',"ninja"),(17,14),hostile
+MONSTER:('@',"ninja"),(18,14),hostile
+MONSTER:('d',"wolf"),(56,05)
+MONSTER:('@',"ninja"),(57,05),hostile
+MONSTER:('d',"wolf"),(58,05)
+MONSTER:('d',"wolf"),(59,05)
+MONSTER:('@',"ninja"),(56,14),hostile
+MONSTER:('d',"wolf"),(57,14)
+MONSTER:('@',"ninja"),(58,14),hostile
+MONSTER:'d',(59,14)
+MONSTER:('d',"wolf"),(60,14)
+LOOP [7 + 1d10] {
+  MONSTER:('E',"stalker"),random
+}
 #	"guards" for the central courtyard.
-MONSTER:'@',"samurai",(30,05),hostile
-MONSTER:'@',"samurai",(31,05),hostile
-MONSTER:'@',"samurai",(32,05),hostile
-MONSTER:'@',"samurai",(32,14),hostile
-MONSTER:'@',"samurai",(33,14),hostile
-MONSTER:'@',"samurai",(34,14),hostile
+MONSTER:('@',"samurai"),(30,05),hostile
+MONSTER:('@',"samurai"),(31,05),hostile
+MONSTER:('@',"samurai"),(32,05),hostile
+MONSTER:('@',"samurai"),(32,14),hostile
+MONSTER:('@',"samurai"),(33,14),hostile
+MONSTER:('@',"samurai"),(34,14),hostile
 
 #
@@ -240,11 +260,13 @@
 #
 
-MAZE: "Sam-goal", ' '
-FLAGS: noteleport
+LEVEL: "Sam-goal"
+FLAGS: noteleport,mazelevel
+INIT_MAP:solidfill,' '
+MON_GENERATION:86%, (64,"wolf"), (16,'d'), (16,"stalker"), (4,'E')
 GEOMETRY:center,center
 MAP
                                              
            .......................           
-       ......---------.---------......       
+       ......-------------------......       
     ......----.................----......    
    ....----.....-------------.....----....   
@@ -254,9 +276,9 @@
  ....|...||...---...--+--...---...||...|.... 
  ....|...|....|....|-...-|....|....|...|.... 
- ....|...|....|....+.....+....|........|.... 
+ ....|...|....|....+.....+....|....|...|.... 
  ....|...|....|....|-...-|....|....|...|.... 
  ....|...||...---...--+--...---...||...|.... 
   ...|....--....---.......---....--....|...  
-  ...||....---....----.----....---....||...  
+  ...||....---....---------....---....||...  
   ....--.....----...........----.....--....  
    ....----.....-------------.....----....   
@@ -266,5 +288,4 @@
 ENDMAP
 # Dungeon Description
-RANDOM_PLACES:(02,11),(42,09)
 REGION:(00,00,44,19),unlit,"ordinary"
 # Doors
@@ -274,23 +295,27 @@
 DOOR:closed,(25,10)
 # Stairs
-STAIR:place[0],up
+$place = { (02,11),(42,09) }
+SHUFFLE:$place
+STAIR:$place[0],up
+
+$place = { (22,14),(30,10),(22, 6),(14,10) }
+SHUFFLE:$place
+TERRAIN:$place[0],'.'
+
+$place = { (22, 4),(35,10),(22,16),( 9,10) }
+SHUFFLE:$place
+TERRAIN:$place[0],'.'
+
+$place = { (22, 2),(22,18) }
+SHUFFLE:$place
+TERRAIN:$place[0],'.'
+
 # Non diggable walls
 NON_DIGGABLE:(00,00,44,19)
 # Objects
-OBJECT:')',"tsurugi",(22,10),blessed,0,"The Tsurugi of Muramasa"
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
+OBJECT:(')',"tsurugi"),(22,10),blessed,0,NAME:"The Tsurugi of Muramasa"
+LOOP [9 + 1d6] {
+  OBJECT:random,random
+}
 #
 TRAP:"board",(22,09)
@@ -298,37 +323,20 @@
 TRAP:"board",(22,11)
 # Random traps
+LOOP [3 + 1d6] {
 TRAP:random,random
-TRAP:random,random
-TRAP:random,random
-TRAP:random,random
-TRAP:random,random
-TRAP:random,random
+}
 # Random monsters.
-MONSTER:'@',"Ashikaga Takauji",(22,10)
-MONSTER:'@',"samurai",random,hostile
-MONSTER:'@',"samurai",random,hostile
-MONSTER:'@',"samurai",random,hostile
-MONSTER:'@',"samurai",random,hostile
-MONSTER:'@',"samurai",random,hostile
-MONSTER:'@',"ninja",random,hostile
-MONSTER:'@',"ninja",random,hostile
-MONSTER:'@',"ninja",random,hostile
-MONSTER:'@',"ninja",random,hostile
-MONSTER:'@',"ninja",random,hostile
-MONSTER:'d',"wolf",random
-MONSTER:'d',"wolf",random
-MONSTER:'d',"wolf",random
-MONSTER:'d',"wolf",random
-MONSTER:'d',random,random
-MONSTER:'d',random,random
-MONSTER:'E',"stalker",random
-MONSTER:'E',"stalker",random
-MONSTER:'E',"stalker",random
-MONSTER:'E',"stalker",random
-MONSTER:'E',"stalker",random
-MONSTER:'E',"stalker",random
-MONSTER:'E',"stalker",random
-MONSTER:'E',"stalker",random
-MONSTER:'E',"stalker",random
+MONSTER:('@',"Ashikaga Takauji"),(22,10) {
+  OBJECT:('(', "Bell of Opening"),uncursed
+  OBJECT:('[',"splint mail")
+}
+LOOP [3 + 1d6] {
+  MONSTER:('@',"samurai"),random,hostile
+  MONSTER[90%]:('@',"ninja"),random,hostile
+  MONSTER:('d',"wolf"),random
+  MONSTER[50%]:'d',random
+  MONSTER:('E',"stalker"),random
+  MONSTER[90%]:('E',"stalker"),random
+}
 
 
@@ -342,6 +350,8 @@
 #
 
-MAZE: "Sam-fila", ' '
-INIT_MAP: '.' , 'P', true, true, random, true
+LEVEL: "Sam-fila"
+FLAGS:mazelevel,noflip
+INIT_MAP: mines, '.' , 'P', true, true, random, true
+MON_GENERATION:86%, (64,"wolf"), (16,'d'), (16,"stalker"), (4,'E')
 NOMAP
 #
@@ -349,28 +359,22 @@
 STAIR: random, down
 #
-OBJECT: random, random, random
-OBJECT: random, random, random
-OBJECT: random, random, random
-OBJECT: random, random, random
-OBJECT: random, random, random
-OBJECT: random, random, random
-OBJECT: random, random, random
-OBJECT: random, random, random
-OBJECT: random, random, random
+LOOP [5 + 1d6] {
+  OBJECT: random, random
+}
 #
-MONSTER: 'd', random, random
-MONSTER: 'd', "wolf", random
-MONSTER: 'd', "wolf", random
-MONSTER: 'd', "wolf", random
-MONSTER: 'd', "wolf", random
-MONSTER: 'd', "wolf", random
-MONSTER: 'E', "stalker", random
+MONSTER: 'd', random
+LOOP [3 + 2d4] {
+  MONSTER: ('d', "wolf"), random
+}
+MONSTER: ('E', "stalker"), random
 #
+LOOP [3 + 1d6] {
 TRAP: random, random
-TRAP: random, random
-TRAP: random, random
-TRAP: random, random
+}
 
-MAZE: "Sam-filb", ' '
+LEVEL: "Sam-filb"
+FLAGS:mazelevel
+INIT_MAP:solidfill,' '
+MON_GENERATION:86%, (64,"wolf"), (16,'d'), (16,"stalker"), (4,'E')
 GEOMETRY:center,center
 MAP
@@ -402,25 +406,15 @@
 STAIR: random, down
 #
-OBJECT: random, random, random
-OBJECT: random, random, random
-OBJECT: random, random, random
-OBJECT: random, random, random
-OBJECT: random, random, random
-OBJECT: random, random, random
-OBJECT: random, random, random
-OBJECT: random, random, random
-OBJECT: random, random, random
+LOOP [6 + 2d3] {
+  OBJECT: random, random
+}
 #
-MONSTER: 'd', random, random
-MONSTER: 'd', "wolf", random
-MONSTER: 'd', "wolf", random
-MONSTER: 'd', "wolf", random
-MONSTER: 'd', "wolf", random
-MONSTER: 'E', "stalker", random
-MONSTER: 'E', "stalker", random
-MONSTER: 'E', "stalker", random
+MONSTER: 'd', random
+LOOP [3 + 2d3] {
+  MONSTER: ('d', "wolf"), random
+  MONSTER: ('E', "stalker"), random
+}
 #
+LOOP [1 + 2d3] {
 TRAP: random, random
-TRAP: random, random
-TRAP: random, random
-TRAP: random, random
+}
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/dat/sokoban.des nethack/dat/sokoban.des
--- nh_orig/dat/sokoban.des	2003-12-07 18:39:13.000000000 -0500
+++ nethack/dat/sokoban.des	2010-04-11 12:36:58.221625824 -0400
@@ -31,8 +31,34 @@
 #   Bones files are not permitted.
 
+# Temporarily commented out 'til bugfix
+# INCLUDE "functions.des"
+
+FUNCTION soko_loot()
+{
+  # Random objects
+  OBJECT:'%',random
+  OBJECT:'%',random
+  OBJECT:'%',random
+  OBJECT:'%',random
+  OBJECT:'=',random
+  OBJECT:'/',random
+}
+
+# Unused temporarily.
+#FUNCTION soko_prize()
+#{
+#  IF [50%] {
+#    OBJECT:'"',"amulet of reflection",$place[0]
+#  } ELSE {
+#    OBJECT:'(',"bag of holding",$place[0]
+#  }
+#  ENGRAVING:$place[0],burn,"Elbereth"
+#}
+
 
 ### Bottom (first) level of Sokoban ###
-MAZE:"soko4-1",' '
-FLAGS:noteleport,hardfloor
+LEVEL:"soko4-1"
+FLAGS:noteleport,hardfloor,mazelevel,premapped
+INIT_MAP:solidfill,' '
 GEOMETRY:center,center
 #12345678901234567890123456789012345678901234567890
@@ -59,16 +85,16 @@
 
 # Boulders
-OBJECT:'`',"boulder",(02,02)
-OBJECT:'`',"boulder",(02,03)
+OBJECT:('`',"boulder"),(02,02)
+OBJECT:('`',"boulder"),(02,03)
 #
-OBJECT:'`',"boulder",(10,02)
-OBJECT:'`',"boulder",(09,03)
-OBJECT:'`',"boulder",(10,04)
+OBJECT:('`',"boulder"),(10,02)
+OBJECT:('`',"boulder"),(09,03)
+OBJECT:('`',"boulder"),(10,04)
 #
-OBJECT:'`',"boulder",(08,07)
-OBJECT:'`',"boulder",(09,08)
-OBJECT:'`',"boulder",(09,09)
-OBJECT:'`',"boulder",(08,10)
-OBJECT:'`',"boulder",(10,10)
+OBJECT:('`',"boulder"),(08,07)
+OBJECT:('`',"boulder"),(09,08)
+OBJECT:('`',"boulder"),(09,09)
+OBJECT:('`',"boulder"),(08,10)
+OBJECT:('`',"boulder"),(10,10)
 
 # Traps
@@ -84,18 +110,13 @@
 
 # A little help
-OBJECT:'?',"earth",(02,11)
-OBJECT:'?',"earth",(03,11)
+OBJECT:('?',"earth"),(02,11)
+OBJECT:('?',"earth"),(03,11)
 
-# Random objects
-OBJECT:'%',random,random
-OBJECT:'%',random,random
-OBJECT:'%',random,random
-OBJECT:'%',random,random
-OBJECT:'=',random,random
-OBJECT:'/',random,random
+soko_loot()
 
 
-MAZE:"soko4-2",' '
-FLAGS:noteleport,hardfloor
+LEVEL:"soko4-2"
+FLAGS:noteleport,hardfloor,mazelevel,premapped
+INIT_MAP:solidfill,' '
 GEOMETRY:center,center
 #12345678901234567890123456789012345678901234567890
@@ -120,18 +141,18 @@
 
 # Boulders
-OBJECT:'`',"boulder",(05,02)
-OBJECT:'`',"boulder",(06,02)
-OBJECT:'`',"boulder",(06,03)
-OBJECT:'`',"boulder",(07,03)
+OBJECT:('`',"boulder"),(05,02)
+OBJECT:('`',"boulder"),(06,02)
+OBJECT:('`',"boulder"),(06,03)
+OBJECT:('`',"boulder"),(07,03)
 #
-OBJECT:'`',"boulder",(09,05)
-OBJECT:'`',"boulder",(10,03)
-OBJECT:'`',"boulder",(11,02)
-OBJECT:'`',"boulder",(12,03)
+OBJECT:('`',"boulder"),(09,05)
+OBJECT:('`',"boulder"),(10,03)
+OBJECT:('`',"boulder"),(11,02)
+OBJECT:('`',"boulder"),(12,03)
 #
-OBJECT:'`',"boulder",(07,08)
-OBJECT:'`',"boulder",(08,08)
-OBJECT:'`',"boulder",(09,08)
-OBJECT:'`',"boulder",(10,08)
+OBJECT:('`',"boulder"),(07,08)
+OBJECT:('`',"boulder"),(08,08)
+OBJECT:('`',"boulder"),(09,08)
+OBJECT:('`',"boulder"),(10,08)
 
 # Traps
@@ -148,19 +169,14 @@
 
 # A little help
-OBJECT:'?',"earth",(01,09)
-OBJECT:'?',"earth",(02,09)
+OBJECT:('?',"earth"),(01,09)
+OBJECT:('?',"earth"),(02,09)
 
-# Random objects
-OBJECT:'%',random,random
-OBJECT:'%',random,random
-OBJECT:'%',random,random
-OBJECT:'%',random,random
-OBJECT:'=',random,random
-OBJECT:'/',random,random
+soko_loot()
 
 
 ### Second level ###
-MAZE:"soko3-1",' '
-FLAGS:noteleport
+LEVEL:"soko3-1"
+FLAGS:noteleport,mazelevel,premapped
+INIT_MAP:solidfill,' '
 GEOMETRY:center,center
 #12345678901234567890123456789012345678901234567890
@@ -187,27 +203,27 @@
 
 # Boulders
-OBJECT:'`',"boulder",(03,02)
-OBJECT:'`',"boulder",(04,02)
+OBJECT:('`',"boulder"),(03,02)
+OBJECT:('`',"boulder"),(04,02)
 #
-OBJECT:'`',"boulder",(06,02)
-OBJECT:'`',"boulder",(06,03)
-OBJECT:'`',"boulder",(07,02)
+OBJECT:('`',"boulder"),(06,02)
+OBJECT:('`',"boulder"),(06,03)
+OBJECT:('`',"boulder"),(07,02)
 #
-OBJECT:'`',"boulder",(03,06)
-OBJECT:'`',"boulder",(02,07)
-OBJECT:'`',"boulder",(03,07)
-OBJECT:'`',"boulder",(03,08)
-OBJECT:'`',"boulder",(02,09)
-OBJECT:'`',"boulder",(03,09)
-OBJECT:'`',"boulder",(04,09)
+OBJECT:('`',"boulder"),(03,06)
+OBJECT:('`',"boulder"),(02,07)
+OBJECT:('`',"boulder"),(03,07)
+OBJECT:('`',"boulder"),(03,08)
+OBJECT:('`',"boulder"),(02,09)
+OBJECT:('`',"boulder"),(03,09)
+OBJECT:('`',"boulder"),(04,09)
 #
-OBJECT:'`',"boulder",(06,07)
-OBJECT:'`',"boulder",(06,09)
-OBJECT:'`',"boulder",(08,07)
-OBJECT:'`',"boulder",(08,10)
-OBJECT:'`',"boulder",(09,08)
-OBJECT:'`',"boulder",(09,09)
-OBJECT:'`',"boulder",(10,07)
-OBJECT:'`',"boulder",(10,10)
+OBJECT:('`',"boulder"),(06,07)
+OBJECT:('`',"boulder"),(06,09)
+OBJECT:('`',"boulder"),(08,07)
+OBJECT:('`',"boulder"),(08,10)
+OBJECT:('`',"boulder"),(09,08)
+OBJECT:('`',"boulder"),(09,09)
+OBJECT:('`',"boulder"),(10,07)
+OBJECT:('`',"boulder"),(10,10)
 
 # Traps
@@ -228,15 +244,10 @@
 TRAP:"hole",(26,10)
 
-# Random objects
-OBJECT:'%',random,random
-OBJECT:'%',random,random
-OBJECT:'%',random,random
-OBJECT:'%',random,random
-OBJECT:'=',random,random
-OBJECT:'/',random,random
+soko_loot()
 
 
-MAZE:"soko3-2",' '
-FLAGS:noteleport
+LEVEL:"soko3-2"
+FLAGS:noteleport,mazelevel,premapped
+INIT_MAP:solidfill,' '
 GEOMETRY:center,center
 #12345678901234567890123456789012345678901234567890
@@ -265,20 +276,20 @@
 
 # Boulders
-OBJECT:'`',"boulder",(02,03)
-OBJECT:'`',"boulder",(08,03)
-OBJECT:'`',"boulder",(09,04)
-OBJECT:'`',"boulder",(02,05)
-OBJECT:'`',"boulder",(04,05)
-OBJECT:'`',"boulder",(09,05)
-OBJECT:'`',"boulder",(02,06)
-OBJECT:'`',"boulder",(05,06)
-OBJECT:'`',"boulder",(06,07)
-OBJECT:'`',"boulder",(03,08)
-OBJECT:'`',"boulder",(07,08)
-OBJECT:'`',"boulder",(05,09)
-OBJECT:'`',"boulder",(10,09)
-OBJECT:'`',"boulder",(07,10)
-OBJECT:'`',"boulder",(10,10)
-OBJECT:'`',"boulder",(03,11)
+OBJECT:('`',"boulder"),(02,03)
+OBJECT:('`',"boulder"),(08,03)
+OBJECT:('`',"boulder"),(09,04)
+OBJECT:('`',"boulder"),(02,05)
+OBJECT:('`',"boulder"),(04,05)
+OBJECT:('`',"boulder"),(09,05)
+OBJECT:('`',"boulder"),(02,06)
+OBJECT:('`',"boulder"),(05,06)
+OBJECT:('`',"boulder"),(06,07)
+OBJECT:('`',"boulder"),(03,08)
+OBJECT:('`',"boulder"),(07,08)
+OBJECT:('`',"boulder"),(05,09)
+OBJECT:('`',"boulder"),(10,09)
+OBJECT:('`',"boulder"),(07,10)
+OBJECT:('`',"boulder"),(10,10)
+OBJECT:('`',"boulder"),(03,11)
 
 # Traps
@@ -296,16 +307,11 @@
 TRAP:"hole",(23,10)
 
-# Random objects
-OBJECT:'%',random,random
-OBJECT:'%',random,random
-OBJECT:'%',random,random
-OBJECT:'%',random,random
-OBJECT:'=',random,random
-OBJECT:'/',random,random
+soko_loot()
 
 
 ### Third level ###
-MAZE:"soko2-1",' '
-FLAGS:noteleport
+LEVEL:"soko2-1"
+FLAGS:noteleport,mazelevel,premapped
+INIT_MAP:solidfill,' '
 GEOMETRY:center,center
 #12345678901234567890123456789012345678901234567890
@@ -332,21 +338,21 @@
 
 # Boulders
-OBJECT:'`',"boulder",(02,02)
-OBJECT:'`',"boulder",(03,02)
+OBJECT:('`',"boulder"),(02,02)
+OBJECT:('`',"boulder"),(03,02)
 #
-OBJECT:'`',"boulder",(05,03)
-OBJECT:'`',"boulder",(07,03)
-OBJECT:'`',"boulder",(07,02)
-OBJECT:'`',"boulder",(08,02)
+OBJECT:('`',"boulder"),(05,03)
+OBJECT:('`',"boulder"),(07,03)
+OBJECT:('`',"boulder"),(07,02)
+OBJECT:('`',"boulder"),(08,02)
 #
-OBJECT:'`',"boulder",(10,03)
-OBJECT:'`',"boulder",(11,03)
+OBJECT:('`',"boulder"),(10,03)
+OBJECT:('`',"boulder"),(11,03)
 #
-OBJECT:'`',"boulder",(02,07)
-OBJECT:'`',"boulder",(02,08)
-OBJECT:'`',"boulder",(03,09)
+OBJECT:('`',"boulder"),(02,07)
+OBJECT:('`',"boulder"),(02,08)
+OBJECT:('`',"boulder"),(03,09)
 #
-OBJECT:'`',"boulder",(05,07)
-OBJECT:'`',"boulder",(06,06)
+OBJECT:('`',"boulder"),(05,07)
+OBJECT:('`',"boulder"),(06,06)
 
 # Traps
@@ -362,15 +368,10 @@
 TRAP:"hole",(17,09)
 
-# Random objects
-OBJECT:'%',random,random
-OBJECT:'%',random,random
-OBJECT:'%',random,random
-OBJECT:'%',random,random
-OBJECT:'=',random,random
-OBJECT:'/',random,random
+soko_loot()
 
 
-MAZE:"soko2-2",' '
-FLAGS:noteleport
+LEVEL:"soko2-2"
+FLAGS:noteleport,mazelevel,premapped
+INIT_MAP:solidfill,' '
 GEOMETRY:center,center
 #12345678901234567890123456789012345678901234567890
@@ -398,20 +399,20 @@
 
 # Boulders
-OBJECT:'`',"boulder",(04,02)
-OBJECT:'`',"boulder",(04,03)
-OBJECT:'`',"boulder",(05,03)
-OBJECT:'`',"boulder",(07,03)
-OBJECT:'`',"boulder",(08,03)
-OBJECT:'`',"boulder",(02,04)
-OBJECT:'`',"boulder",(03,04)
-OBJECT:'`',"boulder",(05,05)
-OBJECT:'`',"boulder",(06,06)
-OBJECT:'`',"boulder",(09,06)
-OBJECT:'`',"boulder",(03,07)
-OBJECT:'`',"boulder",(04,07)
-OBJECT:'`',"boulder",(07,07)
-OBJECT:'`',"boulder",(06,09)
-OBJECT:'`',"boulder",(05,10)
-OBJECT:'`',"boulder",(05,11)
+OBJECT:('`',"boulder"),(04,02)
+OBJECT:('`',"boulder"),(04,03)
+OBJECT:('`',"boulder"),(05,03)
+OBJECT:('`',"boulder"),(07,03)
+OBJECT:('`',"boulder"),(08,03)
+OBJECT:('`',"boulder"),(02,04)
+OBJECT:('`',"boulder"),(03,04)
+OBJECT:('`',"boulder"),(05,05)
+OBJECT:('`',"boulder"),(06,06)
+OBJECT:('`',"boulder"),(09,06)
+OBJECT:('`',"boulder"),(03,07)
+OBJECT:('`',"boulder"),(04,07)
+OBJECT:('`',"boulder"),(07,07)
+OBJECT:('`',"boulder"),(06,09)
+OBJECT:('`',"boulder"),(05,10)
+OBJECT:('`',"boulder"),(05,11)
 
 # Traps
@@ -428,16 +429,11 @@
 TRAP:"hole",(17,11)
 
-# Random objects
-OBJECT:'%',random,random
-OBJECT:'%',random,random
-OBJECT:'%',random,random
-OBJECT:'%',random,random
-OBJECT:'=',random,random
-OBJECT:'/',random,random
+soko_loot()
 
 
 ### Top (last) level of Sokoban ###
-MAZE:"soko1-1",' '
-FLAGS:noteleport
+LEVEL:"soko1-1"
+FLAGS:noteleport,mazelevel,premapped
+INIT_MAP:solidfill,' '
 GEOMETRY:center,center
 #12345678901234567890123456789012345678901234567890
@@ -462,5 +458,6 @@
 -----            -------  
 ENDMAP
-RANDOM_PLACES:(16,11),(16,13),(16,15)
+$place = { (16,11),(16,13),(16,15) }
+SHUFFLE: $place
 STAIR:(01,01),down
 REGION:(00,00,25,17),lit,"ordinary"
@@ -469,25 +466,25 @@
 
 # Boulders
-OBJECT:'`',"boulder",(03,05)
-OBJECT:'`',"boulder",(05,05)
-OBJECT:'`',"boulder",(07,05)
-OBJECT:'`',"boulder",(09,05)
-OBJECT:'`',"boulder",(11,05)
+OBJECT:('`',"boulder"),(03,05)
+OBJECT:('`',"boulder"),(05,05)
+OBJECT:('`',"boulder"),(07,05)
+OBJECT:('`',"boulder"),(09,05)
+OBJECT:('`',"boulder"),(11,05)
 #
-OBJECT:'`',"boulder",(04,07)
-OBJECT:'`',"boulder",(04,08)
-OBJECT:'`',"boulder",(06,07)
-OBJECT:'`',"boulder",(09,07)
-OBJECT:'`',"boulder",(11,07)
+OBJECT:('`',"boulder"),(04,07)
+OBJECT:('`',"boulder"),(04,08)
+OBJECT:('`',"boulder"),(06,07)
+OBJECT:('`',"boulder"),(09,07)
+OBJECT:('`',"boulder"),(11,07)
 #
-OBJECT:'`',"boulder",(03,12)
-OBJECT:'`',"boulder",(04,10)
-OBJECT:'`',"boulder",(05,12)
-OBJECT:'`',"boulder",(06,10)
-OBJECT:'`',"boulder",(07,11)
-OBJECT:'`',"boulder",(08,10)
-OBJECT:'`',"boulder",(09,12)
+OBJECT:('`',"boulder"),(03,12)
+OBJECT:('`',"boulder"),(04,10)
+OBJECT:('`',"boulder"),(05,12)
+OBJECT:('`',"boulder"),(06,10)
+OBJECT:('`',"boulder"),(07,11)
+OBJECT:('`',"boulder"),(08,10)
+OBJECT:('`',"boulder"),(09,12)
 #
-OBJECT:'`',"boulder",(03,14)
+OBJECT:('`',"boulder"),(03,14)
 
 # Traps
@@ -509,14 +506,8 @@
 TRAP:"hole",(23,01)
 
-MONSTER:'m',"giant mimic", random, m_object "boulder"
-MONSTER:'m',"giant mimic", random, m_object "boulder"
+MONSTER:('m',"giant mimic"), random, m_object "boulder"
+MONSTER:('m',"giant mimic"), random, m_object "boulder"
 
-# Random objects
-OBJECT:'%',random,random
-OBJECT:'%',random,random
-OBJECT:'%',random,random
-OBJECT:'%',random,random
-OBJECT:'=',random,random
-OBJECT:'/',random,random
+soko_loot()
 
 # Rewards
@@ -526,10 +517,17 @@
 DOOR:closed,(17,15)
 REGION:(18,10,22,16),lit,"zoo",filled,true
-OBJECT:'(',"bag of holding",place[0]
-ENGRAVING:place[0],burn,"Elbereth"
 
+#soko_prize()
+  IF [50%] {
+    OBJECT:('"',"amulet of reflection"),$place[0]
+  } ELSE {
+    OBJECT:('(',"bag of holding"),$place[0]
+  }
+  ENGRAVING:$place[0],burn,"Elbereth"
 
-MAZE:"soko1-2",' '
-FLAGS:noteleport
+
+LEVEL:"soko1-2"
+FLAGS:noteleport,mazelevel,premapped
+INIT_MAP:solidfill,' '
 GEOMETRY:center,center
 #12345678901234567890123456789012345678901234567890
@@ -553,5 +551,6 @@
      -------     -------  
 ENDMAP
-RANDOM_PLACES:(16,10),(16,12),(16,14)
+$place = { (16,10),(16,12),(16,14) }
+SHUFFLE:$place
 STAIR:(06,15),down
 REGION:(00,00,25,16),lit,"ordinary"
@@ -560,26 +559,26 @@
 
 # Boulders
-OBJECT:'`',"boulder",(04,04)
-OBJECT:'`',"boulder",(02,06)
-OBJECT:'`',"boulder",(03,06)
-OBJECT:'`',"boulder",(04,07)
-OBJECT:'`',"boulder",(05,07)
-OBJECT:'`',"boulder",(02,08)
-OBJECT:'`',"boulder",(05,08)
-OBJECT:'`',"boulder",(03,09)
-OBJECT:'`',"boulder",(04,09)
-OBJECT:'`',"boulder",(03,10)
-OBJECT:'`',"boulder",(05,10)
-OBJECT:'`',"boulder",(06,12)
+OBJECT:('`',"boulder"),(04,04)
+OBJECT:('`',"boulder"),(02,06)
+OBJECT:('`',"boulder"),(03,06)
+OBJECT:('`',"boulder"),(04,07)
+OBJECT:('`',"boulder"),(05,07)
+OBJECT:('`',"boulder"),(02,08)
+OBJECT:('`',"boulder"),(05,08)
+OBJECT:('`',"boulder"),(03,09)
+OBJECT:('`',"boulder"),(04,09)
+OBJECT:('`',"boulder"),(03,10)
+OBJECT:('`',"boulder"),(05,10)
+OBJECT:('`',"boulder"),(06,12)
 #
-OBJECT:'`',"boulder",(07,14)
+OBJECT:('`',"boulder"),(07,14)
 #
-OBJECT:'`',"boulder",(11,05)
-OBJECT:'`',"boulder",(12,06)
-OBJECT:'`',"boulder",(10,07)
-OBJECT:'`',"boulder",(11,07)
-OBJECT:'`',"boulder",(10,08)
-OBJECT:'`',"boulder",(12,09)
-OBJECT:'`',"boulder",(11,10)
+OBJECT:('`',"boulder"),(11,05)
+OBJECT:('`',"boulder"),(12,06)
+OBJECT:('`',"boulder"),(10,07)
+OBJECT:('`',"boulder"),(11,07)
+OBJECT:('`',"boulder"),(10,08)
+OBJECT:('`',"boulder"),(12,09)
+OBJECT:('`',"boulder"),(11,10)
 
 # Traps
@@ -603,14 +602,8 @@
 TRAP:"hole",(22,01)
 
-MONSTER:'m',"giant mimic", random, m_object "boulder"
-MONSTER:'m',"giant mimic", random, m_object "boulder"
+MONSTER:('m',"giant mimic"), random, m_object "boulder"
+MONSTER:('m',"giant mimic"), random, m_object "boulder"
 
-# Random objects
-OBJECT:'%',random,random
-OBJECT:'%',random,random
-OBJECT:'%',random,random
-OBJECT:'%',random,random
-OBJECT:'=',random,random
-OBJECT:'/',random,random
+soko_loot()
 
 # Rewards
@@ -620,4 +613,9 @@
 DOOR:closed,(17,14)
 REGION:(18,09,22,15),lit,"zoo",filled,true
-OBJECT:'"',"amulet of reflection",place[0]
-ENGRAVING:place[0],burn,"Elbereth"
+#soko_prize()
+  IF [50%] {
+    OBJECT:('"',"amulet of reflection"),$place[0]
+  } ELSE {
+    OBJECT:('(',"bag of holding"),$place[0]
+  }
+  ENGRAVING:$place[0],burn,"Elbereth"
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/dat/Tourist.des nethack/dat/Tourist.des
--- nh_orig/dat/Tourist.des	2003-12-07 18:39:12.000000000 -0500
+++ nethack/dat/Tourist.des	2010-08-16 13:20:13.633706782 -0400
@@ -9,6 +9,8 @@
 #	and receive your quest assignment.
 #
-MAZE: "Tou-strt",' '
-FLAGS: noteleport,hardfloor
+LEVEL: "Tou-strt"
+FLAGS: noteleport,hardfloor,mazelevel
+INIT_MAP:solidfill,' '
+MON_GENERATION:86%, (64,"giant spider"), (16,'S'), (16,"forest centaur"), (4,'C')
 GEOMETRY:center,center
 MAP
@@ -16,5 +18,5 @@
 ........}}...|.......|..|.-------------------------------------------...|...
 .........}}..|.......|..|.|......|......|.............|......|......|...|...
-..........}}.|.......|..|.|......+......+.............+......+..\...|...|...
+..........}}.|.......|..|.|......+......+.............+......+......|...|...
 ...........}}}..........|.|......|......|.............|......|......|...|...
 .............}}.........|.|----S-|--S---|S----------S-|---S--|------|...|...
@@ -71,62 +73,89 @@
 DOOR:locked,(36,07)
 # Monsters on siege duty.
-MONSTER: 's',"giant spider",random
-MONSTER: 's',"giant spider",random
-MONSTER: 's',"giant spider",random
-MONSTER: 's',"giant spider",random
-MONSTER: 's',"giant spider",random
-MONSTER: 's',"giant spider",random
-MONSTER: 's',"giant spider",random
-MONSTER: 's',"giant spider",random
-MONSTER: 's',"giant spider",random
-MONSTER: 's',"giant spider",random
-MONSTER: 's',"giant spider",random
-MONSTER: 's',"giant spider",random
-MONSTER: 's',random,random
-MONSTER: 's',random,random
-MONSTER: 'C',"forest centaur",random
-MONSTER: 'C',"forest centaur",random
-MONSTER: 'C',"forest centaur",random
-MONSTER: 'C',"forest centaur",random
-MONSTER: 'C',"forest centaur",random
-MONSTER: 'C',"forest centaur",random
-MONSTER: 'C',"forest centaur",random
-MONSTER: 'C',"forest centaur",random
-MONSTER: 'C',random,random
+LOOP [10 + 1d10] {
+  MONSTER: ('s',"giant spider"),random
+}
+MONSTER: 's',random
+MONSTER: 's',random
+LOOP [6 + 1d10] {
+  MONSTER: ('C',"forest centaur"),random
+}
+MONSTER: 'C',random
 # Twoflower
-MONSTER:'@',"Twoflower",(64,03)
+OBJECT:('\',"throne"),(64,03)
+MONSTER:('@',"Twoflower"),(64,03) {
+  OBJECT:random
+  OBJECT:random
+  OBJECT:random
+  OBJECT:random
+  OBJECT:random
+  OBJECT:random
+}
 # The treasure of Twoflower
-OBJECT:'(',"chest",(64,03)
+OBJECT:('(',"chest"),(64,03)
 # guides for the audience chamber
-MONSTER:'@',"guide",(29,03)
-MONSTER:'@',"guide",(32,04)
-MONSTER:'@',"guide",(35,02)
-MONSTER:'@',"guide",(38,03)
-MONSTER:'@',"guide",(45,03)
-MONSTER:'@',"guide",(48,02)
-MONSTER:'@',"guide",(49,04)
-MONSTER:'@',"guide",(51,03)
-MONSTER:'@',"guide",(57,03)
-MONSTER:'@',"guide",(62,04)
-MONSTER:'@',"guide",(66,04)
+MONSTER:('@',"guide"),(29,03) {
+  OBJECT:random
+  OBJECT[25%]:random
+}
+MONSTER:('@',"guide"),(32,04) {
+  OBJECT:random
+  OBJECT[25%]:random
+}
+MONSTER:('@',"guide"),(35,02) {
+  OBJECT:random
+  OBJECT[25%]:random
+}
+MONSTER:('@',"guide"),(38,03) {
+  OBJECT:random
+  OBJECT[25%]:random
+}
+MONSTER:('@',"guide"),(45,03) {
+  OBJECT:random
+  OBJECT[25%]:random
+}
+MONSTER:('@',"guide"),(48,02) {
+  OBJECT:random
+  OBJECT[25%]:random
+}
+MONSTER:('@',"guide"),(49,04) {
+  OBJECT:random
+  OBJECT[25%]:random
+}
+MONSTER:('@',"guide"),(51,03) {
+  OBJECT:random
+  OBJECT[25%]:random
+}
+MONSTER:('@',"guide"),(57,03) {
+  OBJECT:random
+  OBJECT[25%]:random
+}
+MONSTER:('@',"guide"),(62,04) {
+  OBJECT:random
+  OBJECT[25%]:random
+}
+MONSTER:('@',"guide"),(66,04) {
+  OBJECT:random
+  OBJECT[25%]:random
+}
 # path guards
-MONSTER:'@',"watchman",(35,08)
-MONSTER:'@',"watchman",(36,08)
+MONSTER:('@',"watchman"),(35,08) {
+  OBJECT:'['
+  OBJECT:')'
+}
+MONSTER:('@',"watchman"),(36,08) {
+  OBJECT:'['
+  OBJECT:')'
+}
 # river monsters
-MONSTER:';',"giant eel",(62,12)
-MONSTER:';',"piranha",(47,10)
-MONSTER:';',"piranha",(29,11)
-MONSTER:';',"kraken",(34,09)
-MONSTER:';',"kraken",(37,09)
+MONSTER:(';',"giant eel"),(62,12)
+MONSTER:(';',"piranha"),(47,10)
+MONSTER:(';',"piranha"),(29,11)
+MONSTER:(';',"kraken"),(34,09)
+MONSTER:(';',"kraken"),(37,09)
 # Random traps
+LOOP [7 + 1d10] {
 TRAP:random,random
-TRAP:random,random
-TRAP:random,random
-TRAP:random,random
-TRAP:random,random
-TRAP:random,random
-TRAP:random,random
-TRAP:random,random
-TRAP:random,random
+}
 
 #
@@ -137,6 +166,8 @@
 #
 
-MAZE: "Tou-loca",' '
-FLAGS: hardfloor
+LEVEL: "Tou-loca"
+FLAGS: hardfloor,mazelevel
+INIT_MAP:solidfill,' '
+MON_GENERATION:86%, (64,"giant spider"), (16,'S'), (16,"forest centaur"), (4,'C')
 GEOMETRY:center,center
 MAP
@@ -152,5 +183,5 @@
 |....+.....+.........S...|...........|....|-------|........................|
 |....|.....|.........|...|.|---------|....|.........|-------|.|----------|.|
-|....|.....|---------|---|.|......|..+....|-------|.|.......|.+......S.\.|.|
+|....|.....|---------|---|.|......|..+....|-------|.|.......|.+......S...|.|
 |....|.....+.........S...|.|......|..|....|.......|.|.......|.|......|...|.|
 |-------|..|.........|---|.|+-------------------+-|.|.......+.|----------|.|
@@ -243,50 +274,21 @@
 
 # Objects
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
+LOOP [10 + 1d10] {
+  OBJECT:random,random
+}
 # Toilet paper
-OBJECT:'?',"blank paper",(71,12)
-OBJECT:'?',"blank paper",(71,12)
+OBJECT:('\',"throne"),(71,11)
+OBJECT:('?',"blank paper"),(71,12)
+OBJECT:('?',"blank paper"),(71,12)
 # Random traps
+LOOP [5 + 1d10] {
 TRAP:random,random
-TRAP:random,random
-TRAP:random,random
-TRAP:random,random
-TRAP:random,random
-TRAP:random,random
-TRAP:random,random
-TRAP:random,random
-TRAP:random,random
+}
 # Random monsters.
-MONSTER:'s',"giant spider",random
-MONSTER:'s',"giant spider",random
-MONSTER:'s',"giant spider",random
-MONSTER:'s',"giant spider",random
-MONSTER:'s',"giant spider",random
-MONSTER:'s',"giant spider",random
-MONSTER:'s',"giant spider",random
-MONSTER:'s',"giant spider",random
-MONSTER:'s',"giant spider",random
-MONSTER:'s',"giant spider",random
-MONSTER:'s',"giant spider",random
-MONSTER:'s',"giant spider",random
-MONSTER:'s',"giant spider",random
-MONSTER:'s',"giant spider",random
-MONSTER:'s',"giant spider",random
-MONSTER:'s',"giant spider",random
-MONSTER:'s',random,random
-MONSTER:'s',random,random
+LOOP [10 + 2d10] {
+  MONSTER:('s',"giant spider"),random
+}
+MONSTER:'s',random
+MONSTER:'s',random
 
 #
@@ -298,5 +300,8 @@
 #
 
-MAZE: "Tou-goal", ' '
+LEVEL: "Tou-goal"
+FLAGS:mazelevel
+INIT_MAP:solidfill,' '
+MON_GENERATION:86%, (64,"giant spider"), (16,'S'), (16,"forest centaur"), (4,'C')
 GEOMETRY:center,center
 MAP
@@ -385,68 +390,49 @@
 DOOR:open,(59,17)
 # Objects
-OBJECT:'(',"credit card",(04,01),blessed,0,"The Platinum Yendorian Express Card"
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
+OBJECT:('(',"credit card"),(04,01),blessed,0,NAME:"The Platinum Yendorian Express Card"
+LOOP [8 + 1d5] {
+  OBJECT:random,random
+}
 # Random traps
+LOOP [3 + 1d5] {
 TRAP:random,random
-TRAP:random,random
-TRAP:random,random
-TRAP:random,random
-TRAP:random,random
-TRAP:random,random
+}
 # Random monsters.
-MONSTER:'@',"Master of Thieves",(04,01),hostile
-MONSTER:'s',"giant spider",random
-MONSTER:'s',"giant spider",random
-MONSTER:'s',"giant spider",random
-MONSTER:'s',"giant spider",random
-MONSTER:'s',"giant spider",random
-MONSTER:'s',"giant spider",random
-MONSTER:'s',"giant spider",random
-MONSTER:'s',"giant spider",random
-MONSTER:'s',"giant spider",random
-MONSTER:'s',"giant spider",random
-MONSTER:'s',"giant spider",random
-MONSTER:'s',"giant spider",random
-MONSTER:'s',"giant spider",random
-MONSTER:'s',"giant spider",random
-MONSTER:'s',"giant spider",random
-MONSTER:'s',"giant spider",random
-MONSTER:'s',random,random
-MONSTER:'s',random,random
+MONSTER:('@',"Master of Thieves"),(04,01),hostile {
+  OBJECT:('(', "Bell of Opening"),uncursed
+  OBJECT:'['
+  OBJECT:')'
+  OBJECT:'!'
+  OBJECT:'!'
+  OBJECT:'!'
+  OBJECT:'!'
+}
+LOOP [10 + 2d5] {
+  MONSTER:('s',"giant spider"),random
+}
+MONSTER:'s',random
+MONSTER:'s',random
 # ladies of the evening
-MONSTER:'&',"succubus",(02,08)
-MONSTER:'&',"succubus",(08,08)
-MONSTER:'&',"incubus",(02,14)
-MONSTER:'&',"incubus",(08,14)
-MONSTER:'&',"incubus",(02,17)
-MONSTER:'&',"incubus",(08,17)
+MONSTER:('&',"succubus"),(02,08)
+MONSTER:('&',"succubus"),(08,08)
+MONSTER:('&',"incubus"),(02,14)
+MONSTER:('&',"incubus"),(08,14)
+MONSTER:('&',"incubus"),(02,17)
+MONSTER:('&',"incubus"),(08,17)
 # Police station (with drunken prisoners)
-MONSTER:'K',"Kop Kaptain",(24,09),hostile
-MONSTER:'K',"Kop Lieutenant",(20,09),hostile
-MONSTER:'K',"Kop Lieutenant",(22,11),hostile
-MONSTER:'K',"Kop Lieutenant",(22,07),hostile
-MONSTER:'K',"Keystone Kop",(19,07),hostile
-MONSTER:'K',"Keystone Kop",(19,08),hostile
-MONSTER:'K',"Keystone Kop",(22,09),hostile
-MONSTER:'K',"Keystone Kop",(24,11),hostile
-MONSTER:'K',"Keystone Kop",(19,11),hostile
-MONSTER:'@',"prisoner",(19,13)
-MONSTER:'@',"prisoner",(21,13)
-MONSTER:'@',"prisoner",(24,13)
+MONSTER:('K',"Kop Kaptain"),(24,09),hostile
+MONSTER:('K',"Kop Lieutenant"),(20,09),hostile
+MONSTER:('K',"Kop Lieutenant"),(22,11),hostile
+MONSTER:('K',"Kop Lieutenant"),(22,07),hostile
+MONSTER:('K',"Keystone Kop"),(19,07),hostile
+MONSTER:('K',"Keystone Kop"),(19,08),hostile
+MONSTER:('K',"Keystone Kop"),(22,09),hostile
+MONSTER:('K',"Keystone Kop"),(24,11),hostile
+MONSTER:('K',"Keystone Kop"),(19,11),hostile
+MONSTER:('@',"prisoner"),(19,13)
+MONSTER:('@',"prisoner"),(21,13)
+MONSTER:('@',"prisoner"),(24,13)
 #
-MONSTER:'@',"watchman",(33,10),hostile
+MONSTER:('@',"watchman"),(33,10),hostile
 
 WALLIFY
@@ -459,6 +445,8 @@
 #
 
-MAZE: "Tou-fila" , ' '
-INIT_MAP: '.' , ' ', true, true, random, true
+LEVEL: "Tou-fila"
+FLAGS:mazelevel,noflip
+INIT_MAP: mines, '.' , ' ', true, true, random, true
+MON_GENERATION:86%, (64,"giant spider"), (16,'S'), (16,"forest centaur"), (4,'C')
 NOMAP
 #
@@ -466,27 +454,22 @@
 STAIR: random, down
 #
-OBJECT: random, random, random
-OBJECT: random, random, random
-OBJECT: random, random, random
-OBJECT: random, random, random
-OBJECT: random, random, random
-OBJECT: random, random, random
-OBJECT: random, random, random
+LOOP [2 + 2d4] {
+  OBJECT: random, random
+}
 #
+LOOP [2 + 2d4] {
 TRAP: random, random
-TRAP: random, random
-TRAP: random, random
-TRAP: random, random
+}
 #
-MONSTER: '@', "soldier", random, hostile
-MONSTER: '@', "soldier", random, hostile
-MONSTER: '@', "soldier", random, hostile
-MONSTER: '@', "soldier", random, hostile
-MONSTER: '@', "soldier", random, hostile
-MONSTER: 'H', random, random, hostile
-MONSTER: 'C', random, random, hostile
+LOOP [2 + 2d4] {
+  MONSTER: ('@', "soldier"), random, hostile
+}
+MONSTER: 'H', random, hostile
+MONSTER: 'C', random, hostile
 
-MAZE: "Tou-filb" , ' '
-INIT_MAP: '.' , ' ', true, true, random, true
+LEVEL: "Tou-filb"
+FLAGS:mazelevel,noflip
+INIT_MAP: mines, '.' , ' ', true, true, random, true
+MON_GENERATION:86%, (64,"giant spider"), (16,'S'), (16,"forest centaur"), (4,'C')
 NOMAP
 #
@@ -494,26 +477,19 @@
 STAIR: random, down
 #
-OBJECT: random, random, random
-OBJECT: random, random, random
-OBJECT: random, random, random
-OBJECT: random, random, random
-OBJECT: random, random, random
-OBJECT: random, random, random
-OBJECT: random, random, random
-OBJECT: random, random, random
-OBJECT: random, random, random
-OBJECT: random, random, random
-OBJECT: random, random, random
+LOOP [7 + 2d4] {
+  OBJECT: random, random
+}
 #
+LOOP [4 + 2d4] {
 TRAP: random, random
-TRAP: random, random
-TRAP: random, random
-TRAP: random, random
+}
 #
-MONSTER: '@', "soldier", random, hostile
-MONSTER: '@', "captain", random, hostile
-MONSTER: '@', "captain", random, hostile
-MONSTER: 'H', random, random, hostile
-MONSTER: 'H', random, random, hostile
-MONSTER: 'C', random, random, hostile
-MONSTER: 's', random, random
+LOOP [2d4] {
+  MONSTER: ('@', "soldier"), random, hostile
+  MONSTER: 'C', random, hostile
+  MONSTER: 's', random
+}
+MONSTER: ('@', "captain"), random, hostile
+MONSTER: ('@', "captain"), random, hostile
+MONSTER: 'H', random, hostile
+MONSTER: 'H', random, hostile
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/dat/tower.des nethack/dat/tower.des
--- nh_orig/dat/tower.des	2003-12-07 18:39:13.000000000 -0500
+++ nethack/dat/tower.des	2010-04-11 12:36:58.306750100 -0400
@@ -4,6 +4,7 @@
 #
 # Upper stage of Vlad's tower
-MAZE:"tower1",' '
-FLAGS: noteleport,hardfloor
+LEVEL:"tower1"
+FLAGS: noteleport,hardfloor,mazelevel
+INIT_MAP:solidfill,' '
 GEOMETRY:half-left,center
 MAP
@@ -13,5 +14,5 @@
 |.......+.+...|
 ---+-----.-----
-  |...\.|.+.|  
+  |.....|.+.|  
 ---+-----.-----
 |.......+.+...|
@@ -22,11 +23,15 @@
 LADDER:(11,05),down
 # The lord and his court
-MONSTER:'V',"Vlad the Impaler",(06,05)
-MONSTER:'V',random,(03,09)
-MONSTER:'V',random,(07,09)
-MONSTER:'V',random,(11,09)
-MONSTER:'V',random,(03,01)
-MONSTER:'V',random,(07,01)
-MONSTER:'V',random,(11,01)
+OBJECT:('\',"throne"),(06,05)
+MONSTER:('V',"Vlad the Impaler"),(06,05) {
+  OBJECT:(')',"two-handed sword"),1d3,NAME:"Lifestealer",cursed,erodeproof
+  OBJECT:('(',"Candelabrum of Invocation")
+}
+MONSTER:'V',(03,09)
+MONSTER:'V',(07,09)
+MONSTER:'V',(11,09)
+MONSTER:'V',(03,01)
+MONSTER:'V',(07,01)
+MONSTER:'V',(11,01)
 # The doors
 DOOR:closed,(08,03)
@@ -38,11 +43,11 @@
 DOOR:closed,(03,06)
 # treasures
-OBJECT:'(',"chest",(07,05)
-OBJECT:'(',"chest",(03,09)
-OBJECT:'(',"chest",(07,09)
-OBJECT:'(',"chest",(11,09)
-OBJECT:'(',"chest",(03,01)
-OBJECT:'(',"chest",(07,01)
-OBJECT:'(',"chest",(11,01)
+OBJECT:('(',"chest"),(07,05)
+OBJECT:('(',"chest"),(03,09)
+OBJECT:('(',"chest"),(07,09)
+OBJECT:('(',"chest"),(11,09)
+OBJECT:('(',"chest"),(03,01)
+OBJECT:('(',"chest"),(07,01)
+OBJECT:('(',"chest"),(11,01)
 # We have to protect the tower against outside attacks
 NON_DIGGABLE:(00,00,14,10)
@@ -50,6 +55,7 @@
 
 # Intermediate stage of Vlad's tower
-MAZE:"tower2",' '
-FLAGS: noteleport,hardfloor
+LEVEL:"tower2"
+FLAGS: noteleport,hardfloor,mazelevel
+INIT_MAP:solidfill,' '
 GEOMETRY:half-left,center
 MAP
@@ -67,22 +73,25 @@
 ENDMAP
 # Random places are the 10 niches
-RANDOM_PLACES:(03,01),(07,01),(11,01),(01,03),(13,03),
-	      (01,07),(13,07),(03,09),(07,09),(11,09)
+$place = { (03,01),(07,01),(11,01),(01,03),(13,03),
+	      (01,07),(13,07),(03,09),(07,09),(11,09) }
+SHUFFLE:$place
 LADDER:(11,05),up
 LADDER:(03,07),down
 DOOR:locked,(10,04)
 DOOR:locked,(09,07)
-MONSTER:'&',random,place[0]
-MONSTER:'&',random,place[1]
-MONSTER:'d',"hell hound pup",place[2]
-MONSTER:'d',"hell hound pup",place[3]
-MONSTER:'d',"winter wolf",place[4]
-CONTAINER:'(',"chest",place[5]
-OBJECT:'"',"amulet of life saving",contained
-CONTAINER:'(',"chest",place[6]
-OBJECT:'"',"amulet of strangulation",contained
-OBJECT:'[',"water walking boots",place[7]
-OBJECT:'[',"crystal plate mail",place[8]
-OBJECT:'+',"invisibility",place[9]
+MONSTER:'&',$place[0]
+MONSTER:'&',$place[1]
+MONSTER:('d',"hell hound pup"),$place[2]
+MONSTER:('d',"hell hound pup"),$place[3]
+MONSTER:('d',"winter wolf"),$place[4]
+CONTAINER:('(',"chest"),$place[5] {
+  OBJECT:('"',"amulet of life saving")
+}
+CONTAINER:('(',"chest"),$place[6] {
+  OBJECT:('"',"amulet of strangulation")
+}
+OBJECT:('[',"water walking boots"),$place[7]
+OBJECT:('[',"crystal plate mail"),$place[8]
+OBJECT:('+',"invisibility"),$place[9]
 # Walls in the tower are non diggable
 NON_DIGGABLE:(00,00,14,10)
@@ -90,6 +99,7 @@
 
 # Bottom most stage of Vlad's tower
-MAZE:"tower3",' '
-FLAGS: noteleport,hardfloor
+LEVEL:"tower3"
+FLAGS: noteleport,hardfloor,mazelevel
+INIT_MAP:solidfill,' '
 GEOMETRY:half-left,center
 MAP
@@ -109,6 +119,7 @@
 ENDMAP
 # Random places are the 10 niches
-RANDOM_PLACES:(05,01),(09,01),(13,01),(03,03),(15,03),
-	      (03,07),(15,07),(05,09),(09,09),(13,09)
+$place = { (05,01),(09,01),(13,01),(03,03),(15,03),
+	      (03,07),(15,07),(05,09),(09,09),(13,09) }
+SHUFFLE:$place
 BRANCH:(02,05,02,05),(00,00,00,00)
 LADDER:(05,07),up
@@ -116,21 +127,18 @@
 DOOR:locked,(14,05)
 # Let's put a dragon behind the door, just for the fun...
-MONSTER:'D',random,(13,05)
-MONSTER:random,random,(12,04)
-MONSTER:random,random,(12,06)
-MONSTER:random,random,random
-MONSTER:random,random,random
-MONSTER:random,random,random
-MONSTER:random,random,random
-MONSTER:random,random,random
-MONSTER:random,random,random
-OBJECT:')',"long sword",place[0]
-TRAP:random,place[0]
-OBJECT:'(',"lock pick",place[1]
-TRAP:random,place[1]
-OBJECT:'[',"elven cloak",place[2]
-TRAP:random,place[2]
-OBJECT:'(',"blindfold",place[3]
-TRAP:random,place[3]
+MONSTER:'D',(13,05)
+MONSTER:random,(12,04)
+MONSTER:random,(12,06)
+LOOP [4 + 3d4] {
+  MONSTER:random,random
+}
+OBJECT:(')',"long sword"),$place[0]
+TRAP:random,$place[0]
+OBJECT:('(',"lock pick"),$place[1]
+TRAP:random,$place[1]
+OBJECT:('[',"elven cloak"),$place[2]
+TRAP:random,$place[2]
+OBJECT:('(',"blindfold"),$place[3]
+TRAP:random,$place[3]
 # Walls in the tower are non diggable
 NON_DIGGABLE:(00,00,18,12)
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/dat/Valkyrie.des nethack/dat/Valkyrie.des
--- nh_orig/dat/Valkyrie.des	2003-12-07 18:39:12.000000000 -0500
+++ nethack/dat/Valkyrie.des	2010-08-16 13:20:13.633706782 -0400
@@ -9,29 +9,46 @@
 #	and receive your quest assignment.
 #
-MAZE: "Val-strt",' '
-FLAGS: noteleport,hardfloor
+LEVEL: "Val-strt"
+FLAGS: noteleport,hardfloor,mazelevel
+INIT_MAP:solidfill,'I'
+
+# This works because the random coordinates in $pools are evaluated once,
+# when the variable is initialized.
+$pools = selection: random & random & random & random & random &
+	   random & random & random & random & random & random &
+	   random & random &
+	   grow(west, random) &
+	   grow(north, random) &
+	   grow(random & random)
+TERRAIN:grow($pools), 'P'
+TERRAIN:$pools, 'L'
+
+MON_GENERATION:86%, (64,"fire ant"), (16,'a'), (16,"fire giant"), (4,'H')
 GEOMETRY:center,center
 MAP
-IIIIIIPPPIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII
-IIIIPPPPPIIIIIIII..IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII...IIIIIIIIIIIIIIIIIIIII
-IIIIPLLPPIIIIIII..IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII..{..IIIIIIIIIIIIIIIIIIII
-IIIIPLPPIIIIIII..IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII.....IIIIIIPPPIIIIIIIIII
-IIIPPPPPIIIIII..IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII.IIIIIPPLPIIIIIIIIII
-IIIIPIIIIIIII..IIIIPPPIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII.IIIIIPLPPIIIIIIIIII
-IIIIIIIIIIII..IIIIIPLPPIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII..IIIIIPPPIIIIIIIIIII
-IIIIIIII.....IIIIIIPPPIIII|----------------|IIIIIPPPIII.IIIIIIIIIIIIIIIIIIII
-IIIIIII..III...IIIIIIIIIII|................|IIIIIPLPII..IIIIIIIIIIIIIIIIIIII
-IIIIII..IIIIII......IIIII.|................|.IIIIPPPII.IIIIIIIIIIIIIIIIIIIII
-IIIII..IIIIIIIIIIII.......+................+...IIIIIII.IIIIIIIIIIIIIIIIIIIII
-IIII..IIIIIIIII.....IIIII.|................|.I...IIIII.IIIIIIIIIIIIIIIIIIIII
-III..IIIIIIIII..IIIIIIIIII|................|IIII.......IIIIIIIIIIIIIIIIIIIII
-IIII..IIIIIII..IIIIIIIIIII|----------------|IIIIIIIIII...IIIIIIIIIIIIIIIIIII
-IIIIII..IIII..IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIPPPPIIII...IIIIIIIIIIIIIIIII
-IIIIIII......IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIPLLPPIIIII...IIIIIIIIIIIIIII
-IIIIPPPIP...IIIIIIIIIIIPIIIIIIIIIIIIIIIIIIIIIIIIPPPPIIIIIIII...I......IIIIII
-IIIPPLPPIIIIIIIIIIIIIIPPPIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII.........IIIII
-IIIIPPPIIIIIIIIIIIIIIPPLPIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII.......IIIIII
-IIIIIIIIIIIIIIIIIIIIIIPPPIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxx..xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx...xxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxx..xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx..{..xxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxx..xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.....xxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxx..xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.xxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxx..xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.xxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxx..xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx..xxxxxxxxxxxxxxxxxxx
+xxxxxxxx.....xxxxxxxxxxxxx|----------------|xxxxxxxxxxx.xxxxxxxxxxxxxxxxxxxx
+xxxxxxx..xxx...xxxxxxxxxxx|................|xxxxxxxxxx..xxxxxxxxxxxxxxxxxxxx
+xxxxxx..xxxxxx......xxxxx.|................|.xxxxxxxxx.xxxxxxxxxxxxxxxxxxxxx
+xxxxx..xxxxxxxxxxxx.......+................+...xxxxxxx.xxxxxxxxxxxxxxxxxxxxx
+xxxx..xxxxxxxxx.....xxxxx.|................|.x...xxxxx.xxxxxxxxxxxxxxxxxxxxx
+xxx..xxxxxxxxx..xxxxxxxxxx|................|xxxx.......xxxxxxxxxxxxxxxxxxxxx
+xxxx..xxxxxxx..xxxxxxxxxxx|----------------|xxxxxxxxxx...xxxxxxxxxxxxxxxxxxx
+xxxxxx..xxxx..xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx...xxxxxxxxxxxxxxxxx
+xxxxxxx......xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx...xxxxxxxxxxxxxxx
+xxxxxxxxx...xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx...x......xxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.........xxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.......xxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
 ENDMAP
+
+REPLACE_TERRAIN:(00,00,75,19), 'I', 'P', 2%
+
 # Dungeon Description
 REGION:(00,00,75,19),lit,"ordinary"
@@ -46,38 +63,64 @@
 DOOR:locked,(43,10)
 # Norn
-MONSTER:'@',"Norn",(35,10)
+MONSTER:('@',"Norn"),(35,10) {
+  OBJECT:'['
+  OBJECT:')'
+  OBJECT:'?'
+  OBJECT:'?'
+}
 # The treasure of the Norn
-OBJECT:'(',"chest",(36,10)
+OBJECT:('(',"chest"),(36,10)
 # valkyrie guards for the audience chamber
-MONSTER:'@',"warrior",(27,08)
-MONSTER:'@',"warrior",(27,09)
-MONSTER:'@',"warrior",(27,11)
-MONSTER:'@',"warrior",(27,12)
-MONSTER:'@',"warrior",(42,08)
-MONSTER:'@',"warrior",(42,09)
-MONSTER:'@',"warrior",(42,11)
-MONSTER:'@',"warrior",(42,12)
+MONSTER:('@',"warrior"),(27,08) {
+  OBJECT[75%]:'['
+  OBJECT[75%]:')'
+}
+MONSTER:('@',"warrior"),(27,09) {
+  OBJECT[75%]:'['
+  OBJECT[75%]:')'
+}
+MONSTER:('@',"warrior"),(27,11) {
+  OBJECT[75%]:'['
+  OBJECT[75%]:')'
+}
+MONSTER:('@',"warrior"),(27,12) {
+  OBJECT[75%]:'['
+  OBJECT[75%]:')'
+}
+MONSTER:('@',"warrior"),(42,08) {
+  OBJECT[75%]:'['
+  OBJECT[75%]:')'
+}
+MONSTER:('@',"warrior"),(42,09) {
+  OBJECT[75%]:'['
+  OBJECT[75%]:')'
+}
+MONSTER:('@',"warrior"),(42,11) {
+  OBJECT[75%]:'['
+  OBJECT[75%]:')'
+}
+MONSTER:('@',"warrior"),(42,12) {
+  OBJECT[75%]:'['
+  OBJECT[75%]:')'
+}
 # Non diggable walls
 NON_DIGGABLE:(26,07,43,13)
 # Random traps
+LOOP [3 + 3d5] {
 TRAP:"fire",random
-TRAP:"fire",random
-TRAP:"fire",random
-TRAP:"fire",random
-TRAP:"fire",random
-TRAP:"fire",random
+}
 # Monsters on siege duty.
-MONSTER: 'a',"fire ant",(04,12)
-MONSTER: 'a',"fire ant",(08,08)
-MONSTER: 'a',"fire ant",(14,04)
-MONSTER: 'a',"fire ant",(17,11)
-MONSTER: 'a',"fire ant",(24,10)
-MONSTER: 'a',"fire ant",(45,10)
-MONSTER: 'a',"fire ant",(54,02)
-MONSTER: 'a',"fire ant",(55,07)
-MONSTER: 'a',"fire ant",(58,14)
-MONSTER: 'a',"fire ant",(63,17)
-MONSTER: 'H',"fire giant",(18,01),hostile
-MONSTER: 'H',"fire giant",(10,16),hostile
+MONSTER: ('a',"fire ant"),(04,12)
+MONSTER: ('a',"fire ant"),(08,08)
+MONSTER: ('a',"fire ant"),(14,04)
+MONSTER: ('a',"fire ant"),(17,11)
+MONSTER: ('a',"fire ant"),(24,10)
+MONSTER: ('a',"fire ant"),(45,10)
+MONSTER: ('a',"fire ant"),(54,02)
+MONSTER: ('a',"fire ant"),(55,07)
+MONSTER: ('a',"fire ant"),(58,14)
+MONSTER: ('a',"fire ant"),(63,17)
+MONSTER: ('H',"fire giant"),(18,01),hostile
+MONSTER: ('H',"fire giant"),(10,16),hostile
 
 #
@@ -88,7 +131,8 @@
 #
 
-MAZE: "Val-loca",' '
-FLAGS: hardfloor
-INIT_MAP: '.' , 'I' , true , true , lit , false
+LEVEL: "Val-loca"
+FLAGS: hardfloor,mazelevel
+INIT_MAP: mines, '.' , 'I' , true , true , lit , false
+MON_GENERATION:86%, (64,"fire ant"), (16,'a'), (16,"fire giant"), (4,'H')
 GEOMETRY:center,center
 MAP
@@ -115,54 +159,23 @@
 NON_DIGGABLE:(00,00,39,12)
 # Objects
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
+LOOP [6 + 3d5] {
+  OBJECT:random,random
+}
 # Random traps
+LOOP [2 + 3d5] {
 TRAP:"fire",random
-TRAP:"fire",random
-TRAP:"fire",random
-TRAP:"fire",random
+}
 TRAP:random,random
 TRAP:random,random
 # Random monsters.
-MONSTER:'a',"fire ant",random
-MONSTER:'a',"fire ant",random
-MONSTER:'a',"fire ant",random
-MONSTER:'a',"fire ant",random
-MONSTER:'a',"fire ant",random
-MONSTER:'a',"fire ant",random
-MONSTER:'a',"fire ant",random
-MONSTER:'a',"fire ant",random
-MONSTER:'a',"fire ant",random
-MONSTER:'a',"fire ant",random
-MONSTER:'a',"fire ant",random
-MONSTER:'a',"fire ant",random
-MONSTER:'a',"fire ant",random
-MONSTER:'a',"fire ant",random
-MONSTER:'a',"fire ant",random
-MONSTER:'a',"fire ant",random
-MONSTER:'a',"fire ant",random
-MONSTER:'a',random,random
-MONSTER:'H',random,random,hostile
-MONSTER:'H',"fire giant",random,hostile
-MONSTER:'H',"fire giant",random,hostile
-MONSTER:'H',"fire giant",random,hostile
-MONSTER:'H',"fire giant",random,hostile
-MONSTER:'H',"fire giant",random,hostile
-MONSTER:'H',"fire giant",random,hostile
-MONSTER:'H',"fire giant",random,hostile
-MONSTER:'H',random,random,hostile
+LOOP [10 + 3d5] {
+  MONSTER:('a',"fire ant"),random
+}
+MONSTER:'a',random
+MONSTER:'H',random,hostile
+LOOP [2 + 3d5] {
+  MONSTER:('H',"fire giant"),random,hostile
+}
+MONSTER:'H',random,hostile
 
 #
@@ -174,14 +187,16 @@
 #
 
-MAZE: "Val-goal", 'L'
-INIT_MAP: '.' , 'L' , true , true , lit , false
+LEVEL: "Val-goal"
+FLAGS:mazelevel
+INIT_MAP: mines, '.' , 'L' , true , true , lit , false
+MON_GENERATION:86%, (64,"fire ant"), (16,'a'), (16,"fire giant"), (4,'H')
 GEOMETRY:center,center
 MAP
-.L............................LLLLL
-LLL.........LLLLL.LLLLL.........LLL
-.LLL......LLLLLLLLLLLLLLL.......LL.
-.LLL.....LLL|---------|LLL.....L...
-..LL....LL|--.........--|LL.....LLL
-.......LL|-...LLLLLLL...-|LL.....L.
+xLxxxx......................xxLLLLL
+LLLx........LLLLL.LLLLL.......xxLLL
+xLLL......LLLLLLLLLLLLLLL......xLLx
+xLLL.....LLL|---------|LLL.....Lxxx
+xxLL....LL|--.........--|LL.....LLL
+x......LL|-...LLLLLLL...-|LL.....Lx
 .......LL|...LL.....LL...|LL.......
 ......LL|-..LL.......LL..-|LL......
@@ -189,10 +204,10 @@
 ......LL|-..LL.......LL..-|LL......
 .......LL|...LL.....LL...|LL.......
-.......LL|-...LLLLLLL...-|LL.......
-..L.....LL|--.........--|LL.....LL.
-..LL.....LLL|---------|LLL....LLLL.
-..LLL.....LLLLLLLLLLLLLLL...LLLLL..
-.LLLL.......LLLLL.LLLLL.....LLLL...
-..LL...............................
+.......LL|-...LLLLLLL...-|LL......x
+x.L.....LL|--.........--|LL.....LLx
+xxLL.....LLL|---------|LLL....LLLLx
+xxLLL.....LLLLLLLLLLLLLLL...LLLLLxx
+xLLLL.......LLLLL.LLLLL.....LLLLxxx
+xxLLxxx....................xxxxxxxx
 ENDMAP
 # Dungeon Description
@@ -207,51 +222,39 @@
 DRAWBRIDGE:(17,14),north,open
 # Objects
-OBJECT:'(',"crystal ball",(17,08),blessed,5,"The Orb of Fate"
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
+OBJECT:('(',"crystal ball"),(17,08),blessed,5,NAME:"The Orb of Fate"
+LOOP [4 + 3d5] {
+  OBJECT:random,random
+}
 # Traps
 TRAP:"board",(13,08)
 TRAP:"board",(21,08)
 # Random traps
+LOOP [2 + 2d3] {
 TRAP:"fire",random
-TRAP:"fire",random
-TRAP:"fire",random
-TRAP:"fire",random
+}
 TRAP:"board",random
 TRAP:random,random
 TRAP:random,random
 # Random monsters.
-MONSTER:'H',"Lord Surtur",(17,08)
-MONSTER:'a',"fire ant",random
-MONSTER:'a',"fire ant",random
-MONSTER:'a',"fire ant",random
-MONSTER:'a',"fire ant",random
-MONSTER:'a',random,random
-MONSTER:'a',random,random
-MONSTER:'H',"fire giant",(10,06),hostile
-MONSTER:'H',"fire giant",(10,07),hostile
-MONSTER:'H',"fire giant",(10,08),hostile
-MONSTER:'H',"fire giant",(10,09),hostile
-MONSTER:'H',"fire giant",(10,10),hostile
-MONSTER:'H',"fire giant",(24,06),hostile
-MONSTER:'H',"fire giant",(24,07),hostile
-MONSTER:'H',"fire giant",(24,08),hostile
-MONSTER:'H',"fire giant",(24,09),hostile
-MONSTER:'H',"fire giant",(24,10),hostile
-MONSTER:'H',"fire giant",random,hostile
-MONSTER:'H',"fire giant",random,hostile
-MONSTER:'H',random,random,hostile
+MONSTER:('H',"Lord Surtur"),(17,08) {
+  OBJECT:('(', "Bell of Opening"),uncursed
+  OBJECT:'['
+  OBJECT:')'
+  OBJECT:random
+  OBJECT:random
+}
+LOOP [2 + 2d3] {
+  MONSTER:('a',"fire ant"),random
+}
+MONSTER:'a',random
+MONSTER:'a',random
+REGION:(10,6,10,6),lit,"ordinary",filled, true {
+  LOOP [5 + 4d3] {
+    MONSTER:('H',"fire giant"),random,hostile
+  }
+}
+MONSTER:('H',"fire giant"),random,hostile
+MONSTER:('H',"fire giant"),random,hostile
+MONSTER:'H',random,hostile
 
 #
@@ -264,6 +267,8 @@
 #
 
-MAZE: "Val-fila" , 'I'
-INIT_MAP: '.' , 'I' , true , true , lit, false
+LEVEL: "Val-fila"
+FLAGS:mazelevel,noflip
+INIT_MAP: mines, '.' , 'I' , true , true , lit, false
+MON_GENERATION:86%, (64,"fire ant"), (16,'a'), (16,"fire giant"), (4,'H')
 NOMAP
 #
@@ -271,32 +276,22 @@
 STAIR: random, down
 #
-OBJECT: random, random, random
-OBJECT: random, random, random
-OBJECT: random, random, random
-OBJECT: random, random, random
-OBJECT: random, random, random
-OBJECT: random, random, random
-OBJECT: random, random, random
-OBJECT: random, random, random
-OBJECT: random, random, random
+LOOP [5 + 2d3] {
+  OBJECT: random, random
+}
 #
-MONSTER: 'a', "fire ant", random
-MONSTER: 'a', "fire ant", random
-MONSTER: 'a', "fire ant", random
-MONSTER: 'a', "fire ant", random
-MONSTER: 'a', "fire ant", random
-MONSTER: 'a', random, random
-MONSTER: 'H', "fire giant", random, hostile
+LOOP [2 + 2d2] {
+  MONSTER: ('a', "fire ant"), random
+}
+MONSTER: 'a', random
+MONSTER: ('H', "fire giant"), random, hostile
 #
+LOOP [6 + 2d2] {
 TRAP: random, random
-TRAP: random, random
-TRAP: random, random
-TRAP: random, random
-TRAP: random, random
-TRAP: random, random
-TRAP: random, random
+}
 
-MAZE: "Val-filb" , 'L'
-INIT_MAP: '.' , 'L' , true , true , lit, false
+LEVEL: "Val-filb"
+FLAGS:mazelevel,noflip
+INIT_MAP: mines, '.' , 'L' , true , true , lit, false
+MON_GENERATION:86%, (64,"fire ant"), (16,'a'), (16,"fire giant"), (4,'H')
 NOMAP
 #
@@ -304,29 +299,17 @@
 STAIR: random, down
 #
-OBJECT: random, random, random
-OBJECT: random, random, random
-OBJECT: random, random, random
-OBJECT: random, random, random
-OBJECT: random, random, random
-OBJECT: random, random, random
-OBJECT: random, random, random
-OBJECT: random, random, random
-OBJECT: random, random, random
-OBJECT: random, random, random
-OBJECT: random, random, random
+LOOP [8 + 2d2] {
+  OBJECT: random, random
+}
 #
-MONSTER: 'a', "fire ant", random
-MONSTER: 'a', "fire ant", random
-MONSTER: 'a', "fire ant", random
-MONSTER: 'a', random, random
-MONSTER: 'H', "fire giant", random, hostile
-MONSTER: 'H', "fire giant", random, hostile
-MONSTER: 'H', "fire giant", random, hostile
+LOOP [3 + 2d2] {
+  MONSTER: ('a', "fire ant"), random
+  MONSTER[80%]: ('H', "fire giant"), random, hostile
+}
+MONSTER: 'a', random
 #
+LOOP [3 + 3d2] {
 TRAP: "fire", random
-TRAP: "fire", random
-TRAP: "fire", random
-TRAP: "fire", random
-TRAP: "fire", random
+}
 TRAP: random, random
 TRAP: random, random
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/dat/Wizard.des nethack/dat/Wizard.des
--- nh_orig/dat/Wizard.des	2003-12-07 18:39:12.000000000 -0500
+++ nethack/dat/Wizard.des	2010-04-29 10:53:24.170716015 -0400
@@ -8,6 +8,8 @@
 #	and receive your quest assignment.
 #
-MAZE: "Wiz-strt",' '
-FLAGS: noteleport,hardfloor
+LEVEL: "Wiz-strt"
+FLAGS: noteleport,hardfloor,mazelevel
+INIT_MAP:solidfill,' '
+MON_GENERATION:86%, (64,"vampire bat"), (16,'B'), (16,"xorn"), (4,'W')
 GEOMETRY:center,center
 MAP
@@ -17,10 +19,10 @@
 ........CC........-----------.......C.C...C...C....C........................
 .......C.....---------------------...C..C..C..C.............................
-......C..C...------....\....------....C.....C...............................
+......C..C...------.........------....C.....C...............................
 ........C...||....|.........|....||.........................................
 .......C....||....|.........+....||.........................................
 .......C...||---+--.........|....|||........................................
 ......C....||...............|--S--||........................................
-...........||--+--|++----|---|..|.SS..........C......C......................
+...........||--+--|++----|---|..|.||..........C......C......................
 ........C..||.....|..|...|...|--|.||..CC..C.....C..........C................
 .......C...||.....|..|.--|.|.|....||.................C..C...................
@@ -33,4 +35,13 @@
 ......................CCC.C.................................................
 ENDMAP
+
+SPILL:(60,15), '}', west, 20
+SPILL:(69,15), '}', north, 20
+
+# first do cloud everywhere
+REPLACE_TERRAIN:(0,0, 75,19), '.', 'C', 10%
+# then replace clouds inside the tower back to floor
+REPLACE_TERRAIN:(13,5, 33,15), 'C', '.', 100%
+
 # Dungeon Description
 REGION:(00,00,75,19),lit,"ordinary"
@@ -42,4 +53,6 @@
 STAIR:(30,10),down
 # Portal arrival point
+# need to make sure it's clear
+TERRAIN:(63,06),'.'
 BRANCH:(63,06,63,06),(0,0,0,0)
 # Doors
@@ -47,51 +60,98 @@
 DOOR:closed,(16,08)
 DOOR:closed,(28,07)
-DOOR:locked,(34,10)
-DOOR:locked,(35,10)
 DOOR:closed,(15,10)
 DOOR:locked,(19,10)
 DOOR:locked,(20,10)
+
+# Entrance into the tower
+SWITCH [3] {
+  CASE 0:
+    TERRAIN:(20,16),'S'
+    TERRAIN:(20,17),'S'
+    DOOR:locked,(20,16)
+    DOOR:locked,(20,17)
+    BREAK
+  CASE 1:
+    TERRAIN:(32,15),'S'
+    TERRAIN:(32,16),'S'
+    DOOR:locked,(32,15)
+    DOOR:locked,(32,16)
+    BREAK
+  CASE 2:
+  DEFAULT:
+    TERRAIN:(34,10),'S'
+    TERRAIN:(35,10),'S'
+    DOOR:locked,(34,10)
+    DOOR:locked,(35,10)
+    BREAK
+}
+
 # Neferet the Green, the quest leader
-MONSTER:'@',"Neferet the Green",(23,05)
+OBJECT:('\',"throne"),(23,05)
+MONSTER:('@',"Neferet the Green"),(23,05) {
+  OBJECT:'/'
+  OBJECT:'/'
+  OBJECT:'?'
+  OBJECT:'?'
+  OBJECT:'['
+}
 # The treasure of the quest leader
-OBJECT:'(',"chest",(24,05)
+OBJECT:('(',"chest"),(24,05)
 # apprentice guards for the audience chamber
-MONSTER:'@',"apprentice",(30,07)
-MONSTER:'@',"apprentice",(24,06)
-MONSTER:'@',"apprentice",(15,06)
-MONSTER:'@',"apprentice",(15,12)
-MONSTER:'@',"apprentice",(26,11)
-MONSTER:'@',"apprentice",(27,11)
-MONSTER:'@',"apprentice",(19,09)
-MONSTER:'@',"apprentice",(20,09)
+MONSTER:('@',"apprentice"),(30,07) {
+  OBJECT:random
+}
+MONSTER:('@',"apprentice"),(24,06) {
+  OBJECT:random
+  OBJECT:random
+}
+MONSTER:('@',"apprentice"),(15,06) {
+  OBJECT:random
+}
+MONSTER:('@',"apprentice"),(15,12) {
+  OBJECT:random
+}
+MONSTER:('@',"apprentice"),(26,11) {
+  OBJECT:random
+}
+MONSTER:('@',"apprentice"),(27,11) {
+  OBJECT:random
+}
+MONSTER:('@',"apprentice"),(19,09) {
+  OBJECT:random
+  OBJECT[50%]:random
+  OBJECT[25%]:random
+}
+MONSTER:('@',"apprentice"),(20,09) {
+  OBJECT:random
+  OBJECT[50%]:random
+  OBJECT[25%]:random
+}
 # Eels in the pond
-MONSTER:';',"giant eel",(62,14)
-MONSTER:';',"giant eel",(69,15)
-MONSTER:';',"giant eel",(67,17)
+MONSTER:(';',"giant eel"),(62,14)
+MONSTER:(';',"giant eel"),(69,15)
+MONSTER:(';',"giant eel"),(67,17)
 # Non diggable walls
 NON_DIGGABLE:(00,00,75,19)
 # Random traps
+LOOP [3 + 3d3] {
 TRAP:random,random
-TRAP:random,random
-TRAP:random,random
-TRAP:random,random
-TRAP:random,random
-TRAP:random,random
+}
 # Monsters on siege duty.
-MONSTER: 'B',random,(60,09),hostile
-MONSTER: 'W',random,(60,10),hostile
-MONSTER: 'B',random,(60,11),hostile
-MONSTER: 'B',random,(60,12),hostile
-MONSTER: 'i',random,(60,13),hostile
-MONSTER: 'B',random,(61,10),hostile
-MONSTER: 'B',random,(61,11),hostile
-MONSTER: 'B',random,(61,12),hostile
-MONSTER: 'B',random,(35,03),hostile
-MONSTER: 'i',random,(35,17),hostile
-MONSTER: 'B',random,(36,17),hostile
-MONSTER: 'B',random,(34,16),hostile
-MONSTER: 'i',random,(34,17),hostile
-MONSTER: 'W',random,(67,02),hostile
-MONSTER: 'B',random,(10,19),hostile
+MONSTER: 'B',(60,09),hostile
+MONSTER: 'W',(60,10),hostile
+MONSTER: 'B',(60,11),hostile
+MONSTER: 'B',(60,12),hostile
+MONSTER: 'i',(60,13),hostile
+MONSTER: 'B',(61,10),hostile
+MONSTER: 'B',(61,11),hostile
+MONSTER: 'B',(61,12),hostile
+MONSTER: 'B',(35,03),hostile
+MONSTER: 'i',(35,17),hostile
+MONSTER: 'B',(36,17),hostile
+MONSTER: 'B',(34,16),hostile
+MONSTER: 'i',(34,17),hostile
+MONSTER: 'W',(67,02),hostile
+MONSTER: 'B',(10,19),hostile
 
 #
@@ -102,44 +162,63 @@
 #
 
-MAZE: "Wiz-loca",' '
-FLAGS: hardfloor
+LEVEL: "Wiz-loca"
+FLAGS: hardfloor,mazelevel
+INIT_MAP:solidfill,' '
+MON_GENERATION:86%, (64,"vampire bat"), (16,'B'), (16,"xorn"), (4,'W')
 GEOMETRY:center,center
 MAP
-.............        .......................................................
-..............       .............}}}}}}}.}}}}}}}}}}}}}}}}}}}.}}}}}}}.......
-..............      ..............}.................................}.......
-..............      ..............}.---------S---------------------.}.......
-...............     .........C....}.|.............................|.}.......
-...............    ..........C....}.|.---------------------------.|.}.......
-...............    .........CCC.....|.|.........................|.|.........
-................   ....C....CCC...}.|.|.---S-------------------.|.|.}.......
-.......C..C.....  .....C....CCC...}.|.|.|......+.......+......|.|.|.}.......
-.............C..CC.....C....CCC...}.|.|.|......|-------|......|.|.|.}.......
-................   ....C....CCC...}.|.|.|......|.......S......|.|.|.}.......
-......C..C.....    ....C....CCC...}.|.|.|......|-------|......|.|.|.}.......
-............C..     ...C....CCC...}.|.|.|......+.......+......|.|.|.}.......
-........C......    ....C....CCC...}.|.|.-----------------------.|.|.}.......
-....C......C...     ........CCC.....|.|.........................|.|.........
-......C..C....      .........C....}.|.--------------------S------.|.}.......
-..............      .........C....}.|.............................|.}.......
-.............       ..............}.-------------------------------.}.......
-.............        .............}.................................}.......
-.............        .............}}}}}}}.}}}}}}}}}}}}}}}}}}}.}}}}}}}.......
-.............        .......................................................
+.............         ......................................................
+.............         ............}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}.......
+.............         ............}.................................}.......
+.............         ............}.-------------------------------.}.......
+.............         .......C....}.|.............................|.}.......
+.............         .......C....}.|.---------------------------.|.}.......
+.............         ......CCC...}.|.|.........................|.|.}.......
+.............         .C....CCC...}.|.|.-----------------------.|.|.}.......
+.......C..C..         .C....CCC...}.|.|.|......+.......+......|.|.|.}.......
+.............         .C....CCC...}.|.|.|......|-------|......|.|.|.}.......
+.............        C.C....CCC...}.|.|.|......|.......|......|.|.|.}.......
+......C..C...         .C....CCC...}.|.|.|......|-------|......|.|.|.}.......
+............C         .C....CCC...}.|.|.|......+.......+......|.|.|.}.......
+........C....         .C....CCC...}.|.|.-----------------------.|.|.}.......
+....C......C.         ......CCC...}.|.|.........................|.|.}.......
+......C..C...         .......C....}.|.---------------------------.|.}.......
+.............         .......C....}.|.............................|.}.......
+.............         ............}.-------------------------------.}.......
+.............         ............}.................................}.......
+.............         ............}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}.......
+.............         ......................................................
 ENDMAP
+
+REPLACE_TERRAIN:(0,0,30,20), '.', 'C', 15%
+REPLACE_TERRAIN:(68,0,75,20), '.', '}', 25%
+
+REPLACE_TERRAIN:(34,1,68,19), '}', '.', 2%
+
+# Fog Maze, with occasional broken walls.
+MAZEWALK:(12,10),east,false,'C'
+REPLACE_TERRAIN:(13,0,21,20), ' ', 'C', 4%
+
 # Dungeon Description
 REGION:(00,00,75,20),lit,"ordinary"
-REGION:(37,04,65,16),unlit,"ordinary"
-REGION:(41,08,46,12),lit,"ordinary"
-REGION:(56,08,61,12),lit,"ordinary"
+REGION:(37,04,65,16),unlit,"ordinary",filled,true {
+  ROOMDOOR:true,closed,north|south|west|east,random
+}
+REGION:(39,06,63,14),unlit,"ordinary",filled,true {
+  ROOMDOOR:true,closed,north|south|west|east,random
+}
+REGION:(41,08,46,12),lit,"ordinary",filled,true {
+  ROOMDOOR:true,closed,north|south|west,random
+}
+REGION:(56,08,61,12),lit,"ordinary",filled,true {
+  ROOMDOOR:true,closed,north|south|east,random
+}
 REGION:(48,08,54,08),unlit,"ordinary"
 REGION:(48,12,54,12),unlit,"ordinary"
-REGION:(48,10,54,10),unlit,"ordinary"
+REGION:(48,10,54,10),unlit,"ordinary",filled,true {
+  ROOMDOOR:true,closed,north|south|west|east,random
+}
 
 # Doors
-DOOR:locked,(45,03)
-DOOR:locked,(43,07)
-DOOR:locked,(58,15)
-DOOR:locked,(55,10)
 DOOR:locked,(55,08)
 DOOR:locked,(55,12)
@@ -148,23 +227,11 @@
 # Stairs
 STAIR:(03,17),up
-STAIR:(48,10),down
+STAIR:(51,10),down
 # Non diggable walls
 NON_DIGGABLE:(00,00,75,20)
 # Objects
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
+LOOP [10 + 1d6] {
+  OBJECT:random,random
+}
 # Random traps
 TRAP:"spiked pit",(24,02)
@@ -190,31 +257,9 @@
 TRAP:"dart",random
 # Random monsters.
-MONSTER:'B',random,random,hostile
-MONSTER:'B',random,random,hostile
-MONSTER:'B',random,random,hostile
-MONSTER:'B',random,random,hostile
-MONSTER:'B',random,random,hostile
-MONSTER:'B',random,random,hostile
-MONSTER:'B',random,random,hostile
-MONSTER:'B',random,random,hostile
-MONSTER:'B',random,random,hostile
-MONSTER:'B',random,random,hostile
-MONSTER:'B',random,random,hostile
-MONSTER:'B',random,random,hostile
-MONSTER:'i',random,random,hostile
-MONSTER:'i',random,random,hostile
-MONSTER:'i',random,random,hostile
-MONSTER:'i',random,random,hostile
-MONSTER:'i',random,random,hostile
-MONSTER:'i',random,random,hostile
-MONSTER:'i',random,random,hostile
-MONSTER:'B',"vampire bat",random
-MONSTER:'B',"vampire bat",random
-MONSTER:'B',"vampire bat",random
-MONSTER:'B',"vampire bat",random
-MONSTER:'B',"vampire bat",random
-MONSTER:'B',"vampire bat",random
-MONSTER:'B',"vampire bat",random
-MONSTER:'i',random,random,hostile
+LOOP [10 + 1d10] {
+  MONSTER:'B',random,hostile
+  MONSTER[80%]:'i',random,hostile
+  MONSTER[90%]:('B',"vampire bat"),random
+}
 
 #
@@ -226,5 +271,8 @@
 #
 
-MAZE: "Wiz-goal", ' '
+LEVEL: "Wiz-goal"
+FLAGS:mazelevel
+INIT_MAP:solidfill,' '
+MON_GENERATION:86%, (64,"vampire bat"), (16,'B'), (16,"xorn"), (4,'W')
 GEOMETRY:center,center
 MAP
@@ -232,7 +280,7 @@
                                                                             
                                                                             
-                   -------------                 -------------              
-                   |...........|                 |...........|              
-            -------|...........-------------------...........|              
+            --------------------                 -------------              
+            |......|...........|                 |...........|              
+            ---S---|...........-------------------...........|              
             |......S...........|..|..|..|..|..|..|...........|              
             |......|...........|..|..|..|..|..|..|...........|              
@@ -242,7 +290,7 @@
             |......|...........|..|..|..|..|..|..|...........|              
             |......|...........|..|..|..|..|..|..|...........|              
-            -------|...........-------------------...........|              
-                   |...........|                 |...........|              
-                   -------------                 -------------              
+            ----S--|...........-------------------...........|              
+            |......|...........|                 |...........|              
+            --------------------                 -------------              
                                                                             
                                                                             
@@ -268,4 +316,6 @@
 REGION:(47,11,48,12),unlit,"ordinary"
 REGION:(50,04,60,14),lit,"ordinary"
+REGION:(13,04,18,04),lit,"ordinary"
+REGION:(13,14,18,14),lit,"ordinary"
 # Doors
 DOOR:locked,(19,06)
@@ -285,4 +335,6 @@
 DOOR:locked,(48,10)
 DOOR:locked,(49,09)
+DOOR:locked,(16,13)
+DOOR:locked,(15,05)
 # Stairs
 STAIR:(55,05),up
@@ -292,64 +344,40 @@
 ALTAR:(16,11),noncoaligned,altar
 # Objects
-OBJECT:'"',"amulet of ESP",(16,11),blessed,0,"The Eye of the Aethiopica"
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
-OBJECT:random,random,random
+OBJECT:('"',"amulet of power"),(16,11),blessed,0,NAME:"The Eye of the Aethiopica"
+LOOP [9 + 2d5] {
+  OBJECT:random,random
+}
+OBJECT:('+',"knock"),(13,14)
+OBJECT:'+',(18,14)
+OBJECT:'+',(13,04)
+OBJECT:('+',"wizard lock"),(18,04)
 # Random traps
+LOOP [2 + 2d8] {
 TRAP:random,random
-TRAP:random,random
-TRAP:random,random
-TRAP:random,random
-TRAP:random,random
-TRAP:random,random
+}
+TRAP:random,(16,14)
+TRAP:random,(15,04)
 # Random monsters.
-MONSTER:'@',"Dark One",(16,11)
-MONSTER:'B',random,random,hostile
-MONSTER:'B',random,random,hostile
-MONSTER:'B',random,random,hostile
-MONSTER:'B',random,random,hostile
-MONSTER:'B',random,random,hostile
-MONSTER:'B',random,random,hostile
-MONSTER:'B',random,random,hostile
-MONSTER:'B',random,random,hostile
-MONSTER:'B',random,random,hostile
-MONSTER:'B',random,random,hostile
-MONSTER:'B',random,random,hostile
-MONSTER:'i',random,random,hostile
-MONSTER:'i',random,random,hostile
-MONSTER:'i',random,random,hostile
-MONSTER:'i',random,random,hostile
-MONSTER:'i',random,random,hostile
-MONSTER:'i',random,random,hostile
-MONSTER:'i',random,random,hostile
-MONSTER:'B',"vampire bat",random
-MONSTER:'B',"vampire bat",random
-MONSTER:'B',"vampire bat",random
-MONSTER:'B',"vampire bat",random
-MONSTER:'B',"vampire bat",random
-MONSTER:'B',"vampire bat",random
-MONSTER:'B',"vampire bat",random
-MONSTER:'B',"vampire bat",random
-MONSTER:'i',random,random,hostile
+MONSTER:('@',"Dark One"),(16,11) {
+  OBJECT:('(', "Bell of Opening"),uncursed
+  OBJECT:'/'
+  OBJECT:'?'
+  OBJECT:'+'
+  OBJECT:'['
+}
+LOOP [8 + 3d8] {
+  MONSTER:'B',random,hostile
+  MONSTER:'i',random,hostile
+  MONSTER:('B',"vampire bat"),random
+}
 # Captive Monsters in the dungeon
-MONSTER:'@',"rogue",(35,06),peaceful,"Pug"
-MONSTER:'Y',"owlbear",(47,06),peaceful,asleep
-MONSTER:'@',"wizard",(32,11),peaceful,asleep,"Newt"
-MONSTER:'@',"Grey-elf",(44,11),peaceful
-MONSTER:'H',"hill giant",(47,11),peaceful,asleep
-MONSTER:'G',"gnomish wizard",(38,06),peaceful
-MONSTER:'@',"prisoner",(35,11),peaceful
-MONSTER:'@',"prisoner",(41,11),peaceful,asleep
+MONSTER:('@',"rogue"),(35,06),peaceful,"Pug"
+MONSTER:('Y',"owlbear"),(47,06),peaceful,asleep
+MONSTER:('@',"wizard"),(32,11),peaceful,asleep,"Newt"
+MONSTER:('@',"Grey-elf"),(44,11),peaceful
+MONSTER:('H',"hill giant"),(47,11),peaceful,asleep
+MONSTER:('G',"gnomish wizard"),(38,06),peaceful
+MONSTER:('@',"prisoner"),(35,11),peaceful
+MONSTER:('@',"prisoner"),(41,11),peaceful,asleep
 
 #
@@ -363,77 +391,103 @@
 
 LEVEL: "Wiz-fila"
+MON_GENERATION:86%, (64,"vampire bat"), (16,'B'), (16,"xorn"), (4,'W')
 #
 ROOM: "ordinary" , random, random, random, random
+{
 STAIR: random, up
-OBJECT: random,random,random
-MONSTER: 'i', random, random, hostile
+OBJECT: random,random
+MONSTER: 'i', random, hostile
+}
 
 ROOM: "ordinary" , random, random, random, random
-OBJECT: random, random, random
-OBJECT: random,random,random
-MONSTER: 'i', random, random, hostile
+{
+OBJECT: random, random
+OBJECT: random,random
+MONSTER: 'i', random, hostile
+}
 
 ROOM: "ordinary" , random, random, random, random
-OBJECT: random, random, random
+{
+OBJECT: random, random
 TRAP: random, random
-OBJECT: random,random,random
-MONSTER: 'B', "vampire bat", random
-MONSTER: 'B', "vampire bat", random
+OBJECT: random,random
+MONSTER: ('B', "vampire bat"), random
+MONSTER: ('B', "vampire bat"), random
+}
 
 ROOM: "ordinary" , random, random, random, random
+{
 STAIR: random, down
-OBJECT: random, random, random
+OBJECT: random, random
 TRAP: random, random
-MONSTER: 'i', random, random, hostile
-MONSTER: 'B', "vampire bat", random
+MONSTER: 'i', random, hostile
+MONSTER: ('B', "vampire bat"), random
+}
 
 ROOM: "ordinary" , random, random, random, random
-OBJECT: random, random, random
-OBJECT: random, random, random
+{
+OBJECT: random, random
+OBJECT: random, random
 TRAP: random, random
-MONSTER: 'i', random, random, hostile
+MONSTER: 'i', random, hostile
+}
 
 ROOM: "ordinary" , random, random, random, random
-OBJECT: random, random, random
+{
+OBJECT: random, random
 TRAP: random, random
-MONSTER: 'B', "vampire bat", random
+MONSTER: ('B', "vampire bat"), random
+}
 
 RANDOM_CORRIDORS
 
 LEVEL: "Wiz-filb"
+MON_GENERATION:86%, (64,"vampire bat"), (16,'B'), (16,"xorn"), (4,'W')
 #
 ROOM: "ordinary" , random, random, random, random
+{
 STAIR: random, up
-OBJECT: random,random,random
-MONSTER: 'X', random, random, hostile
+OBJECT: random,random
+MONSTER: 'X', random, hostile
+}
 
 ROOM: "ordinary" , random, random, random, random
-OBJECT: random, random, random
-OBJECT: random,random,random
-MONSTER: 'i', random, random, hostile
+{
+OBJECT: random, random
+OBJECT: random,random
+MONSTER: 'i', random, hostile
+}
 
 ROOM: "ordinary" , random, random, random, random
-OBJECT: random, random, random
+{
+OBJECT: random, random
 TRAP: random, random
-OBJECT: random,random,random
-MONSTER: 'X', random, random, hostile
+OBJECT: random,random
+MONSTER: 'X', random, hostile
+}
 
 ROOM: "ordinary" , random, random, random, random
+{
 STAIR: random, down
-OBJECT: random, random, random
+OBJECT: random, random
 TRAP: random, random
-MONSTER: 'i', random, random, hostile
-MONSTER: 'B', "vampire bat", random
+MONSTER: 'i', random, hostile
+MONSTER: ('B', "vampire bat"), random
+}
 
 ROOM: "ordinary" , random, random, random, random
-OBJECT: random, random, random
-OBJECT: random, random, random
+{
+OBJECT: random, random
+OBJECT: random, random
 TRAP: random, random
-MONSTER: 'i', random, random, hostile
+MONSTER: 'i', random, hostile
+}
 
 ROOM: "ordinary" , random, random, random, random
-OBJECT: random, random, random
+{
+OBJECT: random, random
 TRAP: random, random
-MONSTER: 'B', "vampire bat", random
+MONSTER: ('B', "vampire bat"), random
+}
 
 RANDOM_CORRIDORS
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/dat/yendor.des nethack/dat/yendor.des
--- nh_orig/dat/yendor.des	2003-12-07 18:39:13.000000000 -0500
+++ nethack/dat/yendor.des	2010-04-11 12:36:58.301624882 -0400
@@ -6,6 +6,7 @@
 # The top (real) wizard level.
 # Keeping the Moat for old-time's sake
-MAZE:"wizard1",random
-FLAGS:noteleport,hardfloor
+LEVEL:"wizard1"
+FLAGS:noteleport,hardfloor,mazelevel
+INIT_MAP:mazegrid,'-'
 GEOMETRY:center,center
 MAP
@@ -28,7 +29,8 @@
 BRANCH:levregion(01,00,79,20),(0,0,28,12)
 TELEPORT_REGION:levregion(01,00,79,20),(0,0,27,12)
-# Make it a morgue for rm id in mkmaze.c
-# for the purpose of random sdoor placement
-REGION:(12,01,20,09),unlit,"morgue",unfilled
+
+REGION:(12,01,20,09),unlit,"morgue",unfilled {
+  ROOMDOOR:true, locked, south|east|west, random
+}
 MAZEWALK:(28,05),east
 LADDER:(06,05),down
@@ -45,27 +47,27 @@
 NON_PASSWALL:(21,00,27,10)
 # The wizard and his guards
-MONSTER:'@',"Wizard of Yendor",(16,05),asleep
-MONSTER:'d',"hell hound",(15,05)
-MONSTER:'V',"vampire lord",(17,05)
+MONSTER:('@',"Wizard of Yendor"),(16,05),asleep
+MONSTER:('d',"hell hound"),(15,05)
+MONSTER:('V',"vampire lord"),(17,05)
 # The local treasure
-OBJECT:'+',"Book of the Dead",(16,05)
+OBJECT:('+',"Book of the Dead"),(16,05)
 # Surrounding terror
-MONSTER:';',"kraken",(14,02)
-MONSTER:';',"giant eel",(17,02)
-MONSTER:';',"kraken",(13,04)
-MONSTER:';',"giant eel",(13,06)
-MONSTER:';',"kraken",(19,04)
-MONSTER:';',"giant eel",(19,06)
-MONSTER:';',"kraken",(15,08)
-MONSTER:';',"giant eel",(17,08)
-MONSTER:';',"piranha",(15,02)
-MONSTER:';',"piranha",(19,08)
+MONSTER:(';',"kraken"),(14,02)
+MONSTER:(';',"giant eel"),(17,02)
+MONSTER:(';',"kraken"),(13,04)
+MONSTER:(';',"giant eel"),(13,06)
+MONSTER:(';',"kraken"),(19,04)
+MONSTER:(';',"giant eel"),(19,06)
+MONSTER:(';',"kraken"),(15,08)
+MONSTER:(';',"giant eel"),(17,08)
+MONSTER:(';',"piranha"),(15,02)
+MONSTER:(';',"piranha"),(19,08)
 # Random monsters
-MONSTER:'D',random,random
-MONSTER:'H',random,random
-MONSTER:'&',random,random
-MONSTER:'&',random,random
-MONSTER:'&',random,random
-MONSTER:'&',random,random
+MONSTER:'D',random
+MONSTER:'H',random
+MONSTER:'&',random
+MONSTER:'&',random
+MONSTER:'&',random
+MONSTER:'&',random
 # And to make things a little harder.
 TRAP:"board",(16,04)
@@ -79,17 +81,18 @@
 TRAP:"magic",random
 # Some random loot.
-OBJECT:'*',"ruby",random
-OBJECT:'!',random,random
-OBJECT:'!',random,random
-OBJECT:'?',random,random
-OBJECT:'?',random,random
-OBJECT:'+',random,random
-OBJECT:'+',random,random
-OBJECT:'+',random,random
+OBJECT:('*',"ruby"),random
+OBJECT:'!',random
+OBJECT:'!',random
+OBJECT:'?',random
+OBJECT:'?',random
+OBJECT:'+',random
+OBJECT:'+',random
+OBJECT:'+',random
 
 
 # The middle wizard level.
-MAZE:"wizard2",random
-FLAGS:noteleport,hardfloor
+LEVEL:"wizard2"
+FLAGS:noteleport,hardfloor,mazelevel
+INIT_MAP:mazegrid,'-'
 GEOMETRY:center,center
 MAP
@@ -131,17 +134,18 @@
 TRAP:"magic",random
 # Some random loot.
-OBJECT:'!',random,random
-OBJECT:'!',random,random
-OBJECT:'?',random,random
-OBJECT:'?',random,random
-OBJECT:'+',random,random
+OBJECT:'!',random
+OBJECT:'!',random
+OBJECT:'?',random
+OBJECT:'?',random
+OBJECT:'+',random
 # treasures
-OBJECT:'"',random,(04,06)
+OBJECT:'"',(04,06)
 
 
 # The bottom wizard level.
 # Memorialize the fakewiz setup.
-MAZE:"wizard3",random
-FLAGS:noteleport,hardfloor
+LEVEL:"wizard3"
+FLAGS:noteleport,hardfloor,mazelevel
+INIT_MAP:mazegrid,'-'
 GEOMETRY:center,center
 MAP
@@ -157,5 +161,5 @@
 |.....|.}}---}}.|..|.......|.
 |.....S.}}}}}}}.|..|.......|.
-|.....|.........|..S.......|.
+|.....|.........|..|.......|.
 ----------------------------.
 ENDMAP
@@ -170,7 +174,8 @@
 # make the entry chamber a real room; it affects monster arrival;
 # `unfilled' is a kludge to force an ordinary room to remain a room
-REGION:(20,06,26,11),unlit,"ordinary",unfilled
+REGION:(20,06,26,11),unlit,"ordinary",unfilled {
+  ROOMDOOR:true, locked, north|west, random
+}
 DOOR:closed,(18,05)
-DOOR:closed,(19,11)
 LADDER:(11,07),up
 # Non diggable walls
@@ -186,18 +191,18 @@
 NON_PASSWALL:(06,12,16,12)
 #
-MONSTER:'L',random,(10,07)
-MONSTER:'V',"vampire lord",(12,07)
+MONSTER:'L',(10,07)
+MONSTER:('V',"vampire lord"),(12,07)
 # Some surrounding horrors
-MONSTER:';',"kraken",(08,05)
-MONSTER:';',"giant eel",(08,08)
-MONSTER:';',"kraken",(14,05)
-MONSTER:';',"giant eel",(14,08)
+MONSTER:(';',"kraken"),(08,05)
+MONSTER:(';',"giant eel"),(08,08)
+MONSTER:(';',"kraken"),(14,05)
+MONSTER:(';',"giant eel"),(14,08)
 # Other monsters
-MONSTER:'L',random,random
-MONSTER:'D',random,random
-MONSTER:'D',random,(26,09)
-MONSTER:'&',random,random
-MONSTER:'&',random,random
-MONSTER:'&',random,random
+MONSTER:'L',random
+MONSTER:'D',random
+MONSTER:'D',(26,09)
+MONSTER:'&',random
+MONSTER:'&',random
+MONSTER:'&',random
 # And to make things a little harder.
 TRAP:"board",(10,07)
@@ -206,11 +211,11 @@
 TRAP:"board",(11,08)
 # Some loot
-OBJECT:')',random,random
-OBJECT:'!',random,random
-OBJECT:'?',random,random
-OBJECT:'?',random,random
-OBJECT:'(',random,random
+OBJECT:')',random
+OBJECT:'!',random
+OBJECT:'?',random
+OBJECT:'?',random
+OBJECT:'(',random
 # treasures
-OBJECT:'"',random,(11,07)
+OBJECT:'"',(11,07)
 
 
@@ -218,5 +223,7 @@
 # There are two of these, and we need to
 # distinguish between them for the portal.
-MAZE:"fakewiz1",random
+LEVEL:"fakewiz1"
+FLAGS:mazelevel
+INIT_MAP:mazegrid,'-'
 GEOMETRY:center,center
 MAP
@@ -237,7 +244,7 @@
 MAZEWALK:(08,05),east
 REGION:(04,03,06,06),unlit,"ordinary",unfilled,true
-MONSTER:'L',random,(04,04)
-MONSTER:'V',"vampire lord",(03,04)
-MONSTER:';',"kraken",(06,06)
+MONSTER:'L',(04,04)
+MONSTER:('V',"vampire lord"),(03,04)
+MONSTER:(';',"kraken"),(06,06)
 # And to make things a little harder.
 TRAP:"board",(04,03)
@@ -247,5 +254,7 @@
 
 
-MAZE:"fakewiz2",random
+LEVEL:"fakewiz2"
+FLAGS:mazelevel
+INIT_MAP:mazegrid,'-'
 GEOMETRY:center,center
 MAP
@@ -265,7 +274,7 @@
 MAZEWALK:(08,05),east
 REGION:(04,03,06,06),unlit,"ordinary",unfilled,true
-MONSTER:'L',random,(04,04)
-MONSTER:'V',"vampire lord",(03,04)
-MONSTER:';',"kraken",(06,06)
+MONSTER:'L',(04,04)
+MONSTER:('V',"vampire lord"),(03,04)
+MONSTER:(';',"kraken"),(06,06)
 # And to make things a little harder.
 TRAP:"board",(04,03)
@@ -274,3 +283,3 @@
 TRAP:"board",(05,04)
 # treasures
-OBJECT:'"',random,(04,04)
+OBJECT:'"',(04,04)
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/doc/Guidebook.mn nethack/doc/Guidebook.mn
--- nh_orig/doc/Guidebook.mn	2003-12-07 18:39:13.000000000 -0500
+++ nethack/doc/Guidebook.mn	2009-08-02 13:49:34.150409063 -0400
@@ -1771,4 +1771,10 @@
 Name your starting dog (ex. ``dogname:Fang'').
 Cannot be set with the `O' command.
+.lp dumpfile
+The name of a file where the disclosure information is written when the
+game ends. You may use the macro %n that will be replaced with the name
+of your player character. The game must have write permissions to the
+directory where the file is written. Normally /tmp may be used for unix
+systems.
 .lp dungeon
 Set the graphics symbols for displaying the dungeon
@@ -2099,4 +2105,16 @@
 .lp "silent  "
 Suppress terminal beeps (default on).
+.lp sortloot
+Controls the behavior of the sortloot patch that sorts pickup lists for
+inventory and #loot commands and some others.
+The possible values are:
+.sd
+.si
+full - always sort the lists;
+loot - only sort the lists that don't use inventory
+       letters, like with the #loot and pickup commands;
+none - show lists the traditional way without sorting.
+.ei
+.ed
 .lp sortpack
 Sort the pack contents by type when displaying inventory (default on).
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/doc/Guidebook.tex nethack/doc/Guidebook.tex
--- nh_orig/doc/Guidebook.tex	2003-12-07 18:39:13.000000000 -0500
+++ nethack/doc/Guidebook.tex	2009-08-02 13:49:34.160408550 -0400
@@ -2210,4 +2210,11 @@
 Cannot be set with the `{\tt O}' command.
 %.lp
+\item[\ib{dumpfile}]
+The name of a file where the disclosure information is written when the
+game ends. You may use the macro %n that will be replaced with the name
+of your player character. The game must have write permissions to the
+directory where the file is written. Normally /tmp may be used for unix
+systems.
+%.lp
 \item[\ib{dungeon}]
 Set the graphics symbols for displaying the dungeon (default
@@ -2574,4 +2581,19 @@
 Suppress terminal beeps (default on).
 %.lp
+\item[\ib{sortloot}]
+Controls the behavior of the sortloot patch that sorts pickup lists for
+inventory and \#loot commands and some others.
+
+The possible values are:
+%.sd
+%.si
+{\tt full} --- always sort the lists;\\
+{\tt loot} --- only sort the lists that don't use inventory
+       letters, like with the \#loot and pickup commands;\\
+{\tt none} --- show lists the traditional way without sorting.
+%.ei
+%.ed
+%.lp
+The default is 'none', the way an unpatched game works.
 \item[\ib{sortpack}]
 Sort the pack contents by type when displaying inventory (default on).
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/doc/Guidebook.txt nethack/doc/Guidebook.txt
--- nh_orig/doc/Guidebook.txt	2003-12-07 18:39:13.000000000 -0500
+++ nethack/doc/Guidebook.txt	2009-08-02 13:49:34.157408524 -0400
@@ -2275,4 +2275,11 @@
             with the `O' command.
 
+          dumpfile
+            The name of a file where the disclosure information is
+            written when the game ends. You may use the macro %n that
+            will be replaced with the name of your player character.
+            The game must have write permissions to the directory where
+            the file is written. Normally /tmp may be used for unixes.
+
           dungeon
             Set the graphics symbols for displaying  the  dungeon  (default
@@ -2724,4 +2731,16 @@
             Suppress terminal beeps (default on).
 
+          sortloot
+               Controls the behavior of the sortloot patch that sorts
+               pickup lists for inventory and #loot commands and some
+               others.
+               The possible values are:
+
+                    full - always sort the lists
+                    loot - only sort the lists that don't use inventory
+                           letters, like with the #loot and pickup commands
+                    none - show lists the traditional way without sorting
+               The default is 'none', the way an unpatched game works.
+
           sortpack
             Sort the pack contents by type when displaying  inventory  (de-
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/include/align.h nethack/include/align.h
--- nh_orig/include/align.h	2003-12-07 18:39:13.000000000 -0500
+++ nethack/include/align.h	2009-08-02 13:49:33.026408602 -0400
@@ -13,6 +13,8 @@
 } align;
 
-/* bounds for "record" -- respect initial alignments of 10 */
-#define ALIGNLIM	(10L + (moves/200L))
+/* bounds for "record" -- respect initial alignments of 10.
+ * note that the maximum alignment is now 50, so that mortal
+ * sins always put you out of favor with your god. */
+#define ALIGNLIM	(min(50,10L + (moves/300L)))
 
 #define A_NONE	      (-128)	/* the value range of type */
@@ -40,3 +42,13 @@
 			 : ((x) == A_LAWFUL) ? AM_LAWFUL : (x) + 2)
 
+/*
+ * These will make it a bit easier to adjust alignment swings
+ * while trying to get it balanced out to where it matters...
+ */
+
+#define venial_sin() (adjalign(-5))
+#define minor_sin() (adjalign(-10))
+#define major_sin() (adjalign(-20))
+#define mortal_sin() (adjalign(-50))
+
 #endif /* ALIGN_H */
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/include/artifact.h nethack/include/artifact.h
--- nh_orig/include/artifact.h	2003-12-07 18:39:13.000000000 -0500
+++ nethack/include/artifact.h	2009-08-02 13:49:33.036408503 -0400
@@ -35,5 +35,23 @@
 #define SPFX_XRAY   0x2000000L	/* gives X-RAY vision to player */
 #define SPFX_REFLECT 0x4000000L /* Reflection */
+#define SPFX_STR	  0x8000000L   /* item bestows STR 18(**) */
+#define SPFX_CON	  0x10000000L   /* item bestows CON 25 */
+#define SPFX_POLYC  0x20000000L	 /* items grants polymorph control */
 
+#define SPDF_NONE		  0x00000000L /* No special effects */
+#define SPDF_MAGIC	  0x00000001L /* Magic resistance */
+#define SPDF_FIRE		  0x00000002L /* Fire defense */
+#define SPDF_COLD		  0x00000004L /* Cold defense */
+#define SPDF_SLEEP	  0x00000008L /* Sleep defense */
+#define SPDF_DISINT	  0x00000010L /* Disintegration defense */
+#define SPDF_ELEC		  0x00000020L /* Shock defense */
+#define SPDF_POISON	  0x00000040L /* Poison defense */
+#define SPDF_ACID		  0x00000080L /* Acid defense */
+#define SPDF_BLIND	  0x00000100L /* Blinding resistance */
+#define SPDF_WERE		  0x00000200L /* Lycanthropy resistance */
+#define SPDF_DRAIN	  0x00000400L /* Drain level defense */
+#define SPDF_CONFUSE	  0x00000800L /* Confusion */
+#define SPDF_STUN		  0x00001000L /* Stunning */
+#define SPDF_ELEMENTAL 0x000000FEL	/* All elemental resistances (Dragonbane) */
 
 struct artifact {
@@ -43,5 +61,7 @@
 	unsigned long cspfx;	/* special effect just from carrying obj */
 	unsigned long mtype;	/* monster type, symbol, or flag */
-	struct attack attk, defn, cary;
+	struct attack attk;
+	unsigned long defn;	/* special defensive properties from wielding/wearing */
+	struct attack cary;
 	uchar	    inv_prop;	/* property obtained by invoking artifact */
 	aligntyp    alignment;	/* alignment of bequeathing gods */
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/include/artilist.h nethack/include/artilist.h
--- nh_orig/include/artilist.h	2003-12-07 18:39:13.000000000 -0500
+++ nethack/include/artilist.h	2009-10-31 10:32:37.579669351 -0400
@@ -16,5 +16,4 @@
 
 #define     NO_ATTK	{0,0,0,0}		/* no attack */
-#define     NO_DFNS	{0,0,0,0}		/* no defense */
 #define     NO_CARY	{0,0,0,0}		/* no carry effects */
 #define     DFNS(c)	{0,c,0,0}
@@ -26,4 +25,5 @@
 #define     ELEC(a,b)	{0,AD_ELEC,a,b}		/* electrical shock */
 #define     STUN(a,b)	{0,AD_STUN,a,b}		/* magical attack */
+#define		DRST(a,b)	{0,AD_DRST,a,b}		/* poison attack */
 
 STATIC_OVL NEARDATA struct artifact artilist[] = {
@@ -39,9 +39,16 @@
 /*  dummy element #0, so that all interesting indices are non-zero */
 A("",				STRANGE_OBJECT,
-	0, 0, 0, NO_ATTK, NO_DFNS, NO_CARY, 0, A_NONE, NON_PM, NON_PM, 0L ),
+	0, 0, 0, NO_ATTK, SPDF_NONE, NO_CARY, 0, A_NONE, NON_PM, NON_PM, 0L ),
 
 A("Excalibur",			LONG_SWORD,
 	(SPFX_NOGEN|SPFX_RESTR|SPFX_SEEK|SPFX_DEFN|SPFX_INTEL|SPFX_SEARCH),0,0,
-	PHYS(5,10),	DRLI(0,0),	NO_CARY,	0, A_LAWFUL, PM_KNIGHT, NON_PM, 4000L ),
+	PHYS(5,10),	SPDF_DRAIN,	NO_CARY,	0, A_LAWFUL, PM_KNIGHT, NON_PM, 4000L ),
+/* 
+ * The Knight needed a chaotic longsword to obtain, since Excalibur
+ * will be restricted from him... 
+*/
+A("Dirge",			LONG_SWORD,
+	(SPFX_ATTK|SPFX_NOGEN|SPFX_RESTR|SPFX_DEFN|SPFX_INTEL),0,0,
+	DRST(5,0),	SPDF_DRAIN,	NO_CARY,	0, A_CHAOTIC, NON_PM, NON_PM, 3000L ),
 /*
  *	Stormbringer only has a 2 because it can drain a level,
@@ -50,5 +57,13 @@
 A("Stormbringer",		RUNESWORD,
 	(SPFX_RESTR|SPFX_ATTK|SPFX_DEFN|SPFX_INTEL|SPFX_DRLI), 0, 0,
-	DRLI(5,2),	DRLI(0,0),	NO_CARY,	0, A_CHAOTIC, NON_PM, NON_PM, 8000L ),
+	DRLI(5,2),	SPDF_DRAIN,	NO_CARY,	0, A_CHAOTIC, NON_PM, NON_PM, 8000L ),
+/*
+ * Lifestealer gets the same restrictions as Stormy, but it's designed
+ * to be generated in Vlad's hands anyway, so this isn't such a big deal.
+ * It's two-handed so players (hopefully) won't really want to use it...
+ */
+A("Lifestealer",		TWO_HANDED_SWORD,
+	(SPFX_NOGEN|SPFX_RESTR|SPFX_ATTK|SPFX_DEFN|SPFX_INTEL|SPFX_DRLI), 0, 0,
+	DRLI(5,2),	SPDF_DRAIN,	NO_CARY,	0, A_CHAOTIC, NON_PM, NON_PM, 8000L ),
 /*
  *	Mjollnir will return to the hand of the wielder when thrown
@@ -57,29 +72,27 @@
 A("Mjollnir",			WAR_HAMMER,		/* Mjo:llnir */
 	(SPFX_RESTR|SPFX_ATTK),  0, 0,
-	ELEC(5,24),	NO_DFNS,	NO_CARY,	0, A_NEUTRAL, PM_VALKYRIE, NON_PM, 4000L ),
+	ELEC(5,24),	SPDF_NONE,	NO_CARY,	0, A_NEUTRAL, PM_VALKYRIE, NON_PM, 4000L ),
 
 A("Cleaver",			BATTLE_AXE,
 	SPFX_RESTR, 0, 0,
-	PHYS(3,6),	NO_DFNS,	NO_CARY,	0, A_NEUTRAL, PM_BARBARIAN, NON_PM, 1500L ),
+	PHYS(3,6),	SPDF_NONE,	NO_CARY,	0, A_NEUTRAL, PM_BARBARIAN, NON_PM, 1500L ),
 
 A("Grimtooth",			ORCISH_DAGGER,
 	SPFX_RESTR, 0, 0,
-	PHYS(2,6),	NO_DFNS,	NO_CARY,	0, A_CHAOTIC, NON_PM, PM_ORC, 300L ),
+	PHYS(5,6),	SPDF_NONE,	NO_CARY,	0, A_CHAOTIC, NON_PM, PM_ORC, 600L ),
 /*
  *	Orcrist and Sting have same alignment as elves.
- */
-A("Orcrist",			ELVEN_BROADSWORD,
-	SPFX_DFLAG2, 0, M2_ORC,
-	PHYS(5,0),	NO_DFNS,	NO_CARY,	0, A_CHAOTIC, NON_PM, PM_ELF, 2000L ),
-
-/*
  *	The combination of SPFX_WARN and M2_something on an artifact
  *	will trigger EWarn_of_mon for all monsters that have the appropriate
  *	M2_something flags.  In Sting's case it will trigger EWarn_of_mon
- *	for M2_ORC monsters.
+ *	for M2_SPIDER monsters; in Orcrist, for M2_ORC.
  */
+A("Orcrist",			ELVEN_BROADSWORD,
+	(SPFX_WARN|SPFX_DCLAS), 0, S_ORC,
+	PHYS(5,4),	SPDF_NONE,	NO_CARY,	0, A_CHAOTIC, NON_PM, PM_ELF, 2000L ),
+
 A("Sting",			ELVEN_DAGGER,
-	(SPFX_WARN|SPFX_DFLAG2), 0, M2_ORC,
-	PHYS(5,0),	NO_DFNS,	NO_CARY,	0, A_CHAOTIC, NON_PM, PM_ELF, 800L ),
+	(SPFX_WARN|SPFX_DCLAS), 0, S_SPIDER,
+	PHYS(5,3),	SPDF_NONE,	NO_CARY,	0, A_CHAOTIC, NON_PM, PM_ELF, 800L ),
 /*
  *	Magicbane is a bit different!  Its magic fanfare
@@ -88,41 +101,41 @@
 A("Magicbane",			ATHAME,
 	(SPFX_RESTR|SPFX_ATTK|SPFX_DEFN), 0, 0,
-	STUN(3,4),	DFNS(AD_MAGM),	NO_CARY,	0, A_NEUTRAL, PM_WIZARD, NON_PM, 3500L ),
+	STUN(3,4),	SPDF_MAGIC,	NO_CARY,	0, A_NEUTRAL, PM_WIZARD, NON_PM, 3500L ),
 
 A("Frost Brand",		LONG_SWORD,
 	(SPFX_RESTR|SPFX_ATTK|SPFX_DEFN), 0, 0,
-	COLD(5,0),	COLD(0,0),	NO_CARY,	0, A_NONE, NON_PM, NON_PM, 3000L ),
+	COLD(5,0),	SPDF_COLD,	NO_CARY,	0, A_NONE, NON_PM, NON_PM, 3000L ),
 
 A("Fire Brand",			LONG_SWORD,
 	(SPFX_RESTR|SPFX_ATTK|SPFX_DEFN), 0, 0,
-	FIRE(5,0),	FIRE(0,0),	NO_CARY,	0, A_NONE, NON_PM, NON_PM, 3000L ),
+	FIRE(5,0),	SPDF_FIRE,	NO_CARY,	0, A_NONE, NON_PM, NON_PM, 3000L ),
 
-A("Dragonbane",			BROADSWORD,
-	(SPFX_RESTR|SPFX_DCLAS), 0, S_DRAGON,
-	PHYS(5,0),	NO_DFNS,	NO_CARY,	0, A_NONE, NON_PM, NON_PM, 500L ),
+A("Dragonbane",			DWARVISH_SPEAR,
+	(SPFX_WARN|SPFX_RESTR|SPFX_DCLAS), 0, S_DRAGON,
+	PHYS(5,4),	SPDF_ELEMENTAL,	NO_CARY,	0, A_NONE, NON_PM, NON_PM, 1500L ),
 
-A("Demonbane",			LONG_SWORD,
-	(SPFX_RESTR|SPFX_DFLAG2), 0, M2_DEMON,
-	PHYS(5,0),	NO_DFNS,	NO_CARY,	0, A_LAWFUL, NON_PM, NON_PM, 2500L ),
+A("Demonbane",			SILVER_MACE,
+	(SPFX_WARN|SPFX_RESTR|SPFX_DCLAS), 0, S_DEMON,
+	PHYS(5,4),	SPDF_NONE,	NO_CARY,	0, A_LAWFUL, NON_PM, NON_PM, 2500L ),
 
 A("Werebane",			SILVER_SABER,
-	(SPFX_RESTR|SPFX_DFLAG2), 0, M2_WERE,
-	PHYS(5,0),	DFNS(AD_WERE),	NO_CARY,	0, A_NONE, NON_PM, NON_PM, 1500L ),
+	(SPFX_WARN|SPFX_RESTR|SPFX_DCLAS|SPFX_POLYC), 0, S_WERE,
+	PHYS(5,4),	SPDF_WERE,	NO_CARY,	0, A_NONE, NON_PM, NON_PM, 1500L ),
 
 A("Grayswandir",		SILVER_SABER,
 	(SPFX_RESTR|SPFX_HALRES), 0, 0,
-	PHYS(5,0),	NO_DFNS,	NO_CARY,	0, A_LAWFUL, NON_PM, NON_PM, 8000L ),
+	PHYS(5,0),	SPDF_NONE,	NO_CARY,	0, A_LAWFUL, NON_PM, NON_PM, 8000L ),
 
-A("Giantslayer",		LONG_SWORD,
-	(SPFX_RESTR|SPFX_DFLAG2), 0, M2_GIANT,
-	PHYS(5,0),	NO_DFNS,	NO_CARY,	0, A_NEUTRAL, NON_PM, NON_PM, 200L ),
+A("Giantslayer",		SLING,
+	(SPFX_WARN|SPFX_RESTR|SPFX_DCLAS|SPFX_STR), 0, S_GIANT,
+	PHYS(5,8),	SPDF_NONE,	NO_CARY,	0, A_NEUTRAL, NON_PM, NON_PM, 1200L ),
 
 A("Ogresmasher",		WAR_HAMMER,
-	(SPFX_RESTR|SPFX_DCLAS), 0, S_OGRE,
-	PHYS(5,0),	NO_DFNS,	NO_CARY,	0, A_NONE, NON_PM, NON_PM, 200L ),
+	(SPFX_WARN|SPFX_RESTR|SPFX_DCLAS|SPFX_CON), 0, S_OGRE,
+	PHYS(5,4),	SPDF_NONE,	NO_CARY,	0, A_NONE, NON_PM, NON_PM, 1200L ),
 
 A("Trollsbane",			MORNING_STAR,
-	(SPFX_RESTR|SPFX_DCLAS), 0, S_TROLL,
-	PHYS(5,0),	NO_DFNS,	NO_CARY,	0, A_NONE, NON_PM, NON_PM, 200L ),
+	(SPFX_WARN|SPFX_RESTR|SPFX_DCLAS|SPFX_REGEN), 0, S_TROLL,
+	PHYS(5,4),	SPDF_NONE,	NO_CARY,	0, A_NONE, NON_PM, NON_PM, 1200L ),
 /*
  *	Two problems:  1) doesn't let trolls regenerate heads,
@@ -132,5 +145,5 @@
 A("Vorpal Blade",		LONG_SWORD,
 	(SPFX_RESTR|SPFX_BEHEAD), 0, 0,
-	PHYS(5,1),	NO_DFNS,	NO_CARY,	0, A_NEUTRAL, NON_PM, NON_PM, 4000L ),
+	PHYS(5,1),	SPDF_NONE,	NO_CARY,	0, A_NEUTRAL, NON_PM, NON_PM, 4000L ),
 /*
  *	Ah, never shall I forget the cry,
@@ -143,9 +156,13 @@
 A("Snickersnee",		KATANA,
 	SPFX_RESTR, 0, 0,
-	PHYS(0,8),	NO_DFNS,	NO_CARY,	0, A_LAWFUL, PM_SAMURAI, NON_PM, 1200L ),
+	PHYS(5,8),	SPDF_NONE,	NO_CARY,	0, A_LAWFUL, PM_SAMURAI, NON_PM, 1200L ),
 
-A("Sunsword",			LONG_SWORD,
-	(SPFX_RESTR|SPFX_DFLAG2), 0, M2_UNDEAD,
-	PHYS(5,0),	DFNS(AD_BLND),	NO_CARY,	0, A_LAWFUL, NON_PM, NON_PM, 1500L ),
+A("Sunsword",			SILVER_LONG_SWORD,
+	(SPFX_WARN|SPFX_RESTR|SPFX_DCLAS), 0, S_UNDEAD,
+	PHYS(5,4),	SPDF_BLIND,	NO_CARY,	0, A_LAWFUL, NON_PM, NON_PM, 1500L ),
+
+A("Keolewa",CLUB,
+	SPFX_RESTR, 0, 0,
+	PHYS(5,6), SPDF_NONE, NO_CARY, 0, A_NEUTRAL, PM_CAVEMAN, NON_PM, 1000L ),
 
 /*
@@ -155,5 +172,5 @@
 A("The Orb of Detection",	CRYSTAL_BALL,
 	(SPFX_NOGEN|SPFX_RESTR|SPFX_INTEL), (SPFX_ESP|SPFX_HSPDAM), 0,
-	NO_ATTK,	NO_DFNS,	CARY(AD_MAGM),
+	NO_ATTK,	SPDF_NONE,	CARY(AD_MAGM),
 	INVIS,		A_LAWFUL, PM_ARCHEOLOGIST, NON_PM, 2500L ),
 
@@ -161,10 +178,10 @@
 	(SPFX_NOGEN|SPFX_RESTR|SPFX_INTEL), SPFX_STLTH, 0,
 	/* this stone does double damage if used as a projectile weapon */
-	PHYS(5,0),	NO_DFNS,	NO_CARY,
+	PHYS(5,0),	SPDF_NONE,	NO_CARY,
 	LEVITATION,	A_NEUTRAL, PM_BARBARIAN, NON_PM, 2500L ),
 
 A("The Sceptre of Might",	MACE,
 	(SPFX_NOGEN|SPFX_RESTR|SPFX_INTEL|SPFX_DALIGN), 0, 0,
-	PHYS(5,0),	NO_DFNS,	CARY(AD_MAGM),
+	PHYS(5,0),	SPDF_NONE,	CARY(AD_MAGM),
 	CONFLICT,	A_LAWFUL, PM_CAVEMAN, NON_PM, 2500L ),
 
@@ -179,25 +196,26 @@
 A("The Staff of Aesculapius",	QUARTERSTAFF,
 	(SPFX_NOGEN|SPFX_RESTR|SPFX_ATTK|SPFX_INTEL|SPFX_DRLI|SPFX_REGEN), 0,0,
-	DRLI(0,0),	DRLI(0,0),	NO_CARY,
+	DRLI(0,0),	SPDF_DRAIN,	NO_CARY,
 	HEALING,	A_NEUTRAL, PM_HEALER, NON_PM, 5000L ),
 
 A("The Magic Mirror of Merlin", MIRROR,
-	(SPFX_NOGEN|SPFX_RESTR|SPFX_INTEL|SPFX_SPEAK), SPFX_ESP, 0,
-	NO_ATTK,	NO_DFNS,	CARY(AD_MAGM),
+	(SPFX_NOGEN|SPFX_RESTR|SPFX_INTEL|SPFX_SPEAK|SPFX_REFLECT), 
+	(SPFX_REFLECT|SPFX_ESP|SPFX_HSPDAM), 0,
+	NO_ATTK,	SPDF_NONE,	NO_CARY,
 	0,		A_LAWFUL, PM_KNIGHT, NON_PM, 1500L ),
 
 A("The Eyes of the Overworld",	LENSES,
 	(SPFX_NOGEN|SPFX_RESTR|SPFX_INTEL|SPFX_XRAY), 0, 0,
-	NO_ATTK,	NO_DFNS,	CARY(AD_MAGM),
+	NO_ATTK,	SPDF_NONE,	CARY(AD_MAGM),
 	ENLIGHTENING,	A_NEUTRAL,	 PM_MONK, NON_PM, 2500L ),
 
 A("The Mitre of Holiness",	HELM_OF_BRILLIANCE,
 	(SPFX_NOGEN|SPFX_RESTR|SPFX_DFLAG2|SPFX_INTEL), 0, M2_UNDEAD,
-	NO_ATTK,	NO_DFNS,	CARY(AD_FIRE),
+	NO_ATTK,	SPDF_NONE,	CARY(AD_FIRE),
 	ENERGY_BOOST,	A_LAWFUL, PM_PRIEST, NON_PM, 2000L ),
 
 A("The Longbow of Diana", BOW,
 	(SPFX_NOGEN|SPFX_RESTR|SPFX_INTEL|SPFX_REFLECT), SPFX_ESP, 0,
-	PHYS(5,0),	NO_DFNS,	NO_CARY,
+	PHYS(5,0),	SPDF_NONE,	NO_CARY,
 	CREATE_AMMO, A_CHAOTIC, PM_RANGER, NON_PM, 4000L ),
 
@@ -205,10 +223,10 @@
 	(SPFX_NOGEN|SPFX_RESTR|SPFX_INTEL|SPFX_SPEAK),
 		(SPFX_WARN|SPFX_TCTRL|SPFX_HPHDAM), 0,
-	NO_ATTK,	NO_DFNS,	NO_CARY,
+	NO_ATTK,	SPDF_NONE,	NO_CARY,
 	UNTRAP,		A_CHAOTIC, PM_ROGUE, NON_PM, 3500L ),
 
 A("The Tsurugi of Muramasa",	TSURUGI,
 	(SPFX_NOGEN|SPFX_RESTR|SPFX_INTEL|SPFX_BEHEAD|SPFX_LUCK), 0, 0,
-	PHYS(0,8),	NO_DFNS,	NO_CARY,
+	PHYS(0,8),	SPDF_NONE,	NO_CARY,
 	0,		A_LAWFUL, PM_SAMURAI, NON_PM, 4500L ),
 
@@ -217,5 +235,5 @@
 	(SPFX_NOGEN|SPFX_RESTR|SPFX_INTEL|SPFX_DEFN),
 		(SPFX_ESP|SPFX_HSPDAM), 0,
-	NO_ATTK,	NO_DFNS,	CARY(AD_MAGM),
+	NO_ATTK,	SPDF_NONE,	CARY(AD_MAGM),
 	CHARGE_OBJ,	A_NEUTRAL, PM_TOURIST, NON_PM, 7000L ),
 #endif
@@ -223,11 +241,11 @@
 A("The Orb of Fate",		CRYSTAL_BALL,
 	(SPFX_NOGEN|SPFX_RESTR|SPFX_INTEL|SPFX_LUCK),
-		(SPFX_WARN|SPFX_HSPDAM|SPFX_HPHDAM), 0,
-	NO_ATTK,	NO_DFNS,	NO_CARY,
+		(SPFX_WARN|SPFX_HPHDAM), 0,
+	NO_ATTK,	SPDF_NONE,	NO_CARY,
 	LEV_TELE,	A_NEUTRAL, PM_VALKYRIE, NON_PM, 3500L ),
 
-A("The Eye of the Aethiopica",	AMULET_OF_ESP,
-	(SPFX_NOGEN|SPFX_RESTR|SPFX_INTEL), (SPFX_EREGEN|SPFX_HSPDAM), 0,
-	NO_ATTK,	NO_DFNS,	CARY(AD_MAGM),
+A("The Eye of the Aethiopica",	AMULET_OF_POWER,
+	(SPFX_NOGEN|SPFX_RESTR|SPFX_INTEL), (SPFX_ESP|SPFX_HSPDAM), 0,
+	NO_ATTK,	SPDF_NONE,	CARY(AD_MAGM),
 	CREATE_PORTAL,	A_NEUTRAL, PM_WIZARD, NON_PM, 4000L ),
 
@@ -235,5 +253,5 @@
  *  terminator; otyp must be zero
  */
-A(0, 0, 0, 0, 0, NO_ATTK, NO_DFNS, NO_CARY, 0, A_NONE, NON_PM, NON_PM, 0L )
+A(0, 0, 0, 0, 0, NO_ATTK, SPDF_NONE, NO_CARY, 0, A_NONE, NON_PM, NON_PM, 0L )
 
 };	/* artilist[] (or artifact_names[]) */
@@ -243,5 +261,4 @@
 #ifndef MAKEDEFS_C
 #undef	NO_ATTK
-#undef	NO_DFNS
 #undef	DFNS
 #undef	PHYS
@@ -251,4 +268,5 @@
 #undef	ELEC
 #undef	STUN
+#undef	DRST
 #endif
 
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/include/color.h nethack/include/color.h
--- nh_orig/include/color.h	2003-12-07 18:39:13.000000000 -0500
+++ nethack/include/color.h	2009-09-07 11:17:28.044650941 -0400
@@ -6,4 +6,10 @@
 #define COLOR_H
 
+#ifdef MENU_COLOR
+# ifdef MENU_COLOR_REGEX
+#  include <regex.h>
+# endif
+#endif
+
 /*
  * The color scheme used is tailored for an IBM PC.  It consists of the
@@ -50,3 +56,38 @@
 #define HI_ZAP		CLR_BRIGHT_BLUE
 
+#ifdef MENU_COLOR
+struct menucoloring {
+# ifdef MENU_COLOR_REGEX
+#  ifdef MENU_COLOR_REGEX_POSIX
+    regex_t match;
+#  else
+    struct re_pattern_buffer match;
+#  endif
+# else
+    char *match;
+# endif
+    int color, attr;
+    struct menucoloring *next;
+};
+#endif /* MENU_COLOR */
+
+#ifdef STATUS_COLORS
+struct color_option {
+    int color;
+    int attr_bits;
+};
+
+struct percent_color_option {
+	int percentage;
+	struct color_option color_option;
+	const struct percent_color_option *next;
+};
+
+struct text_color_option {
+	const char *text;
+	struct color_option color_option;
+	const struct text_color_option *next;
+};
+#endif
+
 #endif /* COLOR_H */
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/include/config.h nethack/include/config.h
--- nh_orig/include/config.h	2003-12-07 18:39:13.000000000 -0500
+++ nethack/include/config.h	2010-05-14 11:22:24.446714491 -0400
@@ -144,14 +144,19 @@
 #ifndef WIZARD		/* allow for compile-time or Makefile changes */
 # ifndef KR1ED
-#  define WIZARD  "wizard" /* the person allowed to use the -D option */
+#  define WIZARD  "derek" /* the person allowed to use the -D option */
 # else
 #  define WIZARD
-#  define WIZARD_NAME "wizard"
+#  define WIZARD_NAME "derek"
 # endif
 #endif
 
 #define LOGFILE "logfile"	/* larger file for debugging purposes */
+#define XLOGFILE "xlogfile" /* even larger logfile */
 #define NEWS "news"		/* the file containing the latest hack news */
 #define PANICLOG "paniclog"	/* log of panic and impossible events */
+#define DUMP_LOG				 /* turn on dumping */
+#define DUMP_FN "dumps/%n.lastlog"	 /* dump goes here */
+
+#define SERVER_ADMIN_MSG "admin_msg"
 
 /*
@@ -170,9 +175,9 @@
 #ifdef UNIX
 /* path and file name extension for compression program */
-#define COMPRESS "/usr/bin/compress"	/* Lempel-Ziv compression */
-#define COMPRESS_EXTENSION ".Z"		/* compress's extension */
+/* #define COMPRESS "/usr/bin/compress"	 Lempel-Ziv compression */
+/* #define COMPRESS_EXTENSION ".Z"	 compress's extension */
 /* An example of one alternative you might want to use: */
-/* #define COMPRESS "/usr/local/bin/gzip" */	/* FSF gzip compression */
-/* #define COMPRESS_EXTENSION ".gz" */		/* normal gzip extension */
+#define COMPRESS "/usr/bin/gzip" /* FSF gzip compression */
+#define COMPRESS_EXTENSION ".gz" 	/* normal gzip extension */
 #endif
 
@@ -186,5 +191,5 @@
  *	for detailed configuration.
  */
-/* #define DLB */	/* not supported on all platforms */
+#define DLB /* not supported on all platforms */
 
 /*
@@ -215,5 +220,5 @@
  * Of course SECURE is meaningful only if HACKDIR is defined.
  */
-/* #define SECURE */	/* do setuid(getuid()) after chdir() */
+#define SECURE 	/* do setuid(getuid()) after chdir() */
 
 /*
@@ -301,5 +306,5 @@
  */
 
-/* #define VISION_TABLES */ /* use vision tables generated at compile time */
+#define VISION_TABLES /* use vision tables generated at compile time */
 #ifndef VISION_TABLES
 # ifndef NO_MACRO_CPATH
@@ -328,4 +333,5 @@
 /* difficulty */
 #define ELBERETH	/* Engraving the E-word repels monsters */
+#define SORTLOOT
 /* I/O */
 #define REDO		/* support for redoing last command - DGK */
@@ -339,5 +345,25 @@
 
 #define EXP_ON_BOTL	/* Show experience on bottom line */
-/* #define SCORE_ON_BOTL */	/* added by Gary Erickson (erickson@ucivax) */
+#define SCORE_ON_BOTL /* added by Gary Erickson (erickson@ucivax) */
+
+/* #define REALTIME_ON_BOTL */  /* Show elapsed time on bottom line.  Note:
+                                 * this breaks savefile compatibility. */
+
+/* The options in this section require the extended logfile support */
+#ifdef XLOGFILE
+#define RECORD_CONDUCT  /* Record conducts kept in logfile */
+#define RECORD_TURNS    /* Record turns elapsed in logfile */
+#define RECORD_ACHIEVE  /* Record certain notable achievements in the
+                         * logfile.  Note: this breaks savefile compatibility
+                         * due to the addition of the u_achieve struct. */
+#define RECORD_REALTIME /* Record the amount of actual playing time (in
+                         * seconds) in the record file.  Note: this breaks
+                         * savefile compatibility. */
+#define RECORD_START_END_TIME /* Record to-the-second starting and ending
+                               * times; stored as 32-bit values obtained
+                               * from time(2) (seconds since the Epoch.) */
+#define RECORD_GENDER0   /* Record initial gender in logfile */
+#define RECORD_ALIGN0   /* Record initial alignment in logfile */
+#endif
 
 /*
@@ -349,6 +375,23 @@
  */
 
-/*#define GOLDOBJ */	/* Gold is kept on obj chains - Helge Hafting */
-/*#define AUTOPICKUP_EXCEPTIONS */ /* exceptions to autopickup */
+#if defined(TTY_GRAPHICS) || defined(MSWIN_GRAPHICS)
+# define MENU_COLOR
+# define MENU_COLOR_REGEX
+/* if MENU_COLOR_REGEX is defined, use regular expressions (regex.h,
+ * GNU specific functions by default, POSIX functions with
+ * MENU_COLOR_REGEX_POSIX).
+ *
+ * POSIX is required for OSX and possibly others.
+ *
+ * otherwise use pmatch() to match menu color lines.
+ * pmatch() provides basic globbing: '*' and '?' wildcards.
+ */
+#endif
+
+#define STATUS_COLORS
+#define GOLDOBJ /* Gold is kept on obj chains - Helge Hafting */
+#define AUTOPICKUP_EXCEPTIONS /* exceptions to autopickup */
+#define WHEREIS_FILE /* Write out player's current location to player.whereis */
+#define WISH_TRACKER /* Write all wishes to a tracking file */
 
 /* End of Section 5 */
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/include/decl.h nethack/include/decl.h
--- nh_orig/include/decl.h	2003-12-07 18:39:13.000000000 -0500
+++ nethack/include/decl.h	2010-04-26 14:16:44.738840681 -0400
@@ -28,4 +28,5 @@
 
 E NEARDATA int multi;
+E char multi_txt[BUFSZ];
 #if 0
 E NEARDATA int warnlevel;
@@ -73,4 +74,8 @@
     d_level	d_qstart_level, d_qlocate_level, d_nemesis_level;
     d_level	d_knox_level;
+#ifdef RECORD_ACHIEVE
+    d_level     d_mineend_level;
+    d_level     d_sokoend_level;
+#endif
 } dungeon_topology;
 /* macros for accesing the dungeon levels by their old names */
@@ -105,4 +110,8 @@
 #define nemesis_level		(dungeon_topology.d_nemesis_level)
 #define knox_level		(dungeon_topology.d_knox_level)
+#ifdef RECORD_ACHIEVE
+#define mineend_level           (dungeon_topology.d_mineend_level)
+#define sokoend_level           (dungeon_topology.d_sokoend_level)
+#endif
 
 E NEARDATA stairway dnstair, upstair;		/* stairs up and down */
@@ -185,4 +194,7 @@
 #endif
 E char killer_buf[BUFSZ];
+#ifdef DUMP_LOG
+E char dump_fn[];		/* dumpfile name (dump patch) */
+#endif
 E const char *configfile;
 E NEARDATA char plname[PL_NSIZ];
@@ -244,5 +256,5 @@
 #endif
 	*uskin, *uamul, *uleft, *uright, *ublindf,
-	*uwep, *uswapwep, *uquiver;
+	*uwep, *uswapwep, *uquiver, *ulauncher;
 
 E NEARDATA struct obj *uchain;		/* defined only when punished */
@@ -252,4 +264,7 @@
 E NEARDATA struct obj zeroobj;		/* init'd and defined in decl.c */
 
+#include "engrave.h"
+E struct engr *head_engr;
+
 #include "you.h"
 E NEARDATA struct you u;
@@ -262,4 +277,6 @@
 E NEARDATA struct monst youmonst;	/* init'd and defined in decl.c */
 E NEARDATA struct monst *mydogs, *migrating_mons;
+E NEARDATA struct monst* polemonst;
+E NEARDATA struct monst* ukiller;
 
 E NEARDATA struct mvitals {
@@ -386,4 +403,38 @@
 #endif /* AUTOPICKUP_EXCEPTIONS */
 
+#ifdef RECORD_ACHIEVE
+struct u_achieve {
+        Bitfield(get_bell,1);        /* You have obtained the bell of 
+                                      * opening */
+        Bitfield(get_candelabrum,1); /* You have obtained the candelabrum */
+        Bitfield(get_book,1);        /* You have obtained the book of 
+                                      * the dead */
+        Bitfield(enter_gehennom,1);  /* Entered Gehennom (including the 
+                                      * Valley) by any means */
+        Bitfield(perform_invocation,1); /* You have performed the invocation
+                                         * ritual */
+        Bitfield(get_amulet,1);      /* You have obtained the amulet
+                                      * of Yendor */
+        Bitfield(ascended,1);        /* You ascended to demigod[dess]hood.
+                                      * Not quite the same as 
+                                      * u.uevent.ascended. */
+        Bitfield(get_luckstone,1);   /* You obtained the luckstone at the
+                                      * end of the mines. */
+        Bitfield(finish_sokoban,1);  /* You obtained the sokoban prize. */
+        Bitfield(killed_medusa,1);   /* You defeated Medusa. */
+};
+
+E struct u_achieve achieve;
+#endif
+
+#if defined(RECORD_REALTIME) || defined(REALTIME_ON_BOTL)
+E struct realtime_data {
+  time_t realtime;    /* Amount of actual playing time up until the last time
+                       * the game was restored. */
+  time_t restoretime; /* The time that the game was started or restored. */
+  time_t last_displayed_time; /* Last time displayed on the status line */
+} realtime_data;
+#endif /* RECORD_REALTIME || REALTIME_ON_BOTL */
+
 #undef E
 
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/include/decl.h.~1~ nethack/include/decl.h.~1~
--- nh_orig/include/decl.h.~1~	1969-12-31 19:00:00.000000000 -0500
+++ nethack/include/decl.h.~1~	2009-11-22 07:19:36.043482113 -0500
@@ -0,0 +1,441 @@
+/*	SCCS Id: @(#)decl.h	3.4	2001/12/10	*/
+/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
+/* NetHack may be freely redistributed.  See license for details. */
+
+#ifndef DECL_H
+#define DECL_H
+
+#define E extern
+
+E int NDECL((*occupation));
+E int NDECL((*afternmv));
+
+E const char *hname;
+E int hackpid;
+#if defined(UNIX) || defined(VMS)
+E int locknum;
+#endif
+#ifdef DEF_PAGER
+E char *catmore;
+#endif	/* DEF_PAGER */
+
+E char SAVEF[];
+#ifdef MICRO
+E char SAVEP[];
+#endif
+
+E NEARDATA int bases[MAXOCLASSES];
+
+E NEARDATA int multi;
+E char multi_txt[BUFSZ];
+#if 0
+E NEARDATA int warnlevel;
+#endif
+E NEARDATA int nroom;
+E NEARDATA int nsubroom;
+E NEARDATA int occtime;
+
+#define WARNCOUNT 6			/* number of different warning levels */
+E uchar warnsyms[WARNCOUNT];
+
+E int x_maze_max, y_maze_max;
+E int otg_temp;
+
+#ifdef REDO
+E NEARDATA int in_doagain;
+#endif
+
+E struct dgn_topology {		/* special dungeon levels for speed */
+    d_level	d_oracle_level;
+    d_level	d_bigroom_level;	/* unused */
+#ifdef REINCARNATION
+    d_level	d_rogue_level;
+#endif
+    d_level	d_medusa_level;
+    d_level	d_stronghold_level;
+    d_level	d_valley_level;
+    d_level	d_wiz1_level;
+    d_level	d_wiz2_level;
+    d_level	d_wiz3_level;
+    d_level	d_juiblex_level;
+    d_level	d_orcus_level;
+    d_level	d_baalzebub_level;	/* unused */
+    d_level	d_asmodeus_level;	/* unused */
+    d_level	d_portal_level;		/* only in goto_level() [do.c] */
+    d_level	d_sanctum_level;
+    d_level	d_earth_level;
+    d_level	d_water_level;
+    d_level	d_fire_level;
+    d_level	d_air_level;
+    d_level	d_astral_level;
+    xchar	d_tower_dnum;
+    xchar	d_sokoban_dnum;
+    xchar	d_mines_dnum, d_quest_dnum;
+    d_level	d_qstart_level, d_qlocate_level, d_nemesis_level;
+    d_level	d_knox_level;
+#ifdef RECORD_ACHIEVE
+    d_level     d_mineend_level;
+    d_level     d_sokoend_level;
+#endif
+} dungeon_topology;
+/* macros for accesing the dungeon levels by their old names */
+#define oracle_level		(dungeon_topology.d_oracle_level)
+#define bigroom_level		(dungeon_topology.d_bigroom_level)
+#ifdef REINCARNATION
+#define rogue_level		(dungeon_topology.d_rogue_level)
+#endif
+#define medusa_level		(dungeon_topology.d_medusa_level)
+#define stronghold_level	(dungeon_topology.d_stronghold_level)
+#define valley_level		(dungeon_topology.d_valley_level)
+#define wiz1_level		(dungeon_topology.d_wiz1_level)
+#define wiz2_level		(dungeon_topology.d_wiz2_level)
+#define wiz3_level		(dungeon_topology.d_wiz3_level)
+#define juiblex_level		(dungeon_topology.d_juiblex_level)
+#define orcus_level		(dungeon_topology.d_orcus_level)
+#define baalzebub_level		(dungeon_topology.d_baalzebub_level)
+#define asmodeus_level		(dungeon_topology.d_asmodeus_level)
+#define portal_level		(dungeon_topology.d_portal_level)
+#define sanctum_level		(dungeon_topology.d_sanctum_level)
+#define earth_level		(dungeon_topology.d_earth_level)
+#define water_level		(dungeon_topology.d_water_level)
+#define fire_level		(dungeon_topology.d_fire_level)
+#define air_level		(dungeon_topology.d_air_level)
+#define astral_level		(dungeon_topology.d_astral_level)
+#define tower_dnum		(dungeon_topology.d_tower_dnum)
+#define sokoban_dnum		(dungeon_topology.d_sokoban_dnum)
+#define mines_dnum		(dungeon_topology.d_mines_dnum)
+#define quest_dnum		(dungeon_topology.d_quest_dnum)
+#define qstart_level		(dungeon_topology.d_qstart_level)
+#define qlocate_level		(dungeon_topology.d_qlocate_level)
+#define nemesis_level		(dungeon_topology.d_nemesis_level)
+#define knox_level		(dungeon_topology.d_knox_level)
+#ifdef RECORD_ACHIEVE
+#define mineend_level           (dungeon_topology.d_mineend_level)
+#define sokoend_level           (dungeon_topology.d_sokoend_level)
+#endif
+
+E NEARDATA stairway dnstair, upstair;		/* stairs up and down */
+#define xdnstair	(dnstair.sx)
+#define ydnstair	(dnstair.sy)
+#define xupstair	(upstair.sx)
+#define yupstair	(upstair.sy)
+
+E NEARDATA stairway dnladder, upladder;		/* ladders up and down */
+#define xdnladder	(dnladder.sx)
+#define ydnladder	(dnladder.sy)
+#define xupladder	(upladder.sx)
+#define yupladder	(upladder.sy)
+
+E NEARDATA stairway sstairs;
+
+E NEARDATA dest_area updest, dndest;	/* level-change destination areas */
+
+E NEARDATA coord inv_pos;
+E NEARDATA dungeon dungeons[];
+E NEARDATA s_level *sp_levchn;
+#define dunlev_reached(x)	(dungeons[(x)->dnum].dunlev_ureached)
+
+#include "quest.h"
+E struct q_score quest_status;
+
+E NEARDATA char pl_character[PL_CSIZ];
+E NEARDATA char pl_race;		/* character's race */
+
+E NEARDATA char pl_fruit[PL_FSIZ];
+E NEARDATA int current_fruit;
+E NEARDATA struct fruit *ffruit;
+
+E NEARDATA char tune[6];
+
+#define MAXLINFO (MAXDUNGEON * MAXLEVEL)
+E struct linfo level_info[MAXLINFO];
+
+E NEARDATA struct sinfo {
+	int gameover;		/* self explanatory? */
+	int stopprint;		/* inhibit further end of game disclosure */
+#if defined(UNIX) || defined(VMS) || defined (__EMX__) || defined(WIN32)
+	int done_hup;		/* SIGHUP or moral equivalent received
+				 * -- no more screen output */
+#endif
+	int something_worth_saving;	/* in case of panic */
+	int panicking;		/* `panic' is in progress */
+#if defined(VMS) || defined(WIN32)
+	int exiting;		/* an exit handler is executing */
+#endif
+	int in_impossible;
+#ifdef PANICLOG
+	int in_paniclog;
+#endif
+} program_state;
+
+E boolean restoring;
+
+E const char quitchars[];
+E const char vowels[];
+E const char ynchars[];
+E const char ynqchars[];
+E const char ynaqchars[];
+E const char ynNaqchars[];
+E NEARDATA long yn_number;
+
+E const char disclosure_options[];
+
+E NEARDATA int smeq[];
+E NEARDATA int doorindex;
+E NEARDATA char *save_cm;
+#define KILLED_BY_AN	 0
+#define KILLED_BY	 1
+#define NO_KILLER_PREFIX 2
+E NEARDATA int killer_format;
+E const char *killer;
+E const char *delayed_killer;
+#ifdef GOLDOBJ
+E long done_money;
+#endif
+E char killer_buf[BUFSZ];
+#ifdef DUMP_LOG
+E char dump_fn[];		/* dumpfile name (dump patch) */
+#endif
+E const char *configfile;
+E NEARDATA char plname[PL_NSIZ];
+E NEARDATA char dogname[];
+E NEARDATA char catname[];
+E NEARDATA char horsename[];
+E char preferred_pet;
+E const char *occtxt;			/* defined when occupation != NULL */
+E const char *nomovemsg;
+E const char nul[];
+E char lock[];
+
+E const char sdir[], ndir[];
+E const schar xdir[], ydir[], zdir[];
+
+E NEARDATA schar tbx, tby;		/* set in mthrowu.c */
+
+E NEARDATA struct multishot { int n, i; short o; boolean s; } m_shot;
+
+E NEARDATA struct dig_info {		/* apply.c, hack.c */
+	int	effort;
+	d_level level;
+	coord	pos;
+	long lastdigtime;
+	boolean down, chew, warned, quiet;
+} digging;
+
+E NEARDATA long moves, monstermoves;
+E NEARDATA long wailmsg;
+
+E NEARDATA boolean in_mklev;
+E NEARDATA boolean stoned;
+E NEARDATA boolean unweapon;
+E NEARDATA boolean mrg_to_wielded;
+E NEARDATA struct obj *current_wand;
+
+E NEARDATA boolean in_steed_dismounting;
+
+E const int shield_static[];
+
+#include "spell.h"
+E NEARDATA struct spell spl_book[];	/* sized in decl.c */
+
+#include "color.h"
+#ifdef TEXTCOLOR
+E const int zapcolors[];
+#endif
+
+E const char def_oc_syms[MAXOCLASSES];	/* default class symbols */
+E uchar oc_syms[MAXOCLASSES];		/* current class symbols */
+E const char def_monsyms[MAXMCLASSES];	/* default class symbols */
+E uchar monsyms[MAXMCLASSES];		/* current class symbols */
+
+#include "obj.h"
+E NEARDATA struct obj *invent,
+	*uarm, *uarmc, *uarmh, *uarms, *uarmg, *uarmf,
+#ifdef TOURIST
+	*uarmu,				/* under-wear, so to speak */
+#endif
+	*uskin, *uamul, *uleft, *uright, *ublindf,
+	*uwep, *uswapwep, *uquiver, *ulauncher;
+
+E NEARDATA struct obj *uchain;		/* defined only when punished */
+E NEARDATA struct obj *uball;
+E NEARDATA struct obj *migrating_objs;
+E NEARDATA struct obj *billobjs;
+E NEARDATA struct obj zeroobj;		/* init'd and defined in decl.c */
+
+#include "engrave.h"
+E struct engr *head_engr;
+
+#include "you.h"
+E NEARDATA struct you u;
+
+#include "onames.h"
+#ifndef PM_H		/* (pm.h has already been included via youprop.h) */
+#include "pm.h"
+#endif
+
+E NEARDATA struct monst youmonst;	/* init'd and defined in decl.c */
+E NEARDATA struct monst *mydogs, *migrating_mons;
+E NEARDATA struct monst* polemonst;
+E NEARDATA struct monst* ukiller;
+
+E NEARDATA struct mvitals {
+	uchar	born;
+	uchar	died;
+	uchar	mvflags;
+} mvitals[NUMMONS];
+
+E NEARDATA struct c_color_names {
+    const char	*const c_black, *const c_amber, *const c_golden,
+		*const c_light_blue,*const c_red, *const c_green,
+		*const c_silver, *const c_blue, *const c_purple,
+		*const c_white;
+} c_color_names;
+#define NH_BLACK		c_color_names.c_black
+#define NH_AMBER		c_color_names.c_amber
+#define NH_GOLDEN		c_color_names.c_golden
+#define NH_LIGHT_BLUE		c_color_names.c_light_blue
+#define NH_RED			c_color_names.c_red
+#define NH_GREEN		c_color_names.c_green
+#define NH_SILVER		c_color_names.c_silver
+#define NH_BLUE			c_color_names.c_blue
+#define NH_PURPLE		c_color_names.c_purple
+#define NH_WHITE		c_color_names.c_white
+
+/* The names of the colors used for gems, etc. */
+E const char *c_obj_colors[];
+
+E struct c_common_strings {
+    const char	*const c_nothing_happens, *const c_thats_enough_tries,
+		*const c_silly_thing_to, *const c_shudder_for_moment,
+		*const c_something, *const c_Something,
+		*const c_You_can_move_again,
+		*const c_Never_mind, *c_vision_clears,
+		*const c_the_your[2];
+} c_common_strings;
+#define nothing_happens    c_common_strings.c_nothing_happens
+#define thats_enough_tries c_common_strings.c_thats_enough_tries
+#define silly_thing_to	   c_common_strings.c_silly_thing_to
+#define shudder_for_moment c_common_strings.c_shudder_for_moment
+#define something	   c_common_strings.c_something
+#define Something	   c_common_strings.c_Something
+#define You_can_move_again c_common_strings.c_You_can_move_again
+#define Never_mind	   c_common_strings.c_Never_mind
+#define vision_clears	   c_common_strings.c_vision_clears
+#define the_your	   c_common_strings.c_the_your
+
+/* material strings */
+E const char *materialnm[];
+
+/* Monster name articles */
+#define ARTICLE_NONE	0
+#define ARTICLE_THE	1
+#define ARTICLE_A	2
+#define ARTICLE_YOUR	3
+
+/* Monster name suppress masks */
+#define SUPPRESS_IT		0x01
+#define SUPPRESS_INVISIBLE	0x02
+#define SUPPRESS_HALLUCINATION  0x04
+#define SUPPRESS_SADDLE		0x08
+#define EXACT_NAME		0x0F
+
+/* Vision */
+E NEARDATA boolean vision_full_recalc;	/* TRUE if need vision recalc */
+E NEARDATA char **viz_array;		/* could see/in sight row pointers */
+
+/* Window system stuff */
+E NEARDATA winid WIN_MESSAGE, WIN_STATUS;
+E NEARDATA winid WIN_MAP, WIN_INVEN;
+E char toplines[];
+#ifndef TCAP_H
+E struct tc_gbl_data {	/* also declared in tcap.h */
+    char *tc_AS, *tc_AE;	/* graphics start and end (tty font swapping) */
+    int   tc_LI,  tc_CO;	/* lines and columns */
+} tc_gbl_data;
+#define AS tc_gbl_data.tc_AS
+#define AE tc_gbl_data.tc_AE
+#define LI tc_gbl_data.tc_LI
+#define CO tc_gbl_data.tc_CO
+#endif
+
+/* xxxexplain[] is in drawing.c */
+E const char * const monexplain[], invisexplain[], * const objexplain[], * const oclass_names[];
+
+/* Some systems want to use full pathnames for some subsets of file names,
+ * rather than assuming that they're all in the current directory.  This
+ * provides all the subclasses that seem reasonable, and sets up for all
+ * prefixes being null.  Port code can set those that it wants.
+ */
+#define HACKPREFIX	0
+#define LEVELPREFIX	1
+#define SAVEPREFIX	2
+#define BONESPREFIX	3
+#define DATAPREFIX	4	/* this one must match hardcoded value in dlb.c */
+#define SCOREPREFIX	5
+#define LOCKPREFIX	6
+#define CONFIGPREFIX	7
+#define TROUBLEPREFIX	8
+#define PREFIX_COUNT	9
+/* used in files.c; xxconf.h can override if needed */
+# ifndef FQN_MAX_FILENAME
+#define FQN_MAX_FILENAME 512
+# endif
+
+#if defined(NOCWD_ASSUMPTIONS) || defined(VAR_PLAYGROUND)
+/* the bare-bones stuff is unconditional above to simplify coding; for
+ * ports that actually use prefixes, add some more localized things
+ */
+#define PREFIXES_IN_USE
+#endif
+
+E char *fqn_prefix[PREFIX_COUNT];
+#ifdef PREFIXES_IN_USE
+E char *fqn_prefix_names[PREFIX_COUNT];
+#endif
+
+#ifdef AUTOPICKUP_EXCEPTIONS
+struct autopickup_exception {
+	char *pattern;
+	boolean grab;
+	struct autopickup_exception *next;
+};
+#endif /* AUTOPICKUP_EXCEPTIONS */
+
+#ifdef RECORD_ACHIEVE
+struct u_achieve {
+        Bitfield(get_bell,1);        /* You have obtained the bell of 
+                                      * opening */
+        Bitfield(get_candelabrum,1); /* You have obtained the candelabrum */
+        Bitfield(get_book,1);        /* You have obtained the book of 
+                                      * the dead */
+        Bitfield(enter_gehennom,1);  /* Entered Gehennom (including the 
+                                      * Valley) by any means */
+        Bitfield(perform_invocation,1); /* You have performed the invocation
+                                         * ritual */
+        Bitfield(get_amulet,1);      /* You have obtained the amulet
+                                      * of Yendor */
+        Bitfield(ascended,1);        /* You ascended to demigod[dess]hood.
+                                      * Not quite the same as 
+                                      * u.uevent.ascended. */
+        Bitfield(get_luckstone,1);   /* You obtained the luckstone at the
+                                      * end of the mines. */
+        Bitfield(finish_sokoban,1);  /* You obtained the sokoban prize. */
+        Bitfield(killed_medusa,1);   /* You defeated Medusa. */
+};
+
+E struct u_achieve achieve;
+#endif
+
+#if defined(RECORD_REALTIME) || defined(REALTIME_ON_BOTL)
+E struct realtime_data {
+  time_t realtime;    /* Amount of actual playing time up until the last time
+                       * the game was restored. */
+  time_t restoretime; /* The time that the game was started or restored. */
+  time_t last_displayed_time; /* Last time displayed on the status line */
+} realtime_data;
+#endif /* RECORD_REALTIME || REALTIME_ON_BOTL */
+
+#undef E
+
+#endif /* DECL_H */
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/include/display.h nethack/include/display.h
--- nh_orig/include/display.h	2003-12-07 18:39:13.000000000 -0500
+++ nethack/include/display.h	2010-03-24 12:55:58.944626078 -0400
@@ -27,5 +27,5 @@
 #define tp_sensemon(mon) (	/* The hero can always sense a monster IF:  */\
     (!mindless(mon->data)) &&	/* 1. the monster has a brain to sense AND  */\
-      ((Blind && Blind_telepat) ||	/* 2a. hero is blind and telepathic OR	    */\
+    ((Blind && Blind_telepat && (distu(mon->mx, mon->my) <= u.u_telepathy_dist)) ||	/* 2a. hero is blind and telepathic OR	    */ \
 				/* 2b. hero is using a telepathy inducing   */\
 				/*	 object and in range		    */\
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/include/dungeon.h nethack/include/dungeon.h
--- nh_orig/include/dungeon.h	2003-12-07 18:39:13.000000000 -0500
+++ nethack/include/dungeon.h	2009-09-07 11:23:57.339293253 -0400
@@ -122,4 +122,8 @@
 #define Is_nemesis(x)		(on_level(x, &nemesis_level))
 #define Is_knox(x)		(on_level(x, &knox_level))
+#ifdef RECORD_ACHIEVE
+#define Is_mineend_level(x)     (on_level(x, &mineend_level))
+#define Is_sokoend_level(x)     (on_level(x, &sokoend_level))
+#endif
 
 #define In_sokoban(x)		((x)->dnum == sokoban_dnum)
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/include/eshk.h nethack/include/eshk.h
--- nh_orig/include/eshk.h	2003-12-07 18:39:13.000000000 -0500
+++ nethack/include/eshk.h	2009-11-23 13:59:51.796398963 -0500
@@ -43,3 +43,6 @@
 #define ANGRY(mon)	(!NOTANGRY(mon))
 
+#define match_shkrace(mon) ((urace.malenum == (mon)->mnum) || \
+				(urace.malenum == PM_ELF && (mon)->mnum == PM_GREEN_ELF))
+
 #endif /* ESHK_H */
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/include/extern.h nethack/include/extern.h
--- nh_orig/include/extern.h	2003-12-07 18:39:13.000000000 -0500
+++ nethack/include/extern.h	2010-08-16 13:20:13.101707800 -0400
@@ -26,4 +26,7 @@
 E void NDECL(newgame);
 E void FDECL(welcome, (BOOLEAN_P));
+#if defined(RECORD_REALTIME) || defined(REALTIME_ON_BOTL)
+E time_t NDECL(get_realtime);
+#endif
 
 /* ### apply.c ### */
@@ -132,4 +135,8 @@
 E const char *FDECL(rank_of, (int,SHORT_P,BOOLEAN_P));
 E void NDECL(bot);
+#ifdef DUMP_LOG
+E void FDECL(bot1str, (char *));
+E void FDECL(bot2str, (char *));
+#endif
 
 /* ### cmd.c ### */
@@ -167,4 +174,8 @@
 E void FDECL(enlightenment, (int));
 E void FDECL(show_conduct, (int));
+#ifdef DUMP_LOG
+E void FDECL(dump_enlightenment, (int));
+E void FDECL(dump_conduct, (int));
+#endif
 E int FDECL(xytod, (SCHAR_P,SCHAR_P));
 E void FDECL(dtoxy, (coord *,int));
@@ -243,4 +254,5 @@
 E void FDECL(rot_organic, (genericptr_t, long));
 E void FDECL(rot_corpse, (genericptr_t, long));
+E void NDECL(get_coal);
 #if 0
 E void FDECL(bury_monst, (struct monst *));
@@ -282,4 +294,7 @@
 E void NDECL(cls);
 E void FDECL(flush_screen, (int));
+#ifdef DUMP_LOG
+E void NDECL(dump_screen);
+#endif
 E int FDECL(back_to_glyph, (XCHAR_P,XCHAR_P));
 E int FDECL(zapdir_to_glyph, (int,int,int));
@@ -434,4 +449,6 @@
 /* ### dothrow.c ### */
 
+E int NDECL(boom_flightpath_menu);
+E struct monst * FDECL(camera_demon, (struct obj *,SCHAR_P, SCHAR_P));
 E int NDECL(dothrow);
 E int NDECL(dofire);
@@ -517,4 +534,5 @@
 E int NDECL(unfaint);
 #endif
+E char * FDECL(tin_content_text, (struct obj *));
 E boolean FDECL(is_edible, (struct obj *));
 E void NDECL(init_uhunger);
@@ -554,4 +572,8 @@
 E void FDECL(done, (int));
 E void FDECL(container_contents, (struct obj *,BOOLEAN_P,BOOLEAN_P));
+#ifdef DUMP_LOG
+E void FDECL(dump, (char *, char *));
+E void FDECL(do_containerconts, (struct obj *,BOOLEAN_P,BOOLEAN_P,BOOLEAN_P,BOOLEAN_P));
+#endif
 E void FDECL(terminate, (int));
 E int NDECL(num_genocides);
@@ -661,4 +683,12 @@
 E void NDECL(really_close);
 #endif
+#ifdef WHEREIS_FILE
+E void NDECL(touch_whereis);
+E void NDECL(delete_whereis);
+#endif
+#ifdef WISH_TRACKER
+E void FDECL(trackwish,(char *));
+E void FDECL(makeannounce,(char *));
+#endif
 
 /* ### fountain.c ### */
@@ -695,7 +725,8 @@
 E void NDECL(lookaround);
 E int NDECL(monster_nearby);
-E void FDECL(nomul, (int));
+E void FDECL(nomul, (int, const char *));
 E void FDECL(unmul, (const char *));
 E void FDECL(losehp, (int,const char *,BOOLEAN_P));
+E int FDECL(gainmaxhp, (int));
 E int NDECL(weight_cap);
 E int NDECL(inv_weight);
@@ -718,4 +749,6 @@
 E char *FDECL(upstart, (char *));
 E char *FDECL(mungspaces, (char *));
+E char *FDECL(stripctrl, (char *));
+E char *FDECL(trim, (char *));
 E char *FDECL(eos, (char *));
 E char *FDECL(strkitten, (char *,CHAR_P));
@@ -748,4 +781,5 @@
 E int NDECL(phase_of_the_moon);
 E boolean NDECL(friday_13th);
+E boolean NDECL(christmas);
 E int NDECL(night);
 E int NDECL(midnight);
@@ -791,4 +825,7 @@
 E int NDECL(ddoinv);
 E char FDECL(display_inventory, (const char *,BOOLEAN_P));
+#ifdef DUMP_LOG
+E char FDECL(dump_inventory, (const char *,BOOLEAN_P,BOOLEAN_P));
+#endif
 E int FDECL(display_binventory, (int,int,BOOLEAN_P));
 E struct obj *FDECL(display_cinventory,(struct obj *));
@@ -809,5 +846,5 @@
 E int NDECL(doprinuse);
 E void FDECL(useupf, (struct obj *,long));
-E char *FDECL(let_to_name, (CHAR_P,BOOLEAN_P));
+E char *FDECL(let_to_name, (CHAR_P,BOOLEAN_P,BOOLEAN_P));
 E void NDECL(free_invbuf);
 E void NDECL(reassign);
@@ -860,5 +897,5 @@
 E boolean FDECL(picking_at, (int,int));
 E void NDECL(reset_pick);
-E int FDECL(pick_lock, (struct obj *));
+E int FDECL(pick_lock, (struct obj *,int,int));
 E int NDECL(doforce);
 E boolean FDECL(boxlock, (struct obj *,struct obj *));
@@ -909,4 +946,5 @@
 /* ### mail.c ### */
 
+E void NDECL(ck_server_admin_msg);
 #ifdef MAIL
 # ifdef UNIX
@@ -953,4 +991,5 @@
 
 E int FDECL(fightm, (struct monst *));
+E boolean FDECL(resist_conflict, (struct monst *));
 E int FDECL(mattackm, (struct monst *,struct monst *));
 E int FDECL(noattacks, (struct permonst *));
@@ -996,6 +1035,7 @@
 E void FDECL(add_subroom, (struct mkroom *,int,int,int,int,
 			   BOOLEAN_P,SCHAR_P,BOOLEAN_P));
-E void NDECL(makecorridors);
+E void FDECL(makecorridors, (int));
 E void FDECL(add_door, (int,int,struct mkroom *));
+E void NDECL(mkpoolroom);
 E void NDECL(mklev);
 #ifdef SPECIALIZATION
@@ -1011,4 +1051,5 @@
 E void FDECL(mkstairs, (XCHAR_P,XCHAR_P,CHAR_P,struct mkroom *));
 E void NDECL(mkinvokearea);
+E void FDECL(wallwalk_right, (XCHAR_P,XCHAR_P,SCHAR_P,SCHAR_P,SCHAR_P,int));
 
 /* ### mkmap.c ### */
@@ -1020,5 +1061,6 @@
 
 E void FDECL(wallification, (int,int,int,int));
-E void FDECL(walkfrom, (int,int));
+E void FDECL(wall_extends, (int,int,int,int));
+E void FDECL(walkfrom, (int,int, SCHAR_P));
 E void FDECL(makemaz, (const char *));
 E void FDECL(mazexy, (coord *));
@@ -1072,4 +1114,5 @@
 E int FDECL(add_to_minv, (struct monst *, struct obj *));
 E struct obj *FDECL(add_to_container, (struct obj *, struct obj *));
+E long FDECL(get_container_weight, (struct obj *));
 E void FDECL(add_to_migration, (struct obj *));
 E void FDECL(add_to_buried, (struct obj *));
@@ -1083,4 +1126,5 @@
 /* ### mkroom.c ### */
 
+E struct mkroom * FDECL(pick_room,(BOOLEAN_P));
 E void FDECL(mkroom, (int));
 E void FDECL(fill_zoo, (struct mkroom *));
@@ -1100,4 +1144,5 @@
 /* ### mon.c ### */
 
+E void FDECL(remove_monster, (int, int));
 E int FDECL(undead_to_corpse, (int));
 E int FDECL(genus, (int,int));
@@ -1152,4 +1197,5 @@
 E boolean FDECL(angry_guards, (BOOLEAN_P));
 E void NDECL(pacify_guards);
+E boolean FDECL(damage_mon,(struct monst*,int,int));
 
 /* ### mondata.c ### */
@@ -1162,4 +1208,5 @@
 E boolean FDECL(resists_magm, (struct monst *));
 E boolean FDECL(resists_blnd, (struct monst *));
+E boolean FDECL(vulnerable_to, (struct monst *,int));
 E boolean FDECL(can_blnd, (struct monst *,struct monst *,UCHAR_P,struct obj *));
 E boolean FDECL(ranged_attk, (struct permonst *));
@@ -1212,4 +1259,5 @@
 /* ### mplayer.c ### */
 
+E const char *FDECL(elf_name, (size_t));
 E struct monst *FDECL(mk_mplayer, (struct permonst *,XCHAR_P,
 				   XCHAR_P,BOOLEAN_P));
@@ -1358,7 +1406,12 @@
 E boolean FDECL(the_unique_obj, (struct obj *obj));
 E char *FDECL(doname, (struct obj *));
+E char *FDECL(doname_with_price, (struct obj *));
 E boolean FDECL(not_fully_identified, (struct obj *));
 E char *FDECL(corpse_xname, (struct obj *,BOOLEAN_P));
 E char *FDECL(cxname, (struct obj *));
+E void FDECL(add_erosion_words, (struct obj *, char *));
+#ifdef SORTLOOT
+E char *FDECL(cxname2, (struct obj *));
+#endif
 E char *FDECL(killer_xname, (struct obj *));
 E const char *FDECL(singular, (struct obj *,char *(*)(OBJ_P)));
@@ -1406,4 +1459,7 @@
 E void NDECL(free_autopickup_exceptions);
 #endif /* AUTOPICKUP_EXCEPTIONS */
+#ifdef MENU_COLOR
+E boolean FDECL(add_menu_coloring, (char *));
+#endif /* MENU_COLOR */
 
 /* ### pager.c ### */
@@ -1544,4 +1600,8 @@
 E void FDECL(set_itimeout, (long *,long));
 E void FDECL(incr_itimeout, (long *,int));
+E void FDECL(incr_resistance, (long *,int));
+E void FDECL(decr_resistance, (long *,int));
+E int FDECL(how_resistant, (int));
+E int FDECL(resist_reduce, (int,int));
 E void FDECL(make_confused, (long,BOOLEAN_P));
 E void FDECL(make_stunned, (long,BOOLEAN_P));
@@ -1624,5 +1684,5 @@
 E void FDECL(com_pager, (int));
 E void FDECL(qt_pager, (int));
-E struct permonst *NDECL(qt_montype);
+E char *FDECL(string_subst, (char *));
 
 /* ### random.c ### */
@@ -1677,5 +1737,5 @@
 E void FDECL(save_regions, (int,int));
 E void FDECL(rest_regions, (int,BOOLEAN_P));
-E NhRegion* FDECL(create_gas_cloud, (XCHAR_P, XCHAR_P, int, int));
+E NhRegion* FDECL(create_gas_cloud, (XCHAR_P, XCHAR_P, int, size_t));
 
 /* ### restore.c ### */
@@ -1827,8 +1887,10 @@
 E void FDECL(check_unpaid, (struct obj *));
 E void FDECL(costly_gold, (XCHAR_P,XCHAR_P,long));
+E long FDECL(get_cost_of_shop_item, (struct obj *));
 E boolean FDECL(block_door, (XCHAR_P,XCHAR_P));
 E boolean FDECL(block_entry, (XCHAR_P,XCHAR_P));
 E char *FDECL(shk_your, (char *,struct obj *));
 E char *FDECL(Shk_Your, (char *,struct obj *));
+E void FDECL(shk_holler, (struct monst*));
 
 /* ### shknam.c ### */
@@ -1941,4 +2003,5 @@
 E void FDECL(tele_trap, (struct trap *));
 E void FDECL(level_tele_trap, (struct trap *));
+E boolean FDECL(rloc_pos_ok, (int,int,struct monst *));
 E void FDECL(rloc_to, (struct monst *,int,int));
 E boolean FDECL(rloc, (struct monst *, BOOLEAN_P));
@@ -1987,4 +2050,7 @@
 
 E void FDECL(topten, (int));
+#ifdef LOGFILE
+E void FDECL(write_log_entry, (int,long));
+#endif
 E void FDECL(prscore, (int,char **));
 E struct obj *FDECL(tt_oname, (struct obj *));
@@ -2238,4 +2304,7 @@
 E int NDECL(dbon);
 E int NDECL(enhance_weapon_skill);
+#ifdef DUMP_LOG
+E void NDECL(dump_weapon_skill);
+#endif
 E void FDECL(unrestrict_weapon_skill, (int));
 E void FDECL(use_skill, (int,int));
@@ -2260,8 +2329,10 @@
 E void FDECL(setuwep, (struct obj *));
 E void FDECL(setuqwep, (struct obj *));
+E void FDECL(setulauncher, (struct obj *));
 E void FDECL(setuswapwep, (struct obj *));
 E int NDECL(dowield);
 E int NDECL(doswapweapon);
 E int NDECL(dowieldquiver);
+E int NDECL(dowieldlauncher);
 E boolean FDECL(wield_tool, (struct obj *,const char *));
 E int NDECL(can_twoweapon);
@@ -2271,6 +2342,8 @@
 E void NDECL(uswapwepgone);
 E void NDECL(uqwepgone);
+E void NDECL(ulwepgone);
 E void NDECL(untwoweapon);
-E void FDECL(erode_obj, (struct obj *,BOOLEAN_P,BOOLEAN_P));
+E boolean FDECL(_erode_obj, (struct obj *,int));
+E void FDECL(erode_obj, (struct obj *,BOOLEAN_P,BOOLEAN_P,BOOLEAN_P));
 E int FDECL(chwepon, (struct obj *,int));
 E int FDECL(welded, (struct obj *));
@@ -2293,5 +2366,5 @@
 E void NDECL(clonewiz);
 E int NDECL(pick_nasty);
-E int FDECL(nasty, (struct monst*));
+E int FDECL(nasty, (struct monst*,BOOLEAN_P));
 E void NDECL(resurrect);
 E void NDECL(intervene);
@@ -2369,9 +2442,9 @@
 E struct monst *FDECL(bhit, (int,int,int,int,int (*)(MONST_P,OBJ_P),
 			     int (*)(OBJ_P,OBJ_P),struct obj *));
-E struct monst *FDECL(boomhit, (int,int));
+E struct monst *FDECL(boomhit, (int,int,int));
 E int FDECL(burn_floor_paper, (int,int,BOOLEAN_P,BOOLEAN_P));
 E void FDECL(buzz, (int,int,XCHAR_P,XCHAR_P,int,int));
 E void FDECL(melt_ice, (XCHAR_P,XCHAR_P));
-E int FDECL(zap_over_floor, (XCHAR_P,XCHAR_P,int,boolean *));
+E int FDECL(zap_over_floor, (XCHAR_P,XCHAR_P,int,boolean *,boolean));
 E void FDECL(fracture_rock, (struct obj *));
 E boolean FDECL(break_statue, (struct obj *));
@@ -2380,4 +2453,7 @@
 E int FDECL(resist, (struct monst *,CHAR_P,int,int));
 E void NDECL(makewish);
+E void FDECL(monstseesu,(unsigned long));
+E void FDECL(monstseesulose,(unsigned long));
+E void NDECL(blindingflash);
 
 #endif /* !MAKEDEFS_C && !LEV_LEX_C */
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/include/flag.h nethack/include/flag.h
--- nh_orig/include/flag.h	2003-12-07 18:39:13.000000000 -0500
+++ nethack/include/flag.h	2010-08-16 13:20:13.102707769 -0400
@@ -184,4 +184,10 @@
 	boolean  extmenu;	/* extended commands use menu interface */
 #endif
+#ifdef MENU_COLOR
+	boolean use_menu_color;	/* use color in menus; only if wc_color */
+#endif
+#if defined(STATUS_COLORS) && defined(TEXTCOLOR)
+	boolean use_status_colors; /* use color in status line; only if wc_color */
+#endif
 #ifdef MFLOPPY
 	boolean  checkspace;	/* check disk space before writing files */
@@ -217,4 +223,7 @@
 	boolean lan_mail_fetched; /* mail is awaiting display */
 #endif
+#ifdef SORTLOOT
+	char sortloot;          /* sort items to loot alphabetically */
+#endif
 /*
  * Window capability support.
@@ -264,4 +273,6 @@
 	boolean wc2_softkeyboard;	/* use software keyboard */
 	boolean wc2_wraptext;		/* wrap text */
+	boolean wc2_darkgray;		/* try to use PC dark-gray color
+					 * to represent black object */
 
 	boolean  cmdassist;	/* provide detailed assistance for some commands */
@@ -270,5 +281,11 @@
 	boolean  lootabc;	/* use "a/b/c" rather than "o/i/b" when looting */
 	boolean  showrace;	/* show hero glyph by race rather than by role */
+	boolean  showobjsym;	/* show object class symbol in menus where available */
 	boolean  travelcmd;	/* allow travel command */
+	boolean  show_dgn_name; /* show dungeon names instead of Dlvl: on bottom line
+										 probably only good for people taking advantage of 
+										 the wide terminals allowed in Spork */
+    int boom_flight_path; /* boomerang flight path */
+
 	int	 runmode;	/* update screen display during run moves */
 #ifdef AUTOPICKUP_EXCEPTIONS
@@ -281,4 +298,8 @@
 	char	 altkeyhandler[MAX_ALTKEYHANDLER];
 #endif
+#ifdef REALTIME_ON_BOTL
+  boolean  showrealtime; /* show actual elapsed time */
+#endif
+    boolean  dark_room;	/* show shadows in lit rooms */
 };
 
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/include/global.h nethack/include/global.h
--- nh_orig/include/global.h	2003-12-07 18:39:13.000000000 -0500
+++ nethack/include/global.h	2009-09-07 09:52:23.773293399 -0400
@@ -237,4 +237,8 @@
 #endif
 
+#ifdef OSX
+# define MENU_COLOR_REGEX_POSIX
+#endif
+
 #ifdef VMS
 /* vms_exit() (sys/vms/vmsmisc.c) expects the non-VMS EXIT_xxx values below.
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/include/hack.h nethack/include/hack.h
--- nh_orig/include/hack.h	2003-12-07 18:39:13.000000000 -0500
+++ nethack/include/hack.h	2009-08-02 13:49:33.029408334 -0400
@@ -19,5 +19,5 @@
 #define ON		1
 #define OFF		0
-#define BOLT_LIM	8 /* from this distance ranged attacks will be made */
+#define BOLT_LIM	16 /* from this distance ranged attacks may be made */
 #define MAX_CARR_CAP	1000	/* so that boulders can be heavier */
 #define DUMMY { 0 }
@@ -100,7 +100,8 @@
 #define FLASHED_LIGHT	3
 #define INVIS_BEAM	4
-
 #define MATCH_WARN_OF_MON(mon)	 (Warn_of_mon && flags.warntype && \
-		   		 (flags.warntype & (mon)->data->mflags2))
+		   		 ((flags.warntype == (unsigned long)(mon)->data->mlet) || \
+						(flags.warntype == S_WERE && (mon)->data->mflags2 & M2_WERE) || \
+					   (flags.warntype == S_UNDEAD && (mon)->data->mflags2 & M2_UNDEAD)))
 
 #include "trap.h"
@@ -142,4 +143,5 @@
 #define MM_IGNOREWATER	  0x80	/* ignore water when positioning */
 #define MM_ADJACENTOK	  0x100 /* it is acceptable to use adjacent coordinates */
+#define MM_UNSAFEOK		  0x200 /* potentially dangerous locations (lava) are OK */
 
 /* special mhpmax value when loading bones monster to flag as extinct or genocided */
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/include/mkroom.h nethack/include/mkroom.h
--- nh_orig/include/mkroom.h	2003-12-07 18:39:13.000000000 -0500
+++ nethack/include/mkroom.h	2009-12-03 16:14:46.415273207 -0500
@@ -12,4 +12,5 @@
 	schar rtype;		/* type of room (zoo, throne, etc...) */
 	schar rlit;		/* is the room lit ? */
+	schar needfill;		/* does the room need filling? */
 	schar doorct;		/* door count */
 	schar fdoor;		/* index for the first door of the room */
@@ -62,17 +63,19 @@
 #define COCKNEST	12	/* cockatrice nest (Tom Proudfoot) */
 #define ANTHOLE		13	/* ants (Tom Proudfoot) */
-#define SHOPBASE	14	/* everything above this is a shop */
-#define ARMORSHOP	15	/* specific shop defines for level compiler */
-#define SCROLLSHOP	16
-#define POTIONSHOP	17
-#define WEAPONSHOP	18
-#define FOODSHOP	19
-#define RINGSHOP	20
-#define WANDSHOP	21
-#define TOOLSHOP	22
-#define BOOKSHOP	23
-#define UNIQUESHOP	24	/* shops here & above not randomly gen'd. */
-#define CANDLESHOP	24
-#define MAXRTYPE	24	/* maximum valid room type */
+#define TRAPROOM	14
+#define POOLROOM	15
+#define SHOPBASE	16	/* everything above this is a shop */
+#define ARMORSHOP	17	/* specific shop defines for level compiler */
+#define SCROLLSHOP	18
+#define POTIONSHOP	19
+#define WEAPONSHOP	20
+#define FOODSHOP	21
+#define RINGSHOP	22
+#define WANDSHOP	23
+#define TOOLSHOP	24
+#define BOOKSHOP	25
+#define UNIQUESHOP	26	/* shops here & above not randomly gen'd. */
+#define CANDLESHOP	26
+#define MAXRTYPE	26	/* maximum valid room type */
 
 /* Special type for search_special() */
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/include/monattk.h nethack/include/monattk.h
--- nh_orig/include/monattk.h	2003-12-07 18:39:13.000000000 -0500
+++ nethack/include/monattk.h	2009-08-02 13:49:33.032408767 -0400
@@ -25,4 +25,5 @@
 #define AT_GAZE		15	/* gaze - ranged */
 #define AT_TENT		16	/* tentacles */
+#define AT_SCRE	   17 /* scream - sonic attack */
 
 #define AT_WEAP		254	/* uses weapon */
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/include/mondata.h nethack/include/mondata.h
--- nh_orig/include/mondata.h	2003-12-07 18:39:13.000000000 -0500
+++ nethack/include/mondata.h	2010-04-29 10:53:23.669716280 -0400
@@ -19,4 +19,6 @@
 #define resists_acid(mon)	(((mon)->mintrinsics & MR_ACID) != 0)
 #define resists_ston(mon)	(((mon)->mintrinsics & MR_STONE) != 0)
+#define resists_sick(mon)  ((mon)->data->mlet == S_FUNGUS || \
+										(mon)->data == &mons[PM_GHOUL])
 
 #define is_lminion(mon)		(is_minion((mon)->data) && \
@@ -27,4 +29,5 @@
 #define is_flyer(ptr)		(((ptr)->mflags1 & M1_FLY) != 0L)
 #define is_floater(ptr)		((ptr)->mlet == S_EYE)
+#define is_flying(mon)		((mon)->mflying != 0L)
 #define is_clinger(ptr)		(((ptr)->mflags1 & M1_CLING) != 0L)
 #define is_swimmer(ptr)		(((ptr)->mflags1 & M1_SWIM) != 0L)
@@ -69,4 +72,10 @@
 				 (ptr) == &mons[PM_MIND_FLAYER] || \
 				 (ptr) == &mons[PM_MASTER_MIND_FLAYER])
+#define gives_telepathy(ptr)	(telepathic((ptr)) ||		       \
+				 ((ptr) == &mons[PM_KOBOLD_SHAMAN]) || \
+				 ((ptr) == &mons[PM_GOBLIN_SHAMAN]) || \
+				 ((ptr) == &mons[PM_ORC_SHAMAN]) || \
+				 ((ptr) == &mons[PM_HILL_GIANT_SHAMAN]) || \
+				 ((ptr) == &mons[PM_GNOMISH_WIZARD]))
 #define is_armed(ptr)		attacktype(ptr, AT_WEAP)
 #define acidic(ptr)		(((ptr)->mflags1 & M1_ACID) != 0L)
@@ -128,4 +137,8 @@
 				 ((ptr) == &mons[PM_LONG_WORM_TAIL]))
 #define is_covetous(ptr)	((ptr->mflags3 & M3_COVETOUS))
+#define is_skittish(ptr)   ((ptr->mflags3 & M3_SKITTISH))
+#define is_accurate(ptr)   ((ptr->mflags3 & M3_EAGLEEYE))
+#define is_berserker(ptr)  ((ptr->mflags3 & M3_BERSERK))
+#define is_shopguard(ptr)  ((ptr->mflags3 & M3_SHOPGUARD))
 #define infravision(ptr)	((ptr->mflags3 & M3_INFRAVISION))
 #define infravisible(ptr)	((ptr->mflags3 & M3_INFRAVISIBLE))
@@ -147,4 +160,6 @@
 				  (ptr) == &mons[PM_FLAMING_SPHERE] || \
 				  (ptr) == &mons[PM_SHOCKING_SPHERE] || \
+				  (ptr) == &mons[PM_GOLD_DRAGON] || \
+				  (ptr) == &mons[PM_BABY_GOLD_DRAGON] || \
 				  (ptr) == &mons[PM_FIRE_VORTEX]) ? 1 : \
 				 ((ptr) == &mons[PM_FIRE_ELEMENTAL]) ? 1 : 0)
@@ -189,5 +204,10 @@
 
 #define befriend_with_obj(ptr, obj) ((obj)->oclass == FOOD_CLASS && \
-				     is_domestic(ptr))
+				(is_domestic(ptr) || (Role_if(PM_CAVEMAN) && (ptr) == &mons[PM_MASTODON]) || \
+				 ((obj)->otyp == BANANA && ((ptr) == &mons[PM_MONKEY] || (ptr) == &mons[PM_APE]))))
+
+#define is_rockbreaker(ptr)							\
+				(((ptr)->msound == MS_LEADER || is_rider((ptr))) && \
+				 !mtmp->mpeaceful)
 
 #endif /* MONDATA_H */
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/include/monflag.h nethack/include/monflag.h
--- nh_orig/include/monflag.h	2003-12-07 18:39:13.000000000 -0500
+++ nethack/include/monflag.h	2009-08-02 13:49:33.023408895 -0400
@@ -153,11 +153,19 @@
 #define M3_WAITFORU	0x0040		/* waits to see you or get attacked */
 #define M3_CLOSE	0x0080		/* lets you close unless attacked */
+/* Infravision is currently implemented for players only */
+#define M3_INFRAVISION	0x0100		/* has infravision */
+#define M3_INFRAVISIBLE 0x0200		/* visible by infravision */
+#define M3_SKITTISH  0x0400	   /* tends to stay a few squares away from you */
+#define M3_EAGLEEYE  0x0800		/* gets an accuracy bonus to hit */
+#define M3_BERSERK   0x1000	   /* extremely indiscriminate in its attacks */
+#define M3_SHOPGUARD	0x2000	   /* Guardian for a shop */
 
 #define M3_COVETOUS	0x001f		/* wants something */
 #define M3_WAITMASK	0x00c0		/* waiting... */
 
-/* Infravision is currently implemented for players only */
-#define M3_INFRAVISION	0x0100		/* has infravision */
-#define M3_INFRAVISIBLE 0x0200		/* visible by infravision */
+#define M4_VULNERABLE_FIRE		0x0001	 /* inherent elemental vulnerabilities */
+#define M4_VULNERABLE_COLD		0x0002
+#define M4_VULNERABLE_ELEC		0x0004
+#define M4_VULNERABLE_ACID		0x0008
 
 #define MZ_TINY		0		/* < 2' */
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/include/monst.h nethack/include/monst.h
--- nh_orig/include/monst.h	2003-12-07 18:39:13.000000000 -0500
+++ nethack/include/monst.h	2009-09-07 11:18:19.719417264 -0400
@@ -41,5 +41,5 @@
 	struct monst *nmon;
 	struct permonst *data;
-	unsigned m_id;
+	size_t m_id;
 	short mnum;		/* permanent monster index number */
 	short movement;		/* movement points (derived from permonst definition and added effects */
@@ -64,4 +64,24 @@
 	int mspec_used;		/* monster's special ability attack timeout */
 
+/* These should stay in the same order as monattk.h so
+ * the mask translations will work properly */
+
+#define M_SEEN_NOTHING	0x0000
+#define M_SEEN_MAGR		0x0001
+#define M_SEEN_FIRE		0x0002
+#define M_SEEN_COLD		0x0004
+#define M_SEEN_SLEEP		0x0008
+#define M_SEEN_DISINT	0x0010
+#define M_SEEN_ELEC		0x0020
+#define M_SEEN_POISON	0x0040
+#define M_SEEN_ACID	 	0x0080
+#define M_SEEN_REFL		0x0100
+
+#define m_seenres(mon,mask)	((mon)->seen_resistance & (mask))
+#define m_setseen(mon,mask)	((mon)->seen_resistance |= (mask))
+#define m_sawlose(mon,mask)	((mon)->seen_resistance &= (~mask))
+
+	unsigned long seen_resistance;  /* Has seen you resist an element or magical effect */
+
 	Bitfield(female,1);	/* is female */
 	Bitfield(minvis,1);	/* currently invisible */
@@ -96,4 +116,5 @@
 	Bitfield(mcanmove,1);	/* paralysis, similar to mblinded */
 	Bitfield(mfrozen,7);
+	Bitfield(mflying,1);	  /* is monster levitating/flying artificially? */
 
 	Bitfield(msleeping,1);	/* asleep until woken */
@@ -103,7 +124,10 @@
 	Bitfield(mtrapped,1);	/* trapped in a pit, web or bear trap */
 	Bitfield(mleashed,1);	/* monster is on a leash */
+	Bitfield(mberserk,1);    /* monster is berserk */
+
 	Bitfield(isshk,1);	/* is shopkeeper */
 	Bitfield(isminion,1);	/* is a minion */
 
+	Bitfield(isshopguard,1);	 /* monster is a shop guard */
 	Bitfield(isgd,1);	/* is guard */
 	Bitfield(ispriest,1);	/* is a priest */
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/include/monsym.h nethack/include/monsym.h
--- nh_orig/include/monsym.h	2003-12-07 18:39:13.000000000 -0500
+++ nethack/include/monsym.h	2009-08-02 13:49:33.040407823 -0400
@@ -74,4 +74,7 @@
 #define MAXMCLASSES 61	/* number of monster classes */
 
+#define S_WERE		100	/* don't include this in MAXMCLASSES, it's a hack for warning */
+#define S_UNDEAD	101	/* etc */
+
 #if 0	/* moved to decl.h so that makedefs.c won't see them */
 extern const char def_monsyms[MAXMCLASSES];	/* default class symbols */
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/include/objclass.h nethack/include/objclass.h
--- nh_orig/include/objclass.h	2003-12-07 18:39:13.000000000 -0500
+++ nethack/include/objclass.h	2010-04-25 13:07:29.176715584 -0400
@@ -71,4 +71,5 @@
 /* is_flammable(otmp), is_rottable(otmp) in mkobj.c */
 #define is_rustprone(otmp)	(objects[otmp->otyp].oc_material == IRON)
+#define is_meltable(otmp)	(objects[otmp->otyp].oc_material == COPPER || objects[otmp->otyp].oc_material == GOLD)
 
 /* secondary damage: rot/acid/acid */
@@ -140,5 +141,6 @@
 #define CHAIN_CLASS	16
 #define VENOM_CLASS	17
-#define MAXOCLASSES	18
+#define FURNITURE_CLASS	18
+#define MAXOCLASSES	19
 
 #define ALLOW_COUNT	(MAXOCLASSES+1) /* Can be used in the object class */
@@ -148,4 +150,5 @@
 #define BURNING_OIL	(MAXOCLASSES+1) /* Can be used as input to explode. */
 #define MON_EXPLODE	(MAXOCLASSES+2) /* Exploding monster (e.g. gas spore) */
+#define MON_CASTBALL	(MAXOCLASSES+3) /* For monsters casting area-effect spells */
 
 #if 0	/* moved to decl.h so that makedefs.c won't see them */
@@ -173,4 +176,5 @@
 #define CHAIN_SYM	'_'
 #define VENOM_SYM	'.'
+#define FURNITURE_SYM	'\\'
 
 struct fruit {
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/include/obj.h nethack/include/obj.h
--- nh_orig/include/obj.h	2003-12-07 18:39:13.000000000 -0500
+++ nethack/include/obj.h	2010-05-13 09:22:22.141715011 -0400
@@ -23,5 +23,5 @@
 
 	struct obj *cobj;	/* contents list for containers */
-	unsigned o_id;
+	size_t o_id;
 	xchar ox,oy;
 	short otyp;		/* object class number */
@@ -67,4 +67,6 @@
 	Bitfield(oeroded2,2);	/* corroded/rotted weapon/armor */
 #define greatest_erosion(otmp) (int)((otmp)->oeroded > (otmp)->oeroded2 ? (otmp)->oeroded : (otmp)->oeroded2)
+#define set_erodeproof(otmp) { (otmp)->oeroded = (otmp)->oeroded2 = 0; (otmp)->oerodeproof = TRUE; }
+
 #define MAX_ERODE 3
 #define orotten oeroded		/* rotten food */
@@ -98,6 +100,13 @@
 #define spestudied corpsenm	/* # of times a spellbook has been studied */
 #define fromsink  corpsenm	/* a potion from a sink */
+
+#ifdef RECORD_ACHIEVE
+#define record_achieve_special corpsenm
+#endif
+
 	unsigned oeaten;	/* nutrition left in food, if partly eaten */
 	long age;		/* creation date */
+	long capacity;	  /* how much can this container hold? */
+#define MAX_CAPACITY 0xFFFFFF	  /* "lots" */
 
 	uchar onamelth;		/* length of name (following oxlth) */
@@ -139,6 +148,5 @@
 #define is_pole(otmp)	((otmp->oclass == WEAPON_CLASS || \
 			otmp->oclass == TOOL_CLASS) && \
-			 (objects[otmp->otyp].oc_skill == P_POLEARMS || \
-			 objects[otmp->otyp].oc_skill == P_LANCE))
+			 (objects[otmp->otyp].oc_skill == P_POLEARMS))
 #define is_spear(otmp)	(otmp->oclass == WEAPON_CLASS && \
 			 objects[otmp->otyp].oc_skill >= P_SPEAR && \
@@ -158,4 +166,11 @@
 			 objects[otmp->otyp].oc_skill >= -P_BOOMERANG && \
 			 objects[otmp->otyp].oc_skill <= -P_DART)
+#define is_thrown(otmp)	  ((otmp->oclass == WEAPON_CLASS) && \
+		  ((objects[otmp->otyp].oc_skill >= P_DART && \
+			 objects[otmp->otyp].oc_skill <= P_BOOMERANG) || \
+			 objects[otmp->otyp].oc_skill == P_DAGGER || \
+			 objects[otmp->otyp].oc_skill == P_KNIFE || \
+			(objects[otmp->otyp].oc_skill >= P_SPEAR && \
+			 objects[otmp->otyp].oc_skill <= P_TRIDENT)))
 #define is_weptool(o)	((o)->oclass == TOOL_CLASS && \
 			 objects[(o)->otyp].oc_skill != P_NONE)
@@ -218,6 +233,7 @@
 #define Has_contents(o) (/* (Is_container(o) || (o)->otyp == STATUE) && */ \
 			 (o)->cobj != (struct obj *)0)
-#define Is_container(o) ((o)->otyp >= LARGE_BOX && (o)->otyp <= BAG_OF_TRICKS)
-#define Is_box(otmp)	(otmp->otyp == LARGE_BOX || otmp->otyp == CHEST)
+#define Is_container(o) ((o)->otyp >= LARGE_BOX && (o)->otyp <= BAG_OF_POO)
+#define Is_box(otmp)	(otmp->otyp == LARGE_BOX || otmp->otyp == CHEST || \
+								otmp->otyp == IRON_SAFE)
 #define Is_mbag(otmp)	(otmp->otyp == BAG_OF_HOLDING || \
 			 otmp->otyp == BAG_OF_TRICKS)
@@ -273,5 +289,6 @@
 				|| (otmp)->otyp == TALLOW_CANDLE\
 				|| (otmp)->otyp == WAX_CANDLE\
-				|| (otmp)->otyp == POT_OIL)
+				|| (otmp)->otyp == POT_OIL\
+				|| (otmp)->otyp == BAG_OF_POO)
 /* object can be ignited */
 #define ignitable(otmp)	((otmp)->otyp == BRASS_LANTERN\
@@ -280,11 +297,12 @@
 				|| (otmp)->otyp == TALLOW_CANDLE\
 				|| (otmp)->otyp == WAX_CANDLE\
-				|| (otmp)->otyp == POT_OIL)
+				|| (otmp)->otyp == POT_OIL\
+				|| (otmp)->otyp == FUR_BRAZIER\
+				|| (otmp)->otyp == BAG_OF_POO)
 
 /* special stones */
 #define is_graystone(obj)	((obj)->otyp == LUCKSTONE || \
-				 (obj)->otyp == LOADSTONE || \
-				 (obj)->otyp == FLINT     || \
-				 (obj)->otyp == TOUCHSTONE)
+				 (obj)->otyp == LOADSTONE || (obj)->otyp == FLINT     || \
+				 (obj)->otyp == TOUCHSTONE || (obj)->otyp == SALT_CHUNK)
 
 /* misc */
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/include/patchlevel.h nethack/include/patchlevel.h
--- nh_orig/include/patchlevel.h	2003-12-07 18:39:13.000000000 -0500
+++ nethack/include/patchlevel.h	2010-04-29 11:10:56.036011963 -0400
@@ -3,7 +3,7 @@
 /* NetHack may be freely redistributed.  See license for details. */
 
-/* NetHack 3.4.3 */
-#define VERSION_MAJOR	3
-#define VERSION_MINOR	4
+/* SporkHack 0.3.0 */
+#define VERSION_MAJOR	0
+#define VERSION_MINOR	6
 /*
  * PATCHLEVEL is updated for each release.
@@ -17,8 +17,8 @@
 
 #define COPYRIGHT_BANNER_A \
-"NetHack, Copyright 1985-2003"
+"SporkHack, copyright 2007 Derek S. Ray; a variant of NetHack 3.4.3, "
 
 #define COPYRIGHT_BANNER_B \
-"         By Stichting Mathematisch Centrum and M. Stephenson."
+"  copyright 1985-2003 by Stichting Mathematisch Centrum and M. Stephenson."
 
 #define COPYRIGHT_BANNER_C \
@@ -34,5 +34,7 @@
  * with all four numbers specified as two hexadecimal digits.
  */
-#define VERSION_COMPATIBILITY 0x03040000L	/* 3.4.0-0 */
+
+/*                            0xMMmmPPeeL            */
+#define VERSION_COMPATIBILITY 0x00060300L	/* 0.6.1-0 */
 
 
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/include/permonst.h nethack/include/permonst.h
--- nh_orig/include/permonst.h	2003-12-07 18:39:13.000000000 -0500
+++ nethack/include/permonst.h	2009-09-13 08:38:18.966292366 -0400
@@ -56,7 +56,8 @@
 	uchar		mresists;		/* resistances */
 	uchar		mconveys;		/* conveyed by eating */
-	unsigned long	mflags1,		/* boolean bitflags */
-			mflags2;		/* more boolean bitflags */
-	unsigned short	mflags3;		/* yet more boolean bitflags */
+	unsigned long	mflags1;		/* boolean bitflags */
+	unsigned long  mflags2;		/* more boolean bitflags */
+	unsigned long	mflags3;		/* yet more boolean bitflags */
+	unsigned long	mflags4;	  /* Add room for more */
 # ifdef TEXTCOLOR
 	uchar		mcolor;			/* color to use */
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/include/prop.h nethack/include/prop.h
--- nh_orig/include/prop.h	2003-12-07 18:39:13.000000000 -0500
+++ nethack/include/prop.h	2009-09-05 10:47:01.555291838 -0400
@@ -74,5 +74,14 @@
 #define WARN_OF_MON		65
 #define DETECT_MONSTERS		66
-#define LAST_PROP		(DETECT_MONSTERS)
+#define WERE_RES			67
+#define BLIND_RES			68
+#define SLOW				69
+#define VISION				70
+#define LUCKY				71
+#define VULN_FIRE			72
+#define VULN_COLD			73
+#define VULN_ELEC			74
+#define VULN_ACID			75
+#define LAST_PROP		 	(VULN_ACID)
 
 /*** Where the properties come from ***/
@@ -100,4 +109,5 @@
 #	define W_ART	    0x00001000L /* Carrying artifact (not really worn) */
 #	define W_ARTI	    0x00002000L /* Invoked artifact  (not really worn) */
+#  define W_LAUNCHER  0x00004000L /* Selected ranged launcher */
 	/* Amulets, rings, tools, and other items */
 #	define W_AMUL	    0x00010000L /* Amulet */
@@ -123,5 +133,6 @@
 #	define FROMRACE     0x02000000L /* Gain/lose with experience, for race */
 #	define FROMOUTSIDE  0x04000000L /* By corpses, prayer, thrones, etc. */
-#	define INTRINSIC    (FROMOUTSIDE|FROMRACE|FROMEXPER)
+#  define HAVEPARTIAL  0x08000000L /* This is no longer a timeout, but a partial resistance */
+#	define INTRINSIC    (FROMOUTSIDE|FROMRACE|FROMEXPER|HAVEPARTIAL)
 	/* Control flags */
 #	define I_SPECIAL    0x10000000L /* Property is controllable */
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/include/rm.h nethack/include/rm.h
--- nh_orig/include/rm.h	2003-12-07 18:39:13.000000000 -0500
+++ nethack/include/rm.h	2010-05-14 11:22:24.447714895 -0400
@@ -31,42 +31,42 @@
 
 /* Level location types */
-#define STONE		0
-#define VWALL		1
-#define HWALL		2
-#define TLCORNER	3
-#define TRCORNER	4
-#define BLCORNER	5
-#define BRCORNER	6
-#define CROSSWALL	7	/* For pretty mazes and special levels */
-#define TUWALL		8
-#define TDWALL		9
-#define TLWALL		10
-#define TRWALL		11
-#define DBWALL		12
-#define TREE		13	/* KMH */
-#define SDOOR		14
-#define SCORR		15
-#define POOL		16
-#define MOAT		17	/* pool that doesn't boil, adjust messages */
-#define WATER		18
-#define DRAWBRIDGE_UP	19
-#define LAVAPOOL	20
-#define IRONBARS	21	/* KMH */
-#define DOOR		22
-#define CORR		23
-#define ROOM		24
-#define STAIRS		25
-#define LADDER		26
-#define FOUNTAIN	27
-#define THRONE		28
-#define SINK		29
-#define GRAVE		30
-#define ALTAR		31
-#define ICE		32
-#define DRAWBRIDGE_DOWN 33
-#define AIR		34
-#define CLOUD		35
-
-#define MAX_TYPE	36
+enum {
+    STONE = 0,
+    VWALL,
+    HWALL,
+    TLCORNER,
+    TRCORNER,
+    BLCORNER,
+    BRCORNER,
+    CROSSWALL,		/* For pretty mazes and special levels */
+    TUWALL,
+    TDWALL,
+    TLWALL,
+    TRWALL,
+    DBWALL,
+    TREE,			/* KMH */
+    SDOOR,
+    SCORR,
+    POOL,
+    MOAT,			/* pool that doesn't boil, adjust messages */
+    WATER,
+    DRAWBRIDGE_UP,
+    LAVAPOOL,
+    IRONBARS,		/* KMH */
+    DOOR,
+    CORR,
+    ROOM,
+    STAIRS,
+    LADDER,
+    FOUNTAIN,
+    SINK,
+    GRAVE,
+    ALTAR,
+    ICE,
+    DRAWBRIDGE_DOWN,
+    AIR,
+    CLOUD,
+    MAX_TYPE
+};
 #define INVALID_TYPE	127
 
@@ -87,5 +87,4 @@
 #define SPACE_POS(typ)	((typ) > DOOR)
 #define IS_POOL(typ)	((typ) >= POOL && (typ) <= DRAWBRIDGE_UP)
-#define IS_THRONE(typ)	((typ) == THRONE)
 #define IS_FOUNTAIN(typ) ((typ) == FOUNTAIN)
 #define IS_SINK(typ)	((typ) == SINK)
@@ -104,113 +103,117 @@
 
 /* begin dungeon characters */
-
-#define S_stone		0
-#define S_vwall		1
-#define S_hwall		2
-#define S_tlcorn	3
-#define S_trcorn	4
-#define S_blcorn	5
-#define S_brcorn	6
-#define S_crwall	7
-#define S_tuwall	8
-#define S_tdwall	9
-#define S_tlwall	10
-#define S_trwall	11
-#define S_ndoor		12
-#define S_vodoor	13
-#define S_hodoor	14
-#define S_vcdoor	15	/* closed door, vertical wall */
-#define S_hcdoor	16	/* closed door, horizontal wall */
-#define S_bars		17	/* KMH -- iron bars */
-#define S_tree		18	/* KMH */
-#define S_room		19
-#define S_corr		20
-#define S_litcorr	21
-#define S_upstair	22
-#define S_dnstair	23
-#define S_upladder	24
-#define S_dnladder	25
-#define S_altar		26
-#define S_grave		27
-#define S_throne	28
-#define S_sink		29
-#define S_fountain	30
-#define S_pool		31
-#define S_ice		32
-#define S_lava		33
-#define S_vodbridge	34
-#define S_hodbridge	35
-#define S_vcdbridge	36	/* closed drawbridge, vertical wall */
-#define S_hcdbridge	37	/* closed drawbridge, horizontal wall */
-#define S_air		38
-#define S_cloud		39
-#define S_water		40
+enum {
+    S_stone = 0,
+    S_vwall,
+    S_hwall,
+    S_tlcorn,
+    S_trcorn,
+    S_blcorn,
+    S_brcorn,
+    S_crwall,
+    S_tuwall,
+    S_tdwall,
+    S_tlwall,
+    S_trwall,
+    S_ndoor,
+    S_vodoor,
+    S_hodoor,
+    S_vcdoor,		/* closed door, vertical wall */
+    S_hcdoor,		/* closed door, horizontal wall */
+    S_bars,		/* KMH -- iron bars */
+    S_tree,		/* KMH */
+    S_room,
+    S_darkroom,
+    S_corr,
+    S_litcorr,
+    S_upstair,
+    S_dnstair,
+    S_upladder,
+    S_dnladder,
+    S_altar,
+    S_grave,
+    S_sink,
+    S_fountain,
+    S_pool,
+    S_ice,
+    S_lava,
+    S_vodbridge,
+    S_hodbridge,
+    S_vcdbridge,       	/* closed drawbridge, vertical wall */
+    S_hcdbridge,	/* closed drawbridge, horizontal wall */
+    S_air,
+    S_cloud,
+    S_water,
 
 /* end dungeon characters, begin traps */
 
-#define S_arrow_trap		41
-#define S_dart_trap		42
-#define S_falling_rock_trap	43
-#define S_squeaky_board		44
-#define S_bear_trap		45
-#define S_land_mine		46
-#define S_rolling_boulder_trap	47
-#define S_sleeping_gas_trap	48
-#define S_rust_trap		49
-#define S_fire_trap		50
-#define S_pit			51
-#define S_spiked_pit		52
-#define S_hole			53
-#define S_trap_door		54
-#define S_teleportation_trap	55
-#define S_level_teleporter	56
-#define S_magic_portal		57
-#define S_web			58
-#define S_statue_trap		59
-#define S_magic_trap		60
-#define S_anti_magic_trap	61
-#define S_polymorph_trap	62
+    S_arrow_trap,
+    S_dart_trap,
+    S_falling_rock_trap,
+    S_squeaky_board,
+    S_bear_trap,
+    S_land_mine,
+    S_rolling_boulder_trap,
+    S_sleeping_gas_trap,
+    S_rust_trap,
+    S_fire_trap,
+    S_pit,
+    S_spiked_pit,
+    S_hole,
+    S_trap_door,
+    S_teleportation_trap,
+    S_level_teleporter,
+    S_magic_portal,
+    S_web,
+    S_statue_trap,
+    S_magic_trap,
+    S_anti_magic_trap,
+    S_polymorph_trap,
+    S_spear_trap,
+    S_falling_rocks_trap,
+    S_magic_beam_trap,
 
 /* end traps, begin special effects */
 
-#define S_vbeam		63	/* The 4 zap beam symbols.  Do NOT separate. */
-#define S_hbeam		64	/* To change order or add, see function     */
-#define S_lslant	65	/* zapdir_to_glyph() in display.c.	    */
-#define S_rslant	66
-#define S_digbeam	67	/* dig beam symbol */
-#define S_flashbeam	68	/* camera flash symbol */
-#define S_boomleft	69	/* thrown boomerang, open left, e.g ')'    */
-#define S_boomright	70	/* thrown boomerand, open right, e.g. '('  */
-#define S_ss1		71	/* 4 magic shield glyphs */
-#define S_ss2		72
-#define S_ss3		73
-#define S_ss4		74
+    S_vbeam,		/* The 4 zap beam symbols.  Do NOT separate. */
+    S_hbeam,		/* To change order or add, see function     */
+    S_lslant,		/* zapdir_to_glyph() in display.c.	    */
+    S_rslant,
+    S_digbeam,		/* dig beam symbol */
+    S_flashbeam,	/* camera flash symbol */
+    S_boomleft,		/* thrown boomerang, open left, e.g ')'    */
+    S_boomright,	/* thrown boomerand, open right, e.g. '('  */
+    S_ss1,		/* 4 magic shield glyphs */
+    S_ss2,
+    S_ss3,
+    S_ss4,
 
 /* The 8 swallow symbols.  Do NOT separate.  To change order or add, see */
 /* the function swallow_to_glyph() in display.c.			 */
-#define S_sw_tl		75	/* swallow top left [1]			*/
-#define S_sw_tc		76	/* swallow top center [2]	Order:	*/
-#define S_sw_tr		77	/* swallow top right [3]		*/
-#define S_sw_ml		78	/* swallow middle left [4]	1 2 3	*/
-#define S_sw_mr		79	/* swallow middle right [6]	4 5 6	*/
-#define S_sw_bl		80	/* swallow bottom left [7]	7 8 9	*/
-#define S_sw_bc		81	/* swallow bottom center [8]		*/
-#define S_sw_br		82	/* swallow bottom right [9]		*/
+    S_sw_tl,			/* swallow top left [1]			*/
+    S_sw_tc,			/* swallow top center [2]	Order:	*/
+    S_sw_tr,			/* swallow top right [3]		*/
+    S_sw_ml,			/* swallow middle left [4]	1 2 3	*/
+    S_sw_mr,			/* swallow middle right [6]	4 5 6	*/
+    S_sw_bl,			/* swallow bottom left [7]	7 8 9	*/
+    S_sw_bc,			/* swallow bottom center [8]		*/
+    S_sw_br,			/* swallow bottom right [9]		*/
 
-#define S_explode1	83	/* explosion top left			*/
-#define S_explode2	84	/* explosion top center			*/
-#define S_explode3	85	/* explosion top right		 Ex.	*/
-#define S_explode4	86	/* explosion middle left		*/
-#define S_explode5	87	/* explosion middle center	 /-\	*/
-#define S_explode6	88	/* explosion middle right	 |@|	*/
-#define S_explode7	89	/* explosion bottom left	 \-/	*/
-#define S_explode8	90	/* explosion bottom center		*/
-#define S_explode9	91	/* explosion bottom right		*/
+    S_explode1,		/* explosion top left			*/
+    S_explode2,		/* explosion top center			*/
+    S_explode3,		/* explosion top right		 Ex.	*/
+    S_explode4,		/* explosion middle left		*/
+    S_explode5,		/* explosion middle center	 /-\	*/
+    S_explode6,		/* explosion middle right	 |@|	*/
+    S_explode7,		/* explosion bottom left	 \-/	*/
+    S_explode8,		/* explosion bottom center		*/
+    S_explode9,		/* explosion bottom right		*/
 
 /* end effects */
 
-#define MAXPCHARS	92	/* maximum number of mapped characters */
+    MAXPCHARS		/* maximum number of mapped characters */
+};
 #define MAXDCHARS	41	/* maximum of mapped dungeon characters */
-#define MAXTCHARS	22	/* maximum of mapped trap characters */
+#define MAXTCHARS	25	/* maximum of mapped trap characters */
 #define MAXECHARS	29	/* maximum of mapped effects characters */
 #define MAXEXPCHARS	9	/* number of explosion characters */
@@ -246,4 +249,5 @@
 #define D_LOCKED	8
 #define D_TRAPPED	16
+#define D_SECRET	32 /* only used by sp_lev.c, NOT in rm-struct */
 
 /*
@@ -253,9 +257,4 @@
 
 /*
- * Thrones should only be looted once.
- */
-#define T_LOOTED	1
-
-/*
  * Trees have more than one kick result.
  */
@@ -343,4 +342,15 @@
 };
 
+
+#define SET_TYPLIT(x,y,ttyp,llit)				\
+{								\
+    if ((ttyp) < MAX_TYPE) levl[(x)][(y)].typ = (ttyp);		\
+    if ((ttyp) == LAVAPOOL) levl[(x)][(y)].lit = 1;		\
+    else if ((schar)(llit) != -2) {				\
+	if ((schar)(llit) == -1) levl[(x)][(y)].lit = rn2(2);	\
+	else levl[(x)][(y)].lit = (llit);			\
+    }								\
+}
+
 /*
  * Add wall angle viewing by defining "modes" for each wall type.  Each
@@ -463,7 +473,39 @@
 	Bitfield(graveyard,1);		/* has_morgue, but remains set */
 	Bitfield(is_maze_lev,1);
+	Bitfield(stormy,1);		/* thunderous clouds */
 
 	Bitfield(is_cavernous_lev,1);
 	Bitfield(arboreal, 1);		/* Trees replace rock */
+	/* and where it is written "ad aquarium"... */
+	Bitfield(vault_is_aquarium,1);
+};
+
+struct mon_gen_tuple {
+    int freq;
+    boolean is_sym;
+    int monid;
+    struct mon_gen_tuple *next;
+};
+
+struct mon_gen_override {
+    int override_chance;
+    int total_mon_freq;
+    struct mon_gen_tuple *gen_chances;
+};
+
+#define LVLSND_HEARD	0	/* You_hear(msg); */
+#define LVLSND_PLINED	1	/* pline(msg); */
+#define LVLSND_VERBAL	2	/* verbalize(msg); */
+#define LVLSND_FELT	3	/* You_feel(msg); */
+
+struct lvl_sound_bite {
+    int flags; /* LVLSND_foo */
+    char *msg;
+};
+
+struct lvl_sounds {
+    int freq;
+    int n_sounds;
+    struct lvl_sound_bite *sounds;
 };
 
@@ -485,4 +527,6 @@
     struct damage	*damagelist;
     struct levelflags	flags;
+    struct mon_gen_override *mon_gen;
+    struct lvl_sounds	*sounds;
 }
 dlevel_t;
@@ -513,10 +557,5 @@
 #define MON_BURIED_AT(x,y)	(level.monsters[x][y] != (struct monst *)0 && \
 				(level.monsters[x][y])->mburied)
-#ifndef STEED
-#define place_monster(m,x,y)	((m)->mx=(x),(m)->my=(y),\
-				 level.monsters[(m)->mx][(m)->my]=(m))
-#endif
 #define place_worm_seg(m,x,y)	level.monsters[x][y] = m
-#define remove_monster(x,y)	level.monsters[x][y] = (struct monst *)0
 #define m_at(x,y)		(MON_AT(x,y) ? level.monsters[x][y] : \
 						(struct monst *)0)
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/include/sp_lev.h nethack/include/sp_lev.h
--- nh_orig/include/sp_lev.h	2003-12-07 18:39:13.000000000 -0500
+++ nethack/include/sp_lev.h	2010-04-26 14:12:02.404715531 -0400
@@ -18,13 +18,262 @@
 
     /* Per level flags */
-#define NOTELEPORT	1
-#define HARDFLOOR	2
-#define NOMMAP		4
-#define SHORTSIGHTED	8
-#define ARBOREAL	16
+#define NOTELEPORT	0x00000001L
+#define HARDFLOOR	0x00000002L
+#define NOMMAP		0x00000004L
+#define SHORTSIGHTED	0x00000008L
+#define ARBOREAL	0x00000010L
+#define NOFLIPX		0x00000020L
+#define NOFLIPY		0x00000040L
+#define MAZELEVEL	0x00000080L
+#define PREMAPPED	0x00000100L
+#define SHROUD		0x00000200L
+#define STORMY		0x00000400L
+#define GRAVEYARD	0x00000800L
 
-    /* special level types */
-#define SP_LEV_ROOMS	1
-#define SP_LEV_MAZE	2
+/* different level layout initializers */
+#define LVLINIT_NONE		0
+#define LVLINIT_SOLIDFILL	1
+#define LVLINIT_MAZEGRID	2
+#define LVLINIT_MINES		3
+
+/* max. layers of object containment */
+#define MAX_CONTAINMENT 10
+
+/* max. # of random registers */
+#define MAX_REGISTERS	10
+
+/* max. nested depth of subrooms */
+#define MAX_NESTED_ROOMS 5
+
+/* max. # of opcodes per special level */
+#define SPCODER_MAX_RUNTIME	65536
+
+/* Opcodes for creating the level
+ * If you change these, also change opcodestr[] in util/lev_main.c
+ */
+enum opcode_defs {
+    SPO_NULL = 0,
+    SPO_MESSAGE,
+    SPO_MONSTER,
+    SPO_OBJECT,
+    SPO_ENGRAVING,
+    SPO_ROOM,
+    SPO_SUBROOM,
+    SPO_DOOR,
+    SPO_STAIR,
+    SPO_LADDER,
+    SPO_ALTAR,
+    SPO_FOUNTAIN,
+    SPO_SINK,
+    SPO_POOL,
+    SPO_TRAP,
+    SPO_GOLD,
+    SPO_CORRIDOR,
+    SPO_LEVREGION,
+    SPO_DRAWBRIDGE,
+    SPO_MAZEWALK,
+    SPO_NON_DIGGABLE,
+    SPO_NON_PASSWALL,
+    SPO_WALLIFY,
+    SPO_MAP,
+    SPO_ROOM_DOOR,
+    SPO_REGION,
+    SPO_CMP,
+    SPO_JMP,
+    SPO_JL,
+    SPO_JLE,
+    SPO_JG,
+    SPO_JGE,
+    SPO_JE,
+    SPO_JNE,
+    SPO_SPILL,
+    SPO_TERRAIN,
+    SPO_REPLACETERRAIN,
+    SPO_EXIT,
+    SPO_ENDROOM,
+    SPO_POP_CONTAINER,
+    SPO_PUSH,
+    SPO_POP,
+    SPO_RN2,
+    SPO_DEC,
+    SPO_INC,
+    SPO_MATH_ADD,
+    SPO_MATH_SUB,
+    SPO_MATH_MUL,
+    SPO_MATH_DIV,
+    SPO_MATH_MOD,
+    SPO_COPY,
+    SPO_MON_GENERATION,
+    SPO_END_MONINVENT,
+    SPO_GRAVE,
+    SPO_FRAME_PUSH,
+    SPO_FRAME_POP,
+    SPO_CALL,
+    SPO_RETURN,
+    SPO_INITLEVEL,
+    SPO_LEVEL_FLAGS,
+    SPO_LEVEL_SOUNDS,
+    SPO_WALLWALK,
+    SPO_VAR_INIT, /* variable_name data */
+    SPO_SHUFFLE_ARRAY,
+    SPO_DICE,
+
+    SPO_SEL_ADD,
+    SPO_SEL_POINT,
+    SPO_SEL_RECT,
+    SPO_SEL_FILLRECT,
+    SPO_SEL_LINE,
+    SPO_SEL_RNDLINE,
+    SPO_SEL_GROW,
+    SPO_SEL_FLOOD,
+    SPO_SEL_RNDCOORD,
+    SPO_SEL_ELLIPSE,
+    SPO_SEL_FILTER,
+
+    MAX_SP_OPCODES
+};
+
+/* MONSTER and OBJECT can take a variable number of parameters,
+ * they also pop different # of values from the stack. So,
+ * first we pop a value that tells what the _next_ value will
+ * mean.
+ */
+/* MONSTER */
+#define SP_M_V_PEACEFUL         0
+#define SP_M_V_ALIGN            1
+#define SP_M_V_ASLEEP           2
+#define SP_M_V_APPEAR           3
+#define SP_M_V_NAME             4
+
+#define SP_M_V_FEMALE		5
+#define SP_M_V_INVIS		6
+#define SP_M_V_CANCELLED	7
+#define SP_M_V_REVIVED		8
+#define SP_M_V_AVENGE		9
+#define SP_M_V_FLEEING		10
+#define SP_M_V_BLINDED		11
+#define SP_M_V_PARALYZED	12
+#define SP_M_V_STUNNED		13
+#define SP_M_V_CONFUSED		14
+#define SP_M_V_SEENTRAPS	15
+
+#define SP_M_V_END              16 /* end of variable parameters */
+
+/* OBJECT */
+#define SP_O_V_SPE              0
+#define SP_O_V_CURSE            1
+#define SP_O_V_CORPSENM         2
+#define SP_O_V_NAME             3
+#define SP_O_V_QUAN		4
+#define SP_O_V_BURIED		5
+#define SP_O_V_LIT		6
+#define SP_O_V_ERODED		7
+#define SP_O_V_LOCKED		8
+#define SP_O_V_TRAPPED		9
+#define SP_O_V_RECHARGED	10
+#define SP_O_V_INVIS		11
+#define SP_O_V_GREASED		12
+#define SP_O_V_BROKEN		13
+#define SP_O_V_COORD		14
+#define SP_O_V_END              15 /* end of variable parameters */
+
+
+/* When creating objects, we need to know whether
+ * it's a container and/or contents.
+ */
+#define SP_OBJ_CONTENT		0x1
+#define SP_OBJ_CONTAINER	0x2
+
+
+
+#define SPOVAR_NULL	0x00
+#define SPOVAR_INT	0x01 /* l */
+#define SPOVAR_STRING	0x02 /* str */
+#define SPOVAR_VARIABLE	0x03 /* str (contains the variable name) */
+#define SPOVAR_COORD	0x04 /* coordinate, encoded in l; use SP_COORD_X() and SP_COORD_Y() */
+#define SPOVAR_REGION	0x05 /* region, encoded in l; use SP_REGION_X1() etc */
+#define SPOVAR_MAPCHAR	0x06 /* map char, in l */
+#define SPOVAR_MONST	0x07 /* monster class & specific monster, encoded in l; use SP_MONST_... */
+#define SPOVAR_OBJ	0x08 /* object class & specific object type, encoded in l; use SP_OBJ_... */
+#define SPOVAR_SEL	0x09 /* selection. char[COLNO][ROWNO] in str */
+#define SPOVAR_ARRAY	0x40 /* used in splev_var & lc_vardefs, not in opvar */
+
+#define SP_COORD_X(l)	(l & 0xff)
+#define SP_COORD_Y(l)	((l >> 16) & 0xff)
+#define SP_COORD_PACK(x,y) ((( x ) & 0xff) + ((( y ) & 0xff) << 16))
+
+#define SP_REGION_X1(l)	(l & 0xff)
+#define SP_REGION_Y1(l)	((l >> 8) & 0xff)
+#define SP_REGION_X2(l)	((l >> 16) & 0xff)
+#define SP_REGION_Y2(l)	((l >> 24) & 0xff)
+#define SP_REGION_PACK(x1,y1,x2,y2) ((( x1 ) & 0xff) + ((( y1 ) & 0xff) << 8) + ((( x2 ) & 0xff) << 16) + ((( y2 ) & 0xff) << 24))
+
+#define SP_MONST_CLASS(l) (l & 0xff)
+#define SP_MONST_PM(l)	  ((l >> 8) & 0xffff)
+#define SP_MONST_PACK(m,c) ((( m ) << 8) + ((char)( c )))
+
+#define SP_OBJ_CLASS(l)	  (l & 0xff)
+#define SP_OBJ_TYP(l)	  ((l >> 8) & 0xffff)
+#define SP_OBJ_PACK(o,c)  ((( o ) << 8) + ((char)( c )))
+
+#define SP_MAPCHAR_TYP(l) (l & 0xff)
+#define SP_MAPCHAR_LIT(l) ((l >> 8) & 0xff)
+#define SP_MAPCHAR_PACK(typ,lit) ((( lit ) << 8) + ((char)( typ )))
+
+struct opvar {
+    xchar spovartyp; /* one of SPOVAR_foo */
+    union {
+	char *str;
+	long l;
+    } vardata;
+};
+
+struct splev_var {
+    struct splev_var *next;
+    char *name;
+    xchar svtyp; /* SPOVAR_foo */
+    union {
+	struct opvar *value;
+	struct opvar **arrayvalues;
+    } data;
+    long array_len;
+};
+
+struct splevstack {
+    long depth;
+    long depth_alloc;
+    struct opvar **stackdata;
+};
+
+
+struct sp_frame {
+    struct sp_frame *next;
+    struct splevstack *stack;
+    struct splev_var *variables;
+    long n_opcode;
+};
+
+
+struct sp_coder {
+    struct splevstack *stack;
+    struct sp_frame *frame;
+    int allow_flips;
+    int premapped;
+    struct mkroom *croom;
+    struct mkroom *tmproomlist[MAX_NESTED_ROOMS+1];
+    boolean failed_room[MAX_NESTED_ROOMS+1];
+    int n_subroom;
+    boolean exit_script;
+    int  lvl_is_joined;
+
+    int opcode;  /* current opcode */
+    struct opvar *opdat; /* current push data (req. opcode == SPO_PUSH) */
+};
+
+/* special level coder CPU flags */
+#define SP_CPUFLAG_LT	1
+#define SP_CPUFLAG_GT	2
+#define SP_CPUFLAG_EQ	4
+#define SP_CPUFLAG_ZERO	8
 
 /*
@@ -32,4 +281,20 @@
  */
 
+typedef struct {
+    xchar x1,y1,x2,y2;
+    xchar fg, lit;
+    int roughness;
+    xchar thick;
+} randline;
+
+typedef struct {
+	int cmp_what;
+	int cmp_val;
+} opcmp;
+
+typedef struct {
+	long jmp_target;
+} opjmp;
+
 typedef union str_or_len {
 	char *str;
@@ -38,8 +303,10 @@
 
 typedef struct {
-	boolean init_present, padding;
+	xchar   init_style; /* one of LVLINIT_foo */
 	char	fg, bg;
 	boolean smoothed, joined;
 	xchar	lit, walled;
+	long	flags;
+	schar	filling;
 } lev_init;
 
@@ -53,5 +320,5 @@
 
 typedef struct {
-	xchar x, y, chance, type;
+	xchar x, y, type;
 } trap;
 
@@ -60,6 +327,9 @@
 	short id;
 	aligntyp align;
-	xchar x, y, chance, class, appear;
+	xchar x, y, class, appear;
 	schar peaceful, asleep;
+        short female, invis, cancelled, revived, avenge, fleeing, blinded, paralyzed, stunned, confused;
+        long seentraps;
+	short has_invent;
 } monster;
 
@@ -68,6 +338,10 @@
 	int   corpsenm;
 	short id, spe;
-	xchar x, y, chance, class, containment;
+	xchar x, y, class, containment;
 	schar curse_state;
+	int   quan;
+	short buried;
+	short lit;
+        short eroded, locked, trapped, recharged, invis, greased, broken;
 } object;
 
@@ -83,5 +357,5 @@
 
 typedef struct {
-	xchar x, y, dir;
+    xchar x, y, dir, stocked, typ;
 } walk;
 
@@ -103,4 +377,16 @@
 } region;
 
+typedef struct {
+    xchar areatyp;
+    xchar x1,y1,x2,y2;
+    xchar ter, tlit;
+} terrain;
+
+typedef struct {
+    xchar chance;
+    xchar x1,y1,x2,y2;
+    xchar fromter, toter, tolit;
+} replaceterrain;
+
 /* values for rtype are defined in dungeon.h */
 typedef struct {
@@ -135,92 +421,21 @@
 } pool;
 
-typedef struct {
-	char halign, valign;
-	char xsize, ysize;
-	char **map;
-	char nrobjects;
-	char *robjects;
-	char nloc;
-	char *rloc_x;
-	char *rloc_y;
-	char nrmonst;
-	char *rmonst;
-	char nreg;
-	region **regions;
-	char nlreg;
-	lev_region **lregions;
-	char ndoor;
-	door **doors;
-	char ntrap;
-	trap **traps;
-	char nmonster;
-	monster **monsters;
-	char nobject;
-	object **objects;
-	char ndrawbridge;
-	drawbridge **drawbridges;
-	char nwalk;
-	walk **walks;
-	char ndig;
-	digpos **digs;
-	char npass;
-	digpos **passs;
-	char nlad;
-	lad **lads;
-	char nstair;
-	stair **stairs;
-	char naltar;
-	altar **altars;
-	char ngold;
-	gold **golds;
-	char nengraving;
-	engraving **engravings;
-	char nfountain;
-	fountain **fountains;
-} mazepart;
-
-typedef struct {
-	long flags;
-	lev_init init_lev;
-	schar filling;
-	char numpart;
-	mazepart **parts;
-} specialmaze;
-
 typedef struct _room {
-	char  *name;
-	char  *parent;
+	Str_or_Len name;
+	Str_or_Len parent;
 	xchar x, y, w, h;
 	xchar xalign, yalign;
 	xchar rtype, chance, rlit, filled;
-	char ndoor;
-	room_door **doors;
-	char ntrap;
-	trap **traps;
-	char nmonster;
-	monster **monsters;
-	char nobject;
-	object **objects;
-	char naltar;
-	altar **altars;
-	char nstair;
-	stair **stairs;
-	char ngold;
-	gold **golds;
-	char nengraving;
-	engraving **engravings;
-	char nfountain;
-	fountain **fountains;
-	char nsink;
-	sink **sinks;
-	char npool;
-	pool **pools;
-	/* These three fields are only used when loading the level... */
-	int nsubroom;
-	struct _room *subrooms[MAX_SUBROOMS];
-	struct mkroom *mkr;
 } room;
 
 typedef struct {
+    	schar zaligntyp;
+	schar keep_region;
+	schar halign, valign;
+	char xsize, ysize;
+	char **map;
+} mazepart;
+
+typedef struct {
 	struct {
 		xchar room;
@@ -230,17 +445,35 @@
 } corridor;
 
-/* used only by lev_comp */
 typedef struct {
-	long flags;
-	lev_init init_lev;
-	char nrobjects;
-	char *robjects;
-	char nrmonst;
-	char *rmonst;
-	xchar nroom;
-	room **rooms;
-	xchar ncorr;
-	corridor **corrs;
-} splev;
+    int opcode;
+    struct opvar *opdat;
+} _opcode;
+
+typedef struct {
+    _opcode  *opcodes;
+    long     n_opcodes;
+} sp_lev;
+
+typedef struct {
+	xchar x, y, direction, count, lit;
+	char typ;
+} spill;
+
+
+/* only used by lev_comp */
+
+struct lc_funcdefs {
+    struct lc_funcdefs *next;
+    char *name;
+    long addr;
+    sp_lev code;
+    long n_called;
+};
+
+struct lc_vardefs {
+    struct lc_vardefs *next;
+    char *name;
+    long var_type; /* SPOVAR_foo */
+};
 
 #endif /* SP_LEV_H */
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/include/system.h nethack/include/system.h
--- nh_orig/include/system.h	2003-12-07 18:39:13.000000000 -0500
+++ nethack/include/system.h	2009-09-07 09:52:30.877293621 -0400
@@ -474,5 +474,5 @@
 #ifdef NEED_VARARGS
 # if defined(USE_STDARG) || defined(USE_VARARGS)
-#  if !defined(SVR4) && !defined(apollo)
+#  if !defined(SVR4) && !defined(apollo) && !defined(OSX)
 #   if !(defined(ULTRIX_PROTO) && defined(__GNUC__))
 #    if !(defined(SUNOS4) && defined(__STDC__)) /* Solaris unbundled cc (acc) */
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/include/trap.h nethack/include/trap.h
--- nh_orig/include/trap.h	2003-12-07 18:39:13.000000000 -0500
+++ nethack/include/trap.h	2009-09-28 07:52:26.134418460 -0400
@@ -73,5 +73,8 @@
 #define ANTI_MAGIC	21
 #define POLY_TRAP	22
-#define TRAPNUM 23
+#define SPEAR_TRAP 23
+#define COLLAPSE_TRAP 24
+#define MAGIC_BEAM_TRAP	25
+#define TRAPNUM 26
 
 #endif /* TRAP_H */
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/include/unixconf.h nethack/include/unixconf.h
--- nh_orig/include/unixconf.h	2003-12-07 18:39:13.000000000 -0500
+++ nethack/include/unixconf.h	2010-04-26 14:16:44.817948018 -0400
@@ -33,10 +33,11 @@
 
 /* define any of the following that are appropriate */
-#define SVR4		/* use in addition to SYSV for System V Release 4 */
+/* #define SVR4		/* use in addition to SYSV for System V Release 4 */
 			/* including Solaris 2+ */
 #define NETWORK		/* if running on a networked system */
 			/* e.g. Suns sharing a playground through NFS */
 /* #define SUNOS4 */	/* SunOS 4.x */
-/* #define LINUX */	/* Another Unix clone */
+#define LINUX /* Another Unix clone */
+/* #define OSX	 /* Apple OS X */
 /* #define CYGWIN32 */	/* Unix on Win32 -- use with case sensitive defines */
 /* #define GENIX */	/* Yet Another Unix Clone */
@@ -110,9 +111,7 @@
  * If defined, it can be overridden by the environment variable PAGER.
  * Hack will use its internal pager if DEF_PAGER is not defined.
- * (This might be preferable for security reasons.)
- * #define DEF_PAGER	".../mydir/mypager"
- */
-
+ * (This might be preferable for security reasons.)*/
 
+/*#define DEF_PAGER	"/usr/bin/less"*/
 
 /*
@@ -133,5 +132,5 @@
  * a fine-grained timer.
  */
-/* #define TIMED_DELAY */	/* usleep() */
+#define TIMED_DELAY /* usleep() */
 #endif
 
@@ -144,5 +143,5 @@
  */
 
-#define MAIL			/* Deliver mail during the game */
+/* #define MAIL			/* Deliver mail during the game */
 
 /* The Andrew Message System does mail a little differently from normal
@@ -210,4 +209,10 @@
 #define FCMASK	0660	/* file creation mask */
 
+/* fcntl(2) is a POSIX-portable call for manipulating file descriptors.
+ * Comment out the USE_FCNTL if for some reason you have a strange
+ * os/filesystem combination for which fcntl(2) does not work. */
+#ifdef POSIX_TYPES
+# define USE_FCNTL
+#endif
 
 /*
@@ -271,5 +276,5 @@
 #define tgetch getchar
 
-#define SHELL		/* do not delete the '!' command */
+/* #define SHELL		do not delete the '!' command */
 
 #include "system.h"
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/include/unixconf.h.~1~ nethack/include/unixconf.h.~1~
--- nh_orig/include/unixconf.h.~1~	1969-12-31 19:00:00.000000000 -0500
+++ nethack/include/unixconf.h.~1~	2009-08-02 13:49:33.035408669 -0400
@@ -0,0 +1,356 @@
+/*	SCCS Id: @(#)unixconf.h 3.4	1999/07/02	*/
+/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
+/* NetHack may be freely redistributed.  See license for details. */
+
+#ifdef UNIX
+#ifndef UNIXCONF_H
+#define UNIXCONF_H
+
+/*
+ * Some include files are in a different place under SYSV
+ *	BSD		   SYSV
+ * <sys/time.h>		<time.h>
+ * <sgtty.h>		<termio.h>
+ *
+ * Some routines are called differently
+ * index		strchr
+ * rindex		strrchr
+ *
+ */
+
+/* define exactly one of the following four choices */
+/* #define BSD 1 */	/* define for 4.n/Free/Open/Net BSD  */
+			/* also for relatives like SunOS 4.x, DG/UX, and */
+			/* older versions of Linux */
+/* #define ULTRIX */	/* define for Ultrix v3.0 or higher (but not lower) */
+			/* Use BSD for < v3.0 */
+			/* "ULTRIX" not to be confused with "ultrix" */
+#define SYSV		/* define for System V, Solaris 2.x, newer versions */
+			/* of Linux */
+/* #define HPUX */	/* Hewlett-Packard's Unix, version 6.5 or higher */
+			/* use SYSV for < v6.5 */
+
+
+/* define any of the following that are appropriate */
+/* #define SVR4		/* use in addition to SYSV for System V Release 4 */
+			/* including Solaris 2+ */
+#define NETWORK		/* if running on a networked system */
+			/* e.g. Suns sharing a playground through NFS */
+/* #define SUNOS4 */	/* SunOS 4.x */
+#define LINUX /* Another Unix clone */
+/* #define OSX	 /* Apple OS X */
+/* #define CYGWIN32 */	/* Unix on Win32 -- use with case sensitive defines */
+/* #define GENIX */	/* Yet Another Unix Clone */
+/* #define HISX */	/* Bull Unix for XPS Machines */
+/* #define BOS */	/* Bull Open Software - Unix for DPX/2 Machines */
+/* #define UNIXPC */	/* use in addition to SYSV for AT&T 7300/3B1 */
+/* #define AIX_31 */	/* In AIX 3.1 (IBM RS/6000) use BSD ioctl's to gain
+			 * job control (note that AIX is SYSV otherwise)
+			 * Also define this for AIX 3.2 */
+
+#define TERMINFO	/* uses terminfo rather than termcap */
+			/* Should be defined for most SYSV, SVR4 (including
+			 * Solaris 2+), HPUX, and Linux systems.  In
+			 * particular, it should NOT be defined for the UNIXPC
+			 * unless you remove the use of the shared library in
+			 * the Makefile */
+#define TEXTCOLOR	/* Use System V r3.2 terminfo color support */
+			/* and/or ANSI color support on termcap systems */
+			/* and/or X11 color */
+#define POSIX_JOB_CONTROL /* use System V / Solaris 2.x / POSIX job control */
+			/* (e.g., VSUSP) */
+#define POSIX_TYPES	/* use POSIX types for system calls and termios */
+			/* Define for many recent OS releases, including
+			 * those with specific defines (since types are
+			 * changing toward the standard from earlier chaos).
+			 * For example, platforms using the GNU libraries,
+			 * Linux, Solaris 2.x
+			 */
+
+/* #define OPENWINBUG */	/* avoid a problem using OpenWindows 3.0 for
+				   X11 on SunOS 4.1.x, x>= 2.  Do not define
+				   for other X11 implementations. */
+/* #define PYRAMID_BUG */	/* avoid a bug on the Pyramid */
+/* #define BSD_43_BUG */	/* for real 4.3BSD cc's without schain botch fix */
+/* #define MICROPORT_BUG */	/* problems with large arrays in structs */
+/* #define MICROPORT_286_BUG */ /* changes needed in termcap.c to get it to
+				   run with Microport Sys V/AT version 2.4.
+				   By Jay Maynard */
+/* #define AIXPS_2BUG */	/* avoid a problem with little_to_big() optimization */
+
+/* #define RANDOM */		/* if neither random/srandom nor lrand48/srand48
+				   is available from your system */
+
+/* see sys/unix/snd86unx.shr for more information on these */
+/* #define UNIX386MUSIC */	/* play real music through speaker on systems
+				   with music driver installed */
+/* #define VPIX_MUSIC */	/* play real music through speaker on systems
+				   with built-in VPIX support */
+
+
+/*
+ * The next two defines are intended mainly for the Andrew File System,
+ * which does not allow hard links.  If NO_FILE_LINKS is defined, lock files
+ * will be created in LOCKDIR using open() instead of in the playground using
+ * link().
+ *		Ralf Brown, 7/26/89 (from v2.3 hack of 10/10/88)
+ */
+
+/* #define NO_FILE_LINKS */	/* if no hard links */
+/* #define LOCKDIR "/usr/games/lib/nethackdir" */	/* where to put locks */
+
+/*
+ * If you want the static parts of your playground on a read-only file
+ * system, define VAR_PLAYGROUND to be where the variable parts are kept.
+ */
+/* #define VAR_PLAYGROUND "/var/lib/games/nethack" */
+
+
+/*
+ * Define DEF_PAGER as your default pager, e.g. "/bin/cat" or "/usr/ucb/more"
+ * If defined, it can be overridden by the environment variable PAGER.
+ * Hack will use its internal pager if DEF_PAGER is not defined.
+ * (This might be preferable for security reasons.)*/
+
+/*#define DEF_PAGER	"/usr/bin/less"*/
+
+/*
+ * Define PORT_HELP to be the name of the port-specfic help file.
+ * This file is found in HACKDIR.
+ * Normally, you shouldn't need to change this.
+ * There is currently no port-specific help for Unix systems.
+ */
+/* #define PORT_HELP "Unixhelp" */
+
+#ifdef TTY_GRAPHICS
+/*
+ * To enable the `timed_delay' option for using a timer rather than extra
+ * screen output when pausing for display effect.  Requires that `msleep'
+ * function be available (with time argument specified in milliseconds).
+ * Various output devices can produce wildly varying delays when the
+ * "extra output" method is used, but not all systems provide access to
+ * a fine-grained timer.
+ */
+#define TIMED_DELAY /* usleep() */
+#endif
+
+/*
+ * If you define MAIL, then the player will be notified of new mail
+ * when it arrives.  If you also define DEF_MAILREADER then this will
+ * be the default mail reader, and can be overridden by the environment
+ * variable MAILREADER; otherwise an internal pager will be used.
+ * A stat system call is done on the mailbox every MAILCKFREQ moves.
+ */
+
+/* #define MAIL			/* Deliver mail during the game */
+
+/* The Andrew Message System does mail a little differently from normal
+ * UNIX.  Mail is deposited in the user's own directory in ~/Mailbox
+ * (another directory).  MAILBOX is the element that will be added on to
+ * the user's home directory path to generate the Mailbox path - just in
+ * case other Andrew sites do it differently from CMU.
+ *
+ *		dan lovinger
+ *		dl2n+@andrew.cmu.edu (dec 19 1989)
+ */
+
+/* #define AMS */		/* use Andrew message system for mail */
+
+/* NO_MAILREADER is for kerberos authenticating filesystems where it is
+ * essentially impossible to securely exec child processes, like mail
+ * readers, when the game is running under a special token.
+ *
+ *	       dan
+ */
+
+/* #define NO_MAILREADER */	/* have mail daemon just tell player of mail */
+
+#ifdef	MAIL
+# if defined(BSD) || defined(ULTRIX)
+#  ifdef AMS
+#define AMS_MAILBOX	"/Mailbox"
+#  else
+#   if defined(__FreeBSD__) || defined(__OpenBSD__)
+#define DEF_MAILREADER	"/usr/bin/mail"
+#   else
+#define DEF_MAILREADER	"/usr/ucb/Mail"
+#   endif
+#  endif
+#else
+# if (defined(SYSV) || defined(DGUX) || defined(HPUX)) && !defined(LINUX)
+#  if defined(M_XENIX)
+#define DEF_MAILREADER	"/usr/bin/mail"
+#  else
+#   ifdef __sgi
+#define DEF_MAILREADER	"/usr/sbin/Mail"
+#   else
+#define DEF_MAILREADER	"/usr/bin/mailx"
+#   endif
+#  endif
+# else
+#define DEF_MAILREADER	"/bin/mail"
+# endif
+#endif
+
+#define MAILCKFREQ	50
+#endif	/* MAIL */
+
+
+
+#ifdef COMPRESS
+/* Some implementations of compress need a 'quiet' option.
+ * If you've got one of these versions, put -q here.
+ * You can also include any other strange options your compress needs.
+ * If you have a normal compress, just leave it commented out.
+ */
+/* #define COMPRESS_OPTIONS "-q" */
+#endif
+
+#define FCMASK	0660	/* file creation mask */
+
+/* fcntl(2) is a POSIX-portable call for manipulating file descriptors.
+ * Comment out the USE_FCNTL if for some reason you have a strange
+ * os/filesystem combination for which fcntl(2) does not work. */
+#ifdef POSIX_TYPES
+# define USE_FCNTL
+#endif
+
+/*
+ * The remainder of the file should not need to be changed.
+ */
+
+#ifdef _AUX_SOURCE
+# ifdef AUX /* gcc ? */
+#  define _SYSV_SOURCE
+#  define _BSD_SOURCE
+#else
+#  define AUX
+# endif
+#endif /* _AUX_SOURCE */
+
+#if defined(LINUX) || defined(bsdi)
+# ifndef POSIX_TYPES
+#  define POSIX_TYPES
+# endif
+# ifndef POSIX_JOB_CONTROL
+#  define POSIX_JOB_CONTROL
+# endif
+#endif
+
+/*
+ * BSD/ULTRIX systems are normally the only ones that can suspend processes.
+ * Suspending NetHack processes cleanly should be easy to add to other systems
+ * that have SIGTSTP in the Berkeley sense.  Currently the only such systems
+ * known to work are HPUX and AIX 3.1; other systems will probably require
+ * tweaks to unixtty.c and ioctl.c.
+ *
+ * POSIX defines a slightly different type of job control, which should be
+ * equivalent for NetHack's purposes.  POSIX_JOB_CONTROL should work on
+ * various recent SYSV versions (with possibly tweaks to unixtty.c again).
+ */
+#ifndef POSIX_JOB_CONTROL
+# if defined(BSD) || defined(ULTRIX) || defined(HPUX) || defined(AIX_31)
+#  define BSD_JOB_CONTROL
+# else
+#  if defined(SVR4)
+#   define POSIX_JOB_CONTROL
+#  endif
+# endif
+#endif
+#if defined(BSD_JOB_CONTROL) || defined(POSIX_JOB_CONTROL) || defined(AUX)
+#define SUSPEND		/* let ^Z suspend the game */
+#endif
+
+
+#if defined(BSD) || defined(ULTRIX)
+#include <sys/time.h>
+#else
+#include <time.h>
+#endif
+
+#define HLOCK	"perm"	/* an empty file used for locking purposes */
+
+#ifndef REDO
+#define Getchar nhgetch
+#endif
+#define tgetch getchar
+
+/* #define SHELL		do not delete the '!' command */
+
+#include "system.h"
+
+#if defined(POSIX_TYPES) || defined(__GNUC__)
+#include <stdlib.h>
+#include <unistd.h>
+#endif
+
+#if defined(POSIX_TYPES) || defined(__GNUC__) || defined(BSD) || defined(ULTRIX)
+#include <sys/wait.h>
+#endif
+
+#if defined(BSD) || defined(ULTRIX)
+# if !defined(DGUX) && !defined(SUNOS4)
+#define memcpy(d, s, n)		bcopy(s, d, n)
+#define memcmp(s1, s2, n)	bcmp(s2, s1, n)
+# endif
+# ifdef SUNOS4
+#include <memory.h>
+# endif
+#else	/* therefore SYSV */
+# ifndef index	/* some systems seem to do this for you */
+#define index	strchr
+# endif
+# ifndef rindex
+#define rindex	strrchr
+# endif
+#endif
+
+/* Use the high quality random number routines. */
+#if defined(BSD) || defined(LINUX) || defined(ULTRIX) || defined(CYGWIN32) || defined(RANDOM) || defined(__APPLE__)
+#define Rand()	random()
+#else
+#define Rand()	lrand48()
+#endif
+
+#ifdef TIMED_DELAY
+# if defined(SUNOS4) || defined(LINUX) || (defined(BSD) && !defined(ULTRIX))
+# define msleep(k) usleep((k)*1000)
+# endif
+# ifdef ULTRIX
+# define msleep(k) napms(k)
+# endif
+#endif
+
+#ifdef hc	/* older versions of the MetaWare High-C compiler define this */
+# ifdef __HC__
+#  undef __HC__
+# endif
+# define __HC__ hc
+# undef hc
+#endif
+
+#if defined(GNOME_GRAPHICS)
+#if defined(LINUX)
+# include <linux/unistd.h>
+# if defined(__NR_getresuid) && defined(__NR_getresgid)	/* ie., >= v2.1.44 */
+#  define GETRES_SUPPORT
+# endif
+#else
+# if defined(BSD) || defined(SVR4)
+/*
+ * [ALI] We assume that SVR4 means we can safely include syscall.h
+ * (although it's really a BSDism). This is certainly true for Solaris 2.5,
+ * Solaris 7, Solaris 8 and Compaq Tru64 5.1
+ * Later BSD systems will have the getresid system calls.
+ */
+# include <sys/syscall.h>
+# if (defined (SYS_getuid) || defined(SYS_getresuid)) && \
+  (defined(SYS_getgid) || defined(SYS_getresgid))
+#  define GETRES_SUPPORT
+# endif
+# endif	/* BSD || SVR4 */
+#endif /* LINUX */
+#endif	/* GNOME_GRAPHICS */
+
+#endif /* UNIXCONF_H */
+#endif /* UNIX */
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/include/wincurs.h nethack/include/wincurs.h
--- nh_orig/include/wincurs.h	1969-12-31 19:00:00.000000000 -0500
+++ nethack/include/wincurs.h	2009-09-05 11:30:14.265303603 -0400
@@ -0,0 +1,250 @@
+#ifndef WINCURS_H
+#define WINCURS_H
+
+/* Global declarations for curses interface */
+
+int term_rows, term_cols; /* size of underlying terminal */
+
+WINDOW *base_term;    /* underlying terminal window */
+
+WINDOW *mapborderwin;
+
+
+#define TEXTCOLOR   /* Allow color */
+#define NHW_END 19
+#define OFF 0
+#define ON 1
+#define NONE -1
+#define KEY_ESC 0x1b
+#define DIALOG_BORDER_COLOR CLR_MAGENTA
+#define HIGHLIGHT_COLOR CLR_WHITE
+#define MORECOLOR CLR_ORANGE
+#define STAT_UP_COLOR CLR_GREEN
+#define STAT_DOWN_COLOR CLR_RED
+#define MESSAGE_WIN 1
+#define STATUS_WIN  2
+#define MAP_WIN     3
+#define HPOS_WIN    4
+#define MESG_HISTORY_MAX   200
+
+
+typedef enum orient_type
+{
+    CENTER,
+    UP,
+    DOWN,
+    RIGHT,
+    LEFT
+} orient;
+
+
+/* cursmain.c */
+
+extern struct window_procs curses_procs;
+
+extern void curses_init_nhwindows(int* argcp, char** argv);
+
+extern void curses_player_selection(void);
+
+extern void curses_askname(void);
+
+extern void curses_get_nh_event(void);
+
+extern void curses_exit_nhwindows(const char *str);
+
+extern void curses_suspend_nhwindows(const char *str);
+
+extern void curses_resume_nhwindows(void);
+
+extern winid curses_create_nhwindow(int type);
+
+extern void curses_clear_nhwindow(winid wid);
+
+extern void curses_display_nhwindow(winid wid, BOOLEAN_P block);
+
+extern void curses_destroy_nhwindow(winid wid);
+
+extern void curses_curs(winid wid, int x, int y);
+
+extern void curses_putstr(winid wid, int attr, const char *text);
+
+extern void curses_display_file(const char *filename,BOOLEAN_P must_exist);
+
+extern void curses_start_menu(winid wid);
+
+extern void curses_add_menu(winid wid, int glyph, const ANY_P * identifier,
+		CHAR_P accelerator, CHAR_P group_accel, int attr, 
+		const char *str, BOOLEAN_P presel);
+
+extern void curses_end_menu(winid wid, const char *prompt);
+
+extern int curses_select_menu(winid wid, int how, MENU_ITEM_P **selected);
+
+extern void curses_update_inventory(void);
+
+extern void curses_mark_synch(void);
+
+extern void curses_wait_synch(void);
+
+extern void curses_cliparound(int x, int y);
+
+extern void curses_print_glyph(winid wid,XCHAR_P x,XCHAR_P y,int glyph);
+
+extern void curses_raw_print(const char *str);
+
+extern void curses_raw_print_bold(const char *str);
+
+extern int curses_nhgetch(void);
+
+extern int curses_nh_poskey(int *x, int *y, int *mod);
+
+extern void curses_nhbell(void);
+
+extern int curses_doprev_message(void);
+
+extern char curses_yn_function(const char *question, const char *choices, CHAR_P def);
+
+extern void curses_getlin(const char *question, char *input);
+
+extern int curses_get_ext_cmd(void);
+
+extern void curses_number_pad(int state);
+
+extern void curses_delay_output(void);
+
+extern void curses_start_screen(void);
+
+extern void curses_end_screen(void);
+
+extern void curses_outrip(winid wid, int how);
+
+extern void genl_outrip(winid tmpwin, int how);
+
+extern void curses_preference_update(const char *pref);
+
+
+/* curswins.c */
+
+extern WINDOW *curses_create_window(int width, int height, orient orientation);
+
+extern void curses_destroy_win(WINDOW *win);
+
+extern WINDOW *curses_get_nhwin(winid wid);
+
+extern void curses_add_nhwin(winid wid, int height, int width, int y,
+ int x, orient orientation, boolean border);
+
+extern void curses_refresh_nhwin(winid wid);
+
+extern void curses_refresh_nethack_windows(void);
+
+extern void curses_del_nhwin(winid wid);
+
+extern void curses_putch(winid wid, int x, int y, int ch, int color, int attrs);
+
+extern void curses_get_window_size(winid wid, int *height, int *width);
+
+extern boolean curses_window_has_border(winid wid);
+
+extern boolean curses_window_exists(winid wid);
+
+extern int curses_get_window_orientation(winid wid);
+
+extern void curses_get_window_xy(winid wid, int *x, int *y);
+
+extern void curses_puts(winid wid, int attr, const char *text);
+
+
+/* cursmisc.c */
+
+extern int curses_read_char(void);
+
+extern void curses_toggle_color_attr(WINDOW *win, int color, int attr, int onoff);
+
+extern void curses_bail(const char *mesg);
+
+extern winid curses_get_wid(int type);
+
+extern char *curses_copy_of(const char *s);
+
+extern int curses_num_lines(const char *str, int width);
+
+extern char *curses_break_str(const char *str, int width, int line_num);
+
+extern char *curses_str_remainder(const char *str, int width, int line_num);
+
+extern boolean curses_is_menu(winid wid);
+
+extern boolean curses_is_text(winid wid);
+
+extern int curses_convert_glyph(int ch, int glyph);
+
+extern void curses_move_cursor(winid wid, int x, int y);
+
+extern void curses_prehousekeeping(void);
+
+extern void curses_posthousekeeping(void);
+
+extern void curses_view_file(const char *filename, boolean must_exist);
+
+extern char *curses_rtrim(char *str);
+
+
+/* cursdial.c */
+
+extern void curses_line_input_dialog(const char *prompt, char *answer, int buffer);
+
+extern int curses_character_input_dialog(const char *prompt, const char *choices, CHAR_P def);
+
+extern int curses_ext_cmd(void);
+
+extern void curses_create_nhmenu(winid wid);
+
+extern void curses_add_nhmenu_item(winid wid, const ANY_P *identifier,
+ CHAR_P accelerator, CHAR_P group_accel, int attr, const char *str,
+ BOOLEAN_P presel);
+
+extern void curses_finalize_nhmenu(winid wid, const char *prompt);
+
+extern int curses_display_nhmenu(winid wid, int how, MENU_ITEM_P **_selected);
+
+extern boolean curses_menu_exists(winid wid);
+
+extern void curses_del_menu(winid wid);
+
+
+/* cursstat.c */
+
+extern void curses_update_stats(void);
+
+extern void curses_decrement_highlight(void);
+
+
+/* cursinit.c */
+
+extern void curses_create_main_windows(void);
+
+extern void curses_init_nhcolors(void);
+
+extern void curses_choose_character(void);
+
+extern int curses_character_dialog(const char** choices, const char *prompt);
+
+extern void curses_init_options(void);
+
+
+/* cursmesg.c */
+
+extern void curses_message_win_puts(const char *message, boolean recursed);
+
+extern void curses_more(void);
+
+extern void curses_clear_unhighlight_message_window(void);
+
+extern void curses_last_messages(void);
+
+extern void curses_init_mesg_history(void);
+
+
+#endif  /* WINCURS_H */
+
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/include/winprocs.h nethack/include/winprocs.h
--- nh_orig/include/winprocs.h	2003-12-07 18:39:13.000000000 -0500
+++ nethack/include/winprocs.h	2010-04-11 12:36:57.794750618 -0400
@@ -177,6 +177,7 @@
 #define WC2_FULLSCREEN		0x01L	/* 01 display full screen                    */
 #define WC2_SOFTKEYBOARD	0x02L	/* 02 software keyboard                      */
-#define WC2_WRAPTEXT		0x04L	/* 04 wrap long lines of text                */
-					/* 29 free bits */
+#define WC2_WRAPTEXT		0x04L	/* 03 wrap long lines of text                */
+#define WC2_DARKGRAY		0x08L	/* 04 try to use "bright black" color        */
+					/* 28 free bits */
 
 #define ALIGN_LEFT	1
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/include/you.h nethack/include/you.h
--- nh_orig/include/you.h	2003-12-07 18:39:13.000000000 -0500
+++ nethack/include/you.h	2010-03-24 12:55:58.963750958 -0400
@@ -89,9 +89,5 @@
 	      ldrnum,		/* PM_ of quest leader (questpgr.c) */
 	      guardnum,		/* PM_ of quest guardians (questpgr.c) */
-	      neminum,		/* PM_ of quest nemesis (questpgr.c) */
-	      enemy1num,	/* specific quest enemies (NON_PM == random) */
-	      enemy2num;
-	char  enemy1sym,	/* quest enemies by class (S_) */
-	      enemy2sym;
+	      neminum;		/* PM_ of quest nemesis (questpgr.c) */
 	short questarti;	/* index (ART_) of quest artifact (questpgr.c) */
 
@@ -264,4 +260,6 @@
 	struct prop uprops[LAST_PROP+1];
 
+    int u_telepathy_dist;
+
 	unsigned umconf;
 	char usick_cause[PL_PSIZ+20]; /* sizeof "unicorn horn named "+1 */
@@ -345,4 +343,5 @@
 	long	ucleansed;	/* to record moves when player was cleansed */
 	long	usleep;		/* sleeping; monstermove you last started */
+	long  udiseased;  /* diseased: are you diseased, and how badly? */
 	int uinvault;
 	struct monst *ustuck;
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/include/youprop.h nethack/include/youprop.h
--- nh_orig/include/youprop.h	2003-12-07 18:39:13.000000000 -0500
+++ nethack/include/youprop.h	2009-08-02 13:49:33.040407823 -0400
@@ -61,4 +61,24 @@
 				 resists_drli(&youmonst))
 
+#define HVulnerable_fire  u.uprops[VULN_FIRE].intrinsic
+#define EVulnerable_fire  u.uprops[VULN_FIRE].extrinsic
+#define Vulnerable_fire	  (HVulnerable_fire || EVulnerable_fire || \
+		vulnerable_to(&youmonst,AD_FIRE))
+
+#define HVulnerable_cold  u.uprops[VULN_COLD].intrinsic
+#define EVulnerable_cold  u.uprops[VULN_COLD].extrinsic
+#define Vulnerable_cold	  (HVulnerable_cold || EVulnerable_cold || \
+		vulnerable_to(&youmonst,AD_COLD))
+
+#define HVulnerable_elec  u.uprops[VULN_ELEC].intrinsic
+#define EVulnerable_elec  u.uprops[VULN_ELEC].extrinsic
+#define Vulnerable_elec	  (HVulnerable_elec || EVulnerable_elec || \
+		vulnerable_to(&youmonst,AD_ELEC))
+
+#define HVulnerable_acid  u.uprops[VULN_ACID].intrinsic
+#define EVulnerable_acid  u.uprops[VULN_ACID].extrinsic
+#define Vulnerable_acid	  (HVulnerable_acid || EVulnerable_acid || \
+		vulnerable_to(&youmonst,AD_ACID))
+
 /* Intrinsics only */
 #define HSick_resistance	u.uprops[SICK_RES].intrinsic
@@ -80,4 +100,10 @@
 #define Stone_resistance	(EStone_resistance || resists_ston(&youmonst))
 
+#define EWere_resistance  u.uprops[WERE_RES].extrinsic
+#define Were_resistance	  (EWere_resistance)
+
+#define EBlind_resistance  u.uprops[BLIND_RES].extrinsic
+#define Blind_resistance	(EBlind_resistance || Vision)
+
 
 /*** Troubles ***/
@@ -87,10 +113,16 @@
 /* Those implemented solely as timeouts (we use just intrinsic) */
 #define HStun			u.uprops[STUNNED].intrinsic
-#define Stunned			(HStun || u.umonnum == PM_STALKER || \
-				 youmonst.data->mlet == S_BAT)
+#define Stunned			(!Stun_resistance && \
+							(HStun || u.umonnum == PM_STALKER || youmonst.data->mlet == S_BAT))
 		/* Note: birds will also be stunned */
 
 #define HConfusion		u.uprops[CONFUSION].intrinsic
-#define Confusion		HConfusion
+#define Confusion					  (HConfusion && !Confusion_resistance)
+
+/* cheap hack to avoid breaking save */
+#define EConfusion_resistance	  u.uprops[CONFUSION].extrinsic
+#define Confusion_resistance	  EConfusion_resistance
+#define EStun_resistance		  u.uprops[STUNNED].extrinsic
+#define Stun_resistance			  EStun_resistance
 
 #define Blinded			u.uprops[BLINDED].intrinsic
@@ -98,7 +130,10 @@
 		/* ...means blind because of a cover */
 #define Blind	((Blinded || Blindfolded || !haseyes(youmonst.data)) && \
-		 !(ublindf && ublindf->oartifact == ART_EYES_OF_THE_OVERWORLD))
+		 !(ublindf && ublindf->oartifact == ART_EYES_OF_THE_OVERWORLD) && \
+		 !(haseyes(youmonst.data) && Blind_resistance))
+
 		/* ...the Eyes operate even when you really are blind
-		    or don't have any eyes */
+		    or don't have any eyes, but blindness resistance won't
+			 grant sight to something that didn't have it... */
 
 #define Sick			u.uprops[SICK].intrinsic
@@ -112,5 +147,5 @@
 #define HHallucination		u.uprops[HALLUC].intrinsic
 #define EHalluc_resistance	u.uprops[HALLUC_RES].extrinsic
-#define Halluc_resistance	(EHalluc_resistance || \
+#define Halluc_resistance	(EHalluc_resistance || Vision || \
 				 (Upolyd && dmgtype(youmonst.data, AD_HALU)))
 #define Hallucination		(HHallucination && !Halluc_resistance)
@@ -138,11 +173,12 @@
 #define ESee_invisible		u.uprops[SEE_INVIS].extrinsic
 #define See_invisible		(HSee_invisible || ESee_invisible || \
-				 perceives(youmonst.data))
+				 perceives(youmonst.data) || Vision)
 
 #define HTelepat		u.uprops[TELEPAT].intrinsic
 #define ETelepat		u.uprops[TELEPAT].extrinsic
-#define Blind_telepat		(HTelepat || ETelepat || \
-				 telepathic(youmonst.data))
-#define Unblind_telepat		(ETelepat)
+#define Blind_telepat		((HTelepat || ETelepat || \
+				 telepathic(youmonst.data)) && !BTelepat)
+#define Unblind_telepat		(ETelepat && !BTelepat)
+#define BTelepat	 u.uprops[TELEPAT].blocked
 
 #define HWarning		u.uprops[WARNING].intrinsic
@@ -150,4 +186,10 @@
 #define Warning			(HWarning || EWarning)
 
+/* See invisible, infravision, protection from shape changers,
+ * blindness and hallucination resistance all rolled into one */
+#define EVision		 u.uprops[VISION].extrinsic
+#define Vision			 (EVision)
+
+
 /* Warning for a specific type of monster */
 #define HWarn_of_mon		u.uprops[WARN_OF_MON].intrinsic
@@ -171,5 +213,5 @@
 #define EInfravision		u.uprops[INFRAVISION].extrinsic
 #define Infravision		(HInfravision || EInfravision || \
-				  infravision(youmonst.data))
+				  infravision(youmonst.data) || Vision)
 
 #define HDetect_monsters	u.uprops[DETECT_MONSTERS].intrinsic
@@ -241,4 +283,5 @@
 	/* May touch surface; does not override any others */
 
+#define EWwalking	   u.uprops[WWALKING].extrinsic
 #define Wwalking		(u.uprops[WWALKING].extrinsic && \
 				 !Is_waterlevel(&u.uz))
@@ -310,5 +353,6 @@
 #define Protection_from_shape_changers \
 				(HProtection_from_shape_changers || \
-				 EProtection_from_shape_changers)
+				 EProtection_from_shape_changers || \
+				 Vision)
 
 #define HPolymorph		u.uprops[POLYMORPH].intrinsic
@@ -326,9 +370,14 @@
 #define HFast			u.uprops[FAST].intrinsic
 #define EFast			u.uprops[FAST].extrinsic
-#define Fast			(HFast || EFast)
-#define Very_fast		((HFast & ~INTRINSIC) || EFast)
+#define Fast			((HFast || EFast) && !Slow)
+#define Very_fast		(((HFast & ~INTRINSIC) || EFast) && !Slow)
+
+#define HSlow		   u.uprops[SLOW].intrinsic
+#define ESlow		   u.uprops[SLOW].extrinsic
+#define Slow			(HSlow || ESlow)
 
+#define HReflecting		u.uprops[REFLECTING].intrinsic
 #define EReflecting		u.uprops[REFLECTING].extrinsic
-#define Reflecting		(EReflecting || \
+#define Reflecting		(EReflecting || HReflecting || \
 				 (youmonst.data == &mons[PM_SILVER_DRAGON]))
 
@@ -339,4 +388,6 @@
 #define Lifesaved		u.uprops[LIFESAVED].extrinsic
 
+#define ELucky				u.uprops[LUCKY].extrinsic
+#define Lucky				(ELucky)
 
 #endif /* YOUPROP_H */
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/nh343-curses-a2.patch nethack/nh343-curses-a2.patch
--- nh_orig/nh343-curses-a2.patch	1969-12-31 19:00:00.000000000 -0500
+++ nethack/nh343-curses-a2.patch	2009-09-05 10:31:56.532294000 -0400
@@ -0,0 +1,9003 @@
+diff -burN nethack-3.4.3/doc/window.doc nethack/doc/window.doc
+--- nethack-3.4.3/doc/window.doc	2003-12-07 18:39:13.000000000 -0500
++++ nethack/doc/window.doc	2009-03-11 13:33:19.000000000 -0400
+@@ -518,6 +518,9 @@
+   |  fullscreen        | WC2_FULLSCREEN     | wc2_fullscreen     |boolean |
+   |  softkeyboard      | WC2_SOFTKEYBOARD   | wc2_softkeyboard   |boolean |
+   |  wraptext          | WC2_WRAPTEXT       | wc2_wraptext       |boolean |
++  |  term_cols         | WC2_TERM_COLS      | wc2_term_cols      |int     |
++  |  term_rows         | WC2_TERM_ROWS      | wc2_term_rows      |int     |
++  |  windowborders     | WC2_WINDOWBORDERS  | wc2_windowborders  |int     |
+   +--------------------+--------------------+--------------------+--------+
+ 
+ align_message	-- where to place message window (top, bottom, left, right)
+@@ -548,6 +551,8 @@
+ 		   is this number of cells away from the edge of the window.
+ softkeyboard    -- handhelds should display an on-screen keyboard if possible.
+ splash_screen   -- port should/should not display an opening splashscreen.
++term_cols       -- Terminal should size itself to specified width, if possible.
++term_rows       -- Terminal should size itself to specified height, if possible.
+ tiled_map	-- port should display a tiled map if it can.
+ tile_width	-- port should display tiles with this width or round to closest
+ 		   if it can.
+@@ -558,6 +563,8 @@
+ use_inverse	-- port should display inverse when NetHack asks for it.
+ vary_msgcount	-- port should display this number of messages at a time in
+ 		   the message window.
++windowborders   -- port should display borders around main NetHack windows.
++                Can be set to (1) on, (2) off, or (3) auto.
+ windowcolors
+ 		-- port should use these colors for window foreground/background
+ 		   colors.  Syntax:
+diff -burN nethack-3.4.3/include/config.h nethack/include/config.h
+--- nethack-3.4.3/include/config.h	2003-12-07 18:39:13.000000000 -0500
++++ nethack/include/config.h	2009-03-05 13:50:37.000000000 -0500
+@@ -42,7 +42,8 @@
+  * Define all of those you want supported in your binary.
+  * Some combinations make no sense.  See the installation document.
+  */
+-#define TTY_GRAPHICS	/* good old tty based graphics */
++/* #define TTY_GRAPHICS */	/* good old tty based graphics */
++#define CURSES_GRAPHICS     /* Proper curses interface */
+ /* #define X11_GRAPHICS */	/* X11 interface */
+ /* #define QT_GRAPHICS */	/* Qt interface */
+ /* #define GNOME_GRAPHICS */	/* Gnome interface */
+@@ -113,6 +114,15 @@
+ # define HACKDIR "\\nethack"
+ #endif
+ 
++#ifdef CURSES_GRAPHICS
++# ifdef TTY_GRAPHICS
++# undef TTY_GRAPHICS
++# endif
++# ifndef DEFAULT_WINDOW_SYS
++#  define DEFAULT_WINDOW_SYS "curses"
++# endif
++#endif
++
+ #ifndef DEFAULT_WINDOW_SYS
+ # define DEFAULT_WINDOW_SYS "tty"
+ #endif
+@@ -169,11 +179,11 @@
+ 
+ #ifdef UNIX
+ /* path and file name extension for compression program */
+-#define COMPRESS "/usr/bin/compress"	/* Lempel-Ziv compression */
+-#define COMPRESS_EXTENSION ".Z"		/* compress's extension */
++/* #define COMPRESS "/usr/bin/compress" */	/* Lempel-Ziv compression */
++/* #define COMPRESS_EXTENSION ".Z"	*/	/* compress's extension */
+ /* An example of one alternative you might want to use: */
+-/* #define COMPRESS "/usr/local/bin/gzip" */	/* FSF gzip compression */
+-/* #define COMPRESS_EXTENSION ".gz" */		/* normal gzip extension */
++#define COMPRESS "/bin/gzip"	/* FSF gzip compression */
++#define COMPRESS_EXTENSION ".gz"		/* normal gzip extension */
+ #endif
+ 
+ #ifndef COMPRESS
+diff -burN nethack-3.4.3/include/flag.h nethack/include/flag.h
+--- nethack-3.4.3/include/flag.h	2003-12-07 18:39:13.000000000 -0500
++++ nethack/include/flag.h	2009-03-05 13:50:37.000000000 -0500
+@@ -156,6 +156,7 @@
+ 
+ struct instance_flags {
+ 	boolean  cbreak;	/* in cbreak mode, rogue format */
++    boolean  cursesgraphics;    /* Use portable curses extended characters */
+ 	boolean  DECgraphics;	/* use DEC VT-xxx extended character set */
+ 	boolean  echo;		/* 1 to echo characters */
+ 	boolean  IBMgraphics;	/* use IBM extended character set */
+@@ -181,6 +182,8 @@
+ #endif
+ #ifdef TTY_GRAPHICS
+ 	char prevmsg_window;	/* type of old message window to use */
++#endif
++#if defined(TTY_GRAPHICS) || defined(CURSES_GRAPHICS)
+ 	boolean  extmenu;	/* extended commands use menu interface */
+ #endif
+ #ifdef MFLOPPY
+@@ -263,6 +266,9 @@
+ 	boolean wc2_fullscreen;		/* run fullscreen */
+ 	boolean wc2_softkeyboard;	/* use software keyboard */
+ 	boolean wc2_wraptext;		/* wrap text */
++    int     wc2_term_cols;      /* terminal width, in characters */
++    int     wc2_term_rows;      /* terminal height, in characters */
++    int     wc2_windowborders;  /* display borders on NetHack windows */
+ 
+ 	boolean  cmdassist;	/* provide detailed assistance for some commands */
+ 	boolean	 obsolete;	/* obsolete options can point at this, it isn't used */
+diff -burN nethack-3.4.3/include/ntconf.h nethack/include/ntconf.h
+--- nethack-3.4.3/include/ntconf.h	2003-12-07 18:39:13.000000000 -0500
++++ nethack/include/ntconf.h	2009-03-11 13:27:04.000000000 -0400
+@@ -159,7 +159,9 @@
+ long _RTLENTRY _EXPFUNC lseek  (int __handle, long __offset, int __fromwhere);
+ int  _RTLENTRY _EXPFUNC read  (int __handle, void _FAR *__buf, unsigned __len);
+ #endif
+-#include <conio.h>
++#ifndef CURSES_GRAPHICS
++# include <conio.h>
++#endif
+ #undef kbhit		/* Use our special NT kbhit */
+ #define kbhit (*nt_kbhit)
+ 
+diff -burN nethack-3.4.3/include/rm.h nethack/include/rm.h
+--- nethack-3.4.3/include/rm.h	2003-12-07 18:39:13.000000000 -0500
++++ nethack/include/rm.h	2009-03-05 13:50:38.000000000 -0500
+@@ -234,6 +234,7 @@
+ #define IBM_GRAPHICS	1	/* PC graphic characters */
+ #define DEC_GRAPHICS	2	/* VT100 line drawing characters */
+ #define MAC_GRAPHICS	3	/* Macintosh drawing characters */
++#define CURS_GRAPHICS   4   /* Portable curses drawing characters */
+ 
+ /*
+  * The 5 possible states of doors
+diff -burN nethack-3.4.3/include/wincurs.h nethack/include/wincurs.h
+--- nethack-3.4.3/include/wincurs.h	1969-12-31 19:00:00.000000000 -0500
++++ nethack/include/wincurs.h	2009-03-05 13:50:38.000000000 -0500
+@@ -0,0 +1,250 @@
++#ifndef WINCURS_H
++#define WINCURS_H
++
++/* Global declarations for curses interface */
++
++int term_rows, term_cols; /* size of underlying terminal */
++
++WINDOW *base_term;    /* underlying terminal window */
++
++WINDOW *mapborderwin;
++
++
++#define TEXTCOLOR   /* Allow color */
++#define NHW_END 19
++#define OFF 0
++#define ON 1
++#define NONE -1
++#define KEY_ESC 0x1b
++#define DIALOG_BORDER_COLOR CLR_MAGENTA
++#define HIGHLIGHT_COLOR CLR_WHITE
++#define MORECOLOR CLR_ORANGE
++#define STAT_UP_COLOR CLR_GREEN
++#define STAT_DOWN_COLOR CLR_RED
++#define MESSAGE_WIN 1
++#define STATUS_WIN  2
++#define MAP_WIN     3
++#define HPOS_WIN    4
++#define MESG_HISTORY_MAX   200
++
++
++typedef enum orient_type
++{
++    CENTER,
++    UP,
++    DOWN,
++    RIGHT,
++    LEFT
++} orient;
++
++
++/* cursmain.c */
++
++extern struct window_procs curses_procs;
++
++extern void curses_init_nhwindows(int* argcp, char** argv);
++
++extern void curses_player_selection(void);
++
++extern void curses_askname(void);
++
++extern void curses_get_nh_event(void);
++
++extern void curses_exit_nhwindows(const char *str);
++
++extern void curses_suspend_nhwindows(const char *str);
++
++extern void curses_resume_nhwindows(void);
++
++extern winid curses_create_nhwindow(int type);
++
++extern void curses_clear_nhwindow(winid wid);
++
++extern void curses_display_nhwindow(winid wid, BOOLEAN_P block);
++
++extern void curses_destroy_nhwindow(winid wid);
++
++extern void curses_curs(winid wid, int x, int y);
++
++extern void curses_putstr(winid wid, int attr, const char *text);
++
++extern void curses_display_file(const char *filename,BOOLEAN_P must_exist);
++
++extern void curses_start_menu(winid wid);
++
++extern void curses_add_menu(winid wid, int glyph, const ANY_P * identifier,
++		CHAR_P accelerator, CHAR_P group_accel, int attr, 
++		const char *str, BOOLEAN_P presel);
++
++extern void curses_end_menu(winid wid, const char *prompt);
++
++extern int curses_select_menu(winid wid, int how, MENU_ITEM_P **selected);
++
++extern void curses_update_inventory(void);
++
++extern void curses_mark_synch(void);
++
++extern void curses_wait_synch(void);
++
++extern void curses_cliparound(int x, int y);
++
++extern void curses_print_glyph(winid wid,XCHAR_P x,XCHAR_P y,int glyph);
++
++extern void curses_raw_print(const char *str);
++
++extern void curses_raw_print_bold(const char *str);
++
++extern int curses_nhgetch(void);
++
++extern int curses_nh_poskey(int *x, int *y, int *mod);
++
++extern void curses_nhbell(void);
++
++extern int curses_doprev_message(void);
++
++extern char curses_yn_function(const char *question, const char *choices, CHAR_P def);
++
++extern void curses_getlin(const char *question, char *input);
++
++extern int curses_get_ext_cmd(void);
++
++extern void curses_number_pad(int state);
++
++extern void curses_delay_output(void);
++
++extern void curses_start_screen(void);
++
++extern void curses_end_screen(void);
++
++extern void curses_outrip(winid wid, int how);
++
++extern void genl_outrip(winid tmpwin, int how);
++
++extern void curses_preference_update(const char *pref);
++
++
++/* curswins.c */
++
++extern WINDOW *curses_create_window(int width, int height, orient orientation);
++
++extern void curses_destroy_win(WINDOW *win);
++
++extern WINDOW *curses_get_nhwin(winid wid);
++
++extern void curses_add_nhwin(winid wid, int height, int width, int y,
++ int x, orient orientation, boolean border);
++
++extern void curses_refresh_nhwin(winid wid);
++
++extern void curses_refresh_nethack_windows(void);
++
++extern void curses_del_nhwin(winid wid);
++
++extern void curses_putch(winid wid, int x, int y, int ch, int color, int attrs);
++
++extern void curses_get_window_size(winid wid, int *height, int *width);
++
++extern boolean curses_window_has_border(winid wid);
++
++extern boolean curses_window_exists(winid wid);
++
++extern int curses_get_window_orientation(winid wid);
++
++extern void curses_get_window_xy(winid wid, int *x, int *y);
++
++extern void curses_puts(winid wid, int attr, const char *text);
++
++
++/* cursmisc.c */
++
++extern int curses_read_char(void);
++
++extern void curses_toggle_color_attr(WINDOW *win, int color, int attr, int onoff);
++
++extern void curses_bail(const char *mesg);
++
++extern winid curses_get_wid(int type);
++
++extern char *curses_copy_of(const char *s);
++
++extern int curses_num_lines(const char *str, int width);
++
++extern char *curses_break_str(const char *str, int width, int line_num);
++
++extern char *curses_str_remainder(const char *str, int width, int line_num);
++
++extern boolean curses_is_menu(winid wid);
++
++extern boolean curses_is_text(winid wid);
++
++extern int curses_convert_glyph(int ch, int glyph);
++
++extern void curses_move_cursor(winid wid, int x, int y);
++
++extern void curses_prehousekeeping(void);
++
++extern void curses_posthousekeeping(void);
++
++extern void curses_view_file(const char *filename, boolean must_exist);
++
++extern char *curses_rtrim(char *str);
++
++
++/* cursdial.c */
++
++extern void curses_line_input_dialog(const char *prompt, char *answer, int buffer);
++
++extern int curses_character_input_dialog(const char *prompt, const char *choices, CHAR_P def);
++
++extern int curses_ext_cmd(void);
++
++extern void curses_create_nhmenu(winid wid);
++
++extern void curses_add_nhmenu_item(winid wid, const ANY_P *identifier,
++ CHAR_P accelerator, CHAR_P group_accel, int attr, const char *str,
++ BOOLEAN_P presel);
++
++extern void curses_finalize_nhmenu(winid wid, const char *prompt);
++
++extern int curses_display_nhmenu(winid wid, int how, MENU_ITEM_P **_selected);
++
++extern boolean curses_menu_exists(winid wid);
++
++extern void curses_del_menu(winid wid);
++
++
++/* cursstat.c */
++
++extern void curses_update_stats(void);
++
++extern void curses_decrement_highlight(void);
++
++
++/* cursinit.c */
++
++extern void curses_create_main_windows(void);
++
++extern void curses_init_nhcolors(void);
++
++extern void curses_choose_character(void);
++
++extern int curses_character_dialog(const char** choices, const char *prompt);
++
++extern void curses_init_options(void);
++
++
++/* cursmesg.c */
++
++extern void curses_message_win_puts(const char *message, boolean recursed);
++
++extern void curses_more(void);
++
++extern void curses_clear_unhighlight_message_window(void);
++
++extern void curses_last_messages(void);
++
++extern void curses_init_mesg_history(void);
++
++
++#endif  /* WINCURS_H */
++
+diff -burN nethack-3.4.3/include/winprocs.h nethack/include/winprocs.h
+--- nethack-3.4.3/include/winprocs.h	2003-12-07 18:39:13.000000000 -0500
++++ nethack/include/winprocs.h	2009-03-05 13:50:38.000000000 -0500
+@@ -176,8 +176,11 @@
+ 
+ #define WC2_FULLSCREEN		0x01L	/* 01 display full screen                    */
+ #define WC2_SOFTKEYBOARD	0x02L	/* 02 software keyboard                      */
+-#define WC2_WRAPTEXT		0x04L	/* 04 wrap long lines of text                */
+-					/* 29 free bits */
++#define WC2_WRAPTEXT		0x04L	/* 03 wrap long lines of text                */
++#define WC2_TERM_COLS		0x08L	/* 04 supports setting terminal width        */
++#define WC2_TERM_ROWS		0x10L	/* 05 supports setting terminal height       */
++#define WC2_WINDOWBORDERS	0x20L	/* 06 display borders for NetHack windows    */
++					/* 26 free bits */
+ 
+ #define ALIGN_LEFT	1
+ #define ALIGN_RIGHT	2
+diff -burN nethack-3.4.3/src/cmd.c nethack/src/cmd.c
+--- nethack-3.4.3/src/cmd.c	2003-12-07 18:39:13.000000000 -0500
++++ nethack/src/cmd.c	2009-03-05 13:50:38.000000000 -0500
+@@ -322,7 +322,7 @@
+ 	return 0;
+ }
+ 
+-#ifdef TTY_GRAPHICS
++#if defined(TTY_GRAPHICS) || defined(CURSES_GRAPHICS)
+ #define MAX_EXT_CMD 40		/* Change if we ever have > 40 ext cmds */
+ /*
+  * This is currently used only by the tty port and is
+diff -burN nethack-3.4.3/src/drawing.c nethack/src/drawing.c
+--- nethack-3.4.3/src/drawing.c	2003-12-07 18:39:13.000000000 -0500
++++ nethack/src/drawing.c	2009-03-05 13:50:38.000000000 -0500
+@@ -4,7 +4,6 @@
+ 
+ #include "hack.h"
+ #include "tcap.h"
+-
+ /* Relevent header information in rm.h and objclass.h. */
+ 
+ #ifdef C
+@@ -314,6 +313,10 @@
+ void NDECL((*ibmgraphics_mode_callback)) = 0;	/* set in tty_start_screen() */
+ #endif /* PC9800 */
+ 
++#ifdef CURSES_GRAPHICS
++void NDECL((*cursesgraphics_mode_callback)) = 0;
++#endif
++
+ static uchar ibm_graphics[MAXPCHARS] = {
+ /* 0*/	g_FILLER(S_stone),
+ 	0xb3,	/* S_vwall:	meta-3, vertical rule */
+@@ -674,6 +677,9 @@
+  */
+ 	    iflags.IBMgraphics = TRUE;
+ 	    iflags.DECgraphics = FALSE;
++#ifdef CURSES_GRAPHICS
++        iflags.cursesgraphics = FALSE;
++#endif
+ 	    assign_graphics(ibm_graphics, SIZE(ibm_graphics), MAXPCHARS, 0);
+ #ifdef PC9800
+ 	    if (ibmgraphics_mode_callback) (*ibmgraphics_mode_callback)();
+@@ -687,6 +693,9 @@
+  */
+ 	    iflags.DECgraphics = TRUE;
+ 	    iflags.IBMgraphics = FALSE;
++#ifdef CURSES_GRAPHICS
++        iflags.cursesgraphics = FALSE;
++#endif
+ 	    assign_graphics(dec_graphics, SIZE(dec_graphics), MAXPCHARS, 0);
+ 	    if (decgraphics_mode_callback) (*decgraphics_mode_callback)();
+ 	    break;
+@@ -696,6 +705,12 @@
+ 	    assign_graphics(mac_graphics, SIZE(mac_graphics), MAXPCHARS, 0);
+ 	    break;
+ #endif
++#ifdef CURSES_GRAPHICS
++    case CURS_GRAPHICS:
++	    iflags.IBMgraphics = FALSE;
++	    iflags.DECgraphics = FALSE;
++        break;
++#endif
+ 	}
+     return;
+ }
+diff -burN nethack-3.4.3/src/options.c nethack/src/options.c
+--- nethack-3.4.3/src/options.c	2003-12-07 18:39:13.000000000 -0500
++++ nethack/src/options.c	2009-03-05 13:50:38.000000000 -0500
+@@ -69,19 +69,24 @@
+ 	{"checkspace", (boolean *)0, FALSE, SET_IN_FILE},
+ #endif
+ 	{"cmdassist", &iflags.cmdassist, TRUE, SET_IN_GAME},
+-# if defined(MICRO) || defined(WIN32)
++# if defined(MICRO) || defined(WIN32) || defined(CURSES_GRAPHICS)
+ 	{"color",         &iflags.wc_color,TRUE, SET_IN_GAME},		/*WC*/
+ # else	/* systems that support multiple terminals, many monochrome */
+ 	{"color",         &iflags.wc_color, FALSE, SET_IN_GAME},	/*WC*/
+ # endif
+ 	{"confirm",&flags.confirm, TRUE, SET_IN_GAME},
++#ifdef CURSES_GRAPHICS
++	{"cursesgraphics", &iflags.cursesgraphics, TRUE, SET_IN_GAME},
++#else
++	{"cursesgraphics", (boolean *)0, FALSE, SET_IN_FILE},
++#endif
+ #if defined(TERMLIB) && !defined(MAC_GRAPHICS_ENV)
+ 	{"DECgraphics", &iflags.DECgraphics, FALSE, SET_IN_GAME},
+ #else
+ 	{"DECgraphics", (boolean *)0, FALSE, SET_IN_FILE},
+ #endif
+ 	{"eight_bit_tty", &iflags.wc_eight_bit_input, FALSE, SET_IN_GAME},	/*WC*/
+-#ifdef TTY_GRAPHICS
++#if defined(TTY_GRAPHICS) || defined(CURSES_GRAPHICS)
+ 	{"extmenu", &iflags.extmenu, FALSE, SET_IN_GAME},
+ #else
+ 	{"extmenu", (boolean *)0, FALSE, SET_IN_FILE},
+@@ -2043,6 +2048,49 @@
+ 		return;
+ 	}
+ 
++	/* WINCAP2
++	 * term_cols:amount */
++	fullname = "term_cols";
++	if (match_optname(opts, fullname, sizeof("term_cols")-1, TRUE)) {
++		op = string_for_opt(opts, negated);
++		iflags.wc2_term_cols = atoi(op);
++		if (negated) bad_negation(fullname, FALSE);
++		return;
++	}
++
++	/* WINCAP2
++	 * term_rows:amount */
++	fullname = "term_rows";
++	if (match_optname(opts, fullname, sizeof("term_rows")-1, TRUE)) {
++		op = string_for_opt(opts, negated);
++		iflags.wc2_term_rows = atoi(op);
++		if (negated) bad_negation(fullname, FALSE);
++		return;
++	}
++
++
++	/* WINCAP2
++	 * windowborders:n */
++	fullname = "windowborders";
++	if (match_optname(opts, fullname, sizeof("windowborders")-1, TRUE)) {
++		op = string_for_opt(opts, negated);
++		if (negated && op) bad_negation(fullname, TRUE);
++		else {
++		    if (negated)
++		        iflags.wc2_windowborders = 2; /* Off */
++		    else if (!op)
++		        iflags.wc2_windowborders = 1; /* On */
++		    else    /* Value supplied */
++		        iflags.wc2_windowborders = atoi(op);
++		    if ((iflags.wc2_windowborders > 3) ||
++		     (iflags.wc2_windowborders < 1)) {
++		        iflags.wc2_windowborders = 0;
++		        badoption(opts);
++		    }
++		}
++		return;
++	}
++
+ 	/* menustyle:traditional or combo or full or partial */
+ 	if (match_optname(opts, "menustyle", 4, TRUE)) {
+ 		int tmp;
+@@ -2149,7 +2197,7 @@
+ 
+ 			duplicate_opt_detection(boolopt[i].name, 0);
+ 
+-#if defined(TERMLIB) || defined(ASCIIGRAPH) || defined(MAC_GRAPHICS_ENV)
++#if defined(TERMLIB) || defined(ASCIIGRAPH) || defined(MAC_GRAPHICS_ENV) || defined(CURSES_GRAPHICS)
+ 			if (FALSE
+ # ifdef TERMLIB
+ 				 || (boolopt[i].addr) == &iflags.DECgraphics
+@@ -2160,6 +2208,9 @@
+ # ifdef MAC_GRAPHICS_ENV
+ 				 || (boolopt[i].addr) == &iflags.MACgraphics
+ # endif
++# ifdef CURSES_GRAPHICS
++				 || (boolopt[i].addr) == &iflags.cursesgraphics
++# endif
+ 				) {
+ # ifdef REINCARNATION
+ 			    if (!initial && Is_rogue_level(&u.uz))
+@@ -2181,6 +2232,11 @@
+ 				switch_graphics(iflags.MACgraphics ?
+ 						MAC_GRAPHICS : ASCII_GRAPHICS);
+ # endif
++# ifdef CURSES_GRAPHICS
++			    if ((boolopt[i].addr) == &iflags.cursesgraphics)
++				switch_graphics(iflags.cursesgraphics ?
++						CURS_GRAPHICS : ASCII_GRAPHICS);
++# endif
+ # ifdef REINCARNATION
+ 			    if (!initial && Is_rogue_level(&u.uz))
+ 				assign_rogue_graphics(TRUE);
+@@ -2226,6 +2282,11 @@
+ 					(boolopt[i].addr) == &iflags.hilite_pet) {
+ 			    need_redraw = TRUE;
+ 			}
++#ifdef CURSES_GRAPHICS
++			else if ((boolopt[i].addr) == &iflags.cursesgraphics) {
++			    need_redraw = TRUE;
++			}
++#endif
+ #ifdef TEXTCOLOR
+ 			else if ((boolopt[i].addr) == &iflags.use_color) {
+ 			    need_redraw = TRUE;
+@@ -3087,6 +3148,14 @@
+ 			FEATURE_NOTICE_VER_MIN,
+ 			FEATURE_NOTICE_VER_PATCH);
+ 	}
++	else if (!strcmp(optname, "term_cols")) {
++		if (iflags.wc2_term_cols) Sprintf(buf, "%d",iflags.wc2_term_cols);
++		else Strcpy(buf, defopt);
++	}
++	else if (!strcmp(optname, "term_rows")) {
++		if (iflags.wc2_term_rows) Sprintf(buf, "%d",iflags.wc2_term_rows);
++		else Strcpy(buf, defopt);
++	}
+ 	else if (!strcmp(optname, "tile_file"))
+ 		Sprintf(buf, "%s", iflags.wc_tile_file ? iflags.wc_tile_file : defopt);
+ 	else if (!strcmp(optname, "tile_height")) {
+@@ -3120,6 +3189,11 @@
+ 			ttycolors[CLR_BRIGHT_MAGENTA],
+ 			ttycolors[CLR_BRIGHT_CYAN]);
+ #endif /* VIDEOSHADES */
++	else if (!strcmp(optname,"windowborders"))
++		Sprintf(buf, "%s", iflags.wc2_windowborders == 1     ? "1=on" :
++				   iflags.wc2_windowborders == 2             ? "2=off" :
++				   iflags.wc2_windowborders == 3             ? "3=auto" :
++				   defopt);
+ 	else if (!strcmp(optname, "windowtype"))
+ 		Sprintf(buf, "%s", windowprocs.name);
+ 	else if (!strcmp(optname, "windowcolors"))
+@@ -3593,6 +3667,9 @@
+ 	{"fullscreen", WC2_FULLSCREEN},
+ 	{"softkeyboard", WC2_SOFTKEYBOARD},
+ 	{"wraptext", WC2_WRAPTEXT},
++	{"term_cols", WC2_TERM_COLS},
++	{"term_rows", WC2_TERM_ROWS},
++	{"windowborders", WC2_WINDOWBORDERS},
+ 	{(char *)0, 0L}
+ };
+ 
+diff -burN nethack-3.4.3/src/rip.c nethack/src/rip.c
+--- nethack-3.4.3/src/rip.c	2003-12-07 18:39:13.000000000 -0500
++++ nethack/src/rip.c	2009-03-05 13:50:38.000000000 -0500
+@@ -8,7 +8,7 @@
+ 
+ extern const char * const killed_by_prefix[];	/* from topten.c */
+ 
+-#if defined(TTY_GRAPHICS) || defined(X11_GRAPHICS) || defined(GEM_GRAPHICS) || defined(MSWIN_GRAPHICS)
++#if defined(TTY_GRAPHICS) || defined(X11_GRAPHICS) || defined(GEM_GRAPHICS) || defined(MSWIN_GRAPHICS) || defined(CURSES_GRAPHICS)
+ # define TEXT_TOMBSTONE
+ #endif
+ #if defined(mac) || defined(__BEOS__) || defined(WIN32_GRAPHICS)
+diff -burN nethack-3.4.3/src/windows.c nethack/src/windows.c
+--- nethack-3.4.3/src/windows.c	2003-12-07 18:39:13.000000000 -0500
++++ nethack/src/windows.c	2009-03-05 13:50:38.000000000 -0500
+@@ -6,6 +6,9 @@
+ #ifdef TTY_GRAPHICS
+ #include "wintty.h"
+ #endif
++#ifdef CURSES_GRAPHICS
++extern struct window_procs curses_procs;
++#endif
+ #ifdef X11_GRAPHICS
+ /* cannot just blindly include winX.h without including all of X11 stuff */
+ /* and must get the order of include files right.  Don't bother */
+@@ -53,6 +56,9 @@
+ #ifdef TTY_GRAPHICS
+     { &tty_procs, win_tty_init },
+ #endif
++#ifdef CURSES_GRAPHICS
++    { &curses_procs, 0 },
++#endif
+ #ifdef X11_GRAPHICS
+     { &X11_procs, win_X11_init },
+ #endif
+diff -burN nethack-3.4.3/sys/unix/Makefile.src nethack/sys/unix/Makefile.src
+--- nethack-3.4.3/sys/unix/Makefile.src	2003-12-07 18:39:13.000000000 -0500
++++ nethack/sys/unix/Makefile.src	2009-03-05 13:50:38.000000000 -0500
+@@ -61,7 +61,7 @@
+ #	if you get setcgtty() warnings during execution, you are feeding gcc
+ #		a non-ANSI <sys/ioctl.h> -- either run fixincludes on it or use
+ #		-traditional in CFLAGS
+-# CC = gcc
++CC = gcc
+ #
+ #	For Bull DPX/2 systems at B.O.S. 2.0 or higher use the following:
+ #
+@@ -141,6 +141,15 @@
+ #LINK = gcc
+ #LFLAGS = -Xlinker -soname=_APP_
+ 
++# Compile with PDCurses installed in a separate directory that doesn't
++# conflict with the system curses/ncurses library
++#CFLAGS = -O -I../include -I/usr/local/include/pdcurses
++# Same as above, but for XCurses
++#CFLAGS = -O -DXCURSES -I../include -I/usr/local/include/pdcurses
++# Compile against system curses library, such as ncurses
++CFLAGS = -O -I../include
++
++
+ # Only used for the Gnome interface.
+ # When including the Gnome interface, you need to include gnome specific
+ # directories.  The ones given below is the usual spot for linux systems.
+@@ -151,8 +160,8 @@
+ # flags for debugging:
+ # CFLAGS = -g -I../include
+ 
+-CFLAGS = -O -I../include
+-LFLAGS = 
++#CFLAGS = -O -I../include
++#LFLAGS = 
+ 
+ # The Qt and Be window systems are written in C++, while the rest of
+ # NetHack is standard C.  If using Qt, uncomment the LINK line here to get
+@@ -174,6 +183,14 @@
+ 	../win/tty/wintty.c
+ WINTTYOBJ = getline.o termcap.o topl.o wintty.o
+ #
++# Files for curses interface
++WINCURSESSRC = ../win/curses/cursmain.c ../win/curses/curswins.c \
++	../win/curses/cursmisc.c ../win/curses/cursdial.c \
++	../win/curses/cursstat.c ../win/curses/cursinit.c \
++	../win/curses/cursmesg.c
++WINCURSESOBJ = cursmain.o curswins.o cursmisc.o cursdial.o cursstat.o \
++	cursinit.o cursmesg.o
++#
+ # files for an X11 port
+ # (tile.c is a generated source file)
+ WINX11SRC = ../win/X11/Window.c ../win/X11/dialogs.c ../win/X11/winX.c \
+@@ -214,8 +231,8 @@
+ 
+ #
+ #
+-WINSRC = $(WINTTYSRC)
+-WINOBJ = $(WINTTYOBJ)
++WINSRC = $(WINCURSESSRC)
++WINOBJ = $(WINCURSESOBJ)
+ 
+ # on some systems the termcap library is in -ltermcap or -lcurses
+ # on 386 Xenix, the -ltermlib tputs() seems not to work; use -lcurses instead
+@@ -231,8 +248,15 @@
+ # WINTTYLIB = -lcurses
+ # WINTTYLIB = -lcurses16
+ # WINTTYLIB = -lncurses
+-WINTTYLIB = -ltermlib
++# WINTTYLIB = -ltermlib
+ #
++# libraries for curses port
++# link with ncurses
++WINCURSESLIB = -lncurses
++# link with pdcurses for SDL, installed in a separate directory
++#WINCURSESLIB = -L/usr/local/lib/pdcurses -lpdcurses -lSDL
++# same as above, for XCurses
++#WINCURSESLIB = -L/usr/local/lib/pdcurses -lXCurses -lXawM -lXmu -lXext -lXt -lX11
+ # libraries for X11
+ # If USE_XPM is defined in config.h, you will also need -lXpm here.
+ WINX11LIB = -lXaw -lXmu -lXext -lXt -lX11
+@@ -255,7 +279,7 @@
+ # libraries for BeOS 
+ WINBELIB = -lbe
+ 
+-WINLIB = $(WINTTYLIB)
++WINLIB = $(WINCURSESLIB)
+ 
+ # any other strange libraries your system needs (for Sysunix only -- the more
+ # specialized targets should already be right)
+@@ -605,6 +629,26 @@
+ wintty.o: ../win/tty/wintty.c $(HACK_H) ../include/dlb.h \
+ 		../include/patchlevel.h ../include/tcap.h
+ 	$(CC) $(CFLAGS) -c ../win/tty/wintty.c
++cursmain.o: ../win/curses/cursmain.c $(HACK_H) ../include/wincurs.h
++	$(CC) $(CFLAGS) -c ../win/curses/cursmain.c
++curswins.o: ../win/curses/curswins.c $(HACK_H) ../include/func_tab.h \
++		../include/wincurs.h ../win/curses/curswins.h
++	$(CC) $(CFLAGS) -c ../win/curses/curswins.c
++cursmisc.o: ../win/curses/cursmisc.c $(HACK_H) ../include/wincurs.h \
++		../win/curses/cursmisc.h
++	$(CC) $(CFLAGS) -c ../win/curses/cursmisc.c
++cursdial.o: ../win/curses/cursdial.c $(HACK_H) ../include/func_tab.h \
++		../include/wincurs.h ../win/curses/cursdial.h
++	$(CC) $(CFLAGS) -c ../win/curses/cursdial.c
++cursstat.o: ../win/curses/cursstat.c $(HACK_H) ../include/wincurs.h \
++		../win/curses/cursstat.h
++	$(CC) $(CFLAGS) -c ../win/curses/cursstat.c
++cursinit.o: ../win/curses/cursinit.c $(HACK_H) ../include/wincurs.h \
++		../win/curses/cursinit.h
++	$(CC) $(CFLAGS) -c ../win/curses/cursinit.c
++cursmesg.o: ../win/curses/cursmesg.c $(HACK_H) ../include/wincurs.h \
++		../win/curses/cursmesg.h
++	$(CC) $(CFLAGS) -c ../win/curses/cursmesg.c
+ Window.o: ../win/X11/Window.c ../include/xwindowp.h ../include/xwindow.h \
+ 		$(CONFIG_H)
+ 	$(CC) $(CFLAGS) -c ../win/X11/Window.c
+diff -burN nethack-3.4.3/sys/winnt/cursmake.gcc nethack/sys/winnt/cursmake.gcc
+--- nethack-3.4.3/sys/winnt/cursmake.gcc	1969-12-31 19:00:00.000000000 -0500
++++ nethack/sys/winnt/cursmake.gcc	2009-03-05 13:50:38.000000000 -0500
+@@ -0,0 +1,1357 @@
++#   SCCS Id: @(#)Makefile.gcc       3.4     $Date: 2003/11/16 04:50:57 $
++#   Copyright (c) NetHack PC Development Team 1993-2003
++#
++#   NetHack 3.4.x Makefile for MinGW
++#
++#   Win32 Compilers Tested:
++#                  - MinGW 1.0 (gcc version 2.95.3-6) (Console NetHack only)
++#                  - MinGW 2.0 (gcc version 3.2)
++#
++#   If you don't have this compiler, you can get it at:
++#       http://www.mingw.org/
++#
++#   This is used for building two versions of NetHack:
++#   A tty port utilizing the Win32 Console I/O subsystem, Console
++#       NetHack;
++#   A Win32 native port built on the Windows API, Graphical NetHack or
++#       NetHackW.
++#
++#   In addition to your C compiler,
++#
++#     if you want to change     you will need a
++#     files with suffix         workalike for
++#         .y                     yacc   (such as bison)
++#         .l                     lex    (such as flex)
++#
++#
++#   If you have any questions read the sys/winnt/Install.nt file included
++#   with the distribution.
++#
++#   --
++#   Dion Nicolaas
++#==============================================================================
++# Graphical interface
++# Set to Y for a graphical version
++# Set to anything else (or undefine) for a tty version
++
++GRAPHICAL = N
++
++# Debug
++# Set to Y for Debug support (to produce debug information)
++# Set to anything else (or undefine) for a "release" version
++# You can set your debug options below.
++
++DEBUG = Y
++
++cc     = gcc
++rc     = windres
++link   = gcc
++
++cflags = -mms-bitfields
++lflags  = 
++ifeq  "$(DEBUG)" "Y"
++cdebug = -g
++linkdebug = -g
++else
++cdebug =
++linkdebug =
++endif
++
++#
++#  Set the gamedir according to your preference.
++#  If not present prior to compilation it gets created.
++
++ifeq  "$(GRAPHICAL)" "Y"
++# Game Name
++GAME    = NetHackW
++else
++# Game Name
++GAME    = NetHackC
++endif
++# Game directory
++GAMEDIR = ../binary
++
++#
++#  Source directories.    Makedefs hardcodes these, don't change them.
++#
++
++# NetHack include files
++INCL  = ../include
++# NetHack data files
++DAT   = ../dat
++# NetHack documentation files
++DOC   = ../doc
++# Utility source
++UTIL  = ../util
++# Main source
++SRC   = ../src
++# Shared system files
++SSYS  = ../sys/share
++# NT Win32 specific files
++NTSYS = ../sys/winnt
++# window port files (tty)
++#TTY   = ../win/tty
++TTY   = ../win/curses
++# window port files (Win32)
++WIN32 = ../win/win32
++# Tile support files
++WSHR  = ../win/share
++
++#
++#  Object directory.
++#
++
++OBJ = o
++
++
++#
++#==========================================
++# Exe File Info.
++#==========================================
++
++# Yacc/Lex ... if you got 'em.
++#
++# If you have yacc and lex programs (or work-alike such as bison
++# and flex), comment out the upper two macros and uncomment
++# the lower two.
++#
++
++DO_YACC = YACC_MSG
++DO_LEX  = LEX_MSG
++#DO_YACC  = YACC_ACT
++#DO_LEX   = LEX_ACT
++
++# - Specify your yacc and lex programs (or work-alikes) here.
++
++#YACC   = bison -y
++YACC   = byacc
++#YACC   = yacc
++
++#LEX    = lex
++LEX     = flex
++
++#
++# - Specify your flex skeleton file (if needed).
++#
++
++FLEXSKEL =
++#FLEXSKEL = -S../tools/flex.ske
++
++YTABC   = y_tab.c
++YTABH   = y_tab.h
++LEXYYC  = lexyy.c
++
++#
++# Optional high-quality BSD random number generation routines
++# (see pcconf.h). Set to nothing if not used.
++#
++
++RANDOM  = $(OBJ)/random.o
++#RANDOM =
++
++#===============================================
++#======= End of Modification Section ===========
++#===============================================
++################################################
++#                                              #
++# Nothing below here should have to be changed.#
++#                                              #
++################################################
++
++ifeq  "$(GRAPHICAL)" "Y"
++WINPORT  = $(O)tile.o $(O)mhaskyn.o $(O)mhdlg.o \
++	$(O)mhfont.o $(O)mhinput.o $(O)mhmain.o $(O)mhmap.o \
++	$(O)mhmenu.o $(O)mhmsgwnd.o $(O)mhrip.o $(O)mhsplash.o \
++	$(O)mhstatus.o $(O)mhtext.o $(O)mswproc.o $(O)winhack.o
++WINPFLAG   = -DTILES -DMSWIN_GRAPHICS -D_WIN32_IE=0x0400
++NHRES   = $(O)winres.o
++WINPINC = -I$(WIN32)
++WINPHDR = $(WIN32)/mhaskyn.h $(WIN32)/mhdlg.h $(WIN32)/mhfont.h \
++	$(WIN32)/mhinput.h $(WIN32)/mhmain.h $(WIN32)/mhmap.h \
++	$(WIN32)/mhmenu.h $(WIN32)/mhmsg.h $(WIN32)/mhmsgwnd.h \
++	$(WIN32)/mhrip.h $(WIN32)/mhstatus.h \
++	$(WIN32)/mhtext.h $(WIN32)/resource.h $(WIN32)/winMS.h
++WINPLIBS =  -lcomctl32 -lwinmm
++else
++WINPORT = $(O)nttty.o
++#WINPFLAG= -DWIN32CON
++WINPHDR =
++NHRES   = $(O)console.o
++WINPINC =
++#WINPLIBS = ../lib/pdcurses.a -lwinmm
++WINPLIBS = ../lib/libpdcurses.a ../lib/libSDL.a -lwinmm
++endif
++
++TILEUTIL16  = $(UTIL)/tile2bmp.exe
++TILEBMP16   = $(SRC)/tiles.bmp
++
++TILEUTIL32  = $(UTIL)/til2bm32.exe
++TILEBMP32   = $(SRC)/tiles32.bmp
++
++SOUND = $(OBJ)/ntsound.o
++
++#SOUND =
++
++# To store all the level files,
++# help files, etc. in a single library file.
++# USE_DLB = Y is left uncommented
++
++USE_DLB = Y
++
++ifeq  "$(USE_DLB)" "Y"
++DLBFLG = -DDLB
++else
++DLBFLG =
++endif
++
++#==========================================
++# Setting up the compiler and linker
++# macros. All builds include the base ones.
++#==========================================
++
++CFLAGSBASE  = -c $(cflags) -I$(INCL) $(WINPINC) $(cdebug)
++LFLAGSBASEC = $(linkdebug) -mwindows
++LFLAGSBASEG = $(linkdebug) -mwindows
++
++#==========================================
++# Util builds
++#==========================================
++
++CFLAGSU = $(CFLAGSBASE) $(WINPFLAG)
++LFLAGSU = $(LFLAGSBASEC)
++
++#==========================================
++# - Game build
++#==========================================
++
++CFLAGS   = $(CFLAGSBASE) $(WINPFLAG) $(DLBFLG)
++lflags  = $(LFLAGSBASE)
++ifeq "$(GRAPHICAL)" "Y"
++lflags  = $(LFLAGSBASEG)
++else
++lflags  = $(LFLAGSBASEC)
++endif
++
++GAMEFILE = $(GAMEDIR)/$(GAME).exe # whole thing
++
++ifeq  "$(USE_DLB)" "Y"
++DLB = nhdat
++else
++DLB =
++endif
++
++#==========================================
++#================ RULES ==================
++#==========================================
++
++.SUFFIXES: .exe .o .til .uu .c .y .l
++
++#==========================================
++# Rules for files in src
++#==========================================
++
++$(OBJ)/%.o : /%.c
++	$(cc) $(CFLAGS)  -o$@ $<
++
++$(OBJ)/%.o : $(SRC)/%.c
++	$(cc) $(CFLAGS)   -o$@  $<
++
++#==========================================
++# Rules for files in sys/share
++#==========================================
++
++$(OBJ)/%.o : $(SSYS)/%.c
++	$(cc) $(CFLAGS)  -o$@  $<
++
++#==========================================
++# Rules for files in sys/winnt
++#==========================================
++
++$(OBJ)/%.o : $(NTSYS)/%.c
++	$(cc) $(CFLAGS)  -o$@  $<
++
++$(INCL)/%.h : $(NTSYS)/%.h
++	@copy $< $@
++
++#==========================================
++# Rules for files in util
++#==========================================
++
++$(OBJ)/%.o : $(UTIL)/%.c
++	$(cc) $(CFLAGSU) -o$@ $<
++
++#==========================================
++# Rules for files in win/share
++#==========================================
++
++$(OBJ)/%.o : $(WSHR)/%.c
++	$(cc) $(CFLAGS)  -o$@ $<
++
++$(INCL)/%.h : $(WSHR)/%.h
++	@copy $< $@
++
++#{$(WSHR)}.txt{$(DAT)}.txt:
++#	@copy $< $@
++
++#==========================================
++# Rules for files in win/tty
++#==========================================
++
++$(OBJ)/%.o : $(TTY)/%.c
++	$(cc) $(CFLAGS)  -o$@  $<
++
++#==========================================
++# Rules for files in win/win32
++#==========================================
++
++$(OBJ)/%.o : $(WIN32)/%.c
++	$(cc) $(CFLAGS)  -o$@  $<
++
++#==========================================
++#================ MACROS ==================
++#==========================================
++# This section creates shorthand macros for many objects
++# referenced later on in the Makefile.
++#
++
++DEFFILE = $(NTSYS)/$(GAME).def
++
++#
++# Shorten up the location for some files
++#
++
++O  = $(OBJ)/
++
++U  = $(UTIL)/
++
++#
++# Utility Objects.
++#
++
++MAKESRC        = $(U)makedefs.c
++
++SPLEVSRC       = $(U)lev_yacc.c  $(U)lev_$(LEX).c $(U)lev_main.c  $(U)panic.c
++
++DGNCOMPSRC     = $(U)dgn_yacc.c  $(U)dgn_$(LEX).c $(U)dgn_main.c
++
++MAKEOBJS       = $(O)makedefs.o $(O)monst.o $(O)objects.o
++
++SPLEVOBJS      = $(O)lev_yacc.o  $(O)lev_$(LEX).o $(O)lev_main.o \
++	$(O)alloc.o   $(O)decl.o      $(O)drawing.o \
++	$(O)monst.o   $(O)objects.o   $(O)panic.o
++
++DGNCOMPOBJS    = $(O)dgn_yacc.o  $(O)dgn_$(LEX).o $(O)dgn_main.o \
++	$(O)alloc.o   $(O)panic.o
++
++RECOVOBJS      = $(O)recover.o
++
++TILEFILES      = $(WSHR)/monsters.txt $(WSHR)/objects.txt $(WSHR)/other.txt
++
++#
++# These are not invoked during a normal game build in 3.4
++#
++TEXT_IO        = $(O)tiletext.o  $(O)tiletxt.o   $(O)drawing.o \
++	$(O)decl.o    $(O)monst.o     $(O)objects.o
++
++TEXT_IO32      = $(O)tilete32.o $(O)tiletx32.o $(O)drawing.o \
++	$(O)decl.o    $(O)monst.o     $(O)objects.o
++
++GIFREADERS     = $(O)gifread.o   $(O)alloc.o $(O)panic.o
++GIFREADERS32   = $(O)gifrd32.o $(O)alloc.o $(O)panic.o
++
++PPMWRITERS     = $(O)ppmwrite.o $(O)alloc.o $(O)panic.o
++
++#
++#  Object files for the game itself.
++#
++
++VOBJ01 = $(O)allmain.o  $(O)alloc.o    $(O)apply.o    $(O)artifact.o
++VOBJ02 = $(O)attrib.o   $(O)ball.o     $(O)bones.o    $(O)botl.o
++VOBJ03 = $(O)cmd.o      $(O)dbridge.o  $(O)decl.o     $(O)detect.o
++VOBJ04 = $(O)dig.o      $(O)display.o  $(O)do.o       $(O)do_name.o
++VOBJ05 = $(O)do_wear.o  $(O)dog.o      $(O)dogmove.o  $(O)dokick.o
++VOBJ06 = $(O)dothrow.o  $(O)drawing.o  $(O)dungeon.o  $(O)eat.o
++VOBJ07 = $(O)end.o      $(O)engrave.o  $(O)exper.o    $(O)explode.o
++VOBJ08 = $(O)extralev.o $(O)files.o    $(O)fountain.o $(O)hack.o
++VOBJ09 = $(O)hacklib.o  $(O)invent.o   $(O)light.o    $(O)lock.o
++VOBJ10 = $(O)mail.o     $(O)makemon.o  $(O)mapglyph.o $(O)mcastu.o
++VOBJ11 = $(O)mhitm.o    $(O)mhitu.o    $(O)minion.o   $(O)mklev.o
++VOBJ12 = $(O)mkmap.o    $(O)mkmaze.o   $(O)mkobj.o    $(O)mkroom.o
++VOBJ13 = $(O)mon.o      $(O)mondata.o  $(O)monmove.o  $(O)monst.o
++VOBJ14 = $(O)monstr.o   $(O)mplayer.o  $(O)mthrowu.o  $(O)muse.o
++VOBJ15 = $(O)music.o    $(O)o_init.o   $(O)objects.o  $(O)objnam.o
++VOBJ16 = $(O)options.o  $(O)pager.o    $(O)pickup.o   $(O)pline.o
++VOBJ17 = $(O)polyself.o $(O)potion.o   $(O)pray.o     $(O)priest.o
++VOBJ18 = $(O)quest.o    $(O)questpgr.o $(RANDOM)      $(O)read.o
++VOBJ19 = $(O)rect.o     $(O)region.o   $(O)restore.o  $(O)rip.o
++VOBJ20 = $(O)rnd.o      $(O)role.o     $(O)rumors.o   $(O)save.o
++VOBJ21 = $(O)shk.o      $(O)shknam.o   $(O)sit.o      $(O)sounds.o
++VOBJ22 = $(O)sp_lev.o   $(O)spell.o    $(O)steal.o    $(O)steed.o
++VOBJ23 = $(O)teleport.o $(O)timeout.o  $(O)topten.o   $(O)track.o
++VOBJ24 = $(O)trap.o     $(O)u_init.o   $(O)uhitm.o    $(O)vault.o
++VOBJ25 = $(O)vis_tab.o  $(O)vision.o   $(O)weapon.o   $(O)were.o
++VOBJ26 = $(O)wield.o    $(O)windows.o  $(O)wizard.o   $(O)worm.o
++VOBJ27 = $(O)worn.o     $(O)write.o    $(O)zap.o
++
++DLBOBJ = $(O)dlb.o
++
++#TTYOBJ = $(O)topl.o     $(O)getline.o  $(O)wintty.o
++TTYOBJ = $(O)cursmain.o $(O)curswins.o  $(O)cursmisc.o $(O)cursdial.o \
++	$(O)cursstat.o $(O)cursinit.o $(O)cursmesg.o 
++
++SOBJ   = $(O)winnt.o    $(O)pcsys.o      $(O)pcunix.o  \
++	$(SOUND) $(O)pcmain.o $(O)mapimail.o $(O)nhlan.o
++
++OBJS   = $(VOBJ01) $(VOBJ02) $(VOBJ03) $(VOBJ04) $(VOBJ05) \
++	$(VOBJ06) $(VOBJ07) $(VOBJ08) $(VOBJ09) $(VOBJ10) \
++	$(VOBJ11) $(VOBJ12) $(VOBJ13) $(VOBJ14) $(VOBJ15) \
++	$(VOBJ16) $(VOBJ17) $(VOBJ18) $(VOBJ19) $(VOBJ20) \
++	$(VOBJ21) $(VOBJ22) $(VOBJ23) $(VOBJ24) $(VOBJ25) \
++	$(VOBJ26) $(VOBJ27)
++
++WINPOBJ = $(WINPORT)
++
++VVOBJ  = $(O)version.o
++
++ALLOBJ  = $(WINPOBJ) $(SOBJ) $(DLBOBJ)  $(TTYOBJ) $(WOBJ) $(OBJS) $(VVOBJ)
++
++ifeq "$(GRAPHICAL)" "Y"
++OPTIONS_FILE = $(DAT)/guioptions
++else
++OPTIONS_FILE = $(DAT)/ttyoptions
++endif
++
++#==========================================
++# Header file macros
++#==========================================
++
++CONFIG_H = $(INCL)/config.h $(INCL)/config1.h $(INCL)/tradstdc.h \
++	       $(INCL)/global.h $(INCL)/coord.h $(INCL)/vmsconf.h \
++	       $(INCL)/system.h $(INCL)/unixconf.h $(INCL)/os2conf.h \
++	       $(INCL)/micro.h $(INCL)/pcconf.h $(INCL)/tosconf.h \
++	       $(INCL)/amiconf.h $(INCL)/macconf.h $(INCL)/beconf.h \
++	       $(INCL)/ntconf.h $(INCL)/nhlan.h
++
++HACK_H = $(INCL)/hack.h $(CONFIG_H) $(INCL)/align.h \
++	       $(INCL)/dungeon.h $(INCL)/monsym.h $(INCL)/mkroom.h \
++	       $(INCL)/objclass.h $(INCL)/youprop.h $(INCL)/prop.h \
++	       $(INCL)/permonst.h $(INCL)/monattk.h \
++	       $(INCL)/monflag.h $(INCL)/mondata.h $(INCL)/pm.h \
++	       $(INCL)/wintype.h $(INCL)/decl.h $(INCL)/quest.h \
++	       $(INCL)/spell.h $(INCL)/color.h $(INCL)/obj.h \
++	       $(INCL)/you.h $(INCL)/attrib.h $(INCL)/monst.h \
++	       $(INCL)/skills.h $(INCL)/onames.h $(INCL)/timeout.h \
++	       $(INCL)/trap.h $(INCL)/flag.h $(INCL)/rm.h \
++	       $(INCL)/vision.h $(INCL)/display.h $(INCL)/engrave.h \
++	       $(INCL)/rect.h $(INCL)/region.h $(INCL)/winprocs.h \
++	       $(INCL)/wintty.h $(INCL)/trampoli.h
++
++LEV_H       = $(INCL)/lev.h
++DGN_FILE_H  = $(INCL)/dgn_file.h
++LEV_COMP_H  = $(INCL)/lev_comp.h
++SP_LEV_H    = $(INCL)/sp_lev.h
++TILE_H      = ../win/share/tile.h
++
++#==========================================
++# Miscellaneous
++#==========================================
++
++DATABASE = $(DAT)/data.base
++
++#
++#  The name of the game.
++#
++
++GAMEFILE = $(GAMEDIR)/$(GAME).exe
++
++
++#==========================================
++#=============== TARGETS ==================
++#==========================================
++
++# Since DOS doesn't allow / as path separator, and GCC doesn't allow \ as
++# path separator, we must change all pathnames when performing DOS commands.
++# This is done by blindly applying $(subst /,\, ...) on every command.
++# Where any command contain / for another reason (switch char, or echoing
++# comment lines to lev/dungeon files) a little more care is taken.
++
++#
++#  The default make target (so just typing 'nmake' is useful).
++#
++default : $(GAMEFILE)
++
++#
++#  The main target.
++#
++
++$(GAME) : $(O)obj.tag $(O)utility.tag graphicschk $(GAMEFILE)
++	@echo $(GAME) is up to date.
++
++#
++#  Everything
++#
++
++all :   install
++
++install: graphicschk $(GAME) $(O)install.tag
++	@echo Done.
++
++
++$(O)install.tag:  $(DAT)/data    $(DAT)/rumors    $(DAT)/dungeon \
++	       $(DAT)/oracles $(DAT)/quest.dat $(O)sp_lev.tag $(DLB)
++ifeq  "$(USE_DLB)" "Y"
++	$(subst /,\,copy nhdat                $(GAMEDIR))
++	$(subst /,\,copy $(DAT)/license       $(GAMEDIR))
++	$(subst /,\,copy $(DAT)/opthelp       $(GAMEDIR))
++else
++	$(subst /,\,copy $(DAT)/*.            $(GAMEDIR))
++	$(subst /,\,copy $(DAT)/*.dat         $(GAMEDIR))
++	$(subst /,\,copy $(DAT)/*.lev         $(GAMEDIR))
++	$(subst /,\,if exist $(GAMEDIR)/makefile del $(GAMEDIR)/makefile)
++endif
++	$(subst /,\,if exist $(DOC)/guidebook.txt copy $(DOC)/guidebook.txt $(GAMEDIR)/Guidebook.txt)
++	$(subst /,\,if exist $(DOC)/nethack.txt copy $(DOC)/nethack.txt $(GAMEDIR)/NetHack.txt)
++	$(subst /,\,copy $(NTSYS)/defaults.nh   $(GAMEDIR)/defaults.nh)
++	$(subst /,\,echo install done > $@)
++
++#  copy $(NTSYS)/winnt.hlp    $(GAMEDIR)
++
++recover: $(U)recover.exe
++	$(subst /,\,if exist $(U)recover.exe copy $(U)recover.exe  $(GAMEDIR))
++	$(subst /,\,if exist $(DOC)/recover.txt copy $(DOC)/recover.txt $(GAMEDIR)/recover.txt)
++
++$(O)sp_lev.tag: $(O)utility.tag $(DAT)/bigroom.des  $(DAT)/castle.des \
++	 $(DAT)/endgame.des $(DAT)/gehennom.des $(DAT)/knox.des   \
++	 $(DAT)/medusa.des  $(DAT)/oracle.des   $(DAT)/tower.des  \
++	 $(DAT)/yendor.des  $(DAT)/arch.des     $(DAT)/barb.des   \
++	 $(DAT)/caveman.des $(DAT)/healer.des   $(DAT)/knight.des \
++	 $(DAT)/monk.des    $(DAT)/priest.des   $(DAT)/ranger.des \
++	 $(DAT)/rogue.des   $(DAT)/samurai.des  $(DAT)/sokoban.des \
++	 $(DAT)/tourist.des $(DAT)/valkyrie.des $(DAT)/wizard.des
++	$(subst /,\,$(U)lev_comp $(DAT)/bigroom.des)
++	$(subst /,\,$(U)lev_comp $(DAT)/castle.des)
++	$(subst /,\,$(U)lev_comp $(DAT)/endgame.des)
++	$(subst /,\,$(U)lev_comp $(DAT)/gehennom.des)
++	$(subst /,\,$(U)lev_comp $(DAT)/knox.des)
++	$(subst /,\,$(U)lev_comp $(DAT)/mines.des)
++	$(subst /,\,$(U)lev_comp $(DAT)/medusa.des)
++	$(subst /,\,$(U)lev_comp $(DAT)/oracle.des)
++	$(subst /,\,$(U)lev_comp $(DAT)/sokoban.des)
++	$(subst /,\,$(U)lev_comp $(DAT)/tower.des)
++	$(subst /,\,$(U)lev_comp $(DAT)/yendor.des)
++	$(subst /,\,$(U)lev_comp $(DAT)/arch.des)
++	$(subst /,\,$(U)lev_comp $(DAT)/barb.des)
++	$(subst /,\,$(U)lev_comp $(DAT)/caveman.des)
++	$(subst /,\,$(U)lev_comp $(DAT)/healer.des)
++	$(subst /,\,$(U)lev_comp $(DAT)/knight.des)
++	$(subst /,\,$(U)lev_comp $(DAT)/monk.des)
++	$(subst /,\,$(U)lev_comp $(DAT)/priest.des)
++	$(subst /,\,$(U)lev_comp $(DAT)/ranger.des)
++	$(subst /,\,$(U)lev_comp $(DAT)/rogue.des)
++	$(subst /,\,$(U)lev_comp $(DAT)/samurai.des)
++	$(subst /,\,$(U)lev_comp $(DAT)/tourist.des)
++	$(subst /,\,$(U)lev_comp $(DAT)/valkyrie.des)
++	$(subst /,\,$(U)lev_comp $(DAT)/wizard.des)
++	$(subst /,\,copy *.lev $(DAT))
++	$(subst /,\,del *.lev)
++	$(subst /,\,echo sp_levs done > $(O)sp_lev.tag)
++
++$(O)utility.tag: $(INCL)/date.h $(INCL)/onames.h $(INCL)/pm.h \
++	 $(SRC)/monstr.c $(SRC)/vis_tab.c $(U)lev_comp.exe $(INCL)/vis_tab.h \
++	 $(U)dgn_comp.exe $(TILEUTIL16)
++	$(subst /,\,@echo utilities made >$@)
++	@echo utilities made.
++
++tileutil: $(U)gif2txt.exe $(U)gif2tx32.exe $(U)txt2ppm.exe
++	@echo Optional tile development utilities are up to date.
++
++ifeq  "$(GRAPHICAL)" "Y"
++$(NHRES): $(TILEBMP16) $(WIN32)/winhack.rc $(WIN32)/mnsel.bmp \
++	 $(WIN32)/mnselcnt.bmp $(WIN32)/mnunsel.bmp \
++	 $(WIN32)/petmark.bmp $(WIN32)/NetHack.ico $(WIN32)/rip.bmp \
++	 $(WIN32)/splash.bmp
++	@$(rc) -o$@ --include-dir $(WIN32) -i $(WIN32)/winhack.rc
++else
++$(NHRES): $(NTSYS)/console.rc $(NTSYS)/NetHack.ico 
++	@$(rc) -o$@ --include-dir $(NTSYS) -i $(NTSYS)/console.rc
++endif
++
++#==========================================
++#  The main target.
++#==========================================
++$(O)gamedir.tag:
++	$(subst /,\,@if not exist $(GAMEDIR)/*.* echo creating directory $(GAMEDIR))
++	$(subst /,\,@if not exist $(GAMEDIR)/*.* mkdir $(GAMEDIR))
++	$(subst /,\,@echo directory created > $@)
++
++ifeq  "$(GRAPHICAL)" "Y"
++$(GAMEFILE) : $(ALLOBJ) $(NHRES) $(O)gamedir.tag
++else
++#$(GAMEFILE) : $(ALLOBJ) $(NHRES) $(O)gamedir.tag \
++#	 $(GAMEDIR)/nhdefkey.dll $(GAMEDIR)/nh340key.dll $(GAMEDIR)/nhraykey.dll
++$(GAMEFILE) : $(ALLOBJ) $(NHRES) $(O)gamedir.tag
++endif
++	@echo Linking....
++	$(link) $(lflags) -o$@ $(ALLOBJ) $(NHRES) $(WINPLIBS)
++	$(subst /,\,@if exist $(O)install.tag del $(O)install.tag)
++
++
++$(O)nhdefkey.o:
++	$(cc) $(CFLAGS) -DBUILD_DLL -o$@ $(NTSYS)/nhdefkey.c 
++
++$(GAMEDIR)/nhdefkey.dll : $(O)nhdefkey.o $(O)gamedir.tag
++	@echo Linking $@
++	$(cc) -shared -Wl,--export-all-symbols \
++		-Wl,--add-stdcall-alias -o $@ $<
++
++$(O)nh340key.o:
++	$(cc) $(CFLAGS) -DBUILD_DLL -o$@ $(NTSYS)/nh340key.c 
++
++$(GAMEDIR)/nh340key.dll : $(O)nh340key.o $(O)gamedir.tag
++	@echo Linking $@
++	$(cc) -shared -Wl,--export-all-symbols \
++		-Wl,--add-stdcall-alias -o $@ $<
++
++$(O)nhraykey.o:
++		$(cc) $(CFLAGS) -DBUILD_DLL -o$@ $(NTSYS)/nhraykey.c 
++
++$(GAMEDIR)/nhraykey.dll : $(O)nhraykey.o $(O)gamedir.tag
++	@echo Linking $@
++	$(cc) -shared -Wl,--export-all-symbols \
++		-Wl,--add-stdcall-alias -o $@ $<
++
++$(GAME)_.ico : $(NTSYS)/$(GAME).ico
++	$(subst /,\,@copy $(NTSYS)/$(GAME).ico $@)
++
++#==========================================
++# Create directory for holding object files
++#==========================================
++
++graphicschk:
++ifeq  "$(GRAPHICAL)" "Y"
++	@echo ----
++	@echo NOTE: This build will include tile support.
++	@echo ----
++endif
++	$(subst /,\,@echo graphicschk > graphicschk)
++
++#
++#  Secondary Targets.
++#
++
++#==========================================
++# Makedefs Stuff
++#==========================================
++
++$(U)makedefs.exe: $(MAKEOBJS)
++	@$(link) $(LFLAGSU) -o$@ $(MAKEOBJS)
++
++$(O)makedefs.o: $(CONFIG_H) $(INCL)/monattk.h $(INCL)/monflag.h \
++	 $(INCL)/objclass.h $(INCL)/monsym.h $(INCL)/qtext.h \
++	 $(INCL)/patchlevel.h $(U)makedefs.c $(O)obj.tag
++	$(cc) $(CFLAGSU) -o$@ $(U)makedefs.c
++
++#
++#  date.h should be remade every time any of the source or include
++#  files is modified.
++#
++
++$(INCL)/date.h $(OPTIONS_FILE): $(U)makedefs.exe
++	$(subst /,\,$(U)makedefs -v)
++
++#$(OPTIONS_FILE): $(U)makedefs.exe
++#	$(subst /,\,$(U)makedefs -v)
++
++$(INCL)/onames.h : $(U)makedefs.exe
++	$(subst /,\,$(U)makedefs -o)
++
++$(INCL)/pm.h : $(U)makedefs.exe
++	$(subst /,\,$(U)makedefs -p)
++
++#$(INCL)/trap.h : $(U)makedefs.exe
++#  $(U)makedefs -t
++
++$(SRC)/monstr.c: $(U)makedefs.exe
++	$(subst /,\,$(U)makedefs -m)
++
++$(INCL)/vis_tab.h: $(U)makedefs.exe
++	$(subst /,\,$(U)makedefs -z)
++
++$(SRC)/vis_tab.c: $(U)makedefs.exe
++	$(subst /,\,$(U)makedefs -z)
++
++#==========================================
++# uudecode utility and uuencoded targets
++#==========================================
++
++$(U)uudecode.exe: $(O)uudecode.o
++	@$(link) $(LFLAGSU) -o$@ $(O)uudecode.o
++
++$(O)uudecode.o: $(SSYS)/uudecode.c
++
++$(NTSYS)/NetHack.ico : $(U)uudecode.exe $(NTSYS)/nhico.uu
++	$(subst /,\,$(U)uudecode.exe $(NTSYS)/nhico.uu)
++	$(subst /,\,copy NetHack.ico $@)
++	del NetHack.ico
++
++$(WIN32)/NetHack.ico : $(NTSYS)/NetHack.ico
++	$(subst /,\,copy $< $@)
++
++$(WIN32)/mnsel.bmp: $(U)uudecode.exe $(WIN32)/mnsel.uu
++	$(subst /,\,$(U)uudecode.exe $(WIN32)/mnsel.uu)
++	$(subst /,\,copy mnsel.bmp $@)
++	del mnsel.bmp
++
++$(WIN32)/mnselcnt.bmp: $(U)uudecode.exe $(WIN32)/mnselcnt.uu
++	$(subst /,\,$(U)uudecode.exe $(WIN32)/mnselcnt.uu)
++	$(subst /,\,copy mnselcnt.bmp $@)
++	del mnselcnt.bmp
++
++$(WIN32)/mnunsel.bmp: $(U)uudecode.exe $(WIN32)/mnunsel.uu
++	$(subst /,\,$(U)uudecode.exe $(WIN32)/mnunsel.uu)
++	$(subst /,\,copy mnunsel.bmp $@)
++	del mnunsel.bmp
++
++$(WIN32)/petmark.bmp: $(U)uudecode.exe $(WIN32)/petmark.uu
++	$(subst /,\,$(U)uudecode.exe $(WIN32)/petmark.uu)
++	$(subst /,\,copy petmark.bmp $@)
++	del petmark.bmp
++
++$(WIN32)/rip.bmp: $(U)uudecode.exe $(WIN32)/rip.uu
++	$(subst /,\,$(U)uudecode.exe $(WIN32)/rip.uu)
++	$(subst /,\,copy rip.bmp $@)
++	del rip.bmp
++
++$(WIN32)/splash.bmp: $(U)uudecode.exe $(WIN32)/splash.uu
++	$(subst /,\,$(U)uudecode.exe $(WIN32)/splash.uu)
++	$(subst /,\,copy splash.bmp $@)
++	del splash.bmp
++
++
++#==========================================
++# Level Compiler Stuff
++#==========================================
++
++LEVCFLAGS=$(cflags) -c -DWIN32 -D_WIN32 -I../include $(cdebug) -DDLB
++
++$(U)lev_comp.exe: $(SPLEVOBJS)
++	@echo Linking $@...
++	@$(link) $(LFLAGSU) -o$@ $(SPLEVOBJS)
++
++$(O)lev_yacc.o: $(HACK_H)   $(SP_LEV_H) $(INCL)/lev_comp.h $(U)lev_yacc.c
++	$(cc) $(LEVCFLAGS) -o$@ $(U)lev_yacc.c
++
++$(O)lev_$(LEX).o: $(HACK_H)   $(INCL)/lev_comp.h $(SP_LEV_H) \
++	$(U)lev_$(LEX).c
++	$(cc) $(LEVCFLAGS) -o$@ $(U)lev_$(LEX).c
++
++$(O)lev_main.o:   $(U)lev_main.c $(HACK_H)   $(SP_LEV_H)
++	$(cc) $(LEVCFLAGS) -o$@ $(U)lev_main.c
++
++
++$(U)lev_yacc.c $(INCL)/lev_comp.h : $(U)lev_comp.y
++ifeq  "$(DO_YACC)" "YACC_ACT"
++	$(subst /,\,$(YACC) -d $(U)lev_comp.y)
++	$(subst /,\,copy $(YTABC) $(U)lev_yacc.c)
++	$(subst /,\,copy $(YTABH) $(INCL)/lev_comp.h)
++	$(subst /,\,@del $(YTABC))
++	$(subst /,\,@del $(YTABH))
++
++else
++	@echo $(U)lev_comp.y has changed.
++	@echo To update $(U)lev_yacc.c and $(INCL)/lev_comp.h run $(YACC).
++	@echo ---
++	@echo For now, we will copy the prebuilt lev_yacc.c and
++	@echo lev_comp.h from $(SSYS) into $(UTIL) and use them.
++	$(subst /,\,@copy $(SSYS)/lev_yacc.c $(U)lev_yacc.c >nul)
++	$(subst /,\,@copy $(SSYS)/lev_comp.h $(INCL)/lev_comp.h >nul)
++	$(subst /,\,echo.>>$(U)lev_yacc.c)
++	$(subst /,\,echo.>>$(INCL)/lev_comp.h)
++endif
++
++$(U)lev_$(LEX).c: $(U)lev_comp.l
++ifeq  "$(DO_LEX)" "LEX_ACT"
++	$(subst /,\,$(LEX) $(FLEXSKEL) $(U)lev_comp.l)
++	$(subst /,\,copy $(LEXYYC) $@)
++	$(subst /,\,@del $(LEXYYC))
++else
++	@echo $(U)lev_comp.l has changed. To update $@ run $(LEX).
++	@echo ---
++	@echo For now, we will copy the prebuilt lev_lex.c
++	@echo from $(SSYS) into $(UTIL) and use it.
++	$(subst /,\,@copy $(SSYS)/lev_lex.c $@ >nul)
++	$(subst /,\,echo.>>$@)
++endif
++
++#==========================================
++# Dungeon Compiler Stuff
++#==========================================
++
++$(U)dgn_comp.exe: $(DGNCOMPOBJS)
++	@echo Linking $@...
++	@$(link) $(LFLAGSU) -o$@ $(DGNCOMPOBJS)
++
++
++$(O)dgn_yacc.o:   $(HACK_H)   $(DGN_FILE_H) $(INCL)/dgn_comp.h $(U)dgn_yacc.c
++	$(cc) $(LEVCFLAGS) -o$@ $(U)dgn_yacc.c
++
++$(O)dgn_$(LEX).o: $(HACK_H)   $(DGN_FILE_H)  $(INCL)/dgn_comp.h \
++	 $(U)dgn_$(LEX).c
++	$(cc) $(LEVCFLAGS) -o$@ $(U)dgn_$(LEX).c
++
++$(O)dgn_main.o:   $(HACK_H) $(U)dgn_main.c
++	$(cc) $(LEVCFLAGS) -o$@ $(U)dgn_main.c
++
++$(U)dgn_yacc.c $(INCL)/dgn_comp.h : $(U)dgn_comp.y
++ifeq  "$(DO_YACC)" "YACC_ACT"
++	$(subst /,\,$(YACC) -d $(U)dgn_comp.y)
++	$(subst /,\,copy $(YTABC) $(U)dgn_yacc.c)
++	$(subst /,\,copy $(YTABH) $(INCL)/dgn_comp.h)
++	$(subst /,\,@del $(YTABC))
++	$(subst /,\,@del $(YTABH))
++else
++	@echo $(U)dgn_comp.y has changed. To update dgn_yacc.c and
++	@echo $(INCL)/dgn_comp.h run $(YACC).
++	@echo ---
++	@echo For now, we will copy the prebuilt $(U)dgn_yacc.c and
++	@echo dgn_comp.h from $(SSYS) into $(UTIL) and use them.
++	$(subst /,\,@copy $(SSYS)/dgn_yacc.c $(U)dgn_yacc.c >nul)
++	$(subst /,\,@copy $(SSYS)/dgn_comp.h $(INCL)/dgn_comp.h >nul)
++	$(subst /,\,echo.>>$(U)dgn_yacc.c)
++	$(subst /,\,echo.>>$(INCL)/dgn_comp.h)
++endif
++
++$(U)dgn_$(LEX).c: $(U)dgn_comp.l
++ifeq  "$(DO_LEX)" "LEX_ACT"
++	$(subst /,\,$(LEX) $(FLEXSKEL) $(U)dgn_comp.l)
++	$(subst /,\,copy $(LEXYYC) $@)
++	$(subst /,\,@del $(LEXYYC))
++else
++	@echo $(U)dgn_comp.l has changed. To update $@ run $(LEX).
++	@echo ---
++	@echo For now, we will copy the prebuilt dgn_lex.c
++	@echo from $(SSYS) into $(UTIL) and use it.
++	$(subst /,\,@copy $(SSYS)/dgn_lex.c $@ >nul)
++	$(subst /,\,echo.>>$@)
++endif
++
++#==========================================
++# Create directory for holding object files
++#==========================================
++
++$(O)obj.tag:
++	$(subst /,\,@if not exist $(OBJ)/*.* echo creating directory $(OBJ))
++	$(subst /,\,@if not exist $(OBJ)/*.* mkdir $(OBJ))
++	$(subst /,\,@echo directory created > $@)
++
++
++#==========================================
++#=========== SECONDARY TARGETS ============
++#==========================================
++
++#===========================================
++# Header files NOT distributed in ../include
++#===========================================
++
++$(INCL)/win32api.h: $(NTSYS)/win32api.h
++	$(subst /,\,copy $(NTSYS)/win32api.h $@)
++
++
++#==========================================
++# DLB utility and nhdat file creation
++#==========================================
++
++$(U)dlb_main.exe: $(DLBOBJ) $(O)dlb.o
++	@$(link) $(LFLAGSU) -o$@ $(O)dlb_main.o $(O)dlb.o $(O)alloc.o $(O)panic.o
++
++
++$(O)dlb.o:   $(O)dlb_main.o $(O)alloc.o $(O)panic.o $(INCL)/dlb.h
++	$(cc) $(CFLAGS) -o$@ $(SRC)/dlb.c
++
++$(O)dlb_main.o: $(UTIL)/dlb_main.c $(INCL)/config.h $(INCL)/dlb.h
++	$(cc) $(CFLAGS) -o$@ $(UTIL)/dlb_main.c
++
++$(DAT)/porthelp: $(NTSYS)/porthelp
++	$(subst /,\,@copy $(NTSYS)/porthelp $@ >nul)
++
++nhdat:  $(U)dlb_main.exe $(DAT)/data $(DAT)/oracles $(OPTIONS_FILE) \
++	 $(DAT)/quest.dat $(DAT)/rumors $(DAT)/help $(DAT)/hh $(DAT)/cmdhelp \
++	 $(DAT)/history $(DAT)/opthelp $(DAT)/wizhelp $(DAT)/dungeon \
++	 $(DAT)/porthelp $(DAT)/license $(O)sp_lev.tag
++	$(subst /,\,echo data >$(DAT)/dlb.lst)
++	$(subst /,\,echo oracles >>$(DAT)/dlb.lst)
++	$(subst /,\,if exist $(DAT)/options echo options >>$(DAT)/dlb.lst)
++	$(subst /,\,if exist $(DAT)/ttyoptions echo ttyoptions >>$(DAT)/dlb.lst)
++	$(subst /,\,if exist $(DAT)/guioptions echo guioptions >>$(DAT)/dlb.lst)
++	$(subst /,\,if exist $(DAT)/porthelp echo porthelp >>$(DAT)/dlb.lst)
++	$(subst /,\,echo quest.dat >>$(DAT)/dlb.lst)
++	$(subst /,\,echo rumors >>$(DAT)/dlb.lst)
++	$(subst /,\,echo help >>$(DAT)/dlb.lst)
++	$(subst /,\,echo hh >>$(DAT)/dlb.lst)
++	$(subst /,\,echo cmdhelp >>$(DAT)/dlb.lst)
++	$(subst /,\,echo history >>$(DAT)/dlb.lst)
++	$(subst /,\,echo opthelp >>$(DAT)/dlb.lst)
++	$(subst /,\,echo wizhelp >>$(DAT)/dlb.lst)
++	$(subst /,\,echo dungeon >>$(DAT)/dlb.lst)
++	$(subst /,\,echo license >>$(DAT)/dlb.lst)
++	dir /l /b /-p $(subst /,\,$(DAT)/*.lev >>$(DAT)/dlb.lst)
++	$(subst /,\,$(U)dlb_main CcIf $(DAT) dlb.lst $(SRC)/nhdat)
++
++#==========================================
++#  Recover Utility
++#==========================================
++
++$(U)recover.exe: $(RECOVOBJS)
++	$(link) $(LFLAGSU) -o$@ $(RECOVOBJS)
++
++$(O)recover.o: $(CONFIG_H) $(U)recover.c $(INCL)/win32api.h
++	$(cc) $(CFLAGSU) -o$@ $(U)recover.c
++
++#==========================================
++#  Tile Mapping
++#==========================================
++
++$(SRC)/tile.c: $(U)tilemap.exe
++	@echo A new $@ has been created
++	@$(U)tilemap
++
++$(U)tilemap.exe: $(O)tilemap.o
++	@$(link) $(LFLAGSU) -o$@ $(O)tilemap.o
++
++$(O)tilemap.o: $(WSHR)/tilemap.c $(HACK_H)
++	$(cc) $(CFLAGSU) -o$@ $(WSHR)/tilemap.c
++
++$(O)tiletx32.o: $(WSHR)/tilemap.c $(HACK_H)
++	$(cc) $(CFLAGS) -DTILETEXT -DTILE_X=32 -DTILE_Y=32 -o$@ $(WSHR)/tilemap.c
++
++$(O)tiletxt.o: $(WSHR)/tilemap.c $(HACK_H)
++	$(cc) $(CFLAGS) -DTILETEXT -o$@ $(WSHR)/tilemap.c
++
++$(O)gifread.o: $(WSHR)/gifread.c  $(CONFIG_H) $(TILE_H)
++	$(cc) $(CFLAGS) -I$(WSHR) -o$@ $(WSHR)/gifread.c
++
++$(O)gifrd32.o: $(WSHR)/gifread.c  $(CONFIG_H) $(TILE_H)
++	$(cc) $(CFLAGS) -I$(WSHR) -DTILE_X=32 -DTILE_Y=32 -o$@ $(WSHR)/gifread.c
++
++$(O)ppmwrite.o: $(WSHR)/ppmwrite.c $(CONFIG_H) $(TILE_H)
++	$(cc) $(CFLAGS) -I$(WSHR) -o$@ $(WSHR)/ppmwrite.c
++
++$(O)tiletext.o: $(WSHR)/tiletext.c  $(CONFIG_H) $(TILE_H)
++	$(cc) $(CFLAGS) -I$(WSHR) -o$@ $(WSHR)/tiletext.c
++
++$(O)tilete32.o: $(WSHR)/tiletext.c  $(CONFIG_H) $(TILE_H)
++	$(cc) $(CFLAGS) -I$(WSHR) -DTILE_X=32 -DTILE_Y=32 -o$@ $(WSHR)/tiletext.c
++
++#==========================================
++# Optional Tile Utilities
++#==========================================
++
++$(U)gif2txt.exe: $(GIFREADERS) $(TEXT_IO)
++	@echo Linking $@...
++	@$(link) $(LFLAGSU) -o$@ $(GIFREADERS) $(TEXT_IO)
++
++$(U)gif2tx32.exe: $(GIFREADERS32) $(TEXT_IO32)
++	@echo Linking $@...
++	@$(link) $(LFLAGSU) -o$@ $(GIFREADERS32) $(TEXT_IO32)
++
++
++$(U)txt2ppm.exe: $(PPMWRITERS) $(TEXT_IO)
++	@echo Linking $@...
++	@$(link) $(LFLAGSU) -o$@ $(PPMWRITERS) $(TEXT_IO)
++
++
++ifeq  "$(GRAPHICAL)" "Y"
++$(TILEBMP16): $(TILEUTIL16) $(TILEFILES)
++	@echo Creating 16x16 binary tile files (this may take some time)
++	$(subst /,\,@$(U)tile2bmp $(TILEBMP16))
++#$(TILEBMP32): $(TILEUTIL32) $(TILEFILES32)
++#	@echo Creating 32x32 binary tile files (this may take some time)
++#	$(subst /,\,@$(U)til2bm32 $(TILEBMP32))
++else
++$(TILEBMP16):
++$(TILEBMP32):
++endif
++
++$(U)tile2bmp.exe: $(O)tile2bmp.o $(TEXT_IO)
++	@echo Linking $@...
++	@$(link) $(LFLAGSU) -o$@ $(O)tile2bmp.o $(TEXT_IO)
++
++$(U)til2bm32.exe: $(O)til2bm32.o $(TEXT_IO32)
++	@echo Linking $@...
++	@$(link) $(LFLAGSU) -o$@ $(O)til2bm32.o $(TEXT_IO32)
++
++$(O)tile2bmp.o: $(WSHR)/tile2bmp.c $(HACK_H) $(TILE_H) $(INCL)/win32api.h
++	$(cc) $(CFLAGS) -I$(WSHR) -o$@ $(WSHR)/tile2bmp.c
++
++$(O)til2bm32.o: $(WSHR)/til2bm32.c $(HACK_H) $(TILE_H) $(INCL)/win32api.h
++	$(cc) $(CFLAGS) -I$(WSHR) -DTILE_X=32 -DTILE_Y=32 -o$@ $(WSHR)/til2bm32.c
++
++#==========================================
++# Housekeeping
++#==========================================
++
++spotless: clean
++	$(subst /,\,if exist graphicschk       del graphicschk)
++	$(subst /,\,if exist $(INCL)/date.h    del $(INCL)/date.h)
++	$(subst /,\,if exist $(INCL)/onames.h  del $(INCL)/onames.h)
++	$(subst /,\,if exist $(INCL)/pm.h      del $(INCL)/pm.h)
++	$(subst /,\,if exist $(INCL)/vis_tab.h del $(INCL)/vis_tab.h)
++	$(subst /,\,if exist $(SRC)/vis_tab.c  del $(SRC)/vis_tab.c)
++	$(subst /,\,if exist $(SRC)/tile.c     del $(SRC)/tile.c)
++	$(subst /,\,if exist $(U)*.lnk         del $(U)*.lnk)
++	$(subst /,\,if exist $(U)*.map         del $(U)*.map)
++	$(subst /,\,if exist $(DAT)/data       del $(DAT)/data)
++	$(subst /,\,if exist $(DAT)/rumors     del $(DAT)/rumors)
++	$(subst /,\,if exist $(DAT)/???-fil?.lev      del $(DAT)/???-fil?.lev)
++	$(subst /,\,if exist $(DAT)/???-goal.lev      del $(DAT)/???-goal.lev)
++	$(subst /,\,if exist $(DAT)/???-loca.lev      del $(DAT)/???-loca.lev)
++	$(subst /,\,if exist $(DAT)/???-strt.lev      del $(DAT)/???-strt.lev)
++	$(subst /,\,if exist $(DAT)/air.lev      del $(DAT)/air.lev)
++	$(subst /,\,if exist $(DAT)/asmodeus.lev      del $(DAT)/asmodeus.lev)
++	$(subst /,\,if exist $(DAT)/astral.lev   del $(DAT)/astral.lev)
++	$(subst /,\,if exist $(DAT)/baalz.lev    del $(DAT)/baalz.lev)
++	$(subst /,\,if exist $(DAT)/bigrm-*.lev  del $(DAT)/bigrm-*.lev)
++	$(subst /,\,if exist $(DAT)/castle.lev   del $(DAT)/castle.lev)
++	$(subst /,\,if exist $(DAT)/data    del $(DAT)/data)
++	$(subst /,\,if exist $(DAT)/dungeon      del $(DAT)/dungeon)
++	$(subst /,\,if exist $(DAT)/dungeon.pdf  del $(DAT)/dungeon.pdf)
++	$(subst /,\,if exist $(DAT)/earth.lev    del $(DAT)/earth.lev)
++	$(subst /,\,if exist $(DAT)/fakewiz?.lev      del $(DAT)/fakewiz?.lev)
++	$(subst /,\,if exist $(DAT)/fire.lev     del $(DAT)/fire.lev)
++	$(subst /,\,if exist $(DAT)/juiblex.lev  del $(DAT)/juiblex.lev)
++	$(subst /,\,if exist $(DAT)/knox.lev     del $(DAT)/knox.lev)
++	$(subst /,\,if exist $(DAT)/medusa-?.lev      del $(DAT)/medusa-?.lev)
++	$(subst /,\,if exist $(DAT)/mine*.lev    del $(DAT)/mine*.lev)
++	$(subst /,\,if exist $(DAT)/options      del $(DAT)/options)
++	$(subst /,\,if exist $(DAT)/ttyoptions   del $(DAT)/ttyoptions)
++	$(subst /,\,if exist $(DAT)/guioptions   del $(DAT)/guioptions)
++	$(subst /,\,if exist $(DAT)/oracle.lev   del $(DAT)/oracle.lev)
++	$(subst /,\,if exist $(DAT)/oracles      del $(DAT)/oracles)
++	$(subst /,\,if exist $(DAT)/orcus.lev    del $(DAT)/orcus.lev)
++	$(subst /,\,if exist $(DAT)/rumors  del $(DAT)/rumors)
++	$(subst /,\,if exist $(DAT)/quest.dat    del $(DAT)/quest.dat)
++	$(subst /,\,if exist $(DAT)/sanctum.lev  del $(DAT)/sanctum.lev)
++	$(subst /,\,if exist $(DAT)/soko?-?.lev  del $(DAT)/soko?-?.lev)
++	$(subst /,\,if exist $(DAT)/tower?.lev   del $(DAT)/tower?.lev)
++	$(subst /,\,if exist $(DAT)/valley.lev   del $(DAT)/valley.lev)
++	$(subst /,\,if exist $(DAT)/water.lev    del $(DAT)/water.lev)
++	$(subst /,\,if exist $(DAT)/wizard?.lev  del $(DAT)/wizard?.lev)
++	$(subst /,\,if exist $(O)sp_lev.tag     del $(O)sp_lev.tag)
++	$(subst /,\,if exist $(SRC)/monstr.c    del $(SRC)/monstr.c)
++	$(subst /,\,if exist $(SRC)/vis_tab.c   del $(SRC)/vis_tab.c)
++	$(subst /,\,if exist $(U)recover.exe    del $(U)recover.exe)
++	$(subst /,\,if exist $(DAT)/dlb.lst      del $(DAT)/dlb.lst)
++	$(subst /,\,if exist nhdat.         del nhdat.)
++	$(subst /,\,if exist $(O)install.tag    del $(O)install.tag)
++	$(subst /,\,if exist $(O)obj.tag    del $(O)obj.tag)
++	$(subst /,\,if exist $(O)gamedir.tag    del $(O)gamedir.tag)
++ifneq "$(OBJ)" ""
++	$(subst /,\,rmdir $(OBJ)) /s /Q
++endif
++
++clean:
++	$(subst /,\,if exist $(O)*.o del $(O)*.o)
++	$(subst /,\,if exist $(O)utility.tag   del $(O)utility.tag)
++	$(subst /,\,if exist $(U)makedefs.exe  del $(U)makedefs.exe)
++	$(subst /,\,if exist $(U)lev_comp.exe  del $(U)lev_comp.exe)
++	$(subst /,\,if exist $(U)dgn_comp.exe  del $(U)dgn_comp.exe)
++	$(subst /,\,if exist $(SRC)/*.lnk      del $(SRC)/*.lnk)
++	$(subst /,\,if exist $(SRC)/*.map      del $(SRC)/*.map)
++	$(subst /,\,if exist $(TILEBMP16)      del $(TILEBMP16))
++	$(subst /,\,if exist $(TILEBMP32)      del $(TILEBMP32))
++
++#===================================================================
++# OTHER DEPENDENCIES
++#===================================================================
++
++#
++# dat dependencies
++#
++
++$(DAT)/data: $(O)utility.tag    $(DATABASE)
++	$(subst /,\,$(U)makedefs -d)
++
++$(DAT)/rumors: $(O)utility.tag    $(DAT)/rumors.tru   $(DAT)/rumors.fal
++	$(subst /,\,$(U)makedefs -r)
++
++$(DAT)/quest.dat: $(O)utility.tag  $(DAT)/quest.txt
++	$(subst /,\,$(U)makedefs -q)
++
++$(DAT)/oracles: $(O)utility.tag    $(DAT)/oracles.txt
++	$(subst /,\,$(U)makedefs -h)
++
++$(DAT)/dungeon: $(O)utility.tag  $(DAT)/dungeon.def
++	$(subst /,\,$(U)makedefs -e)
++	$(subst /,\,$(U)dgn_comp $(DAT)/dungeon.pdf)
++
++#
++# NT dependencies
++#
++
++$(O)nttty.o:   $(HACK_H) $(TILE_H) $(INCL)/win32api.h $(NTSYS)/nttty.c
++	$(cc) $(CFLAGS) -I$(WSHR) -o$@  $(NTSYS)/nttty.c
++$(O)winnt.o: $(HACK_H) $(INCL)/win32api.h $(NTSYS)/winnt.c
++	$(cc) $(CFLAGS) -o$@  $(NTSYS)/winnt.c
++$(O)ntsound.o: $(HACK_H) $(NTSYS)/ntsound.c
++	$(cc) $(CFLAGS)  -o$@ $(NTSYS)/ntsound.c
++$(O)mapimail.o: $(HACK_H) $(INCL)/nhlan.h $(NTSYS)/mapimail.c
++	$(cc) $(CFLAGS) -DMAPI_VERBOSE  -o$@ $(NTSYS)/mapimail.c
++
++#
++# util dependencies
++#
++
++$(O)panic.o:  $(U)panic.c $(CONFIG_H)
++	$(cc) $(CFLAGS) -o$@ $(U)panic.c
++
++#
++# The rest are stolen from sys/unix/Makefile.src,
++# with the following changes:
++#   * ../include changed to $(INCL)
++#   * -c (which is included in CFLAGS) substituted
++#	with -o$@
++#   * targets prefixed with $(O)
++#   * $(CC) changed to $(cc)
++# but otherwise untouched. 
++# That means that there is some irrelevant stuff
++# in here, but maintenance should be easier.
++#
++$(O)tos.o: ../sys/atari/tos.c $(HACK_H) $(INCL)/tcap.h
++	$(cc) $(CFLAGS) -o$@ ../sys/atari/tos.c
++$(O)pcmain.o: ../sys/share/pcmain.c $(HACK_H) $(INCL)/dlb.h \
++		$(INCL)/win32api.h
++	$(cc) $(CFLAGS) -o$@ ../sys/share/pcmain.c
++$(O)pcsys.o: ../sys/share/pcsys.c $(HACK_H)
++	$(cc) $(CFLAGS) -o$@ ../sys/share/pcsys.c
++$(O)pctty.o: ../sys/share/pctty.c $(HACK_H)
++	$(cc) $(CFLAGS) -o$@ ../sys/share/pctty.c
++$(O)pcunix.o: ../sys/share/pcunix.c $(HACK_H)
++	$(cc) $(CFLAGS) -o$@ ../sys/share/pcunix.c
++$(O)random.o: ../sys/share/random.c $(HACK_H)
++	$(cc) $(CFLAGS) -o$@ ../sys/share/random.c
++$(O)ioctl.o: ../sys/share/ioctl.c $(HACK_H) $(INCL)/tcap.h
++	$(cc) $(CFLAGS) -o$@ ../sys/share/ioctl.c
++$(O)unixtty.o: ../sys/share/unixtty.c $(HACK_H)
++	$(cc) $(CFLAGS) -o$@ ../sys/share/unixtty.c
++$(O)unixmain.o: ../sys/unix/unixmain.c $(HACK_H) $(INCL)/dlb.h
++	$(cc) $(CFLAGS) -o$@ ../sys/unix/unixmain.c
++$(O)unixunix.o: ../sys/unix/unixunix.c $(HACK_H)
++	$(cc) $(CFLAGS) -o$@ ../sys/unix/unixunix.c
++$(O)unixres.o: ../sys/unix/unixres.c $(CONFIG_H)
++	$(cc) $(CFLAGS) -o$@ ../sys/unix/unixres.c
++$(O)bemain.o: ../sys/be/bemain.c $(HACK_H) $(INCL)/dlb.h
++	$(cc) $(CFLAGS) -o$@ ../sys/be/bemain.c
++$(O)getline.o: ../win/tty/getline.c $(HACK_H) $(INCL)/func_tab.h
++	$(cc) $(CFLAGS) -o$@ ../win/tty/getline.c
++$(O)termcap.o: ../win/tty/termcap.c $(HACK_H) $(INCL)/tcap.h
++	$(cc) $(CFLAGS) -o$@ ../win/tty/termcap.c
++$(O)topl.o: ../win/tty/topl.c $(HACK_H) $(INCL)/tcap.h
++	$(cc) $(CFLAGS) -o$@ ../win/tty/topl.c
++$(O)wintty.o: ../win/tty/wintty.c $(HACK_H) $(INCL)/dlb.h \
++		$(INCL)/patchlevel.h $(INCL)/tcap.h
++	$(cc) $(CFLAGS) -o$@ ../win/tty/wintty.c
++$(O)Window.o: ../win/X11/Window.c $(INCL)/xwindowp.h $(INCL)/xwindow.h \
++		$(CONFIG_H)
++	$(cc) $(CFLAGS) -o$@ ../win/X11/Window.c
++$(O)dialogs.o: ../win/X11/dialogs.c $(CONFIG_H)
++	$(cc) $(CFLAGS) -o$@ ../win/X11/dialogs.c
++$(O)winX.o: ../win/X11/winX.c $(HACK_H) $(INCL)/winX.h $(INCL)/dlb.h \
++		$(INCL)/patchlevel.h ../win/X11/nh72icon \
++		../win/X11/nh56icon ../win/X11/nh32icon
++	$(cc) $(CFLAGS) -o$@ ../win/X11/winX.c
++$(O)winmap.o: ../win/X11/winmap.c $(INCL)/xwindow.h $(HACK_H) $(INCL)/dlb.h \
++		$(INCL)/winX.h $(INCL)/tile2x11.h
++	$(cc) $(CFLAGS) -o$@ ../win/X11/winmap.c
++$(O)winmenu.o: ../win/X11/winmenu.c $(HACK_H) $(INCL)/winX.h
++	$(cc) $(CFLAGS) -o$@ ../win/X11/winmenu.c
++$(O)winmesg.o: ../win/X11/winmesg.c $(INCL)/xwindow.h $(HACK_H) $(INCL)/winX.h
++	$(cc) $(CFLAGS) -o$@ ../win/X11/winmesg.c
++$(O)winmisc.o: ../win/X11/winmisc.c $(HACK_H) $(INCL)/func_tab.h \
++		$(INCL)/winX.h
++	$(cc) $(CFLAGS) -o$@ ../win/X11/winmisc.c
++$(O)winstat.o: ../win/X11/winstat.c $(HACK_H) $(INCL)/winX.h
++	$(cc) $(CFLAGS) -o$@ ../win/X11/winstat.c
++$(O)wintext.o: ../win/X11/wintext.c $(HACK_H) $(INCL)/winX.h $(INCL)/xwindow.h
++	$(cc) $(CFLAGS) -o$@ ../win/X11/wintext.c
++$(O)winval.o: ../win/X11/winval.c $(HACK_H) $(INCL)/winX.h
++	$(cc) $(CFLAGS) -o$@ ../win/X11/winval.c
++$(O)tile.o: tile.c $(HACK_H)
++$(O)gnaskstr.o: ../win/gnome/gnaskstr.c ../win/gnome/gnaskstr.h \
++		../win/gnome/gnmain.h
++	$(cc) $(CFLAGS) $(GNOMEINC) -o$@ ../win/gnome/gnaskstr.c
++$(O)gnbind.o: ../win/gnome/gnbind.c ../win/gnome/gnbind.h ../win/gnome/gnmain.h \
++		../win/gnome/gnaskstr.h ../win/gnome/gnyesno.h
++	$(cc) $(CFLAGS) $(GNOMEINC) -o$@ ../win/gnome/gnbind.c
++$(O)gnglyph.o: ../win/gnome/gnglyph.c ../win/gnome/gnglyph.h $(INCL)/tile2x11.h
++	$(cc) $(CFLAGS) $(GNOMEINC) -o$@ ../win/gnome/gnglyph.c
++$(O)gnmain.o: ../win/gnome/gnmain.c ../win/gnome/gnmain.h ../win/gnome/gnsignal.h \
++		../win/gnome/gnbind.h ../win/gnome/gnopts.h $(HACK_H) \
++		$(INCL)/date.h
++	$(cc) $(CFLAGS) $(GNOMEINC) -o$@ ../win/gnome/gnmain.c
++$(O)gnmap.o: ../win/gnome/gnmap.c ../win/gnome/gnmap.h ../win/gnome/gnglyph.h \
++		../win/gnome/gnsignal.h $(HACK_H)
++	$(cc) $(CFLAGS) $(GNOMEINC) -o$@ ../win/gnome/gnmap.c
++$(O)gnmenu.o: ../win/gnome/gnmenu.c ../win/gnome/gnmenu.h ../win/gnome/gnmain.h \
++		../win/gnome/gnbind.h
++	$(cc) $(CFLAGS) $(GNOMEINC) -o$@ ../win/gnome/gnmenu.c
++$(O)gnmesg.o: ../win/gnome/gnmesg.c ../win/gnome/gnmesg.h ../win/gnome/gnsignal.h
++	$(cc) $(CFLAGS) $(GNOMEINC) -o$@ ../win/gnome/gnmesg.c
++$(O)gnopts.o: ../win/gnome/gnopts.c ../win/gnome/gnopts.h ../win/gnome/gnglyph.h \
++		../win/gnome/gnmain.h ../win/gnome/gnmap.h $(HACK_H)
++	$(cc) $(CFLAGS) $(GNOMEINC) -o$@ ../win/gnome/gnopts.c
++$(O)gnplayer.o: ../win/gnome/gnplayer.c ../win/gnome/gnplayer.h \
++		../win/gnome/gnmain.h $(HACK_H)
++	$(cc) $(CFLAGS) $(GNOMEINC) -o$@ ../win/gnome/gnplayer.c
++$(O)gnsignal.o: ../win/gnome/gnsignal.c ../win/gnome/gnsignal.h \
++		../win/gnome/gnmain.h
++	$(cc) $(CFLAGS) $(GNOMEINC) -o$@ ../win/gnome/gnsignal.c
++$(O)gnstatus.o: ../win/gnome/gnstatus.c ../win/gnome/gnstatus.h \
++		../win/gnome/gnsignal.h ../win/gnome/gn_xpms.h \
++		../win/gnome/gnomeprv.h
++	$(cc) $(CFLAGS) $(GNOMEINC) -o$@ ../win/gnome/gnstatus.c
++$(O)gntext.o: ../win/gnome/gntext.c ../win/gnome/gntext.h ../win/gnome/gnmain.h \
++		../win/gnome/gn_rip.h
++	$(cc) $(CFLAGS) $(GNOMEINC) -o$@ ../win/gnome/gntext.c
++$(O)gnworn.o: ../win/gnome/gnworn.c ../win/gnome/gnworn.h ../win/gnome/gnglyph.h \
++		../win/gnome/gnsignal.h ../win/gnome/gnomeprv.h
++	$(cc) $(CFLAGS) $(GNOMEINC) -o$@ ../win/gnome/gnworn.c
++$(O)gnyesno.o: ../win/gnome/gnyesno.c ../win/gnome/gnbind.h ../win/gnome/gnyesno.h
++	$(cc) $(CFLAGS) $(GNOMEINC) -o$@ ../win/gnome/gnyesno.c
++$(O)wingem.o: ../win/gem/wingem.c $(HACK_H) $(INCL)/func_tab.h $(INCL)/dlb.h \
++		$(INCL)/patchlevel.h $(INCL)/wingem.h
++	$(cc) $(CFLAGS) -o$@ ../win/gem/wingem.c
++$(O)wingem1.o: ../win/gem/wingem1.c $(INCL)/gem_rsc.h $(INCL)/load_img.h \
++		$(INCL)/gr_rect.h $(INCL)/wintype.h $(INCL)/wingem.h
++	$(cc) $(CFLAGS) -o$@ ../win/gem/wingem1.c
++$(O)load_img.o: ../win/gem/load_img.c $(INCL)/load_img.h
++	$(cc) $(CFLAGS) -o$@ ../win/gem/load_img.c
++$(O)gr_rect.o: ../win/gem/gr_rect.c $(INCL)/gr_rect.h
++	$(cc) $(CFLAGS) -o$@ ../win/gem/gr_rect.c
++$(O)tile.o: tile.c $(HACK_H)
++$(O)qt_win.o: ../win/Qt/qt_win.cpp $(HACK_H) $(INCL)/func_tab.h \
++		$(INCL)/dlb.h $(INCL)/patchlevel.h $(INCL)/tile2x11.h \
++		$(INCL)/qt_win.h $(INCL)/qt_clust.h $(INCL)/qt_kde0.h \
++		$(INCL)/qt_xpms.h qt_win.moc qt_kde0.moc qttableview.moc
++	$(CXX) $(CXXFLAGS) -o$@ ../win/Qt/qt_win.cpp
++$(O)qt_clust.o: ../win/Qt/qt_clust.cpp $(INCL)/qt_clust.h
++	$(CXX) $(CXXFLAGS) -o$@ ../win/Qt/qt_clust.cpp
++$(O)qttableview.o: ../win/Qt/qttableview.cpp $(INCL)/qttableview.h
++	$(CXX) $(CXXFLAGS) -o$@ ../win/Qt/qttableview.cpp
++$(O)monstr.o: monstr.c $(CONFIG_H)
++$(O)vis_tab.o: vis_tab.c $(CONFIG_H) $(INCL)/vis_tab.h
++$(O)allmain.o: allmain.c $(HACK_H)
++$(O)alloc.o: alloc.c $(CONFIG_H)
++$(O)apply.o: apply.c $(HACK_H) $(INCL)/edog.h
++$(O)artifact.o: artifact.c $(HACK_H) $(INCL)/artifact.h $(INCL)/artilist.h
++$(O)attrib.o: attrib.c $(HACK_H)
++$(O)ball.o: ball.c $(HACK_H)
++$(O)bones.o: bones.c $(HACK_H) $(INCL)/lev.h
++$(O)botl.o: botl.c $(HACK_H)
++$(O)cmd.o: cmd.c $(HACK_H) $(INCL)/func_tab.h
++$(O)dbridge.o: dbridge.c $(HACK_H)
++$(O)decl.o: decl.c $(HACK_H)
++$(O)detect.o: detect.c $(HACK_H) $(INCL)/artifact.h
++$(O)dig.o: dig.c $(HACK_H) $(INCL)/edog.h
++$(O)display.o: display.c $(HACK_H)
++$(O)dlb.o: dlb.c $(CONFIG_H) $(INCL)/dlb.h
++$(O)do.o: do.c $(HACK_H) $(INCL)/lev.h
++$(O)do_name.o: do_name.c $(HACK_H)
++$(O)do_wear.o: do_wear.c $(HACK_H)
++$(O)dog.o: dog.c $(HACK_H) $(INCL)/edog.h
++$(O)dogmove.o: dogmove.c $(HACK_H) $(INCL)/mfndpos.h $(INCL)/edog.h
++$(O)dokick.o: dokick.c $(HACK_H) $(INCL)/eshk.h
++$(O)dothrow.o: dothrow.c $(HACK_H) $(INCL)/edog.h
++$(O)drawing.o: drawing.c $(HACK_H) $(INCL)/tcap.h
++$(O)dungeon.o: dungeon.c $(HACK_H) $(INCL)/dgn_file.h $(INCL)/dlb.h
++$(O)eat.o: eat.c $(HACK_H)
++$(O)end.o: end.c $(HACK_H) $(INCL)/eshk.h $(INCL)/dlb.h
++$(O)engrave.o: engrave.c $(HACK_H) $(INCL)/lev.h
++$(O)exper.o: exper.c $(HACK_H)
++$(O)explode.o: explode.c $(HACK_H)
++$(O)extralev.o: extralev.c $(HACK_H)
++$(O)files.o: files.c $(HACK_H) $(INCL)/dlb.h
++$(O)fountain.o: fountain.c $(HACK_H)
++$(O)hack.o: hack.c $(HACK_H)
++$(O)hacklib.o: hacklib.c $(HACK_H)
++$(O)invent.o: invent.c $(HACK_H)
++$(O)light.o: light.c $(HACK_H) $(INCL)/lev.h
++$(O)lock.o: lock.c $(HACK_H)
++$(O)mail.o: mail.c $(HACK_H) $(INCL)/mail.h
++$(O)makemon.o: makemon.c $(HACK_H) $(INCL)/epri.h $(INCL)/emin.h \
++		$(INCL)/edog.h
++$(O)mapglyph.o: mapglyph.c $(HACK_H)
++$(O)mcastu.o: mcastu.c $(HACK_H)
++$(O)mhitm.o: mhitm.c $(HACK_H) $(INCL)/artifact.h $(INCL)/edog.h
++$(O)mhitu.o: mhitu.c $(HACK_H) $(INCL)/artifact.h $(INCL)/edog.h
++$(O)minion.o: minion.c $(HACK_H) $(INCL)/emin.h $(INCL)/epri.h
++$(O)mklev.o: mklev.c $(HACK_H)
++$(O)mkmap.o: mkmap.c $(HACK_H) $(INCL)/sp_lev.h
++$(O)mkmaze.o: mkmaze.c $(HACK_H) $(INCL)/sp_lev.h $(INCL)/lev.h
++$(O)mkobj.o: mkobj.c $(HACK_H)
++$(O)mkroom.o: mkroom.c $(HACK_H)
++$(O)mon.o: mon.c $(HACK_H) $(INCL)/mfndpos.h $(INCL)/edog.h
++$(O)mondata.o: mondata.c $(HACK_H) $(INCL)/eshk.h $(INCL)/epri.h
++$(O)monmove.o: monmove.c $(HACK_H) $(INCL)/mfndpos.h $(INCL)/artifact.h \
++		$(INCL)/epri.h
++$(O)monst.o: monst.c $(CONFIG_H) $(INCL)/permonst.h $(INCL)/align.h \
++		$(INCL)/monattk.h $(INCL)/monflag.h $(INCL)/monsym.h \
++		$(INCL)/dungeon.h $(INCL)/eshk.h $(INCL)/vault.h \
++		$(INCL)/epri.h $(INCL)/color.h
++$(O)mplayer.o: mplayer.c $(HACK_H)
++$(O)mthrowu.o: mthrowu.c $(HACK_H)
++$(O)muse.o: muse.c $(HACK_H) $(INCL)/edog.h
++$(O)music.o: music.c $(HACK_H) #interp.c
++$(O)o_init.o: o_init.c $(HACK_H) $(INCL)/lev.h
++$(O)objects.o: objects.c $(CONFIG_H) $(INCL)/obj.h $(INCL)/objclass.h \
++		$(INCL)/prop.h $(INCL)/skills.h $(INCL)/color.h
++$(O)objnam.o: objnam.c $(HACK_H)
++$(O)options.o: options.c $(CONFIG_H) $(INCL)/objclass.h $(INCL)/flag.h \
++		$(HACK_H) $(INCL)/tcap.h
++$(O)pager.o: pager.c $(HACK_H) $(INCL)/dlb.h
++$(O)pickup.o: pickup.c $(HACK_H)
++$(O)pline.o: pline.c $(HACK_H) $(INCL)/epri.h $(INCL)/edog.h
++$(O)polyself.o: polyself.c $(HACK_H)
++$(O)potion.o: potion.c $(HACK_H)
++$(O)pray.o: pray.c $(HACK_H) $(INCL)/epri.h
++$(O)priest.o: priest.c $(HACK_H) $(INCL)/mfndpos.h $(INCL)/eshk.h \
++		$(INCL)/epri.h $(INCL)/emin.h
++$(O)quest.o: quest.c $(HACK_H) $(INCL)/qtext.h
++$(O)questpgr.o: questpgr.c $(HACK_H) $(INCL)/dlb.h $(INCL)/qtext.h
++$(O)read.o: read.c $(HACK_H)
++$(O)rect.o: rect.c $(HACK_H)
++$(O)region.o: region.c $(HACK_H) $(INCL)/lev.h
++$(O)restore.o: restore.c $(HACK_H) $(INCL)/lev.h $(INCL)/tcap.h
++$(O)rip.o: rip.c $(HACK_H)
++$(O)rnd.o: rnd.c $(HACK_H)
++$(O)role.o: role.c $(HACK_H)
++$(O)rumors.o: rumors.c $(HACK_H) $(INCL)/lev.h $(INCL)/dlb.h
++$(O)save.o: save.c $(HACK_H) $(INCL)/lev.h
++$(O)shk.o: shk.c $(HACK_H) $(INCL)/eshk.h
++$(O)shknam.o: shknam.c $(HACK_H) $(INCL)/eshk.h
++$(O)sit.o: sit.c $(HACK_H) $(INCL)/artifact.h
++$(O)sounds.o: sounds.c $(HACK_H) $(INCL)/edog.h
++$(O)sp_lev.o: sp_lev.c $(HACK_H) $(INCL)/dlb.h $(INCL)/sp_lev.h
++$(O)spell.o: spell.c $(HACK_H)
++$(O)steal.o: steal.c $(HACK_H)
++$(O)steed.o: steed.c $(HACK_H)
++$(O)teleport.o: teleport.c $(HACK_H)
++$(O)timeout.o: timeout.c $(HACK_H) $(INCL)/lev.h
++$(O)topten.o: topten.c $(HACK_H) $(INCL)/dlb.h $(INCL)/patchlevel.h
++$(O)track.o: track.c $(HACK_H)
++$(O)trap.o: trap.c $(HACK_H)
++$(O)u_init.o: u_init.c $(HACK_H)
++$(O)uhitm.o: uhitm.c $(HACK_H)
++$(O)vault.o: vault.c $(HACK_H) $(INCL)/vault.h
++$(O)version.o: version.c $(HACK_H) $(INCL)/date.h $(INCL)/patchlevel.h
++$(O)vision.o: vision.c $(HACK_H) $(INCL)/vis_tab.h
++$(O)weapon.o: weapon.c $(HACK_H)
++$(O)were.o: were.c $(HACK_H)
++$(O)wield.o: wield.c $(HACK_H)
++$(O)windows.o: windows.c $(HACK_H) $(INCL)/wingem.h $(INCL)/winGnome.h
++$(O)wizard.o: wizard.c $(HACK_H) $(INCL)/qtext.h $(INCL)/epri.h
++$(O)worm.o: worm.c $(HACK_H) $(INCL)/lev.h
++$(O)worn.o: worn.c $(HACK_H)
++$(O)write.o: write.c $(HACK_H)
++$(O)zap.o: zap.c $(HACK_H)
++
++# end of file
+diff -burN nethack-3.4.3/util/makedefs.c nethack/util/makedefs.c
+--- nethack-3.4.3/util/makedefs.c	2003-12-07 18:39:13.000000000 -0500
++++ nethack/util/makedefs.c	2009-03-11 13:35:46.000000000 -0400
+@@ -782,6 +782,9 @@
+ #ifdef TTY_GRAPHICS
+ 		"traditional tty-based graphics",
+ #endif
++#ifdef CURSES_GRAPHICS
++        "curses",
++#endif
+ #ifdef X11_GRAPHICS
+ 		"X11",
+ #endif
+diff -burN nethack-3.4.3/win/curses/Bugs.txt nethack/win/curses/Bugs.txt
+--- nethack-3.4.3/win/curses/Bugs.txt	1969-12-31 19:00:00.000000000 -0500
++++ nethack/win/curses/Bugs.txt	2009-03-05 13:50:38.000000000 -0500
+@@ -0,0 +1,13 @@
++Here is a list of known issues with the curses interface at the time of
++this writing.  Send any others you discover to me (Karl Garrison) at
++kgarrison@obox.com, along with how to reproduce the problem, if
++possible.  Missing features are listed in the file Todo.txt.
++
++ * Resizing a window to 80 columns or less causes a crash (PDCurses for
++ SDL and X11 only).  Windows starting at this size and below do not
++ cause a crash, however.
++ 
++ * Cursor position is wrong on map for smaller terminal windows in all
++ versions of PDCurses (smaller than 80 width or 24 height).  This is
++ due to an incomplete workaround for an issue with the wmove() function
++ in PDCurses.
+diff -burN nethack-3.4.3/win/curses/cursdial.c nethack/win/curses/cursdial.c
+--- nethack-3.4.3/win/curses/cursdial.c	1969-12-31 19:00:00.000000000 -0500
++++ nethack/win/curses/cursdial.c	2009-03-11 15:08:53.000000000 -0400
+@@ -0,0 +1,1182 @@
++#include "curses.h"
++#include "hack.h"
++#include "wincurs.h"
++#include "cursdial.h"
++#include "func_tab.h"
++
++
++/* Dialog windows for curses interface */
++
++static nhmenu *nhmenus = NULL;  /* NetHack menu array */
++
++
++/* Get a line of text from the player, such as asking for a character name or a wish */
++
++void curses_line_input_dialog(const char *prompt, char *answer, int buffer)
++{
++    int map_height, map_width, maxwidth, remaining_buf, winx, winy, count;
++    WINDOW *askwin, *bwin;
++    char input[buffer];
++    char *tmpstr;
++    int prompt_width = strlen(prompt) + buffer + 1;
++    int prompt_height = 1;
++    int height = prompt_height;
++
++    maxwidth = term_cols - 2;
++
++    if (iflags.window_inited)
++    {
++        curses_get_window_size(MAP_WIN, &map_height, &map_width);
++        if ((prompt_width + 2) > map_width)
++            maxwidth = map_width - 2;
++    }
++    
++    if (prompt_width > maxwidth)
++    {
++        prompt_height = curses_num_lines(prompt, maxwidth);
++        height = prompt_height;
++        prompt_width = maxwidth;
++        tmpstr = curses_break_str(prompt, maxwidth, prompt_height);
++        remaining_buf = buffer - (strlen(tmpstr) - 1);
++        if (remaining_buf > 0 )
++        {
++            height += (remaining_buf / prompt_width);
++            if ((remaining_buf % prompt_width) > 0)
++            {
++                height++;
++            }
++        }
++    }
++    
++    if (iflags.window_inited)
++    {
++        bwin = curses_create_window(prompt_width, height, UP);
++        wrefresh(bwin);
++        getbegyx(bwin, winy, winx);
++        askwin = newwin(height, prompt_width, winy + 1, winx + 1);
++    }
++    else
++    {
++        bwin = curses_create_window(prompt_width, height, CENTER);
++        wrefresh(bwin);
++        getbegyx(bwin, winy, winx);
++        askwin = newwin(height, prompt_width, winy + 1, winx + 1);
++    }
++    for (count = 0; count < prompt_height; count++)
++    {
++        tmpstr = curses_break_str(prompt, maxwidth, count + 1);
++        if (count == (prompt_height - 1))    /* Last line */
++        {
++            mvwprintw(askwin, count, 0, "%s ", tmpstr);
++        }
++        else
++        {
++            mvwaddstr(askwin, count, 0, tmpstr);
++        }
++        free(tmpstr);
++    }
++    
++    echo();
++    curs_set(1);
++    wgetnstr(askwin, input, buffer-1);
++    curs_set(0);
++    strcpy(answer, input);
++    werase(bwin);
++    delwin(bwin);
++    curses_destroy_win(askwin);
++    noecho();
++}
++
++
++/* Get a single character response from the player, such as a y/n prompt */
++
++int curses_character_input_dialog(const char *prompt, const char *choices, CHAR_P def)
++{
++    WINDOW *askwin;
++    int answer, count, maxwidth, map_height, map_width;
++    char *linestr;
++    char askstr[BUFSZ + QBUFSZ];
++    char choicestr[QBUFSZ];
++    int prompt_width = strlen(prompt);
++    int prompt_height = 1;
++    boolean any_choice = FALSE;
++
++    curses_get_window_size(MAP_WIN, &map_height, &map_width);
++    maxwidth = map_width - 2;
++    
++    if (choices != NULL)
++    {
++        choicestr[0] = ' ';
++        choicestr[1] = '[';
++        for (count = 0; choices[count] != '\0'; count++)
++        {
++            if (choices[count] == '\033')   /* Escape */
++            {
++                break;
++            }
++            choicestr[count + 2] = choices[count];
++        }
++        choicestr[count + 2] = ']';
++        if (((def >= 'A') && (def <= 'Z')) || ((def >= 'a') && (def <= 'z')))
++        {
++            choicestr[count + 3] = ' ';
++            choicestr[count + 4] = '(';
++            choicestr[count + 5] = def;
++            choicestr[count + 6] = ')';
++            choicestr[count + 7] = '\0';
++        }
++        else    /* No usable default choice */
++        {
++            choicestr[count + 3] = '\0';
++            def = '\0'; /* Mark as no default */
++        }
++        strcpy(askstr, prompt);
++        strcat(askstr, choicestr);
++    }
++    else
++    {
++        strcpy(askstr, prompt);
++        any_choice = TRUE;
++    }
++    
++    prompt_width = strlen(askstr);
++    
++    if ((prompt_width + 2) > maxwidth)
++    {
++        prompt_height = curses_num_lines(askstr, maxwidth);
++        prompt_width = map_width - 2;
++    }
++
++    if (iflags.wc_popup_dialog)
++    {
++        askwin = curses_create_window(prompt_width, prompt_height, UP);
++        for (count = 0; count < prompt_height; count++)
++        {
++            linestr = curses_break_str(askstr, maxwidth, count + 1);
++            mvwaddstr(askwin, count + 1, 1, linestr);
++            free(linestr);
++        }
++    
++        wrefresh(askwin);
++    }
++    else
++    {
++        linestr = curses_copy_of(askstr);
++        pline("%s", linestr);
++        free(linestr);
++        curs_set(1);
++    }
++
++    while (1)
++    {
++        answer = curses_read_char();
++        if (answer==KEY_ESC)
++        {
++            if (choices == NULL)
++            {
++                break;
++            }
++            answer = def;
++            for (count = 0; choices[count] != '\0'; count++)
++            {
++                if (choices[count] == 'q') /* q is preferred over n */
++                {
++                    answer = 'q';
++                }
++                else if ((choices[count] == 'n') && answer != 'q')
++                {
++                    answer = 'n';
++                }
++            }
++            break;
++        }
++        else if ((answer == '\n') || (answer == '\r'))
++        {
++            if ((choices != NULL) && (def != '\0'))
++            {
++                answer = def;
++            }
++            break;
++        }
++        if (any_choice)
++        {
++            break;
++        }
++        if (choices != NULL)
++        {
++            for (count = 0; count < strlen(choices); count++)
++            {
++                if (choices[count] == answer)
++                {
++                    break;
++                }
++            }
++            if (choices[count] == answer)
++            {
++                break;
++            }
++        }
++    }
++
++    if (iflags.wc_popup_dialog)
++    {
++        curses_destroy_win(askwin);
++    }
++    else
++    {
++        curses_clear_unhighlight_message_window();
++        curs_set(0);
++    }
++    
++    return answer;
++}
++
++
++/* Return an extended command from the user */
++
++int curses_ext_cmd()
++{
++    /* We should check the value of iflags.extmenu here, but there is
++    currently no non-menu alternative */
++
++    return extcmd_via_menu();
++}
++
++
++/* Initialize a menu from given NetHack winid */
++
++void curses_create_nhmenu(winid wid)
++{
++    nhmenu *new_menu = NULL;
++    nhmenu *menuptr = nhmenus;
++    nhmenu_item *menu_item_ptr = NULL;
++    nhmenu_item *tmp_menu_item = NULL;
++    
++    new_menu = get_menu(wid);
++    
++    if (new_menu != NULL)
++    {
++        /* Reuse existing menu, clearing out current entries */
++        menu_item_ptr = new_menu->entries;
++        
++        if (menu_item_ptr != NULL)
++        {
++            while (menu_item_ptr->next_item != NULL)
++            {
++                tmp_menu_item = menu_item_ptr->next_item;
++                free(menu_item_ptr);
++                menu_item_ptr = tmp_menu_item;
++            }
++            free(menu_item_ptr);    /* Last entry */
++            new_menu->entries = NULL;
++        }
++        if (new_menu->prompt != NULL)   /* Reusing existing menu */
++        {
++            free((char *)new_menu->prompt);
++        }    
++        return;
++    }
++    
++    new_menu = malloc(sizeof(nhmenu));
++    new_menu->wid = wid;
++    new_menu->prompt = NULL;
++    new_menu->entries = NULL;
++    new_menu->num_pages = 0;
++    new_menu->height = 0;
++    new_menu->width = 0;
++    new_menu->next_menu = NULL;
++    
++    if (nhmenus == NULL)    /* no menus in memory yet */
++    {
++        new_menu->prev_menu = NULL;
++        nhmenus = new_menu;
++    }
++    else
++    {
++        while (menuptr->next_menu != NULL)
++        {
++            menuptr = menuptr->next_menu;
++        }
++        new_menu->prev_menu = menuptr;
++        menuptr->next_menu = new_menu;
++    }
++}
++
++
++/* Add a menu item to the given menu window */
++
++void curses_add_nhmenu_item(winid wid, const ANY_P *identifier,
++ CHAR_P accelerator, CHAR_P group_accel, int attr, const char *str,
++ BOOLEAN_P presel)
++{
++    char *new_str;
++    nhmenu_item *new_item, *current_items, *menu_item_ptr;
++    nhmenu *current_menu = get_menu(wid);
++    
++    if (str == NULL)
++    {
++        return;
++    }
++
++    new_str = curses_copy_of(str);
++    curses_rtrim((char *) new_str);
++    new_item = malloc(sizeof(nhmenu_item));
++    new_item->wid = wid;
++    new_item->identifier = *identifier;
++    new_item->accelerator = accelerator;
++    new_item->group_accel = group_accel;
++    new_item->attr = attr;
++    new_item->str = new_str;
++    new_item->presel = presel;
++    new_item->selected = FALSE;
++    new_item->page_num = 0;
++    new_item->line_num = 0;
++    new_item->num_lines = 0;
++    new_item->next_item = NULL;
++    
++    if (current_menu == NULL)
++    {
++        panic("curses_add_nhmenu_item: attempt to add item to nonexistant menu");
++    }
++
++    current_items = current_menu->entries;
++    menu_item_ptr = current_items;
++
++    if (current_items == NULL)
++    {
++        new_item->prev_item = NULL;
++        current_menu->entries = new_item;
++    }
++    else
++    {
++        while (menu_item_ptr->next_item != NULL)
++        {
++            menu_item_ptr = menu_item_ptr->next_item;
++        }
++        new_item->prev_item = menu_item_ptr;
++        menu_item_ptr->next_item = new_item;
++    }
++}
++
++
++/* No more entries are to be added to menu, so details of the menu can be
++ finalized in memory */
++
++void curses_finalize_nhmenu(winid wid, const char *prompt)
++{
++    int count = 0;
++    nhmenu *current_menu = get_menu(wid);
++    nhmenu_item *menu_item_ptr = current_menu->entries;
++
++    if (current_menu == NULL)
++    {
++        panic("curses_finalize_nhmenu: attempt to finalize nonexistant menu");
++    }
++
++    while (menu_item_ptr != NULL)
++    {
++        menu_item_ptr = menu_item_ptr->next_item;
++        count++;
++    }
++
++    current_menu->num_entries = count;
++    current_menu->prompt = curses_copy_of(prompt);
++}
++
++
++/* Display a nethack menu, and return a selection, if applicable */
++
++int curses_display_nhmenu(winid wid, int how, MENU_ITEM_P **_selected)
++{
++    nhmenu *current_menu = get_menu(wid);
++    nhmenu_item *menu_item_ptr;
++    int num_choices, num_chosen, count;
++    WINDOW *win;
++    int curpage = 1;
++    MENU_ITEM_P *selected = NULL;
++
++	*_selected = NULL;
++    
++    if (current_menu == NULL)
++    {
++        panic("curses_display_nhmenu: attempt to display nonexistant menu");
++    }
++    
++    menu_item_ptr = current_menu->entries;
++    
++    if (menu_item_ptr == NULL)
++    {
++        panic("curses_display_nhmenu: attempt to display empty menu");
++    }
++    
++    /* Reset items to unselected to clear out selections from previous
++    invocations of this menu */
++    while (menu_item_ptr != NULL)
++    {
++        menu_item_ptr->selected = FALSE;
++        menu_item_ptr = menu_item_ptr->next_item;
++    }
++
++    menu_win_size(current_menu);
++    menu_determine_pages(current_menu);
++    win = curses_create_window(current_menu->width, current_menu->height, RIGHT);
++    num_choices = menu_get_choices(current_menu, how);
++    num_chosen = menu_get_selections(win, current_menu, num_choices, how);
++    curses_destroy_win(win);
++    
++    if (num_chosen > 0)
++    {
++        selected = (MENU_ITEM_P*) malloc(num_chosen * sizeof(MENU_ITEM_P));
++        count = 0;
++        
++        menu_item_ptr = current_menu->entries;
++
++        while (menu_item_ptr != NULL)
++        {
++            if (menu_item_ptr->selected)
++            {
++                if (count == num_chosen)
++                {
++                    panic("curses_display_nhmenu: Selected items exceeds expected number");
++                }
++                selected[count].item = menu_item_ptr->identifier;
++                selected[count].count = -1;
++                count++; 
++            }
++            menu_item_ptr = menu_item_ptr->next_item;
++        }
++        
++        if (count != num_chosen)
++        {
++            panic("curses_display_nhmenu: Selected items less than expected number");
++        }
++    }
++
++    *_selected = selected;
++    
++    return num_chosen;
++}
++
++
++boolean curses_menu_exists(winid wid)
++{
++    if (get_menu(wid) != NULL)
++    {
++        return TRUE;
++    }
++    else
++    {
++        return FALSE;
++    }
++}
++
++/* Delete the menu associated with the given NetHack winid from memory */
++
++void curses_del_menu(winid wid)
++{
++    nhmenu_item *tmp_menu_item;
++    nhmenu_item *menu_item_ptr;
++    nhmenu *tmpmenu;
++    nhmenu *current_menu = get_menu(wid);
++    
++    if (current_menu == NULL)
++    {
++       return;
++    }
++    
++    menu_item_ptr = current_menu->entries;
++    
++    /* First free entries associated with this menu from memory */
++    if (menu_item_ptr != NULL)
++    {
++        while (menu_item_ptr->next_item != NULL)
++        {
++            tmp_menu_item = menu_item_ptr->next_item;
++            free(menu_item_ptr);
++            menu_item_ptr = tmp_menu_item;
++        }
++        free(menu_item_ptr);    /* Last entry */
++        current_menu->entries = NULL;
++    }
++    
++    /* Now unlink the menu from the list and free it as well */
++    if (current_menu->prev_menu != NULL)
++    {
++        tmpmenu = current_menu->prev_menu;
++        tmpmenu->next_menu = current_menu->next_menu;
++    }
++    else
++    {
++        nhmenus = current_menu->next_menu;   /* New head mode or NULL */
++    }
++    if (current_menu->next_menu != NULL)
++    {
++        tmpmenu = current_menu->next_menu;
++        tmpmenu->prev_menu = current_menu->prev_menu;
++    }
++    free(current_menu);
++}
++
++
++/* return a pointer to the menu associated with the given NetHack winid */
++
++static nhmenu *get_menu(winid wid)
++{
++    nhmenu *menuptr = nhmenus;
++
++    while (menuptr != NULL)
++    {
++        if (menuptr->wid == wid)
++        {
++            return menuptr;
++        }
++        menuptr = menuptr->next_menu;
++    }
++    
++    
++    return NULL;    /* Not found */
++}
++
++
++static char menu_get_accel(boolean first)
++{
++    char ret;
++    static char next_letter = 'a';
++    
++    if (first)
++    {
++        next_letter = 'a';
++    }
++    
++    ret = next_letter;
++    
++    if (((next_letter < 'z') && (next_letter >= 'a')) || ((next_letter < 'Z')
++     && (next_letter >= 'A')))
++    {
++        next_letter++;
++    }
++    else if (next_letter == 'z')
++    {
++        next_letter = 'A';
++    }
++    
++    return ret;
++}
++
++
++/* Determine if menu will require multiple pages to display */
++
++static boolean menu_is_multipage(nhmenu *menu, int width, int height)
++{
++    int num_lines;
++    int curline = 0;
++    nhmenu_item *menu_item_ptr = menu->entries;
++
++    if (strlen(menu->prompt) > 0)
++    {
++        curline += curses_num_lines(menu->prompt, width) + 1;
++    }
++    
++    if (menu->num_entries <= (height - curline))
++    {   
++        while (menu_item_ptr != NULL)
++        {
++            menu_item_ptr->line_num = curline;
++            if (menu_item_ptr->identifier.a_void == NULL)
++            {
++                num_lines = curses_num_lines(menu_item_ptr->str, width);
++            }
++            else
++            {
++                /* Add space for accelerator */
++                num_lines = curses_num_lines(menu_item_ptr->str, width - 4);
++            }
++            menu_item_ptr->num_lines = num_lines;
++            curline += num_lines;
++            menu_item_ptr = menu_item_ptr->next_item;
++            if (curline > height)
++            {
++                break;
++            }
++        }
++        if (menu_item_ptr == NULL)
++        {
++            return FALSE;
++        }
++    }
++    return TRUE;
++}
++
++
++/* Determine which entries go on which page, and total number of pages */
++
++static void menu_determine_pages(nhmenu *menu)
++{
++    int tmpline, num_lines;
++    int curline = 0;
++    int page_num = 1;
++    nhmenu_item *menu_item_ptr = menu->entries;
++    int width = menu->width;
++    int height = menu->height;
++    int page_end = height;
++    
++    
++    if (strlen(menu->prompt) > 0)
++    {
++        curline += curses_num_lines(menu->prompt, width) + 1;
++    }
++        
++    tmpline = curline;
++    
++    if (menu_is_multipage(menu, width, height))
++    {
++        page_end -= 2;  /* Room to display current page number */
++    }
++
++    /* Determine what entries belong on which page */
++    menu_item_ptr = menu->entries;
++    
++    while (menu_item_ptr != NULL)
++    {
++        menu_item_ptr->page_num = page_num;
++        menu_item_ptr->line_num = curline;
++        if (menu_item_ptr->identifier.a_void == NULL)
++        {
++            num_lines = curses_num_lines(menu_item_ptr->str, width);
++        }
++        else
++        {
++            /* Add space for accelerator */
++            num_lines = curses_num_lines(menu_item_ptr->str, width - 4);
++        }
++        menu_item_ptr->num_lines = num_lines;
++        curline += num_lines;
++        if (curline > page_end)
++        {
++            page_num++;
++            curline = tmpline;
++            /* Move ptr back so entry will be reprocessed on new page */
++            menu_item_ptr = menu_item_ptr->prev_item;
++        }
++        menu_item_ptr = menu_item_ptr->next_item;
++    }
++    
++    menu->num_pages = page_num;
++}
++
++
++/* Determine dimensions of menu window based on term size and entries */
++
++static void menu_win_size(nhmenu *menu)
++{
++    int width, height, maxwidth, maxheight, curentrywidth, lastline,
++     map_height, map_width;
++    int maxentrywidth = strlen(menu->prompt);
++    int maxheaderwidth = 0;
++    nhmenu_item *menu_item_ptr = menu->entries;
++    
++    maxwidth = 38;  /* Reasonable minimum usable width */
++    
++    if ((term_cols / 2) > maxwidth)
++    {
++        maxwidth = (term_cols / 2); /* Half the screen */
++    }
++    
++    maxheight = term_rows - 2;
++    
++    /* First, determine the width of the longest menu entry */
++    while (menu_item_ptr != NULL)
++    {
++        if (menu_item_ptr->identifier.a_void == NULL)
++        {
++            curentrywidth=strlen(menu_item_ptr->str);
++
++            if (curentrywidth > maxheaderwidth)
++            {
++                maxheaderwidth = curentrywidth;
++            }
++        }
++        else
++        {
++            /* Add space for accelerator */
++            curentrywidth=strlen(menu_item_ptr->str) + 4;
++        }
++        if (curentrywidth > maxentrywidth)
++        {
++            maxentrywidth = curentrywidth;          
++        }
++        menu_item_ptr = menu_item_ptr->next_item;
++    }
++    
++    /* If the widest entry is smaller than maxwidth, reduce maxwidth accordingly */
++    if (maxentrywidth < maxwidth)
++    {
++        maxwidth = maxentrywidth;
++    }
++    
++    /* Try not to wrap headers/normal text lines if possible.  We can
++    go wider than half the screen for this purpose if need be */
++    
++    if ((maxheaderwidth > maxwidth) && (maxheaderwidth < (term_cols - 2)))
++    {
++        maxwidth = maxheaderwidth;
++    }
++    
++    width = maxwidth;
++    
++    /* Possibly reduce height if only 1 page */    
++    if (!menu_is_multipage(menu, maxwidth, maxheight))   
++    {
++        menu_item_ptr = menu->entries;
++        
++        while (menu_item_ptr->next_item != NULL)
++        {
++            menu_item_ptr = menu_item_ptr->next_item;
++        }
++        
++        lastline = (menu_item_ptr->line_num) + menu_item_ptr->num_lines;
++    
++        if (lastline < maxheight)
++        {
++            maxheight = lastline;
++        }
++    }
++    else    /* If multipage, make sure we have enough width for page footer */
++    {
++        if (width < 20)
++        {
++            width = 20;
++        }
++    }
++
++    height = maxheight;
++    menu->width = width;
++    menu->height = height;
++}
++
++
++/* Displays menu selections in the given window */
++
++static void menu_display_page(nhmenu *menu, WINDOW *win, int page_num)
++{
++    nhmenu_item *menu_item_ptr;
++    int count, curletter, entry_cols, start_col, num_lines, footer_x;
++    boolean first_accel = TRUE;
++        
++    /* Cycle through entries until we are on the correct page */
++
++    menu_item_ptr = menu->entries;
++    
++    while (menu_item_ptr != NULL)
++    {
++        if (menu_item_ptr->page_num == page_num)
++        {
++            break;
++        }
++        menu_item_ptr = menu_item_ptr->next_item;
++    }
++    
++    if (menu_item_ptr == NULL)  /* Page not found */
++    {
++        panic("menu_display_page: attempt to display nonexistant page");
++    }
++
++    werase(win);
++
++    if (strlen(menu->prompt) > 0)
++    {
++        num_lines = curses_num_lines(menu->prompt, menu->width);
++        
++        for (count = 0; count < num_lines; count++)
++        {
++            mvwprintw(win, count + 1, 1, "%s",
++             curses_break_str(menu->prompt, menu->width, count + 1));
++        }
++    }
++
++    /* Display items for current page */
++    
++    while (menu_item_ptr != NULL)
++    {
++        if (menu_item_ptr->page_num != page_num)
++        {
++            break;
++        }
++        if (menu_item_ptr->identifier.a_void != NULL)
++        {
++            if (menu_item_ptr->accelerator != 0)
++            {
++                curletter = menu_item_ptr->accelerator;
++            }
++            else
++            {
++                if (first_accel)
++                {
++                    curletter = menu_get_accel(TRUE);
++                    first_accel = FALSE;
++                }
++                else
++                {
++                    curletter = menu_get_accel(FALSE);
++                }
++                menu_item_ptr->accelerator = curletter;
++            }
++            curses_toggle_color_attr(win, NONE, ATR_BOLD, ON);
++            mvwaddch(win, menu_item_ptr->line_num + 1, 2, curletter);
++            curses_toggle_color_attr(win, NONE, ATR_BOLD, OFF);
++            if (menu_item_ptr->selected)
++            {
++                curses_toggle_color_attr(win, HIGHLIGHT_COLOR, NONE, ON);
++                mvwaddch(win, menu_item_ptr->line_num + 1, 1, '<');
++                mvwaddch(win, menu_item_ptr->line_num + 1, 3, '>');
++                curses_toggle_color_attr(win, HIGHLIGHT_COLOR, NONE, OFF);
++            }
++            else
++            {
++                mvwprintw(win, menu_item_ptr->line_num + 1, 3, ") ");
++            }
++        }
++        curses_toggle_color_attr(win, NONE, menu_item_ptr->attr, ON);
++        entry_cols = menu->width;
++        start_col = 1;
++
++        if (menu_item_ptr->identifier.a_void != NULL)
++        {
++            entry_cols -= 4;
++            start_col += 4;
++        }        
++        
++        num_lines = curses_num_lines(menu_item_ptr->str, entry_cols);
++        
++        for (count = 0; count < num_lines; count++)
++        {
++            if (strlen(menu_item_ptr->str) > 0)
++            {
++                mvwprintw(win, menu_item_ptr->line_num + count + 1,
++                 start_col, "%s", curses_break_str(menu_item_ptr->str,
++                 entry_cols, count + 1));
++             }
++        }
++        curses_toggle_color_attr(win, NONE, menu_item_ptr->attr, OFF);
++        menu_item_ptr = menu_item_ptr->next_item;
++    }
++
++    if (menu->num_pages > 1)
++    {
++        footer_x = menu->width - strlen("<- (Page X of Y) ->");
++        if (menu->num_pages > 9)    /* Unlikely */
++        {
++            footer_x -= 2;
++        }
++        mvwprintw(win, menu->height, footer_x + 3, "(Page %d of %d)",
++         page_num, menu->num_pages);
++        if (page_num != 1)
++        {
++            curses_toggle_color_attr(win, HIGHLIGHT_COLOR, NONE, ON);
++            mvwaddstr(win, menu->height, footer_x, "<=");
++            curses_toggle_color_attr(win, HIGHLIGHT_COLOR, NONE, OFF);
++        }
++        if (page_num != menu->num_pages)
++        {
++            curses_toggle_color_attr(win, HIGHLIGHT_COLOR, NONE, ON);
++            mvwaddstr(win, menu->height, menu->width - 2, "=>");        
++            curses_toggle_color_attr(win, HIGHLIGHT_COLOR, NONE, OFF);
++        }
++    }
++    curses_toggle_color_attr(win, DIALOG_BORDER_COLOR, NONE, ON);
++    box(win, 0, 0);
++    curses_toggle_color_attr(win, DIALOG_BORDER_COLOR, NONE, OFF);
++    wrefresh(win);
++}
++
++
++/* Add valid selections to choices array, and return the number of choices */
++
++static int menu_get_choices(nhmenu *menu, int how)
++{
++    char curletter;
++    int count = 0;
++    int accel_idx = 0;
++    nhmenu_item *menu_item_ptr = menu->entries;
++    
++    if (how == PICK_NONE)
++        return 0;
++
++    while (menu_item_ptr != NULL)
++    {
++        if (menu_item_ptr->identifier.a_void != NULL)
++        {
++            if (menu_item_ptr->accelerator != 0)
++            {
++                curletter = menu_item_ptr->accelerator;
++            }
++            else
++            {
++                if (accel_idx == 0)
++                {
++                    curletter = menu_get_accel(TRUE);
++                }
++                else
++                {
++                    curletter = menu_get_accel(FALSE);
++                }
++                menu_item_ptr->accelerator = curletter;
++            }
++            accel_idx++;
++        }
++        menu_item_ptr = menu_item_ptr->next_item;
++        count++;
++    }
++    return count;
++}
++
++
++
++static int menu_get_selections(WINDOW *win, nhmenu *menu, int num_choices, int how)
++{
++    int count, curletter;
++    int curpage = 1;
++    int num_selected = 0;
++    boolean dismiss = FALSE;
++    nhmenu_item *menu_item_ptr = menu->entries;
++
++    menu_display_page(menu, win, 1);
++
++    while (!dismiss)
++    {
++        curletter = getch();
++        
++        switch (curletter)
++        {
++            case KEY_ESC:
++            {
++                num_selected = -1;
++                dismiss = TRUE;
++                break;
++            }
++            case '\n':
++            case '\r':
++            {
++                dismiss = TRUE;
++                break;
++            }
++            case KEY_RIGHT:
++            case KEY_NPAGE:
++            case MENU_NEXT_PAGE:
++            case ' ':
++            {
++                if (curpage < menu->num_pages)
++                {
++                    curpage++;
++                    menu_display_page(menu, win, curpage);
++                }
++                break;
++            }
++            case KEY_LEFT:
++            case KEY_PPAGE:
++            case MENU_PREVIOUS_PAGE:
++            {
++                if (curpage > 1)
++                {
++                    curpage--;
++                    menu_display_page(menu, win, curpage);
++                }
++                break;
++            }
++            case KEY_END:
++            case MENU_LAST_PAGE:
++            {
++                if (curpage != menu->num_pages)
++                {
++                    curpage = menu->num_pages;
++                    menu_display_page(menu, win, curpage);
++                }
++                break;
++            }
++            case KEY_HOME:
++            case MENU_FIRST_PAGE:
++            {
++                if (curpage != 1)
++                {
++                    curpage = 1;
++                    menu_display_page(menu, win, curpage);
++                }
++                break;
++            }
++        }
++        if (how == PICK_ANY)
++        {
++            switch (curletter)
++                {
++                case MENU_SELECT_PAGE:
++                {
++                    (void) menu_operation(win, menu, SELECT, curpage);
++                    break;
++                }
++                case MENU_SELECT_ALL:
++                {
++                    curpage = menu_operation(win, menu, SELECT, 0);
++                    break;
++                }
++                case MENU_UNSELECT_PAGE:
++                {
++                    (void) menu_operation(win, menu, DESELECT, curpage);
++                    break;
++                }
++                case MENU_UNSELECT_ALL:
++                {
++                    curpage = menu_operation(win, menu, DESELECT, 0);
++                    break;
++                }
++                case MENU_INVERT_PAGE:
++                {
++                    (void) menu_operation(win, menu, INVERT, curpage);
++                    break;
++                }
++                case MENU_INVERT_ALL:
++                {
++                    curpage = menu_operation(win, menu, INVERT, 0);
++                    break;
++                }
++            }
++        }
++        
++        menu_item_ptr = menu->entries;
++        
++        while ((menu_item_ptr != NULL) && (how != PICK_NONE))
++        {
++            if (menu_item_ptr->identifier.a_void != NULL)
++            {
++                if (curletter == menu_item_ptr->accelerator)
++                {
++                    if (curpage != menu_item_ptr->page_num)
++                    {
++                        curpage = menu_item_ptr->page_num;
++                        menu_display_page(menu, win, curpage);
++                    }
++                    menu_select_deselect(win, menu_item_ptr, INVERT);
++                    if (how == PICK_ONE)
++                    {
++                        num_selected = 1;
++                        dismiss = TRUE;
++                    }
++                    break;
++                }
++            }
++            menu_item_ptr = menu_item_ptr->next_item;
++        }
++    }
++    
++    if ((how == PICK_ANY) && (num_selected != -1))
++    {
++        num_selected = 0;
++        menu_item_ptr = menu->entries;
++        
++        while (menu_item_ptr != NULL)
++        {
++            if (menu_item_ptr->identifier.a_void != NULL)
++            {
++                if (menu_item_ptr->selected)
++                {
++                    num_selected++;
++                }
++            }
++            menu_item_ptr = menu_item_ptr->next_item;
++        }
++    }
++    
++    return num_selected;
++}
++
++
++/* Select, deselect, or toggle selected for the given menu entry */
++
++static void menu_select_deselect(WINDOW *win, nhmenu_item *item, menu_op operation)
++{
++    if ((operation == DESELECT) || (item->selected && (operation ==
++     INVERT)))
++    {
++        item->selected = FALSE;
++        mvwaddch(win, item->line_num + 1, 1, ' ');
++        mvwaddch(win, item->line_num + 1, 3, ')');
++    }
++    else
++    {
++        item->selected = TRUE;
++        curses_toggle_color_attr(win, HIGHLIGHT_COLOR, NONE, ON);
++        mvwaddch(win, item->line_num + 1, 1, '<');
++        mvwaddch(win, item->line_num + 1, 3, '>');
++        curses_toggle_color_attr(win, HIGHLIGHT_COLOR, NONE, OFF);
++    }
++    
++    wrefresh(win);
++}
++
++
++/* Perform the selected operation (select, unselect, invert selection)
++on the given menu page.  If menu_page is 0, then perform opetation on
++all pages in menu.  Returns last page displayed.  */
++
++static int menu_operation(WINDOW *win, nhmenu *menu, menu_op
++ operation, int page_num)
++{
++    int first_page, last_page, current_page;
++    nhmenu_item *menu_item_ptr = menu->entries;    
++    
++    if (page_num == 0)  /* Operation to occur on all pages */
++    {
++        first_page = 1;
++        last_page = menu->num_pages;
++    }
++    else
++    {
++        first_page = page_num;
++        last_page = page_num;
++    }
++
++    /* Cycle through entries until we are on the correct page */
++
++    while (menu_item_ptr != NULL)
++    {
++        if (menu_item_ptr->page_num == first_page)
++        {
++            break;
++        }
++        menu_item_ptr = menu_item_ptr->next_item;
++    }
++    
++    current_page = first_page;
++    
++    if (page_num == 0)
++    {
++        menu_display_page(menu, win, current_page);
++    }
++    
++    if (menu_item_ptr == NULL)  /* Page not found */
++    {
++        panic("menu_display_page: attempt to display nonexistant page");
++    }
++    
++    while (menu_item_ptr != NULL)
++    {        
++        if (menu_item_ptr->page_num != current_page)
++        {
++            if (menu_item_ptr->page_num > last_page)
++            {
++                break;
++            }
++
++            current_page = menu_item_ptr->page_num;
++            menu_display_page(menu, win, current_page);
++        }
++        
++        if (menu_item_ptr->identifier.a_void != NULL)
++        {
++            menu_select_deselect(win, menu_item_ptr, operation);
++        }
++        
++        menu_item_ptr = menu_item_ptr->next_item;
++    }
++    
++    return current_page;
++}
+diff -burN nethack-3.4.3/win/curses/cursdial.h nethack/win/curses/cursdial.h
+--- nethack-3.4.3/win/curses/cursdial.h	1969-12-31 19:00:00.000000000 -0500
++++ nethack/win/curses/cursdial.h	2009-03-05 13:50:38.000000000 -0500
+@@ -0,0 +1,89 @@
++#ifndef CURSDIAL_H
++#define CURSDIAL_H
++
++
++/* Global declarations */
++
++void curses_line_input_dialog(const char *prompt, char *answer, int buffer);
++
++int curses_character_input_dialog(const char *prompt, const char *choices, CHAR_P def);
++
++int curses_ext_cmd(void);
++
++void curses_create_nhmenu(winid wid);
++
++void curses_add_nhmenu_item(winid wid, const ANY_P *identifier,
++ CHAR_P accelerator, CHAR_P group_accel, int attr, const char *str,
++ BOOLEAN_P presel);
++
++void curses_finalize_nhmenu(winid wid, const char *prompt);
++
++int curses_display_nhmenu(winid wid, int how, MENU_ITEM_P **_selected);
++
++boolean curses_menu_exists(winid wid);
++
++void curses_del_menu(winid wid);
++
++
++/* Private declarations */
++
++typedef struct nhmi
++{
++    winid wid;  /* NetHack window id */
++    anything identifier; /* Value returned if item selected */
++    CHAR_P accelerator;  /* Character used to select item from menu */
++    CHAR_P group_accel; /* Group accelerator for menu item, if any */
++    int attr;  /* Text attributes for item */
++    const char *str;  /* Text of menu item */
++    BOOLEAN_P presel; /* Whether menu item should be preselected */
++    boolean selected;   /* Whether item is currently selected */
++    int page_num;   /* Display page number for entry */
++    int line_num;   /* Line number on page where entry begins */
++    int num_lines;  /* Number of lines entry uses on page */
++    struct nhmi *prev_item;    /* Pointer to previous entry */
++    struct nhmi *next_item;    /* Pointer to next entry */
++} nhmenu_item;
++
++typedef struct nhm
++{
++    winid wid;  /* NetHack window id */
++    const char *prompt;  /* Menu prompt text */
++    nhmenu_item *entries;   /* Menu entries */
++    int num_entries;          /* Number of menu entries */
++    int num_pages;            /* Number of display pages for entry */
++    int height;               /* Window height of menu */
++    int width;                /* Window width of menu */
++    struct nhm *prev_menu;    /* Pointer to previous entry */
++    struct nhm *next_menu;    /* Pointer to next entry */
++} nhmenu;
++
++typedef enum menu_op_type
++{
++    SELECT,
++    DESELECT,
++    INVERT
++} menu_op;
++
++static nhmenu *get_menu(winid wid);
++
++static char menu_get_accel(boolean first);
++
++static void menu_determine_pages(nhmenu *menu);
++
++static boolean menu_is_multipage(nhmenu *menu, int width, int height);
++
++static void menu_win_size(nhmenu *menu);
++
++static void menu_display_page(nhmenu *menu, WINDOW *win, int page_num);
++
++static int menu_get_choices(nhmenu *menu, int how);
++
++static int menu_get_selections(WINDOW *win, nhmenu *menu, int num_choices, int how);
++
++static void menu_select_deselect(WINDOW *win, nhmenu_item *item, menu_op operation);
++
++static int menu_operation(WINDOW *win, nhmenu *menu, menu_op operation,
++ int page_num);
++
++
++#endif  /* CURSDIAL_H */
+diff -burN nethack-3.4.3/win/curses/cursinit.c nethack/win/curses/cursinit.c
+--- nethack-3.4.3/win/curses/cursinit.c	1969-12-31 19:00:00.000000000 -0500
++++ nethack/win/curses/cursinit.c	2009-03-11 15:08:53.000000000 -0400
+@@ -0,0 +1,792 @@
++#include "curses.h"
++#include "hack.h"
++#include "wincurs.h"
++#include "cursinit.h"
++
++/* Initialization functions for curses interface */
++
++
++/* Create the "main" nonvolitile windows used by nethack */
++
++void curses_create_main_windows()
++{
++    int message_x, message_y, status_x, status_y, map_x, map_y;
++    int message_height, message_width, status_height, status_width,
++     map_height, map_width;
++    int min_message_height = 1;
++    int message_orientation = 0;
++    int status_orientation = 0;
++    int border_space = 0;
++    int hspace = term_cols - 80;
++    boolean borders = FALSE;
++
++    switch (iflags.wc2_windowborders)
++    {
++        case 1: /* On */
++        {
++            borders = TRUE;
++            break;
++        }
++        case 2: /* Off */
++        {
++            borders = FALSE;
++            break;
++        }
++        case 3: /* Auto */
++        {
++            if ((term_cols > 81) && (term_rows > 25))
++            {
++                borders = TRUE;
++            }
++            break;
++        }
++        default:
++        {
++            borders = FALSE;
++        }
++    }
++
++    
++    if (borders)
++    {
++        border_space = 2;
++        hspace -= border_space;
++    }
++    
++    if ((term_cols - border_space) < COLNO)
++    {
++        min_message_height++;
++    }
++    
++    /* Determine status window orientation */    
++    if (!iflags.wc_align_status || (iflags.wc_align_status == ALIGN_TOP)
++     || (iflags.wc_align_status == ALIGN_BOTTOM))
++    {
++        if (!iflags.wc_align_status)
++        {
++            iflags.wc_align_status = ALIGN_BOTTOM;
++        }
++        status_orientation = iflags.wc_align_status;
++    }
++    else    /* left or right alignment */
++    {
++        /* Max space for player name and title horizontally */
++        if ((hspace >= 26) && (term_rows >= 24))
++        {
++            status_orientation = iflags.wc_align_status;
++            hspace -= (26 + border_space);
++        }
++        else
++        {
++            status_orientation = ALIGN_BOTTOM;
++        }
++    }
++    
++    /* Determine message window orientation */    
++    if (!iflags.wc_align_message || (iflags.wc_align_message == ALIGN_TOP)
++     || (iflags.wc_align_message == ALIGN_BOTTOM))
++    {
++        if (!iflags.wc_align_message)
++        {
++            iflags.wc_align_message = ALIGN_TOP;
++        }
++        message_orientation = iflags.wc_align_message;
++    }
++    else    /* left or right alignment */
++    {
++        if ((hspace - border_space) >= 25)   /* Arbitrary */
++        {
++            message_orientation = iflags.wc_align_message;
++        }
++        else
++        {
++            message_orientation = ALIGN_TOP;
++        }
++    }
++    
++    /* Determine window placement and size - 16 possible combos
++       If anyone wants to try to generalize this, be my guest! */
++    if ((status_orientation == ALIGN_TOP) &&
++     (message_orientation == ALIGN_TOP))
++    {
++        status_x = 0;
++        status_y = 0;
++        status_width = (term_cols - border_space);
++        status_height = 2;
++        message_x = 0;
++        message_y = status_y + (status_height + border_space);
++        message_width = (term_cols - border_space);
++        message_height = term_rows - (status_height + ROWNO + (border_space * 3));
++        if (message_height < min_message_height)
++        {
++            message_height = min_message_height;
++        }
++        map_x = 0;
++        map_y = message_y + (message_height + border_space);
++        map_width = (term_cols - border_space);
++        map_height = term_rows - (status_height + message_height + (border_space * 3));
++    }
++    else if ((status_orientation == ALIGN_TOP) &&
++     (message_orientation == ALIGN_RIGHT))
++    {
++        status_x = 0;
++        status_y = 0;
++        status_height = 2;
++        message_height = (term_rows - border_space);
++        message_width = term_cols - (COLNO + (border_space * 2));
++        status_width = term_cols - (message_width + (border_space * 2));
++        message_x = status_x + (status_width + border_space);
++        message_y = 0;
++        map_x = 0;
++        map_y = status_y + (status_height + border_space);
++        map_width = status_width;
++        map_height = term_rows - (status_height + (border_space * 2));
++    }
++    else if ((status_orientation == ALIGN_TOP) &&
++     (message_orientation == ALIGN_BOTTOM))
++    {
++        status_x = 0;
++        status_y = 0;
++        status_width = (term_cols - border_space);
++        status_height = 2;
++        map_x = 0;
++        map_y = status_y + (status_height + border_space);
++        map_width = (term_cols - border_space);
++        message_height = term_rows - (status_height + ROWNO + (border_space * 3));
++        if (message_height < min_message_height)
++        {
++            message_height = min_message_height;
++        }
++        map_height = term_rows - (status_height + message_height + (border_space * 3));
++        message_x = 0;
++        message_y = map_y + (map_height + border_space);
++        message_width = (term_cols - border_space);
++    }
++    else if ((status_orientation == ALIGN_TOP) &&
++     (message_orientation == ALIGN_LEFT))
++    {
++        message_x = 0;
++        message_y = 0;
++        message_height = (term_rows - border_space);
++        message_width = term_cols - (COLNO + (border_space * 2));
++        status_x = message_x + (message_width + border_space);
++        status_y = 0;
++        status_height = 2;
++        status_width = term_cols - (message_width + (border_space * 2));
++        map_x = status_x;
++        map_y = status_y + (status_height + border_space);
++        map_height = term_rows - (status_height + (border_space * 2));
++        map_width = status_width;
++    }
++    if ((status_orientation == ALIGN_RIGHT) &&
++     (message_orientation == ALIGN_TOP))
++    {
++        status_width = 26;
++        status_height = (term_rows - border_space);
++        status_x = term_cols - (status_width + border_space);
++        status_y = 0;
++        message_x = 0;
++        message_y = 0;
++        message_width = term_cols - (status_width + (border_space * 2));
++        message_height = term_rows - (ROWNO + (border_space * 2));
++        if (message_height < min_message_height)
++        {
++            message_height = min_message_height;
++        }
++        map_x = 0;
++        map_y = message_y + (message_height + border_space);
++        map_width = term_cols - (status_width + (border_space * 2));
++        map_height = term_rows - (message_height + (border_space * 2));
++    }
++    else if ((status_orientation == ALIGN_RIGHT) &&
++     (message_orientation == ALIGN_RIGHT))
++    {
++        map_x = 0;
++        map_y = 0;
++        map_height = (term_rows - border_space);
++        status_width = 26;
++        message_width = term_cols - (COLNO + status_width + (border_space * 3));
++        map_width = term_cols - (status_width + message_width + (border_space * 3));
++        message_x = map_x + (map_width + border_space);
++        message_y = 0;
++        message_height = (term_rows - border_space);
++        status_x = message_x + (message_width + border_space);
++        status_y = 0;
++        status_height = (term_rows - border_space);
++    }
++    else if ((status_orientation == ALIGN_RIGHT) &&
++     (message_orientation == ALIGN_BOTTOM))
++    {
++        map_x = 0;
++        map_y = 0;
++        status_width = 26;
++        map_width = term_cols - (status_width + (border_space * 2));
++        message_height = term_rows - (ROWNO + (border_space * 2));
++        if (message_height < min_message_height)
++        {
++            message_height = min_message_height;
++        }
++        map_height = term_rows - (message_height + (border_space * 2));
++        message_x = 0;
++        message_y = map_y + (map_height + border_space);
++        message_width = map_width;
++        status_x = map_x + (map_width + border_space);
++        status_y = 0;
++        status_height = (term_rows - border_space);
++    }
++    else if ((status_orientation == ALIGN_RIGHT) &&
++     (message_orientation == ALIGN_LEFT))
++    {
++        status_x = 0;
++        status_y = 0;
++        status_height = (term_rows - border_space);
++        status_width = 26;
++        message_width = term_cols - (status_width + COLNO + (border_space * 3));
++        map_x = status_x + (status_width + border_space);
++        map_y = 0;
++        map_height = (term_rows - border_space);
++        map_width = term_cols - (status_width + message_width + (border_space * 3));
++        message_x = map_x + (map_width + border_space);
++        message_y = 0;
++        message_height = (term_rows - border_space);
++    }
++    if ((status_orientation == ALIGN_BOTTOM) &&
++     (message_orientation == ALIGN_TOP))
++    {
++        message_x = 0;
++        message_y = 0;
++        message_width = (term_cols - border_space);
++        status_height = 2;
++        message_height = term_rows - (status_height + ROWNO + (border_space * 3));
++        if (message_height < min_message_height)
++        {
++            message_height = min_message_height;
++        }
++        map_x = 0;
++        map_y = message_y + (message_height + border_space);
++        map_width = (term_cols - border_space);
++        map_height = term_rows - (status_height + message_height + (border_space * 3));
++        status_x = 0;
++        status_y = map_y + (map_height + border_space);
++        status_width = (term_cols - border_space);
++    }
++    else if ((status_orientation == ALIGN_BOTTOM) &&
++     (message_orientation == ALIGN_RIGHT))
++    {
++        map_x = 0;
++        map_y = 0;
++        status_height = 2;
++        map_height = term_rows - (status_height + (border_space * 2));
++        message_width = term_cols - (COLNO + (border_space * 2));
++        map_width = term_cols - (message_width + (border_space * 2));
++        status_x = 0;
++        status_y = map_y + (map_height + border_space);
++        status_width = map_width;
++        message_x = map_x + (map_width + border_space);
++        message_y = 0;
++        message_height = (term_rows - border_space);
++    }
++    else if ((status_orientation == ALIGN_BOTTOM) &&
++     (message_orientation == ALIGN_BOTTOM))
++    {
++        map_x = 0;
++        map_y = 0;
++        message_x = 0;
++        status_x = 0;
++        message_width = (term_cols - border_space);
++        status_height = 2;
++        message_height = term_rows - (status_height + ROWNO + (border_space * 3));
++        if (message_height < min_message_height)
++        {
++            message_height = min_message_height;
++        }
++        map_width = (term_cols - border_space);
++        map_height = term_rows - (status_height + message_height + (border_space * 3));
++        message_y = map_y + (map_height + border_space);
++        status_y = message_y + (message_height + border_space);
++        status_width = (term_cols - border_space);
++    }
++    else if ((status_orientation == ALIGN_BOTTOM) &&
++     (message_orientation == ALIGN_LEFT))
++    {
++        message_x = 0;
++        message_y = 0;
++        message_height = (term_rows - border_space);
++        message_width = term_cols - (COLNO + (border_space * 2));
++        status_height = 2;
++        map_x = message_x + (message_width + border_space);
++        map_y = 0;
++        map_height = term_rows - (status_height + (border_space * 2));
++        map_width = term_cols - (message_width + (border_space * 2));
++        status_x = map_x;
++        status_y = map_y + (map_height + border_space);
++        status_width = term_cols - (message_width + (border_space * 2));
++    }
++    if ((status_orientation == ALIGN_LEFT) &&
++     (message_orientation == ALIGN_TOP))
++    {
++        status_x = 0;
++        status_y = 0;
++        status_height = (term_rows - border_space);
++        status_width = 26;
++        message_x = status_x + (status_width + border_space);
++        message_y = 0;
++        message_height = term_rows - (ROWNO + (border_space * 2));
++        if (message_height < min_message_height)
++        {
++            message_height = min_message_height;
++        }
++        message_width = term_cols - (status_width + (border_space * 2));
++        map_x = message_x;
++        map_y = message_y + (message_height + border_space);
++        map_height = term_rows - (message_height + (border_space * 2));
++        map_width = term_cols - (status_width + (border_space * 2));
++    }
++    else if ((status_orientation == ALIGN_LEFT) &&
++     (message_orientation == ALIGN_RIGHT))
++    {
++        message_x = 0;
++        message_y = 0;
++        message_height = (term_rows - border_space);
++        status_width = 26;
++        message_width = term_cols - (status_width + COLNO + (border_space * 3));
++        map_x = message_x + (message_width + border_space);
++        map_y = 0;
++        map_height = (term_rows - border_space);
++        map_width = term_cols - (status_width + message_width + (border_space * 3));
++        status_x = map_x + (map_width + border_space);
++        status_y = 0;
++        status_height = (term_rows - border_space);
++    }
++    else if ((status_orientation == ALIGN_LEFT) &&
++     (message_orientation == ALIGN_BOTTOM))
++    {
++        status_x = 0;
++        status_y = 0;
++        status_height = (term_rows - border_space);
++        status_width = 26;
++        map_x = status_x + (status_width + border_space);
++        map_y = 0;
++        message_height = term_rows - (ROWNO + (border_space * 2));
++        if (message_height < min_message_height)
++        {
++            message_height = min_message_height;
++        }
++        map_height = term_rows - (message_height + (border_space * 2));
++        map_width = term_cols - (status_width + (border_space * 2));
++        message_x = status_x + (status_width + border_space);
++        message_y = map_y + (map_height + border_space);
++        message_width = map_width;
++    }
++    else if ((status_orientation == ALIGN_LEFT) &&
++     (message_orientation == ALIGN_LEFT))
++    {
++        status_x = 0;
++        status_y = 0;
++        status_height = (term_rows - border_space);
++        status_width = 26;
++        message_x = status_x + (status_width + border_space);
++        message_y = 0;
++        message_height = status_height;
++        message_width = term_cols - (COLNO + status_width + (border_space * 3));
++        map_x = message_x + (message_width + border_space);
++        map_y = 0;
++        map_height = message_height;
++        map_width = term_cols - (status_width + message_width + (border_space * 3));
++    }
++    
++    if (map_width > COLNO)
++    {
++        map_width = COLNO;
++    }
++    
++    if (map_height > ROWNO)
++    {
++        map_height = ROWNO;
++    }
++    
++    if (curses_window_exists(STATUS_WIN))
++    {
++        curses_del_nhwin(STATUS_WIN);
++        curses_del_nhwin(MESSAGE_WIN);
++        curses_del_nhwin(MAP_WIN);
++        clear();
++    }
++    
++    curses_add_nhwin(STATUS_WIN, status_height, status_width, status_y,
++     status_x, status_orientation, borders);
++
++    curses_add_nhwin(MESSAGE_WIN, message_height, message_width, message_y,
++     message_x, message_orientation, borders);
++
++    if (borders)
++    {
++        mapborderwin = newwin(map_height + border_space, map_width
++         + border_space, map_y, map_x);
++        wrefresh(mapborderwin);
++        curses_add_nhwin(MAP_WIN, map_height, map_width, map_y + 1, map_x + 1,
++         0, borders);
++    }
++    else
++    {
++        curses_add_nhwin(MAP_WIN, map_height, map_width, map_y, map_x, 0,
++         borders);
++    }
++
++    refresh();
++    curses_refresh_nethack_windows();
++
++    if (iflags.window_inited)
++    {
++        curses_update_stats();
++    }
++    else
++    {
++        iflags.window_inited = TRUE;
++    }
++}
++
++
++/* Initialize curses colors to colors used by NetHack */
++
++void curses_init_nhcolors()
++{
++#ifdef TEXTCOLOR
++    if (has_colors())
++    {
++#ifdef NCURSES_VERSION
++        use_default_colors();
++        init_pair(1, COLOR_BLACK, -1);
++        init_pair(2, COLOR_RED, -1);
++        init_pair(3, COLOR_GREEN, -1);
++        init_pair(4, COLOR_YELLOW, -1);
++        init_pair(5, COLOR_BLUE, -1);
++        init_pair(6, COLOR_MAGENTA, -1);
++        init_pair(7, COLOR_CYAN, -1);
++        init_pair(8, -1, -1);
++        init_pair(9, COLOR_WHITE, -1);
++#else        
++        init_pair(1, COLOR_BLACK, COLOR_BLACK);
++        init_pair(2, COLOR_RED, COLOR_BLACK);
++        init_pair(3, COLOR_GREEN, COLOR_BLACK);
++        init_pair(4, COLOR_YELLOW, COLOR_BLACK);
++        init_pair(5, COLOR_BLUE, COLOR_BLACK);
++        init_pair(6, COLOR_MAGENTA, COLOR_BLACK);
++        init_pair(7, COLOR_CYAN, COLOR_BLACK);
++        init_pair(8, COLOR_WHITE, COLOR_BLACK);
++#endif
++        if (can_change_color())
++        {
++            init_color(COLOR_YELLOW, 500, 300, 0);
++            init_color(COLOR_WHITE, 600, 600, 600);
++        }
++    }
++#endif
++}
++
++
++/* Allow player to pick character's role, race, gender, and alignment.
++Borrowed from the Gnome window port. */
++
++void curses_choose_character()
++{
++    int n, i, sel;
++    const char** choices;
++    int* pickmap;
++
++    /* prevent an unnecessary prompt */
++    rigid_role_checks();
++
++    if (!flags.randomall && flags.initrole < 0) {
++
++	/* select a role */
++	for (n = 0; roles[n].name.m; n++) continue;
++	choices = (const char **)alloc(sizeof(char *) * (n+1));
++	pickmap = (int*)alloc(sizeof(int) * (n+1));
++	for (;;) {
++	    for (n = 0, i = 0; roles[i].name.m; i++) {
++		if (ok_role(i, flags.initrace,
++			    flags.initgend, flags.initalign)) {
++		    if (flags.initgend >= 0 && flags.female && roles[i].name.f)
++			choices[n] = roles[i].name.f;
++		    else
++			choices[n] = roles[i].name.m;
++		    pickmap[n++] = i;
++		}
++	    }
++	    if (n > 0) break;
++	    else if (flags.initalign >= 0) flags.initalign = -1;    /* reset */
++	    else if (flags.initgend >= 0) flags.initgend = -1;
++	    else if (flags.initrace >= 0) flags.initrace = -1;
++	    else panic("no available ROLE+race+gender+alignment combinations");
++	}
++	choices[n] = (const char *) 0;
++	if (n > 1)
++        sel = curses_character_dialog(choices, "Choose one of the following roles:");
++	else sel = 0;
++	if (sel >= 0) sel = pickmap[sel];
++	else if (sel == ROLE_NONE) {		/* Quit */
++	    clearlocks();
++	    curses_bail(0);
++	}
++	free(choices);
++	free(pickmap);
++    } else if (flags.initrole < 0) sel = ROLE_RANDOM;
++    else sel = flags.initrole;
++  
++    if (sel == ROLE_RANDOM) {	/* Random role */
++	sel = pick_role(flags.initrace, flags.initgend,
++			  flags.initalign, PICK_RANDOM);
++	if (sel < 0) sel = randrole();
++    }
++
++    flags.initrole = sel;
++
++    /* Select a race, if necessary */
++    /* force compatibility with role, try for compatibility with
++     * pre-selected gender/alignment */
++    if (flags.initrace < 0 || !validrace(flags.initrole, flags.initrace)) {
++	if (flags.initrace == ROLE_RANDOM || flags.randomall) {
++	    flags.initrace = pick_race(flags.initrole, flags.initgend,
++				       flags.initalign, PICK_RANDOM);
++	    if (flags.initrace < 0) flags.initrace = randrace(flags.initrole);
++	} else {
++	    /* Count the number of valid races */
++	    n = 0;	/* number valid */
++	    for (i = 0; races[i].noun; i++) {
++		if (ok_race(flags.initrole, i, flags.initgend, flags.initalign))
++		    n++;
++	    }
++	    if (n == 0) {
++		for (i = 0; races[i].noun; i++) {
++		    if (validrace(flags.initrole, i)) n++;
++		}
++	    }
++
++	    choices = (const char **)alloc(sizeof(char *) * (n+1));
++	    pickmap = (int*)alloc(sizeof(int) * (n + 1));
++	    for (n = 0, i = 0; races[i].noun; i++) {
++		if (ok_race(flags.initrole, i, flags.initgend,
++			    flags.initalign)) {
++		    choices[n] = races[i].noun;
++		    pickmap[n++] = i;
++		}
++	    }
++	    choices[n] = (const char *) 0;
++	    /* Permit the user to pick, if there is more than one */
++	    if (n > 1)
++		sel = curses_character_dialog(choices, "Choose one of the following races:");
++	    else sel = 0;
++	    if (sel >= 0) sel = pickmap[sel];
++	    else if (sel == ROLE_NONE) { /* Quit */
++		clearlocks();
++		curses_bail(0);
++	    }
++	    flags.initrace = sel;
++	    free(choices);
++	    free(pickmap);
++	}
++	if (flags.initrace == ROLE_RANDOM) {	/* Random role */
++	    sel = pick_race(flags.initrole, flags.initgend,
++			    flags.initalign, PICK_RANDOM);
++	    if (sel < 0) sel = randrace(flags.initrole);
++	    flags.initrace = sel;
++	}
++    }
++
++    /* Select a gender, if necessary */
++    /* force compatibility with role/race, try for compatibility with
++     * pre-selected alignment */
++    if (flags.initgend < 0 ||
++	!validgend(flags.initrole, flags.initrace, flags.initgend)) {
++	if (flags.initgend == ROLE_RANDOM || flags.randomall) {
++	    flags.initgend = pick_gend(flags.initrole, flags.initrace,
++				       flags.initalign, PICK_RANDOM);
++	    if (flags.initgend < 0)
++		flags.initgend = randgend(flags.initrole, flags.initrace);
++	} else {
++	    /* Count the number of valid genders */
++	    n = 0;	/* number valid */
++	    for (i = 0; i < ROLE_GENDERS; i++) {
++		if (ok_gend(flags.initrole, flags.initrace, i, flags.initalign))
++		    n++;
++	    }
++	    if (n == 0) {
++		for (i = 0; i < ROLE_GENDERS; i++) {
++		    if (validgend(flags.initrole, flags.initrace, i)) n++;
++		}
++	    }
++
++	    choices = (const char **)alloc(sizeof(char *) * (n+1));
++	    pickmap = (int*)alloc(sizeof(int) * (n + 1));
++	    for (n = 0, i = 0; i < ROLE_GENDERS; i++) {
++		if (ok_gend(flags.initrole, flags.initrace, i,
++				flags.initalign)) {
++		    choices[n] = genders[i].adj;
++		    pickmap[n++] = i;
++		}
++	    }
++	    choices[n] = (const char *) 0;
++	    /* Permit the user to pick, if there is more than one */
++	    if (n > 1)
++		sel = curses_character_dialog(choices, "Choose one of the following genders:");
++	    else sel = 0;
++	    if (sel >= 0) sel = pickmap[sel];
++	    else if (sel == ROLE_NONE) { /* Quit */
++		clearlocks();
++		curses_bail(0);
++	    }
++	    flags.initgend = sel;
++	    free(choices);
++	    free(pickmap);
++	}
++	if (flags.initgend == ROLE_RANDOM) {	/* Random gender */
++	    sel = pick_gend(flags.initrole, flags.initrace,
++			    flags.initalign, PICK_RANDOM);
++	    if (sel < 0) sel = randgend(flags.initrole, flags.initrace);
++	    flags.initgend = sel;
++	}
++    }
++
++    /* Select an alignment, if necessary */
++    /* force compatibility with role/race/gender */
++    if (flags.initalign < 0 ||
++	!validalign(flags.initrole, flags.initrace, flags.initalign)) {
++	if (flags.initalign == ROLE_RANDOM || flags.randomall) {
++	    flags.initalign = pick_align(flags.initrole, flags.initrace,
++					 flags.initgend, PICK_RANDOM);
++	    if (flags.initalign < 0)
++		flags.initalign = randalign(flags.initrole, flags.initrace);
++	} else {
++	    /* Count the number of valid alignments */
++	    n = 0;	/* number valid */
++	    for (i = 0; i < ROLE_ALIGNS; i++) {
++		if (ok_align(flags.initrole, flags.initrace, flags.initgend, i))
++		    n++;
++	    }
++	    if (n == 0) {
++		for (i = 0; i < ROLE_ALIGNS; i++)
++		    if (validalign(flags.initrole, flags.initrace, i)) n++;
++	    }
++
++	    choices = (const char **)alloc(sizeof(char *) * (n+1));
++	    pickmap = (int*)alloc(sizeof(int) * (n + 1));
++	    for (n = 0, i = 0; i < ROLE_ALIGNS; i++) {
++		if (ok_align(flags.initrole,
++			     flags.initrace, flags.initgend, i)) {
++		    choices[n] = aligns[i].adj;
++		    pickmap[n++] = i;
++		}
++	    }
++	    choices[n] = (const char *) 0;
++	    /* Permit the user to pick, if there is more than one */
++	    if (n > 1)
++		sel = curses_character_dialog(choices, "Choose one of the following alignments:");
++	    else sel = 0;
++	    if (sel >= 0) sel = pickmap[sel];
++	    else if (sel == ROLE_NONE) { /* Quit */
++		clearlocks();
++		curses_bail(0);
++	    }
++	    flags.initalign = sel;
++	    free(choices);
++	    free(pickmap);
++	}
++	if (flags.initalign == ROLE_RANDOM) {
++	    sel = pick_align(flags.initrole, flags.initrace,
++			     flags.initgend, PICK_RANDOM);
++	    if (sel < 0) sel = randalign(flags.initrole, flags.initrace);
++	    flags.initalign = sel;
++	}
++    }
++}
++
++
++/* Prompt user for character race, role, alignment, or gender */
++
++int curses_character_dialog(const char** choices, const char *prompt)
++{
++    int count, count2, ret, curletter;
++    char used_letters[52];
++    anything identifier;
++    menu_item *selected = NULL;
++    winid wid = curses_get_wid(NHW_MENU);
++
++    identifier.a_void = 0;
++    curses_start_menu(wid);
++
++    for (count=0; choices[count]; count++)
++    {
++        curletter=tolower(choices[count][0]);
++        for (count2=0; count2<count; count2++)
++        {
++            if (curletter==used_letters[count2])
++            {
++                curletter=toupper(curletter);
++            }
++        }
++
++        identifier.a_int = (count + 1); /* Must be non-zero */
++        curses_add_menu(wid, NO_GLYPH, &identifier, curletter, 0,
++         A_NONE, choices[count], FALSE);
++        used_letters[count] = curletter;
++    }
++
++    /* Random Selection */
++    identifier.a_int = ROLE_RANDOM;
++    curses_add_menu(wid, NO_GLYPH, &identifier, '*', 0, A_NONE, "Random",
++     FALSE);    
++    
++    /* Quit prompt */
++    identifier.a_int = ROLE_NONE;
++    curses_add_menu(wid, NO_GLYPH, &identifier, 'q', 0, A_NONE, "Quit",
++     FALSE);    
++    curses_end_menu(wid, prompt);
++    ret = curses_select_menu(wid, PICK_ONE, &selected);
++    ret = (selected->item.a_int);
++
++    if (ret > 0)
++    {
++        ret--;
++    }
++    
++    free(selected);
++    return ret;
++}
++
++
++/* Initialize and display options appropriately */
++
++void curses_init_options()
++{
++	set_wc_option_mod_status(WC_ALIGN_MESSAGE|WC_ALIGN_STATUS|WC_COLOR|
++	 WC_HILITE_PET|WC_POPUP_DIALOG, SET_IN_GAME);
++	set_wc2_option_mod_status(WC2_TERM_COLS|WC2_TERM_ROWS|
++	 WC2_WINDOWBORDERS, SET_IN_GAME);
++	set_option_mod_status("DECgraphics", SET_IN_FILE);
++	set_option_mod_status("perm_invent", SET_IN_FILE);
++	set_option_mod_status("eight_bit_tty", SET_IN_FILE);
++#ifdef PDCURSES
++    /* PDCurses for SDL, win32 and OS/2 has the ability to set the
++     terminal size programatically.  If the user does not specify a
++     size in the config file, we will set it to a nice big 110x32 to
++     take advantage of some of the nice features of this windowport. */
++    if (iflags.wc2_term_cols == 0)
++    {
++        iflags.wc2_term_cols = 110;
++    }
++    
++    if (iflags.wc2_term_rows == 0)
++    {
++        iflags.wc2_term_rows = 32;
++    }
++    
++    resize_term(iflags.wc2_term_rows, iflags.wc2_term_cols);
++    getmaxyx(base_term, term_rows, term_cols);
++#endif
++    if (!iflags.wc2_windowborders)
++    {
++        iflags.wc2_windowborders = 3; /* Set to auto if not specified */
++    }
++}
++
+diff -burN nethack-3.4.3/win/curses/cursinit.h nethack/win/curses/cursinit.h
+--- nethack-3.4.3/win/curses/cursinit.h	1969-12-31 19:00:00.000000000 -0500
++++ nethack/win/curses/cursinit.h	2009-03-05 13:50:38.000000000 -0500
+@@ -0,0 +1,17 @@
++#ifndef CURSINIT_H
++#define CURSINIT_H
++
++/* Global declarations */
++
++void curses_create_main_windows(void);
++
++void curses_init_nhcolors(void);
++
++void curses_choose_character(void);
++
++int curses_character_dialog(const char** choices, const char *prompt);
++
++void curses_init_options(void);
++
++
++#endif  /* CURSINIT_H */
+diff -burN nethack-3.4.3/win/curses/cursmain.c nethack/win/curses/cursmain.c
+--- nethack-3.4.3/win/curses/cursmain.c	1969-12-31 19:00:00.000000000 -0500
++++ nethack/win/curses/cursmain.c	2009-03-11 15:08:53.000000000 -0400
+@@ -0,0 +1,650 @@
++#include "curses.h"
++#include "hack.h"
++#include "wincurs.h"
++
++/* Public functions for curses NetHack interface */
++
++/* Interface definition, for windows.c */
++struct window_procs curses_procs = {
++    "curses",
++    WC_ALIGN_MESSAGE|WC_ALIGN_STATUS|WC_COLOR|WC_HILITE_PET|
++    WC_POPUP_DIALOG,
++    WC2_TERM_COLS|WC2_TERM_ROWS|WC2_WINDOWBORDERS,
++    curses_init_nhwindows,
++    curses_player_selection,
++    curses_askname,
++    curses_get_nh_event,
++    curses_exit_nhwindows,
++    curses_suspend_nhwindows,
++    curses_resume_nhwindows,
++    curses_create_nhwindow,
++    curses_clear_nhwindow,
++    curses_display_nhwindow,
++    curses_destroy_nhwindow,
++    curses_curs,
++    curses_putstr,
++    curses_display_file,
++    curses_start_menu,
++    curses_add_menu,
++    curses_end_menu,
++    curses_select_menu,
++    genl_message_menu,
++    curses_update_inventory,
++    curses_mark_synch,
++    curses_wait_synch,
++#ifdef CLIPPING
++    curses_cliparound,
++#endif
++#ifdef POSITIONBAR
++    donull,
++#endif
++    curses_print_glyph,
++    curses_raw_print,
++    curses_raw_print_bold,
++    curses_nhgetch,
++    curses_nh_poskey,
++    curses_nhbell,
++    curses_doprev_message,
++    curses_yn_function,
++    curses_getlin,
++    curses_get_ext_cmd,
++    curses_number_pad,
++    curses_delay_output,
++#ifdef CHANGE_COLOR	/* only a Mac option currently */
++    donull,
++    donull,
++#endif
++    curses_start_screen,
++    curses_end_screen,
++    genl_outrip,
++    curses_preference_update,
++};
++
++/*  
++init_nhwindows(int* argcp, char** argv)
++                -- Initialize the windows used by NetHack.  This can also
++                   create the standard windows listed at the top, but does
++                   not display them.
++                -- Any commandline arguments relevant to the windowport
++                   should be interpreted, and *argcp and *argv should
++                   be changed to remove those arguments.
++                -- When the message window is created, the variable
++                   iflags.window_inited needs to be set to TRUE.  Otherwise
++                   all plines() will be done via raw_print().
++                ** Why not have init_nhwindows() create all of the "standard"
++                ** windows?  Or at least all but WIN_INFO?      -dean
++*/
++void curses_init_nhwindows(int* argcp, char** argv)
++{
++#ifdef XCURSES
++    base_term = Xinitscr(*argcp, argv);
++#else
++    base_term = initscr();
++#endif
++#ifdef TEXTCOLOR
++    if (has_colors())
++        start_color();
++    else
++        iflags.use_color = FALSE;
++    curses_init_nhcolors();
++#else
++    iflags.use_color = FALSE;
++#endif
++    noecho();
++    raw();
++    keypad(stdscr, TRUE);
++    meta(stdscr, TRUE);
++    curs_set(0);
++    getmaxyx(base_term, term_rows, term_cols);
++    curses_init_options();
++    if ((term_rows < 18) || (term_cols < 40))
++    {
++        panic("Terminal too small.  Must be minumum 40 width and 18 height");
++    }
++
++    curses_create_main_windows();
++    curses_init_mesg_history();
++}
++
++
++/* Do a window-port specific player type selection. If player_selection()
++   offers a Quit option, it is its responsibility to clean up and terminate
++   the process. You need to fill in pl_character[0].
++*/
++void curses_player_selection()
++{
++    curses_choose_character();
++}
++
++
++/* Ask the user for a player name. */
++void curses_askname()
++{
++    curses_line_input_dialog("Who are you?", plname, PL_NSIZ);
++}
++
++
++/* Does window event processing (e.g. exposure events).
++   A noop for the tty and X window-ports.
++*/
++void curses_get_nh_event()
++{
++#ifdef PDCURSES
++    if (is_termresized())
++    {
++        resize_term(0, 0);
++        getmaxyx(base_term, term_rows, term_cols);
++        curses_create_main_windows();
++        curses_last_messages();
++        doredraw();
++    }
++#endif
++#ifdef NCURSES_VERSION  /* Is there a better way to detect ncurses? */
++    if (is_term_resized(term_rows, term_cols))
++    {
++        if (!isendwin())
++        {
++            endwin();
++        }
++        
++        refresh();
++        getmaxyx(base_term, term_rows, term_cols);
++        curses_create_main_windows();
++        curses_last_messages();
++        doredraw();
++    }
++#endif
++}
++
++/* Exits the window system.  This should dismiss all windows,
++   except the "window" used for raw_print().  str is printed if possible.
++*/
++void curses_exit_nhwindows(const char *str)
++{
++    endwin();
++    iflags.window_inited = 0;
++    if (str != NULL)
++    {
++        raw_print(str);
++    }
++}
++
++/* Prepare the window to be suspended. */
++void curses_suspend_nhwindows(const char *str)
++{
++}
++
++
++/* Restore the windows after being suspended. */
++void curses_resume_nhwindows()
++{
++    curses_refresh_nethack_windows();
++}
++
++/*  Create a window of type "type" which can be 
++        NHW_MESSAGE     (top line)
++        NHW_STATUS      (bottom lines)
++        NHW_MAP         (main dungeon)
++        NHW_MENU        (inventory or other "corner" windows)
++        NHW_TEXT        (help/text, full screen paged window)
++*/
++winid curses_create_nhwindow(int type)
++{
++    winid wid = curses_get_wid(type);
++
++    if (curses_is_menu(wid) || curses_is_text(wid))
++    {
++        curses_start_menu(wid);
++        /* Add to window list just to keep track of the wid */
++        curses_add_nhwin(wid, 0, 0, 0, 0, 0, TRUE);
++    }
++    
++    return wid;
++}
++
++
++/* Clear the given window, when asked to. */
++void curses_clear_nhwindow(winid wid)
++{
++    if (wid != NHW_MESSAGE)
++    {
++        curses_clear_nhwin(wid);
++    }
++}
++
++/* -- Display the window on the screen.  If there is data
++                   pending for output in that window, it should be sent.
++                   If blocking is TRUE, display_nhwindow() will not
++                   return until the data has been displayed on the screen,
++                   and acknowledged by the user where appropriate.
++                -- All calls are blocking in the tty window-port.
++                -- Calling display_nhwindow(WIN_MESSAGE,???) will do a
++                   --more--, if necessary, in the tty window-port.
++*/
++void curses_display_nhwindow(winid wid, BOOLEAN_P block)
++{
++    menu_item *selected = NULL;
++    WINDOW *win = curses_get_nhwin(wid);
++    
++    if ((win != NULL) && (wid == MAP_WIN) && block)
++    {
++        curses_more();
++    }
++    else if (curses_is_menu(wid) || curses_is_text(wid))
++    {
++        curses_end_menu(wid, "");
++        curses_select_menu(wid, PICK_NONE, &selected);
++    }
++}
++
++
++/* Destroy will dismiss the window if the window has not 
++ * already been dismissed.
++*/
++void curses_destroy_nhwindow(winid wid)
++{
++    curses_del_nhwin(wid);
++}
++
++/* Next output to window will start at (x,y), also moves
++ displayable cursor to (x,y).  For backward compatibility,
++ 1 <= x < cols, 0 <= y < rows, where cols and rows are
++ the size of window.
++*/
++void curses_curs(winid wid, int x, int y)
++{
++    curses_move_cursor(wid, x, y);
++}
++
++/*
++putstr(window, attr, str)
++                -- Print str on the window with the given attribute.  Only
++                   printable ASCII characters (040-0126) must be supported.
++                   Multiple putstr()s are output on separate lines.
++Attributes
++                   can be one of
++                        ATR_NONE (or 0)
++                        ATR_ULINE
++                        ATR_BOLD
++                        ATR_BLINK
++                        ATR_INVERSE
++                   If a window-port does not support all of these, it may map
++                   unsupported attributes to a supported one (e.g. map them
++                   all to ATR_INVERSE).  putstr() may compress spaces out of
++                   str, break str, or truncate str, if necessary for the
++                   display.  Where putstr() breaks a line, it has to clear
++                   to end-of-line.
++                -- putstr should be implemented such that if two putstr()s
++                   are done consecutively the user will see the first and
++                   then the second.  In the tty port, pline() achieves this
++                   by calling more() or displaying both on the same line.
++*/
++void curses_putstr(winid wid, int attr, const char *text)
++{
++    curses_puts(wid, attr, text);
++}
++
++/* Display the file named str.  Complain about missing files
++                   iff complain is TRUE.
++*/
++void curses_display_file(const char *filename,BOOLEAN_P must_exist)
++{
++    curses_view_file(filename, must_exist);
++}
++
++/* Start using window as a menu.  You must call start_menu()
++   before add_menu().  After calling start_menu() you may not
++   putstr() to the window.  Only windows of type NHW_MENU may
++   be used for menus.
++*/
++void curses_start_menu(winid wid)
++{
++    curses_create_nhmenu(wid);
++}
++
++/*
++add_menu(winid wid, int glyph, const anything identifier,
++                                char accelerator, char groupacc,
++                                int attr, char *str, boolean preselected)
++                -- Add a text line str to the given menu window.  If identifier
++                   is 0, then the line cannot be selected (e.g. a title).
++                   Otherwise, identifier is the value returned if the line is
++                   selected.  Accelerator is a keyboard key that can be used
++                   to select the line.  If the accelerator of a selectable
++                   item is 0, the window system is free to select its own
++                   accelerator.  It is up to the window-port to make the
++                   accelerator visible to the user (e.g. put "a - " in front
++                   of str).  The value attr is the same as in putstr().
++                   Glyph is an optional glyph to accompany the line.  If
++                   window port cannot or does not want to display it, this
++                   is OK.  If there is no glyph applicable, then this
++                   value will be NO_GLYPH.
++                -- All accelerators should be in the range [A-Za-z].
++                -- It is expected that callers do not mix accelerator
++                   choices.  Either all selectable items have an accelerator
++                   or let the window system pick them.  Don't do both.
++                -- Groupacc is a group accelerator.  It may be any character
++                   outside of the standard accelerator (see above) or a
++                   number.  If 0, the item is unaffected by any group
++                   accelerator.  If this accelerator conflicts with
++                   the menu command (or their user defined alises), it loses.
++                   The menu commands and aliases take care not to interfere
++                   with the default object class symbols.
++                -- If you want this choice to be preselected when the
++                   menu is displayed, set preselected to TRUE.
++*/
++void curses_add_menu(winid wid, int glyph, const ANY_P * identifier,
++		CHAR_P accelerator, CHAR_P group_accel, int attr, 
++		const char *str, BOOLEAN_P presel)
++{
++    curses_add_nhmenu_item(wid, identifier, accelerator, group_accel, attr,
++     str, presel);
++}
++
++/*
++end_menu(window, prompt)
++                -- Stop adding entries to the menu and flushes the window
++                   to the screen (brings to front?).  Prompt is a prompt
++                   to give the user.  If prompt is NULL, no prompt will
++                   be printed.
++                ** This probably shouldn't flush the window any more (if
++                ** it ever did).  That should be select_menu's job.  -dean
++*/
++void curses_end_menu(winid wid, const char *prompt)
++{
++    curses_finalize_nhmenu(wid, prompt);
++}
++
++/*
++int select_menu(winid window, int how, menu_item **selected)
++                -- Return the number of items selected; 0 if none were chosen,
++                   -1 when explicitly cancelled.  If items were selected, then
++                   selected is filled in with an allocated array of menu_item
++                   structures, one for each selected line.  The caller must
++                   free this array when done with it.  The "count" field
++                   of selected is a user supplied count.  If the user did
++                   not supply a count, then the count field is filled with
++                   -1 (meaning all).  A count of zero is equivalent to not
++                   being selected and should not be in the list.  If no items
++                   were selected, then selected is NULL'ed out.  How is the
++                   mode of the menu.  Three valid values are PICK_NONE,
++                   PICK_ONE, and PICK_N, meaning: nothing is selectable,
++                   only one thing is selectable, and any number valid items
++                   may selected.  If how is PICK_NONE, this function should
++                   never return anything but 0 or -1.
++                -- You may call select_menu() on a window multiple times --
++                   the menu is saved until start_menu() or destroy_nhwindow()
++                   is called on the window.
++                -- Note that NHW_MENU windows need not have select_menu()
++                   called for them. There is no way of knowing whether
++                   select_menu() will be called for the window at
++                   create_nhwindow() time.
++*/
++int curses_select_menu(winid wid, int how, MENU_ITEM_P **selected)
++{
++    return curses_display_nhmenu(wid, how, selected);
++}
++
++/*
++    -- Indicate to the window port that the inventory has been changed.
++    -- Merely calls display_inventory() for window-ports that leave the 
++	window up, otherwise empty.
++*/
++void curses_update_inventory()
++{
++}
++
++/*
++mark_synch()    -- Don't go beyond this point in I/O on any channel until
++                   all channels are caught up to here.  Can be an empty call
++                   for the moment
++*/
++void curses_mark_synch()
++{
++}
++
++/*
++wait_synch()    -- Wait until all pending output is complete (*flush*() for
++                   streams goes here).
++                -- May also deal with exposure events etc. so that the
++                   display is OK when return from wait_synch().
++*/
++void curses_wait_synch()
++{
++}
++
++/*
++cliparound(x, y)-- Make sure that the user is more-or-less centered on the
++                   screen if the playing area is larger than the screen.
++                -- This function is only defined if CLIPPING is defined.
++*/
++void curses_cliparound(int x, int y)
++{
++}
++
++/*
++print_glyph(window, x, y, glyph)
++                -- Print the glyph at (x,y) on the given window.  Glyphs are
++                   integers at the interface, mapped to whatever the window-
++                   port wants (symbol, font, color, attributes, ...there's
++                   a 1-1 map between glyphs and distinct things on the map).
++*/
++void curses_print_glyph(winid wid, XCHAR_P x, XCHAR_P y, int glyph)
++{
++    int ch, color, special;
++    int attr = -1;
++
++    /* map glyph to character and color */
++    mapglyph(glyph, &ch, &color, &special, x, y);
++    if ((special & MG_PET) && iflags.hilite_pet)
++    {
++        attr = ATR_ULINE;
++    }
++    if ((special & MG_DETECT) && iflags.use_inverse)
++	{
++	    attr = ATR_INVERSE;
++	}
++	if (iflags.cursesgraphics)
++	{
++	    ch = curses_convert_glyph(ch, glyph);
++	}
++    curses_putch(wid, x, y, ch, color, attr);
++}
++
++/*
++raw_print(str)  -- Print directly to a screen, or otherwise guarantee that
++                   the user sees str.  raw_print() appends a newline to str.
++                   It need not recognize ASCII control characters.  This is
++                   used during startup (before windowing system initialization
++                   -- maybe this means only error startup messages are raw),
++                   for error messages, and maybe other "msg" uses.  E.g.
++                   updating status for micros (i.e, "saving").
++*/
++void curses_raw_print(const char *str)
++{
++    puts(str);
++}
++
++/*
++raw_print_bold(str)
++            -- Like raw_print(), but prints in bold/standout (if possible).
++*/
++void curses_raw_print_bold(const char *str)
++{
++    curses_raw_print(str);
++}
++
++/*
++int nhgetch()   -- Returns a single character input from the user.
++                -- In the tty window-port, nhgetch() assumes that tgetch()
++                   will be the routine the OS provides to read a character.
++                   Returned character _must_ be non-zero.
++*/
++int curses_nhgetch()
++{    
++    int ch;
++    
++    curses_prehousekeeping();
++    ch = curses_read_char();
++    curses_posthousekeeping();
++    
++    return ch;
++}
++
++/*
++int nh_poskey(int *x, int *y, int *mod)
++                -- Returns a single character input from the user or a
++                   a positioning event (perhaps from a mouse).  If the
++                   return value is non-zero, a character was typed, else,
++                   a position in the MAP window is returned in x, y and mod.
++                   mod may be one of
++
++                        CLICK_1         -- mouse click type 1 
++                        CLICK_2         -- mouse click type 2 
++
++                   The different click types can map to whatever the
++                   hardware supports.  If no mouse is supported, this
++                   routine always returns a non-zero character.
++*/
++int curses_nh_poskey(int *x, int *y, int *mod)
++{
++    return curses_nhgetch();
++}
++
++/*
++nhbell()        -- Beep at user.  [This will exist at least until sounds are
++                   redone, since sounds aren't attributable to windows anyway.]
++*/
++void curses_nhbell()
++{
++    beep();
++}
++
++/*
++doprev_message()
++                -- Display previous messages.  Used by the ^P command.
++                -- On the tty-port this scrolls WIN_MESSAGE back one line.
++*/
++int curses_doprev_message()
++{
++    curses_prev_mesg();
++}
++
++/*
++char yn_function(const char *ques, const char *choices, char default)
++                -- Print a prompt made up of ques, choices and default.
++                   Read a single character response that is contained in
++                   choices or default.  If choices is NULL, all possible
++                   inputs are accepted and returned.  This overrides
++                   everything else.  The choices are expected to be in
++                   lower case.  Entering ESC always maps to 'q', or 'n',
++                   in that order, if present in choices, otherwise it maps
++                   to default.  Entering any other quit character (SPACE,
++                   RETURN, NEWLINE) maps to default.
++                -- If the choices string contains ESC, then anything after
++                   it is an acceptable response, but the ESC and whatever
++                   follows is not included in the prompt.
++                -- If the choices string contains a '#' then accept a count.
++                   Place this value in the global "yn_number" and return '#'.
++                -- This uses the top line in the tty window-port, other
++                   ports might use a popup.
++*/
++char curses_yn_function(const char *question, const char *choices, CHAR_P def)
++{
++    curses_character_input_dialog(question, choices, def);
++}
++
++/*
++getlin(const char *ques, char *input)
++	    -- Prints ques as a prompt and reads a single line of text,
++	       up to a newline.  The string entered is returned without the
++	       newline.  ESC is used to cancel, in which case the string
++	       "\033\000" is returned.
++	    -- getlin() must call flush_screen(1) before doing anything.
++	    -- This uses the top line in the tty window-port, other
++	       ports might use a popup.
++*/
++void curses_getlin(const char *question, char *input)
++{
++    curses_line_input_dialog(question, input, BUFSZ);
++}
++
++/*
++int get_ext_cmd(void)
++	    -- Get an extended command in a window-port specific way.
++	       An index into extcmdlist[] is returned on a successful
++	       selection, -1 otherwise.
++*/
++int curses_get_ext_cmd()
++{
++    return curses_ext_cmd();
++}
++
++
++/*
++number_pad(state)
++	    -- Initialize the number pad to the given state.
++*/
++void curses_number_pad(int state)
++{
++}
++
++/*
++delay_output()  -- Causes a visible delay of 50ms in the output.
++	       Conceptually, this is similar to wait_synch() followed
++	       by a nap(50ms), but allows asynchronous operation.
++*/
++void curses_delay_output()
++{
++//    curses_refresh_nethack_windows();
++//    usleep(5000);
++}
++
++/*
++start_screen()  -- Only used on Unix tty ports, but must be declared for
++	       completeness.  Sets up the tty to work in full-screen
++	       graphics mode.  Look at win/tty/termcap.c for an
++	       example.  If your window-port does not need this function
++	       just declare an empty function.
++*/
++void curses_start_screen()
++{
++}
++
++/*
++end_screen()    -- Only used on Unix tty ports, but must be declared for
++	       completeness.  The complement of start_screen().
++*/
++void curses_end_screen()
++{
++}
++
++/*
++outrip(winid, int)
++	    -- The tombstone code.  If you want the traditional code use
++	       genl_outrip for the value and check the #if in rip.c.
++*/
++void curses_outrip(winid wid, int how)
++{
++}
++
++/*
++preference_update(preference)
++		-- The player has just changed one of the wincap preference
++		   settings, and the NetHack core is notifying your window
++		   port of that change.  If your window-port is capable of
++		   dynamically adjusting to the change then it should do so.
++		   Your window-port will only be notified of a particular
++		   change if it indicated that it wants to be by setting the 
++		   corresponding bit in the wincap mask.
++*/
++void curses_preference_update(const char *pref)
++{
++    if ((strcmp(pref, "align_status") == 0) ||
++     (strcmp(pref, "align_message") == 0))
++    {
++        curses_create_main_windows();
++        curses_last_messages();
++        doredraw();
++    }
++}
+diff -burN nethack-3.4.3/win/curses/cursmesg.c nethack/win/curses/cursmesg.c
+--- nethack-3.4.3/win/curses/cursmesg.c	1969-12-31 19:00:00.000000000 -0500
++++ nethack/win/curses/cursmesg.c	2009-03-11 15:08:53.000000000 -0400
+@@ -0,0 +1,365 @@
++#include "curses.h"
++#include "hack.h"
++#include "wincurs.h"
++#include "cursmesg.h"
++
++/* Message window routines for curses interface */
++
++static int turn_lines = 1;
++static int mx = 0;
++static int my = 0;  /* message window text location */
++static nhprev_mesg *first_mesg = NULL;
++static nhprev_mesg *last_mesg = NULL;
++static int max_messages;
++static int num_messages = 0;
++
++
++
++/* Write a string to the message window.  Attributes set by calling function. */
++
++void curses_message_win_puts(const char *message, boolean recursed)
++{
++    int height, width, linespace, count;
++    char *tmpstr;
++    WINDOW *win = curses_get_nhwin(MESSAGE_WIN);
++    boolean border = curses_window_has_border(MESSAGE_WIN);
++    int message_length = strlen(message);
++    int border_space = 0;
++    
++    if (!recursed)
++    {
++        strcpy(toplines, message);
++        mesg_add_line((char *) message);
++    }
++    
++    curses_get_window_size(MESSAGE_WIN, &height, &width);
++    if (border)
++    {
++        border_space = 1;
++        if (mx < 1)
++        {
++            mx = 1;
++        }
++        if (my < 1)
++        {
++            my = 1;
++        }
++    }
++    
++    linespace = ((width + border_space) - 3) - mx;
++    
++    if (linespace < message_length)
++    {
++        if (my >= (height - 1 + border_space)) /* bottom of message win */
++        {
++            if (turn_lines == height)
++            {
++                curses_more();
++            }
++            else
++            {
++                scroll_window(MESSAGE_WIN);
++                turn_lines++;
++            }
++        }
++        else
++        {
++            if (mx != border_space)
++            {
++                my++;
++                mx = border_space;
++            }
++        }
++    }
++
++    if (height > 1)
++    {
++        curses_toggle_color_attr(win, NONE, ATR_BOLD, ON);
++    }
++    
++    if ((mx == border_space) && ((message_length + 2) > width))
++    {
++        tmpstr = curses_break_str(message, (width - 2), 1);
++        mvwprintw(win, my, mx, tmpstr);
++        mx += strlen(tmpstr);
++        free(tmpstr);
++        if (height > 1)
++        {
++            curses_toggle_color_attr(win, NONE, ATR_BOLD, OFF);
++        }
++        wrefresh(win);
++        curses_message_win_puts(curses_str_remainder(message, (width - 2), 1),
++         TRUE);
++    }
++    else
++    {
++        mvwprintw(win, my, mx, message);
++        curses_toggle_color_attr(win, NONE, ATR_BOLD, OFF);
++    }
++    wrefresh(win);
++    mx += message_length + 1;
++}
++
++
++void curses_more()
++{
++    int height, width;
++    WINDOW *win = curses_get_nhwin(MESSAGE_WIN);
++    
++    curses_get_window_size(MESSAGE_WIN, &height, &width);
++    curses_toggle_color_attr(win, MORECOLOR, NONE, ON);
++    mvwprintw(win, my, mx - 1, ">>");
++    curses_toggle_color_attr(win, MORECOLOR, NONE, OFF);
++    wrefresh(win);
++    wgetch(win);
++    if (height == 1)
++    {
++        curses_clear_unhighlight_message_window();
++    }
++    else
++    {
++        mvwprintw(win, my, mx - 1, "  ");
++        scroll_window(MESSAGE_WIN);
++        turn_lines = 1;
++    }
++}
++
++
++/* Clear the message window if one line; otherwise unhighlight old messages */
++
++void curses_clear_unhighlight_message_window()
++{
++    int mh, mw, count;
++    boolean border = curses_window_has_border(MESSAGE_WIN);
++    WINDOW *win = curses_get_nhwin(MESSAGE_WIN);
++
++    turn_lines = 1;
++    
++    curses_get_window_size(MESSAGE_WIN, &mh, &mw); 
++    
++    mx = 0;
++    
++    if (border)
++    {
++        mx++;
++    }
++       
++    if (mh == 1)
++    {
++        curses_clear_nhwin(MESSAGE_WIN);
++    }
++    else
++    {
++        mx += mw;    /* Force new line on new turn */
++        
++        if (border)
++        {
++
++            for (count = 0; count < mh; count++)
++            {
++                mvwchgat(win, count+1, 1, mw, COLOR_PAIR(8), A_NORMAL, NULL);
++            }
++        }
++        else
++        {
++            for (count = 0; count < mh; count++)
++            {
++                mvwchgat(win, count, 0, mw, COLOR_PAIR(8), A_NORMAL, NULL);
++            }
++        }
++
++        wrefresh(win);
++    }
++}
++
++
++/* Reset message window cursor to starting position, and display most
++recent messages. */
++
++void curses_last_messages()
++{
++    boolean border = curses_window_has_border(MESSAGE_WIN);
++
++    if (border)
++    {
++        mx = 1;
++        my = 1;
++    }
++    else
++    {
++        mx = 0;
++        my = 0;
++    }
++    
++    pline(toplines);
++}
++
++
++/* Initialize list for message history */
++
++void curses_init_mesg_history()
++{
++    max_messages = iflags.msg_history;
++    
++    if (max_messages < 1)
++    {
++        max_messages = 1;
++    }
++
++    if (max_messages > MESG_HISTORY_MAX)
++    {
++        max_messages = MESG_HISTORY_MAX;
++    }
++}
++
++
++/* Display previous message window messages in reverse chron order */
++
++void curses_prev_mesg()
++{
++    int count;
++    winid wid;
++    long turn = 0;
++    anything *identifier;
++    nhprev_mesg *mesg;
++    menu_item *selected = NULL;
++
++    wid = curses_get_wid(NHW_MENU);
++    curses_create_nhmenu(wid);
++    identifier = malloc(sizeof(anything));
++    identifier->a_void = NULL;
++    
++    for (count = 0; count < num_messages; count++)
++    {
++        mesg = get_msg_line(TRUE, count);
++        if ((turn != mesg->turn) && (count != 0))
++        {
++            curses_add_menu(wid, NO_GLYPH, identifier, 0, 0, A_NONE,
++             "---", FALSE);
++        }
++        curses_add_menu(wid, NO_GLYPH, identifier, 0, 0, A_NONE,
++         mesg->str, FALSE);
++        turn = mesg->turn;
++    }
++    
++    curses_end_menu(wid, "");
++    curses_select_menu(wid, PICK_NONE, &selected);
++}
++
++
++/* Scroll lines upward in given window, or clear window if only one line. */
++
++static void scroll_window(winid wid)
++{
++    int wh, ww, s_top, s_bottom;
++    boolean border = curses_window_has_border(wid);
++    WINDOW *win = curses_get_nhwin(wid);
++    
++    curses_get_window_size(wid, &wh, &ww);
++    if (wh == 1)
++    {
++        curses_clear_nhwin(wid);
++        return;
++    }
++    if (border)
++    {
++        s_top = 1;
++        s_bottom = wh;
++    }
++    else
++    {
++        s_top = 0;
++        s_bottom = wh - 1;
++    }
++    scrollok(win, TRUE);
++    wsetscrreg(win, s_top, s_bottom);
++    scroll(win);
++    scrollok(win, FALSE);
++    if (wid == MESSAGE_WIN)
++    {
++        if (border)
++            mx = 1;
++        else
++            mx = 0;
++    }
++    if (border)
++    {
++        box(win, 0, 0);
++    }
++    wrefresh(win);
++}
++
++
++/* Add given line to message history */
++
++static void mesg_add_line(char *mline)
++{
++    nhprev_mesg *tmp_mesg = NULL;
++    nhprev_mesg *current_mesg = malloc(sizeof(nhprev_mesg));
++
++    current_mesg->str = curses_copy_of(mline);
++    current_mesg->turn = moves;
++    current_mesg->next_mesg = NULL;
++
++    if (num_messages == 0)
++    {
++        first_mesg = current_mesg;
++    }
++    
++    if (last_mesg != NULL)
++    {
++        last_mesg->next_mesg = current_mesg;
++    }
++    current_mesg->prev_mesg = last_mesg;
++    last_mesg = current_mesg;
++
++
++    if (num_messages < max_messages)
++    {
++        num_messages++;
++    }
++    else
++    {
++        tmp_mesg = first_mesg->next_mesg;
++        free(first_mesg);
++        first_mesg = tmp_mesg;
++    }
++}
++
++
++/* Returns specified line from message history, or NULL if out of bounds */
++
++static nhprev_mesg *get_msg_line(boolean reverse, int mindex)
++{
++    int count;
++    char *line;
++    nhprev_mesg *current_mesg;
++
++    if (reverse)
++    {
++        current_mesg = last_mesg;
++        for (count = 0; count < mindex; count++)
++        {
++            if (current_mesg == NULL)
++            {
++                return NULL;
++            }
++            current_mesg = current_mesg->prev_mesg;
++        }
++        return current_mesg;
++    }
++    else
++    {
++        current_mesg = first_mesg;
++        for (count = 0; count < mindex; count++)
++        {
++            if (current_mesg == NULL)
++            {
++                return NULL;
++            }
++            current_mesg = current_mesg->next_mesg;
++        }
++        return current_mesg;
++    }
++}
++
+diff -burN nethack-3.4.3/win/curses/cursmesg.h nethack/win/curses/cursmesg.h
+--- nethack-3.4.3/win/curses/cursmesg.h	1969-12-31 19:00:00.000000000 -0500
++++ nethack/win/curses/cursmesg.h	2009-03-05 13:50:38.000000000 -0500
+@@ -0,0 +1,37 @@
++#ifndef CURSMESG_H
++#define CURSMESG_H
++
++
++/* Global declarations */
++
++void curses_message_win_puts(const char *message, boolean recursed);
++
++void curses_more(void);
++
++void curses_clear_unhighlight_message_window(void);
++
++void curses_last_messages(void);
++
++void curses_init_mesg_history(void);
++
++void curses_prev_mesg(void);
++
++
++/* Private declatations */
++
++typedef struct nhpm
++{
++    char *str;  /* Message text */
++    long turn;  /* Turn number for message */
++    struct nhpm *prev_mesg;    /* Pointer to previous message */
++    struct nhpm *next_mesg;    /* Pointer to next message */
++} nhprev_mesg;
++
++static void scroll_window(winid wid);
++
++static void mesg_add_line(char *mline);
++
++static nhprev_mesg *get_msg_line(boolean reverse, int mindex);
++
++
++#endif  /* CURSMESG_H */
+diff -burN nethack-3.4.3/win/curses/cursmisc.c nethack/win/curses/cursmisc.c
+--- nethack-3.4.3/win/curses/cursmisc.c	1969-12-31 19:00:00.000000000 -0500
++++ nethack/win/curses/cursmisc.c	2009-03-11 15:08:53.000000000 -0400
+@@ -0,0 +1,647 @@
++#include "curses.h"
++#include "hack.h"
++#include "wincurs.h"
++#include "cursmisc.h"
++#include "func_tab.h"
++#include "dlb.h"
++
++/* Misc. curses interface functions */
++
++static int curs_x = -1;
++static int curs_y = -1;
++static winid curs_win = 0;
++
++
++/* Read a character of input from the user */
++
++int curses_read_char()
++{
++    int ch;
++
++    ch = getch();
++    if (!ch)
++    {
++        ch = '\033'; /* map NUL to ESC since nethack doesn't expect NUL */
++    }
++    
++    if ((ch >= 0x197) && (ch <= 0x1ba)) /* Alt/Meta key handling */
++    {
++        ch = (ch - 0x140) | 0x80;
++    }
++
++#ifdef KEY_RESIZE
++    /* Handle resize events via get_nh_event, not this code */
++    if (ch == KEY_RESIZE)
++    {
++        ch = '\033'; /* NetHack doesn't know what to do with KEY_RESIZE */
++    }
++#endif
++
++    /* Handle arrow keys */
++    
++    switch (ch)
++    {
++        case KEY_LEFT:
++        {
++            if (iflags.num_pad)
++            {
++                ch = '4';
++            }
++            else
++            {
++                ch = 'h';
++            }
++            break;
++        }
++        case KEY_RIGHT:
++        {
++            if (iflags.num_pad)
++            {
++                ch = '6';
++            }
++            else
++            {
++                ch = 'l';
++            }
++            break;
++        }
++        case KEY_UP:
++        {
++            if (iflags.num_pad)
++            {
++                ch = '8';
++            }
++            else
++            {
++                ch = 'k';
++            }
++            break;
++        }
++        case KEY_DOWN:
++        {
++            if (iflags.num_pad)
++            {
++                ch = '2';
++            }
++            else
++            {
++                ch = 'j';
++            }
++            break;
++        }
++    }
++
++    return ch;
++}
++
++/* Turn on or off the specified color and / or attribute */
++
++void curses_toggle_color_attr(WINDOW *win, int color, int attr, int onoff)
++{
++#ifdef TEXTCOLOR
++    int curses_color, curses_attr;
++
++    switch (attr)
++    {
++        case ATR_NONE:
++        {
++            curses_attr = A_NORMAL;
++            break;
++        }
++        case ATR_ULINE:
++        {
++            curses_attr = A_UNDERLINE;
++            break;
++        }
++        case ATR_BOLD:
++        {
++            curses_attr = A_BOLD;
++            break;
++        }
++        case ATR_BLINK:
++        {
++            curses_attr = A_BLINK;
++            break;
++        }
++        case ATR_INVERSE:
++        {
++            curses_attr = A_REVERSE;
++            break;
++        }
++        default:
++        {
++            curses_attr = A_NORMAL;
++        }
++    }
++    if (color == 0) /* make black fg visible */
++#ifdef CURSES_VERSION
++        color = 16;
++#else
++        color = 8;
++#endif
++    curses_color = color + 1;
++    if (curses_color > 8)
++        curses_color -= 8;
++    if (onoff == ON)    /* Turn on color/attributes */
++    {
++        if ((attr != NONE) && iflags.use_color)
++            wattron(win, curses_attr);
++        if ((color != NONE) && iflags.use_color)
++        {
++            if ((color > 7) && iflags.use_color)  /* high-intensity color */
++                wattron(win, A_BOLD);
++            if (iflags.use_color)
++                wattron(win, COLOR_PAIR(curses_color));
++        }
++    }
++    else                /* Turn off color/attributes */
++    {
++        if ((attr != NONE) && iflags.use_color)
++            wattroff(win, curses_attr);
++        if ((color != NONE) && iflags.use_color)
++        {
++            if ((color > 7) && iflags.use_color)  /* high-intensity color */
++                wattroff(win, A_BOLD);
++            if (iflags.use_color)
++                wattroff(win, COLOR_PAIR(curses_color));
++        }
++    }
++#endif
++}
++
++
++/* clean up and quit - taken from tty port */
++
++void curses_bail(const char *mesg)
++{
++    clearlocks();
++    curses_exit_nhwindows(mesg);
++    terminate(EXIT_SUCCESS);
++}
++
++
++/* Return a winid for a new window of the given type */
++
++winid curses_get_wid(int type)
++{
++	winid ret;
++    static winid menu_wid = 20; /* Always even */
++    static winid text_wid = 21; /* Always odd */
++
++	switch (type)
++	{
++		case NHW_MESSAGE:
++		{
++			return MESSAGE_WIN;
++			break;
++		}
++		case NHW_MAP:
++		{
++			return MAP_WIN;
++			break;
++		}
++		case NHW_STATUS:
++		{
++			return STATUS_WIN;
++			break;
++		}
++		case NHW_MENU:
++		{
++			ret = menu_wid;
++			break;
++		}
++		case NHW_TEXT:
++		{
++			ret = text_wid;
++			break;
++		}
++		default:
++		{
++			panic("curses_get_wid: unsupported window type");
++		}
++	}
++
++	while (curses_window_exists(ret))
++	{
++	    ret += 2;
++	    if ((ret + 2) > 10000)    /* Avoid "wid2k" problem */
++	    {
++	        ret -= 9900;
++	    }
++	}
++	
++	if (type == NHW_MENU)
++	{
++	    menu_wid += 2;
++	}
++	else
++	{
++	    text_wid += 2;
++	}
++
++	return ret;
++}
++
++
++/*
++ * Allocate a copy of the given string.  If null, return a string of
++ * zero length.
++ *
++ * This is taken from copy_of() in tty/wintty.c.
++ */
++
++char *curses_copy_of(const char *s)
++{
++    if (!s) s = "";
++    return strcpy((char *) alloc((unsigned) (strlen(s) + 1)), s);
++}
++
++
++/* Determine the number of lines needed for a string for a dialog window
++of the given width */
++
++int curses_num_lines(const char *str, int width)
++{
++    int last_space, count;
++    int curline = 1;
++    char substr[BUFSZ];
++    char tmpstr[BUFSZ];
++    
++    strcpy(substr, str);
++    
++    while (strlen(substr) > width)
++    {
++        last_space = 0;
++        
++        for (count = 0; count <= width; count++)
++        {
++            if (substr[count] == ' ')
++            last_space = count;
++        }
++        if (last_space == 0)    /* No spaces found */
++        {
++            last_space = count - 1;
++        }
++        for (count = (last_space + 1); count < strlen(substr); count++)
++        {
++            tmpstr[count - (last_space + 1)] = substr[count];
++        }
++        tmpstr[count - (last_space + 1)] = '\0';
++        strcpy(substr, tmpstr);
++        curline++;
++    }
++    
++    return curline;
++}
++
++
++/* Break string into smaller lines to fit into a dialog window of the
++given width */
++
++char *curses_break_str(const char *str, int width, int line_num)
++{
++    int last_space, count;
++    char *retstr;
++    int curline = 0;
++    int strsize = strlen(str);
++    char substr[strsize];
++    char curstr[strsize];
++    char tmpstr[strsize];
++    
++    strcpy(substr, str);
++    
++    while (curline < line_num)
++    {
++        if (strlen(substr) == 0 )
++        {
++            break;
++        }
++        curline++;
++        last_space = 0;       
++        for (count = 0; count <= width; count++)
++        {
++            if (substr[count] == ' ')
++            {
++                last_space = count;
++            }
++            else if (substr[count] == '\0')           
++            {
++                last_space = count;
++                break;
++            }
++        }
++        if (last_space == 0)    /* No spaces found */
++        {
++            last_space = count - 1;
++        }
++        for (count = 0; count < last_space; count++)
++        {
++            curstr[count] = substr[count];
++        }
++        curstr[count] = '\0';
++        if (substr[count] == '\0')
++        {
++            break;
++        }
++        for (count = (last_space + 1); count < strlen(substr); count++)
++        {
++            tmpstr[count - (last_space + 1)] = substr[count];
++        }
++        tmpstr[count - (last_space + 1)] = '\0';
++        strcpy(substr, tmpstr);
++    }
++    
++    if (curline < line_num)
++    {
++        return NULL;
++    }
++    
++    retstr = curses_copy_of(curstr);
++    
++    return retstr;
++}
++
++
++/* Return the remaining portion of a string after hacking-off line_num lines */
++
++char *curses_str_remainder(const char *str, int width, int line_num)
++{
++    int last_space, count;
++    char *retstr;
++    int curline = 0;
++    int strsize = strlen(str);
++    char substr[strsize];
++    char curstr[strsize];
++    char tmpstr[strsize];
++    
++    strcpy(substr, str);
++    
++    while (curline < line_num)
++    {
++        if (strlen(substr) == 0 )
++        {
++            break;
++        }
++        curline++;
++        last_space = 0;       
++        for (count = 0; count <= width; count++)
++        {
++            if (substr[count] == ' ')
++            {
++                last_space = count;
++            }
++            else if (substr[count] == '\0')           
++            {
++                last_space = count;
++                break;
++            }
++        }
++        if (last_space == 0)    /* No spaces found */
++        {
++            last_space = count - 1;
++        }
++        for (count = 0; count < last_space; count++)
++        {
++            curstr[count] = substr[count];
++        }
++        curstr[count] = '\0';
++        if (substr[count] == '\0')
++        {
++            break;
++        }
++        for (count = (last_space + 1); count < strlen(substr); count++)
++        {
++            tmpstr[count - (last_space + 1)] = substr[count];
++        }
++        tmpstr[count - (last_space + 1)] = '\0';
++        strcpy(substr, tmpstr);
++    }
++    
++    if (curline < line_num)
++    {
++        return NULL;
++    }
++    
++    retstr = curses_copy_of(substr);
++    
++    return retstr;
++}
++
++
++/* Determine if the given NetHack winid is a menu window */
++
++boolean curses_is_menu(winid wid)
++{
++    if ((wid > 19) && !(wid % 2))   /* Even number */
++    {
++        return TRUE;
++    }
++    else
++    {
++        return FALSE;
++    }
++}
++
++
++/* Determine if the given NetHack winid is a text window */
++
++boolean curses_is_text(winid wid)
++{
++    if ((wid > 19) && (wid % 2))   /* Odd number */
++    {
++        return TRUE;
++    }
++    else
++    {
++        return FALSE;
++    }
++}
++
++
++/* Replace certain characters with portable drawing characters if
++cursesgraphics option is enabled */
++
++int curses_convert_glyph(int ch, int glyph)
++{
++    int symbol;
++    
++    /* Save some processing time by returning if the glyph represents
++    an object that we don't have custom characters for */
++    if (!glyph_is_cmap(glyph))
++    {
++        return ch;
++    }
++    
++    symbol = glyph_to_cmap(glyph);
++    
++    /* If user selected a custom character for this object, don't
++    override this. */
++    if (((glyph_is_cmap(glyph)) && (ch != showsyms[symbol])))
++    {
++        return ch;
++    }
++
++    switch (symbol)
++    {
++        case S_vwall:
++            return ACS_VLINE;
++        case S_hwall:
++            return ACS_HLINE;
++        case S_tlcorn:
++            return ACS_ULCORNER;
++        case S_trcorn:
++            return ACS_URCORNER;
++        case S_blcorn:
++            return ACS_LLCORNER;
++        case S_brcorn:
++            return ACS_LRCORNER;
++        case S_crwall:
++            return ACS_PLUS;
++        case S_tuwall:
++            return ACS_TTEE;
++        case S_tdwall:
++            return ACS_BTEE;
++        case S_tlwall:
++            return ACS_LTEE;
++        case S_trwall:
++            return ACS_RTEE;
++        case S_tree:
++            return ACS_PLMINUS;
++        case S_corr:
++            return ACS_CKBOARD;
++        case S_litcorr:
++            return ACS_CKBOARD;
++    }
++
++	return ch;
++}
++
++
++/* Move text cursor to specified coordinates in the given NetHack window */
++
++void curses_move_cursor(winid wid, int x, int y)
++{
++    WINDOW *win = curses_get_nhwin(curs_win);
++
++    if (wid != MAP_WIN)
++    {
++        return;
++    }
++
++#ifdef PDCURSES
++    /* PDCurses seems to not handle wmove correctly, so we use move and
++    physical screen coordinates instead */
++    curses_get_window_xy(wid, &curs_x, &curs_y);
++    curs_x += x;
++    curs_y += y;
++#else
++    curs_x = x;
++    curs_y = y;
++#endif    
++    curs_win = wid;
++#ifdef PDCURSES
++    move(curs_y, curs_x);
++#else
++    wmove(win, curs_y, curs_x);
++#endif
++}
++
++
++/* Perform actions that should be done every turn before nhgetch() */
++
++void curses_prehousekeeping()
++{
++    WINDOW *win = curses_get_nhwin(curs_win);
++
++    if ((curs_x > -1) && (curs_y > -1))
++    {
++        curs_set(1);
++#ifdef PDCURSES
++        /* PDCurses seems to not handle wmove correctly, so we use move
++        and physical screen coordinates instead */
++        move(curs_y, curs_x);
++#else
++        wmove(win, curs_y, curs_x);
++#endif
++        curses_refresh_nhwin(curs_win);
++    }
++}
++
++
++/* Perform actions that should be done every turn after nhgetch() */
++
++void curses_posthousekeeping()
++{
++    curs_set(0);
++    curses_decrement_highlight();
++    curses_clear_unhighlight_message_window();
++}
++
++
++void curses_view_file(const char *filename, boolean must_exist)
++{
++    winid wid;
++    anything *identifier;
++    char buf[BUFSZ];
++    menu_item *selected = NULL;
++    dlb *fp = dlb_fopen(filename, "r");
++    
++    if ((fp == NULL) && (must_exist))
++    {
++        pline("Cannot open %s for reading!", filename);
++    }
++
++    if (fp == NULL)
++    {
++        return;
++    }
++    
++    wid = curses_get_wid(NHW_MENU);
++    curses_create_nhmenu(wid);
++    identifier = malloc(sizeof(anything));
++    identifier->a_void = NULL;
++    
++    while (dlb_fgets(buf, BUFSZ, fp) != NULL)
++    {
++        curses_add_menu(wid, NO_GLYPH, identifier, 0, 0, A_NONE, buf,
++         FALSE);
++    }
++    
++    dlb_fclose(fp);
++    curses_end_menu(wid, "");
++    curses_select_menu(wid, PICK_NONE, &selected);
++}
++
++
++char *curses_rtrim(char *str)
++{
++    char *s;
++
++    for(s = str; *s != '\0'; ++s);
++    for(--s;isspace(*s) && s > str; --s);
++    if(s == str) *s = '\0';
++    else *(++s) = '\0';
++}
++
++/* Use nethack wall symbols for drawing unless cursesgraphics is
++defined, in which case we use the standard curses ones.  Not sure if
++this is desirable behavior since one may prefer regular lines for
++borders but traditional symbols to draw rooms.  Commenting it out for
++now. */
++
++/*
++ * void curses_border(WINDOW *win)
++ * {
++ *     if (iflags.cursesgraphics)
++ *     {
++ *         box(win, 0, 0);
++ *     }
++ *     else
++ *     {
++ *         wborder(win, showsyms[S_vwall], showsyms[S_vwall],
++ *          showsyms[S_hwall], showsyms[S_hwall], showsyms[S_tlcorn],
++ *          showsyms[S_trcorn], showsyms[S_blcorn], showsyms[S_brcorn]);
++ *     }
++ * }
++ */
++
+diff -burN nethack-3.4.3/win/curses/cursmisc.h nethack/win/curses/cursmisc.h
+--- nethack-3.4.3/win/curses/cursmisc.h	1969-12-31 19:00:00.000000000 -0500
++++ nethack/win/curses/cursmisc.h	2009-03-05 13:50:38.000000000 -0500
+@@ -0,0 +1,38 @@
++#ifndef CURSMISC_H
++#define CURSMISC_H
++
++/* Global declarations */
++
++int curses_read_char(void);
++
++void curses_toggle_color_attr(WINDOW *win, int color, int attr, int onoff);
++
++void curses_bail(const char *mesg);
++
++winid curses_get_wid(int type);
++
++char *curses_copy_of(const char *s);
++
++int curses_num_lines(const char *str, int width);
++
++char *curses_break_str(const char *str, int width, int line_num);
++
++char *curses_str_remainder(const char *str, int width, int line_num);
++
++boolean curses_is_menu(winid wid);
++
++boolean curses_is_text(winid wid);
++
++int curses_convert_glyph(int ch, int glyph);
++
++void curses_move_cursor(winid wid, int x, int y);
++
++void curses_prehousekeeping(void);
++
++void curses_posthousekeeping(void);
++
++void curses_view_file(const char *filename, boolean must_exist);
++
++char *curses_rtrim(char *str);
++
++#endif  /* CURSMISC_H */
+diff -burN nethack-3.4.3/win/curses/cursstat.c nethack/win/curses/cursstat.c
+--- nethack-3.4.3/win/curses/cursstat.c	1969-12-31 19:00:00.000000000 -0500
++++ nethack/win/curses/cursstat.c	2009-03-11 15:08:53.000000000 -0400
+@@ -0,0 +1,2145 @@
++#include "curses.h"
++#include "hack.h"
++#include "wincurs.h"
++#include "cursstat.h"
++
++/* Status window functions for curses interface */
++
++static nhstat prevname;
++static nhstat prevdepth;
++static nhstat prevstr;
++static nhstat prevint;
++static nhstat prevwis;
++static nhstat prevdex;
++static nhstat prevcon;
++static nhstat prevcha;
++static nhstat prevalign;  
++static nhstat prevau;
++static nhstat prevhp;
++static nhstat prevmhp;
++static nhstat prevlevel;
++static nhstat prevpow;
++static nhstat prevmpow;
++static nhstat prevac;
++static nhstat prevexp;
++static nhstat prevtime;
++static nhstat prevscore;
++static nhstat prevhunger;
++static nhstat prevconf;
++static nhstat prevblind;
++static nhstat prevstun;
++static nhstat prevhallu;
++static nhstat prevsick;
++static nhstat prevslime;
++static nhstat prevencumb;
++
++extern const char *hu_stat[]; /* from eat.c */
++extern const char *enc_stat[]; /* from botl.c */
++
++/* Update the status win - this is called when NetHack would normally
++write to the status window, so we know somwthing has changed.  We
++override the write and update what needs to be updated ourselves. */
++
++void curses_update_stats()
++{
++    char buf[BUFSZ];
++    int count, enc, orient, sx_start;
++    WINDOW *win = curses_get_nhwin(STATUS_WIN);
++    static boolean first = TRUE;
++    boolean horiz;
++    int sx = 0;
++    int sy = 0;
++    boolean border = curses_window_has_border(STATUS_WIN);
++    
++    if (border)
++    {
++        sx++;
++        sy++;
++    }
++    
++    sx_start = sx;
++        
++    if (first)
++    {
++        init_stats();
++        first = FALSE;
++    }
++    
++    orient = curses_get_window_orientation(STATUS_WIN);
++
++    if ((orient == ALIGN_RIGHT) || (orient == ALIGN_LEFT))
++    {
++        horiz = FALSE;
++    }
++    else
++    {
++        horiz = TRUE;
++    }
++
++    curses_clear_nhwin(STATUS_WIN);
++    
++    /* Line 1 */
++    
++    /* Player name and title */
++    strcpy(buf, plname);
++    if ('a' <= buf[0] && buf[0] <= 'z') buf[0] += 'A'-'a';
++    strcat(buf, " the ");
++    if (u.mtimedone) {
++        char mname[BUFSZ];
++        int k = 0;
++
++        strcpy(mname, mons[u.umonnum].mname);
++        while(mname[k] != 0) {
++            if ((k == 0 || (k > 0 && mname[k-1] == ' '))
++             && 'a' <= mname[k] && mname[k] <= 'z')
++            {
++                mname[k] += 'A' - 'a';
++            }
++            k++;
++        }
++        strcat(buf, mname);
++    } else {
++        strcat(buf, rank_of(u.ulevel, pl_character[0], flags.female));
++    }
++    
++    if (strcmp(buf, prevname.txt) != 0) /* Title changed */
++    {
++        prevname.highlight_turns = 5;
++        prevname.highlight_color = HIGHLIGHT_COLOR;
++        free(prevname.txt);
++        prevname.txt = curses_copy_of(buf);
++    }
++    
++    if (prevname.label != NULL)
++    {
++        mvwaddstr(win, sy, sx, prevname.label);
++        sx += strlen(prevname.label);
++    }
++    
++    if (prevname.highlight_turns > 0)
++    {
++        curses_toggle_color_attr(win, prevname.highlight_color, NONE, ON);
++        mvwaddstr(win, sy, sx, prevname.txt);
++        curses_toggle_color_attr(win, prevname.highlight_color, NONE, OFF);
++    }
++    else
++    {
++        mvwaddstr(win, sy, sx, prevname.txt);
++    }
++    
++    if (horiz)
++    {
++        sx += strlen(prevname.txt) + 1;
++    }
++    else
++    {
++        sx = sx_start;
++        sy++;
++    }
++    
++    /* Strength */
++    if (ACURR(A_STR) != prevstr.value)  /* Strength changed */
++    {
++        
++        if (ACURR(A_STR) > prevstr.value)
++        {
++            prevstr.highlight_color = STAT_UP_COLOR;
++        }
++        else
++        {
++            prevstr.highlight_color = STAT_DOWN_COLOR;
++        }
++        prevstr.value = ACURR(A_STR);
++        if (ACURR(A_STR) > 118)
++        {
++            sprintf(buf, "%d", ACURR(A_STR) - 100);
++        }
++        else if (ACURR(A_STR)==118)
++        {
++            sprintf(buf, "18/**");
++        }
++        else if(ACURR(A_STR) > 18)
++        {
++            sprintf(buf, "18/%02d", ACURR(A_STR) - 18);
++        }
++        else
++        {
++            sprintf(buf, "%d", ACURR(A_STR));
++        }
++        free(prevstr.txt);
++        prevstr.txt = curses_copy_of(buf);
++        prevstr.highlight_turns = 5;
++    }
++
++    if (prevstr.label != NULL)
++    {
++        mvwaddstr(win, sy, sx, prevstr.label);
++        sx += strlen(prevstr.label);
++    }
++    
++    if (prevstr.highlight_turns > 0)
++    {
++        curses_toggle_color_attr(win, prevstr.highlight_color, NONE, ON);
++        mvwaddstr(win, sy, sx, prevstr.txt);
++        curses_toggle_color_attr(win, prevstr.highlight_color, NONE, OFF);
++    }
++    else
++    {
++        mvwaddstr(win, sy, sx, prevstr.txt);
++    }
++    
++    if (horiz)
++    {
++        sx += strlen(prevstr.txt) + 1;
++    }
++    else
++    {
++        sx = sx_start;
++        sy++;
++    }
++
++    /* Intelligence */
++    if (ACURR(A_INT) != prevint.value)  /* Intelligence changed */
++    {
++        
++        if (ACURR(A_INT) > prevint.value)
++        {
++            prevint.highlight_color = STAT_UP_COLOR;
++        }
++        else
++        {
++            prevint.highlight_color = STAT_DOWN_COLOR;
++        }
++        prevint.value = ACURR(A_INT);
++        sprintf(buf, "%d", ACURR(A_INT)); 
++        free(prevint.txt);
++        prevint.txt = curses_copy_of(buf);
++        prevint.highlight_turns = 5;
++    }
++
++    if (prevint.label != NULL)
++    {
++        mvwaddstr(win, sy, sx, prevint.label);
++        sx += strlen(prevint.label);
++    }
++    
++    if (prevint.highlight_turns > 0)
++    {
++        curses_toggle_color_attr(win, prevint.highlight_color, NONE, ON);
++        mvwaddstr(win, sy, sx, prevint.txt);
++        curses_toggle_color_attr(win, prevint.highlight_color, NONE, OFF);
++    }
++    else
++    {
++        mvwaddstr(win, sy, sx, prevint.txt);
++    }
++    
++    if (horiz)
++    {
++        sx += strlen(prevint.txt) + 1;
++    }
++    else
++    {
++        sx = sx_start;
++        sy++;
++    }
++
++    /* Wisdom */
++    if (ACURR(A_WIS) != prevwis.value)  /* Wisdom changed */
++    {
++        
++        if (ACURR(A_WIS) > prevwis.value)
++        {
++            prevwis.highlight_color = STAT_UP_COLOR;
++        }
++        else
++        {
++            prevwis.highlight_color = STAT_DOWN_COLOR;
++        }
++        prevwis.value = ACURR(A_WIS);
++        sprintf(buf, "%d", ACURR(A_WIS)); 
++        free(prevwis.txt);
++        prevwis.txt = curses_copy_of(buf);
++        prevwis.highlight_turns = 5;
++    }
++
++    if (prevwis.label != NULL)
++    {
++        mvwaddstr(win, sy, sx, prevwis.label);
++        sx += strlen(prevwis.label);
++    }
++    
++    if (prevwis.highlight_turns > 0)
++    {
++        curses_toggle_color_attr(win, prevwis.highlight_color, NONE, ON);
++        mvwaddstr(win, sy, sx, prevwis.txt);
++        curses_toggle_color_attr(win, prevwis.highlight_color, NONE, OFF);
++    }
++    else
++    {
++        mvwaddstr(win, sy, sx, prevwis.txt);
++    }
++    
++    if (horiz)
++    {
++        sx += strlen(prevwis.txt) + 1;
++    }
++    else
++    {
++        sx = sx_start;
++        sy++;
++    }
++
++    /* Dexterity */
++    if (ACURR(A_DEX) != prevdex.value)  /* Dexterity changed */
++    {
++        
++        if (ACURR(A_DEX) > prevdex.value)
++        {
++            prevdex.highlight_color = STAT_UP_COLOR;
++        }
++        else
++        {
++            prevdex.highlight_color = STAT_DOWN_COLOR;
++        }
++        prevdex.value = ACURR(A_DEX);
++        sprintf(buf, "%d", ACURR(A_DEX));
++        free(prevdex.txt);
++        prevdex.txt = curses_copy_of(buf);
++        prevdex.highlight_turns = 5;
++    }
++
++    if (prevdex.label != NULL)
++    {
++        mvwaddstr(win, sy, sx, prevdex.label);
++        sx += strlen(prevdex.label);
++    }
++    
++    if (prevdex.highlight_turns > 0)
++    {
++        curses_toggle_color_attr(win, prevdex.highlight_color, NONE, ON);
++        mvwaddstr(win, sy, sx, prevdex.txt);
++        curses_toggle_color_attr(win, prevdex.highlight_color, NONE, OFF);
++    }
++    else
++    {
++        mvwaddstr(win, sy, sx, prevdex.txt);
++    }
++    
++    if (horiz)
++    {
++        sx += strlen(prevdex.txt) + 1;
++    }
++    else
++    {
++        sx = sx_start;
++        sy++;
++    }
++
++    /* Constitution */
++    if (ACURR(A_CON) != prevcon.value)  /* Constitution changed */
++    {
++        
++        if (ACURR(A_CON) > prevcon.value)
++        {
++            prevcon.highlight_color = STAT_UP_COLOR;
++        }
++        else
++        {
++            prevcon.highlight_color = STAT_DOWN_COLOR;
++        }
++        prevcon.value = ACURR(A_CON);
++        sprintf(buf, "%d", ACURR(A_CON));
++        free(prevcon.txt);
++        prevcon.txt = curses_copy_of(buf);
++        prevcon.highlight_turns = 5;
++    }
++
++    if (prevcon.label != NULL)
++    {
++        mvwaddstr(win, sy, sx, prevcon.label);
++        sx += strlen(prevcon.label);
++    }
++    
++    if (prevcon.highlight_turns > 0)
++    {
++        curses_toggle_color_attr(win, prevcon.highlight_color, NONE, ON);
++        mvwaddstr(win, sy, sx, prevcon.txt);
++        curses_toggle_color_attr(win, prevcon.highlight_color, NONE, OFF);
++    }
++    else
++    {
++        mvwaddstr(win, sy, sx, prevcon.txt);
++    }
++    
++    if (horiz)
++    {
++        sx += strlen(prevcon.txt) + 1;
++    }
++    else
++    {
++        sx = sx_start;
++        sy++;
++    }
++
++    /* Charisma */
++    if (ACURR(A_CHA) != prevcha.value)  /* Charisma changed */
++    {
++        if (ACURR(A_CHA) > prevcha.value)
++        {
++            prevcha.highlight_color = STAT_UP_COLOR;
++        }
++        else
++        {
++            prevcha.highlight_color = STAT_DOWN_COLOR;
++        }
++        prevcha.value = ACURR(A_CHA);
++        sprintf(buf, "%d", ACURR(A_CHA));
++        free(prevcha.txt);
++        prevcha.txt = curses_copy_of(buf);
++        prevcha.highlight_turns = 5;
++    }
++
++    if (prevcha.label != NULL)
++    {
++        mvwaddstr(win, sy, sx, prevcha.label);
++        sx += strlen(prevcha.label);
++    }
++    
++    if (prevcha.highlight_turns > 0)
++    {
++        curses_toggle_color_attr(win, prevcha.highlight_color, NONE, ON);
++        mvwaddstr(win, sy, sx, prevcha.txt);
++        curses_toggle_color_attr(win, prevcha.highlight_color, NONE, OFF);
++    }
++    else
++    {
++        mvwaddstr(win, sy, sx, prevcha.txt);
++    }
++    
++    if (horiz)
++    {
++        sx += strlen(prevcha.txt) + 1;
++    }
++    else
++    {
++        sx = sx_start;
++        sy++;
++    }
++    
++    /* Alignment */
++    if (prevalign.alignment != u.ualign.type)   /* Alignment changed */
++    {
++        prevalign.highlight_color = HIGHLIGHT_COLOR;
++        prevalign.highlight_turns = 10; /* This is a major change! */
++        prevalign.alignment = u.ualign.type;
++        free(prevalign.txt);
++        switch (u.ualign.type)
++        {
++            case A_LAWFUL:
++            {
++                prevalign.txt = curses_copy_of("Lawful");
++                break;
++            }
++            case A_NEUTRAL:
++            {
++                prevalign.txt = curses_copy_of("Neutral");
++                break;
++            }
++            case A_CHAOTIC:
++            {
++                prevalign.txt = curses_copy_of("Chaotic");
++                break;
++            }
++        }
++    }
++
++    if (prevalign.label != NULL)
++    {
++        mvwaddstr(win, sy, sx, prevalign.label);
++        sx += strlen(prevalign.label);
++    }
++    
++    if (prevalign.highlight_turns > 0)
++    {
++        curses_toggle_color_attr(win, prevalign.highlight_color, NONE, ON);
++        mvwaddstr(win, sy, sx, prevalign.txt);
++        curses_toggle_color_attr(win, prevalign.highlight_color, NONE, OFF);
++    }
++    else
++    {
++        mvwaddstr(win, sy, sx, prevalign.txt);
++    }
++    
++    /* Line 2 */
++    
++    sx = sx_start;
++    sy++;
++    
++    /* Dungeon Level */
++    if (depth(&u.uz) != prevdepth.value)    /* Dungeon level changed */
++    {
++        prevdepth.highlight_color = HIGHLIGHT_COLOR;
++        prevdepth.highlight_turns = 5;
++        prevdepth.value = depth(&u.uz);
++        free(prevdepth.txt);
++        if (In_endgame(&u.uz))
++        {
++            strcpy(buf, (Is_astralevel(&u.uz) ? "Astral Plane":"End Game"));
++        }
++        else
++        {
++            sprintf(buf, "%d", depth(&u.uz));
++        }
++        prevdepth.txt = curses_copy_of(buf);
++    }
++    
++    if (prevdepth.label != NULL)
++    {
++        mvwaddstr(win, sy, sx, prevdepth.label);
++        sx += strlen(prevdepth.label);
++    }
++    
++    if (prevdepth.highlight_turns > 0)
++    {
++        curses_toggle_color_attr(win, prevdepth.highlight_color, NONE, ON);
++        mvwaddstr(win, sy, sx, prevdepth.txt);
++        curses_toggle_color_attr(win, prevdepth.highlight_color, NONE, OFF);
++    }
++    else
++    {
++        mvwaddstr(win, sy, sx, prevdepth.txt);
++    }
++    
++    if (horiz)
++    {
++        sx += strlen(prevdepth.txt) + 1;
++    }
++    else
++    {
++        sx = sx_start;
++        sy++;
++    }
++    
++    /* Gold */
++#ifndef GOLDOBJ
++    if (prevau.value != u.ugold)    /* Gold changed */
++    {
++        if (u.ugold > prevau.value)
++        {
++#else
++    if (prevau.value != money_cnt(invent))  /* Gold changed */
++    {
++        if (money_cnt(invent) > prevau.value)
++        {
++#endif
++            prevau.highlight_color = HI_GOLD;
++        }
++        else
++        {
++            prevau.highlight_color = STAT_DOWN_COLOR;
++        }
++#ifndef GOLDOBJ
++        prevau.value = u.ugold;
++        sprintf(buf,"%ld", u.ugold);
++#else
++        prevau.value = money_cnt(invent);
++        sprintf(buf,"%ld", money_cnt(invent));
++#endif
++        free(prevau.txt);
++        prevau.txt = curses_copy_of(buf);
++        prevau.highlight_turns = 5;
++    }
++    
++    if (prevau.label != NULL)
++    {
++        mvwaddstr(win, sy, sx, prevau.label);
++        sx += strlen(prevau.label);
++    }
++    
++    if (prevau.highlight_turns > 0)
++    {
++        curses_toggle_color_attr(win, prevau.highlight_color, NONE, ON);
++        mvwaddstr(win, sy, sx, prevau.txt);
++        curses_toggle_color_attr(win, prevau.highlight_color, NONE, OFF);
++    }
++    else
++    {
++        mvwaddstr(win, sy, sx, prevau.txt);
++    }
++
++    if (horiz)
++    {
++        sx += strlen(prevau.txt) + 1;
++    }
++    else
++    {
++        sx = sx_start;
++        sy++;
++    }
++    
++    /* Hit Points */
++    if (u.mtimedone)    /* Currently polymorphed - show monster HP */
++    {
++	    if (u.mh != prevhp.value)
++	    {
++	        if (u.mh > prevhp.value)
++	        {
++	            prevhp.highlight_color = STAT_UP_COLOR;
++	        }
++	        else
++	        {
++	            prevhp.highlight_color = STAT_DOWN_COLOR;
++	        }
++            prevhp.highlight_turns = 3;
++            prevhp.value = u.mh;
++            sprintf(buf, "%d", u.mh);
++            free(prevhp.txt);
++            prevhp.txt = curses_copy_of(buf);
++	    }
++	}
++	else if (u.uhp != prevhp.value)  /* Not polymorphed */
++	{
++	    if (u.uhp > prevhp.value)
++	    {
++	        prevhp.highlight_color = STAT_UP_COLOR;
++	    }
++	    else
++	    {
++            prevhp.highlight_color = STAT_DOWN_COLOR;
++	    }
++        prevhp.value = u.uhp;
++        sprintf(buf, "%d", u.uhp);
++        free(prevhp.txt);
++        prevhp.txt = curses_copy_of(buf);
++        prevhp.highlight_turns = 3;
++	}
++
++    if (prevhp.label != NULL)
++    {
++        mvwaddstr(win, sy, sx, prevhp.label);
++        sx += strlen(prevhp.label);
++    }
++
++    if (prevhp.highlight_turns > 0)
++    {
++        curses_toggle_color_attr(win, prevhp.highlight_color, NONE, ON);
++        mvwaddstr(win, sy, sx, prevhp.txt);
++        curses_toggle_color_attr(win, prevhp.highlight_color, NONE, OFF);
++    }
++    else
++    {
++        mvwaddstr(win, sy, sx, prevhp.txt);
++    }
++    
++    sx += strlen(prevhp.txt);
++
++    /* Max Hit Points */
++    if (u.mtimedone)    /* Currently polymorphed - show monster HP */
++    {
++	    if (u.mhmax != prevmhp.value)
++	    {
++	        if (u.mhmax > prevmhp.value)
++	        {
++	            prevmhp.highlight_color = STAT_UP_COLOR;
++	        }
++	        else
++	        {
++	            prevmhp.highlight_color = STAT_DOWN_COLOR;
++	        }
++            prevmhp.value = u.mhmax;
++            sprintf(buf, "%d", u.mhmax);
++            free(prevmhp.txt);
++            prevmhp.txt = curses_copy_of(buf);
++            prevmhp.highlight_turns = 3;
++	    }
++	}
++	else if (u.uhpmax != prevmhp.value)  /* Not polymorphed */
++	{
++	    if (u.uhpmax > prevmhp.value)
++	    {
++	        prevmhp.highlight_color = STAT_UP_COLOR;
++	    }
++	    else
++	    {
++            prevmhp.highlight_color = STAT_DOWN_COLOR;
++	    }
++        prevmhp.value = u.uhpmax;
++        sprintf(buf, "%d", u.uhpmax);
++        free(prevmhp.txt);
++        prevmhp.txt = curses_copy_of(buf);
++        prevmhp.highlight_turns = 3;
++	}
++
++    if (prevmhp.label != NULL)
++    {
++        mvwaddstr(win, sy, sx, prevmhp.label);
++        sx += strlen(prevmhp.label);
++    }
++
++    if (prevmhp.highlight_turns > 0)
++    {
++        curses_toggle_color_attr(win, prevmhp.highlight_color, NONE, ON);
++        mvwaddstr(win, sy, sx, prevmhp.txt);
++        curses_toggle_color_attr(win, prevmhp.highlight_color, NONE, OFF);
++    }
++    else
++    {
++        mvwaddstr(win, sy, sx, prevmhp.txt);
++    }
++    
++    if (horiz)
++    {
++        sx += strlen(prevmhp.txt) + 1;
++    }
++    else
++    {
++        sx = sx_start;
++        sy++;
++    }
++
++    /* Power */
++    if (u.uen != prevpow.value)
++	{
++	    if (u.uen > prevpow.value)
++	    {
++	        prevpow.highlight_color = STAT_UP_COLOR;
++	    }
++	    else
++	    {
++            prevpow.highlight_color = STAT_DOWN_COLOR;
++	    }
++        prevpow.value = u.uen;
++        sprintf(buf, "%d", u.uen);
++        free(prevpow.txt);
++        prevpow.txt = curses_copy_of(buf);
++        prevpow.highlight_turns = 3;
++	}
++
++    if (prevpow.label != NULL)
++    {
++        mvwaddstr(win, sy, sx, prevpow.label);
++        sx += strlen(prevpow.label);
++    }
++
++    if (prevpow.highlight_turns > 0)
++    {
++        curses_toggle_color_attr(win, prevpow.highlight_color, NONE, ON);
++        mvwaddstr(win, sy, sx, prevpow.txt);
++        curses_toggle_color_attr(win, prevpow.highlight_color, NONE, OFF);
++    }
++    else
++    {
++        mvwaddstr(win, sy, sx, prevpow.txt);
++    }
++    
++    sx += strlen(prevpow.txt);
++
++    /* Max Power */
++    if (u.uenmax != prevmpow.value)
++	{
++	    if (u.uenmax > prevmpow.value)
++	    {
++	        prevmpow.highlight_color = STAT_UP_COLOR;
++	    }
++	    else
++	    {
++            prevmpow.highlight_color = STAT_DOWN_COLOR;
++	    }
++        prevmpow.value = u.uenmax;
++        sprintf(buf, "%d", u.uenmax);
++        free(prevmpow.txt);
++        prevmpow.txt = curses_copy_of(buf);
++        prevmpow.highlight_turns = 3;
++	}
++
++    if (prevmpow.label != NULL)
++    {
++        mvwaddstr(win, sy, sx, prevmpow.label);
++        sx += strlen(prevmpow.label);
++    }
++
++    if (prevmpow.highlight_turns > 0)
++    {
++        curses_toggle_color_attr(win, prevmpow.highlight_color, NONE, ON);
++        mvwaddstr(win, sy, sx, prevmpow.txt);
++        curses_toggle_color_attr(win, prevmpow.highlight_color, NONE, OFF);
++    }
++    else
++    {
++        mvwaddstr(win, sy, sx, prevmpow.txt);
++    }
++    
++    if (horiz)
++    {
++        sx += strlen(prevmpow.txt) + 1;
++    }
++    else
++    {
++        sx = sx_start;
++        sy++;
++    }
++
++
++    /* Armor Class */
++    if (u.uac != prevac.value)
++	{
++	    if (u.uac > prevac.value)   /* Lower is better for AC */
++	    {
++	        prevac.highlight_color = STAT_DOWN_COLOR;
++	    }
++	    else
++	    {
++            prevac.highlight_color = STAT_UP_COLOR;
++	    }
++        prevac.value = u.uac;
++        sprintf(buf, "%d", u.uac);
++        free(prevac.txt);
++        prevac.txt = curses_copy_of(buf);
++        prevac.highlight_turns = 5;
++	}
++
++    if (prevac.label != NULL)
++    {
++        mvwaddstr(win, sy, sx, prevac.label);
++        sx += strlen(prevac.label);
++    }
++
++    if (prevac.highlight_turns > 0)
++    {
++        curses_toggle_color_attr(win, prevac.highlight_color, NONE, ON);
++        mvwaddstr(win, sy, sx, prevac.txt);
++        curses_toggle_color_attr(win, prevac.highlight_color, NONE, OFF);
++    }
++    else
++    {
++        mvwaddstr(win, sy, sx, prevac.txt);
++    }
++    
++    if (horiz)
++    {
++        sx += strlen(prevac.txt) + 1;
++    }
++    else
++    {
++        sx = sx_start;
++        sy++;
++    }
++
++    /* Experience */
++#ifdef EXP_ON_BOTL
++    if (prevexp.display != flags.showexp)   /* Setting has changed */
++    {
++        prevexp.display = flags.showexp;
++        free(prevlevel.label);
++        if (prevexp.display)
++        {
++            prevlevel.label = curses_copy_of("/");
++        }
++        else
++        {
++            prevlevel.label = curses_copy_of("Lvl:");
++        }
++    }
++
++    if (prevexp.display && !u.mtimedone)
++    {
++        if (u.uexp != prevexp.value)
++	    {
++	        if (u.uexp > prevexp.value)
++	        {
++	            prevexp.highlight_color = STAT_UP_COLOR;
++	        }
++	        else
++	        {
++                prevexp.highlight_color = STAT_DOWN_COLOR;
++	        }
++            sprintf(buf, "%d", u.uexp);
++            free(prevexp.txt);
++            prevexp.txt = curses_copy_of(buf);
++            prevexp.highlight_turns = 3;
++	    }
++
++        if (prevexp.label != NULL)
++        {
++            mvwaddstr(win, sy, sx, prevexp.label);
++            sx += strlen(prevexp.label);
++        }
++
++        if (prevexp.highlight_turns > 0)
++        {
++            curses_toggle_color_attr(win, prevexp.highlight_color, NONE, ON);
++            mvwaddstr(win, sy, sx, prevexp.txt);
++            curses_toggle_color_attr(win, prevexp.highlight_color, NONE, OFF);
++        }
++        else
++        {
++            mvwaddstr(win, sy, sx, prevexp.txt);
++        }
++
++        sx += strlen(prevexp.txt);
++    }
++    
++    prevexp.value = u.uexp; /* Track it even when it's not displayed */
++#endif  /* EXP_ON_BOTL */
++
++    /* Level */
++    if (u.mtimedone)    /* Currently polymorphed - show monster HD */
++    {
++        if (strncmp(prevlevel.label, "HD:", 3) != 0)
++        {
++            free(prevlevel.label);
++            prevlevel.label = curses_copy_of("HD:");
++        }
++        if (mons[u.umonnum].mlevel != prevlevel.value)
++        {
++            if (mons[u.umonnum].mlevel > prevlevel.value)
++            {
++                prevlevel.highlight_color = STAT_UP_COLOR;
++            }
++            else
++            {
++                prevlevel.highlight_color = STAT_DOWN_COLOR;
++            }
++            prevlevel.highlight_turns = 5;
++        }
++        prevlevel.value = mons[u.umonnum].mlevel;
++        sprintf(buf, "%d", mons[u.umonnum].mlevel);
++        free(prevlevel.txt);
++        prevlevel.txt = curses_copy_of(buf);
++    }
++    else    /* Not polymorphed */
++    {
++        if (strncmp(prevlevel.label, "HD:", 3) == 0)
++        {
++            free(prevlevel.label);
++            if (prevexp.display)
++            {
++                prevlevel.label = curses_copy_of("/");
++            }
++            else
++            {
++                prevlevel.label = curses_copy_of("Lvl:");
++            }
++        }
++        if (u.ulevel > prevlevel.value)
++        {
++            prevlevel.highlight_color = STAT_UP_COLOR;
++            prevlevel.highlight_turns = 5;
++        }
++        else if (u.ulevel < prevlevel.value)
++        {
++            prevlevel.highlight_color = STAT_DOWN_COLOR;
++            prevlevel.highlight_turns = 5;
++        }
++        prevlevel.value = u.ulevel;
++        sprintf(buf, "%d", u.ulevel);
++        free(prevlevel.txt);
++        prevlevel.txt = curses_copy_of(buf);
++    }
++
++    if (prevlevel.label != NULL)
++    {
++        mvwaddstr(win, sy, sx, prevlevel.label);
++        sx += strlen(prevlevel.label);
++    }
++
++    if (prevlevel.highlight_turns > 0)
++    {
++        curses_toggle_color_attr(win, prevlevel.highlight_color, NONE, ON);
++        mvwaddstr(win, sy, sx, prevlevel.txt);
++        curses_toggle_color_attr(win, prevlevel.highlight_color, NONE, OFF);
++    }
++    else
++    {
++        mvwaddstr(win, sy, sx, prevlevel.txt);
++    }
++
++    if (horiz)
++    {
++        sx += strlen(prevlevel.txt) + 1;
++    }
++    else
++    {
++        sx = sx_start;
++        sy++;
++    }
++
++    /* Time */
++    if (prevtime.display != flags.time)   /* Setting has changed */
++    {
++        prevtime.display = flags.time;
++    }
++    if (prevtime.display)
++    {
++        if (moves != prevtime.value)
++	    {
++            sprintf(buf, "%ld", moves);
++            free(prevtime.txt);
++            prevtime.txt = curses_copy_of(buf);
++	    }
++
++        if (prevtime.label != NULL)
++        {
++            mvwaddstr(win, sy, sx, prevtime.label);
++            sx += strlen(prevtime.label);
++        }
++
++        mvwaddstr(win, sy, sx, prevtime.txt);
++
++        if (horiz)
++        {
++            sx += strlen(prevtime.txt) + 1;
++        }
++        else
++        {
++            sx = sx_start;
++            sy++;
++        }
++    }
++    
++    /* Score */
++#ifdef SCORE_ON_BOTL
++    if (prevscore.display != flags.showscore)   /* Setting has changed */
++    {
++        prevscore.display = flags.showscore;
++    }
++    if (prevscore.display)
++    {
++        if (botl_score() != prevscore.value)
++	    {
++	        if (botl_score() > prevscore.value)
++	        {
++	            prevscore.highlight_color = STAT_UP_COLOR;
++	        }
++	        else    /* Not sure this is possible */
++	        {
++                prevscore.highlight_color = STAT_DOWN_COLOR;
++	        }
++            sprintf(buf, "%ld", botl_score());
++            free(prevscore.txt);
++            prevscore.txt = curses_copy_of(buf);
++            prevscore.highlight_turns = 3;
++	    }
++
++        if (prevscore.label != NULL)
++        {
++            mvwaddstr(win, sy, sx, prevscore.label);
++            sx += strlen(prevscore.label);
++        }
++
++        if (prevscore.highlight_turns > 0)
++        {
++            curses_toggle_color_attr(win, prevscore.highlight_color, NONE, ON);
++            mvwaddstr(win, sy, sx, prevscore.txt);
++            curses_toggle_color_attr(win, prevscore.highlight_color, NONE, OFF);
++        }
++        else
++        {
++            mvwaddstr(win, sy, sx, prevscore.txt);
++        }
++
++        if (horiz)
++        {
++            sx += strlen(prevscore.txt) + 1;
++        }
++        else
++        {
++            sx = sx_start;
++            sy++;
++        }
++    }
++    
++    prevscore.value = botl_score(); /* Track it even when it's not displayed */
++#endif  /* SCORE_ON_BOTL */
++
++    /* Hunger */
++    if (u.uhs != prevhunger.value)
++	{
++	    if ((u.uhs > prevhunger.value) || (u.uhs > 3))
++	    {
++	        prevhunger.highlight_color = STAT_DOWN_COLOR;
++	    }
++	    else
++	    {
++            prevhunger.highlight_color = STAT_UP_COLOR;
++	    }
++        prevhunger.value = u.uhs;
++        for (count = 0; count < strlen(hu_stat[u.uhs]); count++)
++        {
++            if ((hu_stat[u.uhs][count]) == ' ')
++            {
++                break;
++            }
++            buf[count] = hu_stat[u.uhs][count];
++        }
++
++        buf[count] = '\0';
++        free(prevhunger.txt);
++        prevhunger.txt = curses_copy_of(buf);
++        prevhunger.highlight_turns = 5;
++	}
++
++    if (prevhunger.label != NULL)
++    {
++        mvwaddstr(win, sy, sx, prevhunger.label);
++        sx += strlen(prevhunger.label);
++    }
++
++    if (prevhunger.highlight_turns > 0)
++    {
++        curses_toggle_color_attr(win, prevhunger.highlight_color, NONE, ON);
++        mvwaddstr(win, sy, sx, prevhunger.txt);
++        curses_toggle_color_attr(win, prevhunger.highlight_color, NONE, OFF);
++    }
++    else
++    {
++        mvwaddstr(win, sy, sx, prevhunger.txt);
++    }
++    
++    if (strlen(prevhunger.txt) > 0)
++    {
++        if (horiz)
++        {
++            sx += strlen(prevhunger.txt) + 1;
++        }
++        else
++        {
++            sx = sx_start;
++            sy++;
++        }
++    }
++
++    /* Confusion */
++    if (Confusion != prevconf.value)
++	{
++	    prevconf.highlight_color = STAT_DOWN_COLOR;
++        if (prevconf.txt != NULL)
++        {
++            free(prevconf.txt);
++        }
++        if (Confusion)
++        {
++            prevconf.txt = curses_copy_of("Conf");
++        }
++        else
++        {
++            prevconf.txt = NULL;
++        }
++        if (prevconf.value == 0)
++        {
++            prevconf.highlight_turns = 5;
++	    }
++        prevconf.value = Confusion;
++	}
++
++    if (prevconf.label != NULL)
++    {
++        mvwaddstr(win, sy, sx, prevconf.label);
++        sx += strlen(prevconf.label);
++    }
++
++    if (prevconf.txt != NULL)
++    {
++        if (prevconf.highlight_turns > 0)
++        {
++            curses_toggle_color_attr(win, prevconf.highlight_color, NONE, ON);
++            mvwaddstr(win, sy, sx, prevconf.txt);
++            curses_toggle_color_attr(win, prevconf.highlight_color, NONE, OFF);
++        }
++        else
++        {
++            mvwaddstr(win, sy, sx, prevconf.txt);
++        }
++    }
++
++    if (prevconf.txt != NULL)
++    {
++        if (horiz)
++        {
++            sx += strlen(prevconf.txt) + 1;
++        }
++        else
++        {
++            sx = sx_start;
++            sy++;
++        }
++    }
++
++    /* Blindness */
++    if (Blind != prevblind.value)
++	{
++	    prevblind.highlight_color = STAT_DOWN_COLOR;
++        if (prevblind.txt != NULL)
++        {
++            free(prevblind.txt);
++        }
++        if (Blind)
++        {
++            prevblind.txt = curses_copy_of("Blind");
++        }
++        else
++        {
++            prevblind.txt = NULL;
++        }
++        if (prevblind.value == 0)
++        {
++            prevblind.highlight_turns = 5;
++	    }
++        prevblind.value = Blind;
++	}
++
++    if (prevblind.label != NULL)
++    {
++        mvwaddstr(win, sy, sx, prevblind.label);
++        sx += strlen(prevblind.label);
++    }
++
++    if (prevblind.txt != NULL)
++    {
++        if (prevblind.highlight_turns > 0)
++        {
++            curses_toggle_color_attr(win, prevblind.highlight_color, NONE, ON);
++            mvwaddstr(win, sy, sx, prevblind.txt);
++            curses_toggle_color_attr(win, prevblind.highlight_color, NONE, OFF);
++        }
++        else
++        {
++            mvwaddstr(win, sy, sx, prevblind.txt);
++        }
++    }
++
++    if (prevblind.txt != NULL)
++    {
++        if (horiz)
++        {
++            sx += strlen(prevblind.txt) + 1;
++        }
++        else
++        {
++            sx = sx_start;
++            sy++;
++        }
++    }
++
++    /* Stun */
++    if (Stunned != prevstun.value)
++	{
++	    prevstun.highlight_color = STAT_DOWN_COLOR;
++        if (prevstun.txt != NULL)
++        {
++            free(prevstun.txt);
++        }
++        if (Stunned)
++        {
++            prevstun.txt = curses_copy_of("Stun");
++        }
++        else
++        {
++            prevstun.txt = NULL;
++        }
++        if (prevstun.value == 0)
++        {
++            prevstun.highlight_turns = 5;
++	    }
++        prevstun.value = Stunned;
++	}
++
++    if (prevstun.label != NULL)
++    {
++        mvwaddstr(win, sy, sx, prevstun.label);
++        sx += strlen(prevstun.label);
++    }
++
++    if (prevstun.txt != NULL)
++    {
++        if (prevstun.highlight_turns > 0)
++        {
++            curses_toggle_color_attr(win, prevstun.highlight_color, NONE, ON);
++            mvwaddstr(win, sy, sx, prevstun.txt);
++            curses_toggle_color_attr(win, prevstun.highlight_color, NONE, OFF);
++        }
++        else
++        {
++            mvwaddstr(win, sy, sx, prevstun.txt);
++        }
++    }
++
++    if (prevstun.txt != NULL)
++    {
++        if (horiz)
++        {
++            sx += strlen(prevstun.txt) + 1;
++        }
++        else
++        {
++            sx = sx_start;
++            sy++;
++        }
++    }
++
++    /* Hallucination */
++    if (Hallucination != prevhallu.value)
++	{
++	    prevhallu.highlight_color = STAT_DOWN_COLOR;
++        if (prevhallu.txt != NULL)
++        {
++            free(prevhallu.txt);
++        }
++        if (Hallucination)
++        {
++            prevhallu.txt = curses_copy_of("Hallu");
++        }
++        else
++        {
++            prevhallu.txt = NULL;
++        }
++        if (prevhallu.value == 0)
++        {
++            prevhallu.highlight_turns = 5;
++	    }
++        prevhallu.value = Hallucination;
++	}
++
++    if (prevhallu.label != NULL)
++    {
++        mvwaddstr(win, sy, sx, prevhallu.label);
++        sx += strlen(prevhallu.label);
++    }
++
++    if (prevhallu.txt != NULL)
++    {
++        if (prevhallu.highlight_turns > 0)
++        {
++            curses_toggle_color_attr(win, prevhallu.highlight_color, NONE, ON);
++            mvwaddstr(win, sy, sx, prevhallu.txt);
++            curses_toggle_color_attr(win, prevhallu.highlight_color, NONE, OFF);
++        }
++        else
++        {
++            mvwaddstr(win, sy, sx, prevhallu.txt);
++        }
++    }
++
++    if (prevhallu.txt != NULL)
++    {
++        if (horiz)
++        {
++            sx += strlen(prevhallu.txt) + 1;
++        }
++        else
++        {
++            sx = sx_start;
++            sy++;
++        }
++    }
++
++    /* Sick */
++    if (Sick != prevsick.value)
++	{
++	    prevsick.highlight_color = STAT_DOWN_COLOR;
++        if (prevsick.txt != NULL)
++        {
++            free(prevsick.txt);
++        }
++        if (Sick)
++        {
++            if (u.usick_type & SICK_VOMITABLE)
++            {
++                prevsick.txt = curses_copy_of("FoodPois");
++            }
++            else      
++            {
++                prevsick.txt = curses_copy_of("Ill");
++            }
++        }
++        else
++        {
++            prevsick.txt = NULL;
++        }
++        if (prevsick.value == 0)
++        {
++            prevsick.highlight_turns = 5;
++	    }
++        prevsick.value = Sick;
++	}
++
++    if (prevsick.label != NULL)
++    {
++        mvwaddstr(win, sy, sx, prevsick.label);
++        sx += strlen(prevsick.label);
++    }
++
++    if (prevsick.txt != NULL)
++    {
++        if (prevsick.highlight_turns > 0)
++        {
++            curses_toggle_color_attr(win, prevsick.highlight_color, NONE, ON);
++            mvwaddstr(win, sy, sx, prevsick.txt);
++            curses_toggle_color_attr(win, prevsick.highlight_color, NONE, OFF);
++        }
++        else
++        {
++            mvwaddstr(win, sy, sx, prevsick.txt);
++        }
++    }
++
++    if (prevsick.txt != NULL)
++    {
++        if (horiz)
++        {
++            sx += strlen(prevsick.txt) + 1;
++        }
++        else
++        {
++            sx = sx_start;
++            sy++;
++        }
++    }
++
++    /* Slime */
++    if (Slimed != prevslime.value)
++	{
++	    prevslime.highlight_color = STAT_DOWN_COLOR;
++        if (prevslime.txt != NULL)
++        {
++            free(prevslime.txt);
++        }
++        if (Slimed)
++        {
++            prevslime.txt = curses_copy_of("Slime");
++        }
++        else
++        {
++            prevslime.txt = NULL;
++        }
++        if (prevslime.value == 0)
++        {
++            prevslime.highlight_turns = 5;
++	    }
++        prevslime.value = Slimed;
++	}
++
++    if (prevslime.label != NULL)
++    {
++        mvwaddstr(win, sy, sx, prevslime.label);
++        sx += strlen(prevslime.label);
++    }
++
++    if (prevslime.txt != NULL)
++    {
++        if (prevslime.highlight_turns > 0)
++        {
++            curses_toggle_color_attr(win, prevslime.highlight_color, NONE, ON);
++            mvwaddstr(win, sy, sx, prevslime.txt);
++            curses_toggle_color_attr(win, prevslime.highlight_color, NONE, OFF);
++        }
++        else
++        {
++            mvwaddstr(win, sy, sx, prevslime.txt);
++        }
++    }
++
++    if (prevslime.txt != NULL)
++    {
++        if (horiz)
++        {
++            sx += strlen(prevslime.txt) + 1;
++        }
++        else
++        {
++            sx = sx_start;
++            sy++;
++        }
++    }
++
++    /* Encumberance */
++    enc = near_capacity();
++    
++    if (enc != prevencumb.value)
++	{
++	    if (enc < prevencumb.value)
++	    {
++	        prevencumb.highlight_color = STAT_UP_COLOR;
++	    }
++	    else
++	    {
++	        prevencumb.highlight_color = STAT_DOWN_COLOR;
++        }
++        if (prevencumb.txt != NULL)
++        {
++            free(prevencumb.txt);
++        }
++        if (enc > UNENCUMBERED)
++        {
++            sprintf(buf, "%s", enc_stat[enc]);
++            prevencumb.txt = curses_copy_of(buf);
++            prevencumb.highlight_turns = 5;
++        }
++        else
++        {
++            prevencumb.txt = NULL;
++        }
++        prevencumb.value = enc;
++	}
++
++    if (prevencumb.label != NULL)
++    {
++        mvwaddstr(win, sy, sx, prevencumb.label);
++        sx += strlen(prevencumb.label);
++    }
++
++    if (prevencumb.txt != NULL)
++    {
++        if (prevencumb.highlight_turns > 0)
++        {
++            curses_toggle_color_attr(win, prevencumb.highlight_color, NONE, ON);
++            mvwaddstr(win, sy, sx, prevencumb.txt);
++            curses_toggle_color_attr(win, prevencumb.highlight_color, NONE, OFF);
++        }
++        else
++        {
++            mvwaddstr(win, sy, sx, prevencumb.txt);
++        }
++    }
++
++    if (prevencumb.txt != NULL)
++    {
++        if (horiz)
++        {
++            sx += strlen(prevencumb.txt) + 1;
++        }
++        else
++        {
++            sx = sx_start;
++            sy++;
++        }
++    }
++
++    wrefresh(win);
++}
++
++
++/* Decrement the highlight_turns for all stats.  Call curses_update_stats
++if needed to unhighlight a stat */
++
++void curses_decrement_highlight()
++{
++    boolean unhighlight = FALSE;
++    
++    if (prevname.highlight_turns > 0)
++    {
++        prevname.highlight_turns--;
++        if (prevname.highlight_turns == 0)
++        {
++            unhighlight = TRUE;
++        }
++    }
++    if (prevdepth.highlight_turns > 0)
++    {
++        prevdepth.highlight_turns--;
++        if (prevdepth.highlight_turns == 0)
++        {
++            unhighlight = TRUE;
++        }
++    }
++    if (prevstr.highlight_turns > 0)
++    {
++        prevstr.highlight_turns--;
++        if (prevstr.highlight_turns == 0)
++        {
++            unhighlight = TRUE;
++        }
++    }
++    if (prevint.highlight_turns > 0)
++    {
++        prevint.highlight_turns--;
++        if (prevint.highlight_turns == 0)
++        {
++            unhighlight = TRUE;
++        }
++    }
++    if (prevwis.highlight_turns > 0)
++    {
++        prevwis.highlight_turns--;
++        if (prevwis.highlight_turns == 0)
++        {
++            unhighlight = TRUE;
++        }
++    }
++    if (prevdex.highlight_turns > 0)
++    {
++        prevdex.highlight_turns--;
++        if (prevdex.highlight_turns == 0)
++        {
++            unhighlight = TRUE;
++        }
++    }
++    if (prevcon.highlight_turns > 0)
++    {
++        prevcon.highlight_turns--;
++        if (prevcon.highlight_turns == 0)
++        {
++            unhighlight = TRUE;
++        }
++    }
++    if (prevcha.highlight_turns > 0)
++    {
++        prevcha.highlight_turns--;
++        if (prevcha.highlight_turns == 0)
++        {
++            unhighlight = TRUE;
++        }
++    }
++    if (prevalign.highlight_turns > 0)
++    {
++        prevalign.highlight_turns--;
++        if (prevalign.highlight_turns == 0)
++        {
++            unhighlight = TRUE;
++        }
++    }
++    if (prevau.highlight_turns > 0)
++    {
++        prevau.highlight_turns--;
++        if (prevau.highlight_turns == 0)
++        {
++            unhighlight = TRUE;
++        }
++    }
++    if (prevhp.highlight_turns > 0)
++    {
++        prevhp.highlight_turns--;
++        if (prevhp.highlight_turns == 0)
++        {
++            unhighlight = TRUE;
++        }
++    }
++    if (prevmhp.highlight_turns > 0)
++    {
++        prevmhp.highlight_turns--;
++        if (prevmhp.highlight_turns == 0)
++        {
++            unhighlight = TRUE;
++        }
++    }
++    if (prevlevel.highlight_turns > 0)
++    {
++        prevlevel.highlight_turns--;
++        if (prevlevel.highlight_turns == 0)
++        {
++            unhighlight = TRUE;
++        }
++    }
++    if (prevpow.highlight_turns > 0)
++    {
++        prevpow.highlight_turns--;
++        if (prevpow.highlight_turns == 0)
++        {
++            unhighlight = TRUE;
++        }
++    }
++    if (prevmpow.highlight_turns > 0)
++    {
++        prevmpow.highlight_turns--;
++        if (prevmpow.highlight_turns == 0)
++        {
++            unhighlight = TRUE;
++        }
++    }
++    if (prevac.highlight_turns > 0)
++    {
++        prevac.highlight_turns--;
++        if (prevac.highlight_turns == 0)
++        {
++            unhighlight = TRUE;
++        }
++    }
++#ifdef EXP_ON_BOTL
++    if (prevexp.highlight_turns > 0)
++    {
++        prevexp.highlight_turns--;
++        if (prevexp.highlight_turns == 0)
++        {
++            unhighlight = TRUE;
++        }
++    }
++#endif
++    if (prevtime.highlight_turns > 0)
++    {
++        prevtime.highlight_turns--;
++        if (prevtime.highlight_turns == 0)
++        {
++            unhighlight = TRUE;
++        }
++    }
++#ifdef SCORE_ON_BOTL
++    if (prevscore.highlight_turns > 0)
++    {
++        prevscore.highlight_turns--;
++        if (prevscore.highlight_turns == 0)
++        {
++            unhighlight = TRUE;
++        }
++    }
++#endif
++    if (prevhunger.highlight_turns > 0)
++    {
++        prevhunger.highlight_turns--;
++        if (prevhunger.highlight_turns == 0)
++        {
++            unhighlight = TRUE;
++        }
++    }
++    if (prevconf.highlight_turns > 0)
++    {
++        prevconf.highlight_turns--;
++        if (prevconf.highlight_turns == 0)
++        {
++            unhighlight = TRUE;
++        }
++    }
++    if (prevblind.highlight_turns > 0)
++    {
++        prevblind.highlight_turns--;
++        if (prevblind.highlight_turns == 0)
++        {
++            unhighlight = TRUE;
++        }
++    }
++    if (prevstun.highlight_turns > 0)
++    {
++        prevstun.highlight_turns--;
++        if (prevstun.highlight_turns == 0)
++        {
++            unhighlight = TRUE;
++        }
++    }
++    if (prevhallu.highlight_turns > 0)
++    {
++        prevhallu.highlight_turns--;
++        if (prevhallu.highlight_turns == 0)
++        {
++            unhighlight = TRUE;
++        }
++    }
++    if (prevsick.highlight_turns > 0)
++    {
++        prevsick.highlight_turns--;
++        if (prevsick.highlight_turns == 0)
++        {
++            unhighlight = TRUE;
++        }
++    }
++    if (prevslime.highlight_turns > 0)
++    {
++        prevslime.highlight_turns--;
++        if (prevslime.highlight_turns == 0)
++        {
++            unhighlight = TRUE;
++        }
++    }
++    if (prevencumb.highlight_turns > 0)
++    {
++        prevencumb.highlight_turns--;
++        if (prevencumb.highlight_turns == 0)
++        {
++            unhighlight = TRUE;
++        }
++    }
++    
++    if (unhighlight)
++    {
++        curses_update_stats();
++    }
++}
++
++
++/* Initialize the stats with beginning values. */
++
++static void init_stats()
++{
++    char buf[BUFSZ];
++    int count;
++
++    /* Player name and title */
++    strcpy(buf, plname);
++    if ('a' <= buf[0] && buf[0] <= 'z') buf[0] += 'A'-'a';
++    strcat(buf, " the ");
++    if (u.mtimedone) {
++        char mname[BUFSZ];
++        int k = 0;
++
++        strcpy(mname, mons[u.umonnum].mname);
++        while(mname[k] != 0) {
++            if ((k == 0 || (k > 0 && mname[k-1] == ' '))
++             && 'a' <= mname[k] && mname[k] <= 'z')
++            {
++                mname[k] += 'A' - 'a';
++            }
++            k++;
++        }
++        strcat(buf, mname);
++    } else {
++        strcat(buf, rank_of(u.ulevel, pl_character[0], flags.female));
++    }
++
++    prevname.txt = curses_copy_of(buf);
++    prevname.display = TRUE;
++    prevname.highlight_turns = 0;
++    prevname.label = NULL;
++    
++    /* Strength */
++    if (ACURR(A_STR) > 118)
++    {
++        sprintf(buf, "%d", ACURR(A_STR) - 100);
++    }
++    else if (ACURR(A_STR)==118)
++    {
++        sprintf(buf, "18/**");
++    }
++    else if(ACURR(A_STR) > 18)
++    {
++        sprintf(buf, "18/%02d", ACURR(A_STR) - 18);
++    }
++    else
++    {
++        sprintf(buf, "%d", ACURR(A_STR));
++    }
++
++    prevstr.value = ACURR(A_STR);
++    prevstr.txt = curses_copy_of(buf);
++    prevstr.display = TRUE;
++    prevstr.highlight_turns = 0;
++    prevstr.label = curses_copy_of("Str:");
++
++    /* Intelligence */
++    sprintf(buf, "%d", ACURR(A_INT));
++    prevint.value = ACURR(A_INT);
++    prevint.txt = curses_copy_of(buf);
++    prevint.display = TRUE;
++    prevint.highlight_turns = 0;
++    prevint.label = curses_copy_of("Int:");
++
++    /* Wisdom */
++    sprintf(buf, "%d", ACURR(A_WIS));
++    prevwis.value = ACURR(A_WIS);
++    prevwis.txt = curses_copy_of(buf);
++    prevwis.display = TRUE;
++    prevwis.highlight_turns = 0;
++    prevwis.label = curses_copy_of("Wis:");
++
++    /* Dexterity */
++    sprintf(buf, "%d", ACURR(A_DEX));
++    prevdex.value = ACURR(A_DEX);
++    prevdex.txt = curses_copy_of(buf);
++    prevdex.display = TRUE;
++    prevdex.highlight_turns = 0;
++    prevdex.label = curses_copy_of("Dex:");
++
++    /* Constitution */
++    sprintf(buf, "%d", ACURR(A_CON));
++    prevcon.value = ACURR(A_CON);
++    prevcon.txt = curses_copy_of(buf);
++    prevcon.display = TRUE;
++    prevcon.highlight_turns = 0;
++    prevcon.label = curses_copy_of("Con:");
++
++    /* Charisma */
++    sprintf(buf, "%d", ACURR(A_CHA));
++    prevcha.value = ACURR(A_CHA);
++    prevcha.txt = curses_copy_of(buf);
++    prevcha.display = TRUE;
++    prevcha.highlight_turns = 0;
++    prevcha.label = curses_copy_of("Cha:");
++
++    /* Alignment */
++    switch (u.ualign.type)
++    {
++        case A_LAWFUL:
++        {
++            prevalign.txt = curses_copy_of("Lawful");
++            break;
++        }
++        case A_NEUTRAL:
++        {
++            prevalign.txt = curses_copy_of("Neutral");
++            break;
++        }
++        case A_CHAOTIC:
++        {
++            prevalign.txt = curses_copy_of("Chaotic");
++            break;
++        }
++    }
++    
++    prevalign.alignment = u.ualign.type;
++    prevalign.display = TRUE;
++    prevalign.highlight_turns = 0;
++    prevalign.label = NULL;
++    
++    /* Dungeon level */
++    if (In_endgame(&u.uz))
++    {
++        strcpy(buf, (Is_astralevel(&u.uz) ? "Astral Plane":"End Game"));
++    }
++    else
++    {
++        sprintf(buf, "%d", depth(&u.uz));
++    }
++
++    prevdepth.value = depth(&u.uz);
++    prevdepth.txt = curses_copy_of(buf);
++    prevdepth.display = TRUE;
++    prevdepth.highlight_turns = 0;
++    prevdepth.label = curses_copy_of("Dlvl:");
++    
++    /* Gold */
++#ifndef GOLDOBJ
++    sprintf(buf,"%ld", u.ugold);
++    prevau.value = u.ugold;
++#else
++    sprintf(buf,"%ld", money_cnt(invent));
++    prevau.value = money_cnt(invent);
++#endif
++    prevau.txt = curses_copy_of(buf);
++    prevau.display = TRUE;
++    prevau.highlight_turns = 0;
++    sprintf(buf, "%c:", GOLD_SYM);
++    prevau.label = curses_copy_of(buf);
++
++    /* Hit Points */
++    if (u.mtimedone)    /* Currently polymorphed - show monster HP */
++    {
++        prevhp.value = u.mh;
++        sprintf(buf, "%d", u.mh);
++        prevhp.txt = curses_copy_of(buf);
++	}
++	else if (u.uhp != prevhp.value)  /* Not polymorphed */
++	{
++	    prevhp.value = u.uhp;
++        sprintf(buf, "%d", u.uhp);
++        prevhp.txt = curses_copy_of(buf);
++	}
++	prevhp.display = TRUE;
++	prevhp.highlight_turns = 0;
++    prevhp.label = curses_copy_of("HP:");
++
++    /* Max Hit Points */
++    if (u.mtimedone)    /* Currently polymorphed - show monster HP */
++    {
++        prevmhp.value = u.mhmax;
++        sprintf(buf, "%d", u.mhmax);
++        prevmhp.txt = curses_copy_of(buf);
++	}
++	else    /* Not polymorphed */
++	{
++	    prevmhp.value = u.uhpmax;
++        sprintf(buf, "%d", u.uhpmax);
++        prevmhp.txt = curses_copy_of(buf);
++	}
++	prevmhp.display = TRUE;
++	prevmhp.highlight_turns = 0;
++    prevmhp.label = curses_copy_of("/");
++
++    /* Power */
++    prevpow.value = u.uen;
++    sprintf(buf, "%d", u.uen);
++    prevpow.txt = curses_copy_of(buf);
++	prevpow.display = TRUE;
++	prevpow.highlight_turns = 0;
++    prevpow.label = curses_copy_of("Pw:");
++
++    /* Max Power */
++    prevmpow.value = u.uenmax;
++    sprintf(buf, "%d", u.uenmax);
++    prevmpow.txt = curses_copy_of(buf);
++	prevmpow.display = TRUE;
++	prevmpow.highlight_turns = 0;
++    prevmpow.label = curses_copy_of("/");
++
++    /* Armor Class */
++    prevac.value = u.uac;
++    sprintf(buf, "%d", u.uac);
++    prevac.txt = curses_copy_of(buf);
++	prevac.display = TRUE;
++	prevac.highlight_turns = 0;
++    prevac.label = curses_copy_of("AC:");
++
++    /* Experience */
++#ifdef EXP_ON_BOTL
++    prevexp.value = u.uexp;
++    sprintf(buf, "%ld", u.uexp);
++    prevexp.txt = curses_copy_of(buf);
++	prevexp.display = flags.showexp;
++	prevexp.highlight_turns = 0;
++    prevexp.label = curses_copy_of("Xp:");
++#endif
++
++    /* Level */
++    if (u.mtimedone)    /* Currently polymorphed - show monster HP */
++    {
++        prevlevel.value = mons[u.umonnum].mlevel;
++        sprintf(buf, "%d", mons[u.umonnum].mlevel);
++        prevlevel.txt = curses_copy_of(buf);
++        prevlevel.label = curses_copy_of("HD:");
++	}
++	else if (u.ulevel != prevlevel.value)  /* Not polymorphed */
++	{
++	    prevlevel.value = u.ulevel;
++        sprintf(buf, "%d", u.ulevel);
++        prevlevel.txt = curses_copy_of(buf);
++        if (prevexp.display)
++        {
++            prevlevel.label = curses_copy_of("/");
++        }
++        else
++        {    
++            prevlevel.label = curses_copy_of("Lvl:");
++        }
++	}
++	prevlevel.display = TRUE;
++	prevlevel.highlight_turns = 0;
++
++    /* Time */
++    prevtime.value = moves;
++    sprintf(buf, "%ld", moves);
++    prevtime.txt = curses_copy_of(buf);
++	prevtime.display = flags.time;
++	prevtime.highlight_turns = 0;
++    prevtime.label = curses_copy_of("T:");
++
++    /* Score */
++#ifdef SCORE_ON_BOTL
++    prevscore.value = botl_score();
++    sprintf(buf, "%ld", botl_score());
++    prevscore.txt = curses_copy_of(buf);
++	prevscore.display = flags.showscore;
++	prevscore.highlight_turns = 0;
++    prevscore.label = curses_copy_of("S:");
++#endif
++
++    /* Hunger */
++    prevhunger.value = u.uhs;
++    for (count = 0; count < strlen(hu_stat[u.uhs]); count++)
++    {
++        if ((hu_stat[u.uhs][count]) == ' ')
++        {
++            break;
++        }
++        buf[count] = hu_stat[u.uhs][count];
++    }
++
++    buf[count] = '\0';
++    prevhunger.txt = curses_copy_of(buf);
++    prevhunger.display = TRUE;
++    prevhunger.highlight_turns = 0;
++    prevhunger.label = NULL;
++
++    /* Confusion */
++    prevconf.value = Confusion;
++    if (Confusion)
++    {
++        prevconf.txt = curses_copy_of("Conf");
++    }
++    else
++    {
++        prevconf.txt = NULL;
++    }
++    prevconf.display = TRUE;
++    prevconf.highlight_turns = 0;
++    prevconf.label = NULL;
++
++    /* Blindness */
++    prevblind.value = Blind;
++    if (Blind)
++    {
++        prevblind.txt = curses_copy_of("Blind");
++    }
++    else
++    {
++        prevblind.txt = NULL;
++    }
++    prevblind.display = TRUE;
++    prevblind.highlight_turns = 0;
++    prevblind.label = NULL;
++
++    /* Stun */
++    prevstun.value = Stunned;
++    if (Stunned)
++    {
++        prevstun.txt = curses_copy_of("Stun");
++    }
++    else
++    {
++        prevstun.txt = NULL;
++    }
++    prevstun.display = TRUE;
++    prevstun.highlight_turns = 0;
++    prevstun.label = NULL;
++
++    /* Hallucination */
++    prevhallu.value = Hallucination;
++    if (Hallucination)
++    {
++        prevhallu.txt = curses_copy_of("Hallu");
++    }
++    else
++    {
++        prevhallu.txt = NULL;
++    }
++    prevhallu.display = TRUE;
++    prevhallu.highlight_turns = 0;
++    prevhallu.label = NULL;
++
++    /* Sick */
++    prevsick.value = Sick;
++    if (Sick)
++    {
++        if (u.usick_type & SICK_VOMITABLE)
++        {
++            prevsick.txt = curses_copy_of("Sick");
++        }
++        else     
++        {
++            prevsick.txt = curses_copy_of("Ill");
++        }
++    }
++    else
++    {
++        prevsick.txt = NULL;
++    }
++    prevsick.display = TRUE;
++    prevsick.highlight_turns = 0;
++    prevsick.label = NULL;
++
++    /* Slimed */
++    prevslime.value = Slimed;
++    if (Slimed)
++    {
++        prevslime.txt = curses_copy_of("Slime");
++    }
++    else
++    {
++        prevslime.txt = NULL;
++    }
++    prevslime.display = TRUE;
++    prevslime.highlight_turns = 0;
++    prevslime.label = NULL;
++
++    /* Encumberance */
++    prevencumb.value = near_capacity();
++    if (prevencumb.value > UNENCUMBERED)
++    {
++        sprintf(buf, "%s", enc_stat[prevencumb.value]);
++        prevencumb.txt = curses_copy_of(buf);
++    }
++    else
++    {
++        prevencumb.txt = NULL;
++    }
++    prevencumb.display = TRUE;
++    prevencumb.highlight_turns = 0;
++    prevencumb.label = NULL;
++}
++
+diff -burN nethack-3.4.3/win/curses/cursstat.h nethack/win/curses/cursstat.h
+--- nethack-3.4.3/win/curses/cursstat.h	1969-12-31 19:00:00.000000000 -0500
++++ nethack/win/curses/cursstat.h	2009-03-05 13:50:38.000000000 -0500
+@@ -0,0 +1,29 @@
++#ifndef CURSSTAT_H
++#define CURSSTAT_H
++
++
++/* Global declarations */
++
++void curses_update_stats(void);
++
++void curses_decrement_highlight(void);
++
++
++/* Private declarations */
++
++typedef struct nhs
++{
++    long value;
++    char *txt;
++    aligntyp alignment;
++    boolean display;
++    int highlight_turns;
++    int highlight_color;
++    int x;
++    int y;
++    char *label;
++} nhstat;
++
++static void init_stats(void);
++
++#endif  /* CURSSTAT_H */
+diff -burN nethack-3.4.3/win/curses/curswins.c nethack/win/curses/curswins.c
+--- nethack-3.4.3/win/curses/curswins.c	1969-12-31 19:00:00.000000000 -0500
++++ nethack/win/curses/curswins.c	2009-03-11 15:08:53.000000000 -0400
+@@ -0,0 +1,462 @@
++#include "curses.h"
++#include "hack.h"
++#include "wincurs.h"
++#include "curswins.h"
++
++/* Window handling for curses interface */
++
++static nethack_window *nhwins = NULL;  /* NetHack window array */
++
++
++
++/* Create a window with the specified size and orientation */
++
++WINDOW *curses_create_window(int width, int height, orient orientation)
++{
++    int mapx, mapy, maph, mapw = 0;
++    int startx = 0;
++    int starty = 0;
++    WINDOW *win;
++    boolean map_border = FALSE;
++        
++    if ((orientation == UP) || (orientation == DOWN) ||
++     (orientation == LEFT))
++    {
++        map_border = curses_window_has_border(MAP_WIN);
++        curses_get_window_xy(MAP_WIN, &mapx, &mapy);
++        curses_get_window_size(MAP_WIN, &maph, &mapw);
++    }
++    width += 2;    /* leave room for bounding box */
++    height += 2;
++    if ((width > term_cols) || (height > term_rows))
++        panic("curses_create_window: Terminal too small for dialog window");
++    switch (orientation)
++    {
++        case CENTER:
++        {
++            startx = (term_cols / 2) - (width / 2);
++            starty = (term_rows / 2) - (height / 2);
++            break;
++        }
++        case UP:
++        {
++            startx = (mapw / 2) - (width / 2) + mapx;
++            starty = mapy;
++            break;
++        }
++        case DOWN:
++        {
++            startx = (mapw / 2) - (width / 2) + mapx;
++            starty = height - mapy - 1;
++            break;
++        }
++        case LEFT:
++        {
++            if (map_border && (width < term_cols))
++                startx = 1;
++            else
++                startx = 0;
++            starty = term_rows - height;
++            break;
++        }
++        case RIGHT:
++        {
++            startx = term_cols - width;
++            starty = 0;
++            break;
++        }
++        default:
++        {
++            panic("curses_create_window: Bad orientation");
++        }
++    }
++    win = newwin(height, width, starty, startx);
++    curses_toggle_color_attr(win, DIALOG_BORDER_COLOR, NONE, ON);
++    box(win, 0, 0);
++    curses_toggle_color_attr(win, DIALOG_BORDER_COLOR, NONE, OFF);
++    return win;
++}
++
++
++/* Erase and delete curses window, and refresh standard windows */
++
++void curses_destroy_win(WINDOW *win)
++{
++    werase(win);
++    wrefresh(win);
++    delwin(win);
++    curses_refresh_nethack_windows();
++}
++
++
++/* Refresh nethack windows if they exist, or base window if not */
++
++void curses_refresh_nethack_windows()
++{
++    WINDOW *status_window, *message_window;
++    
++    status_window = curses_get_nhwin(STATUS_WIN);
++    message_window = curses_get_nhwin(MESSAGE_WIN);
++    
++    if (!iflags.window_inited)
++    {
++        /* Main windows not yet displayed; refresh base window instead */
++        touchwin(stdscr);
++        refresh();
++    }
++    else
++    {
++        touchwin(status_window);
++        wnoutrefresh(status_window);
++        box(mapborderwin, 0, 0);
++        wrefresh(mapborderwin);
++        touchwin(message_window);
++        wnoutrefresh(message_window);
++        doupdate();
++        refresh_map_window();
++    }
++}
++
++
++/* Return curses window pointer for given NetHack winid */
++
++WINDOW *curses_get_nhwin(winid wid)
++{
++    nethack_window *winptr = nhwins;
++ 
++    while (winptr != NULL)
++    {
++        if (winptr->nhwin == wid)
++            return winptr->curwin;
++        winptr = winptr->next_window;
++    }
++    
++    return NULL;    /* Not found */
++}
++
++
++/* Add curses window pointer and window info to list for given NetHack winid */
++
++void curses_add_nhwin(winid wid, int height, int width, int y, int x,
++  orient orientation, boolean border)
++{
++    WINDOW *win;
++    nethack_window *new_win;
++    nethack_window *winptr = nhwins;
++    int real_width = width;
++    int real_height = height;
++    
++    new_win = malloc(sizeof(nethack_window));
++    new_win->nhwin = wid;
++    new_win->border = border;
++    new_win->width = width;
++    new_win->height = height;
++    new_win->x = x;
++    new_win->y = y;
++    new_win->orientation = orientation;
++    if (border)
++    {
++        real_width += 2;    /* leave room for bounding box */
++        real_height += 2;
++    }
++    new_win->next_window = NULL;
++    if (winptr == NULL)
++    {
++        new_win->prev_window = NULL;
++        nhwins = new_win;
++    }
++    else
++    {
++        while (winptr->next_window != NULL)
++            winptr = winptr->next_window;
++        new_win->prev_window = winptr;
++        winptr->next_window = new_win;
++    }
++    if (wid != MAP_WIN)
++    {
++        win = newwin(real_height, real_width, y, x);
++        if (border)
++        {
++            box(win, 0, 0);
++        }
++    }
++    else
++    {
++        if (border)
++        {
++            box(mapborderwin, 0, 0);
++        }
++        win = newpad(ROWNO, COLNO);
++    }
++    new_win->curwin = win;
++}
++
++
++/* refresh a curses window via given nethack winid */
++
++void curses_refresh_nhwin(winid wid)
++{
++    if (wid != MAP_WIN)
++        wrefresh(curses_get_nhwin(wid));
++    else
++        refresh_map_window();
++}
++
++
++/* Delete curses window via given NetHack winid and remove entry from list */
++
++void curses_del_nhwin(winid wid)
++{
++    nethack_window *tmpwin;
++    nethack_window *winptr = nhwins;
++    
++    if (curses_is_menu(wid) || curses_is_text(wid))
++    {
++        curses_del_menu(wid);
++    }
++    
++    while (winptr != NULL)
++    {
++        if (winptr->nhwin == wid)
++        {
++            if (winptr->prev_window != NULL)
++            {
++                tmpwin = winptr->prev_window;
++                tmpwin->next_window = winptr->next_window;
++            }
++            else
++            {
++                nhwins = winptr->next_window;   /* New head mode, or NULL */
++            }
++            if (winptr->next_window != NULL)
++            {
++                tmpwin = winptr->next_window;
++                tmpwin->prev_window = winptr->prev_window;
++            }
++            free(winptr);
++            break;
++        }
++        winptr = winptr->next_window;
++    }
++}
++
++
++/* Print a single character in the given window at the given coordinates */
++
++void curses_putch(winid wid, int x, int y, int ch, int color, int attr)
++{
++    WINDOW *win;
++    boolean border = curses_window_has_border(wid);
++    
++    if (border && (wid != MAP_WIN))
++    {
++        x++;
++        y++;
++    }
++    win = curses_get_nhwin(wid);
++    curses_toggle_color_attr(win, color, attr, ON);
++#ifdef PDCURSES
++    mvwaddrawch(win, y, x, ch);
++#else
++    mvwaddch(win, y, x, ch);
++#endif
++    if (wid == MAP_WIN)
++    {
++        refresh_map_window();
++    }
++else
++    {
++        wrefresh(win);
++    }
++    
++    curses_toggle_color_attr(win, color, attr, OFF);
++}
++
++
++/* Get x, y coordinates of curses window on the physical terminal window */
++
++void curses_get_window_xy(winid wid, int *x, int *y)
++{
++    nethack_window *winptr = nhwins;
++ 
++    while (winptr != NULL)
++    {
++        if (winptr->nhwin == wid)
++        {
++            *x = winptr->x;
++            *y = winptr->y;
++            break;
++        }
++        winptr = winptr->next_window;
++    }
++}
++
++
++/* Get usable width and height curses window on the physical terminal window */
++
++void curses_get_window_size(winid wid, int *height, int *width)
++{
++    nethack_window *winptr = nhwins;
++ 
++    while (winptr != NULL)
++    {
++        if (winptr->nhwin == wid)
++        {
++            *height = winptr->height;
++            *width = winptr->width;
++            break;
++        }
++        winptr = winptr->next_window;
++    }
++}
++
++
++/* Determine if given window has a visible border */
++
++boolean curses_window_has_border(winid wid)
++{
++    nethack_window *winptr = nhwins;
++ 
++    while (winptr != NULL)
++    {
++        if (winptr->nhwin == wid)
++        {
++            return winptr->border;
++        }
++        winptr = winptr->next_window;
++    }
++}
++
++
++/* Determine if window for given winid exists */
++
++boolean curses_window_exists(winid wid)
++{
++    nethack_window *winptr = nhwins;
++ 
++    while (winptr != NULL)
++    {
++        if (winptr->nhwin == wid)
++        {
++            return TRUE;
++        }
++        winptr = winptr->next_window;
++    }
++    
++    return FALSE;
++}
++
++
++/* Return the orientation of the specified window */
++
++int curses_get_window_orientation(winid wid)
++{
++    nethack_window *winptr = nhwins;
++ 
++    while (winptr != NULL)
++    {
++        if (winptr->nhwin == wid)
++        {
++            return winptr->orientation;
++        }
++        winptr = winptr->next_window;
++    }
++}
++
++
++/* Output a line of text to specified NetHack window with given coordinates
++and text attributes */
++
++void curses_puts(winid wid, int attr, const char *text)
++{
++    anything *identifier;
++    WINDOW *win = curses_get_nhwin(wid);
++    
++    curses_toggle_color_attr(win, NONE, attr, ON);
++    if (wid == MESSAGE_WIN)
++    {
++        curses_message_win_puts(text, FALSE);
++        return;
++    }
++    
++    if (wid == STATUS_WIN)
++    {
++        curses_update_stats();  /* We will do the write ourselves */
++        return;
++    }
++    
++    if (curses_is_menu(wid) || curses_is_text(wid))
++    {
++        if (!curses_menu_exists(wid))
++        {
++            panic("curses_puts: Attempted write to nonexistant window!"); 
++        }
++        identifier = malloc(sizeof(anything));
++        identifier->a_void = NULL;
++        curses_add_menu(wid, NO_GLYPH, identifier, 0, 0, attr, text,
++         FALSE);
++    }
++    else
++    {
++        waddstr(win, text);
++        wrefresh(win);
++    }
++    curses_toggle_color_attr(win, NONE, attr, OFF);
++}
++
++
++/* Clear the contents of a window via the given NetHack winid */
++
++void curses_clear_nhwin(winid wid)
++{
++    WINDOW *win = curses_get_nhwin(wid);
++    boolean border = curses_window_has_border(wid);
++    
++    werase(win);
++    if (border && (wid != MAP_WIN))
++        box(win, 0, 0);
++    if (wid != MAP_WIN)
++    {
++        wrefresh(win);
++    }
++    else
++    {
++        refresh_map_window();
++    }
++}
++
++
++/* Refresh visible portion of map window */
++
++static void refresh_map_window()
++{
++    int mapwinx, mapwiny, maph, mapw, mapwinw, mapwinh, mapx, mapy;
++    WINDOW *map_window = curses_get_nhwin(MAP_WIN);
++    boolean border = curses_window_has_border(MAP_WIN);
++    
++    curses_get_window_xy(MAP_WIN, &mapwinx, &mapwiny);
++    curses_get_window_size(MAP_WIN, &mapwinh, &mapwinw);
++    maph = ROWNO;
++    mapw = COLNO;
++    mapx = u.ux - (mapwinw / 2);
++    if ((mapx + mapwinw) > mapw)
++    {
++        mapx = mapw - mapwinw;
++    }
++    if (mapx < 0)
++    {
++        mapx = 0;
++    }
++    mapy = u.uy - (mapwinh / 2);
++    if ((mapy + mapwinh) > maph)
++    {
++        mapy = maph - mapwinh;
++    }
++    if (mapy < 0)
++    {
++        mapy = 0;
++    }
++    prefresh(map_window, mapy, mapx, mapwiny, mapwinx, mapwiny + mapwinh - 1, 
++     mapwinx + mapwinw - 1);
++}
++
+diff -burN nethack-3.4.3/win/curses/curswins.h nethack/win/curses/curswins.h
+--- nethack-3.4.3/win/curses/curswins.h	1969-12-31 19:00:00.000000000 -0500
++++ nethack/win/curses/curswins.h	2009-03-05 13:50:38.000000000 -0500
+@@ -0,0 +1,55 @@
++#ifndef CURSWIN_H
++#define CURSWIN_H
++
++
++/* Global declarations */
++
++WINDOW *curses_create_window(int width, int height, orient orientation);
++
++void curses_destroy_win(WINDOW *win);
++
++void curses_refresh_nethack_windows(void);
++
++WINDOW *curses_get_nhwin(winid wid);
++
++void curses_add_nhwin(winid wid, int height, int width, int y, int x,
++ orient orientation, boolean border);
++
++void curses_refresh_nhwin(winid wid);
++
++void curses_del_nhwin(winid wid);
++
++void curses_putch(winid wid, int x, int y, int ch, int color, int attrs);
++
++void curses_get_window_xy(winid wid, int *x, int *y);
++
++boolean curses_window_has_border(winid wid);
++
++boolean curses_window_exists(winid wid);
++
++int curses_get_window_orientation(winid wid);
++
++void curses_puts(winid wid, int attr, const char *text);
++
++void curses_clear_nhwin(winid wid);
++
++
++/* Private declarations */
++
++typedef struct nhw
++{
++    winid nhwin;  /* NetHack window id */
++    WINDOW *curwin; /* Curses window pointer */
++    int width;  /* Usable width not counting border */
++    int height; /* Usable height not counting border */
++    int x;  /* start of window on terminal (left) */
++    int y;  /* start of window on termial (top) */
++    int orientation;    /* Placement of window relative to map */
++    boolean border; /* Whether window has a visible border */
++    struct nhw *prev_window;    /* Pointer to previous entry */
++    struct nhw *next_window;    /* Pointer to next entry */
++} nethack_window;
++
++static void refresh_map_window(void);
++
++#endif  /* CURSWIN_H */
+diff -burN nethack-3.4.3/win/curses/Readme.txt nethack/win/curses/Readme.txt
+--- nethack-3.4.3/win/curses/Readme.txt	1969-12-31 19:00:00.000000000 -0500
++++ nethack/win/curses/Readme.txt	2009-03-05 13:50:38.000000000 -0500
+@@ -0,0 +1,116 @@
++INTRO
++=====
++
++The "curses" windowport is a new text-based interface for NetHack,
++using high-level curses routines to control the display.  Currently, it
++has been compiled and tested on Linux and Windows, but it should also
++be portable to a number of other systems, such as other forms of UNIX,
++Mac OS X, MSDOS, and OS/2.
++
++Some features of this interface compared to the traditional tty
++interface include:
++
++ * Dynamic window resizing (e.g. maximizing a terminal window)
++ * Dynamic configurable placement of status and message windows,
++ relative to the map
++ * Makes better use of larger terminal windows
++ * Fancier display (e.g. window borders, optional popup dialogs)
++ * "cursesgraphics" option for fancier line-drawing characters for
++ drawing the dungeon - this should work on most terminals/platforms
++
++
++BUILDING
++========
++
++As of this writing code has been compiled on Linux and Windows.
++
++UNIX/Linux build instructions: Follow the instructions in
++sys/unix/Install.unx.  By default, the Makefile is setup to compile
++against ncurses.  Edit Makefile.src if you wish to compile against a
++different curses library, such as PDCurses for SDL.
++
++Windows build instructions: If you are using Mingw32 as your compiler,
++then follow the instructions in sys/winnt/Install.nt with the following
++changes:
++
++ * After running nhsetup, manually copy the file cursmake.gcc to the
++ src/ subdirectory
++ * Instead of typing "mingw32-make -f Makefile.gcc install" you will
++ type "mingw32-make -f cursmake.gcc install"
++
++If you are using a different compiler, you will have to manually modify
++the appropriate Makefile to include the curses windowport files.
++
++
++GAMEPLAY
++========
++
++Gameplay should be similar to the tty interface for NetHack; the 
++differences are primarily visual.  This windowport supports dymanic
++resizing of the terminal window, so you can play with it to see how it
++looks best to you during a game.  Also, the align_status and
++align_message options may be set during the game, so you can experiment
++to see what arraingement looks best to you.
++
++For menus, in addition to the normal configurable keybindings for menu
++navigation descrived in the Guidebook, you can use the right and left
++arrows to to forward or backward one page, respectively, and the home
++and end keys to go to the first and last pages, respectively.
++
++Some configuration options that are specific to or relevant to the
++curses windowport are shown below.  Copy any of these that you like to
++your nethack configuration file (e.g. .nethackrc for UNIX or
++NetHack.cnf for Windows):
++#
++# Use this if the binary was compiled with multiple window interfaces,
++# and curses is not the default
++OPTIONS=windowtype:curses
++#
++# Set this for Windows systems, or for PDCurses for SDL on any system.
++# The latter uses a cp437 font, which works with this option
++#OPTIONS=IBMgraphics
++#
++# Set this if IBMgraphics above won't work for your system.  Mutually
++# exclusive with the above option, and should work on nearly any
++# system.
++OPTIONS=cursesgraphics
++#
++# Optionally specify the alignment of the message and status windows
++# relative to the map window.  If not specified, the code will default
++# to the locations used in the tty interface: message window on top,
++# and status window on bottom.  Placing either of these on the right or
++# left really only works well for winder terminal windows.
++OPTIONS=align_message:bottom,align_status:right
++#
++# Use a small popup "window" for short prompts, e.g. "Really save?".
++# If this is not set, the message window will be used for these as is
++# done for the tty interface.
++OPTIONS=popup_dialog
++#
++# Specify the initial window size for NetHack in units of characters.
++# This is supported on PDCurses for SDL as well as PDCurses for
++# Windows.
++OPTIONS=term_cols:110,term_rows:32
++#
++# Controls the usage of window borders for the main NetHack windows
++# (message, map, and status windows).  A value of 1 forces the borders
++# to be drawn, a value of 2 forces them to be off, and a value of 3
++# allows the code to decide if they should be drawn based on the size
++# of the terminal window.
++OPTIONS=windowborders:3
++
++
++CONTACT
++=======
++
++Please send any bug reports, suggestions, patches, or miscellaneous
++feedback to me (Karl Garrison) at: kgarrison@pobox.com.  Note that as
++of this writing, I only have sporatic Internet access, so I may not get
++back to you right away.
++
++Happy Hacking!
++
++Karl Garrison
++March, 2009
++
++
+diff -burN nethack-3.4.3/win/curses/Todo.txt nethack/win/curses/Todo.txt
+--- nethack-3.4.3/win/curses/Todo.txt	1969-12-31 19:00:00.000000000 -0500
++++ nethack/win/curses/Todo.txt	2009-03-11 14:32:27.000000000 -0400
+@@ -0,0 +1,146 @@
++Below are some things I would like to see
++
++NETHACK INTERFACE
++=================
++
++(These are the functions in cursmain.c called by the core NetHack code)
++
++ * Implement curses_rip for optional fancier color tombstone, as well
++ as one that will display correctly on smaller terminals.
++ 
++ * I am confused as to how mark_synch, wait_synch, and delay_output
++ should work.  Help, please?
++ 
++ * Both PDCurses and Ncurses have mouse support, so the poskey function
++ could probably be implemented easily enough.
++ 
++ * raw_print is supposed to be able to work before the windowing system
++ has been initialized, as well as after, so I am unsure if curses
++ functions should be used here.  Maybe check to see if initscr() has
++ been called, and use curses functions if so, and call initscr() from
++ there is not?  Right now it is just a call to puts() with no support
++ for bold text.
++
++
++DISPLAY
++=======
++
++ * Consolidate refreshes of the display for smoother output.
++
++ * Horizontal scrollbar to show position for displays < 80 columns.
++ 
++ * Calls to getch() should probably be turned into wgetch() for the
++ appropriate window.  This causes quirty cursor behavior under
++ PDCurses, however.
++
++ * Animation effects do not display properly - this could probably be
++ fixed with a correct implementation of the delay_output function.
++
++ * Support option to set forground and background colors for individual
++ windows
++
++
++MENUS
++=====
++
++(cursdial.c)
++
++ * Menus need to be able to accept a count as input, e.g. to specifiy
++ how many items to drop.
++ 
++ * Currently the "preselected" flag for an individual menu item is
++ ignored.  This should eventually be implemented.
++ 
++ * Menus probably should never overlap with the message window, since
++ the user sometmes needs to be able to see the messages while the menu
++ is active, e.g. when identifying multiple items one at a time.
++ 
++ * Perhaps allow for keyboard navigation of individual items, e.g.
++ using the up and down arrows to move among the selectable items, and
++ selecting individual items with the spacebar.  Perhaps the tab key
++ could jump to the first selectable item after the next heading, and
++ shift-tab could jump to the first item of the previous heading.
++
++
++MESSAGE WINDOW
++==============
++
++(cursmesg.c)
++
++ * Hitting Esc at the more prompt (which is '>>' for the curses
++ interface) should suppress the display of any further messages for
++ that turn like the tty interface does.
++
++
++MAP WINDOW
++==========
++
++(curswins.c)
++
++ * The map window would probably benefit from a total redesign.  Right
++ now, it uses a pad instead of a regular curses window, which causes a
++ number of special cases in the code to account for it, and a seperate
++ window behind it just to draw the border.  It feels kludgy and
++ annoying!
++
++
++STATUS WINDOW
++=============
++
++(cursstat.c)
++
++ * If the status window is on the right or left, then we have much more
++ room to work with for each item horizontally.  Expand out some of the
++ labels for clarity.  We can also list the current dungeon (e.g.
++ Gnomish Mines) and perhaps show thermometer bars for hit points and
++ magical power.
++ 
++ * Conversely, if we have a narrower dislay, compress some of the
++ labels to save space, and do not display some items that never or
++ rarely change (e.g. name, level and title, and alignment).  Perhaps
++ display changes to these fields in the message window if they do
++ happen to change (e.g. converting to a new alignment).
++ 
++ * Maybe add some configuration options for what colors are used and
++ the like.
++
++OTHER DIALOGS
++=============
++
++(cursdial.c)
++
++ * curses_yn_function needs to accept a count if a '#' is present in
++ choices string.
++ 
++ * Extended commands should be enterable letter-by-letter via a '#'
++ prompt if user does not have the extmenu command set to TRUE.
++ 
++ * Character selection should allow for a random selection of any or
++ all choices.
++
++
++OTHER PLATFORMS
++===============
++
++ * PDCurses also work on DOS and OS/2.  PDCurses for SDL and ncurses
++ exist for Mac OS X.  Porting the curses interface to these platforms
++ should not be too difficult.
++
++
++MISC
++====
++
++ * Update documentation and in-game help to describe the newly-added
++ options: cursesgraphics, term_rows, term_cols, and windowborders.
++
++ * Recognize "Alt" key in a platform-independant way to allow its use
++ to select extended commands.  Currently this works for PDCurses.  For
++ Ncurses, the Alt key works in an xterm or rxvt if the -meta8 flag is
++ passed, but I'd like to see a general way of detecting it.
++ 
++ * PDCurses has a function named "addrawch" to output the visual
++ representation of a control character to the screen without having the
++ control character affect the display otherwise.  I would like to find
++ a way to accomplish the same thing via Ncurses to e.g. be able to use
++ a font like nh10 with the correct symbol mappings in an xterm or the
++ like.
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/README.statuscolors nethack/README.statuscolors
--- nh_orig/README.statuscolors	1969-12-31 19:00:00.000000000 -0500
+++ nethack/README.statuscolors	2007-12-27 09:01:28.000000000 -0500
@@ -0,0 +1,62 @@
+Statuscolors is a patch for Nethack (version 3.4.3) that attempts to generalize
+the hpmon patch to be more like the menucolor patch. As of v1.2, the
+statuscolors patch may be applied after the menucolor patch (but not before
+it). Unlike menucolor, it does not use regexps. Instead, it provides the
+following options:
+
+To enable statuscolors:
+    OPTIONS=statuscolors
+
+To specify statuscolor options, write:
+    STATUSCOLOR=<option>,<option>
+
+Numeric options have the format <field>%<max-percent>:<color-option>. For
+example:
+    STATUSCOLOR=hp%15:red&bold,pw%100=green
+
+Text options have the format <text>:<color-option>. Text is case-insensitive.
+For example:
+    STATUSCOLOR=hallu:orange,foodpois:red&inverse&blink
+
+A color option is a <color> followed by an optional sequence of &<attr>. Color
+and attribute names are case insensitive. Valid colors are:
+    black blue brown cyan gray green lightblue lightcyan lightgreen
+    lightmagenta magenta none orange red white yellow
+
+Valid attributes are:
+    blink bold dim inverse none underline
+
+A reasonable set of defaults might be:
+    # HP
+    STATUSCOLOR=hp%100=green,hp%66=yellow,hp%50=orange
+    STATUSCOLOR=hp%33=red&bold,hp%15:red&inverse,hp%0:red&inverse&blink
+    # Pw
+    STATUSCOLOR=pw%100=green,pw%66=yellow,pw%50:orange,pw%33=red&bold
+    # Carry
+    STATUSCOLOR=burdened:yellow,stressed:orange,strained:red&bold
+    STATUSCOLOR=overtaxed:red&inverse,overloaded:red&inverse&blink
+    # Hunger
+    STATUSCOLOR=satiated:yellow,hungry:orange,weak:red&bold
+    STATUSCOLOR=fainting:red&inverse,fainted:red&inverse&blink
+    # Mental
+    STATUSCOLOR=hallu:yellow,conf:orange,stun:red&bold
+    # Health
+    STATUSCOLOR=ill:red&inverse,foodpois:red&inverse,slime:red&inverse
+    # Other
+    STATUSCOLOR=held:red&inverse,blind:red&inverse
+
+Changelog:
+
+    v1.2:
+      - Menucolor compatibility.
+
+    v1.1:
+      - Fixed several shameful bugs.
+
+    v1.0:
+      - Initial release.
+
+---
+Shachaf & Oren Ben-Kiki
+shachaf+nethack@gmail.com
+nethack-oren@ben-kiki.org
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/shrced.php.txt nethack/shrced.php.txt
--- nh_orig/shrced.php.txt	1969-12-31 19:00:00.000000000 -0500
+++ nethack/shrced.php.txt	2009-11-11 07:37:48.960274338 -0500
@@ -0,0 +1,138 @@
+<?php
+
+$logindb = "/var/lib/dgamelaunch/dgldir/dgamelaunch.db";
+$rcpath = "/var/lib/dgamelaunch/dgldir/rcfiles/";
+$default_rc = "/var/lib/dgamelaunch/default.nethackrc";
+
+/*
+$logindb = '/opt/nethack/nethack.alt.org/dgldir/dgamelaunch.db';
+$rcpath = '/opt/nethack/nethack.alt.org/dgldir/userdata/';
+$default_rc = "/opt/nethack/nethack.alt.org/dgl-default-rcfile.nh343";
+*/
+
+function plr_rcfile($plr)
+{
+  global $rcpath;
+  /*return $rcpath.$plr."/".$plr.".nh343rc";*/
+  return $rcpath.$plr.".nethackrc";
+}
+
+
+function dgl_auth_user($username = NULL, $passwd = NULL)
+{
+  global $logindb;
+  if (!isset($username))
+    $username = $_SERVER['PHP_AUTH_USER'];
+  if (!isset($passwd))
+    $passwd = $_SERVER['PHP_AUTH_PW'];
+
+  if (!isset($username) || !isset($passwd) ||
+      ($username == "") || ($passwd == "")) return 0;
+
+  if (!preg_match("/^[0-9a-zA-Z]+$/", $username)) return 0;
+
+  $passwd_crypt = crypt($passwd, substr($passwd, 0, 2));
+
+  $db = sqlite3_open($logindb);
+
+  $username = strtolower($username);
+
+  $result = sqlite3_query($db, "select * from dglusers where lower(username)='".$username."'");
+
+  $dat = sqlite3_fetch_array($result);
+  sqlite3_query_close($result);
+
+  if (strtolower($dat['username']) == $username && $dat['password'] == $passwd_crypt) return 1;
+  return 0;
+} //dgl_auth_user()
+
+
+function edit_form($plr,$passwd)
+{
+  global $default_rc;
+  $cansave = 1;
+
+  $rcfname = plr_rcfile($plr);
+
+  $fp = @fopen($rcfname, "r");
+  if (!$fp) {
+    $cansave = 0;
+    echo '<P>NOTE: You don\'t seem to have an rcfile. <B>You cannot save these changes.</B> You need to log in to nethack.alt.org first!';
+    $fp = @fopen($default_rc, "r");
+  }
+  /*echo '<P><B>NOTE:</B> If you get warnings that the changes could not be written, please wait an hour.';*/
+
+  echo '<P>For more help, see <A HREF="http://nethack.org/v343/Guidebook.html#_TOCentry_43">the Options-section in The Guidebook</A>';
+  echo ' or see <a href="http://nethack.wikia.com/wiki/Options">this page on the NetHack Wiki</a>.';
+
+  echo '<P><form method="POST" action="'.$_SERVER['PHP_SELF'].'">';
+  echo '<input type="hidden" name="plr" value="'.$plr.'">';
+  echo '<input type="hidden" name="passwd" value="'.$passwd.'">';
+  echo '<textarea name="rcdata" rows=24 cols=80>'; fpassthru($fp); echo '</textarea>';
+  echo '<br>';
+  if ($cansave)
+    echo '<input type="submit" value="Save" name="submit">';
+  echo '<input type="reset">';
+  echo '</form>';
+} //edit_form()
+
+
+function update_rcfile($plr, $passwd)
+{
+  if ($_POST['submit']) {
+    $rcdata = str_replace("\\\"", "\"", $_POST['rcdata']);
+    $rcdata = str_replace("\\'", "'", $rcdata);
+    $rcdata = str_replace("\\\\", "\\", $rcdata);
+    $rcdata = str_replace("\r", "", $rcdata);
+
+    $rcfname = plr_rcfile($plr);
+
+    $fp = @fopen($rcfname, "w");
+    if (!$fp) {
+      echo '<P><em>Could not write rc file. Sorry.</em>';
+    } else {
+      $rcdata = "\n".$rcdata;  // what eats the first empty line away?
+      if (fwrite($fp, $rcdata) === FALSE) {
+        echo '<P><em>There was some error when writing the rc file. Sorry.</em>';
+      } else {
+        echo '<P><em>Your rc file was saved.</em>';
+      }
+      fclose($fp);
+    }
+  }
+} //update_rcfile()
+
+
+
+
+
+print '<html><head></head><body>';
+
+print '<h1>Config file editor</h1>';
+
+if ($_SERVER['REQUEST_METHOD'] == 'POST') {
+  $passwd = $_POST['passwd'];
+  $plr = $_POST['plr'];
+  if (dgl_auth_user($plr, $passwd)) {
+    if ($_POST['submit'] == "Login") {
+      edit_form($plr, $passwd);
+    } else if ($_POST['submit'] == "Save") {
+      update_rcfile($plr, $passwd);
+    }
+  } else {
+    echo '<p>wrong username/password combination.';
+  }
+} else {
+  print '<pre>';
+  print '<form method="post" action="'.$_SERVER['PHP_SELF'].'" name="login">';
+  print 'Username: <input type="text" name="plr">';
+  print "\n";
+  print 'Password: <input type="password" name="passwd">';
+  print '<input type="submit" value="Login" name="submit">';
+  print '</form>';
+  print '</pre>';
+}
+
+print '</body></html>';
+
+?>
\ No newline at end of file
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/src/allmain.c nethack/src/allmain.c
--- nh_orig/src/allmain.c	2003-12-07 18:39:13.000000000 -0500
+++ nethack/src/allmain.c	2010-05-02 09:11:33.831736581 -0400
@@ -25,5 +25,11 @@
 #endif
     int moveamt = 0, wtcap = 0, change = 0;
+	 int regen_frequency;
     boolean didmove = FALSE, monscanmove = FALSE;
+	 /* don't make it obvious when monsters will start speeding up */
+	 int monclock;
+	 int timeout_start = rnd(10000)+15000;
+	 int clock_base = 70000L-timeout_start;
+	 int past_clock;
 
     flags.moonphase = phase_of_the_moon();
@@ -59,4 +65,7 @@
     u.uz0.dlevel = u.uz.dlevel;
     youmonst.movement = NORMAL_SPEED;	/* give the hero some movement points */
+#ifdef WHEREIS_FILE
+	 touch_whereis();
+#endif
 
     for(;;) {
@@ -92,7 +101,49 @@
 			mtmp->movement += mcalcmove(mtmp);
 
-		    if(!rn2(u.uevent.udemigod ? 25 :
-			    (depth(&u.uz) > depth(&stronghold_level)) ? 50 : 70))
+			 /* Vanilla generates a critter every 70-ish turns.
+			  * The rate accelerates to every 50 or so below the Castle,
+			  * and 'round every 25 turns once you've done the Invocation.
+			  *
+			  * We will push it even further.  Monsters post-Invocation
+			  * will almost always appear on the stairs (if present), and 
+			  * much more frequently; this, along with the extra intervene()
+			  * calls, should certainly make it seem like you're wading back
+			  * through the teeming hordes.
+			  *
+			  * Aside from that, a more general clock should be put on things;
+			  * after about 30,000 turns, the frequency rate of appearance
+			  * and (TODO) difficulty of monsters generated will slowly increase until
+			  * it reaches the point it will be at as if you were post-Invocation.
+			  *
+			  * 80,000 turns should be adequate as a target mark for this effect;
+			  * if you haven't ascended in 80,000 turns, you're intentionally
+			  * fiddling around somewhere and will certainly be strong enough
+			  * to handle anything that comes your way, so this won't be 
+			  * dropping newbies off the edge of the planet.  -- DSR 12/2/07
+			  */
+
+			 monclock = 70;
+			 if (u.uevent.udemigod) {
+				 monclock = 10;
+			 } else {
+				 if (depth(&u.uz) > depth(&stronghold_level)) {
+					 monclock = 50;
+				 }
+				 past_clock = moves - timeout_start;
+				 if (past_clock > 0) {
+					 monclock -= past_clock*60/clock_base;
+				 }
+			 }
+			 /* make sure we don't fall off the bottom */
+			 if (monclock < 10) { monclock = 10; }
+
+			 /* TODO: adj difficulty in makemon */
+		    if(!rn2(monclock)) {
+				 if (u.uevent.udemigod && xupstair && rn2(10)) {
+					(void) makemon((struct permonst *)0, xupstair, yupstair, MM_ADJACENTOK);
+				 } else {
 			(void) makemon((struct permonst *)0, 0, 0, NO_MM_FLAGS);
+				 }
+			 }
 
 		    /* calculate how much time passed. */
@@ -113,4 +164,7 @@
 			    /* average movement is 1.33 times normal */
 			    if (rn2(3) != 0) moveamt += NORMAL_SPEED / 2;
+				} else if (Slow) {
+					/* average movement noticeably slower */
+					if (rn2(3) != 0) moveamt -= NORMAL_SPEED / 2;
 			}
 		    }
@@ -207,13 +261,23 @@
 		    }
 
-		    if ((u.uen < u.uenmax) &&
-			((wtcap < MOD_ENCUMBER &&
-			  (!(moves%((MAXULEV + 8 - u.ulevel) *
-				    (Role_if(PM_WIZARD) ? 3 : 4) / 6))))
-			 || Energy_regeneration)) {
+			 /* wizards regen slightly faster than others; energy regeneration is
+			  * faster than both; wizards + energy regeneration (Eye) is fastest of all */
+		    if (u.uen < u.uenmax && wtcap < MOD_ENCUMBER) {
+				if (Energy_regeneration) {
+					regen_frequency = (MAXULEV - (Role_if(PM_WIZARD) ? 5 : 0) - u.ulevel) * (Role_if(PM_WIZARD) ? 2 : 3) / 6;
+				} else {
+					regen_frequency = (MAXULEV + 8 - u.ulevel) * (Role_if(PM_WIZARD) ? 3 : 4) / 6;
+				}
+				/* regen_freq should never hit 0 or negative, but let's cover it here just in case
+				 * since we saw a crash earlier at this line -- this is the only thing it could be */
+				if (regen_frequency < 1) { regen_frequency = 1; }
+				if (!(moves % regen_frequency)) {
 			u.uen += rn1((int)(ACURR(A_WIS) + ACURR(A_INT)) / 15 + 1,1);
-			if (u.uen > u.uenmax)  u.uen = u.uenmax;
+					if (u.uen > u.uenmax) {
+						u.uen = u.uenmax;
+					}
 			flags.botl = 1;
 		    }
+		    }
 
 		    if(!u.uinvulnerable) {
@@ -246,5 +310,5 @@
 				    stop_occupation();
 				else
-				    nomul(0);
+				    nomul(0, 0);
 				if (change == 1) polyself(FALSE);
 				else you_were();
@@ -268,5 +332,5 @@
 			if (!u.udg_cnt) {
 			    intervene();
-			    u.udg_cnt = rn1(200, 50);
+			    u.udg_cnt = rn1(100, 50);
 			}
 		    }
@@ -295,4 +359,22 @@
 	    /******************************************/
 
+		 /* move this here so player can check inventory safely in lava
+		  * but any actual action will cause time to pass */
+		if (u.utrap && u.utraptype == TT_LAVA) {
+			if(!is_lava(u.ux,u.uy))
+				u.utrap = 0;
+			else if (!u.uinvulnerable) {
+				u.utrap -= 1<<8;
+				if (u.utrap < 1<<8) {
+					killer_format = KILLED_BY;
+					killer = "molten lava";
+					You("sink below the surface and die.");
+					done(DISSOLVED);
+				} else if(didmove && !u.umoved) {
+					Norep("You sink deeper into the lava.");
+					u.utrap += rnd(4);
+				}
+			}
+		}
 
 	} /* actual time passed */
@@ -317,4 +399,14 @@
 	    if (vision_full_recalc) vision_recalc(0);	/* vision! */
 	}
+
+#ifdef REALTIME_ON_BOTL
+        if(iflags.showrealtime) {
+            /* Update the bottom line if the number of minutes has
+             * changed */
+            if(get_realtime() / 60 != realtime_data.last_displayed_time / 60)
+                flags.botl = 1;
+        }
+#endif
+  
 	if(flags.botl || flags.botlx) bot();
 
@@ -357,21 +449,4 @@
 		do_vicinity_map();
 
-	if(u.utrap && u.utraptype == TT_LAVA) {
-	    if(!is_lava(u.ux,u.uy))
-		u.utrap = 0;
-	    else if (!u.uinvulnerable) {
-		u.utrap -= 1<<8;
-		if(u.utrap < 1<<8) {
-		    killer_format = KILLED_BY;
-		    killer = "molten lava";
-		    You("sink below the surface and die.");
-		    done(DISSOLVED);
-		} else if(didmove && !u.umoved) {
-		    Norep("You sink deeper into the lava.");
-		    u.utrap += rnd(4);
-		}
-	    }
-	}
-
 #ifdef WIZARD
 	if (iflags.sanity_check)
@@ -403,4 +478,5 @@
 	    }
 	} else if (multi == 0) {
+	    ck_server_admin_msg();
 #ifdef MAIL
 	    ckmailstatus();
@@ -439,5 +515,5 @@
 */
 #ifdef REDO
-		nomul(0);
+		nomul(0, 0);
 		pushch(0);
 #endif
@@ -538,4 +614,17 @@
 	program_state.something_worth_saving++;	/* useful data now exists */
 
+#if defined(RECORD_REALTIME) || defined(REALTIME_ON_BOTL)
+
+        /* Start the timer here */
+        realtime_data.realtime = (time_t)0L;
+
+#if defined(BSD) && !defined(POSIX_TYPES)
+        (void) time((long *)&realtime_data.restoretime);
+#else
+        (void) time(&realtime_data.restoretime);
+#endif
+
+#endif /* RECORD_REALTIME || REALTIME_ON_BOTL */
+
 	/* Success! */
 	welcome(TRUE);
@@ -567,6 +656,6 @@
 	Sprintf(eos(buf), " %s", genders[currentgend].adj);
 
-    pline(new_game ? "%s %s, welcome to NetHack!  You are a%s %s %s."
-		   : "%s %s, the%s %s %s, welcome back to NetHack!",
+    pline(new_game ? "%s %s, welcome to SporkHack!  You are a%s %s %s."
+		   : "%s %s, the%s %s %s, welcome back to SporkHack!",
 	  Hello((struct monst *) 0), plname, buf, urace.adj,
 	  (currentgend && urole.name.f) ? urole.name.f : urole.name.m);
@@ -629,4 +718,31 @@
 #endif
 
+#if defined(REALTIME_ON_BOTL) || defined (RECORD_REALTIME)
+time_t
+get_realtime(void)
+{
+    time_t curtime;
+
+    /* Get current time */
+#if defined(BSD) && !defined(POSIX_TYPES)
+    (void) time((long *)&curtime);
+#else
+    (void) time(&curtime);
+#endif
+
+    /* Since the timer isn't set until the game starts, this prevents us
+     * from displaying nonsense on the bottom line before it does. */
+    if(realtime_data.restoretime == 0) {
+        curtime = realtime_data.realtime;
+    } else {
+        curtime -= realtime_data.restoretime;
+        curtime += realtime_data.realtime;
+    }
+ 
+    return curtime;
+}
+#endif /* REALTIME_ON_BOTL || RECORD_REALTIME */
+
+
 #endif /* OVLB */
 
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/src/apply.c nethack/src/apply.c
--- nh_orig/src/apply.c	2003-12-07 18:39:13.000000000 -0500
+++ nethack/src/apply.c	2009-11-22 07:39:48.196273101 -0500
@@ -16,5 +16,5 @@
 #endif
 STATIC_DCL int FDECL(use_towel, (struct obj *));
-STATIC_DCL boolean FDECL(its_dead, (int,int,int *));
+STATIC_DCL boolean FDECL(its_dead, (int,int,int *,struct obj*));
 STATIC_DCL int FDECL(use_stethoscope, (struct obj *));
 STATIC_DCL void FDECL(use_whistle, (struct obj *));
@@ -27,4 +27,5 @@
 STATIC_DCL void FDECL(use_lamp, (struct obj *));
 STATIC_DCL void FDECL(light_cocktail, (struct obj *));
+STATIC_DCL void FDECL(light_poo, (struct obj *));
 STATIC_DCL void FDECL(use_tinning_kit, (struct obj *));
 STATIC_DCL void FDECL(use_figurine, (struct obj **));
@@ -32,4 +33,5 @@
 STATIC_DCL void FDECL(use_trap, (struct obj *));
 STATIC_DCL void FDECL(use_stone, (struct obj *));
+STATIC_DCL void FDECL(apply_flint, (struct obj *));
 STATIC_PTR int NDECL(set_trap);		/* occupation callback */
 STATIC_DCL int FDECL(use_whip, (struct obj *));
@@ -160,6 +162,7 @@
 /* maybe give a stethoscope message based on floor objects */
 STATIC_OVL boolean
-its_dead(rx, ry, resp)
+its_dead(rx, ry, resp, tobj)
 int rx, ry, *resp;
+struct obj* tobj;
 {
 	struct obj *otmp;
@@ -192,4 +195,28 @@
 	    return TRUE;
 	}
+
+	/* listening to eggs is a little fishy, but so is stethoscopes detecting alignment
+	 * The overcomplex wording is because all the monster-naming functions operate
+	 * on actual instances of the monsters, and we're dealing with just an index
+	 * so we can avoid things like "a owlbear", etc. */
+	if (otmp = sobj_at(EGG,rx,ry)) {
+		if (Hallucination) {
+			pline("You listen to the egg and guess... %s?",rndmonnam());
+		} else {
+			if (stale_egg(otmp) || otmp->corpsenm == NON_PM) {
+				pline("The egg doesn't make much noise at all.");
+			} else {
+				pline("You listen to the egg and guess... %s?",mons[otmp->corpsenm].mname);
+			}
+		}
+		return TRUE;
+	}
+
+	/* using a stethoscope on a safe?  You safe-cracker, you. */
+	if (otmp = sobj_at(IRON_SAFE,rx,ry)) {
+		pick_lock(tobj,rx,ry);
+		return TRUE;
+	}
+
 	return FALSE;
 }
@@ -250,5 +277,5 @@
 		    You_cant("reach the %s.",
 			(u.dz > 0) ? surface(u.ux,u.uy) : ceiling(u.ux,u.uy));
-		else if (its_dead(u.ux, u.uy, &res))
+		else if (its_dead(u.ux, u.uy, &res, obj))
 		    ;	/* message already given */
 		else if (Is_stronghold(&u.uz))
@@ -303,5 +330,5 @@
 	}
 
-	if (!its_dead(rx, ry, &res))
+	if (!its_dead(rx, ry, &res, obj))
 	    You("hear nothing special.");	/* not You_hear()  */
 	return res;
@@ -562,6 +589,5 @@
 		    ;	/* still close enough */
 		} else if (otmp->cursed && !breathless(mtmp->data)) {
-		    if (um_dist(mtmp->mx, mtmp->my, 5) ||
-			    (mtmp->mhp -= rnd(2)) <= 0) {
+		    if (um_dist(mtmp->mx, mtmp->my, 5) || damage_mon(mtmp,rnd(2),AD_PHYS)) {
 			long save_pacifism = u.uconduct.killer;
 
@@ -625,5 +651,5 @@
 			      "Yow!  The mirror stares back!" :
 			      "Yikes!  You've frozen yourself!");
-			nomul(-rnd((MAXULEV+6) - u.ulevel));
+			nomul(-rnd((MAXULEV+6) - u.ulevel), "gazing into a mirror");
 			} else You("stiffen momentarily under your gaze.");
 		    } else if (youmonst.data->mlet == S_VAMPIRE)
@@ -789,5 +815,5 @@
 			case 2: /* no explanation; it just happens... */
 				nomovemsg = "";
-				nomul(-rnd(2));
+				nomul(-rnd(2), 0);
 				break;
 		}
@@ -895,5 +921,5 @@
 			(Blind ? "." : " brightly!"));
 	}
-	if (!invocation_pos(u.ux, u.uy)) {
+	if (!invocation_pos(u.ux, u.uy) && u.uevent.invoked) {
 		pline_The("%s %s being rapidly consumed!", s, vtense(s, "are"));
 		obj->age /= 2;
@@ -910,4 +936,34 @@
 }
 
+
+STATIC_OVL void
+light_poo(obj)
+struct obj* obj;
+{
+	char buf[BUFSZ];
+
+	makeknown(obj->otyp);
+	if(Underwater) {
+		pline("Not even -that- will burn here.");
+		return;
+	}
+	if(obj->lamplit) {
+		You("snuff out %s and breathe a little more deeply.", yname(obj));
+		BStealth = 0;
+		end_burn(obj, TRUE);
+		return;
+	}
+	if (obj->age == 0) {
+		pline("This %s is (mostly) empty; what's left won't burn anymore.", xname(obj));
+		return;
+	}
+	check_unpaid(obj);
+	pline("%s %s burns with a dim flame and vile stench.", Shk_Your(buf, obj), xname(obj));
+	begin_burn(obj, FALSE);
+	BStealth = (size_t)obj;
+
+}
+
+
 STATIC_OVL void
 use_candle(optr)
@@ -1009,5 +1065,6 @@
 	if (obj->lamplit) {
 	    if (obj->otyp == OIL_LAMP || obj->otyp == MAGIC_LAMP ||
-		    obj->otyp == BRASS_LANTERN || obj->otyp == POT_OIL) {
+		    obj->otyp == BRASS_LANTERN || obj->otyp == POT_OIL ||
+			 obj->otyp == BAG_OF_POO) {
 		(void) get_obj_location(obj, &x, &y, 0);
 		if (obj->where == OBJ_MINVENT ? cansee(x,y) : !Blind)
@@ -1359,7 +1416,12 @@
 
 	    teleds(cc.x, cc.y, TRUE);
-	    nomul(-1);
+	    nomul(-1, "jumping around");
 	    nomovemsg = "";
+		 /* Knights get it for cheaper */
+		 if (Role_if(PM_KNIGHT)) {
+			 morehungry(rnd(10));
+		 } else {
 	    morehungry(rnd(25));
+		 }
 	    return 1;
 	}
@@ -1447,8 +1509,16 @@
 {
 #define PROP_COUNT 6		/* number of properties we're dealing with */
-#define ATTR_COUNT (A_MAX*3)	/* number of attribute points we might fix */
+#define ATTR_COUNT 0	 	/* number of attribute points we might fix */
+
+	/* Changing this to 0 is going to cause people's hair to stand on end.
+	 * The problem is, the spellbook and potion of restore ability are
+	 * absolutely junk at the moment, because the unicorn horn handles 
+	 * it all.  So we can fix that; let the unicorn horn handle
+	 * transitional troubles, and make the player find restore ability
+	 * potions and whatnot for stat abuse/stat drop.  -- DSR 12/02/07 */
+
 	int idx, val, val_limit,
-	    trouble_count, unfixable_trbl, did_prop, did_attr;
-	int trouble_list[PROP_COUNT + ATTR_COUNT];
+	    trouble_count, unfixable_trbl, did_prop;
+	int trouble_list[PROP_COUNT];
 
 	if (obj && obj->cursed) {
@@ -1484,5 +1554,5 @@
 #define attr_trouble(Y) trouble_list[trouble_count++] = attr2trbl(Y)
 
-	trouble_count = unfixable_trbl = did_prop = did_attr = 0;
+	trouble_count = unfixable_trbl = did_prop = 0;
 
 	/* collect property troubles */
@@ -1496,4 +1566,7 @@
 	unfixable_trbl = unfixable_trouble_count(TRUE);
 
+#if 0
+	/*... don't need to fix these anymore */
+
 	/* collect attribute troubles */
 	for (idx = 0; idx < A_MAX; idx++) {
@@ -1509,4 +1582,5 @@
 	    unfixable_trbl += (AMAX(idx) - val_limit);
 	}
+#endif
 
 	if (trouble_count == 0) {
@@ -1563,4 +1637,5 @@
 		break;
 	    default:
+#if 0
 		if (idx >= 0 && idx < A_MAX) {
 		    ABASE(idx) += 1;
@@ -1568,16 +1643,22 @@
 		} else
 		    panic("use_unicorn_horn: bad trouble? (%d)", idx);
+#endif
 		break;
 	    }
 	}
 
+#if 0
 	if (did_attr)
 	    pline("This makes you feel %s!",
 		  (did_prop + did_attr) == (trouble_count + unfixable_trbl) ?
 		  "great" : "better");
-	else if (!did_prop)
+	else
+#endif
+
+	if (!did_prop)
 	    pline("Nothing seems to happen.");
 
-	flags.botl = (did_attr || did_prop);
+	flags.botl = (did_prop);
+
 #undef PROP_COUNT
 #undef ATTR_COUNT
@@ -1703,5 +1784,5 @@
 		if (!quietly)
 		    You("cannot place a figurine in %s!",
-			IS_TREE(levl[x][y].typ) ? "a tree" : "solid rock");
+			IS_TREE(levl[x][y].typ) ? christmas() ? "a christmas tree" : "a tree" : "solid rock");
 		return FALSE;
 	}
@@ -1832,4 +1913,49 @@
 }
 
+/* creating flint arrows - DSR */
+
+STATIC_OVL void
+apply_flint(flint)
+struct obj* flint;
+{
+	struct obj* obj;
+	char szwork[QBUFSZ];
+	int flints, arrows, i;
+	static const char menulist[2] = {WEAPON_CLASS,0};
+
+	flints = flint->quan;
+
+	Sprintf(szwork, "affix the stone%s to", plur(flints));
+	if ((obj = getobj(menulist,szwork)) == 0) {
+		return;
+	}
+
+	/* can only stick flint to arrows */
+	if (obj->otyp < ARROW || obj->otyp > YA) {
+		You("aren't really sure what good that will do.");
+		return;
+	}
+
+	/* can't make MIRV arrows; if they're +1, leave it be */
+	if (obj->spe > 0) {
+		You("don't think you can make these any better than they are.");
+		return;
+	}
+
+	arrows = obj->quan;
+
+	/* One flint stone will do 10 arrows. */
+	if (flints*10 > arrows) {
+		(obj->spe)++;
+		You("lash flint tips to the arrows.");
+		for (i = 0;i <= arrows/10;i++) {
+			useup(flint);
+		}
+	} else {
+		You("don't have enough flint to re-tip all of these.");
+	}
+	return;
+}
+
 /* touchstones - by Ken Arnold */
 STATIC_OVL void
@@ -1839,4 +1965,7 @@
     struct obj *obj;
     boolean do_scratch;
+	 boolean make_sparks;
+	 int i, j;
+	 struct monst* mtmp;
     const char *streak_color, *choices;
     char stonebuf[QBUFSZ];
@@ -1897,4 +2026,5 @@
 
     do_scratch = FALSE;
+	 make_sparks = FALSE;
     streak_color = 0;
 
@@ -1903,4 +2033,7 @@
     case RING_CLASS:
 	if (tstone->otyp != TOUCHSTONE) {
+				if (tstone->otyp == FLINT && objects[obj->otyp].oc_material == IRON) {
+					make_sparks = TRUE;	/* we'll catch it later */
+				} 
 	    do_scratch = TRUE;
 	} else if (obj->oclass == GEM_CLASS && (tstone->blessed ||
@@ -1946,4 +2079,8 @@
 	    streak_color = "silvery";
 	    break;
+				case IRON:
+					if (tstone->otyp == FLINT) {
+						make_sparks = TRUE;
+					}
 	default:
 	    /* Objects passing the is_flimsy() test will not
@@ -1960,9 +2097,59 @@
 
     Sprintf(stonebuf, "stone%s", plur(tstone->quan));
-    if (do_scratch)
+    if (do_scratch) {
+	 	if (!make_sparks) {
 	pline("You make %s%sscratch marks on the %s.",
 	      streak_color ? streak_color : (const char *)"",
 	      streak_color ? " " : "", stonebuf);
-    else if (streak_color)
+		} else if (tstone->otyp == FLINT) {
+			/* Iron and flint make sparks. Non-intelligent creatures
+			 * fear fire.  So anything next to Our Hero(tm) that isn't
+			 * intelligent should have a chance of becoming afraid. */
+			 makeknown(tstone->otyp);
+			 if (u.uinwater) {
+			 	pline("You'd need a flamethrower to make fire here.");
+				return;
+			 }
+			 You("strike a few sparks from the flint stone!");
+			 if (u.uswallow) {
+				/* Not even the thing you're inside can see your piddly spark. */
+			 	pline("That's not going to make it any brighter in here.");
+				if (!rn2(3)) {
+					Your("flint stone crumbles!");
+					useup(tstone);
+				}
+				return;
+			 }
+
+			 for (i = u.ux-1;i < u.ux+2;i++) {
+			 	for (j = u.uy-1;j < u.uy+2;j++) {
+					if (!isok(i,j)) {
+						continue;
+					}
+					mtmp = m_at(i,j);
+					/* blind monsters can't see it */
+					if (!mtmp || mtmp->mblinded || !haseyes(mtmp->data)) {
+						continue;
+					}
+					/* only some things will be scared:
+					 * animals and undead fear fire, but
+					 * not if they're fire resistant, sufficiently powerful,
+					 * gigantic (purple worm), or currently in water */
+					if ((is_animal(mtmp->data) || is_undead(mtmp->data)) &&
+						!(resists_fire(mtmp) || mtmp->data->mcolor == CLR_MAGENTA ||
+							mtmp->data->msize == MZ_GIGANTIC || is_pool(i,j))) {
+						if (rn2(3)) {
+							monflee(mtmp,rnd(10), TRUE, TRUE);
+						}
+					}	
+				}
+			}
+			if (!rn2(3)) {
+				Your("flint stone crumbles!");
+				useup(tstone);
+			}
+			return;
+		}
+	 } else if (streak_color)
 	pline("You see %s streaks on the %s.", streak_color, stonebuf);
     else
@@ -2247,4 +2434,18 @@
 	   map_invisible(rx, ry);
 	}
+	/* Disciplining your pets? */
+	if (mtmp->mtame) {
+		pline("You severely beat %s!",y_monnam(mtmp));
+		abuse_dog(mtmp);
+		return 1;
+	}
+	/* invitation to a little S&M perhaps? */
+	if (mtmp->data == &mons[PM_SUCCUBUS] || mtmp->data == &mons[PM_INCUBUS]) {
+		pline("As you crack the whip, %s winks at you.",mon_nam(mtmp));
+		if (!Upolyd && mtmp->female != flags.female) {
+			mattacku(mtmp);
+		}
+		return 1;
+	}
 	otmp = MON_WEP(mtmp);	/* can be null */
 	if (otmp) {
@@ -2386,6 +2587,12 @@
 	/* Prompt for a location */
 	pline(where_to_hit);
+	if (polemonst && !DEADMONSTER(polemonst)) {
+		cc.x = polemonst->mx;
+		cc.y = polemonst->my;
+	} else {
+		polemonst = 0;	 /* reset this since it's either already 0 or should be */
 	cc.x = u.ux;
 	cc.y = u.uy;
+	}
 	if (getpos(&cc, TRUE, "the spot to hit") < 0)
 	    return 0;	/* user pressed ESC */
@@ -2416,4 +2623,5 @@
 	    int oldhp = mtmp->mhp;
 
+		 polemonst = mtmp;
 	    bhitpos = cc;
 	    check_caitiff(mtmp);
@@ -2425,4 +2633,5 @@
 	    if (mtmp->mhp < oldhp)
 		u.uconduct.weaphit++;
+		 if (DEADMONSTER(mtmp)) polemonst = 0;	 /* clean up pre-emptively */
 	} else
 	    /* Now you know that nothing is there... */
@@ -2680,4 +2889,5 @@
     case WAN_TELEPORTATION:
     case WAN_UNDEAD_TURNING:
+	 case WAN_WIND:
 	affects_objects = TRUE;
 	break;
@@ -2751,5 +2961,5 @@
     if (obj)
 	delobj(obj);
-    nomul(0);
+    nomul(0, 0);
     return 1;
 }
@@ -2782,9 +2992,11 @@
 	struct obj *obj;
 	register int res = 1;
+	int breakchance;
+	char eroded[256];
 	char class_list[MAXOCLASSES+2];
 
 	if(check_capacity((char *)0)) return (0);
 
-	if (carrying(POT_OIL) || uhave_graystone())
+	if (carrying(FLINT) || carrying(POT_OIL) || uhave_graystone())
 		Strcpy(class_list, tools_too);
 	else
@@ -2827,7 +3039,9 @@
 	case CHEST:
 	case ICE_BOX:
+	case SMALL_SACK:
 	case SACK:
 	case BAG_OF_HOLDING:
 	case OILSKIN_SACK:
+	case IRON_SAFE:
 		res = use_container(obj, 1);
 		break;
@@ -2835,4 +3049,7 @@
 		bagotricks(obj);
 		break;
+	case BAG_OF_POO:
+		light_poo(obj);
+		break;
 	case CAN_OF_GREASE:
 		use_grease(obj);
@@ -2843,5 +3060,5 @@
 #endif
 	case SKELETON_KEY:
-		(void) pick_lock(obj);
+		(void) pick_lock(obj,0,0);
 		break;
 	case PICK_AXE:
@@ -2997,7 +3214,14 @@
 		break;
 	case FLINT:
+		if (Role_if(PM_CAVEMAN)) {
+			apply_flint(obj);
+		} else {
+			use_stone(obj);
+		}
+		break;
 	case LUCKSTONE:
 	case LOADSTONE:
 	case TOUCHSTONE:
+	case SALT_CHUNK:
 		use_stone(obj);
 		break;
@@ -3013,9 +3237,38 @@
 		pline("Sorry, I don't know how to use that.");
 	xit:
-		nomul(0);
+		nomul(0, 0);
 		return 0;
 	}
 	if (res && obj && obj->oartifact) arti_speak(obj);
-	nomul(0);
+	nomul(0, 0);
+	
+	/* Tools that aren't in perfect condition might break... 
+	 * ...but only tools, not the weapons */
+	if (obj && !obj->oerodeproof && obj->otyp != BULLWHIP && 
+			!is_pole(obj) && !is_pick(obj) && !obj->oartifact) {	 /* don't break the Key */
+		breakchance = obj->blessed ? 100 : obj->cursed ? 5 : 10;
+		if (rn2(breakchance) < greatest_erosion(obj)) {
+			Strcpy(eroded,"");
+			add_erosion_words(obj,(char*)eroded);
+			Strcat(eroded,xname(obj));
+			pline("Your %s breaks!",eroded);
+			if (Has_contents(obj)) {
+				struct obj* octmp;
+				struct obj* tobj;
+				pline("The contents spill out everywhere!");
+				for (octmp = obj->cobj; octmp; octmp = tobj) {
+					tobj = octmp->nobj;
+					obj_extract_self(octmp);
+					if (!flooreffects(octmp,u.ux,u.uy,"falls")) {
+						place_object(octmp,u.ux,u.uy);
+						stackobj(octmp);
+					}
+				}
+			}
+			useup(obj);
+			return res;
+		}
+	}
+
 	return res;
 }
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/src/artifact.c nethack/src/artifact.c
--- nh_orig/src/artifact.c	2003-12-07 18:39:13.000000000 -0500
+++ nethack/src/artifact.c	2009-11-22 07:19:36.314397844 -0500
@@ -17,4 +17,7 @@
  */
 
+/*#define DEBUG*/
+/* Uncomment for some complaint messages */
+
 extern boolean notonhead;	/* for long worms */
 
@@ -64,7 +67,16 @@
 		art->alignment = alignmnt;
 
-	/* Excalibur can be used by any lawful character, not just knights */
-	if (!Role_if(PM_KNIGHT))
+	/* Excalibur can be used by any lawful character, not just knights
+		So can Dirge, for that matter */
+	if (!Role_if(PM_KNIGHT)) {
 	    artilist[ART_EXCALIBUR].role = NON_PM;
+		 artilist[ART_DIRGE].role = NON_PM;
+	 }
+
+	/* Demonbane should always be in the Priest's list of available toys
+	 * even though this might look a little odd when it comes out Chaotic */
+	if (Role_if(PM_PRIEST)) {
+		artilist[ART_DEMONBANE].alignment = alignmnt;
+	}
 
 	/* Fix up the quest artifact */
@@ -283,4 +295,10 @@
 #ifdef OVLB
 
+/*
+ * ...Side effect of allowing Sting produces the famous artinaming bug.
+ * We can fix this; naming something an artifact name for an artifact that is
+ * SPFX_RESTR should produce an outright failure.
+ */
+
 boolean
 restrict_name(otmp, name)  /* returns 1 if name is restricted for otmp->otyp */
@@ -299,10 +317,9 @@
 		 */
 	for (a = artilist+1; a->otyp; a++) {
-	    if (a->otyp != otmp->otyp) continue;
 	    aname = a->name;
 	    if (!strncmpi(aname, "the ", 4)) aname += 4;
-	    if (!strcmp(aname, name))
-		return ((boolean)((a->spfx & (SPFX_NOGEN|SPFX_RESTR)) != 0 ||
-			otmp->quan > 1L));
+	    if (!strcmp(aname, name)) {
+			return ((boolean)((a->spfx & (SPFX_NOGEN|SPFX_RESTR)) != 0 || otmp->quan > 1L));
+		 }
 	}
 
@@ -328,7 +345,60 @@
 {
 	register const struct artifact *weap;
+	unsigned long mask;
 
-	if ((weap = get_artifact(otmp)) != 0)
-		return((boolean)(weap->defn.adtyp == adtyp));
+	if ((weap = get_artifact(otmp)) != 0) {
+		switch (adtyp) {
+			case AD_FIRE:
+				mask = (weap->defn & SPDF_FIRE);
+				break;
+			case AD_COLD:
+				mask = (weap->defn & SPDF_COLD);
+				break;
+			case AD_ELEC:
+				mask = (weap->defn & SPDF_ELEC);
+				break;
+			case AD_SLEE:
+				mask = (weap->defn & SPDF_SLEEP);
+				break;
+			case AD_DISN:
+				mask = (weap->defn & SPDF_DISINT);
+				break;
+			case AD_DRST:
+				mask = (weap->defn & SPDF_POISON);
+				break;
+			case AD_ACID:
+				mask = (weap->defn & SPDF_ACID);
+				break;
+			case AD_MAGM:
+				mask = (weap->defn & SPDF_MAGIC);
+				break;
+			case AD_BLND:
+				mask = (weap->defn & SPDF_BLIND);
+				break;
+			case AD_WERE:
+				mask = (weap->defn & SPDF_WERE);
+				break;
+			case AD_DRLI:
+				mask = (weap->defn & SPDF_DRAIN);
+				break;
+			case AD_STUN:
+				mask = (weap->defn & SPDF_STUN);
+				break;
+			case AD_CONF:
+				mask = (weap->defn & SPDF_CONFUSE);
+				break;
+			case AD_DISE:
+			case AD_DRIN:
+				mask = 0;	/* none yet */
+				break;
+			default:
+#ifdef DEBUG
+				/* Don't whine about this unless we really want to */
+				pline("strange attack type in defends(): %d",adtyp);
+#endif
+				return FALSE;
+		}
+		return (mask > 0);  /* straight cast will fail */
+	}
 	return FALSE;
 }
@@ -364,6 +434,6 @@
 	if (!oart) return;
 
-	/* effects from the defn field */
-	dtyp = (wp_mask != W_ART) ? oart->defn.adtyp : oart->cary.adtyp;
+	/* effects from the cary field */
+	dtyp = (wp_mask != W_ART) ? 0 : oart->cary.adtyp;
 
 	if (dtyp == AD_FIRE)
@@ -398,4 +468,59 @@
 	}
 
+	/* effects from the defn field; could be more than one
+		...Note that we don't have to check for other stuff, because
+		this uses wp_mask directly and you can only have one of 
+		any given thing in the appropriate slot */
+	if (wp_mask & (W_WEP | W_ARMOR | W_AMUL | W_RING | W_TOOL)) {
+		if (oart->defn & SPDF_FIRE) {
+			if (on) EFire_resistance |= wp_mask;
+			else EFire_resistance &= ~wp_mask;
+		}
+		if (oart->defn & SPDF_COLD) {
+			if (on) ECold_resistance |= wp_mask;
+			else ECold_resistance &= ~wp_mask;
+		}
+		if (oart->defn & SPDF_ELEC) {
+			if (on) EShock_resistance |= wp_mask;
+			else EShock_resistance &= ~wp_mask;
+		}
+		if (oart->defn & SPDF_SLEEP) {
+			if (on) ESleep_resistance |= wp_mask;
+			else ESleep_resistance &= ~wp_mask;
+		}
+		if (oart->defn & SPDF_POISON) {
+			if (on) EPoison_resistance |= wp_mask;
+			else EPoison_resistance &= ~wp_mask;
+		}
+		if (oart->defn & SPDF_ACID) {
+			if (on) EAcid_resistance |= wp_mask;
+			else EAcid_resistance &= ~wp_mask;
+		}
+		if (oart->defn & SPDF_DISINT) {
+			if (on) EDisint_resistance |= wp_mask;
+			else EDisint_resistance &= ~wp_mask;
+		}
+		if (oart->defn & SPDF_DRAIN) {
+			if (on) EDrain_resistance |= wp_mask;
+			else EDrain_resistance &= ~wp_mask;
+		}
+		if (oart->defn & SPDF_MAGIC) {
+			if (on) EAntimagic |= wp_mask;
+			else EAntimagic &= ~wp_mask;
+		}
+		if (oart->defn & SPDF_WERE) {
+			/* Doesn't have a specific resistance in the table */
+		}
+		if (oart->defn & SPDF_BLIND) {
+			/* Doesn't have a specific resistance in the table */
+		}
+		if (oart->defn & SPDF_CONFUSE) {
+			/* Doesn't have a specific resistance in the table */
+		}
+		if (oart->defn & SPDF_STUN) {
+			/* Doesn't have a specific resistance in the table */
+		}
+	}
+
 	/* intrinsics from the spfx field; there could be more than one */
 	spfx = (wp_mask != W_ART) ? oart->spfx : oart->cspfx;
@@ -414,4 +539,8 @@
 	    else ESearching &= ~wp_mask;
 	}
+	if (spfx & SPFX_POLYC) {
+		if (on) EPolymorph_control |= wp_mask;
+		else EPolymorph_control &= ~wp_mask;
+	}
 	if (spfx & SPFX_HALRES) {
 	    /* make_hallucinated must (re)set the mask itself to get
@@ -441,11 +570,21 @@
 	}
 	if (spfx & SPFX_WARN) {
-	    if (spec_m2(otmp)) {
+		/* right now the only things that warn against a specific monster type
+		 * are wielded artifacts.  this may change in the future but for now
+		 * this is probably the smallest change to clean things up without
+		 * screwing around adding more M2 flags */
+		if (spfx & (SPFX_DCLAS | SPFX_DFLAG2)) {
 	    	if (on) {
-			EWarn_of_mon |= wp_mask;
+				if (spfx & SPFX_DCLAS)
+					flags.warntype = oart->mtype;
+				else
 			flags.warntype |= spec_m2(otmp);
+				EWarn_of_mon |= wp_mask;
 	    	} else {
-			EWarn_of_mon &= ~wp_mask;
+				if (spfx & SPFX_DCLAS)
+					flags.warntype = 0L;
+				else
 	    		flags.warntype &= ~spec_m2(otmp);
+				EWarn_of_mon &= ~wp_mask;
 		}
 		see_monsters();
@@ -473,8 +612,17 @@
 	    vision_full_recalc = 1;
 	}
-	if ((spfx & SPFX_REFLECT) && (wp_mask & W_WEP)) {
+	if (spfx & SPFX_REFLECT) {
+		/* Knights only have to carry the mirror; everyone else must wield it */
+		if (Role_if(PM_KNIGHT)) {
+			if (on) {
+				EReflecting |= wp_mask;
+			} else {
+				EReflecting &= ~wp_mask;
+			}
+		} else if (wp_mask & W_WEP) {
 	    if (on) EReflecting |= wp_mask;
 	    else EReflecting &= ~wp_mask;
 	}
+	}
 
 	if(wp_mask == W_ART && !on && oart->inv_prop) {
@@ -595,14 +743,14 @@
 	    switch(weap->attk.adtyp) {
 		case AD_FIRE:
-			return !(yours ? Fire_resistance : resists_fire(mtmp));
+			return !(!yours ? resists_fire(mtmp) : (how_resistant(FIRE_RES) > 99) ? TRUE : FALSE);
 		case AD_COLD:
-			return !(yours ? Cold_resistance : resists_cold(mtmp));
+			return !(!yours ? resists_cold(mtmp) : (how_resistant(COLD_RES) > 99) ? TRUE : FALSE);
 		case AD_ELEC:
-			return !(yours ? Shock_resistance : resists_elec(mtmp));
+			return !(!yours ? resists_elec(mtmp) : (how_resistant(SHOCK_RES) > 99) ? TRUE : FALSE);
 		case AD_MAGM:
 		case AD_STUN:
 			return !(yours ? Antimagic : (rn2(100) < ptr->mr));
 		case AD_DRST:
-			return !(yours ? Poison_resistance : resists_poison(mtmp));
+			return !(!yours ? resists_poison(mtmp) : (how_resistant(POISON_RES) > 99) ? TRUE : FALSE);
 		case AD_DRLI:
 			return !(yours ? Drain_resistance : resists_drli(mtmp));
@@ -651,4 +799,8 @@
 	register const struct artifact *weap = get_artifact(otmp);
 
+	if (otmp->oclass == GEM_CLASS && uwep && uwep->oartifact == ART_GIANTSLAYER) {
+		weap = get_artifact(uwep);
+	}
+
 	if (!weap || (weap->attk.adtyp == AD_PHYS && /* check for `NO_ATTK' */
 			weap->attk.damn == 0 && weap->attk.damd == 0))
@@ -857,5 +1009,5 @@
 		resisted = TRUE;
 	    } else {
-		nomul(-3);
+		nomul(-3, "being scared stiff");
 		nomovemsg = "";
 		if (magr && magr == u.ustuck && sticks(youmonst.data)) {
@@ -949,4 +1101,6 @@
 	static const char you[] = "you";
 	char hittee[BUFSZ];
+	struct artifact* atmp;
+	int j;
 
 	Strcpy(hittee, youdefend ? you : mon_nam(mdef));
@@ -1006,4 +1160,12 @@
 	    return realizes_damage;
 	}
+	/* the fifth basic attack: poison */
+	if (attacks(AD_DRST, otmp)) {
+		if (realizes_damage) {
+			pline_The("venomous blade %s %s%c",spec_dbon_applies ? "strikes" : "nicks",
+				hittee, spec_dbon_applies ? '!' : '.');
+			return realizes_damage;
+		}
+	}
 
 	if (attacks(AD_STUN, otmp) && dieroll <= MB_MAX_DIEROLL) {
@@ -1018,4 +1180,79 @@
 	}
 
+	/* Are we about to do something special vs. a monster type? */
+	atmp = &artilist[otmp->oartifact];
+	if (otmp->oclass == GEM_CLASS && uwep && uwep->oartifact == ART_GIANTSLAYER) {
+		atmp = &artilist[ART_GIANTSLAYER];
+		otmp->oartifact = ART_GIANTSLAYER;	/* really miserable hack */
+	}
+	if (atmp->spfx & (SPFX_DFLAG2 | SPFX_DCLAS)) {
+		j = rn2(2);	  /* 50% chance of instakill for some artifacts */
+		switch (otmp->oartifact) {
+			case ART_DRAGONBANE:
+				if (youattack && j) {
+					You("pierce the heart of %s!", mon_nam(mdef));
+					*dmgptr = (2 * mdef->mhp + FATAL_DAMAGE_MODIFIER);
+				} else if (youdefend && j) {
+					pline("The deadly spear pierces your heart!");
+					*dmgptr = (2 * Upolyd ? u.mh : u.uhp + FATAL_DAMAGE_MODIFIER);
+				} else {
+					return FALSE;
+				}
+				return TRUE;
+			case ART_WEREBANE:
+				if (youattack && j) {
+					*dmgptr = (2 * mdef->mhp + FATAL_DAMAGE_MODIFIER);
+				} else if (youdefend && j) {
+					*dmgptr = (2 * Upolyd ? u.mh : u.uhp + FATAL_DAMAGE_MODIFIER);
+				} else {
+					return FALSE;
+				}
+				return TRUE;
+			case ART_GIANTSLAYER:
+				if (otmp->oclass == GEM_CLASS) {	 /* second part of miserable hack */
+					otmp->oartifact = 0L;
+				}
+				if (youattack) {
+					You("strike %s in the forehead!",mon_nam(mdef));
+					*dmgptr = (2 * mdef->mhp + FATAL_DAMAGE_MODIFIER);
+				} else if (youdefend) {
+					*dmgptr = (2 * Upolyd ? u.mh : u.uhp + FATAL_DAMAGE_MODIFIER);
+					You("are hit in the center of your forehead!");
+				}
+				return TRUE;
+			case ART_OGRESMASHER:
+				if (youattack && j) {
+					You("crush the skull of %s!", mon_nam(mdef));
+					*dmgptr = (2 * mdef->mhp + FATAL_DAMAGE_MODIFIER);
+				} else if (youdefend && j) {
+					pline("The monstrous hammer crushes your skull!");
+					*dmgptr = (2 * Upolyd ? u.mh : u.uhp + FATAL_DAMAGE_MODIFIER);
+				} else {
+					return FALSE;
+				}
+				return TRUE;
+			case ART_TROLLSBANE:
+				if (youattack && j) {
+					pline("As you strike %s, it bursts into flame!", mon_nam(mdef));
+					*dmgptr = (2 * mdef->mhp + FATAL_DAMAGE_MODIFIER);
+				} else if (youdefend && j) {
+					You("burst into flame as you are hit!");
+					*dmgptr = (2 * Upolyd ? u.mh : u.uhp + FATAL_DAMAGE_MODIFIER);
+				} else {
+					return FALSE;
+				}
+				return TRUE;
+			/* below this we don't get any additional handling, so drop through
+			* just listed here for potential future reference */
+			case ART_DEMONBANE:
+			case ART_SUNSWORD:
+			case ART_ORCRIST:
+			case ART_STING:
+			default:
+				break;
+		}
+
+	}
+
 	/* We really want "on a natural 20" but Nethack does it in */
 	/* reverse from AD&D. */
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/src/attrib.c nethack/src/attrib.c
--- nh_orig/src/attrib.c	2003-12-07 18:39:13.000000000 -0500
+++ nethack/src/attrib.c	2009-11-23 12:02:47.602313145 -0500
@@ -6,4 +6,6 @@
 
 #include "hack.h"
+#include "artifact.h"
+#include "artilist.h"
 
 /* #define DEBUG */	/* uncomment for debugging info */
@@ -187,9 +189,8 @@
 	    if (Upolyd) {
 		u.mh -= 6;
-		u.mhmax -= 6;
 	    } else {
 		u.uhp -= 6;
-		u.uhpmax -= 6;
 	    }
+		 gainmaxhp(-6);
 	}
 	(void) adjattrib(A_STR, -num, TRUE);
@@ -539,4 +540,5 @@
 	register const struct innate *abil, *rabil;
 	long mask = FROMEXPER;
+	int bShowMsgAnyway = 0;
 
 
@@ -571,4 +573,5 @@
 	while (abil || rabil) {
 	    long prevabil;
+		 bShowMsgAnyway = 0;
 	    /* Have we finished with the intrinsics list? */
 	    if (!abil || !abil->ability) {
@@ -581,4 +584,11 @@
 		prevabil = *(abil->ability);
 		if(oldlevel < abil->ulevel && newlevel >= abil->ulevel) {
+			// Must do this check before we set the FROMEXPER flag
+			if ((*(abil->ability) & TIMEOUT) < 100)
+			{
+				bShowMsgAnyway = 1;
+			}
+
+			if (abil->ulevel == 1)
 			/* Abilities gained at level 1 can never be lost
 			 * via level loss, only via means that remove _any_
@@ -587,9 +597,8 @@
 			 * FROMOUTSIDE to avoid such gains.
 			 */
-			if (abil->ulevel == 1)
 				*(abil->ability) |= (mask|FROMOUTSIDE);
 			else
 				*(abil->ability) |= mask;
-			if(!(*(abil->ability) & INTRINSIC & ~mask)) {
+			if(bShowMsgAnyway || !(*(abil->ability) & INTRINSIC & ~mask)) {
 			    if(*(abil->gainstr))
 				You_feel("%s!", abil->gainstr);
@@ -621,6 +630,5 @@
 newhp()
 {
-	int	hp, conplus;
-
+	int	hp, conplus, tempnum;
 
 	if (u.ulevel == 0) {
@@ -645,4 +653,23 @@
 	    	if (urace.hpadv.hirnd > 0) hp += rnd(urace.hpadv.hirnd);
 	    }
+
+		/* Cavemen get a tiny HP boost if they've remained illiterate,
+			as well as a tiny wisdom boost.  The longer they remain illit,
+			the bigger the HP boost gets (capped at d3) */
+
+		if (Role_if(PM_CAVEMAN)) {
+			tempnum = 0;
+			if (u.uconduct.literate < 1) {
+				if (u.ulevel < 4) {
+					tempnum += 1;
+				} else if (u.ulevel < 8) {
+					tempnum += rnd(2);
+				} else {
+					tempnum += rnd(3);
+				}
+				exercise(A_WIS,TRUE);
+			}
+			hp += tempnum;
+		}
 	}
 
@@ -670,4 +697,8 @@
 	if (x == A_STR) {
 		if (uarmg && uarmg->otyp == GAUNTLETS_OF_POWER) return(125);
+		if ((uwep && (artilist[uwep->oartifact].spfx & SPFX_STR)) ||
+				(uswapwep && (artilist[uswapwep->oartifact].spfx & SPFX_STR))) {
+			return (118);
+		}
 #ifdef WIN32_BUG
 		else return(x=((tmp >= 125) ? 125 : (tmp <= 3) ? 3 : tmp));
@@ -675,4 +706,6 @@
 		else return((schar)((tmp >= 125) ? 125 : (tmp <= 3) ? 3 : tmp));
 #endif
+	} else if (x == A_CON) {
+		if (uwep && (artilist[uwep->oartifact].spfx & SPFX_CON)) return (25);
 	} else if (x == A_CHA) {
 		if (tmp < 18 && (youmonst.data->mlet == S_NYMPH ||
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/src/ball.c nethack/src/ball.c
--- nh_orig/src/ball.c	2003-12-07 18:39:13.000000000 -0500
+++ nethack/src/ball.c	2009-11-22 07:19:36.355272024 -0500
@@ -558,5 +558,5 @@
 	    You("cannot %sdrag the heavy iron ball.",
 			    invent ? "carry all that and also " : "");
-	    nomul(0);
+	    nomul(0, 0);
 	    return FALSE;
 	}
@@ -596,5 +596,5 @@
 		    newsym(u.ux0, u.uy0);
 		}
-		nomul(0);
+		nomul(0, 0);
 
 		*bc_control = BC_BALL;
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/src/bones.c nethack/src/bones.c
--- nh_orig/src/bones.c	2003-12-07 18:39:13.000000000 -0500
+++ nethack/src/bones.c	2009-08-02 13:49:38.692407855 -0400
@@ -65,9 +65,11 @@
 		    resetobjs(otmp->cobj,restore);
 
-		if (((otmp->otyp != CORPSE || otmp->corpsenm < SPECIAL_PM)
-			&& otmp->otyp != STATUE)
-			&& (!otmp->oartifact ||
-			   (restore && (exist_artifact(otmp->otyp, ONAME(otmp))
-					|| is_quest_artifact(otmp))))) {
+		if (
+			 ((otmp->otyp != CORPSE || otmp->corpsenm < SPECIAL_PM) && 
+				otmp->otyp != STATUE && otmp->otyp != SKULL) && 
+					(!otmp->oartifact || (restore && 
+						(exist_artifact(otmp->otyp, ONAME(otmp)) || 
+							 is_quest_artifact(otmp))))
+				) {
 			otmp->oartifact = 0;
 			otmp->onamelth = 0;
@@ -156,4 +158,9 @@
 #endif
 	if (cont) cont->owt = weight(cont);
+
+	/* should we leave a skull behind? */
+	if (rn2(3) && has_head(youmonst.data) && !unsolid(youmonst.data)) {
+		otmp = mk_named_object(SKULL,youmonst.data,u.ux,u.uy,plname);
+	}
 }
 
@@ -230,7 +237,8 @@
 	    if (mtmp->iswiz || mptr == &mons[PM_MEDUSA] ||
 		    mptr->msound == MS_NEMESIS || mptr->msound == MS_LEADER ||
-		    mptr == &mons[PM_VLAD_THE_IMPALER])
+		    mptr == &mons[PM_VLAD_THE_IMPALER]) {
 		mongone(mtmp);
 	}
+	}
 #ifdef STEED
 	if (u.usteed) dismount_steed(DISMOUNT_BONES);
@@ -246,4 +254,12 @@
 	if (uball) uball->owornmask = uchain->owornmask = 0;
 
+	/* extinguish armor */
+	if(uarm && (uarm->otyp == GOLD_DRAGON_SCALE_MAIL || uarm->otyp == GOLD_DRAGON_SCALES))
+		end_burn(uarm,FALSE);
+
+	if(uarms && uarms->otyp == SHIELD_OF_LIGHT) {
+		end_burn(uarms,FALSE);
+	}
+
 	/* dispose of your possessions, usually cursed */
 	if (u.ugrave_arise == (NON_PM - 1)) {
@@ -261,6 +277,43 @@
 		drop_upon_death((struct monst *)0, (struct obj *)0);
 		/* trick makemon() into allowing monster creation
-		 * on your location
+		 * on your location */
+		if (ukiller) {
+		   /* If you don't rise from your grave (and are thus carrying your stuff),
+			 * the critter that killed you gets some special handling here.
+			 *
+			 * First, he gets to loot your body; if he's a demon lord or prince,
+			 * he will tend to take all the "good stuff".
+			 *
+			 * He also gets a chance to be removed as well -- hitting Yeenybones
+			 * once is not a big deal, but a persistent upper-dungeon Yeeny from 
+			 * an unlucky fountain quaffer would be a bit much.
 		 */
+			struct obj* otmp;
+			struct obj* otmp2;
+			boolean greedy = FALSE;
+
+			/* For now the only actively mean monsters are demon lords/princes */
+			if (is_dlord(ukiller->data) || is_dprince(ukiller->data)) {
+				greedy = TRUE;
+			}
+
+			for (otmp = level.objects[u.ux][u.uy]; otmp; otmp = otmp2) {
+				otmp2 = otmp->nexthere; /* mpickobj might free otmp */
+				if (!rn2(8) || 
+						(greedy && rn2(2) && (otmp->oartifact || Is_dragon_armor(otmp) ||
+							otmp->otyp == AMULET_OF_LIFE_SAVING || otmp->otyp == AMULET_OF_POWER ||
+							otmp->otyp == MAGIC_MARKER || otmp->otyp == UNICORN_HORN))) {
+					if (!touch_artifact(otmp,ukiller)) continue;
+					if (!can_carry(ukiller,otmp)) continue;
+					obj_extract_self(otmp);
+					mpickobj(ukiller,otmp);
+				}
+			}
+			m_dowear(ukiller, TRUE); /* Let him put them on :) */
+			if (greedy && !rn2(2)) {
+				mongone(ukiller);
+				dmonsfree();		  /* have to call this again */
+			}
+		}
 		in_mklev = TRUE;
 		mtmp = makemon(&mons[PM_GHOST], u.ux, u.uy, MM_NONAME);
@@ -293,4 +346,5 @@
 		mtmp->msleeping = 1;
 	}
+
 	for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
 		resetobjs(mtmp->minvent,FALSE);
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/src/botl.c nethack/src/botl.c
--- nh_orig/src/botl.c	2003-12-07 18:39:13.000000000 -0500
+++ nethack/src/botl.c	2009-09-07 11:26:05.050309303 -0400
@@ -35,4 +35,87 @@
 #endif
 
+#if defined(STATUS_COLORS) && defined(TEXTCOLOR)
+
+extern const struct percent_color_option *hp_colors;
+extern const struct percent_color_option *pw_colors;
+extern const struct text_color_option *text_colors;
+
+struct color_option
+text_color_of(text, color_options)
+const char *text;
+const struct text_color_option *color_options;
+{
+	if (color_options == NULL) {
+		struct color_option result = {NO_COLOR, 0};
+		return result;
+	}
+	if (strstri(color_options->text, text)
+	 || strstri(text, color_options->text))
+		return color_options->color_option;
+	return text_color_of(text, color_options->next);
+}
+
+struct color_option
+percentage_color_of(value, max, color_options)
+int value, max;
+const struct percent_color_option *color_options;
+{
+	if (color_options == NULL) {
+		struct color_option result = {NO_COLOR, 0};
+		return result;
+	}
+	if (100 * value <= color_options->percentage * max)
+		return color_options->color_option;
+	return percentage_color_of(value, max, color_options->next);
+}
+
+void
+start_color_option(color_option)
+struct color_option color_option;
+{
+	int i;
+	if (color_option.color != NO_COLOR)
+		term_start_color(color_option.color);
+	for (i = 0; (1 << i) <= color_option.attr_bits; ++i)
+		if (i != ATR_NONE && color_option.attr_bits & (1 << i))
+			term_start_attr(i);
+}
+
+void
+end_color_option(color_option)
+struct color_option color_option;
+{
+	int i;
+	if (color_option.color != NO_COLOR)
+		term_end_color(color_option.color);
+	for (i = 0; (1 << i) <= color_option.attr_bits; ++i)
+		if (i != ATR_NONE && color_option.attr_bits & (1 << i))
+			term_end_attr(i);
+}
+
+void
+apply_color_option(color_option, str, x)
+struct color_option color_option;
+const char *str;
+int x;
+{
+	if (x >= CO) return;
+	curs(WIN_STATUS, x, 1);
+	if (iflags.use_status_colors) start_color_option(color_option);
+	putstr(WIN_STATUS, 0, str);
+	if (iflags.use_status_colors) end_color_option(color_option);
+}
+
+void
+add_colored_text(text, x)
+const char *text;
+int x;
+{
+	if (*text == '\0') return;
+	apply_color_option(text_color_of(text, text_colors), text, x);
+}
+
+#endif
+
 #ifndef OVLB
 STATIC_DCL int mrank_sz;
@@ -72,5 +155,4 @@
 	register int i;
 
-
 	/* Find the role */
 	for (role = (struct Role *) roles; role->name.m; role++)
@@ -80,4 +162,9 @@
 	    role = &urole;
 
+	/* Gratuitous hack */
+	if (u.ualign.type == A_CHAOTIC && Role_if(PM_KNIGHT)) {
+		role = &urole;
+	}
+
 	/* Find the rank */
 	for (i = xlev_to_rank((int)lev); i >= 0; i--) {
@@ -166,8 +253,14 @@
 #endif
 
+#ifdef DUMP_LOG
+void bot1str(char *newbot1)
+#else
 STATIC_OVL void
 bot1()
+#endif
 {
+#ifndef DUMP_LOG
 	char newbot1[MAXCO];
+#endif
 	register char *nb;
 	register int i,j;
@@ -216,4 +309,13 @@
 	    Sprintf(nb = eos(nb), " S:%ld", botl_score());
 #endif
+#ifdef DUMP_LOG
+}
+STATIC_OVL void
+bot1()
+{
+	char newbot1[MAXCO];
+
+	bot1str(newbot1);
+#endif
 	curs(WIN_STATUS, 1, 0);
 	putstr(WIN_STATUS, 0, newbot1);
@@ -221,4 +323,15 @@
 
 /* provide the name of the current level for display by various ports */
+const char* short_dgn_names[] = {
+	"Dungeons of Doom",
+	"Gehennom",
+	"Gnomish Mines",
+	"Quest Levels",	 /* Placeholder; this is overridden below */
+	"Sokoban",
+	"Fort Ludios",		 /* this too */
+	"Vlad's Tower",
+	"End Game"			 /* and this */
+};
+
 int
 describe_level(buf)
@@ -237,5 +350,7 @@
 	else {
 		/* ports with more room may expand this one */
-		Sprintf(buf, "Dlvl:%-2d ", depth(&u.uz));
+		Sprintf(buf, "%s:%-2d ", 
+				iflags.show_dgn_name ? short_dgn_names[u.uz.dnum] : "Dlvl",
+				depth(&u.uz));
 		ret = 0;
 	}
@@ -243,11 +358,24 @@
 }
 
+#ifdef DUMP_LOG
+void bot2str(newbot2)
+char* newbot2;
+#else
 STATIC_OVL void
 bot2()
+#endif
 {
+#ifndef DUMP_LOG
 	char  newbot2[MAXCO];
+#endif
 	register char *nb;
 	int hp, hpmax;
 	int cap = near_capacity();
+#if defined(STATUS_COLORS) && defined(TEXTCOLOR)
+	struct color_option color_option;
+	int save_botlx = flags.botlx;
+#endif
+
+	int x = 1;
 
 	hp = Upolyd ? u.mh : u.uhp;
@@ -256,43 +384,154 @@
 	if(hp < 0) hp = 0;
 	(void) describe_level(newbot2);
-	Sprintf(nb = eos(newbot2),
-		"%c:%-2ld HP:%d(%d) Pw:%d(%d) AC:%-2d", oc_syms[COIN_CLASS],
+	Sprintf(nb = eos(newbot2), "%c:%-2ld", oc_syms[COIN_CLASS],
 #ifndef GOLDOBJ
-		u.ugold,
+		u.ugold
 #else
-		money_cnt(invent),
+		money_cnt(invent)
 #endif
-		hp, hpmax, u.uen, u.uenmax, u.uac);
+	       );
 
-	if (Upolyd)
+#if defined(STATUS_COLORS) && defined(TEXTCOLOR)
+	Strcat(nb = eos(newbot2), " HP:");
+	curs(WIN_STATUS, x, 1);
+	putstr(WIN_STATUS, 0, newbot2);
+	x += strlen(newbot2);
+
+	Sprintf(nb = eos(nb), "%d(%d)", hp, hpmax);
+
+	apply_color_option(percentage_color_of(hp, hpmax, hp_colors), nb, x);
+	x += strlen(nb);
+#else
+	Sprintf(nb = eos(nb), " HP:%d(%d)", hp, hpmax);
+#endif
+#if defined(STATUS_COLORS) && defined(TEXTCOLOR)
+	Strcat(nb = eos(nb), " Pw:");
+	curs(WIN_STATUS, x, 1);
+	putstr(WIN_STATUS, 0, nb);
+
+	x += strlen(nb);
+
+	Sprintf(nb = eos(nb), "%d(%d)", u.uen, u.uenmax);
+	apply_color_option(percentage_color_of(u.uen, u.uenmax, pw_colors), nb, x);
+	x += strlen(nb);
+#else
+	Sprintf(nb = eos(nb), " Pw:%d(%d)", u.uen, u.uenmax);
+#endif
+	Sprintf(nb = eos(nb), " AC:%-2d", u.uac);
+	curs(WIN_STATUS, x, 1);
+	putstr(WIN_STATUS, 0, nb);
+	x += strlen(nb);
+	if (Upolyd) {
 		Sprintf(nb = eos(nb), " HD:%d", mons[u.umonnum].mlevel);
+		curs(WIN_STATUS, x, 1);
+		putstr(WIN_STATUS, 0, nb);
+		x += strlen(nb);
+	}
 #ifdef EXP_ON_BOTL
-	else if(flags.showexp)
+	else if(flags.showexp) {
 		Sprintf(nb = eos(nb), " Xp:%u/%-1ld", u.ulevel,u.uexp);
+		curs(WIN_STATUS, x, 1);
+		putstr(WIN_STATUS, 0, nb);
+		x += strlen(nb);
+	}
 #endif
-	else
+	else {
 		Sprintf(nb = eos(nb), " Exp:%u", u.ulevel);
-
-	if(flags.time)
+		curs(WIN_STATUS, x, 1);
+		putstr(WIN_STATUS, 0, nb);
+		x += strlen(nb);
+	}
+	if(flags.time) {
 	    Sprintf(nb = eos(nb), " T:%ld", moves);
+	    curs(WIN_STATUS, x, 1);
+	    putstr(WIN_STATUS, 0, nb);
+	    x += strlen(nb);
+	}
+#ifdef REALTIME_ON_BOTL
+  if(iflags.showrealtime) {
+    time_t currenttime = get_realtime();
+    Sprintf(nb = eos(nb), " %d:%2.2d", currenttime / 3600, (currenttime % 3600) / 60);
+  }
+#endif
+	x++;
 	if(strcmp(hu_stat[u.uhs], "        ")) {
-		Sprintf(nb = eos(nb), " ");
-		Strcat(newbot2, hu_stat[u.uhs]);
+#if defined(STATUS_COLORS) && defined(TEXTCOLOR)
+	    add_colored_text(hu_stat[u.uhs], x);
+#endif
+	    Sprintf(nb = eos(nb), " %s", hu_stat[u.uhs]);
+	    x += strlen(nb);
+	}
+ 	if(Confusion) {
+#if defined(STATUS_COLORS) && defined(TEXTCOLOR)
+	    add_colored_text("Conf", x);
+#endif
+	    Strcat(nb = eos(nb), " Conf");
+	    x += strlen(nb);
 	}
-	if(Confusion)	   Sprintf(nb = eos(nb), " Conf");
 	if(Sick) {
-		if (u.usick_type & SICK_VOMITABLE)
-			   Sprintf(nb = eos(nb), " FoodPois");
-		if (u.usick_type & SICK_NONVOMITABLE)
-			   Sprintf(nb = eos(nb), " Ill");
+	    if (u.usick_type & SICK_VOMITABLE) {
+#if defined(STATUS_COLORS) && defined(TEXTCOLOR)
+		add_colored_text("FoodPois", x);
+#endif
+		Strcat(nb = eos(nb), " FoodPois");
+		x += strlen(nb);
 	}
-	if(Blind)	   Sprintf(nb = eos(nb), " Blind");
-	if(Stunned)	   Sprintf(nb = eos(nb), " Stun");
-	if(Hallucination)  Sprintf(nb = eos(nb), " Hallu");
-	if(Slimed)         Sprintf(nb = eos(nb), " Slime");
-	if(cap > UNENCUMBERED)
+	    if (u.usick_type & SICK_NONVOMITABLE) {
+#if defined(STATUS_COLORS) && defined(TEXTCOLOR)
+		add_colored_text("Ill", x);
+#endif
+		Strcat(nb = eos(nb), " Ill");
+		x += strlen(nb);
+	    }
+	}
+	if(Slow) {
+#if defined(STATUS_COLORS) && defined(TEXTCOLOR)
+	    add_colored_text("Slow", x);
+#endif
+	    Strcat(nb = eos(nb)," Slow");
+	    x += strlen(nb);
+	}
+	if(Blind) {
+#if defined(STATUS_COLORS) && defined(TEXTCOLOR)
+	    add_colored_text("Blind", x);
+#endif
+	    Strcat(nb = eos(nb), " Blind");
+	    x += strlen(nb);
+	}
+	if(Stunned) {
+#if defined(STATUS_COLORS) && defined(TEXTCOLOR)
+	    add_colored_text("Stun", x);
+#endif
+	    Strcat(nb = eos(nb), " Stun");
+	    x += strlen(nb);
+	}
+	if(Slimed) {
+#if defined(STATUS_COLORS) && defined(TEXTCOLOR)
+	    add_colored_text("Slime", x);
+#endif
+	    Strcat(nb = eos(nb), " Slime");
+	    x += strlen(nb);
+	}
+	if(cap > UNENCUMBERED) {
+#if defined(STATUS_COLORS) && defined(TEXTCOLOR)
+	    add_colored_text(enc_stat[cap], x);
+	    flags.botlx = save_botlx;
+#endif
 		Sprintf(nb = eos(nb), " %s", enc_stat[cap]);
+	    x += strlen(nb);
+	}
+#ifdef DUMP_LOG
+}
+STATIC_OVL void
+bot2()
+{
+	char newbot2[MAXCO];
+	bot2str(newbot2);
+#endif
+#if defined(STATUS_COLORS) && defined(TEXTCOLOR)
+#else
 	curs(WIN_STATUS, 1, 1);
 	putstr(WIN_STATUS, 0, newbot2);
+#endif
 }
 
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/src/cmd.c nethack/src/cmd.c
--- nh_orig/src/cmd.c	2003-12-07 18:39:13.000000000 -0500
+++ nethack/src/cmd.c	2010-05-13 09:22:21.980839635 -0400
@@ -96,4 +96,5 @@
 extern int NDECL(dowield); /**/
 extern int NDECL(dowieldquiver); /**/
+extern int NDECL(dowieldlauncher); /**/
 extern int NDECL(dozap); /**/
 extern int NDECL(doorganize); /**/
@@ -110,4 +111,5 @@
 STATIC_PTR int NDECL(dotravel);
 # ifdef WIZARD
+int NDECL(wiz_show_rooms);
 STATIC_PTR int NDECL(wiz_wish);
 STATIC_PTR int NDECL(wiz_identify);
@@ -124,4 +126,6 @@
 STATIC_PTR int NDECL(wiz_mon_polycontrol);
 STATIC_PTR int NDECL(wiz_show_wmodes);
+STATIC_PTR int NDECL(wiz_mazewalkmap);
+extern char SpLev_Map[COLNO][ROWNO];
 #if defined(__BORLANDC__) && !defined(_WIN32)
 extern void FDECL(show_borlandc_stats, (winid));
@@ -479,4 +483,8 @@
 enter_explore_mode()
 {
+	/* Solely changed due to public-serverness. */
+	pline("Explore mode has been deactivated.  Sorry.");
+	return 0;
+
 	if(!discover && !wizard) {
 		pline("Beware!  From explore mode there will be no return to normal game.");
@@ -496,4 +504,51 @@
 #ifdef WIZARD
 
+int
+wiz_fliplevel()
+{
+    int f = rnd(3);
+    flip_level(f);
+    if (f & 1) u.uy = (ROWNO-1) - u.uy;
+    if (f & 2) u.ux = (COLNO-1) - u.ux;
+    clear_nhwindow(WIN_MAP);
+    vision_recalc(2);
+    vision_reset();
+    vision_full_recalc = 1;
+    vision_recalc(0);
+    docrt();
+    return 0;
+}
+
+int
+wiz_show_rooms()
+{
+    winid win;
+    int x,y;
+    char row[COLNO+1];
+    struct rm*lev;
+
+    win = create_nhwindow(NHW_TEXT);
+    for (y = 0; y < ROWNO; y++) {
+	for (x = 0; x < COLNO; x++) {
+	    int rno = levl[x][y].roomno;
+	    if (rno == NO_ROOM)
+		row[x] = '.';
+	    else if (rno == SHARED)
+		row[x] = '+';
+	    else if (rno == SHARED_PLUS)
+		row[x] = '*';
+	    else {
+		int i = (rno - ROOMOFFSET) % 52;
+		row[x] = (i < 26) ? ('a'+i) : ('A'+i-26);
+	    }
+	}
+	row[COLNO] = '\0';
+	putstr(win, 0, row);
+    }
+    display_nhwindow(win, TRUE);
+    destroy_nhwindow(win);
+    return 0;
+}
+
 /* ^W command - wish for something */
 STATIC_PTR int
@@ -527,13 +582,75 @@
 	if (wizard) {
 	    struct trap *t;
+	    winid win;
+	    menu_item *pick_list = (menu_item *)0;
+	    anything any;
+	    int n;
 	    long save_Hconf = HConfusion,
 		 save_Hhallu = HHallucination;
 
 	    HConfusion = HHallucination = 0L;
+
+	    win = create_nhwindow(NHW_MENU);
+	    start_menu(win);
+
+	    any.a_void = 0;
+	    any.a_int = 'm'; add_menu(win, NO_GLYPH, &any, 'm', 0, ATR_NONE, "Show map", MENU_UNSELECTED);
+	    any.a_int = 's'; add_menu(win, NO_GLYPH, &any, 's', 0, ATR_NONE, "Show secret doors", MENU_UNSELECTED);
+	    any.a_int = 't'; add_menu(win, NO_GLYPH, &any, 't', 0, ATR_NONE, "Show traps", MENU_UNSELECTED);
+	    any.a_int = 'i'; add_menu(win, NO_GLYPH, &any, 'i', 0, ATR_NONE, "Show items", MENU_UNSELECTED);
+	    any.a_int = 'M'; add_menu(win, NO_GLYPH, &any, 'M', 0, ATR_NONE, "Show monsters", MENU_UNSELECTED);
+	    any.a_int = 'A'; add_menu(win, NO_GLYPH, &any, 'A', 0, ATR_NONE, "All of the above", MENU_UNSELECTED);
+
+	    end_menu(win, "Reveal what");
+
+	    n = select_menu(win, PICK_ANY, &pick_list);
+	    destroy_nhwindow(win);
+	    if (n > 0) {
+		int idx;
+		for (idx = 0; idx < n; idx++) {
+		    if (pick_list[idx].item.a_int == 'm') {
+			do_mapping();
+		    } else if (pick_list[idx].item.a_int == 's') {
+			int x,y;
+			for (x = 0; x < COLNO; x++)
+			    for (y = 0; y < ROWNO; y++)
+				if (levl[x][y].typ == SDOOR) {
+				    cvt_sdoor_to_door(&levl[x][y]);
+				    magic_map_background(x, y, 0);
+				    newsym(x, y);
+				}
+		    } else if (pick_list[idx].item.a_int == 't') {
 	    for (t = ftrap; t != 0; t = t->ntrap) {
 		t->tseen = 1;
 		map_trap(t, TRUE);
 	    }
+		    } else if (pick_list[idx].item.a_int == 'i') {
+			object_detect(NULL, 0);
+		    } else if (pick_list[idx].item.a_int == 'M') {
+			if (HDetect_monsters < 1) incr_itimeout(&HDetect_monsters, 10);
+			see_monsters();
+		    } else if (pick_list[idx].item.a_int == 'A') {
+			int x,y;
 	    do_mapping();
+			for (x = 0; x < COLNO; x++)
+			    for (y = 0; y < ROWNO; y++)
+				if (levl[x][y].typ == SDOOR) {
+				    cvt_sdoor_to_door(&levl[x][y]);
+				    magic_map_background(x, y, 0);
+				    newsym(x, y);
+				}
+			for (t = ftrap; t != 0; t = t->ntrap) {
+			    t->tseen = 1;
+			    map_trap(t, TRUE);
+			}
+			object_detect(NULL, 0);
+			if (HDetect_monsters < 1) incr_itimeout(&HDetect_monsters, 10);
+			see_monsters();
+		    }
+		}
+	    }
+
+            free((genericptr_t)pick_list);
+
 	    HConfusion = save_Hconf;
 	    HHallucination = save_Hhallu;
@@ -593,5 +710,5 @@
 wiz_level_change()
 {
-    char buf[BUFSZ];
+    char buf[BUFSZ] = "";
     int newlevel;
     int ret;
@@ -633,6 +750,37 @@
 wiz_panic()
 {
+	/*
+	 * Hijacked temporarily to sanity-check the new rnd.c code.
+	 * Uncomment to test on your own machine.
+	 *
+
+	int x;
+	int z[20];
+	double q;
+	FILE* testfile;
+
+	for(x=0;x<20;x++)
+	{
+		z[x] = 0;
+	}
+
+	for(x=0;x<=9999999;x++)
+	{
+		z[rn2(20)]++;
+	}
+
+	testfile = fopen("randtest","w");
+	for(x=0;x<20;x++)
+	{
+		q = ((double)z[x] / (double)9999999) * 100;
+		fprintf(testfile,"%2d: %d (%2.3f%%)\n",x,z[x],q);
+	}
+	fclose(testfile);
+
+	*/
+
 	if (yn("Do you want to call panic() and end your game?") == 'y')
 		panic("crash test.");
+
         return 0;
 }
@@ -859,5 +1007,6 @@
 	else if (u.ualign.record >= -3)	you_have("strayed");
 	else if (u.ualign.record >= -8)	you_have("sinned");
-	else you_have("transgressed");
+	else if (u.ualign.record >= -15) you_have("transgressed");
+	else you_are("a filthy heretic");
 #ifdef WIZARD
 	if (wizard) {
@@ -868,20 +1017,31 @@
 
 	/*** Resistances to troubles ***/
-	if (Fire_resistance) you_are("fire resistant");
-	if (Cold_resistance) you_are("cold resistant");
-	if (Sleep_resistance) you_are("sleep resistant");
-	if (Disint_resistance) you_are("disintegration-resistant");
-	if (Shock_resistance) you_are("shock resistant");
-	if (Poison_resistance) you_are("poison resistant");
+	Sprintf(buf,"%d%% fire resistant",how_resistant(FIRE_RES));
+	if (Fire_resistance) you_are(buf);
+	Sprintf(buf,"%d%% cold resistant",how_resistant(COLD_RES));
+	if (Cold_resistance) you_are(buf);
+	Sprintf(buf,"%d%% sleep resistant",how_resistant(SLEEP_RES));
+	if (Sleep_resistance) you_are(buf);
+	Sprintf(buf,"%d%% disintegration-resistant",how_resistant(DISINT_RES));
+	if (Disint_resistance) you_are(buf);
+	Sprintf(buf,"%d%% shock resistant",how_resistant(SHOCK_RES));
+	if (Shock_resistance) you_are(buf);
+	Sprintf(buf,"%d%% poison resistant",how_resistant(POISON_RES));
+	if (Poison_resistance) you_are(buf);
 	if (Drain_resistance) you_are("level-drain resistant");
 	if (Sick_resistance) you_are("immune to sickness");
 	if (Antimagic) you_are("magic-protected");
 	if (Acid_resistance) you_are("acid resistant");
-	if (Stone_resistance)
-		you_are("petrification resistant");
+	if (Stone_resistance) you_are("petrification resistant");
+	if (Confusion_resistance) you_are("confusion resistant");
+	if (Stun_resistance) you_are("stun resistant");
 	if (Invulnerable) you_are("invulnerable");
 	if (u.uedibility) you_can("recognize detrimental food");
 
 	/*** Troubles ***/
+	if (Vulnerable_fire) you_are("vulnerable to fire");
+	if (Vulnerable_cold) you_are("vulnerable to cold");
+	if (Vulnerable_elec) you_are("vulnerable to electricity");
+	if (Vulnerable_acid) you_are("vulnerable to acid");
 	if (Halluc_resistance)
 		enl_msg("You resist", "", "ed", " hallucinations");
@@ -936,4 +1096,5 @@
 		you_are(buf);
 	}
+	if (Blind_resistance) enl_msg(You_,"resist","resisted"," blindness");
 	if (Undead_warning) you_are("warned of undead");
 	if (Searching) you_have("automatic searching");
@@ -1006,4 +1167,5 @@
 	if (Slow_digestion) you_have("slower digestion");
 	if (Regeneration) enl_msg("You regenerate", "", "d", "");
+	if (Energy_regeneration) you_have("faster energy regeneration");
 	if (u.uspellprot || Protection) {
 	    int prot = 0;
@@ -1037,5 +1199,22 @@
 	if (Unchanging) you_can("not change from your current form");
 	if (Fast) you_are(Very_fast ? "very fast" : "fast");
-	if (Reflecting) you_have("reflection");
+	if (Slow) {
+		Strcpy(buf,"slow");
+#ifdef WIZARD
+		if (wizard)
+			if (ESlow) Sprintf(eos(buf)," (from an item)");
+			else Sprintf(eos(buf)," (%d turns)",HSlow);
+#endif
+		you_are(buf);
+	}
+	if (Reflecting) {
+		Strcpy(buf,"reflection");
+#ifdef WIZARD
+		if (wizard)
+			if (EReflecting) Sprintf(eos(buf)," (from an item)");
+			else Sprintf(eos(buf)," (%d turns)",HReflecting);
+#endif
+		you_have(buf);
+	}
 	if (Free_action) you_have("free action");
 	if (Fixed_abil) you_have("fixed abilities");
@@ -1127,4 +1306,318 @@
 }
 
+#ifdef DUMP_LOG
+void
+dump_enlightenment(final)
+int final;
+{
+	int ltmp;
+	char buf[BUFSZ];
+	char buf2[BUFSZ];
+	const char *enc_stat[] = { /* copied from botl.c */
+	     "",
+	     "burdened",
+	     "stressed",
+	     "strained",
+	     "overtaxed",
+	     "overloaded"
+	};
+	char *youwere = "  You were ";
+	char *youhave = "  You have ";
+	char *youhad  = "  You had ";
+	char *youcould = "  You could ";
+
+	dump("", "Final attributes");
+
+#ifdef ELBERETH
+	if (u.uevent.uhand_of_elbereth) {
+	    static const char * const hofe_titles[3] = {
+				"the Hand of Elbereth",
+				"the Envoy of Balance",
+				"the Glory of Arioch"
+	    };
+	    dump(youwere,
+		(char *)hofe_titles[u.uevent.uhand_of_elbereth - 1]);
+	}
+#endif
+
+	if (u.ualign.record >= 20)
+		dump(youwere, "piously aligned");
+	else if (u.ualign.record > 13)
+	    dump(youwere, "devoutly aligned");
+	else if (u.ualign.record > 8)
+	    dump(youwere, "fervently aligned");
+	else if (u.ualign.record > 3)
+	    dump(youwere, "stridently aligned");
+	else if (u.ualign.record == 3)
+	    dump(youwere, "aligned");
+	else if (u.ualign.record > 0)
+	    dump(youwere, "haltingly aligned");
+	else if (u.ualign.record == 0)
+	    dump(youwere, "nominally aligned");
+	else if (u.ualign.record >= -3)	dump(youhave, "strayed");
+	else if (u.ualign.record >= -8)	dump(youhave, "sinned");
+	else if (u.ualign.record >= -15) dump(youhave, "transgressed");
+	else dump("  You are ", "a filthy heretic");
+	Sprintf(buf, " %d", u.ualign.record);
+	dump("  Your alignment was ", buf);
+
+
+	/*** Resistances to troubles ***/
+	Sprintf(buf,"%d%% fire resistant",how_resistant(FIRE_RES));
+	if (Fire_resistance) dump(youwere,buf);
+	Sprintf(buf,"%d%% cold resistant",how_resistant(COLD_RES));
+	if (Cold_resistance) dump(youwere,buf);
+	Sprintf(buf,"%d%% sleep resistant",how_resistant(SLEEP_RES));
+	if (Sleep_resistance) dump(youwere,buf);
+	Sprintf(buf,"%d%% disintegration-resistant",how_resistant(DISINT_RES));
+	if (Disint_resistance) dump(youwere,buf);
+	Sprintf(buf,"%d%% shock resistant",how_resistant(SHOCK_RES));
+	if (Shock_resistance) dump(youwere,buf);
+	Sprintf(buf,"%d%% poison resistant",how_resistant(POISON_RES));
+	if (Poison_resistance) dump(youwere,buf);
+	if (Drain_resistance) dump(youwere, "level-drain resistant");
+	if (Sick_resistance) dump(youwere, "immune to sickness");
+	if (Antimagic) dump(youwere, "magic-protected");
+	if (Acid_resistance) dump(youwere, "acid resistant");
+	if (Stone_resistance) dump(youwere, "petrification resistant");
+	if (Confusion_resistance) dump(youwere, "confusion resistant");
+	if (Stun_resistance) dump(youwere, "stun resistant");
+	if (Invulnerable) dump(youwere, "invulnerable");
+	if (u.uedibility) dump(youcould, "recognize detrimental food");
+
+	/*** Troubles ***/
+	if (Halluc_resistance) 	dump("  ", "You resisted hallucinations");
+	if (Vulnerable_fire) dump(youwere,"vulnerable to fire");
+	if (Vulnerable_cold) dump(youwere,"vulnerable to cold");
+	if (Vulnerable_elec) dump(youwere,"vulnerable to electricity");
+	if (Vulnerable_acid) dump(youwere,"vulnerable to acid");
+	if (Hallucination) dump(youwere, "hallucinating");
+	if (Stunned) dump(youwere, "stunned");
+	if (Confusion) dump(youwere, "confused");
+	if (Blinded) dump(youwere, "blinded");
+	if (Sick) {
+		if (u.usick_type & SICK_VOMITABLE)
+			dump(youwere, "sick from food poisoning");
+		if (u.usick_type & SICK_NONVOMITABLE)
+			dump(youwere, "sick from illness");
+	}
+	if (Stoned) dump(youwere, "turning to stone");
+	if (Slimed) dump(youwere, "turning into slime");
+	if (Strangled)
+		dump(youwere, (u.uburied) ? "buried" : "being strangled");
+	if (Glib) {
+		Sprintf(buf, "slippery %s", makeplural(body_part(FINGER)));
+		dump(youhad, buf);
+	}
+	if (Fumbling) dump("  ", "You fumbled");
+	if (Wounded_legs
+#ifdef STEED
+	    && !u.usteed
+#endif
+			  ) {
+		Sprintf(buf, "wounded %s", makeplural(body_part(LEG)));
+		dump(youhad, buf);
+	}
+#ifdef STEED
+	if (Wounded_legs && u.usteed) {
+	    Strcpy(buf, x_monnam(u.usteed, ARTICLE_YOUR, (char *)0, 
+		    SUPPRESS_SADDLE | SUPPRESS_HALLUCINATION, FALSE));
+	    *buf = highc(*buf);
+	    Strcat(buf, " had wounded legs");
+	    dump("  ", buf);
+	}
+#endif
+	if (Sleeping) dump("  ", "You fell asleep");
+	if (Hunger) dump("  ", "You hungered rapidly");
+
+	/*** Vision and senses ***/
+	if (See_invisible) dump("  ", "You saw invisible");
+	if (Blind_telepat) dump(youwere, "telepathic");
+	if (Warning) dump(youwere, "warned");
+	if (Warn_of_mon && flags.warntype) {
+		Sprintf(buf, "aware of the presence of %s",
+			(flags.warntype & M2_ORC) ? "orcs" :
+			(flags.warntype & M2_DEMON) ? "demons" :
+			something); 
+		dump(youwere, buf);
+	}
+	if (Blind_resistance) dump("  ", "You resisted blindness");
+	if (Undead_warning) dump(youwere, "warned of undead");
+	if (Searching) dump(youhad, "automatic searching");
+	if (Clairvoyant) dump(youwere, "clairvoyant");
+	if (Infravision) dump(youhad, "infravision");
+	if (Detect_monsters)
+	  dump(youwere, "sensing the presence of monsters");
+	if (u.umconf) dump(youwere, "going to confuse monsters");
+
+	/*** Appearance and behavior ***/
+	if (Adornment) {
+	    int adorn = 0;
+	    if(uleft && uleft->otyp == RIN_ADORNMENT) adorn += uleft->spe;
+	    if(uright && uright->otyp == RIN_ADORNMENT) adorn += uright->spe;
+	    if (adorn < 0)
+		dump(youwere, "poorly adorned");
+	    else
+		dump(youwere, "adorned");
+	}
+	if (Invisible) dump(youwere, "invisible");
+	else if (Invis) dump(youwere, "invisible to others");
+	/* ordinarily "visible" is redundant; this is a special case for
+	   the situation when invisibility would be an expected attribute */
+	else if ((HInvis || EInvis || pm_invisible(youmonst.data)) && BInvis)
+	    dump(youwere, "visible");
+	if (Displaced) dump(youwere, "displaced");
+	if (Stealth) dump(youwere, "stealthy");
+	if (Aggravate_monster) dump("  ", "You aggravated monsters");
+	if (Conflict) dump("  ", "You caused conflict");
+
+	/*** Transportation ***/
+	if (Jumping) dump(youcould, "jump");
+	if (Teleportation) dump(youcould, "teleport");
+	if (Teleport_control) dump(youhad, "teleport control");
+	if (Lev_at_will) dump(youwere, "levitating, at will");
+	else if (Levitation)
+	  dump(youwere, "levitating");	/* without control */
+	else if (Flying) dump(youcould, "fly");
+	if (Wwalking) dump(youcould, "walk on water");
+	if (Swimming) dump(youcould, "swim");
+	if (Breathless) dump(youcould, "survive without air");
+	else if (Amphibious) dump(youcould, "breathe water");
+	if (Passes_walls) dump(youcould, "walk through walls");
+#ifdef STEED
+	if (u.usteed && (final < 2 || strcmp(killer, "riding accident"))) {
+	    Sprintf(buf, "riding %s", y_monnam(u.usteed));
+	    dump(youwere, buf);
+	}
+#endif
+	if (u.uswallow) {
+	    Sprintf(buf, "swallowed by %s", a_monnam(u.ustuck));
+#ifdef WIZARD
+	    if (wizard) Sprintf(eos(buf), " (%u)", u.uswldtim);
+#endif
+	    dump(youwere, buf);
+	} else if (u.ustuck) {
+	    Sprintf(buf, "%s %s",
+		    (Upolyd && sticks(youmonst.data)) ? "holding" : "held by",
+		    a_monnam(u.ustuck));
+	    dump(youwere, buf);
+	}
+
+	/*** Physical attributes ***/
+	if (u.uhitinc)
+	    dump(youhad,
+		enlght_combatinc("to hit", u.uhitinc, final, buf));
+	if (u.udaminc)
+	    dump(youhad,
+		enlght_combatinc("damage", u.udaminc, final, buf));
+	if (Slow_digestion) dump(youhad, "slower digestion");
+	if (Regeneration) dump("  ", "You regenerated");
+	if (Energy_regeneration) dump(youhad, "faster energy regeneration");
+	if (u.uspellprot || Protection) {
+	    int prot = 0;
+
+	    if(uleft && uleft->otyp == RIN_PROTECTION) prot += uleft->spe;
+	    if(uright && uright->otyp == RIN_PROTECTION) prot += uright->spe;
+	    if (HProtection & INTRINSIC) prot += u.ublessed;
+	    prot += u.uspellprot;
+	    
+	    if (prot < 0)
+		dump(youwere, "ineffectively protected");
+	    else
+		dump(youwere, "protected");
+	}
+	if (Protection_from_shape_changers)
+		dump(youwere, "protected from shape changers");
+	if (Polymorph) dump(youwere, "polymorphing");
+	if (Polymorph_control) dump(youhad, "polymorph control");
+	if (u.ulycn >= LOW_PM) {
+		Strcpy(buf, an(mons[u.ulycn].mname));
+		dump(youwere, buf);
+	}
+	if (Upolyd) {
+	    if (u.umonnum == u.ulycn) Strcpy(buf, "in beast form");
+	    else Sprintf(buf, "polymorphed into %s",
+			 an(youmonst.data->mname));
+#ifdef WIZARD
+	    if (wizard) Sprintf(eos(buf), " (%d)", u.mtimedone);
+#endif
+	    dump(youwere, buf);
+	}
+	if (Unchanging)
+	  dump(youcould, "not change from your current form");
+	if (Fast) dump(youwere, Very_fast ? "very fast" : "fast");
+	if (Reflecting) dump(youhad, "reflection");
+	if (Free_action) dump(youhad, "free action");
+	if (Fixed_abil) dump(youhad, "fixed abilities");
+	if (Lifesaved)
+		dump("  ", "Your life would have been saved");
+	if (u.twoweap) dump(youwere, "wielding two weapons at once");
+
+	/*** Miscellany ***/
+	if (Luck) {
+	    ltmp = abs((int)Luck);
+	    Sprintf(buf, "%s%slucky (%d)",
+		    ltmp >= 10 ? "extremely " : ltmp >= 5 ? "very " : "",
+		    Luck < 0 ? "un" : "", Luck);
+	    dump(youwere, buf);
+	}
+#ifdef WIZARD
+	 else if (wizard) dump("  ", "Your luck was zero");
+#endif
+	if (u.moreluck > 0) dump(youhad, "extra luck");
+	else if (u.moreluck < 0) dump(youhad, "reduced luck");
+	if (carrying(LUCKSTONE) || stone_luck(TRUE)) {
+	    ltmp = stone_luck(FALSE);
+	    if (ltmp <= 0)
+		dump("  ", "Bad luck did not time out for you");
+	    if (ltmp >= 0)
+		dump("  ", "Good luck did not time out for you");
+	}
+
+	if (u.ugangr) {
+	    Sprintf(buf, " %sangry with you",
+		u.ugangr > 6 ? "extremely " : u.ugangr > 3 ? "very " : "");
+#ifdef WIZARD
+	    if (wizard) Sprintf(eos(buf), " (%d)", u.ugangr);
+#endif
+	    Sprintf(buf2, "%s was %s", u_gname(), buf);
+	    dump("  ", buf2);
+	}
+
+    {
+	const char *p;
+
+	buf[0] = '\0';
+	if (final < 2) {    /* quit/escaped/ascended */
+	    p = "survived after being killed ";
+	    switch (u.umortality) {
+	    case 0:  p = "survived";  break;
+	    case 1:  Strcpy(buf, "once");  break;
+	    case 2:  Strcpy(buf, "twice");  break;
+	    case 3:  Strcpy(buf, "thrice");  break;
+	    default: Sprintf(buf, "%d times", u.umortality);
+		     break;
+	    }
+	} else {		/* game ended in character's death */
+	    p = "are dead";
+	    switch (u.umortality) {
+	    case 0:  impossible("dead without dying?");
+	    case 1:  break;			/* just "are dead" */
+	    default: Sprintf(buf, " (%d%s time!)", u.umortality,
+			     ordin(u.umortality));
+		     break;
+	    }
+	}
+	if (p) {
+	  Sprintf(buf2, "You %s %s", p, buf);
+	  dump("  ", buf2);
+	}
+    }
+	dump("", "");
+	return;
+
+} /* dump_enlightenment */
+#endif
+
 /*
  * Courtesy function for non-debug, non-explorer mode players
@@ -1342,4 +1835,97 @@
 }
 
+#ifdef DUMP_LOG
+void
+dump_conduct(final)
+int final;
+{
+	char buf[BUFSZ];
+	int ngenocided;
+
+	dump("", "Voluntary challenges");
+
+	if (!u.uconduct.food)
+	    dump("", "  You went without food");
+	    /* But beverages are okay */
+	else if (!u.uconduct.unvegan)
+	    dump("", "  You followed a strict vegan diet");
+	else if (!u.uconduct.unvegetarian)
+	    dump("", "  You were a vegetarian");
+	else if (Role_if(PM_MONK) && u.uconduct.unvegetarian < 10) {
+	    sprintf(buf, "  You ate non-vegetarian food %ld time%s.", 
+		u.uconduct.unvegetarian, plur(u.uconduct.unvegetarian));
+	    dump("", buf);
+	}
+
+	if (!u.uconduct.gnostic)
+	    dump("", "  You were an atheist");
+
+	if (!u.uconduct.weaphit)
+	    dump("", "  You never hit with a wielded weapon");
+	else if (Role_if(PM_MONK) && u.uconduct.weaphit < 10) {
+	    Sprintf(buf, "  You hit with a wielded weapon %ld time%s",
+		    u.uconduct.weaphit, plur(u.uconduct.weaphit));
+	    dump("", buf);
+	}
+#ifdef WIZARD
+	else if (wizard) {
+	    Sprintf(buf, "hit with a wielded weapon %ld time%s",
+		    u.uconduct.weaphit, plur(u.uconduct.weaphit));
+	    dump("  You ", buf);
+	}
+#endif
+	if (!u.uconduct.killer)
+	    dump("", "  You were a pacifist");
+
+	if (!u.uconduct.literate)
+	    dump("", "  You were illiterate");
+#ifdef WIZARD
+	else if (wizard) {
+	    Sprintf(buf, "read items or engraved %ld time%s",
+		    u.uconduct.literate, plur(u.uconduct.literate));
+	    dump("  You ", buf);
+	}
+#endif
+
+	ngenocided = num_genocides();
+	if (ngenocided == 0) {
+	    dump("", "  You never genocided any monsters");
+	} else {
+	    Sprintf(buf, "genocided %d type%s of monster%s",
+		    ngenocided, plur(ngenocided), plur(ngenocided));
+	    dump("  You ", buf);
+	}
+
+	if (!u.uconduct.polypiles)
+	    dump("", "  You never polymorphed an object");
+	else {
+	    Sprintf(buf, "polymorphed %ld item%s",
+		    u.uconduct.polypiles, plur(u.uconduct.polypiles));
+	    dump("  You ", buf);
+	}
+
+	if (!u.uconduct.polyselfs)
+	    dump("", "  You never changed form");
+	else {
+	    Sprintf(buf, "changed form %ld time%s",
+		    u.uconduct.polyselfs, plur(u.uconduct.polyselfs));
+	    dump("  You ", buf);
+	}
+
+	if (!u.uconduct.wishes)
+	    dump("", "  You used no wishes");
+	else {
+	    Sprintf(buf, "used %ld wish%s",
+		    u.uconduct.wishes, (u.uconduct.wishes > 1L) ? "es" : "");
+	    dump("  You ", buf);
+
+	    if (!u.uconduct.wisharti)
+		dump("", "  You did not wish for any artifacts");
+	}
+
+	dump("", "");
+}
+#endif /* DUMP_LOG */
+
 #endif /* OVLB */
 #ifdef OVL1
@@ -1470,4 +2056,5 @@
 	{GOLD_SYM, TRUE, doprgold},
 	{SPBOOK_SYM, TRUE, dovspell},			/* Mike Stephenson */
+	{'%', FALSE, dowieldlauncher},
 	{'#', TRUE, doextcmd},
 	{'_', TRUE, dotravel},
@@ -1510,4 +2097,5 @@
 	{(char *)0, (char *)0, donull, TRUE},
 	{(char *)0, (char *)0, donull, TRUE},
+	{(char *)0, (char *)0, donull, TRUE},
 #ifdef DEBUG_MIGRATING_MONS
 	{(char *)0, (char *)0, donull, TRUE},
@@ -1516,4 +2104,5 @@
 	{(char *)0, (char *)0, donull, TRUE},
 	{(char *)0, (char *)0, donull, TRUE},
+	{(char *)0, (char *)0, donull, TRUE},
 #ifdef PORT_DEBUG
 	{(char *)0, (char *)0, donull, TRUE},
@@ -1523,4 +2112,5 @@
 	{(char *)0, (char *)0, donull, TRUE},
 	{(char *)0, (char *)0, donull, TRUE},
+	{(char *)0, (char *)0, donull, TRUE},
 #ifdef DEBUG
 	{(char *)0, (char *)0, donull, TRUE},
@@ -1533,6 +2123,8 @@
 #if defined(WIZARD)
 static const struct ext_func_tab debug_extcmdlist[] = {
+	{"flip_level", "flip level horizontally and/or vertically", wiz_fliplevel, TRUE},
 	{"levelchange", "change experience level", wiz_level_change, TRUE},
 	{"lightsources", "show mobile light sources", wiz_light_sources, TRUE},
+	{"mazewalkmap", "show MAZEWALK paths", wiz_mazewalkmap, TRUE},
 #ifdef DEBUG_MIGRATING_MONS
 	{"migratemons", "migrate n random monsters", wiz_migrate_mons, TRUE},
@@ -1544,4 +2136,5 @@
 	{"portdebug", "wizard port debug command", wiz_port_debug, TRUE},
 #endif
+	{"rooms", "show room numbers", wiz_show_rooms, TRUE},
 	{"seenv", "show seen vectors", wiz_show_seenv, TRUE},
 	{"stats", "show memory statistics", wiz_show_stats, TRUE},
@@ -1698,4 +2291,27 @@
 }
 
+static int
+wiz_mazewalkmap()
+{
+	winid win;
+	int x, y;
+	char row[COLNO+1];
+
+	win = create_nhwindow(NHW_TEXT);
+
+	for (y = 0; y < ROWNO; y++) {
+	    for (x = 0; x < COLNO; x++)
+		row[x] = SpLev_Map[x][y] ? '1' : '.';
+	    if (y == u.uy)
+		row[u.ux] = '@';
+	    row[x] = '\0';
+	    putstr(win, 0, row);
+	}
+	display_nhwindow(win, TRUE);
+	destroy_nhwindow(win);
+	return 0;
+}
+
+
 /*
  * Display memory usage of all monsters and objects on the level.
@@ -1771,5 +2387,5 @@
 {
 	int mcount = 0;
-	char inbuf[BUFSZ];
+	char inbuf[BUFSZ] = "";
 	struct permonst *ptr;
 	struct monst *mtmp;
@@ -2081,5 +2697,7 @@
 {
 	char dirsym;
+	boolean validselection = FALSE;
 
+	while (!validselection) {
 #ifdef REDO
 	if(in_doagain || *readchar_queue)
@@ -2092,7 +2710,8 @@
 	savech(dirsym);
 #endif
-	if(dirsym == '.' || dirsym == 's')
+		if (dirsym == '.' || dirsym == 's') {
 		u.dx = u.dy = u.dz = 0;
-	else if(!movecmd(dirsym) && !u.dz) {
+			validselection = TRUE;
+		} else if(!movecmd(dirsym) && !u.dz) {
 		boolean did_help = FALSE;
 		if(!index(quitchars, dirsym)) {
@@ -2102,7 +2721,12 @@
 		    }
 		    if (!did_help) pline("What a strange direction!");
+			} else {
+				return 0;	/* selected a valid quitchar */
 		}
-		return 0;
+		} else {
+			validselection = TRUE;
 	}
+	}	/* while */
+
 	if(!u.dz && (Stunned || (Confusion && !rn2(5)))) confdir();
 	return 1;
@@ -2243,5 +2867,5 @@
                 cmd[0]=mod == CLICK_1 ? 'q' : M('d');
                 return cmd;
-            } else if(IS_THRONE(levl[u.ux][u.uy].typ)) {
+            } else if(sobj_at(FUR_THRONE,u.ux,u.uy)) {
                 cmd[0]=M('s');
                 return cmd;
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/src/dbridge.c nethack/src/dbridge.c
--- nh_orig/src/dbridge.c	2003-12-07 18:39:13.000000000 -0500
+++ nethack/src/dbridge.c	2009-08-02 13:49:38.690407629 -0400
@@ -364,9 +364,9 @@
 				Flying || Levitation)) ||
 			is_swimmer(etmp->edata) || is_flyer(etmp->edata) ||
-			is_floater(etmp->edata));
+			is_floater(etmp->edata) || is_flying(etmp->emon));
 	/* must force call to lava_effects in e_died if is_u */
 	if (is_lava(x, y))
 		return (boolean)((is_u(etmp) && (Levitation || Flying)) ||
-			    likes_lava(etmp->edata) || is_flyer(etmp->edata));
+			    likes_lava(etmp->edata) || is_flyer(etmp->edata) || is_flying(etmp->emon));
 	if (is_db_wall(x, y))
 		return((boolean)(is_u(etmp) ? Passes_walls :
@@ -466,5 +466,5 @@
 		return(TRUE);
 
-	if (is_flyer(etmp->edata) &&
+	if ((is_flyer(etmp->edata) || is_flying(etmp->emon)) &&
 	    (is_u(etmp)? !Sleeping :
 	     (etmp->emon->mcanmove && !etmp->emon->msleeping)))
@@ -709,5 +709,5 @@
 		if (e_survives_at(etmp, etmp->ex, etmp->ey)) {
 			if (e_inview && !is_flyer(etmp->edata) &&
-			    !is_floater(etmp->edata))
+			    !is_floater(etmp->edata) && !is_flying(etmp->emon))
 				pline("%s from the bridge.",
 				      E_phrase(etmp, "fall"));
@@ -755,4 +755,8 @@
 	lev1 = &levl[x][y];
 	if (lev1->typ != DRAWBRIDGE_DOWN) return;
+	if (rn2(4)) {
+		pline("The mechanism seems to have something stuck in it and won't close.");
+		return;
+	}
 	x2 = x; y2 = y;
 	get_wall_for_db(&x2,&y2);
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/src/decl.c nethack/src/decl.c
--- nh_orig/src/decl.c	2003-12-07 18:39:13.000000000 -0500
+++ nethack/src/decl.c	2009-11-22 07:19:36.373272935 -0500
@@ -21,4 +21,5 @@
 
 NEARDATA int multi = 0;
+char multi_txt[BUFSZ] = DUMMY;
 #if 0
 NEARDATA int warnlevel = 0;		/* used by movemon and dochugw */
@@ -138,4 +139,6 @@
 struct mkroom *upstairs_room, *dnstairs_room, *sstairs_room;
 
+struct engr *head_engr;
+
 dlevel_t level;		/* level map */
 struct trap *ftrap = (struct trap *)0;
@@ -144,4 +147,6 @@
 NEARDATA struct instance_flags iflags = DUMMY;
 NEARDATA struct you u = DUMMY;
+NEARDATA struct monst* polemonst = (struct monst*)0;	/* last monster we tried to polearm */
+NEARDATA struct monst* ukiller = (struct monst*)0;		/* The one that got ya */
 
 NEARDATA struct obj *invent = (struct obj *)0,
@@ -149,4 +154,5 @@
 	*uswapwep = (struct obj *)0,
 	*uquiver = (struct obj *)0, /* quiver */
+	*ulauncher = (struct obj *)0, /* def. ranged weapon */
 #ifdef TOURIST
 	*uarmu = (struct obj *)0, /* under-wear, so to speak */
@@ -210,4 +216,13 @@
 NEARDATA struct mvitals mvitals[NUMMONS];
 
+/* originally from end.c */
+#ifdef DUMP_LOG
+#ifdef DUMP_FN
+char dump_fn[] = DUMP_FN;
+#else
+char dump_fn[PL_PSIZ] = DUMMY;
+#endif
+#endif /* DUMP_LOG */
+
 NEARDATA struct c_color_names c_color_names = {
 	"black", "amber", "golden",
@@ -236,4 +251,8 @@
 };
 
+#ifdef MENU_COLOR
+struct menucoloring *menu_colorings = 0;
+#endif
+
 struct c_common_strings c_common_strings = {
 	"Nothing happens.",		"That's enough tries!",
@@ -272,4 +291,12 @@
 #endif
 
+#ifdef RECORD_ACHIEVE
+struct u_achieve achieve = DUMMY;
+#endif
+
+#if defined(RECORD_REALTIME) || defined(REALTIME_ON_BOTL)
+struct realtime_data realtime_data = { 0, 0, 0 };
+#endif
+
 /* dummy routine used to force linkage */
 void
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/src/detect.c nethack/src/detect.c
--- nh_orig/src/detect.c	2003-12-07 18:39:13.000000000 -0500
+++ nethack/src/detect.c	2010-04-25 13:07:29.306716603 -0400
@@ -298,5 +298,5 @@
     register struct monst *mtmp;
     register int ct = 0, ctu = 0;
-    boolean confused = (Confusion || (sobj && sobj->cursed)), stale;
+    boolean confused = Confusion, stale;
     char oclass = confused ? POTION_CLASS : FOOD_CLASS;
     const char *what = confused ? something : "food";
@@ -695,5 +695,6 @@
     }
     for (obj = fobj; obj; obj = obj->nobj) {
-	if ((obj->otyp==LARGE_BOX || obj->otyp==CHEST) && obj->otrapped) {
+	if ((obj->otyp == LARGE_BOX || obj->otyp == CHEST || obj->otyp == IRON_SAFE) && 
+			obj->otrapped) {
 	    if (obj->ox != u.ux || obj->oy != u.uy)
 		goto outtrapmap;
@@ -726,5 +727,6 @@
 
     for (obj = fobj; obj; obj = obj->nobj)
-	if ((obj->otyp==LARGE_BOX || obj->otyp==CHEST) && obj->otrapped)
+	if ((obj->otyp == LARGE_BOX || obj->otyp == CHEST || obj->otyp == IRON_SAFE) && 
+			obj->otrapped)
 	sense_trap((struct trap *)0, obj->ox, obj->oy, sobj && sobj->cursed);
 
@@ -862,5 +864,5 @@
     }
     You("peer into %s...", the(xname(obj)));
-    nomul(-rnd(10));
+    nomul(-rnd(10), "gazing into a crystal ball");
     nomovemsg = "";
     if (obj->spe <= 0)
@@ -1104,5 +1106,5 @@
 
 	if(u.uswallow) return(0);
-	do_clear_area(u.ux, u.uy, BOLT_LIM, findone, (genericptr_t) &num);
+	do_clear_area(u.ux, u.uy, 8, findone, (genericptr_t) &num);
 	return(num);
 }
@@ -1122,5 +1124,5 @@
 	}
 
-	do_clear_area(u.ux, u.uy, BOLT_LIM, openone, (genericptr_t) &num);
+	do_clear_area(u.ux, u.uy, 8, openone, (genericptr_t) &num);
 	return(num);
 }
@@ -1192,5 +1194,5 @@
 			cvt_sdoor_to_door(&levl[x][y]);	/* .typ = DOOR */
 			exercise(A_WIS, TRUE);
-			nomul(0);
+			nomul(0, 0);
 			if (Blind && !aflag)
 			    feel_location(x,y);	/* make sure it shows up */
@@ -1202,5 +1204,5 @@
 			unblock_point(x,y);	/* vision */
 			exercise(A_WIS, TRUE);
-			nomul(0);
+			nomul(0, 0);
 			newsym(x,y);
 		    } else {
@@ -1247,5 +1249,5 @@
 
 			if ((trap = t_at(x,y)) && !trap->tseen && !rnl(8)) {
-			    nomul(0);
+			    nomul(0, 0);
 
 			    if (trap->ttyp == STATUE_TRAP) {
@@ -1281,6 +1283,12 @@
 	for (x = 1; x < COLNO; x++)
 	    for (y = 0; y < ROWNO; y++) {
+		if (IS_WALL(levl[x][y].typ))
 	    	levl[x][y].seenv = SVALL;
-	    	levl[x][y].waslit = TRUE;
+		else if (levl[x][y].typ == SDOOR)
+		    levl[x][y].typ = DOOR;
+		else if (levl[x][y].typ == SCORR)
+		    levl[x][y].typ = CORR;
+
+		levl[x][y].waslit = (levl[x][y].typ != CORR) ? (!iflags.dark_room) : levl[x][y].lit;
 	    	map_background(x, y, 1);
 	    	for (obj = level.objects[x][y]; obj; obj = obj->nexthere)
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/src/dig.c nethack/src/dig.c
--- nh_orig/src/dig.c	2003-12-07 18:39:13.000000000 -0500
+++ nethack/src/dig.c	2009-11-22 07:19:36.405397990 -0500
@@ -174,7 +174,4 @@
 	    } else if(verbose) pline_The("stairs are too hard to %s.", verb);
 	    return(FALSE);
-	} else if (IS_THRONE(levl[x][y].typ) && madeby != BY_OBJECT) {
-	    if(verbose) pline_The("throne is too hard to break apart.");
-	    return(FALSE);
 	} else if (IS_ALTAR(levl[x][y].typ) && (madeby != BY_OBJECT ||
 				Is_astralevel(&u.uz) || Is_sanctum(&u.uz))) {
@@ -230,5 +227,5 @@
 	    if (IS_TREE(lev->typ) && !may_dig(dpx,dpy) &&
 			dig_typ(uwep, dpx, dpy) == DIGTYP_TREE) {
-		pline("This tree seems to be petrified.");
+		pline("This %stree seems to be petrified.",christmas() ? "christmas " : "");
 		return(0);
 	    }
@@ -305,4 +302,5 @@
 		register struct obj *obj;
 		register boolean shopedge = *in_rooms(dpx, dpy, SHOPBASE);
+		boolean getcoal = FALSE;
 
 		if ((obj = sobj_at(STATUE, dpx, dpy)) != 0) {
@@ -337,5 +335,10 @@
 			}
 			if (IS_TREE(lev->typ)) {
+				if (christmas()) {
+			    digtxt = "You cut down the christmas tree.";
+				 getcoal = TRUE;
+				} else {
 			    digtxt = "You cut down the tree.";
+				}
 			    lev->typ = ROOM;
 			    if (!rn2(5)) (void) rnd_treefruit_at(dpx, dpy);
@@ -381,4 +384,7 @@
 		    newsym(dpx, dpy);
 		if(digtxt && !digging.quiet) pline(digtxt); /* after newsym */
+		if (getcoal) {
+			get_coal();
+		}
 		if(dmgtxt)
 		    pay_for_damage(dmgtxt, FALSE);
@@ -425,5 +431,6 @@
 		    return(0); /* statue or boulder got taken */
 		if(!did_dig_msg) {
-		    You("hit the %s with all your might.",
+		    You("hit the %s%s with all your might.",
+					 (christmas() && dig_target == 5) ? "christmas " : "",
 			d_target[dig_target]);
 		    did_dig_msg = TRUE;
@@ -558,8 +565,8 @@
 			(void) pickup(1);	/* detects pit */
 	    } else if(mtmp) {
-		if(is_flyer(mtmp->data) || is_floater(mtmp->data)) {
+		if(is_flyer(mtmp->data) || is_floater(mtmp->data) || is_flying(mtmp)) {
 		    if(canseemon(mtmp))
 			pline("%s %s over the pit.", Monnam(mtmp),
-						     (is_flyer(mtmp->data)) ?
+						     (is_flyer(mtmp->data) || is_flying(mtmp)) ?
 						     "flies" : "floats");
 		} else if(mtmp != madeby)
@@ -618,5 +625,5 @@
 		     /*[don't we need special sokoban handling here?]*/
 		    if (is_flyer(mtmp->data) || is_floater(mtmp->data) ||
-		        mtmp->data == &mons[PM_WUMPUS] ||
+		        is_flying(mtmp) || mtmp->data == &mons[PM_WUMPUS] ||
 			(mtmp->wormno && count_wsegs(mtmp) > 5) ||
 			mtmp->data->msize >= MZ_HUGE) return;
@@ -735,7 +742,5 @@
 		return TRUE;
 
-	/* the following two are here for the wand of digging */
-	} else if (IS_THRONE(lev->typ)) {
-		pline_The("throne is too hard to break apart.");
+	/* the following is here for the wand of digging */
 
 	} else if (IS_ALTAR(lev->typ)) {
@@ -770,11 +775,11 @@
 	exercise(A_WIS, FALSE);
 	if (Role_if(PM_ARCHEOLOGIST)) {
-	    adjalign(-sgn(u.ualign.type)*3);
+	    minor_sin();
 	    You_feel("like a despicable grave-robber!");
 	} else if (Role_if(PM_SAMURAI)) {
-	    adjalign(-sgn(u.ualign.type));
+	    venial_sin();
 	    You("disturb the honorable dead!");
 	} else if ((u.ualign.type == A_LAWFUL) && (u.ualign.record > -10)) {
-	    adjalign(-sgn(u.ualign.type));
+	    venial_sin();
 	    You("have violated the sanctity of this grave!");
 	}
@@ -917,5 +922,5 @@
 			    /* you ought to be able to let go; tough luck */
 			    /* (maybe `move_into_trap()' would be better) */
-			    nomul(-d(2,2));
+			    nomul(-d(2,2), "stuck in a spider web");
 			    nomovemsg = "You pull free.";
 			} else if (lev->typ == IRONBARS) {
@@ -1046,5 +1051,5 @@
 			str = "door";
 		    else if (IS_TREE(lev->typ))
-			str = "tree";
+			str = christmas() ? "christmas tree" : "tree";
 		    else if (IS_ROCK(lev->typ))
 			str = "wall";
@@ -1238,5 +1243,5 @@
 			unblock_point(zx,zy); /* vision */
 		    } else if (!Blind)
-			pline_The("tree shudders but is unharmed.");
+			pline_The("%stree shudders but is unharmed.",christmas() ? "christmas " : "");
 		    break;
 		} else if (room->typ == STONE || room->typ == SCORR) {
@@ -1441,4 +1446,7 @@
 		uqwepgone();
 		stop_occupation();
+	    } else if (obj == ulauncher) { /* not sure how this would be possible but */
+		ulwepgone();
+		stop_occupation();
 	    }
 	} else if (obj->where == OBJ_MINVENT && obj->owornmask) {
@@ -1554,4 +1562,15 @@
 #endif
 
+void
+get_coal()
+{
+	pline("What a Scrooge! There will surely be consequences...");
+	change_luck(-2);
+	if (!rn2(3)) {
+		pline("The Spirit of Dungeons Past appears before you!");
+		makemon(&mons[PM_SHADE],u.ux,u.uy,MM_ADJACENTOK);
+	}
+}
+
 #ifdef DEBUG
 int
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/src/display.c nethack/src/display.c
--- nh_orig/src/display.c	2003-12-07 18:39:13.000000000 -0500
+++ nethack/src/display.c	2010-04-11 12:36:57.336750392 -0400
@@ -135,4 +135,7 @@
 STATIC_DCL int FDECL(wall_angle, (struct rm *));
 
+/* needed for warning, now */
+extern const int monstr[];
+
 #ifdef INVISIBLE_OBJECTS
 /*
@@ -180,5 +183,5 @@
 	/* Floor spaces are dark if unlit.  Corridors are dark if unlit. */
 	if (lev->typ == ROOM && glyph == cmap_to_glyph(S_room))
-	    glyph = cmap_to_glyph(S_stone);
+	    glyph = cmap_to_glyph(S_darkroom);
 	else if (lev->typ == CORR && glyph == cmap_to_glyph(S_litcorr))
 	    glyph = cmap_to_glyph(S_corr);
@@ -307,5 +310,5 @@
 	if (!lev->waslit && lev->glyph == cmap_to_glyph(S_room) &&
 							    lev->typ == ROOM)
-	    lev->glyph = cmap_to_glyph(S_stone);
+	    lev->glyph = cmap_to_glyph(S_darkroom);
     } else
 	levl[x][y].glyph = cmap_to_glyph(S_stone);	/* default val */
@@ -458,7 +461,8 @@
 {
     int x = mon->mx, y = mon->my;
-    int wl = (int) (mon->m_lev / 4);
+    int wl = (int)((monstr[mon->mnum] - u.ulevel) / 3) + 3;
     int glyph;
 
+	 if (wl < 1) wl = 1;	/* won't show up right */
     if (mon_warning(mon)) {
         if (wl > WARNCOUNT - 1) wl = WARNCOUNT - 1;
@@ -561,13 +565,12 @@
 		    map_background(x, y, 1);
 		} else {
-		    lev->glyph = lev->waslit ? cmap_to_glyph(S_room) :
-					       cmap_to_glyph(S_stone);
+		    lev->glyph = (!lev->waslit) ? cmap_to_glyph(S_darkroom) : cmap_to_glyph(S_room);
 		    show_glyph(x,y,lev->glyph);
 		}
 	    } else if ((lev->glyph >= cmap_to_glyph(S_stone) &&
-			lev->glyph < cmap_to_glyph(S_room)) ||
+			lev->glyph < cmap_to_glyph(S_darkroom)) ||
 		       glyph_is_invisible(levl[x][y].glyph)) {
-		lev->glyph = lev->waslit ? cmap_to_glyph(S_room) :
-					   cmap_to_glyph(S_stone);
+		lev->glyph = (!cansee(x,y) && !lev->waslit) ? cmap_to_glyph(S_darkroom) :
+					   cmap_to_glyph(S_room);
 		show_glyph(x,y,lev->glyph);
 	    }
@@ -609,5 +612,5 @@
 	if (lev->typ == ROOM &&
 		    lev->glyph == cmap_to_glyph(S_room) && !lev->waslit)
-	    show_glyph(x,y, lev->glyph = cmap_to_glyph(S_stone));
+	    show_glyph(x,y, lev->glyph = cmap_to_glyph(S_darkroom));
 	else if (lev->typ == CORR &&
 		    lev->glyph == cmap_to_glyph(S_litcorr) && !lev->waslit)
@@ -637,4 +640,6 @@
     if (in_mklev) return;
 
+	 if (!isok(x,y)) return;
+
     /* only permit updating the hero when swallowed */
     if (u.uswallow) {
@@ -753,9 +758,9 @@
 	 * They are dependent on the position being out of sight.
 	 */
-	else if (!lev->waslit) {
+	else if (!lev->waslit || (iflags.dark_room && iflags.use_color)) {
 	    if (lev->glyph == cmap_to_glyph(S_litcorr) && lev->typ == CORR)
 		show_glyph(x, y, lev->glyph = cmap_to_glyph(S_corr));
 	    else if (lev->glyph == cmap_to_glyph(S_room) && lev->typ == ROOM)
-		show_glyph(x, y, lev->glyph = cmap_to_glyph(S_stone));
+		show_glyph(x, y, lev->glyph = cmap_to_glyph(S_darkroom));
 	    else
 		goto show_mem;
@@ -887,5 +892,5 @@
 	default:	/* do it */
 	    if (tglyph->style == DISP_BEAM) {
-		if (!cansee(x,y)) break;
+			if (!isok(x,y) || !cansee(x,y)) break;
 		/* save pos for later erasing */
 		tglyph->saved[tglyph->sidx].x = x;
@@ -897,5 +902,5 @@
 		    tglyph->sidx = 0;	/* display is presently up to date */
 		}
-		if (!cansee(x,y) && tglyph->style != DISP_ALWAYS) break;
+			if (isok(x,y) && !cansee(x,y) && tglyph->style != DISP_ALWAYS) break;
 		tglyph->saved[0].x = x;
 		tglyph->saved[0].y = y;
@@ -1219,4 +1224,8 @@
      */
     if (!isok(x, y)) {
+
+		/* Stop crashing the game just because you couldn't draw a character */
+
+#if 0
 	const char *text;
 	int  offset;
@@ -1256,12 +1265,17 @@
 	}
 
-	impossible("show_glyph:  bad pos %d %d with glyph %d [%s %d].",
-						x, y, glyph, text, offset);
+		 impossible("show_glyph:  bad pos %d %d with glyph %d [%s %d].", x, y, glyph, text, offset);
+
+#endif
+
 	return;
     }
 
     if (glyph >= MAX_GLYPH) {
-	impossible("show_glyph:  bad glyph %d [max %d] at (%d,%d).",
-					glyph, MAX_GLYPH, x, y);
+		/*
+		 * Same here.  There's no reason to crash out, just don't show an illegal glyph and move on
+		 *
+		 * impossible("show_glyph:  bad glyph %d [max %d] at (%d,%d).", glyph, MAX_GLYPH, x, y);
+		 */
 	return;
     }
@@ -1371,4 +1385,104 @@
 /* ========================================================================= */
 
+#ifdef DUMP_LOG
+/* D: Added to dump screen to output file */
+STATIC_PTR uchar get_glyph_char(glyph)
+int glyph;
+{
+    uchar   ch;
+    register int offset;
+
+    if (glyph >= NO_GLYPH)
+        return ' ';
+
+    /*
+     *  Map the glyph back to a character.
+     *
+     *  Warning:  For speed, this makes an assumption on the order of
+     *		  offsets.  The order is set in display.h.
+     */
+    if ((offset = (glyph - GLYPH_WARNING_OFF)) >= 0) {	/* a warning flash */
+	ch = def_warnsyms[offset].sym;
+    } else if ((offset = (glyph - GLYPH_SWALLOW_OFF)) >= 0) {	/* swallow */
+	/* see swallow_to_glyph() in display.c */
+	ch = (uchar) defsyms[S_sw_tl + (offset & 0x7)].sym;
+    } else if ((offset = (glyph - GLYPH_ZAP_OFF)) >= 0) {	/* zap beam */
+	/* see zapdir_to_glyph() in display.c */
+	ch = defsyms[S_vbeam + (offset & 0x3)].sym;
+    } else if ((offset = (glyph - GLYPH_CMAP_OFF)) >= 0) {	/* cmap */
+	ch = defsyms[offset].sym;
+    } else if ((offset = (glyph - GLYPH_OBJ_OFF)) >= 0) {	/* object */
+	ch = def_oc_syms[(int)objects[offset].oc_class];
+    } else if ((offset = (glyph - GLYPH_RIDDEN_OFF)) >= 0) { /* mon ridden */
+	ch = def_monsyms[(int)mons[offset].mlet];
+    } else if ((offset = (glyph - GLYPH_BODY_OFF)) >= 0) {	/* a corpse */
+	ch = def_oc_syms[(int)objects[CORPSE].oc_class];
+    } else if ((offset = (glyph - GLYPH_DETECT_OFF)) >= 0) { /* mon detect */
+	ch = def_monsyms[(int)mons[offset].mlet];
+    } else if ((offset = (glyph - GLYPH_INVIS_OFF)) >= 0) {  /* invisible */
+	ch = DEF_INVISIBLE;
+    } else if ((offset = (glyph - GLYPH_PET_OFF)) >= 0) {	/* a pet */
+	ch = def_monsyms[(int)mons[offset].mlet];
+    } else {						    /* a monster */
+	ch = monsyms[(int)mons[glyph].mlet];
+    }
+    return ch;
+}
+
+#ifdef TTY_GRAPHICS
+extern const char * FDECL(compress_str, (const char *));
+#else
+const char*
+compress_str(str) /* copied from win/tty/wintty.c */
+const char *str;
+{
+	static char cbuf[BUFSZ];
+	/* compress in case line too long */
+	if((int)strlen(str) >= 80) {
+		register const char *bp0 = str;
+		register char *bp1 = cbuf;
+
+		do {
+			if(*bp0 != ' ' || bp0[1] != ' ')
+				*bp1++ = *bp0;
+		} while(*bp0++);
+	} else
+	    return str;
+	return cbuf;
+}
+#endif /* TTY_GRAPHICS */
+
+/* Take a screen dump */
+void dump_screen()
+{
+    register int x,y;
+    int lastc;
+    /* D: botl.c has a closer approximation to the size, but we'll go with
+     *    this */
+    char buf[300], *ptr;
+    
+    for (y = 0; y < ROWNO; y++) {
+	lastc = 0;
+	ptr = buf;
+	for (x = 1; x < COLNO; x++) {
+	    uchar c = get_glyph_char(gbuf[y][x].glyph);
+	    *ptr++ = c;
+	    if (c != ' ')
+		lastc = x;
+	}
+	buf[lastc] = '\0';
+	dump("", buf);
+    }
+    dump("", "");
+    bot1str(buf);
+    ptr = (char *) compress_str((const char *) buf);
+    dump("", ptr);
+    bot2str(buf);
+    dump("", buf);
+    dump("", "");
+    dump("", "");
+}
+#endif /* DUMP_LOG */
+
 /*
  * back_to_glyph()
@@ -1398,5 +1512,7 @@
 	    idx = level.flags.arboreal ? S_tree : S_stone;
 	    break;
-	case ROOM:		idx = S_room;	  break;
+	case ROOM:
+	    idx = (!cansee(x,y) && !ptr->waslit) ? S_darkroom : S_room;
+	    break;
 	case CORR:
 	    idx = (ptr->waslit || flags.lit_corridor) ? S_litcorr : S_corr;
@@ -1441,5 +1557,4 @@
 	case ALTAR:		idx = S_altar;    break;
 	case GRAVE:		idx = S_grave;    break;
-	case THRONE:		idx = S_throne;   break;
 	case LAVAPOOL:		idx = S_lava;	  break;
 	case ICE:		idx = S_ice;      break;
@@ -1455,9 +1570,9 @@
 	    case DB_LAVA:  idx = S_lava; break;
 	    case DB_ICE:   idx = S_ice;  break;
-	    case DB_FLOOR: idx = S_room; break;
+	    case DB_FLOOR: idx = (!cansee(x,y) && !ptr->waslit) ? S_darkroom : S_room; break;
 	    default:
 		impossible("Strange db-under: %d",
 			   ptr->drawbridgemask & DB_UNDER);
-		idx = S_room; /* something is better than nothing */
+		idx = (!cansee(x,y) && !ptr->waslit) ? S_darkroom : S_room; /* something is better than nothing */
 		break;
 	    }
@@ -1468,5 +1583,5 @@
 	default:
 	    impossible("back_to_glyph:  unknown level type [ = %d ]",ptr->typ);
-	    idx = S_room;
+	    idx = (!cansee(x,y) && !ptr->waslit) ? S_darkroom : S_room;
 	    break;
     }
@@ -1557,5 +1672,5 @@
 	"MOAT",		"WATER",	"DRAWBRIDGE_UP","LAVAPOOL",
 	"DOOR",		"CORR",		"ROOM",		"STAIRS",
-	"LADDER",	"FOUNTAIN",	"THRONE",	"SINK",
+	"LADDER",	"FOUNTAIN",			"SINK",
 	"ALTAR",	"ICE",		"DRAWBRIDGE_DOWN","AIR",
 	"CLOUD"
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/src/do.c nethack/src/do.c
--- nh_orig/src/do.c	2003-12-07 18:39:13.000000000 -0500
+++ nethack/src/do.c	2009-10-23 14:33:39.377272693 -0400
@@ -109,9 +109,7 @@
 		    You("find yourself on dry land again!");
 		} else if (lava && distu(rx,ry) <= 2) {
-		    You("are hit by molten lava%c",
-			Fire_resistance ? '.' : '!');
+		    You("are hit by molten lava%c", (how_resistant(FIRE_RES) > 50) ? '.' : '!');
 			burn_away_slime();
-		    losehp(d((Fire_resistance ? 1 : 3), 6),
-			   "molten lava", KILLED_BY);
+		    losehp(resist_reduce(d(3,6),FIRE_RES), "molten lava", KILLED_BY);
 		} else if (!fills_up && flags.verbose &&
 			   (pushing ? !Blind : cansee(rx,ry)))
@@ -474,4 +472,7 @@
 		setuswapwep((struct obj *)0);
 	}
+	if (obj == ulauncher) {
+		setulauncher((struct obj*)0);
+	}
 
 	if (u.uswallow) {
@@ -540,4 +541,5 @@
 	if (obj == uwep) setuwep((struct obj *)0);
 	if (obj == uquiver) setuqwep((struct obj *)0);
+	if (obj == ulauncher) setulauncher((struct obj *)0);
 	if (obj == uswapwep) setuswapwep((struct obj *)0);
 
@@ -979,22 +981,31 @@
 	/* If you have the amulet and are trying to get out of Gehennom, going
 	 * up a set of stairs sometimes does some very strange things!
-	 * Biased against law and towards chaos, but not nearly as strongly
-	 * as it used to be (prior to 3.2.0).
-	 * Odds:	    old				    new
-	 *	"up"    L      N      C		"up"    L      N      C
-	 *	 +1   75.0   75.0   75.0	 +1   75.0   75.0   75.0
-	 *	  0    0.0   12.5   25.0	  0    6.25   8.33  12.5
-	 *	 -1    8.33   4.17   0.0	 -1    6.25   8.33  12.5
-	 *	 -2    8.33   4.17   0.0	 -2    6.25   8.33   0.0
-	 *	 -3    8.33   4.17   0.0	 -3    6.25   0.0    0.0
+	 *
+	 * No longer biased, because it's bad enough to get zotzed without getting
+	 * absolutely bludgeoned to death by being dropped too many levels.  This
+	 * was really just annoying players to no good effect; Rodney's appearance
+	 * rate is tuned up for Lawful and Nootral players to help counter this change.
+	 *
+	 * Odds:        older                       old            Newest
+	 *	"up"    L      N      C		"up"    L      N      C		  L/N/C
+	 *	 +1   75.0   75.0   75.0	 +1   75.0   75.0   75.0      75.0
+	 *	  0    0.0   12.5   25.0	  0    6.25   8.33  12.5      12.5
+	 *	 -1    8.33   4.17   0.0	 -1    6.25   8.33  12.5      12.5
+	 *	 -2    8.33   4.17   0.0	 -2    6.25   8.33   0.0       0.0
+	 *	 -3    8.33   4.17   0.0	 -3    6.25   0.0    0.0       0.0
+	 *
+	 *	 11/19: Removed entirely as part of an experiment with new nasty()
+	 *	 functionality; clog the stairs with critters, but let the player move
+	 *	 between levels without jerking him around.
+	 *
 	 */
+#if 0
 	if (Inhell && up && u.uhave.amulet && !newdungeon && !portal &&
 				(dunlev(&u.uz) < dunlevs_in_dungeon(&u.uz)-3)) {
 		if (!rn2(4)) {
-		    int odds = 3 + (int)u.ualign.type,		/* 2..4 */
-			diff = odds <= 1 ? 0 : rn2(odds);	/* paranoia */
-
+		    int diff = rn2(2);
 		    if (diff != 0) {
 			assign_rnd_level(newlevel, &u.uz, diff);
+
 			/* if inside the tower, stay inside */
 			if (was_in_W_tower &&
@@ -1015,4 +1026,5 @@
 		}
 	}
+#endif
 
 	/* Prevent the player from going past the first quest level unless
@@ -1134,15 +1146,8 @@
 		} else {
 		    if (newdungeon) {
-			if (Is_stronghold(&u.uz)) {
-			    register xchar x, y;
-
-			    do {
-				x = (COLNO - 2 - rnd(5));
-				y = rn1(ROWNO - 4, 3);
-			    } while(occupied(x, y) ||
-				    IS_WALL(levl[x][y].typ));
-			    u_on_newpos(x, y);
-			} else u_on_sstairs();
-		    } else u_on_dnstairs();
+				u_on_sstairs();
+			} else {
+				u_on_dnstairs();
+			}
 		}
 		/* Remove bug which crashes with levitation/punishment  KAA */
@@ -1284,4 +1289,8 @@
 		You_hear("groans and moans everywhere.");
 	    } else pline("It is hot here.  You smell smoke...");
+
+#ifdef RECORD_ACHIEVE
+            achieve.enter_gehennom = 1;
+#endif
 	}
 
@@ -1319,6 +1328,12 @@
 #endif
 	/* Final confrontation */
-	if (In_endgame(&u.uz) && newdungeon && u.uhave.amulet)
+	if (In_endgame(&u.uz) && newdungeon && u.uhave.amulet) {
+#ifdef WISH_TRACKER
+		char buf[512];
+		Sprintf(buf,"%s just entered the Plane of Earth on T:%d!",plname,moves);
+		makeannounce(buf);
+#endif
 		resurrect();
+	}
 	if (newdungeon && In_V_tower(&u.uz) && In_hell(&u.uz0))
 		pline_The("heat and smoke are gone.");
@@ -1357,4 +1372,12 @@
 	(void) in_out_region(u.ux, u.uy);
 	(void) pickup(1);
+
+	/* Don't autotarget a monster on a level you've just left */
+	polemonst = 0;
+
+#ifdef WHEREIS_FILE
+	touch_whereis();
+#endif
+
 }
 
@@ -1364,4 +1387,5 @@
 	struct monst *mtmp;
 	struct obj *otmp;
+	char buf[512];
 	coord mm;
 	int i;
@@ -1374,4 +1398,9 @@
 	create_mplayers(rn1(4, 3), TRUE);
 
+#ifdef WISH_TRACKER
+	Sprintf(buf,"%s just entered the Astral Plane on T:%d!",plname,moves);
+	makeannounce(buf);
+#endif
+
 	/* create a guardian angel next to player, if worthy */
 	if (Conflict) {
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/src/dog.c nethack/src/dog.c
--- nh_orig/src/dog.c	2003-12-07 18:39:13.000000000 -0500
+++ nethack/src/dog.c	2009-08-02 13:49:38.693407991 -0400
@@ -101,4 +101,7 @@
 	    if (chance > 2) chance = otmp->blessed ? 0 : !otmp->cursed ? 1 : 2;
 	    /* 0,1,2:  b=80%,10,10; nc=10%,80,10; c=10%,10,80 */
+		 if (Role_if(PM_KNIGHT) && mtmp->data->mlet == S_DRAGON) {
+		 	chance = 2;
+		 }
 	    if (chance > 0) {
 		mtmp->mtame = 0;	/* not tame after all */
@@ -141,6 +144,11 @@
 	if (pettype == PM_LITTLE_DOG)
 		petname = dogname;
-	else if (pettype == PM_PONY)
+	else if (pettype == PM_PONY) {
 		petname = horsename;
+		/* hijack creation for chaotic knights */
+		if (u.ualign.type == A_CHAOTIC && Role_if(PM_KNIGHT)) {
+			pettype = PM_NIGHTMARE;
+		}
+	}
 	else
 		petname = catname;
@@ -161,5 +169,5 @@
 #ifdef STEED
 	/* Horses already wear a saddle */
-	if (pettype == PM_PONY && !!(otmp = mksobj(SADDLE, TRUE, FALSE))) {
+	if ((pettype == PM_PONY || pettype == PM_NIGHTMARE) && !!(otmp = mksobj(SADDLE, TRUE, FALSE))) {
 	    if (mpickobj(mtmp, otmp))
 		panic("merged saddle?");
@@ -636,4 +644,8 @@
 	mtmp->muy = new_lev.dlevel;
 	mtmp->mx = mtmp->my = 0;	/* this implies migration */
+	/* if we were targeting it, clear the target */
+	if (mtmp == polemonst) {
+		polemonst = 0;
+	}
 }
 
@@ -754,4 +766,9 @@
 		return((struct monst *)0);
 
+	/* Knights can never tame dragons.  Natural enemies, y'see. */
+	if (Role_if(PM_KNIGHT) && mtmp->data->mlet == S_DRAGON) {
+		return ((struct monst *)0);
+	}
+
 	/* worst case, at least it'll be peaceful. */
 	mtmp->mpeaceful = 1;
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/src/dogmove.c nethack/src/dogmove.c
--- nh_orig/src/dogmove.c	2003-12-07 18:39:13.000000000 -0500
+++ nethack/src/dogmove.c	2009-08-02 13:49:38.683408178 -0400
@@ -513,5 +513,5 @@
 	/* Let steeds eat and maybe throw rider during Conflict */
 	if (mtmp == u.usteed) {
-	    if (Conflict && !resist(mtmp, RING_CLASS, 0, 0)) {
+	    if (Conflict && !resist_conflict(mtmp)) {
 		dismount_steed(DISMOUNT_THROWN);
 		return (1);
@@ -545,5 +545,5 @@
 	if (passes_bars(mtmp->data)) allowflags |= ALLOW_BARS;
 	if (throws_rocks(mtmp->data)) allowflags |= ALLOW_ROCK;
-	if (Conflict && !resist(mtmp, RING_CLASS, 0, 0)) {
+	if (Conflict && !resist_conflict(mtmp)) {
 	    allowflags |= ALLOW_U;
 	    if (!has_edog) {
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/src/dokick.c nethack/src/dokick.c
--- nh_orig/src/dokick.c	2003-12-07 18:39:13.000000000 -0500
+++ nethack/src/dokick.c	2009-10-05 13:36:36.238417575 -0400
@@ -18,5 +18,5 @@
 STATIC_DCL void FDECL(kick_monster, (XCHAR_P, XCHAR_P));
 STATIC_DCL int FDECL(kick_object, (XCHAR_P, XCHAR_P));
-STATIC_DCL char *FDECL(kickstr, (char *));
+STATIC_DCL char *FDECL(kickstr, (int,int,char *));
 STATIC_DCL void FDECL(otransit_msg, (struct obj *, BOOLEAN_P, long));
 STATIC_DCL void FDECL(drop_to, (coord *,SCHAR_P));
@@ -36,4 +36,6 @@
 	int blessed_foot_damage = 0;
 	boolean trapkilled = FALSE;
+	boolean forcepush = FALSE;
+	struct trap* ttmp;
 
 	if (uarmf && uarmf->otyp == KICKING_BOOTS)
@@ -87,13 +89,27 @@
 	if (uarmf) dmg += uarmf->spe;
 	dmg += u.udaminc;	/* add ring(s) of increase damage */
-	if (dmg > 0)
-		mon->mhp -= dmg;
-	if (mon->mhp > 0 && martial() && !bigmonst(mon->data) && !rn2(3) &&
-	    mon->mcanmove && mon != u.ustuck && !mon->mtrapped) {
+	if (dmg > 0) {
+		damage_mon(mon,dmg,AD_PHYS);
+	}
+
+	/* THIS. IS. YENDOOOOOR? */
+	mdx = mon->mx + u.dx;
+	mdy = mon->my + u.dy;
+	if (isok(mdx,mdy)) {
+		ttmp = t_at(mdx,mdy);
+		if (ttmp && (ttmp->ttyp == PIT || ttmp->ttyp == SPIKED_PIT)) { 
+			forcepush = TRUE;
+		}
+	}
+
+	if ((mon->mhp > 0 && !bigmonst(mon->data) && mon != u.ustuck && !mon->mtrapped) && 
+			((!rn2(3) && martial() && mon->mcanmove) || forcepush)) {
 		/* see if the monster has a place to move into */
 		mdx = mon->mx + u.dx;
 		mdy = mon->my + u.dy;
 		if(goodpos(mdx, mdy, mon, 0)) {
+			if (!forcepush) {
 			pline("%s reels from the blow.", Monnam(mon));
+			}
 			if (m_in_out_region(mon, mdx, mdy)) {
 			    remove_monster(mon->mx, mon->my);
@@ -122,4 +138,6 @@
 	register struct monst *mon = m_at(x, y);
 	register int i, j;
+	struct trap* ttmp;
+	int mdx,mdy;
 
 	bhitpos.x = x;
@@ -169,5 +187,5 @@
 
 	if(Levitation && !rn2(3) && verysmall(mon->data) &&
-	   !is_flyer(mon->data)) {
+	   !is_flyer(mon->data) && !is_flying(mon)) {
 		pline("Floating in the air, you miss wildly!");
 		exercise(A_DEX, FALSE);
@@ -182,4 +200,13 @@
 		if(!rn2((i < j/10) ? 2 : (i < j/5) ? 3 : 4)) {
 			if(martial() && !rn2(2)) goto doit;
+			mdx = mon->mx + u.dx;
+			mdy = mon->my + u.dy;
+			/* even a zero-damage kick may push them in */
+			if (isok(mdx,mdy)) {
+				ttmp = t_at(mdx,mdy);
+				if (ttmp && (ttmp->ttyp == PIT || ttmp->ttyp == SPIKED_PIT)) {
+					goto doit;
+				}
+			}
 			Your("clumsy kick does no damage.");
 			(void) passive(mon, FALSE, 1, AT_KICK);
@@ -216,5 +243,5 @@
 				(can_teleport(mon->data) ? "teleports" :
 				 is_floater(mon->data) ? "floats" :
-				 is_flyer(mon->data) ? "swoops" :
+				 (is_flyer(mon->data) || is_flying(mon)) ? "swoops" :
 				 (nolimbs(mon->data) || slithy(mon->data)) ?
 					"slides" : "jumps"),
@@ -507,8 +534,12 @@
 		boolean otrp = kickobj->otrapped;
 
-		if(range < 2) pline("THUD!");
+		if(range < 2) pline("%s",kickobj->otyp == IRON_SAFE ? "CLANG!" : "THUD!");
 
 		container_impact_dmg(kickobj);
 
+		if (kickobj->otyp == IRON_SAFE) { /* can't kick these open or break 'em */
+			return 1;
+		}
+
 		if (kickobj->olocked) {
 		    if (!rn2(5) || (martial() && !rn2(2))) {
@@ -594,5 +625,6 @@
 
 STATIC_OVL char *
-kickstr(buf)
+kickstr(x,y,buf)
+int x,y;
 char *buf;
 {
@@ -601,8 +633,8 @@
 	if (kickobj) what = distant_name(kickobj,doname);
 	else if (IS_DOOR(maploc->typ)) what = "a door";
-	else if (IS_TREE(maploc->typ)) what = "a tree";
+	else if (IS_TREE(maploc->typ)) what = christmas() ? "a christmas tree" : "a tree";
 	else if (IS_STWALL(maploc->typ)) what = "a wall";
 	else if (IS_ROCK(maploc->typ)) what = "a rock";
-	else if (IS_THRONE(maploc->typ)) what = "a throne";
+	else if (sobj_at(FUR_THRONE, x,y)) what = "a throne";
 	else if (IS_FOUNTAIN(maploc->typ)) what = "a fountain";
 	else if (IS_GRAVE(maploc->typ)) what = "a headstone";
@@ -777,4 +809,5 @@
 	kickobj = (struct obj *)0;
 	if (OBJ_AT(x, y) &&
+	    (objects[level.objects[x][y]->otyp].oc_class != FURNITURE_CLASS) &&
 	    (!Levitation || Is_airlevel(&u.uz) || Is_waterlevel(&u.uz)
 	     || sobj_at(BOULDER,x,y))) {
@@ -826,10 +859,12 @@
 		    } else goto ouch;
 		}
-		if(IS_THRONE(maploc->typ)) {
+		if(sobj_at(FUR_THRONE,x,y)) {
 		    register int i;
+		    struct obj *tmpobj = sobj_at(FUR_THRONE, x,y);
 		    if(Levitation) goto dumb;
-		    if((Luck < 0 || maploc->doormask) && !rn2(3)) {
-			maploc->typ = ROOM;
-			maploc->doormask = 0; /* don't leave loose ends.. */
+		    if((Luck < 0) && !rn2(3)) {
+			obj_extract_self(tmpobj);
+			dealloc_obj(tmpobj);
+			tmpobj = NULL;
 			(void) mkgold((long)rnd(200), x, y);
 			if (Blind)
@@ -841,5 +876,5 @@
 			exercise(A_DEX, TRUE);
 			return(1);
-		    } else if(Luck > 0 && !rn2(3) && !maploc->looted) {
+		    } else if(Luck > 0 && !rn2(3) && !tmpobj->obroken) {
 			(void) mkgold((long) rn1(201, 300), x, y);
 			i = Luck + 1;
@@ -855,5 +890,5 @@
 			}
 			/* prevent endless milking */
-			maploc->looted = T_LOOTED;
+			tmpobj->obroken = 1;
 			return(1);
 		    } else if (!rn2(4)) {
@@ -890,4 +925,23 @@
 		if(IS_TREE(maploc->typ)) {
 		    struct obj *treefruit;
+			/* special-case for christmas... :) */
+			if (christmas()) {
+				coord loc;
+				/* we can cheat with enexto to find an empty spot
+				 * next to the tree to drop our present... */
+				if (!rn2(5) || !enexto(&loc,x,y,(struct permonst*)0) ||
+						(maploc->looted & TREE_LOOTED) || In_quest(&u.uz)) {
+					goto ouch;
+				}
+				treefruit = mkobj_at(RANDOM_CLASS,loc.x,loc.y,FALSE);
+				if (treefruit) {
+					pline("%s falls out!",Blind ? "Something" : "A present");
+					newsym(loc.x,loc.y);
+					maploc->looted |= TREE_LOOTED;
+					return 1;
+				} else {
+					goto ouch;
+				}
+			}
 		    /* nothing, fruit or trouble? 75:23.5:1.5% */
 		    if (rn2(3)) {
@@ -926,7 +980,6 @@
 		    	mm.x = x; mm.y = y;
 			while (cnt--) {
-			    if (enexto(&mm, mm.x, mm.y, &mons[PM_KILLER_BEE])
-				&& makemon(&mons[PM_KILLER_BEE],
-					       mm.x, mm.y, MM_ANGRY))
+					if (enexto(&mm, mm.x, mm.y, &mons[PM_KILLER_BEE]) && 
+							makemon(&mons[PM_KILLER_BEE], mm.x, mm.y, MM_ANGRY))
 				made++;
 			}
@@ -1010,5 +1063,5 @@
 		    }
 		    if(!rn2(3)) set_wounded_legs(RIGHT_SIDE, 5 + rnd(5));
-		    losehp(rnd(ACURR(A_CON) > 15 ? 3 : 5), kickstr(buf),
+		    losehp(rnd(ACURR(A_CON) > 15 ? 3 : 5), kickstr(x,y,buf),
 			KILLED_BY);
 		    if(Is_airlevel(&u.uz) || Levitation)
@@ -1339,4 +1392,5 @@
 	if (otmp == uwep) setuwep((struct obj *)0);
 	if (otmp == uquiver) setuqwep((struct obj *)0);
+	if (otmp == ulauncher) setulauncher((struct obj *)0);
 	if (otmp == uswapwep) setuswapwep((struct obj *)0);
 
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/src/do_name.c nethack/src/do_name.c
--- nh_orig/src/do_name.c	2003-12-07 18:39:13.000000000 -0500
+++ nethack/src/do_name.c	2010-04-29 10:53:23.922715740 -0400
@@ -225,5 +225,5 @@
 do_mname()
 {
-	char buf[BUFSZ];
+	char buf[BUFSZ] = "";
 	coord cc;
 	register int cx,cy;
@@ -271,4 +271,12 @@
 	(void) distant_monnam(mtmp, ARTICLE_THE, buf);
 	Sprintf(qbuf, "What do you want to call %s?", buf);
+
+	if (mtmp->data->mlet == S_DOG)
+	    strncpy(buf, dogname, BUFSZ);
+	else if (mtmp->data->mlet == S_FELINE)
+	    strncpy(buf, catname, BUFSZ);
+	else if (mtmp->data->mlet == S_UNICORN)
+	    strncpy(buf, horsename, BUFSZ);
+
 	getlin(qbuf,buf);
 	if(!*buf || *buf == '\033') return(0);
@@ -293,5 +301,5 @@
 register struct obj *obj;
 {
-	char buf[BUFSZ], qbuf[QBUFSZ];
+	char buf[BUFSZ] = "", qbuf[QBUFSZ];
 	const char *aname;
 	short objtyp;
@@ -312,13 +320,7 @@
 		return;
 	} else if (restrict_name(obj, buf) || exist_artifact(obj->otyp, buf)) {
-		int n = rn2((int)strlen(buf));
-		register char c1, c2;
-
-		c1 = lowc(buf[n]);
-		do c2 = 'a' + rn2('z'-'a'); while (c1 == c2);
-		buf[n] = (buf[n] == c1) ? c2 : highc(c2);  /* keep same case */
-		pline("While engraving your %s slips.", body_part(HAND));
+		pline("You realize there can only ever be one %s, and decide against it.",buf);
 		display_nhwindow(WIN_MESSAGE, FALSE);
-		You("engrave: \"%s\".",buf);
+		return;
 	}
 	obj = oname(obj, buf);
@@ -463,5 +465,7 @@
 		allowall[0] = ALL_CLASSES; allowall[1] = '\0';
 		obj = getobj(allowall, "name");
-		if(obj) do_oname(obj);
+		if (obj && obj->otyp == SKULL) {
+			pline("That already has its own name.");
+		} else if (obj) do_oname(obj);
 		break;
 	default :
@@ -491,5 +495,5 @@
 register struct obj *obj;
 {
-	char buf[BUFSZ], qbuf[QBUFSZ];
+	char buf[BUFSZ] = "", qbuf[QBUFSZ];
 	struct obj otemp;
 	register char **str1;
@@ -899,4 +903,5 @@
 	"Ancient Multi-Hued Dragon", "Evil Iggy",
 						/* Moria */
+	"Evil Otto", /* Berzerk */
 	"emu", "kestrel", "xeroc", "venus flytrap",
 						/* Rogue */
@@ -909,5 +914,5 @@
 	"Ent",					/* Lord of the Rings */
 	"tangle tree", "nickelpede", "wiggle",	/* Xanth */
-	"white rabbit", "snark",		/* Lewis Carroll */
+	"white rabbit",		/* Lewis Carroll */
 	"pushmi-pullyu",			/* Dr. Doolittle */
 	"smurf",				/* The Smurfs */
@@ -937,5 +942,57 @@
 	"questing beast",		/* King Arthur */
 	"Predator",				/* Movie */
-	"mother-in-law"				/* common pest */
+	"mother-in-law",				/* common pest */
+
+	"one-winged dewinged stab-bat",  /* KoL */
+	"praying mantis",
+	"arch-pedant",
+	"beluga whale",
+	"bluebird of happiness",
+	"bouncing eye", "floating nose",
+	"buffer overflow", "dangling pointer", "walking disk drive",
+	"cacodemon", "scrag",
+	"cardboard golem", "duct tape golem",
+	"chess pawn",
+	"chicken",
+	"chocolate pudding",
+	"coelacanth",
+	"corpulent porpoise",
+	"Crow T. Robot",
+	"diagonally moving grid bug",
+	"dropbear",
+	"Dudley",
+	"El Pollo Diablo",
+	"evil overlord",
+	"existential angst",
+	"figment of your imagination", "flash of insight",
+	"flying pig",
+	"gazebo",
+	"gonzo journalist",
+	"gray goo", "magnetic monopole",
+	"heisenbug",
+	"lag monster",
+	"loan shark",
+	"Lord British",
+	"newsgroup troll",
+	"ninja pirate zombie robot",
+	"octarine dragon",
+	"particle man",
+	"possessed waffle iron",
+	"poultrygeist",
+	"raging nerd",
+	"roomba",
+	"sea cucumber",
+	"spelling bee",
+	"Strong Bad",
+	"stuffed raccoon puppet",
+	"tapeworm",
+	"liger",
+	"velociraptor",
+	"vermicious knid",
+	"viking",
+	"voluptuous ampersand",
+	"wee green blobbie",
+	"wereplatypus",
+	"zergling"
 };
 
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/src/dothrow.c nethack/src/dothrow.c
--- nh_orig/src/dothrow.c	2003-12-07 18:39:13.000000000 -0500
+++ nethack/src/dothrow.c	2010-08-16 13:20:13.435709808 -0400
@@ -32,4 +32,42 @@
 extern boolean notonhead;	/* for long worms */
 
+int
+boom_flightpath_menu()
+{
+    winid win;
+    anything any;
+    menu_item *pick_list = NULL;
+    int n;
+
+    any.a_void = 0;
+    win = create_nhwindow(NHW_MENU);
+    start_menu(win);
+
+    any.a_int = 1;
+    add_menu(win, NO_GLYPH, &any, 'r', 0, ATR_NONE, "Curve right and return", MENU_UNSELECTED);
+
+    any.a_int = 2;
+    add_menu(win, NO_GLYPH, &any, 'l', 0, ATR_NONE, "Curve left and return", MENU_UNSELECTED);
+
+    any.a_int = 3;
+    add_menu(win, NO_GLYPH, &any, 's', 0, ATR_NONE, "Short straight flight and return", MENU_UNSELECTED);
+
+    any.a_int = 4;
+    add_menu(win, NO_GLYPH, &any, 'x', 0, ATR_NONE, "Long straight flight", MENU_UNSELECTED);
+
+    any.a_int = 0;
+    add_menu(win, NO_GLYPH, &any, 0, 0, ATR_NONE, "", MENU_UNSELECTED);
+    any.a_int = 0;
+    add_menu(win, NO_GLYPH, &any, 0, 0, ATR_NONE, "To change this, change boom_flightpath in options", MENU_UNSELECTED);
+
+    end_menu(win, "How do you wish boomerangs to behave?");
+    n = select_menu(win, PICK_ONE, &pick_list);
+    destroy_nhwindow(win);
+    if (pick_list) {
+	n = (pick_list[0].item.a_int - 1);
+	free((genericptr_t) pick_list);
+    }
+    return n;
+}
 
 /* Throw the selected object, asking for direction */
@@ -78,4 +116,10 @@
 	if(!canletgo(obj,"throw"))
 		return(0);
+
+	if (obj->otyp == BOOMERANG) {
+	    if (iflags.boom_flight_path < 0)
+		iflags.boom_flight_path = boom_flightpath_menu();
+	}
+
 	if (obj->oartifact == ART_MJOLLNIR && obj != uwep) {
 	    pline("%s must be wielded before it can be thrown.",
@@ -128,4 +172,9 @@
 		if (obj->otyp == YA && uwep && uwep->otyp == YUMI) multishot++;
 		break;
+		 case PM_CAVEMAN:
+		if (uslinging()) {		/* give an extra rock to cavies */
+			multishot++;
+		}
+		break;
 	    default:
 		break;	/* No bonus */
@@ -296,4 +345,14 @@
 	}
 
+	/* If they've got something already picked, wield it;
+	 * wield_tool() will return error messages if they couldn't,
+	 * but go ahead and let them throw whatever even if it fails
+	 *
+	 * Must do this before autoquiver gets called since autoquiver
+	 * tries to be smart based on what you've got wielded */
+	if (ulauncher && ulauncher != uwep) {
+		wield_tool(ulauncher,"fire");
+	}
+
 	if(check_capacity((char *)0)) return(0);
 	if (!uquiver) {
@@ -470,5 +529,5 @@
 	    pline("Ouch!");
 	    if (IS_TREE(levl[x][y].typ))
-		s = "bumping into a tree";
+		s = christmas() ? "bumping into a christmas tree" : "bumping into a tree";
 	    else if (IS_ROCK(levl[x][y].typ))
 		s = "bumping into a wall";
@@ -478,4 +537,11 @@
 	    return FALSE;
 	}
+	if (IS_DOOR(levl[x][y].typ) && (levl[x][y].doormask & D_ISOPEN) &&
+	    (u.ux - x) && (u.uy - y)) {
+	    /* closed door handled above */
+	    pline("You hit the door edge!");
+	    losehp(rnd(2+*range), "bumping into a door", KILLED_BY);
+	    return FALSE;
+	}
 	if (levl[x][y].typ == IRONBARS) {
 	    You("crash into some iron bars.  Ouch!");
@@ -570,8 +636,10 @@
 	struct monst *mon = (struct monst *)arg;
 
-	/* TODO: Treat walls, doors, iron bars, pools, lava, etc. specially
+	/* TODO: Treat walls, doors, iron bars, etc. specially
 	 * rather than just stopping before.
+	 *
+	 * DONE: pools and lava (DSR 3/2/08)
 	 */
-	if (goodpos(x, y, mon, 0) && m_in_out_region(mon, x, y)) {
+	if (goodpos(x, y, mon, MM_UNSAFEOK) && m_in_out_region(mon, x, y)) {
 	    remove_monster(mon->mx, mon->my);
 	    newsym(mon->mx, mon->my);
@@ -580,4 +648,6 @@
 	    set_apparxy(mon);
 	    (void) mintrap(mon);
+		 /* TODO: we need to check minliquid here eventually to see
+		  * if monsters can properly die, but for now... */
 	    return TRUE;
 	}
@@ -609,5 +679,5 @@
     if(Punished && !carried(uball)) {
 	You_feel("a tug from the iron ball.");
-	nomul(0);
+	nomul(0, 0);
 	return;
     } else if (u.utrap) {
@@ -615,5 +685,5 @@
 	    u.utraptype == TT_WEB ? "web" : u.utraptype == TT_LAVA ? "lava" :
 		u.utraptype == TT_INFLOOR ? surface(u.ux,u.uy) : "trap");
-	nomul(0);
+	nomul(0, 0);
 	return;
     }
@@ -625,5 +695,5 @@
     if(!range || (!dx && !dy) || u.ustuck) return; /* paranoia */
 
-    nomul(-range);
+    nomul(-range, "moving through the air");
     if (verbose)
 	You("%s in the opposite direction.", range > 1 ? "hurtle" : "float");
@@ -926,7 +996,8 @@
 
 	} else if(obj->otyp == BOOMERANG && !Underwater) {
+
 		if(Is_airlevel(&u.uz) || Levitation)
 		    hurtle(-u.dx, -u.dy, 1, TRUE);
-		mon = boomhit(u.dx, u.dy);
+		mon = boomhit(u.dx, u.dy, !impaired ? iflags.boom_flight_path : rn2(4));
 		if(mon == &youmonst) {		/* the thing was caught */
 			exercise(A_DEX, TRUE);
@@ -942,4 +1013,10 @@
 	} else {
 		urange = (int)(ACURRSTR)/2;
+
+		/* hard limit this so crossbows will fire further
+		 * than anything except a superstrong elf wielding a
+		 * racial bow, or a samurai with his yumi */
+		if (urange > 9) { urange = 9; }
+
 		/* balls are easy to throw or at least roll */
 		/* also, this insures the maximum range of a ball is greater
@@ -958,10 +1035,35 @@
 
 		if (is_ammo(obj)) {
-		    if (ammo_and_launcher(obj, uwep))
-			range++;
-		    else if (obj->oclass != GEM_CLASS)
+			/* stuff that's fired from a proper launcher should have
+			 * a noticeably longer range than stuff that was just
+			 * flung (like daggers, darts, etc.) */
+		    if (ammo_and_launcher(obj, uwep)) {
+				 switch (uwep->otyp) {
+					 case ELVEN_BOW:
+					 case YUMI:
+						 range += urange + 2;	/* better workmanship... */
+						 break;
+					 case ORCISH_BOW:
+						 range += urange - 2;	/* orcish gear sucks */
+						 break;
+					 case BOW:
+						 range += urange;
+						 break;
+					 case CROSSBOW:
+						 range += 10;	 /* not strength dependent! */
+						 break;
+					 case SLING:
+						 range += (int)urange/2;
+						 break;
+					 /* case BLOWGUN: maaaybe? */
+					 default:
+						 break;
+				 }
+			 } else if (obj->oclass != GEM_CLASS) {
 			range /= 2;
 		}
 
+		}
+
 		if (Is_airlevel(&u.uz) || Levitation) {
 		    /* action, reaction... */
@@ -1196,6 +1298,7 @@
 	 * Distance and monster size affect chance to hit.
 	 */
-	tmp = -1 + Luck + find_mac(mon) + u.uhitinc +
+	tmp = -1 + (Luck/2) + find_mac(mon) + u.uhitinc + 
 			maybe_polyd(youmonst.data->mlevel, u.ulevel);
+
 	if (ACURR(A_DEX) < 4) tmp -= 3;
 	else if (ACURR(A_DEX) < 6) tmp -= 2;
@@ -1222,4 +1325,6 @@
 	    case LEATHER_GLOVES:
 	    case GAUNTLETS_OF_DEXTERITY:
+		 case GAUNTLETS_OF_FORTUNE:
+		 case GAUNTLETS_OF_FORCE:
 		break;
 	    default:
@@ -1406,4 +1511,15 @@
 		is_animal(u.ustuck->data) ? "entrails" : "currents");
 	} else {
+		struct monst* montmp;
+		/* Oz reference: Nomes ('gnomes') are afraid of eggs
+		 * ... this is both here and in uhitm because of the odd structure
+		 * related to 'hit' and 'not hit' with the huge pile of elseifs */
+		if (obj->otyp == EGG) {
+			for (montmp = fmon; montmp; montmp = montmp->nmon) {
+				if (is_gnome(montmp->data) && m_canseeu(montmp)) {
+					monflee(montmp,rnd(6)+4,TRUE,TRUE);
+				}
+			}
+		}
 	    tmiss(obj, mon);
 	}
@@ -1585,4 +1701,9 @@
 			/* monster breathing isn't handled... [yet?] */
 			break;
+#ifdef TOURIST
+	case EXPENSIVE_CAMERA:
+	    (void) camera_demon(obj, x,y);
+	    break;
+#endif
 		case EGG:
 			/* breaking your own eggs is bad luck */
@@ -1619,4 +1740,20 @@
 }
 
+struct monst *
+camera_demon(obj, x,y)
+struct obj *obj;
+schar x,y;
+{
+    struct monst *mtmp = NULL;
+    if (!rn2(3) && (mtmp = makemon(&mons[(rn2(2) ? PM_HOMUNCULUS : PM_IMP)],x,y, NO_MM_FLAGS)) != 0) {
+	pline("%s is released!", !canspotmon(mtmp) ?
+	      Something : Hallucination ?
+	      An(rndmonnam()) : "The picture-painting demon");
+	mtmp->mpeaceful = ((obj) ? !obj->cursed : 0);
+	set_malign(mtmp);
+    }
+    return mtmp;
+}
+
 /*
  * Check to see if obj is going to break, but don't actually break it.
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/src/do_wear.c nethack/src/do_wear.c
--- nh_orig/src/do_wear.c	2003-12-07 18:39:13.000000000 -0500
+++ nethack/src/do_wear.c	2009-11-22 07:19:36.431273410 -0500
@@ -40,5 +40,5 @@
 	WORN_SHIRT,
 #endif
-	WORN_BOOTS, W_SWAPWEP, W_QUIVER, 0L };
+	WORN_BOOTS, W_SWAPWEP, W_QUIVER, W_LAUNCHER, 0L };
 
 STATIC_DCL void FDECL(on_msg, (struct obj *));
@@ -100,4 +100,5 @@
     switch(uarmf->otyp) {
 	case LOW_BOOTS:
+	case GNOMISH_BOOTS:
 	case IRON_SHOES:
 	case HIGH_BOOTS:
@@ -111,4 +112,5 @@
 		/* Speed boots are still better than intrinsic speed, */
 		/* though not better than potion speed */
+		/* Can also safely assume we're not wearing molasses boots */
 		if (!oldprop && !(HFast & TIMEOUT)) {
 			makeknown(uarmf->otyp);
@@ -117,4 +119,11 @@
 		}
 		break;
+	case BOOTS_OF_MOLASSES:
+		if (!oldprop && !HSlow) {
+			makeknown(uarmf->otyp);
+			You_feel("yourself slow down.");
+			flags.botl = 1;
+		}
+		break;
 	case ELVEN_BOOTS:
 		if (!oldprop && !HStealth && !BStealth) {
@@ -158,4 +167,11 @@
 		}
 		break;
+	case BOOTS_OF_MOLASSES:
+		if (!oldprop && !HSlow) {
+			makeknown(otyp);
+			You_feel("yourself speed up.");
+			flags.botl = 1;
+		}
+		break;
 	case WATER_WALKING_BOOTS:
 		if (is_pool(u.ux,u.uy) && !Levitation && !Flying &&
@@ -187,4 +203,5 @@
 	case JUMPING_BOOTS:
 	case KICKING_BOOTS:
+	case GNOMISH_BOOTS:
 		break;
 	default: impossible(unknown_type, c_boots, otyp);
@@ -207,4 +224,7 @@
 		break;
 	case ORCISH_CLOAK:
+		if (Race_if(PM_ORC)) {
+		}
+		break;
 	case DWARVISH_CLOAK:
 	case CLOAK_OF_MAGIC_RESISTANCE:
@@ -255,4 +275,8 @@
 	case ELVEN_CLOAK:
 	case ORCISH_CLOAK:
+		if (Race_if(PM_ORC)) {
+			u.uac -= 2;
+		}
+		break;
 	case DWARVISH_CLOAK:
 	case CLOAK_OF_PROTECTION:
@@ -299,5 +323,7 @@
 	case ELVEN_LEATHER_HELM:
 	case DWARVISH_IRON_HELM:
+	case GNOMISH_HELM:
 	case ORCISH_HELM:
+	case HELM_OF_DISCOVERY:
 	case HELM_OF_TELEPATHY:
 		break;
@@ -305,4 +331,8 @@
 		adj_abon(uarmh, uarmh->spe);
 		break;
+	case HELM_OF_CLARITY:
+	   make_hallucinated(0, TRUE, 0);
+		see_monsters();
+		break;
 	case CORNUTHAUM:
 		/* people think marked wizards know what they're talking
@@ -316,8 +346,8 @@
 	case HELM_OF_OPPOSITE_ALIGNMENT:
 		if (u.ualign.type == A_NEUTRAL)
-		    u.ualign.type = rn2(2) ? A_CHAOTIC : A_LAWFUL;
+		    u.ualign.type = (uarmh->o_id % 2) ? A_CHAOTIC : A_LAWFUL;
 		else u.ualign.type = -(u.ualign.type);
 		u.ublessed = 0; /* lose your god's protection */
-	     /* makeknown(uarmh->otyp);   -- moved below, after xname() */
+		u.ualign.record = -(u.ualign.record/2); /* your past actions now count against you */
 		/*FALLTHRU*/
 	case DUNCE_CAP:
@@ -358,5 +388,7 @@
 	case ELVEN_LEATHER_HELM:
 	case DWARVISH_IRON_HELM:
+	case GNOMISH_HELM:
 	case ORCISH_HELM:
+	case HELM_OF_DISCOVERY:
 	    break;
 	case DUNCE_CAP:
@@ -370,4 +402,5 @@
 	    break;
 	case HELM_OF_TELEPATHY:
+	case HELM_OF_CLARITY:
 	    /* need to update ability before calling see_monsters() */
 	    setworn((struct obj *)0, W_ARMH);
@@ -380,4 +413,8 @@
 	    u.ualign.type = u.ualignbase[A_CURRENT];
 	    u.ublessed = 0; /* lose the other god's protection */
+		 u.ualign.record = -(u.ualign.record); 
+								/* your past actions may count for you again...
+								 * we don't divide it by 2 here because we 
+								 * don't want to decrease it _too_ sharply */
 	    flags.botl = 1;
 	    break;
@@ -393,9 +430,10 @@
 Gloves_on()
 {
-    long oldprop =
-	u.uprops[objects[uarmg->otyp].oc_oprop].extrinsic & ~WORN_GLOVES;
+    long oldprop = u.uprops[objects[uarmg->otyp].oc_oprop].extrinsic & ~WORN_GLOVES;
 
     switch(uarmg->otyp) {
 	case LEATHER_GLOVES:
+		case GAUNTLETS_OF_FORCE:
+		case GAUNTLETS_OF_FORTUNE:
 		break;
 	case GAUNTLETS_OF_FUMBLING:
@@ -418,6 +456,5 @@
 Gloves_off()
 {
-    long oldprop =
-	u.uprops[objects[uarmg->otyp].oc_oprop].extrinsic & ~WORN_GLOVES;
+    long oldprop = u.uprops[objects[uarmg->otyp].oc_oprop].extrinsic & ~WORN_GLOVES;
 
     takeoff_mask &= ~W_ARMG;
@@ -425,4 +462,6 @@
     switch(uarmg->otyp) {
 	case LEATHER_GLOVES:
+		case GAUNTLETS_OF_FORCE:
+		case GAUNTLETS_OF_FORTUNE:
 	    break;
 	case GAUNTLETS_OF_FUMBLING:
@@ -474,17 +513,13 @@
 Shield_on()
 {
-/*
     switch (uarms->otyp) {
-	case SMALL_SHIELD:
-	case ELVEN_SHIELD:
-	case URUK_HAI_SHIELD:
-	case ORCISH_SHIELD:
-	case DWARVISH_ROUNDSHIELD:
-	case LARGE_SHIELD:
-	case SHIELD_OF_REFLECTION:
+		case SHIELD_OF_LIGHT:
+			begin_burn(uarms,FALSE);
+			if(!Blind)
+				pline("%s to glow.",Tobjnam(uarms,"begin"));
+			break;
+		default:	 /* impossible() here was a bit paranoid */
 		break;
-	default: impossible(unknown_type, c_shield, uarms->otyp);
     }
-*/
     return 0;
 }
@@ -494,17 +529,16 @@
 {
     takeoff_mask &= ~W_ARMS;
-/*
+
     switch (uarms->otyp) {
-	case SMALL_SHIELD:
-	case ELVEN_SHIELD:
-	case URUK_HAI_SHIELD:
-	case ORCISH_SHIELD:
-	case DWARVISH_ROUNDSHIELD:
-	case LARGE_SHIELD:
-	case SHIELD_OF_REFLECTION:
+		case SHIELD_OF_LIGHT:
+			end_burn(uarms,FALSE);
+			if(!Blind)
+				pline("%s glowing.",Tobjnam(uarms,"stop"));
+			break;
+		break;
+	default: 
 		break;
-	default: impossible(unknown_type, c_shield, uarms->otyp);
     }
-*/
+
     setworn((struct obj *)0, W_ARMS);
     return 0;
@@ -551,4 +585,35 @@
 Armor_on()
 {
+	long oldprop = EFast & W_ARM;
+
+	/* It's a very cheap hack to bolt this stuff on here, but... needs must */
+	if (uarm) {
+		switch (uarm->otyp) {
+			case GOLD_DRAGON_SCALE_MAIL:
+			case GOLD_DRAGON_SCALES:
+				begin_burn(uarm,FALSE);
+				if(!Blind)
+					pline("%s to glow.",Tobjnam(uarm,"begin"));
+				break;
+			case BLUE_DRAGON_SCALE_MAIL:
+			case BLUE_DRAGON_SCALES:
+				if (!oldprop && !Very_fast) {
+					pline("You speed up%s.",Fast ? " a bit more" : "");
+				}
+				EFast |= W_ARM;
+				break;
+			case YELLOW_DRAGON_SCALE_MAIL:
+			case YELLOW_DRAGON_SCALES:
+				EConfusion_resistance |= W_ARM;
+				EStun_resistance |= W_ARM;
+				break;
+			case WHITE_DRAGON_SCALE_MAIL:
+			case WHITE_DRAGON_SCALES:
+				EWwalking |= W_ARM;
+				break;
+			default:
+				break;
+		}
+	}
     return 0;
 }
@@ -557,4 +622,30 @@
 Armor_off()
 {
+	if (uarm) {
+		switch (uarm->otyp) {
+			case GOLD_DRAGON_SCALE_MAIL:
+			case GOLD_DRAGON_SCALES:
+				end_burn(uarm,FALSE);
+				if(!Blind)
+					pline("%s glowing.",Tobjnam(uarm,"stop"));
+				break;
+			case BLUE_DRAGON_SCALE_MAIL:
+			case BLUE_DRAGON_SCALES:
+				EFast &= ~W_ARM;
+				if (!Very_fast) {
+					pline("You slow down.");
+				}
+			case YELLOW_DRAGON_SCALE_MAIL:
+			case YELLOW_DRAGON_SCALES:
+				EConfusion_resistance &= ~W_ARM;
+				EStun_resistance &= ~W_ARM;
+				break;
+			case WHITE_DRAGON_SCALE_MAIL:
+			case WHITE_DRAGON_SCALES:
+				EWwalking &= ~W_ARM;
+			default:
+				break;
+		}
+	}
     takeoff_mask &= ~W_ARM;
     setworn((struct obj *)0, W_ARM);
@@ -569,4 +660,29 @@
 Armor_gone()
 {
+	if (uarm) {
+		switch (uarm->otyp) {
+			case GOLD_DRAGON_SCALE_MAIL:
+			case GOLD_DRAGON_SCALES:
+				end_burn(uarm,FALSE);
+				break;
+			case BLUE_DRAGON_SCALE_MAIL:
+			case BLUE_DRAGON_SCALES:
+				EFast &= ~W_ARM;
+				if (!Very_fast) {
+					pline("You slow down.");
+				}
+				break;
+			case YELLOW_DRAGON_SCALE_MAIL:
+			case YELLOW_DRAGON_SCALES:
+				EConfusion_resistance &= ~W_ARM;
+				EStun_resistance &= ~W_ARM;
+				break;
+			case WHITE_DRAGON_SCALE_MAIL:
+			case WHITE_DRAGON_SCALES:
+				EWwalking &= ~W_ARM;
+			default:
+				break;
+		}
+	}
     takeoff_mask &= ~W_ARM;
     setnotworn(uarm);
@@ -584,4 +700,5 @@
 	case AMULET_OF_REFLECTION:
 	case AMULET_OF_MAGICAL_BREATHING:
+	case AMULET_OF_POWER:
 	case FAKE_AMULET_OF_YENDOR:
 		break;
@@ -645,4 +762,5 @@
 	case AMULET_OF_CHANGE:
 	case AMULET_OF_UNCHANGING:
+	case AMULET_OF_POWER:
 	case FAKE_AMULET_OF_YENDOR:
 		break;
@@ -688,4 +806,5 @@
     if (obj == uswapwep) setuswapwep((struct obj *) 0);
     if (obj == uquiver) setuqwep((struct obj *) 0);
+    if (obj == ulauncher) setulauncher((struct obj *) 0);
 
     /* only mask out W_RING when we don't have both
@@ -917,4 +1036,6 @@
 	if (otmp == uquiver)
 	    setuqwep((struct obj *) 0);
+	if (otmp == ulauncher)
+	    setulauncher((struct obj *) 0);
 	setworn(otmp, W_TOOL);
 	on_msg(otmp);
@@ -1185,5 +1306,5 @@
 	if(cursed(otmp)) return(0);
 	if(delay) {
-		nomul(delay);
+		nomul(delay, "disrobing");
 		if (is_helmet(otmp)) {
 			nomovemsg = "You finish taking off your helmet.";
@@ -1439,8 +1560,10 @@
 	if (otmp == uquiver)
 		setuqwep((struct obj *) 0);
+	if (otmp == ulauncher)
+		setulauncher((struct obj *) 0);
 	setworn(otmp, mask);
 	delay = -objects[otmp->otyp].oc_delay;
 	if(delay){
-		nomul(delay);
+		nomul(delay, "dressing up");
 		if(is_boots(otmp)) afternmv = Boots_on;
 		if(is_helmet(otmp)) afternmv = Helmet_on;
@@ -1489,4 +1612,6 @@
 	if(otmp == uquiver)
 		setuqwep((struct obj *) 0);
+	if(otmp == ulauncher)
+		setulauncher((struct obj *) 0);
 	if(otmp->oclass == RING_CLASS || otmp->otyp == MEAT_RING) {
 		if(nolimbs(youmonst.data)) {
@@ -1596,10 +1721,58 @@
 {
 	int uac = mons[u.umonnum].ac;
+	int racial_bonus;
 
-	if(uarm) uac -= ARM_BONUS(uarm);
-	if(uarmc) uac -= ARM_BONUS(uarmc);
-	if(uarmh) uac -= ARM_BONUS(uarmh);
-	if(uarmf) uac -= ARM_BONUS(uarmf);
-	if(uarms) uac -= ARM_BONUS(uarms);
+	/* Wearing racial armor is worth +x to the armor's AC; orcs get a slightly
+	 * larger bonus to compensate the crummy equipment, lack of equipment,
+	 * and the crummy orc itself :) 
+	 * ...gnomes get the same bonus and get some custom crappy armor added
+	 * solely for their use
+	 */
+	racial_bonus = (Race_if(PM_ORC) || Race_if(PM_GNOME)) ? 2 : 
+							(Race_if(PM_ELF) || Race_if(PM_DWARF)) ? 1 : 0;
+
+	if(uarm) {
+		uac -= ARM_BONUS(uarm);
+		if ((Race_if(PM_ORC) && (uarm->otyp == ORCISH_CHAIN_MAIL || uarm->otyp == ORCISH_RING_MAIL)) ||
+				(Race_if(PM_GNOME) && uarm->otyp == GNOMISH_SUIT) ||
+				(Race_if(PM_ELF) && uarm->otyp == ELVEN_MITHRIL_COAT) ||
+				(Race_if(PM_DWARF) && uarm->otyp == DWARVISH_MITHRIL_COAT)) {
+			uac -= racial_bonus;
+		}
+	}
+	if(uarmc) {
+		uac -= ARM_BONUS(uarmc);
+		if ((Race_if(PM_ORC) && uarmc->otyp == ORCISH_CLOAK) ||
+				(Race_if(PM_ELF) && uarmc->otyp == ELVEN_CLOAK) ||
+				(Race_if(PM_DWARF) && uarmc->otyp == DWARVISH_CLOAK)) {
+			uac -= racial_bonus;
+		}
+	}
+	if(uarmh) {
+		uac -= ARM_BONUS(uarmh);
+		if ((Race_if(PM_ORC) && uarmh->otyp == ORCISH_HELM) ||
+				(Race_if(PM_GNOME) && uarmh->otyp == GNOMISH_HELM) ||
+				(Race_if(PM_ELF) && uarmh->otyp == ELVEN_LEATHER_HELM) ||
+				(Race_if(PM_DWARF) && uarmh->otyp == DWARVISH_IRON_HELM)) {
+			uac -= racial_bonus;
+		}
+	}
+	if(uarmf) {
+		uac -= ARM_BONUS(uarmf);
+		if ((Race_if(PM_ELF) && uarmf->otyp == ELVEN_BOOTS) ||
+				(Race_if(PM_GNOME) && uarmf->otyp == GNOMISH_BOOTS) ||
+				(Race_if(PM_DWARF) && uarmf->otyp == IRON_SHOES)) {
+			uac -= racial_bonus;
+		}
+	}
+	if(uarms) {
+		uac -= ARM_BONUS(uarms);
+		if ((Race_if(PM_ORC) && (uarms->otyp == ORCISH_SHIELD ||
+											uarms->otyp == URUK_HAI_SHIELD)) ||
+				(Race_if(PM_ELF) && uarms->otyp == ELVEN_SHIELD) ||
+				(Race_if(PM_DWARF) && uarms->otyp == DWARVISH_ROUNDSHIELD)) {
+			uac -= racial_bonus;
+		}
+	}
 	if(uarmg) uac -= ARM_BONUS(uarmg);
 #ifdef TOURIST
@@ -1717,5 +1890,5 @@
 
 	if (otmph && (otmph != uarmf)) {
-	    erode_obj(otmph, acid_dmg, FALSE);
+	    if (!_erode_obj(otmph, AD_ACID))
 	    if (carried(otmph)) update_inventory();
 	}
@@ -1840,5 +2013,5 @@
 	}
 	/* basic curse check */
-	if (otmp == uquiver || (otmp == uswapwep && !u.twoweap)) {
+	if (otmp == uquiver || otmp == ulauncher || (otmp == uswapwep && !u.twoweap)) {
 	    ;	/* some items can be removed even when cursed */
 	} else {
@@ -1863,4 +2036,5 @@
 	else if(otmp == uswapwep) takeoff_mask |= W_SWAPWEP;
 	else if(otmp == uquiver) takeoff_mask |= W_QUIVER;
+	else if(otmp == ulauncher) takeoff_mask |= W_LAUNCHER;
 
 	else impossible("select_off: %s???", doname(otmp));
@@ -1887,4 +2061,7 @@
 	  setuqwep((struct obj *) 0);
 	  You("no longer have ammunition readied.");
+	} else if (taking_off == W_LAUNCHER) {
+		setulauncher((struct obj*) 0);
+		You("no longer have a default ranged weapon chosen.");
 	} else if (taking_off == WORN_ARMOR) {
 	  otmp = uarm;
@@ -1964,4 +2141,6 @@
 	} else if (taking_off == W_QUIVER) {
 	  todelay = 1;
+	} else if (taking_off == W_LAUNCHER) {
+	  todelay = 0;
 	} else if (taking_off == WORN_ARMOR) {
 	  otmp = uarm;
@@ -2031,5 +2210,5 @@
 	set_occupation(take_off, disrobing, 0);
 	return 0;
-    } else if (!uwep && !uswapwep && !uquiver && !uamul && !ublindf &&
+    } else if (!uwep && !uswapwep && !uquiver && !uamul && !ublindf && !ulauncher &&
 		!uleft && !uright && !wearing_armor()) {
 	You("are not wearing anything.");
@@ -2047,5 +2226,5 @@
 	disrobing = "disrobing";
 	/* specific activity when handling weapons only */
-	if (!(takeoff_mask & ~(W_WEP|W_SWAPWEP|W_QUIVER)))
+	if (!(takeoff_mask & ~(W_WEP|W_SWAPWEP|W_QUIVER|W_LAUNCHER)))
 	    disrobing = "disarming";
 	(void) take_off();
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/src/drawing.c nethack/src/drawing.c
--- nh_orig/src/drawing.c	2003-12-07 18:39:13.000000000 -0500
+++ nethack/src/drawing.c	2010-05-01 11:04:47.118713846 -0400
@@ -44,5 +44,6 @@
 /*15*/	BALL_SYM,
 	CHAIN_SYM,
-	VENOM_SYM
+	VENOM_SYM,
+	FURNITURE_SYM
 };
 
@@ -68,5 +69,6 @@
 /*15*/	"iron ball",
 	"iron chain",
-	"splash of venom"
+	"splash of venom",
+	"piece of furniture"
 };
 
@@ -90,5 +92,6 @@
 /*15*/	"iron balls",
 	"chains",
-	"venoms"
+	"venoms",
+	"furniture"
 };
 
@@ -177,5 +180,5 @@
     "dragon",			"elemental",		"fungus or mold",
     "gnome",			"giant humanoid",	0,
-    "jabberwock",		"Keystone Kop",		"lich",
+    "looking-glass creature",		"Keystone Kop",		"lich",
     "mummy",			"naga",			"ogre",
     "pudding or ooze",		"quantum mechanic",	"rust monster or disenchanter",
@@ -205,5 +208,5 @@
  */
 const struct symdef defsyms[MAXPCHARS] = {
-/* 0*/	{' ', "dark part of a room",C(NO_COLOR)},	/* stone */
+/* 0*/	{' ', "unexplored area",C(NO_COLOR)},	/* stone */
 	{'|', "wall",		C(CLR_GRAY)},	/* vwall */
 	{'-', "wall",		C(CLR_GRAY)},	/* hwall */
@@ -225,4 +228,5 @@
 	{'#', "tree",		C(CLR_GREEN)},	/* tree */
 	{'.', "floor of a room",C(CLR_GRAY)},	/* room */
+	{'.', "dark part of a room",C(CLR_BLACK)},	/* dark room */
 /*20*/	{'#', "corridor",	C(CLR_GRAY)},	/* dark corr */
 	{'#', "lit corridor",	C(CLR_GRAY)},	/* lit corr (see mapglyph.c) */
@@ -233,5 +237,4 @@
 	{'_', "altar",		C(CLR_GRAY)},	/* altar */
 	{'|', "grave",      C(CLR_GRAY)},   /* grave */
-	{'\\', "opulent throne",C(HI_GOLD)},	/* throne */
 #ifdef SINKS
 	{'#', "sink",		C(CLR_GRAY)},	/* sink */
@@ -239,5 +242,5 @@
 	{'#', "",		C(CLR_GRAY)},	/* sink */
 #endif
-/*30*/	{'{', "fountain",	C(CLR_BLUE)},	/* fountain */
+/*30*/	{'{', "fountain",	C(CLR_BRIGHT_BLUE)},	/* fountain */
 	{'}', "water",		C(CLR_BLUE)},	/* pool */
 	{'.', "ice",		C(CLR_CYAN)},	/* ice */
@@ -272,4 +275,7 @@
 	{'^', "anti-magic field", C(HI_ZAP)},	/* trap */
 	{'^', "polymorph trap",	C(CLR_BRIGHT_GREEN)},	/* trap */
+	{'^', "spear trap",	C(CLR_BROWN)},	/* trap */
+	{'^', "falling-rocks trap", C(CLR_GRAY)},	/* trap */
+	{'^', "magic beam trap", C(CLR_YELLOW)},	/* trap */
 	{'|', "wall",		C(CLR_GRAY)},	/* vbeam */
 	{'-', "wall",		C(CLR_GRAY)},	/* hbeam */
@@ -336,4 +342,5 @@
 	241,	/* S_tree:	plus or minus symbol */
 	0xfa,	/* S_room:	meta-z, centered dot */
+	g_FILLER(S_stone),	/* S_darkroom:	meta-z, centered dot */
 /*20*/	0xb0,	/* S_corr:	meta-0, light shading */
 	0xb1,	/* S_litcorr:	meta-1, medium shading */
@@ -344,5 +351,4 @@
 	g_FILLER(S_altar),
 	g_FILLER(S_grave),
-	g_FILLER(S_throne),
 	g_FILLER(S_sink),
 /*30*/	0xf4,	/* S_fountain:	meta-t, integral top half */
@@ -379,4 +385,7 @@
 	g_FILLER(S_anti_magic_trap),
 	g_FILLER(S_polymorph_trap),
+	g_FILLER(S_spear_trap),
+	g_FILLER(S_falling_rocks_trap),
+	g_FILLER(S_magic_beam_trap),
 	0xb3,	/* S_vbeam:	meta-3, vertical rule */
 	0xc4,	/* S_hbeam:	meta-D, horizontal rule */
@@ -435,4 +444,5 @@
 	0xe7,	/* S_tree:	meta-g, plus-or-minus */
 	0xfe,	/* S_room:	meta-~, centered dot */
+	g_FILLER(S_stone),	/* S_darkroom:	meta-~, centered dot */
 /*20*/	g_FILLER(S_corr),
 	g_FILLER(S_litcorr),
@@ -443,5 +453,4 @@
 	g_FILLER(S_altar),	/* 0xc3, \E)3: meta-C, dagger */
 	g_FILLER(S_grave),
-	g_FILLER(S_throne),
 	g_FILLER(S_sink),
 /*30*/	g_FILLER(S_fountain),	/* 0xdb, \E)3: meta-[, integral top half */
@@ -478,4 +487,7 @@
 	g_FILLER(S_anti_magic_trap),
 	g_FILLER(S_polymorph_trap),
+	g_FILLER(S_spear_trap),
+	g_FILLER(S_falling_rocks_trap),
+	g_FILLER(S_magic_beam_trap),
 	0xf8,	/* S_vbeam:	meta-x, vertical rule */
 	0xf1,	/* S_hbeam:	meta-q, horizontal rule */
@@ -540,5 +552,4 @@
 	g_FILLER(S_altar),
 	0xef,	/* S_grave:	same as open door */
-	g_FILLER(S_throne),
 	g_FILLER(S_sink),
 /*30*/	g_FILLER(S_fountain),
@@ -575,4 +586,5 @@
 	g_FILLER(S_anti_magic_trap),
 	g_FILLER(S_polymorph_trap),
+	g_FILLER(S_spear_trap),
 	g_FILLER(S_vbeam),
 	g_FILLER(S_hbeam),
@@ -729,5 +741,6 @@
 /*15*/	BALL_SYM,
 	CHAIN_SYM,
-	VENOM_SYM
+	VENOM_SYM,
+	FURNITURE_SYM
 };
 
@@ -772,5 +785,6 @@
 /*15*/	BALL_SYM,
 	CHAIN_SYM,
-	VENOM_SYM
+	VENOM_SYM,
+	FURNITURE_SYM
 };
 # endif /* ASCIIGRAPH */
@@ -866,4 +880,7 @@
 	    showsyms[S_anti_magic_trap] = 0x04;
 	    showsyms[S_polymorph_trap] = 0x04;
+	    showsyms[S_spear_trap] = 0x04;
+	    showsyms[S_falling_rocks_trap] = 0x04;
+	    showsyms[S_magic_beam_trap] = 0x04;
 #endif
 	}
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/src/dungeon.c nethack/src/dungeon.c
--- nh_orig/src/dungeon.c	2003-12-07 18:39:13.000000000 -0500
+++ nethack/src/dungeon.c	2009-09-07 11:24:04.638417961 -0400
@@ -633,4 +633,8 @@
 	{ "wizard2",	&wiz2_level },
 	{ "wizard3",	&wiz3_level },
+#ifdef RECORD_ACHIEVE
+        { "minend",     &mineend_level },
+        { "soko1",      &sokoend_level },
+#endif
 	{ X_START,	&qstart_level },
 	{ X_LOCATE,	&qlocate_level },
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/src/eat.c nethack/src/eat.c
--- nh_orig/src/eat.c	2003-12-07 18:39:13.000000000 -0500
+++ nethack/src/eat.c	2010-04-29 10:53:23.923715306 -0400
@@ -135,7 +135,5 @@
 	{"soup made from", 20},
 	{"pureed",	500},
-#define ROTTEN_TIN 4
-	{"rotten",	-50},
-#define HOMEMADE_TIN 5
+#define HOMEMADE_TIN 4
 	{"homemade",	 50},
 	{"stir fried",   80},
@@ -144,12 +142,52 @@
 	{"dried",        55},
 	{"szechuan",     70},
-#define FRENCH_FRIED_TIN 11
+#define FRENCH_FRIED_TIN 10
 	{"french fried", 40},
 	{"sauteed",      95},
 	{"broiled",      80},
 	{"smoked",       50},
+	/* only specials below; ROTTEN_TIN used as marker */
+#define ROTTEN_TIN 14
+	{"rotten",	-50},
+#define SPINACH_TIN 15
+	{"spinach",	  0},
 	{"", 0}
 };
-#define TTSZ	SIZE(tintxts)
+
+int
+tin_content_idx(obj)
+     struct obj *obj;
+{
+    /* for tins, spe==-1 means player made it, and spe==1 means spinach */
+    if (obj->spe ==  1) return SPINACH_TIN;
+    if (obj->spe == -1) return HOMEMADE_TIN;
+    /* don't select special stuff here */
+    return (obj->o_id % ROTTEN_TIN);
+}
+
+char *
+tin_content_text(obj)
+     struct obj *obj;
+{
+    static char buf[BUFSZ];
+    static const char *tin_label_msgs[] = {
+	"simulation meat",
+	"meat-like product",
+	"soylent green",
+	"spoo",
+	"stone soup"
+    };
+    int idx = (obj->corpsenm == NON_PM) ? (obj->o_id % PM_LONG_WORM_TAIL) : obj->corpsenm;
+    int t = tin_content_idx(obj);
+    if (Hallucination)
+	sprintf(buf, "%s", tin_label_msgs[obj->o_id % SIZE(tin_label_msgs)]);
+    else {
+	if (t == SPINACH_TIN)
+	    sprintf(buf, "%s", tintxts[t].txt);
+	else
+	    snprintf(buf, BUFSZ, "%s %s", tintxts[t].txt, mons[idx].mname);
+    }
+    return upstart(buf);
+}
 
 static NEARDATA struct {
@@ -232,5 +270,5 @@
 			return;
 	} else if (Role_if(PM_KNIGHT) && u.ualign.type == A_LAWFUL) {
-			adjalign(-1);		/* gluttony is unchivalrous */
+			major_sin();		/* gluttony is unchivalrous */
 			You_feel("like a glutton!");
 	}
@@ -454,4 +492,14 @@
 		return TRUE;
 	}
+	
+	/* Cavemen get a bonus for cannibalism */
+	if (Role_if(PM_CAVEMAN) && your_race(&mons[pm])) {
+		if (allowmsg) {
+			You("consume the corpse in accordance with ancient ritual.");
+			u.ualign.record += 5;
+			return FALSE;
+		}
+	}
+
 	return FALSE;
 }
@@ -625,10 +673,10 @@
 	    case TELEPAT:
 #ifdef DEBUG
-		if (telepathic(ptr)) {
+		if (gives_telepathy(ptr)) {
 			debugpline("can get telepathy");
 			return(TRUE);
 		} else  return(FALSE);
 #else
-		return(telepathic(ptr));
+		return(gives_telepathy(ptr));
 #endif
 	    default:
@@ -638,4 +686,19 @@
 }
 
+int
+gives_telepathy_incr(ptr)
+struct permonst *ptr;
+{
+    if (ptr == &mons[PM_FLOATING_EYE]) return 6;
+    if (ptr == &mons[PM_MIND_FLAYER]) return 6;
+    if (ptr == &mons[PM_MASTER_MIND_FLAYER]) return 9;
+    if (ptr == &mons[PM_KOBOLD_SHAMAN]) return 3;
+    if (ptr == &mons[PM_GOBLIN_SHAMAN]) return 3;
+    if (ptr == &mons[PM_ORC_SHAMAN]) return 3;
+    if (ptr == &mons[PM_HILL_GIANT_SHAMAN]) return 3;
+    if (ptr == &mons[PM_GNOMISH_WIZARD]) return 3;
+    return 0;
+}
+
 /* givit() tries to give you an intrinsic based on the monster's level
  * and what type of intrinsic it is trying to give you.
@@ -647,22 +710,18 @@
 {
 	register int chance;
+	long percentincrease;
 
 #ifdef DEBUG
 	debugpline("Attempting to give intrinsic %d", type);
 #endif
-	/* some intrinsics are easier to get than others */
+	/* some intrinsics are easier to get than others...
+	 * the values seem high because there's a chance to get each when
+	 * you eat a critter now, so it has to be adjusted slightly */
 	switch (type) {
-		case POISON_RES:
-			if ((ptr == &mons[PM_KILLER_BEE] ||
-					ptr == &mons[PM_SCORPION]) && !rn2(4))
-				chance = 1;
-			else
-				chance = 15;
-			break;
 		case TELEPORT:
-			chance = 10;
+			chance = 30;
 			break;
 		case TELEPORT_CONTROL:
-			chance = 12;
+			chance = 36;
 			break;
 		case TELEPAT:
@@ -670,5 +729,5 @@
 			break;
 		default:
-			chance = 15;
+			chance = 1;	/* the rest use the new system, give it to them all the time */
 			break;
 	}
@@ -677,13 +736,16 @@
 		return;		/* failed die roll */
 
+	percentincrease = (ptr->cwt / 90);
+	if (percentincrease < 5) { percentincrease = 5; }
+
 	switch (type) {
+		 /* All these use the new system, which is based on corpse weight. */
 	    case FIRE_RES:
 #ifdef DEBUG
 		debugpline("Trying to give fire resistance");
 #endif
-		if(!(HFire_resistance & FROMOUTSIDE)) {
-			You(Hallucination ? "be chillin'." :
-			    "feel a momentary chill.");
-			HFire_resistance |= FROMOUTSIDE;
+		if((HFire_resistance & (TIMEOUT|FROMRACE|FROMEXPER)) < 100) {
+			You(Hallucination ? "be chillin'." : "feel slightly more chill.");
+			incr_resistance(&HFire_resistance,percentincrease);
 		}
 		break;
@@ -692,7 +754,7 @@
 		debugpline("Trying to give sleep resistance");
 #endif
-		if(!(HSleep_resistance & FROMOUTSIDE)) {
-			You_feel("wide awake.");
-			HSleep_resistance |= FROMOUTSIDE;
+		if((HSleep_resistance & (TIMEOUT|FROMRACE|FROMEXPER)) < 100) {
+			You_feel("a bit perkier.");
+			incr_resistance(&HSleep_resistance,percentincrease);
 		}
 		break;
@@ -701,7 +763,7 @@
 		debugpline("Trying to give cold resistance");
 #endif
-		if(!(HCold_resistance & FROMOUTSIDE)) {
-			You_feel("full of hot air.");
-			HCold_resistance |= FROMOUTSIDE;
+		if((HCold_resistance & (TIMEOUT|FROMRACE|FROMEXPER)) < 100) {
+			You_feel("a little bit warmer.");
+			incr_resistance(&HCold_resistance,percentincrease);
 		}
 		break;
@@ -710,9 +772,7 @@
 		debugpline("Trying to give disintegration resistance");
 #endif
-		if(!(HDisint_resistance & FROMOUTSIDE)) {
-			You_feel(Hallucination ?
-			    "totally together, man." :
-			    "very firm.");
-			HDisint_resistance |= FROMOUTSIDE;
+		if((HDisint_resistance & (TIMEOUT|FROMRACE|FROMEXPER)) < 100) {
+			You_feel(Hallucination ? "totally together, man." : "a touch more firm.");
+			incr_resistance(&HDisint_resistance,percentincrease);
 		}
 		break;
@@ -721,10 +781,10 @@
 		debugpline("Trying to give shock resistance");
 #endif
-		if(!(HShock_resistance & FROMOUTSIDE)) {
+		if((HShock_resistance & (TIMEOUT|FROMRACE|FROMEXPER)) < 100) {
 			if (Hallucination)
 				You_feel("grounded in reality.");
 			else
-				Your("health currently feels amplified!");
-			HShock_resistance |= FROMOUTSIDE;
+				Your("health is slightly more amplified!");
+			incr_resistance(&HShock_resistance,percentincrease);
 		}
 		break;
@@ -733,10 +793,10 @@
 		debugpline("Trying to give poison resistance");
 #endif
-		if(!(HPoison_resistance & FROMOUTSIDE)) {
-			You_feel(Poison_resistance ?
-				 "especially healthy." : "healthy.");
-			HPoison_resistance |= FROMOUTSIDE;
+		if((HPoison_resistance & (TIMEOUT|FROMRACE|FROMEXPER)) < 100) {
+			You_feel(how_resistant(POISON_RES) == 100 ? "noticeably healthier." : "healthier.");
+			incr_resistance(&HPoison_resistance,percentincrease);
 		}
 		break;
+		/* From here forward, we'll use the old stuff.  But. */
 	    case TELEPORT:
 #ifdef DEBUG
@@ -769,7 +829,16 @@
 			    "a strange mental acuity.");
 			HTelepat |= FROMOUTSIDE;
-			/* If blind, make sure monsters show up. */
-			if (Blind) see_monsters();
+			u.u_telepathy_dist += gives_telepathy_incr(ptr);
+		} else {
+		    int incr = gives_telepathy_incr(ptr);
+		    if (incr && (u.u_telepathy_dist < 600)) {
+			You_feel(Hallucination ?
+				 "like everyone is tad closer." :
+				 "your senses expand a bit.");
+			u.u_telepathy_dist += incr;
+		    }
 		}
+		/* If blind, make sure monsters show up at the correct range. */
+		if (Blind) see_monsters();
 		break;
 	    default:
@@ -829,11 +898,9 @@
 		break;
 	    case PM_STALKER:
+			incr_itimeout(&HInvis, (long)rn1(100, 50));
 		if(!Invis) {
-			set_itimeout(&HInvis, (long)rn1(100, 50));
 			if (!Blind && !BInvis) self_invis_message();
 		} else {
-			if (!(HInvis & INTRINSIC)) You_feel("hidden!");
-			HInvis |= FROMOUTSIDE;
-			HSee_invisible |= FROMOUTSIDE;
+				incr_itimeout(&HSee_invisible, (long)rn1(100, 50));
 		}
 		newsym(u.ux, u.uy);
@@ -863,5 +930,5 @@
 		    if (u.usteed) dismount_steed(DISMOUNT_FELL);
 #endif
-		    nomul(-tmp);
+		    nomul(-tmp, "pretending to be a pile of gold");
 		    Sprintf(buf, Hallucination ?
 			"You suddenly dread being peeled and mimic %s again!" :
@@ -884,9 +951,13 @@
 		if (HFast & INTRINSIC) {
 			HFast &= ~INTRINSIC;
+			if (!Slow) {
 			You("seem slower.");
+			}
 		} else {
 			HFast |= FROMOUTSIDE;
+			if (!Slow) {
 			You("seem faster.");
 		}
+		}
 		break;
 	    case PM_LIZARD:
@@ -947,27 +1018,20 @@
 		 */
 
+		/* Above proof recorded for posterity, even though i'm about
+		 * to vigorously jostle the means of getting most of
+		 * the resistances in the first place; it's no longer random
+		 * for anything except telecontrol, teleport, and telepathy.
+		 *
+		 * Derek S. Ray, October 28, 2007
+		 */
+
 		 count = 0;	/* number of possible intrinsics */
 		 tmp = 0;	/* which one we will try to give */
 		 for (i = 1; i <= LAST_PROP; i++) {
 			if (intrinsic_possible(i, ptr)) {
-				count++;
-				/* a 1 in count chance of replacing the old
-				 * one with this one, and a count-1 in count
-				 * chance of keeping the old one.  (note
-				 * that 1 in 1 and 0 in 1 are what we want
-				 * for the first one
-				 */
-				if (!rn2(count)) {
-#ifdef DEBUG
-					debugpline("Intrinsic %d replacing %d",
-								i, tmp);
-#endif
-					tmp = i;
-				}
+				givit(i,ptr);
 			}
 		 }
 
-		 /* if any found try to give them one */
-		 if (count) givit(tmp, ptr);
 	    }
 	    break;
@@ -990,5 +1054,5 @@
     if (Role_if(PM_MONK)) {
 	You_feel("guilty.");
-	adjalign(-1);
+		venial_sin();
     }
     return;
@@ -1044,9 +1108,8 @@
 	    }
 	    r = tin.tin->cursed ? ROTTEN_TIN :	/* always rotten if cursed */
-		    (tin.tin->spe == -1) ? HOMEMADE_TIN :  /* player made it */
-			rn2(TTSZ-1);		/* else take your pick */
+		tin_content_idx(tin.tin);
 	    if (r == ROTTEN_TIN && (tin.tin->corpsenm == PM_LIZARD ||
 			tin.tin->corpsenm == PM_LICHEN))
-		r = HOMEMADE_TIN;		/* lizards don't rot */
+		r = tin_content_idx(tin.tin);		/* lizards don't rot */
 	    else if (tin.tin->spe == -1 && !tin.tin->blessed && !rn2(7))
 		r = ROTTEN_TIN;			/* some homemade tins go bad */
@@ -1225,5 +1288,5 @@
 		pline_The("world spins and %s %s.", what, where);
 		flags.soundok = 0;
-		nomul(-rnd(10));
+		nomul(-rnd(10), "unconscious from rotten food");
 		nomovemsg = "You are conscious again.";
 		afternmv = Hear_again;
@@ -1290,7 +1353,7 @@
 		tp++;
 		pline("Ecch - that must have been poisonous!");
-		if(!Poison_resistance) {
-			losestr(rnd(4));
-			losehp(rnd(15), "poisonous corpse", KILLED_BY_AN);
+		if(how_resistant(POISON_RES) < 100) {
+			losestr(resist_reduce(rnd(4),POISON_RES));
+			losehp(resist_reduce(rnd(15),POISON_RES), "poisonous corpse", KILLED_BY_AN);
 		} else	You("seem unaffected by the poison.");
 	/* now any corpse left too long will make you mildly ill */
@@ -1554,9 +1617,9 @@
 	    case RIN_FREE_ACTION:
 		/* Give sleep resistance instead */
-		if (!(HSleep_resistance & FROMOUTSIDE))
+			if (how_resistant(SLEEP_RES) < 100) {
 		    accessory_has_effect(otmp);
-		if (!Sleep_resistance)
 		    You_feel("wide awake.");
-		HSleep_resistance |= FROMOUTSIDE;
+			}
+			incr_resistance(&HSleep_resistance,100);
 		break;
 	    case AMULET_OF_CHANGE:
@@ -1587,4 +1650,5 @@
 	    case RIN_SUSTAIN_ABILITY:
 	    case AMULET_OF_LIFE_SAVING:
+		 case AMULET_OF_POWER:
 	    case AMULET_OF_REFLECTION: /* nice try */
 	    /* can't eat Amulet of Yendor or fakes,
@@ -1643,4 +1707,5 @@
 	if (otmp == uwep && otmp->quan == 1L) uwepgone();
 	if (otmp == uquiver && otmp->quan == 1L) uqwepgone();
+	if (otmp == ulauncher && otmp->quan == 1L) ulwepgone();
 	if (otmp == uswapwep && otmp->quan == 1L) uswapwepgone();
 
@@ -1694,5 +1759,5 @@
 		    u.mh += otmp->cursed ? -rnd(20) : rnd(20);
 		    if (u.mh > u.mhmax) {
-			if (!rn2(17)) u.mhmax++;
+			if (!rn2(17)) gainmaxhp(1);
 			u.mh = u.mhmax;
 		    } else if (u.mh <= 0) {
@@ -1702,5 +1767,5 @@
 		    u.uhp += otmp->cursed ? -rnd(20) : rnd(20);
 		    if (u.uhp > u.uhpmax) {
-			if(!rn2(17)) u.uhpmax++;
+				if(!rn2(17)) gainmaxhp(1);
 			u.uhp = u.uhpmax;
 		    } else if (u.uhp <= 0) {
@@ -1804,5 +1869,5 @@
 		else return 2;
 	}
-	if (cadaver && poisonous(&mons[mnum]) && !Poison_resistance) {
+	if (cadaver && poisonous(&mons[mnum]) && how_resistant(POISON_RES) < 100) {
 		/* poisonous */
 		Sprintf(buf, "%s like %s might be poisonous! %s",
@@ -1944,4 +2009,9 @@
 	    victual.usedtime = 0;
 	    victual.canchoke = (u.uhs == SATIATED);
+		 /* for characters with code of conduct, gluttony is bad */
+		if (Role_if(PM_KNIGHT) && u.ualign.type == A_LAWFUL) {
+			You("are slightly ashamed for overeating.");
+			venial_sin();
+		}
 		/* Note: gold weighs 1 pt. for each 1000 pieces (see */
 		/* pickup.c) so gold and non-gold is consistent. */
@@ -1970,7 +2040,7 @@
 	    if (otmp->oclass == WEAPON_CLASS && otmp->opoisoned) {
 		pline("Ecch - that must have been poisonous!");
-		if(!Poison_resistance) {
-		    losestr(rnd(4));
-		    losehp(rnd(15), xname(otmp), KILLED_BY_AN);
+		if (how_resistant(POISON_RES) < 100) {
+		    losestr(resist_reduce(rnd(4),POISON_RES));
+		    losehp(resist_reduce(rnd(15),POISON_RES), xname(otmp), KILLED_BY_AN);
 		} else
 		    You("seem unaffected by the poison.");
@@ -2245,5 +2315,5 @@
 reset_faint()	/* call when a faint must be prematurely terminated */
 {
-	if(is_fainted()) nomul(0);
+	if(is_fainted()) nomul(0, 0);
 }
 
@@ -2256,5 +2326,5 @@
 
 		flags.soundok = 0;
-		nomul(-10+(u.uhunger/10));
+		nomul(-10+(u.uhunger/10), "fainted from lack of food");
 		nomovemsg = "You regain consciousness.";
 		afternmv = unfaint;
@@ -2273,7 +2343,8 @@
 
 	newhs = (h > 1000) ? SATIATED :
-		(h > 150) ? NOT_HUNGRY :
+		(h > 200) ? NOT_HUNGRY :
 		(h > 50) ? HUNGRY :
-		(h > 0) ? WEAK : FAINTING;
+		(h > 0) ? WEAK : 
+		FAINTING;
 
 	/* While you're eating, you may pass from WEAK to HUNGRY to NOT_HUNGRY.
@@ -2321,5 +2392,5 @@
 				You("faint from lack of food.");
 				flags.soundok = 0;
-				nomul(-10+(u.uhunger/10));
+				nomul(-10+(u.uhunger/10), "fainted from lack of food");
 				nomovemsg = "You regain consciousness.";
 				afternmv = unfaint;
@@ -2490,5 +2561,5 @@
 {
 	make_sick(0L, (char *) 0, TRUE, SICK_VOMITABLE);
-	nomul(-2);
+	nomul(-2, "vomiting");
 }
 
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/src/end.c nethack/src/end.c
--- nh_orig/src/end.c	2003-12-07 18:39:13.000000000 -0500
+++ nethack/src/end.c	2010-08-16 13:26:43.564845433 -0400
@@ -11,4 +11,6 @@
 #endif
 #include "dlb.h"
+#include <sys/types.h>
+#include <sys/stat.h>
 
 	/* these probably ought to be generated by makedefs, like LAST_GEM */
@@ -35,4 +37,5 @@
 # endif
 #endif
+STATIC_DCL long FDECL(count_score,(int));
 STATIC_DCL void FDECL(disclose,(int,BOOLEAN_P));
 STATIC_DCL void FDECL(get_valuables, (struct obj *));
@@ -41,5 +44,13 @@
 STATIC_DCL void FDECL(savelife, (int));
 STATIC_DCL void FDECL(list_vanquished, (CHAR_P,BOOLEAN_P));
+#ifdef DUMP_LOG
+extern char msgs[][BUFSZ];
+extern int lastmsg;
+extern void NDECL(dump_spells);
+void FDECL(do_vanquished, (int, BOOLEAN_P, BOOLEAN_P));
+STATIC_DCL void FDECL(list_genocided, (int, BOOLEAN_P, BOOLEAN_P));
+#else
 STATIC_DCL void FDECL(list_genocided, (CHAR_P,BOOLEAN_P));
+#endif /* DUMP_LOG */
 STATIC_DCL boolean FDECL(should_query_disclose_option, (int,char *));
 
@@ -87,4 +98,75 @@
 extern const char * const killed_by_prefix[];	/* from topten.c */
 
+#ifdef DUMP_LOG
+FILE *dump_fp = (FILE *)0;  /* file pointer for dumps */
+/* functions dump_init, dump_exit and dump are from the dump patch */
+
+void
+dump_init ()
+{
+#ifdef UNIX
+	mode_t dumpmode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH;
+#endif
+  if (dump_fn[0]) {
+    char *p = (char *) strstr(dump_fn, "%n");
+    if (p) {
+      int new_dump_fn_len = strlen(dump_fn)+strlen(plname)-2; /* %n */
+      char *new_dump_fn = (char *) alloc((unsigned)(new_dump_fn_len+1));
+      char *q = new_dump_fn;
+      strncpy(q, dump_fn, p-dump_fn);
+      q += p-dump_fn;
+      strncpy(q, plname, strlen(plname) + 1);
+      regularize(q);
+      q[strlen(plname)] = '\0';
+      q += strlen(q);
+      p += 2;	/* skip "%n" */
+      strncpy(q, p, strlen(p));
+      new_dump_fn[new_dump_fn_len] = '\0';
+
+      dump_fp = fopen(new_dump_fn, "w");
+      if (!dump_fp) {
+			pline("Can't open %s for output.", new_dump_fn);
+			pline("Dump file not created.");
+      } else {
+			fclose(dump_fp);
+			dump_fp = fopen(new_dump_fn, "w");
+#ifdef UNIX
+			chmod(new_dump_fn,dumpmode);
+#endif
+		}
+      free(new_dump_fn);
+      
+    } else {
+      dump_fp = fopen (dump_fn, "w");
+
+      if (!dump_fp) {
+			pline("Can't open %s for output.", dump_fn);
+			pline("Dump file not created.");
+      } else {
+			fclose(dump_fp);
+			dump_fp = fopen(dump_fn, "w");
+#ifdef UNIX
+			chmod(dump_fn,dumpmode);
+#endif
+		}
+    }
+  }
+}
+
+void
+dump_exit ()
+{
+  if (dump_fp)
+    fclose (dump_fp);
+}
+
+void dump (pre, str)
+     char *pre, *str;
+{
+  if (dump_fp)
+    fprintf (dump_fp, "%s%s\n", pre, str);
+}
+#endif  /* DUMP_LOG */
+
 /*ARGSUSED*/
 void
@@ -102,5 +184,5 @@
 		curs_on_u();
 		wait_synch();
-		if(multi > 0) nomul(0);
+		if(multi > 0) nomul(0, 0);
 	} else {
 		(void)done2();
@@ -120,5 +202,5 @@
 		curs_on_u();
 		wait_synch();
-		if(multi > 0) nomul(0);
+		if(multi > 0) nomul(0, 0);
 		if(multi == 0) {
 		    u.uinvulnerable = FALSE;	/* avoid ctrl-C bug -dlc */
@@ -225,6 +307,17 @@
 	}
 
-	if (multi) Strcat(buf, ", while helpless");
+	if (multi) {
+	  if (strlen(multi_txt) > 0)
+	    Sprintf(eos(buf), ", while %s", multi_txt);
+	  else
+	    Strcat(buf, ", while helpless");
+	}
 	killer = buf;
+	ukiller = mtmp;
+	if (ukiller && (likes_gold(ukiller->data) || likes_gems(ukiller->data) ||
+				likes_objs(ukiller->data) || likes_magic(ukiller->data) ||
+				is_covetous(ukiller->data))) {
+		pline("%s rummages through your possessions.",Monnam(ukiller));
+	}
 	if (mtmp->data->mlet == S_WRAITH)
 		u.ugrave_arise = PM_WRAITH;
@@ -245,5 +338,5 @@
 }
 
-#if defined(WIN32)
+#if defined(WIN32) || defined(UNIX)
 #define NOTIFY_NETHACK_BUGS
 #endif
@@ -273,6 +366,6 @@
 # if defined(NOTIFY_NETHACK_BUGS)
 	if (!wizard)
-	    raw_printf("Report the following error to \"%s\".",
-			"nethack-bugs@nethack.org");
+	    raw_printf("Report the following error to \"%s\""
+				 ", and it may be possible to rebuild.", "spork@sporkhack.com");
 	else if (program_state.something_worth_saving)
 	    raw_print("\nError save file being written.\n");
@@ -367,5 +460,11 @@
 	    if (!done_stopprint) {
 		c = ask ? yn_function(qbuf, ynqchars, defquery) : defquery;
-		if (c == 'y') {
+	    } else {
+		c = 'n';
+	    }
+		{
+#ifdef DUMP_LOG
+			boolean want_disp = (c == 'y')? TRUE: FALSE;
+#endif
 			struct obj *obj;
 
@@ -374,9 +473,15 @@
 			    obj->known = obj->bknown = obj->dknown = obj->rknown = 1;
 			}
+#ifdef DUMP_LOG
+			(void) dump_inventory((char *)0, TRUE, want_disp);
+			do_containerconts(invent, TRUE, TRUE, TRUE, want_disp);
+#else
+			if (c == 'y') {
 			(void) display_inventory((char *)0, TRUE);
 			container_contents(invent, TRUE, TRUE);
 		}
-		if (c == 'q')  done_stopprint++;
+#endif /* DUMP_LOG */
 	    }
+		if (c == 'q')  done_stopprint++;
 	}
 
@@ -389,12 +494,26 @@
 	    if (c == 'q') done_stopprint++;
 	}
+#ifdef DUMP_LOG
+	if (dump_fp) {
+	  dump_enlightenment((int) (how >= PANICKED ? 1 : 2));
+	  dump_spells();
+	}
+#endif
 
 	ask = should_query_disclose_option('v', &defquery);
+#ifdef DUMP_LOG
+	do_vanquished(defquery, ask, TRUE);
+#else
 	if (!done_stopprint)
 	    list_vanquished(defquery, ask);
+#endif
 
 	ask = should_query_disclose_option('g', &defquery);
 	if (!done_stopprint)
+#ifdef DUMP_LOG
+	    list_genocided(defquery, ask,TRUE);
+#else
 	    list_genocided(defquery, ask);
+#endif
 
 	ask = should_query_disclose_option('c', &defquery);
@@ -406,4 +525,10 @@
 	    if (c == 'q') done_stopprint++;
 	}
+#ifdef DUMP_LOG
+	if (dump_fp) {
+	    dump_conduct(how >= PANICKED ? 1 : 2);
+	    dump_weapon_skill();
+	}
+#endif
 }
 
@@ -524,4 +649,9 @@
 				OBJ_NAME(objects[otmp->otyp]),
 			value, currency(value), points);
+#ifdef DUMP_LOG
+		if (dump_fp)
+		  dump("", pbuf);
+		if (endwin != WIN_ERR)
+#endif
 		putstr(endwin, 0, pbuf);
 	    }
@@ -543,4 +673,5 @@
 	struct obj *corpse = (struct obj *)0;
 	long umoney;
+	long uscore;
 
 	if (how == TRICKED) {
@@ -574,6 +705,16 @@
 		pline("But wait...");
 		makeknown(AMULET_OF_LIFE_SAVING);
-		Your("medallion %s!",
-		      !Blind ? "begins to glow" : "feels warm");
+		Your("medallion %s!", !Blind ? "begins to glow" : "feels warm");
+		/* Keep it blessed! */
+		if (uamul->cursed && !rn2(2)) {
+			pline("The chain on your medallion breaks, and you hear a faint giggling!");
+			Your("medallion suddenly falls off!");
+			pline("It doesn't look like you're going to make it after all...");
+			killer_format = KILLED_BY;
+			Strcpy(kilbuf, "a cursed amulet of life saving");
+			killer = kilbuf;
+			Lifesaved = 0L;
+			uamul = 0;
+		} else {
 		if (how == CHOKING) You("vomit ...");
 		You_feel("much better!");
@@ -587,9 +728,15 @@
 			pline("Unfortunately you are still genocided...");
 		else {
+#ifdef WISH_TRACKER
+				Sprintf(pbuf,"%s lifesaved instead of being killed by a %s on T:%d",plname,killer,moves);
+				makeannounce(pbuf);
+#endif
 			killer = 0;
 			killer_format = 0;
+				ukiller = (struct monst*)0;
 			return;
 		}
 	}
+	}
 	if ((
 #ifdef WIZARD
@@ -604,4 +751,5 @@
 		killer = 0;
 		killer_format = 0;
+		ukiller = (struct monst*)0;
 		return;
 	}
@@ -612,7 +760,24 @@
 
 die:
+	kilbuf[BUFSZ-1] = 0;	 /* cheap hack bugfix */
 	program_state.gameover = 1;
 	/* in case of a subsequent panic(), there's no point trying to save */
 	program_state.something_worth_saving = 0;
+#ifdef DUMP_LOG
+	/* D: Grab screen dump right here */
+	if (dump_fn[0]) {
+	  dump_init();
+	  Sprintf(pbuf, "%s, %s %s %s %s", plname,
+		  aligns[1 - u.ualign.type].adj,
+		  genders[flags.female].adj,
+		  urace.adj,
+		  (flags.female && urole.name.f)?
+		   urole.name.f : urole.name.m);
+	  dump("", pbuf);
+	  /* D: Add a line for clearance from the screen dump */
+	  dump("", "");
+	  dump_screen();
+	}
+#endif /* DUMP_LOG */
 	/* render vision subsystem inoperative */
 	iflags.vision_inited = 0;
@@ -621,4 +786,10 @@
 	inven_inuse(TRUE);
 
+#ifdef RECORD_REALTIME
+        /* Update the realtime counter to reflect the playtime of the current
+         * game. */
+        realtime_data.realtime = get_realtime();
+#endif /* RECORD_REALTIME */
+
 	/* Sometimes you die on the first move.  Life's not fair.
 	 * On those rare occasions you get hosed immediately, go out
@@ -693,6 +864,28 @@
 	if (have_windows) display_nhwindow(WIN_MESSAGE, FALSE);
 
-	if (strcmp(flags.end_disclose, "none") && how != PANICKED)
+	/* Must pre-calculate score here for correct logfile writing */
+
+#ifdef LOGFILE
+	uscore = count_score(how);
+	write_log_entry(how,uscore);
+#endif
+
+	if (strcmp(flags.end_disclose, "none") && how != PANICKED) {
 		disclose(how, taken);
+#if defined(DUMP_LOG) && defined(DUMPMSGS)
+		if (lastmsg >= 0) {
+		  dump ("", "Latest messages");
+		  for (i = lastmsg + 1; i < DUMPMSGS; i++) {
+		    if (msgs[i] && strcmp(msgs[i], "") )
+		      dump ("  ", msgs[i]);
+		  } 
+		  for (i = 0; i <= lastmsg; i++) {
+		    if (msgs[i] && strcmp(msgs[i], "") )
+		      dump ("  ", msgs[i]);
+		  } 
+		  dump ("","");
+		}
+#endif
+	}
 	/* finish_paybill should be called after disclosure but before bones */
 	if (bones_ok && taken) finish_paybill();
@@ -771,5 +964,4 @@
 	}
 
-	if (!done_stopprint) {
 	    Sprintf(pbuf, "%s %s the %s...", Goodbye(), plname,
 		   how != ASCENDED ?
@@ -777,7 +969,11 @@
 		         urole.name.f : urole.name.m) :
 		      (const char *) (flags.female ? "Demigoddess" : "Demigod"));
+	if (!done_stopprint) {
 	    putstr(endwin, 0, pbuf);
 	    putstr(endwin, 0, "");
 	}
+#ifdef DUMP_LOG
+	if (dump_fp) dump("", pbuf);
+#endif
 
 	if (how == ESCAPED || how == ASCENDED) {
@@ -806,8 +1002,7 @@
 	    viz_array[0][0] |= IN_SIGHT; /* need visibility for naming */
 	    mtmp = mydogs;
-	    if (!done_stopprint) Strcpy(pbuf, "You");
+	    Strcpy(pbuf, "You");
 	    if (mtmp) {
 		while (mtmp) {
-		    if (!done_stopprint)
 			Sprintf(eos(pbuf), " and %s", mon_nam(mtmp));
 		    if (mtmp->mtame)
@@ -816,13 +1011,19 @@
 		}
 		if (!done_stopprint) putstr(endwin, 0, pbuf);
+#ifdef DUMP_LOG
+		if (dump_fp) dump("", pbuf);
+#endif
 		pbuf[0] = '\0';
 	    } else {
 		if (!done_stopprint) Strcat(pbuf, " ");
 	    }
-	    if (!done_stopprint) {
 		Sprintf(eos(pbuf), "%s with %ld point%s,",
 			how==ASCENDED ? "went to your reward" :
 					"escaped from the dungeon",
 			u.urexp, plur(u.urexp));
+#ifdef DUMP_LOG
+	    if (dump_fp) dump("", pbuf);
+#endif
+	    if (!done_stopprint) {
 		putstr(endwin, 0, pbuf);
 	    }
@@ -830,5 +1031,8 @@
 	    if (!done_stopprint)
 		artifact_score(invent, FALSE, endwin);	/* list artifacts */
-
+#ifdef DUMP_LOG
+	    else
+		artifact_score(invent, FALSE, WIN_ERR);
+#endif
 	    /* list valuables here */
 	    for (val = valuables; val->list; val++) {
@@ -856,8 +1060,11 @@
 		    }
 		    putstr(endwin, 0, pbuf);
+#ifdef DUMP_LOG
+		    if (dump_fp) dump("", pbuf);
+#endif
 		}
 	    }
 
-	} else if (!done_stopprint) {
+	} else {
 	    /* did not escape or ascend */
 	    if (u.uz.dnum == 0 && u.uz.dlevel <= 0) {
@@ -879,19 +1086,30 @@
 	    Sprintf(eos(pbuf), " with %ld point%s,",
 		    u.urexp, plur(u.urexp));
-	    putstr(endwin, 0, pbuf);
+	    if (!done_stopprint) putstr(endwin, 0, pbuf);
+#ifdef DUMP_LOG
+	    if (dump_fp) dump("", pbuf);
+#endif
 	}
 
-	if (!done_stopprint) {
 	    Sprintf(pbuf, "and %ld piece%s of gold, after %ld move%s.",
 		    umoney, plur(umoney), moves, plur(moves));
-	    putstr(endwin, 0, pbuf);
+	if (!done_stopprint)  putstr(endwin, 0, pbuf);
+#ifdef DUMP_LOG
+	if (dump_fp) {
+	  dump("", pbuf);
+	  Sprintf(pbuf, "Killer: %s", killer);
+	  dump("", pbuf);
 	}
-	if (!done_stopprint) {
+#endif
 	    Sprintf(pbuf,
 	     "You were level %d with a maximum of %d hit point%s when you %s.",
 		    u.ulevel, u.uhpmax, plur(u.uhpmax), ends[how]);
+	if (!done_stopprint) {
 	    putstr(endwin, 0, pbuf);
 	    putstr(endwin, 0, "");
 	}
+#ifdef DUMP_LOG
+	    if (dump_fp) dump("", pbuf);
+#endif
 	if (!done_stopprint)
 	    display_nhwindow(endwin, TRUE);
@@ -910,4 +1128,7 @@
 	    topten(how);
 	}
+#ifdef DUMP_LOG
+	if (dump_fp) dump_exit();
+#endif
 
 	if(done_stopprint) { raw_print(""); raw_print(""); }
@@ -920,6 +1141,21 @@
 struct obj *list;
 boolean identified, all_containers;
+#ifdef DUMP_LOG
+{
+	do_containerconts(list, identified, all_containers, FALSE, TRUE);
+}
+
+void do_containerconts(list, identified, all_containers, want_dump, want_disp)
+struct obj *list;
+boolean identified, all_containers, want_dump, want_disp;
+#endif
+/* The original container_contents function */
 {
 	register struct obj *box, *obj;
+#ifdef SORTLOOT
+        struct obj **oarray;
+        int i,j,n;
+        char *invlet;
+#endif /* SORTLOOT */
 	char buf[BUFSZ];
 
@@ -930,8 +1166,57 @@
 		} else if (box->cobj) {
 		    winid tmpwin = create_nhwindow(NHW_MENU);
+#ifdef SORTLOOT
+		    /* count the number of items */
+		    for (n = 0, obj = box->cobj; obj; obj = obj->nobj) n++;
+		    /* Make a temporary array to store the objects sorted */
+		    oarray = (struct obj **) alloc(n*sizeof(struct obj*));
+
+		    /* Add objects to the array */
+		    i = 0;
+		    invlet = flags.inv_order;
+		nextclass:
+		    for (obj = box->cobj; obj; obj = obj->nobj) {
+                      if (!flags.sortpack || obj->oclass == *invlet) {
+			if (iflags.sortloot == 'f'
+			    || iflags.sortloot == 'l') {
+			  /* Insert object at correct index */
+			  for (j = i; j; j--) {
+			    if (strcmpi(cxname2(obj), cxname2(oarray[j-1]))>0
+			    || (flags.sortpack &&
+				oarray[j-1]->oclass != obj->oclass))
+			      break;
+			    oarray[j] = oarray[j-1];
+			  }
+			  oarray[j] = obj;
+			  i++;
+			} else {
+			  /* Just add it to the array */
+			  oarray[i++] = obj;
+			}
+		      }
+		    } /* for loop */
+		    if (flags.sortpack) {
+		      if (*++invlet) goto nextclass;
+		    }
+#endif /* SORTLOOT */
+#ifdef DUMP_LOG
+		    if (want_disp)
+#endif
 		    Sprintf(buf, "Contents of %s:", the(xname(box)));
+#ifdef DUMP_LOG
+		    if (want_disp) {
+#endif
 		    putstr(tmpwin, 0, buf);
 		    putstr(tmpwin, 0, "");
+#ifdef DUMP_LOG
+		    }
+		    if (dump_fp) dump("", buf);
+#endif
+#ifdef SORTLOOT
+		    for (i = 0; i < n; i++) {
+			obj = oarray[i];
+#else
 		    for (obj = box->cobj; obj; obj = obj->nobj) {
+#endif
 			if (identified) {
 			    makeknown(obj->otyp);
@@ -939,13 +1224,50 @@
 			    obj->dknown = obj->rknown = 1;
 			}
+#ifdef DUMP_LOG
+ 			if (want_dump)  dump("  ", doname(obj));
+ 			if (want_disp)
+#endif
 			putstr(tmpwin, 0, doname(obj));
 		    }
+#ifdef DUMP_LOG
+		    if (want_dump)  dump("","");
+		    if (want_disp) {
+#endif
 		    display_nhwindow(tmpwin, TRUE);
 		    destroy_nhwindow(tmpwin);
-		    if (all_containers)
+#ifdef DUMP_LOG
+		    }
+		    if (all_containers) {
+			do_containerconts(box->cobj, identified, TRUE,
+					  want_dump, want_disp);
+#else
+		    if (all_containers) {
 			container_contents(box->cobj, identified, TRUE);
+#endif
+			 }
+		} else {
+			if (box->otyp == BAG_OF_POO) {
+				Sprintf(buf," is rather full of %s poo.",rndmonnam());
+			}
+#ifdef DUMP_LOG
+		    if (want_disp) {
+#endif
+				 if (box->otyp == BAG_OF_POO) {
+					 pline("%s%s",The(xname(box)),buf);
 		} else {
 		    pline("%s empty.", Tobjnam(box, "are"));
+				 }
 		    display_nhwindow(WIN_MESSAGE, FALSE);
+#ifdef DUMP_LOG
+		    }
+		    if (want_dump) {
+				 if (box->otyp == BAG_OF_POO) {
+					 dump(The(xname(box)),buf);
+				 } else {
+					dump(The(xname(box)), " is empty.");
+				 }
+		      dump("", "");
+		    }
+#endif
 		}
 	    }
@@ -978,4 +1300,15 @@
 char defquery;
 boolean ask;
+#ifdef DUMP_LOG
+{
+  do_vanquished(defquery, ask, FALSE);
+}
+
+void
+do_vanquished(defquery, ask, want_dump)
+int defquery;
+boolean ask;
+boolean want_dump;
+#endif
 {
     register int i, lev;
@@ -997,5 +1330,10 @@
      */
     if (ntypes != 0) {
-	c = ask ? yn_function("Do you want an account of creatures vanquished?",
+#ifdef DUMP_LOG
+	c = done_stopprint ? 'n': ask ?
+#else
+	c = ask ?
+#endif
+	  yn_function("Do you want an account of creatures vanquished?",
 			      ynqchars, defquery) : defquery;
 	if (c == 'q') done_stopprint++;
@@ -1004,4 +1342,8 @@
 	    putstr(klwin, 0, "Vanquished creatures:");
 	    putstr(klwin, 0, "");
+#ifdef DUMP_LOG
+	} /* the original end of block removed by the patch */
+	    if (want_dump)  dump("", "Vanquished creatures");
+#endif
 
 	    /* countdown by monster "toughness" */
@@ -1031,18 +1373,33 @@
 				    nkilled, makeplural(mons[i].mname));
 		    }
-		    putstr(klwin, 0, buf);
+		    if (c == 'y') putstr(klwin, 0, buf);
+#ifdef DUMP_LOG
+		    if (want_dump)  dump("  ", buf);
+#endif
+		}
+		 Strcpy(buf,"and a partridge in a pear tree");
+	     if (christmas()) {
+	         if (c == 'y') putstr(klwin, 0, buf);
+#ifdef DUMP_LOG
+				if (want_dump) dump("  ",buf);
+#endif
 		}
-	    /*
-	     * if (Hallucination)
-	     *     putstr(klwin, 0, "and a partridge in a pear tree");
-	     */
 	    if (ntypes > 1) {
-		putstr(klwin, 0, "");
+		if (c == 'y') putstr(klwin, 0, "");
 		Sprintf(buf, "%ld creatures vanquished.", total_killed);
-		putstr(klwin, 0, buf);
+		if (c == 'y') putstr(klwin, 0, buf);
+#ifdef DUMP_LOG
+		if (want_dump)  dump("  ", buf);
+#endif
 	    }
+	    if (c == 'y') {
 	    display_nhwindow(klwin, TRUE);
 	    destroy_nhwindow(klwin);
 	}
+#ifdef DUMP_LOG
+	    if (want_dump)  dump("", "");
+#else
+	} /* the original end of if (c == 'y') */
+#endif
     }
 }
@@ -1060,8 +1417,16 @@
 }
 
+#ifdef DUMP_LOG
+STATIC_OVL void
+list_genocided(defquery, ask, want_dump)
+int defquery;
+boolean ask;
+boolean want_dump;
+#else
 STATIC_OVL void
 list_genocided(defquery, ask)
 char defquery;
 boolean ask;
+#endif
 {
     register int i;
@@ -1080,6 +1445,10 @@
 	if (c == 'y') {
 	    klwin = create_nhwindow(NHW_MENU);
-	    putstr(klwin, 0, "Genocided species:");
+	    Sprintf(buf, "Genocided species:");
+	    putstr(klwin, 0, buf);
 	    putstr(klwin, 0, "");
+#ifdef DUMP_LOG
+	    if (want_dump)  dump("", buf);
+#endif
 
 	    for (i = LOW_PM; i < NUMMONS; i++)
@@ -1092,4 +1461,7 @@
 			Strcpy(buf, makeplural(mons[i].mname));
 		    putstr(klwin, 0, buf);
+#ifdef DUMP_LOG
+		    if (want_dump)  dump("  ", buf);
+#endif
 		}
 
@@ -1097,4 +1469,7 @@
 	    Sprintf(buf, "%d species genocided.", ngenocided);
 	    putstr(klwin, 0, buf);
+#ifdef DUMP_LOG
+	    if (want_dump)  dump("  ", buf);
+#endif
 
 	    display_nhwindow(klwin, TRUE);
@@ -1104,3 +1479,86 @@
 }
 
+
+/* All of this is bolted together in an effort to get an accurate
+ * score now that the logfile's been moved so far up.  Don't
+ * suggest using it for anything else. */
+
+STATIC_OVL 
+long count_score(how)
+int how;
+{
+	long tmp, newscore, umoney, old_exp;
+	int deepest = deepest_lev_reached(FALSE);
+
+	newscore = u.urexp;
+
+#ifndef GOLDOBJ
+	umoney = u.ugold;
+	tmp = u.ugold0;
+#else
+	umoney = money_cnt(invent);
+	tmp = u.umoney0;
+#endif
+	umoney += hidden_gold();
+	tmp = umoney - tmp;
+
+	if (tmp < 0L) tmp = 0L;
+
+	if (how < PANICKED) {
+		tmp -= tmp / 10L;
+	}
+
+	newscore += tmp;
+	newscore += 50L * (long)(deepest - 1);
+
+	if (deepest > 20) {
+		newscore += 1000L * (long)((deepest > 30) ? 10 : deepest - 20);
+	}
+
+	if (how == ASCENDED) {
+		newscore *= 2L;
+	}
+
+	if (how == ESCAPED || how == ASCENDED) {
+		register struct monst *mtmp;
+		register struct obj *otmp;
+		register struct val_list *val;
+		register int i;
+
+		for (val = valuables; val->list; val++) {
+			for (i = 0; i < val->size; i++) {
+				val->list[i].count = 0L;
+			}
+		}
+		get_valuables(invent);
+
+		/* add points for collected valuables */
+		for (val = valuables; val->list; val++)
+				for (i = 0; i < val->size; i++)
+					if (val->list[i].count != 0L)
+						newscore += val->list[i].count * (long)objects[val->list[i].typ].oc_cost;
+
+		/* count the points for artifacts, with a juggling act since
+		 * it's inherently somewhat destructive */
+		old_exp = u.urexp;
+		u.urexp = newscore;
+		artifact_score(invent, TRUE, WIN_ERR);
+		newscore = u.urexp;
+		u.urexp = old_exp;
+
+		viz_array[0][0] |= IN_SIGHT; /* need visibility for naming */
+		mtmp = mydogs;
+		if (mtmp) {
+			while (mtmp) {
+				if (mtmp->mtame) {
+					newscore += mtmp->mhp;
+				}
+				mtmp = mtmp->nmon;
+			}
+		}
+	}
+
+	return newscore;
+}
+
 /*end.c*/
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/src/engrave.c nethack/src/engrave.c
--- nh_orig/src/engrave.c	2003-12-07 18:39:13.000000000 -0500
+++ nethack/src/engrave.c	2010-04-29 10:53:23.924715044 -0400
@@ -5,8 +5,7 @@
 #include "hack.h"
 #include "lev.h"
+#include "decl.h"
 #include <ctype.h>
 
-STATIC_VAR NEARDATA struct engr *head_engr;
-
 #ifdef OVLB
 /* random engravings */
@@ -34,4 +33,24 @@
 #endif
 	"As if!", /* Clueless */
+	"Arooo!  Werewolves of Yendor!", /* gang tag */
+	"Dig for Victory here", /* pun, duh */
+	"Don't go this way",
+	"Gaius Julius Primigenius was here.  Why are you late?", /* pompeii */
+	"Go left --->", "<--- Go right",
+	"Haermund Hardaxe carved these runes", /* viking graffiti */
+	"Here be dragons",
+	"Need a light?  Come visit the Minetown branch of Izchak's Lighting Store!",
+	"Save now, and do your homework!",
+	"Snakes on the Astral Plane - Soon in a dungeon near you",
+	"There was a hole here.  It's gone now.",
+	"The Vibrating Square",
+	"This is a pit!",
+	"This is not the dungeon you are looking for.",
+	"This square deliberately left blank.",
+	"Warning, Exploding runes!",
+	"Watch out, there's a gnome with a wand of death behind that door!",
+	"X marks the spot",
+	"X <--- You are here.",
+	"You are the one millionth visitor to this place!  Please wait 200 turns for your wand of wishing.",
 };
 
@@ -344,5 +363,5 @@
 		You("%s: \"%s\".",
 		      (Blind) ? "feel the words" : "read",  et);
-		if(flags.run > 1) nomul(0);
+		if(flags.run > 1) nomul(0, 0);
 	    }
 	}
@@ -447,5 +466,6 @@
 	xchar type = DUST;	/* Type of engraving made */
 	char buf[BUFSZ];	/* Buffer for final/poly engraving text */
-	char ebuf[BUFSZ];	/* Buffer for initial engraving text */
+	static char oebuf[BUFSZ] = "";
+	char ebuf[BUFSZ] = "";	/* Buffer for initial engraving text */
 	char qbuf[QBUFSZ];	/* Buffer for query text */
 	char post_engr_text[BUFSZ]; /* Text displayed after engraving prompt */
@@ -464,5 +484,4 @@
 
 	buf[0] = (char)0;
-	ebuf[0] = (char)0;
 	post_engr_text[0] = (char)0;
 	maxelen = BUFSZ - 1;
@@ -698,4 +717,7 @@
 			}
 			break;
+		    case WAN_WIND:
+			Strcpy(post_engr_text, "The bugs on the floor are blown away!");
+			break;
 
 		    /* type = ENGRAVE wands */
@@ -971,5 +993,8 @@
 	/* Prompt for engraving! */
 	Sprintf(qbuf,"What do you want to %s the %s here?", everb, eloc);
-	getlin(qbuf, ebuf);
+	getlin(qbuf, oebuf);
+	(void) strncpy(ebuf, oebuf, BUFSZ);
+	stripctrl(oebuf);
+	trim(oebuf);
 
 	/* Count the actual # of chars engraved not including spaces */
@@ -1230,5 +1255,367 @@
 	"Soon ripe. Soon rotten. Soon gone. But not forgotten.",
 	"Here lies the body of Jonathan Blake. Stepped on the gas instead of the brake.",
-	"Go away!"
+	"Go away!",
+	"Alas fair Death, 'twas missed in life - some peace and quiet from my wife",
+	"Applaud, my friends, the comedy is finished.",
+	"At last... a nice long sleep.",
+	"Audi Partem Alteram",
+	"Basil, assaulted by bears",
+	"Burninated",
+	"Confusion will be my epitaph",
+	"Do not open until Christmas",
+	"Don't be daft, they couldn't hit an elephant at this dist-",
+	"Don't forget to stop and smell the roses",
+	"Don't let this happen to you!",
+	"Dulce et decorum est pro patria mori",
+	"Et in Arcadia ego",
+	"Fatty and skinny went to bed.  Fatty rolled over and skinny was dead.  Skinny Smith 1983-2000.",
+	"Finally I am becoming stupider no more",
+	"Follow me to hell",
+	"...for famous men have the whole earth as their memorial",
+	"Game over, man.  Game over.",
+	"Go away!  I'm trying to take a nap in here!  Bloody adventurers...",
+	"Gone fishin'",
+	"Good night, sweet prince: And flights of angels sing thee to thy rest!",
+	"Go Team Ant!",
+	"He farmed his way here",
+	"Here lies a programmer.  Killed by a fatal error.",
+	"Here lies Bob - decided to try an acid blob",
+	"Here lies Dudley, killed by another %&#@#& newt.",
+	"Here lies Gregg, choked on an egg",
+	"Here lies Lies. It's True",
+	"Here lies The Lady's maid, died of a Vorpal Blade",
+	"Here lies the left foot of Jack, killed by a land mine.  Let us know if you find any more of him",
+	"He waited too long",
+	"I'd rather be sailing",
+	"If a man's deeds do not outlive him, of what value is a mark in stone?",
+	"I'm gonna make it!",
+	"I took both pills!",
+	"I will survive!",
+	"Killed by a black dragon -- This grave is empty",
+	"Let me out of here!",
+	"Lookin' good, Medusa.",
+	"Mrs. Smith, choked on an apple.  She left behind grieving husband, daughter, and granddaughter.",
+	"Nobody believed her when she said her feet were killing her",
+	"No!  I don't want to see my damn conduct!",
+	"One corpse, sans head",
+	"On the whole, I'd rather be in Minetown",
+	"On vacation",
+	"Oops.",
+	"Out to Lunch",
+	"SOLD",
+	"Someone set us up the bomb!",
+	"Take my stuff, I don't need it anymore",
+	"Taking a year dead for tax reasons",
+	"The reports of my demise are completely accurate",
+	"(This space for sale)",
+	"This was actually just a pit, but since there was a corpse, we filled it",
+	"This way to the crypt",
+	"Tu quoque, Brute?",
+	"VACANCY",
+	"Welcome!",
+	"Wish you were here!",
+	"Yea, it got me too",
+	"You should see the other guy",
+	"...and they made me engrave my own headstone too!",
+	"...but the blood has stopped pumping and I am left to decay...",
+	"<Expletive Deleted>",
+	"A masochist is never satisfied.",
+	"Ach, 'twas a wee monster in the loch",
+	"Adapt.  Enjoy.  Survive.",
+	"Adventure, hah!  Excitement, hah!",
+	"After all, what are friends for...",
+	"After this, nothing will shock me",
+	"After three days, fish and guests stink",
+	"Age and treachery will always overcome youth and skill",
+	"Ageing is not so bad.  The real killer is when you stop.",
+	"Ain't I a stinker?",
+	"Algernon",
+	"All else failed...",
+	"All hail RNG",
+	"All right, we'll call it a draw!",
+	"All's well that end well",
+	"Alone at last!",
+	"Always attack a floating eye from behind!",
+	"Am I having fun yet?",
+	"And I can still crawl, I'm not dead yet!",
+	"And all I wanted was a free lunch",
+	"And all of the signs were right there on your face",
+	"And don't give me that innocent look either!",
+	"And everyone died.  Boo hoo hoo.",
+	"And here I go again...",
+	"And nobody cares until somebody famous dies...",
+	"And so it ends?",
+	"And so... it begins.",
+	"And sometimes the bear eats you.",
+	"And then 'e nailed me 'ead to the floor!",
+	"And they said it couldn't be done!",
+	"And what do I look like?  The living?",
+	"And yes, it was ALL his fault!",
+	"And you said it was pretty here...",
+	"Another lost soul",
+	"Any day above ground is a good day!",
+	"Any more of this and I'll die of a stroke before I'm 30.",
+	"Anybody seen my head?",
+	"Anyone for deathmatch?",
+	"Anything for a change.",
+	"Anything that kills you makes you ... well, dead",
+	"Anything worth doing is worth overdoing.",
+	"Are unicorns supposedly peaceful if you're a virgin?  Hah!",
+	"Are we all being disintegrated, or is it just me?",
+	"At least I'm good at something",
+	"Attempted suicide",
+	"Auribus teneo lupum",
+	"Be prepared",
+	"Beauty survives",
+	"Been Here. Now Gone. Had a Good Time.",
+	"Been through Hell, eh?  What did you bring me?",
+	"Beg your pardon, didn't recognize you, I've changed a lot.",
+	"Being dead builds character",
+	"Beloved daughter, a treasure, buried here.",
+	"Best friends come and go...  Mine just die.",
+	"Better be dead than a fat slave",
+	"Better luck next time",
+	"Beware of Discordians bearing answers",
+	"Beware the ...",
+	"Bloody Hell...",
+	"Bloody barbarians!",
+	"Blown upward out of sight: He sought the leak by candlelight",
+	"Brains... Brains... Fresh human brains...",
+	"Buried the cat.  Took an hour.  Damn thing kept fighting.",
+	"But I disarmed the trap!",
+	"CONNECT 1964 - NO CARRIER 1994",
+	"Call me if you need my phone number!",
+	"Can YOU fly?",
+	"Can you believe that thing is STILL moving?",
+	"Can you come up with some better ending for this?",
+	"Can you feel anything when I do this?",
+	"Can you give me mouth to mouth, you just took my breath away.",
+	"Can't I just have a LITTLE peril?",
+	"Can't eat, can't sleep, had to bury the husband here.",
+	"Can't you hit me?!",
+	"Chaos, panic and disorder.  My work here is done.",
+	"Check enclosed.",
+	"Check this out!  It's my brain!",
+	"Chivalry is only reasonably dead",
+	"Coffin for sale.  Lifetime guarantee.",
+	"Come Monday, I'll be all right.",
+	"Come and see the violence inherent in the system",
+	"Come back here!  I'll bite your bloody knees off!",
+	"Commodore Business Machines, Inc.   Died for our sins.",
+	"Complain to one who can help you",
+	"Confess my sins to god?  Which one?",
+	"Confusion will be my epitaph",
+	"Cooties?  Ain't no cooties on me!",
+	"Could somebody get this noose off me?",
+	"Could you check again?  My name MUST be there.",
+	"Could you please take a breath mint?",
+	"Couldn't I be sedated for this?",
+	"Courage is looking at your setbacks with serenity",
+	"Cover me, I'm going in!",
+	"Crash course in brain surgery",
+	"Cross my fingers for me.",
+	"Curse god and die",
+	"Cut to fit",
+	"De'Ath",
+	"Dead Again?  Pardon me for not getting it right the first time!",
+	"Dead and loving every moment!",
+	"Dear wife of mine. Died of a broken heart, after I took it out of her.",
+	"Don't tread on me!",
+	"Dragon? What dragon?",
+	"Drawn and quartered",
+	"Either I'm dead or my watch has stopped.",
+	"Eliza -- Was I really alive, or did I just think I was?",
+	"Elvis",
+	"Enter not into the path of the wicked",
+	"Eris?  I don't need Eris",
+	"Eternal Damnation, Come and stay a long while!",
+	"Even The Dead pay taxes (and they aren't Grateful).",
+	"Even a tomb stone will say good things when you're down!",
+	"Ever notice that live is evil backwards?",
+	"Every day is starting to look like Monday",
+	"Every day, in every way, I am getting better and better.",
+	"Every survival kit should include a sense of humor",
+	"Evil I did dwell;  lewd did I live",
+	"Ex post fucto",
+	"Excellent day to have a rotten day.",
+	"Excuse me for not standing up.",
+	"Experience isn't everything. First, You've got to survive",
+	"First shalt thou pull out the Holy Pin",
+	"For a Breath, I Tarry...",
+	"For recreational use only.",
+	"For sale: One soul, slightly used. Asking for 3 wishes.",
+	"For some moments in life, there are no words.",
+	"Forget Disney World, I'm going to Hell!",
+	"Forget about the dog, Beware of my wife.",
+	"Funeral - Real fun.",
+	"Gawd, it's depressing in here, isn't it?",
+	"Genuine Exploding Gravestone.  (c)Acme Gravestones Inc.",
+	"Get back here!  I'm not finished yet...",
+	"Go ahead, I dare you to!",
+	"Go ahead, it's either you or him.",
+	"Goldilocks -- This casket is just right",
+	"Gone But Not Forgotten",
+	"Gone Underground For Good",
+	"Gone away owin' more than he could pay.",
+	"Gone, but not forgiven",
+	"Got a life. Didn't know what to do with it.",
+	"Grave?  But I was cremated!",
+	"Greetings from Hell - Wish you were here.",
+	"HELP! It's dark in here... Oh, my eyes are closed - sorry",
+	"Ha! I NEVER pay income tax!",
+	"Have you come to raise the dead?",
+	"Having a good time can be deadly.",
+	"Having a great time. Where am I exactly??",
+	"He died of the flux.",
+	"He died today... May we rest in peace!",
+	"He got the upside, I got the downside.",
+	"He lost his face when he was beheaded.",
+	"He missed me first.",
+	"He's not dead, he just smells that way.",
+	"Help! I've fallen and I can't get up!",
+	"Help, I can't wake up!",
+	"Here lies Pinocchio",
+	"Here lies the body of John Round. Lost at sea and never found.",
+	"Here there be dragons",
+	"Hey, I didn't write this stuff!",
+	"Hold my calls",
+	"Home Sweet Hell",
+	"Humpty Dumpty, a Bad Egg.  He was pushed off the wall.",
+	"I KNEW this would happen if I lived long enough.",
+	"I TOLD you I was sick!",
+	"I ain't broke but I am badly bent.",
+	"I ain't old. I'm chronologically advantaged.",
+	"I am NOT a vampire. I just like to bite..nibble, really!",
+	"I am here. Wish you were fine.",
+	"I am not dead yet, but watch for further reports.",
+	"I believe them bones are me.",
+	"I broke his brain.",
+	"I can feel it.  My mind.  It's going.  I can feel it.",
+	"I can't go to Hell. They're afraid I'm gonna take over!",
+	"I can't go to hell, they don't want me.",
+	"I didn't believe in reincarnation the last time, either.",
+	"I didn't mean it when I said 'Bite me'",
+	"I died laughing",
+	"I disbelieved in reincarnation in my last life, too.",
+	"I hacked myself to death",
+	"I have all the time in the world",
+	"I knew I'd find a use for this gravestone!",
+	"I know my mind. And it's around here someplace.",
+	"I lied!  I'll never be alright!",
+	"I like it better in the dark.",
+	"I like to be here when I can.",
+	"I may rise but I refuse to shine.",
+	"I never get any either.",
+	"I said hit HIM with the fireball, not me!",
+	"I told you I would never say goodbye.",
+	"I used to be amusing. Now I'm just disgusting.",
+	"I used up all my sick days, so now I'm calling in dead.",
+	"I was killed by <illegible scrawl>",
+	"I was somebody. Who, is no business of yours.",
+	"I will not go quietly.",
+	"I'd give you a piece of my mind... but I can't find it.",
+	"I'd rather be breathing",
+	"I'll be back!",
+	"I'll be mellow when I'm dead. For now, let's PARTY!",
+	"I'm doing this only for tax purposes.",
+	"I'm not afraid of Death!  What's he gonna do? Kill me?",
+	"I'm not getting enough money, so I'm not going to engrave anything useful here.",
+	"I'm not saying anything.",
+	"I'm weeth stupeed --->",
+	"If you thought you had problems...",
+	"Ignorance kills daily.",
+	"Ignore me... I'm just here for my looks!",
+	"Ilene Toofar -- Fell off a cliff",
+	"Is that all?",
+	"Is there life before Death?",
+	"Is this a joke, or a grave matter?",
+	"It happens sometimes. People just explode.",
+	"It must be Thursday. I never could get the hang of Thursdays.",
+	"It wasn't a fair fight",
+	"It wasn't so easy.",
+	"It's Loot, Pillage and THEN Burn...",
+	"Just doing my job here",
+	"Killed by diarrhea of mouth and constipation of brain.",
+	"Let her RIP",
+	"Let it be; I am dead.",
+	"Let's play Hide the Corpse",
+	"Life is NOT a dream",
+	"Madge Ination -- It wasn't all in my head",
+	"Meet me in Heaven",
+	"Move on, there's nothing to see here.",
+	"Mr. Flintstone -- Yabba-dabba-done",
+	"My heart is not in this",
+	"No one ever died from it",
+	"No, you want room 12A, next door.",
+	"Nope.  No trap on that chest.  I swear.",
+	"Not again!",
+	"Not every soil can bear all things",
+	"Now I have a life",
+	"Now I lay thee down to sleep... wanna join me?",
+	"OK, here is a question: Where ARE your tanlines?",
+	"Obesa Cantavit",
+	"Oh! An untimely death.",
+	"Oh, by the way, how was my funeral?",
+	"Oh, honey..I missed you! She said, and fired again.",
+	"Ok, so the light does go off. Now let me out of here.",
+	"One stone brain",
+	"Ooh! Somebody STOP me!",
+	"Oops!",
+	"Out for the night.  Leave a message.",
+	"Ow!  Do that again!",
+	"Pardon my dust.",
+	"Part of me still works.",
+	"Please, not in front of those orcs!",
+	"Prepare to meet me in Heaven",
+	"R2D2 -- Rest, Tin Piece",
+	"Relax.  Nothing ever happens on the first level.",
+	"Res omnia mea culpa est",
+	"Rest In Pieces",
+	"Rest, rest, perturbed spirit.",
+	"Rip Torn",
+	"She always said her feet were killing her but nobody believed her.",
+	"She died of a chest cold.",
+	"So let it be written, so let it be done!",
+	"So then I says, How do I know you're the real angel of death?",
+	"Some patients insist on dying.",
+	"Some people have it dead easy, don't they?",
+	"Some things are better left buried.",
+	"Sure, trust me, I'm a lawyer...",
+	"Thank God I wore my corset, because I think my sides have split.",
+	"That is all",
+	"The Gods DO have a sense of humor: I'm living proof!",
+	"The frog's dead. He Kermitted suicide.",
+	"This dungeon is a pushover",
+	"This elevator doesn't go to Heaven",
+	"This gravestone is shareware. To register, please send me 10 zorkmids",
+	"This gravestone provided by The Yendorian Grave Services Inc.",
+	"This is not an important part of my life.",
+	"This one's on me.",
+	"This side up",
+	"Tim Burr -- Smashed by a tree",
+	"Tone it down a bit, I'm trying to get some rest here.",
+	"Virtually Alive",
+	"We Will Meet Again.",
+	"Weep not, he is at rest",
+	"Welcome to Dante's.  What level please?",
+	"Well, at least they listened to my sermon...",
+	"Went to be an angel.",
+	"What are you doing over there?",
+	"What are you smiling at?",
+	"What can you say, Death's got appeal...!",
+	"What health care?",
+	"What pit?",
+	"When the gods want to punish you, they answer your prayers.",
+	"Where e'er you be let your wind go free. Keeping it in was the death of me!",
+	"Where's my refund?",
+	"Will let you know for sure in a day or two...",
+	"Wizards are wimps",
+	"Worms at work, do not disturb!",
+	"Would you mind moving a bit?  I'm short of breath down here.",
+	"Would you quit being evil over my shoulder?",
+	"Ya really had me going baby, but now I'm gone.",
+	"Yes Dear, just a few more minutes...",
+	"You said it wasn't poisonous!",
+	"You set my heart aflame. You gave me heartburn."
 };
 
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/src/exper.c nethack/src/exper.c
--- nh_orig/src/exper.c	2003-12-07 18:39:13.000000000 -0500
+++ nethack/src/exper.c	2009-08-02 13:49:38.662408417 -0400
@@ -141,5 +141,5 @@
 	}
 	num = newhp();
-	u.uhpmax -= num;
+	gainmaxhp(-num);
 	if (u.uhpmax < 1) u.uhpmax = 1;
 	u.uhp -= num;
@@ -186,4 +186,7 @@
 	if (!incr) You_feel("more experienced.");
 	num = newhp();
+	/* we let this go rather than pushing it through gainmaxhp() because
+	 * the player's HP growth from levels is already restricted at XL30
+	 * and we don't want to screw them on level gain */
 	u.uhpmax += num;
 	u.uhp += num;
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/src/explode.c nethack/src/explode.c
--- nh_orig/src/explode.c	2003-12-07 18:39:13.000000000 -0500
+++ nethack/src/explode.c	2009-11-22 07:19:36.480398230 -0500
@@ -42,4 +42,10 @@
 	boolean shopdamage = FALSE;
 	boolean generic = FALSE;
+	boolean skipitems = FALSE;
+
+#if 0
+	// No good justification for this.  Why should
+	// these roles take _such_ less damage from explosions?
+	// If they're going to huck fireballs around, _be careful_.
 
 	if (olet == WAND_CLASS)		/* retributive strike */
@@ -54,4 +60,5 @@
 			default:  break;
 		}
+#endif
 
 	if (olet == MON_EXPLODE) {
@@ -105,19 +112,19 @@
 				break;
 			case AD_FIRE:
-				explmask[i][j] = !!Fire_resistance;
+				explmask[i][j] = (how_resistant(FIRE_RES) > 50);
 				break;
 			case AD_COLD:
-				explmask[i][j] = !!Cold_resistance;
+				explmask[i][j] = (how_resistant(COLD_RES) > 50);
 				break;
 			case AD_DISN:
 				explmask[i][j] = (olet == WAND_CLASS) ?
 						!!(nonliving(youmonst.data) || is_demon(youmonst.data)) :
-						!!Disint_resistance;
+						(how_resistant(DISINT_RES) > 50);
 				break;
 			case AD_ELEC:
-				explmask[i][j] = !!Shock_resistance;
+				explmask[i][j] = (how_resistant(SHOCK_RES) > 50);
 				break;
 			case AD_DRST:
-				explmask[i][j] = !!Poison_resistance;
+				explmask[i][j] = (how_resistant(POISON_RES) > 50);
 				break;
 			case AD_ACID:
@@ -226,5 +233,5 @@
 	}
 
-    if (dam)
+    if (dam) {
 	for (i=0; i<3; i++) for (j=0; j<3; j++) {
 		if (explmask[i][j] == 2) continue;
@@ -233,6 +240,5 @@
 		idamres = idamnonres = 0;
 		if (type >= 0)
-		    (void)zap_over_floor((xchar)(i+x-1), (xchar)(j+y-1),
-		    		type, &shopdamage);
+				(void)zap_over_floor((xchar)(i+x-1), (xchar)(j+y-1), type, &shopdamage, MON_CASTBALL);
 
 		mtmp = m_at(i+x-1, j+y-1);
@@ -278,5 +284,5 @@
 		if (explmask[i][j] == 1) {
 			golemeffects(mtmp, (int) adtyp, dam + idamres);
-			mtmp->mhp -= idamnonres;
+				damage_mon(mtmp,idamnonres,adtyp);
 		} else {
 		/* call resist with 0 and do damage manually so 1) we can
@@ -297,12 +303,17 @@
 			else if (resists_fire(mtmp) && adtyp == AD_COLD)
 				mdam *= 2;
-			mtmp->mhp -= mdam;
-			mtmp->mhp -= (idamres + idamnonres);
+				damage_mon(mtmp,mdam,adtyp);
+				damage_mon(mtmp,idamres + idamnonres,adtyp);
 		}
 		if (mtmp->mhp <= 0) {
-			/* KMH -- Don't blame the player for pets killing gas spores */
-			if (!flags.mon_moving) killed(mtmp);
-			else monkilled(mtmp, "", (int)adtyp);
-		} else if (!flags.mon_moving) setmangry(mtmp);
+				/* KMH -- Don't blame the player for pets killing gas spores
+				 * DSR -- And don't blame the player for monsters fireballing things */
+				if (!flags.mon_moving && olet != MON_CASTBALL) {
+					killed(mtmp);
+				} else {
+					monkilled(mtmp, "", (int)adtyp);
+				}
+			} else if (!flags.mon_moving && olet != MON_CASTBALL) setmangry(mtmp);
+		}
 	}
 
@@ -314,4 +325,8 @@
 		/* do property damage first, in case we end up leaving bones */
 		if (adtyp == AD_FIRE) burn_away_slime();
+		/* small explosions won't burn your items up anymore
+		 * ...this needs to be here so gnomish wizards aren't
+		 * frosting or toasting all your stuff on xl2 */
+		skipitems = (damu <= 16);
 		if (Invulnerable) {
 		    damu = 0;
@@ -319,5 +334,6 @@
 		} else if (Half_physical_damage && adtyp == AD_PHYS)
 		    damu = (damu+1) / 2;
-		if (adtyp == AD_FIRE) (void) burnarmor(&youmonst);
+		if (adtyp == AD_FIRE && !skipitems) (void) burnarmor(&youmonst);
+		if (!skipitems) {
 		destroy_item(SCROLL_CLASS, (int) adtyp);
 		destroy_item(SPBOOK_CLASS, (int) adtyp);
@@ -325,4 +341,5 @@
 		destroy_item(RING_CLASS, (int) adtyp);
 		destroy_item(WAND_CLASS, (int) adtyp);
+		}
 
 		ugolemeffects((int) adtyp, damu);
@@ -335,4 +352,9 @@
 		}
 
+		/* You resisted the damage, so alert critters */
+		if (uhurt == 1) {
+			monstseesu(1 << (adtyp-1));
+		}
+
 		if (u.uhp <= 0 || (Upolyd && u.mh <= 0)) {
 		    if (Upolyd) {
@@ -344,4 +366,7 @@
 				Strcpy(killer_buf, str);
 			    killer_format = KILLED_BY_AN;
+			} else if (olet == MON_CASTBALL) {
+				killer_format = KILLED_BY_AN;
+				Strcpy(killer_buf, str);
 			} else if (type >= 0 && olet != SCROLL_CLASS) {
 			    killer_format = NO_KILLER_PREFIX;
@@ -514,5 +539,5 @@
 				    int hitvalu, hitu;
 
-				    if (multi) nomul(0);
+				    if (multi) nomul(0, 0);
 				    hitvalu = 8 + stmp->obj->spe;
 				    if (bigmonst(youmonst.data)) hitvalu++;
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/src/extralev.c nethack/src/extralev.c
--- nh_orig/src/extralev.c	2003-12-07 18:39:13.000000000 -0500
+++ nethack/src/extralev.c	2010-05-13 09:22:21.979839300 -0400
@@ -329,10 +329,10 @@
 		ghostobj = mksobj_at(RING_MAIL, x, y, FALSE, FALSE);
 		ghostobj->spe = rn2(3);
-		if (!rn2(3)) ghostobj->oerodeproof = TRUE;
+		if (!rn2(3)) set_erodeproof(ghostobj);
 		if (rn2(4)) curse(ghostobj);
 	} else {
 		ghostobj = mksobj_at(PLATE_MAIL, x, y, FALSE, FALSE);
 		ghostobj->spe = rnd(5) - 2;
-		if (!rn2(3)) ghostobj->oerodeproof = TRUE;
+		if (!rn2(3)) set_erodeproof(ghostobj);
 		if (rn2(4)) curse(ghostobj);
 	}
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/src/files.c nethack/src/files.c
--- nh_orig/src/files.c	2003-12-07 18:39:13.000000000 -0500
+++ nethack/src/files.c	2009-08-02 13:49:38.667410509 -0400
@@ -12,5 +12,5 @@
 #include <ctype.h>
 
-#if !defined(MAC) && !defined(O_WRONLY) && !defined(AZTEC_C)
+#if (!defined(MAC) && !defined(O_WRONLY) && !defined(AZTEC_C)) || defined(USE_FCNTL)
 #include <fcntl.h>
 #endif
@@ -535,4 +535,7 @@
 	for (x = (n_dgns ? maxledgerno() : 0); x >= 0; x--)
 		delete_levelfile(x);	/* not all levels need be present */
+#  ifdef WHEREIS_FILE
+	delete_whereis();
+#  endif
 #endif
 }
@@ -599,4 +602,110 @@
 #endif
 	
+#ifdef WISH_TRACKER
+const char* wish_tracker_file =
+# ifdef UNIX
+		"wishtracker";
+# else
+#  if defined(MAC) || defined(__BEOS__)
+		"Wish Tracker";
+#  else
+		"wishes.txt";
+#  endif
+# endif
+
+void
+trackwish(wishstring)
+char* wishstring;
+{
+	char bigbuf[512];
+	FILE* fp;
+
+	fp = fopen_datafile(wish_tracker_file,"a+",LEVELPREFIX);
+	if (fp) {
+		Sprintf(bigbuf,"%s wished for %s (%d%s wish, T:%d)\n",
+				plname,wishstring,u.uconduct.wishes,
+				u.uconduct.wishes == 1 ? "st" : u.uconduct.wishes == 2 ? "nd" : 
+				u.uconduct.wishes == 3 ? "rd" : "th",moves);
+		fwrite(bigbuf,strlen(bigbuf),1,fp);
+		fclose(fp);
+	}
+}
+
+/* Handles generic announcements.  Cheats and uses the wishtracker file. */
+void makeannounce(announcement)
+char* announcement;
+{
+	FILE* fp;
+	fp = fopen_datafile(wish_tracker_file,"a+",LEVELPREFIX);
+	if (fp) {
+		fwrite(announcement,strlen(announcement),1,fp);
+		if (announcement[strlen(announcement)-1] != '\n') { fwrite("\n",1,1,fp); }
+		fclose(fp);
+	}
+
+}
+#endif
+
+#ifdef WHEREIS_FILE
+void
+touch_whereis()
+{
+	/* Write out our current level and branch to name.whereis
+	 *
+	 *	Could eventually bolt on all kinds of info, but this way
+	 *	at least something which wants to can scan for the games.
+	 *
+	 * For now this only works on Win32 and UNIX.  I'm too lazy
+	 * to sort out all the proper other-OS stuff.
+	 */
+
+	FILE* fp;
+	char whereis_file[255];
+	char whereis_work[255];
+
+#ifdef WIN32
+	Sprintf(whereis_file,"%s-%s.whereis",get_username(0),plname);
+#else
+	Sprintf(whereis_file,"%d-%s.whereis",(int)getuid(),plname);
+#endif
+	Sprintf(whereis_work,"%d,%d,%d,%d,%d,0,0,%s,%s,%s,%d,%d\n",
+			depth(&u.uz), u.uz.dnum, u.uhp, u.uhpmax, moves,
+			urole.name.m,urace.adj,u.mfemale ? "F" : "M",u.ualign.type + 2,
+			u.uhave.amulet ? 1 : 0);
+	fp = fopen_datafile(whereis_file,"w",LEVELPREFIX);
+	if (fp) {
+		fwrite(whereis_work,strlen(whereis_work),1,fp);
+		fclose(fp);
+	}
+
+}
+
+
+/* Changed over to write out where the player last was when they
+ * left the game; including possibly 'dead' :) */
+void
+delete_whereis()
+{
+	FILE* fp;
+	char whereis_file[255];
+	char whereis_work[255];
+#if defined (WIN32)
+	Sprintf(whereis_file,"%s-%s.whereis",get_username(0),plname);
+#else
+	Sprintf(whereis_file,"%d-%s.whereis",(int)getuid(),plname);
+#endif
+	Sprintf(whereis_work,"%d,%d,%d,%d,%d,%d,1,%s,%s,%s,%d,%d\n",
+			depth(&u.uz), u.uz.dnum, u.uhp, u.uhpmax, moves, 
+			u.uevent.ascended ? 2 : killer ? 1 : 0,
+			urole.name.m,urace.adj,u.mfemale ? "F" : "M",u.ualign.type + 2,
+			u.uhave.amulet ? 1 : 0);
+	fp = fopen_datafile(whereis_file,"w",LEVELPREFIX);
+	if (fp) {
+		fwrite(whereis_work,strlen(whereis_work),1,fp);
+		fclose(fp);
+	}
+}
+#endif /* WHEREIS_FILE */
+
 /* ----------  END LEVEL FILE HANDLING ----------- */
 
@@ -1244,7 +1353,10 @@
 static int nesting = 0;
 
-#ifdef NO_FILE_LINKS	/* implies UNIX */
+#if defined(NO_FILE_LINKS) || defined(USE_FCNTL) 	/* implies UNIX */
 static int lockfd;	/* for lock_file() to pass to unlock_file() */
 #endif
+#ifdef USE_FCNTL
+struct flock sflock; /* for unlocking, same as above */
+#endif
 
 #define HUP	if (!program_state.done_hup)
@@ -1284,5 +1396,4 @@
 }
 
-
 /* lock a file */
 boolean
@@ -1304,11 +1415,28 @@
 	}
 
+#ifndef USE_FCNTL
 	lockname = make_lockname(filename, locknambuf);
-	filename = fqname(filename, whichprefix, 0);
 #ifndef NO_FILE_LINKS	/* LOCKDIR should be subsumed by LOCKPREFIX */
 	lockname = fqname(lockname, LOCKPREFIX, 2);
 #endif
+#endif
+	filename = fqname(filename, whichprefix, 0);
+
+#ifdef USE_FCNTL
+	lockfd = open(filename,O_RDWR);
+	if (lockfd == -1) {
+		HUP raw_printf("Cannot open file %s. This is a program bug.",
+			filename);
+	}
+	sflock.l_type = F_WRLCK;
+	sflock.l_whence = SEEK_SET;
+	sflock.l_start = 0;
+	sflock.l_len = 0;
+#endif
 
 #if defined(UNIX) || defined(VMS)
+# ifdef USE_FCNTL
+	while (fcntl(lockfd,F_SETLK,&sflock) == -1) {
+# else 
 # ifdef NO_FILE_LINKS
 	while ((lockfd = open(lockname, O_RDWR|O_CREAT|O_EXCL, 0666)) == -1) {
@@ -1316,4 +1444,20 @@
 	while (link(filename, lockname) == -1) {
 # endif
+# endif 
+
+#ifdef USE_FCNTL
+		if (retryct--) {
+			HUP raw_printf(
+				"Waiting for release of fcntl lock on %s. (%d retries left).",
+				filename, retryct);
+			sleep(1);
+		} else {
+		    HUP (void) raw_print("I give up.  Sorry.");
+		    HUP raw_printf("Some other process has an unnatural grip on %s.",
+					filename);
+		    nesting--;
+		    return FALSE;
+		}
+#else
 	    register int errnosv = errno;
 
@@ -1361,9 +1505,9 @@
 		return FALSE;
 	    }
-
+#endif /* USE_FCNTL */
 	}
 #endif  /* UNIX || VMS */
 
-#if defined(AMIGA) || defined(WIN32) || defined(MSDOS)
+#if (defined(AMIGA) || defined(WIN32) || defined(MSDOS)) && !defined(USE_FCNTL)
 # ifdef AMIGA
 #define OPENFAILURE(fd) (!fd)
@@ -1419,4 +1563,11 @@
 
 	if (nesting == 1) {
+#ifdef USE_FCNTL
+		sflock.l_type = F_UNLCK;
+		if (fcntl(lockfd,F_SETLK,&sflock) == -1) {
+			HUP raw_printf("Can't remove fcntl lock on %s.", filename);
+			(void) close(lockfd);
+		}
+# else
 		lockname = make_lockname(filename, locknambuf);
 #ifndef NO_FILE_LINKS	/* LOCKDIR should be subsumed by LOCKPREFIX */
@@ -1438,4 +1589,5 @@
 		lockptr = 0;
 #endif /* AMIGA || WIN32 || MSDOS */
+#endif /* USE_FCNTL */
 	}
 
@@ -1450,4 +1602,19 @@
 const char *configfile =
 #ifdef UNIX
+			".sporkrc";
+#else
+# if defined(MAC) || defined(__BEOS__)
+			"SporkHack Defaults";
+# else
+#  if defined(MSDOS) || defined(WIN32)
+			"defaults.sh";
+#  else
+			"SporkHack.cnf";
+#  endif
+# endif
+#endif
+
+const char *oldconfigfile =
+#ifdef UNIX
 			".nethackrc";
 #else
@@ -1464,4 +1631,5 @@
 
 
+
 #ifdef MSDOS
 /* conflict with speed-dial under windows
@@ -1479,4 +1647,5 @@
 #endif
 
+
 STATIC_OVL FILE *
 fopen_config_file(filename)
@@ -1521,6 +1690,8 @@
 
 #if defined(MICRO) || defined(MAC) || defined(__BEOS__) || defined(WIN32)
-	if ((fp = fopenp(fqname(configfile, CONFIGPREFIX, 0), "r"))
-								!= (FILE *)0)
+	if ((fp = fopenp(fqname(configfile, CONFIGPREFIX, 0), "r")) != (FILE *)0)
+		return(fp);
+	/* try .nethackrc? */
+	else if ((fp = fopenp(fqname(oldconfigfile, CONFIGPREFIX, 0), "r")) != (FILE *)0)
 		return(fp);
 # ifdef MSDOS
@@ -1557,4 +1728,13 @@
 	if ((fp = fopenp(tmp_config, "r")) != (FILE *)0)
 		return(fp);
+	else {
+		/* try .nethackrc? */
+		if (!envp)
+			Strcpy(tmp_config, oldconfigfile);
+		else
+			Sprintf(tmp_config, "%s/%s", envp, oldconfigfile);
+		if ((fp = fopenp(tmp_config, "r")) != (FILE *)0)
+			return(fp);
+	}
 # if defined(__APPLE__)
 	/* try an alternative */
@@ -1795,8 +1975,16 @@
 	    (void) get_uchars(fp, buf, bufp, &iflags.bouldersym, TRUE,
 			      1, "BOULDER");
+	} else if (match_varname(buf, "MENUCOLOR", 9)) {
+#ifdef MENU_COLOR
+	    (void) add_menu_coloring(bufp);
+#endif
 	} else if (match_varname(buf, "GRAPHICS", 4)) {
 	    len = get_uchars(fp, buf, bufp, translate, FALSE,
 			     MAXPCHARS, "GRAPHICS");
 	    assign_graphics(translate, len, MAXPCHARS, 0);
+#if defined(STATUS_COLORS) && defined(TEXTCOLOR)
+	} else if (match_varname(buf, "STATUSCOLOR", 11)) {
+	    (void) parse_status_color_options(bufp);
+#endif
 	} else if (match_varname(buf, "DUNGEON", 4)) {
 	    len = get_uchars(fp, buf, bufp, translate, FALSE,
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/src/fountain.c nethack/src/fountain.c
--- nh_orig/src/fountain.c	2003-12-07 18:39:13.000000000 -0500
+++ nethack/src/fountain.c	2010-05-13 09:22:21.972714813 -0400
@@ -255,5 +255,5 @@
 
 			pline_The("water is contaminated!");
-			if (Poison_resistance) {
+			if (how_resistant(POISON_RES) == 100) {
 			   pline(
 			      "Perhaps it is runoff from the nearby %s farm.",
@@ -263,6 +263,6 @@
 			   break;
 			}
-			losestr(rn1(4,3));
-			losehp(rnd(10),"contaminated water", KILLED_BY);
+			losestr(resist_reduce(rn1(4,3),POISON_RES));
+			losehp(resist_reduce(rnd(10),POISON_RES),"contaminated water", KILLED_BY);
 			exercise(A_CON, FALSE);
 			break;
@@ -301,5 +301,5 @@
 			   pline("But it disappears.");
 			}
-			HSee_invisible |= FROMOUTSIDE;
+			incr_itimeout(&HSee_invisible, (long)rn1(100, 50));
 			newsym(u.ux,u.uy);
 			exercise(A_WIS, TRUE);
@@ -330,5 +330,5 @@
 			for(mtmp = fmon; mtmp; mtmp = mtmp->nmon)
 			    if(!DEADMONSTER(mtmp))
-				monflee(mtmp, 0, FALSE, FALSE);
+				monflee(mtmp, 0, FALSE, canseemon(mtmp) ? TRUE : FALSE);
 			}
 			break;
@@ -364,5 +364,5 @@
 	    && !exist_artifact(LONG_SWORD, artiname(ART_EXCALIBUR))) {
 
-		if (u.ualign.type != A_LAWFUL) {
+		if (u.ualign.type != A_LAWFUL || !Role_if(PM_KNIGHT)) {
 			/* Ha!  Trying to cheat her. */
 			pline("A freezing mist rises from the water and envelopes the sword.");
@@ -380,6 +380,5 @@
 			discover_artifact(ART_EXCALIBUR);
 			bless(obj);
-			obj->oeroded = obj->oeroded2 = 0;
-			obj->oerodeproof = TRUE;
+			set_erodeproof(obj);
 			exercise(A_WIS, TRUE);
 		}
@@ -523,7 +522,9 @@
 			break;
 		case 2: You("take a sip of scalding hot water.");
-			if (Fire_resistance)
+			if (how_resistant(FIRE_RES) == 100) {
 				pline("It seems quite tasty.");
-			else losehp(rnd(6), "sipping boiling water", KILLED_BY);
+				monstseesu(M_SEEN_FIRE);
+			}
+			else losehp(resist_reduce(rnd(6),FIRE_RES), "sipping boiling water", KILLED_BY);
 			break;
 		case 3: if (mvitals[PM_SEWER_RAT].mvflags & G_GONE)
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/src/hack.c nethack/src/hack.c
--- nh_orig/src/hack.c	2003-12-07 18:39:13.000000000 -0500
+++ nethack/src/hack.c	2009-11-22 07:40:06.206272750 -0500
@@ -73,5 +73,5 @@
 	rx = u.ux + 2 * u.dx;	/* boulder destination position */
 	ry = u.uy + 2 * u.dy;
-	nomul(0);
+	nomul(0, 0);
 	if (Levitation || Is_airlevel(&u.uz)) {
 	    if (Blind) feel_location(sx, sy);
@@ -317,4 +317,5 @@
     struct obj *boulder = sobj_at(BOULDER,x,y);
     const char *digtxt = (char *)0, *dmgtxt = (char *)0;
+	 boolean getcoal = FALSE;
 
     if (digging.down)		/* not continuing previous dig (w/ pick-axe) */
@@ -323,6 +324,7 @@
     if (!boulder && IS_ROCK(lev->typ) && !may_dig(x,y)) {
 	You("hurt your teeth on the %s.",
-	    IS_TREE(lev->typ) ? "tree" : "hard stone");
-	nomul(0);
+			/* ternary abuse! */
+	    IS_TREE(lev->typ) ? christmas() ? "christmas tree" : "tree" : "hard stone");
+	nomul(0, 0);
 	return 1;
     } else if (digging.pos.x != x || digging.pos.y != y ||
@@ -340,5 +342,6 @@
 	    (boulder || IS_TREE(lev->typ)) ? "on a" : "a hole in the",
 	    boulder ? "boulder" :
-	    IS_TREE(lev->typ) ? "tree" : IS_ROCK(lev->typ) ? "rock" : "door");
+	    IS_TREE(lev->typ) ? christmas() ? "christmas tree" : "tree" : 
+			IS_ROCK(lev->typ) ? "rock" : "door");
 	watch_dig((struct monst *)0, x, y, FALSE);
 	return 1;
@@ -348,5 +351,5 @@
 		digging.chew ? "continue" : "begin",
 		boulder ? "boulder" :
-		IS_TREE(lev->typ) ? "tree" :
+		IS_TREE(lev->typ) ? christmas() ? "christmas tree" : "tree" :
 		IS_ROCK(lev->typ) ? "rock" : "door");
 	digging.chew = TRUE;
@@ -392,5 +395,10 @@
 	}
     } else if (IS_TREE(lev->typ)) {
+		 if (christmas()) {
+			digtxt = "chew through the christmas tree.";
+			getcoal = TRUE;
+		 } else {
 	digtxt = "chew through the tree.";
+		 }
 	lev->typ = ROOM;
     } else if (lev->typ == SDOOR) {
@@ -425,4 +433,5 @@
     newsym(x, y);
     if (digtxt) You(digtxt);	/* after newsym */
+	 if (getcoal) get_coal();
     if (dmgtxt) pay_for_damage(dmgtxt, FALSE);
     (void) memset((genericptr_t)&digging, 0, sizeof digging);
@@ -720,5 +729,5 @@
 	    u.dx = u.tx-u.ux;
 	    u.dy = u.ty-u.uy;
-	    nomul(0);
+	    nomul(0, 0);
 	    iflags.travelcc.x = iflags.travelcc.y = -1;
 	    return TRUE;
@@ -786,5 +795,5 @@
 				u.dy = y-uy;
 				if (x == u.tx && y == u.ty) {
-				    nomul(0);
+				    nomul(0, 0);
 				    /* reset run so domove run checks work */
 				    flags.run = 8;
@@ -856,5 +865,5 @@
     u.dx = 0;
     u.dy = 0;
-    nomul(0);
+    nomul(0, 0);
     return FALSE;
 }
@@ -892,5 +901,5 @@
 	    } else
 		You("collapse under your load.");
-	    nomul(0);
+	    nomul(0, 0);
 	    return;
 	}
@@ -926,7 +935,9 @@
 			    || resists_cold(&youmonst) || Flying
 			    || is_floater(youmonst.data) || is_clinger(youmonst.data)
-			    || is_whirly(youmonst.data))
+			    || is_whirly(youmonst.data) ||
+				 (uarm && (uarm->otyp == WHITE_DRAGON_SCALE_MAIL || 
+							  uarm->otyp == WHITE_DRAGON_SCALES)))
 			on_ice = FALSE;
-		    else if (!rn2(Cold_resistance ? 3 : 2)) {
+		    else if (!rn2((how_resistant(COLD_RES) > 50) ? 3 : 2)) {	
 			HFumbling |= FROMOUTSIDE;
 			HFumbling &= ~TIMEOUT;
@@ -944,5 +955,5 @@
 			do {
 				if(tries++ > 50) {
-					nomul(0);
+					nomul(0, 0);
 					return;
 				}
@@ -956,5 +967,5 @@
 			water_friction();
 			if (!u.dx && !u.dy) {
-				nomul(0);
+				nomul(0, 0);
 				return;
 			}
@@ -963,5 +974,5 @@
 		}
 		if(!isok(x, y)) {
-			nomul(0);
+			nomul(0, 0);
 			return;
 		}
@@ -971,9 +982,9 @@
 		     (is_pool(x, y) || is_lava(x, y)) && levl[x][y].seenv)) {
 			if(flags.run >= 2) {
-				nomul(0);
+				nomul(0, 0);
 				flags.move = 0;
 				return;
 			} else
-				nomul(0);
+				nomul(0, 0);
 		}
 
@@ -1016,5 +1027,5 @@
 				goto pull_free;
 			    You("cannot escape from %s!", mon_nam(u.ustuck));
-			    nomul(0);
+			    nomul(0, 0);
 			    return;
 			}
@@ -1032,5 +1043,5 @@
 			       Protection_from_shape_changers)) ||
 			     sensemon(mtmp))) {
-				nomul(0);
+				nomul(0, 0);
 				flags.move = 0;
 				return;
@@ -1047,5 +1058,5 @@
 	/* attack monster */
 	if(mtmp) {
-	    nomul(0);
+	    nomul(0, 0);
 	    /* only attack if we know it's there */
 	    /* or if we used the 'F' command to fight blindly */
@@ -1109,5 +1120,5 @@
 		unmap_object(x, y); /* known empty -- remove 'I' if present */
 		newsym(x, y);
-		nomul(0);
+		nomul(0, 0);
 		if (expl) {
 		    u.mh = -1;		/* dead in the current form */
@@ -1124,5 +1135,5 @@
 	if (u.usteed && !u.usteed->mcanmove && (u.dx || u.dy)) {
 		pline("%s won't move!", upstart(y_monnam(u.usteed)));
-		nomul(0);
+		nomul(0, 0);
 		return;
 	} else
@@ -1132,5 +1143,5 @@
 		    Levitation || Is_airlevel(&u.uz) || Is_waterlevel(&u.uz) ?
 		    "in place" : "to the ground");
-		nomul(0);
+		nomul(0, 0);
 		return;
 	}
@@ -1255,5 +1266,5 @@
 	if (!test_move(u.ux, u.uy, x-u.ux, y-u.uy, DO_MOVE)) {
 	    flags.move = 0;
-	    nomul(0);
+	    nomul(0, 0);
 	    return;
 	}
@@ -1342,5 +1353,5 @@
 		    /* there's already been a trap message, reinforce it */
 		    abuse_dog(mtmp);
-		    adjalign(-3);
+			 minor_sin();
 		    break;
 		case 2:
@@ -1351,5 +1362,5 @@
 			You_feel("guilty about losing your pet like this.");
 			u.ugangr++;
-			adjalign(-15);
+				major_sin();
 		    }
 
@@ -1371,5 +1382,5 @@
 		if (IS_DOOR(tmpr->typ) || IS_ROCK(tmpr->typ) ||
 			IS_FURNITURE(tmpr->typ))
-		    nomul(0);
+		    nomul(0, 0);
 	}
 
@@ -1404,4 +1415,15 @@
 	    move_bc(0,bc_control,ballx,bally,chainx,chainy);
 
+	/* Special effects of WDSM; don't spam the player unless he's stepped onto
+	 * water from something that wasn't water/ice already */
+	if (is_pool(u.ux,u.uy) && !Levitation && !Flying && uarm && 
+			(uarm->otyp == WHITE_DRAGON_SCALE_MAIL || uarm->otyp == WHITE_DRAGON_SCALES)) {
+		levl[u.ux][u.uy].typ = ICE;
+      if (!is_pool(u.ux0,u.uy0) && !is_ice(u.ux0,u.uy0)) {
+			pline("The pool crackles and freezes under your feet.");
+		}
+		bury_objs(u.ux,u.uy);
+	}
+
 	spoteffects(TRUE);
 
@@ -1409,5 +1431,5 @@
 	/* must come after we finished picking up, in spoteffects() */
 	if (cause_delay) {
-	    nomul(-2);
+	    nomul(-2, "dragging an iron ball");
 	    nomovemsg = "";
 	}
@@ -1437,5 +1459,5 @@
 	    struct obj *otmp = carrying(CANDELABRUM_OF_INVOCATION);
 
-	    nomul(0);		/* stop running or travelling */
+	    nomul(0, 0);		/* stop running or travelling */
 #ifdef STEED
 	    if (u.usteed) Sprintf(buf, "beneath %s", y_monnam(u.usteed));
@@ -1496,5 +1518,5 @@
 #ifdef STEED
 		if (u.usteed && !is_flyer(u.usteed->data) &&
-			!is_floater(u.usteed->data) &&
+			!is_floater(u.usteed->data) && !is_flying(u.usteed) &&
 			!is_clinger(u.usteed->data)) {
 		    dismount_steed(Underwater ?
@@ -1925,5 +1947,5 @@
     /* they polymorphed while in the middle of a long move. */
     if (u.umonnum == PM_GRID_BUG && u.dx && u.dy) {
-	nomul(0);
+	nomul(0, 0);
 	return;
     }
@@ -2002,5 +2024,5 @@
 	}
 stop:
-	nomul(0);
+	nomul(0, 0);
 	return;
     } /* end for loops */
@@ -2065,6 +2087,7 @@
 
 void
-nomul(nval)
+nomul(nval, txt)
 	register int nval;
+const char *txt;
 {
 	if(multi < nval) return;	/* This is a bug fix by ab@unido */
@@ -2072,4 +2095,8 @@
 	u.usleep = 0;
 	multi = nval;
+	if (txt && txt[0])
+	  (void) strncpy(multi_txt, txt, BUFSZ);
+	else
+	  (void) memset(multi_txt, 0, BUFSZ);
 	flags.travel = iflags.travel1 = flags.mv = flags.run = 0;
 }
@@ -2081,4 +2108,5 @@
 {
 	multi = 0;	/* caller will usually have done this already */
+	(void) memset(multi_txt, 0, BUFSZ);
 	if (msg_override) nomovemsg = msg_override;
 	else if (!nomovemsg) nomovemsg = You_can_move_again;
@@ -2156,4 +2184,82 @@
 
 int
+gainmaxhp(desired)
+int desired;
+{
+	int softcap,hardcap,i;
+	float scaled,overpct;
+	boolean pastcap;
+	int conbonus;
+
+	/* handle everything cleanly; the current-hp checks are in case we get called
+	 * to actually lose max HP, which might be desirable in some places */
+	if (Upolyd) {
+		/* Don't need to worry about capping anything with regard to this,
+		 * since it'll generally be temporary anyway.  Someone who slaps on
+		 * the amulet of unchanging and then busts out the HP abuse, well,
+		 * very clever, congratulations ;) */
+		u.mhmax += desired;
+		if (u.mh > u.mhmax) { u.mh = u.mhmax; }
+		return u.mhmax;
+	} else if (desired < 0) {
+		/* no need to do silly stuff if we're losing maxhp */
+		u.uhpmax += desired;
+		if (u.uhp > u.uhpmax) { u.uhp = u.uhpmax; }
+		return u.uhpmax;
+	}
+
+	/* Magical methods of increasing HP should certainly allow one to step
+	 * outside of the normal range gained by levels... but perhaps not 
+	 * _ridiculously_ so, to the point of 500+ HP or better on any character.
+	 *
+	 * So implement some slide based on your role/race; you can boost it
+	 * beyond a certain point that's appropriate for your level, but the
+	 * effectiveness of those gains will slowly decrease until you hit
+	 * an effective hard cap at 150% of possible natural maxHP at L30.  */
+	
+	/* first determine the maximum natural amounts this character could have */
+	conbonus = ACURR(A_CON) - 15;
+	if (conbonus < 0) conbonus = 0; 
+	if (conbonus > 4) conbonus = 4;
+	hardcap = softcap = urole.hpadv.infix + urole.hpadv.inrnd + 
+								urace.hpadv.infix + urace.hpadv.inrnd;
+
+	for (i=1;i<=30;i++) {
+		if (i <= u.ulevel) {
+			softcap += (i < urole.xlev) ? 
+				(urole.hpadv.lofix + urole.hpadv.lornd + urace.hpadv.lofix + urace.hpadv.lornd) :
+				(urole.hpadv.hifix + urole.hpadv.hirnd + urace.hpadv.hifix + urace.hpadv.hirnd);
+			softcap += conbonus;
+		}
+		hardcap += (i < urole.xlev) ?
+			(urole.hpadv.lofix + urole.hpadv.lornd + urace.hpadv.lofix + urace.hpadv.lornd) :
+			(urole.hpadv.hifix + urole.hpadv.hirnd + urace.hpadv.hifix + urace.hpadv.hirnd);
+		hardcap += conbonus;
+	}
+
+	/* paranoia */
+	if (softcap <= 0) { impossible("HP cap suspiciously low?"); return u.uhpmax; }
+
+	/* Reduce gains related to how far you are over the top.
+	 * If you're still below the maximum hard cap, you can be up to 200%
+	 * better than you should be at your level; otherwise, don't go more
+	 * than 150% past where you should be. */
+	pastcap = u.uhpmax >= hardcap;
+	overpct = (float)u.uhpmax / (float)softcap - 1;
+	if (overpct >= 0 && overpct < (pastcap ? 0.5 : 1.0)) { 
+		scaled = (float)desired * (1 - overpct * (pastcap ? 2 : 1));	
+		u.uhpmax += (int)scaled;
+		if (scaled - (int)scaled >= .5) { u.uhpmax++; } /* round up */
+	} else if (overpct < 0) {
+		/* if you haven't even hit the soft cap, you get the full bonus */
+		u.uhpmax += desired; 
+	} 
+
+	if (u.uhp > u.uhpmax) { u.uhp = u.uhpmax; }
+	return u.uhpmax;
+
+}
+
+int
 weight_cap()
 {
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/src/hacklib.c nethack/src/hacklib.c
--- nh_orig/src/hacklib.c	2003-12-07 18:39:13.000000000 -0500
+++ nethack/src/hacklib.c	2010-04-29 10:53:23.927730767 -0400
@@ -6,4 +6,7 @@
 /* We could include only config.h, except for the overlay definitions... */
 #include "hack.h"
+#ifdef UNIX
+#include <sys/times.h>
+#endif
 /*=
     Assorted 'small' utility routines.	They're virtually independent of
@@ -18,4 +21,6 @@
 	char *		upstart		(char *)
 	char *		mungspaces	(char *)
+	char *		stripctrl	(char *)
+	char *		trim		(char *)
 	char *		eos		(char *)
 	char *		strkitten	(char *,char)
@@ -121,4 +126,33 @@
 }
 
+char *
+stripctrl(bp) /* replace non-alphanum characters with spaces */
+     char *bp;
+{
+    register char *p;
+    for (p = bp; *p != '\0'; p++)
+	if (iscntrl(*p)) *p = ' ';
+    return bp;
+}
+
+/* trim leading and trailing spaces, in place */
+char *
+trim(bp)
+     char *bp;
+{
+    register char c, *p, *p2;
+    boolean was_space = TRUE;
+
+    for (p = p2 = bp; (c = *p) != '\0'; p++) {
+	if (!isspace(c)) {
+	    *p2++ = c;
+	    was_space = FALSE;
+	} else if (!was_space) *p2++ = c;
+    }
+    p = eos(bp);
+    while (--p >= bp && isspace(*p)) *p = '\0';
+    return bp;
+}
+
 #endif /* OVLB */
 
@@ -461,9 +495,22 @@
 setrandom()
 {
+	/* This isn't terribly portable at the moment, but it will compile
+	 * on both foonix and MinGW; it isn't the best situation, since someone
+	 * on Win32 should be able to predict process IDs with little effort, but
+	 * it's more of a "problem" on public servers anywa -- which are foonix. */
+	unsigned long seed;
+#ifdef UNIX
+	struct tms buf;
+	seed = (unsigned long)times(&buf) * getpid();
+#else
+	seed = (unsigned long)time((time_t*)0) * getpid();
+#endif
+
+
 	/* the types are different enough here that sweeping the different
 	 * routine names into one via #defines is even more confusing
 	 */
 #ifdef RANDOM	/* srandom() from sys/share/random.c */
-	srandom((unsigned int) time((time_t *)0));
+	srandom(seed);
 #else
 # if defined(__APPLE__) || defined(BSD) || defined(LINUX) || defined(ULTRIX) || defined(CYGWIN32) /* system srandom() */
@@ -472,13 +519,13 @@
 	(void)
 #   endif
-		srandom((int) time((long *)0));
+		srandom(seed);
 #  else
-		srandom((int) time((time_t *)0));
+		srandom(seed);
 #  endif
 # else
 #  ifdef UNIX	/* system srand48() */
-	srand48((long) time((time_t *)0));
+	srand48(seed);
 #  else		/* poor quality system routine */
-	srand((int) time((time_t *)0));
+	srand(seed);
 #  endif
 # endif
@@ -598,4 +645,12 @@
 }
 
+boolean
+christmas()
+{
+	struct tm* lt = getlt();
+	return (boolean)(lt->tm_mon == 11 && (lt->tm_mday > 15 && lt->tm_mday < 26));
+	/* 'twas the week(ish) before christmas, and all through the dungeon... */
+}
+
 int
 night()
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/src/invent.c nethack/src/invent.c
--- nh_orig/src/invent.c	2003-12-07 18:39:13.000000000 -0500
+++ nethack/src/invent.c	2010-08-29 07:52:40.525707081 -0400
@@ -20,5 +20,10 @@
 STATIC_PTR int FDECL(ckunpaid,(struct obj *));
 STATIC_PTR int FDECL(ckvalidcat,(struct obj *));
+#ifdef DUMP_LOG
+static char FDECL(display_pickinv,
+		 (const char *,BOOLEAN_P, long *, BOOLEAN_P, BOOLEAN_P));
+#else
 static char FDECL(display_pickinv, (const char *,BOOLEAN_P, long *));
+#endif /* DUMP_LOG */
 #ifdef OVLB
 STATIC_DCL boolean FDECL(this_type_only, (struct obj *));
@@ -245,4 +250,5 @@
 struct obj *obj;
 {
+	char buf[512];
 	if (obj->oclass == COIN_CLASS) {
 #ifndef GOLDOBJ
@@ -254,13 +260,33 @@
 		if (u.uhave.amulet) impossible("already have amulet?");
 		u.uhave.amulet = 1;
+#ifdef RECORD_ACHIEVE
+		achieve.get_amulet = 1;
+#endif
+#ifdef WISH_TRACKER
+		if (Is_sanctum(&u.uz)) {
+			Sprintf(buf,
+				"%s picked up the Amulet of Yendor in Moloch's Sanctum on T:%d", 
+				plname,moves);
+			makeannounce(buf);
+		}
+#endif
 	} else if (obj->otyp == CANDELABRUM_OF_INVOCATION) {
 		if (u.uhave.menorah) impossible("already have candelabrum?");
 		u.uhave.menorah = 1;
+#ifdef RECORD_ACHIEVE
+                achieve.get_candelabrum = 1;
+#endif
 	} else if (obj->otyp == BELL_OF_OPENING) {
 		if (u.uhave.bell) impossible("already have silver bell?");
 		u.uhave.bell = 1;
+#ifdef RECORD_ACHIEVE
+                achieve.get_bell = 1;
+#endif
 	} else if (obj->otyp == SPE_BOOK_OF_THE_DEAD) {
 		if (u.uhave.book) impossible("already have the book?");
 		u.uhave.book = 1;
+#ifdef RECORD_ACHIEVE
+                achieve.get_book = 1;
+#endif
 	} else if (obj->oartifact) {
 		if (is_quest_artifact(obj)) {
@@ -272,4 +298,17 @@
 		set_artifact_intrinsic(obj, 1, W_ART);
 	}
+
+#ifdef RECORD_ACHIEVE
+        if(obj->otyp == LUCKSTONE && obj->record_achieve_special) {
+                achieve.get_luckstone = 1;
+                obj->record_achieve_special = 0;
+        } else if((obj->otyp == AMULET_OF_REFLECTION ||
+                   obj->otyp == BAG_OF_HOLDING) &&
+                  obj->record_achieve_special) {
+                achieve.finish_sokoban = 1;
+                obj->record_achieve_special = 0;
+        }
+#endif /* RECORD_ACHIEVE */
+
 }
 
@@ -917,7 +956,14 @@
 		if ((!strcmp(word, "read") &&
 		    (otmp->otyp == FORTUNE_COOKIE
+		     || otmp->otyp == TIN
+		     || otmp->otyp == CAN_OF_GREASE
+		     || otmp->otyp == CANDY_BAR
+		     || otmp->otyp == ALCHEMY_SMOCK
 #ifdef TOURIST
 			|| otmp->otyp == T_SHIRT
+		     || otmp->otyp == CREDIT_CARD
 #endif
+		     || (OBJ_DESCR(objects[otmp->otyp]) &&
+			 !strncmp(OBJ_DESCR(objects[otmp->otyp]), "runed", 5))
 		    )))
 			allowall = TRUE;
@@ -1018,5 +1064,9 @@
 			allowed_choices = altlets;
 		    ilet = display_pickinv(allowed_choices, TRUE,
-					   allowcnt ? &ctmp : (long *)0);
+					   allowcnt ? &ctmp : (long *)0
+#ifdef DUMP_LOG
+					   , FALSE, TRUE
+#endif
+					   );
 		    if(!ilet) continue;
 		    if (allowcnt && ctmp >= 0) {
@@ -1164,5 +1214,5 @@
 			W_SADDLE |
 #endif
-			W_WEP | W_SWAPWEP | W_QUIVER))));
+			W_WEP | W_SWAPWEP | W_QUIVER | W_LAUNCHER))));
 }
 
@@ -1190,6 +1240,6 @@
 #endif
 	char sym, *ip, olets[MAXOCLASSES+5], ilets[MAXOCLASSES+5];
-	char extra_removeables[3+1];	/* uwep,uswapwep,uquiver */
-	char buf[BUFSZ], qbuf[QBUFSZ];
+	char extra_removeables[4+1];	/* uwep,uswapwep,uquiver,ulauncher */
+	char buf[BUFSZ] = "", qbuf[QBUFSZ];
 
 	if (resultflags) *resultflags = 0;
@@ -1259,4 +1309,5 @@
 	    if (uswapwep) (void)strkitten(extra_removeables, uswapwep->oclass);
 	    if (uquiver) (void)strkitten(extra_removeables, uquiver->oclass);
+	    if (ulauncher) (void)strkitten(extra_removeables, ulauncher->oclass);
 	}
 
@@ -1276,5 +1327,5 @@
 		    return 0;
 		} else if (oc_of_sym == WEAPON_CLASS &&
-			!uwep && !uswapwep && !uquiver) {
+			!uwep && !uswapwep && !uquiver && !ulauncher) {
 		    You("are not wielding anything.");
 		    return 0;
@@ -1690,4 +1741,13 @@
  * any count returned from the menu selection is placed here.
  */
+#ifdef DUMP_LOG
+static char
+display_pickinv(lets, want_reply, out_cnt, want_dump, want_disp)
+register const char *lets;
+boolean want_reply;
+long* out_cnt;
+boolean want_dump;
+boolean want_disp;
+#else
 static char
 display_pickinv(lets, want_reply, out_cnt)
@@ -1695,6 +1755,11 @@
 boolean want_reply;
 long* out_cnt;
+#endif
 {
 	struct obj *otmp;
+#ifdef SORTLOOT
+	struct obj **oarray;
+	int i, j;
+#endif
 	char ilet, ret;
 	char *invlet = flags.inv_order;
@@ -1705,4 +1770,7 @@
 	menu_item *selected;
 
+#ifdef DUMP_LOG
+	if (want_disp) {
+#endif
 	/* overriden by global flag */
 	if (flags.perm_invent) {
@@ -1714,4 +1782,9 @@
 	    win = WIN_INVEN;
 
+#ifdef DUMP_LOG
+	}
+	if (want_dump)   dump("", "Your inventory");
+#endif
+
 	/*
 	Exit early if no inventory -- but keep going if we are doing
@@ -1726,4 +1799,7 @@
 	*/
 	if (!invent && !(flags.perm_invent && !lets && !want_reply)) {
+#ifdef DUMP_LOG
+	  if (want_disp) {
+#endif
 #ifndef GOLDOBJ
 	    pline("Not carrying anything%s.", u.ugold ? " except gold" : "");
@@ -1731,4 +1807,14 @@
 	    pline("Not carrying anything.");
 #endif
+#ifdef DUMP_LOG
+	  }
+	  if (want_dump) {
+#ifdef GOLDOBJ
+	    dump("  ", "Not carrying anything");
+#else
+	    dump("  Not carrying anything", u.ugold ? " except gold." : ".");
+#endif
+	  }
+#endif
 	    return 0;
 	}
@@ -1744,8 +1830,20 @@
 	    for (otmp = invent; otmp; otmp = otmp->nobj) {
 		if (otmp->invlet == lets[0]) {
+#ifdef DUMP_LOG
+		  if (want_disp) {
+#endif
 		    ret = message_menu(lets[0],
 			  want_reply ? PICK_ONE : PICK_NONE,
 			  xprname(otmp, (char *)0, lets[0], TRUE, 0L, 0L));
 		    if (out_cnt) *out_cnt = -1L;	/* select all */
+#ifdef DUMP_LOG
+		  }
+		  if (want_dump) {
+		    char letbuf[7];
+		    sprintf(letbuf, "  %c - ", lets[0]);
+		    dump(letbuf,
+			 xprname(otmp, (char *)0, lets[0], TRUE, 0L, 0L));
+		  }
+#endif
 		    break;
 		}
@@ -1754,8 +1852,74 @@
 	}
 
+#ifdef SORTLOOT
+	/* count the number of items */
+	for (n = 0, otmp = invent; otmp; otmp = otmp->nobj)
+	  if(!lets || !*lets || index(lets, otmp->invlet)) n++;
+
+	/* Make a temporary array to store the objects sorted */
+	oarray = (struct obj **)alloc(n*sizeof(struct obj*));
+
+	/* Add objects to the array */
+	i = 0;
+	for(otmp = invent; otmp; otmp = otmp->nobj)
+	  if(!lets || !*lets || index(lets, otmp->invlet)) {
+	    if (iflags.sortloot == 'f') {
+	      /* Insert object at correct index */
+	      for (j = i; j; j--) {
+		if (strcmpi(cxname2(otmp), cxname2(oarray[j-1]))>0) break;
+		oarray[j] = oarray[j-1];
+	      }
+	      oarray[j] = otmp;
+	      i++;
+	    } else {
+	      /* Just add it to the array */
+	      oarray[i++] = otmp;
+	    }
+	  }
+#endif /* SORTLOOT */
+
+#ifdef DUMP_LOG
+	if (want_disp)
+#endif
+
 	start_menu(win);
 nextclass:
 	classcount = 0;
 	any.a_void = 0;		/* set all bits to zero */
+#ifdef SORTLOOT
+	for(i = 0; i < n; i++) {
+	  otmp = oarray[i];
+	  ilet = otmp->invlet;
+	  if (!flags.sortpack || otmp->oclass == *invlet) {
+	    if (flags.sortpack && !classcount) {
+	      any.a_void = 0;             /* zero */
+#ifdef DUMP_LOG
+			if (want_disp)
+#endif
+	      add_menu(win, NO_GLYPH, &any, 0, 0, iflags.menu_headings,
+		       let_to_name(*invlet, FALSE, FALSE), MENU_UNSELECTED);
+#ifdef DUMP_LOG
+	      if (want_dump)
+		  dump("  ", let_to_name(*invlet, FALSE, FALSE));
+#endif
+	      classcount++;
+	    }
+	    any.a_char = ilet;
+#ifdef DUMP_LOG
+			if (want_disp)
+#endif
+	    add_menu(win, obj_to_glyph(otmp),
+		     &any, ilet, 0, ATR_NONE, doname(otmp),
+		     MENU_UNSELECTED);
+#ifdef DUMP_LOG
+	    if (want_dump) {
+	      char letbuf[7];
+	      sprintf(letbuf, "  %c - ", ilet);
+	      dump(letbuf, doname(otmp));
+	    }
+#endif
+	  }
+	}
+#else /* SORTLOOT */
 	for(otmp = invent; otmp; otmp = otmp->nobj) {
 		ilet = otmp->invlet;
@@ -1764,9 +1928,22 @@
 			    if (flags.sortpack && !classcount) {
 				any.a_void = 0;		/* zero */
+#ifdef DUMP_LOG
+				if (want_dump)
+				    dump("  ", let_to_name(*invlet, FALSE, FALSE));
+				if (want_disp)
+#endif
 				add_menu(win, NO_GLYPH, &any, 0, 0, iflags.menu_headings,
-				    let_to_name(*invlet, FALSE), MENU_UNSELECTED);
+					 let_to_name(*invlet, FALSE, FALSE), MENU_UNSELECTED);
 				classcount++;
 			    }
 			    any.a_char = ilet;
+#ifdef DUMP_LOG
+			    if (want_dump) {
+			      char letbuf[7];
+			      sprintf(letbuf, "  %c - ", ilet);
+			      dump(letbuf, doname(otmp));
+			    }
+			    if (want_disp)
+#endif
 			    add_menu(win, obj_to_glyph(otmp),
 					&any, ilet, 0, ATR_NONE, doname(otmp),
@@ -1775,4 +1952,5 @@
 		}
 	}
+#endif /* SORTLOOT */
 	if (flags.sortpack) {
 		if (*++invlet) goto nextclass;
@@ -1784,4 +1962,10 @@
 #endif
 	}
+#ifdef SORTLOOT
+	free(oarray);
+#endif
+#ifdef DUMP_LOG
+	if (want_disp) {
+#endif
 	end_menu(win, (char *) 0);
 
@@ -1793,4 +1977,8 @@
 	} else
 	    ret = !n ? '\0' : '\033';	/* cancelled */
+#ifdef DUMP_LOG
+	} /* want_disp */
+	if (want_dump)  dump("", "");
+#endif
 
 	return ret;
@@ -1809,7 +1997,22 @@
 boolean want_reply;
 {
-	return display_pickinv(lets, want_reply, (long *)0);
+	return display_pickinv(lets, want_reply, (long *)0
+#ifdef DUMP_LOG
+			       , FALSE , TRUE
+#endif
+	);
 }
 
+#ifdef DUMP_LOG
+/* See display_inventory. This is the same thing WITH dumpfile creation */
+char
+dump_inventory(lets, want_reply, want_disp)
+register const char *lets;
+boolean want_reply, want_disp;
+{
+  return display_pickinv(lets, want_reply, (long *)0, TRUE, want_disp);
+}
+#endif
+
 /*
  * Returns the number of unpaid items within the given list.  This includes
@@ -1910,5 +2113,5 @@
 		if (!flags.sortpack || otmp->oclass == *invlet) {
 		    if (flags.sortpack && !classcount) {
-			putstr(win, 0, let_to_name(*invlet, TRUE));
+			putstr(win, 0, let_to_name(*invlet, TRUE, FALSE));
 			classcount++;
 		    }
@@ -1930,5 +2133,5 @@
 	/* something unpaid is contained */
 	if (flags.sortpack)
-	    putstr(win, 0, let_to_name(CONTAINED_SYM, TRUE));
+	    putstr(win, 0, let_to_name(CONTAINED_SYM, TRUE, FALSE));
 	/*
 	 * Search through the container objects in the inventory for
@@ -2106,6 +2309,4 @@
 	} else if (IS_FOUNTAIN(ltyp))
 	    cmap = S_fountain;				/* "fountain" */
-	else if (IS_THRONE(ltyp))
-	    cmap = S_throne;				/* "opulent throne" */
 	else if (is_lava(x,y))
 	    cmap = S_lava;				/* "molten lava" */
@@ -2236,5 +2437,5 @@
 	    if (otmp->oinvis && !See_invisible) verb = "feel";
 #endif
-	    You("%s here %s.", verb, doname(otmp));
+	    You("%s here %s.", verb, doname_with_price(otmp));
 	    if (otmp->otyp == CORPSE) feel_cockatrice(otmp, FALSE);
 	} else {
@@ -2256,5 +2457,5 @@
 			break;
 		}
-		putstr(tmpwin, 0, doname(otmp));
+		putstr(tmpwin, 0, doname_with_price(otmp));
 	    }
 	    display_nhwindow(tmpwin, TRUE);
@@ -2590,8 +2791,10 @@
 
 char *
-let_to_name(let,unpaid)
+let_to_name(let,unpaid,showsym)
 char let;
 boolean unpaid;
+boolean showsym;
 {
+	static const char *ocsymformat = "%s('%c')";
 	const char *class_name;
 	const char *pos;
@@ -2606,5 +2809,6 @@
 	    class_name = names[0];
 
-	len = strlen(class_name) + (unpaid ? sizeof "unpaid_" : sizeof "");
+	len = strlen(class_name) + (unpaid ? sizeof "unpaid_" : sizeof "") +
+	    ((oclass && showsym) ? strlen(ocsymformat) : 0);
 	if (len > invbufsiz) {
 	    if (invbuf) free((genericptr_t)invbuf);
@@ -2616,4 +2820,7 @@
 	else
 	    Strcpy(invbuf, class_name);
+	if (oclass && showsym)
+	    Sprintf(eos(invbuf), ocsymformat,
+		    iflags.menu_tab_sep ? "\t" : "  ", def_oc_syms[let]);
 	return invbuf;
 }
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/src/light.c nethack/src/light.c
--- nh_orig/src/light.c	2003-12-07 18:39:13.000000000 -0500
+++ nethack/src/light.c	2009-10-22 09:38:12.054453154 -0400
@@ -309,8 +309,8 @@
 	    if (ls->type == LS_OBJECT || ls->type == LS_MONSTER) {
 		if (ghostly) {
-		    if (!lookup_id_mapping((unsigned)ls->id, &nid))
+		    if (!lookup_id_mapping((size_t)ls->id, &nid))
 			impossible("relink_light_sources: no id mapping");
 		} else
-		    nid = (unsigned) ls->id;
+		    nid = (size_t) ls->id;
 		if (ls->type == LS_OBJECT) {
 		    which = 'o';
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/src/lock.c nethack/src/lock.c
--- nh_orig/src/lock.c	2003-12-07 18:39:13.000000000 -0500
+++ nethack/src/lock.c	2009-11-25 10:31:20.831272890 -0500
@@ -51,5 +51,6 @@
 		/* [1] */	"unlocking the chest",
 		/* [2] */	"unlocking the box",
-		/* [3] */	"picking the lock"
+		/* [3] */   "cracking the safe",
+		/* [4] */	"picking the lock"
 	};
 
@@ -58,16 +59,18 @@
 		return actions[0]+2;	/* "locking the door" */
 	else if (xlock.box && !xlock.box->olocked)
-		return xlock.box->otyp == CHEST ? actions[1]+2 : actions[2]+2;
+		return xlock.box->otyp == CHEST ? actions[1]+2 : xlock.box->otyp == IRON_SAFE ?
+			actions[3]+2 : actions[2]+2;
 	/* otherwise we're trying to unlock it */
 	else if (xlock.picktyp == LOCK_PICK)
-		return actions[3];	/* "picking the lock" */
+		return actions[4];	/* "picking the lock" */
 #ifdef TOURIST
 	else if (xlock.picktyp == CREDIT_CARD)
-		return actions[3];	/* same as lock_pick */
+		return actions[4];	/* same as lock_pick */
 #endif
 	else if (xlock.door)
 		return actions[0];	/* "unlocking the door" */
 	else
-		return xlock.box->otyp == CHEST ? actions[1] : actions[2];
+		return xlock.box->otyp == CHEST ? actions[1] : xlock.box->otyp == IRON_SAFE ?
+			actions[3] : actions[2];
 }
 
@@ -78,5 +81,7 @@
 
 	if (xlock.box) {
-	    if((xlock.box->ox != u.ux) || (xlock.box->oy != u.uy)) {
+	    if(((xlock.box->ox != u.ux) || (xlock.box->oy != u.uy)) &&
+				 (xlock.box->otyp != IRON_SAFE || abs(xlock.box->oy - u.uy) > 1 ||
+				  abs(xlock.box->ox - u.ux) > 1)) {
 		return((xlock.usedtime = 0));		/* you or it moved */
 	    }
@@ -224,7 +229,9 @@
 
 int
-pick_lock(pick) /* pick a lock with a given object */
+pick_lock(pick,rx,ry) /* pick a lock with a given object */
 	register struct	obj	*pick;
+int rx,ry;
 {
+	/* rx and ry are passed only from the use-stethoscope stuff */
 	int picktyp, c, ch;
 	coord cc;
@@ -244,4 +251,6 @@
 		if (picktyp == CREDIT_CARD) what = "card";
 #endif
+		if (picktyp == STETHOSCOPE) what = "stethoscope";
+
 		pline(no_longer, "hold the", what);
 		reset_pick();
@@ -264,5 +273,5 @@
 	}
 
-	if((picktyp != LOCK_PICK &&
+	if((picktyp != LOCK_PICK && picktyp != STETHOSCOPE &&
 #ifdef TOURIST
 	    picktyp != CREDIT_CARD &&
@@ -274,6 +283,14 @@
 	ch = 0;		/* lint suppression */
 
+	/* If this is a stethoscope, we know where we came from */
+	if (picktyp == STETHOSCOPE) {
+		cc.x = rx; cc.y = ry;
+	} else {
 	if(!get_adjacent_loc((char *)0, "Invalid location!", u.ux, u.uy, &cc)) return 0;
-	if (cc.x == u.ux && cc.y == u.uy) {	/* pick lock on a container */
+	}
+
+	/* Very clumsy special case for this, but forcing the player to
+	 * a)pply > just to open a safe, when a)pply . works in all other cases? */
+	if (cc.x == u.ux && cc.y == u.uy || picktyp == STETHOSCOPE) {	/* pick lock on a container */
 	    const char *verb;
 	    boolean it;
@@ -304,4 +321,5 @@
 		    it = 0;
 		    if (otmp->obroken) verb = "fix";
+			 else if (otmp->otyp == IRON_SAFE) verb = "crack", it = 1;
 		    else if (!otmp->olocked) verb = "lock", it = 1;
 		    else if (picktyp != LOCK_PICK) verb = "unlock", it = 1;
@@ -316,4 +334,12 @@
 		    if(c == 'n') continue;
 
+			 if (otmp->otyp == IRON_SAFE && picktyp != STETHOSCOPE) {
+				 You("aren't sure how to go about opening the safe that way.");
+				 return 0;
+			 }
+			 if (!otmp->olocked && otmp->otyp == IRON_SAFE) {
+				 You_cant("change the combination.");
+				 return 0;
+			 }
 		    if (otmp->obroken) {
 			You_cant("fix its broken lock with %s.", doname(pick));
@@ -339,4 +365,7 @@
 			    ch = 75 + ACURR(A_DEX);
 			    break;
+			case STETHOSCOPE:
+				 ch = 5 + 2*ACURR(A_DEX)*Role_if(PM_ROGUE);
+				 break;
 			default:	ch = 0;
 		    }
@@ -350,5 +379,5 @@
 	    if (c != 'y') {
 		if (!count)
-		    There("doesn't seem to be any sort of lock here.");
+		    There("doesn't seem to be any sort of pickable lock here.");
 		return(0);		/* decided against all boxes */
 	    }
@@ -467,4 +496,8 @@
 	for(otmp = level.objects[u.ux][u.uy]; otmp; otmp = otmp->nexthere)
 	    if(Is_box(otmp)) {
+			 if (otmp->otyp == IRON_SAFE) {
+				 You("would need dynamite to force %s.", the(xname(otmp)));
+				 continue;
+			 }
 		if (otmp->obroken || !otmp->olocked) {
 		    There("is %s here, but its lock is already %s.",
@@ -486,5 +519,6 @@
 		    You("start bashing it with your %s.", xname(uwep));
 		xlock.box = otmp;
-		xlock.chance = objects[uwep->otyp].oc_wldam * 2;
+		xlock.chance = objects[uwep->otyp].oc_wldam * 2 +
+			(picktyp ? ((ACURR(A_DEX) > 14) ? ACURR(A_DEX) - 14 : 0) : dbon());
 		xlock.picktyp = picktyp;
 		xlock.usedtime = 0;
@@ -724,5 +758,4 @@
 	    break;
 	case WAN_POLYMORPH:
-	case SPE_POLYMORPH:
 	    /* maybe start unlocking chest, get interrupted, then zap it;
 	       we must avoid any attempt to resume unlocking it */
@@ -830,4 +863,5 @@
 	case WAN_STRIKING:
 	case SPE_FORCE_BOLT:
+	case WAN_WIND:
 	    if (door->doormask & (D_LOCKED | D_CLOSED)) {
 		if (door->doormask & D_TRAPPED) {
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/src/mail.c nethack/src/mail.c
--- nh_orig/src/mail.c	2003-12-07 18:39:13.000000000 -0500
+++ nethack/src/mail.c	2010-08-16 13:20:13.485755039 -0400
@@ -5,4 +5,8 @@
 #include "hack.h"
 
+#if !defined(MAIL) && defined(SERVER_ADMIN_MSG)
+#include <sys/stat.h>
+#endif
+
 #ifdef MAIL
 #include "mail.h"
@@ -554,5 +558,5 @@
 #  ifdef SHELL	/* can't access mail reader without spawning subprocess */
     const char *txt, *cmd;
-    char *p, buf[BUFSZ], qbuf[BUFSZ];
+    char *p, buf[BUFSZ] = "", qbuf[BUFSZ];
     int len;
 
@@ -623,3 +627,48 @@
 #endif /* MAIL */
 
+void
+ck_server_admin_msg()
+{
+#ifdef SERVER_ADMIN_MSG
+  static struct stat ost,nst;
+  static long lastchk = 0;
+
+  if (moves < lastchk + 10) return;
+  lastchk = moves;
+
+  if (!stat(SERVER_ADMIN_MSG, &nst)) {
+
+    if (nst.st_mtime > ost.st_mtime) {
+      char curline[250];
+      boolean shown_name = FALSE;
+      FILE* mb = fopen(SERVER_ADMIN_MSG, "r");
+      boolean snd = flags.soundok;
+
+      if (!mb) return;
+
+      while (fgets(curline, 250, mb) != NULL) {
+        char *msg = strchr(curline, ':');
+        if (!msg) {
+          fclose(mb);
+	  flags.soundok = snd;
+          return;
+        }
+        *msg = '\0';
+        msg++;
+        msg[strlen(msg) - 1] = '\0'; /* kill newline */
+	flags.soundok = TRUE;
+        if (!shown_name) {
+          pline("The voice of %s booms through the caverns:", curline);
+          shown_name = TRUE;
+        }
+        verbalize(msg);
+      }
+      ost.st_mtime = nst.st_mtime;
+      fclose(mb);
+      flags.soundok = snd;
+    }
+  }
+#endif /* SERVER_ADMIN_MSG */
+}
+
 /*mail.c*/
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/src/makemon.c nethack/src/makemon.c
--- nh_orig/src/makemon.c	2003-12-07 18:39:13.000000000 -0500
+++ nethack/src/makemon.c	2010-05-13 09:22:21.966714579 -0400
@@ -71,4 +71,6 @@
 	if (!pm_resistance(ptr,MR_FIRE)) return TRUE;
     } else if (Is_airlevel(&u.uz)) {
+	/* fortunately elementals can't cast 'fly' so we don't have
+	 * to check for is_flying here; we don't have a monst pointer */
 	if(!(is_flyer(ptr) && ptr->mlet != S_TRAPPER) && !is_floater(ptr)
 	   && !amorphous(ptr) && !noncorporeal(ptr) && !is_whirly(ptr))
@@ -168,4 +170,5 @@
 	register int mm = monsndx(ptr);
 	struct obj *otmp;
+	int randwand;
 
 #ifdef REINCARNATION
@@ -201,4 +204,44 @@
 			case PM_SERGEANT:
 			  w1 = rn2(2) ? FLAIL : MACE;
+			  /* The sergeants in the towers get bows and wands so
+				* they can shoot at you while you're piddling with the
+				* drawbridge.  This should suck a lot if you're low level. */
+			  if (Is_stronghold(&u.uz)) {
+				  w2 = BOW;
+				  m_initthrow(mtmp,ARROW,30);
+
+				  /* wands of death should be very rare: 1 in 400 or so
+					* since we're making 8 wands per castle at this point,
+					* we need to be sure it's _super_ rare that one shows up */
+				  do {
+					  randwand = rn2(7);
+				  } while (randwand > 5 && rn2(50));
+
+				  switch (randwand) {
+					  case 1:
+						  randwand = WAN_MAGIC_MISSILE;
+						  break;
+					  case 2:
+						  randwand = WAN_SLEEP;
+						  break;
+					  case 3:
+						  randwand = WAN_FIRE;
+						  break;
+					  case 4:
+						  randwand = WAN_COLD;
+						  break;
+					  case 5:
+						  randwand = WAN_LIGHTNING;
+						  break;
+					  case 6:
+						  randwand = WAN_DEATH;
+						  break;
+					  case 0:
+					  default:
+						  randwand = WAN_STRIKING;
+						  break;
+				  }
+				  (void)mongets(mtmp, randwand);
+			  }
 			  break;
 			case PM_LIEUTENANT:
@@ -208,4 +251,5 @@
 			case PM_WATCH_CAPTAIN:
 			  w1 = rn2(2) ? LONG_SWORD : SILVER_SABER;
+			  (void)mongets(mtmp, SKELETON_KEY);
 			  break;
 			default:
@@ -218,7 +262,8 @@
 		    if (w2) (void)mongets(mtmp, w2);
 		} else if (is_elf(ptr)) {
-		    if (rn2(2))
-			(void) mongets(mtmp,
-				   rn2(2) ? ELVEN_MITHRIL_COAT : ELVEN_CLOAK);
+			/* only higher-ranking elves get the good armor */
+		    if (rn2(2)) (void)mongets(mtmp,
+					(rn2(2) && (mm == PM_GREY_ELF || mm == PM_ELF_LORD || mm == PM_ELVENKING)) ? 
+					ELVEN_MITHRIL_COAT : ELVEN_CLOAK);
 		    if (rn2(2)) (void)mongets(mtmp, ELVEN_LEATHER_HELM);
 		    else if (!rn2(4)) (void)mongets(mtmp, ELVEN_BOOTS);
@@ -262,13 +307,20 @@
 		    int spe2;
 
-		    /* create minion stuff; can't use mongets */
+		    /* create minion stuff; can't use mongets.
+			  * some angelic minions will get demonbane or sunsword;
+			  * decide that ahead of time so we know what to make */
+		    if (!rn2(20) || is_lord(ptr)) {
+				spe2 = rn2(2);
+				if (spe2) {
+					otmp = mksobj(SILVER_MACE, FALSE, FALSE);	/* TODO: unhardcode this crap */
+				} else {
+					otmp = mksobj(SILVER_LONG_SWORD, FALSE, FALSE);
+				}
+				otmp = oname(otmp, artiname(spe2 ? ART_DEMONBANE : ART_SUNSWORD));
+			 } else {
 		    otmp = mksobj(LONG_SWORD, FALSE, FALSE);
-
-		    /* maybe make it special */
-		    if (!rn2(20) || is_lord(ptr))
-			otmp = oname(otmp, artiname(
-				rn2(2) ? ART_DEMONBANE : ART_SUNSWORD));
+			 }
 		    bless(otmp);
-		    otmp->oerodeproof = TRUE;
+		    set_erodeproof(otmp);
 		    spe2 = rn2(4);
 		    otmp->spe = max(otmp->spe, spe2);
@@ -279,5 +331,5 @@
 				  FALSE, FALSE);
 		    otmp->cursed = FALSE;
-		    otmp->oerodeproof = TRUE;
+		    set_erodeproof(otmp);
 		    otmp->spe = 0;
 		    (void) mpickobj(mtmp, otmp);
@@ -287,4 +339,11 @@
 	    case S_HUMANOID:
 		if (mm == PM_HOBBIT) {
+			if (!rn2(20)) {
+				(void)mongets(mtmp, ELVEN_MITHRIL_COAT);
+				(void)mongets(mtmp, ELVEN_DAGGER);
+				otmp = mksobj(RIN_INVISIBILITY,FALSE,FALSE);
+				otmp->cursed = TRUE;
+				(void) mpickobj(mtmp,otmp);
+			} else {
 		    switch (rn2(3)) {
 			case 0:
@@ -298,5 +357,5 @@
 			    break;
 		      }
-		    if (!rn2(10)) (void)mongets(mtmp, ELVEN_MITHRIL_COAT);
+			}
 		    if (!rn2(10)) (void)mongets(mtmp, DWARVISH_CLOAK);
 		} else if (is_dwarf(ptr)) {
@@ -312,5 +371,6 @@
 			}
 			(void)mongets(mtmp, DWARVISH_IRON_HELM);
-			if (!rn2(3))
+			/* only higher ranking dwarves get the good stuff */
+			if (!rn2(3) && mm != PM_DWARF)
 			    (void)mongets(mtmp, DWARVISH_MITHRIL_COAT);
 		    } else {
@@ -372,13 +432,12 @@
 
 	    case S_CENTAUR:
-		if (rn2(2)) {
-		    if(ptr == &mons[PM_FOREST_CENTAUR]) {
+			/* the skittish centaurs all need to have missile weapons at least */
+			if(ptr == &mons[PM_FOREST_CENTAUR] || ptr == &mons[PM_PLAINS_CENTAUR]) {
 			(void)mongets(mtmp, BOW);
-			m_initthrow(mtmp, ARROW, 12);
-		    } else {
+				m_initthrow(mtmp, ARROW, 24);
+			} else if (rn2(2)) {
 			(void)mongets(mtmp, CROSSBOW);
 			m_initthrow(mtmp, CROSSBOW_BOLT, 12);
 		    }
-		}
 		break;
 	    case S_WRAITH:
@@ -396,4 +455,30 @@
 					     TRIDENT : STILETTO));
 		break;
+		 case S_GNOME:
+			if (rn2(5)) { (void)mongets(mtmp, GNOMISH_HELM); }
+			if (!rn2(3)) { (void)mongets(mtmp, GNOMISH_BOOTS); }
+			if (!rn2(5)) { (void)mongets(mtmp, GNOMISH_SUIT); }
+			/* some of this ported up from below, so gnomes are
+			 * more than a speedbump again */
+			switch (rn2(4)) {
+				case 3:
+					(void) mongets(mtmp, CROSSBOW);
+					m_initthrow(mtmp, CROSSBOW_BOLT, 12);
+					break;
+				case 2:
+					(void) mongets(mtmp, BOW);
+					m_initthrow(mtmp, ARROW, 12);
+					break;
+				case 1:
+					m_initthrow(mtmp, DAGGER, 3);
+					break;
+				case 0:
+				default:
+					(void) mongets(mtmp, AKLYS);
+					if ((int) mtmp->m_lev > rn2(75)) {
+						(void) mongets(mtmp, rnd_offensive_item(mtmp));
+					}
+			}
+		break;
 	    case S_DEMON:
 		switch (mm) {
@@ -402,7 +487,4 @@
 			(void)mongets(mtmp, BROADSWORD);
 			break;
-		    case PM_ORCUS:
-			(void)mongets(mtmp, WAN_DEATH); /* the Wand of Orcus */
-			break;
 		    case PM_HORNED_DEVIL:
 			(void)mongets(mtmp, rn2(4) ? TRIDENT : BULLWHIP);
@@ -614,5 +696,5 @@
 				      TRUE, rn2(13) ? FALSE : TRUE);
 			if (otmp->spe < 2) otmp->spe = rnd(3);
-			if (!rn2(4)) otmp->oerodeproof = 1;
+			if (!rn2(4)) set_erodeproof(otmp);
 			(void) mpickobj(mtmp, otmp);
 		}
@@ -625,4 +707,5 @@
 			otmp = mksobj(LARGE_BOX, FALSE, FALSE);
 			otmp->spe = 1; /* flag for special box */
+			otmp->capacity = 3000; /* it should still be standard capacity */
 			otmp->owt = weight(otmp);
 			(void) mpickobj(mtmp, otmp);
@@ -641,7 +724,4 @@
 		if (ptr == &mons[PM_ICE_DEVIL] && !rn2(4)) {
 			(void)mongets(mtmp, SPEAR);
-		} else if (ptr == &mons[PM_ASMODEUS]) {
-			(void)mongets(mtmp, WAN_COLD);
-			(void)mongets(mtmp, WAN_FIRE);
 		}
 		break;
@@ -709,11 +789,22 @@
 	m2->mgold = 0L;
 #endif
-	/* Max HP the same, but current HP halved for both.  The caller
-	 * might want to override this by halving the max HP also.
-	 * When current HP is odd, the original keeps the extra point.
+	/* Max HP remaining the same allows infinite pudding farming
+	 * so let's go ahead and chop both in half as well, so eventually
+	 * there'll be a finite end to things...
 	 */
-	m2->mhpmax = mon->mhpmax;
+	m2->mhpmax = mon->mhpmax / 2;
 	m2->mhp = mon->mhp / 2;
+	/* Big Daddy is a bit meaner; the originals don't suffer from the split */
+	if (mon->data != &mons[PM_JUIBLEX]) {
+		mon->mhpmax -= m2->mhpmax;
 	mon->mhp -= m2->mhp;
+	}
+
+	/* don't accidentally set any of these to zero
+	 * since our caller will be expecting a live critter */
+	if (m2->mhpmax < 1) m2->mhpmax = 1;
+	if (mon->mhpmax < 1) mon->mhpmax = 1;
+	if (m2->mhp < 1) m2->mhp = 1;
+	if (mon->mhp < 1) mon->mhp = 1;
 
 	/* since shopkeepers and guards will only be cloned if they've been
@@ -828,5 +919,6 @@
 {
 	register struct monst *mtmp;
-	int mndx, mcham, ct, mitem, xlth;
+	struct obj* otmp;
+	int mndx, mcham, ct, mitem, xlth, mhitdie;
 	boolean anymon = (!ptr);
 	boolean byyou = (x == u.ux && y == u.uy);
@@ -919,6 +1011,8 @@
 	    mtmp->mhpmax = mtmp->mhp = golemhp(mndx);
 	} else if (is_rider(ptr)) {
-	    /* We want low HP, but a high mlevel so they can attack well */
-	    mtmp->mhpmax = mtmp->mhp = d(10,8);
+	    /* We want low HP, but a high mlevel so they can attack well
+		  *
+		  * DSR 10/31/09: What, are you nuts?  They're way too crunchy. */
+	    mtmp->mhpmax = mtmp->mhp = 100 + d(8,8);
 	} else if (ptr->mlevel > 49) {
 	    /* "special" fixed hp monster
@@ -928,12 +1022,30 @@
 	    mtmp->mhpmax = mtmp->mhp = 2*(ptr->mlevel - 6);
 	    mtmp->m_lev = mtmp->mhp / 4;	/* approximation */
-	} else if (ptr->mlet == S_DRAGON && mndx >= PM_GRAY_DRAGON) {
-	    /* adult dragons */
-	    mtmp->mhpmax = mtmp->mhp = (int) (In_endgame(&u.uz) ?
-		(8 * mtmp->m_lev) : (4 * mtmp->m_lev + d((int)mtmp->m_lev, 4)));
+	} else if (ptr->mlet == S_DRAGON && mndx >= PM_GRAY_DRAGON && In_endgame(&u.uz)) {
+	    /* dragons in the endgame are always at least average HP
+		  * note modified hit die here as well; they're MZ_GIGANTIC */
+	    mtmp->mhpmax = mtmp->mhp = 7 * mtmp->m_lev + d((int)mtmp->m_lev, 8);
 	} else if (!mtmp->m_lev) {
-	    mtmp->mhpmax = mtmp->mhp = rnd(4);
+	    mtmp->mhpmax = mtmp->mhp = rnd(4);	 /* level 0 monsters are pathetic */
+	} else if (ptr->msound == MS_LEADER) {
+		/* Quest Leaders need to be fairly burly */
+		mtmp->mhpmax = mtmp->mhp = 135 + rnd(30);
 	} else {
-	    mtmp->mhpmax = mtmp->mhp = d((int)mtmp->m_lev, 8);
+		/* plain old ordinary monsters; modify hit die based on size;
+		 * big-ass critters like mastodons should have big-ass HP, and
+		 * small things like bees and locusts should get less 
+		 */
+		switch (mtmp->data->msize) {
+			case MZ_TINY: mhitdie = 4; break;
+			case MZ_SMALL: mhitdie = 6; break;
+			case MZ_LARGE: mhitdie = 10; break;
+			case MZ_HUGE: mhitdie = 12; break;
+			case MZ_GIGANTIC: mhitdie = 15; break;
+			case MZ_MEDIUM: 
+			default:	
+				mhitdie = 8;
+				break;
+		}
+	    mtmp->mhpmax = mtmp->mhp = d((int)mtmp->m_lev, mhitdie);
 	    if (is_home_elemental(ptr))
 		mtmp->mhpmax = (mtmp->mhp *= 3);
@@ -951,4 +1063,7 @@
 	place_monster(mtmp, x, y);
 	mtmp->mcansee = mtmp->mcanmove = TRUE;
+	mtmp->mflying = is_flyer(mtmp->data);	  /* fliers start out flying */
+	mtmp->seen_resistance = M_SEEN_NOTHING;
+	mtmp->mberserk = is_berserker(mtmp->data); /* berserkers start out crazed */
 	mtmp->mpeaceful = (mmflags & MM_ANGRY) ? FALSE : peace_minded(ptr);
 
@@ -980,4 +1095,5 @@
 			break;
 		case S_JABBERWOCK:
+			break;
 		case S_NYMPH:
 			if (rn2(5) && !u.uhave.amulet) mtmp->msleeping = 1;
@@ -995,4 +1111,29 @@
 			    mon_adjust_speed(mtmp, 2, (struct obj *)0);
 			break;
+		case S_DRAGON:
+			/* Dragons are always generated awake and pissed for Knights. */
+			if (Role_if(PM_KNIGHT)) {
+				mtmp->mpeaceful = mtmp->mtame = FALSE;
+				mtmp->msleeping = 0;
+			}
+			/* Warren Robinett didn't leave this easter egg, but... */
+			if (!rn2(13)) {
+				switch (mtmp->mnum) {
+					case PM_YELLOW_DRAGON:
+						mtmp = christen_monst(mtmp,"Yorgle"); 
+						break;
+					case PM_GREEN_DRAGON:
+						mtmp = christen_monst(mtmp,"Grundle");
+						if (rn2(2)) (void)mongets(mtmp, SKELETON_KEY); /* black key */
+						break;
+					case PM_RED_DRAGON:
+						mtmp = christen_monst(mtmp,"Rhindle");
+						if (rn2(2)) (void)mongets(mtmp, SKELETON_KEY); /* white key */
+						break;
+					default:
+						break;
+				}
+			}
+			break;
 	}
 	if ((ct = emits_light(mtmp->data)) > 0)
@@ -1022,12 +1163,4 @@
 		if (!(mmflags & MM_NONAME))
 			mtmp = christen_monst(mtmp, rndghostname());
-	} else if (mndx == PM_VLAD_THE_IMPALER) {
-		mitem = CANDELABRUM_OF_INVOCATION;
-	} else if (mndx == PM_CROESUS) {
-		mitem = TWO_HANDED_SWORD;
-	} else if (ptr->msound == MS_NEMESIS) {
-		mitem = BELL_OF_OPENING;
-	} else if (mndx == PM_PESTILENCE) {
-		mitem = POT_SICKNESS;
 	}
 	if (mitem && allow_minvent) (void) mongets(mtmp, mitem);
@@ -1189,4 +1322,30 @@
 }
 
+
+struct permonst *
+get_override_mon(override)
+struct mon_gen_override *override;
+{
+    int chance, try = 100;
+    struct mon_gen_tuple *mt;
+    int ok;
+    if (!override) return NULL;
+
+    chance = rnd(override->total_mon_freq);
+    do {
+	mt = override->gen_chances;
+	while (mt && ((chance -= mt->freq) > 0)) mt = mt->next;
+	if (mt && (chance <= 0)) {
+	    if (mt->is_sym) {
+		return (mkclass(mt->monid, 0));
+	    } else {
+		if (!(mvitals[mt->monid].mvflags & G_GENOD))
+		    return (&mons[mt->monid]);
+	    }
+	}
+    } while (--try > 0);
+    return NULL;
+}
+
 static NEARDATA struct {
 	int choice_count;
@@ -1201,5 +1360,7 @@
 	register int mndx, ct;
 
-	if (u.uz.dnum == quest_dnum && rn2(7) && (ptr = qt_montype()) != 0)
+	if (level.mon_gen &&
+	    (rn2(100) < level.mon_gen->override_chance) &&
+	    ((ptr = get_override_mon(level.mon_gen)) != 0))
 	    return ptr;
 
@@ -1492,4 +1653,8 @@
 	if (!otyp) return 0;
 	otmp = mksobj(otyp, TRUE, FALSE);
+	/* special case for Vlad's new sword */
+	if (mtmp->mnum == PM_VLAD_THE_IMPALER && otyp == TWO_HANDED_SWORD) {
+		otmp = mk_artifact(otmp,(aligntyp)A_NONE);
+	}
 	if (otmp) {
 	    if (mtmp->data->mlet == S_DEMON) {
@@ -1500,5 +1665,5 @@
 		otmp->cursed = FALSE;
 		if(otmp->spe < 0) otmp->spe = 0;
-		otmp->oerodeproof = TRUE;
+		set_erodeproof(otmp);
 	    } else if(is_mplayer(mtmp->data) && is_sword(otmp)) {
 		otmp->spe = (3 + rn2(4));
@@ -1510,6 +1675,4 @@
 		otmp->lamplit = FALSE;
 		otmp->blessed = otmp->cursed = FALSE;
-	    } else if (otmp->otyp == BELL_OF_OPENING) {
-		otmp->blessed = otmp->cursed = FALSE;
 	    } else if (otmp->otyp == SPE_BOOK_OF_THE_DEAD) {
 		otmp->blessed = FALSE;
@@ -1544,10 +1707,10 @@
 		case PM_LEATHER_GOLEM: return 40;
 		case PM_GOLD_GOLEM: return 40;
-		case PM_WOOD_GOLEM: return 50;
+		case PM_WOOD_GOLEM: return 60;
 		case PM_FLESH_GOLEM: return 40;
-		case PM_CLAY_GOLEM: return 50;
-		case PM_STONE_GOLEM: return 60;
-		case PM_GLASS_GOLEM: return 60;
-		case PM_IRON_GOLEM: return 80;
+		case PM_CLAY_GOLEM: return 60;
+		case PM_STONE_GOLEM: return 150;		/* it's a rock */
+		case PM_GLASS_GOLEM: return 80;
+		case PM_IRON_GOLEM: return 150;		/* it's solid iron */
 		default: return 0;
 	}
@@ -1642,5 +1805,5 @@
 			mtmp->malign = 0;
 		else
-			mtmp->malign = max(5,absmal);
+			mtmp->malign = max(3,absmal);
 	} else if (coaligned) {
 		int absmal = abs(mal);
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/src/mapglyph.c nethack/src/mapglyph.c
--- nh_orig/src/mapglyph.c	2003-12-07 18:39:13.000000000 -0500
+++ nethack/src/mapglyph.c	2010-04-11 12:36:57.402750082 -0400
@@ -113,9 +113,9 @@
 	    if (offset >= S_vwall && offset <= S_hcdoor)
 		color = CLR_BROWN;
-	    else if (offset >= S_arrow_trap && offset <= S_polymorph_trap)
+	    else if (offset >= S_arrow_trap && offset <= S_magic_beam_trap)
 		color = CLR_MAGENTA;
 	    else if (offset == S_corr || offset == S_litcorr)
 		color = CLR_GRAY;
-	    else if (offset >= S_room && offset <= S_water)
+	    else if (offset >= S_room && offset <= S_water && offset != S_darkroom)
 		color = CLR_GREEN;
 	    else
@@ -133,5 +133,7 @@
 	    cmap_color(offset);
     } else if ((offset = (glyph - GLYPH_OBJ_OFF)) >= 0) {	/* object */
-	if (offset == BOULDER && iflags.bouldersym) ch = iflags.bouldersym;
+	if (objects[offset].oc_class == FURNITURE_CLASS) {
+	    ch = objects[offset].oc_oc1;
+	} else if (offset == BOULDER && iflags.bouldersym) ch = iflags.bouldersym;
 	else ch = oc_syms[(int)objects[offset].oc_class];
 #ifdef ROGUE_COLOR
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/src/mcastu.c nethack/src/mcastu.c
--- nh_orig/src/mcastu.c	2003-12-07 18:39:13.000000000 -0500
+++ nethack/src/mcastu.c	2009-11-22 07:40:25.916272781 -0500
@@ -4,4 +4,6 @@
 
 #include "hack.h"
+#include "edog.h"
+#include "epri.h"
 
 /* monster mage spells */
@@ -18,4 +20,8 @@
 #define MGC_CLONE_WIZ	10
 #define MGC_DEATH_TOUCH	11
+#define MGC_FLY			12
+#define MGC_ENRAGE		13
+#define MGC_FIRE_BOLT   14
+#define MGC_ICE_BOLT    15
 
 /* monster cleric spells */
@@ -30,12 +36,16 @@
 #define CLC_FIRE_PILLAR	 8
 #define CLC_GEYSER	 9
+#define CLC_FLY			10
+#define CLC_VULN_YOU		11
+#define CLC_SUMMON_ELM  12
 
 STATIC_DCL void FDECL(cursetxt,(struct monst *,BOOLEAN_P));
-STATIC_DCL int FDECL(choose_magic_spell, (int));
-STATIC_DCL int FDECL(choose_clerical_spell, (int));
+STATIC_DCL int FDECL(choose_magic_spell, (struct monst *, int));
+STATIC_DCL int FDECL(choose_clerical_spell, (struct monst *, int));
 STATIC_DCL void FDECL(cast_wizard_spell,(struct monst *, int,int));
 STATIC_DCL void FDECL(cast_cleric_spell,(struct monst *, int,int));
 STATIC_DCL boolean FDECL(is_undirected_spell,(unsigned int,int));
 STATIC_DCL boolean FDECL(spell_would_be_useless,(struct monst *,unsigned int,int));
+STATIC_DCL void FDECL(cast_fly,(struct monst *));
 
 #ifdef OVL0
@@ -78,26 +88,39 @@
    inappropriate choices will be screened out by spell_would_be_useless() */
 STATIC_OVL int
-choose_magic_spell(spellval)
+choose_magic_spell(mtmp,spellval)
+struct monst* mtmp;
 int spellval;
 {
+	struct trap* tr;
+	int i;
+
+	/* If we're stuck in a pit, we know a way out */
+	tr = t_at(mtmp->mx,mtmp->my);
+	if (mtmp->mtrapped && tr && (tr->ttyp == PIT || tr->ttyp == SPIKED_PIT) 
+			&& mtmp->m_lev > 5) { spellval = 5; }
+
+	/* If we're hurt, seriously consider giving fixing ourselves priority */
+	if ((mtmp->mhp * 4) <= mtmp->mhpmax) { spellval = 1; }
+
     switch (spellval) {
     case 22:
     case 21:
-    case 20:
 	return MGC_DEATH_TOUCH;
+		case 20:
     case 19:
-    case 18:
 	return MGC_CLONE_WIZ;
+		case 18:
     case 17:
+			return MGC_ENRAGE;
     case 16:
     case 15:
 	return MGC_SUMMON_MONS;
     case 14:
-    case 13:
 	return MGC_AGGRAVATION;
+		case 13:
     case 12:
     case 11:
-    case 10:
 	return MGC_CURSE_ITEMS;
+		case 10:
     case 9:
     case 8:
@@ -107,4 +130,5 @@
 	return MGC_WEAKEN_YOU;
     case 5:
+			return MGC_FLY;
     case 4:
 	return MGC_DISAPPEAR;
@@ -117,14 +141,36 @@
     case 0:
     default:
+			i = rn2(3);
+			switch (i) {
+				case 2:
+					return MGC_FIRE_BOLT;
+				case 1:
+					return MGC_ICE_BOLT;
+				case 0:
+				default:
 	return MGC_PSI_BOLT;
     }
 }
+}
 
 /* convert a level based random selection into a specific cleric spell */
 STATIC_OVL int
-choose_clerical_spell(spellnum)
+choose_clerical_spell(mtmp,spellnum)
+struct monst* mtmp;
 int spellnum;
 {
+	struct trap* tr;
+
+	/* If we're stuck in a pit, we know a way out */
+	tr = t_at(mtmp->mx,mtmp->my);
+	if (mtmp->mtrapped && tr && (tr->ttyp == PIT || tr->ttyp == SPIKED_PIT) 
+			&& mtmp->m_lev > 3) { spellnum = 3; }
+
+	/* If we're hurt, seriously consider giving fixing ourselves priority */
+	if ((mtmp->mhp * 4) <= mtmp->mhpmax) { spellnum = 1; }
+
     switch (spellnum) {
+		case 14:
+			return CLC_SUMMON_ELM;
     case 13:
 	return CLC_GEYSER;
@@ -132,17 +178,19 @@
 	return CLC_FIRE_PILLAR;
     case 11:
-	return CLC_LIGHTNING;
     case 10:
+			return CLC_PARALYZE;
     case 9:
-	return CLC_CURSE_ITEMS;
+			return CLC_LIGHTNING;
     case 8:
-	return CLC_INSECTS;
     case 7:
+			return CLC_CURSE_ITEMS;
     case 6:
-	return CLC_BLIND_YOU;
+			return CLC_INSECTS;
     case 5:
+			return CLC_BLIND_YOU;
     case 4:
-	return CLC_PARALYZE;
+			return CLC_FLY;
     case 3:
+			return CLC_VULN_YOU;
     case 2:
 	return CLC_CONFUSE_YOU;
@@ -188,11 +236,10 @@
 		spellnum = rn2(ml);
 		if (mattk->adtyp == AD_SPEL)
-		    spellnum = choose_magic_spell(spellnum);
+				spellnum = choose_magic_spell(mtmp,spellnum);
 		else
-		    spellnum = choose_clerical_spell(spellnum);
+				spellnum = choose_clerical_spell(mtmp,spellnum);
 		/* not trying to attack?  don't allow directed spells */
 		if (!thinks_it_foundyou) {
-		    if (!is_undirected_spell(mattk->adtyp, spellnum) ||
-			spell_would_be_useless(mtmp, mattk->adtyp, spellnum)) {
+				if (!is_undirected_spell(mattk->adtyp, spellnum) || spell_would_be_useless(mtmp, mattk->adtyp, spellnum)) {
 			if (foundyou)
 			    impossible("spellcasting monster found you and doesn't know it?");
@@ -213,6 +260,8 @@
 
 	if (mattk->adtyp == AD_SPEL || mattk->adtyp == AD_CLRC) {
-	    mtmp->mspec_used = 10 - mtmp->m_lev;
+	    mtmp->mspec_used = 8 - mtmp->m_lev;
 	    if (mtmp->mspec_used < 2) mtmp->mspec_used = 2;
+		 /* your quest leader is a badass and does not need recharge time */
+		 if (mtmp->data->msound == MS_LEADER) mtmp->mspec_used = 0;
 	}
 
@@ -229,10 +278,16 @@
 	}
 
-	nomul(0);
-	if(rn2(ml*10) < (mtmp->mconf ? 100 : 20)) {	/* fumbled attack */
-	    if (canseemon(mtmp) && flags.soundok)
+	nomul(0, 0);
+	if(rn2(ml*10) < (mtmp->mconf ? 100 : 10)) {	/* fumbled attack */
+	    if (flags.soundok) {
+			 if (canseemon(mtmp)) {
 		pline_The("air crackles around %s.", mon_nam(mtmp));
+			 } else {
+				 You("hear the air crackling with magical energy.");
+			 }
+		 }
 	    return(0);
 	}
+
 	if (canspotmon(mtmp) || !is_undirected_spell(mattk->adtyp, spellnum)) {
 	    pline("%s casts a spell%s!",
@@ -270,8 +325,11 @@
 	    case AD_FIRE:
 		pline("You're enveloped in flames.");
-		if(Fire_resistance) {
+		if (how_resistant(FIRE_RES) == 100) {
 			shieldeff(u.ux, u.uy);
 			pline("But you resist the effects.");
+			monstseesu(M_SEEN_FIRE);
 			dmg = 0;
+		} else {
+			dmg = resist_reduce(dmg,FIRE_RES);
 		}
 		burn_away_slime();
@@ -279,17 +337,22 @@
 	    case AD_COLD:
 		pline("You're covered in frost.");
-		if(Cold_resistance) {
+		if(how_resistant(COLD_RES) == 100) {
 			shieldeff(u.ux, u.uy);
 			pline("But you resist the effects.");
+			monstseesu(M_SEEN_COLD);
 			dmg = 0;
+		} else {
+			dmg = resist_reduce(dmg,COLD_RES);
 		}
 		break;
 	    case AD_MAGM:
 		You("are hit by a shower of missiles!");
+		dmg = d((int)mtmp->m_lev/2 + 1,6);
 		if(Antimagic) {
 			shieldeff(u.ux, u.uy);
-			pline_The("missiles bounce off!");
-			dmg = 0;
-		} else dmg = d((int)mtmp->m_lev/2 + 1,6);
+			pline("Some of the missiles bounce off!");
+			monstseesu(M_SEEN_MAGR);
+			dmg /= 2;
+		}
 		break;
 	    case AD_SPEL:	/* wizard spell */
@@ -324,4 +387,11 @@
 int spellnum;
 {
+	struct obj* oatmp;
+	struct monst* mtmp2;
+	int erodelvl;
+	const char* desc = 0;
+	int seen,count;
+	struct edog* edog;
+
     if (dmg == 0 && !is_undirected_spell(AD_SPEL, spellnum)) {
 	impossible("cast directed wizard spell (%d) with dmg=0?", spellnum);
@@ -334,15 +404,19 @@
 	if (nonliving(youmonst.data) || is_demon(youmonst.data)) {
 	    You("seem no deader than before.");
-	} else if (!Antimagic && rn2(mtmp->m_lev) > 12) {
+	} else {
 	    if (Hallucination) {
 		You("have an out of body experience.");
 	    } else {
-		killer_format = KILLED_BY_AN;
-		killer = "touch of death";
-		done(DIED);
+			dmg = d(8,6);
+			/* Magic resistance or half spell damage will cut this in half... */
+			if (Antimagic || Half_spell_damage) {
+				shieldeff(u.ux, u.uy);
+				monstseesu(M_SEEN_MAGR);
+				dmg /= 2;
+			}
+			You("feel drained...");
+			gainmaxhp(dmg/-2);
+			losehp(dmg,"touch of death",KILLED_BY_AN);
 	    }
-	} else {
-	    if (Antimagic) shieldeff(u.ux, u.uy);
-	    pline("Lucky for you, it didn't work!");
 	}
 	dmg = 0;
@@ -356,9 +430,47 @@
 	    impossible("bad wizard cloning?");
 	break;
+	/* Inspire critters to fight a little more vigorously...
+	 *
+	 * -- Peaceful critters may become hostile.
+	 * -- Hostile critters may become berserk.
+	 * -- Borderline tame critters, or tame critters
+	 *    who have been treated poorly may ALSO become hostile!
+	 */
+	 case MGC_ENRAGE:
+		for (mtmp2 = fmon; mtmp2; mtmp2 = mtmp2->nmon) {
+			if (m_cansee(mtmp,mtmp2->mx,mtmp2->my) && rn2(3) &&
+					mtmp2 != mtmp && distu(mtmp2->mx,mtmp2->my) < 16) {
+				seen++;
+				if (mtmp2->mtame) {
+					edog = (mtmp2->isminion) ? 0 : EDOG(mtmp2);
+					if (mtmp2->mtame <= 3 || (edog && edog->abuse >= 5)) {
+						mtmp2->mtame = mtmp2->mpeaceful = 0;
+						if (mtmp2->mleashed) { m_unleash(mtmp2,FALSE); }
+						count++;
+					}
+				} else if (mtmp2->mpeaceful) {
+					mtmp2->mpeaceful = 0;
+					count++;
+				} else {
+					mtmp2->mberserk = 1;
+					count++;
+				}
+			}
+		}
+		/* Don't yell if we didn't see anyone to yell at. */
+		if (seen && (!rn2(3) || mtmp->iswiz)) {
+			verbalize("Get %s, you fools, or I'll have your figgin on a stick!",uhim());
+		}
+		if (count) {
+			pline("It seems a little more dangerous here now...");
+			doredraw();
+		}
+		dmg = 0;
+		break;
     case MGC_SUMMON_MONS:
     {
 	int count;
 
-	count = nasty(mtmp);	/* summon something nasty */
+	count = nasty(mtmp,FALSE);	/* summon something nasty */
 	if (mtmp->iswiz)
 	    verbalize("Destroy the thief, my pet%s!", plur(count));
@@ -391,15 +503,54 @@
 	break;
     case MGC_DESTRY_ARMR:
+	/* Magic resistance will reduce the amount by which your stuff is fiddled,
+	 * but it won't actually stop things from being damaged */
+	erodelvl = rnd(3);
 	if (Antimagic) {
 	    shieldeff(u.ux, u.uy);
-	    pline("A field of force surrounds you!");
-	} else if (!destroy_arm(some_armor(&youmonst))) {
+		monstseesu(M_SEEN_MAGR);
+		erodelvl = 1;
+	}
+	oatmp = some_armor(&youmonst);
+	if (oatmp) {
+		if (oatmp->oerodeproof) {
+			if (!Blind) {
+				pline("Your %s glows brown for a moment.",xname(oatmp));
+			}
+			oatmp->oerodeproof = 0;
+		}
+		if (greatest_erosion(oatmp) == MAX_ERODE) {
+			destroy_arm(oatmp);
+		} else {
+			while (erodelvl-- > 0) {
+				_erode_obj(oatmp, AD_MAGM);
+			}
+		}
+	} else {
 	    Your("skin itches.");
 	}
 	dmg = 0;
 	break;
+	 case MGC_FIRE_BOLT:
+	 case MGC_ICE_BOLT:
+		/* hotwire these to only go off if the critter can see you
+		 * to avoid bugs WRT the Eyes and detect monsters */
+		if (m_canseeu(mtmp)) {
+			pline("%s blasts you with %s!",Monnam(mtmp), (spellnum == MGC_FIRE_BOLT) ? "fire" : "cold");
+			explode(u.ux,u.uy,(spellnum == MGC_FIRE_BOLT) ? AD_FIRE-1 : AD_COLD-1,
+					d((mtmp->m_lev/5)+1,8),MON_CASTBALL,(spellnum == MGC_FIRE_BOLT) ? EXPL_FIERY : EXPL_FROSTY);
+		} else {
+			if (canspotmon(mtmp)) {
+				pline("%s blasts the %s with %s and curses!", Monnam(mtmp), rn2(2) ? "ceiling" : "floor",  
+						(spellnum == MGC_FIRE_BOLT) ? "fire" : "cold");
+			} else {
+				You_hear("some cursing!");
+			}
+		}
+		dmg = 0;
+	break;
     case MGC_WEAKEN_YOU:		/* drain strength */
 	if (Antimagic) {
 	    shieldeff(u.ux, u.uy);
+		 monstseesu(M_SEEN_MAGR);
 	    You_feel("momentarily weakened.");
 	} else {
@@ -423,4 +574,7 @@
 	    impossible("no reason for monster to cast disappear spell?");
 	break;
+	 case MGC_FLY:		 /* take off! */
+		cast_fly(mtmp);
+		break;
     case MGC_STUN_YOU:
 	if (Antimagic || Free_action) {
@@ -456,6 +610,18 @@
 	if (Antimagic) {
 	    shieldeff(u.ux, u.uy);
+		 monstseesu(M_SEEN_MAGR);
 	    dmg = (dmg + 1) / 2;
 	}
+	/* Tinfoil hat? ;) */
+	if (uarmh) {
+		desc = OBJ_DESCR(objects[uarmh->otyp]);
+		if (desc && strstri(desc,"tinfoil")) {
+			shieldeff(u.ux, u.uy);
+			dmg = 0;
+			Your("%s tingles.%s", body_part(HEAD), Hallucination ?
+					" You think your dandruff might be clearing up." : "");
+			break;
+		}
+	}
 	if (dmg <= 5)
 	    You("get a slight %sache.", body_part(HEAD));
@@ -476,4 +642,12 @@
 }
 
+const char* vulntext[] = {
+	"chartreuse polka-dot",
+	"reddish-orange",
+	"purplish-blue",
+	"coppery-yellow",
+	"greenish-mottled"
+};
+
 STATIC_OVL
 void
@@ -483,4 +657,6 @@
 int spellnum;
 {
+	int aligntype;
+
     if (dmg == 0 && !is_undirected_spell(AD_CLRC, spellnum)) {
 	impossible("cast directed cleric spell (%d) with dmg=0?", spellnum);
@@ -489,4 +665,14 @@
 
     switch (spellnum) {
+	 case CLC_SUMMON_ELM:
+		 if (mtmp->ispriest) {
+			 aligntype = EPRI(mtmp)->shralign;
+		 } else {
+			 /* uh, who fed the orc shaman so many gain level potions? */
+			 aligntype = (int)mtmp->data->maligntyp;
+		 }
+		 pline("A servant of %s appears!",aligns[1 - aligntype].noun);
+		summon_minion(aligntype, TRUE);
+		 break;
     case CLC_GEYSER:
 	/* this is physical damage, not magical damage */
@@ -497,9 +683,10 @@
     case CLC_FIRE_PILLAR:
 	pline("A pillar of fire strikes all around you!");
-	if (Fire_resistance) {
+	if (how_resistant(FIRE_RES) == 100) {
 	    shieldeff(u.ux, u.uy);
+		 monstseesu(M_SEEN_FIRE);
 	    dmg = 0;
 	} else
-	    dmg = d(8, 6);
+	    dmg = resist_reduce(d(8,6),FIRE_RES);
 	if (Half_spell_damage) dmg = (dmg + 1) / 2;
 	burn_away_slime();
@@ -513,17 +700,25 @@
     {
 	boolean reflects;
-
 	pline("A bolt of lightning strikes down at you from above!");
-	reflects = ureflects("It bounces off your %s%s.", "");
-	if (reflects || Shock_resistance) {
+		reflects = ureflects("Some of it bounces off your %s%s.", "");
+		if (reflects || (how_resistant(SHOCK_RES) == 100)) {
 	    shieldeff(u.ux, u.uy);
+			if (reflects) {
+				dmg = resist_reduce(d(4,6),SHOCK_RES);
+				monstseesu(M_SEEN_REFL);
+			}
+			if (how_resistant(SHOCK_RES) == 100) {
+				pline("You aren't shocked.");
 	    dmg = 0;
-	    if (reflects)
-		break;
-	} else
-	    dmg = d(8, 6);
-	if (Half_spell_damage) dmg = (dmg + 1) / 2;
-	destroy_item(WAND_CLASS, AD_ELEC);
+				monstseesu(M_SEEN_ELEC);
+			}
+		} else {
+			dmg = resist_reduce(d(8,6),SHOCK_RES);
+		}
+		if (dmg && Half_spell_damage)  { dmg = (dmg + 1) / 2; }
+		if (!reflects) {
+			destroy_item(WAND_CLASS, AD_ELEC);	 /* reflection protects items */
 	destroy_item(RING_CLASS, AD_ELEC);
+		}
 	break;
     }
@@ -601,5 +796,5 @@
 	    if (multi >= 0)
 		You("stiffen briefly.");
-	    nomul(-1);
+	    nomul(-1, "paralyzed by a monster");
 	} else {
 	    if (multi >= 0)
@@ -607,5 +802,5 @@
 	    dmg = 4 + (int)mtmp->m_lev;
 	    if (Half_spell_damage) dmg = (dmg + 1) / 2;
-	    nomul(-dmg);
+	    nomul(-dmg, "paralyzed by a monster");
 	}
 	dmg = 0;
@@ -614,4 +809,5 @@
 	if (Antimagic) {
 	    shieldeff(u.ux, u.uy);
+		 monstseesu(M_SEEN_MAGR);
 	    You_feel("momentarily dizzy.");
 	} else {
@@ -638,7 +834,39 @@
 	}
 	break;
+	 case CLC_FLY:
+		cast_fly(mtmp);
+		break;
+	 case CLC_VULN_YOU:
+		dmg = rnd(4);
+		pline("A %s film oozes over your skin!",Blind ? "slimy" : vulntext[dmg]);
+		switch (dmg) {
+			case 1:
+				if (Vulnerable_fire) return;
+				incr_itimeout(&HVulnerable_fire,rnd(100)+150);
+				You_feel("more inflammable.");
+				break;
+			case 2:
+				if (Vulnerable_cold) return;
+				incr_itimeout(&HVulnerable_cold,rnd(100)+150);
+				You_feel("like Jack Frost is out to get you.");
+				break;
+			case 3:
+				if (Vulnerable_elec) return;
+				incr_itimeout(&HVulnerable_elec,rnd(100)+150);
+				You_feel("overly conductive.");
+				break;
+			case 4:
+				if (Vulnerable_acid) return;
+				incr_itimeout(&HVulnerable_acid,rnd(100)+150);
+				You_feel("easily corrodable.");
+				break;
+			default:
+				break;
+		}
+		break;
     case CLC_OPEN_WOUNDS:
 	if (Antimagic) {
 	    shieldeff(u.ux, u.uy);
+		 monstseesu(M_SEEN_MAGR);
 	    dmg = (dmg + 1) / 2;
 	}
@@ -675,4 +903,8 @@
 	case MGC_HASTE_SELF:
 	case MGC_CURE_SELF:
+	case MGC_FLY:
+	case MGC_ENRAGE:
+	case MGC_FIRE_BOLT:
+	case MGC_ICE_BOLT:
 	    return TRUE;
 	default:
@@ -683,4 +915,5 @@
 	case CLC_INSECTS:
 	case CLC_CURE_SELF:
+	case CLC_FLY:
 	    return TRUE;
 	default:
@@ -691,4 +924,29 @@
 }
 
+STATIC_DCL
+void
+cast_fly(mtmp)
+struct monst* mtmp;
+{
+	struct trap* tr;
+	char msg[200];
+
+	if (!mtmp->mflying) {
+		mtmp->mflying = TRUE;
+		if (mtmp->mtrapped) {
+			tr = t_at(mtmp->mx,mtmp->my);
+			if (tr && (tr->ttyp == PIT || tr->ttyp == SPIKED_PIT)) {
+				sprintf(msg,"%s rises up, out of the pit!",Monnam(mtmp));
+				mtmp->mtrapped = FALSE;
+			}
+		} else {
+			sprintf(msg,"%s rises into the air!",Monnam(mtmp));
+		}
+		if (canseemon(mtmp)) { pline(msg); }
+	} else {
+		impossible("No reason to cast 'fly' spell?");
+	}
+}
+
 /* Some spells are useless under some circumstances. */
 STATIC_DCL
@@ -734,4 +992,27 @@
 						&& spellnum == MGC_CLONE_WIZ)
 	    return TRUE;
+		/* don't lift off if we're already in the air or just-peaceful
+		* ...but go ahead and let pets do it */
+		if ((is_flyer(mtmp->data) || is_flying(mtmp) || 
+					(mtmp->mpeaceful && !mtmp->mtame)) && spellnum == MGC_FLY)
+			return TRUE;
+		/* Don't go making everything else bonkers if you're peaceful! */
+		if (spellnum == MGC_ENRAGE && (mtmp->mpeaceful || mtmp->mtame)) {
+			return TRUE;
+		}
+		/* Don't waste time zapping resisted spells at the player,
+		* and don't blast ourselves with our own explosions */
+		if ((m_seenres(mtmp,M_SEEN_FIRE) || distu(mtmp->mx,mtmp->my) < 2) && 
+				spellnum == MGC_FIRE_BOLT) {
+			return TRUE;
+		}
+		if ((m_seenres(mtmp,M_SEEN_COLD) || distu(mtmp->mx,mtmp->my) < 2) && 
+				spellnum == MGC_ICE_BOLT) {
+			return TRUE;
+		}
+		if ((spellnum == MGC_ICE_BOLT || spellnum == MGC_FIRE_BOLT) && mtmp->mpeaceful)
+		{
+			return TRUE;
+		}
     } else if (adtyp == AD_CLRC) {
 	/* summon insects/sticks to snakes won't be cast by peaceful monsters */
@@ -747,4 +1028,9 @@
 	if (Blinded && spellnum == CLC_BLIND_YOU)
 	    return TRUE;
+		/* don't lift off if we're already in the air or just-peaceful
+		* ...but go ahead and let pets do it */
+		if ((is_flyer(mtmp->data) || is_flying(mtmp) || 
+					(mtmp->mpeaceful && !mtmp->mtame)) && spellnum == CLC_FLY)
+			return TRUE;
     }
     return FALSE;
@@ -772,5 +1058,5 @@
 	}
 	if(lined_up(mtmp) && rn2(3)) {
-	    nomul(0);
+	    nomul(0, 0);
 	    if(mattk->adtyp && (mattk->adtyp < 11)) { /* no cf unsigned >0 */
 		if(canseemon(mtmp))
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/src/mhitm.c nethack/src/mhitm.c
--- nh_orig/src/mhitm.c	2003-12-07 18:39:13.000000000 -0500
+++ nethack/src/mhitm.c	2009-08-02 13:49:38.694407876 -0400
@@ -112,7 +112,20 @@
 	nmon = 0;
 #endif
+
 	/* perhaps the monster will resist Conflict */
-	if(resist(mtmp, RING_CLASS, 0, 0))
-	    return(0);
+
+	/* In practice, this should be suffixed with "... but probably not".  
+	 * The old MR check was just letting too many monsters avoid being hit with
+	 * conflict in the first place; the ones that didn't resist basically swarmed under
+	 * the ones that did, allowing the player to blithely walk through a street brawl
+	 * almost totally untouched.  Not so anymore.
+	 *
+	 * Resistance is based on the player's (mostly-useless) Charisma.  High-CHA players
+	 * will be able to 'convince' monsters (through the magic of the ring, of course) to fight
+	 * for them much more easily than low-CHA players. */
+
+	/*if(resist(mtmp, RING_CLASS, 0, 0)) return(0);*/
+
+	if (resist_conflict(mtmp)) return 0;
 
 	if(u.ustuck == mtmp) {
@@ -171,4 +184,17 @@
 }
 
+
+boolean
+resist_conflict(mtmp)
+struct monst* mtmp;
+{
+	int resist_chance;
+
+	resist_chance = ACURR(A_CHA) - mtmp->m_lev + u.ulevel;
+	if (resist_chance > 19) resist_chance = 19;		/* always a small chance */
+	return (rnd(20) > resist_chance);
+
+}
+
 /*
  * mattackm() -- a monster attacks another monster.
@@ -789,5 +815,5 @@
 		}
 		if (!rn2(30)) erode_armor(mdef, TRUE);
-		if (!rn2(6)) erode_obj(MON_WEP(mdef), TRUE, TRUE);
+		if (!rn2(6)) _erode_obj(MON_WEP(mdef),AD_ACID);
 		break;
 	    case AD_RUST:
@@ -852,4 +878,8 @@
 		if (!cancelled && tmp < mdef->mhp && !tele_restrict(mdef)) {
 		    char mdef_Monnam[BUFSZ];
+			/* works on other critters too.. */
+			if (magr->mnum == PM_BOOJUM) {
+				mdef->perminvis = mdef->minvis = TRUE;
+			}
 		    /* save the name before monster teleports, otherwise
 		       we'll get "it" in the suddenly disappears message */
@@ -990,5 +1020,9 @@
 		break;
 	    case AD_DRLI:
-		if (!cancelled && !rn2(3) && !resists_drli(mdef)) {
+		 case AD_DETH:
+		/* Closest match; save us having to do a lot of silliness 
+		 * just to handle one critter on Astral */
+		if (mattk->adtyp == AD_DETH || 
+				(!cancelled && !rn2(3) && !resists_drli(mdef))) {
 			tmp = d(2,6);
 			if (vis)
@@ -1132,5 +1166,5 @@
 	if(!tmp) return(MM_MISS);
 
-	if((mdef->mhp -= tmp) < 1) {
+	if(damage_mon(mdef,tmp,mattk->adtyp)) {
 	    if (m_at(mdef->mx, mdef->my) == magr) {  /* see gulpmm() */
 		remove_monster(mdef->mx, mdef->my);
@@ -1387,4 +1421,13 @@
 		    pline("%s is suddenly very hot!", Monnam(magr));
 		break;
+		 case AD_DISE:
+			if (canseemon(magr)) {
+				pline("%s is covered with tiny spores!", Monnam(magr));
+			}
+			if (resists_sick(magr)) {
+				pline("%s doesn't seem to notice the spores.", Monnam(magr));
+				tmp = 0;
+			} 
+		break;
 	    case AD_ELEC:
 		if (resists_elec(magr)) {
@@ -1405,5 +1448,5 @@
 
     assess_dmg:
-	if((magr->mhp -= tmp) <= 0) {
+	if(damage_mon(magr,tmp,(int)mddat->mattk[i].adtyp)) {
 		monkilled(magr, "", (int)mddat->mattk[i].adtyp);
 		return (mdead | mhit | MM_AGR_DIED);
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/src/mhitu.c nethack/src/mhitu.c
--- nh_orig/src/mhitu.c	2003-12-07 18:39:13.000000000 -0500
+++ nethack/src/mhitu.c	2009-11-23 12:36:46.974399341 -0500
@@ -27,4 +27,5 @@
 STATIC_DCL void FDECL(mswings,(struct monst *,struct obj *));
 STATIC_DCL void FDECL(wildmiss, (struct monst *,struct attack *));
+STATIC_DCL int FDECL(mon_scream, (struct monst*,struct attack*));
 
 STATIC_DCL void FDECL(hurtarmor,(int));
@@ -133,13 +134,15 @@
 }
 
-/* called when your intrinsic speed is taken away */
+/* called when you get artificially slowed for some reason */
 void
 u_slow_down()
 {
-	HFast = 0L;
-	if (!Fast)
+	if (!Fast && !Slow)
 	    You("slow down.");
-	else	/* speed boots */
-	    Your("quickness feels less natural.");
+	else if (!Slow)			 /* speed of some sort */
+	    You("feel a strange lethargy overcome you.");
+	else
+		Your("lethargy seems to be settling in for the long haul.");
+	incr_itimeout(&HSlow,rnd(11)+9);
 	exercise(A_DEX, FALSE);
 }
@@ -318,5 +321,5 @@
 		 */
 	
-	if(!ranged) nomul(0);
+	if(!ranged) nomul(0, 0);
 	if(mtmp->mhp <= 0 || (Underwater && !is_swimmer(mtmp->data)))
 	    return(0);
@@ -387,5 +390,5 @@
 			    pline("%s is hit by a falling piercer (you)!",
 								Monnam(mtmp));
-			    if ((mtmp->mhp -= d(3,6)) < 1)
+			    if (damage_mon(mtmp,d(3,6),AD_PHYS))
 				killed(mtmp);
 			} else
@@ -467,4 +470,5 @@
 		tmp -= 2;
 	if(mtmp->mtrapped) tmp -= 2;
+	if (is_accurate(mdat)) tmp += 5;	  /* eagle-eyed monsters get a bonus */
 	if(tmp <= 0) tmp = 1;
 
@@ -676,4 +680,10 @@
 			break;
 
+		case AT_SCRE:
+			if (ranged) {
+				sum[i] = mon_scream(mtmp, mattk);
+			}
+			/* if you're nice and close, don't bother */
+			break;
 		default:		/* no attack */
 			break;
@@ -905,6 +915,12 @@
 /*	First determine the base damage done */
 	dmg = d((int)mattk->damn, (int)mattk->damd);
-	if(is_undead(mdat) && midnight())
-		dmg += d((int)mattk->damn, (int)mattk->damd); /* extra damage */
+
+	/* undead do extra damage in the witching hour;
+	 * berserk monsters always do extra damage;
+	 * and elementals on their home plane hit really hard */
+	if((is_undead(mdat) && midnight()) || mtmp->mberserk ||
+			(is_home_elemental(mdat) && mtmp->mnum != PM_AIR_ELEMENTAL)) {
+		dmg += d((int)mattk->damn, (int)mattk->damd);
+	}
 
 /*	Next a cancellation factor	*/
@@ -913,5 +929,5 @@
  */
 	armpro = magic_negation(&youmonst);
-	uncancelled = !mtmp->mcan && ((rn2(3) >= armpro) || !rn2(50));
+	uncancelled = !mtmp->mcan && ((rn2(3) >= armpro) || !rn2(45));
 
 	permdmg = 0;
@@ -985,7 +1001,10 @@
 			    rehumanize();
 			    break;
-		    } else if (Fire_resistance) {
+		    } else if (how_resistant(FIRE_RES) == 100) {
 			pline_The("fire doesn't feel hot!");
+				monstseesu(M_SEEN_FIRE);
 			dmg = 0;
+		    } else {
+				 dmg = resist_reduce(dmg,FIRE_RES);
 		    }
 		    if((int) mtmp->m_lev > rn2(20))
@@ -1002,7 +1021,10 @@
 		if (uncancelled) {
 		    pline("You're covered in frost!");
-		    if (Cold_resistance) {
+				if (how_resistant(COLD_RES) == 100) {
 			pline_The("frost doesn't seem cold!");
+					monstseesu(M_SEEN_COLD);
 			dmg = 0;
+				} else {
+					dmg = resist_reduce(dmg,COLD_RES);
 		    }
 		    if((int) mtmp->m_lev > rn2(20))
@@ -1014,7 +1036,10 @@
 		if (uncancelled) {
 		    You("get zapped!");
-		    if (Shock_resistance) {
+		    if (how_resistant(SHOCK_RES) == 100) {
 			pline_The("zap doesn't shock you!");
+				monstseesu(M_SEEN_ELEC);
 			dmg = 0;
+		    } else {
+				 dmg = resist_reduce(dmg,SHOCK_RES);
 		    }
 		    if((int) mtmp->m_lev > rn2(20))
@@ -1027,6 +1052,9 @@
 		hitmsg(mtmp, mattk);
 		if (uncancelled && multi >= 0 && !rn2(5)) {
-		    if (Sleep_resistance) break;
-		    fall_asleep(-rnd(10), TRUE);
+		    if (how_resistant(SLEEP_RES) == 100) {
+				monstseesu(M_SEEN_SLEEP);
+				 break;
+			 }
+		    fall_asleep(-resist_reduce(rnd(10),SLEEP_RES), TRUE);
 		    if (Blind) You("are put to sleep!");
 		    else You("are put to sleep by %s!", mon_nam(mtmp));
@@ -1103,4 +1131,5 @@
 			    killer = "brainlessness";
 			    killer_format = KILLED_BY;
+				 ukiller = mtmp;
 			    done(DIED);
 			    lifesaved++;
@@ -1123,5 +1152,5 @@
 			else You("are frozen by %s!", mon_nam(mtmp));
 			nomovemsg = 0;	/* default: "you can move again" */
-			nomul(-rnd(10));
+			nomul(-rnd(10), "paralyzed by a monster");
 			exercise(A_DEX, FALSE);
 		    }
@@ -1187,6 +1216,5 @@
 			if (flags.soundok)
 			    You_hear("%s hissing!", s_suffix(mon_nam(mtmp)));
-			if(!rn2(10) ||
-			    (flags.moonphase == NEW_MOON && !have_lizard())) {
+			if(!rn2(3) || (flags.moonphase == NEW_MOON && !have_lizard())) {
  do_stone:
 			    if (!Stoned && !Stone_resistance
@@ -1338,7 +1366,24 @@
 	    case AD_TLPT:
 		hitmsg(mtmp, mattk);
-		if (uncancelled) {
+		if (uncancelled || mtmp->mnum == PM_BOOJUM) {
+			/* "But oh, beamish nephew, beware of the day
+			 * if your Snark be a Boojum!  For then
+			 * You will softly and suddenly vanish away,
+			 * And never be met with again!" */
+			if (mtmp->mnum == PM_BOOJUM) {
+				/* depending on what we are or if we can't teleport,
+				 * display appropriate messages */
+				if (!level.flags.noteleport) {
+					You("suddenly vanish!");
+				} else {
+					if (!Invis) {
+						You("suddenly %s!",See_invisible ? "become transparent" : "vanish");
+					}
+				}
+				incr_itimeout(&HInvis, d(6,100));   /* In multiple senses of 'vanish' :) */
+			} else {
 		    if(flags.verbose)
 			Your("position suddenly seems very uncertain!");
+			}
 		    tele();
 		}
@@ -1388,6 +1433,5 @@
 			u.mh += rnd(7);
 			if (!rn2(7)) {
-			    /* no upper limit necessary; effect is temporary */
-			    u.mhmax++;
+				gainmaxhp(1);
 			    if (!rn2(13)) goaway = TRUE;
 			}
@@ -1398,5 +1442,5 @@
 			    /* hard upper limit via nurse care: 25 * ulevel */
 			    if (u.uhpmax < 5 * u.ulevel + d(2 * u.ulevel, 10))
-				u.uhpmax++;
+					 gainmaxhp(1);
 			    if (!rn2(13)) goaway = TRUE;
 			}
@@ -1450,7 +1494,8 @@
 	    case AD_ACID:
 		hitmsg(mtmp, mattk);
-		if (!mtmp->mcan && !rn2(3))
+			if (!mtmp->mcan && !rn2(3)) {
 		    if (Acid_resistance) {
 			pline("You're covered in acid, but it seems harmless.");
+					monstseesu(M_SEEN_ACID);
 			dmg = 0;
 		    } else {
@@ -1458,5 +1503,7 @@
 			exercise(A_STR, FALSE);
 		    }
-		else		dmg = 0;
+			} else {	
+				dmg /= 2;	/* less painful... */
+			}
 		break;
 	    case AD_SLOW:
@@ -1495,4 +1542,5 @@
 			killer_format = KILLED_BY_AN;
 			killer = "touch of death";
+			ukiller = mtmp;
 			done(DIED);
 			dmg = 0;
@@ -1584,4 +1632,6 @@
 		 * Never reduces hpmax below 1 hit point per level.
 		 */
+
+		/* this doesn't need to go through gainmaxhp - 7/29/07 DSR */
 		permdmg = rn2(dmg / 2 + 1);
 		if (Upolyd || u.uhpmax > 25 * u.ulevel) permdmg = dmg;
@@ -1731,4 +1781,5 @@
 		    if (Acid_resistance) {
 			You("are covered with a seemingly harmless goo.");
+			monstseesu(M_SEEN_ACID);
 			tmp = 0;
 		    } else {
@@ -1753,9 +1804,12 @@
 		    if(!mtmp->mcan && rn2(2)) {
 			pline_The("air around you crackles with electricity.");
-			if (Shock_resistance) {
+				if (how_resistant(SHOCK_RES) == 100) {
 				shieldeff(u.ux, u.uy);
 				You("seem unhurt.");
+					monstseesu(M_SEEN_ELEC);
 				ugolemeffects(AD_ELEC,tmp);
 				tmp = 0;
+				} else {
+					tmp = resist_reduce(tmp,SHOCK_RES);
 			}
 		    } else tmp = 0;
@@ -1763,20 +1817,28 @@
 		case AD_COLD:
 		    if(!mtmp->mcan && rn2(2)) {
-			if (Cold_resistance) {
+				if (how_resistant(COLD_RES) == 100) {
 				shieldeff(u.ux, u.uy);
 				You_feel("mildly chilly.");
+					monstseesu(M_SEEN_COLD);
 				ugolemeffects(AD_COLD,tmp);
 				tmp = 0;
-			} else You("are freezing to death!");
+				} else {
+					You("are freezing to death!");
+					tmp = resist_reduce(tmp,COLD_RES);
+				}
 		    } else tmp = 0;
 		    break;
 		case AD_FIRE:
 		    if(!mtmp->mcan && rn2(2)) {
-			if (Fire_resistance) {
+				if (how_resistant(FIRE_RES) == 100) {
 				shieldeff(u.ux, u.uy);
 				You_feel("mildly hot.");
+					monstseesu(M_SEEN_FIRE);
 				ugolemeffects(AD_FIRE,tmp);
 				tmp = 0;
-			} else You("are burning to a crisp!");
+				} else { 
+					You("are burning to a crisp!");
+					tmp = resist_reduce(tmp,FIRE_RES);
+				}
 			burn_away_slime();
 		    } else tmp = 0;
@@ -1795,4 +1857,7 @@
 	if (tmp) stop_occupation();
 
+	/* glomp attacks should still trigger these effects */
+	passiveum(youmonst.data,mtmp,mattk);
+
 	if (touch_petrifies(youmonst.data) && !resists_ston(mtmp)) {
 	    pline("%s very hurriedly %s you!", Monnam(mtmp),
@@ -1830,11 +1895,11 @@
 	switch (mattk->adtyp) {
 	    case AD_COLD:
-		not_affected |= Cold_resistance;
+		not_affected |= (how_resistant(COLD_RES) == 100);
 		goto common;
 	    case AD_FIRE:
-		not_affected |= Fire_resistance;
+		not_affected |= (how_resistant(FIRE_RES) == 100);
 		goto common;
 	    case AD_ELEC:
-		not_affected |= Shock_resistance;
+		not_affected |= (how_resistant(SHOCK_RES) == 100);
 common:
 
@@ -1849,4 +1914,6 @@
 		    if (Half_physical_damage) tmp = (tmp+1) / 2;
 		    mdamageu(mtmp, tmp);
+		} else {
+			monstseesu(1 << (mattk->adtyp-1));	 /* we seeee you */
 		}
 		break;
@@ -1953,9 +2020,10 @@
 
 		    mtmp->mspec_used = mtmp->mspec_used + (conf + rn2(6));
+			 if (!Confusion_resistance) {
 		    if(!Confusion)
-			pline("%s gaze confuses you!",
-			                  s_suffix(Monnam(mtmp)));
+					pline("%s gaze confuses you!", s_suffix(Monnam(mtmp)));
 		    else
 			You("are getting more and more confused.");
+			 }
 		    make_confused(HConfusion + conf, FALSE);
 		    stop_occupation();
@@ -1993,12 +2061,12 @@
 		if (!mtmp->mcan && canseemon(mtmp) &&
 			couldsee(mtmp->mx, mtmp->my) &&
-			mtmp->mcansee && !mtmp->mspec_used && rn2(5)) {
-		    int dmg = d(2,6);
+			mtmp->mcansee && !rn2(2)) {
+		    int dmg = d(mattk->damn,mattk->damd);
 
 		    pline("%s attacks you with a fiery gaze!", Monnam(mtmp));
 		    stop_occupation();
-		    if (Fire_resistance) {
-			pline_The("fire doesn't feel hot!");
-			dmg = 0;
+			 dmg = resist_reduce(dmg,FIRE_RES);
+		    if (dmg < 1) {
+				 monstseesu(M_SEEN_FIRE);
 		    }
 		    burn_away_slime();
@@ -2012,24 +2080,40 @@
 		}
 		break;
-#ifdef PM_BEHOLDER /* work in progress */
+		 case AD_COLD:
+		if (!mtmp->mcan && canseemon(mtmp) &&
+			couldsee(mtmp->mx, mtmp->my) &&
+			mtmp->mcansee && !rn2(2)) {
+		    int dmg = d(mattk->damn,mattk->damd);
+
+		    pline("%s attacks you with a chilling gaze!", Monnam(mtmp));
+		    stop_occupation();
+			 dmg = resist_reduce(dmg,COLD_RES);
+		    if (dmg < 1) {
+				 monstseesu(M_SEEN_COLD);
+		    }
+		    if ((int) mtmp->m_lev > rn2(20))
+			destroy_item(POTION_CLASS, AD_COLD);
+		    if (dmg) mdamageu(mtmp, dmg);
+		}
+		break;
 	    case AD_SLEE:
 		if(!mtmp->mcan && canseemon(mtmp) &&
 		   couldsee(mtmp->mx, mtmp->my) && mtmp->mcansee &&
-		   multi >= 0 && !rn2(5) && !Sleep_resistance) {
-
-		    fall_asleep(-rnd(10), TRUE);
+		   multi >= 0 && rn2(5) && (how_resistant(SLEEP_RES) < 100)) {
+		    fall_asleep(-resist_reduce(d(mattk->damn,mattk->damd),SLEEP_RES), TRUE);
 		    pline("%s gaze makes you very sleepy...",
 			  s_suffix(Monnam(mtmp)));
 		}
+		if (how_resistant(SLEEP_RES) == 100) {
+			monstseesu(M_SEEN_SLEEP);
+		}
 		break;
 	    case AD_SLOW:
 		if(!mtmp->mcan && canseemon(mtmp) && mtmp->mcansee &&
-		   (HFast & (INTRINSIC|TIMEOUT)) &&
-		   !defends(AD_SLOW, uwep) && !rn2(4))
-
+				!Slow && !defends(AD_SLOW, uwep)) {
 		    u_slow_down();
 		    stop_occupation();
+		}
 		break;
-#endif
 	    default: impossible("Gaze attack %d?", mattk->adtyp);
 		break;
@@ -2197,4 +2281,5 @@
 		if (ring==uswapwep) setuswapwep((struct obj *)0);
 		if (ring==uquiver) setuqwep((struct obj *)0);
+		if (ring==ulauncher) setulauncher((struct obj *)0);
 		freeinv(ring);
 		(void) mpickobj(mon,ring);
@@ -2276,9 +2361,13 @@
 	if (u.ualign.type == A_CHAOTIC)
 		adjalign(1);
+	if (u.ualign.type == A_LAWFUL) {
+		pline("You feel a little guilty about doing this...");
+		minor_sin();
+	}
 
 	/* by this point you have discovered mon's identity, blind or not... */
 	pline("Time stands still while you and %s lie in each other's arms...",
 		noit_mon_nam(mon));
-	if (rn2(35) > ACURR(A_CHA) + ACURR(A_INT)) {
+	if (rn2(40) > ACURR(A_CHA) + ACURR(A_INT)) {
 		/* Don't bother with mspec_used here... it didn't get tired! */
 		pline("%s seems to have enjoyed it more than you...",
@@ -2324,7 +2413,8 @@
 		    noit_mon_nam(mon));
 		switch (rn2(5)) {
-		case 0: You_feel("raised to your full potential.");
+		case 0: You_feel("full of new energy!");
 			exercise(A_CON, TRUE);
-			u.uen = (u.uenmax += rnd(5));
+			u.uen += (rnd((u.uenmax/5)+1));
+			if (u.uen > u.uenmax) u.uen = u.uenmax;
 			break;
 		case 1: You_feel("good enough to do it again.");
@@ -2446,4 +2536,52 @@
 
 STATIC_OVL int
+mon_scream(mtmp,mattk)
+struct monst* mtmp;
+struct attack* mattk;
+{
+	int effect = 0;
+	int dmg = d(mattk->damn,mattk->damd);
+
+	switch (mattk->adtyp) {
+		case AD_STUN:
+			/* don't let stuff use this every turn */ 
+			if (mtmp->mspec_used) {
+				return 0;
+			}
+			/* Only do this when we're _close_ to the player */
+			if (distu(mtmp->mx,mtmp->my) > 100)
+			{
+				return 0;
+			}
+			if (mtmp->mcan) {
+				if (canseemon(mtmp)) {
+					pline("%s croaks hoarsely.",Monnam(mtmp));
+				} else {
+					You_hear("a frog nearby.");
+				}
+			} else {
+				if (canseemon(mtmp)) {
+					pline("%s screams!",Monnam(mtmp));
+				} else {
+					You_hear("a horrific scream!");
+				}
+				if (u.usleep) { unmul("You are shocked awake!"); }
+				if (!Stun_resistance) {
+					Your("mind reels from the noise!");
+					effect = 1;
+				}
+				make_stunned(dmg,FALSE);	/* Stun resistance checked inside */
+			}
+			mtmp->mspec_used = 2 + rn2(3);
+			break;
+		default:
+			break;
+	}
+
+	return effect;
+}
+
+
+STATIC_OVL int
 passiveum(olduasmon,mtmp,mattk)
 struct permonst *olduasmon;
@@ -2452,4 +2590,55 @@
 {
 	int i, tmp;
+	char plurbuf[BUFSZ];
+
+	/* Putting this in this way is kind of ugly but most of the alternatives are worse;
+	 * at least this way there's a hook available for use.
+	 *
+	 * Yes, the dragons themselves don't get these effects, for good reason. */
+	if (uarm) {
+		switch(uarm->otyp) {
+			case GREEN_DRAGON_SCALE_MAIL:
+			case GREEN_DRAGON_SCALES:
+				if (resists_poison(mtmp)) { return 1; }
+				i = rn2(20);
+				if (i) { 
+					damage_mon(mtmp,rnd(6),AD_DRST);
+					if (rn2(3) || mtmp->mhp < 1) { pline("%s staggers from the poison!",Monnam(mtmp)); }
+				}
+				else { 
+					mtmp->mhp = -1; 
+					pline("%s is fatally poisoned!",Monnam(mtmp));
+				}
+				if (mtmp->mhp < 1) {
+					xkilled(mtmp,1);
+					return 2;  /* let the chain upstream know it died */
+				}
+				return 1;
+				break;
+			case ORANGE_DRAGON_SCALE_MAIL:
+			case ORANGE_DRAGON_SCALES:
+				if (resists_sleep(mtmp)) { return 1; }
+				if (canseemon(mtmp) && mtmp->mspeed != MSLOW) {
+					pline("%s looks a little sleepy...",Monnam(mtmp));
+				}
+				mtmp->mspeed = MSLOW;
+				return 1;
+				break;
+			case BLACK_DRAGON_SCALE_MAIL:
+			case BLACK_DRAGON_SCALES:
+				if (!haseyes(mtmp->data)) { return 1; }
+				if (canseemon(mtmp) && mtmp->mcansee && rn2(2)) {
+					Sprintf(plurbuf,"%s",s_suffix(Monnam(mtmp)));
+					pline("%s eye%s veiled with darkness!",plurbuf,
+							eyecount(mtmp->data) > 1 ? "s are" : " is");
+				}
+				mtmp->mcansee = 0;
+				mtmp->mblinded += rnd(20);
+				return 1;
+				break;
+			default:	  /* all other types of armor, just pass on through */
+				break;
+		}
+	}
 
 	for (i = 0; ; i++) {
@@ -2477,5 +2666,5 @@
 		} else tmp = 0;
 		if (!rn2(30)) erode_armor(mtmp, TRUE);
-		if (!rn2(6)) erode_obj(MON_WEP(mtmp), TRUE, TRUE);
+		if (!rn2(6)) _erode_obj(MON_WEP(mtmp),AD_ACID);
 		goto assess_dmg;
 	    case AD_STON: /* cockatrice */
@@ -2597,5 +2786,5 @@
 
     assess_dmg:
-	if((mtmp->mhp -= tmp) <= 0) {
+	if(damage_mon(mtmp,tmp,youmonst.data->mattk[i].adtyp)) {
 		pline("%s dies!", Monnam(mtmp));
 		xkilled(mtmp,0);
@@ -2622,6 +2811,9 @@
 	initedog(mon);
 	mon->m_lev = youmonst.data->mlevel;
-	mon->mhpmax = u.mhmax;
+	mon->mhpmax = u.mhmax / 2;
 	mon->mhp = u.mh / 2;
+	/* just in case */
+	if (mon->mhpmax < 1) mon->mhpmax = 1;
+	if (mon->mhp < 1) mon->mhp = 1;
 	u.mh -= mon->mhp;
 	flags.botl = 1;
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/src/minion.c nethack/src/minion.c
--- nh_orig/src/minion.c	2003-12-07 18:39:13.000000000 -0500
+++ nethack/src/minion.c	2010-08-16 13:20:13.436709737 -0400
@@ -16,4 +16,10 @@
 	struct monst *mtmp;
 
+	/* Wielded Demonbane prevents demons from gating in others. */
+	if (uwep && uwep->oartifact == ART_DEMONBANE && is_demon(mon->data)) {
+		pline("%s looks puzzled for a moment.",Monnam(mon));
+		return;
+	}
+
 	if (mon) {
 	    ptr = mon->data;
@@ -127,4 +133,5 @@
     if (mon) {
 	if (talk) {
+	    if (flags.soundok)
 	    pline_The("voice of %s booms:", align_gname(alignment));
 	    verbalize("Thou shalt pay for thy indiscretion!");
@@ -165,13 +172,23 @@
 	    return(1);
 	}
-#ifndef GOLDOBJ
-	cash = u.ugold;
-#else
-	cash = money_cnt(invent);
-#endif
+
+	/* This isn't _that_ much better than the old way, but it removes
+	 * the trivial case of people being able to bribe demons with 
+	 * 10 gold pieces to bypass him.  You can still carry lots of gold,
+	 * of course, but at least now you have to lug it with you. */
+	do {
+		cash = rnd(15000) + 5000;
+
 	demand = (cash * (rnd(80) + 20 * Athome)) /
 	    (100 * (1 + (sgn(u.ualign.type) == sgn(mtmp->data->maligntyp))));
+	} while (demand < 3000);
 
-	if (!demand) {		/* you have no gold */
+	if (
+#ifndef GOLDOBJ
+			u.ugold == 0
+#else
+			money_cnt(invent) == 0
+#endif
+			) {						  /* you have no gold */
 	    mtmp->mpeaceful = 0;
 	    set_malign(mtmp);
@@ -182,5 +199,11 @@
 	       and removed from the game (along with said Amulet...) */
 	    if (mon_has_amulet(mtmp))
-		demand = cash + (long)rn1(1000,40);
+			demand = 
+#ifndef GOLDOBJ
+				u.ugold
+#else
+				money_cnt(invent)
+#endif
+				+ (long)rn1(10000,40);
 
 	    pline("%s demands %ld %s for safe passage.",
@@ -208,5 +231,5 @@
 struct monst *mtmp;
 {
-	char buf[BUFSZ];
+	char buf[BUFSZ] = "";
 	long offer;
 #ifdef GOLDOBJ
@@ -267,4 +290,12 @@
 aligntyp atyp;
 {
+	/*
+	 * This code is ridiculous given that there are exactly two demon lords who
+	 * could be summoned by this -- Yeenoghu and Juiblex.
+	 *
+	 * With the Juiblex changes, this means we don't want him to get summoned
+	 * by accident anywhere, so all of this code now becomes "Check for Yeeny;
+	 * is Yeeny available?  No?  Send in a dingus."
+	 *
 	int tryct, pm;
 
@@ -275,5 +306,13 @@
 		return(pm);
 	}
-	return(ndemon(atyp));	/* approximate */
+
+	*/
+
+	if (!(mvitals[PM_YEENOGHU].mvflags & G_GONE) && 
+			(atyp == A_NONE || sgn(mons[PM_YEENOGHU].maligntyp) == sgn(atyp))) {
+		return PM_YEENOGHU;
+	}
+
+	return(ndemon(atyp));	/* launch the dingus! */
 }
 
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/src/mklev.c nethack/src/mklev.c
--- nh_orig/src/mklev.c	2003-12-07 18:39:13.000000000 -0500
+++ nethack/src/mklev.c	2010-05-01 11:04:47.121714657 -0400
@@ -23,4 +23,6 @@
 STATIC_DCL void FDECL(mksink,(struct mkroom *));
 #endif
+STATIC_DCL void FDECL(mktree,(struct mkroom*));
+STATIC_DCL void FDECL(mkbrazier,(struct mkroom*));
 STATIC_DCL void FDECL(mkaltar,(struct mkroom *));
 STATIC_DCL void FDECL(mkgrave,(struct mkroom *));
@@ -51,5 +53,4 @@
 #define do_vault()	(vault_x != -1)
 static xchar		vault_x, vault_y;
-boolean goldseen;
 static boolean made_branch;	/* used only during level creation */
 
@@ -181,6 +182,7 @@
 		levl[lowx-1][hiy+1].typ = BLCORNER;
 		levl[hix+1][hiy+1].typ = BRCORNER;
-	    } else {	/* a subroom */
 		wallification(lowx-1, lowy-1, hix+1, hiy+1);
+	    } else {	/* a subroom */
+		wallification(lowx, lowy, hix, hiy); /* this is bugs */
 	    }
 	}
@@ -224,4 +226,64 @@
 }
 
+void
+mk_split_room()
+{
+    NhRect *r1 = rnd_rect();
+    NhRect r2;
+    int area;
+    xchar hx, hy, lx, ly, wid, hei;
+    xchar rlit;
+    struct mkroom *troom;
+
+    if (!r1) return;
+
+    wid = rn1(12, 5);
+    hei = rn1(3, 5);
+
+    hx = (r1->hx - r1->lx - wid - 2);
+    hy = (r1->hy - r1->ly - hei - 2);
+
+    lx = ((hx < 1) ? 0 : rn2(hx)) + 1;
+    ly = ((hy < 1) ? 0 : rn2(hy)) + 1;
+
+    area = wid*hei;
+    if (!check_room(&lx, &wid, &ly, &hei, FALSE)) return;
+    if (wid < 5 || hei < 5) return;
+
+    r2.lx = lx;
+    r2.ly = ly;
+    r2.hx = lx + wid;
+    r2.hy = ly + hei;
+    split_rects(r1, &r2);
+    smeq[nroom] = nroom;
+    if ((wid > hei) || (wid == hei && rn2(2))) {
+	int adj = (wid/2);
+	rlit = (rnd(1+abs(depth(&u.uz))) < 11 && rn2(77)) ? TRUE : FALSE;
+	add_room(lx,     ly, lx+adj-1,     ly+hei, rlit, OROOM, FALSE);
+	smeq[nroom] = nroom;
+	rlit = (rnd(1+abs(depth(&u.uz))) < 11 && rn2(77)) ? TRUE : FALSE;
+	troom = &rooms[nroom];
+#ifdef SPECIALIZATION
+	topologize(troom,FALSE);              /* set roomno */
+#else
+	topologize(troom);                    /* set roomno */
+#endif
+	add_room(lx+adj+1, ly, lx+adj+adj, ly+hei, rlit, OROOM, FALSE);
+    } else {
+	int adj = (hei/2);
+	rlit = (rnd(1+abs(depth(&u.uz))) < 11 && rn2(77)) ? TRUE : FALSE;
+	add_room(lx, ly,     lx+wid, ly+adj-1,     rlit, OROOM, FALSE);
+	smeq[nroom] = nroom;
+	rlit = (rnd(1+abs(depth(&u.uz))) < 11 && rn2(77)) ? TRUE : FALSE;
+	troom = &rooms[nroom];
+#ifdef SPECIALIZATION
+	topologize(troom,FALSE);              /* set roomno */
+#else
+	topologize(troom);                    /* set roomno */
+#endif
+	add_room(lx, ly+adj+1, lx+wid, ly+adj+adj, rlit, OROOM, FALSE);
+    }
+}
+
 STATIC_OVL void
 makerooms()
@@ -239,7 +301,13 @@
 				rooms[nroom].hx = -1;
 			}
-		} else
+		} else {
+		    switch (rn2(8)) {
+		    default:
 		    if (!create_room(-1, -1, -1, -1, -1, -1, OROOM, -1))
 			return;
+			break;
+		    case 0: mk_split_room(); break;
+		    }
+		}
 	}
 	return;
@@ -319,9 +387,15 @@
 
 void
-makecorridors()
+makecorridors(style)
+int style;
 {
 	int a, b, i;
 	boolean any = TRUE;
 
+	if (style == -1) style = rn2(4);
+
+	switch (style) {
+
+	default: /* vanilla style */
 	for(a = 0; a < nroom-1; a++) {
 		join(a, a+1, FALSE);
@@ -346,4 +420,38 @@
 		join(a, b, TRUE);
 	    }
+	break;
+	case 1: /* at least one corridor leaves from each room and goes to random room */
+	    if (nroom > 1) {
+		int cnt = 0;
+		for (a = 0; a < nroom; a++) {
+		    do {
+			b = rn2(nroom-1);
+		    } while (((a == b) || (rooms[b].doorct)) && cnt++ < 100);
+		    if (cnt >= 100) {
+			for (b = 0; b < nroom-1; b++)
+			    if (!rooms[b].doorct && (a != b)) break;
+		    }
+		    if (a == b) b++;
+		    join(a, b, FALSE);
+		}
+	    }
+	    break;
+	case 2: /* circular path: room1 -> room2 -> room3 -> ... -> room1  */
+	    if (nroom > 1) {
+		for (a = 0; a < nroom; a++) {
+		    b = (a + 1) % nroom;
+		    join(a, b, FALSE);
+		}
+	    }
+	    break;
+	case 3: /* all roads lead to rome. or to the first room. */
+	    if (nroom > 1) {
+		b = 0;
+		for (a = 1; a < nroom; a++) {
+		    join(a, b, FALSE);
+		}
+	    }
+	    break;
+	}
 }
 
@@ -456,5 +564,5 @@
 			"Vlad was here", "ad aerarium", "ad aerarium",
 			(char *)0, (char *)0, (char *)0, (char *)0, (char *)0,
-			(char *)0,
+			(char *)0, (char *)0,
 };
 
@@ -488,6 +596,9 @@
 			if (trap_type != ROCKTRAP) ttmp->once = 1;
 			if (trap_engravings[trap_type]) {
-			    make_engr_at(xx, yy-dy,
-				     trap_engravings[trap_type], 0L, DUST);
+				if (level.flags.vault_is_aquarium) {
+					make_engr_at(xx, yy-dy,"ad aquarium",0L, DUST);
+				} else {
+			    make_engr_at(xx, yy-dy, trap_engravings[trap_type], 0L, DUST);
+				}
 			    wipe_engr_at(xx, yy-dy, 5); /* age it a little */
 			}
@@ -500,4 +611,12 @@
 		    dosdoor(xx, yy, aroom, rn2(5) ? SDOOR : DOOR);
 		else {
+		    if (!rn2(2) && IS_WALL(levl[xx][yy].typ)) {
+			levl[xx][yy].typ = IRONBARS;
+			if (rn2(3))
+			    (void) mkcorpstat(rn2(2) ? CORPSE : SKULL,
+					      (struct monst *)0,
+					      mkclass(S_HUMAN, 0),
+					      xx, yy+dy, TRUE);
+		    }
 		    if (!level.flags.noteleport)
 			(void) mksobj_at(SCR_TELEPORTATION,
@@ -510,4 +629,36 @@
 }
 
+/* replaces horiz/vert walls with iron bars,
+   iff there's no door next to the place, and there's space
+   on the other side of the wall */
+void
+make_ironbarwalls(chance)
+     int chance;
+{
+    xchar x,y;
+
+    if (chance < 1) return;
+
+    for (x = 1; x < COLNO-1; x++) {
+	for(y = 1; y < ROWNO-1; y++) {
+	    schar typ = levl[x][y].typ;
+	    if (typ == HWALL) {
+		if ((IS_WALL(levl[x-1][y].typ) || levl[x-1][y].typ == IRONBARS) &&
+		    (IS_WALL(levl[x+1][y].typ) || levl[x+1][y].typ == IRONBARS) &&
+		    SPACE_POS(levl[x][y-1].typ) && SPACE_POS(levl[x][y+1].typ) &&
+		    rn2(100) < chance)
+		    levl[x][y].typ = IRONBARS;
+	    } else if (typ == VWALL) {
+		if ((IS_WALL(levl[x][y-1].typ) || levl[x][y-1].typ == IRONBARS) &&
+		    (IS_WALL(levl[x][y+1].typ) || levl[x][y+1].typ == IRONBARS) &&
+		    SPACE_POS(levl[x-1][y].typ) && SPACE_POS(levl[x+1][y].typ) &&
+		    rn2(100) < chance)
+		    levl[x][y].typ = IRONBARS;
+	    }
+	}
+    }
+}
+
+
 STATIC_OVL void
 make_niches()
@@ -566,4 +717,6 @@
 	level.monlist = (struct monst *)0;
 	level.damagelist = (struct damage *)0;
+	level.mon_gen = (struct mon_gen_override *)0;
+	level.sounds = NULL;
 
 	level.flags.nfountains = 0;
@@ -586,4 +739,5 @@
 	level.flags.is_maze_lev = 0;
 	level.flags.is_cavernous_lev = 0;
+	level.flags.stormy = 0;
 
 	nroom = 0;
@@ -609,5 +763,5 @@
 	struct monst *tmonst;	/* always put a web with a spider */
 	branch *branchp;
-	int room_threshold;
+	int room_threshold, boxtype;
 
 	if(wiz1_level.dlevel == 0) init_dungeons();
@@ -648,5 +802,12 @@
 		  (rn2(5) && u.uz.dnum == medusa_level.dnum
 			  && depth(&u.uz) > depth(&medusa_level))) {
+			 /* The vibrating square code is hardcoded into mkmaze --
+			  * rather than fiddle around trying to port it to a 'generalist'
+			  * sort of level, just go ahead and let the VS level be a maze */
+			 if (!Invocation_lev(&u.uz)) {
+				makemaz("hellfill");
+			 } else {
 		    makemaz("");
+			 }
 		    return;
 	    }
@@ -689,7 +850,9 @@
 	if (Is_rogue_level(&u.uz)) goto skip0;
 #endif
-	makecorridors();
+	makecorridors(rn2(10) ? 0 : -1);
 	make_niches();
 
+	if (!rn2(5)) make_ironbarwalls(rn2(20) ? rn2(20) : rn2(50));
+
 	/* make a secret treasure vault, not connected to the rest */
 	if(do_vault()) {
@@ -721,26 +884,46 @@
     {
 	register int u_depth = depth(&u.uz);
-
+		int tmpi = 1;
+		while (tmpi < 4 && !rn2(6)) tmpi++;
+		/* the following code creates approximately the same number of special rooms
+			with the same probabilities as vanilla code.  */
+		do {
+			switch (rn2(26)) {
+				default:
 #ifdef WIZARD
 	if(wizard && nh_getenv("SHOPTYPE")) mkroom(SHOPBASE); else
 #endif
-	if (u_depth > 1 &&
-	    u_depth < depth(&medusa_level) &&
-	    nroom >= room_threshold &&
-	    rn2(u_depth) < 3) mkroom(SHOPBASE);
-	else if (u_depth > 4 && !rn2(6)) mkroom(COURT);
-	else if (u_depth > 5 && !rn2(8) &&
-	   !(mvitals[PM_LEPRECHAUN].mvflags & G_GONE)) mkroom(LEPREHALL);
-	else if (u_depth > 6 && !rn2(7)) mkroom(ZOO);
-	else if (u_depth > 8 && !rn2(5)) mkroom(TEMPLE);
-	else if (u_depth > 9 && !rn2(5) &&
-	   !(mvitals[PM_KILLER_BEE].mvflags & G_GONE)) mkroom(BEEHIVE);
-	else if (u_depth > 11 && !rn2(6)) mkroom(MORGUE);
-	else if (u_depth > 12 && !rn2(8)) mkroom(ANTHOLE);
-	else if (u_depth > 14 && !rn2(4) &&
-	   !(mvitals[PM_SOLDIER].mvflags & G_GONE)) mkroom(BARRACKS);
-	else if (u_depth > 15 && !rn2(6)) mkroom(SWAMP);
-	else if (u_depth > 16 && !rn2(8) &&
-	   !(mvitals[PM_COCKATRICE].mvflags & G_GONE)) mkroom(COCKNEST);
+					if (u_depth > 1 && u_depth < depth(&medusa_level) &&
+						nroom >= room_threshold && rn2(u_depth) < 5) { mkroom(SHOPBASE); break; }
+				case 0:
+					if (u_depth > 4 && !rn2(6)) { mkroom(COURT); break; }
+				case 1:
+					if (u_depth > 5 && !rn2(11) &&
+					!(mvitals[PM_LEPRECHAUN].mvflags & G_GONE)) { mkroom(LEPREHALL); break; }
+				case 2:
+					if (u_depth > 6 && !rn2(12)) { mkroom(ZOO); break; }
+				case 3:
+					if (u_depth > 8 && !rn2(11)) { mkroom(TEMPLE); break; }
+				case 4:
+					if (u_depth > 9 && !rn2(15) &&
+					!(mvitals[PM_KILLER_BEE].mvflags & G_GONE)) { mkroom(BEEHIVE); break; }
+				case 5:
+					if (u_depth > 11 && !rn2(25)) { mkroom(MORGUE); break; }
+				case 6:
+					if (u_depth > 12 && !rn2(27)) { mkroom(ANTHOLE); break; }
+				case 7:
+					if (u_depth > 14 && !rn2(18) &&
+					!(mvitals[PM_SOLDIER].mvflags & G_GONE)) { mkroom(BARRACKS); break; }
+				case 8:
+					if (u_depth > 15 && !rn2(39)) { mkroom(SWAMP); break; }
+				case 9:
+					if (u_depth > 16 && !rn2(94) &&
+					!(mvitals[PM_COCKATRICE].mvflags & G_GONE)) { mkroom(COCKNEST); break; }
+				case 10:
+					if (u_depth > 4 && !rn2(24)) { mkroom(TRAPROOM); break; }
+				case 11:
+					if (u_depth > 4 && !rn2(24)) { mkroom(POOLROOM); break; }
+			}
+		} while (--tmpi >= 0);
     }
 
@@ -769,10 +952,9 @@
 		}
 		/* put traps and mimics inside */
-		goldseen = FALSE;
 		x = 8 - (level_difficulty()/6);
 		if (x <= 1) x = 2;
 		while (!rn2(x))
 		    mktrap(0,0,croom,(coord*)0);
-		if (!goldseen && !rn2(3))
+		if (!rn2(3))
 		    (void) mkgold(0L, somex(croom), somey(croom));
 #ifdef REINCARNATION
@@ -783,4 +965,6 @@
 		if(!rn2(60)) mksink(croom);
 #endif
+		if (christmas() && !rn2(20)) mktree(croom);
+
 		if(!rn2(60)) mkaltar(croom);
 		x = 80 - (depth(&u.uz) * 2);
@@ -788,4 +972,6 @@
 		if(!rn2(x)) mkgrave(croom);
 
+		if (!croom->rlit && !rn2(15)) mkbrazier(croom);
+
 		/* put statues inside */
 		if(!rn2(20))
@@ -793,12 +979,22 @@
 				      (struct permonst *)0,
 				      somex(croom), somey(croom), TRUE);
-		/* put box/chest inside;
+		/* put box/chest/safe inside;
 		 *  40% chance for at least 1 box, regardless of number
 		 *  of rooms; about 5 - 7.5% for 2 boxes, least likely
 		 *  when few rooms; chance for 3 or more is neglible.
+		 *
+		 *  Safes only show up below level 15 since they're not unlockable.
 		 */
-		if(!rn2(nroom * 5 / 2))
-		    (void) mksobj_at((rn2(3)) ? LARGE_BOX : CHEST,
-				     somex(croom), somey(croom), TRUE, FALSE);
+		if(!rn2(nroom * 5 / 2)) {
+			x = rn2(5);
+			if (!x && depth(&u.uz) > 15) {
+				boxtype = IRON_SAFE;
+			} else if (x > 2) {
+				boxtype = CHEST;
+			} else {
+				boxtype = LARGE_BOX;
+			}
+		    (void) mksobj_at(boxtype, somex(croom), somey(croom), TRUE, FALSE);
+		}
 
 		/* maybe make some graffiti */
@@ -810,6 +1006,5 @@
 			    x = somex(croom);  y = somey(croom);
 			} while(levl[x][y].typ != ROOM && !rn2(40));
-			if (!(IS_POOL(levl[x][y].typ) ||
-			      IS_FURNITURE(levl[x][y].typ)))
+			if (!(IS_POOL(levl[x][y].typ) || IS_FURNITURE(levl[x][y].typ)))
 			    make_engr_at(x, y, mesg, 0L, MARK);
 		    }
@@ -819,8 +1014,10 @@
 	skip_nonrogue:
 #endif
-		if(!rn2(3)) {
+		/* Boost object generation here slightly so that later when we
+		 * start encouraging players to use resources, there _are_ some */
+		if(rn2(3)) {
 		    (void) mkobj_at(0, somex(croom), somey(croom), TRUE);
 		    tryct = 0;
-		    while(!rn2(5)) {
+		    while(!rn2(4)) {
 			if(++tryct > 100) {
 			    impossible("tryct overflow4");
@@ -918,4 +1115,67 @@
 }
 
+
+void
+wallwalk_right(x,y,fgtyp,fglit,bgtyp,chance)
+     xchar x,y;
+     schar fgtyp,fglit,bgtyp;
+     int chance;
+{
+    int sx,sy, nx,ny, dir, cnt;
+    schar tmptyp;
+    struct rm *lev;
+    sx = x;
+    sy = y;
+    dir = 1;
+
+    if (!isok(x,y)) return;
+    if (levl[x][y].typ != bgtyp) return;
+
+    do {
+	if (!t_at(x,y) && !bydoor(x,y) && levl[x][y].typ == bgtyp && (chance >= rn2(100))) {
+	    SET_TYPLIT(x,y, fgtyp, fglit);
+	}
+	cnt = 0;
+	do {
+	    nx = x;
+	    ny = y;
+	    switch (dir % 4) {
+	    case 0: y--; break;
+	    case 1: x++; break;
+	    case 2: y++; break;
+	    case 3: x--; break;
+	    }
+	    if (isok(x,y)) {
+		tmptyp = levl[x][y].typ;
+		if (tmptyp != bgtyp && tmptyp != fgtyp) {
+		    dir++; x = nx; y = ny; cnt++;
+		} else {
+		    dir = (dir + 3) % 4;
+		}
+	    } else {
+		dir++; x = nx; y = ny; cnt++;
+	    }
+	} while ((nx == x && ny == y) && (cnt < 5));
+    } while ((x != sx) || (y != sy));
+}
+
+
+void
+mkpoolroom()
+{
+    struct mkroom *sroom;
+    schar typ;
+
+    if (!(sroom = pick_room(TRUE))) return;
+
+    if (sroom->hx - sroom->lx < 3 || sroom->hy - sroom->ly < 3) return;
+
+    sroom->rtype = POOLROOM;
+    typ = !rn2(5) ? POOL : LAVAPOOL;
+
+    wallwalk_right(sroom->lx, sroom->ly, typ, sroom->rlit, ROOM, 96);
+}
+
+
 void
 mklev()
@@ -930,6 +1190,6 @@
 	in_mklev = FALSE;
 	/* has_morgue gets cleared once morgue is entered; graveyard stays
-	   set (graveyard might already be set even when has_morgue is clear
-	   [see fixup_special()], so don't update it unconditionally) */
+	   set (graveyard might already be set even when has_morgue is clear,
+	   so don't update it unconditionally) */
 	if (level.flags.has_morgue)
 	    level.flags.graveyard = 1;
@@ -1225,5 +1485,7 @@
 			if (lvl < 5) kind = NO_TRAP; break;
 		    case LANDMINE:
+			 case SPEAR_TRAP:
 			if (lvl < 6) kind = NO_TRAP; break;
+			 case ANTI_MAGIC:
 		    case WEB:
 			if (lvl < 7) kind = NO_TRAP; break;
@@ -1231,4 +1493,7 @@
 		    case POLY_TRAP:
 			if (lvl < 8) kind = NO_TRAP; break;
+			 case COLLAPSE_TRAP:
+		    case MAGIC_BEAM_TRAP:
+			if (lvl < 16) kind = NO_TRAP; break;	/* these hurt, put 'em deep */
 		    case FIRE_TRAP:
 			if (!Inhell) kind = NO_TRAP; break;
@@ -1349,4 +1614,38 @@
 #endif /* SINKS */
 
+STATIC_OVL void
+mktree(croom)
+struct mkroom* croom;
+{
+	coord loc;
+	int count = 0;
+
+	do { 
+		if (!somexy(croom,&loc)) return;
+		count++;
+	} while (count < 200 && (occupied(loc.x,loc.y) || bydoor(loc.x,loc.y)));
+
+	/* ho, ho, ho */
+	levl[loc.x][loc.y].typ = TREE;
+	if (level.objects[loc.x][loc.y]) {  /* "under" the tree */
+		bury_objs(loc.x,loc.y);
+	}
+}
+
+STATIC_OVL void
+mkbrazier(croom)
+struct mkroom* croom;
+{
+	coord loc;
+	int count = 0;
+
+	do {
+		if (!somexy(croom,&loc)) return;
+		count++;
+	} while (count < 200 && (occupied(loc.x,loc.y) || bydoor(loc.x,loc.y)));
+
+	(void) mksobj_at(FUR_BRAZIER, loc.x, loc.y, TRUE, FALSE);
+}
+
 
 STATIC_OVL void
@@ -1463,4 +1762,8 @@
     newsym(u.ux, u.uy);
     vision_full_recalc = 1;	/* everything changed */
+
+#ifdef RECORD_ACHIEVE
+    achieve.perform_invocation = 1;
+#endif
 }
 
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/src/mkmap.c nethack/src/mkmap.c
--- nh_orig/src/mkmap.c	2003-12-07 18:39:13.000000000 -0500
+++ nethack/src/mkmap.c	2010-08-16 13:20:13.437708572 -0400
@@ -19,4 +19,5 @@
 STATIC_DCL void FDECL(finish_map,(SCHAR_P,SCHAR_P,XCHAR_P,XCHAR_P));
 STATIC_DCL void FDECL(remove_room,(unsigned));
+STATIC_DCL void FDECL(backfill,(SCHAR_P,SCHAR_P));
 void FDECL(mkmap, (lev_init *));
 
@@ -31,8 +32,35 @@
 	register int i,j;
 
+	if (bg_typ >= MAX_TYPE) return;
+
 	for(i=1; i<COLNO; i++)
-	    for(j=0; j<ROWNO; j++)
+	    for(j=0; j<ROWNO; j++) {
 		levl[i][j].typ = bg_typ;
+		levl[i][j].lit = FALSE;
 }
+}
+
+
+STATIC_OVL void
+backfill(bg_typ,filler)
+schar bg_typ,filler;
+{
+	int x,y;
+
+	if (filler >= MAX_TYPE) return;
+
+	for(x=1;x<COLNO;x++) {
+		for(y=0;y<ROWNO;y++) {
+			if (levl[x][y].typ == bg_typ) {
+				levl[x][y].typ = filler;
+				if (filler == LAVAPOOL) {	 /* lava's always lit */
+					levl[x][y].lit = 1;
+				}
+			}
+		}
+	}
+
+}
+
 
 STATIC_OVL void
@@ -43,4 +71,6 @@
 	long limit, count;
 
+	if (fg_typ >= MAX_TYPE) return;
+
 	limit = (WIDTH * HEIGHT * 2) / 5;
 	count = 0;
@@ -88,4 +118,5 @@
 		  case 1 :
 		  case 2:
+		      if (bg_typ >= MAX_TYPE) break;
 			  levl[i][j].typ = bg_typ;
 			  break;
@@ -94,4 +125,5 @@
 		  case 7:
 		  case 8:
+		      if (fg_typ >= MAX_TYPE) break;
 			  levl[i][j].typ = fg_typ;
 			  break;
@@ -125,4 +157,5 @@
 	for(i=2; i<=WIDTH; i++)
 	    for(j=1; j<HEIGHT; j++)
+		if (new_loc(i,j) < MAX_TYPE)
 		levl[i][j].typ = new_loc(i,j);
 }
@@ -149,4 +182,5 @@
 	for(i=2; i<=WIDTH; i++)
 	    for(j=1; j<HEIGHT; j++)
+		if (new_loc(i,j) < MAX_TYPE)
 		levl[i][j].typ = new_loc(i,j);
 }
@@ -452,4 +486,5 @@
 	new_locations = (char *)alloc((WIDTH+1) * HEIGHT);
 
+	if (bg_typ < MAX_TYPE)
 	init_map(bg_typ);
 	init_fill(bg_typ, fg_typ);
@@ -469,8 +504,14 @@
 
 	finish_map(fg_typ, bg_typ, (boolean)lit, (boolean)walled);
-	/* a walled, joined level is cavernous, not mazelike -dlc */
-	if (walled && join) {
+	/* a walled, joined level is cavernous, not mazelike -dlc
+	 *
+	 * also, caverns have a defined "inside" and "outside"; the outside
+	 * doesn't _have_ to be stone, say, for hell.  so if the player
+	 * defined a maze filler originally, go ahead and backfill the 
+	 * background in with that filler - DSR */
+	if (walled && join && (init_lev->filling > -1)) {
 	    level.flags.is_maze_lev = FALSE;
 	    level.flags.is_cavernous_lev = TRUE;
+		 backfill(bg_typ,init_lev->filling);
 	}
 	free(new_locations);
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/src/mkmaze.c nethack/src/mkmaze.c
--- nh_orig/src/mkmaze.c	2003-12-07 18:39:13.000000000 -0500
+++ nethack/src/mkmaze.c	2010-03-30 14:05:06.588625607 -0400
@@ -11,4 +11,5 @@
 extern lev_region *lregions;
 extern int num_lregions;
+extern char SpLev_Map[COLNO][ROWNO];
 
 STATIC_DCL boolean FDECL(iswall,(int,int));
@@ -125,17 +126,4 @@
 	register int x,y;
 	struct rm *lev;
-	int bits;
-	int locale[3][3];	/* rock or wall status surrounding positions */
-	/*
-	 * Value 0 represents a free-standing wall.  It could be anything,
-	 * so even though this table says VWALL, we actually leave whatever
-	 * typ was there alone.
-	 */
-	static xchar spine_array[16] = {
-	    VWALL,	HWALL,		HWALL,		HWALL,
-	    VWALL,	TRCORNER,	TLCORNER,	TDWALL,
-	    VWALL,	BRCORNER,	BLCORNER,	TUWALL,
-	    VWALL,	TLWALL,		TRWALL,		CROSSWALL
-	};
 
 	/* sanity check on incoming variables */
@@ -161,9 +149,33 @@
 	    }
 
+	wall_extends(x1,y1,x2,y2);
+}
+
+void
+wall_extends(x1, y1, x2, y2)
+int x1, y1, x2, y2;
+{
+	uchar type;
+	register int x,y;
+	struct rm *lev;
+	int bits;
+	int locale[3][3];	/* rock or wall status surrounding positions */
+
 	/*
-	 * Step 2: set the correct wall type.  We can't combine steps
-	 * 1 and 2 into a single sweep because we depend on knowing if
-	 * the surrounding positions are stone.
+	 * Value 0 represents a free-standing wall.  It could be anything,
+	 * so even though this table says VWALL, we actually leave whatever
+	 * typ was there alone.
 	 */
+	static xchar spine_array[16] = {
+	    VWALL,	HWALL,		HWALL,		HWALL,
+	    VWALL,	TRCORNER,	TLCORNER,	TDWALL,
+	    VWALL,	BRCORNER,	BLCORNER,	TUWALL,
+	    VWALL,	TLWALL,		TRWALL,		CROSSWALL
+	};
+
+	/* sanity check on incoming variables */
+	if (x1<0 || x2>=COLNO || x1>x2 || y1<0 || y2>=ROWNO || y1>y2)
+	    panic("wall_extends: bad bounds (%d,%d) to (%d,%d)",x1,y1,x2,y2);
+
 	for(x = x1; x <= x2; x++)
 	    for(y = y1; y <= y2; y++) {
@@ -345,5 +357,4 @@
 	unsetup_waterlevel();
     } else if (Is_waterlevel(&u.uz)) {
-	level.flags.hero_memory = 0;
 	was_waterlevel = TRUE;
 	/* water level is an odd beast - it has to be set up
@@ -406,8 +417,4 @@
     }
 
-	/* KMH -- Sokoban levels */
-	if(In_sokoban(&u.uz))
-		sokoban_detect();
-
     /* Still need to add some stuff to level file */
     if (Is_medusa_level(&u.uz)) {
@@ -440,8 +447,4 @@
 	    }
 	}
-    } else if(Is_wiz1_level(&u.uz)) {
-	croom = search_special(MORGUE);
-
-	create_secret_door(croom, W_SOUTH|W_EAST|W_WEST);
     } else if(Is_knox(&u.uz)) {
 	/* using an unfilled morgue for rm id */
@@ -457,13 +460,4 @@
 		    (void)maketrap(x, y, rn2(3) ? LANDMINE : SPIKED_PIT);
 	    }
-    } else if (Role_if(PM_PRIEST) && In_quest(&u.uz)) {
-	/* less chance for undead corpses (lured from lower morgues) */
-	level.flags.graveyard = 1;
-    } else if (Is_stronghold(&u.uz)) {
-	level.flags.graveyard = 1;
-    } else if(Is_sanctum(&u.uz)) {
-	croom = search_special(TEMPLE);
-
-	create_secret_door(croom, W_ANY);
     } else if(on_level(&u.uz, &orcus_level)) {
 	   register struct monst *mtmp, *mtmp2;
@@ -499,4 +493,5 @@
 	int x,y;
 	char protofile[20];
+	struct obj* otmp;
 	s_level	*sp = Is_special(&u.uz);
 	coord mm;
@@ -570,5 +565,5 @@
 
 	maze0xy(&mm);
-	walkfrom((int) mm.x, (int) mm.y);
+	walkfrom((int) mm.x, (int) mm.y, 0);
 	/* put a boulder at the maze center */
 	(void) mksobj_at(BOULDER, (int) mm.x, (int) mm.y, TRUE, FALSE);
@@ -619,4 +614,5 @@
 	    inv_pos.x = x;
 	    inv_pos.y = y;
+		 otmp = mksobj_at(FUR_BRAZIER,(int)inv_pos.x,(int)inv_pos.y,TRUE,FALSE);
 #undef INVPOS_X_MARGIN
 #undef INVPOS_Y_MARGIN
@@ -660,6 +656,7 @@
  */
 void
-walkfrom(x,y)
+walkfrom(x,y,typ)
 int x,y;
+schar typ;
 {
 #define CELLS (ROWNO * COLNO) / 4		/* a maze cell is 4 squares */
@@ -668,4 +665,10 @@
 	int dirs[4];
 
+#ifndef WALLIFIED_MAZE
+	if (!typ) typ = CORR;
+#else
+	if (!typ) typ = ROOM;
+#endif
+
 	pos = 1;
 	mazex[pos] = (char) x;
@@ -676,10 +679,7 @@
 		if(!IS_DOOR(levl[x][y].typ)) {
 		    /* might still be on edge of MAP, so don't overwrite */
-#ifndef WALLIFIED_MAZE
-		    levl[x][y].typ = CORR;
-#else
-		    levl[x][y].typ = ROOM;
-#endif
+		    levl[x][y].typ = typ;
 		    levl[x][y].flags = 0;
+		    SpLev_Map[x][y] = 1;
 		}
 		q = 0;
@@ -691,10 +691,8 @@
 			dir = dirs[rn2(q)];
 			move(&x, &y, dir);
-#ifndef WALLIFIED_MAZE
-			levl[x][y].typ = CORR;
-#else
-			levl[x][y].typ = ROOM;
-#endif
+			levl[x][y].typ = typ;
+			SpLev_Map[x][y] = 1;
 			move(&x, &y, dir);
+			SpLev_Map[x][y] = 1;
 			pos++;
 			if (pos > CELLS)
@@ -708,18 +706,22 @@
 
 void
-walkfrom(x,y)
+walkfrom(x,y,typ)
 int x,y;
+schar typ;
 {
 	register int q,a,dir;
 	int dirs[4];
 
-	if(!IS_DOOR(levl[x][y].typ)) {
-	    /* might still be on edge of MAP, so don't overwrite */
 #ifndef WALLIFIED_MAZE
-	    levl[x][y].typ = CORR;
+	if (!typ) typ = CORR;
 #else
-	    levl[x][y].typ = ROOM;
+	if (!typ) typ = ROOM;
 #endif
+
+	if(!IS_DOOR(levl[x][y].typ)) {
+	    /* might still be on edge of MAP, so don't overwrite */
+	    levl[x][y].typ = typ;
 	    levl[x][y].flags = 0;
+	    SpLev_Map[x][y] = 1;
 	}
 
@@ -731,11 +733,9 @@
 		dir = dirs[rn2(q)];
 		move(&x,&y,dir);
-#ifndef WALLIFIED_MAZE
-		levl[x][y].typ = CORR;
-#else
-		levl[x][y].typ = ROOM;
-#endif
+		levl[x][y].typ = typ;
+		SpLev_Map[x][y] = 1;
 		move(&x,&y,dir);
-		walkfrom(x,y);
+		SpLev_Map[x][y] = 1;
+		walkfrom(x,y, typ);
 	}
 }
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/src/mkobj.c nethack/src/mkobj.c
--- nh_orig/src/mkobj.c	2003-12-07 18:39:13.000000000 -0500
+++ nethack/src/mkobj.c	2010-05-13 09:22:21.977715007 -0400
@@ -89,4 +89,8 @@
 	otmp = mkobj(let, artif);
 	place_object(otmp, x, y);
+	if (!artif && is_damageable(otmp) && !rn2(5) &&
+	    (!otmp->oerodeproof) &&
+	    (let == WEAPON_CLASS ||
+	     let == ARMOR_CLASS)) otmp->oeroded = rn2(2)+1;
 	return(otmp);
 }
@@ -100,5 +104,11 @@
 
 	otmp = mksobj(otyp, init, artif);
+	if (!artif && init && is_damageable(otmp) && !rn2(5) &&
+	    (!otmp->oerodeproof) &&
+	    (objects[otyp].oc_class == WEAPON_CLASS ||
+	     objects[otyp].oc_class == ARMOR_CLASS))
+	    otmp->oeroded = rn2(2)+1;
 	place_object(otmp, x, y);
+
 	return(otmp);
 }
@@ -145,14 +155,24 @@
 
 	switch (box->otyp) {
-	case ICE_BOX:		n = 20; break;
-	case CHEST:		n = 5; break;
-	case LARGE_BOX:		n = 3; break;
+		case ICE_BOX:		
+			n = 20; box->capacity = MAX_CAPACITY; break;
+		case IRON_SAFE:   
+			n = 10; box->capacity = MAX_CAPACITY; break;
+		case CHEST:		   
+			n = 5; box->capacity = MAX_CAPACITY; break;
+		case LARGE_BOX:	
+			n = 3; box->capacity = 3000; break;
+		case SMALL_SACK:
+			n = 1; box->capacity = 200; break;
 	case SACK:
 	case OILSKIN_SACK:
+			box->capacity = 1000;
 				/* initial inventory: sack starts out empty */
-				if (moves <= 1 && !in_mklev) { n = 0; break; }
-				/*else FALLTHRU*/
-	case BAG_OF_HOLDING:	n = 1; break;
-	default:		n = 0; break;
+			if (moves <= 1 && !in_mklev) { n = 0; } else { n = 1; }
+			break;
+		case BAG_OF_HOLDING:	
+			n = 1; box->capacity = MAX_CAPACITY; break;
+		default:		
+			n = 0; box->capacity = 1000; break;
 	}
 
@@ -174,4 +194,5 @@
 		for (tprob = rnd(100); (tprob -= iprobs->iprob) > 0; iprobs++)
 		    ;
+
 		if (!(otmp = mkobj(iprobs->iclass, TRUE))) continue;
 
@@ -181,9 +202,11 @@
 		    otmp->quan = (long)(rnd(level_difficulty()+2) * rnd(75));
 		    otmp->owt = weight(otmp);
-		} else while (otmp->otyp == ROCK) {
+			} else { 
+				while (otmp->otyp == ROCK) {
 		    otmp->otyp = rnd_class(DILITHIUM_CRYSTAL, LOADSTONE);
 		    if (otmp->quan > 2L) otmp->quan = 1L;
 		    otmp->owt = weight(otmp);
 		}
+			}
 		if (box->otyp == BAG_OF_HOLDING) {
 		    if (Is_mbag(otmp)) {
@@ -194,4 +217,11 @@
 			    otmp->otyp = rnd_class(WAN_LIGHT, WAN_LIGHTNING);
 		}
+
+			/* now that we know the weight, only add it if it fits */
+			if (weight(box) + otmp->owt > box->capacity) {
+				obfree(otmp,(struct obj*) 0);
+				continue;
+			}
+
 	    }
 	    (void) add_to_container(box, otmp);
@@ -400,4 +430,5 @@
 		if (is_poisonable(otmp) && !rn2(100))
 			otmp->opoisoned = 1;
+		if (!artif && is_damageable(otmp) && !rn2(10)) otmp->oeroded = rn2(2)+1;
 
 		if (artif && !rn2(20))
@@ -468,11 +499,12 @@
 					      (long)objects[otmp->otyp].oc_cost;
 					otmp->lamplit = 0;
-					otmp->quan = 1L +
-					      (long)(rn2(2) ? rn2(7) : 0);
+					otmp->quan = 1L + (long)rn2(7);
 					blessorcurse(otmp, 5);
 					break;
 		case BRASS_LANTERN:
-		case OIL_LAMP:		otmp->spe = 1;
-					otmp->age = (long) rn1(500,1000);
+		case BAG_OF_POO:
+		case OIL_LAMP:		
+					otmp->spe = 1;
+					otmp->age = (long) rn1((otmp->otyp == BAG_OF_POO) ? 750 : 500,1000);
 					otmp->lamplit = 0;
 					blessorcurse(otmp, 5);
@@ -482,8 +514,18 @@
 					blessorcurse(otmp, 2);
 					break;
+		case FUR_BRAZIER:
+					otmp->spe = 1;
+					otmp->lamplit = 0;
+					break;
+		case IRON_SAFE:
+					otmp->olocked = 1;
 		case CHEST:
-		case LARGE_BOX:		otmp->olocked = !!(rn2(5));
+		case LARGE_BOX:		
+					if (otmp->otyp != IRON_SAFE) {
+						otmp->olocked = !!(rn2(5));  /* clumsy tweak */
+					}
 					otmp->otrapped = !(rn2(10));
 		case ICE_BOX:
+		case SMALL_SACK:
 		case SACK:
 		case OILSKIN_SACK:
@@ -553,4 +595,5 @@
 		   otmp->otyp == HELM_OF_OPPOSITE_ALIGNMENT ||
 		   otmp->otyp == GAUNTLETS_OF_FUMBLING ||
+			otmp->otyp == BOOTS_OF_MOLASSES ||
 		   !rn2(11))) {
 			curse(otmp);
@@ -560,4 +603,5 @@
 			otmp->spe = rne(3);
 		} else	blessorcurse(otmp, 10);
+		if (!artif && is_damageable(otmp) && !rn2(10)) otmp->oeroded = rn2(2)+1;
 		if (artif && !rn2(40))                
 		    otmp = mk_artifact(otmp, (aligntyp)A_NONE);
@@ -565,19 +609,17 @@
 		if (Role_if(PM_SAMURAI) && otmp->otyp == SPLINT_MAIL &&
 		    (moves <= 1 || In_quest(&u.uz))) {
-#ifdef UNIXPC
-			/* optimizer bitfield bug */
-			otmp->oerodeproof = 1;
+		    set_erodeproof(otmp);
 			otmp->rknown = 1;
-#else
-			otmp->oerodeproof = otmp->rknown = 1;
-#endif
 		}
 		break;
 	case WAND_CLASS:
-		if(otmp->otyp == WAN_WISHING) otmp->spe = rnd(3); else
-		otmp->spe = rn1(5,
-			(objects[otmp->otyp].oc_dir == NODIR) ? 11 : 4);
-		blessorcurse(otmp, 17);
+		if (otmp->otyp == WAN_WISHING) { 
+			otmp->spe = rnd(3); 
+			otmp->recharged = Is_stronghold(&u.uz) ? 0 : 1;
+		} else {
+			otmp->spe = rn1(5, (objects[otmp->otyp].oc_dir == NODIR) ? 11 : 4);
 		otmp->recharged = 0; /* used to control recharging */
+		}
+		blessorcurse(otmp, 17);
 		break;
 	case RING_CLASS:
@@ -604,4 +646,5 @@
 		    case STATUE:
 			/* possibly overridden by mkcorpstat() */
+			otmp->capacity = MAX_CAPACITY;
 			otmp->corpsenm = rndmonnum();
 			if (!verysmall(&mons[otmp->corpsenm]) &&
@@ -613,4 +656,6 @@
 	case COIN_CLASS:
 		break;	/* do nothing */
+	case FURNITURE_CLASS:
+		break;	/* do nothing */
 	default:
 		impossible("impossible mkobj %d, sym '%c'.", otmp->otyp,
@@ -875,5 +920,5 @@
 
     if (amount <= 0L)
-	amount = (long)(1 + rnd(level_difficulty()+2) * rnd(30));
+	amount = (long)(1 + rnd(level_difficulty()+2) * rnd(15));
     if (gold) {
 	gold->quan += amount;
@@ -906,5 +951,5 @@
 struct obj *
 mkcorpstat(objtype, mtmp, ptr, x, y, init)
-int objtype;	/* CORPSE or STATUE */
+int objtype;	/* CORPSE, SKULL or STATUE */
 struct monst *mtmp;
 struct permonst *ptr;
@@ -914,5 +959,5 @@
 	register struct obj *otmp;
 
-	if (objtype != CORPSE && objtype != STATUE)
+	if (objtype != CORPSE && objtype != STATUE && objtype != SKULL)
 	    impossible("making corpstat type %d", objtype);
 	if (x == 0 && y == 0) {		/* special case - random placement */
@@ -1130,4 +1175,18 @@
     fobj = otmp;
     if (otmp->timed) obj_timer_checks(otmp, x, y, 0);
+
+	 /* very ugly special case here: braziers will always be on the ground
+	  * and can't be picked up, so the act of placing them on the ground 
+	  * lights them for the first (and only) time.
+	  *
+	  * this would normally go in mksobj, but begin_burn requires a location
+	  * for an object prior to being willing to start it burning...
+	  */
+
+	if (otmp->otyp == FUR_BRAZIER)
+	{
+		begin_burn(otmp,FALSE);
+	}
+
 }
 
@@ -1434,4 +1493,24 @@
 }
 
+/* Small utility function to allow us to check against capacity quickly.
+ * Do not confuse with container_weight! */
+long
+get_container_weight(container)
+struct obj* container;
+{
+	struct obj* ot;
+	long total_weight = 0;
+
+	if (container && container->cobj) {
+		/* quick recalculate so we can be lazy */
+		container_weight(container);
+		for (ot = container->cobj; ot; ot = ot->nobj) {
+			total_weight += ot->owt;
+		}
+	}
+	return total_weight;
+}
+
+
 void
 add_to_migration(obj)
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/src/mkroom.c nethack/src/mkroom.c
--- nh_orig/src/mkroom.c	2003-12-07 18:39:13.000000000 -0500
+++ nethack/src/mkroom.c	2009-12-03 16:14:46.204274117 -0500
@@ -18,7 +18,7 @@
 #ifdef OVLB
 STATIC_DCL boolean FDECL(isbig, (struct mkroom *));
-STATIC_DCL struct mkroom * FDECL(pick_room,(BOOLEAN_P));
 STATIC_DCL void NDECL(mkshop), FDECL(mkzoo,(int)), NDECL(mkswamp);
 STATIC_DCL void NDECL(mktemple);
+STATIC_DCL void NDECL(mktraproom);
 STATIC_DCL coord * FDECL(shrine_pos, (int));
 STATIC_DCL struct permonst * NDECL(morguemon);
@@ -62,4 +62,6 @@
 	case COCKNEST:	mkzoo(COCKNEST); break;
 	case ANTHOLE:	mkzoo(ANTHOLE); break;
+	case TRAPROOM:  mktraproom(); break;
+	case POOLROOM:  mkpoolroom(); break;
 	default:	impossible("Tried to make a room of type %d.", roomtype);
     }
@@ -183,5 +185,5 @@
 }
 
-STATIC_OVL struct mkroom *
+struct mkroom *
 pick_room(strict)
 register boolean strict;
@@ -233,4 +235,5 @@
 	int rmno = (sroom - rooms) + ROOMOFFSET;
 	coord mm;
+	int has_throne = 0;
 
 #ifdef GCC_WARN
@@ -244,7 +247,9 @@
 		    for(tx = sroom->lx; tx <= sroom->hx; tx++)
 			for(ty = sroom->ly; ty <= sroom->hy; ty++)
-			    if(IS_THRONE(levl[tx][ty].typ))
+			    if(sobj_at(FUR_THRONE,tx,ty)) {
+				has_throne = 1;
 				goto throne_placed;
 		}
+		}
 		i = 100;
 		do {	/* don't place throne on top of stairs */
@@ -288,5 +293,5 @@
 		    continue;
 		/* don't place monster on explicitly placed throne */
-		if(type == COURT && IS_THRONE(levl[sx][sy].typ))
+		if(type == COURT && sobj_at(FUR_THRONE,sx,sy))
 		    continue;
 		mon = makemon(
@@ -339,5 +344,5 @@
 		    case BARRACKS:
 			if(!rn2(20))	/* the payroll and some loot */
-			    (void) mksobj_at((rn2(3)) ? LARGE_BOX : CHEST,
+			    (void) mksobj_at((rn2(3) || depth(&u.uz) < 16) ? CHEST : IRON_SAFE,
 					     sx, sy, TRUE, FALSE);
 			break;
@@ -364,9 +369,14 @@
 		{
 		  struct obj *chest;
-		  levl[tx][ty].typ = THRONE;
+		  if (!has_throne)
+		      mksobj_at(FUR_THRONE, tx,ty, TRUE, FALSE);
 		  (void) somexy(sroom, &mm);
 		  (void) mkgold((long) rn1(50 * level_difficulty(),10), mm.x, mm.y);
 		  /* the royal coffers */
+		  if (depth(&u.uz) > 15) {
+				chest = mksobj_at(IRON_SAFE, mm.x, mm.y, TRUE, FALSE);
+		  } else {
 		  chest = mksobj_at(CHEST, mm.x, mm.y, TRUE, FALSE);
+		  }
 		  chest->spe = 2; /* so it can be found later */
 		  level.flags.has_court = 1;
@@ -493,4 +503,37 @@
 }
 
+void
+mktraproom()
+{
+    struct mkroom *sroom;
+    struct rm *lev;
+    int area, ttyp, ntraps;
+    int idx = (level_difficulty() + ((long)u.ubirthday)) % 9;
+
+    if(!(sroom = pick_room(TRUE))) return;
+
+    sroom->rtype = TRAPROOM;
+    if (!rn2(10)) idx = rn2(10); /* occasionally give anything if called twice on same level */
+
+    area = ((sroom->hx - sroom->lx + 1) * (sroom->hy - sroom->ly + 1));
+    ntraps = rn2(area/3) + (area/4);
+
+    while (ntraps-- > 0) {
+	switch (idx) {
+	default: ttyp = LANDMINE; break;
+	case 0:  ttyp = ROLLING_BOULDER_TRAP; ntraps--; break;
+	case 1:  ttyp = rn2(2) ? PIT : SPIKED_PIT; break;
+	case 2:  ttyp = WEB; break;
+	case 3:  ttyp = rn2(3) ? ROCKTRAP : COLLAPSE_TRAP; break;
+	case 4:  ttyp = FIRE_TRAP; break;
+	case 5:  ttyp = rn2(5) ? TRAPDOOR : HOLE; break;
+	case 6:  ttyp = STATUE_TRAP; break;
+	case 7:  ttyp = rn2(2) ? DART_TRAP : ARROW_TRAP; break;
+	}
+	mktrap(ttyp, 0, sroom, NULL);
+    }
+
+}
+
 STATIC_OVL void
 mktemple()
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/src/mon.c nethack/src/mon.c
--- nh_orig/src/mon.c	2003-12-07 18:39:13.000000000 -0500
+++ nethack/src/mon.c	2010-05-02 09:11:33.857714751 -0400
@@ -53,4 +53,16 @@
 STATIC_DCL void FDECL(lifesaved_monster, (struct monst *));
 
+void
+remove_monster(x,y)
+int x,y;
+{
+    if (level.monsters[x][y] &&
+	(level.monsters[x][y]->data == &mons[PM_GIANT_TURTLE] &&
+	 (!level.monsters[x][y]->minvis || See_invisible)))
+	unblock_point(x,y);
+    level.monsters[x][y] = (struct monst *)0;
+}
+
+
 /* convert the monster index of an undead to its living counterpart */
 int
@@ -188,4 +200,5 @@
 	    case PM_BLUE_DRAGON:
 	    case PM_GREEN_DRAGON:
+	    case PM_GOLD_DRAGON:
 	    case PM_YELLOW_DRAGON:
 		/* Make dragon scales.  This assumes that the order of the */
@@ -210,5 +223,8 @@
 		goto default_1;
 	    case PM_LONG_WORM:
-		(void) mksobj_at(WORM_TOOTH, x, y, TRUE, FALSE);
+		{
+		    struct obj *otmp = mksobj_at(WORM_TOOTH, x, y, TRUE, FALSE);
+		    otmp->oeroded = 0;
+		}
 		goto default_1;
 	    case PM_VAMPIRE:
@@ -384,7 +400,7 @@
     boolean inpool, inlava, infountain;
 
-    inpool = is_pool(mtmp->mx,mtmp->my) &&
+	 inpool = is_pool(mtmp->mx,mtmp->my) && !is_flying(mtmp) &&
 	     !is_flyer(mtmp->data) && !is_floater(mtmp->data);
-    inlava = is_lava(mtmp->mx,mtmp->my) &&
+    inlava = is_lava(mtmp->mx,mtmp->my) && !is_flying(mtmp) &&
 	     !is_flyer(mtmp->data) && !is_floater(mtmp->data);
     infountain = IS_FOUNTAIN(levl[mtmp->mx][mtmp->my].typ);
@@ -410,5 +426,5 @@
 	if (cansee(mtmp->mx,mtmp->my))
 	    pline("%s rusts.", Monnam(mtmp));
-	mtmp->mhp -= dam;
+	damage_mon(mtmp,dam,AD_PHYS); /* Not quite accurate but no resistance to rusting */
 	if (mtmp->mhpmax > dam) mtmp->mhpmax -= dam;
 	if (mtmp->mhp < 1) {
@@ -435,5 +451,5 @@
 	    }
 	    else {
-		if (--mtmp->mhp < 1) {
+		if (damage_mon(mtmp,1,AD_FIRE)) {
 		    if (cansee(mtmp->mx,mtmp->my))
 			pline("%s surrenders to the fire.", Monnam(mtmp));
@@ -478,6 +494,6 @@
 	/* but eels have a difficult time outside */
 	if (mtmp->data->mlet == S_EEL && !Is_waterlevel(&u.uz)) {
-	    if(mtmp->mhp > 1) mtmp->mhp--;
-	    monflee(mtmp, 2, FALSE, FALSE);
+		if(mtmp->mhp > 1) damage_mon(mtmp,1,AD_PHYS);
+	    monflee(mtmp, 2, FALSE, mtmp->mflee ? FALSE : TRUE);
 	}
     }
@@ -503,11 +519,41 @@
 #ifdef STEED
     if (mon == u.usteed) {
+		/* if you aren't a good rider you can't go as fast
+		* this offsets to some degree the perma-bonus we had to
+		* give Knights to let them be able to use starting equipment
+		* (ie. their pony) safely */
+
+		switch (P_SKILL(P_RIDING)) {
+			case P_BASIC:
+				mmove -= 4;
+				break;
+			case P_SKILLED:
+				break;
+			case P_EXPERT:
+				mmove += 4;
+				break;
+			case P_UNSKILLED:
+			default:
+				mmove -= 6;
+				break;
+		}
+
 	if (u.ugallop && flags.mv) {
 	    /* average movement is 1.50 times normal */
 	    mmove = ((rn2(2) ? 4 : 5) * mmove) / 3;
 	}
+
+		/* If we don't do this, player riding a slow monster at unskilled
+		* or basic will never get any turns.  such as a wumpus.
+		*
+		* don't ask me why someone tried to ride a wumpus, but they did.
+		*/
+		if (mmove < 1) {
+			mmove = 1;
+		}
     }
 #endif
 
+
     return mmove;
 }
@@ -607,5 +653,5 @@
 
 	/* continue if the monster died fighting */
-	if (Conflict && !mtmp->iswiz && mtmp->mcansee) {
+	if (Conflict && !mtmp->iswiz && m_canseeu(mtmp)) {
 	    /* Note:
 	     *  Conflict does not take effect in the first round.
@@ -616,5 +662,5 @@
 	     *  have died if it returns 1.
 	     */
-	    if (couldsee(mtmp->mx,mtmp->my) &&
+	    if (cansee(mtmp->mx,mtmp->my) &&
 		(distu(mtmp->mx,mtmp->my) <= BOLT_LIM*BOLT_LIM) &&
 							fightm(mtmp))
@@ -890,8 +936,19 @@
 		if (otmp->oinvis && !perceives(mtmp->data)) continue;
 #endif
-		if (cansee(mtmp->mx,mtmp->my) && flags.verbose)
-			pline("%s picks up %s.", Monnam(mtmp),
-			      (distu(mtmp->mx, mtmp->my) <= 5) ?
-				doname(otmp) : distant_name(otmp, doname));
+		if (otmp->otyp == BOULDER && is_rockbreaker(mtmp->data)) {
+			if (cansee(mtmp->mx,mtmp->my)) {
+				pline("A thunderclap rings out, and %s shatters!", (distu(mtmp->mx, mtmp->my) <= 5) ? doname(otmp) : distant_name(otmp, doname));
+				pline("%s strides through the dust cloud.", Monnam(mtmp));
+			} else {
+				pline("A thunderclap rings out!");
+			}
+		} else {
+			if (cansee(mtmp->mx,mtmp->my) && flags.verbose) { 
+				pline("%s picks up %s.", Monnam(mtmp), (distu(mtmp->mx, mtmp->my) <= 5) ? doname(otmp) : distant_name(otmp, doname));
+			}
+		}
+		if (otmp->otyp == BOULDER && is_rockbreaker(mtmp->data)) {
+			remove_object(otmp);
+		} else {
 		obj_extract_self(otmp);
 		/* unblock point after extract, before pickup */
@@ -899,4 +956,5 @@
 		    unblock_point(otmp->ox,otmp->oy);	/* vision */
 		(void) mpickobj(mtmp, otmp);	/* may merge and free otmp */
+		}
 		m_dowear(mtmp, FALSE);
 		newsym(mtmp->mx, mtmp->my);
@@ -983,6 +1041,22 @@
 	 */
 
-	/* special--boulder throwers carry unlimited amounts of boulders */
-	if (throws_rocks(mdat) && otyp == BOULDER)
+	/* Critters without hands can't pick up gold, rocks, or gems; ie,
+	 * things that are typically in a loose pile.
+	 * (Technically they could do it one item at a time, but that
+	 * requires a lot of elaborate fiddling and doesn't add to gameplay.)
+	 *
+	 * This will also prevent them from picking up a significant stack
+	 * anything; ie. 100 darts.
+	 *
+	 * Dragons are exempted from this for obvious thematic reasons.
+	 */
+	if ((otmp->oclass == COIN_CLASS || otmp->oclass == GEM_CLASS ||
+				otmp->quan > 3) && nohands(mdat) && mdat->mlet != S_DRAGON) {
+		return FALSE;
+	}
+
+	/* special--boulder throwers carry unlimited amounts of boulders
+	 * and quest leaders can shatter boulders (will be handled in mpickstuff) */
+	if ((throws_rocks(mdat) || is_rockbreaker(mdat)) && otyp == BOULDER)
 		return(TRUE);
 
@@ -1012,4 +1086,5 @@
 	boolean rockok = FALSE, treeok = FALSE, thrudoor;
 	int maxx, maxy;
+	boolean treewalk;
 
 	x = mon->mx;
@@ -1018,8 +1093,10 @@
 
 	nodiag = (mdat == &mons[PM_GRID_BUG]);
+	treewalk = (mdat == &mons[PM_WOOD_NYMPH]);
 	wantpool = mdat->mlet == S_EEL;
-	poolok = is_flyer(mdat) || is_clinger(mdat) ||
+	poolok = is_flyer(mdat) || is_clinger(mdat) || is_flying(mon) ||
 		 (is_swimmer(mdat) && !wantpool);
-	lavaok = is_flyer(mdat) || is_clinger(mdat) || likes_lava(mdat);
+	lavaok = is_flyer(mdat) || is_clinger(mdat) || is_flying(mon) ||
+				likes_lava(mdat);
 	thrudoor = ((flag & (ALLOW_WALL|BUSTDOOR)) != 0L);
 	if (flag & ALLOW_DIG) {
@@ -1059,5 +1136,5 @@
 	    if(IS_ROCK(ntyp = levl[nx][ny].typ) &&
 	       !((flag & ALLOW_WALL) && may_passwall(nx,ny)) &&
-	       !((IS_TREE(ntyp) ? treeok : rockok) && may_dig(nx,ny))) continue;
+	       !((IS_TREE(ntyp) ? (treeok|treewalk) : rockok) && may_dig(nx,ny))) continue;
 	    /* KMH -- Added iron bars */
 	    if (ntyp == IRONBARS && !(flag & ALLOW_BARS)) continue;
@@ -1172,5 +1249,6 @@
 				      || (!is_flyer(mdat)
 				    && !is_floater(mdat)
-				    && !is_clinger(mdat))
+				    && !is_clinger(mdat)
+					 && !is_flying(mon))
 				      || In_sokoban(&u.uz))
 				&& (ttmp->ttyp != SLP_GAS_TRAP ||
@@ -1178,8 +1256,8 @@
 				&& (ttmp->ttyp != BEAR_TRAP ||
 				    (mdat->msize > MZ_SMALL &&
-				     !amorphous(mdat) && !is_flyer(mdat)))
+				     !amorphous(mdat) && !is_flyer(mdat) && !is_flying(mon)))
 				&& (ttmp->ttyp != FIRE_TRAP ||
 				    !resists_fire(mon))
-				&& (ttmp->ttyp != SQKY_BOARD || !is_flyer(mdat))
+				&& (ttmp->ttyp != SQKY_BOARD || !is_flyer(mdat) || !is_flying(mon))
 				&& (ttmp->ttyp != WEB || (!amorphous(mdat) &&
 				    !webmaker(mdat)))
@@ -1220,10 +1298,29 @@
 	/* supposedly purple worms are attracted to shrieking because they
 	   like to eat shriekers, so attack the latter when feasible */
-	if (magr->data == &mons[PM_PURPLE_WORM] &&
-		mdef->data == &mons[PM_SHRIEKER])
+	if (magr->data == &mons[PM_PURPLE_WORM] && mdef->data == &mons[PM_SHRIEKER])
 	    return ALLOW_M|ALLOW_TM;
 	/* Various other combinations such as dog vs cat, cat vs rat, and
 	   elf vs orc have been suggested.  For the time being we don't
 	   support those. */
+
+	/* don't let pets kill each other, as amusing as it can be */
+	if (!magr->mtame && !magr->mpeaceful) {
+		/* bigger critters and Riders will step on your pets to get to you */
+		if ((is_rider(magr->data) || 
+					magr->data->msize > mdef->data->msize + 1) && mdef->mtame) {
+			return ALLOW_M|ALLOW_TM;
+		}
+		if (m_canseeu(magr)) {	/* if you're in sight... */
+			/* Berserk monsters will attack anything but their own to reach you... */
+			if (magr->mberserk && magr->data->mlet != mdef->data->mlet) {
+				return ALLOW_M|ALLOW_TM;
+			} 
+			/* and just about everything will step on an insect in the way */
+			if (mdef->data->msize == MZ_TINY && magr->data->msize > MZ_TINY) {
+				return ALLOW_M|ALLOW_TM;
+			}
+		}
+	}
+
 	return 0L;
 }
@@ -1416,4 +1513,5 @@
 	struct permonst *mptr;
 	int tmp;
+	struct obj* otmp;
 
 	if(mtmp->isgd) {
@@ -1431,4 +1529,13 @@
 #endif
 
+	/* extinguish monster's armor */
+	if ( (otmp = which_armor(mtmp, W_ARM)) && 
+		(otmp->otyp==GOLD_DRAGON_SCALE_MAIL || otmp->otyp == GOLD_DRAGON_SCALES) )
+		end_burn(otmp,FALSE);
+
+	if ((otmp = which_armor(mtmp, W_ARMS)) && otmp->otyp == SHIELD_OF_LIGHT) {
+		end_burn(otmp,FALSE);
+	}
+
 	mptr = mtmp->data;		/* save this for m_detach() */
 	/* restore chameleon, lycanthropes to true form at death */
@@ -1482,4 +1589,10 @@
 	if(mtmp->iswiz) wizdead();
 	if(mtmp->data->msound == MS_NEMESIS) nemdead();
+        
+#ifdef RECORD_ACHIEVE
+        if(mtmp->data == &mons[PM_MEDUSA])
+            achieve.killed_medusa = 1;
+#endif
+
 	if(glyph_is_invisible(levl[mtmp->mx][mtmp->my].glyph))
 	    unmap_object(mtmp->mx, mtmp->my);
@@ -1503,4 +1616,12 @@
 	}
 
+	/* Trolls don't leave a corpse when the player is wielding Trollsbane */
+	if (mdat->mlet == S_TROLL && uwep && uwep->oartifact == ART_TROLLSBANE) {
+		if (cansee(mon->mx, mon->my)) {
+			pline("%s corpse flares brightly and burns to ashes.", s_suffix(Monnam(mon)));
+			return FALSE;
+		}
+	}
+
 	/* Gas spores always explode upon death */
 	for(i = 0; i < NATTK; i++) {
@@ -1522,5 +1643,5 @@
 		    } else {
 			if (flags.soundok) You_hear("an explosion.");
-			magr->mhp -= tmp;
+			damage_mon(magr,tmp,AD_PHYS);
 			if (magr->mhp < 1) mondied(magr);
 			if (magr->mhp < 1) { /* maybe lifesaved */
@@ -1853,11 +1974,19 @@
 	if(redisp) newsym(x,y);
 cleanup:
-	/* punish bad behaviour */
-	if(is_human(mdat) && (!always_hostile(mdat) && mtmp->malign <= 0) &&
-	   (mndx < PM_ARCHEOLOGIST || mndx > PM_WIZARD) &&
+	/* punish bad behaviour...
+	 * malign check should catch renegade priests on Astral so you don't
+	 * end up a murderer even though they're trying to eat your face
+	 */
+	if(((always_peaceful(mdat) && mtmp->malign <= 0) || mtmp->isshk) && 
 	   u.ualign.type != A_CHAOTIC) {
 		HTelepat &= ~INTRINSIC;
 		change_luck(-2);
+		if (u.ualign.type == A_LAWFUL) {
+			You("murderer! You feel very guilty.");
+			mortal_sin();
+		} else {
 		You("murderer!");
+			major_sin();
+		}
 		if (Blind && !Blind_telepat)
 		    see_monsters(); /* Can't sense monsters any more. */
@@ -1867,4 +1996,5 @@
 				sgn(u.ualign.type) == sgn(mdat->maligntyp)) {
 		change_luck(-5);
+		major_sin();
 		You_feel("guilty...");
 	}
@@ -1887,16 +2017,21 @@
 	    else pline("Whoopsie-daisy!");
 	}else if (mtmp->ispriest) {
-		adjalign((p_coaligned(mtmp)) ? -2 : 2);
 		/* cancel divine protection for killing your priest */
-		if (p_coaligned(mtmp)) u.ublessed = 0;
+		if (p_coaligned(mtmp)) {
+			mortal_sin();
+			u.ublessed = 0;
+		} else {
+			adjalign(5);
+		}
 		if (mdat->maligntyp == A_NONE)
 			adjalign((int)(ALIGNLIM / 4));		/* BIG bonus */
 	} else if (mtmp->mtame) {
-		adjalign(-15);	/* bad!! */
-		/* your god is mighty displeased... */
+		major_sin();	 /* bad!  your god is mighty displeased... */
 		if (!Hallucination) You_hear("the rumble of distant thunder...");
 		else You_hear("the studio audience applaud!");
-	} else if (mtmp->mpeaceful)
-		adjalign(-5);
+	} else if (mtmp->mpeaceful) {
+		You("slaughter the unwary!");
+		minor_sin();	 /* very hard to get this, but */
+	}
 
 	/* malign was already adjusted for u.ualign.type and randomization */
@@ -2028,5 +2163,5 @@
 	}
 
-	if(Poison_resistance) {
+	if(how_resistant(POISON_RES) == 100) {
 		if(!strcmp(string, "blast")) shieldeff(u.ux, u.uy);
 		pline_The("poison doesn't seem to affect you.");
@@ -2045,12 +2180,16 @@
 	i = rn2(fatal + 20*thrown_weapon);
 	if(i == 0 && typ != A_CHA) {
-		u.uhp = -1;
-		pline_The("poison was deadly...");
+		/* used to be instantly fatal; now just gongs your maxhp for (4d6)/2
+		 * ...which is probably pretty close to fatal anyway for low-levels */
+		pline_The("poison was extremely toxic!");
+		i = resist_reduce(d(4,6),POISON_RES);
+		losehp(i,pname,kprefix);
+		gainmaxhp(i/-2);
 	} else if(i <= 5) {
 		/* Check that a stat change was made */
-		if (adjattrib(typ, thrown_weapon ? -1 : -rn1(3,3), 1))
+		if (adjattrib(typ, thrown_weapon ? -1 : -resist_reduce(rn1(3,3),POISON_RES), 1))
 		    pline("You%s!", poiseff[typ]);
 	} else {
-		i = thrown_weapon ? rnd(6) : rn1(10,6);
+		i = resist_reduce(thrown_weapon ? rnd(6) : rn1(10,6),POISON_RES);
 		if(Half_physical_damage) i = (i+1) / 2;
 		losehp(i, pname, kprefix);
@@ -2107,8 +2246,9 @@
 	mtmp->mpeaceful = 0;
 	if(mtmp->ispriest) {
-		if(p_coaligned(mtmp)) adjalign(-5); /* very bad */
+		if (p_coaligned(mtmp)) minor_sin(); /* very bad */
 		else adjalign(2);
-	} else
-		adjalign(-1);		/* attacking peaceful monsters is bad */
+	} else {
+		venial_sin();		/* attacking peaceful monsters is bad */
+	}
 	if (couldsee(mtmp->mx, mtmp->my)) {
 		if (humanoid(mtmp->data) || mtmp->isshk || mtmp->isgd)
@@ -2136,4 +2276,49 @@
 		      got_mad == 1 ? "s" : "");
 	}
+
+	/* make other peaceful monsters react */
+	if (!flags.mon_moving) {
+	    struct monst *mon;
+	    int got_mad = 0;
+	    for (mon = fmon; mon; mon = mon->nmon)
+		if (!DEADMONSTER(mon) && !mindless(mon->data) && mon->mpeaceful && couldsee(mon->mx, mon->my) &&
+		    !mon->msleeping && mon->mcansee && m_canseeu(mon)) {
+		    boolean exclaimed = FALSE;
+		    if (humanoid(mon->data) || mon->isshk || mon->ispriest ||
+			(mon->data == &mons[PM_WATCHMAN] || mon->data == &mons[PM_WATCH_CAPTAIN])) {
+			if (mon->data == &mons[PM_WATCHMAN] || mon->data == &mons[PM_WATCH_CAPTAIN]) {
+			    verbalize("Halt!  You're under arrest!");
+			    (void) angry_guards(!(flags.soundok));
+			} else {
+			    const char *exclam[] = {
+				"Gasp!", "Uh-oh.", "Oh my!", "What?"
+			    };
+			    if (!rn2(5)) {
+				verbalize("%s", exclam[rn2(SIZE(exclam))]);
+				exclaimed = TRUE;
+			    }
+			    if (!mon->isshk && !mon->ispriest && (mon->data->mlevel < rn2(10))) {
+				monflee(mon, rn2(50)+25, TRUE, !exclaimed);
+				exclaimed = TRUE;
+			    }
+			    if (!mon->isshk && !mon->ispriest) {
+				mon->mpeaceful = 0;
+				adjalign(-1);
+				if (!exclaimed)
+				    pline("%s gets angry!", Monnam(mon));
+			    }
+			}
+		    } else if ((mtmp->data == mon->data) && !rn2(3)) {
+			if (!rn2(4)) {
+			    growl(mon);
+			    exclaimed = TRUE;
+			}
+			if (rn2(6)) {
+			    monflee(mon, rn2(25)+15, TRUE, !exclaimed);
+			} else
+			    mon->mberserk = 1;
+		    }
+		}
+	}
 }
 
@@ -2359,7 +2544,8 @@
 	/* For debugging only: allow control of polymorphed monster; not saved */
 	if (wizard && iflags.mon_polycontrol) {
-		char pprompt[BUFSZ], buf[BUFSZ];
+		char pprompt[BUFSZ], buf[BUFSZ] = "";
 		int tries = 0;
 		do {
+		    if (buf[0] == '\033') buf[0] = '\0';
 			Sprintf(pprompt,
 				"Change %s into what kind of monster? [type the name]",
@@ -2737,4 +2923,21 @@
 }
 
+/* Damages mon by amount of type; handles vulnerabilities.
+ * Returns whether mon should have died or not.
+ */
+boolean
+damage_mon(mon,amount,type)
+struct monst* mon;
+int amount;
+int type;
+{
+	if (vulnerable_to(mon,type)) {
+		amount *= 1.5;
+	}
+	mon->mhp -= amount;
+	return (mon->mhp < 1);
+}
+
+
 boolean
 angry_guards(silent)
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/src/mondata.c nethack/src/mondata.c
--- nh_orig/src/mondata.c	2003-12-07 18:39:13.000000000 -0500
+++ nethack/src/mondata.c	2009-08-02 13:49:38.662408417 -0400
@@ -213,4 +213,24 @@
 }
 
+boolean
+vulnerable_to(mon,element)
+struct monst* mon;
+int element;
+{
+	switch (element) {
+		case AD_FIRE:
+			return (mon->data->mflags4 && M4_VULNERABLE_FIRE);
+		case AD_COLD:
+			return (mon->data->mflags4 && M4_VULNERABLE_COLD);
+		case AD_ELEC:
+			return (mon->data->mflags4 && M4_VULNERABLE_ELEC);
+		case AD_ACID:
+			return (mon->data->mflags4 && M4_VULNERABLE_ACID);
+		default:
+			break;
+	}
+	return FALSE;
+}
+
 #endif /* OVLB */
 #ifdef OVL0
@@ -363,5 +383,5 @@
 		    (adtyp == AD_FIRE && !resists_fire(magr)) ||
 		    (adtyp == AD_ELEC && !resists_elec(magr)) ||
-		    adtyp == AD_PHYS) {
+		    adtyp == AD_DISE || adtyp == AD_PHYS) {
 		dmg = mdef->data->mattk[i].damn;
 		if(!dmg) dmg = mdef->data->mlevel+1;
@@ -386,6 +406,6 @@
 	if (i < LOW_PM || i >= NUMMONS) {
 		/* ought to switch this to use `fmt_ptr' */
-	    panic("monsndx - could not index monster (%lx)",
-		  (unsigned long)ptr);
+		panic("monsndx could not get index, missed by %d;\n"
+				 "pointer claims name is \"%s\"", (i-NUMMONS), ptr->mname);
 	    return NON_PM;		/* will not get here */
 	}
@@ -586,4 +606,5 @@
 	{PM_BABY_BLUE_DRAGON, PM_BLUE_DRAGON},
 	{PM_BABY_GREEN_DRAGON, PM_GREEN_DRAGON},
+	{PM_BABY_GOLD_DRAGON, PM_GOLD_DRAGON},
 	{PM_BABY_YELLOW_DRAGON, PM_YELLOW_DRAGON},
 	{PM_RED_NAGA_HATCHLING, PM_RED_NAGA},
@@ -680,4 +701,5 @@
 	int capitalize = (*def == highc(*def));
 
+	/* TODO: no pointer to the monster here so we can't check is_flying */
 	return (
 		is_floater(ptr) ? levitate[capitalize] :
@@ -700,4 +722,5 @@
 	int capitalize = 2 + (*def == highc(*def));
 
+	/* TODO: no pointer to the monster here so we can't check is_flying */
 	return (
 		is_floater(ptr) ? levitate[capitalize] :
@@ -753,4 +776,5 @@
 }
 
+
 #endif /* OVLB */
 
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/src/monmove.c nethack/src/monmove.c
--- nh_orig/src/monmove.c	2003-12-07 18:39:13.000000000 -0500
+++ nethack/src/monmove.c	2009-10-25 17:51:50.276398488 -0400
@@ -32,5 +32,5 @@
 	wake_nearto(mtmp->mx, mtmp->my, 7*7);
 	mtmp->mstun = 1;
-	mtmp->mhp -= rnd(15);
+	damage_mon(mtmp,rnd(15),AD_PHYS);
 	if(mtmp->mhp <= 0) {
 		mondied(mtmp);
@@ -132,13 +132,26 @@
 struct monst *mtmp;
 {
+	int resist_percentage;
+	boolean mresists;
+
 	if (mtmp->isshk || mtmp->isgd || mtmp->iswiz || !mtmp->mcansee ||
 	    mtmp->mpeaceful || mtmp->data->mlet == S_HUMAN ||
 	    is_lminion(mtmp) || mtmp->data == &mons[PM_ANGEL] ||
-	    is_rider(mtmp->data) || mtmp->data == &mons[PM_MINOTAUR])
+	    is_rider(mtmp->data) || mtmp->data == &mons[PM_MINOTAUR] ||
+		 mtmp->mnum == quest_info(MS_NEMESIS) || mtmp->mnum == PM_VLAD_THE_IMPALER)
 		return(FALSE);
 
+	/* the smallest monsters always respect Elbereth;
+	 * more powerful things less so */
+	if (mtmp->m_lev < 10) {
+		resist_percentage = (int)(mtmp->m_lev * 1.5) - 3;
+	} else {
+		resist_percentage = (int)(mtmp->m_lev * 2.0);
+	}
+	mresists = rn2(100) < resist_percentage;
+
 	return (boolean)(sobj_at(SCR_SCARE_MONSTER, x, y)
 #ifdef ELBERETH
-			 || sengr_at("Elbereth", x, y)
+			 || (sengr_at("Elbereth", x, y) && !mresists)
 #endif
 			 || (mtmp->data->mlet == S_VAMPIRE
@@ -213,4 +226,6 @@
 boolean fleemsg;
 {
+	struct monst* mtmp2;
+
 	if (u.ustuck == mtmp) {
 	    if (u.uswallow)
@@ -232,6 +247,23 @@
 		mtmp->mfleetim = min(fleetime, 127);
 	    }
-	    if (!mtmp->mflee && fleemsg && canseemon(mtmp) && !mtmp->mfrozen)
+	    if (!mtmp->mflee && fleemsg && !mtmp->mfrozen) {
+			 /* mindless, silent, and critters without proper voices 
+			  * won't scream, of course. */
+			 if (!rn2(8) && !mindless(mtmp->data) && !is_silent(mtmp->data) &&
+					 mtmp->data->msound != MS_BUZZ && mtmp->data->msound != MS_HISS) {
+				if (canseemon(mtmp))
+					pline("%s screams in terror!",Monnam(mtmp));
+				else 
+					You_hear("a frightened squeal!");
+				/* Check and see who was close enough to hear it */
+				for (mtmp2 = fmon; mtmp2; mtmp2 = mtmp2->nmon) {
+					if (dist2(mtmp->mx,mtmp->my,mtmp2->mx,mtmp2->my) < 19 && !rn2(3)) {
+						mtmp2->msleeping = 0;
+					}
+			   }
+			 }
+			 if (canseemon(mtmp))
 		pline("%s turns to flee!", (Monnam(mtmp)));
+		 }
 	    mtmp->mflee = 1;
 	}
@@ -297,5 +329,6 @@
 	register struct permonst *mdat;
 	register int tmp=0;
-	int inrange, nearby, scared;
+	struct monst* mdummy;
+	int inrange, nearby, scared, oldx, oldy;
 #ifdef GOLDOBJ
         struct obj *ygold = 0, *lepgold = 0;
@@ -336,4 +369,28 @@
 	wipe_engr_at(mtmp->mx, mtmp->my, 1);
 
+	/* special snark code; if it's next to you, you might discover
+	 * that it's a Boojum, and we need to swap out monsters in that case
+	 */
+	if (mtmp->mnum == PM_SNARK && distu(mtmp->mx,mtmp->my) <= 2) {
+		if (mtmp->m_id % 3 < 1) {
+			oldx = mtmp->mx; oldy = mtmp->my;
+			mongone(mtmp);
+			mdummy = makemon(&mons[PM_BOOJUM], oldx, oldy, NO_MM_FLAGS);
+			/* If someone has managed to extinct boojum, this will
+			 * result in the monster just vanishing.  But this should
+			 * be fairly difficult to do, since boojum only generate
+			 * from snarks at a rate of one snark, one boojum. */
+			if (mdummy) {
+				mtmp = mdummy;
+				if (canseemon(mtmp)) {
+					pline("Oh, no, this Snark is a Boojum!");
+				}
+				mtmp->msleeping = 0;
+			} else {
+				return(0);	// mtmp just went away, we'd better bail out
+			}
+		}
+	}
+
 	/* confused monsters get unconfused with small probability */
 	if (mtmp->mconf && !rn2(50)) mtmp->mconf = 0;
@@ -364,7 +421,10 @@
 	 */
 
-	/* Monsters that want to acquire things */
-	/* may teleport, so do it before inrange is set */
-	if(is_covetous(mdat)) (void) tactics(mtmp);
+	/* Monsters that want to acquire things may teleport, so do it 
+	 * before inrange is set
+	 * ...don't let peaceful covetous monsters stay underfoot, but
+	 * also don't stop demon princes from teleporting to you to get bribed */
+	if(is_covetous(mdat) && (!mtmp->mpeaceful || is_dprince(mtmp->data))) 
+			(void) tactics(mtmp);
 
 	/* check distance and scariness of attacks */
@@ -408,11 +468,15 @@
 		if (canseemon(mtmp))
 			pline("%s concentrates.", Monnam(mtmp));
-		if (distu(mtmp->mx, mtmp->my) > BOLT_LIM * BOLT_LIM) {
+		/* tinfoil hat is the only way to get blocked telepathy, so
+		 * it'll protect us here, though so should other future things 
+		 * that might block telepathy */
+		if (distu(mtmp->mx, mtmp->my) > BOLT_LIM * BOLT_LIM && !BTelepat) {
 			You("sense a faint wave of psychic energy.");
 			goto toofar;
 		}
+		if (!BTelepat) {
 		pline("A wave of psychic energy pours over you!");
 		if (mtmp->mpeaceful &&
-		    (!Conflict || resist(mtmp, RING_CLASS, 0, 0)))
+				(!Conflict || resist_conflict(mtmp)))
 			pline("It feels quite soothing.");
 		else {
@@ -429,4 +493,5 @@
 			}
 		}
+		}
 		for(m2=fmon; m2; m2 = nmon) {
 			nmon = m2->nmon;
@@ -439,5 +504,5 @@
 				if (cansee(m2->mx, m2->my))
 				    pline("It locks on to %s.", mon_nam(m2));
-				m2->mhp -= rnd(15);
+				damage_mon(m2,rnd(15),AD_DRIN);
 				if (m2->mhp <= 0)
 				    monkilled(m2, "", AD_DRIN);
@@ -489,5 +554,5 @@
 	   (mdat->mlet == S_LEPRECHAUN && !ygold && (lepgold || rn2(2))) ||
 #endif
-	   (is_wanderer(mdat) && !rn2(4)) || (Conflict && !mtmp->iswiz) ||
+	   (is_wanderer(mdat) && !rn2(4)) || (Conflict && !mtmp->iswiz) || is_skittish(mdat) ||
 	   (!mtmp->mcansee && !rn2(4)) || mtmp->mpeaceful) {
 		/* Possibly cast an undirected spell if not attacking you */
@@ -503,5 +568,5 @@
 			if (a->aatyp == AT_MAGC && (a->adtyp == AD_SPEL || a->adtyp == AD_CLRC)) {
 			    if (castmu(mtmp, a, FALSE, FALSE)) {
-				tmp = 3;
+						tmp = is_skittish(mdat) ? 0 : 3;
 				break;
 			    }
@@ -548,6 +613,5 @@
 /*	Now, attack the player if possible - one attack set per monst	*/
 
-	if (!mtmp->mpeaceful ||
-	    (Conflict && !resist(mtmp, RING_CLASS, 0, 0))) {
+	if (!mtmp->mpeaceful || (Conflict && !resist_conflict(mtmp))) {
 	    if(inrange && !noattacks(mdat) && u.uhp > 0 && !scared && tmp != 3)
 		if(mattacku(mtmp)) return(1); /* monster died (e.g. exploded) */
@@ -600,5 +664,5 @@
 	int chi;	/* could be schar except for stupid Sun-2 compiler */
 	boolean likegold=0, likegems=0, likeobjs=0, likemagic=0, conceals=0;
-	boolean likerock=0, can_tunnel=0;
+	boolean likerock=0, can_tunnel=0, breakrock=0;
 	boolean can_open=0, can_unlock=0, doorbuster=0;
 	boolean uses_items=0, setlikes=0;
@@ -663,5 +727,5 @@
 
 	/* and the acquisitive monsters get special treatment */
-	if(is_covetous(ptr)) {
+	if(is_covetous(ptr) && !mtmp->mpeaceful) {
 	    xchar tx = STRAT_GOALX(mtmp->mstrategy),
 		  ty = STRAT_GOALY(mtmp->mstrategy);
@@ -715,4 +779,8 @@
 	gy = mtmp->muy;
 	appr = mtmp->mflee ? -1 : 1;
+	/* does this monster like to play keep-away? */
+	if (is_skittish(ptr) && (dist2(mtmp->mx, mtmp->my, mtmp->mux, mtmp->muy) < 10)) {
+		appr = -1;
+	}
 	if (mtmp->mconf || (u.uswallow && mtmp == u.ustuck))
 		appr = 0;
@@ -780,5 +848,6 @@
 		likeobjs = (likes_objs(ptr) && pctload < 75);
 		likemagic = (likes_magic(ptr) && pctload < 85);
-		likerock = (throws_rocks(ptr) && pctload < 50 && !In_sokoban(&u.uz));
+		likerock = ((throws_rocks(ptr) && pctload < 50 && !In_sokoban(&u.uz)));
+		breakrock = is_rockbreaker(ptr);
 		conceals = hides_under(ptr);
 		setlikes = TRUE;
@@ -799,5 +868,5 @@
 	if(!mtmp->mpeaceful && is_mercenary(ptr)) minr = 1;
 
-	if((likegold || likegems || likeobjs || likemagic || likerock || conceals)
+	if((likegold || likegems || likeobjs || likemagic || likerock || breakrock || conceals)
 	      && (!*in_rooms(omx, omy, SHOPBASE) || (!rn2(25) && !mtmp->isshk))) {
 	look_for_obj:
@@ -832,5 +901,5 @@
 		       (likemagic && index(magical, otmp->oclass)) ||
 		       (uses_items && searches_for_item(mtmp, otmp)) ||
-		       (likerock && otmp->otyp == BOULDER) ||
+		       ((likerock) && otmp->otyp == BOULDER) ||
 		       (likegems && otmp->oclass == GEM_CLASS &&
 			objects[otmp->otyp].oc_material != MINERAL) ||
@@ -866,5 +935,5 @@
 	    /* don't try to pick up anything else, but use the same loop */
 	    uses_items = 0;
-	    likegems = likeobjs = likemagic = likerock = conceals = 0;
+	    likegems = likeobjs = likemagic = likerock = breakrock = conceals = 0;
 	    goto look_for_obj;
 	}
@@ -888,5 +957,5 @@
 	niy = omy;
 	flag = 0L;
-	if (mtmp->mpeaceful && (!Conflict || resist(mtmp, RING_CLASS, 0, 0)))
+	if (mtmp->mpeaceful && (!Conflict || resist_conflict(mtmp)))
 	    flag |= (ALLOW_SANCT | ALLOW_SSM);
 	else flag |= ALLOW_U;
@@ -899,5 +968,7 @@
 	if (is_human(ptr) || ptr == &mons[PM_MINOTAUR]) flag |= ALLOW_SSM;
 	if (is_undead(ptr) && ptr->mlet != S_GHOST) flag |= NOGARLIC;
-	if (throws_rocks(ptr)) flag |= ALLOW_ROCK;
+	if (throws_rocks(ptr) || is_rockbreaker(ptr)) {
+		flag |= ALLOW_ROCK;	
+	}
 	if (can_open) flag |= OPENDOOR;
 	if (can_unlock) flag |= UNLOCKDOOR;
@@ -965,5 +1036,6 @@
 			mtmp->weapon_check = NEED_PICK_OR_AXE;
 		} else if (IS_TREE(levl[nix][niy].typ)) {
-		    if (!(mw_tmp = MON_WEP(mtmp)) || !is_axe(mw_tmp))
+		    if ((!(mw_tmp = MON_WEP(mtmp)) || !is_axe(mw_tmp)) &&
+			(monsndx(mtmp->data) != PM_WOOD_NYMPH))
 			mtmp->weapon_check = NEED_AXE;
 		} else if (!(mw_tmp = MON_WEP(mtmp)) || !is_pick(mw_tmp)) {
@@ -1163,6 +1235,6 @@
 		    likeobjs = (likes_objs(ptr) && pctload < 75);
 		    likemagic = (likes_magic(ptr) && pctload < 85);
-		    likerock = (throws_rocks(ptr) && pctload < 50 &&
-				!In_sokoban(&u.uz));
+		    likerock = ((throws_rocks(ptr) && pctload < 50 && !In_sokoban(&u.uz))); 
+			 breakrock = is_rockbreaker(ptr);
 		    conceals = hides_under(ptr);
 		}
@@ -1185,5 +1257,5 @@
 		    if(likeobjs) picked |= mpickstuff(mtmp, practical);
 		    if(likemagic) picked |= mpickstuff(mtmp, magical);
-		    if(likerock) picked |= mpickstuff(mtmp, boulder_class);
+		    if(likerock || breakrock) picked |= mpickstuff(mtmp, boulder_class);
 		    if(likegems) picked |= mpickstuff(mtmp, gem_class);
 		    if(uses_items) picked |= mpickstuff(mtmp, (char *)0);
@@ -1351,5 +1423,5 @@
 		    obj->oclass != VENOM_CLASS &&
 #endif
-		    typ != SACK && typ != BAG_OF_HOLDING &&
+		    typ != SMALL_SACK && typ != SACK && typ != BAG_OF_HOLDING &&
 		    typ != BAG_OF_TRICKS && !Is_candle(obj) &&
 		    typ != OILSKIN_SACK && typ != LEASH &&
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/src/monst.c nethack/src/monst.c
--- nh_orig/src/monst.c	2003-12-07 18:39:13.000000000 -0500
+++ nethack/src/monst.c	2010-03-30 14:05:06.670625603 -0400
@@ -39,9 +39,9 @@
  *	sounds made (MS_* defines), physical size (MZ_* defines),
  *	resistances, resistances conferred (both MR_* defines),
- *	3 * flag bitmaps (M1_*, M2_*, and M3_* defines respectively)
+ *	4 * flag bitmaps (M1_*, M2_*, M3_*, and M4_* defines respectively)
  *	symbol color (C(x) macro)
  */
-#define MON(nam,sym,lvl,gen,atk,siz,mr1,mr2,flg1,flg2,flg3,col) \
-	   {nam,sym,lvl,gen,atk,siz,mr1,mr2,flg1,flg2,flg3,C(col)}
+#define MON(nam,sym,lvl,gen,atk,siz,mr1,mr2,flg1,flg2,flg3,flg4,col) \
+	   {nam,sym,lvl,gen,atk,siz,mr1,mr2,flg1,flg2,flg3,flg4,C(col)}
 /* LVL() and SIZ() collect several fields to cut down on # of args for MON() */
 #define LVL(lvl,mov,ac,mr,aln) lvl,mov,ac,mr,aln
@@ -101,5 +101,5 @@
 	SIZ(10, 10, 0, MS_SILENT, MZ_TINY), 0, 0,
 	M1_ANIMAL|M1_NOHANDS|M1_OVIPAROUS|M1_CARNIVORE,
-	M2_HOSTILE, 0, CLR_BROWN),
+	M2_HOSTILE, 0, 0, CLR_BROWN),
     MON("killer bee", S_ANT,
 	LVL(1, 18, -1, 0, 0), (G_GENO|G_LGROUP|2),
@@ -108,5 +108,5 @@
 	SIZ(1, 5, 0, MS_BUZZ, MZ_TINY), MR_POISON, MR_POISON,
 	M1_ANIMAL|M1_FLY|M1_NOHANDS|M1_POIS,
-	M2_HOSTILE|M2_FEMALE, 0, CLR_YELLOW),
+	M2_HOSTILE|M2_FEMALE, 0, 0, CLR_YELLOW),
     MON("soldier ant", S_ANT,
 	LVL(3, 18, 3, 0, 0), (G_GENO|G_SGROUP|2),
@@ -115,5 +115,5 @@
 	SIZ(20, 5, 0, MS_SILENT, MZ_TINY), MR_POISON, MR_POISON,
 	M1_ANIMAL|M1_NOHANDS|M1_OVIPAROUS|M1_POIS|M1_CARNIVORE,
-	M2_HOSTILE, 0, CLR_BLUE),
+	M2_HOSTILE, 0, 0, CLR_BLUE),
     MON("fire ant", S_ANT,
 	LVL(3, 18, 3, 10, 0), (G_GENO|G_SGROUP|1),
@@ -122,5 +122,5 @@
 	SIZ(30, 10, 0, MS_SILENT, MZ_TINY), MR_FIRE, MR_FIRE,
 	M1_ANIMAL|M1_NOHANDS|M1_OVIPAROUS|M1_CARNIVORE,
-	M2_HOSTILE, M3_INFRAVISIBLE, CLR_RED),
+	M2_HOSTILE, M3_INFRAVISIBLE, M4_VULNERABLE_COLD, CLR_RED),
     MON("giant beetle", S_ANT,
 	LVL(5, 6, 4, 0, 0), (G_GENO|3),
@@ -129,5 +129,5 @@
 	SIZ(10, 10, 0, MS_SILENT, MZ_LARGE), MR_POISON, MR_POISON,
 	M1_ANIMAL|M1_NOHANDS|M1_POIS|M1_CARNIVORE,
-	M2_HOSTILE, 0, CLR_BLACK),
+	M2_HOSTILE, 0, 0, CLR_BLACK),
     MON("queen bee", S_ANT,
 	LVL(9, 24, -4, 0, 0), (G_GENO|G_NOGEN),
@@ -136,5 +136,12 @@
 	SIZ(1, 5, 0, MS_BUZZ, MZ_TINY), MR_POISON, MR_POISON,
 	M1_ANIMAL|M1_FLY|M1_NOHANDS|M1_OVIPAROUS|M1_POIS,
-	M2_HOSTILE|M2_FEMALE|M2_PRINCE, 0, HI_LORD),
+	M2_HOSTILE|M2_FEMALE|M2_PRINCE, 0, 0, HI_LORD),
+    MON("locust", S_ANT,
+	LVL(9, 12, 0, 0, 0), (G_GENO|G_SGROUP|1),
+	A(ATTK(AT_BITE, AD_PHYS, 1, 8), ATTK(AT_STNG, AD_DISE, 1, 4),
+		NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
+	SIZ(1, 5, 0, MS_BUZZ, MZ_TINY), MR_POISON, MR_POISON,
+	M1_ANIMAL|M1_FLY|M1_NOHANDS|M1_OVIPAROUS|M1_POIS,
+	M2_HOSTILE, 0, 0, CLR_GRAY),
 /*
  * blobs
@@ -148,5 +155,5 @@
 	M1_BREATHLESS|M1_AMORPHOUS|M1_NOEYES|M1_NOLIMBS|M1_NOHEAD|
 	  M1_MINDLESS|M1_ACID,
-	M2_WANDER|M2_NEUTER, 0, CLR_GREEN),
+	M2_WANDER|M2_NEUTER, 0, 0, CLR_GREEN),
     MON("quivering blob", S_BLOB,
 	LVL(5, 1, 8, 0, 0), (G_GENO|2),
@@ -156,5 +163,5 @@
 	MR_SLEEP|MR_POISON, MR_POISON,
 	M1_NOEYES|M1_NOLIMBS|M1_NOHEAD|M1_MINDLESS,
-	M2_WANDER|M2_HOSTILE|M2_NEUTER, 0, CLR_WHITE),
+	M2_WANDER|M2_HOSTILE|M2_NEUTER, 0, 0, CLR_WHITE),
     MON("gelatinous cube", S_BLOB,
 	LVL(6, 6, 8, 0, 0), (G_GENO|2),
@@ -165,5 +172,5 @@
 	MR_FIRE|MR_COLD|MR_ELEC|MR_SLEEP,
 	M1_NOEYES|M1_NOLIMBS|M1_NOHEAD|M1_MINDLESS|M1_OMNIVORE|M1_ACID,
-	M2_WANDER|M2_HOSTILE|M2_NEUTER, 0, CLR_CYAN),
+	M2_WANDER|M2_HOSTILE|M2_NEUTER, 0, 0, CLR_CYAN),
 /*
  * cockatrice
@@ -173,8 +180,8 @@
 	A(ATTK(AT_BITE, AD_PHYS, 1, 2), ATTK(AT_TUCH, AD_STON, 0, 0),
 	  ATTK(AT_NONE, AD_STON, 0, 0), NO_ATTK, NO_ATTK, NO_ATTK),
-	SIZ(10, 10, 0, MS_HISS, MZ_TINY),
+	SIZ(10, 10, 0, MS_HISS, MZ_SMALL),
 	MR_POISON|MR_STONE, MR_POISON|MR_STONE,
 	M1_ANIMAL|M1_NOHANDS|M1_OMNIVORE, M2_HOSTILE,
-	M3_INFRAVISIBLE, CLR_BROWN),
+	M3_INFRAVISIBLE, 0, CLR_BROWN),
     MON("cockatrice", S_COCKATRICE,
 	LVL(5, 6, 6, 30, 0), (G_GENO|5),
@@ -184,5 +191,5 @@
 	MR_POISON|MR_STONE, MR_POISON|MR_STONE,
 	M1_ANIMAL|M1_NOHANDS|M1_OMNIVORE|M1_OVIPAROUS, M2_HOSTILE,
-	M3_INFRAVISIBLE, CLR_YELLOW),
+	M3_INFRAVISIBLE, 0, CLR_YELLOW),
     MON("pyrolisk", S_COCKATRICE, 
 	LVL(6, 6, 6, 30, 0), (G_GENO|1),
@@ -192,5 +199,5 @@
 	MR_POISON|MR_FIRE, MR_POISON|MR_FIRE,
 	M1_ANIMAL|M1_NOHANDS|M1_OMNIVORE|M1_OVIPAROUS, M2_HOSTILE,
-	M3_INFRAVISIBLE, CLR_RED),
+	M3_INFRAVISIBLE, M4_VULNERABLE_COLD, CLR_RED),
 /*
  * dogs & other canines
@@ -202,5 +209,5 @@
 	SIZ(300, 250, 0, MS_BARK, MZ_SMALL), 0, 0,
 	M1_ANIMAL|M1_NOHANDS|M1_CARNIVORE, M2_HOSTILE, M3_INFRAVISIBLE,
-	CLR_BROWN),
+	0, CLR_BROWN),
     MON("fox", S_DOG,
 	LVL(0, 15, 7, 0, 0), (G_GENO|1),
@@ -209,5 +216,5 @@
 	SIZ(300, 250, 0, MS_BARK, MZ_SMALL), 0, 0,
 	M1_ANIMAL|M1_NOHANDS|M1_CARNIVORE, M2_HOSTILE, M3_INFRAVISIBLE,
-	CLR_RED),
+	0, CLR_RED),
     MON("coyote", S_DOG,
 	LVL(1, 12, 7, 0, 0), (G_GENO|G_SGROUP|1),
@@ -216,5 +223,5 @@
 	SIZ(300, 250, 0, MS_BARK, MZ_SMALL), 0, 0,
 	M1_ANIMAL|M1_NOHANDS|M1_CARNIVORE, M2_HOSTILE, M3_INFRAVISIBLE,
-	CLR_BROWN),
+	0, CLR_BROWN),
     MON("werejackal", S_DOG,
 	LVL(2, 12, 7, 10, -7), (G_NOGEN|G_NOCORPSE),
@@ -223,5 +230,5 @@
 	SIZ(300, 250, 0, MS_BARK, MZ_SMALL), MR_POISON, 0,
 	M1_NOHANDS|M1_POIS|M1_REGEN|M1_CARNIVORE,
-	M2_NOPOLY|M2_WERE|M2_HOSTILE, M3_INFRAVISIBLE, CLR_BROWN),
+	M2_NOPOLY|M2_WERE|M2_HOSTILE, M3_INFRAVISIBLE, 0, CLR_BROWN),
     MON("little dog", S_DOG,
 	LVL(2, 18, 6, 0, 0), (G_GENO|1),
@@ -230,5 +237,5 @@
 	SIZ(150, 150, 0, MS_BARK, MZ_SMALL), 0, 0,
 	M1_ANIMAL|M1_NOHANDS|M1_CARNIVORE, M2_DOMESTIC, M3_INFRAVISIBLE,
-	HI_DOMESTIC),
+	0, HI_DOMESTIC),
     MON("dog", S_DOG,
 	LVL(4, 16, 5, 0, 0), (G_GENO|1),
@@ -237,5 +244,5 @@
 	SIZ(400, 200, 0, MS_BARK, MZ_MEDIUM), 0, 0,
 	M1_ANIMAL|M1_NOHANDS|M1_CARNIVORE, M2_DOMESTIC, M3_INFRAVISIBLE,
-	HI_DOMESTIC),
+	0, HI_DOMESTIC),
     MON("large dog", S_DOG,
 	LVL(6, 15, 4, 0, 0), (G_GENO|1),
@@ -244,5 +251,5 @@
 	SIZ(800, 250, 0, MS_BARK, MZ_MEDIUM), 0, 0,
 	M1_ANIMAL|M1_NOHANDS|M1_CARNIVORE,
-	M2_STRONG|M2_DOMESTIC, M3_INFRAVISIBLE, HI_DOMESTIC),
+	M2_STRONG|M2_DOMESTIC, M3_INFRAVISIBLE, 0, HI_DOMESTIC),
     MON("dingo", S_DOG,
 	LVL(4, 16, 5, 0, 0), (G_GENO|1),
@@ -251,5 +258,5 @@
 	SIZ(400, 200, 0, MS_BARK, MZ_MEDIUM), 0, 0,
 	M1_ANIMAL|M1_NOHANDS|M1_CARNIVORE, M2_HOSTILE, M3_INFRAVISIBLE,
-	CLR_YELLOW),
+	0, CLR_YELLOW),
     MON("wolf", S_DOG,
 	LVL(5, 12, 4, 0, 0), (G_GENO|G_SGROUP|2),
@@ -258,5 +265,5 @@
 	SIZ(500, 250, 0, MS_BARK, MZ_MEDIUM), 0, 0,
 	M1_ANIMAL|M1_NOHANDS|M1_CARNIVORE, M2_HOSTILE, M3_INFRAVISIBLE,
-	CLR_BROWN),
+	0, CLR_BROWN),
     MON("werewolf", S_DOG,
 	LVL(5, 12, 4, 20, -7), (G_NOGEN|G_NOCORPSE),
@@ -265,5 +272,5 @@
 	SIZ(500, 250, 0, MS_BARK, MZ_MEDIUM), MR_POISON, 0,
 	M1_NOHANDS|M1_POIS|M1_REGEN|M1_CARNIVORE,
-	M2_NOPOLY|M2_WERE|M2_HOSTILE, M3_INFRAVISIBLE, CLR_BROWN),
+	M2_NOPOLY|M2_WERE|M2_HOSTILE, M3_INFRAVISIBLE, 0, CLR_BROWN),
     MON("warg", S_DOG,
 	LVL(7, 12, 4, 0, -5), (G_GENO|G_SGROUP|2),
@@ -272,5 +279,5 @@
 	SIZ(850, 350, 0, MS_BARK, MZ_MEDIUM), 0, 0,
 	M1_ANIMAL|M1_NOHANDS|M1_CARNIVORE, M2_HOSTILE, M3_INFRAVISIBLE,
-	CLR_BROWN),
+	0, CLR_BROWN),
     MON("winter wolf cub", S_DOG,
 	LVL(5, 12, 4, 0, -5), (G_NOHELL|G_GENO|G_SGROUP|2),
@@ -278,5 +285,6 @@
 	  NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
 	SIZ(250, 200, 0, MS_BARK, MZ_SMALL), MR_COLD, MR_COLD,
-	M1_ANIMAL|M1_NOHANDS|M1_CARNIVORE, M2_HOSTILE, 0, CLR_CYAN),
+	M1_ANIMAL|M1_NOHANDS|M1_CARNIVORE, M2_HOSTILE, 0, 
+	M4_VULNERABLE_FIRE, CLR_CYAN),
     MON("winter wolf", S_DOG,
 	LVL(7, 12, 4, 20, 0), (G_NOHELL|G_GENO|1),
@@ -285,5 +293,6 @@
 	SIZ(700, 300, 0, MS_BARK, MZ_LARGE), MR_COLD, MR_COLD,
 	M1_ANIMAL|M1_NOHANDS|M1_CARNIVORE,
-	M2_HOSTILE|M2_STRONG, 0, CLR_CYAN),
+	M2_HOSTILE|M2_STRONG, 0, 
+	M4_VULNERABLE_FIRE, CLR_CYAN),
     MON("hell hound pup", S_DOG,
 	LVL(7, 12, 4, 20, -5), (G_HELL|G_GENO|G_SGROUP|1),
@@ -292,5 +301,5 @@
 	SIZ(200, 200, 0, MS_BARK, MZ_SMALL), MR_FIRE, MR_FIRE,
 	M1_ANIMAL|M1_NOHANDS|M1_CARNIVORE, M2_HOSTILE, M3_INFRAVISIBLE,
-	CLR_RED),
+	M4_VULNERABLE_COLD, CLR_RED),
     MON("hell hound", S_DOG,
 	LVL(12, 14, 2, 20, 0), (G_HELL|G_GENO|1),
@@ -299,5 +308,5 @@
 	SIZ(600, 300, 0, MS_BARK, MZ_MEDIUM), MR_FIRE, MR_FIRE,
 	M1_ANIMAL|M1_NOHANDS|M1_CARNIVORE, M2_HOSTILE|M2_STRONG,
-	M3_INFRAVISIBLE, CLR_RED),
+	M3_INFRAVISIBLE, M4_VULNERABLE_COLD, CLR_RED),
 #ifdef CHARON
     MON("Cerberus", S_DOG,
@@ -308,5 +317,5 @@
 	M1_ANIMAL|M1_NOHANDS|M1_CARNIVORE,
 	M2_NOPOLY|M2_HOSTILE|M2_STRONG|M2_PNAME|M2_MALE, M3_INFRAVISIBLE,
-	CLR_RED),
+	0, CLR_RED),
 #endif
 /*
@@ -314,48 +323,47 @@
  */
     MON("gas spore", S_EYE,
-	LVL(1, 3, 10, 0, 0), (G_NOCORPSE|G_GENO|1),
+	LVL(1, 3, 10, 0, 0), (G_NOCORPSE|1),
 	A(ATTK(AT_BOOM, AD_PHYS, 4, 6), NO_ATTK, NO_ATTK,
 	  NO_ATTK, NO_ATTK, NO_ATTK),
 	SIZ(10, 10, 0, MS_SILENT, MZ_SMALL), 0, 0,
 	M1_FLY|M1_BREATHLESS|M1_NOLIMBS|M1_NOHEAD|M1_MINDLESS,
-	M2_HOSTILE|M2_NEUTER, 0, CLR_GRAY),
+	M2_HOSTILE|M2_NEUTER, 0, 0, CLR_GRAY),
     MON("floating eye", S_EYE,
-	LVL(2, 1, 9, 10, 0), (G_GENO|5),
+	LVL(2, 1, 9, 10, 0), (5),
 	A(ATTK(AT_NONE, AD_PLYS, 0,70),
 	  NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
 	SIZ(10, 10, 0, MS_SILENT, MZ_SMALL), 0, 0,
 	M1_FLY|M1_AMPHIBIOUS|M1_NOLIMBS|M1_NOHEAD|M1_NOTAKE,
-	M2_HOSTILE|M2_NEUTER, M3_INFRAVISIBLE, CLR_BLUE),
+	M2_HOSTILE|M2_NEUTER, M3_INFRAVISIBLE, 0, CLR_BLUE),
     MON("freezing sphere", S_EYE,
-	LVL(6, 13, 4, 0, 0), (G_NOCORPSE|G_NOHELL|G_GENO|2),
+	LVL(6, 13, 4, 0, 0), (G_NOCORPSE|G_NOHELL|2),
 	A(ATTK(AT_EXPL, AD_COLD, 4, 6),
 	  NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
 	SIZ(10, 10, 0, MS_SILENT, MZ_SMALL), MR_COLD, MR_COLD,
 	M1_FLY|M1_BREATHLESS|M1_NOLIMBS|M1_NOHEAD|M1_MINDLESS|M1_NOTAKE,
-	M2_HOSTILE|M2_NEUTER, M3_INFRAVISIBLE, CLR_WHITE),
+	M2_HOSTILE|M2_NEUTER, M3_INFRAVISIBLE, M4_VULNERABLE_FIRE, CLR_WHITE),
     MON("flaming sphere", S_EYE, 
-	LVL(6, 13, 4, 0, 0), (G_NOCORPSE|G_GENO|2),
+	LVL(6, 13, 4, 0, 0), (G_NOCORPSE|2),
 	A(ATTK(AT_EXPL, AD_FIRE, 4, 6), NO_ATTK, NO_ATTK,
 	    NO_ATTK, NO_ATTK, NO_ATTK),
 	SIZ(10, 10, 0, MS_SILENT, MZ_SMALL), MR_FIRE, MR_FIRE,
 	M1_FLY|M1_BREATHLESS|M1_NOLIMBS|M1_NOHEAD|M1_MINDLESS,
-	M2_HOSTILE|M2_NEUTER, M3_INFRAVISIBLE, CLR_RED),
+	M2_HOSTILE|M2_NEUTER, M3_INFRAVISIBLE, M4_VULNERABLE_COLD, CLR_RED),
     MON("shocking sphere", S_EYE, 
-	LVL(6, 13, 4, 0, 0), (G_NOCORPSE|G_GENO|2),
+	LVL(6, 13, 4, 0, 0), (G_NOCORPSE|2),
 	A(ATTK(AT_EXPL, AD_ELEC, 4, 6), NO_ATTK, NO_ATTK,
 	  NO_ATTK, NO_ATTK, NO_ATTK),
 	SIZ(10, 10, 0, MS_SILENT, MZ_SMALL), MR_ELEC, MR_ELEC,
 	M1_FLY|M1_BREATHLESS|M1_NOLIMBS|M1_NOHEAD|M1_MINDLESS,
-	M2_HOSTILE|M2_NEUTER, M3_INFRAVISIBLE, HI_ZAP),
-#if 0		/* not yet implemented */
-    MON("beholder", S_EYE,
-	LVL(6, 3, 4, 0, -10), (G_GENO|2),
-	A(ATTK(AT_GAZE, AD_SLOW, 0, 0), ATTK(AT_GAZE, AD_SLEE, 2,25),
-	  ATTK(AT_GAZE, AD_DISN, 0, 0), ATTK(AT_GAZE, AD_STON, 0, 0),
-	  ATTK(AT_GAZE, AD_CNCL, 2, 4), ATTK(AT_BITE, AD_PHYS, 2, 4)),
-	SIZ(10, 10, 0, MS_SILENT, MZ_SMALL), MR_COLD, 0,
-	M1_FLY|M1_BREATHLESS|M1_NOLIMBS|M1_NOHEAD|M1_MINDLESS,
-	M2_NOPOLY|M2_HOSTILE|M2_NEUTER, M3_INFRAVISIBLE, CLR_BROWN),
-#endif
+	M2_HOSTILE|M2_NEUTER, M3_INFRAVISIBLE, 0, HI_ZAP),
+    MON("magical eye", S_EYE,
+	LVL(9, 6, 4, 90, -10), (2),
+	A(ATTK(AT_GAZE, AD_SLOW, 0, 0), ATTK(AT_GAZE, AD_SLEE, 2,6),
+	  ATTK(AT_GAZE, AD_STUN, 0, 0), ATTK(AT_GAZE, AD_FIRE, 4, 6),
+	  ATTK(AT_GAZE, AD_COLD, 4, 6), ATTK(AT_BITE, AD_PHYS, 2, 4)),
+	SIZ(10, 10, 0, MS_SILENT, MZ_SMALL), MR_COLD|MR_FIRE|MR_ELEC, 0,
+	M1_FLY|M1_BREATHLESS|M1_NOLIMBS|M1_NOHEAD,
+	M2_NOPOLY|M2_HOSTILE|M2_NEUTER|M2_NASTY, 
+	M3_SKITTISH|M3_INFRAVISIBLE|M3_INFRAVISION, 0, HI_LORD),
 /*
  * felines
@@ -367,5 +375,5 @@
 	SIZ(150, 150, 0, MS_MEW, MZ_SMALL), 0, 0,
 	M1_ANIMAL|M1_NOHANDS|M1_CARNIVORE,
-	M2_WANDER|M2_DOMESTIC, M3_INFRAVISIBLE, HI_DOMESTIC),
+	M2_WANDER|M2_DOMESTIC, M3_INFRAVISIBLE, 0, HI_DOMESTIC),
     MON("housecat", S_FELINE,
 	LVL(4, 16, 5, 0, 0), (G_GENO|1),
@@ -374,5 +382,5 @@
 	SIZ(200, 200, 0, MS_MEW, MZ_SMALL), 0, 0,
 	M1_ANIMAL|M1_NOHANDS|M1_CARNIVORE, M2_DOMESTIC, M3_INFRAVISIBLE,
-	HI_DOMESTIC),
+	0, HI_DOMESTIC),
     MON("jaguar", S_FELINE,
 	LVL(4, 15, 6, 0, 0), (G_GENO|2),
@@ -381,5 +389,5 @@
 	SIZ(600, 300, 0, MS_GROWL, MZ_LARGE), 0, 0,
 	M1_ANIMAL|M1_NOHANDS|M1_CARNIVORE, M2_HOSTILE, M3_INFRAVISIBLE,
-	CLR_BROWN),
+	0, CLR_BROWN),
     MON("lynx", S_FELINE, 
 	LVL(5, 15, 6, 0, 0), (G_GENO|1),
@@ -388,5 +396,5 @@
 	SIZ(600, 300, 0, MS_GROWL, MZ_SMALL), 0, 0,
 	M1_ANIMAL|M1_NOHANDS|M1_CARNIVORE,M2_HOSTILE, M3_INFRAVISIBLE,
-	CLR_CYAN),
+	0, CLR_CYAN),
     MON("panther", S_FELINE, 
 	LVL(5, 15, 6, 0, 0), (G_GENO|1),
@@ -395,5 +403,5 @@
 	SIZ(600, 300, 0, MS_GROWL, MZ_LARGE), 0, 0,
 	M1_ANIMAL|M1_NOHANDS|M1_CARNIVORE,M2_HOSTILE, M3_INFRAVISIBLE,
-	CLR_BLACK),
+	0, CLR_BLACK),
     MON("large cat", S_FELINE,
 	LVL(6, 15, 4, 0, 0), (G_GENO|1),
@@ -402,5 +410,5 @@
 	SIZ(250, 250, 0, MS_MEW, MZ_SMALL), 0, 0,
 	M1_ANIMAL|M1_NOHANDS|M1_CARNIVORE,
-	M2_STRONG|M2_DOMESTIC, M3_INFRAVISIBLE, HI_DOMESTIC),
+	M2_STRONG|M2_DOMESTIC, M3_INFRAVISIBLE, 0, HI_DOMESTIC),
     MON("tiger", S_FELINE,
 	LVL(6, 12, 6, 0, 0), (G_GENO|2),
@@ -409,5 +417,5 @@
 	SIZ(600, 300, 0, MS_GROWL, MZ_LARGE), 0, 0,
 	M1_ANIMAL|M1_NOHANDS|M1_CARNIVORE, M2_HOSTILE, M3_INFRAVISIBLE,
-	CLR_YELLOW),
+	0, CLR_YELLOW),
 /*
  * gremlins and gargoyles
@@ -419,5 +427,5 @@
 	  NO_ATTK, NO_ATTK),
 	SIZ(100, 20, 0, MS_LAUGH, MZ_SMALL), MR_POISON, MR_POISON,
-	M1_SWIM|M1_HUMANOID|M1_POIS, M2_STALK, M3_INFRAVISIBLE, CLR_GREEN),
+	M1_SWIM|M1_HUMANOID|M1_POIS, M2_STALK, M3_INFRAVISIBLE, 0, CLR_GREEN),
     MON("gargoyle", S_GREMLIN,
 	LVL(6, 10, -4, 0, -9), (G_GENO|2),
@@ -426,12 +434,12 @@
 	SIZ(1000, 200, 0, MS_GRUNT, MZ_HUMAN), MR_STONE, MR_STONE,
 	M1_HUMANOID|M1_THICK_HIDE|M1_BREATHLESS,
-	M2_HOSTILE|M2_STRONG, 0, CLR_BROWN),
+	M2_HOSTILE|M2_STRONG, 0, 0, CLR_BROWN),
     MON("winged gargoyle", S_GREMLIN,
-	LVL(9, 15, -2, 0, -12), (G_GENO|1),
+	LVL(11, 15, -2, 0, -12), (G_GENO|1),
 	A(ATTK(AT_CLAW, AD_PHYS, 3, 6), ATTK(AT_CLAW, AD_PHYS, 3, 6),
 	  ATTK(AT_BITE, AD_PHYS, 3, 4), NO_ATTK, NO_ATTK, NO_ATTK),
 	SIZ(1200, 300, 0, MS_GRUNT, MZ_HUMAN), MR_STONE, MR_STONE,
 	M1_FLY|M1_HUMANOID|M1_THICK_HIDE|M1_BREATHLESS|M1_OVIPAROUS,
-	M2_LORD|M2_HOSTILE|M2_STRONG|M2_MAGIC, 0, HI_LORD),
+	M2_LORD|M2_HOSTILE|M2_STRONG|M2_MAGIC, M3_BERSERK, 0, HI_LORD),
 /*
  * humanoids
@@ -443,5 +451,5 @@
 	SIZ(500, 200, 0, MS_HUMANOID, MZ_SMALL), 0, 0,
 	M1_HUMANOID|M1_OMNIVORE, M2_COLLECT, M3_INFRAVISIBLE|M3_INFRAVISION,
-	CLR_GREEN),
+	0, CLR_GREEN),
     MON("dwarf", S_HUMANOID,
 	LVL(2, 6, 10, 10, 4), (G_GENO|3),
@@ -451,5 +459,5 @@
 	M1_TUNNEL|M1_NEEDPICK|M1_HUMANOID|M1_OMNIVORE,
 	M2_NOPOLY|M2_DWARF|M2_STRONG|M2_GREEDY|M2_JEWELS|M2_COLLECT,
-	M3_INFRAVISIBLE|M3_INFRAVISION, CLR_RED),
+	M3_INFRAVISIBLE|M3_INFRAVISION, 0, CLR_RED),
     MON("bugbear", S_HUMANOID,
 	LVL(3, 9, 5, 0, -6), (G_GENO|1),
@@ -458,5 +466,5 @@
 	SIZ(1250, 250, 0, MS_GROWL, MZ_LARGE), 0, 0,
 	M1_HUMANOID|M1_OMNIVORE, M2_STRONG|M2_COLLECT,
-	M3_INFRAVISIBLE|M3_INFRAVISION, CLR_BROWN),
+	M3_INFRAVISIBLE|M3_INFRAVISION, 0, CLR_BROWN),
     MON("dwarf lord", S_HUMANOID,
 	LVL(4, 6, 10, 10, 5), (G_GENO|2),
@@ -466,5 +474,5 @@
 	M1_TUNNEL|M1_NEEDPICK|M1_HUMANOID|M1_OMNIVORE,
 	M2_DWARF|M2_STRONG|M2_LORD|M2_MALE|M2_GREEDY|M2_JEWELS|M2_COLLECT,
-	M3_INFRAVISIBLE|M3_INFRAVISION, CLR_BLUE),
+	M3_INFRAVISIBLE|M3_INFRAVISION, 0, CLR_BLUE),
     MON("dwarf king", S_HUMANOID,
 	LVL(6, 6, 10, 20, 6), (G_GENO|1),
@@ -474,5 +482,5 @@
 	M1_TUNNEL|M1_NEEDPICK|M1_HUMANOID|M1_OMNIVORE,
 	M2_DWARF|M2_STRONG|M2_PRINCE|M2_MALE|M2_GREEDY|M2_JEWELS|M2_COLLECT,
-	M3_INFRAVISIBLE|M3_INFRAVISION, HI_LORD),
+	M3_EAGLEEYE|M3_INFRAVISIBLE|M3_INFRAVISION, 0, HI_LORD),
     MON("mind flayer", S_HUMANOID,
 	LVL(9, 12, 5, 90, -8), (G_GENO|1),
@@ -483,5 +491,5 @@
 	M1_HUMANOID|M1_FLY|M1_SEE_INVIS|M1_OMNIVORE,
 	M2_HOSTILE|M2_NASTY|M2_GREEDY|M2_JEWELS|M2_COLLECT,
-	M3_INFRAVISIBLE|M3_INFRAVISION, CLR_MAGENTA),
+	M3_INFRAVISIBLE|M3_INFRAVISION, 0, CLR_MAGENTA),
     MON("master mind flayer", S_HUMANOID,
 	LVL(13, 12, 0, 90, -8), (G_GENO|1),
@@ -492,5 +500,5 @@
 	M1_HUMANOID|M1_FLY|M1_SEE_INVIS|M1_OMNIVORE,
 	M2_HOSTILE|M2_NASTY|M2_GREEDY|M2_JEWELS|M2_COLLECT,
-	M3_INFRAVISIBLE|M3_INFRAVISION, CLR_MAGENTA),
+	M3_INFRAVISIBLE|M3_INFRAVISION, 0, CLR_MAGENTA),
 /*
  * imps & other minor demons/devils
@@ -501,5 +509,5 @@
 	  ATTK(AT_BITE, AD_PHYS, 1, 4), NO_ATTK, NO_ATTK, NO_ATTK),
 	SIZ(100, 100, 0, MS_SILENT, MZ_SMALL), MR_SLEEP|MR_POISON, 0,
-	M1_POIS, M2_HOSTILE|M2_STALK, M3_INFRAVISIBLE|M3_INFRAVISION, CLR_RED),
+	M1_POIS, M2_HOSTILE|M2_STALK, M3_INFRAVISIBLE|M3_INFRAVISION, 0, CLR_RED),
     MON("homunculus", S_IMP,
 	LVL(2, 12, 6, 10, -7), (G_GENO|2),
@@ -508,5 +516,5 @@
 	SIZ(60, 100, 0, MS_SILENT, MZ_TINY),
 	MR_SLEEP|MR_POISON, MR_SLEEP|MR_POISON,
-	M1_FLY|M1_POIS, M2_STALK, M3_INFRAVISIBLE|M3_INFRAVISION, CLR_GREEN),
+	M1_FLY|M1_POIS, M2_STALK, M3_INFRAVISIBLE|M3_INFRAVISION, 0, CLR_GREEN),
     MON("imp", S_IMP,
 	LVL(3, 12, 2, 20, -7), (G_GENO|1),
@@ -514,5 +522,5 @@
 	  NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
 	SIZ(20, 10, 0, MS_CUSS, MZ_TINY), 0, 0,
-	M1_REGEN, M2_WANDER|M2_STALK, M3_INFRAVISIBLE|M3_INFRAVISION, CLR_RED),
+	M1_REGEN, M2_WANDER|M2_STALK, M3_INFRAVISIBLE|M3_INFRAVISION, 0, CLR_RED),
     MON("lemure", S_IMP,
 	LVL(3, 3, 7, 0, -7), (G_HELL|G_GENO|G_LGROUP|G_NOCORPSE|1),
@@ -522,5 +530,5 @@
 	MR_SLEEP|MR_POISON, MR_SLEEP, M1_POIS|M1_REGEN,
 	M2_HOSTILE|M2_WANDER|M2_STALK|M2_NEUTER,
-	M3_INFRAVISIBLE|M3_INFRAVISION, CLR_BROWN),
+	M3_INFRAVISIBLE|M3_INFRAVISION, 0, CLR_BROWN),
     MON("quasit", S_IMP,
 	LVL(3, 15, 2, 20, -7), (G_GENO|2),
@@ -528,5 +536,5 @@
 	  ATTK(AT_BITE, AD_PHYS, 1, 4), NO_ATTK, NO_ATTK, NO_ATTK),
 	SIZ(200, 200, 0, MS_SILENT, MZ_SMALL), MR_POISON, MR_POISON,
-	M1_REGEN, M2_STALK, M3_INFRAVISIBLE|M3_INFRAVISION, CLR_BLUE),
+	M1_REGEN, M2_STALK, M3_INFRAVISIBLE|M3_INFRAVISION, 0, CLR_BLUE),
     MON("tengu", S_IMP,
 	LVL(6, 13, 5, 30, 7), (G_GENO|3),
@@ -535,5 +543,5 @@
 	SIZ(300, 200, 0, MS_SQAWK, MZ_SMALL), MR_POISON, MR_POISON,
 	M1_TPORT|M1_TPORT_CNTRL, M2_STALK, M3_INFRAVISIBLE|M3_INFRAVISION,
-	CLR_CYAN),
+	0, CLR_CYAN),
 /*
  * jellies
@@ -547,5 +555,5 @@
 	M1_BREATHLESS|M1_AMORPHOUS|M1_NOEYES|M1_NOLIMBS|M1_NOHEAD|M1_MINDLESS
 	  |M1_NOTAKE,
-	M2_HOSTILE|M2_NEUTER, 0, CLR_BLUE),
+	M2_HOSTILE|M2_NEUTER, 0, M4_VULNERABLE_FIRE, CLR_BLUE),
     MON("spotted jelly", S_JELLY,
 	LVL(5, 0, 8, 10, 0), (G_GENO|1),
@@ -555,5 +563,5 @@
 	M1_BREATHLESS|M1_AMORPHOUS|M1_NOEYES|M1_NOLIMBS|M1_NOHEAD|
 	  M1_MINDLESS|M1_ACID|M1_NOTAKE,
-	M2_HOSTILE|M2_NEUTER, 0, CLR_GREEN),
+	M2_HOSTILE|M2_NEUTER, 0, 0, CLR_GREEN),
     MON("ochre jelly", S_JELLY,
 	LVL(6, 3, 8, 20, 0), (G_GENO|2),
@@ -563,5 +571,5 @@
 	M1_BREATHLESS|M1_AMORPHOUS|M1_NOEYES|M1_NOLIMBS|M1_NOHEAD|
 	  M1_MINDLESS|M1_ACID|M1_NOTAKE,
-	M2_HOSTILE|M2_NEUTER, 0, CLR_BROWN),
+	M2_HOSTILE|M2_NEUTER, 0, 0, CLR_BROWN),
 /*
  * kobolds
@@ -573,5 +581,5 @@
 	SIZ(400, 100, 0, MS_ORC, MZ_SMALL), MR_POISON, 0,
 	M1_HUMANOID|M1_POIS|M1_OMNIVORE, M2_HOSTILE|M2_COLLECT,
-	M3_INFRAVISIBLE|M3_INFRAVISION, CLR_BROWN),
+	M3_INFRAVISIBLE|M3_INFRAVISION, 0, CLR_BROWN),
     MON("large kobold", S_KOBOLD,
 	LVL(1, 6, 10, 0, -3), (G_GENO|1),
@@ -580,5 +588,5 @@
 	SIZ(450, 150, 0, MS_ORC, MZ_SMALL), MR_POISON, 0,
 	M1_HUMANOID|M1_POIS|M1_OMNIVORE, M2_HOSTILE|M2_COLLECT,
-	M3_INFRAVISIBLE|M3_INFRAVISION, CLR_RED),
+	M3_INFRAVISIBLE|M3_INFRAVISION, 0, CLR_RED),
     MON("kobold lord", S_KOBOLD,
 	LVL(2, 6, 10, 0, -4), (G_GENO|1),
@@ -588,12 +596,12 @@
 	M1_HUMANOID|M1_POIS|M1_OMNIVORE,
 	M2_HOSTILE|M2_LORD|M2_MALE|M2_COLLECT, M3_INFRAVISIBLE|M3_INFRAVISION,
-	HI_LORD),
+	0, HI_LORD),
     MON("kobold shaman", S_KOBOLD,
 	LVL(2, 6, 6, 10, -4), (G_GENO|1),
-	A(ATTK(AT_MAGC, AD_SPEL, 0, 0),
+	A(ATTK(AT_MAGC, AD_CLRC, 0, 0),
 	  NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
 	SIZ(450, 150, 0, MS_ORC, MZ_SMALL), MR_POISON, 0,
 	M1_HUMANOID|M1_POIS|M1_OMNIVORE, M2_HOSTILE|M2_MAGIC,
-	M3_INFRAVISIBLE|M3_INFRAVISION, HI_ZAP),
+	M3_INFRAVISIBLE|M3_INFRAVISION, 0, HI_ZAP),
 /*
  * leprechauns
@@ -604,5 +612,5 @@
 	  NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
 	SIZ(60, 30, 0, MS_LAUGH, MZ_TINY), 0, 0,
-	M1_HUMANOID|M1_TPORT, M2_HOSTILE|M2_GREEDY, M3_INFRAVISIBLE, CLR_GREEN),
+	M1_HUMANOID|M1_TPORT, M2_HOSTILE|M2_GREEDY, M3_INFRAVISIBLE, 0, CLR_GREEN),
 /*
  * mimics
@@ -615,5 +623,5 @@
 	M1_BREATHLESS|M1_AMORPHOUS|M1_HIDE|M1_ANIMAL|M1_NOEYES|
 	  M1_NOHEAD|M1_NOLIMBS|M1_THICK_HIDE|M1_CARNIVORE,
-	M2_HOSTILE, 0, CLR_BROWN),
+	M2_HOSTILE, 0, 0, CLR_BROWN),
     MON("large mimic", S_MIMIC,
 	LVL(8, 3, 7, 10, 0), (G_GENO|1),
@@ -623,5 +631,5 @@
 	M1_CLING|M1_BREATHLESS|M1_AMORPHOUS|M1_HIDE|M1_ANIMAL|M1_NOEYES|
 	  M1_NOHEAD|M1_NOLIMBS|M1_THICK_HIDE|M1_CARNIVORE,
-	M2_HOSTILE|M2_STRONG, 0, CLR_RED),
+	M2_HOSTILE|M2_STRONG, 0, 0, CLR_RED),
     MON("giant mimic", S_MIMIC,
 	LVL(9, 3, 7, 20, 0), (G_GENO|1),
@@ -631,5 +639,5 @@
 	M1_CLING|M1_BREATHLESS|M1_AMORPHOUS|M1_HIDE|M1_ANIMAL|M1_NOEYES|
 	  M1_NOHEAD|M1_NOLIMBS|M1_THICK_HIDE|M1_CARNIVORE,
-	M2_HOSTILE|M2_STRONG, 0, HI_LORD),
+	M2_HOSTILE|M2_STRONG, 0, 0, HI_LORD),
 /*
  * nymphs
@@ -641,5 +649,5 @@
 	SIZ(600, 300, 0, MS_SEDUCE, MZ_HUMAN), 0, 0,
 	M1_HUMANOID|M1_TPORT, M2_HOSTILE|M2_FEMALE|M2_COLLECT, M3_INFRAVISIBLE,
-	CLR_GREEN),
+	M4_VULNERABLE_FIRE, CLR_GREEN),
     MON("water nymph", S_NYMPH,
 	LVL(3, 12, 9, 20, 0), (G_GENO|2),
@@ -648,5 +656,5 @@
 	SIZ(600, 300, 0, MS_SEDUCE, MZ_HUMAN), 0, 0,
 	M1_HUMANOID|M1_TPORT|M1_SWIM,
-	M2_HOSTILE|M2_FEMALE|M2_COLLECT, M3_INFRAVISIBLE, CLR_BLUE),
+	M2_HOSTILE|M2_FEMALE|M2_COLLECT, M3_INFRAVISIBLE, 0, CLR_BLUE),
     MON("mountain nymph", S_NYMPH,
 	LVL(3, 12, 9, 20, 0), (G_GENO|2),
@@ -655,15 +663,15 @@
 	SIZ(600, 300, 0, MS_SEDUCE, MZ_HUMAN), 0, 0,
 	M1_HUMANOID|M1_TPORT, M2_HOSTILE|M2_FEMALE|M2_COLLECT,
-	M3_INFRAVISIBLE, CLR_BROWN),
+	M3_INFRAVISIBLE, 0, CLR_BROWN),
 /*
  * orcs
  */
     MON("goblin", S_ORC,
-	LVL(0, 6, 10, 0, -3), (G_GENO|2),
+	LVL(0, 6, 10, 0, -3), (G_GENO|2|G_SGROUP),
 	A(ATTK(AT_WEAP, AD_PHYS, 1, 4),
 	  NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
 	SIZ(400, 100, 0, MS_ORC, MZ_SMALL), 0, 0,
 	M1_HUMANOID|M1_OMNIVORE, M2_ORC|M2_COLLECT,
-	M3_INFRAVISIBLE|M3_INFRAVISION, CLR_GRAY),
+	M3_INFRAVISIBLE|M3_INFRAVISION, 0, CLR_GRAY),
     MON("hobgoblin", S_ORC,
 	LVL(1, 9, 10, 0, -4), (G_GENO|2),
@@ -672,5 +680,12 @@
 	SIZ(1000, 200, 0, MS_ORC, MZ_HUMAN), 0, 0,
 	M1_HUMANOID|M1_OMNIVORE, M2_ORC|M2_STRONG|M2_COLLECT,
-	M3_INFRAVISIBLE|M3_INFRAVISION, CLR_BROWN),
+	M3_INFRAVISIBLE|M3_INFRAVISION, 0, CLR_BROWN),
+	 MON("goblin shaman", S_ORC,
+	LVL(2, 9, 10, 0, -4), (G_GENO|2),
+	A(ATTK(AT_MAGC, AD_CLRC, 0, 0),
+	  NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
+	SIZ(400, 100, 0, MS_ORC, MZ_SMALL), 0, 0,
+	M1_HUMANOID|M1_OMNIVORE, M2_ORC|M2_COLLECT,
+	M3_INFRAVISIBLE|M3_INFRAVISION, 0, CLR_GREEN),
 	/* plain "orc" for zombie corpses only; not created at random
 	 */
@@ -681,5 +696,5 @@
 	SIZ(850, 150, 0, MS_ORC, MZ_HUMAN), 0, 0, M1_HUMANOID|M1_OMNIVORE,
 	M2_NOPOLY|M2_ORC|M2_STRONG|M2_GREEDY|M2_JEWELS|M2_COLLECT,
-	M3_INFRAVISIBLE|M3_INFRAVISION, CLR_RED),
+	M3_INFRAVISIBLE|M3_INFRAVISION, 0, CLR_RED),
     MON("hill orc", S_ORC,
 	LVL(2, 9, 10, 0, -4), (G_GENO|G_LGROUP|2),
@@ -688,26 +703,27 @@
 	SIZ(1000, 200, 0, MS_ORC, MZ_HUMAN), 0, 0, M1_HUMANOID|M1_OMNIVORE,
 	M2_ORC|M2_STRONG|M2_GREEDY|M2_JEWELS|M2_COLLECT,
-	M3_INFRAVISIBLE|M3_INFRAVISION, CLR_YELLOW),
+	M3_INFRAVISIBLE|M3_INFRAVISION, 0, CLR_YELLOW),
+	 /* remember, berserk means it's _always_ doubled */
     MON("Mordor orc", S_ORC,
 	LVL(3, 5, 10, 0, -5), (G_GENO|G_LGROUP|1),
-	A(ATTK(AT_WEAP, AD_PHYS, 1, 6),
+	A(ATTK(AT_WEAP, AD_PHYS, 1, 4),
 	  NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
 	SIZ(1200, 200, 0, MS_ORC, MZ_HUMAN), 0, 0, M1_HUMANOID|M1_OMNIVORE,
 	M2_ORC|M2_STRONG|M2_GREEDY|M2_JEWELS|M2_COLLECT,
-	M3_INFRAVISIBLE|M3_INFRAVISION, CLR_BLUE),
+	M3_INFRAVISIBLE|M3_INFRAVISION|M3_BERSERK, 0, CLR_BLUE),
     MON("Uruk-hai", S_ORC,
 	LVL(3, 7, 10, 0, -4), (G_GENO|G_LGROUP|1),
-	A(ATTK(AT_WEAP, AD_PHYS, 1, 8),
+	A(ATTK(AT_WEAP, AD_PHYS, 1, 6),
 	  NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
 	SIZ(1300, 300, 0, MS_ORC, MZ_HUMAN), 0, 0, M1_HUMANOID|M1_OMNIVORE,
 	M2_ORC|M2_STRONG|M2_GREEDY|M2_JEWELS|M2_COLLECT,
-	M3_INFRAVISIBLE|M3_INFRAVISION, CLR_BLACK),
+	M3_EAGLEEYE|M3_INFRAVISIBLE|M3_INFRAVISION|M3_BERSERK, 0, CLR_BLACK),
     MON("orc shaman", S_ORC,
 	LVL(3, 9, 5, 10, -5), (G_GENO|1),
-	A(ATTK(AT_MAGC, AD_SPEL, 0, 0),
+	A(ATTK(AT_MAGC, AD_CLRC, 0, 0),
 	  NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
 	SIZ(1000, 300, 0, MS_ORC, MZ_HUMAN), 0, 0, M1_HUMANOID|M1_OMNIVORE,
 	M2_ORC|M2_STRONG|M2_GREEDY|M2_JEWELS|M2_MAGIC,
-	M3_INFRAVISIBLE|M3_INFRAVISION, HI_ZAP),
+	M3_INFRAVISIBLE|M3_INFRAVISION, 0, HI_ZAP),
     MON("orc-captain", S_ORC,
 	LVL(5, 5, 10, 0, -5), (G_GENO|1),
@@ -716,5 +732,5 @@
 	SIZ(1350, 350, 0, MS_ORC, MZ_HUMAN), 0, 0, M1_HUMANOID|M1_OMNIVORE,
 	M2_ORC|M2_STRONG|M2_GREEDY|M2_JEWELS|M2_COLLECT,
-	M3_INFRAVISIBLE|M3_INFRAVISION, HI_LORD),
+	M3_EAGLEEYE|M3_INFRAVISIBLE|M3_INFRAVISION, 0, HI_LORD),
 /*
  * piercers
@@ -726,5 +742,5 @@
 	SIZ(200, 200, 0, MS_SILENT, MZ_SMALL), 0, 0,
 	M1_CLING|M1_HIDE|M1_ANIMAL|M1_NOEYES|M1_NOLIMBS|M1_CARNIVORE|M1_NOTAKE,
-	M2_HOSTILE, 0, CLR_GRAY),
+	M2_HOSTILE, 0, 0, CLR_GRAY),
     MON("iron piercer", S_PIERCER,
 	LVL(5, 1, 0, 0, 0), (G_GENO|2),
@@ -733,5 +749,5 @@
 	SIZ(400, 300, 0, MS_SILENT, MZ_MEDIUM), 0, 0,
 	M1_CLING|M1_HIDE|M1_ANIMAL|M1_NOEYES|M1_NOLIMBS|M1_CARNIVORE|M1_NOTAKE,
-	M2_HOSTILE, 0, CLR_CYAN),
+	M2_HOSTILE, 0, M4_VULNERABLE_ELEC, CLR_CYAN),
     MON("glass piercer", S_PIERCER,
 	LVL(7, 1, 0, 0, 0), (G_GENO|1),
@@ -740,5 +756,5 @@
 	SIZ(400, 300, 0, MS_SILENT, MZ_MEDIUM), MR_ACID, 0,
 	M1_CLING|M1_HIDE|M1_ANIMAL|M1_NOEYES|M1_NOLIMBS|M1_CARNIVORE|M1_NOTAKE,
-	M2_HOSTILE, 0, CLR_WHITE),
+	M2_HOSTILE, 0, 0, CLR_WHITE),
 /*
  * quadrupeds
@@ -750,5 +766,5 @@
 	SIZ(400, 100, 0, MS_SILENT, MZ_LARGE), 0, 0,
 	M1_ANIMAL|M1_NOHANDS|M1_OMNIVORE, M2_HOSTILE, M3_INFRAVISIBLE,
-	CLR_BROWN),
+	0, CLR_BROWN),
     MON("mumak", S_QUADRUPED,
 	LVL(5, 9, 0, 0, -2), (G_GENO|1),
@@ -757,5 +773,5 @@
 	SIZ(2500, 500, 0, MS_ROAR, MZ_LARGE), 0, 0,
 	M1_ANIMAL|M1_THICK_HIDE|M1_NOHANDS|M1_HERBIVORE,
-	M2_HOSTILE|M2_STRONG, M3_INFRAVISIBLE, CLR_GRAY),
+	M2_HOSTILE|M2_STRONG, M3_INFRAVISIBLE, 0, CLR_GRAY),
     MON("leocrotta", S_QUADRUPED,
 	LVL(6, 18, 4, 10, 0), (G_GENO|2),
@@ -764,5 +780,5 @@
 	SIZ(1200, 500, 0, MS_IMITATE, MZ_LARGE), 0, 0,
 	M1_ANIMAL|M1_NOHANDS|M1_OMNIVORE, M2_HOSTILE|M2_STRONG,
-	M3_INFRAVISIBLE, CLR_RED),
+	M3_INFRAVISIBLE, 0, CLR_RED),
     MON("wumpus", S_QUADRUPED,
 	LVL(8, 3, 2, 10, 0), (G_GENO|1),
@@ -771,26 +787,26 @@
 	SIZ(2500, 500, 0, MS_BURBLE, MZ_LARGE), 0, 0,
 	M1_CLING|M1_ANIMAL|M1_NOHANDS|M1_OMNIVORE,
-	M2_HOSTILE|M2_STRONG, M3_INFRAVISIBLE, CLR_CYAN),
+	M2_HOSTILE|M2_STRONG, M3_INFRAVISIBLE, 0, CLR_CYAN),
     MON("titanothere", S_QUADRUPED,
 	LVL(12, 12, 6, 0, 0), (G_GENO|2),
 	A(ATTK(AT_CLAW, AD_PHYS, 2, 8),
 	  NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
-	SIZ(2650, 650, 0, MS_SILENT, MZ_LARGE), 0, 0,
+	SIZ(2650, 650, 0, MS_SILENT, MZ_HUGE), 0, 0,
 	M1_ANIMAL|M1_THICK_HIDE|M1_NOHANDS|M1_HERBIVORE,
-	M2_HOSTILE|M2_STRONG, M3_INFRAVISIBLE, CLR_GRAY),
+	M2_HOSTILE|M2_STRONG, M3_INFRAVISIBLE, 0, CLR_GRAY),
     MON("baluchitherium", S_QUADRUPED,
 	LVL(14, 12, 5, 0, 0), (G_GENO|2),
 	A(ATTK(AT_CLAW, AD_PHYS, 5, 4), ATTK(AT_CLAW, AD_PHYS, 5, 4),
 	  NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
-	SIZ(3800, 800, 0, MS_SILENT, MZ_LARGE), 0, 0,
+	SIZ(3800, 800, 0, MS_SILENT, MZ_HUGE), 0, 0,
 	M1_ANIMAL|M1_THICK_HIDE|M1_NOHANDS|M1_HERBIVORE,
-	M2_HOSTILE|M2_STRONG, M3_INFRAVISIBLE, CLR_GRAY),
+	M2_HOSTILE|M2_STRONG, M3_INFRAVISIBLE, 0, CLR_GRAY),
     MON("mastodon", S_QUADRUPED,
 	LVL(20, 12, 5, 0, 0), (G_GENO|1),
-	A(ATTK(AT_BUTT, AD_PHYS, 4, 8), ATTK(AT_BUTT, AD_PHYS, 4, 8),
+	A(ATTK(AT_BUTT, AD_PHYS, 3, 8), ATTK(AT_BUTT, AD_PHYS, 3, 8),
 	  NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
-	SIZ(3800, 800, 0, MS_SILENT, MZ_LARGE), 0, 0,
+	SIZ(3800, 800, 0, MS_SILENT, MZ_HUGE), 0, 0,
 	M1_ANIMAL|M1_THICK_HIDE|M1_NOHANDS|M1_HERBIVORE,
-	M2_HOSTILE|M2_STRONG, M3_INFRAVISIBLE, CLR_BLACK),
+	M2_HOSTILE|M2_STRONG, M3_INFRAVISIBLE|M3_BERSERK, 0, CLR_BLACK),
 /*
  * rodents
@@ -802,5 +818,5 @@
 	SIZ(20, 12, 0, MS_SQEEK, MZ_TINY), 0, 0,
 	M1_ANIMAL|M1_NOHANDS|M1_CARNIVORE, M2_HOSTILE, M3_INFRAVISIBLE,
-	CLR_BROWN),
+	0, CLR_BROWN),
     MON("giant rat", S_RODENT,
 	LVL(1, 10, 7, 0, 0), (G_GENO|G_SGROUP|2),
@@ -809,5 +825,5 @@
 	SIZ(30, 30, 0, MS_SQEEK, MZ_TINY), 0, 0,
 	M1_ANIMAL|M1_NOHANDS|M1_CARNIVORE, M2_HOSTILE, M3_INFRAVISIBLE,
-	CLR_BROWN),
+	0, CLR_BROWN),
     MON("rabid rat", S_RODENT,
 	LVL(2, 12, 6, 0, 0), (G_GENO|1),
@@ -816,5 +832,5 @@
 	SIZ(30, 5, 0, MS_SQEEK, MZ_TINY), MR_POISON, 0,
 	M1_ANIMAL|M1_NOHANDS|M1_POIS|M1_CARNIVORE, M2_HOSTILE, M3_INFRAVISIBLE,
-	CLR_BROWN),
+	0, CLR_BROWN),
     MON("wererat", S_RODENT,
 	LVL(2, 12, 6, 10, -7), (G_NOGEN|G_NOCORPSE),
@@ -823,5 +839,5 @@
 	SIZ(40, 30, 0, MS_SQEEK, MZ_TINY), MR_POISON, 0,
 	M1_NOHANDS|M1_POIS|M1_REGEN|M1_CARNIVORE,
-	M2_NOPOLY|M2_WERE|M2_HOSTILE, M3_INFRAVISIBLE, CLR_BROWN),
+	M2_NOPOLY|M2_WERE|M2_HOSTILE, M3_INFRAVISIBLE, 0, CLR_BROWN),
     MON("rock mole", S_RODENT,
 	LVL(3, 3, 0, 20, 0), (G_GENO|2),
@@ -830,5 +846,5 @@
 	SIZ(30, 30, 0, MS_SILENT, MZ_SMALL), 0, 0,
 	M1_TUNNEL|M1_ANIMAL|M1_NOHANDS|M1_METALLIVORE,
-	M2_HOSTILE|M2_GREEDY|M2_JEWELS|M2_COLLECT, M3_INFRAVISIBLE, CLR_GRAY),
+	M2_HOSTILE|M2_GREEDY|M2_JEWELS|M2_COLLECT, M3_INFRAVISIBLE, 0, CLR_GRAY),
     MON("woodchuck", S_RODENT,
 	LVL(3, 3, 0, 20, 0), (G_NOGEN|G_GENO),
@@ -838,5 +854,5 @@
 	M1_TUNNEL/*LOGGING*/|M1_ANIMAL|M1_NOHANDS|M1_SWIM|M1_HERBIVORE,
 		/* In reality, they tunnel instead of cutting lumber.  Oh, well. */
-	M2_WANDER|M2_HOSTILE, M3_INFRAVISIBLE, CLR_BROWN),
+	M2_WANDER|M2_HOSTILE, M3_INFRAVISIBLE, 0, CLR_BROWN),
 /*
  * spiders & scorpions (keep webmaker() in sync if new critters are added)
@@ -848,5 +864,5 @@
 	SIZ(50, 50, 0, MS_SILENT, MZ_TINY), MR_POISON, MR_POISON,
 	M1_CONCEAL|M1_ANIMAL|M1_NOHANDS|M1_OVIPAROUS|M1_CARNIVORE,
-	M2_HOSTILE, 0, CLR_GRAY),
+	M2_HOSTILE, 0, 0, CLR_GRAY),
     MON("centipede", S_SPIDER, 
 	LVL(2, 4, 3, 0, 0), (G_GENO|1),
@@ -855,5 +871,5 @@
 	SIZ(50, 50, 0, MS_SILENT, MZ_TINY), MR_POISON, MR_POISON,
 	M1_CONCEAL|M1_ANIMAL|M1_NOHANDS|M1_OVIPAROUS|M1_CARNIVORE,
-	M2_HOSTILE, 0, CLR_YELLOW),
+	M2_HOSTILE, 0, 0, CLR_YELLOW),
     MON("giant spider", S_SPIDER,
 	LVL(5, 15, 4, 0, 0), (G_GENO|1),
@@ -862,5 +878,5 @@
 	SIZ(100, 100, 0, MS_SILENT, MZ_LARGE), MR_POISON, MR_POISON,
 	M1_ANIMAL|M1_NOHANDS|M1_OVIPAROUS|M1_POIS|M1_CARNIVORE,
-	M2_HOSTILE|M2_STRONG, 0, CLR_MAGENTA),
+	M2_HOSTILE|M2_STRONG, 0, 0, CLR_MAGENTA),
     MON("scorpion", S_SPIDER,
 	LVL(5, 15, 3, 0, 0), (G_GENO|2),
@@ -869,5 +885,5 @@
 	SIZ(50, 100, 0, MS_SILENT, MZ_SMALL), MR_POISON, MR_POISON,
 	M1_CONCEAL|M1_ANIMAL|M1_NOHANDS|M1_OVIPAROUS|M1_POIS|M1_CARNIVORE,
-	M2_HOSTILE, 0, CLR_RED),
+	M2_HOSTILE, M3_EAGLEEYE, 0, CLR_RED),
 /*
  * trappers, lurkers, &c
@@ -879,5 +895,5 @@
 	SIZ(800, 350, 0, MS_SILENT, MZ_HUGE), 0, 0,
 	M1_HIDE|M1_FLY|M1_ANIMAL|M1_NOEYES|M1_NOLIMBS|M1_NOHEAD|M1_CARNIVORE,
-	M2_HOSTILE|M2_STALK|M2_STRONG, 0, CLR_GRAY),
+	M2_HOSTILE|M2_STALK|M2_STRONG, 0, 0, CLR_GRAY),
     MON("trapper", S_TRAPPER,
 	LVL(12, 3, 3, 0, 0), (G_GENO|2),
@@ -886,5 +902,5 @@
 	SIZ(800, 350, 0, MS_SILENT, MZ_HUGE), 0, 0,
 	M1_HIDE|M1_ANIMAL|M1_NOEYES|M1_NOLIMBS|M1_NOHEAD|M1_CARNIVORE,
-	M2_HOSTILE|M2_STALK|M2_STRONG, 0, CLR_GREEN),
+	M2_HOSTILE|M2_STALK|M2_STRONG, 0, 0, CLR_GREEN),
 /*
  * unicorns and horses
@@ -896,5 +912,5 @@
 	SIZ(1300, 300, 0, MS_NEIGH, MZ_LARGE), MR_POISON, MR_POISON,
 	M1_NOHANDS|M1_HERBIVORE, M2_WANDER|M2_STRONG|M2_JEWELS,
-	M3_INFRAVISIBLE, CLR_WHITE),
+	M3_INFRAVISIBLE, 0, CLR_WHITE),
     MON("gray unicorn", S_UNICORN,
 	LVL(4, 24, 2, 70, 0), (G_GENO|1),
@@ -903,5 +919,5 @@
 	SIZ(1300, 300, 0, MS_NEIGH, MZ_LARGE), MR_POISON, MR_POISON,
 	M1_NOHANDS|M1_HERBIVORE, M2_WANDER|M2_STRONG|M2_JEWELS,
-	M3_INFRAVISIBLE, CLR_GRAY),
+	M3_INFRAVISIBLE, 0, CLR_GRAY),
     MON("black unicorn", S_UNICORN,
 	LVL(4, 24, 2, 70, -7), (G_GENO|1),
@@ -910,5 +926,5 @@
 	SIZ(1300, 300, 0, MS_NEIGH, MZ_LARGE), MR_POISON, MR_POISON,
 	M1_NOHANDS|M1_HERBIVORE, M2_WANDER|M2_STRONG|M2_JEWELS,
-	M3_INFRAVISIBLE, CLR_BLACK),
+	M3_INFRAVISIBLE, 0, CLR_BLACK),
     MON("pony", S_UNICORN,
 	LVL(3, 16, 6, 0, 0), (G_GENO|2),
@@ -917,5 +933,5 @@
 	SIZ(1300, 250, 0, MS_NEIGH, MZ_MEDIUM), 0, 0,
 	M1_ANIMAL|M1_NOHANDS|M1_HERBIVORE, M2_WANDER|M2_STRONG|M2_DOMESTIC,
-	M3_INFRAVISIBLE, CLR_BROWN),
+	M3_INFRAVISIBLE, 0, CLR_BROWN),
     MON("horse", S_UNICORN,
 	LVL(5, 20, 5, 0, 0), (G_GENO|2),
@@ -924,5 +940,12 @@
 	SIZ(1500, 300, 0, MS_NEIGH, MZ_LARGE), 0, 0,
 	M1_ANIMAL|M1_NOHANDS|M1_HERBIVORE, M2_WANDER|M2_STRONG|M2_DOMESTIC,
-	M3_INFRAVISIBLE, CLR_BROWN),
+	M3_INFRAVISIBLE, 0, CLR_BROWN),
+     MON("nightmare", S_UNICORN,
+	LVL(5, 20, 5, 0, -9), (G_GENO|2),
+	A(ATTK(AT_KICK, AD_PHYS, 1, 10), ATTK(AT_BITE, AD_DRST, 1, 2),
+	  NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
+	SIZ(1500, 300, 0, MS_NEIGH, MZ_LARGE), MR_POISON, MR_POISON,
+	M1_ANIMAL|M1_NOHANDS|M1_HERBIVORE, M2_WANDER|M2_STRONG|M2_DOMESTIC,
+	M3_INFRAVISIBLE, 0, CLR_GREEN),
     MON("warhorse", S_UNICORN,
 	LVL(7, 24, 4, 0, 0), (G_GENO|2),
@@ -931,5 +954,5 @@
 	SIZ(1800, 350, 0, MS_NEIGH, MZ_LARGE), 0, 0,
 	M1_ANIMAL|M1_NOHANDS|M1_HERBIVORE, M2_WANDER|M2_STRONG|M2_DOMESTIC,
-	M3_INFRAVISIBLE, CLR_BROWN),
+	M3_INFRAVISIBLE, 0, CLR_BROWN),
 /*
  * vortices
@@ -942,5 +965,5 @@
 	M1_FLY|M1_BREATHLESS|M1_NOEYES|M1_NOLIMBS|M1_NOHEAD|M1_MINDLESS|
 	  M1_AMORPHOUS|M1_UNSOLID,
-	M2_HOSTILE|M2_NEUTER, 0, CLR_GRAY),
+	M2_HOSTILE|M2_NEUTER, 0, 0, CLR_GRAY),
     MON("dust vortex", S_VORTEX,
 	LVL(4, 20, 2, 30, 0), (G_GENO|G_NOCORPSE|2),
@@ -949,5 +972,5 @@
 	SIZ(0, 0, 0, MS_SILENT, MZ_HUGE), MR_SLEEP|MR_POISON|MR_STONE, 0,
 	M1_FLY|M1_BREATHLESS|M1_NOEYES|M1_NOLIMBS|M1_NOHEAD|M1_MINDLESS,
-	M2_HOSTILE|M2_NEUTER, 0, CLR_BROWN),
+	M2_HOSTILE|M2_NEUTER, 0, 0, CLR_BROWN),
     MON("ice vortex", S_VORTEX,
 	LVL(5, 20, 2, 30, 0), (G_NOHELL|G_GENO|G_NOCORPSE|1),
@@ -957,5 +980,5 @@
 	MR_COLD|MR_SLEEP|MR_POISON|MR_STONE, 0,
 	M1_FLY|M1_BREATHLESS|M1_NOEYES|M1_NOLIMBS|M1_NOHEAD|M1_MINDLESS,
-	M2_HOSTILE|M2_NEUTER, M3_INFRAVISIBLE, CLR_CYAN),
+	M2_HOSTILE|M2_NEUTER, M3_INFRAVISIBLE, M4_VULNERABLE_FIRE, CLR_CYAN),
     MON("energy vortex", S_VORTEX,
 	LVL(6, 20, 2, 30, 0), (G_GENO|G_NOCORPSE|1),
@@ -966,5 +989,5 @@
 	M1_FLY|M1_BREATHLESS|M1_NOEYES|M1_NOLIMBS|M1_NOHEAD|M1_MINDLESS|
 	  M1_UNSOLID,
-	M2_HOSTILE|M2_NEUTER, 0, HI_ZAP),
+	M2_HOSTILE|M2_NEUTER, 0, 0, HI_ZAP),
     MON("steam vortex", S_VORTEX,
 	LVL(7, 22, 2, 30, 0), (G_HELL|G_GENO|G_NOCORPSE|2),
@@ -975,5 +998,5 @@
 	M1_FLY|M1_BREATHLESS|M1_NOEYES|M1_NOLIMBS|M1_NOHEAD|M1_MINDLESS|
 	  M1_UNSOLID,
-	M2_HOSTILE|M2_NEUTER, M3_INFRAVISIBLE, CLR_BLUE),
+	M2_HOSTILE|M2_NEUTER, M3_INFRAVISIBLE, M4_VULNERABLE_COLD, CLR_BLUE),
     MON("fire vortex", S_VORTEX,
 	LVL(8, 22, 2, 30, 0), (G_HELL|G_GENO|G_NOCORPSE|1),
@@ -984,5 +1007,5 @@
 	M1_FLY|M1_BREATHLESS|M1_NOEYES|M1_NOLIMBS|M1_NOHEAD|M1_MINDLESS|
 	  M1_UNSOLID,
-	M2_HOSTILE|M2_NEUTER, M3_INFRAVISIBLE, CLR_YELLOW),
+	M2_HOSTILE|M2_NEUTER, M3_INFRAVISIBLE, M4_VULNERABLE_COLD, CLR_YELLOW),
 /*
  * worms
@@ -994,5 +1017,5 @@
 	SIZ(600, 250, 0, MS_SILENT, MZ_LARGE), 0, 0,
 	M1_ANIMAL|M1_SLITHY|M1_NOLIMBS|M1_CARNIVORE|M1_NOTAKE,
-	M2_HOSTILE, 0, CLR_BROWN),
+	M2_HOSTILE, 0, 0, CLR_BROWN),
     MON("baby purple worm", S_WORM,
 	LVL(8, 3, 5, 0, 0), G_GENO,
@@ -1001,5 +1024,5 @@
 	SIZ(600, 250, 0, MS_SILENT, MZ_LARGE), 0, 0,
 	M1_ANIMAL|M1_SLITHY|M1_NOLIMBS|M1_CARNIVORE, M2_HOSTILE,
-	0, CLR_MAGENTA),
+	0, 0, CLR_MAGENTA),
     MON("long worm", S_WORM,
 	LVL(8, 3, 5, 10, 0), (G_GENO|2),
@@ -1008,12 +1031,12 @@
 	SIZ(1500, 500, 0, MS_SILENT, MZ_GIGANTIC), 0, 0,
 	M1_ANIMAL|M1_SLITHY|M1_NOLIMBS|M1_OVIPAROUS|M1_CARNIVORE|M1_NOTAKE,
-	M2_HOSTILE|M2_STRONG|M2_NASTY, 0, CLR_BROWN),
+	M2_HOSTILE|M2_STRONG|M2_NASTY, 0, 0, CLR_BROWN),
     MON("purple worm", S_WORM,
 	LVL(15, 9, 6, 20, 0), (G_GENO|2),
-	A(ATTK(AT_BITE, AD_PHYS, 2, 8), ATTK(AT_ENGL, AD_DGST, 1,10),
+	A(ATTK(AT_BITE, AD_PHYS, 2, 8), ATTK(AT_ENGL, AD_DGST, 3,10),
 	  NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
 	SIZ(2700, 700, 0, MS_SILENT, MZ_GIGANTIC), 0, 0,
 	M1_ANIMAL|M1_SLITHY|M1_NOLIMBS|M1_OVIPAROUS|M1_CARNIVORE,
-	M2_HOSTILE|M2_STRONG|M2_NASTY, 0, CLR_MAGENTA),
+	M2_HOSTILE|M2_STRONG|M2_NASTY, 0, 0, CLR_MAGENTA),
 /*
  * xan, &c
@@ -1024,5 +1047,5 @@
 	  NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
 	SIZ(15, 10, 0, MS_BUZZ, MZ_TINY), MR_ELEC|MR_POISON, 0,
-	M1_ANIMAL, M2_HOSTILE, M3_INFRAVISIBLE, CLR_MAGENTA),
+	M1_ANIMAL, M2_HOSTILE, M3_INFRAVISIBLE, 0, CLR_MAGENTA),
     MON("xan", S_XAN,
 	LVL(7, 18, -4, 0, 0), (G_GENO|3),
@@ -1031,5 +1054,5 @@
 	SIZ(300, 300, 0, MS_BUZZ, MZ_TINY), MR_POISON, MR_POISON,
 	M1_FLY|M1_ANIMAL|M1_NOHANDS|M1_POIS, M2_HOSTILE, M3_INFRAVISIBLE,
-	CLR_RED),
+	0, CLR_RED),
 /*
  * lights
@@ -1044,5 +1067,5 @@
 	M1_FLY|M1_BREATHLESS|M1_AMORPHOUS|M1_NOEYES|M1_NOLIMBS|M1_NOHEAD|
 	  M1_MINDLESS|M1_UNSOLID|M1_NOTAKE,
-	M2_HOSTILE|M2_NEUTER, M3_INFRAVISIBLE, CLR_YELLOW),
+	M2_HOSTILE|M2_NEUTER, M3_INFRAVISIBLE, 0, CLR_YELLOW),
     MON("black light", S_LIGHT,
 	LVL(5, 15, 0, 0, 0), (G_NOCORPSE|G_GENO|2),
@@ -1054,5 +1077,5 @@
 	M1_FLY|M1_BREATHLESS|M1_AMORPHOUS|M1_NOEYES|M1_NOLIMBS|M1_NOHEAD|
 	  M1_MINDLESS|M1_UNSOLID|M1_SEE_INVIS|M1_NOTAKE,
-	M2_HOSTILE|M2_NEUTER, 0, CLR_BLACK),
+	M2_HOSTILE|M2_NEUTER, 0, 0, CLR_BLACK),
 /*
  * zruty
@@ -1064,5 +1087,5 @@
 	SIZ(1200, 600, 0, MS_SILENT, MZ_LARGE), 0, 0,
 	M1_ANIMAL|M1_HUMANOID|M1_CARNIVORE,
-	M2_HOSTILE|M2_STRONG, M3_INFRAVISIBLE, CLR_BROWN),
+	M2_HOSTILE|M2_STRONG, M3_INFRAVISIBLE, 0, CLR_BROWN),
 /*
  * Angels and other lawful minions
@@ -1075,18 +1098,18 @@
 	M1_FLY|M1_POIS,
 	M2_MINION|M2_STALK|M2_STRONG|M2_NASTY, M3_INFRAVISIBLE|M3_INFRAVISION,
-	CLR_GREEN),
+	0, CLR_GREEN),
     MON("Aleax", S_ANGEL,
 	LVL(10, 8, 0, 30, 7), (G_NOHELL|G_NOCORPSE|1),
-	A(ATTK(AT_WEAP, AD_PHYS, 1, 6), ATTK(AT_WEAP, AD_PHYS, 1, 6),
-	  ATTK(AT_KICK, AD_PHYS, 1, 4), NO_ATTK, NO_ATTK, NO_ATTK),
+	A(ATTK(AT_WEAP, AD_PHYS, 2, 6), ATTK(AT_WEAP, AD_PHYS, 2, 6),
+	  ATTK(AT_KICK, AD_PHYS, 2, 4), NO_ATTK, NO_ATTK, NO_ATTK),
 	SIZ(WT_HUMAN, 400, 0, MS_IMITATE, MZ_HUMAN),
 	MR_COLD|MR_ELEC|MR_SLEEP|MR_POISON, 0,
 	M1_HUMANOID|M1_SEE_INVIS,
 	M2_MINION|M2_STALK|M2_NASTY|M2_COLLECT, M3_INFRAVISIBLE|M3_INFRAVISION,
-	CLR_YELLOW),
+	0, CLR_YELLOW),
     MON("Angel", S_ANGEL,
 	LVL(14, 10, -4, 55, 12), (G_NOHELL|G_NOCORPSE|1),
-	A(ATTK(AT_WEAP, AD_PHYS, 1, 6), ATTK(AT_WEAP, AD_PHYS, 1, 6), 
-	  ATTK(AT_CLAW, AD_PHYS, 1, 4), ATTK(AT_MAGC, AD_MAGM, 2, 6),
+	A(ATTK(AT_WEAP, AD_PHYS, 3, 6), ATTK(AT_WEAP, AD_PHYS, 3, 6), 
+	  ATTK(AT_CLAW, AD_PHYS, 3, 4), ATTK(AT_MAGC, AD_MAGM, 6, 6),
 	  NO_ATTK, NO_ATTK),
 	SIZ(WT_HUMAN, 400, sizeof(struct epri), MS_CUSS, MZ_HUMAN),
@@ -1094,18 +1117,18 @@
 	M1_FLY|M1_HUMANOID|M1_SEE_INVIS,
 	M2_NOPOLY|M2_MINION|M2_STALK|M2_STRONG|M2_NASTY|M2_COLLECT,
-	M3_INFRAVISIBLE|M3_INFRAVISION, CLR_WHITE),
+	M3_EAGLEEYE|M3_INFRAVISIBLE|M3_INFRAVISION, 0, CLR_WHITE),
     MON("ki-rin", S_ANGEL,
 	LVL(16, 18, -5, 90, 15), (G_NOHELL|G_NOCORPSE|1),
-	A(ATTK(AT_KICK, AD_PHYS, 2, 4), ATTK(AT_KICK, AD_PHYS, 2, 4),
-	  ATTK(AT_BUTT, AD_PHYS, 3, 6), ATTK(AT_MAGC, AD_SPEL, 2, 6),
+	A(ATTK(AT_KICK, AD_PHYS, 4, 4), ATTK(AT_KICK, AD_PHYS, 4, 4),
+	  ATTK(AT_BUTT, AD_PHYS, 4, 6), ATTK(AT_MAGC, AD_SPEL, 2, 6),
 	  NO_ATTK, NO_ATTK),
 	SIZ(WT_HUMAN, 400, 0, MS_NEIGH, MZ_LARGE), 0, 0,
 	M1_FLY|M1_SEE_INVIS,
 	M2_NOPOLY|M2_MINION|M2_STALK|M2_STRONG|M2_NASTY|M2_LORD,
-	M3_INFRAVISIBLE|M3_INFRAVISION, HI_GOLD),
+	M3_INFRAVISIBLE|M3_INFRAVISION, 0, HI_GOLD),
     MON("Archon", S_ANGEL,
 	LVL(19, 16, -6, 80, 15), (G_NOHELL|G_NOCORPSE|1),
-	A(ATTK(AT_WEAP, AD_PHYS, 2, 4), ATTK(AT_WEAP, AD_PHYS, 2, 4),
-	  ATTK(AT_GAZE, AD_BLND, 2, 6), ATTK(AT_CLAW, AD_PHYS, 1, 8),
+	A(ATTK(AT_WEAP, AD_PHYS, 6, 6), ATTK(AT_WEAP, AD_PHYS, 6, 6),
+	  ATTK(AT_GAZE, AD_BLND, 2, 6), ATTK(AT_CLAW, AD_PHYS, 3, 8),
 	  ATTK(AT_MAGC, AD_SPEL, 4, 6), NO_ATTK),
 	SIZ(WT_HUMAN, 400, 0, MS_CUSS, MZ_LARGE),
@@ -1114,5 +1137,5 @@
 	M2_NOPOLY|M2_MINION|M2_STALK|M2_STRONG|M2_NASTY|M2_LORD|
 	  M2_COLLECT|M2_MAGIC,
-	M3_INFRAVISIBLE|M3_INFRAVISION, HI_LORD),
+	M3_EAGLEEYE|M3_INFRAVISIBLE|M3_INFRAVISION, 0, HI_LORD),
 /*
  * Bats
@@ -1123,6 +1146,6 @@
 	  NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
 	SIZ(20, 20, 0, MS_SQEEK, MZ_TINY), 0, 0,
-	M1_FLY|M1_ANIMAL|M1_NOHANDS|M1_CARNIVORE, M2_WANDER, M3_INFRAVISIBLE,
-	CLR_BROWN),
+	M1_FLY|M1_ANIMAL|M1_NOHANDS|M1_CARNIVORE, M2_WANDER, 
+	M3_INFRAVISIBLE|M3_SKITTISH, 0, CLR_BROWN),
     MON("giant bat", S_BAT,
 	LVL(2, 22, 7, 0, 0), (G_GENO|2),
@@ -1131,5 +1154,5 @@
 	SIZ(30, 30, 0, MS_SQEEK, MZ_SMALL), 0, 0,
 	M1_FLY|M1_ANIMAL|M1_NOHANDS|M1_CARNIVORE,
-	M2_WANDER|M2_HOSTILE, M3_INFRAVISIBLE, CLR_RED),
+	M2_WANDER|M2_HOSTILE, M3_INFRAVISIBLE, 0, CLR_RED),
     MON("raven", S_BAT,
 	LVL(4, 20, 6, 0, 0), (G_GENO|2),
@@ -1138,5 +1161,5 @@
 	SIZ(40, 20, 0, MS_SQAWK, MZ_SMALL), 0, 0,
 	M1_FLY|M1_ANIMAL|M1_NOHANDS|M1_CARNIVORE,
-	M2_WANDER|M2_HOSTILE, M3_INFRAVISIBLE, CLR_BLACK),
+	M2_WANDER|M2_HOSTILE, M3_INFRAVISIBLE, 0, CLR_BLACK),
     MON("vampire bat", S_BAT,
 	LVL(5, 20, 6, 0, 0), (G_GENO|2),
@@ -1145,5 +1168,5 @@
 	SIZ(30, 20, 0, MS_SQEEK, MZ_SMALL), MR_SLEEP|MR_POISON, 0,
 	M1_FLY|M1_ANIMAL|M1_NOHANDS|M1_POIS|M1_REGEN|M1_OMNIVORE,
-	M2_HOSTILE, M3_INFRAVISIBLE, CLR_BLACK),
+	M2_HOSTILE, M3_INFRAVISIBLE, M4_VULNERABLE_FIRE, CLR_BLACK),
 /*
  * Centaurs
@@ -1155,5 +1178,5 @@
 	SIZ(2500, 500, 0, MS_HUMANOID, MZ_LARGE), 0, 0,
 	M1_HUMANOID|M1_OMNIVORE, M2_STRONG|M2_GREEDY|M2_COLLECT,
-	M3_INFRAVISIBLE, CLR_BROWN),
+	M3_EAGLEEYE|M3_INFRAVISIBLE|M3_SKITTISH, 0, CLR_BROWN),
     MON("forest centaur", S_CENTAUR,
 	LVL(5, 18, 3, 10, -1), (G_GENO|1),
@@ -1162,5 +1185,5 @@
 	SIZ(2550, 600, 0, MS_HUMANOID, MZ_LARGE), 0, 0,
 	M1_HUMANOID|M1_OMNIVORE, M2_STRONG|M2_GREEDY|M2_COLLECT,
-	M3_INFRAVISIBLE, CLR_GREEN),
+	M3_EAGLEEYE|M3_INFRAVISIBLE|M3_SKITTISH, 0, CLR_GREEN),
     MON("mountain centaur", S_CENTAUR,
 	LVL(6, 20, 2, 10, -3), (G_GENO|1),
@@ -1169,5 +1192,5 @@
 	SIZ(2550, 500, 0, MS_HUMANOID, MZ_LARGE), 0, 0,
 	M1_HUMANOID|M1_OMNIVORE, M2_STRONG|M2_GREEDY|M2_COLLECT,
-	M3_INFRAVISIBLE, CLR_CYAN),
+	M3_EAGLEEYE|M3_INFRAVISIBLE|M3_SKITTISH, 0, CLR_CYAN),
 /*
  * Dragons
@@ -1188,5 +1211,5 @@
 	SIZ(1500, 500, 0, MS_ROAR, MZ_HUGE), 0, 0,
 	M1_FLY|M1_THICK_HIDE|M1_NOHANDS|M1_CARNIVORE,
-	M2_HOSTILE|M2_STRONG|M2_GREEDY|M2_JEWELS, 0, CLR_GRAY),
+	M2_HOSTILE|M2_STRONG|M2_GREEDY|M2_JEWELS, 0, 0, CLR_GRAY),
     MON("baby silver dragon", S_DRAGON,
 	LVL(12, 9, 2, 10, 0), G_GENO,
@@ -1195,5 +1218,5 @@
 	SIZ(1500, 500, 0, MS_ROAR, MZ_HUGE), 0, 0,
 	M1_FLY|M1_THICK_HIDE|M1_NOHANDS|M1_CARNIVORE,
-	M2_HOSTILE|M2_STRONG|M2_GREEDY|M2_JEWELS, 0, DRAGON_SILVER),
+	M2_HOSTILE|M2_STRONG|M2_GREEDY|M2_JEWELS, 0, 0, DRAGON_SILVER),
 #if 0	/* DEFERRED */
     MON("baby shimmering dragon", S_DRAGON,
@@ -1203,5 +1226,5 @@
 	SIZ(1500, 500, 0, MS_ROAR, MZ_HUGE), 0, 0,
 	M1_FLY|M1_THICK_HIDE|M1_NOHANDS|M1_CARNIVORE,
-	M2_HOSTILE|M2_STRONG|M2_GREEDY|M2_JEWELS, 0, CLR_CYAN),
+	M2_HOSTILE|M2_STRONG|M2_GREEDY|M2_JEWELS, 0, 0, CLR_CYAN),
 #endif
     MON("baby red dragon", S_DRAGON,
@@ -1211,5 +1234,6 @@
 	SIZ(1500, 500, 0, MS_ROAR, MZ_HUGE), MR_FIRE, 0,
 	M1_FLY|M1_THICK_HIDE|M1_NOHANDS|M1_CARNIVORE,
-	M2_HOSTILE|M2_STRONG|M2_GREEDY|M2_JEWELS, M3_INFRAVISIBLE, CLR_RED),
+	M2_HOSTILE|M2_STRONG|M2_GREEDY|M2_JEWELS, M3_INFRAVISIBLE, 
+	M4_VULNERABLE_COLD, CLR_RED),
     MON("baby white dragon", S_DRAGON,
 	LVL(12, 9, 2, 10, 0), G_GENO,
@@ -1218,5 +1242,6 @@
 	SIZ(1500, 500, 0, MS_ROAR, MZ_HUGE), MR_COLD, 0,
 	M1_FLY|M1_THICK_HIDE|M1_NOHANDS|M1_CARNIVORE,
-	M2_HOSTILE|M2_STRONG|M2_GREEDY|M2_JEWELS, 0, CLR_WHITE),
+	M2_HOSTILE|M2_STRONG|M2_GREEDY|M2_JEWELS, 0, 
+	M4_VULNERABLE_FIRE, CLR_WHITE),
     MON("baby orange dragon", S_DRAGON,
 	LVL(12, 9, 2, 10, 0), G_GENO,
@@ -1225,5 +1250,5 @@
 	SIZ(1500, 500, 0, MS_ROAR, MZ_HUGE), MR_SLEEP, 0,
 	M1_FLY|M1_THICK_HIDE|M1_NOHANDS|M1_CARNIVORE,
-	M2_HOSTILE|M2_STRONG|M2_GREEDY|M2_JEWELS, 0, CLR_ORANGE),
+	M2_HOSTILE|M2_STRONG|M2_GREEDY|M2_JEWELS, 0, 0, CLR_ORANGE),
     MON("baby black dragon", S_DRAGON,
 	LVL(12, 9, 2, 10, 0), G_GENO,
@@ -1232,5 +1257,5 @@
 	SIZ(1500, 500, 0, MS_ROAR, MZ_HUGE), MR_DISINT, 0,
 	M1_FLY|M1_THICK_HIDE|M1_NOHANDS|M1_CARNIVORE,
-	M2_HOSTILE|M2_STRONG|M2_GREEDY|M2_JEWELS, 0, CLR_BLACK),
+	M2_HOSTILE|M2_STRONG|M2_GREEDY|M2_JEWELS, 0, 0, CLR_BLACK),
     MON("baby blue dragon", S_DRAGON,
 	LVL(12, 9, 2, 10, 0), G_GENO,
@@ -1239,5 +1264,5 @@
 	SIZ(1500, 500, 0, MS_ROAR, MZ_HUGE), MR_ELEC, 0,
 	M1_FLY|M1_THICK_HIDE|M1_NOHANDS|M1_CARNIVORE,
-	M2_HOSTILE|M2_STRONG|M2_GREEDY|M2_JEWELS, 0, CLR_BLUE),
+	M2_HOSTILE|M2_STRONG|M2_GREEDY|M2_JEWELS, 0, 0, CLR_BLUE),
     MON("baby green dragon", S_DRAGON,
 	LVL(12, 9, 2, 10, 0), G_GENO,
@@ -1246,5 +1271,13 @@
 	SIZ(1500, 500, 0, MS_ROAR, MZ_HUGE), MR_POISON, 0,
 	M1_FLY|M1_THICK_HIDE|M1_NOHANDS|M1_CARNIVORE|M1_POIS,
-	M2_HOSTILE|M2_STRONG|M2_GREEDY|M2_JEWELS, 0, CLR_GREEN),
+	M2_HOSTILE|M2_STRONG|M2_GREEDY|M2_JEWELS, 0, 0, CLR_GREEN),
+    MON("baby gold dragon", S_DRAGON,
+	LVL(12, 9, 2, 10, 0), G_GENO,
+	A(ATTK(AT_BITE, AD_PHYS, 2, 6),
+	  NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
+	SIZ(1500, 500, 0, MS_ROAR, MZ_HUGE), MR_FIRE, 0,
+	M1_FLY|M1_THICK_HIDE|M1_NOHANDS|M1_CARNIVORE,
+	M2_HOSTILE|M2_STRONG|M2_GREEDY|M2_JEWELS, M3_INFRAVISIBLE, 
+	M4_VULNERABLE_COLD, HI_GOLD),
     MON("baby yellow dragon", S_DRAGON,
 	LVL(12, 9, 2, 10, 0), G_GENO,
@@ -1253,5 +1286,5 @@
 	SIZ(1500, 500, 0, MS_ROAR, MZ_HUGE), MR_ACID|MR_STONE, 0,
 	M1_FLY|M1_THICK_HIDE|M1_NOHANDS|M1_CARNIVORE|M1_ACID,
-	M2_HOSTILE|M2_STRONG|M2_GREEDY|M2_JEWELS, 0, CLR_YELLOW),
+	M2_HOSTILE|M2_STRONG|M2_GREEDY|M2_JEWELS, 0, 0, CLR_YELLOW),
     MON("gray dragon", S_DRAGON,
 	LVL(15, 9, -1, 20, 4), (G_GENO|1),
@@ -1262,5 +1295,5 @@
 	M1_FLY|M1_THICK_HIDE|M1_NOHANDS|M1_SEE_INVIS|M1_OVIPAROUS|
 	  M1_CARNIVORE,
-	M2_HOSTILE|M2_STRONG|M2_NASTY|M2_GREEDY|M2_JEWELS|M2_MAGIC, 0, CLR_GRAY),
+	M2_HOSTILE|M2_STRONG|M2_NASTY|M2_GREEDY|M2_JEWELS|M2_MAGIC, 0, 0, CLR_GRAY),
     MON("silver dragon", S_DRAGON,
 	LVL(15, 9, -1, 20, 4), (G_GENO|1),
@@ -1272,5 +1305,5 @@
 	  M1_CARNIVORE,
 	M2_HOSTILE|M2_STRONG|M2_NASTY|M2_GREEDY|M2_JEWELS|M2_MAGIC,
-	0, DRAGON_SILVER),
+	0, 0, DRAGON_SILVER),
 #if 0	/* DEFERRED */
     MON("shimmering dragon", S_DRAGON,
@@ -1283,5 +1316,5 @@
 	  M1_CARNIVORE,
 	M2_HOSTILE|M2_STRONG|M2_NASTY|M2_GREEDY|M2_JEWELS|M2_MAGIC,
-	0, CLR_CYAN),
+	0, 0, CLR_CYAN),
 #endif
     MON("red dragon", S_DRAGON,
@@ -1294,5 +1327,5 @@
 	  M1_CARNIVORE,
 	M2_HOSTILE|M2_STRONG|M2_NASTY|M2_GREEDY|M2_JEWELS|M2_MAGIC,
-	M3_INFRAVISIBLE, CLR_RED),
+	M3_INFRAVISIBLE, M4_VULNERABLE_COLD, CLR_RED),
     MON("white dragon", S_DRAGON,
 	LVL(15, 9, -1, 20, -5), (G_GENO|1),
@@ -1303,5 +1336,6 @@
 	M1_FLY|M1_THICK_HIDE|M1_NOHANDS|M1_SEE_INVIS|M1_OVIPAROUS|
 	  M1_CARNIVORE,
-	M2_HOSTILE|M2_STRONG|M2_NASTY|M2_GREEDY|M2_JEWELS|M2_MAGIC, 0, CLR_WHITE),
+	M2_HOSTILE|M2_STRONG|M2_NASTY|M2_GREEDY|M2_JEWELS|M2_MAGIC, 0, 
+	M4_VULNERABLE_FIRE, CLR_WHITE),
     MON("orange dragon", S_DRAGON,
 	LVL(15, 9, -1, 20, 5), (G_GENO|1),
@@ -1313,5 +1347,5 @@
 	  M1_CARNIVORE,
 	M2_HOSTILE|M2_STRONG|M2_NASTY|M2_GREEDY|M2_JEWELS|M2_MAGIC,
-	0, CLR_ORANGE),
+	0, 0, CLR_ORANGE),
     MON("black dragon", S_DRAGON,
 	LVL(15, 9, -1, 20, -6), (G_GENO|1),
@@ -1322,5 +1356,5 @@
 	M1_FLY|M1_THICK_HIDE|M1_NOHANDS|M1_SEE_INVIS|M1_OVIPAROUS|
 	  M1_CARNIVORE,
-	M2_HOSTILE|M2_STRONG|M2_NASTY|M2_GREEDY|M2_JEWELS|M2_MAGIC, 0, CLR_BLACK),
+	M2_HOSTILE|M2_STRONG|M2_NASTY|M2_GREEDY|M2_JEWELS|M2_MAGIC, 0, 0, CLR_BLACK),
     MON("blue dragon", S_DRAGON,
 	LVL(15, 9, -1, 20, -7), (G_GENO|1),
@@ -1331,5 +1365,5 @@
 	M1_FLY|M1_THICK_HIDE|M1_NOHANDS|M1_SEE_INVIS|M1_OVIPAROUS|
 	  M1_CARNIVORE,
-	M2_HOSTILE|M2_STRONG|M2_NASTY|M2_GREEDY|M2_JEWELS|M2_MAGIC, 0, CLR_BLUE),
+	M2_HOSTILE|M2_STRONG|M2_NASTY|M2_GREEDY|M2_JEWELS|M2_MAGIC, 0, 0, CLR_BLUE),
     MON("green dragon", S_DRAGON,
 	LVL(15, 9, -1, 20, 6), (G_GENO|1),
@@ -1340,5 +1374,15 @@
 	M1_FLY|M1_THICK_HIDE|M1_NOHANDS|M1_SEE_INVIS|M1_OVIPAROUS|
 	  M1_CARNIVORE|M1_POIS,
-	M2_HOSTILE|M2_STRONG|M2_NASTY|M2_GREEDY|M2_JEWELS|M2_MAGIC, 0, CLR_GREEN),
+	M2_HOSTILE|M2_STRONG|M2_NASTY|M2_GREEDY|M2_JEWELS|M2_MAGIC, 0, 0, CLR_GREEN),
+    MON("gold dragon", S_DRAGON,
+	LVL(15, 9, -1, 20, -4), (G_GENO|1),
+	A(ATTK(AT_BREA, AD_FIRE, 6, 6), ATTK(AT_BITE, AD_PHYS, 3, 8),
+	  ATTK(AT_CLAW, AD_PHYS, 1, 4), ATTK(AT_CLAW, AD_PHYS, 1, 4),
+	  NO_ATTK, NO_ATTK),
+	SIZ(WT_DRAGON, 1500, 0, MS_ROAR, MZ_GIGANTIC), MR_FIRE, MR_FIRE,
+	M1_FLY|M1_THICK_HIDE|M1_NOHANDS|M1_SEE_INVIS|M1_OVIPAROUS|
+	  M1_CARNIVORE,
+	M2_HOSTILE|M2_STRONG|M2_NASTY|M2_GREEDY|M2_JEWELS|M2_MAGIC,
+	M3_INFRAVISIBLE, M4_VULNERABLE_COLD, HI_GOLD),
     MON("yellow dragon", S_DRAGON,
 	LVL(15, 9, -1, 20, 7), (G_GENO|1),
@@ -1351,5 +1395,5 @@
 	  M1_CARNIVORE|M1_ACID,
 	M2_HOSTILE|M2_STRONG|M2_NASTY|M2_GREEDY|M2_JEWELS|M2_MAGIC,
-	0, CLR_YELLOW),
+	0, 0, CLR_YELLOW),
 /*
  * Elementals
@@ -1361,5 +1405,5 @@
 	SIZ(900, 400, 0, MS_SILENT, MZ_LARGE), 0, 0,
 	M1_ANIMAL|M1_FLY|M1_SEE_INVIS,
-	M2_WANDER|M2_STALK|M2_HOSTILE|M2_STRONG, M3_INFRAVISION, CLR_WHITE),
+	M2_WANDER|M2_STALK|M2_HOSTILE|M2_STRONG, M3_INFRAVISION, 0, CLR_WHITE),
     MON("air elemental", S_ELEMENTAL,
 	LVL(8, 36, 2, 30, 0), (G_NOCORPSE|1),
@@ -1368,5 +1412,5 @@
 	SIZ(0, 0, 0, MS_SILENT, MZ_HUGE), MR_POISON|MR_STONE, 0,
 	M1_NOEYES|M1_NOLIMBS|M1_NOHEAD|M1_MINDLESS|M1_UNSOLID|M1_FLY,
-	M2_STRONG|M2_NEUTER, 0, CLR_CYAN),
+	M2_STRONG|M2_NEUTER, 0, 0, CLR_CYAN),
     MON("fire elemental", S_ELEMENTAL,
 	LVL(8, 12, 2, 30, 0), (G_NOCORPSE|1),
@@ -1375,5 +1419,5 @@
 	SIZ(0, 0, 0, MS_SILENT, MZ_HUGE), MR_FIRE|MR_POISON|MR_STONE, 0,
 	M1_NOEYES|M1_NOLIMBS|M1_NOHEAD|M1_MINDLESS|M1_UNSOLID|M1_FLY|M1_NOTAKE,
-	M2_STRONG|M2_NEUTER, M3_INFRAVISIBLE, CLR_YELLOW),
+	M2_STRONG|M2_NEUTER, M3_INFRAVISIBLE, M4_VULNERABLE_COLD, CLR_YELLOW),
     MON("earth elemental", S_ELEMENTAL,
 	LVL(8, 6, 2, 30, 0), (G_NOCORPSE|1),
@@ -1384,5 +1428,5 @@
 	M1_NOEYES|M1_NOLIMBS|M1_NOHEAD|M1_MINDLESS|M1_BREATHLESS|
 	  M1_WALLWALK|M1_THICK_HIDE,
-	M2_STRONG|M2_NEUTER, 0, CLR_BROWN),
+	M2_STRONG|M2_NEUTER, 0, M4_VULNERABLE_ACID, CLR_BROWN),
     MON("water elemental", S_ELEMENTAL,
 	LVL(8, 6, 2, 30, 0), (G_NOCORPSE|1),
@@ -1391,5 +1435,5 @@
 	SIZ(2500, 0, 0, MS_SILENT, MZ_HUGE), MR_POISON|MR_STONE, 0,
 	M1_NOEYES|M1_NOLIMBS|M1_NOHEAD|M1_MINDLESS|M1_AMPHIBIOUS|M1_SWIM,
-	M2_STRONG|M2_NEUTER, 0, CLR_BLUE),
+	M2_STRONG|M2_NEUTER, 0, M4_VULNERABLE_ELEC, CLR_BLUE),
 /*
  * Fungi
@@ -1401,5 +1445,5 @@
 	SIZ(20, 200, 0, MS_SILENT, MZ_SMALL), 0, 0,
 	M1_BREATHLESS|M1_NOEYES|M1_NOLIMBS|M1_NOHEAD|M1_MINDLESS|M1_NOTAKE,
-	M2_HOSTILE|M2_NEUTER, 0, CLR_BRIGHT_GREEN),
+	M2_HOSTILE|M2_NEUTER, 0, 0, CLR_BRIGHT_GREEN),
     MON("brown mold", S_FUNGUS,
 	LVL(1, 0, 9, 0, 0), (G_GENO|1),
@@ -1409,5 +1453,5 @@
 	MR_COLD|MR_POISON, MR_COLD|MR_POISON,
 	M1_BREATHLESS|M1_NOEYES|M1_NOLIMBS|M1_NOHEAD|M1_MINDLESS|M1_NOTAKE,
-	M2_HOSTILE|M2_NEUTER, 0, CLR_BROWN),
+	M2_HOSTILE|M2_NEUTER, 0, M4_VULNERABLE_FIRE, CLR_BROWN),
     MON("yellow mold", S_FUNGUS,
 	LVL(1, 0, 9, 0, 0), (G_GENO|2),
@@ -1416,5 +1460,5 @@
 	SIZ(50, 30, 0, MS_SILENT, MZ_SMALL), MR_POISON, MR_POISON,
 	M1_BREATHLESS|M1_NOEYES|M1_NOLIMBS|M1_NOHEAD|M1_MINDLESS|M1_POIS|M1_NOTAKE,
-	M2_HOSTILE|M2_NEUTER, 0, CLR_YELLOW),
+	M2_HOSTILE|M2_NEUTER, 0, 0, CLR_YELLOW),
     MON("green mold", S_FUNGUS,
 	LVL(1, 0, 9, 0, 0), (G_GENO|1),
@@ -1423,5 +1467,5 @@
 	SIZ(50, 30, 0, MS_SILENT, MZ_SMALL), MR_ACID|MR_STONE, MR_STONE,
 	M1_BREATHLESS|M1_NOEYES|M1_NOLIMBS|M1_NOHEAD|M1_MINDLESS|M1_ACID|M1_NOTAKE,
-	M2_HOSTILE|M2_NEUTER, 0, CLR_GREEN),
+	M2_HOSTILE|M2_NEUTER, 0, 0, CLR_GREEN),
     MON("red mold", S_FUNGUS,
 	LVL(1, 0, 9, 0, 0), (G_GENO|1),
@@ -1431,5 +1475,5 @@
 	MR_FIRE|MR_POISON, MR_FIRE|MR_POISON,
 	M1_BREATHLESS|M1_NOEYES|M1_NOLIMBS|M1_NOHEAD|M1_MINDLESS|M1_NOTAKE,
-	M2_HOSTILE|M2_NEUTER, M3_INFRAVISIBLE, CLR_RED),
+	M2_HOSTILE|M2_NEUTER, M3_INFRAVISIBLE, M4_VULNERABLE_COLD, CLR_RED),
     MON("shrieker", S_FUNGUS,
 	LVL(3, 1, 7, 0, 0), (G_GENO|1),
@@ -1437,5 +1481,5 @@
 	SIZ(100, 100, 0, MS_SHRIEK, MZ_SMALL), MR_POISON, MR_POISON,
 	M1_BREATHLESS|M1_NOEYES|M1_NOLIMBS|M1_NOHEAD|M1_MINDLESS|M1_NOTAKE,
-	M2_HOSTILE|M2_NEUTER, 0, CLR_MAGENTA),
+	M2_HOSTILE|M2_NEUTER, 0, 0, CLR_MAGENTA),
     MON("violet fungus", S_FUNGUS,
 	LVL(3, 1, 7, 0, 0), (G_GENO|2),
@@ -1444,5 +1488,12 @@
 	SIZ(100, 100, 0, MS_SILENT, MZ_SMALL), MR_POISON, MR_POISON,
 	M1_BREATHLESS|M1_NOEYES|M1_NOLIMBS|M1_NOHEAD|M1_MINDLESS|M1_NOTAKE,
-	M2_HOSTILE|M2_NEUTER, 0, CLR_MAGENTA),
+	M2_HOSTILE|M2_NEUTER, 0, 0, CLR_MAGENTA),
+    MON("gray fungus", S_FUNGUS,
+	LVL(3, 0, 7, 0, 0), (G_GENO|2),
+	A(ATTK(AT_NONE, AD_DISE, 0, 2),
+	  NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
+	SIZ(50, 30, 0, MS_SILENT, MZ_SMALL), MR_POISON, MR_POISON,
+	M1_BREATHLESS|M1_NOEYES|M1_NOLIMBS|M1_NOHEAD|M1_MINDLESS|M1_NOTAKE|M1_POIS,
+	M2_HOSTILE|M2_NEUTER, 0, 0, CLR_GRAY),
 /*
  * Gnomes
@@ -1454,5 +1505,5 @@
 	SIZ(650, 100, 0, MS_ORC, MZ_SMALL), 0, 0,
 	M1_HUMANOID|M1_OMNIVORE, M2_NOPOLY|M2_GNOME|M2_COLLECT,
-	M3_INFRAVISIBLE|M3_INFRAVISION, CLR_BROWN),
+	M3_INFRAVISIBLE|M3_INFRAVISION, 0, CLR_BROWN),
     MON("gnome lord", S_GNOME,
 	LVL(3, 8, 10, 4, 0), (G_GENO|2),
@@ -1461,5 +1512,5 @@
 	SIZ(700, 120, 0, MS_ORC, MZ_SMALL), 0, 0,
 	M1_HUMANOID|M1_OMNIVORE, M2_GNOME|M2_LORD|M2_MALE|M2_COLLECT,
-	M3_INFRAVISIBLE|M3_INFRAVISION, CLR_BLUE),
+	M3_INFRAVISIBLE|M3_INFRAVISION, 0, CLR_BLUE),
     MON("gnomish wizard", S_GNOME,
 	LVL(3, 10, 4, 10, 0), (G_GENO|1),
@@ -1468,5 +1519,5 @@
 	SIZ(700, 120, 0, MS_ORC, MZ_SMALL), 0, 0,
 	M1_HUMANOID|M1_OMNIVORE, M2_GNOME|M2_MAGIC,
-	M3_INFRAVISIBLE|M3_INFRAVISION, HI_ZAP),
+	M3_INFRAVISIBLE|M3_INFRAVISION, 0, HI_ZAP),
     MON("gnome king", S_GNOME,
 	LVL(5, 10, 10, 20, 0), (G_GENO|1),
@@ -1475,5 +1526,5 @@
 	SIZ(750, 150, 0, MS_ORC, MZ_SMALL), 0, 0,
 	M1_HUMANOID|M1_OMNIVORE, M2_GNOME|M2_PRINCE|M2_MALE|M2_COLLECT,
-	M3_INFRAVISIBLE|M3_INFRAVISION, HI_LORD),
+	M3_EAGLEEYE|M3_INFRAVISIBLE|M3_INFRAVISION, 0, HI_LORD),
 #ifdef SPLITMON_1
 };
@@ -1505,5 +1556,5 @@
 	M1_HUMANOID|M1_CARNIVORE,
 	M2_GIANT|M2_STRONG|M2_ROCKTHROW|M2_NASTY|M2_COLLECT|M2_JEWELS,
-	M3_INFRAVISIBLE|M3_INFRAVISION, CLR_RED),
+	M3_INFRAVISIBLE|M3_INFRAVISION, 0, CLR_RED),
     MON("stone giant", S_GIANT,
 	LVL(6, 6, 0, 0, 2), (G_GENO|G_SGROUP|1),
@@ -1513,5 +1564,13 @@
 	M1_HUMANOID|M1_CARNIVORE,
 	M2_GIANT|M2_STRONG|M2_ROCKTHROW|M2_NASTY|M2_COLLECT|M2_JEWELS,
-	M3_INFRAVISIBLE|M3_INFRAVISION, CLR_GRAY),
+	M3_INFRAVISIBLE|M3_INFRAVISION, 0, CLR_GRAY),
+    MON("hill giant shaman", S_GIANT,
+	LVL(7, 10, 4, 0, -3), (G_GENO|2),
+	A(ATTK(AT_MAGC, AD_CLRC, 0, 0),
+	  NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
+	SIZ(2200, 700, 0, MS_BOAST, MZ_HUGE), 0, 0,
+	M1_HUMANOID|M1_CARNIVORE,
+	M2_GIANT|M2_STRONG|M2_ROCKTHROW|M2_NASTY|M2_COLLECT|M2_JEWELS,
+	M3_INFRAVISIBLE|M3_INFRAVISION, 0, HI_ZAP),
     MON("hill giant", S_GIANT,
 	LVL(8, 10, 6, 0, -2), (G_GENO|G_SGROUP|1),
@@ -1521,5 +1580,5 @@
 	M1_HUMANOID|M1_CARNIVORE,
 	M2_GIANT|M2_STRONG|M2_ROCKTHROW|M2_NASTY|M2_COLLECT|M2_JEWELS,
-	M3_INFRAVISIBLE|M3_INFRAVISION, CLR_CYAN),
+	M3_INFRAVISIBLE|M3_INFRAVISION, 0, CLR_CYAN),
     MON("fire giant", S_GIANT,
 	LVL(9, 12, 4, 5, 2), (G_GENO|G_SGROUP|1),
@@ -1529,5 +1588,5 @@
 	M1_HUMANOID|M1_CARNIVORE,
 	M2_GIANT|M2_STRONG|M2_ROCKTHROW|M2_NASTY|M2_COLLECT|M2_JEWELS,
-	M3_INFRAVISIBLE|M3_INFRAVISION, CLR_YELLOW),
+	M3_INFRAVISIBLE|M3_INFRAVISION|M3_BERSERK, M4_VULNERABLE_COLD, CLR_YELLOW),
     MON("frost giant", S_GIANT,
 	LVL(10, 12, 3, 10, -3), (G_NOHELL|G_GENO|G_SGROUP|1),
@@ -1537,5 +1596,5 @@
 	M1_HUMANOID|M1_CARNIVORE,
 	M2_GIANT|M2_STRONG|M2_ROCKTHROW|M2_NASTY|M2_COLLECT|M2_JEWELS,
-	M3_INFRAVISIBLE|M3_INFRAVISION, CLR_WHITE),
+	M3_INFRAVISIBLE|M3_INFRAVISION|M3_BERSERK, M4_VULNERABLE_FIRE, CLR_WHITE),
     MON("storm giant", S_GIANT,
 	LVL(16, 12, 3, 10, -3), (G_GENO|G_SGROUP|1),
@@ -1545,5 +1604,5 @@
 	M1_HUMANOID|M1_CARNIVORE,
 	M2_GIANT|M2_STRONG|M2_ROCKTHROW|M2_NASTY|M2_COLLECT|M2_JEWELS,
-	M3_INFRAVISIBLE|M3_INFRAVISION, CLR_BLUE),
+	M3_INFRAVISIBLE|M3_INFRAVISION|M3_BERSERK, 0, CLR_BLUE),
     MON("ettin", S_GIANT,
 	LVL(10, 12, 3, 0, 0), (G_GENO|1),
@@ -1553,5 +1612,5 @@
 	M1_ANIMAL|M1_HUMANOID|M1_CARNIVORE,
 	M2_HOSTILE|M2_STRONG|M2_NASTY|M2_COLLECT,
-	M3_INFRAVISIBLE|M3_INFRAVISION, CLR_BROWN),
+	M3_INFRAVISIBLE|M3_INFRAVISION|M3_BERSERK, 0, CLR_BROWN),
     MON("titan", S_GIANT,
 	LVL(16, 18, -3, 70, 9), (1),
@@ -1561,5 +1620,5 @@
 	M1_FLY|M1_HUMANOID|M1_OMNIVORE,
 	M2_STRONG|M2_ROCKTHROW|M2_NASTY|M2_COLLECT|M2_MAGIC,
-	M3_INFRAVISIBLE|M3_INFRAVISION, CLR_MAGENTA),
+	M3_EAGLEEYE|M3_INFRAVISIBLE|M3_INFRAVISION, 0, CLR_MAGENTA),
     MON("minotaur", S_GIANT,
 	LVL(15, 15, 6, 0, 0), (G_GENO|G_NOGEN),
@@ -1569,9 +1628,16 @@
 	M1_ANIMAL|M1_HUMANOID|M1_CARNIVORE,
 	M2_HOSTILE|M2_STRONG|M2_NASTY, M3_INFRAVISIBLE|M3_INFRAVISION,
-	CLR_BROWN),
+	0, CLR_BROWN),
 /* 'I' is a visual marker for all invisible monsters and must be unused */
 /*
- * Jabberwock
+ * Jabberwocks (and Carroll-ish fictional monsters)
  */
+	 MON("snark", S_JABBERWOCK,
+	LVL(12, 18, 0, 30, 0), (G_GENO|2),
+	A(ATTK(AT_BITE, AD_PHYS, 2,6), ATTK(AT_BITE, AD_PHYS, 2,6),
+		NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
+	SIZ(400, 200, 0, MS_SILENT, MZ_LARGE), MR_DISINT, MR_DISINT,
+	M1_ANIMAL|M1_FLY|M1_CARNIVORE,
+	M2_HOSTILE|M2_STRONG|M2_NOPOLY, M3_SKITTISH|M3_INFRAVISIBLE, 0, CLR_WHITE),
     MON("jabberwock", S_JABBERWOCK,
 	LVL(15, 12, -2, 50, 0), (G_GENO|1),
@@ -1581,5 +1647,16 @@
 	SIZ(1300, 600, 0, MS_BURBLE, MZ_LARGE), 0, 0,
 	M1_ANIMAL|M1_FLY|M1_CARNIVORE,
-	M2_HOSTILE|M2_STRONG|M2_NASTY|M2_COLLECT, M3_INFRAVISIBLE, CLR_ORANGE),
+	M2_HOSTILE|M2_STRONG|M2_NASTY|M2_COLLECT, M3_INFRAVISIBLE, 0, CLR_ORANGE),
+	 /* boojum only come from snarks */
+	 MON("boojum", S_JABBERWOCK,
+	LVL(18, 15, 0, 90, 0), (G_NOGEN),
+	A(ATTK(AT_BITE, AD_PHYS, 3,10), ATTK(AT_CLAW, AD_PHYS, 3,10),
+	  ATTK(AT_CLAW, AD_PHYS, 3,10), ATTK(AT_CLAW, AD_TLPT, 0,0),
+		 NO_ATTK, NO_ATTK),
+	SIZ(400, 200, 0, MS_SILENT, MZ_LARGE), 
+	MR_FIRE|MR_ELEC|MR_DISINT, 
+	MR_FIRE|MR_ELEC|MR_DISINT,
+	M1_ANIMAL|M1_FLY|M1_CARNIVORE|M1_SEE_INVIS,
+	M2_HOSTILE|M2_NOPOLY|M2_STRONG, M3_INFRAVISIBLE, 0, CLR_YELLOW),
 #if 0	/* DEFERRED */
     MON("vorpal jabberwock", S_JABBERWOCK,       
@@ -1590,5 +1667,5 @@
 	SIZ(1300, 600, 0, MS_BURBLE, MZ_LARGE), 0, 0,
 	M1_ANIMAL|M1_FLY|M1_CARNIVORE,
-	M2_HOSTILE|M2_STRONG|M2_NASTY|M2_COLLECT, M3_INFRAVISIBLE, HI_LORD),
+	M2_HOSTILE|M2_STRONG|M2_NASTY|M2_COLLECT, M3_INFRAVISIBLE, 0, HI_LORD),
 #endif
 #ifdef KOPS
@@ -1602,5 +1679,5 @@
 	SIZ(WT_HUMAN, 200, 0, MS_ARREST, MZ_HUMAN), 0, 0, M1_HUMANOID,
 	M2_HUMAN|M2_WANDER|M2_HOSTILE|M2_MALE|M2_COLLECT, M3_INFRAVISIBLE,
-	CLR_BLUE),
+	0, CLR_BLUE),
     MON("Kop Sergeant", S_KOP,
 	LVL(2, 8, 10, 10, 10), (G_GENO|G_SGROUP|G_NOGEN),
@@ -1609,5 +1686,5 @@
 	SIZ(WT_HUMAN, 200, 0, MS_ARREST, MZ_HUMAN), 0, 0, M1_HUMANOID,
 	M2_HUMAN|M2_WANDER|M2_HOSTILE|M2_STRONG|M2_MALE|M2_COLLECT,
-	M3_INFRAVISIBLE, CLR_BLUE),
+	M3_INFRAVISIBLE, 0, CLR_BLUE),
     MON("Kop Lieutenant", S_KOP,
 	LVL(3, 10, 10, 20, 11), (G_GENO|G_NOGEN),
@@ -1616,5 +1693,5 @@
 	SIZ(WT_HUMAN, 200, 0, MS_ARREST, MZ_HUMAN), 0, 0, M1_HUMANOID,
 	M2_HUMAN|M2_WANDER|M2_HOSTILE|M2_STRONG|M2_MALE|M2_COLLECT,
-	M3_INFRAVISIBLE, CLR_CYAN),
+	M3_INFRAVISIBLE, 0, CLR_CYAN),
     MON("Kop Kaptain", S_KOP,
 	LVL(4, 12, 10, 20, 12), (G_GENO|G_NOGEN),
@@ -1623,5 +1700,5 @@
 	SIZ(WT_HUMAN, 200, 0, MS_ARREST, MZ_HUMAN), 0, 0, M1_HUMANOID,
 	M2_HUMAN|M2_WANDER|M2_HOSTILE|M2_STRONG|M2_MALE|M2_COLLECT,
-	M3_INFRAVISIBLE, HI_LORD),
+	M3_EAGLEEYE|M3_INFRAVISIBLE, 0, HI_LORD),
 #endif
 /*
@@ -1634,6 +1711,6 @@
 	SIZ(1200, 100, 0, MS_MUMBLE, MZ_HUMAN),
 	MR_COLD|MR_SLEEP|MR_POISON, MR_COLD,
-	M1_BREATHLESS|M1_HUMANOID|M1_POIS|M1_REGEN,
-	M2_UNDEAD|M2_HOSTILE|M2_MAGIC, M3_INFRAVISION, CLR_BROWN),
+	M1_SEE_INVIS|M1_BREATHLESS|M1_HUMANOID|M1_POIS|M1_REGEN,
+	M2_UNDEAD|M2_HOSTILE|M2_MAGIC, M3_INFRAVISION, M4_VULNERABLE_FIRE, CLR_BROWN),
     MON("demilich", S_LICH,
 	LVL(14, 9, -2, 60, -12), (G_GENO|G_NOCORPSE|1),
@@ -1642,6 +1719,6 @@
 	SIZ(1200, 100, 0, MS_MUMBLE, MZ_HUMAN),
 	MR_COLD|MR_SLEEP|MR_POISON, MR_COLD,
-	M1_BREATHLESS|M1_HUMANOID|M1_POIS|M1_REGEN,
-	M2_UNDEAD|M2_HOSTILE|M2_MAGIC, M3_INFRAVISION, CLR_RED),
+	M1_SEE_INVIS|M1_BREATHLESS|M1_HUMANOID|M1_POIS|M1_REGEN,
+	M2_UNDEAD|M2_HOSTILE|M2_MAGIC, M3_INFRAVISION, M4_VULNERABLE_FIRE, CLR_RED),
     MON("master lich", S_LICH,
 	LVL(17, 9, -4, 90, -15), (G_HELL|G_GENO|G_NOCORPSE|1),
@@ -1649,7 +1726,7 @@
 	  NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
 	SIZ(1200, 100, 0, MS_MUMBLE, MZ_HUMAN),
-	MR_FIRE|MR_COLD|MR_SLEEP|MR_POISON, MR_FIRE|MR_COLD,
-	M1_BREATHLESS|M1_HUMANOID|M1_POIS|M1_REGEN,
-	M2_UNDEAD|M2_HOSTILE|M2_MAGIC, M3_WANTSBOOK|M3_INFRAVISION, HI_LORD),
+	MR_COLD|MR_SLEEP|MR_POISON, MR_COLD,
+	M1_SEE_INVIS|M1_BREATHLESS|M1_HUMANOID|M1_POIS|M1_REGEN,
+	M2_UNDEAD|M2_HOSTILE|M2_MAGIC, M3_INFRAVISION, M4_VULNERABLE_FIRE, CLR_GREEN),
     MON("arch-lich", S_LICH,
 	LVL(25, 9, -6, 90, -15), (G_HELL|G_GENO|G_NOCORPSE|1),
@@ -1657,7 +1734,7 @@
 	  NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
 	SIZ(1200, 100, 0, MS_MUMBLE, MZ_HUMAN),
-	MR_FIRE|MR_COLD|MR_SLEEP|MR_ELEC|MR_POISON, MR_FIRE|MR_COLD,
-	M1_BREATHLESS|M1_HUMANOID|M1_POIS|M1_REGEN,
-	M2_UNDEAD|M2_HOSTILE|M2_MAGIC, M3_WANTSBOOK|M3_INFRAVISION, HI_LORD),
+	MR_COLD|MR_SLEEP|MR_ELEC|MR_POISON, MR_COLD,
+	M1_SEE_INVIS|M1_BREATHLESS|M1_HUMANOID|M1_POIS|M1_REGEN,
+	M2_UNDEAD|M2_HOSTILE|M2_MAGIC, M3_WANTSBOOK|M3_INFRAVISION, M4_VULNERABLE_FIRE, HI_LORD),
 /*
  * Mummies
@@ -1669,5 +1746,5 @@
 	SIZ(400, 50, 0, MS_SILENT, MZ_SMALL), MR_COLD|MR_SLEEP|MR_POISON, 0,
 	M1_BREATHLESS|M1_MINDLESS|M1_HUMANOID|M1_POIS,
-	M2_UNDEAD|M2_HOSTILE, M3_INFRAVISION, CLR_BROWN),
+	M2_UNDEAD|M2_HOSTILE, M3_INFRAVISION, M4_VULNERABLE_FIRE, CLR_BROWN),
     MON("gnome mummy", S_MUMMY,
 	LVL(4, 10, 6, 20, -3), (G_GENO|G_NOCORPSE|1),
@@ -1676,5 +1753,5 @@
 	SIZ(650, 50, 0, MS_SILENT, MZ_SMALL), MR_COLD|MR_SLEEP|MR_POISON, 0,
 	M1_BREATHLESS|M1_MINDLESS|M1_HUMANOID|M1_POIS,
-	M2_UNDEAD|M2_HOSTILE|M2_GNOME, M3_INFRAVISION, CLR_RED),
+	M2_UNDEAD|M2_HOSTILE|M2_GNOME, M3_INFRAVISION, M4_VULNERABLE_FIRE, CLR_RED),
     MON("orc mummy", S_MUMMY,
 	LVL(5, 10, 5, 20, -4), (G_GENO|G_NOCORPSE|1),
@@ -1683,6 +1760,7 @@
 	SIZ(850, 75, 0, MS_SILENT, MZ_HUMAN), MR_COLD|MR_SLEEP|MR_POISON, 0,
 	M1_BREATHLESS|M1_MINDLESS|M1_HUMANOID|M1_POIS,
-	M2_UNDEAD|M2_HOSTILE|M2_ORC|M2_GREEDY|M2_JEWELS, M3_INFRAVISION,
-	CLR_GRAY),
+	M2_UNDEAD|M2_HOSTILE|M2_ORC|M2_GREEDY|M2_JEWELS, 
+	M3_INFRAVISION|M3_BERSERK,
+	M4_VULNERABLE_FIRE, CLR_GRAY),
     MON("dwarf mummy", S_MUMMY,
 	LVL(5, 10, 5, 20, -4), (G_GENO|G_NOCORPSE|1),
@@ -1692,5 +1770,5 @@
 	M1_BREATHLESS|M1_MINDLESS|M1_HUMANOID|M1_POIS,
 	M2_UNDEAD|M2_HOSTILE|M2_DWARF|M2_GREEDY|M2_JEWELS, M3_INFRAVISION,
-	CLR_RED),
+	M4_VULNERABLE_FIRE, CLR_RED),
     MON("elf mummy", S_MUMMY,
 	LVL(6, 12, 4, 30, -5), (G_GENO|G_NOCORPSE|1),
@@ -1700,5 +1778,5 @@
 	MR_COLD|MR_SLEEP|MR_POISON, 0,
 	M1_BREATHLESS|M1_MINDLESS|M1_HUMANOID|M1_POIS,
-	M2_UNDEAD|M2_HOSTILE|M2_ELF, M3_INFRAVISION, CLR_GREEN),
+	M2_UNDEAD|M2_HOSTILE|M2_ELF, M3_EAGLEEYE|M3_INFRAVISION, M4_VULNERABLE_FIRE, CLR_GREEN),
     MON("human mummy", S_MUMMY,
 	LVL(6, 12, 4, 30, -5), (G_GENO|G_NOCORPSE|1),
@@ -1708,5 +1786,5 @@
 	MR_COLD|MR_SLEEP|MR_POISON, 0,
 	M1_BREATHLESS|M1_MINDLESS|M1_HUMANOID|M1_POIS,
-	M2_UNDEAD|M2_HOSTILE, M3_INFRAVISION, CLR_GRAY),
+	M2_UNDEAD|M2_HOSTILE, M3_INFRAVISION|M3_BERSERK, M4_VULNERABLE_FIRE, CLR_GRAY),
     MON("ettin mummy", S_MUMMY,
 	LVL(7, 12, 4, 30, -6), (G_GENO|G_NOCORPSE|1),
@@ -1716,5 +1794,5 @@
 	MR_COLD|MR_SLEEP|MR_POISON, 0,
 	M1_BREATHLESS|M1_MINDLESS|M1_HUMANOID|M1_POIS,
-	M2_UNDEAD|M2_HOSTILE|M2_STRONG, M3_INFRAVISION, CLR_BLUE),
+	M2_UNDEAD|M2_HOSTILE|M2_STRONG, M3_INFRAVISION|M3_BERSERK, M4_VULNERABLE_FIRE, CLR_BLUE),
     MON("giant mummy", S_MUMMY,
 	LVL(8, 14, 3, 30, -7), (G_GENO|G_NOCORPSE|1),
@@ -1724,6 +1802,7 @@
 	MR_COLD|MR_SLEEP|MR_POISON, 0,
 	M1_BREATHLESS|M1_MINDLESS|M1_HUMANOID|M1_POIS,
-	M2_UNDEAD|M2_HOSTILE|M2_GIANT|M2_STRONG|M2_JEWELS, M3_INFRAVISION,
-	CLR_CYAN),
+	M2_UNDEAD|M2_HOSTILE|M2_GIANT|M2_STRONG|M2_JEWELS, 
+	M3_INFRAVISION|M3_BERSERK,
+	M4_VULNERABLE_FIRE, CLR_CYAN),
 /*
  * Nagas
@@ -1736,5 +1815,5 @@
 	MR_FIRE|MR_POISON, MR_FIRE|MR_POISON,
 	M1_NOLIMBS|M1_SLITHY|M1_THICK_HIDE|M1_NOTAKE|M1_OMNIVORE, M2_STRONG,
-	M3_INFRAVISIBLE, CLR_RED),
+	M3_INFRAVISIBLE, M4_VULNERABLE_COLD, CLR_RED),
     MON("black naga hatchling", S_NAGA,
 	LVL(3, 10, 6, 0, 0), G_GENO,
@@ -1744,5 +1823,5 @@
 	MR_POISON|MR_ACID|MR_STONE, MR_POISON|MR_STONE,
 	M1_NOLIMBS|M1_SLITHY|M1_THICK_HIDE|M1_ACID|M1_NOTAKE|M1_CARNIVORE,
-	M2_STRONG, 0, CLR_BLACK),
+	M2_STRONG, 0, 0, CLR_BLACK),
     MON("golden naga hatchling", S_NAGA,
 	LVL(3, 10, 6, 0, 0), G_GENO,
@@ -1751,5 +1830,5 @@
 	SIZ(500, 100, 0, MS_MUMBLE, MZ_LARGE), MR_POISON, MR_POISON,
 	M1_NOLIMBS|M1_SLITHY|M1_THICK_HIDE|M1_NOTAKE|M1_OMNIVORE,
-	M2_STRONG, 0, HI_GOLD),
+	M2_STRONG, 0, 0, HI_GOLD),
     MON("guardian naga hatchling", S_NAGA,
 	LVL(3, 10, 6, 0, 0), G_GENO,
@@ -1758,5 +1837,5 @@
 	SIZ(500, 100, 0, MS_MUMBLE, MZ_LARGE), MR_POISON, MR_POISON,
 	M1_NOLIMBS|M1_SLITHY|M1_THICK_HIDE|M1_NOTAKE|M1_OMNIVORE,
-	M2_STRONG, 0, CLR_GREEN),
+	M2_STRONG, 0, 0, CLR_GREEN),
     MON("red naga", S_NAGA,
 	LVL(6, 12, 4, 0, -4), (G_GENO|1),
@@ -1766,5 +1845,5 @@
 	MR_FIRE|MR_POISON, MR_FIRE|MR_POISON,
 	M1_NOLIMBS|M1_SLITHY|M1_THICK_HIDE|M1_OVIPAROUS|M1_NOTAKE|M1_OMNIVORE,
-	M2_STRONG, M3_INFRAVISIBLE, CLR_RED),
+	M2_STRONG, M3_INFRAVISIBLE, M4_VULNERABLE_COLD, CLR_RED),
     MON("black naga", S_NAGA,
 	LVL(8, 14, 2, 10, 4), (G_GENO|1),
@@ -1775,5 +1854,5 @@
 	M1_NOLIMBS|M1_SLITHY|M1_THICK_HIDE|M1_OVIPAROUS|M1_ACID|M1_NOTAKE|
 	  M1_CARNIVORE,
-	M2_STRONG, 0, CLR_BLACK),
+	M2_STRONG, 0, 0, CLR_BLACK),
     MON("golden naga", S_NAGA,
 	LVL(10, 14, 2, 70, 5), (G_GENO|1),
@@ -1782,5 +1861,5 @@
 	SIZ(2600, 400, 0, MS_MUMBLE, MZ_HUGE), MR_POISON, MR_POISON,
 	M1_NOLIMBS|M1_SLITHY|M1_THICK_HIDE|M1_OVIPAROUS|M1_NOTAKE|M1_OMNIVORE,
-	M2_STRONG, 0, HI_GOLD),
+	M2_STRONG, 0, 0, HI_GOLD),
     MON("guardian naga", S_NAGA,
 	LVL(12, 16, 0, 50, 7), (G_GENO|1),
@@ -1790,5 +1869,5 @@
 	M1_NOLIMBS|M1_SLITHY|M1_THICK_HIDE|M1_OVIPAROUS|M1_POIS|M1_NOTAKE|
 	  M1_OMNIVORE,
-	M2_STRONG, 0, CLR_GREEN),
+	M2_STRONG, 0, 0, CLR_GREEN),
 /*
  * Ogres
@@ -1800,5 +1879,5 @@
 	SIZ(1600, 500, 0, MS_GRUNT, MZ_LARGE), 0, 0, M1_HUMANOID|M1_CARNIVORE,
 	M2_STRONG|M2_GREEDY|M2_JEWELS|M2_COLLECT,
-	M3_INFRAVISIBLE|M3_INFRAVISION, CLR_BROWN),
+	M3_INFRAVISIBLE|M3_INFRAVISION|M3_BERSERK, 0, CLR_BROWN),
     MON("ogre lord", S_OGRE,
 	LVL(7, 12, 3, 30, -5), (G_GENO|2),
@@ -1807,5 +1886,5 @@
 	SIZ(1700, 700, 0, MS_GRUNT, MZ_LARGE), 0, 0, M1_HUMANOID|M1_CARNIVORE,
 	M2_STRONG|M2_LORD|M2_MALE|M2_GREEDY|M2_JEWELS|M2_COLLECT,
-	M3_INFRAVISIBLE|M3_INFRAVISION, CLR_RED),
+	M3_INFRAVISIBLE|M3_INFRAVISION, 0, CLR_RED),
     MON("ogre king", S_OGRE,
 	LVL(9, 14, 4, 60, -7), (G_GENO|2),
@@ -1814,5 +1893,5 @@
 	SIZ(1700, 750, 0, MS_GRUNT, MZ_LARGE), 0, 0, M1_HUMANOID|M1_CARNIVORE,
 	M2_STRONG|M2_PRINCE|M2_MALE|M2_GREEDY|M2_JEWELS|M2_COLLECT,
-	M3_INFRAVISIBLE|M3_INFRAVISION, HI_LORD),
+	M3_EAGLEEYE|M3_INFRAVISIBLE|M3_INFRAVISION, 0, HI_LORD),
 /*
  * Puddings
@@ -1826,5 +1905,5 @@
 	M1_BREATHLESS|M1_AMORPHOUS|M1_NOEYES|M1_NOLIMBS|M1_NOHEAD|
 	  M1_MINDLESS|M1_OMNIVORE|M1_ACID,
-	M2_HOSTILE|M2_NEUTER, 0, CLR_GRAY),
+	M2_HOSTILE|M2_NEUTER, 0, 0, CLR_GRAY),
     MON("brown pudding", S_PUDDING,
 	LVL(5, 3, 8, 0, 0), (G_GENO|1),
@@ -1835,5 +1914,5 @@
 	M1_BREATHLESS|M1_AMORPHOUS|M1_NOEYES|M1_NOLIMBS|M1_NOHEAD|
 	  M1_MINDLESS|M1_OMNIVORE|M1_ACID,
-	M2_HOSTILE|M2_NEUTER, 0, CLR_BROWN),
+	M2_HOSTILE|M2_NEUTER, 0, M4_VULNERABLE_FIRE, CLR_BROWN),
     MON("black pudding", S_PUDDING,
 	LVL(10, 6, 6, 0, 0), (G_GENO|1),
@@ -1844,5 +1923,5 @@
 	M1_BREATHLESS|M1_AMORPHOUS|M1_NOEYES|M1_NOLIMBS|M1_NOHEAD|
 	  M1_MINDLESS|M1_OMNIVORE|M1_ACID,
-	M2_HOSTILE|M2_NEUTER, 0, CLR_BLACK),
+	M2_HOSTILE|M2_NEUTER, 0, M4_VULNERABLE_FIRE, CLR_BLACK),
     MON("green slime", S_PUDDING, 
 	LVL(6, 6, 6, 0, 0), (G_HELL|G_GENO|1),
@@ -1853,5 +1932,5 @@
 	M1_BREATHLESS|M1_AMORPHOUS|M1_NOEYES|M1_NOLIMBS|M1_NOHEAD|
 	  M1_MINDLESS|M1_OMNIVORE|M1_ACID|M1_POIS,
-	M2_HOSTILE|M2_NEUTER, 0, CLR_GREEN),
+	M2_HOSTILE|M2_NEUTER, 0, M4_VULNERABLE_FIRE, CLR_GREEN),
 /*
  * Quantum mechanics
@@ -1863,5 +1942,5 @@
 	SIZ(WT_HUMAN, 20, 0, MS_HUMANOID, MZ_HUMAN), MR_POISON, 0,
 	M1_HUMANOID|M1_OMNIVORE|M1_POIS|M1_TPORT, M2_HOSTILE, M3_INFRAVISIBLE,
-	CLR_CYAN),
+	0, CLR_CYAN),
 /*
  * Rust monster or disenchanter
@@ -1873,5 +1952,5 @@
 	SIZ(1000, 250, 0, MS_SILENT, MZ_MEDIUM), 0, 0,
 	M1_SWIM|M1_ANIMAL|M1_NOHANDS|M1_METALLIVORE, M2_HOSTILE,
-	M3_INFRAVISIBLE, CLR_BROWN),
+	M3_INFRAVISIBLE, 0, CLR_BROWN),
     MON("disenchanter", S_RUSTMONST,
 	LVL(12, 12, -10, 0, -3), (G_HELL|G_GENO|2),
@@ -1880,5 +1959,5 @@
 	SIZ(750, 200, 0, MS_GROWL, MZ_LARGE), 0, 0,
 	M1_ANIMAL|M1_CARNIVORE, M2_HOSTILE,
-	M3_INFRAVISIBLE, CLR_BLUE),
+	M3_INFRAVISIBLE, 0, CLR_BLUE),
 /*
  * Snakes
@@ -1891,5 +1970,5 @@
 	M1_SWIM|M1_CONCEAL|M1_NOLIMBS|M1_ANIMAL|M1_SLITHY|M1_OVIPAROUS|
 	  M1_CARNIVORE|M1_NOTAKE,
-	0, 0, CLR_GREEN),
+	0, 0, 0, CLR_GREEN),
     MON("snake", S_SNAKE,
 	LVL(4, 15, 3, 0, 0), (G_GENO|2),
@@ -1899,5 +1978,5 @@
 	M1_SWIM|M1_CONCEAL|M1_NOLIMBS|M1_ANIMAL|M1_SLITHY|M1_POIS|
 	  M1_OVIPAROUS|M1_CARNIVORE|M1_NOTAKE,
-	M2_HOSTILE, 0, CLR_BROWN),
+	M2_HOSTILE, 0, 0, CLR_BROWN),
     MON("water moccasin", S_SNAKE,
 	LVL(4, 15, 3, 0, 0), (G_GENO|G_NOGEN|G_LGROUP),
@@ -1907,5 +1986,5 @@
 	M1_SWIM|M1_CONCEAL|M1_NOLIMBS|M1_ANIMAL|M1_SLITHY|M1_POIS|
 	  M1_CARNIVORE|M1_OVIPAROUS|M1_NOTAKE,
-	M2_HOSTILE, 0, CLR_RED),
+	M2_HOSTILE, 0, 0, CLR_RED),
     MON("pit viper", S_SNAKE,
 	LVL(6, 15, 2, 0, 0), (G_GENO|1),
@@ -1916,5 +1995,5 @@
 	M1_SWIM|M1_CONCEAL|M1_NOLIMBS|M1_ANIMAL|M1_SLITHY|M1_POIS|
 	  M1_CARNIVORE|M1_OVIPAROUS|M1_NOTAKE,
-	M2_HOSTILE, M3_INFRAVISION, CLR_BLUE),
+	M2_HOSTILE, M3_INFRAVISION, 0, CLR_BLUE),
     MON("python", S_SNAKE,
 	LVL(6, 3, 5, 0, 0), (G_GENO|1),
@@ -1925,5 +2004,5 @@
 	M1_SWIM|M1_NOLIMBS|M1_ANIMAL|M1_SLITHY|
 	  M1_CARNIVORE|M1_OVIPAROUS|M1_NOTAKE,
-	M2_HOSTILE|M2_STRONG, M3_INFRAVISION, CLR_MAGENTA),
+	M2_HOSTILE|M2_STRONG, M3_INFRAVISION, 0, CLR_MAGENTA),
     MON("cobra", S_SNAKE,
 	LVL(6, 18, 2, 0, 0), (G_GENO|1),
@@ -1934,5 +2013,5 @@
 	M1_SWIM|M1_CONCEAL|M1_NOLIMBS|M1_ANIMAL|M1_SLITHY|M1_POIS|
 	  M1_CARNIVORE|M1_OVIPAROUS|M1_NOTAKE,
-	M2_HOSTILE, 0, CLR_BLUE),
+	M2_HOSTILE, M3_EAGLEEYE, 0, CLR_BLUE),
 /*
  * Trolls
@@ -1945,5 +2024,5 @@
 	M1_HUMANOID|M1_REGEN|M1_CARNIVORE,
 	M2_STRONG|M2_STALK|M2_HOSTILE, M3_INFRAVISIBLE|M3_INFRAVISION,
-	CLR_BROWN),
+	0, CLR_BROWN),
     MON("ice troll", S_TROLL,
 	LVL(9, 10, 2, 20, -3), (G_NOHELL|G_GENO|1),
@@ -1953,5 +2032,5 @@
 	M1_HUMANOID|M1_REGEN|M1_CARNIVORE,
 	M2_STRONG|M2_STALK|M2_HOSTILE, M3_INFRAVISIBLE|M3_INFRAVISION,
-	CLR_WHITE),
+	M4_VULNERABLE_FIRE, CLR_WHITE),
     MON("rock troll", S_TROLL,
 	LVL(9, 12, 0, 0, -3), (G_GENO|1),
@@ -1961,5 +2040,5 @@
 	M1_HUMANOID|M1_REGEN|M1_CARNIVORE,
 	M2_STRONG|M2_STALK|M2_HOSTILE|M2_COLLECT,
-	M3_INFRAVISIBLE|M3_INFRAVISION, CLR_CYAN),
+	M3_INFRAVISIBLE|M3_INFRAVISION, 0, CLR_CYAN),
     MON("water troll", S_TROLL,
 	LVL(11, 14, 4, 40, -3), (G_NOGEN|G_GENO),
@@ -1969,5 +2048,5 @@
 	M1_HUMANOID|M1_REGEN|M1_CARNIVORE|M1_SWIM,
 	M2_STRONG|M2_STALK|M2_HOSTILE, M3_INFRAVISIBLE|M3_INFRAVISION,
-	CLR_BLUE),
+	M4_VULNERABLE_ELEC, CLR_BLUE),
     MON("Olog-hai", S_TROLL,
 	LVL(13, 12, -4, 0, -7), (G_GENO|1),
@@ -1977,5 +2056,5 @@
 	M1_HUMANOID|M1_REGEN|M1_CARNIVORE,
 	M2_STRONG|M2_STALK|M2_HOSTILE|M2_COLLECT,
-	M3_INFRAVISIBLE|M3_INFRAVISION, HI_LORD),
+	M3_EAGLEEYE|M3_INFRAVISIBLE|M3_INFRAVISION, 0, HI_LORD),
 /*
  * Umber hulk
@@ -1987,5 +2066,21 @@
 	  NO_ATTK, NO_ATTK),
 	SIZ(1200, 500, 0, MS_SILENT, MZ_LARGE), 0, 0,
-	M1_TUNNEL|M1_CARNIVORE, M2_STRONG, M3_INFRAVISIBLE, CLR_BROWN),
+	M1_TUNNEL|M1_CARNIVORE, M2_STRONG, M3_INFRAVISIBLE, 0, CLR_BROWN),
+/*
+ * Placeholder for the random creature...
+ *
+ * None of these stats have any significance, they're just to ensure
+ * that if one does get accidentally generated in the 'normal' way
+ * (without a remapped permonst) that nothing useful happens.
+ *
+ * Also note that the LVL value will affect your generated
+ * monster's internal difficulty in monstr.h; be careful to leave this
+ * fairly high as random permutations of ATTK() could make it nasty
+ */
+	 MON("shambling horror", S_UMBER,
+	LVL(10, 12, 0, 0, 0), (G_NOCORPSE|2),
+	A(NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
+	SIZ(25, 25, 0, MS_SILENT, MZ_TINY), 0, 0,
+	M1_CARNIVORE, 0, M3_INFRAVISIBLE, 0, DRAGON_SILVER),
 /*
  * Vampires
@@ -1998,5 +2093,5 @@
 	M1_FLY|M1_BREATHLESS|M1_HUMANOID|M1_POIS|M1_REGEN,
 	M2_UNDEAD|M2_STALK|M2_HOSTILE|M2_STRONG|M2_NASTY, M3_INFRAVISIBLE,
-	CLR_RED),
+	M4_VULNERABLE_FIRE, CLR_RED),
     MON("vampire lord", S_VAMPIRE,
 	LVL(12, 14, 0, 50, -9), (G_GENO|G_NOCORPSE|1),
@@ -2006,5 +2101,5 @@
 	M1_FLY|M1_BREATHLESS|M1_HUMANOID|M1_POIS|M1_REGEN,
 	M2_UNDEAD|M2_STALK|M2_HOSTILE|M2_STRONG|M2_NASTY|M2_LORD|M2_MALE,
-	M3_INFRAVISIBLE, CLR_BLUE),
+	M3_INFRAVISIBLE, M4_VULNERABLE_FIRE, CLR_BLUE),
 #if 0	/* DEFERRED */
     MON("vampire mage", S_VAMPIRE,
@@ -2015,15 +2110,15 @@
 	M1_FLY|M1_BREATHLESS|M1_HUMANOID|M1_POIS|M1_REGEN,
 	M2_UNDEAD|M2_STALK|M2_HOSTILE|M2_STRONG|M2_NASTY|M2_LORD|M2_MALE|
-	M2_MAGIC, M3_INFRAVISIBLE, HI_ZAP),
+	M2_MAGIC, M3_INFRAVISIBLE, 0, HI_ZAP),
 #endif
     MON("Vlad the Impaler", S_VAMPIRE,
 	LVL(14, 18, -3, 80, -10), (G_NOGEN|G_NOCORPSE|G_UNIQ),
 	A(ATTK(AT_WEAP, AD_PHYS, 1, 10), ATTK(AT_BITE, AD_DRLI, 1, 10),
-	  NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
+	  ATTK(AT_MAGC, AD_SPEL, 4, 6), NO_ATTK, NO_ATTK, NO_ATTK),
 	SIZ(WT_HUMAN, 400, 0, MS_VAMPIRE, MZ_HUMAN), MR_SLEEP|MR_POISON, 0,
-	M1_FLY|M1_BREATHLESS|M1_HUMANOID|M1_POIS|M1_REGEN,
+	M1_FLY|M1_BREATHLESS|M1_HUMANOID|M1_POIS|M1_REGEN|M1_SEE_INVIS,
 	M2_NOPOLY|M2_UNDEAD|M2_STALK|M2_HOSTILE|M2_PNAME|M2_STRONG|
 	  M2_NASTY|M2_PRINCE|M2_MALE,
-	M3_WAITFORU|M3_WANTSCAND|M3_INFRAVISIBLE, HI_LORD),
+	M3_EAGLEEYE|M3_WAITFORU|M3_WANTSCAND|M3_INFRAVISIBLE, M4_VULNERABLE_FIRE, HI_LORD),
 /*
  * Wraiths
@@ -2035,5 +2130,5 @@
 	SIZ(1200, 0, 0, MS_SPELL, MZ_HUMAN), MR_COLD|MR_SLEEP|MR_POISON, 0,
 	M1_BREATHLESS|M1_HUMANOID,
-	M2_UNDEAD|M2_STALK|M2_HOSTILE|M2_COLLECT, 0, CLR_GRAY),
+	M2_UNDEAD|M2_STALK|M2_HOSTILE|M2_COLLECT, 0, M4_VULNERABLE_FIRE, CLR_GRAY),
     MON("wraith", S_WRAITH,
 	LVL(6, 12, 4, 15, -6), (G_GENO|2),
@@ -2043,13 +2138,13 @@
 	MR_COLD|MR_SLEEP|MR_POISON|MR_STONE, 0,
 	M1_BREATHLESS|M1_FLY|M1_HUMANOID|M1_UNSOLID,
-	M2_UNDEAD|M2_STALK|M2_HOSTILE, 0, CLR_BLACK),
+	M2_UNDEAD|M2_STALK|M2_HOSTILE, 0, 0, CLR_BLACK),
     MON("Nazgul", S_WRAITH,
 	LVL(13, 12, 0, 25, -17), (G_GENO|G_NOCORPSE|1),
 	A(ATTK(AT_WEAP, AD_DRLI, 1, 4), ATTK(AT_BREA, AD_SLEE, 2,25),
-	  NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
+	  ATTK(AT_SCRE, AD_STUN, 2, 8), NO_ATTK, NO_ATTK, NO_ATTK),
 	SIZ(WT_HUMAN, 0, 0, MS_SPELL, MZ_HUMAN),
-	MR_COLD|MR_SLEEP|MR_POISON, 0, M1_BREATHLESS|M1_HUMANOID,
+	MR_COLD|MR_SLEEP|MR_POISON, 0, M1_BREATHLESS|M1_HUMANOID|M1_SEE_INVIS,
 	M2_NOPOLY|M2_UNDEAD|M2_STALK|M2_STRONG|M2_HOSTILE|M2_MALE|M2_COLLECT,
-	0, HI_LORD),
+	M3_EAGLEEYE, 0, HI_LORD),
 /*
  * Xorn
@@ -2063,5 +2158,5 @@
 	MR_FIRE|MR_COLD|MR_STONE, MR_STONE,
 	M1_BREATHLESS|M1_WALLWALK|M1_THICK_HIDE|M1_METALLIVORE,
-	M2_HOSTILE|M2_STRONG, 0, CLR_BROWN),
+	M2_HOSTILE|M2_STRONG, 0, 0, CLR_BROWN),
 /*
  * Apelike beasts
@@ -2072,5 +2167,5 @@
 	  NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
 	SIZ(100, 50, 0, MS_GROWL, MZ_SMALL), 0, 0,
-	M1_ANIMAL|M1_HUMANOID|M1_CARNIVORE, 0, M3_INFRAVISIBLE, CLR_GRAY),
+	M1_ANIMAL|M1_HUMANOID|M1_CARNIVORE, 0, M3_INFRAVISIBLE, 0, CLR_GRAY),
     MON("ape", S_YETI,
 	LVL(4, 12, 6, 0, 0), (G_GENO|G_SGROUP|2),
@@ -2079,5 +2174,5 @@
 	SIZ(1100, 500, 0, MS_GROWL, MZ_LARGE), 0, 0,
 	M1_ANIMAL|M1_HUMANOID|M1_CARNIVORE, M2_STRONG, M3_INFRAVISIBLE,
-	CLR_BROWN),
+	0, CLR_BROWN),
     MON("owlbear", S_YETI,
 	LVL(5, 12, 5, 0, 0), (G_GENO|3),
@@ -2086,5 +2181,5 @@
 	SIZ(1700, 700, 0, MS_ROAR, MZ_LARGE), 0, 0,
 	M1_ANIMAL|M1_HUMANOID|M1_CARNIVORE,
-	M2_HOSTILE|M2_STRONG|M2_NASTY, M3_INFRAVISIBLE, CLR_BROWN),
+	M2_HOSTILE|M2_STRONG|M2_NASTY, M3_INFRAVISIBLE, 0, CLR_BROWN),
     MON("yeti", S_YETI,
 	LVL(5, 15, 6, 0, 0), (G_GENO|2),
@@ -2093,5 +2188,5 @@
 	SIZ(1600, 700, 0, MS_GROWL, MZ_LARGE), MR_COLD, MR_COLD,
 	M1_ANIMAL|M1_HUMANOID|M1_CARNIVORE, M2_HOSTILE|M2_STRONG,
-	M3_INFRAVISIBLE, CLR_WHITE),
+	M3_INFRAVISIBLE, M4_VULNERABLE_FIRE, CLR_WHITE),
     MON("carnivorous ape", S_YETI,
 	LVL(6, 12, 6, 0, 0), (G_GENO|1),
@@ -2100,5 +2195,5 @@
 	SIZ(1250, 550, 0, MS_GROWL, MZ_LARGE), 0, 0,
 	M1_ANIMAL|M1_HUMANOID|M1_CARNIVORE, M2_HOSTILE|M2_STRONG,
-	M3_INFRAVISIBLE, CLR_BLACK),
+	M3_INFRAVISIBLE, 0, CLR_BLACK),
     MON("sasquatch", S_YETI,
 	LVL(7, 15, 6, 0, 2), (G_GENO|1),
@@ -2107,5 +2202,5 @@
 	SIZ(1550, 750, 0, MS_GROWL, MZ_LARGE), 0, 0,
 	M1_ANIMAL|M1_HUMANOID|M1_SEE_INVIS|M1_OMNIVORE, M2_STRONG,
-	M3_INFRAVISIBLE, CLR_GRAY),
+	M3_INFRAVISIBLE, 0, CLR_GRAY),
 /*
  * Zombies
@@ -2117,5 +2212,5 @@
 	SIZ(400, 50, 0, MS_SILENT, MZ_SMALL), MR_COLD|MR_SLEEP|MR_POISON, 0,
 	M1_BREATHLESS|M1_MINDLESS|M1_HUMANOID|M1_POIS,
-	M2_UNDEAD|M2_STALK|M2_HOSTILE, M3_INFRAVISION, CLR_BROWN),
+	M2_UNDEAD|M2_STALK|M2_HOSTILE, M3_INFRAVISION, M4_VULNERABLE_FIRE, CLR_BROWN),
     MON("gnome zombie", S_ZOMBIE,
 	LVL(1, 6, 10, 0, -2), (G_GENO|G_NOCORPSE|1),
@@ -2124,5 +2219,5 @@
 	SIZ(650, 50, 0, MS_SILENT, MZ_SMALL), MR_COLD|MR_SLEEP|MR_POISON, 0,
 	M1_BREATHLESS|M1_MINDLESS|M1_HUMANOID|M1_POIS,
-	M2_UNDEAD|M2_STALK|M2_HOSTILE|M2_GNOME, M3_INFRAVISION, CLR_BROWN),
+	M2_UNDEAD|M2_STALK|M2_HOSTILE|M2_GNOME, M3_INFRAVISION, M4_VULNERABLE_FIRE, CLR_BROWN),
     MON("orc zombie", S_ZOMBIE,
 	LVL(2, 6, 9, 0, -3), (G_GENO|G_SGROUP|G_NOCORPSE|1),
@@ -2131,5 +2226,6 @@
 	SIZ(850, 75, 0, MS_SILENT, MZ_HUMAN), MR_COLD|MR_SLEEP|MR_POISON, 0,
 	M1_BREATHLESS|M1_MINDLESS|M1_HUMANOID|M1_POIS,
-	M2_UNDEAD|M2_STALK|M2_HOSTILE|M2_ORC, M3_INFRAVISION, CLR_GRAY),
+	M2_UNDEAD|M2_STALK|M2_HOSTILE|M2_ORC, 
+	M3_INFRAVISION|M3_BERSERK, M4_VULNERABLE_FIRE, CLR_GRAY),
     MON("dwarf zombie", S_ZOMBIE,
 	LVL(2, 6, 9, 0, -3), (G_GENO|G_SGROUP|G_NOCORPSE|1),
@@ -2138,5 +2234,5 @@
 	SIZ(900, 150, 0, MS_SILENT, MZ_HUMAN), MR_COLD|MR_SLEEP|MR_POISON, 0,
 	M1_BREATHLESS|M1_MINDLESS|M1_HUMANOID|M1_POIS,
-	M2_UNDEAD|M2_STALK|M2_HOSTILE|M2_DWARF, M3_INFRAVISION, CLR_RED),
+	M2_UNDEAD|M2_STALK|M2_HOSTILE|M2_DWARF, M3_INFRAVISION, M4_VULNERABLE_FIRE, CLR_RED),
     MON("elf zombie", S_ZOMBIE,
 	LVL(3, 6, 9, 0, -3), (G_GENO|G_SGROUP|G_NOCORPSE|1),
@@ -2146,5 +2242,6 @@
 	MR_COLD|MR_SLEEP|MR_POISON, 0,
 	M1_BREATHLESS|M1_MINDLESS|M1_HUMANOID,
-	M2_UNDEAD|M2_STALK|M2_HOSTILE|M2_ELF, M3_INFRAVISION, CLR_GREEN),
+	M2_UNDEAD|M2_STALK|M2_HOSTILE|M2_ELF, M3_EAGLEEYE|M3_INFRAVISION, 
+	M4_VULNERABLE_FIRE, CLR_GREEN),
     MON("human zombie", S_ZOMBIE,
 	LVL(4, 6, 8, 0, -3), (G_GENO|G_SGROUP|G_NOCORPSE|1),
@@ -2154,5 +2251,6 @@
 	MR_COLD|MR_SLEEP|MR_POISON, 0,
 	M1_BREATHLESS|M1_MINDLESS|M1_HUMANOID,
-	M2_UNDEAD|M2_STALK|M2_HOSTILE, M3_INFRAVISION, HI_DOMESTIC),
+	M2_UNDEAD|M2_STALK|M2_HOSTILE, 
+	M3_INFRAVISION|M3_BERSERK, M4_VULNERABLE_FIRE, HI_DOMESTIC),
     MON("ettin zombie", S_ZOMBIE,
 	LVL(6, 8, 6, 0, -4), (G_GENO|G_NOCORPSE|1),
@@ -2162,5 +2260,6 @@
 	MR_COLD|MR_SLEEP|MR_POISON, 0,
 	M1_BREATHLESS|M1_MINDLESS|M1_HUMANOID,
-	M2_UNDEAD|M2_STALK|M2_HOSTILE|M2_STRONG, M3_INFRAVISION, CLR_BLUE),
+	M2_UNDEAD|M2_STALK|M2_HOSTILE|M2_STRONG, 
+	M3_INFRAVISION|M3_BERSERK, M4_VULNERABLE_FIRE, CLR_BLUE),
     MON("giant zombie", S_ZOMBIE,
 	LVL(8, 8, 6, 0, -4), (G_GENO|G_NOCORPSE|1),
@@ -2170,6 +2269,7 @@
 	MR_COLD|MR_SLEEP|MR_POISON, 0,
 	M1_BREATHLESS|M1_MINDLESS|M1_HUMANOID,
-	M2_UNDEAD|M2_STALK|M2_HOSTILE|M2_GIANT|M2_STRONG, M3_INFRAVISION,
-	CLR_CYAN),
+	M2_UNDEAD|M2_STALK|M2_HOSTILE|M2_GIANT|M2_STRONG, 
+	M3_INFRAVISION|M3_BERSERK,
+	M4_VULNERABLE_FIRE, CLR_CYAN),
     MON("ghoul", S_ZOMBIE,
 	LVL(3, 6, 10, 0, -2), (G_GENO|G_NOCORPSE|1),
@@ -2179,5 +2279,5 @@
 	MR_COLD|MR_SLEEP|MR_POISON, 0,
 	M1_BREATHLESS|M1_MINDLESS|M1_HUMANOID|M1_POIS,
-	M2_UNDEAD|M2_WANDER|M2_HOSTILE, M3_INFRAVISION, CLR_BLACK),
+	M2_UNDEAD|M2_WANDER|M2_HOSTILE, M3_INFRAVISION, M4_VULNERABLE_FIRE, CLR_BLACK),
     MON("skeleton", S_ZOMBIE,
 	LVL(12, 8, 4, 0, 0), (G_NOCORPSE|G_NOGEN),
@@ -2188,5 +2288,5 @@
 	M1_BREATHLESS|M1_MINDLESS|M1_HUMANOID|M1_THICK_HIDE,
 	M2_UNDEAD|M2_WANDER|M2_HOSTILE|M2_STRONG|M2_COLLECT|M2_NASTY,
-	M3_INFRAVISION, CLR_WHITE),
+	M3_INFRAVISION, M4_VULNERABLE_FIRE, CLR_WHITE),
 /*
  * golems
@@ -2198,5 +2298,5 @@
 	SIZ(400, 0, 0, MS_SILENT, MZ_LARGE), MR_SLEEP|MR_POISON, 0,
 	M1_BREATHLESS|M1_MINDLESS|M1_HUMANOID,
-	M2_HOSTILE|M2_NEUTER, 0, CLR_YELLOW),
+	M2_HOSTILE|M2_NEUTER, 0, M4_VULNERABLE_FIRE, CLR_YELLOW),
     MON("paper golem", S_GOLEM,
 	LVL(3, 12, 10, 0, 0), (G_NOCORPSE|1),
@@ -2205,5 +2305,5 @@
 	SIZ(400, 0, 0, MS_SILENT, MZ_LARGE), MR_SLEEP|MR_POISON, 0,
 	M1_BREATHLESS|M1_MINDLESS|M1_HUMANOID,
-	M2_HOSTILE|M2_NEUTER, 0, HI_PAPER),
+	M2_HOSTILE|M2_NEUTER, 0, M4_VULNERABLE_FIRE, HI_PAPER),
     MON("rope golem", S_GOLEM,
 	LVL(4, 9, 8, 0, 0), (G_NOCORPSE|1),
@@ -2212,5 +2312,5 @@
 	SIZ(450, 0, 0, MS_SILENT, MZ_LARGE), MR_SLEEP|MR_POISON, 0,
 	M1_BREATHLESS|M1_MINDLESS|M1_HUMANOID,
-	M2_HOSTILE|M2_NEUTER, 0, CLR_BROWN),
+	M2_HOSTILE|M2_NEUTER, 0, M4_VULNERABLE_FIRE, CLR_BROWN),
     MON("gold golem", S_GOLEM,
 	LVL(5, 9, 6, 0, 0), (G_NOCORPSE|1),
@@ -2219,5 +2319,5 @@
 	SIZ(450, 0, 0, MS_SILENT, MZ_LARGE), MR_SLEEP|MR_POISON|MR_ACID, 0,
 	M1_BREATHLESS|M1_MINDLESS|M1_HUMANOID|M1_THICK_HIDE,
-	M2_HOSTILE|M2_NEUTER, 0, HI_GOLD),
+	M2_HOSTILE|M2_NEUTER, 0, 0, HI_GOLD),
     MON("leather golem", S_GOLEM,
 	LVL(6, 6, 6, 0, 0), (G_NOCORPSE|1),
@@ -2226,5 +2326,5 @@
 	SIZ(800, 0, 0, MS_SILENT, MZ_LARGE), MR_SLEEP|MR_POISON, 0,
 	M1_BREATHLESS|M1_MINDLESS|M1_HUMANOID,
-	M2_HOSTILE|M2_NEUTER, 0, HI_LEATHER),
+	M2_HOSTILE|M2_NEUTER, 0, M4_VULNERABLE_FIRE, HI_LEATHER),
     MON("wood golem", S_GOLEM,
 	LVL(7, 3, 4, 0, 0), (G_NOCORPSE|1),
@@ -2233,5 +2333,5 @@
 	SIZ(900, 0, 0, MS_SILENT, MZ_LARGE), MR_SLEEP|MR_POISON, 0,
 	M1_BREATHLESS|M1_MINDLESS|M1_HUMANOID|M1_THICK_HIDE,
-	M2_HOSTILE|M2_NEUTER, 0, HI_WOOD),
+	M2_HOSTILE|M2_NEUTER, 0, M4_VULNERABLE_FIRE, HI_WOOD),
     MON("flesh golem", S_GOLEM,
 	LVL(9, 8, 9, 30, 0), (1),
@@ -2242,5 +2342,5 @@
 	MR_FIRE|MR_COLD|MR_ELEC|MR_SLEEP|MR_POISON,
 	M1_BREATHLESS|M1_MINDLESS|M1_HUMANOID,
-	M2_HOSTILE|M2_STRONG, 0, CLR_RED),
+	M2_HOSTILE|M2_STRONG, 0, M4_VULNERABLE_ACID, CLR_RED),
     MON("clay golem", S_GOLEM,
 	LVL(11, 7, 7, 40, 0), (G_NOCORPSE|1),
@@ -2249,5 +2349,5 @@
 	SIZ(1550, 0, 0, MS_SILENT, MZ_LARGE), MR_SLEEP|MR_POISON, 0,
 	M1_BREATHLESS|M1_MINDLESS|M1_HUMANOID|M1_THICK_HIDE,
-	M2_HOSTILE|M2_STRONG, 0, CLR_BROWN),
+	M2_HOSTILE|M2_STRONG, 0, M4_VULNERABLE_ACID, CLR_BROWN),
     MON("stone golem", S_GOLEM,
 	LVL(14, 6, 5, 50, 0), (G_NOCORPSE|1),
@@ -2256,5 +2356,5 @@
 	SIZ(1900, 0, 0, MS_SILENT, MZ_LARGE), MR_SLEEP|MR_POISON|MR_STONE, 0,
 	M1_BREATHLESS|M1_MINDLESS|M1_HUMANOID|M1_THICK_HIDE,
-	M2_HOSTILE|M2_STRONG, 0, CLR_GRAY),
+	M2_HOSTILE|M2_STRONG, M3_BERSERK, 0, CLR_GRAY),
     MON("glass golem", S_GOLEM,
 	LVL(16, 6, 1, 50, 0), (G_NOCORPSE|1),
@@ -2263,5 +2363,5 @@
 	SIZ(1800, 0, 0, MS_SILENT, MZ_LARGE), MR_SLEEP|MR_POISON|MR_ACID, 0,
 	M1_BREATHLESS|M1_MINDLESS|M1_HUMANOID|M1_THICK_HIDE,
-	M2_HOSTILE|M2_STRONG, 0, CLR_CYAN),
+	M2_HOSTILE|M2_STRONG, 0, 0, CLR_CYAN),
     MON("iron golem", S_GOLEM,
 	LVL(18, 6, 3, 60, 0), (G_NOCORPSE|1),
@@ -2271,5 +2371,5 @@
 	MR_FIRE|MR_COLD|MR_ELEC|MR_SLEEP|MR_POISON, 0,
 	M1_BREATHLESS|M1_MINDLESS|M1_HUMANOID|M1_THICK_HIDE|M1_POIS,
-	M2_HOSTILE|M2_STRONG|M2_COLLECT, 0, HI_METAL),
+	M2_HOSTILE|M2_STRONG|M2_COLLECT, 0, 0, HI_METAL),
 /*
  * humans, including elves and were-critters
@@ -2282,5 +2382,5 @@
 	M1_HUMANOID|M1_OMNIVORE,
 	M2_NOPOLY|M2_HUMAN|M2_STRONG|M2_COLLECT,
-	M3_INFRAVISIBLE, HI_DOMESTIC),
+	M3_INFRAVISIBLE, 0, HI_DOMESTIC),
     MON("wererat", S_HUMAN,
 	LVL(2, 12, 10, 10, -7), (1),
@@ -2290,5 +2390,5 @@
 	M1_HUMANOID|M1_POIS|M1_REGEN|M1_OMNIVORE,
 	M2_NOPOLY|M2_WERE|M2_HOSTILE|M2_HUMAN|M2_COLLECT, M3_INFRAVISIBLE,
-	CLR_BROWN),
+	0, CLR_BROWN),
     MON("werejackal", S_HUMAN,
 	LVL(2, 12, 10, 10, -7), (1),
@@ -2298,5 +2398,5 @@
 	M1_HUMANOID|M1_POIS|M1_REGEN|M1_OMNIVORE,
 	M2_NOPOLY|M2_WERE|M2_HOSTILE|M2_HUMAN|M2_COLLECT, M3_INFRAVISIBLE,
-	CLR_RED),
+	0, CLR_RED),
     MON("werewolf", S_HUMAN,
 	LVL(5, 12, 10, 20, -7), (1),
@@ -2306,5 +2406,5 @@
 	M1_HUMANOID|M1_POIS|M1_REGEN|M1_OMNIVORE,
 	M2_NOPOLY|M2_WERE|M2_HOSTILE|M2_HUMAN|M2_COLLECT,
-	M3_INFRAVISIBLE, CLR_ORANGE),
+	M3_INFRAVISIBLE, 0, CLR_ORANGE),
     MON("elf", S_HUMAN,
 	LVL(10, 12, 10, 2, -3), G_NOGEN,		/* for corpses */
@@ -2313,6 +2413,6 @@
 	SIZ(WT_ELF, 350, 0, MS_HUMANOID, MZ_HUMAN), MR_SLEEP, MR_SLEEP,
 	M1_HUMANOID|M1_OMNIVORE|M1_SEE_INVIS,
-	M2_NOPOLY|M2_ELF|M2_STRONG|M2_COLLECT, M3_INFRAVISION|M3_INFRAVISIBLE,
-	HI_DOMESTIC),
+	M2_NOPOLY|M2_ELF|M2_STRONG|M2_COLLECT, M3_EAGLEEYE|M3_INFRAVISION|M3_INFRAVISIBLE,
+	0, HI_DOMESTIC),
     MON("Woodland-elf", S_HUMAN,
 	LVL(4, 12, 10, 10, -5), (G_GENO|G_SGROUP|2),
@@ -2321,5 +2421,5 @@
 	SIZ(WT_ELF, 350, 0, MS_HUMANOID, MZ_HUMAN), MR_SLEEP, MR_SLEEP,
 	M1_HUMANOID|M1_OMNIVORE|M1_SEE_INVIS,
-	M2_ELF|M2_COLLECT, M3_INFRAVISIBLE|M3_INFRAVISION, CLR_GREEN),
+	M2_ELF|M2_COLLECT, M3_EAGLEEYE|M3_INFRAVISIBLE|M3_INFRAVISION, 0, CLR_GREEN),
     MON("Green-elf", S_HUMAN,
 	LVL(5, 12, 10, 10, -6), (G_GENO|G_SGROUP|2),
@@ -2328,5 +2428,5 @@
 	SIZ(WT_ELF, 350, 0, MS_HUMANOID, MZ_HUMAN), MR_SLEEP, MR_SLEEP,
 	M1_HUMANOID|M1_OMNIVORE|M1_SEE_INVIS,
-	M2_ELF|M2_COLLECT, M3_INFRAVISIBLE|M3_INFRAVISION, CLR_BRIGHT_GREEN),
+	M2_ELF|M2_COLLECT, M3_EAGLEEYE|M3_INFRAVISIBLE|M3_INFRAVISION, 0, CLR_BRIGHT_GREEN),
     MON("Grey-elf", S_HUMAN,
 	LVL(6, 12, 10, 10, -7), (G_GENO|G_SGROUP|2),
@@ -2335,5 +2435,5 @@
 	SIZ(WT_ELF, 350, 0, MS_HUMANOID, MZ_HUMAN), MR_SLEEP, MR_SLEEP,
 	M1_HUMANOID|M1_OMNIVORE|M1_SEE_INVIS,
-	M2_ELF|M2_COLLECT, M3_INFRAVISIBLE|M3_INFRAVISION, CLR_GRAY),
+	M2_ELF|M2_COLLECT, M3_EAGLEEYE|M3_INFRAVISIBLE|M3_INFRAVISION, 0, CLR_GRAY),
     MON("elf-lord", S_HUMAN,
 	LVL(8, 12, 10, 20, -9), (G_GENO|G_SGROUP|2),
@@ -2343,5 +2443,5 @@
 	M1_HUMANOID|M1_OMNIVORE|M1_SEE_INVIS,
 	M2_ELF|M2_STRONG|M2_LORD|M2_MALE|M2_COLLECT,
-	M3_INFRAVISIBLE|M3_INFRAVISION, CLR_BRIGHT_BLUE),
+	M3_EAGLEEYE|M3_INFRAVISIBLE|M3_INFRAVISION, 0, CLR_BRIGHT_BLUE),
     MON("Elvenking", S_HUMAN,
 	LVL(9, 12, 10, 25, -10), (G_GENO|1),
@@ -2351,5 +2451,5 @@
 	M1_HUMANOID|M1_OMNIVORE|M1_SEE_INVIS,
 	M2_ELF|M2_STRONG|M2_PRINCE|M2_MALE|M2_COLLECT,
-	M3_INFRAVISIBLE|M3_INFRAVISION, HI_LORD),
+	M3_EAGLEEYE|M3_INFRAVISIBLE|M3_INFRAVISION, 0, HI_LORD),
     MON("doppelganger", S_HUMAN,
 	LVL(9, 12, 5, 20, 0), (G_GENO|1),
@@ -2359,5 +2459,5 @@
 	M1_HUMANOID|M1_OMNIVORE,
 	M2_NOPOLY|M2_HUMAN|M2_HOSTILE|M2_STRONG|M2_COLLECT,
-	M3_INFRAVISIBLE, HI_DOMESTIC),
+	M3_INFRAVISIBLE, 0, HI_DOMESTIC),
     MON("nurse", S_HUMAN,
 	LVL(11, 6, 0, 0, 0), (G_GENO|3),
@@ -2366,5 +2466,5 @@
 	SIZ(WT_HUMAN, 400, 0, MS_NURSE, MZ_HUMAN), MR_POISON, MR_POISON,
 	M1_HUMANOID|M1_OMNIVORE, M2_NOPOLY|M2_HUMAN|M2_HOSTILE,
-	M3_INFRAVISIBLE, HI_DOMESTIC),
+	M3_INFRAVISIBLE, 0, HI_DOMESTIC),
     MON("shopkeeper", S_HUMAN,
 	LVL(12, 18, 0, 50, 0), G_NOGEN,
@@ -2374,5 +2474,5 @@
 	M1_HUMANOID|M1_OMNIVORE,
 	M2_NOPOLY|M2_HUMAN|M2_PEACEFUL|M2_STRONG|M2_COLLECT|M2_MAGIC,
-	M3_INFRAVISIBLE, HI_DOMESTIC),
+	M3_EAGLEEYE|M3_INFRAVISIBLE, 0, HI_DOMESTIC),
     MON("guard", S_HUMAN,
 	LVL(12, 12, 10, 40, 10), G_NOGEN,
@@ -2382,5 +2482,5 @@
 	M1_HUMANOID|M1_OMNIVORE,
 	M2_NOPOLY|M2_HUMAN|M2_MERC|M2_PEACEFUL|M2_STRONG|M2_COLLECT,
-	M3_INFRAVISIBLE, CLR_BLUE),
+	M3_INFRAVISIBLE, 0, CLR_BLUE),
     MON("prisoner", S_HUMAN,
 	LVL(12, 12, 10, 0, 0), G_NOGEN,          /* for special levels */
@@ -2390,5 +2490,5 @@
 	M1_HUMANOID|M1_OMNIVORE,
 	M2_NOPOLY|M2_HUMAN|M2_PEACEFUL|M2_STRONG|M2_COLLECT,
-	M3_INFRAVISIBLE|M3_CLOSE, HI_DOMESTIC),
+	M3_INFRAVISIBLE|M3_CLOSE, 0, HI_DOMESTIC),
     MON("Oracle", S_HUMAN,
 	LVL(12, 0, 0, 50, 0), (G_NOGEN|G_UNIQ),
@@ -2397,5 +2497,21 @@
 	SIZ(WT_HUMAN, 400, 0, MS_ORACLE, MZ_HUMAN), 0, 0,
 	M1_HUMANOID|M1_OMNIVORE,
-	M2_NOPOLY|M2_HUMAN|M2_PEACEFUL|M2_FEMALE, M3_INFRAVISIBLE, HI_ZAP),
+	M2_NOPOLY|M2_HUMAN|M2_PEACEFUL|M2_FEMALE, M3_INFRAVISIBLE, 0, HI_ZAP),
+/* placeholders for future */
+    MON("nun", S_HUMAN,
+		LVL(7, 12, 10, 50, 5), G_NOGEN,
+		A(ATTK(AT_MAGC, AD_CLRC, 0, 0), ATTK(AT_KICK, AD_PHYS, 1, 4),
+			NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
+		SIZ(WT_HUMAN, 400, 0, MS_HUMANOID, MZ_HUMAN),
+		MR_ELEC, 0, M1_HUMANOID|M1_OMNIVORE,
+		M2_NOPOLY|M2_HUMAN|M2_PEACEFUL|M2_FEMALE, M3_INFRAVISIBLE, 0, CLR_WHITE),
+    MON("cultist", S_HUMAN,
+		LVL(10, 12, 10, 0, -10), G_NOGEN,
+		A(ATTK(AT_MAGC, AD_CLRC, 0, 0), ATTK(AT_KICK, AD_PHYS, 1, 4),
+			NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
+		SIZ(WT_HUMAN, 400, 0, MS_HUMANOID, MZ_HUMAN),
+		0, 0, M1_HUMANOID|M1_OMNIVORE,
+		M2_NOPOLY|M2_HUMAN|M2_HOSTILE, M3_INFRAVISIBLE, 0, CLR_BLACK),
+/* probably should keep all the religious nuts together just in case */
     MON("aligned priest", S_HUMAN,
 	LVL(12, 12, 10, 50, 0), G_NOGEN,
@@ -2405,5 +2521,5 @@
 	MR_ELEC, 0, M1_HUMANOID|M1_OMNIVORE,
 	M2_NOPOLY|M2_HUMAN|M2_LORD|M2_PEACEFUL|M2_COLLECT, M3_INFRAVISIBLE,
-	CLR_WHITE),
+	0, CLR_WHITE),
     MON("high priest", S_HUMAN,
 	LVL(25, 15, 7, 70, 0), (G_NOGEN|G_UNIQ),
@@ -2415,5 +2531,5 @@
 	M1_HUMANOID|M1_SEE_INVIS|M1_OMNIVORE,
 	M2_NOPOLY|M2_HUMAN|M2_MINION|M2_PRINCE|M2_NASTY|M2_COLLECT|M2_MAGIC,
-	M3_INFRAVISIBLE, CLR_WHITE),
+	M3_INFRAVISIBLE, 0, CLR_WHITE),
     MON("soldier", S_HUMAN,
 	LVL(6, 10, 10, 0, -2), (G_SGROUP|G_GENO|1),
@@ -2423,5 +2539,5 @@
 	M1_HUMANOID|M1_OMNIVORE,
 	M2_NOPOLY|M2_HUMAN|M2_MERC|M2_STALK|M2_HOSTILE|M2_STRONG|M2_COLLECT,
-	M3_INFRAVISIBLE, CLR_GRAY),
+	M3_EAGLEEYE|M3_INFRAVISIBLE, 0, CLR_GRAY),
     MON("sergeant", S_HUMAN,
 	LVL(8, 10, 10, 5, -3), (G_SGROUP|G_GENO|1),
@@ -2431,5 +2547,5 @@
 	M1_HUMANOID|M1_OMNIVORE,
 	M2_NOPOLY|M2_HUMAN|M2_MERC|M2_STALK|M2_HOSTILE|M2_STRONG|M2_COLLECT,
-	M3_INFRAVISIBLE, CLR_RED),
+	M3_EAGLEEYE|M3_INFRAVISIBLE, 0, CLR_RED),
     MON("lieutenant", S_HUMAN,
 	LVL(10, 10, 10, 15, -4), (G_GENO|1),
@@ -2439,5 +2555,5 @@
 	M1_HUMANOID|M1_OMNIVORE,
 	M2_NOPOLY|M2_HUMAN|M2_MERC|M2_STALK|M2_HOSTILE|M2_STRONG|M2_COLLECT,
-	M3_INFRAVISIBLE, CLR_GREEN),
+	M3_EAGLEEYE|M3_INFRAVISIBLE, 0, CLR_GREEN),
     MON("captain", S_HUMAN,
 	LVL(12, 10, 10, 15, -5), (G_GENO|1),
@@ -2447,24 +2563,24 @@
 	M1_HUMANOID|M1_OMNIVORE,
 	M2_NOPOLY|M2_HUMAN|M2_MERC|M2_STALK|M2_HOSTILE|M2_STRONG|M2_COLLECT,
-	M3_INFRAVISIBLE, CLR_BLUE),
+	M3_EAGLEEYE|M3_INFRAVISIBLE, 0, CLR_BLUE),
 	/* Keep these separate - some of the mkroom code assumes that
 	 * all the soldiers are contiguous.
 	 */
     MON("watchman", S_HUMAN,
-	LVL(6, 10, 10, 0, -2), (G_SGROUP|G_NOGEN|G_GENO|1),
-	A(ATTK(AT_WEAP, AD_PHYS, 1, 8),
-	  NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
+	LVL(10, 10, 10, 0, -2), (G_SGROUP|G_NOGEN|G_GENO|1),
+	A(ATTK(AT_WEAP, AD_PHYS, 2, 6), ATTK(AT_WEAP, AD_PHYS, 2, 6),
+	  NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
 	SIZ(WT_HUMAN, 400, 0, MS_SOLDIER, MZ_HUMAN), 0, 0,
 	M1_HUMANOID|M1_OMNIVORE,
 	M2_NOPOLY|M2_HUMAN|M2_MERC|M2_STALK|M2_PEACEFUL|M2_STRONG|M2_COLLECT,
-	M3_INFRAVISIBLE, CLR_GRAY),
+	M3_INFRAVISIBLE, 0, CLR_GRAY),
     MON("watch captain", S_HUMAN,
-	LVL(10, 10, 10, 15, -4), (G_NOGEN|G_GENO|1),
-	A(ATTK(AT_WEAP, AD_PHYS, 3, 4), ATTK(AT_WEAP, AD_PHYS, 3, 4),
+	LVL(15, 10, 10, 15, -4), (G_NOGEN|G_GENO|1),
+	A(ATTK(AT_WEAP, AD_PHYS, 4, 5), ATTK(AT_WEAP, AD_PHYS, 3, 5),
 	  NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
 	SIZ(WT_HUMAN, 400, 0, MS_SOLDIER, MZ_HUMAN), 0, 0,
 	M1_HUMANOID|M1_OMNIVORE,
 	M2_NOPOLY|M2_HUMAN|M2_MERC|M2_STALK|M2_PEACEFUL|M2_STRONG|M2_COLLECT,
-	M3_INFRAVISIBLE, CLR_GREEN),
+	M3_EAGLEEYE|M3_INFRAVISIBLE, 0, CLR_GREEN),
 	/* Unique humans not tied to quests.
 	 */
@@ -2478,9 +2594,9 @@
 	M1_FLY|M1_SWIM|M1_AMPHIBIOUS|M1_HUMANOID|M1_POIS|M1_OMNIVORE,
 	M2_NOPOLY|M2_HOSTILE|M2_STRONG|M2_PNAME|M2_FEMALE,
-	M3_WAITFORU|M3_INFRAVISIBLE, CLR_BRIGHT_GREEN),
+	M3_WAITFORU|M3_INFRAVISIBLE, 0, CLR_BRIGHT_GREEN),
     MON("Wizard of Yendor", S_HUMAN,
 	LVL(30, 12, -8, 100, A_NONE), (G_NOGEN|G_UNIQ),
-	A(ATTK(AT_CLAW, AD_SAMU, 2,12), ATTK(AT_MAGC, AD_SPEL, 0, 0),
-	  NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
+	A(ATTK(AT_CLAW, AD_SAMU, 2,12), ATTK(AT_WEAP, AD_PHYS, 4, 6),
+	  ATTK(AT_MAGC, AD_SPEL, 0, 0), NO_ATTK, NO_ATTK, NO_ATTK),
 	SIZ(WT_HUMAN, 400, 0, MS_CUSS, MZ_HUMAN),
 	MR_FIRE|MR_POISON, MR_FIRE|MR_POISON,
@@ -2489,5 +2605,5 @@
 	M2_NOPOLY|M2_HUMAN|M2_HOSTILE|M2_STRONG|M2_NASTY|
 	  M2_PRINCE|M2_MALE|M2_MAGIC,
-	M3_COVETOUS|M3_WAITFORU|M3_INFRAVISIBLE, HI_LORD),
+	M3_COVETOUS|M3_WAITFORU|M3_INFRAVISIBLE, 0, HI_LORD),
     MON("Croesus", S_HUMAN,
 	LVL(20, 15, 0, 40, 15), (G_UNIQ|G_NOGEN),
@@ -2498,5 +2614,5 @@
 	M2_NOPOLY|M2_HUMAN|M2_STALK|M2_HOSTILE|M2_STRONG|M2_NASTY|M2_PNAME|
 	  M2_PRINCE|M2_MALE|M2_GREEDY|M2_JEWELS|M2_COLLECT|M2_MAGIC,
-	M3_INFRAVISIBLE, HI_LORD),
+	M3_INFRAVISIBLE, 0, HI_LORD),
 #ifdef CHARON
     MON("Charon", S_HUMAN,
@@ -2508,5 +2624,5 @@
 	M1_BREATHLESS|M1_SEE_INVIS|M1_HUMANOID,
 	M2_NOPOLY|M2_HUMAN|M2_PEACEFUL|M2_PNAME|M2_MALE|M2_GREEDY|M2_COLLECT,
-	M3_INFRAVISIBLE, CLR_WHITE),
+	M3_INFRAVISIBLE, 0, CLR_WHITE),
 #endif
 /*
@@ -2520,5 +2636,5 @@
 	MR_COLD|MR_DISINT|MR_SLEEP|MR_POISON|MR_STONE, 0,
 	M1_FLY|M1_BREATHLESS|M1_WALLWALK|M1_HUMANOID|M1_UNSOLID,
-	M2_NOPOLY|M2_UNDEAD|M2_STALK|M2_HOSTILE, M3_INFRAVISION, CLR_GRAY),
+	M2_NOPOLY|M2_UNDEAD|M2_STALK|M2_HOSTILE, M3_INFRAVISION, 0, CLR_GRAY),
     MON("shade", S_GHOST,
 	LVL(12, 10, 10, 0, 0), (G_NOCORPSE|G_NOGEN),
@@ -2529,5 +2645,5 @@
 	M1_FLY|M1_BREATHLESS|M1_WALLWALK|M1_HUMANOID|M1_UNSOLID|M1_SEE_INVIS,
 	M2_NOPOLY|M2_UNDEAD|M2_WANDER|M2_STALK|M2_HOSTILE|M2_NASTY,
-	M3_INFRAVISION, CLR_BLACK),
+	M3_INFRAVISION, 0, CLR_BLACK),
 /*
  * (major) demons
@@ -2540,5 +2656,5 @@
 	M1_HUMANOID|M1_POIS|M1_SWIM,
 	M2_NOPOLY|M2_DEMON|M2_STALK|M2_HOSTILE|M2_NASTY|M2_COLLECT,
-	M3_INFRAVISIBLE|M3_INFRAVISION, CLR_BLUE),
+	M3_INFRAVISIBLE|M3_INFRAVISION, M4_VULNERABLE_ELEC, CLR_BLUE),
 	/* standard demons & devils
 	 */
@@ -2551,5 +2667,5 @@
 	M1_POIS|M1_THICK_HIDE,
 	M2_DEMON|M2_STALK|M2_HOSTILE|M2_NASTY, M3_INFRAVISIBLE|M3_INFRAVISION,
-	CLR_BROWN),
+	0, CLR_BROWN),
 #ifdef SEDUCE
 # define SEDUCTION_ATTACKS \
@@ -2567,5 +2683,5 @@
 	M1_HUMANOID|M1_FLY|M1_POIS,
 	M2_DEMON|M2_STALK|M2_HOSTILE|M2_NASTY|M2_FEMALE,
-	M3_INFRAVISIBLE|M3_INFRAVISION, CLR_GRAY),
+	M3_INFRAVISIBLE|M3_INFRAVISION, 0, CLR_GRAY),
     MON("incubus", S_DEMON,
 	LVL(6, 12, 0, 70, -9), (G_NOCORPSE|1),
@@ -2574,5 +2690,5 @@
 	M1_HUMANOID|M1_FLY|M1_POIS,
 	M2_DEMON|M2_STALK|M2_HOSTILE|M2_NASTY|M2_MALE,
-	M3_INFRAVISIBLE|M3_INFRAVISION, CLR_GRAY),
+	M3_INFRAVISIBLE|M3_INFRAVISION, 0, CLR_GRAY),
 #undef SEDUCTION_ATTACKS
     /* Used by AD&D for a type of demon, originally one of the Furies */
@@ -2586,5 +2702,5 @@
 	M2_NOPOLY|M2_DEMON|M2_STALK|M2_HOSTILE|M2_STRONG|M2_NASTY|M2_FEMALE|
 	  M2_COLLECT,
-	M3_INFRAVISIBLE|M3_INFRAVISION, CLR_RED),
+	M3_INFRAVISIBLE|M3_INFRAVISION, 0, CLR_RED),
     MON("barbed devil", S_DEMON,
 	LVL(8, 12, 0, 35, 8), (G_HELL|G_NOCORPSE|G_SGROUP|2),
@@ -2593,5 +2709,5 @@
 	SIZ(WT_HUMAN, 400, 0, MS_SILENT, MZ_HUMAN), MR_FIRE|MR_POISON, 0,
 	M1_POIS|M1_THICK_HIDE, M2_DEMON|M2_STALK|M2_HOSTILE|M2_NASTY,
-	M3_INFRAVISIBLE|M3_INFRAVISION, CLR_RED),
+	M3_INFRAVISIBLE|M3_INFRAVISION, 0, CLR_RED),
     MON("marilith", S_DEMON,
 	LVL(7, 12, -6, 80, -12), (G_HELL|G_NOCORPSE|1),
@@ -2602,5 +2718,5 @@
 	M1_HUMANOID|M1_SLITHY|M1_SEE_INVIS|M1_POIS,
 	M2_DEMON|M2_STALK|M2_HOSTILE|M2_NASTY|M2_FEMALE|M2_COLLECT,
-	M3_INFRAVISIBLE|M3_INFRAVISION, CLR_RED),
+	M3_INFRAVISIBLE|M3_INFRAVISION, 0, CLR_RED),
     MON("vrock", S_DEMON,
 	LVL(8, 12, 0, 50, -9), (G_HELL|G_NOCORPSE|G_SGROUP|2),
@@ -2610,12 +2726,12 @@
 	SIZ(WT_HUMAN, 400, 0, MS_SILENT, MZ_LARGE), MR_FIRE|MR_POISON, 0,
 	M1_POIS, M2_DEMON|M2_STALK|M2_HOSTILE|M2_NASTY,
-	M3_INFRAVISIBLE|M3_INFRAVISION, CLR_RED),
+	M3_INFRAVISIBLE|M3_INFRAVISION, 0, CLR_RED),
     MON("hezrou", S_DEMON,
-	LVL(9, 6, -2, 55, -10), (G_HELL|G_NOCORPSE|G_SGROUP|2),
+	LVL(9, 9, -2, 55, -10), (G_HELL|G_NOCORPSE|G_SGROUP|2),
 	A(ATTK(AT_CLAW, AD_PHYS, 1, 3), ATTK(AT_CLAW, AD_PHYS, 1, 3),
 	  ATTK(AT_BITE, AD_PHYS, 4, 4), NO_ATTK, NO_ATTK, NO_ATTK),
 	SIZ(WT_HUMAN, 400, 0, MS_SILENT, MZ_LARGE), MR_FIRE|MR_POISON, 0,
 	M1_HUMANOID|M1_POIS, M2_DEMON|M2_STALK|M2_HOSTILE|M2_NASTY,
-	M3_INFRAVISIBLE|M3_INFRAVISION, CLR_RED),
+	M3_INFRAVISIBLE|M3_INFRAVISION, 0, CLR_RED),
     MON("bone devil", S_DEMON,
 	LVL(9, 15, -1, 40, -9), (G_HELL|G_NOCORPSE|G_SGROUP|2),
@@ -2624,7 +2740,7 @@
 	SIZ(WT_HUMAN, 400, 0, MS_SILENT, MZ_LARGE), MR_FIRE|MR_POISON, 0,
 	M1_POIS, M2_DEMON|M2_STALK|M2_HOSTILE|M2_NASTY|M2_COLLECT,
-	M3_INFRAVISIBLE|M3_INFRAVISION, CLR_GRAY),
+	M3_INFRAVISIBLE|M3_INFRAVISION, 0, CLR_GRAY),
     MON("ice devil", S_DEMON,
-	LVL(11, 6, -4, 55, -12), (G_HELL|G_NOCORPSE|2),
+	LVL(11, 9, -4, 55, -12), (G_HELL|G_NOCORPSE|2),
 	A(ATTK(AT_CLAW, AD_PHYS, 1, 4), ATTK(AT_CLAW, AD_PHYS, 1, 4),
 	  ATTK(AT_BITE, AD_PHYS, 2, 4), ATTK(AT_STNG, AD_COLD, 3, 4),
@@ -2633,5 +2749,5 @@
 	MR_FIRE|MR_COLD|MR_POISON, 0, M1_SEE_INVIS|M1_POIS,
 	M2_DEMON|M2_STALK|M2_HOSTILE|M2_NASTY, M3_INFRAVISIBLE|M3_INFRAVISION,
-	CLR_WHITE),
+	0, CLR_WHITE),
     MON("nalfeshnee", S_DEMON,
 	LVL(11, 9, -1, 65, -11), (G_HELL|G_NOCORPSE|1),
@@ -2641,7 +2757,7 @@
 	SIZ(WT_HUMAN, 400, 0, MS_SPELL, MZ_LARGE), MR_FIRE|MR_POISON, 0,
 	M1_HUMANOID|M1_POIS, M2_DEMON|M2_STALK|M2_HOSTILE|M2_NASTY,
-	M3_INFRAVISIBLE|M3_INFRAVISION, CLR_RED),
+	M3_INFRAVISIBLE|M3_INFRAVISION, 0, CLR_RED),
     MON("pit fiend", S_DEMON,
-	LVL(13, 6, -3, 65, -13), (G_HELL|G_NOCORPSE|2),
+	LVL(13, 9, -3, 65, -13), (G_HELL|G_NOCORPSE|2),
 	A(ATTK(AT_WEAP, AD_PHYS, 4, 2), ATTK(AT_WEAP, AD_PHYS, 4, 2),
 	  ATTK(AT_HUGS, AD_PHYS, 2, 4), NO_ATTK, NO_ATTK, NO_ATTK),
@@ -2649,27 +2765,25 @@
 	M1_SEE_INVIS|M1_POIS,
 	M2_DEMON|M2_STALK|M2_HOSTILE|M2_NASTY|M2_COLLECT,
-	M3_INFRAVISIBLE|M3_INFRAVISION, CLR_RED),
+	M3_INFRAVISIBLE|M3_INFRAVISION, 0, CLR_RED),
     MON("balrog", S_DEMON,
-	LVL(16, 5, -2, 75, -14), (G_HELL|G_NOCORPSE|1),
-	A(ATTK(AT_WEAP, AD_PHYS, 8, 4), ATTK(AT_WEAP, AD_PHYS, 4, 6),
+	LVL(16, 9, -2, 75, -14), (G_HELL|G_NOCORPSE|1),
+	A(ATTK(AT_WEAP, AD_PHYS, 6, 4), ATTK(AT_WEAP, AD_PHYS, 3, 6),
 	  NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
 	SIZ(WT_HUMAN, 400, 0, MS_SILENT, MZ_LARGE), MR_FIRE|MR_POISON, 0,
 	M1_FLY|M1_SEE_INVIS|M1_POIS,
 	M2_DEMON|M2_STALK|M2_HOSTILE|M2_STRONG|M2_NASTY|M2_COLLECT,
-	M3_INFRAVISIBLE|M3_INFRAVISION, CLR_RED),
+	M3_INFRAVISIBLE|M3_INFRAVISION|M3_BERSERK, 0, CLR_RED),
 	/* Named demon lords & princes plus Arch-Devils.
 	 * (their order matters; see minion.c)
 	 */
     MON("Juiblex", S_DEMON,
-	LVL(50, 3, -7, 65, -15), (G_HELL|G_NOCORPSE|G_NOGEN|G_UNIQ),
-	A(ATTK(AT_ENGL, AD_DISE, 4,10), ATTK(AT_SPIT, AD_ACID, 3, 6),
-	  NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
+	LVL(50, 6, -7, 65, -15), (G_HELL|G_NOCORPSE|G_NOGEN),
+	A(ATTK(AT_SPIT, AD_ACID, 3, 6), ATTK(AT_CLAW, AD_ACID, 2, 6),
+		ATTK(AT_NONE, AD_DISE, 1,10), NO_ATTK, NO_ATTK, NO_ATTK),
 	SIZ(1500, 0, 0, MS_GURGLE, MZ_LARGE),
 	MR_FIRE|MR_POISON|MR_ACID|MR_STONE, 0,
-	M1_AMPHIBIOUS|M1_AMORPHOUS|M1_NOHEAD|M1_FLY|M1_SEE_INVIS|M1_ACID|
-	  M1_POIS,
-	M2_NOPOLY|M2_DEMON|M2_STALK|M2_HOSTILE|M2_PNAME|M2_NASTY|M2_LORD|
-	  M2_MALE,
-	M3_WAITFORU|M3_WANTSAMUL|M3_INFRAVISION, CLR_BRIGHT_GREEN),
+	M1_AMPHIBIOUS|M1_AMORPHOUS|M1_NOHEAD|M1_FLY|M1_SEE_INVIS|M1_ACID|M1_POIS,
+	M2_NOPOLY|M2_DEMON|M2_STALK|M2_HOSTILE|M2_PNAME|M2_NASTY|M2_LORD|M2_MALE,
+	M3_WAITFORU|M3_WANTSAMUL|M3_INFRAVISION, 0, CLR_BRIGHT_GREEN),
     MON("Yeenoghu", S_DEMON,
 	LVL(56, 18, -5, 80, -15), (G_HELL|G_NOCORPSE|G_NOGEN|G_UNIQ),
@@ -2681,5 +2795,5 @@
 	M2_NOPOLY|M2_DEMON|M2_STALK|M2_HOSTILE|M2_PNAME|M2_NASTY|M2_LORD|
 	  M2_MALE|M2_COLLECT,
-	M3_WANTSAMUL|M3_INFRAVISIBLE|M3_INFRAVISION, HI_LORD),
+	M3_WANTSAMUL|M3_INFRAVISIBLE|M3_INFRAVISION, 0, HI_LORD),
     MON("Orcus", S_DEMON,
 	LVL(66, 9, -6, 85, -20), (G_HELL|G_NOCORPSE|G_NOGEN|G_UNIQ),
@@ -2692,14 +2806,15 @@
 	  M2_MALE|M2_COLLECT,
 	M3_WAITFORU|M3_WANTSBOOK|M3_WANTSAMUL|M3_INFRAVISIBLE|M3_INFRAVISION,
-	HI_LORD),
+	0, HI_LORD),
     MON("Geryon", S_DEMON,
-	LVL(72, 3, -3, 75, 15), (G_HELL|G_NOCORPSE|G_NOGEN|G_UNIQ),
+	LVL(72, 6, -3, 75, 15), (G_HELL|G_NOCORPSE|G_NOGEN|G_UNIQ),
 	A(ATTK(AT_CLAW, AD_PHYS, 3, 6), ATTK(AT_CLAW, AD_PHYS, 3, 6),
-	  ATTK(AT_STNG, AD_DRST, 2, 4), NO_ATTK, NO_ATTK, NO_ATTK),
+	  ATTK(AT_STNG, AD_DRST, 2, 4), ATTK(AT_MAGC, AD_SPEL, 3, 6), 
+	  NO_ATTK, NO_ATTK),
 	SIZ(1500, 500, 0, MS_BRIBE, MZ_HUGE), MR_FIRE|MR_POISON, 0,
 	M1_FLY|M1_SEE_INVIS|M1_POIS|M1_SLITHY,
 	M2_NOPOLY|M2_DEMON|M2_STALK|M2_HOSTILE|M2_PNAME|M2_NASTY|
 	  M2_PRINCE|M2_MALE,
-	M3_WANTSAMUL|M3_INFRAVISIBLE|M3_INFRAVISION, HI_LORD),
+	M3_WANTSAMUL|M3_INFRAVISIBLE|M3_INFRAVISION, 0, HI_LORD),
     MON("Dispater", S_DEMON,
 	LVL(78, 15, -2, 80, 15), (G_HELL|G_NOCORPSE|G_NOGEN|G_UNIQ),
@@ -2710,23 +2825,23 @@
 	M2_NOPOLY|M2_DEMON|M2_STALK|M2_HOSTILE|M2_PNAME|M2_NASTY|
 	  M2_PRINCE|M2_MALE|M2_COLLECT,
-	M3_WANTSAMUL|M3_INFRAVISIBLE|M3_INFRAVISION, HI_LORD),
+	M3_WANTSAMUL|M3_INFRAVISIBLE|M3_INFRAVISION, 0, HI_LORD),
     MON("Baalzebub", S_DEMON,
 	LVL(89, 9, -5, 85, 20), (G_HELL|G_NOCORPSE|G_NOGEN|G_UNIQ),
 	A(ATTK(AT_BITE, AD_DRST, 2, 6), ATTK(AT_GAZE, AD_STUN, 2, 6),
-	  NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
+	  ATTK(AT_MAGC, AD_SPEL, 6, 6), NO_ATTK, NO_ATTK, NO_ATTK),
 	SIZ(1500, 500, 0, MS_BRIBE, MZ_LARGE), MR_FIRE|MR_POISON, 0,
 	M1_FLY|M1_SEE_INVIS|M1_POIS,
 	M2_NOPOLY|M2_DEMON|M2_STALK|M2_HOSTILE|M2_PNAME|M2_NASTY|
 	  M2_PRINCE|M2_MALE,
-	M3_WANTSAMUL|M3_WAITFORU|M3_INFRAVISIBLE|M3_INFRAVISION, HI_LORD),
+	M3_WANTSAMUL|M3_WAITFORU|M3_INFRAVISIBLE|M3_INFRAVISION, 0, HI_LORD),
     MON("Asmodeus", S_DEMON,
 	LVL(105, 12, -7, 90, 20), (G_HELL|G_NOCORPSE|G_NOGEN|G_UNIQ),
 	A(ATTK(AT_CLAW, AD_PHYS, 4, 4), ATTK(AT_MAGC, AD_COLD, 6, 6),
-	  NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
+	  ATTK(AT_MAGC, AD_SPEL, 6, 6), NO_ATTK, NO_ATTK, NO_ATTK),
 	SIZ(1500, 500, 0, MS_BRIBE, MZ_HUGE), MR_FIRE|MR_COLD|MR_POISON, 0,
 	M1_FLY|M1_SEE_INVIS|M1_HUMANOID|M1_POIS,
 	M2_NOPOLY|M2_DEMON|M2_STALK|M2_HOSTILE|M2_PNAME|M2_STRONG|
 	  M2_NASTY|M2_PRINCE|M2_MALE,
-	M3_WANTSAMUL|M3_WAITFORU|M3_INFRAVISIBLE|M3_INFRAVISION, HI_LORD),
+	M3_WANTSAMUL|M3_WAITFORU|M3_INFRAVISIBLE|M3_INFRAVISION, 0, HI_LORD),
     MON("Demogorgon", S_DEMON,
 	LVL(106, 15, -8, 95, -20), (G_HELL|G_NOCORPSE|G_NOGEN|G_UNIQ),
@@ -2738,9 +2853,9 @@
 	M2_NOPOLY|M2_DEMON|M2_STALK|M2_HOSTILE|M2_PNAME|M2_NASTY|
 	  M2_PRINCE|M2_MALE,
-	M3_WANTSAMUL|M3_INFRAVISIBLE|M3_INFRAVISION, HI_LORD),
+	M3_WANTSAMUL|M3_INFRAVISIBLE|M3_INFRAVISION, 0, HI_LORD),
 	/* Riders -- the Four Horsemen of the Apocalypse ("War" == player)
 	 */
     MON("Death", S_DEMON,
-	LVL(30, 12, -5, 100, 0), (G_UNIQ|G_NOGEN),
+	LVL(40, 12, -5, 100, 0), (G_UNIQ|G_NOGEN),
 	A(ATTK(AT_TUCH, AD_DETH, 8, 8), ATTK(AT_TUCH, AD_DETH, 8, 8),
 	  NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
@@ -2749,7 +2864,7 @@
 	M1_FLY|M1_HUMANOID|M1_REGEN|M1_SEE_INVIS|M1_TPORT_CNTRL,
 	M2_NOPOLY|M2_STALK|M2_HOSTILE|M2_PNAME|M2_STRONG|M2_NASTY,
-	M3_INFRAVISIBLE|M3_INFRAVISION, HI_LORD),
+	M3_INFRAVISIBLE|M3_INFRAVISION, 0, HI_LORD),
     MON("Pestilence", S_DEMON,
-	LVL(30, 12, -5, 100, 0), (G_UNIQ|G_NOGEN),
+	LVL(40, 12, -5, 100, 0), (G_UNIQ|G_NOGEN),
 	A(ATTK(AT_TUCH, AD_PEST, 8, 8), ATTK(AT_TUCH, AD_PEST, 8, 8),
 	  NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
@@ -2758,7 +2873,7 @@
 	M1_FLY|M1_HUMANOID|M1_REGEN|M1_SEE_INVIS|M1_TPORT_CNTRL,
 	M2_NOPOLY|M2_STALK|M2_HOSTILE|M2_PNAME|M2_STRONG|M2_NASTY,
-	M3_INFRAVISIBLE|M3_INFRAVISION, HI_LORD),
+	M3_INFRAVISIBLE|M3_INFRAVISION, 0, HI_LORD),
     MON("Famine", S_DEMON,
-	LVL(30, 12, -5, 100, 0), (G_UNIQ|G_NOGEN),
+	LVL(40, 12, -5, 100, 0), (G_UNIQ|G_NOGEN),
 	A(ATTK(AT_TUCH, AD_FAMN, 8, 8), ATTK(AT_TUCH, AD_FAMN, 8, 8),
 	  NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
@@ -2767,5 +2882,5 @@
 	M1_FLY|M1_HUMANOID|M1_REGEN|M1_SEE_INVIS|M1_TPORT_CNTRL,
 	M2_NOPOLY|M2_STALK|M2_HOSTILE|M2_PNAME|M2_STRONG|M2_NASTY,
-	M3_INFRAVISIBLE|M3_INFRAVISION, HI_LORD),
+	M3_INFRAVISIBLE|M3_INFRAVISION, 0, HI_LORD),
 	/* other demons
 	 */
@@ -2778,5 +2893,5 @@
 	M1_FLY|M1_SWIM|M1_BREATHLESS|M1_SEE_INVIS|M1_HUMANOID|M1_POIS,
 	M2_NOPOLY|M2_STALK|M2_PEACEFUL, M3_INFRAVISIBLE|M3_INFRAVISION,
-	CLR_BRIGHT_BLUE),
+	0, CLR_BRIGHT_BLUE),
 #endif
     MON("djinni", S_DEMON,
@@ -2786,5 +2901,5 @@
 	SIZ(1500, 400, 0, MS_DJINNI, MZ_HUMAN), MR_POISON|MR_STONE, 0,
 	M1_HUMANOID|M1_FLY|M1_POIS,
-	M2_NOPOLY|M2_STALK|M2_COLLECT, M3_INFRAVISIBLE, CLR_YELLOW),
+	M2_NOPOLY|M2_STALK|M2_COLLECT, M3_INFRAVISIBLE, 0, CLR_YELLOW),
     MON("sandestin", S_DEMON,
 	LVL(13, 12, 4, 60, -5), (G_HELL|G_NOCORPSE|1),
@@ -2793,5 +2908,5 @@
 	SIZ(1500, 400, 0, MS_CUSS, MZ_HUMAN), MR_STONE, 0,
 	M1_HUMANOID, M2_NOPOLY|M2_STALK|M2_STRONG|M2_COLLECT,
-	M3_INFRAVISIBLE|M3_INFRAVISION, CLR_GRAY),
+	M3_EAGLEEYE|M3_INFRAVISIBLE|M3_INFRAVISION, 0, CLR_GRAY),
 /*
  * sea monsters
@@ -2803,5 +2918,5 @@
 	SIZ(80, 20, 0, MS_SILENT, MZ_SMALL), MR_POISON, MR_POISON,
 	M1_SWIM|M1_AMPHIBIOUS|M1_SLITHY|M1_NOLIMBS|M1_NOTAKE|M1_POIS,
-	M2_HOSTILE, 0, CLR_BLUE),
+	M2_HOSTILE, 0, M4_VULNERABLE_ELEC, CLR_BLUE),
     MON("piranha", S_EEL,
 	LVL(5, 12, 4, 0, 0), (G_GENO|G_NOGEN|G_SGROUP),
@@ -2811,5 +2926,5 @@
 	M1_SWIM|M1_AMPHIBIOUS|M1_ANIMAL|M1_SLITHY|M1_NOLIMBS|
 	  M1_CARNIVORE|M1_OVIPAROUS|M1_NOTAKE,
-	M2_HOSTILE, 0, CLR_RED),
+	M2_HOSTILE, 0, M4_VULNERABLE_ELEC, CLR_RED),
     MON("shark", S_EEL,
 	LVL(7, 12, 2, 0, 0), (G_GENO|G_NOGEN),
@@ -2819,5 +2934,5 @@
 	M1_SWIM|M1_AMPHIBIOUS|M1_ANIMAL|M1_SLITHY|M1_NOLIMBS|
 	  M1_CARNIVORE|M1_OVIPAROUS|M1_THICK_HIDE|M1_NOTAKE,
-	M2_HOSTILE, 0, CLR_GRAY),
+	M2_HOSTILE, 0, M4_VULNERABLE_ELEC, CLR_GRAY),
     MON("giant eel", S_EEL,
 	LVL(5, 9, -1, 0, 0), (G_GENO|G_NOGEN),
@@ -2827,5 +2942,5 @@
 	M1_SWIM|M1_AMPHIBIOUS|M1_ANIMAL|M1_SLITHY|M1_NOLIMBS|
 	  M1_CARNIVORE|M1_OVIPAROUS|M1_NOTAKE,
-	M2_HOSTILE, M3_INFRAVISIBLE, CLR_CYAN),
+	M2_HOSTILE, M3_INFRAVISIBLE, M4_VULNERABLE_ELEC, CLR_CYAN),
     MON("electric eel", S_EEL,
 	LVL(7, 10, -3, 0, 0), (G_GENO|G_NOGEN),
@@ -2835,5 +2950,5 @@
 	M1_SWIM|M1_AMPHIBIOUS|M1_ANIMAL|M1_SLITHY|M1_NOLIMBS|
 	  M1_CARNIVORE|M1_OVIPAROUS|M1_NOTAKE,
-	M2_HOSTILE, M3_INFRAVISIBLE, CLR_BRIGHT_BLUE),
+	M2_HOSTILE, M3_INFRAVISIBLE, 0, CLR_BRIGHT_BLUE),
     MON("kraken", S_EEL,
 	LVL(20, 3, 6, 0, -3), (G_GENO|G_NOGEN),
@@ -2843,5 +2958,5 @@
 	SIZ(1800, 1000, 0, MS_SILENT, MZ_HUGE), 0, 0,
 	M1_SWIM|M1_AMPHIBIOUS|M1_ANIMAL|M1_NOHANDS|M1_CARNIVORE,
-	M2_NOPOLY|M2_HOSTILE|M2_STRONG, M3_INFRAVISIBLE, CLR_RED),
+	M2_NOPOLY|M2_HOSTILE|M2_STRONG, M3_INFRAVISIBLE, M4_VULNERABLE_ELEC, CLR_RED),
 /*
  * lizards, &c
@@ -2853,5 +2968,5 @@
 	SIZ(10, 20, 0, MS_SILENT, MZ_TINY), 0, 0,
 	M1_SWIM|M1_AMPHIBIOUS|M1_ANIMAL|M1_NOHANDS|M1_CARNIVORE,
-	M2_HOSTILE, 0, CLR_YELLOW),
+	M2_HOSTILE, 0, 0, CLR_YELLOW),
     MON("gecko", S_LIZARD,
 	LVL(1, 6, 8, 0, 0), (G_GENO|5),
@@ -2859,5 +2974,5 @@
 	  NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
 	SIZ(10, 20, 0, MS_SQEEK, MZ_TINY), 0, 0,
-	M1_ANIMAL|M1_NOHANDS|M1_CARNIVORE, M2_HOSTILE, 0, CLR_GREEN),
+	M1_ANIMAL|M1_NOHANDS|M1_CARNIVORE, M2_HOSTILE, 0, 0, CLR_GREEN),
     MON("iguana", S_LIZARD,
 	LVL(2, 6, 7, 0, 0), (G_GENO|5),
@@ -2865,5 +2980,5 @@
 	  NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
 	SIZ(30, 30, 0, MS_SILENT, MZ_TINY), 0, 0,
-	M1_ANIMAL|M1_NOHANDS|M1_CARNIVORE, M2_HOSTILE, 0, CLR_BROWN),
+	M1_ANIMAL|M1_NOHANDS|M1_CARNIVORE, M2_HOSTILE, 0, 0, CLR_BROWN),
     MON("baby crocodile", S_LIZARD,
 	LVL(3, 6, 7, 0, 0), G_GENO,
@@ -2872,5 +2987,12 @@
 	SIZ(200, 200, 0, MS_SILENT, MZ_MEDIUM), 0, 0,
 	M1_SWIM|M1_AMPHIBIOUS|M1_ANIMAL|M1_NOHANDS|M1_CARNIVORE,
-	M2_HOSTILE, 0, CLR_BROWN),
+	M2_HOSTILE, 0, 0, CLR_BROWN),
+    MON("giant turtle", S_LIZARD,
+	LVL(7, 2, -5, 10, 0), (G_GENO|1),
+	A(ATTK(AT_BITE, AD_PHYS, 4, 6),
+	  NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
+	SIZ(4000, 1200, 0, MS_HISS, MZ_HUGE), MR_STONE, MR_STONE,
+	M1_ANIMAL|M1_THICK_HIDE|M1_NOHANDS|M1_HERBIVORE,
+        M2_HOSTILE, 0, 0, CLR_BRIGHT_GREEN),
     MON("lizard", S_LIZARD,
 	LVL(5, 6, 6, 10, 0), (G_GENO|5),
@@ -2878,11 +3000,11 @@
 	  NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
 	SIZ(10, 40, 0, MS_SILENT, MZ_TINY), MR_STONE, MR_STONE,
-	M1_ANIMAL|M1_NOHANDS|M1_CARNIVORE, M2_HOSTILE, 0, CLR_GREEN),
+	M1_ANIMAL|M1_NOHANDS|M1_CARNIVORE, M2_HOSTILE, 0, 0, CLR_GREEN),
     MON("chameleon", S_LIZARD,
 	LVL(6, 5, 6, 10, 0), (G_GENO|2),
 	A(ATTK(AT_BITE, AD_PHYS, 4, 2),
 	  NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
-	SIZ(100, 100, 0, MS_SILENT, MZ_TINY), 0, 0,
-	M1_ANIMAL|M1_NOHANDS|M1_CARNIVORE, M2_NOPOLY|M2_HOSTILE, 0, CLR_BROWN),
+	SIZ(100, 100, 0, MS_SILENT, MZ_SMALL), 0, 0,
+	M1_ANIMAL|M1_NOHANDS|M1_CARNIVORE, M2_NOPOLY|M2_HOSTILE, 0, 0, CLR_BROWN),
     MON("crocodile", S_LIZARD,
 	LVL(6, 9, 5, 0, 0), (G_GENO|1),
@@ -2892,5 +3014,5 @@
 	M1_SWIM|M1_AMPHIBIOUS|M1_ANIMAL|M1_THICK_HIDE|M1_NOHANDS|
 	  M1_OVIPAROUS|M1_CARNIVORE,
-	M2_STRONG|M2_HOSTILE, 0, CLR_BROWN),
+	M2_STRONG|M2_HOSTILE, 0, 0, CLR_BROWN),
     MON("salamander", S_LIZARD,
 	LVL(8, 12, -1, 0, -9), (G_HELL|1),
@@ -2900,5 +3022,6 @@
 	SIZ(1500, 400, 0, MS_MUMBLE, MZ_HUMAN), MR_SLEEP|MR_FIRE, MR_FIRE,
 	M1_HUMANOID|M1_SLITHY|M1_THICK_HIDE|M1_POIS,
-	M2_STALK|M2_HOSTILE|M2_COLLECT|M2_MAGIC, M3_INFRAVISIBLE, CLR_ORANGE),
+	M2_STALK|M2_HOSTILE|M2_COLLECT|M2_MAGIC, M3_INFRAVISIBLE, 
+	M4_VULNERABLE_COLD, CLR_ORANGE),
 
 /*
@@ -2910,5 +3033,5 @@
 	LVL(0, 0, 0, 0, 0), (G_NOGEN|G_NOCORPSE|G_UNIQ),
 	A(NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
-	SIZ(0, 0, 0, 0, 0), 0, 0, 0L, M2_NOPOLY, 0, CLR_BROWN),
+	SIZ(0, 0, 0, 0, 0), 0, 0, 0L, M2_NOPOLY, 0, 0, CLR_BROWN),
 
 	/* Note:
@@ -2928,5 +3051,5 @@
 	SIZ(WT_HUMAN, 400, 0, MS_HUMANOID, MZ_HUMAN), 0, 0,
 	M1_HUMANOID|M1_TUNNEL|M1_NEEDPICK|M1_OMNIVORE,
-	M2_NOPOLY|M2_HUMAN|M2_STRONG|M2_COLLECT, M3_INFRAVISIBLE, HI_DOMESTIC),
+	M2_NOPOLY|M2_HUMAN|M2_STRONG|M2_COLLECT, M3_INFRAVISIBLE, 0, HI_DOMESTIC),
     MON("barbarian", S_HUMAN,
 	LVL(10, 12, 10, 1, 0), G_NOGEN,
@@ -2935,21 +3058,22 @@
 	SIZ(WT_HUMAN, 400, 0, MS_HUMANOID, MZ_HUMAN), MR_POISON, 0,
 	M1_HUMANOID|M1_OMNIVORE,
-	M2_NOPOLY|M2_HUMAN|M2_STRONG|M2_COLLECT, M3_INFRAVISIBLE, HI_DOMESTIC),
+	M2_NOPOLY|M2_HUMAN|M2_STRONG|M2_COLLECT, 
+	M3_INFRAVISIBLE|M3_BERSERK, 0, HI_DOMESTIC),
     MON("caveman", S_HUMAN,
 	LVL(10, 12, 10, 0, 1), G_NOGEN,
-	A(ATTK(AT_WEAP, AD_PHYS, 2, 4),
-	  NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
+	A(ATTK(AT_WEAP, AD_PHYS, 2, 4), ATTK(AT_WEAP, AD_PHYS, 2, 4),
+	   NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
 	SIZ(WT_HUMAN, 400, 0, MS_HUMANOID, MZ_HUMAN), 0, 0,
 	M1_HUMANOID|M1_OMNIVORE,
 	M2_NOPOLY|M2_HUMAN|M2_STRONG|M2_MALE|M2_COLLECT, M3_INFRAVISIBLE,
-	HI_DOMESTIC),
+	0, HI_DOMESTIC),
     MON("cavewoman", S_HUMAN,
 	LVL(10, 12, 10, 0, 1), G_NOGEN,
-	A(ATTK(AT_WEAP, AD_PHYS, 2, 4),
-	  NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
+	A(ATTK(AT_WEAP, AD_PHYS, 2, 4), ATTK(AT_WEAP, AD_PHYS, 2, 4), 
+		NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
 	SIZ(WT_HUMAN, 400, 0, MS_HUMANOID, MZ_HUMAN), 0, 0,
 	M1_HUMANOID|M1_OMNIVORE,
 	M2_NOPOLY|M2_HUMAN|M2_STRONG|M2_FEMALE|M2_COLLECT, M3_INFRAVISIBLE,
-	HI_DOMESTIC),
+	0, HI_DOMESTIC),
     MON("healer", S_HUMAN,
 	LVL(10, 12, 10, 1, 0), G_NOGEN,
@@ -2958,5 +3082,5 @@
 	SIZ(WT_HUMAN, 400, 0, MS_HUMANOID, MZ_HUMAN), MR_POISON, 0,
 	M1_HUMANOID|M1_OMNIVORE,
-	M2_NOPOLY|M2_HUMAN|M2_STRONG|M2_COLLECT, M3_INFRAVISIBLE, HI_DOMESTIC),
+	M2_NOPOLY|M2_HUMAN|M2_STRONG|M2_COLLECT, M3_INFRAVISIBLE, 0, HI_DOMESTIC),
     MON("knight", S_HUMAN,
 	LVL(10, 12, 10, 1, 3), G_NOGEN,
@@ -2965,5 +3089,5 @@
 	SIZ(WT_HUMAN, 400, 0, MS_HUMANOID, MZ_HUMAN), 0, 0,
 	M1_HUMANOID|M1_OMNIVORE,
-	M2_NOPOLY|M2_HUMAN|M2_STRONG|M2_COLLECT, M3_INFRAVISIBLE, HI_DOMESTIC),
+	M2_NOPOLY|M2_HUMAN|M2_STRONG|M2_COLLECT, M3_INFRAVISIBLE, 0, HI_DOMESTIC),
     MON("monk", S_HUMAN, 
 	LVL(10, 12, 10, 2, 0), G_NOGEN,
@@ -2973,5 +3097,5 @@
 	M1_HUMANOID|M1_HERBIVORE,
 	M2_NOPOLY|M2_HUMAN|M2_STRONG|M2_COLLECT|M2_MALE,
-	M3_INFRAVISIBLE, HI_DOMESTIC),
+	M3_INFRAVISIBLE, 0, HI_DOMESTIC),
     MON("priest", S_HUMAN,
 	LVL(10, 12, 10, 2, 0), G_NOGEN,
@@ -2981,5 +3105,5 @@
 	M1_HUMANOID|M1_OMNIVORE,
 	M2_NOPOLY|M2_HUMAN|M2_STRONG|M2_MALE|M2_COLLECT, M3_INFRAVISIBLE,
-	HI_DOMESTIC),
+	0, HI_DOMESTIC),
     MON("priestess", S_HUMAN,
 	LVL(10, 12, 10, 2, 0), G_NOGEN,
@@ -2989,13 +3113,13 @@
 	M1_HUMANOID|M1_OMNIVORE,
 	M2_NOPOLY|M2_HUMAN|M2_STRONG|M2_FEMALE|M2_COLLECT, M3_INFRAVISIBLE,
-	HI_DOMESTIC),
+	0, HI_DOMESTIC),
     MON("ranger", S_HUMAN,
 	LVL(10, 12, 10, 2, -3), G_NOGEN,
-	A(ATTK(AT_WEAP, AD_PHYS, 1, 4),
-	  NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
+	A(ATTK(AT_WEAP, AD_PHYS, 1, 4), ATTK(AT_WEAP, AD_PHYS, 1, 4),
+	  NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
 	SIZ(WT_HUMAN, 400, 0, MS_HUMANOID, MZ_HUMAN), 0, 0,
 	M1_HUMANOID|M1_OMNIVORE,
-	M2_NOPOLY|M2_HUMAN|M2_STRONG|M2_COLLECT, M3_INFRAVISIBLE,
-	HI_DOMESTIC),
+	M2_NOPOLY|M2_HUMAN|M2_STRONG|M2_COLLECT, M3_EAGLEEYE|M3_INFRAVISIBLE,
+	0, HI_DOMESTIC),
     MON("rogue", S_HUMAN,
 	LVL(10, 12, 10, 1, -3), G_NOGEN,
@@ -3005,5 +3129,5 @@
 	M1_HUMANOID|M1_OMNIVORE,
 	M2_NOPOLY|M2_HUMAN|M2_STRONG|M2_GREEDY|M2_JEWELS|M2_COLLECT,
-	M3_INFRAVISIBLE, HI_DOMESTIC),
+	M3_EAGLEEYE|M3_INFRAVISIBLE, 0, HI_DOMESTIC),
     MON("samurai", S_HUMAN,
 	LVL(10, 12, 10, 1, 3), G_NOGEN,
@@ -3012,5 +3136,5 @@
 	SIZ(WT_HUMAN, 400, 0, MS_HUMANOID, MZ_HUMAN), 0, 0,
 	M1_HUMANOID|M1_OMNIVORE,
-	M2_NOPOLY|M2_HUMAN|M2_STRONG|M2_COLLECT, M3_INFRAVISIBLE, HI_DOMESTIC),
+	M2_NOPOLY|M2_HUMAN|M2_STRONG|M2_COLLECT, M3_INFRAVISIBLE, 0, HI_DOMESTIC),
 #ifdef TOURIST
     MON("tourist", S_HUMAN,
@@ -3020,5 +3144,5 @@
 	SIZ(WT_HUMAN, 400, 0, MS_HUMANOID, MZ_HUMAN), 0, 0,
 	M1_HUMANOID|M1_OMNIVORE,
-	M2_NOPOLY|M2_HUMAN|M2_STRONG|M2_COLLECT, M3_INFRAVISIBLE, HI_DOMESTIC),
+	M2_NOPOLY|M2_HUMAN|M2_STRONG|M2_COLLECT, M3_INFRAVISIBLE, 0, HI_DOMESTIC),
 #endif
     MON("valkyrie", S_HUMAN,
@@ -3029,5 +3153,5 @@
 	M1_HUMANOID|M1_OMNIVORE,
 	M2_NOPOLY|M2_HUMAN|M2_STRONG|M2_FEMALE|M2_COLLECT, M3_INFRAVISIBLE,
-	HI_DOMESTIC),
+	0, HI_DOMESTIC),
     MON("wizard", S_HUMAN,
 	LVL(10, 12, 10, 3, 0), G_NOGEN,
@@ -3037,35 +3161,32 @@
 	M1_HUMANOID|M1_OMNIVORE,
 	M2_NOPOLY|M2_HUMAN|M2_STRONG|M2_COLLECT|M2_MAGIC, M3_INFRAVISIBLE,
-	HI_DOMESTIC),
+	0, HI_DOMESTIC),
 /*
  * quest leaders
  */
     MON("Lord Carnarvon", S_HUMAN,
-	LVL(20, 12, 0, 30, 20), (G_NOGEN|G_UNIQ),
-	A(ATTK(AT_WEAP, AD_PHYS, 1, 6),
-	  NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
-	SIZ(WT_HUMAN, 400, 0, MS_LEADER, MZ_HUMAN), 0, 0,
-	M1_TUNNEL|M1_NEEDPICK|M1_HUMANOID|M1_OMNIVORE,
-	M2_NOPOLY|M2_HUMAN|M2_PNAME|M2_PEACEFUL|M2_STRONG|M2_MALE|
-	  M2_COLLECT|M2_MAGIC,
-	M3_CLOSE|M3_INFRAVISIBLE, HI_LORD),
+	LVL(20, 15, 0, 90, 20), (G_NOGEN|G_UNIQ),
+	A(ATTK(AT_WEAP, AD_PHYS, 4, 10),ATTK(AT_MAGC, AD_SPEL, 4, 8),
+	  NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
+	SIZ(WT_HUMAN, 400, 0, MS_LEADER, MZ_HUMAN), MR_SLEEP|MR_POISON|MR_STONE, 0,
+	M1_FLY|M1_TUNNEL|M1_NEEDPICK|M1_HUMANOID|M1_OMNIVORE,
+	M2_NOPOLY|M2_HUMAN|M2_PNAME|M2_PEACEFUL|M2_STRONG|M2_MALE|M2_COLLECT|M2_MAGIC,
+	M3_CLOSE|M3_INFRAVISIBLE, 0, HI_LORD),
     MON("Pelias", S_HUMAN,
-	LVL(20, 12, 0, 30, 0), (G_NOGEN|G_UNIQ),
-	A(ATTK(AT_WEAP, AD_PHYS, 1, 6),
-	  NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
-	SIZ(WT_HUMAN, 400, 0, MS_LEADER, MZ_HUMAN), MR_POISON, 0,
-	M1_HUMANOID|M1_OMNIVORE,
-	M2_NOPOLY|M2_HUMAN|M2_PNAME|M2_PEACEFUL|M2_STRONG|M2_MALE|
-	  M2_COLLECT|M2_MAGIC,
-	M3_CLOSE|M3_INFRAVISIBLE, HI_LORD),
+	LVL(20, 15, 0, 90, 0), (G_NOGEN|G_UNIQ),
+	A(ATTK(AT_WEAP, AD_PHYS, 4, 10), ATTK(AT_WEAP, AD_PHYS, 4, 10),
+		NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
+	SIZ(WT_HUMAN, 400, 0, MS_LEADER, MZ_HUMAN), MR_SLEEP|MR_POISON|MR_STONE, 0,
+	M1_FLY|M1_HUMANOID|M1_OMNIVORE,
+	M2_NOPOLY|M2_HUMAN|M2_PNAME|M2_PEACEFUL|M2_STRONG|M2_MALE|M2_COLLECT|M2_MAGIC,
+	M3_CLOSE|M3_INFRAVISIBLE, 0, HI_LORD),
     MON("Shaman Karnov", S_HUMAN,
-	LVL(20, 12, 0, 30, 20), (G_NOGEN|G_UNIQ),
-	A(ATTK(AT_WEAP, AD_PHYS, 2, 4),
-	  NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
-	SIZ(WT_HUMAN, 400, 0, MS_LEADER, MZ_HUMAN), 0, 0,
-	M1_HUMANOID|M1_OMNIVORE,
-	M2_NOPOLY|M2_HUMAN|M2_PNAME|M2_PEACEFUL|M2_STRONG|M2_MALE|
-	  M2_COLLECT|M2_MAGIC,
-	M3_CLOSE|M3_INFRAVISIBLE, HI_LORD),
+	LVL(20, 15, 0, 90, 20), (G_NOGEN|G_UNIQ),
+	A(ATTK(AT_WEAP, AD_PHYS, 4, 10), ATTK(AT_MAGC, AD_CLRC, 2, 8),
+		NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
+	SIZ(WT_HUMAN, 400, 0, MS_LEADER, MZ_HUMAN), MR_SLEEP|MR_POISON|MR_STONE, 0,
+	M1_FLY|M1_HUMANOID|M1_OMNIVORE,
+	M2_NOPOLY|M2_HUMAN|M2_PNAME|M2_PEACEFUL|M2_STRONG|M2_MALE|M2_COLLECT|M2_MAGIC,
+	M3_CLOSE|M3_INFRAVISIBLE, 0, HI_LORD),
 #if 0	/* OBSOLETE */
 	/* Two for elves - one of each sex.
@@ -3079,5 +3200,5 @@
 	M2_NOPOLY|M2_ELF|M2_HUMAN|M2_PNAME|M2_PEACEFUL|M2_STRONG|
 	  M2_MALE|M2_COLLECT|M2_MAGIC,
-	M3_CLOSE|M3_INFRAVISION|M3_INFRAVISIBLE, HI_LORD),
+	M3_CLOSE|M3_INFRAVISION|M3_INFRAVISIBLE, 0, HI_LORD),
     MON("Elwing", S_HUMAN,
 	LVL(20, 12, 0, 50, -20), (G_NOGEN|G_UNIQ),
@@ -3088,102 +3209,94 @@
 	M2_NOPOLY|M2_ELF|M2_HUMAN|M2_PNAME|M2_PEACEFUL|M2_STRONG|
 	  M2_FEMALE|M2_COLLECT|M2_MAGIC,
-	M3_CLOSE|M3_INFRAVISION|M3_INFRAVISIBLE, HI_LORD),
+	M3_CLOSE|M3_INFRAVISION|M3_INFRAVISIBLE, 0, HI_LORD),
 #endif
     MON("Hippocrates", S_HUMAN,
-	LVL(20, 12, 0, 40, 0), (G_NOGEN|G_UNIQ),
-	A(ATTK(AT_WEAP, AD_PHYS, 1, 6),
-	  NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
-	SIZ(WT_HUMAN, 400, 0, MS_LEADER, MZ_HUMAN), MR_POISON, 0,
-	M1_HUMANOID|M1_OMNIVORE,
-	M2_NOPOLY|M2_HUMAN|M2_PNAME|M2_PEACEFUL|M2_STRONG|M2_MALE|
-	  M2_COLLECT|M2_MAGIC,
-	M3_CLOSE|M3_INFRAVISIBLE, HI_LORD),
+	LVL(20, 15, 0, 90, 0), (G_NOGEN|G_UNIQ),
+	A(ATTK(AT_WEAP, AD_PHYS, 4, 10), ATTK(AT_MAGC, AD_CLRC, 2, 8),
+		NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
+	SIZ(WT_HUMAN, 400, 0, MS_LEADER, MZ_HUMAN), MR_SLEEP|MR_POISON|MR_STONE, 0,
+	M1_FLY|M1_HUMANOID|M1_OMNIVORE,
+	M2_NOPOLY|M2_HUMAN|M2_PNAME|M2_PEACEFUL|M2_STRONG|M2_MALE|M2_COLLECT|M2_MAGIC,
+	M3_CLOSE|M3_INFRAVISIBLE, 0, HI_LORD),
     MON("King Arthur", S_HUMAN,
-	LVL(20, 12, 0, 40, 20), (G_NOGEN|G_UNIQ),
-	A(ATTK(AT_WEAP, AD_PHYS, 1, 6), ATTK(AT_WEAP, AD_PHYS, 1, 6),
+	LVL(20, 15, 0, 90, 20), (G_NOGEN|G_UNIQ),
+	A(ATTK(AT_WEAP, AD_PHYS, 4, 10), ATTK(AT_WEAP, AD_PHYS, 4, 10),
 	  NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
-	SIZ(WT_HUMAN, 400, 0, MS_LEADER, MZ_HUMAN), 0, 0,
-	M1_HUMANOID|M1_OMNIVORE,
-	M2_NOPOLY|M2_HUMAN|M2_PNAME|M2_PEACEFUL|M2_STRONG|M2_MALE|
-	  M2_COLLECT|M2_MAGIC,
-	M3_CLOSE|M3_INFRAVISIBLE, HI_LORD),
+	SIZ(WT_HUMAN, 400, 0, MS_LEADER, MZ_HUMAN), MR_SLEEP|MR_POISON|MR_STONE, 0,
+	M1_FLY|M1_HUMANOID|M1_OMNIVORE,
+	M2_NOPOLY|M2_HUMAN|M2_PNAME|M2_PEACEFUL|M2_STRONG|M2_MALE|M2_COLLECT|M2_MAGIC,
+	M3_CLOSE|M3_INFRAVISIBLE, 0, HI_LORD),
     MON("Grand Master", S_HUMAN,
-	LVL(25, 12, 0, 70, 0), (G_NOGEN|G_UNIQ),
+	LVL(25, 15, 0, 90, 0), (G_NOGEN|G_UNIQ),
 	A(ATTK(AT_CLAW, AD_PHYS, 4, 10), ATTK(AT_KICK, AD_PHYS, 2, 8),
 	  ATTK(AT_MAGC, AD_CLRC, 2, 8), ATTK(AT_MAGC, AD_CLRC, 2, 8),
 	  NO_ATTK, NO_ATTK),
 	SIZ(WT_HUMAN, 400, 0, MS_LEADER, MZ_HUMAN),
-	MR_FIRE|MR_ELEC|MR_SLEEP|MR_POISON, 0,
-	M1_HUMANOID|M1_SEE_INVIS|M1_HERBIVORE,
+	MR_FIRE|MR_ELEC|MR_SLEEP|MR_POISON|MR_STONE, 0,
+	M1_FLY|M1_HUMANOID|M1_SEE_INVIS|M1_HERBIVORE,
 	M2_NOPOLY|M2_HUMAN|M2_PEACEFUL|M2_STRONG|M2_NASTY|M2_MAGIC,
-	M3_CLOSE|M3_INFRAVISIBLE, CLR_BLACK),
+	M3_CLOSE|M3_INFRAVISIBLE, 0, CLR_BLACK),
     MON("Arch Priest", S_HUMAN,
-	LVL(25, 12, 7, 70, 0), (G_NOGEN|G_UNIQ),
+	LVL(25, 15, 0, 90, 0), (G_NOGEN|G_UNIQ),
 	A(ATTK(AT_WEAP, AD_PHYS, 4,10), ATTK(AT_KICK, AD_PHYS, 2, 8),
 	  ATTK(AT_MAGC, AD_CLRC, 2, 8), ATTK(AT_MAGC, AD_CLRC, 2, 8),
 	  NO_ATTK, NO_ATTK),
 	SIZ(WT_HUMAN, 400, 0, MS_LEADER, MZ_HUMAN),
-	MR_FIRE|MR_ELEC|MR_SLEEP|MR_POISON, 0,
-	M1_HUMANOID|M1_SEE_INVIS|M1_OMNIVORE,
+	MR_FIRE|MR_ELEC|MR_SLEEP|MR_POISON|MR_STONE, 0,
+	M1_FLY|M1_HUMANOID|M1_SEE_INVIS|M1_OMNIVORE,
 	M2_NOPOLY|M2_HUMAN|M2_PEACEFUL|M2_STRONG|M2_COLLECT|M2_MAGIC,
-	M3_CLOSE|M3_INFRAVISIBLE, CLR_WHITE),
+	M3_CLOSE|M3_INFRAVISIBLE, 0, CLR_WHITE),
     MON("Orion", S_HUMAN,
-	LVL(20, 12, 0, 30, 0), (G_NOGEN|G_UNIQ),
-	A(ATTK(AT_WEAP, AD_PHYS, 1, 6),
-	  NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
-	SIZ(WT_HUMAN, 400, 0, MS_LEADER, MZ_HUMAN), 0, 0,
-	M1_HUMANOID|M1_OMNIVORE|M1_SEE_INVIS|M1_SWIM|M1_AMPHIBIOUS,
-	M2_NOPOLY|M2_HUMAN|M2_PNAME|M2_PEACEFUL|M2_STRONG|M2_MALE|
-	  M2_COLLECT|M2_MAGIC,
-	M3_CLOSE|M3_INFRAVISION|M3_INFRAVISIBLE, HI_LORD),
+	LVL(20, 15, 0, 90, 0), (G_NOGEN|G_UNIQ),
+	A(ATTK(AT_WEAP, AD_PHYS, 4, 10), ATTK(AT_MAGC, AD_SPEL, 4, 8),
+		NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
+	SIZ(WT_HUMAN, 400, 0, MS_LEADER, MZ_HUMAN), MR_SLEEP|MR_POISON|MR_STONE, 0,
+	M1_FLY|M1_HUMANOID|M1_OMNIVORE|M1_SEE_INVIS|M1_SWIM|M1_AMPHIBIOUS,
+	M2_NOPOLY|M2_HUMAN|M2_PNAME|M2_PEACEFUL|M2_STRONG|M2_MALE|M2_COLLECT|M2_MAGIC,
+	M3_CLOSE|M3_INFRAVISION|M3_INFRAVISIBLE, 0, HI_LORD),
 	/* Note: Master of Thieves is also the Tourist's nemesis.
 	 */
     MON("Master of Thieves", S_HUMAN,
-	LVL(20, 12, 0, 30, -20), (G_NOGEN|G_UNIQ),
-	A(ATTK(AT_WEAP, AD_PHYS, 2, 6), ATTK(AT_WEAP, AD_PHYS, 2, 6),
+	LVL(20, 15, 0, 90, -20), (G_NOGEN|G_UNIQ),
+	A(ATTK(AT_WEAP, AD_PHYS, 4, 10), ATTK(AT_WEAP, AD_PHYS, 2, 6),
 	  ATTK(AT_CLAW, AD_SAMU, 2, 4), NO_ATTK, NO_ATTK, NO_ATTK),
-	SIZ(WT_HUMAN, 400, 0, MS_LEADER, MZ_HUMAN), MR_STONE, 0,
-	M1_HUMANOID|M1_OMNIVORE,
-	M2_NOPOLY|M2_HUMAN|M2_PEACEFUL|M2_STRONG|M2_MALE|M2_GREEDY|
-	  M2_JEWELS|M2_COLLECT|M2_MAGIC,
-	M3_CLOSE|M3_INFRAVISIBLE, HI_LORD),
+	SIZ(WT_HUMAN, 400, 0, MS_LEADER, MZ_HUMAN), MR_SLEEP|MR_POISON|MR_STONE, 0,
+	M1_FLY|M1_HUMANOID|M1_OMNIVORE,
+	M2_NOPOLY|M2_HUMAN|M2_PEACEFUL|M2_STRONG|M2_MALE|M2_GREEDY|M2_JEWELS|M2_COLLECT|M2_MAGIC,
+	M3_CLOSE|M3_INFRAVISIBLE, 0, HI_LORD),
     MON("Lord Sato", S_HUMAN,
-	LVL(20, 12, 0, 30, 20), (G_NOGEN|G_UNIQ),
-	A(ATTK(AT_WEAP, AD_PHYS, 1, 8), ATTK(AT_WEAP, AD_PHYS, 1, 6),
+	LVL(20, 15, 0, 90, 20), (G_NOGEN|G_UNIQ),
+	A(ATTK(AT_WEAP, AD_PHYS, 4, 10), ATTK(AT_WEAP, AD_PHYS, 4, 10),
 	  NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
-	SIZ(WT_HUMAN, 400, 0, MS_LEADER, MZ_HUMAN), 0, 0,
-	M1_HUMANOID|M1_OMNIVORE,
-	M2_NOPOLY|M2_HUMAN|M2_PNAME|M2_PEACEFUL|M2_STRONG|M2_MALE|
-	  M2_COLLECT|M2_MAGIC,
-	M3_CLOSE|M3_INFRAVISIBLE, HI_LORD),
+	SIZ(WT_HUMAN, 400, 0, MS_LEADER, MZ_HUMAN), MR_SLEEP|MR_POISON|MR_STONE, 0,
+	M1_FLY|M1_HUMANOID|M1_OMNIVORE,
+	M2_NOPOLY|M2_HUMAN|M2_PNAME|M2_PEACEFUL|M2_STRONG|M2_MALE|M2_COLLECT|M2_MAGIC,
+	M3_CLOSE|M3_INFRAVISIBLE, 0, HI_LORD),
 #ifdef TOURIST
     MON("Twoflower", S_HUMAN,
-	LVL(20, 12, 10, 20, 0), (G_NOGEN|G_UNIQ),
-	A(ATTK(AT_WEAP, AD_PHYS, 1, 6), ATTK(AT_WEAP, AD_PHYS, 1, 6),
-	  NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
-	SIZ(WT_HUMAN, 400, 0, MS_LEADER, MZ_HUMAN), 0, 0,
-	M1_HUMANOID|M1_OMNIVORE,
-	M2_NOPOLY|M2_HUMAN|M2_PNAME|M2_PEACEFUL|M2_STRONG|M2_MALE|
-	  M2_COLLECT|M2_MAGIC,
-	M3_CLOSE|M3_INFRAVISIBLE, HI_DOMESTIC),
+	LVL(20, 15, 10, 90, 0), (G_NOGEN|G_UNIQ),
+	A(ATTK(AT_WEAP, AD_PHYS, 4, 10), 
+	  NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
+	SIZ(WT_HUMAN, 400, 0, MS_LEADER, MZ_HUMAN), MR_SLEEP|MR_POISON|MR_STONE, 0,
+	M1_FLY|M1_HUMANOID|M1_OMNIVORE,
+	M2_NOPOLY|M2_HUMAN|M2_PNAME|M2_PEACEFUL|M2_STRONG|M2_MALE|M2_COLLECT|M2_MAGIC,
+	M3_CLOSE|M3_INFRAVISIBLE, 0, HI_DOMESTIC),
 #endif
     MON("Norn", S_HUMAN,
-	LVL(20, 12, 0, 80, 0), (G_NOGEN|G_UNIQ),
-	A(ATTK(AT_WEAP, AD_PHYS, 1, 8), ATTK(AT_WEAP, AD_PHYS, 1, 6),
+	LVL(20, 15, 0, 90, 0), (G_NOGEN|G_UNIQ),
+	A(ATTK(AT_WEAP, AD_PHYS, 4, 10), ATTK(AT_WEAP, AD_PHYS, 4, 10),
 	  NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
-	SIZ(WT_HUMAN, 400, 0, MS_LEADER, MZ_HUMAN), MR_COLD, 0,
-	M1_HUMANOID|M1_OMNIVORE,
-	M2_NOPOLY|M2_HUMAN|M2_PEACEFUL|M2_STRONG|M2_FEMALE|
-	  M2_COLLECT|M2_MAGIC,
-	M3_CLOSE|M3_INFRAVISIBLE, HI_LORD),
+	SIZ(WT_HUMAN, 400, 0, MS_LEADER, MZ_HUMAN), MR_SLEEP|MR_COLD|MR_POISON|MR_STONE, 0,
+	M1_FLY|M1_HUMANOID|M1_OMNIVORE,
+	M2_NOPOLY|M2_HUMAN|M2_PEACEFUL|M2_STRONG|M2_FEMALE|M2_COLLECT|M2_MAGIC,
+	M3_CLOSE|M3_INFRAVISIBLE, 0, HI_LORD),
     MON("Neferet the Green", S_HUMAN,
-	LVL(20, 12, 0, 60, 0), (G_NOGEN|G_UNIQ),
-	A(ATTK(AT_WEAP, AD_PHYS, 1, 6), ATTK(AT_MAGC, AD_SPEL, 2, 8),
+	LVL(20, 15, 0, 90, 0), (G_NOGEN|G_UNIQ),
+	A(ATTK(AT_MAGC, AD_SPEL, 2, 8), ATTK(AT_MAGC, AD_SPEL, 2, 8),
 	  NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
-	SIZ(WT_HUMAN, 400, 0, MS_LEADER, MZ_HUMAN), 0, 0,
-	M1_HUMANOID|M1_OMNIVORE,
-	M2_NOPOLY|M2_HUMAN|M2_FEMALE|M2_PNAME|M2_PEACEFUL|
-	  M2_STRONG|M2_COLLECT|M2_MAGIC,
-	M3_CLOSE|M3_INFRAVISIBLE, CLR_GREEN),
+	SIZ(WT_HUMAN, 400, 0, MS_LEADER, MZ_HUMAN), MR_SLEEP|MR_POISON|MR_STONE, 0,
+	M1_FLY|M1_HUMANOID|M1_OMNIVORE,
+	M2_NOPOLY|M2_HUMAN|M2_FEMALE|M2_PNAME|M2_PEACEFUL|M2_STRONG|M2_COLLECT|M2_MAGIC,
+	M3_CLOSE|M3_INFRAVISIBLE, 0, CLR_GREEN),
 /*
  * quest nemeses
@@ -3197,5 +3310,5 @@
 	MR_FIRE|MR_POISON|MR_STONE, 0, M1_FLY|M1_SEE_INVIS|M1_POIS,
 	M2_NOPOLY|M2_DEMON|M2_STALK|M2_HOSTILE|M2_STRONG|M2_NASTY|M2_COLLECT,
-	M3_WANTSARTI|M3_WAITFORU|M3_INFRAVISION|M3_INFRAVISIBLE, CLR_RED),
+	M3_WANTSARTI|M3_WAITFORU|M3_INFRAVISION|M3_INFRAVISIBLE, 0, CLR_RED),
     MON("Thoth Amon", S_HUMAN,
 	LVL(16, 12, 0, 10, -14), (G_NOGEN|G_UNIQ|G_NOCORPSE),
@@ -3207,5 +3320,5 @@
 	M2_NOPOLY|M2_HUMAN|M2_PNAME|M2_STRONG|M2_MALE|M2_STALK|M2_HOSTILE|
 	  M2_NASTY|M2_COLLECT|M2_MAGIC,
-	M3_WANTSARTI|M3_WAITFORU|M3_INFRAVISIBLE, HI_LORD),
+	M3_WANTSARTI|M3_WAITFORU|M3_INFRAVISIBLE, 0, HI_LORD),
 	/* Multi-headed, possessing the breath attacks of all the other dragons
 	 * (selected at random when attacking).
@@ -3222,5 +3335,5 @@
 	M2_NOPOLY|M2_HOSTILE|M2_FEMALE|M2_STALK|M2_STRONG|M2_NASTY|
 	  M2_GREEDY|M2_JEWELS|M2_MAGIC,
-	M3_WANTSARTI|M3_WAITFORU|M3_INFRAVISIBLE, HI_LORD),
+	M3_WANTSARTI|M3_WAITFORU|M3_INFRAVISIBLE, 0, HI_LORD),
 #if 0	/* OBSOLETE */
     MON("Goblin King", S_ORC,
@@ -3232,5 +3345,5 @@
 	M2_NOPOLY|M2_ORC|M2_HOSTILE|M2_STRONG|M2_STALK|M2_NASTY|M2_MALE|
 	  M2_GREEDY|M2_JEWELS|M2_COLLECT|M2_MAGIC,
-	M3_WANTSARTI|M3_WAITFORU|M3_INFRAVISION|M3_INFRAVISIBLE, HI_LORD),
+	M3_WANTSARTI|M3_WAITFORU|M3_INFRAVISION|M3_INFRAVISIBLE, 0, HI_LORD),
 #endif
     MON("Cyclops", S_GIANT,
@@ -3242,5 +3355,5 @@
 	M2_NOPOLY|M2_GIANT|M2_STRONG|M2_ROCKTHROW|M2_STALK|M2_HOSTILE|
 	  M2_NASTY|M2_MALE|M2_JEWELS|M2_COLLECT,
-	M3_WANTSARTI|M3_WAITFORU|M3_INFRAVISION|M3_INFRAVISIBLE, CLR_GRAY),
+	M3_WANTSARTI|M3_WAITFORU|M3_INFRAVISION|M3_INFRAVISIBLE, 0, CLR_GRAY),
     MON("Ixoth", S_DRAGON,
 	LVL(15, 12, -1, 20, -14), (G_NOGEN|G_UNIQ),
@@ -3249,9 +3362,9 @@
 	  ATTK(AT_CLAW, AD_SAMU, 2, 4), NO_ATTK ),
 	SIZ(WT_DRAGON, 1600, 0, MS_NEMESIS, MZ_GIGANTIC),
-	MR_FIRE|MR_STONE, MR_FIRE,
+	MR_FIRE|MR_STONE|MR_POISON, MR_FIRE,
 	M1_FLY|M1_THICK_HIDE|M1_NOHANDS|M1_CARNIVORE|M1_SEE_INVIS,
 	M2_NOPOLY|M2_PNAME|M2_HOSTILE|M2_STRONG|M2_NASTY|M2_STALK|
 	  M2_GREEDY|M2_JEWELS|M2_MAGIC,
-	M3_WANTSARTI|M3_WAITFORU|M3_INFRAVISIBLE, CLR_RED),
+	M3_WANTSARTI|M3_WAITFORU|M3_INFRAVISIBLE, 0, CLR_RED),
     MON("Master Kaen", S_HUMAN,
 	LVL(25, 12, -10, 10, -20), (G_NOGEN|G_UNIQ),
@@ -3264,5 +3377,5 @@
 	M2_NOPOLY|M2_HUMAN|M2_PNAME|M2_HOSTILE|M2_STRONG|M2_NASTY|
 	  M2_STALK|M2_COLLECT|M2_MAGIC,
-	M3_WANTSARTI|M3_WAITFORU|M3_INFRAVISIBLE, HI_LORD),
+	M3_WANTSARTI|M3_WAITFORU|M3_INFRAVISIBLE, 0, HI_LORD),
     MON("Nalzok", S_DEMON,
 	LVL(16, 12, -2, 85, -127), (G_NOGEN|G_UNIQ|G_NOCORPSE),
@@ -3274,5 +3387,5 @@
 	M2_NOPOLY|M2_DEMON|M2_PNAME|M2_HOSTILE|M2_STRONG|M2_STALK|
 	  M2_NASTY|M2_COLLECT,
-	M3_WANTSARTI|M3_WAITFORU|M3_INFRAVISION|M3_INFRAVISIBLE, CLR_RED),
+	M3_WANTSARTI|M3_WAITFORU|M3_INFRAVISION|M3_INFRAVISIBLE, 0, CLR_RED),
     MON("Scorpius", S_SPIDER,
 	LVL(15, 12, 10, 0, -15), (G_NOGEN|G_UNIQ),
@@ -3283,5 +3396,5 @@
 	M2_NOPOLY|M2_PNAME|M2_HOSTILE|M2_STRONG|M2_STALK|M2_NASTY|
 	  M2_COLLECT|M2_MAGIC,
-	M3_WANTSARTI|M3_WAITFORU, HI_LORD),
+	M3_EAGLEEYE|M3_WANTSARTI|M3_WAITFORU, 0, HI_LORD),
     MON("Master Assassin", S_HUMAN,
 	LVL(15, 12, 0, 30, 18), (G_NOGEN|G_UNIQ),
@@ -3292,5 +3405,5 @@
 	M2_NOPOLY|M2_HUMAN|M2_STRONG|M2_HOSTILE|M2_STALK|M2_NASTY|
 	  M2_COLLECT|M2_MAGIC,
-	M3_WANTSARTI|M3_WAITFORU|M3_INFRAVISIBLE, HI_LORD),
+	M3_EAGLEEYE|M3_WANTSARTI|M3_WAITFORU|M3_INFRAVISIBLE, 0, HI_LORD),
 	/* A renegade daimyo who led a 13 year civil war against the shogun
 	 * of his time.
@@ -3304,5 +3417,5 @@
 	M2_NOPOLY|M2_HUMAN|M2_PNAME|M2_HOSTILE|M2_STRONG|M2_STALK|
 	  M2_NASTY|M2_MALE|M2_COLLECT|M2_MAGIC,
-	M3_WANTSARTI|M3_WAITFORU|M3_INFRAVISIBLE, HI_LORD),
+	M3_WANTSARTI|M3_WAITFORU|M3_INFRAVISIBLE, 0, HI_LORD),
 #ifdef TOURIST
 	/*
@@ -3318,5 +3431,5 @@
 	M2_NOPOLY|M2_GIANT|M2_MALE|M2_PNAME|M2_HOSTILE|M2_STALK|
 	  M2_STRONG|M2_NASTY|M2_ROCKTHROW|M2_JEWELS|M2_COLLECT,
-	M3_WANTSARTI|M3_WAITFORU|M3_INFRAVISION|M3_INFRAVISIBLE, HI_LORD),
+	M3_WANTSARTI|M3_WAITFORU|M3_INFRAVISION|M3_INFRAVISIBLE, 0, HI_LORD),
     MON("Dark One", S_HUMAN,
 	LVL(15, 12, 0, 80, -10), (G_NOGEN|G_UNIQ|G_NOCORPSE),
@@ -3328,5 +3441,5 @@
 	M2_NOPOLY|M2_HUMAN|M2_STRONG|M2_HOSTILE|M2_STALK|M2_NASTY|
 	  M2_COLLECT|M2_MAGIC,
-	M3_WANTSARTI|M3_WAITFORU|M3_INFRAVISIBLE, CLR_BLACK),
+	M3_WANTSARTI|M3_WAITFORU|M3_INFRAVISIBLE, 0, CLR_BLACK),
 /*
  * quest "guardians"
@@ -3339,5 +3452,5 @@
 	M1_TUNNEL|M1_NEEDPICK|M1_HUMANOID|M1_OMNIVORE,
 	M2_NOPOLY|M2_HUMAN|M2_PEACEFUL|M2_STRONG|M2_COLLECT, M3_INFRAVISIBLE,
-	HI_DOMESTIC),
+	0, HI_DOMESTIC),
     MON("chieftain", S_HUMAN,
 	LVL(5, 12, 10, 10, 0), G_NOGEN,
@@ -3347,5 +3460,5 @@
 	M1_HUMANOID|M1_OMNIVORE,
 	M2_NOPOLY|M2_HUMAN|M2_PEACEFUL|M2_STRONG|M2_COLLECT, M3_INFRAVISIBLE,
-	HI_DOMESTIC),
+	0, HI_DOMESTIC),
     MON("neanderthal", S_HUMAN,
 	LVL(5, 12, 10, 10, 1), G_NOGEN,
@@ -3355,5 +3468,5 @@
 	M1_HUMANOID|M1_OMNIVORE,
 	M2_NOPOLY|M2_HUMAN|M2_PEACEFUL|M2_STRONG|M2_COLLECT, M3_INFRAVISIBLE,
-	HI_DOMESTIC),
+	0, HI_DOMESTIC),
 #if 0	/* OBSOLETE */
     MON("High-elf", S_HUMAN,
@@ -3364,5 +3477,5 @@
 	M1_HUMANOID|M1_SEE_INVIS|M1_OMNIVORE,
 	M2_NOPOLY|M2_ELF|M2_PEACEFUL|M2_COLLECT,
-	M3_INFRAVISION|M3_INFRAVISIBLE, HI_DOMESTIC),
+	M3_INFRAVISION|M3_INFRAVISIBLE, 0, HI_DOMESTIC),
 #endif
     MON("attendant", S_HUMAN,
@@ -3373,5 +3486,5 @@
 	M1_HUMANOID|M1_OMNIVORE,
 	M2_NOPOLY|M2_HUMAN|M2_PEACEFUL|M2_STRONG|M2_COLLECT, M3_INFRAVISIBLE,
-	HI_DOMESTIC),
+	0, HI_DOMESTIC),
     MON("page", S_HUMAN,
 	LVL(5, 12, 10, 10, 3), G_NOGEN,
@@ -3381,5 +3494,5 @@
 	M1_HUMANOID|M1_OMNIVORE,
 	M2_NOPOLY|M2_HUMAN|M2_PEACEFUL|M2_STRONG|M2_COLLECT, M3_INFRAVISIBLE,
-	HI_DOMESTIC),
+	0, HI_DOMESTIC),
     MON("abbot", S_HUMAN, 
 	LVL(5, 12, 10, 20, 0), G_NOGEN,
@@ -3389,5 +3502,5 @@
 	M1_HUMANOID|M1_HERBIVORE,
 	M2_NOPOLY|M2_HUMAN|M2_PEACEFUL|M2_STRONG|M2_COLLECT, M3_INFRAVISIBLE,
-	HI_DOMESTIC),
+	0, HI_DOMESTIC),
     MON("acolyte", S_HUMAN,
 	LVL(5, 12, 10, 20, 0), G_NOGEN,
@@ -3397,5 +3510,5 @@
 	M1_HUMANOID|M1_OMNIVORE,
 	M2_NOPOLY|M2_HUMAN|M2_PEACEFUL|M2_STRONG|M2_COLLECT, M3_INFRAVISIBLE,
-	HI_DOMESTIC),
+	0, HI_DOMESTIC),
     MON("hunter", S_HUMAN,
 	LVL(5, 12, 10, 10, -7), G_NOGEN,
@@ -3405,5 +3518,5 @@
 	M1_HUMANOID|M1_SEE_INVIS|M1_OMNIVORE,
 	M2_NOPOLY|M2_HUMAN|M2_PEACEFUL|M2_STRONG|M2_COLLECT,
-	M3_INFRAVISION|M3_INFRAVISIBLE, HI_DOMESTIC),
+	M3_EAGLEEYE|M3_INFRAVISION|M3_INFRAVISIBLE, 0, HI_DOMESTIC),
     MON("thug", S_HUMAN,
 	LVL(5, 12, 10, 10, -3), G_NOGEN,
@@ -3413,5 +3526,5 @@
 	M1_HUMANOID|M1_OMNIVORE,
 	M2_NOPOLY|M2_HUMAN|M2_PEACEFUL|M2_STRONG|M2_GREEDY|M2_COLLECT,
-	M3_INFRAVISIBLE, HI_DOMESTIC),
+	M3_INFRAVISIBLE, 0, HI_DOMESTIC),
     MON("ninja", S_HUMAN,
 	LVL(5, 12, 10, 10, 3), G_NOGEN,
@@ -3420,6 +3533,6 @@
 	SIZ(WT_HUMAN, 400, 0, MS_HUMANOID, MZ_HUMAN), 0, 0,
 	M1_HUMANOID|M1_OMNIVORE,
-	M2_NOPOLY|M2_HUMAN|M2_HOSTILE|M2_STRONG|M2_COLLECT, M3_INFRAVISIBLE,
-	HI_DOMESTIC),
+	M2_NOPOLY|M2_HUMAN|M2_HOSTILE|M2_STRONG|M2_COLLECT, M3_EAGLEEYE|M3_INFRAVISIBLE,
+	0, HI_DOMESTIC),
     MON("roshi", S_HUMAN,
 	LVL(5, 12, 10, 10, 3), G_NOGEN,
@@ -3429,5 +3542,5 @@
 	M1_HUMANOID|M1_OMNIVORE,
 	M2_NOPOLY|M2_HUMAN|M2_PEACEFUL|M2_STRONG|M2_COLLECT, M3_INFRAVISIBLE,
-	HI_DOMESTIC),
+	0, HI_DOMESTIC),
 #ifdef TOURIST
     MON("guide", S_HUMAN,
@@ -3438,5 +3551,5 @@
 	M1_HUMANOID|M1_OMNIVORE,
 	M2_NOPOLY|M2_HUMAN|M2_PEACEFUL | M2_STRONG|M2_COLLECT|M2_MAGIC,
-	M3_INFRAVISIBLE, HI_DOMESTIC),
+	M3_INFRAVISIBLE, 0, HI_DOMESTIC),
 #endif
     MON("warrior", S_HUMAN,
@@ -3447,5 +3560,5 @@
 	M1_HUMANOID|M1_OMNIVORE,
 	M2_NOPOLY|M2_HUMAN|M2_PEACEFUL|M2_STRONG|M2_COLLECT|M2_FEMALE, M3_INFRAVISIBLE,
-	HI_DOMESTIC),
+	0, HI_DOMESTIC),
     MON("apprentice", S_HUMAN,
 	LVL(5, 12, 10, 30, 0), G_NOGEN,
@@ -3455,5 +3568,5 @@
 	M1_HUMANOID|M1_OMNIVORE,
 	M2_NOPOLY|M2_HUMAN|M2_PEACEFUL|M2_STRONG|M2_COLLECT|M2_MAGIC,
-	M3_INFRAVISIBLE, HI_DOMESTIC),
+	M3_INFRAVISIBLE, 0, HI_DOMESTIC),
 /*
  * array terminator
@@ -3462,5 +3575,5 @@
 	LVL(0, 0, 0, 0, 0), (0),
 	A(NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
-	SIZ(0, 0, 0, 0, 0), 0, 0, 0L, 0L, 0, 0)
+	SIZ(0, 0, 0, 0, 0), 0, 0, 0L, 0L, 0L, 0L, 0)
 };
 #endif /* !SPLITMON_1 */
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/src/mplayer.c nethack/src/mplayer.c
--- nh_orig/src/mplayer.c	2003-12-07 18:39:13.000000000 -0500
+++ nethack/src/mplayer.c	2010-05-13 09:22:21.978715533 -0400
@@ -89,4 +89,34 @@
 }
 
+/* return a randomly generated elven name */
+const char *
+elf_name(id)
+size_t id;
+{
+    static char buf[30];
+    /* Elf name fragments courtesy of ToME */
+    static const char *elf_syllable1[] = {
+	"Al", "An", "Bal", "Bel", "Cal", "Cel", "El", "Elr", "Elv", "Eow",
+	"Ear", "F", "Fal", "Fel", "Fin", "G", "Gal", "Gel", "Gl", "Is", "Lan",
+	"Leg", "Lom", "N", "Nal","Nel", "S", "Sal", "Sel", "T", "Tal", "Tel",
+	"Thr", "Tin",
+    };
+    static const char *elf_syllable2[] = {
+	"a", "adrie", "ara", "e", "ebri", "ele", "ere", "i", "io", "ithra",
+	"ilma", "il-Ga", "ili", "o", "orfi", "u", "y",
+    };
+    static const char *elf_syllable3[] = {
+	"l", "las", "lad", "ldor", "ldur", "linde", "lith", "mir", "n", "nd",
+	"ndel", "ndil", "ndir", "nduil", "ng", "mbor", "r", "rith", "ril",
+	"riand", "rion", "s", "thien", "viel", "wen", "wyn",
+    };
+    snprintf(buf, 30, "%s%s%s",
+	     elf_syllable1[id % SIZE(elf_syllable1)],
+	     elf_syllable2[id % SIZE(elf_syllable2)],
+	     elf_syllable3[id % SIZE(elf_syllable3)]);
+    return buf;
+}
+
+
 STATIC_OVL void
 mk_mplayer_armor(mon, typ)
@@ -98,5 +128,5 @@
 	if (typ == STRANGE_OBJECT) return;
 	obj = mksobj(typ, FALSE, FALSE);
-	if (!rn2(3)) obj->oerodeproof = 1;
+	if (!rn2(3)) set_erodeproof(obj);
 	if (!rn2(3)) curse(obj);
 	if (!rn2(3)) bless(obj);
@@ -228,5 +258,5 @@
 		otmp = mksobj(weapon, TRUE, FALSE);
 		otmp->spe = (special ? rn1(5,4) : rn2(4));
-		if (!rn2(3)) otmp->oerodeproof = 1;
+		if (!rn2(3)) { set_erodeproof(otmp); }
 		else if (!rn2(2)) otmp->greased = 1;
 		if (special && rn2(2))
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/src/mthrowu.c nethack/src/mthrowu.c
--- nh_orig/src/mthrowu.c	2003-12-07 18:39:13.000000000 -0500
+++ nethack/src/mthrowu.c	2009-11-22 07:40:39.728356377 -0500
@@ -41,4 +41,5 @@
 {
 	const char *onm, *knm;
+	int realac;
 	boolean is_acid;
 	int kprefix = KILLED_BY_AN;
@@ -62,5 +63,6 @@
 	is_acid = (obj && obj->otyp == ACID_VENOM);
 
-	if(u.uac + tlev <= rnd(20)) {
+	realac = AC_VALUE(u.uac);
+	if(realac + tlev <= rnd(20)) {
 		if(Blind || !flags.verbose) pline("It misses.");
 		else You("are almost hit by %s.", onm);
@@ -76,7 +78,8 @@
 			exercise(A_CON, FALSE);
 		}
-		if (is_acid && Acid_resistance)
+		if (is_acid && Acid_resistance) {
 			pline("It doesn't seem to hurt you.");
-		else {
+			monstseesu(M_SEEN_ACID);
+		} else {
 			if (is_acid) pline("It burns!");
 			if (Half_physical_damage) dam = (dam+1) / 2;
@@ -148,4 +151,5 @@
 {
 	int damage, tmp;
+	int damtype = AD_PHYS;
 	boolean vis, ismimic;
 	int objgone = 1;
@@ -184,4 +188,5 @@
 				   mon_nam(mtmp));
 		} else {
+			damtype = AD_DRST;
 		    if (rn2(30)) {
 			damage += rnd(6);
@@ -204,9 +209,10 @@
 		    damage = 0;
 		} else {
+			damtype = AD_ACID;
 		    if (vis) pline_The("acid burns %s!", mon_nam(mtmp));
 		    else if (verbose) pline("It is burned!");
 		}
 	    }
-	    mtmp->mhp -= damage;
+		 damage_mon(mtmp,damage,AD_ACID);
 	    if (mtmp->mhp < 1) {
 		if (vis || verbose)
@@ -325,5 +331,5 @@
 			break;
 		} else if (bhitpos.x == u.ux && bhitpos.y == u.uy) {
-		    if (multi) nomul(0);
+		    if (multi) nomul(0, 0);
 
 		    if (singleobj->oclass == GEM_CLASS &&
@@ -368,6 +374,5 @@
 			    hitv = 3 - distmin(u.ux,u.uy, mon->mx,mon->my);
 			    if (hitv < -4) hitv = -4;
-			    if (is_elf(mon->data) &&
-				objects[singleobj->otyp].oc_skill == P_BOW) {
+			    if (is_elf(mon->data) && objects[singleobj->otyp].oc_skill == P_BOW) {
 				hitv++;
 				if (MON_WEP(mon) &&
@@ -378,4 +383,6 @@
 			    if (bigmonst(youmonst.data)) hitv++;
 			    hitv += 8 + singleobj->spe;
+				 /* eagle-eyed monsters get a BIG bonus here */
+				 if (is_accurate(mon->data)) { hitv += mon->m_lev; }
 			    if (dam < 1) dam = 1;
 			    hitu = thitu(hitv, dam, singleobj, (char *)0);
@@ -490,4 +497,5 @@
 	schar skill;
 	int multishot;
+	int maxrange;
 	const char *onm;
 
@@ -528,6 +536,32 @@
 	}
 
+	skill = objects[otmp->otyp].oc_skill;
+	mwep = MON_WEP(mtmp);		/* wielded weapon */
 	x = mtmp->mx;
 	y = mtmp->my;
+
+	/* critters get to shoot things further, too */
+	maxrange = BOLT_LIM/2;
+	if (ammo_and_launcher(otmp,mwep)) {
+		switch (mwep->otyp) {
+			case ELVEN_BOW:
+			case YUMI:
+				maxrange += 6;
+				break;
+			case ORCISH_BOW:
+			case SLING:
+				maxrange += 2;
+				break;
+			case BOW:
+				maxrange += 4;
+				break;
+			case CROSSBOW:
+				maxrange *= 2;
+				break;
+			default:
+				break;
+		}
+	}
+
 	/* If you are coming toward the monster, the monster
 	 * should try to soften you up with missiles.  If you are
@@ -535,11 +569,11 @@
 	 * chase, but if you are getting too far away, throw.
 	 */
-	if (!lined_up(mtmp) ||
-		(URETREATING(x,y) &&
+	if (!lined_up(mtmp) || (URETREATING(x,y) && 
 			rn2(BOLT_LIM - distmin(x,y,mtmp->mux,mtmp->muy))))
 	    return;
 
-	skill = objects[otmp->otyp].oc_skill;
-	mwep = MON_WEP(mtmp);		/* wielded weapon */
+	/* oh, and don't plink foolishly if we can't reach the hero */
+	if (distmin(x,y,mtmp->mux,mtmp->muy) > maxrange)
+		return;
 
 	/* Multishot calculations */
@@ -603,11 +637,10 @@
 	m_shot.n = multishot;
 	for (m_shot.i = 1; m_shot.i <= m_shot.n; m_shot.i++)
-	    m_throw(mtmp, mtmp->mx, mtmp->my, sgn(tbx), sgn(tby),
-		    distmin(mtmp->mx, mtmp->my, mtmp->mux, mtmp->muy), otmp);
+	    m_throw(mtmp, mtmp->mx, mtmp->my, sgn(tbx), sgn(tby), maxrange, otmp);
 	m_shot.n = m_shot.i = 0;
 	m_shot.o = STRANGE_OBJECT;
 	m_shot.s = FALSE;
 
-	nomul(0);
+	nomul(0, 0);
 }
 
@@ -636,6 +669,4 @@
 			break;
 		    default:
-			impossible("bad attack type in spitmu");
-				/* fall through */
 		    case AD_ACID:
 			otmp = mksobj(ACID_VENOM, TRUE, FALSE);
@@ -647,5 +678,5 @@
 		    m_throw(mtmp, mtmp->mx, mtmp->my, sgn(tbx), sgn(tby),
 			distmin(mtmp->mx,mtmp->my,mtmp->mux,mtmp->muy), otmp);
-		    nomul(0);
+		    nomul(0, 0);
 		    return 0;
 		}
@@ -664,7 +695,7 @@
 	/* if new breath types are added, change AD_ACID to max type */
 	int typ = (mattk->adtyp == AD_RBRE) ? rnd(AD_ACID) : mattk->adtyp ;
+	boolean player_resists = FALSE;
 
 	if(lined_up(mtmp)) {
-
 	    if(mtmp->mcan) {
 		if(flags.soundok) {
@@ -676,8 +707,15 @@
 		return(0);
 	    }
-	    if(!mtmp->mspec_used && rn2(3)) {
 
-		if((typ >= AD_MAGM) && (typ <= AD_ACID)) {
+		/* if we've seen the actual resistance, don't bother, or
+		 * if we're close by and they reflect, just jump the player */
+		player_resists = (m_seenres(mtmp,1 << (typ-1)) > 0);
+		if (player_resists || 
+				(m_seenres(mtmp,M_SEEN_REFL) && monnear(mtmp,mtmp->mux,mtmp->muy))) { 
+			return 1; 
+		}
 
+		if(!mtmp->mspec_used && rn2(3)) {
+			if((typ >= AD_MAGM) && (typ <= AD_ACID)) {
 		    if(canseemon(mtmp))
 			pline("%s breathes %s!", Monnam(mtmp),
@@ -685,5 +723,5 @@
 		    buzz((int) (-20 - (typ-1)), (int)mattk->damn,
 			 mtmp->mx, mtmp->my, sgn(tbx), sgn(tby));
-		    nomul(0);
+				nomul(0, 0);
 		    /* breath runs out sometimes. Also, give monster some
 		     * cunning; don't breath if the player fell asleep.
@@ -691,5 +729,5 @@
 		    if(!rn2(3))
 			mtmp->mspec_used = 10+rn2(20);
-		    if(typ == AD_SLEE && !Sleep_resistance)
+				if(typ == AD_SLEE && how_resistant(SLEEP_RES) < 100)
 			mtmp->mspec_used += rnd(20);
 		} else impossible("Breath weapon %d used", typ-1);
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/src/muse.c nethack/src/muse.c
--- nh_orig/src/muse.c	2003-12-07 18:39:13.000000000 -0500
+++ nethack/src/muse.c	2009-11-22 07:19:36.634397830 -0500
@@ -137,5 +137,5 @@
 		return 1;
 	    }
-	    else mon->mhp -= dam;
+		 else damage_mon(mon,dam,AD_RBRE);
 	    m.has_defense = m.has_offense = m.has_misc = 0;
 	    /* Only one needed to be set to 0 but the others are harmless */
@@ -669,5 +669,5 @@
 				surface(mtmp->mx, mtmp->my));
 		    pline("%s %s through...", Monnam(mtmp),
-			  is_flyer(mtmp->data) ? "dives" : "falls");
+			  (is_flyer(mtmp->data) || is_flying(mtmp)) ? "dives" : "falls");
 		} else if (flags.soundok)
 			You_hear("%s crash through the %s.", something,
@@ -772,5 +772,12 @@
 		}
 		m_flee(mtmp);
-		if (Inhell && mon_has_amulet(mtmp) && !rn2(4) &&
+		/* 
+		 * This has been removed from the player, but not so for the monsters...
+		 * ...and a little more common, too.
+		 *
+		 * Why else do you think none of them have walked out with the Amulet?
+		 * You're the "chosen one", right?  ;)
+		 */
+		if (Inhell && mon_has_amulet(mtmp) && !rn2(2) &&
 			(dunlev(&u.uz) < dunlevs_in_dungeon(&u.uz) - 3)) {
 		    if (vismon) pline(
@@ -968,5 +975,9 @@
 	register struct obj *obj;
 	boolean ranged_stuff = lined_up(mtmp);
-	boolean reflection_skip = (Reflecting && rn2(2));
+	/* In general if the monster has seen that you're not taking much damage (reflection or MR),
+	 * then it's going to prefer just running up and hitting you if it can.  But we need to take
+	 * the range into account, since half damage is better than no damage... */
+	boolean reflection_skip = m_seenres(mtmp,M_SEEN_REFL) && monnear(mtmp,mtmp->mux,mtmp->muy);
+	boolean mr_skip = m_seenres(mtmp,M_SEEN_MAGR) && monnear(mtmp,mtmp->mux,mtmp->muy);
 	struct obj *helmet = which_armor(mtmp, W_ARMH);
 
@@ -990,40 +1001,42 @@
 		/* nomore(MUSE_WAN_DEATH); */
 		if (!reflection_skip) {
-		    if(obj->otyp == WAN_DEATH && obj->spe > 0) {
+		    if(obj->otyp == WAN_DEATH && obj->spe > 0 && !m_seenres(mtmp,M_SEEN_MAGR) &&
+					/* don't zap death if we know it'll bounce back... unless we resist it */
+					 (!m_seenres(mtmp,M_SEEN_REFL) || nonliving(mtmp->data) || mtmp->data->msound == MS_LEADER)) {
 			m.offensive = obj;
 			m.has_offense = MUSE_WAN_DEATH;
 		    }
 		    nomore(MUSE_WAN_SLEEP);
-		    if(obj->otyp == WAN_SLEEP && obj->spe > 0 && multi >= 0) {
+		    if(obj->otyp == WAN_SLEEP && obj->spe > 0 && multi >= 0 && !m_seenres(mtmp,M_SEEN_SLEEP)) {
 			m.offensive = obj;
 			m.has_offense = MUSE_WAN_SLEEP;
 		    }
 		    nomore(MUSE_WAN_FIRE);
-		    if(obj->otyp == WAN_FIRE && obj->spe > 0) {
+		    if(obj->otyp == WAN_FIRE && obj->spe > 0 && !m_seenres(mtmp,M_SEEN_FIRE)) {
 			m.offensive = obj;
 			m.has_offense = MUSE_WAN_FIRE;
 		    }
 		    nomore(MUSE_FIRE_HORN);
-		    if(obj->otyp == FIRE_HORN && obj->spe > 0) {
+		    if(obj->otyp == FIRE_HORN && obj->spe > 0 && !m_seenres(mtmp,M_SEEN_FIRE)) {
 			m.offensive = obj;
 			m.has_offense = MUSE_FIRE_HORN;
 		    }
 		    nomore(MUSE_WAN_COLD);
-		    if(obj->otyp == WAN_COLD && obj->spe > 0) {
+		    if(obj->otyp == WAN_COLD && obj->spe > 0 && !m_seenres(mtmp,M_SEEN_COLD)) {
 			m.offensive = obj;
 			m.has_offense = MUSE_WAN_COLD;
 		    }
 		    nomore(MUSE_FROST_HORN);
-		    if(obj->otyp == FROST_HORN && obj->spe > 0) {
+		    if(obj->otyp == FROST_HORN && obj->spe > 0 && !m_seenres(mtmp,M_SEEN_COLD)) {
 			m.offensive = obj;
 			m.has_offense = MUSE_FROST_HORN;
 		    }
 		    nomore(MUSE_WAN_LIGHTNING);
-		    if(obj->otyp == WAN_LIGHTNING && obj->spe > 0) {
+		    if(obj->otyp == WAN_LIGHTNING && obj->spe > 0 && !m_seenres(mtmp,M_SEEN_ELEC)) {
 			m.offensive = obj;
 			m.has_offense = MUSE_WAN_LIGHTNING;
 		    }
 		    nomore(MUSE_WAN_MAGIC_MISSILE);
-		    if(obj->otyp == WAN_MAGIC_MISSILE && obj->spe > 0) {
+		    if(obj->otyp == WAN_MAGIC_MISSILE && obj->spe > 0 && !m_seenres(mtmp,M_SEEN_MAGR)) {
 			m.offensive = obj;
 			m.has_offense = MUSE_WAN_MAGIC_MISSILE;
@@ -1031,5 +1044,5 @@
 		}
 		nomore(MUSE_WAN_STRIKING);
-		if(obj->otyp == WAN_STRIKING && obj->spe > 0) {
+		if(obj->otyp == WAN_STRIKING && obj->spe > 0 && !m_seenres(mtmp,M_SEEN_MAGR)) {
 			m.offensive = obj;
 			m.has_offense = MUSE_WAN_STRIKING;
@@ -1051,10 +1064,10 @@
 		}
 		nomore(MUSE_POT_SLEEPING);
-		if(obj->otyp == POT_SLEEPING) {
+		if(obj->otyp == POT_SLEEPING && !m_seenres(mtmp,M_SEEN_SLEEP)) {
 			m.offensive = obj;
 			m.has_offense = MUSE_POT_SLEEPING;
 		}
 		nomore(MUSE_POT_ACID);
-		if(obj->otyp == POT_ACID) {
+		if(obj->otyp == POT_ACID && !m_seenres(mtmp,M_SEEN_ACID)) {
 			m.offensive = obj;
 			m.has_offense = MUSE_POT_ACID;
@@ -1114,4 +1127,5 @@
 			if (Antimagic) {
 			    shieldeff(u.ux, u.uy);
+				 monstseesu(M_SEEN_MAGR);
 			    pline("Boing!");
 			} else if (rnd(20) < 10 + u.uac) {
@@ -1122,5 +1136,5 @@
 			} else pline_The("wand misses you.");
 			stop_occupation();
-			nomul(0);
+			nomul(0, 0);
 		} else if (resists_magm(mtmp)) {
 			shieldeff(mtmp->mx, mtmp->my);
@@ -1267,7 +1281,8 @@
 struct monst *mtmp;
 {
-	int i;
+	int i,maxdmg;
 	struct obj *otmp = m.offensive;
 	boolean oseen;
+	struct attack* mattk;
 
 	/* offensive potions are not drunk, they're thrown */
@@ -1276,4 +1291,27 @@
 	oseen = otmp && canseemon(mtmp);
 
+	/* Not all monsters need to be hucking around potions, wands, etc. if they have
+	 * a chance to actually haul off and hit you -- things like the Olog-hai, Vlad,
+	 * and shopkeepers come to mind.  If the monster is wielding an artifact, OR
+	 * if one of the monster's attacks is noticeably meaner... and the monster is
+	 * close enough to actually _use_ the attack, then don't give too much priority
+	 * to the ranged/offensive item stuff. */
+
+	for (i = 0; i < NATTK; i++) {
+		mattk = &mtmp->data->mattk[i];
+		maxdmg += mattk->damn * mattk->damd;	/* total up the possible damage for just swinging */
+	}
+
+	/* if damage is sufficient _or_ we have a good weapon, use that if we're close enough;
+	 * but if we have the incapacitator wands use those anyway.  note that even though the player
+	 * may be sleep resistant the check for the monster knowing this is done in find_offensive,
+	 * so if we get here then the monster can correctly pick sleep wands */
+	if ((maxdmg > 36 || (MON_WEP(mtmp) && MON_WEP(mtmp)->oartifact)) && 
+			(monnear(mtmp,mtmp->mux,mtmp->muy) && 
+			 m.has_offense != MUSE_WAN_DEATH &&
+			 m.has_offense != MUSE_WAN_SLEEP)) {
+		return 0;
+	}
+
 	switch(m.has_offense) {
 	case MUSE_WAN_DEATH:
@@ -1389,5 +1427,5 @@
 				    }
 				}
-	    	    	    	mtmp2->mhp -= mdmg;
+							damage_mon(mtmp2,mdmg,AD_PHYS);
 	    	    	    	if (mtmp2->mhp <= 0) {
 				    pline("%s is killed.", Monnam(mtmp2));
@@ -1811,4 +1849,5 @@
 
 		(void) newcham(mtmp, (struct permonst *)0, FALSE, FALSE);
+		if (!rn2(10)) { deltrap(t_at(trapx,trapy)); }
 		return 2;
 	case MUSE_BULLWHIP:
@@ -2074,4 +2113,11 @@
 	    	makeknown(SHIELD_OF_REFLECTION);
 	    }
+		 monstseesu(M_SEEN_REFL);
+	    return TRUE;
+	} else if (HReflecting) {
+		if (fmt && str) {
+			pline(fmt,str,"magical shield");
+		}
+		monstseesu(M_SEEN_REFL);
 	    return TRUE;
 	} else if (EReflecting & W_WEP) {
@@ -2079,4 +2125,5 @@
 	    if (fmt && str)
 	    	pline(fmt, str, "weapon");
+		 monstseesu(M_SEEN_REFL);
 	    return TRUE;
 	} else if (EReflecting & W_AMUL) {
@@ -2085,12 +2132,22 @@
 	    	makeknown(AMULET_OF_REFLECTION);
 	    }
+		 monstseesu(M_SEEN_REFL);
 	    return TRUE;
 	} else if (EReflecting & W_ARM) {
 	    if (fmt && str)
 	    	pline(fmt, str, "armor");
+		 monstseesu(M_SEEN_REFL);
+	    return TRUE;
+	} else if (EReflecting & W_ART) {
+		/* Due to the Magic Mirror, which shows as W_ART */
+		if (fmt && str) {
+			pline(fmt, str, "mirror");
+		}
+		monstseesu(M_SEEN_REFL);
 	    return TRUE;
 	} else if (youmonst.data == &mons[PM_SILVER_DRAGON]) {
 	    if (fmt && str)
 	    	pline(fmt, str, "scales");
+		 monstseesu(M_SEEN_REFL);
 	    return TRUE;
 	}
@@ -2148,5 +2205,5 @@
     if (((obj->otyp == POT_ACID) || acidic(&mons[obj->corpsenm])) &&
 		    !resists_acid(mon)) {
-	mon->mhp -= rnd(15);
+	damage_mon(mon,rnd(15),AD_ACID);
 	pline("%s has a very bad case of stomach acid.",
 	    Monnam(mon));
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/src/music.c nethack/src/music.c
--- nh_orig/src/music.c	2003-12-07 18:39:13.000000000 -0500
+++ nethack/src/music.c	2010-04-23 14:27:35.791715546 -0400
@@ -268,8 +268,4 @@
 				pline_The("headstone topples into a chasm.");
 			goto do_pit;
-		  case THRONE :
-			if (cansee(x,y))
-				pline_The("throne falls into a chasm.");
-			/* Falls into next case */
 		  case ROOM :
 		  case CORR : /* Try to make a pit */
@@ -282,4 +278,10 @@
 		    mtmp = m_at(x,y);
 
+		    if (cansee(x,y)) {
+			if (sobj_at(FUR_THRONE, x, y))
+			    pline_The("throne falls into a chasm.");
+		    }
+			/* Falls into next case */
+
 		    if ((otmp = sobj_at(BOULDER, x, y)) != 0) {
 			if (cansee(x, y))
@@ -297,5 +299,6 @@
 
 		    if (mtmp) {
-			if(!is_flyer(mtmp->data) && !is_clinger(mtmp->data)) {
+			if(!is_flyer(mtmp->data) && !is_clinger(mtmp->data) &&
+					!is_flying(mtmp)) {
 			    mtmp->mtrapped = 1;
 			    if(cansee(x,y))
@@ -305,5 +308,5 @@
 			    mselftouch(mtmp, "Falling, ", TRUE);
 			    if (mtmp->mhp > 0)
-				if ((mtmp->mhp -= rnd(6)) <= 0) {
+				if (damage_mon(mtmp,rnd(6),AD_PHYS)) {
 				    if(!cansee(x,y))
 					pline("It is destroyed!");
@@ -477,5 +480,5 @@
 struct obj *instr;
 {
-    char buf[BUFSZ], c = 'y';
+    char buf[BUFSZ] = "", c = 'y';
     char *s;
     int x,y;
@@ -551,5 +554,5 @@
 			    else
 				open_drawbridge(x,y);
-			    return 0;
+			    return 1;
 			}
 	    } else if(flags.soundok) {
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/src/objects.c nethack/src/objects.c
--- nh_orig/src/objects.c	2003-12-07 18:39:13.000000000 -0500
+++ nethack/src/objects.c	2009-11-25 11:48:58.329273002 -0500
@@ -89,5 +89,5 @@
 		0, 20, 1, 2, 5, 6, 0, IRON, -P_BOW, CLR_BLACK),
 PROJECTILE("silver arrow", (char *)0,
-		1, 12, 1, 5, 6, 6, 0, SILVER, -P_BOW, HI_SILVER),
+		1, 15, 1, 5, 6, 6, 0, SILVER, -P_BOW, HI_SILVER),
 PROJECTILE("ya", "bamboo arrow",
 		0, 15, 1, 4, 7, 7, 1, METAL, -P_BOW, HI_METAL),
@@ -110,12 +110,12 @@
 	0, 1, 0, 13, 30,  3,  5,  8, 0, P,   P_SPEAR, IRON, CLR_BLACK),
 WEAPON("dwarvish spear", "stout spear",
-	0, 1, 0, 12, 35,  3,  8,  8, 0, P,   P_SPEAR, IRON, HI_METAL),
+	0, 1, 0, 12, 30,  3,  8,  8, 0, P,   P_SPEAR, IRON, HI_METAL),
 WEAPON("silver spear", (char *)0,
-	1, 1, 0,  2, 36, 40,  6,  8, 0, P,   P_SPEAR, SILVER, HI_SILVER),
+	1, 1, 0,  6, 30, 40,  6,  8, 0, P,   P_SPEAR, SILVER, HI_SILVER),
 WEAPON("javelin", "throwing spear",
-	0, 1, 0, 10, 20,  3,  6,  6, 0, P,   P_JAVELIN, IRON, HI_METAL),
+	0, 1, 0, 15, 20,  3,  6,  6, 0, P,   P_JAVELIN, IRON, HI_METAL),
 
 WEAPON("trident", (char *)0,
-	1, 0, 0,  8, 25,  5,  6,  4, 0, P,   P_TRIDENT, IRON, HI_METAL),
+	1, 0, 0, 12, 25,  5,  6,  4, 0, P,   P_TRIDENT, IRON, HI_METAL),
 						/* +1 small, +2d4 large */
 
@@ -128,5 +128,5 @@
 	0, 1, 0, 12, 10,  4,  3,  3, 2, P,   P_DAGGER, IRON, CLR_BLACK),
 WEAPON("silver dagger", (char *)0,
-	1, 1, 0,  3, 12, 40,  4,  3, 2, P,   P_DAGGER, SILVER, HI_SILVER),
+	1, 1, 0,  4, 10, 40,  4,  3, 2, P,   P_DAGGER, SILVER, HI_SILVER),
 WEAPON("athame", (char *)0,
 	1, 1, 0,  0, 10,  4,  4,  3, 2, S,   P_DAGGER, IRON, HI_METAL),
@@ -136,5 +136,5 @@
 	1, 1, 0, 20,  5,  4,  3,  2, 0, P|S, P_KNIFE, IRON, HI_METAL),
 WEAPON("stiletto", (char *)0,
-	1, 1, 0,  5,  5,  4,  3,  2, 0, P|S, P_KNIFE, IRON, HI_METAL),
+	1, 1, 0,  6,  5,  4,  3,  2, 0, P|S, P_KNIFE, IRON, HI_METAL),
 WEAPON("worm tooth", (char *)0,
 	1, 0, 0,  0, 20,  2,  2,  2, 0, 0,   P_KNIFE, 0, CLR_WHITE),
@@ -145,16 +145,18 @@
 	1, 0, 0, 40, 60,  8,  6,  4, 0, S,   P_AXE, IRON, HI_METAL),
 WEAPON("battle-axe", "double-headed axe",
-	0, 0, 1, 10,120, 40,  8,  6, 0, S,   P_AXE, IRON, HI_METAL),
+	0, 0, 1, 12,120, 40,  8,  6, 0, S,   P_AXE, IRON, HI_METAL),
 						/* "double-bitted" ? */
 
 /* swords */
 WEAPON("short sword", (char *)0,
-	1, 0, 0,  8, 30, 10,  6,  8, 0, P,   P_SHORT_SWORD, IRON, HI_METAL),
+	1, 0, 0, 10, 30, 10,  6,  8, 0, P,   P_SHORT_SWORD, IRON, HI_METAL),
 WEAPON("elven short sword", "runed short sword",
-	0, 0, 0,  2, 30, 10,  8,  8, 0, P,   P_SHORT_SWORD, WOOD, HI_WOOD),
+	0, 0, 0,  6, 30, 10,  8,  8, 0, P,   P_SHORT_SWORD, WOOD, HI_WOOD),
 WEAPON("orcish short sword", "crude short sword",
-	0, 0, 0,  3, 30, 10,  5,  8, 0, P,   P_SHORT_SWORD, IRON, CLR_BLACK),
+	0, 0, 0,  6, 30, 10,  5,  8, 0, P,   P_SHORT_SWORD, IRON, CLR_BLACK),
 WEAPON("dwarvish short sword", "broad short sword",
-	0, 0, 0,  2, 30, 10,  7,  8, 0, P,   P_SHORT_SWORD, IRON, HI_METAL),
+	0, 0, 0,  6, 30, 10,  7,  8, 0, P,   P_SHORT_SWORD, IRON, HI_METAL),
+WEAPON("silver short sword", (char *)0,
+	0, 0, 0,  6, 30, 10,  6,  8, 0, P,   P_SHORT_SWORD, SILVER, HI_SILVER),
 WEAPON("scimitar", "curved sword",
 	0, 0, 0, 15, 40, 15,  8,  8, 0, S,   P_SCIMITAR, IRON, HI_METAL),
@@ -162,16 +164,19 @@
 	1, 0, 0,  6, 40, 75,  8,  8, 0, S,   P_SABER, SILVER, HI_SILVER),
 WEAPON("broadsword", (char *)0,
-	1, 0, 0,  8, 70, 10,  4,  6, 0, S,   P_BROAD_SWORD, IRON, HI_METAL),
+	1, 0, 0, 10, 70, 10,  4,  6, 0, S,   P_BROAD_SWORD, IRON, HI_METAL),
 						/* +d4 small, +1 large */
 WEAPON("elven broadsword", "runed broadsword",
-	0, 0, 0,  4, 70, 10,  6,  6, 0, S,   P_BROAD_SWORD, WOOD, HI_WOOD),
+	0, 0, 0,  8, 70, 10,  6,  6, 0, S,   P_BROAD_SWORD, WOOD, HI_WOOD),
 						/* +d4 small, +1 large */
 WEAPON("long sword", (char *)0,
-	1, 0, 0, 50, 40, 15,  8, 12, 0, S,   P_LONG_SWORD, IRON, HI_METAL),
+	1, 0, 0, 40, 40, 15,  8, 12, 0, S,   P_LONG_SWORD, IRON, HI_METAL),
+/* Base artifact for Sunsword */
+WEAPON("silver long sword", (char *)0,
+	1, 0, 0, 0, 40, 150,  8, 12, 0, S,   P_LONG_SWORD, SILVER, HI_SILVER),
 WEAPON("two-handed sword", (char *)0,
 	1, 0, 1, 22,150, 50, 12,  6, 0, S,   P_TWO_HANDED_SWORD, IRON, HI_METAL),
 						/* +2d6 large */
 WEAPON("katana", "samurai sword",
-	0, 0, 0,  4, 40, 80, 10, 12, 1, S,   P_LONG_SWORD, IRON, HI_METAL),
+	0, 0, 0,  8, 40, 80, 10, 12, 1, S,   P_LONG_SWORD, IRON, HI_METAL),
 /* special swords set up for artifacts */
 WEAPON("tsurugi", "long samurai sword",
@@ -186,16 +191,16 @@
 /* spear-type */
 WEAPON("partisan", "vulgar polearm",
-	0, 0, 1,  5, 80, 10,  6,  6, 0, P,   P_POLEARMS, IRON, HI_METAL),
+	0, 0, 1,  0, 80, 10,  6,  6, 0, P,   P_POLEARMS, IRON, HI_METAL),
 						/* +1 large */
 WEAPON("ranseur", "hilted polearm",
-	0, 0, 1,  5, 50,  6,  4,  4, 0, P,   P_POLEARMS, IRON, HI_METAL),
+	0, 0, 1,  0, 50,  6,  4,  4, 0, P,   P_POLEARMS, IRON, HI_METAL),
 						/* +d4 both */
 WEAPON("spetum", "forked polearm",
-	0, 0, 1,  5, 50,  5,  6,  6, 0, P,   P_POLEARMS, IRON, HI_METAL),
+	0, 0, 1,  0, 50,  5,  6,  6, 0, P,   P_POLEARMS, IRON, HI_METAL),
 						/* +1 small, +d6 large */
 WEAPON("glaive", "single-edged polearm",
-	0, 0, 1,  8, 75,  6,  6, 10, 0, S,   P_POLEARMS, IRON, HI_METAL),
+	0, 0, 1,  0, 75,  6,  6, 10, 0, S,   P_POLEARMS, IRON, HI_METAL),
 WEAPON("lance", (char *)0,
-	1, 0, 0,  4,180, 10,  6,  8, 0, P,   P_LANCE, IRON, HI_METAL),
+	1, 0, 0,  8,180, 10,  6,  8, 0, P,   P_LANCE, IRON, HI_METAL),
 /* axe-type */
 WEAPON("halberd", "angled poleaxe",
@@ -203,8 +208,8 @@
 						/* +1d6 large */
 WEAPON("bardiche", "long poleaxe",
-	0, 0, 1,  4,120,  7,  4,  4, 0, S,   P_POLEARMS, IRON, HI_METAL),
+	0, 0, 1,  0,120,  7,  4,  4, 0, S,   P_POLEARMS, IRON, HI_METAL),
 						/* +1d4 small, +2d4 large */
 WEAPON("voulge", "pole cleaver",
-	0, 0, 1,  4,125,  5,  4,  4, 0, S,   P_POLEARMS, IRON, HI_METAL),
+	0, 0, 1,  0,125,  5,  4,  4, 0, S,   P_POLEARMS, IRON, HI_METAL),
 						/* +d4 both */
 WEAPON("dwarvish mattock", "broad pick",
@@ -213,24 +218,28 @@
 /* curved/hooked */
 WEAPON("fauchard", "pole sickle",
-	0, 0, 1,  6, 60,  5,  6,  8, 0, P|S, P_POLEARMS, IRON, HI_METAL),
+	0, 0, 1,  0, 60,  5,  6,  8, 0, P|S, P_POLEARMS, IRON, HI_METAL),
 WEAPON("guisarme", "pruning hook",
-	0, 0, 1,  6, 80,  5,  4,  8, 0, S,   P_POLEARMS, IRON, HI_METAL),
+	0, 0, 1,  0, 80,  5,  4,  8, 0, S,   P_POLEARMS, IRON, HI_METAL),
 						/* +1d4 small */
 WEAPON("bill-guisarme", "hooked polearm",
-	0, 0, 1,  4,120,  7,  4, 10, 0, P|S, P_POLEARMS, IRON, HI_METAL),
+	0, 0, 1,  0,120,  7,  4, 10, 0, P|S, P_POLEARMS, IRON, HI_METAL),
 						/* +1d4 small */
 /* other */
 WEAPON("lucern hammer", "pronged polearm",
-	0, 0, 1,  5,150,  7,  4,  6, 0, B|P, P_POLEARMS, IRON, HI_METAL),
+	0, 0, 1,  0,150,  7,  4,  6, 0, B|P, P_POLEARMS, IRON, HI_METAL),
 						/* +1d4 small */
 WEAPON("bec de corbin", "beaked polearm",
-	0, 0, 1,  4,100,  8,  8,  6, 0, B|P, P_POLEARMS, IRON, HI_METAL),
+	0, 0, 1,  0,100,  8,  8,  6, 0, B|P, P_POLEARMS, IRON, HI_METAL),
 
 /* bludgeons */
 WEAPON("mace", (char *)0,
 	1, 0, 0, 40, 30,  5,  6,  6, 0, B,   P_MACE, IRON, HI_METAL),
+/* can't be generated ranodomly; base object for Demonbane */
+WEAPON("silver mace", (char *)0,
+	1, 0, 0, 0, 30,  100,  6,  6, 0, B,   P_MACE, SILVER, HI_SILVER),
 						/* +1 small */
+
 WEAPON("morning star", (char *)0,
-	1, 0, 0, 12,120, 10,  4,  6, 0, B,   P_MORNING_STAR, IRON, HI_METAL),
+	1, 0, 0, 15,120, 10,  4,  6, 0, B,   P_MORNING_STAR, IRON, HI_METAL),
 						/* +d4 small, +1 large */
 WEAPON("war hammer", (char *)0,
@@ -238,27 +247,31 @@
 						/* +1 small */
 WEAPON("club", (char *)0,
-	1, 0, 0, 12, 30,  3,  6,  3, 0, B,   P_CLUB, WOOD, HI_WOOD),
+	1, 0, 0, 15, 30,  3,  6,  3, 0, B,   P_CLUB, WOOD, HI_WOOD),
 #ifdef KOPS
 WEAPON("rubber hose", (char *)0,
 	1, 0, 0,  0, 20,  3,  4,  3, 0, B,   P_WHIP, PLASTIC, CLR_BROWN),
 #endif
-WEAPON("quarterstaff", "staff",
-	0, 0, 1, 11, 40,  5,  6,  6, 0, B,   P_QUARTERSTAFF, WOOD, HI_WOOD),
+WEAPON("quarterstaff", "staff", 0, 0, 1, 15, 40,  5,  6,  6, 0, B,   P_QUARTERSTAFF, WOOD, HI_WOOD),
+/* spell school staves */
+WEAPON("staff of divination", "staff", 0, 0, 1, 5, 40, 400,  6,  6, 0, B, P_QUARTERSTAFF, WOOD, HI_WOOD),
+WEAPON("staff of healing",    "staff", 0, 0, 1, 5, 40, 400,  6,  6, 0, B, P_QUARTERSTAFF, WOOD, HI_WOOD),
+WEAPON("staff of holiness",   "staff", 0, 0, 1, 5, 40, 400,  6,  6, 0, B, P_QUARTERSTAFF, WOOD, HI_WOOD),
+WEAPON("staff of matter",     "staff", 0, 0, 1, 5, 40, 400,  6,  6, 0, B, P_QUARTERSTAFF, WOOD, HI_WOOD),
+WEAPON("staff of escape",     "staff", 0, 0, 1, 5, 40, 400,  6,  6, 0, B, P_QUARTERSTAFF, WOOD, HI_WOOD),
+WEAPON("staff of battle",     "staff", 0, 0, 1, 5, 40, 400,  6,  6, 0, B, P_QUARTERSTAFF, WOOD, HI_WOOD),
 /* two-piece */
-WEAPON("aklys", "thonged club",
-	0, 0, 0,  8, 15,  4,  6,  3, 0, B,   P_CLUB, IRON, HI_METAL),
-WEAPON("flail", (char *)0,
-	1, 0, 0, 40, 15,  4,  6,  4, 0, B,   P_FLAIL, IRON, HI_METAL),
+WEAPON("aklys", "thonged club", 0, 0, 0,  3, 15,  4,  6,  3, 0, B,   P_CLUB, IRON, HI_METAL),
+WEAPON("flail", (char *)0, 1, 0, 0, 20, 15,  4,  6,  4, 0, B,   P_FLAIL, IRON, HI_METAL),
 						/* +1 small, +1d4 large */
 /* misc */
 WEAPON("bullwhip", (char *)0,
-	1, 0, 0,  2, 20,  4,  2,  1, 0, 0,   P_WHIP, LEATHER, CLR_BROWN),
+	1, 0, 0,  5, 20,  4,  2,  1, 0, 0,   P_WHIP, LEATHER, CLR_BROWN),
 
 /* bows */
-BOW("bow", (char *)0,		1, 24, 30, 60, 0, WOOD, P_BOW, HI_WOOD),
-BOW("elven bow", "runed bow",	0, 12, 30, 60, 0, WOOD, P_BOW, HI_WOOD),
-BOW("orcish bow", "crude bow",	0, 12, 30, 60, 0, WOOD, P_BOW, CLR_BLACK),
+BOW("bow", (char *)0,			  1, 32, 30, 60, 0, WOOD, P_BOW, HI_WOOD),
+BOW("elven bow", "runed bow",	  0, 15, 30, 60, 0, WOOD, P_BOW, HI_WOOD),
+BOW("orcish bow", "crude bow",  0, 20, 30, 60, 0, WOOD, P_BOW, CLR_BLACK),
 BOW("yumi", "long bow",		0,  0, 30, 60, 0, WOOD, P_BOW, HI_WOOD),
-BOW("sling", (char *)0,		1, 40,  3, 20, 0, LEATHER, P_SLING, HI_LEATHER),
+BOW("sling", (char *)0,			  1, 16,  3, 20, 0, LEATHER, P_SLING, HI_LEATHER),
 BOW("crossbow", (char *)0,	1, 45, 50, 40, 0, WOOD, P_CROSSBOW, HI_WOOD),
 
@@ -295,14 +308,15 @@
 /* helmets */
 HELM("elven leather helm", "leather hat",
-		0, 0,  0,	6, 1,  3,   8, 9, 0, LEATHER, HI_LEATHER),
+		0, 0,  0,			5, 1,  3,   8, 9, 0, LEATHER, HI_LEATHER),
+HELM("gnomish helm", "little red hat",
+		0, 0,  0,			5, 1,  3,   8, 10, 0, CLOTH, CLR_RED),
 HELM("orcish helm", "iron skull cap",
-		0, 0,  0,	6, 1, 30,  10, 9, 0, IRON, CLR_BLACK),
+		0, 0,  0,			5, 1, 30,  10, 9, 0, IRON, CLR_BLACK),
 HELM("dwarvish iron helm", "hard hat",
-		0, 0,  0,	6, 1, 40,  20, 8, 0, IRON, HI_METAL),
+		0, 0,  0,			5, 1, 40,  20, 8, 0, IRON, HI_METAL),
 HELM("fedora", (char *)0,
 		1, 0,  0,	0, 0,  3,   1,10, 0, CLOTH, CLR_BROWN),
 HELM("cornuthaum", "conical hat",
-		0, 1,  CLAIRVOYANT,
-				3, 1,  4,  80,10, 2, CLOTH, CLR_BLUE),
+		0, 1,  CLAIRVOYANT, 3, 1,  4,  80,10, 2, CLOTH, CLR_BLUE),
 HELM("dunce cap", "conical hat",
 		0, 1,  0,	3, 1,  4,   1,10, 0, CLOTH, CLR_BLUE),
@@ -311,11 +325,15 @@
 /* With shuffled appearances... */
 HELM("helmet", "plumed helmet",
-		0, 0,  0,      10, 1, 30,  10, 9, 0, IRON, HI_METAL),
+		0, 0, 0,				9, 1, 30,  10, 9, 0, IRON, HI_METAL),
 HELM("helm of brilliance", "etched helmet",
-		0, 1,  0,	6, 1, 50,  50, 9, 0, IRON, CLR_GREEN),
+		0, 1, 0,				4, 1, 50,  50, 9, 0, IRON, CLR_GREEN),
 HELM("helm of opposite alignment", "crested helmet",
-		0, 1,  0,	6, 1, 50,  50, 9, 0, IRON, HI_METAL),
+		0, 1, 0,				3, 1, 50, 50, 9, 0, IRON, HI_METAL),
 HELM("helm of telepathy", "visored helmet",
 		0, 1,  TELEPAT, 2, 1, 50,  50, 9, 0, IRON, HI_METAL),
+HELM("helm of discovery", "viking helmet", 
+		0, 1, SEARCHING,	2, 1, 50,  50, 9, 0, IRON, HI_METAL),
+HELM("helm of clarity", "tinfoil hat", 
+		0, 1, VISION,		2, 1, 50,  50, 9, 0, IRON, HI_SILVER),
 
 /* suits of armor */
@@ -343,4 +361,5 @@
 DRGN_ARMR("blue dragon scale mail",   1, SHOCK_RES,   900, 1, CLR_BLUE),
 DRGN_ARMR("green dragon scale mail",  1, POISON_RES,  900, 1, CLR_GREEN),
+DRGN_ARMR("gold dragon scale mail",   1, 0,  900, 1, HI_GOLD),
 DRGN_ARMR("yellow dragon scale mail", 1, ACID_RES,    900, 1, CLR_YELLOW),
 
@@ -359,42 +378,45 @@
 DRGN_ARMR("blue dragon scales",   0, SHOCK_RES,  500, 7, CLR_BLUE),
 DRGN_ARMR("green dragon scales",  0, POISON_RES, 500, 7, CLR_GREEN),
+DRGN_ARMR("gold dragon scales",   0, 0, 500, 7, HI_GOLD),
 DRGN_ARMR("yellow dragon scales", 0, ACID_RES,   500, 7, CLR_YELLOW),
 #undef DRGN_ARMR
 
 ARMOR("plate mail", (char *)0,
-	1, 0, 1, 0,	44, 5, 450, 600,  3, 2, ARM_SUIT, IRON, HI_METAL),
+	1, 0, 1, 0,	44, 5, 350, 600,  3, 2, ARM_SUIT, IRON, HI_METAL),
 ARMOR("crystal plate mail", (char *)0,
-	1, 0, 1, 0,	10, 5, 450, 820,  3, 2, ARM_SUIT, GLASS, CLR_WHITE),
+	1, 0, 1, 0,	15, 5, 350, 820,  3, 2, ARM_SUIT, GLASS, CLR_WHITE),
 #ifdef TOURIST
 ARMOR("bronze plate mail", (char *)0,
-	1, 0, 1, 0,	25, 5, 450, 400,  4, 0, ARM_SUIT, COPPER, HI_COPPER),
+	1, 0, 1, 0,	30, 5, 300, 400,  4, 0, ARM_SUIT, COPPER, HI_COPPER),
 #else
 ARMOR("bronze plate mail", (char *)0,
-	1, 0, 1, 0,	35, 5, 450, 400,  4, 0, ARM_SUIT, COPPER, HI_COPPER),
+	1, 0, 1, 0,	40, 5, 300, 400,  4, 0, ARM_SUIT, COPPER, HI_COPPER),
 #endif
 ARMOR("splint mail", (char *)0,
-	1, 0, 1, 0,	62, 5, 400,  80,  4, 1, ARM_SUIT, IRON, HI_METAL),
+	1, 0, 1, 0,	57, 5, 300,  80,  4, 1, ARM_SUIT, WOOD, HI_WOOD),	/* bamboo */
 ARMOR("banded mail", (char *)0,
-	1, 0, 1, 0,	72, 5, 350,  90,  4, 0, ARM_SUIT, IRON, HI_METAL),
+	1, 0, 1, 0,	67, 5, 250,  90,  4, 0, ARM_SUIT, IRON, HI_METAL),
 ARMOR("dwarvish mithril-coat", (char *)0,
 	1, 0, 0, 0,	10, 1, 150, 240,  4, 3, ARM_SUIT, MITHRIL, HI_METAL),
 ARMOR("elven mithril-coat", (char *)0,
 	1, 0, 0, 0,	15, 1, 150, 240,  5, 3, ARM_SUIT, MITHRIL, HI_METAL),
+ARMOR("gnomish suit", "little blue vest",
+	0, 0, 0, 0,	12, 0, 50,  10,  9, 0, ARM_SUIT, CLOTH, CLR_BLUE),
 ARMOR("chain mail", (char *)0,
-	1, 0, 0, 0,	72, 5, 300,  75,  5, 1, ARM_SUIT, IRON, HI_METAL),
+	1, 0, 0, 0,	70, 5, 200,  75,  5, 1, ARM_SUIT, IRON, HI_METAL),
 ARMOR("orcish chain mail", "crude chain mail",
-	0, 0, 0, 0,	20, 5, 300,  75,  6, 1, ARM_SUIT, IRON, CLR_BLACK),
+	0, 0, 0, 0,	20, 5, 200,  75,  6, 1, ARM_SUIT, IRON, CLR_BLACK),
 ARMOR("scale mail", (char *)0,
-	1, 0, 0, 0,	72, 5, 250,  45,  6, 0, ARM_SUIT, IRON, HI_METAL),
+	1, 0, 0, 0,	70, 5, 150,  45,  6, 0, ARM_SUIT, IRON, HI_METAL),
 ARMOR("studded leather armor", (char *)0,
-	1, 0, 0, 0,	72, 3, 200,  15,  7, 1, ARM_SUIT, LEATHER, HI_LEATHER),
+	1, 0, 0, 0,	70, 3, 125,  15,  7, 1, ARM_SUIT, LEATHER, HI_LEATHER),
 ARMOR("ring mail", (char *)0,
-	1, 0, 0, 0,	72, 5, 250, 100,  7, 0, ARM_SUIT, IRON, HI_METAL),
+	1, 0, 0, 0,	70, 5, 150, 100,  7, 0, ARM_SUIT, IRON, HI_METAL),
 ARMOR("orcish ring mail", "crude ring mail",
-	0, 0, 0, 0,	20, 5, 250,  80,  8, 1, ARM_SUIT, IRON, CLR_BLACK),
+	0, 0, 0, 0,	20, 5, 150,  80,  8, 1, ARM_SUIT, IRON, CLR_BLACK),
 ARMOR("leather armor", (char *)0,
-	1, 0, 0, 0,	82, 3, 150,   5,  8, 0, ARM_SUIT, LEATHER, HI_LEATHER),
+	1, 0, 0, 0,	80, 3, 75,   5,  8, 0, ARM_SUIT, LEATHER, HI_LEATHER),
 ARMOR("leather jacket", (char *)0,
-	1, 0, 0, 0,	12, 0,	30,  10,  9, 0, ARM_SUIT, LEATHER, CLR_BLACK),
+	1, 0, 0, 0,	10, 0,	30,  10,  9, 0, ARM_SUIT, LEATHER, CLR_BLACK),
 
 #ifdef TOURIST
@@ -413,7 +435,7 @@
 		0, 1,	STEALTH,    8, 0, 10, 60,  9, 3, CLOTH, CLR_BLACK),
 CLOAK("orcish cloak", "coarse mantelet",
-		0, 0,	0,	    8, 0, 10, 40, 10, 2, CLOTH, CLR_BLACK),
+		0, 0,	0,	    7, 0, 10, 40, 10, 2, CLOTH, CLR_BLACK),
 CLOAK("dwarvish cloak", "hooded cloak",
-		0, 0,	0,	    8, 0, 10, 50, 10, 2, CLOTH, HI_CLOTH),
+		0, 0,	0,	    7, 0, 10, 50, 10, 2, CLOTH, HI_CLOTH),
 CLOAK("oilskin cloak", "slippery cloak",
 		0, 0,	0,	    8, 0, 10, 50,  9, 3, CLOTH, HI_CLOTH),
@@ -426,27 +448,40 @@
 /* With shuffled appearances... */
 CLOAK("cloak of protection", "tattered cape",
-		0, 1,	PROTECTION, 9, 0, 10, 50,  7, 3, CLOTH, HI_CLOTH),
+		0, 1,	PROTECTION, 8, 0, 10, 50,  7, 3, CLOTH, HI_CLOTH),
 CLOAK("cloak of invisibility", "opera cloak",
-		0, 1,	INVIS,	   10, 0, 10, 60,  9, 2, CLOTH, CLR_BRIGHT_MAGENTA),
+		0, 1,	INVIS,	   8, 0, 10, 60,  9, 2, CLOTH, CLR_BRIGHT_MAGENTA),
 CLOAK("cloak of magic resistance", "ornamental cope",
 		0, 1,	ANTIMAGIC,  2, 0, 10, 60,  9, 3, CLOTH, CLR_WHITE),
 CLOAK("cloak of displacement", "piece of cloth",
-		0, 1,	DISPLACED, 10, 0, 10, 50,  9, 2, CLOTH, HI_CLOTH),
+		0, 1,	DISPLACED,  8, 0, 10, 50,  9, 2, CLOTH, HI_CLOTH),
 
 /* shields */
 SHIELD("small shield", (char *)0,
-		1, 0, 0, 0,	     6, 0, 30,	3,  9, 0, WOOD, HI_WOOD),
+		1, 0, 0, 0,	     5, 0, 30,	3,  9, 0, WOOD, HI_WOOD),
 SHIELD("elven shield", "blue and green shield",
-		0, 0, 0, 0,	     2, 0, 40,	7,  8, 0, WOOD, CLR_GREEN),
+		0, 0, 0, 0,	     2, 0, 36,	7,  8, 0, WOOD, CLR_GREEN),
 SHIELD("Uruk-hai shield", "white-handed shield",
-		0, 0, 0, 0,	     2, 0, 50,	7,  9, 0, IRON, HI_METAL),
+		0, 0, 0, 0,	     2, 0, 40,	7,  9, 0, IRON, HI_METAL),
 SHIELD("orcish shield", "red-eyed shield",
-		0, 0, 0, 0,	     2, 0, 50,	7,  9, 0, IRON, CLR_RED),
+		0, 0, 0, 0,	     2, 0, 40,	7,  9, 0, IRON, CLR_RED),
 SHIELD("large shield", (char *)0,
-		1, 0, 1, 0,	     7, 0,100, 10,  8, 0, IRON, HI_METAL),
+		1, 0, 1, 0,	     5, 0,100, 10,  8, 0, IRON, HI_METAL),
 SHIELD("dwarvish roundshield", "large round shield",
-		0, 0, 0, 0,	     4, 0,100, 10,  8, 0, IRON, HI_METAL),
+		0, 0, 0, 0,	     3, 0,100, 10,  8, 0, IRON, HI_METAL),
 SHIELD("shield of reflection", "polished silver shield",
-		0, 1, 0, REFLECTING, 3, 0, 50, 50,  8, 0, SILVER, HI_SILVER),
+		0, 1, 0, REFLECTING, 2, 0, 50, 50,  8, 0, SILVER, HI_SILVER),
+/* These still may change, but we can at least generate them randomly now */
+SHIELD("flame shield", "dark red shield",
+		0, 1, 0, FIRE_RES,	 2, 0, 50, 300, 8, 0, IRON, CLR_RED),
+SHIELD("ice shield", "dark blue shield",
+		0, 1, 0, COLD_RES,	 2, 0, 50, 300, 8, 0, IRON, CLR_BLUE),
+SHIELD("lightning shield", "dull yellow shield",
+		0, 1, 0, SHOCK_RES,	 2, 0, 50, 300, 8, 0, IRON, CLR_YELLOW),
+SHIELD("venom shield", "dark green shield",
+		0, 1, 0, POISON_RES,	 2, 0, 50, 300, 8, 0, IRON, CLR_GREEN),
+SHIELD("shield of light", "shiny shield",
+		0, 1, 0, 0,				 2, 0, 50, 300, 8, 0, IRON, CLR_YELLOW),
+SHIELD("shield of mobility", "slippery shield",
+		0, 1, 0, FREE_ACTION, 2, 0, 50, 300, 9, 0, IRON, HI_METAL),
 
 /* gloves */
@@ -455,34 +490,42 @@
  */
 GLOVES("leather gloves", "old gloves",
-		0, 0,  0,	  16, 1, 10,  8,  9, 0, LEATHER, HI_LEATHER),
+		0, 0,  0,		  14, 1, 10,  8,  9, 0, LEATHER, HI_LEATHER),
 GLOVES("gauntlets of fumbling", "padded gloves",
-		0, 1,  FUMBLING,   8, 1, 10, 50,  9, 0, LEATHER, HI_LEATHER),
+		0, 1,  FUMBLING,  6, 1, 10, 50,  9, 0, LEATHER, HI_LEATHER),
 GLOVES("gauntlets of power", "riding gloves",
-		0, 1,  0,	   8, 1, 30, 50,  9, 0, IRON, CLR_BROWN),
+		0, 1,  0,			5, 1, 30, 50,  9, 0, IRON, CLR_BROWN),
 GLOVES("gauntlets of dexterity", "fencing gloves",
-		0, 1,  0,	   8, 1, 10, 50,  9, 0, LEATHER, HI_LEATHER),
+		0, 1,  0,			5, 1, 10, 50,  9, 0, LEATHER, HI_LEATHER),
+GLOVES("gauntlets of force", "fur-lined mittens",
+		0, 1,  0,			5, 1, 10, 50,  9, 0, LEATHER, HI_LEATHER),
+GLOVES("gauntlets of fortune", "ragged gloves",
+		0, 1,  LUCKY,		5, 1, 10, 50,  9, 0, LEATHER, HI_LEATHER),
 
 /* boots */
 BOOTS("low boots", "walking shoes",
-		0, 0,  0,	  25, 2, 10,  8,  9, 0, LEATHER, HI_LEATHER),
+		0, 0,  0,	  20, 2, 10,  8,  9, 0, LEATHER, HI_LEATHER),
 BOOTS("iron shoes", "hard shoes",
 		0, 0,  0,	   7, 2, 50, 16,  8, 0, IRON, HI_METAL),
+BOOTS("gnomish boots", "little black boots",
+		0, 0,  0,	   7, 2, 10, 16,  10, 0, LEATHER, CLR_BLACK),
 BOOTS("high boots", "jackboots",
-		0, 0,  0,	  15, 2, 20, 12,  8, 0, LEATHER, HI_LEATHER),
+		0, 0,  0,	  13, 2, 20, 12,  8, 0, LEATHER, HI_LEATHER),
 /* With shuffled appearances... */
 BOOTS("speed boots", "combat boots",
-		0, 1,  FAST,	  12, 2, 20, 50,  9, 0, LEATHER, HI_LEATHER),
+		0, 1,  FAST,	  10, 2, 20, 50,  9, 0, LEATHER, HI_LEATHER),
+BOOTS("boots of molasses", "thigh boots",
+		0, 1,  SLOW,	  11, 2, 20, 50, 9, 0, LEATHER, CLR_BLACK),
 BOOTS("water walking boots", "jungle boots",
-		0, 1,  WWALKING,  12, 2, 20, 50,  9, 0, LEATHER, HI_LEATHER),
+		0, 1,  WWALKING,  10, 2, 20, 50,  9, 0, LEATHER, HI_LEATHER),
 BOOTS("jumping boots", "hiking boots",
-		0, 1,  JUMPING,   12, 2, 20, 50,  9, 0, LEATHER, HI_LEATHER),
+		0, 1,  JUMPING,   10, 2, 20, 50,  9, 0, LEATHER, HI_LEATHER),
 BOOTS("elven boots", "mud boots",
-		0, 1,  STEALTH,   12, 2, 15,  8,  9, 0, LEATHER, HI_LEATHER),
+		0, 1,  STEALTH,   10, 2, 15,  8,  9, 0, LEATHER, HI_LEATHER),
 BOOTS("kicking boots", "buckled boots",
-		0, 1,  0,         12, 2, 15,  8,  9, 0, IRON, CLR_BROWN),
+		0, 1,  0,         11, 2, 15,  8,  9, 0, IRON, CLR_BROWN),
 BOOTS("fumble boots", "riding boots",
-		0, 1,  FUMBLING,  12, 2, 20, 30,  9, 0, LEATHER, HI_LEATHER),
+		0, 1,  FUMBLING,  11, 2, 20, 30,  9, 0, LEATHER, HI_LEATHER),
 BOOTS("levitation boots", "snow boots",
-		0, 1,  LEVITATION,12, 2, 15, 30,  9, 0, LEATHER, HI_LEATHER),
+		0, 1,  LEVITATION,11, 2, 15, 30,  9, 0, LEATHER, HI_LEATHER),
 #undef HELM
 #undef CLOAK
@@ -543,14 +586,15 @@
 		AMULET_CLASS, prob, 0, 20, 150, 0, 0, 0, 0, 20, HI_METAL )
 
-AMULET("amulet of ESP",           "circular",   TELEPAT,    175),
-AMULET("amulet of life saving",   "spherical",  LIFESAVED,   75),
-AMULET("amulet of strangulation", "oval",       STRANGLED,  135),
-AMULET("amulet of restful sleep", "triangular", SLEEPING,   135),
-AMULET("amulet versus poison",    "pyramidal",  POISON_RES, 165),
-AMULET("amulet of change",        "square",     0,          130),
+AMULET("amulet of ESP",           "circular",   TELEPAT,    155),
+AMULET("amulet of life saving",   "spherical",  LIFESAVED,   60),
+AMULET("amulet of strangulation", "oval",       STRANGLED,  120),
+AMULET("amulet of restful sleep", "triangular", SLEEPING,   120),
+AMULET("amulet versus poison",    "pyramidal",  POISON_RES, 155),
+AMULET("amulet of change",        "square",     0,          110),
 						/* POLYMORPH */
 AMULET("amulet of unchanging",    "concave",    UNCHANGING,	 45),
-AMULET("amulet of reflection",    "hexagonal",  REFLECTING,  75),
-AMULET("amulet of magical breathing", "octagonal",      MAGICAL_BREATHING, 65),
+AMULET("amulet of reflection",    "hexagonal",  REFLECTING,  65),
+AMULET("amulet of magical breathing", "octagonal",      MAGICAL_BREATHING, 55),
+AMULET("amulet of power",			 "spiked",		ENERGY_REGENERATION,  115),
 OBJECT(OBJ("cheap plastic imitation of the Amulet of Yendor",
 	"Amulet of Yendor"), BITS(0,0,1,0,0,0,0,0,0,0,0,0,PLASTIC), 0,
@@ -580,14 +624,17 @@
 /* containers */
 CONTAINER("large box", (char *)0,       1, 0, 0,  40,350,   8, WOOD, HI_WOOD),
-CONTAINER("chest", (char *)0,           1, 0, 0,  35,600,  16, WOOD, HI_WOOD),
+CONTAINER("chest", (char *)0,           1, 0, 0,  25,600,  16, WOOD, HI_WOOD),
+CONTAINER("iron safe", (char *)0,       1, 0, 0,  10,900,  50, IRON, HI_METAL),
 CONTAINER("ice box", (char *)0,         1, 0, 0,   5,900,  42, PLASTIC, CLR_WHITE),
-CONTAINER("sack", "bag",                0, 0, 0,  35, 15,   2, CLOTH, HI_CLOTH),
+CONTAINER("small sack", "small bag",    0, 0, 0,  30, 15,   2, CLOTH, HI_CLOTH),
+CONTAINER("sack", "bag",                0, 0, 0,  20, 15,   2, CLOTH, HI_CLOTH),
 CONTAINER("oilskin sack", "bag",        0, 0, 0,   5, 15, 100, CLOTH, HI_CLOTH),
 CONTAINER("bag of holding", "bag",      0, 1, 0,  20, 15, 100, CLOTH, HI_CLOTH),
 CONTAINER("bag of tricks", "bag",       0, 1, 1,  20, 15, 100, CLOTH, HI_CLOTH),
+CONTAINER("bag of poo", "bag",          0, 0, 0,   5, 15,   2, CLOTH, HI_CLOTH),
 #undef CONTAINER
 
 /* lock opening tools */
-TOOL("skeleton key", "key",     0, 0, 0, 0,  80,  3,  10, IRON, HI_METAL),
+TOOL("skeleton key", "key",     0, 0, 0, 0,  60,  3,  10, IRON, HI_METAL),
 #ifdef TOURIST
 TOOL("lock pick", (char *)0,    1, 0, 0, 0,  60,  4,  20, IRON, HI_METAL),
@@ -604,18 +651,16 @@
 /* other tools */
 #ifdef TOURIST
-TOOL("expensive camera", (char *)0,
-				1, 0, 0, 1,  15, 12, 200, PLASTIC, CLR_BLACK),
-TOOL("mirror", "looking glass", 0, 0, 0, 0,  45, 13,  10, GLASS, HI_SILVER),
+TOOL("expensive camera", (char *)0, 1, 0, 0, 1,  20, 12, 200, PLASTIC, CLR_BLACK),
+TOOL("mirror", "looking glass", 0, 0, 0, 0,  25, 13,  10, GLASS, HI_SILVER),
 #else
 TOOL("mirror", "looking glass", 0, 0, 0, 0,  60, 13,  10, GLASS, HI_SILVER),
 #endif
-TOOL("crystal ball", "glass orb",
-				0, 0, 1, 1,  15,150,  60, GLASS, HI_GLASS),
+TOOL("crystal ball", "glass orb", 0, 0, 1, 1,  15,150,  60, GLASS, HI_GLASS),
 TOOL("lenses", (char *)0,	1, 0, 0, 0,   5,  3,  80, GLASS, HI_GLASS),
 TOOL("blindfold", (char *)0,    1, 0, 0, 0,  50,  2,  20, CLOTH, CLR_BLACK),
 TOOL("towel", (char *)0,        1, 0, 0, 0,  50,  2,  50, CLOTH, CLR_MAGENTA),
 #ifdef STEED
-TOOL("saddle", (char *)0,       1, 0, 0, 0,   5,200, 150, LEATHER, HI_LEATHER),
-TOOL("leash", (char *)0,        1, 0, 0, 0,  65, 12,  20, LEATHER, HI_LEATHER),
+TOOL("saddle", (char *)0,       1, 0, 0, 0,  25,200, 150, LEATHER, HI_LEATHER),
+TOOL("leash", (char *)0,        1, 0, 0, 0,  45, 12,  20, LEATHER, HI_LEATHER),
 #else
 TOOL("leash", (char *)0,        1, 0, 0, 0,  70, 12,  20, LEATHER, HI_LEATHER),
@@ -624,7 +669,7 @@
 TOOL("tinning kit", (char *)0,  1, 0, 0, 1,  15,100,  30, IRON, HI_METAL),
 TOOL("tin opener", (char *)0,   1, 0, 0, 0,  35,  4,  30, IRON, HI_METAL),
-TOOL("can of grease", (char *)0,1, 0, 0, 1,  15, 15,  20, IRON, HI_METAL),
+TOOL("can of grease", (char *)0,1, 0, 0, 1,  20, 15,  20, IRON, HI_METAL),
 TOOL("figurine", (char *)0,     1, 0, 1, 0,  25, 50,  80, MINERAL, HI_MINERAL),
-TOOL("magic marker", (char *)0, 1, 0, 1, 1,  15,  2,  50, PLASTIC, CLR_RED),
+TOOL("magic marker", (char *)0, 1, 0, 1, 1,   0,  2,  50, PLASTIC, CLR_RED),
 /* traps */
 TOOL("land mine",(char *)0,     1, 0, 0, 0,   0,300, 180, IRON, CLR_RED),
@@ -634,17 +679,16 @@
 TOOL("magic whistle", "whistle",0, 0, 1, 0,  30,  3,  10, METAL, HI_METAL),
 /* "If tin whistles are made out of tin, what do they make foghorns out of?" */
-TOOL("wooden flute", "flute",   0, 0, 0, 0,   4,  5,  12, WOOD, HI_WOOD),
-TOOL("magic flute", "flute",    0, 0, 1, 1,   2,  5,  36, WOOD, HI_WOOD),
-TOOL("tooled horn", "horn",     0, 0, 0, 0,   5, 18,  15, BONE, CLR_WHITE),
-TOOL("frost horn", "horn",      0, 0, 1, 1,   2, 18,  50, BONE, CLR_WHITE),
-TOOL("fire horn", "horn",       0, 0, 1, 1,   2, 18,  50, BONE, CLR_WHITE),
-TOOL("horn of plenty", "horn",  0, 0, 1, 1,   2, 18,  50, BONE, CLR_WHITE),
-TOOL("wooden harp", "harp",     0, 0, 0, 0,   4, 30,  50, WOOD, HI_WOOD),
-TOOL("magic harp", "harp",      0, 0, 1, 1,   2, 30,  50, WOOD, HI_WOOD),
+TOOL("wooden flute", "flute",   0, 0, 0, 0,   8,  5,  12, WOOD, HI_WOOD),
+TOOL("magic flute", "flute",    0, 0, 1, 1,   5,  5,  36, WOOD, HI_WOOD),
+TOOL("tooled horn", "horn",     0, 0, 0, 0,   7, 18,  15, BONE, CLR_WHITE),
+TOOL("frost horn", "horn",      0, 0, 1, 1,   4, 18,  50, BONE, CLR_WHITE),
+TOOL("fire horn", "horn",       0, 0, 1, 1,   4, 18,  50, BONE, CLR_WHITE),
+TOOL("horn of plenty", "horn",  0, 0, 1, 1,   6, 18,  50, BONE, CLR_WHITE),
+TOOL("wooden harp", "harp",     0, 0, 0, 0,   6, 30,  50, WOOD, HI_WOOD),
+TOOL("magic harp", "harp",      0, 0, 1, 1,   4, 30,  50, WOOD, HI_WOOD),
 TOOL("bell", (char *)0,         1, 0, 0, 0,   2, 30,  50, COPPER, HI_COPPER),
 TOOL("bugle", (char *)0,        1, 0, 0, 0,   4, 10,  15, COPPER, HI_COPPER),
-TOOL("leather drum", "drum",    0, 0, 0, 0,   4, 25,  25, LEATHER, HI_LEATHER),
-TOOL("drum of earthquake", "drum",
-				0, 0, 1, 1,   2, 25,  25, LEATHER, HI_LEATHER),
+TOOL("leather drum", "drum",    0, 0, 0, 0,   6, 25,  25, LEATHER, HI_LEATHER),
+TOOL("drum of earthquake", "drum", 0, 0, 1, 1,   4, 25,  25, LEATHER, HI_LEATHER),
 /* tools useful as weapons */
 WEPTOOL("pick-axe", (char *)0,
@@ -749,4 +793,8 @@
 POTION("acid", "white",                 0, 0,          10, 250, CLR_WHITE),
 POTION("oil", "murky",                  0, 0,          30, 250, CLR_BROWN),
+POTION("salt water",	"polka-dot",	    0, 0,			  0,  50, CLR_RED),
+POTION((char*)0, "greasy",              0, 0,           0, 100, CLR_BLACK),
+POTION((char*)0, "slimy",               0, 0,           0, 100, CLR_BROWN),
+POTION((char*)0, "chartreuse",          0, 0,           0, 100, CLR_GREEN),
 POTION("water", "clear",                0, 0,          92, 100, CLR_CYAN),
 #undef POTION
@@ -793,15 +841,15 @@
 		SPBOOK_CLASS, prob, delay, \
 		50, level*100, 0, 0, 0, level, 20, color )
-SPELL("dig",             "parchment",   P_MATTER_SPELL, 20,  6, 5, 1, RAY,       HI_PAPER),
-SPELL("magic missile",   "vellum",      P_ATTACK_SPELL, 45,  2, 2, 1, RAY,       HI_PAPER),
+SPELL("dig",             "parchment",   P_MATTER_SPELL,		  20,  6, 4, 1, RAY,       HI_PAPER),
+SPELL("magic missile",   "vellum",      P_ATTACK_SPELL,		  40,  2, 2, 1, RAY,       HI_PAPER),
 SPELL("fireball",        "ragged",      P_ATTACK_SPELL, 20,  4, 4, 1, RAY,       HI_PAPER),
 SPELL("cone of cold",    "dog eared",   P_ATTACK_SPELL, 10,  7, 4, 1, RAY,       HI_PAPER),
-SPELL("sleep",           "mottled",     P_ENCHANTMENT_SPELL, 50,  1, 1, 1, RAY,       HI_PAPER),
+SPELL("sleep",           "mottled",     P_ENCHANTMENT_SPELL,  40,  1, 1, 1, RAY,       HI_PAPER),
 SPELL("finger of death", "stained",     P_ATTACK_SPELL,  5, 10, 7, 1, RAY,       HI_PAPER),
-SPELL("light",           "cloth",       P_DIVINATION_SPELL, 45,  1, 1, 1, NODIR,     HI_CLOTH),
-SPELL("detect monsters", "leather",     P_DIVINATION_SPELL, 43,  1, 1, 1, NODIR,     HI_LEATHER),
-SPELL("healing",         "white",       P_HEALING_SPELL, 40,  2, 1, 1, IMMEDIATE, CLR_WHITE),
-SPELL("knock",           "pink",        P_MATTER_SPELL, 35,  1, 1, 1, IMMEDIATE, CLR_BRIGHT_MAGENTA),
-SPELL("force bolt",      "red",         P_ATTACK_SPELL, 35,  2, 1, 1, IMMEDIATE, CLR_RED),
+SPELL("light",           "cloth",       P_DIVINATION_SPELL,	  40,  1, 1, 1, NODIR,     HI_CLOTH),
+SPELL("detect monsters", "leather",     P_DIVINATION_SPELL,	  43,  1, 3, 1, NODIR,     HI_LEATHER),
+SPELL("healing",         "white",       P_HEALING_SPELL,		  35,  2, 1, 1, IMMEDIATE, CLR_WHITE),
+SPELL("knock",           "pink",        P_MATTER_SPELL,		  30,  1, 1, 1, IMMEDIATE, CLR_BRIGHT_MAGENTA),
+SPELL("force bolt",      "red",         P_ATTACK_SPELL,		  30,  2, 1, 1, IMMEDIATE, CLR_RED),
 SPELL("confuse monster", "orange",      P_ENCHANTMENT_SPELL, 30,  2, 2, 1, IMMEDIATE, CLR_ORANGE),
 SPELL("cure blindness",  "yellow",      P_HEALING_SPELL, 25,  2, 2, 1, IMMEDIATE, CLR_YELLOW),
@@ -810,31 +858,32 @@
 SPELL("wizard lock",     "dark green",  P_MATTER_SPELL, 30,  3, 2, 1, IMMEDIATE, CLR_GREEN),
 SPELL("create monster",  "turquoise",   P_CLERIC_SPELL, 35,  3, 2, 1, NODIR,     CLR_BRIGHT_CYAN),
-SPELL("detect food",     "cyan",        P_DIVINATION_SPELL, 30,  3, 2, 1, NODIR,     CLR_CYAN),
+SPELL("obtain food",     "cyan",        P_MATTER_SPELL,  	  30,  3, 1, 1, NODIR,     CLR_CYAN),
 SPELL("cause fear",      "light blue",  P_ENCHANTMENT_SPELL, 25,  3, 3, 1, NODIR,     CLR_BRIGHT_BLUE),
 SPELL("clairvoyance",    "dark blue",   P_DIVINATION_SPELL, 15,  3, 3, 1, NODIR,     CLR_BLUE),
 SPELL("cure sickness",   "indigo",      P_HEALING_SPELL, 32,  3, 3, 1, NODIR,     CLR_BLUE),
-SPELL("charm monster",   "magenta",     P_ENCHANTMENT_SPELL, 20,  3, 3, 1, IMMEDIATE, CLR_MAGENTA),
+SPELL("charm monster",   "magenta",     P_ENCHANTMENT_SPELL,  20,  3, 6, 1, IMMEDIATE, CLR_MAGENTA),
 SPELL("haste self",      "purple",      P_ESCAPE_SPELL, 33,  4, 3, 1, NODIR,     CLR_MAGENTA),
-SPELL("detect unseen",   "violet",      P_DIVINATION_SPELL, 20,  4, 3, 1, NODIR,     CLR_MAGENTA),
+SPELL("detect unseen",   "violet",      P_DIVINATION_SPELL,	  20,  4, 2, 1, NODIR,     CLR_MAGENTA),
 SPELL("levitation",      "tan",         P_ESCAPE_SPELL, 20,  4, 4, 1, NODIR,     CLR_BROWN),
 SPELL("extra healing",   "plaid",       P_HEALING_SPELL, 27,  5, 3, 1, IMMEDIATE, CLR_GREEN),
-SPELL("restore ability", "light brown", P_HEALING_SPELL, 25,  5, 4, 1, NODIR,     CLR_BROWN),
-SPELL("invisibility",    "dark brown",  P_ESCAPE_SPELL, 25,  5, 4, 1, NODIR,     CLR_BROWN),
+SPELL("restore ability", "light brown", P_HEALING_SPELL,		  25,  5, 2, 1, NODIR,     CLR_BROWN),
+SPELL("invisibility",    "dark brown",  P_ESCAPE_SPELL,		  20,  5, 2, 1, NODIR,     CLR_BROWN),
 SPELL("detect treasure", "gray",        P_DIVINATION_SPELL, 20,  5, 4, 1, NODIR,     CLR_GRAY),
 SPELL("remove curse",    "wrinkled",    P_CLERIC_SPELL, 25,  5, 3, 1, NODIR,     HI_PAPER),
 SPELL("magic mapping",   "dusty",       P_DIVINATION_SPELL, 18,  7, 5, 1, NODIR,     HI_PAPER),
 SPELL("identify",        "bronze",      P_DIVINATION_SPELL, 20,  6, 3, 1, NODIR,     HI_COPPER),
-SPELL("turn undead",     "copper",      P_CLERIC_SPELL, 16,  8, 6, 1, IMMEDIATE, HI_COPPER),
-SPELL("polymorph",       "silver",      P_MATTER_SPELL, 10,  8, 6, 1, IMMEDIATE, HI_SILVER),
+SPELL("turn undead",     "copper",      P_CLERIC_SPELL,		  11,  8, 6, 1, IMMEDIATE, HI_COPPER),
+SPELL("polymorph creature", "silver",   P_MATTER_SPELL,		  10,  8, 6, 1, IMMEDIATE, HI_SILVER),
 SPELL("teleport away",   "gold",        P_ESCAPE_SPELL, 15,  6, 6, 1, IMMEDIATE, HI_GOLD),
-SPELL("create familiar", "glittering",  P_CLERIC_SPELL, 10,  7, 6, 1, NODIR,     CLR_WHITE),
+SPELL("create familiar", "glittering",  P_CLERIC_SPELL,		  10,  7, 3, 1, NODIR,     CLR_WHITE),
 SPELL("cancellation",    "shining",     P_MATTER_SPELL, 15,  8, 7, 1, IMMEDIATE, CLR_WHITE),
-SPELL("protection",	     "dull",        P_CLERIC_SPELL, 18,  3, 1, 1, NODIR,     HI_PAPER),
-SPELL("jumping",	     "thin",        P_ESCAPE_SPELL, 20,  3, 1, 1, IMMEDIATE, HI_PAPER),
+SPELL("protection",	    "dull",        P_CLERIC_SPELL,		  13,  3, 1, 1, NODIR,     HI_PAPER),
+SPELL("jumping",			 "thin",        P_ESCAPE_SPELL,		  15,  3, 2, 1, IMMEDIATE, HI_PAPER),
 SPELL("stone to flesh",	 "thick",       P_HEALING_SPELL, 15,  1, 3, 1, IMMEDIATE, HI_PAPER),
-#if 0	/* DEFERRED */
-SPELL("flame sphere",    "canvas",      P_MATTER_SPELL, 20,  2, 1, 1, NODIR, CLR_BROWN),
-SPELL("freeze sphere",   "hardcover",   P_MATTER_SPELL, 20,  2, 1, 1, NODIR, CLR_BROWN),
-#endif
+SPELL("detect foot",		 "chartreuse",	 P_DIVINATION_SPELL,	  20,  2, 7, 1, NODIR, CLR_GREEN),
+SPELL("reflection",		 "decrepit",    P_MATTER_SPELL,		  20,  7, 6, 1, IMMEDIATE, CLR_BROWN),
+SPELL("repair armor",	 "paperback",   P_MATTER_SPELL,		  15,  6, 3, 1, IMMEDIATE, HI_PAPER),
+SPELL((char*)0,		    "canvas",      P_MATTER_SPELL,		   0,  2, 1, 1, NODIR, CLR_BROWN),
+SPELL((char*)0,			 "hardcover",   P_MATTER_SPELL,		   0,  2, 1, 1, NODIR, CLR_BROWN),
 /* blank spellbook must come last because it retains its description */
 SPELL("blank paper",     "plain",       P_NONE, 18,  0, 0, 0, 0,         HI_PAPER),
@@ -853,5 +902,5 @@
 WAND("enlightenment",  "crystal",  15, 150, 1, NODIR,     GLASS,    HI_GLASS),
 WAND("create monster", "maple",    45, 200, 1, NODIR,     WOOD,     HI_WOOD),
-WAND("wishing",        "pine",      5, 500, 1, NODIR,     WOOD,     HI_WOOD),
+WAND("wishing",        "pine",      0, 500, 1, NODIR,     WOOD,     HI_WOOD),
 WAND("nothing",        "oak",      25, 100, 0, IMMEDIATE, WOOD,     HI_WOOD),
 WAND("striking",       "ebony",    75, 150, 1, IMMEDIATE, WOOD,     HI_WOOD),
@@ -862,5 +911,5 @@
 WAND("polymorph",      "silver",   45, 200, 1, IMMEDIATE, SILVER,   HI_SILVER),
 WAND("cancellation",   "platinum", 45, 200, 1, IMMEDIATE, PLATINUM, CLR_WHITE),
-WAND("teleportation",  "iridium",  45, 200, 1, IMMEDIATE, METAL,    CLR_BRIGHT_CYAN),
+WAND("teleportation",  "iridium",  40, 200, 1, IMMEDIATE, METAL,    CLR_BRIGHT_CYAN),
 WAND("opening",        "zinc",     25, 150, 1, IMMEDIATE, METAL,    HI_METAL),
 WAND("locking",        "aluminum", 25, 150, 1, IMMEDIATE, METAL,    HI_METAL),
@@ -868,10 +917,10 @@
 WAND("digging",        "iron",     55, 150, 1, RAY,       IRON,     HI_METAL),
 WAND("magic missile",  "steel",    50, 150, 1, RAY,       IRON,     HI_METAL),
-WAND("fire",           "hexagonal",40, 175, 1, RAY,       IRON,     HI_METAL),
-WAND("cold",           "short",    40, 175, 1, RAY,       IRON,     HI_METAL),
-WAND("sleep",          "runed",    50, 175, 1, RAY,       IRON,     HI_METAL),
+WAND("fire",           "hexagonal",35, 175, 1, RAY,       IRON,     HI_METAL),
+WAND("cold",           "short",    35, 175, 1, RAY,       IRON,     HI_METAL),
+WAND("sleep",          "runed",    45, 175, 1, RAY,       IRON,     HI_METAL),
 WAND("death",          "long",      5, 500, 1, RAY,       IRON,     HI_METAL),
-WAND("lightning",      "curved",   40, 175, 1, RAY,       IRON,     HI_METAL),
-WAND((char *)0,        "forked",    0, 150, 1, 0,         WOOD,     HI_WOOD),
+WAND("lightning",      "curved",   35, 175, 1, RAY,       IRON,     HI_METAL),
+WAND("wind",           "forked",   30, 150, 1, IMMEDIATE, WOOD,     HI_WOOD),
 WAND((char *)0,        "spiked",    0, 150, 1, 0,         IRON,     HI_METAL),
 WAND((char *)0,        "jeweled",   0, 150, 1, 0,         IRON,     HI_MINERAL),
@@ -931,8 +980,9 @@
  * that is currently everything between luckstones and flint (inclusive).
  */
-ROCK("luckstone", "gray",	0, 10,  10, 60, 3, 3, 1, 10, 7, MINERAL, CLR_GRAY),
-ROCK("loadstone", "gray",	0, 10, 500,  1, 3, 3, 1, 10, 6, MINERAL, CLR_GRAY),
-ROCK("touchstone", "gray",	0,  8,  10, 45, 3, 3, 1, 10, 6, MINERAL, CLR_GRAY),
-ROCK("flint", "gray",		0, 10,  10,  1, 6, 6, 0, 10, 7, MINERAL, CLR_GRAY),
+ROCK("luckstone", "gray",	0,  8,  10, 60, 3, 3, 1, 10, 7, MINERAL, CLR_GRAY),
+ROCK("loadstone", "gray",	0,  9, 500,  1, 3, 3, 1, 10, 6, MINERAL, CLR_GRAY),
+ROCK("touchstone", "gray",	0,  7,  10, 45, 3, 3, 1, 10, 6, MINERAL, CLR_GRAY),
+ROCK("salt chunk", "gray", 0,  5,   5,  1, 2, 2, 0, 10, 2, MINERAL, CLR_GRAY),
+ROCK("flint", "gray",		0,  9,  10,  1, 6, 6, 0, 10, 7, MINERAL, CLR_GRAY),
 ROCK("rock", (char *)0,		1,100,  10,  0, 3, 3, 0, 10, 7, MINERAL, CLR_GRAY),
 #undef GEM
@@ -949,4 +999,6 @@
 OBJECT(OBJ("statue", (char *)0), BITS(1,0,0,1,0,0,0,0,0,0,0,P_NONE,MINERAL), 0,
 		ROCK_CLASS,   900, 0, 2500,  0, 20, 20, 0, 0, 2500, CLR_WHITE),
+OBJECT(OBJ("skull", (char *)0), BITS(1,0,0,1,0,0,0,0,0,0,0,P_NONE,BONE), 0,
+		ROCK_CLASS,   0, 0, 10,  0, 3, 3, 0, 0, 10, CLR_WHITE),
 
 OBJECT(OBJ("heavy iron ball", (char *)0), BITS(1,0,0,0,0,0,0,0,0,0,WHACK,P_NONE,IRON), 0,
@@ -965,4 +1017,18 @@
 		/* +d6 small or large */
 
+
+#define FURN(name,desc,wt,material,chr,color) OBJECT(	\
+	    OBJ(name,desc), \
+	    BITS(0,1,0,0,0,0,0,1,1,0,0,0,material), 0, \
+	    FURNITURE_CLASS, 0, 0, wt, 0, 3, 3, chr, 0, 0, color )
+	/* oc_oc1 == map symbol */
+	FURN("throne", (char *)0, 5000, MINERAL, '\\', CLR_YELLOW),
+	FURN("gravestone", (char *)0, 3500, MINERAL, '|', CLR_GRAY),
+	FURN("brazier", (char *)0, 5000, MINERAL, '(', CLR_YELLOW),
+#ifdef SINKS
+	FURN("kitchen sink", (char *)0, 1000, METAL, '#', CLR_GRAY),
+#endif
+#undef FURN
+
 /* fencepost, the deadly Array Terminator -- name [1st arg] *must* be NULL */
 	OBJECT(OBJ((char *)0,(char *)0), BITS(0,0,0,0,0,0,0,0,0,0,0,P_NONE,0), 0,
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/src/objnam.c nethack/src/objnam.c
--- nh_orig/src/objnam.c	2003-12-07 18:39:13.000000000 -0500
+++ nethack/src/objnam.c	2010-04-25 13:07:29.335715867 -0400
@@ -15,5 +15,7 @@
 #endif
 static char *NDECL(nextobuf);
-static void FDECL(add_erosion_words, (struct obj *, char *));
+#ifdef SORTLOOT
+char * FDECL(xname2, (struct obj *, boolean));
+#endif
 
 struct Jitem {
@@ -234,4 +236,13 @@
 xname(obj)
 register struct obj *obj;
+#ifdef SORTLOOT
+{
+	return xname2(obj, FALSE);
+}
+char *
+xname2(obj, ignore_oquan)
+register struct obj *obj;
+boolean ignore_oquan;
+#endif
 {
 	register char *buf;
@@ -467,11 +478,30 @@
 		break;
 	    }
+	case FURNITURE_CLASS:
+		if (!obj->dknown)
+			Strcat(buf, dn ? dn : actualn);
+		else if (nn)
+			Strcat(buf, actualn);
+		else if (un) {
+			Strcat(buf, dn ? dn : actualn);
+			Strcat(buf, " called ");
+			Strcat(buf, un);
+		} else
+			Strcat(buf, dn ? dn : actualn);
+		break;
 	default:
 		Sprintf(buf,"glorkum %d %d %d", obj->oclass, typ, obj->spe);
 	}
+#ifdef SORTLOOT
+	if (!ignore_oquan)
+#endif
 	if (obj->quan != 1L) Strcpy(buf, makeplural(buf));
 
 	if (obj->onamelth && obj->dknown) {
+		if (obj->otyp == SKULL) {
+			Strcat(buf, " of ");		 /* cheesy hotwire */
+		} else {
 		Strcat(buf, " named ");
+		}
 nameit:
 		Strcat(buf, ONAME(obj));
@@ -518,5 +548,5 @@
 }
 
-static void
+void
 add_erosion_words(obj,prefix)
 struct obj *obj;
@@ -525,11 +555,15 @@
 	boolean iscrys = (obj->otyp == CRYSKNIFE);
 
-
-	if (!is_damageable(obj) && !iscrys) return;
-
 	/* The only cases where any of these bits do double duty are for
 	 * rotted food and diluted potions, which are all not is_damageable().
 	 */
 	if (obj->oeroded && !iscrys) {
+	    if (!is_rustprone(obj) && is_meltable(obj)) {
+		switch (obj->oeroded) {
+		case 1: Strcat(prefix, "partly "); break;
+		case 3:	Strcat(prefix, "thoroughly "); break;
+		}
+		Strcat(prefix, "melted ");
+	    } else {
 		switch (obj->oeroded) {
 			case 2:	Strcat(prefix, "very "); break;
@@ -538,4 +572,5 @@
 		Strcat(prefix, is_rustprone(obj) ? "rusty " : "burnt ");
 	}
+	}
 	if (obj->oeroded2 && !iscrys) {
 		switch (obj->oeroded2) {
@@ -543,6 +578,7 @@
 			case 3:	Strcat(prefix, "thoroughly "); break;
 		}			
-		Strcat(prefix, is_corrodeable(obj) ? "corroded " :
-			"rotted ");
+		/* This catches things like dragonscale mail. */
+		Strcat(prefix, !is_damageable(obj) ? "deteriorated " : 
+				is_corrodeable(obj) ? "corroded " : "rotted ");
 	}
 	if (obj->rknown && obj->oerodeproof)
@@ -554,7 +590,8 @@
 }
 
-char *
-doname(obj)
+static char *
+doname_base(obj, with_price)
 register struct obj *obj;
+boolean with_price;
 {
 	boolean ispoisoned = FALSE;
@@ -673,5 +710,5 @@
 			break;
 		} else if (obj->otyp == OIL_LAMP || obj->otyp == MAGIC_LAMP ||
-			obj->otyp == BRASS_LANTERN || Is_candle(obj)) {
+			obj->otyp == BRASS_LANTERN || obj->otyp == BAG_OF_POO || Is_candle(obj)) {
 			if (Is_candle(obj) &&
 			    obj->age < 20L * (long)objects[obj->otyp].oc_cost)
@@ -684,4 +721,10 @@
 		    goto charges;
 		break;
+	case FURNITURE_CLASS:
+		if (obj->otyp == FUR_BRAZIER && obj->lamplit)
+		{
+			Strcat(bp, " (lit)");
+		}
+		break;
 	case WAND_CLASS:
 		add_erosion_words(obj, prefix);
@@ -764,4 +807,5 @@
 	}
 	if(obj->owornmask & W_QUIVER) Strcat(bp, " (in quiver)");
+	if(obj->owornmask & W_LAUNCHER) Strcat(bp, " (chosen ranged weapon)");
 	if(obj->unpaid) {
 		xchar ox, oy; 
@@ -776,4 +820,9 @@
 		Sprintf(eos(bp), " (unpaid, %ld %s)",
 			quotedprice, currency(quotedprice));
+	} else if (with_price) {
+		long price = get_cost_of_shop_item(obj);
+		if (price > 0) {
+			Sprintf(eos(bp), " (%ld %s)", price, currency(price));
+		}
 	}
 	if (!strncmp(prefix, "a ", 2) &&
@@ -790,4 +839,20 @@
 }
 
+/** Wrapper function for vanilla behaviour. */
+char *
+doname(obj)
+register struct obj *obj;
+{
+	return doname_base(obj, FALSE);
+}
+
+/** Name of object including price. */
+char *
+doname_with_price(obj)
+register struct obj *obj;
+{
+	return doname_base(obj, TRUE);
+}
+
 #endif /* OVL0 */
 #ifdef OVLB
@@ -854,4 +919,14 @@
 	return xname(obj);
 }
+#ifdef SORTLOOT
+char *
+cxname2(obj)
+struct obj *obj;
+{
+	if (obj->otyp == CORPSE)
+	    return corpse_xname(obj, TRUE);
+	return xname2(obj, TRUE);
+}
+#endif /* SORTLOOT */
 
 /* treat an object as fully ID'd when it might be used as reason for death */
@@ -1497,5 +1572,5 @@
 /* wishable subranges of objects */
 STATIC_OVL NEARDATA const struct o_range o_ranges[] = {
-	{ "bag",	TOOL_CLASS,   SACK,	      BAG_OF_TRICKS },
+	{ "bag",	  TOOL_CLASS,   SMALL_SACK,      BAG_OF_POO },
 	{ "lamp",	TOOL_CLASS,   OIL_LAMP,	      MAGIC_LAMP },
 	{ "candle",	TOOL_CLASS,   TALLOW_CANDLE,  WAX_CANDLE },
@@ -1722,8 +1797,13 @@
 	{ "leather armour", LEATHER_ARMOR },
 	{ "studded leather armour", STUDDED_LEATHER_ARMOR },
+	{ "spellbook of repair armour", SPE_REPAIR_ARMOR },
+	{ "spellbook of polymorph", SPE_POLYMORPH_CREATURE },
+	{ "spellbook of detect food", SPE_OBTAIN_FOOD },
 	{ "iron ball", HEAVY_IRON_BALL },
 	{ "lantern", BRASS_LANTERN },
+	{ "bag of poop", BAG_OF_POO },
 	{ "mattock", DWARVISH_MATTOCK },
 	{ "amulet of poison resistance", AMULET_VERSUS_POISON },
+	{ "salt", SALT_CHUNK },
 	{ "stone", ROCK },
 #ifdef TOURIST
@@ -1876,4 +1956,5 @@
 		} else if (!strncmpi(bp, "rusty ", l=6) ||
 			   !strncmpi(bp, "rusted ", l=7) ||
+			   !strncmpi(bp, "melted ", l=7) ||
 			   !strncmpi(bp, "burnt ", l=6) ||
 			   !strncmpi(bp, "burned ", l=7)) {
@@ -2333,10 +2414,4 @@
 			return(&zeroobj);
 		}
-		if(!BSTRCMP(bp, p-6, "throne")) {
-			levl[u.ux][u.uy].typ = THRONE;
-			pline("A throne.");
-			newsym(u.ux, u.uy);
-			return(&zeroobj);
-		}
 # ifdef SINKS
 		if(!BSTRCMP(bp, p-4, "sink")) {
@@ -2463,5 +2538,5 @@
 
 	if (islit &&
-		(typ == OIL_LAMP || typ == MAGIC_LAMP || typ == BRASS_LANTERN ||
+		(typ == OIL_LAMP || typ == MAGIC_LAMP || typ == BRASS_LANTERN || typ == BAG_OF_POO ||
 		 Is_candle(otmp) || typ == POT_OIL)) {
 	    place_object(otmp, u.ux, u.uy);  /* make it viable light source */
@@ -2517,5 +2592,5 @@
 		case SLIME_MOLD: otmp->spe = ftype;
 			/* Fall through */
-		case SKELETON_KEY: case CHEST: case LARGE_BOX:
+		case SKELETON_KEY: case CHEST: case LARGE_BOX: case IRON_SAFE:
 		case HEAVY_IRON_BALL: case IRON_CHAIN: case STATUE:
 			/* otmp->cobj already done in mksobj() */
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/src/o_init.c nethack/src/o_init.c
--- nh_orig/src/o_init.c	2003-12-07 18:39:13.000000000 -0500
+++ nethack/src/o_init.c	2010-08-16 13:20:13.409707335 -0400
@@ -175,4 +175,5 @@
 	shuffle_tiles();
 #endif
+	objects[WAN_NOTHING].oc_dir = rn2(2) ? IMMEDIATE : NODIR;
 }
 
@@ -214,8 +215,8 @@
 
 	/* shuffle the helmets */
-	shuffle(HELMET, HELM_OF_TELEPATHY, FALSE);
+	shuffle(HELMET, HELM_OF_CLARITY, FALSE);
 
 	/* shuffle the gloves */
-	shuffle(LEATHER_GLOVES, GAUNTLETS_OF_DEXTERITY, FALSE);
+	shuffle(LEATHER_GLOVES, GAUNTLETS_OF_FORTUNE, FALSE);
 
 	/* shuffle the cloaks */
@@ -407,5 +408,5 @@
 		ct++;
 		if (oclass != prev_class) {
-		    putstr(tmpwin, iflags.menu_headings, let_to_name(oclass, FALSE));
+		    putstr(tmpwin, iflags.menu_headings, let_to_name(oclass, FALSE, FALSE));
 		    prev_class = oclass;
 		}
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/src/options.c nethack/src/options.c
--- nh_orig/src/options.c	2003-12-07 18:39:13.000000000 -0500
+++ nethack/src/options.c	2010-08-16 13:20:13.486708170 -0400
@@ -76,4 +76,5 @@
 # endif
 	{"confirm",&flags.confirm, TRUE, SET_IN_GAME},
+	{"dark_room", &iflags.dark_room, TRUE, SET_IN_GAME},
 #if defined(TERMLIB) && !defined(MAC_GRAPHICS_ENV)
 	{"DECgraphics", &iflags.DECgraphics, FALSE, SET_IN_GAME},
@@ -126,4 +127,18 @@
 	{"mail", (boolean *)0, TRUE, SET_IN_FILE},
 #endif
+#ifdef MENU_COLOR
+# ifdef MICRO
+	{"menucolors", &iflags.use_menu_color, TRUE,  SET_IN_GAME},
+# else
+	{"menucolors", &iflags.use_menu_color, FALSE, SET_IN_GAME},
+# endif
+#else
+	{"menucolors", (boolean *)0, FALSE, SET_IN_GAME},
+#endif
+#if defined(STATUS_COLORS) && defined(TEXTCOLOR)
+	{"statuscolors", &iflags.use_status_colors, TRUE, SET_IN_GAME},
+#else
+	{"statuscolors", (boolean *)0, TRUE, SET_IN_GAME},
+#endif
 #ifdef WIZARD
 	/* for menu debugging only*/
@@ -161,4 +176,5 @@
 	{"sanity_check", (boolean *)0, FALSE, SET_IN_FILE},
 #endif
+	{"show_dgn_name", &iflags.show_dgn_name, TRUE, SET_IN_GAME},
 #ifdef EXP_ON_BOTL
 	{"showexp", &flags.showexp, FALSE, SET_IN_GAME},
@@ -166,5 +182,9 @@
 	{"showexp", (boolean *)0, FALSE, SET_IN_FILE},
 #endif
+	{"show_obj_sym", &iflags.showobjsym, TRUE, SET_IN_GAME},
 	{"showrace", &iflags.showrace, FALSE, SET_IN_GAME},
+#ifdef REALTIME_ON_BOTL
+  {"showrealtime", &iflags.showrealtime, FALSE, SET_IN_GAME},
+#endif
 #ifdef SCORE_ON_BOTL
 	{"showscore", &flags.showscore, FALSE, SET_IN_GAME},
@@ -187,6 +207,9 @@
 #endif
 	{"tombstone",&flags.tombstone, TRUE, SET_IN_GAME},
-	{"toptenwin",&flags.toptenwin, FALSE, SET_IN_GAME},
+#if 0
+	{"toptenwin",&flags.toptenwin, FALSE, SET_IN_GAME},  /* TODO: fix HUP bug */
+#endif
 	{"travel", &iflags.travelcmd, TRUE, SET_IN_GAME},
+	{"use_darkgray", &iflags.wc2_darkgray, FALSE, SET_IN_FILE},
 #ifdef WIN32CON
 	{"use_inverse",   &iflags.wc_inverse, TRUE, SET_IN_GAME},		/*WC*/
@@ -216,4 +239,5 @@
 	{ "align_status", "status window alignment", 20, DISP_IN_GAME }, 	/*WC*/
 	{ "altkeyhandler", "alternate key handler", 20, DISP_IN_GAME },
+	{ "boom_flightpath", "the default boomerang flight path", 1, SET_IN_GAME},
 	{ "boulder",  "the symbol to use for displaying boulders",
 						1, SET_IN_GAME },
@@ -225,4 +249,12 @@
 	{ "dogname",  "the name of your (first) dog (e.g., dogname:Fang)",
 						PL_PSIZ, DISP_IN_GAME },
+#ifdef DUMP_LOG
+	{ "dumpfile", "where to dump data (e.g., dumpfile:/tmp/dump.nh)",
+#ifdef DUMP_FN
+						PL_PSIZ, DISP_IN_GAME },
+#else
+						PL_PSIZ, SET_IN_GAME },
+#endif
+#endif
 	{ "dungeon",  "the symbols to use in drawing the dungeon map",
 						MAXDCHARS+1, SET_IN_FILE },
@@ -247,4 +279,5 @@
 						PL_PSIZ, DISP_IN_GAME },
 	{ "map_mode", "map display mode under Windows", 20, DISP_IN_GAME },	/*WC*/
+	{ "menucolor", "set menu colors", PL_PSIZ, SET_IN_FILE },
 	{ "menustyle", "user interface for object selection",
 						MENUTYPELEN, SET_IN_GAME },
@@ -307,7 +340,11 @@
 						20, DISP_IN_GAME }, /*WC*/
 	{ "scroll_margin", "scroll map when this far from the edge", 20, DISP_IN_GAME }, /*WC*/
+#ifdef SORTLOOT
+	{ "sortloot", "sort object selection lists by description", 4, SET_IN_GAME },
+#endif
 #ifdef MSDOS
 	{ "soundcard", "type of sound card to use", 20, SET_IN_FILE },
 #endif
+	{ "statuscolor", "set status colors", PL_PSIZ, SET_IN_FILE },
 	{ "suppress_alert", "suppress alerts about version-specific features",
 						8, SET_IN_GAME },
@@ -509,4 +546,5 @@
 	iflags.runmode = RUN_LEAP;
 	iflags.msg_history = 20;
+	iflags.boom_flight_path = -1;
 #ifdef TTY_GRAPHICS
 	iflags.prevmsg_window = 's';
@@ -539,4 +577,8 @@
 	flags.pickup_burden = MOD_ENCUMBER;
 
+#ifdef SORTLOOT
+	iflags.sortloot = 'n';
+#endif
+
 	for (i = 0; i < NUM_DISCLOSURE_OPTIONS; i++)
 		flags.end_disclose[i] = DISCLOSE_PROMPT_DEFAULT_NO;
@@ -604,4 +646,10 @@
 	obj_descr[SLIME_MOLD].oc_name = "fruit";
 
+	if (iflags.dark_room && iflags.use_color) {
+	    showsyms[S_darkroom] = showsyms[S_room];
+	} else {
+	    showsyms[S_darkroom] = showsyms[S_stone];
+	}
+
 	return;
 }
@@ -886,5 +934,5 @@
 		Sprintf(buf, "%lu.%lu.%lu", FEATURE_NOTICE_VER_MAJ,
 			FEATURE_NOTICE_VER_MIN, FEATURE_NOTICE_VER_PATCH);
-		pline("Feature change alerts disabled for NetHack %s features and prior.",
+		pline("Feature change alerts disabled for SporkHack %s features and prior.",
 			buf);
 	}
@@ -892,4 +940,163 @@
 }
 
+#if defined(STATUS_COLORS) && defined(TEXTCOLOR)
+
+struct name_value {
+	char *name;
+	int value;
+};
+
+const struct name_value status_colornames[] = {
+	{ "black",	CLR_BLACK },
+	{ "red",	CLR_RED },
+	{ "green",	CLR_GREEN },
+	{ "brown",	CLR_BROWN },
+	{ "blue",	CLR_BLUE },
+	{ "magenta",	CLR_MAGENTA },
+	{ "cyan",	CLR_CYAN },
+	{ "gray",	CLR_GRAY },
+	{ "orange",	CLR_ORANGE },
+	{ "lightgreen",	CLR_BRIGHT_GREEN },
+	{ "yellow",	CLR_YELLOW },
+	{ "lightblue",	CLR_BRIGHT_BLUE },
+	{ "lightmagenta", CLR_BRIGHT_MAGENTA },
+	{ "lightcyan",	CLR_BRIGHT_CYAN },
+	{ "white",	CLR_WHITE },
+	{ NULL,		-1 }
+};
+
+const struct name_value status_attrnames[] = {
+	 { "none",	ATR_NONE },
+	 { "bold",	ATR_BOLD },
+	 { "dim",	ATR_DIM },
+	 { "underline",	ATR_ULINE },
+	 { "blink",	ATR_BLINK },
+	 { "inverse",	ATR_INVERSE },
+	 { NULL,	-1 }
+};
+
+int
+value_of_name(name, name_values)
+const char *name;
+const struct name_value *name_values;
+{
+	while (name_values->name && !strstri(name_values->name, name))
+		++name_values;
+	return name_values->value;
+}
+
+struct color_option
+parse_color_option(start)
+char *start;
+{
+	struct color_option result = {NO_COLOR, 0};
+	char last;
+	char *end;
+	int attr;
+
+	for (end = start; *end != '&' && *end != '\0'; ++end);
+	last = *end;
+	*end = '\0';
+	result.color = value_of_name(start, status_colornames);
+
+	while (last == '&') {
+		for (start = ++end; *end != '&' && *end != '\0'; ++end);
+		last = *end;
+		*end = '\0';
+		attr = value_of_name(start, status_attrnames);
+		if (attr >= 0)
+			result.attr_bits |= 1 << attr;
+	}
+
+	return result;
+}
+
+const struct percent_color_option *hp_colors = NULL;
+const struct percent_color_option *pw_colors = NULL;
+const struct text_color_option *text_colors = NULL;
+
+struct percent_color_option *
+add_percent_option(new_option, list_head)
+struct percent_color_option *new_option;
+struct percent_color_option *list_head;
+{
+	if (list_head == NULL)
+		return new_option;
+	if (new_option->percentage <= list_head->percentage) {
+		new_option->next = list_head;
+		return new_option;
+	}
+	list_head->next = add_percent_option(new_option, list_head->next);
+	return list_head;
+}
+
+boolean
+parse_status_color_option(start)
+char *start;
+{
+	char *middle;
+
+	while (*start && isspace(*start)) start++;
+	for (middle = start; *middle != ':' && *middle != '=' && *middle != '\0'; ++middle);
+	*middle++ = '\0';
+	if (middle - start > 2 && start[2] == '%') {
+		struct percent_color_option *percent_color_option =
+			(struct percent_color_option *)alloc(sizeof(*percent_color_option));
+		percent_color_option->next = NULL;
+		percent_color_option->percentage = atoi(start + 3);
+		percent_color_option->color_option = parse_color_option(middle);
+		start[2] = '\0';
+		if (percent_color_option->color_option.color >= 0
+		 && percent_color_option->color_option.attr_bits >= 0) {
+			if (!strcmpi(start, "hp")) {
+				hp_colors = add_percent_option(percent_color_option, hp_colors);
+				return TRUE;
+			}
+			if (!strcmpi(start, "pw")) {
+				pw_colors = add_percent_option(percent_color_option, pw_colors);
+				return TRUE;
+			}
+		}
+		free(percent_color_option);
+		return FALSE;
+	} else {
+		int length = strlen(start) + 1;
+		struct text_color_option *text_color_option =
+			(struct text_color_option *)alloc(sizeof(*text_color_option));
+		text_color_option->next = NULL;
+		text_color_option->text = (char *)alloc(length);
+		memcpy((char *)text_color_option->text, start, length);
+		text_color_option->color_option = parse_color_option(middle);
+		if (text_color_option->color_option.color >= 0
+		 && text_color_option->color_option.attr_bits >= 0) {
+			text_color_option->next = text_colors;
+			text_colors = text_color_option;
+			return TRUE;
+		}
+		free((void*)text_color_option->text);
+		free(text_color_option);
+		return FALSE;
+	}
+}
+
+boolean
+parse_status_color_options(start)
+char *start;
+{
+	char last = ',';
+	char *end = start - 1;
+	boolean ok = TRUE;
+	while (last == ',') {
+		for (start = ++end; *end != ',' && *end != '\0'; ++end);
+		last = *end;
+		*end = '\0';
+		ok = parse_status_color_option(start) && ok;
+	}
+	return ok;
+}
+
+
+#endif /* STATUS_COLORS */
+
 void
 set_duplicate_opt_detection(on_or_off)
@@ -965,4 +1172,131 @@
 }
 
+#ifdef MENU_COLOR
+extern struct menucoloring *menu_colorings;
+
+static const struct {
+   const char *name;
+   const int color;
+} colornames[] = {
+   {"black", CLR_BLACK},
+   {"red", CLR_RED},
+   {"green", CLR_GREEN},
+   {"brown", CLR_BROWN},
+   {"blue", CLR_BLUE},
+   {"magenta", CLR_MAGENTA},
+   {"cyan", CLR_CYAN},
+   {"gray", CLR_GRAY},
+   {"orange", CLR_ORANGE},
+   {"lightgreen", CLR_BRIGHT_GREEN},
+   {"yellow", CLR_YELLOW},
+   {"lightblue", CLR_BRIGHT_BLUE},
+   {"lightmagenta", CLR_BRIGHT_MAGENTA},
+   {"lightcyan", CLR_BRIGHT_CYAN},
+   {"white", CLR_WHITE}
+};
+
+static const struct {
+   const char *name;
+   const int attr;
+} attrnames[] = {
+     {"none", ATR_NONE},
+     {"bold", ATR_BOLD},
+     {"dim", ATR_DIM},
+     {"underline", ATR_ULINE},
+     {"blink", ATR_BLINK},
+     {"inverse", ATR_INVERSE}
+
+};
+
+/* parse '"regex_string"=color&attr' and add it to menucoloring */
+boolean
+add_menu_coloring(str)
+char *str;
+{
+    int i, c = NO_COLOR, a = ATR_NONE;
+    struct menucoloring *tmp;
+    char *tmps, *cs = strchr(str, '=');
+#ifdef MENU_COLOR_REGEX_POSIX
+    int errnum;
+    char errbuf[80];
+#endif
+    const char *err = (char *)0;
+
+    if (!cs || !str) return FALSE;
+
+    tmps = cs;
+    tmps++;
+    while (*tmps && isspace(*tmps)) tmps++;
+
+    for (i = 0; i < SIZE(colornames); i++)
+	if (strstri(tmps, colornames[i].name) == tmps) {
+	    c = colornames[i].color;
+	    break;
+	}
+    if ((i == SIZE(colornames)) && (*tmps >= '0' && *tmps <='9'))
+	c = atoi(tmps);
+
+    if (c > 15) return FALSE;
+
+    tmps = strchr(str, '&');
+    if (tmps) {
+	tmps++;
+	while (*tmps && isspace(*tmps)) tmps++;
+	for (i = 0; i < SIZE(attrnames); i++)
+	    if (strstri(tmps, attrnames[i].name) == tmps) {
+		a = attrnames[i].attr;
+		break;
+	    }
+	if ((i == SIZE(attrnames)) && (*tmps >= '0' && *tmps <='9'))
+	    a = atoi(tmps);
+    }
+
+    *cs = '\0';
+    tmps = str;
+    if ((*tmps == '"') || (*tmps == '\'')) {
+	cs--;
+	while (isspace(*cs)) cs--;
+	if (*cs == *tmps) {
+	    *cs = '\0';
+	    tmps++;
+	}
+    }
+
+    tmp = (struct menucoloring *)alloc(sizeof(struct menucoloring));
+#ifdef MENU_COLOR_REGEX
+#ifdef MENU_COLOR_REGEX_POSIX
+    errnum = regcomp(&tmp->match, tmps, REG_EXTENDED | REG_NOSUB);
+    if (errnum != 0)
+    {
+	regerror(errnum, &tmp->match, errbuf, sizeof(errbuf));
+	err = errbuf;
+    }
+#else
+    tmp->match.translate = 0;
+    tmp->match.fastmap = 0;
+    tmp->match.buffer = 0;
+    tmp->match.allocated = 0;
+    tmp->match.regs_allocated = REGS_FIXED;
+    err = re_compile_pattern(tmps, strlen(tmps), &tmp->match);
+#endif
+#else
+    tmp->match = (char *)alloc(strlen(tmps)+1);
+    (void) memcpy((genericptr_t)tmp->match, (genericptr_t)tmps, strlen(tmps)+1);
+#endif
+    if (err) {
+	raw_printf("\nMenucolor regex error: %s\n", err);
+	wait_synch();
+	free(tmp);
+	return FALSE;
+    } else {
+	tmp->next = menu_colorings;
+	tmp->color = c;
+	tmp->attr = a;
+	menu_colorings = tmp;
+	return TRUE;
+    }
+}
+#endif /* MENU_COLOR */
+
 void
 parseoptions(opts, tinitial, tfrom_file)
@@ -1078,4 +1412,17 @@
 	}
 
+#ifdef DUMP_LOG
+	fullname = "dumpfile";
+	if (match_optname(opts, fullname, 3, TRUE)) {
+#ifndef DUMP_FN
+		if (negated) bad_negation(fullname, FALSE);
+		else if ((op = string_for_opt(opts, !tfrom_file)) != 0
+			&& strlen(op) > 1)
+			nmcpy(dump_fn, op, PL_PSIZ);
+#endif
+		return;
+       }
+#endif
+
 	fullname = "horsename";
 	if (match_optname(opts, fullname, 5, TRUE)) {
@@ -1134,4 +1481,16 @@
 	}
 
+	/* menucolor:"regex_string"=color */
+	fullname = "menucolor";
+	if (match_optname(opts, fullname, 9, TRUE)) {
+#ifdef MENU_COLOR
+	    if (negated) bad_negation(fullname, FALSE);
+	    else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0)
+		if (!add_menu_coloring(op))
+		    badoption(opts);
+#endif
+	    return;
+	}
+
 	fullname = "msghistory";
 	if (match_optname(opts, fullname, 3, TRUE)) {
@@ -1451,4 +1810,24 @@
 		return;
 	}
+
+	fullname = "boom_flightpath";
+	if (match_optname(opts, fullname, 4, TRUE)) {
+	    int val = -1;
+	    if (negated) {
+		bad_negation(fullname, FALSE);
+		return;
+	    }
+	    if (!(opts = string_for_opt(opts, FALSE)))
+		return;
+	    switch (opts[0]) {
+	    case '0': case 'r': val = 0; break;
+	    case '1': case 'l': val = 1; break;
+	    case '2': case 's': val = 2; break;
+	    case '3': case 'x': val = 3; break;
+	    default: break;
+	    }
+	    iflags.boom_flight_path = val;
+	}
+
 	/* boulder:symbol */
 	fullname = "boulder";
@@ -1649,5 +2028,5 @@
 	if (match_optname(opts, "pickup_types", 8, TRUE)) {
 		char ocl[MAXOCLASSES + 1], tbuf[MAXOCLASSES + 1],
-		     qbuf[QBUFSZ], abuf[BUFSZ];
+		     qbuf[QBUFSZ], abuf[BUFSZ] = "";
 		int oc_sym;
 		boolean badopt = FALSE, compat = (strlen(opts) <= 6), use_menu;
@@ -1840,4 +2219,33 @@
 	}
 
+#ifdef SORTLOOT
+	fullname = "sortloot";
+	if (match_optname(opts, fullname, 4, TRUE)) {
+		op = string_for_env_opt(fullname, opts, FALSE);
+		if (op) {
+			switch (tolower(*op)) {
+                        case 'n':
+                        case 'l':
+                        case 'f': iflags.sortloot = tolower(*op);
+				break;
+                        default:  badoption(opts);
+				return;
+			}
+		}
+		return;
+	}
+#endif /* SORTLOOT */
+
+	fullname = "statuscolor";
+	if (match_optname(opts, fullname, 11, TRUE)) {
+#if defined(STATUS_COLORS) && defined(TEXTCOLOR)
+		if (negated) bad_negation(fullname, FALSE);
+		else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0)
+			if (!parse_status_color_options(op))
+				badoption(opts);
+#endif
+	    return;
+	}
+	
 	fullname = "suppress_alert";
 	if (match_optname(opts, fullname, 4, TRUE)) {
@@ -2211,5 +2619,6 @@
 			}
 #endif
-			else if ((boolopt[i].addr) == &flags.lit_corridor) {
+			else if (((boolopt[i].addr) == &flags.lit_corridor) ||
+			         ((boolopt[i].addr) == &iflags.dark_room)) {
 			    /*
 			     * All corridor squares seen via night vision or
@@ -2221,4 +2630,5 @@
 			    vision_recalc(2);		/* shut down vision */
 			    vision_full_recalc = 1;	/* delayed recalc */
+			    if (iflags.use_color) need_redraw = TRUE;  /* darkroom refresh */
 			}
 			else if ((boolopt[i].addr) == &iflags.use_inverse ||
@@ -2264,4 +2674,10 @@
 };
 
+#ifdef SORTLOOT
+static NEARDATA const char *sortltype[] = {
+	"none", "loot", "full"
+};
+#endif
+
 /*
  * Convert the given string of object classes to a string of default object
@@ -2370,5 +2786,5 @@
 doset()
 {
-	char buf[BUFSZ], buf2[BUFSZ];
+	char buf[BUFSZ], buf2[BUFSZ] = "";
 	int i, pass, boolcount, pick_cnt, pick_idx, opt_indx;
 	boolean *bool_p;
@@ -2507,4 +2923,5 @@
 							setinitial, fromfile)) {
 			Sprintf(buf, "Set %s to what?", compopt[opt_indx].name);
+			if (buf2[0] == '\033') buf2[0] = '\0';
 			getlin(buf, buf2);
 			if (buf2[0] == '\033')
@@ -2524,6 +2941,12 @@
 
 	destroy_nhwindow(tmpwin);
-	if (need_redraw)
+	if (need_redraw) {
+	    if (iflags.dark_room && iflags.use_color) {
+		showsyms[S_darkroom]=showsyms[S_room];
+	    } else {
+		showsyms[S_darkroom]=showsyms[S_stone];
+	    }
 	    (void) doredraw();
+	}
 	return 0;
 }
@@ -2541,5 +2964,5 @@
     
     /* Special handling of menustyle, pickup_burden, pickup_types,
-     * disclose, runmode, msg_window, menu_headings, and number_pad options.
+     * disclose, runmode, msg_window, menu_headings, number_pad and sortloot
 #ifdef AUTOPICKUP_EXCEPTIONS
      * Also takes care of interactive autopickup_exception_handling changes.
@@ -2566,4 +2989,7 @@
 	destroy_nhwindow(tmpwin);
         retval = TRUE;
+    } else if (!strcmp("boom_flightpath", optname)) {
+	iflags.boom_flight_path = boom_flightpath_menu();
+	retval = TRUE;
     } else if (!strcmp("pickup_burden", optname)) {
 	const char *burden_name, *burden_letters = "ubsntl";
@@ -2696,4 +3122,24 @@
 	destroy_nhwindow(tmpwin);
         retval = TRUE;
+#ifdef SORTLOOT
+    } else if (!strcmp("sortloot", optname)) {
+	const char *sortl_name;
+	menu_item *sortl_pick = (menu_item *)0;
+	tmpwin = create_nhwindow(NHW_MENU);
+	start_menu(tmpwin);
+	for (i = 0; i < SIZE(sortltype); i++) {
+	    sortl_name = sortltype[i];
+	    any.a_char = *sortl_name;
+	    add_menu(tmpwin, NO_GLYPH, &any, *sortl_name, 0,
+		     ATR_NONE, sortl_name, MENU_UNSELECTED);
+	}
+	end_menu(tmpwin, "Select loot sorting type:");
+	if (select_menu(tmpwin, PICK_ONE, &sortl_pick) > 0) {
+	    iflags.sortloot = sortl_pick->item.a_char;
+	    free((genericptr_t)sortl_pick);
+	}
+	destroy_nhwindow(tmpwin);
+	retval = TRUE;
+#endif
     }
 #endif
@@ -2799,5 +3245,5 @@
 	menu_item *pick_list = (menu_item *)0;
 	anything any;
-	char apebuf[BUFSZ];
+	char apebuf[BUFSZ] = "";
 	struct autopickup_exception *ape;
 	static const char *action_titles[] = {
@@ -2919,4 +3365,6 @@
 		Sprintf(buf, "%c", iflags.bouldersym ?
 			iflags.bouldersym : oc_syms[(int)objects[BOULDER].oc_class]);
+	else if (!strcmp(optname, "boom_flightpath"))
+	    Sprintf(buf, "%i", iflags.boom_flight_path);
 	else if (!strcmp(optname, "catname")) 
 		Sprintf(buf, "%s", catname[0] ? catname : none );
@@ -2934,4 +3382,8 @@
 	else if (!strcmp(optname, "dogname")) 
 		Sprintf(buf, "%s", dogname[0] ? dogname : none );
+#ifdef DUMP_LOG
+	else if (!strcmp(optname, "dumpfile"))
+		Sprintf(buf, "%s", dump_fn[0] ? dump_fn: none );
+#endif
 	else if (!strcmp(optname, "dungeon"))
 		Sprintf(buf, "%s", to_be_done);
@@ -3073,4 +3525,15 @@
 		else Strcpy(buf, defopt);
 	}
+#ifdef SORTLOOT
+	else if (!strcmp(optname, "sortloot")) {
+		char *sortname = (char *)NULL;
+		for (i=0; i < SIZE(sortltype) && sortname==(char *)NULL; i++) {
+		   if (iflags.sortloot == sortltype[i][0])
+		     sortname = (char *)sortltype[i];
+		}
+		if (sortname != (char *)NULL)
+		   Sprintf(buf, "%s", sortname);
+	}
+#endif
 	else if (!strcmp(optname, "player_selection"))
 		Sprintf(buf, "%s", iflags.wc_player_selection ? "prompts" : "dialog");
@@ -3266,5 +3729,5 @@
 static const char *opt_intro[] = {
 	"",
-	"                 NetHack Options Help:",
+	"                 SporkHack Options Help:",
 	"",
 #define CONFIG_SLOT 3	/* fill in next value at run-time */
@@ -3594,4 +4057,5 @@
 	{"softkeyboard", WC2_SOFTKEYBOARD},
 	{"wraptext", WC2_WRAPTEXT},
+	{"use_darkgray", WC2_DARKGRAY},
 	{(char *)0, 0L}
 };
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/src/pager.c nethack/src/pager.c
--- nh_orig/src/pager.c	2003-12-07 18:39:13.000000000 -0500
+++ nethack/src/pager.c	2010-04-29 10:53:23.921715802 -0400
@@ -135,5 +135,5 @@
 
 	    pm = mtmp->data;
-	    Sprintf(buf, "%s%s%s",
+	    Sprintf(buf, "%s%s%s%s%s",
 		    (mtmp->mx != x || mtmp->my != y) ?
 			((mtmp->isshk && accurate)
@@ -141,4 +141,8 @@
 		    (mtmp->mtame && accurate) ? "tame " :
 		    (mtmp->mpeaceful && accurate) ? "peaceful " : "",
+			 /* don't show 'flying' unless they're not a natural flier */
+			 (is_flying(mtmp) && !is_flyer(mtmp->data) && accurate) ? "flying " : "",
+			 /* don't show 'berserk' unless they've had the spell cast on them */
+			 (mtmp->mberserk && !is_berserker(mtmp->data) && accurate) ? "enraged " : "",
 		    name);
 	    if (u.ustuck == mtmp)
@@ -262,5 +266,5 @@
 	Strcpy(buf, defsyms[trap_to_defsym(tnum)].explanation);
     } else if(!glyph_is_cmap(glyph)) {
-	Strcpy(buf,"dark part of a room");
+	Strcpy(buf,"unexplored area");
     } else switch(glyph_to_cmap(glyph)) {
     case S_altar:
@@ -459,5 +463,5 @@
     boolean quick;	/* use cursor && don't search for "more info" */
 {
-    char    out_str[BUFSZ], look_buf[BUFSZ];
+    char    out_str[BUFSZ] = "", look_buf[BUFSZ];
     const char *x_str, *firstmatch = 0;
     struct permonst *pm = 0;
@@ -625,5 +629,5 @@
 	}
 
-#define is_cmap_trap(i) ((i) >= S_arrow_trap && (i) <= S_polymorph_trap)
+#define is_cmap_trap(i) ((i) >= S_arrow_trap && (i) <= S_magic_beam_trap)
 #define is_cmap_drawbridge(i) ((i) >= S_vodbridge && (i) <= S_hcdbridge)
 
@@ -632,6 +636,6 @@
 	    x_str = defsyms[i].explanation;
 	    if (sym == (from_screen ? showsyms[i] : defsyms[i].sym) && *x_str) {
-		/* avoid "an air", "a water", or "a floor of a room" */
-		int article = (i == S_room) ? 2 :		/* 2=>"the" */
+		/* avoid "an air", "a water", "a floor of a room", "a dark part of a room" */
+		int article = ((i == S_room)||(i == S_darkroom)) ? 2 :		/* 2=>"the" */
 			      !(strcmp(x_str, "air") == 0 ||	/* 1=>"an"  */
 				strcmp(x_str, "water") == 0);	/* 0=>(none)*/
@@ -729,4 +733,10 @@
 	/* Finally, print out our explanation. */
 	if (found) {
+		/* Really lame hijack, but... */
+		if (christmas() && strstri(out_str,"(tree)")) {
+			char temp_buf[BUFSZ];
+			Sprintf(temp_buf," (with little colored balls on it)");
+			(void)strncat(out_str, temp_buf, BUFSZ-strlen(out_str)-1);
+		}
 	    pline("%s", out_str);
 	    /* check the data file for information about this thing */
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/src/pickup.c nethack/src/pickup.c
--- nh_orig/src/pickup.c	2003-12-07 18:39:13.000000000 -0500
+++ nethack/src/pickup.c	2010-08-16 13:20:13.437708572 -0400
@@ -39,4 +39,5 @@
 STATIC_DCL boolean FDECL(able_to_loot, (int, int));
 STATIC_DCL boolean FDECL(mon_beside, (int, int));
+STATIC_DCL int FDECL(dump_container, (struct obj*, BOOLEAN_P));
 
 /* define for query_objlist() and autopickup() */
@@ -160,5 +161,5 @@
 #endif
 {
-	char ilets[20], inbuf[BUFSZ];
+	char ilets[20], inbuf[BUFSZ] = "";
 	int iletct, oclassct;
 	boolean not_everything;
@@ -268,5 +269,5 @@
 	/* If there are objects here, take a look. */
 	if (ct) {
-	    if (flags.run) nomul(0);
+	    if (flags.run) nomul(0, 0);
 	    flush_screen(1);
 	    (void) look_here(ct, picked_some);
@@ -366,5 +367,5 @@
 {
 	return((boolean)(!!(otmp->owornmask &
-			(W_ARMOR | W_RING | W_AMUL | W_TOOL | W_WEP | W_SWAPWEP | W_QUIVER)))
+			(W_ARMOR | W_RING | W_AMUL | W_TOOL | W_WEP | W_SWAPWEP | W_QUIVER | W_LAUNCHER)))
 	        && (index(valid_menu_classes, otmp->oclass) != (char *)0));
 }
@@ -441,5 +442,5 @@
 
 		/* if there's anything here, stop running */
-		if (OBJ_AT(u.ux,u.uy) && flags.run && flags.run != 8 && !flags.nopick) nomul(0);
+		if (OBJ_AT(u.ux,u.uy) && flags.run && flags.run != 8 && !flags.nopick) nomul(0, 0);
 	}
 
@@ -691,7 +692,13 @@
 boolean FDECL((*allow), (OBJ_P));/* allow function */
 {
+#ifdef SORTLOOT
+	int i, j;
+#endif
 	int n;
 	winid win;
 	struct obj *curr, *last;
+#ifdef SORTLOOT
+	struct obj **oarray;
+#endif
 	char *pack;
 	anything any;
@@ -718,4 +725,31 @@
 	}
 
+#ifdef SORTLOOT
+	/* Make a temporary array to store the objects sorted */
+	oarray = (struct obj **)alloc(n*sizeof(struct obj*));
+
+	/* Add objects to the array */
+	i = 0;
+	for (curr = olist; curr; curr = FOLLOW(curr, qflags)) {
+	  if ((*allow)(curr)) {
+	    if (iflags.sortloot == 'f' ||
+		(iflags.sortloot == 'l' && !(qflags & USE_INVLET)))
+	      {
+		/* Insert object at correct index */
+		for (j = i; j; j--)
+		  {
+		    if (strcmpi(cxname2(curr), cxname2(oarray[j-1]))>0) break;
+		    oarray[j] = oarray[j-1];
+		  }
+		oarray[j] = curr;
+		i++;
+	      } else {
+		/* Just add it to the array */
+		oarray[i++] = curr;
+	      }
+	  }
+	}
+#endif /* SORTLOOT */
+
 	win = create_nhwindow(NHW_MENU);
 	start_menu(win);
@@ -731,5 +765,10 @@
 	do {
 	    printed_type_name = FALSE;
+#ifdef SORTLOOT
+	    for (i = 0; i < n; i++) {
+		curr = oarray[i];
+#else /* SORTLOOT */
 	    for (curr = olist; curr; curr = FOLLOW(curr, qflags)) {
+#endif /* SORTLOOT */
 		if ((qflags & FEEL_COCKATRICE) && curr->otyp == CORPSE &&
 		     will_feel_cockatrice(curr, FALSE)) {
@@ -745,5 +784,5 @@
 			any.a_obj = (struct obj *) 0;
 			add_menu(win, NO_GLYPH, &any, 0, 0, iflags.menu_headings,
-					let_to_name(*pack, FALSE), MENU_UNSELECTED);
+				 let_to_name(*pack, FALSE, iflags.showobjsym), MENU_UNSELECTED);
 			printed_type_name = TRUE;
 		    }
@@ -753,5 +792,5 @@
 			    qflags & USE_INVLET ? curr->invlet : 0,
 			    def_oc_syms[(int)objects[curr->otyp].oc_class],
-			    ATR_NONE, doname(curr), MENU_UNSELECTED);
+			    ATR_NONE, doname_with_price(curr), MENU_UNSELECTED);
 		}
 	    }
@@ -759,4 +798,7 @@
 	} while (qflags & INVORDER_SORT && *pack);
 
+#ifdef SORTLOOT
+	free(oarray);
+#endif
 	end_menu(win, qstr);
 	n = select_menu(win, how, pick_list);
@@ -827,5 +869,5 @@
 	    for (curr = olist; curr; curr = FOLLOW(curr, qflags)) {
 		if ((qflags & WORN_TYPES) &&
-		    !(curr->owornmask & (W_ARMOR|W_RING|W_AMUL|W_TOOL|W_WEP|W_SWAPWEP|W_QUIVER)))
+		    !(curr->owornmask & (W_ARMOR|W_RING|W_AMUL|W_TOOL|W_WEP|W_SWAPWEP|W_QUIVER|W_LAUNCHER)))
 		    continue;
 		break;
@@ -862,5 +904,5 @@
 		   if ((qflags & WORN_TYPES) &&
 		   		!(curr->owornmask & (W_ARMOR | W_RING | W_AMUL | W_TOOL |
-		    	W_WEP | W_SWAPWEP | W_QUIVER)))
+		    	W_WEP | W_SWAPWEP | W_QUIVER | W_LAUNCHER)))
 			 continue;
 		   if (!collected_type_name) {
@@ -869,5 +911,5 @@
 			add_menu(win, NO_GLYPH, &any, invlet++,
 				def_oc_syms[(int)objects[curr->otyp].oc_class],
-				ATR_NONE, let_to_name(*pack, FALSE),
+				 ATR_NONE, let_to_name(*pack, FALSE, iflags.showobjsym),
 				MENU_UNSELECTED);
 			collected_type_name = TRUE;
@@ -961,5 +1003,5 @@
 		   if ((qflags & WORN_TYPES) &&
 		    	!(curr->owornmask & (W_ARMOR | W_RING | W_AMUL | W_TOOL |
-		    	W_WEP | W_SWAPWEP | W_QUIVER)))
+		    	W_WEP | W_SWAPWEP | W_QUIVER | W_LAUNCHER)))
 			 continue;
 		   if (!counted_category) {
@@ -1302,5 +1344,5 @@
 	    }
 	    flags.botl = 1;
-	    if (flags.run) nomul(0);
+	    if (flags.run) nomul(0, 0);
 	    return 1;
 #endif
@@ -1562,4 +1604,12 @@
 		}
 
+		if (cobj->otyp == BAG_OF_POO) {
+			You("carefully open the bag...");
+			pline("This bag is full of %s poo and gives off a horrific stench.",rndmonnam());
+			makeknown(BAG_OF_POO);
+			timepassed = 1;
+			continue;
+		}
+
 		You("carefully open %s...", the(xname(cobj)));
 		timepassed |= use_container(cobj, 0);
@@ -1585,5 +1635,5 @@
 	    freeinv(goldob);
 #endif
-	    if (IS_THRONE(levl[u.ux][u.uy].typ)){
+	    if (sobj_at(FUR_THRONE,u.ux,u.uy)){
 		struct obj *coffers;
 		int pass;
@@ -1591,5 +1641,5 @@
 		for (pass = 2; pass > -1; pass -= 2)
 		    for (coffers = fobj; coffers; coffers = coffers->nobj)
-			if (coffers->otyp == CHEST && coffers->spe == pass)
+			if ((coffers->otyp == CHEST || coffers->otyp == IRON_SAFE) && coffers->spe == pass)
 			    goto gotit;	/* two level break */
 gotit:
@@ -1743,18 +1793,18 @@
 {
     /* these won't cause an explosion when they're empty */
-    if ((obj->otyp == WAN_CANCELLATION || obj->otyp == BAG_OF_TRICKS) &&
-	    obj->spe <= 0)
+    if ((obj->otyp == WAN_CANCELLATION || obj->otyp == BAG_OF_TRICKS) && obj->spe <= 0){
 	return FALSE;
+	 }
 
-    /* odds: 1/1, 2/2, 3/4, 4/8, 5/16, 6/32, 7/64, 8/128, 9/128, 10/128,... */
-    if ((Is_mbag(obj) || obj->otyp == WAN_CANCELLATION) &&
-	(rn2(1 << (depthin > 7 ? 7 : depthin)) <= depthin))
+    /* odds: 1/1  (DSR 9/23/09: just be mean, it's not like the stuff will be gone anymore) */
+    if (Is_mbag(obj) || obj->otyp == WAN_CANCELLATION) {
 	return TRUE;
-    else if (Has_contents(obj)) {
+	 } else if (Has_contents(obj)) {
 	struct obj *otmp;
 
-	for (otmp = obj->cobj; otmp; otmp = otmp->nobj)
+		for (otmp = obj->cobj; otmp; otmp = otmp->nobj) {
 	    if (mbag_explodes(otmp, depthin+1)) return TRUE;
     }
+	 }
     return FALSE;
 }
@@ -1773,4 +1823,5 @@
 	boolean was_unpaid = FALSE;
 	char buf[BUFSZ];
+	long one_item_weight = obj->quan < 2 ? obj->owt : (obj->owt / obj->quan);
 
 	if (!current_container) {
@@ -1792,4 +1843,5 @@
 		return 0;
 	} else if (obj->otyp == AMULET_OF_YENDOR ||
+			obj->otyp == FAKE_AMULET_OF_YENDOR ||
 		   obj->otyp == CANDELABRUM_OF_INVOCATION ||
 		   obj->otyp == BELL_OF_OPENING ||
@@ -1804,4 +1856,11 @@
 		pline("%s attached to your pet.", Tobjnam(obj, "are"));
 		return 0;
+	} else if (obj->owt + get_container_weight(current_container) > current_container->capacity) {
+		pline("You can't seem to fit %s into %s; it's too full.",
+				doname(obj),doname(current_container));
+		return -1;
+	} else if (current_container->otyp == SMALL_SACK && (one_item_weight > 30 || is_spear(obj))) {
+		pline("You aren't going to be able to wedge %s in there.",doname(obj));
+		return -1;
 	} else if (obj == uwep) {
 		if (welded(obj)) {
@@ -1818,4 +1877,10 @@
 		if (uquiver) return 0;     /* unwielded, died, rewielded */
 	}
+	/* it's possible for this to also be uwep since ulauncher
+	 * is a virtual, not a physical location on the player */
+	if (obj == ulauncher) {
+		setulauncher((struct obj *) 0);
+		if (ulauncher) return 0;  
+	}
 
 	if (obj->otyp == CORPSE) {
@@ -1879,17 +1944,14 @@
 	} else if (Is_mbag(current_container) && mbag_explodes(obj, 0)) {
 		/* explicitly mention what item is triggering the explosion */
-		pline(
-	      "As you put %s inside, you are blasted by a magical explosion!",
-		      doname(obj));
+		pline( "As you put %s inside, you are blasted by a magical explosion!", doname(obj));
 		/* did not actually insert obj yet */
 		if (was_unpaid) addtobill(obj, FALSE, FALSE, TRUE);
 		obfree(obj, (struct obj *)0);
-		delete_contents(current_container);
-		if (!floor_container)
-			useup(current_container);
-		else if (obj_here(current_container, u.ux, u.uy))
-			useupf(current_container, obj->quan);
-		else
-			panic("in_container:  bag not found.");
+
+		/* dump it out onto the floor so the scatterage can take effect */
+		if (dump_container(current_container, TRUE)) {
+			pline("The contents fly everywhere!");
+		}
+		scatter(u.ux,u.uy,10,VIS_EFFECTS|MAY_HIT|MAY_DESTROY|MAY_FRACTURE,0);
 
 		losehp(d(6,6),"magical explosion", KILLED_BY_AN);
@@ -2102,5 +2164,5 @@
 	    /* even if the trap fails, you've used up this turn */
 	    if (multi >= 0) {	/* in case we didn't become paralyzed */
-		nomul(-1);
+		nomul(-1, "opening a container");
 		nomovemsg = "";
 	    }
@@ -2415,3 +2477,56 @@
 }
 
+/* Dumps out a container, possibly as the prelude/result of an explosion.
+ * destroy_after trashes the container afterwards; try not to use it :P
+ *
+ * Player is assumed to not be handling the contents directly.
+ *
+ * Returns 1 if at least one object was present, 0 if empty.
+ */ 
+int
+dump_container(container, destroy_after)
+struct obj* container;
+BOOLEAN_P destroy_after;
+{
+	struct obj* otmp,*otmp2;
+	int ret = 0;
+
+	/* sanity check */
+	if (!container) { return 0; }
+
+	for (otmp = container->cobj; otmp; otmp = otmp2)
+	{
+		ret = 1;
+		otmp2 = otmp->nobj;
+		obj_extract_self(otmp);
+		container->owt = weight(container);
+
+		/* we do need to start the timer on these */
+		if (container->otyp == ICE_BOX && !age_is_relative(otmp)) {
+			otmp->age = monstermoves - otmp->age;
+			if (otmp->otyp == CORPSE) {
+				start_corpse_timeout(otmp);
+			}
+		}
+		place_object(otmp,u.ux,u.uy);
+
+		if (otmp->otyp == GOLD_PIECE) {
+#ifndef GOLDOBJ
+			dealloc_obj(otmp);
+#endif
+			bot();	/* update character's gold piece count immediately */
+		}
+	}
+
+	if (destroy_after) {
+		if (container->where == OBJ_INVENT) {
+			useup(container);
+		} else if (obj_here(container, u.ux, u.uy)) {
+			useupf(container, container->quan);
+		}
+	}
+
+	return ret;
+}
+
 /*pickup.c*/
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/src/pline.c nethack/src/pline.c
--- nh_orig/src/pline.c	2003-12-07 18:39:13.000000000 -0500
+++ nethack/src/pline.c	2009-08-02 13:49:38.692407855 -0400
@@ -16,4 +16,9 @@
 static char *FDECL(You_buf, (int));
 
+#if defined(DUMP_LOG) && defined(DUMPMSGS)
+char msgs[DUMPMSGS][BUFSZ];
+int lastmsg = -1;
+#endif
+
 /*VARARGS1*/
 /* Note that these declarations rely on knowledge of the internals
@@ -56,4 +61,10 @@
 	    line = pbuf;
 	}
+#if defined(DUMP_LOG) && defined(DUMPMSGS)
+	if (DUMPMSGS > 0 && !program_state.gameover) {
+	  lastmsg = (lastmsg + 1) % DUMPMSGS;
+	  strncpy(msgs[lastmsg], line, BUFSZ);
+	}
+#endif
 	if (!iflags.window_inited) {
 	    raw_print(line);
@@ -258,5 +269,5 @@
 	}
 	vpline(s,VA_ARGS);
-	pline("Program in disorder - perhaps you'd better #quit.");
+	pline("Program in disorder; you probably should S)ave and restart the process.");
 	program_state.in_impossible = 0;
 	VA_END();
@@ -312,4 +323,5 @@
 	if (mtmp->mstun)	  Strcat(info, ", stunned");
 	if (mtmp->msleeping)	  Strcat(info, ", asleep");
+	if (mtmp->mflying && !is_flyer(mtmp->data)) { Strcat(info,", flying"); }
 #if 0	/* unfortunately mfrozen covers temporary sleep and being busy
 	   (donning armor, for instance) as well as paralysis */
@@ -400,4 +412,5 @@
 	if (Fast)		Strcat(info, Very_fast ?
 						", very fast" : ", fast");
+	if (Slow)		Strcat(info, ", slow");
 	if (u.uundetected)	Strcat(info, ", concealed");
 	if (Invis)		Strcat(info, ", invisible");
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/src/polyself.c nethack/src/polyself.c
--- nh_orig/src/polyself.c	2003-12-07 18:39:13.000000000 -0500
+++ nethack/src/polyself.c	2010-04-29 10:53:23.920716055 -0400
@@ -167,6 +167,5 @@
 	 */
 #ifndef LINT
-	u.uhpmax = ((u.uhpmax - 10) * (long)u.ulevel / oldlvl + 10) +
-		(9 - rn2(19));
+	u.uhpmax = ((u.uhpmax - 10) * (long)u.ulevel / oldlvl + 10) + (9 - rn2(19));
 #endif
 
@@ -222,5 +221,5 @@
 boolean forcecontrol;     
 {
-	char buf[BUFSZ];
+	static char buf[BUFSZ] = "";
 	int old_light, new_light;
 	int mntmp = NON_PM;
@@ -245,6 +244,9 @@
 	if (Polymorph_control || forcecontrol) {
 		do {
+		    if (buf[0] == '\033') buf[0] = 0;
 			getlin("Become what kind of monster? [type the name]",
 				buf);
+			stripctrl(buf);
+			trim(buf);
 			mntmp = name_to_mon(buf);
 			if (mntmp < LOW_PM)
@@ -730,5 +732,5 @@
 	}
 	if (!uarmg) selftouch("No longer petrify-resistant, you");
-	nomul(0);
+	nomul(0, 0);
 
 	flags.botl = 1;
@@ -1006,5 +1008,5 @@
 			if((int) u.ulevel > rn2(25))
 			    (void) destroy_mitem(mtmp, SPBOOK_CLASS, AD_FIRE);
-			if (dmg && !DEADMONSTER(mtmp)) mtmp->mhp -= dmg;
+			if (dmg && !DEADMONSTER(mtmp)) damage_mon(mtmp,dmg,AD_FIRE);
 			if (mtmp->mhp <= 0) killed(mtmp);
 		    }
@@ -1020,5 +1022,5 @@
 				    -d((int)mtmp->m_lev+1,
 					    (int)mtmp->data->mattk[0].damd)
-				    : -200);
+				    : -200, "frozen by a monster's gaze");
 			    return 1;
 			} else
@@ -1098,5 +1100,5 @@
 				telepathic(mtmp->data) ? "latent telepathy" :
 				"mind");
-			mtmp->mhp -= rnd(15);
+			damage_mon(mtmp,rnd(15),AD_DRIN);
 			if (mtmp->mhp <= 0)
 				killed(mtmp);
@@ -1327,4 +1329,7 @@
 	    case GREEN_DRAGON_SCALES:
 		return PM_GREEN_DRAGON;
+	    case GOLD_DRAGON_SCALE_MAIL:
+	    case GOLD_DRAGON_SCALES:
+		return PM_GOLD_DRAGON;
 	    case YELLOW_DRAGON_SCALE_MAIL:
 	    case YELLOW_DRAGON_SCALES:
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/src/potion.c nethack/src/potion.c
--- nh_orig/src/potion.c	2003-12-07 18:39:13.000000000 -0500
+++ nethack/src/potion.c	2010-05-11 11:04:36.506714072 -0400
@@ -54,4 +54,86 @@
 }
 
+/* increase a partial-resistance intrinsic by XX%
+ * ...will automatically cap at 100% */
+void
+incr_resistance(which, incr)
+long* which;
+int incr;
+{
+	long oldval = *which & TIMEOUT;
+	if (oldval + incr > 100) { 
+		oldval = 100; 
+	} else {
+		oldval += incr;
+	}
+	*which &= ~TIMEOUT;
+	*which |= (oldval | HAVEPARTIAL);
+
+}
+
+/* decrease a partial-resistance intrinsic by XX% */
+void
+decr_resistance(which, incr)
+long* which;
+int incr;
+{
+	long oldval = *which & TIMEOUT;
+	if (oldval - incr < 0) { 
+		oldval = 0; 
+	} else {
+		oldval -= incr;
+	}
+	*which &= ~TIMEOUT;
+	*which |= (oldval | ((oldval < 1) ? 0 : HAVEPARTIAL));
+
+}
+
+/* Return percent which a player is resistant -- 100% if from external/race/etc. */
+int
+how_resistant(which)
+int which;
+{
+	int val;
+
+	/* externals and level/race based intrinsics always provide 100%
+	 * as do monster resistances */
+	if (u.uprops[which].extrinsic || 
+			(u.uprops[which].intrinsic & (FROMEXPER|FROMRACE)) ||
+			(youmonst.mintrinsics & (1 << (which-1)))) {	  /* depends on FIRE_RES/MR_FIRE order matching! */
+		val = 100; 
+	} else {
+		/* None of this is necessary, but this is going in without a savebreak
+		* so people might load save files that have values higher than 100 */
+		val = (u.uprops[which].intrinsic & TIMEOUT);
+		if (val > 100) {
+			val = 100;
+			u.uprops[which].intrinsic &= ~TIMEOUT;
+			u.uprops[which].intrinsic |= (val|HAVEPARTIAL);
+		}
+	}
+
+	/* vulnerability will affect things... */
+	switch (which) {
+		case FIRE_RES:	 if (Vulnerable_fire) { val -= 50; } break;
+		case COLD_RES:	 if (Vulnerable_cold) { val -= 50; } break;
+		case SHOCK_RES: if (Vulnerable_elec) { val -= 50; } break;
+		case ACID_RES:	 if (Vulnerable_acid) { val -= 50; } break;
+		default: break;
+	}
+
+	return val;
+}
+
+/* Handles the damage-reduction shuffle necessary to convert 80% resistance
+ * into 20% damage (and keeps the floating-point silliness out of the main lines */
+int
+resist_reduce(amount,which)
+int amount, which;
+{
+	float tmp = (float)(100 - how_resistant(which));
+	tmp /= 100;
+	return (int)((float)amount * tmp);
+}
+
 void
 make_confused(xtime,talk)
@@ -61,4 +143,9 @@
 	long old = HConfusion;
 
+	if (Confusion_resistance) { 
+		set_itimeout(&HConfusion, 0);
+		return; 
+	}
+
 	if (!xtime && old) {
 		if (talk)
@@ -78,4 +165,9 @@
 	long old = HStun;
 
+	if (Stun_resistance) { 
+		set_itimeout(&HStun, 0);
+		return; 
+	}
+
 	if (!xtime && old) {
 		if (talk)
@@ -95,4 +187,6 @@
 	if ((!xtime && old) || (xtime && !old)) flags.botl = TRUE;
 
+	/* Stops us from wandering around with travel while stunned */
+	nomul(0,0);
 	set_itimeout(&HStun, xtime);
 }
@@ -317,5 +411,5 @@
 	if(flags.verbose)
 	    You("are frightened to death, and unable to move.");
-	nomul(-3);
+	nomul(-3, "being frightened to death");
 	nomovemsg = "You regain your composure.";
 }
@@ -423,8 +517,6 @@
 		    break;
 		} else {
-		    pline("Wow!  This makes you feel %s!",
-			  (otmp->blessed) ?
-				(unfixable_trouble_count(FALSE) ? "better" : "great")
-			  : "good");
+		    pline("Wow!  This makes you feel %s!", (otmp->blessed) ?
+				(unfixable_trouble_count(FALSE) ? "better" : "great") : "good");
 		    i = rn2(A_MAX);		/* start at a random point */
 		    for (ii = 0; ii < A_MAX; ii++) {
@@ -444,5 +536,5 @@
 		if (Hallucination || Halluc_resistance) nothing++;
 		(void) make_hallucinated(itimeout_incr(HHallucination,
-					   rn1(200, 600 - 300 * bcsign(otmp))),
+					   rn1(otmp->odiluted ? 100 : 200, 600 - 300 * bcsign(otmp))),
 				  TRUE, 0L);
 		break;
@@ -543,6 +635,5 @@
 		    self_invis_message();
 		}
-		if (otmp->blessed) HInvis |= FROMOUTSIDE;
-		else incr_itimeout(&HInvis, rn1(15,31));
+		incr_itimeout(&HInvis, rn1(15,31*(otmp->blessed ? rnd(4) : 1)));
 		newsym(u.ux,u.uy);	/* update position */
 		if(otmp->cursed) {
@@ -578,8 +669,6 @@
 			make_blinded(0L,TRUE);
 		}
-		if (otmp->blessed)
-			HSee_invisible |= FROMOUTSIDE;
-		else
-			incr_itimeout(&HSee_invisible, rn1(100,750));
+		/* remove free permanent see-invis... */
+		incr_itimeout(&HSee_invisible, rn1(otmp->odiluted ? 50 : 100, otmp->blessed ? 1500: 750));
 		set_mimic_blocking(); /* do special mimic handling */
 		see_monsters();	/* see invisible monsters */
@@ -604,5 +693,5 @@
 			Your("%s are frozen to the %s!",
 			     makeplural(body_part(FOOT)), surface(u.ux, u.uy));
-		    nomul(-(rn1(10, 25 - 12*bcsign(otmp))));
+		    nomul(-(rn1(otmp->odiluted ? 5 : 10, 25 - 12*bcsign(otmp))), "frozen by a potion");
 		    nomovemsg = You_can_move_again;
 		    exercise(A_DEX, FALSE);
@@ -610,9 +699,14 @@
 		break;
 	case POT_SLEEPING:
-		if(Sleep_resistance || Free_action)
+		if(how_resistant(SLEEP_RES) == 100 || Free_action) {
+			/* Yes, this isn't technically accurate, but then, monsters don't
+			 * know that you just resisted a sleeping potion because of your ring,
+			 * now do they?  They just saw you drink it and nothing happened. */
+			monstseesu(M_SEEN_SLEEP);
 		    You("yawn.");
-		else {
+		} else {
 		    You("suddenly fall asleep!");
-		    fall_asleep(-rn1(10, 25 - 12*bcsign(otmp)), TRUE);
+		    fall_asleep(-resist_reduce(rn1(otmp->odiluted ? 5 : 10, 
+							 25 - 12*bcsign(otmp)),SLEEP_RES),TRUE);
 		}
 		break;
@@ -628,5 +722,5 @@
 			i = 1;
 		    else
-			i = rn1(40,21);
+			i = rn1(otmp->odiluted ? 20 : 40,21);
 		    incr_itimeout(&HDetect_monsters, i);
 		    for (x = 1; x < COLNO; x++) {
@@ -663,26 +757,22 @@
 		    }
 		} else {
-		    if(Poison_resistance)
-			pline(
-			  "(But in fact it was biologically contaminated %s.)",
-			      fruitname(TRUE));
-		    if (Role_if(PM_HEALER))
+		    if(how_resistant(POISON_RES) == 100)
+				pline( "(But in fact it was biologically contaminated %s.)", fruitname(TRUE));
+		    if (Role_if(PM_HEALER)) {
+				 monstseesu(M_SEEN_POISON);
 			pline("Fortunately, you have been immunized.");
-		    else {
+			 } else {
 			int typ = rn2(A_MAX);
 
 			if (!Fixed_abil) {
 			    poisontell(typ);
-			    (void) adjattrib(typ,
-			    		Poison_resistance ? -1 : -rn1(4,3),
+			    (void) adjattrib(typ, -(resist_reduce(rn1(4,3),POISON_RES)+1),
 			    		TRUE);
 			}
-			if(!Poison_resistance) {
+			if(how_resistant(POISON_RES) < 100) {
 			    if (otmp->fromsink)
-				losehp(rnd(10)+5*!!(otmp->cursed),
-				       "contaminated tap water", KILLED_BY);
+					losehp(resist_reduce(rnd(10)+5*!!(otmp->cursed),POISON_RES), "contaminated tap water", KILLED_BY);
 			    else
-				losehp(rnd(10)+5*!!(otmp->cursed),
-				       "contaminated potion", KILLED_BY_AN);
+					losehp(resist_reduce(rnd(10)+5*!!(otmp->cursed),POISON_RES), "contaminated potion", KILLED_BY_AN);
 			}
 			exercise(A_CON, FALSE);
@@ -703,5 +793,5 @@
 		else	nothing++;
 		make_confused(itimeout_incr(HConfusion,
-					    rn1(7, 16 - 8 * bcsign(otmp))),
+					    rn1(otmp->odiluted ? 4 : 7, 16 - 8 * bcsign(otmp))),
 			      FALSE);
 		break;
@@ -726,4 +816,12 @@
 		break;
 	case POT_SPEED:
+		/* only the potion will fix intrinsic 'slow' */
+		if (Slow) {
+			HSlow = 0;
+			if (!ESlow) {
+				You("no longer feel sluggish.");
+			}
+		}
+
 		if(Wounded_legs && !otmp->cursed
 #ifdef STEED
@@ -736,8 +834,8 @@
 		} /* and fall through */
 	case SPE_HASTE_SELF:
-		if(!Very_fast) /* wwf@doe.carleton.ca */
+		if(!Very_fast && !Slow) /* wwf@doe.carleton.ca */
 			You("are suddenly moving %sfaster.",
 				Fast ? "" : "much ");
-		else {
+		else if (!Slow) {
 			Your("%s get new energy.",
 				makeplural(body_part(LEG)));
@@ -745,10 +843,10 @@
 		}
 		exercise(A_DEX, TRUE);
-		incr_itimeout(&HFast, rn1(10, 100 + 60 * bcsign(otmp)));
+		incr_itimeout(&HFast, rn1(otmp->odiluted ? 5 : 10, 100 + 60 * bcsign(otmp)));
 		break;
 	case POT_BLINDNESS:
 		if(Blind) nothing++;
 		make_blinded(itimeout_incr(Blinded,
-					   rn1(200, 250 - 125 * bcsign(otmp))),
+					   rn1(otmp->odiluted ? 100 : 200, 250 - 125 * bcsign(otmp))),
 			     (boolean)!Blind);
 		break;
@@ -787,5 +885,5 @@
 	case POT_HEALING:
 		You_feel("better.");
-		healup(d(6 + 2 * bcsign(otmp), 4),
+		healup(d(10 + 2 * bcsign(otmp), 4) / (otmp->odiluted ? 2 : 1),
 		       !otmp->cursed ? 1 : 0, !!otmp->blessed, !otmp->cursed);
 		exercise(A_CON, TRUE);
@@ -793,6 +891,6 @@
 	case POT_EXTRA_HEALING:
 		You_feel("much better.");
-		healup(d(6 + 2 * bcsign(otmp), 8),
-		       otmp->blessed ? 5 : !otmp->cursed ? 2 : 0,
+		healup(d(10 + 2 * bcsign(otmp), 8) / (otmp->odiluted ? 2 : 1),
+		       (otmp->blessed ? 5 : !otmp->cursed ? 2 : 0) / (otmp->odiluted ? 2 : 1),
 		       !otmp->cursed, TRUE);
 		(void) make_hallucinated(0L,TRUE,0L);
@@ -802,5 +900,5 @@
 	case POT_FULL_HEALING:
 		You_feel("completely healed.");
-		healup(400, 4+4*bcsign(otmp), !otmp->cursed, TRUE);
+		healup(400, (4+4*bcsign(otmp)) / (otmp->odiluted ? 2 : 1), !otmp->cursed, TRUE);
 		/* Restore one lost level if blessed */
 		if (otmp->blessed && u.ulevel < u.ulevelmax) {
@@ -839,7 +937,7 @@
 			nothing++;
 		if (otmp->blessed) {
-		    incr_itimeout(&HLevitation, rn1(50,250));
+		    incr_itimeout(&HLevitation, rn1(otmp->odiluted ? 25 : 50,250));
 		    HLevitation |= I_SPECIAL;
-		} else incr_itimeout(&HLevitation, rn1(140,10));
+		} else incr_itimeout(&HLevitation, rn1(otmp->odiluted ? 70 : 140,10));
 		spoteffects(FALSE);	/* for sinks */
 		break;
@@ -852,5 +950,7 @@
 			num = rnd(5) + 5 * otmp->blessed + 1;
 			u.uenmax += (otmp->cursed) ? -num : num;
+			num = (otmp->odiluted ? 0 : rnd(75)) + 75 * otmp->blessed + 1;  /* make this part matter */
 			u.uen += (otmp->cursed) ? -num : num;
+			if(u.uen > u.uenmax) u.uen = u.uenmax;
 			if(u.uenmax <= 0) u.uenmax = 0;
 			if(u.uen <= 0) u.uen = 0;
@@ -869,6 +969,5 @@
 			    } else {
 				You("burn your %s.", body_part(FACE));
-				losehp(d(Fire_resistance ? 1 : 3, 4),
-				       "burning potion of oil", KILLED_BY_AN);
+					losehp(resist_reduce(d(2,4),FIRE_RES)+d(1,4), "burning potion of oil", KILLED_BY_AN);
 			    }
 			} else if(otmp->cursed)
@@ -880,8 +979,9 @@
 		break;
 	case POT_ACID:
-		if (Acid_resistance)
+		if (Acid_resistance) {
 			/* Not necessarily a creature who _likes_ acid */
 			pline("This tastes %s.", Hallucination ? "tangy" : "sour");
-		else {
+			monstseesu(M_SEEN_ACID);
+		} else {
 			pline("This burns%s!", otmp->blessed ? " a little" :
 					otmp->cursed ? " a lot" : " like acid");
@@ -897,4 +997,9 @@
 		if (!Unchanging) polyself(FALSE);
 		break;
+	case POT_SALT_WATER:
+		pline("Yuck... this is salt water!");
+		exercise(A_WIS, FALSE);
+		make_vomiting(Vomiting + rnd(10) + 5,TRUE);
+		break;
 	default:
 		impossible("What a funny potion! (%u)", otmp->otyp);
@@ -912,8 +1017,8 @@
 		if (Upolyd) {
 			u.mh += nhp;
-			if (u.mh > u.mhmax) u.mh = (u.mhmax += nxtra);
+			if (u.mh > u.mhmax) u.mh = gainmaxhp(nxtra);
 		} else {
 			u.uhp += nhp;
-			if(u.uhp > u.uhpmax) u.uhp = (u.uhpmax += nxtra);
+			if(u.uhp > u.uhpmax) u.uhp = gainmaxhp(nxtra);
 		}
 	}
@@ -988,5 +1093,5 @@
 		}
 		if(rn2(5) && mon->mhp > 1)
-			mon->mhp--;
+			damage_mon(mon,1,AD_PHYS);
 	}
 
@@ -1011,4 +1116,6 @@
 		    losehp(d(obj->cursed ? 2 : 1, obj->blessed ? 4 : 8),
 				    "potion of acid", KILLED_BY_AN);
+		} else {
+			monstseesu(M_SEEN_ACID);
 		}
 		break;
@@ -1095,5 +1202,5 @@
 			pline("%s %s in pain!", Monnam(mon),
 			      is_silent(mon->data) ? "writhes" : "shrieks");
-			mon->mhp -= d(2,6);
+			damage_mon(mon,d(2,6),AD_ACID);
 			/* should only be by you */
 			if (mon->mhp < 1) killed(mon);
@@ -1116,5 +1223,5 @@
 		    if (canseemon(mon))
 			pline("%s rusts.", Monnam(mon));
-		    mon->mhp -= d(1,6);
+			 damage_mon(mon,d(1,6),AD_PHYS);
 		    /* should only be by you */
 		    if (mon->mhp < 1) killed(mon);
@@ -1129,5 +1236,5 @@
 		    pline("%s %s in pain!", Monnam(mon),
 			  is_silent(mon->data) ? "writhes" : "shrieks");
-		    mon->mhp -= d(obj->cursed ? 2 : 1, obj->blessed ? 4 : 8);
+		    damage_mon(mon,d(obj->cursed ? 2 : 1, obj->blessed ? 4 : 8),AD_ACID);
 		    if (mon->mhp < 1) {
 			if (your_fault)
@@ -1256,5 +1363,5 @@
 		if (!Free_action) {
 		    pline("%s seems to be holding you.", Something);
-		    nomul(-rnd(5));
+		    nomul(-rnd(5), "frozen by a potion");
 		    nomovemsg = You_can_move_again;
 		    exercise(A_DEX, FALSE);
@@ -1263,13 +1370,16 @@
 	case POT_SLEEPING:
 		kn++;
-		if (!Free_action && !Sleep_resistance) {
+		if (!Free_action && how_resistant(SLEEP_RES) < 100) {
 		    You_feel("rather tired.");
-		    nomul(-rnd(5));
+		    nomul(-resist_reduce(rnd(5),SLEEP_RES), "sleeping off a magical draught");
 		    nomovemsg = You_can_move_again;
 		    exercise(A_DEX, FALSE);
-		} else You("yawn.");
+		} else {
+			monstseesu(M_SEEN_SLEEP);
+			You("yawn.");
+		}
 		break;
 	case POT_SPEED:
-		if (!Fast) Your("knees seem more flexible now.");
+		if (!Fast && !Slow) Your("knees seem more flexible now.");
 		incr_itimeout(&HFast, rnd(5));
 		exercise(A_DEX, TRUE);
@@ -1423,4 +1533,5 @@
 {
 	char Your_buf[BUFSZ];
+	struct obj* otmp;
 
 	if (snuff_lit(obj)) return(TRUE);
@@ -1504,4 +1615,18 @@
 		}
 		break;
+		 case GEM_CLASS:
+			if (obj->otyp == SALT_CHUNK) {
+				pline("The %s dissolves!",xname2(obj,TRUE));
+				makeknown(obj->otyp);
+				useup(obj);
+				otmp = mksobj(POT_SALT_WATER,TRUE,FALSE);
+				if (otmp) {
+					otmp->blessed = otmp->cursed = 0;
+					addinv(otmp);
+					update_inventory();
+				}
+				return TRUE;
+			}
+			break;
 	    case WEAPON_CLASS:
 	    /* Just "fall through" to generic rustprone check for now. */
@@ -1528,4 +1653,5 @@
 	struct obj *singlepotion;
 	const char *tmp;
+	const char* potion_descr;
 	uchar here;
 	char allowall[2];
@@ -1630,5 +1756,5 @@
 	    if (obj->otyp == potion->otyp ||	/* both POT_POLY */
 		    obj->otyp == WAN_POLYMORPH ||
-		    obj->otyp == SPE_POLYMORPH ||
+		    obj->otyp == SPE_POLYMORPH_CREATURE ||
 		    obj == uball || obj == uskin ||
 		    obj_resists(obj->otyp == POT_POLYMORPH ?
@@ -1636,5 +1762,6 @@
 		pline(nothing_happens);
 	    } else {
-	    	boolean was_wep = FALSE, was_swapwep = FALSE, was_quiver = FALSE;
+	    	boolean was_wep = FALSE, was_swapwep = FALSE, 
+					  was_quiver = FALSE, was_launcher = FALSE;
 		short save_otyp = obj->otyp;
 		/* KMH, conduct */
@@ -1644,4 +1771,5 @@
 		else if (obj == uswapwep) was_swapwep = TRUE;
 		else if (obj == uquiver) was_quiver = TRUE;
+		else if (obj == ulauncher) was_launcher = TRUE;
 
 		obj = poly_obj(obj, STRANGE_OBJECT);
@@ -1650,4 +1778,5 @@
 		else if (was_swapwep) setuswapwep(obj);
 		else if (was_quiver) setuqwep(obj);
+		else if (was_launcher) setulauncher(obj);
 
 		if (obj->otyp != save_otyp) {
@@ -1829,4 +1958,20 @@
     more_dips:
 
+	/* If a greasy potion wasn't something else, grease the dipped */
+	potion_descr = OBJ_DESCR(objects[potion->otyp]);
+	if (!strcmp(potion_descr,"greasy")) {
+		/* Drop through to "...Interesting" if you're dipping already greasy stuff */
+		if (!obj->greased) {
+			Your("%s %s covered with a thick layer of grease.",xname(obj),otense(obj, "are"));
+			obj->greased = 1;
+			if (potion->cursed && !nohands(youmonst.data)) {
+			    incr_itimeout(&Glib, rnd(10)+5);
+			    pline("Some of the grease gets all over your %s.",makeplural(body_part(HAND)));
+			}
+			useup(potion);
+			return 1;
+		}
+	}
+
 	/* Allow filling of MAGIC_LAMPs to prevent identification by player */
 	if ((obj->otyp == OIL_LAMP || obj->otyp == MAGIC_LAMP) &&
@@ -1993,4 +2138,7 @@
 		mtmp2->mhpmax = u.mhmax / 2;
 		u.mhmax -= mtmp2->mhpmax;
+		/* just in case we split some low hp critters */
+		if (mtmp2->mhpmax < 1) mtmp2->mhpmax = 1;
+		if (u.mhmax < 1) u.mhmax = 1;
 		flags.botl = 1;
 		You("multiply%s!", reason);
@@ -2001,4 +2149,7 @@
 		mtmp2->mhpmax = mon->mhpmax / 2;
 		mon->mhpmax -= mtmp2->mhpmax;
+		/* just in case we split some low hp critters */
+		if (mtmp2->mhpmax < 1) mtmp2->mhpmax = 1;
+		if (mon->mhpmax < 1) mon->mhpmax = 1;
 		if (canspotmon(mon))
 		    pline("%s multiplies%s!", Monnam(mon), reason);
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/src/pray.c nethack/src/pray.c
--- nh_orig/src/pray.c	2003-12-07 18:39:13.000000000 -0500
+++ nethack/src/pray.c	2010-05-13 09:22:21.971714041 -0400
@@ -173,6 +173,14 @@
 
 	/*
-	 * minor troubles
+	 * Minor troubles from here forward.
+	 * And Cavemen get another flavor kick: their god is also
+	 * a bit primitive, so they get a 20% chance of god being
+	 * asleep at the switch
 	 */
+
+	if (Role_if(PM_CAVEMAN) && !rn2(5)) {
+		return (0);
+	}
+
 	if(Punished) return(TROUBLE_PUNISHED);
 	if (Cursed_obj(uarmg, GAUNTLETS_OF_FUMBLING) ||
@@ -319,9 +327,9 @@
 		    You_feel("much better.");
 		    if (Upolyd) {
-			u.mhmax += rnd(5);
+				 gainmaxhp(rnd(5));
 			if (u.mhmax <= 5) u.mhmax = 5+1;
 			u.mh = u.mhmax;
 		    }
-		    if (u.uhpmax < u.ulevel * 5 + 11) u.uhpmax += rnd(5);
+		    if (u.uhpmax < u.ulevel * 5 + 11) gainmaxhp(rnd(5));
 		    if (u.uhpmax <= 5) u.uhpmax = 5+1;
 		    u.uhp = u.uhpmax;
@@ -481,10 +489,12 @@
 	    if (Reflecting) {
 		shieldeff(u.ux, u.uy);
+		monstseesu(M_SEEN_REFL);
 		if (Blind)
 		    pline("For some reason you're unaffected.");
 		else
 		    (void) ureflects("%s reflects from your %s.", "It");
-	    } else if (Shock_resistance) {
+	    } else if (how_resistant(SHOCK_RES) == 100) {
 		shieldeff(u.ux, u.uy);
+			monstseesu(M_SEEN_ELEC);
 		pline("It seems not to affect you.");
 	    } else
@@ -519,8 +529,9 @@
 	    if (uarmu && !uarm && !uarmc) (void) destroy_arm(uarmu);
 #endif
-	    if (!Disint_resistance)
+	    if (how_resistant(DISINT_RES) < 100)
 		fry_by_god(resp_god);
 	    else {
 		You("bask in its %s glow for a minute...", NH_BLACK);
+			monstseesu(M_SEEN_DISINT);
 		godvoice(resp_god, "I believe it not!");
 	    }
@@ -645,9 +656,10 @@
 
     HSee_invisible |= FROMOUTSIDE;
-    HFire_resistance |= FROMOUTSIDE;
-    HCold_resistance |= FROMOUTSIDE;
-    HShock_resistance |= FROMOUTSIDE;
-    HSleep_resistance |= FROMOUTSIDE;
-    HPoison_resistance |= FROMOUTSIDE;
+	 incr_resistance(&HFire_resistance,100);
+    incr_resistance(&HCold_resistance,100);
+    incr_resistance(&HShock_resistance,100);
+    incr_resistance(&HSleep_resistance,100);
+    incr_resistance(&HPoison_resistance,100);
+	 monstseesu(M_SEEN_FIRE|M_SEEN_COLD|M_SEEN_ELEC|M_SEEN_SLEEP|M_SEEN_POISON);
     godvoice(u.ualign.type, (char *)0);
 
@@ -727,4 +739,5 @@
 	    obj = mksobj(LONG_SWORD, FALSE, FALSE);
 	    obj = oname(obj, artiname(ART_VORPAL_BLADE));
+	    obj->oeroded = 0;
 	    obj->spe = 1;
 	    at_your_feet("A sword");
@@ -751,4 +764,5 @@
 	    obj = oname(obj, artiname(ART_STORMBRINGER));
 	    at_your_feet(An(swordbuf));
+	    obj->oeroded = 0;
 	    obj->spe = 1;
 	    dropy(obj);
@@ -769,6 +783,5 @@
     if (ok_wep(obj)) {
 	bless(obj);
-	obj->oeroded = obj->oeroded2 = 0;
-	obj->oerodeproof = TRUE;
+	set_erodeproof(obj);
 	obj->bknown = obj->rknown = TRUE;
 	if (obj->spe < 1) obj->spe = 1;
@@ -801,5 +814,5 @@
 	/* not your deity */
 	if (on_altar() && p_aligntyp != u.ualign.type) {
-		adjalign(-1);
+		major_sin();
 		return;
 	} else if (u.ualign.record < 2 && trouble <= 0) adjalign(1);
@@ -847,5 +860,8 @@
        fixed or there were no troubles to begin with; hallucination
        won't be in effect so special handling for it is superfluous */
-    if(pat_on_head)
+
+	 /* Cavemen may be ignored occasionally by god */
+
+    if(pat_on_head && (Role_if(PM_CAVEMAN) ? rn2(5) : 1))
 	switch(rn2((Luck + 6)>>1)) {
 	case 0:	break;
@@ -922,6 +938,5 @@
 		pluslvl(FALSE);
 	    } else {
-		u.uhpmax += 5;
-		if (Upolyd) u.mhmax += 5;
+			 gainmaxhp(5);	  /* no longer get base form benefit if selfpolied */
 	    }
 	    u.uhp = u.uhpmax;
@@ -1014,4 +1029,6 @@
 	default:	impossible("Confused deity!");
 	    break;
+	} else if (pat_on_head) {
+		You_feel("that %s is not entirely paying attention.", align_gname(g_align));
 	}
 
@@ -1207,17 +1224,34 @@
 			dmon->mpeaceful = TRUE;
 		    You("are terrified, and unable to move.");
-		    nomul(-3);
+		    nomul(-3, "being terrified of a demon");
 		} else pline_The("%s.", demonless_msg);
 	    }
 
 	    if (u.ualign.type != A_CHAOTIC) {
-		adjalign(-5);
+			 mortal_sin();
 		u.ugangr += 3;
 		(void) adjattrib(A_WIS, -1, TRUE);
 		if (!Inhell) angrygods(u.ualign.type);
 		change_luck(-5);
-	    } else adjalign(5);
+	    } else {
+			 adjalign(5);
+		 }
 	    if (carried(otmp)) useup(otmp);
 	    else useupf(otmp, 1L);
+
+		 /* create Dirge from player's longsword here if possible */
+		 if (u.ualign.type == A_CHAOTIC && Role_if(PM_KNIGHT) && 
+				 !u.ugangr && u.ualign.record > 0 &&
+				 uwep && uwep->otyp == LONG_SWORD && !uwep->oartifact &&
+				 !exist_artifact(LONG_SWORD, artiname(ART_DIRGE))) {
+
+			 uwep = oname(uwep, artiname(ART_DIRGE));
+			 bless(uwep);
+			 set_erodeproof(uwep);
+			 discover_artifact(ART_DIRGE);
+			 exercise(A_WIS,TRUE);
+			 pline("Your sword slithers in your hand and seems to change!");
+		 }
+
 	    return(1);
 	} else if (otmp->oxlth && otmp->oattached == OATTACHED_MONST
@@ -1227,5 +1261,5 @@
 	     * not a real monster */
 	    pline("So this is how you repay loyalty?");
-	    adjalign(-3);
+		 major_sin();
 	    value = -1;
 	    HAggravate_monster |= FROMOUTSIDE;
@@ -1242,5 +1276,6 @@
 		      ? "chaos" : unicalign ? "law" : "balance");
 		(void) adjattrib(A_WIS, -1, TRUE);
-		value = -5;
+			major_sin();
+			value = -1;
 	    } else if (u.ualign.type == altaralign) {
 		/* If different from altar, and altar is same as yours, */
@@ -1278,5 +1313,5 @@
 		/* And the opposing team picks you up and
 		   carries you off on their shoulders */
-		adjalign(-99);
+		adjalign(-2*ALIGNLIM);
 		pline("%s accepts your gift, and gains dominion over %s...",
 		      a_gname(), u_gname());
@@ -1286,6 +1321,22 @@
 		      hcolor((const char *)"orange"));
 		done(ESCAPED);
-	    } else { /* super big win */
+	    } else { 
+			/* Would this action put you in positive standing? */
 		adjalign(10);
+			/* You'd better hope so... */
+			if (u.ualign.record < 0) {
+				pline("%s accepts your gift...",a_gname());
+				godvoice(altaralign,"Mortal, thou art unworthy to join me!");
+				verbalize("Thou art no longer a follower of the path of %s, "
+						"and this I cannot forgive.",a_gname());
+				verbalize("I permit thee to retain thy treasure, but "
+						"thou shalt not be freed of this mortal coil.  BEGONE!");
+				pline("A cloud of %s smoke surrounds you...",hcolor((const char*)"orange"));
+				done(ESCAPED);
+			}
+			/* super big win */
+#ifdef RECORD_ACHIEVE
+			achieve.ascended = 1;
+#endif
 pline("An invisible choir sings, and you are bathed in radiance...");
 		godvoice(altaralign, "Congratulations, mortal!");
@@ -1311,5 +1362,5 @@
 		/* don't you dare try to fool the gods */
 		change_luck(-3);
-		adjalign(-1);
+		minor_sin();
 		u.ugangr += 3;
 		value = -3;
@@ -1366,5 +1417,5 @@
 		} else {
 		    u.ugangr += 3;
-		    adjalign(-5);
+			 major_sin();
 		    pline("%s rejects your sacrifice!", a_gname());
 		    godvoice(altaralign, "Suffer, infidel!");
@@ -1386,6 +1437,5 @@
 		    levl[u.ux][u.uy].altarmask &= AM_SHRINE;
 		    /* the following accommodates stupid compilers */
-		    levl[u.ux][u.uy].altarmask =
-			levl[u.ux][u.uy].altarmask | (Align2amask(u.ualign.type));
+		    levl[u.ux][u.uy].altarmask = levl[u.ux][u.uy].altarmask | (Align2amask(u.ualign.type));
 		    if (!Blind)
 			pline_The("altar glows %s.",
@@ -1393,12 +1443,20 @@
 			      u.ualign.type == A_LAWFUL ? NH_WHITE :
 			      u.ualign.type ? NH_BLACK : (const char *)"gray"));
-
-		    if (rnl(u.ulevel) > 6 && u.ualign.record > 0 &&
-		       rnd(u.ualign.record) > (3*ALIGNLIM)/4)
+			 /* 
+			  * The old test here started with "if rnl(u.ulevel) > 6", thus ensuring
+			  * that the vast majority of altars converted in the dungeon never,
+			  * EVER pissed off the owner due to the stilted effect of luck.
+			  *
+			  * We can fix that.  god should be pissed if you muck up his altars.
+			  * If you muck up his temples, he should be even more pissed.
+			  */
+		    if (u.ualign.record > 0 && rnd(u.ualign.record) > 
+					 (3*ALIGNLIM)/(temple_occupied(u.urooms) ? 12 : u.ulevel)) {
 			summon_minion(altaralign, TRUE);
+			 }
 		    /* anger priest; test handles bones files */
-		    if((pri = findpriest(temple_occupied(u.urooms))) &&
-		       !p_coaligned(pri))
+		    if((pri = findpriest(temple_occupied(u.urooms))) && !p_coaligned(pri)) {
 			angry_priest();
+			 }
 		} else {
 		    pline("Unluckily, you feel the power of %s decrease.",
@@ -1417,6 +1475,5 @@
 	/* OK, you get brownie points. */
 	if(u.ugangr) {
-	    u.ugangr -=
-		((value * (u.ualign.type == A_CHAOTIC ? 2 : 3)) / MAXVALUE);
+	    u.ugangr -= ((value * (u.ualign.type == A_CHAOTIC ? 2 : 3)) / MAXVALUE);
 	    if(u.ugangr < 0) u.ugangr = 0;
 	    if(u.ugangr != saved_anger) {
@@ -1424,15 +1481,12 @@
 		    pline("%s seems %s.", u_gname(),
 			  Hallucination ? "groovy" : "slightly mollified");
-
 		    if ((int)u.uluck < 0) change_luck(1);
 		} else {
 		    pline("%s seems %s.", u_gname(), Hallucination ?
 			  "cosmic (not a new fact)" : "mollified");
-
 		    if ((int)u.uluck < 0) u.uluck = 0;
 		}
 	    } else { /* not satisfied yet */
-		if (Hallucination)
-		    pline_The("gods seem tall.");
+			if (Hallucination) pline_The("gods seem tall.");
 		else You("have a feeling of inadequacy.");
 	    }
@@ -1443,6 +1497,5 @@
 	    You_feel("partially absolved.");
 	} else if (u.ublesscnt > 0) {
-	    u.ublesscnt -=
-		((value * (u.ualign.type == A_CHAOTIC ? 500 : 300)) / MAXVALUE);
+	    u.ublesscnt -= ((value * (u.ualign.type == A_CHAOTIC ? 500 : 300)) / MAXVALUE);
 	    if(u.ublesscnt < 0) u.ublesscnt = 0;
 	    if(u.ublesscnt != saved_cnt) {
@@ -1463,15 +1516,64 @@
 	} else {
 	    int nartifacts = nartifact_exist();
+		 int nchance = u.ulevel+6;
 
-	    /* you were already in pretty good standing */
-	    /* The player can gain an artifact */
-	    /* The chance goes down as the number of artifacts goes up */
-	    if (u.ulevel > 2 && u.uluck >= 0 &&
-		!rn2(10 + (2 * u.ugifts * nartifacts))) {
+	    /* you were already in pretty good standing
+		  *
+		  * The player can gain an artifact;
+	     * The chance goes down as the number of artifacts goes up.
+		  * 
+		  * The player can also get handed just a plain old hunk of weaponry
+		  * or piece of armor, but it will be blessed, +3 to +5, fire/rustproof, and 
+		  * if it's a weapon, it'll be in one of the player's available skill 
+		  * slots. The lower level you are, the more likely it is that you'll 
+		  * get a hunk of ordinary junk rather than an artifact.
+		  *
+		  * Note that no artifact is guaranteed; it's still subject to the
+		  * chances of generating one of those in the first place; these are
+		  * just the chances that an artifact will even be considered as a gift.
+		  *
+		  * level  4: 10% chance  level  9: 20% chance  level 12: 30% chance 
+		  * level 14: 40% chance  level 17: 50% chance  level 19: 60% chance 
+		  * level 21: 70% chance  level 23: 80% chance  level 24: 90% chance 
+		  * level 26: 100% chance
+		  */
+
+		 if (rn2(10) >= (nchance*nchance)/100) {
+			 if (u.uluck >= 0 && !rn2(6 + (2 * u.ugifts))) {
+				 int typ, ncount = 0; 
+				 if (rn2(2)) {
+					/* don't give unicorn horns or anything the player's restricted in */
+					do {
+						typ = rnd_class(SPEAR,CROSSBOW);
+					} while (ncount++ < 500 && typ && P_RESTRICTED(objects[typ].oc_skill));
+					if (ncount > 499) { return 1; }
+				 } else {
+					 typ = rnd_class(ELVEN_LEATHER_HELM,LEVITATION_BOOTS);
+				 }
+				 if (typ) {
+					otmp = mksobj(typ, FALSE, FALSE);
+					if (otmp) {
+						bless(otmp);
+						otmp->spe = rn2(3)+3; /* +3 to +5 */
+						if (u_gname() && strcmp(u_gname(), "Loki")) { /* Trickster */
+						    set_erodeproof(otmp);
+						}
+						dropy(otmp);
+						at_your_feet("An object");
+						godvoice(u.ualign.type, "Use this gift valorously!");
+						u.ugifts++;
+						u.ublesscnt = rnz(300 + (50 * u.ugifts));
+						exercise(A_WIS, TRUE);
+						makeknown(otmp->otyp);
+						return 1;
+					}
+				 }
+			 }
+		 } else if (u.uluck >= 0 && !rn2(10 + (2 * nartifacts))) {
 		otmp = mk_artifact((struct obj *)0, a_align(u.ux,u.uy));
 		if (otmp) {
 		    if (otmp->spe < 0) otmp->spe = 0;
 		    if (otmp->cursed) uncurse(otmp);
-		    otmp->oerodeproof = TRUE;
+				set_erodeproof(otmp);
 		    dropy(otmp);
 		    at_your_feet("An object");
@@ -1580,5 +1682,5 @@
     }
 #endif
-    nomul(-3);
+    nomul(-3, "praying");
     nomovemsg = "You finish your prayer.";
     afternmv = prayer_done;
@@ -1691,5 +1793,5 @@
 
 	/* note: does not perform unturn_dead() on victims' inventories */
-	range = BOLT_LIM + (u.ulevel / 5);	/* 5 to 11 */
+	range = 8 + (u.ulevel / 5);	/* 5 to 11 */
 	range *= range;
 	once = 0;
@@ -1740,5 +1842,5 @@
 	    }
 	}
-	nomul(-5);
+	nomul(-5, "trying to turn the monsters");
 	return(1);
 }
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/src/priest.c nethack/src/priest.c
--- nh_orig/src/priest.c	2003-12-07 18:39:13.000000000 -0500
+++ nethack/src/priest.c	2009-11-22 07:19:36.725397504 -0500
@@ -163,5 +163,5 @@
 
 	if(!priest->mpeaceful ||
-	   (Conflict && !resist(priest, RING_CLASS, 0, 0))) {
+	   (Conflict && !resist_conflict(priest))) {
 		if(monnear(priest, u.ux, u.uy)) {
 			if(Displaced)
@@ -252,13 +252,10 @@
 	Strcpy(pname, "the ");
 	if (mon->minvis) Strcat(pname, "invisible ");
-	if (mon->ispriest || mon->data == &mons[PM_ALIGNED_PRIEST] ||
-					mon->data == &mons[PM_ANGEL]) {
+	if (mon->ispriest || mon->data == &mons[PM_ALIGNED_PRIEST] || mon->data == &mons[PM_ANGEL]) {
 		/* use epri */
 		if (mon->mtame && mon->data == &mons[PM_ANGEL])
 			Strcat(pname, "guardian ");
-		if (mon->data != &mons[PM_ALIGNED_PRIEST] &&
-				mon->data != &mons[PM_HIGH_PRIEST]) {
+		if (mon->data != &mons[PM_ALIGNED_PRIEST] && mon->data != &mons[PM_HIGH_PRIEST]) {
 			Strcat(pname, what);
-			Strcat(pname, " ");
 		}
 		if (mon->data != &mons[PM_ANGEL]) {
@@ -274,6 +271,9 @@
 				Strcat(pname, "priest ");
 		}
+		/* You can't tell what kind of priest it is 'til you see them with your eyeballs. */
+		if (canseemon(mon)) {
 		Strcat(pname, "of ");
 		Strcat(pname, halu_gname((int)EPRI(mon)->shralign));
+		}
 		return(pname);
 	}
@@ -394,5 +394,5 @@
 		    if(flags.verbose)
 			You("are frightened to death, and unable to move.");
-		    nomul(-3);
+		    nomul(-3, "frightened to death");
 		    nomovemsg = "You regain your composure.";
 	       }
@@ -481,5 +481,5 @@
 	    if((offer = bribe(priest)) == 0) {
 		verbalize("Thou shalt regret thine action!");
-		if(coaligned) adjalign(-1);
+		if(coaligned) venial_sin();
 	    } else if(offer < (u.ulevel * 200)) {
 #ifndef GOLDOBJ
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/src/quest.c nethack/src/quest.c
--- nh_orig/src/quest.c	2003-12-07 18:39:13.000000000 -0500
+++ nethack/src/quest.c	2010-05-13 09:22:21.952715600 -0400
@@ -96,6 +96,9 @@
 ok_to_quest()
 {
-	return((boolean)((Qstat(got_quest) || Qstat(got_thanks)))
-			&& (is_pure(FALSE) > 0));
+	if (((Qstat(got_quest) || Qstat(got_thanks)) && is_pure(FALSE) > 0) ||
+		quest_status.leader_is_dead) {
+		return TRUE;
+	}
+	return FALSE;
 }
 
@@ -199,4 +202,5 @@
 	       quest artifact */
 	    fully_identify_obj(obj);
+	    set_erodeproof(obj);
 	    update_inventory();
 	}
@@ -240,5 +244,9 @@
 	    Qstat(met_leader) = TRUE;
 	    Qstat(not_ready) = 0;
-	  } else qt_pager(QT_NEXTLEADER);
+	  } else if (!Qstat(pissed_off)) {
+		  qt_pager(QT_NEXTLEADER);
+	  } else {
+		  verbalize("Your bones shall serve to warn others.");
+	  }
 	  /* the quest leader might have passed through the portal into
 	     the regular dungeon; none of the remaining make sense there */
@@ -250,16 +258,16 @@
 	    expulsion(FALSE);
 	  } else if(is_pure(TRUE) < 0) {
+		  /* don't keep lecturing once the player's been kicked out once. */
+		  if (!Qstat(pissed_off)) {
 	    com_pager(QT_BANISHED);
-	    expulsion(TRUE);
+			Qstat(pissed_off) = 1;
+			expulsion(FALSE);
+		  }
 	  } else if(is_pure(TRUE) == 0) {
+		  /* Don't end the game for too many tries anymore, that's silly */
 	    qt_pager(QT_BADALIGN);
-	    if(Qstat(not_ready) == MAX_QUEST_TRIES) {
-	      qt_pager(QT_LASTLEADER);
-	      expulsion(TRUE);
-	    } else {
-	      Qstat(not_ready)++;
+	 	Qstat(not_ready) = 1;
 	      exercise(A_WIS, TRUE);
 	      expulsion(FALSE);
-	    }
 	  } else {	/* You are worthy! */
 	    qt_pager(QT_ASSIGNQUEST);
@@ -276,5 +284,11 @@
 	/* maybe you attacked leader? */
 	if(!mtmp->mpeaceful) {
-		Qstat(pissed_off) = TRUE;
+		if (!Qstat(pissed_off)) {
+			/* again, don't end it permanently if the leader gets angry
+			* since you're going to have to kill him to go questing... :)
+			* ...but do only show this crap once. */
+			qt_pager(QT_LASTLEADER);
+		}
+		Qstat(pissed_off) = 1;
 		mtmp->mstrategy &= ~STRAT_WAITMASK;	/* end the inaction */
 	}
@@ -283,8 +297,12 @@
 	if (!on_level(&u.uz, &qstart_level)) return;
 
+	if(!Qstat(pissed_off)) chat_with_leader();
+
+	/* leader might have become pissed during the chat */
 	if(Qstat(pissed_off)) {
-	  qt_pager(QT_LASTLEADER);
-	  expulsion(TRUE);
-	} else chat_with_leader();
+		mtmp->mstrategy &= ~STRAT_WAITMASK;
+		mtmp->mpeaceful = 0;
+	}
+
 }
 
@@ -351,4 +369,9 @@
     if (mtmp->m_id == Qstat(leader_m_id)) {
 	chat_with_leader();
+		/* leader might have become pissed during the chat */
+		if(Qstat(pissed_off)) {
+			mtmp->mstrategy &= ~STRAT_WAITMASK;
+			mtmp->mpeaceful = 0;
+		}
 	return;
     }
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/src/questpgr.c nethack/src/questpgr.c
--- nh_orig/src/questpgr.c	2003-12-07 18:39:13.000000000 -0500
+++ nethack/src/questpgr.c	2009-10-04 19:50:51.069292957 -0400
@@ -289,8 +289,7 @@
 {
 	char *c, *cc;
-	char xbuf[BUFSZ];
 
 	cc = out_line;
-	for (c = xcrypt(in_line, xbuf); *c; c++) {
+	for (c = in_line; *c; c++) {
 
 	    *cc = 0;
@@ -356,4 +355,15 @@
 }
 
+char *
+string_subst(str)
+     char *str;
+{
+    strncpy(in_line, str, 79);
+    in_line[79] = '\0';
+    convert_line();
+    return out_line;
+}
+
+
 STATIC_OVL void
 deliver_by_pline(qt_msg)
@@ -361,7 +371,9 @@
 {
 	long	size;
+	char xbuf[BUFSZ];
 
 	for (size = 0; size < qt_msg->size; size += (long)strlen(in_line)) {
-	    (void) dlb_fgets(in_line, 80, msg_file);
+	    (void) dlb_fgets(xbuf, 80, msg_file);
+	    (void) xcrypt(xbuf, in_line);
 	    convert_line();
 	    pline(out_line);
@@ -376,8 +388,10 @@
 {
 	long	size;
+	char xbuf[BUFSZ];
 	winid datawin = create_nhwindow(how);
 
 	for (size = 0; size < qt_msg->size; size += (long)strlen(in_line)) {
-	    (void) dlb_fgets(in_line, 80, msg_file);
+	    (void) dlb_fgets(xbuf, 80, msg_file);
+	    (void) xcrypt(xbuf, in_line);
 	    convert_line();
 	    putstr(datawin, 0, out_line);
@@ -423,20 +437,4 @@
 }
 
-struct permonst *
-qt_montype()
-{
-	int qpm;
-
-	if (rn2(5)) {
-	    qpm = urole.enemy1num;
-	    if (qpm != NON_PM && rn2(5) && !(mvitals[qpm].mvflags & G_GENOD))
-	    	return (&mons[qpm]);
-	    return (mkclass(urole.enemy1sym, 0));
-	}
-	qpm = urole.enemy2num;
-	if (qpm != NON_PM && rn2(5) && !(mvitals[qpm].mvflags & G_GENOD))
-	    return (&mons[qpm]);
-	return (mkclass(urole.enemy2sym, 0));
-}
 
 /*questpgr.c*/
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/src/read.c nethack/src/read.c
--- nh_orig/src/read.c	2003-12-07 18:39:13.000000000 -0500
+++ nethack/src/read.c	2010-08-29 07:52:40.524707821 -0400
@@ -74,4 +74,63 @@
     "Furinkan High School Athletic Dept.",	/* Ranma 1/2 */
     "Hel-LOOO, Nurse!",			/* Animaniacs */
+
+    "=^.^=",
+    "100% goblin hair - do not wash",
+    "Aberzombie and Fitch",
+    "Aim >>> <<< here",
+    "cK -- Cockatrice touches the Kop",
+    "Croesus for President 2008 - Campaign Finance Reform Now (for the other guy)",
+    "- - - - - - CUT HERE - - - - - -",
+    "Don't ask me, I only adventure here",
+    "Down With Pants!",
+    "d, your dog or a killer?",
+    "FREE PUG AND NEWT!",
+    "Gehennoms Angels",
+    "Glutton For Punishment",
+    "Go Team Ant!",
+    "Got Newt?",
+    "Heading for Godhead",
+    "Hey! Nymphs! Steal This T-Shirt!",
+    "I <3 Dungeon of Doom",
+    "I <3 Maud",
+    "I am a Valkyrie. If you see me running, try to keep up.",
+    "I Am Not a Pack Rat - I Am a Collector",
+    "I bounced off a rubber tree",
+    "If you can read this, I can hit you with my polearm",
+    "I'm Confused!",
+    "I met Carl, the swordmaster of Jambalaya island and all I got was this lousy t-shirt",
+    "I'm in ur base, killin ur doods",
+    "I scored with the princess",
+    "I Support Single Succubi",
+    "I want to live forever or die in the attempt.",
+    "Kop Killaz",
+    "Lichen Park",
+    "LOST IN THOUGHT - please send search party",
+    "Meat Is Mordor",
+    "Minetown Better Business Bureau",
+    "Minetown Watch",
+    "Ms. Palm's House of Negotiable Affection -- A Very Reputable House Of Disrepute",
+    "^^  My eyes are up there!  ^^",
+    "Neferet/Pelias '08",
+    "Next time you wave at me, use more than one finger, please.",
+    "No Outfit Is Complete Without a Little Cat Fur",
+    "Objects In This Shirt Are Closer Than They Appear",
+    "Protection Racketeer",
+    "P Happens",
+    "Real men love Crom",
+    "Rodney in '08. OR ELSE!",
+    "Sokoban Gym -- Get Strong or Die Trying",
+    "Somebody stole my Mojo!",
+    "The Hellhound Gang",
+    "The Werewolves",
+    "They Might Be Storm Giants",
+    "Up with miniskirts!",
+    "Weapons don't kill people, I kill people",
+    "Where's the beef?",
+    "White Zombie",
+    "Worship me",
+    "You laugh because I'm different, I laugh because you're about to die",
+    "You're killing me!",
+    "You should hear what the voices in my head are saying about you.",
 	    };
 	    char buf[BUFSZ];
@@ -93,5 +152,132 @@
 	    pline("\"%s\"", buf);
 	    return 1;
+	} else if (scroll->otyp == CREDIT_CARD) {
+	    static const char *card_msgs[] = {
+		"Leprechaun Gold Tru$t - Shamrock Card",
+		"Magic Memory Vault Charge Card",
+		"Larn National Bank", /* Larn */
+		"First Bank of Omega", /* Omega */
+		"Bank of Zork - Frobozz Magic Card", /* Zork */
+		"Ankh-Morpork Merchant's Guild Barter Card",
+		"Ankh-Morpork Thieves' Guild Unlimited Transaction Card",
+		"Ransmannsby Moneylenders Association",
+		"Bank of Gehennom - 99% Interest Card",
+		"Yendorian Express - Copper Card",
+		"Yendorian Express - Silver Card",
+		"Yendorian Express - Gold Card",
+		"Yendorian Express - Mithril Card",
+		"Yendorian Express - Platinum Card",
+            };
+            if (Blind) {
+                You("feel the embossed numbers:");
+            } else {
+		if(flags.verbose)
+                    pline("It reads:");
+                pline("\"%s\"", scroll->oartifact ? card_msgs[SIZE(card_msgs)-1]
+		      : card_msgs[scroll->o_id % (SIZE(card_msgs)-1)]);
+            }
+            /* Make a credit card number */
+	    pline("\"%d0%d %d%d1 0%d%d0\"", ((scroll->o_id % 89)+10), (scroll->o_id % 4),
+		  (((scroll->o_id * 499) % 899999) + 100000), (scroll->o_id % 10), 
+		  (!(scroll->o_id % 3)), ((scroll->o_id * 7) % 10));
+            u.uconduct.literate++;
+            return 1;
 #endif	/* TOURIST */
+	} else if (scroll->otyp == ALCHEMY_SMOCK) {
+	    static const char *apron_msgs[] = {
+		"Kiss the cook",
+		"I'm making SCIENCE!",
+		"Don't mess with the chef",
+		"Don't make me poison you",
+		"Gehennom's Kitchen",
+		"Rat: The other white meat",
+		"If you can't stand the heat, get out of Gehennom!",
+		"If we weren't meant to eat animals, why are they made out of meat?",
+		"If you don't like the food, I'll stab you"
+	    };
+	    char buf[BUFSZ];
+	    int erosion;
+	    /* duplicates the t-shirt read code */
+	    if (Blind) {
+		You_cant("feel any Braille writing.");
+		return 0;
+	    }
+	    u.uconduct.literate++;
+	    if(flags.verbose)
+		pline("It reads:");
+	    Strcpy(buf, apron_msgs[scroll->o_id % SIZE(apron_msgs)]);
+	    erosion = greatest_erosion(scroll);
+	    if (erosion)
+		wipeout_text(buf,
+			(int)(strlen(buf) * erosion / (2*MAX_ERODE)),
+			     scroll->o_id ^ (unsigned)u.ubirthday);
+	    pline("\"%s\"", buf);
+	    return 1;
+        } else if (scroll->otyp == TIN) {
+	    if (scroll->o_id % 3) {
+		pline("This %s has no label.", singular(scroll, xname));
+		return(0);
+	    } else {
+		if (Blind) {
+		    You_cant("feel any Braille writing.");
+		    return 0;
+		}
+		pline("The label reads: \"%s\"", tin_content_text(scroll));
+		u.uconduct.literate++;
+		return 1;
+	    }
+	} else if (scroll->otyp == CAN_OF_GREASE) {
+            pline("This %s has no label.", singular(scroll, xname));
+            return(0);
+	} else if (scroll->otyp == CANDY_BAR) {
+	    static const char *wrapper_msgs[] = {
+		"Apollo",	/* Lost */
+		"Moon Crunchy", /* South Park */
+		"Snacky Cake",
+		"Chocolate Nuggie",
+		"The Small Bar",
+		"Crispy Yum Yum",
+		"Nilla Crunchie",
+		"Berry Bar",
+		"Choco Nummer",
+		"Om-nom",	/* Cat Macro */
+		"Fruity Oaty",	/* Serenity */
+		"Wonka"		/* Charlie and the Chocolate Factory */
+	    };
+	    if (Blind) {
+		You_cant("feel any Braille writing.");
+		return 0;
+	    }
+	    pline("The wrapper reads: \"%s\"", wrapper_msgs[scroll->o_id % SIZE(wrapper_msgs)]);
+	    u.uconduct.literate++;
+	    return 1;
+	} else if (OBJ_DESCR(objects[scroll->otyp]) &&
+		   !strncmp(OBJ_DESCR(objects[scroll->otyp]), "runed", 5) &&
+		   scroll->oclass != SCROLL_CLASS &&
+		   scroll->oclass != SPBOOK_CLASS) {
+	    if (scroll->otyp == RUNESWORD) {
+	        You_cant("decipher the arcane runes.");
+		return 0;
+	    } if (!Race_if(PM_ELF) && !Role_if(PM_ARCHEOLOGIST)) {
+	        You_cant("decipher the Elvish runes.");
+		return 0;
+	    }
+            u.uconduct.literate++;
+	    if (objects[scroll->otyp].oc_merge) {
+		if (Blind)
+		    You("feel the engraved runes:");
+		else if (flags.verbose) pline("The runes read:");
+		pline("\"Made in Elfheim.\"");
+		return 1;
+	    } else {
+		/* "Avoid any artifact with Runes on it, even if the Runes
+		 *  prove only to spell the maker's name." -- Diana Wynne Jones
+		 */
+		if (Blind)
+		    You("feel the engraved signature:");
+		else pline("It is signed:");
+	        pline("\"%s\"", elf_name(scroll->o_id));
+	        return 1;
+	    }
 	} else if (scroll->oclass != SCROLL_CLASS
 		&& scroll->oclass != SPBOOK_CLASS) {
@@ -240,5 +426,5 @@
 	     */
 	    n = (int)obj->recharged;
-	    if (n > 0 && (obj->otyp == WAN_WISHING ||
+	    if (n > 0 && (obj->otyp == WAN_WISHING || obj->otyp == WAN_DEATH ||
 		    (n * n * n > rn2(7*7*7)))) {	/* recharge_limit */
 		wand_explode(obj);
@@ -275,5 +461,5 @@
 
 	    /* destruction depends on current state, not adjustment */
-	    if (obj->spe > rn2(7) || obj->spe <= -5) {
+	    if (obj->spe > rn2(6)+3 || (is_cursed && obj->spe <= -5)) {
 		Your("%s %s momentarily, then %s!",
 		     xname(obj), otense(obj,"pulsate"), otense(obj,"explode"));
@@ -352,4 +538,5 @@
 	    case OIL_LAMP:
 	    case BRASS_LANTERN:
+		 case BAG_OF_POO:
 		if (is_cursed) {
 		    stripspe(obj);
@@ -1027,6 +1214,11 @@
 		if (confused || sobj->cursed) return(trap_detect(sobj));
 		else return(gold_detect(sobj));
+	case SPE_OBTAIN_FOOD:
+		/* even basic skill creates food as well as detect it */
+		if (!sobj->cursed) {
+			pline("A food ration appears at your feet!");
+			mksobj_at(FOOD_RATION,u.ux,u.uy,TRUE,FALSE);
+		}
 	case SCR_FOOD_DETECTION:
-	case SPE_DETECT_FOOD:
 		if (food_detect(sobj))
 			return(1);	/* nothing detected */
@@ -1129,6 +1321,7 @@
 		makeknown(SCR_FIRE);
 		if(confused) {
-		    if(Fire_resistance) {
+		    if(how_resistant(FIRE_RES) == 100) {
 			shieldeff(u.ux, u.uy);
+				monstseesu(M_SEEN_FIRE);
 			if(!Blind)
 			    pline("Oh, look, what a pretty fire in your %s.",
@@ -1137,6 +1330,5 @@
 				makeplural(body_part(HAND)));
 		    } else {
-			pline_The("scroll catches fire and you burn your %s.",
-				makeplural(body_part(HAND)));
+				pline_The("scroll catches fire and you burn your %s.",makeplural(body_part(HAND)));
 			losehp(1, "scroll of fire", KILLED_BY_AN);
 		    }
@@ -1217,5 +1409,5 @@
 				    }
 				}
-	    	    	    	mtmp->mhp -= mdmg;
+							damage_mon(mtmp,mdmg,AD_PHYS);
 	    	    	    	if (mtmp->mhp <= 0)
 	    	    	    	    xkilled(mtmp, 1);
@@ -1414,4 +1606,6 @@
 	 *  set the waslit bit [could be messed up from above].
 	 */
+	if (on) blindingflash();
+
 	if (!Blind) {
 	    vision_recalc(2);
@@ -1425,9 +1619,14 @@
 }
 
+/* 1/9/08 DSR: Experimental change; what if blessed geno wiped out
+ * two species, but selected those species at random (with preference
+ * to the weaker stuff first)?
+ */
 static void
 do_class_genocide()
 {
 	int i, j, immunecnt, gonecnt, goodcnt, class, feel_dead = 0;
-	char buf[BUFSZ];
+	int killed, candidates;
+	char buf[BUFSZ] = "";
 	boolean gameover = FALSE;	/* true iff killed self */
 
@@ -1438,4 +1637,5 @@
 		}
 		do {
+		    if (buf[0]=='\033') buf[0] = 0;
 		    getlin("What class of monsters do you wish to genocide?",
 			buf);
@@ -1459,6 +1659,5 @@
 		immunecnt = gonecnt = goodcnt = 0;
 		for (i = LOW_PM; i < NUMMONS; i++) {
-		    if (class == 0 &&
-			    strstri(monexplain[(int)mons[i].mlet], buf) != 0)
+		    if (class == 0 && strstri(monexplain[(int)mons[i].mlet], buf) != 0)
 			class = mons[i].mlet;
 		    if (mons[i].mlet == class) {
@@ -1476,6 +1675,5 @@
 			if (gonecnt)
 	pline("All such monsters are already nonexistent.");
-			else if (immunecnt ||
-				(buf[0] == DEF_INVISIBLE && buf[1] == '\0'))
+			else if (immunecnt || (buf[0] == DEF_INVISIBLE && buf[1] == '\0'))
 	You("aren't permitted to genocide such monsters.");
 			else
@@ -1499,4 +1697,5 @@
 		}
 
+		killed = candidates = 0;
 		for (i = LOW_PM; i < NUMMONS; i++) {
 		    if(mons[i].mlet == class) {
@@ -1507,10 +1706,16 @@
 			 * from both race and role; thus genocide affects either.
 			 */
+			candidates++;
 			if (Your_Own_Role(i) || Your_Own_Race(i) ||
-				((mons[i].geno & G_GENO)
-				&& !(mvitals[i].mvflags & G_GENOD))) {
+				((mons[i].geno & G_GENO) && !(mvitals[i].mvflags & G_GENOD))) {
 			/* This check must be first since player monsters might
-			 * have G_GENOD or !G_GENO.
+			 * have G_GENOD or !G_GENO.  We also have to keep track of
+			 * whether there are only two or fewer critters left available for us
+			 * to geno in the first place; we must get them all then.
+			 * finally, we have to make sure the self-geno cases always happen.
 			 */
+				if ((killed < 2 && (!rn2(goodcnt) || (killed+candidates > goodcnt-2))) ||
+					Your_Own_Role(i) || Your_Own_Race(i)) {
+					killed++;
 			    mvitals[i].mvflags |= (G_GENOD|G_NOCORPSE);
 			    reset_rndmonst(i);
@@ -1540,4 +1745,5 @@
 				}
 			    }
+				} 
 			} else if (mvitals[i].mvflags & G_GENOD) {
 			    if (!gameover)
@@ -1589,5 +1795,5 @@
 /* 5 (4 | 1) = normal genocide from throne */
 {
-	char buf[BUFSZ];
+	char buf[BUFSZ] = "";
 	register int	i, killplayer = 0;
 	register int mndx;
@@ -1634,12 +1840,17 @@
 			break;
 		}
-		if (is_human(ptr)) adjalign(-sgn(u.ualign.type));
-		if (is_demon(ptr)) adjalign(sgn(u.ualign.type));
+
+		/* you'll still be punished for some of this... */
+		if ((is_human(ptr) && u.ualign.type != A_CHAOTIC) ||
+				(is_demon(ptr) && u.ualign.type == A_CHAOTIC)) {
+			major_sin();
+		} else {
+			adjalign(sgn(u.ualign.type));
+		}
 
 		if(!(ptr->geno & G_GENO)) {
 			if(flags.soundok) {
-	/* fixme: unconditional "caverns" will be silly in some circumstances */
 			    if(flags.verbose)
-			pline("A thunderous voice booms through the caverns:");
+			pline("A thunderous voice booms:");
 			    verbalize("No, mortal!  That will not be done.");
 			}
@@ -1807,5 +2018,5 @@
 create_particular()
 {
-	char buf[BUFSZ], *bufp, monclass = MAXMCLASSES;
+	char buf[BUFSZ] = "", *bufp, monclass = MAXMCLASSES;
 	int which, tries, i;
 	struct permonst *whichpm;
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/src/region.c nethack/src/region.c
--- nh_orig/src/region.c	2003-12-07 18:39:13.000000000 -0500
+++ nethack/src/region.c	2009-09-07 11:18:19.722293354 -0400
@@ -1,3 +1,3 @@
-/*	SCCS Id: @(#)region.c	3.4	2002/10/15	*/
+/*	SCCS Id: @(#)region.c	5.4	2002/10/15	*/
 /* Copyright (c) 1996 by Jean-Christophe Collet	 */
 /* NetHack may be freely redistributed.  See license for details. */
@@ -879,8 +879,8 @@
 {
     NhRegion *reg;
-    int damage;
+    size_t damage;
 
     reg = (NhRegion *) p1;
-    damage = (int) reg->arg;
+    damage = (size_t) reg->arg;
 
     /* If it was a thick cloud, it dissipates a little first */
@@ -904,5 +904,5 @@
 
     reg = (NhRegion *) p1;
-    dam = (int) reg->arg;
+    dam = (size_t) reg->arg;
     if (p2 == NULL) {		/* This means *YOU* Bozo! */
 	if (nonliving(youmonst.data) || Breathless)
@@ -910,10 +910,11 @@
 	if (!Blind)
 	    make_blinded(1L, FALSE);
-	if (!Poison_resistance) {
+	if (how_resistant(POISON_RES) < 100) {
 	    pline("%s is burning your %s!", Something, makeplural(body_part(LUNG)));
 	    You("cough and spit blood!");
-	    losehp(rnd(dam) + 5, "gas cloud", KILLED_BY_AN);
+	    losehp(resist_reduce(rnd(dam) + 5,POISON_RES), "gas cloud", KILLED_BY_AN);
 	    return FALSE;
 	} else {
+		 monstseesu(M_SEEN_POISON);
 	    You("cough!");
 	    return FALSE;
@@ -933,5 +934,5 @@
 	    if (resists_poison(mtmp))
 		return FALSE;
-	    mtmp->mhp -= rnd(dam) + 5;
+		 damage_mon(mtmp,rnd(dam)+5,AD_DRST);
 	    if (mtmp->mhp <= 0) {
 		if (heros_fault(reg))
@@ -952,5 +953,5 @@
 xchar x, y;
 int radius;
-int damage;
+size_t damage;
 {
     NhRegion *cloud;
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/src/restore.c nethack/src/restore.c
--- nh_orig/src/restore.c	2003-12-07 18:39:13.000000000 -0500
+++ nethack/src/restore.c	2009-10-04 19:50:51.089293406 -0400
@@ -191,4 +191,63 @@
 }
 
+struct lvl_sounds *
+rest_lvl_sounds(fd)
+register int fd;
+{
+    int marker;
+    struct lvl_sounds *or = NULL;
+    struct lvl_sound_bite *mt = NULL;
+    mread(fd, (genericptr_t) &marker, sizeof(marker));
+    if (marker) {
+	or = (struct lvl_sounds *)alloc(sizeof(struct lvl_sounds));
+	mread(fd, (genericptr_t) or, sizeof(*or));
+	or->sounds = NULL;
+	if (or->n_sounds) {
+	    int i;
+	    int len;
+	    or->sounds = (struct lvl_sound_bite *)alloc(sizeof(struct lvl_sound_bite)*or->n_sounds);
+	    for (i = 0; i < or->n_sounds; i++) {
+		mread(fd, (genericptr_t)&(or->sounds[i].flags), sizeof(or->sounds[i].flags));
+		mread(fd, (genericptr_t)&len, sizeof(len));
+		or->sounds[i].msg = (char *)alloc(len);
+		mread(fd, (genericptr_t)or->sounds[i].msg, len);
+	    }
+	}
+    }
+    return or;
+}
+
+struct mon_gen_override *
+rest_mongen_override(fd)
+register int fd;
+{
+    int marker;
+    struct mon_gen_override *or = NULL;
+    struct mon_gen_tuple *mt = NULL;
+    int next;
+
+    mread(fd, (genericptr_t) &marker, sizeof(marker));
+    if (marker) {
+	or = (struct mon_gen_override *)alloc(sizeof(struct mon_gen_override));
+	mread(fd, (genericptr_t) or, sizeof(*or));
+	if (or->gen_chances) {
+	    or->gen_chances = NULL;
+	    do {
+		mt = (struct mon_gen_tuple *)alloc(sizeof(struct mon_gen_tuple));
+		mread(fd, (genericptr_t) mt, sizeof(*mt));
+		if (mt->next) {
+		    next = 1;
+		} else {
+		    next = 0;
+		}
+		mt->next = or->gen_chances;
+		or->gen_chances = mt;
+	    } while (next);
+	}
+    }
+    return or;
+}
+
+
 STATIC_OVL struct obj *
 restobjchn(fd, ghostly, frozen)
@@ -248,6 +307,7 @@
 	register struct monst *mtmp, *mtmp2 = 0;
 	register struct monst *first = (struct monst *)0;
-	int xl;
+	int xl, monstoread, iter;
 	struct permonst *monbegin;
+	int namesize = sizeof(monbegin->mname);
 	boolean moved;
 
@@ -307,4 +367,17 @@
 		mtmp2->nmon = 0;
 	}
+
+	/* get the permonst chain back */
+	mread(fd, (genericptr_t) &monstoread, sizeof(int));
+	if (monstoread != NUMMONS)
+	{
+		impossible("Restmonchn: number of permonst stored doesn't match current NUMMONS. Using default permonst");
+	} else {
+		for (iter=0;iter < NUMMONS;iter++)
+		{
+			mread(fd, (genericptr_t) &mons[iter]+namesize, sizeof(struct permonst)-namesize);
+		}
+	}
+
 	return(first);
 }
@@ -446,7 +519,19 @@
 	restnames(fd);
 	restore_waterlevel(fd);
+
+#ifdef RECORD_ACHIEVE
+        mread(fd, (genericptr_t) &achieve, sizeof achieve);
+#endif
+#if defined(RECORD_REALTIME) || defined(REALTIME_ON_BOTL)
+        mread(fd, (genericptr_t) &realtime_data.realtime, 
+                  sizeof realtime_data.realtime);
+#endif
+  
 	/* must come after all mons & objs are restored */
 	relink_timers(FALSE);
 	relink_light_sources(FALSE);
+#ifdef WHEREIS_FILE
+	touch_whereis();
+#endif
 	return(TRUE);
 }
@@ -677,4 +762,15 @@
 	program_state.something_worth_saving++;	/* useful data now exists */
 
+#if defined(RECORD_REALTIME) || defined(REALTIME_ON_BOTL)
+
+/* Start the timer here (realtime has already been set) */
+#if defined(BSD) && !defined(POSIX_TYPES)
+        (void) time((long *)&realtime_data.restoretime);
+#else
+        (void) time(&realtime_data.restoretime);
+#endif
+
+#endif /* RECORD_REALTIME || REALTIME_ON_BOTL */
+
 	/* Success! */
 	welcome(FALSE);
@@ -829,4 +925,6 @@
 	level.buriedobjlist = restobjchn(fd, ghostly, FALSE);
 	billobjs = restobjchn(fd, ghostly, FALSE);
+	level.mon_gen = rest_mongen_override(fd);
+	level.sounds = rest_lvl_sounds(fd);
 	rest_engravings(fd);
 
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/src/rnd.c nethack/src/rnd.c
--- nh_orig/src/rnd.c	2003-12-07 18:39:13.000000000 -0500
+++ nethack/src/rnd.c	2010-05-11 11:39:24.207714514 -0400
@@ -4,16 +4,10 @@
 #include "hack.h"
 
-/* "Rand()"s definition is determined by [OS]conf.h */
-#if defined(LINT) && defined(UNIX)	/* rand() is long... */
-extern int NDECL(rand);
-#define RND(x)	(rand() % x)
-#else /* LINT */
-# if defined(UNIX) || defined(RANDOM)
-#define RND(x)	(int)(Rand() % (long)(x))
-# else
-/* Good luck: the bottom order bits are cyclic. */
-#define RND(x)	(int)((Rand()>>3) % (x))
-# endif
-#endif /* LINT */
+unsigned int good_random(void);
+
+#define RND(x) (good_random() % x)
+
+#include <stdint.h>
+#include <sys/time.h>
 
 #ifdef OVL0
@@ -23,5 +17,4 @@
 register int x;
 {
-#ifdef DEBUG
 	if (x <= 0) {
 		impossible("rn2(%d) attempted", x);
@@ -30,7 +23,4 @@
 	x = RND(x);
 	return(x);
-#else
-	return(RND(x));
-#endif
 }
 
@@ -44,10 +34,9 @@
 	register int i;
 
-#ifdef DEBUG
 	if (x <= 0) {
 		impossible("rnl(%d) attempted", x);
 		return(0);
 	}
-#endif
+
 	i = RND(x);
 
@@ -68,5 +57,4 @@
 register int x;
 {
-#ifdef DEBUG
 	if (x <= 0) {
 		impossible("rnd(%d) attempted", x);
@@ -75,7 +63,4 @@
 	x = RND(x)+1;
 	return(x);
-#else
-	return(RND(x)+1);
-#endif
 }
 
@@ -89,10 +74,9 @@
 	register int tmp = n;
 
-#ifdef DEBUG
 	if (x < 0 || n < 0 || (x == 0 && n != 0)) {
 		impossible("d(%d,%d) attempted", n, x);
 		return(1);
 	}
-#endif
+
 	while(n--) tmp += RND(x);
 	return(tmp); /* Alea iacta est. -- J.C. */
@@ -143,3 +127,2002 @@
 #endif /* OVLB */
 
+/* Vastly improved RNG functions here, using AES and SHA256 to generate 
+   random numbers. The code is more or less copy+paste from public 
+   domain LibTomCrypt */
+
+#ifdef RND
+#undef RND
+#endif
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+#define CRYPT_OK 0
+#define CRYPT_INVALID_ARG 1
+#define CRYPT_INVALID_KEYSIZE 2
+#define CRYPT_INVALID_ROUNDS 3
+#define CRYPT_ERROR 4
+
+#define RORc(x, y) ( ((((unsigned long)(x)&0xFFFFFFFFUL)>>(unsigned long)((y)&31)) | ((unsigned long)(x)<<(unsigned long)(32-((y)&31)))) & 0xFFFFFFFFUL)
+
+#define MIN(x, y) ( ((x)<(y))?(x):(y) )
+
+#define STORE64H(x, y)                                                                     \
+   { (y)[0] = (unsigned char)(((x)>>56)&255); (y)[1] = (unsigned char)(((x)>>48)&255);     \
+     (y)[2] = (unsigned char)(((x)>>40)&255); (y)[3] = (unsigned char)(((x)>>32)&255);     \
+     (y)[4] = (unsigned char)(((x)>>24)&255); (y)[5] = (unsigned char)(((x)>>16)&255);     \
+     (y)[6] = (unsigned char)(((x)>>8)&255); (y)[7] = (unsigned char)((x)&255); }
+
+#define STORE32H(x, y)                                                                     \
+     { (y)[0] = (unsigned char)(((x)>>24)&255); (y)[1] = (unsigned char)(((x)>>16)&255);   \
+       (y)[2] = (unsigned char)(((x)>>8)&255); (y)[3] = (unsigned char)((x)&255); }
+
+#define LOAD32H(x, y)                            \
+     { x = ((unsigned long)((y)[0] & 255)<<24) | \
+           ((unsigned long)((y)[1] & 255)<<16) | \
+           ((unsigned long)((y)[2] & 255)<<8)  | \
+           ((unsigned long)((y)[3] & 255)); }
+
+typedef uint64_t ulong64;
+typedef uint32_t ulong32;
+
+struct rijndael_key {
+   ulong32 eK[60], dK[60];
+   int Nr;
+};
+
+typedef union Symmetric_key {
+   struct rijndael_key rijndael;
+   void   *data;
+} symmetric_key;
+
+#define byte(x, n) (((x) >> (8 * (n))) & 255)
+
+/**
+  @file aes_tab.c
+  AES tables
+*/  
+static const ulong32 TE0[256] = {
+    0xc66363a5UL, 0xf87c7c84UL, 0xee777799UL, 0xf67b7b8dUL,
+    0xfff2f20dUL, 0xd66b6bbdUL, 0xde6f6fb1UL, 0x91c5c554UL,
+    0x60303050UL, 0x02010103UL, 0xce6767a9UL, 0x562b2b7dUL,
+    0xe7fefe19UL, 0xb5d7d762UL, 0x4dababe6UL, 0xec76769aUL,
+    0x8fcaca45UL, 0x1f82829dUL, 0x89c9c940UL, 0xfa7d7d87UL,
+    0xeffafa15UL, 0xb25959ebUL, 0x8e4747c9UL, 0xfbf0f00bUL,
+    0x41adadecUL, 0xb3d4d467UL, 0x5fa2a2fdUL, 0x45afafeaUL,
+    0x239c9cbfUL, 0x53a4a4f7UL, 0xe4727296UL, 0x9bc0c05bUL,
+    0x75b7b7c2UL, 0xe1fdfd1cUL, 0x3d9393aeUL, 0x4c26266aUL,
+    0x6c36365aUL, 0x7e3f3f41UL, 0xf5f7f702UL, 0x83cccc4fUL,
+    0x6834345cUL, 0x51a5a5f4UL, 0xd1e5e534UL, 0xf9f1f108UL,
+    0xe2717193UL, 0xabd8d873UL, 0x62313153UL, 0x2a15153fUL,
+    0x0804040cUL, 0x95c7c752UL, 0x46232365UL, 0x9dc3c35eUL,
+    0x30181828UL, 0x379696a1UL, 0x0a05050fUL, 0x2f9a9ab5UL,
+    0x0e070709UL, 0x24121236UL, 0x1b80809bUL, 0xdfe2e23dUL,
+    0xcdebeb26UL, 0x4e272769UL, 0x7fb2b2cdUL, 0xea75759fUL,
+    0x1209091bUL, 0x1d83839eUL, 0x582c2c74UL, 0x341a1a2eUL,
+    0x361b1b2dUL, 0xdc6e6eb2UL, 0xb45a5aeeUL, 0x5ba0a0fbUL,
+    0xa45252f6UL, 0x763b3b4dUL, 0xb7d6d661UL, 0x7db3b3ceUL,
+    0x5229297bUL, 0xdde3e33eUL, 0x5e2f2f71UL, 0x13848497UL,
+    0xa65353f5UL, 0xb9d1d168UL, 0x00000000UL, 0xc1eded2cUL,
+    0x40202060UL, 0xe3fcfc1fUL, 0x79b1b1c8UL, 0xb65b5bedUL,
+    0xd46a6abeUL, 0x8dcbcb46UL, 0x67bebed9UL, 0x7239394bUL,
+    0x944a4adeUL, 0x984c4cd4UL, 0xb05858e8UL, 0x85cfcf4aUL,
+    0xbbd0d06bUL, 0xc5efef2aUL, 0x4faaaae5UL, 0xedfbfb16UL,
+    0x864343c5UL, 0x9a4d4dd7UL, 0x66333355UL, 0x11858594UL,
+    0x8a4545cfUL, 0xe9f9f910UL, 0x04020206UL, 0xfe7f7f81UL,
+    0xa05050f0UL, 0x783c3c44UL, 0x259f9fbaUL, 0x4ba8a8e3UL,
+    0xa25151f3UL, 0x5da3a3feUL, 0x804040c0UL, 0x058f8f8aUL,
+    0x3f9292adUL, 0x219d9dbcUL, 0x70383848UL, 0xf1f5f504UL,
+    0x63bcbcdfUL, 0x77b6b6c1UL, 0xafdada75UL, 0x42212163UL,
+    0x20101030UL, 0xe5ffff1aUL, 0xfdf3f30eUL, 0xbfd2d26dUL,
+    0x81cdcd4cUL, 0x180c0c14UL, 0x26131335UL, 0xc3ecec2fUL,
+    0xbe5f5fe1UL, 0x359797a2UL, 0x884444ccUL, 0x2e171739UL,
+    0x93c4c457UL, 0x55a7a7f2UL, 0xfc7e7e82UL, 0x7a3d3d47UL,
+    0xc86464acUL, 0xba5d5de7UL, 0x3219192bUL, 0xe6737395UL,
+    0xc06060a0UL, 0x19818198UL, 0x9e4f4fd1UL, 0xa3dcdc7fUL,
+    0x44222266UL, 0x542a2a7eUL, 0x3b9090abUL, 0x0b888883UL,
+    0x8c4646caUL, 0xc7eeee29UL, 0x6bb8b8d3UL, 0x2814143cUL,
+    0xa7dede79UL, 0xbc5e5ee2UL, 0x160b0b1dUL, 0xaddbdb76UL,
+    0xdbe0e03bUL, 0x64323256UL, 0x743a3a4eUL, 0x140a0a1eUL,
+    0x924949dbUL, 0x0c06060aUL, 0x4824246cUL, 0xb85c5ce4UL,
+    0x9fc2c25dUL, 0xbdd3d36eUL, 0x43acacefUL, 0xc46262a6UL,
+    0x399191a8UL, 0x319595a4UL, 0xd3e4e437UL, 0xf279798bUL,
+    0xd5e7e732UL, 0x8bc8c843UL, 0x6e373759UL, 0xda6d6db7UL,
+    0x018d8d8cUL, 0xb1d5d564UL, 0x9c4e4ed2UL, 0x49a9a9e0UL,
+    0xd86c6cb4UL, 0xac5656faUL, 0xf3f4f407UL, 0xcfeaea25UL,
+    0xca6565afUL, 0xf47a7a8eUL, 0x47aeaee9UL, 0x10080818UL,
+    0x6fbabad5UL, 0xf0787888UL, 0x4a25256fUL, 0x5c2e2e72UL,
+    0x381c1c24UL, 0x57a6a6f1UL, 0x73b4b4c7UL, 0x97c6c651UL,
+    0xcbe8e823UL, 0xa1dddd7cUL, 0xe874749cUL, 0x3e1f1f21UL,
+    0x964b4bddUL, 0x61bdbddcUL, 0x0d8b8b86UL, 0x0f8a8a85UL,
+    0xe0707090UL, 0x7c3e3e42UL, 0x71b5b5c4UL, 0xcc6666aaUL,
+    0x904848d8UL, 0x06030305UL, 0xf7f6f601UL, 0x1c0e0e12UL,
+    0xc26161a3UL, 0x6a35355fUL, 0xae5757f9UL, 0x69b9b9d0UL,
+    0x17868691UL, 0x99c1c158UL, 0x3a1d1d27UL, 0x279e9eb9UL,
+    0xd9e1e138UL, 0xebf8f813UL, 0x2b9898b3UL, 0x22111133UL,
+    0xd26969bbUL, 0xa9d9d970UL, 0x078e8e89UL, 0x339494a7UL,
+    0x2d9b9bb6UL, 0x3c1e1e22UL, 0x15878792UL, 0xc9e9e920UL,
+    0x87cece49UL, 0xaa5555ffUL, 0x50282878UL, 0xa5dfdf7aUL,
+    0x038c8c8fUL, 0x59a1a1f8UL, 0x09898980UL, 0x1a0d0d17UL,
+    0x65bfbfdaUL, 0xd7e6e631UL, 0x844242c6UL, 0xd06868b8UL,
+    0x824141c3UL, 0x299999b0UL, 0x5a2d2d77UL, 0x1e0f0f11UL,
+    0x7bb0b0cbUL, 0xa85454fcUL, 0x6dbbbbd6UL, 0x2c16163aUL,
+};
+
+#ifndef PELI_TAB
+static const ulong32 Te4[256] = {
+    0x63636363UL, 0x7c7c7c7cUL, 0x77777777UL, 0x7b7b7b7bUL,
+    0xf2f2f2f2UL, 0x6b6b6b6bUL, 0x6f6f6f6fUL, 0xc5c5c5c5UL,
+    0x30303030UL, 0x01010101UL, 0x67676767UL, 0x2b2b2b2bUL,
+    0xfefefefeUL, 0xd7d7d7d7UL, 0xababababUL, 0x76767676UL,
+    0xcacacacaUL, 0x82828282UL, 0xc9c9c9c9UL, 0x7d7d7d7dUL,
+    0xfafafafaUL, 0x59595959UL, 0x47474747UL, 0xf0f0f0f0UL,
+    0xadadadadUL, 0xd4d4d4d4UL, 0xa2a2a2a2UL, 0xafafafafUL,
+    0x9c9c9c9cUL, 0xa4a4a4a4UL, 0x72727272UL, 0xc0c0c0c0UL,
+    0xb7b7b7b7UL, 0xfdfdfdfdUL, 0x93939393UL, 0x26262626UL,
+    0x36363636UL, 0x3f3f3f3fUL, 0xf7f7f7f7UL, 0xccccccccUL,
+    0x34343434UL, 0xa5a5a5a5UL, 0xe5e5e5e5UL, 0xf1f1f1f1UL,
+    0x71717171UL, 0xd8d8d8d8UL, 0x31313131UL, 0x15151515UL,
+    0x04040404UL, 0xc7c7c7c7UL, 0x23232323UL, 0xc3c3c3c3UL,
+    0x18181818UL, 0x96969696UL, 0x05050505UL, 0x9a9a9a9aUL,
+    0x07070707UL, 0x12121212UL, 0x80808080UL, 0xe2e2e2e2UL,
+    0xebebebebUL, 0x27272727UL, 0xb2b2b2b2UL, 0x75757575UL,
+    0x09090909UL, 0x83838383UL, 0x2c2c2c2cUL, 0x1a1a1a1aUL,
+    0x1b1b1b1bUL, 0x6e6e6e6eUL, 0x5a5a5a5aUL, 0xa0a0a0a0UL,
+    0x52525252UL, 0x3b3b3b3bUL, 0xd6d6d6d6UL, 0xb3b3b3b3UL,
+    0x29292929UL, 0xe3e3e3e3UL, 0x2f2f2f2fUL, 0x84848484UL,
+    0x53535353UL, 0xd1d1d1d1UL, 0x00000000UL, 0xededededUL,
+    0x20202020UL, 0xfcfcfcfcUL, 0xb1b1b1b1UL, 0x5b5b5b5bUL,
+    0x6a6a6a6aUL, 0xcbcbcbcbUL, 0xbebebebeUL, 0x39393939UL,
+    0x4a4a4a4aUL, 0x4c4c4c4cUL, 0x58585858UL, 0xcfcfcfcfUL,
+    0xd0d0d0d0UL, 0xefefefefUL, 0xaaaaaaaaUL, 0xfbfbfbfbUL,
+    0x43434343UL, 0x4d4d4d4dUL, 0x33333333UL, 0x85858585UL,
+    0x45454545UL, 0xf9f9f9f9UL, 0x02020202UL, 0x7f7f7f7fUL,
+    0x50505050UL, 0x3c3c3c3cUL, 0x9f9f9f9fUL, 0xa8a8a8a8UL,
+    0x51515151UL, 0xa3a3a3a3UL, 0x40404040UL, 0x8f8f8f8fUL,
+    0x92929292UL, 0x9d9d9d9dUL, 0x38383838UL, 0xf5f5f5f5UL,
+    0xbcbcbcbcUL, 0xb6b6b6b6UL, 0xdadadadaUL, 0x21212121UL,
+    0x10101010UL, 0xffffffffUL, 0xf3f3f3f3UL, 0xd2d2d2d2UL,
+    0xcdcdcdcdUL, 0x0c0c0c0cUL, 0x13131313UL, 0xececececUL,
+    0x5f5f5f5fUL, 0x97979797UL, 0x44444444UL, 0x17171717UL,
+    0xc4c4c4c4UL, 0xa7a7a7a7UL, 0x7e7e7e7eUL, 0x3d3d3d3dUL,
+    0x64646464UL, 0x5d5d5d5dUL, 0x19191919UL, 0x73737373UL,
+    0x60606060UL, 0x81818181UL, 0x4f4f4f4fUL, 0xdcdcdcdcUL,
+    0x22222222UL, 0x2a2a2a2aUL, 0x90909090UL, 0x88888888UL,
+    0x46464646UL, 0xeeeeeeeeUL, 0xb8b8b8b8UL, 0x14141414UL,
+    0xdedededeUL, 0x5e5e5e5eUL, 0x0b0b0b0bUL, 0xdbdbdbdbUL,
+    0xe0e0e0e0UL, 0x32323232UL, 0x3a3a3a3aUL, 0x0a0a0a0aUL,
+    0x49494949UL, 0x06060606UL, 0x24242424UL, 0x5c5c5c5cUL,
+    0xc2c2c2c2UL, 0xd3d3d3d3UL, 0xacacacacUL, 0x62626262UL,
+    0x91919191UL, 0x95959595UL, 0xe4e4e4e4UL, 0x79797979UL,
+    0xe7e7e7e7UL, 0xc8c8c8c8UL, 0x37373737UL, 0x6d6d6d6dUL,
+    0x8d8d8d8dUL, 0xd5d5d5d5UL, 0x4e4e4e4eUL, 0xa9a9a9a9UL,
+    0x6c6c6c6cUL, 0x56565656UL, 0xf4f4f4f4UL, 0xeaeaeaeaUL,
+    0x65656565UL, 0x7a7a7a7aUL, 0xaeaeaeaeUL, 0x08080808UL,
+    0xbabababaUL, 0x78787878UL, 0x25252525UL, 0x2e2e2e2eUL,
+    0x1c1c1c1cUL, 0xa6a6a6a6UL, 0xb4b4b4b4UL, 0xc6c6c6c6UL,
+    0xe8e8e8e8UL, 0xddddddddUL, 0x74747474UL, 0x1f1f1f1fUL,
+    0x4b4b4b4bUL, 0xbdbdbdbdUL, 0x8b8b8b8bUL, 0x8a8a8a8aUL,
+    0x70707070UL, 0x3e3e3e3eUL, 0xb5b5b5b5UL, 0x66666666UL,
+    0x48484848UL, 0x03030303UL, 0xf6f6f6f6UL, 0x0e0e0e0eUL,
+    0x61616161UL, 0x35353535UL, 0x57575757UL, 0xb9b9b9b9UL,
+    0x86868686UL, 0xc1c1c1c1UL, 0x1d1d1d1dUL, 0x9e9e9e9eUL,
+    0xe1e1e1e1UL, 0xf8f8f8f8UL, 0x98989898UL, 0x11111111UL,
+    0x69696969UL, 0xd9d9d9d9UL, 0x8e8e8e8eUL, 0x94949494UL,
+    0x9b9b9b9bUL, 0x1e1e1e1eUL, 0x87878787UL, 0xe9e9e9e9UL,
+    0xcecececeUL, 0x55555555UL, 0x28282828UL, 0xdfdfdfdfUL,
+    0x8c8c8c8cUL, 0xa1a1a1a1UL, 0x89898989UL, 0x0d0d0d0dUL,
+    0xbfbfbfbfUL, 0xe6e6e6e6UL, 0x42424242UL, 0x68686868UL,
+    0x41414141UL, 0x99999999UL, 0x2d2d2d2dUL, 0x0f0f0f0fUL,
+    0xb0b0b0b0UL, 0x54545454UL, 0xbbbbbbbbUL, 0x16161616UL,
+};
+#endif
+
+static const ulong32 TD0[256] = {
+    0x51f4a750UL, 0x7e416553UL, 0x1a17a4c3UL, 0x3a275e96UL,
+    0x3bab6bcbUL, 0x1f9d45f1UL, 0xacfa58abUL, 0x4be30393UL,
+    0x2030fa55UL, 0xad766df6UL, 0x88cc7691UL, 0xf5024c25UL,
+    0x4fe5d7fcUL, 0xc52acbd7UL, 0x26354480UL, 0xb562a38fUL,
+    0xdeb15a49UL, 0x25ba1b67UL, 0x45ea0e98UL, 0x5dfec0e1UL,
+    0xc32f7502UL, 0x814cf012UL, 0x8d4697a3UL, 0x6bd3f9c6UL,
+    0x038f5fe7UL, 0x15929c95UL, 0xbf6d7aebUL, 0x955259daUL,
+    0xd4be832dUL, 0x587421d3UL, 0x49e06929UL, 0x8ec9c844UL,
+    0x75c2896aUL, 0xf48e7978UL, 0x99583e6bUL, 0x27b971ddUL,
+    0xbee14fb6UL, 0xf088ad17UL, 0xc920ac66UL, 0x7dce3ab4UL,
+    0x63df4a18UL, 0xe51a3182UL, 0x97513360UL, 0x62537f45UL,
+    0xb16477e0UL, 0xbb6bae84UL, 0xfe81a01cUL, 0xf9082b94UL,
+    0x70486858UL, 0x8f45fd19UL, 0x94de6c87UL, 0x527bf8b7UL,
+    0xab73d323UL, 0x724b02e2UL, 0xe31f8f57UL, 0x6655ab2aUL,
+    0xb2eb2807UL, 0x2fb5c203UL, 0x86c57b9aUL, 0xd33708a5UL,
+    0x302887f2UL, 0x23bfa5b2UL, 0x02036abaUL, 0xed16825cUL,
+    0x8acf1c2bUL, 0xa779b492UL, 0xf307f2f0UL, 0x4e69e2a1UL,
+    0x65daf4cdUL, 0x0605bed5UL, 0xd134621fUL, 0xc4a6fe8aUL,
+    0x342e539dUL, 0xa2f355a0UL, 0x058ae132UL, 0xa4f6eb75UL,
+    0x0b83ec39UL, 0x4060efaaUL, 0x5e719f06UL, 0xbd6e1051UL,
+    0x3e218af9UL, 0x96dd063dUL, 0xdd3e05aeUL, 0x4de6bd46UL,
+    0x91548db5UL, 0x71c45d05UL, 0x0406d46fUL, 0x605015ffUL,
+    0x1998fb24UL, 0xd6bde997UL, 0x894043ccUL, 0x67d99e77UL,
+    0xb0e842bdUL, 0x07898b88UL, 0xe7195b38UL, 0x79c8eedbUL,
+    0xa17c0a47UL, 0x7c420fe9UL, 0xf8841ec9UL, 0x00000000UL,
+    0x09808683UL, 0x322bed48UL, 0x1e1170acUL, 0x6c5a724eUL,
+    0xfd0efffbUL, 0x0f853856UL, 0x3daed51eUL, 0x362d3927UL,
+    0x0a0fd964UL, 0x685ca621UL, 0x9b5b54d1UL, 0x24362e3aUL,
+    0x0c0a67b1UL, 0x9357e70fUL, 0xb4ee96d2UL, 0x1b9b919eUL,
+    0x80c0c54fUL, 0x61dc20a2UL, 0x5a774b69UL, 0x1c121a16UL,
+    0xe293ba0aUL, 0xc0a02ae5UL, 0x3c22e043UL, 0x121b171dUL,
+    0x0e090d0bUL, 0xf28bc7adUL, 0x2db6a8b9UL, 0x141ea9c8UL,
+    0x57f11985UL, 0xaf75074cUL, 0xee99ddbbUL, 0xa37f60fdUL,
+    0xf701269fUL, 0x5c72f5bcUL, 0x44663bc5UL, 0x5bfb7e34UL,
+    0x8b432976UL, 0xcb23c6dcUL, 0xb6edfc68UL, 0xb8e4f163UL,
+    0xd731dccaUL, 0x42638510UL, 0x13972240UL, 0x84c61120UL,
+    0x854a247dUL, 0xd2bb3df8UL, 0xaef93211UL, 0xc729a16dUL,
+    0x1d9e2f4bUL, 0xdcb230f3UL, 0x0d8652ecUL, 0x77c1e3d0UL,
+    0x2bb3166cUL, 0xa970b999UL, 0x119448faUL, 0x47e96422UL,
+    0xa8fc8cc4UL, 0xa0f03f1aUL, 0x567d2cd8UL, 0x223390efUL,
+    0x87494ec7UL, 0xd938d1c1UL, 0x8ccaa2feUL, 0x98d40b36UL,
+    0xa6f581cfUL, 0xa57ade28UL, 0xdab78e26UL, 0x3fadbfa4UL,
+    0x2c3a9de4UL, 0x5078920dUL, 0x6a5fcc9bUL, 0x547e4662UL,
+    0xf68d13c2UL, 0x90d8b8e8UL, 0x2e39f75eUL, 0x82c3aff5UL,
+    0x9f5d80beUL, 0x69d0937cUL, 0x6fd52da9UL, 0xcf2512b3UL,
+    0xc8ac993bUL, 0x10187da7UL, 0xe89c636eUL, 0xdb3bbb7bUL,
+    0xcd267809UL, 0x6e5918f4UL, 0xec9ab701UL, 0x834f9aa8UL,
+    0xe6956e65UL, 0xaaffe67eUL, 0x21bccf08UL, 0xef15e8e6UL,
+    0xbae79bd9UL, 0x4a6f36ceUL, 0xea9f09d4UL, 0x29b07cd6UL,
+    0x31a4b2afUL, 0x2a3f2331UL, 0xc6a59430UL, 0x35a266c0UL,
+    0x744ebc37UL, 0xfc82caa6UL, 0xe090d0b0UL, 0x33a7d815UL,
+    0xf104984aUL, 0x41ecdaf7UL, 0x7fcd500eUL, 0x1791f62fUL,
+    0x764dd68dUL, 0x43efb04dUL, 0xccaa4d54UL, 0xe49604dfUL,
+    0x9ed1b5e3UL, 0x4c6a881bUL, 0xc12c1fb8UL, 0x4665517fUL,
+    0x9d5eea04UL, 0x018c355dUL, 0xfa877473UL, 0xfb0b412eUL,
+    0xb3671d5aUL, 0x92dbd252UL, 0xe9105633UL, 0x6dd64713UL,
+    0x9ad7618cUL, 0x37a10c7aUL, 0x59f8148eUL, 0xeb133c89UL,
+    0xcea927eeUL, 0xb761c935UL, 0xe11ce5edUL, 0x7a47b13cUL,
+    0x9cd2df59UL, 0x55f2733fUL, 0x1814ce79UL, 0x73c737bfUL,
+    0x53f7cdeaUL, 0x5ffdaa5bUL, 0xdf3d6f14UL, 0x7844db86UL,
+    0xcaaff381UL, 0xb968c43eUL, 0x3824342cUL, 0xc2a3405fUL,
+    0x161dc372UL, 0xbce2250cUL, 0x283c498bUL, 0xff0d9541UL,
+    0x39a80171UL, 0x080cb3deUL, 0xd8b4e49cUL, 0x6456c190UL,
+    0x7bcb8461UL, 0xd532b670UL, 0x486c5c74UL, 0xd0b85742UL,
+};
+
+static const ulong32 Td4[256] = {
+    0x52525252UL, 0x09090909UL, 0x6a6a6a6aUL, 0xd5d5d5d5UL,
+    0x30303030UL, 0x36363636UL, 0xa5a5a5a5UL, 0x38383838UL,
+    0xbfbfbfbfUL, 0x40404040UL, 0xa3a3a3a3UL, 0x9e9e9e9eUL,
+    0x81818181UL, 0xf3f3f3f3UL, 0xd7d7d7d7UL, 0xfbfbfbfbUL,
+    0x7c7c7c7cUL, 0xe3e3e3e3UL, 0x39393939UL, 0x82828282UL,
+    0x9b9b9b9bUL, 0x2f2f2f2fUL, 0xffffffffUL, 0x87878787UL,
+    0x34343434UL, 0x8e8e8e8eUL, 0x43434343UL, 0x44444444UL,
+    0xc4c4c4c4UL, 0xdedededeUL, 0xe9e9e9e9UL, 0xcbcbcbcbUL,
+    0x54545454UL, 0x7b7b7b7bUL, 0x94949494UL, 0x32323232UL,
+    0xa6a6a6a6UL, 0xc2c2c2c2UL, 0x23232323UL, 0x3d3d3d3dUL,
+    0xeeeeeeeeUL, 0x4c4c4c4cUL, 0x95959595UL, 0x0b0b0b0bUL,
+    0x42424242UL, 0xfafafafaUL, 0xc3c3c3c3UL, 0x4e4e4e4eUL,
+    0x08080808UL, 0x2e2e2e2eUL, 0xa1a1a1a1UL, 0x66666666UL,
+    0x28282828UL, 0xd9d9d9d9UL, 0x24242424UL, 0xb2b2b2b2UL,
+    0x76767676UL, 0x5b5b5b5bUL, 0xa2a2a2a2UL, 0x49494949UL,
+    0x6d6d6d6dUL, 0x8b8b8b8bUL, 0xd1d1d1d1UL, 0x25252525UL,
+    0x72727272UL, 0xf8f8f8f8UL, 0xf6f6f6f6UL, 0x64646464UL,
+    0x86868686UL, 0x68686868UL, 0x98989898UL, 0x16161616UL,
+    0xd4d4d4d4UL, 0xa4a4a4a4UL, 0x5c5c5c5cUL, 0xccccccccUL,
+    0x5d5d5d5dUL, 0x65656565UL, 0xb6b6b6b6UL, 0x92929292UL,
+    0x6c6c6c6cUL, 0x70707070UL, 0x48484848UL, 0x50505050UL,
+    0xfdfdfdfdUL, 0xededededUL, 0xb9b9b9b9UL, 0xdadadadaUL,
+    0x5e5e5e5eUL, 0x15151515UL, 0x46464646UL, 0x57575757UL,
+    0xa7a7a7a7UL, 0x8d8d8d8dUL, 0x9d9d9d9dUL, 0x84848484UL,
+    0x90909090UL, 0xd8d8d8d8UL, 0xababababUL, 0x00000000UL,
+    0x8c8c8c8cUL, 0xbcbcbcbcUL, 0xd3d3d3d3UL, 0x0a0a0a0aUL,
+    0xf7f7f7f7UL, 0xe4e4e4e4UL, 0x58585858UL, 0x05050505UL,
+    0xb8b8b8b8UL, 0xb3b3b3b3UL, 0x45454545UL, 0x06060606UL,
+    0xd0d0d0d0UL, 0x2c2c2c2cUL, 0x1e1e1e1eUL, 0x8f8f8f8fUL,
+    0xcacacacaUL, 0x3f3f3f3fUL, 0x0f0f0f0fUL, 0x02020202UL,
+    0xc1c1c1c1UL, 0xafafafafUL, 0xbdbdbdbdUL, 0x03030303UL,
+    0x01010101UL, 0x13131313UL, 0x8a8a8a8aUL, 0x6b6b6b6bUL,
+    0x3a3a3a3aUL, 0x91919191UL, 0x11111111UL, 0x41414141UL,
+    0x4f4f4f4fUL, 0x67676767UL, 0xdcdcdcdcUL, 0xeaeaeaeaUL,
+    0x97979797UL, 0xf2f2f2f2UL, 0xcfcfcfcfUL, 0xcecececeUL,
+    0xf0f0f0f0UL, 0xb4b4b4b4UL, 0xe6e6e6e6UL, 0x73737373UL,
+    0x96969696UL, 0xacacacacUL, 0x74747474UL, 0x22222222UL,
+    0xe7e7e7e7UL, 0xadadadadUL, 0x35353535UL, 0x85858585UL,
+    0xe2e2e2e2UL, 0xf9f9f9f9UL, 0x37373737UL, 0xe8e8e8e8UL,
+    0x1c1c1c1cUL, 0x75757575UL, 0xdfdfdfdfUL, 0x6e6e6e6eUL,
+    0x47474747UL, 0xf1f1f1f1UL, 0x1a1a1a1aUL, 0x71717171UL,
+    0x1d1d1d1dUL, 0x29292929UL, 0xc5c5c5c5UL, 0x89898989UL,
+    0x6f6f6f6fUL, 0xb7b7b7b7UL, 0x62626262UL, 0x0e0e0e0eUL,
+    0xaaaaaaaaUL, 0x18181818UL, 0xbebebebeUL, 0x1b1b1b1bUL,
+    0xfcfcfcfcUL, 0x56565656UL, 0x3e3e3e3eUL, 0x4b4b4b4bUL,
+    0xc6c6c6c6UL, 0xd2d2d2d2UL, 0x79797979UL, 0x20202020UL,
+    0x9a9a9a9aUL, 0xdbdbdbdbUL, 0xc0c0c0c0UL, 0xfefefefeUL,
+    0x78787878UL, 0xcdcdcdcdUL, 0x5a5a5a5aUL, 0xf4f4f4f4UL,
+    0x1f1f1f1fUL, 0xddddddddUL, 0xa8a8a8a8UL, 0x33333333UL,
+    0x88888888UL, 0x07070707UL, 0xc7c7c7c7UL, 0x31313131UL,
+    0xb1b1b1b1UL, 0x12121212UL, 0x10101010UL, 0x59595959UL,
+    0x27272727UL, 0x80808080UL, 0xececececUL, 0x5f5f5f5fUL,
+    0x60606060UL, 0x51515151UL, 0x7f7f7f7fUL, 0xa9a9a9a9UL,
+    0x19191919UL, 0xb5b5b5b5UL, 0x4a4a4a4aUL, 0x0d0d0d0dUL,
+    0x2d2d2d2dUL, 0xe5e5e5e5UL, 0x7a7a7a7aUL, 0x9f9f9f9fUL,
+    0x93939393UL, 0xc9c9c9c9UL, 0x9c9c9c9cUL, 0xefefefefUL,
+    0xa0a0a0a0UL, 0xe0e0e0e0UL, 0x3b3b3b3bUL, 0x4d4d4d4dUL,
+    0xaeaeaeaeUL, 0x2a2a2a2aUL, 0xf5f5f5f5UL, 0xb0b0b0b0UL,
+    0xc8c8c8c8UL, 0xebebebebUL, 0xbbbbbbbbUL, 0x3c3c3c3cUL,
+    0x83838383UL, 0x53535353UL, 0x99999999UL, 0x61616161UL,
+    0x17171717UL, 0x2b2b2b2bUL, 0x04040404UL, 0x7e7e7e7eUL,
+    0xbabababaUL, 0x77777777UL, 0xd6d6d6d6UL, 0x26262626UL,
+    0xe1e1e1e1UL, 0x69696969UL, 0x14141414UL, 0x63636363UL,
+    0x55555555UL, 0x21212121UL, 0x0c0c0c0cUL, 0x7d7d7d7dUL,
+};
+
+#ifdef LTC_SMALL_CODE
+
+#define Te0(x) TE0[x]
+#define Te1(x) RORc(TE0[x], 8)
+#define Te2(x) RORc(TE0[x], 16)
+#define Te3(x) RORc(TE0[x], 24)
+
+#define Td0(x) TD0[x]
+#define Td1(x) RORc(TD0[x], 8)
+#define Td2(x) RORc(TD0[x], 16)
+#define Td3(x) RORc(TD0[x], 24)
+
+#define Te4_0 0x000000FF & Te4
+#define Te4_1 0x0000FF00 & Te4
+#define Te4_2 0x00FF0000 & Te4
+#define Te4_3 0xFF000000 & Te4
+
+#else
+
+#define Te0(x) TE0[x]
+#define Te1(x) TE1[x]
+#define Te2(x) TE2[x]
+#define Te3(x) TE3[x]
+
+#define Td0(x) TD0[x]
+#define Td1(x) TD1[x]
+#define Td2(x) TD2[x]
+#define Td3(x) TD3[x]
+
+static const ulong32 TE1[256] = {
+    0xa5c66363UL, 0x84f87c7cUL, 0x99ee7777UL, 0x8df67b7bUL,
+    0x0dfff2f2UL, 0xbdd66b6bUL, 0xb1de6f6fUL, 0x5491c5c5UL,
+    0x50603030UL, 0x03020101UL, 0xa9ce6767UL, 0x7d562b2bUL,
+    0x19e7fefeUL, 0x62b5d7d7UL, 0xe64dababUL, 0x9aec7676UL,
+    0x458fcacaUL, 0x9d1f8282UL, 0x4089c9c9UL, 0x87fa7d7dUL,
+    0x15effafaUL, 0xebb25959UL, 0xc98e4747UL, 0x0bfbf0f0UL,
+    0xec41adadUL, 0x67b3d4d4UL, 0xfd5fa2a2UL, 0xea45afafUL,
+    0xbf239c9cUL, 0xf753a4a4UL, 0x96e47272UL, 0x5b9bc0c0UL,
+    0xc275b7b7UL, 0x1ce1fdfdUL, 0xae3d9393UL, 0x6a4c2626UL,
+    0x5a6c3636UL, 0x417e3f3fUL, 0x02f5f7f7UL, 0x4f83ccccUL,
+    0x5c683434UL, 0xf451a5a5UL, 0x34d1e5e5UL, 0x08f9f1f1UL,
+    0x93e27171UL, 0x73abd8d8UL, 0x53623131UL, 0x3f2a1515UL,
+    0x0c080404UL, 0x5295c7c7UL, 0x65462323UL, 0x5e9dc3c3UL,
+    0x28301818UL, 0xa1379696UL, 0x0f0a0505UL, 0xb52f9a9aUL,
+    0x090e0707UL, 0x36241212UL, 0x9b1b8080UL, 0x3ddfe2e2UL,
+    0x26cdebebUL, 0x694e2727UL, 0xcd7fb2b2UL, 0x9fea7575UL,
+    0x1b120909UL, 0x9e1d8383UL, 0x74582c2cUL, 0x2e341a1aUL,
+    0x2d361b1bUL, 0xb2dc6e6eUL, 0xeeb45a5aUL, 0xfb5ba0a0UL,
+    0xf6a45252UL, 0x4d763b3bUL, 0x61b7d6d6UL, 0xce7db3b3UL,
+    0x7b522929UL, 0x3edde3e3UL, 0x715e2f2fUL, 0x97138484UL,
+    0xf5a65353UL, 0x68b9d1d1UL, 0x00000000UL, 0x2cc1ededUL,
+    0x60402020UL, 0x1fe3fcfcUL, 0xc879b1b1UL, 0xedb65b5bUL,
+    0xbed46a6aUL, 0x468dcbcbUL, 0xd967bebeUL, 0x4b723939UL,
+    0xde944a4aUL, 0xd4984c4cUL, 0xe8b05858UL, 0x4a85cfcfUL,
+    0x6bbbd0d0UL, 0x2ac5efefUL, 0xe54faaaaUL, 0x16edfbfbUL,
+    0xc5864343UL, 0xd79a4d4dUL, 0x55663333UL, 0x94118585UL,
+    0xcf8a4545UL, 0x10e9f9f9UL, 0x06040202UL, 0x81fe7f7fUL,
+    0xf0a05050UL, 0x44783c3cUL, 0xba259f9fUL, 0xe34ba8a8UL,
+    0xf3a25151UL, 0xfe5da3a3UL, 0xc0804040UL, 0x8a058f8fUL,
+    0xad3f9292UL, 0xbc219d9dUL, 0x48703838UL, 0x04f1f5f5UL,
+    0xdf63bcbcUL, 0xc177b6b6UL, 0x75afdadaUL, 0x63422121UL,
+    0x30201010UL, 0x1ae5ffffUL, 0x0efdf3f3UL, 0x6dbfd2d2UL,
+    0x4c81cdcdUL, 0x14180c0cUL, 0x35261313UL, 0x2fc3ececUL,
+    0xe1be5f5fUL, 0xa2359797UL, 0xcc884444UL, 0x392e1717UL,
+    0x5793c4c4UL, 0xf255a7a7UL, 0x82fc7e7eUL, 0x477a3d3dUL,
+    0xacc86464UL, 0xe7ba5d5dUL, 0x2b321919UL, 0x95e67373UL,
+    0xa0c06060UL, 0x98198181UL, 0xd19e4f4fUL, 0x7fa3dcdcUL,
+    0x66442222UL, 0x7e542a2aUL, 0xab3b9090UL, 0x830b8888UL,
+    0xca8c4646UL, 0x29c7eeeeUL, 0xd36bb8b8UL, 0x3c281414UL,
+    0x79a7dedeUL, 0xe2bc5e5eUL, 0x1d160b0bUL, 0x76addbdbUL,
+    0x3bdbe0e0UL, 0x56643232UL, 0x4e743a3aUL, 0x1e140a0aUL,
+    0xdb924949UL, 0x0a0c0606UL, 0x6c482424UL, 0xe4b85c5cUL,
+    0x5d9fc2c2UL, 0x6ebdd3d3UL, 0xef43acacUL, 0xa6c46262UL,
+    0xa8399191UL, 0xa4319595UL, 0x37d3e4e4UL, 0x8bf27979UL,
+    0x32d5e7e7UL, 0x438bc8c8UL, 0x596e3737UL, 0xb7da6d6dUL,
+    0x8c018d8dUL, 0x64b1d5d5UL, 0xd29c4e4eUL, 0xe049a9a9UL,
+    0xb4d86c6cUL, 0xfaac5656UL, 0x07f3f4f4UL, 0x25cfeaeaUL,
+    0xafca6565UL, 0x8ef47a7aUL, 0xe947aeaeUL, 0x18100808UL,
+    0xd56fbabaUL, 0x88f07878UL, 0x6f4a2525UL, 0x725c2e2eUL,
+    0x24381c1cUL, 0xf157a6a6UL, 0xc773b4b4UL, 0x5197c6c6UL,
+    0x23cbe8e8UL, 0x7ca1ddddUL, 0x9ce87474UL, 0x213e1f1fUL,
+    0xdd964b4bUL, 0xdc61bdbdUL, 0x860d8b8bUL, 0x850f8a8aUL,
+    0x90e07070UL, 0x427c3e3eUL, 0xc471b5b5UL, 0xaacc6666UL,
+    0xd8904848UL, 0x05060303UL, 0x01f7f6f6UL, 0x121c0e0eUL,
+    0xa3c26161UL, 0x5f6a3535UL, 0xf9ae5757UL, 0xd069b9b9UL,
+    0x91178686UL, 0x5899c1c1UL, 0x273a1d1dUL, 0xb9279e9eUL,
+    0x38d9e1e1UL, 0x13ebf8f8UL, 0xb32b9898UL, 0x33221111UL,
+    0xbbd26969UL, 0x70a9d9d9UL, 0x89078e8eUL, 0xa7339494UL,
+    0xb62d9b9bUL, 0x223c1e1eUL, 0x92158787UL, 0x20c9e9e9UL,
+    0x4987ceceUL, 0xffaa5555UL, 0x78502828UL, 0x7aa5dfdfUL,
+    0x8f038c8cUL, 0xf859a1a1UL, 0x80098989UL, 0x171a0d0dUL,
+    0xda65bfbfUL, 0x31d7e6e6UL, 0xc6844242UL, 0xb8d06868UL,
+    0xc3824141UL, 0xb0299999UL, 0x775a2d2dUL, 0x111e0f0fUL,
+    0xcb7bb0b0UL, 0xfca85454UL, 0xd66dbbbbUL, 0x3a2c1616UL,
+};
+static const ulong32 TE2[256] = {
+    0x63a5c663UL, 0x7c84f87cUL, 0x7799ee77UL, 0x7b8df67bUL,
+    0xf20dfff2UL, 0x6bbdd66bUL, 0x6fb1de6fUL, 0xc55491c5UL,
+    0x30506030UL, 0x01030201UL, 0x67a9ce67UL, 0x2b7d562bUL,
+    0xfe19e7feUL, 0xd762b5d7UL, 0xabe64dabUL, 0x769aec76UL,
+    0xca458fcaUL, 0x829d1f82UL, 0xc94089c9UL, 0x7d87fa7dUL,
+    0xfa15effaUL, 0x59ebb259UL, 0x47c98e47UL, 0xf00bfbf0UL,
+    0xadec41adUL, 0xd467b3d4UL, 0xa2fd5fa2UL, 0xafea45afUL,
+    0x9cbf239cUL, 0xa4f753a4UL, 0x7296e472UL, 0xc05b9bc0UL,
+    0xb7c275b7UL, 0xfd1ce1fdUL, 0x93ae3d93UL, 0x266a4c26UL,
+    0x365a6c36UL, 0x3f417e3fUL, 0xf702f5f7UL, 0xcc4f83ccUL,
+    0x345c6834UL, 0xa5f451a5UL, 0xe534d1e5UL, 0xf108f9f1UL,
+    0x7193e271UL, 0xd873abd8UL, 0x31536231UL, 0x153f2a15UL,
+    0x040c0804UL, 0xc75295c7UL, 0x23654623UL, 0xc35e9dc3UL,
+    0x18283018UL, 0x96a13796UL, 0x050f0a05UL, 0x9ab52f9aUL,
+    0x07090e07UL, 0x12362412UL, 0x809b1b80UL, 0xe23ddfe2UL,
+    0xeb26cdebUL, 0x27694e27UL, 0xb2cd7fb2UL, 0x759fea75UL,
+    0x091b1209UL, 0x839e1d83UL, 0x2c74582cUL, 0x1a2e341aUL,
+    0x1b2d361bUL, 0x6eb2dc6eUL, 0x5aeeb45aUL, 0xa0fb5ba0UL,
+    0x52f6a452UL, 0x3b4d763bUL, 0xd661b7d6UL, 0xb3ce7db3UL,
+    0x297b5229UL, 0xe33edde3UL, 0x2f715e2fUL, 0x84971384UL,
+    0x53f5a653UL, 0xd168b9d1UL, 0x00000000UL, 0xed2cc1edUL,
+    0x20604020UL, 0xfc1fe3fcUL, 0xb1c879b1UL, 0x5bedb65bUL,
+    0x6abed46aUL, 0xcb468dcbUL, 0xbed967beUL, 0x394b7239UL,
+    0x4ade944aUL, 0x4cd4984cUL, 0x58e8b058UL, 0xcf4a85cfUL,
+    0xd06bbbd0UL, 0xef2ac5efUL, 0xaae54faaUL, 0xfb16edfbUL,
+    0x43c58643UL, 0x4dd79a4dUL, 0x33556633UL, 0x85941185UL,
+    0x45cf8a45UL, 0xf910e9f9UL, 0x02060402UL, 0x7f81fe7fUL,
+    0x50f0a050UL, 0x3c44783cUL, 0x9fba259fUL, 0xa8e34ba8UL,
+    0x51f3a251UL, 0xa3fe5da3UL, 0x40c08040UL, 0x8f8a058fUL,
+    0x92ad3f92UL, 0x9dbc219dUL, 0x38487038UL, 0xf504f1f5UL,
+    0xbcdf63bcUL, 0xb6c177b6UL, 0xda75afdaUL, 0x21634221UL,
+    0x10302010UL, 0xff1ae5ffUL, 0xf30efdf3UL, 0xd26dbfd2UL,
+    0xcd4c81cdUL, 0x0c14180cUL, 0x13352613UL, 0xec2fc3ecUL,
+    0x5fe1be5fUL, 0x97a23597UL, 0x44cc8844UL, 0x17392e17UL,
+    0xc45793c4UL, 0xa7f255a7UL, 0x7e82fc7eUL, 0x3d477a3dUL,
+    0x64acc864UL, 0x5de7ba5dUL, 0x192b3219UL, 0x7395e673UL,
+    0x60a0c060UL, 0x81981981UL, 0x4fd19e4fUL, 0xdc7fa3dcUL,
+    0x22664422UL, 0x2a7e542aUL, 0x90ab3b90UL, 0x88830b88UL,
+    0x46ca8c46UL, 0xee29c7eeUL, 0xb8d36bb8UL, 0x143c2814UL,
+    0xde79a7deUL, 0x5ee2bc5eUL, 0x0b1d160bUL, 0xdb76addbUL,
+    0xe03bdbe0UL, 0x32566432UL, 0x3a4e743aUL, 0x0a1e140aUL,
+    0x49db9249UL, 0x060a0c06UL, 0x246c4824UL, 0x5ce4b85cUL,
+    0xc25d9fc2UL, 0xd36ebdd3UL, 0xacef43acUL, 0x62a6c462UL,
+    0x91a83991UL, 0x95a43195UL, 0xe437d3e4UL, 0x798bf279UL,
+    0xe732d5e7UL, 0xc8438bc8UL, 0x37596e37UL, 0x6db7da6dUL,
+    0x8d8c018dUL, 0xd564b1d5UL, 0x4ed29c4eUL, 0xa9e049a9UL,
+    0x6cb4d86cUL, 0x56faac56UL, 0xf407f3f4UL, 0xea25cfeaUL,
+    0x65afca65UL, 0x7a8ef47aUL, 0xaee947aeUL, 0x08181008UL,
+    0xbad56fbaUL, 0x7888f078UL, 0x256f4a25UL, 0x2e725c2eUL,
+    0x1c24381cUL, 0xa6f157a6UL, 0xb4c773b4UL, 0xc65197c6UL,
+    0xe823cbe8UL, 0xdd7ca1ddUL, 0x749ce874UL, 0x1f213e1fUL,
+    0x4bdd964bUL, 0xbddc61bdUL, 0x8b860d8bUL, 0x8a850f8aUL,
+    0x7090e070UL, 0x3e427c3eUL, 0xb5c471b5UL, 0x66aacc66UL,
+    0x48d89048UL, 0x03050603UL, 0xf601f7f6UL, 0x0e121c0eUL,
+    0x61a3c261UL, 0x355f6a35UL, 0x57f9ae57UL, 0xb9d069b9UL,
+    0x86911786UL, 0xc15899c1UL, 0x1d273a1dUL, 0x9eb9279eUL,
+    0xe138d9e1UL, 0xf813ebf8UL, 0x98b32b98UL, 0x11332211UL,
+    0x69bbd269UL, 0xd970a9d9UL, 0x8e89078eUL, 0x94a73394UL,
+    0x9bb62d9bUL, 0x1e223c1eUL, 0x87921587UL, 0xe920c9e9UL,
+    0xce4987ceUL, 0x55ffaa55UL, 0x28785028UL, 0xdf7aa5dfUL,
+    0x8c8f038cUL, 0xa1f859a1UL, 0x89800989UL, 0x0d171a0dUL,
+    0xbfda65bfUL, 0xe631d7e6UL, 0x42c68442UL, 0x68b8d068UL,
+    0x41c38241UL, 0x99b02999UL, 0x2d775a2dUL, 0x0f111e0fUL,
+    0xb0cb7bb0UL, 0x54fca854UL, 0xbbd66dbbUL, 0x163a2c16UL,
+};
+static const ulong32 TE3[256] = {
+
+    0x6363a5c6UL, 0x7c7c84f8UL, 0x777799eeUL, 0x7b7b8df6UL,
+    0xf2f20dffUL, 0x6b6bbdd6UL, 0x6f6fb1deUL, 0xc5c55491UL,
+    0x30305060UL, 0x01010302UL, 0x6767a9ceUL, 0x2b2b7d56UL,
+    0xfefe19e7UL, 0xd7d762b5UL, 0xababe64dUL, 0x76769aecUL,
+    0xcaca458fUL, 0x82829d1fUL, 0xc9c94089UL, 0x7d7d87faUL,
+    0xfafa15efUL, 0x5959ebb2UL, 0x4747c98eUL, 0xf0f00bfbUL,
+    0xadadec41UL, 0xd4d467b3UL, 0xa2a2fd5fUL, 0xafafea45UL,
+    0x9c9cbf23UL, 0xa4a4f753UL, 0x727296e4UL, 0xc0c05b9bUL,
+    0xb7b7c275UL, 0xfdfd1ce1UL, 0x9393ae3dUL, 0x26266a4cUL,
+    0x36365a6cUL, 0x3f3f417eUL, 0xf7f702f5UL, 0xcccc4f83UL,
+    0x34345c68UL, 0xa5a5f451UL, 0xe5e534d1UL, 0xf1f108f9UL,
+    0x717193e2UL, 0xd8d873abUL, 0x31315362UL, 0x15153f2aUL,
+    0x04040c08UL, 0xc7c75295UL, 0x23236546UL, 0xc3c35e9dUL,
+    0x18182830UL, 0x9696a137UL, 0x05050f0aUL, 0x9a9ab52fUL,
+    0x0707090eUL, 0x12123624UL, 0x80809b1bUL, 0xe2e23ddfUL,
+    0xebeb26cdUL, 0x2727694eUL, 0xb2b2cd7fUL, 0x75759feaUL,
+    0x09091b12UL, 0x83839e1dUL, 0x2c2c7458UL, 0x1a1a2e34UL,
+    0x1b1b2d36UL, 0x6e6eb2dcUL, 0x5a5aeeb4UL, 0xa0a0fb5bUL,
+    0x5252f6a4UL, 0x3b3b4d76UL, 0xd6d661b7UL, 0xb3b3ce7dUL,
+    0x29297b52UL, 0xe3e33eddUL, 0x2f2f715eUL, 0x84849713UL,
+    0x5353f5a6UL, 0xd1d168b9UL, 0x00000000UL, 0xeded2cc1UL,
+    0x20206040UL, 0xfcfc1fe3UL, 0xb1b1c879UL, 0x5b5bedb6UL,
+    0x6a6abed4UL, 0xcbcb468dUL, 0xbebed967UL, 0x39394b72UL,
+    0x4a4ade94UL, 0x4c4cd498UL, 0x5858e8b0UL, 0xcfcf4a85UL,
+    0xd0d06bbbUL, 0xefef2ac5UL, 0xaaaae54fUL, 0xfbfb16edUL,
+    0x4343c586UL, 0x4d4dd79aUL, 0x33335566UL, 0x85859411UL,
+    0x4545cf8aUL, 0xf9f910e9UL, 0x02020604UL, 0x7f7f81feUL,
+    0x5050f0a0UL, 0x3c3c4478UL, 0x9f9fba25UL, 0xa8a8e34bUL,
+    0x5151f3a2UL, 0xa3a3fe5dUL, 0x4040c080UL, 0x8f8f8a05UL,
+    0x9292ad3fUL, 0x9d9dbc21UL, 0x38384870UL, 0xf5f504f1UL,
+    0xbcbcdf63UL, 0xb6b6c177UL, 0xdada75afUL, 0x21216342UL,
+    0x10103020UL, 0xffff1ae5UL, 0xf3f30efdUL, 0xd2d26dbfUL,
+    0xcdcd4c81UL, 0x0c0c1418UL, 0x13133526UL, 0xecec2fc3UL,
+    0x5f5fe1beUL, 0x9797a235UL, 0x4444cc88UL, 0x1717392eUL,
+    0xc4c45793UL, 0xa7a7f255UL, 0x7e7e82fcUL, 0x3d3d477aUL,
+    0x6464acc8UL, 0x5d5de7baUL, 0x19192b32UL, 0x737395e6UL,
+    0x6060a0c0UL, 0x81819819UL, 0x4f4fd19eUL, 0xdcdc7fa3UL,
+    0x22226644UL, 0x2a2a7e54UL, 0x9090ab3bUL, 0x8888830bUL,
+    0x4646ca8cUL, 0xeeee29c7UL, 0xb8b8d36bUL, 0x14143c28UL,
+    0xdede79a7UL, 0x5e5ee2bcUL, 0x0b0b1d16UL, 0xdbdb76adUL,
+    0xe0e03bdbUL, 0x32325664UL, 0x3a3a4e74UL, 0x0a0a1e14UL,
+    0x4949db92UL, 0x06060a0cUL, 0x24246c48UL, 0x5c5ce4b8UL,
+    0xc2c25d9fUL, 0xd3d36ebdUL, 0xacacef43UL, 0x6262a6c4UL,
+    0x9191a839UL, 0x9595a431UL, 0xe4e437d3UL, 0x79798bf2UL,
+    0xe7e732d5UL, 0xc8c8438bUL, 0x3737596eUL, 0x6d6db7daUL,
+    0x8d8d8c01UL, 0xd5d564b1UL, 0x4e4ed29cUL, 0xa9a9e049UL,
+    0x6c6cb4d8UL, 0x5656faacUL, 0xf4f407f3UL, 0xeaea25cfUL,
+    0x6565afcaUL, 0x7a7a8ef4UL, 0xaeaee947UL, 0x08081810UL,
+    0xbabad56fUL, 0x787888f0UL, 0x25256f4aUL, 0x2e2e725cUL,
+    0x1c1c2438UL, 0xa6a6f157UL, 0xb4b4c773UL, 0xc6c65197UL,
+    0xe8e823cbUL, 0xdddd7ca1UL, 0x74749ce8UL, 0x1f1f213eUL,
+    0x4b4bdd96UL, 0xbdbddc61UL, 0x8b8b860dUL, 0x8a8a850fUL,
+    0x707090e0UL, 0x3e3e427cUL, 0xb5b5c471UL, 0x6666aaccUL,
+    0x4848d890UL, 0x03030506UL, 0xf6f601f7UL, 0x0e0e121cUL,
+    0x6161a3c2UL, 0x35355f6aUL, 0x5757f9aeUL, 0xb9b9d069UL,
+    0x86869117UL, 0xc1c15899UL, 0x1d1d273aUL, 0x9e9eb927UL,
+    0xe1e138d9UL, 0xf8f813ebUL, 0x9898b32bUL, 0x11113322UL,
+    0x6969bbd2UL, 0xd9d970a9UL, 0x8e8e8907UL, 0x9494a733UL,
+    0x9b9bb62dUL, 0x1e1e223cUL, 0x87879215UL, 0xe9e920c9UL,
+    0xcece4987UL, 0x5555ffaaUL, 0x28287850UL, 0xdfdf7aa5UL,
+    0x8c8c8f03UL, 0xa1a1f859UL, 0x89898009UL, 0x0d0d171aUL,
+    0xbfbfda65UL, 0xe6e631d7UL, 0x4242c684UL, 0x6868b8d0UL,
+    0x4141c382UL, 0x9999b029UL, 0x2d2d775aUL, 0x0f0f111eUL,
+    0xb0b0cb7bUL, 0x5454fca8UL, 0xbbbbd66dUL, 0x16163a2cUL,
+};
+
+#ifndef PELI_TAB
+static const ulong32 Te4_0[] = {
+0x00000063UL, 0x0000007cUL, 0x00000077UL, 0x0000007bUL, 0x000000f2UL, 0x0000006bUL, 0x0000006fUL, 0x000000c5UL, 
+0x00000030UL, 0x00000001UL, 0x00000067UL, 0x0000002bUL, 0x000000feUL, 0x000000d7UL, 0x000000abUL, 0x00000076UL, 
+0x000000caUL, 0x00000082UL, 0x000000c9UL, 0x0000007dUL, 0x000000faUL, 0x00000059UL, 0x00000047UL, 0x000000f0UL, 
+0x000000adUL, 0x000000d4UL, 0x000000a2UL, 0x000000afUL, 0x0000009cUL, 0x000000a4UL, 0x00000072UL, 0x000000c0UL, 
+0x000000b7UL, 0x000000fdUL, 0x00000093UL, 0x00000026UL, 0x00000036UL, 0x0000003fUL, 0x000000f7UL, 0x000000ccUL, 
+0x00000034UL, 0x000000a5UL, 0x000000e5UL, 0x000000f1UL, 0x00000071UL, 0x000000d8UL, 0x00000031UL, 0x00000015UL, 
+0x00000004UL, 0x000000c7UL, 0x00000023UL, 0x000000c3UL, 0x00000018UL, 0x00000096UL, 0x00000005UL, 0x0000009aUL, 
+0x00000007UL, 0x00000012UL, 0x00000080UL, 0x000000e2UL, 0x000000ebUL, 0x00000027UL, 0x000000b2UL, 0x00000075UL, 
+0x00000009UL, 0x00000083UL, 0x0000002cUL, 0x0000001aUL, 0x0000001bUL, 0x0000006eUL, 0x0000005aUL, 0x000000a0UL, 
+0x00000052UL, 0x0000003bUL, 0x000000d6UL, 0x000000b3UL, 0x00000029UL, 0x000000e3UL, 0x0000002fUL, 0x00000084UL, 
+0x00000053UL, 0x000000d1UL, 0x00000000UL, 0x000000edUL, 0x00000020UL, 0x000000fcUL, 0x000000b1UL, 0x0000005bUL, 
+0x0000006aUL, 0x000000cbUL, 0x000000beUL, 0x00000039UL, 0x0000004aUL, 0x0000004cUL, 0x00000058UL, 0x000000cfUL, 
+0x000000d0UL, 0x000000efUL, 0x000000aaUL, 0x000000fbUL, 0x00000043UL, 0x0000004dUL, 0x00000033UL, 0x00000085UL, 
+0x00000045UL, 0x000000f9UL, 0x00000002UL, 0x0000007fUL, 0x00000050UL, 0x0000003cUL, 0x0000009fUL, 0x000000a8UL, 
+0x00000051UL, 0x000000a3UL, 0x00000040UL, 0x0000008fUL, 0x00000092UL, 0x0000009dUL, 0x00000038UL, 0x000000f5UL, 
+0x000000bcUL, 0x000000b6UL, 0x000000daUL, 0x00000021UL, 0x00000010UL, 0x000000ffUL, 0x000000f3UL, 0x000000d2UL, 
+0x000000cdUL, 0x0000000cUL, 0x00000013UL, 0x000000ecUL, 0x0000005fUL, 0x00000097UL, 0x00000044UL, 0x00000017UL, 
+0x000000c4UL, 0x000000a7UL, 0x0000007eUL, 0x0000003dUL, 0x00000064UL, 0x0000005dUL, 0x00000019UL, 0x00000073UL, 
+0x00000060UL, 0x00000081UL, 0x0000004fUL, 0x000000dcUL, 0x00000022UL, 0x0000002aUL, 0x00000090UL, 0x00000088UL, 
+0x00000046UL, 0x000000eeUL, 0x000000b8UL, 0x00000014UL, 0x000000deUL, 0x0000005eUL, 0x0000000bUL, 0x000000dbUL, 
+0x000000e0UL, 0x00000032UL, 0x0000003aUL, 0x0000000aUL, 0x00000049UL, 0x00000006UL, 0x00000024UL, 0x0000005cUL, 
+0x000000c2UL, 0x000000d3UL, 0x000000acUL, 0x00000062UL, 0x00000091UL, 0x00000095UL, 0x000000e4UL, 0x00000079UL, 
+0x000000e7UL, 0x000000c8UL, 0x00000037UL, 0x0000006dUL, 0x0000008dUL, 0x000000d5UL, 0x0000004eUL, 0x000000a9UL, 
+0x0000006cUL, 0x00000056UL, 0x000000f4UL, 0x000000eaUL, 0x00000065UL, 0x0000007aUL, 0x000000aeUL, 0x00000008UL, 
+0x000000baUL, 0x00000078UL, 0x00000025UL, 0x0000002eUL, 0x0000001cUL, 0x000000a6UL, 0x000000b4UL, 0x000000c6UL, 
+0x000000e8UL, 0x000000ddUL, 0x00000074UL, 0x0000001fUL, 0x0000004bUL, 0x000000bdUL, 0x0000008bUL, 0x0000008aUL, 
+0x00000070UL, 0x0000003eUL, 0x000000b5UL, 0x00000066UL, 0x00000048UL, 0x00000003UL, 0x000000f6UL, 0x0000000eUL, 
+0x00000061UL, 0x00000035UL, 0x00000057UL, 0x000000b9UL, 0x00000086UL, 0x000000c1UL, 0x0000001dUL, 0x0000009eUL, 
+0x000000e1UL, 0x000000f8UL, 0x00000098UL, 0x00000011UL, 0x00000069UL, 0x000000d9UL, 0x0000008eUL, 0x00000094UL, 
+0x0000009bUL, 0x0000001eUL, 0x00000087UL, 0x000000e9UL, 0x000000ceUL, 0x00000055UL, 0x00000028UL, 0x000000dfUL, 
+0x0000008cUL, 0x000000a1UL, 0x00000089UL, 0x0000000dUL, 0x000000bfUL, 0x000000e6UL, 0x00000042UL, 0x00000068UL, 
+0x00000041UL, 0x00000099UL, 0x0000002dUL, 0x0000000fUL, 0x000000b0UL, 0x00000054UL, 0x000000bbUL, 0x00000016UL
+};
+
+static const ulong32 Te4_1[] = {
+0x00006300UL, 0x00007c00UL, 0x00007700UL, 0x00007b00UL, 0x0000f200UL, 0x00006b00UL, 0x00006f00UL, 0x0000c500UL, 
+0x00003000UL, 0x00000100UL, 0x00006700UL, 0x00002b00UL, 0x0000fe00UL, 0x0000d700UL, 0x0000ab00UL, 0x00007600UL, 
+0x0000ca00UL, 0x00008200UL, 0x0000c900UL, 0x00007d00UL, 0x0000fa00UL, 0x00005900UL, 0x00004700UL, 0x0000f000UL, 
+0x0000ad00UL, 0x0000d400UL, 0x0000a200UL, 0x0000af00UL, 0x00009c00UL, 0x0000a400UL, 0x00007200UL, 0x0000c000UL, 
+0x0000b700UL, 0x0000fd00UL, 0x00009300UL, 0x00002600UL, 0x00003600UL, 0x00003f00UL, 0x0000f700UL, 0x0000cc00UL, 
+0x00003400UL, 0x0000a500UL, 0x0000e500UL, 0x0000f100UL, 0x00007100UL, 0x0000d800UL, 0x00003100UL, 0x00001500UL, 
+0x00000400UL, 0x0000c700UL, 0x00002300UL, 0x0000c300UL, 0x00001800UL, 0x00009600UL, 0x00000500UL, 0x00009a00UL, 
+0x00000700UL, 0x00001200UL, 0x00008000UL, 0x0000e200UL, 0x0000eb00UL, 0x00002700UL, 0x0000b200UL, 0x00007500UL, 
+0x00000900UL, 0x00008300UL, 0x00002c00UL, 0x00001a00UL, 0x00001b00UL, 0x00006e00UL, 0x00005a00UL, 0x0000a000UL, 
+0x00005200UL, 0x00003b00UL, 0x0000d600UL, 0x0000b300UL, 0x00002900UL, 0x0000e300UL, 0x00002f00UL, 0x00008400UL, 
+0x00005300UL, 0x0000d100UL, 0x00000000UL, 0x0000ed00UL, 0x00002000UL, 0x0000fc00UL, 0x0000b100UL, 0x00005b00UL, 
+0x00006a00UL, 0x0000cb00UL, 0x0000be00UL, 0x00003900UL, 0x00004a00UL, 0x00004c00UL, 0x00005800UL, 0x0000cf00UL, 
+0x0000d000UL, 0x0000ef00UL, 0x0000aa00UL, 0x0000fb00UL, 0x00004300UL, 0x00004d00UL, 0x00003300UL, 0x00008500UL, 
+0x00004500UL, 0x0000f900UL, 0x00000200UL, 0x00007f00UL, 0x00005000UL, 0x00003c00UL, 0x00009f00UL, 0x0000a800UL, 
+0x00005100UL, 0x0000a300UL, 0x00004000UL, 0x00008f00UL, 0x00009200UL, 0x00009d00UL, 0x00003800UL, 0x0000f500UL, 
+0x0000bc00UL, 0x0000b600UL, 0x0000da00UL, 0x00002100UL, 0x00001000UL, 0x0000ff00UL, 0x0000f300UL, 0x0000d200UL, 
+0x0000cd00UL, 0x00000c00UL, 0x00001300UL, 0x0000ec00UL, 0x00005f00UL, 0x00009700UL, 0x00004400UL, 0x00001700UL, 
+0x0000c400UL, 0x0000a700UL, 0x00007e00UL, 0x00003d00UL, 0x00006400UL, 0x00005d00UL, 0x00001900UL, 0x00007300UL, 
+0x00006000UL, 0x00008100UL, 0x00004f00UL, 0x0000dc00UL, 0x00002200UL, 0x00002a00UL, 0x00009000UL, 0x00008800UL, 
+0x00004600UL, 0x0000ee00UL, 0x0000b800UL, 0x00001400UL, 0x0000de00UL, 0x00005e00UL, 0x00000b00UL, 0x0000db00UL, 
+0x0000e000UL, 0x00003200UL, 0x00003a00UL, 0x00000a00UL, 0x00004900UL, 0x00000600UL, 0x00002400UL, 0x00005c00UL, 
+0x0000c200UL, 0x0000d300UL, 0x0000ac00UL, 0x00006200UL, 0x00009100UL, 0x00009500UL, 0x0000e400UL, 0x00007900UL, 
+0x0000e700UL, 0x0000c800UL, 0x00003700UL, 0x00006d00UL, 0x00008d00UL, 0x0000d500UL, 0x00004e00UL, 0x0000a900UL, 
+0x00006c00UL, 0x00005600UL, 0x0000f400UL, 0x0000ea00UL, 0x00006500UL, 0x00007a00UL, 0x0000ae00UL, 0x00000800UL, 
+0x0000ba00UL, 0x00007800UL, 0x00002500UL, 0x00002e00UL, 0x00001c00UL, 0x0000a600UL, 0x0000b400UL, 0x0000c600UL, 
+0x0000e800UL, 0x0000dd00UL, 0x00007400UL, 0x00001f00UL, 0x00004b00UL, 0x0000bd00UL, 0x00008b00UL, 0x00008a00UL, 
+0x00007000UL, 0x00003e00UL, 0x0000b500UL, 0x00006600UL, 0x00004800UL, 0x00000300UL, 0x0000f600UL, 0x00000e00UL, 
+0x00006100UL, 0x00003500UL, 0x00005700UL, 0x0000b900UL, 0x00008600UL, 0x0000c100UL, 0x00001d00UL, 0x00009e00UL, 
+0x0000e100UL, 0x0000f800UL, 0x00009800UL, 0x00001100UL, 0x00006900UL, 0x0000d900UL, 0x00008e00UL, 0x00009400UL, 
+0x00009b00UL, 0x00001e00UL, 0x00008700UL, 0x0000e900UL, 0x0000ce00UL, 0x00005500UL, 0x00002800UL, 0x0000df00UL, 
+0x00008c00UL, 0x0000a100UL, 0x00008900UL, 0x00000d00UL, 0x0000bf00UL, 0x0000e600UL, 0x00004200UL, 0x00006800UL, 
+0x00004100UL, 0x00009900UL, 0x00002d00UL, 0x00000f00UL, 0x0000b000UL, 0x00005400UL, 0x0000bb00UL, 0x00001600UL
+};
+
+static const ulong32 Te4_2[] = {
+0x00630000UL, 0x007c0000UL, 0x00770000UL, 0x007b0000UL, 0x00f20000UL, 0x006b0000UL, 0x006f0000UL, 0x00c50000UL, 
+0x00300000UL, 0x00010000UL, 0x00670000UL, 0x002b0000UL, 0x00fe0000UL, 0x00d70000UL, 0x00ab0000UL, 0x00760000UL, 
+0x00ca0000UL, 0x00820000UL, 0x00c90000UL, 0x007d0000UL, 0x00fa0000UL, 0x00590000UL, 0x00470000UL, 0x00f00000UL, 
+0x00ad0000UL, 0x00d40000UL, 0x00a20000UL, 0x00af0000UL, 0x009c0000UL, 0x00a40000UL, 0x00720000UL, 0x00c00000UL, 
+0x00b70000UL, 0x00fd0000UL, 0x00930000UL, 0x00260000UL, 0x00360000UL, 0x003f0000UL, 0x00f70000UL, 0x00cc0000UL, 
+0x00340000UL, 0x00a50000UL, 0x00e50000UL, 0x00f10000UL, 0x00710000UL, 0x00d80000UL, 0x00310000UL, 0x00150000UL, 
+0x00040000UL, 0x00c70000UL, 0x00230000UL, 0x00c30000UL, 0x00180000UL, 0x00960000UL, 0x00050000UL, 0x009a0000UL, 
+0x00070000UL, 0x00120000UL, 0x00800000UL, 0x00e20000UL, 0x00eb0000UL, 0x00270000UL, 0x00b20000UL, 0x00750000UL, 
+0x00090000UL, 0x00830000UL, 0x002c0000UL, 0x001a0000UL, 0x001b0000UL, 0x006e0000UL, 0x005a0000UL, 0x00a00000UL, 
+0x00520000UL, 0x003b0000UL, 0x00d60000UL, 0x00b30000UL, 0x00290000UL, 0x00e30000UL, 0x002f0000UL, 0x00840000UL, 
+0x00530000UL, 0x00d10000UL, 0x00000000UL, 0x00ed0000UL, 0x00200000UL, 0x00fc0000UL, 0x00b10000UL, 0x005b0000UL, 
+0x006a0000UL, 0x00cb0000UL, 0x00be0000UL, 0x00390000UL, 0x004a0000UL, 0x004c0000UL, 0x00580000UL, 0x00cf0000UL, 
+0x00d00000UL, 0x00ef0000UL, 0x00aa0000UL, 0x00fb0000UL, 0x00430000UL, 0x004d0000UL, 0x00330000UL, 0x00850000UL, 
+0x00450000UL, 0x00f90000UL, 0x00020000UL, 0x007f0000UL, 0x00500000UL, 0x003c0000UL, 0x009f0000UL, 0x00a80000UL, 
+0x00510000UL, 0x00a30000UL, 0x00400000UL, 0x008f0000UL, 0x00920000UL, 0x009d0000UL, 0x00380000UL, 0x00f50000UL, 
+0x00bc0000UL, 0x00b60000UL, 0x00da0000UL, 0x00210000UL, 0x00100000UL, 0x00ff0000UL, 0x00f30000UL, 0x00d20000UL, 
+0x00cd0000UL, 0x000c0000UL, 0x00130000UL, 0x00ec0000UL, 0x005f0000UL, 0x00970000UL, 0x00440000UL, 0x00170000UL, 
+0x00c40000UL, 0x00a70000UL, 0x007e0000UL, 0x003d0000UL, 0x00640000UL, 0x005d0000UL, 0x00190000UL, 0x00730000UL, 
+0x00600000UL, 0x00810000UL, 0x004f0000UL, 0x00dc0000UL, 0x00220000UL, 0x002a0000UL, 0x00900000UL, 0x00880000UL, 
+0x00460000UL, 0x00ee0000UL, 0x00b80000UL, 0x00140000UL, 0x00de0000UL, 0x005e0000UL, 0x000b0000UL, 0x00db0000UL, 
+0x00e00000UL, 0x00320000UL, 0x003a0000UL, 0x000a0000UL, 0x00490000UL, 0x00060000UL, 0x00240000UL, 0x005c0000UL, 
+0x00c20000UL, 0x00d30000UL, 0x00ac0000UL, 0x00620000UL, 0x00910000UL, 0x00950000UL, 0x00e40000UL, 0x00790000UL, 
+0x00e70000UL, 0x00c80000UL, 0x00370000UL, 0x006d0000UL, 0x008d0000UL, 0x00d50000UL, 0x004e0000UL, 0x00a90000UL, 
+0x006c0000UL, 0x00560000UL, 0x00f40000UL, 0x00ea0000UL, 0x00650000UL, 0x007a0000UL, 0x00ae0000UL, 0x00080000UL, 
+0x00ba0000UL, 0x00780000UL, 0x00250000UL, 0x002e0000UL, 0x001c0000UL, 0x00a60000UL, 0x00b40000UL, 0x00c60000UL, 
+0x00e80000UL, 0x00dd0000UL, 0x00740000UL, 0x001f0000UL, 0x004b0000UL, 0x00bd0000UL, 0x008b0000UL, 0x008a0000UL, 
+0x00700000UL, 0x003e0000UL, 0x00b50000UL, 0x00660000UL, 0x00480000UL, 0x00030000UL, 0x00f60000UL, 0x000e0000UL, 
+0x00610000UL, 0x00350000UL, 0x00570000UL, 0x00b90000UL, 0x00860000UL, 0x00c10000UL, 0x001d0000UL, 0x009e0000UL, 
+0x00e10000UL, 0x00f80000UL, 0x00980000UL, 0x00110000UL, 0x00690000UL, 0x00d90000UL, 0x008e0000UL, 0x00940000UL, 
+0x009b0000UL, 0x001e0000UL, 0x00870000UL, 0x00e90000UL, 0x00ce0000UL, 0x00550000UL, 0x00280000UL, 0x00df0000UL, 
+0x008c0000UL, 0x00a10000UL, 0x00890000UL, 0x000d0000UL, 0x00bf0000UL, 0x00e60000UL, 0x00420000UL, 0x00680000UL, 
+0x00410000UL, 0x00990000UL, 0x002d0000UL, 0x000f0000UL, 0x00b00000UL, 0x00540000UL, 0x00bb0000UL, 0x00160000UL
+};
+
+static const ulong32 Te4_3[] = {
+0x63000000UL, 0x7c000000UL, 0x77000000UL, 0x7b000000UL, 0xf2000000UL, 0x6b000000UL, 0x6f000000UL, 0xc5000000UL, 
+0x30000000UL, 0x01000000UL, 0x67000000UL, 0x2b000000UL, 0xfe000000UL, 0xd7000000UL, 0xab000000UL, 0x76000000UL, 
+0xca000000UL, 0x82000000UL, 0xc9000000UL, 0x7d000000UL, 0xfa000000UL, 0x59000000UL, 0x47000000UL, 0xf0000000UL, 
+0xad000000UL, 0xd4000000UL, 0xa2000000UL, 0xaf000000UL, 0x9c000000UL, 0xa4000000UL, 0x72000000UL, 0xc0000000UL, 
+0xb7000000UL, 0xfd000000UL, 0x93000000UL, 0x26000000UL, 0x36000000UL, 0x3f000000UL, 0xf7000000UL, 0xcc000000UL, 
+0x34000000UL, 0xa5000000UL, 0xe5000000UL, 0xf1000000UL, 0x71000000UL, 0xd8000000UL, 0x31000000UL, 0x15000000UL, 
+0x04000000UL, 0xc7000000UL, 0x23000000UL, 0xc3000000UL, 0x18000000UL, 0x96000000UL, 0x05000000UL, 0x9a000000UL, 
+0x07000000UL, 0x12000000UL, 0x80000000UL, 0xe2000000UL, 0xeb000000UL, 0x27000000UL, 0xb2000000UL, 0x75000000UL, 
+0x09000000UL, 0x83000000UL, 0x2c000000UL, 0x1a000000UL, 0x1b000000UL, 0x6e000000UL, 0x5a000000UL, 0xa0000000UL, 
+0x52000000UL, 0x3b000000UL, 0xd6000000UL, 0xb3000000UL, 0x29000000UL, 0xe3000000UL, 0x2f000000UL, 0x84000000UL, 
+0x53000000UL, 0xd1000000UL, 0x00000000UL, 0xed000000UL, 0x20000000UL, 0xfc000000UL, 0xb1000000UL, 0x5b000000UL, 
+0x6a000000UL, 0xcb000000UL, 0xbe000000UL, 0x39000000UL, 0x4a000000UL, 0x4c000000UL, 0x58000000UL, 0xcf000000UL, 
+0xd0000000UL, 0xef000000UL, 0xaa000000UL, 0xfb000000UL, 0x43000000UL, 0x4d000000UL, 0x33000000UL, 0x85000000UL, 
+0x45000000UL, 0xf9000000UL, 0x02000000UL, 0x7f000000UL, 0x50000000UL, 0x3c000000UL, 0x9f000000UL, 0xa8000000UL, 
+0x51000000UL, 0xa3000000UL, 0x40000000UL, 0x8f000000UL, 0x92000000UL, 0x9d000000UL, 0x38000000UL, 0xf5000000UL, 
+0xbc000000UL, 0xb6000000UL, 0xda000000UL, 0x21000000UL, 0x10000000UL, 0xff000000UL, 0xf3000000UL, 0xd2000000UL, 
+0xcd000000UL, 0x0c000000UL, 0x13000000UL, 0xec000000UL, 0x5f000000UL, 0x97000000UL, 0x44000000UL, 0x17000000UL, 
+0xc4000000UL, 0xa7000000UL, 0x7e000000UL, 0x3d000000UL, 0x64000000UL, 0x5d000000UL, 0x19000000UL, 0x73000000UL, 
+0x60000000UL, 0x81000000UL, 0x4f000000UL, 0xdc000000UL, 0x22000000UL, 0x2a000000UL, 0x90000000UL, 0x88000000UL, 
+0x46000000UL, 0xee000000UL, 0xb8000000UL, 0x14000000UL, 0xde000000UL, 0x5e000000UL, 0x0b000000UL, 0xdb000000UL, 
+0xe0000000UL, 0x32000000UL, 0x3a000000UL, 0x0a000000UL, 0x49000000UL, 0x06000000UL, 0x24000000UL, 0x5c000000UL, 
+0xc2000000UL, 0xd3000000UL, 0xac000000UL, 0x62000000UL, 0x91000000UL, 0x95000000UL, 0xe4000000UL, 0x79000000UL, 
+0xe7000000UL, 0xc8000000UL, 0x37000000UL, 0x6d000000UL, 0x8d000000UL, 0xd5000000UL, 0x4e000000UL, 0xa9000000UL, 
+0x6c000000UL, 0x56000000UL, 0xf4000000UL, 0xea000000UL, 0x65000000UL, 0x7a000000UL, 0xae000000UL, 0x08000000UL, 
+0xba000000UL, 0x78000000UL, 0x25000000UL, 0x2e000000UL, 0x1c000000UL, 0xa6000000UL, 0xb4000000UL, 0xc6000000UL, 
+0xe8000000UL, 0xdd000000UL, 0x74000000UL, 0x1f000000UL, 0x4b000000UL, 0xbd000000UL, 0x8b000000UL, 0x8a000000UL, 
+0x70000000UL, 0x3e000000UL, 0xb5000000UL, 0x66000000UL, 0x48000000UL, 0x03000000UL, 0xf6000000UL, 0x0e000000UL, 
+0x61000000UL, 0x35000000UL, 0x57000000UL, 0xb9000000UL, 0x86000000UL, 0xc1000000UL, 0x1d000000UL, 0x9e000000UL, 
+0xe1000000UL, 0xf8000000UL, 0x98000000UL, 0x11000000UL, 0x69000000UL, 0xd9000000UL, 0x8e000000UL, 0x94000000UL, 
+0x9b000000UL, 0x1e000000UL, 0x87000000UL, 0xe9000000UL, 0xce000000UL, 0x55000000UL, 0x28000000UL, 0xdf000000UL, 
+0x8c000000UL, 0xa1000000UL, 0x89000000UL, 0x0d000000UL, 0xbf000000UL, 0xe6000000UL, 0x42000000UL, 0x68000000UL, 
+0x41000000UL, 0x99000000UL, 0x2d000000UL, 0x0f000000UL, 0xb0000000UL, 0x54000000UL, 0xbb000000UL, 0x16000000UL
+};
+#endif /* pelimac */
+
+static const ulong32 TD1[256] = {
+    0x5051f4a7UL, 0x537e4165UL, 0xc31a17a4UL, 0x963a275eUL,
+    0xcb3bab6bUL, 0xf11f9d45UL, 0xabacfa58UL, 0x934be303UL,
+    0x552030faUL, 0xf6ad766dUL, 0x9188cc76UL, 0x25f5024cUL,
+    0xfc4fe5d7UL, 0xd7c52acbUL, 0x80263544UL, 0x8fb562a3UL,
+    0x49deb15aUL, 0x6725ba1bUL, 0x9845ea0eUL, 0xe15dfec0UL,
+    0x02c32f75UL, 0x12814cf0UL, 0xa38d4697UL, 0xc66bd3f9UL,
+    0xe7038f5fUL, 0x9515929cUL, 0xebbf6d7aUL, 0xda955259UL,
+    0x2dd4be83UL, 0xd3587421UL, 0x2949e069UL, 0x448ec9c8UL,
+    0x6a75c289UL, 0x78f48e79UL, 0x6b99583eUL, 0xdd27b971UL,
+    0xb6bee14fUL, 0x17f088adUL, 0x66c920acUL, 0xb47dce3aUL,
+    0x1863df4aUL, 0x82e51a31UL, 0x60975133UL, 0x4562537fUL,
+    0xe0b16477UL, 0x84bb6baeUL, 0x1cfe81a0UL, 0x94f9082bUL,
+    0x58704868UL, 0x198f45fdUL, 0x8794de6cUL, 0xb7527bf8UL,
+    0x23ab73d3UL, 0xe2724b02UL, 0x57e31f8fUL, 0x2a6655abUL,
+    0x07b2eb28UL, 0x032fb5c2UL, 0x9a86c57bUL, 0xa5d33708UL,
+    0xf2302887UL, 0xb223bfa5UL, 0xba02036aUL, 0x5ced1682UL,
+    0x2b8acf1cUL, 0x92a779b4UL, 0xf0f307f2UL, 0xa14e69e2UL,
+    0xcd65daf4UL, 0xd50605beUL, 0x1fd13462UL, 0x8ac4a6feUL,
+    0x9d342e53UL, 0xa0a2f355UL, 0x32058ae1UL, 0x75a4f6ebUL,
+    0x390b83ecUL, 0xaa4060efUL, 0x065e719fUL, 0x51bd6e10UL,
+    0xf93e218aUL, 0x3d96dd06UL, 0xaedd3e05UL, 0x464de6bdUL,
+    0xb591548dUL, 0x0571c45dUL, 0x6f0406d4UL, 0xff605015UL,
+    0x241998fbUL, 0x97d6bde9UL, 0xcc894043UL, 0x7767d99eUL,
+    0xbdb0e842UL, 0x8807898bUL, 0x38e7195bUL, 0xdb79c8eeUL,
+    0x47a17c0aUL, 0xe97c420fUL, 0xc9f8841eUL, 0x00000000UL,
+    0x83098086UL, 0x48322bedUL, 0xac1e1170UL, 0x4e6c5a72UL,
+    0xfbfd0effUL, 0x560f8538UL, 0x1e3daed5UL, 0x27362d39UL,
+    0x640a0fd9UL, 0x21685ca6UL, 0xd19b5b54UL, 0x3a24362eUL,
+    0xb10c0a67UL, 0x0f9357e7UL, 0xd2b4ee96UL, 0x9e1b9b91UL,
+    0x4f80c0c5UL, 0xa261dc20UL, 0x695a774bUL, 0x161c121aUL,
+    0x0ae293baUL, 0xe5c0a02aUL, 0x433c22e0UL, 0x1d121b17UL,
+    0x0b0e090dUL, 0xadf28bc7UL, 0xb92db6a8UL, 0xc8141ea9UL,
+    0x8557f119UL, 0x4caf7507UL, 0xbbee99ddUL, 0xfda37f60UL,
+    0x9ff70126UL, 0xbc5c72f5UL, 0xc544663bUL, 0x345bfb7eUL,
+    0x768b4329UL, 0xdccb23c6UL, 0x68b6edfcUL, 0x63b8e4f1UL,
+    0xcad731dcUL, 0x10426385UL, 0x40139722UL, 0x2084c611UL,
+    0x7d854a24UL, 0xf8d2bb3dUL, 0x11aef932UL, 0x6dc729a1UL,
+    0x4b1d9e2fUL, 0xf3dcb230UL, 0xec0d8652UL, 0xd077c1e3UL,
+    0x6c2bb316UL, 0x99a970b9UL, 0xfa119448UL, 0x2247e964UL,
+    0xc4a8fc8cUL, 0x1aa0f03fUL, 0xd8567d2cUL, 0xef223390UL,
+    0xc787494eUL, 0xc1d938d1UL, 0xfe8ccaa2UL, 0x3698d40bUL,
+    0xcfa6f581UL, 0x28a57adeUL, 0x26dab78eUL, 0xa43fadbfUL,
+    0xe42c3a9dUL, 0x0d507892UL, 0x9b6a5fccUL, 0x62547e46UL,
+    0xc2f68d13UL, 0xe890d8b8UL, 0x5e2e39f7UL, 0xf582c3afUL,
+    0xbe9f5d80UL, 0x7c69d093UL, 0xa96fd52dUL, 0xb3cf2512UL,
+    0x3bc8ac99UL, 0xa710187dUL, 0x6ee89c63UL, 0x7bdb3bbbUL,
+    0x09cd2678UL, 0xf46e5918UL, 0x01ec9ab7UL, 0xa8834f9aUL,
+    0x65e6956eUL, 0x7eaaffe6UL, 0x0821bccfUL, 0xe6ef15e8UL,
+    0xd9bae79bUL, 0xce4a6f36UL, 0xd4ea9f09UL, 0xd629b07cUL,
+    0xaf31a4b2UL, 0x312a3f23UL, 0x30c6a594UL, 0xc035a266UL,
+    0x37744ebcUL, 0xa6fc82caUL, 0xb0e090d0UL, 0x1533a7d8UL,
+    0x4af10498UL, 0xf741ecdaUL, 0x0e7fcd50UL, 0x2f1791f6UL,
+    0x8d764dd6UL, 0x4d43efb0UL, 0x54ccaa4dUL, 0xdfe49604UL,
+    0xe39ed1b5UL, 0x1b4c6a88UL, 0xb8c12c1fUL, 0x7f466551UL,
+    0x049d5eeaUL, 0x5d018c35UL, 0x73fa8774UL, 0x2efb0b41UL,
+    0x5ab3671dUL, 0x5292dbd2UL, 0x33e91056UL, 0x136dd647UL,
+    0x8c9ad761UL, 0x7a37a10cUL, 0x8e59f814UL, 0x89eb133cUL,
+    0xeecea927UL, 0x35b761c9UL, 0xede11ce5UL, 0x3c7a47b1UL,
+    0x599cd2dfUL, 0x3f55f273UL, 0x791814ceUL, 0xbf73c737UL,
+    0xea53f7cdUL, 0x5b5ffdaaUL, 0x14df3d6fUL, 0x867844dbUL,
+    0x81caaff3UL, 0x3eb968c4UL, 0x2c382434UL, 0x5fc2a340UL,
+    0x72161dc3UL, 0x0cbce225UL, 0x8b283c49UL, 0x41ff0d95UL,
+    0x7139a801UL, 0xde080cb3UL, 0x9cd8b4e4UL, 0x906456c1UL,
+    0x617bcb84UL, 0x70d532b6UL, 0x74486c5cUL, 0x42d0b857UL,
+};
+static const ulong32 TD2[256] = {
+    0xa75051f4UL, 0x65537e41UL, 0xa4c31a17UL, 0x5e963a27UL,
+    0x6bcb3babUL, 0x45f11f9dUL, 0x58abacfaUL, 0x03934be3UL,
+    0xfa552030UL, 0x6df6ad76UL, 0x769188ccUL, 0x4c25f502UL,
+    0xd7fc4fe5UL, 0xcbd7c52aUL, 0x44802635UL, 0xa38fb562UL,
+    0x5a49deb1UL, 0x1b6725baUL, 0x0e9845eaUL, 0xc0e15dfeUL,
+    0x7502c32fUL, 0xf012814cUL, 0x97a38d46UL, 0xf9c66bd3UL,
+    0x5fe7038fUL, 0x9c951592UL, 0x7aebbf6dUL, 0x59da9552UL,
+    0x832dd4beUL, 0x21d35874UL, 0x692949e0UL, 0xc8448ec9UL,
+    0x896a75c2UL, 0x7978f48eUL, 0x3e6b9958UL, 0x71dd27b9UL,
+    0x4fb6bee1UL, 0xad17f088UL, 0xac66c920UL, 0x3ab47dceUL,
+    0x4a1863dfUL, 0x3182e51aUL, 0x33609751UL, 0x7f456253UL,
+    0x77e0b164UL, 0xae84bb6bUL, 0xa01cfe81UL, 0x2b94f908UL,
+    0x68587048UL, 0xfd198f45UL, 0x6c8794deUL, 0xf8b7527bUL,
+    0xd323ab73UL, 0x02e2724bUL, 0x8f57e31fUL, 0xab2a6655UL,
+    0x2807b2ebUL, 0xc2032fb5UL, 0x7b9a86c5UL, 0x08a5d337UL,
+    0x87f23028UL, 0xa5b223bfUL, 0x6aba0203UL, 0x825ced16UL,
+    0x1c2b8acfUL, 0xb492a779UL, 0xf2f0f307UL, 0xe2a14e69UL,
+    0xf4cd65daUL, 0xbed50605UL, 0x621fd134UL, 0xfe8ac4a6UL,
+    0x539d342eUL, 0x55a0a2f3UL, 0xe132058aUL, 0xeb75a4f6UL,
+    0xec390b83UL, 0xefaa4060UL, 0x9f065e71UL, 0x1051bd6eUL,
+    0x8af93e21UL, 0x063d96ddUL, 0x05aedd3eUL, 0xbd464de6UL,
+    0x8db59154UL, 0x5d0571c4UL, 0xd46f0406UL, 0x15ff6050UL,
+    0xfb241998UL, 0xe997d6bdUL, 0x43cc8940UL, 0x9e7767d9UL,
+    0x42bdb0e8UL, 0x8b880789UL, 0x5b38e719UL, 0xeedb79c8UL,
+    0x0a47a17cUL, 0x0fe97c42UL, 0x1ec9f884UL, 0x00000000UL,
+    0x86830980UL, 0xed48322bUL, 0x70ac1e11UL, 0x724e6c5aUL,
+    0xfffbfd0eUL, 0x38560f85UL, 0xd51e3daeUL, 0x3927362dUL,
+    0xd9640a0fUL, 0xa621685cUL, 0x54d19b5bUL, 0x2e3a2436UL,
+    0x67b10c0aUL, 0xe70f9357UL, 0x96d2b4eeUL, 0x919e1b9bUL,
+    0xc54f80c0UL, 0x20a261dcUL, 0x4b695a77UL, 0x1a161c12UL,
+    0xba0ae293UL, 0x2ae5c0a0UL, 0xe0433c22UL, 0x171d121bUL,
+    0x0d0b0e09UL, 0xc7adf28bUL, 0xa8b92db6UL, 0xa9c8141eUL,
+    0x198557f1UL, 0x074caf75UL, 0xddbbee99UL, 0x60fda37fUL,
+    0x269ff701UL, 0xf5bc5c72UL, 0x3bc54466UL, 0x7e345bfbUL,
+    0x29768b43UL, 0xc6dccb23UL, 0xfc68b6edUL, 0xf163b8e4UL,
+    0xdccad731UL, 0x85104263UL, 0x22401397UL, 0x112084c6UL,
+    0x247d854aUL, 0x3df8d2bbUL, 0x3211aef9UL, 0xa16dc729UL,
+    0x2f4b1d9eUL, 0x30f3dcb2UL, 0x52ec0d86UL, 0xe3d077c1UL,
+    0x166c2bb3UL, 0xb999a970UL, 0x48fa1194UL, 0x642247e9UL,
+    0x8cc4a8fcUL, 0x3f1aa0f0UL, 0x2cd8567dUL, 0x90ef2233UL,
+    0x4ec78749UL, 0xd1c1d938UL, 0xa2fe8ccaUL, 0x0b3698d4UL,
+    0x81cfa6f5UL, 0xde28a57aUL, 0x8e26dab7UL, 0xbfa43fadUL,
+    0x9de42c3aUL, 0x920d5078UL, 0xcc9b6a5fUL, 0x4662547eUL,
+    0x13c2f68dUL, 0xb8e890d8UL, 0xf75e2e39UL, 0xaff582c3UL,
+    0x80be9f5dUL, 0x937c69d0UL, 0x2da96fd5UL, 0x12b3cf25UL,
+    0x993bc8acUL, 0x7da71018UL, 0x636ee89cUL, 0xbb7bdb3bUL,
+    0x7809cd26UL, 0x18f46e59UL, 0xb701ec9aUL, 0x9aa8834fUL,
+    0x6e65e695UL, 0xe67eaaffUL, 0xcf0821bcUL, 0xe8e6ef15UL,
+    0x9bd9bae7UL, 0x36ce4a6fUL, 0x09d4ea9fUL, 0x7cd629b0UL,
+    0xb2af31a4UL, 0x23312a3fUL, 0x9430c6a5UL, 0x66c035a2UL,
+    0xbc37744eUL, 0xcaa6fc82UL, 0xd0b0e090UL, 0xd81533a7UL,
+    0x984af104UL, 0xdaf741ecUL, 0x500e7fcdUL, 0xf62f1791UL,
+    0xd68d764dUL, 0xb04d43efUL, 0x4d54ccaaUL, 0x04dfe496UL,
+    0xb5e39ed1UL, 0x881b4c6aUL, 0x1fb8c12cUL, 0x517f4665UL,
+    0xea049d5eUL, 0x355d018cUL, 0x7473fa87UL, 0x412efb0bUL,
+    0x1d5ab367UL, 0xd25292dbUL, 0x5633e910UL, 0x47136dd6UL,
+    0x618c9ad7UL, 0x0c7a37a1UL, 0x148e59f8UL, 0x3c89eb13UL,
+    0x27eecea9UL, 0xc935b761UL, 0xe5ede11cUL, 0xb13c7a47UL,
+    0xdf599cd2UL, 0x733f55f2UL, 0xce791814UL, 0x37bf73c7UL,
+    0xcdea53f7UL, 0xaa5b5ffdUL, 0x6f14df3dUL, 0xdb867844UL,
+    0xf381caafUL, 0xc43eb968UL, 0x342c3824UL, 0x405fc2a3UL,
+    0xc372161dUL, 0x250cbce2UL, 0x498b283cUL, 0x9541ff0dUL,
+    0x017139a8UL, 0xb3de080cUL, 0xe49cd8b4UL, 0xc1906456UL,
+    0x84617bcbUL, 0xb670d532UL, 0x5c74486cUL, 0x5742d0b8UL,
+};
+static const ulong32 TD3[256] = {
+    0xf4a75051UL, 0x4165537eUL, 0x17a4c31aUL, 0x275e963aUL,
+    0xab6bcb3bUL, 0x9d45f11fUL, 0xfa58abacUL, 0xe303934bUL,
+    0x30fa5520UL, 0x766df6adUL, 0xcc769188UL, 0x024c25f5UL,
+    0xe5d7fc4fUL, 0x2acbd7c5UL, 0x35448026UL, 0x62a38fb5UL,
+    0xb15a49deUL, 0xba1b6725UL, 0xea0e9845UL, 0xfec0e15dUL,
+    0x2f7502c3UL, 0x4cf01281UL, 0x4697a38dUL, 0xd3f9c66bUL,
+    0x8f5fe703UL, 0x929c9515UL, 0x6d7aebbfUL, 0x5259da95UL,
+    0xbe832dd4UL, 0x7421d358UL, 0xe0692949UL, 0xc9c8448eUL,
+    0xc2896a75UL, 0x8e7978f4UL, 0x583e6b99UL, 0xb971dd27UL,
+    0xe14fb6beUL, 0x88ad17f0UL, 0x20ac66c9UL, 0xce3ab47dUL,
+    0xdf4a1863UL, 0x1a3182e5UL, 0x51336097UL, 0x537f4562UL,
+    0x6477e0b1UL, 0x6bae84bbUL, 0x81a01cfeUL, 0x082b94f9UL,
+    0x48685870UL, 0x45fd198fUL, 0xde6c8794UL, 0x7bf8b752UL,
+    0x73d323abUL, 0x4b02e272UL, 0x1f8f57e3UL, 0x55ab2a66UL,
+    0xeb2807b2UL, 0xb5c2032fUL, 0xc57b9a86UL, 0x3708a5d3UL,
+    0x2887f230UL, 0xbfa5b223UL, 0x036aba02UL, 0x16825cedUL,
+    0xcf1c2b8aUL, 0x79b492a7UL, 0x07f2f0f3UL, 0x69e2a14eUL,
+    0xdaf4cd65UL, 0x05bed506UL, 0x34621fd1UL, 0xa6fe8ac4UL,
+    0x2e539d34UL, 0xf355a0a2UL, 0x8ae13205UL, 0xf6eb75a4UL,
+    0x83ec390bUL, 0x60efaa40UL, 0x719f065eUL, 0x6e1051bdUL,
+    0x218af93eUL, 0xdd063d96UL, 0x3e05aeddUL, 0xe6bd464dUL,
+    0x548db591UL, 0xc45d0571UL, 0x06d46f04UL, 0x5015ff60UL,
+    0x98fb2419UL, 0xbde997d6UL, 0x4043cc89UL, 0xd99e7767UL,
+    0xe842bdb0UL, 0x898b8807UL, 0x195b38e7UL, 0xc8eedb79UL,
+    0x7c0a47a1UL, 0x420fe97cUL, 0x841ec9f8UL, 0x00000000UL,
+    0x80868309UL, 0x2bed4832UL, 0x1170ac1eUL, 0x5a724e6cUL,
+    0x0efffbfdUL, 0x8538560fUL, 0xaed51e3dUL, 0x2d392736UL,
+    0x0fd9640aUL, 0x5ca62168UL, 0x5b54d19bUL, 0x362e3a24UL,
+    0x0a67b10cUL, 0x57e70f93UL, 0xee96d2b4UL, 0x9b919e1bUL,
+    0xc0c54f80UL, 0xdc20a261UL, 0x774b695aUL, 0x121a161cUL,
+    0x93ba0ae2UL, 0xa02ae5c0UL, 0x22e0433cUL, 0x1b171d12UL,
+    0x090d0b0eUL, 0x8bc7adf2UL, 0xb6a8b92dUL, 0x1ea9c814UL,
+    0xf1198557UL, 0x75074cafUL, 0x99ddbbeeUL, 0x7f60fda3UL,
+    0x01269ff7UL, 0x72f5bc5cUL, 0x663bc544UL, 0xfb7e345bUL,
+    0x4329768bUL, 0x23c6dccbUL, 0xedfc68b6UL, 0xe4f163b8UL,
+    0x31dccad7UL, 0x63851042UL, 0x97224013UL, 0xc6112084UL,
+    0x4a247d85UL, 0xbb3df8d2UL, 0xf93211aeUL, 0x29a16dc7UL,
+    0x9e2f4b1dUL, 0xb230f3dcUL, 0x8652ec0dUL, 0xc1e3d077UL,
+    0xb3166c2bUL, 0x70b999a9UL, 0x9448fa11UL, 0xe9642247UL,
+    0xfc8cc4a8UL, 0xf03f1aa0UL, 0x7d2cd856UL, 0x3390ef22UL,
+    0x494ec787UL, 0x38d1c1d9UL, 0xcaa2fe8cUL, 0xd40b3698UL,
+    0xf581cfa6UL, 0x7ade28a5UL, 0xb78e26daUL, 0xadbfa43fUL,
+    0x3a9de42cUL, 0x78920d50UL, 0x5fcc9b6aUL, 0x7e466254UL,
+    0x8d13c2f6UL, 0xd8b8e890UL, 0x39f75e2eUL, 0xc3aff582UL,
+    0x5d80be9fUL, 0xd0937c69UL, 0xd52da96fUL, 0x2512b3cfUL,
+    0xac993bc8UL, 0x187da710UL, 0x9c636ee8UL, 0x3bbb7bdbUL,
+    0x267809cdUL, 0x5918f46eUL, 0x9ab701ecUL, 0x4f9aa883UL,
+    0x956e65e6UL, 0xffe67eaaUL, 0xbccf0821UL, 0x15e8e6efUL,
+    0xe79bd9baUL, 0x6f36ce4aUL, 0x9f09d4eaUL, 0xb07cd629UL,
+    0xa4b2af31UL, 0x3f23312aUL, 0xa59430c6UL, 0xa266c035UL,
+    0x4ebc3774UL, 0x82caa6fcUL, 0x90d0b0e0UL, 0xa7d81533UL,
+    0x04984af1UL, 0xecdaf741UL, 0xcd500e7fUL, 0x91f62f17UL,
+    0x4dd68d76UL, 0xefb04d43UL, 0xaa4d54ccUL, 0x9604dfe4UL,
+    0xd1b5e39eUL, 0x6a881b4cUL, 0x2c1fb8c1UL, 0x65517f46UL,
+    0x5eea049dUL, 0x8c355d01UL, 0x877473faUL, 0x0b412efbUL,
+    0x671d5ab3UL, 0xdbd25292UL, 0x105633e9UL, 0xd647136dUL,
+    0xd7618c9aUL, 0xa10c7a37UL, 0xf8148e59UL, 0x133c89ebUL,
+    0xa927eeceUL, 0x61c935b7UL, 0x1ce5ede1UL, 0x47b13c7aUL,
+    0xd2df599cUL, 0xf2733f55UL, 0x14ce7918UL, 0xc737bf73UL,
+    0xf7cdea53UL, 0xfdaa5b5fUL, 0x3d6f14dfUL, 0x44db8678UL,
+    0xaff381caUL, 0x68c43eb9UL, 0x24342c38UL, 0xa3405fc2UL,
+    0x1dc37216UL, 0xe2250cbcUL, 0x3c498b28UL, 0x0d9541ffUL,
+    0xa8017139UL, 0x0cb3de08UL, 0xb4e49cd8UL, 0x56c19064UL,
+    0xcb84617bUL, 0x32b670d5UL, 0x6c5c7448UL, 0xb85742d0UL,
+};
+
+static const ulong32 Tks0[] = {
+0x00000000UL, 0x0e090d0bUL, 0x1c121a16UL, 0x121b171dUL, 0x3824342cUL, 0x362d3927UL, 0x24362e3aUL, 0x2a3f2331UL, 
+0x70486858UL, 0x7e416553UL, 0x6c5a724eUL, 0x62537f45UL, 0x486c5c74UL, 0x4665517fUL, 0x547e4662UL, 0x5a774b69UL, 
+0xe090d0b0UL, 0xee99ddbbUL, 0xfc82caa6UL, 0xf28bc7adUL, 0xd8b4e49cUL, 0xd6bde997UL, 0xc4a6fe8aUL, 0xcaaff381UL, 
+0x90d8b8e8UL, 0x9ed1b5e3UL, 0x8ccaa2feUL, 0x82c3aff5UL, 0xa8fc8cc4UL, 0xa6f581cfUL, 0xb4ee96d2UL, 0xbae79bd9UL, 
+0xdb3bbb7bUL, 0xd532b670UL, 0xc729a16dUL, 0xc920ac66UL, 0xe31f8f57UL, 0xed16825cUL, 0xff0d9541UL, 0xf104984aUL, 
+0xab73d323UL, 0xa57ade28UL, 0xb761c935UL, 0xb968c43eUL, 0x9357e70fUL, 0x9d5eea04UL, 0x8f45fd19UL, 0x814cf012UL, 
+0x3bab6bcbUL, 0x35a266c0UL, 0x27b971ddUL, 0x29b07cd6UL, 0x038f5fe7UL, 0x0d8652ecUL, 0x1f9d45f1UL, 0x119448faUL, 
+0x4be30393UL, 0x45ea0e98UL, 0x57f11985UL, 0x59f8148eUL, 0x73c737bfUL, 0x7dce3ab4UL, 0x6fd52da9UL, 0x61dc20a2UL, 
+0xad766df6UL, 0xa37f60fdUL, 0xb16477e0UL, 0xbf6d7aebUL, 0x955259daUL, 0x9b5b54d1UL, 0x894043ccUL, 0x87494ec7UL, 
+0xdd3e05aeUL, 0xd33708a5UL, 0xc12c1fb8UL, 0xcf2512b3UL, 0xe51a3182UL, 0xeb133c89UL, 0xf9082b94UL, 0xf701269fUL, 
+0x4de6bd46UL, 0x43efb04dUL, 0x51f4a750UL, 0x5ffdaa5bUL, 0x75c2896aUL, 0x7bcb8461UL, 0x69d0937cUL, 0x67d99e77UL, 
+0x3daed51eUL, 0x33a7d815UL, 0x21bccf08UL, 0x2fb5c203UL, 0x058ae132UL, 0x0b83ec39UL, 0x1998fb24UL, 0x1791f62fUL, 
+0x764dd68dUL, 0x7844db86UL, 0x6a5fcc9bUL, 0x6456c190UL, 0x4e69e2a1UL, 0x4060efaaUL, 0x527bf8b7UL, 0x5c72f5bcUL, 
+0x0605bed5UL, 0x080cb3deUL, 0x1a17a4c3UL, 0x141ea9c8UL, 0x3e218af9UL, 0x302887f2UL, 0x223390efUL, 0x2c3a9de4UL, 
+0x96dd063dUL, 0x98d40b36UL, 0x8acf1c2bUL, 0x84c61120UL, 0xaef93211UL, 0xa0f03f1aUL, 0xb2eb2807UL, 0xbce2250cUL, 
+0xe6956e65UL, 0xe89c636eUL, 0xfa877473UL, 0xf48e7978UL, 0xdeb15a49UL, 0xd0b85742UL, 0xc2a3405fUL, 0xccaa4d54UL, 
+0x41ecdaf7UL, 0x4fe5d7fcUL, 0x5dfec0e1UL, 0x53f7cdeaUL, 0x79c8eedbUL, 0x77c1e3d0UL, 0x65daf4cdUL, 0x6bd3f9c6UL, 
+0x31a4b2afUL, 0x3fadbfa4UL, 0x2db6a8b9UL, 0x23bfa5b2UL, 0x09808683UL, 0x07898b88UL, 0x15929c95UL, 0x1b9b919eUL, 
+0xa17c0a47UL, 0xaf75074cUL, 0xbd6e1051UL, 0xb3671d5aUL, 0x99583e6bUL, 0x97513360UL, 0x854a247dUL, 0x8b432976UL, 
+0xd134621fUL, 0xdf3d6f14UL, 0xcd267809UL, 0xc32f7502UL, 0xe9105633UL, 0xe7195b38UL, 0xf5024c25UL, 0xfb0b412eUL, 
+0x9ad7618cUL, 0x94de6c87UL, 0x86c57b9aUL, 0x88cc7691UL, 0xa2f355a0UL, 0xacfa58abUL, 0xbee14fb6UL, 0xb0e842bdUL, 
+0xea9f09d4UL, 0xe49604dfUL, 0xf68d13c2UL, 0xf8841ec9UL, 0xd2bb3df8UL, 0xdcb230f3UL, 0xcea927eeUL, 0xc0a02ae5UL, 
+0x7a47b13cUL, 0x744ebc37UL, 0x6655ab2aUL, 0x685ca621UL, 0x42638510UL, 0x4c6a881bUL, 0x5e719f06UL, 0x5078920dUL, 
+0x0a0fd964UL, 0x0406d46fUL, 0x161dc372UL, 0x1814ce79UL, 0x322bed48UL, 0x3c22e043UL, 0x2e39f75eUL, 0x2030fa55UL, 
+0xec9ab701UL, 0xe293ba0aUL, 0xf088ad17UL, 0xfe81a01cUL, 0xd4be832dUL, 0xdab78e26UL, 0xc8ac993bUL, 0xc6a59430UL, 
+0x9cd2df59UL, 0x92dbd252UL, 0x80c0c54fUL, 0x8ec9c844UL, 0xa4f6eb75UL, 0xaaffe67eUL, 0xb8e4f163UL, 0xb6edfc68UL, 
+0x0c0a67b1UL, 0x02036abaUL, 0x10187da7UL, 0x1e1170acUL, 0x342e539dUL, 0x3a275e96UL, 0x283c498bUL, 0x26354480UL, 
+0x7c420fe9UL, 0x724b02e2UL, 0x605015ffUL, 0x6e5918f4UL, 0x44663bc5UL, 0x4a6f36ceUL, 0x587421d3UL, 0x567d2cd8UL, 
+0x37a10c7aUL, 0x39a80171UL, 0x2bb3166cUL, 0x25ba1b67UL, 0x0f853856UL, 0x018c355dUL, 0x13972240UL, 0x1d9e2f4bUL, 
+0x47e96422UL, 0x49e06929UL, 0x5bfb7e34UL, 0x55f2733fUL, 0x7fcd500eUL, 0x71c45d05UL, 0x63df4a18UL, 0x6dd64713UL, 
+0xd731dccaUL, 0xd938d1c1UL, 0xcb23c6dcUL, 0xc52acbd7UL, 0xef15e8e6UL, 0xe11ce5edUL, 0xf307f2f0UL, 0xfd0efffbUL, 
+0xa779b492UL, 0xa970b999UL, 0xbb6bae84UL, 0xb562a38fUL, 0x9f5d80beUL, 0x91548db5UL, 0x834f9aa8UL, 0x8d4697a3UL
+};
+
+static const ulong32 Tks1[] = {
+0x00000000UL, 0x0b0e090dUL, 0x161c121aUL, 0x1d121b17UL, 0x2c382434UL, 0x27362d39UL, 0x3a24362eUL, 0x312a3f23UL, 
+0x58704868UL, 0x537e4165UL, 0x4e6c5a72UL, 0x4562537fUL, 0x74486c5cUL, 0x7f466551UL, 0x62547e46UL, 0x695a774bUL, 
+0xb0e090d0UL, 0xbbee99ddUL, 0xa6fc82caUL, 0xadf28bc7UL, 0x9cd8b4e4UL, 0x97d6bde9UL, 0x8ac4a6feUL, 0x81caaff3UL, 
+0xe890d8b8UL, 0xe39ed1b5UL, 0xfe8ccaa2UL, 0xf582c3afUL, 0xc4a8fc8cUL, 0xcfa6f581UL, 0xd2b4ee96UL, 0xd9bae79bUL, 
+0x7bdb3bbbUL, 0x70d532b6UL, 0x6dc729a1UL, 0x66c920acUL, 0x57e31f8fUL, 0x5ced1682UL, 0x41ff0d95UL, 0x4af10498UL, 
+0x23ab73d3UL, 0x28a57adeUL, 0x35b761c9UL, 0x3eb968c4UL, 0x0f9357e7UL, 0x049d5eeaUL, 0x198f45fdUL, 0x12814cf0UL, 
+0xcb3bab6bUL, 0xc035a266UL, 0xdd27b971UL, 0xd629b07cUL, 0xe7038f5fUL, 0xec0d8652UL, 0xf11f9d45UL, 0xfa119448UL, 
+0x934be303UL, 0x9845ea0eUL, 0x8557f119UL, 0x8e59f814UL, 0xbf73c737UL, 0xb47dce3aUL, 0xa96fd52dUL, 0xa261dc20UL, 
+0xf6ad766dUL, 0xfda37f60UL, 0xe0b16477UL, 0xebbf6d7aUL, 0xda955259UL, 0xd19b5b54UL, 0xcc894043UL, 0xc787494eUL, 
+0xaedd3e05UL, 0xa5d33708UL, 0xb8c12c1fUL, 0xb3cf2512UL, 0x82e51a31UL, 0x89eb133cUL, 0x94f9082bUL, 0x9ff70126UL, 
+0x464de6bdUL, 0x4d43efb0UL, 0x5051f4a7UL, 0x5b5ffdaaUL, 0x6a75c289UL, 0x617bcb84UL, 0x7c69d093UL, 0x7767d99eUL, 
+0x1e3daed5UL, 0x1533a7d8UL, 0x0821bccfUL, 0x032fb5c2UL, 0x32058ae1UL, 0x390b83ecUL, 0x241998fbUL, 0x2f1791f6UL, 
+0x8d764dd6UL, 0x867844dbUL, 0x9b6a5fccUL, 0x906456c1UL, 0xa14e69e2UL, 0xaa4060efUL, 0xb7527bf8UL, 0xbc5c72f5UL, 
+0xd50605beUL, 0xde080cb3UL, 0xc31a17a4UL, 0xc8141ea9UL, 0xf93e218aUL, 0xf2302887UL, 0xef223390UL, 0xe42c3a9dUL, 
+0x3d96dd06UL, 0x3698d40bUL, 0x2b8acf1cUL, 0x2084c611UL, 0x11aef932UL, 0x1aa0f03fUL, 0x07b2eb28UL, 0x0cbce225UL, 
+0x65e6956eUL, 0x6ee89c63UL, 0x73fa8774UL, 0x78f48e79UL, 0x49deb15aUL, 0x42d0b857UL, 0x5fc2a340UL, 0x54ccaa4dUL, 
+0xf741ecdaUL, 0xfc4fe5d7UL, 0xe15dfec0UL, 0xea53f7cdUL, 0xdb79c8eeUL, 0xd077c1e3UL, 0xcd65daf4UL, 0xc66bd3f9UL, 
+0xaf31a4b2UL, 0xa43fadbfUL, 0xb92db6a8UL, 0xb223bfa5UL, 0x83098086UL, 0x8807898bUL, 0x9515929cUL, 0x9e1b9b91UL, 
+0x47a17c0aUL, 0x4caf7507UL, 0x51bd6e10UL, 0x5ab3671dUL, 0x6b99583eUL, 0x60975133UL, 0x7d854a24UL, 0x768b4329UL, 
+0x1fd13462UL, 0x14df3d6fUL, 0x09cd2678UL, 0x02c32f75UL, 0x33e91056UL, 0x38e7195bUL, 0x25f5024cUL, 0x2efb0b41UL, 
+0x8c9ad761UL, 0x8794de6cUL, 0x9a86c57bUL, 0x9188cc76UL, 0xa0a2f355UL, 0xabacfa58UL, 0xb6bee14fUL, 0xbdb0e842UL, 
+0xd4ea9f09UL, 0xdfe49604UL, 0xc2f68d13UL, 0xc9f8841eUL, 0xf8d2bb3dUL, 0xf3dcb230UL, 0xeecea927UL, 0xe5c0a02aUL, 
+0x3c7a47b1UL, 0x37744ebcUL, 0x2a6655abUL, 0x21685ca6UL, 0x10426385UL, 0x1b4c6a88UL, 0x065e719fUL, 0x0d507892UL, 
+0x640a0fd9UL, 0x6f0406d4UL, 0x72161dc3UL, 0x791814ceUL, 0x48322bedUL, 0x433c22e0UL, 0x5e2e39f7UL, 0x552030faUL, 
+0x01ec9ab7UL, 0x0ae293baUL, 0x17f088adUL, 0x1cfe81a0UL, 0x2dd4be83UL, 0x26dab78eUL, 0x3bc8ac99UL, 0x30c6a594UL, 
+0x599cd2dfUL, 0x5292dbd2UL, 0x4f80c0c5UL, 0x448ec9c8UL, 0x75a4f6ebUL, 0x7eaaffe6UL, 0x63b8e4f1UL, 0x68b6edfcUL, 
+0xb10c0a67UL, 0xba02036aUL, 0xa710187dUL, 0xac1e1170UL, 0x9d342e53UL, 0x963a275eUL, 0x8b283c49UL, 0x80263544UL, 
+0xe97c420fUL, 0xe2724b02UL, 0xff605015UL, 0xf46e5918UL, 0xc544663bUL, 0xce4a6f36UL, 0xd3587421UL, 0xd8567d2cUL, 
+0x7a37a10cUL, 0x7139a801UL, 0x6c2bb316UL, 0x6725ba1bUL, 0x560f8538UL, 0x5d018c35UL, 0x40139722UL, 0x4b1d9e2fUL, 
+0x2247e964UL, 0x2949e069UL, 0x345bfb7eUL, 0x3f55f273UL, 0x0e7fcd50UL, 0x0571c45dUL, 0x1863df4aUL, 0x136dd647UL, 
+0xcad731dcUL, 0xc1d938d1UL, 0xdccb23c6UL, 0xd7c52acbUL, 0xe6ef15e8UL, 0xede11ce5UL, 0xf0f307f2UL, 0xfbfd0effUL, 
+0x92a779b4UL, 0x99a970b9UL, 0x84bb6baeUL, 0x8fb562a3UL, 0xbe9f5d80UL, 0xb591548dUL, 0xa8834f9aUL, 0xa38d4697UL
+};
+
+static const ulong32 Tks2[] = {
+0x00000000UL, 0x0d0b0e09UL, 0x1a161c12UL, 0x171d121bUL, 0x342c3824UL, 0x3927362dUL, 0x2e3a2436UL, 0x23312a3fUL, 
+0x68587048UL, 0x65537e41UL, 0x724e6c5aUL, 0x7f456253UL, 0x5c74486cUL, 0x517f4665UL, 0x4662547eUL, 0x4b695a77UL, 
+0xd0b0e090UL, 0xddbbee99UL, 0xcaa6fc82UL, 0xc7adf28bUL, 0xe49cd8b4UL, 0xe997d6bdUL, 0xfe8ac4a6UL, 0xf381caafUL, 
+0xb8e890d8UL, 0xb5e39ed1UL, 0xa2fe8ccaUL, 0xaff582c3UL, 0x8cc4a8fcUL, 0x81cfa6f5UL, 0x96d2b4eeUL, 0x9bd9bae7UL, 
+0xbb7bdb3bUL, 0xb670d532UL, 0xa16dc729UL, 0xac66c920UL, 0x8f57e31fUL, 0x825ced16UL, 0x9541ff0dUL, 0x984af104UL, 
+0xd323ab73UL, 0xde28a57aUL, 0xc935b761UL, 0xc43eb968UL, 0xe70f9357UL, 0xea049d5eUL, 0xfd198f45UL, 0xf012814cUL, 
+0x6bcb3babUL, 0x66c035a2UL, 0x71dd27b9UL, 0x7cd629b0UL, 0x5fe7038fUL, 0x52ec0d86UL, 0x45f11f9dUL, 0x48fa1194UL, 
+0x03934be3UL, 0x0e9845eaUL, 0x198557f1UL, 0x148e59f8UL, 0x37bf73c7UL, 0x3ab47dceUL, 0x2da96fd5UL, 0x20a261dcUL, 
+0x6df6ad76UL, 0x60fda37fUL, 0x77e0b164UL, 0x7aebbf6dUL, 0x59da9552UL, 0x54d19b5bUL, 0x43cc8940UL, 0x4ec78749UL, 
+0x05aedd3eUL, 0x08a5d337UL, 0x1fb8c12cUL, 0x12b3cf25UL, 0x3182e51aUL, 0x3c89eb13UL, 0x2b94f908UL, 0x269ff701UL, 
+0xbd464de6UL, 0xb04d43efUL, 0xa75051f4UL, 0xaa5b5ffdUL, 0x896a75c2UL, 0x84617bcbUL, 0x937c69d0UL, 0x9e7767d9UL, 
+0xd51e3daeUL, 0xd81533a7UL, 0xcf0821bcUL, 0xc2032fb5UL, 0xe132058aUL, 0xec390b83UL, 0xfb241998UL, 0xf62f1791UL, 
+0xd68d764dUL, 0xdb867844UL, 0xcc9b6a5fUL, 0xc1906456UL, 0xe2a14e69UL, 0xefaa4060UL, 0xf8b7527bUL, 0xf5bc5c72UL, 
+0xbed50605UL, 0xb3de080cUL, 0xa4c31a17UL, 0xa9c8141eUL, 0x8af93e21UL, 0x87f23028UL, 0x90ef2233UL, 0x9de42c3aUL, 
+0x063d96ddUL, 0x0b3698d4UL, 0x1c2b8acfUL, 0x112084c6UL, 0x3211aef9UL, 0x3f1aa0f0UL, 0x2807b2ebUL, 0x250cbce2UL, 
+0x6e65e695UL, 0x636ee89cUL, 0x7473fa87UL, 0x7978f48eUL, 0x5a49deb1UL, 0x5742d0b8UL, 0x405fc2a3UL, 0x4d54ccaaUL, 
+0xdaf741ecUL, 0xd7fc4fe5UL, 0xc0e15dfeUL, 0xcdea53f7UL, 0xeedb79c8UL, 0xe3d077c1UL, 0xf4cd65daUL, 0xf9c66bd3UL, 
+0xb2af31a4UL, 0xbfa43fadUL, 0xa8b92db6UL, 0xa5b223bfUL, 0x86830980UL, 0x8b880789UL, 0x9c951592UL, 0x919e1b9bUL, 
+0x0a47a17cUL, 0x074caf75UL, 0x1051bd6eUL, 0x1d5ab367UL, 0x3e6b9958UL, 0x33609751UL, 0x247d854aUL, 0x29768b43UL, 
+0x621fd134UL, 0x6f14df3dUL, 0x7809cd26UL, 0x7502c32fUL, 0x5633e910UL, 0x5b38e719UL, 0x4c25f502UL, 0x412efb0bUL, 
+0x618c9ad7UL, 0x6c8794deUL, 0x7b9a86c5UL, 0x769188ccUL, 0x55a0a2f3UL, 0x58abacfaUL, 0x4fb6bee1UL, 0x42bdb0e8UL, 
+0x09d4ea9fUL, 0x04dfe496UL, 0x13c2f68dUL, 0x1ec9f884UL, 0x3df8d2bbUL, 0x30f3dcb2UL, 0x27eecea9UL, 0x2ae5c0a0UL, 
+0xb13c7a47UL, 0xbc37744eUL, 0xab2a6655UL, 0xa621685cUL, 0x85104263UL, 0x881b4c6aUL, 0x9f065e71UL, 0x920d5078UL, 
+0xd9640a0fUL, 0xd46f0406UL, 0xc372161dUL, 0xce791814UL, 0xed48322bUL, 0xe0433c22UL, 0xf75e2e39UL, 0xfa552030UL, 
+0xb701ec9aUL, 0xba0ae293UL, 0xad17f088UL, 0xa01cfe81UL, 0x832dd4beUL, 0x8e26dab7UL, 0x993bc8acUL, 0x9430c6a5UL, 
+0xdf599cd2UL, 0xd25292dbUL, 0xc54f80c0UL, 0xc8448ec9UL, 0xeb75a4f6UL, 0xe67eaaffUL, 0xf163b8e4UL, 0xfc68b6edUL, 
+0x67b10c0aUL, 0x6aba0203UL, 0x7da71018UL, 0x70ac1e11UL, 0x539d342eUL, 0x5e963a27UL, 0x498b283cUL, 0x44802635UL, 
+0x0fe97c42UL, 0x02e2724bUL, 0x15ff6050UL, 0x18f46e59UL, 0x3bc54466UL, 0x36ce4a6fUL, 0x21d35874UL, 0x2cd8567dUL, 
+0x0c7a37a1UL, 0x017139a8UL, 0x166c2bb3UL, 0x1b6725baUL, 0x38560f85UL, 0x355d018cUL, 0x22401397UL, 0x2f4b1d9eUL, 
+0x642247e9UL, 0x692949e0UL, 0x7e345bfbUL, 0x733f55f2UL, 0x500e7fcdUL, 0x5d0571c4UL, 0x4a1863dfUL, 0x47136dd6UL, 
+0xdccad731UL, 0xd1c1d938UL, 0xc6dccb23UL, 0xcbd7c52aUL, 0xe8e6ef15UL, 0xe5ede11cUL, 0xf2f0f307UL, 0xfffbfd0eUL, 
+0xb492a779UL, 0xb999a970UL, 0xae84bb6bUL, 0xa38fb562UL, 0x80be9f5dUL, 0x8db59154UL, 0x9aa8834fUL, 0x97a38d46UL
+};
+
+static const ulong32 Tks3[] = {
+0x00000000UL, 0x090d0b0eUL, 0x121a161cUL, 0x1b171d12UL, 0x24342c38UL, 0x2d392736UL, 0x362e3a24UL, 0x3f23312aUL, 
+0x48685870UL, 0x4165537eUL, 0x5a724e6cUL, 0x537f4562UL, 0x6c5c7448UL, 0x65517f46UL, 0x7e466254UL, 0x774b695aUL, 
+0x90d0b0e0UL, 0x99ddbbeeUL, 0x82caa6fcUL, 0x8bc7adf2UL, 0xb4e49cd8UL, 0xbde997d6UL, 0xa6fe8ac4UL, 0xaff381caUL, 
+0xd8b8e890UL, 0xd1b5e39eUL, 0xcaa2fe8cUL, 0xc3aff582UL, 0xfc8cc4a8UL, 0xf581cfa6UL, 0xee96d2b4UL, 0xe79bd9baUL, 
+0x3bbb7bdbUL, 0x32b670d5UL, 0x29a16dc7UL, 0x20ac66c9UL, 0x1f8f57e3UL, 0x16825cedUL, 0x0d9541ffUL, 0x04984af1UL, 
+0x73d323abUL, 0x7ade28a5UL, 0x61c935b7UL, 0x68c43eb9UL, 0x57e70f93UL, 0x5eea049dUL, 0x45fd198fUL, 0x4cf01281UL, 
+0xab6bcb3bUL, 0xa266c035UL, 0xb971dd27UL, 0xb07cd629UL, 0x8f5fe703UL, 0x8652ec0dUL, 0x9d45f11fUL, 0x9448fa11UL, 
+0xe303934bUL, 0xea0e9845UL, 0xf1198557UL, 0xf8148e59UL, 0xc737bf73UL, 0xce3ab47dUL, 0xd52da96fUL, 0xdc20a261UL, 
+0x766df6adUL, 0x7f60fda3UL, 0x6477e0b1UL, 0x6d7aebbfUL, 0x5259da95UL, 0x5b54d19bUL, 0x4043cc89UL, 0x494ec787UL, 
+0x3e05aeddUL, 0x3708a5d3UL, 0x2c1fb8c1UL, 0x2512b3cfUL, 0x1a3182e5UL, 0x133c89ebUL, 0x082b94f9UL, 0x01269ff7UL, 
+0xe6bd464dUL, 0xefb04d43UL, 0xf4a75051UL, 0xfdaa5b5fUL, 0xc2896a75UL, 0xcb84617bUL, 0xd0937c69UL, 0xd99e7767UL, 
+0xaed51e3dUL, 0xa7d81533UL, 0xbccf0821UL, 0xb5c2032fUL, 0x8ae13205UL, 0x83ec390bUL, 0x98fb2419UL, 0x91f62f17UL, 
+0x4dd68d76UL, 0x44db8678UL, 0x5fcc9b6aUL, 0x56c19064UL, 0x69e2a14eUL, 0x60efaa40UL, 0x7bf8b752UL, 0x72f5bc5cUL, 
+0x05bed506UL, 0x0cb3de08UL, 0x17a4c31aUL, 0x1ea9c814UL, 0x218af93eUL, 0x2887f230UL, 0x3390ef22UL, 0x3a9de42cUL, 
+0xdd063d96UL, 0xd40b3698UL, 0xcf1c2b8aUL, 0xc6112084UL, 0xf93211aeUL, 0xf03f1aa0UL, 0xeb2807b2UL, 0xe2250cbcUL, 
+0x956e65e6UL, 0x9c636ee8UL, 0x877473faUL, 0x8e7978f4UL, 0xb15a49deUL, 0xb85742d0UL, 0xa3405fc2UL, 0xaa4d54ccUL, 
+0xecdaf741UL, 0xe5d7fc4fUL, 0xfec0e15dUL, 0xf7cdea53UL, 0xc8eedb79UL, 0xc1e3d077UL, 0xdaf4cd65UL, 0xd3f9c66bUL, 
+0xa4b2af31UL, 0xadbfa43fUL, 0xb6a8b92dUL, 0xbfa5b223UL, 0x80868309UL, 0x898b8807UL, 0x929c9515UL, 0x9b919e1bUL, 
+0x7c0a47a1UL, 0x75074cafUL, 0x6e1051bdUL, 0x671d5ab3UL, 0x583e6b99UL, 0x51336097UL, 0x4a247d85UL, 0x4329768bUL, 
+0x34621fd1UL, 0x3d6f14dfUL, 0x267809cdUL, 0x2f7502c3UL, 0x105633e9UL, 0x195b38e7UL, 0x024c25f5UL, 0x0b412efbUL, 
+0xd7618c9aUL, 0xde6c8794UL, 0xc57b9a86UL, 0xcc769188UL, 0xf355a0a2UL, 0xfa58abacUL, 0xe14fb6beUL, 0xe842bdb0UL, 
+0x9f09d4eaUL, 0x9604dfe4UL, 0x8d13c2f6UL, 0x841ec9f8UL, 0xbb3df8d2UL, 0xb230f3dcUL, 0xa927eeceUL, 0xa02ae5c0UL, 
+0x47b13c7aUL, 0x4ebc3774UL, 0x55ab2a66UL, 0x5ca62168UL, 0x63851042UL, 0x6a881b4cUL, 0x719f065eUL, 0x78920d50UL, 
+0x0fd9640aUL, 0x06d46f04UL, 0x1dc37216UL, 0x14ce7918UL, 0x2bed4832UL, 0x22e0433cUL, 0x39f75e2eUL, 0x30fa5520UL, 
+0x9ab701ecUL, 0x93ba0ae2UL, 0x88ad17f0UL, 0x81a01cfeUL, 0xbe832dd4UL, 0xb78e26daUL, 0xac993bc8UL, 0xa59430c6UL, 
+0xd2df599cUL, 0xdbd25292UL, 0xc0c54f80UL, 0xc9c8448eUL, 0xf6eb75a4UL, 0xffe67eaaUL, 0xe4f163b8UL, 0xedfc68b6UL, 
+0x0a67b10cUL, 0x036aba02UL, 0x187da710UL, 0x1170ac1eUL, 0x2e539d34UL, 0x275e963aUL, 0x3c498b28UL, 0x35448026UL, 
+0x420fe97cUL, 0x4b02e272UL, 0x5015ff60UL, 0x5918f46eUL, 0x663bc544UL, 0x6f36ce4aUL, 0x7421d358UL, 0x7d2cd856UL, 
+0xa10c7a37UL, 0xa8017139UL, 0xb3166c2bUL, 0xba1b6725UL, 0x8538560fUL, 0x8c355d01UL, 0x97224013UL, 0x9e2f4b1dUL, 
+0xe9642247UL, 0xe0692949UL, 0xfb7e345bUL, 0xf2733f55UL, 0xcd500e7fUL, 0xc45d0571UL, 0xdf4a1863UL, 0xd647136dUL, 
+0x31dccad7UL, 0x38d1c1d9UL, 0x23c6dccbUL, 0x2acbd7c5UL, 0x15e8e6efUL, 0x1ce5ede1UL, 0x07f2f0f3UL, 0x0efffbfdUL, 
+0x79b492a7UL, 0x70b999a9UL, 0x6bae84bbUL, 0x62a38fb5UL, 0x5d80be9fUL, 0x548db591UL, 0x4f9aa883UL, 0x4697a38dUL
+};
+
+#endif /* SMALL CODE */
+
+static const ulong32 rcon[] = {
+    0x01000000UL, 0x02000000UL, 0x04000000UL, 0x08000000UL,
+    0x10000000UL, 0x20000000UL, 0x40000000UL, 0x80000000UL,
+    0x1B000000UL, 0x36000000UL, /* for 128-bit blocks, Rijndael never uses more than 10 rcon values */
+};
+
+/* Various logical functions */
+#define Ch(x,y,z)       (z ^ (x & (y ^ z)))
+#define Maj(x,y,z)      (((x | y) & z) | (x & y)) 
+#define S(x, n)         RORc((x),(n))
+#define R(x, n)         (((x)&0xFFFFFFFFUL)>>(n))
+#define Sigma0(x)       (S(x, 2) ^ S(x, 13) ^ S(x, 22))
+#define Sigma1(x)       (S(x, 6) ^ S(x, 11) ^ S(x, 25))
+#define Gamma0(x)       (S(x, 7) ^ S(x, 18) ^ R(x, 3))
+#define Gamma1(x)       (S(x, 17) ^ S(x, 19) ^ R(x, 10))
+
+static ulong32 setup_mix(ulong32 temp)
+{
+   return (Te4_3[byte(temp, 2)]) ^
+          (Te4_2[byte(temp, 1)]) ^
+          (Te4_1[byte(temp, 0)]) ^
+          (Te4_0[byte(temp, 3)]);
+}
+
+#ifdef LTC_SMALL_CODE
+static ulong32 setup_mix2(ulong32 temp)
+{
+   return Td0(255 & Te4[byte(temp, 3)]) ^
+          Td1(255 & Te4[byte(temp, 2)]) ^
+          Td2(255 & Te4[byte(temp, 1)]) ^
+          Td3(255 & Te4[byte(temp, 0)]);
+}
+#endif
+
+ /**
+    Initialize the AES (Rijndael) block cipher
+    @param key The symmetric key you wish to pass
+    @param keylen The key length in bytes
+    @param num_rounds The number of rounds desired (0 for default)
+    @param skey The key in as scheduled by this function.
+    @return CRYPT_OK if successful
+ */
+int AES_SETUP(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey)
+{
+    int i, j;
+    ulong32 temp, *rk;
+    ulong32 *rrk;
+  
+    if (keylen != 16 && keylen != 24 && keylen != 32) {
+       return CRYPT_INVALID_KEYSIZE;
+    }
+    
+    if (num_rounds != 0 && num_rounds != (10 + ((keylen/8)-2)*2)) {
+       return CRYPT_INVALID_ROUNDS;
+    }
+    
+    skey->rijndael.Nr = 10 + ((keylen/8)-2)*2;
+        
+    /* setup the forward key */
+    i                 = 0;
+    rk                = skey->rijndael.eK;
+    LOAD32H(rk[0], key     );
+    LOAD32H(rk[1], key +  4);
+    LOAD32H(rk[2], key +  8);
+    LOAD32H(rk[3], key + 12);
+    if (keylen == 16) {
+        j = 44;
+        for (;;) {
+            temp  = rk[3];
+            rk[4] = rk[0] ^ setup_mix(temp) ^ rcon[i];
+            rk[5] = rk[1] ^ rk[4];
+            rk[6] = rk[2] ^ rk[5];
+            rk[7] = rk[3] ^ rk[6];
+            if (++i == 10) {
+               break;
+            }
+            rk += 4;
+        }
+    } else if (keylen == 24) {
+        j = 52;   
+        LOAD32H(rk[4], key + 16);
+        LOAD32H(rk[5], key + 20);
+        for (;;) {
+        #ifdef _MSC_VER
+            temp = skey->rijndael.eK[rk - skey->rijndael.eK + 5]; 
+        #else
+            temp = rk[5];
+        #endif
+            rk[ 6] = rk[ 0] ^ setup_mix(temp) ^ rcon[i];
+            rk[ 7] = rk[ 1] ^ rk[ 6];
+            rk[ 8] = rk[ 2] ^ rk[ 7];
+            rk[ 9] = rk[ 3] ^ rk[ 8];
+            if (++i == 8) {
+                break;
+            }
+            rk[10] = rk[ 4] ^ rk[ 9];
+            rk[11] = rk[ 5] ^ rk[10];
+            rk += 6;
+        }
+    } else if (keylen == 32) {
+        j = 60;
+        LOAD32H(rk[4], key + 16);
+        LOAD32H(rk[5], key + 20);
+        LOAD32H(rk[6], key + 24);
+        LOAD32H(rk[7], key + 28);
+        for (;;) {
+        #ifdef _MSC_VER
+            temp = skey->rijndael.eK[rk - skey->rijndael.eK + 7]; 
+        #else
+            temp = rk[7];
+        #endif
+            rk[ 8] = rk[ 0] ^ setup_mix(temp) ^ rcon[i];
+            rk[ 9] = rk[ 1] ^ rk[ 8];
+            rk[10] = rk[ 2] ^ rk[ 9];
+            rk[11] = rk[ 3] ^ rk[10];
+            if (++i == 7) {
+                break;
+            }
+            temp = rk[11];
+            rk[12] = rk[ 4] ^ setup_mix(RORc(temp, 8));
+            rk[13] = rk[ 5] ^ rk[12];
+            rk[14] = rk[ 6] ^ rk[13];
+            rk[15] = rk[ 7] ^ rk[14];
+            rk += 8;
+        }
+    } else {
+       /* this can't happen */
+       return CRYPT_ERROR;
+    }
+
+    /* setup the inverse key now */
+    rk   = skey->rijndael.dK;
+    rrk  = skey->rijndael.eK + j - 4; 
+    
+    /* apply the inverse MixColumn transform to all round keys but the first and the last: */
+    /* copy first */
+    *rk++ = *rrk++;
+    *rk++ = *rrk++;
+    *rk++ = *rrk++;
+    *rk   = *rrk;
+    rk -= 3; rrk -= 3;
+    
+    for (i = 1; i < skey->rijndael.Nr; i++) {
+        rrk -= 4;
+        rk  += 4;
+    #ifdef LTC_SMALL_CODE        
+        temp = rrk[0];
+        rk[0] = setup_mix2(temp);
+        temp = rrk[1];
+        rk[1] = setup_mix2(temp);
+        temp = rrk[2];
+        rk[2] = setup_mix2(temp);
+        temp = rrk[3];
+        rk[3] = setup_mix2(temp);
+     #else
+        temp = rrk[0];
+        rk[0] =
+            Tks0[byte(temp, 3)] ^
+            Tks1[byte(temp, 2)] ^
+            Tks2[byte(temp, 1)] ^
+            Tks3[byte(temp, 0)];
+        temp = rrk[1];
+        rk[1] =
+            Tks0[byte(temp, 3)] ^
+            Tks1[byte(temp, 2)] ^
+            Tks2[byte(temp, 1)] ^
+            Tks3[byte(temp, 0)];
+        temp = rrk[2];
+        rk[2] =
+            Tks0[byte(temp, 3)] ^
+            Tks1[byte(temp, 2)] ^
+            Tks2[byte(temp, 1)] ^
+            Tks3[byte(temp, 0)];
+        temp = rrk[3];
+        rk[3] =
+            Tks0[byte(temp, 3)] ^
+            Tks1[byte(temp, 2)] ^
+            Tks2[byte(temp, 1)] ^
+            Tks3[byte(temp, 0)];
+      #endif            
+     
+    }
+
+    /* copy last */
+    rrk -= 4;
+    rk  += 4;
+    *rk++ = *rrk++;
+    *rk++ = *rrk++;
+    *rk++ = *rrk++;
+    *rk   = *rrk;
+    return CRYPT_OK;   
+}
+
+/**
+  Encrypts a block of text with AES
+  @param pt The input plaintext (16 bytes)
+  @param ct The output ciphertext (16 bytes)
+  @param skey The key as scheduled
+  @return CRYPT_OK if successful
+*/
+#ifdef LTC_CLEAN_STACK
+static int _rijndael_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey) 
+#else
+int AES_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey)
+#endif
+{
+    ulong32 s0, s1, s2, s3, t0, t1, t2, t3, *rk;
+    int Nr, r;
+    
+    Nr = skey->rijndael.Nr;
+    rk = skey->rijndael.eK;
+    
+    /*
+     * map byte array block to cipher state
+     * and add initial round key:
+     */
+    LOAD32H(s0, pt      ); s0 ^= rk[0];
+    LOAD32H(s1, pt  +  4); s1 ^= rk[1];
+    LOAD32H(s2, pt  +  8); s2 ^= rk[2];
+    LOAD32H(s3, pt  + 12); s3 ^= rk[3];
+
+#ifdef LTC_SMALL_CODE
+
+    for (r = 0; ; r++) {
+        rk += 4;
+        t0 =
+            Te0(byte(s0, 3)) ^
+            Te1(byte(s1, 2)) ^
+            Te2(byte(s2, 1)) ^
+            Te3(byte(s3, 0)) ^
+            rk[0];
+        t1 =
+            Te0(byte(s1, 3)) ^
+            Te1(byte(s2, 2)) ^
+            Te2(byte(s3, 1)) ^
+            Te3(byte(s0, 0)) ^
+            rk[1];
+        t2 =
+            Te0(byte(s2, 3)) ^
+            Te1(byte(s3, 2)) ^
+            Te2(byte(s0, 1)) ^
+            Te3(byte(s1, 0)) ^
+            rk[2];
+        t3 =
+            Te0(byte(s3, 3)) ^
+            Te1(byte(s0, 2)) ^
+            Te2(byte(s1, 1)) ^
+            Te3(byte(s2, 0)) ^
+            rk[3];
+        if (r == Nr-2) { 
+           break;
+        }
+        s0 = t0; s1 = t1; s2 = t2; s3 = t3;
+    }
+    rk += 4;
+
+#else
+
+    /*
+     * Nr - 1 full rounds:
+     */
+    r = Nr >> 1;
+    for (;;) {
+        t0 =
+            Te0(byte(s0, 3)) ^
+            Te1(byte(s1, 2)) ^
+            Te2(byte(s2, 1)) ^
+            Te3(byte(s3, 0)) ^
+            rk[4];
+        t1 =
+            Te0(byte(s1, 3)) ^
+            Te1(byte(s2, 2)) ^
+            Te2(byte(s3, 1)) ^
+            Te3(byte(s0, 0)) ^
+            rk[5];
+        t2 =
+            Te0(byte(s2, 3)) ^
+            Te1(byte(s3, 2)) ^
+            Te2(byte(s0, 1)) ^
+            Te3(byte(s1, 0)) ^
+            rk[6];
+        t3 =
+            Te0(byte(s3, 3)) ^
+            Te1(byte(s0, 2)) ^
+            Te2(byte(s1, 1)) ^
+            Te3(byte(s2, 0)) ^
+            rk[7];
+
+        rk += 8;
+        if (--r == 0) {
+            break;
+        }
+
+        s0 =
+            Te0(byte(t0, 3)) ^
+            Te1(byte(t1, 2)) ^
+            Te2(byte(t2, 1)) ^
+            Te3(byte(t3, 0)) ^
+            rk[0];
+        s1 =
+            Te0(byte(t1, 3)) ^
+            Te1(byte(t2, 2)) ^
+            Te2(byte(t3, 1)) ^
+            Te3(byte(t0, 0)) ^
+            rk[1];
+        s2 =
+            Te0(byte(t2, 3)) ^
+            Te1(byte(t3, 2)) ^
+            Te2(byte(t0, 1)) ^
+            Te3(byte(t1, 0)) ^
+            rk[2];
+        s3 =
+            Te0(byte(t3, 3)) ^
+            Te1(byte(t0, 2)) ^
+            Te2(byte(t1, 1)) ^
+            Te3(byte(t2, 0)) ^
+            rk[3];
+    }
+
+#endif
+
+    /*
+     * apply last round and
+     * map cipher state to byte array block:
+     */
+    s0 =
+        (Te4_3[byte(t0, 3)]) ^
+        (Te4_2[byte(t1, 2)]) ^
+        (Te4_1[byte(t2, 1)]) ^
+        (Te4_0[byte(t3, 0)]) ^
+        rk[0];
+    STORE32H(s0, ct);
+    s1 =
+        (Te4_3[byte(t1, 3)]) ^
+        (Te4_2[byte(t2, 2)]) ^
+        (Te4_1[byte(t3, 1)]) ^
+        (Te4_0[byte(t0, 0)]) ^
+        rk[1];
+    STORE32H(s1, ct+4);
+    s2 =
+        (Te4_3[byte(t2, 3)]) ^
+        (Te4_2[byte(t3, 2)]) ^
+        (Te4_1[byte(t0, 1)]) ^
+        (Te4_0[byte(t1, 0)]) ^
+        rk[2];
+    STORE32H(s2, ct+8);
+    s3 =
+        (Te4_3[byte(t3, 3)]) ^
+        (Te4_2[byte(t0, 2)]) ^
+        (Te4_1[byte(t1, 1)]) ^
+        (Te4_0[byte(t2, 0)]) ^ 
+        rk[3];
+    STORE32H(s3, ct+12);
+
+    return CRYPT_OK;
+}
+
+#ifdef LTC_CLEAN_STACK
+int ECB_ENC(const unsigned char *pt, unsigned char *ct, symmetric_key *skey) 
+{
+   int err = _rijndael_ecb_encrypt(pt, ct, skey);
+   burn_stack(sizeof(unsigned long)*8 + sizeof(unsigned long*) + sizeof(int)*2);
+   return err;
+}
+#endif
+
+/**
+  Decrypts a block of text with AES
+  @param ct The input ciphertext (16 bytes)
+  @param pt The output plaintext (16 bytes)
+  @param skey The key as scheduled 
+  @return CRYPT_OK if successful
+*/
+#ifdef LTC_CLEAN_STACK
+static int _rijndael_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey) 
+#else
+int ECB_DEC(const unsigned char *ct, unsigned char *pt, symmetric_key *skey)
+#endif
+{
+    ulong32 s0, s1, s2, s3, t0, t1, t2, t3, *rk;
+    int Nr, r;
+
+    Nr = skey->rijndael.Nr;
+    rk = skey->rijndael.dK;
+
+    /*
+     * map byte array block to cipher state
+     * and add initial round key:
+     */
+    LOAD32H(s0, ct      ); s0 ^= rk[0];
+    LOAD32H(s1, ct  +  4); s1 ^= rk[1];
+    LOAD32H(s2, ct  +  8); s2 ^= rk[2];
+    LOAD32H(s3, ct  + 12); s3 ^= rk[3];
+
+#ifdef LTC_SMALL_CODE
+    for (r = 0; ; r++) {
+        rk += 4;
+        t0 =
+            Td0(byte(s0, 3)) ^
+            Td1(byte(s3, 2)) ^
+            Td2(byte(s2, 1)) ^
+            Td3(byte(s1, 0)) ^
+            rk[0];
+        t1 =
+            Td0(byte(s1, 3)) ^
+            Td1(byte(s0, 2)) ^
+            Td2(byte(s3, 1)) ^
+            Td3(byte(s2, 0)) ^
+            rk[1];
+        t2 =
+            Td0(byte(s2, 3)) ^
+            Td1(byte(s1, 2)) ^
+            Td2(byte(s0, 1)) ^
+            Td3(byte(s3, 0)) ^
+            rk[2];
+        t3 =
+            Td0(byte(s3, 3)) ^
+            Td1(byte(s2, 2)) ^
+            Td2(byte(s1, 1)) ^
+            Td3(byte(s0, 0)) ^
+            rk[3];
+        if (r == Nr-2) {
+           break; 
+        }
+        s0 = t0; s1 = t1; s2 = t2; s3 = t3;
+    }
+    rk += 4;
+
+#else       
+
+    /*
+     * Nr - 1 full rounds:
+     */
+    r = Nr >> 1;
+    for (;;) {
+
+        t0 =
+            Td0(byte(s0, 3)) ^
+            Td1(byte(s3, 2)) ^
+            Td2(byte(s2, 1)) ^
+            Td3(byte(s1, 0)) ^
+            rk[4];
+        t1 =
+            Td0(byte(s1, 3)) ^
+            Td1(byte(s0, 2)) ^
+            Td2(byte(s3, 1)) ^
+            Td3(byte(s2, 0)) ^
+            rk[5];
+        t2 =
+            Td0(byte(s2, 3)) ^
+            Td1(byte(s1, 2)) ^
+            Td2(byte(s0, 1)) ^
+            Td3(byte(s3, 0)) ^
+            rk[6];
+        t3 =
+            Td0(byte(s3, 3)) ^
+            Td1(byte(s2, 2)) ^
+            Td2(byte(s1, 1)) ^
+            Td3(byte(s0, 0)) ^
+            rk[7];
+
+        rk += 8;
+        if (--r == 0) {
+            break;
+        }
+
+
+        s0 =
+            Td0(byte(t0, 3)) ^
+            Td1(byte(t3, 2)) ^
+            Td2(byte(t2, 1)) ^
+            Td3(byte(t1, 0)) ^
+            rk[0];
+        s1 =
+            Td0(byte(t1, 3)) ^
+            Td1(byte(t0, 2)) ^
+            Td2(byte(t3, 1)) ^
+            Td3(byte(t2, 0)) ^
+            rk[1];
+        s2 =
+            Td0(byte(t2, 3)) ^
+            Td1(byte(t1, 2)) ^
+            Td2(byte(t0, 1)) ^
+            Td3(byte(t3, 0)) ^
+            rk[2];
+        s3 =
+            Td0(byte(t3, 3)) ^
+            Td1(byte(t2, 2)) ^
+            Td2(byte(t1, 1)) ^
+            Td3(byte(t0, 0)) ^
+            rk[3];
+    }
+#endif
+
+    /*
+     * apply last round and
+     * map cipher state to byte array block:
+     */
+    s0 =
+        (Td4[byte(t0, 3)] & 0xff000000) ^
+        (Td4[byte(t3, 2)] & 0x00ff0000) ^
+        (Td4[byte(t2, 1)] & 0x0000ff00) ^
+        (Td4[byte(t1, 0)] & 0x000000ff) ^
+        rk[0];
+    STORE32H(s0, pt);
+    s1 =
+        (Td4[byte(t1, 3)] & 0xff000000) ^
+        (Td4[byte(t0, 2)] & 0x00ff0000) ^
+        (Td4[byte(t3, 1)] & 0x0000ff00) ^
+        (Td4[byte(t2, 0)] & 0x000000ff) ^
+        rk[1];
+    STORE32H(s1, pt+4);
+    s2 =
+        (Td4[byte(t2, 3)] & 0xff000000) ^
+        (Td4[byte(t1, 2)] & 0x00ff0000) ^
+        (Td4[byte(t0, 1)] & 0x0000ff00) ^
+        (Td4[byte(t3, 0)] & 0x000000ff) ^
+        rk[2];
+    STORE32H(s2, pt+8);
+    s3 =
+        (Td4[byte(t3, 3)] & 0xff000000) ^
+        (Td4[byte(t2, 2)] & 0x00ff0000) ^
+        (Td4[byte(t1, 1)] & 0x0000ff00) ^
+        (Td4[byte(t0, 0)] & 0x000000ff) ^
+        rk[3];
+    STORE32H(s3, pt+12);
+
+    return CRYPT_OK;
+}
+
+
+#ifdef LTC_CLEAN_STACK
+int ECB_DEC(const unsigned char *ct, unsigned char *pt, symmetric_key *skey) 
+{
+   int err = _rijndael_ecb_decrypt(ct, pt, skey);
+   burn_stack(sizeof(unsigned long)*8 + sizeof(unsigned long*) + sizeof(int)*2);
+   return err;
+}
+#endif
+
+
+/** Terminate the context 
+   @param skey    The scheduled key
+*/
+void ECB_DONE(symmetric_key *skey)
+{
+}
+
+
+/**
+  Gets suitable key size
+  @param keysize [in/out] The length of the recommended key (in bytes).  This function will store the suitable size back in this variable.
+  @return CRYPT_OK if the input key size is acceptable.
+*/
+int ECB_KS(int *keysize)
+{
+   if (*keysize < 16)
+      return CRYPT_INVALID_KEYSIZE;
+   if (*keysize < 24) {
+      *keysize = 16;
+      return CRYPT_OK;
+   } else if (*keysize < 32) {
+      *keysize = 24;
+      return CRYPT_OK;
+   } else {
+      *keysize = 32;
+      return CRYPT_OK;
+   }
+}
+
+
+/* public domain code from LibTomCrypt.
+   Some macros were taken from headers so that the code can be
+   pasted in the middle of somewhere (like here in NetHack rnd.c) */
+
+struct sha256_state {
+    ulong64 length;
+    ulong32 state[8], curlen;
+    unsigned char buf[64];
+};
+
+typedef union Hash_state {
+    char dummy[1];
+    struct sha256_state sha256;
+    void *data;
+} hash_state;
+
+int sha256_init(hash_state * md);
+int sha256_process(hash_state * md, const unsigned char *in, unsigned long inlen);
+int sha256_done(hash_state * md, unsigned char *hash);
+
+#ifdef LTC_SMALL_CODE
+/* the K array */
+static const ulong32 K[64] = {
+    0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL, 0x3956c25bUL,
+    0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL, 0xd807aa98UL, 0x12835b01UL,
+    0x243185beUL, 0x550c7dc3UL, 0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL,
+    0xc19bf174UL, 0xe49b69c1UL, 0xefbe4786UL, 0x0fc19dc6UL, 0x240ca1ccUL,
+    0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL, 0x983e5152UL,
+    0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL, 0xc6e00bf3UL, 0xd5a79147UL,
+    0x06ca6351UL, 0x14292967UL, 0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL,
+    0x53380d13UL, 0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL,
+    0xa2bfe8a1UL, 0xa81a664bUL, 0xc24b8b70UL, 0xc76c51a3UL, 0xd192e819UL,
+    0xd6990624UL, 0xf40e3585UL, 0x106aa070UL, 0x19a4c116UL, 0x1e376c08UL,
+    0x2748774cUL, 0x34b0bcb5UL, 0x391c0cb3UL, 0x4ed8aa4aUL, 0x5b9cca4fUL,
+    0x682e6ff3UL, 0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL,
+    0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL
+};
+#endif
+
+/* compress 512-bits */
+#ifdef LTC_CLEAN_STACK
+static int _sha256_compress(hash_state * md, unsigned char *buf)
+#else
+static int  sha256_compress(hash_state * md, unsigned char *buf)
+#endif
+{
+    ulong32 S[8], W[64], t0, t1;
+#ifdef LTC_SMALL_CODE
+    ulong32 t;
+#endif
+    int i;
+
+    /* copy state into S */
+    for (i = 0; i < 8; i++) {
+        S[i] = md->sha256.state[i];
+    }
+
+    /* copy the state into 512-bits into W[0..15] */
+    for (i = 0; i < 16; i++) {
+        LOAD32H(W[i], buf + (4*i));
+    }
+
+    /* fill W[16..63] */
+    for (i = 16; i < 64; i++) {
+        W[i] = Gamma1(W[i - 2]) + W[i - 7] + Gamma0(W[i - 15]) + W[i - 16];
+    }        
+
+    /* Compress */
+#ifdef LTC_SMALL_CODE   
+#define RND(a,b,c,d,e,f,g,h,i)                         \
+     t0 = h + Sigma1(e) + Ch(e, f, g) + K[i] + W[i];   \
+     t1 = Sigma0(a) + Maj(a, b, c);                    \
+     d += t0;                                          \
+     h  = t0 + t1;
+
+     for (i = 0; i < 64; ++i) {
+         RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],i);
+         t = S[7]; S[7] = S[6]; S[6] = S[5]; S[5] = S[4]; 
+         S[4] = S[3]; S[3] = S[2]; S[2] = S[1]; S[1] = S[0]; S[0] = t;
+     }  
+#else 
+#define RND(a,b,c,d,e,f,g,h,i,ki)                    \
+     t0 = h + Sigma1(e) + Ch(e, f, g) + ki + W[i];   \
+     t1 = Sigma0(a) + Maj(a, b, c);                  \
+     d += t0;                                        \
+     h  = t0 + t1;
+
+    RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],0,0x428a2f98);
+    RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],1,0x71374491);
+    RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],2,0xb5c0fbcf);
+    RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],3,0xe9b5dba5);
+    RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],4,0x3956c25b);
+    RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],5,0x59f111f1);
+    RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],6,0x923f82a4);
+    RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],7,0xab1c5ed5);
+    RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],8,0xd807aa98);
+    RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],9,0x12835b01);
+    RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],10,0x243185be);
+    RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],11,0x550c7dc3);
+    RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],12,0x72be5d74);
+    RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],13,0x80deb1fe);
+    RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],14,0x9bdc06a7);
+    RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],15,0xc19bf174);
+    RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],16,0xe49b69c1);
+    RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],17,0xefbe4786);
+    RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],18,0x0fc19dc6);
+    RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],19,0x240ca1cc);
+    RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],20,0x2de92c6f);
+    RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],21,0x4a7484aa);
+    RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],22,0x5cb0a9dc);
+    RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],23,0x76f988da);
+    RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],24,0x983e5152);
+    RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],25,0xa831c66d);
+    RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],26,0xb00327c8);
+    RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],27,0xbf597fc7);
+    RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],28,0xc6e00bf3);
+    RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],29,0xd5a79147);
+    RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],30,0x06ca6351);
+    RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],31,0x14292967);
+    RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],32,0x27b70a85);
+    RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],33,0x2e1b2138);
+    RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],34,0x4d2c6dfc);
+    RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],35,0x53380d13);
+    RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],36,0x650a7354);
+    RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],37,0x766a0abb);
+    RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],38,0x81c2c92e);
+    RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],39,0x92722c85);
+    RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],40,0xa2bfe8a1);
+    RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],41,0xa81a664b);
+    RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],42,0xc24b8b70);
+    RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],43,0xc76c51a3);
+    RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],44,0xd192e819);
+    RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],45,0xd6990624);
+    RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],46,0xf40e3585);
+    RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],47,0x106aa070);
+    RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],48,0x19a4c116);
+    RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],49,0x1e376c08);
+    RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],50,0x2748774c);
+    RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],51,0x34b0bcb5);
+    RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],52,0x391c0cb3);
+    RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],53,0x4ed8aa4a);
+    RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],54,0x5b9cca4f);
+    RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],55,0x682e6ff3);
+    RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],56,0x748f82ee);
+    RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],57,0x78a5636f);
+    RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],58,0x84c87814);
+    RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],59,0x8cc70208);
+    RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],60,0x90befffa);
+    RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],61,0xa4506ceb);
+    RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],62,0xbef9a3f7);
+    RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],63,0xc67178f2);
+
+#undef RND     
+    
+#endif     
+
+    /* feedback */
+    for (i = 0; i < 8; i++) {
+        md->sha256.state[i] = md->sha256.state[i] + S[i];
+    }
+    return CRYPT_OK;
+}
+
+#ifdef LTC_CLEAN_STACK
+static int sha256_compress(hash_state * md, unsigned char *buf)
+{
+    int err;
+    err = _sha256_compress(md, buf);
+    burn_stack(sizeof(ulong32) * 74);
+    return err;
+}
+#endif
+
+/**
+   Initialize the hash state
+   @param md   The hash state you wish to initialize
+   @return CRYPT_OK if successful
+*/
+int sha256_init(hash_state * md)
+{
+    md->sha256.curlen = 0;
+    md->sha256.length = 0;
+    md->sha256.state[0] = 0x6A09E667UL;
+    md->sha256.state[1] = 0xBB67AE85UL;
+    md->sha256.state[2] = 0x3C6EF372UL;
+    md->sha256.state[3] = 0xA54FF53AUL;
+    md->sha256.state[4] = 0x510E527FUL;
+    md->sha256.state[5] = 0x9B05688CUL;
+    md->sha256.state[6] = 0x1F83D9ABUL;
+    md->sha256.state[7] = 0x5BE0CD19UL;
+    return CRYPT_OK;
+}
+
+#define HASH_PROCESS(func_name, compress_name, state_var, block_size)                       \
+int func_name (hash_state * md, const unsigned char *in, unsigned long inlen)               \
+{                                                                                           \
+    unsigned long n;                                                                        \
+    int           err;                                                                      \
+    if (md-> state_var .curlen > sizeof(md-> state_var .buf)) {                             \
+       return CRYPT_INVALID_ARG;                                                            \
+    }                                                                                       \
+    while (inlen > 0) {                                                                     \
+        if (md-> state_var .curlen == 0 && inlen >= block_size) {                           \
+           if ((err = compress_name (md, (unsigned char *)in)) != CRYPT_OK) {               \
+              return err;                                                                   \
+           }                                                                                \
+           md-> state_var .length += block_size * 8;                                        \
+           in             += block_size;                                                    \
+           inlen          -= block_size;                                                    \
+        } else {                                                                            \
+           n = MIN(inlen, (block_size - md-> state_var .curlen));                           \
+           memcpy(md-> state_var .buf + md-> state_var.curlen, in, (size_t)n);              \
+           md-> state_var .curlen += n;                                                     \
+           in             += n;                                                             \
+           inlen          -= n;                                                             \
+           if (md-> state_var .curlen == block_size) {                                      \
+              if ((err = compress_name (md, md-> state_var .buf)) != CRYPT_OK) {            \
+                 return err;                                                                \
+              }                                                                             \
+              md-> state_var .length += 8*block_size;                                       \
+              md-> state_var .curlen = 0;                                                   \
+           }                                                                                \
+       }                                                                                    \
+    }                                                                                       \
+    return CRYPT_OK;                                                                        \
+}
+
+/**
+   Process a block of memory though the hash
+   @param md     The hash state
+   @param in     The data to hash
+   @param inlen  The length of the data (octets)
+   @return CRYPT_OK if successful
+*/
+HASH_PROCESS(sha256_process, sha256_compress, sha256, 64)
+
+/**
+   Terminate the hash to get the digest
+   @param md  The hash state
+   @param out [out] The destination of the hash (32 bytes)
+   @return CRYPT_OK if successful
+*/
+int sha256_done(hash_state * md, unsigned char *out)
+{
+    int i;
+
+    if (md->sha256.curlen >= sizeof(md->sha256.buf)) {
+       return CRYPT_INVALID_ARG;
+    }
+
+
+    /* increase the length of the message */
+    md->sha256.length += md->sha256.curlen * 8;
+
+    /* append the '1' bit */
+    md->sha256.buf[md->sha256.curlen++] = (unsigned char)0x80;
+
+    /* if the length is currently above 56 bytes we append zeros
+     * then compress.  Then we can fall back to padding zeros and length
+     * encoding like normal.
+     */
+    if (md->sha256.curlen > 56) {
+        while (md->sha256.curlen < 64) {
+            md->sha256.buf[md->sha256.curlen++] = (unsigned char)0;
+        }
+        sha256_compress(md, md->sha256.buf);
+        md->sha256.curlen = 0;
+    }
+
+    /* pad upto 56 bytes of zeroes */
+    while (md->sha256.curlen < 56) {
+        md->sha256.buf[md->sha256.curlen++] = (unsigned char)0;
+    }
+
+    /* store length */
+    STORE64H(md->sha256.length, md->sha256.buf+56);
+    sha256_compress(md, md->sha256.buf);
+
+    /* copy output */
+    for (i = 0; i < 8; i++) {
+        STORE32H(md->sha256.state[i], out+(4*i));
+    }
+#ifdef LTC_CLEAN_STACK
+    zeromem(md, sizeof(hash_state));
+#endif
+    return CRYPT_OK;
+}
+
+/***
+  Write entropy collectors here.
+  
+  Entropy collector can return entropy of up to 32 bytes.
+  Copy entropy to 'data'.
+***/
+
+/* UNIX /dev/random Linux /dev/urandom entropy collector */
+void collect_entropy1(char* data)
+{
+	#ifdef UNIX
+	#ifdef LINUX
+	FILE* f = fopen("/dev/urandom", "rb");
+	#else
+	FILE* f = fopen("/dev/random", "rb");
+	#endif
+	memset(data, 0, 32);
+	
+	if (!f)
+		return;
+	
+	/* Read 32 bytes */
+	fread(data, 32, 1, f);
+	
+	fclose(f);
+	#endif
+}
+
+/* High-resolution timer entropy collector */
+void collect_entropy2(char* data)
+{
+	struct timeval tv;
+	gettimeofday(&tv, (struct timezone*) 0);
+	
+	memcpy(data, &tv.tv_sec, sizeof(int));
+	memcpy(data + sizeof(int), &tv.tv_usec, sizeof(int));
+	memset(data + 2 * sizeof(int), 0, 32 - sizeof(int) * 2);
+}
+
+hash_state md;
+
+unsigned int good_random(void)
+{
+	/* A 128-bit counter value. */
+	static unsigned int counter[] = { 0, 0, 0, 0 };
+	static int output_number = 4;
+	static unsigned int outputs[] = { 0, 0, 0, 0 };
+	static symmetric_key key;
+	static unsigned char encrypt_key[] = { '1', '2', '3', '4', '5', '6', '7', '8', '9', '0',
+	                                       '1', '2', '3', '4', '5', '6', '7', '8', '9', '0',
+	                                       '1', '2', '3', '4', '5', '6', '7', '8', '9', '0',
+	                                       '1', '2' };
+	char entropy[96];
+	
+	/* Collect entropy and reseed every 1000th random number (and at start) */
+	if (!(counter[0] % 1000))
+	{
+		collect_entropy1(entropy);
+		collect_entropy2(entropy + 32);
+		memcpy(entropy + 64, encrypt_key, 32);
+		
+		sha256_init(&md);
+		sha256_process(&md, (unsigned char*) entropy, 96);
+		sha256_done(&md, (unsigned char*) encrypt_key);
+		
+		AES_SETUP(encrypt_key, 32, 0, &key);
+	}
+	
+	/* One block will provide us with 4 random outputs. */
+	if (output_number == 4)
+	{
+		output_number = 0;
+		AES_encrypt((unsigned char*) counter, (unsigned char*) outputs, &key);
+		/* Generate new key after every 28 random numbers */
+		if (!(counter[0] % 28))
+		{
+			sha256_init(&md);
+			sha256_process(&md, (unsigned char*) outputs, sizeof(unsigned int) * 4);
+			sha256_done(&md, (unsigned char*) encrypt_key);
+			
+			AES_SETUP(encrypt_key, 32, 0, &key);
+			AES_encrypt((unsigned char*) counter, (unsigned char*) outputs, &key);
+		}
+	}
+	
+	++counter[0];
+	if (counter[0] == 0)
+	{
+		++counter[1];
+		if (counter[1] == 0)
+		{
+			++counter[2];
+			if (counter[2] == 0)
+				++counter[3];
+		}
+	}
+	
+	return outputs[output_number++];
+}
+
+
 /*rnd.c*/
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/src/role.c nethack/src/role.c
--- nh_orig/src/role.c	2003-12-07 18:39:13.000000000 -0500
+++ nethack/src/role.c	2009-11-04 09:17:51.009397878 -0500
@@ -40,7 +40,6 @@
 	PM_ARCHEOLOGIST, NON_PM, NON_PM,
 	PM_LORD_CARNARVON, PM_STUDENT, PM_MINION_OF_HUHETOTL,
-	NON_PM, PM_HUMAN_MUMMY, S_SNAKE, S_MUMMY,
 	ART_ORB_OF_DETECTION,
-	MH_HUMAN|MH_DWARF|MH_GNOME | ROLE_MALE|ROLE_FEMALE |
+	MH_HUMAN|MH_DWARF|MH_GNOME|MH_ELF|MH_ORC | ROLE_MALE|ROLE_FEMALE |
 	  ROLE_LAWFUL|ROLE_NEUTRAL,
 	/* Str Int Wis Dex Con Cha */
@@ -66,7 +65,6 @@
 	PM_BARBARIAN, NON_PM, NON_PM,
 	PM_PELIAS, PM_CHIEFTAIN, PM_THOTH_AMON,
-	PM_OGRE, PM_TROLL, S_OGRE, S_TROLL,
 	ART_HEART_OF_AHRIMAN,
-	MH_HUMAN|MH_ORC | ROLE_MALE|ROLE_FEMALE |
+	MH_HUMAN|MH_DWARF|MH_GNOME|MH_ELF|MH_ORC | ROLE_MALE|ROLE_FEMALE |
 	  ROLE_NEUTRAL|ROLE_CHAOTIC,
 	/* Str Int Wis Dex Con Cha */
@@ -76,5 +74,5 @@
 	{ 14, 0,  0,10,  2, 0 },	/* Hit points */
 	{  1, 0,  0, 1,  0, 1 },10,	/* Energy */
-	10, 14, 0, 0,  8, A_INT, SPE_HASTE_SELF,      -4
+	10, 14, 0, 0,  8, A_INT, SPE_CAUSE_FEAR,      -8	/* this isn't accidental */
 },
 {	{"Caveman", "Cavewoman"}, {
@@ -89,10 +87,9 @@
 	{"Pioneer",     0} },
 	"Anu", "_Ishtar", "Anshar", /* Babylonian */
-	"Cav", "the Caves of the Ancestors", "the Dragon's Lair",
+	"Cav", "the Deep Jungle", "the Dragon's Lair",
 	PM_CAVEMAN, PM_CAVEWOMAN, PM_LITTLE_DOG,
 	PM_SHAMAN_KARNOV, PM_NEANDERTHAL, PM_CHROMATIC_DRAGON,
-	PM_BUGBEAR, PM_HILL_GIANT, S_HUMANOID, S_GIANT,
 	ART_SCEPTRE_OF_MIGHT,
-	MH_HUMAN|MH_DWARF|MH_GNOME | ROLE_MALE|ROLE_FEMALE |
+	MH_HUMAN|MH_DWARF|MH_GNOME|MH_ELF|MH_ORC | ROLE_MALE|ROLE_FEMALE |
 	  ROLE_LAWFUL|ROLE_NEUTRAL,
 	/* Str Int Wis Dex Con Cha */
@@ -118,7 +115,7 @@
 	PM_HEALER, NON_PM, NON_PM,
 	PM_HIPPOCRATES, PM_ATTENDANT, PM_CYCLOPS,
-	PM_GIANT_RAT, PM_SNAKE, S_RODENT, S_YETI,
 	ART_STAFF_OF_AESCULAPIUS,
-	MH_HUMAN|MH_GNOME | ROLE_MALE|ROLE_FEMALE | ROLE_NEUTRAL,
+	MH_HUMAN|MH_GNOME|MH_ELF|MH_ORC|MH_DWARF | ROLE_MALE|ROLE_FEMALE | 
+		ROLE_LAWFUL|ROLE_NEUTRAL,
 	/* Str Int Wis Dex Con Cha */
 	{   7,  7, 13,  7, 11, 16 },
@@ -143,7 +140,7 @@
 	PM_KNIGHT, NON_PM, PM_PONY,
 	PM_KING_ARTHUR, PM_PAGE, PM_IXOTH,
-	PM_QUASIT, PM_OCHRE_JELLY, S_IMP, S_JELLY,
 	ART_MAGIC_MIRROR_OF_MERLIN,
-	MH_HUMAN | ROLE_MALE|ROLE_FEMALE | ROLE_LAWFUL,
+	MH_HUMAN|MH_GNOME|MH_ELF|MH_ORC|MH_DWARF | ROLE_MALE|ROLE_FEMALE | 
+		ROLE_LAWFUL|ROLE_CHAOTIC,
 	/* Str Int Wis Dex Con Cha */
 	{  13,  7, 14,  8, 10, 17 },
@@ -152,5 +149,5 @@
 	{ 14, 0,  0, 8,  2, 0 },	/* Hit points */
 	{  1, 4,  0, 1,  0, 2 },10,	/* Energy */
-	10, 8,-2, 0,  9, A_WIS, SPE_TURN_UNDEAD,     -4
+	10, 8,-2, 0,  9, A_WIS, SPE_EXTRA_HEALING,     -4
 },
 {	{"Monk", 0}, {
@@ -169,7 +166,6 @@
 	PM_MONK, NON_PM, NON_PM,
 	PM_GRAND_MASTER, PM_ABBOT, PM_MASTER_KAEN,
-	PM_EARTH_ELEMENTAL, PM_XORN, S_ELEMENTAL, S_XORN,
 	ART_EYES_OF_THE_OVERWORLD,
-	MH_HUMAN | ROLE_MALE|ROLE_FEMALE |
+	MH_HUMAN|MH_ELF|MH_GNOME|MH_ORC|MH_DWARF | ROLE_MALE|ROLE_FEMALE |
 	  ROLE_LAWFUL|ROLE_NEUTRAL|ROLE_CHAOTIC,
 	/* Str Int Wis Dex Con Cha */
@@ -195,7 +191,6 @@
 	PM_PRIEST, PM_PRIESTESS, NON_PM,
 	PM_ARCH_PRIEST, PM_ACOLYTE, PM_NALZOK,
-	PM_HUMAN_ZOMBIE, PM_WRAITH, S_ZOMBIE, S_WRAITH,
 	ART_MITRE_OF_HOLINESS,
-	MH_HUMAN|MH_ELF | ROLE_MALE|ROLE_FEMALE |
+	MH_HUMAN|MH_ELF|MH_GNOME|MH_ORC|MH_DWARF | ROLE_MALE|ROLE_FEMALE |
 	  ROLE_LAWFUL|ROLE_NEUTRAL|ROLE_CHAOTIC,
 	/* Str Int Wis Dex Con Cha */
@@ -223,8 +218,7 @@
 	PM_ROGUE, NON_PM, NON_PM,
 	PM_MASTER_OF_THIEVES, PM_THUG, PM_MASTER_ASSASSIN,
-	PM_LEPRECHAUN, PM_GUARDIAN_NAGA, S_NYMPH, S_NAGA,
 	ART_MASTER_KEY_OF_THIEVERY,
-	MH_HUMAN|MH_ORC | ROLE_MALE|ROLE_FEMALE |
-	  ROLE_CHAOTIC,
+	MH_HUMAN|MH_ORC|MH_ELF|MH_GNOME|MH_DWARF | ROLE_MALE|ROLE_FEMALE |
+	  ROLE_NEUTRAL|ROLE_CHAOTIC,
 	/* Str Int Wis Dex Con Cha */
 	{   7,  7,  7, 10,  7,  6 },
@@ -263,7 +257,6 @@
 	PM_RANGER, NON_PM, PM_LITTLE_DOG /* Orion & canis major */,
 	PM_ORION, PM_HUNTER, PM_SCORPIUS,
-	PM_FOREST_CENTAUR, PM_SCORPION, S_CENTAUR, S_SPIDER,
 	ART_LONGBOW_OF_DIANA,
-	MH_HUMAN|MH_ELF|MH_GNOME|MH_ORC | ROLE_MALE|ROLE_FEMALE |
+	MH_HUMAN|MH_ELF|MH_GNOME|MH_ORC|MH_DWARF | ROLE_MALE|ROLE_FEMALE |
 	  ROLE_NEUTRAL|ROLE_CHAOTIC,
 	/* Str Int Wis Dex Con Cha */
@@ -273,5 +266,5 @@
 	{ 13, 0,  0, 6,  1, 0 },	/* Hit points */
 	{  1, 0,  0, 1,  0, 1 },12,	/* Energy */
-	10, 9, 2, 1, 10, A_INT, SPE_INVISIBILITY,   -4
+	10, 9, 2, 1, 10, A_INT, SPE_DETECT_MONSTERS,   -4
 },
 {	{"Samurai", 0}, {
@@ -289,7 +282,7 @@
 	PM_SAMURAI, NON_PM, PM_LITTLE_DOG,
 	PM_LORD_SATO, PM_ROSHI, PM_ASHIKAGA_TAKAUJI,
-	PM_WOLF, PM_STALKER, S_DOG, S_ELEMENTAL,
 	ART_TSURUGI_OF_MURAMASA,
-	MH_HUMAN | ROLE_MALE|ROLE_FEMALE | ROLE_LAWFUL,
+	MH_HUMAN|MH_ELF|MH_DWARF|MH_GNOME|MH_ORC | ROLE_MALE|ROLE_FEMALE | 
+		ROLE_LAWFUL | ROLE_NEUTRAL,
 	/* Str Int Wis Dex Con Cha */
 	{  10,  8,  7, 10, 17,  6 },
@@ -315,7 +308,7 @@
 	PM_TOURIST, NON_PM, NON_PM,
 	PM_TWOFLOWER, PM_GUIDE, PM_MASTER_OF_THIEVES,
-	PM_GIANT_SPIDER, PM_FOREST_CENTAUR, S_SPIDER, S_CENTAUR,
 	ART_YENDORIAN_EXPRESS_CARD,
-	MH_HUMAN | ROLE_MALE|ROLE_FEMALE | ROLE_NEUTRAL,
+	MH_HUMAN|MH_ELF|MH_DWARF|MH_GNOME|MH_ORC | ROLE_MALE|ROLE_FEMALE | 
+		ROLE_NEUTRAL | ROLE_CHAOTIC,
 	/* Str Int Wis Dex Con Cha */
 	{   7, 10,  6,  7,  7, 10 },
@@ -341,7 +334,6 @@
 	PM_VALKYRIE, NON_PM, NON_PM /*PM_WINTER_WOLF_CUB*/,
 	PM_NORN, PM_WARRIOR, PM_LORD_SURTUR,
-	PM_FIRE_ANT, PM_FIRE_GIANT, S_ANT, S_GIANT,
 	ART_ORB_OF_FATE,
-	MH_HUMAN|MH_DWARF | ROLE_FEMALE | ROLE_LAWFUL|ROLE_NEUTRAL,
+	MH_HUMAN|MH_DWARF|MH_ELF|MH_GNOME|MH_ORC | ROLE_FEMALE | ROLE_LAWFUL|ROLE_NEUTRAL,
 	/* Str Int Wis Dex Con Cha */
 	{  10,  7,  7,  7, 10,  7 },
@@ -350,5 +342,5 @@
 	{ 14, 0,  0, 8,  2, 0 },	/* Hit points */
 	{  1, 0,  0, 1,  0, 1 },10,	/* Energy */
-	0, 10,-2, 0,  9, A_WIS, SPE_CONE_OF_COLD,    -4
+	0, 10,-2, 0,  9, A_WIS, SPE_REPAIR_ARMOR,    -4
 },
 {	{"Wizard", 0}, {
@@ -366,7 +358,6 @@
 	PM_WIZARD, NON_PM, PM_KITTEN,
 	PM_NEFERET_THE_GREEN, PM_APPRENTICE, PM_DARK_ONE,
-	PM_VAMPIRE_BAT, PM_XORN, S_BAT, S_WRAITH,
 	ART_EYE_OF_THE_AETHIOPICA,
-	MH_HUMAN|MH_ELF|MH_GNOME|MH_ORC | ROLE_MALE|ROLE_FEMALE |
+	MH_HUMAN|MH_ELF|MH_GNOME|MH_ORC|MH_DWARF | ROLE_MALE|ROLE_FEMALE |
 	  ROLE_NEUTRAL|ROLE_CHAOTIC,
 	/* Str Int Wis Dex Con Cha */
@@ -374,5 +365,5 @@
 	{  10, 30, 10, 20, 20, 10 },
 	/* Init   Lower  Higher */
-	{ 10, 0,  0, 8,  1, 0 },	/* Hit points */
+	{ 12, 0,  0, 6,  1, 0 },	/* Hit points */
 	{  4, 3,  0, 2,  0, 3 },12,	/* Energy */
 	0, 1, 0, 3, 10, A_INT, SPE_MAGIC_MISSILE,   -4
@@ -382,4 +373,40 @@
 };
 
+/* 
+ * Realistically we don't need to build another structure array just for this
+ * but this does leave us a framework to do more crossaligned roles
+ * sometimes in the future, if we feel like it
+ *
+ * ideally we'd just properly expand roles[] but the hack is easier for a patch
+ */
+
+const struct Role align_roles[] = {
+{	{"Dark Knight", 0}, 
+	{  {"Sniveler", 0},
+		{"Pawn", 0},
+		{"Brute", 0},
+		{"Mercenary", 0},
+		{"Blackguard", 0},
+		{"Turncoat", 0},
+		{"Knave", 0},
+		{"Dark Baron", 0}, 
+		{"Dark Paladin", 0} },
+	"Lugh", "_Brigit", "Manannan Mac Lir", /* Celtic */
+	"Kni", "Camelot Castle", "the Isle of Glass",
+	PM_KNIGHT, NON_PM, PM_PONY,
+	PM_KING_ARTHUR, PM_PAGE, PM_IXOTH,
+	ART_MAGIC_MIRROR_OF_MERLIN,
+	MH_HUMAN | ROLE_MALE|ROLE_FEMALE | ROLE_LAWFUL|ROLE_CHAOTIC,
+	/* Str Int Wis Dex Con Cha */
+	{  13,  7, 14,  8, 10, 17 },
+	{  30, 15, 15, 10, 20, 10 },
+	/* Init   Lower  Higher */
+	{ 14, 0,  0, 8,  2, 0 },	/* Hit points */
+	{  1, 4,  0, 1,  0, 2 },10,	/* Energy */
+	10, 8,-2, 0,  9, A_WIS, SPE_TURN_UNDEAD,     -4
+},
+/* new terminator, though we don't need it here */
+{{0, 0}}
+};
 
 /* The player's role, created at runtime from initial
@@ -391,5 +418,5 @@
 	"L", "N", "C", "Xxx", "home", "locate",
 	NON_PM, NON_PM, NON_PM, NON_PM, NON_PM, NON_PM,
-	NON_PM, NON_PM, 0, 0, 0, 0,
+	0, 0,
 	/* Str Int Wis Dex Con Cha */
 	{   7,  7,  7,  7,  7,  7 },
@@ -408,6 +435,5 @@
 	{"man", "woman"},
 	PM_HUMAN, NON_PM, PM_HUMAN_MUMMY, PM_HUMAN_ZOMBIE,
-	MH_HUMAN | ROLE_MALE|ROLE_FEMALE |
-	  ROLE_LAWFUL|ROLE_NEUTRAL|ROLE_CHAOTIC,
+	MH_HUMAN | ROLE_MALE|ROLE_FEMALE | ROLE_LAWFUL|ROLE_NEUTRAL|ROLE_CHAOTIC,
 	MH_HUMAN, 0, MH_GNOME|MH_ORC,
 	/*    Str     Int Wis Dex Con Cha */
@@ -421,5 +447,5 @@
 	{0, 0},
 	PM_ELF, NON_PM, PM_ELF_MUMMY, PM_ELF_ZOMBIE,
-	MH_ELF | ROLE_MALE|ROLE_FEMALE | ROLE_CHAOTIC,
+	MH_ELF | ROLE_MALE|ROLE_FEMALE | ROLE_NEUTRAL|ROLE_CHAOTIC,
 	MH_ELF, MH_ELF, MH_ORC,
 	/*  Str    Int Wis Dex Con Cha */
@@ -433,5 +459,5 @@
 	{0, 0},
 	PM_DWARF, NON_PM, PM_DWARF_MUMMY, PM_DWARF_ZOMBIE,
-	MH_DWARF | ROLE_MALE|ROLE_FEMALE | ROLE_LAWFUL,
+	MH_DWARF | ROLE_MALE|ROLE_FEMALE | ROLE_LAWFUL|ROLE_NEUTRAL,
 	MH_DWARF, MH_DWARF|MH_GNOME, MH_ORC,
 	/*    Str     Int Wis Dex Con Cha */
@@ -445,5 +471,5 @@
 	{0, 0},
 	PM_GNOME, NON_PM, PM_GNOME_MUMMY, PM_GNOME_ZOMBIE,
-	MH_GNOME | ROLE_MALE|ROLE_FEMALE | ROLE_NEUTRAL,
+	MH_GNOME | ROLE_MALE|ROLE_FEMALE | ROLE_NEUTRAL|ROLE_CHAOTIC,
 	MH_GNOME, MH_DWARF|MH_GNOME, MH_HUMAN,
 	/*  Str    Int Wis Dex Con Cha */
@@ -457,5 +483,5 @@
 	{0, 0},
 	PM_ORC, NON_PM, PM_ORC_MUMMY, PM_ORC_ZOMBIE,
-	MH_ORC | ROLE_MALE|ROLE_FEMALE | ROLE_CHAOTIC,
+	MH_ORC | ROLE_MALE|ROLE_FEMALE | ROLE_NEUTRAL|ROLE_CHAOTIC,
 	MH_ORC, 0, MH_HUMAN|MH_ELF|MH_DWARF,
 	/*  Str    Int Wis Dex Con Cha */
@@ -1333,4 +1359,6 @@
  *	across a save/restore.  :-)
  *
+ *	DSR 10/31/09: Well, you don't anymore, but hacking this up doesn't add much.
+ *
  *	1 - The Rogue Leader is the Tourist Nemesis.
  *	2 - Priests start with a random alignment - convert the leader and
@@ -1389,4 +1417,9 @@
 	urace = races[flags.initrace];
 
+	/* kick it over to alternate-alignment role */
+	if (alignmnt == A_CHAOTIC && Role_if(PM_KNIGHT)) {
+		urole = align_roles[0];
+	}
+
 	/* Fix up the quest leader */
 	if (urole.ldrnum != NON_PM) {
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/src/save.c nethack/src/save.c
--- nh_orig/src/save.c	2003-12-07 18:39:13.000000000 -0500
+++ nethack/src/save.c	2009-11-22 07:19:36.746272070 -0500
@@ -32,4 +32,6 @@
 STATIC_DCL void FDECL(savetrapchn, (int,struct trap *,int));
 STATIC_DCL void FDECL(savegamestate, (int,int));
+void FDECL(save_mongen_override, (int,struct mon_gen_override *, int));
+void FDECL(save_lvl_sounds, (int,struct lvl_sounds *, int));
 #ifdef MFLOPPY
 STATIC_DCL void FDECL(savelev0, (int,XCHAR_P,int));
@@ -49,4 +51,14 @@
 #endif
 
+#ifdef MENU_COLOR
+extern struct menucoloring *menu_colorings;
+#endif
+
+#if defined(STATUS_COLORS) && defined(TEXTCOLOR)
+extern const struct percent_color_option *hp_colors;
+extern const struct percent_color_option *pw_colors;
+extern const struct text_color_option *text_colors;
+#endif
+
 /* need to preserve these during save to avoid accessing freed memory */
 static unsigned ustuck_id = 0, usteed_id = 0;
@@ -58,5 +70,5 @@
 	if(yn("Really save?") == 'n') {
 		clear_nhwindow(WIN_MESSAGE);
-		if(multi > 0) nomul(0);
+		if(multi > 0) nomul(0, 0);
 	} else {
 		clear_nhwindow(WIN_MESSAGE);
@@ -211,4 +223,5 @@
 	usteed_id = (u.usteed ? u.usteed->m_id : 0);
 #endif
+
 	savelev(fd, ledger_no(&u.uz), WRITE_SAVE | FREE_SAVE);
 	savegamestate(fd, WRITE_SAVE | FREE_SAVE);
@@ -266,4 +279,7 @@
 	delete_levelfile(ledger_no(&u.uz));
 	delete_levelfile(0);
+#ifdef WHEREIS_FILE
+	delete_whereis();
+#endif
 	compress(fq_save);
 	return(1);
@@ -275,4 +291,8 @@
 {
 	int uid;
+#if defined(RECORD_REALTIME) || defined(REALTIME_ON_BOTL)
+        time_t realtime;
+#endif
+
 
 #ifdef MFLOPPY
@@ -320,4 +340,13 @@
 	savenames(fd, mode);
 	save_waterlevel(fd, mode);
+
+#ifdef RECORD_ACHIEVE
+        bwrite(fd, (genericptr_t) &achieve, sizeof achieve);
+#endif
+#if defined(RECORD_REALTIME) || defined(REALTIME_ON_BOTL)
+        realtime = get_realtime();
+        bwrite(fd, (genericptr_t) &realtime, sizeof realtime);
+#endif
+
 	bflush(fd);
 }
@@ -541,4 +570,6 @@
 	saveobjchn(fd, level.buriedobjlist, mode);
 	saveobjchn(fd, billobjs, mode);
+	save_mongen_override(fd, level.mon_gen, mode);
+	save_lvl_sounds(fd, level.sounds, mode);
 	if (release_data(mode)) {
 	    fmon = 0;
@@ -547,4 +578,7 @@
 	    level.buriedobjlist = 0;
 	    billobjs = 0;
+	    free(level.mon_gen);
+	    level.mon_gen = NULL;
+	    level.sounds = NULL;
 	}
 	save_engravings(fd, mode);
@@ -836,4 +870,78 @@
 }
 
+void
+save_mongen_override(fd, or, mode)
+register int fd, mode;
+register struct mon_gen_override *or;
+{
+    struct mon_gen_tuple *mt;
+    struct mon_gen_tuple *prev;
+    int marker = 0;
+
+    if (!or) {
+	if (perform_bwrite(mode)) {
+	    marker = 0;
+	    bwrite(fd, (genericptr_t) &marker, sizeof(marker));
+	}
+    } else {
+	if (perform_bwrite(mode)) {
+	    marker = 1;
+	    bwrite(fd, (genericptr_t) &marker, sizeof(marker));
+	    bwrite(fd, (genericptr_t) or, sizeof(struct mon_gen_override));
+	}
+	mt = or->gen_chances;
+	while (mt) {
+	    if (perform_bwrite(mode)) {
+		bwrite(fd, (genericptr_t) mt, sizeof(struct mon_gen_tuple));
+	    }
+	    prev = mt;
+	    mt = mt->next;
+	    if (release_data(mode))
+		free(prev);
+	}
+	if (release_data(mode))
+	    or->gen_chances = NULL;
+    }
+}
+
+void
+save_lvl_sounds(fd, or, mode)
+register int fd, mode;
+register struct lvl_sounds *or;
+{
+    struct lvl_sound_bite *mt;
+    int marker = 0;
+    int i;
+    int len;
+
+    if (!or) {
+	if (perform_bwrite(mode)) {
+	    marker = 0;
+	    bwrite(fd, (genericptr_t) &marker, sizeof(marker));
+	}
+    } else {
+	if (perform_bwrite(mode)) {
+	    marker = 1;
+	    bwrite(fd, (genericptr_t) &marker, sizeof(marker));
+	    bwrite(fd, (genericptr_t) or, sizeof(struct lvl_sounds));
+
+	    for (i = 0; i < or->n_sounds; i++) {
+		bwrite(fd, (genericptr_t)&(or->sounds[i].flags), sizeof(or->sounds[i].flags));
+		len = strlen(or->sounds[i].msg)+1;
+		bwrite(fd, (genericptr_t)&len, sizeof(len));
+		bwrite(fd, (genericptr_t)or->sounds[i].msg, len);
+	    }
+	}
+	if (release_data(mode)) {
+	    for (i = 0; i < or->n_sounds; i++)
+		free(or->sounds[i].msg);
+	    free(or->sounds);
+	    or->sounds = NULL;
+	    or->n_sounds = 0;
+	}
+    }
+}
+
+
 STATIC_OVL void
 saveobjchn(fd, otmp, mode)
@@ -875,6 +983,9 @@
 	register struct monst *mtmp2;
 	unsigned int xl;
+	int iter;
 	int minusone = -1;
+	int nummons = NUMMONS;
 	struct permonst *monbegin = &mons[0];
+	int namesize = sizeof(monbegin->mname);
 
 	if (perform_bwrite(mode))
@@ -896,4 +1007,16 @@
 	if (perform_bwrite(mode))
 	    bwrite(fd, (genericptr_t) &minusone, sizeof(int));
+
+	/* save off our own particular permonst chain */
+	if (perform_bwrite(mode)) {
+	    bwrite(fd, (genericptr_t) &nummons, sizeof(int));	 /* future compatibility check */
+	}
+	for (iter=0;iter < nummons;iter++)
+	{
+		if (perform_bwrite(mode)) {
+			bwrite(fd, (genericptr_t) &mons[iter]+namesize, sizeof(struct permonst)-namesize);
+		}
+	}
+
 }
 
@@ -943,4 +1066,34 @@
 }
 
+#if defined(STATUS_COLORS) && defined(TEXTCOLOR)
+
+void
+free_percent_color_options(list_head)
+const struct percent_color_option *list_head;
+{
+	if (list_head == NULL) return;
+	free_percent_color_options(list_head->next);
+	free((void*)list_head);
+}
+
+void
+free_text_color_options(list_head)
+const struct text_color_option *list_head;
+{
+	if (list_head == NULL) return;
+	free_text_color_options(list_head->next);
+	free((void*)list_head->text);
+	free((void*)list_head);
+}
+
+void
+free_status_colors()
+{
+	free_percent_color_options(hp_colors); hp_colors = NULL;
+	free_percent_color_options(pw_colors); pw_colors = NULL;
+	free_text_color_options(text_colors); text_colors = NULL;
+}
+#endif
+
 /* also called by prscore(); this probably belongs in dungeon.c... */
 void
@@ -954,10 +1107,35 @@
 }
 
+#ifdef MENU_COLOR
+void
+free_menu_coloring()
+{
+    struct menucoloring *tmp = menu_colorings;
+
+    while (tmp) {
+	struct menucoloring *tmp2 = tmp->next;
+# ifdef MENU_COLOR_REGEX
+	(void) regfree(&tmp->match);
+# else
+	free(tmp->match);
+# endif
+	free(tmp);
+	tmp = tmp2;
+    }
+}
+#endif /* MENU_COLOR */
+
 void
 freedynamicdata()
 {
+#if defined(STATUS_COLORS) && defined(TEXTCOLOR)
+	free_status_colors();
+#endif
 	unload_qtlist();
 	free_invbuf();	/* let_to_name (invent.c) */
 	free_youbuf();	/* You_buf,&c (pline.c) */
+#ifdef MENU_COLOR
+	free_menu_coloring();
+#endif
 	tmp_at(DISP_FREEMEM, 0);	/* temporary display effects */
 #ifdef FREE_ALL_MEMORY
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/src/shk.c nethack/src/shk.c
--- nh_orig/src/shk.c	2003-12-07 18:39:13.000000000 -0500
+++ nethack/src/shk.c	2010-04-23 14:27:35.746714987 -0400
@@ -493,5 +493,5 @@
 	    total, currency(total));
 	if (!Role_if(PM_ROGUE))	/* stealing is unlawful */
-	    adjalign(-sgn(u.ualign.type));
+		minor_sin();
 
 	hot_pursuit(shkp);
@@ -1842,4 +1842,33 @@
 #ifdef OVL3
 
+/** Returns the price of an arbitrary item in the shop.
+ * Returns 0 if the item doesn't belong to a shopkeeper. */
+long
+get_cost_of_shop_item(obj)
+register struct obj *obj;
+{
+	struct monst *shkp;
+	xchar x, y;
+	int cost=0;
+
+	if (get_obj_location(obj, &x, &y, 0) &&
+	    (obj->unpaid ||
+	     (obj->where==OBJ_FLOOR && !obj->no_charge && costly_spot(x,y)))) {
+
+		if (!(shkp = shop_keeper(*in_rooms(x, y, SHOPBASE)))) return 0;
+		if (!inhishop(shkp)) return 0;
+		if (!costly_spot(x, y))	return 0;
+		if (!*u.ushops) return 0;
+
+		if (obj->oclass != COIN_CLASS) {
+			cost = (obj == uball || obj == uchain) ? 0L :
+			    (obj->quan * get_cost(obj, shkp));
+			if (Has_contents(obj)) {
+				cost += contained_cost(obj, shkp, 0L, FALSE, FALSE);
+			}
+		}
+	}
+	return cost;
+}
 /* calculate the value that the shk will charge for [one of] an object */
 STATIC_OVL long
@@ -1918,4 +1947,94 @@
 	/* anger surcharge should match rile_shk's */
 	if (shkp && ESHK(shkp)->surcharge) tmp += (tmp + 2L) / 3L;
+
+	/* possible additional surcharges based on shk race, if one was passed in */
+	if (shkp) {
+		switch (shkp->mnum) {
+			default:
+			case PM_HUMAN:
+			case PM_SERGEANT:
+			case PM_LIEUTENANT:
+			case PM_CAPTAIN:
+			case PM_KOP_SERGEANT:
+			case PM_KOP_LIEUTENANT:
+			case PM_KOP_KAPTAIN:
+				/* nasty, brutish, and short */
+				if (Race_if(PM_ORC) || Race_if(PM_GNOME)) { tmp += tmp / 3L; }	  
+				break;
+			case PM_WOODLAND_ELF:
+			case PM_GREEN_ELF:
+			case PM_GREY_ELF:
+			case PM_ELF_LORD:
+				if (Race_if(PM_ORC)) { tmp *= 2L; }
+				if (Race_if(PM_DWARF)) { tmp += tmp / 3L; }	/* "lawn ornament." */
+				break;
+			case PM_DWARF:
+				if (Race_if(PM_ORC)) { tmp *= 2L; }
+				if (Race_if(PM_ELF)) { tmp += tmp / 3L; }  /* "pointy-eared tree hugger." */
+				break;
+			case PM_ORC:
+				if (Race_if(PM_ELF)) { tmp *= 3L; }
+				if (Race_if(PM_DWARF)) { tmp += (tmp * 2L) / 3L; }
+				if (Race_if(PM_HUMAN)) { tmp += tmp / 3L; }
+				if (Race_if(PM_ORC)) { tmp -= tmp / 3L; }	  
+				/* big discount on top of professional courtesy */
+				break;
+			case PM_GNOME:
+			case PM_GNOME_LORD:
+			case PM_GNOME_KING:
+				/* Gnomes are crafty.  They don't really have racial animosities, but
+				* it's going to be a lot harder to get a good deal out of a gnome unless
+				* you're remarkably shrewd yourself. */
+				if (ACURR(A_INT) < 15) { tmp += tmp / 2L; }
+				else if (ACURR(A_INT) < 18) { tmp += tmp / 3L; }
+				break;
+			case PM_LICH:
+			case PM_DEMILICH:
+			case PM_MASTER_LICH:
+			case PM_ARCH_LICH:
+				/* They'd prefer not to sell their libraries. */
+				tmp *= (shkp->mnum - PM_LICH + 2);
+				break;
+			case PM_OGRE:
+			case PM_OGRE_LORD:
+			case PM_OGRE_KING:
+				/* Will tolerate orcs, but no discount. */
+				if (!Race_if(PM_ORC)) {
+					tmp += tmp / 2L;
+				}
+				break;
+			case PM_WOOD_NYMPH:
+			case PM_MOUNTAIN_NYMPH:
+			case PM_WATER_NYMPH:
+				if (ACURR(A_CHA) > 14)
+				{
+					/* Pretty people don't get gouged TOO badly... */
+					tmp += (shkp->mnum - PM_WOOD_NYMPH + 2) * (tmp / 6L);
+				} else {
+					/* ... but if you don't measure up... */
+					tmp += (shkp->mnum - PM_WOOD_NYMPH + 2) * (tmp / 3L);
+				}
+				break;
+			case PM_STONE_GIANT:
+			case PM_HILL_GIANT_SHAMAN:
+			case PM_HILL_GIANT:
+			case PM_FIRE_GIANT:
+			case PM_FROST_GIANT:
+			case PM_STORM_GIANT:
+				/* Non-Elder-Race humanoids are not thought of highly. */
+				if (Race_if(PM_HUMAN) || Race_if(PM_GNOME))
+				{
+					tmp += tmp / 2L;
+				}
+				break;
+		}
+	}
+
+	/* professional courtesy if nonhuman */
+	if (shkp && shkp->mnum != PM_HUMAN && match_shkrace(shkp)) { tmp -= tmp / 2L; }
+
+	/* and just make sure we haven't dealt ourselves out of money */
+	if (tmp < 1) { tmp = 3; }
+
 	return tmp;
 }
@@ -2049,4 +2168,96 @@
 			tmp -= tmp / 4L;
 	}
+
+	/* possible additional adjustments based on shk race.. */
+	switch (shkp->mnum) {
+		default:
+		case PM_HUMAN:
+		case PM_SERGEANT:
+		case PM_LIEUTENANT:
+		case PM_CAPTAIN:
+		case PM_KOP_SERGEANT:
+		case PM_KOP_LIEUTENANT:
+		case PM_KOP_KAPTAIN:
+			if (Race_if(PM_ORC) || Race_if(PM_GNOME)) { tmp -= tmp / 3L; }	  /* nasty, brutish, and short */
+			break;
+		case PM_WOODLAND_ELF:
+		case PM_GREEN_ELF:
+		case PM_GREY_ELF:
+		case PM_ELF_LORD:
+			if (Race_if(PM_ORC)) { tmp /= 2L; }
+			if (Race_if(PM_DWARF)) { tmp -= tmp / 3L; }	/* "lawn ornament." */
+			break;
+		case PM_DWARF:
+			if (Race_if(PM_ORC)) { tmp /= 2L; }
+			if (Race_if(PM_ELF)) { tmp -= tmp / 3L; }  /* "pointy-eared tree hugger." */
+			break;
+		case PM_ORC:
+			if (Race_if(PM_ELF)) { tmp /= 3L; }
+			if (Race_if(PM_DWARF)) { tmp -= (tmp * 2L) / 3L; }
+			if (Race_if(PM_HUMAN)) { tmp -= tmp / 3L; }
+			if (Race_if(PM_ORC)) { tmp += tmp / 3L; }	 /* on top of prof. courtesy */
+			break;
+		case PM_GNOME:
+		case PM_GNOME_LORD:
+		case PM_GNOME_KING:
+			/* Gnomes are crafty.  They don't really have racial animosities, but
+			 * it's going to be a lot harder to get a good deal out of a gnome unless
+			 * you're remarkably shrewd yourself. */
+			if (ACURR(A_INT) < 15) { tmp -= tmp / 2L; }
+			else if (ACURR(A_INT) < 18) { tmp -= tmp / 3L; }
+			break;
+		case PM_LICH:
+		case PM_DEMILICH:
+		case PM_MASTER_LICH:
+		case PM_ARCH_LICH:
+			/* They don't mind acquiring more books...
+			 * ...and yes, this is correct, older liches would value the books 
+			 * more than younger ones */
+			tmp -= tmp / (shkp->mnum - PM_LICH + 2);
+			break;
+		case PM_OGRE:
+		case PM_OGRE_LORD:
+		case PM_OGRE_KING:
+			/* Will tolerate orcs, but no discount. */
+			if (!Race_if(PM_ORC)) {
+				tmp -= tmp / 2L;
+			}
+			break;
+		case PM_WOOD_NYMPH:
+		case PM_MOUNTAIN_NYMPH:
+		case PM_WATER_NYMPH:
+			if (ACURR(A_CHA) > 14)
+			{
+				/* Pretty people don't get gouged TOO badly... */
+				tmp -= (shkp->mnum - PM_WOOD_NYMPH + 2) * (tmp / 6L);
+			} else {
+				/* ... but if you don't measure up... */
+				tmp -= (shkp->mnum - PM_WOOD_NYMPH + 2) * (tmp / 4L);
+			}
+			break;
+		case PM_STONE_GIANT:
+		case PM_HILL_GIANT_SHAMAN:
+		case PM_HILL_GIANT:
+		case PM_FIRE_GIANT:
+		case PM_FROST_GIANT:
+		case PM_STORM_GIANT:
+			/* Non-Elder-Race humanoids are not thought of highly. */
+			if (Race_if(PM_HUMAN) || Race_if(PM_GNOME))
+			{
+				tmp -= tmp / 2L;
+			}
+			break;
+
+	}
+
+	/* professional courtesy if nonhuman, but not _that_ much */
+	if (shkp->mnum != PM_HUMAN && match_shkrace(shkp)) { tmp += tmp / 3L; }
+
+	/* Final quick check; if we're about to buy this for more than we'd sell
+	 * it for in the first place, let's arrange to, er, not do that.  */
+	if (tmp > get_cost(obj,shkp) * obj->quan) { 
+		tmp = (get_cost(obj,shkp) * 4L / 5L) * obj->quan; 
+	}
+
 	return tmp;
 }
@@ -3205,4 +3416,9 @@
 	omy = shkp->my;
 
+	/* Random advertising to passersby */
+	if (!ANGRY(shkp) && inhishop(shkp) && !*u.ushops && !rn2(10)) {
+		shk_holler(shkp);
+	}
+
 	if (inhishop(shkp))
 	    remove_damage(shkp, FALSE);
@@ -3211,5 +3427,5 @@
 	   (shkp->data != &mons[PM_GRID_BUG] || (omx==u.ux || omy==u.uy))) {
 		if(ANGRY(shkp) ||
-		   (Conflict && !resist(shkp, RING_CLASS, 0, 0))) {
+		   (Conflict && !resist_conflict(shkp))) {
 			if(Displaced)
 			  Your("displaced image doesn't fool %s!",
@@ -3349,5 +3565,5 @@
 	if (Role_if(PM_KNIGHT)) {
 	    You_feel("like a common thief.");
-	    adjalign(-sgn(u.ualign.type));
+		 major_sin();
 	}
 	return;
@@ -3366,5 +3582,5 @@
 	if (Role_if(PM_KNIGHT)) {
 	    You_feel("like a common thief.");
-	    adjalign(-sgn(u.ualign.type));
+		 major_sin();
 	}
     } else if(!um_dist(shkp->mx, shkp->my, 5) &&
@@ -3595,5 +3811,5 @@
 		verbalize("Oh, yes!  You'll pay!");
 		hot_pursuit(shkp);
-		adjalign(-sgn(u.ualign.type));
+		minor_sin();
 	}
 }
@@ -3657,5 +3873,5 @@
 	if (otmp->oclass == COIN_CLASS) continue;
 	cost = (otmp->no_charge || otmp == uball || otmp == uchain) ? 0L :
-		get_cost(otmp, (struct monst *)0);
+		get_cost(otmp, shkp ? shkp : (struct monst*)0);
 	if (Has_contents(otmp))
 	    cost += contained_cost(otmp, shkp, 0L, FALSE, FALSE);
@@ -3676,5 +3892,5 @@
 	} else {
 	    /* print cost in slightly different format, so can't reuse buf */
-	    cost = get_cost(first_obj, (struct monst *)0);
+	    cost = get_cost(first_obj, shkp ? shkp : (struct monst *)0);
 	    if (Has_contents(first_obj))
 		cost += contained_cost(first_obj, shkp, 0L, FALSE, FALSE);
@@ -3800,4 +4016,120 @@
 }
 
+#define CRYNUMBER 5
+
+const char* armor_wares[] = {
+	"Any %s would love these!  Finest quality!",
+	"Fit for a Knight, but they'll last for weeks!",
+	"It's dangerous 'round here these days... better wear something safe!",
+	"Hey, %s, I've got something here that'll fit you perfectly!",
+	"Guaranteed safety or double your money back!"
+};
+const char* scroll_wares[] = {
+	"Large print available!",
+	"'ere now, this isn't a library; get lost, you freeloader!",
+	"Waterproof ink upon request!  ... for a small surcharge.",
+	"Curses removed, gold detected, and weapons enchanted, at your whim!",
+	"If you can read, %s, you'll want some of these!"
+};
+const char* potion_wares[] = {
+	"Bugger off, you filthy little %s. Don't come begging around here!",
+	"Booze on ice!  Getcher booze on ice!",
+	"Come on, %s.  You know you're thirsty.",
+	"Ahhh, it'll put hair on yer chest!",
+	"Lowest percentage of cursed items around!"
+};
+const char* weapon_wares[] = {
+	"Sharpest weapons around! On sale, today only!",
+	"We sell 'em, you stab 'em!",
+	"Guaranteed to not dull for ten fights or your money back!",
+	"Look, %s, with a face like that you'll be in a lot of fights.  Better buy something now.",
+	"You'll never slash the same again after one of ours!"
+};
+const char* food_wares[] = {
+	"Gitchore luvverly orinjes!",
+	"Fresh fish! So fresh it'll grab yer naughty bits!",
+	"Sausage inna bun!  Hot sausage!",
+	"Bugger off, you filthy little %s. Don't come begging around here!",
+	"Genuine pig parts, these. So good most pigs don't even know they got 'em."
+};
+const char* ring_wares[] = {
+	"Well, you seem like a fine, discerning young %s; come look at this.",
+	"Special sparklies for a special %s, perhaps?",
+	"Once you put one of ours on, you'll never want to take it off!",
+	"Our bands never break or melt!",
+	"Shiny, isn't it?"
+};
+const char* wand_wares[] = {
+	"Credit available for valued customers!",
+	"Bugger off, you filthy little %s. Don't come begging around here!",
+	"Straightest zaps anywhere!  100%% money back guarantee (less usage)!",
+	"Our wands explode less than all others!",
+	"New EZ-BREAK feature on these in case of emergency!"
+};
+const char* tool_wares[] = {
+	"Bugger off, you filthy little %s. Don't come begging around here!",
+	"Tins opened, faces wiped, gazes reflected; your one-stop shop!",
+	"How you gonna carry all your stuff without a bag, %s?",
+	"Must be hard kickin' all those doors down, I bet a key would help...",
+	"Only tools wouldn't buy our tools!"
+};
+const char* book_wares[] = {
+	"Large print available!",
+	"'ere now, this isn't a library; get lost, you freeloader!",
+	"Mental magnificence for the scholarly IN-clined!",
+	"Credit available for valued customers!",
+	"'Banned' section now open! (I.D. required)"
+};
+const char* candle_wares[] = {
+	"Hey, %s! Best candles in Minetown! You'll need 'em later, count on it!",
+	"You've got a long way down yet, %s.  Be sure you're ready.",
+	"Let us be the light in your darkness!",
+	"You know, I hear some of these old lamps might be... magic.",
+	"Be a shame if you missed anything because you didn't see it!"
+};
+
+void
+shk_holler(shkp)
+struct monst* shkp;
+{
+
+	/* Don't yell from too far away... */
+	if (distu(shkp->mx,shkp->my)<=13) {
+		switch (ESHK(shkp)->shoptype) {
+			default:
+			case ARMORSHOP:
+				verbalize(armor_wares[rn2(CRYNUMBER)],urace.noun);
+				break;
+			case SCROLLSHOP:
+				verbalize(scroll_wares[rn2(CRYNUMBER)],urace.noun);
+				break;
+			case POTIONSHOP:
+				verbalize(potion_wares[rn2(CRYNUMBER)],urace.noun);
+				break;
+			case WEAPONSHOP:
+				verbalize(weapon_wares[rn2(CRYNUMBER)],urace.noun);
+				break;
+			case FOODSHOP:
+				verbalize(food_wares[rn2(CRYNUMBER)],urace.noun);
+				break;
+			case RINGSHOP:
+				verbalize(ring_wares[rn2(CRYNUMBER)],urace.noun);
+				break;
+			case WANDSHOP:
+				verbalize(wand_wares[rn2(CRYNUMBER)],urace.noun);
+				break;
+			case TOOLSHOP:
+				verbalize(tool_wares[rn2(CRYNUMBER)],urace.noun);
+				break;
+			case BOOKSHOP:
+				verbalize(book_wares[rn2(CRYNUMBER)],urace.noun);
+				break;
+			case CANDLESHOP:
+				verbalize(candle_wares[rn2(CRYNUMBER)],urace.noun);
+				break;
+		}
+	}
+}
+
 #ifdef KOPS
 STATIC_OVL void
@@ -3858,4 +4190,5 @@
 		  otmp->otyp == OIL_LAMP ||		 /* 1 - 10 */
 		  otmp->otyp == BRASS_LANTERN ||
+		  otmp->otyp == BAG_OF_POO ||
 		 (otmp->otyp >= MAGIC_FLUTE &&
 		  otmp->otyp <= DRUM_OF_EARTHQUAKE) ||	 /* 5 - 9 */
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/src/shknam.c nethack/src/shknam.c
--- nh_orig/src/shknam.c	2003-12-07 18:39:13.000000000 -0500
+++ nethack/src/shknam.c	2009-11-23 14:58:57.184284194 -0500
@@ -15,5 +15,5 @@
 STATIC_DCL void FDECL(mkshobj_at, (const struct shclass *,int,int));
 STATIC_DCL void FDECL(nameshk, (struct monst *,const char * const *));
-STATIC_DCL int  FDECL(shkinit, (const struct shclass *,struct mkroom *));
+STATIC_DCL int  FDECL(shkinit, (const struct shclass *,struct mkroom *,int));
 
 static const char * const shkliquors[] = {
@@ -113,5 +113,5 @@
     "Yelpur", "Nosnehpets", "Stewe", "Renrut", "_Zlaw", "Nosalnef",
     "Rewuorb", "Rellenk", "Yad", "Cire Htims", "Y-crad", "Nenilukah",
-    "Corsh", "Aned",
+    "Corsh", "Aned", "Kere-Dyar",
 #ifdef OVERLAY
     "Erreip", "Nehpets", "Mron", "Snivek", "Lapu", "Kahztiy",
@@ -217,6 +217,6 @@
 	 */
 	{"lighting store", TOOL_CLASS, 0, D_SHOP,
-	    {{32, -WAX_CANDLE}, {50, -TALLOW_CANDLE},
-	     {5, -BRASS_LANTERN}, {10, -OIL_LAMP}, {3, -MAGIC_LAMP}}, shklight},
+	    {{33, -WAX_CANDLE}, {50, -TALLOW_CANDLE},
+	     {5, -BRASS_LANTERN}, {10, -OIL_LAMP}, {2, -MAGIC_LAMP}}, shklight},
 	{(char *)0, 0, 0, 0, {{0, 0}, {0, 0}, {0, 0}}, 0}
 };
@@ -333,10 +333,13 @@
 
 STATIC_OVL int
-shkinit(shp, sroom)	/* create a new shopkeeper in the given room */
+shkinit(shp, sroom, shp_indx)	/* create a new shopkeeper in the given room */
 const struct shclass	*shp;
 struct mkroom	*sroom;
+int shp_indx;
 {
 	register int sh, sx, sy;
+	int srace = 0;
 	struct monst *shk;
+	struct permonst* mdat;
 
 	/* place the shopkeeper in the given room */
@@ -391,4 +394,91 @@
 	if(!(shk = makemon(&mons[PM_SHOPKEEPER], sx, sy, NO_MM_FLAGS)))
 		return(-1);
+
+	/* change the shopkeeper to a particular race */
+	switch (shtypes[shp_indx].symb)
+	{
+		/* armors and weaponry are similar... */
+		case ARMOR_CLASS:
+		case WEAPON_CLASS:
+			switch (rn2(3))
+			{
+				default:
+				case 0:
+					srace = PM_SERGEANT + rn2(3);
+					break;
+				case 1:
+					srace = PM_STONE_GIANT + rn2(6);
+					break;
+				case 2:
+					srace = PM_KOP_SERGEANT + rn2(3);
+					break;
+			}
+			break;
+		case FOOD_CLASS:
+			srace = PM_OGRE + rn2(2);
+			break;
+		case RING_CLASS:
+			srace = PM_WOOD_NYMPH + rn2(3);
+			break;
+		/* wands and potions also similar... */
+		case WAND_CLASS:
+		case POTION_CLASS:
+			srace = PM_WOODLAND_ELF + rn2(4);
+			break;
+		case TOOL_CLASS:
+			/* Make sure we don't redo Izchak's here */
+			if (shtypes[shp_indx].prob != 0)
+			{
+				srace = PM_GNOME_LORD + rn2(2);
+			}
+			break;
+		/* and scrolls and books fall to spellcasters */
+		case SCROLL_CLASS:
+		case SPBOOK_CLASS:
+			srace = PM_LICH + rn2(4);
+			break;
+		default:
+			break;
+	}
+
+	/* if we picked a specific monster, use that... */
+	if (srace) {
+		/* on the odd chance that it hit one that was genoed, leave it a normal shk */
+		if (!(mvitals[srace].mvflags & G_GONE))
+		{
+			mdat = &mons[srace];
+			shk->mnum = srace;
+			set_mon_data(shk,mdat,1);
+		}
+	}
+	else
+	{
+		srace = rn2(5);
+		if (srace) { 
+			switch (srace) {
+				case 1:
+					mdat = &mons[PM_GREEN_ELF];
+					shk->mnum = PM_GREEN_ELF;
+					break;
+				case 2:
+					mdat = &mons[PM_DWARF];
+					shk->mnum = PM_DWARF;
+					break;
+				case 3:
+					mdat = &mons[PM_ORC];
+					shk->mnum = PM_ORC;
+					break;
+				case 4:
+					mdat = &mons[PM_GNOME];
+					shk->mnum = PM_GNOME;
+					break;
+				case 0:
+				default:
+					break;
+			}
+			set_mon_data(shk,mdat,1);
+		}
+	}
+
 	shk->isshk = shk->mpeaceful = 1;
 	set_malign(shk);
@@ -439,5 +529,5 @@
 
     /* first, try to place a shopkeeper in the room */
-    if ((sh = shkinit(shp, sroom)) < 0)
+    if ((sh = shkinit(shp, sroom, shp_indx)) < 0)
 	return;
 
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/src/sit.c nethack/src/sit.c
--- nh_orig/src/sit.c	2003-12-07 18:39:13.000000000 -0500
+++ nethack/src/sit.c	2009-11-23 12:06:17.278399363 -0500
@@ -61,5 +61,5 @@
 	}
 
-	if(OBJ_AT(u.ux, u.uy)) {
+	if(OBJ_AT(u.ux, u.uy) && (objects[level.objects[u.ux][u.uy]->otyp].oc_class != FURNITURE_CLASS)) {
 	    register struct obj *obj;
 
@@ -146,11 +146,10 @@
 	    }
 	    pline_The("lava burns you!");
-	    losehp(d((Fire_resistance ? 2 : 10), 10),
-		   "sitting on lava", KILLED_BY);
+	    losehp(resist_reduce(d(8,10),FIRE_RES) + d(2,10), "sitting on lava", KILLED_BY);
 
 	} else if (is_ice(u.ux, u.uy)) {
 
 	    You(sit_message, defsyms[S_ice].explanation);
-	    if (!Cold_resistance) pline_The("ice feels cold.");
+	    if (how_resistant(COLD_RES) < 100) pline_The("ice feels cold.");
 
 	} else if (typ == DRAWBRIDGE_DOWN) {
@@ -158,7 +157,7 @@
 	    You(sit_message, "drawbridge");
 
-	} else if(IS_THRONE(typ)) {
+	} else if(sobj_at(FUR_THRONE, u.ux,u.uy)) {
 
-	    You(sit_message, defsyms[S_throne].explanation);
+	    You(sit_message, OBJ_NAME(objects[FUR_THRONE]));
 	    if (rnd(6) > 4)  {
 		switch (rnd(13))  {
@@ -171,8 +170,6 @@
 			break;
 		    case 3:
-			pline("A%s electric shock shoots through your body!",
-			      (Shock_resistance) ? "n" : " massive");
-			losehp(Shock_resistance ? rnd(6) : rnd(30),
-			       "electric chair", KILLED_BY_AN);
+			pline("A%s electric shock shoots through your body!", (how_resistant(SHOCK_RES) > 50) ? "n" : " massive");
+			losehp(resist_reduce(rnd(24),SHOCK_RES)+rnd(6), "electric chair", KILLED_BY_AN);
 			exercise(A_CON, FALSE);
 			break;
@@ -180,8 +177,8 @@
 			You_feel("much, much better!");
 			if (Upolyd) {
-			    if (u.mh >= (u.mhmax - 5))  u.mhmax += 4;
+			    if (u.mh >= (u.mhmax - 5))  gainmaxhp(4);
 			    u.mh = u.mhmax;
 			}
-			if(u.uhp >= (u.uhpmax - 5))  u.uhpmax += 4;
+			if(u.uhp >= (u.uhpmax - 5)) gainmaxhp(4);
 			u.uhp = u.uhpmax;
 			make_blinded(0L,TRUE);
@@ -236,5 +233,5 @@
 			} else  {
 				Your("vision becomes clear.");
-				HSee_invisible |= FROMOUTSIDE;
+				incr_itimeout(&HSee_invisible, (long)rn1(100, 50));
 				newsym(u.ux, u.uy);
 			}
@@ -271,7 +268,9 @@
 	    }
 
-	    if (!rn2(3) && IS_THRONE(levl[u.ux][u.uy].typ)) {
+	    if (!rn2(3) && sobj_at(FUR_THRONE,u.ux,u.uy)) {
 		/* may have teleported */
-		levl[u.ux][u.uy].typ = ROOM;
+		struct obj *tmpobj = sobj_at(FUR_THRONE, u.ux, u.uy);
+		obj_extract_self(tmpobj);
+		dealloc_obj(tmpobj);
 		pline_The("throne vanishes in a puff of logic.");
 		newsym(u.ux,u.uy);
@@ -386,7 +385,8 @@
 attrcurse()			/* remove a random INTRINSIC ability */
 {
-	switch(rnd(11)) {
-	case 1 : if (HFire_resistance & INTRINSIC) {
-			HFire_resistance &= ~INTRINSIC;
+	switch(rnd(14)) {
+	case 1 : if (HFire_resistance) {
+			HFire_resistance = HFire_resistance & (TIMEOUT|FROMOUTSIDE|HAVEPARTIAL);
+			decr_resistance(&HFire_resistance,rnd(50)+50);
 			You_feel("warmer.");
 			break;
@@ -397,6 +397,7 @@
 			break;
 		}
-	case 3 : if (HPoison_resistance & INTRINSIC) {
-			HPoison_resistance &= ~INTRINSIC;
+	case 3 : if (HPoison_resistance) {
+			HPoison_resistance = HPoison_resistance & (TIMEOUT|FROMOUTSIDE|HAVEPARTIAL);
+			decr_resistance(&HPoison_resistance,rnd(50)+50);
 			You_feel("a little sick!");
 			break;
@@ -409,6 +410,7 @@
 			break;
 		}
-	case 5 : if (HCold_resistance & INTRINSIC) {
-			HCold_resistance &= ~INTRINSIC;
+	case 5 : if (HCold_resistance) {
+			HCold_resistance = HCold_resistance & (TIMEOUT|FROMOUTSIDE|HAVEPARTIAL);
+			decr_resistance(&HCold_resistance,rnd(50)+50);
 			You_feel("cooler.");
 			break;
@@ -427,5 +429,7 @@
 	case 8 : if (HFast & INTRINSIC) {
 			HFast &= ~INTRINSIC;
+			if (!Slow) {
 			You_feel("slower.");
+			}
 			break;
 		}
@@ -445,4 +449,22 @@
 			break;
 		}
+	case 12 : if (HSleep_resistance) {
+			HSleep_resistance = HSleep_resistance & (TIMEOUT|FROMOUTSIDE|HAVEPARTIAL);
+			decr_resistance(&HSleep_resistance,rnd(50)+50);
+			You_feel("a little tired.");
+			break;
+		}
+	case 13 : if (HDisint_resistance) {
+			HDisint_resistance = HDisint_resistance & (TIMEOUT|FROMOUTSIDE|HAVEPARTIAL);
+			decr_resistance(&HDisint_resistance,rnd(50)+50);
+			You_feel("less firm.");
+			break;
+		}
+	case 14 : if (HShock_resistance) {
+			HShock_resistance = HShock_resistance & (TIMEOUT|FROMOUTSIDE|HAVEPARTIAL);
+			decr_resistance(&HShock_resistance,rnd(50)+50);
+			You_feel("more conductive.");
+			break;
+		}
 	default: break;
 	}
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/src/sounds.c nethack/src/sounds.c
--- nh_orig/src/sounds.c	2003-12-07 18:39:13.000000000 -0500
+++ nethack/src/sounds.c	2009-11-22 07:19:36.760397941 -0500
@@ -45,4 +45,18 @@
     if (!flags.soundok || u.uswallow || Underwater) return;
 
+    if (level.sounds && !rn2(level.sounds->freq)) {
+	int idx = rn2(level.sounds->n_sounds);
+	char *buf;
+	struct lvl_sound_bite snd = level.sounds->sounds[idx];
+	buf = string_subst(snd.msg);
+	switch (snd.flags) {
+	default:
+	case LVLSND_HEARD:  You_hear(buf);  break;
+	case LVLSND_PLINED: pline(buf);     break;
+	case LVLSND_VERBAL: verbalize(buf); break;
+	case LVLSND_FELT:   You_feel(buf);  break;
+	}
+    }
+
     hallu = Hallucination ? 1 : 0;
 
@@ -326,5 +340,5 @@
     if (growl_verb) {
 	pline("%s %s!", Monnam(mtmp), vtense((char *)0, growl_verb));
-	if(flags.run) nomul(0);
+	if(flags.run) nomul(0, 0);
 	wake_nearto(mtmp->mx, mtmp->my, mtmp->data->mlevel * 18);
     }
@@ -367,5 +381,5 @@
     if (yelp_verb) {
 	pline("%s %s!", Monnam(mtmp), vtense((char *)0, yelp_verb));
-	if(flags.run) nomul(0);
+	if(flags.run) nomul(0, 0);
 	wake_nearto(mtmp->mx, mtmp->my, mtmp->data->mlevel * 12);
     }
@@ -399,5 +413,5 @@
     if (whimper_verb) {
 	pline("%s %s.", Monnam(mtmp), vtense((char *)0, whimper_verb));
-	if(flags.run) nomul(0);
+	if(flags.run) nomul(0, 0);
 	wake_nearto(mtmp->mx, mtmp->my, mtmp->data->mlevel * 6);
     }
@@ -628,5 +642,5 @@
 	    pline("%s rattles noisily.", Monnam(mtmp));
 	    You("freeze for a moment.");
-	    nomul(-2);
+	    nomul(-2, "scared by rattling");
 	    break;
 	case MS_LAUGH:
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/src/spell.c nethack/src/spell.c
--- nh_orig/src/spell.c	2003-12-07 18:39:13.000000000 -0500
+++ nethack/src/spell.c	2009-11-25 11:48:38.567567349 -0500
@@ -31,4 +31,5 @@
 STATIC_DCL int NDECL(throwspell);
 STATIC_DCL void NDECL(cast_protection);
+STATIC_DCL void NDECL(cast_reflection);
 STATIC_DCL void FDECL(spell_backfire, (int));
 STATIC_DCL const char *FDECL(spelltypemnemonic, (int));
@@ -62,8 +63,8 @@
  *  spelspec, spelsbon:
  *	Arc map masters (SPE_MAGIC_MAPPING)
- *	Bar fugue/berserker (SPE_HASTE_SELF)
+ *	Bar to frighten enemies (SPE_CAUSE_FEAR)
  *	Cav born to dig (SPE_DIG)
  *	Hea to heal (SPE_CURE_SICKNESS)
- *	Kni to turn back evil (SPE_TURN_UNDEAD)
+ *	Kni to lay on hands (SPE_EXTRA_HEALING)
  *	Mon to preserve their abilities (SPE_RESTORE_ABILITY)
  *	Pri to bless (SPE_REMOVE_CURSE)
@@ -72,5 +73,5 @@
  *	Sam to be At One (SPE_CLAIRVOYANCE)
  *	Tou to smile (SPE_CHARM_MONSTER)
- *	Val control the cold (SPE_CONE_OF_COLD)
+ *	Val to maintain their armor (SPE_REPAIR_ARMOR)
  *	Wiz all really, but SPE_MAGIC_MISSILE is their party trick
  *
@@ -153,7 +154,6 @@
 		/* temp disable in_use; death should not destroy the book */
 		bp->in_use = FALSE;
-		losestr(Poison_resistance ? rn1(2,1) : rn1(4,3));
-		losehp(rnd(Poison_resistance ? 6 : 10),
-		       "contact-poisoned spellbook", KILLED_BY_AN);
+		losestr(resist_reduce(rn1(4,3),POISON_RES)+rn1(2,1));
+		losehp(resist_reduce(rnd(6),POISON_RES)+rnd(6),"contact-poisoned spellbook", KILLED_BY_AN);
 		bp->in_use = TRUE;
 		break;
@@ -251,4 +251,10 @@
 	    mkinvokearea();
 	    u.uevent.invoked = 1;
+		 /* trigger the candles to start burning */
+		 for (otmp = invent; otmp; otmp = otmp->nobj) {
+			 if (otmp->otyp == CANDELABRUM_OF_INVOCATION) {
+				 begin_burn(otmp,TRUE);
+			 }
+		 }
 	    /* in case you haven't killed the Wizard yet, behave as if
 	       you just did */
@@ -326,5 +332,5 @@
 	    (void) confused_book(book);
 	    book = 0;			/* no longer studying */
-	    nomul(delay);		/* remaining delay is uninterrupted */
+	    nomul(delay, "reading a book");		/* remaining delay is uninterrupted */
 	    delay = 0;
 	    return(0);
@@ -433,5 +439,5 @@
 		/* Books are often wiser than their readers (Rus.) */
 		spellbook->in_use = TRUE;
-		if (!spellbook->blessed &&
+		if ((!spellbook->blessed || (spellbook->blessed && Role_if(PM_CAVEMAN))) &&
 		    spellbook->otyp != SPE_BOOK_OF_THE_DEAD) {
 		    if (spellbook->cursed) {
@@ -454,4 +460,10 @@
 			    }
 			}
+
+			/* Cavemen always have at least a 20% chance to fail */
+			if (Role_if(PM_CAVEMAN) && read_ability > 16) {
+				read_ability = 16;
+			}
+
 			/* its up to random luck now */
 			if (rnd(20) > read_ability) {
@@ -464,5 +476,5 @@
 		    boolean gone = cursed_book(spellbook);
 
-		    nomul(delay);			/* study time */
+		    nomul(delay, "reading a book");			/* study time */
 		    delay = 0;
 		    if(gone || !rn2(3)) {
@@ -479,5 +491,5 @@
 			spellbook->in_use = FALSE;
 		    }
-		    nomul(delay);
+		    nomul(delay, "reading a book");
 		    delay = 0;
 		    return(1);
@@ -681,4 +693,21 @@
 }
 
+STATIC_OVL void
+cast_reflection()
+{
+	if (HReflecting) {
+		if (!Blind)
+			pline("The shimmering globe around you becomes slightly brighter.");
+		else
+			You_feel("slightly more smooth.");
+	} else {
+		if (!Blind)
+			pline("A shimmering globe appears around you!");
+		else
+			You_feel("smooth.");
+	}
+	incr_itimeout(&HReflecting, rn1(10, HReflecting ? 20 : 100));
+}
+
 /* attempting to cast a forgotten spell will cause disorientation */
 STATIC_OVL void
@@ -719,4 +748,5 @@
 	boolean confused = (Confusion != 0);
 	struct obj *pseudo;
+	struct obj* otmp;
 	coord cc;
 
@@ -737,5 +767,5 @@
 	energy = (spellev(spell) * 5);    /* 5 <= energy <= 35 */
 
-	if (u.uhunger <= 10 && spellid(spell) != SPE_DETECT_FOOD) {
+	if (u.uhunger <= 10 && spellid(spell) != SPE_OBTAIN_FOOD) {
 		You("are too hungry to cast that spell.");
 		return(0);
@@ -759,5 +789,5 @@
 		return(0);
 	} else {
-		if (spellid(spell) != SPE_DETECT_FOOD) {
+		if (spellid(spell) != SPE_OBTAIN_FOOD) {
 			int hungr = energy * 2;
 
@@ -866,5 +896,5 @@
 	case SPE_DIG:
 	case SPE_TURN_UNDEAD:
-	case SPE_POLYMORPH:
+	case SPE_POLYMORPH_CREATURE:
 	case SPE_TELEPORT_AWAY:
 	case SPE_CANCELLATION:
@@ -879,6 +909,7 @@
 			if (atme) u.dx = u.dy = u.dz = 0;
 			else if (!getdir((char *)0)) {
-			    /* getdir cancelled, re-use previous direction */
+			    /* getdir cancelled, use random direction */
 			    pline_The("magical energy is released!");
+				 confdir();
 			}
 			if(!u.dx && !u.dy && !u.dz) {
@@ -894,7 +925,9 @@
 
 	/* these are all duplicates of scroll effects */
+	case SPE_OBTAIN_FOOD:
+		/* for this case only, unskilled is cursed scroll */
+		if (role_skill < P_BASIC) pseudo->cursed = 1;
 	case SPE_REMOVE_CURSE:
 	case SPE_CONFUSE_MONSTER:
-	case SPE_DETECT_FOOD:
 	case SPE_CAUSE_FEAR:
 		/* high skill yields effect equivalent to blessed scroll */
@@ -951,4 +984,35 @@
 			pline(nothing_happens);
 		break;
+	case SPE_DETECT_FOOT:
+		pline("Your nose tingles, and you smell feet!");
+		if (nolimbs(youmonst.data) || slithy(youmonst.data)) {
+			pline("You aren't sure where the feet might be, though.");
+		} else {
+			pline("You see here a %s on the end of your %s.",body_part(FOOT),body_part(LEG));
+		}
+		break;
+	case SPE_REFLECTION:
+		cast_reflection();
+		break;
+	case SPE_REPAIR_ARMOR:
+		/* removes one level of erosion (both types) for a random piece of armor */
+		otmp = some_armor(&youmonst);
+		if (otmp) {
+			if (greatest_erosion(otmp) > 0) {
+				if (!Blind) {
+					pline("Your %s glows faintly golden for a moment.",xname(otmp));
+				}
+				if (otmp->oeroded > 0) { otmp->oeroded--; }
+				if (otmp->oeroded2 > 0) { otmp->oeroded2--; }
+			} else {
+				if (!Blind) {
+					pline("Your %s glows briefly, but looks as new as ever.",xname(otmp));
+				}
+			}
+		} else {
+			/* the player can probably feel this, so no need for a !Blind check :) */
+			pline("Your embarrassing skin rash clears up slightly.");
+		}
+		break;
 	default:
 		impossible("Unknown spell %d attempted.", spell);
@@ -1115,4 +1179,33 @@
 }
 
+#ifdef DUMP_LOG
+void 
+dump_spells()
+{
+	int i;
+	char buf[BUFSZ];
+
+	if (spellid(0) == NO_SPELL) {
+	    dump("", "You didn't know any spells.");
+	    dump("", "");
+	    return;
+	}
+	dump("", "Spells known in the end");
+
+	Sprintf(buf, "%-20s   Level    %-12s Fail", "    Name", "Category");
+	dump("  ",buf);
+	for (i = 0; i < MAXSPELL && spellid(i) != NO_SPELL; i++) {
+		Sprintf(buf, "%c - %-20s  %2d%s   %-12s %3d%%",
+			spellet(i), spellname(i), spellev(i),
+			spellknow(i) ? " " : "*",
+			spelltypemnemonic(spell_skilltype(spellid(i))),
+			100 - percent_success(i));
+		dump("  ", buf);
+	}
+	dump("","");
+
+} /* dump_spells */
+#endif
+
 /* Integer square root function without using floating point. */
 STATIC_OVL int
@@ -1140,4 +1233,6 @@
 	int difficulty;
 	int skill;
+	int penalty;
+	boolean paladin_bonus;
 
 	/* Calculate intrinsic ability (splcaster) */
@@ -1147,15 +1242,17 @@
 	statused = ACURR(urole.spelstat);
 
-	if (uarm && is_metallic(uarm))
-	    splcaster += (uarmc && uarmc->otyp == ROBE) ?
-		urole.spelarmr/2 : urole.spelarmr;
+	/* Knights don't get metal armor penalty for clerical spells */
+	paladin_bonus = Role_if(PM_KNIGHT) && spell_skilltype(spellid(spell)) == P_CLERIC_SPELL;
+
+	if (uarm && is_metallic(uarm) && !paladin_bonus)
+	    splcaster += (uarmc && uarmc->otyp == ROBE) ? urole.spelarmr/2 : urole.spelarmr;
 	else if (uarmc && uarmc->otyp == ROBE)
-	    splcaster -= urole.spelarmr;
+	    splcaster -= urole.spelarmr/2;
 	if (uarms) splcaster += urole.spelshld;
 
-	if (uarmh && is_metallic(uarmh) && uarmh->otyp != HELM_OF_BRILLIANCE)
+	if (uarmh && is_metallic(uarmh) && uarmh->otyp != HELM_OF_BRILLIANCE && !paladin_bonus)
 		splcaster += uarmhbon;
-	if (uarmg && is_metallic(uarmg)) splcaster += uarmgbon;
-	if (uarmf && is_metallic(uarmf)) splcaster += uarmfbon;
+	if (uarmg && is_metallic(uarmg) && !paladin_bonus) splcaster += uarmgbon;
+	if (uarmf && is_metallic(uarmf) && !paladin_bonus) splcaster += uarmfbon;
 
 	if (spellid(spell) == urole.spelspec)
@@ -1230,4 +1327,49 @@
 	chance = chance * (20-splcaster) / 15 - splcaster;
 
+	/* Wielding one of the special staves will help enormously.
+	 * It won't fix the Wizard's body armor restriction, but for all other
+	 * classes it should be a significant help.
+	 */
+	if (uwep && uwep->otyp >= STAFF_OF_DIVINATION && uwep->otyp <= STAFF_OF_BATTLE)
+	{
+#define STAFFBONUS 50
+		if (spell_skilltype(spellid(spell)) == P_CLERIC_SPELL && uwep->otyp == STAFF_OF_HOLINESS)
+		{
+			chance += STAFFBONUS;
+		}
+		if (spell_skilltype(spellid(spell)) == P_HEALING_SPELL && uwep->otyp == STAFF_OF_HEALING)
+		{
+			chance += STAFFBONUS;
+		}
+		if (spell_skilltype(spellid(spell)) == P_DIVINATION_SPELL && uwep->otyp == STAFF_OF_DIVINATION)
+		{
+			chance += STAFFBONUS;
+		}
+		if (spell_skilltype(spellid(spell)) == P_MATTER_SPELL && uwep->otyp == STAFF_OF_MATTER)
+		{
+			chance += STAFFBONUS;
+		}
+		if (spell_skilltype(spellid(spell)) == P_ESCAPE_SPELL && uwep->otyp == STAFF_OF_ESCAPE)
+		{
+			chance += STAFFBONUS;
+		}
+		if (spell_skilltype(spellid(spell)) == P_ATTACK_SPELL && uwep->otyp == STAFF_OF_BATTLE)
+		{
+			chance += STAFFBONUS;
+		}
+#undef STAFFBONUS
+	}
+
+	/* Oh, wait... and there's one more.  Wizards are casters,
+	 * not combat monkeys.  Bolting body armor onto a Wizard is
+	 * very similar to bolting body armor onto a Monk.  It just isn't
+	 * going to work that well.  So there's a minimum chance of failure...
+	 * which of course increases with the spell difficulty. */
+
+	if (Role_if(PM_WIZARD) && uarm) { 
+		penalty = 90 - spellev(spell) * 10;
+		if (chance > penalty) { chance = penalty; }
+	}
+
 	/* Clamp to percentile */
 	if (chance > 100) chance = 100;
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/src/sp_lev.c nethack/src/sp_lev.c
--- nh_orig/src/sp_lev.c	2003-12-07 18:39:13.000000000 -0500
+++ nethack/src/sp_lev.c	2010-08-16 13:20:13.433713922 -0400
@@ -24,4 +24,7 @@
 #include "sp_lev.h"
 #include "rect.h"
+#include "epri.h"
+#include "eshk.h"
+
 
 extern void FDECL(mkmap, (lev_init *));
@@ -42,4 +45,5 @@
 STATIC_DCL void NDECL(fix_stair_rooms);
 STATIC_DCL void FDECL(create_corridor, (corridor *));
+STATIC_DCL void NDECL(count_features);
 
 STATIC_DCL boolean FDECL(create_subroom, (struct mkroom *, XCHAR_P, XCHAR_P,
@@ -55,6 +59,4 @@
 #define BOTTOM	5
 
-#define sq(x) ((x)*(x))
-
 #define XLIM	4
 #define YLIM	3
@@ -62,13 +64,11 @@
 #define Fread	(void)dlb_fread
 #define Fgetc	(schar)dlb_fgetc
-#define New(type)		(type *) alloc(sizeof(type))
-#define NewTab(type, size)	(type **) alloc(sizeof(type *) * (unsigned)size)
 #define Free(ptr)		if(ptr) free((genericptr_t) (ptr))
 
-static NEARDATA walk walklist[50];
+extern struct engr *head_engr;
+
 extern int min_rx, max_rx, min_ry, max_ry; /* from mkmap.c */
 
-static char Map[COLNO][ROWNO];
-static char robjects[10], rloc_x[10], rloc_y[10], rmonst[10];
+char SpLev_Map[COLNO][ROWNO];
 static aligntyp	ralign[3] = { AM_CHAOTIC, AM_NEUTRAL, AM_LAWFUL };
 static NEARDATA xchar xstart, ystart;
@@ -78,22 +78,629 @@
 STATIC_DCL int NDECL(rnddoor);
 STATIC_DCL int NDECL(rndtrap);
-STATIC_DCL void FDECL(get_location, (schar *,schar *,int));
-STATIC_DCL void FDECL(sp_lev_shuffle, (char *,char *,int));
+STATIC_DCL void FDECL(get_location, (schar *,schar *,int, struct mkroom *));
 STATIC_DCL void FDECL(light_region, (region *));
-STATIC_DCL void FDECL(load_common_data, (dlb *,int));
 STATIC_DCL void FDECL(load_one_monster, (dlb *,monster *));
 STATIC_DCL void FDECL(load_one_object, (dlb *,object *));
 STATIC_DCL void FDECL(load_one_engraving, (dlb *,engraving *));
-STATIC_DCL boolean FDECL(load_rooms, (dlb *));
 STATIC_DCL void FDECL(maze1xy, (coord *,int));
-STATIC_DCL boolean FDECL(load_maze, (dlb *));
+STATIC_DCL boolean FDECL(sp_level_loader, (dlb *, sp_lev *));
 STATIC_DCL void FDECL(create_door, (room_door *, struct mkroom *));
-STATIC_DCL void FDECL(free_rooms,(room **, int));
-STATIC_DCL void FDECL(build_room, (room *, room*));
+STATIC_DCL struct mkroom *FDECL(build_room, (room *, struct mkroom *));
 
 char *lev_message = 0;
 lev_region *lregions = 0;
 int num_lregions = 0;
-lev_init init_lev;
+
+struct obj *container_obj[MAX_CONTAINMENT];
+int container_idx = 0;
+
+struct monst *invent_carrying_monster = NULL;
+
+#define SPLEV_STACK_RESERVE 128
+
+void
+splev_stack_init(st)
+     struct splevstack *st;
+{
+    if (st) {
+	st->depth = 0;
+	st->depth_alloc = SPLEV_STACK_RESERVE;
+	st->stackdata = (struct opvar **)alloc(st->depth_alloc * sizeof(struct opvar *));
+    }
+}
+
+void
+splev_stack_done(st)
+     struct splevstack *st;
+{
+    if (st) {
+	int i;
+
+	if (st->stackdata && st->depth)
+	    for (i = 0; i < st->depth; i++) {
+		switch (st->stackdata[i]->spovartyp) {
+		default:
+		case SPOVAR_NULL:
+		case SPOVAR_COORD:
+		case SPOVAR_REGION:
+		case SPOVAR_MAPCHAR:
+		case SPOVAR_MONST:
+		case SPOVAR_OBJ:
+		case SPOVAR_INT:
+		    break;
+		case SPOVAR_VARIABLE:
+		case SPOVAR_STRING:
+		case SPOVAR_SEL:
+		    if (st->stackdata[i]->vardata.str) Free(st->stackdata[i]->vardata.str);
+		    st->stackdata[i]->vardata.str = NULL;
+		    break;
+		}
+		Free(st->stackdata[i]);
+		st->stackdata[i] = NULL;
+	    }
+
+	if (st->stackdata) free(st->stackdata);
+	st->stackdata = NULL;
+	st->depth = st->depth_alloc = 0;
+	Free(st);
+    }
+}
+
+void
+splev_stack_push(st, v)
+     struct splevstack *st;
+     struct opvar *v;
+{
+    if (!st) return;
+    if (!st->stackdata) panic("splev_stack_push: no stackdata allocated?");
+
+    if (st->depth >= st->depth_alloc) {
+	struct opvar **tmp = (struct opvar **)alloc((st->depth_alloc + SPLEV_STACK_RESERVE) * sizeof(struct opvar *));
+	(void)memcpy(tmp, st->stackdata, st->depth_alloc * sizeof(struct opvar *));
+	Free(st->stackdata);
+	st->stackdata = tmp;
+	st->depth_alloc += SPLEV_STACK_RESERVE;
+    }
+
+    st->stackdata[st->depth] = v;
+    st->depth++;
+}
+
+struct opvar *
+splev_stack_pop(st)
+     struct splevstack *st;
+{
+    struct opvar *ret = NULL;
+    if (!st) return ret;
+    if (!st->stackdata) panic("splev_stack_pop: no stackdata allocated?");
+
+    if (st->depth) {
+	st->depth--;
+	ret = st->stackdata[st->depth];
+	st->stackdata[st->depth] = NULL;
+	return ret;
+    } else impossible("splev_stack_pop: empty stack?");
+    return ret;
+}
+
+
+#define OV_typ(o) (o->spovartyp)
+#define OV_i(o) (o->vardata.l)
+#define OV_s(o) (o->vardata.str)
+
+#define OV_pop_i(x) (x = splev_stack_getdat(coder, SPOVAR_INT))
+#define OV_pop_c(x) (x = splev_stack_getdat(coder, SPOVAR_COORD))
+#define OV_pop_r(x) (x = splev_stack_getdat(coder, SPOVAR_REGION))
+#define OV_pop_s(x) (x = splev_stack_getdat(coder, SPOVAR_STRING))
+#define OV_pop(x)   (x = splev_stack_getdat_any(coder))
+#define OV_pop_typ(x,typ) (x = splev_stack_getdat(coder, typ))
+
+
+struct opvar *
+opvar_new_str(s)
+     char *s;
+{
+    struct opvar *tmpov = (struct opvar *)alloc(sizeof(struct opvar));
+    if (!tmpov) panic("could not alloc opvar struct");
+    tmpov->spovartyp = SPOVAR_STRING;
+    if (s) {
+	int len = strlen(s);
+	tmpov->vardata.str = (char *)alloc(len + 1);
+	(void)memcpy((genericptr_t)tmpov->vardata.str,
+		     (genericptr_t)s, len);
+	tmpov->vardata.str[len] = '\0';
+    } else
+	tmpov->vardata.str = NULL;
+    return tmpov;
+}
+
+struct opvar *
+opvar_new_int(i)
+     long i;
+{
+    struct opvar *tmpov = (struct opvar *)alloc(sizeof(struct opvar));
+    if (!tmpov) panic("could not alloc opvar struct");
+    tmpov->spovartyp = SPOVAR_INT;
+    tmpov->vardata.l = i;
+    return tmpov;
+}
+
+struct opvar *
+opvar_new_coord(x,y)
+     int x,y;
+{
+    struct opvar *tmpov = (struct opvar *)alloc(sizeof(struct opvar));
+    if (!tmpov) panic("could not alloc opvar struct");
+    tmpov->spovartyp = SPOVAR_COORD;
+    tmpov->vardata.l = SP_COORD_PACK(x,y);
+    return tmpov;
+}
+
+void
+opvar_free_x(ov)
+     struct opvar *ov;
+{
+    if (!ov) return;
+    switch (ov->spovartyp) {
+    case SPOVAR_COORD:
+    case SPOVAR_REGION:
+    case SPOVAR_MAPCHAR:
+    case SPOVAR_MONST:
+    case SPOVAR_OBJ:
+    case SPOVAR_INT:
+	break;
+    case SPOVAR_VARIABLE:
+    case SPOVAR_STRING:
+    case SPOVAR_SEL:
+	if (ov->vardata.str)
+	    Free(ov->vardata.str);
+	break;
+    default: impossible("Unknown opvar value type (%i)!", ov->spovartyp);
+    }
+    Free(ov);
+}
+
+#define opvar_free(ov) { if (ov) { opvar_free_x(ov); ov = NULL; } else impossible("opvar_free(), %s", __FUNCTION__); }
+
+struct opvar *
+opvar_clone(ov)
+     struct opvar *ov;
+{
+    struct opvar *tmpov = (struct opvar *)alloc(sizeof(struct opvar));
+    if (!tmpov) panic("could not alloc opvar struct");
+    switch (ov->spovartyp) {
+    case SPOVAR_COORD:
+    case SPOVAR_REGION:
+    case SPOVAR_MAPCHAR:
+    case SPOVAR_MONST:
+    case SPOVAR_OBJ:
+    case SPOVAR_INT:
+	{
+	    tmpov->spovartyp = ov->spovartyp;
+	    tmpov->vardata.l = ov->vardata.l;
+	}
+	break;
+    case SPOVAR_VARIABLE:
+    case SPOVAR_STRING:
+    case SPOVAR_SEL:
+	{
+	    int len = strlen(ov->vardata.str);
+	    tmpov->spovartyp = ov->spovartyp;
+	    tmpov->vardata.str = (char *)alloc(len+1);
+	    (void)memcpy((genericptr_t)tmpov->vardata.str,
+			 (genericptr_t)ov->vardata.str, len);
+	    tmpov->vardata.str[len] = '\0';
+	}
+	break;
+    default: impossible("Unknown push value type (%i)!", ov->spovartyp);
+    }
+    return tmpov;
+}
+
+
+struct opvar *
+opvar_var_conversion(coder, ov)
+     struct sp_coder *coder;
+     struct opvar *ov;
+{
+    struct splev_var *tmp;
+    struct opvar *tmpov;
+    struct opvar *array_idx = NULL;
+    if (!coder || !ov) return NULL;
+    if (ov->spovartyp != SPOVAR_VARIABLE) return ov;
+    tmp = coder->frame->variables;
+    while (tmp) {
+	if (!strcmp(tmp->name, OV_s(ov))) {
+	    if ((tmp->svtyp & SPOVAR_ARRAY)) {
+		array_idx = opvar_var_conversion(coder, splev_stack_pop(coder->stack));
+		if (!array_idx || OV_typ(array_idx) != SPOVAR_INT)
+		    panic("array idx not an int");
+		if (tmp->array_len < 1) panic("array len < 1");
+		OV_i(array_idx) = (OV_i(array_idx) % tmp->array_len);
+		tmpov = opvar_clone(tmp->data.arrayvalues[OV_i(array_idx)]);
+		return tmpov;
+	    } else {
+		tmpov = opvar_clone(tmp->data.value);
+		return tmpov;
+	    }
+	}
+	tmp = tmp->next;
+    }
+    return NULL;
+}
+
+struct splev_var *
+opvar_var_defined(coder, name)
+     struct sp_coder *coder;
+     char *name;
+{
+    struct splev_var *tmp;
+    if (!coder) return NULL;
+    tmp = coder->frame->variables;
+    while (tmp) {
+	if (!strcmp(tmp->name, name)) return tmp;
+	tmp = tmp->next;
+    }
+    return NULL;
+}
+
+struct opvar *
+splev_stack_getdat(coder, typ)
+     struct sp_coder *coder;
+     xchar typ;
+{
+    if (coder && coder->stack) {
+	struct opvar *tmp = splev_stack_pop(coder->stack);
+	if (tmp->spovartyp == SPOVAR_VARIABLE)
+	    tmp = opvar_var_conversion(coder, tmp);
+	if (tmp->spovartyp == typ)
+	    return tmp;
+    }
+    return NULL;
+}
+
+struct opvar *
+splev_stack_getdat_any(coder)
+     struct sp_coder *coder;
+{
+    if (coder && coder->stack) {
+	struct opvar *tmp = splev_stack_pop(coder->stack);
+	if (tmp->spovartyp == SPOVAR_VARIABLE)
+	    tmp = opvar_var_conversion(coder, tmp);
+	return tmp;
+    }
+    return NULL;
+}
+
+
+
+void
+variable_list_del(varlist)
+     struct splev_var *varlist;
+{
+    struct splev_var *tmp = varlist;
+    if (!tmp) return;
+    while (tmp) {
+	free(tmp->name);
+	if ((tmp->svtyp & SPOVAR_ARRAY)) {
+	    long idx = tmp->array_len;
+	    while (idx-- > 0) {
+		opvar_free(tmp->data.arrayvalues[idx]);
+	    };
+	    free(tmp->data.arrayvalues);
+	} else {
+	    opvar_free(tmp->data.value);
+	}
+	tmp = varlist->next;
+	free(varlist);
+	varlist = tmp;
+    }
+}
+
+
+void
+lvlfill_maze_grid(x1,y1,x2,y2,filling)
+     int x1,y1,x2,y2;
+     schar filling;
+{
+    int x,y;
+
+    for (x = x1; x <= x2; x++)
+	for (y = y1; y <= y2; y++) {
+#ifndef WALLIFIED_MAZE
+	    levl[x][y].typ = STONE;
+#else
+            levl[x][y].typ =
+		(y < 2 || ((x % 2) && (y % 2))) ? STONE : filling;
+#endif
+	}
+}
+
+void
+lvlfill_solid(filling,lit)
+     schar filling;
+     schar lit;
+{
+    int x,y;
+    for (x = 2; x <= x_maze_max; x++)
+	for (y = 0; y <= y_maze_max; y++) {
+	    SET_TYPLIT(x,y,filling,lit);
+	}
+}
+
+void flip_drawbridge_horizontal(lev)
+struct rm *lev;
+{
+        if (IS_DRAWBRIDGE(lev->typ)) {
+                if ((lev->drawbridgemask & DB_DIR) == DB_WEST) {
+                        lev->drawbridgemask &= ~DB_WEST;
+                        lev->drawbridgemask |=  DB_EAST;
+                } else if ((lev->drawbridgemask & DB_DIR) == DB_EAST) {
+                        lev->drawbridgemask &= ~DB_EAST;
+                        lev->drawbridgemask |=  DB_WEST;
+                }
+        }
+}
+
+void flip_drawbridge_vertical(lev)
+struct rm *lev;
+{
+        if (IS_DRAWBRIDGE(lev->typ)) {
+                if ((lev->drawbridgemask & DB_DIR) == DB_NORTH) {
+                        lev->drawbridgemask &= ~DB_NORTH;
+                        lev->drawbridgemask |=  DB_SOUTH;
+                } else if ((lev->drawbridgemask & DB_DIR) == DB_SOUTH) {
+                        lev->drawbridgemask &= ~DB_SOUTH;
+                        lev->drawbridgemask |=  DB_NORTH;
+                }
+        }
+}
+
+void
+flip_level(int flp)
+{
+    int x2 = COLNO-1;
+    int y2 = ROWNO-1;
+
+    int x, y, i;
+
+    struct rm trm;
+
+    struct trap *ttmp;
+    struct obj *otmp;
+    struct monst *mtmp;
+    struct engr *etmp;
+    struct mkroom *sroom;
+
+    /* stairs and ladders */
+    if (flp & 1) {
+	yupstair = y2 - yupstair;
+	ydnstair = y2 - ydnstair;
+	yupladder = y2 - yupladder;
+	ydnladder = y2 - ydnladder;
+    }
+    if (flp & 2) {
+	xupstair = x2 - xupstair;
+	xdnstair = x2 - xdnstair;
+	xupladder = x2 - xupladder;
+	xdnladder = x2 - xdnladder;
+    }
+
+    /* traps */
+    for (ttmp = ftrap; ttmp; ttmp = ttmp->ntrap) {
+	if (flp & 1) {
+	    ttmp->ty = y2 - ttmp->ty;
+	    if (ttmp->ttyp == ROLLING_BOULDER_TRAP) {
+		ttmp->launch.y = y2 - ttmp->launch.y;
+		ttmp->launch2.y = y2 - ttmp->launch2.y;
+	    } else if (ttmp->ttyp == MAGIC_BEAM_TRAP) {
+		ttmp->launch.y = y2 - ttmp->launch.y;
+	    }
+	}
+	if (flp & 2) {
+	    ttmp->tx = x2 - ttmp->tx;
+	    if (ttmp->ttyp == ROLLING_BOULDER_TRAP) {
+		ttmp->launch.x = x2 - ttmp->launch.x;
+		ttmp->launch2.x = x2 - ttmp->launch2.x;
+	    } else if (ttmp->ttyp == MAGIC_BEAM_TRAP) {
+		ttmp->launch.x = x2 - ttmp->launch.x;
+	    }
+	}
+    }
+
+    /* objects */
+    for (otmp = fobj; otmp; otmp = otmp->nobj) {
+	if (flp & 1)
+	    otmp->oy = y2 - otmp->oy;
+	if (flp & 2)
+	    otmp->ox = x2 - otmp->ox;
+    }
+
+    /* buried objects */
+    for (otmp = level.buriedobjlist; otmp; otmp = otmp->nobj) {
+	if (flp & 1)
+	    otmp->oy = y2 - otmp->oy;
+	if (flp & 2)
+	    otmp->ox = x2 - otmp->ox;
+    }
+
+    /* monsters */
+    for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
+	if (flp & 1) {
+	    mtmp->my = y2 - mtmp->my;
+	    if (mtmp->ispriest)
+		EPRI(mtmp)->shrpos.y = y2 - EPRI(mtmp)->shrpos.y;
+	    else if (mtmp->isshk) {
+		ESHK(mtmp)->shk.y = y2 - ESHK(mtmp)->shk.y;
+		ESHK(mtmp)->shd.y = y2 - ESHK(mtmp)->shd.y;
+	    }
+	}
+	if (flp & 2) {
+	    mtmp->mx = x2 - mtmp->mx;
+	    if (mtmp->ispriest)
+		EPRI(mtmp)->shrpos.x = x2 - EPRI(mtmp)->shrpos.x;
+	    else if (mtmp->isshk) {
+		ESHK(mtmp)->shk.x = x2 - ESHK(mtmp)->shk.x;
+		ESHK(mtmp)->shd.x = x2 - ESHK(mtmp)->shd.x;
+	    }
+	}
+    }
+
+    /* engravings */
+    for (etmp = head_engr; etmp; etmp = etmp->nxt_engr) {
+	if (flp & 1)
+	    etmp->engr_y = y2 - etmp->engr_y;
+	if (flp & 2)
+	    etmp->engr_x = x2 - etmp->engr_x;
+    }
+
+    /* regions */
+    for (i = 0; i < num_lregions; i++) {
+	if (flp & 1) {
+	    lregions[i].inarea.y1 = y2 - lregions[i].inarea.y1;
+	    lregions[i].inarea.y2 = y2 - lregions[i].inarea.y2;
+	    if (lregions[i].inarea.y1 > lregions[i].inarea.y2) {
+		int tmp = lregions[i].inarea.y1;
+		lregions[i].inarea.y1 = lregions[i].inarea.y2;
+		lregions[i].inarea.y2 = tmp;
+	    }
+
+	    lregions[i].delarea.y1 = y2 - lregions[i].delarea.y1;
+	    lregions[i].delarea.y2 = y2 - lregions[i].delarea.y2;
+	    if (lregions[i].delarea.y1 > lregions[i].delarea.y2) {
+		int tmp = lregions[i].delarea.y1;
+		lregions[i].delarea.y1 = lregions[i].delarea.y2;
+		lregions[i].delarea.y2 = tmp;
+	    }
+	}
+	if (flp & 2) {
+	    lregions[i].inarea.x1 = x2 - lregions[i].inarea.x1;
+	    lregions[i].inarea.x2 = x2 - lregions[i].inarea.x2;
+	    if (lregions[i].inarea.x1 > lregions[i].inarea.x2) {
+		int tmp = lregions[i].inarea.x1;
+		lregions[i].inarea.x1 = lregions[i].inarea.x2;
+		lregions[i].inarea.x2 = tmp;
+	    }
+
+	    lregions[i].delarea.x1 = x2 - lregions[i].delarea.x1;
+	    lregions[i].delarea.x2 = x2 - lregions[i].delarea.x2;
+	    if (lregions[i].delarea.x1 > lregions[i].delarea.x2) {
+		int tmp = lregions[i].delarea.x1;
+		lregions[i].delarea.x1 = lregions[i].delarea.x2;
+		lregions[i].delarea.x2 = tmp;
+	    }
+	}
+    }
+
+    /* rooms */
+    for(sroom = &rooms[0]; ; sroom++) {
+	if (sroom->hx < 0) break;
+
+	if (flp & 1) {
+	    sroom->ly = y2 - sroom->ly;
+	    sroom->hy = y2 - sroom->hy;
+	    if (sroom->ly > sroom->hy) {
+		int tmp = sroom->ly;
+		sroom->ly = sroom->hy;
+		sroom->hy = tmp;
+	    }
+	}
+	if (flp & 2) {
+	    sroom->lx = x2 - sroom->lx;
+	    sroom->hx = x2 - sroom->hx;
+	    if (sroom->lx > sroom->hx) {
+		int tmp = sroom->lx;
+		sroom->lx = sroom->hx;
+		sroom->hx = tmp;
+	    }
+	}
+
+	if (sroom->nsubrooms)
+	    for (i = 0; i < sroom->nsubrooms; i++) {
+		struct mkroom *rroom = sroom->sbrooms[i];
+		if (flp & 1) {
+		    rroom->ly = y2 - rroom->ly;
+		    rroom->hy = y2 - rroom->hy;
+		    if (rroom->ly > rroom->hy) {
+			int tmp = rroom->ly;
+			rroom->ly = rroom->hy;
+			rroom->hy = tmp;
+		    }
+		}
+		if (flp & 2) {
+		    rroom->lx = x2 - rroom->lx;
+		    rroom->hx = x2 - rroom->hx;
+		    if (rroom->lx > rroom->hx) {
+			int tmp = rroom->lx;
+			rroom->lx = rroom->hx;
+			rroom->hx = tmp;
+		    }
+		}
+	    }
+    }
+
+    /* doors */
+    for (i = 0; i < doorindex; i++) {
+	if (flp & 1)
+	    doors[i].y = y2 - doors[i].y;
+	if (flp & 2)
+	    doors[i].x = x2 - doors[i].x;
+    }
+
+    /* the map */
+    if (flp & 1) {
+	for (x = 0; x <= x2; x++)
+	    for (y = 0; y <= (y2 / 2); y++) {
+
+		flip_drawbridge_vertical(&levl[x][y]);
+		flip_drawbridge_vertical(&levl[x][y2-y]);
+
+		trm = levl[x][y];
+		levl[x][y] = levl[x][y2-y];
+		levl[x][y2-y] = trm;
+
+		otmp = level.objects[x][y];
+		level.objects[x][y] = level.objects[x][y2-y];
+		level.objects[x][y2-y] = otmp;
+
+		mtmp = level.monsters[x][y];
+		level.monsters[x][y] = level.monsters[x][y2-y];
+		level.monsters[x][y2-y] = mtmp;
+	    }
+    }
+    if (flp & 2) {
+	for (x = 0; x <= (x2 / 2); x++)
+	    for (y = 0; y <= y2; y++) {
+
+		flip_drawbridge_horizontal(&levl[x][y]);
+		flip_drawbridge_horizontal(&levl[x2-x][y]);
+
+		trm = levl[x][y];
+		levl[x][y] = levl[x2-x][y];
+		levl[x2-x][y] = trm;
+
+		otmp = level.objects[x][y];
+		level.objects[x][y] = level.objects[x2-x][y];
+		level.objects[x2-x][y] = otmp;
+
+		mtmp = level.monsters[x][y];
+		level.monsters[x][y] = level.monsters[x2-x][y];
+		level.monsters[x2-x][y] = mtmp;
+	    }
+    }
+
+    wall_extends(1, 0, COLNO-1, ROWNO-1);
+}
+
+void
+flip_level_rnd(int flp)
+{
+    int c = 0;
+    if ((flp & 1) && rn2(2)) c |= 1;
+    if ((flp & 2) && rn2(2)) c |= 2;
+    flip_level(c);
+}
+
+
 
 /*
@@ -114,4 +721,70 @@
 }
 
+STATIC_OVL void
+shuffle_alignments()
+{
+    int	i;
+    aligntyp atmp;
+    /* shuffle 3 alignments */
+    i = rn2(3);   atmp=ralign[2]; ralign[2]=ralign[i]; ralign[i]=atmp;
+    if (rn2(2)) { atmp=ralign[1]; ralign[1]=ralign[0]; ralign[0]=atmp; }
+}
+
+/*
+ * Count the different features (sinks, fountains) in the level.
+ */
+STATIC_OVL void
+count_features()
+{
+    xchar x,y;
+    level.flags.nfountains = level.flags.nsinks = 0;
+    for (y = 0; y < ROWNO; y++)
+	for (x = 0; x < COLNO; x++) {
+	    int typ = levl[x][y].typ;
+	    if (typ == FOUNTAIN)
+		level.flags.nfountains++;
+	    else if (typ == SINK)
+		level.flags.nsinks++;
+	}
+}
+
+void
+remove_boundary_syms()
+{
+    /*
+     * If any CROSSWALLs are found, must change to ROOM after REGION's
+     * are laid out.  CROSSWALLS are used to specify "invisible"
+     * boundaries where DOOR syms look bad or aren't desirable.
+     */
+    xchar x,y;
+    boolean has_bounds = FALSE;
+    for (x = 0; x < COLNO-1; x++)
+	for (y = 0; y < ROWNO-1; y++)
+	    if ((levl[x][y].typ == CROSSWALL)) {
+		has_bounds = TRUE;
+		break;
+	    }
+    if (has_bounds) {
+	for(x = 0; x < x_maze_max; x++)
+	    for(y = 0; y < y_maze_max; y++)
+		if ((levl[x][y].typ == CROSSWALL) && !SpLev_Map[x][y])
+		    levl[x][y].typ = ROOM;
+    }
+}
+
+void
+fill_rooms()
+{
+    int tmpi;
+    for (tmpi = 0; tmpi < nroom; tmpi++) {
+	int m;
+	if (rooms[tmpi].needfill)
+	    fill_room(&rooms[tmpi], (rooms[tmpi].needfill == 2));
+	for (m = 0; m < rooms[tmpi].nsubrooms; m++)
+	    if (rooms[tmpi].sbrooms[m]->needfill)
+		fill_room(rooms[tmpi].sbrooms[m], FALSE);
+    }
+}
+
 /*
  * Choose randomly the state (nodoor, open, closed or locked) for a door
@@ -155,9 +828,5 @@
  * Coordinates in special level files are handled specially:
  *
- *	if x or y is -11, we generate a random coordinate.
- *	if x or y is between -1 and -10, we read one from the corresponding
- *	register (x0, x1, ... x9).
- *	if x or y is nonnegative, we convert it from relative to the local map
- *	to global coordinates.
+ *	if x or y is < 0, we generate a random coordinate.
  *	The "humidity" flag is used to insure that engravings aren't
  *	created underwater, or eels on dry land.
@@ -169,20 +838,38 @@
 
 STATIC_OVL void
-get_location(x, y, humidity)
+get_location(x, y, humidity, croom)
 schar *x, *y;
 int humidity;
+struct mkroom *croom;
 {
 	int cpt = 0;
+        int mx, my, sx, sy;
+
+        if (croom) {
+	    mx = croom->lx;
+	    my = croom->ly;
+	    sx = croom->hx - mx + 1;
+	    sy = croom->hy - my + 1;
+	} else {
+	    mx = xstart;
+	    my = ystart;
+	    sx = xsize;
+	    sy = ysize;
+	}
 
 	if (*x >= 0) {			/* normal locations */
-		*x += xstart;
-		*y += ystart;
-	} else if (*x > -11) {		/* special locations */
-		*y = ystart + rloc_y[ - *y - 1];
-		*x = xstart + rloc_x[ - *x - 1];
+		*x += mx;
+		*y += my;
 	} else {			/* random location */
 	    do {
-		*x = xstart + rn2((int)xsize);
-		*y = ystart + rn2((int)ysize);
+		if (croom) { /* handle irregular areas */
+		    coord tmpc;
+		    somexy(croom, &tmpc);
+		    *x = tmpc.x;
+		    *y = tmpc.y;
+		} else {
+		    *x = mx + rn2((int)sx);
+		    *y = my + rn2((int)sy);
+		}
 		if (is_ok_location(*x,*y,humidity)) break;
 	    } while (++cpt < 100);
@@ -190,11 +877,11 @@
 		register int xx, yy;
 		/* last try */
-		for (xx = 0; xx < xsize; xx++)
-		    for (yy = 0; yy < ysize; yy++) {
-			*x = xstart + xx;
-			*y = ystart + yy;
+		for (xx = 0; xx < sx; xx++)
+		    for (yy = 0; yy < sy; yy++) {
+			*x = mx + xx;
+			*y = my + yy;
 			if (is_ok_location(*x,*y,humidity)) goto found_it;
 		    }
-		panic("get_location:  can't find a place!");
+		impossible("get_location:  can't find a place!");
 	    }
 	}
@@ -230,29 +917,4 @@
 
 /*
- * Shuffle the registers for locations, objects or monsters
- */
-
-STATIC_OVL void
-sp_lev_shuffle(list1, list2, n)
-char list1[], list2[];
-int n;
-{
-	register int i, j;
-	register char k;
-
-	for (i = n - 1; i > 0; i--) {
-		if ((j = rn2(i + 1)) == i) continue;
-		k = list1[j];
-		list1[j] = list1[i];
-		list1[i] = k;
-		if (list2) {
-			k = list2[j];
-			list2[j] = list2[i];
-			list2[i] = k;
-		}
-	}
-}
-
-/*
  * Get a relative position inside a room.
  * negative values for x or y means RANDOM!
@@ -295,4 +957,8 @@
 	register int trycnt = 0;
 
+        try_x = *x,  try_y = *y;
+
+	get_location(&try_x, &try_y, DRY, croom);
+        if (levl[try_x][try_y].typ != ROOM) {
 	do {
 	    try_x = *x,  try_y = *y;
@@ -302,4 +968,5 @@
 	if (trycnt > 100)
 	    panic("get_free_room_loc:  can't find a place!");
+	}
 	*x = try_x,  *y = try_y;
 }
@@ -584,6 +1251,6 @@
 struct mkroom *broom;
 {
-	int	x, y;
-	int	trycnt = 0;
+	int	x = 0, y = 0;
+	int	trycnt = 0, walltry = 0, wtry = 0;
 
 	if (dd->secret == -1)
@@ -620,34 +1287,41 @@
 
 		dpos = dd->pos;
-		if (dpos == -1)	/* The position is RANDOM */
-		    dpos = rn2((dwall == W_WEST || dwall == W_EAST) ?
-			    (broom->hy - broom->ly) : (broom->hx - broom->lx));
 
 		/* Convert wall and pos into an absolute coordinate! */
-
-		switch (dwall) {
-		      case W_NORTH:
+		wtry = rn2(4);
+		switch (wtry) {
+		      case 0:
+			if (!(dwall & W_NORTH)) goto redoloop;
 			y = broom->ly - 1;
-			x = broom->lx + dpos;
-			break;
-		      case W_SOUTH:
+			x = broom->lx + ((dpos == -1) ? rn2(1+(broom->hx - broom->lx)) : dpos);
+			if (IS_ROCK(levl[x][y-1].typ)) goto redoloop;
+			goto outdirloop;
+		      case 1:
+			if (!(dwall & W_SOUTH)) goto redoloop;
 			y = broom->hy + 1;
-			x = broom->lx + dpos;
-			break;
-		      case W_WEST:
+			x = broom->lx + ((dpos == -1) ? rn2(1+(broom->hx - broom->lx)) : dpos);
+			if (IS_ROCK(levl[x][y+1].typ)) goto redoloop;
+			goto outdirloop;
+		      case 2:
+			if (!(dwall & W_WEST)) goto redoloop;
 			x = broom->lx - 1;
-			y = broom->ly + dpos;
-			break;
-		      case W_EAST:
+			y = broom->ly + ((dpos == -1) ? rn2(1+(broom->hy - broom->ly)) : dpos);
+			if (IS_ROCK(levl[x-1][y].typ)) goto redoloop;
+			goto outdirloop;
+		      case 3:
+			if (!(dwall & W_EAST)) goto redoloop;
 			x = broom->hx + 1;
-			y = broom->ly + dpos;
-			break;
+			y = broom->ly + ((dpos == -1) ? rn2(1+(broom->hy - broom->ly)) : dpos);
+			if (IS_ROCK(levl[x+1][y].typ)) goto redoloop;
+			goto outdirloop;
 		      default:
 			x = y = 0;
 			panic("create_door: No wall for door!");
-			break;
+			goto outdirloop;
 		}
+outdirloop:
 		if (okdoor(x,y))
 		    break;
+redoloop: ;
 	} while (++trycnt <= 100);
 	if (trycnt > 100) {
@@ -713,11 +1387,17 @@
     coord	tm;
 
-    if (rn2(100) < t->chance) {
 	x = t->x;
 	y = t->y;
 	if (croom)
 	    get_free_room_loc(&x, &y, croom);
-	else
-	    get_location(&x, &y, DRY);
+	else {
+	    int trycnt = 0;
+	    do {
+		x = t->x;
+		y = t->y;
+		get_location(&x, &y, DRY, croom);
+	    } while ((levl[x][y].typ == STAIRS || levl[x][y].typ == LADDER) && ++trycnt <= 100);
+	    if (trycnt > 100) return;
+	}
 
 	tm.x = x;
@@ -726,6 +1406,83 @@
 	mktrap(t->type, 1, (struct mkroom*) 0, &tm);
     }
+
+STATIC_OVL void
+spill_terrain(sp, croom)
+spill* sp;
+struct mkroom* croom;
+{
+	schar x,y,nx,ny,qx,qy;
+	int j,k,lastdir,guard;
+	boolean found = FALSE;
+
+	if (sp->typ >= MAX_TYPE) return;
+
+	/* This code assumes that you're going to spill one particular
+	 * type of terrain from a wall into somewhere.
+	 *
+	 * If we were given a specific coordinate, though, it doesn't have
+	 * to start from a wall... */
+	if (sp->x < 0 || sp->y < 0) {
+		for (j = 0;j < 500;j++) {
+			x = sp->x;
+			y = sp->y;
+			get_location(&x, &y, DRY|WET, croom);
+			nx = x; ny = y;
+			switch (sp->direction) {
+				case W_NORTH: ny++; break;	  /* backwards to make sure we're against a wall */
+				case W_SOUTH: ny--; break;
+				case W_WEST: nx++; break;
+				case W_EAST: nx--; break;
+				default: return; break;
+			}
+			if (!isok(nx,ny)) { continue; }
+			if (IS_WALL(levl[nx][ny].typ)) {	 /* mark it as broken through */
+				SET_TYPLIT(nx,ny,sp->typ, sp->lit);
+				found = TRUE;
+				break;
+			}
+		}
+	} else {
+		found = TRUE;
+		x = sp->x;
+		y = sp->y;
+		get_location(&x, &y, DRY|WET, croom); /* support random registers too */
 }
 
+	if (!found) { return; }
+
+	/* gloop! */
+	lastdir = -1; nx = x; ny = y;
+	for (j = sp->count;j > 0;j--) {
+		guard = 0;
+		SET_TYPLIT(nx,ny, sp->typ, sp->lit);
+		do {
+			guard++;
+			do {
+				k = rn2(5);
+				qx = nx;qy = ny;
+				if (k > 3) { k = sp->direction; }
+				else { k = 1 << k; }
+				switch(k) {
+					case W_NORTH: qy--; break;
+					case W_SOUTH: qy++; break;
+					case W_WEST: qx--; break;
+					case W_EAST: qx++; break;
+				}
+			} while (!isok(qx,qy));
+		} while ((k == lastdir || levl[qx][qy].typ == sp->typ) && guard < 200);
+		/* tend to not make rivers, but pools; and don't redo stuff of the same type! */
+
+		switch(k) {
+			case W_NORTH: ny--; break;
+			case W_SOUTH: ny++; break;
+			case W_WEST: nx--; break;
+			case W_EAST: nx++; break;
+		}
+		lastdir = k;
+	}
+}
+
+
 /*
  * Create a monster in a room.
@@ -757,10 +1514,7 @@
     unsigned g_mvflags;
 
-    if (rn2(100) < m->chance) {
 
 	if (m->class >= 0)
 	    class = (char) def_char_to_monclass((char)m->class);
-	else if (m->class > -11)
-	    class = (char) def_char_to_monclass(rmonst[- m->class - 1]);
 	else
 	    class = 0;
@@ -773,5 +1527,5 @@
 		(m->align == AM_SPLEV_NONCO) ?
 			Align2amask(noncoalignment(u.ualignbase[A_ORIGINAL])) :
-		(m->align <= -11) ? induced_align(80) :
+		(m->align <= -(MAX_REGISTERS+1)) ? induced_align(80) :
 		(m->align < 0 ? ralign[-m->align-1] : m->align);
 
@@ -782,5 +1536,5 @@
 	    g_mvflags = (unsigned) mvitals[monsndx(pm)].mvflags;
 	    if ((pm->geno & G_UNIQ) && (g_mvflags & G_EXTINCT))
-		goto m_done;
+		return;
 	    else if (g_mvflags & G_GONE)	/* genocided or extinct */
 		pm = (struct permonst *) 0;	/* make random monster */
@@ -796,19 +1550,15 @@
 	x = m->x;
 	y = m->y;
-	if (croom)
-	    get_room_loc(&x, &y, croom);
-	else {
 	    if (!pm || !is_swimmer(pm))
-		get_location(&x, &y, DRY);
+		get_location(&x, &y, DRY, croom);
 	    else if (pm->mlet == S_EEL)
-		get_location(&x, &y, WET);
+		get_location(&x, &y, WET, croom);
 	    else
-		get_location(&x, &y, DRY|WET);
-	}
+		get_location(&x, &y, DRY|WET, croom);
 	/* try to find a close place if someone else is already there */
 	if (MON_AT(x,y) && enexto(&cc, x, y, pm))
 	    x = cc.x,  y = cc.y;
 
-	if(m->align != -12)
+	if(m->align != -(MAX_REGISTERS+2))
 	    mtmp = mk_roamer(pm, Amask2align(amask), x, y, m->peaceful);
 	else if(PM_ARCHEOLOGIST <= m->id && m->id <= PM_WIZARD)
@@ -893,10 +1643,34 @@
 #endif
 	    }
+
+	    if (m->seentraps) mtmp->mtrapseen = m->seentraps;
+	    if (m->female) mtmp->female = 1;
+	    if (m->cancelled) mtmp->mcan = 1;
+	    if (m->revived) mtmp->mrevived = 1;
+	    if (m->avenge) mtmp->mavenge = 1;
+	    if (m->stunned) mtmp->mstun = 1;
+	    if (m->confused) mtmp->mconf = 1;
+	    if (m->invis) {
+		mtmp->minvis = mtmp->perminvis = 1;
+	    }
+	    if (m->blinded) {
+		mtmp->mcansee = 0;
+		mtmp->mblinded = (m->blinded % 127);
+	    }
+	    if (m->paralyzed) {
+		mtmp->mcanmove = 0;
+		mtmp->mfrozen = (m->paralyzed % 127);
+	    }
+	    if (m->fleeing) {
+		mtmp->mflee = 1;
+		mtmp->mfleetim = (m->fleeing % 127);
+	    }
+
+	    if (m->has_invent) {
+		discard_minvent(mtmp);
+		invent_carrying_monster = mtmp;
+	    }
 	}
 
-    }		/* if (rn2(100) < m->chance) */
- m_done:
-    Free(m->name.str);
-    Free(m->appear_as.str);
 }
 
@@ -915,17 +1689,11 @@
     boolean named;	/* has a name been supplied in level description? */
 
-    if (rn2(100) < o->chance) {
 	named = o->name.str ? TRUE : FALSE;
 
 	x = o->x; y = o->y;
-	if (croom)
-	    get_room_loc(&x, &y, croom);
-	else
-	    get_location(&x, &y, DRY);
+	get_location(&x, &y, DRY, croom);
 
 	if (o->class >= 0)
 	    c = o->class;
-	else if (o->class > -11)
-	    c = robjects[ -(o->class+1)];
 	else
 	    c = 0;
@@ -979,25 +1747,70 @@
 	    otmp = oname(otmp, o->name.str);
 
-	switch(o->containment) {
-	    static struct obj *container = 0;
+	if (o->eroded) {
+	    if (o->eroded < 0) otmp->oerodeproof = 1;
+	    else {
+		otmp->oeroded = (o->eroded % 4);
+		otmp->oeroded2 = ((o->eroded >> 2) % 4);
+	    }
+	}
+	if (o->recharged) otmp->recharged = (o->recharged % 8);
+	if (o->locked) otmp->olocked = 1;
+	else if (o->broken) {
+	    otmp->obroken = 1;
+	    otmp->olocked = 0; /* obj generation may set */
+	}
+	if (o->trapped) otmp->otrapped = 1;
+	if (o->greased) otmp->greased = 1;
+#ifdef INVISIBLE_OBJECTS
+	if (o->invis) otmp->oinvis = 1;
+#endif
+
+	if ((o->quan > 0) && objects[otmp->otyp].oc_merge) {
+	    otmp->quan = o->quan;
+	    otmp->owt = weight(otmp);
+	}
 
 	    /* contents */
-	    case 1:
-		if (!container) {
-		    impossible("create_object: no container");
-		    break;
+	if (o->containment & SP_OBJ_CONTENT) {
+	    if (!container_idx) {
+		if (!invent_carrying_monster) {
+		    /*impossible("create_object: no container");*/
+		    /* don't complain, the monster may be gone legally (eg. unique demon already generated)
+		       TODO: In the case of unique demon lords, they should get their inventories even when
+		       they get generated outside the des-file. Maybe another data file that determines what
+		       inventories monsters get by default?
+		     */
+		} else {
+		    int c;
+		    struct obj *objcheck = otmp;
+		    int inuse = -1;
+		    for (c = 0; c < container_idx; c++)
+			if (container_obj[c] == objcheck)
+			    inuse = c;
+		    remove_object(otmp);
+		    if (mpickobj(invent_carrying_monster, otmp)) {
+			if (inuse > -1) {
+			    impossible("container given to monster was merged or deallocated.");
+			    for (c = inuse; c < container_idx-1; c++)
+				container_obj[c] = container_obj[c+1];
+			    container_obj[container_idx] = NULL;
+			    container_idx--;
+			}
+			/* we lost track of it. */
+			return;
+		    }
 		}
+	    } else {
 		remove_object(otmp);
-		(void) add_to_container(container, otmp);
-		goto o_done;		/* don't stack, but do other cleanup */
+		(void) add_to_container(container_obj[container_idx-1], otmp);
+	    }
+	}
 	    /* container */
-	    case 2:
+	if (o->containment & SP_OBJ_CONTAINER) {
 		delete_contents(otmp);
-		container = otmp;
-		break;
-	    /* nothing */
-	    case 0: break;
-
-	    default: impossible("containment type %d?", (int) o->containment);
+	    if (container_idx < MAX_CONTAINMENT) {
+		container_obj[container_idx] = otmp;
+		container_idx++;
+	    } else impossible("create_object: too deeply nested containers.");
 	}
 
@@ -1033,9 +1846,28 @@
 	}
 
+#ifdef RECORD_ACHIEVE
+        /* Nasty hack here: try to determine if this is the Mines or Sokoban
+         * "prize" and then set record_achieve_special (maps to corpsenm)
+         * for the object.  That field will later be checked to find out if
+         * the player obtained the prize. */
+        if(otmp->otyp == LUCKSTONE && Is_mineend_level(&u.uz)) {
+                otmp->record_achieve_special = 1;
+        } else if((otmp->otyp == AMULET_OF_REFLECTION ||
+                   otmp->otyp == BAG_OF_HOLDING) &&
+                  Is_sokoend_level(&u.uz)) {
+                otmp->record_achieve_special = 1;
+        }
+#endif
+
 	stackobj(otmp);
 
-    }		/* if (rn2(100) < o->chance) */
- o_done:
-    Free(o->name.str);
+	if (o->lit) {
+	    begin_burn(otmp, FALSE);
+	}
+
+	if (o->buried && !o->containment) {
+	    /* What if we'd want to bury a container? bury_an_obj() may dealloc obj. */
+	    (void) bury_an_obj(otmp);
+	}
 }
 
@@ -1051,11 +1883,7 @@
 
 	x = e->x,  y = e->y;
-	if (croom)
-	    get_room_loc(&x, &y, croom);
-	else
-	    get_location(&x, &y, DRY);
+	get_location(&x, &y, DRY, croom);
 
 	make_engr_at(x, y, e->engr.str, 0L, e->etype);
-	free((genericptr_t) e->engr.str);
 }
 
@@ -1073,5 +1901,5 @@
 
 	x = s->x; y = s->y;
-	get_free_room_loc(&x, &y, croom);
+	get_location(&x, &y, DRY, croom);
 	mkstairs(x,y,(char)s->up, croom);
 }
@@ -1098,5 +1926,5 @@
 		croom_is_temple = FALSE;
 	} else {
-	    get_location(&x, &y, DRY);
+	    get_location(&x, &y, DRY, croom);
 	    if ((sproom = (schar) *in_rooms(x, y, TEMPLE)) != 0)
 		croom = &rooms[sproom - ROOMOFFSET];
@@ -1125,5 +1953,5 @@
 		(a->align == AM_SPLEV_NONCO) ?
 			Align2amask(noncoalignment(u.ualignbase[A_ORIGINAL])) :
-		(a->align == -11) ? induced_align(80) :
+		(a->align == -(MAX_REGISTERS+1)) ? induced_align(80) :
 		(a->align < 0 ? ralign[-a->align-1] : a->align);
 
@@ -1133,9 +1961,4 @@
 	if (a->shrine < 0) a->shrine = rn2(2);	/* handle random case */
 
-	if (oldtyp == FOUNTAIN)
-	    level.flags.nfountains--;
-	else if (oldtyp == SINK)
-	    level.flags.nsinks--;
-
 	if (!croom_is_temple || !a->shrine) return;
 
@@ -1159,8 +1982,5 @@
 
 	x = g->x; y= g->y;
-	if (croom)
-	    get_room_loc(&x, &y, croom);
-	else
-	    get_location(&x, &y, DRY);
+	get_location(&x, &y, DRY, croom);
 
 	if (g->amount == -1)
@@ -1180,34 +2000,97 @@
 {
 	schar		x,y;
-	int		trycnt = 0;
 
 	x = fx;  y = fy;
-	if (croom) {
-	    if (x < 0 && y < 0)
-		do {
-		    x = -1;  y = -1;
-		    get_room_loc(&x, &y, croom);
-		} while (++trycnt <= 200 && occupied(x,y));
-	    else
-		get_room_loc(&x, &y, croom);
-	    if(trycnt > 200)
-		return;
-	} else {
-	    get_location(&x, &y, DRY);
-	}
+	get_location(&x, &y, DRY, croom);
 	/* Don't cover up an existing feature (particularly randomly
-	   placed stairs).  However, if the _same_ feature is already
-	   here, it came from the map drawing and we still need to
-	   update the special counters. */
-	if (IS_FURNITURE(levl[x][y].typ) && levl[x][y].typ != typ)
-	    return;
+	   placed stairs). */
+	if (IS_FURNITURE(levl[x][y].typ)) return;
 
 	levl[x][y].typ = typ;
-	if (typ == FOUNTAIN)
-	    level.flags.nfountains++;
-	else if (typ == SINK)
-	    level.flags.nsinks++;
 }
 
+void
+replace_terrain(terr, croom)
+replaceterrain *terr;
+struct mkroom *croom;
+{
+    schar x, y, x1, y1, x2, y2;
+
+    if (terr->toter >= MAX_TYPE) return;
+
+    x1 = terr->x1;  y1 = terr->y1;
+    get_location(&x1, &y1, DRY|WET, croom);
+
+    x2 = terr->x2;  y2 = terr->y2;
+    get_location(&x2, &y2, DRY|WET, croom);
+
+    for (x = x1; x <= x2; x++)
+	for (y = y1; y <= y2; y++)
+	    if ((levl[x][y].typ == terr->fromter) && (rn2(100) < terr->chance)) {
+		SET_TYPLIT(x,y, terr->toter, terr->tolit);
+	    }
+}
+
+
+void
+set_terrain(terr, croom)
+terrain *terr;
+struct mkroom *croom;
+{
+    schar x, y, x1, y1, x2, y2;
+
+    if (terr->ter >= MAX_TYPE) return;
+
+    x1 = terr->x1;  y1 = terr->y1;
+    get_location(&x1, &y1, DRY|WET, croom);
+
+    switch (terr->areatyp) {
+    case 0: /* point */
+    default:
+	SET_TYPLIT(x1,y1, terr->ter, terr->tlit);
+	/* handle doors and secret doors */
+	if (levl[x1][y1].typ == SDOOR || IS_DOOR(levl[x1][y1].typ)) {
+	    if(levl[x1][y1].typ == SDOOR)
+		levl[x1][y1].doormask = D_CLOSED;
+	    if (x1 && (IS_WALL(levl[x1-1][y1].typ) ||
+				levl[x1-1][y1].horizontal))
+		levl[x1][y1].horizontal = 1;
+	}
+	break;
+    case 1: /* horiz line */
+	for (x = 0; x < (terr->x2); x++) {
+	    SET_TYPLIT(x+x1,y1, terr->ter, terr->tlit);
+	}
+	break;
+    case 2: /* vert line */
+	for (y = 0; y < (terr->y2); y++) {
+	    SET_TYPLIT(x1,y+y1, terr->ter, terr->tlit);
+	}
+	break;
+    case 3: /* filled rectangle */
+	x2 = terr->x2;  y2 = terr->y2;
+	get_location(&x2, &y2, DRY|WET, croom);
+	for (x = x1; x <= x2; x++) {
+	    for (y = y1; y <= y2; y++) {
+		SET_TYPLIT(x,y, terr->ter, terr->tlit);
+	    }
+	}
+	break;
+    case 4: /* rectangle */
+	x2 = terr->x2;  y2 = terr->y2;
+	get_location(&x2, &y2, DRY|WET, croom);
+	for (x = x1; x <= x2; x++) {
+	    SET_TYPLIT(x,y1, terr->ter, terr->tlit);
+	    SET_TYPLIT(x,y2, terr->ter, terr->tlit);
+	}
+	for (y = y1; y <= y2; y++) {
+	    SET_TYPLIT(x1,y, terr->ter, terr->tlit);
+	    SET_TYPLIT(x2,y, terr->ter, terr->tlit);
+	}
+	break;
+    }
+}
+
+
 /*
  * Search for a door in a room on a specified wall.
@@ -1424,7 +2307,7 @@
 
 	if (c->src.room == -1) {
-		sort_rooms();
+	    /*sort_rooms();*/
 		fix_stair_rooms();
-		makecorridors();
+		makecorridors(c->src.door);
 		return;
 	}
@@ -1482,4 +2365,16 @@
 			for (y=croom->ly;y<=croom->hy;y++)
 			    (void) mkgold((long)rn1(abs(depth(&u.uz))*100, 51), x, y);
+			if (rn2(2)) {
+				/* it's an aquarium!  :) */
+				level.flags.vault_is_aquarium = TRUE;
+				create_feature(0,0,croom,POOL);
+				create_feature(1,1,croom,POOL);
+				if (!rn2(3)) {
+					(void)makemon(&mons[PM_GIANT_EEL],croom->lx,croom->ly,NO_MM_FLAGS);
+				}
+				if (!rn2(3)) {
+					(void)makemon(&mons[PM_GIANT_EEL],croom->hx,croom->hy,NO_MM_FLAGS);
+				}
+			}
 		    break;
 		case COURT:
@@ -1520,88 +2415,16 @@
 }
 
-STATIC_OVL void
-free_rooms(ro, n)
-room **ro;
-int n;
-{
-	short j;
+STATIC_OVL struct mkroom *
+build_room(r, mkr)
 	room *r;
-
-	while(n--) {
-		r = ro[n];
-		Free(r->name);
-		Free(r->parent);
-		if ((j = r->ndoor) != 0) {
-			while(j--)
-			    Free(r->doors[j]);
-			Free(r->doors);
-		}
-		if ((j = r->nstair) != 0) {
-			while(j--)
-			    Free(r->stairs[j]);
-			Free(r->stairs);
-		}
-		if ((j = r->naltar) != 0) {
-			while (j--)
-			    Free(r->altars[j]);
-			Free(r->altars);
-		}
-		if ((j = r->nfountain) != 0) {
-			while(j--)
-			    Free(r->fountains[j]);
-			Free(r->fountains);
-		}
-		if ((j = r->nsink) != 0) {
-			while(j--)
-			    Free(r->sinks[j]);
-			Free(r->sinks);
-		}
-		if ((j = r->npool) != 0) {
-			while(j--)
-			    Free(r->pools[j]);
-			Free(r->pools);
-		}
-		if ((j = r->ntrap) != 0) {
-			while (j--)
-			    Free(r->traps[j]);
-			Free(r->traps);
-		}
-		if ((j = r->nmonster) != 0) {
-			while (j--)
-				Free(r->monsters[j]);
-			Free(r->monsters);
-		}
-		if ((j = r->nobject) != 0) {
-			while (j--)
-				Free(r->objects[j]);
-			Free(r->objects);
-		}
-		if ((j = r->ngold) != 0) {
-			while(j--)
-			    Free(r->golds[j]);
-			Free(r->golds);
-		}
-		if ((j = r->nengraving) != 0) {
-			while (j--)
-				Free(r->engravings[j]);
-			Free(r->engravings);
-		}
-		Free(r);
-	}
-	Free(ro);
-}
-
-STATIC_OVL void
-build_room(r, pr)
-room *r, *pr;
+struct mkroom *mkr;
 {
 	boolean okroom;
 	struct mkroom	*aroom;
-	short i;
 	xchar rtype = (!r->chance || rn2(100) < r->chance) ? r->rtype : OROOM;
 
-	if(pr) {
+	if(mkr) {
 		aroom = &subrooms[nsubroom];
-		okroom = create_subroom(pr->mkr, r->x, r->y, r->w, r->h,
+		okroom = create_subroom(mkr, r->x, r->y, r->w, r->h,
 					rtype, r->rlit);
 	} else {
@@ -1609,51 +2432,7 @@
 		okroom = create_room(r->x, r->y, r->w, r->h, r->xalign,
 				     r->yalign, rtype, r->rlit);
-		r->mkr = aroom;
 	}
 
 	if (okroom) {
-		/* Create subrooms if necessary... */
-		for(i=0; i < r->nsubroom; i++)
-		    build_room(r->subrooms[i], r);
-		/* And now we can fill the room! */
-
-		/* Priority to the stairs */
-
-		for(i=0; i <r->nstair; i++)
-		    create_stairs(r->stairs[i], aroom);
-
-		/* Then to the various elements (sinks, etc..) */
-		for(i = 0; i<r->nsink; i++)
-		    create_feature(r->sinks[i]->x, r->sinks[i]->y, aroom, SINK);
-		for(i = 0; i<r->npool; i++)
-		    create_feature(r->pools[i]->x, r->pools[i]->y, aroom, POOL);
-		for(i = 0; i<r->nfountain; i++)
-		    create_feature(r->fountains[i]->x, r->fountains[i]->y,
-				   aroom, FOUNTAIN);
-		for(i = 0; i<r->naltar; i++)
-		    create_altar(r->altars[i], aroom);
-		for(i = 0; i<r->ndoor; i++)
-		    create_door(r->doors[i], aroom);
-
-		/* The traps */
-		for(i = 0; i<r->ntrap; i++)
-		    create_trap(r->traps[i], aroom);
-
-		/* The monsters */
-		for(i = 0; i<r->nmonster; i++)
-		    create_monster(r->monsters[i], aroom);
-
-		/* The objects */
-		for(i = 0; i<r->nobject; i++)
-		    create_object(r->objects[i], aroom);
-
-		/* The gold piles */
-		for(i = 0; i<r->ngold; i++)
-		    create_gold(r->golds[i], aroom);
-
-		/* The engravings */
-		for (i = 0; i < r->nengraving; i++)
-		    create_engraving(r->engravings[i], aroom);
-
 #ifdef SPECIALIZATION
 		topologize(aroom,FALSE);		/* set roomno */
@@ -1661,11 +2440,8 @@
 		topologize(aroom);			/* set roomno */
 #endif
-		/* MRS - 07/04/91 - This is temporary but should result
-		 * in proper filling of shops, etc.
-		 * DLC - this can fail if corridors are added to this room
-		 * at a later point.  Currently no good way to fix this.
-		 */
-		if(aroom->rtype != OROOM && r->filled) fill_room(aroom, FALSE);
+		aroom->needfill = ((aroom->rtype != OROOM) && r->filled);
+	        return aroom;
 	}
+	return (struct mkroom *)0;
 }
 
@@ -1701,53 +2477,4 @@
 }
 
-/* initialization common to all special levels */
-STATIC_OVL void
-load_common_data(fd, typ)
-dlb *fd;
-int typ;
-{
-	uchar	n;
-	long	lev_flags;
-	int	i;
-
-      {
-	aligntyp atmp;
-	/* shuffle 3 alignments; can't use sp_lev_shuffle() on aligntyp's */
-	i = rn2(3);   atmp=ralign[2]; ralign[2]=ralign[i]; ralign[i]=atmp;
-	if (rn2(2)) { atmp=ralign[1]; ralign[1]=ralign[0]; ralign[0]=atmp; }
-      }
-
-	level.flags.is_maze_lev = typ == SP_LEV_MAZE;
-
-	/* Read the level initialization data */
-	Fread((genericptr_t) &init_lev, 1, sizeof(lev_init), fd);
-	if(init_lev.init_present) {
-	    if(init_lev.lit < 0)
-		init_lev.lit = rn2(2);
-	    mkmap(&init_lev);
-	}
-
-	/* Read the per level flags */
-	Fread((genericptr_t) &lev_flags, 1, sizeof(lev_flags), fd);
-	if (lev_flags & NOTELEPORT)
-	    level.flags.noteleport = 1;
-	if (lev_flags & HARDFLOOR)
-	    level.flags.hardfloor = 1;
-	if (lev_flags & NOMMAP)
-	    level.flags.nommap = 1;
-	if (lev_flags & SHORTSIGHTED)
-	    level.flags.shortsighted = 1;
-	if (lev_flags & ARBOREAL)
-	    level.flags.arboreal = 1;
-
-	/* Read message */
-	Fread((genericptr_t) &n, 1, sizeof(n), fd);
-	if (n) {
-	    lev_message = (char *) alloc(n + 1);
-	    Fread((genericptr_t) lev_message, 1, (int) n, fd);
-	    lev_message[n] = 0;
-	}
-}
-
 STATIC_OVL void
 load_one_monster(fd, m)
@@ -1802,725 +2529,1925 @@
 }
 
+STATIC_OVL void
+load_one_room(fd, r)
+dlb *fd;
+room *r;
+{
+    int size;
+
+    Fread((genericptr_t) r, 1, sizeof *r, fd);
+    size = r->name.len;
+    if (size > 0) {
+	r->name.str = (char *) alloc((unsigned)size + 1);
+	Fread((genericptr_t) r->name.str, 1, size, fd);
+	r->name.str[size] = '\0';
+    }
+    size = r->parent.len;
+    if (size > 0) {
+	r->parent.str = (char *) alloc((unsigned)size + 1);
+	Fread((genericptr_t) r->parent.str, 1, size, fd);
+	r->parent.str[size] = '\0';
+    }
+}
+
+void
+wallify_map(x1,y1,x2,y2)
+int x1,y1,x2,y2;
+{
+	int x, y, xx, yy, lo_xx, lo_yy, hi_xx, hi_yy;
+
+	for (y = y1; y <= y2; y++) {
+	    lo_yy = (y > 0) ? y - 1 : 0;
+	    hi_yy = (y < y2) ? y + 1 : y2;
+	    for (x = x1; x <= x2; x++) {
+		if (levl[x][y].typ != STONE) continue;
+		lo_xx = (x > 0) ? x - 1 : 0;
+		hi_xx = (x < x2) ? x + 1 : x2;
+		for (yy = lo_yy; yy <= hi_yy; yy++)
+		    for (xx = lo_xx; xx <= hi_xx; xx++)
+			if (IS_ROOM(levl[xx][yy].typ) ||
+				levl[xx][yy].typ == CROSSWALL) {
+			    levl[x][y].typ = (yy != y) ? HWALL : VWALL;
+			    yy = hi_yy;		/* end `yy' loop */
+			    break;		/* end `xx' loop */
+			}
+	    }
+	}
+}
+
+/*
+ * Select a random coordinate in the maze.
+ *
+ * We want a place not 'touched' by the loader.  That is, a place in
+ * the maze outside every part of the special level.
+ */
+
+STATIC_OVL void
+maze1xy(m, humidity)
+coord *m;
+int humidity;
+{
+	register int x, y, tryct = 2000;
+	/* tryct:  normally it won't take more than ten or so tries due
+	   to the circumstances under which we'll be called, but the
+	   `humidity' screening might drastically change the chances */
+
+	do {
+	    x = rn1(x_maze_max - 3, 3);
+	    y = rn1(y_maze_max - 3, 3);
+	    if (--tryct < 0) break;	/* give up */
+	} while (!(x % 2) || !(y % 2) || !SpLev_Map[x][y] ||
+		 !is_ok_location((schar)x, (schar)y, humidity));
+
+	m->x = (xchar)x,  m->y = (xchar)y;
+}
+
+/*
+ * If there's a significant portion of maze unused by the special level,
+ * we don't want it empty.
+ *
+ * Makes the number of traps, monsters, etc. proportional
+ * to the size of the maze.
+ */
+STATIC_OVL void
+fill_empty_maze()
+{
+    int mapcountmax, mapcount, mapfact;
+    xchar x,y;
+    coord mm;
+
+    mapcountmax = mapcount = (x_maze_max - 2) * (y_maze_max - 2);
+    mapcountmax = mapcountmax / 2;
+
+    for(x = 2; x < x_maze_max; x++)
+	for(y = 0; y < y_maze_max; y++)
+	    if(!SpLev_Map[x][y]) mapcount--;
+
+    if ((mapcount > (int) (mapcountmax / 10))) {
+	    mapfact = (int) ((mapcount * 100L) / mapcountmax);
+	    for(x = rnd((int) (20 * mapfact) / 100); x; x--) {
+		    maze1xy(&mm, DRY);
+		    (void) mkobj_at(rn2(2) ? GEM_CLASS : RANDOM_CLASS,
+							mm.x, mm.y, TRUE);
+	    }
+	    for(x = rnd((int) (12 * mapfact) / 100); x; x--) {
+		    maze1xy(&mm, DRY);
+		    (void) mksobj_at(BOULDER, mm.x, mm.y, TRUE, FALSE);
+	    }
+	    for (x = rn2(2); x; x--) {
+		maze1xy(&mm, DRY);
+		(void) makemon(&mons[PM_MINOTAUR], mm.x, mm.y, NO_MM_FLAGS);
+	    }
+	    for(x = rnd((int) (12 * mapfact) / 100); x; x--) {
+		    maze1xy(&mm, WET|DRY);
+		    (void) makemon((struct permonst *) 0, mm.x, mm.y, NO_MM_FLAGS);
+	    }
+	    for(x = rn2((int) (15 * mapfact) / 100); x; x--) {
+		    maze1xy(&mm, DRY);
+		    (void) mkgold(0L,mm.x,mm.y);
+	    }
+	    for(x = rn2((int) (15 * mapfact) / 100); x; x--) {
+		    int trytrap;
+
+		    maze1xy(&mm, DRY);
+		    trytrap = rndtrap();
+		    if (sobj_at(BOULDER, mm.x, mm.y))
+			while (trytrap == PIT || trytrap == SPIKED_PIT ||
+				trytrap == TRAPDOOR || trytrap == HOLE)
+			    trytrap = rndtrap();
+		    (void) maketrap(mm.x, mm.y, trytrap);
+	    }
+    }
+}
+
+/*
+ * special level loader
+ */
 STATIC_OVL boolean
-load_rooms(fd)
+sp_level_loader(fd, lvl)
 dlb *fd;
+sp_lev *lvl;
 {
-	xchar		nrooms, ncorr;
-	char		n;
-	short		size;
-	corridor	tmpcor;
-	room**		tmproom;
-	int		i, j;
+    long n_opcode = 0;
+    struct opvar *opdat;
+    int opcode;
 
-	load_common_data(fd, SP_LEV_ROOMS);
+    Fread((genericptr_t)&(lvl->n_opcodes), 1, sizeof(lvl->n_opcodes), fd);
 
-	Fread((genericptr_t) &n, 1, sizeof(n), fd); /* nrobjects */
-	if (n) {
-		Fread((genericptr_t)robjects, sizeof(*robjects), n, fd);
-		sp_lev_shuffle(robjects, (char *)0, (int)n);
+    lvl->opcodes = (_opcode *)alloc(sizeof(_opcode) * (lvl->n_opcodes));
+
+    while (n_opcode < lvl->n_opcodes) {
+
+	Fread((genericptr_t) &lvl->opcodes[n_opcode].opcode, 1,
+	      sizeof(lvl->opcodes[n_opcode].opcode), fd);
+	opcode = lvl->opcodes[n_opcode].opcode;
+
+	opdat = NULL;
+
+	if (opcode < SPO_NULL || opcode >= MAX_SP_OPCODES)
+	    panic("sp_level_loader: impossible opcode %i.", opcode);
+
+	if (opcode == SPO_PUSH) {
+	    struct opvar *ov = (opdat = (struct opvar *)alloc(sizeof(struct opvar)));
+	    int nsize;
+
+	    ov->spovartyp = SPO_NULL;
+	    ov->vardata.l = 0;
+	    Fread((genericptr_t)&(ov->spovartyp), 1, sizeof(ov->spovartyp), fd);
+
+	    switch (ov->spovartyp) {
+	    case SPOVAR_NULL: break;
+	    case SPOVAR_COORD:
+	    case SPOVAR_REGION:
+	    case SPOVAR_MAPCHAR:
+	    case SPOVAR_MONST:
+	    case SPOVAR_OBJ:
+	    case SPOVAR_INT:
+		Fread((genericptr_t)&(ov->vardata.l), 1, sizeof(ov->vardata.l), fd);
+		break;
+	    case SPOVAR_VARIABLE:
+	    case SPOVAR_STRING:
+	    case SPOVAR_SEL:
+		{
+		    char *opd;
+		    Fread((genericptr_t) &nsize, 1, sizeof(nsize), fd);
+		    opd = (char *)alloc(nsize + 1);
+		    if (nsize) Fread(opd, 1, nsize, fd);
+		    opd[nsize] = 0;
+		    ov->vardata.str = opd;
+		}
+		break;
+	    default:
+		panic("sp_level_loader: unknown opvar type %i", ov->spovartyp);
+	    }
 	}
 
-	Fread((genericptr_t) &n, 1, sizeof(n), fd); /* nrmonst */
-	if (n) {
-		Fread((genericptr_t)rmonst, sizeof(*rmonst), n, fd);
-		sp_lev_shuffle(rmonst, (char *)0, (int)n);
+	lvl->opcodes[n_opcode].opdat = opdat;
+	n_opcode++;
+    } /*while*/
+
+    return TRUE;
 	}
 
-	Fread((genericptr_t) &nrooms, 1, sizeof(nrooms), fd);
-						/* Number of rooms to read */
-	tmproom = NewTab(room,nrooms);
-	for (i=0;i<nrooms;i++) {
-		room *r;
 
-		r = tmproom[i] = New(room);
+/* Frees the memory allocated for special level creation structs */
+STATIC_OVL boolean
+sp_level_free(lvl)
+sp_lev *lvl;
+{
+    long n_opcode = 0;
 
-		/* Let's see if this room has a name */
-		Fread((genericptr_t) &size, 1, sizeof(size), fd);
-		if (size > 0) {	/* Yup, it does! */
-			r->name = (char *) alloc((unsigned)size + 1);
-			Fread((genericptr_t) r->name, 1, size, fd);
-			r->name[size] = 0;
-		} else
-		    r->name = (char *) 0;
+    while (n_opcode < lvl->n_opcodes) {
+	int opcode = lvl->opcodes[n_opcode].opcode;
+	struct opvar *opdat = lvl->opcodes[n_opcode].opdat;
 
-		/* Let's see if this room has a parent */
-		Fread((genericptr_t) &size, 1, sizeof(size), fd);
-		if (size > 0) {	/* Yup, it does! */
-			r->parent = (char *) alloc((unsigned)size + 1);
-			Fread((genericptr_t) r->parent, 1, size, fd);
-			r->parent[size] = 0;
-		} else
-		    r->parent = (char *) 0;
+	if (opcode < SPO_NULL || opcode >= MAX_SP_OPCODES)
+	    panic("sp_level_free: unknown opcode %i", opcode);
 
-		Fread((genericptr_t) &r->x, 1, sizeof(r->x), fd);
-					/* x pos on the grid (1-5) */
-		Fread((genericptr_t) &r->y, 1, sizeof(r->y), fd);
-					 /* y pos on the grid (1-5) */
-		Fread((genericptr_t) &r->w, 1, sizeof(r->w), fd);
-					 /* width of the room */
-		Fread((genericptr_t) &r->h, 1, sizeof(r->h), fd);
-					 /* height of the room */
-		Fread((genericptr_t) &r->xalign, 1, sizeof(r->xalign), fd);
-					 /* horizontal alignment */
-		Fread((genericptr_t) &r->yalign, 1, sizeof(r->yalign), fd);
-					 /* vertical alignment */
-		Fread((genericptr_t) &r->rtype, 1, sizeof(r->rtype), fd);
-					 /* type of room (zoo, shop, etc.) */
-		Fread((genericptr_t) &r->chance, 1, sizeof(r->chance), fd);
-					 /* chance of room being special. */
-		Fread((genericptr_t) &r->rlit, 1, sizeof(r->rlit), fd);
-					 /* lit or not ? */
-		Fread((genericptr_t) &r->filled, 1, sizeof(r->filled), fd);
-					 /* to be filled? */
-		r->nsubroom= 0;
+	if (opdat) opvar_free(opdat);
+	n_opcode++;
+    }
+    free(lvl->opcodes);
+    return TRUE;
+}
 
-		/* read the doors */
-		Fread((genericptr_t) &r->ndoor, 1, sizeof(r->ndoor), fd);
-		if ((n = r->ndoor) != 0)
-		    r->doors = NewTab(room_door, n);
-		while(n--) {
-			r->doors[(int)n] = New(room_door);
-			Fread((genericptr_t) r->doors[(int)n], 1,
-				sizeof(room_door), fd);
+void
+splev_initlev(linit)
+lev_init *linit;
+{
+    switch (linit->init_style) {
+    default: impossible("Unrecognized level init style."); break;
+    case LVLINIT_NONE: break;
+    case LVLINIT_SOLIDFILL:
+	if (linit->lit == -1) linit->lit = rn2(2);
+	lvlfill_solid(linit->filling, linit->lit);
+	break;
+    case LVLINIT_MAZEGRID:
+	lvlfill_maze_grid(2,0, x_maze_max,y_maze_max, linit->filling);
+	break;
+    case LVLINIT_MINES:
+	if (linit->filling > -1) lvlfill_solid(linit->filling, 0);
+	mkmap(linit);
+	break;
+    }
 		}
 
-		/* read the stairs */
-		Fread((genericptr_t) &r->nstair, 1, sizeof(r->nstair), fd);
-		if ((n = r->nstair) != 0)
-		    r->stairs = NewTab(stair, n);
-		while (n--) {
-			r->stairs[(int)n] = New(stair);
-			Fread((genericptr_t) r->stairs[(int)n], 1,
-				sizeof(stair), fd);
+struct sp_frame *
+frame_new(execptr)
+     long execptr;
+{
+    struct sp_frame *frame = (struct sp_frame *)alloc(sizeof(struct sp_frame));
+    if (!frame) panic("could not create execution frame.");
+    frame->next = NULL;
+    frame->variables = NULL;
+    frame->n_opcode = execptr;
+    frame->stack = (struct splevstack *)alloc(sizeof(struct splevstack));
+    if (!frame->stack) panic("could not create execution frame stack.");
+    splev_stack_init(frame->stack);
+    return frame;
 		}
 
-		/* read the altars */
-		Fread((genericptr_t) &r->naltar, 1, sizeof(r->naltar), fd);
-		if ((n = r->naltar) != 0)
-		    r->altars = NewTab(altar, n);
-		while (n--) {
-			r->altars[(int)n] = New(altar);
-			Fread((genericptr_t) r->altars[(int)n], 1,
-				sizeof(altar), fd);
+void
+frame_del(frame)
+     struct sp_frame *frame;
+{
+    if (!frame) return;
+    if (frame->stack) {
+	splev_stack_done(frame->stack);
+	frame->stack = NULL;
+    }
+    if (frame->variables) {
+	variable_list_del(frame->variables);
+	frame->variables = NULL;
+    }
+    Free(frame);
 		}
 
-		/* read the fountains */
-		Fread((genericptr_t) &r->nfountain, 1,
-			sizeof(r->nfountain), fd);
-		if ((n = r->nfountain) != 0)
-		    r->fountains = NewTab(fountain, n);
-		while (n--) {
-			r->fountains[(int)n] = New(fountain);
-			Fread((genericptr_t) r->fountains[(int)n], 1,
-				sizeof(fountain), fd);
+
+void
+spo_frame_push(coder)
+     struct sp_coder *coder;
+{
+    struct sp_frame *tmpframe = frame_new(coder->frame->n_opcode);
+    tmpframe->next = coder->frame;
+    coder->frame = tmpframe;
 		}
 
-		/* read the sinks */
-		Fread((genericptr_t) &r->nsink, 1, sizeof(r->nsink), fd);
-		if ((n = r->nsink) != 0)
-		    r->sinks = NewTab(sink, n);
-		while (n--) {
-			r->sinks[(int)n] = New(sink);
-			Fread((genericptr_t) r->sinks[(int)n], 1, sizeof(sink), fd);
+void
+spo_frame_pop(coder)
+     struct sp_coder *coder;
+{
+    if (coder->frame->next) {
+	struct sp_frame *tmpframe = coder->frame->next;
+	frame_del(coder->frame);
+	coder->frame = tmpframe;
+    }
 		}
 
-		/* read the pools */
-		Fread((genericptr_t) &r->npool, 1, sizeof(r->npool), fd);
-		if ((n = r->npool) != 0)
-		    r->pools = NewTab(pool,n);
-		while (n--) {
-			r->pools[(int)n] = New(pool);
-			Fread((genericptr_t) r->pools[(int)n], 1, sizeof(pool), fd);
+long
+sp_code_jmpaddr(curpos, jmpaddr)
+     long curpos, jmpaddr;
+{
+    return (curpos + jmpaddr);
 		}
 
-		/* read the traps */
-		Fread((genericptr_t) &r->ntrap, 1, sizeof(r->ntrap), fd);
-		if ((n = r->ntrap) != 0)
-		    r->traps = NewTab(trap, n);
-		while(n--) {
-			r->traps[(int)n] = New(trap);
-			Fread((genericptr_t) r->traps[(int)n], 1, sizeof(trap), fd);
+void
+spo_call(coder)
+     struct sp_coder *coder;
+{
+    struct opvar *addr;
+    struct opvar *params;
+    struct sp_frame *tmpframe;
+
+    if (!OV_pop_i(addr) || !OV_pop_i(params)) return;
+    if (OV_i(params) < 0) return;
+
+    /* push a frame */
+    tmpframe = frame_new(sp_code_jmpaddr(coder->frame->n_opcode, OV_i(addr)-1));
+    tmpframe->next = coder->frame;
+    coder->frame = tmpframe;
+
+    while (OV_i(params)-- > 0) {
+	splev_stack_push(tmpframe->stack, splev_stack_pop(coder->stack));
+    }
+    opvar_free(addr);
+    opvar_free(params);
 		}
 
-		/* read the monsters */
-		Fread((genericptr_t) &r->nmonster, 1, sizeof(r->nmonster), fd);
-		if ((n = r->nmonster) != 0) {
-		    r->monsters = NewTab(monster, n);
-		    while(n--) {
-			r->monsters[(int)n] = New(monster);
-			load_one_monster(fd, r->monsters[(int)n]);
+void
+spo_return(coder)
+     struct sp_coder *coder;
+{
+    struct opvar *params;
+    if (!coder->frame->next) return; /* something is seriously wrong */
+    if (!OV_pop_i(params)) return;
+    if (OV_i(params) < 0) return;
+
+    while (OV_i(params)-- > 0) {
+	splev_stack_push(coder->frame->next->stack, splev_stack_pop(coder->stack));
 		    }
-		} else
-		    r->monsters = 0;
 
-		/* read the objects, in same order as mazes */
-		Fread((genericptr_t) &r->nobject, 1, sizeof(r->nobject), fd);
-		if ((n = r->nobject) != 0) {
-		    r->objects = NewTab(object, n);
-		    for (j = 0; j < n; ++j) {
-			r->objects[j] = New(object);
-			load_one_object(fd, r->objects[j]);
+    /* pop the frame */
+    if (coder->frame->next) {
+	struct sp_frame *tmpframe = coder->frame->next;
+	frame_del(coder->frame);
+	coder->frame = tmpframe;
+	coder->stack = coder->frame->stack;
 		    }
-		} else
-		    r->objects = 0;
 
-		/* read the gold piles */
-		Fread((genericptr_t) &r->ngold, 1, sizeof(r->ngold), fd);
-		if ((n = r->ngold) != 0)
-		    r->golds = NewTab(gold, n);
-		while (n--) {
-			r->golds[(int)n] = New(gold);
-			Fread((genericptr_t) r->golds[(int)n], 1, sizeof(gold), fd);
+    opvar_free(params);
 		}
 
-		/* read the engravings */
-		Fread((genericptr_t) &r->nengraving, 1,
-			sizeof(r->nengraving), fd);
-		if ((n = r->nengraving) != 0) {
-		    r->engravings = NewTab(engraving,n);
-		    while (n--) {
-			r->engravings[(int)n] = New(engraving);
-			load_one_engraving(fd, r->engravings[(int)n]);
+void
+spo_end_moninvent(coder)
+     struct sp_coder *coder;
+{
+    if (invent_carrying_monster)
+	m_dowear(invent_carrying_monster, TRUE);
+    invent_carrying_monster = NULL;
 		    }
-		} else
-		    r->engravings = 0;
 
+void
+spo_pop_container(coder)
+     struct sp_coder *coder;
+{
+    if (container_idx > 0) {
+	container_idx--;
+	container_obj[container_idx] = NULL;
+    }
 	}
 
-	/* Now that we have loaded all the rooms, search the
-	 * subrooms and create the links.
-	 */
 
-	for (i = 0; i<nrooms; i++)
-	    if (tmproom[i]->parent) {
-		    /* Search the parent room */
-		    for(j=0; j<nrooms; j++)
-			if (tmproom[j]->name && !strcmp(tmproom[j]->name,
-						       tmproom[i]->parent)) {
-				n = tmproom[j]->nsubroom++;
-				tmproom[j]->subrooms[(int)n] = tmproom[i];
+void
+spo_message(coder)
+     struct sp_coder *coder;
+{
+    struct opvar *op;
+    char *msg, *levmsg;
+    int old_n, n;
+    if (!OV_pop_s(op)) return;
+    msg = string_subst(OV_s(op));
+    if (!msg) return;
+
+    old_n = lev_message ? (strlen(lev_message)+1) : 0;
+    n = strlen(msg);
+
+    levmsg = (char *) alloc(old_n+n+1);
+    if (old_n) levmsg[old_n-1] = '\n';
+    if (lev_message)
+	(void) memcpy((genericptr_t)levmsg, (genericptr_t)lev_message, old_n-1);
+    (void) memcpy((genericptr_t)&levmsg[old_n], msg, n);
+    levmsg[old_n+n] = '\0';
+    Free(lev_message);
+    lev_message = levmsg;
+    opvar_free(op);
+}
+
+void
+spo_monster(coder)
+     struct sp_coder *coder;
+{
+    int nparams = 0;
+
+    struct opvar *varparam;
+    struct opvar *id, *coord, *has_inv;
+    monster tmpmons;
+
+    tmpmons.peaceful = -1;
+    tmpmons.asleep = -1;
+    tmpmons.name.str = (char *)0;
+    tmpmons.appear = 0;
+    tmpmons.appear_as.str = (char *)0;
+    tmpmons.align = - MAX_REGISTERS - 2;
+    tmpmons.female = 0;
+    tmpmons.invis = 0;
+    tmpmons.cancelled = 0;
+    tmpmons.revived = 0;
+    tmpmons.avenge = 0;
+    tmpmons.fleeing = 0;
+    tmpmons.blinded = 0;
+    tmpmons.paralyzed = 0;
+    tmpmons.stunned = 0;
+    tmpmons.confused = 0;
+    tmpmons.seentraps = 0;
+    tmpmons.has_invent = 0;
+
+    if (!OV_pop_i(has_inv)) return;
+
+    if (!OV_pop_i(varparam)) return;
+
+    while ((nparams++ < (SP_M_V_END+1)) &&
+	   (OV_typ(varparam) == SPOVAR_INT) &&
+	   (OV_i(varparam) >= 0) &&
+	   (OV_i(varparam) < SP_M_V_END)) {
+	struct opvar *parm = NULL;
+	OV_pop(parm);
+	switch (OV_i(varparam)) {
+	case SP_M_V_NAME:
+	    if ((OV_typ(parm) == SPOVAR_STRING) &&
+		!tmpmons.name.str)
+		tmpmons.name.str = strdup(OV_s(parm));
+	    break;
+	case SP_M_V_APPEAR:
+	    if ((OV_typ(parm) == SPOVAR_INT) &&
+		!tmpmons.appear_as.str) {
+		tmpmons.appear = OV_i(parm);
+		opvar_free(parm);
+		OV_pop(parm);
+		tmpmons.appear_as.str = strdup(OV_s(parm));
+	    }
+	    break;
+	case SP_M_V_ASLEEP:
+	    if (OV_typ(parm) == SPOVAR_INT)
+		tmpmons.asleep = OV_i(parm);
+	    break;
+	case SP_M_V_ALIGN:
+	    if (OV_typ(parm) == SPOVAR_INT)
+		tmpmons.align = OV_i(parm);
+	    break;
+	case SP_M_V_PEACEFUL:
+	    if (OV_typ(parm) == SPOVAR_INT)
+		tmpmons.peaceful = OV_i(parm);
+	    break;
+	case SP_M_V_FEMALE:
+	    if (OV_typ(parm) == SPOVAR_INT)
+		tmpmons.female = OV_i(parm);
+	    break;
+	case SP_M_V_INVIS:
+	    if (OV_typ(parm) == SPOVAR_INT)
+		tmpmons.invis = OV_i(parm);
+	    break;
+	case SP_M_V_CANCELLED:
+	    if (OV_typ(parm) == SPOVAR_INT)
+		tmpmons.cancelled = OV_i(parm);
+	    break;
+	case SP_M_V_REVIVED:
+	    if (OV_typ(parm) == SPOVAR_INT)
+		tmpmons.revived = OV_i(parm);
+	    break;
+	case SP_M_V_AVENGE:
+	    if (OV_typ(parm) == SPOVAR_INT)
+		tmpmons.avenge = OV_i(parm);
+	    break;
+	case SP_M_V_FLEEING:
+	    if (OV_typ(parm) == SPOVAR_INT)
+		tmpmons.fleeing = OV_i(parm);
+	    break;
+	case SP_M_V_BLINDED:
+	    if (OV_typ(parm) == SPOVAR_INT)
+		tmpmons.blinded = OV_i(parm);
+	    break;
+	case SP_M_V_PARALYZED:
+	    if (OV_typ(parm) == SPOVAR_INT)
+		tmpmons.paralyzed = OV_i(parm);
+	    break;
+	case SP_M_V_STUNNED:
+	    if (OV_typ(parm) == SPOVAR_INT)
+		tmpmons.stunned = OV_i(parm);
+	    break;
+	case SP_M_V_CONFUSED:
+	    if (OV_typ(parm) == SPOVAR_INT)
+		tmpmons.confused = OV_i(parm);
+	    break;
+	case SP_M_V_SEENTRAPS:
+	    if (OV_typ(parm) == SPOVAR_INT)
+		tmpmons.seentraps = OV_i(parm);
+	    break;
+	case SP_M_V_END:
+	    nparams = SP_M_V_END+1;
+	    break;
+	default:
+	    impossible("MONSTER with unknown variable param type!");
 				break;
 			}
+	opvar_free(parm);
+	if (OV_i(varparam) != SP_M_V_END) {
+	    opvar_free(varparam);
+	    OV_pop(varparam);
+	}
 	    }
 
-	/*
-	 * Create the rooms now...
-	 */
+    if (!OV_pop_c(coord)) panic("no monster coord?");
 
-	for (i=0; i < nrooms; i++)
-	    if(!tmproom[i]->parent)
-		build_room(tmproom[i], (room *) 0);
+    if (!OV_pop_typ(id, SPOVAR_MONST)) panic("no mon type");
 
-	free_rooms(tmproom, nrooms);
+    tmpmons.id = SP_MONST_PM(OV_i(id));
+    tmpmons.class = SP_MONST_CLASS(OV_i(id));
+    tmpmons.x = SP_COORD_X(OV_i(coord));
+    tmpmons.y = SP_COORD_Y(OV_i(coord));
+    tmpmons.has_invent = OV_i(has_inv);
 
-	/* read the corridors */
+    create_monster(&tmpmons, coder->croom);
 
-	Fread((genericptr_t) &ncorr, sizeof(ncorr), 1, fd);
-	for (i=0; i<ncorr; i++) {
-		Fread((genericptr_t) &tmpcor, 1, sizeof(tmpcor), fd);
-		create_corridor(&tmpcor);
+    free(tmpmons.name.str);
+    free(tmpmons.appear_as.str);
+
+    opvar_free(id);
+    opvar_free(coord);
+    opvar_free(has_inv);
+    opvar_free(varparam);
 	}
 
-	return TRUE;
+void
+spo_object(coder)
+     struct sp_coder *coder;
+{
+    int nparams = 0;
+    long quancnt;
+
+    struct opvar *varparam;
+    struct opvar *id, *containment;
+
+    object tmpobj;
+
+    tmpobj.spe = -127;
+    tmpobj.curse_state = -1;
+    tmpobj.corpsenm = NON_PM;
+    tmpobj.name.str = (char *)0;
+    tmpobj.quan = -1;
+    tmpobj.buried = 0;
+    tmpobj.lit = 0;
+    tmpobj.eroded = 0;
+    tmpobj.locked = 0;
+    tmpobj.trapped = 0;
+    tmpobj.recharged = 0;
+    tmpobj.invis = 0;
+    tmpobj.greased = 0;
+    tmpobj.broken = 0;
+    tmpobj.x = tmpobj.y = -1;
+
+    if (!OV_pop_i(containment)) return;
+
+    if (!OV_pop_i(varparam)) return;
+
+    while ((nparams++ < (SP_O_V_END+1)) &&
+	   (OV_typ(varparam) == SPOVAR_INT) &&
+	   (OV_i(varparam) >= 0) &&
+	   (OV_i(varparam) < SP_O_V_END)) {
+	struct opvar *parm;
+	OV_pop(parm);
+	switch (OV_i(varparam)) {
+	case SP_O_V_NAME:
+	    if ((OV_typ(parm) == SPOVAR_STRING) &&
+		!tmpobj.name.str)
+		tmpobj.name.str = strdup(OV_s(parm));
+	    break;
+	case SP_O_V_CORPSENM:
+	    if ((OV_typ(parm) == SPOVAR_MONST)) {
+		char monclass = SP_MONST_CLASS(OV_i(parm));
+		int monid = SP_MONST_PM(OV_i(parm));
+		if (monid >= 0 && monid < NUMMONS) {
+		    tmpobj.corpsenm = monid;
+		    break; /* we're done! */
+		} else {
+		    struct permonst *pm = (struct permonst *)0;
+		    if (def_char_to_monclass(monclass) != MAXMCLASSES) {
+			pm = mkclass(def_char_to_monclass(monclass), G_NOGEN);
+		    } else {
+			pm = rndmonst();
+		    }
+		    if (pm)
+			tmpobj.corpsenm = monsndx(pm);
+		}
+	    }
+	    break;
+	case SP_O_V_CURSE:
+	    if (OV_typ(parm) == SPOVAR_INT)
+		tmpobj.curse_state = OV_i(parm);
+	    break;
+	case SP_O_V_SPE:
+	    if (OV_typ(parm) == SPOVAR_INT)
+		tmpobj.spe = OV_i(parm);
+	    break;
+	case SP_O_V_QUAN:
+	    if (OV_typ(parm) == SPOVAR_INT)
+		tmpobj.quan = OV_i(parm);
+	    break;
+	case SP_O_V_BURIED:
+	    if (OV_typ(parm) == SPOVAR_INT)
+		tmpobj.buried = OV_i(parm);
+	    break;
+	case SP_O_V_LIT:
+	    if (OV_typ(parm) == SPOVAR_INT)
+		tmpobj.lit = OV_i(parm);
+	    break;
+	case SP_O_V_ERODED:
+	    if (OV_typ(parm) == SPOVAR_INT)
+		tmpobj.eroded = OV_i(parm);
+	    break;
+	case SP_O_V_LOCKED:
+	    if (OV_typ(parm) == SPOVAR_INT)
+		tmpobj.locked = OV_i(parm);
+	    break;
+	case SP_O_V_TRAPPED:
+	    if (OV_typ(parm) == SPOVAR_INT)
+		tmpobj.trapped = OV_i(parm);
+	    break;
+	case SP_O_V_RECHARGED:
+	    if (OV_typ(parm) == SPOVAR_INT)
+		tmpobj.recharged = OV_i(parm);
+	    break;
+	case SP_O_V_INVIS:
+	    if (OV_typ(parm) == SPOVAR_INT)
+		tmpobj.invis = OV_i(parm);
+	    break;
+	case SP_O_V_GREASED:
+	    if (OV_typ(parm) == SPOVAR_INT)
+		tmpobj.greased = OV_i(parm);
+	    break;
+	case SP_O_V_BROKEN:
+	    if (OV_typ(parm) == SPOVAR_INT)
+		tmpobj.broken = OV_i(parm);
+	    break;
+	case SP_O_V_COORD:
+	    if (OV_typ(parm) != SPOVAR_COORD)
+		panic("no coord for obj?");
+	    tmpobj.y = SP_COORD_Y(OV_i(parm));
+	    tmpobj.x = SP_COORD_X(OV_i(parm));
+	    break;
+	case SP_O_V_END:
+	    nparams = SP_O_V_END+1;
+	    break;
+	default:
+	    impossible("OBJECT with unknown variable param type!");
+	    break;
+	}
+	opvar_free(parm);
+	if (OV_i(varparam) != SP_O_V_END) {
+	    opvar_free(varparam);
+	    OV_pop(varparam);
+	}
 }
 
-/*
- * Select a random coordinate in the maze.
- *
- * We want a place not 'touched' by the loader.  That is, a place in
- * the maze outside every part of the special level.
- */
+    if (!OV_pop_typ(id, SPOVAR_OBJ)) panic("no obj type");
 
-STATIC_OVL void
-maze1xy(m, humidity)
-coord *m;
-int humidity;
-{
-	register int x, y, tryct = 2000;
-	/* tryct:  normally it won't take more than ten or so tries due
-	   to the circumstances under which we'll be called, but the
-	   `humidity' screening might drastically change the chances */
+    tmpobj.id = SP_OBJ_TYP(OV_i(id));
+    tmpobj.class = SP_OBJ_CLASS(OV_i(id));
+    tmpobj.containment = OV_i(containment);
+
+    quancnt = (tmpobj.id > STRANGE_OBJECT) ? tmpobj.quan : 0;
 
 	do {
-	    x = rn1(x_maze_max - 3, 3);
-	    y = rn1(y_maze_max - 3, 3);
-	    if (--tryct < 0) break;	/* give up */
-	} while (!(x % 2) || !(y % 2) || Map[x][y] ||
-		 !is_ok_location((schar)x, (schar)y, humidity));
+	create_object(&tmpobj, coder->croom);
+	quancnt--;
+    } while ((quancnt > 0) &&
+	     ((tmpobj.id > STRANGE_OBJECT) &&
+	      !objects[tmpobj.id].oc_merge));
 
-	m->x = (xchar)x,  m->y = (xchar)y;
+    Free(tmpobj.name.str);
+
+    opvar_free(varparam);
+    opvar_free(id);
+    opvar_free(containment);
 }
 
-/*
- * The Big Thing: special maze loader
- *
- * Could be cleaner, but it works.
- */
+void
+spo_level_flags(coder)
+     struct sp_coder *coder;
+{
+    struct opvar *flagdata;
+    long flags;
 
-STATIC_OVL boolean
-load_maze(fd)
-dlb *fd;
+    if (!OV_pop_i(flagdata)) return;
+    flags = OV_i(flagdata);
+
+    if (flags & NOTELEPORT)   level.flags.noteleport = 1;
+    if (flags & HARDFLOOR)    level.flags.hardfloor = 1;
+    if (flags & NOMMAP)       level.flags.nommap = 1;
+    if (flags & SHORTSIGHTED) level.flags.shortsighted = 1;
+    if (flags & ARBOREAL)     level.flags.arboreal = 1;
+    if (flags & NOFLIPX)      coder->allow_flips &= ~1;
+    if (flags & NOFLIPY)      coder->allow_flips &= ~2;
+    if (flags & MAZELEVEL)    level.flags.is_maze_lev = 1;
+    if (flags & PREMAPPED)    coder->premapped = TRUE;
+    if (flags & SHROUD)       level.flags.hero_memory = 0;
+    if (flags & STORMY)       level.flags.stormy = 1;
+    if (flags & GRAVEYARD)    level.flags.graveyard = 1;
+
+    opvar_free(flagdata);
+}
+
+void
+spo_initlevel(coder)
+     struct sp_coder *coder;
 {
-    xchar   x, y, typ;
-    boolean prefilled, room_not_needed;
+    lev_init init_lev;
+    struct opvar *init_style, *fg, *bg, *smoothed, *joined, *lit, *walled, *filling;
 
-    char    n, numpart = 0;
-    xchar   nwalk = 0, nwalk_sav;
-    schar   filling;
-    char    halign, valign;
+    if (!OV_pop_i(fg) ||
+	!OV_pop_i(bg) ||
+	!OV_pop_i(smoothed) ||
+	!OV_pop_i(joined) ||
+	!OV_pop_i(lit) ||
+	!OV_pop_i(walled) ||
+	!OV_pop_i(filling) ||
+	!OV_pop_i(init_style)) return;
 
-    int     xi, dir, size;
-    coord   mm;
-    int     mapcount, mapcountmax, mapfact;
+    init_lev.init_style = OV_i(init_style);
+    init_lev.fg = OV_i(fg);
+    init_lev.bg = OV_i(bg);
+    init_lev.smoothed = OV_i(smoothed);
+    init_lev.joined = OV_i(joined);
+    init_lev.lit = OV_i(lit);
+    init_lev.walled = OV_i(walled);
+    init_lev.filling = OV_i(filling);
 
-    lev_region  tmplregion;
-    region  tmpregion;
-    door    tmpdoor;
-    trap    tmptrap;
-    monster tmpmons;
-    object  tmpobj;
-    drawbridge tmpdb;
-    walk    tmpwalk;
-    digpos  tmpdig;
-    lad     tmplad;
-    stair   tmpstair, prevstair;
-    altar   tmpaltar;
-    gold    tmpgold;
-    fountain tmpfountain;
-    engraving tmpengraving;
-    xchar   mustfill[(MAXNROFROOMS+1)*2];
-    struct trap *badtrap;
-    boolean has_bounds;
+    coder->lvl_is_joined = OV_i(joined);
 
-    (void) memset((genericptr_t)&Map[0][0], 0, sizeof Map);
-    load_common_data(fd, SP_LEV_MAZE);
+    splev_initlev(&init_lev);
 
-    /* Initialize map */
-    Fread((genericptr_t) &filling, 1, sizeof(filling), fd);
-    if (!init_lev.init_present) { /* don't init if mkmap() has been called */
-      for(x = 2; x <= x_maze_max; x++)
-	for(y = 0; y <= y_maze_max; y++)
-	    if (filling == -1) {
-#ifndef WALLIFIED_MAZE
-		    levl[x][y].typ = STONE;
-#else
-		    levl[x][y].typ =
-			(y < 2 || ((x % 2) && (y % 2))) ? STONE : HWALL;
-#endif
-	    } else {
-		    levl[x][y].typ = filling;
+    opvar_free(init_style);
+    opvar_free(fg);
+    opvar_free(bg);
+    opvar_free(smoothed);
+    opvar_free(joined);
+    opvar_free(lit);
+    opvar_free(walled);
+    opvar_free(filling);
 	    }
+
+void
+spo_mon_generation(coder)
+     struct sp_coder *coder;
+{
+    struct opvar *freq, *n_tuples;
+    struct mon_gen_override *mg;
+    struct mon_gen_tuple *mgtuple;
+
+    if (level.mon_gen) {
+	impossible("monster generation override already defined.");
+	return;
     }
 
-    /* Start reading the file */
-    Fread((genericptr_t) &numpart, 1, sizeof(numpart), fd);
-						/* Number of parts */
-    if (!numpart || numpart > 9)
-	panic("load_maze error: numpart = %d", (int) numpart);
+    if (!OV_pop_i(n_tuples) ||
+	!OV_pop_i(freq)) return;
 
-    while (numpart--) {
-	Fread((genericptr_t) &halign, 1, sizeof(halign), fd);
-					/* Horizontal alignment */
-	Fread((genericptr_t) &valign, 1, sizeof(valign), fd);
-					/* Vertical alignment */
-	Fread((genericptr_t) &xsize, 1, sizeof(xsize), fd);
-					/* size in X */
-	Fread((genericptr_t) &ysize, 1, sizeof(ysize), fd);
-					/* size in Y */
-	switch((int) halign) {
-	    case LEFT:	    xstart = 3;					break;
-	    case H_LEFT:    xstart = 2+((x_maze_max-2-xsize)/4);	break;
-	    case CENTER:    xstart = 2+((x_maze_max-2-xsize)/2);	break;
-	    case H_RIGHT:   xstart = 2+((x_maze_max-2-xsize)*3/4);	break;
-	    case RIGHT:     xstart = x_maze_max-xsize-1;		break;
+    mg = (struct mon_gen_override *)alloc(sizeof(struct mon_gen_override));
+    mg->override_chance = OV_i(freq);
+    mg->total_mon_freq = 0;
+    mg->gen_chances = NULL;
+    while (OV_i(n_tuples)-- > 0) {
+	struct opvar *mfreq, *is_sym, *mon;
+	mgtuple = (struct mon_gen_tuple *)alloc(sizeof(struct mon_gen_tuple));
+
+	if (!OV_pop_i(is_sym) ||
+	    !OV_pop_i(mon) ||
+	    !OV_pop_i(mfreq)) {
+	    panic("oopsie when loading mon_gen chances.");
 	}
-	switch((int) valign) {
-	    case TOP:	    ystart = 3;					break;
-	    case CENTER:    ystart = 2+((y_maze_max-2-ysize)/2);	break;
-	    case BOTTOM:    ystart = y_maze_max-ysize-1;		break;
+
+	mgtuple->freq = OV_i(mfreq);
+	if (OV_i(mfreq) < 1) OV_i(mfreq) = 1;
+	mgtuple->is_sym = OV_i(is_sym);
+	if (OV_i(is_sym))
+	    mgtuple->monid = def_char_to_monclass(OV_i(mon));
+	else mgtuple->monid = OV_i(mon);
+	mgtuple->next = mg->gen_chances;
+	mg->gen_chances = mgtuple;
+	mg->total_mon_freq += OV_i(mfreq);
+	opvar_free(mfreq);
+	opvar_free(is_sym);
+	opvar_free(mon);
 	}
-	if (!(xstart % 2)) xstart++;
-	if (!(ystart % 2)) ystart++;
-	if ((ystart < 0) || (ystart + ysize > ROWNO)) {
-	    /* try to move the start a bit */
-	    ystart += (ystart > 0) ? -2 : 2;
-	    if(ysize == ROWNO) ystart = 0;
-	    if(ystart < 0 || ystart + ysize > ROWNO)
-		panic("reading special level with ysize too large");
+    level.mon_gen = mg;
+    opvar_free(freq);
+    opvar_free(n_tuples);
 	}
 
-	/*
-	 * If any CROSSWALLs are found, must change to ROOM after REGION's
-	 * are laid out.  CROSSWALLS are used to specify "invisible"
-	 * boundaries where DOOR syms look bad or aren't desirable.
-	 */
-	has_bounds = FALSE;
+void
+spo_level_sounds(coder)
+     struct sp_coder *coder;
+{
+    struct opvar *freq, *n_tuples;
+    struct lvl_sounds *mg;
+    struct lvl_sound_bite *mgtuple;
 
-	if(init_lev.init_present && xsize <= 1 && ysize <= 1) {
+    if (level.sounds) {
+	impossible("level sounds already defined.");
+	return;
+    }
+
+    if (!OV_pop_i(n_tuples)) return;
+
+    if (OV_i(n_tuples) < 1) {
+	impossible("no level sounds attached to the sound opcode?");
+    }
+
+    mg = (struct lvl_sounds *)alloc(sizeof(struct lvl_sounds));
+    mg->n_sounds = OV_i(n_tuples);
+    mg->sounds = (struct lvl_sound_bite *)alloc(sizeof(struct lvl_sound_bite) * mg->n_sounds);
+
+    while (OV_i(n_tuples)-- > 0) {
+	struct opvar *flags, *msg;
+
+	if (!OV_pop_i(flags) || !OV_pop_s(msg)) {
+	    panic("oopsie when loading lvl_sound_bite.");
+	}
+
+	mg->sounds[OV_i(n_tuples)].flags = OV_i(flags);
+	mg->sounds[OV_i(n_tuples)].msg = strdup(OV_s(msg));
+
+	opvar_free(flags);
+	opvar_free(msg);
+    }
+
+    if (!OV_pop_i(freq)) mg->freq = 1;
+    else mg->freq = OV_i(freq);
+    if (mg->freq < 0) mg->freq = -(mg->freq);
+
+    level.sounds = mg;
+
+    opvar_free(freq);
+    opvar_free(n_tuples);
+}
+
+void
+spo_engraving(coder)
+     struct sp_coder *coder;
+{
+    struct opvar *etyp, *txt, *coord;
+    engraving tmpe;
+
+    if (!OV_pop_i(etyp) ||
+	!OV_pop_s(txt) ||
+	!OV_pop_c(coord)) return;
+
+    tmpe.x = SP_COORD_X(OV_i(coord));
+    tmpe.y = SP_COORD_Y(OV_i(coord));
+    tmpe.engr.str = OV_s(txt);
+    tmpe.etype = OV_i(etyp);
+
+    create_engraving(&tmpe, coder->croom);
+
+    opvar_free(etyp);
+    opvar_free(txt);
+    opvar_free(coord);
+}
+
+void
+spo_room(coder)
+     struct sp_coder *coder;
+{
+    if (coder->n_subroom > MAX_NESTED_ROOMS)
+	panic("Too deeply nested rooms?!");
+    else {
+	struct opvar *filled, *h, *w, *yalign, *xalign,
+	    *y, *x, *rlit, *chance, *rtype;
+
+	room tmproom;
+	struct mkroom *tmpcr;
+
+	if (!OV_pop_i(h) ||
+	    !OV_pop_i(w) ||
+	    !OV_pop_i(y) ||
+	    !OV_pop_i(x) ||
+	    !OV_pop_i(yalign) ||
+	    !OV_pop_i(xalign) ||
+	    !OV_pop_i(filled) ||
+	    !OV_pop_i(rlit) ||
+	    !OV_pop_i(chance) ||
+	    !OV_pop_i(rtype)) return;
+
+
+	tmproom.x = OV_i(x);
+	tmproom.y = OV_i(y);
+	tmproom.w = OV_i(w);
+	tmproom.h = OV_i(h);
+	tmproom.xalign = OV_i(xalign);
+	tmproom.yalign = OV_i(yalign);
+	tmproom.rtype = OV_i(rtype);
+	tmproom.chance = OV_i(chance);
+	tmproom.rlit = OV_i(rlit);
+	tmproom.filled = OV_i(filled);
+
+	opvar_free(x);
+	opvar_free(y);
+	opvar_free(w);
+	opvar_free(h);
+	opvar_free(xalign);
+	opvar_free(yalign);
+	opvar_free(rtype);
+	opvar_free(chance);
+	opvar_free(rlit);
+	opvar_free(filled);
+
+	if (!coder->failed_room[coder->n_subroom-1]) {
+	    tmpcr = build_room(&tmproom, coder->croom);
+	    if (tmpcr) {
+		coder->tmproomlist[coder->n_subroom] = tmpcr;
+		coder->failed_room[coder->n_subroom] = FALSE;
+		coder->n_subroom++;
+		return;
+	    }
+	} /* failed to create parent room, so fail this too */
+    }
+    coder->tmproomlist[coder->n_subroom] = (struct mkroom *)0;
+    coder->failed_room[coder->n_subroom] = TRUE;
+    coder->n_subroom++;
+}
+
+void
+spo_endroom(coder)
+     struct sp_coder *coder;
+{
+    if (coder->n_subroom > 1) {
+	coder->n_subroom--;
+    } else {
+	/* no subroom, get out of top-level room */
+	/* Need to ensure xstart/ystart/xsize/ysize have something sensible,
+	   in case there's some stuff to be created outside the outermost room,
+	   and there's no MAP.
+	*/
+	if(xsize <= 1 && ysize <= 1) {
 	    xstart = 1;
 	    ystart = 0;
 	    xsize = COLNO-1;
 	    ysize = ROWNO;
+	}
+    }
+}
+
+void
+spo_stair(coder)
+     struct sp_coder *coder;
+{
+    xchar x,y;
+    struct opvar *up, *coord;
+    struct trap *badtrap;
+
+    if (!OV_pop_i(up) ||
+	!OV_pop_c(coord)) return;
+
+    x = SP_COORD_X(OV_i(coord));
+    y = SP_COORD_Y(OV_i(coord));
+
+    if (coder->croom) {
+	get_location(&x, &y, DRY, coder->croom);
+	mkstairs(x,y,(char)OV_i(up), coder->croom);
+	SpLev_Map[x][y] = 1;
 	} else {
-	    /* Load the map */
-	    for(y = ystart; y < ystart+ysize; y++)
-		for(x = xstart; x < xstart+xsize; x++) {
-		    levl[x][y].typ = Fgetc(fd);
-		    levl[x][y].lit = FALSE;
-		    /* clear out levl: load_common_data may set them */
-		    levl[x][y].flags = 0;
-		    levl[x][y].horizontal = 0;
-		    levl[x][y].roomno = 0;
-		    levl[x][y].edge = 0;
-		    /*
-		     * Note: Even though levl[x][y].typ is type schar,
-		     *	 lev_comp.y saves it as type char. Since schar != char
-		     *	 all the time we must make this exception or hack
-		     *	 through lev_comp.y to fix.
-		     */
+	get_location(&x, &y, DRY, coder->croom);
+	if ((badtrap = t_at(x,y)) != 0) deltrap(badtrap);
+	mkstairs(x, y, (char)OV_i(up), coder->croom);
+	SpLev_Map[x][y] = 1;
+    }
 
-		    /*
-		     *  Set secret doors to closed (why not trapped too?).  Set
-		     *  the horizontal bit.
-		     */
-		    if (levl[x][y].typ == SDOOR || IS_DOOR(levl[x][y].typ)) {
-			if(levl[x][y].typ == SDOOR)
-			    levl[x][y].doormask = D_CLOSED;
-			/*
-			 *  If there is a wall to the left that connects to a
-			 *  (secret) door, then it is horizontal.  This does
-			 *  not allow (secret) doors to be corners of rooms.
-			 */
-			if (x != xstart && (IS_WALL(levl[x-1][y].typ) ||
-					    levl[x-1][y].horizontal))
-			    levl[x][y].horizontal = 1;
-		    } else if(levl[x][y].typ == HWALL ||
-				levl[x][y].typ == IRONBARS)
-			levl[x][y].horizontal = 1;
-		    else if(levl[x][y].typ == LAVAPOOL)
-			levl[x][y].lit = 1;
-		    else if(levl[x][y].typ == CROSSWALL)
-			has_bounds = TRUE;
-		    Map[x][y] = 1;
+    opvar_free(coord);
+    opvar_free(up);
 		}
-	    if (init_lev.init_present && init_lev.joined)
-		remove_rooms(xstart, ystart, xstart+xsize, ystart+ysize);
+
+void
+spo_ladder(coder)
+     struct sp_coder *coder;
+{
+    xchar x,y;
+    struct opvar *up, *coord;
+
+    if (!OV_pop_i(up) ||
+	!OV_pop_c(coord)) return;
+
+    x = SP_COORD_X(OV_i(coord));
+    y = SP_COORD_Y(OV_i(coord));
+
+    get_location(&x, &y, DRY, coder->croom);
+
+    levl[x][y].typ = LADDER;
+    SpLev_Map[x][y] = 1;
+    if (OV_i(up)) {
+	xupladder = x; yupladder = y;
+	levl[x][y].ladder = LA_UP;
+    } else {
+	xdnladder = x; ydnladder = y;
+	levl[x][y].ladder = LA_DOWN;
+    }
+    opvar_free(coord);
+    opvar_free(up);
 	}
 
-	Fread((genericptr_t) &n, 1, sizeof(n), fd);
-						/* Number of level regions */
-	if(n) {
-	    if(num_lregions) {
-		/* realloc the lregion space to add the new ones */
-		/* don't really free it up until the whole level is done */
-		lev_region *newl = (lev_region *) alloc(sizeof(lev_region) *
-						(unsigned)(n+num_lregions));
-		(void) memcpy((genericptr_t)(newl+n), (genericptr_t)lregions,
-					sizeof(lev_region) * num_lregions);
-		Free(lregions);
-		num_lregions += n;
-		lregions = newl;
+void
+spo_grave(coder)
+     struct sp_coder *coder;
+{
+    struct opvar *coord, *typ, *txt;
+    schar x,y;
+    if (!OV_pop_i(typ) ||
+	!OV_pop_s(txt) ||
+	!OV_pop_c(coord)) return;
+
+    x = SP_COORD_X(OV_i(coord)); y = SP_COORD_Y(OV_i(coord));
+    get_location(&x, &y, DRY, coder->croom);
+
+    if (isok(x, y) && !t_at(x, y)) {
+	levl[x][y].typ = GRAVE;
+	switch (OV_i(typ)) {
+	case 2: make_grave(x, y, OV_s(txt)); break;
+	case 1: make_grave(x, y, NULL); break;
+	default: del_engr_at(x, y); break;
+	}
+    }
+
+    opvar_free(coord);
+    opvar_free(typ);
+    opvar_free(txt);
+}
+
+void
+spo_altar(coder)
+     struct sp_coder *coder;
+{
+    struct opvar *al, *shrine, *coord;
+    altar tmpaltar;
+
+    if (!OV_pop_i(al) ||
+	!OV_pop_i(shrine) ||
+	!OV_pop_c(coord)) return;
+
+    tmpaltar.x = SP_COORD_X(OV_i(coord));
+    tmpaltar.y = SP_COORD_Y(OV_i(coord));
+    tmpaltar.align = OV_i(al);
+    tmpaltar.shrine = OV_i(shrine);
+
+    create_altar(&tmpaltar, coder->croom);
+
+    opvar_free(coord);
+    opvar_free(shrine);
+    opvar_free(al);
+}
+
+void
+spo_wallwalk(coder)
+     struct sp_coder *coder;
+{
+    struct opvar *coord, *fgtyp, *bgtyp, *chance;
+    xchar x,y;
+
+    if (!OV_pop_i(chance) ||
+	!OV_pop_typ(bgtyp, SPOVAR_MAPCHAR) ||
+	!OV_pop_typ(fgtyp, SPOVAR_MAPCHAR) ||
+	!OV_pop_c(coord)) return;
+
+    x = SP_COORD_X(OV_i(coord));
+    y = SP_COORD_Y(OV_i(coord));
+    get_location(&x, &y, DRY|WET, coder->croom);
+
+    if (SP_MAPCHAR_TYP(OV_i(fgtyp)) >= MAX_TYPE) return;
+    if (SP_MAPCHAR_TYP(OV_i(bgtyp)) >= MAX_TYPE) return;
+
+    wallwalk_right(x, y, SP_MAPCHAR_TYP(OV_i(fgtyp)), SP_MAPCHAR_LIT(OV_i(fgtyp)), SP_MAPCHAR_TYP(OV_i(bgtyp)), OV_i(chance));
+
+    opvar_free(coord);
+    opvar_free(chance);
+    opvar_free(fgtyp);
+    opvar_free(bgtyp);
+}
+
+void
+spo_trap(coder)
+     struct sp_coder *coder;
+{
+    struct opvar *type;
+    struct opvar *coord;
+    trap tmptrap;
+
+    if (!OV_pop_i(type) ||
+	!OV_pop_c(coord)) return;
+
+    tmptrap.x = SP_COORD_X(OV_i(coord));
+    tmptrap.y = SP_COORD_Y(OV_i(coord));
+    tmptrap.type = OV_i(type);
+
+    create_trap(&tmptrap, coder->croom);
+    opvar_free(coord);
+    opvar_free(type);
+}
+
+void
+spo_gold(coder)
+     struct sp_coder *coder;
+{
+    struct opvar *coord, *amt;
+    gold tmpgold;
+    if (!OV_pop_c(coord) || !OV_pop_i(amt)) return;
+    tmpgold.x = SP_COORD_X(OV_i(coord));
+    tmpgold.y = SP_COORD_Y(OV_i(coord));
+    tmpgold.amount = OV_i(amt);
+    create_gold(&tmpgold, coder->croom);
+    opvar_free(coord);
+    opvar_free(amt);
+}
+
+void
+spo_corridor(coder)
+     struct sp_coder *coder;
+{
+    struct opvar *deswall, *desdoor, *desroom,
+	*srcwall, *srcdoor, *srcroom;
+    corridor tc;
+
+    if (!OV_pop_i(deswall) ||
+	!OV_pop_i(desdoor) ||
+	!OV_pop_i(desroom) ||
+	!OV_pop_i(srcwall) ||
+	!OV_pop_i(srcdoor) ||
+	!OV_pop_i(srcroom)) return;
+
+    tc.src.room = OV_i(srcroom);
+    tc.src.door = OV_i(srcdoor);
+    tc.src.wall = OV_i(srcwall);
+    tc.dest.room = OV_i(desroom);
+    tc.dest.door = OV_i(desdoor);
+    tc.dest.wall = OV_i(deswall);
+
+    create_corridor(&tc);
+
+    opvar_free(deswall);
+    opvar_free(desdoor);
+    opvar_free(desroom);
+    opvar_free(srcwall);
+    opvar_free(srcdoor);
+    opvar_free(srcroom);
+}
+
+struct opvar *
+selection_opvar(nbuf)
+     char *nbuf;
+{
+    struct opvar *ov;
+    char buf[(COLNO*ROWNO)+1];
+    int x,y,i = 0;
+
+    if (!nbuf) {
+	(void) memset(buf, 1, sizeof(buf));
+	buf[(COLNO*ROWNO)] = '\0';
+	ov = opvar_new_str(buf);
 	    } else {
-		num_lregions = n;
-		lregions = (lev_region *)
-				alloc(sizeof(lev_region) * (unsigned)n);
+	ov = opvar_new_str(nbuf);
 	    }
+    ov->spovartyp = SPOVAR_SEL;
+    return ov;
 	}
 
-	while(n--) {
-	    Fread((genericptr_t) &tmplregion, sizeof(tmplregion), 1, fd);
-	    if ((size = tmplregion.rname.len) != 0) {
-		tmplregion.rname.str = (char *) alloc((unsigned)size + 1);
-		Fread((genericptr_t) tmplregion.rname.str, size, 1, fd);
-		tmplregion.rname.str[size] = '\0';
-	    } else
-		tmplregion.rname.str = (char *) 0;
-	    if(!tmplregion.in_islev) {
-		get_location(&tmplregion.inarea.x1, &tmplregion.inarea.y1,
-								DRY|WET);
-		get_location(&tmplregion.inarea.x2, &tmplregion.inarea.y2,
-								DRY|WET);
+char
+selection_getpoint(x,y,ov)
+     int x,y;
+     struct opvar *ov;
+{
+    if (!ov || ov->spovartyp != SPOVAR_SEL) return 0;
+    if (x < 0 || y < 0 || x >= COLNO || y >= ROWNO) return 0;
+
+    return (ov->vardata.str[COLNO*y + x] - 1);
 	    }
-	    if(!tmplregion.del_islev) {
-		get_location(&tmplregion.delarea.x1, &tmplregion.delarea.y1,
-								DRY|WET);
-		get_location(&tmplregion.delarea.x2, &tmplregion.delarea.y2,
-								DRY|WET);
+
+void
+selection_setpoint(x,y,ov, c)
+     int x,y;
+     struct opvar *ov;
+     char c;
+{
+    if (!ov || ov->spovartyp != SPOVAR_SEL) return;
+    if (x < 0 || y < 0 || x >= COLNO || y >= ROWNO) return;
+
+    ov->vardata.str[COLNO*y + x] = (c + 1);
+}
+
+struct opvar *
+selection_logical_oper(s1, s2, oper)
+     struct opvar *s1, *s2;
+     char oper;
+{
+    struct opvar *ov;
+    int x,y;
+
+    ov = selection_opvar(NULL);
+    if (!ov) return NULL;
+
+    for (x = 0; x < COLNO; x++)
+	for (y = 0; y < ROWNO; y++) {
+	    switch (oper) {
+	    default:
+	    case '|':
+		if (selection_getpoint(x,y,s1) || selection_getpoint(x,y,s2))
+		    selection_setpoint(x,y,ov,1);
+		break;
+	    case '&':
+		if (selection_getpoint(x,y,s1) && selection_getpoint(x,y,s2))
+		    selection_setpoint(x,y,ov,1);
+		break;
 	    }
-	    lregions[(int)n] = tmplregion;
 	}
 
-	Fread((genericptr_t) &n, 1, sizeof(n), fd);
-						/* Random objects */
-	if(n) {
-		Fread((genericptr_t)robjects, sizeof(*robjects), (int) n, fd);
-		sp_lev_shuffle(robjects, (char *)0, (int)n);
+    return ov;
 	}
 
-	Fread((genericptr_t) &n, 1, sizeof(n), fd);
-						/* Random locations */
-	if(n) {
-		Fread((genericptr_t)rloc_x, sizeof(*rloc_x), (int) n, fd);
-		Fread((genericptr_t)rloc_y, sizeof(*rloc_y), (int) n, fd);
-		sp_lev_shuffle(rloc_x, rloc_y, (int)n);
+
+
+void
+selection_filter_percent(ov, percent)
+    struct opvar *ov;
+    int percent;
+{
+    int x,y;
+    if (!ov) return;
+    for (x = 0; x < COLNO; x++)
+	for (y = 0; y < ROWNO; y++)
+	    if (selection_getpoint(x,y,ov) && (rn2(100) >= percent))
+		selection_setpoint(x,y,ov,0);
 	}
 
-	Fread((genericptr_t) &n, 1, sizeof(n), fd);
-						/* Random monsters */
-	if(n) {
-		Fread((genericptr_t)rmonst, sizeof(*rmonst), (int) n, fd);
-		sp_lev_shuffle(rmonst, (char *)0, (int)n);
+int
+selection_rndcoord(ov, x,y)
+    struct opvar *ov;
+    schar *x, *y;
+{
+    struct opvar *coord;
+    int idx = 0;
+    int c;
+    int dx,dy;
+
+    for (dx = 0; dx < COLNO; dx++)
+	for (dy = 0; dy < ROWNO; dy++)
+	    if (isok(dx,dy) && selection_getpoint(dx,dy,ov)) idx++;
+
+    if (idx) {
+	c = rn2(idx);
+	for (dx = 0; dx < COLNO; dx++)
+	    for (dy = 0; dy < ROWNO; dy++)
+		if (isok(dx,dy) && selection_getpoint(dx,dy, ov)) {
+		    if (!c) {
+			*x = dx;
+			*y = dy;
+			return 1;
+		    }
+		    c--;
+		}
+    }
+    *x = *y = -1;
+    return 0;
 	}
 
-	(void) memset((genericptr_t)mustfill, 0, sizeof(mustfill));
-	Fread((genericptr_t) &n, 1, sizeof(n), fd);
-						/* Number of subrooms */
-	while(n--) {
-		register struct mkroom *troom;
+void
+selection_do_grow(ov, dir)
+     struct opvar *ov;
+     int dir;
+{
+    int x,y, c;
+    char tmp[COLNO][ROWNO];
 
-		Fread((genericptr_t)&tmpregion, 1, sizeof(tmpregion), fd);
+    if (ov->spovartyp != SPOVAR_SEL) return;
+    if (!ov) return;
 
-		if(tmpregion.rtype > MAXRTYPE) {
-		    tmpregion.rtype -= MAXRTYPE+1;
-		    prefilled = TRUE;
-		} else
-		    prefilled = FALSE;
+    (void) memset(tmp, 0, sizeof(tmp));
 
-		if(tmpregion.rlit < 0)
-		    tmpregion.rlit = (rnd(1+abs(depth(&u.uz))) < 11 && rn2(77))
-			? TRUE : FALSE;
+    for (x = 0; x < COLNO; x++)
+	for (y = 0; y < ROWNO; y++) {
+	    c = 0;
+	    if ((dir & W_WEST) && (x > 0) && (selection_getpoint(x-1,y, ov))) c++;
+	    if ((dir & (W_WEST|W_NORTH)) && (x > 0) && (y > 0) && (selection_getpoint(x-1,y-1, ov))) c++;
+	    if ((dir & W_NORTH) && (y > 0) && (selection_getpoint(x,y-1, ov))) c++;
+	    if ((dir & (W_NORTH|W_EAST)) && (y > 0) && (x < COLNO-1) && (selection_getpoint(x+1,y-1, ov))) c++;
+	    if ((dir & W_EAST) && (x < COLNO-1) && (selection_getpoint(x+1,y, ov))) c++;
+	    if ((dir & (W_EAST|W_SOUTH)) && (x < COLNO-1) && (y < ROWNO-1) && (selection_getpoint(x+1,y+1, ov))) c++;
+	    if ((dir & W_SOUTH) && (y < ROWNO-1) && (selection_getpoint(x,y+1, ov))) c++;
+	    if ((dir & (W_SOUTH|W_WEST)) && (y < ROWNO-1) && (x > 0) && (selection_getpoint(x-1,y+1, ov))) c++;
+	    if (c) tmp[x][y] = 1;
+	}
 
-		get_location(&tmpregion.x1, &tmpregion.y1, DRY|WET);
-		get_location(&tmpregion.x2, &tmpregion.y2, DRY|WET);
+    for (x = 0; x < COLNO; x++)
+	for (y = 0; y < ROWNO; y++)
+	    if (tmp[x][y]) selection_setpoint(x,y,ov,1);
+}
 
-		/* for an ordinary room, `prefilled' is a flag to force
-		   an actual room to be created (such rooms are used to
-		   control placement of migrating monster arrivals) */
-		room_not_needed = (tmpregion.rtype == OROOM &&
-				   !tmpregion.rirreg && !prefilled);
-		if (room_not_needed || nroom >= MAXNROFROOMS) {
-		    if (!room_not_needed)
-			impossible("Too many rooms on new level!");
-		    light_region(&tmpregion);
-		    continue;
+void
+selection_floodfill(ov, x,y)
+     struct opvar *ov;
+     int x,y;
+{
+    struct opvar *tmp = selection_opvar(NULL);
+#define SEL_FLOOD_STACK (COLNO*ROWNO)
+#define SEL_FLOOD(nx,ny) {if (idx<SEL_FLOOD_STACK) { dx[idx]=(nx); dy[idx]=(ny); idx++; } else panic("floodfill stack overrun");}
+    int idx = 0;
+    xchar dx[SEL_FLOOD_STACK];
+    xchar dy[SEL_FLOOD_STACK];
+    schar under = levl[x][y].typ;
+    SEL_FLOOD(x,y);
+    do {
+	idx--;
+	x = dx[idx];
+	y = dy[idx];
+	if (isok(x,y)) {
+	    selection_setpoint(x,y, ov, 1);
+	    selection_setpoint(x,y, tmp, 1);
+	}
+	if (isok(x+1,y) && (levl[x+1][y].typ == under) && !selection_getpoint(x+1,y,tmp)) SEL_FLOOD(x+1, y);
+	if (isok(x-1,y) && (levl[x-1][y].typ == under) && !selection_getpoint(x-1,y,tmp)) SEL_FLOOD(x-1, y);
+	if (isok(x,y+1) && (levl[x][y+1].typ == under) && !selection_getpoint(x,y+1,tmp)) SEL_FLOOD(x, y+1);
+	if (isok(x,y-1) && (levl[x][y-1].typ == under) && !selection_getpoint(x,y-1,tmp)) SEL_FLOOD(x, y-1);
+    } while (idx > 0);
+#undef SEL_FLOOD
+#undef SEL_FLOOD_STACK
+    opvar_free(tmp);
 		}
 
-		troom = &rooms[nroom];
+/* McIlroy's Ellipse Algorithm */
+void
+selection_do_ellipse(ov, xc,yc, a,b, filled)
+    struct opvar *ov;
+    int xc,yc,a,b,filled;
+{                       /* e(x,y) = b^2*x^2 + a^2*y^2 - a^2*b^2 */
+    int x = 0, y = b;
+    long a2 = (long)a*a, b2 = (long)b*b;
+    long crit1 = -(a2/4 + a%2 + b2);
+    long crit2 = -(b2/4 + b%2 + a2);
+    long crit3 = -(b2/4 + b%2);
+    long t = -a2*y; /* e(x+1/2,y-1/2) - (a^2+b^2)/4 */
+    long dxt = 2*b2*x, dyt = -2*a2*y;
+    long d2xt = 2*b2, d2yt = 2*a2;
+    long width = 1;
+    long i;
 
-		/* mark rooms that must be filled, but do it later */
-		if (tmpregion.rtype != OROOM)
-		    mustfill[nroom] = (prefilled ? 2 : 1);
+    if (!ov) return;
 
-		if(tmpregion.rirreg) {
-		    min_rx = max_rx = tmpregion.x1;
-		    min_ry = max_ry = tmpregion.y1;
-		    flood_fill_rm(tmpregion.x1, tmpregion.y1,
-				  nroom+ROOMOFFSET, tmpregion.rlit, TRUE);
-		    add_room(min_rx, min_ry, max_rx, max_ry,
-			     FALSE, tmpregion.rtype, TRUE);
-		    troom->rlit = tmpregion.rlit;
-		    troom->irregular = TRUE;
+    filled = !filled;
+
+    if (!filled) {
+	while (y>=0 && x<=a) {
+	    selection_setpoint(xc+x, yc+y, ov, 1);
+	    if (x!=0 || y!=0)
+		selection_setpoint(xc-x, yc-y, ov, 1);
+	    if (x!=0 && y!=0) {
+		selection_setpoint(xc+x, yc-y, ov, 1);
+		selection_setpoint(xc-x, yc+y, ov, 1);
+	    }
+	    if (t + b2*x <= crit1 ||   /* e(x+1,y-1/2) <= 0 */
+		t + a2*y <= crit3) {     /* e(x+1/2,y) <= 0 */
+		x++; dxt += d2xt; t += dxt;
+	    } else if (t - a2*y > crit2) { /* e(x+1/2,y-1) > 0 */
+		y--; dyt += d2yt; t += dyt;
 		} else {
-		    add_room(tmpregion.x1, tmpregion.y1,
-			     tmpregion.x2, tmpregion.y2,
-			     tmpregion.rlit, tmpregion.rtype, TRUE);
-#ifdef SPECIALIZATION
-		    topologize(troom,FALSE);		/* set roomno */
-#else
-		    topologize(troom);			/* set roomno */
-#endif
+		x++; dxt += d2xt; t += dxt;
+		y--; dyt += d2yt; t += dyt;
+	    }
+	}
+    } else {
+	while (y>=0 && x<=a) {
+	    if (t + b2*x <= crit1 ||   /* e(x+1,y-1/2) <= 0 */
+		t + a2*y <= crit3) {     /* e(x+1/2,y) <= 0 */
+		x++; dxt += d2xt; t += dxt;
+		width += 2;
+	    } else if (t - a2*y > crit2) { /* e(x+1/2,y-1) > 0 */
+		for (i = 0; i < width; i++) selection_setpoint(xc-x+i, yc-y, ov, 1);
+		if (y!=0)
+		    for (i = 0; i < width; i++) selection_setpoint(xc-x+i, yc+y, ov, 1);
+		y--; dyt += d2yt; t += dyt;
+	    } else {
+		for (i = 0; i < width; i++) selection_setpoint(xc-x+i, yc-y, ov, 1);
+		if (y!=0)
+		    for (i = 0; i < width; i++) selection_setpoint(xc-x+i, yc+y, ov, 1);
+		x++; dxt += d2xt; t += dxt;
+		y--; dyt += d2yt; t += dyt;
+		width += 2;
+	    }
+	}
 		}
 	}
 
-	Fread((genericptr_t) &n, 1, sizeof(n), fd);
-						/* Number of doors */
-	while(n--) {
-		struct mkroom *croom = &rooms[0];
 
-		Fread((genericptr_t)&tmpdoor, 1, sizeof(tmpdoor), fd);
 
-		x = tmpdoor.x;	y = tmpdoor.y;
-		typ = tmpdoor.mask == -1 ? rnddoor() : tmpdoor.mask;
+void
+selection_do_line(x1,y1,x2,y2, ov) /* bresenham line algo */
+     schar x1,y1,x2,y2;
+     struct opvar *ov;
+{
+    int d,dx,dy,ai,bi,xi,yi;
 
-		get_location(&x, &y, DRY);
-		if(levl[x][y].typ != SDOOR)
-			levl[x][y].typ = DOOR;
-		else {
+    if (x1 < x2) {
+	xi = 1;
+	dx = x2 - x1;
+    } else {
+	xi = - 1;
+	dx = x1 - x2;
+    }
+
+    if (y1 < y2) {
+	yi = 1;
+	dy = y2 - y1;
+    } else {
+	yi = - 1;
+	dy = y1 - y2;
+    }
+
+    selection_setpoint(x1,y1, ov, 1);
+
+    if (dx > dy) {
+	ai = (dy - dx) * 2;
+	bi = dy * 2;
+	d  = bi - dx;
+	do {
+	    if (d >= 0) {
+		y1 += yi;
+		d += ai;
+	    } else d += bi;
+	    x1 += xi;
+	    selection_setpoint(x1,y1, ov, 1);
+	} while (x1 != x2);
+    } else {
+	ai = (dx - dy) * 2;
+	bi = dx * 2;
+	d  = bi - dy;
+	do {
+	    if (d >= 0) {
+		x1 += xi;
+		d += ai;
+	    } else d += bi;
+	    y1 += yi;
+	    selection_setpoint(x1,y1, ov, 1);
+	} while (y1 != y2);
+    }
+}
+
+void
+selection_do_randline(x1,y1,x2,y2,rough, rec, ov)
+     schar x1,y1,x2,y2,rough,rec;
+     struct opvar *ov;
+{
+    int mx, my;
+    int dx, dy;
+
+    if (rec < 1) {
+	return;
+    }
+
+    if ((x2 == x1) && (y2 == y1)) {
+	selection_setpoint(x1,y1, ov, 1);
+	return;
+    }
+
+    if (rough > max(abs(x2-x1), abs(y2-y1)))
+	rough = max(abs(x2-x1), abs(y2-y1));
+
+    if (rough < 2) {
+	mx = ((x1 + x2) / 2);
+	my = ((y1 + y2) / 2);
+    } else {
+	do {
+	    dx = (rand() % rough) - (rough / 2);
+	    dy = (rand() % rough) - (rough / 2);
+	    mx = ((x1 + x2) / 2) + dx;
+	    my = ((y1 + y2) / 2) + dy;
+	} while ((mx > COLNO-1 || mx < 0 || my < 0 || my > ROWNO-1));
+    }
+
+    selection_setpoint(mx,my, ov, 1);
+
+    rough = (rough * 2) / 3;
+
+    rec--;
+
+    selection_do_randline(x1,y1,mx,my, rough, rec, ov);
+    selection_do_randline(mx,my,x2,y2, rough, rec, ov);
+}
+
+
+void
+selection_iterate(ov, func, arg)
+     struct opvar *ov;
+     void FDECL((*func), (int,int,genericptr_t));
+     genericptr_t arg;
+{
+    int x,y;
+    /* yes, this is very naive, but it's not _that_ expensive. */
+    for (x = 0; x < COLNO; x++)
+	for (y = 0; y < ROWNO; y++)
+	    if (selection_getpoint(x,y, ov)) (*func)(x,y, arg);
+}
+
+void
+sel_set_ter(x,y,arg)
+     int x,y;
+     genericptr_t arg;
+{
+    terrain terr;
+    terr = (*(terrain *)arg);
+    SET_TYPLIT(x,y, terr.ter, terr.tlit);
+    /* handle doors and secret doors */
+    if (levl[x][y].typ == SDOOR || IS_DOOR(levl[x][y].typ)) {
+	if(levl[x][y].typ == SDOOR)
+	    levl[x][y].doormask = D_CLOSED;
+	if (x && (IS_WALL(levl[x-1][y].typ) ||
+		  levl[x-1][y].horizontal))
+	    levl[x][y].horizontal = 1;
+    }
+}
+
+void
+sel_set_feature(x,y,arg)
+     int x,y;
+     genericptr_t arg;
+{
+    if (IS_FURNITURE(levl[x][y].typ)) return;
+    levl[x][y].typ = (*(int *)arg);
+}
+
+void
+sel_set_door(dx,dy,arg)
+     int dx,dy;
+     genericptr_t arg;
+{
+    xchar typ = (*(xchar *)arg);
+    xchar x = dx;
+    xchar y = dy;
+    struct mkroom *droom;
+    droom = &rooms[0];
+    /*get_location(&x, &y, DRY, (struct mkroom *)0);*/
+    if (!IS_DOOR(levl[x][y].typ) && levl[x][y].typ != SDOOR)
+	levl[x][y].typ = (typ & D_SECRET) ? SDOOR : DOOR;
+    if (typ & D_SECRET) {
+	typ &= ~D_SECRET;
 			if(typ < D_CLOSED)
-			    typ = D_CLOSED; /* force it to be closed */
+	    typ = D_CLOSED;
 		}
 		levl[x][y].doormask = typ;
+    /*SpLev_Map[x][y] = 1;*/
 
 		/* Now the complicated part, list it with each subroom */
 		/* The dog move and mail daemon routines use this */
-		while(croom->hx >= 0 && doorindex < DOORMAX) {
-		    if(croom->hx >= x-1 && croom->lx <= x+1 &&
-		       croom->hy >= y-1 && croom->ly <= y+1) {
+    while(droom->hx >= 0 && doorindex < DOORMAX) {
+	if(droom->hx >= x-1 && droom->lx <= x+1 &&
+	   droom->hy >= y-1 && droom->ly <= y+1) {
 			/* Found it */
-			add_door(x, y, croom);
+	    add_door(x, y, droom);
 		    }
-		    croom++;
+	droom++;
 		}
+
 	}
 
-	/* now that we have rooms _and_ associated doors, fill the rooms */
-	for(n = 0; n < SIZE(mustfill); n++)
-	    if(mustfill[(int)n])
-		fill_room(&rooms[(int)n], (mustfill[(int)n] == 2));
+void
+spo_door(coder)
+     struct sp_coder *coder;
+{
+    struct opvar *msk, *sel;
+    xchar typ;
 
-	/* if special boundary syms (CROSSWALL) in map, remove them now */
-	if(has_bounds) {
-	    for(x = xstart; x < xstart+xsize; x++)
-		for(y = ystart; y < ystart+ysize; y++)
-		    if(levl[x][y].typ == CROSSWALL)
-			levl[x][y].typ = ROOM;
+    if (!OV_pop_i(msk) ||
+	!OV_pop_typ(sel, SPOVAR_SEL)) return;
+
+    typ = OV_i(msk) == -1 ? rnddoor() : (xchar)OV_i(msk);
+
+    selection_iterate(sel, sel_set_door, (genericptr_t)&typ);
+
+    opvar_free(sel);
+    opvar_free(msk);
 	}
 
-	Fread((genericptr_t) &n, 1, sizeof(n), fd);
-						/* Number of drawbridges */
-	while(n--) {
-		Fread((genericptr_t)&tmpdb, 1, sizeof(tmpdb), fd);
+void
+spo_feature(coder)
+     struct sp_coder *coder;
+{
+    struct opvar *sel;
+    int typ;
 
-		x = tmpdb.x;  y = tmpdb.y;
-		get_location(&x, &y, DRY|WET);
+    if (!OV_pop_typ(sel, SPOVAR_SEL)) return;
 
-		if (!create_drawbridge(x, y, tmpdb.dir, tmpdb.db_open))
-		    impossible("Cannot create drawbridge.");
+    switch (coder->opcode) {
+    default: impossible("spo_feature called with wrong opcode %i.", coder->opcode); break;
+    case SPO_FOUNTAIN: typ = FOUNTAIN; break;
+    case SPO_SINK:     typ = SINK;     break;
+    case SPO_POOL:     typ = POOL;     break;
+    }
+    selection_iterate(sel, sel_set_feature, (genericptr_t)&typ);
+    opvar_free(sel);
 	}
 
-	Fread((genericptr_t) &n, 1, sizeof(n), fd);
-						/* Number of mazewalks */
-	while(n--) {
-		Fread((genericptr_t)&tmpwalk, 1, sizeof(tmpwalk), fd);
+void
+spo_terrain(coder)
+     struct sp_coder *coder;
+{
+    terrain tmpterrain;
+    struct opvar *ter, *sel;
 
-		get_location(&tmpwalk.x, &tmpwalk.y, DRY|WET);
+    if (!OV_pop_typ(ter, SPOVAR_MAPCHAR) ||
+	!OV_pop_typ(sel, SPOVAR_SEL)) return;
 
-		walklist[nwalk++] = tmpwalk;
+    tmpterrain.ter = SP_MAPCHAR_TYP(OV_i(ter));
+    tmpterrain.tlit = SP_MAPCHAR_LIT(OV_i(ter));
+    selection_iterate(sel, sel_set_ter, (genericptr_t)&tmpterrain);
+
+    opvar_free(ter);
+    opvar_free(sel);
 	}
 
-	Fread((genericptr_t) &n, 1, sizeof(n), fd);
-						/* Number of non_diggables */
-	while(n--) {
-		Fread((genericptr_t)&tmpdig, 1, sizeof(tmpdig), fd);
+void
+spo_replace_terrain(coder)
+     struct sp_coder *coder;
+{
+    replaceterrain rt;
+    struct opvar *reg,*from_ter,*to_ter,*chance;
 
-		get_location(&tmpdig.x1, &tmpdig.y1, DRY|WET);
-		get_location(&tmpdig.x2, &tmpdig.y2, DRY|WET);
+    if (!OV_pop_i(chance) ||
+	!OV_pop_typ(to_ter, SPOVAR_MAPCHAR) ||
+	!OV_pop_typ(from_ter, SPOVAR_MAPCHAR) ||
+	!OV_pop_r(reg)) return;
 
-		set_wall_property(tmpdig.x1, tmpdig.y1,
-				  tmpdig.x2, tmpdig.y2, W_NONDIGGABLE);
+    rt.chance = OV_i(chance);
+    rt.tolit = SP_MAPCHAR_LIT(OV_i(to_ter));
+    rt.toter = SP_MAPCHAR_TYP(OV_i(to_ter));
+    rt.fromter = SP_MAPCHAR_TYP(OV_i(from_ter));
+    /* TODO: use SP_MAPCHAR_LIT(OV_i(from_ter)) too */
+    rt.x1 = SP_REGION_X1(OV_i(reg));
+    rt.y1 = SP_REGION_Y1(OV_i(reg));
+    rt.x2 = SP_REGION_X2(OV_i(reg));
+    rt.y2 = SP_REGION_Y2(OV_i(reg));
+
+    replace_terrain(&rt, coder->croom);
+
+    opvar_free(reg);
+    opvar_free(from_ter);
+    opvar_free(to_ter);
+    opvar_free(chance);
 	}
 
-	Fread((genericptr_t) &n, 1, sizeof(n), fd);
-						/* Number of non_passables */
-	while(n--) {
-		Fread((genericptr_t)&tmpdig, 1, sizeof(tmpdig), fd);
+void
+spo_spill(coder)
+     struct sp_coder *coder;
+{
+    spill sp;
+    struct opvar *coord,*typ,*dir,*count,*lit;
+    if (!OV_pop_i(lit) ||
+	!OV_pop_i(count) ||
+	!OV_pop_i(dir) ||
+	!OV_pop_i(typ) ||
+	!OV_pop_c(coord)) return;
 
-		get_location(&tmpdig.x1, &tmpdig.y1, DRY|WET);
-		get_location(&tmpdig.x2, &tmpdig.y2, DRY|WET);
+    sp.x = SP_COORD_X(OV_i(coord));
+    sp.y = SP_COORD_Y(OV_i(coord));
 
-		set_wall_property(tmpdig.x1, tmpdig.y1,
-				  tmpdig.x2, tmpdig.y2, W_NONPASSWALL);
+    sp.lit = OV_i(lit);
+    sp.count = OV_i(count);
+    sp.direction = OV_i(dir);
+    sp.typ = OV_i(typ);
+
+    spill_terrain(&sp, coder->croom);
+
+    opvar_free(coord);
+    opvar_free(typ);
+    opvar_free(dir);
+    opvar_free(count);
+    opvar_free(lit);
 	}
 
-	Fread((genericptr_t) &n, 1, sizeof(n), fd);
-						/* Number of ladders */
-	while(n--) {
-		Fread((genericptr_t)&tmplad, 1, sizeof(tmplad), fd);
+void
+spo_levregion(coder)
+     struct sp_coder *coder;
+{
+    struct opvar *rname, *padding, *rtype,
+	*del_islev, *dy2, *dx2, *dy1, *dx1,
+	*in_islev,  *iy2, *ix2, *iy1, *ix1;
 
-		x = tmplad.x;  y = tmplad.y;
-		get_location(&x, &y, DRY);
+    lev_region *tmplregion;
 
-		levl[x][y].typ = LADDER;
-		if (tmplad.up == 1) {
-			xupladder = x;	yupladder = y;
-			levl[x][y].ladder = LA_UP;
-		} else {
-			xdnladder = x;	ydnladder = y;
-			levl[x][y].ladder = LA_DOWN;
+    if (!OV_pop_s(rname) ||
+	!OV_pop_i(padding) ||
+	!OV_pop_i(rtype) ||
+	!OV_pop_i(del_islev) ||
+	!OV_pop_i(dy2) ||
+	!OV_pop_i(dx2) ||
+	!OV_pop_i(dy1) ||
+	!OV_pop_i(dx1) ||
+	!OV_pop_i(in_islev) ||
+	!OV_pop_i(iy2) ||
+	!OV_pop_i(ix2) ||
+	!OV_pop_i(iy1) ||
+	!OV_pop_i(ix1)) return;
+
+    tmplregion = (lev_region *)alloc(sizeof(lev_region));
+
+    tmplregion->inarea.x1 = OV_i(ix1);
+    tmplregion->inarea.y1 = OV_i(iy1);
+    tmplregion->inarea.x2 = OV_i(ix2);
+    tmplregion->inarea.y2 = OV_i(iy2);
+
+    tmplregion->delarea.x1 = OV_i(dx1);
+    tmplregion->delarea.y1 = OV_i(dy1);
+    tmplregion->delarea.x2 = OV_i(dx2);
+    tmplregion->delarea.y2 = OV_i(dy2);
+
+    tmplregion->in_islev = OV_i(in_islev);
+    tmplregion->del_islev = OV_i(del_islev);
+    tmplregion->rtype = OV_i(rtype);
+    tmplregion->padding = OV_i(padding);
+    tmplregion->rname.str = strdup(OV_s(rname));
+
+    if(!tmplregion->in_islev) {
+	get_location(&tmplregion->inarea.x1, &tmplregion->inarea.y1,
+		     DRY|WET, (struct mkroom *)0);
+	get_location(&tmplregion->inarea.x2, &tmplregion->inarea.y2,
+		     DRY|WET, (struct mkroom *)0);
+    }
+
+    if(!tmplregion->del_islev) {
+	get_location(&tmplregion->delarea.x1, &tmplregion->delarea.y1,
+		     DRY|WET, (struct mkroom *)0);
+	get_location(&tmplregion->delarea.x2, &tmplregion->delarea.y2,
+		     DRY|WET, (struct mkroom *)0);
 		}
+    if(num_lregions) {
+	/* realloc the lregion space to add the new one */
+	lev_region *newl = (lev_region *) alloc(sizeof(lev_region) *
+						(unsigned)(1+num_lregions));
+	(void) memcpy((genericptr_t)(newl), (genericptr_t)lregions,
+		      sizeof(lev_region) * num_lregions);
+	Free(lregions);
+	num_lregions++;
+	lregions = newl;
+    } else {
+	num_lregions = 1;
+	lregions = (lev_region *) alloc(sizeof(lev_region));
 	}
+    (void) memcpy(&lregions[num_lregions-1], tmplregion, sizeof(lev_region));
 
-	prevstair.x = prevstair.y = 0;
-	Fread((genericptr_t) &n, 1, sizeof(n), fd);
-						/* Number of stairs */
-	while(n--) {
-		Fread((genericptr_t)&tmpstair, 1, sizeof(tmpstair), fd);
+    opvar_free(dx1);
+    opvar_free(dy1);
+    opvar_free(dx2);
+    opvar_free(dy2);
 
-		xi = 0;
-		do {
-		    x = tmpstair.x;  y = tmpstair.y;
-		    get_location(&x, &y, DRY);
-		} while(prevstair.x && xi++ < 100 &&
-			distmin(x,y,prevstair.x,prevstair.y) <= 8);
-		if ((badtrap = t_at(x,y)) != 0) deltrap(badtrap);
-		mkstairs(x, y, (char)tmpstair.up, (struct mkroom *)0);
-		prevstair.x = x;
-		prevstair.y = y;
+    opvar_free(ix1);
+    opvar_free(iy1);
+    opvar_free(ix2);
+    opvar_free(iy2);
+
+    opvar_free(del_islev);
+    opvar_free(in_islev);
+    opvar_free(rname);
+    opvar_free(rtype);
+    opvar_free(padding);
 	}
 
-	Fread((genericptr_t) &n, 1, sizeof(n), fd);
-						/* Number of altars */
-	while(n--) {
-		Fread((genericptr_t)&tmpaltar, 1, sizeof(tmpaltar), fd);
+void
+spo_region(coder)
+     struct sp_coder *coder;
+{
+    struct opvar *rtype, *rlit, *rirreg, *area;
+    xchar dx1,dy1,dx2,dy2;
+    register struct mkroom *troom;
+    boolean prefilled, room_not_needed;
 
-		create_altar(&tmpaltar, (struct mkroom *)0);
-	}
+    if (!OV_pop_i(rirreg) ||
+	!OV_pop_i(rtype) ||
+	!OV_pop_i(rlit) ||
+	!OV_pop_r(area)) return;
 
-	Fread((genericptr_t) &n, 1, sizeof(n), fd);
-						/* Number of fountains */
-	while (n--) {
-		Fread((genericptr_t)&tmpfountain, 1, sizeof(tmpfountain), fd);
+    if(OV_i(rtype) > MAXRTYPE) {
+	OV_i(rtype) -= MAXRTYPE+1;
+	prefilled = TRUE;
+    } else
+	prefilled = FALSE;
 
-		create_feature(tmpfountain.x, tmpfountain.y,
-			       (struct mkroom *)0, FOUNTAIN);
-	}
+    if(OV_i(rlit) < 0)
+	OV_i(rlit) = (rnd(1+abs(depth(&u.uz))) < 11 && rn2(77))
+	    ? TRUE : FALSE;
 
-	Fread((genericptr_t) &n, 1, sizeof(n), fd);
-						/* Number of traps */
-	while(n--) {
-		Fread((genericptr_t)&tmptrap, 1, sizeof(tmptrap), fd);
+    dx1 = SP_REGION_X1(OV_i(area));
+    dy1 = SP_REGION_Y1(OV_i(area));
+    dx2 = SP_REGION_X2(OV_i(area));
+    dy2 = SP_REGION_Y2(OV_i(area));
 
-		create_trap(&tmptrap, (struct mkroom *)0);
-	}
+    get_location(&dx1, &dy1, DRY|WET, (struct mkroom *)0);
+    get_location(&dx2, &dy2, DRY|WET, (struct mkroom *)0);
 
-	Fread((genericptr_t) &n, 1, sizeof(n), fd);
-						/* Number of monsters */
-	while(n--) {
-		load_one_monster(fd, &tmpmons);
+    /* for an ordinary room, `prefilled' is a flag to force
+       an actual room to be created (such rooms are used to
+       control placement of migrating monster arrivals) */
+    room_not_needed = (OV_i(rtype) == OROOM &&
+		       !OV_i(rirreg) && !prefilled);
+    if (room_not_needed || nroom >= MAXNROFROOMS) {
+	region tmpregion;
+	if (!room_not_needed)
+	    impossible("Too many rooms on new level!");
+	tmpregion.rlit = OV_i(rlit);
+	tmpregion.x1 = dx1;
+	tmpregion.y1 = dy1;
+	tmpregion.x2 = dx2;
+	tmpregion.y2 = dy2;
+	light_region(&tmpregion);
 
-		create_monster(&tmpmons, (struct mkroom *)0);
+	opvar_free(area);
+	opvar_free(rirreg);
+	opvar_free(rlit);
+	opvar_free(rtype);
+
+	return;
 	}
 
-	Fread((genericptr_t) &n, 1, sizeof(n), fd);
-						/* Number of objects */
-	while(n--) {
-		load_one_object(fd, &tmpobj);
+    troom = &rooms[nroom];
 
-		create_object(&tmpobj, (struct mkroom *)0);
+    /* mark rooms that must be filled, but do it later */
+    if (OV_i(rtype) != OROOM)
+	troom->needfill = (prefilled ? 2 : 1);
+
+    if (OV_i(rirreg)) {
+	min_rx = max_rx = dx1;
+	min_ry = max_ry = dy1;
+	flood_fill_rm(dx1, dy1, nroom+ROOMOFFSET,
+		      OV_i(rlit), TRUE);
+	add_room(min_rx, min_ry, max_rx, max_ry,
+		 FALSE, OV_i(rtype), TRUE);
+	troom->rlit = OV_i(rlit);
+	troom->irregular = TRUE;
+    } else {
+	add_room(dx1, dy1, dx2, dy2,
+		 OV_i(rlit), OV_i(rtype), TRUE);
+#ifdef SPECIALIZATION
+	topologize(troom,FALSE);              /* set roomno */
+#else
+	topologize(troom);                    /* set roomno */
+#endif
 	}
 
-	Fread((genericptr_t) &n, 1, sizeof(n), fd);
-						/* Number of gold piles */
-	while (n--) {
-		Fread((genericptr_t)&tmpgold, 1, sizeof(tmpgold), fd);
+    if (!room_not_needed) {
+	if (coder->n_subroom > 1)
+	    impossible("region as subroom");
+	else {
+	    coder->tmproomlist[coder->n_subroom] = troom;
+	    coder->failed_room[coder->n_subroom] = FALSE;
+	    coder->n_subroom++;
+	}
+    }
 
-		create_gold(&tmpgold, (struct mkroom *)0);
+    opvar_free(area);
+    opvar_free(rirreg);
+    opvar_free(rlit);
+    opvar_free(rtype);
 	}
 
-	Fread((genericptr_t) &n, 1, sizeof(n), fd);
-						/* Number of engravings */
-	while(n--) {
-		load_one_engraving(fd, &tmpengraving);
+void
+spo_drawbridge(coder)
+     struct sp_coder *coder;
+{
+    xchar x,y;
+    struct opvar *dir, *db_open, *coord;
 
-		create_engraving(&tmpengraving, (struct mkroom *)0);
+    if (!OV_pop_i(dir) ||
+	!OV_pop_i(db_open) ||
+	!OV_pop_c(coord)) return;
+
+    x = SP_COORD_X(OV_i(coord));
+    y = SP_COORD_Y(OV_i(coord));
+    get_location(&x, &y, DRY|WET, coder->croom);
+    if (!create_drawbridge(x, y, OV_i(dir), OV_i(db_open)))
+	impossible("Cannot create drawbridge.");
+    SpLev_Map[x][y] = 1;
+
+    opvar_free(coord);
+    opvar_free(db_open);
+    opvar_free(dir);
 	}
 
-    }		/* numpart loop */
+void
+spo_mazewalk(coder)
+     struct sp_coder *coder;
+{
+    xchar x,y;
+    struct opvar *ftyp, *fstocked,*fdir, *coord;
+    int dir;
 
-    nwalk_sav = nwalk;
-    while(nwalk--) {
-	    x = (xchar) walklist[nwalk].x;
-	    y = (xchar) walklist[nwalk].y;
-	    dir = walklist[nwalk].dir;
+    if (!OV_pop_i(ftyp) ||
+	!OV_pop_i(fstocked) ||
+	!OV_pop_i(fdir) ||
+	!OV_pop_c(coord)) return;
+
+    dir = OV_i(fdir);
+    x = SP_COORD_X(OV_i(coord));
+    y = SP_COORD_Y(OV_i(coord));
+
+    get_location(&x, &y, DRY|WET, coder->croom);
+
+    if (OV_i(ftyp) < 1) {
+#ifndef WALLIFIED_MAZE
+	OV_i(ftyp) = CORR;
+#else
+	OV_i(ftyp) = ROOM;
+#endif
+    }
 
 	    /* don't use move() - it doesn't use W_NORTH, etc. */
@@ -2530,13 +4457,10 @@
 		case W_EAST:  x++; break;
 		case W_WEST:  --x; break;
-		default: panic("load_maze: bad MAZEWALK direction");
+    default:
+	impossible("sp_level_coder: Bad MAZEWALK direction");
 	    }
 
 	    if(!IS_DOOR(levl[x][y].typ)) {
-#ifndef WALLIFIED_MAZE
-		levl[x][y].typ = CORR;
-#else
-		levl[x][y].typ = ROOM;
-#endif
+	levl[x][y].typ = OV_i(ftyp);
 		levl[x][y].flags = 0;
 	    }
@@ -2554,9 +4478,5 @@
 
 		/* no need for IS_DOOR check; out of map bounds */
-#ifndef WALLIFIED_MAZE
-		levl[x][y].typ = CORR;
-#else
-		levl[x][y].typ = ROOM;
-#endif
+	levl[x][y].typ = OV_i(ftyp);
 		levl[x][y].flags = 0;
 	    }
@@ -2569,56 +4489,895 @@
 	    }
 
-	    walkfrom(x, y);
+    walkfrom(x, y, OV_i(ftyp));
+    if (OV_i(fstocked)) fill_empty_maze();
+
+    opvar_free(coord);
+    opvar_free(fdir);
+    opvar_free(fstocked);
+    opvar_free(ftyp);
     }
-    wallification(1, 0, COLNO-1, ROWNO-1);
 
+void
+spo_wall_property(coder)
+     struct sp_coder *coder;
+{
+    struct opvar *r;
+    xchar dx1,dy1,dx2,dy2;
+    int wprop = (coder->opcode == SPO_NON_DIGGABLE) ? W_NONDIGGABLE : W_NONPASSWALL;
+
+    if (!OV_pop_r(r)) return;
+
+    dx1 = SP_REGION_X1(OV_i(r));
+    dy1 = SP_REGION_Y1(OV_i(r));
+    dx2 = SP_REGION_X2(OV_i(r));
+    dy2 = SP_REGION_Y2(OV_i(r));
+
+    get_location(&dx1, &dy1, DRY|WET, (struct mkroom *)0);
+    get_location(&dx2, &dy2, DRY|WET, (struct mkroom *)0);
+
+    set_wall_property(dx1, dy1, dx2, dy2, wprop);
+
+    opvar_free(r);
+}
+
+void
+spo_room_door(coder)
+     struct sp_coder *coder;
+{
+    struct opvar *wall, *secret, *mask, *pos;
+    room_door tmpd;
+
+    if (!OV_pop_i(wall) ||
+	!OV_pop_i(secret) ||
+	!OV_pop_i(mask) ||
+	!OV_pop_i(pos) ||
+	!coder->croom) return;
+
+    tmpd.secret = OV_i(secret);
+    tmpd.mask = OV_i(mask);
+    tmpd.pos = OV_i(pos);
+    tmpd.wall = OV_i(wall);
+
+    create_door(&tmpd, coder->croom);
+
+    opvar_free(wall);
+    opvar_free(secret);
+    opvar_free(mask);
+    opvar_free(pos);
+}
+
+void
+spo_wallify(coder)
+     struct sp_coder *coder;
+{
+    struct opvar *r;
+    int dx1,dy1,dx2,dy2;
+    if (!OV_pop_r(r)) return;
+    dx1 = (xchar)SP_REGION_X1(OV_i(r));
+    dy1 = (xchar)SP_REGION_Y1(OV_i(r));
+    dx2 = (xchar)SP_REGION_X2(OV_i(r));
+    dy2 = (xchar)SP_REGION_Y2(OV_i(r));
+    wallify_map(dx1 < 0 ? xstart : dx1,
+		dy1 < 0 ? ystart : dy1,
+		dx2 < 0 ? xstart+xsize : dx2,
+		dy2 < 0 ? ystart+ysize : dy2);
+    opvar_free(r);
+}
+
+void
+spo_map(coder)
+     struct sp_coder *coder;
+{
+    mazepart tmpmazepart;
+    struct opvar *mpxs, *mpys, *mpmap, *mpa, *mpkeepr, *mpzalign;
+    xchar halign, valign;
+    xchar tmpxstart, tmpystart, tmpxsize, tmpysize;
+
+    if (!OV_pop_i(mpxs) ||
+	!OV_pop_i(mpys) ||
+	!OV_pop_s(mpmap) ||
+	!OV_pop_i(mpkeepr) ||
+	!OV_pop_i(mpzalign) ||
+	!OV_pop_c(mpa)) return;
+
+    tmpmazepart.xsize = OV_i(mpxs);
+    tmpmazepart.ysize = OV_i(mpys);
+    tmpmazepart.zaligntyp = OV_i(mpzalign);
+    tmpmazepart.halign = SP_COORD_X(OV_i(mpa));
+    tmpmazepart.valign = SP_COORD_Y(OV_i(mpa));
+
+    tmpxsize = xsize; tmpysize = ysize;
+    tmpxstart = xstart; tmpystart = ystart;
+
+    halign = tmpmazepart.halign;
+    valign = tmpmazepart.valign;
+    xsize = tmpmazepart.xsize;
+    ysize = tmpmazepart.ysize;
+    switch (tmpmazepart.zaligntyp) {
+    default:
+    case 0:
+	break;
+    case 1:
+	switch((int) halign) {
+	case LEFT:	    xstart = 3;					break;
+	case H_LEFT:    xstart = 2+((x_maze_max-2-xsize)/4);	break;
+	case CENTER:    xstart = 2+((x_maze_max-2-xsize)/2);	break;
+	case H_RIGHT:   xstart = 2+((x_maze_max-2-xsize)*3/4);	break;
+	case RIGHT:     xstart = x_maze_max-xsize-1;		break;
+	}
+	switch((int) valign) {
+	case TOP:	    ystart = 3;					break;
+	case CENTER:    ystart = 2+((y_maze_max-2-ysize)/2);	break;
+	case BOTTOM:    ystart = y_maze_max-ysize-1;		break;
+	}
+	if (!(xstart % 2)) xstart++;
+	if (!(ystart % 2)) ystart++;
+	break;
+    case 2:
+	get_location(&halign, &valign, DRY|WET, coder->croom);
+	xstart = halign;
+	ystart = valign;
+	break;
+    }
+    if ((ystart < 0) || (ystart + ysize > ROWNO)) {
+	/* try to move the start a bit */
+	ystart += (ystart > 0) ? -2 : 2;
+	if(ysize == ROWNO) ystart = 0;
+	if(ystart < 0 || ystart + ysize > ROWNO)
+	    panic("reading special level with ysize too large");
+    }
+    if (xsize <= 1 && ysize <= 1) {
+	xstart = 1;
+	ystart = 0;
+	xsize = COLNO-1;
+	ysize = ROWNO;
+    } else {
+	xchar x,y;
+	/* Load the map */
+	for(y = ystart; y < ystart+ysize; y++)
+	    for(x = xstart; x < xstart+xsize; x++) {
+		xchar mptyp = (mpmap->vardata.str[(y-ystart) * xsize + (x-xstart)] - 1);
+		if (mptyp >= MAX_TYPE) continue;
+		levl[x][y].typ = mptyp;
+		levl[x][y].lit = FALSE;
+		/* clear out levl: load_common_data may set them */
+		levl[x][y].flags = 0;
+		levl[x][y].horizontal = 0;
+		levl[x][y].roomno = 0;
+		levl[x][y].edge = 0;
     /*
-     * If there's a significant portion of maze unused by the special level,
-     * we don't want it empty.
-     *
-     * Makes the number of traps, monsters, etc. proportional
-     * to the size of the maze.
+		 *  Set secret doors to closed (why not trapped too?).  Set
+		 *  the horizontal bit.
      */
-    mapcountmax = mapcount = (x_maze_max - 2) * (y_maze_max - 2);
+		if (levl[x][y].typ == SDOOR || IS_DOOR(levl[x][y].typ)) {
+		    if(levl[x][y].typ == SDOOR)
+			levl[x][y].doormask = D_CLOSED;
+		    /*
+		     *  If there is a wall to the left that connects to a
+		     *  (secret) door, then it is horizontal.  This does
+		     *  not allow (secret) doors to be corners of rooms.
+		     */
+		    if (x != xstart && (IS_WALL(levl[x-1][y].typ) ||
+					levl[x-1][y].horizontal))
+			levl[x][y].horizontal = 1;
+		} else if(levl[x][y].typ == HWALL ||
+			  levl[x][y].typ == IRONBARS)
+		    levl[x][y].horizontal = 1;
+		else if(levl[x][y].typ == LAVAPOOL)
+		    levl[x][y].lit = 1;
+	    }
+	if (coder->lvl_is_joined)
+	    remove_rooms(xstart, ystart, xstart+xsize, ystart+ysize);
+    }
+    if (!OV_i(mpkeepr)) {
+	xstart = tmpxstart; ystart = tmpystart;
+	xsize = tmpxsize; ysize = tmpysize;
+    }
 
-    for(x = 2; x < x_maze_max; x++)
-	for(y = 0; y < y_maze_max; y++)
-	    if(Map[x][y]) mapcount--;
+    opvar_free(mpxs);
+    opvar_free(mpys);
+    opvar_free(mpmap);
+    opvar_free(mpa);
+    opvar_free(mpkeepr);
+    opvar_free(mpzalign);
+}
 
-    if (nwalk_sav && (mapcount > (int) (mapcountmax / 10))) {
-	    mapfact = (int) ((mapcount * 100L) / mapcountmax);
-	    for(x = rnd((int) (20 * mapfact) / 100); x; x--) {
-		    maze1xy(&mm, DRY);
-		    (void) mkobj_at(rn2(2) ? GEM_CLASS : RANDOM_CLASS,
-							mm.x, mm.y, TRUE);
+void
+spo_jmp(coder, lvl)
+     struct sp_coder *coder;
+     sp_lev *lvl;
+{
+    struct opvar *tmpa;
+    long a;
+    if (!OV_pop_i(tmpa)) return;
+    a = sp_code_jmpaddr(coder->frame->n_opcode, (OV_i(tmpa) - 1));
+    if ((a >= 0) && (a < lvl->n_opcodes) &&
+	(a != coder->frame->n_opcode))
+	coder->frame->n_opcode = a;
+    opvar_free(tmpa);
 	    }
-	    for(x = rnd((int) (12 * mapfact) / 100); x; x--) {
-		    maze1xy(&mm, DRY);
-		    (void) mksobj_at(BOULDER, mm.x, mm.y, TRUE, FALSE);
+
+void
+spo_conditional_jump(coder,lvl)
+     struct sp_coder *coder;
+     sp_lev *lvl;
+{
+    struct opvar *oa, *oc;
+    long a,c;
+    int test = 0;
+    if (!OV_pop_i(oa) || !OV_pop_i(oc)) return;
+
+    a = sp_code_jmpaddr(coder->frame->n_opcode, (OV_i(oa) - 1));
+    c = OV_i(oc);
+
+    switch (coder->opcode) {
+    default: impossible("spo_conditional_jump: illegal opcode"); break;
+    case SPO_JL:  test = (c & SP_CPUFLAG_LT); break;
+    case SPO_JLE: test = (c & (SP_CPUFLAG_LT|SP_CPUFLAG_EQ)); break;
+    case SPO_JG:  test = (c & SP_CPUFLAG_GT); break;
+    case SPO_JGE: test = (c & (SP_CPUFLAG_GT|SP_CPUFLAG_EQ)); break;
+    case SPO_JE:  test = (c & SP_CPUFLAG_EQ); break;
+    case SPO_JNE: test = (c & ~SP_CPUFLAG_EQ); break;
 	    }
-	    for (x = rn2(2); x; x--) {
-		maze1xy(&mm, DRY);
-		(void) makemon(&mons[PM_MINOTAUR], mm.x, mm.y, NO_MM_FLAGS);
+
+    if ((test) && (a >= 0) &&
+	(a < lvl->n_opcodes) &&
+	(a != coder->frame->n_opcode))
+	coder->frame->n_opcode = a;
+
+    opvar_free(oa);
+    opvar_free(oc);
 	    }
-	    for(x = rnd((int) (12 * mapfact) / 100); x; x--) {
-		    maze1xy(&mm, WET|DRY);
-		    (void) makemon((struct permonst *) 0, mm.x, mm.y, NO_MM_FLAGS);
+
+
+void
+spo_var_init(coder)
+     struct sp_coder *coder;
+{
+    struct opvar *vname;
+    struct opvar *arraylen;
+    struct opvar *vvalue;
+    struct splev_var *tmpvar;
+    struct splev_var *tmp2;
+    long idx;
+
+    OV_pop_s(vname);
+    OV_pop_i(arraylen);
+
+    if (!vname || !arraylen)
+	panic("no values for SPO_VAR_INIT");
+
+    tmpvar = opvar_var_defined(coder, OV_s(vname));
+
+    if (tmpvar) {
+	/* variable redefinition */
+	if (OV_i(arraylen) < 0) {
+	    /* copy variable */
+	    if (tmpvar->array_len) {
+		idx = tmpvar->array_len;
+		while (idx-- > 0) {
+		    opvar_free(tmpvar->data.arrayvalues[idx]);
 	    }
-	    for(x = rn2((int) (15 * mapfact) / 100); x; x--) {
-		    maze1xy(&mm, DRY);
-		    (void) mkgold(0L,mm.x,mm.y);
+		free(tmpvar->data.arrayvalues);
+	    } else {
+		opvar_free(tmpvar->data.value);
 	    }
-	    for(x = rn2((int) (15 * mapfact) / 100); x; x--) {
-		    int trytrap;
+	    tmpvar->data.arrayvalues = NULL;
+	    goto copy_variable;
+	} else if (OV_i(arraylen)) {
+	    /* redefined array */
+	    idx = tmpvar->array_len;
+	    while (idx-- > 0) {
+		opvar_free(tmpvar->data.arrayvalues[idx]);
+	    }
+	    free(tmpvar->data.arrayvalues);
+	    tmpvar->data.arrayvalues = NULL;
+	    goto create_new_array;
+	} else {
+	    /* redefined single value */
+	    OV_pop(vvalue);
+	    if (tmpvar->svtyp != vvalue->spovartyp) panic("redefining variable as different type");
+	    opvar_free(tmpvar->data.value);
+	    tmpvar->data.value = vvalue;
+	    tmpvar->array_len = 0;
+	}
+    } else {
+	/* new variable definition */
+	tmpvar = (struct splev_var *)malloc(sizeof(struct splev_var));
+	if (!tmpvar) return;
+	tmpvar->next = coder->frame->variables;
+	tmpvar->name = strdup(OV_s(vname));
+	coder->frame->variables = tmpvar;
 
-		    maze1xy(&mm, DRY);
-		    trytrap = rndtrap();
-		    if (sobj_at(BOULDER, mm.x, mm.y))
-			while (trytrap == PIT || trytrap == SPIKED_PIT ||
-				trytrap == TRAPDOOR || trytrap == HOLE)
-			    trytrap = rndtrap();
-		    (void) maketrap(mm.x, mm.y, trytrap);
+	if (OV_i(arraylen) < 0) {
+	    /* copy variable */
+copy_variable:
+	    OV_pop(vvalue);
+	    tmp2 = opvar_var_defined(coder, OV_s(vvalue));
+	    if (!tmp2) panic("no copyable var");
+	    tmpvar->svtyp = tmp2->svtyp;
+	    tmpvar->array_len = tmp2->array_len;
+	    if (tmpvar->array_len) {
+		idx = tmpvar->array_len;
+		tmpvar->data.arrayvalues = (struct opvar **)malloc(sizeof(struct opvar *) * idx);
+		while (idx-- > 0) {
+		    tmpvar->data.arrayvalues[idx] = opvar_clone(tmp2->data.arrayvalues[idx]);
 	    }
+	    } else {
+		tmpvar->data.value = opvar_clone(tmp2->data.value);
     }
+	    opvar_free(vvalue);
+	} else if (OV_i(arraylen)) {
+	    /* new array */
+create_new_array:
+	    idx = OV_i(arraylen);
+	    tmpvar->array_len = idx;
+	    tmpvar->data.arrayvalues = (struct opvar **)malloc(sizeof(struct opvar *) * idx);
+	    if (!tmpvar->data.arrayvalues) panic("malloc tmpvar->data.arrayvalues");
+	    while (idx-- > 0) {
+		OV_pop(vvalue);
+		if (!vvalue) panic("no value for arrayvariable");
+		tmpvar->data.arrayvalues[idx] = vvalue;
+	    }
+	    tmpvar->svtyp = SPOVAR_ARRAY;
+	} else {
+	    /* new single value */
+	    OV_pop(vvalue);
+	    if (!vvalue) panic("no value for variable");
+	    tmpvar->svtyp = OV_typ(vvalue);
+	    tmpvar->data.value = vvalue;
+	    tmpvar->array_len = 0;
+	}
+    }
+
+    opvar_free(vname);
+    opvar_free(arraylen);
+}
+
+void
+spo_shuffle_array(coder)
+     struct sp_coder *coder;
+{
+    struct opvar *vname;
+    struct splev_var *tmp;
+    struct opvar *tmp2;
+    long i,j;
+
+    if (!OV_pop_s(vname)) return;
+
+    tmp = opvar_var_defined(coder, OV_s(vname));
+    if (!tmp || (tmp->array_len < 1)) return;
+
+    for (i = tmp->array_len - 1; i > 0; i--) {
+	if ((j = rn2(i + 1)) == i) continue;
+	tmp2 = tmp->data.arrayvalues[j];
+	tmp->data.arrayvalues[j] = tmp->data.arrayvalues[i];
+	tmp->data.arrayvalues[i] = tmp2;
+    }
+
+    opvar_free(vname);
+}
+
+
+
+/* Special level coder, creates the special level from the sp_lev codes.
+ * Does not free the allocated memory.
+ */
+STATIC_OVL boolean
+sp_level_coder(lvl)
+sp_lev *lvl;
+{
+    long exec_opcodes = 0;
+    int     tmpi;
+    struct sp_coder *coder = (struct sp_coder *)alloc(sizeof(struct sp_coder));
+
+    coder->frame = frame_new(0);
+    coder->stack = NULL;
+    coder->premapped = FALSE;
+    coder->allow_flips = 3;
+    coder->croom = NULL;
+    coder->n_subroom = 1;
+    coder->exit_script = FALSE;
+    coder->lvl_is_joined = 0;
+
+    for (tmpi = 0; tmpi <= MAX_NESTED_ROOMS; tmpi++) {
+	coder->tmproomlist[tmpi] = (struct mkroom *)0;
+	coder->failed_room[tmpi] = FALSE;
+    }
+
+    shuffle_alignments();
+
+    for (tmpi = 0; tmpi < MAX_CONTAINMENT; tmpi++) container_obj[tmpi] = NULL;
+    container_idx = 0;
+
+    invent_carrying_monster = NULL;
+
+    (void) memset((genericptr_t)&SpLev_Map[0][0], 0, sizeof SpLev_Map);
+
+    level.flags.is_maze_lev = 0;
+
+    xstart = 1;
+    ystart = 0;
+    xsize = COLNO-1;
+    ysize = ROWNO;
+
+    while (coder->frame->n_opcode < lvl->n_opcodes && !coder->exit_script) {
+	coder->opcode = lvl->opcodes[coder->frame->n_opcode].opcode;
+	coder->opdat = lvl->opcodes[coder->frame->n_opcode].opdat;
+
+	coder->stack = coder->frame->stack;
+
+	if (exec_opcodes++ > SPCODER_MAX_RUNTIME) {
+	    impossible("Level script is taking too much time, stopping.");
+	    coder->exit_script = TRUE;
+	}
+
+	if (coder->failed_room[coder->n_subroom-1] &&
+	    coder->opcode != SPO_ENDROOM &&
+	    coder->opcode != SPO_ROOM &&
+	    coder->opcode != SPO_SUBROOM) goto next_opcode;
+
+	coder->croom = coder->tmproomlist[coder->n_subroom-1];
+
+	switch (coder->opcode) {
+        case SPO_NULL: break;
+	case SPO_EXIT: coder->exit_script = TRUE; break;
+	case SPO_FRAME_PUSH: spo_frame_push(coder); break;
+	case SPO_FRAME_POP:  spo_frame_pop(coder); break;
+	case SPO_CALL:       spo_call(coder); break;
+	case SPO_RETURN:     spo_return(coder); break;
+	case SPO_END_MONINVENT: spo_end_moninvent(coder); break;
+	case SPO_POP_CONTAINER: spo_pop_container(coder); break;
+	case SPO_POP:
+	    {
+		struct opvar *ov = splev_stack_pop(coder->stack);
+		opvar_free(ov);
+	    }
+	    break;
+	case SPO_PUSH: splev_stack_push(coder->stack, opvar_clone(coder->opdat)); break;
+	case SPO_MESSAGE:        spo_message(coder);        break;
+	case SPO_MONSTER:        spo_monster(coder);        break;
+	case SPO_OBJECT:         spo_object(coder);         break;
+	case SPO_LEVEL_FLAGS:    spo_level_flags(coder);    break;
+	case SPO_INITLEVEL:      spo_initlevel(coder);      break;
+	case SPO_MON_GENERATION: spo_mon_generation(coder); break;
+	case SPO_LEVEL_SOUNDS:   spo_level_sounds(coder);   break;
+	case SPO_ENGRAVING:      spo_engraving(coder);      break;
+	case SPO_SUBROOM:
+	case SPO_ROOM:           spo_room(coder);           break;
+	case SPO_ENDROOM:        spo_endroom(coder);        break;
+	case SPO_DOOR:           spo_door(coder);           break;
+	case SPO_STAIR:          spo_stair(coder);          break;
+	case SPO_LADDER:         spo_ladder(coder);         break;
+	case SPO_GRAVE:          spo_grave(coder);          break;
+	case SPO_ALTAR:          spo_altar(coder);          break;
+	case SPO_SINK:
+	case SPO_POOL:
+	case SPO_FOUNTAIN:       spo_feature(coder);        break;
+	case SPO_WALLWALK:       spo_wallwalk(coder);        break;
+	case SPO_TRAP:           spo_trap(coder);           break;
+	case SPO_GOLD:           spo_gold(coder);           break;
+	case SPO_CORRIDOR:       spo_corridor(coder);       break;
+	case SPO_TERRAIN:        spo_terrain(coder);        break;
+	case SPO_REPLACETERRAIN: spo_replace_terrain(coder); break;
+	case SPO_SPILL:          spo_spill(coder);    break;
+	case SPO_LEVREGION:      spo_levregion(coder); break;
+	case SPO_REGION:         spo_region(coder);    break;
+	case SPO_DRAWBRIDGE:      spo_drawbridge(coder);  break;
+	case SPO_MAZEWALK:        spo_mazewalk(coder);    break;
+	case SPO_NON_PASSWALL:
+	case SPO_NON_DIGGABLE:    spo_wall_property(coder);   break;
+	case SPO_ROOM_DOOR:       spo_room_door(coder);    break;
+	case SPO_WALLIFY:         spo_wallify(coder);    break;
+	case SPO_COPY:
+	    {
+		struct opvar *a = splev_stack_pop(coder->stack);
+		splev_stack_push(coder->stack, opvar_clone(a));
+		splev_stack_push(coder->stack, opvar_clone(a));
+		opvar_free(a);
+	    }
+	    break;
+	case SPO_DEC:
+	    {
+		struct opvar *a;
+		if (!OV_pop_i(a)) break;
+		OV_i(a)--;
+		splev_stack_push(coder->stack, a);
+	    }
+	    break;
+	case SPO_INC:
+	    {
+		struct opvar *a;
+		if (!OV_pop_i(a)) break;
+		OV_i(a)++;
+		splev_stack_push(coder->stack, a);
+	    }
+	    break;
+	case SPO_MATH_ADD:
+	    {
+		struct opvar *a, *b;
+		if (!OV_pop(b) || !OV_pop(a)) break;
+		if (OV_typ(b) == OV_typ(a)) {
+		    if (OV_typ(a) == SPOVAR_INT) {
+			OV_i(a) = OV_i(a) + OV_i(b);
+			splev_stack_push(coder->stack, a);
+			opvar_free(b);
+		    } else if (OV_typ(a) == SPOVAR_STRING) {
+			char *tmpbuf = (char *)alloc(strlen(OV_s(a)) + strlen(OV_s(b)) + 1);
+			if (tmpbuf) {
+			    struct opvar *c;
+			    (void) sprintf(tmpbuf, "%s%s", OV_s(a), OV_s(b));
+			    c = opvar_new_str(tmpbuf);
+			    splev_stack_push(coder->stack, c);
+			    opvar_free(a);
+			    opvar_free(b);
+			    free(tmpbuf);
+			} else {
+			    splev_stack_push(coder->stack, a);
+			    opvar_free(b);
+			    impossible("malloc at str concat");
+			}
+		    } else {
+			splev_stack_push(coder->stack, a);
+			opvar_free(b);
+			impossible("adding weird types");
+		    }
+		} else {
+		    splev_stack_push(coder->stack, a);
+		    opvar_free(b);
+		    impossible("adding different types");
+		}
+	    }
+	    break;
+	case SPO_MATH_SUB:
+	    {
+		struct opvar *a, *b;
+		if (!OV_pop_i(b) || !OV_pop_i(a)) break;
+		OV_i(a) = OV_i(a) - OV_i(b);
+		splev_stack_push(coder->stack, a);
+		opvar_free(b);
+	    }
+	    break;
+	case SPO_MATH_MUL:
+	    {
+		struct opvar *a, *b;
+		if (!OV_pop_i(b) || !OV_pop_i(a)) break;
+		OV_i(a) = OV_i(a) * OV_i(b);
+		splev_stack_push(coder->stack, a);
+		opvar_free(b);
+	    }
+	    break;
+	case SPO_MATH_DIV:
+	    {
+		struct opvar *a, *b;
+		if (!OV_pop_i(b) || !OV_pop_i(a)) break;
+		if (OV_i(b) >= 1) {
+		    OV_i(a) = OV_i(a) / OV_i(b);
+		} else {
+		    OV_i(a) = 0;
+		}
+		splev_stack_push(coder->stack, a);
+		opvar_free(b);
+	    }
+	    break;
+	case SPO_MATH_MOD:
+	    {
+		struct opvar *a, *b;
+		if (!OV_pop_i(b) || !OV_pop_i(a)) break;
+		if (OV_i(b) > 0) {
+		    OV_i(a) = OV_i(a) % OV_i(b);
+		} else {
+		    OV_i(a) = 0;
+		}
+		splev_stack_push(coder->stack, a);
+		opvar_free(b);
+	    }
+	    break;
+        case SPO_CMP:
+	    {
+		struct opvar *a;
+		struct opvar *b;
+		struct opvar *c;
+		long val = 0;
+
+		OV_pop(b);
+		OV_pop(a);
+
+		if (!a || !b) {
+		    impossible("spo_cmp: no values in stack");
+		    break;
+		}
+
+		if (OV_typ(a) != OV_typ(b)) {
+		    impossible("spo_cmp: trying to compare differing datatypes");
+		    break;
+		}
+
+		switch (OV_typ(a)) {
+		case SPOVAR_COORD:
+		case SPOVAR_REGION:
+		case SPOVAR_MAPCHAR:
+		case SPOVAR_MONST:
+		case SPOVAR_OBJ:
+		case SPOVAR_INT:
+		    if (OV_i(b) > OV_i(a)) val |= SP_CPUFLAG_LT;
+		    if (OV_i(b) < OV_i(a)) val |= SP_CPUFLAG_GT;
+		    if (OV_i(b) == OV_i(a)) val |= SP_CPUFLAG_EQ;
+		    c = opvar_new_int(val);
+		    break;
+		case SPOVAR_STRING:
+		    c = opvar_new_int(((!strcmp(OV_s(b), OV_s(a))) ? SP_CPUFLAG_EQ : 0));
+		    break;
+		default:
+		    c = opvar_new_int(0);
+		    break;
+		}
+		splev_stack_push(coder->stack, c);
+		opvar_free(a);
+		opvar_free(b);
+	    }
+	    break;
+        case SPO_JMP:
+	    spo_jmp(coder, lvl); break;
+        case SPO_JL:
+        case SPO_JLE:
+        case SPO_JG:
+        case SPO_JGE:
+        case SPO_JE:
+        case SPO_JNE:
+	    spo_conditional_jump(coder, lvl); break;
+	case SPO_RN2:
+	    {
+		struct opvar *tmpv;
+		struct opvar *t;
+		if (!OV_pop_i(tmpv)) break;
+		t = opvar_new_int((OV_i(tmpv) > 1) ? rn2(OV_i(tmpv)) : 0);
+		splev_stack_push(coder->stack, t);
+		opvar_free(tmpv);
+	    }
+         break;
+	case SPO_DICE:
+	    {
+		struct opvar *a, *b, *t;
+		if (!OV_pop_i(b) || !OV_pop_i(a)) break;
+		if (OV_i(b) < 1) OV_i(b) = 1;
+		if (OV_i(a) < 1) OV_i(a) = 1;
+		t = opvar_new_int(d(OV_i(a), OV_i(b)));
+		splev_stack_push(coder->stack, t);
+		opvar_free(a);
+		opvar_free(b);
+	    }
+	    break;
+	case SPO_MAP:
+	    spo_map(coder); break;
+	case SPO_VAR_INIT:
+	    spo_var_init(coder); break;
+	case SPO_SHUFFLE_ARRAY:
+	    spo_shuffle_array(coder); break;
+	case SPO_SEL_ADD: /* actually, logical or */
+	    {
+		struct opvar *sel1, *sel2, *pt;
+		if (!OV_pop_typ(sel1, SPOVAR_SEL)) panic("no sel1 for add");
+		if (!OV_pop_typ(sel2, SPOVAR_SEL)) panic("no sel1 for add");
+		pt = selection_logical_oper(sel1, sel2, '|');
+		opvar_free(sel1);
+		opvar_free(sel2);
+		splev_stack_push(coder->stack, pt);
+	    }
+	    break;
+	case SPO_SEL_FILTER: /* sorta like logical and */
+	    {
+		struct opvar *filtertype;
+		int x,y;
+		if (!OV_pop_i(filtertype)) panic("no sel filter type");
+		switch (OV_i(filtertype)) {
+		case 0: /* percentage */
+		    {
+			struct opvar *tmp1, *sel;
+			if (!OV_pop_i(tmp1)) panic("no sel filter percent");
+			if (!OV_pop_typ(sel, SPOVAR_SEL)) panic("no sel filter");
+			selection_filter_percent(sel, OV_i(tmp1));
+			splev_stack_push(coder->stack, sel);
+			opvar_free(tmp1);
+		    }
+		    break;
+		case 1: /* logical and */
+		    {
+			struct opvar *pt, *sel1, *sel2;
+			if (!OV_pop_typ(sel1, SPOVAR_SEL)) panic("no sel filter sel1");
+			if (!OV_pop_typ(sel2, SPOVAR_SEL)) panic("no sel filter sel2");
+			pt = selection_logical_oper(sel1, sel2, '&');
+			splev_stack_push(coder->stack, pt);
+			opvar_free(sel1);
+			opvar_free(sel2);
+		    }
+		    break;
+		default: panic("unknown sel filter type");
+		}
+		opvar_free(filtertype);
+	    }
+	    break;
+	case SPO_SEL_POINT:
+	    {
+		struct opvar *tmp;
+		schar x,y;
+		if (!OV_pop_c(tmp)) panic("no ter sel coord");
+		x = SP_COORD_X(OV_i(tmp));
+		y = SP_COORD_Y(OV_i(tmp));
+		get_location(&x, &y, DRY|WET, coder->croom);
+		if (isok(x,y)) {
+		    struct opvar *pt = selection_opvar(NULL);
+		    selection_setpoint(x,y, pt, 1);
+		    splev_stack_push(coder->stack, pt);
+		}
+		opvar_free(tmp);
+	    }
+	    break;
+	case SPO_SEL_RECT:
+	case SPO_SEL_FILLRECT:
+	    {
+		struct opvar *tmp, *pt = selection_opvar(NULL);
+		schar x,y,x1,y1,x2,y2;
+		if (!OV_pop_r(tmp)) panic("no ter sel region");
+		x1 = min(SP_REGION_X1(OV_i(tmp)), SP_REGION_X2(OV_i(tmp)));
+		y1 = min(SP_REGION_Y1(OV_i(tmp)), SP_REGION_Y2(OV_i(tmp)));
+		x2 = max(SP_REGION_X1(OV_i(tmp)), SP_REGION_X2(OV_i(tmp)));
+		y2 = max(SP_REGION_Y1(OV_i(tmp)), SP_REGION_Y2(OV_i(tmp)));
+		get_location(&x1, &y1, DRY|WET, coder->croom);
+		get_location(&x2, &y2, DRY|WET, coder->croom);
+		x1 = (x1 < 0) ? 0 : x1;
+		y1 = (y1 < 0) ? 0 : y1;
+		x2 = (x2 >= COLNO) ? COLNO-1 : x2;
+		y2 = (y2 >= ROWNO) ? ROWNO-1 : y2;
+		if (coder->opcode == SPO_SEL_RECT) {
+		    for (x = x1; x <= x2; x++) {
+			selection_setpoint(x,y1, pt, 1);
+			selection_setpoint(x,y2, pt, 1);
+		    }
+		    for (y = y1; y <= y2; y++) {
+			selection_setpoint(x1,y, pt, 1);
+			selection_setpoint(x2,y, pt, 1);
+		    }
+		} else {
+		    for (x = x1; x <= x2; x++)
+			for (y = y1; y <= y2; y++)
+			    selection_setpoint(x,y, pt, 1);
+		}
+		splev_stack_push(coder->stack, pt);
+		opvar_free(tmp);
+	    }
+	    break;
+	case SPO_SEL_LINE:
+	    {
+		struct opvar *tmp, *tmp2, *pt = selection_opvar(NULL);
+		schar x1,y1,x2,y2;
+		if (!OV_pop_c(tmp) || !OV_pop_c(tmp2)) panic("no ter sel linecoord");
+		x1 = SP_COORD_X(OV_i(tmp));
+		y1 = SP_COORD_Y(OV_i(tmp));
+		x2 = SP_COORD_X(OV_i(tmp2));
+		y2 = SP_COORD_Y(OV_i(tmp2));
+		get_location(&x1, &y1, DRY|WET, coder->croom);
+		get_location(&x2, &y2, DRY|WET, coder->croom);
+		x1 = (x1 < 0) ? 0 : x1;
+		y1 = (y1 < 0) ? 0 : y1;
+		x2 = (x2 >= COLNO) ? COLNO-1 : x2;
+		y2 = (y2 >= ROWNO) ? ROWNO-1 : y2;
+		selection_do_line(x1,y1,x2,y2, pt);
+		splev_stack_push(coder->stack, pt);
+		opvar_free(tmp);
+		opvar_free(tmp2);
+	    }
+	    break;
+	case SPO_SEL_RNDLINE:
+	    {
+		struct opvar *tmp, *tmp2, *tmp3, *pt = selection_opvar(NULL);
+		schar x1,y1,x2,y2;
+		if (!OV_pop_i(tmp3) || !OV_pop_c(tmp) || !OV_pop_c(tmp2)) panic("no ter sel randline");
+		x1 = SP_COORD_X(OV_i(tmp));
+		y1 = SP_COORD_Y(OV_i(tmp));
+		x2 = SP_COORD_X(OV_i(tmp2));
+		y2 = SP_COORD_Y(OV_i(tmp2));
+		get_location(&x1, &y1, DRY|WET, coder->croom);
+		get_location(&x2, &y2, DRY|WET, coder->croom);
+		x1 = (x1 < 0) ? 0 : x1;
+		y1 = (y1 < 0) ? 0 : y1;
+		x2 = (x2 >= COLNO) ? COLNO-1 : x2;
+		y2 = (y2 >= ROWNO) ? ROWNO-1 : y2;
+		selection_do_randline(x1,y1,x2,y2, OV_i(tmp3), 12, pt);
+		splev_stack_push(coder->stack, pt);
+		opvar_free(tmp);
+		opvar_free(tmp2);
+		opvar_free(tmp3);
+	    }
+	    break;
+	case SPO_SEL_GROW:
+	    {
+		struct opvar *dirs, *pt;
+		if (!OV_pop_i(dirs)) panic("no dirs for grow");
+		if (!OV_pop_typ(pt, SPOVAR_SEL)) panic("no selection for grow");
+		selection_do_grow(pt, OV_i(dirs));
+		splev_stack_push(coder->stack, pt);
+		opvar_free(dirs);
+	    }
+	    break;
+	case SPO_SEL_FLOOD:
+	    {
+		struct opvar *tmp;
+		schar x,y;
+		if (!OV_pop_c(tmp)) panic("no ter sel flood coord");
+		x = SP_COORD_X(OV_i(tmp));
+		y = SP_COORD_Y(OV_i(tmp));
+		get_location(&x, &y, DRY|WET, coder->croom);
+		if (isok(x,y)) {
+		    struct opvar *pt = selection_opvar(NULL);
+		    selection_floodfill(pt, x,y);
+		    splev_stack_push(coder->stack, pt);
+		}
+		opvar_free(tmp);
+	    }
+	    break;
+	case SPO_SEL_RNDCOORD:
+	    {
+		struct opvar *pt;
+		schar x,y;
+		if (!OV_pop_typ(pt, SPOVAR_SEL)) panic("no selection for rndcoord");
+		if (selection_rndcoord(pt, &x, &y)) {
+		    x -= xstart;
+		    y -= ystart;
+		}
+		/*get_location(&x, &y, DRY|WET, coder->croom);*/
+		splev_stack_push(coder->stack, opvar_new_coord(x,y));
+		opvar_free(pt);
+	    }
+	    break;
+	case SPO_SEL_ELLIPSE:
+	    {
+		struct opvar *filled, *xaxis, *yaxis, *pt;
+		schar x,y;
+		if (!OV_pop_i(filled)) panic("no filled for ellipse");
+		if (!OV_pop_i(yaxis)) panic("no yaxis for ellipse");
+		if (!OV_pop_i(xaxis)) panic("no xaxis for ellipse");
+		if (!OV_pop_c(pt)) panic("no pt for ellipse");
+		x = SP_COORD_X(OV_i(pt));
+		y = SP_COORD_Y(OV_i(pt));
+		get_location(&x, &y, DRY|WET, coder->croom);
+		if (isok(x,y)) {
+		    struct opvar *sel = selection_opvar(NULL);
+		    selection_do_ellipse(sel, x,y, OV_i(xaxis), OV_i(yaxis), OV_i(filled));
+		    splev_stack_push(coder->stack, sel);
+		}
+		opvar_free(filled);
+		opvar_free(yaxis);
+		opvar_free(xaxis);
+		opvar_free(pt);
+	    }
+	    break;
+	default:
+	    panic("sp_level_coder: Unknown opcode %i", coder->opcode);
+	}
+
+next_opcode:
+	coder->frame->n_opcode++;
+    } /*while*/
+
+    fill_rooms();
+    remove_boundary_syms();
+    wallification(1, 0, COLNO-1, ROWNO-1);
+
+    flip_level_rnd(coder->allow_flips);
+
+    count_features();
+
+    if (coder->premapped) sokoban_detect();
+
+    if (coder->frame) {
+	struct sp_frame *tmpframe;
+	do {
+	    tmpframe = coder->frame->next;
+	    frame_del(coder->frame);
+	    coder->frame = tmpframe;
+	} while (coder->frame);
+    }
+
     return TRUE;
 }
@@ -2633,6 +5392,6 @@
 {
 	dlb *fd;
+	sp_lev lvl;
 	boolean result = FALSE;
-	char c;
 	struct version_info vers_info;
 
@@ -2644,16 +5403,7 @@
 	    goto give_up;
 
-	Fread((genericptr_t) &c, sizeof c, 1, fd); /* c Header */
-
-	switch (c) {
-		case SP_LEV_ROOMS:
-		    result = load_rooms(fd);
-		    break;
-		case SP_LEV_MAZE:
-		    result = load_maze(fd);
-		    break;
-		default:	/* ??? */
-		    result = FALSE;
-	}
+	result = sp_level_loader(fd, &lvl);
+	if (result) result = sp_level_coder(&lvl);
+	sp_level_free(&lvl);
  give_up:
 	(void)dlb_fclose(fd);
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/src/steal.c nethack/src/steal.c
--- nh_orig/src/steal.c	2003-12-07 18:39:13.000000000 -0500
+++ nethack/src/steal.c	2009-11-22 07:19:36.794273726 -0500
@@ -209,5 +209,5 @@
 	} else if (obj->owornmask & W_TOOL) {
 	    Blindf_off(obj);
-	} else if (obj->owornmask & (W_WEP|W_SWAPWEP|W_QUIVER)) {
+	} else if (obj->owornmask & (W_WEP|W_SWAPWEP|W_QUIVER|W_LAUNCHER)) {
 	    if (obj == uwep)
 		uwepgone();
@@ -216,4 +216,6 @@
 	    if (obj == uquiver)
 		uqwepgone();
+	    if (obj == ulauncher)
+		ulwepgone();
 	}
 
@@ -313,5 +315,5 @@
 	    if (otmp == uball)
 		ostuck = TRUE;	/* effectively worn; curse is implicit */
-	    else if (otmp == uquiver || (otmp == uswapwep && !u.twoweap))
+	    else if (otmp == uquiver || otmp == ulauncher || (otmp == uswapwep && !u.twoweap))
 		ostuck = FALSE;	/* not really worn; curse doesn't matter */
 	    else
@@ -383,5 +385,5 @@
 			named++;
 			/* the following is to set multi for later on */
-			nomul(-armordelay);
+			nomul(-armordelay, "taking off clothes");
 			remove_worn_item(otmp, TRUE);
 			otmp->cursed = curssv;
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/src/steed.c nethack/src/steed.c
--- nh_orig/src/steed.c	2003-12-07 18:39:13.000000000 -0500
+++ nethack/src/steed.c	2010-03-30 14:05:06.559750680 -0400
@@ -34,5 +34,9 @@
 			(!humanoid(ptr) || ptr->mlet == S_CENTAUR) &&
 			!amorphous(ptr) && !noncorporeal(ptr) &&
-			!is_whirly(ptr) && !unsolid(ptr));
+			!is_whirly(ptr) && !unsolid(ptr) && 
+			!(ptr->mlet == S_JABBERWOCK && mtmp->mnum != PM_JABBERWOCK));
+
+	/* hack to avoid people saddling up snarks and boojum */
+
 }
 
@@ -195,4 +199,5 @@
 	struct obj *otmp;
 	char buf[BUFSZ];
+	int role_modifier;
 	struct permonst *ptr;
 
@@ -300,5 +305,5 @@
 
 	/* Is the player impaired? */
-	if (!force && !is_floater(ptr) && !is_flyer(ptr) &&
+	if (!force && !is_floater(ptr) && !is_flyer(ptr) && !is_flying(mtmp) &&
 			Levitation && !Lev_at_will) {
 	    You("cannot reach %s.", mon_nam(mtmp));
@@ -312,6 +317,9 @@
 	    return (FALSE);
 	}
+	/* A Knight should be able to ride his own horse!
+		so we get a bonus for all horse-like things */
+	role_modifier = (Role_if(PM_KNIGHT) && mtmp->data->mlet == S_UNICORN) ? 10 : 0;
 	if (!force && (Confusion || Fumbling || Glib || Wounded_legs ||
-		otmp->cursed || (u.ulevel+mtmp->mtame < rnd(MAXULEV/2+5)))) {
+		otmp->cursed || (u.ulevel+mtmp->mtame+role_modifier < rnd(MAXULEV/2+5)))) {
 	    if (Levitation) {
 		pline("%s slips away from you.", Monnam(mtmp));
@@ -331,5 +339,5 @@
 	/* Success */
 	if (!force) {
-	    if (Levitation && !is_floater(ptr) && !is_flyer(ptr))
+	    if (Levitation && !is_floater(ptr) && !is_flyer(ptr) && !is_flying(mtmp))
 	    	/* Must have Lev_at_will at this point */
 	    	pline("%s magically floats up!", Monnam(mtmp));
@@ -352,6 +360,8 @@
 		return;
 
-	/* It takes many turns of riding to exercise skill */
-	if (u.urideturns++ >= 100) {
+	/* It takes many turns of riding to exercise skill...
+	 * but for god's sake, 2,000 turns on the horse just to get to Basic?
+	 * Let's clean that up a bit. */
+	if (u.urideturns++ >= 50) {
 	    u.urideturns = 0;
 	    use_skill(P_RIDING, 1);
@@ -547,5 +557,5 @@
 
 		/* The steed may drop into water/lava */
-		if (!is_flyer(mdat) && !is_floater(mdat) && !is_clinger(mdat)) {
+		if (!is_flyer(mdat) && !is_floater(mdat) && !is_clinger(mdat) && !is_flying(mtmp)) {
 		    if (is_pool(u.ux, u.uy)) {
 			if (!Underwater)
@@ -554,5 +564,5 @@
 			if (!is_swimmer(mdat) && !amphibious(mdat)) {
 			    killed(mtmp);
-			    adjalign(-1);
+				 major_sin();
 			}
 		    } else if (is_lava(u.ux, u.uy)) {
@@ -560,5 +570,5 @@
 			if (!likes_lava(mdat)) {
 			    killed(mtmp);
-			    adjalign(-1);
+				 major_sin();
 			}
 		    }
@@ -602,5 +612,5 @@
 	    } else {
 		killed(mtmp);
-		adjalign(-1);
+		major_sin();
 	    }
 	}
@@ -629,10 +639,12 @@
 	    /* special case is for convoluted vault guard handling */
 	    (DEADMONSTER(mon) && !(mon->isgd && x == 0 && y == 0))) {
-	impossible("placing %s onto map?",
-		   (mon == u.usteed) ? "steed" : "defunct monster");
+	/*impossible("placing %s onto map?",
+		   (mon == u.usteed) ? "steed" : "defunct monster");*/
 	return;
     }
     mon->mx = x, mon->my = y;
     level.monsters[x][y] = mon;
+    if (mon->data == &mons[PM_GIANT_TURTLE] && (!mon->minvis || See_invisible))
+	block_point(x,y);
 }
 
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/src/teleport.c nethack/src/teleport.c
--- nh_orig/src/teleport.c	2003-12-07 18:39:13.000000000 -0500
+++ nethack/src/teleport.c	2010-04-25 07:54:35.678715209 -0400
@@ -8,5 +8,4 @@
 STATIC_DCL boolean FDECL(teleok, (int,int,BOOLEAN_P));
 STATIC_DCL void NDECL(vault_tele);
-STATIC_DCL boolean FDECL(rloc_pos_ok, (int,int,struct monst *));
 STATIC_DCL void FDECL(mvault_tele, (struct monst *));
 
@@ -26,4 +25,5 @@
 	struct permonst *mdat = NULL;
 	boolean ignorewater = ((gpflags & MM_IGNOREWATER) != 0);
+	boolean unsafe = ((gpflags & MM_UNSAFEOK) != 0);
 
 	if (!isok(x, y)) return FALSE;
@@ -60,20 +60,31 @@
 	    mdat = mtmp->data;
 	    if (is_pool(x,y) && !ignorewater) {
+			 if (unsafe) {
+				 return TRUE;
+			 }
 		if (mtmp == &youmonst)
-			return !!(HLevitation || Flying || Wwalking ||
-					Swimming || Amphibious);
-		else	return (is_flyer(mdat) || is_swimmer(mdat) ||
-							is_clinger(mdat));
+				return !!(HLevitation || Flying || Wwalking || Swimming || Amphibious);
+			else	
+				return (is_flyer(mdat) || is_swimmer(mdat) || is_clinger(mdat) || is_flying(mtmp));
 	    } else if (mdat->mlet == S_EEL && rn2(13) && !ignorewater) {
 		return FALSE;
 	    } else if (is_lava(x,y)) {
+			 if (unsafe) {
+				 return TRUE;
+			 }
 		if (mtmp == &youmonst)
 		    return !!HLevitation;
 		else
-		    return (is_flyer(mdat) || likes_lava(mdat));
+				return (is_flyer(mdat) || likes_lava(mdat) || is_flying(mtmp));
 	    }
 	    if (passes_walls(mdat) && may_passwall(x,y)) return TRUE;
 	}
+
 	if (!ACCESSIBLE(levl[x][y].typ)) {
+		if (unsafe) {
+			if (is_pool(x,y) || is_lava(x,y)) {
+				return TRUE;
+			}
+		}
 		if (!(is_pool(x,y) && ignorewater)) return FALSE;
 	}
@@ -81,6 +92,8 @@
 	if (closed_door(x, y) && (!mdat || !amorphous(mdat)))
 		return FALSE;
+
 	if (sobj_at(BOULDER, x, y) && (!mdat || !throws_rocks(mdat)))
 		return FALSE;
+
 	return TRUE;
 }
@@ -327,5 +340,5 @@
 	see_monsters();
 	vision_full_recalc = 1;
-	nomul(0);
+	nomul(0, 0);
 	vision_recalc(0);	/* vision before effects */
 	spoteffects(TRUE);
@@ -415,5 +428,6 @@
 	if (!Blinded) make_blinded(0L,FALSE);
 
-	if ((u.uhave.amulet || On_W_tower_level(&u.uz)) && !rn2(3)) {
+	/* With Gehennom now teleportable again, the amulet must block it all. */
+	if (u.uhave.amulet || On_W_tower_level(&u.uz)) {
 	    You_feel("disoriented for a moment.");
 	    return;
@@ -567,5 +581,5 @@
 	d_level newlevel;
 	const char *escape_by_flying = 0;	/* when surviving dest of -N */
-	char buf[BUFSZ];
+	char buf[BUFSZ] = "";
 	boolean force_dest = FALSE;
 
@@ -880,5 +894,5 @@
 
 /* check whether monster can arrive at location <x,y> via Tport (or fall) */
-STATIC_OVL boolean
+boolean
 rloc_pos_ok(x, y, mtmp)
 register int x, y;		/* coordinates of candidate location */
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/src/timeout.c nethack/src/timeout.c
--- nh_orig/src/timeout.c	2003-12-07 18:39:13.000000000 -0500
+++ nethack/src/timeout.c	2009-11-22 07:19:36.824397915 -0500
@@ -36,5 +36,5 @@
 		HFast = 0L;
 	if (i == 3L)
-		nomul(-3);
+		nomul(-3, "getting stoned");
 	exercise(A_DEX, FALSE);
 }
@@ -138,5 +138,5 @@
 	    HFast = 0L;	/* lose intrinsic speed */
 	    stop_occupation();
-	    if (multi > 0) nomul(0);
+	    if (multi > 0) nomul(0, 0);
 	}
 	exercise(A_DEX, FALSE);
@@ -167,4 +167,5 @@
 
 	if (flags.friday13) baseluck -= 1;
+	if (Lucky) { baseluck += 5; }
 
 	if (u.uluck != baseluck &&
@@ -173,5 +174,6 @@
 	 * stop good luck from timing out; normal luckstones stop both;
 	 * neither is stopped if you don't have a luckstone.
-	 * Luck is based at 0 usually, +1 if a full moon and -1 on Friday 13th
+	 * Luck is based at 0 usually, +1 if a full moon, -1 on Friday 13th
+	 * and +5 if you have the gauntlets of fortune
 	 */
 	    register int time_luck = stone_luck(FALSE);
@@ -208,4 +210,9 @@
 	}
 
+	/* Give a small warning that spell-based reflection is running out. */
+	if (HReflecting == 20 && !Blind) {
+		pline("The shimmering globe around you is becoming faint.");
+	}
+
 #ifdef STEED
 	if (u.ugallop) {
@@ -216,5 +223,7 @@
 
 	for(upp = u.uprops; upp < u.uprops+SIZE(u.uprops); upp++)
-	    if((upp->intrinsic & TIMEOUT) && !(--upp->intrinsic & TIMEOUT)) {
+	    if(!(upp->intrinsic & HAVEPARTIAL) &&	 /* partial intrinsics don't time out */
+				 (upp->intrinsic & TIMEOUT) && 
+				 !(--upp->intrinsic & TIMEOUT)) {
 		switch(upp - u.uprops){
 		case STONED:
@@ -266,4 +275,34 @@
 							Fast ? " a bit" : "");
 			break;
+		case SLOW:
+			You_feel("less sluggish.");
+			break;
+		case REFLECTING:
+			if (!Blind)
+				pline("The shimmering globe around you flickers and vanishes.");
+			else
+				pline("You don't feel very smooth anymore.");
+			/* Monsters will see this, too, and assume it's safe to shoot again */
+			monstseesulose(M_SEEN_REFL);
+			break;
+		/*
+		 * all these need to make sure the external intrinsic isn't there too
+		 */
+		case VULN_FIRE:
+			if (!Vulnerable_fire)
+				You("don't shy away from sparks anymore.");
+			break;
+		case VULN_COLD:
+			if (!Vulnerable_cold)
+				You("aren't nervous about open iceboxes now.");
+			break;
+		case VULN_ELEC:
+			if (!Vulnerable_elec)
+				You("seem to be a less ideal conductor again.");
+			break;
+		case VULN_ACID:
+			if (!Vulnerable_acid)
+				You("don't seem to dissolve so easily anymore.");
+			break;
 		case CONFUSION:
 			HConfusion = 1; /* So make_confused works properly */
@@ -306,9 +345,9 @@
 			break;
 		case SLEEPING:
-			if (unconscious() || Sleep_resistance)
+			if (unconscious() || how_resistant(SLEEP_RES) == 100)
 				HSleeping += rnd(100);
 			else if (Sleeping) {
 				You("fall asleep.");
-				sleeptime = rnd(20);
+				sleeptime = resist_reduce(rnd(20),SLEEP_RES);
 				fall_asleep(-sleeptime, TRUE);
 				HSleeping += sleeptime + rnd(100);
@@ -328,5 +367,5 @@
 			if (u.umoved && !Levitation) {
 			    slip_or_trip();
-			    nomul(-2);
+			    nomul(-2, "fumbling");
 			    nomovemsg = "";
 			    /* The more you are carrying the more likely you
@@ -363,5 +402,5 @@
 {
 	stop_occupation();
-	nomul(how_long);
+	nomul(how_long, "sleeping");
 	/* generally don't notice sounds while sleeping */
 	if (wakeup_msg && multi == how_long) {
@@ -813,5 +852,9 @@
 	    case BRASS_LANTERN:
 	    case OIL_LAMP:
+		 case BAG_OF_POO:
 		switch((int)obj->age) {
+			case 300:
+			case 250:
+			case 200:
 		    case 150:
 		    case 100:
@@ -869,4 +912,10 @@
 			}
 			end_burn(obj, FALSE);
+
+			/* has to happen afterwards */
+			if (obj->otyp == BAG_OF_POO) { 
+				useup(obj);
+				BStealth = 0; 
+			}
 			break;
 
@@ -880,5 +929,5 @@
 		}
 
-		if (obj->age)
+		if (obj && obj->age)
 		    begin_burn(obj, TRUE);
 
@@ -1018,5 +1067,5 @@
  *
  * Burn rules:
- *	potions of oil, lamps & candles:
+ *	potions of oil, lamps, bags of poo & candles:
  *		age = # of turns of fuel left
  *		spe = <unused>
@@ -1049,8 +1098,16 @@
 	boolean do_timer = TRUE;
 
-	if (obj->age == 0 && obj->otyp != MAGIC_LAMP && !artifact_light(obj))
+	if (obj->age == 0 && obj->otyp != MAGIC_LAMP && obj->otyp != FUR_BRAZIER && !artifact_light(obj))
 	    return;
 
 	switch (obj->otyp) {
+		case FUR_BRAZIER:
+			obj->lamplit = 1;
+			do_timer = FALSE;
+			break;
+		case SHIELD_OF_LIGHT:
+			radius = 2;	 /* not quite as good as the others */
+		case GOLD_DRAGON_SCALE_MAIL:
+		case GOLD_DRAGON_SCALES:
 	    case MAGIC_LAMP:
 		obj->lamplit = 1;
@@ -1063,4 +1120,7 @@
 		break;
 
+		/* These last a bit longer due to more, er, fuel */
+		 case BAG_OF_POO:
+		radius = 2;
 	    case BRASS_LANTERN:
 	    case OIL_LAMP:
@@ -1079,4 +1139,8 @@
 
 	    case CANDELABRUM_OF_INVOCATION:
+			if (!u.uevent.invoked) {
+				do_timer = FALSE;
+				obj->lamplit = 1;
+			}
 	    case TALLOW_CANDLE:
 	    case WAX_CANDLE:
@@ -1143,5 +1207,6 @@
 	}
 
-	if (obj->otyp == MAGIC_LAMP || artifact_light(obj))
+	if (obj->otyp == MAGIC_LAMP || artifact_light(obj) ||
+			(obj->otyp == CANDELABRUM_OF_INVOCATION && !u.uevent.invoked))
 	    timer_attached = FALSE;
 
@@ -1195,6 +1260,6 @@
     int count;
 
-    /* no lightning if not the air level or too often, even then */
-    if(!Is_airlevel(&u.uz) || rn2(8))
+    /* no lightning if not stormy level or too often, even then */
+    if(!level.flags.stormy || rn2(8))
 	return;
 
@@ -1221,5 +1286,5 @@
 	if(!u.uinvulnerable) {
 	    stop_occupation();
-	    nomul(-3);
+	    nomul(-3, "hiding from thunderstorm");
 	}
     } else
@@ -1837,8 +1902,8 @@
 	    if (curr->kind == TIMER_OBJECT) {
 		if (ghostly) {
-		    if (!lookup_id_mapping((unsigned)curr->arg, &nid))
+		    if (!lookup_id_mapping((size_t)curr->arg, &nid))
 			panic("relink_timers 1");
 		} else
-		    nid = (unsigned) curr->arg;
+		    nid = (size_t) curr->arg;
 		curr->arg = (genericptr_t) find_oid(nid);
 		if (!curr->arg) panic("cant find o_id %d", nid);
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/src/topten.c nethack/src/topten.c
--- nh_orig/src/topten.c	2003-12-07 18:39:13.000000000 -0500
+++ nethack/src/topten.c	2010-08-16 14:13:30.979837463 -0400
@@ -34,10 +34,10 @@
 #define DTHSZ	100
 #define ROLESZ   3
-#define PERSMAX	 3		/* entries per name/uid per char. allowed */
+#define PERSMAX	 50		/* entries per name/uid per char. allowed */
 #define POINTSMIN	1	/* must be > 0 */
-#define ENTRYMAX	100	/* must be >= 10 */
+#define ENTRYMAX	2000	/* must be >= 10 */
 
 #if !defined(MICRO) && !defined(MAC) && !defined(WIN32)
-#define PERS_IS_UID		/* delete for PERSMAX per name; now per uid */
+/*#define PERS_IS_UID		 delete for PERSMAX per name; now per uid */
 #endif
 struct toptenentry {
@@ -67,8 +67,18 @@
 STATIC_DCL void FDECL(readentry, (FILE *,struct toptenentry *));
 STATIC_DCL void FDECL(writeentry, (FILE *,struct toptenentry *));
+#ifdef XLOGFILE
+STATIC_DCL void FDECL(munge_xlstring, (char *dest, char *src, int n));
+STATIC_DCL void FDECL(write_xlentry, (FILE *,struct toptenentry *));
+#endif
 STATIC_DCL void FDECL(free_ttlist, (struct toptenentry *));
 STATIC_DCL int FDECL(classmon, (char *,BOOLEAN_P));
 STATIC_DCL int FDECL(score_wanted,
 		(BOOLEAN_P, int,struct toptenentry *,int,const char **,int));
+#ifdef RECORD_CONDUCT
+STATIC_DCL long FDECL(encodeconduct, (void));
+#endif
+#ifdef RECORD_ACHIEVE
+STATIC_DCL long FDECL(encodeachieve, (void));
+#endif
 #ifdef NO_SCAN_BRACK
 STATIC_DCL void FDECL(nsb_mung_line,(char*));
@@ -85,4 +95,8 @@
 static winid toptenwin = WIN_ERR;
 
+#ifdef RECORD_START_END_TIME
+static time_t deathtime = 0L;
+#endif
+
 STATIC_OVL void
 topten_print(x)
@@ -153,5 +167,6 @@
 	else {
 		/* Check for backwards compatibility */
-		if (tt->ver_major < 3 ||
+		/* force using the latest method even though we're a weird version */
+		if (0 && tt->ver_major < 3 ||
 				(tt->ver_major == 3 && tt->ver_minor < 3)) {
 			int i;
@@ -203,5 +218,6 @@
 		tt->maxlvl, tt->hp, tt->maxhp, tt->deaths,
 		tt->deathdate, tt->birthdate, tt->uid);
-	if (tt->ver_major < 3 ||
+	/* force using the latest method even though we're a weird version */
+	if (0 && tt->ver_major < 3 ||
 			(tt->ver_major == 3 && tt->ver_minor < 3))
 #ifdef NO_SCAN_BRACK
@@ -227,4 +243,107 @@
 }
 
+#ifdef XLOGFILE
+#define SEP ":"
+#define SEPC ':'
+
+/* copy a maximum of n-1 characters from src to dest, changing ':' and '\n'
+ * to '_'; always null-terminate. */
+STATIC_OVL void
+munge_xlstring(dest, src, n)
+char *dest;
+char *src;
+int n;
+{
+  int i;
+
+  for(i = 0; i < (n - 1) && src[i] != '\0'; i++) {
+    if(src[i] == SEPC || src[i] == '\n')
+      dest[i] = '_';
+    else
+      dest[i] = src[i];
+  }
+
+  dest[i] = '\0';
+
+  return;
+}
+
+STATIC_OVL void
+write_xlentry(rfile,tt)
+FILE *rfile;
+struct toptenentry *tt;
+{
+
+  char buf[DTHSZ+1];
+
+  /* Log all of the data found in the regular logfile */
+  (void)fprintf(rfile,
+                "version=%d.%d.%d"
+                SEP "points=%ld"
+                SEP "deathdnum=%d"
+                SEP "deathlev=%d"
+                SEP "maxlvl=%d"
+                SEP "hp=%d"
+                SEP "maxhp=%d"
+                SEP "deaths=%d"
+                SEP "deathdate=%d"
+                SEP "birthdate=%d"
+                SEP "uid=%d",
+                tt->ver_major, tt->ver_minor, tt->patchlevel,
+                tt->points, tt->deathdnum, tt->deathlev,
+                tt->maxlvl, tt->hp, tt->maxhp, tt->deaths,
+                tt->deathdate, tt->birthdate, tt->uid);
+
+  (void)fprintf(rfile,
+                SEP "role=%s"
+                SEP "race=%s"
+                SEP "gender=%s"
+                SEP "align=%s",
+                tt->plrole, tt->plrace, tt->plgend, tt->plalign);
+   
+   munge_xlstring(buf, plname, DTHSZ + 1);
+  (void)fprintf(rfile, SEP "name=%s", buf);
+
+   munge_xlstring(buf, tt->death, DTHSZ + 1);
+  (void)fprintf(rfile, SEP "death=%s", buf);
+
+#ifdef RECORD_CONDUCT
+  (void)fprintf(rfile, SEP "conduct=0x%lx", encodeconduct());
+#endif
+
+#ifdef RECORD_TURNS
+  (void)fprintf(rfile, SEP "turns=%ld", moves);
+#endif
+
+#ifdef RECORD_ACHIEVE
+  (void)fprintf(rfile, SEP "achieve=0x%lx", encodeachieve());
+#endif
+
+#ifdef RECORD_REALTIME
+  (void)fprintf(rfile, SEP "realtime=%ld", (long)realtime_data.realtime);
+#endif
+
+#ifdef RECORD_START_END_TIME
+  (void)fprintf(rfile, SEP "starttime=%ld", (long)u.ubirthday);
+  (void)fprintf(rfile, SEP "endtime=%ld", (long)deathtime);
+#endif
+
+#ifdef RECORD_GENDER0
+  (void)fprintf(rfile, SEP "gender0=%s", genders[flags.initgend].filecode);
+#endif
+
+#ifdef RECORD_ALIGN0
+  (void)fprintf(rfile, SEP "align0=%s", 
+          aligns[1 - u.ualignbase[A_ORIGINAL]].filecode);
+#endif
+
+  (void)fprintf(rfile, "\n");
+
+}
+
+#undef SEP
+#undef SEPC
+#endif /* XLOGFILE */
+
 STATIC_OVL void
 free_ttlist(tt)
@@ -241,4 +360,89 @@
 }
 
+
+#ifdef LOGFILE
+void
+write_log_entry(how,score)
+int how;
+long score;
+{
+	int uid = getuid();
+	register struct toptenentry *t0;
+	FILE *lfile;
+
+	t0 = newttentry();
+	t0->ver_major = VERSION_MAJOR;
+	t0->ver_minor = VERSION_MINOR;
+	t0->patchlevel = PATCHLEVEL;
+	t0->points = score;
+	t0->deathdnum = u.uz.dnum;
+	t0->deathlev = observable_depth(&u.uz);
+	t0->maxlvl = deepest_lev_reached(TRUE);
+	t0->hp = u.uhp;
+	t0->maxhp = u.uhpmax;
+	t0->deaths = u.umortality;
+	t0->uid = uid;
+	(void) strncpy(t0->plrole, urole.filecode, ROLESZ);
+	t0->plrole[ROLESZ] = '\0';
+	(void) strncpy(t0->plrace, urace.filecode, ROLESZ);
+	t0->plrace[ROLESZ] = '\0';
+	(void) strncpy(t0->plgend, genders[flags.female].filecode, ROLESZ);
+	t0->plgend[ROLESZ] = '\0';
+	(void) strncpy(t0->plalign, aligns[1-u.ualign.type].filecode, ROLESZ);
+	t0->plalign[ROLESZ] = '\0';
+	(void) strncpy(t0->name, plname, NAMSZ);
+	t0->name[NAMSZ] = '\0';
+	t0->death[0] = '\0';
+	switch (killer_format) {
+		default: impossible("bad killer format?");
+		case KILLED_BY_AN:
+			Strcat(t0->death, killed_by_prefix[how]);
+			(void) strncat(t0->death, an(killer),
+						DTHSZ-strlen(t0->death));
+			break;
+		case KILLED_BY:
+			Strcat(t0->death, killed_by_prefix[how]);
+			(void) strncat(t0->death, killer,
+						DTHSZ-strlen(t0->death));
+			break;
+		case NO_KILLER_PREFIX:
+			(void) strncat(t0->death, killer, DTHSZ);
+			break;
+	}
+	t0->birthdate = yyyymmdd(u.ubirthday);
+
+#ifdef RECORD_START_END_TIME
+  /* Make sure that deathdate and deathtime refer to the same time; it
+   * wouldn't be good to have deathtime refer to the day after deathdate. */
+
+#if defined(BSD) && !defined(POSIX_TYPES)
+        (void) time((long *)&deathtime);
+#else
+        (void) time(&deathtime);
+#endif
+
+        t0->deathdate = yyyymmdd(deathtime);
+#else
+        t0->deathdate = yyyymmdd((time_t)0L);
+#endif /* RECORD_START_END_TIME */
+
+	t0->tt_next = 0;
+#ifdef UPDATE_RECORD_IN_PLACE
+	t0->fpos = -1L;
+#endif
+
+	if (lock_file(LOGFILE, SCOREPREFIX, 10)) {
+	    if(!(lfile = fopen_datafile(LOGFILE, "a", SCOREPREFIX))) {
+			 /* should do something here */
+	    } else {
+		writeentry(lfile, t0);
+		(void) fclose(lfile);
+	    }
+	    unlock_file(LOGFILE);
+	}
+
+}
+#endif
+
 void
 topten(how)
@@ -253,7 +457,7 @@
 	register int flg = 0;
 	boolean t0_used;
-#ifdef LOGFILE
-	FILE *lfile;
-#endif /* LOGFILE */
+#ifdef XLOGFILE
+ 	FILE *xlfile;
+#endif /* XLOGFILE */
 
 /* Under DICE 3.0, this crashes the system consistently, apparently due to
@@ -273,5 +477,6 @@
 
 	if (flags.toptenwin) {
-	    toptenwin = create_nhwindow(NHW_TEXT);
+	    /* toptenwin = create_nhwindow(NHW_TEXT); */
+		flags.toptenwin = 0;
 	}
 
@@ -339,15 +544,15 @@
 #endif
 
-#ifdef LOGFILE		/* used for debugging (who dies of what, where) */
-	if (lock_file(LOGFILE, SCOREPREFIX, 10)) {
-	    if(!(lfile = fopen_datafile(LOGFILE, "a", SCOREPREFIX))) {
-		HUP raw_print("Cannot open log file!");
+#ifdef XLOGFILE
+         if(lock_file(XLOGFILE, SCOREPREFIX, 10)) {
+             if(!(xlfile = fopen_datafile(XLOGFILE, "a", SCOREPREFIX))) {
+                  HUP raw_print("Cannot open extended log file!");
 	    } else {
-		writeentry(lfile, t0);
-		(void) fclose(lfile);
+                  write_xlentry(xlfile, t0);
+                  (void) fclose(xlfile);
 	    }
-	    unlock_file(LOGFILE);
+             unlock_file(XLOGFILE);
 	}
-#endif /* LOGFILE */
+#endif /* XLOGFILE */
 
 	if (wizard || discover) {
@@ -359,4 +564,10 @@
 		    wizard ? "wizard" : "discover");
 		topten_print(pbuf);
+#ifdef DUMP_LOG
+		if (dump_fn[0]) {
+		  dump("", pbuf);
+		  dump("", "");
+		}
+#endif
 	    }
 	    goto showwin;
@@ -379,4 +590,7 @@
 
 	HUP topten_print("");
+#ifdef DUMP_LOG
+	dump("", "");
+#endif
 
 	/* assure minimum number of points */
@@ -423,4 +637,8 @@
 			    topten_print(pbuf);
 			    topten_print("");
+#ifdef DUMP_LOG
+			    dump("", pbuf);
+			    dump("", "");
+#endif
 			}
 		    }
@@ -453,15 +671,25 @@
 		}
 #endif	/* UPDATE_RECORD_IN_PLACE */
-		if(!done_stopprint) if(rank0 > 0){
-		    if(rank0 <= 10)
+		if(rank0 > 0){
+		    if(rank0 <= 10) {
+			if(!done_stopprint) 
 			topten_print("You made the top ten list!");
-		    else {
+#ifdef DUMP_LOG
+			dump("", "You made the top ten list!");
+#endif
+		    } else {
 			char pbuf[BUFSZ];
 			Sprintf(pbuf,
 			  "You reached the %d%s place on the top %d list.",
 				rank0, ordin(rank0), ENTRYMAX);
-			topten_print(pbuf);
+			if(!done_stopprint) topten_print(pbuf);
+#ifdef DUMP_LOG
+			dump("", pbuf);
+#endif
 		    }
-		    topten_print("");
+		    if(!done_stopprint) topten_print("");
+#ifdef DUMP_LOG
+		    dump("", "");
+#endif
 		}
 	}
@@ -476,5 +704,5 @@
 #endif
 		) writeentry(rfile, t1);
-	    if (done_stopprint) continue;
+	    /* if (done_stopprint) continue; */
 	    if (rank > flags.end_top &&
 		    (rank < rank0 - flags.end_around ||
@@ -489,6 +717,10 @@
 	    if (rank == rank0 - flags.end_around &&
 		    rank0 > flags.end_top + flags.end_around + 1 &&
-		    !flags.end_own)
-		topten_print("");
+		    !flags.end_own) {
+		if(!done_stopprint) topten_print("");
+#ifdef DUMP_LOG
+		dump("", "");
+#endif
+	    }
 	    if(rank != rank0)
 		outentry(rank, t1, FALSE);
@@ -547,5 +779,8 @@
 	while(bp < linebuf + COLNO - 9) *bp++ = ' ';
 	Strcpy(bp, "Hp [max]");
-	topten_print(linebuf);
+	if(!done_stopprint) topten_print(linebuf);
+#ifdef DUMP_LOG
+	dump("", linebuf);
+#endif
 }
 
@@ -657,4 +892,7 @@
 		    bp--)
 		;
+   /* crude fix for un-wrappable word. 
+    * needs improvement, swallows one character of the long word */ 
+			if (linebuf+15 == bp) { bp += hppos-15; } 
 	    /* special case: if about to wrap in the middle of maximum
 	       dungeon depth reached, wrap in front of it instead */
@@ -665,7 +903,14 @@
 		while (bp < linebuf + (COLNO-1)) *bp++ = ' ';
 		*bp = 0;
-		topten_print_bold(linebuf);
-	    } else
-		topten_print(linebuf);
+		if(!done_stopprint) topten_print_bold(linebuf);
+#ifdef DUMP_LOG
+		dump("*", linebuf[0]==' '? linebuf+1: linebuf);
+#endif
+	    } else {
+		if(!done_stopprint) topten_print(linebuf);
+#ifdef DUMP_LOG
+		dump(" ", linebuf[0]==' '? linebuf+1: linebuf);
+#endif
+	    }
 	    Sprintf(linebuf, "%15s %s", "", linebuf3);
 	    lngr = strlen(linebuf);
@@ -689,7 +934,10 @@
 	    while (bp < linebuf + so) *bp++ = ' ';
 	    *bp = 0;
-	    topten_print_bold(linebuf);
+	    if(!done_stopprint) topten_print_bold(linebuf);
 	} else
-	    topten_print(linebuf);
+	    if(!done_stopprint) topten_print(linebuf);
+#ifdef DUMP_LOG
+	dump(" ", linebuf[0]==' '? linebuf+1: linebuf);
+#endif
 }
 
@@ -736,4 +984,68 @@
 }
 
+#ifdef RECORD_CONDUCT
+long
+encodeconduct(void)
+{
+       long e = 0L;
+
+       if(!u.uconduct.food)            e |= 0x001L;
+       if(!u.uconduct.unvegan)         e |= 0x002L;
+       if(!u.uconduct.unvegetarian)    e |= 0x004L;
+       if(!u.uconduct.gnostic)         e |= 0x008L;
+       if(!u.uconduct.weaphit)         e |= 0x010L;
+       if(!u.uconduct.killer)          e |= 0x020L;
+       if(!u.uconduct.literate)        e |= 0x040L;
+       if(!u.uconduct.polypiles)       e |= 0x080L;
+       if(!u.uconduct.polyselfs)       e |= 0x100L;
+       if(!u.uconduct.wishes)          e |= 0x200L;
+       if(!u.uconduct.wisharti)        e |= 0x400L;
+       if(!num_genocides())            e |= 0x800L;
+
+       return e;
+}
+#endif
+
+#ifdef RECORD_ACHIEVE
+long
+encodeachieve(void)
+{
+  /* Achievement bitfield:
+   * bit  meaning
+   *  0   obtained the Bell of Opening
+   *  1   entered gehennom (by any means)
+   *  2   obtained the Candelabrum of Invocation
+   *  3   obtained the Book of the Dead
+   *  4   performed the invocation ritual
+   *  5   obtained the amulet
+   *  6   entered elemental planes
+   *  7   entered astral plane
+   *  8   ascended (not "escaped in celestial disgrace!")
+   *  9   obtained the luckstone from the Mines
+   *  10  obtained the sokoban prize
+   *  11  killed medusa
+   */
+
+  long r;
+
+  r = 0;
+
+  if(achieve.get_bell)           r |= 1L << 0;
+  if(achieve.enter_gehennom)     r |= 1L << 1;
+  if(achieve.get_candelabrum)    r |= 1L << 2;
+  if(achieve.get_book)           r |= 1L << 3;
+  if(achieve.perform_invocation) r |= 1L << 4;
+  if(achieve.get_amulet)         r |= 1L << 5;
+  if(In_endgame(&u.uz))          r |= 1L << 6;
+  if(Is_astralevel(&u.uz))       r |= 1L << 7;
+  if(achieve.ascended)           r |= 1L << 8;
+  if(achieve.get_luckstone)      r |= 1L << 9;
+  if(achieve.finish_sokoban)     r |= 1L << 10;
+  if(achieve.killed_medusa)      r |= 1L << 11;
+
+  return r;
+}
+#endif
+
 /*
  * print selected parts of score list.
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/src/trap.c nethack/src/trap.c
--- nh_orig/src/trap.c	2003-12-07 18:39:13.000000000 -0500
+++ nethack/src/trap.c	2009-11-22 17:07:41.000272771 -0500
@@ -9,4 +9,5 @@
 STATIC_DCL void FDECL(dofiretrap, (struct obj *));
 STATIC_DCL void NDECL(domagictrap);
+STATIC_DCL void FDECL(rocks_fall, (int, int));
 STATIC_DCL boolean FDECL(emergency_disrobe,(boolean *));
 STATIC_DCL int FDECL(untrap_prob, (struct trap *ttmp));
@@ -275,4 +276,46 @@
 		break;
 	      }
+	    case MAGIC_BEAM_TRAP:
+		{
+		    int d,startdir = rn2(8);
+		    int dist;
+		    int lx, ly;
+		    int ok = 0;
+		    for (d = 0; ((d < 8) && !ok); d++)
+			for (dist = 1; ((dist < 8) && !ok); dist++) {
+			    lx = x;
+			    ly = y;
+			    switch ((startdir + d) % 8) {
+			    case 0: lx += dist; break;
+			    case 1: lx += dist; ly += dist; break;
+			    case 2: ly += dist; break;
+			    case 3: lx -= dist; ly += dist; break;
+			    case 4: lx -= dist; break;
+			    case 5: lx -= dist; ly -= dist; break;
+			    case 6: ly -= dist; break;
+			    case 7: lx += dist; ly -= dist; break;
+			    }
+			    if (isok(lx,ly) && IS_STWALL(levl[lx][ly].typ)) {
+				ttmp->launch.x = lx;
+				ttmp->launch.y = ly;
+				/* no AD_DISN, thanks */
+				ttmp->launch_otyp = -10-(AD_MAGM-1);
+				if (!rn2(15))
+				    ttmp->launch_otyp = -20-(AD_ELEC-1);
+				else if (!rn2(10))
+				    ttmp->launch_otyp = -20-(AD_FIRE-1);
+				else if (!rn2(10))
+				    ttmp->launch_otyp = -10-(AD_COLD-1);
+				else if (!rn2(7))
+				    ttmp->launch_otyp = -20-(AD_DRST-1);
+				else if (!rn2(7))
+				    ttmp->launch_otyp = -20-(AD_ACID-1);
+				else if (!rn2(5))
+				    ttmp->launch_otyp = -10-(AD_SLEE-1);
+				ok = 1;
+			    }
+			}
+		}
+		break;
 	    case ROLLING_BOULDER_TRAP:	/* boulder will roll towards trigger */
 		(void) mkroll_launch(ttmp, x, y, BOULDER, 1L);
@@ -496,5 +539,5 @@
 	    if (historic) {
 		    You_feel("guilty that the historic statue is now gone.");
-		    adjalign(-1);
+			 venial_sin();
 	    }
 	} else if (cause == ANIMATE_SHATTER)
@@ -592,5 +635,5 @@
 	boolean forcebungle = (trflags & FORCEBUNGLE);
 
-	nomul(0);
+	nomul(0, 0);
 
 	/* KMH -- You can't escape the Sokoban level traps */
@@ -661,4 +704,17 @@
 		}
 		break;
+	    case MAGIC_BEAM_TRAP:
+		You_hear("a soft click.");
+		seetrap(trap);
+		if (isok(trap->launch.x,trap->launch.y) && IS_STWALL(levl[trap->launch.x][trap->launch.y].typ)) {
+		    buzz(trap->launch_otyp, 8,
+			 trap->launch.x,trap->launch.y,
+			 sgn(trap->tx - trap->launch.x),sgn(trap->ty - trap->launch.y));
+		    trap->once = 1;
+		} else {
+		    deltrap(trap);
+		    newsym(u.ux,u.uy);
+		}
+		break;
 	    case DART_TRAP:
 		if (trap->once && trap->tseen && !rn2(15)) {
@@ -782,10 +838,11 @@
 	    case SLP_GAS_TRAP:
 		seetrap(trap);
-		if(Sleep_resistance || breathless(youmonst.data)) {
+		if(how_resistant(SLEEP_RES) == 100 || breathless(youmonst.data)) {
+			monstseesu(M_SEEN_SLEEP);
 		    You("are enveloped in a cloud of gas!");
 		    break;
 		}
 		pline("A cloud of gas puts you to sleep!");
-		fall_asleep(-rnd(25), TRUE);
+		fall_asleep(-resist_reduce(rnd(25),SLEEP_RES), TRUE);
 #ifdef STEED
 		(void) steedintrap(trap, (struct obj *)0);
@@ -826,5 +883,5 @@
 			    break;
 			if (u.twoweap || (uwep && bimanual(uwep)))
-			    erode_obj(u.twoweap ? uswapwep : uwep, FALSE, TRUE);
+			    _erode_obj(u.twoweap ? uswapwep : uwep, AD_RUST);
 glovecheck:		(void) rust_dmg(uarmg, "gauntlets", 1, TRUE, &youmonst);
 			/* Not "metal gauntlets" since it gets called
@@ -835,5 +892,5 @@
 			pline("%s your right %s!", A_gush_of_water_hits,
 				    body_part(ARM));
-			erode_obj(uwep, FALSE, TRUE);
+			_erode_obj(uwep,AD_RUST);
 			goto glovecheck;
 		    default:
@@ -1058,11 +1115,26 @@
 	    case MAGIC_TRAP:	    /* A magic trap. */
 		seetrap(trap);
-		if (!rn2(30)) {
+		/* Trap always goes away... but does it toast you? */
+		if (!rn2(15)) {
 		    deltrap(trap);
-		    newsym(u.ux,u.uy);	/* update position */
+			newsym(u.ux,u.uy);
+			if (!rn2(2)) {
 		    You("are caught in a magical explosion!");
 		    losehp(rnd(10), "magical explosion", KILLED_BY_AN);
 		    Your("body absorbs some of the magical energy!");
 		    u.uen = (u.uenmax += 2);
+			} else {
+				if (!Blind) {
+					if (!Hallucination) {
+						pline("A cloud of brightly colored smoke billows up around you!");
+					} else {
+						pline("The floor lights came on!  Let's disco!");
+					}
+				} else {
+					pline("It smells sort of %s in here.", 
+							Hallucination ? "chartreuse" : "smoggy");
+				}
+				incr_itimeout(&HHallucination,rnd(50)+50);
+			}
 		} else domagictrap();
 #ifdef STEED
@@ -1073,8 +1145,9 @@
 	    case ANTI_MAGIC:
 		seetrap(trap);
-		if(Antimagic) {
-		    shieldeff(u.ux, u.uy);
+		if (u.uen > 1) {
+			drain_en(rnd(u.uen / 2) + 2);
+		} else {
 		    You_feel("momentarily lethargic.");
-		} else drain_en(rnd(u.ulevel) + 1);
+		}
 		break;
 
@@ -1181,4 +1254,27 @@
 		break;
 
+		 case SPEAR_TRAP:
+		seetrap(trap);
+		pline("A spear stabs up from a hole in the ground at you!");
+		if (thick_skinned(youmonst.data)) {
+			pline("But it breaks off against your body.");
+			deltrap(trap);
+		} else if (Levitation) {
+			pline("The spear isn't long enough to reach you.");
+		} else if (unsolid(youmonst.data)) {
+			pline("It passes right through you!");
+		} else {
+			pline("Ouch! That hurts!");
+			losehp(rnd(10)+10,"sharpened bamboo stick",KILLED_BY_AN);
+		}
+		break;
+
+		 case COLLAPSE_TRAP:
+			pline("Rocks fall all around you!");
+			deltrap(trap);
+			newsym(u.ux,u.uy);
+			rocks_fall(u.ux,u.uy);
+		 break;
+
 	    default:
 		seetrap(trap);
@@ -1187,4 +1283,66 @@
 }
 
+STATIC_OVL void
+rocks_fall(zx,zy)
+int zx,zy;
+{
+	int dmg = 0;
+	int mdmg,rocks,rx,ry;
+	boolean somehit = FALSE;
+	struct monst* mtmp;
+	struct obj* mhat;
+	struct obj* otmp;
+
+	for (rocks = rnd(100)+100;rocks > 0;rocks--) {
+		rx = zx + rn2(3)-1; 
+		ry = zy + rn2(3)-1;
+		if (levl[rx][ry].typ == ROOM || levl[rx][ry].typ == CORR) {
+			if (rn2(50)) {
+				otmp = mksobj(ROCK,FALSE,FALSE);
+			} else {
+				otmp = mksobj(BOULDER,FALSE,FALSE);
+			}
+			/* in case of weirdness */
+			if (!flooreffects(otmp,rx,ry,"fall")) {
+				place_object(otmp,rx,ry);
+				stackobj(otmp);
+			}
+			/* postpone player's possible death 'til all the rocks are down */
+			if (rx == u.ux && ry == u.uy) { 
+				somehit = TRUE; 
+				dmg += rn2(4) + (otmp->otyp == BOULDER ? d(2,6) : 0);
+			} else if (mtmp = m_at(rx,ry)) {
+				/* spare the player a barrage of messages for each time
+				 * a monster is hit by a rock; just show the killed message */
+				mhat = which_armor(mtmp, W_ARMH);
+				mdmg = rn2(4) + (otmp->otyp == BOULDER ? d(2,6) : 0);
+				if (thick_skinned(mtmp->data) || (mhat && is_metallic(mhat))) {
+					mdmg /= 2;
+				}
+				if (!unsolid(mtmp->data)) {
+					damage_mon(mtmp,mdmg,AD_PHYS);
+					if (mtmp->mhp <= 0) { monkilled(mtmp,"shower of rocks",AD_PHYS); }
+				}
+			}
+			newsym(rx,ry);
+		}
+	}
+
+	if (somehit) {
+		pline("Some rocks land on your %s!",body_part(HEAD));
+		if (uarmh) {
+			if (is_metallic(uarmh)) {
+				pline("Your hard helmet protects you somewhat.");
+				dmg /= 2;
+			} else if (flags.verbose) {
+				Your("%s does not protect you.", xname(uarmh));
+			}
+		}
+	}
+	losehp(dmg,"shower of rocks",KILLED_BY_AN);
+
+}
+
+
 #ifdef STEED
 STATIC_OVL int
@@ -1236,4 +1394,10 @@
 			steedhit = TRUE;
 			break;
+		case SPEAR_TRAP:
+			if (thitm(0, mtmp, (struct obj*)0, rnd(10)+10, FALSE)) {
+				trapkilled = TRUE;
+			}
+			steedhit = TRUE;
+			break;
 		case LANDMINE:
 			if (thitm(0, mtmp, (struct obj *)0, rnd(16), FALSE))
@@ -1266,4 +1430,6 @@
 		    steedhit = TRUE;
 		    break;
+		case COLLAPSE_TRAP:	 /* TODO: make this affect steeds */
+			 break;
 		default:
 			return 0;
@@ -1416,5 +1582,5 @@
 			}
 		} else if (bhitpos.x == u.ux && bhitpos.y == u.uy) {
-			if (multi) nomul(0);
+			if (multi) nomul(0, 0);
 			if (thitu(9 + singleobj->spe,
 				  dmgval(singleobj, &youmonst),
@@ -1651,4 +1817,5 @@
 	struct permonst *mptr = mtmp->data;
 	struct obj *otmp;
+	struct monst* mtmp2;
 
 	if (!trap) {
@@ -1718,4 +1885,13 @@
 	    in_sight = canseemon(mtmp);
 	    see_it = cansee(mtmp->mx, mtmp->my);
+
+		 /* some monsters may learn from others' errors */
+		 for (mtmp2 = fmon; mtmp2; mtmp2 = mtmp2->nmon)
+		 {
+			 if (m_cansee(mtmp2,mtmp->mx,mtmp->my) && !mindless(mtmp2->data))
+			 {
+				 mtmp2->mtrapseen |= (1 << (tt-1));
+			 }
+		 }
 #ifdef STEED
 	    /* assume hero can tell what's going on for the steed */
@@ -1776,5 +1952,5 @@
 
 		case SQKY_BOARD:
-			if(is_flyer(mptr)) break;
+			if(is_flyer(mptr) || is_flying(mtmp)) break;
 			/* stepped on a squeaky board */
 			if (in_sight) {
@@ -1790,5 +1966,5 @@
 			if(mptr->msize > MZ_SMALL &&
 				!amorphous(mptr) && !is_flyer(mptr) &&
-				!is_whirly(mptr) && !unsolid(mptr)) {
+				!is_whirly(mptr) && !unsolid(mptr) && !is_flying(mtmp)) {
 			    mtmp->mtrapped = 1;
 			    if(in_sight) {
@@ -1841,5 +2017,5 @@
 			    target = MON_WEP(mtmp);
 			    if (target && bimanual(target))
-				erode_obj(target, FALSE, TRUE);
+				_erode_obj(target,AD_RUST);
 glovecheck:		    target = which_armor(mtmp, W_ARMG);
 			    (void) rust_dmg(target, "gauntlets", 1, TRUE, mtmp);
@@ -1849,5 +2025,5 @@
 				pline("%s %s's right %s!", A_gush_of_water_hits,
 				    mon_nam(mtmp), mbodypart(mtmp, ARM));
-			    erode_obj(MON_WEP(mtmp), FALSE, TRUE);
+			    _erode_obj(MON_WEP(mtmp),AD_RUST);
 			    goto glovecheck;
 			default:
@@ -1941,5 +2117,5 @@
 		case SPIKED_PIT:
 			fallverb = "falls";
-			if (is_flyer(mptr) || is_floater(mptr) ||
+			if (is_flyer(mptr) || is_floater(mptr) || is_flying(mtmp) ||
 				(mtmp->wormno && count_wsegs(mtmp) > 5) ||
 				is_clinger(mptr)) {
@@ -1970,5 +2146,5 @@
 			    break;	/* don't activate it after all */
 			}
-			if (is_flyer(mptr) || is_floater(mptr) ||
+			if (is_flyer(mptr) || is_floater(mptr) || is_flying(mtmp) ||
 				mptr == &mons[PM_WUMPUS] ||
 				(mtmp->wormno && count_wsegs(mtmp) > 5) ||
@@ -2079,4 +2255,6 @@
 			break;
 		case ANTI_MAGIC:
+			/* simulate energy drain by increasing cast time */
+			mtmp->mspec_used += 2;
 			break;
 
@@ -2084,5 +2262,5 @@
 			if(rn2(3))
 				break; /* monsters usually don't set it off */
-			if(is_flyer(mptr)) {
+			if(is_flyer(mptr) || is_flying(mtmp)) {
 				boolean already_seen = trap->tseen;
 				if (in_sight && !already_seen) {
@@ -2123,12 +2301,12 @@
 			shieldeff(mtmp->mx, mtmp->my);
 		    } else if (!resist(mtmp, WAND_CLASS, 0, NOTELL)) {
-			(void) newcham(mtmp, (struct permonst *)0,
-				       FALSE, FALSE);
+				(void) newcham(mtmp, (struct permonst *)0, FALSE, FALSE);
 			if (in_sight) seetrap(trap);
+				if (!rn2(10)) deltrap(trap);
 		    }
 		    break;
 
 		case ROLLING_BOULDER_TRAP:
-		    if (!is_flyer(mptr)) {
+		    if (!is_flyer(mptr) && !is_flying(mtmp)) {
 			int style = ROLL | (in_sight ? 0 : LAUNCH_UNSEEN);
 
@@ -2150,4 +2328,53 @@
 		    break;
 
+		case SPEAR_TRAP:
+			if (in_sight) {
+				seetrap(trap);
+				pline("A spear stabs up from a hole in the ground!");
+			}
+			if (thick_skinned(mptr)) {
+				if (in_sight) {
+					pline("But it breaks off against %s.",mon_nam(mtmp));
+				}
+				deltrap(trap);
+			} else if (unsolid(mptr)) {
+				if (in_sight) {
+					pline("It passes right through %s!",mon_nam(mtmp));
+				}
+			} else if (is_flyer(mptr) || is_flying(mtmp)) {
+				if (in_sight) {
+					pline("The spear isn't long enough to reach %s.",mon_nam(mtmp));
+				}
+			} else {
+				if (thitm(0, mtmp, (struct obj *)0, rnd(10)+10, FALSE))
+					trapkilled = TRUE;
+				else if (in_sight) {
+					pline("%s is skewered!",Monnam(mtmp));
+				}
+			}
+			 break;
+
+		case COLLAPSE_TRAP:
+			 if (in_sight) {
+				 pline("Rocks suddenly fall all around %s!",mon_nam(mtmp));
+				 deltrap(trap);
+				 rocks_fall(mtmp->mx,mtmp->my);
+			 }
+			 break;
+	    case MAGIC_BEAM_TRAP:
+		if (distu(trap->tx, trap->ty) < 4) You_hear("a faint click.");
+		if (in_sight) {
+		    seetrap(trap);
+		}
+		if (isok(trap->launch.x,trap->launch.y) && IS_STWALL(levl[trap->launch.x][trap->launch.y].typ)) {
+		    buzz(trap->launch_otyp, 8,
+			 trap->launch.x,trap->launch.y,
+			 sgn(trap->tx - trap->launch.x),sgn(trap->ty - trap->launch.y));
+		    trap->once = 1;
+		} else {
+		    deltrap(trap);
+		    newsym(u.ux,u.uy);
+		}
+		break;
 		default:
 			impossible("Some monster encountered a strange trap of type %d.", tt);
@@ -2275,5 +2502,5 @@
 #ifdef STEED
 	if (u.usteed && !is_floater(u.usteed->data) &&
-						!is_flyer(u.usteed->data)) {
+						!is_flyer(u.usteed->data) && !is_flying(u.usteed)) {
 	    if (Lev_at_will)
 	    	pline("%s magically floats up!", Monnam(u.usteed));
@@ -2354,4 +2581,11 @@
 			no_msg = drown();
 
+		if (is_pool(u.ux,u.uy) && !Levitation && !Flying && uarm &&
+				(uarm->otyp == WHITE_DRAGON_SCALE_MAIL || uarm->otyp == WHITE_DRAGON_SCALES)) {
+			levl[u.ux][u.uy].typ = ICE;
+			pline("The pool crackles and freezes under your feet.");
+			bury_objs(u.ux,u.uy);
+		}
+
 		if(is_lava(u.ux,u.uy)) {
 			(void) lava_effects();
@@ -2441,5 +2675,8 @@
 	    pline("A cascade of steamy bubbles erupts from %s!",
 		    the(box ? xname(box) : surface(u.ux,u.uy)));
-	    if (Fire_resistance) You("are uninjured.");
+	    if (how_resistant(FIRE_RES) > 50) {
+			 You("are uninjured.");
+			 monstseesu(M_SEEN_FIRE);
+		 }
 	    else losehp(rnd(3), "boiling water", KILLED_BY);
 	    return;
@@ -2448,6 +2685,7 @@
 	      box ? "bursts" : "erupts",
 	      the(box ? xname(box) : surface(u.ux,u.uy)));
-	if (Fire_resistance) {
+	if (how_resistant(FIRE_RES) == 100) {
 	    shieldeff(u.ux, u.uy);
+		 monstseesu(M_SEEN_FIRE);
 	    num = rn2(2);
 	} else if (Upolyd) {
@@ -2464,5 +2702,5 @@
 		u.mhmax -= rn2(min(u.mhmax,num + 1)), flags.botl = 1;
 	} else {
-	    num = d(2,4);
+	    num = resist_reduce(d(2,4),FIRE_RES);
 	    if (u.uhpmax > u.ulevel)
 		u.uhpmax -= rn2(min(u.uhpmax,num + 1)), flags.botl = 1;
@@ -2511,7 +2749,25 @@
 
 	     case 10:
-	     case 11:
 		      /* sometimes nothing happens */
 			break;
+	     case 11:	/* toggle any intrinsic invisibility */
+			You_hear("a low hum.");
+			if (!Invis) {
+				if (!Blind) { self_invis_message(); }
+			} else if (!EInvis && !pm_invisible(youmonst.data)) {
+				if (!Blind) {
+					if (!See_invisible) {
+						pline("You can see yourself again!");
+					} else {
+						pline("You can't see through yourself anymore.");
+					}
+				}
+			} else { 
+				/* If we're invisible from another source */
+				You_feel("a little more %s now.",HInvis ? "obvious" : "hidden");
+			}
+			HInvis = HInvis ? 0 : HInvis | FROMOUTSIDE;
+			newsym(u.ux,u.uy);
+			break;
 	     case 12: /* a flash of fire */
 			dofiretrap((struct obj *)0);
@@ -2607,4 +2863,5 @@
 	    switch (obj->otyp) {
 	    case ICE_BOX:
+		 case IRON_SAFE:
 		continue;		/* Immune */
 		/*NOTREACHED*/
@@ -2884,13 +3141,4 @@
 		return(FALSE);
 	}
-	if ((Teleportation || can_teleport(youmonst.data)) &&
-		    !u.usleep && (Teleport_control || rn2(3) < Luck+2)) {
-		You("attempt a teleport spell.");	/* utcsri!carroll */
-		if (!level.flags.noteleport) {
-			(void) dotele();
-			if(!is_pool(u.ux,u.uy))
-				return(TRUE);
-		} else pline_The("attempted teleport spell fails.");
-	}
 #ifdef STEED
 	if (u.usteed) {
@@ -2942,4 +3190,14 @@
 		pline("But in vain.");
 	}
+	/* moved after crawl attempt */
+	if ((Teleportation || can_teleport(youmonst.data)) &&
+		    !u.usleep && (Teleport_control || rn2(3) < Luck+2)) {
+		You("attempt a teleport spell.");	/* utcsri!carroll */
+		if (!level.flags.noteleport) {
+			(void) dotele();
+			if(!is_pool(u.ux,u.uy))
+				return(TRUE);
+		} else pline_The("attempted teleport spell fails.");
+	}
 	u.uinwater = 1;
 	You("drown.");
@@ -3030,5 +3288,9 @@
 struct trap *ttmp;
 {
-	struct obj *otmp = mksobj(otyp, TRUE, FALSE);
+	struct obj *otmp;
+	
+	/* "That must have been a claymore mine."  -- DSR */
+	if (otyp == LAND_MINE && rn2(2)) { otyp = TWO_HANDED_SWORD; }
+	otmp = mksobj(otyp, TRUE, FALSE);
 	otmp->quan=cnt;
 	otmp->owt = weight(otmp);
@@ -3125,5 +3387,5 @@
 			if (ttype == BEAR_TRAP) {
 			    if (mtmp->mtame) abuse_dog(mtmp);
-			    if ((mtmp->mhp -= rnd(4)) <= 0) killed(mtmp);
+			    if (damage_mon(mtmp,rnd(4),AD_PHYS)) killed(mtmp);
 			} else if (ttype == WEB) {
 			    if (!webmaker(youmonst.data)) {
@@ -3726,10 +3988,11 @@
 
 			You("are jolted by a surge of electricity!");
-			if(Shock_resistance)  {
+			if(how_resistant(SHOCK_RES) == 100)  {
 			    shieldeff(u.ux, u.uy);
+				 monstseesu(M_SEEN_ELEC);
 			    You("don't seem to be affected.");
 			    dmg = 0;
 			} else
-			    dmg = d(4, 4);
+				dmg = resist_reduce(d(4,4),SHOCK_RES);
 			destroy_item(RING_CLASS, AD_ELEC);
 			destroy_item(WAND_CLASS, AD_ELEC);
@@ -3742,5 +4005,5 @@
 			if (!Free_action) {                        
 			pline("Suddenly you are frozen in place!");
-			nomul(-d(5, 6));
+			nomul(-d(5, 6), "frozen by a trap");
 			exercise(A_DEX, FALSE);
 			nomovemsg = You_can_move_again;
@@ -3891,5 +4154,5 @@
 			if (dam < 1) dam = 1;
 		}
-		if ((mon->mhp -= dam) <= 0) {
+		if (damage_mon(mon,dam,AD_PHYS)) {
 			int xx = mon->mx;
 			int yy = mon->my;
@@ -3931,7 +4194,16 @@
     if (likes_lava(youmonst.data)) return FALSE;
 
-    if (!Fire_resistance) {
+    if (how_resistant(FIRE_RES) < 100) {
 	if(Wwalking) {
-	    dmg = d(6,6);
+			if (!Levitation && !Flying && uarm && 
+					(uarm->otyp == WHITE_DRAGON_SCALE_MAIL || uarm->otyp == WHITE_DRAGON_SCALES)) {
+				levl[u.ux][u.uy].typ = ROOM;
+				if (!rn2(4)) {
+					pline_The("lava cools and solidifies under your feet.");
+				}
+				bury_objs(u.ux,u.uy);
+				return FALSE;
+			}
+			dmg = resist_reduce(d(6,6),FIRE_RES);
 	    pline_The("lava here burns you!");
 	    if(dmg < u.uhp) {
@@ -3968,4 +4240,5 @@
 		    else if(obj == uwep) uwepgone();
 		    else if (obj == uquiver) uqwepgone();
+					else if (obj == ulauncher) ulwepgone();
 		    else if (obj == uswapwep) uswapwepgone();
 		}
@@ -3992,6 +4265,17 @@
 	u.utraptype = TT_LAVA;
 	You("sink into the lava, but it only burns slightly!");
+		monstseesu(M_SEEN_FIRE);
 	if (u.uhp > 1)
 	    losehp(1, lava_killer, KILLED_BY);
+    } else {
+		if (!Levitation && !Flying && uarm && 
+				(uarm->otyp == WHITE_DRAGON_SCALE_MAIL || uarm->otyp == WHITE_DRAGON_SCALES)) {
+			levl[u.ux][u.uy].typ = ROOM;
+			if (!rn2(4)) {
+				pline_The("lava cools and solidifies under your feet.");
+			}
+			bury_objs(u.ux,u.uy);
+			return FALSE;
+		}
     }
     /* just want to burn boots, not all armor; destroy_item doesn't work on
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/src/uhitm.c nethack/src/uhitm.c
--- nh_orig/src/uhitm.c	2003-12-07 18:39:13.000000000 -0500
+++ nethack/src/uhitm.c	2010-04-11 12:36:57.633626023 -0400
@@ -9,4 +9,5 @@
 STATIC_DCL boolean FDECL(hitum, (struct monst *,int,struct attack *));
 STATIC_DCL boolean FDECL(hmon_hitmon, (struct monst *,struct obj *,int));
+STATIC_DCL void FDECL(noisy_hit,(struct monst*,struct obj*,int));
 #ifdef STEED
 STATIC_DCL int FDECL(joust, (struct monst *,struct obj *));
@@ -220,8 +221,7 @@
 	if (Role_if(PM_KNIGHT) && u.ualign.type == A_LAWFUL &&
 	    (!mtmp->mcanmove || mtmp->msleeping ||
-	     (mtmp->mflee && !mtmp->mavenge)) &&
-	    u.ualign.record > -10) {
+	     (mtmp->mflee && !mtmp->mavenge))) {
 	    You("caitiff!");
-	    adjalign(-1);
+		 minor_sin();
 	}
 }
@@ -232,8 +232,8 @@
 {
 	schar tmp;
-	int tmp2;
+	int tmp2,wepskill,twowepskill,useskill;
 
-	tmp = 1 + Luck + abon() + find_mac(mtmp) + u.uhitinc +
-		maybe_polyd(youmonst.data->mlevel, u.ulevel);
+	tmp = 1 + (Luck/3) + abon() + find_mac(mtmp) + u.uhitinc +
+		maybe_polyd(youmonst.data->mlevel, (u.ulevel > 20 ? 20 : u.ulevel));
 
 	check_caitiff(mtmp);
@@ -243,5 +243,5 @@
 	    u.ualign.record > -10) {
 	    You("dishonorably attack the innocent!");
-	    adjalign(-1);
+		 minor_sin();
 	}
 
@@ -274,4 +274,9 @@
 	}
 
+	/* gloves' bonus contributes if unarmed */
+	if (!uwep && uarmg) {
+		tmp += uarmg->spe;
+	}
+
 /*	with a lot of luggage, your agility diminishes */
 	if ((tmp2 = near_capacity()) != 0) tmp -= (tmp2*2) - 1;
@@ -281,7 +286,29 @@
  *	it only for the specific attack (in hmonas()).
  */
-	if (uwep && !Upolyd) {
+	if (!Upolyd) {
 		tmp += hitval(uwep, mtmp);
-		tmp += weapon_hit_bonus(uwep);
+		tmp += weapon_hit_bonus(uwep);  /* picks up bare-handed bonuses */
+	} 
+	/* Let's make UNSKILLED matter, shall we?  If you're UNSKILLED,
+	 * you never get more than an 75% chance to hit anything.
+	 * (we'll let the fisticuffs guys slide on this, they've got
+	 * a hard enough row to hoe anyway)
+	 */
+	if (uwep && !u.uswallow) {
+		wepskill = P_SKILL(weapon_type(uwep));
+		twowepskill = P_SKILL(P_TWO_WEAPON_COMBAT);
+		/* use the lesser skill of two-weapon or your primary */
+		useskill = (u.twoweap && twowepskill < wepskill) ? twowepskill : wepskill;
+		if ((useskill == P_UNSKILLED || useskill == P_ISRESTRICTED) && tmp > 15) {
+			tmp = 15;
+			if (!rn2(3)) {
+				/* there's no 'right way' to swing a cockatrice corpse... */
+				if (uwep->oclass != WEAPON_CLASS && !is_weptool(uwep)) {
+					You("are having a tough time swinging the %s.",aobjnam(uwep, (char*)0));
+				} else {
+					You("aren't sure you're doing this the right way...");
+				}
+			}
+		}
 	}
 	return tmp;
@@ -496,7 +523,14 @@
 			     mon->data == &mons[PM_WATCHMAN] ||
 			     mon->data == &mons[PM_WATCH_CAPTAIN]));
+
+	/* check to see if what we're doing would wake up nearby critters */
+	noisy_hit(mon,obj,thrown);
+
+	/* go ahead and 'hit' the monster */
 	result = hmon_hitmon(mon, obj, thrown);
+
 	if (mon->ispriest && !rn2(2)) ghod_hitsu(mon);
 	if (anger_guards) (void)angry_guards(!flags.soundok);
+
 	return result;
 }
@@ -524,6 +558,8 @@
 	boolean valid_weapon_attack = FALSE;
 	boolean unarmed = !uwep && !uarm && !uarms;
+	boolean bigpunch = (uarmg && uarmg->otyp == GAUNTLETS_OF_FORCE);
 #ifdef STEED
 	int jousting = 0;
+	int joustdmg;
 #endif
 	int wtype;
@@ -544,8 +580,12 @@
 	    else
 		tmp = rnd(2);
-	    valid_weapon_attack = (tmp > 1);
+		 valid_weapon_attack = TRUE;	/* remove dorky 1 = d1 and no bonuses */
 	    /* blessed gloves give bonuses when fighting 'bare-handed' */
 	    if (uarmg && uarmg->blessed && (is_undead(mdat) || is_demon(mdat)))
 		tmp += rnd(4);
+		 /* fighting with fists will get the gloves' bonus... */
+		 if (uarmg) {
+			 tmp += uarmg->spe;
+		 }
 	    /* So do silver rings.  Note: rings are worn under gloves, so you
 	     * don't get both bonuses.
@@ -604,5 +644,8 @@
 		    if (!valid_weapon_attack || mon == u.ustuck || u.twoweap) {
 			;	/* no special bonuses */
-		    } else if (mon->mflee && Role_if(PM_ROGUE) && !Upolyd) {
+		    } else if (mon->mflee && Role_if(PM_ROGUE) && 
+								!Upolyd && !thrown) {
+				 /* Rogues get the backstab bonus for fleeing monsters...
+				  * at least if they're in _melee_ :P */
 			You("strike %s from behind!", mon_nam(mon));
 			tmp += rnd(u.ulevel);
@@ -639,5 +682,6 @@
 		    }
 
-		    if (obj->oartifact &&
+		    if ((obj->oartifact || /* special case for rocks fired from giantslayer */
+					((obj->oclass == GEM_CLASS) && uwep && uwep->oartifact == ART_GIANTSLAYER)) &&
 			artifact_hit(&youmonst, mon, obj, &tmp, dieroll)) {
 			if(mon->mhp <= 0) /* artifact killed monster */
@@ -715,4 +759,5 @@
 			You("succeed in destroying %s camera.  Congratulations!",
 			        shk_your(yourbuf, obj));
+			(void) camera_demon(obj, u.ux,u.uy);
 			useup(obj);
 			return(TRUE);
@@ -776,13 +821,12 @@
 			    return (boolean) (mon->mhp > 0);
 			} else {	/* ordinary egg(s) */
+				struct monst* montmp;
 			    const char *eggp =
 				     (obj->corpsenm != NON_PM && obj->known) ?
 					      the(mons[obj->corpsenm].mname) :
 					      (cnt > 1L) ? "some" : "an";
-			    You("hit %s with %s egg%s.",
-				mon_nam(mon), eggp, plur(cnt));
+			    You("hit %s with %s egg%s.", mon_nam(mon), eggp, plur(cnt));
 			    if (touch_petrifies(mdat) && !stale_egg(obj)) {
-				pline_The("egg%s %s alive any more...",
-				      plur(cnt),
+					pline_The("egg%s %s alive any more...", plur(cnt),
 				      (cnt == 1L) ? "isn't" : "aren't");
 				if (obj->timed) obj_stop_timers(obj);
@@ -799,4 +843,10 @@
 				exercise(A_WIS, FALSE);
 			    }
+				 /* Oz reference: Nomes ('gnomes') are afraid of eggs */
+				 for (montmp = fmon; montmp; montmp = montmp->nmon) {
+					 if (is_gnome(montmp->data) && m_canseeu(montmp)) {
+						 monflee(montmp,rnd(6)+4,TRUE,TRUE);
+					 }
+				 }
 			}
 			break;
@@ -890,9 +940,21 @@
 	if (get_dmg_bonus && tmp > 0) {
 		tmp += u.udaminc;
-		/* If you throw using a propellor, you don't get a strength
-		 * bonus but you do get an increase-damage bonus.
+		/* If you throw using a propellor, you don't get a full strength
+		 * bonus.  For that matter, if you throw anything _period_ 
+		 * you don't get a full strength bonus; it's silly to consider that 
+		 * you could throw anything hard enough to match the force with 
+		 * which you could strike holding it.
+		 *
+		 * Magic increase-damage is different; it's _magic_.
 		 */
-		if(!thrown || !obj || !uwep || !ammo_and_launcher(obj, uwep))
+		if(!thrown || !obj || !uwep) /* || !ammo_and_launcher(obj, uwep)) */
 		    tmp += dbon();
+		else if (thrown)
+			tmp += (dbon() > 1) ? 2 : dbon();
+	}
+
+	/* Red make Zog MAD!  Zog hit harder. */
+	if (uarm && (uarm->otyp == RED_DRAGON_SCALE_MAIL || uarm->otyp == RED_DRAGON_SCALES)) {
+		tmp += rnd(6);
 	}
 
@@ -908,15 +970,19 @@
 	}
 
-	if (ispoisoned) {
+	if (ispoisoned || (obj && obj->oartifact == ART_DIRGE)) {
 	    int nopoison = (10 - (obj->owt/10));            
 	    if(nopoison < 2) nopoison = 2;
 	    if Role_if(PM_SAMURAI) {
 		You("dishonorably use a poisoned weapon!");
-		adjalign(-sgn(u.ualign.type));
+		minor_sin();
 	    } else if ((u.ualign.type == A_LAWFUL) && (u.ualign.record > -10)) {
 		You_feel("like an evil coward for using a poisoned weapon.");
-		adjalign(-1);
+		if (Role_if(PM_KNIGHT)) {
+			minor_sin();
+		} else {
+			venial_sin();
 	    }
-	    if (obj && !rn2(nopoison)) {
+	    }
+	    if (obj && !rn2(nopoison) && obj->oartifact != ART_DIRGE) {
 		obj->opoisoned = FALSE;
 		Your("%s %s no longer poisoned.", xname(obj),
@@ -948,5 +1014,16 @@
 #ifdef STEED
 	if (jousting) {
-	    tmp += d(2, (obj == uwep) ? 10 : 2);	/* [was in dmgval()] */
+		/*
+		 * jousting damage is a bit too strong in the early game
+		 * ...another change necessitated by making the Knight 100%
+		 * to ride his starting pony.
+		 *
+		 * While it's appropriate to consider that a fully-armored Knight
+		 * on a horse would be able to completely mop up the Mines,
+		 * game balance says there should be at least SOME effort
+		 * involved in getting to the luckstone.... 
+		 */
+		 joustdmg = 5 + u.ulevel/3;	 /* 2d5 -> 2d15 */
+	    tmp += d(2, (obj == uwep) ? joustdmg : 2);	/* [was in dmgval()] */
 	    You("joust %s%s",
 			 mon_nam(mon), canseemon(mon) ? exclam(tmp) : ".");
@@ -972,20 +1049,24 @@
 	/* VERY small chance of stunning opponent if unarmed. */
 	if (unarmed && tmp > 1 && !thrown && !obj && !Upolyd) {
-	    if (rnd(100) < P_SKILL(P_BARE_HANDED_COMBAT) &&
-			!bigmonst(mdat) && !thick_skinned(mdat)) {
-		if (canspotmon(mon))
-		    pline("%s %s from your powerful strike!", Monnam(mon),
-			  makeplural(stagger(mon->data, "stagger")));
+	    if ((rnd(100) < P_SKILL(P_BARE_HANDED_COMBAT) && !bigmonst(mdat) && !thick_skinned(mdat)) || bigpunch) {
+			/* try to avoid spamming the user with "powerful strike" messages just because they're
+			 * slinging around the gloves of punchy */
+			if (canspotmon(mon)) {
+				if (!bigpunch || !rn2(3)) {
+					pline("%s %s from your powerful strike!", Monnam(mon), makeplural(stagger(mon->data, "stagger")));
+					hittxt = TRUE;
+				}
+			}
 		/* avoid migrating a dead monster */
 		if (mon->mhp > tmp) {
-		    mhurtle(mon, u.dx, u.dy, 1);
+				mhurtle(mon, u.dx, u.dy, (bigmonst(mdat) || thick_skinned(mdat) || !bigpunch) ? 1 : rnd(4));
 		    mdat = mon->data; /* in case of a polymorph trap */
 		    if (DEADMONSTER(mon)) already_killed = TRUE;
 		}
-		hittxt = TRUE;
 	    }
 	}
 
-	if (!already_killed) mon->mhp -= tmp;
+	/* artifact_hit handles flaming-sword type damage */
+	if (!already_killed) damage_mon(mon,tmp,AD_PHYS);
 	/* adjustments might have made tmp become less than what
 	   a level draining artifact has already done to max HP */
@@ -1008,4 +1089,12 @@
 	}
 
+	if (mdat == &mons[PM_JUIBLEX] && mon->mhp > 1 && !thrown && !mon->mcan)
+	{
+		if (clone_mon(mon, 0, 0)) {
+			pline("%s swirls and reforms in two!", Monnam(mon));
+			hittxt = FALSE;
+		}
+	}
+
 	if (!hittxt &&			/*( thrown => obj exists )*/
 	  (!destroyed || (thrown && m_shot.n > 1 && m_shot.o == obj->otyp))) {
@@ -1066,4 +1155,63 @@
 }
 
+/* It's always seemed a bit odd that you can chop up a throne room,
+ * piece by piece, and nothing ever wakes up, yes?  Let's curb
+ * that behavior a bit; fighting is noisy!  This is a place to
+ * drop any special noise effects you may want to occur when a
+ * particular monster is hit.  */
+
+STATIC_OVL void
+noisy_hit(mtmp,otmp,thrown)
+struct monst* mtmp;
+struct obj* otmp;
+int thrown;
+{
+	struct monst* mtmp2;
+	int noiserange;
+	schar skilltype = P_NONE;
+
+	if (otmp && otmp->oclass == WEAPON_CLASS) { 
+		skilltype = objects[otmp->otyp].oc_skill; 
+	}
+
+	/* properly fired missiles shouldn't make much noise on impact,
+	 * and thrown darts, shuriken, and knives are by definition sneaky */
+	if (otmp && thrown) {
+		if ((ammo_and_launcher(otmp,uwep) && rn2(3)) || 
+				otmp->otyp == DART || otmp->otyp == SHURIKEN || skilltype == P_KNIFE) {
+			return;
+		}
+	}
+
+	/* If you're stealthy, you can slit throats with knives */
+	if (otmp && Stealth && skilltype == P_KNIFE) {
+		return;
+	}
+
+	/* Stealth will reduce the amount of noise made while fighting,
+	 * but won't reduce it entirely to zero */
+	noiserange = Stealth ? 9 : 64;
+
+	/* Some things are just never sneaky.
+	 * For example, smacking things with lightning is loud.
+	 * (TODO: add wand sounds for loud wands) */
+	if (otmp && (otmp->oclass != WEAPON_CLASS || 
+				otmp->oartifact == ART_MJOLLNIR || otmp->otyp == BULLWHIP)) {
+		noiserange = 64;
+	}
+
+	/* Check and see who was close enough to hear it */
+	for (mtmp2 = fmon; mtmp2; mtmp2 = mtmp2->nmon) {
+		if (dist2(mtmp->mx,mtmp->my,mtmp2->mx,mtmp2->my) < noiserange) {
+			/* Rogues get a bit of a bonus for knowing how to kill
+			 * in nice, quiet ways */
+			if (rn2(Role_if(PM_ROGUE) ? 3 : 5)) {
+				mtmp2->msleeping = 0;
+			}
+		}
+	}
+}
+
+
 STATIC_OVL boolean
 shade_aware(obj)
@@ -1470,5 +1618,5 @@
 			pline("%s suddenly seems weaker!", Monnam(mdef));
 			mdef->mhpmax -= xtmp;
-			if ((mdef->mhp -= xtmp) <= 0 || !mdef->m_lev) {
+			if (damage_mon(mdef,xtmp,AD_DRLI) || !mdef->m_lev) {
 				pline("%s dies!", Monnam(mdef));
 				xkilled(mdef,0);
@@ -1525,4 +1673,7 @@
 			}
 		    }
+		    if (how_resistant(COLD_RES) != 100 && mdef->data == &mons[PM_BLUE_JELLY]) {
+				pline("Aggh!  Brain freeze!");
+			 }
 		    break;
 		}
@@ -1640,5 +1791,5 @@
 
 	mdef->mstrategy &= ~STRAT_WAITFORU; /* in case player is very fast */
-	if((mdef->mhp -= tmp) < 1) {
+	if(damage_mon(mdef,tmp,mattk->adtyp)) {
 	    if (mdef->mtame && !cansee(mdef->mx,mdef->my)) {
 		You_feel("embarrassed for a moment.");
@@ -1690,5 +1841,5 @@
 		if (!resistance) {
 		    pline("%s gets blasted!", Monnam(mdef));
-		    mdef->mhp -= tmp;
+			 damage_mon(mdef,tmp,AD_ELEC);
 		    if (mdef->mhp <= 0) {
 			 killed(mdef);
@@ -1814,5 +1965,5 @@
 				You("digest %s.", mon_nam(mdef));
 				if (Slow_digestion) tmp *= 2;
-				nomul(-tmp);
+				nomul(-tmp, "digesting something");
 				nomovemsg = msgbuf;
 			    } else pline("%s", msgbuf);
@@ -1892,5 +2043,5 @@
 		}
 		end_engulf();
-		if ((mdef->mhp -= dam) <= 0) {
+		if (damage_mon(mdef,dam,mattk->adtyp)) {
 		    killed(mdef);
 		    if (mdef->mhp <= 0)	/* not lifesaved */
@@ -1955,9 +2106,7 @@
 	 * attack.  Is this really desirable?
 	 */
-			if (uwep) {
 			    hittmp = hitval(uwep, mon);
 			    hittmp += weapon_hit_bonus(uwep);
 			    tmp += hittmp;
-			}
 			dhit = (tmp > (dieroll = rnd(20)) || u.uswallow);
 			/* KMH -- Don't accumulate to-hit bonuses */
@@ -2164,4 +2313,6 @@
 		if (!Acid_resistance)
 			mdamageu(mon, tmp);
+		else
+			monstseesu(M_SEEN_ACID);
 		if(!rn2(30)) erode_armor(&youmonst, TRUE);
 	    }
@@ -2268,5 +2419,5 @@
 			    You("are frozen by %s gaze!",
 				  s_suffix(mon_nam(mon)));
-			    nomul((ACURR(A_WIS) > 12 || rn2(4)) ? -tmp : -127);
+			    nomul((ACURR(A_WIS) > 12 || rn2(4)) ? -tmp : -127, "frozen by a monster's gaze");
 			}
 		    } else {
@@ -2280,5 +2431,5 @@
 		    You("are frozen by %s!", mon_nam(mon));
 	    	    nomovemsg = 0;	/* default: "you can move again" */
-		    nomul(-tmp);
+		    nomul(-tmp, "frozen by a monster");
 		    exercise(A_DEX, FALSE);
 		}
@@ -2286,6 +2437,7 @@
 	      case AD_COLD:		/* brown mold or blue jelly */
 		if(monnear(mon, u.ux, u.uy)) {
-		    if(Cold_resistance) {
+		    if(how_resistant(COLD_RES) == 100) {
 			shieldeff(u.ux, u.uy);
+				monstseesu(M_SEEN_COLD);
 			You_feel("a mild chill.");
 			ugolemeffects(AD_COLD, tmp);
@@ -2293,4 +2445,5 @@
 		    }
 		    You("are suddenly very cold!");
+			 tmp = resist_reduce(tmp,COLD_RES);
 		    mdamageu(mon, tmp);
 		/* monster gets stronger with your heat! */
@@ -2308,6 +2461,7 @@
 	      case AD_FIRE:
 		if(monnear(mon, u.ux, u.uy)) {
-		    if(Fire_resistance) {
+					if(how_resistant(FIRE_RES) == 100) {
 			shieldeff(u.ux, u.uy);
+						monstseesu(M_SEEN_FIRE);
 			You_feel("mildly warm.");
 			ugolemeffects(AD_FIRE, tmp);
@@ -2315,10 +2469,12 @@
 		    }
 		    You("are suddenly very hot!");
+					tmp = resist_reduce(tmp,FIRE_RES);
 		    mdamageu(mon, tmp);
 		}
 		break;
 	      case AD_ELEC:
-		if(Shock_resistance) {
+				if(how_resistant(SHOCK_RES) == 100) {
 		    shieldeff(u.ux, u.uy);
+					monstseesu(M_SEEN_ELEC);
 		    You_feel("a mild tingle.");
 		    ugolemeffects(AD_ELEC, tmp);
@@ -2326,5 +2482,25 @@
 		}
 		You("are jolted with electricity!");
+				tmp = resist_reduce(tmp,SHOCK_RES);
+				mdamageu(mon, tmp);
+				break;
+			case AD_DISE:	/* gray fungus or Juiblex, for now */
+				if (mon->data == &mons[PM_JUIBLEX])
+				{
+					if (Sick_resistance) {
+						You("are sprayed with a vile ichor, but it doesn't hurt at all.");
+					} else {
+						You("are sprayed with a vile ichor!");
+						make_sick(20, "the blood of Juiblex", TRUE, SICK_NONVOMITABLE);
+					}
+				} else {
+					if (Sick_resistance) {
+						You("are covered with botulism spores, but they seem to be inert.");
+					} else {
+						You("are covered with botulism spores!");
 		mdamageu(mon, tmp);
+						make_sick(20, "bad case of botulism", TRUE, SICK_NONVOMITABLE);
+					}
+				}
 		break;
 	      default:
@@ -2369,15 +2545,15 @@
 	case AD_ACID:
 	    if(!rn2(6)) {
-		erode_obj(obj, TRUE, FALSE);
+		_erode_obj(obj,AD_ACID);
 	    }
 	    break;
 	case AD_RUST:
 	    if(!mon->mcan) {
-		erode_obj(obj, FALSE, FALSE);
+		_erode_obj(obj,AD_RUST);
 	    }
 	    break;
 	case AD_CORR:
 	    if(!mon->mcan) {
-		erode_obj(obj, TRUE, FALSE);
+		_erode_obj(obj,AD_ACID);
 	    }
 	    break;
@@ -2394,5 +2570,6 @@
 	}
 
-	if (carried(obj)) update_inventory();
+	/* erode_obj might have made it go away */
+	if (obj && carried(obj)) update_inventory();
 }
 
@@ -2485,5 +2662,5 @@
 		    pline("%s %s!", Monnam(mtmp), amt > mtmp->mhp / 2 ?
 			  "wails in agony" : "cries out in pain");
-		    if ((mtmp->mhp -= amt) <= 0) {
+		    if (damage_mon(mtmp,amt,AD_BLND)) {
 			if (flags.mon_moving)
 			    monkilled(mtmp, (char *)0, AD_BLND);
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/src/u_init.c nethack/src/u_init.c
--- nh_orig/src/u_init.c	2003-12-07 18:39:13.000000000 -0500
+++ nethack/src/u_init.c	2010-04-11 12:36:57.634626035 -0400
@@ -73,5 +73,5 @@
 	{ LONG_SWORD, 1, WEAPON_CLASS, 1, UNDEF_BLESS },
 	{ LANCE, 1, WEAPON_CLASS, 1, UNDEF_BLESS },
-	{ RING_MAIL, 1, ARMOR_CLASS, 1, UNDEF_BLESS },
+	{ PLATE_MAIL, 0, ARMOR_CLASS, 1, UNDEF_BLESS },
 	{ HELMET, 0, ARMOR_CLASS, 1, UNDEF_BLESS },
 	{ SMALL_SHIELD, 0, ARMOR_CLASS, 1, UNDEF_BLESS },
@@ -121,5 +121,5 @@
 static struct trobj Rogue[] = {
 #define R_DAGGERS	1
-	{ SHORT_SWORD, 0, WEAPON_CLASS, 1, UNDEF_BLESS },
+	{ STILETTO, 1, WEAPON_CLASS, 1, UNDEF_BLESS },
 	{ DAGGER, 0, WEAPON_CLASS, 10, 0 },	/* quan is variable */
 	{ LEATHER_ARMOR, 1, ARMOR_CLASS, 1, UNDEF_BLESS },
@@ -162,5 +162,5 @@
 #define W_MULTEND	6
 	{ QUARTERSTAFF, 1, WEAPON_CLASS, 1, 1 },
-	{ CLOAK_OF_MAGIC_RESISTANCE, 0, ARMOR_CLASS, 1, UNDEF_BLESS },
+	{ CLOAK_OF_PROTECTION, 0, ARMOR_CLASS, 1, UNDEF_BLESS },
 	{ UNDEF_TYP, UNDEF_SPE, WAND_CLASS, 1, UNDEF_BLESS },
 	{ UNDEF_TYP, UNDEF_SPE, RING_CLASS, 2, UNDEF_BLESS },
@@ -168,4 +168,5 @@
 	{ UNDEF_TYP, UNDEF_SPE, SCROLL_CLASS, 3, UNDEF_BLESS },
 	{ SPE_FORCE_BOLT, 0, SPBOOK_CLASS, 1, 1 },
+	{ SPE_PROTECTION, 0, SPBOOK_CLASS, 1, 1},
 	{ UNDEF_TYP, UNDEF_SPE, SPBOOK_CLASS, 1, UNDEF_BLESS },
 	{ 0, 0, 0, 0, 0 }
@@ -180,8 +181,4 @@
 	{ 0, 0, 0, 0, 0 }
 };
-static struct trobj Magicmarker[] = {
-	{ MAGIC_MARKER, UNDEF_SPE, TOOL_CLASS, 1, 0 },
-	{ 0, 0, 0, 0, 0 }
-};
 static struct trobj Lamp[] = {
 	{ OIL_LAMP, 1, TOOL_CLASS, 1, 0 },
@@ -200,4 +197,12 @@
 	{ 0, 0, 0, 0, 0 }
 };
+static struct trobj Poison[] = {
+	{ POT_SICKNESS, 0, POTION_CLASS, 2, 0 },
+	{ 0, 0, 0, 0, 0 }
+};
+static struct trobj Pickaxe[] = {
+	{ PICK_AXE, 0, TOOL_CLASS, 1, 0 },
+	{ 0, 0, 0, 0, 0 }
+};
 #ifdef TOURIST
 static struct trobj Leash[] = {
@@ -249,4 +254,8 @@
     { PM_GNOME, BOW,			CROSSBOW	      },
     { PM_GNOME, ARROW,			CROSSBOW_BOLT	      },
+	 { PM_GNOME, HELMET,	GNOMISH_HELM },
+	 { PM_GNOME, LOW_BOOTS, GNOMISH_BOOTS },
+	 { PM_GNOME, HIGH_BOOTS, GNOMISH_BOOTS },
+	 { PM_GNOME, LEATHER_ARMOR, GNOMISH_SUIT },
     { NON_PM,	STRANGE_OBJECT,		STRANGE_OBJECT	      }
 };
@@ -280,5 +289,5 @@
     { P_QUARTERSTAFF, P_BASIC },	{ P_SPEAR, P_SKILLED },
     { P_TRIDENT, P_SKILLED },		{ P_BOW, P_BASIC },
-    { P_ATTACK_SPELL, P_SKILLED },
+    { P_ATTACK_SPELL, P_SKILLED }, { P_ESCAPE_SPELL, P_BASIC },
 #ifdef STEED
     { P_RIDING, P_BASIC },
@@ -290,5 +299,5 @@
 
 static const struct def_skill Skill_C[] = {
-    { P_DAGGER, P_BASIC },		{ P_KNIFE,  P_SKILLED },
+    { P_KNIFE,  P_SKILLED },
     { P_AXE, P_SKILLED },		{ P_PICK_AXE, P_BASIC },
     { P_CLUB, P_EXPERT },		{ P_MACE, P_EXPERT },
@@ -298,7 +307,7 @@
     { P_JAVELIN, P_SKILLED },		{ P_TRIDENT, P_SKILLED },
     { P_BOW, P_SKILLED },		{ P_SLING, P_EXPERT },
-    { P_ATTACK_SPELL, P_BASIC },	{ P_MATTER_SPELL, P_SKILLED },
-    { P_BOOMERANG, P_EXPERT },		{ P_UNICORN_HORN, P_BASIC },
-    { P_BARE_HANDED_COMBAT, P_MASTER },
+    { P_ESCAPE_SPELL, P_SKILLED },	{ P_MATTER_SPELL, P_SKILLED },
+    { P_BOOMERANG, P_EXPERT }, { P_BARE_HANDED_COMBAT, P_MASTER },
+    { P_TWO_WEAPON_COMBAT, P_BASIC },
     { P_NONE, 0 }
 };
@@ -313,5 +322,5 @@
     { P_SLING, P_SKILLED },		{ P_DART, P_EXPERT },
     { P_SHURIKEN, P_SKILLED },		{ P_UNICORN_HORN, P_EXPERT },
-    { P_HEALING_SPELL, P_EXPERT },
+    { P_HEALING_SPELL, P_EXPERT }, { P_MATTER_SPELL, P_BASIC },
     { P_BARE_HANDED_COMBAT, P_BASIC },
     { P_NONE, 0 }
@@ -321,15 +330,14 @@
     { P_DAGGER, P_BASIC },		{ P_KNIFE, P_BASIC },
     { P_AXE, P_SKILLED },		{ P_PICK_AXE, P_BASIC },
-    { P_SHORT_SWORD, P_SKILLED },	{ P_BROAD_SWORD, P_SKILLED },
-    { P_LONG_SWORD, P_EXPERT },	{ P_TWO_HANDED_SWORD, P_SKILLED },
+    { P_SHORT_SWORD, P_SKILLED },	{ P_BROAD_SWORD, P_EXPERT },
+    { P_LONG_SWORD, P_EXPERT },	{ P_TWO_HANDED_SWORD, P_EXPERT },
     { P_SCIMITAR, P_BASIC },		{ P_SABER, P_SKILLED },
-    { P_CLUB, P_BASIC },		{ P_MACE, P_SKILLED },
+    { P_CLUB, P_BASIC },		{ P_MACE, P_BASIC },
     { P_MORNING_STAR, P_SKILLED },	{ P_FLAIL, P_BASIC },
-    { P_HAMMER, P_BASIC },		{ P_POLEARMS, P_SKILLED },
-    { P_SPEAR, P_SKILLED },		{ P_JAVELIN, P_SKILLED },
+    { P_HAMMER, P_BASIC },		{ P_POLEARMS, P_EXPERT },
+    { P_SPEAR, P_EXPERT },		{ P_JAVELIN, P_BASIC },
     { P_TRIDENT, P_BASIC },		{ P_LANCE, P_EXPERT },
     { P_BOW, P_BASIC },			{ P_CROSSBOW, P_SKILLED },
-    { P_ATTACK_SPELL, P_SKILLED },	{ P_HEALING_SPELL, P_SKILLED },
-    { P_CLERIC_SPELL, P_SKILLED },
+    { P_HEALING_SPELL, P_SKILLED }, { P_CLERIC_SPELL, P_SKILLED },
 #ifdef STEED
     { P_RIDING, P_EXPERT },
@@ -363,5 +371,5 @@
     { P_BOOMERANG, P_BASIC },		{ P_UNICORN_HORN, P_SKILLED },
     { P_HEALING_SPELL, P_EXPERT },	{ P_DIVINATION_SPELL, P_EXPERT },
-    { P_CLERIC_SPELL, P_EXPERT },
+    { P_CLERIC_SPELL, P_EXPERT }, { P_MATTER_SPELL, P_BASIC },
     { P_BARE_HANDED_COMBAT, P_BASIC },
     { P_NONE, 0 }
@@ -399,5 +407,5 @@
     { P_DART, P_EXPERT },	 { P_SHURIKEN, P_SKILLED },
     { P_BOOMERANG, P_EXPERT },	 { P_WHIP, P_BASIC },
-    { P_HEALING_SPELL, P_BASIC },
+    { P_HEALING_SPELL, P_BASIC }, { P_MATTER_SPELL, P_BASIC },
     { P_DIVINATION_SPELL, P_EXPERT },
     { P_ESCAPE_SPELL, P_BASIC },
@@ -405,4 +413,5 @@
     { P_RIDING, P_BASIC },
 #endif
+    { P_TWO_WEAPON_COMBAT, P_BASIC },
     { P_BARE_HANDED_COMBAT, P_BASIC },
     { P_NONE, 0 }
@@ -444,5 +453,5 @@
     { P_WHIP, P_BASIC },		{ P_UNICORN_HORN, P_SKILLED },
     { P_DIVINATION_SPELL, P_BASIC },	{ P_ENCHANTMENT_SPELL, P_BASIC },
-    { P_ESCAPE_SPELL, P_SKILLED },
+    { P_ESCAPE_SPELL, P_SKILLED }, { P_MATTER_SPELL, P_BASIC },
 #ifdef STEED
     { P_RIDING, P_BASIC },
@@ -475,13 +484,9 @@
 static const struct def_skill Skill_W[] = {
     { P_DAGGER, P_EXPERT },		{ P_KNIFE,  P_SKILLED },
-    { P_AXE, P_SKILLED },		{ P_SHORT_SWORD, P_BASIC },
-    { P_CLUB, P_SKILLED },		{ P_MACE, P_BASIC },
-    { P_QUARTERSTAFF, P_EXPERT },	{ P_POLEARMS, P_SKILLED },
-    { P_SPEAR, P_BASIC },		{ P_JAVELIN, P_BASIC },
-    { P_TRIDENT, P_BASIC },		{ P_SLING, P_SKILLED },
-    { P_DART, P_EXPERT },		{ P_SHURIKEN, P_BASIC },
-    { P_ATTACK_SPELL, P_EXPERT },	{ P_HEALING_SPELL, P_SKILLED },
-    { P_DIVINATION_SPELL, P_EXPERT },	{ P_ENCHANTMENT_SPELL, P_SKILLED },
-    { P_CLERIC_SPELL, P_SKILLED },	{ P_ESCAPE_SPELL, P_EXPERT },
+    { P_CLUB, P_BASIC },		{ P_QUARTERSTAFF, P_EXPERT },
+    { P_DART, P_SKILLED },
+    { P_ATTACK_SPELL, P_EXPERT },	{ P_HEALING_SPELL, P_EXPERT },
+    { P_DIVINATION_SPELL, P_EXPERT },	{ P_ENCHANTMENT_SPELL, P_EXPERT },
+    { P_CLERIC_SPELL, P_BASIC },	{ P_ESCAPE_SPELL, P_EXPERT },
     { P_MATTER_SPELL, P_EXPERT },
 #ifdef STEED
@@ -518,4 +523,6 @@
 {
 	register int i;
+	struct permonst* shambler = &mons[PM_SHAMBLING_HORROR];
+	struct attack* attkptr;
 
 	flags.female = flags.initgend;
@@ -535,5 +542,5 @@
 	uarm = uarmc = uarmh = uarms = uarmg = uarmf = 0;
 	uwep = uball = uchain = uleft = uright = 0;
-	uswapwep = uquiver = 0;
+	uswapwep = uquiver = ulauncher = 0;
 	u.twoweap = 0;
 	u.ublessed = 0;				/* not worthy yet */
@@ -577,4 +584,6 @@
 	u.ulevel = u.ulevelmax = 1;
 
+	u.u_telepathy_dist = 0;
+
 	init_uhunger();
 	for (i = 0; i <= MAXSPELL; i++) spl_book[i].sp_id = NO_SPELL;
@@ -597,4 +606,6 @@
 	u.xray_range = -1;
 
+	/* Everyone knows what the scroll of identify is. */
+	knows_object(SCR_IDENTIFY);
 
 	/*** Role-specific initializations ***/
@@ -608,5 +619,4 @@
 		if(!rn2(10)) ini_inv(Tinopener);
 		else if(!rn2(4)) ini_inv(Lamp);
-		else if(!rn2(10)) ini_inv(Magicmarker);
 		knows_object(SACK);
 		knows_object(TOUCHSTONE);
@@ -625,5 +635,5 @@
 		break;
 	case PM_CAVEMAN:
-		Cave_man[C_AMMO].trquan = rn1(11, 10);	/* 10..20 */
+		Cave_man[C_AMMO].trquan = rn1(11, 20);	/* 20..30 */
 		ini_inv(Cave_man);
 		skill_init(Skill_C);
@@ -656,6 +666,5 @@
 		}
 		ini_inv(Monk);
-		if(!rn2(5)) ini_inv(Magicmarker);
-		else if(!rn2(10)) ini_inv(Lamp);
+		if(!rn2(10)) ini_inv(Lamp);
 		knows_class(ARMOR_CLASS);
 		skill_init(Skill_Mon);
@@ -663,6 +672,5 @@
 	case PM_PRIEST:
 		ini_inv(Priest);
-		if(!rn2(10)) ini_inv(Magicmarker);
-		else if(!rn2(10)) ini_inv(Lamp);
+		if(!rn2(10)) ini_inv(Lamp);
 		knows_object(POT_WATER);
 		skill_init(Skill_P);
@@ -713,5 +721,4 @@
 		else if(!rn2(25)) ini_inv(Leash);
 		else if(!rn2(25)) ini_inv(Towel);
-		else if(!rn2(25)) ini_inv(Magicmarker);
 		skill_init(Skill_T);
 		break;
@@ -726,5 +733,4 @@
 	case PM_WIZARD:
 		ini_inv(Wizard);
-		if(!rn2(5)) ini_inv(Magicmarker);
 		if(!rn2(5)) ini_inv(Blindfold);
 		skill_init(Skill_W);
@@ -780,7 +786,17 @@
 	    knows_object(DWARVISH_CLOAK);
 	    knows_object(DWARVISH_ROUNDSHIELD);
+		 if (!rn2(4) && !Role_if(PM_ARCHEOLOGIST))
+		 {
+			 /* Wise dwarves bring their toy to the dungeons. */
+			 ini_inv(Pickaxe);
+		 }
 	    break;
 
 	case PM_GNOME:
+		 /* Gnomes don't see how silly they really look */
+		 knows_object(GNOMISH_HELM);
+		 knows_object(GNOMISH_BOOTS);
+		 knows_object(GNOMISH_SUIT);
+		 knows_object(AKLYS);			  /* they're all carrying one! */
 	    break;
 
@@ -789,4 +805,6 @@
 	    if (!Role_if(PM_WIZARD))
 		ini_inv(Xtra_food);
+		 /* Orcs are naughty and carry poison */
+		 ini_inv(Poison);
 	    /* Orcs can recognize all orcish objects */
 	    knows_object(ORCISH_SHORT_SWORD);
@@ -801,4 +819,5 @@
 	    knows_object(URUK_HAI_SHIELD);
 	    knows_object(ORCISH_CLOAK);
+		 knows_object(POT_SICKNESS);
 	    break;
 
@@ -843,4 +862,79 @@
 	}
 
+	/* what a horrible night to have a curse */
+	shambler->mlevel += rnd(6)-3;				/* shuffle level */
+	shambler->mmove = rn2(10)+9;				/* slow to very fast */
+	shambler->ac = rn2(21)-10;					/* any AC */
+	shambler->mr = rn2(5)*25;					/* varying amounts of MR */
+	shambler->maligntyp = rn2(21)-10;			/* any alignment */
+	/* attacks...?  */
+	for (i = 0; i < rnd(4); i++) {
+		attkptr = &shambler->mattk[i];
+		attkptr->aatyp = rn2(AT_GAZE);		/* limit it to semi-normal attacks for now */
+		/* theoretically rnd(AT_GAZE)-3 should work since these are uchar, but
+		 * let's not totally confuse the poor people browsing... */
+		if (attkptr->aatyp == AT_BOOM) {
+			attkptr->aatyp = AT_MAGC;
+		}
+		if (attkptr->aatyp == AT_EXPL) {
+			attkptr->aatyp = AT_WEAP;
+		}
+		attkptr->adtyp = 0;
+		/* Don't let the special Rider attacks be used here 
+		 * ...everything else is fair game :D */
+		while (attkptr->adtyp == 0 || attkptr->adtyp == AD_DETH ||
+					attkptr->adtyp == AD_PEST || attkptr->adtyp == AD_FAMN ||
+					attkptr->adtyp == AD_SPC1 || attkptr->adtyp == AD_SPC2) {
+			attkptr->adtyp = rnd(AD_CORR);
+		}
+		if (attkptr->aatyp == AT_MAGC) {
+			attkptr->adtyp = AD_CLRC + rn2(2);	 /* AT_MAGC must correspond to a spell type */
+		}
+		if (attkptr->aatyp == AT_BREA) {
+			attkptr->adtyp == AD_RBRE;				 /* Tiamat's breath weapon if you're a breather at all :)  */
+		}
+		attkptr->damn = 2;							 /* we're almost sure to get this wrong first time */
+		attkptr->damd = 10;							 /* either too high or too low */
+	}
+	shambler->msize = rn2(MZ_GIGANTIC+1);	/* any size */
+	shambler->cwt = 20;							/* fortunately moot as it's flagged NOCORPSE */
+	shambler->cnutrit = 20;						/* see above */
+	shambler->msound = rn2(MS_HUMANOID);	/* any but the specials */
+	shambler->mresists = 0;
+	for (i = 0; i < rnd(6); i++) {
+		shambler->mresists |= (1 << rn2(8));		/* physical resistances... */
+	}
+	for (i = 0; i < rnd(5); i++) {
+		shambler->mresists |= (0x100 << rn2(7));	/* 'different' resistances, even clumsy */
+	}
+	shambler->mconveys = 0;						/* flagged NOCORPSE */
+	/*
+	 * now time for the random flags.  this will likely produce
+	 * a number of complete trainwreck monsters at first, but
+	 * every so often something will dial up nasty stuff
+	 */
+	shambler->mflags1 = 0;
+	for (i = 0; i < rnd(17); i++) {
+		shambler->mflags1 |= (1 << rn2(33));		/* trainwreck this way :D */
+	}
+	shambler->mflags1 &= ~M1_UNSOLID;				/* no ghosts */
+	shambler->mflags1 &= ~M1_WALLWALK;				/* no wall-walkers */
+
+	shambler->mflags2 = M2_NOPOLY | M2_HOSTILE;	/* Don't let the player be one of these yet. */
+	for (i = 0; i < rnd(17); i++) {
+		shambler->mflags2 |= (1 << rn2(33));
+	}
+	shambler->mflags2 &= ~M2_MERC;					/* no guards */
+	shambler->mflags2 &= ~M2_PEACEFUL;				/* no peacefuls */
+	shambler->mflags2 &= ~M2_WERE;					/* no lycanthropes */
+	shambler->mflags2 &= ~M2_PNAME;					/* not a proper name */
+
+	for (i = 0; i < rnd(5); i++) {
+		shambler->mflags3 |= (0x100 << rn2(6));	/* no covetous, but any of the middle M3_ flags are OK */
+	}
+	if (rn2(2)) {
+		shambler->mflags4 |= (1 << rn2(4));			/* don't overload it with vulnerabilities */
+	}
+
 	return;
 }
@@ -938,6 +1032,7 @@
 				|| (otyp == SCR_ENCHANT_WEAPON &&
 				    Role_if(PM_MONK))
-				/* wizard patch -- they already have one */
-				|| (otyp == SPE_FORCE_BOLT &&
+				/* wizard patch -- they already have one
+				   and the polymorph wand lets wizards go nuts with spellbooks too easily */
+				|| ((otyp == SPE_FORCE_BOLT || otyp == WAN_POLYMORPH) &&
 				    Role_if(PM_WIZARD))
 				/* powerful spells are either useless to
@@ -971,5 +1066,5 @@
 			    case RIN_POLYMORPH_CONTROL:
 				nocreate = RIN_POLYMORPH;
-				nocreate2 = SPE_POLYMORPH;
+				nocreate2 = SPE_POLYMORPH_CREATURE;
 				nocreate3 = POT_POLYMORPH;
 			}
@@ -988,4 +1083,5 @@
 			obj->dknown = obj->bknown = obj->rknown = 1;
 			if (objects[otyp].oc_uses_known) obj->known = 1;
+			obj->oeroded = 0;
 			obj->cursed = 0;
 			if (obj->opoisoned && u.ualign.type != A_CHAOTIC)
@@ -1038,9 +1134,14 @@
 		if (obj->oclass == WEAPON_CLASS || is_weptool(obj) ||
 			otyp == TIN_OPENER || otyp == FLINT || otyp == ROCK) {
-		    if (is_ammo(obj) || is_missile(obj)) {
-			if (!uquiver) setuqwep(obj);
-		    } else if (!uwep) setuwep(obj);
+			/* In order: fill the quiver first if possible, then launcher;
+			 * then the rest will sort themselves out later. */
+			if (!uquiver && (is_ammo(obj) || is_missile(obj) || (is_thrown(obj) && obj->quan > 1))) setuqwep(obj);
+			else if (!ulauncher && is_launcher(obj)) setulauncher(obj);
+			/* don't put ammo in weapon slots */
+			else if (!is_ammo(obj) && !is_missile(obj)) {
+				if (!uwep) setuwep(obj);
 		    else if (!uswapwep) setuswapwep(obj);
 		}
+		}
 		if (obj->oclass == SPBOOK_CLASS &&
 				obj->otyp != SPE_BLANK_PAPER)
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/src/vault.c nethack/src/vault.c
--- nh_orig/src/vault.c	2003-12-07 18:39:13.000000000 -0500
+++ nethack/src/vault.c	2010-04-23 14:27:35.647715657 -0400
@@ -145,5 +145,5 @@
     guard = findgd();
     if(++u.uinvault % 30 == 0 && !guard) { /* if time ok and no guard now. */
-	char buf[BUFSZ];
+	char buf[BUFSZ] = "";
 	register int x, y, dd, gx, gy;
 	int lx = 0, ly = 0;
@@ -261,5 +261,5 @@
 
 	stop_occupation();		/* if occupied, stop it *now* */
-	if (multi > 0) { nomul(0); unmul((char *)0); }
+	if (multi > 0) { nomul(0, 0); unmul((char *)0); }
 	trycount = 5;
 	do {
@@ -271,5 +271,5 @@
 	    /* ignore trailing text, in case player includes character's rank */
 	    strncmpi(buf, plname, (int) strlen(plname)) != 0) {
-		adjalign(-1);		/* Liar! */
+		venial_sin();		/* Liar! */
 	}
 
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/src/vision.c nethack/src/vision.c
--- nh_orig/src/vision.c	2003-12-07 18:39:13.000000000 -0500
+++ nethack/src/vision.c	2010-04-11 12:36:57.610751317 -0400
@@ -178,7 +178,8 @@
     /* Mimics mimicing a door or boulder block light. */
     if ((mon = m_at(x,y)) && (!mon->minvis || See_invisible) &&
+	((mon->data == &mons[PM_GIANT_TURTLE]) ||
 	  ((mon->m_ap_type == M_AP_FURNITURE &&
 	  (mon->mappearance == S_hcdoor || mon->mappearance == S_vcdoor)) ||
-	  (mon->m_ap_type == M_AP_OBJECT && mon->mappearance == BOULDER)))
+	   (mon->m_ap_type == M_AP_OBJECT && mon->mappearance == BOULDER))))
 	return 1;
 
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/src/weapon.c nethack/src/weapon.c
--- nh_orig/src/weapon.c	2003-12-07 18:39:13.000000000 -0500
+++ nethack/src/weapon.c	2009-08-02 13:49:38.697407902 -0400
@@ -1,2 +1,3 @@
+
 /*	SCCS Id: @(#)weapon.c	3.4	2002/11/07	*/
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
@@ -10,4 +11,8 @@
 #include "hack.h"
 
+#ifdef DUMP_LOG
+STATIC_DCL int FDECL(enhance_skill, (boolean));
+#endif
+
 /* Categories whose names don't come from OBJ_NAME(objects[type])
  */
@@ -129,5 +134,8 @@
 	int	tmp = 0;
 	struct permonst *ptr = mon->data;
-	boolean Is_weapon = (otmp->oclass == WEAPON_CLASS || is_weptool(otmp));
+	boolean Is_weapon = (otmp && (otmp->oclass == WEAPON_CLASS || is_weptool(otmp)));
+
+	/* not using a weapon; no special bonuses */
+	if (!otmp) return 0;
 
 	if (Is_weapon)
@@ -717,15 +725,28 @@
 {
 	int str = ACURR(A_STR);
+	int dbon = 0;
 
 	if (Upolyd) return(0);
 
-	if (str < 6) return(-1);
-	else if (str < 16) return(0);
-	else if (str < 18) return(1);
-	else if (str == 18) return(2);		/* up to 18 */
-	else if (str <= STR18(75)) return(3);		/* up to 18/75 */
-	else if (str <= STR18(90)) return(4);		/* up to 18/90 */
-	else if (str < STR18(100)) return(5);		/* up to 18/99 */
-	else return(6);
+	if (str < 6) dbon = -1;
+	else if (str < 16) dbon = 0;
+	else if (str < 18) dbon = 1;
+	else if (str == 18) dbon = 2;		/* up to 18 */
+	else if (str <= STR18(75)) dbon = 3;		/* up to 18/75 */
+	else if (str <= STR18(90)) dbon = 4;		/* up to 18/90 */
+	else if (str < STR18(100)) dbon = 5;		/* up to 18/99 */
+	else if (str == STR18(100)) dbon = 6;	   /* 18/00 only */
+	else dbon = 7;									   /* gauntlets of power */
+
+	/* HASAAAAAN CHOP!
+	 *
+	 * If you're wielding a two-handed weapon, let's just, hmm,
+	 * double this bonus.  Yes, even when negative; those are HEAVY.
+	 *
+	 * This should sharply increase the appeal of two-handers compared to #twoweapon. */
+
+	if (uwep && bimanual(uwep)) { dbon *= 2; }
+	return dbon;
+
 }
 
@@ -852,4 +873,21 @@
 int
 enhance_weapon_skill()
+#ifdef DUMP_LOG
+{
+	return enhance_skill(FALSE);
+}
+
+void dump_weapon_skill()
+{
+	enhance_skill(TRUE);
+}
+
+int enhance_skill(boolean want_dump)
+/* This is the original enhance_weapon_skill() function slightly modified
+ * to write the skills to the dump file. I added the wrapper functions just
+ * because it looked like the easiest way to add a parameter to the
+ * function call. - Jukka Lahtinen, August 2001
+ */
+#endif
 {
     int pass, i, n, len, longest,
@@ -861,6 +899,13 @@
     winid win;
     boolean speedy = FALSE;
+#ifdef DUMP_LOG
+    char buf2[BUFSZ];
+    boolean logged;
+#endif
 
 #ifdef WIZARD
+#ifdef DUMP_LOG
+	if (!want_dump)
+#endif
 	if (wizard && yn("Advance skills without practice?") == 'y')
 	    speedy = TRUE;
@@ -879,4 +924,9 @@
 	    }
 
+#ifdef DUMP_LOG
+	    if (want_dump)
+		dump("","Your skills at the end");
+	    else {
+#endif
 	    win = create_nhwindow(NHW_MENU);
 	    start_menu(win);
@@ -906,4 +956,7 @@
 			     "", MENU_UNSELECTED);
 	    }
+#ifdef DUMP_LOG
+	    } /* want_dump or not */
+#endif
 
 	    /* List the skills, making ones that could be advanced
@@ -917,6 +970,24 @@
 		any.a_void = 0;
 		if (i == skill_ranges[pass].first)
+#ifdef DUMP_LOG
+		if (want_dump) {
+		    dump("  ",(char *)skill_ranges[pass].name);
+		    logged=FALSE;
+		} else
+#endif
 		    add_menu(win, NO_GLYPH, &any, 0, 0, iflags.menu_headings,
 			     skill_ranges[pass].name, MENU_UNSELECTED);
+#ifdef DUMP_LOG
+		if (want_dump) {
+		    if (P_SKILL(i) > P_UNSKILLED) {
+		 	Sprintf(buf2,"%-*s [%s]",
+			    longest, P_NAME(i),skill_level_name(i, buf));
+			dump("    ",buf2);
+			logged=TRUE;
+		    } else if (i == skill_ranges[pass].last && !logged) {
+			dump("    ","(none)");
+		    }
+               } else {
+#endif
 
 		if (P_RESTRICTED(i)) continue;
@@ -963,4 +1034,7 @@
 		add_menu(win, NO_GLYPH, &any, 0, 0, ATR_NONE,
 			 buf, MENU_UNSELECTED);
+#ifdef DUMP_LOG
+		} /* !want_dump */
+#endif
 	    }
 
@@ -972,4 +1046,10 @@
 			u.weapon_slots, plur(u.weapon_slots));
 #endif
+#ifdef DUMP_LOG
+	    if (want_dump) {
+		dump("","");
+		n=0;
+	    } else {
+#endif
 	    end_menu(win, buf);
 	    n = select_menu(win, to_advance ? PICK_ONE : PICK_NONE, &selected);
@@ -988,4 +1068,7 @@
 		}
 	    }
+#ifdef DUMP_LOG
+	    }
+#endif
 	} while (speedy && n > 0);
 	return 0;
@@ -1000,4 +1083,14 @@
 int skill;
 {
+
+	/* Cavemen are good at what they know how to use, but not much on advanced fencing or combat tactics.
+	 * So never unrestrict an edged weapon for them.
+	 *
+	 * Same for priests and monks, though slightly different: priests shouldn't have edged weapons, and
+	 * monks and wizards really shouldn't be _using_ weapons, so don't give them _any_. */
+
+	if (Role_if(PM_MONK) || Role_if(PM_WIZARD)) { return; }
+	if ((Role_if(PM_CAVEMAN) || Role_if(PM_PRIEST)) && skill >= P_DAGGER && skill <= P_SABER) { return; }
+
     if (skill < P_NUM_SKILLS && P_RESTRICTED(skill)) {
 	P_SKILL(skill) = P_UNSKILLED;
@@ -1099,4 +1192,5 @@
 {
     int type, wep_type, skill, bonus = 0;
+	unsigned int maxweight = 0;
     static const char bad_skill[] = "weapon_hit_bonus: bad skill %d";
 
@@ -1113,6 +1207,6 @@
 	    case P_UNSKILLED:   bonus = -4; break;
 	    case P_BASIC:       bonus =  0; break;
-	    case P_SKILLED:     bonus =  2; break;
-	    case P_EXPERT:      bonus =  3; break;
+		case P_SKILLED:     bonus =  3; break;
+		case P_EXPERT:      bonus =  6; break;
 	}
     } else if (type == P_TWO_WEAPON_COMBAT) {
@@ -1122,9 +1216,28 @@
 	    default: impossible(bad_skill, skill); /* fall through */
 	    case P_ISRESTRICTED:
-	    case P_UNSKILLED:   bonus = -9; break;
+			case P_UNSKILLED:   bonus = -9; break;	  /* tweaked back to support 2-handers */
 	    case P_BASIC:	bonus = -7; break;
 	    case P_SKILLED:	bonus = -5; break;
 	    case P_EXPERT:	bonus = -3; break;
 	}
+		/* Heavy things are hard to use in your offhand unless you're
+		 * very good at what you're doing.
+		 *
+		 * No real need to restrict unskilled here since knives and such
+		 * are very hard to find and people who are restricted can't
+		 * #twoweapon even at unskilled...
+		 */
+		switch (P_SKILL(P_TWO_WEAPON_COMBAT)) {
+			default: impossible(bad_skill, P_SKILL(P_TWO_WEAPON_COMBAT));
+			case P_ISRESTRICTED:
+			case P_UNSKILLED:
+			case P_BASIC:		 maxweight = 20; break;	 /* daggers */
+			case P_SKILLED:	 maxweight = 30; break;	 /* shortswords and spears */
+			case P_EXPERT:		 maxweight = 40; break;	 /* sabers and long swords */
+		}
+		if (uswapwep->owt > maxweight) {
+			pline("Your %s seem%s very unwieldy.",xname(uswapwep),uswapwep->quan == 1 ? "s" : "");
+			bonus = -30;
+		}
     } else if (type == P_BARE_HANDED_COMBAT) {
 	/*
@@ -1134,10 +1247,11 @@
 	 *	skild:	+2    +4
 	 *	exprt:	+2    +5
-	 *	mastr:	+3    +6
-	 *	grand:	+3    +7
+	 *	mastr:	+3    +7
+	 *	grand:	+3    +9
 	 */
 	bonus = P_SKILL(type);
 	bonus = max(bonus,P_UNSKILLED) - 1;	/* unskilled => 0 */
 	bonus = ((bonus + 2) * (martial_bonus() ? 2 : 1)) / 2;
+		if (bonus > 5) { bonus += ((bonus - 5) * 2); }	/* extra boost for master/GM */
     }
 
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/src/wield.c nethack/src/wield.c
--- nh_orig/src/wield.c	2003-12-07 18:39:13.000000000 -0500
+++ nethack/src/wield.c	2009-08-02 13:49:38.684407752 -0400
@@ -220,4 +220,12 @@
 }
 
+void
+setulauncher(obj)
+struct obj* obj;
+{
+	setworn(obj, W_LAUNCHER);
+	update_inventory();
+}
+
 
 /*** Commands to change particular slot(s) ***/
@@ -229,4 +237,6 @@
 static NEARDATA const char bullets[] =	/* (note: different from dothrow.c) */
 	{ ALL_CLASSES, ALLOW_NONE, GEM_CLASS, WEAPON_CLASS, 0 };
+static NEARDATA const char launchers[] =
+	{ ALL_CLASSES, ALLOW_NONE, WEAPON_CLASS, 0 };
 
 int
@@ -341,5 +351,5 @@
 
 	/* Because 'Q' used to be quit... */
-	if (flags.suppress_alert < FEATURE_NOTICE_VER(3,3,0))
+	if (flags.suppress_alert < FEATURE_NOTICE_VER(0,2,0))
 		pline("Note: Please use #quit if you wish to exit the game.");
 
@@ -398,4 +408,49 @@
 }
 
+int
+dowieldlauncher()
+{
+	struct obj *newlauncher;
+
+	/* Since the "spot" isn't in your hands, don't check cantwield(), */
+	/* will_weld(), touch_petrifies(), etc. */
+	multi = 0;
+
+	/* Prompt for a new object */
+	if (!(newlauncher = getobj(launchers, "fire missiles with"))) {
+		return 0;
+	}
+
+	/* did they explicitly pick nothing? */
+	if (newlauncher == &zeroobj) {
+		if (ulauncher) {
+			You("now have no ranged weapon chosen.");
+			setulauncher(newlauncher = (struct obj *) 0);
+		} else {
+			You("didn't have a ranged weapon ready to begin with.");
+			return 0;
+		}
+	/* It's OK for this to also be the primary or secondary weapon. */
+	} else if (newlauncher == ulauncher) {
+		pline("That's already your chosen ranged weapon.");
+		return 0;
+	} else if (!is_launcher(newlauncher)) {
+		pline("That won't fire anything very far.");
+		return 0;
+	} else {
+		long dummy;
+		dummy = newlauncher->owornmask;
+		newlauncher->owornmask |= W_LAUNCHER;
+		prinv((char *)0, newlauncher, 0L);
+		newlauncher->owornmask = dummy;
+	}
+
+	setulauncher(newlauncher);
+
+	/* Never use any time for this */
+	return 0;
+}
+
+
 /* used for #rub and for applying pick-axe, whip, grappling hook, or polearm */
 /* (moved from apply.c) */
@@ -523,4 +578,7 @@
 }
 
+/* This needs to take a turn, really.  You've either _got_ a sharp thing
+ * in each hand and are trying to put it away, or you're trying to get a
+ * sharp thing out and get it operational. */
 int
 dotwoweapon()
@@ -531,5 +589,5 @@
 		u.twoweap = 0;
 		update_inventory();
-		return (0);
+		return 1;
 	}
 
@@ -540,7 +598,7 @@
 		u.twoweap = 1;
 		update_inventory();
-		return (rnd(20) > ACURR(A_DEX));
+		return 1;
 	}
-	return (0);
+	return 0;
 }
 
@@ -584,4 +642,13 @@
 
 void
+ulwepgone()
+{
+	if (ulauncher) {
+		setworn((struct obj*)0, W_LAUNCHER);
+		update_inventory();
+	}
+}
+
+void
 untwoweapon()
 {
@@ -594,10 +661,178 @@
 }
 
+/*
+ * Centralized call for eroding any single object; handles all types of
+ * damage appropriately, including magical (cf. "destroy armor" spell)
+ *
+ * For now, the corresponding AD_* damage types are used:
+ *
+ * AD_MAGM: the "destroy armor" spell
+ * AD_FIRE: fire damage
+ * AD_RUST: water damage
+ * AD_ACID: acid damage (corrosion)
+ * 
+ * If 'target' goes away as a result of this damage, returns TRUE.
+ */
+boolean
+_erode_obj(target, damage_type)
+struct obj* target;
+uchar damage_type;
+{
+	int old_erlevel;
+	struct monst* victim;
+	boolean vismon, visobj;
+	boolean unaffected = FALSE;
+	boolean secondary = FALSE;
+	char verb[20];
+	char past_adj[20];
+	char adjective[20];
+
+	if (!target) return TRUE;	/* we didn't do it, but it's gone */
+
+	victim = carried(target) ? &youmonst : mcarried(target) ? target->ocarry : (struct monst *)0;
+	vismon = victim && (victim != &youmonst) && canseemon(victim);
+	visobj = !victim && cansee(bhitpos.x, bhitpos.y);	/* assume thrown */
+
+	/* grease protects against everything but magic damage */
+	if (target->greased && damage_type != AD_MAGM) {
+		grease_protect(target,(char*)0,victim);
+		return FALSE;
+	} 
+
+	/* scrolls will fade if exposed to water, or dissolve in acid */
+	if (target->oclass == SCROLL_CLASS) {
+#ifdef MAIL
+		if (target->otyp == SCR_MAIL) {
+			unaffected = TRUE;
+		} else
+#endif
+		if (target->otyp != SCR_BLANK_PAPER && damage_type == AD_RUST) {
+			if (!Blind) {
+				if (victim == &youmonst) {
+					Your("%s.", aobjnam(target, "fade"));
+				} else if (vismon) {
+					pline("%s's %s.",Monnam(victim),aobjnam(target,"fade"));
+				} else if (visobj) {
+					pline_The("%s.",aobjnam(target,"fade"));
+				}
+			}
+			target->otyp = SCR_BLANK_PAPER;
+			target->spe = 0;
+			return FALSE;
+		} else if (damage_type == AD_ACID) {
+			if (!Blind) {
+				if (victim == &youmonst) {
+					Your("%s!", aobjnam(target,"dissolve"));
+				} else if (vismon) {
+					pline("%s's %s!",Monnam(victim),aobjnam(target,"dissolve"));
+				} else if (visobj) {
+					pline_The("%s!",aobjnam(target,"dissolve"));
+				}
+			}
+			useupall(target);
+			return TRUE;
+		}
+		unaffected = TRUE;
+	} 
+
+	/* weed out all the fooproof stuff here */
+	if ((damage_type != AD_MAGM && target->oerodeproof) ||
+			(damage_type == AD_ACID && !is_corrodeable(target) && !is_rottable(target)) ||
+			(damage_type == AD_RUST && !is_rustprone(target)) ||
+			(damage_type == AD_FIRE && !is_flammable(target))) {
+		unaffected = TRUE;
+	}
+		
+	if (unaffected) {
+		if (flags.verbose || !(target->oerodeproof && target->rknown)) {
+			if (victim == &youmonst) {
+				Your("%s not affected.",aobjnam(target,"are"));
+			} else if (vismon) {
+				pline("%s's %s not affected.",Monnam(victim),aobjnam(target,"are"));
+			}
+		}
+		if (target->oerodeproof) target->rknown = TRUE;
+		return FALSE;
+	}
+
+	/* Ugly, but cleaner than the old way */
+	switch (damage_type) {
+		case AD_MAGM:
+			if (is_flammable(target)) { 
+				strcpy(verb,"smolder"); strcpy(past_adj,"burnt"); 
+			} else if (is_rottable(target)) { 
+				strcpy(verb,"rot"); strcpy(past_adj,"rotten"); secondary = TRUE; 
+			} else if (is_rustprone(target)) { 
+				strcpy(verb,"rust"); strcpy(past_adj,"rusty");
+			} else if (is_corrodeable(target)) { 
+				strcpy(verb,"corrode"); strcpy(past_adj,"corroded"); secondary = TRUE; 
+			} else { 
+				strcpy(verb,"deteriorate"); strcpy(past_adj,"deteriorated"); 
+				secondary = TRUE;
+			}
+			break;
+		case AD_RUST:
+			if (is_rustprone(target)) { 
+				strcpy(verb,"rust"); strcpy(past_adj,"rusty");
+			} else { 
+				strcpy(verb,"rot"); strcpy(past_adj,"rotten"); secondary = TRUE; 
+			}
+			break;
+		case AD_ACID:
+			if (is_rottable(target)) { 
+				strcpy(verb,"rot"); strcpy(past_adj,"rotten"); 
+			} else {
+				strcpy(verb,"corrode"); strcpy(past_adj,"corroded"); 
+			}
+			secondary = TRUE;
+			break;
+		case AD_FIRE:
+			strcpy(verb,"smolder");
+			strcpy(past_adj,"burnt");
+			break;
+	}
+
+	old_erlevel = secondary ? target->oeroded2 : target->oeroded;
+	if (!old_erlevel) { 
+		strcpy(adjective,""); 
+	} else { 
+		if (old_erlevel+1 < MAX_ERODE) { strcpy(adjective," further"); } 
+		else { strcpy(adjective," completely"); }
+	}
+
+	/* generate obnoxious output */
+	if (old_erlevel < MAX_ERODE) {
+		if (secondary) { target->oeroded2++; } 
+		else { target->oeroded++; }
+		if (victim == &youmonst) {
+			Your("%s%s!",aobjnam(target,verb),adjective);
+		} else if (vismon) {
+			pline("%s's %s%s!",Monnam(victim),aobjnam(target,verb),adjective);
+		} else if (visobj) {
+			pline_The("%s%s!",aobjnam(target,verb),adjective);
+		}
+	} else {
+	/* eventually there will be a possibility of complete destruction here */
+		if (flags.verbose) {
+			if (victim == &youmonst) {
+				Your("%s completely %s.",aobjnam(target,Blind ? "feel" : "look"),past_adj);
+			} else if (vismon) {
+				pline("%s's %s completely %s.",Monnam(victim),aobjnam(target,"look"),past_adj);
+			} else if (visobj) {
+				pline_The("%s completely %s.",aobjnam(target,"look"),past_adj);
+			}
+		}
+	}
+
+	return FALSE;
+}
+
 /* Maybe rust object, or corrode it if acid damage is called for */
 void
-erode_obj(target, acid_dmg, fade_scrolls)
+erode_obj(target, acid_dmg, fade_scrolls, magic_dmg)
 struct obj *target;		/* object (e.g. weapon or armor) to erode */
 boolean acid_dmg;
 boolean fade_scrolls;
+boolean magic_dmg;
 {
 	int erosion;
@@ -605,4 +840,6 @@
 	boolean vismon;
 	boolean visobj;
+	boolean corrosion;
+	boolean rotting;
 
 	if (!target)
@@ -613,7 +850,9 @@
 	visobj = !victim && cansee(bhitpos.x, bhitpos.y); /* assume thrown */
 
-	erosion = acid_dmg ? target->oeroded2 : target->oeroded;
+	erosion = (acid_dmg || magic_dmg) ? target->oeroded2 : target->oeroded;
+	corrosion = (acid_dmg || magic_dmg);
+	rotting = FALSE; /* TODO: temporary */
 
-	if (target->greased) {
+	if (target->greased && !magic_dmg) {
 	    grease_protect(target,(char *)0,victim);
 	} else if (target->oclass == SCROLL_CLASS) {
@@ -636,6 +875,7 @@
 		target->spe = 0;
 	    }
-	} else if (target->oerodeproof ||
-		(acid_dmg ? !is_corrodeable(target) : !is_rustprone(target))) {
+	/* if this is 'destroy armor', non-corrodeable won't affect it */
+	} else if (!magic_dmg && (target->oerodeproof ||
+		(acid_dmg ? !is_corrodeable(target) : !is_rustprone(target)))) {
 	    if (flags.verbose || !(target->oerodeproof && target->rknown)) {
 		if (victim == &youmonst)
@@ -649,18 +889,21 @@
 	} else if (erosion < MAX_ERODE) {
 	    if (victim == &youmonst)
-		Your("%s%s!", aobjnam(target, acid_dmg ? "corrode" : "rust"),
+		Your("%s%s!", aobjnam(target, !is_damageable(target) ? "deteriorate" : 
+			 corrosion ? "corrode" : rotting ? "rot" : "rust"),
 		    erosion+1 == MAX_ERODE ? " completely" :
 		    erosion ? " further" : "");
 	    else if (vismon)
 		pline("%s's %s%s!", Monnam(victim),
-		    aobjnam(target, acid_dmg ? "corrode" : "rust"),
+		    aobjnam(target, !is_damageable(target) ? "deteriorate" : 
+			 corrosion ? "corrode" : rotting ? "rot" : "rust"),
 		    erosion+1 == MAX_ERODE ? " completely" :
 		    erosion ? " further" : "");
 	    else if (visobj)
 		pline_The("%s%s!",
-		    aobjnam(target, acid_dmg ? "corrode" : "rust"),
+		    aobjnam(target, !is_damageable(target) ? "deteriorate" : 
+			 corrosion ? "corrode" : rotting ? "rot" : "rust"),
 		    erosion+1 == MAX_ERODE ? " completely" :
 		    erosion ? " further" : "");
-	    if (acid_dmg)
+	    if (corrosion)
 		target->oeroded2++;
 	    else
@@ -671,13 +914,16 @@
 		    Your("%s completely %s.",
 			aobjnam(target, Blind ? "feel" : "look"),
-			acid_dmg ? "corroded" : "rusty");
+			!is_damageable(target) ? "deteriorated" : corrosion ? "corroded" : 
+			rotting ? "rotten" : "rusty");
 		else if (vismon)
 		    pline("%s's %s completely %s.", Monnam(victim),
 			aobjnam(target, "look"),
-			acid_dmg ? "corroded" : "rusty");
+			!is_damageable(target) ? "deteriorated" : corrosion ? "corroded" : 
+			rotting ? "rotten" : "rusty");
 		else if (visobj)
 		    pline_The("%s completely %s.",
 			aobjnam(target, "look"),
-			acid_dmg ? "corroded" : "rusty");
+			!is_damageable(target) ? "deteriorated" : corrosion ? "corroded" : 
+			rotting ? "rotten" : "rusty");
 	    }
 	}
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/src/wizard.c nethack/src/wizard.c
--- nh_orig/src/wizard.c	2003-12-07 18:39:13.000000000 -0500
+++ nethack/src/wizard.c	2009-10-31 10:50:33.264577598 -0400
@@ -33,5 +33,5 @@
 	PM_FIRE_ELEMENTAL, PM_JABBERWOCK, PM_ARCH_LICH, PM_OGRE_KING,
 	PM_OLOG_HAI, PM_IRON_GOLEM, PM_OCHRE_JELLY, PM_GREEN_SLIME,
-	PM_DISENCHANTER
+	PM_DISENCHANTER, PM_MAGICAL_EYE
 	};
 
@@ -55,5 +55,6 @@
 	struct monst *mtmp;
 	struct trap *ttmp;
-	struct obj *amu;
+	struct obj *amu = 0;
+	struct obj* otmp;
 
 #if 0		/* caller takes care of this check */
@@ -61,7 +62,15 @@
 		return;
 #endif
-	if ((((amu = uamul) != 0 && amu->otyp == AMULET_OF_YENDOR) ||
-	     ((amu = uwep) != 0 && amu->otyp == AMULET_OF_YENDOR))
-	    && !rn2(15)) {
+
+	/* have to do this to pick up the amulet object itself */
+	for (otmp = invent; otmp; otmp = otmp->nobj)
+	{
+		if (otmp->otyp == AMULET_OF_YENDOR)
+		{
+			amu = otmp;
+		}
+	}
+
+	if (amu && !rn2(15)) {
 	    for(ttmp = ftrap; ttmp; ttmp = ttmp->ntrap) {
 		if(ttmp->ttyp == MAGIC_PORTAL) {
@@ -233,5 +242,6 @@
 		return(STRAT(STRAT_GROUND, otmp->ox, otmp->oy, mask));
 	    else if((mtmp2 = other_mon_has_arti(mtmp, otyp)))
-		return(STRAT(STRAT_MONSTR, mtmp2->mx, mtmp2->my, mask));
+		return(STRAT(STRAT_PLAYER, u.ux, u.uy, mask));
+		 /* Don't fight over the Amulet, mostly */
 	}
 	return(STRAT_NONE);
@@ -269,4 +279,11 @@
 	}
 
+	/* do not let multiple Juiblexes fight for the stairs;
+	 * it's not like he needs to heal anyway */
+	if (mtmp->data == &mons[PM_JUIBLEX] && dstrat == STRAT_HEAL)
+	{
+		dstrat = STRAT_NONE;
+	}
+
 	if(flags.made_amulet)
 	    if((strat = target_on(M3_WANTSAMUL, mtmp)) != STRAT_NONE)
@@ -302,7 +319,35 @@
 {
 	long strat = strategy(mtmp);
+	int j;
+	schar nx,ny;
 
 	mtmp->mstrategy = (mtmp->mstrategy & STRAT_WAITMASK) | strat;
 
+	/* this should be in strategy() but the STRAT_ flags are
+	 * overloaded and i'm in no mood to fix them right now;
+	 * if monster is scared, don't 'flee' right next
+	 * to the player */
+	if (mtmp->mflee) {
+		mtmp->mavenge = 1;
+		for (j=0;j<400;j++) {
+			nx = rnd(COLNO-1);
+			ny = rn2(ROWNO);
+			if (rloc_pos_ok(nx,ny,mtmp) && distu(nx,ny) > 64) {
+				rloc_to(mtmp,nx,ny);
+				/* this was the part that was missing before -- faster heals
+				 * this should solve the problem of scared covetous running
+				 * all over the damn place for 2k+ turns */
+				if(mtmp->mhp <= mtmp->mhpmax - 8) {
+					mtmp->mhp += rnd(8);
+				}
+				return 1;
+			}
+		}
+		/* we couldn't find someplace far enough away from the player
+		 * to run to, which should be very rare, but ...
+		 * and in that case, just fall through so we do something */
+		pline("%s looks around nervously.",Monnam(mtmp));
+	}
+
 	switch (strat) {
 	    case STRAT_HEAL:	/* hide and recover */
@@ -318,5 +363,5 @@
 		}
 		/* if you're not around, cast healing spells */
-		if (distu(mtmp->mx,mtmp->my) > (BOLT_LIM * BOLT_LIM))
+			if (distu(mtmp->mx,mtmp->my) > 64)
 		    if(mtmp->mhp <= mtmp->mhpmax - 8) {
 			mtmp->mhp += rnd(8);
@@ -326,6 +371,28 @@
 
 	    case STRAT_NONE:	/* harrass */
-		if (!rn2(!mtmp->mflee ? 5 : 33)) mnexto(mtmp);
+		{
+			xchar tx = STRAT_GOALX(strat),
+					ty = STRAT_GOALY(strat),
+					dx = 0,
+					dy = 0,
+					stx = tx,
+					sty = ty;
+
+			/* If we're close enough, pounce */
+			if (distu(mtmp->mx, mtmp->my) <= 25) {
+				mnexto(mtmp);
+			} else {
+				/* figure out what direction the player's in */
+				dx = sgn(u.ux - mtmp->mx);
+				dy = sgn(u.uy - mtmp->my);
+
+				/* since we're not close enough -- use short jumps to change that */
+				stx = mtmp->mx + ((rn2(3) + 4)*dx);
+				sty = mtmp->my + ((rn2(3) + 3)*dy);
+				mnearto(mtmp,stx,sty,TRUE);
+			}
+
 		return(0);
+		}
 
 	    default:		/* kill, maim, pillage! */
@@ -333,5 +400,9 @@
 		long  where = (strat & STRAT_STRATMASK);
 		xchar tx = STRAT_GOALX(strat),
-		      ty = STRAT_GOALY(strat);
+						ty = STRAT_GOALY(strat),
+						dx = 0,
+						dy = 0,
+						stx = tx,
+						sty = ty;
 		int   targ = strat & STRAT_GOAL;
 		struct obj *otmp;
@@ -340,9 +411,23 @@
 		    return(0);
 		}
-		if((u.ux == tx && u.uy == ty) || where == STRAT_PLAYER) {
+
 		    /* player is standing on it (or has it) */
+				if ((u.ux == tx && u.uy == ty) || where == STRAT_PLAYER) {
+					/* If we're close enough, pounce */
+					if (distu(mtmp->mx, mtmp->my) <= 25) {
 		    mnexto(mtmp);
+					} else {
+						/* figure out what direction the player's in */
+						dx = sgn(u.ux - mtmp->mx);
+						dy = sgn(u.uy - mtmp->my);
+
+						/* since we're not close enough -- use short jumps to change that */
+						stx = mtmp->mx + ((rn2(3) + 4)*dx);
+						sty = mtmp->my + ((rn2(3) + 3)*dy);
+						mnearto(mtmp,stx,sty,TRUE);
+					}
 		    return(0);
 		}
+
 		if(where == STRAT_GROUND) {
 		    if(!MON_AT(tx, ty) || (mtmp->mx == tx && mtmp->my == ty)) {
@@ -420,8 +505,10 @@
 /* a null caster defaults to a chaotic caster (e.g. the wizard) */
 int
-nasty(mcast)
+nasty(mcast,centered_on_stairs)
 	struct monst *mcast;
+BOOLEAN_P centered_on_stairs;
 {
     register struct monst	*mtmp;
+	 struct permonst* mdat;
     register int	i, j, tmp;
     int castalign = (mcast ? mcast->data->maligntyp : -1);
@@ -434,7 +521,14 @@
     } else {
 	tmp = (u.ulevel > 3) ? u.ulevel/3 : 1; /* just in case -- rph */
-	/* if we don't have a casting monster, the nasties appear around you */
+		/* if we don't have a casting monster, the nasties appear around you
+		 * ...unless we're being called with the 'stairs' flag to block the
+		 * adventurer's return with the amulet */
+		if (centered_on_stairs && xupstair) {
+			bypos.x = xupstair;
+			bypos.y = yupstair;
+		} else {
 	bypos.x = u.ux;
 	bypos.y = u.uy;
+		}
 	for(i = rnd(tmp); i > 0; --i)
 	    for(j=0; j<20; j++) {
@@ -452,11 +546,17 @@
 		    !enexto(&bypos, mcast->mux, mcast->muy, &mons[makeindex]))
 		    continue;
-		if ((mtmp = makemon(&mons[makeindex],
-				    bypos.x, bypos.y, NO_MM_FLAGS)) != 0) {
+				/* If this is a demon prince, tend to make more demons */
+				if (mcast && is_dprince(mcast->data) && !rn2(2)) {
+					mdat = mkclass(S_DEMON,0);
+					mtmp = makemon(mdat ? mdat : &mons[makeindex],bypos.x, bypos.y, MM_ADJACENTOK);
+				} else {
+					mtmp = makemon(&mons[makeindex], bypos.x, bypos.y, MM_ADJACENTOK);
+				}
+				if (mtmp != 0) {
 		    mtmp->msleeping = mtmp->mpeaceful = mtmp->mtame = 0;
 		    set_malign(mtmp);
 		} else /* GENOD? */
 		    mtmp = makemon((struct permonst *)0,
-					bypos.x, bypos.y, NO_MM_FLAGS);
+							bypos.x, bypos.y, MM_ADJACENTOK);
 		if(mtmp && (mtmp->data->maligntyp == 0 ||
 		            sgn(mtmp->data->maligntyp) == sgn(castalign)) ) {
@@ -523,6 +623,7 @@
 intervene()
 {
-	int which = Is_astralevel(&u.uz) ? rnd(4) : rn2(6);
-	/* cases 0 and 5 don't apply on the Astral level */
+	/* many cases don't apply on the Astral level or Planes */
+	int which = Is_astralevel(&u.uz) ? rnd(4) : rn2(8);
+
 	switch (which) {
 	    case 0:
@@ -536,7 +637,12 @@
 	    case 3:	aggravate();
 			break;
-	    case 4:	(void)nasty((struct monst *)0);
+	    case 4:	
+			(void)nasty((struct monst *)0,FALSE);
 			break;
-	    case 5:	resurrect();
+	    case 5:	
+			resurrect();
+		 case 6:
+		 case 7:
+			(void)nasty((struct monst*)0,TRUE);
 			break;
 	}
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/src/worm.c nethack/src/worm.c
--- nh_orig/src/worm.c	2003-12-07 18:39:13.000000000 -0500
+++ nethack/src/worm.c	2010-04-11 12:36:57.310626006 -0400
@@ -248,5 +248,5 @@
 
     if (worm->mhp > 3)
-	worm->mhp -= 3;		/* mhpmax not changed ! */
+	worm->mhp -= 3;		/* mhpmax not changed!  no need to call damage_mon() here */
     else
 	worm->mhp = 1;
@@ -304,4 +304,21 @@
 }
 
+/*  cutoff()
+ *
+ *  Remove the tail of a worm and adjust the hp of the worm.
+ */
+void
+cutoff(worm, tail)
+    struct monst *worm;
+    struct wseg *tail;
+{
+	if (flags.mon_moving)
+	    pline("Part of the tail of %s is cut off.", mon_nam(worm));
+	else
+	    You("cut part of the tail off of %s.", mon_nam(worm));
+	toss_wsegs(tail, TRUE);
+	if (worm->mhp > 1) worm->mhp /= 2;
+}
+
 /*  cutworm()
  *
@@ -368,16 +385,15 @@
 
     /* Sometimes the tail end dies. */
-    if (rn2(3) || !(new_wnum = get_wormno())) {
-	if (flags.mon_moving)
-	    pline("Part of the tail of %s is cut off.", mon_nam(worm));
-	else
-	    You("cut part of the tail off of %s.", mon_nam(worm));
-	toss_wsegs(new_tail, TRUE);
-	if (worm->mhp > 1) worm->mhp /= 2;
+    if (!rn2(3) || !(new_wnum = get_wormno())) {
+		cutoff(worm, new_tail);
 	return;
     }
 
     remove_monster(x, y);		/* clone_mon puts new head here */
-    new_worm = clone_mon(worm, x, y);
+    if (!(new_worm = clone_mon(worm, x, y)))
+	 {
+		 cutoff(worm, new_tail);
+		 return;
+	 }
     new_worm->wormno = new_wnum;	/* affix new worm number */
 
@@ -396,4 +412,8 @@
     }
 
+	 /* just in case... */
+	 if (worm->mhp < 1) { worm->mhp = worm->mhpmax = 1; }
+	 if (new_worm->mhp < 1) { new_worm->mhp = new_worm->mhpmax = 1; }
+
     wtails[new_wnum] = new_tail;	/* We've got all the info right now */
     wheads[new_wnum] = curr;		/* so we can do this faster than    */
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/src/worn.c nethack/src/worn.c
--- nh_orig/src/worn.c	2003-12-07 18:39:13.000000000 -0500
+++ nethack/src/worn.c	2010-03-30 14:05:06.618624388 -0400
@@ -8,4 +8,5 @@
 STATIC_DCL void FDECL(m_dowear_type, (struct monst *,long, BOOLEAN_P, BOOLEAN_P));
 STATIC_DCL int FDECL(extra_pref, (struct monst *, struct obj *));
+STATIC_DCL int FDECL(w_blocks, (struct obj *, long));
 
 const struct worn {
@@ -27,4 +28,5 @@
 	{ W_SWAPWEP, &uswapwep },
 	{ W_QUIVER, &uquiver },
+	{ W_LAUNCHER, &ulauncher },
 	{ W_AMUL, &uamul },
 	{ W_TOOL, &ublindf },
@@ -34,12 +36,37 @@
 };
 
-/* This only allows for one blocking item per property */
+/* This only allows for one blocking item per property
 #define w_blocks(o,m) \
 		((o->otyp == MUMMY_WRAPPING && ((m) & W_ARMC)) ? INVIS : \
 		 (o->otyp == CORNUTHAUM && ((m) & W_ARMH) && \
-			!Role_if(PM_WIZARD)) ? CLAIRVOYANT : 0)
-		/* note: monsters don't have clairvoyance, so your role
-		   has no significant effect on their use of w_blocks() */
+			!Role_if(PM_WIZARD)) ? CLAIRVOYANT : \
+		 (strcmpi(OBJ_DESCR(objects[o->otyp]),"tinfoil") == 0 ? TELEPAT : 0)
+
+		 note: monsters don't have clairvoyance, so your role
+		 has no significant effect on their use of w_blocks()
+
+*/
+
+int
+w_blocks(obj, mask) 
+struct obj* obj;
+long mask;
+{
+	const char* desc = 0;
+
+	if (!obj) { return 0; }
+	desc = OBJ_DESCR(objects[obj->otyp]);
+
+	if (obj->otyp == MUMMY_WRAPPING && 
+			(mask & W_ARMC)) { return INVIS; }
+
+	if (obj->otyp == CORNUTHAUM && (mask & W_ARMH) && 
+			!Role_if(PM_WIZARD)) { return CLAIRVOYANT; }
+
+	if (desc && strstri(desc,"tinfoil") && 
+			(mask & W_ARMH)) { return TELEPAT; }
 
+	return 0;
+}
 
 /* Updated to use the extrinsic and blocked fields. */
@@ -66,5 +93,5 @@
 			u.twoweap = 0;
 		    oobj->owornmask &= ~wp->w_mask;
-		    if (wp->w_mask & ~(W_SWAPWEP|W_QUIVER)) {
+		    if (wp->w_mask & ~(W_SWAPWEP|W_QUIVER|W_LAUNCHER)) {
 			/* leave as "x = x <op> y", here and below, for broken
 			 * compilers */
@@ -86,5 +113,5 @@
 		     * wp_mask should be same as mask at this point.
 		     */
-		    if (wp->w_mask & ~(W_SWAPWEP|W_QUIVER)) {
+		    if (wp->w_mask & ~(W_SWAPWEP|W_QUIVER|W_LAUNCHER)) {
 			if (obj->oclass == WEAPON_CLASS || is_weptool(obj) ||
 					    mask != W_WEP) {
@@ -136,4 +163,6 @@
 	if (!mon->invis_blkd) {
 	    mon->minvis = 1;
+	    if (mon->data == &mons[PM_GIANT_TURTLE])
+		unblock_point(mon->mx, mon->my);
 	    newsym(mon->mx, mon->my);		/* make it disappear */
 	    if (mon->wormno) see_wsegs(mon);	/* and any tail too */
@@ -220,4 +249,14 @@
 
     unseen = !canseemon(mon);
+	if(obj->otyp == GOLD_DRAGON_SCALE_MAIL || obj->otyp == GOLD_DRAGON_SCALES ||
+			obj->otyp == SHIELD_OF_LIGHT) {
+		if(on)
+			begin_burn(obj,FALSE);
+		else
+			end_burn(obj,FALSE);
+		if(!unseen && !silently)
+			if(on) pline("%s begins to glow.", The(xname(obj)));
+	}
+		
     if (!which) goto maybe_blocks;
 
@@ -331,4 +370,6 @@
 	register struct obj *obj;
 	int base = mon->data->ac;
+	float bonus;
+	int div;
 	long mwflags = mon->misc_worn_check;
 
@@ -338,4 +379,13 @@
 		/* since ARM_BONUS is positive, subtracting it increases AC */
 	}
+
+	/* Tweak the monster's AC a bit according to its level */
+	div = (mon->m_lev > 20) ? 6 : 5;
+	bonus = (float)(mon->m_lev/2);
+	bonus *= bonus/div;
+	if (bonus > 12) { bonus = 12; }
+	if (bonus < 0) { bonus = 0; }
+	base -= (int)bonus;
+
 	return base;
 }
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/src/write.c nethack/src/write.c
--- nh_orig/src/write.c	2003-12-07 18:39:13.000000000 -0500
+++ nethack/src/write.c	2010-04-23 14:27:35.700715152 -0400
@@ -72,5 +72,5 @@
 {
 	register struct obj *paper;
-	char namebuf[BUFSZ], *nm, *bp;
+	char namebuf[BUFSZ] = "", *nm, *bp;
 	register struct obj *new_obj;
 	int basecost, actualcost;
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/src/zap.c nethack/src/zap.c
--- nh_orig/src/zap.c	2003-12-07 18:39:13.000000000 -0500
+++ nethack/src/zap.c	2010-05-14 11:36:06.424714182 -0400
@@ -29,4 +29,5 @@
 STATIC_DCL void FDECL(zhitu, (int,int,const char *,XCHAR_P,XCHAR_P));
 STATIC_DCL void FDECL(revive_egg, (struct obj *));
+
 #ifdef STEED
 STATIC_DCL boolean FDECL(zap_steed, (struct obj *));
@@ -34,9 +35,9 @@
 
 #ifdef OVLB
-STATIC_DCL int FDECL(zap_hit, (int,int));
+STATIC_DCL int FDECL(zap_hit, (int,int,BOOLEAN_P));
 #endif
 #ifdef OVL0
 STATIC_DCL void FDECL(backfire, (struct obj *));
-STATIC_DCL int FDECL(spell_hit_bonus, (int));
+STATIC_DCL int FDECL(spell_hit_bonus, (int,BOOLEAN_P));
 #endif
 
@@ -107,6 +108,7 @@
 	boolean wake = TRUE;	/* Most 'zaps' should wake monster */
 	boolean reveal_invis = FALSE;
-	boolean dbldam = Role_if(PM_KNIGHT) && u.uhave.questart;
+	boolean dbldam = FALSE;
 	int dmg, otyp = otmp->otyp;
+	int hurtlex,hurtley;
 	const char *zap_type_text = "spell";
 	struct obj *obj;
@@ -173,5 +175,5 @@
 		break;
 	case WAN_POLYMORPH:
-	case SPE_POLYMORPH:
+	case SPE_POLYMORPH_CREATURE:
 	case POT_POLYMORPH:
 		if (resists_magm(mtmp)) {
@@ -326,5 +328,5 @@
 		else if (!resist(mtmp, otmp->oclass, dmg, NOTELL) &&
 				mtmp->mhp > 0) {
-		    mtmp->mhp -= dmg;
+			 damage_mon(mtmp,dmg,AD_DRIN);
 		    mtmp->mhpmax -= dmg;
 		    if (mtmp->mhp <= 0 || mtmp->mhpmax <= 0 || mtmp->m_lev < 1)
@@ -337,4 +339,15 @@
 		}
 		break;
+	case WAN_WIND:
+		/* Actually distance, not damage */
+		dmg = rnd(2) + (bigmonst(mtmp->data) ? 0 : rnd(3));	
+		hurtlex = sgn(mtmp->mx - u.ux);
+		hurtley = sgn(mtmp->my - u.uy);
+		if (hurtlex) { hurtley = rnd(3)-2; }
+		else if (hurtley) { hurtlex = rnd(3)-2; }
+		pline("%s is blown around!",Monnam(mtmp));
+		mhurtle(mtmp,hurtlex,hurtley,dmg);
+		makeknown(otyp);
+		break;
 	default:
 		impossible("What an interesting effect (%d)", otyp);
@@ -772,5 +785,5 @@
 
 #ifdef OVLB
-static const char charged_objs[] = { WAND_CLASS, WEAPON_CLASS, ARMOR_CLASS, 0 };
+static const char charged_objs[] = { WAND_CLASS, 0 };
 
 STATIC_OVL void
@@ -1161,5 +1174,6 @@
 	    /* some may metamorphosize */
 	    for (i = obj->quan; i; i--)
-		if (! rn2(Luck + 45)) {
+			 /* increase chances of Happy Golem Time */
+		if (!rn2(Luck/5 + 2)) {
 		    poly_zapped = objects[obj->otyp].oc_material;
 		    break;
@@ -1238,4 +1252,10 @@
 	if (obj_location == OBJ_INVENT)
 	    otmp->invlet = obj->invlet;
+
+	/* Meddle with obj->spe to reduce utility of polying heavily enchanted stuff */
+	if (obj->spe > 0) {
+		otmp->spe = rn2(obj->spe);
+	}
+
 #ifdef MAIL
 	/* You can't send yourself 100 mail messages and then
@@ -1262,9 +1282,9 @@
 		otmp->spe = 0;
 
-		/* now change it into something layed by the hero */
+		/* now change it into something laid by the hero */
 		while (tryct--) {
 		    mnum = can_be_hatched(random_monster());
 		    if (mnum != NON_PM && !dead_species(mnum, TRUE)) {
-			otmp->spe = 1;	/* layed by hero */
+			otmp->spe = 1;	/* laid by hero */
 			otmp->corpsenm = mnum;
 			attach_egg_hatch_timeout(otmp);
@@ -1274,5 +1294,5 @@
 	}
 
-	/* keep special fields (including charges on wands) */
+	/* keep special fields and charges on wands */
 	if (index(charged_objs, otmp->oclass)) otmp->spe = obj->spe;
 	otmp->recharged = obj->recharged;
@@ -1284,6 +1304,8 @@
 	if (!is_flammable(otmp) && !is_rustprone(otmp)) otmp->oeroded = 0;
 	if (!is_corrodeable(otmp) && !is_rottable(otmp)) otmp->oeroded2 = 0;
-	if (is_damageable(otmp))
-	    otmp->oerodeproof = obj->oerodeproof;
+	if (is_damageable(otmp)) {
+	    if (obj->oerodeproof) { set_erodeproof(otmp); }
+	    else otmp->oerodeproof = FALSE;
+	}
 
 	/* Keep chest/box traps and poisoned ammo if we may */
@@ -1299,6 +1321,5 @@
 		otmp->oclass = ARMOR_CLASS;
 		otmp->spe = 0;
-		otmp->oeroded = 0;
-		otmp->oerodeproof = TRUE;
+		set_erodeproof(otmp);
 		otmp->quan = 1L;
 		otmp->cursed = FALSE;
@@ -1341,6 +1362,4 @@
 
 	case SPBOOK_CLASS:
-	    while (otmp->otyp == SPE_POLYMORPH)
-		otmp->otyp = rnd_class(SPE_DIG, SPE_BLANK_PAPER);
 	    /* reduce spellbook abuse */
 	    otmp->spestudied = obj->spestudied + 1;
@@ -1383,4 +1402,6 @@
 		if (otmp->owornmask & W_QUIVER)
 		    uquiver = otmp;
+		if (otmp->owornmask & W_LAUNCHER)
+		    ulauncher = otmp;
 		goto no_unwear;
 	    }
@@ -1500,7 +1521,5 @@
 	switch(otmp->otyp) {
 	case WAN_POLYMORPH:
-	case SPE_POLYMORPH:
 		if (obj->otyp == WAN_POLYMORPH ||
-			obj->otyp == SPE_POLYMORPH ||
 			obj->otyp == POT_POLYMORPH ||
 			obj_resists(obj, 5, 95)) {
@@ -1527,7 +1546,11 @@
 		obj->dknown = 1;
 		if (Is_container(obj) || obj->otyp == STATUE) {
-		    if (!obj->cobj)
+		    if (!obj->cobj) {
+				 if (obj->otyp == BAG_OF_POO) {
+					 pline("%s rather full of %s poo.",Tobjnam(obj,"are"),rndmonnam());
+				 } else {
 			pline("%s empty.", Tobjnam(obj, "are"));
-		    else {
+				 }
+			 } else {
 			struct obj *o;
 			/* view contents (not recursively) */
@@ -1600,4 +1623,5 @@
 	case SPE_HEALING:
 	case SPE_EXTRA_HEALING:
+	case SPE_POLYMORPH_CREATURE:
 		res = 0;
 		break;
@@ -1700,4 +1724,11 @@
 		newsym(refresh_x, refresh_y);
 		break;
+	case WAN_WIND:
+		refresh_x = obj->ox;
+		refresh_y = obj->oy;
+		scatter(obj->ox,obj->oy,4,VIS_EFFECTS|MAY_HIT|MAY_DESTROY|MAY_FRACTURE,(struct obj*)0);
+		newsym(refresh_x,refresh_y);
+		makeknown(otmp->otyp);
+		break;
 	default:
 		impossible("What an interesting effect (%d)", otmp->otyp);
@@ -1887,4 +1918,5 @@
 			shieldeff(u.ux, u.uy);
 			pline("Boing!");
+			monstseesu(M_SEEN_MAGR);
 		    } else {
 			if (ordinary) {
@@ -1896,14 +1928,21 @@
 		    }
 		    break;
-
+		case WAN_WIND:
+			 /* This is not usually a bright idea. */
+			 You("are caught up in the winds!");
+			 scatter(u.ux,u.uy,4,VIS_EFFECTS|MAY_HIT|MAY_DESTROY|MAY_FRACTURE,(struct obj*)0);
+			 hurtle(rnd(3)-2,rnd(3)-2,rnd(3)+2,FALSE);
+			 exercise(A_WIS,FALSE);
+			 break;
 		case WAN_LIGHTNING:
 		    makeknown(WAN_LIGHTNING);
-		    if (!Shock_resistance) {
+		    if (how_resistant(SHOCK_RES) < 100) {
 			You("shock yourself!");
-			damage = d(12,6);
+				damage = resist_reduce(d(12,6),SHOCK_RES);
 			exercise(A_CON, FALSE);
 		    } else {
 			shieldeff(u.ux, u.uy);
 			You("zap yourself, but seem unharmed.");
+				monstseesu(M_SEEN_ELEC);
 			ugolemeffects(AD_ELEC, d(12,6));
 		    }
@@ -1919,16 +1958,17 @@
 		case SPE_FIREBALL:
 		    You("explode a fireball on top of yourself!");
-		    explode(u.ux, u.uy, 11, d(6,6), WAND_CLASS, EXPL_FIERY);
+		    explode(u.ux, u.uy, AD_FIRE - 1, d(12,6), WAND_CLASS, EXPL_FIERY);
 		    break;
 		case WAN_FIRE:
 		    makeknown(WAN_FIRE);
 		case FIRE_HORN:
-		    if (Fire_resistance) {
+		    if (how_resistant(FIRE_RES) == 100) {
 			shieldeff(u.ux, u.uy);
 			You_feel("rather warm.");
+				monstseesu(M_SEEN_FIRE);
 			ugolemeffects(AD_FIRE, d(12,6));
 		    } else {
 			pline("You've set yourself afire!");
-			damage = d(12,6);
+				damage = resist_reduce(d(12,6),FIRE_RES);
 		    }
 		    burn_away_slime();
@@ -1943,11 +1983,12 @@
 		case SPE_CONE_OF_COLD:
 		case FROST_HORN:
-		    if (Cold_resistance) {
+		    if (how_resistant(COLD_RES) == 100) {
 			shieldeff(u.ux, u.uy);
 			You_feel("a little chill.");
+				monstseesu(M_SEEN_COLD);
 			ugolemeffects(AD_COLD, d(12,6));
 		    } else {
 			You("imitate a popsicle!");
-			damage = d(12,6);
+				damage = resist_reduce(d(12,6),COLD_RES);
 		    }
 		    destroy_item(POTION_CLASS, AD_COLD);
@@ -1960,4 +2001,5 @@
 			shieldeff(u.ux, u.uy);
 			pline_The("missiles bounce!");
+			monstseesu(M_SEEN_MAGR);
 		    } else {
 			damage = d(4,6);
@@ -1969,5 +2011,5 @@
 		    if (!Unchanging)
 		    	makeknown(WAN_POLYMORPH);
-		case SPE_POLYMORPH:
+		case SPE_POLYMORPH_CREATURE:
 		    if (!Unchanging)
 		    	polyself(FALSE);
@@ -1998,9 +2040,7 @@
 		        break;
 		    }
-		    if (ordinary || !rn2(10)) {	/* permanent */
-			HInvis |= FROMOUTSIDE;
-		    } else {			/* temporary */
+			 /* wand and potion now only do temporary invis,
+			  * to make the cloak and ring more useful */ 
 		    	incr_itimeout(&HInvis, d(obj->spe, 250));
-		    }
 		    if (msg) {
 			makeknown(WAN_MAKE_INVISIBLE);
@@ -2013,7 +2053,7 @@
 		case WAN_SPEED_MONSTER:
 		    if (!(HFast & INTRINSIC)) {
-			if (!Fast)
+			if (!Fast && !Slow)
 			    You("speed up.");
-			else
+			else if (!Slow)
 			    Your("quickness feels more natural.");
 			makeknown(WAN_SPEED_MONSTER);
@@ -2026,10 +2066,11 @@
 		    makeknown(WAN_SLEEP);
 		case SPE_SLEEP:
-		    if(Sleep_resistance) {
+		    if (how_resistant(SLEEP_RES) == 100) {
 			shieldeff(u.ux, u.uy);
 			You("don't feel sleepy!");
+				monstseesu(M_SEEN_SLEEP);
 		    } else {
 			pline_The("sleep ray hits you!");
-			fall_asleep(-rnd(50), TRUE);
+				fall_asleep(-resist_reduce(rnd(50),SLEEP_RES), TRUE);
 		    }
 		    break;
@@ -2037,8 +2078,6 @@
 		case WAN_SLOW_MONSTER:
 		case SPE_SLOW_MONSTER:
-		    if(HFast & (TIMEOUT | INTRINSIC)) {
 			u_slow_down();
 			makeknown(obj->otyp);
-		    }
 		    break;
 
@@ -2191,5 +2230,5 @@
 		case SPE_CANCELLATION:
 		case WAN_POLYMORPH:
-		case SPE_POLYMORPH:
+		case SPE_POLYMORPH_CREATURE:
 		case WAN_STRIKING:
 		case SPE_FORCE_BOLT:
@@ -2202,4 +2241,5 @@
 		case WAN_OPENING:
 		case SPE_KNOCK:
+		case WAN_WIND:
 		    (void) bhitm(u.usteed, obj);
 		    steedhit = TRUE;
@@ -2328,4 +2368,5 @@
 	case WAN_STRIKING:
 	case SPE_FORCE_BOLT:
+	case WAN_WIND:
 	    striking = TRUE;
 	    /*FALLTHRU*/
@@ -2406,5 +2447,4 @@
 		switch (obj->otyp) {
 		case WAN_POLYMORPH:
-		case SPE_POLYMORPH:
 		    del_engr(e);
 		    make_engr_at(x, y, random_engraving(buf), moves, (xchar)0);
@@ -2430,4 +2470,5 @@
 		case WAN_STRIKING:
 		case SPE_FORCE_BOLT:
+		case WAN_WIND:
 		    wipe_engr_at(x, y, d(2,4));
 		    break;
@@ -2449,4 +2490,5 @@
 register struct	obj	*obj;
 {
+	int sp_skill;
 	int otyp = obj->otyp;
 	boolean disclose = FALSE, was_unkn = !objects[otyp].oc_name_known;
@@ -2462,4 +2504,8 @@
 	    obj_zapped = FALSE;
 
+		if (obj->otyp == WAN_WIND) {
+			pline("Winds swirl around you!");
+			makeknown(obj->otyp);
+		}
 	    if (u.uswallow) {
 		(void) bhitm(u.ustuck, obj);
@@ -2480,16 +2526,21 @@
 	    /* neither immediate nor directionless */
 
-	    if (otyp == WAN_DIGGING || otyp == SPE_DIG)
+	    if (otyp == WAN_DIGGING || otyp == SPE_DIG) {
 		zap_dig();
-	    else if (otyp >= SPE_MAGIC_MISSILE && otyp <= SPE_FINGER_OF_DEATH)
-		buzz(otyp - SPE_MAGIC_MISSILE + 10,
-		     u.ulevel / 2 + 1,
-		     u.ux, u.uy, u.dx, u.dy);
-	    else if (otyp >= WAN_MAGIC_MISSILE && otyp <= WAN_LIGHTNING)
-		buzz(otyp - WAN_MAGIC_MISSILE,
-		     (otyp == WAN_MAGIC_MISSILE) ? 2 : 6,
+		 } else if (otyp == SPE_MAGIC_MISSILE) {
+			 /* Special case added here; level 2 magic missile shouldn't be doing
+			  * the same damage as level 4 fire blasts/cold rays, especially since
+			  * almost nothing is magic-missile resistant and many things are fire
+			  * and/or cold resistant */
+			 sp_skill = (P_SKILL(spell_skilltype(SPE_MAGIC_MISSILE)) == P_EXPERT) ? 3 : 4;
+			buzz(AD_MAGM + 9, u.ulevel / sp_skill + 1, u.ux, u.uy, u.dx, u.dy);
+		 } else if (otyp >= SPE_FIREBALL && otyp <= SPE_FINGER_OF_DEATH) {
+			buzz(otyp - SPE_MAGIC_MISSILE + 10, u.ulevel / 2 + 1, u.ux, u.uy, u.dx, u.dy);
+		 } else if (otyp >= WAN_MAGIC_MISSILE && otyp <= WAN_LIGHTNING) {
+			buzz(otyp - WAN_MAGIC_MISSILE, (otyp == WAN_MAGIC_MISSILE) ? 2 : 6,
 		     u.ux, u.uy, u.dx, u.dy);
-	    else
+		 } else {
 		impossible("weffects: unexpected spell or wand");
+		 }
 	    disclose = TRUE;
 	}
@@ -2532,16 +2583,21 @@
  */
 STATIC_OVL int
-spell_hit_bonus(skill)
+spell_hit_bonus(skill,is_wand)
 int skill;
+boolean is_wand;
 {
     int hit_bon = 0;
     int dex = ACURR(A_DEX);
 
+	 if (is_wand) {
+		 if (!uwep) { hit_bon = 3; }	/* easier to aim with hands free */
+	 } else {
     switch (P_SKILL(spell_skilltype(skill))) {
 	case P_ISRESTRICTED:
 	case P_UNSKILLED:   hit_bon = -4; break;
 	case P_BASIC:       hit_bon =  0; break;
-	case P_SKILLED:     hit_bon =  2; break;
-	case P_EXPERT:      hit_bon =  3; break;
+			case P_SKILLED:     hit_bon =  4; break;
+			case P_EXPERT:      hit_bon =  8; break;	 /* expert means expert */
+		}
     }
 
@@ -2557,4 +2613,7 @@
 	hit_bon += dex - 14; /* Even increment for dextrous heroes (see weapon.c abon) */
 
+	 /* experience matters... */
+	 hit_bon += (u.ulevel < 15) ? u.ulevel : 15;
+
     return hit_bon;
 }
@@ -2693,4 +2752,5 @@
 		    case WAN_STRIKING:
 		    case SPE_FORCE_BOLT:
+			 case WAN_WIND:
 			if (typ != DRAWBRIDGE_UP)
 			    destroy_drawbridge(x,y);
@@ -2762,4 +2822,5 @@
 		case SPE_WIZARD_LOCK:
 		case SPE_FORCE_BOLT:
+		case WAN_WIND:
 		    if (doorlock(obj, bhitpos.x, bhitpos.y)) {
 			if (cansee(bhitpos.x, bhitpos.y) ||
@@ -2839,6 +2900,6 @@
 
 struct monst *
-boomhit(dx, dy)
-int dx, dy;
+boomhit(dx, dy, type)
+int dx, dy, type;
 {
 	register int i, ct;
@@ -2855,6 +2916,22 @@
 		boom = (boom == S_boomleft) ? S_boomright : S_boomleft;
 		tmp_at(DISP_CHANGE, cmap_to_glyph(boom));/* change glyph */
+		switch (type) {
+		default:
 		dx = xdir[i];
 		dy = ydir[i];
+		    break;
+		case 1:
+		    dx = xdir[(i+4)%8];
+		    dy = ydir[(i+4)%8];
+		    break;
+		case 2:
+		    if (ct && (ct % 5 == 0)) {
+			dx = -dx;
+			dy = -dy;
+		    }
+		    break;
+		case 3:
+		    break;
+		}
 		bhitpos.x += dx;
 		bhitpos.y += dy;
@@ -2974,5 +3051,5 @@
 		    }
 		    if (nonliving(mon->data) || is_demon(mon->data) ||
-			    resists_magm(mon)) {	/* similar to player */
+			    resists_magm(mon) || mon->data->msound == MS_LEADER) {	/* similar to player */
 			sho_shieldeff = TRUE;
 			break;
@@ -3047,11 +3124,9 @@
 		}
 		tmp = d(nd,6);
-		if (!rn2(6)) erode_obj(MON_WEP(mon), TRUE, TRUE);
+		if (!rn2(6)) _erode_obj(MON_WEP(mon),AD_ACID);
 		if (!rn2(6)) erode_armor(mon, TRUE);
 		break;
 	}
 	if (sho_shieldeff) shieldeff(mon->mx, mon->my);
-	if (is_hero_spell(type) && (Role_if(PM_KNIGHT) && u.uhave.questart))
-	    tmp *= 2;
 	if (tmp > 0 && type >= 0 &&
 		resist(mon, type < ZT_SPELL(0) ? WAND_CLASS : '\0', 0, NOTELL))
@@ -3061,5 +3136,5 @@
 	pline("zapped monster hp = %d (= %d - %d)", mon->mhp-tmp,mon->mhp,tmp);
 #endif
-	mon->mhp -= tmp;
+	damage_mon(mon,tmp,abstype);
 	return(tmp);
 }
@@ -3075,21 +3150,27 @@
 	switch (abs(type) % 10) {
 	case ZT_MAGIC_MISSILE:
+		 dam = d(nd,6);
 	    if (Antimagic) {
+			 monstseesu(M_SEEN_MAGR);
 		shieldeff(sx, sy);
-		pline_The("missiles bounce off!");
-	    } else {
-		dam = d(nd,6);
-		exercise(A_STR, FALSE);
+			pline("Some of the missiles bounce off!");
+			dam /= 2;
 	    }
+		 if (Half_spell_damage) {	 /* yes, this stacks */
+			 dam /= 2;
+		 }
+		 exercise(A_STR, FALSE);
 	    break;
 	case ZT_FIRE:
-	    if (Fire_resistance) {
+	    if (how_resistant(FIRE_RES) == 100) {
 		shieldeff(sx, sy);
 		You("don't feel hot!");
+			monstseesu(M_SEEN_FIRE);
 		ugolemeffects(AD_FIRE, d(nd, 6));
 	    } else {
-		dam = d(nd, 6);
+			 dam = resist_reduce(d(nd,6),FIRE_RES);
 	    }
 	    burn_away_slime();
+		 if (!Reflecting) {
 	    if (burnarmor(&youmonst)) {	/* "body hit" */
 		if (!rn2(3)) destroy_item(POTION_CLASS, AD_FIRE);
@@ -3097,27 +3178,39 @@
 		if (!rn2(5)) destroy_item(SPBOOK_CLASS, AD_FIRE);
 	    }
+	    }
 	    break;
 	case ZT_COLD:
-	    if (Cold_resistance) {
+	    if (how_resistant(COLD_RES) == 100) {
 		shieldeff(sx, sy);
 		You("don't feel cold.");
+			monstseesu(M_SEEN_COLD);
 		ugolemeffects(AD_COLD, d(nd, 6));
 	    } else {
-		dam = d(nd, 6);
+			 dam = resist_reduce(d(nd,6),COLD_RES);
 	    }
+		 if (!Reflecting) {
 	    if (!rn2(3)) destroy_item(POTION_CLASS, AD_COLD);
+		 }
 	    break;
 	case ZT_SLEEP:
-	    if (Sleep_resistance) {
+	    if (how_resistant(SLEEP_RES) == 100) {
 		shieldeff(u.ux, u.uy);
 		You("don't feel sleepy.");
+			monstseesu(M_SEEN_SLEEP);
+		 } else if (Reflecting) {
+			fall_asleep(-resist_reduce(d(1,6),SLEEP_RES), TRUE); /* sleep ray */
 	    } else {
-		fall_asleep(-d(nd,25), TRUE); /* sleep ray */
+			fall_asleep(-resist_reduce(d(nd,25),SLEEP_RES), TRUE);
 	    }
 	    break;
 	case ZT_DEATH:
 	    if (abs(type) == ZT_BREATH(ZT_DEATH)) {
-		if (Disint_resistance) {
+			if (how_resistant(DISINT_RES) == 100) {
 		    You("are not disintegrated.");
+				monstseesu(M_SEEN_DISINT);
+				break;
+			} else if (Reflecting) {
+				You("aren't disintegrated, but that hurts!");
+				dam = resist_reduce(d(nd,6),DISINT_RES);			/* partial is worthwhile! */
 		    break;
 		} else if (uarms) {
@@ -3133,15 +3226,23 @@
 		/* no shield or suit, you're dead; wipe out cloak
 		   and/or shirt in case of life-saving or bones */
+			if (!Reflecting) {
 		if (uarmc) (void) destroy_arm(uarmc);
 #ifdef TOURIST
 		if (uarmu) (void) destroy_arm(uarmu);
 #endif
+			}
 	    } else if (nonliving(youmonst.data) || is_demon(youmonst.data)) {
 		shieldeff(sx, sy);
-		You("seem unaffected.");
+			You("shrug it off.");
 		break;
 	    } else if (Antimagic) {
+			 monstseesu(M_SEEN_MAGR);
 		shieldeff(sx, sy);
-		You("aren't affected.");
+			You("remain unhurt.");
+			break;
+	    } else if (Reflecting) {
+			 You("feel a little bit drained!");
+			 dam = d(2,6);
+			 gainmaxhp(-dam);	 /* it'll cost you... */
 		break;
 	    }
@@ -3153,21 +3254,28 @@
 	    return; /* lifesaved */
 	case ZT_LIGHTNING:
-	    if (Shock_resistance) {
+	    if (how_resistant(SHOCK_RES) == 100) {
 		shieldeff(sx, sy);
-		You("aren't affected.");
+			You("aren't shocked.");
+			monstseesu(M_SEEN_ELEC);
 		ugolemeffects(AD_ELEC, d(nd, 6));
 	    } else {
-		dam = d(nd, 6);
+			dam = resist_reduce(d(nd,6),SHOCK_RES);
 		exercise(A_CON, FALSE);
 	    }
+		 if (!Reflecting) {
 	    if (!rn2(3)) destroy_item(WAND_CLASS, AD_ELEC);
 	    if (!rn2(3)) destroy_item(RING_CLASS, AD_ELEC);
+		 }
 	    break;
 	case ZT_POISON_GAS:
+		 if (!Reflecting) {
 	    poisoned("blast", A_DEX, "poisoned blast", 15);
+		 }
 	    break;
 	case ZT_ACID:
 	    if (Acid_resistance) {
 		dam = 0;
+			pline_The("acid doesn't seem to hurt!");
+			monstseesu(M_SEEN_ACID);
 	    } else {
 		pline_The("acid burns!");
@@ -3175,8 +3283,10 @@
 		exercise(A_STR, FALSE);
 	    }
+		 if (!Reflecting) {
 	    /* using two weapons at once makes both of them more vulnerable */
-	    if (!rn2(u.twoweap ? 3 : 6)) erode_obj(uwep, TRUE, TRUE);
-	    if (u.twoweap && !rn2(3)) erode_obj(uswapwep, TRUE, TRUE);
+			if (!rn2(u.twoweap ? 3 : 6)) _erode_obj(uwep,AD_ACID);
+			if (u.twoweap && !rn2(3)) _erode_obj(uswapwep,AD_ACID);
 	    if (!rn2(6)) erode_armor(&youmonst, TRUE);
+		 }
 	    break;
 	}
@@ -3247,10 +3357,11 @@
 /* will zap/spell/breath attack score a hit against armor class `ac'? */
 STATIC_OVL int
-zap_hit(ac, type)
+zap_hit(ac, type, is_wand)
 int ac;
 int type;	/* either hero cast spell type or 0 */
+boolean is_wand;
 {
     int chance = rn2(20);
-    int spell_bonus = type ? spell_hit_bonus(type) : 0;
+    int spell_bonus = type ? spell_hit_bonus(type,is_wand) : 0;
 
     /* small chance for naked target to avoid being hit */
@@ -3260,5 +3371,5 @@
     ac = AC_VALUE(ac);
 
-    return (3 - chance) < ac+spell_bonus;
+	 return -(chance) < ac+spell_bonus;
 }
 
@@ -3285,4 +3396,11 @@
     struct obj *otmp;
     int spell_type;
+	 boolean is_wand = (type >= 0 && type <= 9);
+
+	 if (type < -39 || type > 29)
+	 {
+		 impossible("Bad attack type passed in buzz(): %d",type);
+		 abstype = type = AD_MAGM;    /* just be a magic missile */
+	 }
 
     /* if its a Hero Spell then get its SPE_TYPE */
@@ -3335,5 +3453,5 @@
 	/* Fireballs only damage when they explode */
 	if (type != ZT_SPELL(ZT_FIRE))
-	    range += zap_over_floor(sx, sy, type, &shopdamage);
+	    range += zap_over_floor(sx, sy, type, &shopdamage, FALSE);
 
 	if (mon) {
@@ -3343,5 +3461,5 @@
 	    buzzmonst:
 #endif
-	    if (zap_hit(find_mac(mon), spell_type)) {
+	    if (zap_hit(find_mac(mon), spell_type, is_wand)) {
 		if (mon_reflects(mon, (char *)0)) {
 		    if(cansee(mon->mx,mon->my)) {
@@ -3437,5 +3555,5 @@
 	    }
 	} else if (sx == u.ux && sy == u.uy && range >= 0) {
-	    nomul(0);
+	    nomul(0, 0);
 #ifdef STEED
 	    if (u.usteed && !rn2(3) && !mon_reflects(u.usteed, (char *)0)) {
@@ -3444,18 +3562,19 @@
 	    } else
 #endif
-	    if (zap_hit((int) u.uac, 0)) {
+	    if (zap_hit((int) u.uac, 0, 0)) {
 		range -= 2;
 		pline("%s hits you!", The(fltxt));
 		if (Reflecting) {
 		    if (!Blind) {
-		    	(void) ureflects("But %s reflects from your %s!", "it");
+					(void) ureflects("Some of %s reflects from your %s!", "it");
 		    } else
-			pline("For some reason you are not affected.");
+				pline("You only seem to have been partially affected.");
 		    dx = -dx;
 		    dy = -dy;
 		    shieldeff(sx, sy);
-		} else {
-		    zhitu(type, nd, fltxt, sx, sy);
+				nd /= 2;
+				monstseesu(M_SEEN_REFL);
 		}
+			zhitu(type, nd, fltxt, sx, sy);
 	    } else {
 		pline("%s whizzes by you!", The(fltxt));
@@ -3467,5 +3586,5 @@
 	    }
 	    stop_occupation();
-	    nomul(0);
+	    nomul(0, 0);
 	}
 
@@ -3484,5 +3603,8 @@
 	    if(range && isok(lsx, lsy) && cansee(lsx,lsy))
 		pline("%s bounces!", The(fltxt));
-	    if(!dx || !dy || !rn2(20)) {
+	    if(!dx || !dy ||
+	       ((In_mines(&u.uz) && IS_WALL(levl[sx][sy].typ) && !rn2(20)) ||
+		((levl[sx][sy].typ == STONE) && !rn2(10)) ||
+		!rn2(100) )) {
 		dx = -dx;
 		dy = -dy;
@@ -3562,10 +3684,14 @@
  * Sets shopdamage to TRUE if a shop door is destroyed, and returns the
  * amount by which range is reduced (the latter is just ignored by fireballs)
+ *
+ * If moncast is TRUE, then a monster is causing this damage; do not penalize
+ * the player for any shop damage or miscellaneous item destruction.
  */
 int
-zap_over_floor(x, y, type, shopdamage)
+zap_over_floor(x, y, type, shopdamage, moncast)
 xchar x, y;
 int type;
 boolean *shopdamage;
+boolean moncast;
 {
 	struct monst *mon;
@@ -3671,4 +3797,6 @@
 		}
 		obj_ice_effects(x,y,TRUE);
+	} else if (abstype == ZT_POISON_GAS) {
+	    (void) create_gas_cloud(x,y,1,8);
 	}
 	if(closed_door(x, y)) {
@@ -3713,5 +3841,5 @@
 		if (new_doormask >= 0) {	/* door gets broken */
 		    if (*in_rooms(x, y, SHOPBASE)) {
-			if (type >= 0) {
+			if (type >= 0 && !moncast) {
 			    add_damage(x, y, 400L);
 			    *shopdamage = TRUE;
@@ -3737,5 +3865,5 @@
 
 	if(OBJ_AT(x, y) && abstype == ZT_FIRE)
-		if (burn_floor_paper(x, y, FALSE, type > 0) && couldsee(x, y)) {
+		if (burn_floor_paper(x, y, FALSE, (type > 0 && !moncast)) && couldsee(x, y)) {
 		    newsym(x,y);
 		    You("%s of smoke.",
@@ -3746,5 +3874,6 @@
 		mon->msleeping = 0;
 		if(mon->m_ap_type) seemimic(mon);
-		if(type >= 0) {
+		/* again, don't penalize player for critter fireballs */
+		if(type >= 0 && !moncast) {
 		    setmangry(mon);
 		    if(mon->ispriest && *in_rooms(mon->mx, mon->my, TEMPLE))
@@ -3805,5 +3934,5 @@
 	if (Role_if(PM_ARCHEOLOGIST) && !flags.mon_moving && (obj->spe & STATUE_HISTORIC)) {
 	    You_feel("guilty about damaging such a historic statue.");
-	    adjalign(-1);
+		 minor_sin();
 	}
 	obj->spe = 0;
@@ -3850,5 +3979,5 @@
 		    break;
 		case AD_FIRE:
-		    xresist = (Fire_resistance && obj->oclass != POTION_CLASS);
+		    xresist = (how_resistant(FIRE_RES) == 100 && obj->oclass != POTION_CLASS);
 
 		    if (obj->otyp == SCR_FIRE || obj->otyp == SPE_FIREBALL)
@@ -3880,5 +4009,5 @@
 		    break;
 		case AD_ELEC:
-		    xresist = (Shock_resistance && obj->oclass != RING_CLASS);
+		    xresist = ((how_resistant(SHOCK_RES) > 50) && obj->oclass != RING_CLASS);
 		    quan = obj->quan;
 		    switch(osym) {
@@ -4081,5 +4210,5 @@
 
 	if (damage) {
-	    mtmp->mhp -= damage;
+		 damage_mon(mtmp,damage,AD_RBRE);
 	    if (mtmp->mhp < 1) {
 		if(m_using) monkilled(mtmp, "", AD_RBRE);
@@ -4093,5 +4222,5 @@
 makewish()
 {
-	char buf[BUFSZ];
+	static char buf[BUFSZ] = "";
 	struct obj *otmp, nothing;
 	int tries = 0;
@@ -4102,4 +4231,6 @@
 	getlin("For what do you wish?", buf);
 	if(buf[0] == '\033') buf[0] = 0;
+	stripctrl(buf);
+	trim(buf);
 	/*
 	 *  Note: if they wished for and got a non-object successfully,
@@ -4125,4 +4256,9 @@
 
 	if (otmp != &zeroobj) {
+
+#ifdef WISH_TRACKER
+		/* write it out to our universal wishtracker file */
+		trackwish(buf);
+#endif
 	    /* The(aobjnam()) is safe since otmp is unidentified -dlc */
 	    (void) hold_another_object(otmp, u.uswallow ?
@@ -4142,4 +4278,60 @@
 }
 
+
+/*	these both use the M_SEEN definitions in monst.h */
+void
+monstseesu(mask)
+unsigned long mask;
+{
+	struct monst* mtmp;
+	for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
+		if (!DEADMONSTER(mtmp) && m_canseeu(mtmp)) m_setseen(mtmp,mask);
+	}
+}
+
+void
+monstseesulose(mask)
+unsigned long mask;
+{
+	struct monst* mtmp;
+	for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
+		if (!DEADMONSTER(mtmp) && m_canseeu(mtmp)) m_sawlose(mtmp,mask);
+	}
+
+}
+
+void
+blindingflash()
+{
+	struct monst* mtmp;
+	long blindprop;
+
+	/* Due to some sloppiness by the vision code, we need to
+		* force the player to always be unblind during this part */
+	blindprop = u.uprops[BLIND_RES].extrinsic;
+	u.uprops[BLIND_RES].extrinsic = 0xFFFF;
+	for (mtmp = fmon; mtmp; mtmp = mtmp->nmon)
+	{
+		/* if it can't see the flash, don't bother */
+		if (DEADMONSTER(mtmp) || mtmp->msleeping || mtmp->mflee ||
+				!haseyes(mtmp->data) || !mtmp->mcansee || mtmp->mblinded)
+		{
+			continue;
+		}
+		/* must be able to see our location... */
+		if (m_cansee(mtmp,u.ux,u.uy) && !rn2(4))
+		{
+			if (canseemon(mtmp)) {
+				pline("%s is blinded by the flash!", Monnam(mtmp));
+			}
+			if (mtmp->mtame) { abuse_dog(mtmp); }
+			else if (mtmp->mpeaceful) { setmangry(mtmp); }
+			mtmp->mblinded = rnd(20);
+			mtmp->mcansee = 0;
+		}
+	}
+	u.uprops[BLIND_RES].extrinsic = blindprop;
+}
+
 #endif /*OVL2*/
 
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/svn-commit.tmp nethack/svn-commit.tmp
--- nh_orig/svn-commit.tmp	1969-12-31 19:00:00.000000000 -0500
+++ nethack/svn-commit.tmp	2009-10-23 14:34:19.135272935 -0400
@@ -0,0 +1,5 @@
+Oops.  Overaggressive chop; fix so we don't always come up on the portal stairs.  :D
+
+--This line, and those below, will be ignored--
+
+M    src/do.c
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/sys/amiga/Makefile.agc nethack/sys/amiga/Makefile.agc
--- nh_orig/sys/amiga/Makefile.agc	2003-12-07 18:39:13.000000000 -0500
+++ nethack/sys/amiga/Makefile.agc	2010-04-23 14:27:36.427715812 -0400
@@ -291,4 +291,6 @@
 	$(SLIB)baalz.lev	$(SLIB)bigrm-1.lev	$(SLIB)bigrm-2.lev \
 	$(SLIB)bigrm-3.lev	$(SLIB)bigrm-4.lev	$(SLIB)bigrm-5.lev \
+	$(SLIB)bigrm-6.lev	$(SLIB)bigrm-7.lev	$(SLIB)bigrm-8.lev \
+	$(SLIB)bigrm-9.lev	$(SLIB)bigrm-10.lev	$(SLIB)bigrm-11.lev \
 	$(SLIB)castle.lev	$(SLIB)dungeon		$(SLIB)earth.lev \
 	$(SLIB)fakewiz1.lev	$(SLIB)fakewiz2.lev	$(SLIB)fire.lev \
@@ -302,5 +304,5 @@
 	$(SLIB)tower1.lev	$(SLIB)tower2.lev	$(SLIB)tower3.lev \
 	$(SLIB)valley.lev	$(SLIB)water.lev	$(SLIB)wizard1.lev \
-	$(SLIB)wizard2.lev	$(SLIB)wizard3.lev \
+	$(SLIB)wizard2.lev	$(SLIB)wizard3.lev  $(SLIB)hellfill.lev \
 	$(XDFILES)
 
@@ -779,5 +781,7 @@
 
 # Create compiled dungeon files
-BGM= $(SLIB)bigrm-2.lev $(SLIB)bigrm-3.lev $(SLIB)bigrm-4.lev $(SLIB)bigrm-5.lev
+BGM= $(SLIB)bigrm-2.lev $(SLIB)bigrm-3.lev $(SLIB)bigrm-4.lev $(SLIB)bigrm-5.lev \
+  $(SLIB)bigrm-6.lev $(SLIB)bigrm-7.lev $(SLIB)bigrm-8.lev $(SLIB)bigrm-9.lev \
+  $(SLIB)bigrm-10.lev $(SLIB)bigrm-11.lev
 $(BGM):	$(SLIB)bigrm-1.lev
 
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/sys/amiga/Makefile.ami nethack/sys/amiga/Makefile.ami
--- nh_orig/sys/amiga/Makefile.ami	2003-12-07 18:39:13.000000000 -0500
+++ nethack/sys/amiga/Makefile.ami	2010-04-23 14:27:36.428715621 -0400
@@ -498,4 +498,6 @@
 	$(SLIB)baalz.lev	$(SLIB)bigrm-1.lev	$(SLIB)bigrm-2.lev \
 	$(SLIB)bigrm-3.lev	$(SLIB)bigrm-4.lev	$(SLIB)bigrm-5.lev \
+	$(SLIB)bigrm-6.lev	$(SLIB)bigrm-7.lev	$(SLIB)bigrm-8.lev \
+	$(SLIB)bigrm-9.lev	$(SLIB)bigrm-10.lev	$(SLIB)bigrm-11.lev \
 	$(SLIB)castle.lev	$(SLIB)dungeon		$(SLIB)earth.lev \
 	$(SLIB)fakewiz1.lev	$(SLIB)fakewiz2.lev	$(SLIB)fire.lev \
@@ -509,5 +511,5 @@
 	$(SLIB)tower1.lev	$(SLIB)tower2.lev	$(SLIB)tower3.lev \
 	$(SLIB)valley.lev	$(SLIB)water.lev	$(SLIB)wizard1.lev \
-	$(SLIB)wizard2.lev	$(SLIB)wizard3.lev \
+	$(SLIB)wizard2.lev	$(SLIB)wizard3.lev  $(SLIB)hellfill.lev \
 	$(XDFILES)
 
@@ -1056,5 +1058,7 @@
 
 # Create compiled dungeon files
-BGM= $(SLIB)bigrm-2.lev $(SLIB)bigrm-3.lev $(SLIB)bigrm-4.lev $(SLIB)bigrm-5.lev
+BGM= $(SLIB)bigrm-2.lev $(SLIB)bigrm-3.lev $(SLIB)bigrm-4.lev $(SLIB)bigrm-5.lev \
+  $(SLIB)bigrm-6.lev $(SLIB)bigrm-7.lev $(SLIB)bigrm-8.lev $(SLIB)bigrm-9.lev \
+  $(SLIB)bigrm-10.lev $(SLIB)bigrm-11.lev
 $(BGM):	$(SLIB)bigrm-1.lev
 
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/sys/mac/Files.r nethack/sys/mac/Files.r
--- nh_orig/sys/mac/Files.r	2003-12-07 18:39:13.000000000 -0500
+++ nethack/sys/mac/Files.r	2010-04-23 14:27:36.210714630 -0400
@@ -36,4 +36,10 @@
 read 'File' (1016,"bigrm-4.lev") ":lib:bigrm-4.lev";
 read 'File' (1017,"bigrm-5.lev") ":lib:bigrm-5.lev";
+read 'File' (1017,"bigrm-6.lev") ":lib:bigrm-6.lev";
+read 'File' (1017,"bigrm-7.lev") ":lib:bigrm-7.lev";
+read 'File' (1017,"bigrm-8.lev") ":lib:bigrm-8.lev";
+read 'File' (1017,"bigrm-9.lev") ":lib:bigrm-9.lev";
+read 'File' (1017,"bigrm-10.lev") ":lib:bigrm-10.lev";
+read 'File' (1017,"bigrm-11.lev") ":lib:bigrm-11.lev";
 read 'File' (1018,"castle.lev") ":lib:castle.lev";
 read 'File' (1019,"data") ":lib:data";
@@ -147,2 +153,3 @@
 read 'File' (1163,"Wiz-loca.lev") ":lib:Wiz-loca.lev";
 read 'File' (1164,"Wiz-strt.lev") ":lib:Wiz-strt.lev";
+read 'File' (1165,"hellfill.lev") ":lib:hellfill.lev";
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/sys/os2/Makefile.os2 nethack/sys/os2/Makefile.os2
--- nh_orig/sys/os2/Makefile.os2	2003-12-07 18:39:13.000000000 -0500
+++ nethack/sys/os2/Makefile.os2	2010-04-23 14:27:36.263714927 -0400
@@ -517,6 +517,8 @@
 
 SPEC_LEVS = \
- asmodeus.lev baalz.lev    bigrm-1.lev \
- bigrm-2.lev  bigrm-3.lev  bigrm-4.lev castle.lev   fakewiz1.lev fakewiz2.lev \
+ asmodeus.lev baalz.lev    bigrm-1.lev  hellfill.lev \
+ bigrm-2.lev  bigrm-3.lev  bigrm-4.lev  bigrm-5.lev  bigrm-6.lev  bigrm-7.lev \
+ bigrm-8.lev  bigrm-9.lev  bigrm-10.lev bigrm-11.lev \
+ castle.lev   fakewiz1.lev fakewiz2.lev \
  juiblex.lev  knox.lev     medusa-1.lev medusa-2.lev minend-1.lev minend-2.lev \
  minend-3.lev minefill.lev minetn-1.lev minetn-2.lev minetn-3.lev minetn-4.lev \
@@ -1109,5 +1111,5 @@
 	-$(RM) $(GAMEDIR)\asmodeus.lev
 	-$(RM) $(GAMEDIR)\baalz.lev
-	-$(RM) $(GAMEDIR)\bigrm-?.lev
+	-$(RM) $(GAMEDIR)\bigrm-*.lev
 	-$(RM) $(GAMEDIR)\castle.lev
 	-$(RM) $(GAMEDIR)\fakewiz?.lev
@@ -1328,6 +1330,6 @@
 $(GAMEDIR)\bigrm-1.lev : $(DAT)\bigroom.des $(TEMP)\lev_comp.exe
 	$(TEMP)\lev_comp $(DAT)\bigroom.des
-	$(CP) bigrm-?.lev $(GAMEDIR)
-	$(RM) bigrm-?.lev
+	$(CP) bigrm-*.lev $(GAMEDIR)
+	$(RM) bigrm-*.lev
 
 $(GAMEDIR)\medusa-1.lev : $(DAT)\medusa.des $(TEMP)\lev_comp.exe
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/sys/unix/Makefile.dat nethack/sys/unix/Makefile.dat
--- nh_orig/sys/unix/Makefile.dat	2003-12-07 18:39:13.000000000 -0500
+++ nethack/sys/unix/Makefile.dat	2009-09-11 15:43:19.272293227 -0400
@@ -7,4 +7,5 @@
 
 VARDAT = data rumors quest.dat oracles options
+LEVCOMP_FLAGS=-v
 
 all:	$(VARDAT) spec_levs quest_levs dungeon
@@ -103,15 +104,15 @@
 	bigroom.des castle.des endgame.des gehennom.des knox.des medusa.des \
 	mines.des oracle.des sokoban.des tower.des yendor.des
-	../util/lev_comp bigroom.des
-	../util/lev_comp castle.des
-	../util/lev_comp endgame.des
-	../util/lev_comp gehennom.des
-	../util/lev_comp knox.des
-	../util/lev_comp medusa.des
-	../util/lev_comp mines.des
-	../util/lev_comp oracle.des
-	../util/lev_comp sokoban.des
-	../util/lev_comp tower.des
-	../util/lev_comp yendor.des
+	../util/lev_comp $(LEVCOMP_FLAGS) bigroom.des
+	../util/lev_comp $(LEVCOMP_FLAGS) castle.des
+	../util/lev_comp $(LEVCOMP_FLAGS) endgame.des
+	../util/lev_comp $(LEVCOMP_FLAGS) gehennom.des
+	../util/lev_comp $(LEVCOMP_FLAGS) knox.des
+	../util/lev_comp $(LEVCOMP_FLAGS) medusa.des
+	../util/lev_comp $(LEVCOMP_FLAGS) mines.des
+	../util/lev_comp $(LEVCOMP_FLAGS) oracle.des
+	../util/lev_comp $(LEVCOMP_FLAGS) sokoban.des
+	../util/lev_comp $(LEVCOMP_FLAGS) tower.des
+	../util/lev_comp $(LEVCOMP_FLAGS) yendor.des
 	touch spec_levs
 
@@ -120,17 +121,17 @@
 	Priest.des Ranger.des Rogue.des Samurai.des Tourist.des Valkyrie.des \
 	Wizard.des
-	../util/lev_comp Arch.des
-	../util/lev_comp Barb.des
-	../util/lev_comp Caveman.des
-	../util/lev_comp Healer.des
-	../util/lev_comp Knight.des
-	../util/lev_comp Monk.des
-	../util/lev_comp Priest.des
-	../util/lev_comp Ranger.des
-	../util/lev_comp Rogue.des
-	../util/lev_comp Samurai.des
-	../util/lev_comp Tourist.des
-	../util/lev_comp Valkyrie.des
-	../util/lev_comp Wizard.des
+	../util/lev_comp $(LEVCOMP_FLAGS) Arch.des
+	../util/lev_comp $(LEVCOMP_FLAGS) Barb.des
+	../util/lev_comp $(LEVCOMP_FLAGS) Caveman.des
+	../util/lev_comp $(LEVCOMP_FLAGS) Healer.des
+	../util/lev_comp $(LEVCOMP_FLAGS) Knight.des
+	../util/lev_comp $(LEVCOMP_FLAGS) Monk.des
+	../util/lev_comp $(LEVCOMP_FLAGS) Priest.des
+	../util/lev_comp $(LEVCOMP_FLAGS) Ranger.des
+	../util/lev_comp $(LEVCOMP_FLAGS) Rogue.des
+	../util/lev_comp $(LEVCOMP_FLAGS) Samurai.des
+	../util/lev_comp $(LEVCOMP_FLAGS) Tourist.des
+	../util/lev_comp $(LEVCOMP_FLAGS) Valkyrie.des
+	../util/lev_comp $(LEVCOMP_FLAGS) Wizard.des
 	touch quest_levs
 
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/sys/unix/Makefile.src nethack/sys/unix/Makefile.src
--- nh_orig/sys/unix/Makefile.src	2003-12-07 18:39:13.000000000 -0500
+++ nethack/sys/unix/Makefile.src	2009-09-07 09:52:38.845417245 -0400
@@ -225,4 +225,5 @@
 # and -ltermcap otherwise
 # Linux uses -lncurses (newer) or -ltermcap (older)
+# OSX uses -lncurses
 # Be uses -ltermcap
 #
@@ -231,6 +232,6 @@
 # WINTTYLIB = -lcurses
 # WINTTYLIB = -lcurses16
-# WINTTYLIB = -lncurses
-WINTTYLIB = -ltermlib
+WINTTYLIB = -lncurses
+# WINTTYLIB = -ltermlib
 #
 # libraries for X11
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/sys/unix/Makefile.top nethack/sys/unix/Makefile.top
--- nh_orig/sys/unix/Makefile.top	2003-12-07 18:39:13.000000000 -0500
+++ nethack/sys/unix/Makefile.top	2010-04-23 14:27:36.305714143 -0400
@@ -74,5 +74,5 @@
 DATHELP = help hh cmdhelp history opthelp wizhelp
 
-SPEC_LEVS = asmodeus.lev baalz.lev bigrm-?.lev castle.lev fakewiz?.lev \
+SPEC_LEVS = asmodeus.lev baalz.lev bigrm-*.lev castle.lev fakewiz?.lev hellfill.lev \
 	juiblex.lev knox.lev medusa-?.lev minend-?.lev minefill.lev \
 	minetn-?.lev oracle.lev orcus.lev sanctum.lev soko?-?.lev \
@@ -167,5 +167,5 @@
 	@if egrep -s librarian dat/options ; then $(MAKE) dlb ; else true ; fi
 
-dlb:
+dlb: spec_levs
 	( cd util ; $(MAKE) dlb )
 	( cd dat ; ../util/dlb cf nhdat $(DATDLB) )
@@ -244,8 +244,8 @@
 	( $(MAKE) dofiles )
 # set up some additional files
-	touch $(VARDIR)/perm $(VARDIR)/record $(VARDIR)/logfile
-	-( cd $(VARDIR) ; $(CHOWN) $(GAMEUID) perm record logfile ; \
-			$(CHGRP) $(GAMEGRP) perm record logfile ; \
-			chmod $(FILEPERM) perm record logfile )
+	touch $(VARDIR)/perm $(VARDIR)/record $(VARDIR)/logfile $(VARDIR)/xlogfile
+	-( cd $(VARDIR) ; $(CHOWN) $(GAMEUID) perm record logfile xlogfile ; \
+			$(CHGRP) $(GAMEGRP) perm record logfile xlogfile ; \
+			chmod $(FILEPERM) perm record logfile xlogfile )
 # and a reminder
 	@echo You may also want to reinstall the man pages via the doc Makefile.
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/sys/unix/unixmain.c nethack/sys/unix/unixmain.c
--- nh_orig/sys/unix/unixmain.c	2003-12-07 18:39:13.000000000 -0500
+++ nethack/sys/unix/unixmain.c	2010-04-26 14:17:07.007714415 -0400
@@ -183,6 +183,5 @@
 	else
 #endif
-	if(!*plname || !strncmp(plname, "player", 4)
-		    || !strncmp(plname, "games", 4)) {
+	if(!*plname) {
 		askname();
 	} else if (exact_username) {
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/sys/winnt/cursmake.gcc nethack/sys/winnt/cursmake.gcc
--- nh_orig/sys/winnt/cursmake.gcc	1969-12-31 19:00:00.000000000 -0500
+++ nethack/sys/winnt/cursmake.gcc	2009-09-05 11:12:29.831292485 -0400
@@ -0,0 +1,1357 @@
+#   SCCS Id: @(#)Makefile.gcc       3.4     $Date: 2003/11/16 04:50:57 $
+#   Copyright (c) NetHack PC Development Team 1993-2003
+#
+#   NetHack 3.4.x Makefile for MinGW
+#
+#   Win32 Compilers Tested:
+#                  - MinGW 1.0 (gcc version 2.95.3-6) (Console NetHack only)
+#                  - MinGW 2.0 (gcc version 3.2)
+#
+#   If you don't have this compiler, you can get it at:
+#       http://www.mingw.org/
+#
+#   This is used for building two versions of NetHack:
+#   A tty port utilizing the Win32 Console I/O subsystem, Console
+#       NetHack;
+#   A Win32 native port built on the Windows API, Graphical NetHack or
+#       NetHackW.
+#
+#   In addition to your C compiler,
+#
+#     if you want to change     you will need a
+#     files with suffix         workalike for
+#         .y                     yacc   (such as bison)
+#         .l                     lex    (such as flex)
+#
+#
+#   If you have any questions read the sys/winnt/Install.nt file included
+#   with the distribution.
+#
+#   --
+#   Dion Nicolaas
+#==============================================================================
+# Graphical interface
+# Set to Y for a graphical version
+# Set to anything else (or undefine) for a tty version
+
+GRAPHICAL = N
+
+# Debug
+# Set to Y for Debug support (to produce debug information)
+# Set to anything else (or undefine) for a "release" version
+# You can set your debug options below.
+
+DEBUG = Y
+
+cc     = gcc
+rc     = windres
+link   = gcc
+
+cflags = -mms-bitfields
+lflags  = 
+ifeq  "$(DEBUG)" "Y"
+cdebug = -g
+linkdebug = -g
+else
+cdebug =
+linkdebug =
+endif
+
+#
+#  Set the gamedir according to your preference.
+#  If not present prior to compilation it gets created.
+
+ifeq  "$(GRAPHICAL)" "Y"
+# Game Name
+GAME    = NetHackW
+else
+# Game Name
+GAME    = NetHackC
+endif
+# Game directory
+GAMEDIR = ../binary
+
+#
+#  Source directories.    Makedefs hardcodes these, don't change them.
+#
+
+# NetHack include files
+INCL  = ../include
+# NetHack data files
+DAT   = ../dat
+# NetHack documentation files
+DOC   = ../doc
+# Utility source
+UTIL  = ../util
+# Main source
+SRC   = ../src
+# Shared system files
+SSYS  = ../sys/share
+# NT Win32 specific files
+NTSYS = ../sys/winnt
+# window port files (tty)
+#TTY   = ../win/tty
+TTY   = ../win/curses
+# window port files (Win32)
+WIN32 = ../win/win32
+# Tile support files
+WSHR  = ../win/share
+
+#
+#  Object directory.
+#
+
+OBJ = o
+
+
+#
+#==========================================
+# Exe File Info.
+#==========================================
+
+# Yacc/Lex ... if you got 'em.
+#
+# If you have yacc and lex programs (or work-alike such as bison
+# and flex), comment out the upper two macros and uncomment
+# the lower two.
+#
+
+DO_YACC = YACC_MSG
+DO_LEX  = LEX_MSG
+#DO_YACC  = YACC_ACT
+#DO_LEX   = LEX_ACT
+
+# - Specify your yacc and lex programs (or work-alikes) here.
+
+#YACC   = bison -y
+YACC   = byacc
+#YACC   = yacc
+
+#LEX    = lex
+LEX     = flex
+
+#
+# - Specify your flex skeleton file (if needed).
+#
+
+FLEXSKEL =
+#FLEXSKEL = -S../tools/flex.ske
+
+YTABC   = y_tab.c
+YTABH   = y_tab.h
+LEXYYC  = lexyy.c
+
+#
+# Optional high-quality BSD random number generation routines
+# (see pcconf.h). Set to nothing if not used.
+#
+
+RANDOM  = $(OBJ)/random.o
+#RANDOM =
+
+#===============================================
+#======= End of Modification Section ===========
+#===============================================
+################################################
+#                                              #
+# Nothing below here should have to be changed.#
+#                                              #
+################################################
+
+ifeq  "$(GRAPHICAL)" "Y"
+WINPORT  = $(O)tile.o $(O)mhaskyn.o $(O)mhdlg.o \
+	$(O)mhfont.o $(O)mhinput.o $(O)mhmain.o $(O)mhmap.o \
+	$(O)mhmenu.o $(O)mhmsgwnd.o $(O)mhrip.o $(O)mhsplash.o \
+	$(O)mhstatus.o $(O)mhtext.o $(O)mswproc.o $(O)winhack.o
+WINPFLAG   = -DTILES -DMSWIN_GRAPHICS -D_WIN32_IE=0x0400
+NHRES   = $(O)winres.o
+WINPINC = -I$(WIN32)
+WINPHDR = $(WIN32)/mhaskyn.h $(WIN32)/mhdlg.h $(WIN32)/mhfont.h \
+	$(WIN32)/mhinput.h $(WIN32)/mhmain.h $(WIN32)/mhmap.h \
+	$(WIN32)/mhmenu.h $(WIN32)/mhmsg.h $(WIN32)/mhmsgwnd.h \
+	$(WIN32)/mhrip.h $(WIN32)/mhstatus.h \
+	$(WIN32)/mhtext.h $(WIN32)/resource.h $(WIN32)/winMS.h
+WINPLIBS =  -lcomctl32 -lwinmm
+else
+WINPORT = $(O)nttty.o
+#WINPFLAG= -DWIN32CON
+WINPHDR =
+NHRES   = $(O)console.o
+WINPINC =
+#WINPLIBS = ../lib/pdcurses.a -lwinmm
+WINPLIBS = ../lib/libpdcurses.a ../lib/libSDL.a -lwinmm
+endif
+
+TILEUTIL16  = $(UTIL)/tile2bmp.exe
+TILEBMP16   = $(SRC)/tiles.bmp
+
+TILEUTIL32  = $(UTIL)/til2bm32.exe
+TILEBMP32   = $(SRC)/tiles32.bmp
+
+SOUND = $(OBJ)/ntsound.o
+
+#SOUND =
+
+# To store all the level files,
+# help files, etc. in a single library file.
+# USE_DLB = Y is left uncommented
+
+USE_DLB = Y
+
+ifeq  "$(USE_DLB)" "Y"
+DLBFLG = -DDLB
+else
+DLBFLG =
+endif
+
+#==========================================
+# Setting up the compiler and linker
+# macros. All builds include the base ones.
+#==========================================
+
+CFLAGSBASE  = -c $(cflags) -I$(INCL) $(WINPINC) $(cdebug)
+LFLAGSBASEC = $(linkdebug) -mwindows
+LFLAGSBASEG = $(linkdebug) -mwindows
+
+#==========================================
+# Util builds
+#==========================================
+
+CFLAGSU = $(CFLAGSBASE) $(WINPFLAG)
+LFLAGSU = $(LFLAGSBASEC)
+
+#==========================================
+# - Game build
+#==========================================
+
+CFLAGS   = $(CFLAGSBASE) $(WINPFLAG) $(DLBFLG)
+lflags  = $(LFLAGSBASE)
+ifeq "$(GRAPHICAL)" "Y"
+lflags  = $(LFLAGSBASEG)
+else
+lflags  = $(LFLAGSBASEC)
+endif
+
+GAMEFILE = $(GAMEDIR)/$(GAME).exe # whole thing
+
+ifeq  "$(USE_DLB)" "Y"
+DLB = nhdat
+else
+DLB =
+endif
+
+#==========================================
+#================ RULES ==================
+#==========================================
+
+.SUFFIXES: .exe .o .til .uu .c .y .l
+
+#==========================================
+# Rules for files in src
+#==========================================
+
+$(OBJ)/%.o : /%.c
+	$(cc) $(CFLAGS)  -o$@ $<
+
+$(OBJ)/%.o : $(SRC)/%.c
+	$(cc) $(CFLAGS)   -o$@  $<
+
+#==========================================
+# Rules for files in sys/share
+#==========================================
+
+$(OBJ)/%.o : $(SSYS)/%.c
+	$(cc) $(CFLAGS)  -o$@  $<
+
+#==========================================
+# Rules for files in sys/winnt
+#==========================================
+
+$(OBJ)/%.o : $(NTSYS)/%.c
+	$(cc) $(CFLAGS)  -o$@  $<
+
+$(INCL)/%.h : $(NTSYS)/%.h
+	@copy $< $@
+
+#==========================================
+# Rules for files in util
+#==========================================
+
+$(OBJ)/%.o : $(UTIL)/%.c
+	$(cc) $(CFLAGSU) -o$@ $<
+
+#==========================================
+# Rules for files in win/share
+#==========================================
+
+$(OBJ)/%.o : $(WSHR)/%.c
+	$(cc) $(CFLAGS)  -o$@ $<
+
+$(INCL)/%.h : $(WSHR)/%.h
+	@copy $< $@
+
+#{$(WSHR)}.txt{$(DAT)}.txt:
+#	@copy $< $@
+
+#==========================================
+# Rules for files in win/tty
+#==========================================
+
+$(OBJ)/%.o : $(TTY)/%.c
+	$(cc) $(CFLAGS)  -o$@  $<
+
+#==========================================
+# Rules for files in win/win32
+#==========================================
+
+$(OBJ)/%.o : $(WIN32)/%.c
+	$(cc) $(CFLAGS)  -o$@  $<
+
+#==========================================
+#================ MACROS ==================
+#==========================================
+# This section creates shorthand macros for many objects
+# referenced later on in the Makefile.
+#
+
+DEFFILE = $(NTSYS)/$(GAME).def
+
+#
+# Shorten up the location for some files
+#
+
+O  = $(OBJ)/
+
+U  = $(UTIL)/
+
+#
+# Utility Objects.
+#
+
+MAKESRC        = $(U)makedefs.c
+
+SPLEVSRC       = $(U)lev_yacc.c  $(U)lev_$(LEX).c $(U)lev_main.c  $(U)panic.c
+
+DGNCOMPSRC     = $(U)dgn_yacc.c  $(U)dgn_$(LEX).c $(U)dgn_main.c
+
+MAKEOBJS       = $(O)makedefs.o $(O)monst.o $(O)objects.o
+
+SPLEVOBJS      = $(O)lev_yacc.o  $(O)lev_$(LEX).o $(O)lev_main.o \
+	$(O)alloc.o   $(O)decl.o      $(O)drawing.o \
+	$(O)monst.o   $(O)objects.o   $(O)panic.o
+
+DGNCOMPOBJS    = $(O)dgn_yacc.o  $(O)dgn_$(LEX).o $(O)dgn_main.o \
+	$(O)alloc.o   $(O)panic.o
+
+RECOVOBJS      = $(O)recover.o
+
+TILEFILES      = $(WSHR)/monsters.txt $(WSHR)/objects.txt $(WSHR)/other.txt
+
+#
+# These are not invoked during a normal game build in 3.4
+#
+TEXT_IO        = $(O)tiletext.o  $(O)tiletxt.o   $(O)drawing.o \
+	$(O)decl.o    $(O)monst.o     $(O)objects.o
+
+TEXT_IO32      = $(O)tilete32.o $(O)tiletx32.o $(O)drawing.o \
+	$(O)decl.o    $(O)monst.o     $(O)objects.o
+
+GIFREADERS     = $(O)gifread.o   $(O)alloc.o $(O)panic.o
+GIFREADERS32   = $(O)gifrd32.o $(O)alloc.o $(O)panic.o
+
+PPMWRITERS     = $(O)ppmwrite.o $(O)alloc.o $(O)panic.o
+
+#
+#  Object files for the game itself.
+#
+
+VOBJ01 = $(O)allmain.o  $(O)alloc.o    $(O)apply.o    $(O)artifact.o
+VOBJ02 = $(O)attrib.o   $(O)ball.o     $(O)bones.o    $(O)botl.o
+VOBJ03 = $(O)cmd.o      $(O)dbridge.o  $(O)decl.o     $(O)detect.o
+VOBJ04 = $(O)dig.o      $(O)display.o  $(O)do.o       $(O)do_name.o
+VOBJ05 = $(O)do_wear.o  $(O)dog.o      $(O)dogmove.o  $(O)dokick.o
+VOBJ06 = $(O)dothrow.o  $(O)drawing.o  $(O)dungeon.o  $(O)eat.o
+VOBJ07 = $(O)end.o      $(O)engrave.o  $(O)exper.o    $(O)explode.o
+VOBJ08 = $(O)extralev.o $(O)files.o    $(O)fountain.o $(O)hack.o
+VOBJ09 = $(O)hacklib.o  $(O)invent.o   $(O)light.o    $(O)lock.o
+VOBJ10 = $(O)mail.o     $(O)makemon.o  $(O)mapglyph.o $(O)mcastu.o
+VOBJ11 = $(O)mhitm.o    $(O)mhitu.o    $(O)minion.o   $(O)mklev.o
+VOBJ12 = $(O)mkmap.o    $(O)mkmaze.o   $(O)mkobj.o    $(O)mkroom.o
+VOBJ13 = $(O)mon.o      $(O)mondata.o  $(O)monmove.o  $(O)monst.o
+VOBJ14 = $(O)monstr.o   $(O)mplayer.o  $(O)mthrowu.o  $(O)muse.o
+VOBJ15 = $(O)music.o    $(O)o_init.o   $(O)objects.o  $(O)objnam.o
+VOBJ16 = $(O)options.o  $(O)pager.o    $(O)pickup.o   $(O)pline.o
+VOBJ17 = $(O)polyself.o $(O)potion.o   $(O)pray.o     $(O)priest.o
+VOBJ18 = $(O)quest.o    $(O)questpgr.o $(RANDOM)      $(O)read.o
+VOBJ19 = $(O)rect.o     $(O)region.o   $(O)restore.o  $(O)rip.o
+VOBJ20 = $(O)rnd.o      $(O)role.o     $(O)rumors.o   $(O)save.o
+VOBJ21 = $(O)shk.o      $(O)shknam.o   $(O)sit.o      $(O)sounds.o
+VOBJ22 = $(O)sp_lev.o   $(O)spell.o    $(O)steal.o    $(O)steed.o
+VOBJ23 = $(O)teleport.o $(O)timeout.o  $(O)topten.o   $(O)track.o
+VOBJ24 = $(O)trap.o     $(O)u_init.o   $(O)uhitm.o    $(O)vault.o
+VOBJ25 = $(O)vis_tab.o  $(O)vision.o   $(O)weapon.o   $(O)were.o
+VOBJ26 = $(O)wield.o    $(O)windows.o  $(O)wizard.o   $(O)worm.o
+VOBJ27 = $(O)worn.o     $(O)write.o    $(O)zap.o
+
+DLBOBJ = $(O)dlb.o
+
+#TTYOBJ = $(O)topl.o     $(O)getline.o  $(O)wintty.o
+TTYOBJ = $(O)cursmain.o $(O)curswins.o  $(O)cursmisc.o $(O)cursdial.o \
+	$(O)cursstat.o $(O)cursinit.o $(O)cursmesg.o 
+
+SOBJ   = $(O)winnt.o    $(O)pcsys.o      $(O)pcunix.o  \
+	$(SOUND) $(O)pcmain.o $(O)mapimail.o $(O)nhlan.o
+
+OBJS   = $(VOBJ01) $(VOBJ02) $(VOBJ03) $(VOBJ04) $(VOBJ05) \
+	$(VOBJ06) $(VOBJ07) $(VOBJ08) $(VOBJ09) $(VOBJ10) \
+	$(VOBJ11) $(VOBJ12) $(VOBJ13) $(VOBJ14) $(VOBJ15) \
+	$(VOBJ16) $(VOBJ17) $(VOBJ18) $(VOBJ19) $(VOBJ20) \
+	$(VOBJ21) $(VOBJ22) $(VOBJ23) $(VOBJ24) $(VOBJ25) \
+	$(VOBJ26) $(VOBJ27)
+
+WINPOBJ = $(WINPORT)
+
+VVOBJ  = $(O)version.o
+
+ALLOBJ  = $(WINPOBJ) $(SOBJ) $(DLBOBJ)  $(TTYOBJ) $(WOBJ) $(OBJS) $(VVOBJ)
+
+ifeq "$(GRAPHICAL)" "Y"
+OPTIONS_FILE = $(DAT)/guioptions
+else
+OPTIONS_FILE = $(DAT)/ttyoptions
+endif
+
+#==========================================
+# Header file macros
+#==========================================
+
+CONFIG_H = $(INCL)/config.h $(INCL)/config1.h $(INCL)/tradstdc.h \
+	       $(INCL)/global.h $(INCL)/coord.h $(INCL)/vmsconf.h \
+	       $(INCL)/system.h $(INCL)/unixconf.h $(INCL)/os2conf.h \
+	       $(INCL)/micro.h $(INCL)/pcconf.h $(INCL)/tosconf.h \
+	       $(INCL)/amiconf.h $(INCL)/macconf.h $(INCL)/beconf.h \
+	       $(INCL)/ntconf.h $(INCL)/nhlan.h
+
+HACK_H = $(INCL)/hack.h $(CONFIG_H) $(INCL)/align.h \
+	       $(INCL)/dungeon.h $(INCL)/monsym.h $(INCL)/mkroom.h \
+	       $(INCL)/objclass.h $(INCL)/youprop.h $(INCL)/prop.h \
+	       $(INCL)/permonst.h $(INCL)/monattk.h \
+	       $(INCL)/monflag.h $(INCL)/mondata.h $(INCL)/pm.h \
+	       $(INCL)/wintype.h $(INCL)/decl.h $(INCL)/quest.h \
+	       $(INCL)/spell.h $(INCL)/color.h $(INCL)/obj.h \
+	       $(INCL)/you.h $(INCL)/attrib.h $(INCL)/monst.h \
+	       $(INCL)/skills.h $(INCL)/onames.h $(INCL)/timeout.h \
+	       $(INCL)/trap.h $(INCL)/flag.h $(INCL)/rm.h \
+	       $(INCL)/vision.h $(INCL)/display.h $(INCL)/engrave.h \
+	       $(INCL)/rect.h $(INCL)/region.h $(INCL)/winprocs.h \
+	       $(INCL)/wintty.h $(INCL)/trampoli.h
+
+LEV_H       = $(INCL)/lev.h
+DGN_FILE_H  = $(INCL)/dgn_file.h
+LEV_COMP_H  = $(INCL)/lev_comp.h
+SP_LEV_H    = $(INCL)/sp_lev.h
+TILE_H      = ../win/share/tile.h
+
+#==========================================
+# Miscellaneous
+#==========================================
+
+DATABASE = $(DAT)/data.base
+
+#
+#  The name of the game.
+#
+
+GAMEFILE = $(GAMEDIR)/$(GAME).exe
+
+
+#==========================================
+#=============== TARGETS ==================
+#==========================================
+
+# Since DOS doesn't allow / as path separator, and GCC doesn't allow \ as
+# path separator, we must change all pathnames when performing DOS commands.
+# This is done by blindly applying $(subst /,\, ...) on every command.
+# Where any command contain / for another reason (switch char, or echoing
+# comment lines to lev/dungeon files) a little more care is taken.
+
+#
+#  The default make target (so just typing 'nmake' is useful).
+#
+default : $(GAMEFILE)
+
+#
+#  The main target.
+#
+
+$(GAME) : $(O)obj.tag $(O)utility.tag graphicschk $(GAMEFILE)
+	@echo $(GAME) is up to date.
+
+#
+#  Everything
+#
+
+all :   install
+
+install: graphicschk $(GAME) $(O)install.tag
+	@echo Done.
+
+
+$(O)install.tag:  $(DAT)/data    $(DAT)/rumors    $(DAT)/dungeon \
+	       $(DAT)/oracles $(DAT)/quest.dat $(O)sp_lev.tag $(DLB)
+ifeq  "$(USE_DLB)" "Y"
+	$(subst /,\,copy nhdat                $(GAMEDIR))
+	$(subst /,\,copy $(DAT)/license       $(GAMEDIR))
+	$(subst /,\,copy $(DAT)/opthelp       $(GAMEDIR))
+else
+	$(subst /,\,copy $(DAT)/*.            $(GAMEDIR))
+	$(subst /,\,copy $(DAT)/*.dat         $(GAMEDIR))
+	$(subst /,\,copy $(DAT)/*.lev         $(GAMEDIR))
+	$(subst /,\,if exist $(GAMEDIR)/makefile del $(GAMEDIR)/makefile)
+endif
+	$(subst /,\,if exist $(DOC)/guidebook.txt copy $(DOC)/guidebook.txt $(GAMEDIR)/Guidebook.txt)
+	$(subst /,\,if exist $(DOC)/nethack.txt copy $(DOC)/nethack.txt $(GAMEDIR)/NetHack.txt)
+	$(subst /,\,copy $(NTSYS)/defaults.nh   $(GAMEDIR)/defaults.nh)
+	$(subst /,\,echo install done > $@)
+
+#  copy $(NTSYS)/winnt.hlp    $(GAMEDIR)
+
+recover: $(U)recover.exe
+	$(subst /,\,if exist $(U)recover.exe copy $(U)recover.exe  $(GAMEDIR))
+	$(subst /,\,if exist $(DOC)/recover.txt copy $(DOC)/recover.txt $(GAMEDIR)/recover.txt)
+
+$(O)sp_lev.tag: $(O)utility.tag $(DAT)/bigroom.des  $(DAT)/castle.des \
+	 $(DAT)/endgame.des $(DAT)/gehennom.des $(DAT)/knox.des   \
+	 $(DAT)/medusa.des  $(DAT)/oracle.des   $(DAT)/tower.des  \
+	 $(DAT)/yendor.des  $(DAT)/arch.des     $(DAT)/barb.des   \
+	 $(DAT)/caveman.des $(DAT)/healer.des   $(DAT)/knight.des \
+	 $(DAT)/monk.des    $(DAT)/priest.des   $(DAT)/ranger.des \
+	 $(DAT)/rogue.des   $(DAT)/samurai.des  $(DAT)/sokoban.des \
+	 $(DAT)/tourist.des $(DAT)/valkyrie.des $(DAT)/wizard.des
+	$(subst /,\,$(U)lev_comp $(DAT)/bigroom.des)
+	$(subst /,\,$(U)lev_comp $(DAT)/castle.des)
+	$(subst /,\,$(U)lev_comp $(DAT)/endgame.des)
+	$(subst /,\,$(U)lev_comp $(DAT)/gehennom.des)
+	$(subst /,\,$(U)lev_comp $(DAT)/knox.des)
+	$(subst /,\,$(U)lev_comp $(DAT)/mines.des)
+	$(subst /,\,$(U)lev_comp $(DAT)/medusa.des)
+	$(subst /,\,$(U)lev_comp $(DAT)/oracle.des)
+	$(subst /,\,$(U)lev_comp $(DAT)/sokoban.des)
+	$(subst /,\,$(U)lev_comp $(DAT)/tower.des)
+	$(subst /,\,$(U)lev_comp $(DAT)/yendor.des)
+	$(subst /,\,$(U)lev_comp $(DAT)/arch.des)
+	$(subst /,\,$(U)lev_comp $(DAT)/barb.des)
+	$(subst /,\,$(U)lev_comp $(DAT)/caveman.des)
+	$(subst /,\,$(U)lev_comp $(DAT)/healer.des)
+	$(subst /,\,$(U)lev_comp $(DAT)/knight.des)
+	$(subst /,\,$(U)lev_comp $(DAT)/monk.des)
+	$(subst /,\,$(U)lev_comp $(DAT)/priest.des)
+	$(subst /,\,$(U)lev_comp $(DAT)/ranger.des)
+	$(subst /,\,$(U)lev_comp $(DAT)/rogue.des)
+	$(subst /,\,$(U)lev_comp $(DAT)/samurai.des)
+	$(subst /,\,$(U)lev_comp $(DAT)/tourist.des)
+	$(subst /,\,$(U)lev_comp $(DAT)/valkyrie.des)
+	$(subst /,\,$(U)lev_comp $(DAT)/wizard.des)
+	$(subst /,\,copy *.lev $(DAT))
+	$(subst /,\,del *.lev)
+	$(subst /,\,echo sp_levs done > $(O)sp_lev.tag)
+
+$(O)utility.tag: $(INCL)/date.h $(INCL)/onames.h $(INCL)/pm.h \
+	 $(SRC)/monstr.c $(SRC)/vis_tab.c $(U)lev_comp.exe $(INCL)/vis_tab.h \
+	 $(U)dgn_comp.exe $(TILEUTIL16)
+	$(subst /,\,@echo utilities made >$@)
+	@echo utilities made.
+
+tileutil: $(U)gif2txt.exe $(U)gif2tx32.exe $(U)txt2ppm.exe
+	@echo Optional tile development utilities are up to date.
+
+ifeq  "$(GRAPHICAL)" "Y"
+$(NHRES): $(TILEBMP16) $(WIN32)/winhack.rc $(WIN32)/mnsel.bmp \
+	 $(WIN32)/mnselcnt.bmp $(WIN32)/mnunsel.bmp \
+	 $(WIN32)/petmark.bmp $(WIN32)/NetHack.ico $(WIN32)/rip.bmp \
+	 $(WIN32)/splash.bmp
+	@$(rc) -o$@ --include-dir $(WIN32) -i $(WIN32)/winhack.rc
+else
+$(NHRES): $(NTSYS)/console.rc $(NTSYS)/NetHack.ico 
+	@$(rc) -o$@ --include-dir $(NTSYS) -i $(NTSYS)/console.rc
+endif
+
+#==========================================
+#  The main target.
+#==========================================
+$(O)gamedir.tag:
+	$(subst /,\,@if not exist $(GAMEDIR)/*.* echo creating directory $(GAMEDIR))
+	$(subst /,\,@if not exist $(GAMEDIR)/*.* mkdir $(GAMEDIR))
+	$(subst /,\,@echo directory created > $@)
+
+ifeq  "$(GRAPHICAL)" "Y"
+$(GAMEFILE) : $(ALLOBJ) $(NHRES) $(O)gamedir.tag
+else
+#$(GAMEFILE) : $(ALLOBJ) $(NHRES) $(O)gamedir.tag \
+#	 $(GAMEDIR)/nhdefkey.dll $(GAMEDIR)/nh340key.dll $(GAMEDIR)/nhraykey.dll
+$(GAMEFILE) : $(ALLOBJ) $(NHRES) $(O)gamedir.tag
+endif
+	@echo Linking....
+	$(link) $(lflags) -o$@ $(ALLOBJ) $(NHRES) $(WINPLIBS)
+	$(subst /,\,@if exist $(O)install.tag del $(O)install.tag)
+
+
+$(O)nhdefkey.o:
+	$(cc) $(CFLAGS) -DBUILD_DLL -o$@ $(NTSYS)/nhdefkey.c 
+
+$(GAMEDIR)/nhdefkey.dll : $(O)nhdefkey.o $(O)gamedir.tag
+	@echo Linking $@
+	$(cc) -shared -Wl,--export-all-symbols \
+		-Wl,--add-stdcall-alias -o $@ $<
+
+$(O)nh340key.o:
+	$(cc) $(CFLAGS) -DBUILD_DLL -o$@ $(NTSYS)/nh340key.c 
+
+$(GAMEDIR)/nh340key.dll : $(O)nh340key.o $(O)gamedir.tag
+	@echo Linking $@
+	$(cc) -shared -Wl,--export-all-symbols \
+		-Wl,--add-stdcall-alias -o $@ $<
+
+$(O)nhraykey.o:
+		$(cc) $(CFLAGS) -DBUILD_DLL -o$@ $(NTSYS)/nhraykey.c 
+
+$(GAMEDIR)/nhraykey.dll : $(O)nhraykey.o $(O)gamedir.tag
+	@echo Linking $@
+	$(cc) -shared -Wl,--export-all-symbols \
+		-Wl,--add-stdcall-alias -o $@ $<
+
+$(GAME)_.ico : $(NTSYS)/$(GAME).ico
+	$(subst /,\,@copy $(NTSYS)/$(GAME).ico $@)
+
+#==========================================
+# Create directory for holding object files
+#==========================================
+
+graphicschk:
+ifeq  "$(GRAPHICAL)" "Y"
+	@echo ----
+	@echo NOTE: This build will include tile support.
+	@echo ----
+endif
+	$(subst /,\,@echo graphicschk > graphicschk)
+
+#
+#  Secondary Targets.
+#
+
+#==========================================
+# Makedefs Stuff
+#==========================================
+
+$(U)makedefs.exe: $(MAKEOBJS)
+	@$(link) $(LFLAGSU) -o$@ $(MAKEOBJS)
+
+$(O)makedefs.o: $(CONFIG_H) $(INCL)/monattk.h $(INCL)/monflag.h \
+	 $(INCL)/objclass.h $(INCL)/monsym.h $(INCL)/qtext.h \
+	 $(INCL)/patchlevel.h $(U)makedefs.c $(O)obj.tag
+	$(cc) $(CFLAGSU) -o$@ $(U)makedefs.c
+
+#
+#  date.h should be remade every time any of the source or include
+#  files is modified.
+#
+
+$(INCL)/date.h $(OPTIONS_FILE): $(U)makedefs.exe
+	$(subst /,\,$(U)makedefs -v)
+
+#$(OPTIONS_FILE): $(U)makedefs.exe
+#	$(subst /,\,$(U)makedefs -v)
+
+$(INCL)/onames.h : $(U)makedefs.exe
+	$(subst /,\,$(U)makedefs -o)
+
+$(INCL)/pm.h : $(U)makedefs.exe
+	$(subst /,\,$(U)makedefs -p)
+
+#$(INCL)/trap.h : $(U)makedefs.exe
+#  $(U)makedefs -t
+
+$(SRC)/monstr.c: $(U)makedefs.exe
+	$(subst /,\,$(U)makedefs -m)
+
+$(INCL)/vis_tab.h: $(U)makedefs.exe
+	$(subst /,\,$(U)makedefs -z)
+
+$(SRC)/vis_tab.c: $(U)makedefs.exe
+	$(subst /,\,$(U)makedefs -z)
+
+#==========================================
+# uudecode utility and uuencoded targets
+#==========================================
+
+$(U)uudecode.exe: $(O)uudecode.o
+	@$(link) $(LFLAGSU) -o$@ $(O)uudecode.o
+
+$(O)uudecode.o: $(SSYS)/uudecode.c
+
+$(NTSYS)/NetHack.ico : $(U)uudecode.exe $(NTSYS)/nhico.uu
+	$(subst /,\,$(U)uudecode.exe $(NTSYS)/nhico.uu)
+	$(subst /,\,copy NetHack.ico $@)
+	del NetHack.ico
+
+$(WIN32)/NetHack.ico : $(NTSYS)/NetHack.ico
+	$(subst /,\,copy $< $@)
+
+$(WIN32)/mnsel.bmp: $(U)uudecode.exe $(WIN32)/mnsel.uu
+	$(subst /,\,$(U)uudecode.exe $(WIN32)/mnsel.uu)
+	$(subst /,\,copy mnsel.bmp $@)
+	del mnsel.bmp
+
+$(WIN32)/mnselcnt.bmp: $(U)uudecode.exe $(WIN32)/mnselcnt.uu
+	$(subst /,\,$(U)uudecode.exe $(WIN32)/mnselcnt.uu)
+	$(subst /,\,copy mnselcnt.bmp $@)
+	del mnselcnt.bmp
+
+$(WIN32)/mnunsel.bmp: $(U)uudecode.exe $(WIN32)/mnunsel.uu
+	$(subst /,\,$(U)uudecode.exe $(WIN32)/mnunsel.uu)
+	$(subst /,\,copy mnunsel.bmp $@)
+	del mnunsel.bmp
+
+$(WIN32)/petmark.bmp: $(U)uudecode.exe $(WIN32)/petmark.uu
+	$(subst /,\,$(U)uudecode.exe $(WIN32)/petmark.uu)
+	$(subst /,\,copy petmark.bmp $@)
+	del petmark.bmp
+
+$(WIN32)/rip.bmp: $(U)uudecode.exe $(WIN32)/rip.uu
+	$(subst /,\,$(U)uudecode.exe $(WIN32)/rip.uu)
+	$(subst /,\,copy rip.bmp $@)
+	del rip.bmp
+
+$(WIN32)/splash.bmp: $(U)uudecode.exe $(WIN32)/splash.uu
+	$(subst /,\,$(U)uudecode.exe $(WIN32)/splash.uu)
+	$(subst /,\,copy splash.bmp $@)
+	del splash.bmp
+
+
+#==========================================
+# Level Compiler Stuff
+#==========================================
+
+LEVCFLAGS=$(cflags) -c -DWIN32 -D_WIN32 -I../include $(cdebug) -DDLB
+
+$(U)lev_comp.exe: $(SPLEVOBJS)
+	@echo Linking $@...
+	@$(link) $(LFLAGSU) -o$@ $(SPLEVOBJS)
+
+$(O)lev_yacc.o: $(HACK_H)   $(SP_LEV_H) $(INCL)/lev_comp.h $(U)lev_yacc.c
+	$(cc) $(LEVCFLAGS) -o$@ $(U)lev_yacc.c
+
+$(O)lev_$(LEX).o: $(HACK_H)   $(INCL)/lev_comp.h $(SP_LEV_H) \
+	$(U)lev_$(LEX).c
+	$(cc) $(LEVCFLAGS) -o$@ $(U)lev_$(LEX).c
+
+$(O)lev_main.o:   $(U)lev_main.c $(HACK_H)   $(SP_LEV_H)
+	$(cc) $(LEVCFLAGS) -o$@ $(U)lev_main.c
+
+
+$(U)lev_yacc.c $(INCL)/lev_comp.h : $(U)lev_comp.y
+ifeq  "$(DO_YACC)" "YACC_ACT"
+	$(subst /,\,$(YACC) -d $(U)lev_comp.y)
+	$(subst /,\,copy $(YTABC) $(U)lev_yacc.c)
+	$(subst /,\,copy $(YTABH) $(INCL)/lev_comp.h)
+	$(subst /,\,@del $(YTABC))
+	$(subst /,\,@del $(YTABH))
+
+else
+	@echo $(U)lev_comp.y has changed.
+	@echo To update $(U)lev_yacc.c and $(INCL)/lev_comp.h run $(YACC).
+	@echo ---
+	@echo For now, we will copy the prebuilt lev_yacc.c and
+	@echo lev_comp.h from $(SSYS) into $(UTIL) and use them.
+	$(subst /,\,@copy $(SSYS)/lev_yacc.c $(U)lev_yacc.c >nul)
+	$(subst /,\,@copy $(SSYS)/lev_comp.h $(INCL)/lev_comp.h >nul)
+	$(subst /,\,echo.>>$(U)lev_yacc.c)
+	$(subst /,\,echo.>>$(INCL)/lev_comp.h)
+endif
+
+$(U)lev_$(LEX).c: $(U)lev_comp.l
+ifeq  "$(DO_LEX)" "LEX_ACT"
+	$(subst /,\,$(LEX) $(FLEXSKEL) $(U)lev_comp.l)
+	$(subst /,\,copy $(LEXYYC) $@)
+	$(subst /,\,@del $(LEXYYC))
+else
+	@echo $(U)lev_comp.l has changed. To update $@ run $(LEX).
+	@echo ---
+	@echo For now, we will copy the prebuilt lev_lex.c
+	@echo from $(SSYS) into $(UTIL) and use it.
+	$(subst /,\,@copy $(SSYS)/lev_lex.c $@ >nul)
+	$(subst /,\,echo.>>$@)
+endif
+
+#==========================================
+# Dungeon Compiler Stuff
+#==========================================
+
+$(U)dgn_comp.exe: $(DGNCOMPOBJS)
+	@echo Linking $@...
+	@$(link) $(LFLAGSU) -o$@ $(DGNCOMPOBJS)
+
+
+$(O)dgn_yacc.o:   $(HACK_H)   $(DGN_FILE_H) $(INCL)/dgn_comp.h $(U)dgn_yacc.c
+	$(cc) $(LEVCFLAGS) -o$@ $(U)dgn_yacc.c
+
+$(O)dgn_$(LEX).o: $(HACK_H)   $(DGN_FILE_H)  $(INCL)/dgn_comp.h \
+	 $(U)dgn_$(LEX).c
+	$(cc) $(LEVCFLAGS) -o$@ $(U)dgn_$(LEX).c
+
+$(O)dgn_main.o:   $(HACK_H) $(U)dgn_main.c
+	$(cc) $(LEVCFLAGS) -o$@ $(U)dgn_main.c
+
+$(U)dgn_yacc.c $(INCL)/dgn_comp.h : $(U)dgn_comp.y
+ifeq  "$(DO_YACC)" "YACC_ACT"
+	$(subst /,\,$(YACC) -d $(U)dgn_comp.y)
+	$(subst /,\,copy $(YTABC) $(U)dgn_yacc.c)
+	$(subst /,\,copy $(YTABH) $(INCL)/dgn_comp.h)
+	$(subst /,\,@del $(YTABC))
+	$(subst /,\,@del $(YTABH))
+else
+	@echo $(U)dgn_comp.y has changed. To update dgn_yacc.c and
+	@echo $(INCL)/dgn_comp.h run $(YACC).
+	@echo ---
+	@echo For now, we will copy the prebuilt $(U)dgn_yacc.c and
+	@echo dgn_comp.h from $(SSYS) into $(UTIL) and use them.
+	$(subst /,\,@copy $(SSYS)/dgn_yacc.c $(U)dgn_yacc.c >nul)
+	$(subst /,\,@copy $(SSYS)/dgn_comp.h $(INCL)/dgn_comp.h >nul)
+	$(subst /,\,echo.>>$(U)dgn_yacc.c)
+	$(subst /,\,echo.>>$(INCL)/dgn_comp.h)
+endif
+
+$(U)dgn_$(LEX).c: $(U)dgn_comp.l
+ifeq  "$(DO_LEX)" "LEX_ACT"
+	$(subst /,\,$(LEX) $(FLEXSKEL) $(U)dgn_comp.l)
+	$(subst /,\,copy $(LEXYYC) $@)
+	$(subst /,\,@del $(LEXYYC))
+else
+	@echo $(U)dgn_comp.l has changed. To update $@ run $(LEX).
+	@echo ---
+	@echo For now, we will copy the prebuilt dgn_lex.c
+	@echo from $(SSYS) into $(UTIL) and use it.
+	$(subst /,\,@copy $(SSYS)/dgn_lex.c $@ >nul)
+	$(subst /,\,echo.>>$@)
+endif
+
+#==========================================
+# Create directory for holding object files
+#==========================================
+
+$(O)obj.tag:
+	$(subst /,\,@if not exist $(OBJ)/*.* echo creating directory $(OBJ))
+	$(subst /,\,@if not exist $(OBJ)/*.* mkdir $(OBJ))
+	$(subst /,\,@echo directory created > $@)
+
+
+#==========================================
+#=========== SECONDARY TARGETS ============
+#==========================================
+
+#===========================================
+# Header files NOT distributed in ../include
+#===========================================
+
+$(INCL)/win32api.h: $(NTSYS)/win32api.h
+	$(subst /,\,copy $(NTSYS)/win32api.h $@)
+
+
+#==========================================
+# DLB utility and nhdat file creation
+#==========================================
+
+$(U)dlb_main.exe: $(DLBOBJ) $(O)dlb.o
+	@$(link) $(LFLAGSU) -o$@ $(O)dlb_main.o $(O)dlb.o $(O)alloc.o $(O)panic.o
+
+
+$(O)dlb.o:   $(O)dlb_main.o $(O)alloc.o $(O)panic.o $(INCL)/dlb.h
+	$(cc) $(CFLAGS) -o$@ $(SRC)/dlb.c
+
+$(O)dlb_main.o: $(UTIL)/dlb_main.c $(INCL)/config.h $(INCL)/dlb.h
+	$(cc) $(CFLAGS) -o$@ $(UTIL)/dlb_main.c
+
+$(DAT)/porthelp: $(NTSYS)/porthelp
+	$(subst /,\,@copy $(NTSYS)/porthelp $@ >nul)
+
+nhdat:  $(U)dlb_main.exe $(DAT)/data $(DAT)/oracles $(OPTIONS_FILE) \
+	 $(DAT)/quest.dat $(DAT)/rumors $(DAT)/help $(DAT)/hh $(DAT)/cmdhelp \
+	 $(DAT)/history $(DAT)/opthelp $(DAT)/wizhelp $(DAT)/dungeon \
+	 $(DAT)/porthelp $(DAT)/license $(O)sp_lev.tag
+	$(subst /,\,echo data >$(DAT)/dlb.lst)
+	$(subst /,\,echo oracles >>$(DAT)/dlb.lst)
+	$(subst /,\,if exist $(DAT)/options echo options >>$(DAT)/dlb.lst)
+	$(subst /,\,if exist $(DAT)/ttyoptions echo ttyoptions >>$(DAT)/dlb.lst)
+	$(subst /,\,if exist $(DAT)/guioptions echo guioptions >>$(DAT)/dlb.lst)
+	$(subst /,\,if exist $(DAT)/porthelp echo porthelp >>$(DAT)/dlb.lst)
+	$(subst /,\,echo quest.dat >>$(DAT)/dlb.lst)
+	$(subst /,\,echo rumors >>$(DAT)/dlb.lst)
+	$(subst /,\,echo help >>$(DAT)/dlb.lst)
+	$(subst /,\,echo hh >>$(DAT)/dlb.lst)
+	$(subst /,\,echo cmdhelp >>$(DAT)/dlb.lst)
+	$(subst /,\,echo history >>$(DAT)/dlb.lst)
+	$(subst /,\,echo opthelp >>$(DAT)/dlb.lst)
+	$(subst /,\,echo wizhelp >>$(DAT)/dlb.lst)
+	$(subst /,\,echo dungeon >>$(DAT)/dlb.lst)
+	$(subst /,\,echo license >>$(DAT)/dlb.lst)
+	dir /l /b /-p $(subst /,\,$(DAT)/*.lev >>$(DAT)/dlb.lst)
+	$(subst /,\,$(U)dlb_main CcIf $(DAT) dlb.lst $(SRC)/nhdat)
+
+#==========================================
+#  Recover Utility
+#==========================================
+
+$(U)recover.exe: $(RECOVOBJS)
+	$(link) $(LFLAGSU) -o$@ $(RECOVOBJS)
+
+$(O)recover.o: $(CONFIG_H) $(U)recover.c $(INCL)/win32api.h
+	$(cc) $(CFLAGSU) -o$@ $(U)recover.c
+
+#==========================================
+#  Tile Mapping
+#==========================================
+
+$(SRC)/tile.c: $(U)tilemap.exe
+	@echo A new $@ has been created
+	@$(U)tilemap
+
+$(U)tilemap.exe: $(O)tilemap.o
+	@$(link) $(LFLAGSU) -o$@ $(O)tilemap.o
+
+$(O)tilemap.o: $(WSHR)/tilemap.c $(HACK_H)
+	$(cc) $(CFLAGSU) -o$@ $(WSHR)/tilemap.c
+
+$(O)tiletx32.o: $(WSHR)/tilemap.c $(HACK_H)
+	$(cc) $(CFLAGS) -DTILETEXT -DTILE_X=32 -DTILE_Y=32 -o$@ $(WSHR)/tilemap.c
+
+$(O)tiletxt.o: $(WSHR)/tilemap.c $(HACK_H)
+	$(cc) $(CFLAGS) -DTILETEXT -o$@ $(WSHR)/tilemap.c
+
+$(O)gifread.o: $(WSHR)/gifread.c  $(CONFIG_H) $(TILE_H)
+	$(cc) $(CFLAGS) -I$(WSHR) -o$@ $(WSHR)/gifread.c
+
+$(O)gifrd32.o: $(WSHR)/gifread.c  $(CONFIG_H) $(TILE_H)
+	$(cc) $(CFLAGS) -I$(WSHR) -DTILE_X=32 -DTILE_Y=32 -o$@ $(WSHR)/gifread.c
+
+$(O)ppmwrite.o: $(WSHR)/ppmwrite.c $(CONFIG_H) $(TILE_H)
+	$(cc) $(CFLAGS) -I$(WSHR) -o$@ $(WSHR)/ppmwrite.c
+
+$(O)tiletext.o: $(WSHR)/tiletext.c  $(CONFIG_H) $(TILE_H)
+	$(cc) $(CFLAGS) -I$(WSHR) -o$@ $(WSHR)/tiletext.c
+
+$(O)tilete32.o: $(WSHR)/tiletext.c  $(CONFIG_H) $(TILE_H)
+	$(cc) $(CFLAGS) -I$(WSHR) -DTILE_X=32 -DTILE_Y=32 -o$@ $(WSHR)/tiletext.c
+
+#==========================================
+# Optional Tile Utilities
+#==========================================
+
+$(U)gif2txt.exe: $(GIFREADERS) $(TEXT_IO)
+	@echo Linking $@...
+	@$(link) $(LFLAGSU) -o$@ $(GIFREADERS) $(TEXT_IO)
+
+$(U)gif2tx32.exe: $(GIFREADERS32) $(TEXT_IO32)
+	@echo Linking $@...
+	@$(link) $(LFLAGSU) -o$@ $(GIFREADERS32) $(TEXT_IO32)
+
+
+$(U)txt2ppm.exe: $(PPMWRITERS) $(TEXT_IO)
+	@echo Linking $@...
+	@$(link) $(LFLAGSU) -o$@ $(PPMWRITERS) $(TEXT_IO)
+
+
+ifeq  "$(GRAPHICAL)" "Y"
+$(TILEBMP16): $(TILEUTIL16) $(TILEFILES)
+	@echo Creating 16x16 binary tile files (this may take some time)
+	$(subst /,\,@$(U)tile2bmp $(TILEBMP16))
+#$(TILEBMP32): $(TILEUTIL32) $(TILEFILES32)
+#	@echo Creating 32x32 binary tile files (this may take some time)
+#	$(subst /,\,@$(U)til2bm32 $(TILEBMP32))
+else
+$(TILEBMP16):
+$(TILEBMP32):
+endif
+
+$(U)tile2bmp.exe: $(O)tile2bmp.o $(TEXT_IO)
+	@echo Linking $@...
+	@$(link) $(LFLAGSU) -o$@ $(O)tile2bmp.o $(TEXT_IO)
+
+$(U)til2bm32.exe: $(O)til2bm32.o $(TEXT_IO32)
+	@echo Linking $@...
+	@$(link) $(LFLAGSU) -o$@ $(O)til2bm32.o $(TEXT_IO32)
+
+$(O)tile2bmp.o: $(WSHR)/tile2bmp.c $(HACK_H) $(TILE_H) $(INCL)/win32api.h
+	$(cc) $(CFLAGS) -I$(WSHR) -o$@ $(WSHR)/tile2bmp.c
+
+$(O)til2bm32.o: $(WSHR)/til2bm32.c $(HACK_H) $(TILE_H) $(INCL)/win32api.h
+	$(cc) $(CFLAGS) -I$(WSHR) -DTILE_X=32 -DTILE_Y=32 -o$@ $(WSHR)/til2bm32.c
+
+#==========================================
+# Housekeeping
+#==========================================
+
+spotless: clean
+	$(subst /,\,if exist graphicschk       del graphicschk)
+	$(subst /,\,if exist $(INCL)/date.h    del $(INCL)/date.h)
+	$(subst /,\,if exist $(INCL)/onames.h  del $(INCL)/onames.h)
+	$(subst /,\,if exist $(INCL)/pm.h      del $(INCL)/pm.h)
+	$(subst /,\,if exist $(INCL)/vis_tab.h del $(INCL)/vis_tab.h)
+	$(subst /,\,if exist $(SRC)/vis_tab.c  del $(SRC)/vis_tab.c)
+	$(subst /,\,if exist $(SRC)/tile.c     del $(SRC)/tile.c)
+	$(subst /,\,if exist $(U)*.lnk         del $(U)*.lnk)
+	$(subst /,\,if exist $(U)*.map         del $(U)*.map)
+	$(subst /,\,if exist $(DAT)/data       del $(DAT)/data)
+	$(subst /,\,if exist $(DAT)/rumors     del $(DAT)/rumors)
+	$(subst /,\,if exist $(DAT)/???-fil?.lev      del $(DAT)/???-fil?.lev)
+	$(subst /,\,if exist $(DAT)/???-goal.lev      del $(DAT)/???-goal.lev)
+	$(subst /,\,if exist $(DAT)/???-loca.lev      del $(DAT)/???-loca.lev)
+	$(subst /,\,if exist $(DAT)/???-strt.lev      del $(DAT)/???-strt.lev)
+	$(subst /,\,if exist $(DAT)/air.lev      del $(DAT)/air.lev)
+	$(subst /,\,if exist $(DAT)/asmodeus.lev      del $(DAT)/asmodeus.lev)
+	$(subst /,\,if exist $(DAT)/astral.lev   del $(DAT)/astral.lev)
+	$(subst /,\,if exist $(DAT)/baalz.lev    del $(DAT)/baalz.lev)
+	$(subst /,\,if exist $(DAT)/bigrm-*.lev  del $(DAT)/bigrm-*.lev)
+	$(subst /,\,if exist $(DAT)/castle.lev   del $(DAT)/castle.lev)
+	$(subst /,\,if exist $(DAT)/data    del $(DAT)/data)
+	$(subst /,\,if exist $(DAT)/dungeon      del $(DAT)/dungeon)
+	$(subst /,\,if exist $(DAT)/dungeon.pdf  del $(DAT)/dungeon.pdf)
+	$(subst /,\,if exist $(DAT)/earth.lev    del $(DAT)/earth.lev)
+	$(subst /,\,if exist $(DAT)/fakewiz?.lev      del $(DAT)/fakewiz?.lev)
+	$(subst /,\,if exist $(DAT)/fire.lev     del $(DAT)/fire.lev)
+	$(subst /,\,if exist $(DAT)/juiblex.lev  del $(DAT)/juiblex.lev)
+	$(subst /,\,if exist $(DAT)/knox.lev     del $(DAT)/knox.lev)
+	$(subst /,\,if exist $(DAT)/medusa-?.lev      del $(DAT)/medusa-?.lev)
+	$(subst /,\,if exist $(DAT)/mine*.lev    del $(DAT)/mine*.lev)
+	$(subst /,\,if exist $(DAT)/options      del $(DAT)/options)
+	$(subst /,\,if exist $(DAT)/ttyoptions   del $(DAT)/ttyoptions)
+	$(subst /,\,if exist $(DAT)/guioptions   del $(DAT)/guioptions)
+	$(subst /,\,if exist $(DAT)/oracle.lev   del $(DAT)/oracle.lev)
+	$(subst /,\,if exist $(DAT)/oracles      del $(DAT)/oracles)
+	$(subst /,\,if exist $(DAT)/orcus.lev    del $(DAT)/orcus.lev)
+	$(subst /,\,if exist $(DAT)/rumors  del $(DAT)/rumors)
+	$(subst /,\,if exist $(DAT)/quest.dat    del $(DAT)/quest.dat)
+	$(subst /,\,if exist $(DAT)/sanctum.lev  del $(DAT)/sanctum.lev)
+	$(subst /,\,if exist $(DAT)/soko?-?.lev  del $(DAT)/soko?-?.lev)
+	$(subst /,\,if exist $(DAT)/tower?.lev   del $(DAT)/tower?.lev)
+	$(subst /,\,if exist $(DAT)/valley.lev   del $(DAT)/valley.lev)
+	$(subst /,\,if exist $(DAT)/water.lev    del $(DAT)/water.lev)
+	$(subst /,\,if exist $(DAT)/wizard?.lev  del $(DAT)/wizard?.lev)
+	$(subst /,\,if exist $(O)sp_lev.tag     del $(O)sp_lev.tag)
+	$(subst /,\,if exist $(SRC)/monstr.c    del $(SRC)/monstr.c)
+	$(subst /,\,if exist $(SRC)/vis_tab.c   del $(SRC)/vis_tab.c)
+	$(subst /,\,if exist $(U)recover.exe    del $(U)recover.exe)
+	$(subst /,\,if exist $(DAT)/dlb.lst      del $(DAT)/dlb.lst)
+	$(subst /,\,if exist nhdat.         del nhdat.)
+	$(subst /,\,if exist $(O)install.tag    del $(O)install.tag)
+	$(subst /,\,if exist $(O)obj.tag    del $(O)obj.tag)
+	$(subst /,\,if exist $(O)gamedir.tag    del $(O)gamedir.tag)
+ifneq "$(OBJ)" ""
+	$(subst /,\,rmdir $(OBJ)) /s /Q
+endif
+
+clean:
+	$(subst /,\,if exist $(O)*.o del $(O)*.o)
+	$(subst /,\,if exist $(O)utility.tag   del $(O)utility.tag)
+	$(subst /,\,if exist $(U)makedefs.exe  del $(U)makedefs.exe)
+	$(subst /,\,if exist $(U)lev_comp.exe  del $(U)lev_comp.exe)
+	$(subst /,\,if exist $(U)dgn_comp.exe  del $(U)dgn_comp.exe)
+	$(subst /,\,if exist $(SRC)/*.lnk      del $(SRC)/*.lnk)
+	$(subst /,\,if exist $(SRC)/*.map      del $(SRC)/*.map)
+	$(subst /,\,if exist $(TILEBMP16)      del $(TILEBMP16))
+	$(subst /,\,if exist $(TILEBMP32)      del $(TILEBMP32))
+
+#===================================================================
+# OTHER DEPENDENCIES
+#===================================================================
+
+#
+# dat dependencies
+#
+
+$(DAT)/data: $(O)utility.tag    $(DATABASE)
+	$(subst /,\,$(U)makedefs -d)
+
+$(DAT)/rumors: $(O)utility.tag    $(DAT)/rumors.tru   $(DAT)/rumors.fal
+	$(subst /,\,$(U)makedefs -r)
+
+$(DAT)/quest.dat: $(O)utility.tag  $(DAT)/quest.txt
+	$(subst /,\,$(U)makedefs -q)
+
+$(DAT)/oracles: $(O)utility.tag    $(DAT)/oracles.txt
+	$(subst /,\,$(U)makedefs -h)
+
+$(DAT)/dungeon: $(O)utility.tag  $(DAT)/dungeon.def
+	$(subst /,\,$(U)makedefs -e)
+	$(subst /,\,$(U)dgn_comp $(DAT)/dungeon.pdf)
+
+#
+# NT dependencies
+#
+
+$(O)nttty.o:   $(HACK_H) $(TILE_H) $(INCL)/win32api.h $(NTSYS)/nttty.c
+	$(cc) $(CFLAGS) -I$(WSHR) -o$@  $(NTSYS)/nttty.c
+$(O)winnt.o: $(HACK_H) $(INCL)/win32api.h $(NTSYS)/winnt.c
+	$(cc) $(CFLAGS) -o$@  $(NTSYS)/winnt.c
+$(O)ntsound.o: $(HACK_H) $(NTSYS)/ntsound.c
+	$(cc) $(CFLAGS)  -o$@ $(NTSYS)/ntsound.c
+$(O)mapimail.o: $(HACK_H) $(INCL)/nhlan.h $(NTSYS)/mapimail.c
+	$(cc) $(CFLAGS) -DMAPI_VERBOSE  -o$@ $(NTSYS)/mapimail.c
+
+#
+# util dependencies
+#
+
+$(O)panic.o:  $(U)panic.c $(CONFIG_H)
+	$(cc) $(CFLAGS) -o$@ $(U)panic.c
+
+#
+# The rest are stolen from sys/unix/Makefile.src,
+# with the following changes:
+#   * ../include changed to $(INCL)
+#   * -c (which is included in CFLAGS) substituted
+#	with -o$@
+#   * targets prefixed with $(O)
+#   * $(CC) changed to $(cc)
+# but otherwise untouched. 
+# That means that there is some irrelevant stuff
+# in here, but maintenance should be easier.
+#
+$(O)tos.o: ../sys/atari/tos.c $(HACK_H) $(INCL)/tcap.h
+	$(cc) $(CFLAGS) -o$@ ../sys/atari/tos.c
+$(O)pcmain.o: ../sys/share/pcmain.c $(HACK_H) $(INCL)/dlb.h \
+		$(INCL)/win32api.h
+	$(cc) $(CFLAGS) -o$@ ../sys/share/pcmain.c
+$(O)pcsys.o: ../sys/share/pcsys.c $(HACK_H)
+	$(cc) $(CFLAGS) -o$@ ../sys/share/pcsys.c
+$(O)pctty.o: ../sys/share/pctty.c $(HACK_H)
+	$(cc) $(CFLAGS) -o$@ ../sys/share/pctty.c
+$(O)pcunix.o: ../sys/share/pcunix.c $(HACK_H)
+	$(cc) $(CFLAGS) -o$@ ../sys/share/pcunix.c
+$(O)random.o: ../sys/share/random.c $(HACK_H)
+	$(cc) $(CFLAGS) -o$@ ../sys/share/random.c
+$(O)ioctl.o: ../sys/share/ioctl.c $(HACK_H) $(INCL)/tcap.h
+	$(cc) $(CFLAGS) -o$@ ../sys/share/ioctl.c
+$(O)unixtty.o: ../sys/share/unixtty.c $(HACK_H)
+	$(cc) $(CFLAGS) -o$@ ../sys/share/unixtty.c
+$(O)unixmain.o: ../sys/unix/unixmain.c $(HACK_H) $(INCL)/dlb.h
+	$(cc) $(CFLAGS) -o$@ ../sys/unix/unixmain.c
+$(O)unixunix.o: ../sys/unix/unixunix.c $(HACK_H)
+	$(cc) $(CFLAGS) -o$@ ../sys/unix/unixunix.c
+$(O)unixres.o: ../sys/unix/unixres.c $(CONFIG_H)
+	$(cc) $(CFLAGS) -o$@ ../sys/unix/unixres.c
+$(O)bemain.o: ../sys/be/bemain.c $(HACK_H) $(INCL)/dlb.h
+	$(cc) $(CFLAGS) -o$@ ../sys/be/bemain.c
+$(O)getline.o: ../win/tty/getline.c $(HACK_H) $(INCL)/func_tab.h
+	$(cc) $(CFLAGS) -o$@ ../win/tty/getline.c
+$(O)termcap.o: ../win/tty/termcap.c $(HACK_H) $(INCL)/tcap.h
+	$(cc) $(CFLAGS) -o$@ ../win/tty/termcap.c
+$(O)topl.o: ../win/tty/topl.c $(HACK_H) $(INCL)/tcap.h
+	$(cc) $(CFLAGS) -o$@ ../win/tty/topl.c
+$(O)wintty.o: ../win/tty/wintty.c $(HACK_H) $(INCL)/dlb.h \
+		$(INCL)/patchlevel.h $(INCL)/tcap.h
+	$(cc) $(CFLAGS) -o$@ ../win/tty/wintty.c
+$(O)Window.o: ../win/X11/Window.c $(INCL)/xwindowp.h $(INCL)/xwindow.h \
+		$(CONFIG_H)
+	$(cc) $(CFLAGS) -o$@ ../win/X11/Window.c
+$(O)dialogs.o: ../win/X11/dialogs.c $(CONFIG_H)
+	$(cc) $(CFLAGS) -o$@ ../win/X11/dialogs.c
+$(O)winX.o: ../win/X11/winX.c $(HACK_H) $(INCL)/winX.h $(INCL)/dlb.h \
+		$(INCL)/patchlevel.h ../win/X11/nh72icon \
+		../win/X11/nh56icon ../win/X11/nh32icon
+	$(cc) $(CFLAGS) -o$@ ../win/X11/winX.c
+$(O)winmap.o: ../win/X11/winmap.c $(INCL)/xwindow.h $(HACK_H) $(INCL)/dlb.h \
+		$(INCL)/winX.h $(INCL)/tile2x11.h
+	$(cc) $(CFLAGS) -o$@ ../win/X11/winmap.c
+$(O)winmenu.o: ../win/X11/winmenu.c $(HACK_H) $(INCL)/winX.h
+	$(cc) $(CFLAGS) -o$@ ../win/X11/winmenu.c
+$(O)winmesg.o: ../win/X11/winmesg.c $(INCL)/xwindow.h $(HACK_H) $(INCL)/winX.h
+	$(cc) $(CFLAGS) -o$@ ../win/X11/winmesg.c
+$(O)winmisc.o: ../win/X11/winmisc.c $(HACK_H) $(INCL)/func_tab.h \
+		$(INCL)/winX.h
+	$(cc) $(CFLAGS) -o$@ ../win/X11/winmisc.c
+$(O)winstat.o: ../win/X11/winstat.c $(HACK_H) $(INCL)/winX.h
+	$(cc) $(CFLAGS) -o$@ ../win/X11/winstat.c
+$(O)wintext.o: ../win/X11/wintext.c $(HACK_H) $(INCL)/winX.h $(INCL)/xwindow.h
+	$(cc) $(CFLAGS) -o$@ ../win/X11/wintext.c
+$(O)winval.o: ../win/X11/winval.c $(HACK_H) $(INCL)/winX.h
+	$(cc) $(CFLAGS) -o$@ ../win/X11/winval.c
+$(O)tile.o: tile.c $(HACK_H)
+$(O)gnaskstr.o: ../win/gnome/gnaskstr.c ../win/gnome/gnaskstr.h \
+		../win/gnome/gnmain.h
+	$(cc) $(CFLAGS) $(GNOMEINC) -o$@ ../win/gnome/gnaskstr.c
+$(O)gnbind.o: ../win/gnome/gnbind.c ../win/gnome/gnbind.h ../win/gnome/gnmain.h \
+		../win/gnome/gnaskstr.h ../win/gnome/gnyesno.h
+	$(cc) $(CFLAGS) $(GNOMEINC) -o$@ ../win/gnome/gnbind.c
+$(O)gnglyph.o: ../win/gnome/gnglyph.c ../win/gnome/gnglyph.h $(INCL)/tile2x11.h
+	$(cc) $(CFLAGS) $(GNOMEINC) -o$@ ../win/gnome/gnglyph.c
+$(O)gnmain.o: ../win/gnome/gnmain.c ../win/gnome/gnmain.h ../win/gnome/gnsignal.h \
+		../win/gnome/gnbind.h ../win/gnome/gnopts.h $(HACK_H) \
+		$(INCL)/date.h
+	$(cc) $(CFLAGS) $(GNOMEINC) -o$@ ../win/gnome/gnmain.c
+$(O)gnmap.o: ../win/gnome/gnmap.c ../win/gnome/gnmap.h ../win/gnome/gnglyph.h \
+		../win/gnome/gnsignal.h $(HACK_H)
+	$(cc) $(CFLAGS) $(GNOMEINC) -o$@ ../win/gnome/gnmap.c
+$(O)gnmenu.o: ../win/gnome/gnmenu.c ../win/gnome/gnmenu.h ../win/gnome/gnmain.h \
+		../win/gnome/gnbind.h
+	$(cc) $(CFLAGS) $(GNOMEINC) -o$@ ../win/gnome/gnmenu.c
+$(O)gnmesg.o: ../win/gnome/gnmesg.c ../win/gnome/gnmesg.h ../win/gnome/gnsignal.h
+	$(cc) $(CFLAGS) $(GNOMEINC) -o$@ ../win/gnome/gnmesg.c
+$(O)gnopts.o: ../win/gnome/gnopts.c ../win/gnome/gnopts.h ../win/gnome/gnglyph.h \
+		../win/gnome/gnmain.h ../win/gnome/gnmap.h $(HACK_H)
+	$(cc) $(CFLAGS) $(GNOMEINC) -o$@ ../win/gnome/gnopts.c
+$(O)gnplayer.o: ../win/gnome/gnplayer.c ../win/gnome/gnplayer.h \
+		../win/gnome/gnmain.h $(HACK_H)
+	$(cc) $(CFLAGS) $(GNOMEINC) -o$@ ../win/gnome/gnplayer.c
+$(O)gnsignal.o: ../win/gnome/gnsignal.c ../win/gnome/gnsignal.h \
+		../win/gnome/gnmain.h
+	$(cc) $(CFLAGS) $(GNOMEINC) -o$@ ../win/gnome/gnsignal.c
+$(O)gnstatus.o: ../win/gnome/gnstatus.c ../win/gnome/gnstatus.h \
+		../win/gnome/gnsignal.h ../win/gnome/gn_xpms.h \
+		../win/gnome/gnomeprv.h
+	$(cc) $(CFLAGS) $(GNOMEINC) -o$@ ../win/gnome/gnstatus.c
+$(O)gntext.o: ../win/gnome/gntext.c ../win/gnome/gntext.h ../win/gnome/gnmain.h \
+		../win/gnome/gn_rip.h
+	$(cc) $(CFLAGS) $(GNOMEINC) -o$@ ../win/gnome/gntext.c
+$(O)gnworn.o: ../win/gnome/gnworn.c ../win/gnome/gnworn.h ../win/gnome/gnglyph.h \
+		../win/gnome/gnsignal.h ../win/gnome/gnomeprv.h
+	$(cc) $(CFLAGS) $(GNOMEINC) -o$@ ../win/gnome/gnworn.c
+$(O)gnyesno.o: ../win/gnome/gnyesno.c ../win/gnome/gnbind.h ../win/gnome/gnyesno.h
+	$(cc) $(CFLAGS) $(GNOMEINC) -o$@ ../win/gnome/gnyesno.c
+$(O)wingem.o: ../win/gem/wingem.c $(HACK_H) $(INCL)/func_tab.h $(INCL)/dlb.h \
+		$(INCL)/patchlevel.h $(INCL)/wingem.h
+	$(cc) $(CFLAGS) -o$@ ../win/gem/wingem.c
+$(O)wingem1.o: ../win/gem/wingem1.c $(INCL)/gem_rsc.h $(INCL)/load_img.h \
+		$(INCL)/gr_rect.h $(INCL)/wintype.h $(INCL)/wingem.h
+	$(cc) $(CFLAGS) -o$@ ../win/gem/wingem1.c
+$(O)load_img.o: ../win/gem/load_img.c $(INCL)/load_img.h
+	$(cc) $(CFLAGS) -o$@ ../win/gem/load_img.c
+$(O)gr_rect.o: ../win/gem/gr_rect.c $(INCL)/gr_rect.h
+	$(cc) $(CFLAGS) -o$@ ../win/gem/gr_rect.c
+$(O)tile.o: tile.c $(HACK_H)
+$(O)qt_win.o: ../win/Qt/qt_win.cpp $(HACK_H) $(INCL)/func_tab.h \
+		$(INCL)/dlb.h $(INCL)/patchlevel.h $(INCL)/tile2x11.h \
+		$(INCL)/qt_win.h $(INCL)/qt_clust.h $(INCL)/qt_kde0.h \
+		$(INCL)/qt_xpms.h qt_win.moc qt_kde0.moc qttableview.moc
+	$(CXX) $(CXXFLAGS) -o$@ ../win/Qt/qt_win.cpp
+$(O)qt_clust.o: ../win/Qt/qt_clust.cpp $(INCL)/qt_clust.h
+	$(CXX) $(CXXFLAGS) -o$@ ../win/Qt/qt_clust.cpp
+$(O)qttableview.o: ../win/Qt/qttableview.cpp $(INCL)/qttableview.h
+	$(CXX) $(CXXFLAGS) -o$@ ../win/Qt/qttableview.cpp
+$(O)monstr.o: monstr.c $(CONFIG_H)
+$(O)vis_tab.o: vis_tab.c $(CONFIG_H) $(INCL)/vis_tab.h
+$(O)allmain.o: allmain.c $(HACK_H)
+$(O)alloc.o: alloc.c $(CONFIG_H)
+$(O)apply.o: apply.c $(HACK_H) $(INCL)/edog.h
+$(O)artifact.o: artifact.c $(HACK_H) $(INCL)/artifact.h $(INCL)/artilist.h
+$(O)attrib.o: attrib.c $(HACK_H)
+$(O)ball.o: ball.c $(HACK_H)
+$(O)bones.o: bones.c $(HACK_H) $(INCL)/lev.h
+$(O)botl.o: botl.c $(HACK_H)
+$(O)cmd.o: cmd.c $(HACK_H) $(INCL)/func_tab.h
+$(O)dbridge.o: dbridge.c $(HACK_H)
+$(O)decl.o: decl.c $(HACK_H)
+$(O)detect.o: detect.c $(HACK_H) $(INCL)/artifact.h
+$(O)dig.o: dig.c $(HACK_H) $(INCL)/edog.h
+$(O)display.o: display.c $(HACK_H)
+$(O)dlb.o: dlb.c $(CONFIG_H) $(INCL)/dlb.h
+$(O)do.o: do.c $(HACK_H) $(INCL)/lev.h
+$(O)do_name.o: do_name.c $(HACK_H)
+$(O)do_wear.o: do_wear.c $(HACK_H)
+$(O)dog.o: dog.c $(HACK_H) $(INCL)/edog.h
+$(O)dogmove.o: dogmove.c $(HACK_H) $(INCL)/mfndpos.h $(INCL)/edog.h
+$(O)dokick.o: dokick.c $(HACK_H) $(INCL)/eshk.h
+$(O)dothrow.o: dothrow.c $(HACK_H) $(INCL)/edog.h
+$(O)drawing.o: drawing.c $(HACK_H) $(INCL)/tcap.h
+$(O)dungeon.o: dungeon.c $(HACK_H) $(INCL)/dgn_file.h $(INCL)/dlb.h
+$(O)eat.o: eat.c $(HACK_H)
+$(O)end.o: end.c $(HACK_H) $(INCL)/eshk.h $(INCL)/dlb.h
+$(O)engrave.o: engrave.c $(HACK_H) $(INCL)/lev.h
+$(O)exper.o: exper.c $(HACK_H)
+$(O)explode.o: explode.c $(HACK_H)
+$(O)extralev.o: extralev.c $(HACK_H)
+$(O)files.o: files.c $(HACK_H) $(INCL)/dlb.h
+$(O)fountain.o: fountain.c $(HACK_H)
+$(O)hack.o: hack.c $(HACK_H)
+$(O)hacklib.o: hacklib.c $(HACK_H)
+$(O)invent.o: invent.c $(HACK_H)
+$(O)light.o: light.c $(HACK_H) $(INCL)/lev.h
+$(O)lock.o: lock.c $(HACK_H)
+$(O)mail.o: mail.c $(HACK_H) $(INCL)/mail.h
+$(O)makemon.o: makemon.c $(HACK_H) $(INCL)/epri.h $(INCL)/emin.h \
+		$(INCL)/edog.h
+$(O)mapglyph.o: mapglyph.c $(HACK_H)
+$(O)mcastu.o: mcastu.c $(HACK_H)
+$(O)mhitm.o: mhitm.c $(HACK_H) $(INCL)/artifact.h $(INCL)/edog.h
+$(O)mhitu.o: mhitu.c $(HACK_H) $(INCL)/artifact.h $(INCL)/edog.h
+$(O)minion.o: minion.c $(HACK_H) $(INCL)/emin.h $(INCL)/epri.h
+$(O)mklev.o: mklev.c $(HACK_H)
+$(O)mkmap.o: mkmap.c $(HACK_H) $(INCL)/sp_lev.h
+$(O)mkmaze.o: mkmaze.c $(HACK_H) $(INCL)/sp_lev.h $(INCL)/lev.h
+$(O)mkobj.o: mkobj.c $(HACK_H)
+$(O)mkroom.o: mkroom.c $(HACK_H)
+$(O)mon.o: mon.c $(HACK_H) $(INCL)/mfndpos.h $(INCL)/edog.h
+$(O)mondata.o: mondata.c $(HACK_H) $(INCL)/eshk.h $(INCL)/epri.h
+$(O)monmove.o: monmove.c $(HACK_H) $(INCL)/mfndpos.h $(INCL)/artifact.h \
+		$(INCL)/epri.h
+$(O)monst.o: monst.c $(CONFIG_H) $(INCL)/permonst.h $(INCL)/align.h \
+		$(INCL)/monattk.h $(INCL)/monflag.h $(INCL)/monsym.h \
+		$(INCL)/dungeon.h $(INCL)/eshk.h $(INCL)/vault.h \
+		$(INCL)/epri.h $(INCL)/color.h
+$(O)mplayer.o: mplayer.c $(HACK_H)
+$(O)mthrowu.o: mthrowu.c $(HACK_H)
+$(O)muse.o: muse.c $(HACK_H) $(INCL)/edog.h
+$(O)music.o: music.c $(HACK_H) #interp.c
+$(O)o_init.o: o_init.c $(HACK_H) $(INCL)/lev.h
+$(O)objects.o: objects.c $(CONFIG_H) $(INCL)/obj.h $(INCL)/objclass.h \
+		$(INCL)/prop.h $(INCL)/skills.h $(INCL)/color.h
+$(O)objnam.o: objnam.c $(HACK_H)
+$(O)options.o: options.c $(CONFIG_H) $(INCL)/objclass.h $(INCL)/flag.h \
+		$(HACK_H) $(INCL)/tcap.h
+$(O)pager.o: pager.c $(HACK_H) $(INCL)/dlb.h
+$(O)pickup.o: pickup.c $(HACK_H)
+$(O)pline.o: pline.c $(HACK_H) $(INCL)/epri.h $(INCL)/edog.h
+$(O)polyself.o: polyself.c $(HACK_H)
+$(O)potion.o: potion.c $(HACK_H)
+$(O)pray.o: pray.c $(HACK_H) $(INCL)/epri.h
+$(O)priest.o: priest.c $(HACK_H) $(INCL)/mfndpos.h $(INCL)/eshk.h \
+		$(INCL)/epri.h $(INCL)/emin.h
+$(O)quest.o: quest.c $(HACK_H) $(INCL)/qtext.h
+$(O)questpgr.o: questpgr.c $(HACK_H) $(INCL)/dlb.h $(INCL)/qtext.h
+$(O)read.o: read.c $(HACK_H)
+$(O)rect.o: rect.c $(HACK_H)
+$(O)region.o: region.c $(HACK_H) $(INCL)/lev.h
+$(O)restore.o: restore.c $(HACK_H) $(INCL)/lev.h $(INCL)/tcap.h
+$(O)rip.o: rip.c $(HACK_H)
+$(O)rnd.o: rnd.c $(HACK_H)
+$(O)role.o: role.c $(HACK_H)
+$(O)rumors.o: rumors.c $(HACK_H) $(INCL)/lev.h $(INCL)/dlb.h
+$(O)save.o: save.c $(HACK_H) $(INCL)/lev.h
+$(O)shk.o: shk.c $(HACK_H) $(INCL)/eshk.h
+$(O)shknam.o: shknam.c $(HACK_H) $(INCL)/eshk.h
+$(O)sit.o: sit.c $(HACK_H) $(INCL)/artifact.h
+$(O)sounds.o: sounds.c $(HACK_H) $(INCL)/edog.h
+$(O)sp_lev.o: sp_lev.c $(HACK_H) $(INCL)/dlb.h $(INCL)/sp_lev.h
+$(O)spell.o: spell.c $(HACK_H)
+$(O)steal.o: steal.c $(HACK_H)
+$(O)steed.o: steed.c $(HACK_H)
+$(O)teleport.o: teleport.c $(HACK_H)
+$(O)timeout.o: timeout.c $(HACK_H) $(INCL)/lev.h
+$(O)topten.o: topten.c $(HACK_H) $(INCL)/dlb.h $(INCL)/patchlevel.h
+$(O)track.o: track.c $(HACK_H)
+$(O)trap.o: trap.c $(HACK_H)
+$(O)u_init.o: u_init.c $(HACK_H)
+$(O)uhitm.o: uhitm.c $(HACK_H)
+$(O)vault.o: vault.c $(HACK_H) $(INCL)/vault.h
+$(O)version.o: version.c $(HACK_H) $(INCL)/date.h $(INCL)/patchlevel.h
+$(O)vision.o: vision.c $(HACK_H) $(INCL)/vis_tab.h
+$(O)weapon.o: weapon.c $(HACK_H)
+$(O)were.o: were.c $(HACK_H)
+$(O)wield.o: wield.c $(HACK_H)
+$(O)windows.o: windows.c $(HACK_H) $(INCL)/wingem.h $(INCL)/winGnome.h
+$(O)wizard.o: wizard.c $(HACK_H) $(INCL)/qtext.h $(INCL)/epri.h
+$(O)worm.o: worm.c $(HACK_H) $(INCL)/lev.h
+$(O)worn.o: worn.c $(HACK_H)
+$(O)write.o: write.c $(HACK_H)
+$(O)zap.o: zap.c $(HACK_H)
+
+# end of file
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/sys/winnt/cursmake.gcc.rej nethack/sys/winnt/cursmake.gcc.rej
--- nh_orig/sys/winnt/cursmake.gcc.rej	1969-12-31 19:00:00.000000000 -0500
+++ nethack/sys/winnt/cursmake.gcc.rej	2009-09-05 11:10:55.956417595 -0400
@@ -0,0 +1,1360 @@
+***************
+*** 0 ****
+--- 1,1357 ----
++ #   SCCS Id: @(#)Makefile.gcc       3.4     $Date: 2003/11/16 04:50:57 $
++ #   Copyright (c) NetHack PC Development Team 1993-2003
++ #
++ #   NetHack 3.4.x Makefile for MinGW
++ #
++ #   Win32 Compilers Tested:
++ #                  - MinGW 1.0 (gcc version 2.95.3-6) (Console NetHack only)
++ #                  - MinGW 2.0 (gcc version 3.2)
++ #
++ #   If you don't have this compiler, you can get it at:
++ #       http://www.mingw.org/
++ #
++ #   This is used for building two versions of NetHack:
++ #   A tty port utilizing the Win32 Console I/O subsystem, Console
++ #       NetHack;
++ #   A Win32 native port built on the Windows API, Graphical NetHack or
++ #       NetHackW.
++ #
++ #   In addition to your C compiler,
++ #
++ #     if you want to change     you will need a
++ #     files with suffix         workalike for
++ #         .y                     yacc   (such as bison)
++ #         .l                     lex    (such as flex)
++ #
++ #
++ #   If you have any questions read the sys/winnt/Install.nt file included
++ #   with the distribution.
++ #
++ #   --
++ #   Dion Nicolaas
++ #==============================================================================
++ # Graphical interface
++ # Set to Y for a graphical version
++ # Set to anything else (or undefine) for a tty version
++ 
++ GRAPHICAL = N
++ 
++ # Debug
++ # Set to Y for Debug support (to produce debug information)
++ # Set to anything else (or undefine) for a "release" version
++ # You can set your debug options below.
++ 
++ DEBUG = Y
++ 
++ cc     = gcc
++ rc     = windres
++ link   = gcc
++ 
++ cflags = -mms-bitfields
++ lflags  = 
++ ifeq  "$(DEBUG)" "Y"
++ cdebug = -g
++ linkdebug = -g
++ else
++ cdebug =
++ linkdebug =
++ endif
++ 
++ #
++ #  Set the gamedir according to your preference.
++ #  If not present prior to compilation it gets created.
++ 
++ ifeq  "$(GRAPHICAL)" "Y"
++ # Game Name
++ GAME    = NetHackW
++ else
++ # Game Name
++ GAME    = NetHackC
++ endif
++ # Game directory
++ GAMEDIR = ../binary
++ 
++ #
++ #  Source directories.    Makedefs hardcodes these, don't change them.
++ #
++ 
++ # NetHack include files
++ INCL  = ../include
++ # NetHack data files
++ DAT   = ../dat
++ # NetHack documentation files
++ DOC   = ../doc
++ # Utility source
++ UTIL  = ../util
++ # Main source
++ SRC   = ../src
++ # Shared system files
++ SSYS  = ../sys/share
++ # NT Win32 specific files
++ NTSYS = ../sys/winnt
++ # window port files (tty)
++ #TTY   = ../win/tty
++ TTY   = ../win/curses
++ # window port files (Win32)
++ WIN32 = ../win/win32
++ # Tile support files
++ WSHR  = ../win/share
++ 
++ #
++ #  Object directory.
++ #
++ 
++ OBJ = o
++ 
++ 
++ #
++ #==========================================
++ # Exe File Info.
++ #==========================================
++ 
++ # Yacc/Lex ... if you got 'em.
++ #
++ # If you have yacc and lex programs (or work-alike such as bison
++ # and flex), comment out the upper two macros and uncomment
++ # the lower two.
++ #
++ 
++ DO_YACC = YACC_MSG
++ DO_LEX  = LEX_MSG
++ #DO_YACC  = YACC_ACT
++ #DO_LEX   = LEX_ACT
++ 
++ # - Specify your yacc and lex programs (or work-alikes) here.
++ 
++ #YACC   = bison -y
++ YACC   = byacc
++ #YACC   = yacc
++ 
++ #LEX    = lex
++ LEX     = flex
++ 
++ #
++ # - Specify your flex skeleton file (if needed).
++ #
++ 
++ FLEXSKEL =
++ #FLEXSKEL = -S../tools/flex.ske
++ 
++ YTABC   = y_tab.c
++ YTABH   = y_tab.h
++ LEXYYC  = lexyy.c
++ 
++ #
++ # Optional high-quality BSD random number generation routines
++ # (see pcconf.h). Set to nothing if not used.
++ #
++ 
++ RANDOM  = $(OBJ)/random.o
++ #RANDOM =
++ 
++ #===============================================
++ #======= End of Modification Section ===========
++ #===============================================
++ ################################################
++ #                                              #
++ # Nothing below here should have to be changed.#
++ #                                              #
++ ################################################
++ 
++ ifeq  "$(GRAPHICAL)" "Y"
++ WINPORT  = $(O)tile.o $(O)mhaskyn.o $(O)mhdlg.o \
++ 	$(O)mhfont.o $(O)mhinput.o $(O)mhmain.o $(O)mhmap.o \
++ 	$(O)mhmenu.o $(O)mhmsgwnd.o $(O)mhrip.o $(O)mhsplash.o \
++ 	$(O)mhstatus.o $(O)mhtext.o $(O)mswproc.o $(O)winhack.o
++ WINPFLAG   = -DTILES -DMSWIN_GRAPHICS -D_WIN32_IE=0x0400
++ NHRES   = $(O)winres.o
++ WINPINC = -I$(WIN32)
++ WINPHDR = $(WIN32)/mhaskyn.h $(WIN32)/mhdlg.h $(WIN32)/mhfont.h \
++ 	$(WIN32)/mhinput.h $(WIN32)/mhmain.h $(WIN32)/mhmap.h \
++ 	$(WIN32)/mhmenu.h $(WIN32)/mhmsg.h $(WIN32)/mhmsgwnd.h \
++ 	$(WIN32)/mhrip.h $(WIN32)/mhstatus.h \
++ 	$(WIN32)/mhtext.h $(WIN32)/resource.h $(WIN32)/winMS.h
++ WINPLIBS =  -lcomctl32 -lwinmm
++ else
++ WINPORT = $(O)nttty.o
++ #WINPFLAG= -DWIN32CON
++ WINPHDR =
++ NHRES   = $(O)console.o
++ WINPINC =
++ #WINPLIBS = ../lib/pdcurses.a -lwinmm
++ WINPLIBS = ../lib/libpdcurses.a ../lib/libSDL.a -lwinmm
++ endif
++ 
++ TILEUTIL16  = $(UTIL)/tile2bmp.exe
++ TILEBMP16   = $(SRC)/tiles.bmp
++ 
++ TILEUTIL32  = $(UTIL)/til2bm32.exe
++ TILEBMP32   = $(SRC)/tiles32.bmp
++ 
++ SOUND = $(OBJ)/ntsound.o
++ 
++ #SOUND =
++ 
++ # To store all the level files,
++ # help files, etc. in a single library file.
++ # USE_DLB = Y is left uncommented
++ 
++ USE_DLB = Y
++ 
++ ifeq  "$(USE_DLB)" "Y"
++ DLBFLG = -DDLB
++ else
++ DLBFLG =
++ endif
++ 
++ #==========================================
++ # Setting up the compiler and linker
++ # macros. All builds include the base ones.
++ #==========================================
++ 
++ CFLAGSBASE  = -c $(cflags) -I$(INCL) $(WINPINC) $(cdebug)
++ LFLAGSBASEC = $(linkdebug) -mwindows
++ LFLAGSBASEG = $(linkdebug) -mwindows
++ 
++ #==========================================
++ # Util builds
++ #==========================================
++ 
++ CFLAGSU = $(CFLAGSBASE) $(WINPFLAG)
++ LFLAGSU = $(LFLAGSBASEC)
++ 
++ #==========================================
++ # - Game build
++ #==========================================
++ 
++ CFLAGS   = $(CFLAGSBASE) $(WINPFLAG) $(DLBFLG)
++ lflags  = $(LFLAGSBASE)
++ ifeq "$(GRAPHICAL)" "Y"
++ lflags  = $(LFLAGSBASEG)
++ else
++ lflags  = $(LFLAGSBASEC)
++ endif
++ 
++ GAMEFILE = $(GAMEDIR)/$(GAME).exe # whole thing
++ 
++ ifeq  "$(USE_DLB)" "Y"
++ DLB = nhdat
++ else
++ DLB =
++ endif
++ 
++ #==========================================
++ #================ RULES ==================
++ #==========================================
++ 
++ .SUFFIXES: .exe .o .til .uu .c .y .l
++ 
++ #==========================================
++ # Rules for files in src
++ #==========================================
++ 
++ $(OBJ)/%.o : /%.c
++ 	$(cc) $(CFLAGS)  -o$@ $<
++ 
++ $(OBJ)/%.o : $(SRC)/%.c
++ 	$(cc) $(CFLAGS)   -o$@  $<
++ 
++ #==========================================
++ # Rules for files in sys/share
++ #==========================================
++ 
++ $(OBJ)/%.o : $(SSYS)/%.c
++ 	$(cc) $(CFLAGS)  -o$@  $<
++ 
++ #==========================================
++ # Rules for files in sys/winnt
++ #==========================================
++ 
++ $(OBJ)/%.o : $(NTSYS)/%.c
++ 	$(cc) $(CFLAGS)  -o$@  $<
++ 
++ $(INCL)/%.h : $(NTSYS)/%.h
++ 	@copy $< $@
++ 
++ #==========================================
++ # Rules for files in util
++ #==========================================
++ 
++ $(OBJ)/%.o : $(UTIL)/%.c
++ 	$(cc) $(CFLAGSU) -o$@ $<
++ 
++ #==========================================
++ # Rules for files in win/share
++ #==========================================
++ 
++ $(OBJ)/%.o : $(WSHR)/%.c
++ 	$(cc) $(CFLAGS)  -o$@ $<
++ 
++ $(INCL)/%.h : $(WSHR)/%.h
++ 	@copy $< $@
++ 
++ #{$(WSHR)}.txt{$(DAT)}.txt:
++ #	@copy $< $@
++ 
++ #==========================================
++ # Rules for files in win/tty
++ #==========================================
++ 
++ $(OBJ)/%.o : $(TTY)/%.c
++ 	$(cc) $(CFLAGS)  -o$@  $<
++ 
++ #==========================================
++ # Rules for files in win/win32
++ #==========================================
++ 
++ $(OBJ)/%.o : $(WIN32)/%.c
++ 	$(cc) $(CFLAGS)  -o$@  $<
++ 
++ #==========================================
++ #================ MACROS ==================
++ #==========================================
++ # This section creates shorthand macros for many objects
++ # referenced later on in the Makefile.
++ #
++ 
++ DEFFILE = $(NTSYS)/$(GAME).def
++ 
++ #
++ # Shorten up the location for some files
++ #
++ 
++ O  = $(OBJ)/
++ 
++ U  = $(UTIL)/
++ 
++ #
++ # Utility Objects.
++ #
++ 
++ MAKESRC        = $(U)makedefs.c
++ 
++ SPLEVSRC       = $(U)lev_yacc.c  $(U)lev_$(LEX).c $(U)lev_main.c  $(U)panic.c
++ 
++ DGNCOMPSRC     = $(U)dgn_yacc.c  $(U)dgn_$(LEX).c $(U)dgn_main.c
++ 
++ MAKEOBJS       = $(O)makedefs.o $(O)monst.o $(O)objects.o
++ 
++ SPLEVOBJS      = $(O)lev_yacc.o  $(O)lev_$(LEX).o $(O)lev_main.o \
++ 	$(O)alloc.o   $(O)decl.o      $(O)drawing.o \
++ 	$(O)monst.o   $(O)objects.o   $(O)panic.o
++ 
++ DGNCOMPOBJS    = $(O)dgn_yacc.o  $(O)dgn_$(LEX).o $(O)dgn_main.o \
++ 	$(O)alloc.o   $(O)panic.o
++ 
++ RECOVOBJS      = $(O)recover.o
++ 
++ TILEFILES      = $(WSHR)/monsters.txt $(WSHR)/objects.txt $(WSHR)/other.txt
++ 
++ #
++ # These are not invoked during a normal game build in 3.4
++ #
++ TEXT_IO        = $(O)tiletext.o  $(O)tiletxt.o   $(O)drawing.o \
++ 	$(O)decl.o    $(O)monst.o     $(O)objects.o
++ 
++ TEXT_IO32      = $(O)tilete32.o $(O)tiletx32.o $(O)drawing.o \
++ 	$(O)decl.o    $(O)monst.o     $(O)objects.o
++ 
++ GIFREADERS     = $(O)gifread.o   $(O)alloc.o $(O)panic.o
++ GIFREADERS32   = $(O)gifrd32.o $(O)alloc.o $(O)panic.o
++ 
++ PPMWRITERS     = $(O)ppmwrite.o $(O)alloc.o $(O)panic.o
++ 
++ #
++ #  Object files for the game itself.
++ #
++ 
++ VOBJ01 = $(O)allmain.o  $(O)alloc.o    $(O)apply.o    $(O)artifact.o
++ VOBJ02 = $(O)attrib.o   $(O)ball.o     $(O)bones.o    $(O)botl.o
++ VOBJ03 = $(O)cmd.o      $(O)dbridge.o  $(O)decl.o     $(O)detect.o
++ VOBJ04 = $(O)dig.o      $(O)display.o  $(O)do.o       $(O)do_name.o
++ VOBJ05 = $(O)do_wear.o  $(O)dog.o      $(O)dogmove.o  $(O)dokick.o
++ VOBJ06 = $(O)dothrow.o  $(O)drawing.o  $(O)dungeon.o  $(O)eat.o
++ VOBJ07 = $(O)end.o      $(O)engrave.o  $(O)exper.o    $(O)explode.o
++ VOBJ08 = $(O)extralev.o $(O)files.o    $(O)fountain.o $(O)hack.o
++ VOBJ09 = $(O)hacklib.o  $(O)invent.o   $(O)light.o    $(O)lock.o
++ VOBJ10 = $(O)mail.o     $(O)makemon.o  $(O)mapglyph.o $(O)mcastu.o
++ VOBJ11 = $(O)mhitm.o    $(O)mhitu.o    $(O)minion.o   $(O)mklev.o
++ VOBJ12 = $(O)mkmap.o    $(O)mkmaze.o   $(O)mkobj.o    $(O)mkroom.o
++ VOBJ13 = $(O)mon.o      $(O)mondata.o  $(O)monmove.o  $(O)monst.o
++ VOBJ14 = $(O)monstr.o   $(O)mplayer.o  $(O)mthrowu.o  $(O)muse.o
++ VOBJ15 = $(O)music.o    $(O)o_init.o   $(O)objects.o  $(O)objnam.o
++ VOBJ16 = $(O)options.o  $(O)pager.o    $(O)pickup.o   $(O)pline.o
++ VOBJ17 = $(O)polyself.o $(O)potion.o   $(O)pray.o     $(O)priest.o
++ VOBJ18 = $(O)quest.o    $(O)questpgr.o $(RANDOM)      $(O)read.o
++ VOBJ19 = $(O)rect.o     $(O)region.o   $(O)restore.o  $(O)rip.o
++ VOBJ20 = $(O)rnd.o      $(O)role.o     $(O)rumors.o   $(O)save.o
++ VOBJ21 = $(O)shk.o      $(O)shknam.o   $(O)sit.o      $(O)sounds.o
++ VOBJ22 = $(O)sp_lev.o   $(O)spell.o    $(O)steal.o    $(O)steed.o
++ VOBJ23 = $(O)teleport.o $(O)timeout.o  $(O)topten.o   $(O)track.o
++ VOBJ24 = $(O)trap.o     $(O)u_init.o   $(O)uhitm.o    $(O)vault.o
++ VOBJ25 = $(O)vis_tab.o  $(O)vision.o   $(O)weapon.o   $(O)were.o
++ VOBJ26 = $(O)wield.o    $(O)windows.o  $(O)wizard.o   $(O)worm.o
++ VOBJ27 = $(O)worn.o     $(O)write.o    $(O)zap.o
++ 
++ DLBOBJ = $(O)dlb.o
++ 
++ #TTYOBJ = $(O)topl.o     $(O)getline.o  $(O)wintty.o
++ TTYOBJ = $(O)cursmain.o $(O)curswins.o  $(O)cursmisc.o $(O)cursdial.o \
++ 	$(O)cursstat.o $(O)cursinit.o $(O)cursmesg.o 
++ 
++ SOBJ   = $(O)winnt.o    $(O)pcsys.o      $(O)pcunix.o  \
++ 	$(SOUND) $(O)pcmain.o $(O)mapimail.o $(O)nhlan.o
++ 
++ OBJS   = $(VOBJ01) $(VOBJ02) $(VOBJ03) $(VOBJ04) $(VOBJ05) \
++ 	$(VOBJ06) $(VOBJ07) $(VOBJ08) $(VOBJ09) $(VOBJ10) \
++ 	$(VOBJ11) $(VOBJ12) $(VOBJ13) $(VOBJ14) $(VOBJ15) \
++ 	$(VOBJ16) $(VOBJ17) $(VOBJ18) $(VOBJ19) $(VOBJ20) \
++ 	$(VOBJ21) $(VOBJ22) $(VOBJ23) $(VOBJ24) $(VOBJ25) \
++ 	$(VOBJ26) $(VOBJ27)
++ 
++ WINPOBJ = $(WINPORT)
++ 
++ VVOBJ  = $(O)version.o
++ 
++ ALLOBJ  = $(WINPOBJ) $(SOBJ) $(DLBOBJ)  $(TTYOBJ) $(WOBJ) $(OBJS) $(VVOBJ)
++ 
++ ifeq "$(GRAPHICAL)" "Y"
++ OPTIONS_FILE = $(DAT)/guioptions
++ else
++ OPTIONS_FILE = $(DAT)/ttyoptions
++ endif
++ 
++ #==========================================
++ # Header file macros
++ #==========================================
++ 
++ CONFIG_H = $(INCL)/config.h $(INCL)/config1.h $(INCL)/tradstdc.h \
++ 	       $(INCL)/global.h $(INCL)/coord.h $(INCL)/vmsconf.h \
++ 	       $(INCL)/system.h $(INCL)/unixconf.h $(INCL)/os2conf.h \
++ 	       $(INCL)/micro.h $(INCL)/pcconf.h $(INCL)/tosconf.h \
++ 	       $(INCL)/amiconf.h $(INCL)/macconf.h $(INCL)/beconf.h \
++ 	       $(INCL)/ntconf.h $(INCL)/nhlan.h
++ 
++ HACK_H = $(INCL)/hack.h $(CONFIG_H) $(INCL)/align.h \
++ 	       $(INCL)/dungeon.h $(INCL)/monsym.h $(INCL)/mkroom.h \
++ 	       $(INCL)/objclass.h $(INCL)/youprop.h $(INCL)/prop.h \
++ 	       $(INCL)/permonst.h $(INCL)/monattk.h \
++ 	       $(INCL)/monflag.h $(INCL)/mondata.h $(INCL)/pm.h \
++ 	       $(INCL)/wintype.h $(INCL)/decl.h $(INCL)/quest.h \
++ 	       $(INCL)/spell.h $(INCL)/color.h $(INCL)/obj.h \
++ 	       $(INCL)/you.h $(INCL)/attrib.h $(INCL)/monst.h \
++ 	       $(INCL)/skills.h $(INCL)/onames.h $(INCL)/timeout.h \
++ 	       $(INCL)/trap.h $(INCL)/flag.h $(INCL)/rm.h \
++ 	       $(INCL)/vision.h $(INCL)/display.h $(INCL)/engrave.h \
++ 	       $(INCL)/rect.h $(INCL)/region.h $(INCL)/winprocs.h \
++ 	       $(INCL)/wintty.h $(INCL)/trampoli.h
++ 
++ LEV_H       = $(INCL)/lev.h
++ DGN_FILE_H  = $(INCL)/dgn_file.h
++ LEV_COMP_H  = $(INCL)/lev_comp.h
++ SP_LEV_H    = $(INCL)/sp_lev.h
++ TILE_H      = ../win/share/tile.h
++ 
++ #==========================================
++ # Miscellaneous
++ #==========================================
++ 
++ DATABASE = $(DAT)/data.base
++ 
++ #
++ #  The name of the game.
++ #
++ 
++ GAMEFILE = $(GAMEDIR)/$(GAME).exe
++ 
++ 
++ #==========================================
++ #=============== TARGETS ==================
++ #==========================================
++ 
++ # Since DOS doesn't allow / as path separator, and GCC doesn't allow \ as
++ # path separator, we must change all pathnames when performing DOS commands.
++ # This is done by blindly applying $(subst /,\, ...) on every command.
++ # Where any command contain / for another reason (switch char, or echoing
++ # comment lines to lev/dungeon files) a little more care is taken.
++ 
++ #
++ #  The default make target (so just typing 'nmake' is useful).
++ #
++ default : $(GAMEFILE)
++ 
++ #
++ #  The main target.
++ #
++ 
++ $(GAME) : $(O)obj.tag $(O)utility.tag graphicschk $(GAMEFILE)
++ 	@echo $(GAME) is up to date.
++ 
++ #
++ #  Everything
++ #
++ 
++ all :   install
++ 
++ install: graphicschk $(GAME) $(O)install.tag
++ 	@echo Done.
++ 
++ 
++ $(O)install.tag:  $(DAT)/data    $(DAT)/rumors    $(DAT)/dungeon \
++ 	       $(DAT)/oracles $(DAT)/quest.dat $(O)sp_lev.tag $(DLB)
++ ifeq  "$(USE_DLB)" "Y"
++ 	$(subst /,\,copy nhdat                $(GAMEDIR))
++ 	$(subst /,\,copy $(DAT)/license       $(GAMEDIR))
++ 	$(subst /,\,copy $(DAT)/opthelp       $(GAMEDIR))
++ else
++ 	$(subst /,\,copy $(DAT)/*.            $(GAMEDIR))
++ 	$(subst /,\,copy $(DAT)/*.dat         $(GAMEDIR))
++ 	$(subst /,\,copy $(DAT)/*.lev         $(GAMEDIR))
++ 	$(subst /,\,if exist $(GAMEDIR)/makefile del $(GAMEDIR)/makefile)
++ endif
++ 	$(subst /,\,if exist $(DOC)/guidebook.txt copy $(DOC)/guidebook.txt $(GAMEDIR)/Guidebook.txt)
++ 	$(subst /,\,if exist $(DOC)/nethack.txt copy $(DOC)/nethack.txt $(GAMEDIR)/NetHack.txt)
++ 	$(subst /,\,copy $(NTSYS)/defaults.nh   $(GAMEDIR)/defaults.nh)
++ 	$(subst /,\,echo install done > $@)
++ 
++ #  copy $(NTSYS)/winnt.hlp    $(GAMEDIR)
++ 
++ recover: $(U)recover.exe
++ 	$(subst /,\,if exist $(U)recover.exe copy $(U)recover.exe  $(GAMEDIR))
++ 	$(subst /,\,if exist $(DOC)/recover.txt copy $(DOC)/recover.txt $(GAMEDIR)/recover.txt)
++ 
++ $(O)sp_lev.tag: $(O)utility.tag $(DAT)/bigroom.des  $(DAT)/castle.des \
++ 	 $(DAT)/endgame.des $(DAT)/gehennom.des $(DAT)/knox.des   \
++ 	 $(DAT)/medusa.des  $(DAT)/oracle.des   $(DAT)/tower.des  \
++ 	 $(DAT)/yendor.des  $(DAT)/arch.des     $(DAT)/barb.des   \
++ 	 $(DAT)/caveman.des $(DAT)/healer.des   $(DAT)/knight.des \
++ 	 $(DAT)/monk.des    $(DAT)/priest.des   $(DAT)/ranger.des \
++ 	 $(DAT)/rogue.des   $(DAT)/samurai.des  $(DAT)/sokoban.des \
++ 	 $(DAT)/tourist.des $(DAT)/valkyrie.des $(DAT)/wizard.des
++ 	$(subst /,\,$(U)lev_comp $(DAT)/bigroom.des)
++ 	$(subst /,\,$(U)lev_comp $(DAT)/castle.des)
++ 	$(subst /,\,$(U)lev_comp $(DAT)/endgame.des)
++ 	$(subst /,\,$(U)lev_comp $(DAT)/gehennom.des)
++ 	$(subst /,\,$(U)lev_comp $(DAT)/knox.des)
++ 	$(subst /,\,$(U)lev_comp $(DAT)/mines.des)
++ 	$(subst /,\,$(U)lev_comp $(DAT)/medusa.des)
++ 	$(subst /,\,$(U)lev_comp $(DAT)/oracle.des)
++ 	$(subst /,\,$(U)lev_comp $(DAT)/sokoban.des)
++ 	$(subst /,\,$(U)lev_comp $(DAT)/tower.des)
++ 	$(subst /,\,$(U)lev_comp $(DAT)/yendor.des)
++ 	$(subst /,\,$(U)lev_comp $(DAT)/arch.des)
++ 	$(subst /,\,$(U)lev_comp $(DAT)/barb.des)
++ 	$(subst /,\,$(U)lev_comp $(DAT)/caveman.des)
++ 	$(subst /,\,$(U)lev_comp $(DAT)/healer.des)
++ 	$(subst /,\,$(U)lev_comp $(DAT)/knight.des)
++ 	$(subst /,\,$(U)lev_comp $(DAT)/monk.des)
++ 	$(subst /,\,$(U)lev_comp $(DAT)/priest.des)
++ 	$(subst /,\,$(U)lev_comp $(DAT)/ranger.des)
++ 	$(subst /,\,$(U)lev_comp $(DAT)/rogue.des)
++ 	$(subst /,\,$(U)lev_comp $(DAT)/samurai.des)
++ 	$(subst /,\,$(U)lev_comp $(DAT)/tourist.des)
++ 	$(subst /,\,$(U)lev_comp $(DAT)/valkyrie.des)
++ 	$(subst /,\,$(U)lev_comp $(DAT)/wizard.des)
++ 	$(subst /,\,copy *.lev $(DAT))
++ 	$(subst /,\,del *.lev)
++ 	$(subst /,\,echo sp_levs done > $(O)sp_lev.tag)
++ 
++ $(O)utility.tag: $(INCL)/date.h $(INCL)/onames.h $(INCL)/pm.h \
++ 	 $(SRC)/monstr.c $(SRC)/vis_tab.c $(U)lev_comp.exe $(INCL)/vis_tab.h \
++ 	 $(U)dgn_comp.exe $(TILEUTIL16)
++ 	$(subst /,\,@echo utilities made >$@)
++ 	@echo utilities made.
++ 
++ tileutil: $(U)gif2txt.exe $(U)gif2tx32.exe $(U)txt2ppm.exe
++ 	@echo Optional tile development utilities are up to date.
++ 
++ ifeq  "$(GRAPHICAL)" "Y"
++ $(NHRES): $(TILEBMP16) $(WIN32)/winhack.rc $(WIN32)/mnsel.bmp \
++ 	 $(WIN32)/mnselcnt.bmp $(WIN32)/mnunsel.bmp \
++ 	 $(WIN32)/petmark.bmp $(WIN32)/NetHack.ico $(WIN32)/rip.bmp \
++ 	 $(WIN32)/splash.bmp
++ 	@$(rc) -o$@ --include-dir $(WIN32) -i $(WIN32)/winhack.rc
++ else
++ $(NHRES): $(NTSYS)/console.rc $(NTSYS)/NetHack.ico 
++ 	@$(rc) -o$@ --include-dir $(NTSYS) -i $(NTSYS)/console.rc
++ endif
++ 
++ #==========================================
++ #  The main target.
++ #==========================================
++ $(O)gamedir.tag:
++ 	$(subst /,\,@if not exist $(GAMEDIR)/*.* echo creating directory $(GAMEDIR))
++ 	$(subst /,\,@if not exist $(GAMEDIR)/*.* mkdir $(GAMEDIR))
++ 	$(subst /,\,@echo directory created > $@)
++ 
++ ifeq  "$(GRAPHICAL)" "Y"
++ $(GAMEFILE) : $(ALLOBJ) $(NHRES) $(O)gamedir.tag
++ else
++ #$(GAMEFILE) : $(ALLOBJ) $(NHRES) $(O)gamedir.tag \
++ #	 $(GAMEDIR)/nhdefkey.dll $(GAMEDIR)/nh340key.dll $(GAMEDIR)/nhraykey.dll
++ $(GAMEFILE) : $(ALLOBJ) $(NHRES) $(O)gamedir.tag
++ endif
++ 	@echo Linking....
++ 	$(link) $(lflags) -o$@ $(ALLOBJ) $(NHRES) $(WINPLIBS)
++ 	$(subst /,\,@if exist $(O)install.tag del $(O)install.tag)
++ 
++ 
++ $(O)nhdefkey.o:
++ 	$(cc) $(CFLAGS) -DBUILD_DLL -o$@ $(NTSYS)/nhdefkey.c 
++ 
++ $(GAMEDIR)/nhdefkey.dll : $(O)nhdefkey.o $(O)gamedir.tag
++ 	@echo Linking $@
++ 	$(cc) -shared -Wl,--export-all-symbols \
++ 		-Wl,--add-stdcall-alias -o $@ $<
++ 
++ $(O)nh340key.o:
++ 	$(cc) $(CFLAGS) -DBUILD_DLL -o$@ $(NTSYS)/nh340key.c 
++ 
++ $(GAMEDIR)/nh340key.dll : $(O)nh340key.o $(O)gamedir.tag
++ 	@echo Linking $@
++ 	$(cc) -shared -Wl,--export-all-symbols \
++ 		-Wl,--add-stdcall-alias -o $@ $<
++ 
++ $(O)nhraykey.o:
++ 		$(cc) $(CFLAGS) -DBUILD_DLL -o$@ $(NTSYS)/nhraykey.c 
++ 
++ $(GAMEDIR)/nhraykey.dll : $(O)nhraykey.o $(O)gamedir.tag
++ 	@echo Linking $@
++ 	$(cc) -shared -Wl,--export-all-symbols \
++ 		-Wl,--add-stdcall-alias -o $@ $<
++ 
++ $(GAME)_.ico : $(NTSYS)/$(GAME).ico
++ 	$(subst /,\,@copy $(NTSYS)/$(GAME).ico $@)
++ 
++ #==========================================
++ # Create directory for holding object files
++ #==========================================
++ 
++ graphicschk:
++ ifeq  "$(GRAPHICAL)" "Y"
++ 	@echo ----
++ 	@echo NOTE: This build will include tile support.
++ 	@echo ----
++ endif
++ 	$(subst /,\,@echo graphicschk > graphicschk)
++ 
++ #
++ #  Secondary Targets.
++ #
++ 
++ #==========================================
++ # Makedefs Stuff
++ #==========================================
++ 
++ $(U)makedefs.exe: $(MAKEOBJS)
++ 	@$(link) $(LFLAGSU) -o$@ $(MAKEOBJS)
++ 
++ $(O)makedefs.o: $(CONFIG_H) $(INCL)/monattk.h $(INCL)/monflag.h \
++ 	 $(INCL)/objclass.h $(INCL)/monsym.h $(INCL)/qtext.h \
++ 	 $(INCL)/patchlevel.h $(U)makedefs.c $(O)obj.tag
++ 	$(cc) $(CFLAGSU) -o$@ $(U)makedefs.c
++ 
++ #
++ #  date.h should be remade every time any of the source or include
++ #  files is modified.
++ #
++ 
++ $(INCL)/date.h $(OPTIONS_FILE): $(U)makedefs.exe
++ 	$(subst /,\,$(U)makedefs -v)
++ 
++ #$(OPTIONS_FILE): $(U)makedefs.exe
++ #	$(subst /,\,$(U)makedefs -v)
++ 
++ $(INCL)/onames.h : $(U)makedefs.exe
++ 	$(subst /,\,$(U)makedefs -o)
++ 
++ $(INCL)/pm.h : $(U)makedefs.exe
++ 	$(subst /,\,$(U)makedefs -p)
++ 
++ #$(INCL)/trap.h : $(U)makedefs.exe
++ #  $(U)makedefs -t
++ 
++ $(SRC)/monstr.c: $(U)makedefs.exe
++ 	$(subst /,\,$(U)makedefs -m)
++ 
++ $(INCL)/vis_tab.h: $(U)makedefs.exe
++ 	$(subst /,\,$(U)makedefs -z)
++ 
++ $(SRC)/vis_tab.c: $(U)makedefs.exe
++ 	$(subst /,\,$(U)makedefs -z)
++ 
++ #==========================================
++ # uudecode utility and uuencoded targets
++ #==========================================
++ 
++ $(U)uudecode.exe: $(O)uudecode.o
++ 	@$(link) $(LFLAGSU) -o$@ $(O)uudecode.o
++ 
++ $(O)uudecode.o: $(SSYS)/uudecode.c
++ 
++ $(NTSYS)/NetHack.ico : $(U)uudecode.exe $(NTSYS)/nhico.uu
++ 	$(subst /,\,$(U)uudecode.exe $(NTSYS)/nhico.uu)
++ 	$(subst /,\,copy NetHack.ico $@)
++ 	del NetHack.ico
++ 
++ $(WIN32)/NetHack.ico : $(NTSYS)/NetHack.ico
++ 	$(subst /,\,copy $< $@)
++ 
++ $(WIN32)/mnsel.bmp: $(U)uudecode.exe $(WIN32)/mnsel.uu
++ 	$(subst /,\,$(U)uudecode.exe $(WIN32)/mnsel.uu)
++ 	$(subst /,\,copy mnsel.bmp $@)
++ 	del mnsel.bmp
++ 
++ $(WIN32)/mnselcnt.bmp: $(U)uudecode.exe $(WIN32)/mnselcnt.uu
++ 	$(subst /,\,$(U)uudecode.exe $(WIN32)/mnselcnt.uu)
++ 	$(subst /,\,copy mnselcnt.bmp $@)
++ 	del mnselcnt.bmp
++ 
++ $(WIN32)/mnunsel.bmp: $(U)uudecode.exe $(WIN32)/mnunsel.uu
++ 	$(subst /,\,$(U)uudecode.exe $(WIN32)/mnunsel.uu)
++ 	$(subst /,\,copy mnunsel.bmp $@)
++ 	del mnunsel.bmp
++ 
++ $(WIN32)/petmark.bmp: $(U)uudecode.exe $(WIN32)/petmark.uu
++ 	$(subst /,\,$(U)uudecode.exe $(WIN32)/petmark.uu)
++ 	$(subst /,\,copy petmark.bmp $@)
++ 	del petmark.bmp
++ 
++ $(WIN32)/rip.bmp: $(U)uudecode.exe $(WIN32)/rip.uu
++ 	$(subst /,\,$(U)uudecode.exe $(WIN32)/rip.uu)
++ 	$(subst /,\,copy rip.bmp $@)
++ 	del rip.bmp
++ 
++ $(WIN32)/splash.bmp: $(U)uudecode.exe $(WIN32)/splash.uu
++ 	$(subst /,\,$(U)uudecode.exe $(WIN32)/splash.uu)
++ 	$(subst /,\,copy splash.bmp $@)
++ 	del splash.bmp
++ 
++ 
++ #==========================================
++ # Level Compiler Stuff
++ #==========================================
++ 
++ LEVCFLAGS=$(cflags) -c -DWIN32 -D_WIN32 -I../include $(cdebug) -DDLB
++ 
++ $(U)lev_comp.exe: $(SPLEVOBJS)
++ 	@echo Linking $@...
++ 	@$(link) $(LFLAGSU) -o$@ $(SPLEVOBJS)
++ 
++ $(O)lev_yacc.o: $(HACK_H)   $(SP_LEV_H) $(INCL)/lev_comp.h $(U)lev_yacc.c
++ 	$(cc) $(LEVCFLAGS) -o$@ $(U)lev_yacc.c
++ 
++ $(O)lev_$(LEX).o: $(HACK_H)   $(INCL)/lev_comp.h $(SP_LEV_H) \
++ 	$(U)lev_$(LEX).c
++ 	$(cc) $(LEVCFLAGS) -o$@ $(U)lev_$(LEX).c
++ 
++ $(O)lev_main.o:   $(U)lev_main.c $(HACK_H)   $(SP_LEV_H)
++ 	$(cc) $(LEVCFLAGS) -o$@ $(U)lev_main.c
++ 
++ 
++ $(U)lev_yacc.c $(INCL)/lev_comp.h : $(U)lev_comp.y
++ ifeq  "$(DO_YACC)" "YACC_ACT"
++ 	$(subst /,\,$(YACC) -d $(U)lev_comp.y)
++ 	$(subst /,\,copy $(YTABC) $(U)lev_yacc.c)
++ 	$(subst /,\,copy $(YTABH) $(INCL)/lev_comp.h)
++ 	$(subst /,\,@del $(YTABC))
++ 	$(subst /,\,@del $(YTABH))
++ 
++ else
++ 	@echo $(U)lev_comp.y has changed.
++ 	@echo To update $(U)lev_yacc.c and $(INCL)/lev_comp.h run $(YACC).
++ 	@echo ---
++ 	@echo For now, we will copy the prebuilt lev_yacc.c and
++ 	@echo lev_comp.h from $(SSYS) into $(UTIL) and use them.
++ 	$(subst /,\,@copy $(SSYS)/lev_yacc.c $(U)lev_yacc.c >nul)
++ 	$(subst /,\,@copy $(SSYS)/lev_comp.h $(INCL)/lev_comp.h >nul)
++ 	$(subst /,\,echo.>>$(U)lev_yacc.c)
++ 	$(subst /,\,echo.>>$(INCL)/lev_comp.h)
++ endif
++ 
++ $(U)lev_$(LEX).c: $(U)lev_comp.l
++ ifeq  "$(DO_LEX)" "LEX_ACT"
++ 	$(subst /,\,$(LEX) $(FLEXSKEL) $(U)lev_comp.l)
++ 	$(subst /,\,copy $(LEXYYC) $@)
++ 	$(subst /,\,@del $(LEXYYC))
++ else
++ 	@echo $(U)lev_comp.l has changed. To update $@ run $(LEX).
++ 	@echo ---
++ 	@echo For now, we will copy the prebuilt lev_lex.c
++ 	@echo from $(SSYS) into $(UTIL) and use it.
++ 	$(subst /,\,@copy $(SSYS)/lev_lex.c $@ >nul)
++ 	$(subst /,\,echo.>>$@)
++ endif
++ 
++ #==========================================
++ # Dungeon Compiler Stuff
++ #==========================================
++ 
++ $(U)dgn_comp.exe: $(DGNCOMPOBJS)
++ 	@echo Linking $@...
++ 	@$(link) $(LFLAGSU) -o$@ $(DGNCOMPOBJS)
++ 
++ 
++ $(O)dgn_yacc.o:   $(HACK_H)   $(DGN_FILE_H) $(INCL)/dgn_comp.h $(U)dgn_yacc.c
++ 	$(cc) $(LEVCFLAGS) -o$@ $(U)dgn_yacc.c
++ 
++ $(O)dgn_$(LEX).o: $(HACK_H)   $(DGN_FILE_H)  $(INCL)/dgn_comp.h \
++ 	 $(U)dgn_$(LEX).c
++ 	$(cc) $(LEVCFLAGS) -o$@ $(U)dgn_$(LEX).c
++ 
++ $(O)dgn_main.o:   $(HACK_H) $(U)dgn_main.c
++ 	$(cc) $(LEVCFLAGS) -o$@ $(U)dgn_main.c
++ 
++ $(U)dgn_yacc.c $(INCL)/dgn_comp.h : $(U)dgn_comp.y
++ ifeq  "$(DO_YACC)" "YACC_ACT"
++ 	$(subst /,\,$(YACC) -d $(U)dgn_comp.y)
++ 	$(subst /,\,copy $(YTABC) $(U)dgn_yacc.c)
++ 	$(subst /,\,copy $(YTABH) $(INCL)/dgn_comp.h)
++ 	$(subst /,\,@del $(YTABC))
++ 	$(subst /,\,@del $(YTABH))
++ else
++ 	@echo $(U)dgn_comp.y has changed. To update dgn_yacc.c and
++ 	@echo $(INCL)/dgn_comp.h run $(YACC).
++ 	@echo ---
++ 	@echo For now, we will copy the prebuilt $(U)dgn_yacc.c and
++ 	@echo dgn_comp.h from $(SSYS) into $(UTIL) and use them.
++ 	$(subst /,\,@copy $(SSYS)/dgn_yacc.c $(U)dgn_yacc.c >nul)
++ 	$(subst /,\,@copy $(SSYS)/dgn_comp.h $(INCL)/dgn_comp.h >nul)
++ 	$(subst /,\,echo.>>$(U)dgn_yacc.c)
++ 	$(subst /,\,echo.>>$(INCL)/dgn_comp.h)
++ endif
++ 
++ $(U)dgn_$(LEX).c: $(U)dgn_comp.l
++ ifeq  "$(DO_LEX)" "LEX_ACT"
++ 	$(subst /,\,$(LEX) $(FLEXSKEL) $(U)dgn_comp.l)
++ 	$(subst /,\,copy $(LEXYYC) $@)
++ 	$(subst /,\,@del $(LEXYYC))
++ else
++ 	@echo $(U)dgn_comp.l has changed. To update $@ run $(LEX).
++ 	@echo ---
++ 	@echo For now, we will copy the prebuilt dgn_lex.c
++ 	@echo from $(SSYS) into $(UTIL) and use it.
++ 	$(subst /,\,@copy $(SSYS)/dgn_lex.c $@ >nul)
++ 	$(subst /,\,echo.>>$@)
++ endif
++ 
++ #==========================================
++ # Create directory for holding object files
++ #==========================================
++ 
++ $(O)obj.tag:
++ 	$(subst /,\,@if not exist $(OBJ)/*.* echo creating directory $(OBJ))
++ 	$(subst /,\,@if not exist $(OBJ)/*.* mkdir $(OBJ))
++ 	$(subst /,\,@echo directory created > $@)
++ 
++ 
++ #==========================================
++ #=========== SECONDARY TARGETS ============
++ #==========================================
++ 
++ #===========================================
++ # Header files NOT distributed in ../include
++ #===========================================
++ 
++ $(INCL)/win32api.h: $(NTSYS)/win32api.h
++ 	$(subst /,\,copy $(NTSYS)/win32api.h $@)
++ 
++ 
++ #==========================================
++ # DLB utility and nhdat file creation
++ #==========================================
++ 
++ $(U)dlb_main.exe: $(DLBOBJ) $(O)dlb.o
++ 	@$(link) $(LFLAGSU) -o$@ $(O)dlb_main.o $(O)dlb.o $(O)alloc.o $(O)panic.o
++ 
++ 
++ $(O)dlb.o:   $(O)dlb_main.o $(O)alloc.o $(O)panic.o $(INCL)/dlb.h
++ 	$(cc) $(CFLAGS) -o$@ $(SRC)/dlb.c
++ 
++ $(O)dlb_main.o: $(UTIL)/dlb_main.c $(INCL)/config.h $(INCL)/dlb.h
++ 	$(cc) $(CFLAGS) -o$@ $(UTIL)/dlb_main.c
++ 
++ $(DAT)/porthelp: $(NTSYS)/porthelp
++ 	$(subst /,\,@copy $(NTSYS)/porthelp $@ >nul)
++ 
++ nhdat:  $(U)dlb_main.exe $(DAT)/data $(DAT)/oracles $(OPTIONS_FILE) \
++ 	 $(DAT)/quest.dat $(DAT)/rumors $(DAT)/help $(DAT)/hh $(DAT)/cmdhelp \
++ 	 $(DAT)/history $(DAT)/opthelp $(DAT)/wizhelp $(DAT)/dungeon \
++ 	 $(DAT)/porthelp $(DAT)/license $(O)sp_lev.tag
++ 	$(subst /,\,echo data >$(DAT)/dlb.lst)
++ 	$(subst /,\,echo oracles >>$(DAT)/dlb.lst)
++ 	$(subst /,\,if exist $(DAT)/options echo options >>$(DAT)/dlb.lst)
++ 	$(subst /,\,if exist $(DAT)/ttyoptions echo ttyoptions >>$(DAT)/dlb.lst)
++ 	$(subst /,\,if exist $(DAT)/guioptions echo guioptions >>$(DAT)/dlb.lst)
++ 	$(subst /,\,if exist $(DAT)/porthelp echo porthelp >>$(DAT)/dlb.lst)
++ 	$(subst /,\,echo quest.dat >>$(DAT)/dlb.lst)
++ 	$(subst /,\,echo rumors >>$(DAT)/dlb.lst)
++ 	$(subst /,\,echo help >>$(DAT)/dlb.lst)
++ 	$(subst /,\,echo hh >>$(DAT)/dlb.lst)
++ 	$(subst /,\,echo cmdhelp >>$(DAT)/dlb.lst)
++ 	$(subst /,\,echo history >>$(DAT)/dlb.lst)
++ 	$(subst /,\,echo opthelp >>$(DAT)/dlb.lst)
++ 	$(subst /,\,echo wizhelp >>$(DAT)/dlb.lst)
++ 	$(subst /,\,echo dungeon >>$(DAT)/dlb.lst)
++ 	$(subst /,\,echo license >>$(DAT)/dlb.lst)
++ 	dir /l /b /-p $(subst /,\,$(DAT)/*.lev >>$(DAT)/dlb.lst)
++ 	$(subst /,\,$(U)dlb_main CcIf $(DAT) dlb.lst $(SRC)/nhdat)
++ 
++ #==========================================
++ #  Recover Utility
++ #==========================================
++ 
++ $(U)recover.exe: $(RECOVOBJS)
++ 	$(link) $(LFLAGSU) -o$@ $(RECOVOBJS)
++ 
++ $(O)recover.o: $(CONFIG_H) $(U)recover.c $(INCL)/win32api.h
++ 	$(cc) $(CFLAGSU) -o$@ $(U)recover.c
++ 
++ #==========================================
++ #  Tile Mapping
++ #==========================================
++ 
++ $(SRC)/tile.c: $(U)tilemap.exe
++ 	@echo A new $@ has been created
++ 	@$(U)tilemap
++ 
++ $(U)tilemap.exe: $(O)tilemap.o
++ 	@$(link) $(LFLAGSU) -o$@ $(O)tilemap.o
++ 
++ $(O)tilemap.o: $(WSHR)/tilemap.c $(HACK_H)
++ 	$(cc) $(CFLAGSU) -o$@ $(WSHR)/tilemap.c
++ 
++ $(O)tiletx32.o: $(WSHR)/tilemap.c $(HACK_H)
++ 	$(cc) $(CFLAGS) -DTILETEXT -DTILE_X=32 -DTILE_Y=32 -o$@ $(WSHR)/tilemap.c
++ 
++ $(O)tiletxt.o: $(WSHR)/tilemap.c $(HACK_H)
++ 	$(cc) $(CFLAGS) -DTILETEXT -o$@ $(WSHR)/tilemap.c
++ 
++ $(O)gifread.o: $(WSHR)/gifread.c  $(CONFIG_H) $(TILE_H)
++ 	$(cc) $(CFLAGS) -I$(WSHR) -o$@ $(WSHR)/gifread.c
++ 
++ $(O)gifrd32.o: $(WSHR)/gifread.c  $(CONFIG_H) $(TILE_H)
++ 	$(cc) $(CFLAGS) -I$(WSHR) -DTILE_X=32 -DTILE_Y=32 -o$@ $(WSHR)/gifread.c
++ 
++ $(O)ppmwrite.o: $(WSHR)/ppmwrite.c $(CONFIG_H) $(TILE_H)
++ 	$(cc) $(CFLAGS) -I$(WSHR) -o$@ $(WSHR)/ppmwrite.c
++ 
++ $(O)tiletext.o: $(WSHR)/tiletext.c  $(CONFIG_H) $(TILE_H)
++ 	$(cc) $(CFLAGS) -I$(WSHR) -o$@ $(WSHR)/tiletext.c
++ 
++ $(O)tilete32.o: $(WSHR)/tiletext.c  $(CONFIG_H) $(TILE_H)
++ 	$(cc) $(CFLAGS) -I$(WSHR) -DTILE_X=32 -DTILE_Y=32 -o$@ $(WSHR)/tiletext.c
++ 
++ #==========================================
++ # Optional Tile Utilities
++ #==========================================
++ 
++ $(U)gif2txt.exe: $(GIFREADERS) $(TEXT_IO)
++ 	@echo Linking $@...
++ 	@$(link) $(LFLAGSU) -o$@ $(GIFREADERS) $(TEXT_IO)
++ 
++ $(U)gif2tx32.exe: $(GIFREADERS32) $(TEXT_IO32)
++ 	@echo Linking $@...
++ 	@$(link) $(LFLAGSU) -o$@ $(GIFREADERS32) $(TEXT_IO32)
++ 
++ 
++ $(U)txt2ppm.exe: $(PPMWRITERS) $(TEXT_IO)
++ 	@echo Linking $@...
++ 	@$(link) $(LFLAGSU) -o$@ $(PPMWRITERS) $(TEXT_IO)
++ 
++ 
++ ifeq  "$(GRAPHICAL)" "Y"
++ $(TILEBMP16): $(TILEUTIL16) $(TILEFILES)
++ 	@echo Creating 16x16 binary tile files (this may take some time)
++ 	$(subst /,\,@$(U)tile2bmp $(TILEBMP16))
++ #$(TILEBMP32): $(TILEUTIL32) $(TILEFILES32)
++ #	@echo Creating 32x32 binary tile files (this may take some time)
++ #	$(subst /,\,@$(U)til2bm32 $(TILEBMP32))
++ else
++ $(TILEBMP16):
++ $(TILEBMP32):
++ endif
++ 
++ $(U)tile2bmp.exe: $(O)tile2bmp.o $(TEXT_IO)
++ 	@echo Linking $@...
++ 	@$(link) $(LFLAGSU) -o$@ $(O)tile2bmp.o $(TEXT_IO)
++ 
++ $(U)til2bm32.exe: $(O)til2bm32.o $(TEXT_IO32)
++ 	@echo Linking $@...
++ 	@$(link) $(LFLAGSU) -o$@ $(O)til2bm32.o $(TEXT_IO32)
++ 
++ $(O)tile2bmp.o: $(WSHR)/tile2bmp.c $(HACK_H) $(TILE_H) $(INCL)/win32api.h
++ 	$(cc) $(CFLAGS) -I$(WSHR) -o$@ $(WSHR)/tile2bmp.c
++ 
++ $(O)til2bm32.o: $(WSHR)/til2bm32.c $(HACK_H) $(TILE_H) $(INCL)/win32api.h
++ 	$(cc) $(CFLAGS) -I$(WSHR) -DTILE_X=32 -DTILE_Y=32 -o$@ $(WSHR)/til2bm32.c
++ 
++ #==========================================
++ # Housekeeping
++ #==========================================
++ 
++ spotless: clean
++ 	$(subst /,\,if exist graphicschk       del graphicschk)
++ 	$(subst /,\,if exist $(INCL)/date.h    del $(INCL)/date.h)
++ 	$(subst /,\,if exist $(INCL)/onames.h  del $(INCL)/onames.h)
++ 	$(subst /,\,if exist $(INCL)/pm.h      del $(INCL)/pm.h)
++ 	$(subst /,\,if exist $(INCL)/vis_tab.h del $(INCL)/vis_tab.h)
++ 	$(subst /,\,if exist $(SRC)/vis_tab.c  del $(SRC)/vis_tab.c)
++ 	$(subst /,\,if exist $(SRC)/tile.c     del $(SRC)/tile.c)
++ 	$(subst /,\,if exist $(U)*.lnk         del $(U)*.lnk)
++ 	$(subst /,\,if exist $(U)*.map         del $(U)*.map)
++ 	$(subst /,\,if exist $(DAT)/data       del $(DAT)/data)
++ 	$(subst /,\,if exist $(DAT)/rumors     del $(DAT)/rumors)
++ 	$(subst /,\,if exist $(DAT)/???-fil?.lev      del $(DAT)/???-fil?.lev)
++ 	$(subst /,\,if exist $(DAT)/???-goal.lev      del $(DAT)/???-goal.lev)
++ 	$(subst /,\,if exist $(DAT)/???-loca.lev      del $(DAT)/???-loca.lev)
++ 	$(subst /,\,if exist $(DAT)/???-strt.lev      del $(DAT)/???-strt.lev)
++ 	$(subst /,\,if exist $(DAT)/air.lev      del $(DAT)/air.lev)
++ 	$(subst /,\,if exist $(DAT)/asmodeus.lev      del $(DAT)/asmodeus.lev)
++ 	$(subst /,\,if exist $(DAT)/astral.lev   del $(DAT)/astral.lev)
++ 	$(subst /,\,if exist $(DAT)/baalz.lev    del $(DAT)/baalz.lev)
++ 	$(subst /,\,if exist $(DAT)/bigrm-*.lev  del $(DAT)/bigrm-*.lev)
++ 	$(subst /,\,if exist $(DAT)/castle.lev   del $(DAT)/castle.lev)
++ 	$(subst /,\,if exist $(DAT)/data    del $(DAT)/data)
++ 	$(subst /,\,if exist $(DAT)/dungeon      del $(DAT)/dungeon)
++ 	$(subst /,\,if exist $(DAT)/dungeon.pdf  del $(DAT)/dungeon.pdf)
++ 	$(subst /,\,if exist $(DAT)/earth.lev    del $(DAT)/earth.lev)
++ 	$(subst /,\,if exist $(DAT)/fakewiz?.lev      del $(DAT)/fakewiz?.lev)
++ 	$(subst /,\,if exist $(DAT)/fire.lev     del $(DAT)/fire.lev)
++ 	$(subst /,\,if exist $(DAT)/juiblex.lev  del $(DAT)/juiblex.lev)
++ 	$(subst /,\,if exist $(DAT)/knox.lev     del $(DAT)/knox.lev)
++ 	$(subst /,\,if exist $(DAT)/medusa-?.lev      del $(DAT)/medusa-?.lev)
++ 	$(subst /,\,if exist $(DAT)/mine*.lev    del $(DAT)/mine*.lev)
++ 	$(subst /,\,if exist $(DAT)/options      del $(DAT)/options)
++ 	$(subst /,\,if exist $(DAT)/ttyoptions   del $(DAT)/ttyoptions)
++ 	$(subst /,\,if exist $(DAT)/guioptions   del $(DAT)/guioptions)
++ 	$(subst /,\,if exist $(DAT)/oracle.lev   del $(DAT)/oracle.lev)
++ 	$(subst /,\,if exist $(DAT)/oracles      del $(DAT)/oracles)
++ 	$(subst /,\,if exist $(DAT)/orcus.lev    del $(DAT)/orcus.lev)
++ 	$(subst /,\,if exist $(DAT)/rumors  del $(DAT)/rumors)
++ 	$(subst /,\,if exist $(DAT)/quest.dat    del $(DAT)/quest.dat)
++ 	$(subst /,\,if exist $(DAT)/sanctum.lev  del $(DAT)/sanctum.lev)
++ 	$(subst /,\,if exist $(DAT)/soko?-?.lev  del $(DAT)/soko?-?.lev)
++ 	$(subst /,\,if exist $(DAT)/tower?.lev   del $(DAT)/tower?.lev)
++ 	$(subst /,\,if exist $(DAT)/valley.lev   del $(DAT)/valley.lev)
++ 	$(subst /,\,if exist $(DAT)/water.lev    del $(DAT)/water.lev)
++ 	$(subst /,\,if exist $(DAT)/wizard?.lev  del $(DAT)/wizard?.lev)
++ 	$(subst /,\,if exist $(O)sp_lev.tag     del $(O)sp_lev.tag)
++ 	$(subst /,\,if exist $(SRC)/monstr.c    del $(SRC)/monstr.c)
++ 	$(subst /,\,if exist $(SRC)/vis_tab.c   del $(SRC)/vis_tab.c)
++ 	$(subst /,\,if exist $(U)recover.exe    del $(U)recover.exe)
++ 	$(subst /,\,if exist $(DAT)/dlb.lst      del $(DAT)/dlb.lst)
++ 	$(subst /,\,if exist nhdat.         del nhdat.)
++ 	$(subst /,\,if exist $(O)install.tag    del $(O)install.tag)
++ 	$(subst /,\,if exist $(O)obj.tag    del $(O)obj.tag)
++ 	$(subst /,\,if exist $(O)gamedir.tag    del $(O)gamedir.tag)
++ ifneq "$(OBJ)" ""
++ 	$(subst /,\,rmdir $(OBJ)) /s /Q
++ endif
++ 
++ clean:
++ 	$(subst /,\,if exist $(O)*.o del $(O)*.o)
++ 	$(subst /,\,if exist $(O)utility.tag   del $(O)utility.tag)
++ 	$(subst /,\,if exist $(U)makedefs.exe  del $(U)makedefs.exe)
++ 	$(subst /,\,if exist $(U)lev_comp.exe  del $(U)lev_comp.exe)
++ 	$(subst /,\,if exist $(U)dgn_comp.exe  del $(U)dgn_comp.exe)
++ 	$(subst /,\,if exist $(SRC)/*.lnk      del $(SRC)/*.lnk)
++ 	$(subst /,\,if exist $(SRC)/*.map      del $(SRC)/*.map)
++ 	$(subst /,\,if exist $(TILEBMP16)      del $(TILEBMP16))
++ 	$(subst /,\,if exist $(TILEBMP32)      del $(TILEBMP32))
++ 
++ #===================================================================
++ # OTHER DEPENDENCIES
++ #===================================================================
++ 
++ #
++ # dat dependencies
++ #
++ 
++ $(DAT)/data: $(O)utility.tag    $(DATABASE)
++ 	$(subst /,\,$(U)makedefs -d)
++ 
++ $(DAT)/rumors: $(O)utility.tag    $(DAT)/rumors.tru   $(DAT)/rumors.fal
++ 	$(subst /,\,$(U)makedefs -r)
++ 
++ $(DAT)/quest.dat: $(O)utility.tag  $(DAT)/quest.txt
++ 	$(subst /,\,$(U)makedefs -q)
++ 
++ $(DAT)/oracles: $(O)utility.tag    $(DAT)/oracles.txt
++ 	$(subst /,\,$(U)makedefs -h)
++ 
++ $(DAT)/dungeon: $(O)utility.tag  $(DAT)/dungeon.def
++ 	$(subst /,\,$(U)makedefs -e)
++ 	$(subst /,\,$(U)dgn_comp $(DAT)/dungeon.pdf)
++ 
++ #
++ # NT dependencies
++ #
++ 
++ $(O)nttty.o:   $(HACK_H) $(TILE_H) $(INCL)/win32api.h $(NTSYS)/nttty.c
++ 	$(cc) $(CFLAGS) -I$(WSHR) -o$@  $(NTSYS)/nttty.c
++ $(O)winnt.o: $(HACK_H) $(INCL)/win32api.h $(NTSYS)/winnt.c
++ 	$(cc) $(CFLAGS) -o$@  $(NTSYS)/winnt.c
++ $(O)ntsound.o: $(HACK_H) $(NTSYS)/ntsound.c
++ 	$(cc) $(CFLAGS)  -o$@ $(NTSYS)/ntsound.c
++ $(O)mapimail.o: $(HACK_H) $(INCL)/nhlan.h $(NTSYS)/mapimail.c
++ 	$(cc) $(CFLAGS) -DMAPI_VERBOSE  -o$@ $(NTSYS)/mapimail.c
++ 
++ #
++ # util dependencies
++ #
++ 
++ $(O)panic.o:  $(U)panic.c $(CONFIG_H)
++ 	$(cc) $(CFLAGS) -o$@ $(U)panic.c
++ 
++ #
++ # The rest are stolen from sys/unix/Makefile.src,
++ # with the following changes:
++ #   * ../include changed to $(INCL)
++ #   * -c (which is included in CFLAGS) substituted
++ #	with -o$@
++ #   * targets prefixed with $(O)
++ #   * $(CC) changed to $(cc)
++ # but otherwise untouched. 
++ # That means that there is some irrelevant stuff
++ # in here, but maintenance should be easier.
++ #
++ $(O)tos.o: ../sys/atari/tos.c $(HACK_H) $(INCL)/tcap.h
++ 	$(cc) $(CFLAGS) -o$@ ../sys/atari/tos.c
++ $(O)pcmain.o: ../sys/share/pcmain.c $(HACK_H) $(INCL)/dlb.h \
++ 		$(INCL)/win32api.h
++ 	$(cc) $(CFLAGS) -o$@ ../sys/share/pcmain.c
++ $(O)pcsys.o: ../sys/share/pcsys.c $(HACK_H)
++ 	$(cc) $(CFLAGS) -o$@ ../sys/share/pcsys.c
++ $(O)pctty.o: ../sys/share/pctty.c $(HACK_H)
++ 	$(cc) $(CFLAGS) -o$@ ../sys/share/pctty.c
++ $(O)pcunix.o: ../sys/share/pcunix.c $(HACK_H)
++ 	$(cc) $(CFLAGS) -o$@ ../sys/share/pcunix.c
++ $(O)random.o: ../sys/share/random.c $(HACK_H)
++ 	$(cc) $(CFLAGS) -o$@ ../sys/share/random.c
++ $(O)ioctl.o: ../sys/share/ioctl.c $(HACK_H) $(INCL)/tcap.h
++ 	$(cc) $(CFLAGS) -o$@ ../sys/share/ioctl.c
++ $(O)unixtty.o: ../sys/share/unixtty.c $(HACK_H)
++ 	$(cc) $(CFLAGS) -o$@ ../sys/share/unixtty.c
++ $(O)unixmain.o: ../sys/unix/unixmain.c $(HACK_H) $(INCL)/dlb.h
++ 	$(cc) $(CFLAGS) -o$@ ../sys/unix/unixmain.c
++ $(O)unixunix.o: ../sys/unix/unixunix.c $(HACK_H)
++ 	$(cc) $(CFLAGS) -o$@ ../sys/unix/unixunix.c
++ $(O)unixres.o: ../sys/unix/unixres.c $(CONFIG_H)
++ 	$(cc) $(CFLAGS) -o$@ ../sys/unix/unixres.c
++ $(O)bemain.o: ../sys/be/bemain.c $(HACK_H) $(INCL)/dlb.h
++ 	$(cc) $(CFLAGS) -o$@ ../sys/be/bemain.c
++ $(O)getline.o: ../win/tty/getline.c $(HACK_H) $(INCL)/func_tab.h
++ 	$(cc) $(CFLAGS) -o$@ ../win/tty/getline.c
++ $(O)termcap.o: ../win/tty/termcap.c $(HACK_H) $(INCL)/tcap.h
++ 	$(cc) $(CFLAGS) -o$@ ../win/tty/termcap.c
++ $(O)topl.o: ../win/tty/topl.c $(HACK_H) $(INCL)/tcap.h
++ 	$(cc) $(CFLAGS) -o$@ ../win/tty/topl.c
++ $(O)wintty.o: ../win/tty/wintty.c $(HACK_H) $(INCL)/dlb.h \
++ 		$(INCL)/patchlevel.h $(INCL)/tcap.h
++ 	$(cc) $(CFLAGS) -o$@ ../win/tty/wintty.c
++ $(O)Window.o: ../win/X11/Window.c $(INCL)/xwindowp.h $(INCL)/xwindow.h \
++ 		$(CONFIG_H)
++ 	$(cc) $(CFLAGS) -o$@ ../win/X11/Window.c
++ $(O)dialogs.o: ../win/X11/dialogs.c $(CONFIG_H)
++ 	$(cc) $(CFLAGS) -o$@ ../win/X11/dialogs.c
++ $(O)winX.o: ../win/X11/winX.c $(HACK_H) $(INCL)/winX.h $(INCL)/dlb.h \
++ 		$(INCL)/patchlevel.h ../win/X11/nh72icon \
++ 		../win/X11/nh56icon ../win/X11/nh32icon
++ 	$(cc) $(CFLAGS) -o$@ ../win/X11/winX.c
++ $(O)winmap.o: ../win/X11/winmap.c $(INCL)/xwindow.h $(HACK_H) $(INCL)/dlb.h \
++ 		$(INCL)/winX.h $(INCL)/tile2x11.h
++ 	$(cc) $(CFLAGS) -o$@ ../win/X11/winmap.c
++ $(O)winmenu.o: ../win/X11/winmenu.c $(HACK_H) $(INCL)/winX.h
++ 	$(cc) $(CFLAGS) -o$@ ../win/X11/winmenu.c
++ $(O)winmesg.o: ../win/X11/winmesg.c $(INCL)/xwindow.h $(HACK_H) $(INCL)/winX.h
++ 	$(cc) $(CFLAGS) -o$@ ../win/X11/winmesg.c
++ $(O)winmisc.o: ../win/X11/winmisc.c $(HACK_H) $(INCL)/func_tab.h \
++ 		$(INCL)/winX.h
++ 	$(cc) $(CFLAGS) -o$@ ../win/X11/winmisc.c
++ $(O)winstat.o: ../win/X11/winstat.c $(HACK_H) $(INCL)/winX.h
++ 	$(cc) $(CFLAGS) -o$@ ../win/X11/winstat.c
++ $(O)wintext.o: ../win/X11/wintext.c $(HACK_H) $(INCL)/winX.h $(INCL)/xwindow.h
++ 	$(cc) $(CFLAGS) -o$@ ../win/X11/wintext.c
++ $(O)winval.o: ../win/X11/winval.c $(HACK_H) $(INCL)/winX.h
++ 	$(cc) $(CFLAGS) -o$@ ../win/X11/winval.c
++ $(O)tile.o: tile.c $(HACK_H)
++ $(O)gnaskstr.o: ../win/gnome/gnaskstr.c ../win/gnome/gnaskstr.h \
++ 		../win/gnome/gnmain.h
++ 	$(cc) $(CFLAGS) $(GNOMEINC) -o$@ ../win/gnome/gnaskstr.c
++ $(O)gnbind.o: ../win/gnome/gnbind.c ../win/gnome/gnbind.h ../win/gnome/gnmain.h \
++ 		../win/gnome/gnaskstr.h ../win/gnome/gnyesno.h
++ 	$(cc) $(CFLAGS) $(GNOMEINC) -o$@ ../win/gnome/gnbind.c
++ $(O)gnglyph.o: ../win/gnome/gnglyph.c ../win/gnome/gnglyph.h $(INCL)/tile2x11.h
++ 	$(cc) $(CFLAGS) $(GNOMEINC) -o$@ ../win/gnome/gnglyph.c
++ $(O)gnmain.o: ../win/gnome/gnmain.c ../win/gnome/gnmain.h ../win/gnome/gnsignal.h \
++ 		../win/gnome/gnbind.h ../win/gnome/gnopts.h $(HACK_H) \
++ 		$(INCL)/date.h
++ 	$(cc) $(CFLAGS) $(GNOMEINC) -o$@ ../win/gnome/gnmain.c
++ $(O)gnmap.o: ../win/gnome/gnmap.c ../win/gnome/gnmap.h ../win/gnome/gnglyph.h \
++ 		../win/gnome/gnsignal.h $(HACK_H)
++ 	$(cc) $(CFLAGS) $(GNOMEINC) -o$@ ../win/gnome/gnmap.c
++ $(O)gnmenu.o: ../win/gnome/gnmenu.c ../win/gnome/gnmenu.h ../win/gnome/gnmain.h \
++ 		../win/gnome/gnbind.h
++ 	$(cc) $(CFLAGS) $(GNOMEINC) -o$@ ../win/gnome/gnmenu.c
++ $(O)gnmesg.o: ../win/gnome/gnmesg.c ../win/gnome/gnmesg.h ../win/gnome/gnsignal.h
++ 	$(cc) $(CFLAGS) $(GNOMEINC) -o$@ ../win/gnome/gnmesg.c
++ $(O)gnopts.o: ../win/gnome/gnopts.c ../win/gnome/gnopts.h ../win/gnome/gnglyph.h \
++ 		../win/gnome/gnmain.h ../win/gnome/gnmap.h $(HACK_H)
++ 	$(cc) $(CFLAGS) $(GNOMEINC) -o$@ ../win/gnome/gnopts.c
++ $(O)gnplayer.o: ../win/gnome/gnplayer.c ../win/gnome/gnplayer.h \
++ 		../win/gnome/gnmain.h $(HACK_H)
++ 	$(cc) $(CFLAGS) $(GNOMEINC) -o$@ ../win/gnome/gnplayer.c
++ $(O)gnsignal.o: ../win/gnome/gnsignal.c ../win/gnome/gnsignal.h \
++ 		../win/gnome/gnmain.h
++ 	$(cc) $(CFLAGS) $(GNOMEINC) -o$@ ../win/gnome/gnsignal.c
++ $(O)gnstatus.o: ../win/gnome/gnstatus.c ../win/gnome/gnstatus.h \
++ 		../win/gnome/gnsignal.h ../win/gnome/gn_xpms.h \
++ 		../win/gnome/gnomeprv.h
++ 	$(cc) $(CFLAGS) $(GNOMEINC) -o$@ ../win/gnome/gnstatus.c
++ $(O)gntext.o: ../win/gnome/gntext.c ../win/gnome/gntext.h ../win/gnome/gnmain.h \
++ 		../win/gnome/gn_rip.h
++ 	$(cc) $(CFLAGS) $(GNOMEINC) -o$@ ../win/gnome/gntext.c
++ $(O)gnworn.o: ../win/gnome/gnworn.c ../win/gnome/gnworn.h ../win/gnome/gnglyph.h \
++ 		../win/gnome/gnsignal.h ../win/gnome/gnomeprv.h
++ 	$(cc) $(CFLAGS) $(GNOMEINC) -o$@ ../win/gnome/gnworn.c
++ $(O)gnyesno.o: ../win/gnome/gnyesno.c ../win/gnome/gnbind.h ../win/gnome/gnyesno.h
++ 	$(cc) $(CFLAGS) $(GNOMEINC) -o$@ ../win/gnome/gnyesno.c
++ $(O)wingem.o: ../win/gem/wingem.c $(HACK_H) $(INCL)/func_tab.h $(INCL)/dlb.h \
++ 		$(INCL)/patchlevel.h $(INCL)/wingem.h
++ 	$(cc) $(CFLAGS) -o$@ ../win/gem/wingem.c
++ $(O)wingem1.o: ../win/gem/wingem1.c $(INCL)/gem_rsc.h $(INCL)/load_img.h \
++ 		$(INCL)/gr_rect.h $(INCL)/wintype.h $(INCL)/wingem.h
++ 	$(cc) $(CFLAGS) -o$@ ../win/gem/wingem1.c
++ $(O)load_img.o: ../win/gem/load_img.c $(INCL)/load_img.h
++ 	$(cc) $(CFLAGS) -o$@ ../win/gem/load_img.c
++ $(O)gr_rect.o: ../win/gem/gr_rect.c $(INCL)/gr_rect.h
++ 	$(cc) $(CFLAGS) -o$@ ../win/gem/gr_rect.c
++ $(O)tile.o: tile.c $(HACK_H)
++ $(O)qt_win.o: ../win/Qt/qt_win.cpp $(HACK_H) $(INCL)/func_tab.h \
++ 		$(INCL)/dlb.h $(INCL)/patchlevel.h $(INCL)/tile2x11.h \
++ 		$(INCL)/qt_win.h $(INCL)/qt_clust.h $(INCL)/qt_kde0.h \
++ 		$(INCL)/qt_xpms.h qt_win.moc qt_kde0.moc qttableview.moc
++ 	$(CXX) $(CXXFLAGS) -o$@ ../win/Qt/qt_win.cpp
++ $(O)qt_clust.o: ../win/Qt/qt_clust.cpp $(INCL)/qt_clust.h
++ 	$(CXX) $(CXXFLAGS) -o$@ ../win/Qt/qt_clust.cpp
++ $(O)qttableview.o: ../win/Qt/qttableview.cpp $(INCL)/qttableview.h
++ 	$(CXX) $(CXXFLAGS) -o$@ ../win/Qt/qttableview.cpp
++ $(O)monstr.o: monstr.c $(CONFIG_H)
++ $(O)vis_tab.o: vis_tab.c $(CONFIG_H) $(INCL)/vis_tab.h
++ $(O)allmain.o: allmain.c $(HACK_H)
++ $(O)alloc.o: alloc.c $(CONFIG_H)
++ $(O)apply.o: apply.c $(HACK_H) $(INCL)/edog.h
++ $(O)artifact.o: artifact.c $(HACK_H) $(INCL)/artifact.h $(INCL)/artilist.h
++ $(O)attrib.o: attrib.c $(HACK_H)
++ $(O)ball.o: ball.c $(HACK_H)
++ $(O)bones.o: bones.c $(HACK_H) $(INCL)/lev.h
++ $(O)botl.o: botl.c $(HACK_H)
++ $(O)cmd.o: cmd.c $(HACK_H) $(INCL)/func_tab.h
++ $(O)dbridge.o: dbridge.c $(HACK_H)
++ $(O)decl.o: decl.c $(HACK_H)
++ $(O)detect.o: detect.c $(HACK_H) $(INCL)/artifact.h
++ $(O)dig.o: dig.c $(HACK_H) $(INCL)/edog.h
++ $(O)display.o: display.c $(HACK_H)
++ $(O)dlb.o: dlb.c $(CONFIG_H) $(INCL)/dlb.h
++ $(O)do.o: do.c $(HACK_H) $(INCL)/lev.h
++ $(O)do_name.o: do_name.c $(HACK_H)
++ $(O)do_wear.o: do_wear.c $(HACK_H)
++ $(O)dog.o: dog.c $(HACK_H) $(INCL)/edog.h
++ $(O)dogmove.o: dogmove.c $(HACK_H) $(INCL)/mfndpos.h $(INCL)/edog.h
++ $(O)dokick.o: dokick.c $(HACK_H) $(INCL)/eshk.h
++ $(O)dothrow.o: dothrow.c $(HACK_H) $(INCL)/edog.h
++ $(O)drawing.o: drawing.c $(HACK_H) $(INCL)/tcap.h
++ $(O)dungeon.o: dungeon.c $(HACK_H) $(INCL)/dgn_file.h $(INCL)/dlb.h
++ $(O)eat.o: eat.c $(HACK_H)
++ $(O)end.o: end.c $(HACK_H) $(INCL)/eshk.h $(INCL)/dlb.h
++ $(O)engrave.o: engrave.c $(HACK_H) $(INCL)/lev.h
++ $(O)exper.o: exper.c $(HACK_H)
++ $(O)explode.o: explode.c $(HACK_H)
++ $(O)extralev.o: extralev.c $(HACK_H)
++ $(O)files.o: files.c $(HACK_H) $(INCL)/dlb.h
++ $(O)fountain.o: fountain.c $(HACK_H)
++ $(O)hack.o: hack.c $(HACK_H)
++ $(O)hacklib.o: hacklib.c $(HACK_H)
++ $(O)invent.o: invent.c $(HACK_H)
++ $(O)light.o: light.c $(HACK_H) $(INCL)/lev.h
++ $(O)lock.o: lock.c $(HACK_H)
++ $(O)mail.o: mail.c $(HACK_H) $(INCL)/mail.h
++ $(O)makemon.o: makemon.c $(HACK_H) $(INCL)/epri.h $(INCL)/emin.h \
++ 		$(INCL)/edog.h
++ $(O)mapglyph.o: mapglyph.c $(HACK_H)
++ $(O)mcastu.o: mcastu.c $(HACK_H)
++ $(O)mhitm.o: mhitm.c $(HACK_H) $(INCL)/artifact.h $(INCL)/edog.h
++ $(O)mhitu.o: mhitu.c $(HACK_H) $(INCL)/artifact.h $(INCL)/edog.h
++ $(O)minion.o: minion.c $(HACK_H) $(INCL)/emin.h $(INCL)/epri.h
++ $(O)mklev.o: mklev.c $(HACK_H)
++ $(O)mkmap.o: mkmap.c $(HACK_H) $(INCL)/sp_lev.h
++ $(O)mkmaze.o: mkmaze.c $(HACK_H) $(INCL)/sp_lev.h $(INCL)/lev.h
++ $(O)mkobj.o: mkobj.c $(HACK_H)
++ $(O)mkroom.o: mkroom.c $(HACK_H)
++ $(O)mon.o: mon.c $(HACK_H) $(INCL)/mfndpos.h $(INCL)/edog.h
++ $(O)mondata.o: mondata.c $(HACK_H) $(INCL)/eshk.h $(INCL)/epri.h
++ $(O)monmove.o: monmove.c $(HACK_H) $(INCL)/mfndpos.h $(INCL)/artifact.h \
++ 		$(INCL)/epri.h
++ $(O)monst.o: monst.c $(CONFIG_H) $(INCL)/permonst.h $(INCL)/align.h \
++ 		$(INCL)/monattk.h $(INCL)/monflag.h $(INCL)/monsym.h \
++ 		$(INCL)/dungeon.h $(INCL)/eshk.h $(INCL)/vault.h \
++ 		$(INCL)/epri.h $(INCL)/color.h
++ $(O)mplayer.o: mplayer.c $(HACK_H)
++ $(O)mthrowu.o: mthrowu.c $(HACK_H)
++ $(O)muse.o: muse.c $(HACK_H) $(INCL)/edog.h
++ $(O)music.o: music.c $(HACK_H) #interp.c
++ $(O)o_init.o: o_init.c $(HACK_H) $(INCL)/lev.h
++ $(O)objects.o: objects.c $(CONFIG_H) $(INCL)/obj.h $(INCL)/objclass.h \
++ 		$(INCL)/prop.h $(INCL)/skills.h $(INCL)/color.h
++ $(O)objnam.o: objnam.c $(HACK_H)
++ $(O)options.o: options.c $(CONFIG_H) $(INCL)/objclass.h $(INCL)/flag.h \
++ 		$(HACK_H) $(INCL)/tcap.h
++ $(O)pager.o: pager.c $(HACK_H) $(INCL)/dlb.h
++ $(O)pickup.o: pickup.c $(HACK_H)
++ $(O)pline.o: pline.c $(HACK_H) $(INCL)/epri.h $(INCL)/edog.h
++ $(O)polyself.o: polyself.c $(HACK_H)
++ $(O)potion.o: potion.c $(HACK_H)
++ $(O)pray.o: pray.c $(HACK_H) $(INCL)/epri.h
++ $(O)priest.o: priest.c $(HACK_H) $(INCL)/mfndpos.h $(INCL)/eshk.h \
++ 		$(INCL)/epri.h $(INCL)/emin.h
++ $(O)quest.o: quest.c $(HACK_H) $(INCL)/qtext.h
++ $(O)questpgr.o: questpgr.c $(HACK_H) $(INCL)/dlb.h $(INCL)/qtext.h
++ $(O)read.o: read.c $(HACK_H)
++ $(O)rect.o: rect.c $(HACK_H)
++ $(O)region.o: region.c $(HACK_H) $(INCL)/lev.h
++ $(O)restore.o: restore.c $(HACK_H) $(INCL)/lev.h $(INCL)/tcap.h
++ $(O)rip.o: rip.c $(HACK_H)
++ $(O)rnd.o: rnd.c $(HACK_H)
++ $(O)role.o: role.c $(HACK_H)
++ $(O)rumors.o: rumors.c $(HACK_H) $(INCL)/lev.h $(INCL)/dlb.h
++ $(O)save.o: save.c $(HACK_H) $(INCL)/lev.h
++ $(O)shk.o: shk.c $(HACK_H) $(INCL)/eshk.h
++ $(O)shknam.o: shknam.c $(HACK_H) $(INCL)/eshk.h
++ $(O)sit.o: sit.c $(HACK_H) $(INCL)/artifact.h
++ $(O)sounds.o: sounds.c $(HACK_H) $(INCL)/edog.h
++ $(O)sp_lev.o: sp_lev.c $(HACK_H) $(INCL)/dlb.h $(INCL)/sp_lev.h
++ $(O)spell.o: spell.c $(HACK_H)
++ $(O)steal.o: steal.c $(HACK_H)
++ $(O)steed.o: steed.c $(HACK_H)
++ $(O)teleport.o: teleport.c $(HACK_H)
++ $(O)timeout.o: timeout.c $(HACK_H) $(INCL)/lev.h
++ $(O)topten.o: topten.c $(HACK_H) $(INCL)/dlb.h $(INCL)/patchlevel.h
++ $(O)track.o: track.c $(HACK_H)
++ $(O)trap.o: trap.c $(HACK_H)
++ $(O)u_init.o: u_init.c $(HACK_H)
++ $(O)uhitm.o: uhitm.c $(HACK_H)
++ $(O)vault.o: vault.c $(HACK_H) $(INCL)/vault.h
++ $(O)version.o: version.c $(HACK_H) $(INCL)/date.h $(INCL)/patchlevel.h
++ $(O)vision.o: vision.c $(HACK_H) $(INCL)/vis_tab.h
++ $(O)weapon.o: weapon.c $(HACK_H)
++ $(O)were.o: were.c $(HACK_H)
++ $(O)wield.o: wield.c $(HACK_H)
++ $(O)windows.o: windows.c $(HACK_H) $(INCL)/wingem.h $(INCL)/winGnome.h
++ $(O)wizard.o: wizard.c $(HACK_H) $(INCL)/qtext.h $(INCL)/epri.h
++ $(O)worm.o: worm.c $(HACK_H) $(INCL)/lev.h
++ $(O)worn.o: worn.c $(HACK_H)
++ $(O)write.o: write.c $(HACK_H)
++ $(O)zap.o: zap.c $(HACK_H)
++ 
++ # end of file
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/util/lev_comp.l nethack/util/lev_comp.l
--- nh_orig/util/lev_comp.l	2003-12-07 18:39:13.000000000 -0500
+++ nethack/util/lev_comp.l	2010-04-26 14:12:02.480715295 -0400
@@ -65,4 +65,13 @@
 void FDECL(init_yyout, (FILE *));
 
+void FDECL(include_push, (const char *));
+int NDECL(include_pop);
+
+long NDECL(handle_varstring_check);
+
+extern struct lc_vardefs *FDECL(vardef_defined,(struct lc_vardefs *,char *, int));
+
+extern struct lc_vardefs *variable_definitions;
+
 /*
  * This doesn't always get put in lev_comp.h
@@ -75,4 +84,11 @@
 static int map_cnt = 0;
 
+int doing_included_file = 0;
+YY_BUFFER_STATE include_stack[5];
+int include_line[5];
+char *include_file[5];
+
+FILE *orig_yyin = NULL;
+
 %}
 %e 1500
@@ -89,5 +105,5 @@
 		  return MAP_ID;
 		}
-<MAPC>[-|}{+ABCISHKPLWTF\\#. 0123456789]*\r?\n	{
+<MAPC>[-|}{+xABCISHKPLWTF\\#. 0123456789]*\r?\n	{
 		  int len = yyleng;
 		  /* convert \r\n to \n */
@@ -99,11 +115,13 @@
 		  map[map_cnt] = '\0';
 		}
-^#.*\n		{ line_number++; }
+^[ \t]*#.*\n		{ line_number++; }
 :		{ colon_line_number = line_number; return ':'; }
 MESSAGE		return MESSAGE_ID;
-MAZE		return MAZE_ID;
 NOMAP		return NOMAP_ID;
 LEVEL		return LEVEL_ID;
 INIT_MAP	return LEV_INIT_ID;
+mazegrid	return MAZE_GRID_ID;
+solidfill	return SOLID_FILL_ID;
+mines		return MINES_ID;
 FLAGS		return FLAGS_ID;
 GEOMETRY	return GEOMETRY_ID;
@@ -114,11 +132,9 @@
 TRAP		return TRAP_ID;
 DOOR		return DOOR_ID;
+ROOMDOOR	return ROOMDOOR_ID;
 DRAWBRIDGE	return DRAWBRIDGE_ID;
 MAZEWALK	return MAZEWALK_ID;
 WALLIFY		return WALLIFY_ID;
 REGION		return REGION_ID;
-RANDOM_OBJECTS	return RANDOM_OBJECTS_ID;
-RANDOM_MONSTERS	return RANDOM_MONSTERS_ID;
-RANDOM_PLACES	return RANDOM_PLACES_ID;
 ALTAR		return ALTAR_ID;
 LADDER		return LADDER_ID;
@@ -130,15 +146,70 @@
 SINK		return SINK_ID;
 POOL		return POOL_ID;
+WALLWALK	return WALLWALK_ID;
 NON_DIGGABLE	return NON_DIGGABLE_ID;
 NON_PASSWALL	return NON_PASSWALL_ID;
+IF		return IF_ID;
+ELSE		return ELSE_ID;
+EXIT		return EXIT_ID;
 ROOM		return ROOM_ID;
 SUBROOM		return SUBROOM_ID;
 RANDOM_CORRIDORS	return RAND_CORRIDOR_ID;
 CORRIDOR	return CORRIDOR_ID;
+SPILL	  return SPILL_ID;
+TERRAIN		return TERRAIN_ID;
+REPLACE_TERRAIN	return REPLACE_TERRAIN_ID;
+MON_GENERATION	return MON_GENERATION_ID;
 GOLD		return GOLD_ID;
+GRAVE		return GRAVE_ID;
 ENGRAVING	return ENGRAVING_ID;
 NAME		return NAME_ID;
 CHANCE		return CHANCE_ID;
+LOOP		return LOOP_ID;
+SWITCH		return SWITCH_ID;
+CASE		return CASE_ID;
+BREAK		return BREAK_ID;
+DEFAULT		return DEFAULT_ID;
+FUNCTION	return FUNCTION_ID;
+INCLUDE		return INCLUDE_ID;
+SOUNDS		return SOUNDS_ID;
+SHUFFLE		return SHUFFLE_ID;
+montype		return MONTYPE_ID;
+selection	return selection_ID;
+rect		return rect_ID;
+fillrect	return fillrect_ID;
+line		return line_ID;
+randline	return randline_ID;
+grow		return grow_ID;
+floodfill	return flood_ID;
+rndcoord	return rndcoord_ID;
+circle		return circle_ID;
+ellipse		return ellipse_ID;
+filter		return filter_ID;
+hear		{ yylval.i=LVLSND_HEARD;  return MSG_OUTPUT_TYPE; }
+pline		{ yylval.i=LVLSND_PLINED; return MSG_OUTPUT_TYPE; }
+verbal		{ yylval.i=LVLSND_VERBAL; return MSG_OUTPUT_TYPE; }
+feel		{ yylval.i=LVLSND_FELT;   return MSG_OUTPUT_TYPE; }
 levregion	return LEV;
+quantity	return QUANTITY_ID;
+buried		return BURIED_ID;
+eroded		return ERODED_ID;
+erodeproof	return ERODEPROOF_ID;
+trapped		return TRAPPED_ID;
+recharged	return RECHARGED_ID;
+invisible	return INVIS_ID;
+greased		return GREASED_ID;
+female		return FEMALE_ID;
+cancelled	return CANCELLED_ID;
+revived		return REVIVED_ID;
+avenge		return AVENGE_ID;
+fleeing		return FLEEING_ID;
+blinded		return BLINDED_ID;
+paralyzed	return PARALYZED_ID;
+stunned		return STUNNED_ID;
+confused	return CONFUSED_ID;
+seen_traps	return SEENTRAPS_ID;
+all		return ALL_ID;
+horizontal	{ yylval.i=1; return HORIZ_OR_VERT; }
+vertical	{ yylval.i=2; return HORIZ_OR_VERT; }
 open		{ yylval.i=D_ISOPEN; return DOOR_STATE; }
 closed		{ yylval.i=D_CLOSED; return DOOR_STATE; }
@@ -146,4 +217,5 @@
 nodoor		{ yylval.i=D_NODOOR; return DOOR_STATE; }
 broken		{ yylval.i=D_BROKEN; return DOOR_STATE; }
+secret		{ yylval.i=D_SECRET; return DOOR_STATE; }
 north		{ yylval.i=W_NORTH; return DIRECTION; }
 east		{ yylval.i=W_EAST; return DIRECTION; }
@@ -152,7 +224,4 @@
 random		{ yylval.i = -1; return RANDOM_TYPE; }
 none		{ yylval.i = -2; return NONE; }
-object		return O_REGISTER;
-monster		return M_REGISTER;
-place		return P_REGISTER;
 align		return A_REGISTER;
 left		{ yylval.i=1; return LEFT_OR_RIGHT; }
@@ -191,8 +260,8 @@
 burn		{ yylval.i=BURN; return ENGRAVING_TYPE; }
 mark		{ yylval.i=MARK; return ENGRAVING_TYPE; }
+blood		{ yylval.i=ENGR_BLOOD; return ENGRAVING_TYPE; }
 blessed		{ yylval.i=1; return CURSE_TYPE; }
 uncursed	{ yylval.i=2; return CURSE_TYPE; }
 cursed		{ yylval.i=3; return CURSE_TYPE; }
-contained	{ return CONTAINED; }
 noteleport	{ yylval.i=NOTELEPORT; return FLAG_TYPE; }
 hardfloor	{ yylval.i=HARDFLOOR; return FLAG_TYPE; }
@@ -200,10 +269,41 @@
 arboreal	{ yylval.i=ARBOREAL; return FLAG_TYPE; }	/* KMH */
 shortsighted	{ yylval.i=SHORTSIGHTED; return FLAG_TYPE; }
+noflipx		{ yylval.i=NOFLIPX; return FLAG_TYPE; }
+noflipy		{ yylval.i=NOFLIPY; return FLAG_TYPE; }
+noflip		{ yylval.i=(NOFLIPX + NOFLIPY); return FLAG_TYPE; }
+mazelevel	{ yylval.i=MAZELEVEL; return FLAG_TYPE; }
+premapped	{ yylval.i=PREMAPPED; return FLAG_TYPE; }
+shroud		{ yylval.i=SHROUD; return FLAG_TYPE; }
+stormy		{ yylval.i=STORMY; return FLAG_TYPE; }
+graveyard	{ yylval.i=GRAVEYARD; return FLAG_TYPE; }
+[0-9]+d[0-9]+	{ char *p = strchr(yytext, 'd');
+		  if (p) {
+			*p = '\0';
+			p++;
+			yylval.dice.num=atoi(yytext);
+			yylval.dice.die=atoi(p);
+		  } else { yylval.dice.num = yylval.dice.die = 1; }
+		  return DICE;
+		}
 \[\ *[0-9]+\%\ *\] { yylval.i = atoi(yytext + 1); return PERCENT; }
-[+\-]?[0-9]+	{ yylval.i=atoi(yytext); return INTEGER; }
+-[0-9]+		{ yylval.i=atoi(yytext); return MINUS_INTEGER; }
+\+[0-9]+	{ yylval.i=atoi(yytext); return PLUS_INTEGER; }
+[0-9]+\%	{ yylval.i = atoi(yytext); return SPERCENT; }
+[0-9]+		{ yylval.i=atoi(yytext); return INTEGER; }
 \"[^"]*\"	{ yytext[yyleng-1] = 0; /* Discard the trailing \" */
 		  yylval.map = (char *) alloc(strlen(yytext+1)+1);
 		  Strcpy(yylval.map, yytext+1); /* Discard the first \" */
 		  return STRING; }
+\$[a-zA-Z_][a-zA-Z_0-9]*	{ return handle_varstring_check(); }
+[a-zA-Z_][a-zA-Z_0-9]*	{ yylval.map = (char *) alloc(strlen(yytext)+1);
+		  Strcpy(yylval.map, yytext);
+		  return NQSTRING; }
+"=="		{ yylval.i = SPO_JE; return COMPARE_TYPE; }
+"!="		{ yylval.i = SPO_JNE; return COMPARE_TYPE; }
+"<>"		{ yylval.i = SPO_JNE; return COMPARE_TYPE; }
+"<="		{ yylval.i = SPO_JLE; return COMPARE_TYPE; }
+">="		{ yylval.i = SPO_JGE; return COMPARE_TYPE; }
+"<"		{ yylval.i = SPO_JL; return COMPARE_TYPE; }
+">"		{ yylval.i = SPO_JG; return COMPARE_TYPE; }
 \r?\n		{ line_number++; }
 [ \t]+		;
@@ -230,4 +330,5 @@
 #endif
 	    yyin = input_f;
+	    if (!orig_yyin) orig_yyin = yyin;
 }
 /* analogous routine (for completeness) */
@@ -238,3 +339,76 @@
 }
 
+void
+include_push(fname)
+const char *fname;
+{
+  if (doing_included_file >= 5)
+    yyerror("Too deep includes");
+  else {
+    FILE *fin;
+    fin = fopen(fname, "r");
+    if (!fin) {
+       yyerror("Cannot open file for including.");
+    } else {
+       include_stack[doing_included_file] = YY_CURRENT_BUFFER;
+       include_line[doing_included_file] = line_number;
+       include_file[doing_included_file] = strdup(fname);
+       doing_included_file++;
+       yyin = fin;
+       yy_switch_to_buffer(yy_create_buffer(fin, YY_BUF_SIZE));
+       BEGIN(INITIAL);
+       yyparse();
+    }
+  }
+}
+
+int
+include_pop()
+{
+  if (--doing_included_file < 0) {
+    doing_included_file = 0;
+    init_yyin(orig_yyin);
+    yy_switch_to_buffer(yy_create_buffer(orig_yyin, YY_BUF_SIZE));
+  } else {
+    if (include_file[doing_included_file])
+       free(include_file[doing_included_file]);
+    yy_switch_to_buffer(include_stack[doing_included_file]);
+    line_number = include_line[doing_included_file];
+  }
+  return 0;
+}
+
+/*
+ * Stub needed for lex interface.
+ */
+int
+yywrap()
+{
+    if (doing_included_file >= 0) include_pop();
+    return 1;
+}
+
+long
+handle_varstring_check()
+{
+  struct lc_vardefs *vd;
+  yylval.map = (char *) alloc(strlen(yytext)+1);
+  Strcpy(yylval.map, yytext);
+  if ((vd = vardef_defined(variable_definitions, yytext, 1))) {
+     long l = vd->var_type;
+     long a = ((l & SPOVAR_ARRAY) == SPOVAR_ARRAY);
+     l = (l & ~SPOVAR_ARRAY);
+     if (l == SPOVAR_INT) return (a ? VARSTRING_INT_ARRAY : VARSTRING_INT);
+     if (l == SPOVAR_STRING) return (a ? VARSTRING_STRING_ARRAY : VARSTRING_STRING);
+     if (l == SPOVAR_VARIABLE) return (a ? VARSTRING_VAR_ARRAY : VARSTRING_VAR);
+     if (l == SPOVAR_COORD) return (a ? VARSTRING_COORD_ARRAY : VARSTRING_COORD);
+     if (l == SPOVAR_REGION) return (a ? VARSTRING_REGION_ARRAY : VARSTRING_REGION);
+     if (l == SPOVAR_MAPCHAR) return (a ? VARSTRING_MAPCHAR_ARRAY : VARSTRING_MAPCHAR);
+     if (l == SPOVAR_MONST) return (a ? VARSTRING_MONST_ARRAY : VARSTRING_MONST);
+     if (l == SPOVAR_OBJ) return (a ? VARSTRING_OBJ_ARRAY : VARSTRING_OBJ);
+     if (l == SPOVAR_SEL) return (a ? VARSTRING_SEL_ARRAY : VARSTRING_SEL);
+  }
+  return VARSTRING;
+}
+
 /*lev_comp.l*/
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/util/lev_comp.y nethack/util/lev_comp.y
--- nh_orig/util/lev_comp.y	2003-12-07 18:39:13.000000000 -0500
+++ nethack/util/lev_comp.y	2010-05-13 09:22:22.303714330 -0400
@@ -25,5 +25,4 @@
 #include "sp_lev.h"
 
-#define MAX_REGISTERS	10
 #define ERR		(-1)
 /* many types of things are put in chars for transference to NetHack.
@@ -33,4 +32,8 @@
 #define MAX_OF_TYPE	128
 
+#define MAX_NESTED_IFS	20
+#define MAX_SWITCH_CASES 20
+#define MAX_SWITCH_BREAKS 20
+
 #define New(type)		\
 	(type *) memset((genericptr_t)alloc(sizeof(type)), 0, sizeof(type))
@@ -38,8 +41,12 @@
 #define Free(ptr)		free((genericptr_t)ptr)
 
+extern void VDECL(lc_error, (const char *, ...));
+extern void VDECL(lc_warning, (const char *, ...));
 extern void FDECL(yyerror, (const char *));
 extern void FDECL(yywarning, (const char *));
 extern int NDECL(yylex);
 int NDECL(yyparse);
+ extern void FDECL(include_push, (const char *));
+extern int NDECL(include_pop);
 
 extern int FDECL(get_floor_type, (CHAR_P));
@@ -51,78 +58,65 @@
 extern boolean FDECL(check_object_char, (CHAR_P));
 extern char FDECL(what_map_char, (CHAR_P));
-extern void FDECL(scan_map, (char *));
-extern void NDECL(wallify_map);
-extern boolean NDECL(check_subrooms);
-extern void FDECL(check_coord, (int,int,const char *));
-extern void NDECL(store_part);
-extern void NDECL(store_room);
-extern boolean FDECL(write_level_file, (char *,splev *,specialmaze *));
-extern void FDECL(free_rooms, (splev *));
+extern void FDECL(scan_map, (char *, sp_lev *));
+extern void FDECL(add_opcode, (sp_lev *, int, genericptr_t));
+extern genericptr_t FDECL(get_last_opcode_data1, (sp_lev *, int));
+extern genericptr_t FDECL(get_last_opcode_data2, (sp_lev *, int,int));
+extern boolean FDECL(check_subrooms, (sp_lev *));
+extern boolean FDECL(write_level_file, (char *,sp_lev *));
+extern struct opvar *FDECL(set_opvar_int, (struct opvar *, long));
+extern void VDECL(add_opvars, (sp_lev *, const char *, ...));
 
-static struct reg {
-	int x1, y1;
-	int x2, y2;
-}		current_region;
+extern struct lc_funcdefs *FDECL(funcdef_new,(long,char *));
+extern void FDECL(funcdef_free_all,(struct lc_funcdefs *));
+extern struct lc_funcdefs *FDECL(funcdef_defined,(struct lc_funcdefs *,char *, int));
 
-static struct coord {
-	int x;
-	int y;
-}		current_coord, current_align;
+extern struct lc_vardefs *FDECL(vardef_new,(long,char *));
+extern void FDECL(vardef_free_all,(struct lc_vardefs *));
+extern struct lc_vardefs *FDECL(vardef_defined,(struct lc_vardefs *,char *, int));
 
-static struct size {
-	int height;
-	int width;
-}		current_size;
+extern void FDECL(splev_add_from, (sp_lev *, sp_lev *));
 
-char tmpmessage[256];
-digpos *tmppass[32];
-char *tmpmap[ROWNO];
+extern void FDECL(check_vardef_type, (struct lc_vardefs *, char *, long));
+extern struct lc_vardefs *FDECL(add_vardef_type, (struct lc_vardefs *, char *, long));
 
-digpos *tmpdig[MAX_OF_TYPE];
-region *tmpreg[MAX_OF_TYPE];
-lev_region *tmplreg[MAX_OF_TYPE];
-door *tmpdoor[MAX_OF_TYPE];
-drawbridge *tmpdb[MAX_OF_TYPE];
-walk *tmpwalk[MAX_OF_TYPE];
+extern int FDECL(reverse_jmp_opcode, (int));
 
-room_door *tmprdoor[MAX_OF_TYPE];
-trap *tmptrap[MAX_OF_TYPE];
-monster *tmpmonst[MAX_OF_TYPE];
-object *tmpobj[MAX_OF_TYPE];
-altar *tmpaltar[MAX_OF_TYPE];
-lad *tmplad[MAX_OF_TYPE];
-stair *tmpstair[MAX_OF_TYPE];
-gold *tmpgold[MAX_OF_TYPE];
-engraving *tmpengraving[MAX_OF_TYPE];
-fountain *tmpfountain[MAX_OF_TYPE];
-sink *tmpsink[MAX_OF_TYPE];
-pool *tmppool[MAX_OF_TYPE];
 
-mazepart *tmppart[10];
-room *tmproom[MAXNROFROOMS*2];
-corridor *tmpcor[MAX_OF_TYPE];
+struct coord {
+	long x;
+	long y;
+};
 
-static specialmaze maze;
-static splev special_lev;
-static lev_init init_lev;
+sp_lev *splev = NULL;
 
-static char olist[MAX_REGISTERS], mlist[MAX_REGISTERS];
-static struct coord plist[MAX_REGISTERS];
+static struct opvar *if_list[MAX_NESTED_IFS];
 
-int n_olist = 0, n_mlist = 0, n_plist = 0;
+static short n_if_list = 0;
 
-unsigned int nlreg = 0, nreg = 0, ndoor = 0, ntrap = 0, nmons = 0, nobj = 0;
-unsigned int ndb = 0, nwalk = 0, npart = 0, ndig = 0, nlad = 0, nstair = 0;
-unsigned int naltar = 0, ncorridor = 0, nrooms = 0, ngold = 0, nengraving = 0;
-unsigned int nfountain = 0, npool = 0, nsink = 0, npass = 0;
+unsigned int max_x_map, max_y_map;
+int obj_containment = 0;
 
-static int lev_flags = 0;
+int in_container_obj = 0;
 
-unsigned int max_x_map, max_y_map;
+int in_switch_statement = 0;
+static struct opvar *switch_check_jump = NULL;
+static struct opvar *switch_default_case = NULL;
+static struct opvar *switch_case_list[MAX_SWITCH_CASES];
+static long switch_case_value[MAX_SWITCH_CASES];
+int n_switch_case_list = 0;
+static struct opvar *switch_break_list[MAX_SWITCH_BREAKS];
+int n_switch_break_list = 0;
 
-static xchar in_room;
+
+extern struct lc_vardefs *variable_definitions;
+
+
+static struct lc_funcdefs *function_definitions = NULL;
+int in_function_definition = 0;
+sp_lev *function_splev_backup = NULL;
 
 extern int fatal_error;
-extern int want_warnings;
+extern int got_errors;
+extern int line_number;
 extern const char *fname;
 
@@ -131,113 +125,150 @@
 %union
 {
-	int	i;
+	long	i;
 	char*	map;
 	struct {
-		xchar room;
-		xchar wall;
-		xchar door;
+		long room;
+		long wall;
+		long door;
 	} corpos;
+    struct {
+	long area;
+	long x1;
+	long y1;
+	long x2;
+	long y2;
+    } lregn;
+    struct {
+	long x;
+	long y;
+    } crd;
+    struct {
+	long ter;
+	long lit;
+    } terr;
+    struct {
+	long height;
+	long width;
+    } sze;
+    struct {
+	long die;
+	long num;
+    } dice;
 }
 
 
-%token	<i> CHAR INTEGER BOOLEAN PERCENT
-%token	<i> MESSAGE_ID MAZE_ID LEVEL_ID LEV_INIT_ID GEOMETRY_ID NOMAP_ID
+%token	<i> CHAR INTEGER BOOLEAN PERCENT SPERCENT
+%token	<i> MINUS_INTEGER PLUS_INTEGER
+%token	<i> MAZE_GRID_ID SOLID_FILL_ID MINES_ID
+%token	<i> MESSAGE_ID LEVEL_ID LEV_INIT_ID GEOMETRY_ID NOMAP_ID
 %token	<i> OBJECT_ID COBJECT_ID MONSTER_ID TRAP_ID DOOR_ID DRAWBRIDGE_ID
 %token	<i> MAZEWALK_ID WALLIFY_ID REGION_ID FILLING
-%token	<i> RANDOM_OBJECTS_ID RANDOM_MONSTERS_ID RANDOM_PLACES_ID
 %token	<i> ALTAR_ID LADDER_ID STAIR_ID NON_DIGGABLE_ID NON_PASSWALL_ID ROOM_ID
 %token	<i> PORTAL_ID TELEPRT_ID BRANCH_ID LEV CHANCE_ID
 %token	<i> CORRIDOR_ID GOLD_ID ENGRAVING_ID FOUNTAIN_ID POOL_ID SINK_ID NONE
 %token	<i> RAND_CORRIDOR_ID DOOR_STATE LIGHT_STATE CURSE_TYPE ENGRAVING_TYPE
-%token	<i> DIRECTION RANDOM_TYPE O_REGISTER M_REGISTER P_REGISTER A_REGISTER
+%token	<i> DIRECTION RANDOM_TYPE A_REGISTER
 %token	<i> ALIGNMENT LEFT_OR_RIGHT CENTER TOP_OR_BOT ALTAR_TYPE UP_OR_DOWN
 %token	<i> SUBROOM_ID NAME_ID FLAGS_ID FLAG_TYPE MON_ATTITUDE MON_ALERTNESS
-%token	<i> MON_APPEARANCE
-%token	<i> CONTAINED
-%token	<i> ',' ':' '(' ')' '[' ']'
+%token	<i> MON_APPEARANCE ROOMDOOR_ID IF_ID ELSE_ID
+%token	<i> SPILL_ID TERRAIN_ID HORIZ_OR_VERT REPLACE_TERRAIN_ID
+%token	<i> EXIT_ID SHUFFLE_ID
+%token	<i> QUANTITY_ID BURIED_ID LOOP_ID
+%token	<i> SWITCH_ID CASE_ID BREAK_ID DEFAULT_ID
+%token	<i> ERODED_ID TRAPPED_ID RECHARGED_ID INVIS_ID GREASED_ID
+%token	<i> FEMALE_ID CANCELLED_ID REVIVED_ID AVENGE_ID FLEEING_ID BLINDED_ID
+%token	<i> PARALYZED_ID STUNNED_ID CONFUSED_ID SEENTRAPS_ID ALL_ID
+%token	<i> MON_GENERATION_ID MONTYPE_ID
+%token	<i> GRAVE_ID ERODEPROOF_ID
+%token	<i> FUNCTION_ID
+%token	<i> INCLUDE_ID
+%token	<i> SOUNDS_ID MSG_OUTPUT_TYPE
+%token	<i> WALLWALK_ID COMPARE_TYPE
+%token	<i> rect_ID fillrect_ID line_ID randline_ID grow_ID selection_ID flood_ID
+%token	<i> rndcoord_ID circle_ID ellipse_ID filter_ID
+%token	<i> ',' ':' '(' ')' '[' ']' '{' '}'
 %token	<map> STRING MAP_ID
+%token	<map> NQSTRING VARSTRING
+%token	<map> VARSTRING_INT VARSTRING_INT_ARRAY
+%token	<map> VARSTRING_STRING VARSTRING_STRING_ARRAY
+%token	<map> VARSTRING_VAR VARSTRING_VAR_ARRAY
+%token	<map> VARSTRING_COORD VARSTRING_COORD_ARRAY
+%token	<map> VARSTRING_REGION VARSTRING_REGION_ARRAY
+%token	<map> VARSTRING_MAPCHAR VARSTRING_MAPCHAR_ARRAY
+%token	<map> VARSTRING_MONST VARSTRING_MONST_ARRAY
+%token	<map> VARSTRING_OBJ VARSTRING_OBJ_ARRAY
+%token	<map> VARSTRING_SEL VARSTRING_SEL_ARRAY
+%token	<dice> DICE;
 %type	<i> h_justif v_justif trap_name room_type door_state light_state
-%type	<i> alignment altar_type a_register roomfill filling door_pos
-%type	<i> door_wall walled secret amount chance
-%type	<i> engraving_type flags flag_list prefilled lev_region lev_init
-%type	<i> monster monster_c m_register object object_c o_register
-%type	<map> string maze_def level_def m_name o_name
+%type	<i> alignment altar_type a_register roomfill door_pos
+%type	<i> alignment_prfx
+%type	<i> door_wall walled secret chance
+%type	<i> dir_list map_geometry teleprt_detail
+%type	<i> object_infos object_info monster_infos monster_info
+%type	<i> levstatements region_detail_end
+%type	<i> engraving_type flag_list prefilled
+%type	<i> monster
+%type	<i> comparestmt encodecoord encoderegion mapchar
+%type	<i> seen_trap_mask
+%type	<i> mon_gen_list encodemonster encodeobj encodeobj_list
+%type	<i> sounds_list integer_list string_list encodecoord_list encoderegion_list mapchar_list encodemonster_list
+%type	<i> opt_percent opt_spercent opt_fillchar
+%type	<i> all_integers
+%type	<i> ter_selection ter_selection_x
+%type	<map> string level_def
+%type	<map> any_var any_var_array any_var_or_arr
 %type	<corpos> corr_spec
+%type	<lregn> region lev_region
+%type	<crd> room_pos subroom_pos room_align
+%type	<sze> room_size
+%type	<terr> terrain_type
+%left  '+' '-'
+%left  '*' '/' '%'
 %start	file
 
 %%
-file		: /* nothing */
-		| levels
+file		: header_stmts
+		| header_stmts levels
 		;
 
-levels		: level
-		| level levels
+header_stmts	: /* nothing */
+		| header_stmt header_stmts
 		;
 
-level		: maze_level
-		| room_level
+header_stmt	: function_define
+		| include_def
 		;
 
-maze_level	: maze_def flags lev_init messages regions
-		  {
-			unsigned i;
 
-			if (fatal_error > 0) {
-				(void) fprintf(stderr,
-				"%s : %d errors detected. No output created!\n",
-					fname, fatal_error);
-			} else {
-				maze.flags = $2;
-				(void) memcpy((genericptr_t)&(maze.init_lev),
-						(genericptr_t)&(init_lev),
-						sizeof(lev_init));
-				maze.numpart = npart;
-				maze.parts = NewTab(mazepart, npart);
-				for(i=0;i<npart;i++)
-				    maze.parts[i] = tmppart[i];
-				if (!write_level_file($1, (splev *)0, &maze)) {
-					yyerror("Can't write output file!!");
-					exit(EXIT_FAILURE);
-				}
-				npart = 0;
-			}
-			Free($1);
+include_def	: INCLUDE_ID STRING
+		  {
+		      include_push( $2 );
+		      Free($2);
 		  }
 		;
 
-room_level	: level_def flags lev_init messages rreg_init rooms corridors_def
-		  {
-			unsigned i;
+levels		: level
+		| level levels
+		;
 
+level		: level_def flags levstatements
+		  {
 			if (fatal_error > 0) {
 			    (void) fprintf(stderr,
-			      "%s : %d errors detected. No output created!\n",
-					fname, fatal_error);
-			} else {
-				special_lev.flags = (long) $2;
-				(void) memcpy(
-					(genericptr_t)&(special_lev.init_lev),
-					(genericptr_t)&(init_lev),
-					sizeof(lev_init));
-				special_lev.nroom = nrooms;
-				special_lev.rooms = NewTab(room, nrooms);
-				for(i=0; i<nrooms; i++)
-				    special_lev.rooms[i] = tmproom[i];
-				special_lev.ncorr = ncorridor;
-				special_lev.corrs = NewTab(corridor, ncorridor);
-				for(i=0; i<ncorridor; i++)
-				    special_lev.corrs[i] = tmpcor[i];
-				if (check_subrooms()) {
-				    if (!write_level_file($1, &special_lev,
-							  (specialmaze *)0)) {
-					yyerror("Can't write output file!!");
+				"%s: %d errors detected for level \"%s\". No output created!\n",
+					       fname, fatal_error, $1);
+				fatal_error = 0;
+				got_errors++;
+			} else if (!got_errors) {
+				if (!write_level_file($1, splev)) {
+				    lc_error("Can't write output file for '%s'!", $1);
 					exit(EXIT_FAILURE);
 				    }
 				}
-				free_rooms(&special_lev);
-				nrooms = 0;
-				ncorridor = 0;
-			}
 			Free($1);
+			Free(splev);
+			splev = NULL;
+			vardef_free_all(variable_definitions);
+			variable_definitions = NULL;
 		  }
 		;
@@ -245,43 +276,79 @@
 level_def	: LEVEL_ID ':' string
 		  {
+		      struct lc_funcdefs *f;
 			if (index($3, '.'))
-			    yyerror("Invalid dot ('.') in level name.");
+			    lc_error("Invalid dot ('.') in level name '%s'.", $3);
 			if ((int) strlen($3) > 8)
-			    yyerror("Level names limited to 8 characters.");
+			    lc_error("Level names limited to 8 characters ('%s').", $3);
+			f = function_definitions;
+			while (f) {
+			    f->n_called = 0;
+			    f = f->next;
+			}
+			splev = (sp_lev *)alloc(sizeof(sp_lev));
+			splev->n_opcodes = 0;
+			splev->opcodes = NULL;
+
+			vardef_free_all(variable_definitions);
+			variable_definitions = NULL;
+
 			$$ = $3;
-			special_lev.nrmonst = special_lev.nrobjects = 0;
-			n_mlist = n_olist = 0;
 		  }
 		;
 
-lev_init	: /* nothing */
+lev_init	: LEV_INIT_ID ':' SOLID_FILL_ID ',' terrain_type
 		  {
-			/* in case we're processing multiple files,
-			   explicitly clear any stale settings */
-			(void) memset((genericptr_t) &init_lev, 0,
-					sizeof init_lev);
-			init_lev.init_present = FALSE;
-			$$ = 0;
+		      long filling = $5.ter;
+		      if (filling == INVALID_TYPE || filling >= MAX_TYPE)
+			  lc_error("INIT_MAP: Invalid fill char type.");
+		      add_opvars(splev, "iiiiiiiio", LVLINIT_SOLIDFILL,filling,0,(long)$5.lit, 0,0,0,0, SPO_INITLEVEL);
+		      max_x_map = COLNO-1;
+		      max_y_map = ROWNO;
 		  }
-		| LEV_INIT_ID ':' CHAR ',' CHAR ',' BOOLEAN ',' BOOLEAN ',' light_state ',' walled
+		| LEV_INIT_ID ':' MAZE_GRID_ID ',' CHAR
 		  {
-			init_lev.init_present = TRUE;
-			init_lev.fg = what_map_char((char) $3);
-			if (init_lev.fg == INVALID_TYPE)
-			    yyerror("Invalid foreground type.");
-			init_lev.bg = what_map_char((char) $5);
-			if (init_lev.bg == INVALID_TYPE)
-			    yyerror("Invalid background type.");
-			init_lev.smoothed = $7;
-			init_lev.joined = $9;
-			if (init_lev.joined &&
-			    init_lev.fg != CORR && init_lev.fg != ROOM)
-			    yyerror("Invalid foreground type for joined map.");
-			init_lev.lit = $11;
-			init_lev.walled = $13;
-			$$ = 1;
+		      long filling = what_map_char((char) $5);
+		      if (filling == INVALID_TYPE || filling >= MAX_TYPE)
+			  lc_error("INIT_MAP: Invalid fill char type.");
+		      add_opvars(splev, "iiiiiiiio", LVLINIT_MAZEGRID,filling,0,0, 0,0,0,0, SPO_INITLEVEL);
+		      max_x_map = COLNO-1;
+		      max_y_map = ROWNO;
+		  }
+		| LEV_INIT_ID ':' MINES_ID ',' CHAR ',' CHAR ',' BOOLEAN ',' BOOLEAN ',' light_state ',' walled opt_fillchar
+		  {
+		      long fg = what_map_char((char) $5);
+		      long bg = what_map_char((char) $7);
+		      long smoothed = $9;
+		      long joined = $11;
+		      long lit = $13;
+		      long walled = $15;
+		      long filling = $16;
+		      if (fg == INVALID_TYPE || fg >= MAX_TYPE)
+			  lc_error("INIT_MAP: Invalid foreground type.");
+		      if (bg == INVALID_TYPE || bg >= MAX_TYPE)
+			  lc_error("INIT_MAP: Invalid background type.");
+		      if (joined && fg != CORR && fg != ROOM)
+			  lc_error("INIT_MAP: Invalid foreground type for joined map.");
+
+		      if (filling == INVALID_TYPE)
+			  lc_error("INIT_MAP: Invalid fill char type.");
+
+		      add_opvars(splev, "iiiiiiiio", LVLINIT_MINES,filling,walled,lit, joined,smoothed,bg,fg, SPO_INITLEVEL);
+			max_x_map = COLNO-1;
+			max_y_map = ROWNO;
+		  }
+		;
+
+opt_fillchar	: /* nothing */
+		  {
+		      $$ = -1;
+		  }
+		| ',' CHAR
+		  {
+		      $$ = what_map_char((char) $2);
 		  }
 		;
 
+
 walled		: BOOLEAN
 		| RANDOM_TYPE
@@ -290,10 +357,9 @@
 flags		: /* nothing */
 		  {
-			$$ = 0;
+		      add_opvars(splev, "io", 0, SPO_LEVEL_FLAGS);
 		  }
 		| FLAGS_ID ':' flag_list
 		  {
-			$$ = lev_flags;
-			lev_flags = 0;	/* clear for next user */
+		      add_opvars(splev, "io", $3, SPO_LEVEL_FLAGS);
 		  }
 		;
@@ -301,127 +367,645 @@
 flag_list	: FLAG_TYPE ',' flag_list
 		  {
-			lev_flags |= $1;
+		      $$ = ($1 | $3);
 		  }
 		| FLAG_TYPE
 		  {
-			lev_flags |= $1;
+		      $$ = $1;
 		  }
 		;
 
-messages	: /* nothing */
-		| message messages
+levstatements	: /* nothing */
+		  {
+		      $$ = 0;
+		  }
+		| levstatement levstatements
+		  {
+		      $$ = 1 + $2;
+		  }
 		;
 
-message		: MESSAGE_ID ':' STRING
+levstatement 	: message
+		| lev_init
+		| altar_detail
+		| grave_detail
+		| mon_generation
+		| sounds_detail
+		| branch_region
+		| corridor
+		| variable_define
+		| shuffle_detail
+		| diggable_detail
+		| door_detail
+		| wallwalk_detail
+		| drawbridge_detail
+		| engraving_detail
+		| fountain_detail
+		| gold_detail
+		| switchstatement
+		| loopstatement
+		| ifstatement
+		| exitstatement
+		| function_define
+		| function_call
+		| ladder_detail
+		| map_definition
+		| mazewalk_detail
+		| monster_detail
+		| object_detail
+		| passwall_detail
+		| pool_detail
+		| portal_region
+		| random_corridors
+		| region_detail
+		| room_def
+		| subroom_def
+		| sink_detail
+		| terrain_detail
+		| replace_terrain_detail
+		| spill_detail
+		| stair_detail
+		| stair_region
+		| teleprt_region
+		| trap_detail
+		| wallify_detail
+		;
+
+any_var_array	: VARSTRING_INT_ARRAY
+		| VARSTRING_STRING_ARRAY
+		| VARSTRING_VAR_ARRAY
+		| VARSTRING_COORD_ARRAY
+		| VARSTRING_REGION_ARRAY
+		| VARSTRING_MAPCHAR_ARRAY
+		| VARSTRING_MONST_ARRAY
+		| VARSTRING_OBJ_ARRAY
+		| VARSTRING_SEL_ARRAY
+		;
+
+any_var		: VARSTRING_INT
+		| VARSTRING_STRING
+		| VARSTRING_VAR
+		| VARSTRING_COORD
+		| VARSTRING_REGION
+		| VARSTRING_MAPCHAR
+		| VARSTRING_MONST
+		| VARSTRING_OBJ
+		| VARSTRING_SEL
+		;
+
+any_var_or_arr	: any_var_array
+		| any_var
+		| VARSTRING
+		;
+
+shuffle_detail	: SHUFFLE_ID ':' any_var_array
 		  {
-			int i, j;
+		      struct lc_vardefs *vd;
+		      if ((vd = vardef_defined(variable_definitions, $3, 1))) {
+			  if (!(vd->var_type & SPOVAR_ARRAY))
+			      lc_error("Trying to shuffle non-array variable '%s'", $3);
+		      } else lc_error("Trying to shuffle undefined variable '%s'", $3);
+		      add_opvars(splev, "so", $3, SPO_SHUFFLE_ARRAY);
+		      Free($3);
+		  }
+		;
 
-			i = (int) strlen($3) + 1;
-			j = (int) strlen(tmpmessage);
-			if (i + j > 255) {
-			   yyerror("Message string too long (>256 characters)");
+variable_define	: any_var_or_arr '=' math_expr
+		  {
+		      variable_definitions = add_vardef_type(variable_definitions, $1, SPOVAR_INT);
+		      add_opvars(splev, "iso", 0, $1, SPO_VAR_INIT);
+		      Free($1);
+		  }
+		| any_var_or_arr '=' selection_ID ':' ter_selection
+		  {
+		      variable_definitions = add_vardef_type(variable_definitions, $1, SPOVAR_SEL);
+		      add_opvars(splev, "iso", 0, $1, SPO_VAR_INIT);
+		      Free($1);
+		  }
+		| any_var_or_arr '=' STRING
+		  {
+		      variable_definitions = add_vardef_type(variable_definitions, $1, SPOVAR_STRING);
+		      add_opvars(splev, "siso", $3, 0, $1, SPO_VAR_INIT);
+		      Free($1);
+		      Free($3);
+		  }
+		| any_var_or_arr '=' any_var_or_arr
+		  {
+		      struct lc_vardefs *vd1, *vd2;
+		      if (!strcmp($1, $3)) lc_error("Trying to set variable '%s' to value of itself", $1);
+		      vd2 = vardef_defined(variable_definitions, $3, 1);
+		      if (!vd2) {
+			  lc_error("Trying to use an undefined variable '%s'", $3);
 			} else {
-			    if (j) tmpmessage[j++] = '\n';
-			    (void) strncpy(tmpmessage+j, $3, i - 1);
-			    tmpmessage[j + i - 1] = 0;
+			  if ((vd1 = vardef_defined(variable_definitions, $1, 1))) {
+			      if (vd1->var_type != vd2->var_type)
+				  lc_error("Trying to redefine variable '%s' as different type", $1);
+			  } else {
+			      vd1 = vardef_new(vd2->var_type, $1);
+			      vd1->next = variable_definitions;
+			      variable_definitions = vd1;
+			  }
 			}
+		      add_opvars(splev, "siso", $3, -1, $1, SPO_VAR_INIT);
+		      Free($1);
 			Free($3);
 		  }
+		| any_var_or_arr '=' TERRAIN_ID ':' mapchar
+		  {
+		      variable_definitions = add_vardef_type(variable_definitions, $1, SPOVAR_MAPCHAR);
+		      add_opvars(splev, "miso", (long)$5, 0, $1, SPO_VAR_INIT);
+		      Free($1);
+		  }
+		| any_var_or_arr '=' MONSTER_ID ':' encodemonster
+		  {
+		      variable_definitions = add_vardef_type(variable_definitions, $1, SPOVAR_MONST);
+		      add_opvars(splev, "Miso", (long)$5, 0, $1, SPO_VAR_INIT);
+		      Free($1);
+		  }
+		| any_var_or_arr '=' OBJECT_ID ':' encodeobj
+		  {
+		      variable_definitions = add_vardef_type(variable_definitions, $1, SPOVAR_OBJ);
+		      add_opvars(splev, "Oiso", (long)$5, 0, $1, SPO_VAR_INIT);
+		      Free($1);
+		  }
+		| any_var_or_arr '=' encodecoord
+		  {
+		      variable_definitions = add_vardef_type(variable_definitions, $1, SPOVAR_COORD);
+		      add_opvars(splev, "ciso", (long)$3, 0, $1, SPO_VAR_INIT);
+		      Free($1);
+		  }
+		| any_var_or_arr '=' encoderegion
+		  {
+		      variable_definitions = add_vardef_type(variable_definitions, $1, SPOVAR_REGION);
+		      add_opvars(splev, "riso", (long)$3, 0, $1, SPO_VAR_INIT);
+		      Free($1);
+		  }
+		| any_var_or_arr '=' '{' integer_list '}'
+		  {
+		      long n_items = $4;
+		      variable_definitions = add_vardef_type(variable_definitions, $1, SPOVAR_INT|SPOVAR_ARRAY);
+		      add_opvars(splev, "iso", n_items, $1, SPO_VAR_INIT);
+		      Free($1);
+		  }
+		| any_var_or_arr '=' '{' encodecoord_list '}'
+		  {
+		      long n_items = $4;
+		      variable_definitions = add_vardef_type(variable_definitions, $1, SPOVAR_COORD|SPOVAR_ARRAY);
+		      add_opvars(splev, "iso", n_items, $1, SPO_VAR_INIT);
+		      Free($1);
+		  }
+		| any_var_or_arr '=' '{' encoderegion_list '}'
+		  {
+		      long n_items = $4;
+		      variable_definitions = add_vardef_type(variable_definitions, $1, SPOVAR_REGION|SPOVAR_ARRAY);
+		      add_opvars(splev, "iso", n_items, $1, SPO_VAR_INIT);
+		      Free($1);
+		  }
+		| any_var_or_arr '=' TERRAIN_ID ':' '{' mapchar_list '}'
+		  {
+		      long n_items = $6;
+		      variable_definitions = add_vardef_type(variable_definitions, $1, SPOVAR_MAPCHAR|SPOVAR_ARRAY);
+		      add_opvars(splev, "iso", n_items, $1, SPO_VAR_INIT);
+		      Free($1);
+		  }
+		| any_var_or_arr '=' MONSTER_ID ':' '{' encodemonster_list '}'
+		  {
+		      long n_items = $6;
+		      variable_definitions = add_vardef_type(variable_definitions, $1, SPOVAR_MONST|SPOVAR_ARRAY);
+		      add_opvars(splev, "iso", n_items, $1, SPO_VAR_INIT);
+		      Free($1);
+		  }
+		| any_var_or_arr '=' OBJECT_ID ':' '{' encodeobj_list '}'
+		  {
+		      long n_items = $6;
+		      variable_definitions = add_vardef_type(variable_definitions, $1, SPOVAR_OBJ|SPOVAR_ARRAY);
+		      add_opvars(splev, "iso", n_items, $1, SPO_VAR_INIT);
+		      Free($1);
+		  }
+		| any_var_or_arr '=' '{' string_list '}'
+		  {
+		      long n_items = $4;
+		      variable_definitions = add_vardef_type(variable_definitions, $1, SPOVAR_STRING|SPOVAR_ARRAY);
+		      add_opvars(splev, "iso", n_items, $1, SPO_VAR_INIT);
+		      Free($1);
+		  }
 		;
 
-rreg_init	: /* nothing */
-		| rreg_init init_rreg
+encodeobj_list	: encodeobj
+		  {
+		      add_opvars(splev, "O", $1);
+		      $$ = 1;
+		  }
+		| encodeobj_list ',' encodeobj
+		  {
+		      add_opvars(splev, "O", $3);
+		      $$ = 1 + $1;
+		  }
 		;
 
-init_rreg	: RANDOM_OBJECTS_ID ':' object_list
+encodemonster_list	: encodemonster
 		  {
-			if(special_lev.nrobjects) {
-			    yyerror("Object registers already initialized!");
-			} else {
-			    special_lev.nrobjects = n_olist;
-			    special_lev.robjects = (char *) alloc(n_olist);
-			    (void) memcpy((genericptr_t)special_lev.robjects,
-					  (genericptr_t)olist, n_olist);
+		      add_opvars(splev, "M", $1);
+		      $$ = 1;
 			}
+		| encodemonster_list ',' encodemonster
+		  {
+		      add_opvars(splev, "M", $3);
+		      $$ = 1 + $1;
 		  }
-		| RANDOM_MONSTERS_ID ':' monster_list
+		;
+
+mapchar_list	: mapchar
 		  {
-			if(special_lev.nrmonst) {
-			    yyerror("Monster registers already initialized!");
+		      add_opvars(splev, "m", $1);
+		      $$ = 1;
+		  }
+		| mapchar_list ',' mapchar
+		  {
+		      add_opvars(splev, "m", $3);
+		      $$ = 1 + $1;
+		  }
+		;
+
+encoderegion_list	: encoderegion
+		  {
+		      add_opvars(splev, "r", $1);
+		      $$ = 1;
+		  }
+		| encoderegion_list ',' encoderegion
+		  {
+		      add_opvars(splev, "r", $3);
+		      $$ = 1 + $1;
+		  }
+		;
+
+encodecoord_list	: encodecoord
+		  {
+		      add_opvars(splev, "c", $1);
+		      $$ = 1;
+		  }
+		| encodecoord_list ',' encodecoord
+		  {
+		      add_opvars(splev, "c", $3);
+		      $$ = 1 + $1;
+		  }
+		;
+
+integer_list	: math_expr
+		  {
+		      $$ = 1;
+		  }
+		| integer_list ',' math_expr
+		  {
+		      $$ = 1 + $1;
+		  }
+		;
+
+string_list	: STRING
+		  {
+		      add_opvars(splev, "s", $1);
+		      Free($1);
+		      $$ = 1;
+		  }
+		| string_list ',' STRING
+		  {
+		      add_opvars(splev, "s", $3);
+		      Free($1);
+		      $$ = 1 + $1;
+		  }
+		;
+
+function_define	: FUNCTION_ID NQSTRING '(' ')'
+		  {
+		      struct lc_funcdefs *funcdef;
+
+		      if (in_function_definition)
+			  lc_error("Recursively defined functions not allowed (function %s).", $2);
+
+		      in_function_definition++;
+
+		      if (funcdef_defined(function_definitions, $2, 1))
+			  lc_error("Function '%s' already defined once.", $2);
+
+		      funcdef = funcdef_new(-1, $2);
+		      funcdef->next = function_definitions;
+		      function_definitions = funcdef;
+		      function_splev_backup = splev;
+		      splev = &(funcdef->code);
+		      Free($2);
+		  }
+		'{' levstatements '}'
+		  {
+		      add_opvars(splev, "io", 0, SPO_RETURN);
+		      splev = function_splev_backup;
+		      in_function_definition--;
+		  }
+		;
+
+function_call	: NQSTRING '(' ')'
+		  {
+		      struct lc_funcdefs *tmpfunc;
+		      tmpfunc = funcdef_defined(function_definitions, $1, 1);
+		      if (tmpfunc) {
+			  long l;
+			  if (!(tmpfunc->n_called)) {
+			      /* we haven't called the function yet, so insert it in the code */
+			      struct opvar *jmp = New(struct opvar);
+			      set_opvar_int(jmp, splev->n_opcodes+1);
+			      add_opcode(splev, SPO_PUSH, jmp);
+			      add_opcode(splev, SPO_JMP, NULL); /* we must jump past it first, then CALL it, due to RETURN. */
+
+			      tmpfunc->addr = splev->n_opcodes;
+			      splev_add_from(splev, &(tmpfunc->code));
+			      set_opvar_int(jmp, splev->n_opcodes - jmp->vardata.l);
+			  }
+			  l = tmpfunc->addr - splev->n_opcodes - 2;
+			  add_opvars(splev, "iio", 0, l, SPO_CALL);
+			  tmpfunc->n_called++;
 			} else {
-			    special_lev.nrmonst = n_mlist;
-			    special_lev.rmonst = (char *) alloc(n_mlist);
-			    (void) memcpy((genericptr_t)special_lev.rmonst,
-					  (genericptr_t)mlist, n_mlist);
+			  lc_error("Function '%s' not defined.", $1);
 			  }
+		      Free($1);
 		  }
 		;
 
-rooms		: /* Nothing  -  dummy room for use with INIT_MAP */
+exitstatement	: EXIT_ID
 		  {
-			tmproom[nrooms] = New(room);
-			tmproom[nrooms]->name = (char *) 0;
-			tmproom[nrooms]->parent = (char *) 0;
-			tmproom[nrooms]->rtype = 0;
-			tmproom[nrooms]->rlit = 0;
-			tmproom[nrooms]->xalign = ERR;
-			tmproom[nrooms]->yalign = ERR;
-			tmproom[nrooms]->x = 0;
-			tmproom[nrooms]->y = 0;
-			tmproom[nrooms]->w = 2;
-			tmproom[nrooms]->h = 2;
-			in_room = 1;
+		      add_opcode(splev, SPO_EXIT, NULL);
 		  }
-		| roomlist
 		;
 
-roomlist	: aroom
-		| aroom roomlist
+opt_percent	: /* nothing */
+		  {
+		      $$ = 100;
+		  }
+		| PERCENT
+		  {
+		      if ($1 < 0 || $1 > 100) lc_error("Unexpected percentile chance '%li%%'", $1);
+		      $$ = $1;
+		  }
 		;
 
-corridors_def	: random_corridors
-		| corridors
+opt_spercent	: /* nothing */
+		  {
+		      $$ = 100;
+		  }
+		| ',' SPERCENT
+		  {
+		      if ($2 < 0 || $2 > 100) lc_error("Unexpected percentile chance '%li%%'", $2);
+		      $$ = $2;
+		  }
 		;
 
-random_corridors: RAND_CORRIDOR_ID
+comparestmt     : PERCENT
 		  {
-			tmpcor[0] = New(corridor);
-			tmpcor[0]->src.room = -1;
-			ncorridor = 1;
+		      /* val > rn2(100) */
+		      add_opvars(splev, "iio", (long)$1, 100, SPO_RN2);
+		      $$ = SPO_JG;
+                  }
+		| '[' math_expr_var COMPARE_TYPE math_expr_var ']'
+                  {
+		      $$ = $3;
 		  }
 		;
 
-corridors	: /* nothing */
-		| corridors corridor
+switchstatement	: SWITCH_ID '[' integer_or_var ']'
+		  {
+		      struct opvar *chkjmp;
+		      if (in_switch_statement > 0)
+			  lc_error("Cannot nest switch-statements.");
+
+		      in_switch_statement++;
+
+		      n_switch_case_list = 0;
+		      n_switch_break_list = 0;
+		      switch_default_case = NULL;
+
+		      add_opvars(splev, "o", SPO_RN2);
+
+		      chkjmp = New(struct opvar);
+		      set_opvar_int(chkjmp, splev->n_opcodes+1);
+		      switch_check_jump = chkjmp;
+		      add_opcode(splev, SPO_PUSH, chkjmp);
+		      add_opcode(splev, SPO_JMP, NULL);
+		  }
+		'{' switchcases '}'
+		  {
+		      struct opvar *endjump = New(struct opvar);
+		      int i;
+
+		      set_opvar_int(endjump, splev->n_opcodes+1);
+
+		      add_opcode(splev, SPO_PUSH, endjump);
+		      add_opcode(splev, SPO_JMP, NULL);
+
+		      set_opvar_int(switch_check_jump, splev->n_opcodes - switch_check_jump->vardata.l);
+
+		      for (i = 0; i < n_switch_case_list; i++) {
+			  add_opvars(splev, "oio", SPO_COPY, switch_case_value[i], SPO_CMP);
+			  set_opvar_int(switch_case_list[i], switch_case_list[i]->vardata.l - splev->n_opcodes-1);
+			  add_opcode(splev, SPO_PUSH, switch_case_list[i]);
+			  add_opcode(splev, SPO_JE, NULL);
+		      }
+
+		      if (switch_default_case) {
+			  set_opvar_int(switch_default_case, switch_default_case->vardata.l - splev->n_opcodes-1);
+			  add_opcode(splev, SPO_PUSH, switch_default_case);
+			  add_opcode(splev, SPO_JMP, NULL);
+		      }
+
+		      set_opvar_int(endjump, splev->n_opcodes - endjump->vardata.l);
+
+		      for (i = 0; i < n_switch_break_list; i++) {
+			  set_opvar_int(switch_break_list[i], splev->n_opcodes - switch_break_list[i]->vardata.l);
+		      }
+
+		      add_opcode(splev, SPO_POP, NULL); /* get rid of the value in stack */
+		      in_switch_statement--;
+
+
+		  }
 		;
 
-corridor	: CORRIDOR_ID ':' corr_spec ',' corr_spec
+switchcases	: /* nothing */
+		| switchcase switchcases
+		;
+
+switchcase	: CASE_ID all_integers ':'
 		  {
-			tmpcor[ncorridor] = New(corridor);
-			tmpcor[ncorridor]->src.room = $3.room;
-			tmpcor[ncorridor]->src.wall = $3.wall;
-			tmpcor[ncorridor]->src.door = $3.door;
-			tmpcor[ncorridor]->dest.room = $5.room;
-			tmpcor[ncorridor]->dest.wall = $5.wall;
-			tmpcor[ncorridor]->dest.door = $5.door;
-			ncorridor++;
-			if (ncorridor >= MAX_OF_TYPE) {
-				yyerror("Too many corridors in level!");
-				ncorridor--;
+		      if (n_switch_case_list < MAX_SWITCH_CASES) {
+			  struct opvar *tmppush = New(struct opvar);
+			  set_opvar_int(tmppush, splev->n_opcodes);
+			  switch_case_value[n_switch_case_list] = $2;
+			  switch_case_list[n_switch_case_list++] = tmppush;
+		      } else lc_error("Too many cases in a switch.");
 			}
+		breakstatements
+		  {
 		  }
-		| CORRIDOR_ID ':' corr_spec ',' INTEGER
+		| DEFAULT_ID ':'
 		  {
-			tmpcor[ncorridor] = New(corridor);
-			tmpcor[ncorridor]->src.room = $3.room;
-			tmpcor[ncorridor]->src.wall = $3.wall;
-			tmpcor[ncorridor]->src.door = $3.door;
-			tmpcor[ncorridor]->dest.room = -1;
-			tmpcor[ncorridor]->dest.wall = $5;
-			ncorridor++;
-			if (ncorridor >= MAX_OF_TYPE) {
-				yyerror("Too many corridors in level!");
-				ncorridor--;
+		      struct opvar *tmppush = New(struct opvar);
+
+		      if (switch_default_case)
+			  lc_error("Switch default case already used.");
+
+		      set_opvar_int(tmppush, splev->n_opcodes);
+		      switch_default_case = tmppush;
+		  }
+		breakstatements
+		  {
+		  }
+		;
+
+breakstatements	: /* nothing */
+		| breakstatement breakstatements
+		;
+
+breakstatement	: BREAK_ID
+		  {
+		      struct opvar *tmppush = New(struct opvar);
+		      set_opvar_int(tmppush, splev->n_opcodes);
+		      if (n_switch_break_list >= MAX_SWITCH_BREAKS)
+			  lc_error("Too many BREAKs inside single SWITCH");
+		      switch_break_list[n_switch_break_list++] = tmppush;
+
+		      add_opcode(splev, SPO_PUSH, tmppush);
+		      add_opcode(splev, SPO_JMP, NULL);
+		  }
+		| levstatement
+		  {
+		  }
+		;
+
+loopstatement	: LOOP_ID '[' integer_or_var ']'
+		  {
+		      struct opvar *tmppush = New(struct opvar);
+
+		      if (n_if_list >= MAX_NESTED_IFS) {
+			  lc_error("LOOP: Too deeply nested conditionals.");
+			  n_if_list = MAX_NESTED_IFS - 1;
+		      }
+		      set_opvar_int(tmppush, splev->n_opcodes);
+		      if_list[n_if_list++] = tmppush;
+
+		      add_opvars(splev, "o", SPO_DEC);
+		  }
+		 '{' levstatements '}'
+		  {
+		      struct opvar *tmppush;
+
+		      add_opvars(splev, "oio", SPO_COPY, 0, SPO_CMP);
+
+		      tmppush = (struct opvar *) if_list[--n_if_list];
+		      set_opvar_int(tmppush, tmppush->vardata.l - splev->n_opcodes-1);
+		      add_opcode(splev, SPO_PUSH, tmppush);
+		      add_opcode(splev, SPO_JG, NULL);
+		      add_opcode(splev, SPO_POP, NULL); /* get rid of the count value in stack */
+		  }
+		;
+
+ifstatement 	: IF_ID comparestmt
+		  {
+		      struct opvar *tmppush2 = New(struct opvar);
+
+		      if (n_if_list >= MAX_NESTED_IFS) {
+			  lc_error("IF: Too deeply nested conditionals.");
+			  n_if_list = MAX_NESTED_IFS - 1;
+		      }
+
+		      add_opcode(splev, SPO_CMP, NULL);
+
+		      set_opvar_int(tmppush2, splev->n_opcodes+1);
+
+		      if_list[n_if_list++] = tmppush2;
+
+		      add_opcode(splev, SPO_PUSH, tmppush2);
+
+		      add_opcode(splev, reverse_jmp_opcode( $2 ), NULL);
+		  }
+		 if_ending
+		  {
+		     /* do nothing */
+		  }
+		;
+
+if_ending	: '{' levstatements '}'
+		  {
+		      if (n_if_list > 0) {
+			  struct opvar *tmppush;
+			  tmppush = (struct opvar *) if_list[--n_if_list];
+			  set_opvar_int(tmppush, splev->n_opcodes - tmppush->vardata.l);
+		      } else lc_error("IF: Huh?!  No start address?");
+		  }
+		| '{' levstatements '}'
+		  {
+		      if (n_if_list > 0) {
+			  struct opvar *tmppush = New(struct opvar);
+			  struct opvar *tmppush2;
+
+			  set_opvar_int(tmppush, splev->n_opcodes+1);
+			  add_opcode(splev, SPO_PUSH, tmppush);
+
+			  add_opcode(splev, SPO_JMP, NULL);
+
+			  tmppush2 = (struct opvar *) if_list[--n_if_list];
+
+			  set_opvar_int(tmppush2, splev->n_opcodes - tmppush2->vardata.l);
+			  if_list[n_if_list++] = tmppush;
+		      } else lc_error("IF: Huh?!  No else-part address?");
+		  }
+		 ELSE_ID '{' levstatements '}'
+		  {
+		      if (n_if_list > 0) {
+			  struct opvar *tmppush;
+			  tmppush = (struct opvar *) if_list[--n_if_list];
+			  set_opvar_int(tmppush, splev->n_opcodes - tmppush->vardata.l);
+		      } else lc_error("IF: Huh?! No end address?");
+		  }
+		;
+
+message		: MESSAGE_ID ':' string_expr
+		  {
+		      add_opvars(splev, "o", SPO_MESSAGE);
+		  }
+		;
+
+wallwalk_detail	: WALLWALK_ID ':' coord_or_var ',' mapchar_or_var opt_spercent
+		  {
+		      add_opvars(splev, "mio", SP_MAPCHAR_PACK(ROOM,-2), $6, SPO_WALLWALK);
+		  }
+		| WALLWALK_ID ':' coord_or_var ',' mapchar_or_var ',' mapchar_or_var opt_spercent
+		  {
+		      add_opvars(splev, "io", $8, SPO_WALLWALK);
+		  }
+		;
+
+random_corridors: RAND_CORRIDOR_ID
+		  {
+		      add_opvars(splev, "iiiiiio", -1,  0, -1, -1, -1, -1, SPO_CORRIDOR);
+		  }
+		| RAND_CORRIDOR_ID ':' all_integers
+		  {
+		      add_opvars(splev, "iiiiiio", -1, $3, -1, -1, -1, -1, SPO_CORRIDOR);
+		  }
+		| RAND_CORRIDOR_ID ':' RANDOM_TYPE
+		  {
+		      add_opvars(splev, "iiiiiio", -1, -1, -1, -1, -1, -1, SPO_CORRIDOR);
+		  }
+		;
+
+corridor	: CORRIDOR_ID ':' corr_spec ',' corr_spec
+		  {
+		      add_opvars(splev, "iiiiiio",
+				 $3.room, $3.door, $3.wall,
+				 $5.room, $5.door, $5.wall,
+				 SPO_CORRIDOR);
 			}
+		| CORRIDOR_ID ':' corr_spec ',' all_integers
+		  {
+		      add_opvars(splev, "iiiiiio",
+				 $3.room, $3.door, $3.wall,
+				 -1, -1, (long)$5,
+				 SPO_CORRIDOR);
 		  }
 		;
@@ -429,6 +1013,4 @@
 corr_spec	: '(' INTEGER ',' DIRECTION ',' door_pos ')'
 		  {
-			if ((unsigned) $2 >= nrooms)
-			    yyerror("Wrong room number!");
 			$$.room = $2;
 			$$.wall = $4;
@@ -437,47 +1019,34 @@
 		;
 
-aroom		: room_def room_details
+room_begin      : room_type opt_percent ',' light_state
 		  {
-			store_room();
+		      if (($2 < 100) && ($1 == OROOM))
+			  lc_error("Only typed rooms can have a chance.");
+		      else {
+			  add_opvars(splev, "iii", (long)$1, (long)$2, (long)$4);
 		  }
-		| subroom_def room_details
-		  {
-			store_room();
 		  }
 		;
 
-subroom_def	: SUBROOM_ID ':' room_type ',' light_state ',' subroom_pos ',' room_size ',' string roomfill
+subroom_def	: SUBROOM_ID ':' room_begin ',' subroom_pos ',' room_size roomfill
 		  {
-			tmproom[nrooms] = New(room);
-			tmproom[nrooms]->parent = $11;
-			tmproom[nrooms]->name = (char *) 0;
-			tmproom[nrooms]->rtype = $3;
-			tmproom[nrooms]->rlit = $5;
-			tmproom[nrooms]->filled = $12;
-			tmproom[nrooms]->xalign = ERR;
-			tmproom[nrooms]->yalign = ERR;
-			tmproom[nrooms]->x = current_coord.x;
-			tmproom[nrooms]->y = current_coord.y;
-			tmproom[nrooms]->w = current_size.width;
-			tmproom[nrooms]->h = current_size.height;
-			in_room = 1;
+		      add_opvars(splev, "iiiiiiio", (long)$8, ERR, ERR,
+				 $5.x, $5.y, $7.width, $7.height, SPO_SUBROOM);
+		  }
+		  '{' levstatements '}'
+		  {
+		      add_opcode(splev, SPO_ENDROOM, NULL);
 		  }
 		;
 
-room_def	: ROOM_ID ':' room_type ',' light_state ',' room_pos ',' room_align ',' room_size roomfill
+room_def	: ROOM_ID ':' room_begin ',' room_pos ',' room_align ',' room_size roomfill
 		  {
-			tmproom[nrooms] = New(room);
-			tmproom[nrooms]->name = (char *) 0;
-			tmproom[nrooms]->parent = (char *) 0;
-			tmproom[nrooms]->rtype = $3;
-			tmproom[nrooms]->rlit = $5;
-			tmproom[nrooms]->filled = $12;
-			tmproom[nrooms]->xalign = current_align.x;
-			tmproom[nrooms]->yalign = current_align.y;
-			tmproom[nrooms]->x = current_coord.x;
-			tmproom[nrooms]->y = current_coord.y;
-			tmproom[nrooms]->w = current_size.width;
-			tmproom[nrooms]->h = current_size.height;
-			in_room = 1;
+		      add_opvars(splev, "iiiiiiio", (long)$10,
+				 $7.x, $7.y, $5.x, $5.y,
+				 $9.width, $9.height, SPO_ROOM);
+		  }
+		  '{' levstatements '}'
+		  {
+		      add_opcode(splev, SPO_ENDROOM, NULL);
 		  }
 		;
@@ -497,13 +1066,13 @@
 			if ( $2 < 1 || $2 > 5 ||
 			    $4 < 1 || $4 > 5 ) {
-			    yyerror("Room position should be between 1 & 5!");
+			    lc_error("Room positions should be between 1-5: (%li,%li)!", $2, $4);
 			} else {
-			    current_coord.x = $2;
-			    current_coord.y = $4;
+			    $$.x = $2;
+			    $$.y = $4;
 			}
 		  }
 		| RANDOM_TYPE
 		  {
-			current_coord.x = current_coord.y = ERR;
+			$$.x = $$.y = ERR;
 		  }
 		;
@@ -512,13 +1081,13 @@
 		  {
 			if ( $2 < 0 || $4 < 0) {
-			    yyerror("Invalid subroom position !");
+			    lc_error("Invalid subroom position (%li,%li)!", $2, $4);
 			} else {
-			    current_coord.x = $2;
-			    current_coord.y = $4;
+			    $$.x = $2;
+			    $$.y = $4;
 			}
 		  }
 		| RANDOM_TYPE
 		  {
-			current_coord.x = current_coord.y = ERR;
+			$$.x = $$.y = ERR;
 		  }
 		;
@@ -526,10 +1095,10 @@
 room_align	: '(' h_justif ',' v_justif ')'
 		  {
-			current_align.x = $2;
-			current_align.y = $4;
+		      $$.x = $2;
+		      $$.y = $4;
 		  }
 		| RANDOM_TYPE
 		  {
-			current_align.x = current_align.y = ERR;
+		      $$.x = $$.y = ERR;
 		  }
 		;
@@ -537,71 +1106,25 @@
 room_size	: '(' INTEGER ',' INTEGER ')'
 		  {
-			current_size.width = $2;
-			current_size.height = $4;
+			$$.width = $2;
+			$$.height = $4;
 		  }
 		| RANDOM_TYPE
 		  {
-			current_size.height = current_size.width = ERR;
-		  }
-		;
-
-room_details	: /* nothing */
-		| room_details room_detail
-		;
-
-room_detail	: room_name
-		| room_chance
-		| room_door
-		| monster_detail
-		| object_detail
-		| trap_detail
-		| altar_detail
-		| fountain_detail
-		| sink_detail
-		| pool_detail
-		| gold_detail
-		| engraving_detail
-		| stair_detail
-		;
-
-room_name	: NAME_ID ':' string
-		  {
-			if (tmproom[nrooms]->name)
-			    yyerror("This room already has a name!");
-			else
-			    tmproom[nrooms]->name = $3;
-		  }
-		;
-
-room_chance	: CHANCE_ID ':' INTEGER
-		   {
-			if (tmproom[nrooms]->chance)
-			    yyerror("This room already assigned a chance!");
-			else if (tmproom[nrooms]->rtype == OROOM)
-			    yyerror("Only typed rooms can have a chance!");
-			else if ($3 < 1 || $3 > 99)
-			    yyerror("The chance is supposed to be percentile.");
-			else
-			    tmproom[nrooms]->chance = $3;
+			$$.height = $$.width = ERR;
 		   }
 		;
 
-room_door	: DOOR_ID ':' secret ',' door_state ',' door_wall ',' door_pos
+door_detail	: ROOMDOOR_ID ':' secret ',' door_state ',' door_wall ',' door_pos
 		  {
 			/* ERR means random here */
 			if ($7 == ERR && $9 != ERR) {
-		     yyerror("If the door wall is random, so must be its pos!");
+			    lc_error("If the door wall is random, so must be its pos!");
 			} else {
-			    tmprdoor[ndoor] = New(room_door);
-			    tmprdoor[ndoor]->secret = $3;
-			    tmprdoor[ndoor]->mask = $5;
-			    tmprdoor[ndoor]->wall = $7;
-			    tmprdoor[ndoor]->pos = $9;
-			    ndoor++;
-			    if (ndoor >= MAX_OF_TYPE) {
-				    yyerror("Too many doors in room!");
-				    ndoor--;
+			    add_opvars(splev, "iiiio", (long)$9, (long)$5, (long)$3, (long)$7, SPO_ROOM_DOOR);
 			    }
 			}
+		| DOOR_ID ':' door_state ',' ter_selection
+		  {
+		      add_opvars(splev, "io", (long)$3, SPO_DOOR);
 		  }
 		;
@@ -611,71 +1134,39 @@
 		;
 
-door_wall	: DIRECTION
-		| RANDOM_TYPE
-		;
-
-door_pos	: INTEGER
+door_wall	: dir_list
 		| RANDOM_TYPE
 		;
 
-maze_def	: MAZE_ID ':' string ',' filling
-		  {
-			maze.filling = (schar) $5;
-			if (index($3, '.'))
-			    yyerror("Invalid dot ('.') in level name.");
-			if ((int) strlen($3) > 8)
-			    yyerror("Level names limited to 8 characters.");
-			$$ = $3;
-			in_room = 0;
-			n_plist = n_mlist = n_olist = 0;
-		  }
-		;
-
-filling		: CHAR
+dir_list	: DIRECTION
 		  {
-			$$ = get_floor_type((char)$1);
+		      $$ = $1;
 		  }
-		| RANDOM_TYPE
+		| DIRECTION '|' dir_list
 		  {
-			$$ = -1;
+		      $$ = ($1 | $3);
 		  }
 		;
 
-regions		: aregion
-		| aregion regions
-		;
-
-aregion		: map_definition reg_init map_details
-		  {
-			store_part();
-		  }
+door_pos	: INTEGER
+		| RANDOM_TYPE
 		;
 
 map_definition	: NOMAP_ID
 		  {
-			tmppart[npart] = New(mazepart);
-			tmppart[npart]->halign = 1;
-			tmppart[npart]->valign = 1;
-			tmppart[npart]->nrobjects = 0;
-			tmppart[npart]->nloc = 0;
-			tmppart[npart]->nrmonst = 0;
-			tmppart[npart]->xsize = 1;
-			tmppart[npart]->ysize = 1;
-			tmppart[npart]->map = (char **) alloc(sizeof(char *));
-			tmppart[npart]->map[0] = (char *) alloc(1);
-			tmppart[npart]->map[0][0] = STONE;
+		      add_opvars(splev, "ciisiio", 0, 0, 1, (char *)0, 0, 0, SPO_MAP);
 			max_x_map = COLNO-1;
 			max_y_map = ROWNO;
 		  }
-		| map_geometry MAP_ID
+		| map_geometry roomfill MAP_ID
 		  {
-			tmppart[npart] = New(mazepart);
-			tmppart[npart]->halign = $<i>1 % 10;
-			tmppart[npart]->valign = $<i>1 / 10;
-			tmppart[npart]->nrobjects = 0;
-			tmppart[npart]->nloc = 0;
-			tmppart[npart]->nrmonst = 0;
-			scan_map($2);
-			Free($2);
+		      add_opvars(splev, "cii", ((long)($1 % 10) & 0xff) + (((long)($1 / 10) & 0xff) << 16), 1, (long)$2);
+		      scan_map($3, splev);
+		      Free($3);
+		  }
+		| GEOMETRY_ID ':' coord_or_var roomfill MAP_ID
+		  {
+		      add_opvars(splev, "ii", 2, (long)$4);
+		      scan_map($5, splev);
+		      Free($5);
 		  }
 		;
@@ -683,5 +1174,5 @@
 map_geometry	: GEOMETRY_ID ':' h_justif ',' v_justif
 		  {
-			$<i>$ = $<i>3 + ($<i>5 * 10);
+			$$ = $3 + ($5 * 10);
 		  }
 		;
@@ -695,547 +1186,477 @@
 		;
 
-reg_init	: /* nothing */
-		| reg_init init_reg
+sounds_detail	: SOUNDS_ID ':' integer_or_var ',' sounds_list
+		  {
+		      long n_sounds = $5;
+		      add_opvars(splev, "io", n_sounds, SPO_LEVEL_SOUNDS);
+		  }
 		;
 
-init_reg	: RANDOM_OBJECTS_ID ':' object_list
+sounds_list	: lvl_sound_part
 		  {
-			if (tmppart[npart]->nrobjects) {
-			    yyerror("Object registers already initialized!");
-			} else {
-			    tmppart[npart]->robjects = (char *)alloc(n_olist);
-			    (void) memcpy((genericptr_t)tmppart[npart]->robjects,
-					  (genericptr_t)olist, n_olist);
-			    tmppart[npart]->nrobjects = n_olist;
-			}
+		      $$ = 1;
 		  }
-		| RANDOM_PLACES_ID ':' place_list
+		| lvl_sound_part ',' sounds_list
 		  {
-			if (tmppart[npart]->nloc) {
-			    yyerror("Location registers already initialized!");
-			} else {
-			    register int i;
-			    tmppart[npart]->rloc_x = (char *) alloc(n_plist);
-			    tmppart[npart]->rloc_y = (char *) alloc(n_plist);
-			    for(i=0;i<n_plist;i++) {
-				tmppart[npart]->rloc_x[i] = plist[i].x;
-				tmppart[npart]->rloc_y[i] = plist[i].y;
-			    }
-			    tmppart[npart]->nloc = n_plist;
-			}
+		      $$ = 1 + $3;
 		  }
-		| RANDOM_MONSTERS_ID ':' monster_list
+		;
+
+lvl_sound_part	: '(' MSG_OUTPUT_TYPE ',' string_expr ')'
 		  {
-			if (tmppart[npart]->nrmonst) {
-			    yyerror("Monster registers already initialized!");
-			} else {
-			    tmppart[npart]->rmonst = (char *) alloc(n_mlist);
-			    (void) memcpy((genericptr_t)tmppart[npart]->rmonst,
-					  (genericptr_t)mlist, n_mlist);
-			    tmppart[npart]->nrmonst = n_mlist;
+		      add_opvars(splev, "i", (long)$2);
 			}
+		;
+
+mon_generation	: MON_GENERATION_ID ':' SPERCENT ',' mon_gen_list
+		  {
+		      long chance = $3;
+		      long total_mons = $5;
+		      if (chance < 0) chance = 0;
+		      else if (chance > 100) chance = 100;
+
+		      if (total_mons < 1) lc_error("Monster generation: zero monsters defined?");
+		      add_opvars(splev, "iio", chance, total_mons, SPO_MON_GENERATION);
 		  }
 		;
 
-object_list	: object
+mon_gen_list	: mon_gen_part
 		  {
-			if (n_olist < MAX_REGISTERS)
-			    olist[n_olist++] = $<i>1;
-			else
-			    yyerror("Object list too long!");
+		      $$ = 1;
 		  }
-		| object ',' object_list
+		| mon_gen_part ',' mon_gen_list
 		  {
-			if (n_olist < MAX_REGISTERS)
-			    olist[n_olist++] = $<i>1;
-			else
-			    yyerror("Object list too long!");
+		      $$ = 1 + $3;
 		  }
 		;
 
-monster_list	: monster
+mon_gen_part	: '(' integer_or_var ',' monster ')'
 		  {
-			if (n_mlist < MAX_REGISTERS)
-			    mlist[n_mlist++] = $<i>1;
-			else
-			    yyerror("Monster list too long!");
+		      long token = $4;
+		      if (token == ERR) lc_error("Monster generation: Invalid monster symbol");
+		      add_opvars(splev, "ii", token, 1);
 		  }
-		| monster ',' monster_list
+		| '(' integer_or_var ',' string ')'
 		  {
-			if (n_mlist < MAX_REGISTERS)
-			    mlist[n_mlist++] = $<i>1;
-			else
-			    yyerror("Monster list too long!");
+		      long token;
+		      token = get_monster_id($4, (char)0);
+		      if (token == ERR) lc_error("Monster generation: Invalid monster name");
+		      add_opvars(splev, "ii", token, 0);
 		  }
 		;
 
-place_list	: place
+monster_detail	: MONSTER_ID chance ':' monster_desc
 		  {
-			if (n_plist < MAX_REGISTERS)
-			    plist[n_plist++] = current_coord;
-			else
-			    yyerror("Location list too long!");
+		      add_opvars(splev, "io", 0, SPO_MONSTER);
+
+		      if ( 1 == $2 ) {
+			  if (n_if_list > 0) {
+			      struct opvar *tmpjmp;
+			      tmpjmp = (struct opvar *) if_list[--n_if_list];
+			      set_opvar_int(tmpjmp, splev->n_opcodes - tmpjmp->vardata.l);
+			  } else lc_error("Conditional creation of monster, but no jump point marker.");
 		  }
-		| place
+		  }
+		| MONSTER_ID chance ':' monster_desc
 		  {
-			if (n_plist < MAX_REGISTERS)
-			    plist[n_plist++] = current_coord;
-			else
-			    yyerror("Location list too long!");
+		      add_opvars(splev, "io", 1, SPO_MONSTER);
+		      $<i>$ = $2;
+		      in_container_obj++;
+		  }
+		'{' levstatements '}'
+		 {
+		     in_container_obj--;
+		     add_opvars(splev, "o", SPO_END_MONINVENT);
+		     if ( 1 == $<i>5 ) {
+			 if (n_if_list > 0) {
+			     struct opvar *tmpjmp;
+			     tmpjmp = (struct opvar *) if_list[--n_if_list];
+			     set_opvar_int(tmpjmp, splev->n_opcodes - tmpjmp->vardata.l);
+			 } else lc_error("Conditional creation of monster, but no jump point marker.");
+		     }
 		  }
-		 ',' place_list
 		;
 
-map_details	: /* nothing */
-		| map_details map_detail
+monster_desc	: monster_or_var ',' coord_or_var monster_infos
+		  {
+		      /* nothing */
+		  }
 		;
 
-map_detail	: monster_detail
-		| object_detail
-		| door_detail
-		| trap_detail
-		| drawbridge_detail
-		| region_detail
-		| stair_region
-		| portal_region
-		| teleprt_region
-		| branch_region
-		| altar_detail
-		| fountain_detail
-		| mazewalk_detail
-		| wallify_detail
-		| ladder_detail
-		| stair_detail
-		| gold_detail
-		| engraving_detail
-		| diggable_detail
-		| passwall_detail
+monster_infos	: /* nothing */
+		  {
+		      struct opvar *stopit = New(struct opvar);
+		      set_opvar_int(stopit, SP_M_V_END);
+		      add_opcode(splev, SPO_PUSH, stopit);
+		      $$ = 0x0000;
+		  }
+		| monster_infos ',' monster_info
+		  {
+		      if (( $1 & $3 ))
+			  lc_error("MONSTER extra info defined twice.");
+		      $$ = ( $1 | $3 );
+		  }
 		;
 
-monster_detail	: MONSTER_ID chance ':' monster_c ',' m_name ',' coordinate
+monster_info	: string_expr
 		  {
-			tmpmonst[nmons] = New(monster);
-			tmpmonst[nmons]->x = current_coord.x;
-			tmpmonst[nmons]->y = current_coord.y;
-			tmpmonst[nmons]->class = $<i>4;
-			tmpmonst[nmons]->peaceful = -1; /* no override */
-			tmpmonst[nmons]->asleep = -1;
-			tmpmonst[nmons]->align = - MAX_REGISTERS - 2;
-			tmpmonst[nmons]->name.str = 0;
-			tmpmonst[nmons]->appear = 0;
-			tmpmonst[nmons]->appear_as.str = 0;
-			tmpmonst[nmons]->chance = $2;
-			tmpmonst[nmons]->id = NON_PM;
-			if (!in_room)
-			    check_coord(current_coord.x, current_coord.y,
-					"Monster");
-			if ($6) {
-			    int token = get_monster_id($6, (char) $<i>4);
-			    if (token == ERR)
-				yywarning(
-			      "Invalid monster name!  Making random monster.");
-			    else
-				tmpmonst[nmons]->id = token;
-			    Free($6);
+		      add_opvars(splev, "i", SP_M_V_NAME);
+		      $$ = 0x0001;
 			}
+		| MON_ATTITUDE
+		  {
+		      add_opvars(splev, "ii", (long)$<i>1, SP_M_V_PEACEFUL);
+		      $$ = 0x0002;
 		  }
-		 monster_infos
+		| MON_ALERTNESS
 		  {
-			if (++nmons >= MAX_OF_TYPE) {
-			    yyerror("Too many monsters in room or mazepart!");
-			    nmons--;
+		      add_opvars(splev, "ii", (long)$<i>1, SP_M_V_ASLEEP);
+		      $$ = 0x0004;
 			}
+		| alignment_prfx
+		  {
+		      add_opvars(splev, "ii", (long)$1, SP_M_V_ALIGN);
+		      $$ = 0x0008;
 		  }
-		;
-
-monster_infos	: /* nothing */
-		| monster_infos monster_info
-		;
-
-monster_info	: ',' string
+		| MON_APPEARANCE string_expr
 		  {
-			tmpmonst[nmons]->name.str = $2;
+		      add_opvars(splev, "ii", (long)$<i>1, SP_M_V_APPEAR);
+		      $$ = 0x0010;
 		  }
-		| ',' MON_ATTITUDE
+		| FEMALE_ID
 		  {
-			tmpmonst[nmons]->peaceful = $<i>2;
+		      add_opvars(splev, "ii", 1, SP_M_V_FEMALE);
+		      $$ = 0x0020;
 		  }
-		| ',' MON_ALERTNESS
+		| INVIS_ID
 		  {
-			tmpmonst[nmons]->asleep = $<i>2;
+		      add_opvars(splev, "ii", 1, SP_M_V_INVIS);
+		      $$ = 0x0040;
 		  }
-		| ',' alignment
+		| CANCELLED_ID
 		  {
-			tmpmonst[nmons]->align = $<i>2;
+		      add_opvars(splev, "ii", 1, SP_M_V_CANCELLED);
+		      $$ = 0x0080;
 		  }
-		| ',' MON_APPEARANCE string
+		| REVIVED_ID
 		  {
-			tmpmonst[nmons]->appear = $<i>2;
-			tmpmonst[nmons]->appear_as.str = $3;
+		      add_opvars(splev, "ii", 1, SP_M_V_REVIVED);
+		      $$ = 0x0100;
 		  }
-		;
-
-object_detail	: OBJECT_ID object_desc
+		| AVENGE_ID
 		  {
+		      add_opvars(splev, "ii", 1, SP_M_V_AVENGE);
+		      $$ = 0x0200;
 		  }
-		| COBJECT_ID object_desc
+		| FLEEING_ID ':' integer_or_var
 		  {
-			/* 1: is contents of preceeding object with 2 */
-			/* 2: is a container */
-			/* 0: neither */
-			tmpobj[nobj-1]->containment = 2;
+		      add_opvars(splev, "i", SP_M_V_FLEEING);
+		      $$ = 0x0400;
 		  }
-		;
-
-object_desc	: chance ':' object_c ',' o_name
+		| BLINDED_ID ':' integer_or_var
 		  {
-			tmpobj[nobj] = New(object);
-			tmpobj[nobj]->class = $<i>3;
-			tmpobj[nobj]->corpsenm = NON_PM;
-			tmpobj[nobj]->curse_state = -1;
-			tmpobj[nobj]->name.str = 0;
-			tmpobj[nobj]->chance = $1;
-			tmpobj[nobj]->id = -1;
-			if ($5) {
-			    int token = get_object_id($5, $<i>3);
-			    if (token == ERR)
-				yywarning(
-				"Illegal object name!  Making random object.");
-			     else
-				tmpobj[nobj]->id = token;
-			    Free($5);
+		      add_opvars(splev, "i", SP_M_V_BLINDED);
+		      $$ = 0x0800;
 			}
+		| PARALYZED_ID ':' integer_or_var
+		  {
+		      add_opvars(splev, "i", SP_M_V_PARALYZED);
+		      $$ = 0x1000;
 		  }
-		 ',' object_where object_infos
+		| STUNNED_ID
 		  {
-			if (++nobj >= MAX_OF_TYPE) {
-			    yyerror("Too many objects in room or mazepart!");
-			    nobj--;
+		      add_opvars(splev, "ii", 1, SP_M_V_STUNNED);
+		      $$ = 0x2000;
 			}
+		| CONFUSED_ID
+		  {
+		      add_opvars(splev, "ii", 1, SP_M_V_CONFUSED);
+		      $$ = 0x4000;
+		  }
+		| SEENTRAPS_ID ':' seen_trap_mask
+		  {
+		      add_opvars(splev, "ii", (long)$3, SP_M_V_SEENTRAPS);
+		      $$ = 0x8000;
 		  }
 		;
 
-object_where	: coordinate
+seen_trap_mask	: STRING
 		  {
-			tmpobj[nobj]->containment = 0;
-			tmpobj[nobj]->x = current_coord.x;
-			tmpobj[nobj]->y = current_coord.y;
-			if (!in_room)
-			    check_coord(current_coord.x, current_coord.y,
-					"Object");
+		      int token = get_trap_type($1);
+		      if (token == ERR || token == 0)
+			  lc_error("Unknown trap type '%s'!", $1);
+		      $$ = (1L << (token - 1));
 		  }
-		| CONTAINED
+		| ALL_ID
 		  {
-			tmpobj[nobj]->containment = 1;
-			/* random coordinate, will be overridden anyway */
-			tmpobj[nobj]->x = -MAX_REGISTERS-1;
-			tmpobj[nobj]->y = -MAX_REGISTERS-1;
+		      $$ = (long) ~0;
+		  }
+		| STRING '|' seen_trap_mask
+		  {
+		      int token = get_trap_type($1);
+		      if (token == ERR || token == 0)
+			  lc_error("Unknown trap type '%s'!", $1);
+
+		      if ((1L << (token - 1)) & $3)
+			  lc_error("Monster seen_traps, trap '%s' listed twice.", $1);
+
+		      $$ = ((1L << (token - 1)) | $3);
 		  }
 		;
 
-object_infos	: /* nothing */
+object_detail	: OBJECT_ID chance ':' object_desc
 		  {
-			tmpobj[nobj]->spe = -127;
-	/* Note below: we're trying to make as many of these optional as
-	 * possible.  We clearly can't make curse_state, enchantment, and
-	 * monster_id _all_ optional, since ",random" would be ambiguous.
-	 * We can't even just make enchantment mandatory, since if we do that
-	 * alone, ",random" requires too much lookahead to parse.
-	 */
+		      long cnt = 0;
+		      if (in_container_obj) cnt |= SP_OBJ_CONTENT;
+		      add_opvars(splev, "io", cnt, SPO_OBJECT);
+		      if ( 1 == $2 ) {
+			  if (n_if_list > 0) {
+			      struct opvar *tmpjmp;
+			      tmpjmp = (struct opvar *) if_list[--n_if_list];
+			      set_opvar_int(tmpjmp, splev->n_opcodes - tmpjmp->vardata.l);
+			  } else lc_error("conditional creation of obj, but no jump point marker.");
 		  }
-		| ',' curse_state ',' monster_id ',' enchantment optional_name
+		  }
+		| COBJECT_ID chance ':' object_desc
 		  {
+		      long cnt = SP_OBJ_CONTAINER;
+		      if (in_container_obj) cnt |= SP_OBJ_CONTENT;
+		      add_opvars(splev, "io", cnt, SPO_OBJECT);
+		      $<i>$ = $2;
+		      in_container_obj++;
 		  }
-		| ',' curse_state ',' enchantment optional_name
+		'{' levstatements '}'
 		  {
+		     in_container_obj--;
+		     add_opcode(splev, SPO_POP_CONTAINER, NULL);
+
+		     if ( 1 == $<i>5 ) {
+			 if (n_if_list > 0) {
+			     struct opvar *tmpjmp;
+			     tmpjmp = (struct opvar *) if_list[--n_if_list];
+			     set_opvar_int(tmpjmp, splev->n_opcodes - tmpjmp->vardata.l);
+			 } else lc_error("Conditional creation of obj, but no jump point marker.");
 		  }
-		| ',' monster_id ',' enchantment optional_name
+		 }
+		;
+
+object_desc	: object_or_var object_infos
 		  {
+		      if (( $2 & 0x4000) && in_container_obj) lc_error("Object cannot have a coord when contained.");
+		      else if (!( $2 & 0x4000) && !in_container_obj) lc_error("Object needs a coord when not contained.");
 		  }
 		;
 
-curse_state	: RANDOM_TYPE
+object_infos	: /* nothing */
 		  {
-			tmpobj[nobj]->curse_state = -1;
+		      struct opvar *stopit = New(struct opvar);
+		      set_opvar_int(stopit, SP_O_V_END);
+		      add_opcode(splev, SPO_PUSH, stopit);
+		      $$ = 0x00;
 		  }
-		| CURSE_TYPE
+		| object_infos ',' object_info
 		  {
-			tmpobj[nobj]->curse_state = $1;
+		      if (( $1 & $3 ))
+			  lc_error("OBJECT extra info defined twice.");
+		      $$ = ( $1 | $3 );
 		  }
 		;
 
-monster_id	: STRING
+object_info	: CURSE_TYPE
 		  {
-			int token = get_monster_id($1, (char)0);
-			if (token == ERR)	/* "random" */
-			    tmpobj[nobj]->corpsenm = NON_PM - 1;
-			else
-			    tmpobj[nobj]->corpsenm = token;
-			Free($1);
+		      add_opvars(splev, "ii", (long)$1, SP_O_V_CURSE);
+		      $$ = 0x0001;
 		  }
-		;
-
-enchantment	: RANDOM_TYPE
+		| MONTYPE_ID ':' monster_or_var
 		  {
-			tmpobj[nobj]->spe = -127;
+		      add_opvars(splev, "i", SP_O_V_CORPSENM);
+		      $$ = 0x0002;
 		  }
-		| INTEGER
+		| all_ints_push
 		  {
-			tmpobj[nobj]->spe = $1;
+		      add_opvars(splev, "i", SP_O_V_SPE);
+		      $$ = 0x0004;
 		  }
-		;
-
-optional_name	: /* nothing */
-		| ',' NONE
+		| NAME_ID ':' string_expr
 		  {
+		      add_opvars(splev, "i", SP_O_V_NAME);
+		      $$ = 0x0008;
 		  }
-		| ',' STRING
+		| QUANTITY_ID ':' integer_or_var
 		  {
-			tmpobj[nobj]->name.str = $2;
+		      add_opvars(splev, "i", SP_O_V_QUAN);
+		      $$ = 0x0010;
 		  }
-		;
-
-door_detail	: DOOR_ID ':' door_state ',' coordinate
+		| BURIED_ID
 		  {
-			tmpdoor[ndoor] = New(door);
-			tmpdoor[ndoor]->x = current_coord.x;
-			tmpdoor[ndoor]->y = current_coord.y;
-			tmpdoor[ndoor]->mask = $<i>3;
-			if(current_coord.x >= 0 && current_coord.y >= 0 &&
-			   tmpmap[current_coord.y][current_coord.x] != DOOR &&
-			   tmpmap[current_coord.y][current_coord.x] != SDOOR)
-			    yyerror("Door decl doesn't match the map");
-			ndoor++;
-			if (ndoor >= MAX_OF_TYPE) {
-				yyerror("Too many doors in mazepart!");
-				ndoor--;
+		      add_opvars(splev, "ii", 1, SP_O_V_BURIED);
+		      $$ = 0x0020;
 			}
+		| LIGHT_STATE
+		  {
+		      add_opvars(splev, "ii", (long)$1, SP_O_V_LIT);
+		      $$ = 0x0040;
 		  }
-		;
-
-trap_detail	: TRAP_ID chance ':' trap_name ',' coordinate
+		| ERODED_ID ':' integer_or_var
 		  {
-			tmptrap[ntrap] = New(trap);
-			tmptrap[ntrap]->x = current_coord.x;
-			tmptrap[ntrap]->y = current_coord.y;
-			tmptrap[ntrap]->type = $<i>4;
-			tmptrap[ntrap]->chance = $2;
-			if (!in_room)
-			    check_coord(current_coord.x, current_coord.y,
-					"Trap");
-			if (++ntrap >= MAX_OF_TYPE) {
-				yyerror("Too many traps in room or mazepart!");
-				ntrap--;
+		      add_opvars(splev, "i", SP_O_V_ERODED);
+		      $$ = 0x0080;
 			}
+		| ERODEPROOF_ID
+		  {
+		      add_opvars(splev, "ii", -1, SP_O_V_ERODED);
+		      $$ = 0x0080;
 		  }
-		;
-
-drawbridge_detail: DRAWBRIDGE_ID ':' coordinate ',' DIRECTION ',' door_state
+		| DOOR_STATE
 		   {
-		        int x, y, dir;
-
-			tmpdb[ndb] = New(drawbridge);
-			x = tmpdb[ndb]->x = current_coord.x;
-			y = tmpdb[ndb]->y = current_coord.y;
-			/* convert dir from a DIRECTION to a DB_DIR */
-			dir = $5;
-			switch(dir) {
-			case W_NORTH: dir = DB_NORTH; y--; break;
-			case W_SOUTH: dir = DB_SOUTH; y++; break;
-			case W_EAST:  dir = DB_EAST;  x++; break;
-			case W_WEST:  dir = DB_WEST;  x--; break;
-			default:
-			    yyerror("Invalid drawbridge direction");
-			    break;
+		      if ($1 == D_LOCKED) {
+			  add_opvars(splev, "ii", 1, SP_O_V_LOCKED);
+			  $$ = 0x0100;
+		      } else if ($1 == D_BROKEN) {
+			  add_opvars(splev, "ii", 1, SP_O_V_BROKEN);
+			  $$ = 0x0200;
+		      } else
+			  lc_error("OBJECT state can only be locked or broken.");
 			}
-			tmpdb[ndb]->dir = dir;
-			if (current_coord.x >= 0 && current_coord.y >= 0 &&
-			    !IS_WALL(tmpmap[y][x])) {
-			    char ebuf[60];
-			    Sprintf(ebuf,
-				    "Wall needed for drawbridge (%02d, %02d)",
-				    current_coord.x, current_coord.y);
-			    yyerror(ebuf);
+		| TRAPPED_ID
+		  {
+		      add_opvars(splev, "ii", 1, SP_O_V_TRAPPED);
+		      $$ = 0x0400;
 			}
-
-			if ( $<i>7 == D_ISOPEN )
-			    tmpdb[ndb]->db_open = 1;
-			else if ( $<i>7 == D_CLOSED )
-			    tmpdb[ndb]->db_open = 0;
-			else
-			    yyerror("A drawbridge can only be open or closed!");
-			ndb++;
-			if (ndb >= MAX_OF_TYPE) {
-				yyerror("Too many drawbridges in mazepart!");
-				ndb--;
+		| RECHARGED_ID ':' integer_or_var
+		  {
+		      add_opvars(splev, "i", SP_O_V_RECHARGED);
+		      $$ = 0x0800;
 			}
+		| INVIS_ID
+		  {
+		      add_opvars(splev, "ii", 1, SP_O_V_INVIS);
+		      $$ = 0x1000;
 		   }
-		;
-
-mazewalk_detail : MAZEWALK_ID ':' coordinate ',' DIRECTION
+		| GREASED_ID
 		  {
-			tmpwalk[nwalk] = New(walk);
-			tmpwalk[nwalk]->x = current_coord.x;
-			tmpwalk[nwalk]->y = current_coord.y;
-			tmpwalk[nwalk]->dir = $5;
-			nwalk++;
-			if (nwalk >= MAX_OF_TYPE) {
-				yyerror("Too many mazewalks in mazepart!");
-				nwalk--;
+		      add_opvars(splev, "ii", 1, SP_O_V_GREASED);
+		      $$ = 0x2000;
 			}
+		| coord_or_var
+		  {
+		      add_opvars(splev, "i", SP_O_V_COORD);
+		      $$ = 0x4000;
 		  }
 		;
 
-wallify_detail	: WALLIFY_ID
+trap_detail	: TRAP_ID chance ':' trap_name ',' coord_or_var
 		  {
-			wallify_map();
+		      add_opvars(splev, "io", (long)$4, SPO_TRAP);
+		      if ( 1 == $2 ) {
+			  if (n_if_list > 0) {
+			      struct opvar *tmpjmp;
+			      tmpjmp = (struct opvar *) if_list[--n_if_list];
+			      set_opvar_int(tmpjmp, splev->n_opcodes - tmpjmp->vardata.l);
+			  } else lc_error("Conditional creation of trap, but no jump point marker.");
+		      }
 		  }
 		;
 
-ladder_detail	: LADDER_ID ':' coordinate ',' UP_OR_DOWN
+drawbridge_detail: DRAWBRIDGE_ID ':' coord_or_var ',' DIRECTION ',' door_state
 		  {
-			tmplad[nlad] = New(lad);
-			tmplad[nlad]->x = current_coord.x;
-			tmplad[nlad]->y = current_coord.y;
-			tmplad[nlad]->up = $<i>5;
-			if (!in_room)
-			    check_coord(current_coord.x, current_coord.y,
-					"Ladder");
-			nlad++;
-			if (nlad >= MAX_OF_TYPE) {
-				yyerror("Too many ladders in mazepart!");
-				nlad--;
+		       long d, state = 0;
+		       /* convert dir from a DIRECTION to a DB_DIR */
+		       d = $5;
+		       switch(d) {
+		       case W_NORTH: d = DB_NORTH; break;
+		       case W_SOUTH: d = DB_SOUTH; break;
+		       case W_EAST:  d = DB_EAST;  break;
+		       case W_WEST:  d = DB_WEST;  break;
+		       default:
+			   lc_error("Invalid drawbridge direction.");
+			   break;
 			}
+
+		       if ( $7 == D_ISOPEN )
+			   state = 1;
+		       else if ( $7 == D_CLOSED )
+			   state = 0;
+		       else
+			   lc_error("A drawbridge can only be open or closed!");
+		       add_opvars(splev, "iio", state, d, SPO_DRAWBRIDGE);
 		  }
 		;
 
-stair_detail	: STAIR_ID ':' coordinate ',' UP_OR_DOWN
+mazewalk_detail : MAZEWALK_ID ':' coord_or_var ',' DIRECTION
 		  {
-			tmpstair[nstair] = New(stair);
-			tmpstair[nstair]->x = current_coord.x;
-			tmpstair[nstair]->y = current_coord.y;
-			tmpstair[nstair]->up = $<i>5;
-			if (!in_room)
-			    check_coord(current_coord.x, current_coord.y,
-					"Stairway");
-			nstair++;
-			if (nstair >= MAX_OF_TYPE) {
-				yyerror("Too many stairs in room or mazepart!");
-				nstair--;
+		      add_opvars(splev, "iiio",
+				 (long)$5, 1, 0, SPO_MAZEWALK);
 			}
+		| MAZEWALK_ID ':' coord_or_var ',' DIRECTION ',' BOOLEAN opt_fillchar
+		  {
+		      add_opvars(splev, "iiio",
+				 (long)$5, (long)$<i>7, (long)$8, SPO_MAZEWALK);
 		  }
 		;
 
-stair_region	: STAIR_ID ':' lev_region
+wallify_detail	: WALLIFY_ID
 		  {
-			tmplreg[nlreg] = New(lev_region);
-			tmplreg[nlreg]->in_islev = $3;
-			tmplreg[nlreg]->inarea.x1 = current_region.x1;
-			tmplreg[nlreg]->inarea.y1 = current_region.y1;
-			tmplreg[nlreg]->inarea.x2 = current_region.x2;
-			tmplreg[nlreg]->inarea.y2 = current_region.y2;
+		      add_opvars(splev, "ro", SP_REGION_PACK(-1,-1,-1,-1), SPO_WALLIFY);
 		  }
-		 ',' lev_region ',' UP_OR_DOWN
+		| WALLIFY_ID ':' region_or_var
 		  {
-			tmplreg[nlreg]->del_islev = $6;
-			tmplreg[nlreg]->delarea.x1 = current_region.x1;
-			tmplreg[nlreg]->delarea.y1 = current_region.y1;
-			tmplreg[nlreg]->delarea.x2 = current_region.x2;
-			tmplreg[nlreg]->delarea.y2 = current_region.y2;
-			if($8)
-			    tmplreg[nlreg]->rtype = LR_UPSTAIR;
-			else
-			    tmplreg[nlreg]->rtype = LR_DOWNSTAIR;
-			tmplreg[nlreg]->rname.str = 0;
-			nlreg++;
-			if (nlreg >= MAX_OF_TYPE) {
-				yyerror("Too many levregions in mazepart!");
-				nlreg--;
-			}
+		      add_opvars(splev, "o", SPO_WALLIFY);
 		  }
 		;
 
-portal_region	: PORTAL_ID ':' lev_region
+ladder_detail	: LADDER_ID ':' coord_or_var ',' UP_OR_DOWN
 		  {
-			tmplreg[nlreg] = New(lev_region);
-			tmplreg[nlreg]->in_islev = $3;
-			tmplreg[nlreg]->inarea.x1 = current_region.x1;
-			tmplreg[nlreg]->inarea.y1 = current_region.y1;
-			tmplreg[nlreg]->inarea.x2 = current_region.x2;
-			tmplreg[nlreg]->inarea.y2 = current_region.y2;
+		      add_opvars(splev, "io", (long)$<i>5, SPO_LADDER);
 		  }
-		 ',' lev_region ',' string
+		;
+
+stair_detail	: STAIR_ID ':' coord_or_var ',' UP_OR_DOWN
 		  {
-			tmplreg[nlreg]->del_islev = $6;
-			tmplreg[nlreg]->delarea.x1 = current_region.x1;
-			tmplreg[nlreg]->delarea.y1 = current_region.y1;
-			tmplreg[nlreg]->delarea.x2 = current_region.x2;
-			tmplreg[nlreg]->delarea.y2 = current_region.y2;
-			tmplreg[nlreg]->rtype = LR_PORTAL;
-			tmplreg[nlreg]->rname.str = $8;
-			nlreg++;
-			if (nlreg >= MAX_OF_TYPE) {
-				yyerror("Too many levregions in mazepart!");
-				nlreg--;
-			}
+		      add_opvars(splev, "io", (long)$<i>5, SPO_STAIR);
 		  }
 		;
 
-teleprt_region	: TELEPRT_ID ':' lev_region
+stair_region	: STAIR_ID ':' lev_region ',' lev_region ',' UP_OR_DOWN
 		  {
-			tmplreg[nlreg] = New(lev_region);
-			tmplreg[nlreg]->in_islev = $3;
-			tmplreg[nlreg]->inarea.x1 = current_region.x1;
-			tmplreg[nlreg]->inarea.y1 = current_region.y1;
-			tmplreg[nlreg]->inarea.x2 = current_region.x2;
-			tmplreg[nlreg]->inarea.y2 = current_region.y2;
+		      add_opvars(splev, "iiiii iiiii iiso",
+				 $3.x1, $3.y1, $3.x2, $3.y2, $3.area,
+				 $5.x1, $5.y1, $5.x2, $5.y2, $5.area,
+				 (long)(($7) ? LR_UPSTAIR : LR_DOWNSTAIR),
+				 0, (char *)0, SPO_LEVREGION);
 		  }
-		 ',' lev_region
+		;
+
+portal_region	: PORTAL_ID ':' lev_region ',' lev_region ',' string
 		  {
-			tmplreg[nlreg]->del_islev = $6;
-			tmplreg[nlreg]->delarea.x1 = current_region.x1;
-			tmplreg[nlreg]->delarea.y1 = current_region.y1;
-			tmplreg[nlreg]->delarea.x2 = current_region.x2;
-			tmplreg[nlreg]->delarea.y2 = current_region.y2;
+		      add_opvars(splev, "iiiii iiiii iiso",
+				 $3.x1, $3.y1, $3.x2, $3.y2, $3.area,
+				 $5.x1, $5.y1, $5.x2, $5.y2, $5.area,
+				 LR_PORTAL, 0, $7, SPO_LEVREGION);
+		      Free($7);
 		  }
-		teleprt_detail
+		;
+
+teleprt_region	: TELEPRT_ID ':' lev_region ',' lev_region teleprt_detail
 		  {
-			switch($<i>8) {
-			case -1: tmplreg[nlreg]->rtype = LR_TELE; break;
-			case 0: tmplreg[nlreg]->rtype = LR_DOWNTELE; break;
-			case 1: tmplreg[nlreg]->rtype = LR_UPTELE; break;
-			}
-			tmplreg[nlreg]->rname.str = 0;
-			nlreg++;
-			if (nlreg >= MAX_OF_TYPE) {
-				yyerror("Too many levregions in mazepart!");
-				nlreg--;
+		      long rtype;
+		      switch($6) {
+		      case -1: rtype = LR_TELE; break;
+		      case  0: rtype = LR_DOWNTELE; break;
+		      case  1: rtype = LR_UPTELE; break;
 			}
+		      add_opvars(splev, "iiiii iiiii iiso",
+				 $3.x1, $3.y1, $3.x2, $3.y2, $3.area,
+				 $5.x1, $5.y1, $5.x2, $5.y2, $5.area,
+				 rtype, 0, (char *)0, SPO_LEVREGION);
 		  }
 		;
 
-branch_region	: BRANCH_ID ':' lev_region
-		  {
-			tmplreg[nlreg] = New(lev_region);
-			tmplreg[nlreg]->in_islev = $3;
-			tmplreg[nlreg]->inarea.x1 = current_region.x1;
-			tmplreg[nlreg]->inarea.y1 = current_region.y1;
-			tmplreg[nlreg]->inarea.x2 = current_region.x2;
-			tmplreg[nlreg]->inarea.y2 = current_region.y2;
-		  }
-		 ',' lev_region
+branch_region	: BRANCH_ID ':' lev_region ',' lev_region
 		  {
-			tmplreg[nlreg]->del_islev = $6;
-			tmplreg[nlreg]->delarea.x1 = current_region.x1;
-			tmplreg[nlreg]->delarea.y1 = current_region.y1;
-			tmplreg[nlreg]->delarea.x2 = current_region.x2;
-			tmplreg[nlreg]->delarea.y2 = current_region.y2;
-			tmplreg[nlreg]->rtype = LR_BRANCH;
-			tmplreg[nlreg]->rname.str = 0;
-			nlreg++;
-			if (nlreg >= MAX_OF_TYPE) {
-				yyerror("Too many levregions in mazepart!");
-				nlreg--;
-			}
+		      add_opvars(splev, "iiiii iiiii iiso",
+				 $3.x1, $3.y1, $3.x2, $3.y2, $3.area,
+				 $5.x1, $5.y1, $5.x2, $5.y2, $5.area,
+				 (long)LR_BRANCH, 0, (char *)0, SPO_LEVREGION);
 		  }
 		;
@@ -1243,254 +1664,156 @@
 teleprt_detail	: /* empty */
 		  {
-			$<i>$ = -1;
+			$$ = -1;
 		  }
 		| ',' UP_OR_DOWN
 		  {
-			$<i>$ = $2;
+			$$ = $2;
 		  }
 		;
 
-lev_region	: region
-		  {
-			$$ = 0;
-		  }
-		| LEV '(' INTEGER ',' INTEGER ',' INTEGER ',' INTEGER ')'
+fountain_detail : FOUNTAIN_ID ':' ter_selection
 		  {
-/* This series of if statements is a hack for MSC 5.1.  It seems that its
-   tiny little brain cannot compile if these are all one big if statement. */
-			if ($3 <= 0 || $3 >= COLNO)
-				yyerror("Region out of level range!");
-			else if ($5 < 0 || $5 >= ROWNO)
-				yyerror("Region out of level range!");
-			else if ($7 <= 0 || $7 >= COLNO)
-				yyerror("Region out of level range!");
-			else if ($9 < 0 || $9 >= ROWNO)
-				yyerror("Region out of level range!");
-			current_region.x1 = $3;
-			current_region.y1 = $5;
-			current_region.x2 = $7;
-			current_region.y2 = $9;
-			$$ = 1;
+		      add_opvars(splev, "o", SPO_FOUNTAIN);
 		  }
 		;
 
-fountain_detail : FOUNTAIN_ID ':' coordinate
+sink_detail : SINK_ID ':' ter_selection
 		  {
-			tmpfountain[nfountain] = New(fountain);
-			tmpfountain[nfountain]->x = current_coord.x;
-			tmpfountain[nfountain]->y = current_coord.y;
-			if (!in_room)
-			    check_coord(current_coord.x, current_coord.y,
-					"Fountain");
-			nfountain++;
-			if (nfountain >= MAX_OF_TYPE) {
-			    yyerror("Too many fountains in room or mazepart!");
-			    nfountain--;
-			}
+		      add_opvars(splev, "o", SPO_SINK);
 		  }
 		;
 
-sink_detail : SINK_ID ':' coordinate
+pool_detail : POOL_ID ':' ter_selection
 		  {
-			tmpsink[nsink] = New(sink);
-			tmpsink[nsink]->x = current_coord.x;
-			tmpsink[nsink]->y = current_coord.y;
-			nsink++;
-			if (nsink >= MAX_OF_TYPE) {
-				yyerror("Too many sinks in room!");
-				nsink--;
-			}
+		      add_opvars(splev, "o", SPO_POOL);
 		  }
 		;
 
-pool_detail : POOL_ID ':' coordinate
+terrain_type	: CHAR
 		  {
-			tmppool[npool] = New(pool);
-			tmppool[npool]->x = current_coord.x;
-			tmppool[npool]->y = current_coord.y;
-			npool++;
-			if (npool >= MAX_OF_TYPE) {
-				yyerror("Too many pools in room!");
-				npool--;
+		      $$.lit = -2;
+		      $$.ter = what_map_char((char) $<i>1);
 			}
+		| '(' CHAR ',' light_state ')'
+		  {
+		      $$.lit = $4;
+		      $$.ter = what_map_char((char) $<i>2);
 		  }
 		;
 
-diggable_detail : NON_DIGGABLE_ID ':' region
+replace_terrain_detail : REPLACE_TERRAIN_ID ':' region_or_var ',' mapchar_or_var ',' mapchar_or_var ',' SPERCENT
 		  {
-			tmpdig[ndig] = New(digpos);
-			tmpdig[ndig]->x1 = current_region.x1;
-			tmpdig[ndig]->y1 = current_region.y1;
-			tmpdig[ndig]->x2 = current_region.x2;
-			tmpdig[ndig]->y2 = current_region.y2;
-			ndig++;
-			if (ndig >= MAX_OF_TYPE) {
-				yyerror("Too many diggables in mazepart!");
-				ndig--;
-			}
+		      long chance;
+
+		      chance = $9;
+		      if (chance < 0) chance = 0;
+		      else if (chance > 100) chance = 100;
+		      add_opvars(splev, "io", chance, SPO_REPLACETERRAIN);
 		  }
 		;
 
-passwall_detail : NON_PASSWALL_ID ':' region
+terrain_detail : TERRAIN_ID chance ':' ter_selection ',' mapchar_or_var
 		  {
-			tmppass[npass] = New(digpos);
-			tmppass[npass]->x1 = current_region.x1;
-			tmppass[npass]->y1 = current_region.y1;
-			tmppass[npass]->x2 = current_region.x2;
-			tmppass[npass]->y2 = current_region.y2;
-			npass++;
-			if (npass >= 32) {
-				yyerror("Too many passwalls in mazepart!");
-				npass--;
+		     add_opvars(splev, "o", SPO_TERRAIN);
+
+		     if ( 1 == $2 ) {
+			 if (n_if_list > 0) {
+			     struct opvar *tmpjmp;
+			     tmpjmp = (struct opvar *) if_list[--n_if_list];
+			     set_opvar_int(tmpjmp, splev->n_opcodes - tmpjmp->vardata.l);
+			 } else lc_error("Conditional terrain modification, but no jump point marker.");
 			}
 		  }
 		;
 
-region_detail	: REGION_ID ':' region ',' light_state ',' room_type prefilled
+spill_detail : SPILL_ID ':' coord_or_var ',' terrain_type ',' DIRECTION ',' INTEGER
 		  {
-			tmpreg[nreg] = New(region);
-			tmpreg[nreg]->x1 = current_region.x1;
-			tmpreg[nreg]->y1 = current_region.y1;
-			tmpreg[nreg]->x2 = current_region.x2;
-			tmpreg[nreg]->y2 = current_region.y2;
-			tmpreg[nreg]->rlit = $<i>5;
-			tmpreg[nreg]->rtype = $<i>7;
-			if($<i>8 & 1) tmpreg[nreg]->rtype += MAXRTYPE+1;
-			tmpreg[nreg]->rirreg = (($<i>8 & 2) != 0);
-			if(current_region.x1 > current_region.x2 ||
-			   current_region.y1 > current_region.y2)
-			   yyerror("Region start > end!");
-			if(tmpreg[nreg]->rtype == VAULT &&
-			   (tmpreg[nreg]->rirreg ||
-			    (tmpreg[nreg]->x2 - tmpreg[nreg]->x1 != 1) ||
-			    (tmpreg[nreg]->y2 - tmpreg[nreg]->y1 != 1)))
-				yyerror("Vaults must be exactly 2x2!");
-			if(want_warnings && !tmpreg[nreg]->rirreg &&
-			   current_region.x1 > 0 && current_region.y1 > 0 &&
-			   current_region.x2 < (int)max_x_map &&
-			   current_region.y2 < (int)max_y_map) {
-			    /* check for walls in the room */
-			    char ebuf[60];
-			    register int x, y, nrock = 0;
+		    long c, typ;
 
-			    for(y=current_region.y1; y<=current_region.y2; y++)
-				for(x=current_region.x1;
-				    x<=current_region.x2; x++)
-				    if(IS_ROCK(tmpmap[y][x]) ||
-				       IS_DOOR(tmpmap[y][x])) nrock++;
-			    if(nrock) {
-				Sprintf(ebuf,
-					"Rock in room (%02d,%02d,%02d,%02d)?!",
-					current_region.x1, current_region.y1,
-					current_region.x2, current_region.y2);
-				yywarning(ebuf);
-			    }
-			    if (
-		!IS_ROCK(tmpmap[current_region.y1-1][current_region.x1-1]) ||
-		!IS_ROCK(tmpmap[current_region.y2+1][current_region.x1-1]) ||
-		!IS_ROCK(tmpmap[current_region.y1-1][current_region.x2+1]) ||
-		!IS_ROCK(tmpmap[current_region.y2+1][current_region.x2+1])) {
-				Sprintf(ebuf,
-				"NonRock edge in room (%02d,%02d,%02d,%02d)?!",
-					current_region.x1, current_region.y1,
-					current_region.x2, current_region.y2);
-				yywarning(ebuf);
-			    }
-			} else if(tmpreg[nreg]->rirreg &&
-		!IS_ROOM(tmpmap[current_region.y1][current_region.x1])) {
-			    char ebuf[60];
-			    Sprintf(ebuf,
-				    "Rock in irregular room (%02d,%02d)?!",
-				    current_region.x1, current_region.y1);
-			    yyerror(ebuf);
-			}
-			nreg++;
-			if (nreg >= MAX_OF_TYPE) {
-				yyerror("Too many regions in mazepart!");
-				nreg--;
+		    typ = $5.ter;
+		    if (typ == INVALID_TYPE || typ >= MAX_TYPE) {
+			lc_error("SPILL: Invalid map character!");
 			}
+
+		    c = $9;
+		    if (c < 1) lc_error("SPILL: Invalid count '%li'!", c);
+
+		    add_opvars(splev, "iiiio", typ, (long)$7, c, (long)$5.lit, SPO_SPILL);
 		  }
 		;
 
-altar_detail	: ALTAR_ID ':' coordinate ',' alignment ',' altar_type
+diggable_detail : NON_DIGGABLE_ID ':' region_or_var
 		  {
-			tmpaltar[naltar] = New(altar);
-			tmpaltar[naltar]->x = current_coord.x;
-			tmpaltar[naltar]->y = current_coord.y;
-			tmpaltar[naltar]->align = $<i>5;
-			tmpaltar[naltar]->shrine = $<i>7;
-			if (!in_room)
-			    check_coord(current_coord.x, current_coord.y,
-					"Altar");
-			naltar++;
-			if (naltar >= MAX_OF_TYPE) {
-				yyerror("Too many altars in room or mazepart!");
-				naltar--;
+		     add_opvars(splev, "o", SPO_NON_DIGGABLE);
 			}
+		;
+
+passwall_detail : NON_PASSWALL_ID ':' region_or_var
+		  {
+		     add_opvars(splev, "o", SPO_NON_PASSWALL);
 		  }
 		;
 
-gold_detail	: GOLD_ID ':' amount ',' coordinate
+region_detail	: REGION_ID ':' region_or_var ',' light_state ',' room_type prefilled
 		  {
-			tmpgold[ngold] = New(gold);
-			tmpgold[ngold]->x = current_coord.x;
-			tmpgold[ngold]->y = current_coord.y;
-			tmpgold[ngold]->amount = $<i>3;
-			if (!in_room)
-			    check_coord(current_coord.x, current_coord.y,
-					"Gold");
-			ngold++;
-			if (ngold >= MAX_OF_TYPE) {
-				yyerror("Too many golds in room or mazepart!");
-				ngold--;
+		      long rt, irr;
+		      rt = $7;
+		      if (( $8 ) & 1) rt += MAXRTYPE+1;
+		      irr = ((( $8 ) & 2) != 0);
+		      add_opvars(splev, "iiio",
+				 (long)$5, rt, irr, SPO_REGION);
+		      $<i>$ = (irr || ($8 & 1) || rt != OROOM);
 			}
+		  region_detail_end
+		  {
+		      if ( $<i>9 ) {
+			  add_opcode(splev, SPO_ENDROOM, NULL);
+		      } else if ( $<i>10 )
+			  lc_error("Cannot use lev statements in non-permanent REGION");
 		  }
 		;
 
-engraving_detail: ENGRAVING_ID ':' coordinate ',' engraving_type ',' string
+region_detail_end : /* nothing */
 		  {
-			tmpengraving[nengraving] = New(engraving);
-			tmpengraving[nengraving]->x = current_coord.x;
-			tmpengraving[nengraving]->y = current_coord.y;
-			tmpengraving[nengraving]->engr.str = $7;
-			tmpengraving[nengraving]->etype = $<i>5;
-			if (!in_room)
-			    check_coord(current_coord.x, current_coord.y,
-					"Engraving");
-			nengraving++;
-			if (nengraving >= MAX_OF_TYPE) {
-			    yyerror("Too many engravings in room or mazepart!");
-			    nengraving--;
+		      $$ = 0;
 			}
+		| '{' levstatements '}'
+		  {
+		      $$ = $2;
 		  }
 		;
 
-monster_c	: monster
-		| RANDOM_TYPE
+altar_detail	: ALTAR_ID ':' coord_or_var ',' alignment ',' altar_type
 		  {
-			$<i>$ = - MAX_REGISTERS - 1;
+		      add_opvars(splev, "iio", (long)$7, (long)$5, SPO_ALTAR);
 		  }
-		| m_register
 		;
 
-object_c	: object
-		| RANDOM_TYPE
+grave_detail	: GRAVE_ID ':' coord_or_var ',' string_expr
 		  {
-			$<i>$ = - MAX_REGISTERS - 1;
+		      add_opvars(splev, "io", 2, SPO_GRAVE);
+		  }
+		| GRAVE_ID ':' coord_or_var ',' RANDOM_TYPE
+		  {
+		      add_opvars(splev, "sio",
+				 (char *)0, 1, SPO_GRAVE);
+		  }
+		| GRAVE_ID ':' coord_or_var
+		  {
+		      add_opvars(splev, "sio",
+				 (char *)0, 0, SPO_GRAVE);
 		  }
-		| o_register
 		;
 
-m_name		: string
-		| RANDOM_TYPE
+gold_detail	: GOLD_ID ':' math_expr ',' coord_or_var
 		  {
-			$$ = (char *) 0;
+		      add_opvars(splev, "o", SPO_GOLD);
 		  }
 		;
 
-o_name		: string
-		| RANDOM_TYPE
+engraving_detail: ENGRAVING_ID ':' coord_or_var ',' engraving_type ',' string_expr
 		  {
-			$$ = (char *) 0;
+		      add_opvars(splev, "io",
+				 (long)$5, SPO_ENGRAVING);
 		  }
 		;
@@ -1500,6 +1823,6 @@
 			int token = get_trap_type($1);
 			if (token == ERR)
-				yyerror("Unknown trap type!");
-			$<i>$ = token;
+			    lc_error("Unknown trap type '%s'!", $1);
+			$$ = token;
 			Free($1);
 		  }
@@ -1511,8 +1834,8 @@
 			int token = get_room_type($1);
 			if (token == ERR) {
-				yywarning("Unknown room type!  Making ordinary room...");
-				$<i>$ = OROOM;
+			    lc_warning("Unknown room type \"%s\"!  Making ordinary room...", $1);
+				$$ = OROOM;
 			} else
-				$<i>$ = token;
+				$$ = token;
 			Free($1);
 		  }
@@ -1522,21 +1845,13 @@
 prefilled	: /* empty */
 		  {
-			$<i>$ = 0;
+			$$ = 0;
 		  }
 		| ',' FILLING
 		  {
-			$<i>$ = $2;
+			$$ = $2;
 		  }
 		| ',' FILLING ',' BOOLEAN
 		  {
-			$<i>$ = $2 + ($4 << 1);
-		  }
-		;
-
-coordinate	: coord
-		| p_register
-		| RANDOM_TYPE
-		  {
-			current_coord.x = current_coord.y = -MAX_REGISTERS-1;
+			$$ = $2 + ($4 << 1);
 		  }
 		;
@@ -1554,5 +1869,13 @@
 		| RANDOM_TYPE
 		  {
-			$<i>$ = - MAX_REGISTERS - 1;
+			$$ = - MAX_REGISTERS - 1;
+		  }
+		;
+
+alignment_prfx	: ALIGNMENT
+		| a_register
+		| A_REGISTER ':' RANDOM_TYPE
+		  {
+			$$ = - MAX_REGISTERS - 1;
 		  }
 		;
@@ -1562,82 +1885,424 @@
 		;
 
-p_register	: P_REGISTER '[' INTEGER ']'
+a_register	: A_REGISTER '[' INTEGER ']'
 		  {
-			if ( $3 >= MAX_REGISTERS )
-				yyerror("Register Index overflow!");
+			if ( $3 >= 3 )
+				lc_error("Register Index overflow!");
 			else
-				current_coord.x = current_coord.y = - $3 - 1;
+				$$ = - $3 - 1;
 		  }
 		;
 
-o_register	: O_REGISTER '[' INTEGER ']'
+monster		: CHAR
 		  {
-			if ( $3 >= MAX_REGISTERS )
-				yyerror("Register Index overflow!");
-			else
-				$<i>$ = - $3 - 1;
+			if (check_monster_char((char) $1))
+				$$ = $1 ;
+			else {
+			    lc_error("Unknown monster class '%c'!", $1);
+			    $$ = ERR;
+			}
 		  }
 		;
 
-m_register	: M_REGISTER '[' INTEGER ']'
+string_or_var	: STRING
 		  {
-			if ( $3 >= MAX_REGISTERS )
-				yyerror("Register Index overflow!");
-			else
-				$<i>$ = - $3 - 1;
+		      add_opvars(splev, "s", $1);
+		      Free($1);
+		  }
+		| VARSTRING_STRING
+		  {
+		      check_vardef_type(variable_definitions, $1, SPOVAR_STRING);
+		      add_opvars(splev, "v", $1);
+		      Free($1);
+		  }
+		| VARSTRING_STRING_ARRAY '[' math_expr ']'
+		  {
+		      check_vardef_type(variable_definitions, $1, SPOVAR_STRING|SPOVAR_ARRAY);
+		      add_opvars(splev, "v", $1);
+		      Free($1);
 		  }
 		;
 
-a_register	: A_REGISTER '[' INTEGER ']'
+
+integer_or_var	: math_expr_var
 		  {
-			if ( $3 >= 3 )
-				yyerror("Register Index overflow!");
-			else
-				$<i>$ = - $3 - 1;
+		      /* nothing */
 		  }
 		;
 
-place		: coord
+coord_or_var	: encodecoord
+		  {
+		      add_opvars(splev, "c", $1);
+		  }
+		| rndcoord_ID '(' ter_selection ')'
+		  {
+		      add_opvars(splev, "o", SPO_SEL_RNDCOORD);
+		  }
+		| VARSTRING_COORD
+		  {
+		      check_vardef_type(variable_definitions, $1, SPOVAR_COORD);
+		      add_opvars(splev, "v", $1);
+		      Free($1);
+		  }
+		| VARSTRING_COORD_ARRAY '[' math_expr ']'
+		  {
+		      check_vardef_type(variable_definitions, $1, SPOVAR_COORD|SPOVAR_ARRAY);
+		      add_opvars(splev, "v", $1);
+		      Free($1);
+		  }
 		;
 
-monster		: CHAR
+encodecoord	: '(' INTEGER ',' INTEGER ')'
 		  {
-			if (check_monster_char((char) $1))
-				$<i>$ = $1 ;
+		      if ($2 < 0 || $4 < 0 || $2 >= COLNO || $4 >= ROWNO)
+			  lc_error("Coordinates (%li,%li) out of map range!", $2, $4);
+		      $$ = SP_COORD_PACK($2, $4);
+		  }
+		| RANDOM_TYPE
+		  {
+		      $$ = SP_COORD_PACK(-1,-1);
+		  }
+		;
+
+region_or_var	: encoderegion
+		  {
+		      add_opvars(splev, "r", $1);
+		  }
+		| VARSTRING_REGION
+		  {
+		      check_vardef_type(variable_definitions, $1, SPOVAR_REGION);
+		      add_opvars(splev, "v", $1);
+		      Free($1);
+		  }
+		| VARSTRING_REGION_ARRAY '[' math_expr ']'
+		  {
+		      check_vardef_type(variable_definitions, $1, SPOVAR_REGION|SPOVAR_ARRAY);
+		      add_opvars(splev, "v", $1);
+		      Free($1);
+		  }
+		;
+
+encoderegion	: '(' INTEGER ',' INTEGER ',' INTEGER ',' INTEGER ')'
+		  {
+		      if ( $2 > $6 || $4 > $8 )
+			  lc_error("Region start > end: (%li,%li,%li,%li)!", $2, $4, $6, $8);
+
+		      $$ = SP_REGION_PACK($2, $4, $6, $8);
+		  }
+		;
+
+mapchar_or_var	: mapchar
+		  {
+		      add_opvars(splev, "m", $1);
+		  }
+		| VARSTRING_MAPCHAR
+		  {
+		      check_vardef_type(variable_definitions, $1, SPOVAR_MAPCHAR);
+		      add_opvars(splev, "v", $1);
+		      Free($1);
+		  }
+		| VARSTRING_MAPCHAR_ARRAY '[' math_expr ']'
+		  {
+		      check_vardef_type(variable_definitions, $1, SPOVAR_MAPCHAR|SPOVAR_ARRAY);
+		      add_opvars(splev, "v", $1);
+		      Free($1);
+		  }
+		;
+
+mapchar		: CHAR
+		  {
+		      if (what_map_char((char) $1) != INVALID_TYPE)
+			  $$ = SP_MAPCHAR_PACK(what_map_char((char) $1), -2);
 			else {
-				yyerror("Unknown monster class!");
-				$<i>$ = ERR;
+			  lc_error("Unknown map char type '%c'!", $1);
+			  $$ = SP_MAPCHAR_PACK(STONE, -2);
+		      }
+		  }
+		| '(' CHAR ',' light_state ')'
+		  {
+		      if (what_map_char((char) $2) != INVALID_TYPE)
+			  $$ = SP_MAPCHAR_PACK(what_map_char((char) $2), $4);
+		      else {
+			  lc_error("Unknown map char type '%c'!", $2);
+			  $$ = SP_MAPCHAR_PACK(STONE, $4);
 			}
 		  }
 		;
 
-object		: CHAR
+monster_or_var	: encodemonster
 		  {
-			char c = $1;
-			if (check_object_char(c))
-				$<i>$ = c;
+		      add_opvars(splev, "M", $1);
+		  }
+		| VARSTRING_MONST
+		  {
+		      check_vardef_type(variable_definitions, $1, SPOVAR_MONST);
+		      add_opvars(splev, "v", $1);
+		      Free($1);
+		  }
+		| VARSTRING_MONST_ARRAY '[' math_expr ']'
+		  {
+		      check_vardef_type(variable_definitions, $1, SPOVAR_MONST|SPOVAR_ARRAY);
+		      add_opvars(splev, "v", $1);
+		      Free($1);
+		  }
+		;
+
+encodemonster	: STRING
+		  {
+		      long m = get_monster_id($1, (char)0);
+		      if (m == ERR) {
+			  lc_error("Unknown monster \"%s\"!", $1);
+			  $$ == -1;
+		      } else
+			  $$ = SP_MONST_PACK(m, def_monsyms[(int)mons[m].mlet]);
+		  }
+		| CHAR
+		  {
+			if (check_monster_char((char) $1))
+			    $$ = SP_MONST_PACK(-1, $1);
 			else {
-				yyerror("Unknown char class!");
-				$<i>$ = ERR;
+			    lc_error("Unknown monster class '%c'!", $1);
+			    $$ = -1;
 			}
 		  }
+		| '(' CHAR ',' STRING ')'
+		  {
+		      long m = get_monster_id($4, (char) $2);
+		      if (m == ERR) {
+			  lc_error("Unknown monster ('%c', \"%s\")!", $2, $4);
+			  $$ == -1;
+		      } else
+			  $$ = SP_MONST_PACK(m, $2);
+		  }
+		| RANDOM_TYPE
+		  {
+		      $$ = -1;
+		  }
 		;
 
-string		: STRING
+object_or_var	: encodeobj
+		  {
+		      add_opvars(splev, "O", $1);
+		  }
+		| VARSTRING_OBJ
+		  {
+		      check_vardef_type(variable_definitions, $1, SPOVAR_OBJ);
+		      add_opvars(splev, "v", $1);
+		      Free($1);
+		  }
+		| VARSTRING_OBJ_ARRAY '[' math_expr ']'
+		  {
+		      check_vardef_type(variable_definitions, $1, SPOVAR_OBJ|SPOVAR_ARRAY);
+		      add_opvars(splev, "v", $1);
+		      Free($1);
+		  }
 		;
 
-amount		: INTEGER
+encodeobj	: STRING
+		  {
+		      long m = get_object_id($1, (char)0);
+		      if (m == ERR) {
+			  lc_error("Unknown object \"%s\"!", $1);
+			  $$ == -1;
+		      } else
+			  $$ = SP_OBJ_PACK(m, 1); /* obj class != 0 to force generation of a specific item */
+
+		  }
+		| CHAR
+		  {
+			if (check_object_char((char) $1))
+			    $$ = SP_OBJ_PACK(-1, $1);
+			else {
+			    lc_error("Unknown object class '%c'!", $1);
+			    $$ = -1;
+			}
+		  }
+		| '(' CHAR ',' STRING ')'
+		  {
+		      long m = get_object_id($4, (char) $2);
+		      if (m == ERR) {
+			  lc_error("Unknown object ('%c', \"%s\")!", $2, $4);
+			  $$ == -1;
+		      } else
+			  $$ = SP_OBJ_PACK(m, $2);
+		  }
 		| RANDOM_TYPE
+		  {
+		      $$ = -1;
+		  }
+		;
+
+
+string_expr	: string_or_var                 { }
+		| string_expr '.' string_or_var
+		  {
+		      add_opvars(splev, "o", SPO_MATH_ADD);
+		  }
+		;
+
+math_expr_var	: INTEGER                       { add_opvars(splev, "i", $1 ); }
+		| dice				{ }
+		| '(' MINUS_INTEGER ')'         { add_opvars(splev, "i", $2 ); }
+		| VARSTRING_INT
+		  {
+		      check_vardef_type(variable_definitions, $1, SPOVAR_INT);
+		      add_opvars(splev, "v", $1);
+		      Free($1);
+		  }
+		| VARSTRING_INT_ARRAY '[' math_expr ']'
+		  {
+		      check_vardef_type(variable_definitions, $1, SPOVAR_INT|SPOVAR_ARRAY);
+		      add_opvars(splev, "v", $1);
+		      Free($1);
+		  }
+		| math_expr_var '+' math_expr_var       { add_opvars(splev, "o", SPO_MATH_ADD); }
+		| math_expr_var '-' math_expr_var       { add_opvars(splev, "o", SPO_MATH_SUB); }
+		| math_expr_var '*' math_expr_var       { add_opvars(splev, "o", SPO_MATH_MUL); }
+		| math_expr_var '/' math_expr_var       { add_opvars(splev, "o", SPO_MATH_DIV); }
+		| math_expr_var '%' math_expr_var       { add_opvars(splev, "o", SPO_MATH_MOD); }
+		| '(' math_expr ')'             { }
+		;
+
+math_expr	: INTEGER                       { add_opvars(splev, "i", $1 ); }
+		| dice				{ }
+		| '(' MINUS_INTEGER ')'         { add_opvars(splev, "i", $2 ); }
+		| math_expr '+' math_expr       { add_opvars(splev, "o", SPO_MATH_ADD); }
+		| math_expr '-' math_expr       { add_opvars(splev, "o", SPO_MATH_SUB); }
+		| math_expr '*' math_expr       { add_opvars(splev, "o", SPO_MATH_MUL); }
+		| math_expr '/' math_expr       { add_opvars(splev, "o", SPO_MATH_DIV); }
+		| math_expr '%' math_expr       { add_opvars(splev, "o", SPO_MATH_MOD); }
+		| '(' math_expr ')'             { }
+		;
+
+ter_selection_x	: coord_or_var
+		  {
+		      add_opvars(splev, "o", SPO_SEL_POINT);
+		  }
+		| rect_ID region_or_var
+		  {
+		      add_opvars(splev, "o", SPO_SEL_RECT);
+		  }
+		| fillrect_ID region_or_var
+		  {
+		      add_opvars(splev, "o", SPO_SEL_FILLRECT);
+		  }
+		| line_ID coord_or_var '-' coord_or_var
+		  {
+		      add_opvars(splev, "o", SPO_SEL_LINE);
+		  }
+		| randline_ID coord_or_var '-' coord_or_var ',' math_expr
+		  {
+		      /* randline (x1,y1),(x2,y2), roughness */
+		      add_opvars(splev, "o", SPO_SEL_RNDLINE);
+		  }
+		| grow_ID '(' ter_selection ')'
+		  {
+		      add_opvars(splev, "io", W_ANY, SPO_SEL_GROW);
+		  }
+		| grow_ID '(' dir_list ',' ter_selection ')'
+		  {
+		      add_opvars(splev, "io", $3, SPO_SEL_GROW);
+		  }
+		| filter_ID '(' SPERCENT ',' ter_selection ')'
+		  {
+		      add_opvars(splev, "iio", $3, 0, SPO_SEL_FILTER);
+		  }
+		| filter_ID '(' ter_selection ',' ter_selection ')'
+		  {
+		      add_opvars(splev, "io", 1, SPO_SEL_FILTER);
+		  }
+		| flood_ID coord_or_var
+		  {
+		      add_opvars(splev, "o", SPO_SEL_FLOOD);
+		  }
+		| circle_ID '(' coord_or_var ',' math_expr ')'
+		  {
+		      add_opvars(splev, "oio", SPO_COPY, 1, SPO_SEL_ELLIPSE);
+		  }
+		| circle_ID '(' coord_or_var ',' math_expr ',' FILLING ')'
+		  {
+		      add_opvars(splev, "oio", SPO_COPY, $7, SPO_SEL_ELLIPSE);
+		  }
+		| ellipse_ID '(' coord_or_var ',' math_expr ',' math_expr ')'
+		  {
+		      add_opvars(splev, "io", 1, SPO_SEL_ELLIPSE);
+		  }
+		| ellipse_ID '(' coord_or_var ',' math_expr ',' math_expr ',' FILLING ')'
+		  {
+		      add_opvars(splev, "io", $9, SPO_SEL_ELLIPSE);
+		  }
+		| VARSTRING_SEL
+		  {
+		      check_vardef_type(variable_definitions, $1, SPOVAR_SEL);
+		      add_opvars(splev, "v", $1);
+		      Free($1);
+		  }
+		| '(' ter_selection ')'
+		  {
+		      /* nothing */
+		  }
+		;
+
+ter_selection	: ter_selection_x
+		  {
+		      /* nothing */
+		  }
+		| ter_selection_x '&' ter_selection
+		  {
+		      add_opvars(splev, "o", SPO_SEL_ADD);
+		  }
+		;
+
+dice		: DICE
+		  {
+		      add_opvars(splev, "iio", $1.num, $1.die, SPO_DICE);
+		  }
+		;
+
+all_integers	: MINUS_INTEGER
+		| PLUS_INTEGER
+		| INTEGER
+		;
+
+all_ints_push	: MINUS_INTEGER
+		  {
+		      add_opvars(splev, "i", $1 );
+		  }
+		| PLUS_INTEGER
+		  {
+		      add_opvars(splev, "i", $1 );
+		  }
+		| INTEGER
+		  {
+		      add_opvars(splev, "i", $1 );
+		  }
+		| dice
+		  {
+		      /* nothing */
+		  }
+		;
+
+string		: STRING
 		;
 
 chance		: /* empty */
 		  {
-			$$ = 100;	/* default is 100% */
+		      /* by default we just do it, unconditionally. */
+		      $$ = 0;
 		  }
-		| PERCENT
+		| comparestmt
 		  {
-			if ($1 <= 0 || $1 > 100)
-			    yyerror("Expected percentile chance.");
-			$$ = $1;
+		      /* otherwise we generate an IF-statement */
+		      struct opvar *tmppush2 = New(struct opvar);
+		      if (n_if_list >= MAX_NESTED_IFS) {
+			  lc_error("Comparison: Too deeply nested IFs.");
+			  n_if_list = MAX_NESTED_IFS - 1;
+		      }
+		      add_opcode(splev, SPO_CMP, NULL);
+		      set_opvar_int(tmppush2, splev->n_opcodes+1);
+		      if_list[n_if_list++] = tmppush2;
+		      add_opcode(splev, SPO_PUSH, tmppush2);
+		      add_opcode(splev, reverse_jmp_opcode( $1 ), NULL);
+		      $$ = 1;
 		  }
 		;
@@ -1647,12 +2312,23 @@
 		;
 
-coord		: '(' INTEGER ',' INTEGER ')'
+lev_region	: region
 		  {
-			if (!in_room && !init_lev.init_present &&
-			    ($2 < 0 || $2 > (int)max_x_map ||
-			     $4 < 0 || $4 > (int)max_y_map))
-			    yyerror("Coordinates out of map range!");
-			current_coord.x = $2;
-			current_coord.y = $4;
+			$$ = $1;
+		  }
+		| LEV '(' INTEGER ',' INTEGER ',' INTEGER ',' INTEGER ')'
+		  {
+			if ($3 <= 0 || $3 >= COLNO)
+			    lc_error("Region (%li,%li,%li,%li) out of level range (x1)!", $3, $5, $7, $9);
+			else if ($5 < 0 || $5 >= ROWNO)
+			    lc_error("Region (%li,%li,%li,%li) out of level range (y1)!", $3, $5, $7, $9);
+			else if ($7 <= 0 || $7 >= COLNO)
+			    lc_error("Region (%li,%li,%li,%li) out of level range (x2)!", $3, $5, $7, $9);
+			else if ($9 < 0 || $9 >= ROWNO)
+			    lc_error("Region (%li,%li,%li,%li) out of level range (y2)!", $3, $5, $7, $9);
+			$$.x1 = $3;
+			$$.y1 = $5;
+			$$.x2 = $7;
+			$$.y2 = $9;
+			$$.area = 1;
 		  }
 		;
@@ -1663,18 +2339,20 @@
    tiny little brain cannot compile if these are all one big if statement. */
 			if ($2 < 0 || $2 > (int)max_x_map)
-				yyerror("Region out of map range!");
+			    lc_error("Region (%li,%li,%li,%li) out of map range (x1)!", $2, $4, $6, $8);
 			else if ($4 < 0 || $4 > (int)max_y_map)
-				yyerror("Region out of map range!");
+			    lc_error("Region (%li,%li,%li,%li) out of map range (y1)!", $2, $4, $6, $8);
 			else if ($6 < 0 || $6 > (int)max_x_map)
-				yyerror("Region out of map range!");
+			    lc_error("Region (%li,%li,%li,%li) out of map range (x2)!", $2, $4, $6, $8);
 			else if ($8 < 0 || $8 > (int)max_y_map)
-				yyerror("Region out of map range!");
-			current_region.x1 = $2;
-			current_region.y1 = $4;
-			current_region.x2 = $6;
-			current_region.y2 = $8;
+			    lc_error("Region (%li,%li,%li,%li) out of map range (y2)!", $2, $4, $6, $8);
+			$$.area = 0;
+			$$.x1 = $2;
+			$$.y1 = $4;
+			$$.x2 = $6;
+			$$.y2 = $8;
 		  }
 		;
 
+
 %%
 
diff -X /home/derek/bin/nhdiff_exceptions -iNdEwr -U2 nh_orig/util/lev_main.c nethack/util/lev_main.c
--- nh_orig/util/lev_main.c	2003-12-07 18:39:13.000000000 -0500
+++ nethack/util/lev_main.c	2010-05-01 11:04:47.168714388 -0400
@@ -10,4 +10,6 @@
 /* although, why don't we move those special defines here.. and in dgn_main? */
 
+#include <stdarg.h>
+
 #include "hack.h"
 #include "date.h"
@@ -84,12 +86,17 @@
 boolean FDECL(check_object_char, (CHAR_P));
 char FDECL(what_map_char, (CHAR_P));
-void FDECL(scan_map, (char *));
-void NDECL(wallify_map);
-boolean NDECL(check_subrooms);
-void FDECL(check_coord, (int,int,const char *));
-void NDECL(store_part);
-void NDECL(store_room);
-boolean FDECL(write_level_file, (char *,splev *,specialmaze *));
-void FDECL(free_rooms, (splev *));
+void FDECL(scan_map, (char *, sp_lev *));
+boolean FDECL(check_subrooms, (sp_lev *));
+boolean FDECL(write_level_file, (char *,sp_lev *));
+
+struct lc_funcdefs *FDECL(funcdef_new,(long,char *));
+void FDECL(funcdef_free_all,(struct lc_funcdefs *));
+struct lc_funcdefs *FDECL(funcdef_defined,(struct lc_funcdefs *,char *, int));
+
+struct lc_vardefs *FDECL(vardef_new,(long,char *));
+void FDECL(vardef_free_all,(struct lc_vardefs *));
+struct lc_vardefs *FDECL(vardef_defined,(struct lc_vardefs *,char *, int));
+
+void FDECL(splev_add_from, (sp_lev *, sp_lev *));
 
 extern void NDECL(monst_init);
@@ -97,10 +104,8 @@
 extern void NDECL(decl_init);
 
-static boolean FDECL(write_common_data, (int,int,lev_init *,long));
-static boolean FDECL(write_monsters, (int,char *,monster ***));
-static boolean FDECL(write_objects, (int,char *,object ***));
-static boolean FDECL(write_engravings, (int,char *,engraving ***));
-static boolean FDECL(write_maze, (int,specialmaze *));
-static boolean FDECL(write_rooms, (int,splev *));
+void FDECL(add_opcode, (sp_lev *, int, genericptr_t));
+
+static boolean FDECL(write_common_data, (int,sp_lev *));
+static boolean FDECL(write_maze, (int,sp_lev *));
 static void NDECL(init_obj_classes);
 
@@ -131,4 +136,7 @@
 	{ "anti magic",	ANTI_MAGIC },
 	{ "polymorph",	POLY_TRAP },
+	{ "spear", SPEAR_TRAP },
+	{ "collapse",   COLLAPSE_TRAP },
+	{ "magic beam", MAGIC_BEAM_TRAP },
 	{ 0, 0 }
 };
@@ -152,4 +160,5 @@
 	{ "anthole",	 ANTHOLE },
 	{ "cocknest",	 COCKNEST },
+	{ "traproom",	 TRAPROOM },
 	{ "leprehall",	 LEPREHALL },
 	{ "shop",	 SHOPBASE },
@@ -169,5 +178,7 @@
 const char *fname = "(stdin)";
 int fatal_error = 0;
-int want_warnings = 0;
+int got_errors = 0;
+int be_verbose = 0;
+int decompile = 0;
 
 #ifdef FLEX23_BUG
@@ -176,39 +187,11 @@
 #endif
 
-extern char tmpmessage[];
-extern altar *tmpaltar[];
-extern lad *tmplad[];
-extern stair *tmpstair[];
-extern digpos *tmpdig[];
-extern digpos *tmppass[];
-extern char *tmpmap[];
-extern region *tmpreg[];
-extern lev_region *tmplreg[];
-extern door *tmpdoor[];
-extern room_door *tmprdoor[];
-extern trap *tmptrap[];
-extern monster *tmpmonst[];
-extern object *tmpobj[];
-extern drawbridge *tmpdb[];
-extern walk *tmpwalk[];
-extern gold *tmpgold[];
-extern fountain *tmpfountain[];
-extern sink *tmpsink[];
-extern pool *tmppool[];
-extern engraving *tmpengraving[];
-extern mazepart *tmppart[];
-extern room *tmproom[];
-
-extern int n_olist, n_mlist, n_plist;
-
-extern unsigned int nlreg, nreg, ndoor, ntrap, nmons, nobj;
-extern unsigned int ndb, nwalk, npart, ndig, npass, nlad, nstair;
-extern unsigned int naltar, ncorridor, nrooms, ngold, nengraving;
-extern unsigned int nfountain, npool, nsink;
-
 extern unsigned int max_x_map, max_y_map;
 
 extern int line_number, colon_line_number;
 
+struct lc_vardefs *variable_definitions = NULL;
+
+
 int
 main(argc, argv)
@@ -263,5 +246,5 @@
 	    init_yyin(stdin);
 	    (void) yyparse();
-	    if (fatal_error > 0) {
+	    if (fatal_error > 0 || got_errors > 0) {
 		    errors_encountered = TRUE;
 	    }
@@ -269,6 +252,10 @@
 	    for(i=1; i<argc; i++) {
 		    fname = argv[i];
-		    if(!strcmp(fname, "-w")) {
-			want_warnings++;
+		    if(!strcmp(fname, "-v")) {
+			be_verbose++;
+			continue;
+		    }
+		    if(!strcmp(fname, "-d")) {
+			decompile = 1;
 			continue;
 		    }
@@ -283,9 +270,10 @@
 			(void) yyparse();
 			line_number = 1;
-			if (fatal_error > 0) {
+			if (fatal_error > 0 || got_errors > 0) {
 				errors_encountered = TRUE;
 				fatal_error = 0;
 			}
 		    }
+		    (void) fclose(fin);
 	    }
 	}
@@ -315,4 +303,19 @@
 }
 
+
+void
+lc_error(const char *fmt, ...)
+{
+    char buf[512];
+    va_list argp;
+
+    va_start(argp, fmt);
+    (void) vsnprintf(buf, 511, fmt, argp);
+    va_end(argp);
+
+    yyerror(buf);
+}
+
+
 /*
  * Just display a warning (that is : a non fatal error)
@@ -326,13 +329,431 @@
 }
 
-/*
- * Stub needed for lex interface.
- */
+void
+lc_warning(const char *fmt, ...)
+{
+    char buf[512];
+    va_list argp;
+
+    va_start(argp, fmt);
+    (void) vsnprintf(buf, 511, fmt, argp);
+    va_end(argp);
+
+    yywarning(buf);
+}
+
+
+struct opvar *
+set_opvar_int(ov, val)
+struct opvar *ov;
+long  val;
+{
+    if (ov) {
+        ov->spovartyp = SPOVAR_INT;
+        ov->vardata.l = val;
+    }
+    return ov;
+}
+
+struct opvar *
+set_opvar_coord(ov, val)
+struct opvar *ov;
+long  val;
+{
+    if (ov) {
+        ov->spovartyp = SPOVAR_COORD;
+        ov->vardata.l = val;
+    }
+    return ov;
+}
+
+struct opvar *
+set_opvar_region(ov, val)
+struct opvar *ov;
+long  val;
+{
+    if (ov) {
+        ov->spovartyp = SPOVAR_REGION;
+        ov->vardata.l = val;
+    }
+    return ov;
+}
+
+struct opvar *
+set_opvar_mapchar(ov, val)
+struct opvar *ov;
+long  val;
+{
+    if (ov) {
+        ov->spovartyp = SPOVAR_MAPCHAR;
+        ov->vardata.l = val;
+    }
+    return ov;
+}
+
+struct opvar *
+set_opvar_monst(ov, val)
+struct opvar *ov;
+long  val;
+{
+    if (ov) {
+        ov->spovartyp = SPOVAR_MONST;
+        ov->vardata.l = val;
+    }
+    return ov;
+}
+
+struct opvar *
+set_opvar_obj(ov, val)
+struct opvar *ov;
+long  val;
+{
+    if (ov) {
+        ov->spovartyp = SPOVAR_OBJ;
+        ov->vardata.l = val;
+    }
+    return ov;
+}
+
+struct opvar *
+set_opvar_str(ov, val)
+struct opvar *ov;
+char *val;
+{
+    if (ov) {
+        ov->spovartyp = SPOVAR_STRING;
+	ov->vardata.str = (val) ? strdup(val) : NULL;
+    }
+    return ov;
+}
+
+struct opvar *
+set_opvar_var(ov, val)
+struct opvar *ov;
+char *val;
+{
+    if (ov) {
+        ov->spovartyp = SPOVAR_VARIABLE;
+	ov->vardata.str = (val) ? strdup(val) : NULL;
+    }
+    return ov;
+}
+
+#define New(type)		\
+	(type *) memset((genericptr_t)alloc(sizeof(type)), 0, sizeof(type))
+
+void
+add_opvars(sp_lev *sp, const char *fmt, ...)
+{
+    const char *p;
+    va_list argp;
+
+    va_start(argp, fmt);
+
+    for(p = fmt; *p != '\0'; p++) {
+	switch(*p) {
+	case ' ': break;
+	case 'i':
+	    {
+		struct opvar *ov = New(struct opvar);
+		set_opvar_int(ov, va_arg(argp, long));
+		add_opcode(sp, SPO_PUSH, ov);
+		break;
+	    }
+	case 'c':
+	    {
+		struct opvar *ov = New(struct opvar);
+		set_opvar_coord(ov, va_arg(argp, long));
+		add_opcode(sp, SPO_PUSH, ov);
+		break;
+	    }
+	case 'r':
+	    {
+		struct opvar *ov = New(struct opvar);
+		set_opvar_region(ov, va_arg(argp, long));
+		add_opcode(sp, SPO_PUSH, ov);
+		break;
+	    }
+	case 'm':
+	    {
+		struct opvar *ov = New(struct opvar);
+		set_opvar_mapchar(ov, va_arg(argp, long));
+		add_opcode(sp, SPO_PUSH, ov);
+		break;
+	    }
+	case 'M':
+	    {
+		struct opvar *ov = New(struct opvar);
+		set_opvar_monst(ov, va_arg(argp, long));
+		add_opcode(sp, SPO_PUSH, ov);
+		break;
+	    }
+	case 'O':
+	    {
+		struct opvar *ov = New(struct opvar);
+		set_opvar_obj(ov, va_arg(argp, long));
+		add_opcode(sp, SPO_PUSH, ov);
+		break;
+	    }
+	case 's':
+	    {
+		struct opvar *ov = New(struct opvar);
+		set_opvar_str(ov, va_arg(argp, char *));
+		add_opcode(sp, SPO_PUSH, ov);
+		break;
+	    }
+	case 'v':
+	    {
+		struct opvar *ov = New(struct opvar);
+		set_opvar_var(ov, va_arg(argp, char *));
+		add_opcode(sp, SPO_PUSH, ov);
+		break;
+	    }
+	case 'o':
+	    {
+		long i = va_arg(argp, int);
+		if (i < 0 || i >= MAX_SP_OPCODES)
+		    fprintf(stderr, "add_opvars: unknown opcode '%i'.\n", i);
+		add_opcode(sp, i, NULL);
+		break;
+	    }
+	default:
+	    fprintf(stderr, "add_opvars: illegal format character '%c'.\n", *p);
+	    break;
+	}
+    }
+
+    va_end(argp);
+}
+
+
+struct lc_funcdefs *
+funcdef_new(addr, name)
+     long addr;
+     char *name;
+{
+    struct lc_funcdefs *f = New(struct lc_funcdefs);
+    if (!f) {
+	lc_error("Could not alloc function definition for '%s'.", name);
+	return NULL;
+    }
+    f->next = NULL;
+    f->addr = addr;
+    f->name = strdup(name);
+    f->n_called = 0;
+    f->code.opcodes = NULL;
+    f->code.n_opcodes = 0;
+    return f;
+}
+
+void
+funcdef_free_all(fchain)
+     struct lc_funcdefs *fchain;
+{
+    struct lc_funcdefs *tmp = fchain;
+    struct lc_funcdefs *nxt;
+    while (tmp) {
+	nxt = tmp->next;
+	Free(tmp->name);
+	/* FIXME: free tmp->code */
+	Free(tmp);
+	tmp = nxt;
+    }
+}
+
+struct lc_funcdefs *
+funcdef_defined(f, name, casesense)
+     struct lc_funcdefs *f;
+     char *name;
+     int casesense;
+{
+    while (f) {
+	if (casesense) {
+	    if (!strcmp(name, f->name)) return f;
+	} else {
+	    if (!strcasecmp(name, f->name)) return f;
+	}
+	f = f->next;
+    }
+    return NULL;
+}
+
+
+struct lc_vardefs *
+vardef_new(typ, name)
+     long typ;
+     char *name;
+{
+    struct lc_vardefs *f = New(struct lc_vardefs);
+    if (!f) {
+	lc_error("Could not alloc variable definition for '%s'.", name);
+	return NULL;
+    }
+    f->next = NULL;
+    f->var_type = typ;
+    f->name = strdup(name);
+    return f;
+}
+
+void
+vardef_free_all(fchain)
+     struct lc_vardefs *fchain;
+{
+    struct lc_vardefs *tmp = fchain;
+    struct lc_vardefs *nxt;
+    while (tmp) {
+	nxt = tmp->next;
+	Free(tmp->name);
+	Free(tmp);
+	tmp = nxt;
+    }
+}
+
+struct lc_vardefs *
+vardef_defined(f, name, casesense)
+     struct lc_vardefs *f;
+     char *name;
+     int casesense;
+{
+    while (f) {
+	if (casesense) {
+	    if (!strcmp(name, f->name)) return f;
+	} else {
+	    if (!strcasecmp(name, f->name)) return f;
+	}
+	f = f->next;
+    }
+    return NULL;
+}
+
+const char *
+spovar2str(spovar)
+     long spovar;
+{
+    static togl = 0;
+    static char buf[2][128];
+    char *n;
+    int is_array = (spovar & SPOVAR_ARRAY);
+    spovar &= ~SPOVAR_ARRAY;
+
+    switch (spovar) {
+    default:		  lc_error("spovar2str(%li)", spovar); break;
+    case SPOVAR_INT:	  n = "integer"; break;
+    case SPOVAR_STRING:   n = "string"; break;
+    case SPOVAR_VARIABLE: n = "variable"; break;
+    case SPOVAR_COORD:	  n = "coordinate"; break;
+    case SPOVAR_REGION:	  n = "region"; break;
+    case SPOVAR_MAPCHAR:  n = "mapchar"; break;
+    case SPOVAR_MONST:	  n = "monster"; break;
+    case SPOVAR_OBJ:	  n = "object"; break;
+    }
+
+    togl = ((togl + 1) % 2);
+
+    snprintf(buf[togl], 127, "%s%s", n, (is_array ? " array" : ""));
+    return buf[togl];
+}
+
+void
+check_vardef_type(vd, varname, vartype)
+     struct lc_vardefs *vd;
+     char *varname;
+     long vartype;
+{
+    struct lc_vardefs *tmp;
+    if ((tmp = vardef_defined(vd, varname, 1))) {
+	if (tmp->var_type != vartype)
+	    lc_error("Trying to use variable '%s' as %s, when it is %s.",
+		     varname, spovar2str(vartype), spovar2str(tmp->var_type));
+    } else lc_error("Variable '%s' not defined.", varname);
+}
+
+struct lc_vardefs *
+add_vardef_type(vd, varname, vartype)
+     struct lc_vardefs *vd;
+     char *varname;
+     long vartype;
+{
+    struct lc_vardefs *tmp;
+    if ((tmp = vardef_defined(vd, varname, 1))) {
+	if (tmp->var_type != vartype)
+	    lc_error("Trying to redefine variable '%s' as %s, when it is %s.",
+		     varname, spovar2str(vartype), spovar2str(tmp->var_type));
+    } else {
+	tmp = vardef_new(vartype, varname);
+	tmp->next = vd;
+	return tmp;
+    }
+    return vd;
+}
+
 int
-yywrap()
+reverse_jmp_opcode(opcode)
+     int opcode;
 {
-	return 1;
+    switch (opcode) {
+    case SPO_JE:  return SPO_JNE;
+    case SPO_JNE: return SPO_JE;
+    case SPO_JL:  return SPO_JGE;
+    case SPO_JG:  return SPO_JLE;
+    case SPO_JLE: return SPO_JG;
+    case SPO_JGE: return SPO_JL;
+    default: lc_error("Cannot reverse comparison jmp opcode %i.", opcode); return SPO_NULL;
+    }
+}
+
+/* basically copied from src/sp_lev.c */
+struct opvar *
+opvar_clone(ov)
+     struct opvar *ov;
+{
+    if (ov) {
+	struct opvar *tmpov = (struct opvar *)alloc(sizeof(struct opvar));
+	if (!tmpov) panic("could not alloc opvar struct");
+	switch (ov->spovartyp) {
+	case SPOVAR_COORD:
+	case SPOVAR_REGION:
+	case SPOVAR_MAPCHAR:
+	case SPOVAR_MONST:
+	case SPOVAR_OBJ:
+	case SPOVAR_INT:
+	    {
+		tmpov->spovartyp = ov->spovartyp;
+		tmpov->vardata.l = ov->vardata.l;
+	    }
+	    break;
+	case SPOVAR_VARIABLE:
+	case SPOVAR_STRING:
+	    {
+		int len = strlen(ov->vardata.str);
+		tmpov->spovartyp = ov->spovartyp;
+		tmpov->vardata.str = (char *)alloc(len+1);
+		(void)memcpy((genericptr_t)tmpov->vardata.str,
+			     (genericptr_t)ov->vardata.str, len);
+		tmpov->vardata.str[len] = '\0';
+	    }
+	    break;
+	default:
+	    {
+		lc_error("Unknown opvar_clone value type (%i)!", ov->spovartyp);
+	    }
+	}
+	return tmpov;
+    }
+    return NULL;
 }
 
+
+void
+splev_add_from(splev, from_splev)
+     sp_lev *splev;
+     sp_lev *from_splev;
+{
+    int i;
+    if (splev && from_splev)
+	for (i = 0; i < from_splev->n_opcodes; i++)
+	    add_opcode(splev, from_splev->opcodes[i].opcode, opvar_clone(from_splev->opcodes[i].opdat));
+}
+
+
 /*
  * Find the type of floor, knowing its char representation.
@@ -348,5 +769,5 @@
 	if(val == INVALID_TYPE) {
 	    val = ERR;
-	    yywarning("Invalid fill character in MAZE declaration");
+	    lc_warning("Invalid fill character '%c' in MAZE declaration", c);
 	}
 	return val;
@@ -402,4 +823,12 @@
 	    if (!class || class == mons[i].mlet)
 		if (!strcmp(s, mons[i].mname)) return i;
+	/* didn't find it; lets try case insensitive search */
+	for (i = LOW_PM; i < NUMMONS; i++)
+	    if (!class || class == mons[i].mlet)
+		if (!strcasecmp(s, mons[i].mname)) {
+		    if (be_verbose)
+			lc_warning("Monster type \"%s\" matches \"%s\".", s, mons[i].mname);
+		    return i;
+		}
 	return ERR;
 }
@@ -426,4 +855,15 @@
 		return i;
 	}
+
+	for (i = class ? bases[class] : 0; i < NUM_OBJECTS; i++) {
+	    if (class && objects[i].oc_class != class) break;
+	    objname = obj_descr[i].oc_name;
+	    if (objname && !strcasecmp(s, objname)) {
+		if (be_verbose)
+		    lc_warning("Object type \"%s\" matches \"%s\".", s, objname);
+		return i;
+	    }
+	}
+
 	return ERR;
 }
@@ -485,10 +925,12 @@
 		  case 'H'  : return(SCORR);
 		  case '{'  : return(FOUNTAIN);
-		  case '\\' : return(THRONE);
+		  case '\\' :
+		      lc_warning("Mapchar \\ is deprecated, use OBJECT:('\\',\"throne\"),(x,y) instead.");
+			return(ROOM);
 		  case 'K'  :
 #ifdef SINKS
 		      return(SINK);
 #else
-		      yywarning("Sinks are not allowed in this version!  Ignoring...");
+		      lc_warning("Sinks ('K') are not allowed in this version!  Ignoring...");
 		      return(ROOM);
 #endif
@@ -500,8 +942,36 @@
 		  case 'T'	: return (TREE);
 		  case 'F'	: return (IRONBARS);	/* Fe = iron */
+		  case 'x'  : return(MAX_TYPE); /* 'see-through' */
 	    }
 	return(INVALID_TYPE);
 }
 
+void
+add_opcode(sp, opc, dat)
+sp_lev *sp;
+int opc;
+genericptr_t dat;
+{
+   long nop = sp->n_opcodes;
+   _opcode *tmp;
+
+   if ((opc < 0) || (opc >= MAX_SP_OPCODES))
+       lc_error("Unknown opcode '%i'", opc);
+
+   tmp = (_opcode *)alloc(sizeof(_opcode)*(nop+1));
+   if (sp->opcodes && nop) {
+       (void) memcpy(tmp, sp->opcodes, sizeof(_opcode)*nop);
+       free(sp->opcodes);
+   } else if (!tmp)
+       lc_error("Could not alloc opcode space");
+
+   sp->opcodes = tmp;
+
+   sp->opcodes[nop].opcode = opc;
+   sp->opcodes[nop].opdat = dat;
+
+   sp->n_opcodes++;
+}
+
 /*
  * Yep! LEX gives us the map in a raw mode.
@@ -509,12 +979,16 @@
  */
 void
-scan_map(map)
+scan_map(map, sp)
 char *map;
+sp_lev *sp;
 {
 	register int i, len;
 	register char *s1, *s2;
-	int max_len = 0;
-	int max_hig = 0;
+	long max_len = 0;
+	long max_hig = 0;
 	char msg[256];
+	char *tmpmap[ROWNO];
+	int dx,dy;
+	char *mbuf;
 
 	/* First, strip out digits 0-9 (line numbering) */
@@ -551,8 +1025,5 @@
 		for(i=0; i<len; i++)
 		  if((tmpmap[max_hig][i] = what_map_char(map[i])) == INVALID_TYPE) {
-		      Sprintf(msg,
-			 "Invalid character @ (%d, %d) - replacing with stone",
-			      max_hig, i);
-		      yywarning(msg);
+		      lc_warning("Invalid character '%c' @ (%d, %d) - replacing with stone", map[i], max_hig, i);
 		      tmpmap[max_hig][i] = STONE;
 		    }
@@ -568,549 +1039,314 @@
 	max_y_map = max_hig - 1;
 
-	/* Store the map into the mazepart structure */
 
 	if(max_len > MAP_X_LIM || max_hig > MAP_Y_LIM) {
-	    Sprintf(msg, "Map too large! (max %d x %d)", MAP_X_LIM, MAP_Y_LIM);
-	    yyerror(msg);
-	}
-
-	tmppart[npart]->xsize = max_len;
-	tmppart[npart]->ysize = max_hig;
-	tmppart[npart]->map = (char **) alloc(max_hig*sizeof(char *));
-	for(i = 0; i< max_hig; i++)
-	    tmppart[npart]->map[i] = tmpmap[i];
-}
-
-/*
- *	If we have drawn a map without walls, this allows us to
- *	auto-magically wallify it.
- */
-#define Map_point(x,y) *(tmppart[npart]->map[y] + x)
-
-void
-wallify_map()
-{
-	unsigned int x, y, xx, yy, lo_xx, lo_yy, hi_xx, hi_yy;
-
-	for (y = 0; y <= max_y_map; y++) {
-	    SpinCursor(3);
-	    lo_yy = (y > 0) ? y - 1 : 0;
-	    hi_yy = (y < max_y_map) ? y + 1 : max_y_map;
-	    for (x = 0; x <= max_x_map; x++) {
-		if (Map_point(x,y) != STONE) continue;
-		lo_xx = (x > 0) ? x - 1 : 0;
-		hi_xx = (x < max_x_map) ? x + 1 : max_x_map;
-		for (yy = lo_yy; yy <= hi_yy; yy++)
-		    for (xx = lo_xx; xx <= hi_xx; xx++)
-			if (IS_ROOM(Map_point(xx,yy)) ||
-				Map_point(xx,yy) == CROSSWALL) {
-			    Map_point(x,y) = (yy != y) ? HWALL : VWALL;
-			    yy = hi_yy;		/* end `yy' loop */
-			    break;		/* end `xx' loop */
-			}
-	    }
-	}
+	    lc_error("Map too large at (%d x %d), max is (%d x %d)", max_len, max_hig, MAP_X_LIM, MAP_Y_LIM);
 }
 
-/*
- * We need to check the subrooms apartenance to an existing room.
- */
-boolean
-check_subrooms()
-{
-	unsigned i, j, n_subrooms;
-	boolean	found, ok = TRUE;
-	char	*last_parent, msg[256];
+	mbuf = (char *) alloc(((max_hig-1) * max_len) + (max_len-1) + 2);
+	for (dy = 0; dy < max_hig; dy++)
+	    for (dx = 0; dx < max_len; dx++)
+		mbuf[(dy * max_len) + dx] = (tmpmap[dy][dx] + 1);
 
-	for (i = 0; i < nrooms; i++)
-	    if (tmproom[i]->parent) {
-		found = FALSE;
-		for(j = 0; j < nrooms; j++)
-		    if (tmproom[j]->name &&
-			    !strcmp(tmproom[i]->parent, tmproom[j]->name)) {
-			found = TRUE;
-			break;
-		    }
-		if (!found) {
-		    Sprintf(msg,
-			    "Subroom error : parent room '%s' not found!",
-			    tmproom[i]->parent);
-		    yyerror(msg);
-		    ok = FALSE;
-		}
-	    }
+	mbuf[((max_hig-1) * max_len) + (max_len-1) + 1] = '\0';
 
-	msg[0] = '\0';
-	last_parent = msg;
-	for (i = 0; i < nrooms; i++)
-	    if (tmproom[i]->parent) {
-		n_subrooms = 0;
-		for(j = i; j < nrooms; j++) {
-/*
- *	This is by no means perfect, but should cut down the duplicate error
- *	mess
