Commit Graph

10637 Commits

Author SHA1 Message Date
nhmall
f9cebc5890 avoid a warning with Xcode build 2026-03-22 11:33:26 -04:00
Pasi Kallinen
8e4c7f9fb5 Change some command keys
Change 'v' from #versionshort to #chronicle.
Change 'V' from #history to #versionshort.
History can still be accessed either directly with the extended command,
or via the help menu.
Versionshort now accepts the m-prefix, and then shows the longer version.
2026-03-21 17:56:37 +02:00
nhmall
1eadfa962d don't include size_t * and time_t * in _Generic for now
There are behavior differences with macOS and other plaforms that
would need to be addressed if they were included.
2026-03-21 11:11:28 -04:00
Pasi Kallinen
9fc1514253 Amulet of magical breathing increases energy regen
Normally energy regen is 1d2 or 1d3, so wearing the amulet increases
that to 1d4 or 1d5.  The only way to get energy regeneration is via
The Eye of the Aethiopica, so you cannot have both at the same time.
2026-03-21 13:20:14 +02:00
Pasi Kallinen
63a78edcfa Add toggle extended command
Allows the user to configure a key binding to toggle any boolean
option, for example:

BIND=':toggle(price_quotes)
BIND=v:toggle(autodig)

The option must be settable in-game.
2026-03-21 12:17:37 +02:00
Alex Smith
62a50413d3 New debug command #wizobjprobs for listing item probabilities
As of the change to allow for item probabilities that don't add up
to 1000, it's become a little difficult to figure out the exact
probabilities from the source code, which makes it hard to balance
item generation. Adding a tool to list the probabilities helps.

Part of the problem is that changing an item's probability without
balancing it elsewhere is usually wrong: doing that would in effect
take the probability equally from (or add the probability equally
to) all other items in the class, which might break the balancing
of those items due to the probability change.

As such, it is usually better to make an intentional decision about
which items should be less and which items should be more likely to
generate, then change them in a balancing way (meaning that the
probabilities of objects that weren't intentionally changed remain
unchanged). Doing a complex such change makes arithmetic errors
fairly likely, though, so it's useful to have a command that verifies
that it's been done correctly.

This command is primarily intended as a development aid, so it's
included only in debug builds and pre-release builds (the same as
other similar commands like #wizmondiff).
2026-03-21 05:05:48 +00:00
Alex Smith
26fd5e7d73 Armor probability tweaks
Armor is now slightly more likely to generate outside Gehennom (at
the expense of gems that generate via random generation rather than
mineralisation or level rules).

Basic nonmagical armor (especially body armor) has had its generation
probabilities reduced *relative to other armor*, but outside
Gehennom, it is no less likely to generate (because armor in general
is now more likely to generate outside Gehennom). It is slightly less
likely to generate in Gehennom (but isn't typically needed in
quantity there).

Armor that has extrinsics is more likely to generate, both due to
having increased probability relative to other armor, and due to the
increased proportion of generated items being armor: this is the
primary goal of this change.

The intention behind this change is to increase the chance that
players naturally find useful armor (especially armor that they might
not have been planning to use, but that they can adapt their strategy
to make use of), rather than needing to wish for it: the chance of
finding useful armor is higher both in the Dungeons (due to the
increased probability) and in Gehennom (because it is more biased
towards armor that might be useful at that stage of the game).  In
practice, in 3.6.x (prior to this change and to wishing changes), it
was quite common for players to wish up an entire set of armor at the
Castle, ignoring almost everything they'd found so far that game; I'm
hoping this change encourages more wish variety rather than spending
the majority of wishes on armor.
2026-03-21 04:52:51 +00:00
Pasi Kallinen
f85b5b1c9d Fix segfaults from the key binds change
Should've checked rest_on_space behaviour ...
2026-03-20 22:49:29 +02:00
Pasi Kallinen
c595f241e6 Change key binds from array to linked list
Key bindings were stored as a fixed-size array, indexed by the input
character, pointing to the extended commands.  This changes that into
a linked list of an intermediary struct Cmd_bind, storing the input key
and the pointer to the command.

This is just code cleanup for future enhancements, and should have
no effect on gameplay.
2026-03-20 19:57:44 +02:00
nhmall
b33b09bcac whitespace cleanup: tabs to spaces 2026-03-19 20:22:24 -04:00
PatR
e38377e899 some reformatting for read.c 2026-03-19 16:29:11 -07:00
PatR
aafc414a9f remove inaccurate comment
Floating eyes aren't the only monsters that pass the is_floater() test.
Other 'e's aned 'y's do too.
2026-03-19 15:55:08 -07:00
nhmall
9aa2f61058 limits.h follow-up 2026-03-19 10:02:10 -04:00
Alex Smith
e6d44c68e8 Overhaul of priest donations
The old code had two main problems: a) it was very difficult for
unspoiled players to figure out how it worked (because donating too
much got you a bad result, and the exact amount you needed depended
on magic numbers that weren't stated in game, and because you had to
hide your visible gold to get a good result); b) for players who
knew the mechanics, it was somewhat exploitable and also somewhat
tedious to make use of (due to needing to hide visible gold before
donating).

