Commit Graph

627 Commits

Author SHA1 Message Date
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
9c0e47785a digging in ice
If the spot in front of a closed drawbridge was ICE, digging there
had issues....
2024-11-27 08:41:55 -08:00
nhmall
1dbba0f63b rename IS_ROCK() macro to IS_OBSTRUCTED()
It has included trees since they were added, so give it a
more fitting name.
2024-11-09 11:12:42 -05:00
nhmall
e863583c56 iterating gi.invent (github issue #1315)
GitHub issue #1315 points out that it is possible for
a downstream function to change an object's nobj field
to point to a completely different chain.

The cited example by @vultur-cadens was:

     for (obj = gi.invent; obj; obj = obj->nobj)
         if (obj->oclass != COIN_CLASS && !obj->cursed && !rn2(5)) {
             curse(obj);
             ++buc_changed;
         }

    curse() drops the weapon with drop_uswapwep(),
        which calls dropx(),
            which calls dropy(),
                which calls dropz(),
                    which calls place_object().

place_object alters the nobj pointer, to point to the floor chain:
    otmp->nobj = fobj;
    fobj = otmp;

The result was that the next loop iteration was then using floor
objects from the floor chain.

This alters several for-loops to use a more consistent approach,
particularly when the obj is being handed off to a function,
where a downstream function might, or might not, alter the nobj
field.

References:

https://github.com/NetHack/NetHack/issues/1315
https://www.reddit.com/r/nethack/comments/1gkc9ub/even_if_you_drop_an_item_before_drinking_from_the/
2024-11-06 16:59:51 -05: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
0dad60e485 fix github issue #1291 - water walking vs lava
Issue reported by ars3niy:  non-fireproof water walking boots are
supposed to be destroyed if worn on lava, but a post-3.6 change
made that only happen if the hero died and left bones.

The boots remained intact if hero was fire resistant or survived
6d6 damage.  Staying intact should only happen if they're fireproof.

This seems to work but each time lava_effects() gets modified it
becomes more fragile.  Having deleted objects stick around doesn't
help with this problem, which is to keep an item which is being
stolen--and whose loss causes the hero to drop into lava--from
being burned up before being transferred to the thief's inventory.

Fixes #1291
2024-09-26 08:10:26 -07:00
PatR
993c3b303f some reformatting (4 of 4) 2024-09-05 16:49:42 -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
PatR
a33f1edd24 YMonnam(monst)
Replace several upstart(y_monnam(mon)) with new YMonnam(mon) to
produce "Your little dog" and such.

Also change one or two Monnam(mon) to YMonnam(mon) and one pline(...)
to pline_mon(mon, ...).
2024-07-04 14:27:28 -07:00
Pasi Kallinen
89ea47f702 Monsters can track hero through fixed teleport traps
Also make fixed teleport traps always trigger when entered.
2024-06-15 18:44:30 +03:00
Pasi Kallinen
951401e52a Allow fixed-destination teleport traps
Add a theme room with multiple visible teleportation traps
which will always teleport to specific locations in the same level.

Teleport trap change from xNetHack by copperwater <aosdict@gmail.com>.
2024-06-14 19:50:20 +03:00
Pasi Kallinen
a72b95e4bc Accessibility: more message locations
Add a new pline_mon() which sets the message location
to the monster location.

Add locations to several trap messages.
2024-06-13 19:04:33 +03:00
PatR
6718a8af1f fire_damage() vs containers
Containers can't become fireproofed so the line of code in
fire_damage() which tested for that led to confusion.

Also, add missing handling for statues as containers.
2024-06-08 15:22:08 -07:00
Pasi Kallinen
2ba42cf78c Fix accessing freed landmine trap
Landmine blew up, scatter exploded a potion of oil, which melted
the ice on which the landmine was, resulting in the landmine trap
being deleted.  The code then tried to access it to make a pit.
2024-05-31 10:28:44 +03:00
Pasi Kallinen
5b94745658 Fix only flying monsters able to evade some traps 2024-05-30 17:51:56 +03:00
PatR
5641e2560f fix issue #1248 - drowning on Plane of Water
Issue reported by Umbire:  if hero dies by drowning on the Plane
of Water, cause of death was reported as "drowning in a limitless
water".

Reported for livelogging but applied to tombstone and logfile too.
Omit the article "a" in this situation.

For 3.6.7, it would have started as "drowning in a water" and been
updated on the fly to be "drowning in deep water".  3.7 changed
terrain type WATER to be "wall of water", where "a" is expected,
and also added "limitless water" for Plane of Water, but it was
neglecting to include a similar fixup for the latter.  The "deep
water" fixup is still present but doesn't get triggered anymore.

Fixes #1248
2024-05-29 14:24:10 -07:00
Pasi Kallinen
61e54c2a87 Fix monster hp being above max hp
If the monster took damage from a fire trap, got killed, and then
lifesaved, the trap effect then reduced the map hp below the hp.
2024-05-28 20:58:03 +03:00
Pasi Kallinen
2ebbd13f79 Fix boulder over a hole or a pit dug by a monster
When a monster digs down and creates a pit or a hole,
drop the boulder at the location into it.
2024-05-28 19:10:36 +03:00
Pasi Kallinen
ed5c7114ab Untrapping containers or doors gives some experience 2024-05-08 20:10:32 +03:00
Pasi Kallinen
b76a96bf40 Add missing break
A rolling boulder hitting a wall or a tree could keep going,
possibly going out of map bounds
2024-04-22 14:46:18 +03:00
Pasi Kallinen
00d0700e75 Pit fiends can easily climb out of pits 2024-04-12 11:13:24 +03:00
Pasi Kallinen
defb5d5f80 Pets considered any noise made by hero as whistling
In 3.6.2 parts of the wakeup code were merged together, and this
caused pets consider any noise made by the hero - such as hitting
iron bars or digging - as whistling for them to come to the hero.

Change it to only consider actual whistling and ringing a bell.
2024-04-03 12:46:15 +03:00
PatR
e4ffda7386 blanking novels
Simplify converting novels into blank spellbooks via water damage.
Since that can occur, update cancellation to do it too.
2024-03-28 23:44:34 -07:00
Pasi Kallinen
f131942dd2 Another tamedog message
Give a different message when a peaceful creature was tamed.
Allow suppressing this and the previous message, when the caller
handles messaging.
2024-03-24 10:48:29 +02:00
nhkeni
54c3dd35ac Merge branch 'keni-staticfn' into NetHack-3.7 2024-03-16 09:38:21 -04:00
nhkeni
9c0ed8ae63 NOSTATICFN for src/* 2024-03-14 17:41:51 -04:00
PatR
68312f7feb magic trap uncursing vs scroll of remove curse
Reported directly to devteam:  if a magic trap gave its uncurse
effect, scroll of remove curse could become discovered.

Turns out that it would happen if hero was wielding a stack of
unholy water potions.  It didn't matter whether they were known
as water or known to be cursed or whether hero was carrying any
scrolls of remove curse.
2024-03-13 12:39:50 -07:00
nhmall
6d22361fca separate function for acid potion damage pr#1195
Also includes a couple of trailing whitespace removals.
2024-03-09 09:25:43 -05:00
nhmall
2bda94e982 Merge branch 'pot-acid-damage' of https://github.com/argrath/NetHack into NetHack-3.7 2024-03-09 09:23:20 -05:00
RainRat
a3658f85ac fix typos 2024-02-28 20:15:56 -08:00
PatR
9f7fffc823 rolling boulder trap fix
The recent "trap.c reformatting" commit included a non-formatting
change switching from gb.bhitpos.x,.y to local x,y in the rolling
boudler trap routine.  The part of that routine used when a rolling
boulder hits another boulder and transfers its remaining momentum
to that other one got switched to wrong x,y and the first boulder
basically kept going, possibly hitting itself at each new position.
2024-02-22 11:00:18 -08:00
Erik Lunna
eb22a81088 Refactor, unify, and nerf item destruction
Note: Original change is from xNetHack by copperwater <aosdict@gmail.com>,
      but this commit comes from HACKEM-MUCHE by Erik Lunna, with
      some minor code formatting.

From xNetHack commit a0a6103bea:

'The original goal: nerf item destruction using a method I initially
 proposed for SpliceHack, in which the number of items subject to
 damage from any single source is limited by the amount of damage the
 effect caused. The intent was to be more fair all around and prevent
 aggravating situations where, for instance, a chest shock trap zaps
 you for 4 damage and immediately ten of your rings and wands blow up.

 Problem 1: no easy way to limit the items destroyed without biasing
 heavily towards the start of the invent chain. The old code was able
 to get away without bias by just indiscriminately destroying
 everything eligible with a 1/3 chance. Here, I had to introduce
 reservoir sampling in a somewhat more complex form than I've applied
 it elsewhere, since there are a pool of potential items.

 Problem 2: destroy_item no longer worked remotely like destroy_mitem,
 which still destroyed 1/3 of items indiscriminately. Commence the
 process of squishing them into one function that handles both the
 player and monsters. (Which required making a lot of adjustments to
 destroy_one_item, now named maybe_destroy_item, on nits such as
 messaging and when to negate damage. An annoying consequence of the
 merge is that in the player case, their HP is deducted and they can
 be killed directly, but for monsters they need to add up the
 destruction damage and return it.)

 Unifying destroy_item and destroy_mitem has some advantages: in
 addition to the obvious code duplication removal, it ensures monsters
 now take the same damage as players for destruction (previously they
 took a piddly 1 damage per destroyed item). Now when you hit
 something with Mjollnir and their coveted wand of death breaks apart
 and explodes, you at least get the satisfaction of knowing they took
 the standard amount of damage from it.  Monsters also now get
 symmetry with players in having extrinsic elemental resistance
 protect them from item destruction, and damage negation from item
 destruction if they were appropriately resistant.

 Problem 3: a lot of callers didn't preserve the "amount of incoming
 damage" that this refactor relies on. E.g. if the defender resisted
 that element, the local dmg variable would be set to 0. So I had to
 do some wrangling with callers to save that original damage
 value. The rule of thumb is: all *incoming* damage counts. So that
 includes the player's spellcasting bonus if applicable, but not
 things like half damage, negation due to resistance, or extra damage
 due to being vulnerable to cold/fire.

 Then I figured, while I'm here let's get rid of all those silly cases
 where destroy_items is called multiple times for various different
 object classes, and cut the object class parameter out of it. This
 has a few minor effects:

 - Places where different object classes previously rolled
   independently for destruction to happen at all now roll
   once. (Which, by my calculation, generally means less incidences of
   destruction - a fire attack now won't have three separate chances
   to hit your scrolls, potions, and spellbooks. On the flip side, a
   lucky roll will no longer save an entire object class in your
   inventory.)

 - Callers can no longer specify different probabilities for
   destroying different object classes. The only place this was really
   used was to call destroy_item with a slightly lower probability on
   SPBOOK_CLASS.  With the nerf in this commit, less of them ought to
   be destroyed anyway.

 - A very edge case of where explosion-vs-monster damage was totted up
   differently for golems, which could result in differences of a hit
   point here or there.

 - All object classes being processed in one go means that less items
   are destroyed than would be if they were still processed
   independently.  This is not really visible compared to the old
   baseline of just destroying 33% of everything, but would be a
   marked difference versus a copy of the game that still called
   destroy_items separately for different object classes. To
   compensate, I adjusted my planned damage-to-destruction-limit
   scaling factor down from 8 to 5.

 Not done: merging in ignite_items(), though that would probably be
 really easy now.'

Notes from porting from xNetHack:

- It might be necessary to reexamine at all the conditional checks for
calling destroy_items. Because item destruction is much more
restrained and uses the actual damage from an effect, we might now
need to check 'if (!rn2(3))' and similar in all the places item
destruction occurs.
2024-02-20 22:03:54 +02:00
nhmall
688ac6ffbe remove register from variable declarations 2024-02-19 16:30:07 -05:00
PatR
c84dc79610 trap.c reformatting
Monstly changing '<type>* <var>' to '<type> *<var>'.  Wrap or shorten
a few wide lines.

One of the rolling boulder routines accessed gb.bhitpos.x,y many times;
change that to use local x,y instead.
2024-02-19 11:11:23 -08:00
PatR
d688309012 openholdingtrap() message sequencing
If a trap is blocking levitation or flight and you use wand of opening
or spell of knock to get out, you'd get things like
|You start to float in the air!
|You are released from the bear trap.

Give the release message before the actual untrapping.
2024-02-18 11:18:48 -08:00
PatR
9326f80ecc lava_effects() bit
lava_effects() item destrunction had the logic for handling Book of
the Dead wrong.  (However, that didn't matter since the obj_resists()
check earlier would prevent it from being burned up.  Fix it anyway.)
2024-02-09 15:52:17 -08:00
PatR
061c2ab1b1 fix #K4098 - lava burns up item being stolen
Three months ago to prevent an "object lost" panic situation when
stealing an item that let hero survive water (several candidates)
would result in drowning, remove_worn_item() was changed to flag the
item being removed as in_use and emergency_disrobe() was changed to
avoid dropping in_use items while drowning.  That seemed to work ok.
But for lava instead of water, in_use is a flag to destroy the item
(set in advance, before issuing messages that can give the player a
chance to trigger a hangup save).  So instead of keeping the item
around for theft to finish, it was deallocating it.  steal() would
format the freed object and then access some of its fields, leading
to havoc.

This adds a hack to allow one item already flagged as in_use to be
treated differently by lava_effects() from the ones it flags for
destruction.  This also seems to work ok, but we may need to start
putting freed items on a deferred deallocation list similar to how
dead monsters are kept around for the rest of the current move.

The fix/hack has revealed two more bugs that this doesn't address.
An item being stolen is removed without any message, then if that
removal doesn't kill the hero a theft message is given.  The message
sequencing is wrong.  Flying hero who loses amulet of flying just
gets affected by lava; player is only told why after life saving.

The other issue is that life-saving from lava can teleport the hero
to where the thief can no longer be seen, yielding "It steals <item>"
even though "It" was visible when the theft started.
2024-02-04 15:40:00 -08:00
Pasi Kallinen
829f9f65f7 Split out harmless-to-monster trap
Also make the code much easier to understand, and
more-or-less match hero trap triggering.
2024-01-23 19:01:34 +02:00
PatR
bba6942082 remove unused variable 2024-01-22 17:10:14 -08:00
Michael Meyer
a3e8d8eacb Clean up trapeffect code a little bit
Some minor cleanup of artifacts from the splitting up of trap effects
into the various trapeffect_foo functions: consolidate redundant
variables in trapeffect_pit (tt vs ttype), and simplify the definition
of 'inescapable' traps a couple functions (since the functions are now
specialized to a particular trap, it's unnecessary to check ttype
there in determining whether it's an inescapable Sokoban pit or hole).
2024-01-22 17:02:59 -08:00
PatR
13ff565a67 github issue #1201 - Forcefighting webs
Issue reported by Umbire:  suggestion to always destroy adjacent webs
via 'F'<dir> if wielding Sting or Fire Brand.

Sting already did that; this adds Fire Brand.

This also augments the #untrap command when wielding either of those,
or any other blade.  And rephrases successful untrap message
"You remove {the or your} {bear trap or webbing} from Fido." to
"You extract Fido from {the or your} {bear trap or web}." since the
trap remains intact.

Forcefight and #untrap against webs ought to be reconciled to remove
[some of] their differences and/or share code.  But not by me...

Closes #1201
2024-01-21 11:58:44 -08:00
Pasi Kallinen
57747535af Add m_next2u, analogous to m_next2m and next2u 2024-01-19 21:53:25 +02:00
nhmall
25a8c258e6 replace x >= LOW_PM with ismnum(x) shorthand macro 2024-01-11 14:01:10 -05:00
SHIRAKATA Kentaro
6ff799d4f9 split damage from acid potion into separate function 2024-01-09 22:45:23 +09:00
Mika Kuoppala
0ca1a1ca8e src/trap: Fix isclearpath out of bound access on levl array
Do isok check apriori to accessing the levl array to filter
out dx/dy that have grown too large.

This fixes:
trap.c:3455:19: runtime error: index 80 out of bounds for type 'rm [80][21]'
2024-01-09 01:18:17 +02: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
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
Pasi Kallinen
dc8d9d6cd0 Accessibility: Add location info to messages
Adds a new boolean option, accessiblemsg.  If on, some game messages
are prefixed with direction or location information, for example:

   (west): The newt bites!
   (northwest): You find a hidden door.

I added the info to the most common messages, but several are
still missing it.
2024-01-02 18:59:25 +02:00
nhmall
0927726900 static analyzer bit for trap.c
src/trap.c(5794): warning: Dereferencing NULL pointer 'which'.
2023-12-27 11:13:22 -05:00
nhmall
e9e05db113 add a pair of shorthand macros to validate an index into an array
Two variations:

IndexOk(idx, array)       validate that idx is a valid index into the array

IndexOkT(idx, array)      validate that idx is a valid index into the
                          array, excluding the final Terminator element
2023-12-23 13:46:54 -05:00