<email deleted>:
> If you enter a magic trap on the same turn that you lose your levitation
> and "float gently to the floor", you are hit by the trap twice.
I don't think this is actually a bug, but it does look fairly strange
if there aren't any monsters attacking (after you move on to the trap,
monsters get a chance to move too before timeouts are run, but if there
aren't any messages triggered by monster activity then it feels like the
timeout and second activation happens immediately). To prevent this, if
levitation is due to time out on the same turn that a trap is being
entered, either extend the duration by an extra move or make it end
immediately instead of waiting until end of current turn. Deferring
timeout is a lot easier but doing that unconditionally would allow player
to move back and forth between adjacent traps without ever descending.
The early timeout might lead to anomalous behavior in obscure cases; it
seems to be working ok so far though.
From the newsgroup: it was possible to saddle, mount, and ride on a
sleeping jabberwork without it ever waking up. Movement was checking for
timed sleep (!mon->mcanmove, set when mon->mfrozen contains a timer count
for either sleep or paralysis) but not indefinite sleep (mon->msleeping).
This moves the checking into its own routine which handles both types.
And it gives monsters a chance to wake up when they get saddled or mounted.
Mentioned by <Someone>, who suspected that the fix for C343-114 dealt with
this. When a giant picks up a boulder from a location where more than one
is present, line-of-sight would be inappropriately cleared, as if the
remaining boulders were transparent. (He said that he got no pickup
message when the giant picked up the boulder. I do, and have not tried to
figure out whether this is a post-3.4.3 difference.) Pushing a boulder
onto a landmine had the same bug, although you wouldn't notice unless there
were at least three boulders to be pushed (mysterious ability to push more
than one boulder in a turn strikes again: first one triggers the trap and
is destroyed, allowing hero to see through any others; second fills in the
resulting pit; third gets moved to the former trap spot and [probably--I
haven't checked] re-blocks vision; fourth, if any, stays put; if only one
or two are present, the change in vision is expected and the fact that it
happens too soon in the two boulder case would probably go unnoticed.
Polymorph of a boulder also opened up vision without checking whether any
others are present.
An existing, evidently overly optimistic, fixes34.4 entry covers this.
From a bug report...): pushing a boulder onto a level teleporter trap
could repeat the
You push the boulder and suddenly it disappears!
message. That would happen whenever the teleport destination was the same
as the current level (20% chance). The boulder wasn't being moved onto the
trap location so was still present when the pushing code tried to handle
the next one in the pile. I've changed so that pushing stops whenever a
pushed boulder is affected by a trap, and also so that the boulder gets
moved as usual when a level teleporter fails to send it somewhere.
I've always thought it's pretty strange that pushing ever operates
on more than one boulder in the same turn in any situation, but I haven't
changed that for the non-trap cases. (Usually the first boulder pushed
ends up blocking the second one, so you get a "you try to move it, but
in vain" message which seems odd since you just moved one. But if there's
a pool of water or lava in the path, you can actually push multiple
boulders successfully.)
I'm pretty sure that some pre-standard compilers don't know how to
apply an initializer to a variable of type union. Unfortunately, I don't
have access to one to check. Fortunately, there's no need to explicitly
initialize `zeroany' since the default value is what we want--the first
field will be set to zero or null as appropriate (null in this case).
Strictly speaking, this isn't adequate; what if long is wider than a
pointer rather than narrower? Using `= {DUMMY}' didn't handle that case
either; the ordering of the union's fields controls which bits get stored.
As a practical matter, it should make no difference. As long as the code
reading a union accesses the same field as the code writing that union set
up in it, anything in extraneous bits should be irrelevant--except perhaps
when a debugger tries to format things. The whole issue has always been
implicitly based on the assumption that null pointers have all bits zero
in the first place; that's typical but not guaranteed.
[the problem in the earlier rev was tracked to cleanup_burn(),
where arg was holding a (genericptr_t) timer id, and
passed directly to del_light_source() as is.]
P64 (Win64) has a 64 bit pointer size, but a 32 bit long size.
Remove some code that forced pointers into a long int, and
vice versa where information could be lost.
This part deals with light source functions and their
arguments mostly, and switches some arguments
from type genericptr_t to 'anything'.
P64 (Win64) has a 64 bit pointer size, but a 32 bit long size.
Remove some code that forced pointers into a long int, and
vice versa where information could be lost.
This part deals with light source functions and their
arguments mostly, and switches some arguments
from type genericptr_t to 'anything'.
- remove an unreferenced variable
- continue with recent code trend towards having DEADMONSTER()
check in its own if/continue statement in a few more places
Attempt to fix a buglist item: if hero poly'd into iron golem form
enters a pool of water and drowning triggers reversion to human/whatever
form due to water damage, he will fall into that pool again, crawl or
teleport out, then redundantly crawl or teleport out for the initial entry.
[ spoteffects -> drown -> losehp -> rehumanize -> polyman -> spoteffects
-> drown ]
I don't have a lot of confidence in this fix. It does handle the
reported problem, and hasn't broken a couple of earlier tricky cases
(ice melting to water, land mine turning into a pit). But drown() and
lava_effects() seem to leave a trail of special case handling wherever
they appear so they--or spoteffects, or both--ought to be redone somehow.
<email deleted> wrote the following on April 10, 2006:
> When blind and levitating, you can produce a message - "You try to feel what
> is lying here on the ice. But you can't reach it!" - which reveals too much
> about the terrain below you.
This one turned out to be more effort than I had
originally anticipated.
We had a bug report requesting that zapping a wand of digging
laterally while in a pit should dig beside you. That seemed
like a reasonable enough request, but this ended up with
the following results:
- needed to check where this should not be permitted, or at
least where there should be special-case code because there is
something such as furniture on the surface above the dig
point.
- now tracks conjoined pits through new fields in the trap
structure, hence the pathlevel increment. The array of
8 boolean values represents each of the 8 directions
around a pit.
- Previously, pits could be adjacent to each other as two
individual pits, in which case moving between them
results in a fall as you went into the next pit. That
behavior is preserved.
- Pits created either by zapping a wand of digging
laterally while in a pit, or by "clearing debris"
between two adjacent pits via a pick-axe, sets the
conjoined fields for those two pits. You cannot
create a brand new adjacent pit via pick-axe, only
with the wand.
- The hero can pass between conjoined pits without
falling.
- dighole() was hijacked for adjacent pit digging,
so the ability to pass coordinates to it and
its downstream functions was added (dig_up_grave()
for example). dighole() does pretty much everything
appropriately for this adjacent digging, more so
than calling digactualhole() directly.
- moving into a conjoined pit that has spikes still
does damage, but less so that "falling" into the
spiked pit, and you "step on" the spikes rather
than falling into them.
- Not done: should pits with the conjoined fields
set be referred to as 'trenches' rather than pits
in messages and identifications?
From a bug report, amorphous creatures can fit underneath
closed doors but could still be considered too big to fit through diagonal
gaps. Let them and several other shapeless or flexibly shaped critters
squeeze through provided that they pass the not-carrying-too-much check.
These should have been included with a "#dipping from steed" patch
three years ago. I don't know whether I missed them outright, neglected
to cut diffs at the time, or just forgot to apply the diffs to my cvs
directory prior to committing the rest of that patch.
A post-3.4.3 change dealing with reaching into pits resulted in "you
sit on the air" if you used the #sit command after escaping a pit trap.
Change can_reach_floor() so that caller explicitly controls whether being
on the brink of a pit is a condition that prevents reaching the floor.
This also splits a fairly common message about not being able to reach the
floor into a separate routine.
There is still oddness here: if you're polymorphed into a flyer,
#sit yields "you sit down" followed by "you fly over a pit" (latter occurs
when escaping trap activation). A ceiling hider behaves similarly, but
the second message is "you escape a pit" and doesn't sound quite as silly.
Perhaps #sit should pass TOOKPLUNGE to dotrap(), or maybe there's some
better way to handle this?
<Someone> reported that if you polymorph into a flying monster while in a
pit, you must take u.utrap turns to first climb out before you can fly. Of
course, once you're out, you can swoop down into the pit to pick things up
w/o delay. Rather that have you automatically fly out (e.g. like quaffing
a potion of levitation), I thought it was better to take a turn to fly out,
so that's what I've implemented.
The code to deal with exiting a pit is moved to a new climb_pit function
and the "up" command now lets you climb from a pit too (something I've
found non-intuitive in the past).
Finally, I noticed that non-moving monsters could still go up/down even
though they couldn't move around. Added non-moving checks in doup/dodown.
move the message so it's before the mintrap test. newsym's are needed
to ensure the display is correct if a --More-- prompt results. I left the
"frighten" message alone, except for tense. As per Pat's suggestion, I
changed the wording to future-proof the message.
<Someone> complained that his compiler was giving these
warnings:
cmd.c:2119: warning: declaration of `expl' shadows a global declaration
dungeon.c:292: warning: declaration of `rand' shadows a global declaration
exper.c💯 warning: declaration of `exp' shadows a global declaration
files.c:278: warning: declaration of `basename' shadows a global declaration
hack.c:1102: warning: declaration of `expl' shadows a global declaration
pickup.c:2081: warning: declaration of `select' shadows a global declaration
role.c:1060: warning: declaration of `conj' shadows a global declaration
Something from <Someone>'s list: some messages have hardcoded references
to "helmet" which sound strange when the character is wearing a hat or cap.
helm_simple_name() is comparable to the existing cloak_simple_name(). It
returns "helm" or "hat" depending upon whether the helmet provides the
same protection that yields the assorted repetitions of "fortunately,
you are wearing a hard helmet". This choice ends up categorizing elven
leather helm as a hat (which I think is ok given that its undiscovered
description is "leather hat"), contrary to <Someone>'s suggestion that the
distinction be made based on whether the helmet was made of cloth.
I started on this a year and a half ago but didn't commit it.
Unfortunately I don't remember why and haven't done any significant
additional work now--just recovered from some intervening bit rot and
confirmed that the patch as is seems to be working ok (in the trunk; the
branch side has not been tested). I suspect that I meant to look for
additional helmet messages which could benefit from conditional headgear
description. (Those "hard helmet" ones don't need it, although they
should perhaps be moved into a common routine instead of being replicated.)
A user pointed out that you lose pacifism conduct if you kill your
pet by displacing it into a trap but you don't gain any experience in
the process. Make this consistent with killing monsters in other ways:
if you get blamed for it then you should also get credit for it.
Probably minliquid() and mintrap() should take another argument so
they can call killed() instead of mondead() when necessary, but I didn't
go to that much effort....
"<Someone>" on January 8, 2004, wrote:
> A Valkyrie on the Quest home level, wearing an
> amulet of magical breathing, enters a fire trap
> out on the ice:
>
>> A tower of flame erupts from the ice!
>> The ice crackles and melts.
>> You fall into the water. You sink like a rock.
>> But you aren't drowning. You touch bottom.
>> A cascade of steamy bubbles erupts from the bottom!
>
>Should the trap really be being triggered twice, once on ice and
>once underwater, when I've only moved onto the location once?
Change pit behavior to always mark a non-flying poly'd player as trapped in
a pit, even when Passes_walls is set. This allows players polymorphed into
xorns to descend into pits and pick things up. In this case, any attempt
to move out of the pit now takes a turn but always succeeds. Also fixed
a related bug (w/o ID) that a player could become trapped as if in a pit
when leaving xorn form because u.utrap wasn't checked, and simplified the
code since the extra Passes_walls checks are no longer needed. Also
updated code in sit.c that duplicated uteetering_at_seen_pit.
Fix the recently reported problem:
" If there is a corpse in a pit, you have to enter the pit in order to pick
" it up, however you are can eat it without being in the pit.
If pit bottoms aren't reachable, then can_reach_floor() needs to know
about it. I suspect that this change is likely to create some other
bugs though.
- [fixed in trunk] Jumping/Newton's-Thirding into something solid
- [fixed in trunk] Being hit by Mjollnir on the return
- [fixed in trunk] Contaminated or boiling water from a sink
- [fixed in trunk] Falling on a sink while levitating
- [fixed in trunk, fire only] Any passive attack
- [fixed in trunk] Zapping yourself with a wand, horn or spell
- [fixed in trunk] Burning (un)holy water
- [fixed in trunk] Thrown potion (bottle)
- [fixed in trunk] Bumping head on ceiling by cursed levitation
- [fixed in trunk] Exploding rings and wands (under all circumstances)
- [fixed in trunk] Stinking cloud damage
- [fixed in trunk] Sitting in a spiked pit, in lava
- [fixed in trunk] Exploding spellbooks
- [fixed in trunk] Falling off or failing to mount a steed
- [fixed in trunk] Falling into a (spiked) pit
- [fixed in trunk] Land mine explosion
- [fixed in trunk] Fire traps
I wrote to the devteam early last week:
> Given my understanding of travel, it's supposed to be somewhat intelligent,
> and "convenient", and should, therefore avoid walking into water, lava,
> traps, or other things that distant movement would avoid, even if you're
> right next it. Unless... the travel destination is the "bad" location
> next to you when the travel starts.
To that end...
- add a context (iflags in 3.4.3 to maintain savefile compat) flag to
differenciate the first travel step from later steps, to allow the
detection of the final sentence, above.
- several changes to set/reset the travel1 flag as needed
- add code to findtravelpath to treat the first step specially if it's
the only step, allowing forced travel into a "bad" location
- correct the "don't travel over traps" code, which was getting confused
because hero's starting location was being avoided
- add code to avoid traveling into water and lava, duplicating
checks used for non-travel running
- fix some strange "guess" travel behavior: avoid zigzag paths when there's
a more direct path (even though the number of moves is the same)
- trunk change adds a new DISP_ALL tmp_at type, and uses it in some debug
code for travel, debug changes not added to the 3.4.3 branch
Allow migrated objects to break on arrival. Added code to obj_delivery to
cause this, along with a flag to keep breakage from occurring. The new
flag isn't used yet, because all the current object migration involve
objects that were moving/dropping. To help make this change, rloco now
returns whether the object was placed or not, so caller can know if an obj
pointer is still valid or not.
Making the breakage messages for MIGR_NEAR_PLAYER objects show up after the
new level is displayed required some effort (rather than while the old level
was still displayed, which was confusing), due to the needs of goto_level.
- obj_delivery now has 2 passes, one for before player arrives, another after,
allowing the two cases to be treated differently
- goto_level calls obj_delivery twice (run_timers is not called twice,
since the run required before the level is displayed will have already run
any timers on migrating object)
- kill_genocided_monsters now kills eggs on the migrating_objs list too
Reported a while back, a (stonable) hiding monster will hide at a location
containing only a cockatrice corpse. While it would be interesting to
allow monsters to try, and stone themselves as a result, I chose the
simpler fix which is to not have monsters hide in such situations. I found
the hiding code was duplicated in several places, so I moved it into a new
hideunder() function that works for both the hero and monsters.
Introduce a new set of functions to manage delayed killers in the trunk, used
in addressing the various reports of delayed killer confusion. Since existing
delayed killers are related to player properties, the delayed killers are
keyed by uprop indexes. I did this to avoid adding yet another set of
similar identifiers.
- the new delayed_killer() is used for stoning, sliming, sickness, and
delayed self-genocide while polymorphed. Some other timed events don't
use it (and didn't use the old delayed_killer variable) because they
use a fixed message when the timeout occurs.
- A new data structure, struct kinfo, is used to track both delayed and
immediate killers. This encapsulates all the info involved with
identifying a killer. The structure contains a buffer, which subsumes the
old killer_buf and several other buffers that didn't/couldn't use killer_buf.
- the killer list is saved and restored as part of the game state.
- the special case of usick_cause was removed and a delayed killer list
entry is now used in its place
- common code dealing with (un)sliming is moved to a new make_slimed function
- attempted to update all make dependencies for new end.c -> lev.h
dependency, sorry if I messed any up
Pat Rankin wrote:
> collect them all into some new struct and
> save that separately rather than jamming more non-option stuff
> into struct flags.
This patch:
- collects all context/tracking related fields from flags
into a new structure called "context."
It also adds the following to the new structure:
- stethoscope turn support
- victual support
- tin support
<Someone> submitted the following bug report:
> An object and a pit are occupying the same square. I try to kick
> the object out of the square, but "You can't kick something
> that's in a pit!"
>
> I step into the square and escape the pit, but I can pick up the
> object, so maybe it's not in the pit after all.
>
This patch does *not* address this part of the bug report:
> If it's in the pit and it's a cockatrice corpse, should I die
> from landing on it when I fall into the pit?
Undo the change to test_move and instead, don't even test moving in diagonals.
This opens the possibility for approximating the diagonal while polymorphed
into a grid bug in the future.
This is derived from the proposed patch and feedback to it. This applies
the last-position cache behavior without an option, making the behavior
more like it is for interfaces with a mouse, where holding the mouse still
acts the same way as the travel cache. The code is not #ifdef'd either.
Noticed when investigating one of the killer reason bugs recently
reported: a land mine explosion shouldn't create a concealed pit trap;
make a revealed pit instead. And while testing that, I noticed that the
"Kaboom" message given when pushing a boulder onto a land mine was given
while the map still showed the boulder at its original location even
though it had actually been moved already. It's a little odd that you
get hit by shrapnel at your original position--as if you're shoving the
boulder ahead of you and then pausing a moment before stepping into its
former location--but that's trickier to fix; sometimes you won't advance
due to there being multiple boulders present (in that case you evidently
do shove the boulder instead of performing a steady push, so maybe the
current behavior is fine as it is).
As suggested in the newsgroup, re-factor the calculation of carrcap
so that any change in strength or constitution affects your capacity.
The integer division was rounding off the result.
Prevent burying a ball from ending your punishment.
When you bury the ball, internally NetHack Punishment
ceases, but a new trap type of TT_BURIEDBALL immediately
kicks in (acting similar to TT_INFLOOR in some ways).
You can eventually work the ball free (or teleport, etc.),
but that will just return you back to normal Punishment.