Subject: NH311 Patch: Wisdom -> identify item bonus

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

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

This patch may be a little controversial, but I think it makes a lot of
sense.  As the word "wisdom" means essentially knowledge learned through
life experience, my patch makes it so as characters have higher wisdom,
they're more likely to already know what an item is.  I.e., a wise character
is more likely to have encountered an item in his/her lifetime before
stumbling into the dungeon.  It's silly to expect a character with 18 wisdom
to not have a clue about a potion of fruit juice.

So, by picking up an item, if your character hasn't seen this type of item
before, s/he may discover by picking up the item that the item is identified
depending on how much WIS your character has.  For example, by picking up a
swirly potion, you might see "You recognize this item after closer
inspection.  z - a potion of extra healing.".

The probability that you'll recognize an item ranges from a maximum of 50%
at 18+ WIS, down to a minimum of 5% for 12 or less WIS.  I think this gives
you an incentive to build your wisdom, which as far as I can tell, doesn't
really do anything for you after scanning the source code, unlike
STR/DEX/CON/INT/CHR which all have tangible benefits.

The patch is structured so you can't repeatedly drop and pickup an item
until you recognize it, so once you've first seen an item, you either know
what it is or you don't (until you use an identify scroll).

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/objclass.h nethack-3.3.1-idwis/include/objclass.h
--- nethack-3.3.1/include/objclass.h	Mon Dec  6 15:22:37 1999
+++ nethack-3.3.1-idwis/include/objclass.h	Wed Aug 29 09:42:00 2001
@@ -12,6 +12,7 @@
 	short	oc_descr_idx;		/* description when name unknown */
 	char *	oc_uname;		/* called by user */
 	Bitfield(oc_name_known,1);
+	Bitfield(oc_seen_before,1);	/* hero encountered this type of obj? */
 	Bitfield(oc_merge,1);	/* merge otherwise equal objects */
 	Bitfield(oc_uses_known,1); /* obj->known affects full decription */
 				/* otherwise, obj->dknown and obj->bknown */
diff -u -r nethack-3.3.1/src/objects.c nethack-3.3.1-idwis/src/objects.c
--- nethack-3.3.1/src/objects.c	Mon Feb 21 17:36:26 2000
+++ nethack-3.3.1-idwis/src/objects.c	Wed Aug 29 09:42:00 2001
@@ -42,8 +42,8 @@
 #else
 /* second pass -- object definitions */
 
-# define BITS(nmkn,mrg,uskn,ctnr,mgc,chrg,uniq,nwsh,big,tuf,dir,sub,mtrl) \
-	nmkn,mrg,uskn,0,mgc,chrg,uniq,nwsh,big,tuf,dir,mtrl,sub /* SCO ODT 1.1 cpp fodder */
+# define BITS(nmkn,snbf,mrg,uskn,ctnr,mgc,chrg,uniq,nwsh,big,tuf,dir,sub,mtrl) \
+	nmkn,snbf,mrg,uskn,0,mgc,chrg,uniq,nwsh,big,tuf,dir,mtrl,sub /* SCO ODT 1.1 cpp fodder */
 # define OBJECT(obj,bits,prp,sym,prob,dly,wt,cost,sdam,ldam,oc1,oc2,nut,color) \
 	{0, 0, (char *)0, bits, prp, sym, dly, COLOR_FIELD(color) \
 	 prob, wt, cost, sdam, ldam, oc1, oc2, nut}