This change preserves the spirit of the previous code whilst making
things more transparent for new players and less tedious for existing
players: the donation amounts for the various effects are still
roughly the same (but randomized), but the amounts you need to donate
for clairvoyance and for protection are explicitly stated (and as
before, the alignment reset is done by donating an unnecessarily
large amount and isn't explicitly stated as an option).  If you have
a lot of visible gold, you still need to donate a sizeable proportion
of it to get a useful effect, but now you get a larger reward to
compensate for the larger donation (to the extent that doing this
gives comparable results to doing it as a series of small donations,
removing the incentive to hide your gold before donating).

There's also something here for those players who like to squeeze
every last point of optimality out of a game: the "obvious" donation
strategy gives decent results, but players who are really willing to
dig into the mechanics may be able to find a way to get slightly
better results on average (which if I've balanced this correctly,
will lead to a very long and complicated spoiler).

One other change is that this is now based on your peak rather than
current level, to fix an exploit in which the character was drained
down to level 1 to donate a very large amount of gold (improving by
20 AC points) and then immediately restored back to the previous
experience level using a blessed potion of restore ablity.

This breaks save compatibility, but is being pushed together with
other save-breaking changes to avoid the need for multiple bumps to
EDITLEVEL.
2026-03-19 05:10:09 +00:00
Alex Smith
4d043a6f9c Monsters require experience using wands before they can hit with them
It takes time for an early-game monster to acclimatize itself to the
power of an attack wand: in much the same way as a nervous human may
quite possibly miss with their first attempt to use a gun in combat,
an early-game monster will always miss on its first use of an attack
wand (but from then on will understand how they work and get over
their nerves, and will hit as normal).

This is a balance change based on observed results from tournaments:
guarding against deaths to early-game attack wands requires an
unusually cautious playstyle which isn't much fun (and might not
always be possible even for the best players), so it is quite common
for them to be the cause of random deaths that it wasn't worth trying
to avoid. Although trying to dodge a monster who found an attack wand
is fun, you only actually get that fun if something makes you aware
of the danger: the monster missing with the wand is a clear way to
demonstrate the danger and let the player know that now is the right
time to take precautions.

This change could theoretically have broken saves, but probably
doesn't due to there having been a spare bit in struct monst.  Just
in case, it is being pushed together with other save-breaking changes
to avoid the need for multiple bumps to EDITLEVEL.
2026-03-19 03:55:10 +00:00
Alex Smith
07fc4904c6 Add a new wand, the wand of stasis
A wand of stasis prevents teleportation (even in some cases where
it would normally not be prevented, e.g. the hero teleporting a
monster, or covetous monsters teleporting). This is intended to
provide an alternative tactic against covetous monsters (and their
AI has been adjusted to handle being under a stasis effect), but
might also be useful in other situations. It does not prevent
teleportation of objects, only the hero / monsters, and does not
at present prevent level teleportation (although I'm not sure about
this and it might well change in the future).

This breaks save compatibility, but is being pushed together with
other save-breaking changes to avoid the need for multiple bumps to
EDITLEVEL.
2026-03-19 01:16:30 +00:00
Alex Smith
6886b199be Teleport traps don't teleport you on no-teleport levels
In previous versions of NetHack, this wasn't a problem because
teleport traps didn't *generate* on such levels, but more recent
changes have made this situation possible (e.g. a demon lord
migrates to a Gehennom filler level that already had a teleport
trap on it).

