<html><head><meta name="color-scheme" content="light dark"></head><body><pre style="word-wrap: break-word; white-space: pre-wrap;">diff -Ndur nethack-3.4.3/src/objnam.c nethack-patched/src/objnam.c
--- nethack-3.4.3/src/objnam.c	2006-12-04 21:59:04.000000000 +0000
+++ nethack-patched/src/objnam.c	2007-02-28 00:53:20.000000000 +0000
@@ -1738,6 +1738,152 @@
 	{ (const char *)0, 0 },
 };
 
+
+static struct obj *
+ron_getobj(olist, typ, bucstatus, ispoisoned, erodeproof, spe, name)
+struct obj *olist;
+int typ, bucstatus;
+int ispoisoned, erodeproof, spe;
+const char *name;
+{
+    struct obj *otmp;
+    for (otmp = olist; otmp; otmp = otmp-&gt;nobj) {
+	if (otmp-&gt;otyp != typ) continue;
+	if (bucstatus == 1 &amp;&amp; !otmp-&gt;blessed) continue;
+	if (bucstatus == 2 &amp;&amp; (otmp-&gt;blessed || otmp-&gt;cursed)) continue;
+	if (bucstatus == 3 &amp;&amp; !otmp-&gt;cursed) continue;
+        if (ispoisoned &amp;&amp; !otmp-&gt;opoisoned) continue;
+        if (erodeproof &amp;&amp; !otmp-&gt;oerodeproof) continue;
+	if (name &amp;&amp; !(otmp-&gt;onamelth &amp;&amp; !strcmp(name, ONAME(otmp))))
+	    continue;
+        if (spe != -998 &amp;&amp; otmp-&gt;spe != spe) continue;
+	/* That's all the checks we can make. */
+	return otmp;
+    }
+    return((struct obj *) 0);
+}
+
+/*
+   Find a monster who seems to match the given traits. Match on these criteria:
+   (1) Does the monster's name match a given name ("Bob")? ownercnt must be -3. 100% match.
+   (2) Does the monster's type match the name ("gnome")? 25% match.
+       (2a) Is the monster visible? +25% match, or +50% if "the" was given.
+       (2b) Is the monster carrying a matching object? +25% match.
+   Return the most likely match.
+*/
+static struct monst *
+ron_locateowner(mname, ownercnt, mgold, typ, bucstatus, ispoisoned, erodeproof, name)
+const char *mname;
+int ownercnt, mgold, typ;
+int bucstatus, ispoisoned, erodeproof;
+const char *name;
+{
+    struct monst *mtmp, *bestmatch=0;
+    int ptmp, bestp=0;
+    /* Just check the monsters on this level. Checking visited levels is way too hard. */
+    for (mtmp = fmon; mtmp; mtmp = mtmp-&gt;nmon) {
+    	if (DEADMONSTER(mtmp)) continue;
+        ptmp = 0;
+        if (ownercnt == -3 &amp;&amp; mtmp-&gt;isshk &amp;&amp; !strcmp(shkname(mtmp), mname)) {
+	    ptmp = 100;  /* match "Asidonhopo" at 100% */
+        } else if (ownercnt == -3 &amp;&amp; mtmp-&gt;mnamelth &amp;&amp; !strcmp(NAME(mtmp), mname)) {
+	    ptmp = 100;  /* match "Fido" at 100% */
+	} else if (!strcmp(mtmp-&gt;data-&gt;mname, mname) ||  /* "gnome lord" */
+                   mtmp-&gt;ispriest &amp;&amp; !strcmp("priest", mname)) {  /* "priest" */
+	    ptmp = 25;
+	    if (canspotmon(mtmp)) ptmp += (ownercnt == -3)? 50: 25;
+	    if (mgold != -9) {
+#ifdef GOLDOBJ
+		struct obj *mongold = findgold(mtmp-&gt;minvent);
+		int mqgold = (mongold == 0)? 0: mongold-&gt;quan;
+		if (mqgold &gt;= mgold)
+		    ptmp += 25;
+#else
+                if (mtmp-&gt;mgold &gt;= mgold)
+                    ptmp += 25;
+#endif
+	    }
+            else if (ron_getobj(mtmp-&gt;minvent, typ, bucstatus, ispoisoned, erodeproof, -998, name))
+                ptmp += 25;
+	}
+        if (ptmp &gt; bestp) {
+	    bestp = ptmp;
+	    bestmatch = mtmp;
+        }
+    }
+    return bestmatch;
+}
+
+
+/* Given *bp of the form "12 ^blessed +5 arrows" or "1 ^Longbow of Diana", return 12 or 1,
+   respectively. Return 0 for "0 ^arrows"; return -2 for "the ^arrow". Advance *bp to the
+   marked position in each string. Return -1 for "an" and -2 for "the".
+*/
+static int
+ron_number(bp)
+register char **bp;
+{
+    int cnt, cl;
+    cnt = -3;
+    cl = 0;
+    if (!strncmpi(*bp, "an ", cl=3) ||
+	!strncmpi(*bp, "a ", cl=2)) {
+	cnt = -1;
+    } else if (!strncmpi(*bp, "the ", cl=4)) {
+	cnt = -2;
+    } else if (digit(**bp) &amp;&amp; strcmp(*bp, "0")) {
+	cnt = atoi(*bp);
+	while(digit(**bp)) (*bp)++;
+	while(**bp == ' ') (*bp)++;
+	cl = 0;
+    } else
+        cl = 0;
+    *bp += cl;
+    return cnt;
+}
+
+/* Given *bp of the form "Brad's ^pit" or "Croesus' ^gold", return
+   "Brad" or "Croesus", respectively, and advance *bp to the marked
+   location in each string.
+   Return 0 if no "owner" string exists, e.g. "^+4 blessed arrows".
+*/
+static char *
+ron_owner(bp)
+register char **bp;
+{
+    char *spc, *tmp;
+
+    spc = (*bp);
+    while (1) {
+        if ((spc = strchr(spc+1, ' ')) == (char *)0 || spc &lt; *bp + 2)
+            return (char *) 0;
+        if (spc[-1] == '\'' &amp;&amp; strchr("SsXx", spc[-2])) {
+	    tmp = spc-1;  /* "Brad^'s pit" */
+	    goto found_owner;
+        } else if (spc[-2] == '\'' &amp;&amp; strchr("Ss", spc[-1])) {
+	    tmp = spc-2;
+	    goto found_owner;  /* "Croesus^' gold" */
+        /* Handle "a dagger named John's Dagger" at the expense of "an archlich named Bob's gold",
+           since the latter could be phrased better as simply "Bob's gold". */
+        } else if (spc &gt; (*bp)+6 &amp;&amp; !strncmp(spc-6, " named", 6)) {
+            return (char *) 0;
+        } else if (spc &gt; (*bp)+7 &amp;&amp; !strncmp(spc-7, " called", 7)) {
+            return (char *) 0;
+        } else if (spc &gt; (*bp)+8 &amp;&amp; !strncmp(spc-8, " labeled", 8)) {
+            return (char *) 0;
+        } else if (spc &gt; (*bp)+9 &amp;&amp; !strncmp(spc-9, " labelled", 9)) {
+            return (char *) 0;
+        }
+    }
+
+found_owner:
+    *tmp = '\0';
+    tmp = *bp;
+    *bp = spc+1;
+    return tmp;
+}
+
+
 /*
  * Return something wished for.  Specifying a null pointer for
  * the user request string results in a random object.  Otherwise,
@@ -1748,7 +1894,7 @@
  */
 struct obj *
 readobjnam(bp, no_wish, from_user)
