Commit Graph

15304 Commits

Author SHA1 Message Date
PatR
b19062d2c4 mondata.c formatting 2023-05-27 02:44:49 -07:00
PatR
2abe156516 potion of gain level tweak
Eliminate a use of non-literal format string and consequent need to
manipulate compiler warning settings.  Should be no change in behavior.
2023-05-26 14:03:48 -07:00
PatR
aa63aa8d98 issue #1027 - sticky 'nofollowers' flag
Reported by copperwater:  entering the tutorial sets 'u.nofollowers',
changing to the tutorial level saves a copy of 'u', post-level change
from entering the tutorial level resets u.followers, but subsequently
changing levels to return to the original level 1 restores 'u' from
the saved copy with has 'u.nofollowers==True', overriding the reset.

Move the nofollowers flag from 'u' to 'iflags'.  Invalides save and
bones files.

Fixes #1027
2023-05-25 17:08:53 -07:00
PatR
202afc3b55 choosing whether to run the tutorial
Revise the menu that asks whether to run the tutorial so that it will
accept ESC for "no".

Also, in its hint about how to suppress the menu, change vague "the
config file" to the actual configuration file name.  (This might need
a new 'sysconf' directive to control what's shown on servers where
the player doesn't have access to the file system, but the vague
description wasn't adequate for single player systems.)
2023-05-25 15:43:37 -07:00
PatR
cf8a49cae6 use to "feature" in DEBUGFILES
The code to lookup a value in DEBUGFILES usually operates on a file
name, but there are few non-file uses.  The latter wouldn't work on
VMS because of the way it was manipulating the name:  first stripping
away path, suffix, and version, then adding hardcoded ".c" suffix on.

I thought we already had a routine to get the base part of a name
from a full path, but if so, I haven't been able to find it.  This
adds new nh_basename() to do that, with the option of either keeping
or discarding the suffix or type portion.

The VMS usage that prompted this hasn't actually been tested.
2023-05-25 15:35:49 -07:00
nhmall
2876b6e8fd vmsbuild.com update 2023-05-24 19:46:33 -04:00
PatR
5dc8e98efa a couple of miscellaneous formatting bits 2023-05-24 11:23:15 -07:00
PatR
42356daec0 pull request #1024 - keep hero movement points
Pull request from saltwaterterrapin:  record current move's pending
movement points in save file.  They were being thrown away during
save and hero given 12 at time of restore.  Hero had to have had at
least 12 in order for player to issue the S command, but might have
had more than that if able to move faster than normal speed.

This implements it differently from the suggested commit.  Add new
field umovement to 'struct u' instead of using youmonst.movement and
needing to save and restore that separately.

Invalidates existing save and bones files.

Closes #1024
2023-05-24 11:16:23 -07:00
PatR
6586cc84b2 trap setting bit
Treat a trap object that has become the focus of trap setting
occupation as if it had already been used up.  (No discernable change
in behavior unless someone adds an artifact bear trap or landmine
that talks.)

Shouldn't 'trapinfo' be part of 'context' and be saved and restored?
(If so, it will need to include o_id and undergo pointer fixup during
restore.)  When trap arming is in progress hero will be too busy for
player to issue S(ave) command but a hangup save could take place.
2023-05-23 15:34:58 -07:00
PatR
8385d0a10e fixes entry for PR #1037 - use-after-free
when applying an object.

Pull request form copperwater:  applying a cream pie always uses it up
and applying a lump of royal jelly sometimes uses it up, then after
that use the apply got checked for a talking artifact.  If it had been
used up when the apply routine would access memory which had already
been freed.

Closes #1037
2023-05-23 15:03:03 -07:00
copperwater
d813f534ad Fix: use-after-free when applying an object that got destroyed
Found this running the fuzzer with address sanitizer. After applying an
object, the game checks whether it's a talking artifact so that it can
speak to you afterwards.

If, however, the object got destroyed in the process of applying it,
this will read and dereference obj after they have been freed. I found
this with a cream pie, which is always destroyed when someone applies
it.

