Commit Graph

181 Commits

Author SHA1 Message Date
nhmall
be76727265 granular verbose message suppression mechanics
Switch to using a macro invocation Verbos(n, s) in place of the
flags.verbose checks.

Provide the mechanics for individual suppression of any of the
existing messages that were considered verbose.

Mechanics only - this code update does not provide any means of
setting the suppression bits.

iflags.verbose = 0
is still a master suppression of all the verbose messages.

iflags.verbose = 1
turns on the verbose messages only for those whose suppression
bit is 0 (not set).
2022-06-09 13:53:20 -04:00
nhmall
9e6ac144b4 switch to using a flag parameter on newcham() 2022-05-28 19:35:48 -04:00
PatR
4fbda9ea34 dochugw(mon, X)
Reverse the sense of dochugw()'s new 'X' argument. Use True for the
usual case and False for the special case rather than the other way
around.

Call the special case variant when a monster teleports so that hero
stops occupation if the monster jumps to a position where it becomes
a threat.
2022-05-07 09:11:09 -07:00
PatR
f2f2644e30 busy hero ignoring monster threat
Fix the problem reported by entrez of a zombie corpse reviving and
crawling out of the ground while the hero was busy doing something
(searching, digging, &c) and having the hero fail to react and just
keep doing whatever the thing was because the zombie was already
inside the range where a monster changes from no-threat to threat.

Done in the monster creation routine so any new monster (including
one revived from a corpse) that is visible,&c will cause the hero's
action to be interrupted.  Teleport arrival probably needs this too.

Only interrupts an occupation, not other voluntary multi-turn
actitivy such as running or traveling.  That would be trivial to
change ['if (g.occupation...' to 'if ((g.occupation || multi > 0)...']
but I'm not sure whether it ought to be extended to that.
2022-05-06 18:30:06 -07:00
PatR
d1217b9f25 add glyphs+tiles for door+chest traps
When trap detection finds trapped doors and trapped chests, it shows
those as bear traps.  When the hero comes within view, they revert to
normal and the detected trap is forgotten.  This doesn't change that,
it is just groundwork to be able to show them distinctly.  Like the
TT_BEARTRAP patch, it increments EDITLEVEL so this seemed like a good
time to put the groudwork in place.

There shouldn't be any visible changes even though internal glyph and
tile values have been renumbered after inserting two new entries.
Adding traps after S_vibrating_square was quite a hassle and suffered
though a couple of off-by-one errors that weren't trivial to find and
fix.
2022-04-27 11:22:12 -07:00
Pasi Kallinen
39acd095b2 Add helpless monster macro 2022-03-18 10:19:04 +02:00
Pasi Kallinen
7a1db1d0bd Fix couple cases of unhiding monsters
Hidden monster might be forced to move to a location where it
can't hide, perhaps because it's mostly surrounded by other monsters.

Hidden monster in a pit under items, getting hit by a rolling boulder,
the boulder will fill the pit burying the items, making the monster
unable to hide there.
2022-03-04 19:58:24 +02:00
Pasi Kallinen
2cdd8f8dcb Fix checking monster moving into a trap return value
When I added a new trap return value, this was one place that
should've checked it.

This was really annoying to debug - it manifested as a temp level
file loading error, because a monster moved on to a level teleport
trap, which zeroes out (mx, my), then later in the monster movement,
a web spinner created a web at (0,0), and then hero leaving the level,
the traps were saved into the level file ... and when loaded, the code
thought a trap with x == 0 meant there were no more traps.
2022-03-04 16:42:15 +02:00
Pasi Kallinen
f8cb7ae0b8 Unify shopkeeper/guard/priest bit in m_move 2022-02-26 18:05:43 +02:00
Pasi Kallinen
7523623d95 Make m_move return defines instead of magic numbers 2022-02-26 17:40:17 +02:00
Pasi Kallinen
2777f45bd5 Get rid of force_mintrap, allow passing flags to mintrap
It uses the same flags as dotrap, so simulate force_mintrap
by passing FORCETRAP flag.
2022-02-24 17:13:23 +02:00
Pasi Kallinen
9716f22851 Make trap return values more consistent
Instead of returning monster's mtrapped-state, return specific
trap return values.
Add one extra trap return value, for when a monster was
moved by the trap.
2022-02-24 16:24:02 +02:00
Pasi Kallinen
8e91320d2f Use u_at macro 2022-02-23 20:28:55 +02:00
Kestrel Gregorich-Trevor
355ed43a29 pull request #660 from NullCGT - sleeping monsters
Indicate to players that monsters are sleeping.