This change causes a "wrenching sensation", like stepping onto a
teleport trap with magic resistance does.
2026-03-19 01:01:46 +00:00
Alex Smith
5d3a1e684b Add shields of shock resistance and of drain resistance
These both appear as "wooden shield" when unidentified; so does the
small shield.
2026-03-18 23:27:54 +00:00
Alex Smith
4fae45220e Remember price quotes that have been seen for types of item
These are displayed in discoveries, and a new 'price_quotes' option
allows them to be displayed for un-IDed objects in other contexts
too (the idea is that you turn on the option while identifying
objects and off for general play).

Invalidates existing save files.
2026-03-18 21:08:22 +00:00
Pasi Kallinen
9877e52025 Ring of stealth prevents hero from leaving tracks 2026-03-18 18:04:33 +02:00
Pasi Kallinen
18cb293766 Replace magic number with define 2026-03-18 17:12:01 +02:00
Pasi Kallinen
66e7123678 Categorize more commands as general commands
"general commands" tend to be ones which take no game time,
or are non-diegetic.
2026-03-17 13:38:12 +02:00
Alex Smith
b6df17f342 Iron shoes protect / partially protect against certain trap types 2026-03-17 00:05:16 +00:00
Pasi Kallinen
13e7d21b93 Replace magic number with define 2026-03-16 15:36:23 +02:00
Pasi Kallinen
619de1ec0e Make monster destroy armor -spell erode armor first
Instead of outright destroying the armor, the spell will instead
first erode the armor.  The spell hits 2-4 times, so if it hits
the same armor 4 times, it will get destroyed.  This does not
hit erodeproof armor.

Also change the scroll of destroy armor, so that blessed one will
destroy a cursed armor, if hero is only wearing that.
2026-03-16 11:24:19 +02:00
PatR
b70da87d3e 'onefile' tidbit 2026-03-12 13:17:11 -07:00
PatR
c30eea477d Shroedinger's dead cat
Give experience to the hero if opening Shroedinger's Box reveals a cat
corpse rather than releasing a live cat.

It feels a bit odd to assess a bonus rather than a penalty.
2026-03-12 13:12:42 -07:00
Pasi Kallinen
226157004b Make migratemons ignore debug_mongen
Same as wizgenesis, migratemons should create monsters even
when random monster generation is disabled.
2026-03-11 17:35:23 +02:00
PatR
be0bed8f3c rephrase comment
Triviality: add a couple of commas so that a comment won't be misread.
2026-03-08 03:14:29 -07:00
PatR
98da3a3db6 fix drawbridge + place_monster impossible
Reported via email direct to devteam.

If a monster killed by a drawbridge survives via life-saving and a
second monster also survives (in the reported case, it was a xorn
who will always survive bridge destruction), the second monster will
be placed at the same spot.  That triggers an impossible
"placing <2nd mon> over <1st mon>, at <x,y>, mstates 0 0 at Dlvl N?".
If the first monster survives due to pass_walls rather than due to
life-saving and a second survives too, one of them should end up being
moved to a different spot and not trigger the impossible (not verified
via testing).

When a monster survives via life-saving, kill it again even if there
is no second monster involved.
2026-03-05 12:57:20 -08:00
PatR
ef6e2a9624 fix #15306b - vision blocking sanity check
Update vision affected by invisible mimics if polymorphing hero gains
or loses See_invisibls.  Avoids triggering a sanity_check impossisble
if an invisible mimic is mimicking a boulder.
2026-02-25 18:30:11 -08:00
PatR
398681fd18 fix? #S15277 - Engulfer gets placed over itself
Bug report was that engulfer killed hero who was life-saved and expelled
onto a rolling boulder trap which resulted in the death of a bystanding
monster.  That triggered an impossible about placing the engulfer onto
the map at an already occupied spot (containing the engulfer itself)
while dealing with the dead bystander.

This removes the code in mon_leaving_level() that was putting the
engulfer on the map.  I'm no longer able to reproduce the problem it
was intended to solve, and if that problem (message delivery about the
swallow attack delivered with the engulfer missing from the map) exists,
it would be less severe than the impossible feedback.  I didn't attempt
to reproduce the actual reported problem since the code removal should
make it moot.

