This patch makes pudding farming and altar camping a bit more expensive.

When NO_FARMING is defined, puddings divide almost like gremlins do, but
with a little more max HP.  Careful farming will yield almost as many
two-HP puddings as the original had max HP, but cannot be continued
indefinitely.  Farming rewards are reduced by making eliminating any
death-drops that would have been corroded or rotted by the pudding.
Undead-turning abuse is also prevented by making blobs, jellies, and
puddings immune to it.

When NO_CAMPING is defined, the gods get bored with multiple sacrifices
of the same type of corpse.  In addition, prayer timeouts increase over
time (not much, but should be noticable after extensive altar-camping),
particularly after granting an artifact.

Should be save- and bones-file compatible.

    -- Eric Wald


diff -ur nethack-3.4.3/include/config.h pudding/include/config.h
--- nethack-3.4.3/include/config.h	2005-02-25 15:43:53.000000000 -0700
+++ pudding/include/config.h	2005-02-25 15:37:55.000000000 -0700
@@ -350,6 +350,8 @@
 
 /*#define GOLDOBJ */	/* Gold is kept on obj chains - Helge Hafting */
 #define AUTOPICKUP_EXCEPTIONS /* exceptions to autopickup */
+#define NO_FARMING	/* Prevents pudding abuse - ESW */
+#define NO_CAMPING	/* Reduces benefits of altar camping - ESW */
 
 /* End of Section 5 */
 
diff -ur nethack-3.4.3/include/mondata.h pudding/include/mondata.h
--- nethack-3.4.3/include/mondata.h	2003-12-07 16:39:13.000000000 -0700
+++ pudding/include/mondata.h	2006-01-05 21:37:48.000000000 -0700
@@ -187,6 +187,16 @@
 				((ptr)->mlet == S_PUDDING &&         \
 				 (ptr) != &mons[PM_BLACK_PUDDING]))
 
+/* Animated, not truly alive; used for undead turning */
+#define lifeless(ptr)		((ptr)->mlet == S_BLOB || \
+				 (ptr)->mlet == S_JELLY ||            \
+				 (ptr)->mlet == S_PUDDING ||          \
+				 (ptr)->mlet == S_VORTEX ||           \
+				 (ptr)->mlet == S_LIGHT ||            \
+				((ptr)->mlet == S_ELEMENTAL &&        \
+				 (ptr) != &mons[PM_STALKER]) ||       \
+				 (ptr)->mlet == S_GOLEM)
+
 #define befriend_with_obj(ptr, obj) ((obj)->oclass == FOOD_CLASS && \
 				     is_domestic(ptr))
 
diff -ur nethack-3.4.3/src/makemon.c pudding/src/makemon.c
--- nethack-3.4.3/src/makemon.c	2003-12-07 16:39:13.000000000 -0700
+++ pudding/src/makemon.c	2006-01-05 22:19:49.000000000 -0700
@@ -708,11 +708,20 @@
 #ifndef GOLDOBJ
 	m2->mgold = 0L;
 #endif
+
+#ifdef NO_FARMING
+	/* Divide both HP and max HP by two, for both original and clone.
+	 * When either is odd, the original keeps the extra point.
+	 */
+	m2->mhpmax = mon->mhpmax / 2;
+	mon->mhpmax -= m2->mhpmax;
+#else
 	/* Max HP the same, but current HP halved for both.  The caller
 	 * might want to override this by halving the max HP also.
 	 * When current HP is odd, the original keeps the extra point.
 	 */
 	m2->mhpmax = mon->mhpmax;
+#endif
 	m2->mhp = mon->mhp / 2;
 	mon->mhp -= m2->mhp;
 
diff -ur nethack-3.4.3/src/mhitu.c pudding/src/mhitu.c
--- nethack-3.4.3/src/mhitu.c	2005-02-24 18:29:51.000000000 -0700
+++ pudding/src/mhitu.c	2005-02-24 18:30:13.000000000 -0700
@@ -2621,7 +2621,15 @@
 	mon = christen_monst(mon, plname);
 	initedog(mon);
 	mon->m_lev = youmonst.data->mlevel;
