Commit Graph

1627 Commits

Author SHA1 Message Date
nhmall
d0e43523d7 useupall really won't handle a NULL pointer
Revert useupall() prototype back to NONNULLARG1, as it was.
The callers in nhlua.c check gi.invent to be nonnull before
calling useupall().
2023-12-20 19:31:39 -05:00
PatR
a696cb8d90 some NONNULLs
Update the prototypes of some functions which return a pointer that
will never be NULL.  Only covers pager.c and part of objnam.c.
2023-12-20 15:55:21 -08:00
nhmall
07ef4583ce functions passed a chain explicitly NO_NONNULLS
Some functions are passed an obj or monst chain,
and  the callers typically don't check them
against 0, so mark them explicitly as NO_NONNULLS

(NO_NONNULLS expands to nothing, but it flags that
some null arg analysis has been done)
2023-12-20 18:48:50 -05:00
nhmall
0dafde4079 more nonnull follow-up 2023-12-20 15:53:51 -05:00
Pasi Kallinen
488afffcd7 Fix NONNULL for hitting bare handed 2023-12-20 20:09:50 +02:00
PatR
0713b91beb recalc_mapseen() followup
Update several places where lazy lastseentyp[] might be an issue.

I think it isn't updated in a timely fashion when newsym() shows
a spot covered by an object or trap, but didn't manage to find any
cases where that caused a problem.  This is more in the nature of
a precaution.
2023-12-20 03:17:29 -08:00
nhmall
08a1e68166 remove incorrect NONNULLARG1 on read_config_file 2023-12-18 12:40:31 -05:00
Pasi Kallinen
e4026d55fb Lazy evaluation of overview info
Callgrind showed recalc_mapseen was three times more expensive (in terms
of instructions read) than anything else in our codebase.  It was being
called in every vision change, re-evaluating the last seen map terrain
type for every map location in sight.

Remove updating the lastseen info in the vision code, and make a small
change so newsym() uses update_lastseentyp.

From my short tests, this seems to work correctly ...
2023-12-18 10:53:18 +02:00
nhmall
3bf2f0daee Revert "allow readobjnam arg to be nonnull"
This reverts commit 10f29a9760.
2023-12-17 07:20:35 -05:00
nhmall
10f29a9760 allow readobjnam arg to be nonnull
Have it key on &do_random_str instead of NULL,
and modify makewish() in zap.c for the new protocol.
2023-12-16 19:30:34 -05:00
nhmall
3e83d23b19 skip calling somexyspace() if mkroom ptr is NULL 2023-12-16 18:30:35 -05:00
PatR
ae80e7db47 fix analyzer complaints about Knox level
Fix some of the extreme verbosity for null vs non-null triggered
by mklev.c.  dungeon_branch() never returns Null.

'#include <assert.h>' should probably be moved out of multiple .c
files and into cstd.h or some such but this doesn't do that.
2023-12-16 13:26:17 -08:00
Pasi Kallinen
0099098d35 Silence some nonnull complaints 2023-12-16 14:03:16 +02:00
Pasi Kallinen
3c421da746 Previous hero rising as undead in bones retains intrinsics 2023-12-15 16:03:26 +02:00
nhmall
b368d4fbe9 revert a nonnull instance that deviated from the stated rules 2023-12-15 00:52:15 -05:00
nhmall
978ec6a3a7 augment include/extern.h with nonnull arg info
Define some macros in include/tradstdc.h, for compilers that support
__attribute__((nonnull)), to assist in identifying which parameters
on functions are not supposed to be null pointers.

Next, for the majority of functions declared in include/extern.h, this
adds the appropriate macro that matches the actual use of each function's
parameters. The additions were done after performing some analysis.

These were the rules that were followed when determining which function
parameters should be nonnul, and which are nullable:

    1. If the first use of, or reference to, the pointer parameter in the
       function is a dereference, then the parameter will be considered
       nonnull.

    2. If there is code in the function that tests for the pointer parameter
       being null, and adjusts the code-path accordingly so that no segfault
       will occur, then the parameter will not be considered nonnull (it can
       be null).

The use of the nonnull attributes allows the compiler to detect code in
callers of the function where a null parameter could get passed to the function.

