Change 852f8e4 by requiring a minimum impact before a buried zombie
nearby will be disturbed: light, but still excluding things like
scrolls, if it's a violent impact (dropped while levitating, thrown, or
kicked), and fairly heavy if the hero is just placing the item on the
ground normally.
Moving the call out of flooreffects meant it no longer applied to
pushing boulders around, so have moverock disturb nearby zombies. I
additionally had wake_nearby do the same thing.
Finally, I renamed check_buried_zombies (which doesn't really reflect
what it does) to disturb_buried_zombies.
When returning to play from within the tutorial, remove the level files
similar to how they're discarded for the rest of the dungeon when going
into the endgame. It turned out to be a bit messier than anticipated.
The dungeon.c bit is sufficient for #overview, which now hides regular
level 1 while in the tutorial and hides all tutorial levels once exited.
Those will still appear in end-of-game disclosure.
I was looking to see what the impact of converting glyph_to_cmap() to
a function might have and noticed a couple of places where the macro
edition is passed a non-trivial argument. Since it evaluates that
argument many times, there is hidden overhead. Fetch the glyph once
and pass that to glyph_to_cmap().
This will no longer be very useful--but won't need to be reverted--if
PR #1022 gets incorporated.
do_positionbar() has bugs (only matters for MS-DOS).
This replaces most of commit 0ca2af4d8b
from a couple of days ago with something more robust. That change
actually introduced redundant code that caused fountain and/or sink
count to be off instead of preventing it.
Revise set_levltyp() to update level.flags.nfountains and
level.flags.nsinks if setting the type to or from fountain or sink.
A bunch of places that were setting levl[x][y].typ directly needed
to be revised to use set_levltyp() instead. set_levltyp() itself
hadn't been updated to handle LAVAWALL (to force such to be lit).
Replace tests against tutorial_dnum with 'In_tutorial()' predicate.
Give a message when entering the tutorial (via level change mechanism).
Likewise, give a message when resuming regular play.
If player uses #quit or ^C in the tutorial, ask whether to cut the
tutorial short and resume regular play; skip "Really quit?" if the
answer is yes. Behavior is a bit odd for ^C + yes; it just sits there
until player types something.
Reported by Noisytoot: going from level tut-1 to tut-2 returned the
hero's starting equipment too soon, and exiting the tutorial from
tut-2 let the hero keep any equipment acquired within the tutorial.
Entering and leaving the tutorial was being handled by lua code in
the level description of tut-1 and adding a second level messed that
up. I didn't see any way of handing that with level-specific lua
code so I made it become the core's responsibility. gotolevel()
knows when the hero is moving from one dungeon branch to another so
it can recognize entry to or exit from the tutorial easily.
While fixing this, prevent #invoke of the Eye of the Aethiopica from
offering the tutorial as a candidate destination (was feasible if it
had been entered at start of game).
Not fixed: levels visited in the tutorial become part of #overview.
Show location as "Tutorial:1" instead of "Dlvl:1" on status lines.
Only tested with tty; some interfaces handle location themselves and
may need their own fixup for this.
Fixes#1046
Reported by copperwater: entering the tutorial sets 'u.nofollowers',
changing to the tutorial level saves a copy of 'u', post-level change
from entering the tutorial level resets u.followers, but subsequently
changing levels to return to the original level 1 restores 'u' from
the saved copy with has 'u.nofollowers==True', overriding the reset.
Move the nofollowers flag from 'u' to 'iflags'. Invalides save and
bones files.
Fixes#1027
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.
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.
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.
Selecting both 'P' (the just-picked-up items category) and 'A' (the
'auto-select relevant items' flag) when dropping items by type with 'D'
was automatically dropping every item in inventory instead of only items
that were marked as just having been picked up. Basically, it was
causing 'A' to act like it did before b65c93c amended its functionality.
This commit is more-or-less identical to 991e739, both in terms of the
problem and the fix, except that it applies to dropping items instead of
looting.
Insert the calls to trigger a number of potential soundeffects
into the core.
If no additional soundlib support is integrated into the
build, then the Soundeffect macro (sndprocs.h) expands to nothing:
[#define Soundeffect(seid, vol)
]
If, however, at least one additional soundlib support is integrated
into the build, then the Soundeffect macro gets defined as this
in sndprocs.h:
[#define Soundeffect(seid, vol) \
do { \
if (!Deaf && soundprocs.sound_soundeffect \
&& ((soundprocs.sndcap & SNDCAP_SOUNDEFFECTS) != 0)) \
(*soundprocs.sound_soundeffect)(emptystr, (seid), (vol)); \
} while(0)
]
That macro definition checks for the hero not being Deaf; it checks
to ensure that the active soundlib interface has a non-null
sound_soundeffect() function pointer; and it checks to ensure
that the active soundlib interface has declared that it supports
soundeffects by setting the SNDCAP_SOUNDEFFECTS bit in its sndcap
entry. That just means that the interface routines are prepared to
accept and deal with the calls from the core, whether or not it
actually produces the desired soundeffect.
Allow setting a per-level "temperature": hot, cold, or temperate
via special level flags. Currently it only affects some messages
in Gehennom, but it could be expanded to ice melting, water freezing,
or monster generation, for example.
Invalidates saves and bones.
Amend the safe_wait so it still waits if you have a deadly property,
even if you have a resistance to it.
External resistances do not protect against already existing
deadly properties, for example becoming deadly ill is not cured
even if you wear a green dragon scale mail.
A number of C compiler suites have a math.h library that includes a yn()
function name that conflicts with NetHack's yn() macro:
"The y0(), y1(), and yn() functions are Bessel functions of the second kind,
for orders 0, 1, and n, respectively. The argument x must be positive. The
argument n should be greater than or equal to zero. If n is less than zero,
there will be a negative exponent in the result."
At one point, isaac64.h included math.h, although that has since been removed.
Some libraries used in NetHack (Qt for one) do include math.h and that required
build work-arounds to avoid the conflict.
Rename the NetHack macro from yn() to y_n() and avoid the math.h conflict
altogether, eliminating the need for that particular work-around.
If punished and the attached iron ball was both cursed and wielded,
falling while going down stairs would drop it instead of leaving it
welded to hero's hand. ( Didn't happen for iron ball that wasn't
chained to hero's leg.)
I thought that this was going to be a one or two line fix but ball
and chain stuff is never that simple.
Fixes#949
The consolidation of global variables from scattered source
files into decl.c and declared in decl.h was begun in 3.7.0.
Their placement in common files was done for centralized
initialization and potential re-initialization during a
"play again" scenario.
It wasn't really necessary for all of them to be housed in a
single huge structure to meet the "play again" requirement,
and the single huge structure has been a little unwieldy when
it comes to maintenance.
Following this commit, instead of one single extremely large structure
named 'g' to house all of the relocated global variables, they
are distributed into several ga through gz.
To make things easy for the developer, each variable is placed
into the struct corresponding to the starting letter of the variable.
That way, no lookup is required in order to know which struct houses
a particular variable, it is a simple match to the starting letter
for all the centralized global variables.
A global variable named 'amulets', would be found in ga.
ga.amulets
^ ^
A global varable named 'move', would be found in gm.
gm.moves
^ ^
A global variable named 'val_for_n_or_more' would be found in gv.
gv.val_for_n_or_more
^ ^
A global variable named 'youmonst' would be found in gy.
gy.youmonst
^ ^
Pushing a shop-owned boulder out of the shop wouldn't charge the hero
anything. Remedy this (and remove the boulder from the bill if the hero
then pushes it back in). Also tried to handle a couple other uncharged
boulder "theft" scenarios: pushing a boulder into lava or water, into a
trapdoor or hole, or into a level teleporter (various other traps
already charged for the boulder -- it was pretty inconsistent).
I externified onbill() for this, since relying on otmp->unpaid by itself
impossibles if you push a boulder through a gap in a wall between two
adjoining shops.
Short for distu(mtmp->mx, mtmp->my) (i.e. the distance between the hero
and the specified monster), which is a very common use of distu(). The
idea is that this would be a convenient shorthand for it; I actually
thought it (or something very similar) existed already, but couldn't
find it when I tried to use it earlier. Based on the number of uses of
fully-spelled-out 'distu(mtmp->mx, mtmp->my)' replaced in this commit
I'm guessing I just imagined it.
Instead of using index() macro defined to strchr, use C99 strchr.
Instead of using rindex() macro defined to strrchr, use C99 strrchr.
If you want to try building on a platform that doesn't offer those
two functions, these are available:
define NOT_C99 /* to make some non-C99 code available */
define NEED_INDEX /* to define a macro for index() */
define NEED_RINDX /* to define a macro for rindex() */
Some routines return ECMD_TIME|ECMD_CANCEL (for instance when 'a'pply
wields an item and player cancels the attempt to use it) so change
drop_menu() to test that properly. I don't think drop() ever returns
that combined mask value but be prepared to handle time passage if it
ever does.
Pull request #607 by Vivit-R proposed renaming "huge chunk of meat"
to "giant meatball" to better reflect the similarity to meatball.
But an object name that contains a monster name prefix requires extra
work in the wishing code. I considered "huge meatball" which retains
more of the original name but decided to go with "enormous meatball"
becaues it seems more evocative.
Supersedes #607Closes#607
The way hole destinations work now theoretically allows for a
cross-branch hole or trap door to move you across branches in a way that
decreases your overall depth. If this happened, it would cause an
impossible when the negative result of (depth(new) - depth(old)) was
used to calculate fall damage. Limit fall damage to 1d6 if dist <= 0.
Missed this way to use the trap door (in a block added in 05761ba) in
previous commits, though I'm a little confused about whether that block
in dodown is even reachable given how various trap scenarios are handled
with dotrap earlier in the function.
Pull requet from entrez: give better feedback than "it" when hero
observes a corpse reviving into a monster that can't be seen.
Tweak reviving from a container which was coded as if the container
was optional. That can lead to confusion when someone reads the
code so make the situation more explicit.
Fixes#871
An invisible monster reviving would be called "it" (as in, "It rises
from the dead!"). Improve on this a bit by instead saying that "the
troll corpse disappears!" (similar to the messaging used when undead
turning is used on an invisible monster's corpse), or calling the
revived monster "something" (as in "something escapes from a sack!")
instead of "it". Distinguish between the original location of the
corpse and the location of the revived monster when describing seeing
things that have happened to the corpse, since revival may not place it
on the corpse's location.
delivered across level change checkpointing
Reported by entrez. Simplest test case: give level 1 a short
annotatation, level teleport to level 2, and level teleport back to
level 1. The message window will show
|You materialize on another level. You remember this level as <note>.
but ^P message history will show
|You materialize on another level.
| You remember this level as <note>.
Spaces inserted to separate two messages that fit together on the
top line become part of the second message when saving a checkpoint
during level change flushes the top line into message history.
Change insurance checkpointing to record the full message history
without flushing the current top line so that toggling 'checkpoint'
doesn't affect what shows up on the screen or in message recall.
Make sure u.uswallow is cleared when u.ustuck gets set to Null so
that they won't be out of sync with each other. Having u.uswallow
be non-zero does imply that u.ustuck is non-Null.
Running #panic while swallowed didn't produce any anomalies for me,
either before or after this change.
Change trappers and lurkers above to remove digestion damage. They
fold themselves around rather than swallow the victim. There were
are lot of places that assumed that an engulfer which is an animal
would swallow and digest the victim. In hindsight, it might have
been simpler to take the M1_ANIMAL flag off of trappers and lurkers
above.
This adds a new digests() predicate for creatures with AT_ENGL+AD_DGST
(purple worm) and also enfolds() for AT_ENGL+AD_WRAP (both 't'-class
critters).
There are several minor fixes mixed in with this. I didn't record
them as I went along but the two I remember are
1) if poly'd into a holder and holding on to a monster, the '<' and
'>' commands refursed to work; release the held creature first
and then treat those commands as normal;
2) throwing a non-weapon while engulfed by an ochre jelly reported
"the <item> vanishes into the ochre jelly's /currents/".
This needs a lot more testing. I found and fixed multiple minor
details before my own testing burned out.
This replaces the old pushq/saveq arrays (which were used to save
the keys pressed by the user for repeating a previous command)
with a new command queue. This means there's no hard-coded limit
to the saved keys, and it can repeat extended commands which are
not bound to any key.
The earlier commit just removed monsters from migrating_mons and left
them orphaned. Also it ignored migrating objects.
Actually release the monsters that can no longer arrive at their
migration destinations. Release their inventories too.
Release objects that can no longer arrive at migration destinations.
When the hero enters the planes branch, all the rest of the dungeon
gets discarded since it can no longer be reached. At the time that
that takes place, throw away any migrating monsters waiting to arrive
on any of those levels.