diff -Naurd ../nethack-3.4.1/include/config1.h ./include/config1.h
--- ../nethack-3.4.1/include/config1.h Sun Feb 23 14:43:19 2003
+++ ./include/config1.h Mon Sep 1 14:33:32 2003
@@ -130,6 +130,11 @@
 #endif
 
 
+#if defined(__linux__) && defined(__GNUC__) && !defined(_GNU_SOURCE)
+/* ensure _GNU_SOURCE is defined before including any system headers */
+# define _GNU_SOURCE
+#endif
+
 #ifdef VMS	/* really old compilers need special handling, detected here */
 # undef UNIX
 # ifdef __DECC
diff -Naurd ../nethack-3.4.1/include/decl.h ./include/decl.h
--- ../nethack-3.4.1/include/decl.h Sun Feb 23 14:43:19 2003
+++ ./include/decl.h Mon Sep 1 14:33:32 2003
@@ -222,8 +222,8 @@
 #include "spell.h"
 E NEARDATA struct spell spl_book[];	/* sized in decl.c */
 
-#ifdef TEXTCOLOR
 #include "color.h"
+#ifdef TEXTCOLOR
 E const int zapcolors[];
 #endif
 
diff -Naurd ../nethack-3.4.1/include/display.h ./include/display.h
--- ../nethack-3.4.1/include/display.h Sun Feb 23 14:43:20 2003
+++ ./include/display.h Mon Sep 1 14:33:32 2003
@@ -133,8 +133,7 @@
  * invisible.  If not, then we don't need the check.
  */
 #define canseeself()	(Blind || u.uswallow || (!Invisible && !u.uundetected))
-#define senseself()	(canseeself() || Infravision || Unblind_telepat || \
-			 Detect_monsters)
+#define senseself()	(canseeself() || Unblind_telepat || Detect_monsters)
 
 /*
  * random_monster()
diff -Naurd ../nethack-3.4.1/include/extern.h ./include/extern.h
--- ../nethack-3.4.1/include/extern.h Sun Feb 23 14:43:20 2003
+++ ./include/extern.h Mon Sep 1 14:33:32 2003
@@ -1,4 +1,4 @@
-/*	SCCS Id: @(#)extern.h	3.4	2003/01/02	*/
+/*	SCCS Id: @(#)extern.h	3.4	2003/03/10	*/
 /* Copyright (c) Steve Creps, 1988.				  */
 /* NetHack may be freely redistributed.  See license for details. */
 
@@ -178,6 +178,7 @@
 #ifdef WIZARD
 E void NDECL(sanity_check);
 #endif
+E char FDECL(yn_function, (const char *, const char *, CHAR_P));
 
 /* ### dbridge.c ### */
 
@@ -339,6 +340,7 @@
 E char *FDECL(distant_monnam, (struct monst *,int,char *));
 E const char *NDECL(rndmonnam);
 E const char *FDECL(hcolor, (const char *));
+E const char *NDECL(rndcolor);
 #ifdef REINCARNATION
 E const char *NDECL(roguename);
 #endif
@@ -385,6 +387,7 @@
 E struct obj *FDECL(some_armor,(struct monst *));
 E void FDECL(erode_armor, (struct monst *,BOOLEAN_P));
 E struct obj *FDECL(stuck_ring, (struct obj *,int));
+E struct obj *NDECL(unchanger);
 E void NDECL(reset_remarm);
 E int NDECL(doddoremarm);
 E int FDECL(destroy_arm, (struct obj *));
@@ -418,6 +421,7 @@
 /* ### dokick.c ### */
 
 E boolean FDECL(ghitm, (struct monst *,struct obj *));
+E void FDECL(container_impact_dmg, (struct obj *));
 E int NDECL(dokick);
 E boolean FDECL(ship_object, (struct obj *,XCHAR_P,XCHAR_P,BOOLEAN_P));
 E void NDECL(obj_delivery);
@@ -498,7 +502,7 @@
 E xchar NDECL(level_difficulty);
 E schar FDECL(lev_by_name, (const char *));
 #ifdef WIZARD
-E void NDECL(print_dungeon);
+E schar FDECL(print_dungeon, (BOOLEAN_P));
 #endif
 
 /* ### eat.c ### */
@@ -758,6 +762,7 @@
 			(struct obj *,const char *,const char *,const char *));
 E void FDECL(useupall, (struct obj *));
 E void FDECL(useup, (struct obj *));
+E void FDECL(consume_obj_charge, (struct obj *,BOOLEAN_P));
 E void FDECL(freeinv_core, (struct obj *));
 E void FDECL(freeinv, (struct obj *));
 E void FDECL(delallobj, (int,int));
@@ -789,6 +794,7 @@
 E const char *FDECL(dfeature_at, (int,int,char *));
 E int FDECL(look_here, (int,BOOLEAN_P));
 E int NDECL(dolook);
+E boolean FDECL(will_feel_cockatrice, (struct obj *,BOOLEAN_P));
 E void FDECL(feel_cockatrice, (struct obj *,BOOLEAN_P));
 E void FDECL(stackobj, (struct obj *));
 E int NDECL(doprgold);
@@ -868,6 +874,7 @@
 E int FDECL(macread, (int,void *,unsigned));
 E int FDECL(macwrite, (int,void *,unsigned));
 E long FDECL(macseek, (int,long,short));
+E int FDECL(macunlink, (const char *));
 
 /* ### macsnd.c ### */
 
@@ -927,6 +934,7 @@
 #ifdef GOLDOBJ
 E void FDECL(mkmonmoney, (struct monst *, long));
 #endif
+E void FDECL(bagotricks, (struct obj *));
 
 /* ### mapglyph.c ### */
 
@@ -1002,6 +1010,7 @@
 /* ### mkmap.c ### */
 
 void FDECL(flood_fill_rm, (int,int,int,BOOLEAN_P,BOOLEAN_P));
+void FDECL(remove_rooms, (int,int,int,int));
 
 /* ### mkmaze.c ### */
 
@@ -1086,6 +1095,7 @@
 /* ### mon.c ### */
 
 E int FDECL(undead_to_corpse, (int));
+E int FDECL(genus, (int,int));
 E int FDECL(pm_to_cham, (int));
 E int FDECL(minliquid, (struct monst *));
 E int NDECL(movemon);
@@ -1312,6 +1322,7 @@
 E void NDECL(nttty_rubout);
 E int NDECL(tgetch);
 E int FDECL(ntposkey,(int *, int *, int *));
+E void FDECL(set_output_mode, (int));
 #endif
 
 /* ### o_init.c ### */
@@ -1343,6 +1354,7 @@
 E boolean FDECL(not_fully_identified, (struct obj *));
 E char *FDECL(corpse_xname, (struct obj *,BOOLEAN_P));
 E char *FDECL(cxname, (struct obj *));
+E char *FDECL(killer_xname, (struct obj *));
 E const char *FDECL(singular, (struct obj *,char *(*)(OBJ_P)));
 E char *FDECL(an, (const char *));
 E char *FDECL(An, (const char *));
@@ -1355,6 +1367,8 @@
 E char *FDECL(Doname2, (struct obj *));
 E char *FDECL(yname, (struct obj *));
 E char *FDECL(Yname2, (struct obj *));
+E char *FDECL(ysimple_name, (struct obj *));
+E char *FDECL(Ysimple_name2, (struct obj *));
 E char *FDECL(makeplural, (const char *));
 E char *FDECL(makesingular, (const char *));
 E struct obj *FDECL(readobjnam, (char *,struct obj *,BOOLEAN_P));
@@ -1379,6 +1393,7 @@
 E char *FDECL(nh_getenv, (const char *));
 E void FDECL(set_duplicate_opt_detection, (int));
 E void FDECL(set_wc_option_mod_status, (unsigned long, int));
+E void FDECL(set_wc2_option_mod_status, (unsigned long, int));
 E void FDECL(set_option_mod_status, (const char *,int));
 
 /* ### pager.c ### */
@@ -1469,6 +1484,8 @@
 E int NDECL(doloot);
 E int FDECL(use_container, (struct obj *,int));
 E int FDECL(loot_mon, (struct monst *,int *,boolean *));
+E const char *FDECL(safe_qbuf, (const char *,unsigned,
+				const char *,const char *,const char *));
 
 /* ### pline.c ### */
 
@@ -2046,6 +2063,9 @@
 #ifdef UNIX
 E void NDECL(getlock);
 E void FDECL(regularize, (char *));
+# if defined(TIMED_DELAY) && !defined(msleep) && defined(SYSV)
+E void FDECL(msleep, (unsigned));
+# endif
 # ifdef SHELL
 E int NDECL(dosh);
 # endif /* SHELL */
diff -Naurd ../nethack-3.4.1/include/flag.h ./include/flag.h
--- ../nethack-3.4.1/include/flag.h Sun Feb 23 14:43:20 2003
+++ ./include/flag.h Mon Sep 1 14:33:32 2003
@@ -167,10 +167,12 @@
 	boolean  menu_tab_sep;	/* Use tabs to separate option menu fields */
 	boolean  menu_requested; /* Flag for overloaded use of 'm' prefix
 				  * on some non-move commands */
+	uchar num_pad_mode;
 	int      purge_monsters;	/* # of dead monsters still on fmon list */
 	int *opt_booldup;	/* for duplication of boolean opts in config file */
 	int *opt_compdup;	/* for duplication of compound opts in config file */
-	uchar bouldersym;		/* symbol for boulder display */
+	uchar	bouldersym;	/* symbol for boulder display */
+	coord	travelcc;	/* coordinates for travel_cache */
 #ifdef WIZARD
 	boolean  sanity_check;	/* run sanity checks */
 	boolean  mon_polycontrol;	/* debug: control monster polymorphs */
@@ -186,6 +188,8 @@
 #endif
 #ifdef MICRO
 	boolean  BIOS;		/* use IBM or ST BIOS calls when appropriate */
+#endif
+#if defined(MICRO) || defined(WIN32)
 	boolean  rawio;		/* whether can use rawio (IOCTL call) */
 #endif
 #ifdef MAC_GRAPHICS_ENV
@@ -254,6 +258,9 @@
 				   		in the message window */
 	boolean wc_eight_bit_input;	/* allow eight bit input               */
 	boolean wc_mouse_support;	/* allow mouse support */
+	boolean wc2_fullscreen;		/* run fullscreen */
+	boolean wc2_softkeyboard;	/* use software keyboard */
+	boolean wc2_wraptext;		/* wrap text */
 
 	boolean  cmdassist;	/* provide detailed assistance for some commands */
 	boolean	 obsolete;	/* obsolete options can point at this, it isn't used */
diff -Naurd ../nethack-3.4.1/include/global.h ./include/global.h
--- ../nethack-3.4.1/include/global.h Sun Feb 23 14:43:20 2003
+++ ./include/global.h Mon Sep 1 14:33:32 2003
@@ -1,4 +1,4 @@
-/*	SCCS Id: @(#)global.h	3.4	2003/02/19	*/
+/*	SCCS Id: @(#)global.h	3.4	2003/08/21	*/
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
 /* NetHack may be freely redistributed.  See license for details. */
 
diff -Naurd ../nethack-3.4.1/include/hack.h ./include/hack.h
--- ../nethack-3.4.1/include/hack.h Sun Feb 23 14:43:20 2003
+++ ./include/hack.h Mon Sep 1 14:33:32 2003
@@ -140,6 +140,7 @@
 #define MM_NONAME	  0x20  /* monster is not christened */
 #define MM_NOCOUNTBIRTH	  0x40  /* don't increment born counter (for revival) */
 #define MM_IGNOREWATER	  0x80	/* ignore water when positioning */
+#define MM_ADJACENTOK	  0x100 /* it is acceptable to use adjacent coordinates */
 
 /* flags for special ggetobj status returns */
 #define ALL_FINISHED	  0x01  /* called routine already finished the job */
@@ -150,6 +151,7 @@
 #define USE_INVLET	  0x4	/* use object's invlet */
 #define INVORDER_SORT	  0x8	/* sort objects by packorder */
 #define SIGNAL_NOMENU	  0x10	/* return -1 rather than 0 if none allowed */
+#define FEEL_COCKATRICE   0x20  /* engage cockatrice checks and react */
 
 /* Flags to control query_category() */
 /* BY_NEXTHERE used by query_category() too, so skip 0x01 */
@@ -178,6 +180,8 @@
 
 /* Flags to control dotrap() in trap.c */
 #define NOWEBMSG	0x01	/* suppress stumble into web message */
+#define FORCEBUNGLE	0x02	/* adjustments appropriate for bungling */
+#define RECURSIVETRAP	0x04	/* trap changed into another type this same turn */
 
 /* Flags to control test_move in hack.c */
 #define DO_MOVE		0	/* really doing the move */
@@ -203,6 +207,7 @@
 /* Macros for launching objects */
 #define ROLL		0x01	/* the object is rolling */
 #define FLING		0x02	/* the object is flying thru the air */
+#define LAUNCH_UNSEEN	0x40	/* hero neither caused nor saw it */
 #define LAUNCH_KNOWN	0x80	/* the hero caused this by explicit action */
 
 /* Macros for explosion types */
diff -Naurd ../nethack-3.4.1/include/obj.h ./include/obj.h
--- ../nethack-3.4.1/include/obj.h Sun Feb 23 14:43:21 2003
+++ ./include/obj.h Mon Sep 1 14:33:32 2003
@@ -33,7 +33,11 @@
 				   marks your eggs, spinach tins
 				   royal coffers for a court ( == 2)
 				   tells which fruit a fruit is
-				   special for uball and amulet %% BAH */
+				   special for uball and amulet
+				   historic and gender for statues */
+#define STATUE_HISTORIC 0x01
+#define STATUE_MALE     0x02
+#define STATUE_FEMALE   0x04
 	char	oclass;		/* object class */
 	char	invlet;		/* designation in inventory */
 	char	oartifact;	/* artifact array index */
@@ -260,6 +264,22 @@
 			 otmp->otyp == WAX_CANDLE)
 #define MAX_OIL_IN_FLASK 400	/* maximum amount of oil in a potion of oil */
 
+/* MAGIC_LAMP intentionally excluded below */
+/* age field of this is relative age rather than absolute */
+#define age_is_relative(otmp)	((otmp)->otyp == BRASS_LANTERN\
+				|| (otmp)->otyp == OIL_LAMP\
+				|| (otmp)->otyp == CANDELABRUM_OF_INVOCATION\
+				|| (otmp)->otyp == TALLOW_CANDLE\
+				|| (otmp)->otyp == WAX_CANDLE\
+				|| (otmp)->otyp == POT_OIL)
+/* object can be ignited */
+#define ignitable(otmp)	((otmp)->otyp == BRASS_LANTERN\
+				|| (otmp)->otyp == OIL_LAMP\
+				|| (otmp)->otyp == CANDELABRUM_OF_INVOCATION\
+				|| (otmp)->otyp == TALLOW_CANDLE\
+				|| (otmp)->otyp == WAX_CANDLE\
+				|| (otmp)->otyp == POT_OIL)
+
 /* special stones */
 #define is_graystone(obj)	((obj)->otyp == LUCKSTONE || \
 				 (obj)->otyp == LOADSTONE || \
diff -Naurd ../nethack-3.4.1/include/objclass.h ./include/objclass.h
--- ../nethack-3.4.1/include/objclass.h Sun Feb 23 14:43:21 2003
+++ ./include/objclass.h Mon Sep 1 14:33:32 2003
@@ -75,7 +75,7 @@
 #define is_corrodeable(otmp)	(objects[otmp->otyp].oc_material == COPPER || objects[otmp->otyp].oc_material == IRON)
 
 #define is_damageable(otmp) (is_rustprone(otmp) || is_flammable(otmp) || \
-				is_rottable || is_corrodeable(otmp))
+				is_rottable(otmp) || is_corrodeable(otmp))
 
 	schar	oc_subtyp;
 #define oc_skill	oc_subtyp   /* Skills of weapons, spellbooks, tools, gems */
diff -Naurd ../nethack-3.4.1/include/patchlevel.h ./include/patchlevel.h
--- ../nethack-3.4.1/include/patchlevel.h Sun Feb 23 14:43:21 2003
+++ ./include/patchlevel.h Mon Sep 1 14:33:32 2003
@@ -1,14 +1,14 @@
-/*	SCCS Id: @(#)patchlevel.h	3.4	2003/02/19	*/
+/*	SCCS Id: @(#)patchlevel.h	3.4	2003/08/21	*/
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
 /* NetHack may be freely redistributed.  See license for details. */
 
-/* NetHack 3.4.1 */
+/* NetHack 3.4.2 */
 #define VERSION_MAJOR	3
 #define VERSION_MINOR	4
 /*
  * PATCHLEVEL is updated for each release.
  */
-#define PATCHLEVEL	1
+#define PATCHLEVEL	2
 /*
  * Incrementing EDITLEVEL can be used to force invalidation of old bones
  * and save files.
@@ -34,12 +34,24 @@
  * PP = patch level, ee = edit level, L = literal suffix "L",
  * with all four numbers specified as two hexadecimal digits.
  */
-#define VERSION_COMPATIBILITY 0x03040000L
+#define VERSION_COMPATIBILITY 0x03040100L
 #endif
 
 /*****************************************************************************/
 /* Version 3.4.x */
 
+/*  Patch 2, August 30, 2003
+ *  Fix a fatal bug that caused a crash when applying figurine, candle, or
+ *      bell that gets used up
+ *  Fix a fatal bug that triggered a panic when your secondary weapon was
+ *      cursed during bones file creation
+ *  Several dozen general bug fixes
+ *  Fixed some Gnome compilation problems on Redhat 7.2 and 8.0
+ *  Fixed a problem in the util Makefile
+ *  Use random() by default under linux instead of lrand48()
+ *  win32 tty adjustments and support for loading alternative key handlers
+ */
+
 /*  Patch 1, February 22, 2003
  *  Fix a few fatal errors including one for reentering shops, one
  *     involving land mines and boulders/statues, one for delayed
diff -Naurd ../nethack-3.4.1/include/system.h ./include/system.h
--- ../nethack-3.4.1/include/system.h Sun Feb 23 14:43:22 2003
+++ ./include/system.h Mon Sep 1 14:33:32 2003
@@ -79,7 +79,7 @@
 # if !defined(__SC__) && !defined(LINUX)
 E  long NDECL(random);
 # endif
-# if !defined(SUNOS4) || defined(RANDOM)
+# if (!defined(SUNOS4) && !defined(bsdi) && !defined(__FreeBSD__)) || defined(RANDOM)
 E void FDECL(srandom, (unsigned int));
 # else
 #  if !defined(bsdi) && !defined(__FreeBSD__)
@@ -521,7 +521,7 @@
 #  endif
 # endif
 
-# if defined(ULTRIX) || defined(SYSV) || defined(MICRO) || defined(VMS) || defined(MAC) || (defined(HPUX) && defined(_POSIX_SOURCE))
+# if defined(ULTRIX) || (defined(BSD) && defined(POSIX_TYPES)) || defined(SYSV) || defined(MICRO) || defined(VMS) || defined(MAC) || (defined(HPUX) && defined(_POSIX_SOURCE))
 E time_t FDECL(time, (time_t *));
 # else
 E long FDECL(time, (time_t *));
diff -Naurd ../nethack-3.4.1/include/winprocs.h ./include/winprocs.h
--- ../nethack-3.4.1/include/winprocs.h Sun Feb 23 14:43:24 2003
+++ ./include/winprocs.h Mon Sep 1 14:33:32 2003
@@ -8,6 +8,7 @@
 struct window_procs {
     const char *name;
     unsigned long wincap;	/* window port capability options supported */
+    unsigned long wincap2;	/* additional window port capability options supported */
     void FDECL((*win_init_nhwindows), (int *, char **));
     void NDECL((*win_player_selection));
     void NDECL((*win_askname));
@@ -108,7 +109,6 @@
 #define nh_poskey (*windowprocs.win_nh_poskey)
 #define nhbell (*windowprocs.win_nhbell)
 #define nh_doprev_message (*windowprocs.win_doprev_message)
-#define yn_function (*windowprocs.win_yn_function)
 #define getlin (*windowprocs.win_getlin)
 #define get_ext_cmd (*windowprocs.win_get_ext_cmd)
 #define number_pad (*windowprocs.win_number_pad)
@@ -122,6 +122,12 @@
 #define get_color_string (*windowprocs.win_get_color_string)
 #endif
 
+/* 3.4.2: There is a real yn_function() in the core now, which does
+ *        some buffer length validation on the parameters prior to
+ *        invoking the window port routine. yn_function() is in cmd.c
+ */
+/* #define yn_function (*windowprocs.win_yn_function) */
+
 /* other defs that really should go away (they're tty specific) */
 #define start_screen (*windowprocs.win_start_screen)
 #define end_screen (*windowprocs.win_end_screen)
@@ -168,6 +174,11 @@
 #define WC_MOUSE_SUPPORT 0x80000000L	/* 32 mouse support                          */
 					/* no free bits */
 
+#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 ALIGN_LEFT	1
 #define ALIGN_RIGHT	2
 #define ALIGN_TOP	3
diff -Naurd ../nethack-3.4.1/include/wintype.h ./include/wintype.h
--- ../nethack-3.4.1/include/wintype.h Sun Feb 23 14:43:24 2003
+++ ./include/wintype.h Mon Sep 1 14:33:32 2003
@@ -13,6 +13,7 @@
     struct obj *a_obj;
     int  a_int;
     char a_char;
+    schar a_schar;
     /* add types as needed */
 } anything;
 #define ANY_P union any /* avoid typedef in prototypes */