If a warning is received the developer will have to do one of the following:

     - If the null being passed to the function is now appropriate,
       and the function should be able to expect a null parameter, then the
       NONNULLxxx macro will have to be removed from the function's prototype.

    or

     - If the null being passed to the function is not appropriate,
       correct the caller so it is not passing null.

    or

     - If the warning is about comparing to null, it may indicate an
       unnecessary null check in the code involved. If it is deemed to be
       unnecessary, it can then be removed.

Some static analysis tools apparently can work with the attribute, as well.

Following this, it was discovered that some functions were using one of the
(now) nonnull parameters in the first argument to the 'is_art(obj, ART)'
macro, which is defined like so:
 =>   #define is_art(o,art) ((o) && (o)->oartifact == (art))

That macro expansion inline resulted in a diagnostic warning because of the
'(o)' portion of the expanded macro, anywhere the macro was used with one of
the nonnull parameters. A test against null for a 'nonnull parameter' causes
a diagnostic warning.

To work around that, I replaced the is_art() macro with a function in
artifact.c, that accomplishes the same thing as the macro.

 =>   boolean
      is_art(struct obj *obj, int art)
      {
          if (obj && obj->oartifact == art)
              return TRUE;
          return FALSE;
      }

Some documentation...

These are the macros that have been defined for use when specifying the nonnull
parameters in a function prototype:

   ----------------------------------------------------------------------------
   |      Macro     |              Purpose                                    |
   +----------------+---------------------------------------------------------+
   | NONULL         | The function return value is never NULL.                |
   +----------------+---------------------------------------------------------+
   | NONNULLPTRS    | Every pointer argument is declared nonnull.             |
   +----------------+---------------------------------------------------------+
   | NONNULLARG1    | The 1st argument is declared nonnull.                   |
   +----------------+---------------------------------------------------------+
   | NONNULLARG2    | The 2nd argument is declared nonnull.                   |
   +----------------+---------------------------------------------------------+
   | NONNULLARG3    | The 3rd argument is declared nonnull.                   |
   +----------------+---------------------------------------------------------+
   | NONNULLARG4    | The 4th argument is declared nonnull (not used).        |
   +----------------+---------------------------------------------------------+
   | NONNULLARG5    | The 5th argument is declared nonnull.                   |
   +----------------+---------------------------------------------------------+
   | NONNULLARG7    | The 7th argument is declared nonnull (bhit).            |
   +----------------+---------------------------------------------------------+
   | NONNULLARG12   | The 1st and 2nd arguments are declared nonnull.         |
   +----------------+---------------------------------------------------------+
   | NONNULLARG13   | The 1st and 3rd arguments are declared nonnull.         |
   +----------------+---------------------------------------------------------+
   | NONNULLARG123  | The 1st, 2nd and 3rd arguments are declared nonnull.    |
   +----------------+---------------------------------------------------------+
   | NONNULLARG14   | The 1st and 4th arguments are declared nonnull.         |
   +----------------+---------------------------------------------------------+
   | NONNULLARG134  | The 1st, 3rd and 4th arguments are declared nonnull.    |
   +----------------+---------------------------------------------------------+
   | NONNULLARG17   | The 1st and 7th arguments are declared nonnull (this    |
   |                | was a special-case added for askchain(), where the      |
   |                | arguments are spread out that way. This macro           |
   |                | could be removed if the askchain arguments in the       |
   |                | prototype and callers were changed to make the          |
   |                | nonnull arguments side-by-side).                        |
   +----------------+---------------------------------------------------------+
   | NONNULLARG145  | The 1st, 4th and 5th arguments are declared nonnull     |
   |                | (this was a special-case added for find_roll_to_hit(),  |
   |                | in uhitm.c, where the arguments are spread out that way.|
   |                | We can't just use NONNULLPTRS there because the 3rd     |
   |                | argument 'weapon' can be NULL).                         |
   +----------------+---------------------------------------------------------+
   | NONNULLARG24   | The 2nd and 4th arguments are declared nonnull (this    |
   |                | was a special-case added for query_objlist()            |
   |                | in invent.c).                                           |
   +----------------+---------------------------------------------------------+
   | NONNULLARG45   | The 4th and 5th arguments are declared nonnull (this    |
   |                | was a special-case added for do_screen_description(),   |
   |                | in pager.c, where the arguments are spread out that     |
   |                | way. We can't just use NONNULLPTRS there because the    |
   |                | 6th argument can be NULL).                              |
   +----------------+---------------------------------------------------------+
   | NO_NONNULLS    | This macro expands to nothing. It is just used to       |
   |                | mark that analysis has been done on the function,       |
   |                | and concluded that none of the arguments could be       |
   |                | marked nonnull.That distinguishes a function that has   |
   |                | not been analyzed (yet), from one that has.             |
   +----------------+---------------------------------------------------------+

