[Pkg-nethack-devel] nethack/src allmain.c,1.1.1.1,1.2 apply.c,1.1.1.1,1.2 artifact.c,1.1.1.1,1.2 bones.c,1.1.1.1,1.2 cmd.c,1.1.1.1,1.2 dbridge.c,1.1.1.1,1.2 decl.c,1.1.1.1,1.2 detect.c,1.1.1.1,1.2 dig.c,1.1.1.1,1.2 display.c,1.1.1.1,1.2 do.c,1.1.1.1,1.2 do_name.c,1.1.1.1,1.2 do_wear.c,1.1.1.1,1.2 dog.c,1.1.1.1,1.2 dogmove.c,1.1.1.1,1.2 dokick.c,1.1.1.1,1.2 dothrow.c,1.1.1.1,1.2 drawing.c,1.1.1.1,1.2 dungeon.c,1.1.1.1,1.2 eat.c,1.1.1.1,1.2 end.c,1.1.1.1,1.2 engrave.c,1.1.1.1,1.2 files.c,1.1.1.1,1.2 fountain.c,1.1.1.1,1.2 hack.c,1.1.1.1,1.2 invent.c,1.1.1.1,1.2 makemon.c,1.1.1.1,1.2 mapglyph.c,1.1.1.1,1.2 mhitm.c,1.1.1.1,1.2 mhitu.c,1.1.1.1,1.2 minion.c,1.1.1.1,1.2 mkmap.c,1.1.1.1,1.2 mkmaze.c,1.1.1.1,1.2 mkobj.c,1.1.1.1,1.2 mon.c,1.1.1.1,1.2 mondata.c,1.1.1.1,1.2 monmove.c,1.1.1.1,1.2 monst.c,1.1.1.1,1.2 mplayer.c,1.1.1.1,1.2 muse.c,1.1.1.1,1.2 o_init.c,1.1.1.1,1.2 objnam.c,1.1.1.1,1.2 options.c,1.1.1.1,1.2 pickup.c,1.1.1.1,1.2 pline.c,1.1.1.1,1.2 polyself.c,1.1.1.1,1.2 potion.c,1.1.1.1,1.2 pray.c,1.1.1.1,1.2 priest.c,1.1.1.1,1.2 questpgr.c,1.1.1.1,1.2 read.c,1.1.1.1,1.2 restore.c,1.1.1.1,1.2 save.c,1.1.1.1,1.2 shk.c,1.1.1.1,1.2 shknam.c,1.1.1.1,1.2 steal.c,1.1.1.1,1.2 steed.c,1.1.1.1,1.2 teleport.c,1.1.1.1,1.2 timeout.c,1.1.1.1,1.2 topten.c,1.1.1.1,1.2 trap.c,1.1.1.1,1.2 u_init.c,1.1.1.1,1.2 uhitm.c,1.1.1.1,1.2 vault.c,1.1.1.1,1.2 version.c,1.1.1.1,1.2 weapon.c,1.1.1.1,1.2 were.c,1.1.1.1,1.2 wizard.c,1.1.1.1,1.2 worm.c,1.1.1.1,1.2 zap.c,1.1.1.1,1.2

Joshua Kwan joshk-guest@quantz.debian.org
Tue, 09 Dec 2003 16:14:46 +0000


Update of /cvsroot/pkg-nethack/nethack/src
In directory quantz:/tmp/cvs-serv9687/src

Modified Files:
	allmain.c apply.c artifact.c bones.c cmd.c dbridge.c decl.c 
	detect.c dig.c display.c do.c do_name.c do_wear.c dog.c 
	dogmove.c dokick.c dothrow.c drawing.c dungeon.c eat.c end.c 
	engrave.c files.c fountain.c hack.c invent.c makemon.c 
	mapglyph.c mhitm.c mhitu.c minion.c mkmap.c mkmaze.c mkobj.c 
	mon.c mondata.c monmove.c monst.c mplayer.c muse.c o_init.c 
	objnam.c options.c pickup.c pline.c polyself.c potion.c pray.c 
	priest.c questpgr.c read.c restore.c save.c shk.c shknam.c 
	steal.c steed.c teleport.c timeout.c topten.c trap.c u_init.c 
	uhitm.c vault.c version.c weapon.c were.c wizard.c worm.c 
	zap.c 
Log Message:
Merge Nethack 3.4.3 upstream source.


Index: dungeon.c
===================================================================
RCS file: /cvsroot/pkg-nethack/nethack/src/dungeon.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -d -r1.1.1.1 -r1.2
--- dungeon.c	7 Oct 2003 19:00:11 -0000	1.1.1.1
+++ dungeon.c	9 Dec 2003 16:14:43 -0000	1.2
@@ -29,6 +29,14 @@
 					/*   and mklev.c)		   */
 static branch *branches = (branch *) 0;	/* dungeon branch list		   */
 
+struct lchoice {
+	int idx;
+	schar lev[MAXLINFO];
+	schar playerlev[MAXLINFO];
+	xchar dgn[MAXLINFO];
+	char menuletter;
+};
+
 static void FDECL(Fread, (genericptr_t, int, int, dlb *));
 STATIC_DCL xchar FDECL(dname_to_dnum, (const char *));
 STATIC_DCL int FDECL(find_branch, (const char *, struct proto_dungeon *));
@@ -44,7 +52,7 @@
 STATIC_DCL boolean FDECL(place_level, (int, struct proto_dungeon *));
 #ifdef WIZARD
 STATIC_DCL const char *FDECL(br_string, (int));
-STATIC_DCL void FDECL(print_branch, (winid, int, int, int, BOOLEAN_P, char *));
+STATIC_DCL void FDECL(print_branch, (winid, int, int, int, BOOLEAN_P, struct lchoice *));
 #endif
 
 #ifdef DEBUG
@@ -662,6 +670,10 @@
 # endif
 	    Strcat(tbuf, "\" file!");
 #endif
+#ifdef WIN32
+	    interject_assistance(1, INTERJECT_PANIC, (genericptr_t)tbuf,
+				 (genericptr_t)fqn_prefix[DATAPREFIX]);
+#endif
 	    panic(tbuf);
 	}
 
@@ -1537,13 +1549,13 @@
 
 /* Print all child branches between the lower and upper bounds. */
 STATIC_OVL void
-print_branch(win, dnum, lower_bound, upper_bound, bymenu, menuletter)
+print_branch(win, dnum, lower_bound, upper_bound, bymenu, lchoices)
     winid win;
     int   dnum;
     int   lower_bound;
     int   upper_bound;
     boolean bymenu;
-    char *menuletter;
+    struct lchoice *lchoices;
 {
     branch *br;
     char buf[BUFSZ];
@@ -1558,14 +1570,16 @@
 		    dungeons[br->end2.dnum].dname,
 		    depth(&br->end1));
 	    if (bymenu) {
-	    	schar lev = depth(&br->end1);
+		lchoices->lev[lchoices->idx] = br->end1.dlevel;
+		lchoices->dgn[lchoices->idx] = br->end1.dnum;
+		lchoices->playerlev[lchoices->idx] = depth(&br->end1);
 		any.a_void = 0;
-		if (lev >= 0) any.a_schar = lev + 1;
-		else any.a_schar = lev;
-		add_menu(win, NO_GLYPH, &any, *menuletter,
+		any.a_int = lchoices->idx + 1;
+		add_menu(win, NO_GLYPH, &any, lchoices->menuletter,
 				0, ATR_NONE, buf, MENU_UNSELECTED);
-		if (*menuletter == 'z') *menuletter = 'A';
-		else *menuletter += 1;
+		if (lchoices->menuletter == 'z') lchoices->menuletter = 'A';
+		else lchoices->menuletter++;
+		lchoices->idx++;
 	    } else
 		putstr(win, 0, buf);
 	}
@@ -1574,8 +1588,10 @@
 
 /* Print available dungeon information. */
 schar
-print_dungeon(bymenu)
+print_dungeon(bymenu, rlev, rdgn)
 boolean bymenu;
+schar *rlev;
+xchar *rdgn;
 {
     int     i, last_level, nlev;
     char    buf[BUFSZ];
@@ -1583,13 +1599,14 @@
     s_level *slev;
     dungeon *dptr;
     branch  *br;
-
     anything any;
-    char mlet;
+    struct lchoice lchoices;
+
     winid   win = create_nhwindow(NHW_MENU);
     if (bymenu) {
 	start_menu(win);
-	mlet = 'a';
+	lchoices.idx = 0;
+	lchoices.menuletter = 'a';
     }
 
     for (i = 0, dptr = dungeons; i < n_dgns; i++, dptr++) {
@@ -1610,7 +1627,7 @@
 	}
 	if (bymenu) {
 	    any.a_void = 0;
-	    add_menu(win, NO_GLYPH, &any, 0, 0, ATR_BOLD, buf, MENU_UNSELECTED);
+	    add_menu(win, NO_GLYPH, &any, 0, 0, iflags.menu_headings, buf, MENU_UNSELECTED);
 	} else
 	    putstr(win, 0, buf);
 
@@ -1622,37 +1639,42 @@
 	    if (slev->dlevel.dnum != i) continue;
 
 	    /* print any branches before this level */
-	    print_branch(win, i, last_level, slev->dlevel.dlevel, bymenu, &mlet);
+	    print_branch(win, i, last_level, slev->dlevel.dlevel, bymenu, &lchoices);
 
 	    Sprintf(buf, "   %s: %d", slev->proto, depth(&slev->dlevel));
 	    if (Is_stronghold(&slev->dlevel))
 		Sprintf(eos(buf), " (tune %s)", tune);
 	    if (bymenu) {
-	    	schar lev = depth(&slev->dlevel);
+	    	/* If other floating branches are added, this will need to change */
+	    	if (i != knox_level.dnum) {
+			lchoices.lev[lchoices.idx] = slev->dlevel.dlevel;
+			lchoices.dgn[lchoices.idx] = i;
+		} else {
+			lchoices.lev[lchoices.idx] = depth(&slev->dlevel);
+			lchoices.dgn[lchoices.idx] = 0;
+		}
+		lchoices.playerlev[lchoices.idx] = depth(&slev->dlevel);
 		any.a_void = 0;
-		if (lev >= 0) any.a_schar = lev + 1;
-		else any.a_schar = lev;
-		add_menu(win, NO_GLYPH, &any, mlet, 0, ATR_NONE, buf, MENU_UNSELECTED);
-		if (mlet == 'z') mlet = 'A';
-		else mlet++;
+		any.a_int = lchoices.idx + 1;
+		add_menu(win, NO_GLYPH, &any, lchoices.menuletter,
+				0, ATR_NONE, buf, MENU_UNSELECTED);
+		if (lchoices.menuletter == 'z') lchoices.menuletter = 'A';
+		else lchoices.menuletter++;
+		lchoices.idx++;
 	    } else
 		putstr(win, 0, buf);
 
 	    last_level = slev->dlevel.dlevel;
 	}
 	/* print branches after the last special level */