@@ -56,24 +56,24 @@
 NEARDATA struct objclass objects[] = {
 #endif
 /* dummy object[0] -- description [2nd arg] *must* be NULL */
-	OBJECT(OBJ("strange object",(char *)0), BITS(1,0,0,0,0,0,0,0,0,0,0,P_NONE,0),
+	OBJECT(OBJ("strange object",(char *)0), BITS(1,1,0,0,0,0,0,0,0,0,0,0,P_NONE,0),
 			0, ILLOBJ_CLASS, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
 
 /* weapons ... */
 #define WEAPON(name,app,kn,mg,bi,prob,wt,cost,sdam,ldam,hitbon,typ,sub,metal,color) \
 	OBJECT( \
-		OBJ(name,app), BITS(kn,mg,1,0,0,1,0,0,bi,0,typ,sub,metal), 0, \
+		OBJ(name,app), BITS(kn,0,mg,1,0,0,1,0,0,bi,0,typ,sub,metal), 0, \
 		WEAPON_CLASS, prob, 0, \
 		wt, cost, sdam, ldam, hitbon, 0, wt, color )
 #define PROJECTILE(name,app,kn,prob,wt,cost,sdam,ldam,hitbon,metal,sub,color) \
 	OBJECT( \
 		OBJ(name,app), \
-		BITS(kn,1,1,0,0,1,0,0,0,0,PIERCE,sub,metal), 0, \
+		BITS(kn,0,1,1,0,0,1,0,0,0,0,PIERCE,sub,metal), 0, \
 		WEAPON_CLASS, prob, 0, \
 		wt, cost, sdam, ldam, hitbon, 0, wt, color )
 #define BOW(name,app,kn,prob,wt,cost,hitbon,metal,sub,color) \
 	OBJECT( \
-		OBJ(name,app), BITS(kn,0,1,0,0,1,0,0,0,0,0,sub,metal), 0, \
+		OBJ(name,app), BITS(kn,0,0,1,0,0,1,0,0,0,0,0,sub,metal), 0, \
 		WEAPON_CLASS, prob, 0, \
 		wt, cost, 2, 2, hitbon, 0, wt, color )
 
@@ -282,7 +282,7 @@
  */
 #define ARMOR(name,desc,kn,mgc,blk,power,prob,delay,wt,cost,ac,can,sub,metal,c) \
 	OBJECT( \
-		OBJ(name,desc), BITS(kn,0,1,0,mgc,1,0,0,blk,0,0,sub,metal), power, \
+		OBJ(name,desc), BITS(kn,0,0,1,0,mgc,1,0,0,blk,0,0,sub,metal), power, \
 		ARMOR_CLASS, prob, delay, wt, cost, \
 		0, 0, 10 - ac, can, wt, c )
 #define HELM(name,desc,kn,mgc,power,prob,delay,wt,cost,ac,can,metal,c) \
@@ -492,7 +492,7 @@
 /* rings ... */
 #define RING(name,power,stone,cost,mgc,spec,mohs,metal,color) OBJECT( \
 		OBJ(name,stone), \
-		BITS(0,0,spec,0,mgc,spec,0,0,0,HARDGEM(mohs),0,P_NONE,metal), \
+		BITS(0,0,0,spec,0,mgc,spec,0,0,0,HARDGEM(mohs),0,P_NONE,metal), \
 		power, RING_CLASS, 0, 0, 3, cost, 0, 0, 0, 0, 15, color )
 RING("adornment", ADORNED, "wooden",        100, 1, 1, 2, WOOD, HI_WOOD),
 RING("gain strength", 0, "granite",         150, 1, 1, 7, MINERAL, HI_MINERAL),
@@ -537,7 +537,7 @@
 
 /* amulets ... - THE Amulet comes last because it is special */
 #define AMULET(name,desc,power,prob) OBJECT( \
-		OBJ(name,desc), BITS(0,0,0,0,1,0,0,0,0,0,0,P_NONE,IRON), power, \
+		OBJ(name,desc), BITS(0,0,0,0,0,1,0,0,0,0,0,0,P_NONE,IRON), power, \
 		AMULET_CLASS, prob, 0, 20, 150, 0, 0, 0, 0, 20, HI_METAL )
 
 AMULET("amulet of ESP",           "circular",   TELEPAT,    175),
@@ -551,10 +551,10 @@
 AMULET("amulet of reflection",    "hexagonal",  REFLECTING,  75),
 AMULET("amulet of magical breathing", "octagonal",      MAGICAL_BREATHING, 65),
 OBJECT(OBJ("cheap plastic imitation of the Amulet of Yendor",
-	"Amulet of Yendor"), BITS(0,0,1,0,0,0,0,0,0,0,0,0,PLASTIC), 0,
+	"Amulet of Yendor"), BITS(0,0,0,1,0,0,0,0,0,0,0,0,0,PLASTIC), 0,
 	AMULET_CLASS, 0, 0, 20,    0, 0, 0, 0, 0,  1, HI_METAL),
 OBJECT(OBJ("Amulet of Yendor",	/* note: description == name */
-	"Amulet of Yendor"), BITS(0,0,1,0,1,0,1,1,0,0,0,0,MITHRIL), 0,
+	"Amulet of Yendor"), BITS(0,0,0,1,0,1,0,1,1,0,0,0,0,MITHRIL), 0,
 	AMULET_CLASS, 0, 0, 20, 3500, 0, 0, 0, 0, 20, HI_METAL),
 #undef AMULET
 
