Not sure how long this has existed without triggering any issues, but
when I was testing out a themed room wider than it was tall, I ran into
rn2-of-a-negative-number impossibles. Traced it to here, where it was
trying to subtract the width of the mapfrag from ROWNO to figure out
which y-value it should place the map on. The correct behavior is to
subtract the height of the mapfrag.
It is possible to create a bidirectional teleportation trap by making a
pair of teleportation traps with a fixed destination of each other's
coordinate. Moving or hurtling onto such a trap correctly materializes
the hero on top of the other trap without triggering it, but for some
reason I didn't dig into, sitting down to trigger the first trap does
also trigger the second one at the destination end, causing you to
counterintuitively teleport twice and end up back where you started.
Fix this by stopping tele_trap() from doing anything if it's called
recursively, using a static variable like spoteffects() does for the same
purpose. I had to adjust a bit of other tele_trap code to remove its
sole early return.
If a player initially goes petless then later obtains a pet, it's absent
from the game chronicle. Fix that by adding a livelog for it.
This required a bit of restructuring in create_familiar() that I wanted
to do anyway: removing the kludge of decrementing u.uconduct.pets when a
figurine has been deployed but isn't actually going to come out tame.
Calling initedog() /after/ deciding whether it's needed or not prevents
a first-pet livelog being produced for a figurine that didn't come out
tame.
The guardian angel code, which avoids calling initedog(), can never be
the hero's first pet anyway because it only appears tame when the hero
has already broken petless conduct. But while checking, I noticed a
duplicate comment, so I removed that.
I was working on another patch involving a message that could be printed
for either a monster or the player (using a struct monst * variable that
either holds the monster or &gy.youmonst), but wasn't able to easily use
pline_mon for the message since the mx and my of youmonst aren't kept
updated as the hero moves. (In my testing, they were always 0, but it's
not clear if they will remain 0 throughout the game, or if that's a bad
assumption to make.)
Allow this in the future by checking for youmonst in pline_mon and
setting the coordinates to 0,0 explicitly so no relative coordinate
message gets printed when it's about the hero.
I'm not sure if it's a reasonable assumption that no messages that could
ever be passed to pline_mon for a player would ever need to note
"(here)" when accessiblemsg is turned on. If that's the case, the
correct thing would be to set the coordinates to u.ux, u.uy instead of
0,0.
Most recent version of XQuartz, same as before. Unfortunately,
newer version of macOS => newer version of Xcode and its command
line tools => newer version of clang => emulating newer version of
gcc which defaults to a more recent version of StdC, I suppose, or
perhaps our hints are specifying that. Whichever, it has resulted
in a bunch of complaints about XtOffset() used in win/X11/winX.c:
|warning: performing pointer subtraction with a null pointer has\
undefined behavior [-Wnull-pointer-subtraction]
Adding -wno-null-pointer-subtraction to X11FLAGS silences them,
but that would require figuring out which versions of gcc and
clang added -Wnull-pointer-subtraction and its negation. Revising
XtOffset() to include the ptrdiff_t casts eliminates the warnings,
avoiding the need for version conditionals to deal with X11FLAGS.
Bug description of #1386 by @copperwater on GitHub:
"When generating a random monster from a class using des.monster(),
the G_NOGEN in their statblock is suppressed, but because every monster
of this class has frequency 0, none of them are actually eligible to get
picked. mkclass ends up returning a null pointer and create_monster has
to pick a random monster instead.
This affects the following levels (all the ones that use random sea monsters):
Healer quest start
Healer quest locate
Plane of Water (difficult to notice, since it has lots of specific sea monsters and only 5 random ones)
This can be pretty easily viewed by going to the Healer quest start and
detecting monsters: there is a shark and a giant eel, which are
specifically defined, but the remaining random sea monster that should
be there is absent."
Add a tracking array mclass_maxf[MAXMCLASSES] (about 61 entries, the
first not being used), and fill it one time in init_mongen_order() with
the maximum frequency value seen of any monster in that class.
Any mclass_maxf[] entry of zero represents that entire class of monsters
having no positive frequency value.
Detect that in mkclass_aligned(), and use it to work around the situation
to produce the monster being sought by the Lua level description file.
Reported by k21971: applying an axe toward a location that contained
both a tree and a boulder (or statue) would use the axe to break the
boulder/statue rather than chop down the tree.
Different code is used to finish the dig/chop than is used to decide
whether the tool is appropriate for its target.
Fixes#1383
Issue reported by Umbire: if a mind flayer got turned to stone by
hitting a hero who is polymorphed into a cockatrice and the first
tentacle drain missed but a subsequent one hit, any remaining ones
would keep being applied even though the mind flayer was dead.
This works but doesn't feel right to me. A more substantial change
to mhitm_ad_drin() didn't work as expected so I've settled for this.
Fixes#1378
Issue reported by elunna: nethack has become confused about
resistances held by poly'd hero.
resists_xxxx() got changed to check worn and carried equipment
so was no longer accurate for use when changes shape.
Fixes#1382
When hunting for player's run-time config file under MacOS/OSX,
nethack looks for .nethackrc (or $HOME/.nethackrc), then if not
found it looks for
"$HOME/Library/Preferences/NetHack Defaults", and finally for
"$HOME/Library/Preferences/NetHack Defaults.txt".
When none of those exists, the last choice has been being left in
configfile[] and can get used in messages.
The menu for entering the tutorial includes a tip about setting
OPTIONS=!tutorial in the config file, but it was showing the third
choice rather than the first when none of them are found. Change
config file name setup to remember the first name rather than the
last when it represents a non-existant/not-yet-existent file, so
that the tip recommnends the standard Unix name rather than the
Mac-specific one.
Instead of packing a coordinate into unsigned long, store the goal in
a coord struct, making the code a bit cleaner. Monster struct is
of course slightly bigger, but that should not really matter.
No change in monster behaviour.
Breaks saves and bones.
The array was ending up ordered the same on different qsort
implementations.
This incorporates the mlet value into the sort value for comparison.
That guarantees that everything stays ordered by mlet, followed by
difficulty (and would even if something ever got misplaced in
monsters.h). It means the "they are equal" zero return for differing
mlet values is not required, and has been removed.
This removes the "they are equal" zero returns for G_NOGEN | G_UNIQ
monsters, so they will still get sorted rather than left at the
whatever array element they happened to be at (which I don't think
should be an issue?).
An assumption of monster generating code is that monsters within a class
appear in increasing order of difficulty. This wasn't the case with
some monsters, but swapping the monsters around is rather intrusive,
and doesn't really lend to changing monster difficulties when needed.
As a result, for example ghouls would not randomly generate when they
should have at certain level difficulties (where a ghoul is weak enough
to generate but an ettin zombie would be too strong).
Keep a separate array of monster indexes sorted correctly, generate it
when required by mkclass()
Description of this bug via copperwater <aosdict@gmail.com>
Noticed while testing an earlier fix - after your pet consumes a large mimic
corpse don't have it remain leashed once it begins to mimic something
that isn't leashable
Tutorial code doesn't handle saving and reloading the game gracefully,
and manually saving has been disabled in there already.
Also disable automatic saving in the tutorial when the terminal goes away.
Main problem was there was no condition applied to this message, so
anyone would hear it even if they were deaf. Even assuming a cry of pain
is something that could be seen, the message was still printed when the
hero couldn't see the gremlin.
This puts both a deafness check and a range check on that cry (if a
gremlin somehow takes light damage on the other side of the map behind
many walls, it doesn't make much sense to hear its cry), and provides an
alternate message if the hero can't hear it, but can see it. The
alternate message does rely on the hero being able to /see/, not just
spot, the gremlin and the light it's shying away from -- if you can only
sense it, there is no special message.
This implements a TODO to return an object's material as text rather
than as an int when a Lua file requests all the details about an
object's objclass. That is as simple as looking it up in materialnm[].
With that done, it's possible to clean up the one use where a Lua file
looks up the material of an object it generated, in the
"water-surrounded vault" themed room, previously an inflexible 19 but
which can now be compared directly to "glass". It also enables
shortening the comments that follow since the branches of the if
statement are now obvious.
Report the effect of suit and/or robe on spell casting during
attribute enlightenment.
Doesn't attempt to include other armor slots. That's complicated
and would end up being too verbose.
Some variants were already using a similar approach
using a struct called 'ebones', so adopt the same naming
so NetHack-3.7, hardfought, and some variants are using
the same name.
As before there are fields in the struct that are not
currently used by NetHack-3.7, but the intent is that
hardfought save and bones files can be loaded by
NetHack-3.7 without code modification, for debugging
bug reports.
This invalidates existing save and bones files.