diff -Naurd ../nethack-3.4.0/include/amiconf.h ./include/amiconf.h
--- ../nethack-3.4.0/include/amiconf.h Wed Mar 20 23:42:42 2002
+++ ./include/amiconf.h Mon Feb 24 15:25:05 2003
@@ -38,7 +38,7 @@
 
 #define NOCWD_ASSUMPTIONS	/* Allow paths to be specified for HACKDIR,
 				   LEVELDIR, SAVEDIR, BONESDIR, DATADIR,
-				   SCOREDIR, LOCKDIR, and CONFIGDIR. */
+				   SCOREDIR, LOCKDIR, CONFIGDIR, and TROUBLEDIR */
 
 /* data librarian defs */
 #ifndef NOCWD_ASSUMPTIONS
@@ -47,6 +47,8 @@
 #else
 # define DLBFILE	"nhdat"			/* main library */
 # define DLBFILE2	"nhsdat"		/* sound library */
+#endif
+
 #define FILENAME_CMP	stricmp			/* case insensitive */
 
 #ifndef __SASC_60
diff -Naurd ../nethack-3.4.0/include/artilist.h ./include/artilist.h
--- ../nethack-3.4.0/include/artilist.h Wed Mar 20 23:42:42 2002
+++ ./include/artilist.h Mon Feb 24 15:25:05 2003
@@ -107,7 +107,7 @@
 
 A("Werebane",			SILVER_SABER,
 	(SPFX_RESTR|SPFX_DFLAG2), 0, M2_WERE,
-	PHYS(5,0),	NO_DFNS,	NO_CARY,	0, A_NONE, NON_PM, NON_PM, 1500L ),
+	PHYS(5,0),	DFNS(AD_WERE),	NO_CARY,	0, A_NONE, NON_PM, NON_PM, 1500L ),
 
 A("Grayswandir",		SILVER_SABER,
 	(SPFX_RESTR|SPFX_HALRES), 0, 0,
diff -Naurd ../nethack-3.4.0/include/color.h ./include/color.h
--- ../nethack-3.4.0/include/color.h Wed Mar 20 23:42:43 2002
+++ ./include/color.h Mon Feb 24 15:25:05 2003
@@ -46,6 +46,7 @@
 #define HI_PAPER	CLR_WHITE
 #define HI_GLASS	CLR_BRIGHT_CYAN
 #define HI_MINERAL	CLR_GRAY
+#define DRAGON_SILVER	CLR_BRIGHT_CYAN
 #define HI_ZAP		CLR_BRIGHT_BLUE
 
 #endif /* COLOR_H */
diff -Naurd ../nethack-3.4.0/include/config.h ./include/config.h
--- ../nethack-3.4.0/include/config.h Wed Mar 20 23:42:43 2002
+++ ./include/config.h Mon Feb 24 15:25:05 2003
@@ -83,7 +83,9 @@
 #endif
 
 #ifdef QT_GRAPHICS
+# define DEFAULT_WC_TILED_MAP   /* Default to tiles if users doesn't say wc_ascii_map */
 # define USER_SOUNDS		/* Use sounds */
+# define USER_SOUNDS_REGEX
 # define USE_XPM		/* Use XPM format for images (required) */
 # define GRAPHIC_TOMBSTONE	/* Use graphical tombstone (rip.ppm) */
 # ifndef DEFAULT_WINDOW_SYS
@@ -131,9 +133,10 @@
 
 /*
  * Section 2:	Some global parameters and filenames.
- *		Commenting out WIZARD, LOGFILE, or NEWS removes that feature
- *		from the game; otherwise set the appropriate wizard name.
- *		LOGFILE and NEWS refer to files in the playground.
+ *		Commenting out WIZARD, LOGFILE, NEWS or PANICLOG removes that
+ *		feature from the game; otherwise set the appropriate wizard
+ *		name.  LOGFILE, NEWS and PANICLOG refer to files in the
+ *		playground.
  */
 
 #ifndef WIZARD		/* allow for compile-time or Makefile changes */
@@ -147,6 +150,7 @@
 
 #define LOGFILE "logfile"	/* larger file for debugging purposes */
 #define NEWS "news"		/* the file containing the latest hack news */
+#define PANICLOG "paniclog"	/* log of panic and impossible events */
 
 /*
  *	If COMPRESS is defined, it should contain the full path name of your
diff -Naurd ../nethack-3.4.0/include/decl.h ./include/decl.h
--- ../nethack-3.4.0/include/decl.h Wed Mar 20 23:42:44 2002
+++ ./include/decl.h Mon Feb 24 15:25:05 2003
@@ -270,16 +270,16 @@
 		*const c_silver, *const c_blue, *const c_purple,
 		*const c_white;
 } c_color_names;
-#define Black		c_color_names.c_black
-#define amber		c_color_names.c_amber
-#define golden		c_color_names.c_golden
-#define light_blue	c_color_names.c_light_blue
-#define red		c_color_names.c_red
-#define green		c_color_names.c_green
-#define silver		c_color_names.c_silver
-#define blue		c_color_names.c_blue
-#define purple		c_color_names.c_purple
-#define White		c_color_names.c_white
+#define NH_BLACK		c_color_names.c_black
+#define NH_AMBER		c_color_names.c_amber
+#define NH_GOLDEN		c_color_names.c_golden
+#define NH_LIGHT_BLUE		c_color_names.c_light_blue
+#define NH_RED			c_color_names.c_red
+#define NH_GREEN		c_color_names.c_green
+#define NH_SILVER		c_color_names.c_silver
+#define NH_BLUE			c_color_names.c_blue
+#define NH_PURPLE		c_color_names.c_purple
+#define NH_WHITE		c_color_names.c_white
 
 /* The names of the colors used for gems, etc. */
 E const char *c_obj_colors[];
@@ -337,7 +337,7 @@
 #endif
 
 /* xxxexplain[] is in drawing.c */
-E const char *monexplain[], *invisexplain, *objexplain[], *oclass_names[];
+E const char * const monexplain[], invisexplain[], * const objexplain[], * const oclass_names[];
 
 /* Some systems want to use full pathnames for some subsets of file names,
  * rather than assuming that they're all in the current directory.  This
@@ -348,11 +348,12 @@
 #define LEVELPREFIX	1
 #define SAVEPREFIX	2
 #define BONESPREFIX	3
-#define DATAPREFIX	4
+#define DATAPREFIX	4	/* this one must match hardcoded value in dlb.c */
 #define SCOREPREFIX	5
 #define LOCKPREFIX	6
 #define CONFIGPREFIX	7
-#define PREFIX_COUNT	8
+#define TROUBLEPREFIX	8
+#define PREFIX_COUNT	9
 /* used in files.c; xxconf.h can override if needed */
 # ifndef FQN_MAX_FILENAME
 #define FQN_MAX_FILENAME 512
diff -Naurd ../nethack-3.4.0/include/display.h ./include/display.h
--- ../nethack-3.4.0/include/display.h Wed Mar 20 23:42:44 2002
+++ ./include/display.h Mon Feb 24 15:25:05 2003
@@ -125,6 +125,7 @@
 
 /*
  * canseeself()
+ * senseself()
  *
  * This returns true if the hero can see her/himself.
  *
@@ -132,7 +133,8 @@
  * 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)
 
 /*
  * random_monster()
@@ -192,28 +194,22 @@
  * _if_ the hero can be seen have already been done.
  */
 #ifdef STEED
-#define display_self()							\
-    show_glyph(u.ux, u.uy,						\
-	(u.usteed && mon_visible(u.usteed)) ?			\
-				ridden_mon_to_glyph(u.usteed) :		\
-	youmonst.m_ap_type == M_AP_NOTHING ?				\
-				hero_glyph :					\
-	youmonst.m_ap_type == M_AP_FURNITURE ?				\
-				cmap_to_glyph(youmonst.mappearance) :	\
-	youmonst.m_ap_type == M_AP_OBJECT ?				\
-				objnum_to_glyph(youmonst.mappearance) : \
-	/* else M_AP_MONSTER */ monnum_to_glyph(youmonst.mappearance))
+#define maybe_display_usteed	(u.usteed && mon_visible(u.usteed)) ? \
+					ridden_mon_to_glyph(u.usteed) :
 #else
+#define maybe_display_usteed	/* empty */
+#endif
+
 #define display_self()							\
     show_glyph(u.ux, u.uy,						\
+	maybe_display_usteed			/* else */		\
 	youmonst.m_ap_type == M_AP_NOTHING ?				\
-				hero_glyph :					\
+				hero_glyph :				\
 	youmonst.m_ap_type == M_AP_FURNITURE ?				\
 				cmap_to_glyph(youmonst.mappearance) :	\
 	youmonst.m_ap_type == M_AP_OBJECT ?				\
 				objnum_to_glyph(youmonst.mappearance) : \
 	/* else M_AP_MONSTER */ monnum_to_glyph(youmonst.mappearance))
-#endif
 
 /*
  * A glyph is an abstraction that represents a _unique_ monster, object,
@@ -314,10 +310,12 @@
 #define ridden_monnum_to_glyph(mnum)	((int) (mnum) + GLYPH_RIDDEN_OFF)
 #define petnum_to_glyph(mnum)	((int) (mnum) + GLYPH_PET_OFF)
 
-/* The hero's glyph when seen as a monster.  Could also be...
- * mon_to_glyph(Upolyd || Race_if(PM_HUMAN) ? u.umonnum : urace.malenum)
+/* The hero's glyph when seen as a monster.
  */
-#define hero_glyph monnum_to_glyph(u.umonnum)
+#define hero_glyph \
+	monnum_to_glyph((Upolyd || !iflags.showrace) ? u.umonnum : \
+	                (flags.female && urace.femalenum != NON_PM) ? urace.femalenum : \
+	                urace.malenum)
 
 
 /*
diff -Naurd ../nethack-3.4.0/include/dlb.h ./include/dlb.h
--- ../nethack-3.4.0/include/dlb.h Wed Mar 20 23:42:44 2002
+++ ./include/dlb.h Mon Feb 24 15:25:05 2003
@@ -125,12 +125,12 @@
 #endif
 
 #define RDTMODE "r"
-#if (defined(MSDOS) || defined(WIN32) || defined(TOS)) && defined(DLB)
+#if (defined(MSDOS) || defined(WIN32) || defined(TOS) || defined(OS2)) && defined(DLB)
 #define WRTMODE "w+b"
 #else
 #define WRTMODE "w+"
 #endif
-#if (defined(MICRO) && !defined(AMIGA)) || defined(THINK_C) || defined(__MWERKS__)
+#if (defined(MICRO) && !defined(AMIGA)) || defined(THINK_C) || defined(__MWERKS__) || defined(WIN32)
 # define RDBMODE "rb"
 # define WRBMODE "w+b"
 #else
diff -Naurd ../nethack-3.4.0/include/extern.h ./include/extern.h
--- ../nethack-3.4.0/include/extern.h Wed Mar 20 23:42:46 2002
+++ ./include/extern.h Mon Feb 24 15:25:05 2003
@@ -39,7 +39,6 @@
 E boolean NDECL(next_to_u);
 E struct obj *FDECL(get_mleash, (struct monst *));
 E void FDECL(check_leash, (XCHAR_P,XCHAR_P));
-E boolean FDECL(wield_tool, (struct obj *));
 E boolean FDECL(um_dist, (XCHAR_P,XCHAR_P,XCHAR_P));
 E boolean FDECL(snuff_candle, (struct obj *));
 E boolean FDECL(snuff_lit, (struct obj *));
@@ -62,6 +61,8 @@
 E void FDECL(artifact_exists, (struct obj *,const char *,BOOLEAN_P));
 E int NDECL(nartifact_exist);
 E boolean FDECL(spec_ability, (struct obj *,unsigned long));
+E boolean FDECL(confers_luck, (struct obj *));
+E boolean FDECL(arti_reflects, (struct obj *));
 E boolean FDECL(restrict_name, (struct obj *,const char *));
 E boolean FDECL(defends, (int,struct obj *));
 E boolean FDECL(protects, (int,struct obj *));
@@ -109,7 +110,7 @@
 E void FDECL(set_bc, (int));
 E void FDECL(move_bc, (int,int,XCHAR_P,XCHAR_P,XCHAR_P,XCHAR_P));
 E boolean FDECL(drag_ball, (XCHAR_P,XCHAR_P,
-		    int *,xchar *,xchar *,xchar *,xchar *, boolean *));
+		int *,xchar *,xchar *,xchar *,xchar *, boolean *,BOOLEAN_P));
 E void FDECL(drop_ball, (XCHAR_P,XCHAR_P));
 E void NDECL(drag_down);
 
@@ -171,6 +172,7 @@
 E int FDECL(getdir, (const char *));
 E void NDECL(confdir);
 E int FDECL(isok, (int,int));
+E int FDECL(get_adjacent_loc, (const char *, const char *, XCHAR_P, XCHAR_P, coord *));
 E const char *FDECL(click_to_cmd, (int,int,int));
 E char NDECL(readchar);
 #ifdef WIZARD
@@ -382,6 +384,7 @@
 E void NDECL(glibr);
 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 void NDECL(reset_remarm);
 E int NDECL(doddoremarm);
 E int FDECL(destroy_arm, (struct obj *));
@@ -577,12 +580,12 @@
 E void FDECL(losexp, (const char *));
 E void NDECL(newexplevel);
 E void FDECL(pluslvl, (BOOLEAN_P));
-E long NDECL(rndexp);
+E long FDECL(rndexp, (BOOLEAN_P));
 
 /* ### explode.c ### */
 
 E void FDECL(explode, (int,int,int,int,CHAR_P,int));
-E void FDECL(scatter, (int, int, int, unsigned int, struct obj *));
+E long FDECL(scatter, (int, int, int, unsigned int, struct obj *));
 E void FDECL(splatter_burning_oil, (int, int));
 
 /* ### extralev.c ### */
@@ -595,19 +598,21 @@
 
 /* ### files.c ### */
 
+E char *FDECL(fname_encode, (const char *, CHAR_P, char *, char *, int));
+E char *FDECL(fname_decode, (CHAR_P, char *, char *, int));
 E const char *FDECL(fqname, (const char *, int, int));
-E FILE *FDECL(fopen_datafile, (const char *,const char *,BOOLEAN_P));
+E FILE *FDECL(fopen_datafile, (const char *,const char *,int));
 E boolean FDECL(uptodate, (int,const char *));
 E void FDECL(store_version, (int));
 #ifdef MFLOPPY
 E void NDECL(set_lock_and_bones);
 #endif
 E void FDECL(set_levelfile_name, (char *,int));
-E int FDECL(create_levelfile, (int));
-E int FDECL(open_levelfile, (int));
+E int FDECL(create_levelfile, (int,char *));
+E int FDECL(open_levelfile, (int,char *));
 E void FDECL(delete_levelfile, (int));
 E void NDECL(clearlocks);
-E int FDECL(create_bonesfile, (d_level*,char **));
+E int FDECL(create_bonesfile, (d_level*,char **, char *));
 #ifdef MFLOPPY
 E void NDECL(cancel_bonesfile);
 #endif
@@ -638,6 +643,16 @@
 #if defined(WIZARD)
 E void NDECL(read_wizkit);
 #endif
+E void FDECL(paniclog, (const char *, const char *));
+E int FDECL(validate_prefix_locations, (char *));
+E char** NDECL(get_saved_games);
+E void FDECL(free_saved_games, (char**));
+#ifdef SELF_RECOVER
+E boolean NDECL(recover_savefile);
+#endif
+#ifdef HOLD_LOCKFILE_OPEN
+E void NDECL(really_close);
+#endif
 
 /* ### fountain.c ### */
 
@@ -662,11 +677,12 @@
 E boolean FDECL(may_passwall, (XCHAR_P,XCHAR_P));
 E boolean FDECL(bad_rock, (struct permonst *,XCHAR_P,XCHAR_P));
 E boolean FDECL(invocation_pos, (XCHAR_P,XCHAR_P));
-E boolean FDECL(test_move, (int, int, int, int, BOOLEAN_P));
+E boolean FDECL(test_move, (int, int, int, int, int));
 E void NDECL(domove);
 E void NDECL(invocation_message);
 E void FDECL(spoteffects, (BOOLEAN_P));
 E char *FDECL(in_rooms, (XCHAR_P,XCHAR_P,int));
+E boolean FDECL(in_town, (int,int));
 E void FDECL(check_special_room, (BOOLEAN_P));
 E int NDECL(dopickup);
 E void NDECL(lookaround);
@@ -695,6 +711,7 @@
 E char *FDECL(upstart, (char *));
 E char *FDECL(mungspaces, (char *));
 E char *FDECL(eos, (char *));
+E char *FDECL(strkitten, (char *,CHAR_P));
 E char *FDECL(s_suffix, (const char *));
 E char *FDECL(xcrypt, (const char *,char *));
 E boolean FDECL(onlyspace, (const char *));
@@ -790,6 +807,7 @@
 E int FDECL(count_buc, (struct obj *,int));
 E void FDECL(carry_obj_effects, (struct obj *));
 E const char *FDECL(currency, (long));
+E void FDECL(silly_thing, (const char *,struct obj *));
 
 /* ### ioctl.c ### */
 
@@ -905,6 +923,7 @@
 E void FDECL(set_malign, (struct monst *));
 E void FDECL(set_mimic_sym, (struct monst *));
 E int FDECL(mbirth_limit, (int));
+E void FDECL(mimic_hit_msg, (struct monst *, SHORT_P));
 #ifdef GOLDOBJ
 E void FDECL(mkmonmoney, (struct monst *, long));
 #endif
@@ -925,6 +944,7 @@
 E int FDECL(noattacks, (struct permonst *));
 E int FDECL(sleep_monst, (struct monst *,int,int));
 E void FDECL(slept_monst, (struct monst *));
+E long FDECL(attk_protection, (int));
 
 /* ### mhitu.c ### */
 
@@ -934,6 +954,7 @@
 E void FDECL(expels, (struct monst *,struct permonst *,BOOLEAN_P));
 E struct attack *FDECL(getmattk, (struct permonst *,int,int *,struct attack *));
 E int FDECL(mattacku, (struct monst *));
+E int FDECL(magic_negation, (struct monst *));
 E int FDECL(gazemu, (struct monst *,struct attack *));
 E void FDECL(mdamageu, (struct monst *,int));
 E int FDECL(could_seduce, (struct monst *,struct monst *,struct attack *));
@@ -943,7 +964,7 @@
 
 /* ### minion.c ### */
 
-E void FDECL(msummon, (struct permonst *));
+E void FDECL(msummon, (struct monst *));
 E void FDECL(summon_minion, (ALIGNTYP_P,BOOLEAN_P));
 E int FDECL(demon_talk, (struct monst *));
 E long FDECL(bribe, (struct monst *));
@@ -1107,7 +1128,7 @@
 E void NDECL(restartcham);
 E void FDECL(restore_cham, (struct monst *));
 E void FDECL(mon_animal_list, (BOOLEAN_P));
-E int FDECL(newcham, (struct monst *,struct permonst *,BOOLEAN_P));
+E int FDECL(newcham, (struct monst *,struct permonst *,BOOLEAN_P,BOOLEAN_P));
 E int FDECL(can_be_hatched, (int));
 E int FDECL(egg_type_from_parent, (int,BOOLEAN_P));
 E boolean FDECL(dead_species, (int,BOOLEAN_P));
@@ -1128,10 +1149,12 @@
 E boolean FDECL(can_blnd, (struct monst *,struct monst *,UCHAR_P,struct obj *));
 E boolean FDECL(ranged_attk, (struct permonst *));
 E boolean FDECL(hates_silver, (struct permonst *));
+E boolean FDECL(passes_bars, (struct permonst *));
 E boolean FDECL(can_track, (struct permonst *));
 E boolean FDECL(breakarm, (struct permonst *));
 E boolean FDECL(sliparm, (struct permonst *));
 E boolean FDECL(sticks, (struct permonst *));
+E int FDECL(num_horns, (struct permonst *));
 /* E boolean FDECL(canseemon, (struct monst *)); */
 E struct attack *FDECL(dmgtype_fromattack, (struct permonst *,int,int));
 E boolean FDECL(dmgtype, (struct permonst *,int));
@@ -1145,6 +1168,8 @@
 E int FDECL(big_to_little, (int));
 E const char *FDECL(locomotion, (const struct permonst *,const char *));
 E const char *FDECL(stagger, (const struct permonst *,const char *));
+E const char *FDECL(on_fire, (struct permonst *,struct attack *));
+E const struct permonst *FDECL(raceptr, (struct monst *));
 
 /* ### monmove.c ### */
 
@@ -1176,7 +1201,7 @@
 E void FDECL(create_mplayers, (int,BOOLEAN_P));
 E void FDECL(mplayer_talk, (struct monst *));
 
-#ifdef MICRO
+#if defined(MICRO) || defined(WIN32)
 
 /* ### msdos.c,os2.c,tos.c,winnt.c ### */
 
@@ -1225,8 +1250,7 @@
 E int NDECL((*nt_kbhit));
 E void FDECL(Delay, (int));
 # endif /* WIN32 */
-
-#endif /* MICRO */
+#endif /* MICRO || WIN32 */
 
 /* ### mthrowu.c ### */
 
@@ -1240,6 +1264,7 @@
 E struct obj *FDECL(m_carrying, (struct monst *,int));
 E void FDECL(m_useup, (struct monst *,struct obj *));
 E void FDECL(m_throw, (struct monst *,int,int,int,int,int,struct obj *));
+E boolean FDECL(hits_bars, (struct obj **,int,int,int,int));
 
 /* ### muse.c ### */
 
@@ -1310,6 +1335,7 @@
 E char *FDECL(simple_typename, (int));
 E boolean FDECL(obj_is_pname, (struct obj *));
 E char *FDECL(distant_name, (struct obj *,char *(*)(OBJ_P)));
+E char *FDECL(fruitname, (BOOLEAN_P));
 E char *FDECL(xname, (struct obj *));
 E char *FDECL(mshot_xname, (struct obj *));
 E boolean FDECL(the_unique_obj, (struct obj *obj));
@@ -1334,6 +1360,7 @@
 E struct obj *FDECL(readobjnam, (char *,struct obj *,BOOLEAN_P));
 E int FDECL(rnd_class, (int,int));
 E const char *FDECL(cloak_simple_name, (struct obj *));
+E const char *FDECL(mimic_obj_name, (struct monst *));
 
 /* ### options.c ### */
 
@@ -1352,7 +1379,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_option_mod_status, (char *, int));
+E void FDECL(set_option_mod_status, (const char *,int));
 
 /* ### pager.c ### */
 
