Commit Graph

311 Commits

Author SHA1 Message Date
Pasi Kallinen
37168ab188 Boomerangs can hit multiple monsters
The number of monsters it can hit depends on the enchantment.
2026-02-04 22:35:22 +02:00
Alex Smith
09b879d7ad Give a message when throwing ammo without a launcher
This is primarily intended to help new players understand the
mechanics (the "wield the launcher, throw the arrow" sequence may
be unfamiliar to newer players), so the message is worded to
indicate the correct way to use the ammo.
2026-01-10 20:00:59 +00:00
Alex Smith
fce66245ca Don't attempt to cache encumber_msg result
There was only one point in the code at which this caching was
being done, and it was incorrect: it's possible for the result of
near_capacity to change during a monster turn because monster
actions can change either inventory weight or carry capacity.

The bug was particularly relevant in cases where a character
polymorphed into a slow weak monster gets attacked by a monster
that moves at normal speed: due to the polyform being slow, the
normal-speed monster gets in a lot of attacks and causes a
rehumanization, but due to the polyform being weak, it was
burdened at the start of the monster turn, and so when that
penalty is (due to the bug) applied to the next turn it can
mean that the character misses the next turn too, and may end up
dying as a result.
2025-11-24 02:07:23 +00:00
PatR
34d0e956ed fix issue #1453 - throwing crackable object upward
Issue reported by NullCGT:  throwing a crackable item against the
ceiling would cause it to vanish if it became [more] cracked but not
yet fully shattered.

