fix github issue #349 - out of depth liches

Change mkclass() to always honor the hell-only monster generation
flag for L class, preventing master and arch-liches outside Gehennom.
For other classes, honor hell-only and outside-hell-only most (89%)
of the time.  When not honored (11%), it allows demons and devils to
appear outside of Gehennom as they have in the past.  [That part
might need to be re-done since it is done for all monsters in the
class on any mkclass() call instead of being done on a class-member
by class-member basis within each such call.]

This prevents out of depth liches in the Castle and ought to do same
for themed rooms of type 'Mausoleum' although I haven't figured out
how to test that.

Fixes #349
This commit is contained in:
PatR
2020-05-27 14:05:42 -07:00
parent c63165e5dc
commit c29ffe1d82
2 changed files with 25 additions and 7 deletions
+4 -1
View File
@@ -1,4 +1,4 @@
$NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.223 $ $NHDT-Date: 1589827569 2020/05/18 18:46:09 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.225 $ $NHDT-Date: 1590613502 2020/05/27 21:05:02 $
General Fixes and Modified Features General Fixes and Modified Features
----------------------------------- -----------------------------------
@@ -187,6 +187,9 @@ hold_another_object used hardcoded Stressed to limit carrying instead of
using the 'pickup_burden' option for that using the 'pickup_burden' option for that
when hold_another_object fails while hero is swallowed, drop the item into when hold_another_object fails while hero is swallowed, drop the item into
swallower's inventory instead of onto the floor swallower's inventory instead of onto the floor
change mkclass() to usually honor (always honor for L class) the hell-only and
never-in-hell monster creation flags; no more achi-lich in the Castle
(nor master lich there unless demilich gets a potion of gain level)
Fixes to 3.7.0-x Problems that Were Exposed Via git Repository Fixes to 3.7.0-x Problems that Were Exposed Via git Repository
+21 -6
View File
@@ -1,4 +1,4 @@
/* NetHack 3.6 makemon.c $NHDT-Date: 1587024537 2020/04/16 08:08:57 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.168 $ */ /* NetHack 3.6 makemon.c $NHDT-Date: 1590613502 2020/05/27 21:05:02 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.170 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/*-Copyright (c) Robert Patrick Rankin, 2012. */ /*-Copyright (c) Robert Patrick Rankin, 2012. */
/* NetHack may be freely redistributed. See license for details. */ /* NetHack may be freely redistributed. See license for details. */
@@ -1663,8 +1663,7 @@ aligntyp atyp;
{ {
register int first, last, num = 0; register int first, last, num = 0;
int k, nums[SPECIAL_PM + 1]; /* +1: insurance for final return value */ int k, nums[SPECIAL_PM + 1]; /* +1: insurance for final return value */
int ignore = (spc & G_IGNORE); int maxmlev, gmask;
int maxmlev, mask = (G_NOGEN | G_UNIQ) & ~spc;
(void) memset((genericptr_t) nums, 0, sizeof nums); (void) memset((genericptr_t) nums, 0, sizeof nums);
maxmlev = level_difficulty() >> 1; maxmlev = level_difficulty() >> 1;
@@ -1686,13 +1685,24 @@ aligntyp atyp;
return (struct permonst *) 0; return (struct permonst *) 0;
} }
gmask = (G_NOGEN | G_UNIQ);
/* traditionally mkclass() ignored hell-only and never-in-hell;
now we usually honor those but not all the time, mostly so that
the majority of major demons aren't constrained to Gehennom;
arch- and master liches are always so constrained (for creation;
lesser liches might grow up into them elsewhere) */
if (rn2(9) || class == S_LICH)
gmask |= (Inhell ? G_NOHELL : G_HELL);
gmask &= ~spc;
gmask |= (spc & G_IGNORE);
/* Assumption #2: monsters of a given class are presented in ascending /* Assumption #2: monsters of a given class are presented in ascending
* order of strength. * order of strength.
*/ */
for (last = first; last < SPECIAL_PM && mons[last].mlet == class; last++) { for (last = first; last < SPECIAL_PM && mons[last].mlet == class; last++) {
if (atyp != A_NONE && sgn(mons[last].maligntyp) != sgn(atyp)) if (atyp != A_NONE && sgn(mons[last].maligntyp) != sgn(atyp))
continue; continue;
if (mk_gen_ok(last, G_GONE, mask|ignore)) { if (mk_gen_ok(last, G_GONE, gmask)) {
/* consider it; don't reject a toostrong() monster if we /* consider it; don't reject a toostrong() monster if we
don't have anything yet (num==0) or if it is the same don't have anything yet (num==0) or if it is the same
(or lower) difficulty as preceding candidate (non-zero (or lower) difficulty as preceding candidate (non-zero
@@ -1738,6 +1748,7 @@ mkclass_poly(class)
int class; int class;
{ {
register int first, last, num = 0; register int first, last, num = 0;
int gmask;
for (first = LOW_PM; first < SPECIAL_PM; first++) for (first = LOW_PM; first < SPECIAL_PM; first++)
if (mons[first].mlet == class) if (mons[first].mlet == class)
@@ -1745,14 +1756,18 @@ int class;
if (first == SPECIAL_PM) if (first == SPECIAL_PM)
return NON_PM; return NON_PM;
gmask = (G_NOGEN | G_UNIQ);
if (rn2(9) || class == S_LICH)
gmask |= (Inhell ? G_NOHELL : G_HELL);
for (last = first; last < SPECIAL_PM && mons[last].mlet == class; last++) for (last = first; last < SPECIAL_PM && mons[last].mlet == class; last++)
if (mk_gen_ok(last, G_GENOD, (G_NOGEN | G_UNIQ))) if (mk_gen_ok(last, G_GENOD, gmask))
num += mons[last].geno & G_FREQ; num += mons[last].geno & G_FREQ;
if (!num) if (!num)
return NON_PM; return NON_PM;
for (num = rnd(num); num > 0; first++) for (num = rnd(num); num > 0; first++)
if (mk_gen_ok(first, G_GENOD, (G_NOGEN | G_UNIQ))) if (mk_gen_ok(first, G_GENOD, gmask))
num -= mons[first].geno & G_FREQ; num -= mons[first].geno & G_FREQ;
first--; /* correct an off-by-one error */ first--; /* correct an off-by-one error */