@@ -1360,20 +1387,21 @@
 E int NDECL(doquickwhatis);
 E int NDECL(doidtrap);
 E int NDECL(dowhatdoes);
+E char *FDECL(dowhatdoes_core,(CHAR_P, char *));
 E int NDECL(dohelp);
 E int NDECL(dohistory);
 
 /* ### pcmain.c ### */
 
-#if defined(MICRO)
+#if defined(MICRO) || defined(WIN32)
 # ifdef CHDIR
 E void FDECL(chdirx, (char *,BOOLEAN_P));
 # endif /* CHDIR */
-#endif /* MICRO */
+#endif /* MICRO || WIN32 */
 
 /* ### pcsys.c ### */
 
-#ifdef MICRO
+#if defined(MICRO) || defined(WIN32)
 E void NDECL(flushout);
 E int NDECL(dosh);
 # ifdef MFLOPPY
@@ -1389,11 +1417,11 @@
 E void VDECL(msmsg, (const char *,...));
 # endif
 E FILE *FDECL(fopenp, (const char *,const char *));
-#endif /* MICRO */
+#endif /* MICRO || WIN32 */
 
 /* ### pctty.c ### */
 
-#if defined(MICRO)
+#if defined(MICRO) || defined(WIN32)
 E void NDECL(gettty);
 E void FDECL(settty, (const char *));
 E void NDECL(setftty);
@@ -1401,7 +1429,7 @@
 #if defined(TIMED_DELAY) && defined(_MSC_VER)
 E void FDECL(msleep, (unsigned));
 #endif
-#endif /* MICRO */
+#endif /* MICRO || WIN32 */
 
 /* ### pcunix.c ### */
 
@@ -1416,10 +1444,10 @@
 
 #ifdef GOLDOBJ
 E int FDECL(collect_obj_classes,
-	(char *,struct obj *,BOOLEAN_P,boolean FDECL((*),(OBJ_P))));
+	(char *,struct obj *,BOOLEAN_P,boolean FDECL((*),(OBJ_P)), int *));
 #else
 E int FDECL(collect_obj_classes,
-	(char *,struct obj *,BOOLEAN_P,BOOLEAN_P,boolean FDECL((*),(OBJ_P))));
+	(char *,struct obj *,BOOLEAN_P,BOOLEAN_P,boolean FDECL((*),(OBJ_P)), int *));
 #endif
 E void FDECL(add_valid_menu_class, (int));
 E boolean FDECL(allow_all, (struct obj *));
@@ -1619,14 +1647,14 @@
 E NhRegion *FDECL(visible_region_at, (XCHAR_P,XCHAR_P));
 E void FDECL(show_region, (NhRegion*, XCHAR_P, XCHAR_P));
 E void FDECL(save_regions, (int,int));
-E void FDECL(rest_regions, (int));
+E void FDECL(rest_regions, (int,BOOLEAN_P));
 E NhRegion* FDECL(create_gas_cloud, (XCHAR_P, XCHAR_P, int, int));
 
 /* ### restore.c ### */
 
 E void FDECL(inven_inuse, (BOOLEAN_P));
 E int FDECL(dorecover, (int));
-E void NDECL(trickery);
+E void FDECL(trickery, (char *));
 E void FDECL(getlev, (int,int,XCHAR_P,BOOLEAN_P));
 E void NDECL(minit);
 E boolean FDECL(lookup_id_mapping, (unsigned, unsigned *));
@@ -1741,7 +1769,7 @@
 E void FDECL(hot_pursuit, (struct monst *));
 E void FDECL(make_angry_shk, (struct monst *,XCHAR_P,XCHAR_P));
 E int NDECL(dopay);
-E boolean FDECL(paybill, (BOOLEAN_P));
+E boolean FDECL(paybill, (int));
 E void NDECL(finish_paybill);
 E struct obj *FDECL(find_oid, (unsigned));
 E long FDECL(contained_cost, (struct obj *,struct monst *,long,BOOLEAN_P, BOOLEAN_P));
@@ -1759,9 +1787,10 @@
 E void FDECL(add_damage, (XCHAR_P,XCHAR_P,long));
 E int FDECL(repair_damage, (struct monst *,struct damage *,BOOLEAN_P));
 E int FDECL(shk_move, (struct monst *));
+E void FDECL(after_shk_move, (struct monst *));
 E boolean FDECL(is_fshk, (struct monst *));
 E void FDECL(shopdig, (int));
-E void FDECL(pay_for_damage, (const char *));
+E void FDECL(pay_for_damage, (const char *,BOOLEAN_P));
 E boolean FDECL(costly_spot, (XCHAR_P,XCHAR_P));
 E struct obj *FDECL(shop_object, (XCHAR_P,XCHAR_P));
 E void FDECL(price_quote, (struct obj *));
@@ -1798,6 +1827,7 @@
 E int NDECL(dotalk);
 #ifdef USER_SOUNDS
 E int FDECL(add_sound_mapping, (const char *));
+E void FDECL(play_sound_for_message, (const char *));
 #endif
 
 /* ### sys/msdos/sound.c ### */
@@ -1843,7 +1873,7 @@
 E long NDECL(somegold);
 #endif
 E void FDECL(stealgold, (struct monst *));
-E void FDECL(remove_worn_item, (struct obj *));
+E void FDECL(remove_worn_item, (struct obj *,BOOLEAN_P));
 E int FDECL(steal, (struct monst *, char *));
 E int FDECL(mpickobj, (struct monst *,struct obj *));
 E void FDECL(stealamulet, (struct monst *));
@@ -1855,6 +1885,7 @@
 /* ### steed.c ### */
 
 #ifdef STEED
+E void NDECL(rider_cant_reach);
 E boolean FDECL(can_saddle, (struct monst *));
 E int FDECL(use_saddle, (struct obj *));
 E boolean FDECL(can_ride, (struct monst *));
@@ -1868,10 +1899,11 @@
 
 /* ### teleport.c ### */
 
-E boolean FDECL(goodpos, (int,int,struct monst *));
+E boolean FDECL(goodpos, (int,int,struct monst *,unsigned));
 E boolean FDECL(enexto, (coord *,XCHAR_P,XCHAR_P,struct permonst *));
-E void FDECL(teleds, (int,int));
-E boolean NDECL(safe_teleds);
+E boolean FDECL(enexto_core, (coord *,XCHAR_P,XCHAR_P,struct permonst *,unsigned));
+E void FDECL(teleds, (int,int,BOOLEAN_P));
+E boolean FDECL(safe_teleds, (BOOLEAN_P));
 E boolean FDECL(teleport_pet, (struct monst *,BOOLEAN_P));
 E void NDECL(tele);
 E int NDECL(dotele);
@@ -1978,6 +2010,7 @@
 
 E void FDECL(hurtmarmor,(struct monst *,int));
 E boolean FDECL(attack_checks, (struct monst *,struct obj *));
+E void FDECL(check_caitiff, (struct monst *));
 E schar FDECL(find_roll_to_hit, (struct monst *));
 E boolean FDECL(attack, (struct monst *));
 E boolean FDECL(hmon, (struct monst *,struct obj *,int));
@@ -2051,6 +2084,9 @@
 				const char *,BOOLEAN_P));
 E unsigned long FDECL(get_feature_notice_ver, (char *));
 E unsigned long NDECL(get_current_feature_ver);
+#ifdef RUNTIME_PORT_ID
+E void FDECL(append_port_id, (char *));
+#endif
 
 /* ### video.c ### */
 
@@ -2163,7 +2199,7 @@
 E int FDECL(dmgval, (struct obj *,struct monst *));
 E struct obj *FDECL(select_rwep, (struct monst *));
 E struct obj *FDECL(select_hwep, (struct monst *));
-E void FDECL(possibly_unwield, (struct monst *));
+E void FDECL(possibly_unwield, (struct monst *,BOOLEAN_P));
 E int FDECL(mon_wield_item, (struct monst *));
 E int NDECL(abon);
 E int NDECL(dbon);
@@ -2176,7 +2212,7 @@
 E int NDECL(uwep_skill_type);
 E int FDECL(weapon_hit_bonus, (struct obj *));
 E int FDECL(weapon_dam_bonus, (struct obj *));
-E void FDECL(skill_init, (struct def_skill *));
+E void FDECL(skill_init, (const struct def_skill *));
 
 /* ### were.c ### */
 
@@ -2194,12 +2230,14 @@
 E int NDECL(dowield);
 E int NDECL(doswapweapon);
 E int NDECL(dowieldquiver);
-E int NDECL(dotwoweapon);
+E boolean FDECL(wield_tool, (struct obj *,const char *));
 E int NDECL(can_twoweapon);
-E void NDECL(untwoweapon);
+E void NDECL(drop_uswapwep);
+E int NDECL(dotwoweapon);
 E void NDECL(uwepgone);
 E void NDECL(uswapwepgone);
 E void NDECL(uqwepgone);
+E void NDECL(untwoweapon);
 E void FDECL(erode_obj, (struct obj *,BOOLEAN_P,BOOLEAN_P));
 E int FDECL(chwepon, (struct obj *,int));
 E int FDECL(welded, (struct obj *));
@@ -2251,13 +2289,15 @@
 E void FDECL(setnotworn, (struct obj *));
 E void FDECL(mon_set_minvis, (struct monst *));
 E void FDECL(mon_adjust_speed, (struct monst *,int,struct obj *));
-E void FDECL(update_mon_intrinsics, (struct monst *,struct obj *,BOOLEAN_P));
+E void FDECL(update_mon_intrinsics,
+		(struct monst *,struct obj *,BOOLEAN_P,BOOLEAN_P));
 E int FDECL(find_mac, (struct monst *));
 E void FDECL(m_dowear, (struct monst *,BOOLEAN_P));
 E struct obj *FDECL(which_armor, (struct monst *,long));
 E void FDECL(mon_break_armor, (struct monst *,BOOLEAN_P));
 E void FDECL(bypass_obj, (struct obj *));
 E void NDECL(clear_bypasses);
+E int FDECL(racial_exception, (struct monst *, struct obj *));
 
 /* ### write.c ### */
 
@@ -2285,8 +2325,8 @@
 E void FDECL(zapnodir, (struct obj *));
 E int NDECL(dozap);
 E int FDECL(zapyourself, (struct obj *,BOOLEAN_P));
-E void FDECL(cancel_monst, (struct monst *,struct obj *,
-			    BOOLEAN_P,BOOLEAN_P,BOOLEAN_P));
+E boolean FDECL(cancel_monst, (struct monst *,struct obj *,
+			       BOOLEAN_P,BOOLEAN_P,BOOLEAN_P));
 E void FDECL(weffects, (struct obj *));
 E int NDECL(spell_damage_bonus);
 E const char *FDECL(exclam, (int force));
diff -Naurd ../nethack-3.4.0/include/flag.h ./include/flag.h
--- ../nethack-3.4.0/include/flag.h Wed Mar 20 23:42:46 2002
+++ ./include/flag.h Mon Feb 24 15:25:05 2003
@@ -165,6 +165,8 @@
 	boolean  window_inited; /* true if init_nhwindows() completed */
 	boolean  vision_inited; /* true if vision is ready */
 	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 */
 	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 */
@@ -174,7 +176,7 @@
 	boolean  mon_polycontrol;	/* debug: control monster polymorphs */
 #endif
 #ifdef TTY_GRAPHICS
-	boolean prevmsg_window;	/* show more old messages at a time */
+	char prevmsg_window;	/* type of old message window to use */
 	boolean  extmenu;	/* extended commands use menu interface */
 #endif
 #ifdef MFLOPPY
@@ -241,6 +243,7 @@
 	int     wc_fontsiz_status;	/* font size for the status window     */
 	int     wc_fontsiz_menu;	/* font size for the menu window       */
 	int     wc_fontsiz_text;	/* font size for text windows          */
+	int	wc_scroll_amount;	/* scroll this amount at scroll_margin */
 	int	wc_scroll_margin;	/* scroll map when this far from
 						the edge */
 	int	wc_map_mode;		/* specify map viewing options, mostly
@@ -249,9 +252,16 @@
 	boolean	wc_splash_screen;	/* display an opening splash screen or not */
 	boolean	wc_popup_dialog;	/* put queries in pop up dialogs instead of
 				   		in the message window */
-	boolean wc_large_font;		/* draw in larger fonts (say, 12pt instead
-				   		of 9pt) */
 	boolean wc_eight_bit_input;	/* allow eight bit input               */
+	boolean wc_mouse_support;	/* allow mouse support */
+
+	boolean  cmdassist;	/* provide detailed assistance for some commands */
+	boolean	 obsolete;	/* obsolete options can point at this, it isn't used */
+	/* Items which belong in flags, but are here to allow save compatibility */
+	boolean  lootabc;	/* use "a/b/c" rather than "o/i/b" when looting */
+	boolean  showrace;	/* show hero glyph by race rather than by role */
+	boolean  travelcmd;	/* allow travel command */
+	int	 runmode;	/* update screen display during run moves */
 };
 
 /*
@@ -266,7 +276,7 @@
 #define hilite_pet wc_hilite_pet
 #define use_inverse wc_inverse
 #ifdef MAC_GRAPHICS_ENV
-#define large_font wc_large_font
+#define large_font obsolete
 #endif
 #ifdef MAC
 #define popup_dialog wc_popup_dialog
@@ -276,4 +286,10 @@
 extern NEARDATA struct flag flags;
 extern NEARDATA struct instance_flags iflags;
 
+/* runmode options */
+#define RUN_TPORT	0	/* don't update display until movement stops */
+#define RUN_LEAP	1	/* update display every 7 steps */
+#define RUN_STEP	2	/* update display every single step */
+#define RUN_CRAWL	3	/* walk w/ extra delay after each update */
+
 #endif /* FLAG_H */
diff -Naurd ../nethack-3.4.0/include/global.h ./include/global.h
--- ../nethack-3.4.0/include/global.h Wed Mar 20 23:42:47 2002
+++ ./include/global.h Mon Feb 24 15:25:05 2003
@@ -333,7 +339,7 @@
 
 #define MAXULEV		30	/* max character experience level */
 
-#define MAXMONNO	120	/* geno monst after this number killed */
+#define MAXMONNO	120	/* extinct monst after this number created */
 #define MHPMAX		500	/* maximum monster hp */
 
 #endif /* GLOBAL_H */
diff -Naurd ../nethack-3.4.0/include/hack.h ./include/hack.h
--- ../nethack-3.4.0/include/hack.h Wed Mar 20 23:42:47 2002
+++ ./include/hack.h Mon Feb 24 15:25:05 2003
@@ -24,11 +24,11 @@
 
 /* symbolic names for capacity levels */
 #define UNENCUMBERED	0
-#define SLT_ENCUMBER	1
-#define MOD_ENCUMBER	2
-#define HVY_ENCUMBER	3
-#define EXT_ENCUMBER	4
-#define OVERLOADED	5
+#define SLT_ENCUMBER	1	/* Burdened */
+#define MOD_ENCUMBER	2	/* Stressed */
+#define HVY_ENCUMBER	3	/* Strained */
+#define EXT_ENCUMBER	4	/* Overtaxed */
+#define OVERLOADED	5	/* Overloaded */
 
 /* Macros for how a rumor was delivered in outrumor() */
 #define BY_ORACLE	0
@@ -139,6 +139,7 @@
 #define MM_ANGRY	  0x10  /* monster is created angry */
 #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 */
 
 /* flags for special ggetobj status returns */
 #define ALL_FINISHED	  0x01  /* called routine already finished the job */
@@ -178,6 +179,11 @@
 /* Flags to control dotrap() in trap.c */
 #define NOWEBMSG	0x01	/* suppress stumble into web message */
 
+/* Flags to control test_move in hack.c */
+#define DO_MOVE		0	/* really doing the move */
+#define TEST_MOVE	1	/* test a normal move (move there next) */
+#define TEST_TRAV	2	/* test a future travel location */
+
 /*** some utility macros ***/
 #define yn(query) yn_function(query,ynchars, 'n')
 #define ynq(query) yn_function(query,ynqchars, 'q')
@@ -195,8 +201,9 @@
 #define MAY_FRACTURE	0x10	/* boulders & statues may fracture */
 
 /* Macros for launching objects */
-#define ROLL	1
-#define FLING	2
+#define ROLL		0x01	/* the object is rolling */
+#define FLING		0x02	/* the object is flying thru the air */
+#define LAUNCH_KNOWN	0x80	/* the hero caused this by explicit action */
 
 /* Macros for explosion types */
 #define EXPL_DARK	0
diff -Naurd ../nethack-3.4.0/include/mfndpos.h ./include/mfndpos.h
--- ../nethack-3.4.0/include/mfndpos.h Wed Mar 20 23:42:49 2002
+++ ./include/mfndpos.h Mon Feb 24 15:25:05 2003
@@ -17,6 +17,7 @@
 #define ALLOW_ROCK	0x02000000L	/* pushes rocks */
 #define ALLOW_WALL	0x04000000L	/* walks thru walls */
 #define ALLOW_DIG	0x08000000L	/* digs */
+#define ALLOW_BARS	0x10000000L	/* may pass thru iron bars */
 #define ALLOW_SANCT	0x20000000L	/* enters temples */
 #define ALLOW_SSM	0x40000000L	/* ignores scare monster */
 #ifdef NHSTDC
diff -Naurd ../nethack-3.4.0/include/mkroom.h ./include/mkroom.h
--- ../nethack-3.4.0/include/mkroom.h Wed Mar 20 23:42:49 2002
+++ ./include/mkroom.h Mon Feb 24 15:25:05 2003
@@ -31,7 +31,7 @@
 	    int iprob;		/* probability of an item type */
 	    int itype;	/* item type: if >=0 a class, if < 0 a specific item */
 	} iprobs[5];
-	const char **shknms;	/* list of shopkeeper names for this type */
+	const char * const *shknms;	/* list of shopkeeper names for this type */
 };
 
 extern NEARDATA struct mkroom rooms[(MAXNROFROOMS+1)*2];
diff -Naurd ../nethack-3.4.0/include/monattk.h ./include/monattk.h
--- ../nethack-3.4.0/include/monattk.h Wed Mar 20 23:42:49 2002
+++ ./include/monattk.h Mon Feb 24 15:25:05 2003
@@ -8,6 +8,7 @@
 /*	Add new attack types below - ordering affects experience (exper.c).
  *	Attacks > AT_BUTT are worth extra experience.
  */
+#define AT_ANY		(-1)	/* fake attack; dmgtype_fromattack wildcard */
 #define AT_NONE		0	/* passive monster (ex. acid blob) */
 #define AT_CLAW		1	/* claw (punch, hit, etc.) */
 #define AT_BITE		2	/* bite */
@@ -32,6 +33,7 @@
  *	Note that 1-10 correspond to the types of attack used in buzz().
  *	Please don't disturb the order unless you rewrite the buzz() code.
  */
+#define AD_ANY		(-1)	/* fake damage; attacktype_fordmg wildcard */
 #define AD_PHYS		0	/* ordinary physical */
 #define AD_MAGM		1	/* magic missiles */
 #define AD_FIRE		2	/* fire damage */
diff -Naurd ../nethack-3.4.0/include/mondata.h ./include/mondata.h
--- ../nethack-3.4.0/include/mondata.h Wed Mar 20 23:42:49 2002
+++ ./include/mondata.h Mon Feb 24 15:25:05 2003
@@ -19,6 +19,11 @@
 #define resists_acid(mon)	(((mon)->mintrinsics & MR_ACID) != 0)
 #define resists_ston(mon)	(((mon)->mintrinsics & MR_STONE) != 0)
 
+#define is_lminion(mon)		(is_minion((mon)->data) && \
+				 (mon)->data->maligntyp >= A_COALIGNED && \
+				 ((mon)->data != &mons[PM_ANGEL] || \
+				  EPRI(mon)->shralign > 0))
+
 #define is_flyer(ptr)		(((ptr)->mflags1 & M1_FLY) != 0L)
 #define is_floater(ptr)		((ptr)->mlet == S_EYE)
 #define is_clinger(ptr)		(((ptr)->mflags1 & M1_CLING) != 0L)
