When a monster did something trying to get out of a boulder fort,
it usually meant teleporting or going down stairs or a hole.
The code didn't check for the action return value, and resulted
in a migrating monster being able to throw a potion at hero.
If a monster cannot move, for example because it's being
blocked off by boulders or walls, it will try to escape by some
method - such as a wand or scroll of teleportation.
The mind blast code was previously a part of dochug().
This commit pulls that code into its own function, and also
happens to eliminate a goto and label with no change in functionality.
This commit removes the gotos from set_apparxy, making it easier to read.
It also cuts out at 1-2 variable assignments on certain calls,
so technically it is an efficiency win as well.
Reported by copperwater: if an engulfer swallowed a mounted hero,
odd things could happen if the hero dismounted. The steed would be
silently expelled and float-down flooreffects were attempted.
It turns out that if the engulfer is classified as an animal (so
purple worm, lurker above, trapper), the hero got "plucked from
<steed>'s saddle" and was forcibly dismounted prior to completing
the engulf operation, but non-animals (vortices, air elemental,
ocher jelly, Juiblex) swallowed the hero+steed intact. The most
straightforward fix to dismounting-while-engulfed issues is to change
engulfing to always pluck the hero from the saddle even when the
engulfer isn't an animal.
If there's no room on the level to place the former steed, it gets
killed off. I looked at changing that to put the steed into limbo,
waiting to migrate back to the current level if hero leaves and
subsequently returns, but that breaks movemon()'s assumption that
when monsters are in the process of moving, only the currently moving
one can be taken off the fmon list to be placed on migrating_mons.
[The recently added monster knockback code violates that assumption
too when knocking the victim into a level changer trap. It needs to
be fixed in one fashion or another.]
Make monsters with magic and gaze attacks avoid hero,
just like spitters and breathers already did.
Some small code cleanup related to the ranged attacks.
Add macros to convert AD_foo, WAN_foo, and SPE_foo to relative values
for passing to BZ_U_foo and BZ_M_foo macros.
Change some return values in monster spellcasting function from
magic numbers to MM_MISS or MM_HIT.
Make buzzmu consider hero resistances - previously the
monster with innate zapping ray (Angels and Asmodeus) would
just keep doing that attack, but they will now just curse if
it saw the hero resist the attack.
One of the drivers of this change was that screen coordinates require a
type that can hold values greater than 127. Parameters to the window
port routines require a large type in order to be able to have values
a fair bit larger than COLNO and ROWNO passed to them, particularly for
their use to the right of the map window.
This splits the uses of xchar into 3 different situations, and adjusts
their type and size:
xchar
|
-----------------------
| | |
coordxy xint16 xint8
coordxy: Actual x or y coordinates for various things (moved to 16-bits).
xint16: Same data size as coordxy, but for non-coordinate use (16-bits).
xint8: There are only a few use cases initially, where it was very
plain to see that the variable could remain as 8-bits, rather
than be bumped to 16-bits. There are probably more such cases
that could be changed after additional review.
Note: This first changed all xchar variables to coordxy. Some were
reviewed and got changed to xint16 or xint8 when it became apparent that
their usage was not for coordinates.
This increments EDITLEVEL in patchlevel.h
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).
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.
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.
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.
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.
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.
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.
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.
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
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.
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
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.
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.
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...
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.
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.
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.
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."