Merge branch 'NetHack-3.6.2'

This commit is contained in:
nhmall
2018-12-16 17:39:55 -05:00
4 changed files with 90 additions and 50 deletions

View File

@@ -271,6 +271,8 @@ clairvoyance revealing underwater or under-lava objects left object displayed
make it easier to clear 'pickup_types' (menustyles Traditional and Combination make it easier to clear 'pickup_types' (menustyles Traditional and Combination
could do so by setting it to 'a'; now ' ' works too; Full and Partial could do so by setting it to 'a'; now ' ' works too; Full and Partial
allowed unselecting every object class; now 'all classes' is a choice) allowed unselecting every object class; now 'all classes' is a choice)
distribution of monsters selected by mkclass() didn't match expected distrib
(cited example was ndemon() creating twice as many incubi as succubi)
Fixes to Post-3.6.1 Problems that Were Exposed Via git Repository Fixes to Post-3.6.1 Problems that Were Exposed Via git Repository

View File

@@ -1,4 +1,4 @@
/* NetHack 3.6 extern.h $NHDT-Date: 1544669659 2018/12/13 02:54:19 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.667 $ */ /* NetHack 3.6 extern.h $NHDT-Date: 1544998887 2018/12/16 22:21:27 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.671 $ */
/* Copyright (c) Steve Creps, 1988. */ /* Copyright (c) Steve Creps, 1988. */
/* NetHack may be freely redistributed. See license for details. */ /* NetHack may be freely redistributed. See license for details. */
@@ -1152,6 +1152,7 @@ E boolean FDECL(create_critters, (int, struct permonst *, BOOLEAN_P));
E struct permonst *NDECL(rndmonst); E struct permonst *NDECL(rndmonst);
E void FDECL(reset_rndmonst, (int)); E void FDECL(reset_rndmonst, (int));
E struct permonst *FDECL(mkclass, (CHAR_P, int)); E struct permonst *FDECL(mkclass, (CHAR_P, int));
E struct permonst *FDECL(mkclass_aligned, (CHAR_P, int, ALIGNTYP_P));
E int FDECL(mkclass_poly, (int)); E int FDECL(mkclass_poly, (int));
E int FDECL(adj_lev, (struct permonst *)); E int FDECL(adj_lev, (struct permonst *));
E struct permonst *FDECL(grow_up, (struct monst *, struct monst *)); E struct permonst *FDECL(grow_up, (struct monst *, struct monst *));

View File