+#ifdef NO_FARMING
+	/* Divide both HP and max HP by two, for both player and clone.
+	 * When either is odd, the player keeps the extra point.
+	 */
+	mon->mhpmax = u.mhmax / 2;
+	u.mhmax -= mon->mhpmax;
+#else
 	mon->mhpmax = u.mhmax;
+#endif
 	mon->mhp = u.mh / 2;
 	u.mh -= mon->mhp;
 	flags.botl = 1;
Binary files nethack-3.4.3/src/mhitu.o and pudding/src/mhitu.o differ
diff -ur nethack-3.4.3/src/mon.c pudding/src/mon.c
--- nethack-3.4.3/src/mon.c	2003-12-07 16:39:13.000000000 -0700
+++ pudding/src/mon.c	2005-03-11 18:03:03.000000000 -0700
@@ -1833,6 +1833,15 @@
 			otmp = mkobj_at(RANDOM_CLASS, x, y, TRUE);
 			/* Don't create large objects from small monsters */
 			typ = otmp->otyp;
+#ifdef NO_FARMING
+			/* Don't create objects that would be destroyed */
+			if ((mdat == &mons[PM_BLACK_PUDDING]
+			        && is_corrodeable(otmp))
+			    || (mdat == &mons[PM_BROWN_PUDDING]
+			        && is_rottable(otmp))) {
+			    delobj(otmp);
+			} else
+#endif
 			if (mdat->msize < MZ_HUMAN && typ != FOOD_RATION
 			    && typ != LEASH
 			    && typ != FIGURINE
diff -ur nethack-3.4.3/src/potion.c pudding/src/potion.c
--- nethack-3.4.3/src/potion.c	2003-12-07 16:39:13.000000000 -0700
+++ pudding/src/potion.c	2005-02-24 17:58:34.000000000 -0700
@@ -1990,16 +1990,20 @@
 	if (mon == &youmonst) {
 	    mtmp2 = cloneu();
 	    if (mtmp2) {
+#ifndef NO_FARMING
 		mtmp2->mhpmax = u.mhmax / 2;
 		u.mhmax -= mtmp2->mhpmax;
+#endif
 		flags.botl = 1;
 		You("multiply%s!", reason);
 	    }
 	} else {
 	    mtmp2 = clone_mon(mon, 0, 0);
 	    if (mtmp2) {
+#ifndef NO_FARMING
 		mtmp2->mhpmax = mon->mhpmax / 2;
 		mon->mhpmax -= mtmp2->mhpmax;
+#endif
 		if (canspotmon(mon))
 		    pline("%s multiplies%s!", Monnam(mon), reason);
 	    }
diff -ur nethack-3.4.3/src/pray.c pudding/src/pray.c
--- nethack-3.4.3/src/pray.c	2003-12-07 16:39:13.000000000 -0700
+++ pudding/src/pray.c	2006-01-06 11:00:52.000000000 -0700
@@ -1149,7 +1149,11 @@
     if (otmp->otyp == CORPSE) {
 	register struct permonst *ptr = &mons[otmp->corpsenm];
 	struct monst *mtmp;
+#ifdef NO_CAMPING
+	extern int sacrifice_values[];
+#else
 	extern const int monstr[];
+#endif
 
 	/* KMH, conduct */
 	u.uconduct.gnostic++;
@@ -1159,7 +1163,20 @@
 
 	if (otmp->corpsenm == PM_ACID_BLOB
 		|| (monstermoves <= peek_at_iced_corpse_age(otmp) + 50)) {
+#ifdef NO_CAMPING
+	    /*
+	     * The gods don't care about too many sacrifices of the same type.
+	     * The greater the sacrifice value, the more readily it decays.
+	     */
+	    value = sacrifice_values[otmp->corpsenm] + 1;
+	    if (value > 1 && !rn2(2 * MAXVALUE / value))
+		--sacrifice_values[otmp->corpsenm];
+#else
 	    value = monstr[otmp->corpsenm] + 1;
+#endif
 	    if (otmp->oeaten)
 		value = eaten_stat(value, otmp);
 	}
@@ -1477,7 +1494,16 @@
 		    at_your_feet("An object");
 		    godvoice(u.ualign.type, "Use my gift wisely!");
 		    u.ugifts++;
+#ifdef NO_CAMPING
+		    u.ublesscnt = rnz(200 + (50 * nartifacts) +
+			              (monstermoves / 10));
+#else
 		    u.ublesscnt = rnz(300 + (50 * nartifacts));
+#endif
 		    exercise(A_WIS, TRUE);
 		    /* make sure we can use this weapon */
 		    unrestrict_weapon_skill(weapon_type(otmp));
@@ -1643,6 +1669,14 @@
 	    (void) water_prayer(TRUE);
 	pleased(alignment); /* nice */
     }
+#ifdef NO_CAMPING
+    /* Prayer timeouts increase later in the game */
+    u.ublesscnt += rnz(monstermoves / 100);
+#endif
     return(1);
 }
 
diff -ur nethack-3.4.3/src/uhitm.c pudding/src/uhitm.c
--- nethack-3.4.3/src/uhitm.c	2005-02-24 18:29:58.000000000 -0700
+++ pudding/src/uhitm.c	2005-03-11 18:03:05.000000000 -0700
@@ -1001,8 +1001,13 @@
 		   && objects[obj->otyp].oc_material == IRON
 		   && mon->mhp > 1 && !thrown && !mon->mcan
 		   /* && !destroyed  -- guaranteed by mhp > 1 */ ) {
-		if (clone_mon(mon, 0, 0)) {
+		struct monst *clone = clone_mon(mon, 0, 0);
+		if (clone) {
 			pline("%s divides as you hit it!", Monnam(mon));
+#ifdef NO_FARMING
+			/* Make the puddings just a bit tougher than half. */
+			clone->mhpmax += 1;
+#endif
 			hittxt = TRUE;
 		}
 	}
diff -ur nethack-3.4.3/src/zap.c pudding/src/zap.c
--- nethack-3.4.3/src/zap.c	2003-12-07 16:39:13.000000000 -0700
+++ pudding/src/zap.c	2006-01-05 21:45:04.000000000 -0700
@@ -617,6 +617,15 @@
 				return (struct monst *)0;
 		}
 
