Commit Graph

8730 Commits

Author SHA1 Message Date
nhmall
afca423f06 build fix 2023-05-07 07:20:11 -04:00
Pasi Kallinen
e18548c821 Fix knockback impossible
When monster attacked another monster, and the retaliation attack
knocked back the attacking monster, the variables holding the
attacking monster coordinates were out of sync and caused
"no monster to remove" warning.

Propagate back the knockback hit, so the current monster cannot
do anything further.
2023-05-07 12:57:09 +03:00
PatR
b4b251b618 temporary blindness vs permanent blindness
While testing the fix for unicorn horn vs blindness, I noticed that
when 'blind from birth' (OPTIONS=blind) you would get "your vision
seems to dim for a moment but is normal now" when timed blindness
was added to persistent blindness.  That happened for both 3.6.x and
to-be-3.7.  Change it "you have a strange feeling for a moment".

In 3.7, having temporary blindness timeout while permanently blind
produced "your vision seems to brighten for a moment but is normal
now".  Change that to strange feeling too.  For some reason I haven't
tried to figure out, 3.6.x stayed silent when this took place.
2023-05-07 01:03:29 -07:00
PatR
76fbca7d25 fix github issue #1020 - unicorn horn vs blindness
Reported by argrath:  the test for whether blindness could be fixed
by applying a unicorn horn got broken by the recent change to the
Blinded macro.

While in there, undefine macros once they stop being useful.  I put
these #undef lines closer to their #define instead of at end of file.

Also, remove an out of date comment about encoding property troubles.
It became obsolete when unicorn horn stop fixing lost Str, Dex, &c.

Fixes #1020
2023-05-07 00:37:51 -07:00
PatR
ca02bc4898 fix #K3917 - fuzzer stuck in endless lifesave loop
Life-saving from being burned up in lava attempts to teleport the
hero to safely.  If that fails, hero immediately burns up again.
For fuzz testing, that results in an infinite loop.

While implementing a fix (in done(), not just lava-specific), I
noticed that hangup while running interactively in explore or
wizard mode could be subject to similar effect.

For the fuzzer, if hero dies 15 times without advancing the move
count (not 'moves', the turn count), don't life-save again.  With
hangup, don't prompt for "Die?" more than once.

Normal interactive declining to die still works.  The more exotic
situations aren't tested.
2023-05-06 16:51:59 -07:00
Pasi Kallinen
5023e4bfad Fix tame soldier being angry
Wizard-mode created tame soldier got angry when another
soldier played a bugle.
2023-05-06 23:12:59 +03:00
Pasi Kallinen
fe3dcb4416 Genetic engineer uses up turn when polying a monster
The fuzzer encountered a "no monster to remove" impossible,
this should fix it, even though I did not manage to reproduce
it manually.
2023-05-06 20:16:28 +03:00
Pasi Kallinen
d036116dee Fix hiding under nonexistent obj
Zapping a wand of teleportation at a location with object and
a monster hiding under it, but with the level full of monsters,
the monster would stay hidden even when the object was moved.
2023-05-06 20:13:10 +03:00
PatR
6de996971b fix #K3915 - "deleting worn obj" warning
Knocking a monster into lava triggering impossible warnig "deleting
worn object" for a wooden shield.  The monster had to be wearning
flammable armor and be fire resistant to survive instead dying and
dropping inventory, and it couldn't be a creature that can survive at
lava locations like a salamander and the armor needed to already be
thoroughly burnt.

It wasn't hard to figure out what needed to be fixed, but it was very
hard to reproduce the situation in order to verify that fix.  The
report was for monster vs monster knockback but I jousted with a lance
instead.  I still don't understand why burning up a worn wooden shield
triggered the warning but burning up a worn orcish cloak did not.
2023-05-06 00:08:35 -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
e28d15f491 endgame portal fix
A recent change to prevent creating webs at water locations also
deliberately prevented them at air locations but had the unintended
side-effect of preventing creation of magic portals on the Planes
or Air and Water.  Those two levels always place the portal in air.
Explicitly allow air if the trap being created is a magic portal.
2023-05-05 17:42:57 -07:00
PatR
180042434e more engraving sanity feedback
Delete engravings made in a breach of a shop's wall or of a vault's
wall or in the guard's temporary corridor when the wall is repaired
or the corridor removed.  If 'sanity_check' was On, those would
trigger impossible warning "engraving sanity: illegal surface (x)"
where x was the terrain type code for solid rock or relevant walls.

