<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/include/extern.h nethack-patched/include/extern.h
--- nethack-3.4.3/include/extern.h	2005-12-19 17:51:04.000000000 +0000
+++ nethack-patched/include/extern.h	2006-03-03 16:10:10.000000000 +0000
@@ -1191,6 +1191,7 @@
 E boolean FDECL(hates_silver, (struct permonst *));
 E boolean FDECL(passes_bars, (struct permonst *));
 E boolean FDECL(can_track, (struct permonst *));
+E boolean FDECL(has_slow_digestion, (struct monst *));
 E boolean FDECL(breakarm, (struct permonst *));
 E boolean FDECL(sliparm, (struct permonst *));
 E boolean FDECL(sticks, (struct permonst *));
diff -Ndur nethack-3.4.3/include/monattk.h nethack-patched/include/monattk.h
--- nethack-3.4.3/include/monattk.h	2005-12-19 17:51:06.000000000 +0000
+++ nethack-patched/include/monattk.h	2006-03-03 16:10:10.000000000 +0000
@@ -96,5 +96,6 @@
 #define MM_HIT		0x1	/* aggressor hit defender */
 #define MM_DEF_DIED	0x2	/* defender died */
 #define MM_AGR_DIED	0x4	/* aggressor died */
+#define MM_EXPELLED     0x8     /* defender was saved by slow digestion */
 
 #endif /* MONATTK_H */
diff -Ndur nethack-3.4.3/src/mhitm.c nethack-patched/src/mhitm.c
--- nethack-3.4.3/src/mhitm.c	2005-12-19 17:51:28.000000000 +0000
+++ nethack-patched/src/mhitm.c	2006-03-03 16:10:22.000000000 +0000
@@ -175,12 +175,14 @@
  *
  * This function returns a result bitfield:
  *
- *	    --------- aggressor died
- *	   /  ------- defender died
- *	  /  /  ----- defender was hit
- *	 /  /  /
- *	x  x  x
+ *           ----------- defender was "hurriedly expelled"
+ *	    /  --------- aggressor died
+ *	   /  /  ------- defender died
+ *	  /  /  /  ----- defender was hit
+ *	 /  /  /  /
+ *	x  x  x  x
  *
+ *      0x8     MM_EXPELLED
  *	0x4	MM_AGR_DIED
  *	0x2	MM_DEF_DIED
  *	0x1	MM_HIT
@@ -535,13 +537,20 @@
 	    place_monster(magr, dx, dy);
 	    newsym(dx, dy);
 	}
