Commit Graph

338 Commits

Author SHA1 Message Date
PatR
1fd3bb661f fix issue #1378 - brain eaten after flayer's death
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
2025-02-25 09:54:14 -08:00
nhmall
0792e5fe9e expand implicit fallthrough detection to non-gcc compilers
gcc has recognized various "magic comments" for white-listing
occurrences of implicit fallthrough in switch statements for
a long time:

    The range and shape of "falls through" comments accepted are
    contingent upon the level of the warning. (The default level is =3.)

    -Wimplicit-fallthrough=0 disables the warning altogether.
    -Wimplicit-fallthrough=1 treats any kind of comment as a "falls through" comment.
    -Wimplicit-fallthrough=2 essentially accepts any comment that contains something
     that matches (case insensitively) "falls?[ \t-]*thr(ough|u)" regular expression.
    -Wimplicit-fallthrough=3 case sensitively matches a wide range of regular
     expressions, listed in the GCC manual. E.g., all of these are accepted:
        /* Falls through. */
        /* fall-thru */
        /* Else falls through. */
        /* FALLTHRU */
        /* ... falls through ... */
       etc.
    -Wimplicit-fallthrough=4 also, case sensitively matches a range of regular
     expressions but is much more strict than level =3.
    -Wimplicit-fallthrough=5 doesn't recognize any comments.

Plenty of other compilers did not recognize the gcc comment convention,
and up until now the compiler warning for detecting unintended
fallthrough had to be suppressed on other compilers. That's because the code
in NetHack has been relying on the gcc approach, and only the gcc approach.

The C23 standard introduces an attribute [[fallthrough]] for the
functionality, when implicit fallthrough warnings have been enabled.

Several popular compilers already support that, or a very similar attribute
style approach, today, even ahead of their C23 support:

       C compiler                       whitelist approach
       ---------------------------   -------------------------------------
       C23 conforming compilers         [[fallthrough]]

       clang versions supporting
       standards prior to
       C23                              __attribute__((__fallthrough__))

       Microsoft Visual Studio
       since VS 2022 17.4.
       The warning C5262 controls
       whether the implict
       fallthrough is detected and
       warned about with
       /std:clatest.                    [[fallthrough]]

This adds support to NetHack for the attribute approach by inserting a
macro FALLTHROUGH to the existing cases that require white-listing, so
other compilers can analyze things too.

The definition of the FALLTHROUGH macro is controlled in include/tradstdc.h.

The gcc comment approach has also been left in place at this time.
2024-11-30 14:16:27 -05:00
PatR
1c5b295097 tin consumption edge cases
If eating a tin killed the hero (choked, turned to stone, poly'd into
a new man with new Xp too low to survive) and bones were saved, the
tin remained intact in them.