To fix this, I tracked the obj pointer for what I think are the only two
cases in the big switch statement that don't track this - royal jelly
and cream pie. Royal jelly is only conditionally destroyed depending on
further input, so its function had to be refactored to take a struct
obj**, but cream pies are unconditionally destroyed so it can just be
set to null.
2023-05-23 15:03:02 -07:00
nhmall
65a0ff2d9a update OpenVMS com files (VSI C, NetHack-3.7) 2023-05-23 17:50:24 -04:00
Pasi Kallinen
39530f9228 Fix the mind flayer attacking without knowing your location
This was caused by the mind flayer mind blasting polymorphed hero,
causing them to revert back to human form, and dropping into a pool,
doing an automatic teleport to save them from drowning.
After that the mind flayer tried to hit them in melee, but the hero
was far away.

Recalculate the nearby and inrage variables after mind blast.
2023-05-23 19:24:19 +03:00
nhmall
4761bf190e OpenVMS update follow-up 2023-05-22 20:50:35 -04:00
nhmall
788ade31ca Revert "newest VSI C compiler uses different predefined macro"
This reverts commit 2dfe4c2a27.
2023-05-22 19:47:28 -04:00
PatR
ae0b306f9d sanity_check suppression
Handle ^P vs 'sanity_check' differently, and treat ^R similarly.
2023-05-22 14:43:01 -07:00
nhmall
08335c1e19 avoid a c++ issue in vmsconf.h 2023-05-22 15:31:18 -04:00
nhmall
ff727e916f work around a build issue with a compiler
One compiler was issuing an error diagnostic for cmap_to_glyph() macro (see below).
This just works around that by using cmap_a_to_glyph() which does not suffer the same fate.