@@ -40,6 +45,7 @@
 #define nolimbs(ptr)		(((ptr)->mflags1 & M1_NOLIMBS) == M1_NOLIMBS)
 #define notake(ptr)		(((ptr)->mflags1 & M1_NOTAKE) != 0L)
 #define has_head(ptr)		(((ptr)->mflags1 & M1_NOHEAD) == 0L)
+#define has_horns(ptr)		(num_horns(ptr) > 0)
 #define is_whirly(ptr)		((ptr)->mlet == S_VORTEX || \
 				 (ptr) == &mons[PM_AIR_ELEMENTAL])
 #define is_silent(ptr)		((ptr)->msound == MS_SILENT)
@@ -105,8 +111,6 @@
 #define is_dlord(ptr)		(is_demon(ptr) && is_lord(ptr))
 #define is_dprince(ptr)		(is_demon(ptr) && is_prince(ptr))
 #define is_minion(ptr)		((ptr)->mflags2 & M2_MINION)
-#define is_lminion(ptr)		(is_minion(ptr) && \
-				 (ptr)->maligntyp >= A_COALIGNED)
 #define likes_gold(ptr)		(((ptr)->mflags2 & M2_GREEDY) != 0L)
 #define likes_gems(ptr)		(((ptr)->mflags2 & M2_JEWELS) != 0L)
 #define likes_objs(ptr)		(((ptr)->mflags2 & M2_COLLECT) != 0L || \
diff -Naurd ../nethack-3.4.0/include/monst.h ./include/monst.h
--- ../nethack-3.4.0/include/monst.h Wed Mar 20 23:42:50 2002
+++ ./include/monst.h Mon Feb 24 15:25:05 2003
@@ -6,7 +6,7 @@
 #define MONST_H
 
 /* The weapon_check flag is used two ways:
- * 1) When calling mon_wield_item, is 2, 3, or 4 depending on what is desired.
+ * 1) When calling mon_wield_item, is 2-6 depending on what is desired.
  * 2) Between calls to mon_wield_item, is 0 or 1 depending on whether or not
  *    the weapon is known by the monster to be cursed (so it shouldn't bother
  *    trying for another weapon).
@@ -20,6 +20,8 @@
 # define NEED_RANGED_WEAPON 2
 # define NEED_HTH_WEAPON 3
 # define NEED_PICK_AXE 4
+# define NEED_AXE 5
+# define NEED_PICK_OR_AXE 6
 
 /* The following flags are used for the second argument to display_minventory
  * in invent.c:
@@ -98,7 +100,7 @@
 	Bitfield(mstun,1);	/* stunned (off balance) */
 	Bitfield(mconf,1);	/* confused */
 	Bitfield(mpeaceful,1);	/* does not attack unprovoked */
-	Bitfield(mtrapped,1);	/* trapped in a pit or bear trap */
+	Bitfield(mtrapped,1);	/* trapped in a pit, web or bear trap */
 	Bitfield(mleashed,1);	/* monster is on a leash */
 	Bitfield(isshk,1);	/* is shopkeeper */
 	Bitfield(isminion,1);	/* is a minion */
diff -Naurd ../nethack-3.4.0/include/obj.h ./include/obj.h
--- ../nethack-3.4.0/include/obj.h Wed Mar 20 23:42:51 2002
+++ ./include/obj.h Mon Feb 24 15:25:05 2003
@@ -70,6 +70,7 @@
 	Bitfield(olocked,1);	/* object is locked */
 	Bitfield(obroken,1);	/* lock has been broken */
 	Bitfield(otrapped,1);	/* container is trapped */
+				/* or accidental tripped rolling boulder trap */
 #define opoisoned otrapped	/* object (weapon) is coated with poison */
 
 	Bitfield(recharged,3);	/* number of times it's been recharged */
@@ -179,7 +180,24 @@
 			 objects[otmp->otyp].oc_armcat == ARM_SHIRT)
 #define is_suit(otmp)	(otmp->oclass == ARMOR_CLASS && \
 			 objects[otmp->otyp].oc_armcat == ARM_SUIT)
+#define is_elven_armor(otmp)	((otmp)->otyp == ELVEN_LEATHER_HELM\
+				|| (otmp)->otyp == ELVEN_MITHRIL_COAT\
+				|| (otmp)->otyp == ELVEN_CLOAK\
+				|| (otmp)->otyp == ELVEN_SHIELD\
+				|| (otmp)->otyp == ELVEN_BOOTS)
+#define is_orcish_armor(otmp)	((otmp)->otyp == ORCISH_HELM\
+				|| (otmp)->otyp == ORCISH_CHAIN_MAIL\
+				|| (otmp)->otyp == ORCISH_RING_MAIL\
+				|| (otmp)->otyp == ORCISH_CLOAK\
+				|| (otmp)->otyp == URUK_HAI_SHIELD\
+				|| (otmp)->otyp == ORCISH_SHIELD)
+#define is_dwarvish_armor(otmp)	((otmp)->otyp == DWARVISH_IRON_HELM\
+				|| (otmp)->otyp == DWARVISH_MITHRIL_COAT\
+				|| (otmp)->otyp == DWARVISH_CLOAK\
+				|| (otmp)->otyp == DWARVISH_ROUNDSHIELD)
+#define is_gnomish_armor(otmp)	(FALSE)
 
+				
 /* Eggs and other food */
 #define MAX_EGG_HATCH_TIME 200	/* longest an egg can remain unhatched */
 #define stale_egg(egg)	((monstermoves - (egg)->age) > (2*MAX_EGG_HATCH_TIME))
@@ -211,6 +229,32 @@
 				      - GRAY_DRAGON_SCALE_MAIL]
 #define Dragon_to_scales(pm)	(GRAY_DRAGON_SCALES + (pm - mons))
 
+/* Elven gear */
+#define is_elven_weapon(otmp)	((otmp)->otyp == ELVEN_ARROW\
+				|| (otmp)->otyp == ELVEN_SPEAR\
+				|| (otmp)->otyp == ELVEN_DAGGER\
+				|| (otmp)->otyp == ELVEN_SHORT_SWORD\
+				|| (otmp)->otyp == ELVEN_BROADSWORD\
+				|| (otmp)->otyp == ELVEN_BOW)
+#define is_elven_obj(otmp)	(is_elven_armor(otmp) || is_elven_weapon(otmp))
+
+/* Orcish gear */
+#define is_orcish_obj(otmp)	(is_orcish_armor(otmp)\
+				|| (otmp)->otyp == ORCISH_ARROW\
+				|| (otmp)->otyp == ORCISH_SPEAR\
+				|| (otmp)->otyp == ORCISH_DAGGER\
+				|| (otmp)->otyp == ORCISH_SHORT_SWORD\
+				|| (otmp)->otyp == ORCISH_BOW)
+
+/* Dwarvish gear */
+#define is_dwarvish_obj(otmp)	(is_dwarvish_armor(otmp)\
+				|| (otmp)->otyp == DWARVISH_SPEAR\
+				|| (otmp)->otyp == DWARVISH_SHORT_SWORD\
+				|| (otmp)->otyp == DWARVISH_MATTOCK)
+
+/* Gnomish gear */
+#define is_gnomish_obj(otmp)	(is_gnomish_armor(otmp))
+
 /* Light sources */
 #define Is_candle(otmp) (otmp->otyp == TALLOW_CANDLE || \
 			 otmp->otyp == WAX_CANDLE)
diff -Naurd ../nethack-3.4.0/include/objclass.h ./include/objclass.h
--- ../nethack-3.4.0/include/objclass.h Wed Mar 20 23:42:51 2002
+++ ./include/objclass.h Mon Feb 24 15:25:05 2003
@@ -133,7 +133,7 @@
 #define SCROLL_CLASS	 9
 #define SPBOOK_CLASS	10	/* actually SPELL-book */
 #define WAND_CLASS	11
-#define GOLD_CLASS	12
+#define COIN_CLASS	12
 #define GEM_CLASS	13
 #define ROCK_CLASS	14
 #define BALL_CLASS	15
diff -Naurd ../nethack-3.4.0/include/pcconf.h ./include/pcconf.h
--- ../nethack-3.4.0/include/pcconf.h Wed Mar 20 23:42:51 2002
+++ ./include/pcconf.h Mon Feb 24 15:25:05 2003
@@ -17,7 +17,7 @@
  *     _MSC_VER is defined automatically by Microsoft C.
  *     __BORLANDC__ is defined automatically by Borland C.
  *     __SC__ is defined automatically by Symantec C.
- *	Note: 3.4.0 was not verified with Symantec C.
+ *	Note: 3.4.1 was not verified with Symantec C.
  */
 
 /*
@@ -99,10 +99,6 @@
 			/* amiconf.h).	In the future this will be the */
 			/* hook for mail reader implementation.        */
 
-/*# define PC_LOCKING */	/* Allow confirmation before overwriting game  */
-			/* that is in progress or aborted when another */
-			/* game is started with the same player name.  */
-
 /* The following is needed for prototypes of certain functions */
 
 #if defined(_MSC_VER) || defined(__BORLANDC__) || defined(__SC__)
@@ -141,7 +137,7 @@
 # endif
 #define NOCWD_ASSUMPTIONS	/* Allow paths to be specified for HACKDIR,
 				   LEVELDIR, SAVEDIR, BONESDIR, DATADIR,
-				   SCOREDIR, LOCKDIR, and CONFIGDIR */
+				   SCOREDIR, LOCKDIR, CONFIGDIR, and TROUBLEDIR. */
 
 #endif /* MSDOS configuration stuff */
 
@@ -160,12 +156,16 @@
 #include "system.h"
 #endif
 
-#ifdef __GO32__
+#ifdef __DJGPP__
 #include <unistd.h> /* close(), etc. */
-/* setmode is in io.h but lock() in io.h interferes with lock[] in decl.h */
-extern int FDECL(setmode, (int,int));
+/* lock() in io.h interferes with lock[] in decl.h */
+#define lock djlock
+#include <io.h>
+#undef lock
 #include <pc.h> /* kbhit() */
 #define PC_LOCKING
+#define HOLD_LOCKFILE_OPEN
+#define SELF_RECOVER		/* NetHack itself can recover games */
 #endif
 
 # ifdef MSDOS
diff -Naurd ../nethack-3.4.0/include/qtext.h ./include/qtext.h
--- ../nethack-3.4.0/include/qtext.h Wed Mar 20 23:42:52 2002
+++ ./include/qtext.h Mon Feb 24 15:25:05 2003
@@ -35,6 +35,7 @@
 #define CREC_IN_MSG	"Control record encountered during message - line %d\n"
 #define DUP_MSG		"Duplicate message number at line %d\n"
 #define END_NOT_IN_MSG	"End record encountered before message - line %d\n"
+#define TEXT_NOT_IN_MSG	"Text encountered outside message - line %d\n"
 #define UNREC_CREC	"Unrecognized Control record at line %d\n"
 #define OUT_OF_HEADERS	"Too many message types (line %d)\nAdjust N_HDR in qtext.h and recompile.\n"
 #define OUT_OF_MESSAGES "Too many messages in class (line %d)\nAdjust N_MSG in qtext.h and recompile.\n"
@@ -105,6 +106,7 @@
 #define QT_DEMONIC	30
 #define QTN_DEMONIC	20
 
+#define QT_BANISHED	60
 #endif	/***** !MAKEDEFS *****/
 
 #endif /* QTEXT_H */
diff -Naurd ../nethack-3.4.0/include/region.h ./include/region.h
--- ../nethack-3.4.0/include/region.h Wed Mar 20 23:42:54 2002
+++ ./include/region.h Mon Feb 24 15:25:05 2003
@@ -9,6 +9,27 @@
 
 typedef boolean FDECL((*callback_proc), (genericptr_t, genericptr_t));
 
+/*
+ * Overload the old player_inside field with two values, coded in such
+ * a way as to retain compatibility with 3.4.0 save and bones files;
+ * this relies on the fact that nethack's `boolean' is really stored
+ * in a `char' (or bigger type) rather than in a single bit.
+ *
+ * 3.4.1 save and bones files will be correct.
+ * 3.4.0 save files restored under 3.4.1 will be correct.
+ * 3.4.0 bones files used with 3.4.1 will continue to have the minor
+ *	 3.4.0 bug of falsely claiming that the current game's hero is
+ *	 responsible for the dead former hero's stinking clouds.
+ */
+#define REG_HERO_INSIDE	1
+#define REG_NOT_HEROS	2
+#define hero_inside(r)	((unsigned)(r)->player_flags & REG_HERO_INSIDE)
+#define heros_fault(r)	(!((unsigned)(r)->player_flags & REG_NOT_HEROS))
+#define set_hero_inside(r)	((r)->player_flags |= REG_HERO_INSIDE)
+#define clear_hero_inside(r)	((r)->player_flags &= ~REG_HERO_INSIDE)
+#define set_heros_fault(r)	((r)->player_flags &= ~REG_NOT_HEROS)
+#define clear_heros_fault(r)	((r)->player_flags |= REG_NOT_HEROS)
+
 typedef struct {
   NhRect bounding_box;		/* Bounding box of the region */
   NhRect *rects;		/* Rectangles composing the region */
@@ -28,7 +49,7 @@
   short leave_f;		/* Function to call when the player leaves */
   short inside_f;		/* Function to call every turn if player's
 				   inside */
-  boolean player_inside;	/* Is the player inside this region */
+  boolean player_flags;	/* (see above) */
   unsigned int* monsters;	/* Monsters currently inside this region */
   short n_monst;		/* Number of monsters inside this region */
   short max_monst;		/* Maximum number of monsters that can be
diff -Naurd ../nethack-3.4.0/include/rm.h ./include/rm.h
--- ../nethack-3.4.0/include/rm.h Wed Mar 20 23:42:54 2002
+++ ./include/rm.h Mon Feb 24 15:25:05 2003
@@ -267,6 +267,12 @@
  */
 #define F_LOOTED	1
 #define F_WARNED	2
+#define FOUNTAIN_IS_WARNED(x,y)		(levl[x][y].looted & F_WARNED)
+#define FOUNTAIN_IS_LOOTED(x,y)		(levl[x][y].looted & F_LOOTED)
+#define SET_FOUNTAIN_WARNED(x,y)	levl[x][y].looted |= F_WARNED;
+#define SET_FOUNTAIN_LOOTED(x,y)	levl[x][y].looted |= F_LOOTED;
+#define CLEAR_FOUNTAIN_WARNED(x,y)	levl[x][y].looted &= ~F_WARNED;
+#define CLEAR_FOUNTAIN_LOOTED(x,y)	levl[x][y].looted &= ~F_LOOTED;
 
 /*
  * Doors are even worse :-) The special warning has a side effect
diff -Naurd ../nethack-3.4.0/include/wceconf.h ./include/wceconf.h
--- ../nethack-3.4.0/include/wceconf.h Thu Jan 1 01:00:00 1970
+++ ./include/wceconf.h Mon Feb 24 15:25:05 2003
@@ -0,0 +1,319 @@
+/* Copyright (C) 2001 by Alex Kompel <shurikk@pacbell.net> */
+/* Copyright (c) NetHack PC Development Team 1993, 1994.  */
+/* NetHack may be freely redistributed.  See license for details. */
+
+#ifndef WCECONF_H
+#define WCECONF_H
+
+#pragma warning(disable:4142) /* benign redefinition of type */
+
+#define WIN32_LEAN_AND_MEAN		// Exclude rarely-used stuff from Windows headers
+
+#include <windows.h>
+
+/* Detect the targe device */
+#if defined(WIN32_PLATFORM_PSPC) 
+#	if _WIN32_WCE >= 300
+#		define WIN_CE_POCKETPC
+#	else
+#		define WIN_CE_PS2xx
+#	endif
+#elif defined(WIN32_PLATFORM_HPCPRO)
+#	define WIN_CE_HPCPRO
+#elif defined(WIN32_PLATFORM_WFSP)
+#	define WIN_CE_SMARTPHONE
+#else
+#	error "Unsupported Windows CE platform"
+#endif
+
+/* #define SHELL	/* nt use of pcsys routines caused a hang */
+
+#define RANDOM		/* have Berkeley random(3) */
+#define TEXTCOLOR	/* Color text */
+
+#define EXEPATH			/* Allow .exe location to be used as HACKDIR */
+#define TRADITIONAL_GLYPHMAP	/* Store glyph mappings at level change time */
+
+#define PC_LOCKING		/* Prevent overwrites of aborted or in-progress games */
+				/* without first receiving confirmation. */
+
+#define SELF_RECOVER		/* Allow the game itself to recover from an aborted game */
+
+#define NOTSTDC		/* no strerror() */
+
+#define USER_SOUNDS
+
+/*
+ * -----------------------------------------------------------------
+ *  The remaining code shouldn't need modification.
+ * -----------------------------------------------------------------
+ */
+/* #define SHORT_FILENAMES	/* All NT filesystems support long names now */
+
+#ifdef MICRO
+#undef MICRO			/* never define this! */
+#endif
+
+#define NOCWD_ASSUMPTIONS	/* Always define this. There are assumptions that
+                                   it is defined for WIN32.
+				   Allow paths to be specified for HACKDIR,
+				   LEVELDIR, SAVEDIR, BONESDIR, DATADIR,
+				   SCOREDIR, LOCKDIR, CONFIGDIR, and TROUBLEDIR */
+#define NO_TERMS
+#define ASCIIGRAPH
+
+#ifdef OPTIONS_USED
+#undef OPTIONS_USED
+#endif
+#ifdef MSWIN_GRAPHICS
+#define OPTIONS_USED	"guioptions"
+#else
+#define OPTIONS_USED	"ttyoptions"
+#endif
+#define OPTIONS_FILE OPTIONS_USED
+
+#define PORT_HELP	"porthelp"
+
+#if defined(WIN_CE_POCKETPC)
+#	define PORT_CE_PLATFORM "Pocket PC"
+#elif defined(WIN_CE_PS2xx)
+#	define PORT_CE_PLATFORM "Palm-size PC 2.11"
+#elif defined(WIN_CE_HPCPRO)
+#	define PORT_CE_PLATFORM "H/PC Pro 2.11"
+#elif defined(WIN_CE_SMARTPHONE)
+#	define PORT_CE_PLATFORM "Smartphone 2002"
+#endif
+
+#if defined(ARM)
+#	define PORT_CE_CPU "ARM"
+#elif defined(PPC)
+#	define PORT_CE_CPU "PPC"
+#elif defined(ALPHA)
+#	define PORT_CE_CPU "ALPHA"
+#elif defined(SH3)
+#	define PORT_CE_CPU "SH3"
+#elif defined(SH4)
+#	define PORT_CE_CPU "SH4"
+#elif defined(MIPS)
+#	define PORT_CE_CPU "MIPS"
+#elif defined(X86) || defined(_X86_)
+#	define PORT_CE_CPU "X86"
+#else
+#	error Only ARM, PPC, ALPHA, SH3, SH4, MIPS and X86 supported
+#endif
+
+#define RUNTIME_PORT_ID	/* trigger run-time port identification since
+			   Makedefs is bootstrapped on a cross-platform. */
+
+#include <string.h>	/* Provides prototypes of strncmpi(), etc.     */
+#ifdef STRNCMPI
+#define strncmpi(a,b,c) _strnicmp(a,b,c)
+#endif
+
+#ifdef STRCMPI
+#define strcmpi(a,b) _stricmp(a,b)
+#define stricmp(a,b) _stricmp(a,b)
+#endif
+
+#include <stdlib.h>
+
+#define PATHLEN		BUFSZ /* maximum pathlength */
+#define FILENAME	BUFSZ /* maximum filename length (conservative) */
+
+#if defined(_MAX_PATH) && defined(_MAX_FNAME)
+# if (_MAX_PATH < BUFSZ) && (_MAX_FNAME < BUFSZ)
+#undef PATHLEN
+#undef FILENAME
+#define PATHLEN		_MAX_PATH
+#define FILENAME	_MAX_FNAME
+# endif
+#endif
+
+
+#define NO_SIGNAL
+#define index	strchr
+#define rindex	strrchr
+#define USE_STDARG
+#ifdef RANDOM
+/* Use the high quality random number routines. */
+#define Rand()	random()
+#else
+#define Rand()	rand()
+#endif
+
+#define FCMASK	0660	/* file creation mask */
+#define regularize	nt_regularize
+#define HLOCK "NHPERM"
+
+#ifndef M
+#define M(c)		((char) (0x80 | (c)))
+/* #define M(c)		((c) - 128) */
+#endif
+
+#ifndef C
+#define C(c)		(0x1f & (c))
+#endif
+
+#if defined(DLB)
+#define FILENAME_CMP  _stricmp		      /* case insensitive */
+#endif
+
+#if 0
+extern char levels[], bones[], permbones[],
+#endif /* 0 */
+
+/* this was part of the MICRO stuff in the past */
+extern const char *alllevels, *allbones;
+extern char hackdir[];
+#define ABORT C('a')
+#define getuid() 1
+#define getlogin() ((char *)0)
+extern void NDECL(win32_abort);
+#ifdef WIN32CON
+extern void FDECL(nttty_preference_update, (const char *));
+extern void NDECL(toggle_mouse_support);
+#endif
+
+#ifndef alloca
+#define ALLOCA_HACK	/* used in util/panic.c */
+#endif
+
+#ifndef REDO
+#undef	Getchar
+#define Getchar nhgetch
+#endif
+
+#ifdef _MSC_VER
+#if 0
+#pragma warning(disable:4018)	/* signed/unsigned mismatch */
+#pragma warning(disable:4305)	/* init, conv from 'const int' to 'char' */
+#endif
+#pragma warning(disable:4761)	/* integral size mismatch in arg; conv supp*/
+#ifdef YYPREFIX
+#pragma warning(disable:4102)	/* unreferenced label */
+#endif
+#endif
+
+/* UNICODE stuff */
+#define NHSTR_BUFSIZE	255
+#ifdef UNICODE
+	#define NH_W2A(w, a, cb)     ( WideCharToMultiByte(                              \
+												   CP_ACP,                      \
+												   0,                           \
+												   (w),                           \
+												   -1,                          \
+												   (a),                           \
+												   (cb),                          \
+												   NULL,                        \
+												   NULL), (a) )
+
+	#define NH_A2W(a, w, cb)     ( MultiByteToWideChar(                              \
+												   CP_ACP,                      \
+												   0,                           \
+												   (a),                           \
+												   -1,                          \
+												   (w),                           \
+												   (cb)), (w) )
+#else
+	#define NH_W2A(w, a, cb)     (strncpy((a), (w), (cb)))
+
+	#define NH_A2W(a, w, cb)     (strncpy((w), (a), (cb)))
+#endif
+
+extern int FDECL(set_win32_option, (const char *, const char *));
+
+/* Missing definitions */
+extern int		mswin_have_input();
+#define kbhit	mswin_have_input
+
+#define getenv(a) ((char*)NULL)
+
+/* __stdio.h__ */
+#define perror(a)
+#define freopen(a, b, c) fopen(a, b)
+extern int isatty(int);
+
+/* __time.h___ */
+#ifndef _TIME_T_DEFINED
+typedef __int64 time_t;        /* time value */
+#define _TIME_T_DEFINED     /* avoid multiple def's of time_t */
+#endif
+
+#ifndef _TM_DEFINED
+struct tm {
+        int tm_sec;     /* seconds after the minute - [0,59] */
+        int tm_min;     /* minutes after the hour - [0,59] */
+        int tm_hour;    /* hours since midnight - [0,23] */
+        int tm_mday;    /* day of the month - [1,31] */
+        int tm_mon;     /* months since January - [0,11] */
+        int tm_year;    /* years since 1900 */
+        int tm_wday;    /* days since Sunday - [0,6] */
+        int tm_yday;    /* days since January 1 - [0,365] */
+        int tm_isdst;   /* daylight savings time flag - - NOT IMPLEMENTED */
+        };
+#define _TM_DEFINED
+#endif
+
+struct tm * __cdecl localtime(const time_t *);
+time_t __cdecl time(time_t *);
+
+/* __stdio.h__ */
+#ifndef BUFSIZ
+#define BUFSIZ 255
+#endif
+
+#define rewind(stream) (void)fseek( stream, 0L, SEEK_SET )
+
+/* __io.h__ */
+typedef long off_t;
+
+int __cdecl close(int);
+int __cdecl creat(const char *, int);
+int __cdecl eof(int);
+long __cdecl lseek(int, long, int);
+int __cdecl open(const char *, int, ...);
+int __cdecl read(int, void *, unsigned int);
+int __cdecl unlink(const char *);
+int __cdecl write(int, const void *, unsigned int);
+int __cdecl rename(const char *, const char *);
+int __cdecl access(const char *, int);
+
+#ifdef DeleteFile
+#undef DeleteFile
+#endif
+#define DeleteFile(a) unlink(a)
+
+int chdir( const char *dirname );
+char *getcwd( char *buffer, int maxlen );
+
+/* __stdlib.h__ */
+#define abort()  (void)TerminateProcess(GetCurrentProcess(), 0)
+#ifndef strdup
+#define strdup _strdup
+#endif
+
+/* sys/stat.h */
+#define S_IWRITE  GENERIC_WRITE
+#define S_IREAD   GENERIC_READ
+
+
+/* CE 2.xx is missing even more stuff */
+#if defined(WIN_CE_PS2xx) || defined(WIN32_PLATFORM_HPCPRO)
+#define ZeroMemory(p, s)         memset((p), 0, (s))
+
+int __cdecl isupper(int c);
+int __cdecl isdigit(int c);
+int __cdecl isspace(int c);
+int __cdecl isprint(int c);
+
+char* __cdecl _strdup(const char* s);
+char* __cdecl strrchr( const char *string, int c );
+int   __cdecl _stricmp(const char* a, const char* b);
+#endif
+
+/* ARM - the processor; avoids conflict with ARM in hack.h */
+# ifdef ARM
+# undef ARM
+# endif
+
+#endif /* WCECONF_H */
diff -Naurd ../nethack-3.4.0/include/winprocs.h ./include/winprocs.h
--- ../nethack-3.4.0/include/winprocs.h Wed Mar 20 23:42:58 2002
+++ ./include/winprocs.h Mon Feb 24 15:25:05 2003
@@ -157,15 +157,16 @@
 #define WC_FONTSIZ_MENU	 0x100000L	/* 21 supports specification of mnu win font */
 #define WC_FONTSIZ_TEXT	 0x200000L	/* 22 supports specification of txt win font */
 #define WC_SCROLL_MARGIN 0x400000L	/* 23 supports setting scroll margin for map */