- 	else if (status &amp; MM_AGR_DIED) {	/* agressor died */
+ 	else if (status &amp; MM_AGR_DIED) {	/* aggressor died */
 	    place_monster(mdef, dx, dy);
 	    newsym(dx, dy);
 	}
 	else {					/* both alive, put them back */
-	    if (cansee(dx, dy))
-		pline("%s is regurgitated!", Monnam(mdef));
+	    if (cansee(dx, dy)) {
+                if (status &amp; MM_EXPELLED) {
+                    strcpy(buf, Monnam(magr));
+		    pline("%s hurriedly regurgitates %s!", buf, mon_nam(mdef));
+                    pline("Obviously, it didn't like %s taste.", s_suffix(mon_nam(mdef)));
+                } else {
+		    pline("%s is regurgitated!", Monnam(mdef));
+                }
+            }
 
 	    place_monster(magr, ax, ay);
 	    place_monster(mdef, dx, dy);
@@ -622,6 +631,8 @@
 
 	switch(mattk-&gt;adtyp) {
 	    case AD_DGST:
+                if (has_slow_digestion(mdef) || has_slow_digestion(magr))
+                    return (MM_HIT | MM_EXPELLED);
 		/* eating a Rider or its corpse is fatal */
 		if (is_rider(mdef-&gt;data)) {
 		    if (vis)
diff -Ndur nethack-3.4.3/src/mhitu.c nethack-patched/src/mhitu.c
--- nethack-3.4.3/src/mhitu.c	2005-12-19 17:51:28.000000000 +0000
+++ nethack-patched/src/mhitu.c	2006-03-03 16:10:22.000000000 +0000
@@ -1698,7 +1698,7 @@
 	switch(mattk-&gt;adtyp) {
 
 		case AD_DGST:
-		    if (Slow_digestion) {
+		    if (Slow_digestion || has_slow_digestion(mtmp)) {
 			/* Messages are handled below */
 			u.uswldtim = 0;
 			tmp = 0;
diff -Ndur nethack-3.4.3/src/mondata.c nethack-patched/src/mondata.c
--- nethack-3.4.3/src/mondata.c	2006-02-28 21:30:32.000000000 +0000
+++ nethack-patched/src/mondata.c	2006-03-03 16:53:10.000000000 +0000
@@ -270,6 +270,16 @@
 		return((boolean)haseyes(ptr));
 }
 
+boolean
+has_slow_digestion(mdef)
+register struct monst *mdef;
+{
+    struct obj *obj;
+    if (!(mdef-&gt;misc_worn_check &amp; W_RINGL)) return (FALSE);
+    obj = which_armor(mdef, W_RINGL);
+    return (obj-&gt;otyp == RIN_SLOW_DIGESTION);
+}
+
 #endif /* OVL1 */
 #ifdef OVLB
 
diff -Ndur nethack-3.4.3/src/monmove.c nethack-patched/src/monmove.c
--- nethack-3.4.3/src/monmove.c	2005-12-19 17:51:30.000000000 +0000
+++ nethack-patched/src/monmove.c	2006-03-03 16:10:24.000000000 +0000
@@ -584,6 +584,22 @@
 	return(FALSE);
 }
 
+
+boolean
+is_teleporting(mtmp)
+register struct monst *mtmp;
+{
+    if (mtmp-&gt;mcan || tele_restrict(mtmp)) return FALSE;
+    if (mtmp-&gt;data == &amp;mons[PM_TENGU]) return TRUE;
+    /* Look for a ring of teleportation worn by this monster. */
+    if (mtmp-&gt;misc_worn_check &amp; W_RINGL) {
+        struct obj *obj = which_armor(mtmp, W_RINGL);
+        if (obj &amp;&amp; obj-&gt;otyp == RIN_TELEPORTATION) return TRUE;
+    }
+    return FALSE;
+}
+
+
 /* Return values:
  * 0: did not move, but can still attack and do other stuff.
  * 1: moved, possibly can attack.
@@ -698,8 +714,7 @@
 #endif
 
 	/* teleport if that lies in our nature */
-	if(ptr == &amp;mons[PM_TENGU] &amp;&amp; !rn2(5) &amp;&amp; !mtmp-&gt;mcan &amp;&amp;
-	   !tele_restrict(mtmp)) {
+	if(is_teleporting(mtmp) &amp;&amp; !rn2(5)) {
 	    if(mtmp-&gt;mhp &lt; 7 || mtmp-&gt;mpeaceful || rn2(2))
 		(void) rloc(mtmp, FALSE);
 	    else
diff -Ndur nethack-3.4.3/src/muse.c nethack-patched/src/muse.c
--- nethack-3.4.3/src/muse.c	2005-12-19 17:51:30.000000000 +0000
+++ nethack-patched/src/muse.c	2006-03-03 17:08:16.000000000 +0000
@@ -1953,7 +1953,8 @@
 		mon-&gt;data == &amp;mons[PM_GHOST])	/* don't loot bones piles */
 	    return FALSE;
 
-	if (typ == WAN_MAKE_INVISIBLE || typ == POT_INVISIBILITY)
+	if (typ == WAN_MAKE_INVISIBLE || typ == POT_INVISIBILITY ||
+                                         typ == RIN_INVISIBILITY)
 	    return (boolean)(!mon-&gt;minvis &amp;&amp; !mon-&gt;invis_blkd &amp;&amp; !attacktype(mon-&gt;data, AT_GAZE));
 	if (typ == WAN_SPEED_MONSTER || typ == POT_SPEED)
 	    return (boolean)(mon-&gt;mspeed != MFAST);
@@ -2016,6 +2017,31 @@
 	    if (typ == EGG)
 		return (boolean)(touch_petrifies(&amp;mons[obj-&gt;corpsenm]));
 	    break;
+        case RING_CLASS:
+            /* Should match the list in m_dowear_type */
+            /* Shopkeepers don't go for invisibility or teleportation */
+            if (typ == RIN_PROTECTION)
+                return (obj-&gt;spe &gt; 0);
+            if (typ == RIN_FIRE_RESISTANCE)
+                return (!resists_fire(mon));
+            if (typ == RIN_COLD_RESISTANCE)
+                return (!resists_cold(mon));
+            if (typ == RIN_SHOCK_RESISTANCE)
+                return (!resists_elec(mon));
+            if (typ == RIN_POISON_RESISTANCE)
+                return (!resists_poison(mon));
+            if (typ == RIN_SLOW_DIGESTION)
+                return (youmonst.data == &amp;mons[PM_PURPLE_WORM]);
+            if (typ == RIN_REGENERATION)
+                return (!is_reviver(mon-&gt;data));
+            /* Below this line are off-limits to shks and uniques */
+            if (is_covetous(mon-&gt;data) || (mon-&gt;data-&gt;geno &amp; G_UNIQ))
+                return (FALSE);
+            if (typ == RIN_INVISIBILITY)
+                return (!(mon-&gt;minvis) &amp;&amp; !HSee_invisible);
+            if (typ == RIN_TELEPORTATION)
+                return (mon-&gt;data != &amp;mons[PM_TENGU]);
+            break;
 	default:
 	    break;
 	}
diff -Ndur nethack-3.4.3/src/uhitm.c nethack-patched/src/uhitm.c
--- nethack-3.4.3/src/uhitm.c	2005-12-19 17:51:44.000000000 +0000
+++ nethack-patched/src/uhitm.c	2006-03-03 17:07:58.000000000 +0000
@@ -1763,6 +1763,14 @@
 		start_engulf(mdef);
 		switch(mattk-&gt;adtyp) {
 		    case AD_DGST:
+                        /* slow digestion protects against engulfing */
+                        if (has_slow_digestion(mdef)) {
+			    You("hurriedly regurgitate the sizzling in your %s.",
+				body_part(STOMACH));
+                            end_engulf();
+                            return (2);
+                        }
+
 			/* eating a Rider or its corpse is fatal */
 			if (is_rider(mdef-&gt;data)) {
 			 pline("Unfortunately, digesting any of it is fatal.");
diff -Ndur nethack-3.4.3/src/worn.c nethack-patched/src/worn.c
--- nethack-3.4.3/src/worn.c	2005-12-19 17:51:46.000000000 +0000
+++ nethack-patched/src/worn.c	2006-03-03 17:19:54.000000000 +0000
@@ -4,6 +4,10 @@
 
 #include "hack.h"
 
+/* Monsters with "digest" attacks affected by rings of slow digestion. */
+#define is_digester(m) ((m == &amp;mons[PM_PURPLE_WORM]) || \
+     (m == &amp;mons[PM_TRAPPER]) || (m == &amp;mons[PM_LURKER_ABOVE]))
+
 STATIC_DCL void FDECL(m_lose_armor, (struct monst *,struct obj *));
 STATIC_DCL void FDECL(m_dowear_type, (struct monst *,long, BOOLEAN_P, BOOLEAN_P));
 STATIC_DCL int FDECL(extra_pref, (struct monst *, struct obj *));
@@ -386,6 +390,10 @@
 	m_dowear_type(mon, W_ARMH, creation, FALSE);
 	if (!MON_WEP(mon) || !bimanual(MON_WEP(mon)))
 	    m_dowear_type(mon, W_ARMS, creation, FALSE);
+        /* One ring per monster; ring takes up a "hand" slot (always W_RINGL) */
+        if (!MON_WEP(mon) ||
+             (!bimanual(MON_WEP(mon)) &amp;&amp; !(mon-&gt;misc_worn_check &amp; W_ARMS)))
+          m_dowear_type(mon, W_RINGL, creation, FALSE);
 	m_dowear_type(mon, W_ARMG, creation, FALSE);
 	if (!slithy(mon-&gt;data) &amp;&amp; mon-&gt;data-&gt;mlet != S_CENTAUR)
 	    m_dowear_type(mon, W_ARMF, creation, FALSE);
@@ -452,6 +460,22 @@
 		    if (!is_suit(obj)) continue;
 		    if (racialexception &amp;&amp; (racial_exception(mon, obj) &lt; 1)) continue;
 		    break;
+                case W_RINGL:
+                    /* Monsters can put on only the following rings. */
+                    if (obj-&gt;oclass != RING_CLASS ||
+			(obj-&gt;otyp != RIN_INVISIBILITY &amp;&amp;
+			 obj-&gt;otyp != RIN_FIRE_RESISTANCE &amp;&amp;
+			 obj-&gt;otyp != RIN_COLD_RESISTANCE &amp;&amp;
+			 obj-&gt;otyp != RIN_POISON_RESISTANCE &amp;&amp;
+			 obj-&gt;otyp != RIN_SHOCK_RESISTANCE &amp;&amp;
+			 obj-&gt;otyp != RIN_REGENERATION &amp;&amp;
+			 obj-&gt;otyp != RIN_TELEPORTATION &amp;&amp;
+			 obj-&gt;otyp != RIN_SLOW_DIGESTION &amp;&amp;
+			 obj-&gt;otyp != RIN_PROTECTION))
+			continue;
+                    if (obj-&gt;otyp == RIN_SLOW_DIGESTION &amp;&amp;
+                        !is_digester(youmonst.data)) continue;
+                    break;
 	    }
 	    if (obj-&gt;owornmask) continue;
 	    /* I'd like to define a VISIBLE_ARM_BONUS which doesn't assume the
@@ -696,6 +725,12 @@
 		if (polyspot) bypass_obj(otmp);
 		m_lose_armor(mon, otmp);
 	    }
+            if ((otmp = which_armor(mon, W_RINGL)) != 0) {
+                if (vis)
+                    pline("%s drops %s ring!", Monnam(mon), ppronoun);
+		if (polyspot) bypass_obj(otmp);
+		m_lose_armor(mon, otmp);
+            }
 	}
 	if (handless_or_tiny || has_horns(mdat)) {
 	    if ((otmp = which_armor(mon, W_ARMH)) != 0 &amp;&amp;
@@ -752,19 +787,68 @@
 	return;
 }
 
-/* bias a monster's preferences towards armor that has special benefits. */
-/* currently only does speed boots, but might be expanded if monsters get to
-   use more armor abilities */
+/*
+ * Bias a monster's preferences towards armor that has special benefits.
+ * Currently does speed boots and various rings.
+ */
 static int
 extra_pref(mon, obj)
 struct monst *mon;
 struct obj *obj;
 {
-    if (obj) {
-	if (obj-&gt;otyp == SPEED_BOOTS &amp;&amp; mon-&gt;permspeed != MFAST)
-	    return 20;
+    struct obj *old;
+    int rc = 1;
+
+    if (!obj) return 0;
+
+    if (obj-&gt;otyp == SPEED_BOOTS &amp;&amp; mon-&gt;permspeed != MFAST)
+        return 20;
+    if (obj-&gt;oclass != RING_CLASS)
+        return 0;
+
+    /* Find out whether the monster already has some resistance. */
+    old = which_armor(mon, W_RINGL);
+    if (old) update_mon_intrinsics(mon, old, FALSE, TRUE);
+    /* This list should match the list in m_dowear_type. */
+    switch (obj-&gt;otyp) {
+        case RIN_FIRE_RESISTANCE:
+            if (!resists_fire(mon))
+                rc = (uwep &amp;&amp; uwep-&gt;oartifact == ART_FIRE_BRAND)? 20: 12;
+            break;
+        case RIN_COLD_RESISTANCE:
+            if (!resists_cold(mon))
+                rc = (uwep &amp;&amp; uwep-&gt;oartifact == ART_FROST_BRAND)? 20: 12;
+            break;
+	case RIN_POISON_RESISTANCE:
+            if (!resists_poison(mon))
+                rc = 10;
+            break;
+	case RIN_SHOCK_RESISTANCE:
+            if (!resists_elec(mon))
+                rc = (uwep &amp;&amp; uwep-&gt;oartifact == ART_MJOLLNIR)? 20: 10;
+            break;
+	case RIN_REGENERATION:
+            rc = is_reviver(mon-&gt;data)? 20: 5;
+	case RIN_INVISIBILITY:
+            if (!is_covetous(mon-&gt;data))
+                rc = See_invisible? 4: 30;
+            break;
+	case RIN_PROTECTION:
+            if (obj-&gt;spe &gt; 0)
+                rc = 10 + 3*(obj-&gt;spe);
+            else rc = 0;
+            break;
+        case RIN_TELEPORTATION:
+            if (mon-&gt;data != &amp;mons[PM_TENGU] &amp;&amp; !is_covetous(mon-&gt;data))
+                rc = (obj-&gt;cursed)? 5: 15;
+            break;
+        case RIN_SLOW_DIGESTION:
+            /* If we're here, the player is polyed into a digesting monster. */
+            rc = 25;
+            break;
     }
-    return 0;
+    if (old) update_mon_intrinsics(mon, old, TRUE, TRUE);
+    return rc;
 }
 
 /*
</pre></body></html>