diff -Naurd ../nethack-3.4.1/src/allmain.c ./src/allmain.c
--- ../nethack-3.4.1/src/allmain.c Sun Feb 23 14:43:24 2003
+++ ./src/allmain.c Mon Sep 1 14:33:32 2003
@@ -1,4 +1,4 @@
-/*	SCCS Id: @(#)allmain.c	3.4	2002/01/04	*/
+/*	SCCS Id: @(#)allmain.c	3.4	2003/04/02	*/
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
 /* NetHack may be freely redistributed.  See license for details. */
 
@@ -60,9 +60,6 @@
     youmonst.movement = NORMAL_SPEED;	/* give the hero some movement points */
 
     for(;;) {
-#ifdef CLIPPING
-	cliparound(u.ux, u.uy);
-#endif
 	get_nh_event();
 #ifdef POSITIONBAR
 	do_positionbar();
@@ -381,6 +378,11 @@
 	    sanity_check();
 #endif
 
+#ifdef CLIPPING
+	/* just before rhack */
+	cliparound(u.ux, u.uy);
+#endif
+
 	u.umoved = FALSE;
 
 	if (multi > 0) {
@@ -495,10 +497,11 @@
 				 * and init_artifacts() */
 
 	init_dungeons();	/* must be before u_init() to avoid rndmonst()
-				 * creating odd monsters for initial tins and
-				 * eggs */
+				 * creating odd monsters for any tins and eggs
+				 * in hero's initial inventory */
+	init_artifacts();	/* before u_init() in case $WIZKIT specifies
+				 * any artifacts */
 	u_init();
-	init_artifacts();
 
 #ifndef NO_SIGNAL
 	(void) signal(SIGINT, (SIG_RET_TYPE) done1);
diff -Naurd ../nethack-3.4.1/src/apply.c ./src/apply.c
--- ../nethack-3.4.1/src/apply.c Sun Feb 23 14:43:24 2003
+++ ./src/apply.c Mon Sep 1 14:33:32 2003
@@ -1,4 +1,4 @@
-/*	SCCS Id: @(#)apply.c	3.4	2003/02/13	*/
+/*	SCCS Id: @(#)apply.c	3.4	2003/05/25	*/
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
 /* NetHack may be freely redistributed.  See license for details. */
 
@@ -21,13 +21,13 @@
 STATIC_DCL void FDECL(use_magic_whistle, (struct obj *));
 STATIC_DCL void FDECL(use_leash, (struct obj *));
 STATIC_DCL int FDECL(use_mirror, (struct obj *));
-STATIC_DCL void FDECL(use_bell, (struct obj *));
+STATIC_DCL void FDECL(use_bell, (struct obj **));
 STATIC_DCL void FDECL(use_candelabrum, (struct obj *));
-STATIC_DCL void FDECL(use_candle, (struct obj *));
+STATIC_DCL void FDECL(use_candle, (struct obj **));
 STATIC_DCL void FDECL(use_lamp, (struct obj *));
 STATIC_DCL void FDECL(light_cocktail, (struct obj *));
 STATIC_DCL void FDECL(use_tinning_kit, (struct obj *));
-STATIC_DCL void FDECL(use_figurine, (struct obj *));
+STATIC_DCL void FDECL(use_figurine, (struct obj **));
 STATIC_DCL void FDECL(use_grease, (struct obj *));
 STATIC_DCL void FDECL(use_trap, (struct obj *));
 STATIC_DCL void FDECL(use_stone, (struct obj *));
@@ -65,8 +65,8 @@
 		pline(nothing_happens);
 		return (1);
 	}
-	check_unpaid(obj);
-	obj->spe--;
+	consume_obj_charge(obj, TRUE);
+
 	if (obj->cursed && !rn2(2)) {
 		(void) zapyourself(obj, TRUE);
 	} else if (u.uswallow) {
@@ -202,10 +202,13 @@
 use_stethoscope(obj)
 	register struct obj *obj;
 {
-	static long last_used = 0;
+	static long last_used_move = -1;
+	static short last_used_movement = 0;
 	struct monst *mtmp;
 	struct rm *lev;
 	int rx, ry, res;
+	boolean interference = (u.uswallow && is_whirly(u.ustuck->data) &&
+				!rn2(Role_if(PM_HEALER) ? 10 : 3));
 
 	if (nohands(youmonst.data)) {	/* should also check for no ears and/or deaf */
 		You("have no hands!");	/* not `body_part(HAND)' */
@@ -216,17 +219,28 @@
 	}
 	if (!getdir((char *)0)) return 0;
 
-	res = (moves + monstermoves == last_used);
-	last_used = moves + monstermoves;
+	res = (moves == last_used_move) &&
+	      (youmonst.movement == last_used_movement);
+	last_used_move = moves;
+	last_used_movement = youmonst.movement;
 
+#ifdef STEED
+	if (u.usteed && u.dz > 0) {
+		if (interference) {
+			pline("%s interferes.", Monnam(u.ustuck));
+			mstatusline(u.ustuck);
+		} else
+			mstatusline(u.usteed);
+		return res;
+	} else
+#endif
 	if (u.uswallow && (u.dx || u.dy || u.dz)) {
 		mstatusline(u.ustuck);
 		return res;
-#ifdef STEED
-	} else if (u.usteed && u.dz > 0) {
-		mstatusline(u.usteed);
+	} else if (u.uswallow && interference) {
+		pline("%s interferes.", Monnam(u.ustuck));
+		mstatusline(u.ustuck);
 		return res;
-#endif
 	} else if (u.dz) {
 		if (Underwater)
 		    You_hear("faint splashing.");
@@ -725,9 +739,10 @@
 }
 
 STATIC_OVL void
-use_bell(obj)
-register struct obj *obj;
+use_bell(optr)
+struct obj **optr;
 {
+	register struct obj *obj = *optr;
 	struct monst *mtmp;
 	boolean wakem = FALSE, learno = FALSE,
 		ordinary = (obj->otyp != BELL_OF_OPENING || !obj->spe),
@@ -762,6 +777,7 @@
 		if (!obj_resists(obj, 93, 100)) {
 		    pline("%s shattered!", Tobjnam(obj, "have"));
 		    useup(obj);
+		    *optr = 0;
 		} else switch (rn2(3)) {
 			default:
 				break;
@@ -778,8 +794,7 @@
 
 	} else {
 	    /* charged Bell of Opening */
-	    check_unpaid(obj);
-	    obj->spe--;
+	    consume_obj_charge(obj, TRUE);
 
 	    if (u.uswallow) {
 		if (!obj->cursed)
@@ -893,9 +908,10 @@
 }
 
 STATIC_OVL void
-use_candle(obj)
-register struct obj *obj;
+use_candle(optr)
+struct obj **optr;
 {
+	register struct obj *obj = *optr;
 	register struct obj *otmp;
 	const char *s = (obj->quan != 1) ? "candles" : "candle";
 	char qbuf[QBUFSZ];
@@ -916,7 +932,9 @@
 	}
 
 	Sprintf(qbuf, "Attach %s", the(xname(obj)));
-	Sprintf(eos(qbuf), " to %s?", the(xname(otmp)));
+	Sprintf(eos(qbuf), " to %s?",
+		safe_qbuf(qbuf, sizeof(" to ?"), the(xname(otmp)),
+			the(simple_typename(otmp->otyp)), "it"));
 	if(yn(qbuf) == 'n') {
 		if (!obj->lamplit)
 		    You("try to light %s...", the(xname(obj)));
@@ -925,6 +943,7 @@
 	} else {
 		if ((long)otmp->spe + obj->quan > 7L)
 		    obj = splitobj(obj, 7L - (long)otmp->spe);
+		else *optr = 0;
 		You("attach %ld%s %s to %s.",
 		    obj->quan, !otmp->spe ? "" : " more",
 		    s, the(xname(otmp)));
@@ -1007,10 +1026,7 @@
 {
 	xchar x, y;
 
-	if (!obj->lamplit && (obj->otyp == CANDELABRUM_OF_INVOCATION ||
-		obj->otyp == WAX_CANDLE || obj->otyp == TALLOW_CANDLE ||
-		obj->otyp == OIL_LAMP || obj->otyp == MAGIC_LAMP ||
-		obj->otyp == BRASS_LANTERN || obj->otyp == POT_OIL)) {
+	if (!obj->lamplit && (obj->otyp == MAGIC_LAMP || ignitable(obj))) {
 	    if ((obj->otyp == MAGIC_LAMP ||
 		 obj->otyp == CANDELABRUM_OF_INVOCATION) &&
 		obj->spe == 0)
@@ -1398,7 +1414,8 @@
 		pline("That's too insubstantial to tin.");
 		return;
 	}
-	obj->spe--;
+	consume_obj_charge(obj, TRUE);
+
 	if ((can = mksobj(TIN, FALSE, FALSE)) != 0) {
 	    static const char you_buy_it[] = "You tin it, you bought it!";
 
@@ -1696,9 +1713,10 @@
 }
 
 STATIC_OVL void
-use_figurine(obj)
-register struct obj *obj;
+use_figurine(optr)
+struct obj **optr;
 {
+	register struct obj *obj = *optr;
 	xchar x, y;
 	coord cc;
 
@@ -1726,6 +1744,7 @@
 	(void) make_familiar(obj, cc.x, cc.y, FALSE);
 	(void) stop_timer(FIG_TRANSFORM, (genericptr_t)obj);
 	useup(obj);
+	*optr = 0;
 }
 
 static NEARDATA const char lubricables[] = { ALL_CLASSES, ALLOW_NONE, 0 };
@@ -1748,8 +1767,8 @@
 
 	if (obj->spe > 0) {
 		if ((obj->cursed || Fumbling) && !rn2(2)) {
-			check_unpaid(obj);
-			obj->spe--;
+			consume_obj_charge(obj, TRUE);
+
 			pline("%s from your %s.", Tobjnam(obj, "slip"),
 			      makeplural(body_part(FINGER)));
 			dropx(obj);
@@ -1771,8 +1790,8 @@
 			return;
 		}
 #endif
-		check_unpaid(obj);
-		obj->spe--;
+		consume_obj_charge(obj, TRUE);
+
 		if (otmp != &zeroobj) {
 			You("cover %s with a thick layer of grease.",
 			    yname(otmp));
@@ -1800,12 +1819,14 @@
 	struct obj *tobj;
 	xchar tx, ty;
 	int time_needed;
+	boolean force_bungle;
 } trapinfo;
 
 void
 reset_trapset()
 {
 	trapinfo.tobj = 0;
+	trapinfo.force_bungle = 0;
 }
 
 /* touchstones - by Ken Arnold */
@@ -2004,7 +2025,37 @@
 	    trapinfo.time_needed += (tmp > 12) ? 1 : (tmp > 7) ? 2 : 4;
 	/*[fumbling and/or confusion and/or cursed object check(s)
 	   should be incorporated here instead of in set_trap]*/
+#ifdef STEED
+	if (u.usteed && P_SKILL(P_RIDING) < P_BASIC) {
+	    boolean chance;
 
+	    if (Fumbling || otmp->cursed) chance = (rnl(10) > 3);
+	    else  chance = (rnl(10) > 5);
+	    You("aren't very skilled at reaching from %s.",
+		mon_nam(u.usteed));
+	    Sprintf(buf, "Continue your attempt to set %s?",
+		the(defsyms[trap_to_defsym(what_trap(ttyp))].explanation));
+	    if(yn(buf) == 'y') {
+		if (chance) {
+			switch(ttyp) {
+			    case LANDMINE:	/* set it off */
+			    	trapinfo.time_needed = 0;
+			    	trapinfo.force_bungle = TRUE;
+				break;
+			    case BEAR_TRAP:	/* drop it without arming it */
+				reset_trapset();
+				You("drop %s!",
+			  the(defsyms[trap_to_defsym(what_trap(ttyp))].explanation));
+				dropx(otmp);
+				return;
+			}
+		}
+	    } else {
+	    	reset_trapset();
+		return;
+	    }
+	}
+#endif
 	You("begin setting %s %s.",
 	    shk_your(buf, otmp),
 	    defsyms[trap_to_defsym(what_trap(ttyp))].explanation);
@@ -2038,9 +2089,12 @@
 	    if (*in_rooms(u.ux,u.uy,SHOPBASE)) {
 		add_damage(u.ux, u.uy, 0L);		/* schedule removal */
 	    }
-	    You("finish arming %s.",
-		the(defsyms[trap_to_defsym(what_trap(ttyp))].explanation));
-	    if ((otmp->cursed || Fumbling) && (rnl(10) > 5)) dotrap(ttmp, 0);
+	    if (!trapinfo.force_bungle)
+		You("finish arming %s.",
+			the(defsyms[trap_to_defsym(what_trap(ttyp))].explanation));
+	    if (((otmp->cursed || Fumbling) && (rnl(10) > 5)) || trapinfo.force_bungle)
+		dotrap(ttmp,
+			(unsigned)(trapinfo.force_bungle ? FORCEBUNGLE : 0));
 	} else {
 	    /* this shouldn't happen */
 	    Your("trap setting attempt fails.");
@@ -2344,7 +2398,9 @@
 	} else if (distu(cc.x, cc.y) < min_range) {
 	    pline("Too close!");
 	    return (res);
-	} else if (!cansee(cc.x, cc.y)) {
+	} else if (!cansee(cc.x, cc.y) &&
+		   ((mtmp = m_at(cc.x, cc.y)) == (struct monst *)0 ||
+		    !canseemon(mtmp))) {
 	    You(cant_see_spot);
 	    return (res);
 	}
@@ -2545,7 +2601,9 @@
     char confirm[QBUFSZ], the_wand[BUFSZ], buf[BUFSZ];
 
     Strcpy(the_wand, yname(obj));
-    Sprintf(confirm, "Are you really sure you want to break %s?", the_wand);
+    Sprintf(confirm, "Are you really sure you want to break %s?",
+	safe_qbuf("", sizeof("Are you really sure you want to break ?"),
+				the_wand, ysimple_name(obj), "the wand"));
     if (yn(confirm) == 'n' ) return 0;
 
     if (nohands(youmonst.data)) {
@@ -2712,7 +2770,7 @@
 int
 doapply()
 {
-	register struct obj *obj;
+	struct obj *obj;
 	register int res = 1;
 	char class_list[MAXOCLASSES+2];
 
@@ -2765,18 +2823,7 @@
 		res = use_container(obj, 1);
 		break;
 	case BAG_OF_TRICKS:
-		if(obj->spe > 0) {
-			register int cnt = 1;
-
-			check_unpaid(obj);
-			obj->spe--;
-			if(!rn2(23)) cnt += rn2(7) + 1;
-			while(cnt--)
-			   (void) makemon((struct permonst *) 0,
-						u.ux, u.uy, NO_MM_FLAGS);
-			makeknown(BAG_OF_TRICKS);
-		} else
-			pline(nothing_happens);
+		bagotricks(obj);
 		break;
 	case CAN_OF_GREASE:
 		use_grease(obj);
@@ -2838,14 +2885,14 @@
 		break;
 	case BELL:
 	case BELL_OF_OPENING:
-		use_bell(obj);
+		use_bell(&obj);
 		break;
 	case CANDELABRUM_OF_INVOCATION:
 		use_candelabrum(obj);
 		break;
 	case WAX_CANDLE:
 	case TALLOW_CANDLE:
-		use_candle(obj);
+		use_candle(&obj);
 		break;
 	case OIL_LAMP:
 	case MAGIC_LAMP:
@@ -2882,7 +2929,7 @@
 		goto xit;
 
 	case FIGURINE:
-		use_figurine(obj);
+		use_figurine(&obj);
 		break;
 	case UNICORN_HORN:
 		use_unicorn_horn(obj);
@@ -2904,8 +2951,7 @@
 		    struct obj *otmp;
 		    const char *what;
 
-		    check_unpaid(obj);
-		    obj->spe--;
+		    consume_obj_charge(obj, TRUE);
 		    if (!rn2(13)) {
 			otmp = mkobj(POTION_CLASS, FALSE);
 			if (objects[otmp->otyp].oc_magic) do {
@@ -2960,7 +3006,7 @@
 		nomul(0);
 		return 0;
 	}
-	if (res && obj->oartifact) arti_speak(obj);
+	if (res && obj && obj->oartifact) arti_speak(obj);
 	nomul(0);
 	return res;
 }
diff -Naurd ../nethack-3.4.1/src/artifact.c ./src/artifact.c
--- ../nethack-3.4.1/src/artifact.c Sun Feb 23 14:43:24 2003
+++ ./src/artifact.c Mon Sep 1 14:33:32 2003
@@ -1,4 +1,4 @@
-/*	SCCS Id: @(#)artifact.c 3.4	2003/02/08	*/
+/*	SCCS Id: @(#)artifact.c 3.4	2003/08/11	*/
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
 /* NetHack may be freely redistributed.  See license for details. */
 
@@ -821,6 +821,10 @@
     switch (attack_indx) {
     case MB_INDEX_CANCEL:
 	old_uasmon = youmonst.data;
+	/* No mdef->mcan check: even a cancelled monster can be polymorphed
+	 * into a golem, and the "cancel" effect acts as if some magical
+	 * energy remains in spellcasting defenders to be absorbed later.
+	 */
 	if (!cancel_monst(mdef, mb, youattack, FALSE, FALSE)) {
 	    resisted = TRUE;
 	} else {
@@ -938,7 +942,8 @@
 	boolean youattack = (magr == &youmonst);
 	boolean youdefend = (mdef == &youmonst);
 	boolean vis = (!youattack && magr && cansee(magr->mx, magr->my))
-		|| (!youdefend && cansee(mdef->mx, mdef->my));
+	    || (!youdefend && cansee(mdef->mx, mdef->my))
+	    || (youattack && u.uswallow && mdef == u.ustuck && !Blind);
 	boolean realizes_damage;
 	const char *wepdesc;
 	static const char you[] = "you";
@@ -1194,7 +1199,8 @@
 	/* It's a special power, not "just" a property */
 	if(obj->age > monstermoves) {
 	    /* the artifact is tired :-) */
-	    You_feel("that %s is ignoring you.", the(xname(obj)));
+	    You_feel("that %s %s ignoring you.",
+		     the(xname(obj)), otense(obj, "are"));
 	    /* and just got more so; patience is essential... */
 	    obj->age += (long) d(3,10);
 	    return 1;
@@ -1352,7 +1358,8 @@
 	if(on && obj->age > monstermoves) {
 	    /* the artifact is tired :-) */
 	    u.uprops[oart->inv_prop].extrinsic ^= W_ARTI;
-	    You_feel("that %s is ignoring you.", the(xname(obj)));
+	    You_feel("that %s %s ignoring you.",
+		     the(xname(obj)), otense(obj, "are"));
 	    /* can't just keep repeatedly trying */
 	    obj->age += (long) d(3,10);
 	    return 1;
diff -Naurd ../nethack-3.4.1/src/bones.c ./src/bones.c
--- ../nethack-3.4.1/src/bones.c Sun Feb 23 14:43:25 2003
+++ ./src/bones.c Mon Sep 1 14:33:32 2003
@@ -106,6 +106,7 @@
 				otmp->quan = (long)otmp->spe;
 			    otmp->spe = 0;
 			    otmp->owt = weight(otmp);
+			    curse(otmp);
 			} else if (otmp->otyp == BELL_OF_OPENING) {
 			    otmp->otyp = BELL;
 			    curse(otmp);
@@ -124,6 +125,7 @@
 {
 	struct obj *otmp;
 
+	uswapwep = 0; /* ensure curse() won't cause swapwep to drop twice */
 	while ((otmp = invent) != 0) {
 		obj_extract_self(otmp);
 		obj_no_longer_held(otmp);
diff -Naurd ../nethack-3.4.1/src/cmd.c ./src/cmd.c
--- ../nethack-3.4.1/src/cmd.c Sun Feb 23 14:43:25 2003
+++ ./src/cmd.c Mon Sep 1 14:33:32 2003
@@ -552,7 +552,7 @@
 STATIC_PTR int
 wiz_where()
 {
-	if (wizard) print_dungeon();
+	if (wizard) (void) print_dungeon(FALSE);
 	else	    pline("Unavailable command '^O'.");
 	return 0;
 }
@@ -1789,7 +1789,18 @@
 		flags.move = FALSE;
 		return;		/* probably we just had an interrupt */
 	}
-
+	if (iflags.num_pad && iflags.num_pad_mode == 1) {
+		/* This handles very old inconsistent DOS/Windows behaviour
+		 * in a new way: earlier, the keyboard handler mapped these,
+		 * which caused counts to be strange when entered from the
+		 * number pad. Now do not map them until here. 
+		 */
+		switch (*cmd) {
+		    case '5':       *cmd = 'g'; break;
+		    case M('5'):    *cmd = 'G'; break;
+		    case M('0'):    *cmd = 'I'; break;
+        	}
+        }
 	/* handle most movement commands */
 	do_walk = do_rush = prefix_seen = FALSE;
 	flags.travel = 0;
@@ -2091,20 +2102,34 @@
 		putstr(win, 0, "");
 	    }
 	}
-	if (iflags.num_pad) {
-		putstr(win, 0, "Valid direction keys (with number_pad on) are:");
-		putstr(win, 0, "          7  8  9");
-		putstr(win, 0, "           \\ | / ");
-		putstr(win, 0, "          4- . -6");
-		putstr(win, 0, "           / | \\ ");
-		putstr(win, 0, "          1  2  3");
+	if (iflags.num_pad && u.umonnum == PM_GRID_BUG) {
+	    putstr(win, 0, "Valid direction keys in your current form (with number_pad on) are:");
+	    putstr(win, 0, "             8   ");
+	    putstr(win, 0, "             |   ");
+	    putstr(win, 0, "          4- . -6");
+	    putstr(win, 0, "             |   ");
+	    putstr(win, 0, "             2   ");
+	} else if (u.umonnum == PM_GRID_BUG) {
+	    putstr(win, 0, "Valid direction keys in your current form are:");
+	    putstr(win, 0, "             k   ");
+	    putstr(win, 0, "             |   ");
+	    putstr(win, 0, "          h- . -l");
+	    putstr(win, 0, "             |   ");
+	    putstr(win, 0, "             j   ");
+	} else if (iflags.num_pad) {
+	    putstr(win, 0, "Valid direction keys (with number_pad on) are:");
+	    putstr(win, 0, "          7  8  9");
+	    putstr(win, 0, "           \\ | / ");
+	    putstr(win, 0, "          4- . -6");
+	    putstr(win, 0, "           / | \\ ");
+	    putstr(win, 0, "          1  2  3");
 	} else {
-		putstr(win, 0, "Valid direction keys are:");
-		putstr(win, 0, "          y  k  u");
-		putstr(win, 0, "           \\ | / ");
-		putstr(win, 0, "          h- . -l");
-		putstr(win, 0, "           / | \\ ");
-		putstr(win, 0, "          b  j  n");
+	    putstr(win, 0, "Valid direction keys are:");
+	    putstr(win, 0, "          y  k  u");
+	    putstr(win, 0, "           \\ | / ");
+	    putstr(win, 0, "          h- . -l");
+	    putstr(win, 0, "           / | \\ ");
+	    putstr(win, 0, "          b  j  n");
 	};
 	putstr(win, 0, "");
 	putstr(win, 0, "          <  up");
@@ -2322,7 +2347,7 @@
 {
 	exit_nhwindows("End of input?");
 #ifndef NOSAVEONHANGUP
-	if (!program_state.done_hup++)
+	if (!program_state.done_hup++ && program_state.something_worth_saving)
 	    (void) dosave0();
 #endif
 	clearlocks();
@@ -2384,15 +2409,20 @@
 
 	if (!iflags.travelcmd) return 0;
 	cmd[1]=0;
-	cc.x = u.ux;
-	cc.y = u.uy;
+	cc.x = iflags.travelcc.x;
+	cc.y = iflags.travelcc.y;
+	if (cc.x == -1 && cc.y == -1) {
+	    /* No cached destination, start attempt from current position */
+	    cc.x = u.ux;
+	    cc.y = u.uy;
+	}
 	pline("Where do you want to travel to?");
 	if (getpos(&cc, TRUE, "the desired destination") < 0) {
 		/* user pressed ESC */
 		return 0;
 	}
-	u.tx = cc.x;
-	u.ty = cc.y;
+	iflags.travelcc.x = u.tx = cc.x;
+	iflags.travelcc.y = u.ty = cc.y;
 	cmd[0] = CMD_TRAVEL;
 	readchar_queue = cmd;
 	return 0;
@@ -2447,5 +2479,31 @@
 # endif /*PORT_DEBUG*/
 
 #endif /* OVL0 */
+#ifdef OVLB
+/*
+ *   Parameter validator for generic yes/no function to prevent
+ *   the core from sending too long a prompt string to the
+ *   window port causing a buffer overflow there.
+ */
+char
+yn_function(query,resp, def)
+const char *query,*resp;
+char def;
+{
+	char qbuf[QBUFSZ];
+	unsigned truncspot, reduction = sizeof(" [N]  ?") + 1;
+
+	if (resp) reduction += strlen(resp) + sizeof(" () ");
+	if (strlen(query) < (QBUFSZ - reduction))
+		return (*windowprocs.win_yn_function)(query, resp, def);
+	paniclog("Query truncated: ", query);
+	reduction += sizeof("...");
+	truncspot = QBUFSZ - reduction;
+	(void) strncpy(qbuf, query, (int)truncspot);
+	qbuf[truncspot] = '\0';
+	Strcat(qbuf,"...");
+	return (*windowprocs.win_yn_function)(qbuf, resp, def);
+}
+#endif
 
 /*cmd.c*/
diff -Naurd ../nethack-3.4.1/src/detect.c ./src/detect.c
--- ../nethack-3.4.1/src/detect.c Sun Feb 23 14:43:25 2003
+++ ./src/detect.c Mon Sep 1 14:33:32 2003
@@ -1,4 +1,4 @@
-/*	SCCS Id: @(#)detect.c	3.4	1999/12/06	*/
+/*	SCCS Id: @(#)detect.c	3.4	2003/08/13	*/
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
 /* NetHack may be freely redistributed.  See license for details. */
 
@@ -797,11 +797,11 @@
 	    break;
 	case 5 : pline("%s!", Tobjnam(obj, "explode"));
 	    useup(obj);
+	    obj = 0;	/* it's gone */
 	    losehp(rnd(30), "exploding crystal ball", KILLED_BY_AN);
 	    break;
 	}
-	check_unpaid(obj);
-	obj->spe--;
+	if (obj) consume_obj_charge(obj, TRUE);
 	return;
     }
 
@@ -825,8 +825,7 @@
 	    default: pline("Oh wow... like a kaleidoscope!");
 		break;
 	    }
-	    check_unpaid(obj);
-	    obj->spe--;
+	    consume_obj_charge(obj, TRUE);
 	}
 	return;
     }
@@ -848,8 +847,7 @@
 	int ret = 0;
 
 	makeknown(CRYSTAL_BALL);
-	check_unpaid(obj);
-	obj->spe--;
+	consume_obj_charge(obj, TRUE);
 
 	if ((class = def_char_to_objclass(ch)) != MAXOCLASSES)
 		ret = object_detect((struct obj *)0, class);
diff -Naurd ../nethack-3.4.1/src/dig.c ./src/dig.c
--- ../nethack-3.4.1/src/dig.c Sun Feb 23 14:43:25 2003
+++ ./src/dig.c Mon Sep 1 14:33:32 2003
@@ -1,4 +1,4 @@
-/*	SCCS Id: @(#)dig.c	3.4	2003/01/29	*/
+/*	SCCS Id: @(#)dig.c	3.4	2003/03/23	*/
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
 /* NetHack may be freely redistributed.  See license for details. */
 
@@ -492,6 +492,8 @@
 	boolean at_u = (x == u.ux) && (y == u.uy);
 	boolean wont_fall = Levitation || Flying;
 
+	if (u.utrap && u.utraptype == TT_INFLOOR) u.utrap = 0;
+
 	/* these furniture checks were in dighole(), but wand
 	   breaking bypasses that routine and calls us directly */
 	if (IS_FOUNTAIN(lev->typ)) {
@@ -546,11 +548,12 @@
 
 	    if(at_u) {
 		if (!wont_fall) {
+		    if (!Passes_walls)
 			u.utrap = rn1(4,2);
-			u.utraptype = TT_PIT;
-			vision_full_recalc = 1;	/* vision limits change */
+		    u.utraptype = TT_PIT;
+		    vision_full_recalc = 1;	/* vision limits change */
 		} else
-			u.utrap = 0;
+		    u.utrap = 0;
 		if (oldobjs != newobjs)	/* something unearthed */
 			(void) pickup(1);	/* detects pit */
 	    } else if(mtmp) {
@@ -1182,7 +1185,7 @@
 			(void)xname(otmp);	/* set dknown, maybe bknown */
 			stackobj(otmp);
 		    }
-		    if (Invisible) newsym(u.ux, u.uy);
+		    newsym(u.ux, u.uy);
 		} else {
 		    watch_dig((struct monst *)0, u.ux, u.uy, TRUE);
 		    (void) dighole(FALSE);
diff -Naurd ../nethack-3.4.1/src/display.c ./src/display.c
--- ../nethack-3.4.1/src/display.c Sun Feb 23 14:43:25 2003
+++ ./src/display.c Mon Sep 1 14:33:32 2003
@@ -272,9 +272,11 @@
 map_invisible(x, y)
 register xchar x, y;
 {
-    if (level.flags.hero_memory)
-	levl[x][y].glyph = GLYPH_INVISIBLE;
-    show_glyph(x, y, GLYPH_INVISIBLE);
+    if (x != u.ux || y != u.uy) { /* don't display I at hero's location */
+	if (level.flags.hero_memory)
+	    levl[x][y].glyph = GLYPH_INVISIBLE;
+	show_glyph(x, y, GLYPH_INVISIBLE);
+    }
 }
 
 /*
diff -Naurd ../nethack-3.4.1/src/do.c ./src/do.c
--- ../nethack-3.4.1/src/do.c Sun Feb 23 14:43:25 2003
+++ ./src/do.c Mon Sep 1 14:33:32 2003
@@ -1,4 +1,4 @@
-/*	SCCS Id: @(#)do.c	3.4	2002/09/08	*/
+/*	SCCS Id: @(#)do.c	3.4	2003/04/25	*/
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
 /* NetHack may be freely redistributed.  See license for details. */
 
@@ -801,7 +801,7 @@
 		trap->ttyp == HOLE ? "down the hole" : "through the trap door");
 
 	if (trap && Is_stronghold(&u.uz)) {
-		goto_hell(TRUE, TRUE);
+		goto_hell(FALSE, TRUE);
 	} else {
 		at_ladder = (boolean) (levl[u.ux][u.uy].typ == LADDER);
 		next_level(!trap);
diff -Naurd ../nethack-3.4.1/src/do_name.c ./src/do_name.c
--- ../nethack-3.4.1/src/do_name.c Sun Feb 23 14:43:26 2003
+++ ./src/do_name.c Mon Sep 1 14:33:32 2003
@@ -1002,6 +1002,15 @@
 		hcolors[rn2(SIZE(hcolors))] : colorpref;
 }
 
+/* return a random real color unless hallucinating */
+const char *
+rndcolor()
+{
+	int k = rn2(CLR_MAX);
+	return Hallucination ? hcolor((char *)0) : (k == NO_COLOR) ?
+		"colorless" : c_obj_colors[k];
+}
+
 /* Aliases for road-runner nemesis
  */
 static const char * const coynames[] = {
diff -Naurd ../nethack-3.4.1/src/do_wear.c ./src/do_wear.c
--- ../nethack-3.4.1/src/do_wear.c Sun Feb 23 14:43:26 2003
+++ ./src/do_wear.c Mon Sep 1 14:33:32 2003
@@ -1,4 +1,4 @@
-/*	SCCS Id: @(#)do_wear.c	3.4	2003/01/08	*/
+/*	SCCS Id: @(#)do_wear.c	3.4	2003/05/25	*/
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
 /* NetHack may be freely redistributed.  See license for details. */
 
@@ -10,7 +10,8 @@
 
 #else /* OVLB */
 
-STATIC_OVL NEARDATA long takeoff_mask = 0L, taking_off = 0L;
+STATIC_OVL NEARDATA long takeoff_mask = 0L;
+static NEARDATA long taking_off = 0L;
 
 static NEARDATA int todelay;
 static boolean cancelled_don = FALSE;
@@ -431,6 +432,7 @@
     }
     setworn((struct obj *)0, W_ARMG);
     cancelled_don = FALSE;
+    (void) encumber_msg();		/* immediate feedback for GoP */
 
     /* Prevent wielding cockatrice when not wearing gloves */
     if (uwep && uwep->otyp == CORPSE &&
@@ -993,8 +995,9 @@
 			      uskin->otyp >= GRAY_DRAGON_SCALES ?
 				"dragon scales are" : "dragon scale mail is");
 		else
-		    pline("Not wearing any armor.%s", iflags.cmdassist ?
-			" Use 'R' command to remove accessories." : "");
+		    pline("Not wearing any armor.%s", (iflags.cmdassist && 
+				(uleft || uright || uamul || ublindf)) ?
+			  "  Use 'R' command to remove accessories." : "");
 		return 0;
 	}
 	if (armorpieces > 1)
@@ -1038,8 +1041,13 @@
 	MOREACC(ublindf);
 
 	if(!Accessories) {
-		pline("Not wearing any accessories.%s", iflags.cmdassist ?
-			" Use 'T' command to take off non-accessories." : "");
+		pline("Not wearing any accessories.%s", (iflags.cmdassist &&
+			    (uarm || uarmc ||
+#ifdef TOURIST
+			     uarmu ||
+#endif
+			     uarms || uarmh || uarmg || uarmf)) ?
+		      "  Use 'T' command to take off armor." : "");
 		return(0);
 	}
 	if (Accessories != 1) otmp = getobj(accessories, "remove");
@@ -1447,6 +1455,8 @@
 	    You("cannot free your weapon hand to put on the ring.");
 			return(0);
 		}
+		if (otmp->oartifact && !touch_artifact(otmp, &youmonst))
+		    return 1; /* costs a turn even though it didn't get worn */
 		setworn(otmp, mask);
 		Ring_on(otmp);
 	} else if (otmp->oclass == AMULET_CLASS) {
@@ -1454,6 +1464,8 @@
 			already_wearing("an amulet");
 			return(0);
 		}
+		if (otmp->oartifact && !touch_artifact(otmp, &youmonst))
+		    return 1;
 		setworn(otmp, W_AMUL);
 		if (otmp->otyp == AMULET_OF_CHANGE) {
 			Amulet_on();
@@ -1484,6 +1496,8 @@
 			You_cant("wear that!");
 			return(0);
 		}
+		if (otmp->oartifact && !touch_artifact(otmp, &youmonst))
+		    return 1;
 		Blindf_on(otmp);
 		return(1);
 	}
@@ -1651,6 +1665,14 @@
     return (struct obj *)0;
 }
 
+/* also for praying; find worn item that confers "Unchanging" attribute */
+struct obj *
+unchanger()
+{
+    if (uamul && uamul->otyp == AMULET_OF_UNCHANGING) return uamul;
+    return 0;
+}
+
 STATIC_PTR
 int
 select_off(otmp)
diff -Naurd ../nethack-3.4.1/src/dogmove.c ./src/dogmove.c
--- ../nethack-3.4.1/src/dogmove.c Sun Feb 23 14:43:26 2003
+++ ./src/dogmove.c Mon Sep 1 14:33:32 2003
@@ -157,8 +157,10 @@
 	    /* TODO: Reveal presence of sea monster (especially sharks) */
 	} else
 	/* hack: observe the action if either new or old location is in view */
+	/* However, invisible monsters should still be "it" even though out of
+	   sight locations should not. */
 	if (cansee(x, y) || cansee(mtmp->mx, mtmp->my))
-	    pline("%s %s %s.", noit_Monnam(mtmp),
+	    pline("%s %s %s.", mon_visible(mtmp) ? noit_Monnam(mtmp) : "It",
 		  devour ? "devours" : "eats",
 		  (obj->oclass == FOOD_CLASS) ?
 			singular(obj, doname) : doname(obj));
diff -Naurd ../nethack-3.4.1/src/dokick.c ./src/dokick.c
--- ../nethack-3.4.1/src/dokick.c Sun Feb 23 14:43:26 2003
+++ ./src/dokick.c Mon Sep 1 14:33:32 2003
@@ -329,16 +329,75 @@
 	return(0);
 }
 
+/* container is kicked, dropped, thrown or otherwise impacted by player.
+ * Assumes container is on floor.  Checks contents for possible damage. */
+void
+container_impact_dmg(obj)
+struct obj *obj;
+{
+	struct monst *shkp;
+	struct obj *otmp, *otmp2;
+	long loss = 0L;
+	boolean costly, insider;
+	xchar x = obj->ox, y = obj->oy;
+
+	/* only consider normal containers */
+	if (!Is_container(obj) || Is_mbag(obj)) return;
+
+	costly = ((shkp = shop_keeper(*in_rooms(x, y, SHOPBASE))) &&
+		  costly_spot(x, y));
+	insider = (*u.ushops && inside_shop(u.ux, u.uy) &&
+		   *in_rooms(x, y, SHOPBASE) == *u.ushops);
+
+	for (otmp = obj->cobj; otmp; otmp = otmp2) {
+	    const char *result = (char *)0;
+
+	    otmp2 = otmp->nobj;
+	    if (objects[otmp->otyp].oc_material == GLASS &&
+		otmp->oclass != GEM_CLASS && !obj_resists(otmp, 33, 100)) {
+		result = "shatter";
+	    } else if (otmp->otyp == EGG && !rn2(3)) {
+		result = "cracking";
+	    }
+	    if (result) {
+		if (otmp->otyp == MIRROR) change_luck(-2);
+
+		/* eggs laid by you.  penalty is -1 per egg, max 5,
+		 * but it's always exactly 1 that breaks */
+		if (otmp->otyp == EGG && otmp->spe && otmp->corpsenm >= LOW_PM)
+		    change_luck(-1);
+		You_hear("a muffled %s.", result);
+		if (costly)
+		    loss += stolen_value(otmp, x, y,
+					 (boolean)shkp->mpeaceful, TRUE);
+		if (otmp->quan > 1L)
+		    useup(otmp);
+		else {
+		    obj_extract_self(otmp);
+		    obfree(otmp, (struct obj *) 0);
+		}
+	    }
+	}
+	if (costly && loss) {
+	    if (!insider) {
+		You("caused %ld %s worth of damage!", loss, currency(loss));
+		make_angry_shk(shkp, x, y);
+	    } else {
+		You("owe %s %ld %s for objects destroyed.",
+		    mon_nam(shkp), loss, currency(loss));
+	    }
+	}
+}
+
 STATIC_OVL int
 kick_object(x, y)
 xchar x, y;
 {
 	int range;
 	register struct monst *mon, *shkp;
-	register struct obj *otmp;
 	struct trap *trap;
 	char bhitroom;
-	boolean costly, insider, isgold, slide = FALSE;
+	boolean costly, isgold, slide = FALSE;
 
 	/* if a pile, the "top" object gets kicked */
 	kickobj = level.objects[x][y];
@@ -404,8 +463,6 @@
 
 	costly = ((shkp = shop_keeper(*in_rooms(x, y, SHOPBASE))) &&
 				    costly_spot(x, y));
-	insider = (*u.ushops && inside_shop(u.ux, u.uy) &&
-				    *in_rooms(x, y, SHOPBASE) == *u.ushops);
 	isgold = (kickobj->oclass == COIN_CLASS);
 
 	if (IS_ROCK(levl[x][y].typ) || closed_door(x, y)) {
@@ -441,51 +498,10 @@
 	/* a box gets a chance of breaking open here */
 	if(Is_box(kickobj)) {
 		boolean otrp = kickobj->otrapped;
-		struct obj *otmp2;
-		long loss = 0L;
 
 		if(range < 2) pline("THUD!");
 
-		for(otmp = kickobj->cobj; otmp; otmp = otmp2) {
-			const char *result = (char *)0;
-
-			otmp2 = otmp->nobj;
-			if (objects[otmp->otyp].oc_material == GLASS
-			    && otmp->oclass != GEM_CLASS
-			    && !obj_resists(otmp, 33, 100)) {
-				result = "shatter";
-			} else if (otmp->otyp == EGG && !rn2(3)) {
-				result = "cracking";
-			}
-			if (result) {
-				if (otmp->otyp == MIRROR)
-				    change_luck(-2);
-				/* eggs laid by you */
-				/* penalty is -1 per egg, max 5, but it's always
-				   exactly 1 that breaks */
-				if (otmp->otyp == EGG && otmp->spe && otmp->corpsenm >= LOW_PM)
-				    change_luck(-1);
-				You_hear("a muffled %s.",result);
-				if(costly) loss += stolen_value(otmp, x, y,
-					    (boolean)shkp->mpeaceful, TRUE);
-				if (otmp->quan > 1L)
-					useup(otmp);
-				else {
-					obj_extract_self(otmp);
-					obfree(otmp, (struct obj *) 0);
-				}
-			}
-		}
-		if(costly && loss) {
-		    if(!insider) {
-			You("caused %ld %s worth of damage!",
-			    loss, currency(loss));
-			make_angry_shk(shkp, x, y);
-		    } else {
-			You("owe %s %ld %s for objects destroyed.",
-			    mon_nam(shkp), loss, currency(loss));
-		    }
-		}
+		container_impact_dmg(kickobj);
 
 		if (kickobj->olocked) {
 		    if (!rn2(5) || (martial() && !rn2(2))) {
@@ -862,7 +878,7 @@
 		    exercise(A_DEX, TRUE);
 		    return(1);
 		}
-		if(IS_GRAVE(maploc->typ))
+		if(IS_GRAVE(maploc->typ) || maploc->typ == IRONBARS)
 		    goto ouch;
 		if(IS_TREE(maploc->typ)) {
 		    struct obj *treefruit;
@@ -875,16 +891,21 @@
 		    if (rn2(15) && !(maploc->looted & TREE_LOOTED) &&
 			  (treefruit = rnd_treefruit_at(x, y))) {
 			long nfruit = 8L-rnl(7), nfall;
+			short frtype = treefruit->otyp;
 			treefruit->quan = nfruit;
 			if (is_plural(treefruit))
 			    pline("Some %s fall from the tree!", xname(treefruit));
 			else
 			    pline("%s falls from the tree!", An(xname(treefruit)));
 			nfall = scatter(x,y,2,MAY_HIT,treefruit);
-			if ( nfall != nfruit ) {
-			    /* scatter left some in the tree */
+			if (nfall != nfruit) {
+			    /* scatter left some in the tree, but treefruit
+			     * may not refer to the correct object */
+			    treefruit = mksobj(frtype, TRUE, FALSE);
+			    treefruit->quan = nfruit-nfall;
 			    pline("%ld %s got caught in the branches.",
 				nfruit-nfall, xname(treefruit));
+			    dealloc_obj(treefruit);
 			}
 			exercise(A_DEX, TRUE);
 			exercise(A_WIS, TRUE);	/* discovered a new food source! */
diff -Naurd ../nethack-3.4.1/src/dothrow.c ./src/dothrow.c
--- ../nethack-3.4.1/src/dothrow.c Sun Feb 23 14:43:26 2003
+++ ./src/dothrow.c Mon Sep 1 14:33:32 2003
@@ -5,6 +5,7 @@
 /* Contains code for 't' (throw) */
 
 #include "hack.h"
+#include "edog.h"
 
 STATIC_DCL int FDECL(throw_obj, (struct obj *,int));
 STATIC_DCL void NDECL(autoquiver);
@@ -339,6 +340,7 @@
 	if (hero_breaks(obj, u.ux, u.uy, TRUE)) return;
 	if (ship_object(obj, u.ux, u.uy, FALSE)) return;
 	dropy(obj);
+	if (!u.uswallow) container_impact_dmg(obj);
 }
 
 /*
@@ -447,6 +449,8 @@
 	return FALSE;
     } else if (!in_out_region(x, y)) {
 	return FALSE;
+    } else if (*range == 0) {
+	return FALSE;			/* previous step wants to stop now */
     }
 
     if (!Passes_walls || !(may_pass = may_passwall(x, y))) {
@@ -532,7 +536,8 @@
 		   In_sokoban(&u.uz)) {
 		/* Air currents overcome the recoil */
     		dotrap(ttmp,0);
-		return FALSE;
+		*range = 0;
+		return TRUE;
     	} else {
 		if (ttmp->tseen)
 		    You("pass right over %s %s.",
@@ -815,10 +820,11 @@
 struct obj *obj;
 {
 	return (is_missile(obj) || is_spear(obj) ||
-			/* daggers and knife (excludes scalpel) */
-			(is_blade(obj) && (objects[obj->otyp].oc_dir & PIERCE)) ||
-			/* special cases [might want to add AXE] */
-			obj->otyp == WAR_HAMMER || obj->otyp == AKLYS);
+		/* daggers and knife (excludes scalpel) */
+		(is_blade(obj) && !is_sword(obj) &&
+		 (objects[obj->otyp].oc_dir & PIERCE)) ||
+		/* special cases [might want to add AXE] */
+		obj->otyp == WAR_HAMMER || obj->otyp == AKLYS);
 }
 
 /* the currently thrown object is returning to you (not for boomerangs) */
@@ -1083,6 +1089,8 @@
 		    newsym(bhitpos.x,bhitpos.y);
 		if (obj_sheds_light(obj))
 		    vision_full_recalc = 1;
+		if (!IS_SOFT(levl[bhitpos.x][bhitpos.y].typ))
+		    container_impact_dmg(obj);
 	}
 }
 
@@ -1300,11 +1308,26 @@
 		   sometimes disappear when thrown */
 		if (objects[otyp].oc_skill < P_NONE &&
 				objects[otyp].oc_skill > -P_BOOMERANG &&
-				!objects[otyp].oc_magic && rn2(3)) {
-		    if (*u.ushops)
-			check_shop_obj(obj, bhitpos.x,bhitpos.y, TRUE);
-		    obfree(obj, (struct obj *)0);
-		    return 1;
+				!objects[otyp].oc_magic) {
+		    /* we were breaking 2/3 of everything unconditionally.
+		     * we still don't want anything to survive unconditionally,
+		     * but we need ammo to stay around longer on average.
+		     */
+		    int broken, chance;
+		    chance = 3 + greatest_erosion(obj) - obj->spe;
+		    if (chance > 1)
+			broken = rn2(chance);
+		    else
+			broken = !rn2(4);
+		    if (obj->blessed && !rnl(4))
+			broken = 0;
+
+		    if (broken) {
+			if (*u.ushops)
+			    check_shop_obj(obj, bhitpos.x,bhitpos.y, TRUE);
+			obfree(obj, (struct obj *)0);
+			return 1;
+		    }
 		}
 		passive_obj(mon, obj, (struct attack *)0);
 	    } else {
@@ -1345,7 +1368,8 @@
 	    potionhit(mon, obj, TRUE);
 	    return 1;
 
-	} else if (befriend_with_obj(mon->data, obj)) {
+	} else if (befriend_with_obj(mon->data, obj) ||
+		   (mon->mtame && dogfood(mon, obj) <= ACCFOOD)) {
 	    if (tamedog(mon, obj))
 		return 1;           	/* obj is gone */
 	    else {
diff -Naurd ../nethack-3.4.1/src/dungeon.c ./src/dungeon.c
--- ../nethack-3.4.1/src/dungeon.c Sun Feb 23 14:43:26 2003
+++ ./src/dungeon.c Mon Sep 1 14:33:32 2003
@@ -44,7 +44,7 @@
 STATIC_DCL boolean FDECL(place_level, (int, struct proto_dungeon *));
 #ifdef WIZARD
 STATIC_DCL const char *FDECL(br_string, (int));
-STATIC_DCL void FDECL(print_branch, (winid, int, int, int));
+STATIC_DCL void FDECL(print_branch, (winid, int, int, int, BOOLEAN_P, char *));
 #endif
 
 #ifdef DEBUG
@@ -1519,7 +1519,6 @@
     return lev;
 }
 
-
 #ifdef WIZARD
 
 /* Convert a branch type to a string usable by print_dungeon(). */
@@ -1538,14 +1537,17 @@
 
 /* Print all child branches between the lower and upper bounds. */
 STATIC_OVL void
-print_branch(win, dnum, lower_bound, upper_bound)
+print_branch(win, dnum, lower_bound, upper_bound, bymenu, menuletter)
     winid win;
     int   dnum;
     int   lower_bound;
     int   upper_bound;
+    boolean bymenu;
+    char *menuletter;
 {
     branch *br;
     char buf[BUFSZ];
+    anything any;
 
     /* This assumes that end1 is the "parent". */
     for (br = branches; br; br = br->next) {
@@ -1555,14 +1557,25 @@
 		    br_string(br->type),
 		    dungeons[br->end2.dnum].dname,
 		    depth(&br->end1));
-	    putstr(win, 0, buf);
+	    if (bymenu) {
+	    	schar lev = depth(&br->end1);
+		any.a_void = 0;
+		if (lev >= 0) any.a_schar = lev + 1;
+		else any.a_schar = lev;
+		add_menu(win, NO_GLYPH, &any, *menuletter,
+				0, ATR_NONE, buf, MENU_UNSELECTED);
+		if (*menuletter == 'z') *menuletter = 'A';
+		else *menuletter += 1;
+	    } else
+		putstr(win, 0, buf);
 	}
     }
 }
 
 /* Print available dungeon information. */
-void
-print_dungeon()
+schar
+print_dungeon(bymenu)
+boolean bymenu;
 {
     int     i, last_level, nlev;
     char    buf[BUFSZ];
@@ -1570,7 +1583,14 @@
     s_level *slev;
     dungeon *dptr;
     branch  *br;
+
+    anything any;
+    char mlet;
     winid   win = create_nhwindow(NHW_MENU);
+    if (bymenu) {
+	start_menu(win);
+	mlet = 'a';
+    }
 
     for (i = 0, dptr = dungeons; i < n_dgns; i++, dptr++) {
 	nlev = dptr->num_dunlevs;
@@ -1588,7 +1608,11 @@
 		Sprintf(eos(buf), ", entrance on %d",
 			dptr->depth_start + dptr->entry_lev - 1);
 	}
-	putstr(win, 0, buf);
+	if (bymenu) {
+	    any.a_void = 0;
+	    add_menu(win, NO_GLYPH, &any, 0, 0, ATR_BOLD, buf, MENU_UNSELECTED);
+	} else
+	    putstr(win, 0, buf);
 
 	/*
 	 * Circle through the special levels to find levels that are in
@@ -1598,31 +1622,70 @@
 	    if (slev->dlevel.dnum != i) continue;
 
 	    /* print any branches before this level */
-	    print_branch(win, i, last_level, slev->dlevel.dlevel);
+	    print_branch(win, i, last_level, slev->dlevel.dlevel, bymenu, &mlet);
 
 	    Sprintf(buf, "   %s: %d", slev->proto, depth(&slev->dlevel));
 	    if (Is_stronghold(&slev->dlevel))
 		Sprintf(eos(buf), " (tune %s)", tune);
-	    putstr(win, 0, buf);
+	    if (bymenu) {
+	    	schar lev = depth(&slev->dlevel);
+		any.a_void = 0;
+		if (lev >= 0) any.a_schar = lev + 1;
+		else any.a_schar = lev;
+		add_menu(win, NO_GLYPH, &any, mlet, 0, ATR_NONE, buf, MENU_UNSELECTED);
+		if (mlet == 'z') mlet = 'A';
+		else mlet++;
+	    } else
+		putstr(win, 0, buf);
 
 	    last_level = slev->dlevel.dlevel;
 	}
 	/* print branches after the last special level */
-	print_branch(win, i, last_level, MAXLEVEL);
+	print_branch(win, i, last_level, MAXLEVEL, bymenu, &mlet);
     }
 
     /* Print out floating branches (if any). */
     for (first = TRUE, br = branches; br; br = br->next) {
 	if (br->end1.dnum == n_dgns) {
 	    if (first) {
-		putstr(win, 0, "");
-		putstr(win, 0, "Floating branches");
+	    	if (bymenu) {
+		    any.a_void = 0;
+		    add_menu(win, NO_GLYPH, &any, 0, 0, ATR_BOLD,
+				"Floating branches", MENU_UNSELECTED);
+	    	} else {
+		    putstr(win, 0, "");
+		    putstr(win, 0, "Floating branches");
+		}
 		first = FALSE;
 	    }
 	    Sprintf(buf, "   %s to %s",
 			br_string(br->type), dungeons[br->end2.dnum].dname);
-	    putstr(win, 0, buf);
+	    if (bymenu) {
+	    	schar lev = lev_by_name(dungeons[br->end2.dnum].dname);
+		any.a_void = 0;
+		if (lev >= 0) any.a_schar = lev + 1;
+		else any.a_schar = lev;
+		add_menu(win, NO_GLYPH, &any, mlet, 0, ATR_NONE, buf, MENU_UNSELECTED);
+		if (mlet == 'z') mlet = 'A';
+		else mlet++;
+	    } else
+		putstr(win, 0, buf);
+	}
+    }
+    if (bymenu) {
+    	int n;
+	menu_item *selected;
+	schar lev = 0;
+
+	end_menu(win, "Level teleport to where:");
+	n = select_menu(win, PICK_ONE, &selected);
+	destroy_nhwindow(win);
+	if (n > 0) {
+		lev = selected[0].item.a_schar;
+		if (lev > 0) lev--;
+		free((genericptr_t)selected);
 	}
+	return lev;
     }
 
     /* I hate searching for the invocation pos while debugging. -dean */
@@ -1654,6 +1717,7 @@
 
     display_nhwindow(win, TRUE);
     destroy_nhwindow(win);
+    return 0;
 }
 #endif /* WIZARD */
 
diff -Naurd ../nethack-3.4.1/src/eat.c ./src/eat.c
--- ../nethack-3.4.1/src/eat.c Sun Feb 23 14:43:26 2003
+++ ./src/eat.c Mon Sep 1 14:33:32 2003
@@ -258,6 +258,11 @@
 				killer = "a very rich meal";
 			} else {
 				killer = food_xname(food, FALSE);
+				if (food->otyp == CORPSE &&
+				    (mons[food->corpsenm].geno & G_UNIQ)) {
+				    killer = the(killer);
+				    killer_format = KILLED_BY;
+				}
 			}
 		} else {
 			You("choke over it.");
@@ -815,6 +820,7 @@
 	    case PM_STALKER:
 		if(!Invis) {
 			set_itimeout(&HInvis, (long)rn1(100, 50));
+			if (!Blind && !BInvis) self_invis_message();
 		} else {
 			if (!(HInvis & INTRINSIC)) You_feel("hidden!");
 			HInvis |= FROMOUTSIDE;
@@ -848,7 +854,7 @@
 #endif
 		    nomul(-tmp);
 		    Sprintf(buf, Hallucination ?
-			"You suddenly dread being peeled and mimick %s again!" :
+			"You suddenly dread being peeled and mimic %s again!" :
 			"You now prefer mimicking %s again.",
 			an(Upolyd ? youmonst.data->mname : urace.noun));
 		    eatmbuf = strcpy((char *) alloc(strlen(buf) + 1), buf);
@@ -1051,6 +1057,8 @@
 		 !tin.tin->no_charge)
 		|| tin.tin->unpaid)) {
 		verbalize("You open it, you bought it!");
+		/* charge for one at pre-eating cost */
+		if(tin.tin->quan > 1L) tin.tin = splitobj(tin.tin, 1L);
 		bill_dummy_object(tin.tin);
 	    }
 
@@ -1084,6 +1092,8 @@
 		 !tin.tin->no_charge)
 		|| tin.tin->unpaid)) {
 		verbalize("You open it, you bought it!");
+		/* charge for one at pre-eating cost */
+		if(tin.tin->quan > 1L) tin.tin = splitobj(tin.tin, 1L);
 		bill_dummy_object(tin.tin);
 	    }
 