-#define WC_SPLASH_SCREEN 0x800000L	/* 24 supports setting scroll margin for map */
+#define WC_SPLASH_SCREEN 0x800000L	/* 24 supports display of splash screen      */
 #define WC_POPUP_DIALOG	 0x1000000L	/* 25 supports queries in pop dialogs        */
-#define WC_LARGE_FONT	 0x2000000L	/* 26 Port supports large font               */
+#define WC_SCROLL_AMOUNT 0x2000000L	/* 26 scroll this amount at scroll margin    */
 #define WC_EIGHT_BIT_IN	 0x4000000L	/* 27 8-bit character input                  */
 #define WC_PERM_INVENT	 0x8000000L	/* 28 8-bit character input                  */
 #define WC_MAP_MODE	 0x10000000L	/* 29 map_mode option                        */
 #define WC_WINDOWCOLORS  0x20000000L	/* 30 background color for message window    */
 #define WC_PLAYER_SELECTION  0x40000000L /* 31 background color for message window    */
-					/* 1 free bit */
+#define WC_MOUSE_SUPPORT 0x80000000L	/* 32 mouse support                          */
+					/* no free bits */
 
 #define ALIGN_LEFT	1
 #define ALIGN_RIGHT	2
@@ -201,7 +202,7 @@
 #endif
 
 struct wc_Opt {
-	char *wc_name;
+	const char *wc_name;
 	unsigned long wc_bit;
 };
 
diff -Naurd ../nethack-3.4.0/src/allmain.c ./src/allmain.c
--- ../nethack-3.4.0/src/allmain.c Wed Mar 20 23:42:59 2002
+++ ./src/allmain.c Mon Feb 24 15:25:05 2003
@@ -100,7 +100,7 @@
 
 		    /* calculate how much time passed. */
 #ifdef STEED
-		    if (u.usteed && flags.mv) {
+		    if (u.usteed && u.umoved) {
 			/* your speed doesn't augment steed's speed */
 			moveamt = mcalcmove(u.usteed);
 		    } else
@@ -221,21 +221,27 @@
 
 		    if(!u.uinvulnerable) {
 			if(Teleportation && !rn2(85)) {
-#ifdef REDO
 			    xchar old_ux = u.ux, old_uy = u.uy;
-#endif
 			    tele();
-#ifdef REDO
 			    if (u.ux != old_ux || u.uy != old_uy) {
+				if (!next_to_u()) {
+				    check_leash(old_ux, old_uy);
+				}
+#ifdef REDO
 				/* clear doagain keystrokes */
 				pushch(0);
 				savech(0);
-			    }
 #endif
+			    }
 			}
+			/* delayed change may not be valid anymore */
+			if ((change == 1 && !Polymorph) ||
+			    (change == 2 && u.ulycn == NON_PM))
+			    change = 0;
 			if(Polymorph && !rn2(100))
 			    change = 1;
-			else if (u.ulycn >= LOW_PM && !rn2(80 - (20 * night())))
+			else if (u.ulycn >= LOW_PM && !Upolyd &&
+				 !rn2(80 - (20 * night())))
 			    change = 2;
 			if (change && !Unchanging) {
 			    if (multi >= 0) {
@@ -278,10 +284,13 @@
 
 		    /* when immobile, count is in turns */
 		    if(multi < 0) {
-			if (++multi == 0)	/* finished yet? */
+			if (++multi == 0) {	/* finished yet? */
 			    unmul((char *)0);
+			    /* if unmul caused a level change, take it now */
+			    if (u.utotype) deferred_goto();
+			}
 		    }
-		}			
+		}
 	    } while (youmonst.movement<NORMAL_SPEED); /* hero can't move loop */
 
 	    /******************************************/
@@ -331,14 +340,14 @@
 #endif
 		occupation = 0;
 	    if(
-#ifdef MICRO
+#if defined(MICRO) || defined(WIN32)
 		   abort_lev ||
 #endif
 		   monster_nearby()) {
 		stop_occupation();
 		reset_eat();
 	    }
-#ifdef MICRO
+#if defined(MICRO) || defined(WIN32)
 	    if (!(++occtime % 7))
 		display_nhwindow(WIN_MAP, FALSE);
 #endif
@@ -403,8 +412,12 @@
 	    flags.botl = 1;
 
 	if (vision_full_recalc) vision_recalc(0);	/* vision! */
-	if (multi && multi%7 == 0)
+	/* when running in non-tport mode, this gets done through domove() */
+	if ((!flags.run || iflags.runmode == RUN_TPORT) &&
+		(multi && (!flags.travel ? !(multi % 7) : !(moves % 7L)))) {
+	    if (flags.time && flags.run) flags.botl = 1;
 	    display_nhwindow(WIN_MAP, FALSE);
+	}
     }
 }
 
diff -Naurd ../nethack-3.4.0/src/apply.c ./src/apply.c
--- ../nethack-3.4.0/src/apply.c Wed Mar 20 23:42:59 2002
+++ ./src/apply.c Mon Feb 24 15:25:05 2003
@@ -34,17 +34,19 @@
 STATIC_PTR int NDECL(set_trap);		/* occupation callback */
 STATIC_DCL int FDECL(use_whip, (struct obj *));
 STATIC_DCL int FDECL(use_pole, (struct obj *));
+STATIC_DCL int FDECL(use_cream_pie, (struct obj *));
 STATIC_DCL int FDECL(use_grapple, (struct obj *));
 STATIC_DCL int FDECL(do_break_wand, (struct obj *));
 STATIC_DCL boolean FDECL(figurine_location_checks,
 				(struct obj *, coord *, BOOLEAN_P));
 STATIC_DCL boolean NDECL(uhave_graystone);
+STATIC_DCL void FDECL(add_class, (char *, CHAR_P));
 
 #ifdef	AMIGA
 void FDECL( amii_speaker, ( struct obj *, char *, int ) );
 #endif
 
-static char no_elbow_room[] = "don't have enough elbow-room to maneuver.";
+static const char no_elbow_room[] = "don't have enough elbow-room to maneuver.";
 
 #ifdef TOURIST
 STATIC_OVL int
@@ -190,7 +192,7 @@
 	return FALSE;
 }
 
-static char hollow_str[] = "a hollow sound.  This must be a secret %s!";
+static const char hollow_str[] = "a hollow sound.  This must be a secret %s!";
 
 /* Strictly speaking it makes no sense for usage of a stethoscope to
    not take any time; however, unless it did, the stethoscope would be
@@ -289,7 +291,7 @@
 	return res;
 }
 
-static char whistle_str[] = "produce a %s whistling sound.";
+static const char whistle_str[] = "produce a %s whistling sound.";
 
 STATIC_OVL void
 use_whistle(obj)
@@ -325,7 +327,7 @@
 			if (mintrap(mtmp) == 2) change_luck(-1);
 		    }
 		}
-		if (pet_cnt > 0) makeknown(MAGIC_WHISTLE);
+		if (pet_cnt > 0) makeknown(obj->otyp);
 	}
 }
 
@@ -398,7 +400,7 @@
 use_leash(obj)
 struct obj *obj;
 {
-	register int x, y;
+	coord cc;
 	register struct monst *mtmp;
 	int spotmon;
 
@@ -407,12 +409,9 @@
 		return;
 	}
 
-	if(!getdir((char *)0)) return;
-
-	x = u.ux + u.dx;
-	y = u.uy + u.dy;
+	if(!get_adjacent_loc((char *)0, (char *)0, u.ux, u.uy, &cc)) return;
 
-	if((x == u.ux) && (y == u.uy)) {
+	if((cc.x == u.ux) && (cc.y == u.uy)) {
 #ifdef STEED
 		if (u.usteed && u.dz > 0) {
 		    mtmp = u.usteed;
@@ -424,7 +423,7 @@
 		return;
 	}
 
-	if(!(mtmp = m_at(x, y))) {
+	if(!(mtmp = m_at(cc.x, cc.y))) {
 		There("is no creature there.");
 		return;
 	}
@@ -528,94 +527,65 @@
 register xchar x, y;
 {
 	register struct obj *otmp;
-	register struct monst *mtmp = fmon;
+	register struct monst *mtmp;
 
-	for(otmp = invent; otmp; otmp = otmp->nobj)
-	    if(otmp->otyp == LEASH && otmp->leashmon != 0) {
-		while(mtmp) {
-		    if(!DEADMONSTER(mtmp) && ((int)mtmp->m_id == otmp->leashmon &&
-			    (dist2(u.ux,u.uy,mtmp->mx,mtmp->my) >
-				dist2(x,y,mtmp->mx,mtmp->my)))
-			) {
-			if(otmp->cursed && !breathless(mtmp->data)) {
-			    if(um_dist(mtmp->mx, mtmp->my, 5)) {
-				pline("%s chokes to death!",Monnam(mtmp));
-				mondied(mtmp);
-			    } else
-				if(um_dist(mtmp->mx, mtmp->my, 3))
-					pline("%s chokes on the leash!",
-						Monnam(mtmp));
-			} else {
-			    if(um_dist(mtmp->mx, mtmp->my, 5)) {
-				pline("%s leash snaps loose!",
-					s_suffix(Monnam(mtmp)));
-				m_unleash(mtmp, FALSE);
-			    } else {
-				if(um_dist(mtmp->mx, mtmp->my, 3)) {
-				    You("pull on the leash.");
-				    if (mtmp->data->msound != MS_SILENT)
-					switch(rn2(3)) {
-					    case 0:  growl(mtmp);	break;
-					    case 1:  yelp(mtmp);	break;
-					    default: whimper(mtmp); break;
-					}
-				}
+	for (otmp = invent; otmp; otmp = otmp->nobj) {
+	    if (otmp->otyp != LEASH || otmp->leashmon == 0) continue;
+	    for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
+		if (DEADMONSTER(mtmp)) continue;
+		if ((int)mtmp->m_id == otmp->leashmon) break; 
+	    }
+	    if (!mtmp) {
+		impossible("leash in use isn't attached to anything?");
+		otmp->leashmon = 0;
+		continue;
+	    }
+	    if (dist2(u.ux,u.uy,mtmp->mx,mtmp->my) >
+		    dist2(x,y,mtmp->mx,mtmp->my)) {
+		if (!um_dist(mtmp->mx, mtmp->my, 3)) {
+		    ;	/* still close enough */
+		} else if (otmp->cursed && !breathless(mtmp->data)) {
+		    if (um_dist(mtmp->mx, mtmp->my, 5) ||
+			    (mtmp->mhp -= rnd(2)) <= 0) {
+			long save_pacifism = u.uconduct.killer;
+
+			Your("leash chokes %s to death!", mon_nam(mtmp));
+			/* hero might not have intended to kill pet, but
+			   that's the result of his actions; gain experience,
+			   lose pacifism, take alignment and luck hit, make
+			   corpse less likely to remain tame after revival */
+			xkilled(mtmp, 0);	/* no "you kill it" message */
+			/* life-saving doesn't ordinarily reset this */
+			if (mtmp->mhp > 0) u.uconduct.killer = save_pacifism;
+		    } else {
+			pline("%s chokes on the leash!", Monnam(mtmp));
+			/* tameness eventually drops to 1 here (never 0) */
+			if (mtmp->mtame && rn2(mtmp->mtame)) mtmp->mtame--;
+		    }
+		} else {
+		    if (um_dist(mtmp->mx, mtmp->my, 5)) {
+			pline("%s leash snaps loose!", s_suffix(Monnam(mtmp)));
+			m_unleash(mtmp, FALSE);
+		    } else {
+			You("pull on the leash.");
+			if (mtmp->data->msound != MS_SILENT)
+			    switch (rn2(3)) {
+			    case 0:  growl(mtmp);   break;
+			    case 1:  yelp(mtmp);    break;
+			    default: whimper(mtmp); break;
 			    }
-			}
 		    }
-		    mtmp = mtmp->nmon;
 		}
 	    }
+	}
 }
 
 #endif /* OVL0 */
 #ifdef OVLB
 
-boolean
-wield_tool(obj)
-struct obj *obj;
-{
-	if(welded(uwep)) {
-		/* Andreas Bormann - ihnp4!decvax!mcvax!unido!ab */
-		if(flags.verbose) {
-			pline("Since your weapon is welded to your %s,",
-				bimanual(uwep) ?
-				(const char *)makeplural(body_part(HAND))
-				: body_part(HAND));
-			pline("you cannot wield that %s.", xname(obj));
-		}
-		return(FALSE);
-	}
-	if (cantwield(youmonst.data)) {
-		You_cant("hold it strongly enough.");
-		return(FALSE);
-	}
-	/* Check shield */
-	if (uarms && bimanual(obj)) {
-		You("cannot wield a two-handed tool while wearing a shield.");
-		return(FALSE);
-	}
-	if(uquiver == obj) setuqwep((struct obj *)0);
-	if(uswapwep == obj) {
-	    (void) doswapweapon();
-	    /* If doswapweapon failed... */
-	    if(uswapwep == obj) return (FALSE);
-	} else {
-	    You("now wield %s.", doname(obj));
-	    setuwep(obj);
-	}
-	if (uwep != obj) return(FALSE); /* rewielded old object after dying */
-	/* applying weapon or tool that gets wielded ends two-weapon combat */
-	if (u.twoweap)
-		untwoweapon();
-	if (obj->oclass != WEAPON_CLASS)
-		unweapon = TRUE;
-	return(TRUE);
-}
-
 #define WEAK	3	/* from eat.c */
 
-static char look_str[] = "look %s.";
+static const char look_str[] = "look %s.";
 
 STATIC_OVL int
 use_mirror(obj)
@@ -875,7 +845,7 @@
 use_candelabrum(obj)
 register struct obj *obj;
 {
-	char *s = obj->spe != 1 ? "candles" : "candle";
+	const char *s = (obj->spe != 1) ? "candles" : "candle";
 
 	if(Underwater) {
 		You("cannot make fire under water.");
@@ -927,7 +897,7 @@
 register struct obj *obj;
 {
 	register struct obj *otmp;
-	char *s = obj->quan != 1 ? "candles" : "candle";
+	const char *s = (obj->quan != 1) ? "candles" : "candle";
 	char qbuf[QBUFSZ];
 
 	if(u.uswallow) {
@@ -971,8 +941,8 @@
 			      (obj->quan > 1L) ? "them" : "it",
 			      (obj->quan > 1L) ? "them" : "it");
 		if (obj->quan < 7L && otmp->spe == 7)
-		    pline("%s now has seven%s %s attached.",
-			  The(xname(otmp)), otmp->lamplit ? " lit" : "", s);
+		    pline("%s now has seven%s candles attached.",
+			  The(xname(otmp)), otmp->lamplit ? " lit" : "");
 		/* candelabrum's light range might increase */
 		if (otmp->lamplit) obj_merge_light_sources(otmp, otmp);
 		/* candles are no longer a separate light source */
@@ -1056,7 +1026,15 @@
 		return FALSE;
 	    if (obj->where == OBJ_MINVENT ? cansee(x,y) : !Blind)
 		pline("%s %s light!", Yname2(obj), otense(obj, "catch"));
-	    begin_burn(obj, TRUE);
+	    if (obj->otyp == POT_OIL) makeknown(obj->otyp);
+	    if (obj->unpaid && costly_spot(u.ux, u.uy) && (obj->where == OBJ_INVENT)) {
+	        /* if it catches while you have it, then it's your tough luck */
+		check_unpaid(obj);
+	        verbalize("That's in addition to the cost of %s %s, of course.",
+				Yname2(obj), obj->quan == 1 ? "itself" : "themselves");
+		bill_dummy_object(obj);
+	    }
+	    begin_burn(obj, FALSE);
 	    return TRUE;
 	}
 	return FALSE;
@@ -1181,7 +1159,7 @@
 	    }
 	}
 