+#ifdef NO_FARMING
+		/* pudding and jelly corpses don't revive */
+		if (lifeless(&mons[montype])) {
+		    /* Another pun on "turn," if it would work properly. */
+		    /* pline("%s over.", Tobjnam(obj, "flip")); */
+		    return (struct monst *)0;
+		}
+#endif
+
 		if (MON_AT(x,y)) {
 		    coord new_xy;
 
diff -ur nethack-3.4.3/util/makedefs.c pudding/util/makedefs.c
--- nethack-3.4.3/util/makedefs.c	2003-12-07 16:39:13.000000000 -0700
+++ pudding/util/makedefs.c	2006-01-06 10:09:35.000000000 -0700
@@ -1364,10 +1364,18 @@
     /* might want to insert a final 0 entry here instead of just newline */
     Fprintf(ofp,"%s};\n", (j & 15) ? "\n" : "");
 
+    Fprintf(ofp,"#ifdef NO_CAMPING\n");
+    Fprintf(ofp,"\nint sacrifice_values[sizeof(monstr)/sizeof(monstr[0])];\n");
+    Fprintf(ofp,"#endif\n");
     Fprintf(ofp,"\nvoid NDECL(monstr_init);\n");
     Fprintf(ofp,"\nvoid\n");
     Fprintf(ofp,"monstr_init()\n");
     Fprintf(ofp,"{\n");
+    Fprintf(ofp,"#ifdef NO_CAMPING\n");
+    Fprintf(ofp,"    register int j;\n");
+    Fprintf(ofp,"    (void)memcpy((genericptr_t)sacrifice_values,\n");
+    Fprintf(ofp,"                 (genericptr_t)monstr, sizeof monstr);\n");
+    Fprintf(ofp,"#endif\n");
     Fprintf(ofp,"    return;\n");
     Fprintf(ofp,"}\n");
     Fprintf(ofp,"\n/*monstr.c*/\n");