Closes #660
2022-02-22 11:36:40 -08:00
Pasi Kallinen
91e2d3633e Use macro for a location next to hero 2022-02-12 11:05:10 +02:00
nhmall
947d80ec6f replace some trap function result magic numbers 2022-02-08 19:16:42 -05:00
Pasi Kallinen
8db18275a6 Define engulfing_u, making clearer code 2021-12-31 21:12:21 +02:00
Pasi Kallinen
2591a21cf0 Leprechauns bury their gold after teleporting 2021-12-31 18:48:44 +02:00
Pasi Kallinen
ea0c488178 Split leprechaun avoidance into separate function 2021-12-28 19:11:30 +02:00
Pasi Kallinen
4b525374d0 Make vrocks emit a poison cloud when they flee 2021-12-25 10:51:20 +02:00
Pasi Kallinen
f6b7be49f4 Accessibility: give a message when teleporting a monster
Teleporting a monster only updated the map. Give a message
so blind players can get the same information.
Making a monster invisible gives the same message, if you
cannot detect invisible.
Several other places where monsters teleported themselves
now also give the same message.
2021-12-12 16:50:49 +02:00
PatR
d736cbd751 fix github issue #603 - guarding prize items
Reported by Vivit-R with comments by several others.  The prize item
in one of the closets off the Sokoban treasure zoo is sometimes
missing, most likely picked up by an elf who won't be dissuaded by
the presence of engraved Elbereth or a scroll of scare monster.

This fix prevents monsters from targetting the mines' and sokoban's
prizes for pickup (or for eating).  Once the hero picks either of the
prizes up, they stop being prizes and will be ordinary monster fodder
if dropped/stolen/stashed.

One of the comments by copperwater suggested this approach as a
possible way to fix things.  I had already implemented it from scratch
before noticing that.  It handles the usual monster behavior toward
items, but there could easily be some unusual cases still susceptible
to taking the prize before the hero gets to it.  Those are the breaks.

Fixes #603
2021-10-28 01:05:18 -07:00
PatR
cffeecee26 fix #K3474 - "you detect it where <foo> was"
A vampire in bat form was seen via infravision or possibly telepathy,
then when it changed into fog cloud form the feedback was
|You now detect it where the vampire bat was.
The message substitutes "detect" for "see" when the new form can't
be seen and the monster name formatting yields "it" for that case.

Give a vanish message instead since that is effectively what happens.
2021-10-26 03:11:55 -07:00
nhmall
39713783d1 some trailing whitespace in src, include 2021-10-16 12:12:21 -04:00
PatR
d118ac52af fix github issue #589 - gremlin crash
when fleeing hero who was wearing gold dragon scales/mail and not
wielding any weapon.

When a gremlin was made to flee "artifact light", code originally
intended for Sunsword attempted to format 'uwep' as an artifact.  For
gold scales/mail instead of that, it gave a sane but inappropriate
value if wielding something or segfaulted if not wielding anything.

Fixes #589
2021-09-11 03:04:04 -07:00
PatR
5a09a01a13 gold dragon and scales
Add two new monsters and two new objects:
 gold dragon
 baby gold dragon
 gold dragon scale mail
 set of gold dragon scales