-	if(!obj || (obj != uwep && !wield_tool(obj))) return 0;
+	if (!obj || !wield_tool(obj, "rub")) return 0;
 
 	/* now uwep is obj */
 	if (uwep->otyp == MAGIC_LAMP) {
@@ -1361,7 +1339,7 @@
 	    if (In_sokoban(&u.uz))
 		change_luck(-1);
 
-	    teleds(cc.x, cc.y);
+	    teleds(cc.x, cc.y, TRUE);
 	    nomul(-1);
 	    nomovemsg = "";
 	    morehungry(rnd(25));
@@ -1690,6 +1668,11 @@
 {
 	xchar x,y;
 
+	if (carried(obj) && u.uswallow) {
+		if (!quietly)
+			You("don't have enough room in here.");
+		return FALSE;
+	}
 	x = cc->x; y = cc->y;
 	if (!isok(x,y)) {
 		if (!quietly)
@@ -1719,6 +1702,11 @@
 	xchar x, y;
 	coord cc;
 
+	if (u.uswallow) {
+		/* can't activate a figurine while swallowed */
+		if (!figurine_location_checks(obj, (coord *)0, FALSE))
+			return;
+	}
 	if(!getdir((char *)0)) {
 		flags.move = multi = 0;
 		return;
@@ -1729,12 +1717,13 @@
 	if (!figurine_location_checks(obj, &cc, FALSE)) return;
 	You("%s and it transforms.",
 	    (u.dx||u.dy) ? "set the figurine beside you" :
-	    (Is_airlevel(&u.uz) || Is_waterlevel(&u.uz)) ?
+	    (Is_airlevel(&u.uz) || Is_waterlevel(&u.uz) ||
+	     is_pool(cc.x, cc.y)) ?
 		"release the figurine" :
 	    (u.dz < 0 ?
 		"toss the figurine into the air" :
 		"set the figurine on the ground"));
-	(void) make_familiar(obj, u.ux+u.dx, u.uy+u.dy, FALSE);
+	(void) make_familiar(obj, cc.x, cc.y, FALSE);
 	(void) stop_timer(FIG_TRANSFORM, (genericptr_t)obj);
 	useup(obj);
 }
@@ -1751,9 +1740,9 @@
 	char buf[BUFSZ];
 
 	if (Glib) {
-	    dropx(obj);
 	    pline("%s from your %s.", Tobjnam(obj, "slip"),
 		  makeplural(body_part(FINGER)));
+	    dropx(obj);
 	    return;
 	}
 
@@ -1761,9 +1750,9 @@
 		if ((obj->cursed || Fumbling) && !rn2(2)) {
 			check_unpaid(obj);
 			obj->spe--;
-			dropx(obj);
 			pline("%s from your %s.", Tobjnam(obj, "slip"),
 			      makeplural(body_part(FINGER)));
+			dropx(obj);
 			return;
 		}
 		otmp = getobj(lubricables, "grease");
@@ -1826,19 +1815,26 @@
 {
     struct obj *obj;
     boolean do_scratch;
-    const char *streak_color;
+    const char *streak_color, *choices;
     char stonebuf[QBUFSZ];
     static const char scritch[] = "\"scritch, scritch\"";
-    static char allowall[3] = { GOLD_CLASS, ALL_CLASSES, 0 };
+    static const char allowall[3] = { COIN_CLASS, ALL_CLASSES, 0 };
+    static const char justgems[3] = { ALLOW_NONE, GEM_CLASS, 0 };
 #ifndef GOLDOBJ
     struct obj goldobj;
 #endif
 
+    /* in case it was acquired while blinded */
+    if (!Blind) tstone->dknown = 1;
+    /* when the touchstone is fully known, don't bother listing extra
+       junk as likely candidates for rubbing */
+    choices = (tstone->otyp == TOUCHSTONE && tstone->dknown &&
+		objects[TOUCHSTONE].oc_name_known) ? justgems : allowall;
     Sprintf(stonebuf, "rub on the stone%s", plur(tstone->quan));
-    if ((obj = getobj(allowall, stonebuf)) == 0)
+    if ((obj = getobj(choices, stonebuf)) == 0)
 	return;
 #ifndef GOLDOBJ
-    if (obj->oclass == GOLD_CLASS) {
+    if (obj->oclass == COIN_CLASS) {
 	u.ugold += obj->quan;	/* keep botl up to date */
 	goldobj = *obj;
 	dealloc_obj(obj);
@@ -2066,10 +2062,8 @@
     const char *msg_snap = "Snap!";
 
     if (obj != uwep) {
-	if (!wield_tool(obj)) return 0;
+	if (!wield_tool(obj, "lash")) return 0;
 	else res = 1;
-	/* prevent bashing msg */
-	unweapon = FALSE;
     }
     if (!getdir((char *)0)) return res;
 
@@ -2180,7 +2174,7 @@
 	    if (proficient && rn2(proficient + 2)) {
 		if (!mtmp || enexto(&cc, rx, ry, youmonst.data)) {
 		    You("yank yourself out of the pit!");
-		    teleds(cc.x, cc.y);
+		    teleds(cc.x, cc.y, TRUE);
 		    u.utrap = 0;
 		    vision_full_recalc = 1;
 		}
@@ -2221,7 +2215,7 @@
 	    }
 	    if (gotit) {
 		obj_extract_self(otmp);
-		possibly_unwield(mtmp);
+		possibly_unwield(mtmp, FALSE);
 		setmnotwielded(mtmp,otmp);
 
 		switch (rn2(proficient + 1)) {
@@ -2307,9 +2301,9 @@
 
 
 static const char
-	*not_enough_room = "There's not enough room here to use that.",
-	*where_to_hit = "Where do you want to hit?",
-	*cant_see_spot = "won't hit anything if you can't see that spot.";
+	not_enough_room[] = "There's not enough room here to use that.",
+	where_to_hit[] = "Where do you want to hit?",
+	cant_see_spot[] = "won't hit anything if you can't see that spot.";
 
 /* Distance attacks by pole-weapons */
 STATIC_OVL int
@@ -2327,7 +2321,7 @@
 	    return (0);
 	}
 	if (obj != uwep) {
-	    if (!wield_tool(obj)) return(0);
+	    if (!wield_tool(obj, "swing")) return(0);
 	    else res = 1;
 	}
      /* assert(obj == uwep); */
@@ -2359,6 +2353,8 @@
 	if ((mtmp = m_at(cc.x, cc.y)) != (struct monst *)0) {
 	    int oldhp = mtmp->mhp;
 
+	    bhitpos = cc;
+	    check_caitiff(mtmp);
 	    (void) thitmonst(mtmp, uwep);
 	    /* check the monster's HP because thitmonst() doesn't return
 	     * an indication of whether it hit.  Not perfect (what if it's a
@@ -2372,12 +2368,50 @@
 	return (1);
 }
 
+STATIC_OVL int
+use_cream_pie(obj)
+struct obj *obj;
+{
+	boolean wasblind = Blind;
+	boolean wascreamed = u.ucreamed;
+	boolean several = FALSE;
+
+	if (obj->quan > 1L) {
+		several = TRUE;
+		obj = splitobj(obj, 1L);
+	}
+	if (Hallucination)
+		You("give yourself a facial.");
+	else
+		pline("You immerse your %s in %s%s.", body_part(FACE),
+			several ? "one of " : "",
+			several ? makeplural(the(xname(obj))) : the(xname(obj)));
+	if(can_blnd((struct monst*)0, &youmonst, AT_WEAP, obj)) {
+		int blindinc = rnd(25);
+		u.ucreamed += blindinc;
+		make_blinded(Blinded + (long)blindinc, FALSE);
+		if (!Blind || (Blind && wasblind))
+			pline("There's %ssticky goop all over your %s.",
+				wascreamed ? "more " : "",
+				body_part(FACE));
+		else /* Blind  && !wasblind */
+			You_cant("see through all the sticky goop on your %s.",
+				body_part(FACE));
+	}
+	if (obj->unpaid) {
+		verbalize("You used it, you bought it!");
+		bill_dummy_object(obj);
+	}
+	obj_extract_self(obj);
+	delobj(obj);
+	return(0);
+}
 
 STATIC_OVL int
 use_grapple (obj)
 	struct obj *obj;
 {
-	int res = 0, typ, max_range = 4;
+	int res = 0, typ, max_range = 4, tohit;
 	coord cc;
 	struct monst *mtmp;
 	struct obj *otmp;
@@ -2388,7 +2422,7 @@
 	    return (0);
 	}
 	if (obj != uwep) {
-	    if (!wield_tool(obj)) return(0);
+	    if (!wield_tool(obj, "cast")) return(0);
 	    else res = 1;
 	}
      /* assert(obj == uwep); */
@@ -2406,15 +2440,46 @@
 	else if (P_SKILL(typ) == P_SKILLED) max_range = 5;
 	else max_range = 8;
 	if (distu(cc.x, cc.y) > max_range) {
-		pline("Too far!");
-		return (res);
+	    pline("Too far!");
+	    return (res);
 	} else if (!cansee(cc.x, cc.y)) {
-		You(cant_see_spot);
-		return (res);
+	    You(cant_see_spot);
+	    return (res);
+	}
+
+	/* What do you want to hit? */
+	tohit = rn2(5);
+	if (typ != P_NONE && P_SKILL(typ) >= P_SKILLED) {
+	    winid tmpwin = create_nhwindow(NHW_MENU);
+	    anything any;
+	    char buf[BUFSZ];
+	    menu_item *selected;
+
+	    any.a_void = 0;	/* set all bits to zero */
+	    any.a_int = 1;	/* use index+1 (cant use 0) as identifier */
+	    start_menu(tmpwin);
+	    any.a_int++;
+	    Sprintf(buf, "an object on the %s", surface(cc.x, cc.y));
+	    add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE,
+			 buf, MENU_UNSELECTED);
+	    any.a_int++;
+	    add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE,
+			"a monster", MENU_UNSELECTED);
+	    any.a_int++;
+	    Sprintf(buf, "the %s", surface(cc.x, cc.y));
+	    add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE,
+			 buf, MENU_UNSELECTED);
+	    end_menu(tmpwin, "Aim for what?");
+	    tohit = rn2(4);
+	    if (select_menu(tmpwin, PICK_ONE, &selected) > 0 &&
+			rn2(P_SKILL(typ) > P_SKILLED ? 20 : 2))
+		tohit = selected[0].item.a_int - 1;
+	    free((genericptr_t)selected);
+	    destroy_nhwindow(tmpwin);
 	}
 
 	/* What did you hit? */
-	switch (rn2(5)) {
+	switch (tohit) {
 	case 0:	/* Trap */
 	    /* FIXME -- untrap needs to deal with non-adjacent traps */
 	    break;
@@ -2475,6 +2540,7 @@
     register struct monst *mon;
     int dmg, damage;
     boolean affects_objects;
+    boolean shop_damage = FALSE;
     int expltype = EXPL_MAGICAL;
     char confirm[QBUFSZ], the_wand[BUFSZ], buf[BUFSZ];
 
@@ -2562,10 +2628,17 @@
 	if (!isok(x,y)) continue;
 
 	if (obj->otyp == WAN_DIGGING) {
-	    if(dig_check(BY_OBJECT, FALSE, x, y))
+	    if(dig_check(BY_OBJECT, FALSE, x, y)) {
+		if (IS_WALL(levl[x][y].typ) || IS_DOOR(levl[x][y].typ)) {
+		    /* normally, pits and holes don't anger guards, but they
+		     * do if it's a wall or door that's being dug */
+		    watch_dig((struct monst *)0, x, y, TRUE);
+		    if (*in_rooms(x,y,SHOPBASE)) shop_damage = TRUE;
+		}		    
 		digactualhole(x, y, BY_OBJECT,
 			      (rn2(obj->spe) < 3 || !Can_dig_down(&u.uz)) ?
 			       PIT : HOLE);
+	    }
 	    continue;
 	} else if(obj->otyp == WAN_CREATE_MONSTER) {
 	    /* u.ux,u.uy creates it near you--x,y might create it in rock */
@@ -2598,6 +2671,10 @@
 	}
     }
 
+    /* Note: if player fell thru, this call is a no-op.
+       Damage is handled in digactualhole in that case */
+    if (shop_damage) pay_for_damage("dig into", FALSE);
+
     if (obj->otyp == WAN_LIGHT)
 	litroom(TRUE, obj);	/* only needs to be done once */
 
@@ -2621,17 +2698,40 @@
 	return FALSE;
 }
 
+STATIC_OVL void
+add_class(cl, class)
+char *cl;
+char class;
+{
+	char tmp[2];
+	tmp[0] = class;
+	tmp[1] = '\0';
+	Strcat(cl, tmp);
+}
+
 int
 doapply()
 {
 	register struct obj *obj;
 	register int res = 1;
+	char class_list[MAXOCLASSES+2];
 
 	if(check_capacity((char *)0)) return (0);
-	obj = getobj(carrying(POT_OIL) || uhave_graystone()
-		? tools_too : tools, "use or apply");
+
+	if (carrying(POT_OIL) || uhave_graystone())
+		Strcpy(class_list, tools_too);
+	else
+		Strcpy(class_list, tools);
+	if (carrying(CREAM_PIE) || carrying(EUCALYPTUS_LEAF))
+		add_class(class_list, FOOD_CLASS);
+
+	obj = getobj(class_list, "use or apply");
 	if(!obj) return 0;
 
+	if (obj->oartifact && !touch_artifact(obj, &youmonst))
+	    return 1;	/* evading your grasp costs a turn; just be
+			   grateful that you don't drop it as well */
+
 	if (obj->oclass == WAND_CLASS)
 	    return do_break_wand(obj);
 
@@ -2647,6 +2747,9 @@
 			ublindf->otyp == BLINDFOLD ? "wearing a blindfold" :
 						     "wearing lenses");
 		break;
+	case CREAM_PIE:
+		res = use_cream_pie(obj);
+		break;
 	case BULLWHIP:
 		res = use_whip(obj);
 		break;
@@ -2706,6 +2809,27 @@
 	case TIN_WHISTLE:
 		use_whistle(obj);
 		break;
+	case EUCALYPTUS_LEAF:
+		/* MRKR: Every Australian knows that a gum leaf makes an */
+		/*	 excellent whistle, especially if your pet is a  */
+		/*	 tame kangaroo named Skippy.			 */
+		if (obj->blessed) {
+		    use_magic_whistle(obj);
+		    /* sometimes the blessing will be worn off */
+		    if (!rn2(49)) {
+			if (!Blind) {
+			    char buf[BUFSZ];
+
+			    pline("%s %s %s.", Shk_Your(buf, obj),
+				  aobjnam(obj, "glow"), hcolor("brown"));
+			    obj->bknown = 1;
+			}
+			unbless(obj);
+		    }
+		} else {
+		    use_whistle(obj);
+		}
+		break;
 	case STETHOSCOPE:
 		res = use_stethoscope(obj);
 		break;
@@ -2798,9 +2922,12 @@
 		    otmp->blessed = obj->blessed;
 		    otmp->cursed = obj->cursed;
 		    otmp->owt = weight(otmp);
-		    otmp = hold_another_object(otmp,
-					(u.uswallow || Is_airlevel(&u.uz) ||
-					 u.uinwater || Is_waterlevel(&u.uz)) ?
+		    otmp = hold_another_object(otmp, u.uswallow ?
+				       "Oops!  %s out of your reach!" :
+					(Is_airlevel(&u.uz) ||
+					 Is_waterlevel(&u.uz) ||
+					 levl[u.ux][u.uy].typ < IRONBARS ||
+					 levl[u.ux][u.uy].typ >= ICE) ?
 					       "Oops!  %s away from you!" :
 					       "Oops!  %s to the floor!",
 					       The(aobjnam(otmp, "slip")),
@@ -2824,7 +2951,7 @@
 		if (is_pole(obj)) {
 			res = use_pole(obj);
 			break;
-		} else if (is_pick(obj) /* || is_axe(obj) */) {
+		} else if (is_pick(obj) || is_axe(obj)) {
 			res = use_pick_axe(obj);
 			break;
 		}
@@ -2841,7 +2968,8 @@
 /* Keep track of unfixable troubles for purposes of messages saying you feel
  * great.
  */
-int unfixable_trouble_count(is_horn)
+int
+unfixable_trouble_count(is_horn)
 	boolean is_horn;
 {
 	int unfixable_trbl = 0;
diff -Naurd ../nethack-3.4.0/src/artifact.c ./src/artifact.c
--- ../nethack-3.4.0/src/artifact.c Wed Mar 20 23:43:00 2002
+++ ./src/artifact.c Mon Feb 24 15:25:05 2003
@@ -20,8 +20,11 @@
 
 #define get_artifact(o) \
 		(((o)&&(o)->oartifact) ? &artilist[(int) (o)->oartifact] : 0)
+
 STATIC_DCL int FDECL(spec_applies, (const struct artifact *,struct monst *));
 STATIC_DCL int FDECL(arti_invoke, (struct obj*));
+STATIC_DCL boolean FDECL(Mb_hit, (struct monst *magr,struct monst *mdef,
+				  struct obj *,int *,int,BOOLEAN_P,char *));
 
 /* The amount added to the victim's total hit points to insure that the
    victim will be killed even after damage bonus/penalty adjustments.
@@ -248,6 +251,34 @@
 	return((boolean)(arti && (arti->spfx & abil)));
 }
 
+/* used so that callers don't need to known about SPFX_ codes */
+boolean
+confers_luck(obj)
+struct obj *obj;
+{
+    /* might as well check for this too */
+    if (obj->otyp == LUCKSTONE) return TRUE;
+
+    return (obj->oartifact && spec_ability(obj, SPFX_LUCK));
+}
+
+/* used to check whether a monster is getting reflection from an artifact */
+boolean
+arti_reflects(obj)
+struct obj *obj;
+{
+    const struct artifact *arti = get_artifact(obj);
+
+    if (arti) {      
+	/* while being worn */
+	if ((obj->owornmask & ~W_ART) && (arti->spfx & SPFX_REFLECT))
+	    return TRUE;
+	/* just being carried */
+	if (arti->cspfx & SPFX_REFLECT) return TRUE;
+    }
+    return FALSE;
+}
+
 #endif /* OVL0 */
 #ifdef OVLB
 
@@ -439,6 +470,7 @@
 	    /* this assumes that no one else is using xray_range */
 	    if (on) u.xray_range = 3;
 	    else u.xray_range = -1;
+	    vision_full_recalc = 1;
 	}
 	if ((spfx & SPFX_REFLECT) && (wp_mask & W_WEP)) {
 	    if (on) EReflecting |= wp_mask;
@@ -547,8 +579,9 @@
 	} else if (weap->spfx & SPFX_DFLAG1) {
 	    return ((ptr->mflags1 & weap->mtype) != 0L);
 	} else if (weap->spfx & SPFX_DFLAG2) {
-	    return ((ptr->mflags2 & weap->mtype) ||
-		(yours && !Upolyd && (urace.selfmask & weap->mtype)));
+	    return ((ptr->mflags2 & weap->mtype) || (yours &&
+			((!Upolyd && (urace.selfmask & weap->mtype)) ||
+			 ((weap->mtype & M2_WERE) && u.ulycn >= LOW_PM))));
 	} else if (weap->spfx & SPFX_DALIGN) {
 	    return yours ? (u.ualign.type != weap->alignment) :
 			   (ptr->maligntyp == A_NONE ||
@@ -688,6 +721,205 @@
 
 #ifdef OVLB
 
+
+	/*
+	 * Magicbane's intrinsic magic is incompatible with normal
+	 * enchantment magic.  Thus, its effects have a negative
+	 * dependence on spe.  Against low mr victims, it typically
+	 * does "double athame" damage, 2d4.  Occasionally, it will
+	 * cast unbalancing magic which effectively averages out to
+	 * 4d4 damage (3d4 against high mr victims), for spe = 0.
+	 *
+	 * Prior to 3.4.1, the cancel (aka purge) effect always
+	 * included the scare effect too; now it's one or the other.
+	 * Likewise, the stun effect won't be combined with either
+	 * of those two; it will be chosen separately or possibly
+	 * used as a fallback when scare or cancel fails.
+	 *
+	 * [Historical note: a change to artifact_hit() for 3.4.0
+	 * unintentionally made all of Magicbane's special effects
+	 * be blocked if the defender successfully saved against a
+	 * stun attack.  As of 3.4.1, those effects can occur but
+	 * will be slightly less likely than they were in 3.3.x.]
+	 */
+#define MB_MAX_DIEROLL		8	/* rolls above this aren't magical */
+static const char * const mb_verb[2][4] = {
+	{ "probe", "stun", "scare", "cancel" },
+	{ "prod", "amaze", "tickle", "purge" },
+};
+#define MB_INDEX_PROBE		0
+#define MB_INDEX_STUN		1
+#define MB_INDEX_SCARE		2
+#define MB_INDEX_CANCEL		3
+
+/* called when someone is being hit by Magicbane */
+STATIC_OVL boolean
+Mb_hit(magr, mdef, mb, dmgptr, dieroll, vis, hittee)
+struct monst *magr, *mdef;	/* attacker and defender */
+struct obj *mb;			/* Magicbane */
+int *dmgptr;			/* extra damage target will suffer */
+int dieroll;			/* d20 that has already scored a hit */
+boolean vis;			/* whether the action can be seen */
+char *hittee;			/* target's name: "you" or mon_nam(mdef) */
+{
+    struct permonst *old_uasmon;
+    const char *verb;
+    boolean youattack = (magr == &youmonst),
+	    youdefend = (mdef == &youmonst),
+	    resisted = FALSE, do_stun, do_confuse, result;
+    int attack_indx, scare_dieroll = MB_MAX_DIEROLL / 2;
+
+    result = FALSE;		/* no message given yet */
+    /* the most severe effects are less likely at higher enchantment */
+    if (mb->spe >= 3)
+	scare_dieroll /= (1 << (mb->spe / 3));
+    /* if target successfully resisted the artifact damage bonus,
+       reduce overall likelihood of the assorted special effects */
+    if (!spec_dbon_applies) dieroll += 1;
+
+    /* might stun even when attempting a more severe effect, but
+       in that case it will only happen if the other effect fails;
+       extra damage will apply regardless; 3.4.1: sometimes might
+       just probe even when it hasn't been enchanted */
+    do_stun = (max(mb->spe,0) < rn2(spec_dbon_applies ? 11 : 7));
+
+    /* the special effects also boost physical damage; increments are
+       generally cumulative, but since the stun effect is based on a
+       different criterium its damage might not be included; the base
+       damage is either 1d4 (athame) or 2d4 (athame+spec_dbon) depending
+       on target's resistance check against AD_STUN (handled by caller)
+       [note that a successful save against AD_STUN doesn't actually
+       prevent the target from ending up stunned] */
+    attack_indx = MB_INDEX_PROBE;
+    *dmgptr += rnd(4);			/* (2..3)d4 */
+    if (do_stun) {
+	attack_indx = MB_INDEX_STUN;
+	*dmgptr += rnd(4);		/* (3..4)d4 */
+    }
+    if (dieroll <= scare_dieroll) {
+	attack_indx = MB_INDEX_SCARE;
+	*dmgptr += rnd(4);		/* (3..5)d4 */
+    }
+    if (dieroll <= (scare_dieroll / 2)) {
+	attack_indx = MB_INDEX_CANCEL;
+	*dmgptr += rnd(4);		/* (4..6)d4 */
+    }
+
+    /* give the hit message prior to inflicting the effects */
+    verb = mb_verb[!!Hallucination][attack_indx];
+    if (youattack || youdefend || vis) {
+	result = TRUE;
+	pline_The("magic-absorbing blade %s %s!",
+		  vtense((const char *)0, verb), hittee);
+	/* assume probing has some sort of noticeable feedback
+	   even if it is being done by one monster to another */
+	if (attack_indx == MB_INDEX_PROBE && !canspotmon(mdef))
+	    map_invisible(mdef->mx, mdef->my);
+    }
+
+    /* now perform special effects */
+    switch (attack_indx) {
+    case MB_INDEX_CANCEL:
+	old_uasmon = youmonst.data;
+	if (!cancel_monst(mdef, mb, youattack, FALSE, FALSE)) {
+	    resisted = TRUE;
+	} else {
+	    do_stun = FALSE;
+	    if (youdefend) {
+		if (youmonst.data != old_uasmon)
+		    *dmgptr = 0;    /* rehumanized, so no more damage */
+		if (u.uenmax > 0) {
+		    You("lose magical energy!");
+		    u.uenmax--;
+		    if (u.uen > 0) u.uen--;
+		    flags.botl = 1;
+		}
+	    } else {
+		if (mdef->data == &mons[PM_CLAY_GOLEM])
+		    mdef->mhp = 1;	/* cancelled clay golems will die */
+		if (youattack && attacktype(mdef->data, AT_MAGC)) {
+		    You("absorb magical energy!");
+		    u.uenmax++;
+		    u.uen++;
+		    flags.botl = 1;
+		}
+	    }
+	}
+	break;
+
+    case MB_INDEX_SCARE:
+	if (youdefend) {
+	    if (Antimagic) {
+		resisted = TRUE;
+	    } else {
+		nomul(-3);
+		nomovemsg = "";
+		if (magr && magr == u.ustuck && sticks(youmonst.data)) {
+		    u.ustuck = (struct monst *)0;
+		    You("release %s!", mon_nam(magr));
+		}
+	    }
+	} else {
+	    if (rn2(2) && resist(mdef, WEAPON_CLASS, 0, NOTELL))
+		resisted = TRUE;
+	    else
+		monflee(mdef, 3, FALSE, (mdef->mhp > *dmgptr));
+	}
+	if (!resisted) do_stun = FALSE;
+	break;
+
+    case MB_INDEX_STUN:
+	do_stun = TRUE;		/* (this is redundant...) */
+	break;
+
+    case MB_INDEX_PROBE:
+	if (youattack && (mb->spe == 0 || !rn2(3 * abs(mb->spe)))) {
+	    pline_The("%s is insightful.", verb);
+	    /* pre-damage status */
+	    probe_monster(mdef);
+	}
+	break;
+    }
+    /* stun if that was selected and a worse effect didn't occur */
+    if (do_stun) {
+	if (youdefend)
+	    make_stunned((HStun + 3), FALSE);
+	else
+	    mdef->mstun = 1;
+	/* avoid extra stun message below if we used mb_verb["stun"] above */
+	if (attack_indx == MB_INDEX_STUN) do_stun = FALSE;
+    }
+    /* lastly, all this magic can be confusing... */
+    do_confuse = !rn2(12);
+    if (do_confuse) {
+	if (youdefend)
+	    make_confused(HConfusion + 4, FALSE);
+	else
+	    mdef->mconf = 1;
+    }
+
+    if (youattack || youdefend || vis) {
+	(void) upstart(hittee);	/* capitalize */
+	if (resisted) {
+	    pline("%s %s!", hittee, vtense(hittee, "resist"));
+	    shieldeff(youdefend ? u.ux : mdef->mx,
+		      youdefend ? u.uy : mdef->my);
+	}
+	if ((do_stun || do_confuse) && flags.verbose) {
+	    char buf[BUFSZ];
+
+	    buf[0] = '\0';
+	    if (do_stun) Strcat(buf, "stunned");
+	    if (do_stun && do_confuse) Strcat(buf, " and ");
+	    if (do_confuse) Strcat(buf, "confused");
+	    pline("%s %s %s%c", hittee, vtense(hittee, "are"),
+		  buf, (do_stun && do_confuse) ? '!' : '.');
+	}
+    }
+
+    return result;
+}
+  
 /* Function used when someone attacks someone else with an artifact
  * weapon.  Only adds the special (artifact) damage, and returns a 1 if it
  * did something special (in which case the caller won't print the normal
@@ -725,7 +957,9 @@
 	    return FALSE;
 	}
 
-	realizes_damage = (youdefend || vis);
+	realizes_damage = (youdefend || vis || 
+			   /* feel the effect even if not seen */
+			   (youattack && mdef == u.ustuck));
 
 	/* the four basic attacks: fire, cold, shock and missiles */
 	if (attacks(AD_FIRE, otmp)) {
@@ -750,192 +984,34 @@
 	    return realizes_damage;
 	}
 	if (attacks(AD_ELEC, otmp)) {
-	    if (realizes_damage) {
-		if (youattack ? otmp != uwep : !spec_dbon_applies)
-		    pline("%s %s%c", Tobjnam(otmp, "hit"),
+	    if (realizes_damage)
+		pline_The("massive hammer hits%s %s%c",
+			  !spec_dbon_applies ? "" : "!  Lightning strikes",
 			  hittee, !spec_dbon_applies ? '.' : '!');
-		if (spec_dbon_applies)
-		    pline("Lightning strikes %s!", hittee);
-	    }
 	    if (!rn2(5)) (void) destroy_mitem(mdef, RING_CLASS, AD_ELEC);
 	    if (!rn2(5)) (void) destroy_mitem(mdef, WAND_CLASS, AD_ELEC);
 	    return realizes_damage;
 	}
 	if (attacks(AD_MAGM, otmp)) {
-	    if (realizes_damage) {
-		if (youattack ? otmp != uwep : !spec_dbon_applies)
-		    pline("%s %s%c", Tobjnam(otmp, "hit"),
+	    if (realizes_damage)
+		pline_The("imaginary widget hits%s %s%c",
+			  !spec_dbon_applies ? "" :
+				"!  A hail of magic missiles strikes",
 			  hittee, !spec_dbon_applies ? '.' : '!');
-		if (spec_dbon_applies)
-		    pline("A hail of magic missiles strikes %s!", hittee);
-	    }
 	    return realizes_damage;
 	}
 
+	if (attacks(AD_STUN, otmp) && dieroll <= MB_MAX_DIEROLL) {
+	    /* Magicbane's special attacks (possibly modifies hittee[]) */
+	    return Mb_hit(magr, mdef, otmp, dmgptr, dieroll, vis, hittee);
+	}
+
 	if (!spec_dbon_applies) {
 	    /* since damage bonus didn't apply, nothing more to do;  
 	       no further attacks have side-effects on inventory */
 	    return FALSE;
 	}
 
-	/*
-	 * Magicbane's intrinsic magic is incompatible with normal
-	 * enchantment magic.  Thus, its effects have a negative
-	 * dependence on spe.  Against low mr victims, it typically
-	 * does "double athame" damage, 2d4.  Occasionally, it will
-	 * cast unbalancing magic which effectively averages out to
-	 * 4d4 damage (2.5d4 against high mr victims), for spe = 0.
-	 */
-
-#define MB_MAX_DIEROLL		8    /* rolls above this aren't magical */
-#define MB_INDEX_INIT		(-1)
-#define MB_INDEX_PROBE		0
-#define MB_INDEX_STUN		1
-#define MB_INDEX_SCARE		2
-#define MB_INDEX_PURGE		3
-#define MB_RESIST_ATTACK	(resist_index = attack_index)
-#define MB_RESISTED_ATTACK	(resist_index == attack_index)
-#define MB_UWEP_ATTACK		(youattack && (otmp == uwep))
-
-	if (attacks(AD_STUN, otmp) && (dieroll <= MB_MAX_DIEROLL)) {
-		int attack_index = MB_INDEX_INIT;
-		int resist_index = MB_INDEX_INIT;
-		int scare_dieroll = MB_MAX_DIEROLL / 2;
-
-		if (otmp->spe >= 3)
-			scare_dieroll /= (1 << (otmp->spe / 3));
-
-		*dmgptr += rnd(4);			/* 3d4 */
-
-		if (otmp->spe > rn2(10))		/* probe */
-			attack_index = MB_INDEX_PROBE;
-		else {					/* stun */
-			attack_index = MB_INDEX_STUN;
-			*dmgptr += rnd(4);		/* 4d4 */
-
-			if (youdefend)
-				make_stunned((HStun + 3), FALSE);
-			else
-				mdef->mstun = 1;
-		}
-		if (dieroll <= scare_dieroll) {		/* scare */
-			attack_index = MB_INDEX_SCARE;
-			*dmgptr += rnd(4);		/* 5d4 */
-
-			if (youdefend) {
-				if (Antimagic)
-					MB_RESIST_ATTACK;
-				else {
-					nomul(-3);
-					nomovemsg = "";
-					if (magr && magr == u.ustuck
-						&& sticks(youmonst.data)) {
-					    u.ustuck = (struct monst *)0;
-					    You("release %s!", mon_nam(magr));
-					}
-				}
-			} else if (youattack) {
-				if (rn2(2) && resist(mdef,SPBOOK_CLASS,0,0)) {
-				    MB_RESIST_ATTACK;
-				} else {
-				    monflee(mdef, 3, FALSE, TRUE);
-				}
-			}
-		}
-		if (dieroll <= (scare_dieroll / 2)) {	/* purge */
-			struct obj *ospell;
-			struct permonst *old_uasmon = youmonst.data;
-
-			attack_index = MB_INDEX_PURGE;
-			*dmgptr += rnd(4);		/* 6d4 */
-
-			/* Create a fake spell object, ala spell.c */
-			ospell = mksobj(SPE_CANCELLATION, FALSE, FALSE);
-			ospell->blessed = ospell->cursed = 0;
-			ospell->quan = 20L;
-
-			cancel_monst(mdef, ospell, youattack, FALSE, FALSE);
-
-			if (youdefend) {
-				if (old_uasmon != youmonst.data)
-					/* rehumanized, no more damage */
-					*dmgptr = 0;
-				if (Antimagic)
-					MB_RESIST_ATTACK;
-			} else {
-				if (!mdef->mcan)
-					MB_RESIST_ATTACK;
-
-				/* cancelled clay golems will die ... */
-				else if (mdef->data == &mons[PM_CLAY_GOLEM])
-					mdef->mhp = 1;
-			}
-
-			obfree(ospell, (struct obj *)0);
-		}
-
-		if (youdefend || mdef->mhp > 0) {  /* ??? -dkh- */
-			static const char *mb_verb[4] =
-				{"probe", "stun", "scare", "purge"};
-
-			if (youattack || youdefend || vis) {
-				pline_The("magic-absorbing blade %ss %s!",
-					mb_verb[attack_index], hittee);
-
-				if (MB_RESISTED_ATTACK) {
-					pline("%s resist%s!",
-					youdefend ? "You" : Monnam(mdef),
-					youdefend ? "" : "s");
-
-					shieldeff(youdefend ? u.ux : mdef->mx,
-						youdefend ? u.uy : mdef->my);
-				}
-			}
-
-			/* Much ado about nothing.  More magic fanfare! */
-			if (MB_UWEP_ATTACK) {
-				if (attack_index == MB_INDEX_PURGE) {
-				    if (!MB_RESISTED_ATTACK &&
-					attacktype(mdef->data, AT_MAGC)) {
-					You("absorb magical energy!");
-					u.uenmax++;
-					u.uen++;
-					flags.botl = 1;
-				    }
-				} else if (attack_index == MB_INDEX_PROBE) {
-				    if (!rn2(4 * otmp->spe)) {
-					pline_The("probe is insightful!");
-					if (!canspotmon(mdef))
-					    map_invisible(u.ux+u.dx,u.uy+u.dy);
-					/* pre-damage status */
-					probe_monster(mdef);
-				    }
-				}
-			} else if (youdefend && !MB_RESISTED_ATTACK
-				   && (attack_index == MB_INDEX_PURGE)) {
-				You("lose magical energy!");
-				if (u.uenmax > 0) u.uenmax--;
-				if (u.uen > 0) u.uen--;
-					flags.botl = 1;
-			}
-
-			/* all this magic is confusing ... */
-			if (!rn2(12)) {
-			    if (youdefend)
-				make_confused((HConfusion + 4), FALSE);
-			    else
-				mdef->mconf = 1;
-
-			    if (youattack || youdefend || vis)
-				pline("%s %s confused.",
-				      youdefend ? "You" : Monnam(mdef),
-				      youdefend ? "are" : "is");
-			}
-		}
-		return TRUE;
-	}
-	/* end of Magicbane code */
-
 	/* We really want "on a natural 20" but Nethack does it in */
 	/* reverse from AD&D. */
 	if (spec_ability(otmp, SPFX_BEHEAD)) {
@@ -986,7 +1062,7 @@
 		}
 	    } else if (otmp->oartifact == ART_VORPAL_BLADE &&
 			(dieroll == 1 || mdef->data == &mons[PM_JABBERWOCK])) {
-		static const char *behead_msg[2] = {
+		static const char * const behead_msg[2] = {
 		     "%s beheads %s!",
 		     "%s decapitates %s!"
 		};
@@ -1043,7 +1119,7 @@
 			if (vis) {
 			    if(otmp->oartifact == ART_STORMBRINGER)
 				pline_The("%s blade draws the life from %s!",
-				      hcolor(Black),
+				      hcolor(NH_BLACK),
 				      mon_nam(mdef));
 			    else
 				pline("%s draws the life from %s!",
@@ -1070,7 +1146,7 @@
 				    "unholy blade" : "object");
 			else if (otmp->oartifact == ART_STORMBRINGER)
 				pline_The("%s blade drains your life!",
-				      hcolor(Black));
+				      hcolor(NH_BLACK));
 			else
 				pline("%s drains your life!",
 				      The(distant_name(otmp, xname)));
@@ -1095,7 +1171,8 @@
     register struct obj *obj;
 
     obj = getobj(invoke_types, "invoke");
-    if(!obj) return 0;
+    if (!obj) return 0;
+    if (obj->oartifact && !touch_artifact(obj, &youmonst)) return 1;
     return arti_invoke(obj);
 }
 
@@ -1138,7 +1215,7 @@
 	    long creamed = (long)u.ucreamed;
 
 	    if (Upolyd) healamt = (u.mhmax + 1 - u.mh) / 2;
-	    if (healamt || Sick || Blinded > creamed)
+	    if (healamt || Sick || Slimed || Blinded > creamed)
 		You_feel("better.");
 	    else
 		goto nothing_special;
@@ -1268,13 +1345,16 @@
 	  }
 	}
     } else {
-	long cprop = (u.uprops[oart->inv_prop].extrinsic ^= W_ARTI);
-	boolean on = (cprop & W_ARTI) != 0; /* true if invoked prop just set */
+	long eprop = (u.uprops[oart->inv_prop].extrinsic ^= W_ARTI),
+	     iprop = u.uprops[oart->inv_prop].intrinsic;
+	boolean on = (eprop & W_ARTI) != 0; /* true if invoked prop just set */
 
 	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)));
+	    /* can't just keep repeatedly trying */
+	    obj->age += (long) d(3,10);
 	    return 1;
 	} else if(!on) {
 	    /* when turning off property, determine downtime */
@@ -1282,7 +1362,7 @@
 	    obj->age = monstermoves + rnz(100);
 	}
 
-	if(cprop & ~W_ARTI) {
+	if ((eprop & ~W_ARTI) || iprop) {
 nothing_special:
 	    /* you had the property from some other source too */
 	    if (carried(obj))
@@ -1301,15 +1381,13 @@
 	    } else (void) float_down(I_SPECIAL|TIMEOUT, W_ARTI);
 	    break;
 	case INVIS:
-	    if (!See_invisible && !Blind) {
-		newsym(u.ux,u.uy);
-		if (on) {
-		    Your("body takes on a %s transparency...",
-			 Hallucination ? "normal" : "strange");
-		} else {
-		    Your("body seems to unfade...");
-		}
-	    } else goto nothing_special;
+	    if (BInvis || Blind) goto nothing_special;
+	    newsym(u.ux, u.uy);
+	    if (on)
+		Your("body takes on a %s transparency...",
+		     Hallucination ? "normal" : "strange");
+	    else
+		Your("body seems to unfade...");
 	    break;
 	}
     }
@@ -1327,7 +1405,8 @@
 }
 
 /* KMH -- Talking artifacts are finally implemented */