@@ -562,17 +562,17 @@
 /* tools with weapon characteristics come last */
 #define TOOL(name,desc,kn,mrg,mgc,chg,prob,wt,cost,mat,color) \
 	OBJECT( OBJ(name,desc), \
-		BITS(kn,mrg,chg,0,mgc,chg,0,0,0,0,0,P_NONE,mat), \
+		BITS(kn,0,mrg,chg,0,mgc,chg,0,0,0,0,0,P_NONE,mat), \
 		0, TOOL_CLASS, prob, 0, \
 		wt, cost, 0, 0, 0, 0, wt, color )
 #define CONTAINER(name,desc,kn,mgc,chg,prob,wt,cost,mat,color) \
 	OBJECT( OBJ(name,desc), \
-		BITS(kn,0,chg,1,mgc,chg,0,0,0,0,0,P_NONE,mat), \
+		BITS(kn,0,0,chg,1,mgc,chg,0,0,0,0,0,P_NONE,mat), \
 		0, TOOL_CLASS, prob, 0, \
 		wt, cost, 0, 0, 0, 0, wt, color )
 #define WEPTOOL(name,desc,kn,mgc,bi,prob,wt,cost,sdam,ldam,hitbon,sub,mat,clr) \
 	OBJECT( OBJ(name,desc), \
-		BITS(kn,0,1,0,mgc,1,0,0,bi,0,hitbon,sub,mat), \
+		BITS(kn,0,0,1,0,mgc,1,0,0,bi,0,hitbon,sub,mat), \
 		0, TOOL_CLASS, prob, 0, \
 		wt, cost, sdam, ldam, hitbon, 0, wt, clr )
 /* containers */
@@ -654,17 +654,17 @@
 
 /* two special unique artifact "tools" */
 OBJECT(OBJ("Candelabrum of Invocation", "candelabrum"),
-		BITS(0,0,1,0,1,0,1,1,0,0,0,P_NONE,GOLD), 0,
+		BITS(0,0,0,1,0,1,0,1,1,0,0,0,P_NONE,GOLD), 0,
 		TOOL_CLASS, 0, 0,10, 3000, 0, 0, 0, 0, 200, HI_GOLD),
 OBJECT(OBJ("Bell of Opening", "silver bell"),
-		BITS(0,0,1,0,1,1,1,1,0,0,0,P_NONE,SILVER), 0,
+		BITS(0,0,0,1,0,1,1,1,1,0,0,0,P_NONE,SILVER), 0,
 		TOOL_CLASS, 0, 0,10, 1000, 0, 0, 0, 0, 50, HI_SILVER),
 #undef TOOL
 #undef WEPTOOL
 
 /* Comestibles ... */
 #define FOOD(name,prob,delay,wt,unk,tin,nutrition,color) OBJECT( \