Adding del_engr_at() calls to the shop code was straightforward.
The vault code is very complicated and I'm not sure that all the
calls I added were actually necessary.
2023-05-04 06:02:23 -07:00
PatR
c0441126b8 fix #K3912 - engraving sanity: closed doors
Engraving in an empty doorway and then using locking magic to create
a door there resulted in an impossible warning: "engraving sanity:
illegal surface (23)" if the 'sanity_check' option was On (wizard
mode only).  Engraving in an open doorway and then simply closing
the existing door produced the same effect.

Accept engravings at closed doors.  Presumably hero will be using
Passes_walls to attempt that so treat closed doors same as open ones.
Update the engraving sanity check to deal with that.

Bonus fix: engraving sanity checking stopped after the first problem
instead of checking every engraving.  Have it continue instead.

Not fixed:  vault wall repair and temporary corridor removal does
not delete engravings and can trigger the illegal surface warning if
player engraves before the repairs.  I didn't test shop wall repair
but it doesn't have any engr references so probably has the same bug.
2023-05-03 14:29:03 -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
nhmall
a687e75e9b WIN32 file name normalization 2023-05-03 12:31:15 -04: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
d2f4edc209 'm #genocided' bit
Overlooked part of customizing the #genocided sort menu.

A bit of unrelated trap.c formatting included.
2023-05-03 05:20:13 -07:00
PatR
e48c6bdc00 \#genocided revision
The #genocided command was revealing extinct monster species when used
during normal play.  That was not intended, so stop.  Change to only
reveal them in wizard or explore modes and also during end-of-game
disclosure but suppress them during normal play.

The full description of #genocided is now dynamically updated for '# ?'
during normal play to remove its reference to extinctions.  Also, check
for skipping wizard mode commands before doing description searching.

\#genocided was out of alphabetical order in the full commands list.
Both it and #vanquished should have had the GENERALCMD flag; they
don't affect game state.

Change #genocided to use the sort order currently set for #vanquished,
and allow 'm #genocided' to put up the same menu as 'm #vanquished'.
(Not quite the same.  Sorting by count of monster deaths isn't
appropriate for listing genocides where an arbitrary number may have
been killed before the genocide occurred.  If the preferred order for
vanquished is set that way, alphabetical will be used for genocided.)

Setting the order via menu for either command sets the order for both,
but doing so via #genocided doesn't offer the count-high-to-low and
count-low-to-high choices.  During disclosure, you can answer 'a' when
asked whether to disclose genocided and extinct monster types and like
for vanquished monsters, that lets you choose an order at end-of-game.
Doing so won't affect disclosing of vanquished monsters--it'll be too
late for them.

A chunk of this diff is due to moving the #wizborn code out of the
middle of #vanquished handling.

Guidebook.ms has been updated but Guidebook.tex is lagging.
2023-05-03 04:58:39 -07: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
nhmall
e298bb09c1 build fix for Windows Visual Studio 2023-05-01 11:00:10 -04:00
Pasi Kallinen
6e218cd7ef Fix zapping cancellation at magical trap
The exploding magical trap did not cause problems before just by
being a magical explosion by accident; adding an object caused
the cancellation wand ID to change, and the explosion now had
an impossible explosion type.

Hardcode trap explosions to generic magical blasts.
2023-05-01 17:46:16 +03:00
PatR
b3580289be fix github issue #1017 - webs in/on water
Reported by copperwater, it was possible for a web to be created
at a water or lava location.  It would not be displayed even after
being discovered; showing the terrain superseded showing the trap.
But it functioned normally and could trap the hero.  Webs pull the
victim to the floor so hero would drown or burn up on next move
even if the spot had been reached while floating or flying.

A monster spider couldn't survive at a water or lava location, but
a poly'd hero could.  Creating a web via #monster or wizard mode
wish could result in it affecting some unsuspecting player via bones.