-void arti_speak(obj)
+void
+arti_speak(obj)
     struct obj *obj;
 {
 	register const struct artifact *oart = get_artifact(obj);
diff -Naurd ../nethack-3.4.0/src/attrib.c ./src/attrib.c
--- ../nethack-3.4.0/src/attrib.c Wed Mar 20 23:43:00 2002
+++ ./src/attrib.c Mon Feb 24 15:25:05 2003
@@ -1,11 +1,10 @@
-/*	SCCS Id: @(#)attrib.c	3.4	2000/05/17	*/
+/*	SCCS Id: @(#)attrib.c	3.4	2002/10/07	*/
 /*	Copyright 1988, 1989, 1990, 1992, M. Stephenson		  */
 /* NetHack may be freely redistributed.  See license for details. */
 
 /*  attribute modification routines. */
 
 #include "hack.h"
-#include "artifact.h"
 
 /* #define DEBUG */	/* uncomment for debugging info */
 
@@ -13,10 +12,10 @@
 
 	/* part of the output on gain or loss of attribute */
 static
-const char	*plusattr[] = {
+const char	* const plusattr[] = {
 	"strong", "smart", "wise", "agile", "tough", "charismatic"
 },
-		*minusattr[] = {
+		* const minusattr[] = {
 	"weak", "stupid", "foolish", "clumsy", "fragile", "repulsive"
 };
 
@@ -99,6 +98,7 @@
 
 static long next_check = 600L;	/* arbitrary first setting */
 STATIC_DCL void NDECL(exerper);
+STATIC_DCL void FDECL(postadjabil, (long *));
 
 /* adjust an attribute; return TRUE if change is made, FALSE otherwise */
 boolean
@@ -211,9 +211,8 @@
 	register struct obj *otmp;
 	register long bonchance = 0;
 
-	for(otmp = invent; otmp; otmp=otmp->nobj)
-	    if (otmp->otyp == LUCKSTONE
-		|| (otmp->oartifact && spec_ability(otmp, SPFX_LUCK))) {
+	for (otmp = invent; otmp; otmp = otmp->nobj)
+	    if (confers_luck(otmp)) {
 		if (otmp->cursed) bonchance -= otmp->quan;
 		else if (otmp->blessed) bonchance += otmp->quan;
 		else if (parameter) bonchance += otmp->quan;
@@ -318,9 +317,15 @@
 		pline("exerper: Hunger checks");
 #endif
 		switch (hs) {
-		    case SATIATED:	exercise(A_DEX, FALSE); break;
+		    case SATIATED:	exercise(A_DEX, FALSE);
+					if (Role_if(PM_MONK))
+					    exercise(A_WIS, FALSE);
+					break;
 		    case NOT_HUNGRY:	exercise(A_CON, TRUE); break;
-		    case WEAK:		exercise(A_STR, FALSE); break;
+		    case WEAK:		exercise(A_STR, FALSE);
+					if (Role_if(PM_MONK))	/* fasting */
+					    exercise(A_WIS, TRUE);
+					break;
 		    case FAINTING:
 		    case FAINTED:	exercise(A_CON, FALSE); break;
 		}
@@ -517,6 +522,16 @@
 	(void)encumber_msg();
 }
 
+STATIC_OVL
+void
+postadjabil(ability)
+long *ability;
+{
+	if (!ability) return;
+	if (ability == &(HWarning) || ability == &(HSee_invisible))
+		see_monsters();
+}
+
 void
 adjabil(oldlevel,newlevel)
 int oldlevel, newlevel;
@@ -554,6 +569,7 @@
 	}
 
 	while (abil || rabil) {
+	    long prevabil;
 	    /* Have we finished with the intrinsics list? */
 	    if (!abil || !abil->ability) {
 	    	/* Try the race intrinsics */
@@ -562,7 +578,7 @@
 	    	rabil = 0;
 	    	mask = FROMRACE;
 	    }
-
+		prevabil = *(abil->ability);
 		if(oldlevel < abil->ulevel && newlevel >= abil->ulevel) {
 			/* Abilities gained at level 1 can never be lost
 			 * via level loss, only via means that remove _any_
@@ -587,6 +603,8 @@
 				You_feel("less %s!", abil->gainstr);
 			}
 		}
+	    if (prevabil != *(abil->ability))	/* it changed */
+		postadjabil(abil->ability);
 	    abil++;
 	}
 
diff -Naurd ../nethack-3.4.0/src/ball.c ./src/ball.c
--- ../nethack-3.4.0/src/ball.c Wed Mar 20 23:43:00 2002
+++ ./src/ball.c Mon Feb 24 15:25:05 2003
@@ -38,7 +38,7 @@
 		    } else if (flags.verbose)
 			Your("%s does not protect you.", xname(uarmh));
 		}
-		losehp(dmg, "Crunched in the head by an iron ball",
+		losehp(dmg, "crunched in the head by an iron ball",
 			NO_KILLER_PREFIX);
 	}
 }
@@ -343,19 +343,30 @@
     }
 }
 