@@ -1,4 +1,4 @@
/* NetHack 3.6 makemon.c $NHDT-Date: 1542798623 2018/11/21 11:10:23 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.128 $ */ /* NetHack 3.6 makemon.c $NHDT-Date: 1544998885 2018/12/16 22:21:25 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.131 $ */
/* 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. */
@@ -1635,59 +1635,89 @@ int mndx, mvflagsmask, genomask;
} }
/* Make one of the multiple types of a given monster class. /* Make one of the multiple types of a given monster class.
* The second parameter specifies a special casing bit mask The second parameter specifies a special casing bit mask
* to allow the normal genesis masks to be deactivated. to allow the normal genesis masks to be deactivated.
* Returns Null if no monsters in that class can be made. Returns Null if no monsters in that class can be made. */
*/
struct permonst * struct permonst *
mkclass(class, spc) mkclass(class, spc)
char class; char class;
int spc; int spc;
{
return mkclass_aligned(class, spc, A_NONE);
}
/* mkclass() with alignment restrictions; used by ndemon() */
struct permonst *
mkclass_aligned(class, spc, atyp)
char class;
int spc;
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 maxmlev, mask = (G_NOGEN | G_UNIQ) & ~spc; int maxmlev, mask = (G_NOGEN | G_UNIQ) & ~spc;
(void) memset((genericptr_t) nums, 0, sizeof nums);
maxmlev = level_difficulty() >> 1; maxmlev = level_difficulty() >> 1;
if (class < 1 || class >= MAXMCLASSES) { if (class < 1 || class >= MAXMCLASSES) {
impossible("mkclass called with bad class!"); impossible("mkclass called with bad class!");
return (struct permonst *) 0; return (struct permonst *) 0;
} }
/* Assumption #1: monsters of a given class are contiguous in the /* Assumption #1: monsters of a given class are contiguous in the
* mons[] array. * mons[] array. Player monsters and quest denizens
* are an exception; mkclass() won't pick them.
* SPECIAL_PM is long worm tail and separates the
* regular monsters from the exceptions.
*/ */
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)
break; break;
if (first == SPECIAL_PM) if (first == SPECIAL_PM) {
return (struct permonst *) 0; impossible("mkclass found no class %d monsters", class);
for (last = first; last < SPECIAL_PM && mons[last].mlet == class; last++)
if (mk_gen_ok(last, G_GONE, mask)) {
/* consider it */
if (num && toostrong(last, maxmlev)
&& mons[last].difficulty != mons[last - 1].difficulty && rn2(2))
break;
num += mons[last].geno & G_FREQ;
}
if (!num)
return (struct permonst *) 0; return (struct permonst *) 0;
}
/* 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 (num = rnd(num); num > 0; first++) for (last = first; last < SPECIAL_PM && mons[last].mlet == class; last++) {
if (mk_gen_ok(first, G_GONE, mask)) { if (atyp != A_NONE && sgn(mons[last].maligntyp) != sgn(atyp))
/* skew towards lower value monsters at lower exp. levels */ continue;
num -= mons[first].geno & G_FREQ; if (mk_gen_ok(last, G_GONE, mask)) {
if (num && adj_lev(&mons[first]) > (u.ulevel * 2)) { /* consider it; don't reject a toostrong() monster if we
/* but not when multiple monsters are same level */ don't have anything yet (num==0) or if it is the same
if (mons[first].mlevel != mons[first + 1].mlevel) (or lower) difficulty as preceding candidate (non-zero
num--; 'num' implies last > first so mons[last-1] is safe);
sometimes accept it even if high difficulty */
if (num && toostrong(last, maxmlev)
&& mons[last].difficulty > mons[last - 1].difficulty
&& rn2(2))
break;
if ((k = (mons[last].geno & G_FREQ)) > 0) {
/* skew towards lower value monsters at lower exp. levels
(this used to be done in the next loop, but that didn't
work well when multiple species had the same level and
were followed by one that was past the bias threshold;
cited example was sucubus and incubus, where the bias
against picking the next demon resulted in incubus
being picked nearly twice as often as sucubus);
we need the '+1' in case the entire set is too high
level (really low level hero) */
nums[last] = k + 1 - (adj_lev(&mons[last]) > (u.ulevel * 2));
num += nums[last];
} }
} }
first--; /* correct an off-by-one error */ }
if (!num)
return (struct permonst *) 0;
return &mons[first]; /* the hard work has already been done; 'num' should hit 0 before
first reaches last (which is actually one past our last candidate) */
for (num = rnd(num); first < last; first++)
if ((num -= nums[first]) <= 0)
break;
return nums[first] ? &mons[first] : (struct permonst *) 0;
} }
/* like mkclass(), but excludes difficulty considerations; used when /* like mkclass(), but excludes difficulty considerations; used when

View File

@@ -1,4 +1,4 @@
/* NetHack 3.6 minion.c $NHDT-Date: 1432512773 2015/05/25 00:12:53 $ $NHDT-Branch: master $:$NHDT-Revision: 1.33 $ */ /* NetHack 3.6 minion.c $NHDT-Date: 1544998886 2018/12/16 22:21:26 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.40 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/*-Copyright (c) Robert Patrick Rankin, 2008. */ /*-Copyright (c) Robert Patrick Rankin, 2008. */
/* NetHack may be freely redistributed. See license for details. */ /* NetHack may be freely redistributed. See license for details. */
@@ -256,7 +256,7 @@ register struct monst *mtmp;
flags.female ? "Sister" : "Brother"); flags.female ? "Sister" : "Brother");
if (!tele_restrict(mtmp)) if (!tele_restrict(mtmp))
(void) rloc(mtmp, TRUE); (void) rloc(mtmp, TRUE);
return (1); return 1;
} }
cash = money_cnt(invent); cash = money_cnt(invent);
demand = demand =
@@ -292,7 +292,7 @@ register struct monst *mtmp;
} }
} }
mongone(mtmp); mongone(mtmp);
return (1); return 1;
} }
long long
@@ -323,7 +323,7 @@ struct monst *mtmp;
} }
(void) money2mon(mtmp, offer); (void) money2mon(mtmp, offer);
context.botl = 1; context.botl = 1;
return (offer); return offer;
} }
int int
@@ -336,9 +336,9 @@ aligntyp atyp;
pm = rn1(PM_DEMOGORGON + 1 - PM_ORCUS, PM_ORCUS); pm = rn1(PM_DEMOGORGON + 1 - PM_ORCUS, PM_ORCUS);
if (!(mvitals[pm].mvflags & G_GONE) if (!(mvitals[pm].mvflags & G_GONE)
&& (atyp == A_NONE || sgn(mons[pm].maligntyp) == sgn(atyp))) && (atyp == A_NONE || sgn(mons[pm].maligntyp) == sgn(atyp)))
return (pm); return pm;
} }
return (dlord(atyp)); /* approximate */ return dlord(atyp); /* approximate */
} }
int int
@@ -351,9 +351,9 @@ aligntyp atyp;
pm = rn1(PM_YEENOGHU + 1 - PM_JUIBLEX, PM_JUIBLEX); pm = rn1(PM_YEENOGHU + 1 - PM_JUIBLEX, PM_JUIBLEX);
if (!(mvitals[pm].mvflags & G_GONE) if (!(mvitals[pm].mvflags & G_GONE)
&& (atyp == A_NONE || sgn(mons[pm].maligntyp) == sgn(atyp))) && (atyp == A_NONE || sgn(mons[pm].maligntyp) == sgn(atyp)))
return (pm); return pm;
} }
return (ndemon(atyp)); /* approximate */ return ndemon(atyp); /* approximate */
} }
/* create lawful (good) lord */ /* create lawful (good) lord */
@@ -361,9 +361,9 @@ int
llord() llord()
{ {
if (!(mvitals[PM_ARCHON].mvflags & G_GONE)) if (!(mvitals[PM_ARCHON].mvflags & G_GONE))
return (PM_ARCHON); return PM_ARCHON;
return (lminion()); /* approximate */ return lminion(); /* approximate */
} }
int int
@@ -375,7 +375,7 @@ lminion()
for (tryct = 0; tryct < 20; tryct++) { for (tryct = 0; tryct < 20; tryct++) {
ptr = mkclass(S_ANGEL, 0); ptr = mkclass(S_ANGEL, 0);
if (ptr && !is_lord(ptr)) if (ptr && !is_lord(ptr))
return (monsndx(ptr)); return monsndx(ptr);
} }
return NON_PM; return NON_PM;
@@ -383,19 +383,26 @@ lminion()
int int
ndemon(atyp) ndemon(atyp)
aligntyp atyp; aligntyp atyp; /* A_NONE is used for 'any alignment' */
{ {
int tryct;
struct permonst *ptr; struct permonst *ptr;
for (tryct = 0; tryct < 20; tryct++) { /*
ptr = mkclass(S_DEMON, 0); * 3.6.2: [fix #H2204, 22-Dec-2010, eight years later...]
if (ptr && is_ndemon(ptr) * pick a correctly aligned demon in one try. This used to
&& (atyp == A_NONE || sgn(ptr->maligntyp) == sgn(atyp))) * use mkclass() to choose a random demon type and keep trying
return (monsndx(ptr)); * (up to 20 times) until it got one with the desired alignment.
} * mkclass_aligned() skips wrongly aligned potential candidates.
* [The only neutral demons are djinni and mail daemon and
return NON_PM; * mkclass() won't pick them, but call it anyway in case either
* aspect of that changes someday.]
*/
#if 0
if (atyp == A_NEUTRAL)
return NON_PM;
#endif
ptr = mkclass_aligned(S_DEMON, 0, atyp);
return (ptr && is_ndemon(ptr)) ? monsndx(ptr) : NON_PM;
} }
/* guardian angel has been affected by conflict so is abandoning hero */ /* guardian angel has been affected by conflict so is abandoning hero */