A couple of variants seem to have added these already, but this came
off my ancient list of monsters to add and was done from scratch.
It's a clone of silver dragon, but instead of having reflection and
breathing cold, a gold dragon emits light and breathes fire; because
of the latter it can be seen with infravision like a red dragon.
Adult gold dragons are lawful as in the AD&D Monster Manual rather
than chaotic as the wiki pages show for the variant versions.

Worn gold dragon scales operate similar to wielded Sunsword:  when
blessed, radius is 3 (same as a lamp), if uncursed, radius is 2, and
if cursed, radius is 1 (but functions as 2 when worn by the hero,
otherwise there would be no tangible effect).  Gold dragon scale mail
gets an extra +1, making blessed gold DSM have a bigger radius than
lamps.  Embedded scales have radius 1 regardless of BUC state; light
for that case comes from the gold dragon monster form the hero is in.
When not worn, gold scales and scale-mail don't emit any light.

The tiles use a mix of yellow (for gold) and red.  The two object
tiles seem reasonable variations of the corresponding silver dragon
ones.  The two monster tiles definitely need work since the silver
ones were mostly cyan and changing that to red did not produce very
good result; subsequent attempt at a mixture was haphazard at best.
2021-07-23 10:41:57 -07:00
PatR
dad804e118 web spinning tweak for Sokoban
When spiders try to spin webs, don't let them do so in Sokoban
unless the level has already been solved or the spider can see the
stairs up (which was the simplest way I could achieve something
close to "is in the same room as the stairs up") where it can't
interfere with solving the level.
2021-06-26 17:06:37 -07:00
Pasi Kallinen
075844b4d6 Adjust shopkeeper damage fixing
Allow shopkeeper to remove webs and pits.

Change the damage fix messaging to be more specific when
shopkeeper removes a trap. Before this the message was
"A trap was removed from the floor", which sounds really silly
when it comes to holes.

Change the damage fixing so the shopkeeper will fix one damage spot
at a time (instead of all at once), so it's more like a monster action.

Some code cleanup, splitting into smaller functions.

While doing this, I noticed that shopkeepers don't actually bill
the hero for the damage, but that'll have to be another commit...
2021-06-25 20:02:06 +03:00
Pasi Kallinen
8dfe963652 Allow spiders to spin webs
Revisited this feature, and the chance of a spider spinning a web
depends now on the number of webs already present on the level.

For a giant spider to spin a web in the middle of a room with no
supports, the limit of existing webs is 4, next to one support 9,
next to two supports 14, and so on. Cave spider limits are much lower.
2021-06-23 22:50:57 +03:00
Pasi Kallinen
2f25556025 Conflict based off of charisma
Higher charisma will make it more likely for monsters to be affected.
Conflict will also now require the monster to see the hero.

Originally from SporkHack by Derek Ray.
2021-05-19 18:35:00 +03:00
PatR
6c70b46ea1 more monster/door interaction
Apply visibility fixups for monsters triggering door trap
explosions or digging through doors similar to the monster-opens-
door-handling from a couple of days.  Again, the issue is that
hero/player can see a closed door in situations where they can't
see an open one, and messages about the door being opened or
destroyed need to take that into account when seeing a closed
door go away.

Not as thoroughly tested as monster just opening closed door.
2021-03-23 08:52:36 -07:00
PatR
f209cac5f6 fix #H6928 - monster vs closed door messaging
Report from roughly two and half years ago was about "<monster>
opens the door" without displaying <monster>.

Monster movement first decides whether a monster can pass closed
door.  If so, the monster is placed at the door spot, a message
is given about that movement (unlock, open, smash down, &c), and
finally the map is updated.

Changing the sequence to update the map before issuing the door
message was not sufficient to fix this.  In the corridor plus
closed door plus lit room map fragment shown here, when 'O' moved
to '+', you would see it there if the hero is at '1' or '2', but
not if at '3', '4', or '5'; open door was shown instead.  But the
message described 'O' accurately rather than as "it" for all those
hero locations.
:   -----
: #O+1...
:   |2...
:   |3...
:   |4...
:   |5...
:   -----

