fix github issue #352 - geno'd monsters in quest
The recent change to mkclass() was letting genocided monsters be created when role-specific monsters were chosen for quest levels. makemon(Null) -> rndmonst() -> qt_montype() -> mkclass() -> mk_gen_ok() was accepting members of the quest-specified class even when they should have been rejected. I'm still not sure why the revised bit manipulation didn't work as intended; the re-revised code does. G_IGNORE was a bug waiting to happen since it gets passed to mkclass() as a mons[].geno flag but is used to control the use of mvitals[].mvflags values. It's still being misused but at least it doesn't conflict with any of the other flags now. Fixes #352
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
$NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.226 $ $NHDT-Date: 1590870784 2020/05/30 20:33:04 $
|
||||
$NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.227 $ $NHDT-Date: 1590879610 2020/05/30 23:00:10 $
|
||||
|
||||
General Fixes and Modified Features
|
||||
-----------------------------------
|
||||
@@ -251,6 +251,7 @@ fix new "objects[0] class #1 not in order!" panic if plain 'char' is unsigned
|
||||
only generate shop items on solid floor squares
|
||||
avoid gcc 10 warning by removing duplicate definition of 'head_engr'
|
||||
if a monster removed a corpse from an ice box, the corpse would never rot away
|
||||
monster creation on quest levels could make genocided creatures
|
||||
|
||||
tty: redraw unexplored locations as S_unexplored rather than <space> after
|
||||
map has been partially overwritten by popup menu or text display
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* NetHack 3.6 monflag.h $NHDT-Date: 1585356420 2020/03/28 00:47:00 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.19 $ */
|
||||
/* NetHack 3.6 monflag.h $NHDT-Date: 1590879610 2020/05/30 23:00:10 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.20 $ */
|
||||
/* Copyright (c) 1989 Mike Threepoint */
|
||||
/* NetHack may be freely redistributed. See license for details. */
|
||||
|
||||
@@ -194,14 +194,16 @@ enum ms_sounds {
|
||||
#define G_GENO 0x0020 /* can be genocided */
|
||||
#define G_NOCORPSE 0x0010 /* no corpse left ever */
|
||||
#define G_FREQ 0x0007 /* creation frequency mask */
|
||||
/* note: G_IGNORE controls handling of mvitals[].mvflags bits but is
|
||||
passed to mkclass() as if it dealt with mons[].geno bits */
|
||||
#define G_IGNORE 0x8000 /* for mkclass(), ignore G_GENOD|G_EXTINCT */
|
||||
|
||||
/* for g.mvitals[].mvflags (variant during game), along with G_NOCORPSE */
|
||||
#define G_KNOWN 0x0004 /* have been encountered */
|
||||
#define G_GENOD 0x0002 /* have been genocided */
|
||||
#define G_EXTINCT 0x0001 /* population control; create no more */
|
||||
#define G_KNOWN 0x04 /* have been encountered */
|
||||
#define G_GENOD 0x02 /* have been genocided */
|
||||
#define G_EXTINCT 0x01 /* population control; create no more */
|
||||
#define G_GONE (G_GENOD | G_EXTINCT)
|
||||
#define MV_KNOWS_EGG 0x0008 /* player recognizes egg of this monster type */
|
||||
#define G_IGNORE 0x1000 /* for mkclass(), ignore G_GENOD|G_EXTINCT */
|
||||
#define MV_KNOWS_EGG 0x08 /* player recognizes egg of this monster type */
|
||||
|
||||
/* *INDENT-ON* */
|
||||
/* clang-format on */
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* NetHack 3.6 makemon.c $NHDT-Date: 1590621476 2020/05/27 23:17:56 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.171 $ */
|
||||
/* NetHack 3.6 makemon.c $NHDT-Date: 1590879611 2020/05/30 23:00:11 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.172 $ */
|
||||
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
|
||||
/*-Copyright (c) Robert Patrick Rankin, 2012. */
|
||||
/* NetHack may be freely redistributed. See license for details. */
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
static boolean FDECL(uncommon, (int));
|
||||
static int FDECL(align_shift, (struct permonst *));
|
||||
static boolean FDECL(mk_gen_ok, (int, int, int));
|
||||
static boolean FDECL(mk_gen_ok, (int, unsigned, unsigned));
|
||||
static boolean FDECL(wrong_elem_type, (struct permonst *));
|
||||
static void FDECL(m_initgrp, (struct monst *, int, int, int, int));
|
||||
static void FDECL(m_initthrow, (struct monst *, int, int));
|
||||
@@ -1624,11 +1624,12 @@ rndmonst()
|
||||
/* decide whether it's ok to generate a candidate monster by mkclass() */
|
||||
static boolean
|
||||
mk_gen_ok(mndx, mvflagsmask, genomask)
|
||||
int mndx, mvflagsmask, genomask;
|
||||
int mndx;
|
||||
unsigned mvflagsmask, genomask;
|
||||
{
|
||||
struct permonst *ptr = &mons[mndx];
|
||||
|
||||
if ((g.mvitals[mndx].mvflags & mvflagsmask) && !(genomask & G_IGNORE))
|
||||
if (g.mvitals[mndx].mvflags & mvflagsmask)
|
||||
return FALSE;
|
||||
if (ptr->geno & genomask)
|
||||
return FALSE;
|
||||
@@ -1658,12 +1659,13 @@ int spc;
|
||||
struct permonst *
|
||||
mkclass_aligned(class, spc, atyp)
|
||||
char class;
|
||||
int spc;
|
||||
int spc; /* special mons[].geno handling */
|
||||
aligntyp atyp;
|
||||
{
|
||||
register int first, last, num = 0;
|
||||
int k, nums[SPECIAL_PM + 1]; /* +1: insurance for final return value */
|
||||
int maxmlev, gmask, gehennom = Inhell != 0;
|
||||
int maxmlev, gehennom = Inhell != 0;
|
||||
unsigned mv_mask, gn_mask;
|
||||
|
||||
(void) memset((genericptr_t) nums, 0, sizeof nums);
|
||||
maxmlev = level_difficulty() >> 1;
|
||||
@@ -1685,6 +1687,13 @@ aligntyp atyp;
|
||||
return (struct permonst *) 0;
|
||||
}
|
||||
|
||||
mv_mask = G_GONE; /* G_GENOD | G_EXTINCT */
|
||||
if ((spc & G_IGNORE) != 0) {
|
||||
mv_mask = 0; /* mv_mask &= ~G_GONE; */
|
||||
/* G_IGNORE is not a mons[].geno mask so get rid of it now */
|
||||
spc &= ~G_IGNORE;
|
||||
}
|
||||
|
||||
/* Assumption #2: monsters of a given class are presented in ascending
|
||||
* order of strength.
|
||||
*/
|
||||
@@ -1696,13 +1705,12 @@ aligntyp atyp;
|
||||
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) */
|
||||
gmask = (G_NOGEN | G_UNIQ);
|
||||
gn_mask = (G_NOGEN | G_UNIQ);
|
||||
if (rn2(9) || class == S_LICH)
|
||||
gmask |= (gehennom ? G_NOHELL : G_HELL);
|
||||
gmask &= ~spc;
|
||||
gmask |= (spc & G_IGNORE);
|
||||
gn_mask |= (gehennom ? G_NOHELL : G_HELL);
|
||||
gn_mask &= ~spc;
|
||||
|
||||
if (mk_gen_ok(last, G_GONE, gmask)) {
|
||||
if (mk_gen_ok(last, mv_mask, gn_mask)) {
|
||||
/* consider it; don't reject a toostrong() monster if we
|
||||
don't have anything yet (num==0) or if it is the same
|
||||
(or lower) difficulty as preceding candidate (non-zero
|
||||
@@ -1748,7 +1756,7 @@ mkclass_poly(class)
|
||||
int class;
|
||||
{
|
||||
register int first, last, num = 0;
|
||||
int gmask;
|
||||
unsigned gmask;
|
||||
|
||||
for (first = LOW_PM; first < SPECIAL_PM; first++)
|
||||
if (mons[first].mlet == class)
|
||||
|
||||
Reference in New Issue
Block a user