]> granicus.if.org Git - nethack/commitdiff
spurious mail daemons (trunk only)
authornethack.rankin <nethack.rankin>
Mon, 28 Feb 2011 03:36:08 +0000 (03:36 +0000)
committernethack.rankin <nethack.rankin>
Mon, 28 Feb 2011 03:36:08 +0000 (03:36 +0000)
     From the newsgroup:  when the special level loader is creating
random '&' class monsters, it can produce mail daemons.  The thread
reports seeing some on the levels holding the Wizard of Yendor's Tower
and they vanish as soon as it's their turn to move.  I didn't reproduce
it, but create_monster() is overriding the NOGEN flag when it calls
mkclass() so getting mail daemons is feasible.  This fixes that by
treating them similar to the human/elf/orc/giant placeholder monsters
that are excluded from random generation.  More or less.

doc/fixes35.0
src/makemon.c

index 1f93ea78237106b4b355fb81dff6dcc41be75fd5..d1854634cbd4b2db50e8b6320d9d707b932f3ad7 100644 (file)
@@ -345,6 +345,7 @@ using an unlocking tool on a closed door which was actually a mimic reported
 purple worm could end up in wall or solid rock when swallowing ghost or xorn
 enhance life-saving by preventing subsequent poison from being fatal upon
        rescue from death due to spiked pit, dart trap, or poisoned missile
+don't create mail daemons when populating special levels with random demons
 
 
 Platform- and/or Interface-Specific Fixes
index a29ffe51a455fa985e2480612410f0ebed037f0d..2b7a2846c89c13d4714db42d9201297cf1ea5909 100644 (file)
@@ -1,5 +1,4 @@
 /* NetHack 3.5 makemon.c       $Date$  $Revision$ */
-/*     SCCS Id: @(#)makemon.c  3.5     2009/01/30      */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
 /* NetHack may be freely redistributed.  See license for details. */
 
@@ -20,6 +19,7 @@ STATIC_VAR NEARDATA struct monst zeromonst;
 
 STATIC_DCL boolean FDECL(uncommon, (int));
 STATIC_DCL int FDECL(align_shift, (struct permonst *));
+STATIC_DCL boolean FDECL(mk_gen_ok, (int,int,int));
 STATIC_DCL boolean FDECL(wrong_elem_type, (struct permonst *));
 STATIC_DCL void FDECL(m_initgrp,(struct monst *,int,int,int));
 STATIC_DCL void FDECL(m_initthrow,(struct monst *,int,int));
@@ -1371,6 +1371,23 @@ int mndx;        /* particular species that can no longer be created */
        } /* note: safe to ignore extinction of unique monsters */
 }
 
+/* decide whether it's ok to generate a candidate monster by mkclass() */
+STATIC_OVL boolean
+mk_gen_ok(mndx, mvflagsmask, genomask)
+int mndx, mvflagsmask, genomask;
+{
+       struct permonst *ptr = &mons[mndx];
+
+       if (mvitals[mndx].mvflags & mvflagsmask) return FALSE;
+       if (ptr->geno & genomask) return FALSE;
+       if (is_placeholder(ptr)) return FALSE;
+#ifdef MAIL
+       /* special levels might ask for random demon type; reject this one */
+       if (ptr == &mons[PM_MAIL_DAEMON]) return FALSE;
+#endif
+       return TRUE;
+}
+
 /*     The routine below is used to make one of the multiple types
  *     of a given monster class.  The second parameter specifies a
  *     special casing bit mask to allow the normal genesis
@@ -1400,8 +1417,7 @@ int       spc;
 
        for (last = first;
                last < SPECIAL_PM && mons[last].mlet == class; last++)
-           if (!(mvitals[last].mvflags & G_GONE) && !(mons[last].geno & mask)
-                                       && !is_placeholder(&mons[last])) {
+           if (mk_gen_ok(last, G_GONE, mask)) {
                /* consider it */
                if(num && toostrong(last, maxmlev) &&
                   monstr[last] != monstr[last-1] && rn2(2)) break;
@@ -1414,8 +1430,7 @@ int       spc;
  *                     order of strength.
  */
        for(num = rnd(num); num > 0; first++)
-           if (!(mvitals[first].mvflags & G_GONE) && !(mons[first].geno & mask)
-                                       && !is_placeholder(&mons[first])) {
+           if (mk_gen_ok(last, G_GONE, mask)) {
                /* skew towards lower value monsters at lower exp. levels */
                num -= mons[first].geno & G_FREQ;
                if (num && adj_lev(&mons[first]) > (u.ulevel*2)) {
@@ -1431,7 +1446,8 @@ int       spc;
 
 /* like mkclass(), but excludes difficulty considerations; used when
    player with polycontrol picks a class instead of a specific type;
-   genocided types are avoided but extinct ones are acceptable */
+   genocided types are avoided but extinct ones are acceptable; we don't
+   check polyok() here--caller accepts some choices !polyok() would reject */
 int
 mkclass_poly(class)
 int class;
@@ -1444,16 +1460,12 @@ int class;
 
        for (last = first;
                last < SPECIAL_PM && mons[last].mlet == class; last++)
-           if (!(mvitals[last].mvflags & G_GENOD) &&
-                   !(mons[last].geno & (G_NOGEN|G_UNIQ)) &&
-                   !is_placeholder(&mons[last]))
+           if (mk_gen_ok(last, G_GENOD, (G_NOGEN|G_UNIQ)))
                num += mons[last].geno & G_FREQ;
        if (!num) return NON_PM;
 
        for (num = rnd(num); num > 0; first++)
-           if (!(mvitals[first].mvflags & G_GENOD) &&
-                   !(mons[first].geno & (G_NOGEN|G_UNIQ)) &&
-                   !is_placeholder(&mons[first]))
+           if (mk_gen_ok(last, G_GENOD, (G_NOGEN|G_UNIQ)))
                num -= mons[first].geno & G_FREQ;
        first--; /* correct an off-by-one error */