This is a slightly modified version of Scott Bigham's sticky patch,
version 5.  The differences are:

    - Re-worked for use with patchable Nethack.

Bones/save compatibility:  This patch doesn't affect saved games or bones
files.

This patch is available at http://www.argon.org/~roderick/nethack/.

Roderick Schertler <roderick@argon.org>


diff -r -X /home/roderick/.diff-exclude -uN base.patchable/doc/Guidebook.mn work.preadjust/doc/Guidebook.mn
--- base.patchable/doc/Guidebook.mn	2003-02-23 09:43:18.000000000 -0500
+++ work.preadjust/doc/Guidebook.mn	2003-03-23 10:06:31.000000000 -0500
@@ -1607,6 +1607,14 @@
 entry unchanged; this feature is not available using the option syntax.
 Such a sequence can be continued to multiple lines by putting a `\e'
 at the end of each line to be continued.
+If the PREADJUST compile-time option is enabled, any line starting with
+``PREADJUST:'' causes an #adjust command to be performed on a corresponding
+item in the starting inventory of a new character.  For instance,
+``PREADJUST:C-cloak'' will adjust an object whose name contains ``cloak''
+into the `C' slot; if the #sticky command is available,
+``PREADJUST:C=cloak'' will also mark the object sticky.  Note that common
+prefixes like ``ring of'' do not appear in the internal name data for
+objects, and so should not be included in your match string.
 Any line starting with `#' is treated as a comment.
 .pg
 The default name of the configuration file varies on different
diff -r -X /home/roderick/.diff-exclude -uN base.patchable/doc/Guidebook.tex work.preadjust/doc/Guidebook.tex
--- base.patchable/doc/Guidebook.tex	2003-02-23 09:43:18.000000000 -0500
+++ work.preadjust/doc/Guidebook.tex	2003-03-23 10:06:31.000000000 -0500
@@ -2013,6 +2013,15 @@
 entry unchanged; this feature is not available using the option syntax.
 Such a sequence can be continued to multiple lines by putting a
 `{\tt \verb+\+}' at the end of each line to be continued.