-register char *bp;
+char *bp;
 struct obj *no_wish;
 boolean from_user;
 {
@@ -1757,11 +1903,12 @@
 	register struct obj *otmp;
 	int cnt, spe, spesgn, typ, very, rechrg;
 	int blessed, uncursed, iscursed, ispoisoned, isgreased;
+        int bucstatus; /* blessed=1, uncursed=2, cursed=3 */
 	int eroded, eroded2, erodeproof;
 #ifdef INVISIBLE_OBJECTS
 	int isinvisible;
 #endif
-	int halfeaten, mntmp, contents;
+	int halfeaten, mntmp, contents, ownercnt;
 	int islit, unlabeled, ishistoric, isdiluted;
 	struct fruit *f;
 	int ftype = current_fruit;
@@ -1784,6 +1931,9 @@
 	char oclass;
 	char *un, *dn, *actualn;
 	const char *name=0;
+	const char *owner=0;
+	struct monst *mowner=0;
+	boolean asked_for_gold, all_the_gold;
 
 	cnt = spe = spesgn = typ = very = rechrg =
 		blessed = uncursed = iscursed =
@@ -1799,6 +1949,9 @@
 	contents = UNDEFINED;
 	oclass = 0;
 	actualn = dn = un = 0;
+	ownercnt = 0;
+	asked_for_gold = FALSE;
+	all_the_gold = FALSE;
 
 	if (!bp) goto any;
 	/* first, remove extra whitespace they may have typed */
@@ -1810,21 +1963,31 @@
 	/* save the [nearly] unmodified choice string */
 	Strcpy(fruitbuf, bp);
 
+
+        /* Get numbers and owners from the front of the string. */
+
+	if (!bp) goto any;
+	cnt = ron_number(&amp;bp);
+	if (cnt &lt; 0) {
+	    ownercnt = cnt; /* "the gnome's aklys", "Bill's 20 arrows" */
+	    owner = ron_owner(&amp;bp);
+	    cnt = (owner? ron_number(&amp;bp): 0);
+	} else if (cnt &gt;= 0 &amp;&amp; !strncmpi(bp, "of ", 3)) {
+	    bp += 3; /* "2 of Bill's arrows" */
+	    ownercnt = ron_number(&amp;bp); /* "2 of the gnome's 5 arrows" */
+	    owner = ron_owner(&amp;bp);
+	    (void) ron_number(&amp;bp);
+	}
+	if (cnt == -3) all_the_gold = TRUE;
+	if (cnt &lt; 0) cnt = 1;
+
+	/* Get adjectives and qualifiers from the front of the string. */
+
 	for(;;) {
 		register int l;
 
 		if (!bp || !*bp) goto any;
-		if (!strncmpi(bp, "an ", l=3) ||
-		    !strncmpi(bp, "a ", l=2)) {
-			cnt = 1;
-		} else if (!strncmpi(bp, "the ", l=4)) {
-			;	/* just increment `bp' by `l' below */
-		} else if (!cnt &amp;&amp; digit(*bp) &amp;&amp; strcmp(bp, "0")) {
-			cnt = atoi(bp);
-			while(digit(*bp)) bp++;
-			while(*bp == ' ') bp++;
-			l = 0;
-		} else if (*bp == '+' || *bp == '-') {
+		if (*bp == '+' || *bp == '-') {
 			spesgn = (*bp++ == '+') ? 1 : -1;
 			spe = atoi(bp);
 			while(digit(*bp)) bp++;
@@ -1894,7 +2057,9 @@
 		} else break;
 		bp += l;
 	}
-	if(!cnt) cnt = 1;		/* %% what with "gems" etc. ? */
+
+	/* Get qualifiers (charges) from the end of the string. */
+
 	if (strlen(bp) &gt; 1) {
 	    if ((p = rindex(bp, '(')) != 0) {
 		if (p &gt; bp &amp;&amp; p[-1] == ' ') p[-1] = 0;
@@ -2088,25 +2253,8 @@
 	if(!BSTRCMPI(bp, p-10, "gold piece") || !BSTRCMPI(bp, p-7, "zorkmid") ||
 	   !strcmpi(bp, "gold") || !strcmpi(bp, "money") ||
 	   !strcmpi(bp, "coin") || *bp == GOLD_SYM) {
-			if (cnt &gt; 5000
-#ifdef WIZARD
-					&amp;&amp; !wizard
-#endif
-						) cnt=5000;
-		if (cnt &lt; 1) cnt=1;
-#ifndef GOLDOBJ
-		if (from_user)
-		    pline("%d gold piece%s.", cnt, plur(cnt));
-		u.ugold += cnt;
-		flags.botl=1;
-		return (&amp;zeroobj);
-#else
-                otmp = mksobj(GOLD_PIECE, FALSE, FALSE);
-		otmp-&gt;quan = cnt;
-                otmp-&gt;owt = weight(otmp);
-		flags.botl=1;
-		return (otmp);
-#endif
+		asked_for_gold = TRUE;
+		goto typfnd;
 	}
 	if (strlen(bp) == 1 &amp;&amp;
 	   (i = def_char_to_objclass(*bp)) &lt; MAXOCLASSES &amp;&amp; i &gt; ILLOBJ_CLASS
@@ -2315,6 +2463,22 @@
 				/* avoid stupid mistakes */
 				if((trap == TRAPDOOR || trap == HOLE)
 				      &amp;&amp; !Can_fall_thru(&amp;u.uz)) trap = ROCKTRAP;
+#ifdef BRADS_PIT
+        if (trap == PIT &amp;&amp; owner &amp;&amp;
+                !strncmp(owner, BRADS_TEXT, (sizeof BRADS_TEXT)-3) &amp;&amp;
+                owner[(sizeof BRADS_TEXT)-3] == '\0') {
+            if (brads_pit.created) {
+                pline("Sorry...");
+                return(&amp;zeroobj);
+            }
+            (void) maketrap(u.ux, u.uy, trap);
+            if (!brads_pit.created)
+                make_engr_at(u.ux,u.uy,BRADS_TEXT,0L,ENGRAVE);
+            brads_pit.created = TRUE;
+            pline("%s pit.", BRADS_TEXT);
+            return(&amp;zeroobj);
+        }
+#endif
 				(void) maketrap(u.ux, u.uy, trap);
 				pline("%s.", An(tname));
 				return(&amp;zeroobj);
@@ -2413,6 +2577,20 @@
 	if(!oclass) oclass = wrpsym[rn2((int)sizeof(wrpsym))];
 typfnd:
 	if (typ) oclass = objects[typ].oc_class;
+        bucstatus = blessed ? 1 : (uncursed ? 2 : (iscursed ? 3 : 0));
+
+	if (owner &amp;&amp; !mowner) {
+	    /* Time to figure out from whom, exactly, we're trying to steal an item.
+	       Basically, look for somebody called the given name; or else, look for
+	       somebody of the given monster type who's carrying an object of the given
+	       description, and preferably is visible. */
+	    /* Pass only a few of our flags; it shouldn't really matter. */
+            const char *aname = (name? name: actualn);
+	    mowner = ron_locateowner(owner, ownercnt, (asked_for_gold? (all_the_gold? -3: cnt): -9),
+                typ, bucstatus, ispoisoned, erodeproof, aname);
+	    if (!mowner) /* No such monster exists? */
+		return 0;
+	}
 
 	/* check for some objects that are not allowed */
 	if (typ &amp;&amp; objects[typ].oc_unique) {
@@ -2437,8 +2615,53 @@
 	    }
 	}
 
+	if (asked_for_gold) {
+	    if (!owner) {
+		if (cnt &gt; 5000
+#ifdef WIZARD
+		               &amp;&amp; !wizard
+#endif
+					  )
+		    cnt = 5000;
+                if (cnt &lt; 1) cnt = 1;
+#ifndef GOLDOBJ
+		u.ugold += cnt;
+		otmp = (&amp;zeroobj);
+#else
+		otmp = mksobj(GOLD_PIECE, FALSE, FALSE);
+		otmp-&gt;quan = cnt;
+                otmp-&gt;owt = weight(otmp);
+#endif
+	    } else {
+#ifndef GOLDOBJ
+		int mgold = mowner-&gt;mgold;
+#else
+		struct obj *mongold = findgold(mowner-&gt;minvent);
+		int mgold = (mongold == 0)? 0: mongold-&gt;quan;
+#endif
+		if (all_the_gold) cnt = mgold;
+		else if (cnt &gt; mgold) cnt = rnl(mgold+1);
+#ifndef GOLDOBJ
+		mowner-&gt;mgold -= cnt;
+		u.ugold += cnt;
+		otmp = (&amp;zeroobj);
+#else
+		if (cnt != 0) {
+		    if (cnt &lt; mongold-&gt;quan)
+		        splitobj(mongold, cnt);
+		    obj_extract_self(mongold);
+		    otmp = mongold;
+		} else
+		    otmp = (&amp;zeroobj);
+#endif
+	    }
+	    if (from_user) pline("%d gold pieces.", cnt);
+	    flags.botl=1;
+	    return(otmp);
+	}
+
 	/* catch any other non-wishable objects */
-	if (objects[typ].oc_nowish
+	if (objects[typ].oc_nowish &amp;&amp; !owner
 #ifdef WIZARD
 	    &amp;&amp; !wizard
 #endif
@@ -2447,18 +2670,40 @@
 
 	/* convert magic lamps to regular lamps before lighting them or setting
 	   the charges */
-	if (typ == MAGIC_LAMP
+	if (typ == MAGIC_LAMP &amp;&amp; !owner
 #ifdef WIZARD
 				&amp;&amp; !wizard
 #endif
 						)
 	    typ = OIL_LAMP;
 
-	if(typ) {
+	if (!owner) {
+	    if(typ) {
 		otmp = mksobj(typ, TRUE, FALSE);
-	} else {
+	    } else {
 		otmp = mkobj(oclass, FALSE);
 		if (otmp) typ = otmp-&gt;otyp;
+	    }
+	} else {
+	    long unwornmask;
+	    otmp = ron_getobj(mowner-&gt;minvent, typ, bucstatus,
+                    ispoisoned, erodeproof, spesgn ? spe : -998, name);
+	    if (!otmp) return 0;
+	    obj_extract_self(otmp);
+	    if (otmp == MON_WEP(mowner))
+		possibly_unwield(mowner, FALSE);  /* grab it right from his hand! */
+	    else if ((unwornmask = otmp-&gt;owornmask) != 0L) {
+		mowner-&gt;misc_worn_check &amp;= ~unwornmask;
+		if (otmp-&gt;owornmask &amp; W_WEP) {
+		    setmnotwielded(mowner, otmp);
+		    MON_NOWEP(mowner);
+		}
+		otmp-&gt;owornmask = 0L;
+		update_mon_intrinsics(mowner, otmp, FALSE, FALSE);
+	    }
+	    if (canseemon(mowner))
+		pline("%s looks startled!", Monnam(mowner));
+	    return(otmp);  /* don't reset any of its properties */
 	}
 
 	if (islit &amp;&amp;
</pre></body></html>