For 3,4,5 the #vision command shows the closed door as 3 before
the O move, but blank (0) after.  In other words, the closed door
is within line of sight but once opened, the doorway spot isn't.
It makes sense that the closed door behaves like a wall but I'm
not sure whether the behavior for an open door's breach does too.

I had an awful workaround that successfully displayed the monster,
but it wouldn't show the same thing if the door was already open,
so I've changed the situation to yield "You see a door open."
2021-03-21 02:33:20 -07:00
nhmall
f963c5aca7 switch source tree from k&r to c99 2021-01-26 21:06:16 -05:00
nhmall
62f25fd000 clear five warnings for "set but not used" variables
Note: the line numbers referenced in the warning messages below are not in sync
with the NetHack-3.7 branch and should be disregarded

files.c: In function 'get_saved_games':
files.c:1168:9: warning: unused variable 'n' [-Wunused-variable]
 1168 |     int n, j = 0;
      |         ^

mhitm.c: In function 'mdamagem':
mhitm.c:843:13: warning: variable 'cancelled' set but not used [-Wunused-but-set-variable]
  843 |     boolean cancelled;
      |             ^~~~~~~~~

mhitu.c: In function 'hitmu':
mhitu.c:943:9: warning: variable 'uncancelled' set but not used [-Wunused-but-set-variable]
  943 |     int uncancelled;
      |         ^~~~~~~~~~~

mklev.c: In function 'place_branch':
mklev.c:1214:20: warning: variable 'br_room' set but not used [-Wunused-but-set-variable]
 1214 |     struct mkroom *br_room;
      |                    ^~~~~~~

monmove.c: In function 'm_move':
monmove.c:874:43: warning: variable 'doorbuster' set but not used [-Wunused-but-set-variable]
  874 |     boolean can_open = 0, can_unlock = 0, doorbuster = 0;
      |                                           ^~~~~~~~~~
2021-01-25 12:57:47 -05:00
Pasi Kallinen
bc8dd92621 Monster ranged attacks and staying away from hero
Move the check for monsters that want to stay away from hero
due to having a ranged attack into a separate function.

Add monsters with polearms and breath attacks to it.
Monsters with breath attacks stay away only if they haven't
used their breath recently, or if they are injured.
2021-01-06 14:38:39 +02:00
Pasi Kallinen
fb188dc1aa Unify mfndpos monster movement flags 2020-11-28 12:49:18 +02:00
PatR
0e713dc4e9 fix #K2617 - metallivores eating iron bars
Monsters with rust attacks (rust monster) and corrosion attacks
(black pudding, gray ooze) can eat or otherwise destroy iron bars
but xorns could only move through the iron bars spot without being
able to eat the metal there.  Change xorn to eat bars instead of
phazing through them.  Lets rock moles eat bars too.

Hero polymorphed into a rust monster would eat bars if trying to
move to their location but couldn't do so if already there (maybe
was in xorn form and now in rust monster form).  Xorns could pass
through them but not eat them.  Allow hero metallivores to eat
bars at the current location via 'e', similar to eating food off
the floor.  Hero as rock mole behaves like rust monster.
2020-10-23 19:43:10 -07:00
Pasi Kallinen
aeb0ea65e3 Mild Zombie Apocalypse
When a zombie (or lich) kills a monster in melee without a weapon,
the monster can rise few turns later as a zombie.

The only creatures that can be zombified are ones that actually have
a zombie counterpart monster. A zombie cannot turn a jackal into
a zombie, for instance. But it could turn a shopkeeper into a human
zombie, or a dwarf king into a dwarf zombie.

Zombies will fight with monsters that can be turned into zombies.