Once again, the bug report via the web contact form got misclassified
as spam.
2026-02-20 19:29:55 -08:00
Greg Kennedy
822396c2e0 Attribute adjustment resets abuse / exercise counter 2026-02-17 14:51:37 -08:00
Greg Kennedy
06012e7127 Potion / spell of restore ability resets stat abuse as well 2026-02-17 14:51:37 -08:00
PatR
0d2752d05d more cursed potion of invisibility
Give feedback if a visible monster drinks a potion of invisibility
that happens to be cursed so monster fails to become invisible, or if
hero hits a visible monster with a cursed potion of invisibility and
it fails to become invisible.
2026-02-16 19:51:04 -08:00
PatR
b702be4449 more discoveries of unique items
Show the invocation items in the unique items section of the
discoveries list even when they're only flagged as encountered rather
than fully discovered.  The Amulet of Yendor is excluded; it has to
be fully discovered to be shown in that section.
2026-02-16 14:01:59 -08:00
PatR
1bb7146cbd \#knownclass (back-tick) of relics
The ` command already supports selecting 'u' for unique items as a
pseudo-class.  Add support for 'r' as synonym to match the recent
addition of 'relics' to the Guidebook.

The unique item category includes the Amulet of Yendor in addition
to the three invocation items.  'r' shows it too, once it has been
fully IDed.  I'm ambivalent as to whether the Guidebook's Relics
section should mention it.
2026-02-15 12:37:55 -08:00
PatR
651a91f94c explain Amulet wish
In wizard mode, I used ^W to wish for the Amulet of Yendor and was
immediately prompted for another wish.  It was baffling and took a
while to figure out.  Give a message before initiating the wish.
2026-02-15 11:48:40 -08:00
Pasi Kallinen
fe7b3ce09d Empty tin hallu msg 2026-02-15 17:01:49 +02:00
PatR
f4bb0d93e5 observed objects
This has been laying around for a few weeks.  I meant to do more but
have forgotten what the rest would have been.

Don't mark generic objects as dknown.
2026-02-14 21:03:58 -08:00
Pasi Kallinen
78217c3ebd Allow rogues to backstab sleeping or paralyzed monsters 2026-02-13 12:53:21 +02:00
PatR
a561538c2a cursed potions of invisibility for monsters
Extend the recently changed behavior for cursed potion of invisibility.

Monsters won't drink potions of invisibility if already invisible so
can't accidentally or voluntarily make themselves visible again, but
let player make them become visible by hitting them with thrown or
wielded cursed potion of invisibility.

They don't have any concept of temporary invisibility that might let
them remain invisible while losing permanent invisibility, so they
just lose the latter and immediately become visible.
2026-02-12 10:33:09 -08:00
Pasi Kallinen
bbc3eea066 Make sure negatively enchanted boomerang hits anything 2026-02-12 14:32:58 +02:00
nhmall
fcd9f5468c some coordxy follow-up
Return a couple of variables that actually held a direction back
to int from coordxy.

bhit() takes int params instead of coordxy.

boomhit() takes int params instead of coordxy.

xytod() renamed to xytodir(), and takes int params (promotion will handle
coordxy params).

dtoxy(coord *, int) renamed to dirtocoord(coord *, int).
2026-02-11 09:40:25 -05:00
Pasi Kallinen
db36ee35de Fix the healer knife bonus
dmgval is also used for monster attacks; move the healer knife
bonus to actual hero-specific code, and make sure it only
applies to hand-to-hand combat.
2026-02-11 08:22:02 +02:00
nhmall
b76d4338be avoid a reported obuf reuse in use_misc()
Report: https://github.com/NetHack/NetHack/issues/1486

Resolves #1486
2026-02-09 08:39:21 -05:00
Pasi Kallinen
4b30e3fab8 Healers may get tiny damage increase with knives
Styled as anatomy knowledge, a healer attacking a monster in melee
with a knife gets +1 damage per 6 dead monsters of that type,
capped at +3 damage.

Handwaving away the fact we're not keeping track who actually
killed the monsters...

Idea from aosdict.
2026-02-08 18:11:06 +02:00
Pasi Kallinen
63dd80f5ec More code style nits 2026-02-07 17:03:54 +02:00
Pasi Kallinen
74390fb690 Split ray bouncing dir into separate function 2026-02-07 14:51:03 +02:00
Pasi Kallinen
79c688cc6b Code style nit 2026-02-06 17:26:54 +02:00