Disallow creation of webs at water, lava, and air or cloud spots.
(They're already disallowed at furniture spots.)

Fixes #1017
2023-05-01 01:54:35 -07:00
PatR
57b54664bd \#undef dogmove.c macros
While looking for something in dogmove.c I did some source cleanup.
Undefine its macros by the end of the file, and redo some pet vs
guardian angel handling that dated from when the monst extensions for
those two were overlaid.
2023-05-01 01:13:08 -07:00
PatR
14e35ce419 fix #K3890 - "wall_angle: unknown hwall mode 4"
When lastseentyp[x][y] is different from levl[x][y].typ and #terrain
tries to show <x,y>, the value of levl[x][y].flags might not have an
approrpriate value for the remembered terrain type.  The reported
problem was an impossible() about wall mode.

rm.wall_info == 4 corresponds to rm.doormask == D_OPEN and both of
them are overloaded on rm.flags.  A spot remembered as a wall but
actually a secret door might cause this if it has become discovered
('wall' changed to closed door) and then opened (with door intact)
while out of view.  [I'm not sure how that could happen though.]

I was unable to reproduce it so haven't verified that the fix works.
2023-04-30 00:38:40 -07:00
PatR
70949a787e mplayer creation bestowing 0 gold pieces
Reported directly to devteam:  a fake player monster was petrified
and when creating its statue yielded "Calculating weight of 0 gold
pieces?".

Fake player monsters on the Astral Plane level were being created
with rn2(1000) gold pieces so had a 1 in 1000 chance of that being 0.
Gold gets created with a non-zero amount but the routine that gives
it to a monster sets the amount to the requested value.  That didn't
update the weight so didn't notice the 0.  Putting it into a container
(the statue) did recalculate the weight and did notice.

There was a choice between forcing a non-zero amount or allowing 0
and bypassing its creation and placement in monster's inventory.
I went with the latter.
2023-04-29 05:30:14 -07:00
PatR
f9a35132d6 crystal helmet
Discussed a long time ago, change helm of brilliance from iron to
crystal so that it doesn't need to be a special case for metallic
armor's affect on spell casting.  It now has a fixed description of
"crystal helmet" but is not pre-discovered.

Add new helm of caution to retain the "etched helmet" description
among the shuffled helms.  Wearing it confers the Warning attribute.
That's fairly lame but not necessarily useless.  It's iron and gets
half the former probability for a random piece of armor being helm
of brilliance so is not likely to be popular.

Helm of caution keeps the old helm of brilliance tile and new helm
of brilliance is basically the same image with different color and
pointed on the top.

Not changed:  the etched helmet was marked as green and is drawn
that way for text but the tile doesn't actually use green for it.
Crystal helmet started as hi_glass (rendered as 'bright cyan') but
has been changed to clr_white to match crystal plate mail.

Old save and bones files are invalidated.
2023-04-29 02:18:29 -07:00
PatR
90155cd857 monst->meverseen comment fix
and a minor formatting bit.
2023-04-29 01:48:11 -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
PatR
57ff993352 optimize pline("%s",string)
pline() already skips sprintf/vsnprintf if the format doesn't contain
any percent signs.  Do the same if the entire format is "%s".

Also, if ESC is used to suppress messages for the rest of the current
move, the text for any impossible warnings issued during that time
would be suppressed too so not be seen.
2023-04-24 16:34:48 -07:00
nhmall
2308e2480d wording correction 2023-04-24 11:31:46 -04: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
PatR
7105f0a7d9 another macro relocation: HI_xxx
Move HI_DOMESTIC and HI_LORD from monst.c to color.h.
2023-04-22 16:10:37 -07:00
nhmall
d703539847 define WT_ macros in a header file
A recently added #undef WT_ELF caused a onefile build to break.

trap.c: In function 'trapeffect_landmine':
trap.c:2346:41: error: 'WT_ELF' undeclared (first use in this function); did you mean 'PM_ELF'?
trap.c:2346:41: note: each undeclared identifier is reported only once for each function it appears in
2023-04-22 11:13:53 -04:00
PatR
85a002c157 hearing an unseen monster read a scroll
Heroes recognized unseen same-race monsters by voice, but it yielded
an unexpected result if the monster was unique.  Change it so that
hero will recognize any type of monster by its voice if that monster
has been seen and limit unseen same-race ones to non-unique monsters.
Treats shopkeepers as unique since they have distinct names.

This adds a new flag to struct monst in order to track whether each
specific monster has ever been seen or sensed.
2023-04-22 02:00:04 -07:00
PatR
861fcdf9c4 more 'onefile' tweaks
Undefine some macros when the file that uses them is done so that
they won't be seen by any other source files if combined into one
huge source file.  I only looked at the few files where an #undef was
needed, not all the files, but in those few files I used #undef for
[almost] all their local macros instead of just the troublesome one.
display.c is the exception; it still has lots of macros which persist
through end of file.  nhlobj.c is another exception; I misremembered
the fixup for lua's lobject.c at the time and decided to include the
one #undef for nhlobj.c anyway even though 'onefile' isn't affected.

monst.c includes some reformatting.  display.c's sign() macro was
redone; it's intended for efficiency compared to calling hacklib.c's
sgn() function so streamline it.

[Keni, most of the file-specific #undef fixups in genonefile.pl can
now be removed.  It'll still need one for lua source file lobject.c;
addstr() there conflicts with curses.h, not with nethack's own code.]
2023-04-21 14:32:43 -07:00
nhmall
b26ec2f677 attempt to quiet some onefile complaints 2023-04-21 10:42:36 -04:00
nhmall
826ce951e7 get rid of NetHack macro conflict with curses routine delay_output() 2023-04-21 08:25:53 -04:00
Pasi Kallinen
a725447d65 Corpse-eating monsters will home in on corpses
Also allow non-tame ghouls to eat corpses.
2023-04-20 18:56:26 +03:00
PatR
8293251224 \#overview fix
The revised #overview (displaying info in a menu instead of text
window), works as intended for tty and curses, during play and also
during end of game disclosure.

For X11 it worked during play but during disclosure it issued a
call to impossible() for every line of overview output and there
was no overview shown.  ("add_menu:  called before start_menu",
sent to stdout where the player may not have a chance to see it.)

For Qt things were worse, working during play but with indentation
that isn't what is intended, and during disclosure it crashed in
add_menu().

This avoids the impossible and the crash, by changing how the core
treats the menu rather than by updating how FOO_add_menu() deals
with the offending previous usage.

I suspect that to fix the Qt indentation, #overview might need to
be changed to behave like #attributes:  use a menu during play but
a text window during disclosure.  It has a hack for text windows
to switch from the default font to a fixed-width one if any line
in the text contains four consecutive spaces.  Either menu windows
aren't doing the same thing, or the two-column layout they use to
render their text is messing that up.  (I haven't looked.)
2023-04-20 00:18:05 -07:00
Pasi Kallinen
200cc21fb3 Allow some monsters to break boulders
... if the boulder is in a position they want to move to.
Shopkeepers, priests, and the quest leader can break one boulder
and then need to take several turns before being able to break
another.  Riders can break a boulder every turn.
2023-04-19 14:37:55 +03:00
PatR
4d681eed46 new #overview menu
Require the 'm' prefix to treat #overview as a menu with selectable
entries.  During end-of-game disclosure it shows every level that was
visited, but during play it only shows levels which have annotations
(typically automatically generated ones).  The menu wasn't offering
any chance to add an annotation to levels without such, so force
'm #overview' to show every visited level.  Continue to avoid that
(and also avoid the clutter introduced by menu entry selector letters)
for normal #overview.
2023-04-19 02:30:32 -07:00
Pasi Kallinen
b04ab80cad Allow annotating other levels via #overview
Change the #overview to use a menu, so the player can change
the annotations on levels other than where they currently are.
2023-04-18 09:40:12 +03:00
Pasi Kallinen
cfe60aed8d Dismounting a trapped steed
Riding a steed into a trap and dismounting also untrapped
the steed. Try to keep the steed in the trap.
2023-04-17 18:47:05 +03:00
Pasi Kallinen
0ac9309e1e Simple options menu shows help for each entry 2023-04-17 15:47:50 +03:00
Pasi Kallinen
6fcce6e135 Redo the portal breakage for the fuzzer 2023-04-17 11:09:58 +03:00
copperwater
dad1c3f8b7 Fix: breathless monsters always generate in water in special levels
... unless explicitly specified to generate at a specific point or
within a specific area. But if they are permitted to generate anywhere
on the level, and it contains water, they always end up in the water. I
noticed this when trying to explicitly specify ghouls to generate
anywhere on a level with a minimal amount of water.

This was due to the definition of "amphibious" being conflated with
"breathless", such that all breathless monsters counted as amphibious.
There are plenty of breathless monsters in the game that decidedly don't
normally inhabit water, such as undead, but they would pass the
amphibious() check in pm_to_humidity and thus the game decides that they
must generate in wet terrain if there is any available.

This fix takes the approach of changing amphibious() so that it no
longer checks the M1_BREATHLESS flag and only considers M1_AMPHIBIOUS,
then updating the places where amphibious() and Amphibious are used
accordingly. I also added a new macro cant_drown() which wraps up
swimming, amphibiousness, and breathlessness because these three things
are frequently checked together in the context of whether something
should drown.

Places where amphibious() or Amphibious did NOT have an extra
breathless() or Breathless check added on, and thus where behavior has
been changed:
- The pm_to_humidity function (to fix the bug).
- Player vs water in goodpos; it didn't seem like being polymorphed into
  a breathless non-amphibious monster should make it fair game to
  randomly teleport into water even though it's technically safe.
- Awarding extra experience when killing an eel. (So the hero will get
  the extra experience if they are polymorphed into a breathless
  non-amphibious monster and don't have magical breathing. Very much an
  edge case.)
2023-04-16 09:57:41 +03:00
copperwater
fe39a2b08d Don't drop aklys on the floor due to slippery fingers
Aklyses uniquely have a tether attached to one's wrist, which would stay
secure even when one's fingers are slippery. Therefore, it doesn't make
for the weapon to be dropped completely, tether and all, when Glib.

However, the game doesn't have a way to model a weapon that's on the
floor at your feet but still attached to your arm. (Technically the
uball and uchain code does do this sort of thing already, but it can't
be used here - what if you have an aklys slipping out of your grasp and
are punished at the same time?) So the next best thing is to give
aklyses immunity to slipping from one's hand.
2023-04-16 09:48:42 +03:00
copperwater
95972d7147 Wand of speed gives player temporary speed and potion gives intrinsic
This aims to fix the issue in which there are way more wands of speed
monster in the game than the player has any use for. Usually, one is
enough for the whole game (unless a player has a lot of pets they want
to speed up) but since they're an item monsters can generate with, it's
typical to see eight to twelve of them, useless for anything besides
polypiling into other wands since they just grant an intrinsic that's
usually obtained early in the game.

By making the wand effect (on the player) temporary very fast speed, it
becomes desirable to keep the wand around again. By adding a lightweight
source of very fast speed, it also helps diversify character builds away
from always relying on speed boots. And importantly, it becomes an item
the player can use situationally early in the game to enhance their odds
in a fight or run away from danger.

Meanwhile, the speed-intrinsic-granting has been moved to the potion,
and the potion is still superior to the wand in the duration of very
fast speed it grants (100 + d10 turns for an uncursed potion or 160 +
d10 turns for a blessed one, versus 50 + d25 turns for the wand).

Since monsters don't have a concept of very fast speed, this doesn't
change the wand or potion effects on them. They will still gain
permanent intrinsic speed by either method.
2023-04-16 09:33:56 +03:00
PatR
a93ee09d1a fix github issue #1011 - monster imagination
Issue reported by AndrioCelos:  if hero was killed by a wand zapped
by a monster, the cause of death was "killed by <wand damage>
imagined by <the monster>" instead of intended "killed by <wand
damage> zapped by <the monster>".  Report mentioned that the monster
was unseen but that wasn't relevant.

This worked when monster wand zaps were briefly changed to use
-9..-0 but got broken when that was reverted to using -39..-30 (due
to -0 being the same as 0 so making zapper of wands of magic missile
ambiguous).

Fixes #1011
2023-04-15 12:34:27 -07:00
Pasi Kallinen
36f1596c02 Shop door entrance placement
If for some reason a shop room has multiple doors, try all of them
to find a good shop door, instead of just the first one, and failing
if it wasn't a good one.

This only matters for wizard-mode with SHOPTYPE environment var.
2023-04-15 14:25:52 +03:00