Subject: NH311 Patch: autoopen (bump into doors to open them)

From: "Michael & Heather Gleason" <[email-masked]>
Date: Wed, 29 Aug 2001 15:36:31 GMT

I'm not sure this is the appropriate place to post these, but this is the
first of a few patches to Nethack 3.3.1 I've made to make the game more
enjoyable for me.  Hopefully the DevTeam will take them into consideration
for incorporation into the next release.

What this patch does:
==============

This adds a new .nethackrc option, "autoopen", that if set, will cause your
player to open doors automatically by simply bumping into them.  If the
option is not set (the default), you will get the usual "Ouch!  You bump
into a door" or "That door is closed" message.  (So, if you're worried about
triggering a trap, simply do not bump into the door.)

If the door is locked, you are using autoopen, and you have the skeleton key
in your inventory, you will automatically attempt to unlock the door, and
the automatically open the door if the unlocking succeeded.

The autoopen modification makes the game much easier to navigate, especially
using the numeric keypad.

The loot command is modified so that if you find that the chest is locked,
you will be prompted to "Try to unlock it with your key?" if you have a key
in your inventory.

The untrap command is modified so after checking for traps on a chest/box,
you will be prompted to "Loot it?".

The loot and untrap modifications greatly streamline the tedious process of
opening a goodie box with a minimal impact on game play.

How to use these modifications:
======================

To apply the patch under a *NIX OS do the following:
  (1) Download the source code tarball, available from
ftp://ftp.nethack.org/pub/nethack/nh331/src/nethack-331.tgz .
  (2) Extract the tar ball, i.e. "gzip -d -c nethack-331.tgz | tar xf -" .
  (3) Change directory to the nethack-3.3.1 directory that Tar created.
  (4) Save this patch file into this directory, i.e. "patch.txt" .
  (5) Run patch, i.e. "patch -p1 < patch.txt" .
  (6) Follow Nethack's installation instructions to compile and install
Nethack.

Enjoy!
Mike Gleason from NcFTP

diff -u -r nethack-3.3.1/include/extern.h nethack-3.3.1-autoopen/include/extern.h
--- nethack-3.3.1/include/extern.h	Wed Aug  9 10:46:17 2000
+++ nethack-3.3.1-autoopen/include/extern.h	Wed Aug 29 09:26:02 2001
@@ -810,6 +810,7 @@
 E int NDECL(doforce);
 E boolean FDECL(boxlock, (struct obj *,struct obj *));
 E boolean FDECL(doorlock, (struct obj *,int,int));
+E int FDECL(doautoopen, (int,int));
 E int NDECL(doopen);
 E int NDECL(doclose);
 
@@ -1383,6 +1384,7 @@
 				menu_item **, int, boolean (*)(OBJ_P)));
 E struct obj *FDECL(pick_obj, (struct obj *));
 E int NDECL(encumber_msg);
+E int FDECL(doloot2, (int));
 E int NDECL(doloot);
 E int FDECL(use_container, (struct obj *,int));
 
diff -u -r nethack-3.3.1/include/flag.h nethack-3.3.1-autoopen/include/flag.h
--- nethack-3.3.1/include/flag.h	Fri Jul 21 19:59:00 2000
+++ nethack-3.3.1-autoopen/include/flag.h	Wed Aug 29 09:26:02 2001
@@ -23,6 +23,7 @@
 	boolean  asksavedisk;
 #endif
 	boolean  autoquiver;	/* Automatically fill quiver */
+	boolean  autoopen;	/* Open doors by bumping into them */
 	boolean  beginner;
 #ifdef MAIL
 	boolean  biff;		/* enable checking for mail */
diff -u -r nethack-3.3.1/src/hack.c nethack-3.3.1-autoopen/src/hack.c
--- nethack-3.3.1/src/hack.c	Fri Jul 21 19:59:06 2000
+++ nethack-3.3.1-autoopen/src/hack.c	Wed Aug 29 09:26:02 2001
@@ -845,10 +845,11 @@
 		    if (amorphous(youmonst.data))
 			You("try to ooze under the door, but can't squeeze your possessions through.");
 		    else if (x == u.ux || y == u.uy) {
-			if (Blind || Stunned || ACURR(A_DEX) < 10 || Fumbling) {
+			if (Blind || Stunned || ((! flags.autoopen) && (ACURR(A_DEX) < 10)) || Fumbling) {
 			    pline("Ouch!  You bump into a door.");
 			    exercise(A_DEX, FALSE);
-			} else pline("That door is closed.");
+			} else if ((! flags.autoopen) || (! doautoopen(x,y)))
+			    pline("That door is closed.");
 		    }
 		    nomul(0);
 		    return;