Fixes #1453
2025-10-13 23:02:56 -07:00
PatR
9f04269ec4 couple of formatting bits 2025-04-20 17:18:49 -07:00
nhmall
a943c4c10b replace some weight-related magic numbers
adds a header file include/nhconst.h  (I'm open to a better name)
2025-03-19 13:29:58 -04:00
nhmall
8c0c33aa1f another follow-up bit 2025-03-17 08:09:00 -04:00
nhmall
0bdf9830e6 throw-and-return weapons used by monsters
Resolves #1338
2025-03-16 15:37:49 -04:00
SHIRAKATA Kentaro
d2af1afb52 split "swallowit" on throwit() into a separate function 2025-03-04 21:31:17 +09:00
PatR
d8d4f18a00 analyzer lint for do_wear.c, dothrow.c 2025-01-19 11:23:05 -08:00
PatR
bbb4bfa938 fix issue #1337 - 'fireassist' vs 'f'iring aklys
Issue reported by elunna:  if the 'fireassist' option is on and the
quiver contains ammo, 'f' while wielding an aklys switches to the
ammo's launcher instead of throwing the aklys.

Fixes #1337
2024-12-13 12:30:48 -08:00
Pasi Kallinen
cbb0f9079d Wand of striking strikes the ground
... if dropped while levitating/flying.
2024-12-09 14:36:14 +02:00
Pasi Kallinen
57abae29e8 Don't switch away from polearm if monster in range
Using 'f', if hero is wielding a polearm, and a monster is in range,
don't switch away even if we do have ammo in quiver and a launcher
in the inventory.
2024-12-08 22:19:36 +02: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
5c0834e9d9 hurtle_step() streamlining
Eliminate some code duplication in hurtling.
2024-11-27 10:32:09 -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
Pasi Kallinen
d746060d6e Boomerangs should not mulch
I think this is a regression, but I didn't bother compiling an older
version to check.
2024-09-28 17:50:14 +03:00
PatR
aa043f0ddf some reformatting (2 of 4) 2024-09-05 14:51:21 -07:00
SHIRAKATA Kentaro
82e6eacfbb split returning from throwit() into separate function 2024-07-13 19:38:23 -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
2bec685bae Pyrolisk eggs explode when broken 2024-06-02 10:50:58 +03:00
Pasi Kallinen
472cb7f7fa Prevent throwing gold out of the map 2024-04-25 12:39:02 +03: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
9c0ed8ae63 NOSTATICFN for src/* 2024-03-14 17:41:51 -04:00
PatR
4af03d8ef8 fix garbled comment
The prolog comment for hurtle() ends with
 * dx and dy should be the direction of the hurtle, not of the original
 * kick or throw and be only.
The clause "and be only" is incomplete and was added sometime between
3.3.0 and 3.4.0.

I suspect it was meant to say "and be only -1 or 0 or +1" but the code
enforces that with sgn(dx) and sgn(dy) so if that's the case, it isn't
necessary.  Whether that guess is right or wrong, remove the clause
since as it stands now, it makes no sense.
2024-03-08 23:34:12 -08:00
nhmall
688ac6ffbe remove register from variable declarations 2024-02-19 16:30:07 -05:00
nhmall
25a8c258e6 replace x >= LOW_PM with ismnum(x) shorthand macro 2024-01-11 14:01:10 -05:00
Mika Kuoppala
91781ef0a6 dothrow: Check for LOW_PM before accessing mon array
on toss_up() when checking for touch_petrifies, add
a check for corpsenm >= LOW_PM as EGG can be without
corpse reference.

This prevents:
dothrow.c:1266:29: runtime error: index -1 out of bounds for type 'permonst [384]'
2024-01-10 17:26:38 +02:00
nhmall
70dcab833d remove obj guard from stone_missile(obj) macro
Checking the callers:
toss_up() would have segfaulted prior to use of stone_missile() if obj were NULL.
thitu() now has a guard prior to use of stone_missile()
ohitmon() would have crashed from earlier dereference otmp->dknown if it were NULL,
   otmp arg is declared nonnull
thitm() now has a guard prior to use of stone_missile().
hmon_hitmon_do_hit() null obj takes a different code path than the code path
    using stone_missile(); comment asserting that added
2023-12-16 07:58:44 -05:00
Michael Meyer
1736f3caaa Add 'pickup_stolen' option
Add pickup_stolen option to autopick items stolen from you by a nymph or
monkey, even if they don't match your normal autopickup settings.
Replace was_dropped, was_thrown with a 2-bit bitfield that can contain
values LOST_DROPPED, LOST_THROWN, and LOST_STOLEN (or 0), since they
should all be mutually exclusive anyway as they track the most recent
way the item left the hero's inventory.

[Rebase/merge conflict fixed up.  PR]
2023-12-08 15:19:54 -08: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
nhmall
85e08c4034 splash 2023-11-25 21:14:22 -05: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
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
Michael Meyer
5ba7939110 Fix: hurtling into wall of water
A hero hurtled into a wall of water while levitating, flying, or wearing
water-walking boots wouldn't be stopped by it unless it was on the Plane
of Water.  Make it stop hurtling heroes immediately no matter the
location.

I also noticed that once I was hurtled safely into the wall of water, it
was described as a "pool" when I examined it with ':'.  Fix that, too,
even though I think it shouldn't really be encountered in-game.
2023-11-03 11:04:34 -07:00
nhmall
6cbefc7c2d Revert "granular verbose message suppression mechanics"
This reverts commit be76727265.
2023-10-29 20:39:07 -04:00
Michael Meyer
602af21ca3 Have leader keep already-used invocation items
The other suggestion from Pat about potential extensions to bda0b3b.  I
think it's interesting from a story perspective, and hopefully nobody
will run into this by mistake when they hoped to use the Candelabra as a
light source later!  The specific language used by the leader could be
changed if someone has a better idea (as could the code itself, for that
matter).
2023-09-22 21:40:12 -07:00
Michael Meyer
dedf1ade18 Have quest leader ID thrown unknown fake Amulet
If the hero throws an unidentified fake Amulet of Yendor at the quest
leader, the leader will identify it and toss it back, similar to the
behavior for the real Amulet.

This was one of Pat's suggestions for continuing in the same key as
bda0b3b; I think this makes a lot of sense, especially now that people
may be encouraged to throw things called "Amulet of Yendor" at the quest
leader.  Arguable about whether a _known_ fake Amulet should still anger
the leader and quest helpers; as I have it in this commit, it will, but
I'm somewhat ambivalent about what makes more sense.
2023-09-22 21:40:12 -07:00
PatR
14c7b2015d PR #1093 - quest leader vs thrown invocation items
Pull request from entrez:  if hero throws (or kicks) an invocation
item or the Amulet at the quest leader, identify it and give it back
instead of treating the throw (or kicked item) as an attack.

In addition to the fixes entry I've made several tweaks to related
code, mostly to refer to the leader as "Someone" rather than "It" if
unseen.

Closes #1093
2023-09-20 12:10:57 -07:00
Michael Meyer
bda0b3b807 Allow quest leader to catch and return unique item
It's been possible for a while to throw your quest artifact to your
quest leader, completing the quest (he will then throw the object back
to you).  The quest leader will also react to being brought the Amulet
of Yendor (i.e. having it in inventory when you approach or #chat), but
tossing it over like the quest artifact was treated as a hostile act and
would cause the quest leader and guardians to become hostile and attack
the hero.

Make throwing the Amulet of Yendor at the quest leader work like
throwing the quest artifact, and treat the invocation items similarly
just in case people try throwing those (maybe because they are lost,
unsure what to do, and have already seen their quest leader catch and
react to the quest artifact -- regardless of the reason, throwing over
the Book of the Dead is almost certainly not intended to be an attack).
Doing so for invocation items will ID them but not do much more than
that.  The Amulet of Yendor triggers the existing quest pager message.
2023-09-20 11:00:32 -07: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
PatR
e9c58c2fe4 breaking crystal armor
Instead of a 5% chance for crystal plate mail or crystal helmet to
break each time it's subjected to breakage, switch to a 10% chance
but the damage is treated as erosion rather than break/don't-break.
'crystal foo' will need to go through four stages of damage before
breaking:  cracked crystal foo, very cracked crystal foo, thoroughly
cracked crystal foo, then gone.  Crackproof handling is included,
described as tempered crystal foo.

It mostly still applies to throwing and kicking the item.  Having
some hits trigger damage might be worthwhile but isn't implemented.

Object creation within lua code probably needs to be updated, and
when the Mitre of Holiness is created in the priest/priestess quest
it should start out as tempered (erodeproof).  Perhaps it ought to
be erodeproof regardless of where/how it's created.
2023-06-14 15:54:04 -07:00
PatR
450f060132 github issue #1060 - crystal helmet
Issue reported by vultur-cadens:  changing helm of brilliance to
crystal made it stop being classified as "hard helmet" so it gave
less protection against things falling onto the hero's head.

Change the is_metallic() tests used on helmets to new hard_helmet().
Unlike when thrown, crystal helmets don't break when objects fall
on them.

Fixes #1060
2023-06-14 06:13:11 -07:00
PatR
41c8a18d3d hurtling monster bumping into hero
Typo/thinko resulted in passing wrong monster variable to x_monnam().
2023-05-05 17:50:57 -07:00
PatR
53adba6602 maybe fix #K3909 - hurtled monster detached twice
I haven't forced a test case to verify this, but the logic for
calling mliquid() at the end of mhurtle() was clearly wrong.

Also, implement missing case of one monster causing another to
hurtle and hit the hero.  Compiles but is otherwise untested.
2023-05-03 12:18:15 -07:00
PatR
7778d91193 fix for breaking a crystal helm
Avoid impossible warning "breaking odd object?" when throwing a helm
of brilliance causes it to break.  Presumably dropping one while
levitating or zapping one of the floor with striking/force bolt would
yield similar result.

While in there, reduce the chance of breakage from 99% to 5% for both
helm of brilliance and crystal plate mail.
2023-05-03 05:30:51 -07: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
826ce951e7 get rid of NetHack macro conflict with curses routine delay_output() 2023-04-21 08:25:53 -04:00
nhmall
de79240dea some comment spelling fixes 2023-03-16 22:27:01 -04:00
PatR
74ed2999de knockback feedback
Adjust the message given when an attack knocks its target back.  Say
|<defender> is knocked backward by <attacker>
if target will actually move or
|<defender> is knocked back by <attacker>
if there's something preventing the move.  Most players probably won't
even notice the difference.  (Possibly "rocked back" would be better
when not changing location but this hasn't gone that far.)

Also make the knock back distance be 1 step 2/3 of the time or 2 steps
1/3 instead of 50:50 chance for 1 or 2 steps.
2023-03-11 11:21:09 -08:00