-/* return TRUE if ball could be dragged
+/* return TRUE if the caller needs to place the ball and chain down again
  *
  *  Should not be called while swallowed.  Should be called before movement,
  *  because we might want to move the ball or chain to the hero's old position.
+ *
+ * It is called if we are moving.  It is also called if we are teleporting
+ * *if* the ball doesn't move and we thus must drag the chain.  It is not
+ * called for ordinary teleportation.
+ *
+ * allow_drag is only used in the ugly special case where teleporting must
+ * drag the chain, while an identical-looking movement must drag both the ball
+ * and chain.
  */
 boolean
-drag_ball(x, y, bc_control, ballx, bally, chainx, chainy, cause_delay)
+drag_ball(x, y, bc_control, ballx, bally, chainx, chainy, cause_delay,
+    allow_drag)
 xchar x, y;
 int *bc_control;
 xchar *ballx, *bally, *chainx, *chainy;
 boolean *cause_delay;
+boolean allow_drag;
 {
 	struct trap *t = (struct trap *)0;
+	boolean already_in_rock;
 
 	*ballx  = uball->ox;
 	*bally  = uball->oy;
@@ -371,10 +382,11 @@
 
 	/* only need to move the chain? */
 	if (carried(uball) || distmin(x, y, uball->ox, uball->oy) <= 2) {
+	    xchar oldchainx = uchain->ox, oldchainy = uchain->oy;
 	    *bc_control = BC_CHAIN;
 	    move_bc(1, *bc_control, *ballx, *bally, *chainx, *chainy);
 	    if (carried(uball)) {
-		/* move chain only if necessary; assume they didn't teleport */
+		/* move chain only if necessary */
 		if (distmin(x, y, uchain->ox, uchain->oy) > 1) {
 		    *chainx = u.ux;
 		    *chainy = u.uy;
@@ -383,11 +395,31 @@
 	    }
 #define CHAIN_IN_MIDDLE(chx, chy) \
 (distmin(x, y, chx, chy) <= 1 && distmin(chx, chy, uball->ox, uball->oy) <= 1)
+#define IS_CHAIN_ROCK(x,y) \
+(IS_ROCK(levl[x][y].typ) || (IS_DOOR(levl[x][y].typ) && \
+      (levl[x][y].doormask & (D_CLOSED|D_LOCKED))))
+/* Don't ever move the chain into solid rock.  If we have to, then instead
+ * undo the move_bc() and jump to the drag ball code.  Note that this also
+ * means the "cannot carry and drag" message will not appear, since unless we
+ * moved at least two squares there is no possibility of the chain position
+ * being in solid rock.
+ */
+#define SKIP_TO_DRAG { *chainx = oldchainx; *chainy = oldchainy; \
+    move_bc(0, *bc_control, *ballx, *bally, *chainx, *chainy); \
+    goto drag; } 
+	    if (IS_CHAIN_ROCK(u.ux, u.uy) || IS_CHAIN_ROCK(*chainx, *chainy)
+			|| IS_CHAIN_ROCK(uball->ox, uball->oy))
+		already_in_rock = TRUE;
+	    else
+		already_in_rock = FALSE;
+
 	    switch(dist2(x, y, uball->ox, uball->oy)) {
 		/* two spaces diagonal from ball, move chain inbetween */
 		case 8:
 		    *chainx = (uball->ox + x)/2;
 		    *chainy = (uball->oy + y)/2;
+		    if (IS_CHAIN_ROCK(*chainx, *chainy) && !already_in_rock)
+			SKIP_TO_DRAG;
 		    break;
 
 		/* player is distance 2/1 from ball; move chain to one of the
@@ -410,7 +442,47 @@
 			tempy = y;
 			tempy2 = uball->oy;
 		    }
-		    if (dist2(tempx, tempy, uchain->ox, uchain->oy) <
+		    if (IS_CHAIN_ROCK(tempx, tempy) &&
+				!IS_CHAIN_ROCK(tempx2, tempy2) &&
+				!already_in_rock) {
+			if (allow_drag) {
+			    /* Avoid pathological case *if* not teleporting:
+			     *   0			    0_
+			     *   _X  move northeast  ----->  X@
+			     *    @
+			     */
+			    if (dist2(u.ux, u.uy, uball->ox, uball->oy) == 5 &&
+				  dist2(x, y, tempx, tempy) == 1)
+				SKIP_TO_DRAG;
+			    /* Avoid pathological case *if* not teleporting:
+			     *    0			     0
+			     *   _X  move east       ----->  X_
+			     *    @			      @
+			     */
+			    if (dist2(u.ux, u.uy, uball->ox, uball->oy) == 4 &&
+				  dist2(x, y, tempx, tempy) == 2)
+				SKIP_TO_DRAG;
+			}
+			*chainx = tempx2;
+			*chainy = tempy2;
+		    } else if (!IS_CHAIN_ROCK(tempx, tempy) &&
+				IS_CHAIN_ROCK(tempx2, tempy2) &&
+				!already_in_rock) {
+			if (allow_drag) {
+			    if (dist2(u.ux, u.uy, uball->ox, uball->oy) == 5 &&
+				    dist2(x, y, tempx2, tempy2) == 1)
+				SKIP_TO_DRAG;
+			    if (dist2(u.ux, u.uy, uball->ox, uball->oy) == 4 &&
+				  dist2(x, y, tempx2, tempy2) == 2)
+				SKIP_TO_DRAG;
+			}
+			*chainx = tempx;
+			*chainy = tempy;
+		    } else if (IS_CHAIN_ROCK(tempx, tempy) &&
+				IS_CHAIN_ROCK(tempx2, tempy2) &&
+				!already_in_rock) {
+			SKIP_TO_DRAG;
+		    } else if (dist2(tempx, tempy, uchain->ox, uchain->oy) <
 			 dist2(tempx2, tempy2, uchain->ox, uchain->oy) ||
 		       ((dist2(tempx, tempy, uchain->ox, uchain->oy) ==
 			 dist2(tempx2, tempy2, uchain->ox, uchain->oy)) && rn2(2))) {
@@ -428,8 +500,10 @@
 		case 4:
 		    if (CHAIN_IN_MIDDLE(uchain->ox, uchain->oy))
 			break;
-		    *chainx = (x + uchain->ox)/2;
-		    *chainy = (y + uchain->oy)/2;
+		    *chainx = (x + uball->ox)/2;
+		    *chainy = (y + uball->oy)/2;
+		    if (IS_CHAIN_ROCK(*chainx, *chainy) && !already_in_rock)
+			SKIP_TO_DRAG;
 		    break;
 		
 		/* ball is one space diagonal from player.  Check for the
@@ -447,6 +521,8 @@
 			    *chainx = uball->ox;
 			else
 			    *chainy = uball->oy;
+			if (IS_CHAIN_ROCK(*chainx, *chainy) && !already_in_rock)
+			    SKIP_TO_DRAG;
 			break;
 		    }
 		    /* fall through */
@@ -470,11 +546,15 @@
 		default: impossible("bad chain movement");
 		    break;
 	    }
+#undef SKIP_TO_DRAG
+#undef IS_CHAIN_ROCK
 #undef CHAIN_IN_MIDDLE
 	    return TRUE;
 	}
 
-	if (near_capacity() > SLT_ENCUMBER) {
+drag:
+
+	if (near_capacity() > SLT_ENCUMBER && dist2(x, y, u.ux, u.uy) <= 2) {
 	    You("cannot %sdrag the heavy iron ball.",
 			    invent ? "carry all that and also " : "");
 	    nomul(0);
@@ -527,13 +607,25 @@
 	    }
 	}
 
-	*bc_control = BC_BALL|BC_CHAIN;;
+	*bc_control = BC_BALL|BC_CHAIN;
 
 	move_bc(1, *bc_control, *ballx, *bally, *chainx, *chainy);
-	*ballx  = uchain->ox;
-	*bally  = uchain->oy;
-	*chainx = u.ux;
-	*chainy = u.uy;
+	if (dist2(x, y, u.ux, u.uy) > 2) {
+	    /* Awful case: we're still in range of the ball, so we thought we
+	     * could only move the chain, but it turned out that the target
+	     * square for the chain was rock, so we had to drag it instead.
+	     * But we can't drag it either, because we teleported and are more
+	     * than one square from our old position.  Revert to the teleport
+	     * behavior.
+	     */
+	    *ballx = *chainx = x;
+	    *bally = *chainy = y;
+	} else {
+	    *ballx  = uchain->ox;
+	    *bally  = uchain->oy;
+	    *chainx = u.ux;
+	    *chainy = u.uy;
+	}
 	*cause_delay = TRUE;
 	return TRUE;
 }
diff -Naurd ../nethack-3.4.0/src/bones.c ./src/bones.c
--- ../nethack-3.4.0/src/bones.c Wed Mar 20 23:43:00 2002
+++ ./src/bones.c Mon Feb 24 15:25:05 2003
@@ -165,6 +165,9 @@
 	    return FALSE;
 	if (no_bones_level(&u.uz))
 	    return FALSE;		/* no bones for specific levels */
+	if (u.uswallow) {
+	    return FALSE;		/* no bones when swallowed */
+	}
 	if (!Is_branchlev(&u.uz)) {
 	    /* no bones on non-branches with portals */
 	    for(ttmp = ftrap; ttmp; ttmp = ttmp->ntrap)
@@ -194,9 +197,11 @@
 	struct permonst *mptr;
 	struct fruit *f;
 	char c, *bonesid;
+	char whynot[BUFSZ];
 
 	/* caller has already checked `can_make_bones()' */
 
+	clear_bypasses();
 	fd = open_bonesfile(&u.uz, &bonesid);
 	if (fd >= 0) {
 		(void) close(fd);
@@ -308,12 +313,16 @@
 	    levl[x][y].glyph = cmap_to_glyph(S_stone);
 	}
 
-	fd = create_bonesfile(&u.uz, &bonesid);
+	fd = create_bonesfile(&u.uz, &bonesid, whynot);
 	if(fd < 0) {
 #ifdef WIZARD
 		if(wizard)
-			pline("Cannot create bones file - create failed");
+			pline("%s", whynot);
 #endif
+		/* bones file creation problems are silent to the player.
+		 * Keep it that way, but place a clue into the paniclog.
+		 */
+		paniclog("savebones", whynot);
 		return;
 	}
 	c = (char) (strlen(bonesid) + 1);
@@ -397,15 +406,18 @@
 #endif
 		mread(fd, (genericptr_t) &c, sizeof c);	/* length incl. '\0' */
 		mread(fd, (genericptr_t) oldbonesid, (unsigned) c); /* DD.nnn */
-		if (strcmp(bonesid, oldbonesid)) {
+		if (strcmp(bonesid, oldbonesid) != 0) {
+			char errbuf[BUFSZ];
+
+			Sprintf(errbuf, "This is bones level '%s', not '%s'!",
+				oldbonesid, bonesid);
 #ifdef WIZARD
 			if (wizard) {
-				pline("This is bones level '%s', not '%s'!",
-					oldbonesid, bonesid);
+				pline("%s", errbuf);
 				ok = FALSE;	/* won't die of trickery */
 			}
 #endif
-			trickery();
+			trickery(errbuf);
 		} else {
 			register struct monst *mtmp;
 			int mndx;
diff -Naurd ../nethack-3.4.0/src/botl.c ./src/botl.c
--- ../nethack-3.4.0/src/botl.c Wed Mar 20 23:43:01 2002
+++ ./src/botl.c Mon Feb 24 15:25:05 2003
@@ -7,7 +7,7 @@
 #ifdef OVL0
 extern const char *hu_stat[];	/* defined in eat.c */
 
-const char *enc_stat[] = {
+const char * const enc_stat[] = {
 	"",
 	"Burdened",
 	"Stressed",
@@ -45,7 +45,8 @@
 #ifdef OVL1
 
 /* convert experience level (1..30) to rank index (0..8) */
-int xlev_to_rank(xlev)
+int
+xlev_to_rank(xlev)
 int xlev;
 {
 	return (xlev <= 2) ? 0 : (xlev <= 30) ? ((xlev + 2) / 4) : 8;
@@ -53,7 +54,8 @@
 
 #if 0	/* not currently needed */
 /* convert rank index (0..8) to experience level (1..30) */
-int rank_to_xlev(rank)
+int
+rank_to_xlev(rank)
 int rank;
 {
 	return (rank <= 0) ? 1 : (rank <= 8) ? ((rank * 4) - 2) : 30;
@@ -254,7 +256,7 @@
 	if(hp < 0) hp = 0;
 	(void) describe_level(newbot2);
 	Sprintf(nb = eos(newbot2),
-		"%c:%-2ld HP:%d(%d) Pw:%d(%d) AC:%-2d", oc_syms[GOLD_CLASS],
+		"%c:%-2ld HP:%d(%d) Pw:%d(%d) AC:%-2d", oc_syms[COIN_CLASS],
 #ifndef GOLDOBJ
 		u.ugold,
 #else
diff -Naurd ../nethack-3.4.0/src/cmd.c ./src/cmd.c
--- ../nethack-3.4.0/src/cmd.c Wed Mar 20 23:43:01 2002
+++ ./src/cmd.c Mon Feb 24 15:25:05 2003
@@ -22,7 +22,7 @@
  * module you are trying to debug) or things are going to get rather
  * hard to link :-)
  */
-extern void NDECL(wiz_debug_cmd);
+extern int NDECL(wiz_debug_cmd);
 #endif
 
 #ifdef DUMB	/* stuff commented out in extern.h, but needed here */
@@ -115,6 +115,7 @@
 STATIC_PTR int NDECL(wiz_genesis);
 STATIC_PTR int NDECL(wiz_where);
 STATIC_PTR int NDECL(wiz_detect);
+STATIC_PTR int NDECL(wiz_panic);
 STATIC_PTR int NDECL(wiz_polyself);
 STATIC_PTR int NDECL(wiz_level_tele);
 STATIC_PTR int NDECL(wiz_level_change);
@@ -131,14 +132,18 @@
 STATIC_DCL void FDECL(mon_chain, (winid, const char *, struct monst *, long *, long *));
 STATIC_DCL void FDECL(contained, (winid, const char *, long *, long *));
 STATIC_PTR int NDECL(wiz_show_stats);
+#  ifdef PORT_DEBUG
+STATIC_DCL int NDECL(wiz_port_debug);
+#  endif
 # endif
 STATIC_PTR int NDECL(enter_explore_mode);
 STATIC_PTR int NDECL(doattributes);
 STATIC_PTR int NDECL(doconduct); /**/
-STATIC_PTR void NDECL(minimal_enlightenment);
+STATIC_PTR boolean NDECL(minimal_enlightenment);
 
 #ifdef OVLB
 STATIC_DCL void FDECL(enlght_line, (const char *,const char *,const char *));
+STATIC_DCL char *FDECL(enlght_combatinc, (const char *,int,int,char *));
 #ifdef UNIX
 static void NDECL(end_of_input);
 #endif
@@ -147,6 +152,7 @@
 static const char* readchar_queue="";
 
 STATIC_DCL char *NDECL(parse);
+STATIC_DCL boolean FDECL(help_dir, (CHAR_P,const char *));
 
 #ifdef OVL1
 
@@ -435,6 +441,7 @@
 }
 #endif
 
+/* #monster command - use special monster ability while polymorphed */
 STATIC_PTR int
 domonability()
 {
@@ -484,6 +491,8 @@
 }
 
 #ifdef WIZARD
+
+/* ^W command - wish for something */
 STATIC_PTR int
 wiz_wish()	/* Unlimited wishes for debug mode by Paul Polderman */
 {
@@ -499,6 +508,7 @@
 	return 0;
 }
 
+/* ^I command - identify hero's inventory */
 STATIC_PTR int
 wiz_identify()
 {
@@ -507,23 +517,29 @@
 	return 0;
 }
 
-/* reveal the level map and any traps on it */
+/* ^F command - reveal the level map and any traps on it */
 STATIC_PTR int
 wiz_map()
 {
 	if (wizard) {
 	    struct trap *t;
+	    long save_Hconf = HConfusion,
+		 save_Hhallu = HHallucination;
 
+	    HConfusion = HHallucination = 0L;
 	    for (t = ftrap; t != 0; t = t->ntrap) {
 		t->tseen = 1;
 		map_trap(t, TRUE);
 	    }
 	    do_mapping();
+	    HConfusion = save_Hconf;
+	    HHallucination = save_Hhallu;
 	} else
 	    pline("Unavailable command '^F'.");
 	return 0;
 }
 
+/* ^G command - generate monster(s); a count prefix will be honored */
 STATIC_PTR int
 wiz_genesis()
 {
@@ -532,6 +548,7 @@
 	return 0;
 }
 
+/* ^O command - display dungeon layout */
 STATIC_PTR int
 wiz_where()
 {
@@ -540,6 +557,7 @@
 	return 0;
 }
 
+/* ^E command - detect unseen (secret doors, traps, hidden monsters) */
 STATIC_PTR int
 wiz_detect()
 {
@@ -548,6 +566,7 @@
 	return 0;
 }
 
+/* ^V command - level teleport */
 STATIC_PTR int
 wiz_level_tele()
 {
@@ -556,6 +575,7 @@
 	return 0;
 }
 
+/* #monpolycontrol command - choose new form for shapechangers, polymorphees */
 STATIC_PTR int
 wiz_mon_polycontrol()
 {
@@ -565,6 +585,7 @@
     return 0;
 }
 
+/* #levelchange command - adjust hero's experience level */
 STATIC_PTR int
 wiz_level_change()
 {
@@ -590,7 +611,7 @@
 	}
 	if (newlevel < 1) newlevel = 1;
 	while (u.ulevel > newlevel)
-	    losexp((const char *)0);
+	    losexp("#levelchange");
     } else {
 	if (u.ulevel >= MAXULEV) {
 	    You("are already as experienced as you can get.");
@@ -604,6 +625,16 @@
     return 0;
 }
 
+/* #panic command - test program's panic handling */
+STATIC_PTR int
+wiz_panic()
+{
+	if (yn("Do you want to call panic() and end your game?") == 'y')
+		panic("crash test.");
+        return 0;
+}
+
+/* #polyself command - change hero's form */
 STATIC_PTR int
 wiz_polyself()
 {
@@ -611,6 +642,7 @@
         return 0;
 }
 
+/* #seenv command */
 STATIC_PTR int
 wiz_show_seenv()
 {
@@ -652,6 +684,7 @@
 	return 0;
 }
 
+/* #vision command */
 STATIC_PTR int
 wiz_show_vision()
 {
@@ -688,6 +721,7 @@
 	return 0;
 }
 
+/* #wmode command */
 STATIC_PTR int
 wiz_show_wmodes()
 {
@@ -725,13 +759,13 @@
 /* -enlightenment and conduct- */
 static winid en_win;
 static const char
-	*You_ = "You ",
-	*are  = "are ",  *were  = "were ",
-	*have = "have ", *had   = "had ",
-	*can  = "can ",  *could = "could ";
+	You_[] = "You ",
+	are[]  = "are ",  were[]  = "were ",
+	have[] = "have ", had[]   = "had ",
+	can[]  = "can ",  could[] = "could ";
 static const char
-	*have_been  = "have been ",
-	*have_never = "have never ", *never = "never ";
+	have_been[]  = "have been ",
+	have_never[] = "have never ", never[] = "never ";
 
 #define enl_msg(prefix,present,past,suffix) \
 			enlght_line(prefix, final ? past : present, suffix)
@@ -752,6 +786,43 @@
 	putstr(en_win, 0, buf);
 }
 
+/* format increased damage or chance to hit */
+static char *
+enlght_combatinc(inctyp, incamt, final, outbuf)
+const char *inctyp;
+int incamt, final;
+char *outbuf;
+{
+	char numbuf[24];
+	const char *modif, *bonus;
+
+	if (final
+#ifdef WIZARD
+		|| wizard
+#endif
+	  ) {
+	    Sprintf(numbuf, "%s%d",
+		    (incamt > 0) ? "+" : "", incamt);
+	    modif = (const char *) numbuf;
+	} else {
+	    int absamt = abs(incamt);
+
+	    if (absamt <= 3) modif = "small";
+	    else if (absamt <= 6) modif = "moderate";
+	    else if (absamt <= 12) modif = "large";
+	    else modif = "huge";
+	}
+	bonus = (incamt > 0) ? "bonus" : "penalty";
+	/* "bonus to hit" vs "damage bonus" */
+	if (!strcmp(inctyp, "damage")) {
+	    const char *ctmp = inctyp;
+	    inctyp = bonus;
+	    bonus = ctmp;
+	}
+	Sprintf(outbuf, "%s %s %s", an(modif), bonus, inctyp);
+	return outbuf;
+}
+
 void
 enlightenment(final)
 int final;	/* 0 => still in progress; 1 => over, survived; 2 => dead */
@@ -765,7 +836,7 @@
 
 #ifdef ELBERETH
 	if (u.uevent.uhand_of_elbereth) {
-	    static const char *hofe_titles[3] = {
+	    static const char * const hofe_titles[3] = {
 				"the Hand of Elbereth",
 				"the Envoy of Balance",
 				"the Glory of Arioch"
@@ -822,18 +893,6 @@
 			if (u.usick_type & SICK_NONVOMITABLE)
 				you_are("sick from illness");
 		}
-		/* added by JDS */
-		if (u.uhitinc) {
-			Sprintf(buf, "%s%i %s to hit", u.uhitinc > 0 ? "+" : "",
-				u.uhitinc, u.uhitinc > 0 ? "bonus" : "penalty");
-			you_have(buf);
-			
-		}
-		if (u.udaminc) {
-			Sprintf(buf, "%s%i %s to damage", u.udaminc > 0 ? "+" : "",
-				u.udaminc, u.udaminc > 0 ? "bonus" : "penalty");
-			you_have(buf);
-		} /* end JDS portion */
 	}
 	if (Stoned) you_are("turning to stone");
 	if (Slimed) you_are("turning into slime");
@@ -881,7 +940,16 @@
 	if (u.umconf) you_are("going to confuse monsters");
 
 	/*** Appearance and behavior ***/
-	if (Adornment) you_are("adorned");
+	if (Adornment) {
+	    int adorn = 0;
+
+	    if(uleft && uleft->otyp == RIN_ADORNMENT) adorn += uleft->spe;
+	    if(uright && uright->otyp == RIN_ADORNMENT) adorn += uright->spe;
+	    if (adorn < 0)
+		you_are("poorly adorned");
+	    else
+		you_are("adorned");
+	}
 	if (Invisible) you_are("invisible");
 	else if (Invis) you_are("invisible to others");
 	/* ordinarily "visible" is redundant; this is a special case for
@@ -906,7 +974,10 @@
 	else if (Amphibious) you_can("breathe water");
 	if (Passes_walls) you_can("walk through walls");
 #ifdef STEED
-	if (u.usteed) {
+	/* If you die while dismounting, u.usteed is still set.  Since several
+	 * places in the done() sequence depend on u.usteed, just detect this
+	 * special case. */
+	if (u.usteed && (final < 2 || strcmp(killer, "riding accident"))) {
 	    Sprintf(buf, "riding %s", y_monnam(u.usteed));
 	    you_are(buf);
 	}
@@ -925,9 +996,25 @@
 	}
 
 	/*** Physical attributes ***/
+	if (u.uhitinc)
+	    you_have(enlght_combatinc("to hit", u.uhitinc, final, buf));
+	if (u.udaminc)
+	    you_have(enlght_combatinc("damage", u.udaminc, final, buf));
 	if (Slow_digestion) you_have("slower digestion");
 	if (Regeneration) enl_msg("You regenerate", "", "d", "");
-	if (u.uspellprot || Protection) you_are("protected");
+	if (u.uspellprot || Protection) {
+	    int prot = 0;
+
+	    if(uleft && uleft->otyp == RIN_PROTECTION) prot += uleft->spe;
+	    if(uright && uright->otyp == RIN_PROTECTION) prot += uright->spe;
+	    if (HProtection & INTRINSIC) prot += u.ublessed;
+	    prot += u.uspellprot;
+
+	    if (prot < 0)
+		you_are("ineffectively protected");
+	    else
+		you_are("protected");
+	}
 	if (Protection_from_shape_changers)
 		you_are("protected from shape changers");
 	if (Polymorph) you_are("polymorphing");
@@ -937,7 +1024,7 @@
 		you_are(buf);
 	}
 	if (Upolyd) {
-	    if (u.ulycn >= LOW_PM) Strcpy(buf, "in beast form");
+	    if (u.umonnum == u.ulycn) Strcpy(buf, "in beast form");
 	    else Sprintf(buf, "polymorphed into %s", an(youmonst.data->mname));
 #ifdef WIZARD
 	    if (wizard) Sprintf(eos(buf), " (%d)", u.mtimedone);
@@ -1039,16 +1126,18 @@
 /*
  * Courtesy function for non-debug, non-explorer mode players
  * to help refresh them about who/what they are.
+ * Returns FALSE if menu cancelled (dismissed with ESC), TRUE otherwise.
  */
-STATIC_OVL void
+STATIC_OVL boolean
 minimal_enlightenment()
 {
 	winid tmpwin;
 	menu_item *selected;
 	anything any;
+	int genidx, n;
 	char buf[BUFSZ], buf2[BUFSZ];
-	static char fmtstr[] = "%-15s: %-12s";
-	static char deity_fmtstr[] = "%-17s%s";
+	static const char fmtstr[] = "%-15s: %-12s";
+	static const char deity_fmtstr[] = "%-17s%s";
 
 	any.a_void = 0;
 	buf[0] = buf2[0] = '\0';
@@ -1085,10 +1174,11 @@
 		(flags.female && urole.name.f) ? urole.name.f : urole.name.m);
 	    add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, buf, FALSE);
 	}
-	Sprintf(buf, fmtstr, "gender", genders[poly_gender()].adj);
+	/* don't want poly_gender() here; it forces `2' for non-humanoids */
+	genidx = is_neuter(youmonst.data) ? 2 : flags.female;
+	Sprintf(buf, fmtstr, "gender", genders[genidx].adj);
 	add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, buf, FALSE);
-
-	if (Upolyd) {
+	if (Upolyd && (int)u.mfemale != genidx) {
 	    Sprintf(buf, fmtstr, "gender (base)", genders[u.mfemale].adj);
 	    add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, buf, FALSE);
 	}
@@ -1105,7 +1195,7 @@
 		&& u.ualign.type == A_CHAOTIC) ? " (s,c)" :
 	    (u.ualignbase[A_ORIGINAL] == A_CHAOTIC)       ? " (s)" :
 	    (u.ualign.type   == A_CHAOTIC)       ? " (c)" : "");