@@ -1563,16 +1573,22 @@
 {
 	register struct obj *otmp = victual.piece;
 
+	/* lesshungry wants an occupation to handle choke messages correctly */
+	set_occupation(eatfood, "eating non-food", 0);
 	lesshungry(victual.nmod);
+	occupation = 0;
 	victual.piece = (struct obj *)0;
 	victual.eating = 0;
 	if (otmp->oclass == COIN_CLASS) {
 #ifdef GOLDOBJ
 		if (carried(otmp))
 		    useupall(otmp);
-		else
+#else
+		if (otmp->where == OBJ_FREE)
+		    dealloc_obj(otmp);
 #endif
-		dealloc_obj(otmp);
+		else
+		    useupf(otmp, otmp->quan);
 		return;
 	}
 	if (otmp->oclass == POTION_CLASS) {
@@ -1887,9 +1903,9 @@
 		stackobj(otmp);
 		return 1;
 	}
-	/* KMH -- Slow digestion is... undigestable */
+	/* KMH -- Slow digestion is... indigestible */
 	if (otmp->otyp == RIN_SLOW_DIGESTION) {
-		pline("This ring is undigestable!");
+		pline("This ring is indigestible!");
 		(void) rottenfood(otmp);
 		if (otmp->dknown && !objects[otmp->otyp].oc_name_known
 				&& !objects[otmp->otyp].oc_uname)
@@ -2405,7 +2421,6 @@
 		    Sprintf(qbuf, "There are %ld gold pieces here; eat them?",
 			    gold->quan);
 		if ((c = yn_function(qbuf, ynqchars, 'n')) == 'y') {
-		    obj_extract_self(gold);
 		    return gold;
 		} else if (c == 'q') {
 		    return (struct obj *)0;
diff -Naurd ../nethack-3.4.1/src/end.c ./src/end.c
--- ../nethack-3.4.1/src/end.c Sun Feb 23 14:43:26 2003
+++ ./src/end.c Mon Sep 1 14:33:32 2003
@@ -1,4 +1,4 @@
-/*	SCCS Id: @(#)end.c	3.4	2003/01/08	*/
+/*	SCCS Id: @(#)end.c	3.4	2003/03/10	*/
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
 /* NetHack may be freely redistributed.  See license for details. */
 
@@ -264,7 +264,9 @@
 	    iflags.window_inited = 0; /* they're gone; force raw_print()ing */
 	}
 
-	raw_print(!program_state.something_worth_saving ?
+	raw_print(program_state.gameover ?
+		  "Postgame wrapup disrupted." :
+		  !program_state.something_worth_saving ?
 		  "Program initialization has failed." :
 		  "Suddenly, the dungeon collapses.");
 #if defined(WIZARD) && !defined(MICRO)
@@ -919,8 +921,10 @@
 	char buf[BUFSZ];
 
 	for (box = list; box; box = box->nobj) {
-	    if (Is_container(box) && box->otyp != BAG_OF_TRICKS) {
-		if (box->cobj) {
+	    if (Is_container(box) || box->otyp == STATUE) {
+		if (box->otyp == BAG_OF_TRICKS) {
+		    continue;	/* wrong type of container */
+		} else if (box->cobj) {
 		    winid tmpwin = create_nhwindow(NHW_MENU);
 		    Sprintf(buf, "Contents of %s:", the(xname(box)));
 		    putstr(tmpwin, 0, buf);
diff -Naurd ../nethack-3.4.1/src/files.c ./src/files.c
--- ../nethack-3.4.1/src/files.c Sun Feb 23 14:43:26 2003
+++ ./src/files.c Mon Sep 1 14:33:32 2003
@@ -91,6 +91,7 @@
 
 #ifdef HOLD_LOCKFILE_OPEN
 struct level_ftrack {
+int init;
 int fd;					/* file descriptor for level file     */
 int oflag;				/* open flags                         */
 boolean nethack_thinks_it_is_open;	/* Does NetHack think it's open?       */
@@ -129,6 +130,10 @@
 #endif
 #endif
 
+#ifdef MAC
+# define unlink macunlink
+#endif
+
 #ifdef USER_SOUNDS
 extern char *sounddir;
 #endif
@@ -535,7 +540,11 @@
 int lev, oflag;
 {
 	int reslt, fd;
-	if (lftrack.fd) {
+	if (!lftrack.init) {
+		lftrack.init = 1;
+		lftrack.fd = -1;
+	}
+	if (lftrack.fd >= 0) {
 		/* check for compatible access */
 		if (lftrack.oflag == oflag) {
 			fd = lftrack.fd;
@@ -554,7 +563,7 @@
 			fd = sopen(name, oflag,SH_DENYRW, FCMASK);
 			lftrack.fd = fd;
 			lftrack.oflag = oflag;
-			if (fd)
+			if (fd >= 0)
 			    lftrack.nethack_thinks_it_is_open = TRUE;
 	}
 	return fd;
@@ -565,12 +574,13 @@
 {
 	int fd = lftrack.fd;
 	lftrack.nethack_thinks_it_is_open = FALSE;
-	lftrack.fd = 0;
+	lftrack.fd = -1;
 	lftrack.oflag = 0;
 	(void)_close(fd);
 	return;
 }
 
+int
 close(fd)
 int fd;
 {
@@ -924,6 +934,7 @@
 	return fd;
 }
 
+#if defined(UNIX) && defined(QT_GRAPHICS)
 /*ARGSUSED*/
 static char*
 plname_from_file(filename)
@@ -956,13 +967,13 @@
        (eg. "/", "_", and "." characters are lost. */
     int k;
     int uid;
-    char name[NAME_MAX];
+    char name[64]; /* more than PL_NSIZ */
 #ifdef COMPRESS_EXTENSION
 #define EXTSTR COMPRESS_EXTENSION
 #else
 #define EXTSTR ""
 #endif
-    if ( sscanf( filename, "%*[^/]/%d%[^.]" EXTSTR, &uid, name ) == 2 ) {
+    if ( sscanf( filename, "%*[^/]/%d%63[^.]" EXTSTR, &uid, name ) == 2 ) {
 #undef EXTSTR
     /* "_" most likely means " ", which certainly looks nicer */
 	for (k=0; name[k]; k++)
@@ -976,6 +987,7 @@
     }
 #endif
 }
+#endif /* defined(UNIX) && defined(QT_GRAPHICS) */
 
 char**
 get_saved_games()
@@ -989,8 +1001,8 @@
 	char** result = (char**)alloc((n+1)*sizeof(char*)); /* at most */
 	for (i=0; i<n; i++) {
 	    int uid;
-	    char name[NAME_MAX];
-	    if ( sscanf( namelist[i]->d_name, "%d%s", &uid, name ) == 2 ) {
+	    char name[64]; /* more than PL_NSIZ */
+	    if ( sscanf( namelist[i]->d_name, "%d%63s", &uid, name ) == 2 ) {
 		if ( uid == myuid ) {
 		    char filename[BUFSZ];
 		    char* r;
@@ -1349,15 +1361,21 @@
 #endif  /* UNIX || VMS */
 
 #if defined(AMIGA) || defined(WIN32) || defined(MSDOS)
+# ifdef AMIGA
+#define OPENFAILURE(fd) (!fd)
     lockptr = 0;
-    while (retryct-- && !lockptr) {
+# else
+#define OPENFAILURE(fd) (fd < 0)
+    lockptr = -1;
+# endif
+    while (retryct-- && OPENFAILURE(lockptr)) {
 # ifdef AMIGA
 	(void)DeleteFile(lockname); /* in case dead process was here first */
 	lockptr = Open(lockname,MODE_NEWFILE);
 # else
 	lockptr = open(lockname, O_RDWR|O_CREAT|O_EXCL, S_IWRITE);
 # endif
-	if (!lockptr) {
+	if (OPENFAILURE(lockptr)) {
 	    raw_printf("Waiting for access to %s.  (%d retries left).",
 			filename, retryct);
 	    Delay(50);
@@ -1525,17 +1543,32 @@
 # else	/* should be only UNIX left */
 	envp = nh_getenv("HOME");
 	if (!envp)
-		Strcpy(tmp_config, ".nethackrc");
+		Strcpy(tmp_config, configfile);
 	else
-		Sprintf(tmp_config, "%s/%s", envp, ".nethackrc");
+		Sprintf(tmp_config, "%s/%s", envp, configfile);
 	if ((fp = fopenp(tmp_config, "r")) != (FILE *)0)
 		return(fp);
-	else if (errno != ENOENT) {
-		/* e.g., problems when setuid NetHack can't search home
-		 * directory restricted to user */
-		raw_printf("Couldn't open default config file %s (%d).",
-					tmp_config, errno);
-		wait_synch();
+# if defined(__APPLE__)
+	/* try an alternative */
+	if (envp) {
+		Sprintf(tmp_config, "%s/%s", envp, "Library/Preferences/NetHack Defaults");
+		if ((fp = fopenp(tmp_config, "r")) != (FILE *)0)
+			return(fp);
+	}
+# endif
+	if (errno != ENOENT) {
+	    char *details;
+
+	    /* e.g., problems when setuid NetHack can't search home
+	     * directory restricted to user */
+
+#if defined (NHSTDC) && !defined(NOTSTDC)
+	    if ((details = strerror(errno)) == 0)
+#endif
+		details = "";
+	    raw_printf("Couldn't open default config file %s %s(%d).",
+		       tmp_config, details, errno);
+	    wait_synch();
 	}
 # endif
 #endif
diff -Naurd ../nethack-3.4.1/src/fountain.c ./src/fountain.c
--- ../nethack-3.4.1/src/fountain.c Sun Feb 23 14:43:26 2003
+++ ./src/fountain.c Mon Sep 1 14:33:32 2003
@@ -1,4 +1,4 @@
-/*	SCCS Id: @(#)fountain.c	3.4	2002/09/08	*/
+/*	SCCS Id: @(#)fountain.c	3.4	2003/03/23	*/
 /*	Copyright Scott R. Turner, srt@ucla, 10/27/86 */
 /* NetHack may be freely redistributed.  See license for details. */
 
@@ -386,7 +386,7 @@
 		update_inventory();
 		levl[u.ux][u.uy].typ = ROOM;
 		levl[u.ux][u.uy].looted = 0;
-		if(Invisible) newsym(u.ux, u.uy);
+		newsym(u.ux, u.uy);
 		level.flags.nfountains--;
 		if(in_town(u.ux, u.uy))
 		    (void) angry_guards(FALSE);
@@ -530,8 +530,9 @@
 			else {
 				mtmp = makemon(&mons[PM_SEWER_RAT],
 						u.ux, u.uy, NO_MM_FLAGS);
-				pline("Eek!  There's %s in the sink!",
-					Blind ? "something squirmy" :
+				if (mtmp) pline("Eek!  There's %s in the sink!",
+					(Blind || !canspotmon(mtmp)) ?
+					"something squirmy" :
 					a_monnam(mtmp));
 			}
 			break;
diff -Naurd ../nethack-3.4.1/src/hack.c ./src/hack.c
--- ../nethack-3.4.1/src/hack.c Sun Feb 23 14:43:27 2003
+++ ./src/hack.c Mon Sep 1 14:33:32 2003
@@ -1,4 +1,4 @@
-/*	SCCS Id: @(#)hack.c	3.4	2003/01/08	*/
+/*	SCCS Id: @(#)hack.c	3.4	2003/04/30	*/
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
 /* NetHack may be freely redistributed.  See license for details. */
 
@@ -134,11 +134,13 @@
 		switch(ttmp->ttyp) {
 		case LANDMINE:
 		    if (rn2(10)) {
-			pline("KAABLAMM!!!  %s %s land mine.",
-				Tobjnam(otmp, "trigger"),
-				ttmp->madeby_u ? "your" : "a");
 			obj_extract_self(otmp);
 			place_object(otmp, rx, ry);
+			unblock_point(sx, sy);
+			newsym(sx, sy);
+			pline("KAABLAMM!!!  %s %s land mine.",
+			      Tobjnam(otmp, "trigger"),
+			      ttmp->madeby_u ? "your" : "a");
 			blow_up_landmine(ttmp);
 			/* if the boulder remains, it should fill the pit */
 			fill_pit(u.ux, u.uy);
@@ -738,8 +740,10 @@
 		int x = travelstepx[set][i];
 		int y = travelstepy[set][i];
 		static int ordered[] = { 0, 2, 4, 6, 1, 3, 5, 7 };
+		/* no diagonal movement for grid bugs */
+		int dirmax = u.umonnum == PM_GRID_BUG ? 4 : 8;
 
-		for (dir = 0; dir < 8; dir++) {
+		for (dir = 0; dir < dirmax; ++dir) {
 		    int nx = x+xdir[ordered[dir]];
 		    int ny = y+ydir[ordered[dir]];
 
@@ -766,6 +770,7 @@
 				    nomul(0);
 				    /* reset run so domove run checks work */
 				    flags.run = 8;
+				    iflags.travelcc.x = iflags.travelcc.y = -1;
 				}
 				return TRUE;
 			    }
@@ -1897,7 +1902,10 @@
 	if (IS_ROCK(levl[x][y].typ) || (levl[x][y].typ == ROOM) ||
 	    IS_AIR(levl[x][y].typ))
 	    continue;
-	else if (closed_door(x,y)) {
+	else if (closed_door(x,y) ||
+		 (mtmp && mtmp->m_ap_type == M_AP_FURNITURE &&
+		  (mtmp->mappearance == S_hcdoor ||
+		   mtmp->mappearance == S_vcdoor))) {
 	    if(x != u.ux && y != u.uy) continue;
 	    if(flags.run != 1) goto stop;
 	    goto bcorr;
@@ -2102,7 +2110,7 @@
 {
 	register long carrcap;
 
-	carrcap = (((ACURRSTR + ACURR(A_CON))/2)+1)*50;
+	carrcap = 25*(ACURRSTR + ACURR(A_CON)) + 50;
 	if (Upolyd) {
 		/* consistent with can_carry() in mon.c */
 		if (youmonst.data->mlet == S_NYMPH)
diff -Naurd ../nethack-3.4.1/src/hacklib.c ./src/hacklib.c
--- ../nethack-3.4.1/src/hacklib.c Sun Feb 23 14:43:27 2003
+++ ./src/hacklib.c Mon Sep 1 14:33:32 2003
@@ -466,8 +466,8 @@
 #ifdef RANDOM	/* srandom() from sys/share/random.c */
 	srandom((unsigned int) time((time_t *)0));
 #else
-# if defined(__APPLE__) || defined(BSD) || defined(ULTRIX) || defined(CYGWIN32) /* system srandom() */
-#  ifdef BSD
+# if defined(__APPLE__) || defined(BSD) || defined(LINUX) || defined(ULTRIX) || defined(CYGWIN32) /* system srandom() */
+#  if defined(BSD) && !defined(POSIX_TYPES)
 #   if defined(SUNOS4)
 	(void)
 #   endif
@@ -490,12 +490,12 @@
 {
 	time_t date;
 
-#ifdef BSD
+#if defined(BSD) && !defined(POSIX_TYPES)
 	(void) time((long *)(&date));
 #else
 	(void) time(&date);
 #endif
-#if (defined(ULTRIX) && !(defined(ULTRIX_PROTO) || defined(NHSTDC))) || defined(BSD)
+#if (defined(ULTRIX) && !(defined(ULTRIX_PROTO) || defined(NHSTDC))) || (defined(BSD) && !defined(POSIX_TYPES))
 	return(localtime((long *)(&date)));
 #else
 	return(localtime(&date));
@@ -542,7 +542,7 @@
 	if (date == 0)
 		lt = getlt();
 	else
-#if (defined(ULTRIX) && !(defined(ULTRIX_PROTO) || defined(NHSTDC))) || defined(BSD)
+#if (defined(ULTRIX) && !(defined(ULTRIX_PROTO) || defined(NHSTDC))) || (defined(BSD) && !defined(POSIX_TYPES))
 		lt = localtime((long *)(&date));
 #else
 		lt = localtime(&date);
diff -Naurd ../nethack-3.4.1/src/invent.c ./src/invent.c
--- ../nethack-3.4.1/src/invent.c Sun Feb 23 14:43:27 2003
+++ ./src/invent.c Mon Sep 1 14:33:32 2003
@@ -1,4 +1,4 @@
-/*	SCCS Id: @(#)invent.c	3.4	2003/01/24	*/
+/*	SCCS Id: @(#)invent.c	3.4	2003/05/25	*/
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
 /* NetHack may be freely redistributed.  See license for details. */
 
@@ -464,6 +464,17 @@
 	}
 }
 
+/* use one charge from an item and possibly incur shop debt for it */
+void
+consume_obj_charge(obj, maybe_unpaid)
+struct obj *obj;
+boolean maybe_unpaid;	/* false if caller handles shop billing */
+{
+	if (maybe_unpaid) check_unpaid(obj);
+	obj->spe -= 1;
+	if (obj->known) update_inventory();
+}
+
 #endif /* OVLB */
 #ifdef OVL3
 
@@ -968,7 +979,12 @@
 		}
 		if(ilet == def_oc_syms[COIN_CLASS]) {
 			if (!usegold) {
-			    You("cannot %s gold.", word);
+			    if (!strncmp(word, "rub on ", 7)) {
+				/* the dangers of building sentences... */
+				You("cannot rub gold%s.", word + 3);
+			    } else {
+				You("cannot %s gold.", word);
+			    }
 			    return(struct obj *)0;
 #ifndef GOLDOBJ
 			} else if (!allowgold) {
@@ -1082,32 +1098,35 @@
 const char *word;
 struct obj *otmp;
 {
-	int otyp = otmp->otyp;
-	boolean domsg = FALSE;
-	const char *s1, *s2, *s3;
-	const char *what = (otmp->quan > 1L) ? "one of those" : "that";
-	if ((!strcmp(word, "wear") || !strcmp(word, "take off")) &&
-		(otmp->oclass == RING_CLASS ||
-		(otmp->oclass == FOOD_CLASS && otmp->otyp == MEAT_RING) ||
-		(otmp->oclass == TOOL_CLASS &&
-		 (otyp == BLINDFOLD || otyp == TOWEL || otyp == LENSES)))) {
-			if (!strcmp(word, "wear")) {
-	    			s1 = "P"; s2 = "put"; s3 = " on"; domsg = TRUE;
-			} else {
-				s1 = "R"; s2 = "remove"; s3 = ""; domsg = TRUE;
-			}
-	} else if ((!strcmp(word, "put on") || !strcmp(word, "remove")) &&
-		(otmp->oclass == ARMOR_CLASS)) {
-			if (!strcmp(word, "remove")) {
-	    			s1 = "T"; s2 = "take"; s3 = " off"; domsg = TRUE;
-			} else {
-	    			s1 = "W"; s2 = "wear"; s3 = ""; domsg = TRUE;
-			}
+	const char *s1, *s2, *s3, *what;
+	int ocls = otmp->oclass, otyp = otmp->otyp;
+
+	s1 = s2 = s3 = 0;
+	/* check for attempted use of accessory commands ('P','R') on armor
+	   and for corresponding armor commands ('W','T') on accessories */
+	if (ocls == ARMOR_CLASS) {
+	    if (!strcmp(word, "put on"))
+		s1 = "W", s2 = "wear", s3 = "";
+	    else if (!strcmp(word, "remove"))
+		s1 = "T", s2 = "take", s3 = " off";
+	} else if ((ocls == RING_CLASS || otyp == MEAT_RING) ||
+		ocls == AMULET_CLASS ||
+		(otyp == BLINDFOLD || otyp == TOWEL || otyp == LENSES)) {
+	    if (!strcmp(word, "wear"))
+		s1 = "P", s2 = "put", s3 = " on";
+	    else if (!strcmp(word, "take off"))
+		s1 = "R", s2 = "remove", s3 = "";
+	}
+	if (s1) {
+	    what = "that";
+	    /* quantity for armor and accessory objects is always 1,
+	       but some things should be referred to as plural */
+	    if (otyp == LENSES || is_gloves(otmp) || is_boots(otmp))
+		what = "those";
+	    pline("Use the '%s' command to %s %s%s.", s1, s2, what, s3);
+	} else {
+	    pline(silly_thing_to, word);
 	}
-	if (domsg)
-		pline("Use the '%s' command to %s %s%s.", s1, s2, what, s3);
-	else
-		pline(silly_thing_to, word);
 }
 
 #endif /* OVL1 */
@@ -2143,7 +2162,7 @@
 	const char *dfeature = (char *)0;
 	char fbuf[BUFSZ], fbuf2[BUFSZ];
 	winid tmpwin;
-	boolean skip_objects = (obj_cnt >= 5);
+	boolean skip_objects = (obj_cnt >= 5), felt_cockatrice = FALSE;
 
 	if (u.uswallow && u.ustuck) {
 	    struct monst *mtmp = u.ustuck;
@@ -2227,13 +2246,22 @@
 		putstr(tmpwin, 0, fbuf);
 		putstr(tmpwin, 0, "");
 	    }
-	    putstr(tmpwin, 0, "Things that are here:");
+	    putstr(tmpwin, 0, Blind ? "Things that you feel here:" :
+				      "Things that are here:");
 	    for ( ; otmp; otmp = otmp->nexthere) {
+		if (otmp->otyp == CORPSE && will_feel_cockatrice(otmp, FALSE)) {
+			char buf[BUFSZ];
+			felt_cockatrice = TRUE;
+			Strcpy(buf, doname(otmp));
+			Strcat(buf, "...");
+			putstr(tmpwin, 0, buf);
+			break;
+		}
 		putstr(tmpwin, 0, doname(otmp));
-		if (otmp->otyp == CORPSE) feel_cockatrice(otmp, FALSE);
 	    }
 	    display_nhwindow(tmpwin, TRUE);
 	    destroy_nhwindow(tmpwin);
+	    if (felt_cockatrice) feel_cockatrice(otmp, FALSE);
 	    read_engr_at(u.ux, u.uy); /* Eric Backus */
 	}
 	return(!!Blind);
@@ -2246,6 +2274,17 @@
 	return look_here(0, FALSE);
 }
 
+boolean
+will_feel_cockatrice(otmp, force_touch)
+struct obj *otmp;
+boolean force_touch;
+{
+	if ((Blind || force_touch) && !uarmg && !Stone_resistance &&
+		(otmp->otyp == CORPSE && touch_petrifies(&mons[otmp->corpsenm])))
+			return TRUE;
+	return FALSE;
+}
+
 void
 feel_cockatrice(otmp, force_touch)
 struct obj *otmp;
@@ -2253,8 +2292,7 @@
 {
 	char kbuf[BUFSZ];
 
-	if ((Blind || force_touch) && !uarmg && !Stone_resistance &&
-		(otmp->otyp == CORPSE && touch_petrifies(&mons[otmp->corpsenm]))) {
+	if (will_feel_cockatrice(otmp, force_touch)) {
 	    if(poly_when_stoned(youmonst.data))
 			You("touched the %s corpse with your bare %s.",
 				mons[otmp->corpsenm].mname, makeplural(body_part(HAND)));
@@ -2506,6 +2544,7 @@
 long numused;
 {
 	register struct obj *otmp;
+	boolean at_u = (obj->ox == u.ux && obj->oy == u.uy);
 
 	/* burn_floor_paper() keeps an object pointer that it tries to
 	 * useupf() multiple times, so obj must survive if plural */
@@ -2519,6 +2558,8 @@
 	    else (void)stolen_value(otmp, otmp->ox, otmp->oy, FALSE, FALSE);
 	}
 	delobj(otmp);
+	if (at_u && u.uundetected && hides_under(youmonst.data))
+	    u.uundetected = OBJ_AT(u.ux, u.uy);
 }
 
 #endif /* OVLB */
diff -Naurd ../nethack-3.4.1/src/light.c ./src/light.c
--- ../nethack-3.4.1/src/light.c Sun Feb 23 14:43:27 2003
+++ ./src/light.c Mon Sep 1 14:33:32 2003
@@ -485,14 +485,7 @@
     struct obj *obj;
 {
     return (obj->lamplit &&
-		(  obj->otyp == MAGIC_LAMP
-		|| obj->otyp == BRASS_LANTERN
-		|| obj->otyp == OIL_LAMP
-		|| obj->otyp == CANDELABRUM_OF_INVOCATION
-		|| obj->otyp == TALLOW_CANDLE
-		|| obj->otyp == WAX_CANDLE
-		|| obj->otyp == POT_OIL
-		|| artifact_light(obj)));
+		(obj->otyp == MAGIC_LAMP || ignitable(obj) || artifact_light(obj)));
 }
 
 /* copy the light source(s) attachted to src, and attach it/them to dest */
diff -Naurd ../nethack-3.4.1/src/lock.c ./src/lock.c
--- ../nethack-3.4.1/src/lock.c Sun Feb 23 14:43:27 2003
+++ ./src/lock.c Mon Sep 1 14:33:32 2003
@@ -307,7 +307,9 @@
 		    else if (picktyp != LOCK_PICK) verb = "unlock", it = 1;
 		    else verb = "pick";
 		    Sprintf(qbuf, "There is %s here, %s %s?",
-			    doname(otmp), verb, it ? "it" : "its lock");
+		    	    safe_qbuf("", sizeof("There is  here, unlock its lock?"),
+			    	doname(otmp), an(simple_typename(otmp->otyp)), "a box"),
+			    verb, it ? "it" : "its lock");
 
 		    c = ynq(qbuf);
 		    if(c == 'q') return(0);
@@ -353,6 +355,11 @@
 	} else {			/* pick the lock in a door */
 	    struct monst *mtmp;
 
+	    if (u.utrap && u.utraptype == TT_PIT) {
+		You_cant("reach over the edge of the pit.");
+		return(0);
+	    }
+
 	    door = &levl[cc.x][cc.y];
 	    if ((mtmp = m_at(cc.x, cc.y)) && canseemon(mtmp)
 			&& mtmp->m_ap_type != M_AP_FURNITURE
@@ -464,7 +471,10 @@
 			  doname(otmp), otmp->obroken ? "broken" : "unlocked");
 		    continue;
 		}
-		Sprintf(qbuf,"There is %s here, force its lock?", doname(otmp));
+		Sprintf(qbuf,"There is %s here, force its lock?",
+			safe_qbuf("", sizeof("There is  here, force its lock?"),
+				doname(otmp), an(simple_typename(otmp->otyp)),
+				"a box"));
 
 		c = ynq(qbuf);
 		if(c == 'q') return(0);
diff -Naurd ../nethack-3.4.1/src/makemon.c ./src/makemon.c
--- ../nethack-3.4.1/src/makemon.c Sun Feb 23 14:43:27 2003
+++ ./src/makemon.c Mon Sep 1 14:33:32 2003
@@ -1,4 +1,4 @@
-/*	SCCS Id: @(#)makemon.c	3.4	2002/02/07	*/
+/*	SCCS Id: @(#)makemon.c	3.4	2003/05/25	*/
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
 /* NetHack may be freely redistributed.  See license for details. */
 
@@ -790,9 +790,18 @@
 			return((struct monst *)0);
 	}
 
-	/* if a monster already exists at the position, return */
-	if(MON_AT(x, y))
-		return((struct monst *) 0);
+	/* Does monster already exist at the position? */
+	if(MON_AT(x, y)) {
+		if ((mmflags & MM_ADJACENTOK) != 0) {
+			coord bypos;
+			if(enexto_core(&bypos, x, y, ptr, gpflags)) {
+				x = bypos.x;
+				y = bypos.y;
+			} else
+				return((struct monst *) 0);
+		} else 
+			return((struct monst *) 0);
+	}
 
 	if(ptr){
 		mndx = monsndx(ptr);
@@ -1719,6 +1728,30 @@
 	mtmp->mappearance = appear;
 }
 
+/* release a monster from a bag of tricks */
+void
+bagotricks(bag)
+struct obj *bag;
+{
+    if (!bag || bag->otyp != BAG_OF_TRICKS) {
+	impossible("bad bag o' tricks");
+    } else if (bag->spe < 1) {
+	pline(nothing_happens);
+    } else {
+	boolean gotone = FALSE;
+	int cnt = 1;
+
+	consume_obj_charge(bag, TRUE);
+
+	if (!rn2(23)) cnt += rn1(7, 1);
+	while (cnt-- > 0) {
+	    if (makemon((struct permonst *)0, u.ux, u.uy, NO_MM_FLAGS))
+		gotone = TRUE;
+	}
+	if (gotone) makeknown(BAG_OF_TRICKS);
+    }
+}
+
 #endif /* OVLB */
 
 /*makemon.c*/
diff -Naurd ../nethack-3.4.1/src/mhitm.c ./src/mhitm.c
--- ../nethack-3.4.1/src/mhitm.c Sun Feb 23 14:43:27 2003
+++ ./src/mhitm.c Mon Sep 1 14:33:32 2003
@@ -78,6 +78,8 @@
 	char buf[BUFSZ], mdef_name[BUFSZ];
 
 	if (vis) {
+		if (!canspotmon(magr))
+		    map_invisible(magr->mx, magr->my);
 		if (!canspotmon(mdef))
 		    map_invisible(mdef->mx, mdef->my);
 		if (mdef->m_ap_type) seemimic(mdef);
@@ -221,7 +223,7 @@
 
 
     /* Set up the visibility of action */
-    vis = (cansee(magr->mx,magr->my) && cansee(mdef->mx,mdef->my));
+    vis = (cansee(magr->mx,magr->my) && cansee(mdef->mx,mdef->my) && (canspotmon(magr) || canspotmon(mdef)));
 
     /*	Set flag indicating monster has moved this turn.  Necessary since a
      *	monster might get an attack out of sequence (i.e. before its move) in
@@ -371,6 +373,8 @@
 		int compat;
 		char buf[BUFSZ], mdef_name[BUFSZ];
 
+		if (!canspotmon(magr))
+		    map_invisible(magr->mx, magr->my);
 		if (!canspotmon(mdef))
 		    map_invisible(mdef->mx, mdef->my);
 		if(mdef->m_ap_type) seemimic(mdef);
diff -Naurd ../nethack-3.4.1/src/mhitu.c ./src/mhitu.c
--- ../nethack-3.4.1/src/mhitu.c Sun Feb 23 14:43:27 2003
+++ ./src/mhitu.c Mon Sep 1 14:33:32 2003
@@ -783,6 +783,7 @@
 	    if (obj->greased && !rn2(2)) {
 		pline_The("grease wears off.");
 		obj->greased = 0;
+		update_inventory();
 	    }
 	    return TRUE;
 	}
@@ -1207,7 +1208,7 @@
 			    killer_format = KILLED_BY_AN;
 			    Sprintf(buf, "%s by %s",
 				    moat ? "moat" : "pool of water",
-				    a_monnam(mtmp));
+				    an(mtmp->data->mname));
 			    killer = buf;
 			    done(DROWNING);
 			} else if(mattk->aatyp == AT_HUGS)
@@ -1683,8 +1684,14 @@
 		    }
 		    break;
 		case AD_PHYS:
-		    You("are pummeled with debris!");
-		    exercise(A_STR, FALSE);
+		    if (mtmp->data == &mons[PM_FOG_CLOUD])
+			You("are laden with moisture and can barely %s!",
+				!breathless(youmonst.data) ? "breathe" :
+				"stay conscious");
+		    else {
+			You("are pummeled with debris!");
+			exercise(A_STR, FALSE);
+		    }
 		    break;
 		case AD_ACID:
 		    if (Acid_resistance) {
@@ -2142,7 +2149,8 @@
 	    if (fem) {
 		if (rn2(20) < ACURR(A_CHA)) {
 		    Sprintf(qbuf, "\"That %s looks pretty.  May I have it?\"",
-			xname(ring));
+			safe_qbuf("",sizeof("\"That  looks pretty.  May I have it?\""),
+			xname(ring), simple_typename(ring->otyp), "ring"));
 		    makeknown(RIN_ADORNMENT);
 		    if (yn(qbuf) == 'n') continue;
 		} else pline("%s decides she'd like your %s, and takes it.",
@@ -2163,7 +2171,9 @@
 		if (ring==uleft || ring==uright) continue;
 		if (rn2(20) < ACURR(A_CHA)) {
 		    Sprintf(qbuf,"\"That %s looks pretty.  Would you wear it for me?\"",
-			xname(ring));
+			safe_qbuf("",
+			    sizeof("\"That  looks pretty.  Would you wear it for me?\""),
+			    xname(ring), simple_typename(ring->otyp), "ring"));
 		    makeknown(RIN_ADORNMENT);
 		    if (yn(qbuf) == 'n') continue;
 		} else {
diff -Naurd ../nethack-3.4.1/src/mklev.c ./src/mklev.c
--- ../nethack-3.4.1/src/mklev.c Sun Feb 23 14:43:27 2003
+++ ./src/mklev.c Mon Sep 1 14:33:32 2003
@@ -485,7 +485,7 @@
 			trap_type = ROCKTRAP;
 		    ttmp = maketrap(xx, yy+dy, trap_type);
 		    if (ttmp) {
-			ttmp->once = 1;
+			if (trap_type != ROCKTRAP) ttmp->once = 1;
 			if (trap_engravings[trap_type]) {
 			    make_engr_at(xx, yy-dy,
 				     trap_engravings[trap_type], 0L, DUST);
diff -Naurd ../nethack-3.4.1/src/mkmap.c ./src/mkmap.c
--- ../nethack-3.4.1/src/mkmap.c Sun Feb 23 14:43:27 2003
+++ ./src/mkmap.c Mon Sep 1 14:33:32 2003
@@ -17,6 +17,7 @@
 STATIC_DCL void NDECL(wallify_map);
 STATIC_DCL void FDECL(join_map,(SCHAR_P,SCHAR_P));
 STATIC_DCL void FDECL(finish_map,(SCHAR_P,SCHAR_P,XCHAR_P,XCHAR_P));
+STATIC_DCL void FDECL(remove_room,(unsigned));
 void FDECL(mkmap, (lev_init *));
 
 char *new_locations;
@@ -361,13 +362,92 @@
 		    levl[i][j].lit = TRUE;
 }
 
+/*
+ * When level processed by join_map is overlaid by a MAP, some rooms may no
+ * longer be valid.  All rooms in the region lx <= x < hx, ly <= y < hy are
+ * removed.  Rooms partially in the region are truncated.  This function
+ * must be called before the REGIONs or ROOMs of the map are processed, or
+ * those rooms will be removed as well.  Assumes roomno fields in the
+ * region are already cleared, and roomno and irregular fields outside the
+ * region are all set.
+ */
+void
+remove_rooms(lx, ly, hx, hy)
+    int lx, ly, hx, hy;
+{
+    int i;
+    struct mkroom *croom;
+
+    for (i = nroom - 1; i >= 0; --i) {
+	croom = &rooms[i];
+	if (croom->hx < lx || croom->lx >= hx ||
+	    croom->hy < ly || croom->ly >= hy) continue; /* no overlap */
+
+	if (croom->lx < lx || croom->hx >= hx ||
+	    croom->ly < ly || croom->hy >= hy) { /* partial overlap */
+	    /* TODO: ensure remaining parts of room are still joined */
+
+	    if (!croom->irregular) impossible("regular room in joined map");
+
+	    /* if a "donut" or even disconnected room, leave bounds alone */
+	    if ((croom->lx < lx && croom->hx >= hx) ||
+		(croom->ly < ly && croom->hy >= hy)) {
+		continue;
+	    }
+
+	    /* truncate the side(s) that are covered by the region */
+	    if (croom->lx < lx && croom->hx < hx) croom->hx = lx - 1;
+	    if (croom->lx >= lx && croom->hx >= hx) croom->lx = hx;
+	    if (croom->ly < ly && croom->hy < hy) croom->hy = ly - 1;
+	    if (croom->ly >= ly && croom->hy >= hy) croom->ly = hy;
+	} else {
+	    /* total overlap, remove the room */
+	    remove_room((unsigned)i);
+	}
+    }
+}
+
+/*
+ * Remove roomno from the rooms array, decrementing nroom.  Also updates
+ * all level roomno values of affected higher numbered rooms.  Assumes
+ * level structure contents corresponding to roomno have already been reset.
+ * Currently handles only the removal of rooms that have no subrooms.
+ */
+STATIC_OVL void
+remove_room(roomno)
+    unsigned roomno;
+{
+    struct mkroom *croom = &rooms[roomno];
+    struct mkroom *maxroom = &rooms[--nroom];
+    int i, j;
+    unsigned oroomno;
+
+    if (croom != maxroom) {
+	/* since the order in the array only matters for making corridors,
+	 * copy the last room over the one being removed on the assumption
+	 * that corridors have already been dug. */
+	(void) memcpy((genericptr_t)croom, (genericptr_t)maxroom,
+		      sizeof(struct mkroom));
+
+	/* since maxroom moved, update affected level roomno values */
+	oroomno = nroom + ROOMOFFSET;
+	roomno += ROOMOFFSET;
+	for (i = croom->lx; i <= croom->hx; ++i)
+	    for (j = croom->ly; j <= croom->hy; ++j) {
+		if (levl[i][j].roomno == oroomno)
+		    levl[i][j].roomno = roomno;
+	    }
+    }
+
+    maxroom->hx = -1;			/* just like add_room */
+}
+
 #define N_P1_ITER	1	/* tune map generation via this value */
 #define N_P2_ITER	1	/* tune map generation via this value */
 #define N_P3_ITER	2	/* tune map smoothing via this value */
 
 void
 mkmap(init_lev)
-
 	lev_init	*init_lev;
 {
 	schar	bg_typ = init_lev->bg,
diff -Naurd ../nethack-3.4.1/src/mkobj.c ./src/mkobj.c
--- ../nethack-3.4.1/src/mkobj.c Sun Feb 23 14:43:28 2003
+++ ./src/mkobj.c Mon Sep 1 14:33:32 2003
@@ -416,7 +416,7 @@
 		   this level; let's create an adventurer's corpse instead, then */
 			otmp->corpsenm = PM_HUMAN;
 		}
-		start_corpse_timeout(otmp);
+		/* timer set below */
 		break;
 	    case EGG:
 		otmp->corpsenm = NON_PM;	/* generic egg */
@@ -617,6 +617,14 @@
 						objects[otmp->otyp].oc_class);
 		return (struct obj *)0;
 	}
+
+	/* Some things must get done (timers) even if init = 0 */
+	switch (otmp->otyp) {
+	    case CORPSE:
+		start_corpse_timeout(otmp);
+		break;
+	}
+
 	/* unique objects may have an associated artifact entry */
 	if (objects[otyp].oc_unique && !otmp->oartifact)
 	    otmp = mk_artifact(otmp, (aligntyp)A_NONE);
diff -Naurd ../nethack-3.4.1/src/mkroom.c ./src/mkroom.c
--- ../nethack-3.4.1/src/mkroom.c Sun Feb 23 14:43:28 2003
+++ ./src/mkroom.c Mon Sep 1 14:33:32 2003
@@ -128,8 +128,10 @@
 		}
 #endif
 	}
+#ifndef MAC
 gottype:
 #endif
+#endif
 	for(sroom = &rooms[0]; ; sroom++){
 		if(sroom->hx < 0) return;
 		if(sroom - rooms >= nroom) {
diff -Naurd ../nethack-3.4.1/src/mon.c ./src/mon.c
--- ../nethack-3.4.1/src/mon.c Sun Feb 23 14:43:28 2003
+++ ./src/mon.c Mon Sep 1 14:33:32 2003
@@ -1,4 +1,4 @@
-/*	SCCS Id: @(#)mon.c	3.4	2003/01/29	*/
+/*	SCCS Id: @(#)mon.c	3.4	2003/08/24	*/
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
 /* NetHack may be freely redistributed.  See license for details. */
 
@@ -84,6 +84,47 @@
 	return mndx;
 }
 
+/* Convert the monster index of some monsters (such as quest guardians)
+ * to their generic species type.
+ *
+ * Return associated character class monster, rather than species
+ * if mode is 1.
+ */
+int
+genus(mndx, mode)
+int mndx, mode;
+{
+	switch (mndx) {
+/* Quest guardians */
+	case PM_STUDENT:     mndx = mode ? PM_VALKYRIE  : PM_HUMAN; break;
+	case PM_CHIEFTAIN:   mndx = mode ? PM_BARBARIAN : PM_HUMAN; break;
+	case PM_NEANDERTHAL: mndx = mode ? PM_CAVEMAN   : PM_HUMAN; break;
+	case PM_ATTENDANT:   mndx = mode ? PM_HEALER    : PM_HUMAN; break;
+	case PM_PAGE:        mndx = mode ? PM_KNIGHT    : PM_HUMAN; break;
+	case PM_ABBOT:       mndx = mode ? PM_MONK      : PM_HUMAN; break;
+	case PM_ACOLYTE:     mndx = mode ? PM_PRIEST    : PM_HUMAN; break;
+	case PM_HUNTER:      mndx = mode ? PM_RANGER    : PM_HUMAN; break;
+	case PM_THUG:        mndx = mode ? PM_ROGUE     : PM_HUMAN; break;
+	case PM_ROSHI:       mndx = mode ? PM_SAMURAI   : PM_HUMAN; break;
+#ifdef TOURIST
+	case PM_GUIDE:       mndx = mode ? PM_TOURIST   : PM_HUMAN; break;
+#endif
+	case PM_APPRENTICE:  mndx = mode ? PM_WIZARD    : PM_HUMAN; break;
+	case PM_WARRIOR:     mndx = mode ? PM_VALKYRIE  : PM_HUMAN; break;
+	default:
+		if (mndx >= LOW_PM && mndx < NUMMONS) {
+			struct permonst *ptr = &mons[mndx];
+			if (is_human(ptr))      mndx = PM_HUMAN;
+			else if (is_elf(ptr))   mndx = PM_ELF;
+			else if (is_dwarf(ptr)) mndx = PM_DWARF;
+			else if (is_gnome(ptr)) mndx = PM_GNOME;
+			else if (is_orc(ptr))   mndx = PM_ORC;
+		}
+		break;
+	}
+	return mndx;
+}
+
 /* convert monster index to chameleon index */
 int
 pm_to_cham(mndx)
@@ -640,7 +681,7 @@
 			pline("%s spits %s out in disgust!",
 			      Monnam(mtmp), distant_name(otmp,doname));
 		    }
-		/* KMH -- Don't eat undigestable/choking objects */
+		/* KMH -- Don't eat indigestible/choking objects */
 		} else if (otmp->otyp != AMULET_OF_STRANGULATION &&
 				otmp->otyp != RIN_SLOW_DIGESTION) {
 		    if (cansee(mtmp->mx,mtmp->my) && flags.verbose)
@@ -1586,8 +1627,7 @@
 		/* defer statue creation until after inventory removal
 		   so that saved monster traits won't retain any stale
 		   item-conferred attributes */
-		otmp = mkcorpstat(STATUE, KEEPTRAITS(mdef) ? mdef : 0,
-				  mdef->data, x, y, FALSE);
+		otmp = mkcorpstat(STATUE, mdef, mdef->data, x, y, FALSE);
 		if (mdef->mnamelth) otmp = oname(otmp, NAME(mdef));
 		while ((obj = oldminvent) != 0) {
 		    oldminvent = obj->nobj;
@@ -1958,13 +1998,13 @@
 
 void
 poisoned(string, typ, pname, fatal)
-register const char *string, *pname;
-register int  typ, fatal;
+const char *string, *pname;
+int  typ, fatal;
 {
-	register int i, plural;
-	boolean thrown_weapon = !strncmp(string, "poison", 6);
-		/* admittedly a kludge... */
+	int i, plural, kprefix = KILLED_BY_AN;
+	boolean thrown_weapon = (fatal < 0);
 
+	if (thrown_weapon) fatal = -fatal;
 	if(strcmp(string, "blast") && !thrown_weapon) {
 	    /* 'blast' has already given a 'poison gas' message */
 	    /* so have "poison arrow", "poison dart", etc... */
@@ -1979,6 +2019,15 @@
 		pline_The("poison doesn't seem to affect you.");
 		return;
 	}
+	/* suppress killer prefix if it already has one */
+	if (!strncmpi(pname, "the ", 4) ||
+		!strncmpi(pname, "an ", 3) ||
+		!strncmpi(pname, "a ", 2) ||
+	    /* ... or if it seems to be a proper name */
+		isupper(*pname)) {
+	    /*[ does this need a plural check too? ]*/
+	    kprefix = KILLED_BY;
+	}
 	i = rn2(fatal + 20*thrown_weapon);
 	if(i == 0 && typ != A_CHA) {
 		u.uhp = -1;
@@ -1986,17 +2035,17 @@
 	} else if(i <= 5) {
 		/* Check that a stat change was made */
 		if (adjattrib(typ, thrown_weapon ? -1 : -rn1(3,3), 1))
-  		    pline("You%s!", poiseff[typ]);
+		    pline("You%s!", poiseff[typ]);
 	} else {
 		i = thrown_weapon ? rnd(6) : rn1(10,6);
 		if(Half_physical_damage) i = (i+1) / 2;
-		losehp(i, pname, KILLED_BY_AN);
+		losehp(i, pname, kprefix);
 	}
 	if(u.uhp < 1) {
-		killer_format = KILLED_BY_AN;
+		killer_format = kprefix;
 		killer = pname;
 		/* "Poisoned by a poisoned ___" is redundant */
-		done(thrown_weapon ? DIED : POISONING);
+		done(strstri(pname, "poison") ? DIED : POISONING);
 	}
 	(void) encumber_msg();
 }
diff -Naurd ../nethack-3.4.1/src/mondata.c ./src/mondata.c
--- ../nethack-3.4.1/src/mondata.c Sun Feb 23 14:43:28 2003
+++ ./src/mondata.c Mon Sep 1 14:33:32 2003
@@ -1,4 +1,4 @@
-/*	SCCS Id: @(#)mondata.c	3.4	2003/01/08	*/
+/*	SCCS Id: @(#)mondata.c	3.4	2003/06/02	*/
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
 /* NetHack may be freely redistributed.  See license for details. */
 
@@ -523,20 +523,29 @@
 pronoun_gender(mtmp)
 register struct monst *mtmp;
 {
-	if (!canspotmon(mtmp) || !humanoid(mtmp->data))
-		return 2;
-	return mtmp->female;
+	if (is_neuter(mtmp->data) || !canspotmon(mtmp)) return 2;
+	return (humanoid(mtmp->data) || (mtmp->data->geno & G_UNIQ) ||
+		type_is_pname(mtmp->data)) ? (int)mtmp->female : 2;
 }
 
 #endif /* OVL2 */
 #ifdef OVLB
 
+/* used for nearby monsters when you go to another level */
 boolean
 levl_follower(mtmp)
-register struct monst *mtmp;
+struct monst *mtmp;
 {
-	return((boolean)(mtmp->mtame || (mtmp->data->mflags2 & M2_STALK) || is_fshk(mtmp)
-		|| (mtmp->iswiz && !mon_has_amulet(mtmp))));
+	/* monsters with the Amulet--even pets--won't follow across levels */
+	if (mon_has_amulet(mtmp)) return FALSE;
+
+	/* some monsters will follow even while intending to flee from you */
+	if (mtmp->mtame || mtmp->iswiz || is_fshk(mtmp)) return TRUE;
+
+	/* stalking types follow, but won't when fleeing unless you hold
+	   the Amulet */
+	return (boolean)((mtmp->data->mflags2 & M2_STALK) &&
+				(!mtmp->mflee || u.uhave.amulet));
 }
 
 static const short grownups[][2] = {
diff -Naurd ../nethack-3.4.1/src/monmove.c ./src/monmove.c
--- ../nethack-3.4.1/src/monmove.c Sun Feb 23 14:43:28 2003
+++ ./src/monmove.c Mon Sep 1 14:33:32 2003
@@ -116,6 +116,7 @@
 	    /* can see it now, or sense it and would normally see it */
 	    (canseemon(mtmp) ||
 		(sensemon(mtmp) && couldsee(mtmp->mx,mtmp->my))) &&
+	    mtmp->mcanmove &&
 	    !noattacks(mtmp->data) && !onscary(u.ux, u.uy, mtmp))
 		stop_occupation();
 
diff -Naurd ../nethack-3.4.1/src/mthrowu.c ./src/mthrowu.c
--- ../nethack-3.4.1/src/mthrowu.c Sun Feb 23 14:43:28 2003
+++ ./src/mthrowu.c Mon Sep 1 14:33:32 2003
@@ -1,4 +1,4 @@
-/*	SCCS Id: @(#)mthrowu.c	3.4	2002/11/07	*/
+/*	SCCS Id: @(#)mthrowu.c	3.4	2003/05/09	*/
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
 /* NetHack may be freely redistributed.  See license for details. */
 
@@ -41,30 +41,21 @@
 {
 	const char *onm, *knm;
 	boolean is_acid;
+	int kprefix = KILLED_BY_AN;
 	char onmbuf[BUFSZ], knmbuf[BUFSZ];
 
 	if (!name) {
-	    struct obj otmp;
-	    unsigned save_ocknown;
-
 	    if (!obj) panic("thitu: name & obj both null?");
 	    name = strcpy(onmbuf,
 			 (obj->quan > 1L) ? doname(obj) : mshot_xname(obj));
-	    /* killer name should be more specific; however, exact info
-	       like blessed/cursed and rustproof make things too verbose */
-	    otmp = *obj;
-	    save_ocknown = objects[otmp.otyp].oc_name_known;
-	    otmp.known = otmp.dknown = 1;
-	    otmp.bknown = otmp.rknown = otmp.greased = 0;
-	    /* "killed by poisoned <obj>" would be misleading
-	       since poison is not the cause of death */
-	    otmp.opoisoned = 0;
-	    objects[otmp.otyp].oc_name_known = 1;
-	    knm = strcpy(knmbuf,
-			 (otmp.quan > 1L) ? doname(&otmp) : xname(&otmp));
-	    objects[otmp.otyp].oc_name_known = save_ocknown;
+	    knm = strcpy(knmbuf, killer_xname(obj));
+	    kprefix = KILLED_BY;  /* killer_name supplies "an" if warranted */
 	} else {
 	    knm = name;
+	    /* [perhaps ought to check for plural here to] */
+	    if (!strncmpi(name, "the ", 4) ||
+		    !strncmpi(name, "an ", 3) ||
+		    !strncmpi(name, "a ", 2)) kprefix = KILLED_BY;
 	}
 	onm = (obj && obj_is_pname(obj)) ? the(name) :
 			    (obj && obj->quan > 1L) ? name : an(name);
@@ -89,8 +80,7 @@
 		else {
 			if (is_acid) pline("It burns!");
 			if (Half_physical_damage) dam = (dam+1) / 2;
-			losehp(dam, knm, (obj && obj_is_pname(obj)) ?
-			       KILLED_BY : KILLED_BY_AN);
+			losehp(dam, knm, kprefix);
 			exercise(A_STR, FALSE);
 		}
 		return(1);
@@ -393,21 +383,10 @@
 		    if (hitu && singleobj->opoisoned &&
 			is_poisonable(singleobj)) {
 			char onmbuf[BUFSZ], knmbuf[BUFSZ];
-			struct obj otmp;
-			unsigned save_ocknown;
 
-			/* [see thitu()'s handling of `name'] */
 			Strcpy(onmbuf, xname(singleobj));
-			otmp = *singleobj;
-			save_ocknown = objects[otmp.otyp].oc_name_known;
-			otmp.known = otmp.dknown = 1;
-			otmp.bknown = otmp.rknown = otmp.greased = 0;
-			/* "poisoned by poisoned <obj>" would be redundant */
-			otmp.opoisoned = 0;
-			objects[otmp.otyp].oc_name_known = 1;
-			Strcpy(knmbuf, xname(&otmp));
-			poisoned(onmbuf, A_STR, knmbuf, 10);
-			objects[otmp.otyp].oc_name_known = save_ocknown;
+			Strcpy(knmbuf, killer_xname(singleobj));
+			poisoned(onmbuf, A_STR, knmbuf, -10);
 		    }
 		    if(hitu &&
 		       can_blnd((struct monst*)0, &youmonst,
diff -Naurd ../nethack-3.4.1/src/music.c ./src/music.c
--- ../nethack-3.4.1/src/music.c Sun Feb 23 14:43:28 2003
+++ ./src/music.c Mon Sep 1 14:33:32 2003
@@ -1,4 +1,4 @@
-/*	SCCS Id: @(#)music.c	3.4	2001/12/03	*/
+/*	SCCS Id: @(#)music.c	3.4	2003/05/25	*/
 /*	Copyright (c) 1989 by Jean-Christophe Collet */
 /* NetHack may be freely redistributed.  See license for details. */
 
@@ -384,8 +384,8 @@
 	switch (instr->otyp) {
 	case MAGIC_FLUTE:		/* Make monster fall asleep */
 	    if (do_spec && instr->spe > 0) {
-		check_unpaid(instr);
-		instr->spe--;
+		consume_obj_charge(instr, TRUE);
+
 		You("produce soft music.");
 		put_monsters_to_sleep(u.ulevel * 5);
 		exercise(A_DEX, TRUE);
@@ -400,8 +400,8 @@
 	case FROST_HORN:		/* Idem wand of cold */
 	case FIRE_HORN:			/* Idem wand of fire */
 	    if (do_spec && instr->spe > 0) {
-		check_unpaid(instr);
-		instr->spe--;
+		consume_obj_charge(instr, TRUE);
+
 		if (!getdir((char *)0)) {
 		    pline("%s.", Tobjnam(instr, "vibrate"));
 		    break;
@@ -430,8 +430,8 @@
 	    break;
 	case MAGIC_HARP:		/* Charm monsters */
 	    if (do_spec && instr->spe > 0) {
-		check_unpaid(instr);
-		instr->spe--;
+		consume_obj_charge(instr, TRUE);
+
 		pline("%s very attractive music.", Tobjnam(instr, "produce"));
 		charm_monsters((u.ulevel - 1) / 3 + 1);
 		exercise(A_DEX, TRUE);
@@ -446,8 +446,8 @@
 	    break;
 	case DRUM_OF_EARTHQUAKE:	/* create several pits */
 	    if (do_spec && instr->spe > 0) {
-		check_unpaid(instr);
-		instr->spe--;
+		consume_obj_charge(instr, TRUE);
+
 		You("produce a heavy, thunderous rolling!");
 		pline_The("entire dungeon is shaking around you!");
 		do_earthquake((u.ulevel - 1) / 3 + 1);
@@ -477,9 +477,7 @@
 struct obj *instr;
 {
     char buf[BUFSZ], c = 'y';
-#ifndef	AMIGA
-	char *s;
-#endif
+    char *s;
     int x,y;
     boolean ok;
 
@@ -491,14 +489,22 @@
 	c = yn("Improvise?");
     }
     if (c == 'n') {
-	if (u.uevent.uheard_tune == 2 && yn("Play the passtune?") == 'y')
-		Strcpy(buf, tune);
-	else
-		getlin("What tune are you playing? [what 5 notes]", buf);
-#ifndef	AMIGA
-	/* The AMIGA supports two octaves of notes */
-	for (s=buf; *s; s++) *s = highc(*s);
+	if (u.uevent.uheard_tune == 2 && yn("Play the passtune?") == 'y') {
+	    Strcpy(buf, tune);
+	} else {
+	    getlin("What tune are you playing? [5 notes, A-G]", buf);
+	    (void)mungspaces(buf);
+	    /* convert to uppercase and change any "H" to the expected "B" */
+	    for (s = buf; *s; s++) {
+#ifndef AMIGA
+		*s = highc(*s);
+#else
+		/* The AMIGA supports two octaves of notes */
+		if (*s == 'h') *s = 'b';
 #endif
+		if (*s == 'H') *s = 'B';
+	    }
+	}
 	You("extract a strange sound from %s!", the(xname(instr)));
 #ifdef UNIX386MUSIC
 	/* if user is at the console, play through the console speaker */
diff -Naurd ../nethack-3.4.1/src/objnam.c ./src/objnam.c
--- ../nethack-3.4.1/src/objnam.c Sun Feb 23 14:43:28 2003
+++ ./src/objnam.c Mon Sep 1 14:33:32 2003
@@ -1,4 +1,4 @@
-/*	SCCS Id: @(#)objnam.c	3.4	2003/02/08	*/
+/*	SCCS Id: @(#)objnam.c	3.4	2003/05/09	*/
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
 /* NetHack may be freely redistributed.  See license for details. */
 
@@ -367,7 +367,7 @@
 	    case ROCK_CLASS:
 		if (typ == STATUE)
 		    Sprintf(buf, "%s%s of %s%s",
-			(Role_if(PM_ARCHEOLOGIST) && obj->spe) ? "historic " : "" ,
+			(Role_if(PM_ARCHEOLOGIST) && (obj->spe & STATUE_HISTORIC)) ? "historic " : "" ,
 			actualn,
 			type_is_pname(&mons[obj->corpsenm]) ? "" :
 			  (mons[obj->corpsenm].geno & G_UNIQ) ? "the " :
@@ -854,6 +854,47 @@
 	return xname(obj);
 }
 
+/* treat an object as fully ID'd when it might be used as reason for death */
+char *
+killer_xname(obj)
+struct obj *obj;
+{
+    struct obj save_obj;
+    unsigned save_ocknown;
+    char *buf, *save_ocuname;
+
+    /* remember original settings for core of the object;
+       oname and oattached extensions don't matter here--since they
+       aren't modified they don't need to be saved and restored */
+    save_obj = *obj;
+    /* killer name should be more specific than general xname; however, exact
+       info like blessed/cursed and rustproof makes things be too verbose */
+    obj->known = obj->dknown = 1;
+    obj->bknown = obj->rknown = obj->greased = 0;
+    /* if character is a priest[ess], bknown will get toggled back on */
+    obj->blessed = obj->cursed = 0;
+    /* "killed by poisoned <obj>" would be misleading when poison is
+       not the cause of death and "poisoned by poisoned <obj>" would
+       be redundant when it is, so suppress "poisoned" prefix */
+    obj->opoisoned = 0;
+    /* strip user-supplied name; artifacts keep theirs */
+    if (!obj->oartifact) obj->onamelth = 0;
+    /* temporarily identify the type of object */
+    save_ocknown = objects[obj->otyp].oc_name_known;
+    objects[obj->otyp].oc_name_known = 1;
+    save_ocuname = objects[obj->otyp].oc_uname;
+    objects[obj->otyp].oc_uname = 0;	/* avoid "foo called bar" */
+
+    buf = xname(obj);
+    if (obj->quan == 1L) buf = obj_is_pname(obj) ? the(buf) : an(buf);
+
+    objects[obj->otyp].oc_name_known = save_ocknown;
+    objects[obj->otyp].oc_uname = save_ocuname;
+    *obj = save_obj;	/* restore object's core settings */
+
+    return buf;
+}
+
 /*
  * Used if only one of a collection of objects is named (e.g. in eat.c).
  */
@@ -1049,7 +1090,7 @@
 register const char *verb;
 {
 	char *buf = nextobuf();
-	int len;
+	int len, ltmp;
 	const char *sp, *spot;
 	const char * const *spec;
 
@@ -1064,6 +1105,8 @@
 	 * present tense form so we don't duplicate this code elsewhere.
 	 */
 	if (subj) {
+	    if (!strncmpi(subj, "a ", 2) || !strncmpi(subj, "an ", 3))
+		goto sing;
 	    spot = (const char *)0;
 	    for (sp = subj; (sp = index(sp, ' ')) != 0; ++sp) {
 		if (!strncmp(sp, " of ", 4) ||
@@ -1090,15 +1133,23 @@
 		((spot - subj) >= 2 && !strncmp(spot-1, "ae", 2))) {
 		/* check for special cases to avoid false matches */
 		len = (int)(spot - subj) + 1;
-		for (spec = special_subjs; *spec; spec++)
-		    if (!strncmpi(*spec, subj, len)) goto sing;
+		for (spec = special_subjs; *spec; spec++) {
+		    ltmp = strlen(*spec);
+		    if (len == ltmp && !strncmpi(*spec, subj, len)) goto sing;
+		    /* also check for <prefix><space><special_subj>
+		       to catch things like "the invisible erinys" */
+		    if (len > ltmp && *(spot - ltmp) == ' ' &&
+			    strncmpi(*spec, spot - ltmp + 1, ltmp)) goto sing;
+		}
 
 		return strcpy(buf, verb);
 	    }
 	    /*
+	     * 3rd person plural doesn't end in telltale 's';
 	     * 2nd person singular behaves as if plural.
 	     */
-	    if (!strcmpi(subj, "you")) return strcpy(buf, verb);
+	    if (!strcmpi(subj, "they") || !strcmpi(subj, "you"))
+		return strcpy(buf, verb);
 	}
 
  sing:
@@ -1161,6 +1212,32 @@
 	return s;
 }
 
+/* returns "your simple_typename(obj->otyp)"
+ * or "Foobar's simple_typename(obj->otyp)"
+ * or "the simple_typename(obj-otyp)"
+ */
+char *
+ysimple_name(obj)
+struct obj *obj;
+{
+	char *outbuf = nextobuf();
+	char *s = shk_your(outbuf, obj);	/* assert( s == outbuf ); */
+	int space_left = BUFSZ - strlen(s) - sizeof " ";
+
+	return strncat(strcat(s, " "), simple_typename(obj->otyp), space_left);
+}
+
+/* capitalized variant of ysimple_name() */
+char *
+Ysimple_name2(obj)
+struct obj *obj;
+{
+	char *s = ysimple_name(obj);
+
+	*s = highc(*s);
+	return s;
+}
+
 static const char *wrp[] = {
 	"wand", "ring", "potion", "scroll", "gem", "amulet",
 	"spellbook", "spell book",
@@ -1936,6 +2013,7 @@
 	if (strncmpi(bp, "wizard lock", 11)) /* not the "wizard" monster! */
 	if (strncmpi(bp, "ninja-to", 8)) /* not the "ninja" rank */
 	if (strncmpi(bp, "master key", 10)) /* not the "master" rank */
+	if (strncmpi(bp, "magenta", 7)) /* not the "mage" rank */
 	if (mntmp < LOW_PM && strlen(bp) > 2 &&
 	    (mntmp = name_to_mon(bp)) >= LOW_PM) {
 		int mntmptoo, mntmplen;	/* double check for rank title */
@@ -2479,7 +2557,10 @@
 			    /* beware of random troll or lizard corpse,
 			       or of ordinary one being forced to such */
 			    if (otmp->timed) obj_stop_timers(otmp);
-			    otmp->corpsenm = mntmp;
+			    if (mons[mntmp].msound == MS_GUARDIAN)
+			    	otmp->corpsenm = genus(mntmp,1);
+			    else
+				otmp->corpsenm = mntmp;
 			    start_corpse_timeout(otmp);
 			}
 			break;
@@ -2505,7 +2586,7 @@
 		case STATUE: otmp->corpsenm = mntmp;
 			if (Has_contents(otmp) && verysmall(&mons[mntmp]))
 			    delete_contents(otmp);	/* no spellbook */
-			otmp->spe = ishistoric;
+			otmp->spe = ishistoric ? STATUE_HISTORIC : 0;
 			break;
 		case SCALE_MAIL:
 			/* Dragon mail - depends on the order of objects */
diff -Naurd ../nethack-3.4.1/src/options.c ./src/options.c
--- ../nethack-3.4.1/src/options.c Sun Feb 23 14:43:28 2003
+++ ./src/options.c Mon Sep 1 14:33:32 2003
@@ -1,4 +1,4 @@
-/*	SCCS Id: @(#)options.c	3.4	2003/01/08	*/
+/*	SCCS Id: @(#)options.c	3.4	2003/05/19	*/
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
 /* NetHack may be freely redistributed.  See license for details. */
 
@@ -98,6 +98,7 @@
 #else
 	{"flush", (boolean *)0, FALSE, SET_IN_FILE},
 #endif
+	{"fullscreen", &iflags.wc2_fullscreen, FALSE, SET_IN_FILE},
 	{"help", &flags.help, TRUE, SET_IN_GAME},
 	{"hilite_pet",    &iflags.wc_hilite_pet, FALSE, SET_IN_GAME},	/*WC*/
 #ifdef ASCIIGRAPH
@@ -137,7 +138,6 @@
 	{"news", (boolean *)0, FALSE, SET_IN_FILE},
 #endif
 	{"null", &flags.null, TRUE, SET_IN_GAME},
-	{"number_pad", &iflags.num_pad, FALSE, SET_IN_GAME},
 #ifdef MAC
 	{"page_wait", &flags.page_wait, TRUE, SET_IN_GAME},
 #else
@@ -172,6 +172,7 @@
 	{"showscore", (boolean *)0, FALSE, SET_IN_FILE},
 #endif
 	{"silent", &flags.silent, TRUE, SET_IN_GAME},
+	{"softkeyboard", &iflags.wc2_softkeyboard, FALSE, SET_IN_FILE},
 	{"sortpack", &flags.sortpack, TRUE, SET_IN_GAME},
 	{"sound", &flags.soundok, TRUE, SET_IN_GAME},
 	{"sparkle", &flags.sparkle, TRUE, SET_IN_GAME},
@@ -208,6 +214,7 @@
 						8, DISP_IN_GAME },
 	{ "align_message", "message window alignment", 20, DISP_IN_GAME }, 	/*WC*/
 	{ "align_status", "status window alignment", 20, DISP_IN_GAME }, 	/*WC*/
+	{ "altkeyhandler", "alternate key handler", 20, DISP_IN_GAME },
 	{ "boulder",  "the symbol to use for displaying boulders",
 						1, SET_IN_GAME },
 	{ "catname",  "the name of your (first) cat (e.g., catname:Tabby)",
@@ -226,10 +233,10 @@
 	{ "font_message", "the font to use in the message window",
 						40, DISP_IN_GAME },		/*WC*/
 	{ "font_size_map", "the size of the map font", 20, DISP_IN_GAME },	/*WC*/
-	{ "font_size_menu", "the size of the map font", 20, DISP_IN_GAME },	/*WC*/
-	{ "font_size_message", "the size of the map font", 20, DISP_IN_GAME },	/*WC*/
-	{ "font_size_status", "the size of the map font", 20, DISP_IN_GAME },	/*WC*/
-	{ "font_size_text", "the size of the map font", 20, DISP_IN_GAME },	/*WC*/
+	{ "font_size_menu", "the size of the menu font", 20, DISP_IN_GAME },	/*WC*/
+	{ "font_size_message", "the size of the message font", 20, DISP_IN_GAME },	/*WC*/
+	{ "font_size_status", "the size of the status font", 20, DISP_IN_GAME },	/*WC*/
+	{ "font_size_text", "the size of the text font", 20, DISP_IN_GAME },	/*WC*/
 	{ "font_status", "the font to use in status window", 40, DISP_IN_GAME }, /*WC*/
 	{ "font_text", "the font to use in text windows", 40, DISP_IN_GAME },	/*WC*/
 	{ "fruit",    "the name of a fruit you enjoy eating",
@@ -267,6 +274,7 @@
 # endif
 	{ "name",     "your character's name (e.g., name:Merlin-W)",
 						PL_NSIZ, DISP_IN_GAME },
+	{ "number_pad", "use the number pad", 1, SET_IN_GAME},
 	{ "objects",  "the symbols to use for objects",
 						MAXOCLASSES, SET_IN_FILE },
 	{ "packorder", "the inventory order of the items in your pack",
@@ -290,11 +298,11 @@
 						PL_CSIZ, DISP_IN_GAME },
 	{ "role",     "your starting role (e.g., Barbarian, Valkyrie)",
 						PL_CSIZ, DISP_IN_GAME },
-	{ "runmode", "display updating frequency when `running' or `travelling'",
+	{ "runmode", "display frequency when `running' or `travelling'",
 						sizeof "teleport", SET_IN_GAME },
 	{ "scores",   "the parts of the score list you wish to see",
 						32, SET_IN_GAME },
-	{ "scroll_amount", "scroll the map this amount when scroll_margin is reached",
+	{ "scroll_amount", "amount to scroll map when scroll_margin is reached",
 						20, DISP_IN_GAME }, /*WC*/
 	{ "scroll_margin", "scroll map when this far from the edge", 20, DISP_IN_GAME }, /*WC*/
 #ifdef MSDOS
@@ -424,6 +435,8 @@
 STATIC_OVL int FDECL(wc_set_window_colors, (char *));
 STATIC_OVL boolean FDECL(is_wc_option, (const char *));
 STATIC_OVL boolean FDECL(wc_supported, (const char *));
+STATIC_OVL boolean FDECL(is_wc2_option, (const char *));
+STATIC_OVL boolean FDECL(wc2_supported, (const char *));
 
 /* check whether a user-supplied option string is a proper leading
    substring of a particular option name; option string might have
@@ -470,7 +483,9 @@
 void
 initoptions()
 {
+#ifndef MAC
 	char *opts;
+#endif
 	int i;
 
 	/* initialize the random number generator */
@@ -507,6 +522,7 @@
 	for (i = 0; i < WARNCOUNT; i++)
 		warnsyms[i] = def_warnsyms[i].sym;
 	iflags.bouldersym = 0;
+	iflags.travelcc.x = iflags.travelcc.y = -1;
 	flags.warnlevel = 1;
 	flags.warntype = 0L;
 
@@ -981,6 +997,7 @@
 	if (match_optname(opts, "colour", 5, FALSE))
 		Strcpy(opts, "color");	/* fortunately this isn't longer */
 
+	if (!match_optname(opts, "subkeyvalue", 11, TRUE)) /* allow multiple */
 	duplicate_opt_detection(opts, 1);	/* 1 means compound opts */
 
 	/* special boolean options */
@@ -1062,6 +1079,35 @@
 		return;
 	}
 
+	fullname = "number_pad";
+	if (match_optname(opts, fullname, 10, TRUE)) {
+		boolean compat = (strlen(opts) <= 10);
+		number_pad(iflags.num_pad ? 1 : 0);
+		op = string_for_opt(opts, (compat || !initial));
+		if (!op) {
+		    if (compat || negated || initial) {
+			/* for backwards compatibility, "number_pad" without a
+			   value is a synonym for number_pad:1 */
+			iflags.num_pad = !negated;
+			if (iflags.num_pad) iflags.num_pad_mode = 0;
+		    }
+		    return;
+		}
+		if (negated) {
+		    bad_negation("number_pad", TRUE);
+		    return;
+		}
+		if (*op == '1' || *op == '2') {
+			iflags.num_pad = 1;
+			if (*op == '2') iflags.num_pad_mode = 1;
+			else iflags.num_pad_mode = 0;
+		} else if (*op == '0') {
+			iflags.num_pad = 0;
+			iflags.num_pad_mode = 0;
+		} else badoption(opts);
+		return;
+	}
+
 	fullname = "runmode";
 	if (match_optname(opts, fullname, 4, TRUE)) {
 		if (negated) {
@@ -1663,29 +1722,28 @@
 		 * string as a prefix to get the desired behaviour.
 		 *
 		 * For backward compatibility, no prefix is required,
-		 * and the presence of a i,a,g,v, or c without a
-		 * prefix sets the corresponding value to DISCLOSE_YES_WITHOUT_PROMPT;
+		 * and the presence of a i,a,g,v, or c without a prefix
+		 * sets the corresponding value to DISCLOSE_YES_WITHOUT_PROMPT.
 		 */
 		boolean badopt = FALSE;
 		int idx, prefix_val;
-		if (!(op = string_for_opt(opts, TRUE))) {
-			/* for backwards compatibility, "disclose" without a
-			 * value means all (was inventory and attributes,
-			 * the only things available then), but negated
-			 * it means "none"
-			 * (note "none" contains none of "iavkgc")
-			 */
-			for (num = 0; num < NUM_DISCLOSURE_OPTIONS; num++) {
-				if (negated)
-				    flags.end_disclose[num] = DISCLOSE_NO_WITHOUT_PROMPT;
-			 	else flags.end_disclose[num] = DISCLOSE_PROMPT_DEFAULT_YES;
-			}
+
+		op = string_for_opt(opts, TRUE);
+		if (op && negated) {
+			bad_negation("disclose", TRUE);
 			return;
 		}
-		if (negated) {
-			bad_negation("disclose", TRUE);
+		/* "disclose" without a value means "all with prompting"
+		   and negated means "none without prompting" */
+		if (!op || !strcmpi(op, "all") || !strcmpi(op, "none")) {
+			if (op && !strcmpi(op, "none")) negated = TRUE;
+			for (num = 0; num < NUM_DISCLOSURE_OPTIONS; num++)
+			    flags.end_disclose[num] = negated ?
+						DISCLOSE_NO_WITHOUT_PROMPT :
+						DISCLOSE_PROMPT_DEFAULT_YES;
 			return;
 		}
+
 		num = 0;
 		prefix_val = -1;
 		while (*op && num < sizeof flags.end_disclose - 1) {
@@ -1930,7 +1999,6 @@
 		} else if (negated) bad_negation(fullname, TRUE);
 		return;
 	}
-
 	fullname = "windowtype";
 	if (match_optname(opts, fullname, 3, TRUE)) {
 	    if (negated) {
@@ -2104,9 +2172,6 @@
 			    else lan_mail_finish();
 			}
 #endif
-			else if ((boolopt[i].addr) == &iflags.num_pad)
-			    number_pad(iflags.num_pad ? 1 : 0);
-
 			else if ((boolopt[i].addr) == &flags.lit_corridor) {
 			    /*
 			     * All corridor squares seen via night vision or
@@ -2296,6 +2361,8 @@
 #endif
 		    if (is_wc_option(boolopt[i].name) &&
 			!wc_supported(boolopt[i].name)) continue;
+		    if (is_wc2_option(boolopt[i].name) &&
+			!wc2_supported(boolopt[i].name)) continue;
 		    any.a_int = (pass == 0) ? 0 : i + 1;
 		    if (!iflags.menu_tab_sep)
 			Sprintf(buf, "%s%-13s [%s]",
@@ -2347,6 +2414,9 @@
 		    	else if (is_wc_option(compopt[i].name) &&
 					!wc_supported(compopt[i].name))
 		    		continue;
+		    	else if (is_wc2_option(compopt[i].name) &&
+					!wc2_supported(compopt[i].name))
+		    		continue;
 		    	else
 				doset_add_menu(tmpwin, compopt[i].name,
 					(pass == DISP_IN_GAME) ? 0 : indexoffset);
@@ -2374,7 +2444,8 @@
 		    Sprintf(buf, "%s%s", *boolopt[opt_indx].addr ? "!" : "",
 			    boolopt[opt_indx].name);
 		    parseoptions(buf, setinitial, fromfile);
-		    if (wc_supported(boolopt[opt_indx].name))
+		    if (wc_supported(boolopt[opt_indx].name) ||
+		    	wc2_supported(boolopt[opt_indx].name))
 			preference_update(boolopt[opt_indx].name);
 		} else {
 		    /* compound option */
@@ -2390,7 +2461,8 @@
 			/* pass the buck */
 			parseoptions(buf, setinitial, fromfile);
 		    }
-		    if (wc_supported(compopt[opt_indx].name))
+		    if (wc_supported(compopt[opt_indx].name) ||
+			wc2_supported(compopt[opt_indx].name))
 			preference_update(compopt[opt_indx].name);
 		}
 	    }
@@ -2415,8 +2487,8 @@
     char buf[BUFSZ];
     boolean retval = FALSE;
     
-    /* Special handling of menustyle, pickup_burden, and pickup_types,
-       disclose, runmode, and msg_window options. */
+    /* Special handling of menustyle, pickup_burden, pickup_types,
+       disclose, runmode, msg_window, and number_pad options. */
     if (!strcmp("menustyle", optname)) {
 	const char *style_name;
 	menu_item *style_pick = (menu_item *)0;
@@ -2600,6 +2672,40 @@
 	destroy_nhwindow(tmpwin);
         retval = TRUE;
     }
+    else if (!strcmp("number_pad", optname)) {
+	static const char *npchoices[3] =
+		{"0 (off)", "1 (on)", "2 (on, DOS compatible)"};
+	char *npletters = "abc";
+	menu_item *mode_pick = (menu_item *)0;
+        tmpwin = create_nhwindow(NHW_MENU);
+	start_menu(tmpwin);
+	for (i = 0; i < SIZE(npchoices); i++) {
+		any.a_int = i + 1;
+		add_menu(tmpwin, NO_GLYPH, &any, npletters[i], 0,
+			 ATR_NONE, npchoices[i], MENU_UNSELECTED);
+        }
+	end_menu(tmpwin, "Select number_pad mode:");
+	if (select_menu(tmpwin, PICK_ONE, &mode_pick) > 0) {
+		int mode = mode_pick->item.a_int - 1;
+		switch(mode) {
+			case 2:
+				iflags.num_pad = 1;
+				iflags.num_pad_mode = 1;
+				break;
+			case 1:
+				iflags.num_pad = 1;
+				iflags.num_pad_mode = 0;
+				break;
+			case 0:
+			default:
+				iflags.num_pad = 0;
+				iflags.num_pad_mode = 0;
+		}
+		free((genericptr_t)mode_pick);
+        }
+	destroy_nhwindow(tmpwin);
+        retval = TRUE;
+    }
     return retval;
 }
 
@@ -2744,6 +2855,10 @@
 #endif
 	else if (!strcmp(optname, "name"))
 		Sprintf(buf, "%s", plname);
+	else if (!strcmp(optname, "number_pad"))
+		Sprintf(buf, "%s",
+			(!iflags.num_pad) ? "0=off" :
+			(iflags.num_pad_mode) ? "2=on, DOS compatible" : "1=on");
 	else if (!strcmp(optname, "objects"))
 		Sprintf(buf, "%s", to_be_done);
 	else if (!strcmp(optname, "packorder")) {
@@ -3197,6 +3312,13 @@
 	{(char *)0, 0L}
 };
 
+struct wc_Opt wc2_options[] = {
+	{"fullscreen", WC2_FULLSCREEN},
+	{"softkeyboard", WC2_SOFTKEYBOARD},
+	{"wraptext", WC2_WRAPTEXT},
+	{(char *)0, 0L}
+};
+
 
 /*
  * If a port wants to change or ensure that the
@@ -3245,7 +3367,7 @@
 {
 	int k = 0;
 	if (status < SET_IN_FILE || status > SET_IN_GAME) {
-		impossible("set_option_mod_status: status out of range %d.",
+		impossible("set_wc_option_mod_status: status out of range %d.",
 			   status);
 		return;
 	}
@@ -3284,6 +3406,63 @@
 	return FALSE;
 }
 
+
+/*
+ * You can set several wc2_options in one call to
+ * set_wc2_option_mod_status() by setting
+ * the appropriate bits for each option that you
+ * are setting in the optmask argument
+ * prior to calling.
+ *    example: set_wc2_option_mod_status(WC2_FULLSCREEN|WC2_SOFTKEYBOARD|WC2_WRAPTEXT, SET_IN_FILE);
+ */
+
+void
+set_wc2_option_mod_status(optmask, status)
+unsigned long optmask;
+int status;
+{
+	int k = 0;
+	if (status < SET_IN_FILE || status > SET_IN_GAME) {
+		impossible("set_wc2_option_mod_status: status out of range %d.",
+			   status);
+		return;
+	}
+	while (wc2_options[k].wc_name) {
+		if (optmask & wc2_options[k].wc_bit) {
+			set_option_mod_status(wc2_options[k].wc_name, status);
+		}
+		k++;
+	}
+}
+
+STATIC_OVL boolean
+is_wc2_option(optnam)
+const char *optnam;
+{
+	int k = 0;
+	while (wc2_options[k].wc_name) {
+		if (strcmp(wc2_options[k].wc_name, optnam) == 0)
+			return TRUE;
+		k++;
+	}
+	return FALSE;
+}
+
+STATIC_OVL boolean
+wc2_supported(optnam)
+const char *optnam;
+{
+	int k = 0;
+	while (wc2_options[k].wc_name) {
+		if (!strcmp(wc2_options[k].wc_name, optnam) &&
+		    (windowprocs.wincap2 & wc2_options[k].wc_bit))
+			return TRUE;
+		k++;
+	}
+	return FALSE;
+}
+
+
 STATIC_OVL void
 wc_set_font_name(wtype, fontname)
 int wtype;
diff -Naurd ../nethack-3.4.1/src/pager.c ./src/pager.c
--- ../nethack-3.4.1/src/pager.c Sun Feb 23 14:43:29 2003
+++ ./src/pager.c Mon Sep 1 14:33:32 2003
@@ -1,4 +1,4 @@
-/*	SCCS Id: @(#)pager.c	3.4	2002/12/18	*/
+/*	SCCS Id: @(#)pager.c	3.4	2003/08/13	*/
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
 /* NetHack may be freely redistributed.  See license for details. */
 
@@ -153,10 +153,9 @@
 
 		/* newsym lets you know of the trap, so mention it here */
 		if (tt == BEAR_TRAP || tt == PIT ||
-		    tt == SPIKED_PIT ||tt == WEB) {
-		    Strcat(buf, ", trapped in ");
-		    Strcat(buf, defsyms[trap_to_defsym(tt)].explanation);
-		}
+			tt == SPIKED_PIT || tt == WEB)
+		    Sprintf(eos(buf), ", trapped in %s",
+			    an(defsyms[trap_to_defsym(tt)].explanation));
 	    }
 
 	    {
@@ -350,12 +349,13 @@
     if (*dbase_str) {
 	/* adjust the input to remove "named " and convert to lower case */
 	char *alt = 0;	/* alternate description */
+
 	if ((ep = strstri(dbase_str, " named ")) != 0)
 	    alt = ep + 7;
 	else
 	    ep = strstri(dbase_str, " called ");
-	if (ep) *ep = '\0';
-	else if ((ep = strstri(dbase_str, ", ")) != 0) *ep = '\0';
+	if (!ep) ep = strstri(dbase_str, ", ");
+	if (ep && ep > dbase_str) *ep = '\0';
 
 	/*
 	 * If the object is named, then the name is the alternate description;
@@ -674,7 +674,7 @@
 		}
 		/* Kludge: warning trumps boulders on the display.
 		   Reveal the boulder too or player can get confused */
-		if (sobj_at(BOULDER, cc.x, cc.y))
+		if (from_screen && sobj_at(BOULDER, cc.x, cc.y))
 			Strcat(out_str, " co-located with a boulder");
 		break;	/* out of for loop*/
 	    }
diff -Naurd ../nethack-3.4.1/src/pickup.c ./src/pickup.c
--- ../nethack-3.4.1/src/pickup.c Sun Feb 23 14:43:29 2003
+++ ./src/pickup.c Mon Sep 1 14:33:32 2003
@@ -1,4 +1,4 @@
-/*	SCCS Id: @(#)pickup.c	3.4	2003/01/08	*/
+/*	SCCS Id: @(#)pickup.c	3.4	2003/07/27	*/
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
 /* NetHack may be freely redistributed.  See license for details. */
 
@@ -31,6 +31,8 @@
 STATIC_PTR int FDECL(in_container,(struct obj *));
 STATIC_PTR int FDECL(ck_bag,(struct obj *));
 STATIC_PTR int FDECL(out_container,(struct obj *));
+STATIC_DCL long FDECL(mbag_item_gone, (int,struct obj *));
+STATIC_DCL void FDECL(observe_quantum_cat, (struct obj *));
 STATIC_DCL int FDECL(menu_loot, (int, struct obj *, BOOLEAN_P));
 STATIC_DCL int FDECL(in_or_out_menu, (const char *,struct obj *, BOOLEAN_P, BOOLEAN_P));
 STATIC_DCL int FDECL(container_at, (int, int, BOOLEAN_P));
@@ -463,8 +465,8 @@
 		    pick_list[i].count = count;
 	    } else {
 		n = query_objlist("Pick up what?", objchain,
-			    traverse_how|AUTOSELECT_SINGLE|INVORDER_SORT,
-			    &pick_list, PICK_ANY, all_but_uchain);
+			traverse_how|AUTOSELECT_SINGLE|INVORDER_SORT|FEEL_COCKATRICE,
+			&pick_list, PICK_ANY, all_but_uchain);
 	    }
 menu_pickup:
 	    n_tried = n;
@@ -536,7 +538,9 @@
 
 		if (!all_of_a_type) {
 		    char qbuf[BUFSZ];
-		    Sprintf(qbuf, "Pick up %s?", doname(obj));
+		    Sprintf(qbuf, "Pick up %s?",
+			safe_qbuf("", sizeof("Pick up ?"), doname(obj),
+					an(simple_typename(obj->otyp)), "something"));
 		    switch ((obj->quan < 2L) ? ynaq(qbuf) : ynNaq(qbuf)) {
 		    case 'q': goto end_query;	/* out 2 levels */
 		    case 'n': continue;
@@ -679,7 +683,13 @@
 	pack = flags.inv_order;
 	do {
 	    printed_type_name = FALSE;
-	    for (curr = olist; curr; curr = FOLLOW(curr, qflags))
+	    for (curr = olist; curr; curr = FOLLOW(curr, qflags)) {
+		if ((qflags & FEEL_COCKATRICE) && curr->otyp == CORPSE &&
+		     will_feel_cockatrice(curr, FALSE)) {
+			destroy_nhwindow(win);	/* stop the menu and revert */
+			(void) look_here(0, FALSE);
+			return 0;
+		}
 		if ((!(qflags & INVORDER_SORT) || curr->oclass == *pack)
 							&& (*allow)(curr)) {
 
@@ -697,6 +707,7 @@
 			    def_oc_syms[(int)objects[curr->otyp].oc_class],
 			    ATR_NONE, doname(curr), MENU_UNSELECTED);
 		}
+	    }
 	    pack++;
 	} while (qflags & INVORDER_SORT && *pack);
 
@@ -1122,10 +1133,13 @@
 		long savequan = obj->quan;
 
 		obj->quan = *cnt_p;
-		Sprintf(qbuf, "%s %s.  Continue?",
+		Strcpy(qbuf,
 			(next_encumbr > HVY_ENCUMBER) ? overloadmsg :
 			(next_encumbr > MOD_ENCUMBER) ? nearloadmsg :
-			moderateloadmsg, doname(obj));
+			moderateloadmsg);
+		Sprintf(eos(qbuf), " %s. Continue?",
+			safe_qbuf(qbuf, sizeof(" . Continue?"),
+				doname(obj), an(simple_typename(obj->otyp)), "something"));
 		obj->quan = savequan;
 		switch (ynq(qbuf)) {
 		case 'q':  result = -1; break;
@@ -1142,6 +1156,32 @@
     return result;
 }
 
+/* To prevent qbuf overflow in prompts use planA only
+ * if it fits, or planB if PlanA doesn't fit,
+ * finally using the fallback as a last resort.
+ * last_restort is expected to be very short.
+ */
+const char *
+safe_qbuf(qbuf, padlength, planA, planB, last_resort)
+const char *qbuf, *planA, *planB, *last_resort;
+unsigned padlength;
+{
+	/* convert size_t (or int for ancient systems) to ordinary unsigned */
+	unsigned len_qbuf = (unsigned)strlen(qbuf),
+	         len_planA = (unsigned)strlen(planA),
+	         len_planB = (unsigned)strlen(planB),
+	         len_lastR = (unsigned)strlen(last_resort);
+	unsigned textleft = QBUFSZ - (len_qbuf + padlength);
+
+	if (len_lastR >= textleft) {
+	    impossible("safe_qbuf: last_resort too large at %u characters.",
+		       len_lastR);
+	    return "";
+	}
+	return (len_planA < textleft) ? planA :
+		    (len_planB < textleft) ? planB : last_resort;
+}
+
 /*
  * Pick up <count> of obj from the ground and add it to the hero's inventory.
  * Returns -1 if caller should break out of its loop, 0 if nothing picked
@@ -1275,8 +1315,8 @@
 }
 
 /*
- * Do the actual work of picking otmp from the floor and putting
- * it in the hero's inventory.  Take care of billing.  Return a
+ * Do the actual work of picking otmp from the floor or monster's interior
+ * and putting it in the hero's inventory.  Take care of billing.  Return a
  * pointer to the object where otmp ends up.  This may be different
  * from otmp because of merging.
  *
@@ -1287,7 +1327,7 @@
 struct obj *otmp;
 {
 	obj_extract_self(otmp);
-	if (otmp != uball && costly_spot(otmp->ox, otmp->oy)) {
+	if (!u.uswallow && otmp != uball && costly_spot(otmp->ox, otmp->oy)) {
 	    char saveushops[5], fakeshop[2];
 
 	    /* addtobill cares about your location rather than the object's;
@@ -1306,7 +1346,7 @@
 	}
 	if (otmp->no_charge)	/* only applies to objects outside invent */
 	    otmp->no_charge = 0;
-	if (Invisible) newsym(otmp->ox, otmp->oy);
+	newsym(otmp->ox, otmp->oy);
 	return addinv(otmp);	/* might merge it with other objects */
 }
 
@@ -1392,6 +1432,10 @@
 	} else if (nolimbs(youmonst.data)) {
 		pline("Without limbs, you cannot loot anything.");
 		return FALSE;
+	} else if (!freehand()) {
+		pline("Without a free %s, you cannot loot anything.",
+			body_part(HAND));
+		return FALSE;
 	}
 	return TRUE;
 }
@@ -1445,7 +1489,10 @@
 	    nobj = cobj->nexthere;
 
 	    if (Is_container(cobj)) {
-		Sprintf(qbuf, "There is %s here, loot it?", doname(cobj));
+		Sprintf(qbuf, "There is %s here, loot it?",
+			safe_qbuf("", sizeof("There is  here, loot it?"),
+			     doname(cobj), an(simple_typename(cobj->otyp)),
+			     "a container"));
 		c = ynq(qbuf);
 		if (c == 'q') return (timepassed);
 		if (c == 'n') continue;
@@ -1772,8 +1819,7 @@
 		sellobj_state(SELL_NORMAL);
 	    }
 	}
-	if (Icebox && obj->otyp != OIL_LAMP && obj->otyp != BRASS_LANTERN
-			&& !Is_candle(obj)) {
+	if (Icebox && !age_is_relative(obj)) {
 		obj->age = monstermoves - obj->age; /* actual age */
 		/* stop any corpse timeouts when frozen */
 		if (obj->otyp == CORPSE && obj->timed) {
@@ -1783,7 +1829,10 @@
 			if (rot_alarm) obj->norevive = 1;
 		}
 	} else if (Is_mbag(current_container) && mbag_explodes(obj, 0)) {
-		You("are blasted by a magical explosion!");
+		/* explicitly mention what item is triggering the explosion */
+		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);
@@ -1803,6 +1852,9 @@
 	    Strcpy(buf, the(xname(current_container)));
 	    You("put %s into %s.", doname(obj), buf);
 
+	    /* gold in container always needs to be added to credit */
+	    if (floor_container && obj->oclass == COIN_CLASS)
+		sellobj(obj, current_container->ox, current_container->oy);
 	    (void) add_to_container(current_container, obj);
 	    current_container->owt = weight(current_container);
 	}
@@ -1868,8 +1920,7 @@
 	obj_extract_self(obj);
 	current_container->owt = weight(current_container);
 
-	if (Icebox && obj->otyp != OIL_LAMP && obj->otyp != BRASS_LANTERN
-			&& !Is_candle(obj)) {
+	if (Icebox && !age_is_relative(obj)) {
 		obj->age = monstermoves - obj->age; /* actual age */
 		if (obj->otyp == CORPSE)
 			start_corpse_timeout(obj);
@@ -1902,6 +1953,70 @@
 	return 1;
 }
 
+/* an object inside a cursed bag of holding is being destroyed */
+STATIC_OVL long
+mbag_item_gone(held, item)
+int held;
+struct obj *item;
+{
+    struct monst *shkp;
+    long loss = 0L;
+
+    if (item->dknown)
+	pline("%s %s vanished!", Doname2(item), otense(item, "have"));
+    else
+	You("%s %s disappear!", Blind ? "notice" : "see", doname(item));
+
+    if (*u.ushops && (shkp = shop_keeper(*u.ushops)) != 0) {
+	if (held ? (boolean) item->unpaid : costly_spot(u.ux, u.uy))
+	    loss = stolen_value(item, u.ux, u.uy,
+				(boolean)shkp->mpeaceful, TRUE);
+    }
+    obfree(item, (struct obj *) 0);
+    return loss;
+}
+
+STATIC_OVL void
+observe_quantum_cat(box)
+struct obj *box;
+{
+    static NEARDATA const char sc[] = "Schroedinger's Cat";
+    struct obj *deadcat;
+    struct monst *livecat;
+    xchar ox, oy;
+
+    box->spe = 0;		/* box->owt will be updated below */
+    if (get_obj_location(box, &ox, &oy, 0))
+	box->ox = ox, box->oy = oy;	/* in case it's being carried */
+
+    /* this isn't really right, since any form of observation
+       (telepathic or monster/object/food detection) ought to
+       force the determination of alive vs dead state; but basing
+       it just on opening the box is much simpler to cope with */
+    livecat = rn2(2) ? makemon(&mons[PM_HOUSECAT],
+			       box->ox, box->oy, NO_MINVENT) : 0;
+    if (livecat) {
+	livecat->mpeaceful = 1;
+	set_malign(livecat);
+	if (!canspotmon(livecat))
+	    You("think %s brushed your %s.", something, body_part(FOOT));
+	else
+	    pline("%s inside the box is still alive!", Monnam(livecat));
+	(void) christen_monst(livecat, sc);
+    } else {
+	deadcat = mk_named_object(CORPSE, &mons[PM_HOUSECAT],
+				  box->ox, box->oy, sc);
+	if (deadcat) {
+	    obj_extract_self(deadcat);
+	    (void) add_to_container(box, deadcat);
+	}
+	pline_The("%s inside the box is dead!",
+	    Hallucination ? rndmonnam() : "housecat");
+    }
+    box->owt = weight(box);
+    return;
+}
+
 #undef Icebox
 
 int
@@ -1913,12 +2028,12 @@
 #ifndef GOLDOBJ
 	struct obj *u_gold = (struct obj *)0;
 #endif
-	struct monst *shkp;
-	boolean one_by_one, allflag, loot_out = FALSE, loot_in = FALSE;
+	boolean one_by_one, allflag, quantum_cat = FALSE,
+		loot_out = FALSE, loot_in = FALSE;
 	char select[MAXOCLASSES+1];
 	char qbuf[BUFSZ], emptymsg[BUFSZ], pbuf[QBUFSZ];
 	long loss = 0L;
-	int cnt = 0, used = 0, lcnt = 0,
+	int cnt = 0, used = 0,
 	    menu_on_request;
 
 	emptymsg[0] = '\0';
@@ -1946,80 +2061,35 @@
 	current_container = obj;	/* for use by in/out_container */
 
 	if (obj->spe == 1) {
-	    static NEARDATA const char sc[] = "Schroedinger's Cat";
-	    struct obj *ocat;
-	    struct monst *cat;
-
-	    obj->spe = 0;		/* obj->owt will be updated below */
-	    /* this isn't really right, since any form of observation
-	       (