fix #K669 - 'nasty' monster summoning

Report complained about multiple Archons causing his character to
be swarmed by monsters on the Plane of Fire.  I don't think that
the behavior has changed significantly from how it worked in 3.4.3.
Nobody can summon an Archon directly because they're excluded from
the nasties[] list.  But whenever summoning picks a genocided
'nasty', the result gets replaced by random monster of appropriate
difficulty for the level (which could be an Archon for a high level
character in the endgame).  [Note that that won't pick an Archon
in Gehennom or at arch-lich outside of there because the random
monster creation honors the only-in-hell and never-in-hell flags;
picking from the nasties[] list doesn't.]

This prevents that for any creature (except arch-lich or the Wizard)
casting the summon nasties spell.  If a replacement creature is a
spellcaster it now has to have lower difficulty than the summoner.
If not, it will be discarded even though its difficulty is classified
as appropriate.  So to summon an Archon, the summoner has to have
higher difficulty than an Archon; arch-lich and the Wizard are the
only ones meeting that criterium.  When summoner is an arch-lich,
it can't summon another arch-lich (since that wouldn't have lower
difficulty than the summoner) and can summon (via replacement for
genocided type, and only if outside of Gehennom) at most one Archon.
When summoner is the Wizard, he could summon an arch-lich (when in
Gehennom; demoted to master lich elsewhere--see below) or an Archon
(outside Gehennom only), but at most one per summoning.

For post-Wizard harassment, which effectively has infinite
difficulty level, it could still happen.  However, each instance of
harassment is only allowed to create at most one Archon or arch-lich
now, so chain summoning should be lessoned.  Also if it tries to
pick an arch-lich when outside of Gehennom it will switch to master
lich instead (which won't be allowed to summon an Archon or an arch-
lich or even another master lich).

(The monmove.c bit is unrelated, just some comment formatting that
I had laying around that got mixed in.)
This commit is contained in:
PatR
2020-03-27 19:05:52 -07:00
parent 0ac3329289
commit 3eed500886
8 changed files with 143 additions and 52 deletions

View File

@@ -1,4 +1,4 @@
/* NetHack 3.6 makemon.c $NHDT-Date: 1574722863 2019/11/25 23:01:03 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.142 $ */
/* NetHack 3.6 makemon.c $NHDT-Date: 1585361050 2020/03/28 02:04:10 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.162 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/*-Copyright (c) Robert Patrick Rankin, 2012. */
/* NetHack may be freely redistributed. See license for details. */
@@ -923,20 +923,20 @@ int mndx;
boolean tally;
boolean ghostly;
{
boolean result;
uchar lim = mbirth_limit(mndx);
boolean gone = (g.mvitals[mndx].mvflags & G_GONE) != 0; /* geno'd|extinct */
boolean gone, result;
int lim = mbirth_limit(mndx);
result = (((int) g.mvitals[mndx].born < lim) && !gone) ? TRUE : FALSE;
gone = (g.mvitals[mndx].mvflags & G_GONE) != 0; /* geno'd|extinct */
result = ((int) g.mvitals[mndx].born < lim && !gone) ? TRUE : FALSE;
/* if it's unique, don't ever make it again */
if ((mons[mndx].geno & G_UNIQ) && mndx != PM_HIGH_PRIEST)
if ((mons[mndx].geno & G_UNIQ) != 0 && mndx != PM_HIGH_PRIEST)
g.mvitals[mndx].mvflags |= G_EXTINCT;
if (g.mvitals[mndx].born < 255 && tally
&& (!ghostly || (ghostly && result)))
if (g.mvitals[mndx].born < 255 && tally && (!ghostly || result))
g.mvitals[mndx].born++;
if ((int) g.mvitals[mndx].born >= lim && !(mons[mndx].geno & G_NOGEN)
if ((int) g.mvitals[mndx].born >= lim
&& !(mons[mndx].geno & G_NOGEN)
&& !(g.mvitals[mndx].mvflags & G_EXTINCT)) {
if (wizard) {
debugpline1("Automatically extinguished %s.",
@@ -1391,7 +1391,7 @@ int mmflags;
} else {
/* no initial inventory is allowed */
if (mtmp->minvent)
discard_minvent(mtmp);
discard_minvent(mtmp, TRUE);
mtmp->minvent = (struct obj *) 0; /* caller expects this */
}
if (ptr->mflags3 && !(mmflags & MM_NOWAIT)) {
@@ -1412,6 +1412,34 @@ int mmflags;
return mtmp;
}
/* caller rejects makemon()'s result; always returns Null */
struct monst *
unmakemon(mon, mmflags)
struct monst *mon;
int mmflags;
{
boolean countbirth = ((mmflags & MM_NOCOUNTBIRTH) == 0);
int mndx = monsndx(mon->data);
/* if count has reached the limit of 255, we don't know whether
that just happened when creating this monster or the threshold
had already been reached and further incrments were suppressed;
assume the latter */
if (countbirth && g.mvitals[mndx].born > 0 && g.mvitals[mndx].born < 255)
g.mvitals[mndx].born -= 1;
if ((mon->data->geno & G_UNIQ) != 0)
g.mvitals[mndx].mvflags &= ~G_EXTINCT;
mon->mhp = 0; /* let discard_minvent() know that mon isn't being kept */
/* uncreate any artifact that the monster was provided with; unlike
mongone(), this doesn't protect special items like the Amulet
by dropping them so caller should handle them when applicable */
discard_minvent(mon, TRUE);
mongone(mon);
return (struct monst *) 0;
}
int
mbirth_limit(mndx)
int mndx;