I didn't like "your hands begin to glow red even more" very much (the
hero's hands aren't really 'beginning' to glow if they already have an
active confuse monster effect, and "glow red even more" was an awkward
turn of phrase on top of that). Rephrase it to "The red glow of your
hands intensifies."
I used ^G to create a monster and specified "invisible owlbear". I
then got "An owlbear appears next to you." Except it didn't; it was
invisible and I lacked see-invisible. I imagine that newsym() was
called for the new-yet-invisible monster, but that remained buffered
and was gone overridden by the time pending map update got flushed
at some point after the monster was made invisible.
Add a new makemon() flag to turn a newly created monster invisible
during its creation, before "monster appears" message is delivered.
Since that message will now be suppressed in this situation, use the
cursor-flash hack that indicates where the new, unseen monster got
placed. Creating "1000 invisible <mon>" is something you probably
won't do twice.
At either of the genocide prompts,
|What type of monster do you want to genocide?
or
|What class of monsters do you want to genocide?
answering "?<return>" will show the list of monster types that have
already been genocided, then re-prompt.
Issue reported by vultur-cadens: changing helm of brilliance to
crystal made it stop being classified as "hard helmet" so it gave
less protection against things falling onto the hero's head.
Change the is_metallic() tests used on helmets to new hard_helmet().
Unlike when thrown, crystal helmets don't break when objects fall
on them.
Fixes#1060
Heroes recognized unseen same-race monsters by voice, but it yielded
an unexpected result if the monster was unique. Change it so that
hero will recognize any type of monster by its voice if that monster
has been seen and limit unseen same-race ones to non-unique monsters.
Treats shopkeepers as unique since they have distinct names.
This adds a new flag to struct monst in order to track whether each
specific monster has ever been seen or sensed.
relocate surface(), ceiling(), and avoid_ceiling() to dungeon.c
adjacent to has_ceiling() etc.
astral and fire, like airlevel and waterlevel return FALSE
for has_ceiling()
if a caller does happen to call ceiling() on fire level,
return "flames above"
if a caller does happen to call ceiling() on quest level,
return a more-generic "expanse above", instead of the
word "ceiling"
add "stairs" return to surface()
remove recent update to engrave.c to special-case "stairs"
since surface() will return that now
sound_verbal(char *text, int32_t gender, int32_t tone, int32_t vol,
int32_t moreinfo);
-- NetHack will call this function when it wants to pass text of
spoken language by a character or creature within the game.
-- text is a transcript of what has been spoken.
-- gender indicates MALE or FEMALE sounding voice.
-- tone indicates the tone of the voice.
-- vol is the volume (1% - 100%) for the sound.
-- moreinfo is used to provide additional information to the soundlib.
-- there may be some accessibility uses for this function.
It may be useful for accessibility purposes too.
A preliminary implementation has been attempted for macsound to test
the interface on macOS. No tinkering of the voices has been done.
Use of the test implementation requires the following at build time with make.
WANT_SPEECH=1
That needs to be included on the make command line to enable the test code,
otherwise just the interface update is compiled in.
I don't know for certain when AVSpeechSynthesizer went into macOS, but older versions
likely don't support it, and would just leave off the WANT_SPEECH=1.
If built with WANT_SPEECH=1, the 'voices' NetHack option needs to be enabled.
It was a bit strange, when I first started up the test, to hear Asidonhopo,
the shopkeeper, talking to me as I entered his shop and interacted with him.
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.
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.
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
^ ^
The getobj prompt for charging was presenting any chargeable tool in the
hero's inventory as a suggested charging target, even tools which were
unidentified and undistinguishable from their mundane counterparts
(e.g. bag of tricks, magic harp, horn of plenty...). This leaked
information about the identity of these items and made it possible to
determine whether a generic 'harp' was magic or not.
When suggesting chargeable tools, include only those which are actually
known to be chargeable (unidentified or unseen chargeable tools can
still be selected, they just won't be suggested targets). Basically the
same as what's done for a potion of oil in the apply prompt.
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() */
More PR #882; give a different message for empty input than "such
creatures do not exist".
The new message mentions 'none' (with single quotes) as a potential
choice so recognize "'none'" as well as "none" to decline.
Make the prompt for single genocide be more precise
from: What monster do you want to genocide?
_to_: What type of monster do you want to genocide?
and the re-prompt for it be slightly more verbose
from: What... [type the name of a monster]
_to_: What... [enter the name of a type of monster]
Also, make the already verbose re-prompt for class genocide even
more verbose
from: What class... [type the symbol representing a class]
_to_: What class... [type the symbol or name representing a class]
Possibly should have changed 'type' to 'enter' on the last one to
keep them consistent but I left that as-is.
The "[type the name]" prompt seems appropriate for handling via
cmdassist, so experienced players who don't need the help can hide it.
I also added a corresponding help note for the class genocide prompt.
So that a blank line wouldn't use up one of the player's "tries" for
class genocide, the game would continue to prompt until the input was
non-blank (or the user hit <esc>), with a tight loop around the getlin
call that only exited when it got some non-empty input. This apparently
risked leaving the game endlessly looping under some worst-case-scenario
hangup conditions. It was also inconsistent with normal genocide, which
doesn't have special handling of blank lines. Make the class genocide
prompt behave like the normal genocide prompt by removing the "blank
input" loop (and consequently treating a blank line the same way as any
other attempt to write a name).
The pull request included some changes that were neither accidental nor
unintentional, so only a subset of the changes from pull request #869
submitted by klorpa were manually applied.
behaviour -> behavior
speach -> speech
knowlege -> knowledge
incrments -> increments
stethscope -> stethoscope
staiway -> stairway
arifact -> artifact
extracing -> extracting
The uses of "iff" were left alone.
Close#869
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.
hero is invisible without being able to see invisible
Issue reported by EndHack: you could see your hands glow red when
reading a scroll of confuse monster or casting the spell of confuse
monster even if you were unable to see yourself.
Switch to the blind feedback (tingling instead of glowing red) if
invisible without see invisible.
Also, have uncursed scroll or low skilled spell confer 1..2 turns
of glowing hands instead of always just 1. (Blessed/highly skilled
stays at 2..9 turns.)
Fixes#828
Issue reported by youkan700: for shopkeepers, taming via magic harp
behaved differently than taming via scroll or spell.
Make magic harp's taming be the same as [non-cursed] scroll of taming
and spell of charm monster: angry shopkeepers will be pacified (even
though they can't be tamed).
Also, add something I've been sitting on for ages: when taming magic
hits an already tame monster, give that monster a chance to become
tamer. Not significant for monsters that eat (unless being starved
for some reason) but matters for ones who don't eat. For tameness N
(which has a maximum of 20), if N is less than 10, have any taming
yield a 10-N out of 10 chance to increase the tameness by 1. So the
closer a pet is to becoming feral, the more likely for it to improve
tameness a little.
Closes#819
... unless there's some other form that would override the choice,
such as a worn dragon armor, lycanthropy, or vampirism.
The polymorph will be in effect for 10-24 turns.
unpunish() duplicated much of delobj() in order to use dealloc_obj().
Switch to delobj(). That required a fix to feel_location() when it
was called by savebones() after vision is turned disabled.
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).
Add the patch from entrez to describe the tower of flame effect from
a scroll of fire as "the blast" rather than "your spell" if it reveals
a secret door.
after charging causes a ring to explode
Reported by gebulmer: if charging exploded a ring, the ring's memory
got freed but the stale pointer was passed to cap_spe() which accessed
it again. Fix by setting the object pointer to Null after using up
the ring. This was a post-3.6 bug.
Fixes#731
For menustyles traditional and combination, allow 'IP' to request
inventory listing of just picked up items even if not carrying any
items flagged as just picked up. The not carrying any such items
feedback was already present but couldn't be triggered.
For menustyles partial and full, the special menu entry for 'P'
when only one item applies shows the item instead of the category
"Items you just picked up". [That sort of thing probably ought to
be done for every menu entry rather than just for 'P'.] Rephrase
it from
| P - <item>
to
| P - Just picked up: <item>
in case it is player's first time seeing that category be listed.
Clear the just picked up flag for any item that is dipped or read.
Lots of other actions besides drop or put-into-container probably
ought to do that too. [Maybe even just picking an item with getobj()
could be sufficient so that it wouldn't have to be replicated all
over the place.]
trycall() is a short docall() wrapper that is a no-op if the item is
already identified or the player has called the object type already. For
some reason, many calls to docall() did those same exact checks
beforehand.
This commit eliminates that redundancy by converting those calls into
trycall(), which is now made extern rather than local to do.c. No
behavior should be changed by this commit; I've checked that none of the
affected places could take a different code path now that the
oc_name_known and oc_uname checks are removed.