The NO_NONNULLS macro is meant to place a flag on the prototype to
make people aware that an assessed function was determined to not
be eligible for nonnull parameters. It expands to nothing.

Unfortunately, that macro was added partway through this exercise, so there
aren't many instances of it in the upper parts of include/extern.h, even though
the functions there were likely assessed and categorized as not having any
eligible nonnull parameters. It just never got any macro at all, in that case.

Following the parameter usage analysis that was done, the following was
noted:

       Some NetHack functions have added a test to catch a passed null
       parameter, and exit the function early as a result, or call
       impossible(), and then exit. While that approach prevents segfaults
       from dereferencing a null parameter, the early return is silent
       (when impossible is not called anyway), and the function's true
       purpose is not fulfilled. Also, the calling function may have no
       awareness that the function did not complete its intended purpose,
       in many instances.

       Functions with such a test and early return, cannot have the parameter
       declared 'nonnull', because the code to test for 'null' will cause a
       diagnostic to be issued if the parameter is nonnull.

       It might be good to revisit some of those functions and consider,
       on a case by case basis, declaring the parameter nonnull in the
       prototype, and the test/code-path commented out.
2023-12-14 20:06:03 -05:00
nhmall
c3f9d8cde2 fix which file contains mimic_hit_msg in extern.h 2023-12-12 22:42:51 -05:00
nhmall
c4e5a06e95 fix more extern.h file containing functions
The following were listed in extern.h as residing in makemon.c,
but they are actually in mon.c:

    copy_mextra(struct monst *, struct monst *);
    dealloc_mextra(struct monst *);
    usmellmon(struct permonst *);
2023-12-12 22:33:09 -05:00
nhmall
b58d89dbcb fix which file contains dealloc_monst() in extern.h 2023-12-12 16:37:15 -05:00
nhmall
fb139a462e fix which file contains parse_sym_line() in extern.h 2023-12-12 12:27:50 -05:00
nhmall
9ad9a558c4 fix which file contains map_engraving() 2023-12-12 11:57:49 -05:00
PatR
4bd7f265f1 wizard mode terrain wishing at drawbridge spot
When trying to reproduce the wand of striking "interesting effect (0)"
report, I tried wishing for lava under the castle drawbridge.  That
wasn't handling drawbridges properly.  This fixes wishing for moat,
lava, ice, or floor at a drawbridge span location whether the bridge
is currently open of closed.  It also allows wishing for room or floor
or ground at room spots; that hasn't had much testing.

Wishing for furniture, pool|moat|water, or lava at an ice location
wasn't cancelling any pending melt timer.

ice_descr() was declared as returning const but returns its non-const
output buffer argument.  Change to 'char *' so that wizterrainwish()
can capitilize that output without jumping through any hoops.
2023-12-11 19:54:20 -08:00
PatR
8e99df14ae refine #K4060 fix - affect of riding on stealth
Hide some of the details about new Stealth.