Originally this was a SliceHack feature, but this is based on xNetHack
version of it, with some modifications.
2020-10-23 19:47:10 +03:00
Pasi Kallinen
f38cb63714 Spitting monsters try to stay away from melee range 2020-10-18 19:18:38 +03:00
PatR
239620ffd7 fix pull request #386 - monster interaction
The previous teleport scroll fix was mislabeled with this pull
request number.  Too late to fix that now; should have been

Closes #307

Now...  Interaction between voluntarily busy hero (resting,
searching, and so on) with approaching monsters to decide whether
to stop had some inconsistencies.

Really closes #386
2020-09-18 15:53:43 -07:00
nhmall
ac9ba38449 file header bump from "NetHack 3.6" to "NetHack 3.7" 2020-08-03 22:07:36 -04:00
PatR
a37975b625 fix pull request #367 - mind flayer psychic blast
hitting a hidden monster didn't reveal that monster.  It stayed
hidden despite the feedback describing it as if it could be seen.

The pull request's two line fix handled a monster's blast hitting
another monster but left two related issues as-is:  monster's blast
hitting hidden poly'd hero left hero unrevealed and poly'd hero's
blast left hidden monster unrevealed.  Same code, different bug:
poly'd hero's blast affected mindless monsters.

This unhides an affected target before the message about it being
hit rather than after.  That would look better if preceded by a
message describing the object (mimic or hides-under) or furniture
(mimic) or empty spot (ceiling hider) as being or concealing a
monster but I didn't put in sufficient effort to accomplish that.

Fixes #367
Fixes #362
2020-07-14 04:55:53 -07:00
PatR
7817e69c41 two new monsters from slash'em
Adds two monsters originally from slash'em.  I used the slash'em
tiles this time, also its code as a starting point but made various
revisions.  Both the tiles could benefit from some touch-ups.

displacer beast:  blue 'f'.  Attempting a melee hit (ie, trying to
  move to its spot) has a 50:50 chance for it to swap places with you.
  Fairly tough monster to begin with, then half your ordinary attacks
  effectively miss and if you try to face a mob by retreating to a
  corridor or backing into a corner you can end up being drawn back
  into the open.  I added bargethrough capability, and also it won't
  be fooled about hero's location by Displacement.  [It only swaps
  places during combat when contact is initiated by the hero, not
  when attacked by another monster or when attacking.]

genetic engineer:  green 'Q'.  Its attack causes the target to be
  polymorphed unless that target resists.  Hero will almost always
  have magic resistance by the time this monster is encountered, but
  it can make conflict become risky by hitting and polymorphing other
  monsters.  Slash'em flagged it hell-only but I took that flag off;
  I also took away its ability to teleport.  Slash'em polymorphs the
  hero if a genetic engineer corpse is eaten; that's included and I
  introduced that for monsters too.

I added both of these to the list of candidates for monster spell
'summon nasties' and for post-Wizard harassment.

I also gave all the 'f's infravision.  Probably only matters if the
hero polymorphs into a feline.

Displacer beast is originally from AD&D which depicts it as a six-
legged cougar with a pair of tentacles; it has Displacement rather
be able to affect an attacker's location.  I think genetic engineer
is original to slash'em where it expands Q class but seems mainly to
be the base monster for Dr.Frankenstein (a unique monster with a
one-level side-branch lair in slash'em's incarnation of Gehennom).
2020-05-03 14:13:08 -07:00
Pasi Kallinen
bddb80f13c Make hostile monsters with launcher and ammo keep away
If a hostile monster is wielding a ranged weapon, and is carrying
appropriate ammo for it, make the monster try to stay away,
outside the melee range.
2020-04-14 15:19:30 +03:00
Pasi Kallinen
297eb934a7 Fix monster booted into limbo trying to act
There's a chance that a tactics-using monster (eg. arch-lich)
teleporting next to you on a full level would get booted off
into limbo. After that, if the monster tried using an item
in the same action you'd get panic "relmon: mon not in list"