diff -u -r nethack-3.3.1/src/lock.c nethack-3.3.1-autoopen/src/lock.c
--- nethack-3.3.1/src/lock.c	Fri Apr 21 21:31:53 2000
+++ nethack-3.3.1-autoopen/src/lock.c	Wed Aug 29 09:26:02 2001
@@ -19,6 +19,7 @@
 STATIC_DCL const char *NDECL(lock_action);
 STATIC_DCL boolean FDECL(obstructed,(int,int));
 STATIC_DCL void FDECL(chest_shatter_msg, (struct obj *));
+STATIC_DCL int FDECL(open_door, (struct rm *,int,int));
 
 boolean
 picking_lock(x, y)
@@ -487,6 +488,114 @@
 	return(1);
 }
 
+STATIC_OVL int
+open_door(door, x, y)
+struct rm *door;
+int x, y;
+{
+	if (door->doormask & D_CLOSED) {
+		if (rnl(20) < (ACURRSTR+ACURR(A_DEX)+ACURR(A_CON))/3) {
+			pline_The("door opens.");
+			if(door->doormask & D_TRAPPED) {
+			b_trapped("door", FINGER);
+			door->doormask = D_NODOOR;
+			if (*in_rooms(x, y, SHOPBASE)) add_damage(x, y, 0L);
+			} else
+			door->doormask = D_ISOPEN;
+			if (Blind)
+			feel_location(x,y);	/* the hero knows she opened it  */
+			else
+			newsym(x,y);
+			unblock_point(x,y);		/* vision: new see through there */
+			return (1);		/* 1 ==> printed a message */
+		} else {
+			exercise(A_STR, TRUE);
+			pline_The("door resists!");
+			return (1);		/* 1 ==> printed a message */
+		}
+	}
+	return(0);	/* 0 ==> need to pline("That door is closed.") */
+}	/* open_door */
+
+int
+doautoopen(x, y)
+int x, y;
+{
+	register struct rm *door;
+	struct monst *mtmp;
+
+	if (nohands(youmonst.data)) {
+		/*
+		 * For autoopen mode, we don't generally print
+		 * messages.  The Hero should do a manual open
+		 * to see why the door didn't open.
+		 */
+	    /* You_cant("open anything -- you have no hands!"); */
+
+		return(0);	/* 0 => pline("That door is closed.") */
+	}
+
+	if (u.utrap && u.utraptype == TT_PIT) {
+	    You_cant("reach over the edge of the pit.");
+		return(1);
+	}
+
+	if ((mtmp = m_at(x,y))				&&
+		mtmp->m_ap_type == M_AP_FURNITURE	&&
+		(mtmp->mappearance == S_hcdoor ||
+			mtmp->mappearance == S_vcdoor)	&&
+		!Protection_from_shape_changers)	 {
+
+	    stumble_onto_mimic(mtmp);
+	    return(1);
+	}
+
+	door = &levl[x][y];
+
+	if(!IS_DOOR(door->typ)) {
+		return(0);
+	}
+
+	if (door->doormask & (~(D_LOCKED|D_CLOSED|D_TRAPPED))) {
+		/* This is not just a locked, trapped, or closed door. */
+	    return(0);
+	}
+
+	if (door->doormask & D_LOCKED) {
+		/* Do not autounlock unless we have a key --
+		 * the lock pick (credit card, ...) may end
+		 * up taking several turns which the player 
+		 * may not intend.
+		 */
+		if (carrying(SKELETON_KEY)) {
+			if (rn2(100) <= (70 + ACURR(A_DEX))) {
+				You("succeed in %s.", "unlocking the door");
+				door->doormask = D_CLOSED;
+				exercise(A_DEX, TRUE);
+			} else {
+				pline("This door remains locked.");
+				return(1);
+			}
+		} else {
+			pline("This door is locked.");
+			return(1);
+		}
+	}
+
+	if (!(door->doormask & D_CLOSED)) {
+		/* Already open, or broken, or not a door */
+	    return(0);
+	}
+
+	if(verysmall(youmonst.data)) {
+	    /* pline("You're too small to pull the door open."); */
+	    return(0);
+	}
+
+	/* door is known to be CLOSED */
+	return (open_door(door, x, y));
+}	/* doautoopen */
+
 int
 doopen()		/* try to open a door */
 {
@@ -552,25 +661,7 @@
 	}
 
 	/* door is known to be CLOSED */