-	print_branch(win, i, last_level, MAXLEVEL, bymenu, &mlet);
+	print_branch(win, i, last_level, MAXLEVEL, bymenu, &lchoices);
     }
 
     /* Print out floating branches (if any). */
     for (first = TRUE, br = branches; br; br = br->next) {
 	if (br->end1.dnum == n_dgns) {
 	    if (first) {
-	    	if (bymenu) {
-		    any.a_void = 0;
-		    add_menu(win, NO_GLYPH, &any, 0, 0, ATR_BOLD,
-				"Floating branches", MENU_UNSELECTED);
-	    	} else {
+	    	if (!bymenu) {
 		    putstr(win, 0, "");
 		    putstr(win, 0, "Floating branches");
 		}
@@ -1660,32 +1682,28 @@
 	    }
 	    Sprintf(buf, "   %s to %s",
 			br_string(br->type), dungeons[br->end2.dnum].dname);
-	    if (bymenu) {
-	    	schar lev = lev_by_name(dungeons[br->end2.dnum].dname);
-		any.a_void = 0;
-		if (lev >= 0) any.a_schar = lev + 1;
-		else any.a_schar = lev;
-		add_menu(win, NO_GLYPH, &any, mlet, 0, ATR_NONE, buf, MENU_UNSELECTED);
-		if (mlet == 'z') mlet = 'A';
-		else mlet++;
-	    } else
+	    if (!bymenu)
 		putstr(win, 0, buf);
 	}
     }
     if (bymenu) {
     	int n;
 	menu_item *selected;
-	schar lev = 0;
+	int idx;
 
 	end_menu(win, "Level teleport to where:");
 	n = select_menu(win, PICK_ONE, &selected);
 	destroy_nhwindow(win);
 	if (n > 0) {
-		lev = selected[0].item.a_schar;
-		if (lev > 0) lev--;
+		idx = selected[0].item.a_int - 1;
 		free((genericptr_t)selected);
+		if (rlev && rdgn) {
+			*rlev = lchoices.lev[idx];
+			*rdgn = lchoices.dgn[idx];
+			return lchoices.playerlev[idx];
+		}
 	}
-	return lev;
+	return 0;
     }
 
     /* I hate searching for the invocation pos while debugging. -dean */

Index: pickup.c
===================================================================
RCS file: /cvsroot/pkg-nethack/nethack/src/pickup.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -d -r1.1.1.1 -r1.2
--- pickup.c	7 Oct 2003 19:00:17 -0000	1.1.1.1
+++ pickup.c	9 Dec 2003 16:14:43 -0000	1.2
@@ -397,6 +397,7 @@
 	    count = 0;
 
 	if (!u.uswallow) {
+		struct trap *ttmp = t_at(u.ux, u.uy);
 		/* no auto-pick if no-pick move, nothing there, or in a pool */
 		if (autopickup && (flags.nopick || !OBJ_AT(u.ux, u.uy) ||
 			(is_pool(u.ux, u.uy) && !Underwater) || is_lava(u.ux, u.uy))) {
@@ -410,7 +411,18 @@
 			read_engr_at(u.ux, u.uy);
 		    return (0);
 		}
-
+		if (ttmp && ttmp->tseen) {
+		    /* Allow pickup from holes and trap doors that you escaped
+		     * from because that stuff is teetering on the edge just
+		     * like you, but not pits, because there is an elevation
+		     * discrepancy with stuff in pits.
+		     */
+		    if ((ttmp->ttyp == PIT || ttmp->ttyp == SPIKED_PIT) &&
+			(!u.utrap || (u.utrap && u.utraptype != TT_PIT))) {
+			read_engr_at(u.ux, u.uy);
+			return(0);
+		    }
+		}
 		/* multi && !flags.run means they are in the middle of some other
 		 * action, or possibly paralyzed, sleeping, etc.... and they just
 		 * teleported onto the object.  They shouldn't pick it up.
@@ -583,6 +595,27 @@
 	return (n_tried > 0);
 }
 
+#ifdef AUTOPICKUP_EXCEPTIONS
+boolean
+is_autopickup_exception(obj, grab)
+struct obj *obj;
+boolean grab;	 /* forced pickup, rather than forced leave behind? */
+{
+	/*
+	 *  Does the text description of this match an exception?
+	 */
+	char *objdesc = makesingular(doname(obj));
+	struct autopickup_exception *ape = (grab) ?
+					iflags.autopickup_exceptions[AP_GRAB] :
+					iflags.autopickup_exceptions[AP_LEAVE];
+	while (ape) {
+		if (pmatch(ape->pattern, objdesc)) return TRUE;
+		ape = ape->next;
+	}
+	return FALSE;
+}
+#endif /* AUTOPICKUP_EXCEPTIONS */
+
 /*
  * Pick from the given list using flags.pickup_types.  Return the number
  * of items picked (not counts).  Create an array that returns pointers
@@ -603,13 +636,27 @@
 
 	/* first count the number of eligible items */
 	for (n = 0, curr = olist; curr; curr = FOLLOW(curr, follow))
+
+
+#ifndef AUTOPICKUP_EXCEPTIONS
 	    if (!*otypes || index(otypes, curr->oclass))
+#else
+	    if ((!*otypes || index(otypes, curr->oclass) ||
+		 is_autopickup_exception(curr, TRUE)) &&
+	    	 !is_autopickup_exception(curr, FALSE))
+#endif
 		n++;
 
 	if (n) {
 	    *pick_list = pi = (menu_item *) alloc(sizeof(menu_item) * n);
 	    for (n = 0, curr = olist; curr; curr = FOLLOW(curr, follow))
+#ifndef AUTOPICKUP_EXCEPTIONS
 		if (!*otypes || index(otypes, curr->oclass)) {
+#else
+	    if ((!*otypes || index(otypes, curr->oclass) ||
+		 is_autopickup_exception(curr, TRUE)) &&
+	    	 !is_autopickup_exception(curr, FALSE)) {
+#endif
 		    pi[n].item.a_obj = curr;
 		    pi[n].count = curr->quan;
 		    n++;
@@ -696,7 +743,7 @@
 		    /* if sorting, print type name (once only) */
 		    if (qflags & INVORDER_SORT && !printed_type_name) {
 			any.a_obj = (struct obj *) 0;
-			add_menu(win, NO_GLYPH, &any, 0, 0, ATR_INVERSE,
+			add_menu(win, NO_GLYPH, &any, 0, 0, iflags.menu_headings,
 					let_to_name(*pack, FALSE), MENU_UNSELECTED);
 			printed_type_name = TRUE;
 		    }
@@ -1811,8 +1858,9 @@
 	    if (current_container->no_charge && !obj->unpaid) {
 		/* don't sell when putting the item into your own container */
 		obj->no_charge = 1;
-	    } else {
-		/* sellobj() will take an unpaid item off the shop bill */
+	    } else if (obj->oclass != COIN_CLASS) {
+		/* sellobj() will take an unpaid item off the shop bill
+		 * note: coins are handled later */
 		was_unpaid = obj->unpaid ? TRUE : FALSE;
 		sellobj_state(SELL_DELIBERATE);
 		sellobj(obj, u.ux, u.uy);
@@ -2095,10 +2143,14 @@
 		    int t;
 		    char menuprompt[BUFSZ];
 		    boolean outokay = (cnt != 0);
+#ifndef GOLDOBJ
+		    boolean inokay = (invent != 0) || (u.ugold != 0);
+#else
 		    boolean inokay = (invent != 0);
+#endif
 		    if (!outokay && !inokay) {
 			pline("%s", emptymsg);
-			pline("You don't have anything to put in.");
+			You("don't have anything to put in.");
 			return used;
 		    }
 		    menuprompt[0] = '\0';

Index: version.c
===================================================================
RCS file: /cvsroot/pkg-nethack/nethack/src/version.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -d -r1.1.1.1 -r1.2
--- version.c	7 Oct 2003 19:00:21 -0000	1.1.1.1
+++ version.c	9 Dec 2003 16:14:43 -0000	1.2
@@ -1,4 +1,4 @@
-/*	SCCS Id: @(#)version.c	3.4	2003/08/21	*/
+/*	SCCS Id: @(#)version.c	3.4	2003/12/06	*/
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
 /* NetHack may be freely redistributed.  See license for details. */
 
@@ -14,19 +14,27 @@
 #include "patchlevel.h"
 #endif
 
-/* #define BETA_INFO "" */
+/* #define BETA_INFO "" */	/* "[ beta n]" */
 
-/* fill and return the given buffer with the nethack version string */
+/* fill buffer with short version (so caller can avoid including date.h) */
+char *
+version_string(buf)
+char *buf;
+{
+	return strcpy(buf, VERSION_STRING);
+}
+
+/* fill and return the given buffer with the long nethack version string */
 char *
 getversionstring(buf)
 char *buf;
 {
-	 Strcpy(buf, VERSION_ID);
+	Strcpy(buf, VERSION_ID);
 #if defined(BETA) && defined(BETA_INFO)
-	 Sprintf(eos(buf), " %s", BETA_INFO);
+	Sprintf(eos(buf), " %s", BETA_INFO);
 #endif
 #if defined(RUNTIME_PORT_ID)
-	 append_port_id(buf);
+	append_port_id(buf);
 #endif
 	return buf;
 }

Index: polyself.c
===================================================================
RCS file: /cvsroot/pkg-nethack/nethack/src/polyself.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -d -r1.1.1.1 -r1.2
--- polyself.c	7 Oct 2003 19:00:17 -0000	1.1.1.1
+++ polyself.c	9 Dec 2003 16:14:43 -0000	1.2
@@ -230,6 +230,7 @@
 				uarm->otyp <= YELLOW_DRAGON_SCALES);
 	boolean iswere = (u.ulycn >= LOW_PM || is_were(youmonst.data));
 	boolean isvamp = (youmonst.data->mlet == S_VAMPIRE || u.umonnum == PM_VAMPIRE_BAT);
+	boolean was_floating = (Levitation || Flying);
 
         if(!Polymorph_control && !forcecontrol && !draconian && !iswere && !isvamp) {
 	    if (rn2(20) > ACURR(A_CON)) {
@@ -319,6 +320,9 @@
 		new_light_source(u.ux, u.uy, new_light,
 				 LS_MONSTER, (genericptr_t)&youmonst);
 	}
+	if (is_pool(u.ux,u.uy) && was_floating && !(Levitation || Flying) &&
+		!breathless(youmonst.data) && !amphibious(youmonst.data) &&
+		!Swimming) drown();
 }
 
 /* (try to) make a mntmp monster out of the player */
@@ -408,7 +412,7 @@
 		You("no longer feel sick.");
 	}
 	if (Slimed) {
-	    if (mntmp == PM_FIRE_VORTEX || mntmp == PM_FIRE_ELEMENTAL || mntmp == PM_SALAMANDER) {
+	    if (flaming(youmonst.data)) {
 		pline_The("slime burns away!");
 		Slimed = 0L;
 		flags.botl = 1;
@@ -902,6 +906,7 @@
 int
 dosummon()
 {
+	int placeholder;
 	if (u.uen < 10) {
 	    You("lack the energy to send forth a call for help!");
 	    return(0);
@@ -911,7 +916,7 @@
 
 	You("call upon your brethren for help!");
 	exercise(A_WIS, TRUE);
-	if (!were_summon(youmonst.data,TRUE))
+	if (!were_summon(youmonst.data, TRUE, &placeholder, (char *)0))
 		pline("But none arrive.");
 	return(1);
 }

Index: eat.c
===================================================================
RCS file: /cvsroot/pkg-nethack/nethack/src/eat.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -d -r1.1.1.1 -r1.2
--- eat.c	7 Oct 2003 19:00:12 -0000	1.1.1.1
+++ eat.c	9 Dec 2003 16:14:43 -0000	1.2
@@ -15,6 +15,7 @@
 
 STATIC_PTR int NDECL(eatmdone);
 STATIC_PTR int NDECL(eatfood);
+STATIC_PTR void FDECL(costly_tin, (const char*));
 STATIC_PTR int NDECL(opentin);
 STATIC_PTR int NDECL(unfaint);
 
@@ -37,11 +38,11 @@
 STATIC_DCL void FDECL(fpostfx, (struct obj *));
 STATIC_DCL int NDECL(bite);
 STATIC_DCL int FDECL(edibility_prompts, (struct obj *));
-
 STATIC_DCL int FDECL(rottenfood, (struct obj *));
 STATIC_DCL void NDECL(eatspecial);
 STATIC_DCL void FDECL(eataccessory, (struct obj *));
 STATIC_DCL const char *FDECL(foodword, (struct obj *));
+STATIC_DCL boolean FDECL(maybe_cannibal, (int,BOOLEAN_P));
 
 char msgbuf[BUFSZ];
 
@@ -260,7 +261,8 @@
 				killer = food_xname(food, FALSE);
 				if (food->otyp == CORPSE &&
 				    (mons[food->corpsenm].geno & G_UNIQ)) {
-				    killer = the(killer);
+				    if (!type_is_pname(&mons[food->corpsenm]))
+					killer = the(killer);
 				    killer_format = KILLED_BY;
 				}
 			}
@@ -436,18 +438,29 @@
 	victual.fullwarn = victual.eating = victual.doreset = FALSE;
 }
 
-STATIC_OVL void
-cprefx(pm)
-register int pm;
+STATIC_OVL boolean
+maybe_cannibal(pm, allowmsg)
+int pm;
+boolean allowmsg;
 {
 	if (!CANNIBAL_ALLOWED() && your_race(&mons[pm])) {
-		if (Upolyd)
-			You("have a bad feeling deep inside.");
-		You("cannibal!  You will regret this!");
+		if (allowmsg) {
+			if (Upolyd)
+				You("have a bad feeling deep inside.");
+			You("cannibal!  You will regret this!");
+		}
 		HAggravate_monster |= FROMOUTSIDE;
 		change_luck(-rn1(4,2));		/* -5..-2 */
+		return TRUE;
 	}
+	return FALSE;
+}
 
+STATIC_OVL void
+cprefx(pm)
+register int pm;
+{
+	(void) maybe_cannibal(pm,TRUE);
 	if (touch_petrifies(&mons[pm]) || pm == PM_MEDUSA) {
 	    if (!Stone_resistance &&
 		!(poly_when_stoned(youmonst.data) && polymon(PM_STONE_GOLEM))) {
@@ -495,10 +508,7 @@
 		    return;
 		}
 	    case PM_GREEN_SLIME:
-		if (!Slimed && !Unchanging &&
-			youmonst.data != &mons[PM_FIRE_VORTEX] &&
-			youmonst.data != &mons[PM_FIRE_ELEMENTAL] &&
-			youmonst.data != &mons[PM_SALAMANDER] &&
+		if (!Slimed && !Unchanging && !flaming(youmonst.data) &&
 			youmonst.data != &mons[PM_GREEN_SLIME]) {
 		    You("don't feel very well.");
 		    Slimed = 10L;
@@ -984,6 +994,23 @@
     return;
 }
 
+/* common code to check and possibly charge for 1 context.tin.tin,
+ * will split() context.tin.tin if necessary */
+STATIC_PTR
+void
+costly_tin(verb)
+	const char* verb;		/* if 0, the verb is "open" */
+{
+	if(((!carried(tin.tin) &&
+	     costly_spot(tin.tin->ox, tin.tin->oy) &&
+	     !tin.tin->no_charge)
+	    || tin.tin->unpaid)) {
+	    verbalize("You %s it, you bought it!", verb ? verb : "open");
+	    if(tin.tin->quan > 1L) tin.tin = splitobj(tin.tin, 1L);
+	    bill_dummy_object(tin.tin);
+	}
+}
+
 STATIC_PTR
 int
 opentin()		/* called during each move whilst opening a tin */
@@ -1004,6 +1031,7 @@
 	if(tin.tin->otrapped ||
 	   (tin.tin->cursed && tin.tin->spe != -1 && !rn2(8))) {
 		b_trapped("tin", 0);
+		costly_tin("destroyed");
 		goto use_me;
 	}
 	You("succeed in opening the tin.");
@@ -1011,6 +1039,7 @@
 	    if (tin.tin->corpsenm == NON_PM) {
 		pline("It turns out to be empty.");
 		tin.tin->dknown = tin.tin->known = TRUE;
+		costly_tin((const char*)0);
 		goto use_me;
 	    }
 	    r = tin.tin->cursed ? ROTTEN_TIN :	/* always rotten if cursed */
@@ -1034,6 +1063,7 @@
 	    if (yn("Eat it?") == 'n') {
 		if (!Hallucination) tin.tin->dknown = tin.tin->known = TRUE;
 		if (flags.verbose) You("discard the open tin.");
+		costly_tin((const char*)0);
 		goto use_me;
 	    }
 	    /* in case stop_occupation() was called on previous meal */
@@ -1053,14 +1083,8 @@
 	    tin.tin->dknown = tin.tin->known = TRUE;
 	    cprefx(tin.tin->corpsenm); cpostfx(tin.tin->corpsenm);
 
-	    if(((!carried(tin.tin) && costly_spot(tin.tin->ox, tin.tin->oy) &&
-		 !tin.tin->no_charge)
-		|| tin.tin->unpaid)) {
-		verbalize("You open it, you bought it!");
-		/* charge for one at pre-eating cost */
-		if(tin.tin->quan > 1L) tin.tin = splitobj(tin.tin, 1L);
-		bill_dummy_object(tin.tin);
-	    }
+	    /* charge for one at pre-eating cost */
+	    costly_tin((const char*)0);
 
 	    /* check for vomiting added by GAN 01/16/87 */
 	    if(tintxts[r].nut < 0) make_vomiting((long)rn1(15,10), FALSE);
@@ -1084,18 +1108,12 @@
 		    tin.tin->dknown = tin.tin->known = TRUE;
 		if (flags.verbose)
 		    You("discard the open tin.");
+		costly_tin((const char*)0);
 		goto use_me;
 	    }
 
 	    tin.tin->dknown = tin.tin->known = TRUE;
-	    if(((!carried(tin.tin) && costly_spot(tin.tin->ox, tin.tin->oy) &&
-		 !tin.tin->no_charge)
-		|| tin.tin->unpaid)) {
-		verbalize("You open it, you bought it!");
-		/* charge for one at pre-eating cost */
-		if(tin.tin->quan > 1L) tin.tin = splitobj(tin.tin, 1L);
-		bill_dummy_object(tin.tin);
-	    }
+	    costly_tin((const char*)0);
 
 	    if (!tin.tin->cursed)
 		pline("This makes you feel like %s!",
@@ -1238,9 +1256,11 @@
 	}
 
 	if (mnum != PM_ACID_BLOB && !stoneable && rotted > 5L) {
-		pline("Ulch - that %s was tainted!",
+		boolean cannibal = maybe_cannibal(mnum, FALSE);
+		pline("Ulch - that %s was tainted%s!",
 		      mons[mnum].mlet == S_FUNGUS ? "fungoid vegetation" :
-		      !vegetarian(&mons[mnum]) ? "meat" : "protoplasm");
+		      !vegetarian(&mons[mnum]) ? "meat" : "protoplasm",
+		      cannibal ? " cannibal" : "");
 		if (Sick_resistance) {
 			pline("It doesn't seem at all sickening, though...");
 		} else {
@@ -1547,6 +1567,14 @@
 		    flags.female ? "feminine" : "masculine");
 		flags.botl = 1;
 		break;
+	    case AMULET_OF_UNCHANGING:
+		/* un-change: it's a pun */
+		if (!Unchanging && Upolyd) {
+		    accessory_has_effect(otmp);
+		    makeknown(typ);
+		    rehumanize();
+		}
+		break;
 	    case AMULET_OF_STRANGULATION: /* bad idea! */
 		/* no message--this gives no permanent effect */
 		choke(otmp);
@@ -1557,7 +1585,6 @@
 		HSleeping = FROMOUTSIDE | rnd(100);
 		break;
 	    case RIN_SUSTAIN_ABILITY:
-	    case AMULET_OF_UNCHANGING:
 	    case AMULET_OF_LIFE_SAVING:
 	    case AMULET_OF_REFLECTION: /* nice try */
 	    /* can't eat Amulet of Yendor or fakes,
@@ -1738,10 +1765,7 @@
 				!poly_when_stoned(youmonst.data));
 
 		if (mnum == PM_GREEN_SLIME)
-		    stoneorslime = (!Unchanging &&
-			youmonst.data != &mons[PM_FIRE_VORTEX] &&
-			youmonst.data != &mons[PM_FIRE_ELEMENTAL] &&
-			youmonst.data != &mons[PM_SALAMANDER] &&
+		    stoneorslime = (!Unchanging && !flaming(youmonst.data) &&
 			youmonst.data != &mons[PM_GREEN_SLIME]);
 
 		if (cadaver && mnum != PM_LIZARD && mnum != PM_LICHEN) {

Index: end.c
===================================================================
RCS file: /cvsroot/pkg-nethack/nethack/src/end.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -d -r1.1.1.1 -r1.2
--- end.c	7 Oct 2003 19:00:12 -0000	1.1.1.1
+++ end.c	9 Dec 2003 16:14:43 -0000	1.2
@@ -298,6 +298,9 @@
 	    raw_print(buf);
 	    paniclog("panic", buf);
 	}
+#ifdef WIN32
+	interject(INTERJECT_PANIC);
+#endif
 #if defined(WIZARD) && (defined(UNIX) || defined(VMS) || defined(LATTICE) || defined(WIN32))
 	if (wizard)
 	    NH_abort();	/* generate core dump */

Index: dogmove.c
===================================================================
RCS file: /cvsroot/pkg-nethack/nethack/src/dogmove.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -d -r1.1.1.1 -r1.2
--- dogmove.c	7 Oct 2003 19:00:10 -0000	1.1.1.1
+++ dogmove.c	9 Dec 2003 16:14:43 -0000	1.2
@@ -16,8 +16,9 @@
 STATIC_DCL int FDECL(dog_goal,(struct monst *,struct edog *,int,int,int));
 
 STATIC_DCL struct obj *FDECL(DROPPABLES, (struct monst *));
-STATIC_DCL boolean FDECL(can_reach_food,(struct monst *,XCHAR_P,XCHAR_P,XCHAR_P,
-    XCHAR_P));
+STATIC_DCL boolean FDECL(can_reach_location,(struct monst *,XCHAR_P,XCHAR_P,
+    XCHAR_P,XCHAR_P));
+STATIC_DCL boolean FDECL(could_reach_item,(struct monst *, XCHAR_P,XCHAR_P));
 
 STATIC_OVL struct obj *
 DROPPABLES(mon)
@@ -293,13 +294,14 @@
 									){
 		int edible = dogfood(mtmp, obj);
 
-		if (edible <= CADAVER ||
+		if ((edible <= CADAVER ||
 			/* starving pet is more aggressive about eating */
-			(edog->mhpmax_penalty && edible == ACCFOOD))
+			(edog->mhpmax_penalty && edible == ACCFOOD)) &&
+		    could_reach_item(mtmp, obj->ox, obj->oy))
 		    return dog_eat(mtmp, obj, omx, omy, FALSE);
 
 		if(can_carry(mtmp, obj) && !obj->cursed &&
-			!is_pool(mtmp->mx,mtmp->my)) {
+			could_reach_item(mtmp, obj->ox, obj->oy)) {
 		    if(rn2(20) < edog->apport+3) {
 			if (rn2(udist) || !rn2(edog->apport)) {
 			    if (cansee(omx, omy) && flags.verbose)
@@ -380,8 +382,11 @@
 		    if (cursed_object_at(nx, ny) &&
 			    !(edog->mhpmax_penalty && otyp < MANFOOD))
 			continue;
-		    if (otyp < MANFOOD &&
-			    can_reach_food(mtmp, mtmp->mx, mtmp->my, nx, ny)) {
+		    /* skip completely unreacheable goals */
+		    if (!could_reach_item(mtmp, nx, ny) ||
+		        !can_reach_location(mtmp, mtmp->mx, mtmp->my, nx, ny))
+			continue;
+		    if (otyp < MANFOOD) {
 			if (otyp < gtyp || DDIST(nx,ny) < DDIST(gx,gy)) {
 			    gx = nx;
 			    gy = ny;
@@ -786,15 +791,28 @@
 	return(1);
 }
 
-/* Hack to prevent a dog from being endlessly stuck near a piece of food that
+/* check if a monster could pick up objects from a location */
+STATIC_OVL boolean
+could_reach_item(mon, nx, ny)
+struct monst *mon;
+xchar nx, ny;
+{
+    if ((!is_pool(nx,ny) || is_swimmer(mon->data)) &&
+	(!is_lava(nx,ny) || likes_lava(mon->data)) &&
+	(!sobj_at(BOULDER,nx,ny) || throws_rocks(mon->data)))
+    	return TRUE;
+    return FALSE;
+}
+
+/* Hack to prevent a dog from being endlessly stuck near an object that
  * it can't reach, such as caught in a teleport scroll niche.  It recursively
- * checks to see if the squares inbetween are good.  The checking could be a
+ * checks to see if the squares in between are good.  The checking could be a
  * little smarter; a full check would probably be useful in m_move() too.
  * Since the maximum food distance is 5, this should never be more than 5 calls
  * deep.
  */
-STATIC_OVL  boolean
-can_reach_food(mon, mx, my, fx, fy)
+STATIC_OVL boolean
+can_reach_location(mon, mx, my, fx, fy)
 struct monst *mon;
 xchar mx, my, fx, fy;
 {
@@ -817,13 +835,9 @@
 	    if (IS_DOOR(levl[i][j].typ) &&
 				(levl[i][j].doormask & (D_CLOSED | D_LOCKED)))
 		continue;
-	    if (is_pool(i, j) && !is_swimmer(mon->data))
-		continue;
-	    if (is_lava(i, j) && !likes_lava(mon->data))
-		continue;
-	    if (sobj_at(BOULDER,i,j) && !throws_rocks(mon->data))
+	    if (!could_reach_item(mon, i, j))
 		continue;
-	    if (can_reach_food(mon, i, j, fx, fy))
+	    if (can_reach_location(mon, i, j, fx, fy))
 		return TRUE;
 	}
     }

Index: makemon.c
===================================================================
RCS file: /cvsroot/pkg-nethack/nethack/src/makemon.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -d -r1.1.1.1 -r1.2
--- makemon.c	7 Oct 2003 19:00:13 -0000	1.1.1.1
+++ makemon.c	9 Dec 2003 16:14:43 -0000	1.2
@@ -1,4 +1,4 @@
-/*	SCCS Id: @(#)makemon.c	3.4	2003/05/25	*/
+/*	SCCS Id: @(#)makemon.c	3.4	2003/09/06	*/
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
 /* NetHack may be freely redistributed.  See license for details. */
 
@@ -666,9 +666,11 @@
 #endif
 }
 
+/* Note: for long worms, always call cutworm (cutworm calls clone_mon) */
 struct monst *
-clone_mon(mon)
+clone_mon(mon, x, y)
 struct monst *mon;
+xchar x, y;	/* clone's preferred location or 0 (near mon) */
 {
 	coord mm;
 	struct monst *m2;
@@ -677,10 +679,21 @@
 	if (mon->mhp <= 1 || (mvitals[monsndx(mon->data)].mvflags & G_EXTINCT))
 	    return (struct monst *)0;
 
-	mm.x = mon->mx;
-	mm.y = mon->my;
-	if (!enexto(&mm, mm.x, mm.y, mon->data) || MON_AT(mm.x, mm.y))
-	    return (struct monst *)0;
+	if (x == 0) {
+	    mm.x = mon->mx;
+	    mm.y = mon->my;
+	    if (!enexto(&mm, mm.x, mm.y, mon->data) || MON_AT(mm.x, mm.y))
+		return (struct monst *)0;
+	} else if (!isok(x, y)) {
+	    return (struct monst *)0;	/* paranoia */
+	} else {
+	    mm.x = x;
+	    mm.y = y;
+	    if (MON_AT(mm.x, mm.y)) {
+		if (!enexto(&mm, mm.x, mm.y, mon->data) || MON_AT(mm.x, mm.y))
+		    return (struct monst *)0;
+	    }
+	}
 	m2 = newmonst(0);
 	*m2 = *mon;			/* copy condition of old monster */
 	m2->nmon = fmon;
@@ -719,9 +732,20 @@
 	if (m2->mnamelth) {
 	    m2->mnamelth = 0; /* or it won't get allocated */
 	    m2 = christen_monst(m2, NAME(mon));
+	} else if (mon->isshk) {
+	    m2 = christen_monst(m2, shkname(mon));
+	}
+
+	/* not all clones caused by player are tame or peaceful */
+	if (!flags.mon_moving) {
+	    if (mon->mtame)
+		m2->mtame = rn2(max(2 + u.uluck, 2)) ? mon->mtame : 0;
+	    else if (mon->mpeaceful)
+		m2->mpeaceful = rn2(max(2 + u.uluck, 2)) ? 1 : 0;
 	}
+
 	newsym(m2->mx,m2->my);	/* display the new monster */
-	if (mon->mtame) {
+	if (m2->mtame) {
 	    struct monst *m3;
 
 	    if (mon->isminion) {
@@ -744,10 +768,52 @@
 		}
 	    }
 	}
+	set_malign(m2);
+
 	return m2;
 }
 
 /*
+ * Propagate a species
+ *
+ * Once a certain number of monsters are created, don't create any more
+ * at random (i.e. make them extinct).  The previous (3.2) behavior was
+ * to do this when a certain number had _died_, which didn't make
+ * much sense.
+ *
+ * Returns FALSE propagation unsuccessful
+ *         TRUE  propagation successful
+ */
+boolean
+propagate(mndx, tally, ghostly)
+int mndx;
+boolean tally;
+boolean ghostly;
+{
+	boolean result;
+	uchar lim = mbirth_limit(mndx);
+	boolean gone = (mvitals[mndx].mvflags & G_GONE); /* genocided or extinct */
+
+	result = (((int) mvitals[mndx].born < lim) && !gone) ? TRUE : FALSE;
+
+	/* if it's unique, don't ever make it again */
+	if (mons[mndx].geno & G_UNIQ) mvitals[mndx].mvflags |= G_EXTINCT;
+
+	if (mvitals[mndx].born < 255 && tally && (!ghostly || (ghostly && result)))
+		 mvitals[mndx].born++;
+	if ((int) mvitals[mndx].born >= lim && !(mons[mndx].geno & G_NOGEN) &&
+		!(mvitals[mndx].mvflags & G_EXTINCT)) {
+#if defined(DEBUG) && defined(WIZARD)
+		if (wizard) pline("Automatically extinguished %s.",
+					makeplural(mons[mndx].mname));
+#endif
+		mvitals[mndx].mvflags |= G_EXTINCT;
+		reset_rndmonst(mndx);
+	}
+	return result;
+}
+
+/*
  * called with [x,y] = coordinates;
  *	[0,0] means anyplace
  *	[u.ux,u.uy] means: near player (if !in_mklev)
@@ -767,7 +833,6 @@
 	boolean allow_minvent = ((mmflags & NO_MINVENT) == 0);
 	boolean countbirth = ((mmflags & MM_NOCOUNTBIRTH) == 0);
 	unsigned gpflags = (mmflags & MM_IGNOREWATER) ? MM_IGNOREWATER : 0;
-	uchar lim;
 
 	/* if caller wants random location, do it here */
 	if(x == 0 && y == 0) {
@@ -808,7 +873,7 @@
 		/* if you are to make a specific monster and it has
 		   already been genocided, return */
 		if (mvitals[mndx].mvflags & G_GENOD) return((struct monst *) 0);
-#ifdef DEBUG
+#if defined(WIZARD) && defined(DEBUG)
 		if (wizard && (mvitals[mndx].mvflags & G_EXTINCT))
 		    pline("Explicitly creating extinct monster %s.",
 			mons[mndx].mname);
@@ -832,32 +897,7 @@
 		} while(!goodpos(x, y, &fakemon, gpflags) && tryct++ < 50);
 		mndx = monsndx(ptr);
 	}
-	/* if it's unique, don't ever make it again */
-	if (ptr->geno & G_UNIQ) mvitals[mndx].mvflags |= G_EXTINCT;
-
-	/* Once a certain number of monsters are created, don't create any more
-	 * at random (i.e. make them extinct).  The previous (3.2) behavior was
-	 * to do this when a certain number had _died_, which didn't make
-	 * much sense.
-	 * This version makes a little more sense but still requires that
-	 * the caller manually decrement mvitals if the monster is created
-	 * under circumstances where one would not logically expect the
-	 * creation to reduce the supply of wild monsters.  Monster cloning
- 	 * might be one case that requires that in order to reduce the
-	 * possibility of abuse, but currently doesn't.
-	 */
-	if (mvitals[mndx].born < 255 && countbirth) mvitals[mndx].born++;
-	lim = mbirth_limit(mndx);
-	if ((int) mvitals[mndx].born >= lim && !(mons[mndx].geno & G_NOGEN) &&
-		!(mvitals[mndx].mvflags & G_EXTINCT)) {
-#ifdef DEBUG
-		pline("Automatically extinguished %s.",
-					makeplural(mons[mndx].mname));
-#endif
-		mvitals[mndx].mvflags |= G_EXTINCT;
-		reset_rndmonst(mndx);
-	}
-
+	(void) propagate(mndx, countbirth, FALSE);
 	xlth = ptr->pxlth;
 	if (mmflags & MM_EDOG) xlth += sizeof(struct edog);
 	else if (mmflags & MM_EMIN) xlth += sizeof(struct emin);
@@ -1061,6 +1101,7 @@
 mbirth_limit(mndx)
 int mndx;
 {
+	/* assert(MAXMONNO < 255); */
 	return (mndx == PM_NAZGUL ? 9 : mndx == PM_ERINYS ? 3 : MAXMONNO); 
 }
 
@@ -1171,8 +1212,10 @@
 
 	    rndmonst_state.choice_count = 0;
 	    /* look for first common monster */
-	    for (mndx = LOW_PM; mndx < SPECIAL_PM; mndx++)
+	    for (mndx = LOW_PM; mndx < SPECIAL_PM; mndx++) {
 		if (!uncommon(mndx)) break;
+		rndmonst_state.mchoices[mndx] = 0;
+	    }		
 	    if (mndx == SPECIAL_PM) {
 		/* evidently they've all been exterminated */
 #ifdef DEBUG

Index: mhitu.c
===================================================================
RCS file: /cvsroot/pkg-nethack/nethack/src/mhitu.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -d -r1.1.1.1 -r1.2
--- mhitu.c	7 Oct 2003 19:00:14 -0000	1.1.1.1
+++ mhitu.c	9 Dec 2003 16:14:43 -0000	1.2
@@ -1,4 +1,4 @@
-/*	SCCS Id: @(#)mhitu.c	3.4	2003/01/02	*/
+/*	SCCS Id: @(#)mhitu.c	3.4	2003/11/26	*/
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
 /* NetHack may be freely redistributed.  See license for details. */
 
@@ -490,15 +490,38 @@
 	    mdat = mtmp->data;
 
 	    if(!rn2(10) && !mtmp->mcan) {
-		if(youseeit) {
+	    	int numseen, numhelp;
+		char buf[BUFSZ], genericwere[BUFSZ];
+
+		Strcpy(genericwere, "creature");
+		numhelp = were_summon(mdat, FALSE, &numseen, genericwere);
+		if (youseeit) {
 			pline("%s summons help!", Monnam(mtmp));
-		} else
-			You_feel("hemmed in.");
-		/* Technically wrong; we really should check if you can see the
-		 * help, but close enough...
-		 */
-		if (!were_summon(mdat,FALSE) && youseeit)
-		    pline("But none comes.");
+			if (numhelp > 0) {
+			    if (numseen == 0)
+				You_feel("hemmed in.");
+			} else pline("But none comes.");
+		} else {
+			const char *from_nowhere;
+
+			if (flags.soundok) {
+				pline("%s %s!", Something,
+					makeplural(growl_sound(mtmp)));
+				from_nowhere = "";
+			} else from_nowhere = " from nowhere";
+			if (numhelp > 0) {
+			    if (numseen < 1) You_feel("hemmed in.");
+			    else {
+				if (numseen == 1)
+			    		Sprintf(buf, "%s appears",
+							an(genericwere));
+			    	else
+			    		Sprintf(buf, "%s appear",
+							makeplural(genericwere));
+				pline("%s%s!", upstart(buf), from_nowhere);
+			    }
+			} /* else no help came; but you didn't know it tried */
+		}
 	    }
 	}
 
@@ -1170,8 +1193,17 @@
 				    && !(poly_when_stoned(youmonst.data) &&
 					polymon(PM_STONE_GOLEM))) {
 				Stoned = 5;
-				killer_format = KILLED_BY_AN;
 				delayed_killer = mtmp->data->mname;
+				if (mtmp->data->geno & G_UNIQ) {
+				    if (!type_is_pname(mtmp->data)) {
+					static char kbuf[BUFSZ];
+
+					/* "the" buffer may be reallocated */
+					Strcpy(kbuf, the(delayed_killer));
+					delayed_killer = kbuf;
+				    }
+				    killer_format = KILLED_BY;
+				} else killer_format = KILLED_BY_AN;
 				return(1);
 				/* You("turn to stone..."); */
 				/* done_in_by(mtmp); */
@@ -1251,7 +1283,7 @@
 			pline("%s %s.", Monnam(mtmp), mtmp->minvent ?
 		    "brags about the goods some dungeon explorer provided" :
 		    "makes some remarks about how difficult theft is lately");
-			if (!tele_restrict(mtmp)) rloc(mtmp);
+			if (!tele_restrict(mtmp)) (void) rloc(mtmp, FALSE);
 			return 3;
 		} else if (mtmp->mcan) {
 		    if (!Blind) {
@@ -1261,7 +1293,7 @@
 			    flags.female ? "unaffected" : "uninterested");
 		    }
 		    if(rn2(3)) {
-			if (!tele_restrict(mtmp)) rloc(mtmp);
+			if (!tele_restrict(mtmp)) (void) rloc(mtmp, FALSE);
 			return 3;
 		    }
 		    break;
@@ -1274,7 +1306,7 @@
 			break;
 		  default:
 			if (!is_animal(mtmp->data) && !tele_restrict(mtmp))
-			    rloc(mtmp);
+			    (void) rloc(mtmp, FALSE);
 			if (is_animal(mtmp->data) && *buf) {
 			    if (canseemon(mtmp))
 				pline("%s tries to %s away with %s.",
@@ -1378,7 +1410,7 @@
 			mongone(mtmp);
 			return 2;
 		    } else if (!rn2(33)) {
-			if (!tele_restrict(mtmp)) rloc(mtmp);
+			if (!tele_restrict(mtmp)) (void) rloc(mtmp, FALSE);
 			monflee(mtmp, d(3, 6), TRUE, FALSE);
 			return 3;
 		    }
@@ -1492,9 +1524,7 @@
 	    case AD_SLIM:    
 		hitmsg(mtmp, mattk);
 		if (!uncancelled) break;
-		if (youmonst.data == &mons[PM_FIRE_VORTEX] ||
-				youmonst.data == &mons[PM_SALAMANDER] ||
-				youmonst.data == &mons[PM_FIRE_ELEMENTAL]) {
+		if (flaming(youmonst.data)) {
 		    pline_The("slime burns away!");
 		    dmg = 0;
 		} else if (Unchanging ||
@@ -1684,11 +1714,15 @@
 		    }
 		    break;
 		case AD_PHYS:
-		    if (mtmp->data == &mons[PM_FOG_CLOUD])
-			You("are laden with moisture and can barely %s!",
-				!breathless(youmonst.data) ? "breathe" :
-				"stay conscious");
-		    else {
+		    if (mtmp->data == &mons[PM_FOG_CLOUD]) {
+			You("are laden with moisture and %s",
+			    flaming(youmonst.data) ? "are smoldering out!" :
+			    Breathless ? "find it mildly uncomfortable." :
+			    amphibious(youmonst.data) ? "feel comforted." :
+			    "can barely breathe!");
+			/* NB: Amphibious includes Breathless */
+			if (Amphibious && !flaming(youmonst.data)) tmp = 0;
+		    } else {
 			You("are pummeled with debris!");
 			exercise(A_STR, FALSE);
 		    }
@@ -1836,9 +1870,11 @@
 			 u.umonnum == PM_VIOLET_FUNGUS ||
 			 dmgtype(youmonst.data, AD_STUN));
 		if (!not_affected) {
+		    boolean chg;
 		    if (!Hallucination)
-			You("are freaked by a blast of kaleidoscopic light!");
-		    make_hallucinated(HHallucination + (long)tmp,FALSE,0L);
+			You("are caught in a blast of kaleidoscopic light!");
+		    chg = make_hallucinated(HHallucination + (long)tmp,FALSE,0L);
+		    You("%s.", chg ? "are freaked out" : "seem unaffected");
 		}
 		break;
 
@@ -1864,33 +1900,33 @@
 	switch(mattk->adtyp) {
 	    case AD_STON:
 		if (mtmp->mcan || !mtmp->mcansee) {
-		    if (mtmp->data == &mons[PM_MEDUSA] && canseemon(mtmp)) {
-			if (mtmp->mcan) {
-			    pline("%s doesn't look all that ugly.",
-				  Monnam(mtmp));
-			    break;
-			}
-		    }
-		    if (canseemon(mtmp))
-			pline("%s gazes ineffectually.", Monnam(mtmp));
+		    if (!canseemon(mtmp)) break;	/* silently */
+		    pline("%s %s.", Monnam(mtmp),
+			  (mtmp->data == &mons[PM_MEDUSA] && mtmp->mcan) ?
+				"doesn't look all that ugly" :
+				"gazes ineffectually");
 		    break;
 		}
-		if (Reflecting && canspotmon(mtmp) &&
-		    mtmp->data == &mons[PM_MEDUSA]) {
-		    if(!Blind) {
-		    	(void) ureflects("%s gaze is reflected by your %s.",
-		    			s_suffix(Monnam(mtmp)));
-		    	if (mon_reflects(mtmp,
-		    			"The gaze is reflected away by %s %s!"))
-		    	    break;
-			if (!m_canseeu(mtmp)) { /* probably you're invisible */
-			    pline("%s doesn't seem to notice that %s gaze was reflected.",
-				Monnam(mtmp),
-				mhis(mtmp));
-			    break;
-			}
-			pline("%s is turned to stone!", Monnam(mtmp));
+		if (Reflecting && couldsee(mtmp->mx, mtmp->my) &&
+			mtmp->data == &mons[PM_MEDUSA]) {
+		    /* hero has line of sight to Medusa and she's not blind */
+		    boolean useeit = canseemon(mtmp);
+
+		    if (useeit)
+			(void) ureflects("%s gaze is reflected by your %s.",
+					 s_suffix(Monnam(mtmp)));
+		    if (mon_reflects(mtmp, !useeit ? (char *)0 :
+				     "The gaze is reflected away by %s %s!"))
+			break;
+		    if (!m_canseeu(mtmp)) { /* probably you're invisible */
+			if (useeit)
+			    pline(
+		      "%s doesn't seem to notice that %s gaze was reflected.",
+				  Monnam(mtmp), mhis(mtmp));
+			break;
 		    }
+		    if (useeit)
+			pline("%s is turned to stone!", Monnam(mtmp));
 		    stoned = TRUE;
 		    killed(mtmp);
 
@@ -1932,8 +1968,8 @@
 		    int stun = d(2,6);
 
 		    mtmp->mspec_used = mtmp->mspec_used + (stun + rn2(6));
-		    make_stunned(HStun + stun, TRUE);
 		    pline("%s stares piercingly at you!", Monnam(mtmp));
+		    make_stunned(HStun + stun, TRUE);
 		    stop_occupation();
 		}
 		break;
@@ -2234,7 +2270,7 @@
 	if (uarm || uarmc) {
 		verbalize("You're such a %s; I wish...",
 				flags.female ? "sweet lady" : "nice guy");
-		if (!tele_restrict(mon)) rloc(mon);
+		if (!tele_restrict(mon)) (void) rloc(mon, FALSE);
 		return 1;
 	}
 	if (u.ualign.type == A_CHAOTIC)
@@ -2366,7 +2402,7 @@
 #endif
 	}
 	if (!rn2(25)) mon->mcan = 1; /* monster is worn out */
-	if (!tele_restrict(mon)) rloc(mon);
+	if (!tele_restrict(mon)) (void) rloc(mon, FALSE);
 	return 1;
 }
 

Index: allmain.c
===================================================================
RCS file: /cvsroot/pkg-nethack/nethack/src/allmain.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -d -r1.1.1.1 -r1.2
--- allmain.c	7 Oct 2003 19:00:07 -0000	1.1.1.1
+++ allmain.c	9 Dec 2003 16:14:43 -0000	1.2
@@ -395,7 +395,7 @@
 	    }
 	    if (flags.mv) {
 		if(multi < COLNO && !--multi)
-		    flags.travel = flags.mv = flags.run = 0;
+		    flags.travel = iflags.travel1 = flags.mv = flags.run = 0;
 		domove();
 	    } else {
 		--multi;

Index: dokick.c
===================================================================
RCS file: /cvsroot/pkg-nethack/nethack/src/dokick.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -d -r1.1.1.1 -r1.2
--- dokick.c	7 Oct 2003 19:00:11 -0000	1.1.1.1
+++ dokick.c	9 Dec 2003 16:14:43 -0000	1.2
@@ -1,4 +1,4 @@
-/*	SCCS Id: @(#)dokick.c	3.4	2003/01/08	*/
+/*	SCCS Id: @(#)dokick.c	3.4	2003/12/04	*/
 /* Copyright (c) Izchak Miller, Mike Stephenson, Steve Linhart, 1989. */
 /* NetHack may be freely redistributed.  See license for details. */
 
@@ -237,13 +237,18 @@
 register struct monst *mtmp;
 register struct obj *gold;
 {
+	boolean msg_given = FALSE;
+
 	if(!likes_gold(mtmp->data) && !mtmp->isshk && !mtmp->ispriest
 			&& !is_mercenary(mtmp->data)) {
 		wakeup(mtmp);
 	} else if (!mtmp->mcanmove) {
 		/* too light to do real damage */
-		if (canseemon(mtmp))
-		    pline_The("gold hits %s.", mon_nam(mtmp));
+		if (canseemon(mtmp)) {
+		    pline_The("%s harmlessly %s %s.", xname(gold),
+			      otense(gold, "hit"), mon_nam(mtmp));
+		    msg_given = TRUE;
+		}
 	} else {
 #ifdef GOLDOBJ
                 long value = gold->quan * objects[gold->otyp].oc_cost;
@@ -317,16 +322,18 @@
 		     if (mtmp->mpeaceful)
 			    verbalize("That should do.  Now beat it!");
 		     else verbalize("That's not enough, coward!");
-		 }
+		}
 
 #ifndef GOLDOBJ
 		dealloc_obj(gold);
 #else
-                add_to_minv(mtmp, gold);
+		add_to_minv(mtmp, gold);
 #endif
-		return(1);
+		return TRUE;
 	}
-	return(0);
+
+	if (!msg_given) miss(xname(gold), mtmp);
+	return FALSE;
 }
 
 /* container is kicked, dropped, thrown or otherwise impacted by player.
@@ -603,7 +610,7 @@
 	else if (IS_SINK(maploc->typ)) what = "a sink";
 #endif
 	else if (IS_ALTAR(maploc->typ)) what = "an altar";
-	else if (IS_DRAWBRIDGE(maploc->typ)) what = "the drawbridge";
+	else if (IS_DRAWBRIDGE(maploc->typ)) what = "a drawbridge";
 	else if (maploc->typ == STAIRS) what = "the stairs";
 	else if (maploc->typ == LADDER) what = "a ladder";
 	else if (maploc->typ == IRONBARS) what = "an iron bar";
@@ -614,7 +621,7 @@
 int
 dokick()
 {
-	register int x, y;
+	int x, y;
 	int avrg_attrib;
 	register struct monst *mtmp;
 	boolean no_kick = FALSE;
@@ -995,17 +1002,17 @@
 		    exercise(A_DEX, FALSE);
 		    exercise(A_STR, FALSE);
 		    if (Blind) feel_location(x,y); /* we know we hit it */
+		    if (is_drawbridge_wall(x,y) >= 0) {
+			pline_The("drawbridge is unaffected.");
+			/* update maploc to refer to the drawbridge */
+			(void) find_drawbridge(&x,&y);
+			maploc = &levl[x][y];
+		    }
 		    if(!rn2(3)) set_wounded_legs(RIGHT_SIDE, 5 + rnd(5));
 		    losehp(rnd(ACURR(A_CON) > 15 ? 3 : 5), kickstr(buf),
 			KILLED_BY);
 		    if(Is_airlevel(&u.uz) || Levitation)
 			hurtle(-u.dx, -u.dy, rn1(2,4), TRUE); /* assume it's heavy */
-		    return(1);
-		}
-		if (is_drawbridge_wall(x,y) >= 0) {
-		    pline_The("drawbridge is unaffected.");
-		    if(Levitation)
-			hurtle(-u.dx, -u.dy, rn1(2,4), TRUE); /* it's heavy */
 		    return(1);
 		}
 		goto dumb;

Index: drawing.c
===================================================================
RCS file: /cvsroot/pkg-nethack/nethack/src/drawing.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -d -r1.1.1.1 -r1.2
--- drawing.c	7 Oct 2003 19:00:11 -0000	1.1.1.1
+++ drawing.c	9 Dec 2003 16:14:43 -0000	1.2
@@ -225,7 +225,7 @@
 	{'#', "tree",		C(CLR_GREEN)},	/* tree */
 	{'.', "floor of a room",C(CLR_GRAY)},	/* room */
 /*20*/	{'#', "corridor",	C(CLR_GRAY)},	/* dark corr */
-	{'#', "lit corridor",	C(CLR_GRAY)},	/* lit corr */
+	{'#', "lit corridor",	C(CLR_GRAY)},	/* lit corr (see mapglyph.c) */
 	{'<', "staircase up",	C(CLR_GRAY)},	/* upstair */
 	{'>', "staircase down",	C(CLR_GRAY)},	/* dnstair */
 	{'<', "ladder up",	C(CLR_BROWN)},	/* upladder */
@@ -612,8 +612,8 @@
 
 /*
  * Convert the given character to an object class.  If the character is not
- * recognized, then MAXOCLASSES is returned.  Used in invent.c, options.c,
- * pickup.c, sp_lev.c, and lev_main.c.
+ * recognized, then MAXOCLASSES is returned.  Used in detect.c invent.c,
+ * options.c, pickup.c, sp_lev.c, and lev_main.c.
  */
 int
 def_char_to_objclass(ch)

Index: vault.c
===================================================================
RCS file: /cvsroot/pkg-nethack/nethack/src/vault.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -d -r1.1.1.1 -r1.2
--- vault.c	7 Oct 2003 19:00:21 -0000	1.1.1.1
+++ vault.c	9 Dec 2003 16:14:43 -0000	1.2
@@ -44,7 +44,7 @@
 			if(mtmp->isgd) return(FALSE);
 			else if(!in_fcorridor(grd, u.ux, u.uy)) {
 			    if(mtmp->mtame) yelp(mtmp);
-			    rloc(mtmp);
+			    (void) rloc(mtmp, FALSE);
 			}
 		}
 		levl[fcx][fcy].typ = EGD(grd)->fakecorr[fcbeg].ftyp;
@@ -388,7 +388,7 @@
 		if (!IS_WALL(levl[x][y].typ) && !in_fcorridor(grd, x, y)) {
 		    if ((mon = m_at(x, y)) != 0 && mon != grd) {
 			if (mon->mtame) yelp(mon);
-			rloc(mon);
+			(void) rloc(mon, FALSE);
 		    }
 		    if ((gold = g_at(x, y)) != 0) {
 			move_gold(gold, EGD(grd)->vroom);
@@ -469,7 +469,7 @@
 	       (grd_in_vault ||
 		(in_fcorridor(grd, grd->mx, grd->my) &&
 		 !in_fcorridor(grd, u.ux, u.uy)))) {
-		rloc(grd);
+		(void) rloc(grd, FALSE);
 		wallify_vault(grd);
 		(void) clear_fcorr(grd, TRUE);
 		goto letknow;
@@ -515,7 +515,7 @@
 		if (u_carry_gold) {	/* player teleported */
 		    m = grd->mx;
 		    n = grd->my;
-		    rloc(grd);
+		    (void) rloc(grd, FALSE);
 		    levl[m][n].typ = egrd->fakecorr[0].ftyp;
 		    newsym(m,n);
 		    grd->mpeaceful = 0;
@@ -591,7 +591,7 @@
 		    /* just for insurance... */
 		    if (MON_AT(m, n) && m != grd->mx && n != grd->my) {
 			verbalize("Out of my way, scum!");
-			rloc(m_at(m, n));
+			(void) rloc(m_at(m, n), FALSE);
 		    }
 		    remove_monster(grd->mx, grd->my);
 		    newsym(grd->mx, grd->my);

Index: pline.c
===================================================================
RCS file: /cvsroot/pkg-nethack/nethack/src/pline.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -d -r1.1.1.1 -r1.2
--- pline.c	7 Oct 2003 19:00:17 -0000	1.1.1.1
+++ pline.c	9 Dec 2003 16:14:43 -0000	1.2
@@ -248,6 +248,9 @@
 impossible VA_DECL(const char *, s)
 	VA_START(s);
 	VA_INIT(s, const char *);
+	if (program_state.in_impossible)
+		panic("impossible called impossible");
+	program_state.in_impossible = 1;
 	{
 	    char pbuf[BUFSZ];
 	    Vsprintf(pbuf,s,VA_ARGS);
@@ -255,6 +258,7 @@
 	}
 	vpline(s,VA_ARGS);
 	pline("Program in disorder - perhaps you'd better #quit.");
+	program_state.in_impossible = 0;
 	VA_END();
 }
 

Index: mhitm.c
===================================================================
RCS file: /cvsroot/pkg-nethack/nethack/src/mhitm.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -d -r1.1.1.1 -r1.2
--- mhitm.c	7 Oct 2003 19:00:13 -0000	1.1.1.1
+++ mhitm.c	9 Dec 2003 16:14:43 -0000	1.2
@@ -153,6 +153,16 @@
 		     */
 		    if (has_u_swallowed) return 0;
 
+		    /* Allow attacked monsters a chance to hit back. Primarily
+		     * to allow monsters that resist conflict to respond.
+		     */
+		    if ((result & MM_HIT) && !(result & MM_DEF_DIED) &&
+			rn2(4) && mon->movement >= NORMAL_SPEED) {
+			mon->movement -= NORMAL_SPEED;
+			notonhead = 0;
+			(void) mattackm(mon, mtmp);	/* return attack */
+		    }
+
 		    return ((result & MM_HIT) ? 1 : 0);
 		}
 	    }
@@ -195,7 +205,7 @@
     struct permonst *pa, *pd;
 
     if (!magr || !mdef) return(MM_MISS);		/* mike@genat */
-    if (!magr->mcanmove) return(MM_MISS);		/* riv05!a3 */
+    if (!magr->mcanmove || magr->msleeping) return(MM_MISS);
     pa = magr->data;  pd = mdef->data;
 
     /* Grid bugs cannot attack at an angle. */
@@ -214,8 +224,12 @@
     if (mdef->mundetected) {
 	mdef->mundetected = 0;
 	newsym(mdef->mx, mdef->my);
-	if(canseemon(mdef) && !sensemon(mdef))
-	    pline("Suddenly, you notice %s.", a_monnam(mdef));
+	if(canseemon(mdef) && !sensemon(mdef)) {
+	    if (u.usleep) You("dream of %s.",
+				(mdef->data->geno & G_UNIQ) ?
+				a_monnam(mdef) : makeplural(m_monnam(mdef)));
+	    else pline("Suddenly, you notice %s.", a_monnam(mdef));
+	}
     }
 
     /* Elves hate orcs. */
@@ -282,7 +296,7 @@
 		       && otmp && objects[otmp->otyp].oc_material == IRON
 		       && mdef->mhp > 1 && !mdef->mcan)
 		    {
-			if (clone_mon(mdef)) {
+			if (clone_mon(mdef, 0, 0)) {
 			    if (vis) {
 				char buf[BUFSZ];
 
@@ -841,7 +855,7 @@
 		       we'll get "it" in the suddenly disappears message */
 		    if (vis) Strcpy(mdef_Monnam, Monnam(mdef));
 		    mdef->mstrategy &= ~STRAT_WAITFORU;
-		    rloc(mdef);
+		    (void) rloc(mdef, FALSE);
 		    if (vis && !canspotmon(mdef)
 #ifdef STEED
 		    	&& mdef != u.usteed
@@ -969,7 +983,7 @@
 		    pline("%s steals some gold from %s.", buf, mon_nam(mdef));
 		}
 		if (!tele_restrict(magr)) {
-		    rloc(magr);
+		    (void) rloc(magr, FALSE);
 		    if (vis && !canspotmon(magr))
 			pline("%s suddenly disappears!", buf);
 		}
@@ -1036,7 +1050,7 @@
 							0 : MM_AGR_DIED));
 			if (magr->data->mlet == S_NYMPH &&
 			    !tele_restrict(magr)) {
-			    rloc(magr);
+			    (void) rloc(magr, FALSE);
 			    if (vis && !canspotmon(magr))
 				pline("%s suddenly disappears!", buf);
 			}
@@ -1095,9 +1109,7 @@
 		break;
 	    case AD_SLIM:
 		if (cancelled) break;	/* physical damage only */
-		if (!rn2(4) && mdef->data != &mons[PM_FIRE_VORTEX] &&
-				mdef->data != &mons[PM_FIRE_ELEMENTAL] &&
-				mdef->data != &mons[PM_SALAMANDER] &&
+		if (!rn2(4) && !flaming(mdef->data) &&
 				mdef->data != &mons[PM_GREEN_SLIME]) {
 		    (void) newcham(mdef, &mons[PM_GREEN_SLIME], FALSE, vis);
 		    mdef->mstrategy &= ~STRAT_WAITFORU;

Index: decl.c
===================================================================
RCS file: /cvsroot/pkg-nethack/nethack/src/decl.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -d -r1.1.1.1 -r1.2
--- decl.c	7 Oct 2003 19:00:09 -0000	1.1.1.1
+++ decl.c	9 Dec 2003 16:14:43 -0000	1.2
@@ -239,7 +239,7 @@
 	"Nothing happens.",		"That's enough tries!",
 	"That is a silly thing to %s.",	"shudder for a moment.",
 	"something", "Something", "You can move again.", "Never mind.",
-	"vision quickly clears."
+	"vision quickly clears.", {"the", "your"}
 };
 
 /* NOTE: the order of these words exactly corresponds to the

Index: mkmaze.c
===================================================================
RCS file: /cvsroot/pkg-nethack/nethack/src/mkmaze.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -d -r1.1.1.1 -r1.2
--- mkmaze.c	7 Oct 2003 19:00:14 -0000	1.1.1.1
+++ mkmaze.c	9 Dec 2003 16:14:43 -0000	1.2
@@ -308,7 +308,7 @@
 	/* "something" means the player in this case */
 	if(MON_AT(x, y)) {
 	    /* move the monster if no choice, or just try again */
-	    if(oneshot) rloc(m_at(x,y));
+	    if(oneshot) (void) rloc(m_at(x,y), FALSE);
 	    else return(FALSE);
 	}
 	u_on_newpos(x, y);
@@ -1142,6 +1142,34 @@
 	ebubbles = b;
 	b->next = (struct bubble *)0;
 	was_waterlevel = TRUE;
+}
+
+const char *waterbody_name(x, y)
+xchar x,y;
+{
+	register struct rm *lev;
+	schar ltyp;
+
+	if (!isok(x,y))
+		return "drink";		/* should never happen */
+	lev = &levl[x][y];
+	ltyp = lev->typ;
+
+	if (is_lava(x,y))
+		return "lava";
+	else if (ltyp == ICE ||
+		 (ltyp == DRAWBRIDGE_UP &&
+		  (levl[x][y].drawbridgemask & DB_UNDER) == DB_ICE))
+		return "ice";
+	else if (((ltyp != POOL) && (ltyp != WATER) &&
+	  !Is_medusa_level(&u.uz) && !Is_waterlevel(&u.uz) && !Is_juiblex_level(&u.uz)) ||
+	   (ltyp == DRAWBRIDGE_UP && (levl[x][y].drawbridgemask & DB_UNDER) == DB_MOAT))
+		return "moat";
+	else if ((ltyp != POOL) && (ltyp != WATER) && Is_juiblex_level(&u.uz))
+		return "swamp";
+	else if (ltyp == POOL)
+		return "pool of water";
+	else return "water";
 }
 
 STATIC_OVL void

Index: mplayer.c
===================================================================
RCS file: /cvsroot/pkg-nethack/nethack/src/mplayer.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -d -r1.1.1.1 -r1.2
--- mplayer.c	7 Oct 2003 19:00:15 -0000	1.1.1.1
+++ mplayer.c	9 Dec 2003 16:14:43 -0000	1.2
@@ -121,7 +121,7 @@
 		return((struct monst *)0);
 
 	if(MON_AT(x, y))
-		rloc(m_at(x, y)); /* insurance */
+		(void) rloc(m_at(x, y), FALSE); /* insurance */
 
 	if(!In_endgame(&u.uz)) special = FALSE;
 

Index: dbridge.c
===================================================================
RCS file: /cvsroot/pkg-nethack/nethack/src/dbridge.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -d -r1.1.1.1 -r1.2
--- dbridge.c	7 Oct 2003 19:00:09 -0000	1.1.1.1
+++ dbridge.c	9 Dec 2003 16:14:43 -0000	1.2
@@ -410,6 +410,8 @@
 		/* we might have crawled out of the moat to survive */
 		etmp->ex = u.ux,  etmp->ey = u.uy;
 	} else {
+		int entitycnt;
+
 		killer = 0;
 		/* fake "digested to death" damage-type suppresses corpse */
 #define mk_message(dest) ((dest & 1) ? "" : (char *)0)
@@ -420,6 +422,13 @@
 		else		/* you caused it */
 		    xkilled(etmp->emon, dest);
 		etmp->edata = (struct permonst *)0;
+
+		/* dead long worm handling */
+		for (entitycnt = 0; entitycnt < ENTITIES; entitycnt++) {
+		    if (etmp != &(occupants[entitycnt]) &&
+			etmp->emon == occupants[entitycnt].emon)
+			occupants[entitycnt].edata = (struct permonst *)0;
+		}
 #undef mk_message
 #undef mk_corpse
 	}

Index: steed.c
===================================================================
RCS file: /cvsroot/pkg-nethack/nethack/src/steed.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -d -r1.1.1.1 -r1.2
--- steed.c	7 Oct 2003 19:00:19 -0000	1.1.1.1
+++ steed.c	9 Dec 2003 16:14:43 -0000	1.2
@@ -79,7 +79,7 @@
 	    return 1;
 	}
 	ptr = mtmp->data;
-	if (touch_petrifies(ptr) && !Stone_resistance) {
+	if (touch_petrifies(ptr) && !uarmg && !Stone_resistance) {
 	    char kbuf[BUFSZ];
 
 	    You("touch %s.", mon_nam(mtmp));
@@ -424,7 +424,7 @@
     boolean found = FALSE;
     struct trap *t;
 
-    /* avoid known traps (i == 0), but allow them as a backup */
+    /* avoid known traps (i == 0) and boulders, but allow them as a backup */
     if (reason != DISMOUNT_BYCHOICE || Stunned || Confusion || Fumbling) i = 1;
     for (; !found && i < 2; ++i) {
 	for (x = u.ux-1; x <= u.ux+1; x++)
@@ -436,7 +436,9 @@
 		    distance = distu(x,y);
 		    if (min_distance < 0 || distance < min_distance ||
 			    (distance == min_distance && rn2(2))) {
-			if (i > 0 || (t = t_at(x, y)) == 0 || !t->tseen) {
+			if (i > 0 || (((t = t_at(x, y)) == 0 || !t->tseen) &&
+				      (!sobj_at(BOULDER, x, y) ||
+				       throws_rocks(youmonst.data)))) {
 			    spot->x = x;
 			    spot->y = y;
 			    min_distance = distance;
@@ -535,7 +537,7 @@
 	    if (enexto(&cc, u.ux, u.uy, mtmp->data))
 		rloc_to(mtmp, cc.x, cc.y);
 	    else	/* evidently no room nearby; move steed elsewhere */
-		rloc(mtmp);
+		(void) rloc(mtmp, FALSE);
 	    return;
 	}
 	if (!DEADMONSTER(mtmp)) {

Index: restore.c
===================================================================
RCS file: /cvsroot/pkg-nethack/nethack/src/restore.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -d -r1.1.1.1 -r1.2
--- restore.c	7 Oct 2003 19:00:18 -0000	1.1.1.1
+++ restore.c	9 Dec 2003 16:14:43 -0000	1.2
@@ -1,4 +1,4 @@
-/*	SCCS Id: @(#)restore.c	3.4	2002/08/21	*/
+/*	SCCS Id: @(#)restore.c	3.4	2003/09/06	*/
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
 /* NetHack may be freely redistributed.  See license for details. */
 
@@ -270,6 +270,13 @@
 		if (moved && mtmp->data) {
 			int offset = mtmp->data - monbegin;	/*(ptrdiff_t)*/
 			mtmp->data = mons + offset;  /* new permonst location */
+		}
+		if (ghostly) {
+			int mndx = monsndx(mtmp->data);
+			if (propagate(mndx, TRUE, ghostly) == 0) {
+				/* cookie to trigger purge in getbones() */
+				mtmp->mhpmax = DEFUNCT_MONSTER;	
+			}
 		}
 		if(mtmp->minvent) {
 			struct obj *obj;

Index: save.c
===================================================================
RCS file: /cvsroot/pkg-nethack/nethack/src/save.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -d -r1.1.1.1 -r1.2
--- save.c	7 Oct 2003 19:00:18 -0000	1.1.1.1
+++ save.c	9 Dec 2003 16:14:43 -0000	1.2
@@ -1,4 +1,4 @@
-/*	SCCS Id: @(#)save.c	3.4	2002/08/22	*/
+/*	SCCS Id: @(#)save.c	3.4	2003/11/14	*/
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
 /* NetHack may be freely redistributed.  See license for details. */
 
@@ -1012,6 +1012,9 @@
 	if (iflags.wc_font_menu) free(iflags.wc_font_menu);
 	if (iflags.wc_font_status) free(iflags.wc_font_status);
 	if (iflags.wc_tile_file) free(iflags.wc_tile_file);
+#ifdef AUTOPICKUP_EXCEPTIONS
+	free_autopickup_exceptions();
+#endif
 
 #endif	/* FREE_ALL_MEMORY */
 	return;

Index: worm.c
===================================================================
RCS file: /cvsroot/pkg-nethack/nethack/src/worm.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -d -r1.1.1.1 -r1.2
--- worm.c	7 Oct 2003 19:00:21 -0000	1.1.1.1
+++ worm.c	9 Dec 2003 16:14:43 -0000	1.2
@@ -341,7 +341,7 @@
     while ( (curr->wx != x) || (curr->wy != y) ) {
 	curr = curr->nseg;
 	if (!curr) {
-	    impossible("cut_worm:  no segment at (%d,%d)", (int) x, (int) y);
+	    impossible("cutworm: no segment at (%d,%d)", (int) x, (int) y);
 	    return;
 	}
     }
@@ -368,27 +368,19 @@
 
     /* Sometimes the tail end dies. */
     if (rn2(3) || !(new_wnum = get_wormno())) {
-	You("cut part of the tail off of %s.", mon_nam(worm));
+	if (flags.mon_moving)
+	    pline("Part of the tail of %s is cut off.", mon_nam(worm));
+	else
+	    You("cut part of the tail off of %s.", mon_nam(worm));
 	toss_wsegs(new_tail, TRUE);
 	if (worm->mhp > 1) worm->mhp /= 2;
 	return;
     }
 
-    /* Create the second worm. */
-    new_worm  = newmonst(0);
-    *new_worm = *worm;			/* make a copy of the old worm */
-    new_worm->m_id = flags.ident++;	/* make sure it has a unique id */
+    remove_monster(x, y);		/* clone_mon puts new head here */
+    new_worm = clone_mon(worm, x, y);
     new_worm->wormno = new_wnum;	/* affix new worm number */
 
-    if (worm->mtame)
-	new_worm->mtame = (rn2(max(2 + u.uluck, 2)) ? worm->mtame : 0);
-    else
-	if (worm->mpeaceful)
-	    new_worm->mpeaceful = (rn2(max(2 + u.uluck, 2)) ? 1 : 0);
-    set_malign(new_worm);
-
-    new_worm->mxlth = new_worm->mnamelth = 0;
-
     /* Devalue the monster level of both halves of the worm. */
     worm->m_lev = ((unsigned)worm->m_lev <= 3) ?
 		   (unsigned)worm->m_lev : max((unsigned)worm->m_lev - 2, 3);
@@ -403,14 +395,6 @@
 	if (worm->mhpmax < worm->mhp) worm->mhp = worm->mhpmax;
     }
 
-    /* Add new monster to mon chain. */
-    new_worm->nmon = fmon;
-    fmon = new_worm;
-
-    /* Initialize the new worm. */
-    place_monster(new_worm, x, y);	/* put worm in level.monsters[][] */
-    newsym(x, y);			/* make sure new worm shows up */
-
     wtails[new_wnum] = new_tail;	/* We've got all the info right now */
     wheads[new_wnum] = curr;		/* so we can do this faster than    */
     wgrowtime[new_wnum] = 0L;		/* trying to call initworm().       */
@@ -418,14 +402,10 @@
     /* Place the new monster at all the segment locations. */
     place_wsegs(new_worm);
 
-#if 0	/* long worms don't glow in the dark... */
-    if (emits_light(worm->data))
-	new_light_source(new_worm->mx, new_worm->my,
-			 emits_light(worm->data),
-			 LS_MONSTER, (genericptr_t)new_worm);
-#endif
-
-    You("cut %s in half.", mon_nam(worm));
+    if (flags.mon_moving)
+	pline("%s is cut in half.", Monnam(worm));
+    else
+	You("cut %s in half.", mon_nam(worm));
 }
 
 
@@ -446,6 +426,30 @@
 
     while (curr != wheads[worm->wormno]) {
 	newsym(curr->wx,curr->wy);
+	curr = curr->nseg;
+    }
+}
+
+/*
+ *  detect_wsegs()
+ *
+ *  Display all of the segments of the given worm for detection.
+ */
+void
+detect_wsegs(worm, use_detection_glyph)
+    struct monst *worm;
+    boolean use_detection_glyph;
+{
+    int num;
+    struct wseg *curr = wtails[worm->wormno];
+
+/*  if (!mtmp->wormno) return;  bullet proofing */
+
+    while (curr != wheads[worm->wormno]) {
+	num = use_detection_glyph ?
+		detected_monnum_to_glyph(what_mon(PM_LONG_WORM_TAIL)) :
+		monnum_to_glyph(what_mon(PM_LONG_WORM_TAIL));
+	show_glyph(curr->wx,curr->wy,num);
 	curr = curr->nseg;
     }
 }

Index: monmove.c
===================================================================
RCS file: /cvsroot/pkg-nethack/nethack/src/monmove.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -d -r1.1.1.1 -r1.2
--- monmove.c	7 Oct 2003 19:00:15 -0000	1.1.1.1
+++ monmove.c	9 Dec 2003 16:14:43 -0000	1.2
@@ -231,7 +231,7 @@
 		if (fleetime == 1) fleetime++;
 		mtmp->mfleetim = min(fleetime, 127);
 	    }
-	    if (!mtmp->mflee && fleemsg && canseemon(mtmp))
+	    if (!mtmp->mflee && fleemsg && canseemon(mtmp) && !mtmp->mfrozen)
 		pline("%s turns to flee!", (Monnam(mtmp)));
 	    mtmp->mflee = 1;
 	}
@@ -344,7 +344,7 @@
 	/* some monsters teleport */
 	if (mtmp->mflee && !rn2(40) && can_teleport(mdat) && !mtmp->iswiz &&
 	    !level.flags.noteleport) {
-		rloc(mtmp);
+		(void) rloc(mtmp, FALSE);
 		return(0);
 	}
 	if (mdat->msound == MS_SHRIEK && !um_dist(mtmp->mx, mtmp->my, 1))
@@ -387,7 +387,7 @@
 
 			if (is_demon(youmonst.data)) {
 			  /* "Good hunting, brother" */
-			    if (!tele_restrict(mtmp)) rloc(mtmp);
+			    if (!tele_restrict(mtmp)) (void) rloc(mtmp, FALSE);
 			} else {
 			    mtmp->minvis = mtmp->perminvis = 0;
 			    /* Why?  For the same reason in real demon talk */
@@ -458,11 +458,15 @@
 
 	    /* The scared check is necessary.  Otherwise a monster that is
 	     * one square near the player but fleeing into a wall would keep	
-	     * switching between pick-axe and weapon.
+	     * switching between pick-axe and weapon.  If monster is stuck
+	     * in a trap, prefer ranged weapon (wielding is done in thrwmu).
+	     * This may cost the monster an attack, but keeps the monster
+	     * from switching back and forth if carrying both.
 	     */
 	    mw_tmp = MON_WEP(mtmp);
 	    if (!(scared && mw_tmp && is_pick(mw_tmp)) &&
-		    mtmp->weapon_check == NEED_WEAPON) {
+		mtmp->weapon_check == NEED_WEAPON &&
+		!(mtmp->mtrapped && !nearby && select_rwep(mtmp))) {
 		mtmp->weapon_check = NEED_HTH_WEAPON;
 		if (mon_wield_item(mtmp) != 0) return(0);
 	    }
@@ -697,7 +701,7 @@
 	if(ptr == &mons[PM_TENGU] && !rn2(5) && !mtmp->mcan &&
 	   !tele_restrict(mtmp)) {
 	    if(mtmp->mhp < 7 || mtmp->mpeaceful || rn2(2))
-		rloc(mtmp);
+		(void) rloc(mtmp, FALSE);
 	    else
 		mnexto(mtmp);
 	    mmoved = 1;
@@ -1031,7 +1035,7 @@
 	    if (mtmp->wormno) worm_move(mtmp);
 	} else {
 	    if(is_unicorn(ptr) && rn2(2) && !tele_restrict(mtmp)) {
-		rloc(mtmp);
+		(void) rloc(mtmp, FALSE);
 		return(1);
 	    }
 	    if(mtmp->wormno) worm_nomove(mtmp);

Index: hack.c
===================================================================
RCS file: /cvsroot/pkg-nethack/nethack/src/hack.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -d -r1.1.1.1 -r1.2
--- hack.c	7 Oct 2003 19:00:13 -0000	1.1.1.1
+++ hack.c	9 Dec 2003 16:14:43 -0000	1.2
@@ -646,11 +646,17 @@
 	    return FALSE;
 	}
     }
-    /* pick a path that does not require crossing a trap */
-    if (flags.run == 8 && mode != DO_MOVE) {
+    /* Pick travel path that does not require crossing a trap.
+     * Avoid water and lava using the usual running rules.
+     * (but not u.ux/u.uy because findtravelpath walks toward u.ux/u.uy) */
+    if (flags.run == 8 && mode != DO_MOVE && (x != u.ux || y != u.uy)) {
 	struct trap* t = t_at(x, y);
 
-	if (t && t->tseen) return FALSE;
+	if ((t && t->tseen) ||
+	    (!Levitation && !Flying &&
+	     !is_clinger(youmonst.data) &&
+	     (is_pool(x, y) || is_lava(x, y)) && levl[x][y].seenv))
+	    return FALSE;
     }
 
     ust = &levl[ux][uy];
@@ -707,6 +713,18 @@
 findtravelpath(guess)
 boolean guess;
 {
+    /* if travel to adjacent, reachable location, use normal movement rules */
+    if (!guess && iflags.travel1 && distmin(u.ux, u.uy, u.tx, u.ty) == 1) {
+	flags.run = 0;
+	if (test_move(u.ux, u.uy, u.tx-u.ux, u.ty-u.uy, TEST_MOVE)) {
+	    u.dx = u.tx-u.ux;
+	    u.dy = u.ty-u.uy;
+	    nomul(0);
+	    iflags.travelcc.x = iflags.travelcc.y = -1;
+	    return TRUE;
+	}
+	flags.run = 8;
+    }
     if (u.tx != u.ux || u.ty != u.uy) {
 	xchar travel[COLNO][ROWNO];
 	xchar travelstepx[2][COLNO*ROWNO];
@@ -792,15 +810,25 @@
 	/* if guessing, find best location in travel matrix and go there */
 	if (guess) {
 	    int px = tx, py = ty;	/* pick location */
-	    int dist, nxtdist;
+	    int dist, nxtdist, d2, nd2;
 
 	    dist = distmin(ux, uy, tx, ty);
+	    d2 = dist2(ux, uy, tx, ty);
 	    for (tx = 1; tx < COLNO; ++tx)
 		for (ty = 0; ty < ROWNO; ++ty)
 		    if (travel[tx][ty]) {
 			nxtdist = distmin(ux, uy, tx, ty);
-			if (nxtdist < dist && couldsee(tx, ty)) {
-			    px = tx; py = ty; dist = nxtdist;
+			if (nxtdist == dist && couldsee(tx, ty)) {
+			    nd2 = dist2(ux, uy, tx, ty);
+			    if (nd2 < d2) {
+				/* prefer non-zigzag path */
+				px = tx; py = ty;
+				d2 = nd2;
+			    }
+			} else if (nxtdist < dist && couldsee(tx, ty)) {
+			    px = tx; py = ty;
+			    dist = nxtdist;
+			    d2 = dist2(ux, uy, tx, ty);
 			}
 		    }
 
@@ -847,9 +875,11 @@
 
 	u_wipe_engr(rnd(5));
 
-	if (flags.travel)
+	if (flags.travel) {
 	    if (!findtravelpath(FALSE))
 		(void) findtravelpath(TRUE);
+	    iflags.travel1 = 0;
+	}
 
 	if(((wtcap = near_capacity()) >= OVERLOADED
 	    || (wtcap > SLT_ENCUMBER &&
@@ -1428,7 +1458,6 @@
 spoteffects(pick)
 boolean pick;
 {
-	register struct trap *trap;
 	register struct monst *mtmp;
 
 	if(u.uinwater) {
@@ -1486,11 +1515,16 @@
 	if(IS_SINK(levl[u.ux][u.uy].typ) && Levitation)
 		dosinkfall();
 #endif
-	if (pick && !in_steed_dismounting)
-		(void) pickup(1);
-	/* if dismounting, we'll check again later */
-	if ((trap = t_at(u.ux,u.uy)) != 0 && !in_steed_dismounting)
-		dotrap(trap, 0);	/* fall into pit, arrow trap, etc. */
+	if (!in_steed_dismounting) { /* if dismounting, we'll check again later */
+		struct trap *trap = t_at(u.ux, u.uy);
+		boolean pit;
+		pit = (trap && (trap->ttyp == PIT || trap->ttyp == SPIKED_PIT));
+		if (trap && pit)
+			dotrap(trap, 0);	/* fall into pit */
+		if (pick) (void) pickup(1);
+		if (trap && !pit)
+			dotrap(trap, 0);	/* fall into arrow trap, etc. */
+	}
 	if((mtmp = m_at(u.ux, u.uy)) && !u.uswallow) {
 		mtmp->mundetected = mtmp->msleeping = 0;
 		switch(mtmp->data->mlet) {
@@ -1802,7 +1836,8 @@
 dopickup()
 {
 	int count;
-	/* awful kludge to work around parse()'s pre-decrement */
+	struct trap *traphere = t_at(u.ux, u.uy);
+ 	/* awful kludge to work around parse()'s pre-decrement */
 	count = (multi || (save_cm && *save_cm == ',')) ? multi + 1 : 0;
 	multi = 0;	/* always reset */
 	/* uswallow case added by GAN 01/29/87 */
@@ -1855,6 +1890,20 @@
 		You("cannot reach the %s.", surface(u.ux,u.uy));
 		return(0);
 	}
+
+ 	if (traphere && traphere->tseen) {
+		/* Allow pickup from holes and trap doors that you escaped from
+		 * because that stuff is teetering on the edge just like you, but
+		 * not pits, because there is an elevation discrepancy with stuff
+		 * in pits.
+		 */
+		if ((traphere->ttyp == PIT || traphere->ttyp == SPIKED_PIT) &&
+		     (!u.utrap || (u.utrap && u.utraptype != TT_PIT))) {
+			You("cannot reach the bottom of the pit.");
+			return(0);
+		}
+	}
+
 	return (pickup(-count));
 }
 
@@ -2022,7 +2071,7 @@
 	u.uinvulnerable = FALSE;	/* Kludge to avoid ctrl-C bug -dlc */
 	u.usleep = 0;
 	multi = nval;
-	flags.travel = flags.mv = flags.run = 0;
+	flags.travel = iflags.travel1 = flags.mv = flags.run = 0;
 }
 
 /* called when a non-movement, multi-turn action has completed */

Index: weapon.c
===================================================================
RCS file: /cvsroot/pkg-nethack/nethack/src/weapon.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -d -r1.1.1.1 -r1.2
--- weapon.c	7 Oct 2003 19:00:21 -0000	1.1.1.1
+++ weapon.c	9 Dec 2003 16:14:43 -0000	1.2
@@ -916,7 +916,7 @@
 		/* Print headings for skill types */
 		any.a_void = 0;
 		if (i == skill_ranges[pass].first)
-		    add_menu(win, NO_GLYPH, &any, 0, 0, ATR_BOLD,
+		    add_menu(win, NO_GLYPH, &any, 0, 0, iflags.menu_headings,
 			     skill_ranges[pass].name, MENU_UNSELECTED);
 
 		if (P_RESTRICTED(i)) continue;

Index: do.c
===================================================================
RCS file: /cvsroot/pkg-nethack/nethack/src/do.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -d -r1.1.1.1 -r1.2
--- do.c	7 Oct 2003 19:00:10 -0000	1.1.1.1
+++ do.c	9 Dec 2003 16:14:43 -0000	1.2
@@ -1,4 +1,4 @@
-/*	SCCS Id: @(#)do.c	3.4	2003/04/25	*/
+/*	SCCS Id: @(#)do.c	3.4	2003/12/02	*/
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
 /* NetHack may be freely redistributed.  See license for details. */
 
@@ -66,7 +66,7 @@
 	    impossible("Not a boulder?");
 	else if (!Is_waterlevel(&u.uz) && (is_pool(rx,ry) || is_lava(rx,ry))) {
 	    boolean lava = is_lava(rx,ry), fills_up;
-	    const char *what = lava ? "lava" : "water";
+	    const char *what = waterbody_name(rx,ry);
 	    schar ltyp = levl[rx][ry].typ;
 	    int chance = rn2(10);		/* water: 90%; lava: 10% */
 	    fills_up = lava ? chance == 0 : chance != 0;
@@ -94,13 +94,9 @@
 	    if (!fills_up || !pushing) {	/* splashing occurs */
 		if (!u.uinwater) {
 		    if (pushing ? !Blind : cansee(rx,ry)) {
-			boolean moat = (ltyp != WATER) &&
-			    !Is_medusa_level(&u.uz) && !Is_waterlevel(&u.uz);
-
 			There("is a large splash as %s %s the %s.",
 			      the(xname(otmp)), fills_up? "fills":"falls into",
-			      lava ? "lava" : ltyp==POOL ? "pool" :
-			      moat ? "moat" : "water");
+			      what);
 		    } else if (flags.soundok)
 			You_hear("a%s splash.", lava ? " sizzling" : "");
 		    wake_nearto(rx, ry, 40);
@@ -198,14 +194,33 @@
 		return fire_damage(obj, FALSE, FALSE, x, y);
 	} else if (is_pool(x, y)) {
 		/* Reasonably bulky objects (arbitrary) splash when dropped.
+		 * If you're floating above the water even small things make noise.
 		 * Stuff dropped near fountains always misses */
-		if (Blind && flags.soundok && ((x == u.ux) && (y == u.uy)) &&
-		    weight(obj) > 9) {
-		    pline("Splash!");
+		if ((Blind || (Levitation || Flying)) && flags.soundok &&
+		    ((x == u.ux) && (y == u.uy))) {
+		    if (!Underwater) {
+			if (weight(obj) > 9) {
+				pline("Splash!");
+		        } else if (Levitation || Flying) {
+				pline("Plop!");
+		        }
+		    }
 		    map_background(x, y, 0);
 		    newsym(x, y);
 		}
 		water_damage(obj, FALSE, FALSE);
+	} else if (u.ux == x && u.uy == y &&
+		(!u.utrap || u.utraptype != TT_PIT) &&
+		(t = t_at(x,y)) != 0 && t->tseen &&
+			(t->ttyp==PIT || t->ttyp==SPIKED_PIT)) {
+		/* you escaped a pit and are standing on the precipice */
+		if (Blind && flags.soundok)
+			You_hear("%s %s downwards.",
+				The(xname(obj)), otense(obj, "tumble"));
+		else
+			pline("%s %s into %s pit.",
+				The(xname(obj)), otense(obj, "tumble"),
+				the_your[t->madeby_u]);
 	}
 	return FALSE;
 }
@@ -405,20 +420,18 @@
 		return(FALSE);
 	}
 	if (obj->otyp == LOADSTONE && obj->cursed) {
-		if (*word)
-			pline("For some reason, you cannot %s the stone%s!",
-				word, plur(obj->quan));
-		/* Kludge -- see invent.c */
-		if (obj->corpsenm) {
-			struct obj *otmp;
-
-			otmp = obj;
-			obj = obj->nobj;
-			obj->quan += otmp->quan;
-			obj->owt = weight(obj);
-			freeinv(otmp);
-			obfree(otmp, obj);
+		/* getobj() kludge sets corpsenm to user's specified count
+		   when refusing to split a stack of cursed loadstones */
+		if (*word) {
+			/* getobj() ignores a count for throwing since that is
+			   implicitly forced to be 1; replicate its kludge... */
+			if (!strcmp(word, "throw") && obj->quan > 1L)
+			    obj->corpsenm = 1;
+			pline("For some reason, you cannot %s%s the stone%s!",
+			      word, obj->corpsenm ? " any of" : "",
+			      plur(obj->quan));
 		}
+		obj->corpsenm = 0;		/* reset */
 		obj->bknown = 1;
 		return(FALSE);
 	}
@@ -693,14 +706,20 @@
 	    for (i = 0; i < n; i++) {
 		otmp = pick_list[i].item.a_obj;
 		cnt = pick_list[i].count;
-		if (cnt < otmp->quan && !welded(otmp) &&
-			(!otmp->cursed || otmp->otyp != LOADSTONE)) {
+		if (cnt < otmp->quan) {
+		    if (welded(otmp)) {
+			;	/* don't split */
+		    } else if (otmp->otyp == LOADSTONE && otmp->cursed) {
+			/* same kludge as getobj(), for canletgo()'s use */
+			otmp->corpsenm = (int) cnt;	/* don't split */
+		    } else {
 #ifndef GOLDOBJ
-		    if (otmp->oclass == COIN_CLASS)
-			(void) splitobj(otmp, otmp->quan - cnt);
-		    else
+			if (otmp->oclass == COIN_CLASS)
+			    (void) splitobj(otmp, otmp->quan - cnt);
+			else
 #endif
-		    otmp = splitobj(otmp, cnt);
+			    otmp = splitobj(otmp, cnt);
+		    }
 		}
 		n_dropped += drop(otmp);
 	    }
@@ -772,8 +791,14 @@
 		if (!(trap = t_at(u.ux,u.uy)) ||
 			(trap->ttyp != TRAPDOOR && trap->ttyp != HOLE)
 			|| !Can_fall_thru(&u.uz) || !trap->tseen) {
-			You_cant("go down here.");
-			return(0);
+
+			if (flags.autodig && !flags.nopick &&
+				uwep && is_pick(uwep)) {
+				return use_pick_axe2(uwep);
+			} else {
+				You_cant("go down here.");
+				return(0);
+			}
 		}
 	}
 	if(u.ustuck) {
@@ -1090,6 +1115,7 @@
 	/* do this prior to level-change pline messages */
 	vision_reset();		/* clear old level's line-of-sight */
 	vision_full_recalc = 0;	/* don't let that reenable vision yet */
+	flush_screen(-1);	/* ensure all map flushes are postponed */
 
 	if (portal && !In_endgame(&u.uz)) {
 	    /* find the portal on the new level */
@@ -1220,7 +1246,7 @@
 
 	    if ((mtmp = m_at(u.ux, u.uy)) != 0) {
 		impossible("mnexto failed (do.c)?");
-		rloc(mtmp);
+		(void) rloc(mtmp, FALSE);
 	    }
 	}
 
@@ -1238,7 +1264,7 @@
 	/* Reset the screen. */
 	vision_reset();		/* reset the blockages */
 	docrt();		/* does a full vision recalc */
-	flush_screen(1);
+	flush_screen(-1);
 
 	/*
 	 *  Move all plines beyond the screen reset.

Index: mkobj.c
===================================================================
RCS file: /cvsroot/pkg-nethack/nethack/src/mkobj.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -d -r1.1.1.1 -r1.2
--- mkobj.c	7 Oct 2003 19:00:14 -0000	1.1.1.1
+++ mkobj.c	9 Dec 2003 16:14:43 -0000	1.2
@@ -915,7 +915,11 @@
 
 	if (objtype != CORPSE && objtype != STATUE)
 	    impossible("making corpstat type %d", objtype);
-	otmp = mksobj_at(objtype, x, y, init, FALSE);
+	if (x == 0 && y == 0) {		/* special case - random placement */
+		otmp = mksobj(objtype, init, FALSE);
+		if (otmp) rloco(otmp);
+	} else
+		otmp = mksobj_at(objtype, x, y, init, FALSE);
 	if (otmp) {
 	    if (mtmp) {
 		struct obj *otmp2;

Index: engrave.c
===================================================================
RCS file: /cvsroot/pkg-nethack/nethack/src/engrave.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -d -r1.1.1.1 -r1.2
--- engrave.c	7 Oct 2003 19:00:12 -0000	1.1.1.1
+++ engrave.c	9 Dec 2003 16:14:43 -0000	1.2
@@ -156,7 +156,7 @@
 	else if (IS_AIR(lev->typ) && Is_airlevel(&u.uz))
 	    return "air";
 	else if (is_pool(x,y))
-	    return "water";
+	    return (Underwater && !Is_waterlevel(&u.uz)) ? "bottom" : "water";
 	else if (is_ice(x,y))
 	    return "ice";
 	else if (is_lava(x,y))

Index: topten.c
===================================================================
RCS file: /cvsroot/pkg-nethack/nethack/src/topten.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -d -r1.1.1.1 -r1.2
--- topten.c	7 Oct 2003 19:00:20 -0000	1.1.1.1
+++ topten.c	9 Dec 2003 16:14:43 -0000	1.2
@@ -595,7 +595,7 @@
 	    if (!strncmp(t1->death, "quit", 4)) {
 		Strcat(linebuf, "quit");
 		second_line = FALSE;
-	    } else if (!strncmp(t1->death, "starv", 5)) {
+	    } else if (!strncmp(t1->death, "died of st", 10)) {
 		Strcat(linebuf, "starved to death");
 		second_line = FALSE;
 	    } else if (!strncmp(t1->death, "choked", 6)) {

Index: display.c
===================================================================
RCS file: /cvsroot/pkg-nethack/nethack/src/display.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -d -r1.1.1.1 -r1.2
--- display.c	7 Oct 2003 19:00:10 -0000	1.1.1.1
+++ display.c	9 Dec 2003 16:14:43 -0000	1.2
@@ -746,14 +746,14 @@
 	 *  Note:  If flags.lit_corridor is set, then corridors act like room
 	 *	   squares.  That is, they light up if in night vision range.
 	 *	   If flags.lit_corridor is not set, then corridors will
-	 *	   remain dark unless lit by a light spell.
+	 *	   remain dark unless lit by a light spell and may darken
+	 *	   again, as discussed above.
 	 *
 	 * These checks and changes must be here and not in back_to_glyph().
 	 * They are dependent on the position being out of sight.
 	 */
 	else if (!lev->waslit) {
-	    if (flags.lit_corridor && lev->glyph == cmap_to_glyph(S_litcorr) &&
-							    lev->typ == CORR)
+	    if (lev->glyph == cmap_to_glyph(S_litcorr) && lev->typ == CORR)
 		show_glyph(x, y, lev->glyph = cmap_to_glyph(S_corr));
 	    else if (lev->glyph == cmap_to_glyph(S_room) && lev->typ == ROOM)
 		show_glyph(x, y, lev->glyph = cmap_to_glyph(S_stone));
@@ -1344,8 +1344,11 @@
      *	    flush_screen->print_glyph->impossible->pline->flush_screen
      */
     static   boolean flushing = 0;
+    static   boolean delay_flushing = 0;
     register int x,y;
 
+    if (cursor_on_u == -1) delay_flushing = !delay_flushing;
+    if (delay_flushing) return;
     if (flushing) return;	/* if already flushing then return */
     flushing = 1;
 

Index: dog.c
===================================================================
RCS file: /cvsroot/pkg-nethack/nethack/src/dog.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -d -r1.1.1.1 -r1.2
--- dog.c	7 Oct 2003 19:00:10 -0000	1.1.1.1
+++ dog.c	9 Dec 2003 16:14:43 -0000	1.2
@@ -358,8 +358,41 @@
 	mtmp->my = xyflags;
 	if (xlocale)
 	    (void) mnearto(mtmp, xlocale, ylocale, FALSE);
-	else
-	    rloc(mtmp);
+	else {
+	    if (!rloc(mtmp,TRUE)) {
+		/*
+		 * Failed to place migrating monster,
+		 * probably because the level is full.
+		 * Dump the monster's cargo and leave the monster dead.
+		 */
+	    	struct obj *obj, *corpse;
+		while ((obj = mtmp->minvent) != 0) {
+		    obj_extract_self(obj);
+		    obj_no_longer_held(obj);
+		    if (obj->owornmask & W_WEP)
+			setmnotwielded(mtmp,obj);
+		    obj->owornmask = 0L;
+		    if (xlocale && ylocale)
+			    place_object(obj, xlocale, ylocale);
+		    else {
+		    	rloco(obj);
+			get_obj_location(obj, &xlocale, &ylocale, 0);
+		    }
+		}
+		corpse = mkcorpstat(CORPSE, (struct monst *)0, mtmp->data,
+				xlocale, ylocale, FALSE);
+#ifndef GOLDOBJ
+		if (mtmp->mgold) {
+		    if (xlocale == 0 && ylocale == 0 && corpse) {
+			(void) get_obj_location(corpse, &xlocale, &ylocale, 0);
+			(void) mkgold(mtmp->mgold, xlocale, ylocale);
+		    }
+		    mtmp->mgold = 0L;
+		}
+#endif
+		mongone(mtmp);
+	    }
+	}
 }
 
 /* heal monster for time spent elsewhere */

Index: invent.c
===================================================================
RCS file: /cvsroot/pkg-nethack/nethack/src/invent.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -d -r1.1.1.1 -r1.2
--- invent.c	7 Oct 2003 19:00:13 -0000	1.1.1.1
+++ invent.c	9 Dec 2003 16:14:43 -0000	1.2
@@ -1,4 +1,4 @@
-/*	SCCS Id: @(#)invent.c	3.4	2003/05/25	*/
+/*	SCCS Id: @(#)invent.c	3.4	2003/12/02	*/
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
 /* NetHack may be freely redistributed.  See license for details. */
 
@@ -1080,14 +1080,12 @@
 	if(allowcnt == 2) {	/* cnt given */
 	    if(cnt == 0) return (struct obj *)0;
 	    if(cnt != otmp->quan) {
-		otmp = splitobj(otmp, cnt);
-		/* Very ugly kludge necessary to prevent someone from trying
-		 * to drop one of several loadstones and having the loadstone
-		 * now be separate.
-		 */
-		if (!strcmp(word, "drop") &&
-		    otmp->otyp == LOADSTONE && otmp->cursed)
-		    otmp->corpsenm = otmp->invlet;
+		/* don't split a stack of cursed loadstones */
+		if (otmp->otyp == LOADSTONE && otmp->cursed)
+		    /* kludge for canletgo()'s can't-drop-this message */
+		    otmp->corpsenm = (int) cnt;
+		else
+		    otmp = splitobj(otmp, cnt);
 	    }
 	}
 	return(otmp);
@@ -1765,7 +1763,7 @@
 			if (!flags.sortpack || otmp->oclass == *invlet) {
 			    if (flags.sortpack && !classcount) {
 				any.a_void = 0;		/* zero */
-				add_menu(win, NO_GLYPH, &any, 0, 0, ATR_INVERSE,
+				add_menu(win, NO_GLYPH, &any, 0, 0, iflags.menu_headings,
 				    let_to_name(*invlet, FALSE), MENU_UNSELECTED);
 				classcount++;
 			    }
@@ -2742,7 +2740,7 @@
 	any.a_void = 0;
 	win = create_nhwindow(NHW_MENU);
 	start_menu(win);
-	add_menu(win, NO_GLYPH, &any, 0, 0, ATR_INVERSE, hdr, MENU_UNSELECTED);
+	add_menu(win, NO_GLYPH, &any, 0, 0, iflags.menu_headings, hdr, MENU_UNSELECTED);
 	add_menu(win, NO_GLYPH, &any, 0, 0, ATR_NONE, "", MENU_UNSELECTED);
 	add_menu(win, NO_GLYPH, &any, 0, 0, ATR_NONE, txt, MENU_UNSELECTED);
 	end_menu(win, (char *)0);

Index: potion.c
===================================================================
RCS file: /cvsroot/pkg-nethack/nethack/src/potion.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -d -r1.1.1.1 -r1.2
--- potion.c	7 Oct 2003 19:00:17 -0000	1.1.1.1
+++ potion.c	9 Dec 2003 16:14:43 -0000	1.2
@@ -238,7 +238,7 @@
 	}
 }
 
-void
+boolean
 make_hallucinated(xtime, talk, mask)
 long xtime;	/* nonzero if this is an attempt to turn on hallucination */
 boolean talk;
@@ -296,6 +296,7 @@
 	    flags.botl = 1;
 	    if (talk) pline(message, verb);
 	}
+	return changed;
 }
 
 STATIC_OVL void
@@ -441,7 +442,7 @@
 		break;
 	case POT_HALLUCINATION:
 		if (Hallucination || Halluc_resistance) nothing++;
-		make_hallucinated(itimeout_incr(HHallucination,
+		(void) make_hallucinated(itimeout_incr(HHallucination,
 					   rn1(200, 600 - 300 * bcsign(otmp))),
 				  TRUE, 0L);
 		break;
@@ -657,12 +658,8 @@
 		    pline("(But in fact it was mildly stale %s.)",
 			  fruitname(TRUE));
 		    if (!Role_if(PM_HEALER)) {
-			if (otmp->corpsenm)
-			    losehp(1,
-				   "mildly contaminated tap water", KILLED_BY);
-			else
-			    losehp(1,
-				   "mildly contaminated potion", KILLED_BY_AN);
+			/* NB: blessed otmp->fromsink is not possible */
+			losehp(1, "mildly contaminated potion", KILLED_BY_AN);
 		    }
 		} else {
 		    if(Poison_resistance)
@@ -681,7 +678,7 @@
 			    		TRUE);
 			}
 			if(!Poison_resistance) {
-			    if (otmp->corpsenm)
+			    if (otmp->fromsink)
 				losehp(rnd(10)+5*!!(otmp->cursed),
 				       "contaminated tap water", KILLED_BY);
 			    else
@@ -693,7 +690,7 @@
 		}
 		if(Hallucination) {
 			You("are shocked back to your senses!");
-			make_hallucinated(0L,FALSE,0L);
+			(void) make_hallucinated(0L,FALSE,0L);
 		}
 		break;
 	case POT_CONFUSION:
@@ -798,7 +795,7 @@
 		healup(d(6 + 2 * bcsign(otmp), 8),
 		       otmp->blessed ? 5 : !otmp->cursed ? 2 : 0,
 		       !otmp->cursed, TRUE);
-		make_hallucinated(0L,TRUE,0L);
+		(void) make_hallucinated(0L,TRUE,0L);
 		exercise(A_CON, TRUE);
 		exercise(A_STR, TRUE);
 		break;
@@ -812,7 +809,7 @@
 		    u.ulevelmax -= 1;
 		    pluslvl(FALSE);
 		}
-		make_hallucinated(0L,TRUE,0L);
+		(void) make_hallucinated(0L,TRUE,0L);
 		exercise(A_STR, TRUE);
 		exercise(A_CON, TRUE);
 		break;
@@ -1435,16 +1432,6 @@
 	(void) Shk_Your(Your_buf, obj);
 	/* (Rusting shop goods ought to be charged for.) */
 	switch (obj->oclass) {
-	    case WEAPON_CLASS:
-		if (!obj->oerodeproof && is_rustprone(obj) &&
-		    (obj->oeroded < MAX_ERODE) && !rn2(2)) {
-			pline("%s %s some%s.",
-			      Your_buf, aobjnam(obj, "rust"),
-			      obj->oeroded ? " more" : "what");
-			obj->oeroded++;
-			update_inventory();
-			return TRUE;
-		} else break;
 	    case POTION_CLASS:
 		if (obj->otyp == POT_WATER) return FALSE;
 		/* KMH -- Water into acid causes an explosion */
@@ -1515,6 +1502,20 @@
 			}
 			return TRUE;
 		}
+		break;
+	    case WEAPON_CLASS:
+	    /* Just "fall through" to generic rustprone check for now. */
+	    /* fall through */
+	    default:
+		if (!obj->oerodeproof && is_rustprone(obj) &&
+		    (obj->oeroded < MAX_ERODE) && !rn2(2)) {
+			pline("%s %s some%s.",
+			      Your_buf, aobjnam(obj, "rust"),
+			      obj->oeroded ? " more" : "what");
+			obj->oeroded++;
+			update_inventory();
+			return TRUE;
+		} else break;
 	}
 	pline("%s %s wet.", Your_buf, aobjnam(obj,"get"));
 	return FALSE;
@@ -1543,7 +1544,7 @@
 			return(1);
 		}
 	} else if (is_pool(u.ux,u.uy)) {
-		tmp = (here == POOL) ? "pool" : "moat";
+		tmp = waterbody_name(u.ux,u.uy);
 		Sprintf(qbuf, "Dip it into the %s?", tmp);
 		if (yn(qbuf) == 'y') {
 		    if (Levitation) {
@@ -1995,7 +1996,7 @@
 		You("multiply%s!", reason);
 	    }
 	} else {
-	    mtmp2 = clone_mon(mon);
+	    mtmp2 = clone_mon(mon, 0, 0);
 	    if (mtmp2) {
 		mtmp2->mhpmax = mon->mhpmax / 2;
 		mon->mhpmax -= mtmp2->mhpmax;

Index: files.c
===================================================================
RCS file: /cvsroot/pkg-nethack/nethack/src/files.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -d -r1.1.1.1 -r1.2
--- files.c	7 Oct 2003 19:00:12 -0000	1.1.1.1
+++ files.c	9 Dec 2003 16:14:43 -0000	1.2
@@ -1,4 +1,4 @@
-/*	SCCS Id: @(#)files.c	3.4	2003/02/18	*/
+/*	SCCS Id: @(#)files.c	3.4	2003/11/14	*/
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
 /* NetHack may be freely redistributed.  See license for details. */
 
@@ -20,6 +20,10 @@
 # if (_MSC_VER >= 600)
 #  define SKIP_ERRNO
 # endif
+#else
+# ifdef NHSTDC
+#  define SKIP_ERRNO
+# endif
 #endif
 #ifndef SKIP_ERRNO
 # ifdef _DCC
@@ -550,7 +554,7 @@
 			fd = lftrack.fd;
 			reslt = lseek(fd, 0L, SEEK_SET);
 			if (reslt == -1L)
-			    panic("open_levelfile_exclusively: lseek failed %d", reslt);
+			    panic("open_levelfile_exclusively: lseek failed %d", errno);
 			lftrack.nethack_thinks_it_is_open = TRUE;
 		} else {
 			really_close();
@@ -1115,7 +1119,6 @@
 # endif
 	args[++i] = (char *)0;
 
-	f = fork();
 # ifdef TTY_GRAPHICS
 	/* If we don't do this and we are right after a y/n question *and*
 	 * there is an error message from the compression, the 'y' or 'n' can
@@ -1124,6 +1127,7 @@
 	if (istty)
 	    mark_synch();
 # endif
+	f = fork();
 	if (f == 0) {	/* child */
 # ifdef TTY_GRAPHICS
 		/* any error messages from the compression must come out after
@@ -1368,12 +1372,16 @@
 #define OPENFAILURE(fd) (fd < 0)
     lockptr = -1;
 # endif
-    while (retryct-- && OPENFAILURE(lockptr)) {
-# ifdef AMIGA
+    while (--retryct && OPENFAILURE(lockptr)) {
+# if defined(WIN32) && !defined(WIN_CE)
+	lockptr = sopen(lockname, O_RDWR|O_CREAT, SH_DENYRW, S_IWRITE);
+# else
 	(void)DeleteFile(lockname); /* in case dead process was here first */
+#  ifdef AMIGA
 	lockptr = Open(lockname,MODE_NEWFILE);
-# else
+#  else
 	lockptr = open(lockname, O_RDWR|O_CREAT|O_EXCL, S_IWRITE);
+#  endif
 # endif
 	if (OPENFAILURE(lockptr)) {
 	    raw_printf("Waiting for access to %s.  (%d retries left).",
@@ -1554,6 +1562,9 @@
 		Sprintf(tmp_config, "%s/%s", envp, "Library/Preferences/NetHack Defaults");
 		if ((fp = fopenp(tmp_config, "r")) != (FILE *)0)
 			return(fp);
+		Sprintf(tmp_config, "%s/%s", envp, "Library/Preferences/NetHack Defaults.txt");
+		if ((fp = fopenp(tmp_config, "r")) != (FILE *)0)
+			return(fp);
 	}
 # endif
 	if (errno != ENOENT) {
@@ -1705,6 +1716,10 @@
 		parseoptions(bufp, TRUE, TRUE);
 		if (plname[0])		/* If a name was given */
 			plnamesuffix();	/* set the character class */
+#ifdef AUTOPICKUP_EXCEPTIONS
+	} else if (match_varname(buf, "AUTOPICKUP_EXCEPTION", 5)) {
+		add_autopickup_exception(bufp);
+#endif
 #ifdef NOCWD_ASSUMPTIONS
 	} else if (match_varname(buf, "HACKDIR", 4)) {
 		adjust_prefix(bufp, HACKPREFIX);
@@ -2223,20 +2238,27 @@
 
 /*ARGSUSED*/
 void
-paniclog(why, s)
-const char* why;
-const char* s;
+paniclog(type, reason)
+const char *type;	/* panic, impossible, trickery */
+const char *reason;	/* explanation */
 {
 #ifdef PANICLOG
 	FILE *lfile;
+	char buf[BUFSZ];
 
-	lfile = fopen_datafile(PANICLOG, "a", TROUBLEPREFIX);
-	if (lfile) {
-	    (void) fprintf(lfile, "%08ld: %s %s\n",
-			   yyyymmdd((time_t)0L), why, s);
-	    (void) fclose(lfile);
+	if (!program_state.in_paniclog) {
+		program_state.in_paniclog = 1;
+		lfile = fopen_datafile(PANICLOG, "a", TROUBLEPREFIX);
+		if (lfile) {
+		    (void) fprintf(lfile, "%s %08ld: %s %s\n",
+				   version_string(buf), yyyymmdd((time_t)0L),
+				   type, reason);
+		    (void) fclose(lfile);
+		}
+		program_state.in_paniclog = 0;
 	}
 #endif /* PANICLOG */
+	return;
 }
 
 /* ----------  END PANIC/IMPOSSIBLE LOG ----------- */

Index: trap.c
===================================================================
RCS file: /cvsroot/pkg-nethack/nethack/src/trap.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -d -r1.1.1.1 -r1.2
--- trap.c	7 Oct 2003 19:00:20 -0000	1.1.1.1
+++ trap.c	9 Dec 2003 16:14:43 -0000	1.2
@@ -1,4 +1,4 @@
-/*	SCCS Id: @(#)trap.c	3.4	2003/05/25	*/
+/*	SCCS Id: @(#)trap.c	3.4	2003/10/20	*/
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
 /* NetHack may be freely redistributed.  See license for details. */
 
@@ -33,7 +33,6 @@
 #ifndef OVLB
 STATIC_VAR const char *a_your[2];
 STATIC_VAR const char *A_Your[2];
-STATIC_VAR const char *the_your[2];
 STATIC_VAR const char tower_of_flame[];
 STATIC_VAR const char *A_gush_of_water_hits;
 STATIC_VAR const char * const blindgas[6];
@@ -42,7 +41,6 @@
 
 STATIC_VAR const char * const a_your[2] = { "a", "your" };
 STATIC_VAR const char * const A_Your[2] = { "A", "Your" };
-STATIC_VAR const char * const the_your[2] = { "the", "your" };
 STATIC_VAR const char tower_of_flame[] = "tower of flame";
 STATIC_VAR const char * const A_gush_of_water_hits = "A gush of water hits";
 STATIC_VAR const char * const blindgas[6] = 
@@ -464,6 +462,9 @@
 	    return (struct monst *)0;
 	}
 
+	/* in case statue is wielded and hero zaps stone-to-flesh at self */
+	if (statue->owornmask) remove_worn_item(statue, TRUE);
+
 	/* allow statues to be of a specific gender */
 	if (statue->spe & STATUE_MALE)
 	    mon->female = FALSE;
@@ -479,6 +480,7 @@
 	}
 	m_dowear(mon, TRUE);
 	delobj(statue);
+
 	/* mimic statue becomes seen mimic; other hiders won't be hidden */
 	if (mon->m_ap_type) seemimic(mon);
 	else mon->mundetected = FALSE;
@@ -793,9 +795,12 @@
 	    case RUST_TRAP:
 		seetrap(trap);
 		if (u.umonnum == PM_IRON_GOLEM) {
+		    int dam = u.mhmax;
+
 		    pline("%s you!", A_gush_of_water_hits);
 		    You("are covered with rust!");
-		    rehumanize();
+		    if (Half_physical_damage) dam = (dam+1) / 2;
+		    losehp(dam, "rusting away", KILLED_BY);
 		    break;
 		} else if (u.umonnum == PM_GREMLIN && rn2(3)) {
 		    pline("%s you!", A_gush_of_water_hits);
@@ -1106,7 +1111,7 @@
 	    case LANDMINE: {
 #ifdef STEED
 		unsigned steed_mid = 0;
-		struct obj *saddle;
+		struct obj *saddle = 0;
 #endif
 		if (Levitation || Flying) {
 		    if (!already_seen && rn2(3)) break;
@@ -1117,8 +1122,8 @@
 					     "a trigger");
 		    if (already_seen && rn2(3)) break;
 		    pline("KAABLAMM!!!  %s %s%s off!",
-		    	    forcebungle ? "Your inept attempt sets" :
-		    	    		  "The air currents set",
+			  forcebungle ? "Your inept attempt sets" :
+					"The air currents set",
 			    already_seen ? a_your[trap->madeby_u] : "",
 			    already_seen ? " land mine" : "it");
 		} else {
@@ -2328,6 +2333,15 @@
 	}
 	/* check for falling into pool - added by GAN 10/20/86 */
 	if(!Flying) {
+		if (!u.uswallow && u.ustuck) {
+			if (sticks(youmonst.data))
+				You("aren't able to maintain your hold on %s.",
+					mon_nam(u.ustuck));
+			else
+				pline("Startled, %s can no longer hold you!",
+					mon_nam(u.ustuck));
+			u.ustuck = 0;
+		}
 		/* kludge alert:
 		 * drown() and lava_effects() print various messages almost
 		 * every time they're called which conflict with the "fall
@@ -2872,9 +2886,11 @@
 	if ((Teleportation || can_teleport(youmonst.data)) &&
 		    !u.usleep && (Teleport_control || rn2(3) < Luck+2)) {
 		You("attempt a teleport spell.");	/* utcsri!carroll */
-		(void) dotele();
-		if(!is_pool(u.ux,u.uy))
-			return(TRUE);
+		if (!level.flags.noteleport) {
+			(void) dotele();
+			if(!is_pool(u.ux,u.uy))
+				return(TRUE);
+		} else pline_The("attempted teleport spell fails.");
 	}
 #ifdef STEED
 	if (u.usteed) {
@@ -3747,7 +3763,7 @@
 				    stagger(youmonst.data, "stagger"));
 			}
 			make_stunned(HStun + rn1(7, 16),FALSE);
-			make_hallucinated(HHallucination + rn1(5, 16),FALSE,0L);
+			(void) make_hallucinated(HHallucination + rn1(5, 16),FALSE,0L);
 			break;
 		default: impossible("bad chest trap");
 			break;

Index: cmd.c
===================================================================
RCS file: /cvsroot/pkg-nethack/nethack/src/cmd.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -d -r1.1.1.1 -r1.2
--- cmd.c	7 Oct 2003 19:00:09 -0000	1.1.1.1
+++ cmd.c	9 Dec 2003 16:14:43 -0000	1.2
@@ -126,6 +126,9 @@
 #if defined(__BORLANDC__) && !defined(_WIN32)
 extern void FDECL(show_borlandc_stats, (winid));
 #endif
+#ifdef DEBUG_MIGRATING_MONS
+STATIC_PTR int NDECL(wiz_migrate_mons);
+#endif
 STATIC_DCL void FDECL(count_obj, (struct obj *, long *, long *, BOOLEAN_P, BOOLEAN_P));
 STATIC_DCL void FDECL(obj_chain, (winid, const char *, struct obj *, long *, long *));
 STATIC_DCL void FDECL(mon_invent_chain, (winid, const char *, struct monst *, long *, long *));
@@ -552,7 +555,7 @@
 STATIC_PTR int
 wiz_where()
 {
-	if (wizard) (void) print_dungeon(FALSE);
+	if (wizard) (void) print_dungeon(FALSE, (schar *)0, (xchar *)0);
 	else	    pline("Unavailable command '^O'.");
 	return 0;
 }
@@ -1136,14 +1139,21 @@
 	anything any;
 	int genidx, n;
 	char buf[BUFSZ], buf2[BUFSZ];
-	static const char fmtstr[] = "%-15s: %-12s";
-	static const char deity_fmtstr[] = "%-17s%s";
+	static const char untabbed_fmtstr[] = "%-15s: %-12s";
+	static const char untabbed_deity_fmtstr[] = "%-17s%s";
+	static const char tabbed_fmtstr[] = "%s:\t%-12s";
+	static const char tabbed_deity_fmtstr[] = "%s\t%s";
+	static const char *fmtstr;
+	static const char *deity_fmtstr;
 
+	fmtstr = iflags.menu_tab_sep ? tabbed_fmtstr : untabbed_fmtstr;
+	deity_fmtstr = iflags.menu_tab_sep ?
+			tabbed_deity_fmtstr : untabbed_deity_fmtstr; 
 	any.a_void = 0;
 	buf[0] = buf2[0] = '\0';
 	tmpwin = create_nhwindow(NHW_MENU);
 	start_menu(tmpwin);
-	add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_BOLD, "Starting", FALSE);
+	add_menu(tmpwin, NO_GLYPH, &any, 0, 0, iflags.menu_headings, "Starting", FALSE);
 
 	/* Starting name, race, role, gender */
 	Sprintf(buf, fmtstr, "name", plname);
@@ -1162,7 +1172,7 @@
 
 	/* Current name, race, role, gender */
 	add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, "", FALSE);
-	add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_BOLD, "Current", FALSE);
+	add_menu(tmpwin, NO_GLYPH, &any, 0, 0, iflags.menu_headings, "Current", FALSE);
 	Sprintf(buf, fmtstr, "race", Upolyd ? youmonst.data->mname : urace.noun);
 	add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, buf, FALSE);
 	if (Upolyd) {
@@ -1189,7 +1199,7 @@
 
 	/* Deity list */
 	add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, "", FALSE);
-	add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_BOLD, "Deities", FALSE);
+	add_menu(tmpwin, NO_GLYPH, &any, 0, 0, iflags.menu_headings, "Deities", FALSE);
 	Sprintf(buf2, deity_fmtstr, align_gname(A_CHAOTIC),
 	    (u.ualignbase[A_ORIGINAL] == u.ualign.type
 		&& u.ualign.type == A_CHAOTIC) ? " (s,c)" :
@@ -1499,6 +1509,9 @@
 	 */
 	{(char *)0, (char *)0, donull, TRUE},
 	{(char *)0, (char *)0, donull, TRUE},
+#ifdef DEBUG_MIGRATING_MONS
+	{(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},
@@ -1521,6 +1534,9 @@
 static const struct ext_func_tab debug_extcmdlist[] = {
 	{"levelchange", "change experience level", wiz_level_change, TRUE},
 	{"lightsources", "show mobile light sources", wiz_light_sources, TRUE},
+#ifdef DEBUG_MIGRATING_MONS
+	{"migratemons", "migrate n random monsters", wiz_migrate_mons, TRUE},
+#endif
 	{"monpolycontrol", "control monster polymorphs", wiz_mon_polycontrol, TRUE},
 	{"panic", "test panic routine (fatal to game)", wiz_panic, TRUE},
 	{"polyself", "polymorph self", wiz_polyself, TRUE},
@@ -1749,6 +1765,35 @@
 	timer_sanity_check();
 }
 
+#ifdef DEBUG_MIGRATING_MONS
+static int
+wiz_migrate_mons()
+{
+	int mcount = 0;
+	char inbuf[BUFSZ];
+	struct permonst *ptr;
+	struct monst *mtmp;
+	d_level tolevel;
+	getlin("How many random monsters to migrate? [0]", inbuf);
+	if (*inbuf == '\033') return 0;
+	mcount = atoi(inbuf);
+	if (mcount < 0 || mcount > (COLNO * ROWNO) || Is_botlevel(&u.uz))
+		return 0;
+	while (mcount > 0) {
+		if (Is_stronghold(&u.uz))
+		    assign_level(&tolevel, &valley_level);
+		else
+		    get_level(&tolevel, depth(&u.uz) + 1);
+		ptr = rndmonst();
+		mtmp = makemon(ptr, 0, 0, NO_MM_FLAGS);
+		if (mtmp) migrate_to_level(mtmp, ledger_no(&tolevel),
+				MIGR_RANDOM, (coord *)0);
+		mcount--;
+	}
+	return 0;
+}
+#endif
+
 #endif /* WIZARD */
 
 #define unctrl(c)	((c) <= C('z') ? (0x60 | (c)) : (c))
@@ -1803,7 +1848,7 @@
         }
 	/* handle most movement commands */
 	do_walk = do_rush = prefix_seen = FALSE;
-	flags.travel = 0;
+	flags.travel = iflags.travel1 = 0;
 	switch (*cmd) {
 	 case 'g':  if (movecmd(cmd[1])) {
 			flags.run = 2;
@@ -1853,6 +1898,7 @@
 	 case CMD_TRAVEL:
 		    if (iflags.travelcmd) {
 			    flags.travel = 1;
+			    iflags.travel1 = 1;
 			    flags.run = 8;
 			    flags.nopick = 1;
 			    do_rush = TRUE;
@@ -2345,11 +2391,11 @@
 void
 end_of_input()
 {
-	exit_nhwindows("End of input?");
 #ifndef NOSAVEONHANGUP
 	if (!program_state.done_hup++ && program_state.something_worth_saving)
 	    (void) dosave0();
 #endif
+	exit_nhwindows((char *)0);
 	clearlocks();
 	terminate(EXIT_SUCCESS);
 }

Index: do_name.c
===================================================================
RCS file: /cvsroot/pkg-nethack/nethack/src/do_name.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -d -r1.1.1.1 -r1.2
--- do_name.c	7 Oct 2003 19:00:11 -0000	1.1.1.1
+++ do_name.c	9 Dec 2003 16:14:43 -0000	1.2
@@ -499,7 +499,7 @@
 	otemp.quan = 1L;
 	otemp.onamelth = 0;
 	otemp.oxlth = 0;
-	if (objects[otemp.otyp].oc_class == POTION_CLASS && otemp.corpsenm)
+	if (objects[otemp.otyp].oc_class == POTION_CLASS && otemp.fromsink)
 	    /* kludge, meaning it's sink water */
 	    Sprintf(qbuf,"Call a stream of %s fluid:",
 		    OBJ_DESCR(objects[otemp.otyp]));

Index: shknam.c
===================================================================
RCS file: /cvsroot/pkg-nethack/nethack/src/shknam.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -d -r1.1.1.1 -r1.2
--- shknam.c	7 Oct 2003 19:00:19 -0000	1.1.1.1
+++ shknam.c	9 Dec 2003 16:14:43 -0000	1.2
@@ -385,7 +385,7 @@
 	    return(-1);
 	}
 
-	if(MON_AT(sx, sy)) rloc(m_at(sx, sy)); /* insurance */
+	if(MON_AT(sx, sy)) (void) rloc(m_at(sx, sy), FALSE); /* insurance */
 
 	/* now initialize the shopkeeper monster structure */
 	if(!(shk = makemon(&mons[PM_SHOPKEEPER], sx, sy, NO_MM_FLAGS)))

Index: read.c
===================================================================
RCS file: /cvsroot/pkg-nethack/nethack/src/read.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -d -r1.1.1.1 -r1.2
--- read.c	7 Oct 2003 19:00:17 -0000	1.1.1.1
+++ read.c	9 Dec 2003 16:14:43 -0000	1.2
@@ -1,4 +1,4 @@
-/*	SCCS Id: @(#)read.c	3.4	2003/01/09	*/
+/*	SCCS Id: @(#)read.c	3.4	2003/10/22	*/
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
 /* NetHack may be freely redistributed.  See license for details. */
 
@@ -322,13 +322,13 @@
 		    else
 			pline(nothing_happens);
 		} else if (is_blessed) {
-		    n = rn1(10,16);		/* 10..25 */
+		    n = rn1(16,15);		/* 15..30 */
 		    if (obj->spe + n <= 50)
 			obj->spe = 50;
 		    else if (obj->spe + n <= 75)
 			obj->spe = 75;
 		    else {
-		    	int chrg = (int)obj->spe;
+			int chrg = (int)obj->spe;
 			if ((chrg + n) > 127)
 				obj->spe = 127;
 			else
@@ -336,11 +336,11 @@
 		    }
 		    p_glow2(obj, NH_BLUE);
 		} else {
-		    n = rn1(5,10);		/* 5..15 */
+		    n = rn1(11,10);		/* 10..20 */
 		    if (obj->spe + n <= 50)
 			obj->spe = 50;
 		    else {
-		    	int chrg = (int)obj->spe;
+			int chrg = (int)obj->spe;
 			if ((chrg + n) > 127)
 				obj->spe = 127;
 			else

Index: priest.c
===================================================================
RCS file: /cvsroot/pkg-nethack/nethack/src/priest.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -d -r1.1.1.1 -r1.2
--- priest.c	7 Oct 2003 19:00:17 -0000	1.1.1.1
+++ priest.c	9 Dec 2003 16:14:43 -0000	1.2
@@ -195,7 +195,7 @@
 	int cnt;
 
 	if(MON_AT(sx+1, sy))
-		rloc(m_at(sx+1, sy)); /* insurance */
+		(void) rloc(m_at(sx+1, sy), FALSE); /* insurance */
 
 	priest = makemon(&mons[sanctum ? PM_HIGH_PRIEST : PM_ALIGNED_PRIEST],
 			 sx + 1, sy, NO_MM_FLAGS);
@@ -386,7 +386,9 @@
 
 		    if(!(mtmp = makemon(&mons[PM_GHOST],u.ux,u.uy,NO_MM_FLAGS)))
 			return;
-		    pline("An enormous ghost appears next to you!");
+		    if (!Blind || sensemon(mtmp))
+			pline("An enormous ghost appears next to you!");
+		    else You("sense a presence close by!");
 		    mtmp->mpeaceful = 0;
 		    set_malign(mtmp);
 		    if(flags.verbose)
@@ -541,7 +543,7 @@
 	if (ptr != &mons[PM_ALIGNED_PRIEST] && ptr != &mons[PM_ANGEL])
 		return((struct monst *)0);
 	
-	if (MON_AT(x, y)) rloc(m_at(x, y));	/* insurance */
+	if (MON_AT(x, y)) (void) rloc(m_at(x, y), FALSE);	/* insurance */
 
 	if (!(roamer = makemon(ptr, x, y, NO_MM_FLAGS)))
 		return((struct monst *)0);

Index: mapglyph.c
===================================================================
RCS file: /cvsroot/pkg-nethack/nethack/src/mapglyph.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -d -r1.1.1.1 -r1.2
--- mapglyph.c	7 Oct 2003 19:00:13 -0000	1.1.1.1
+++ mapglyph.c	9 Dec 2003 16:14:43 -0000	1.2
@@ -122,6 +122,14 @@
 		color = NO_COLOR;
 	} else
 #endif
+#ifdef TEXTCOLOR
+	    /* provide a visible difference if normal and lit corridor
+	     * use the same symbol */
+	    if (iflags.use_color &&
+		offset == S_litcorr && ch == showsyms[S_corr])
+		color = CLR_WHITE;
+	    else
+#endif
 	    cmap_color(offset);
     } else if ((offset = (glyph - GLYPH_OBJ_OFF)) >= 0) {	/* object */
 	if (offset == BOULDER && iflags.bouldersym) ch = iflags.bouldersym;

Index: muse.c
===================================================================
RCS file: /cvsroot/pkg-nethack/nethack/src/muse.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -d -r1.1.1.1 -r1.2
--- muse.c	7 Oct 2003 19:00:15 -0000	1.1.1.1
+++ muse.c	9 Dec 2003 16:14:43 -0000	1.2
@@ -438,7 +438,9 @@
 		    /* digging wouldn't be effective; assume they know that */
 		    && !(levl[x][y].wall_info & W_NONDIGGABLE)
 		    && !(Is_botlevel(&u.uz) || In_endgame(&u.uz))
-		    && !(is_ice(x,y) || is_pool(x,y) || is_lava(x,y))) {
+		    && !(is_ice(x,y) || is_pool(x,y) || is_lava(x,y))
+		    && !(mtmp->data == &mons[PM_VLAD_THE_IMPALER]
+			 && In_V_tower(&u.uz))) {
 			m.defensive = obj;
 			m.has_defense = MUSE_WAN_DIGGING;
 		}
@@ -592,7 +594,7 @@
 		    return 2;
 		}
 		if (oseen && how) makeknown(how);
-		rloc(mtmp);
+		(void) rloc(mtmp, FALSE);
 		return 2;
 	case MUSE_WAN_TELEPORTATION:
 		zap_oseen = oseen;
@@ -1148,7 +1150,7 @@
 			    mtmp->msleeping = 0;
 			    if(mtmp->m_ap_type) seemimic(mtmp);
 			} else if (!tele_restrict(mtmp))
-			    rloc(mtmp);
+			    (void) rloc(mtmp, FALSE);
 		}
 		break;
 	case WAN_CANCELLATION:

Index: shk.c
===================================================================
RCS file: /cvsroot/pkg-nethack/nethack/src/shk.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -d -r1.1.1.1 -r1.2
--- shk.c	7 Oct 2003 19:00:18 -0000	1.1.1.1
+++ shk.c	9 Dec 2003 16:14:43 -0000	1.2
@@ -1,4 +1,4 @@
-/*	SCCS Id: @(#)shk.c	3.4	2003/08/18	*/
+/*	SCCS Id: @(#)shk.c	3.4	2003/12/04	*/
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
 /* NetHack may be freely redistributed.  See license for details. */
 
@@ -474,6 +474,7 @@
 	long total;
 
 	eshkp = ESHK(shkp);
+	rouse_shk(shkp, TRUE);
 	total = (addupbill(shkp) + eshkp->debit);
 	if (eshkp->credit >= total) {
 	    Your("credit of %ld %s is used to cover your shopping bill.",
@@ -535,7 +536,8 @@
 
 	eshkp->bill_p = &(eshkp->bill[0]);
 
-	if (!eshkp->visitct || strncmpi(eshkp->customer, plname, PL_NSIZ)) {
+	if ((!eshkp->visitct || *eshkp->customer) &&
+	    strncmpi(eshkp->customer, plname, PL_NSIZ)) {
 	    /* You seem to be new here */
 	    eshkp->visitct = 0;
 	    eshkp->following = 0;
@@ -957,7 +959,7 @@
 struct monst *shkp;
 boolean verbosely;
 {
-	if (!shkp->mcanmove) {
+	if (!shkp->mcanmove || shkp->msleeping) {
 	    /* greed induced recovery... */
 	    if (verbosely && canspotmon(shkp))
 		pline("%s %s.", Monnam(shkp),
@@ -993,6 +995,9 @@
 		} else {
 			/* if sensed, does disappear regardless whether seen */
 			if (sensemon(shkp)) vanished = TRUE;
+			/* can't act as porter for the Amulet, even if shk
+			   happens to be going farther down rather than up */
+			mdrop_special_objs(shkp);
 			/* arrive near shop's door */
 			migrate_to_level(shkp, ledger_no(&eshkp->shoplevel),
 					 MIGR_APPROX_XY, &eshkp->shd);
@@ -1195,7 +1200,7 @@
 	if (ltmp || eshkp->billct || eshkp->debit) 
 	    rouse_shk(shkp, TRUE);
 
-	if (!shkp->mcanmove) {	    /* still asleep or paralyzed */
+	if (!shkp->mcanmove || shkp->msleeping) { /* still asleep/paralyzed */
 		pline("%s %s.", Monnam(shkp),
 		      rn2(2) ? "seems to be napping" : "doesn't respond");
 		return 0;
@@ -1648,7 +1653,7 @@
 	    if (cansee(shkp->mx, shkp->my && croaked))
 		pline("%s %slooks at your corpse%s and %s.",
 		      Monnam(shkp),
-		      !shkp->mcanmove ? "wakes up, " : "",
+		      (!shkp->mcanmove || shkp->msleeping) ? "wakes up, " : "",
 		      !rn2(2) ? (shkp->female ? ", shakes her head," :
 			   ", shakes his head,") : "",
 		      !inhishop(shkp) ? "disappears" : "sighs");
@@ -1684,7 +1689,7 @@
                 umoney = money_cnt(invent);
 #endif
 		takes[0] = '\0';
-		if (!shkp->mcanmove)
+		if (!shkp->mcanmove || shkp->msleeping)
 			Strcat(takes, "wakes up and ");
 		if (distu(shkp->mx, shkp->my) > 2)
 			Strcat(takes, "comes and ");

Index: do_wear.c
===================================================================
RCS file: /cvsroot/pkg-nethack/nethack/src/do_wear.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -d -r1.1.1.1 -r1.2
--- do_wear.c	7 Oct 2003 19:00:11 -0000	1.1.1.1
+++ do_wear.c	9 Dec 2003 16:14:43 -0000	1.2
@@ -1,4 +1,4 @@
-/*	SCCS Id: @(#)do_wear.c	3.4	2003/05/25	*/
+/*	SCCS Id: @(#)do_wear.c	3.4	2003/11/14	*/
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
 /* NetHack may be freely redistributed.  See license for details. */
 
@@ -47,6 +47,10 @@
 STATIC_DCL int NDECL(Cloak_on);
 STATIC_PTR int NDECL(Helmet_on);
 STATIC_PTR int NDECL(Gloves_on);
+STATIC_PTR int NDECL(Shield_on);
+#ifdef TOURIST
+STATIC_PTR int NDECL(Shirt_on);
+#endif
 STATIC_DCL void NDECL(Amulet_on);
 STATIC_DCL void FDECL(Ring_off_or_gone, (struct obj *, BOOLEAN_P));
 STATIC_PTR int FDECL(select_off, (struct obj *));
@@ -140,7 +144,7 @@
     int otyp = uarmf->otyp;
     long oldprop = u.uprops[objects[otyp].oc_oprop].extrinsic & ~WORN_BOOTS;
 
-
+    takeoff_mask &= ~W_ARMF;
 	/* For levitation, float_down() returns if Levitation, so we
 	 * must do a setworn() _before_ the levitation case.
 	 */
@@ -244,7 +248,7 @@
     int otyp = uarmc->otyp;
     long oldprop = u.uprops[objects[otyp].oc_oprop].extrinsic & ~WORN_CLOAK;
 
-
+    takeoff_mask &= ~W_ARMC;
 	/* For mummy wrapping, taking it off first resets `Invisible'. */
     setworn((struct obj *)0, W_ARMC);
     switch (otyp) {
@@ -345,6 +349,8 @@
 int
 Helmet_off()
 {
+    takeoff_mask &= ~W_ARMH;
+
     switch(uarmh->otyp) {
 	case FEDORA:
 	case HELMET:
@@ -414,6 +420,8 @@
     long oldprop =
 	u.uprops[objects[uarmg->otyp].oc_oprop].extrinsic & ~WORN_GLOVES;
 
+    takeoff_mask &= ~W_ARMG;
+
     switch(uarmg->otyp) {
 	case LEATHER_GLOVES:
 	    break;
@@ -462,11 +470,11 @@
     return 0;
 }
 
-/*
 STATIC_OVL int
 Shield_on()
 {
-    switch(uarms->otyp) {
+/*
+    switch (uarms->otyp) {
 	case SMALL_SHIELD:
 	case ELVEN_SHIELD:
 	case URUK_HAI_SHIELD:
@@ -477,15 +485,16 @@
 		break;
 	default: impossible(unknown_type, c_shield, uarms->otyp);
     }
+*/
     return 0;
 }
-*/
 
 int
 Shield_off()
 {
+    takeoff_mask &= ~W_ARMS;
 /*
-    switch(uarms->otyp) {
+    switch (uarms->otyp) {
 	case SMALL_SHIELD:
 	case ELVEN_SHIELD:
 	case URUK_HAI_SHIELD:
@@ -501,6 +510,38 @@
     return 0;
 }
 
+#ifdef TOURIST
+STATIC_OVL int
+Shirt_on()
+{
+/*
+    switch (uarmu->otyp) {
+	case HAWAIIAN_SHIRT:
+	case T_SHIRT:
+		break;
+	default: impossible(unknown_type, c_shirt, uarmu->otyp);
+    }
+*/
+    return 0;
+}
+
+int
+Shirt_off()
+{
+    takeoff_mask &= ~W_ARMU;
+/*
+    switch (uarmu->otyp) {
+	case HAWAIIAN_SHIRT:
+	case T_SHIRT:
+		break;
+	default: impossible(unknown_type, c_shirt, uarmu->otyp);
+    }
+*/
+    setworn((struct obj *)0, W_ARMU);
+    return 0;
+}
+#endif	/*TOURIST*/
+
 /* This must be done in worn.c, because one of the possible intrinsics conferred
  * is fire resistance, and we have to immediately set HFire_resistance in worn.c
  * since worn.c will check it before returning.
@@ -515,6 +556,7 @@
 int
 Armor_off()
 {
+    takeoff_mask &= ~W_ARM;
     setworn((struct obj *)0, W_ARM);
     cancelled_don = FALSE;
     return 0;
@@ -526,6 +568,7 @@
 int
 Armor_gone()
 {
+    takeoff_mask &= ~W_ARM;
     setnotworn(uarm);
     cancelled_don = FALSE;
     return 0;
@@ -588,6 +631,8 @@
 void
 Amulet_off()
 {
+    takeoff_mask &= ~W_AMUL;
+
     switch(uamul->otyp) {
 	case AMULET_OF_ESP:
 		/* need to update ability before calling see_monsters() */
@@ -744,9 +789,10 @@
 register struct obj *obj;
 boolean gone;
 {
-    register long mask = obj->owornmask & W_RING;
+    long mask = (obj->owornmask & W_RING);
     int old_attrib, which;
 
+    takeoff_mask &= ~mask;
     if(!(u.uprops[objects[obj->otyp].oc_oprop].extrinsic & mask))
 	impossible("Strange... I didn't know you had that ring.");
     if(gone) setnotworn(obj);
@@ -897,6 +943,7 @@
 {
 	boolean was_blind = Blind, changed = FALSE;
 
+	takeoff_mask &= ~W_TOOL;
 	setworn((struct obj *)0, otmp->owornmask);
 	off_msg(otmp);
 
@@ -929,22 +976,51 @@
 void
 set_wear()
 {
+#ifdef TOURIST
+	if (uarmu) (void) Shirt_on();
+#endif
 	if (uarm)  (void) Armor_on();
 	if (uarmc) (void) Cloak_on();
 	if (uarmf) (void) Boots_on();
 	if (uarmg) (void) Gloves_on();
 	if (uarmh) (void) Helmet_on();
-/*	if (uarms) (void) Shield_on(); */
+	if (uarms) (void) Shield_on();
 }
 
+/* check whether the target object is currently being put on (or taken off) */
 boolean
-donning(otmp)
+donning(otmp)		/* also checks for doffing */
 register struct obj *otmp;
 {
-    return((boolean)((otmp == uarmf && (afternmv == Boots_on || afternmv == Boots_off))
-	|| (otmp == uarmh && (afternmv == Helmet_on || afternmv == Helmet_off))
-	|| (otmp == uarmg && (afternmv == Gloves_on || afternmv == Gloves_off))
-	|| (otmp == uarm && (afternmv == Armor_on || afternmv == Armor_off))));
+ /* long what = (occupation == take_off) ? taking_off : 0L; */
+    long what = taking_off;	/* if nonzero, occupation is implied */
+    boolean result = FALSE;
+
+    if (otmp == uarm)
+	result = (afternmv == Armor_on || afternmv == Armor_off ||
+		  what == WORN_ARMOR);
+#ifdef TOURIST
+    else if (otmp == uarmu)
+	result = (afternmv == Shirt_on || afternmv == Shirt_off ||
+		  what == WORN_SHIRT);
+#endif
+    else if (otmp == uarmc)
+	result = (afternmv == Cloak_on || afternmv == Cloak_off ||
+		  what == WORN_CLOAK);
+    else if (otmp == uarmf)
+	result = (afternmv == Boots_on || afternmv == Boots_off ||
+		  what == WORN_BOOTS);
+    else if (otmp == uarmh)
+	result = (afternmv == Helmet_on || afternmv == Helmet_off ||
+		  what == WORN_HELMET);
+    else if (otmp == uarmg)
+	result = (afternmv == Gloves_on || afternmv == Gloves_off ||
+		  what == WORN_GLOVES);
+    else if (otmp == uarms)
+	result = (afternmv == Shield_on || afternmv == Shield_off ||
+		  what == WORN_SHIELD);
+
+    return result;
 }
 
 void
@@ -959,6 +1035,8 @@
 	afternmv = 0;
 	nomovemsg = (char *)0;
 	multi = 0;
+	todelay = 0;
+	taking_off = 0L;
 }
 
 static NEARDATA const char clothes[] = {ARMOR_CLASS, 0};
@@ -1371,7 +1449,10 @@
 		nomovemsg = "You finish your dressing maneuver.";
 	} else {
 		if(is_cloak(otmp)) (void) Cloak_on();
-/*		if(is_shield(otmp)) (void) Shield_on(); */
+		if (is_shield(otmp)) (void) Shield_on();
+#ifdef TOURIST
+		if (is_shirt(otmp)) (void) Shirt_on();
+#endif
 		on_msg(otmp);
 	}
 	takeoff_mask = taking_off = 0L;
@@ -1673,6 +1754,7 @@
     return 0;
 }
 
+/* occupation callback for 'A' */
 STATIC_PTR
 int
 select_off(otmp)
@@ -1825,8 +1907,7 @@
 #ifdef TOURIST
 	} else if (taking_off == WORN_SHIRT) {
 	  otmp = uarmu;
-	  if(!cursed(otmp))
-	    setworn((struct obj *)0, uarmu->owornmask & W_ARMOR);
+	  if (!cursed(otmp)) (void) Shirt_off();
 #endif
 	} else if (taking_off == WORN_AMUL) {
 	  otmp = uamul;
@@ -1922,15 +2003,16 @@
 	if (otmp) todelay += objects[otmp->otyp].oc_delay;
 
 	/* Since setting the occupation now starts the counter next move, that
-         * would always produce a delay 1 too big per item unless we subtract
+	 * would always produce a delay 1 too big per item unless we subtract
 	 * 1 here to account for it.
 	 */
-	if (todelay>0) todelay--;
+	if (todelay > 0) todelay--;
 
 	set_occupation(take_off, disrobing, 0);
 	return(1);		/* get busy */
 }
 
+/* clear saved context to avoid inappropriate resumption of interrupted 'A' */
 void
 reset_remarm()
 {
@@ -1938,7 +2020,7 @@
 	disrobing = nul;
 }
 
-/* the 'A' command */
+/* the 'A' command -- remove multiple worn items */
 int
 doddoremarm()
 {
@@ -1947,7 +2029,6 @@
     if (taking_off || takeoff_mask) {
 	You("continue %s.", disrobing);
 	set_occupation(take_off, disrobing, 0);
-	(void) take_off();
 	return 0;
     } else if (!uwep && !uswapwep && !uquiver && !uamul && !ublindf &&
 		!uleft && !uright && !wearing_armor()) {
@@ -2018,6 +2099,7 @@
     return 0;
 }
 
+/* hit by destroy armor scroll/black dragon breath/monster spell */
 int
 destroy_arm(atmp)
 register struct obj *atmp;
@@ -2028,11 +2110,12 @@
 			(!obj_resists(otmp, 0, 90)))
 
 	if (DESTROY_ARM(uarmc)) {
-		Your("%s crumbles and turns to dust!", cloak_simple_name(uarmc));
+		if (donning(otmp)) cancel_don();
+		Your("%s crumbles and turns to dust!",
+		     cloak_simple_name(uarmc));
 		(void) Cloak_off();
 		useup(otmp);
 	} else if (DESTROY_ARM(uarm)) {
-		/* may be disintegrated by spell or dragon breath... */
 		if (donning(otmp)) cancel_don();
 		Your("armor turns to dust and falls to the %s!",
 			surface(u.ux,u.uy));
@@ -2040,7 +2123,9 @@
 		useup(otmp);
 #ifdef TOURIST
 	} else if (DESTROY_ARM(uarmu)) {
+		if (donning(otmp)) cancel_don();
 		Your("shirt crumbles into tiny threads and falls apart!");
+		(void) Shirt_off();
 		useup(otmp);
 #endif
 	} else if (DESTROY_ARM(uarmh)) {
@@ -2060,12 +2145,16 @@
 		(void) Boots_off();
 		useup(otmp);
 	} else if (DESTROY_ARM(uarms)) {
+		if (donning(otmp)) cancel_don();
 		Your("shield crumbles away!");
 		(void) Shield_off();
 		useup(otmp);
-	} else	return(0);		/* could not destroy anything */
+	} else {
+		return 0;		/* could not destroy anything */
+	}
 
 #undef DESTROY_ARM
+	stop_occupation();
 	return(1);
 }
 

Index: bones.c
===================================================================
RCS file: /cvsroot/pkg-nethack/nethack/src/bones.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -d -r1.1.1.1 -r1.2
--- bones.c	7 Oct 2003 19:00:09 -0000	1.1.1.1
+++ bones.c	9 Dec 2003 16:14:43 -0000	1.2
@@ -1,4 +1,4 @@
-/*	SCCS Id: @(#)bones.c	3.4	2002/08/23	*/
+/*	SCCS Id: @(#)bones.c	3.4	2003/09/06	*/
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985,1993. */
 /* NetHack may be freely redistributed.  See license for details. */
 
@@ -422,21 +422,27 @@
 			trickery(errbuf);
 		} else {
 			register struct monst *mtmp;
-			int mndx;
 
 			getlev(fd, 0, 0, TRUE);
 
-			/* to correctly reset named artifacts on the level and
-			   to keep tabs on unique monsters like demon lords */
+			/* Note that getlev() now keeps tabs on unique
+			 * monsters such as demon lords, and tracks the
+			 * birth counts of all species just as makemon()
+			 * does.  If a bones monster is extinct or has been
+			 * subject to genocide, their mhpmax will be
+			 * set to the magic DEFUNCT_MONSTER cookie value.
+			 */
 			for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
-			    mndx = monsndx(mtmp->data);
-			    if (mvitals[mndx].mvflags & G_EXTINCT) {
+			    if (mtmp->mhpmax == DEFUNCT_MONSTER) {
+#if defined(DEBUG) && defined(WIZARD)
+				if (wizard)
+				    pline("Removing defunct monster %s from bones.",
+					mtmp->data->mname);
+#endif
 				mongone(mtmp);
-			    } else {
-				if (mons[mndx].geno & G_UNIQ)
-				    mvitals[mndx].mvflags |= G_EXTINCT;
+			    } else
+				/* to correctly reset named artifacts on the level */
 				resetobjs(mtmp->minvent,TRUE);
-			    }
 			}
 			resetobjs(fobj,TRUE);
 			resetobjs(level.buriedobjlist,TRUE);

Index: o_init.c
===================================================================
RCS file: /cvsroot/pkg-nethack/nethack/src/o_init.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -d -r1.1.1.1 -r1.2
--- o_init.c	7 Oct 2003 19:00:16 -0000	1.1.1.1
+++ o_init.c	9 Dec 2003 16:14:43 -0000	1.2
@@ -382,7 +382,7 @@
     for (i = dis = 0; i < SIZE(uniq_objs); i++)
 	if (objects[uniq_objs[i]].oc_name_known) {
 	    if (!dis++)
-		putstr(tmpwin, ATR_INVERSE, "Unique Items");
+		putstr(tmpwin, iflags.menu_headings, "Unique Items");
 		Sprintf(buf, "  %s", OBJ_NAME(objects[uniq_objs[i]]));
 	    putstr(tmpwin, 0, buf);
 	    ++ct;
@@ -406,7 +406,7 @@
 	    if ((dis = disco[i]) && interesting_to_discover(dis)) {
 		ct++;
 		if (oclass != prev_class) {
-		    putstr(tmpwin, ATR_INVERSE, let_to_name(oclass, FALSE));
+		    putstr(tmpwin, iflags.menu_headings, let_to_name(oclass, FALSE));
 		    prev_class = oclass;
 		}
 		Sprintf(buf, "%s %s",(objects[dis].oc_pre_discovered ? "*" : " "),

Index: steal.c
===================================================================
RCS file: /cvsroot/pkg-nethack/nethack/src/steal.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -d -r1.1.1.1 -r1.2
--- steal.c	7 Oct 2003 19:00:19 -0000	1.1.1.1
+++ steal.c	9 Dec 2003 16:14:43 -0000	1.2
@@ -1,4 +1,4 @@
-/*	SCCS Id: @(#)steal.c	3.4	2002/09/07	*/
+/*	SCCS Id: @(#)steal.c	3.4	2003/12/04	*/
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
 /* NetHack may be freely redistributed.  See license for details. */
 
@@ -8,6 +8,7 @@
 
 #ifdef OVLB
 STATIC_DCL const char *FDECL(equipname, (struct obj *));
+STATIC_DCL void FDECL(mdrop_obj, (struct monst *,struct obj *,BOOLEAN_P));
 
 STATIC_OVL const char *
 equipname(otmp)
@@ -50,7 +51,7 @@
 	    pline("%s quickly snatches some gold from between your %s!",
 		    Monnam(mtmp), makeplural(body_part(FOOT)));
 	    if(!u.ugold || !rn2(5)) {
-		if (!tele_restrict(mtmp)) rloc(mtmp);
+		if (!tele_restrict(mtmp)) (void) rloc(mtmp, FALSE);
 		/* do not set mtmp->mavenge here; gold on the floor is fair game */
 		monflee(mtmp, 0, FALSE, FALSE);
 	    }
@@ -58,7 +59,7 @@
 	    u.ugold -= (tmp = somegold());
 	    Your("purse feels lighter.");
 	    mtmp->mgold += tmp;
-	if (!tele_restrict(mtmp)) rloc(mtmp);
+	if (!tele_restrict(mtmp)) (void) rloc(mtmp, FALSE);
 	    mtmp->mavenge = 1;
 	    monflee(mtmp, 0, FALSE, FALSE);
 	    flags.botl = 1;
@@ -119,7 +120,7 @@
 	    pline("%s quickly snatches some gold from between your %s!",
 		    Monnam(mtmp), makeplural(body_part(FOOT)));
 	    if(!ygold || !rn2(5)) {
-		if (!tele_restrict(mtmp)) rloc(mtmp);
+		if (!tele_restrict(mtmp)) (void) rloc(mtmp, FALSE);
 		monflee(mtmp, 0, FALSE, FALSE);
 	    }
 	} else if(ygold) {
@@ -130,7 +131,7 @@
             freeinv(ygold);
             add_to_minv(mtmp, ygold);
 	    Your("purse feels lighter.");
-	    if (!tele_restrict(mtmp)) rloc(mtmp);
+	    if (!tele_restrict(mtmp)) (void) rloc(mtmp, FALSE);
 	    monflee(mtmp, 0, FALSE, FALSE);
 	    flags.botl = 1;
 	}
@@ -162,7 +163,7 @@
 			/* Implies seduction, "you gladly hand over ..."
 			   so we don't set mavenge bit here. */
 			monflee(mtmp, 0, FALSE, FALSE);
-			if (!tele_restrict(mtmp)) rloc(mtmp);
+			if (!tele_restrict(mtmp)) (void) rloc(mtmp, FALSE);
 		        break;
 		    }
 		}
@@ -196,6 +197,10 @@
 	    else if (obj == uarmg) (void) Gloves_off();
 	    else if (obj == uarmh) (void) Helmet_off();
 	    else if (obj == uarms) (void) Shield_off();
+#ifdef TOURIST
+	    else if (obj == uarmu) (void) Shirt_off();
+#endif
+	    /* catchall -- should never happen */
 	    else setworn((struct obj *)0, obj->owornmask & W_ARMOR);
 	} else if (obj->owornmask & W_AMUL) {
 	    Amulet_off();
@@ -506,13 +511,66 @@
 	(void) mpickobj(mtmp,otmp);	/* may merge and free otmp */
 	pline("%s stole %s!", Monnam(mtmp), doname(otmp));
 	if (can_teleport(mtmp->data) && !tele_restrict(mtmp))
-	    rloc(mtmp);
+	    (void) rloc(mtmp, FALSE);
     }
 }
 
 #endif /* OVLB */
 #ifdef OVL0
 
+/* drop one object taken from a (possibly dead) monster's inventory */
+STATIC_OVL void
+mdrop_obj(mon, obj, verbosely)
+struct monst *mon;
+struct obj *obj;
+boolean verbosely;
+{
+    int omx = mon->mx, omy = mon->my;
+
+    if (obj->owornmask) {
+	/* perform worn item handling if the monster is still alive */
+	if (mon->mhp > 0) {
+	    mon->misc_worn_check &= ~obj->owornmask;
+	    update_mon_intrinsics(mon, obj, FALSE, TRUE);
+	 /* obj_no_longer_held(obj); -- done by place_object */
+	    if (obj->owornmask & W_WEP) setmnotwielded(mon, obj);
+#ifdef STEED
+	/* don't charge for an owned saddle on dead steed */
+	} else if (mon->mtame && (obj->owornmask & W_SADDLE) && 
+		!obj->unpaid && costly_spot(omx, omy)) {
+	    obj->no_charge = 1;
+#endif
+	}
+	obj->owornmask = 0L;
+    }
+    if (verbosely && cansee(omx, omy))
+	pline("%s drops %s.", Monnam(mon), distant_name(obj, doname));
+    if (!flooreffects(obj, omx, omy, "fall")) {
+	place_object(obj, omx, omy);
+	stackobj(obj);
+    }
+}
+
+/* some monsters bypass the normal rules for moving between levels or
+   even leaving the game entirely; when that happens, prevent them from
+   taking the Amulet or invocation tools with them */
+void
+mdrop_special_objs(mon)
+struct monst *mon;
+{
+    struct obj *obj, *otmp;
+
+    for (obj = mon->minvent; obj; obj = otmp) {
+	otmp = obj->nobj;
+	/* the Amulet, invocation tools, and Rider corpses resist even when
+	   artifacts and ordinary objects are given 0% resistance chance */
+	if (obj_resists(obj, 0, 0)) {
+	    obj_extract_self(obj);
+	    mdrop_obj(mon, obj, FALSE);
+	}
+    }
+}
+
 /* release the objects the creature is carrying */
 void
 relobj(mtmp,show,is_pet)
@@ -530,11 +588,12 @@
 		item1 = item2 = TRUE;
 	if (!tunnels(mtmp->data) || !needspick(mtmp->data))
 		item1 = TRUE;
+
 	while ((otmp = mtmp->minvent) != 0) {
 		obj_extract_self(otmp);
 		/* special case: pick-axe and unicorn horn are non-worn */
 		/* items that we also want pets to keep 1 of */
-		/* (It is a coincidence that these can also be wielded. */
+		/* (It is a coincidence that these can also be wielded.) */
 		if (otmp->owornmask || otmp == wep ||
 		    ((!item1 && otmp->otyp == PICK_AXE) ||
 		     (!item2 && otmp->otyp == UNICORN_HORN && !otmp->cursed))) {
@@ -547,28 +606,10 @@
 				keepobj = otmp;
 				continue;
 			}
-			mtmp->misc_worn_check &= ~(otmp->owornmask);
-#ifdef STEED
-			/* don't charge for an owned saddle on dead pet */
-			if (mtmp->mtame && mtmp->mhp == 0 &&
-			    (otmp->owornmask & W_SADDLE) && !otmp->unpaid &&
-			    costly_spot(mtmp->mx, mtmp->my))
-				otmp->no_charge = 1;
-#endif
-			if (otmp->owornmask)
-			    update_mon_intrinsics(mtmp, otmp, FALSE, TRUE);
-		     /* obj_no_longer_held(otmp); -- done by place_object */
-			if (otmp->owornmask & W_WEP)
-			    setmnotwielded(mtmp, otmp);
-			otmp->owornmask = 0L;
 		}
-		if (is_pet && cansee(omx, omy) && flags.verbose)
-			pline("%s drops %s.", Monnam(mtmp),
-					distant_name(otmp, doname));
-		if (flooreffects(otmp, omx, omy, "fall")) continue;
-		place_object(otmp, omx, omy);
-		stackobj(otmp);
+		mdrop_obj(mtmp, otmp, is_pet && flags.verbose);
 	}
+
 	/* put kept objects back */
 	while ((otmp = keepobj) != (struct obj *)0) {
 	    keepobj = otmp->nobj;

Index: options.c
===================================================================
RCS file: /cvsroot/pkg-nethack/nethack/src/options.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -d -r1.1.1.1 -r1.2
--- options.c	7 Oct 2003 19:00:16 -0000	1.1.1.1
+++ options.c	9 Dec 2003 16:14:43 -0000	1.2
@@ -1,4 +1,4 @@
-/*	SCCS Id: @(#)options.c	3.4	2003/05/19	*/
+/*	SCCS Id: @(#)options.c	3.4	2003/11/14	*/
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
 /* NetHack may be freely redistributed.  See license for details. */
 
@@ -253,6 +253,7 @@
 						4, SET_IN_FILE },
 	{ "menu_first_page", "jump to the first page in a menu",
 						4, SET_IN_FILE },
+	{ "menu_headings", "bold, inverse, or underline headings", 9, SET_IN_GAME },
 	{ "menu_invert_all", "invert all items in a menu", 4, SET_IN_FILE },
 	{ "menu_invert_page", "invert all items on this page of a menu",
 						4, SET_IN_FILE },
@@ -437,6 +438,10 @@
 STATIC_OVL boolean FDECL(wc_supported, (const char *));
 STATIC_OVL boolean FDECL(is_wc2_option, (const char *));
 STATIC_OVL boolean FDECL(wc2_supported, (const char *));
+#ifdef AUTOPICKUP_EXCEPTIONS
+STATIC_DCL void FDECL(remove_autopickup_exception, (struct autopickup_exception *));
+STATIC_OVL int FDECL(count_ape_maps, (int *, int *));
+#endif
 
 /* check whether a user-supplied option string is a proper leading
    substring of a particular option name; option string might have
@@ -506,6 +511,7 @@
 #ifdef TTY_GRAPHICS
 	iflags.prevmsg_window = 's';
 #endif
+	iflags.menu_headings = ATR_INVERSE;
 
 	/* Use negative indices to indicate not yet selected */
 	flags.initrole = -1;
@@ -1447,6 +1453,7 @@
 	/* boulder:symbol */
 	fullname = "boulder";
 	if (match_optname(opts, fullname, 7, TRUE)) {
+		int clash = 0;
 		if (negated) {
 		    bad_negation(fullname, FALSE);
 		    return;
@@ -1455,11 +1462,22 @@
 		if (!(opts = string_for_opt(opts, FALSE)))
 			return;
 		escapes(opts, opts);
-
-		/*
-		 * Override the default boulder symbol.
-		 */
-		iflags.bouldersym = (uchar) opts[0];
+		if (def_char_to_monclass(opts[0]) != MAXMCLASSES)
+			clash = 1;
+		else if (opts[0] >= '1' && opts[0] <= '5')
+			clash = 2;
+		if (clash) {
+			/* symbol chosen matches a used monster or warning
+			   symbol which is not good - reject it*/
+			pline(
+		  "Badoption - boulder symbol '%c' conflicts with a %s symbol.",
+				opts[0], (clash == 1) ? "monster" : "warning");
+		} else {
+			/*
+			 * Override the default boulder symbol.
+			 */
+			iflags.bouldersym = (uchar) opts[0];
+		}
 		if (!initial) need_redraw = TRUE;
 		return;
 	}
@@ -2056,6 +2074,26 @@
 		return;
 	}
 
+	fullname = "menu_headings";
+	if (match_optname(opts, fullname, 12, TRUE)) {
+		if (negated) {
+			bad_negation(fullname, FALSE);
+			return;
+		}
+		else if (!(opts = string_for_env_opt(fullname, opts, FALSE))) {
+			return;
+		}
+		if (!strcmpi(opts,"bold"))
+			iflags.menu_headings = ATR_BOLD;
+		else if (!strcmpi(opts,"inverse"))
+			iflags.menu_headings = ATR_INVERSE;
+		else if (!strcmpi(opts,"underline"))
+			iflags.menu_headings = ATR_ULINE;
+		else
+			badoption(opts);
+		return;
+	}
+
 	/* check for menu command mapping */
 	for (i = 0; i < NUM_MENU_CMDS; i++) {
 	    fullname = default_menu_cmd_info[i].name;
@@ -2345,7 +2383,7 @@
 	start_menu(tmpwin);
 
 	any.a_void = 0;
- add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_BOLD,
+ add_menu(tmpwin, NO_GLYPH, &any, 0, 0, iflags.menu_headings,
 		 "Booleans (selecting will toggle value):", MENU_UNSELECTED);
 	any.a_int = 0;
 	/* first list any other non-modifiable booleans, then modifiable ones */
@@ -2379,7 +2417,7 @@
 	indexoffset = boolcount;
 	any.a_void = 0;
 	add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, "", MENU_UNSELECTED);
- add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_BOLD,
+ add_menu(tmpwin, NO_GLYPH, &any, 0, 0, iflags.menu_headings,
 		 "Compounds (selecting will prompt for new value):",
 		 MENU_UNSELECTED);
 
@@ -2421,9 +2459,17 @@
 				doset_add_menu(tmpwin, compopt[i].name,
 					(pass == DISP_IN_GAME) ? 0 : indexoffset);
 		}
+#ifdef AUTOPICKUP_EXCEPTIONS
+	any.a_int = -1;
+	Sprintf(buf, "autopickup exceptions (%d currently set)",
+		count_ape_maps((int *)0, (int *)0));
+	add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, buf, MENU_UNSELECTED);
+
+#endif /* AUTOPICKUP_EXCEPTIONS */
 #ifdef PREFIXES_IN_USE
+	any.a_void = 0;
 	add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, "", MENU_UNSELECTED);
- add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_BOLD,
+	add_menu(tmpwin, NO_GLYPH, &any, 0, 0, iflags.menu_headings,
 		 "Variable playground locations:", MENU_UNSELECTED);
 	for (i = 0; i < PREFIX_COUNT; i++)
 		doset_add_menu(tmpwin, fqn_prefix_names[i], 0);
@@ -2439,6 +2485,12 @@
 	     */
 	    for (pick_idx = 0; pick_idx < pick_cnt; ++pick_idx) {
 		opt_indx = pick_list[pick_idx].item.a_int - 1;
+#ifdef AUTOPICKUP_EXCEPTIONS
+		if (opt_indx == -2) {
+		    special_handling("autopickup_exception",
+		    			setinitial, fromfile);
+		} else
+#endif
 		if (opt_indx < boolcount) {
 		    /* boolean option */
 		    Sprintf(buf, "%s%s", *boolopt[opt_indx].addr ? "!" : "",
@@ -2488,7 +2540,11 @@
     boolean retval = FALSE;
     
     /* Special handling of menustyle, pickup_burden, pickup_types,
-       disclose, runmode, msg_window, and number_pad options. */
+     * disclose, runmode, msg_window, menu_headings, and number_pad options.
+#ifdef AUTOPICKUP_EXCEPTIONS
+     * Also takes care of interactive autopickup_exception_handling changes.
+#endif
+     */
     if (!strcmp("menustyle", optname)) {
 	const char *style_name;
 	menu_item *style_pick = (menu_item *)0;
@@ -2671,13 +2727,13 @@
 	}
 	destroy_nhwindow(tmpwin);
         retval = TRUE;
-    }
-    else if (!strcmp("number_pad", optname)) {
+    } else if (!strcmp("number_pad", optname)) {
 	static const char *npchoices[3] =
 		{"0 (off)", "1 (on)", "2 (on, DOS compatible)"};
-	char *npletters = "abc";
+	const char *npletters = "abc";
 	menu_item *mode_pick = (menu_item *)0;
-        tmpwin = create_nhwindow(NHW_MENU);
+
+	tmpwin = create_nhwindow(NHW_MENU);
 	start_menu(tmpwin);
 	for (i = 0; i < SIZE(npchoices); i++) {
 		any.a_int = i + 1;
@@ -2705,6 +2761,119 @@
         }
 	destroy_nhwindow(tmpwin);
         retval = TRUE;
+    } else if (!strcmp("menu_headings", optname)) {
+	static const char *mhchoices[3] = {"bold", "inverse", "underline"};
+	const char *npletters = "biu";
+	menu_item *mode_pick = (menu_item *)0;
+
+	tmpwin = create_nhwindow(NHW_MENU);
+	start_menu(tmpwin);
+	for (i = 0; i < SIZE(mhchoices); i++) {
+		any.a_int = i + 1;
+		add_menu(tmpwin, NO_GLYPH, &any, npletters[i], 0,
+			 ATR_NONE, mhchoices[i], MENU_UNSELECTED);
+        }
+	end_menu(tmpwin, "How to highlight menu headings:");
+	if (select_menu(tmpwin, PICK_ONE, &mode_pick) > 0) {
+		int mode = mode_pick->item.a_int - 1;
+		switch(mode) {
+			case 2:
+				iflags.menu_headings = ATR_ULINE;
+				break;
+			case 0:
+				iflags.menu_headings = ATR_BOLD;
+				break;
+			case 1:
+			default:
+				iflags.menu_headings = ATR_INVERSE;
+		}
+		free((genericptr_t)mode_pick);
+        }
+	destroy_nhwindow(tmpwin);
+        retval = TRUE;
+#ifdef AUTOPICKUP_EXCEPTIONS
+    } else if (!strcmp("autopickup_exception", optname)) {
+    	boolean retval;
+	int pick_cnt, pick_idx, opt_idx, pass;
+	int totalapes = 0, numapes[2] = {0,0};
+	menu_item *pick_list = (menu_item *)0;
+	anything any;
+	char apebuf[BUFSZ];
+	struct autopickup_exception *ape;
+	static const char *action_titles[] = {
+		"a", "add new autopickup exception",
+		"l", "list autopickup exceptions",
+		"r", "remove existing autopickup exception",
+		"e", "exit this menu",
+	};
+ape_again:
+	opt_idx = 0;
+	totalapes = count_ape_maps(&numapes[AP_LEAVE], &numapes[AP_GRAB]);
+	tmpwin = create_nhwindow(NHW_MENU);
+	start_menu(tmpwin);
+	any.a_int = 0;
+	for (i = 0; i < SIZE(action_titles) ; i += 2) {
+		any.a_int++;
+		if (!totalapes && (i >= 2 && i < 6)) continue;
+		add_menu(tmpwin, NO_GLYPH, &any, *action_titles[i],
+		      0, ATR_NONE, action_titles[i+1], MENU_UNSELECTED);
+        }
+	end_menu(tmpwin, "Do what?");
+	if ((pick_cnt = select_menu(tmpwin, PICK_ONE, &pick_list)) > 0) {
+		for (pick_idx = 0; pick_idx < pick_cnt; ++pick_idx) {
+			opt_idx = pick_list[pick_idx].item.a_int - 1;
+		}
+		free((genericptr_t)pick_list);
+		pick_list = (menu_item *)0;
+	}
+	destroy_nhwindow(tmpwin);
+	if (pick_cnt < 1) return FALSE;
+
+	if (opt_idx == 0) {	/* add new */
+		getlin("What new autopickup exception pattern?", &apebuf[1]);
+		if (apebuf[1] == '\033') return FALSE;
+		apebuf[0] = '"';
+		Strcat(apebuf,"\"");
+		add_autopickup_exception(apebuf);
+		goto ape_again;
+	} else if (opt_idx == 3) {
+		retval = TRUE;
+	} else {	/* remove */
+		tmpwin = create_nhwindow(NHW_MENU);
+		start_menu(tmpwin);
+		for (pass = AP_LEAVE; pass <= AP_GRAB; ++pass) {
+		    if (numapes[pass] == 0) continue;
+		    ape = iflags.autopickup_exceptions[pass];
+		    any.a_void = 0;
+		    add_menu(tmpwin, NO_GLYPH, &any, 0, 0, iflags.menu_headings,
+				(pass == 0) ? "Never pickup" : "Always pickup",
+				MENU_UNSELECTED);
+		    for (i = 0; i < numapes[pass] && ape; i++) {
+			any.a_void = (opt_idx == 1) ? 0 : ape;
+			Sprintf(apebuf, "\"%s\"", ape->pattern);
+			add_menu(tmpwin, NO_GLYPH, &any,
+				0, 0, ATR_NONE, apebuf, MENU_UNSELECTED);
+			ape = ape->next;
+		    }
+		}
+		Sprintf(apebuf, "%s autopickup exceptions",
+			(opt_idx == 1) ? "List of" : "Remove which");
+		end_menu(tmpwin, apebuf);
+		pick_cnt = select_menu(tmpwin,
+					(opt_idx == 1) ?  PICK_NONE : PICK_ANY,
+					&pick_list);
+		if (pick_cnt > 0) {
+	    	    for (pick_idx = 0; pick_idx < pick_cnt; ++pick_idx)
+			remove_autopickup_exception(
+			 (struct autopickup_exception *)pick_list[pick_idx].item.a_void);
+	        }
+	        free((genericptr_t)pick_list);
+	        pick_list = (menu_item *)0;
+		destroy_nhwindow(tmpwin);
+		goto ape_again;
+	}
+	retval = TRUE;
+#endif /* AUTOPICKUP_EXCEPTIONS */
     }
     return retval;
 }
@@ -2829,6 +2998,12 @@
 		Sprintf(buf, "%s", to_be_done);
 	else if (!strcmp(optname, "menu_invert_all"))
 		Sprintf(buf, "%s", to_be_done);
+	else if (!strcmp(optname, "menu_headings")) {
+		Sprintf(buf, "%s", (iflags.menu_headings == ATR_BOLD) ?
+			"bold" :   (iflags.menu_headings == ATR_INVERSE) ?
+			"inverse" :   (iflags.menu_headings == ATR_ULINE) ?
+			"underline" : "unknown");
+	}
 	else if (!strcmp(optname, "menu_invert_page"))
 		Sprintf(buf, "%s", to_be_done);
 	else if (!strcmp(optname, "menu_last_page"))
@@ -2977,13 +3152,115 @@
 	flags.pickup = !flags.pickup;
 	if (flags.pickup) {
 	    oc_to_str(flags.pickup_types, ocl);
-	    Sprintf(buf, "ON, for %s objects", ocl[0] ? ocl : "all");
+	    Sprintf(buf, "ON, for %s objects%s", ocl[0] ? ocl : "all",
+#ifdef AUTOPICKUP_EXCEPTIONS
+			(iflags.autopickup_exceptions[AP_LEAVE] ||
+			 iflags.autopickup_exceptions[AP_GRAB]) ?
+			 ((count_ape_maps((int *)0, (int *)0) == 1) ?
+			    ", with one exception" : ", with some exceptions") :
+#endif
+			"");
 	} else {
 	    Strcpy(buf, "OFF");
 	}
 	pline("Autopickup: %s.", buf);
 	return 0;
 }
+
+#ifdef AUTOPICKUP_EXCEPTIONS
+int
+add_autopickup_exception(mapping)
+const char *mapping;
+{
+	struct autopickup_exception *ape, **apehead;
+	char text[256], *text2;
+	int textsize = 0;
+	boolean grab = FALSE;
+
+	if (sscanf(mapping, "\"%255[^\"]\"", text) == 1) {
+		text2 = &text[0];
+		if (*text2 == '<') {		/* force autopickup */
+			grab = TRUE;
+			++text2;
+		} else if (*text2 == '>') {	/* default - Do not pickup */
+			grab = FALSE;
+			++text2;
+		}
+		textsize = strlen(text2);
+		apehead = (grab) ? &iflags.autopickup_exceptions[AP_GRAB] :
+				   &iflags.autopickup_exceptions[AP_LEAVE];
+		ape = (struct autopickup_exception *)
+				alloc(sizeof(struct autopickup_exception));
+		ape->pattern = (char *) alloc(textsize+1);
+		Strcpy(ape->pattern, text2);
+		ape->grab = grab;
+		if (!*apehead) ape->next = (struct autopickup_exception *)0;
+		else ape->next = *apehead;
+		*apehead = ape;
+	} else {
+	    raw_print("syntax error in AUTOPICKUP_EXCEPTION");
+	    return 0;
+	}
+	return 1;
+}
+
+STATIC_OVL void
+remove_autopickup_exception(whichape)
+struct autopickup_exception *whichape;
+{
+    struct autopickup_exception *ape, *prev = 0;
+    int chain = whichape->grab ? AP_GRAB : AP_LEAVE;
+
+    for (ape = iflags.autopickup_exceptions[chain]; ape;) {
+	if (ape == whichape) {
+	    struct autopickup_exception *freeape = ape;
+	    ape = ape->next;
+	    if (prev) prev->next = ape;
+	    else iflags.autopickup_exceptions[chain] = ape;
+	    free(freeape->pattern);
+	    free(freeape);
+	} else {
+	    prev = ape;
+	    ape = ape->next;
+	}
+    }
+}
+
+STATIC_OVL int
+count_ape_maps(leave, grab)
+int *leave, *grab;
+{
+	struct autopickup_exception *ape;
+	int pass, totalapes, numapes[2] = {0,0};
+
+	for (pass = AP_LEAVE; pass <= AP_GRAB; ++pass) {
+		ape = iflags.autopickup_exceptions[pass];
+		while(ape) {
+			ape = ape->next;
+			numapes[pass]++;
+		}
+	}
+	totalapes = numapes[AP_LEAVE] + numapes[AP_GRAB];
+	if (leave) *leave = numapes[AP_LEAVE];
+	if (grab) *grab = numapes[AP_GRAB];
+	return totalapes;
+}
+
+void
+free_autopickup_exceptions()
+{
+	struct autopickup_exception *ape;
+	int pass;
+
+	for (pass = AP_LEAVE; pass <= AP_GRAB; ++pass) {
+		while((ape = iflags.autopickup_exceptions[pass]) != 0) {
+			free(ape->pattern);
+			iflags.autopickup_exceptions[pass] = ape->next;
+			free(ape);
+		}
+	}
+}
+#endif /* AUTOPICKUP_EXCEPTIONS */
 
 /* data for option_help() */
 static const char *opt_intro[] = {

Index: detect.c
===================================================================
RCS file: /cvsroot/pkg-nethack/nethack/src/detect.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -d -r1.1.1.1 -r1.2
--- detect.c	7 Oct 2003 19:00:10 -0000	1.1.1.1
+++ detect.c	9 Dec 2003 16:14:43 -0000	1.2
@@ -402,6 +402,7 @@
 int		class;		/* an object class, 0 for all */
 {
     register int x, y;
+    char stuff[BUFSZ];
     int is_cursed = (detector && detector->cursed);
     int do_dknown = (detector && (detector->oclass == POTION_CLASS ||
 				    detector->oclass == SPBOOK_CLASS) &&
@@ -410,22 +411,33 @@
     register struct obj *obj, *otmp = (struct obj *)0;
     register struct monst *mtmp;
     int uw = u.uinwater;
-    const char *stuff;
+    int sym, boulder = 0;
 
     if (class < 0 || class >= MAXOCLASSES) {
 	impossible("object_detect:  illegal class %d", class);
 	class = 0;
     }
 
+    /* Special boulder symbol check - does the class symbol happen
+     * to match iflags.bouldersym which is a user-defined?
+     * If so, that means we aren't sure what they really wanted to
+     * detect. Rather than trump anything, show both possibilities.
+     * We can exclude checking the buried obj chain for boulders below.
+     */
+    sym = class ? def_oc_syms[class] : 0;
+    if (sym && iflags.bouldersym && sym == iflags.bouldersym)
+    	boulder = ROCK_CLASS;
+
     if (Hallucination || (Confusion && class == SCROLL_CLASS))
-	stuff = something;
+	Strcpy(stuff, something);
     else
-	stuff = class ? oclass_names[class] : "objects";
+    	Strcpy(stuff, class ? oclass_names[class] : "objects");
+    if (boulder && class != ROCK_CLASS) Strcat(stuff, " and/or large stones");
 
     if (do_dknown) for(obj = invent; obj; obj = obj->nobj) do_dknown_of(obj);
 
     for (obj = fobj; obj; obj = obj->nobj) {
-	if (!class || o_in(obj, class)) {
+	if ((!class && !boulder) || o_in(obj, class) || o_in(obj, boulder)) {
 	    if (obj->ox == u.ux && obj->oy == u.uy) ctu++;
 	    else ct++;
 	}
@@ -443,7 +455,7 @@
     for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
 	if (DEADMONSTER(mtmp)) continue;
 	for (obj = mtmp->minvent; obj; obj = obj->nobj) {
-	    if (!class || o_in(obj, class)) ct++;
+	    if ((!class && !boulder) || o_in(obj, class) || o_in(obj, boulder)) ct++;
 	    if (do_dknown) do_dknown_of(obj);
 	}
 	if ((is_cursed && mtmp->m_ap_type == M_AP_OBJECT &&
@@ -497,8 +509,9 @@
     for (x = 1; x < COLNO; x++)
 	for (y = 0; y < ROWNO; y++)
 	    for (obj = level.objects[x][y]; obj; obj = obj->nexthere)
-		if (!class || (otmp = o_in(obj, class))) {
-		    if (class) {
+		if ((!class && !boulder) ||
+		    (otmp = o_in(obj, class)) || (otmp = o_in(obj, boulder))) {
+		    if (class || boulder) {
 			if (otmp != obj) {
 			    otmp->ox = obj->ox;
 			    otmp->oy = obj->oy;
@@ -513,8 +526,9 @@
     for (mtmp = fmon ; mtmp ; mtmp = mtmp->nmon) {
 	if (DEADMONSTER(mtmp)) continue;
 	for (obj = mtmp->minvent; obj; obj = obj->nobj)
-	    if (!class || (otmp = o_in(obj, class))) {
-		if (!class) otmp = obj;
+	    if ((!class && !boulder) ||
+		 (otmp = o_in(obj, class)) || (otmp = o_in(obj, boulder))) {
+		if (!class && !boulder) otmp = obj;
 		otmp->ox = mtmp->mx;		/* at monster location */
 		otmp->oy = mtmp->my;
 		map_object(otmp, 1);
@@ -597,9 +611,17 @@
 	cls();
 	for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
 	    if (DEADMONSTER(mtmp)) continue;
-	    if (!mclass || mtmp->data->mlet == mclass)
-	    if (mtmp->mx > 0)
-		show_glyph(mtmp->mx,mtmp->my,mon_to_glyph(mtmp));
+	    if (!mclass || mtmp->data->mlet == mclass ||
+		(mtmp->data == &mons[PM_LONG_WORM] && mclass == S_WORM_TAIL))
+		    if (mtmp->mx > 0) {
+		    	if (mclass && def_monsyms[mclass] == ' ')
+				show_glyph(mtmp->mx,mtmp->my,
+					detected_mon_to_glyph(mtmp));
+			else
+				show_glyph(mtmp->mx,mtmp->my,mon_to_glyph(mtmp));
+			/* don't be stingy - display entire worm */
+			if (mtmp->data == &mons[PM_LONG_WORM]) detect_wsegs(mtmp,0);
+		    }
 	    if (otmp && otmp->cursed &&
 		(mtmp->msleeping || !mtmp->mcanmove)) {
 		mtmp->msleeping = mtmp->mfrozen = 0;
@@ -793,7 +815,7 @@
 	    }
 	    break;
 	case 4 : pline("%s your mind!", Tobjnam(obj, "zap"));
-	    make_hallucinated(HHallucination + rnd(100),FALSE,0L);
+	    (void) make_hallucinated(HHallucination + rnd(100),FALSE,0L);
 	    break;
 	case 5 : pline("%s!", Tobjnam(obj, "explode"));
 	    useup(obj);
@@ -833,7 +855,8 @@
     /* read a single character */
     if (flags.verbose) You("may look for an object or monster symbol.");
     ch = yn_function("What do you look for?", (char *)0, '\0');
-    if (index(quitchars,ch)) {
+    /* Don't filter out ' ' here; it has a use */
+    if ((ch != def_monsyms[S_GHOST]) && index(quitchars,ch)) { 
 	if (flags.verbose) pline(Never_mind);
 	return;
     }
@@ -849,10 +872,17 @@
 	makeknown(CRYSTAL_BALL);
 	consume_obj_charge(obj, TRUE);
 
+	/* special case: accept ']' as synonym for mimic
+	 * we have to do this before the def_char_to_objclass check
+	 */
+	if (ch == DEF_MIMIC_DEF) ch = DEF_MIMIC;
+
 	if ((class = def_char_to_objclass(ch)) != MAXOCLASSES)
 		ret = object_detect((struct obj *)0, class);
 	else if ((class = def_char_to_monclass(ch)) != MAXMCLASSES)
 		ret = monster_detect((struct obj *)0, class);
+	else if (iflags.bouldersym && (ch == iflags.bouldersym))
+		ret = object_detect((struct obj *)0, ROCK_CLASS);
 	else switch(ch) {
 		case '^':
 		    ret = trap_detect((struct obj *)0);

Index: fountain.c
===================================================================
RCS file: /cvsroot/pkg-nethack/nethack/src/fountain.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -d -r1.1.1.1 -r1.2
--- fountain.c	7 Oct 2003 19:00:12 -0000	1.1.1.1
+++ fountain.c	9 Dec 2003 16:14:43 -0000	1.2
@@ -391,7 +391,8 @@
 		if(in_town(u.ux, u.uy))
 		    (void) angry_guards(FALSE);
 		return;
-	} else (void) get_wet(obj);
+	} else if (get_wet(obj) && !rn2(2))
+		return;
 
 	/* Acid and water don't mix */
 	if (obj->otyp == POT_ACID) {
@@ -549,7 +550,7 @@
 			      hcolor(OBJ_DESCR(objects[otmp->otyp])));
 			otmp->dknown = !(Blind || Hallucination);
 			otmp->quan++; /* Avoid panic upon useup() */
-			otmp->corpsenm = 1; /* kludge for docall() */
+			otmp->fromsink = 1; /* kludge for docall() */
 			(void) dopotion(otmp);
 			obfree(otmp, (struct obj *)0);
 			break;

Index: dig.c
===================================================================
RCS file: /cvsroot/pkg-nethack/nethack/src/dig.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -d -r1.1.1.1 -r1.2
--- dig.c	7 Oct 2003 19:00:10 -0000	1.1.1.1
+++ dig.c	9 Dec 2003 16:14:43 -0000	1.2
@@ -61,7 +61,7 @@
 	if(IS_ROCK(lev->typ)) return;
 	if(t_at(x, y)) return; /* don't cover the portal */
 	if ((mtmp = m_at(x, y)) != 0)	/* make sure crucial monsters survive */
-	    if(!passes_walls(mtmp->data)) rloc(mtmp);
+	    if(!passes_walls(mtmp->data)) (void) rloc(mtmp, FALSE);
     } else if(lev->typ == ROOM) return;
 
     unblock_point(x,y);	/* make sure vision knows this location is open */
@@ -1429,7 +1429,7 @@
 		char *cname = corpse_xname(obj, FALSE);
 		Your("%s%s %s away%c",
 		     obj == uwep ? "wielded " : nul, cname,
-		     vtense(cname, "rot"), obj == uwep ? '!' : '.');
+		     otense(obj, "rot"), obj == uwep ? '!' : '.');
 	    }
 	    if (obj == uwep) {
 		uwepgone();	/* now bare handed */

Index: artifact.c
===================================================================
RCS file: /cvsroot/pkg-nethack/nethack/src/artifact.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -d -r1.1.1.1 -r1.2
--- artifact.c	7 Oct 2003 19:00:09 -0000	1.1.1.1
+++ artifact.c	9 Dec 2003 16:14:43 -0000	1.2
@@ -420,7 +420,7 @@
 	     * that can print a message--need to guard against being printed
 	     * when restoring a game
 	     */
-	    make_hallucinated((long)!on, restoring ? FALSE : TRUE, wp_mask);
+	    (void) make_hallucinated((long)!on, restoring ? FALSE : TRUE, wp_mask);
 	}
 	if (spfx & SPFX_ESP) {
 	    if(on) ETelepat |= wp_mask;
@@ -707,7 +707,7 @@
 
     for (i = 0; i < NROFARTIFACTS; i++) {
 	if (artidisco[i] == 0) break;	/* empty slot implies end of list */
-	if (i == 0) putstr(tmpwin, ATR_INVERSE, "Artifacts");
+	if (i == 0) putstr(tmpwin, iflags.menu_headings, "Artifacts");
 	m = artidisco[i];
 	otyp = artilist[m].otyp;
 	Sprintf(buf, "  %s [%s %s]", artiname(m),
@@ -1157,7 +1157,7 @@
 				      The(distant_name(otmp, xname)));
 			losexp("life drainage");
 			if (magr && magr->mhp < magr->mhpmax) {
-			    magr->mhp += (u.uhpmax - oldhpmax)/2;
+			    magr->mhp += (oldhpmax - u.uhpmax)/2;
 			    if (magr->mhp > magr->mhpmax) magr->mhp = magr->mhpmax;
 			}
 			return TRUE;

Index: objnam.c
===================================================================
RCS file: /cvsroot/pkg-nethack/nethack/src/objnam.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -d -r1.1.1.1 -r1.2
--- objnam.c	7 Oct 2003 19:00:16 -0000	1.1.1.1
+++ objnam.c	9 Dec 2003 16:14:43 -0000	1.2
@@ -1,4 +1,4 @@
-/*	SCCS Id: @(#)objnam.c	3.4	2003/05/09	*/
+/*	SCCS Id: @(#)objnam.c	3.4	2003/12/04	*/
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
 /* NetHack may be freely redistributed.  See license for details. */
 
@@ -1139,7 +1139,7 @@
 		    /* also check for <prefix><space><special_subj>
 		       to catch things like "the invisible erinys" */
 		    if (len > ltmp && *(spot - ltmp) == ' ' &&
-			    strncmpi(*spec, spot - ltmp + 1, ltmp)) goto sing;
+			   !strncmpi(*spec, spot - ltmp + 1, ltmp)) goto sing;
 		}
 
 		return strcpy(buf, verb);
@@ -2051,7 +2051,7 @@
 		as++;
 	}
 	/* can't use spellings list for this one due to shuffling */
-	if (!strcmpi(bp, "grey spellbook"))
+	if (!strncmpi(bp, "grey spell", 10))
 		*(bp + 2) = 'a';
     }
 

Index: mondata.c
===================================================================
RCS file: /cvsroot/pkg-nethack/nethack/src/mondata.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -d -r1.1.1.1 -r1.2
--- mondata.c	7 Oct 2003 19:00:14 -0000	1.1.1.1
+++ mondata.c	9 Dec 2003 16:14:43 -0000	1.2
@@ -494,6 +494,10 @@
 			(str[m_i_len] == ' ' ||
 			 !strcmpi(&str[m_i_len], "s") ||
 			 !strncmpi(&str[m_i_len], "s ", 2) ||
+			 !strcmpi(&str[m_i_len], "'") ||
+			 !strncmpi(&str[m_i_len], "' ", 2) ||
+			 !strcmpi(&str[m_i_len], "'s") ||
+			 !strncmpi(&str[m_i_len], "'s ", 3) ||
 			 !strcmpi(&str[m_i_len], "es") ||
 			 !strncmpi(&str[m_i_len], "es ", 3))) {
 		    mntmp = i;
@@ -720,6 +724,7 @@
     case PM_FLAMING_SPHERE:
     case PM_FIRE_VORTEX:
     case PM_FIRE_ELEMENTAL:
+    case PM_SALAMANDER:
 	what = "already on fire";
 	break;
     case PM_WATER_ELEMENTAL:

Index: timeout.c
===================================================================
RCS file: /cvsroot/pkg-nethack/nethack/src/timeout.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -d -r1.1.1.1 -r1.2
--- timeout.c	7 Oct 2003 19:00:20 -0000	1.1.1.1
+++ timeout.c	9 Dec 2003 16:14:43 -0000	1.2
@@ -251,16 +251,11 @@
 			if ((m_idx = name_to_mon(killer)) >= LOW_PM) {
 			    if (type_is_pname(&mons[m_idx])) {
 				killer_format = KILLED_BY;
-			    }
-#if 0				/* at present, there aren't any monster
-				   poisoners with titles rather than names */
-			    else if (mons[m_idx].geno & G_UNIQ) {
-				char buf[BUFSZ];
-				Sprintf(buf, "the %s", killer);
-				Strcpy(u.usick_cause, buf);
+			    } else if (mons[m_idx].geno & G_UNIQ) {
+				killer = the(killer);
+				Strcpy(u.usick_cause, killer);
 				killer_format = KILLED_BY;
 			    }
-#endif
 			}
 			u.usick_type = 0;
 			done(POISONING);
@@ -306,7 +301,7 @@
 			break;
 		case HALLUC:
 			HHallucination = 1;
-			make_hallucinated(0L, TRUE, 0L);
+			(void) make_hallucinated(0L, TRUE, 0L);
 			stop_occupation();
 			break;
 		case SLEEPING:

Index: pray.c
===================================================================
RCS file: /cvsroot/pkg-nethack/nethack/src/pray.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -d -r1.1.1.1 -r1.2
--- pray.c	7 Oct 2003 19:00:17 -0000	1.1.1.1
+++ pray.c	9 Dec 2003 16:14:43 -0000	1.2
@@ -436,7 +436,7 @@
 		    break;
 	    case TROUBLE_HALLUCINATION:
 		    pline ("Looks like you are back in Kansas.");
-		    make_hallucinated(0L,FALSE,0L);
+		    (void) make_hallucinated(0L,FALSE,0L);
 		    break;
 #ifdef STEED
 	    case TROUBLE_SADDLE:

Index: mkmap.c
===================================================================
RCS file: /cvsroot/pkg-nethack/nethack/src/mkmap.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -d -r1.1.1.1 -r1.2
--- mkmap.c	7 Oct 2003 19:00:14 -0000	1.1.1.1
+++ mkmap.c	9 Dec 2003 16:14:43 -0000	1.2
@@ -388,18 +388,6 @@
 	    /* TODO: ensure remaining parts of room are still joined */
 
 	    if (!croom->irregular) impossible("regular room in joined map");
-
-	    /* if a "donut" or even disconnected room, leave bounds alone */
-	    if ((croom->lx < lx && croom->hx >= hx) ||
-		(croom->ly < ly && croom->hy >= hy)) {
-		continue;
-	    }
-
-	    /* truncate the side(s) that are covered by the region */
-	    if (croom->lx < lx && croom->hx < hx) croom->hx = lx - 1;
-	    if (croom->lx >= lx && croom->hx >= hx) croom->lx = hx;
-	    if (croom->ly < ly && croom->hy < hy) croom->hy = ly - 1;
-	    if (croom->ly >= ly && croom->hy >= hy) croom->ly = hy;
 	} else {
 	    /* total overlap, remove the room */
 	    remove_room((unsigned)i);

Index: teleport.c
===================================================================
RCS file: /cvsroot/pkg-nethack/nethack/src/teleport.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -d -r1.1.1.1 -r1.2
--- teleport.c	7 Oct 2003 19:00:19 -0000	1.1.1.1
+++ teleport.c	9 Dec 2003 16:14:43 -0000	1.2
@@ -567,6 +567,7 @@
 	d_level newlevel;
 	const char *escape_by_flying = 0;	/* when surviving dest of -N */
 	char buf[BUFSZ];
+	boolean force_dest = FALSE;
 
 	if ((u.uhave.amulet || In_endgame(&u.uz) || In_sokoban(&u.uz))
 #ifdef WIZARD
@@ -608,7 +609,29 @@
 		}
 #ifdef WIZARD
 		if (wizard && !strcmp(buf,"?")) {
-		    newlev = print_dungeon(TRUE);
+		    schar destlev = 0;
+		    xchar destdnum = 0;
+
+		    if ((newlev = (int)print_dungeon(TRUE, &destlev, &destdnum))) {
+			newlevel.dnum = destdnum;
+			newlevel.dlevel = destlev;
+			if (In_endgame(&newlevel) && !In_endgame(&u.uz)) {
+				Sprintf(buf,
+				    "Destination is earth level");
+				if (!u.uhave.amulet) {
+					struct obj *obj;
+					obj = mksobj(AMULET_OF_YENDOR,
+							TRUE, FALSE);
+					if (obj) {
+						obj = addinv(obj);
+						Strcat(buf, " with the amulet");
+					}
+				}
+				assign_level(&newlevel, &earth_level);
+				pline("%s.", buf);
+			}
+			force_dest = TRUE;
+		    } else return;
 		} else
 #endif
 		if ((newlev = lev_by_name(buf)) == 0) newlev = atoi(buf);
@@ -625,9 +648,14 @@
 		    is_silent(youmonst.data) ? "writhe" : "scream");
 		display_nhwindow(WIN_MESSAGE, FALSE);
 		You("cease to exist.");
+		if (invent) Your("possessions land on the %s with a thud.",
+				surface(u.ux, u.uy));
 		killer_format = NO_KILLER_PREFIX;
 		killer = "committed suicide";
 		done(DIED);
+		pline("An energized cloud of dust begins to coalesce.");
+		Your("body rematerializes%s.", invent ?
+			", and you gather up all your possessions" : "");
 		return;
 	    }
 
@@ -678,7 +706,7 @@
 
 	killer = 0;		/* still alive, so far... */
 
-	if (newlev < 0) {
+	if (newlev < 0 && !force_dest) {
 		if (*u.ushops0) {
 		    /* take unpaid inventory items off of shop bills */
 		    in_mklev = TRUE;	/* suppress map update */
@@ -741,6 +769,9 @@
 	} else if (u.uz.dnum == medusa_level.dnum &&
 	    newlev >= dungeons[u.uz.dnum].depth_start +
 						dunlevs_in_dungeon(&u.uz)) {
+#ifdef WIZARD
+	    if (!(wizard && force_dest))
+#endif
 	    find_hell(&newlevel);
 	} else {
 	    /* if invocation did not yet occur, teleporting into
@@ -763,6 +794,9 @@
 	     * we must translate newlev to a number relative to the
 	     * current dungeon.
 	     */
+#ifdef WIZARD
+	    if (!(wizard && force_dest))
+#endif
 	    get_level(&newlevel, newlev);
 	}
 	schedule_goto(&newlevel, FALSE, FALSE, 0, (char *)0, (char *)0);
@@ -941,16 +975,18 @@
 }
 
 /* place a monster at a random location, typically due to teleport */
-void
-rloc(mtmp)
+/* return TRUE if successful, FALSE if not */
+boolean
+rloc(mtmp, suppress_impossible)
 struct monst *mtmp;	/* mx==0 implies migrating monster arrival */
+boolean suppress_impossible;
 {
 	register int x, y, trycount;
 
 #ifdef STEED
 	if (mtmp == u.usteed) {
 	    tele();
-	    return;
+	    return TRUE;
 	}
 #endif
 
@@ -984,11 +1020,13 @@
 		    goto found_xy;
 
 	/* level either full of monsters or somehow faulty */
-	impossible("rloc(): couldn't relocate monster");
-	return;
+	if (!suppress_impossible)
+		impossible("rloc(): couldn't relocate monster");
+	return FALSE;
 
  found_xy:
 	rloc_to(mtmp, x, y);
+	return TRUE;
 }
 
 STATIC_OVL void
@@ -1003,7 +1041,7 @@
 		rloc_to(mtmp, c.x, c.y);
 		return;
 	}
-	rloc(mtmp);
+	(void) rloc(mtmp, FALSE);
 }
 
 boolean
@@ -1037,7 +1075,7 @@
 	     * the guard isn't going to come for it...
 	     */
 	    if (trap->once) mvault_tele(mtmp);
-	    else rloc(mtmp);
+	    else (void) rloc(mtmp, FALSE);
 
 	    if (in_sight) {
 		if (canseemon(mtmp))
@@ -1241,12 +1279,12 @@
 	    if (give_feedback)
 		You("are no longer inside %s!", mon_nam(mtmp));
 	    unstuck(mtmp);
-	    rloc(mtmp);
+	    (void) rloc(mtmp, FALSE);
 	} else if (is_rider(mtmp->data) && rn2(13) &&
 		   enexto(&cc, u.ux, u.uy, mtmp->data))
 	    rloc_to(mtmp, cc.x, cc.y);
 	else
-	    rloc(mtmp);
+	    (void) rloc(mtmp, FALSE);
 	return TRUE;
 }
 

Index: mon.c
===================================================================
RCS file: /cvsroot/pkg-nethack/nethack/src/mon.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -d -r1.1.1.1 -r1.2
--- mon.c	7 Oct 2003 19:00:14 -0000	1.1.1.1
+++ mon.c	9 Dec 2003 16:14:43 -0000	1.2
@@ -1,4 +1,4 @@
-/*	SCCS Id: @(#)mon.c	3.4	2003/08/24	*/
+/*	SCCS Id: @(#)mon.c	3.4	2003/12/04	*/
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
 /* NetHack may be freely redistributed.  See license for details. */
 
@@ -96,7 +96,7 @@
 {
 	switch (mndx) {
 /* Quest guardians */
-	case PM_STUDENT:     mndx = mode ? PM_VALKYRIE  : PM_HUMAN; break;
+	case PM_STUDENT:     mndx = mode ? PM_ARCHEOLOGIST  : PM_HUMAN; break;
 	case PM_CHIEFTAIN:   mndx = mode ? PM_BARBARIAN : PM_HUMAN; break;
 	case PM_NEANDERTHAL: mndx = mode ? PM_CAVEMAN   : PM_HUMAN; break;
 	case PM_ATTENDANT:   mndx = mode ? PM_HEALER    : PM_HUMAN; break;
@@ -149,9 +149,16 @@
 		PM_SANDESTIN,
 };
 
-#define KEEPTRAITS(mon)	(mon->isshk || mon->mtame || \
-			 (mon->data->geno & G_UNIQ) || is_reviver(mon->data) || \
-			 (mon->m_id == quest_status.leader_m_id))
+/* for deciding whether corpse or statue will carry along full monster data */
+#define KEEPTRAITS(mon)	((mon)->isshk || (mon)->mtame ||		\
+			 ((mon)->data->geno & G_UNIQ) ||		\
+			 is_reviver((mon)->data) ||			\
+			 /* normally leader the will be unique, */	\
+			 /* but he might have been polymorphed  */	\
+			 (mon)->m_id == quest_status.leader_m_id ||	\
+			 /* special cancellation handling for these */	\
+			 (dmgtype((mon)->data, AD_SEDU) ||		\
+			  dmgtype((mon)->data, AD_SSEX)))
 
 /* Creates a monster corpse, a "special" corpse, or nothing if it doesn't
  * leave corpses.  Monsters which leave "special" corpses should have
@@ -438,7 +445,7 @@
 	    if (mtmp->mhp > 0) {
 		(void) fire_damage(mtmp->minvent, FALSE, FALSE,
 						mtmp->mx, mtmp->my);
-		rloc(mtmp);
+		(void) rloc(mtmp, FALSE);
 		return 0;
 	    }
 	    return (1);
@@ -461,7 +468,7 @@
 	    }
 	    mondead(mtmp);
 	    if (mtmp->mhp > 0) {
-		rloc(mtmp);
+		(void) rloc(mtmp, FALSE);
 		water_damage(mtmp->minvent, FALSE, FALSE);
 		return 0;
 	    }
@@ -884,7 +891,7 @@
 #endif
 		if (cansee(mtmp->mx,mtmp->my) && flags.verbose)
 			pline("%s picks up %s.", Monnam(mtmp),
-			      (distu(mtmp->my, mtmp->my) <= 5) ?
+			      (distu(mtmp->mx, mtmp->my) <= 5) ?
 				doname(otmp) : distant_name(otmp, doname));
 		obj_extract_self(otmp);
 		/* unblock point after extract, before pickup */
@@ -1568,13 +1575,18 @@
 mongone(mdef)
 register struct monst *mdef;
 {
+	mdef->mhp = 0;	/* can skip some inventory bookkeeping */
 #ifdef STEED
 	/* Player is thrown from his steed when it disappears */
 	if (mdef == u.usteed)
 		dismount_steed(DISMOUNT_GENERIC);
 #endif
 
-	discard_minvent(mdef);	/* release monster's inventory */
+	/* drop special items like the Amulet so that a dismissed Kop or nurse
+	   can't remove them from the game */
+	mdrop_special_objs(mdef);
+	/* release rest of monster's inventory--it is removed from game */
+	discard_minvent(mdef);
 #ifndef GOLDOBJ
 	mdef->mgold = 0L;
 #endif
@@ -1627,7 +1639,8 @@
 		/* defer statue creation until after inventory removal
 		   so that saved monster traits won't retain any stale
 		   item-conferred attributes */
-		otmp = mkcorpstat(STATUE, mdef, mdef->data, x, y, FALSE);
+		otmp = mkcorpstat(STATUE, KEEPTRAITS(mdef) ? mdef : 0,
+				  mdef->data, x, y, FALSE);
 		if (mdef->mnamelth) otmp = oname(otmp, NAME(mdef));
 		while ((obj = oldminvent) != 0) {
 		    oldminvent = obj->nobj;
@@ -2020,11 +2033,12 @@
 		return;
 	}
 	/* suppress killer prefix if it already has one */
-	if (!strncmpi(pname, "the ", 4) ||
-		!strncmpi(pname, "an ", 3) ||
-		!strncmpi(pname, "a ", 2) ||
-	    /* ... or if it seems to be a proper name */
-		isupper(*pname)) {
+	if ((i = name_to_mon(pname)) >= LOW_PM && mons[i].geno & G_UNIQ) {
+	    kprefix = KILLED_BY;
+	    if (!type_is_pname(&mons[i])) pname = the(pname);
+	} else if (!strncmpi(pname, "the ", 4) ||
+	    !strncmpi(pname, "an ", 3) ||
+	    !strncmpi(pname, "a ", 2)) {
 	    /*[ does this need a plural check too? ]*/
 	    kprefix = KILLED_BY;
 	}

Index: minion.c
===================================================================
RCS file: /cvsroot/pkg-nethack/nethack/src/minion.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -d -r1.1.1.1 -r1.2
--- minion.c	7 Oct 2003 19:00:14 -0000	1.1.1.1
+++ minion.c	9 Dec 2003 16:14:43 -0000	1.2
@@ -161,7 +161,7 @@
 	if (youmonst.data->mlet == S_DEMON) {	/* Won't blackmail their own. */
 	    pline("%s says, \"Good hunting, %s.\"",
 		  Amonnam(mtmp), flags.female ? "Sister" : "Brother");
-	    if (!tele_restrict(mtmp)) rloc(mtmp);
+	    if (!tele_restrict(mtmp)) (void) rloc(mtmp, FALSE);
 	    return(1);
 	}
 #ifndef GOLDOBJ

Index: wizard.c
===================================================================
RCS file: /cvsroot/pkg-nethack/nethack/src/wizard.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -d -r1.1.1.1 -r1.2
--- wizard.c	7 Oct 2003 19:00:21 -0000	1.1.1.1
+++ wizard.c	9 Dec 2003 16:14:43 -0000	1.2
@@ -311,7 +311,7 @@
 		mtmp->mavenge = 1; /* covetous monsters attack while fleeing */
 		if (In_W_tower(mtmp->mx, mtmp->my, &u.uz) ||
 			(mtmp->iswiz && !xupstair && !mon_has_amulet(mtmp))) {
-		    if (!rn2(3 + mtmp->mhp/10)) rloc(mtmp);
+		    if (!rn2(3 + mtmp->mhp/10)) (void) rloc(mtmp, FALSE);
 		} else if (xupstair &&
 			 (mtmp->mx != xupstair || mtmp->my != yupstair)) {
 		    (void) mnearto(mtmp, xupstair, yupstair, TRUE);
@@ -353,7 +353,7 @@
 			    if (cansee(mtmp->mx, mtmp->my))
 				pline("%s picks up %s.",
 				    Monnam(mtmp),
-				    (distu(mtmp->my, mtmp->my) <= 5) ?
+				    (distu(mtmp->mx, mtmp->my) <= 5) ?
 				     doname(otmp) : distant_name(otmp, doname));
 			    obj_extract_self(otmp);
 			    (void) mpickobj(mtmp, otmp);

Index: u_init.c
===================================================================
RCS file: /cvsroot/pkg-nethack/nethack/src/u_init.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -d -r1.1.1.1 -r1.2
--- u_init.c	7 Oct 2003 19:00:20 -0000	1.1.1.1
+++ u_init.c	9 Dec 2003 16:14:43 -0000	1.2
@@ -1,4 +1,4 @@
-/*	SCCS Id: @(#)u_init.c	3.4	2002/03/02	*/
+/*	SCCS Id: @(#)u_init.c	3.4	2002/10/22	*/
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
 /* NetHack may be freely redistributed.  See license for details. */
 
@@ -271,7 +271,7 @@
 
 static const struct def_skill Skill_B[] = {
     { P_DAGGER, P_BASIC },		{ P_AXE, P_EXPERT },
-    { P_PICK_AXE, P_EXPERT },		{ P_SHORT_SWORD, P_BASIC },
+    { P_PICK_AXE, P_SKILLED },	{ P_SHORT_SWORD, P_EXPERT },
     { P_BROAD_SWORD, P_SKILLED },	{ P_LONG_SWORD, P_SKILLED },
     { P_TWO_HANDED_SWORD, P_EXPERT },	{ P_SCIMITAR, P_SKILLED },
     { P_SABER, P_BASIC },		{ P_CLUB, P_SKILLED },
@@ -284,7 +284,7 @@
     { P_RIDING, P_BASIC },
 #endif
     { P_TWO_WEAPON_COMBAT, P_BASIC },
-    { P_BARE_HANDED_COMBAT, P_GRAND_MASTER },
+    { P_BARE_HANDED_COMBAT, P_MASTER },
     { P_NONE, 0 }
 };
 
@@ -299,7 +299,7 @@
     { P_BOW, P_SKILLED },		{ P_SLING, P_EXPERT },
     { P_ATTACK_SPELL, P_BASIC },	{ P_MATTER_SPELL, P_SKILLED },
     { P_BOOMERANG, P_EXPERT },		{ P_UNICORN_HORN, P_BASIC },
-    { P_BARE_HANDED_COMBAT, P_GRAND_MASTER },
+    { P_BARE_HANDED_COMBAT, P_MASTER },
     { P_NONE, 0 }
 };
 
@@ -422,7 +422,7 @@
     { P_RIDING, P_SKILLED },
 #endif
     { P_TWO_WEAPON_COMBAT, P_EXPERT },
-    { P_MARTIAL_ARTS, P_GRAND_MASTER },
+    { P_MARTIAL_ARTS, P_MASTER },
     { P_NONE, 0 }
 };
 

Index: questpgr.c
===================================================================
RCS file: /cvsroot/pkg-nethack/nethack/src/questpgr.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -d -r1.1.1.1 -r1.2
--- questpgr.c	7 Oct 2003 19:00:17 -0000	1.1.1.1
+++ questpgr.c	9 Dec 2003 16:14:43 -0000	1.2
@@ -60,7 +60,7 @@
 
 	if ((cnt = dlb_fread(ptr, size, nitems, stream)) != nitems) {
 
-	    panic("PREMATURE EOF ON QUEST TEXT FILE!\nExpected %d bytes - got %d\n",
+	    panic("PREMATURE EOF ON QUEST TEXT FILE! Expected %d bytes, got %d",
 		    (size * nitems), (size * cnt));
 	}
 }
@@ -96,7 +96,7 @@
 
 	msg_file = dlb_fopen(QTEXT_FILE, RDBMODE);
 	if (!msg_file)
-	    panic("\rCANNOT OPEN QUEST TEXT FILE %s.", QTEXT_FILE);
+	    panic("CANNOT OPEN QUEST TEXT FILE %s.", QTEXT_FILE);
 
 	/*
 	 * Read in the number of classes, then the ID's & offsets for

Index: zap.c
===================================================================
RCS file: /cvsroot/pkg-nethack/nethack/src/zap.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -d -r1.1.1.1 -r1.2
--- zap.c	7 Oct 2003 19:00:22 -0000	1.1.1.1
+++ zap.c	9 Dec 2003 16:14:43 -0000	1.2
@@ -1619,6 +1619,11 @@
 
 			    (void) get_obj_location(obj, &oox, &ooy, 0);
 			    refresh_x = oox; refresh_y = ooy;
+			    if (vegetarian(&mons[obj->corpsenm])) {
+				/* Don't animate monsters that aren't flesh */
+				obj = poly_obj(obj, MEATBALL);
+			    	goto smell;
+			    }
 			    if (!animate_statue(obj, oox, ooy,
 						ANIMATE_SPELL, (int *)0)) {
 				struct obj *item;
@@ -1652,6 +1657,11 @@
 			    res = 0;
 			    break;
 			}
+			if (vegetarian(&mons[obj->corpsenm])) {
+			    /* Don't animate monsters that aren't flesh */
+			    obj = poly_obj(obj, MEATBALL);
+			    goto smell;
+			}
 			(void) get_obj_location(obj, &oox, &ooy, 0);
 			refresh_x = oox; refresh_y = ooy;
 			mon = makemon(&mons[obj->corpsenm],
@@ -1675,7 +1685,8 @@
 			obj = poly_obj(obj, MEATBALL);
 smell:
 			if (herbivorous(youmonst.data) &&
-				!carnivorous(youmonst.data))
+			    (!carnivorous(youmonst.data) ||
+			     Role_if(PM_MONK) || !u.uconduct.unvegetarian))
 			    Norep("You smell the odor of meat.");
 			else
 			    Norep("You smell a delicious smell.");

Index: apply.c
===================================================================
RCS file: /cvsroot/pkg-nethack/nethack/src/apply.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -d -r1.1.1.1 -r1.2
--- apply.c	7 Oct 2003 19:00:08 -0000	1.1.1.1
+++ apply.c	9 Dec 2003 16:14:43 -0000	1.2
@@ -1,4 +1,4 @@
-/*	SCCS Id: @(#)apply.c	3.4	2003/05/25	*/
+/*	SCCS Id: @(#)apply.c	3.4	2003/11/18	*/
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
 /* NetHack may be freely redistributed.  See license for details. */
 
@@ -165,6 +165,8 @@
 	struct obj *otmp;
 	struct trap *ttmp;
 
+	if (!can_reach_floor()) return FALSE;
+
 	/* additional stethoscope messages from jyoung@apanix.apana.org.au */
 	if (Hallucination && sobj_at(CORPSE, rx, ry)) {
 	    /* (a corpse doesn't retain the monster's sex,
@@ -272,7 +274,7 @@
 		mstatusline(mtmp);
 		if (mtmp->mundetected) {
 			mtmp->mundetected = 0;
-			if (cansee(rx,ry)) newsym(mtmp->my,mtmp->my);
+			if (cansee(rx,ry)) newsym(mtmp->mx,mtmp->my);
 		}
 		if (!canspotmon(mtmp))
 			map_invisible(rx,ry);
@@ -718,7 +720,7 @@
 		setnotworn(obj); /* in case mirror was wielded */
 		freeinv(obj);
 		(void) mpickobj(mtmp,obj);
-		if (!tele_restrict(mtmp)) rloc(mtmp);
+		if (!tele_restrict(mtmp)) (void) rloc(mtmp, FALSE);
 	} else if (!is_unicorn(mtmp->data) && !humanoid(mtmp->data) &&
 			(!mtmp->minvis || perceives(mtmp->data)) && rn2(5)) {
 		if (vis)
@@ -1467,7 +1469,7 @@
 		    break;
 	    case 4: (void) adjattrib(rn2(A_MAX), -1, FALSE);
 		    break;
-	    case 5: make_hallucinated(HHallucination + lcount, TRUE, 0L);
+	    case 5: (void) make_hallucinated(HHallucination + lcount, TRUE, 0L);
 		    break;
 	    }
 	    return;
@@ -1544,7 +1546,7 @@
 		did_prop++;
 		break;
 	    case prop2trbl(HALLUC):
-		make_hallucinated(0L, TRUE, 0L);
+		(void) make_hallucinated(0L, TRUE, 0L);
 		did_prop++;
 		break;
 	    case prop2trbl(VOMITING):
@@ -1623,7 +1625,7 @@
 	cansee_spot = cansee(cc.x, cc.y);
 	mtmp = make_familiar(figurine, cc.x, cc.y, TRUE);
 	if (mtmp) {
-	    Sprintf(monnambuf, "%s",a_monnam(mtmp));
+	    Sprintf(monnambuf, "%s",an(m_monnam(mtmp)));
 	    switch (figurine->where) {
 		case OBJ_INVENT:
 		    if (Blind)
@@ -2357,7 +2359,8 @@
 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.";
+	cant_see_spot[] = "won't hit anything if you can't see that spot.",
+	cant_reach[] = "can't reach that spot from here.";
 
 /* Distance attacks by pole-weapons */
 STATIC_OVL int
@@ -2403,6 +2406,9 @@
 		    !canseemon(mtmp))) {
 	    You(cant_see_spot);
 	    return (res);
+	} else if (!couldsee(cc.x, cc.y)) { /* Eyes of the Overworld */
+	    You(cant_reach);
+	    return res;
 	}
 
 	/* Attack the monster there */
@@ -2501,6 +2507,9 @@
 	} else if (!cansee(cc.x, cc.y)) {
 	    You(cant_see_spot);
 	    return (res);
+	} else if (!couldsee(cc.x, cc.y)) { /* Eyes of the Overworld */
+	    You(cant_reach);
+	    return res;
 	}
 
 	/* What do you want to hit? */

Index: uhitm.c
===================================================================
RCS file: /cvsroot/pkg-nethack/nethack/src/uhitm.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -d -r1.1.1.1 -r1.2
--- uhitm.c	7 Oct 2003 19:00:20 -0000	1.1.1.1
+++ uhitm.c	9 Dec 2003 16:14:43 -0000	1.2
@@ -520,7 +520,7 @@
 	boolean hittxt = FALSE, destroyed = FALSE, already_killed = FALSE;
 	boolean get_dmg_bonus = TRUE;
 	boolean ispoisoned = FALSE, needpoismsg = FALSE, poiskilled = FALSE;
-	boolean silvermsg = FALSE;
+	boolean silvermsg = FALSE, silverobj = FALSE;
 	boolean valid_weapon_attack = FALSE;
 	boolean unarmed = !uwep && !uarm && !uarms;
 #ifdef STEED
@@ -530,8 +530,11 @@
 	struct obj *monwep;
 	char yourbuf[BUFSZ];
 	char unconventional[BUFSZ];	/* substituted for word "attack" in msg */
+	char saved_oname[BUFSZ];
 
 	unconventional[0] = '\0';
+	saved_oname[0] = '\0';
+
 	wakeup(mon);
 	if(!obj) {	/* attack with bare hands */
 	    if (mdat == &mons[PM_SHADE])
@@ -558,6 +561,7 @@
 		}
 	    }
 	} else {
+	    Strcpy(saved_oname, cxname(obj));
 	    if(obj->oclass == WEAPON_CLASS || is_weptool(obj) ||
 	       obj->oclass == GEM_CLASS) {
 
@@ -642,8 +646,9 @@
 			hittxt = TRUE;
 		    }
 		    if (objects[obj->otyp].oc_material == SILVER
-				&& hates_silver(mdat))
-			silvermsg = TRUE;
+				&& hates_silver(mdat)) {
+			silvermsg = TRUE; silverobj = TRUE;
+		    }
 #ifdef STEED
 		    if (u.usteed && !thrown && tmp > 0 &&
 			    weapon_type(obj) == P_LANCE && mon != u.ustuck) {
@@ -716,11 +721,13 @@
 #endif
 		    case CORPSE:		/* fixed by polder@cs.vu.nl */
 			if (touch_petrifies(&mons[obj->corpsenm])) {
+			    static const char withwhat[] = "corpse";
 			    tmp = 1;
 			    hittxt = TRUE;
-			    You("hit %s with %s corpse.", mon_nam(mon),
+			    You("hit %s with %s %s.", mon_nam(mon),
 				obj->dknown ? the(mons[obj->corpsenm].mname) :
-				an(mons[obj->corpsenm].mname));
+				an(mons[obj->corpsenm].mname),
+				(obj->quan > 1) ? makeplural(withwhat) : withwhat);
 			    if (!munstone(mon, TRUE))
 				minstapetrify(mon, TRUE);
 			    if (resists_ston(mon)) break;
@@ -863,6 +870,15 @@
 			if(tmp < 1) tmp = 1;
 			else tmp = rnd(tmp);
 			if(tmp > 6) tmp = 6;
+			/*
+			 * Things like silver wands can arrive here so
+			 * so we need another silver check.
+			 */
+			if (objects[obj->otyp].oc_material == SILVER
+						&& hates_silver(mdat)) {
+				tmp += rnd(20);
+				silvermsg = TRUE; silverobj = TRUE;
+			}
 		    }
 		}
 	    }
@@ -985,7 +1001,7 @@
 		   && objects[obj->otyp].oc_material == IRON
 		   && mon->mhp > 1 && !thrown && !mon->mcan
 		   /* && !destroyed  -- guaranteed by mhp > 1 */ ) {
-		if (clone_mon(mon)) {
+		if (clone_mon(mon, 0, 0)) {
 			pline("%s divides as you hit it!", Monnam(mon));
 			hittxt = TRUE;
 		}
@@ -1002,13 +1018,20 @@
 	if (silvermsg) {
 		const char *fmt;
 		char *whom = mon_nam(mon);
+		char silverobjbuf[BUFSZ];
 
 		if (canspotmon(mon)) {
 		    if (barehand_silver_rings == 1)
 			fmt = "Your silver ring sears %s!";
 		    else if (barehand_silver_rings == 2)
 			fmt = "Your silver rings sear %s!";
-		    else
+		    else if (silverobj && saved_oname[0]) {
+		    	Sprintf(silverobjbuf, "Your %s%s %s %%s!",
+		    		strstri(saved_oname, "silver") ?
+					"" : "silver ",
+				saved_oname, vtense(saved_oname, "sear"));
+		    	fmt = silverobjbuf;
+		    } else
 			fmt = "The silver sears %s!";
 		} else {
 		    *whom = highc(*whom);	/* "it" -> "It" */
@@ -1406,7 +1429,8 @@
 		if (tmp <= 0) tmp = 1;
 		if (!negated && tmp < mdef->mhp) {
 		    char nambuf[BUFSZ];
-		    boolean u_saw_mon = canseemon(mdef);
+		    boolean u_saw_mon = canseemon(mdef) ||
+					(u.uswallow && u.ustuck == mdef);
 		    /* record the name before losing sight of monster */
 		    Strcpy(nambuf, Monnam(mdef));
 		    if (u_teleport_mon(mdef, FALSE) &&
@@ -1583,9 +1607,7 @@
 		break;
 	    case AD_SLIM:
 		if (negated) break;	/* physical damage only */
-		if (!rn2(4) && mdef->data != &mons[PM_FIRE_VORTEX] &&
-				mdef->data != &mons[PM_FIRE_ELEMENTAL] &&
-				mdef->data != &mons[PM_SALAMANDER] &&
+		if (!rn2(4) && !flaming(mdef->data) &&
 				mdef->data != &mons[PM_GREEN_SLIME]) {
 		    You("turn %s into slime.", mon_nam(mdef));
 		    (void) newcham(mdef, &mons[PM_GREEN_SLIME], FALSE, FALSE);
@@ -1807,7 +1829,17 @@
 			end_engulf();
 			return(2);
 		    case AD_PHYS:
-			pline("%s is pummeled with your debris!",Monnam(mdef));
+			if (youmonst.data == &mons[PM_FOG_CLOUD]) {
+			    pline("%s is laden with your moisture.",
+				  Monnam(mdef));
+			    if (amphibious(mdef->data) &&
+				!flaming(mdef->data)) {
+				dam = 0;
+				pline("%s seems unharmed.", Monnam(mdef));
+			    }
+			} else
+			    pline("%s is pummeled with your debris!",
+				  Monnam(mdef));
 			break;
 		    case AD_ACID:
 			pline("%s is covered with your goo!", Monnam(mdef));

Index: dothrow.c
===================================================================
RCS file: /cvsroot/pkg-nethack/nethack/src/dothrow.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -d -r1.1.1.1 -r1.2
--- dothrow.c	7 Oct 2003 19:00:11 -0000	1.1.1.1
+++ dothrow.c	9 Dec 2003 16:14:43 -0000	1.2
@@ -1,4 +1,4 @@
-/*	SCCS Id: @(#)dothrow.c	3.4	2003/01/24	*/
+/*	SCCS Id: @(#)dothrow.c	3.4	2003/12/04	*/
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
 /* NetHack may be freely redistributed.  See license for details. */
 
@@ -203,6 +203,11 @@
 	shotlimit = (multi || save_cm) ? multi + 1 : 0;
 	multi = 0;		/* reset; it's been used up */
 
+	if (notake(youmonst.data)) {
+	    You("are physically incapable of throwing anything.");
+	    return 0;
+	}
+
 	if(check_capacity((char *)0)) return(0);
 	obj = getobj(uslinging() ? bullets : toss_objs, "throw");
 	/* it is also possible to throw food */
@@ -285,6 +290,11 @@
 {
 	int shotlimit;
 
+	if (notake(youmonst.data)) {
+	    You("are physically incapable of doing that.");
+	    return 0;
+	}
+
 	if(check_capacity((char *)0)) return(0);
 	if (!uquiver) {
 		if (!flags.autoquiver) {
@@ -1149,7 +1159,7 @@
        an arrow just landing short of any target (no message in that case),
        so will realize that there is a valid target here anyway. */
     if (!canseemon(mon) || (mon->m_ap_type && mon->m_ap_type != M_AP_MONSTER))
-	pline("%s misses.", The(missile));
+	pline("%s %s.", The(missile), otense(obj, "miss"));
     else
 	miss(missile, mon);
     if (!rn2(3)) wakeup(mon);
@@ -1469,7 +1479,7 @@
 
 nopick:
 	if(!Blind) pline("%s", buf);
-	if (!tele_restrict(mon)) rloc(mon);
+	if (!tele_restrict(mon)) (void) rloc(mon, FALSE);
 	return(ret);
 }
 
@@ -1678,9 +1688,6 @@
 	}
 }
 
-/*
- *  Note that the gold object is *not* attached to the fobj chain.
- */
 STATIC_OVL int
 throw_gold(obj)
 struct obj *obj;

Index: monst.c
===================================================================
RCS file: /cvsroot/pkg-nethack/nethack/src/monst.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -d -r1.1.1.1 -r1.2
--- monst.c	7 Oct 2003 19:00:15 -0000	1.1.1.1
+++ monst.c	9 Dec 2003 16:14:43 -0000	1.2
@@ -1734,7 +1734,7 @@
 	  NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
 	SIZ(500, 100, 0, MS_MUMBLE, MZ_LARGE),
 	MR_FIRE|MR_POISON, MR_FIRE|MR_POISON,
-	M1_NOLIMBS|M1_SLITHY|M1_THICK_HIDE|M1_NOTAKE, M2_STRONG,
+	M1_NOLIMBS|M1_SLITHY|M1_THICK_HIDE|M1_NOTAKE|M1_OMNIVORE, M2_STRONG,
 	M3_INFRAVISIBLE, CLR_RED),
     MON("black naga hatchling", S_NAGA,
 	LVL(3, 10, 6, 0, 0), G_GENO,
@@ -1742,27 +1742,29 @@
 	  NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
 	SIZ(500, 100, 0, MS_MUMBLE, MZ_LARGE),
 	MR_POISON|MR_ACID|MR_STONE, MR_POISON|MR_STONE,
-	M1_NOLIMBS|M1_SLITHY|M1_THICK_HIDE|M1_ACID|M1_NOTAKE,
+	M1_NOLIMBS|M1_SLITHY|M1_THICK_HIDE|M1_ACID|M1_NOTAKE|M1_CARNIVORE,
 	M2_STRONG, 0, CLR_BLACK),
     MON("golden naga hatchling", S_NAGA,
 	LVL(3, 10, 6, 0, 0), G_GENO,
 	A(ATTK(AT_BITE, AD_PHYS, 1, 4),
 	  NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
 	SIZ(500, 100, 0, MS_MUMBLE, MZ_LARGE), MR_POISON, MR_POISON,
-	M1_NOLIMBS|M1_SLITHY|M1_THICK_HIDE|M1_NOTAKE, M2_STRONG, 0, HI_GOLD),
+	M1_NOLIMBS|M1_SLITHY|M1_THICK_HIDE|M1_NOTAKE|M1_OMNIVORE,
+	M2_STRONG, 0, HI_GOLD),
     MON("guardian naga hatchling", S_NAGA,
 	LVL(3, 10, 6, 0, 0), G_GENO,
 	A(ATTK(AT_BITE, AD_PHYS, 1, 4),
 	  NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
 	SIZ(500, 100, 0, MS_MUMBLE, MZ_LARGE), MR_POISON, MR_POISON,
-	M1_NOLIMBS|M1_SLITHY|M1_THICK_HIDE|M1_NOTAKE, M2_STRONG, 0, CLR_GREEN),
+	M1_NOLIMBS|M1_SLITHY|M1_THICK_HIDE|M1_NOTAKE|M1_OMNIVORE,
+	M2_STRONG, 0, CLR_GREEN),
     MON("red naga", S_NAGA,
 	LVL(6, 12, 4, 0, -4), (G_GENO|1),
 	A(ATTK(AT_BITE, AD_PHYS, 2, 4), ATTK(AT_BREA, AD_FIRE, 2, 6),
 	  NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
 	SIZ(2600, 400, 0, MS_MUMBLE, MZ_HUGE),
 	MR_FIRE|MR_POISON, MR_FIRE|MR_POISON,
-	M1_NOLIMBS|M1_SLITHY|M1_THICK_HIDE|M1_OVIPAROUS|M1_NOTAKE,
+	M1_NOLIMBS|M1_SLITHY|M1_THICK_HIDE|M1_OVIPAROUS|M1_NOTAKE|M1_OMNIVORE,
 	M2_STRONG, M3_INFRAVISIBLE, CLR_RED),
     MON("black naga", S_NAGA,
 	LVL(8, 14, 2, 10, 4), (G_GENO|1),
@@ -1770,21 +1772,23 @@
 	  NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
 	SIZ(2600, 400, 0, MS_MUMBLE, MZ_HUGE),
 	MR_POISON|MR_ACID|MR_STONE, MR_POISON|MR_STONE,
-	M1_NOLIMBS|M1_SLITHY|M1_THICK_HIDE|M1_OVIPAROUS|M1_ACID|M1_NOTAKE,
+	M1_NOLIMBS|M1_SLITHY|M1_THICK_HIDE|M1_OVIPAROUS|M1_ACID|M1_NOTAKE|
+	  M1_CARNIVORE,
 	M2_STRONG, 0, CLR_BLACK),
     MON("golden naga", S_NAGA,
 	LVL(10, 14, 2, 70, 5), (G_GENO|1),
 	A(ATTK(AT_BITE, AD_PHYS, 2, 6), ATTK(AT_MAGC, AD_SPEL, 4, 6),
 	  NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
 	SIZ(2600, 400, 0, MS_MUMBLE, MZ_HUGE), MR_POISON, MR_POISON,
-	M1_NOLIMBS|M1_SLITHY|M1_THICK_HIDE|M1_OVIPAROUS|M1_NOTAKE,
+	M1_NOLIMBS|M1_SLITHY|M1_THICK_HIDE|M1_OVIPAROUS|M1_NOTAKE|M1_OMNIVORE,
 	M2_STRONG, 0, HI_GOLD),
     MON("guardian naga", S_NAGA,
 	LVL(12, 16, 0, 50, 7), (G_GENO|1),
 	A(ATTK(AT_BITE, AD_PLYS, 1, 6), ATTK(AT_SPIT, AD_DRST, 1, 6),
 	  ATTK(AT_HUGS, AD_PHYS, 2, 4), NO_ATTK, NO_ATTK, NO_ATTK),
 	SIZ(2600, 400, 0, MS_MUMBLE, MZ_HUGE), MR_POISON, MR_POISON,
-	M1_NOLIMBS|M1_SLITHY|M1_THICK_HIDE|M1_OVIPAROUS|M1_POIS|M1_NOTAKE,
+	M1_NOLIMBS|M1_SLITHY|M1_THICK_HIDE|M1_OVIPAROUS|M1_POIS|M1_NOTAKE|
+	  M1_OMNIVORE,
 	M2_STRONG, 0, CLR_GREEN),
 /*
  * Ogres
@@ -3441,7 +3445,7 @@
 	  NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
 	SIZ(WT_HUMAN, 400, 0, MS_GUARDIAN, MZ_HUMAN), 0, 0,
 	M1_HUMANOID|M1_OMNIVORE,
-	M2_NOPOLY|M2_HUMAN|M2_PEACEFUL|M2_STRONG|M2_COLLECT, M3_INFRAVISIBLE,
+	M2_NOPOLY|M2_HUMAN|M2_PEACEFUL|M2_STRONG|M2_COLLECT|M2_FEMALE, M3_INFRAVISIBLE,
 	HI_DOMESTIC),
     MON("apprentice", S_HUMAN,
 	LVL(5, 12, 10, 30, 0), G_NOGEN,

Index: were.c
===================================================================
RCS file: /cvsroot/pkg-nethack/nethack/src/were.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -d -r1.1.1.1 -r1.2
--- were.c	7 Oct 2003 19:00:21 -0000	1.1.1.1
+++ were.c	9 Dec 2003 16:14:43 -0000	1.2
@@ -86,41 +86,50 @@
 	possibly_unwield(mon, FALSE);
 }
 
-boolean
-were_summon(ptr,yours)	/* were-creature (even you) summons a horde */
+int
+were_summon(ptr,yours,visible,genbuf)	/* were-creature (even you) summons a horde */
 register struct permonst *ptr;
 register boolean yours;
+int *visible;			/* number of visible helpers created */
+char *genbuf;
 {
 	register int i, typ, pm = monsndx(ptr);
 	register struct monst *mtmp;
-	boolean success = FALSE;
+	int total = 0;
 
+	*visible = 0;
 	if(Protection_from_shape_changers && !yours)
-		return FALSE;
+		return 0;
 	for(i = rnd(5); i > 0; i--) {
 	   switch(pm) {
 
 		case PM_WERERAT:
 		case PM_HUMAN_WERERAT:
 			typ = rn2(3) ? PM_SEWER_RAT : rn2(3) ? PM_GIANT_RAT : PM_RABID_RAT ;
+			if (genbuf) Strcpy(genbuf, "rat");
 			break;
 		case PM_WEREJACKAL:
 		case PM_HUMAN_WEREJACKAL:
 			typ = PM_JACKAL;
+			if (genbuf) Strcpy(genbuf, "jackal");
 			break;
 		case PM_WEREWOLF:
 		case PM_HUMAN_WEREWOLF:
 			typ = rn2(5) ? PM_WOLF : PM_WINTER_WOLF ;
+			if (genbuf) Strcpy(genbuf, "wolf");
 			break;
 		default:
 			continue;
 	    }
 	    mtmp = makemon(&mons[typ], u.ux, u.uy, NO_MM_FLAGS);
-	    if (mtmp) success = TRUE;
+	    if (mtmp) {
+		total++;
+		if (canseemon(mtmp)) *visible += 1;
+	    }
 	    if (yours && mtmp)
 		(void) tamedog(mtmp, (struct obj *) 0);
 	}
-	return success;
+	return total;
 }
 
 void