when attempting to crawl out of water fails and hero is life-saved
or wizard-/explore-mode player declines to die. If the hero is saved
by positioning him/her one step further away from ball and chain,
teleds() tries to drag them, but if 'emergency disrobe' left the hero
stressed or worse, dragging fails. Ball and chain were being left
where they were, with chain no longer being adjacent to hero.
If drag_ball() fails, have teleds() teleport ball and chain to hero's
new spot, same as when that isn't within range of a one step drag.
Report was for Sokoban but it applied anywhere: if a teleported
boulder landed in a pit or trap door or hole and flooreffects() used
it up (so returned True), rloco() didn't update the location it was
teleported from and it appeared not to have moved. (Line of sight was
updated to reflect its absence but map spot wasn't redrawn without it.)
A couple changes dealing with overcrowded levels. So many monsters
are moving from the Plane of Water to the Astral Plane that the
latter can start out completely full.
Give monsters who trigger the endgame portals a 6/7 chance to not go
through ('home' elementals or any monster carrying the Amulet already
wouldn't go through). They should learn about magic portal trap in
the process and not voluntarily step on that afterward.
When the Wizard or other covetous monster tries to teleport next to
the hero and fails, he was being sent to limbo. There's no need for
that; he's already on the map and can just stay where he is. That
doesn't actually help with the endgame population issue, it just
fixes a couple of uses of mnearto().
I have significant changes for mnearto() and elemental_clog() that
also help with this but will test those more before committing.
While testing, I noticed that I could completely fill the Water level
with air elementals.
Hero can't fly or levitate or water walk into/onto water locations
on Water level without drowning/crawling out the water, and monsters
shouldn't have been able to but could, then they were hit by drowning
since minliquid used different criteria than movement. But goodpos(),
used for teleport destination and new monster creation among other
things, consided water locations acceptable on that level for
non-aquadic creatures with Fly/Lev/Wwalk ability.
It explains why so many dragons and other 'nasty' monsters have been
ending up on the vanquished monsters list when hero uses level
teleport to go directly there from level 1. They've either been
getting created in water and then they drown when it's their turn to
move or moving into it to approach the hero and drowning (not sure
whether that case is immediate or on next move). There's no message
since hero doesn't see it, and air elementals didn't drown since thy
don't breathe.
This doesn't solve the <0,0> problem but it does prevent mnexto()
from using uninitialized coordinates if enexto() fails. It also adds
several debugging messages.
enexto() was ignoring map row #0 (unlike column #0, row #0 contains
valid map locations). Fixing that doesn't matter for Plane of Water
though since that row is stone there--that's probably a bug. It was
also repeatedly re-testing the top+1 and bottom rows and left and
right columns after they had already failed to be acceptable. It
still does some of that, but less.
Fixes#177
The monst struct has 'mintrinsics' field which attempts to handle
both mon->data->mresists and extrinsics supplied by worn armor, but
polymorph/shape-change was clobbering the extrinsics side of things.
Potentially fixing that by changing newcham() to use set_mon_data(...,1)
instead of (...,0) solved that but exposed two other bugs. Intrinsics
from the old form carried over to the new form along with extrinsics
from worn armor, and update_mon_intrinsics() for armor being destroyed
or dropped only worked as intended if the armor->owornmask was cleared
beforehand--some places were clearing it after, so extrinsics from worn
gear could persist even after that gear was gone.
So, fixing the set_mon_data() call in newcham() was a no go. This
fixes update_mon_intrinsics() and adopts the suggested code from
github pull request #177 to have mon->mintrinsics only handle worn
gear instead of trying to overload innate intrinsics with that. This
is a superset of that; the flag argument to set_mon_data() is gone
and mon->mintrinsics has been renamed mon->mextrinsics. (The routine
update_mon_intrinsics() ought to be renamed too, but I didn't do that.)
Fixes#101
If you tell the vault guard your name, drop carried gold, wait one
turn, then pick up the gold again, the guard will move a step away
during the wait. If you teleport away, the guard will seal vault
walls and then park himself on the one-square (so far) temporary
corridor adjacent to the vault wall. Periodically he'll say "Move
along!" and the hero will hear it, regardless of location on the
level. Unless you dig a corridor to rescue him, or one or more of
the vault's walls get breached again, he will never move.
The report emphasized that you could use this to steal the vault's
gold, but it relies on being able to teleport beyond the gaurd's
reach and if you can do that, you might as well do so before the
guard comes. The stranded guard, and him saying "Move along!" when
no longer leading hero out of the vault, are more significant bugs.
Bonus fix: if the game ends and the guard seals up the vault while
the hero is in a spot that gets fixed up (vault wall or temporary
corridor) don't give the "You are encased in the rock" message if
game end was due to death rather than quit.
Fix fuzzer feedback. The new wizard mode ^T menu had an early return
which bypassed destroy_nhwindow(), leaving the menu around. Fuzzer
eventually got "No window slots!" panic from tty. Make sure that the
menu window is torn down fully before returning.
Also, make the normal wizard mode teleportation chioce be preselected
so that not picking anything doesn't lead to an early return any more.
ESC still does though.
Fixes#172
Casting teleport-away via ^T used different requirements for energy,
strength, and hunger than casting it via 'Z'. The strength and hunger
requirements were more stringent, the energy one more lenient. When
it rejected a cast attempt due to any of those, it used up the move,
but 'Z' didn't.
When testing my fix, I wanted an easier way than a debugger to control
how ^T interacts with wizard mode, so finally got around to a first
cut at being able to invoke it via wizard mode but not override those
energy/strength/hunger requirements. It uses the 'm' prefix to ask
for a menu. 'm^T' gives four options about how to teleport. (There
are other permutations which aren't handled.)
Also noticed while testing: ^T wouldn't attempt to cast teleport-away
if you didn't know the corresponding spellbook. 'Z' will attempt that
because it is possible to forget a book and still know its spell.
Jumping or teleporting while levitating in xorn form wouldn't toggle
blocking of levitation when moving from open spots to wall/stone and
unblocking of same when moving the opposite way.
This handles those cases but there are no doubt others. The only
other one I checked was when failed #untrap moves hero onto trap.
That case works correctly--at least after this fix is in place.
Noticed while working on it: change of terrain didn't always update
the status line. When levitation became blocked, it still said Lev
and when unblocked, didn't say that. Next status update got status
condition back in sync.
Add code to run a fuzz tester, simulating (more-or-less) random
keyboard mashing. There's no option to turn it on, you need to
set iflags.debug_fuzzer on via a debugger or something along
those lines.
Make being trapped in/on/over floor block Levitation and Flying, the
way that being inside solid rock already does, and the way levitating
blocks flight.
Blocked levitation still provides enhanced carrying capacity since
magic is attempting to make the hero's body be bouyant. I think that
that is appropriate but am not completely convinced.
One thing that almost certainly needs fixing is digging a hole when
trapped in the floor or tethered to a buried iron ball, where the
first part of digactualhole() releases the hero from being trapped.
If being released re-enables blocked levitation, the further stages
of digging might not make sense in some circumstances.
I recently realized that being held by a grabbing monster is similar
to being trapped so should also interfere with levitation and flying.
Nothing here attempts to address that.
Save files change, but in a compatible fashion unless trapped at the
time of saving. If someone saves while trapped prior to this patch,
then applies it and restores, the game will behave as if the patch
wasn't in place--until escape from trap is achieved. (Not verified.)
Allow the 'm' prefix for wizard mode level teleport command. Using
it skips the initial prompt for level destination and goes directly
to the menu of special level locations that you get when answering
'?' to that prompt.
I ended up not using this, but it might as well be included for
potential future use. Extend mlevel_tele_trap() to support forcing
a monster off the current level to make room either for the hero or
some other monster. goto_level() does something similar when the
hero is arriving on a level. This is for situations where the hero
is already there (such as divine aid attempting to fix STUCK_IN_WALL).
mlevel_tele_trap(mon, (struct trap *) 0) will usually move 'mon' off
the level, scheduled to migrate back if the hero leaves the level and
subsequently returns. 'Usually' because it doesn't work in endgame
and certain monsters are excluded regardless of dungeon location, so
caller has to be prepared to try to move another monster (or resort
to goto_level()'s unconditional forced migration).
Requested by one of the beta testers 13 months ago... when a visible
monster becomes invisible and vanishes, mark its map location with
the remembered, unseen monster glyph. (When the player zaps a
monster with a wand of make invisible, that only happens if the wand
type is known. I'm not sure that's right but didn't alter it....)
The request suggested also doing it for a monster who disappears by
teleporting away, but I haven't attempted to implement that.