-		OBJ(name,(char *)0), BITS(1,1,unk,0,0,0,0,0,0,0,0,P_NONE,tin), 0, \
+		OBJ(name,(char *)0), BITS(1,1,1,unk,0,0,0,0,0,0,0,0,P_NONE,tin), 0, \
 		FOOD_CLASS, prob, delay, \
 		wt, nutrition/20 + 5, 0, 0, 0, 0, nutrition, color )
 /* all types of food (except tins & corpses) must have a delay of at least 1. */
@@ -686,7 +686,7 @@
 FOOD("huge chunk of meat",   0,20,400, 0, FLESH,2000, CLR_BROWN),
 /* special case because it's not mergable */
 OBJECT(OBJ("meat ring", (char *)0),
-    BITS(1,0,0,0,0,0,0,0,0,0,0,0,FLESH),
+    BITS(1,0,0,0,0,0,0,0,0,0,0,0,0,FLESH),
     0, FOOD_CLASS, 0, 1, 5, 1, 0, 0, 0, 0, 5, CLR_BROWN),
 
 /* fruits & veggies */
@@ -718,7 +718,7 @@
 
 /* potions ... */
 #define POTION(name,desc,mgc,power,prob,cost,color) OBJECT( \
-		OBJ(name,desc), BITS(0,1,0,0,mgc,0,0,0,0,0,0,P_NONE,GLASS), power, \
+		OBJ(name,desc), BITS(0,0,1,0,0,mgc,0,0,0,0,0,0,P_NONE,GLASS), power, \
 		POTION_CLASS, prob, 0, 20, cost, 0, 0, 0, 0, 10, color )
 POTION("gain ability", "ruby",          1, 0,          42, 300, CLR_RED),
 POTION("restore ability", "pink",       1, 0,          40, 100, CLR_BRIGHT_MAGENTA),
@@ -750,7 +750,7 @@
 
 /* scrolls ... */
 #define SCROLL(name,text,mgc,prob,cost) OBJECT( \
-		OBJ(name,text), BITS(0,1,0,0,mgc,0,0,0,0,0,0,P_NONE,PAPER), 0, \
+		OBJ(name,text), BITS(0,0,1,0,0,mgc,0,0,0,0,0,0,P_NONE,PAPER), 0, \
 		SCROLL_CLASS, prob, 0, 5, cost, 0, 0, 0, 0, 6, HI_PAPER )
 	SCROLL("enchant armor",         "ZELGO MER",            1,  63,  80),
 	SCROLL("destroy armor",         "JUYED AWK YACC",       1,  45, 100),
@@ -786,7 +786,7 @@
 
 /* spellbooks ... */
 #define SPELL(name,desc,sub,prob,delay,level,mgc,dir,color) OBJECT( \
-		OBJ(name,desc), BITS(0,0,0,0,mgc,0,0,0,0,0,dir,sub,PAPER), 0, \
+		OBJ(name,desc), BITS(0,0,0,0,0,mgc,0,0,0,0,0,dir,sub,PAPER), 0, \
 		SPBOOK_CLASS, prob, delay, \
 		50, level*100, 0, 0, 0, level, 20, color )
 SPELL("dig",             "parchment",   P_MATTER_SPELL, 20,  6, 5, 1, RAY,       HI_PAPER),
@@ -836,13 +836,13 @@
 /* blank spellbook must come last because it retains its description */
 SPELL("blank paper",     "plain",       P_NONE, 18,  0, 0, 0, 0,         HI_PAPER),
 /* a special, one of a kind, spellbook */
