Nothing about read_simplemail is incompatible with using const, and the
lack of const required some contortions (copying ADMIN_SERVER_MSG to
another buffer with nonconst() to prevent a compiler warning).
This was the last place nonconst() was used, so I removed it.
This is a large iteration on a previous implementation of making
nh.getmap() parse its coordinates as relative to the last defined map or
room rather than absolute to the entire level. Now, everything in the
nh.* and obj.* functions interprets coords as relative rather than
absolute. (By default; if no map or room has been defined, or if the lua
code is executing after level creation is done, they will interpret the
coordinates as absolute).
The general motivation is basically the same - routines that use
absolute coordinates are difficult to use in level creation routines,
because then the designer has to remember to convert the relative
coordinate to an absolute one (and that was impossible before
nh.abscoord was added, particularly in themed rooms). And once
nh.getmap() takes relative coordinates, it would be very strange to have
all the other functions (setting timers, burying objects, etc) remain
with absolute ones.
In a couple places, code is changed to account for coordinates that are
relative to a *room* (which uses g.coder->croom->[lx,ly] as an offset,
instead of relative to a *map*, which uses [xstart,ystart].
Specifically, selection.iterate did not account for this, and without
this the ice themed room timer was not being started in the proper
place.
All tests are updated to respect the new behavior. Most of the modified
functions are not actually used anywhere in level files; the one
exception is starting a timer in a themed room, and that has been
adjusted.
Documentation updated as well to clarify when various things are tossing
around relative and absolute coordinates, both in comments and in
lua.adoc.
- Add bounds, so that we don't process any locations outside
as those locations are known to be unset
- The bounds are only recalculated if needed
- Replace instances of selection_not where we actually want
a new selection with all locations set
Previously the mouse clicklook mentioned every tile that matched
the character symbol, leading to overload of information and
if playing with tiles, it was mostly useless. Also the most
important bit - the tile info - was last in the text.
Now mouse clicklook only reports the exact tile information
that was clicked on.
My change to allow binding the mouse buttons made getpos
push the mouse commands into a command queue, so when you
were asked for a map location, clicked on it with a mouse,
you'd first get the expected effect, and then (most likely)
immediately traveled there.
Change getpos to clear the commands bound to the mouse buttons,
and restore the binds afterwards.
Instead of hardcoding mouse button actions, allow the user to
bind mouse buttons to extended commands. For example the new
defaults are:
BIND=mouse1:therecmdmenu
BIND=mouse2:clicklook
Currently a bit rudimentary; the defaults should be OK, but
documentation is bit lacking, and in-game binding and option
saving are missing.
Allowed commands to bind are "nothing", "therecmdmenu", "clicklook",
and "mouseaction". Clicklook replaces the "clicklook" boolean option,
and mouseaction does what mouse 1 button used to do - a context sensitive
action.
By temporarily changing the type definition for each of xint16 and
coordxy to int32_t, the compiler was able to find several places where
the type definitions were wrong.
This will fix some complaints from static analysis. Note that the
code it complained about wasn't incorrect and that's likely to be
the case of a lot of its complaints.
If a monster cannot move, for example because it's being
blocked off by boulders or walls, it will try to escape by some
method - such as a wand or scroll of teleportation.
Apply the patch from entrez that makes pet gelatinous cubes who eat
containers engulf rather than digest the contents, like non-tame
g.cubes. Unlike the latter, tame ones will immediately drop the
stuff they just engulfed and might subsequently eat it all anyway.
find_skates was still in use for its one intended case, but objdescr_is
has been around for a few years now and can do just as good a job
without having to hardcode the first and last boots in objects[].
The monster knockback could mess with the monster linked list while
the code was going through it for monster movements. (For example,
a monster knocked back another into a level teleport trap)
Add iter_mons_safe, which first grabs all the monster pointers in
the list into an array, and goes over that array instead of relying
on the "next monster" pointer. This is possible because dead monsters
are not removed from the linked list until after all the monsters
have moved.
Testing is very minimal, and I'm not sure the vault guard check
for migration is correct - it should probably check for more states?
Also the iterator could be improved by not continually allocating
and freeing the monster pointer array.
Reported by copperwater: if an engulfer swallowed a mounted hero,
odd things could happen if the hero dismounted. The steed would be
silently expelled and float-down flooreffects were attempted.
It turns out that if the engulfer is classified as an animal (so
purple worm, lurker above, trapper), the hero got "plucked from
<steed>'s saddle" and was forcibly dismounted prior to completing
the engulf operation, but non-animals (vortices, air elemental,
ocher jelly, Juiblex) swallowed the hero+steed intact. The most
straightforward fix to dismounting-while-engulfed issues is to change
engulfing to always pluck the hero from the saddle even when the
engulfer isn't an animal.
If there's no room on the level to place the former steed, it gets
killed off. I looked at changing that to put the steed into limbo,
waiting to migrate back to the current level if hero leaves and
subsequently returns, but that breaks movemon()'s assumption that
when monsters are in the process of moving, only the currently moving
one can be taken off the fmon list to be placed on migrating_mons.
[The recently added monster knockback code violates that assumption
too when knocking the victim into a level changer trap. It needs to
be fixed in one fashion or another.]
This replaces the old pushq/saveq arrays (which were used to save
the keys pressed by the user for repeating a previous command)
with a new command queue. This means there's no hard-coded limit
to the saved keys, and it can repeat extended commands which are
not bound to any key.
Using #loot while in a pit allows looting containers in that pit.
Using open and specifying the hero's spot when not in a pit allows
looting containers at hero's spot. But using open while in a pit
complained about not being able to reach out of the pit before player
had a chance to give hero's spot at the place of interest, so did not
allow looting any container there.
Get a target spot before rejecting use of 'open' while in a pit.
The alternate prompt might be tty-centric.
The earlier commit just removed monsters from migrating_mons and left
them orphaned. Also it ignored migrating objects.
Actually release the monsters that can no longer arrive at their
migration destinations. Release their inventories too.
Release objects that can no longer arrive at migration destinations.
When the hero enters the planes branch, all the rest of the dungeon
gets discarded since it can no longer be reached. At the time that
that takes place, throw away any migrating monsters waiting to arrive
on any of those levels.
Add a #saveoptions extended command, to allow saving configuration
settings from within the game. This is still highly experimental,
and gives plenty of warnings before asking to overwrite the file.
Lack of option saving is one of the biggest complaints new players
have, so this should help with it. More experienced players with
highly customized config file should not use this feature, as it
completely rewrites the file, removing all comments and non-config
lines.
The only effect of a new moon was to make hearing a cockatrice's
hissing (whichs happens with 1 in 3 chance) always start the turn to
stone sequence instead just having a 1 in 10 chance to do so, but
that was negated by carrying a lizard corpse.
Keep the hiss-always-starts-petficiation part and remove the
carrying-a-lizard-corpse-negates-that part. So the effect of a new
moon no longer gets controlled by the contents of hero's inventory.
Add macros to convert AD_foo, WAN_foo, and SPE_foo to relative values
for passing to BZ_U_foo and BZ_M_foo macros.
Change some return values in monster spellcasting function from
magic numbers to MM_MISS or MM_HIT.
Make buzzmu consider hero resistances - previously the
monster with innate zapping ray (Angels and Asmodeus) would
just keep doing that attack, but they will now just curse if
it saw the hero resist the attack.
When a monster at least two sizes larger hits another one,
there's a chance the smaller defender will be knocked back.
This applies also to hero, attacking when polymorphed to
a large monster, or defending from a large monster.
Most of the monsters that can knock back are giants and dragons.
Idea and some of the code from EvilHack.
viz_array[][] is indexed by coordinates but the data it contains has
nothing to do with them so it shouldn't have been changed to coordxy.
'char' was sufficient; 'uchar' would have been better; this invents
'seenV' instead. This led to a cascade of required changes. The
result is warning free and seems to be working but my fingers are
crosssed....
back into play with bad data
I don't have a test case to verify the fix, and I'm not absolutely
certain that the cause has been correctly diagnosed, but I think the
problem was caused by a guard being sent into limbo because the map
was too full to place it, then while it was on the migrating monsters
list waiting for a chance to come back the fuzzer executed #wizmakemap.
If the hero left the level and subsequently returned, the guard would
arrive back but monst->mextra->egd contained data for the previous
incarnation of the level that's invalid for wizmakemap's replacement.
Treat any shopkeeper, temple priest, or vault guard who is not on his
'home' level like the Wizard has been treated since 3.6.0. When
leaving the level they're on, put them on the migrating monsters list
scheduled to return to present position instead of stashing them in
the level's data file. That way they can be accessed from any dungeon
level, so wizmakemap can pull ones for the level it's replacing off
the migrating monsters list when removing the old level's monsters,
handling both migration-pending and already-arrived-on-another-level.
Bonus fix: put monsters who are on the migrating_mons list solely in
order to be accessible from other levels back first when returning to
the level they're on so that pets and the hero can't hijack their spot
when those arrive. The Wizard has been vulnerable to that.
Not fixed: #wizfliplevel command needs to flip parts of shk->mextra->
eshk and priest->mextra->epri for shk or priest on migrating_mons.
Vault guards don't contain anything flippable when migrating, but do
have coordinates that need fixing up while they're maintaining a
temporary corridor to/from the vault.
Change the inner workings of the experimental TTY_PERM_INVENT.
Switch to delivering the content to tty for the experimental perm_invent
via the existing window port interface (start_menu(), add_menu(), end_menu).
This also adds a new window port interface call ctrl_nhwindow() for
delivering information to the window port, and/or obtaining specific
information from the window port. The information and requests can
be extended as required. To be documented later once the changes settle
down.
Due to the intrusive nature of these changes and the possibility of
some bugs in the new code, I'm going to leave TTY_PERM_INVENT commented
out in the repository for a day or two. Anyone wishing to test it out
can do so by uncommenting TTY_PERM_INVENT in config.h.
Change the regex_error_desc() interface. Have the caller pass in
a pointer to a buffer of at least BUFSZ characters and have
regex_error_desc() populate that. No need for static buffers or
extra dynamic alloction.
Also, change it to never return Null. None of its callers were
checking for that and could have passed Null to config_error_add()
or raw_print(). printf("%s", NULL) produces "null" on OSX but other
systems would probably crash if a Null result ever actually occurred.
The error explanation returned by cppregex included a trailing period.
config_error_add() adds one, so the message ended up with two. Have
regex_error_desc() check for final period and strip it off if found.
(My test case used a menucolor pattern of "[" which triggers an error
about mismatched brackets.)
Reformat cppregex.cpp; treat 'extern "C" {' as if it isn't introducing
a nested block. Fix the '#include <hack.h>' that 'make depend' was
ignoring.
One of the drivers of this change was that screen coordinates require a
type that can hold values greater than 127. Parameters to the window
port routines require a large type in order to be able to have values
a fair bit larger than COLNO and ROWNO passed to them, particularly for
their use to the right of the map window.
This splits the uses of xchar into 3 different situations, and adjusts
their type and size:
xchar
|
-----------------------
| | |
coordxy xint16 xint8
coordxy: Actual x or y coordinates for various things (moved to 16-bits).
xint16: Same data size as coordxy, but for non-coordinate use (16-bits).
xint8: There are only a few use cases initially, where it was very
plain to see that the variable could remain as 8-bits, rather
than be bumped to 16-bits. There are probably more such cases
that could be changed after additional review.
Note: This first changed all xchar variables to coordxy. Some were
reviewed and got changed to xint16 or xint8 when it became apparent that
their usage was not for coordinates.
This increments EDITLEVEL in patchlevel.h
This starts the tty perm_invent just in time later in the
startup rather than initializing it with the other
game windows.
This also splits the duties:
The core will inquire from the window port about how many
inventory slots it can fill.
The core will handle figuring out the inventory text and
inventory letters, and will do the traversing of internal
data structures like obj chains, and passing customization
options on to the window port.
The window port will look after placing each inventory slot's
text at an appropriate location on the screen.
This, in theory, makes the core-portion available for
window ports other than tty to use, though none currently do.
The decision of what goes in an inventory slot is all left up
to the core with the update_invent_slot interface.
Documentation updates will come later, not at this time.
Refine the code added by pull request #763 to check the quest nemesis
death message for reference to noxious fumes rather than having the
three relevant roles be hardcoded.
I forced a test compile to -std=c++20 mostly to see what we would
be up against. There was only a small number of things and they
are corrected in this commit.
c++20 has some issues with comparisons and bit twiddling between
different enums.
The vendor-supplied Qt5 header files triggered some of those issues as
well, so the qt_pre.h and qt_post.h NetHack header files were adjusted
to make those new warnings go away. I have not tested Qt6 under the
new compiler and c++ version yet.
Because there are multiple pragmas in qt_pre.h now, the conditional
ifdef structure in there was modified a little to make maintenance
simpler and have a single pragma push at the top. The pragma pop
comes after the Qt vendor-supplied header files, and is done
in qt_post.h.
The display.h macro cmap_to_glyph() was used in
a Qt c++ file and triggered a series of warnings because of that.
Rather than write c++20-friendly versions of those macros, the
simple fix is to provide a function on the C side of things
to front the cmap_to_glyph() macro, so fn_cmap_to_glyph()
was added.
Also thrown into this commit, PatR picked up on the fact that for
yesterday's new warning in qt_menu.cpp, the compiler had correctly
picked up on the fact that the format range of the variable 'cash'
had been correctly upper-capped at 999999999L in the warning message
because of an assignment prior. He suggested that perhaps by also adding
if (cash < 0)
cash = 0;
the warning might be eliminated altogether.
After a test, that was proven to be correct, so yesterday's
more-kludgy change is reverted and replaced with that variable
variable restriction ahead of the snprintf().