When hero who is poly'd into metallivore form eats a tin, give a
little extra nutrition for the tin itself.  Also, eat it immediately
by skipping the "It smells like <creature>" message and "Eat it? [yn]"
prompt.  (The message while eating it also reports <creature>, so
skipping the 'smells' one doesn't end up hiding anything.)
2024-11-26 18:01:19 -08:00
PatR
e9a25a0a1c sanity_check: current hero health better than max
Changes to setuhpmax() a couple of days ago to deal with sanity_check
for "current hero health as monster better than maximum" ended up
triggering sanity_check about "current hero health better than maximum"
when gaining experience level(s) while polymorphed.
2024-09-26 23:00:42 -07:00
PatR
aa043f0ddf some reformatting (2 of 4) 2024-09-05 14:51:21 -07:00
PatR
45690624e5 fix pyrolisk egg panic when eating from floor
From a change made about two and half months ago:  eating a pyrolisk
egg tried to use it up from inventory even when it was on the floor.
That would trigger an object lost panic.
2024-08-17 11:02:28 -07:00
Michael Meyer
d09a5beab3 Rename polyfodder() to polyfood()
'Polyfodder' is already a term frequently used by players to describe
items which are useful to hang on to specifically to zap polymorph at
(for example, extra unicorn horns, which can be turned into magic
markers).  Using it as the name of a macro which tests whether a food
item will polymorph the creature consuming it is somewhat confusing, and
I think 'polyfood' is a lot clearer.
2024-07-15 23:42:29 -07:00
nhmall
6c0ae092c6 distinguish global variables that get written to savefile
The g? structs had a mix of variables that were written to
the savefile, and those that were not.

For better clarity and to distinguish those that end up in
the savefile, relocate some g? variables that get written
directly to the savefile into different structs.

This updates EDITLEVEL, although technically it probably
didn't need to, since savefile contents are not changing.

Details:

    gb.bases            -> svb.bases
    gb.bbubbles         -> svb.bbubbles
    gb.branches         -> svb.branches
    gc.context          -> svc.context
    gd.disco            -> svd.disco
    gd.dndest           -> svd.dndest
    gd.doors            -> svd.doors
    gd.doors_alloc      -> svd.doors_alloc
    gd.dungeon_topology -> svd.dungeon_topology
    gd.dungeons         -> svd.dungeons
    ge.exclusion_zones  -> sve.exclusion_zones
    gh.hackpid          -> svh.hackpid
    gi.inv_pos          -> svi.inv_pos
    gk.killer           -> svk.killer
    gl.lastseentyp      -> svl.lastseentyp
    gl.level            -> svl.level
    gl.level_info       -> svl.level_info
    gm.mapseenchn       -> svm.mapseenchn
    gm.moves            -> svm.moves
    gm.mvitals          -> svm.mvitals
    gn.n_dgns           -> svn.n_dgns
    gn.n_regions        -> svn.n_regions
    gn.nroom            -> svn.nroom
    go.oracle_cnt       -> svo.oracle_cnt
    gp.pl_character     -> svp.pl_character
    gp.pl_fruit         -> svp.pl_fruit
    gp.plname           -> svp.plname
    gp.program_state    -> svp.program_state
    gq.quest_status     -> svq.quest_status
    gr.rooms            -> svr.rooms
    gs.sp_levchn        -> svs.sp_levchn
    gs.spl_book         -> svs.spl_book
    gt.timer_id         -> svt.timer_id
    gt.tune             -> svt.tune
    gu.updest           -> svu.updest
    gx.xmax             -> svx.xmax
    gx.xmin             -> svx.xmin
    gy.ymax             -> svy.ymax
    gy.ymin             -> svy.ymin

Related note:
There are some pointer variables that are heads of chains that were not
moved from 'g?' to 'sv?', because they are not actually written to the
savefile directly, but the objects/monst/trap/lightsource/timer in the
chains they point to are. That can be changed, if desired.
Examples: gi.invent, gm.migrating_objs, gb.billobjs, gm.migrating_mons,
          gf.ftrap, gl.light_base, gt.timer_base
2024-07-13 14:57:50 -04:00
Pasi Kallinen
4e29c9b282 Fix eating non-pyrolisk egg effect 2024-06-03 17:40:50 +03:00
Pasi Kallinen
2bec685bae Pyrolisk eggs explode when broken 2024-06-02 10:50:58 +03:00
PatR
82c9e9b737 fix #K4166 - touchfood() can return destroyed obj
Eating from a stack while inventory is full drops the partly eaten
food.  If over lava and it is flammable it gets used up without the
eating code being aware of that.  (Dropping into a hole or trap door
shouldn't have the same problem because the dropped object is still
accessible via the migrating objects list.)

Have touchfood() return NULL if the food item gets used up due to
being dropped.  By itself, that wasn't enough.  Callers needed to be
updated to handle that.

I didn't look at other callers of dropx/dropy/dropz; they might have
similar issues.  Perhaps they should return the dropped object or
take a pointer to an obj pointer so that there can be just one check
for obj->where==OBJ_DELETED after dropping, but their callers would
still need to updated to cope with that.
2024-05-08 07:15:29 -07:00
nhkeni
54c3dd35ac Merge branch 'keni-staticfn' into NetHack-3.7 2024-03-16 09:38:21 -04:00
nhmall
79648c6ce2 some variables not referenced in another translation unit made static
Also adds some cross-refence comments for some variables that are
referenced in another translation unit.
2024-03-15 16:00:14 -04:00
nhkeni
9c0ed8ae63 NOSTATICFN for src/* 2024-03-14 17:41:51 -04:00
RainRat
a3658f85ac fix typos 2024-02-28 20:15:56 -08:00
nhmall
688ac6ffbe remove register from variable declarations 2024-02-19 16:30:07 -05:00
PatR
2d886dfcd8 fix #K4095 - race-specific food weight
Lembas wafers give more than normal nutrition for elves and less than
normal for orcs.  Cram rations give more that nomral for dwarves.  The
way that was implemented affected the weight of those items, at least
after they were partly eaten.  Polymorphing to or from any of the
affected races resulted in inconsistent partly eaten food.

Change how the nutritional bonus or penalty is applied so that there
isn't any affect on item weight.

I haven't incremented EDITLEVEL, so any wafers/rations with incorrect
weight in existing save files will continue to have that wrong weight.
I suppose that it matters more for bones files but even they should be
ok living with this instead of being forced to be thrown away.
2024-02-02 15:32:49 -08:00
Pasi Kallinen
c2ddd2a7c2 Fix some object weight problems
There were few places where the object weight was not updated:

- container when the contents were broken by impact
- starting to eat but getting stopped by rotten food
- using lua, container when putting an object inside it
- when a single egg of a larger stack hatched
2024-01-24 17:58:54 +02:00
bitofhope
11381d631c Rephrase "rotten" non-rottable items 2024-01-16 11:27:46 +02:00
nhmall
c134a128ac rephrase rotten metal
Resolves #1202
2024-01-15 17:58:11 -05:00
nhmall
25a8c258e6 replace x >= LOW_PM with ismnum(x) shorthand macro 2024-01-11 14:01:10 -05:00
PatR
83bdf71932 pull request #1175 - obj->corpsenm fixes
Pull request by mkuoppal:  some objects which use the corpsenm field
to access the mons[] array can have a corpsenm value of NON_PM (-1)
and weren't avoiding array access in those cases.

In addition to a fixes entry for it, this makes some revisions to the
commited code, handling a few of the cases differently.

Closes #1175
2024-01-06 15:13:31 -08:00
Mika Kuoppala
6a085955ea src/eat: Check for valid corpsenm before checking is_rider
corpsenm can be -1 so limit checking is_rider with only
>= LOW_PM corpse numbers.
2024-01-06 12:06:54 -08:00
nhmall
4e19221e55 variable 'display' causes shadow variable warnings in X11 build
display.botl      -> disp.botl
display.botlx     -> disp.botlx
display.time_botl -> disp.time_botl
2024-01-05 05:58:51 -05:00
nhmall
49a5d043c0 consistent use of TRUE vs 1 with botl and botlx 2024-01-04 23:48:38 -05:00
nhmall
22e52ee905 bundle the display-related hints, that tell bot() and others
that an update is required, into a struct. Remove it from
context since there is no reason to save those.
2024-01-04 23:16:27 -05:00
PatR
05cf948007 fix github issue #1186 - eating Medusa's corpse
and having temporary stoning resistance timeout before finishing.

Issue reported by Umbire:  hero was able to finish eating Medusa's
corpse safely after getting the message about no longer being
protected against stoning that is given when temporary resistance
times out.

The eating code was extending temporary resistance--when eating
something protected by such--to avoid just that.  I thought this
was probably a message sequencing situation but it turns out that
the code was using touch_petrifies() to test the meal.  It should
use flesh_petrifies() instead; Medusa doesn't pass touch_petrifies().

I didn't figure that out until after rewriting how the duration is
extended.  The old way probably would have worked as desired with
the revised petrify test but I'm checking in the new version anyway.

Fixes #1186
2023-12-23 17:38:05 -08:00
nhmall
d7fef5f194 avoid another magic number
Some of the hardcoded +1 scattered about are likely
invlet_gold or invlet_overflow, but I didn't hunt those down.
2023-11-30 11:15:32 -05:00
nhmall
76d328d86a gi.invalid_obj -> hands_obj 2023-11-11 19:49:38 -05:00
nhmall
f97ff175de bring a couple of comments up to date 2023-11-10 13:17:09 -05:00
nhmall
24b6f6a03e follow-up cast removal in eat.c 2023-11-10 11:28:08 -05:00
nhmall
314a2a9489 use gi.invalid_obj instead of cg.zeroobj
cg.zeroobj was originally added (under its previous unprefixed name)
for providing a one-line way to zero out the fields of a struct obj.

    struct obj tempobj;
    tempobj = cg.zeroobj;

    initfn(struct obj *otmp)
    {
        if (otmp)
            *otmp = cg.zeroobj;
    }

More recently, the address of cg.zeroobj began to be used as a return
flag to indicate some things, but the 'const struct obj zeroobj' wasn't
an ideal fit for the purpose and required a number of casts, including
casting away const.

Provide a better fitting variable (gi.invalid_obj) and eliminate a
number of casts.
2023-11-10 11:07:49 -05:00
nhmall
6cbefc7c2d Revert "granular verbose message suppression mechanics"
This reverts commit be76727265.
2023-10-29 20:39:07 -04:00
Pasi Kallinen
7bf3888118 Shopkeepers consider monster type for some items
Tins, eggs, and corpses will now cost different amounts
based on what intrinsics the monster type could give
2023-10-25 18:45:16 +03:00
Michael Meyer
fa1f1134c8 Disambiguate b_trapped null bodypart value
b_trapped was treating 0 as a null value for its bodypart parameter, but
0 is actually the value of ARM, so b_trapped(..., ARM) would be treated
as intending no A_CON abuse.  Add NO_PART = -1 to the bodypart_types
enum, and use that instead of 0 as the "no body part" value in
b_trapped, so that ARM can be passed to it without any ambiguity.

aosdict identified this issue in xNetHack and handled it differently; he
added NO_PART with a value of 0, incremented the existing bodypart_types
values, and padded the body part arrays so the actual body parts would
start at index 1.  I think using NO_PART = -1 is simpler, but that's an
alternative approach that can be used instead -- it is advantageous in
that it automatically fixes any other places where 0 is assumed to be a
non-body-part value that I may have overlooked.
2023-09-27 10:40:27 +03:00
PatR
dd05f5183e addinv_nomerge()
Replace several instances of
 obj->nomerge = 1;
 addinv(obj);
 obj->nomerge = 0;
with new
 addinv_nomerge(obj);
and add various related comments.
2023-09-19 14:40:33 -07:00
Pasi Kallinen
50084750c4 Ring of hunger prevents choking on food
... but you will not be prompted to stop eating,
and you will vomit enough to be hungry afterwards.
2023-09-03 18:27:00 +03:00
PatR
1c94bdac89 blindness overhaul
I was working on this at the time 3.6.0 was released and set it aside
until later.  Later has finally arrived.  Redo the Blind, Blinded,
Blindfolded,&c macros to make more complete use of intrinsic property
handling.  Blinded was being treated as a number which could be added
to or subtracted from; now that has to be done via TIMEOUT mask
because it has FROMOUTSIDE (OPTIONS:blind) and FROMFORM (poly'd into
!haseyes() form) bits included.  Object definitions for blindfold and
towel now specify the BLINDED property; overriding blindness via the
Eyes of the Overworld is accomplished via props[BLINDED].blocked.

Code generated for the scores of Blind and !Blind tests throughout
the program should be smaller.

One bug that has been fixed is that putting on the Eyes of the
Overworld cured permanent blindness (from OPTIONS:blind).  The
u.uroleplay.blind flag was cleared and stayed so after taking them
off.  Putting the Eyes on still breaks blind-from-birth conduct but
now blindness will resume when they are removed.

This was untested at the time it was set aside and is only lightly
tested now.  A large number of the changes here are just to switch
from Blinded to BlindedTimeout for current timed value and to call
set_itimeout() for setting a new value.
2023-04-27 14:53:28 -07:00
nhmall
5f69dc6228 make attack result macros more distinguishable from makemon macros
Use the MM_ prefix only for the makemon macros, and change these five as follows:

 MM_MISS 0x0     -> M_ATTK_MISS      /* aggressor missed */
 MM_HIT 0x1      -> M_ATTK_HIT       /* aggressor hit defender */
 MM_DEF_DIED 0x2 -> M_ATTK_DEF_DIED  /* defender died */
 MM_AGR_DIED 0x4 -> M_ATTK_AGR_DIED  /* aggressor died */
 MM_AGR_DONE 0x8 -> M_ATTK_AGR_DONE  /* aggressor is done with their turn */

include/hack.h:#define NO_MM_FLAGS     0x000000L /* use this rather than plain 0 */
include/hack.h:#define MM_NOWAIT       0x000002L /* don't set STRAT_WAITMASK flags */
include/hack.h:#define MM_NOCOUNTBIRTH 0x000004L /* don't increment born count (for revival) */
include/hack.h:#define MM_IGNOREWATER  0x000008L /* ignore water when positioning */
include/hack.h:#define MM_ADJACENTOK   0x000010L /* acceptable to use adjacent coordinates */
include/hack.h:#define MM_ANGRY        0x000020L /* monster is created angry */
include/hack.h:#define MM_NONAME       0x000040L /* monster is not christened */
include/hack.h:#define MM_EGD          0x000100L /* add egd structure */
include/hack.h:#define MM_EPRI         0x000200L /* add epri structure */
include/hack.h:#define MM_ESHK         0x000400L /* add eshk structure */
include/hack.h:#define MM_EMIN         0x000800L /* add emin structure */
include/hack.h:#define MM_EDOG         0x001000L /* add edog structure */
include/hack.h:#define MM_ASLEEP       0x002000L /* monsters should be generated asleep */
include/hack.h:#define MM_NOGRP        0x004000L /* suppress creation of monster groups */
include/hack.h:#define MM_NOTAIL       0x008000L /* if a long worm, don't give it a tail */
include/hack.h:#define MM_MALE         0x010000L /* male variation */
include/hack.h:#define MM_FEMALE       0x020000L /* female variation */
include/hack.h:#define MM_NOMSG        0x040000L /* no appear message */

include/hack.h:#define MM_NOEXCLAM     0x400000L /* more sedate "<mon> appears." mesg for ^G */
include/hack.h:#define MM_IGNORELAVA   0x800000L /* ignore lava when positioning */
2023-03-19 12:19:34 -04:00
Pasi Kallinen
e29bfcab54 Split eating non-food into separate function 2023-03-19 15:12:08 +02:00
nhmall
de79240dea some comment spelling fixes 2023-03-16 22:27:01 -04:00
PatR
3ab5e7b380 eliminate static analysis complaints about eat.c
This is fairly ridiculous but it prevents the bogus complaints
when compiling eat.c with 'gcc -fanalyzer' about some fields in
gc.context.victual being used without having been initialized.

There's bound to be a better way to handle this and I'm curious
whether it will work with the 'onefile' testing.
2023-03-05 16:19:32 -08:00
Pasi Kallinen
d19c92281a Give gremlin the property it stole, if possible 2023-01-25 21:55:11 +02:00
Pasi Kallinen
1d8c944c5a Eating garlic makes some monsters flee 2023-01-24 06:17:17 +02:00
PatR
d6872c0431 analyzer vs eat.c
scan-build from llvm-14 (clang) doesn't complain about bite() or
maybe_finished_meal() so this is unlikely to fix those.  But this
does fix one bogus complaint it has for doeat().  Testing whether
the result from touchfood() is Null was fooling it into thinking
that that was a possibility when it's not.

Also, use plain 1 and 0 instead of TRUE and FALSE when assigning
to the victual bit-fields.  The analyzer doesn't care but the type
was mismatched due to the cast to (boolean) hidden in their macro
definitions.
2023-01-21 01:52:04 -08:00
nhmall
8bbe9282aa add soundeffects hooks to core
Insert the calls to trigger a number of potential soundeffects
into the core.

If no additional soundlib support is integrated into the
build, then the Soundeffect macro (sndprocs.h) expands to nothing:

[#define Soundeffect(seid, vol)
]

If, however, at least one additional soundlib support is integrated
into the build, then the Soundeffect macro gets defined as this
in sndprocs.h:

[#define Soundeffect(seid, vol) \
    do {                                                              \
        if (!Deaf && soundprocs.sound_soundeffect                     \
            && ((soundprocs.sndcap & SNDCAP_SOUNDEFFECTS) != 0))      \
            (*soundprocs.sound_soundeffect)(emptystr, (seid), (vol)); \
    } while(0)
]

That macro definition checks for the hero not being Deaf; it checks
to ensure that the active soundlib interface has a non-null
sound_soundeffect() function pointer; and it checks to ensure
that the active soundlib interface has declared that it supports
soundeffects by setting the SNDCAP_SOUNDEFFECTS bit in its sndcap
entry. That just means that the interface routines are prepared to
accept and deal with the calls from the core, whether or not it
actually produces the desired soundeffect.
2023-01-20 14:20:08 -05:00
Pasi Kallinen
b1fd7344e3 Poly into fire elemental, eat flammable items 2023-01-20 18:56:01 +02:00
nhmall
b0a5c0ee0d quiet a new warning
src/eat.c(74,46): warning C4132: 'zero_victual': const object should be initialized
2023-01-17 19:59:24 -05:00
nhmall
c5cc631b13 comment typo: vicutal -> victual 2023-01-17 19:44:05 -05:00
PatR
2ca7916fdf maybe pacify static analyzer - eat.c
The complaint is that victual.canchoke might be used without having
been initialized.  I'm fairly sure that that isn't correct but get
dizzy trying to trace through the eating code.

This might improve the situation, or maybe not.
2023-01-17 16:31:59 -08:00