-OBJECT(OBJ("Book of the Dead", "papyrus"), BITS(0,0,1,0,1,0,1,1,0,0,0,P_NONE,PAPER), 0,
+OBJECT(OBJ("Book of the Dead", "papyrus"), BITS(0,0,0,1,0,1,0,1,1,0,0,0,P_NONE,PAPER), 0,
 	SPBOOK_CLASS, 0, 0,20, 3500, 0, 0, 0, 7, 20, HI_PAPER),
 #undef SPELL
 
 /* wands ... */
 #define WAND(name,typ,prob,cost,mgc,dir,metal,color) OBJECT( \
-		OBJ(name,typ), BITS(0,0,1,0,mgc,1,0,0,0,0,dir,P_NONE,metal), 0, \
+		OBJ(name,typ), BITS(0,0,0,1,0,mgc,1,0,0,0,0,dir,P_NONE,metal), 0, \
 		WAND_CLASS, prob, 0, 7, cost, 0, 0, 0, 0, 30, color )
 WAND("light",          "glass",    95, 100, 1, NODIR,     GLASS,    HI_GLASS),
 WAND("secret door detection", "balsa",
@@ -876,7 +876,7 @@
 
 /* coins ... - so far, gold is all there is */
 #define COIN(name,prob,metal) OBJECT( \
-		OBJ(name,(char *)0), BITS(0,1,0,0,0,0,0,0,0,0,0,P_NONE,metal), 0, \
+		OBJ(name,(char *)0), BITS(0,1,1,0,0,0,0,0,0,0,0,0,P_NONE,metal), 0, \
 		GOLD_CLASS, prob, 0, 1, 0, 0, 0, 0, 0, 0, HI_GOLD )
 	COIN("gold piece",      1000, GOLD),
 #undef COIN
@@ -884,11 +884,11 @@
 /* gems ... - includes stones and rocks but not boulders */
 #define GEM(name,desc,prob,wt,gval,nutr,mohs,glass,color) OBJECT( \
 	    OBJ(name,desc), \
-	    BITS(0,1,0,0,0,0,0,0,0,HARDGEM(mohs),0,-P_SLING,glass), 0, \
+	    BITS(0,0,1,0,0,0,0,0,0,0,HARDGEM(mohs),0,-P_SLING,glass), 0, \
 	    GEM_CLASS, prob, 0, 1, gval, 3, 3, 0, 0, nutr, color )
 #define ROCK(name,desc,kn,prob,wt,gval,sdam,ldam,mgc,nutr,mohs,glass,color) OBJECT( \
 	    OBJ(name,desc), \
-	    BITS(kn,1,0,0,mgc,0,0,0,0,HARDGEM(mohs),0,-P_SLING,glass), 0, \
+	    BITS(kn,0,1,0,0,mgc,0,0,0,0,HARDGEM(mohs),0,-P_SLING,glass), 0, \
 	    GEM_CLASS, prob, 0, wt, gval, sdam, ldam, 0, 0, nutr, color )
 GEM("dilithium crystal", "white",      2,  1, 4500, 15,  5, GEMSTONE, CLR_WHITE),
 GEM("diamond", "white",                3,  1, 4000, 15, 10, GEMSTONE, CLR_WHITE),
@@ -936,28 +936,28 @@
  * Boulders weigh more than MAX_CARR_CAP; statues use corpsenm to take
  * on a specific type and may act as containers (both affect weight).
  */