+If the {\tt PREADJUST} compile-time option is enabled, any line starting
+with ``{\tt PREADJUST:}'' causes an {\tt \#adjust} command to be performed
+on a corresponding item in the starting inventory of a new character.  For
+instance, ``\mbox{\tt PREADJUST:C-cloak}'' will adjust an object whose name
+contains ``cloak'' into the `C' slot; if the {\tt \#sticky} command is
+available, ``\mbox{\tt PREADJUST:C=cloak}'' will also mark the object
+sticky.  Note that common prefixes like ``ring of'' do not appear in the
+internal name data for objects, and so should not be included in your match
+string.
 Any line starting with `{\tt \#}' is treated as a comment.
 
 %.pg
diff -r -X /home/roderick/.diff-exclude -uN base.patchable/include/config.h work.preadjust/include/config.h
--- base.patchable/include/config.h	2003-03-20 16:41:57.000000000 -0500
+++ work.preadjust/include/config.h	2003-03-23 10:07:23.000000000 -0500
@@ -364,6 +364,12 @@
 /*
  * options patch point; see $top/README.patchable
  */
+
+#define PREADJUST	/* set item letters from options file */
+
+/*
+ * options patch point; see $top/README.patchable
+ */
 /*
  * options patch point; see $top/README.patchable
  */
diff -r -X /home/roderick/.diff-exclude -uN base.patchable/include/extern.h work.preadjust/include/extern.h
--- base.patchable/include/extern.h	2003-02-23 09:43:20.000000000 -0500
+++ work.preadjust/include/extern.h	2003-03-23 10:06:31.000000000 -0500
@@ -800,6 +800,10 @@
 E int NDECL(doprinuse);
 E void FDECL(useupf, (struct obj *,long));
 E char *FDECL(let_to_name, (CHAR_P,BOOLEAN_P));
+#ifdef PREADJUST
+/* This has to be up here so it won't collide with the sticky patch... */
+E void FDECL(doorganize_guts, (struct obj *, char, boolean));
+#endif /* PREADJUST */
 E void NDECL(free_invbuf);
 E void NDECL(reassign);
 E int NDECL(doorganize);
@@ -1375,6 +1379,11 @@
 E int FDECL(choose_classes_menu, (const char *,int,BOOLEAN_P,char *,char *));
 E void FDECL(add_menu_cmd_alias, (CHAR_P, CHAR_P));
 E char FDECL(map_menu_cmd, (CHAR_P));
+#ifdef PREADJUST
+E boolean FDECL(collect_preadjust, (char *));
+E void NDECL(apply_preadjust);
+E void NDECL(cleanup_preadjust);
+#endif /* PREADJUST */
 E void FDECL(assign_warnings, (uchar *));
 E char *FDECL(nh_getenv, (const char *));
 E void FDECL(set_duplicate_opt_detection, (int));
diff -r -X /home/roderick/.diff-exclude -uN base.patchable/src/allmain.c work.preadjust/src/allmain.c
--- base.patchable/src/allmain.c	2003-02-23 09:43:24.000000000 -0500
+++ work.preadjust/src/allmain.c	2003-03-23 10:06:31.000000000 -0500
@@ -498,6 +498,10 @@
 				 * creating odd monsters for initial tins and
 				 * eggs */
 	u_init();
+#ifdef PREADJUST
+	apply_preadjust();
+	cleanup_preadjust();
+#endif /* PREADJUST */
 	init_artifacts();
 
 #ifndef NO_SIGNAL
diff -r -X /home/roderick/.diff-exclude -uN base.patchable/src/files.c work.preadjust/src/files.c
--- base.patchable/src/files.c	2003-02-23 09:43:26.000000000 -0500
+++ work.preadjust/src/files.c	2003-03-23 10:06:31.000000000 -0500
@@ -1775,6 +1775,11 @@
 	    (void) get_uchars(fp, buf, bufp, translate, FALSE,
 					WARNCOUNT, "WARNINGS");
 	    assign_warnings(translate);
+#ifdef PREADJUST
+	} else if (match_varname(buf, "PREADJUST", 6)) {
+	    if (!collect_preadjust(bufp))
+		return 0;
+#endif /* PREADJUST */
 #ifdef WIZARD
 	} else if (match_varname(buf, "WIZKIT", 6)) {
 	    (void) strncpy(wizkit, bufp, WIZKIT_MAX-1);
diff -r -X /home/roderick/.diff-exclude -uN base.patchable/src/invent.c work.preadjust/src/invent.c
--- base.patchable/src/invent.c	2003-02-23 09:43:27.000000000 -0500
+++ work.preadjust/src/invent.c	2003-03-23 10:06:31.000000000 -0500
@@ -2612,7 +2612,9 @@
 	char alphabet[52+1], buf[52+1];
 	char qbuf[QBUFSZ];
 	char allowall[2];
+#ifndef PREADJUST
 	const char *adj_type;
+#endif /* PREADJUST */
 
 	if (!flags.invlet_constant) reassign();
 	/* get a pointer to the object the user wants to organize */
@@ -2655,7 +2657,22 @@
 	}
 
 	/* change the inventory and print the resulting item */
+#ifndef PREADJUST
 	adj_type = "Moving:";
+#else
+	doorganize_guts(obj, let, FALSE);
+	return(0);
+}
+
+void
+doorganize_guts(obj, let, quiet)
+struct obj *obj;
+char let;
+boolean quiet;
+{
+	struct obj *otmp;
+	const char *adj_type = "Moving:";
+#endif /* PREADJUST */
 
 	/*
 	 * don't use freeinv/addinv to avoid double-touching artifacts,
@@ -2684,9 +2701,14 @@
 	invent = obj;
 	reorder_invent();
 
+#ifdef PREADJUST
+	if (!quiet)
+#endif /* PREADJUST */
 	prinv(adj_type, obj, 0L);
 	update_inventory();
+#ifndef PREADJUST
 	return(0);
+#endif /* PREADJUST */
 }
 
 /* common to display_minventory and display_cinventory */
diff -r -X /home/roderick/.diff-exclude -uN base.patchable/src/options.c work.preadjust/src/options.c
--- base.patchable/src/options.c	2003-03-18 20:58:07.000000000 -0500
+++ work.preadjust/src/options.c	2003-03-23 10:06:31.000000000 -0500
@@ -405,6 +405,22 @@
 static short n_menu_mapped = 0;
 
 