-    	Sprintf(buf, fmtstr, "chaotic deity", buf2);
+	Sprintf(buf, fmtstr, "Chaotic", buf2);
 	add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, buf, FALSE);
 
 	Sprintf(buf2, deity_fmtstr, align_gname(A_NEUTRAL),
@@ -1113,25 +1203,28 @@
 		&& u.ualign.type == A_NEUTRAL) ? " (s,c)" :
 	    (u.ualignbase[A_ORIGINAL] == A_NEUTRAL)       ? " (s)" :
 	    (u.ualign.type   == A_NEUTRAL)       ? " (c)" : "");
-    	Sprintf(buf, fmtstr, "neutral deity", buf2);
+	Sprintf(buf, fmtstr, "Neutral", buf2);
 	add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, buf, FALSE);
 
 	Sprintf(buf2, deity_fmtstr, align_gname(A_LAWFUL),
-	    (u.ualignbase[A_ORIGINAL] == u.ualign.type && u.ualign.type == A_LAWFUL)  ? " (s,c)" :
+	    (u.ualignbase[A_ORIGINAL] == u.ualign.type &&
+		u.ualign.type == A_LAWFUL)  ? " (s,c)" :
 	    (u.ualignbase[A_ORIGINAL] == A_LAWFUL)        ? " (s)" :
 	    (u.ualign.type   == A_LAWFUL)        ? " (c)" : "");
-    	Sprintf(buf, fmtstr, "lawful  deity", buf2);
+	Sprintf(buf, fmtstr, "Lawful", buf2);
 	add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, buf, FALSE);
 
 	end_menu(tmpwin, "Base Attributes");
-	(void) select_menu(tmpwin, PICK_NONE, &selected);
+	n = select_menu(tmpwin, PICK_NONE, &selected);
 	destroy_nhwindow(tmpwin);
+	return (n != -1);
 }
 
 STATIC_PTR int
 doattributes()
 {
-	minimal_enlightenment();
+	if (!minimal_enlightenment())
+		return 0;
 	if (wizard || discover)
 		enlightenment(0);
 	return 0;
@@ -1409,6 +1502,10 @@
 	{(char *)0, (char *)0, donull, TRUE},
 	{(char *)0, (char *)0, donull, TRUE},
 	{(char *)0, (char *)0, donull, TRUE},
+#ifdef PORT_DEBUG
+	{(char *)0, (char *)0, donull, TRUE},
+#endif
+	{(char *)0, (char *)0, donull, TRUE},
         {(char *)0, (char *)0, donull, TRUE},
 	{(char *)0, (char *)0, donull, TRUE},
 	{(char *)0, (char *)0, donull, TRUE},
@@ -1423,9 +1520,13 @@
 #if defined(WIZARD)
 static const struct ext_func_tab debug_extcmdlist[] = {
 	{"levelchange", "change experience level", wiz_level_change, TRUE},
-	{"light sources", "show mobile light sources", wiz_light_sources, TRUE},
-	{"monpoly_control", "control monster polymorphs", wiz_mon_polycontrol, TRUE},
-	{"poly", "polymorph self", wiz_polyself, TRUE},
+	{"lightsources", "show mobile light sources", wiz_light_sources, TRUE},
+	{"monpolycontrol", "control monster polymorphs", wiz_mon_polycontrol, TRUE},
+	{"panic", "test panic routine (fatal to game)", wiz_panic, TRUE},
+	{"polyself", "polymorph self", wiz_polyself, TRUE},
+#ifdef PORT_DEBUG
+	{"portdebug", "wizard port debug command", wiz_port_debug, TRUE},
+#endif
 	{"seenv", "show seen vectors", wiz_show_seenv, TRUE},
 	{"stats", "show memory statistics", wiz_show_stats, TRUE},
 	{"timeout", "look at timeout queue", wiz_timeout_queue, TRUE},
@@ -1466,9 +1567,9 @@
 }
 
 
-static const char *template = "%-18s %4ld  %6ld";
-static const char *count_str = "                   count  bytes";
-static const char *separator = "------------------ -----  ------";
+static const char template[] = "%-18s %4ld  %6ld";
+static const char count_str[] = "                   count  bytes";
+static const char separator[] = "------------------ -----  ------";
 
 STATIC_OVL void
 count_obj(chain, total_count, total_size, top, recurse)
@@ -1661,6 +1762,7 @@
 	boolean do_walk, do_rush, prefix_seen, bad_command,
 		firsttime = (cmd == 0);
 
+	iflags.menu_requested = FALSE;
 	if (firsttime) {
 		flags.nopick = 0;
 		cmd = parse();
@@ -1738,12 +1840,16 @@
 		    multi = 0;
 		    return;
 	 case CMD_TRAVEL:
-		    flags.travel = 1;
-		    flags.run = 8;
-		    flags.nopick = 1;
-		    do_rush = TRUE;
-		    break;
+		    if (iflags.travelcmd) {
+			    flags.travel = 1;
+			    flags.run = 8;
+			    flags.nopick = 1;
+			    do_rush = TRUE;
+			    break;
+		    }
+		    /*FALLTHRU*/
 	 default:   if (movecmd(*cmd)) {	/* ordinary movement */
+			flags.run = 0;	/* only matters here if it was 8 */
 			do_walk = TRUE;
 		    } else if (movecmd(iflags.num_pad ?
 				       unmeta(*cmd) : lowc(*cmd))) {
@@ -1755,6 +1861,14 @@
 		    }
 		    break;
 	}
+
+	/* some special prefix handling */
+	/* overload 'm' prefix for ',' to mean "request a menu" */
+	if (prefix_seen && cmd[1] == ',') {
+		iflags.menu_requested = TRUE;
+		++cmd;
+	}
+
 	if (do_walk) {
 	    if (multi) flags.mv = TRUE;
 	    domove();
@@ -1820,7 +1934,9 @@
 		}
 	    }
 	    *cp = '\0';
-	    Norep("Unknown command '%s'.", expcmd);
+	    if (!prefix_seen || !iflags.cmdassist ||
+		!help_dir(0, "Invalid direction key!"))
+		Norep("Unknown command '%s'.", expcmd);
 	}
 	/* didn't move */
 	flags.move = FALSE;
@@ -1870,6 +1986,38 @@
 	return !u.dz;
 }
 
+/*
+ * uses getdir() but unlike getdir() it specifically
+ * produces coordinates using the direction from getdir()
+ * and verifies that those coordinates are ok.
+ *
+ * If the call to getdir() returns 0, Never_mind is displayed.
+ * If the resulting coordinates are not okay, emsg is displayed.
+ *
+ * Returns non-zero if coordinates in cc are valid.
+ */
+int get_adjacent_loc(prompt,emsg,x,y,cc)
+const char *prompt, *emsg;
+xchar x,y;
+coord *cc;
+{
+	xchar new_x, new_y;
+	if (!getdir(prompt)) {
+		pline(Never_mind);
+		return 0;
+	}
+	new_x = x + u.dx;
+	new_y = y + u.dy;
+	if (cc && isok(new_x,new_y)) {
+		cc->x = new_x;
+		cc->y = new_y;
+	} else {
+		if (emsg) pline(emsg);
+		return 0;
+	}
+	return 1;
+}
+
 int
 getdir(s)
 const char *s;
@@ -1881,7 +2029,7 @@
 	    dirsym = readchar();
 	else
 #endif
-	    dirsym = yn_function (s ? s : "In what direction?",
+	    dirsym = yn_function ((s && *s != '^') ? s : "In what direction?",
 					(char *)0, '\0');
 #ifdef REDO
 	savech(dirsym);
@@ -1889,14 +2037,86 @@
 	if(dirsym == '.' || dirsym == 's')
 		u.dx = u.dy = u.dz = 0;
 	else if(!movecmd(dirsym) && !u.dz) {
-		if(!index(quitchars, dirsym))
-			pline("What a strange direction!");
+		boolean did_help = FALSE;
+		if(!index(quitchars, dirsym)) {
+		    if (iflags.cmdassist) {
+			did_help = help_dir((s && *s == '^') ? dirsym : 0,
+					    "Invalid direction key!");
+		    }
+		    if (!did_help) pline("What a strange direction!");
+		}
 		return 0;
 	}
 	if(!u.dz && (Stunned || (Confusion && !rn2(5)))) confdir();
 	return 1;
 }
 
+STATIC_OVL boolean
+help_dir(sym, msg)
+char sym;
+const char *msg;
+{
+	char ctrl;
+	winid win;
+	static const char wiz_only_list[] = "EFGIOVW";
+	char buf[BUFSZ], buf2[BUFSZ], *expl;
+
+	win = create_nhwindow(NHW_TEXT);
+	if (!win) return FALSE;
+	if (msg) {
+		Sprintf(buf, "cmdassist: %s", msg);
+		putstr(win, 0, buf);
+		putstr(win, 0, "");
+	}
+	if (letter(sym)) { 
+	    sym = highc(sym);
+	    ctrl = (sym - 'A') + 1;
+	    if ((expl = dowhatdoes_core(ctrl, buf2))
+		&& (!index(wiz_only_list, sym)
+#ifdef WIZARD
+		    || wizard
+#endif
+	                     )) {
+		Sprintf(buf, "Are you trying to use ^%c%s?", sym,
+			index(wiz_only_list, sym) ? "" :
+			" as specified in the Guidebook");
+		putstr(win, 0, buf);
+		putstr(win, 0, "");
+		putstr(win, 0, expl);
+		putstr(win, 0, "");
+		putstr(win, 0, "To use that command, you press");
+		Sprintf(buf,
+			"the <Ctrl> key, and the <%c> key at the same time.", sym);
+		putstr(win, 0, buf);
+		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");
+	} 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, "");
+	putstr(win, 0, "          <  up");
+	putstr(win, 0, "          >  down");
+	putstr(win, 0, "          .  direct at yourself");
+	putstr(win, 0, "");
+	putstr(win, 0, "(Suppress this message with !cmdassist in config file.)");
+	display_nhwindow(win, FALSE);
+	destroy_nhwindow(win);
+	return TRUE;
+}
+
 #endif /* OVL1 */
 #ifdef OVLB
 
@@ -1936,62 +2156,81 @@
     x -= u.ux;
     y -= u.uy;
 
-    if ( abs(x) <= 1 && abs(y) <= 1 ) {
-	x = sgn(x), y = sgn(y);
-    } else {
-	u.tx = u.ux+x;
-	u.ty = u.uy+y;
-	cmd[0] = CMD_TRAVEL;
-	return cmd;
-    }
+    if (iflags.travelcmd) {
+        if (abs(x) <= 1 && abs(y) <= 1 ) {
+            x = sgn(x), y = sgn(y);
+        } else {
+            u.tx = u.ux+x;
+            u.ty = u.uy+y;
+            cmd[0] = CMD_TRAVEL;
+            return cmd;
+        }
 
-    if(x == 0 && y == 0) {
-	/* here */
-	if(IS_FOUNTAIN(levl[u.ux][u.uy].typ) || IS_SINK(levl[u.ux][u.uy].typ)) {
-	    cmd[0]=mod == CLICK_1 ? 'q' : M('d');
-	    return cmd;
-	} else if(IS_THRONE(levl[u.ux][u.uy].typ)) {
-	    cmd[0]=M('s');
-	    return cmd;
-	} else if((u.ux == xupstair && u.uy == yupstair)
-		  || (u.ux == sstairs.sx && u.uy == sstairs.sy && sstairs.up)
-		  || (u.ux == xupladder && u.uy == yupladder)) {
-	    return "<";
-	} else if((u.ux == xdnstair && u.uy == ydnstair)
-		  || (u.ux == sstairs.sx && u.uy == sstairs.sy && !sstairs.up)
-		  || (u.ux == xdnladder && u.uy == ydnladder)) {
-	    return ">";
-	} else if(OBJ_AT(u.ux, u.uy)) {
-	    cmd[0] = Is_container(level.objects[u.ux][u.uy]) ? M('l') : ',';
-	    return cmd;
-	} else {
-	    return "."; /* just rest */
-	}
-    }
+        if(x == 0 && y == 0) {
+            /* here */
+            if(IS_FOUNTAIN(levl[u.ux][u.uy].typ) || IS_SINK(levl[u.ux][u.uy].typ)) {
+                cmd[0]=mod == CLICK_1 ? 'q' : M('d');
+                return cmd;
+            } else if(IS_THRONE(levl[u.ux][u.uy].typ)) {
+                cmd[0]=M('s');
+                return cmd;
+            } else if((u.ux == xupstair && u.uy == yupstair)
+                      || (u.ux == sstairs.sx && u.uy == sstairs.sy && sstairs.up)
+                      || (u.ux == xupladder && u.uy == yupladder)) {
+                return "<";
+            } else if((u.ux == xdnstair && u.uy == ydnstair)
+                      || (u.ux == sstairs.sx && u.uy == sstairs.sy && !sstairs.up)
+                      || (u.ux == xdnladder && u.uy == ydnladder)) {
+                return ">";
+            } else if(OBJ_AT(u.ux, u.uy)) {
+                cmd[0] = Is_container(level.objects[u.ux][u.uy]) ? M('l') : ',';
+                return cmd;
+            } else {
+                return "."; /* just rest */
+            }
+        }
 
-    /* directional commands */
+        /* directional commands */
 
-    dir = xytod(x, y);
+        dir = xytod(x, y);
 
-    if (!m_at(u.ux+x, u.uy+y) && !test_move(u.ux, u.uy, x, y, 1)) {
-	cmd[1] = (iflags.num_pad ? ndir[dir] : sdir[dir]);
-	cmd[2] = 0;
-	if (IS_DOOR(levl[u.ux+x][u.uy+y].typ)) {
-	    /* slight assistance to the player: choose kick/open for them */
-	    if (levl[u.ux+x][u.uy+y].doormask & D_LOCKED) {
-		cmd[0] = C('d');
-		return cmd;
-	    }
-	    if (levl[u.ux+x][u.uy+y].doormask & D_CLOSED) {
-		cmd[0] = 'o';
-		return cmd;
-	    }
-	}
-	if (levl[u.ux+x][u.uy+y].typ <= SCORR) {
-	    cmd[0] = 's';
-	    cmd[1] = 0;
-	    return cmd;
-	}
+	if (!m_at(u.ux+x, u.uy+y) && !test_move(u.ux, u.uy, x, y, TEST_MOVE)) {
+            cmd[1] = (iflags.num_pad ? ndir[dir] : sdir[dir]);
+            cmd[2] = 0;
+            if (IS_DOOR(levl[u.ux+x][u.uy+y].typ)) {
+                /* slight assistance to the player: c