-	if (rnl(20) < (ACURRSTR+ACURR(A_DEX)+ACURR(A_CON))/3) {
-	    pline_The("door opens.");
-	    if(door->doormask & D_TRAPPED) {
-		b_trapped("door", FINGER);
-		door->doormask = D_NODOOR;
-		if (*in_rooms(x, y, SHOPBASE)) add_damage(x, y, 0L);
-	    } else
-		door->doormask = D_ISOPEN;
-	    if (Blind)
-		feel_location(x,y);	/* the hero knows she opened it  */
-	    else
-		newsym(x,y);
-	    unblock_point(x,y);		/* vision: new see through there */
-	} else {
-	    exercise(A_STR, TRUE);
-	    pline_The("door resists!");
-	}
-
-	return(1);
+	return (open_door(door, x, y));
 }
 
 STATIC_OVL
diff -u -r nethack-3.3.1/src/options.c nethack-3.3.1-autoopen/src/options.c
--- nethack-3.3.1/src/options.c	Wed Aug  9 13:33:01 2000
+++ nethack-3.3.1-autoopen/src/options.c	Wed Aug 29 09:26:02 2001
@@ -41,6 +41,7 @@
 #endif
 	{"autopickup", &flags.pickup, TRUE},
 	{"autoquiver", &flags.autoquiver, FALSE},
+	{"autoopen", &flags.autoopen, FALSE},
 #if defined(MICRO) && !defined(AMIGA)
 	{"BIOS", &iflags.BIOS, FALSE},
 #else
diff -u -r nethack-3.3.1/src/pickup.c nethack-3.3.1-autoopen/src/pickup.c
--- nethack-3.3.1/src/pickup.c	Sat Jul 22 13:41:29 2000
+++ nethack-3.3.1-autoopen/src/pickup.c	Wed Aug 29 09:26:02 2001
@@ -1224,7 +1224,8 @@
 }
 
 int
-doloot()	/* loot a container on the floor. */
+doloot2(asktoloot)
+int asktoloot;
 {
     register struct obj *cobj, *nobj;
     register int c = -1;
@@ -1255,13 +1256,32 @@
 
 	    if (Is_container(cobj)) {
 		Sprintf(qbuf, "There is %s here, loot it?", doname(cobj));
-		c = ynq(qbuf);
+		c = asktoloot ? ynq(qbuf) : 'y';
 		if (c == 'q') return (timepassed);
 		if (c == 'n') continue;
 
 		if (cobj->olocked) {
 		    pline("Hmmm, it seems to be locked.");
-		    continue;
+		    if (carrying(SKELETON_KEY)) {
+		    	c = ynq("Try to unlock it with your key?");
+			if (c == 'q') return (timepassed);
+		        if (c == 'n') continue;
+		        timepassed = 1;
+			if (rn2(100) <= (70 + ACURR(A_DEX))) {
+                            cobj->olocked = 0;
+			    You("succeed in unlocking the %s.", doname(cobj));
+			    exercise(A_DEX, TRUE);
+			} else {
+			    You("fail to unlock the %s.", doname(cobj));
+		            continue;
+			}
+                        if(cobj->otrapped) {
+                            (void) chest_trap(cobj, FINGER, FALSE);
+		            return (timepassed);
+			}
+		    } else {
+		        continue;
+		    }
 		}
 		if (cobj->otyp == BAG_OF_TRICKS) {
 		    You("carefully open the bag...");
@@ -1438,6 +1458,12 @@
 		    underfoot ? "here" : "there");
     }
     return (timepassed);
+}
+
+int
+doloot()	/* loot a container on the floor. */
+{
+    return (doloot2(1));
 }
 
 /*
diff -u -r nethack-3.3.1/src/trap.c nethack-3.3.1-autoopen/src/trap.c
--- nethack-3.3.1/src/trap.c	Fri Aug  4 18:43:52 2000
+++ nethack-3.3.1-autoopen/src/trap.c	Wed Aug 29 09:26:02 2001
@@ -2724,11 +2724,17 @@
 			    } else {
 				You("disarm it!");
 				otmp->otrapped = 0;
+				if (ynq("Loot it?") != 'y')
+				    return(1);
+			        doloot2(0);
 			    }
 			} else pline("That %s was not trapped.", xname(otmp));
 			return(1);
 		    } else {
 			You("find no traps on %s.", the(xname(otmp)));
+			if (ynq("Loot it?") != 'y')
+			    return(1);
+			doloot2(0);
 			return(1);
 		    }
 		}