Merge branch 'NetHack-3.6.2'
This commit is contained in:
@@ -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
|
||||||
|
|||||||
@@ -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 *));
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
49
src/minion.c
49
src/minion.c
@@ -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 */
|
||||||
|
|||||||
Reference in New Issue
Block a user