Streamline mon_break_armor().  Move replicated bypass handling into
m_lose_armor().  Also, eliminate a 'goto'.
2023-12-11 13:55:35 -08:00
PatR
a7db78f7d6 fix #K4060 - "you walk quietly" while riding
Donning elven boots while riding and not already stealthy, you'd get
the message "you walk quietly" when not walking at all.  Instead of
just changing the message, make riding a non-flying steed block
stealth.  Riding a flying steed (or one you take aloft with an amulet
of flying) does not.  It would have been quite a bit simpler to have
made riding anything block stealth, but the hard part is done.
2023-12-10 22:09:26 -08:00
nhmall
0ef2f15f51 check tty in can_set_perm_invent
During very early startup, Windows may not have loaded
the tty window procs yet, and it is running with safeprocs.
It will eventually load the tty stuff. If the currently
operating window port fails in can_set_perm_invent(),
try the check for WC_PERM_INVENT again explicitly on
the tty windowport.
2023-12-09 01:31:08 -05:00
Alex Smith
7ca9951996 Reduce code duplication in extrinsics-protect-items code
The same checks were being repeated for every damage type; this
sends them through two centralised functions (one for checking
whether an extrinsic blocks a specific instance of item destruction
and one for the enlightenment message), so that new mechanisms of
item destruction prevention will need to change only one point in
the code.
2023-12-05 04:34:24 +00:00
Pasi Kallinen
1c933d689e Remove leftover debug extern define 2023-12-04 17:57:58 +02:00
Pasi Kallinen
d8421aa219 Save and restore hero tracks
The tracks left by hero were cleared when player saved and
restored the game, or changed levels.  Now the tracks are
saved in the dungeon level, so changing levels keeps the tracks
left by hero in that level.

Also increased the length of tracks from 50 to 100, and
simplify the tracking function.

Thing not done: fade out old tracks when returning to a level.

Breaks saves and bones.
2023-12-04 17:50:48 +02:00
nhmall
7d22a2c7b9 uhandedness follow-up
boomerang trajectory
bones
2023-12-02 20:25:37 -05:00
Alex Smith
319dfbdaa3 Wizards learn about spellbooks as they enhance their spell skills
Previously, Wizards got a boost to the chance of writing unknown
spellbooks based purely on being a Wizard (with the chance still
luck-based), leading to a very large power spike when the Wizard
gained access to a luckstone and the ability to max out luck.
This had two main issues: this power spike came *after* the major
early-game difficulty spike, often leaving Wizards forced to deal
with it without having appropriate spells; and it promotes
grinding (for Luck and for Magicbane) at an early point in the
game, meaning that the Wizard early game effectively followed a
sequence of extreme difficulty -> grinding -> minimal difficulty,
which isn't very good balance-wise.

With this commit, Wizards lose their advantage to writing unknown
spellbooks by guessing, and instead learn spellbook IDs based on
their spell skills (advancing a skill gives knowledge of higher-
level spellbooks). This means that writing unknown spellbooks
becomes guaranteed with sufficient skill, but has no advantage
over non-Wizards in schools where the Wixard does not have
sufficient skill.

