Merge branch 'NetHack-3.6.2-beta01' into NetHack-3.6.2

This commit is contained in:
nhmall
2018-12-16 17:39:39 -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
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)
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

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. */
/* 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 void FDECL(reset_rndmonst, (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(adj_lev, (struct permonst *));
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) Robert Patrick Rankin, 2012. */
/* 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.
* The second parameter specifies a special casing bit mask
* to allow the normal genesis masks to be deactivated.
* Returns Null if no monsters in that class can be made.
*/
The second parameter specifies a special casing bit mask
to allow the normal genesis masks to be deactivated.
Returns Null if no monsters in that class can be made. */
struct permonst *
mkclass(class, spc)
char class;
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;
int k, nums[SPECIAL_PM + 1]; /* +1: insurance for final return value */
int maxmlev, mask = (G_NOGEN | G_UNIQ) & ~spc;
(void) memset((genericptr_t) nums, 0, sizeof nums);
maxmlev = level_difficulty() >> 1;
if (class < 1 || class >= MAXMCLASSES) {
impossible("mkclass called with bad class!");
return (struct permonst *) 0;
}
/* 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++)
if (mons[first].mlet == class)
break;
if (first == SPECIAL_PM)
return (struct permonst *) 0;
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)
if (first == SPECIAL_PM) {
impossible("mkclass found no class %d monsters", class);
return (struct permonst *) 0;
}
/* Assumption #2: monsters of a given class are presented in ascending
* order of strength.
*/
for (num = rnd(num); num > 0; first++)
if (mk_gen_ok(first, 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)) {
/* but not when multiple monsters are same level */
if (mons[first].mlevel != mons[first + 1].mlevel)
num--;
for (last = first; last < SPECIAL_PM && mons[last].mlet == class; last++) {
if (atyp != A_NONE && sgn(mons[last].maligntyp) != sgn(atyp))
continue;
if (mk_gen_ok(last, G_GONE, 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
'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

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) Robert Patrick Rankin, 2008. */
/* NetHack may be freely redistributed. See license for details. */
@@ -256,7 +256,7 @@ register struct monst *mtmp;
flags.female ? "Sister" : "Brother");
if (!tele_restrict(mtmp))
(void) rloc(mtmp, TRUE);
return (1);
return 1;
}
cash = money_cnt(invent);
demand =
@@ -292,7 +292,7 @@ register struct monst *mtmp;
}
}
mongone(mtmp);
return (1);
return 1;
}
long
@@ -323,7 +323,7 @@ struct monst *mtmp;
}
(void) money2mon(mtmp, offer);
context.botl = 1;
return (offer);
return offer;
}
int
@@ -336,9 +336,9 @@ aligntyp atyp;
pm = rn1(PM_DEMOGORGON + 1 - PM_ORCUS, PM_ORCUS);
if (!(mvitals[pm].mvflags & G_GONE)
&& (atyp == A_NONE || sgn(mons[pm].maligntyp) == sgn(atyp)))
return (pm);
return pm;
}
return (dlord(atyp)); /* approximate */
return dlord(atyp); /* approximate */
}
int
@@ -351,9 +351,9 @@ aligntyp atyp;
pm = rn1(PM_YEENOGHU + 1 - PM_JUIBLEX, PM_JUIBLEX);
if (!(mvitals[pm].mvflags & G_GONE)
&& (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 */
@@ -361,9 +361,9 @@ int
llord()
{
if (!(mvitals[PM_ARCHON].mvflags & G_GONE))
return (PM_ARCHON);
return PM_ARCHON;
return (lminion()); /* approximate */
return lminion(); /* approximate */
}
int
@@ -375,7 +375,7 @@ lminion()
for (tryct = 0; tryct < 20; tryct++) {
ptr = mkclass(S_ANGEL, 0);
if (ptr && !is_lord(ptr))
return (monsndx(ptr));
return monsndx(ptr);
}
return NON_PM;
@@ -383,19 +383,26 @@ lminion()
int
ndemon(atyp)
aligntyp atyp;
aligntyp atyp; /* A_NONE is used for 'any alignment' */
{
int tryct;
struct permonst *ptr;
for (tryct = 0; tryct < 20; tryct++) {
ptr = mkclass(S_DEMON, 0);
if (ptr && is_ndemon(ptr)
&& (atyp == A_NONE || sgn(ptr->maligntyp) == sgn(atyp)))
return (monsndx(ptr));
}
return NON_PM;
/*
* 3.6.2: [fix #H2204, 22-Dec-2010, eight years later...]
* pick a correctly aligned demon in one try. This used to
* use mkclass() to choose a random demon type and keep trying
* (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
* 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 */