-OBJECT(OBJ("boulder",(char *)0), BITS(1,0,0,0,0,0,0,0,1,0,0,P_NONE,MINERAL), 0,
+OBJECT(OBJ("boulder",(char *)0), BITS(1,0,0,0,0,0,0,0,0,1,0,0,P_NONE,MINERAL), 0,
 		ROCK_CLASS,   100, 0, 6000,  0, 20, 20, 0, 0, 2000, HI_MINERAL),
-OBJECT(OBJ("statue", (char *)0), BITS(1,0,0,1,0,0,0,0,0,0,0,P_NONE,MINERAL), 0,
+OBJECT(OBJ("statue", (char *)0), BITS(1,0,0,0,1,0,0,0,0,0,0,0,P_NONE,MINERAL), 0,
 		ROCK_CLASS,   900, 0, 2500,  0, 20, 20, 0, 0, 2500, CLR_WHITE),
 
-OBJECT(OBJ("heavy iron ball", (char *)0), BITS(1,0,0,0,0,0,0,0,0,0,WHACK,P_NONE,IRON), 0,
+OBJECT(OBJ("heavy iron ball", (char *)0), BITS(1,0,0,0,0,0,0,0,0,0,0,WHACK,P_NONE,IRON), 0,
 		BALL_CLASS,  1000, 0,  480, 10, 25, 25, 0, 0,  200, HI_METAL),
 						/* +d4 when "very heavy" */
-OBJECT(OBJ("iron chain", (char *)0), BITS(1,0,0,0,0,0,0,0,0,0,WHACK,P_NONE,IRON), 0,
+OBJECT(OBJ("iron chain", (char *)0), BITS(1,0,0,0,0,0,0,0,0,0,0,WHACK,P_NONE,IRON), 0,
 		CHAIN_CLASS, 1000, 0,  120,  0,  4,  4, 0, 0,  200, HI_METAL),
 						/* +1 both l & s */
 
 OBJECT(OBJ("blinding venom", "splash of venom"),
-		BITS(0,1,0,0,0,0,0,1,0,0,0,P_NONE,LIQUID), 0,
+		BITS(0,0,1,0,0,0,0,0,1,0,0,0,P_NONE,LIQUID), 0,
 		VENOM_CLASS,  500, 0,	 1,  0,  0,  0, 0, 0,	 0, HI_ORGANIC),
 OBJECT(OBJ("acid venom", "splash of venom"),
-		BITS(0,1,0,0,0,0,0,1,0,0,0,P_NONE,LIQUID), 0,
+		BITS(0,0,1,0,0,0,0,0,1,0,0,0,P_NONE,LIQUID), 0,
 		VENOM_CLASS,  500, 0,	 1,  0,  6,  6, 0, 0,	 0, HI_ORGANIC),
 		/* +d6 small or large */
 
 /* fencepost, the deadly Array Terminator -- name [1st arg] *must* be NULL */
-	OBJECT(OBJ((char *)0,(char *)0), BITS(0,0,0,0,0,0,0,0,0,0,0,P_NONE,0), 0,
+	OBJECT(OBJ((char *)0,(char *)0), BITS(0,0,0,0,0,0,0,0,0,0,0,0,P_NONE,0), 0,
 		ILLOBJ_CLASS, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
 }; /* objects[] */
 
diff -u -r nethack-3.3.1/src/pickup.c nethack-3.3.1-idwis/src/pickup.c
--- nethack-3.3.1/src/pickup.c	Sat Jul 22 13:41:29 2000
+++ nethack-3.3.1-idwis/src/pickup.c	Wed Aug 29 09:48:58 2001
@@ -992,11 +992,42 @@
 	int res, nearload;
 	const char *where = (obj->ox == u.ux && obj->oy == u.uy) ?
 			    "here" : "there";
+	int per;
+	struct objclass *ocl = &objects[obj->otyp];
 
 	if (obj->quan < count) {
 	    impossible("pickup_object: count %ld > quan %ld?",
 		count, obj->quan);
 	    return 0;
+	}
+
+	if (!ocl->oc_seen_before) {
+		/*
+		 * This is the first time the hero has picked up
+		 * this type of object.  She may be able to identify
+		 * the type of object (but not its blessed/cursed
+		 * status, charge, etc.) depending on her life
+		 * experience (i.e. wisdom).
+		 */
+		ocl->oc_seen_before = 1;
+		if (!ocl->oc_name_known) {
+			/*
+			 * She has at best a 50% chance of knowing
+			 * about this type of object, if she's
+			 * maxed-out her wisdom.
+			 */
+			if (ACURR(A_WIS) >= 20)
+				per = 50;
+			else if (ACURR(A_WIS) < 12)
+				per = 5;
+			else
+				per = 50 - ((20 - ACURR(A_WIS)) * 5);
+
+			if (rn2(100) < per) {
+				You("recognize this item after closer inspection.");
+				ocl->oc_name_known = 1;
+			}
+		}
 	}
 
 	/* In case of auto-pickup, where we haven't had a chance