mkmaze.c

    static const struct rm water_pos = { cmap_to_glyph(S_water), WATER, 0, 0,
.........................................^
%CC-E-NEEDCONSTEXPR, In the initializer for water_pos.glyph, "In_mines(...)" is not constant, but occurs in a context that requires a constant expression.
at line number 1448 in file mkmaze.c

    static const struct rm water_pos = { cmap_to_glyph(S_water), WATER, 0, 0,
.........................................^
%CC-E-NEEDCONSTEXPR, In the initializer for water_pos.glyph, "In_hell(...)" is not constant, but occurs in a context that requires a constant expression.
at line number 1448 in file mkmaze.c

    static const struct rm water_pos = { cmap_to_glyph(S_water), WATER, 0, 0,
.........................................^
%CC-E-NEEDCONSTEXPR, In the initializer for water_pos.glyph, "gd" is not constant, but occurs in a context that requires a constant expression.
at line number 1448 in file mkmaze.c

    static const struct rm water_pos = { cmap_to_glyph(S_water), WATER, 0, 0,
.........................................^
%CC-E-NEEDCONSTEXPR, In the initializer for water_pos.glyph, "on_level(...)" is not constant, but occurs in a context that requires a constant expression.
at line number 1448 in file mkmaze.c

    static const struct rm water_pos = { cmap_to_glyph(S_water), WATER, 0, 0,
.........................................^
%CC-E-NEEDCONSTEXPR, In the initializer for water_pos.glyph, "(&u.uz)->dnum" is not constant, but occurs in a context that requires a constant expression.
at line number 1448 in file mkmaze.c

    static const struct rm water_pos = { cmap_to_glyph(S_water), WATER, 0, 0,
.........................................^
%CC-E-NEEDCONSTEXPR, In the initializer for water_pos.glyph, "gd.dungeon_topology.d_sokoban_dnum" is not constant, but occurs in a context that requires a const
ant expression.
at line number 1448 in file mkmaze.c

    static const struct rm air_pos = { cmap_to_glyph(S_cloud), AIR, 0, 0, 0,
.......................................^
%CC-E-NEEDCONSTEXPR, In the initializer for air_pos.glyph, "In_mines(...)" is not constant, but occurs in a context that requires a constant expression.
at line number 1450 in file mkmaze.c

    static const struct rm air_pos = { cmap_to_glyph(S_cloud), AIR, 0, 0, 0,
.......................................^
%CC-E-NEEDCONSTEXPR, In the initializer for air_pos.glyph, "In_hell(...)" is not constant, but occurs in a context that requires a constant expression.
at line number 1450 in file mkmaze.c

    static const struct rm air_pos = { cmap_to_glyph(S_cloud), AIR, 0, 0, 0,
.......................................^
%CC-E-NEEDCONSTEXPR, In the initializer for air_pos.glyph, "gd" is not constant, but occurs in a context that requires a constant expression.
at line number 1450 in file mkmaze.c

    static const struct rm air_pos = { cmap_to_glyph(S_cloud), AIR, 0, 0, 0,
.......................................^
%CC-E-NEEDCONSTEXPR, In the initializer for air_pos.glyph, "on_level(...)" is not constant, but occurs in a context that requires a constant expression.
at line number 1450 in file mkmaze.c

    static const struct rm air_pos = { cmap_to_glyph(S_cloud), AIR, 0, 0, 0,
.......................................^
%CC-E-NEEDCONSTEXPR, In the initializer for air_pos.glyph, "(&u.uz)->dnum" is no
t constant, but occurs in a context that requires a constant expression.
at line number 1450 in file mkmaze.c

    static const struct rm air_pos = { cmap_to_glyph(S_cloud), AIR, 0, 0, 0,
.......................................^
%CC-E-NEEDCONSTEXPR, In the initializer for air_pos.glyph, "gd.dungeon_topology.
d_sokoban_dnum" is not constant, but occurs in a context that requires a constant expression.
at line number 1450 in file mkmaze.c
2023-05-22 14:58:29 -04:00
nhmall
68b8e84aa3 changes to build with VSI C compiler
The changes from past OpenVMS compilers are #ifdef'd VMS9
2023-05-22 14:43:10 -04:00
nhmall
2dfe4c2a27 newest VSI C compiler uses different predefined macro
recognize __vms predefined compiler macro and ensure that VMS
is also defined because that is what NetHack source files
currently expect.
2023-05-22 14:25:08 -04:00
nhmall
13a5d978f9 remove a non-UNIX problematic define in termcap.c 2023-05-22 14:13:22 -04:00
nhmall
aab3bd695e don't do the #includes when cstd.h is used on c++ 2023-05-22 13:41:47 -04:00
PatR
1f8b3dfef5 ^P vs sanity_check
Normally when sanity_check is enabled it will take place for every
command executed.  Avoid that when the command is ^P because if a
sanity warning is a recurring one and the msg_window setting is
single or combination (tty-only) which shows one message, ^P will
just repeat each new warning without having any chance to cycle back
to earlier messages.
2023-05-22 00:32:25 -07:00
PatR
4e46a7de69 change enexto() to use collect_coords()
Greatly simplify enexto().  The new code might does more work up front
but less overall when/if a nearby spot is hard to find.
2023-05-21 17:30:06 -07:00
PatR
92a993a0b6 fix github issue #1029 - erroneous death feedback
for monsters that haven't died, when being removed from play to keep
them out of bones.

Reported by copperwater:  if the quest nemesis was present on a level
being saved as bones, it was removed from the map to keep it out of
the bones level but the quest feedback for nemesis death was given
in the process.  Would happen for blessed genocide of "*" too.  (It
didn't happen for #wizmakemap and I'm not sure why.)

This was an unintended side-effect of moving some common stuff from
mondead() and mongone() into m_detach().  The quest feedback isn't
actually common to both.  Instead of moving that back, pass a flag
that m_detach() can use to determine which routine called it.

Fixes #1029
2023-05-20 16:44:18 -07:00
PatR
9052bd5099 fix #K3925 - u.ustuck of long worm tail
Don't allow stick/wrap/engulf attacks directed at long worm tails
to succeed.  Achieved by making sure that 'notonhead' is up do date
in a bunch of places and utilizing the fairly recent can't-{stick,wrap,
engulf}-unsolid-monsters code.

Should prevent a 'sanity_check' warning about being too far from
u.ustuck that would happen when holding the tail while the head was
not adjacent to the hero.

Also don't let pet ranged attacks from choosing a long worm's tail
as target.  They'll still be able to target long worms provided that
the head is lined up and not shielded by tail segment(s).
2023-05-20 15:34:32 -07:00
PatR
f176318c45 covetous fixe(es)
Extracted from a larger pending commit.  While trying to make sure
that bhitpos and notonhead are up to date when attacks are processed,
I noticed that covetous monster handling was buggy.  For dist2(),
a value of 1 means adjacent in an orthogonal direction, so testing
for less than 2 unintentionally excluded diagonal adjacency.
2023-05-20 15:26:36 -07:00
PatR
f8e4c3e078 give fuzzer some protection against brainlessness
With the LifeSaved property (via amulet), hero being killed by
brainlessness gets killed twice.  But for explore|wizard mode where
the answer to "Die?" might be "no" and for the fuzzer where it's
always "no", a mind flayer's 3 drain-Int attacks or master flayer's
5 drain-Int attacks will usually kill the hero all over again (and
again, ...).  Skip remaining ones, like happens when one of them
hits and discovers that the target has no head or is mindless, for
the rest of the flayer's current move.

Monsters wearing life-saving don't get killed twice.  That doesn't
seem very fair, but this hasn't touched that.
2023-05-20 01:58:30 -07:00
nhmall
0d116ac193 update tested OS in hints/macOS.370 2023-05-19 2023-05-19 09:48:41 -04:00
nhmall
476f962f67 update tested versions of Visual Studio 2023-05-18 2023-05-18 22:31:45 -04:00
PatR
925ebf6ea1 fix #K3924 - teleport as giant eel
The safe_teleds() change that restored picking random destination
attempts prior to making an exhaustive search contained a typo tjat
accidentally only accepted invalid positions instead of valid ones.
So unless it randomly picked 40 good spots, erroneously rejecting
all of them and then falling back to the try-everywhere situation
(which has its own testing without any typo), it would yield strange
results by placing the hero in walls or solid rock via choosing the
first inappropriate spot it tried.

Not part of that bug but related, sort of:  for rloc(), use
rloc_pos_ok() instead of goodpos() during the exhaustive search as
well as during the random tries, but hang on to the first (after
randomization) position that passes goodpos() for a last resort.

The collect_coords() flag for 'skip-inaccessible' intended to be a
quick way to filter out walls and solid rock was using !ACCESSIBLE()
which also rejects water and lava locations.  So such spots wouldn't
be picked by either safe_teleds() or rloc() when they were finding
a spot for aquatic or lava-tolerant forms.  Instead of duplicating
a bunch of code to decide whether the hero's current form or the
teleporting monster should avoid !ACCESSIBLE() for a reason other
than having Passes_walls, make collect_coords(CC_SKIP_INACCS) use
!ZAP_POS() which rejects walls and rock but allows pools.
2023-05-17 18:51:28 -07:00
nhmall
75e8e06dee commit 02a48aa8 split of g fixup 2023-05-17 21:17:35 -04:00
PatR
49e93760a8 collect_coords() revisited
Make recently added collect_coords() global even though it is still
only being used in teleport.c.

Add CC_SKIP_INACCS flag to only collect accessible locations so that
there's no need for a custom filter callback or of collecting spots
that will always be rejected when put to use.  Caller needs to check
Passes_walls/passes_walls() to decide whether that is suitable.

Merge some of the old safe_teleds() with the new, making it try
randomly 40 times before collecting coordinates for an exhaustive
selection.  Prior to the recent change which added collect_coords()
it was trying 400 times and giving up if that didn't find a good spot.

Start using collect_coords() for rloc() as well as for safe_teleds().
Only try to pick a spot randomly 50 times now instead of 1000.  If
those all fail, it does an exhaustive search of a randomized list of
candidates instead of old left-to-right, top-to-bottom map traversal.
Has not had nearly as much testing as safe_teleds() underwent.

rloc() was explicilty ignoring map column 1 for some reason.  Unlike
reserved column 0, column 1 is part of every level and should be
considered for monster teleport destination even though most levels
don't utilize it.
2023-05-17 00:33:54 -07:00
nhmall
d7f581d8ad fix compiler complaint
a check for baselen being less than or equal to zero drew a compiler
complaint because the variable is unsigned
2023-05-15 23:14:26 -04:00
nhmall
420048b8d3 keep external identifiers under length of 31 char 2023-05-15 23:11:34 -04:00
PatR
59677e7440 rewrite safe_teleds()
The teleport to safety routine would try to find a viable spot 400
times, the first 200 rejecting trap locations and the last 200
accepting such.  While testing various escape from lava variations
recently, I noticed that I could fail to reach safety even when there
was an open spot immediately adjacent to me.  I added a BandAid(tm)
to make another 400 tries if the first attempt failed, but that was
clumsy and still didn't guarantee picking a viable spot.

This adds a new routine, collect_coords(), which will gather a list
of coordinates for the entire map.  safe_teleds() goes through them
one by one until either finding a spot or exhausting the possibilies,
without randomly trying and retrying the same spot multiple times and
without missing other potential spots, also without just scanning the
map from left to right and top to bottom or similar.

Various other things which retry over and over, and especially the
ones which make a bunch of random attempts and then fallback to trying
every spot on the map, could be switched over to this, at least for
the falling back phase.  Right now collect_coords() is local to
teleport.c but that could be easily changed.

The try-at-random method is much quicker when there are lots of
available spots but the gather-shuffled-candidates method is
guaranteed to succeed if success is possible.  The way safe_teleds()
is presently using it collects the list with all locations within
2 steps first, then those within 3 to 4, then 5 to 6, and so on out,
randomized within each block of ranges.  So the destination will be
within one step of being as close to the starting spot as possible
but not always immediately adjacent when that happens to be available.
2023-05-15 01:42:13 -07:00
PatR
2646688e2d back_on_ground()
Replace a couple of hardcoded "back on solid ground" messages with
something more versatile.

Also, make life-saving handling for failed rescue from drowning
similar to that of failed rescue immolation by lava.  If there are
any cases where more than two tries is needed, they elude me.  The
new code doesn't confer temporary water walking if emergency teleport
fails; perhaps it should.
2023-05-15 01:08:04 -07:00
nhmall
b4f3a0fac2 submodule update 2023-05-14 07:49:19 -04:00
PatR
910868cba8 revise m_at()
Get rid of some unnecessary code when ignoring unimplemented buried
monsters.  A smart compiler probably optimizes away the useless bits
even when not explicitly optimizing but a dumb one isn't likely to.

m_at(x,y) was
|  (levl.monsters[x][y] != 0
|   && (levl.monsters[x][y] ? levl.monsters[x][y] : 0))
when
|  levl.monsters[x][y]
accomplishes the same thing.
2023-05-14 03:03:04 -07:00
PatR
1851c7ca88 update Medusa's data.base entry
The second paragraph about Medusa is an excerpt from Bulfinch's
Mythology, but first paragraph is not.  Insert an empty attribution
line between them.  Also, remove the reference to Graeae from the
introduction since it contradicts Bulfinch, which describes them as
"three sisters who were gray-haired from their birth" and Gorgons as
"monstrous females with huge teeth, brazen claws, and snaky hair".
2023-05-13 11:23:49 -07:00
nhmall
ec9d3cb88e keep external identifiers under 31 characters length 2023-05-13 13:49:57 -04:00
Pasi Kallinen
a54b6ba75c Split object init out of mksobj
Move the random erosions in there, as those should only be done if
the object is getting a random initialization.
2023-05-13 12:12:36 +03:00
nhmall
7ef93ba86a Revert "In file included from ../win/X11/winX.c:42:"
This reverts commit e70310c67b.
2023-05-12 17:47:40 -04:00
Pasi Kallinen
f4f74b2e07 Purple worm burp wakes up monsters 2023-05-12 09:17:09 +03:00
nhmall
68e76e0d88 Revert "add stddef.h include to cstd.h"
This reverts commit 55791c5668.
2023-05-11 23:44:40 -04:00
nhmall
55791c5668 add stddef.h include to cstd.h 2023-05-11 23:32:22 -04:00
nhmall
e70310c67b In file included from ../win/X11/winX.c:42:
In file included from /opt/X11/include/X11/Xos.h:146:
/opt/X11/include/X11/Xarch.h:44:13: fatal error: 'sys/byteorder.h' file not found
            ^~~~~~~~~~~~~~~~~
1 error generated.
make[1]: *** [winX.o] Error 1

Xarch.h has an #ifdef SVR4 block.
2023-05-11 23:26:08 -04:00
PatR
7737fcc97c fix out of date safe_teleds() calls
When safe_teleds() was changed to take an int flags argument instead
of a boolean, some calls weren't updated.
2023-05-11 12:12:12 -07:00
PatR
56f0340f0c fix #K3920 - migrating mimicker sanity
Report says that Wizard of Yendor posing as some other monster
triggers a sanity_check warning if on the migrating_mons list and
hero has Protection_from_shape_changers attribute.  My attmpts to
reproduce that failed, but this updates the mon_sanity checking to
explicitly allow a monster posing as another monster to be on the
migrating monsters list.

This also adds checks for whether a monster on the fmon list has
MON_MIGRATING or MON_LIMBO or MON_DETACH bits set in monst->mstate
and whether a monster on the migrating_mons list has MON_DETACH set
or both MON_MIGRATING and MON_LIMBO clear.  I won't be surprised if
these new checks trigger sanity complaints.
2023-05-11 11:51:57 -07:00
Pasi Kallinen
91257e00c7 Werewolf howling wakes up monsters 2023-05-11 18:48:02 +03:00