Fix this particular case by checking monster mstate.
Other cases may lurk in other places that eventually call mnexto.
2020-04-07 17:23:23 +03:00
PatR
995a6bf4fe purple worms
Compiler complained about 'ptr' possibly being used unitinialized
in meatcorpse() and in this case it was right.  meatcorpse() was
cloned from meatobj() but the necessary initialization was missing.

Purple worm would devore an entire stack of corpses in one bite.
Split one off and have it eat that instead.

I'm not sure whether attempting to revive a Rider corpse can force
a monster off the level to make room.  If so, meatobj() and
meatcorpse() weren't prepared to handle that, nor was their caller.
It appears that the monster (either g.cube or purple worm) will
only eat as it moves so can't revive a Rider on a completely full
level since it won't be able to move in that situation.  I fixed
the caller to be prepared to handle a result of 3 (no further
action allowed) instead of just dealing with 2 (died), but I didn't
fix either of the meatfoo() routines to return 3 since bumping the
eating monster off the level seems to not be possible.

Don't let purple worms eat lichen corpses, regardless of whether
they'll swallow live ones.
2020-04-05 05:57:37 -07:00
Pasi Kallinen
cf1c725148 Purple worm changes
Shriekers only spawn purple worms when they're appropriate difficulty.
Non-tame Purple worms eat corpses off the ground.
Baby purple worms attack shriekers.
Hero polyed into baby purple worm is warned against shriekers.

Original changes by copperwater <aosdict@gmail.com>, added with some
formatting adjustments and consolidation.
2020-04-05 12:44:25 +03:00
Pasi Kallinen
e34f123698 Make hezrous stink 2020-04-03 21:05:49 +03:00
Pasi Kallinen
87513ad6bf Fix polymorphing monster trying to dig undiggable wall
Not sure if this can actually happen in a non-modified game, but
my fuzz testing stopped here, so deal with it.

If a polymorphing monster turns into an earth elemental or other
wall-phasing monster, it can wander into a non-diggable area, and
then turn into a tunneling monster.
This caused mdig_tunnel to issue an impossible.
2020-03-28 15:43:10 +02:00
PatR
3eed500886 fix #K669 - 'nasty' monster summoning
Report complained about multiple Archons causing his character to
be swarmed by monsters on the Plane of Fire.  I don't think that
the behavior has changed significantly from how it worked in 3.4.3.
Nobody can summon an Archon directly because they're excluded from
the nasties[] list.  But whenever summoning picks a genocided
'nasty', the result gets replaced by random monster of appropriate
difficulty for the level (which could be an Archon for a high level
character in the endgame).  [Note that that won't pick an Archon
in Gehennom or at arch-lich outside of there because the random
monster creation honors the only-in-hell and never-in-hell flags;
picking from the nasties[] list doesn't.]

This prevents that for any creature (except arch-lich or the Wizard)
casting the summon nasties spell.  If a replacement creature is a
spellcaster it now has to have lower difficulty than the summoner.
If not, it will be discarded even though its difficulty is classified
as appropriate.  So to summon an Archon, the summoner has to have
higher difficulty than an Archon; arch-lich and the Wizard are the
only ones meeting that criterium.  When summoner is an arch-lich,
it can't summon another arch-lich (since that wouldn't have lower
difficulty than the summoner) and can summon (via replacement for
genocided type, and only if outside of Gehennom) at most one Archon.
When summoner is the Wizard, he could summon an arch-lich (when in
Gehennom; demoted to master lich elsewhere--see below) or an Archon
(outside Gehennom only), but at most one per summoning.

For post-Wizard harassment, which effectively has infinite
difficulty level, it could still happen.  However, each instance of
harassment is only allowed to create at most one Archon or arch-lich
now, so chain summoning should be lessoned.  Also if it tries to
pick an arch-lich when outside of Gehennom it will switch to master
lich instead (which won't be allowed to summon an Archon or an arch-
lich or even another master lich).

(The monmove.c bit is unrelated, just some comment formatting that
I had laying around that got mixed in.)
2020-03-27 19:05:52 -07:00