Due to Wizards' skill caps, there are two spells which they can't
ever write guaranteed: create familiar and charm monster. Create
familiar is a fairly niche spell (that doesn't match the Wizard
playstyle that well) and being unable to write it is not a major
problem. The inability to easily write charm monster is
intentional.
2023-12-02 03:46:55 +00:00
Michael Meyer
0473fff5b5 Make destruction of altar incite its god's wrath
This is for completely destroying an altar with extra-powerful magical
digging -- the normal altar_wrath() punishment didn't seem sufficient
for such an outrage to me, so skip straight to slinging the lightning
bolts.  Destroying an altar is unlikely to happen by accident (though
it's possible with poorly timed usage of a drum of earthquake).
2023-11-29 11:36:56 -08:00
PatR
6c5b5c0688 more '*' and perminv_mode==inuse
If any items are in use and hero isn't wielding anything, include
| - bare hands
in the primary weapon slot of the display of used items as an alert.
More useful for perm_invent than for #seeall.

If no items at all are in use, continue to show "not using any items"
without any specific weaponless alert.

When sortloot() is called for inuse_only, pass a filter that screens
out items which aren't in use so they won't be needlessly sorted.
2023-11-25 14:11:43 -08:00
nhmall
fa4a47d8ff relocate choose_classes_menu() to windows.c
choose_classes_menu was declared extern. The only caller presently
was calling it was optfn_pickup_types() in options.c.

It could have had the extern declaration from include/extern.h and
declare it as static within options.c, if that was the only use
anticipated. Also, if the one existing caller were all there would
ever be, the argument passed to it that was the subject of pr #1146
could have just been removed along with the switch.

Checking the comments above the function, however, it was clearly
designed as a general-purpose function that could be called from
anywhere for the functionality desired, even though there's presently
just the one caller, passing just the one variation of the category
argument.

Relocate the general-purpose function over to src/windows.c, where
several interface-related / menu-related general-purpose functions
already reside.

options.c has gotten *huge* and this is a fitting opportunity to
reduce its size a little.
2023-11-23 14:28:12 -05:00
nhmall
2a48859de2 include the PM_ index in mons (permonst)
This is useful for debugging and it allows the index
to be used directly instead of calculated in a
monsndx() function, which has been removed.

I left monsndx() in as a simple short-hand macro for the value
and didn't change the use cases, the reasoning being that this:
    monsndx(mon->data)
is arguably a little easier on the eyes than:
    mon->data->pmidx

LOW_PM, NON_PM, SPECIAL_PM have been included in the 'enum monnums'
now, instead of as individual macro definitions.

I chose to add the pmidx field as an instance of the enum declaration,
because that has very advantageous results in some debuggers, where it is
then shown as:
    pmidx PM_GRAND_MASTER (349) monnums
instead of the less-informative:
    pmidx 349 int

Adding the element count to the extern declaration for mons from:
    'extern struct permonst *mons[];'
to the more specific declaration to that in src/monst.c:
    'extern struct permonst *mons[NUMMONS + 1];'
then allows navigation through the mons array in one of the debuggers.
2023-11-23 12:22:47 -05:00
nhmall
d7ed474fa7 2nd follow-up to alternative fix for menu search (':') 2023-11-17 14:13:58 -05:00
nhmall
8d1001842d alternative fix for menu search (':')
This avoids clearing core context variables within a window port.
2023-11-17 08:37:54 -05:00
Michael Meyer
f5a22ff5f8 Print current level annotation when restoring
Sometimes I annotate a level with a note like "watch out, chameleon
below", which is useful to remind myself of some danger or thing to
remember when returning to the level -- but if saving and restoring on
the level itself there's no reminder of that annotation.  If you restore
on a level with an annotation, print it as part of the "welcome back"
message.
2023-11-16 23:15:04 -08:00
nhmall
86067dcffd use ctrl_nhwindow() for menu prompt style
This implements the mechanics to use the ctrl_nhwindow() interface
capability to pass down a setting change from the core to the active
window port, without resorting to accessing a core global variable
from within the window port, and without altering the interface..

The passed setting is honored in the tty and curses window ports.

X11 and mswin receive and store the values, but no implementation
to change the menu prompt style is there yet.

Qt does not store the values or have an implementation.

The setting change is done in allmain.c immediately after
creating the WIN_INVEN window.
2023-11-16 00:10:06 -05:00
PatR
fc52f0ef42 'menu_headings' option
If the value is "no color&none" report it as "no-color&none" in 'm O'
and for #saveoptions.

Allow "OPTIONS=menu_headings" without any color or attribute value to
mean "no-color&inverse" as it once did before the player could choose
which attribute or color was supported, and matching the default used
when 'menu_headings' hasn't been specified at all.

Accept "OPTIONS=!menu_headings", meaning "no-color&none".

Explicitly reject "OPTIONS=!menu_headings:anything".  It was rejecting
that due to blanket rejection of negated option, but reporting "can't
both have a value and be negated" whether there was any value present
or not.

For preselected menu entries when interactively choosing a new value
via the submenu of 'm O', use the current color and attribute rather
than NO_COLOR and ATR_NONE.
2023-11-14 21:33:09 -08:00
Pasi Kallinen
d2ca1794df Move other add_menu routines to windows.c 2023-11-13 20:12:47 +02:00
nhmall
4b79baa55b add_menu follow-up, part 2 of interface adjustment
Remove menu_color support from the window port side of the interface.
The window port just has to honor the color parameter that was added
to the add_menu() interface definition in June 2022 commit
2770223d10, and let the core-side of
the interface handle things.

To that end, this does the following:

Removes the #define of add_menu() from include/winprocs.h and add a
real core-side add_menu() function to windows.c which acts as a
trampoline to the window port win_add_menu() function, while providing
a single location to adjust the parameters passed to the window port
function. get_menu_coloring() is now called in there.

Moves get_menu_coloring() from options.c into windows.c and makes it
static.

Removes all the calls to get_menu_coloring() from the tty, Qt, X11,
curses, and win32 interfaces and adjusts their code to simply honor
the color parameter in add_menu, similar to what the menu_headings
change from earlier today did.
2023-11-13 12:56:38 -05:00
Pasi Kallinen
dd5ca5b058 Change menu_headings to accept color and attribute
Instead of just accepting an attribute, it's now possible to
use a color, or both color and attribute, for example:

OPTIONS=menu_headings:inverse
OPTIONS=menu_headings:red
OPTIONS=menu_headings:red&underline

Default is still just inverse.
This lets the player change the menu heading color without
needing to use menu colors for them.

Also makes it so the core uses NO_COLOR instead of 0, for all
the menu lines which don't have any prefedefined color.

Tested for tty, curses, x11, qt, and win32
2023-11-13 07:33:56 +02:00
Michael Meyer
d42564bacd Better align drop_throw with hero ammo breakage
There is a comment above the function indicating that it should be
aligned with hero ammo breakage, but this wasn't the case.  One big
difference is that any monster-thrown or -shot object would be deleted
unconditionally if it hit another monster trapped in a pit.  I don't
know why that was in there, but it's not present in hero ammo breakage
chances, and it meant that a monster could sling the Mines luckstone at
the hero, hit a monster in the pit, and permanently lock the hero out of
getting the luckstone (as just happened to a player during the current
tournament).  This pulls the hero breakage rules out into their own
function and uses that for monster breakage as well, to make sure they
are aligned.  I also refactored drop_throw a bit to reduce the number of
separate variables tracking whether the object was deleted (was create,
objgone, and retvalu), and changed its (and ohitmon's) type to boolean.
2023-11-11 01:17:54 -08:00
Michael Meyer
674b8c6b07 Add additional sink potion #dipping effects
Also put "Nothing seems to happen." into c_common_strings, since it's
used all over several files.
2023-11-09 16:41:05 -08:00
Michael Meyer
3fac63749a Add basic sink #dipping effects
This is largely taken from xNetHack with a few minor changes.  Dipping a
potion into a sink can help with item identification by producing the
potionbreathe effect (or a sink-specific effect, for a couple potions).
Dipping other items will just run water over them.  I also added the
capability to wash your hands at a sink.
2023-11-09 16:41:05 -08:00
Michael Meyer
5af1fad398 Enable hero to wash hands in fountains and pools
Dipping hands (with '-') or currently-worn gloves in a fountain or pool
will cause the hero to wash her hands, washing away any oil and clearing
the Glib intrinsic timeout.  This does mean bare hands can be used to
fish for fountain effects, without having to pick up a stray arrow and
carry it around as a dipping item, but having your hands be the only
thing that does not activate those effects felt weird.  If that would be
too unbalancing this could be scrapped.
2023-11-09 16:41:04 -08:00
Michael Meyer
a1b1f3b250 Try to unify "back on solid ground" messaging
Put everything through a single function that can handle all the
complicated parts of using the correct proposition for different terrain
types, and will not just call things "solid ground" indiscriminately.
This got complicated but I'm not sure if it's possible to do it much
simpler while still using the distinct names for each type of terrain
(unless you are OK with the sentences sounding sort of wonky).
2023-11-07 16:13:55 -08:00
Michael Meyer
85b727c92c Apply sysconf EXPLORERS restriction on startup
The sysconf EXPLORERS list restricting access to explore mode was being
evaluated and used when a player used the #exploremode command in-game,
or when specifying -X or OPTIONS=playmode:explore on the command line
when resuming a normal game, but not when starting an entirely new game.
When SYSCF is avilable, check for authorization early, similar to debug
mode authorization, to restrict access to explore mode to EXPLORERS
under (hopefully) all circumstances.
2023-11-07 15:38:08 -08:00
Michael Meyer
98d2b0ecb3 Follow up on disturbing buried zombies
Change 852f8e4 by requiring a minimum impact before a buried zombie
nearby will be disturbed: light, but still excluding things like
scrolls, if it's a violent impact (dropped while levitating, thrown, or
kicked), and fairly heavy if the hero is just placing the item on the
ground normally.

Moving the call out of flooreffects meant it no longer applied to
pushing boulders around, so have moverock disturb nearby zombies.  I
additionally had wake_nearby do the same thing.

Finally, I renamed check_buried_zombies (which doesn't really reflect
what it does) to disturb_buried_zombies.
2023-11-05 21:51:45 -08:00
Pasi Kallinen
a6051dae81 Simplify adding menu headings 2023-11-03 19:07:15 +02:00