+#ifdef PREADJUST
+/* Stuff for doing starting inventory pre-#adjusts. */
+typedef struct {
+    const char *descr;
+# ifdef STICKY_OBJECTS
+    boolean sticky;
+# endif /* STICKY_OBJECTS */
+    char invlet;
+} preadjust;
+
+static preadjust *preadj_list = 0;
+static int n_preadjust = 0;
+static int preadjust_size = 0;
+#endif /* PREADJUST */
+
+
 static boolean initial, from_file;
 
 STATIC_DCL void FDECL(doset_add_menu, (winid,const char *,int));
@@ -2219,6 +2235,84 @@
 }
 
 
+#ifdef PREADJUST
+boolean
+collect_preadjust(bufp)
+char *bufp;
+{
+    preadjust adj;
+
+    if (!*bufp)
+	return 0;
+    adj.invlet = *bufp++;
+    if (*bufp != '-'
+# ifdef STICKY_OBJECTS
+		     && *bufp != '='
+# endif /* STICKY_OBJECTS */
+				    )
+	return 0;
+# ifdef STICKY_OBJECTS
+    adj.sticky = (*bufp == '=');
+# endif /* STICKY_OBJECTS */
+    bufp++;
+    if (!*bufp)
+	return 0;
+    adj.descr = (char *)strdup(bufp);
+
+    /* allocate additional space if necessary */
+    if (preadjust_size == 0) {
+	preadjust_size = 10;
+	preadj_list = (preadjust *)alloc(10 * sizeof(preadjust));
+    } else if (n_preadjust == preadjust_size) {
+	preadjust *tmp;
+	preadjust_size *= 2;
+	tmp = (preadjust *)alloc(preadjust_size * sizeof(preadjust));
+	(void)memcpy((genericptr_t)tmp, (genericptr_t)preadj_list,
+		     n_preadjust * sizeof(preadjust));
+	free((genericptr_t)preadj_list);
+	preadj_list = tmp;
+    }
+
+    preadj_list[n_preadjust++] = adj;
+    return 1;
+}
+
+void
+apply_preadjust()
+{
+    int i;
+    struct obj *obj;
+
+    if (n_preadjust == 0)
+	return;
+    /* this is kind of expensive, I suppose, but it only happens once */
+    for (i = 0; i < n_preadjust; i++) {
+	for (obj = invent; obj; obj = obj->nobj) {
+	    if (strstri(OBJ_NAME(objects[obj->otyp]), preadj_list[i].descr)) {
+# ifdef STICKY_OBJECTS
+		obj->sticky = preadj_list[i].sticky;
+# endif /* STICKY_OBJECTS */
+		doorganize_guts(obj, preadj_list[i].invlet, TRUE);
+		break;
+	    }
+	}
+    }
+}
+
+void
+cleanup_preadjust()
+{
+    int i;
+
+    if (n_preadjust == 0)
+	return;
+    for (i = 0; i < n_preadjust; i++)
+	free((genericptr_t)preadj_list[i].descr);
+    free((genericptr_t)preadj_list);
+}
+#endif /* PREADJUST */
+
+
 #if defined(MICRO) || defined(MAC) || defined(WIN32)
 # define OPTIONS_HEADING "OPTIONS"
 #else
diff -r -X /home/roderick/.diff-exclude -uN base.patchable/src/restore.c work.preadjust/src/restore.c
--- base.patchable/src/restore.c	2003-02-23 09:43:29.000000000 -0500
+++ work.preadjust/src/restore.c	2003-03-23 10:06:31.000000000 -0500
@@ -670,6 +670,9 @@
 	run_timers();	/* expire all timers that have gone off while away */
 	docrt();
 	restoring = FALSE;
+#ifdef PREADJUST
+	cleanup_preadjust();	/* we're now certain we don't need this */
+#endif /* PREADJUST */
 	clear_nhwindow(WIN_MESSAGE);
 	program_state.something_worth_saving++;	/* useful data now exists */
 
diff -r -X /home/roderick/.diff-exclude -uN base.patchable/util/makedefs.c work.preadjust/util/makedefs.c
--- base.patchable/util/makedefs.c	2003-03-20 16:41:56.000000000 -0500
+++ work.preadjust/util/makedefs.c	2003-03-23 10:06:31.000000000 -0500
@@ -752,6 +752,12 @@
 		/*
 		 * patch list patch point; see $top/README.patchable
 		 */
+#ifdef PREADJUST
+    	    	"patch: preadjust v5-patchable",
+#endif
+		/*
+		 * patch list patch point; see $top/README.patchable
+		 */
 		/*
 		 * patch list patch point; see $top/README.patchable
 		 */
