Commit Graph

392 Commits

Author SHA1 Message Date
nhkeni
9c0ed8ae63 NOSTATICFN for src/* 2024-03-14 17:41:51 -04:00
nhmall
688ac6ffbe remove register from variable declarations 2024-02-19 16:30:07 -05:00
Pasi Kallinen
0d7fc06eb9 Do garbage collection on luacore
Another lua state that is not freed until end of game,
so clean up the stack and do GC regularly.
2024-02-03 12:55:10 +02:00
Pasi Kallinen
3160112ece Accessibility: Show a message when monster is spotted
Adds a new boolean option, spot_monsters.  If on, every time
the hero notices a monster which was out of sight before,
a message is given.  Combine with accessiblemsg to get the
monster location:

(3north): You see a newt.

Breaks saves and bones.
2024-01-14 13:33:02 +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
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
nhkeni
9bcff7b896 Merge branch 'keni-luabits2' into NetHack-3.7 2024-01-04 10:40:27 -05:00
nhkeni
c7ab9a0565 Some lua catchup and cleanup
- add nhl_pcall_handle() to wrap all nhl_pcall calls that didn't check
  return value and either panic() or impossible()
- add --loglua (unix only) to dump Lua memory and steps info to livelog
- remove old logging
- set memory and step limits on all Lua VMs
2024-01-04 10:37:38 -05:00
PatR
1cfa966871 pull request #1143 - menustyle:Full 'A' choice
Pull request from entrez:  in the class filtering menu for multi-drop
and for loot in-or-out of a container, make choosing 'A' without any
other filter choices (such as all, specific class(es), cursed, unpaid,
just-picked-up, &c) become a no-op.

I started with the pull request and then undid much of it.  It would
have been simpler to start from scratch.  If you don't have option
paranoid_confirmation:AutoAll set, when choosing 'A' for all-without-
prompting as the only selection, operate as the PR has made things
work:  effectively, 'A' by itself is ignored and the operation ends
with nothing happening.

However, if you do have paranoid_confirm:A set, then continue treating
'A' by itself as if 'A'+'a':  everything.  Since paranoid confirmation
is specified, that will be followed by a confirmation prompt.

This also adds a context-sensitive hint to the menu about how the 'A'
entry works, shown every time when 'cmdassist' is On or just once (per
session) when that is Off.

The documentation probably needs some updating.

Closes #1143
2023-12-30 16:33:27 -08:00
Michael Meyer
56d5bf50e5 Ignore loot/multidrop 'A' if no filter specified
The 'A' option in the #loot or 'D'rop menu selecting every selectable
item when used on its own has been the cause of many bag of holding
explosions and other typo-related frustration.  Now that it operates on
other filters rather than overriding them, actually require some other
filter be selected for it to have any effect.  This means that 'A' on
its own will do nothing, but 'A'+'a' will still act like 'A' alone
previously did.  I think this will reduce the rate of serious typo
accidents in games, without being intrusive and while still maintaining
'A' as a useful option (which I think it is, in it's 3.7 incarnation --
I use it all the time in combination with other filters, especially
justpicked).
2023-12-30 14:18:44 -08:00
nhmall
9aa87aee05 static analyzer bit
Make it really obvious to the analyzer that we're only
calling canseemon(mcarry) when mcarry is not null.
2023-12-16 10:04:13 -05:00
nhmall
6467b983eb part2: remediate some nonnull-related compiler warnings
do.c:296:16: warning: nonnull parameter 'obj' will evaluate to 'true' on first encounter [-Wpointer-bool-conversion]
  296 |         while (obj && (otmp = obj_nexto_xy(obj, x, y, TRUE)) != 0) {
      |                ^~~ ~~
../include/extern.h:538:43: note: declared 'nonnull' here
  538 |                             const char *) NONNULLPTRS;
      |                                           ^
../include/tradstdc.h:378:36: note: expanded from macro 'NONNULLPTRS'
  378 | #define NONNULLPTRS __attribute__((nonnull))
      |                                    ^
1 warning generated.

invent.c:807:12: warning: nonnull parameter 'objlist' will evaluate to 'true' on first encounter [-Wpointer-bool-conversion]
  807 |     while (objlist) {
      |     ~~~~~  ^~~~~~~
../include/extern.h:1230:61: note: declared 'nonnull' here
 1230 | extern struct obj *merge_choice(struct obj *, struct obj *) NONNULLPTRS;
      |                                                             ^
../include/tradstdc.h:378:36: note: expanded from macro 'NONNULLPTRS'
  378 | #define NONNULLPTRS __attribute__((nonnull))
      |                                    ^
1 warning generated.

monmove.c:2091:23: warning: nonnull parameter 'mtmp' will evaluate to 'true' on first encounter [-Wpointer-bool-conversion]
 2091 |     boolean is_pet = (mtmp && mtmp->mtame && !mtmp->isminion);
      |                       ^~~~ ~~
../include/extern.h:1844:67: note: declared 'nonnull' here
 1844 | extern boolean undesirable_disp(struct monst *, coordxy, coordxy) NONNULLARG1;
      |                                                                   ^
../include/tradstdc.h:379:36: note: expanded from macro 'NONNULLARG1'
  379 | #define NONNULLARG1 __attribute__((nonnull (1)))
      |                                    ^
1 warning generated.

nhlua.c:2095:9: warning: nonnull parameter 'L' will evaluate to 'true' on first encounter [-Wpointer-bool-conversion]
 2095 |     if (L)
      |     ~~  ^
../include/extern.h:1985:35: note: declared 'nonnull' here
 1985 | extern void nhl_done(lua_State *) NONNULLARG1;
      |                                   ^
../include/tradstdc.h:379:36: note: expanded from macro 'NONNULLARG1'
  379 | #define NONNULLARG1 __attribute__((nonnull (1)))
      |                                    ^
1 warning generated.

steal.c:59:12: warning: nonnull parameter 'chain' will evaluate to 'true' on first encounter [-Wpointer-bool-conversion]
   59 |     while (chain && chain->otyp != GOLD_PIECE)
      |            ^~~~~ ~~
../include/extern.h:2910:43: note: declared 'nonnull' here
 2910 | extern struct obj *findgold(struct obj *) NONNULLARG1;
      |                                           ^
../include/tradstdc.h:379:36: note: expanded from macro 'NONNULLARG1'
  379 | #define NONNULLARG1 __attribute__((nonnull (1)))
      |                                    ^
1 warning generated.

utf8map.c:232:9: warning: nonnull parameter 'gmap' will evaluate to 'true' on first encounter [-Wpointer-bool-conversion]
  232 |     if (gmap) {
      |     ~~  ^~~~
../include/extern.h:3318:28: note: declared 'nonnull' here
 3318 |               long ucolor) NONNULLPTRS;
      |                            ^
../include/tradstdc.h:378:36: note: expanded from macro 'NONNULLPTRS'
  378 | #define NONNULLPTRS __attribute__((nonnull))
      |                                    ^
1 warning generated.

worn.c:895:15: warning: nonnull parameter 'objchain' will evaluate to 'true' on first encounter [-Wpointer-bool-conversion]
  895 |     if (on && objchain)
      |            ~~ ^~~~~~~~
../include/extern.h:3664:51: note: declared 'nonnull' here
 3664 | extern void bypass_objlist(struct obj *, boolean) NONNULLARG1;
      |                                                   ^
../include/tradstdc.h:379:36: note: expanded from macro 'NONNULLARG1'
  379 | #define NONNULLARG1 __attribute__((nonnull (1)))
      |                                    ^
worn.c:897:12: warning: nonnull parameter 'objchain' will evaluate to 'true' on first encounter [-Wpointer-bool-conversion]
  897 |     while (objchain) {
      |     ~~~~~  ^~~~~~~~
../include/extern.h:3664:51: note: declared 'nonnull' here
 3664 | extern void bypass_objlist(struct obj *, boolean) NONNULLARG1;
      |                                                   ^
../include/tradstdc.h:379:36: note: expanded from macro 'NONNULLARG1'
  379 | #define NONNULLARG1 __attribute__((nonnull (1)))
      |                                    ^
worn.c:908:12: warning: nonnull parameter 'objchain' will evaluate to 'true' on first encounter [-Wpointer-bool-conversion]
  908 |     while (objchain) {
      |     ~~~~~  ^~~~~~~~
../include/extern.h:3665:53: note: declared 'nonnull' here
 3665 | extern struct obj *nxt_unbypassed_obj(struct obj *) NONNULLARG1;
      |                                                     ^
../include/tradstdc.h:379:36: note: expanded from macro 'NONNULLARG1'
  379 | #define NONNULLARG1 __attribute__((nonnull (1)))
      |                                    ^
3 warnings generated.
2023-12-14 20:06:57 -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
Michael Meyer
d7d1c1476d Add option to exclude dropped items from autopick
This is based on a feature in UnNetHack (and I think some other variants
as well).  If the hero intentionally drops an item with 'pickup_dropped'
disabled, don't autopick it back up when walking over that square again.

Typically when the player drops an item, it's because she doesn't want
it in her inventory any more, and this option stops autopickup from
defeating that goal (especially useful for tasks like stash management
without a container).  Players have come up with workarounds to this
problem like toggling autopickup when approaching their stash pile or
adding name-based autopickup exceptions to allow them to exclude
individual items from autopickup, but this behavior should reduce the
need for those things.

I think 'pickup_dropped' is a little unfortunate because it suggests
equivalence to 'pickup_thrown' (i.e. any dropped items will be
automatically picked up regardless of autopickup exceptions).  Calling
it something like 'nopick_dropped' might be better, but as far as I can
tell options cannot start with the word 'no' because it's interpreted as
a negation of the rest of the option name.
2023-12-08 15:19:04 -08:00
PatR
275713b56e more source reformatting
Less extensive this time.  Contributed by entrez.
2023-12-08 12:15:24 -08:00
PatR
c41cb1a7fa source reformatting
Fixup some of the inconsistently formatted code that has been
introduced recently or been building up for a while.  Done manually.
I wasn't systematic except for looking for lines ending in '&' or '|'
(which wouldn't find such things if they're followed by a comment)
so there might be lots more.  I changed a bunch of C++-style //...
comments to old style C /*...*/ so that they'll match the rest of
the core's code rather than because they shouldn't be used.
2023-12-08 00:30:10 -08: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
Alex Smith
4a00b66b30 TDTTOE: oil has a higher boiling point and flashpoint than water
As such, it shouldn't be affected by the heat of the ground in
Gehennom (which is hot enough to boil but not to burn). The oil
still heats but won't break its bottle.
2023-12-02 14:25:09 +00:00
Alex Smith
6acf5a7784 Potions are often destroyed when dropped onto very hot ground
In Gehennom and on the Plane of Fire, the ground is hot enough to
boil potions (although not hot enough to, e.g., burn scrolls).
The potions sometimes survive this (almost always if it's your
potion, it's blessed, and you have maxed Luck), but often don't.

In addition to making a lot of flavour sense, this serves a
gameplay purpose in that it reduces the number of potions that
are deathdropped by monsters in the late game. In Gehennom,
monsters often generate with potions to use defensively, but then
get killed before they have a chance to use them: this produces a
surfeit of potions that players tend to convert into holy water or
potions of full healing (and in general it doesn't make much sense
that the basic potion of healing primarily generates in Gehennom).
This commit approximately halves the number of useful potion
deathdrops, whilst still allowing monsters access to their
potions; when the monster dies, it drops the potion and this has a
chance of destroying it.
2023-12-02 08:18:01 +00: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
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
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
852f8e4996 Dropping items disturbs buried zombies 2023-11-02 20:31:51 +02:00
nhmall
6cbefc7c2d Revert "granular verbose message suppression mechanics"
This reverts commit be76727265.
2023-10-29 20:39:07 -04:00
Pasi Kallinen
56159742c2 Prevent segfault for non-existent trap
If a buried zombie under stairs revived
2023-09-23 17:25:24 +03:00
PatR
8d60b92407 cleanup when exiting tutorial
When returning to play from within the tutorial, remove the level files
similar to how they're discarded for the rest of the dungeon when going
into the endgame.  It turned out to be a bit messier than anticipated.

The dungeon.c bit is sufficient for #overview, which now hides regular
level 1 while in the tutorial and hides all tutorial levels once exited.
Those will still appear in end-of-game disclosure.
2023-07-17 14:27:28 -07:00
PatR
0e97f8901a glyph_to_cmap() usage
I was looking to see what the impact of converting glyph_to_cmap() to
a function might have and noticed a couple of places where the macro
edition is passed a non-trivial argument.  Since it evaluates that
argument many times, there is hidden overhead.  Fetch the glyph once
and pass that to glyph_to_cmap().

This will no longer be very useful--but won't need to be reverted--if
PR #1022 gets incorporated.

do_positionbar() has bugs (only matters for MS-DOS).
2023-07-03 13:24:56 -07:00
PatR
bf47cc878e fountain and sink bookkeeping
This replaces most of commit 0ca2af4d8b
from a couple of days ago with something more robust.  That change
actually introduced redundant code that caused fountain and/or sink
count to be off instead of preventing it.

Revise set_levltyp() to update level.flags.nfountains and
level.flags.nsinks if setting the type to or from fountain or sink.
A bunch of places that were setting levl[x][y].typ directly needed
to be revised to use set_levltyp() instead.  set_levltyp() itself
hadn't been updated to handle LAVAWALL (to force such to be lit).
2023-06-12 15:07:34 -07:00
PatR
ee27ec97d1 tutorial tweaks
Replace tests against tutorial_dnum with 'In_tutorial()' predicate.

Give a message when entering the tutorial (via level change mechanism).

Likewise, give a message when resuming regular play.

If player uses #quit or ^C in the tutorial, ask whether to cut the
tutorial short and resume regular play; skip "Really quit?" if the
answer is yes.  Behavior is a bit odd for ^C + yes; it just sits there
until player types something.
2023-06-04 00:22:14 -07:00
PatR
2bbfed2183 fix github issue #1046 - tutorial anomalies
Reported by Noisytoot:  going from level tut-1 to tut-2 returned the
hero's starting equipment too soon, and exiting the tutorial from
tut-2 let the hero keep any equipment acquired within the tutorial.

Entering and leaving the tutorial was being handled by lua code in
the level description of tut-1 and adding a second level messed that
up.  I didn't see any way of handing that with level-specific lua
code so I made it become the core's responsibility.  gotolevel()
knows when the hero is moving from one dungeon branch to another so
it can recognize entry to or exit from the tutorial easily.

While fixing this, prevent #invoke of the Eye of the Aethiopica from
offering the tutorial as a candidate destination (was feasible if it
had been entered at start of game).

Not fixed:  levels visited in the tutorial become part of #overview.

Show location as "Tutorial:1" instead of "Dlvl:1" on status lines.
Only tested with tty; some interfaces handle location themselves and
may need their own fixup for this.

Fixes #1046
2023-06-03 16:39:12 -07:00
PatR
aa63aa8d98 issue #1027 - sticky 'nofollowers' flag
Reported by copperwater:  entering the tutorial sets 'u.nofollowers',
changing to the tutorial level saves a copy of 'u', post-level change
from entering the tutorial level resets u.followers, but subsequently
changing levels to return to the original level 1 restores 'u' from
the saved copy with has 'u.nofollowers==True', overriding the reset.

Move the nofollowers flag from 'u' to 'iflags'.  Invalides save and
bones files.

Fixes #1027
2023-05-25 17:08:53 -07:00
PatR
7737fcc97c fix out of date safe_teleds() calls
When safe_teleds() was changed to take an int flags argument instead
of a boolean, some calls weren't updated.
2023-05-11 12:12:12 -07:00
Pasi Kallinen
8c8acee423 Fix hero trapped in nonexistent pit
If hero was trapped in a pit, and a monster threw a boulder
at that location, the boulder filled the pit but hero was still
trapped in it.
2023-05-11 16:00:57 +03:00
PatR
654b7d41b2 fix #K3907 - reviving buried corpse
Burying an olog-hai corpse with a boulder resulted in a panic when
its time to revive occurred.  I was able to reproduce this once but
failed with "you feel less hassled" several times (using same save
file for multiple tests) so I'm not quite sure what was happening.

A buried corpse was allowed to revive if it was for a zombie.  This
fix extends that to auto-revivers (trolls and Riders).  The corpse
keeps its revive_mon timer rather than changing that to zombify_mon.

If/when revival of a buried troll or Rider happens while in view, it
will "claw itself out of the ground" like zombies do.
2023-05-02 18:02:02 -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
Pasi Kallinen
80a8eaf7e6 Prevent calling doaltarobj twice
My change to make items thrown by monsters landing on altar
caused doaltarobj being called twice when hero dropped an item
on it. Call the newer instance only when monsters are moving.
2023-04-23 07:47:46 +03:00
Pasi Kallinen
b61aa235c7 Items thrown by monsters landing on an altar 2023-04-08 21:24:10 +03:00
Pasi Kallinen
e37428d5cd Fix fuzzer teleporting out of Fort Ludios 2023-03-18 08:51:37 +02:00
Pasi Kallinen
4799fc937a Add level flag for plane of fire fumaroles
Also reduce the size of the gas clouds.

Breaks saves and bones.
2023-03-17 19:36:00 +02:00
nhmall
ecf74d5308 some pline()-like function usage 2023-03-08 19:12:52 -05:00
Pasi Kallinen
db0441bf02 Split level temperature message into function 2023-03-05 12:34:33 +02:00
Pasi Kallinen
3cd6b00ab7 Split stuck-cannot-go-up/down into separate function 2023-03-05 11:58:23 +02:00
Pasi Kallinen
fc7a32b86e Tutorial level
Add a tutorial level to teach commands to new players.
Very much a WIP.

Breaks save and bones compat.
2023-03-01 14:00:29 +02:00
Michael Meyer
51c0221383 Fix: 'A'+'P' regression when dropping by type
Selecting both 'P' (the just-picked-up items category) and 'A' (the
'auto-select relevant items' flag) when dropping items by type with 'D'
was automatically dropping every item in inventory instead of only items
that were marked as just having been picked up.  Basically, it was
causing 'A' to act like it did before b65c93c amended its functionality.

This commit is more-or-less identical to 991e739, both in terms of the
problem and the fix, except that it applies to dropping items instead of
looting.
2023-02-09 15:34:09 -08:00
nhmall
28cd188259 resolve 5 analyzer warnings if no SND_LIB_* define 2023-01-20 17:32:55 -05: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
bb8656c190 Move familiar level message into function 2023-01-18 23:33:21 +02:00
Pasi Kallinen
bb8c144809 Level temperature
Allow setting a per-level "temperature": hot, cold, or temperate
via special level flags. Currently it only affects some messages
in Gehennom, but it could be expanded to ice melting, water freezing,
or monster generation, for example.

Invalidates saves and bones.
2023-01-17 20:11:45 +02:00
Pasi Kallinen
eacb68666e Deadly afflictions and resistances for safe_wait
Amend the safe_wait so it still waits if you have a deadly property,
even if you have a resistance to it.

External resistances do not protect against already existing
deadly properties, for example becoming deadly ill is not cured
even if you wear a green dragon scale mail.
2023-01-12 23:19:28 +02:00