Implement the suggestion that since teleporting away from the vault
while being confronted by the guard results in a shrill whistling
sound, the vault guard ought to have a tin whistle in his inventory.
I also added a check that he does have the whistle and to give an
alternate message if not, but after half a dozen tries to have a
squad of beefed up monkeys steal the whistle, they never accomplished
that. At least three times they took everything except the whistle
but I never succeeded in verifying the alternate message.
This issue has been around for a while but wasn't noticable to players
until some post-3.6.0 tweaking of end of game disclosure. When testing
the DUMPLOG artifact_score fix, I level teleported to the Astral Plane
and performed a cheat ascension. Final disclosure listed high priests
as extinct. Same thing would happen after visiting Moloch's Sanctum
instead. (The latter didn't interfere with creating the Astral high
priests if you got that far, just as creation of the first one there
didn't prevent the other two.)
I forget why high priests are flagged as unique (something I think
I'm responisble for...), but they shouldn't share unique's setting of
extinct during monster creation. (They could be set that way after 4
are created, but this fix doesn't do that. It just treats them like
ordinary monsters so you'd need 127 or 255 or some such to make them
become extinct. Unlike other creatures with a special creation limit,
high priests can be produced when aligned priests gain experience--an
event that I don't recall ever noticing happen.)
When a female dwarf grows (via level gain) into a dwarf lord, it
changes sex as well as base monster form because all dwarf lords
are male. The earlier fix for #H4276 (16-Mar-2016, to give an
alternate grow-up message acknowledging the change) used the wrong
monster form (monst's old one instead of new one).
A few things which might conceivably pass negative values to ctype
routines. Some are post-3.6.0. None of them explain the sporadic
Windows assertion failure.
Using tolower() without verifying the argument isupper() should be
completely safe when tolower() is a function but might not be when
it's a macro. (Likewise for toupper() without islower().) NetHack's
lowc() function is always safe, at least for ASCII.
I've hunted for other instances where monster hit points were set
to zero or less without calling the routine that kills off the
monster (see recent mon_unslime() vs zhitm()) and didn't find any
for mhp subtraction. I haven't checked for direct assignment yet.
For a while I thought I'd found several cases where a monster was
intended to be killed but got left with positive hit points, but
it turned out that lifesaved_monster(), of all places, was setting
them to zero. I've moved that to its callers so that it isn't so
well hidden. And changed several ''if ((mon->mhp -= dmg) <= 0)''
into separate subtraction and 'if' just so the mhp manipulation is
a bit more visible.
I think the only actual change here is the message for monster
being killed by lava, where glass golems now melt instead of burn.
Make the handling of unique monsters consistent between vanquished
monsters and genocided/extinct monsters. No visible difference to
players.
This also prevents Nazgul and erinys from being polymorphed into
some other form to reduce the chance that their kill count fails
to match the expected number when they're reported to be extinct.
[My long test game (with 3451 total dead critters as of the last
save file) used for exercising the sorting of vanquished monsters
included
120 soldiers
111 wolves
9 Nazgul
2 erinyes
and the genocided/extinct list had none genocided, those four
extinct. No doubt the missing third erinys was alive somewhere
rather than counted as something else after getting polymorphed,
so this band-aid wouldn't have helped this particular game.]
Make 'zeromonst' global instead of local to makemon.c. Its address
isn't used as a special value like &zeroobj, but it is useful to
have available for initializing various pseudo-monsters.
modified:
include/decl.h
src/decl.c, makemon.c, mkobj.c, mplayer.c, teleport.c
Most of the humanoid species have Lords and several have Kings,
but none of them have Ladies or Queens. When a female grows up
to reach that level of monster, she changes into male. This fix
gives an alternate message acknowledging that change rather than
prevent taking on the stronger form. A better fix would be to
add ogre ladies and dwarf queens as separate monsters, but doing
so will break 3.6.0 save file compatibility.
(I started out with an alternate fix, adding mons[].fname for the
dozen or so creatures which warrant an alternate name for females.
But that requires statues, figurines, corpses, tins, and maybe
even eggs to track gender [some statues already do, and corpses
and statues with attached mtraits also implicitly do] and to not
stack with equivalent ones of the opposite gender. Plus glyphs
to track them, and new tiles. It was becoming too complicated
for such a relatively unimportant feature. Separate monsters is
the way to go, deferred until save file format changes again.)
Suppress a couple of 'dead increment' diagnostics from the clang static
analyzer. The assignments are dead, but keeping the variable up to date
is more valuable (in case someone someday changes the code to use the
affected variable somewhere farther along in that function) than changing
the code to avoid the assignments in order to prevent the diagnostic.
This will only work to suppress the analyzer's diagnostic messages if
either FORCE_ARG_USAGE or GCC_WARN is defined when compiling makemon.c.
With DEBUG suppressed, I started getting
16 warning: empty body in an if-statement
and 2 warning: empty body in an else-statement
from gcc.
Using braces for an empty block instead of just ';' avoids the warning:
if (foo)
debugpline("foo");
is bad,
if (bar) {
debugpline("bar");
}
is good. ;-)
The changes to lint.h are just precautionary.
modified:
include/lint.h
src/attrib.c, bones.c, dbridge.c, dig.c, eat.c,
makemon.c, mkmaze.c, mon.c, sp_lev.c
Fixing up mis-indented block comments, but hit some files that hadn't
had the earlier mixture of tab replacement, etc, so it's bigger than I
expected. If I get to it, they'll be another round of this tomorrow.
Somewhere along the line I started removing redundant parentheses from
return statements, but only in files that needed continuation fixups
so it's not comprehensive.
This time try random locations up to 50 times, then start going
through the map in order to find a good position. First round
tries to pick a location not in sight, if that fails, it might
try stair or ladder location. If that fails, then it will pick
any good position, whether in sight or not.
Outside field of vision restriction and trying stair or ladder
locations does not happen when the monster is placed from special
level code.
mtmp->cham was NON_PM, which select_newcham_form interpreted as a completely
random form. This also resulted Vlad getting a random shape, and not getting
the Candelabrum, making the game unwinnable.
Limit vampire shapeshifting on rogue level to vampire bats (only
choice represented by uppercase letter) and have other shapeshifting
try for uppercase. The latter isn't rigorous because shapeshifters
(chameleon=':', doppelganger='@', sandestin='&') aren't uppercase
themselves, so won't be created there under ordinary circumstances.
It applies to the "summon nasties" monster spell and post-invocation/
post-Wizard's-death harassment effect too.
Gnomes in mines during level generation have 1/20 chance of getting a candle
(should give approximately 4 candles in all of the mines total), and every
randomly generated gnome has 1/60 chance.
The code that intended to have mimics occasionally take on the form
of "strange object" always produced downstairs instead because
S_MIMIC_DEF is greater than MAXOCLASSES.
This problem was present in 3.4.3. I didn't try to go back to see
how long it's been there, but strange objects used to occur once
upon a time. Either nobody noticed that they'd gone away or there's
an alternate way to produce them.
I'll push a formatting guide at some point. There may still be
outstanding changes, but please feel free to resolve those as you arrive
a them.
To the best of my knowledge, there is no changes to the actual code
content, but the formatter does have the occasional bug. If you run into
an issue, please fix it!
Bag of tricks that had been used at least once was being described
as "empty" regardless of charge count, because it always fails the
Has_contents() test. After half this patch fixed that, it started
being flagged as "empty" as soon as the last charge was used rather
than after attempting to use it again after that, since 'cknown' was
being set whenever it was used. Only set that flag when applying
the bag has been observed to fail.
* Replace variadic debugpline() with fixed argument debugpline0(str),
debugpline1(fmt,arg), and so on so that C99 support isn't required;
* showdebug() becomes a function rather than a macro and handles a
bit more;
* two debugpline() calls in light.c have been changed to impossible();
* DEBUGFILES macro (in sys.c) can substitute for SYSCF's DEBUGFILES
setting in !SYSCF configuration (I hope that's temporary).
Move debugging output into couple preprocessor defines, which
are no-op without DEBUG. To show debugging output from a
certain source files, use sysconf:
DEBUGFILES=dungeon.c questpgr.c
Also fix couple debug lines which did not compile.
This also includes fixes due to Derek Ray to depugpline to work better
on other platforms.
There is a lot of code affected by this, and Pat Rankin correctly
observes that it would be better to store roguelike as a level flag
rather than just using Is_rogue_level. A note for the future.
Fix some expressions that were supposed to use bitwise '&' but were
accidentally using logical '&&', pointed out by Keni's lint tool. All 3
instances are in post-3.4.3 code, so don't affect the branch and don't
need a fixes entry.
Back on Feb 28, I committed a patch to prevent the special level
loader from generating mail daemons for levels which specified random
demons. It had a pair of copy+paste mistakes that could result in
mkclass() looping forever. It was looking at the same monster every
time and if that monster was one which mustn't be generated, it would
just keep repeating.
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.
Add questpgr formatting codes to support pronouns for leader,
nemesis, deity, and artifact.
%lh -> "he" or "she" for leader; %nh for nemesis; %dh for hero's god;
%li -> "him" or "her"; likewise %ni, %di;
%lj -> "his" or "her"; and %nj, %dj;
H, I, and J modifiers yield capitalized form of same.
%oh -> "it" or "they" for artifact (Eyes of the Overworld is plural);
%oi -> "it" or "them";
%oj -> "its" or "their"; plus capitalization with uppercase modifiers.
Also, %O yields shortened artifact name ("the Foo" in place of "the Foo
of Bar"). These provide support for terser summary lines, but can also
be used in the regular quest text passages.
A couple of nemeses don't specify gender. The random choices need
to be made early so that the leaders' messages can get them right. This
chooses during role initialization and then uses that result once the
corresponding monster is eventually created. It does the same for leader
even though no current leader needs it, and for deity too.