Switch to using the term "sound triggers" for things that
result in a call to one of the soundlib routines.
SNDCAP_* renamed to SOUND_TRIGGER_*
sndcap field in the sound_procs struct changed to sound_triggers
rename display_gamewindows() to init_sound_and_display_gamewindows()
(I know that's getting pretty long-named).
move activate_chosen_soundlib() into init_sound_and_display_gamewindows()
from moveloop_preamble().
Also included was a missing break in a switch related to sounds.
hmon_hitmon was the biggest function by far; this makes it far more
manageable.
There should be no change in functionality, and although I didn't
test every case, this was just moving chunks of code and changing
variable names until compiler did not complain anymore.
Use macOS AppKit framework routines for a first cut at a
macsound soundlib interface.
Requires WANT_MACSOUND=1 on build.
Nothing has been done to move the stock sounds into the resources
of a bundle, so after building, if you want to try the stock sounds
out:
cp sound/wav/*.wav ~/Library/Sounds
Because the NSSound macOS routines always do the search, supposedly
the following locations are searched in this order:
1. the application’s main bundle
2. ~/Library/Sounds
3. /Library/Sounds
4. /Network/Library/Sounds
5. /System/Library/Sounds
Although not specifically implemented as of yet, it may be pretty
close to being able to put soundeffects wav files (by se_ name)
into ~/Library/Sounds working for the SND_SOUNDEFFECTS_AUTOMAP feature.
Feedback is welcome. Contributions for improving it are even more
welcome.
The new soundlib supporting file is named
sound/macsound/macsound.m since it's got objective C in it.
Known bugs and glitches:
The Hero_playnotes on a set of 5 notes goes too fast, so there
needs to be a slight delay added between the note of a multi-note
play.
Pull request from entrez: if bones left dead hero's corpse on top
of a new grave, don't find a corpse or summon a zombie when digging
the grave up. It also removed the chance that a ghoul might be
summoned when engraving on a headstone, switching to zombie or mummy
instead.
Rather than adopting the pull request, this retains summoning a
ghoul via engraving and adds the possibly of doing so when kicking
a headstone. Having a ghoul prowl around the grave is independent
of whether there is a corpse or zombie inside the grave. To achieve
this, another flag in 'struct rm' is needed; the single bit for
'disturbed' isn't sufficient. The bigger 'flags' field wasn't in
use for graves so commandeer that for new 'emptygrave'. 'disturbed'
still uses the 'horizontal' bit in order to have engraving and/or
kicking summon at most one ghoul.
Closes#944
Commit 0f257ec538 (nhlua.c static analyzer fix) changed
a variable from long to unsigned, but the var is also saved
to the save file, so broke save compat.
Expand windsound to support SNDCAP_USERSOUNDS (existing),
SNDCAP_SOUNDEFFECTS, SNDCAP_HEROMUSIC.
Place a small number of wav files into sound/wav that are considered
more specific to some game stuff in the core, namely: playing
instruments by the hero, squeaky board traps. The intention is that
those ones can be integrated into the game without requiring user
file deposits or mappings. Building soundlib support for sound/windsound
searches for them as resources, so they should "just work."
No actual instrument playback is available in the base sound/windsound
soundlib implementation (yet, at least), so it works around that in
a cheap way by using the note-variant wav sounds to concoct the
notes. There are better ways of doing music generation than that,
of course, but this will do in the early going. Any other soundlib
port (such as Qt) can probably easily do the exact same thing. If it
can play USER_SOUNDS, it can almost certainly use the
sound/wav/se_squeak*.wav and sound/wav/sound_*.wav files for
SND_HEROMUSIC and squeaky board sounds soundeffects.
A few of the se_ sounds in sound/wav are free yet licensed, and
there is a file called attributions.txt to meticulously attempt
to comply with the two license variations involved.
SND_SOUNDEFFECTS_AUTOMAP
If SND_SOUNDEFFECTS_AUTOMAP is defined, and a SND_LIB_ interface
that supports SNDPROC_SOUNDEFFECTS is also defined to integrate
soundlib support, the following gets added:
o If sounddir is defined (existing longstanding feature that's
been used with USER_SOUNDS for many, many years) any wav file
present in SOUNDDIR with a name that matches one of the defined
sound effects in include/sndproc.h will get played each time
that soundeffect comes up. So, just drop appropriate wav files
into sounddir and rename it to match.
No tedious config file entries are required to get soundeffects.
[ The only config file change required is to
set SOUNDDIR to point to your directory with the wav files.
Note: SOUNDDIR only works in your config file if NetHack
was built with USER_SOUNDS defined. ]
This is new so there may certainly be some bugs in here.
Please kindly report them if you encounter any.
For those that don't read C very well, these are the file names
that should trigger the SOUNDEFFECTS_AUTOMAP, assuming it is working.
se_faint_splashing.wav
se_crackling_of_hellfire.wav
se_heart_beat.wav
se_typing_noise.wav
se_hollow_sound.wav
se_rustling_paper.wav
se_crushing_sound.wav
se_splash.wav
se_chains_rattling_gears_turning.wav
se_smashing_and_crushing.wav
se_gears_turning_chains_rattling.wav
se_loud_splash.wav
se_lound_crash.wav
se_crashing_rock.wav
se_sizzling.wav
se_crashing_boulder.wav
se_boulder_drop.wav
se_item_tumble_downwards.wav
se_drain_noises.wav
se_ring_in_drain.wav
se_groans_and_moans.wav
se_scratching.wav
se_glass_shattering.wav
se_egg_cracking.wav
se_gushing_sound.wav
se_glass_crashing.wav
se_egg_splatting.wav
se_sinister_laughter.wav
se_blast.wav
se_stone_breaking.wav
se_stone_crumbling.wav
se_snakes_hissing.wav
se_loud_pop.wav
se_clanking_pipe.wav
se_sewer_song.wav
se_monster_behind_boulder.wav
se_wailing_of_the_banshee.wav
se_swoosh.wav
se_explosion.wav
se_crashing_sound.wav
se_someone_summoning.wav
se_rushing_wind_noise.wav
se_splat_from_engulf.wav
se_faint_sloshing.wav
se_crunching_sound.wav
se_slurping_sound.wav
se_masticating_sound.wav
se_distant_thunder.wav
se_applause.wav
se_shrill_whistle.wav
se_someone_yells.wav
se_door_unlock_and_open.wav
se_door_open.wav
se_door_crash_open.wav
se_dry_throat_rattle.wav
se_cough.wav
se_angry_snakes.wav
se_zap_then_explosion.wav
se_zap.wav
se_horn_being_played.wav
se_mon_chugging_potion.wav
se_bugle_playing_reveille.wav
se_crash_through_floor.wav
se_thump.wav
se_scream.wav
se_tumbler_click.wav
se_gear_turn.wav
se_divine_music.wav
se_thunderclap.wav
se_sad_wailing.wav
se_maniacal_laughter.wav
se_rumbling_of_earth.wav
se_clanging_sound.wav
se_mutter_imprecations.wav
se_mutter_incantation.wav
se_angry_voice.wav
se_sceptor_pounding.wav
se_courtly_conversation.wav
se_low_buzzing.wav
se_angry_drone.wav
se_bees.wav
se_someone_searching.wav
se_guards_footsteps.wav
se_faint_chime.wav
se_loud_click.wav
se_soft_click.wav
se_squeak.wav
se_squeak_C.wav
se_squeak_D_flat.wav
se_squeak_D.wav
se_squeak_E_flat.wav
se_squeak_E.wav
se_squeak_F.wav
se_squeak_F_sharp.wav
se_squeak_G.wav
se_squeak_G_sharp.wav
se_squeak_A.wav
se_squeak_B_flat.wav
se_squeak_B.wav
se_someone_bowling.wav
se_rumbling.wav
se_loud_crash.wav
se_deafening_roar_atmospheric.wav
se_low_hum.wav
se_laughter.wav
se_cockatrice_hiss.wav
se_chant.wav
se_cracking_sound.wav
se_ripping_sound.wav
se_thud.wav
se_clank.wav
se_crumbling_sound.wav
se_soft_crackling.wav
se_crackling.wav
se_sharp_crack.wav
se_wall_of_force.wav
se_alarm.wav
se_kick_door_it_shatters.wav
se_kick_door_it_crashes_open.wav
se_bubble_rising.wav
se_bolt_of_lightning.wav
se_board_squeak.wav
se_board_squeaks_loudly.wav
se_boing.wav
se_crashed_ceiling.wav
se_clash.wav
se_crash_door.wav
se_crash.wav
se_crash_throne_destroyed.wav
se_crash_something_broke.wav
se_kadoom_boulder_falls_in.wav
se_klunk_pipe.wav
se_kerplunk_boulder_gone.wav
se_klunk.wav
se_klick.wav
se_kaboom_door_explodes.wav
se_kaboom_boom_boom.wav
se_kaablamm_of_mine.wav
se_kaboom.wav
se_splat_egg.wav
se_destroy_web.wav
se_iron_ball_dragging_you.wav
se_iron_ball_hits_you.wav
se_lid_slams_open_falls_shut.wav
se_chain_shatters.wav
se_furious_bubbling.wav
se_air_crackles.wav
se_potion_crash_and_break.wav
se_hiss.wav
se_growl.wav
se_canine_bark.wav
se_canine_growl.wav
se_canine_whine.wav
se_canine_yip.wav
se_canine_howl.wav
se_feline_yowl.wav
se_feline_meow.wav
se_feline_purr.wav
se_feline_yip.wav
se_feline_mew.wav
se_roar.wav
se_snarl.wav
se_buzz.wav
se_squeek.wav
se_squawk.wav
se_squeal.wav
se_screech.wav
se_equine_neigh.wav
se_equine_whinny.wav
se_equine_whicker.wav
se_bovine_moo.wav
se_bovine_bellow.wav
se_wail.wav
se_groan.wav
se_grunt.wav
se_gurgle.wav
se_elephant_trumpet.wav
se_snake_rattle.wav
se_hallu_growl.wav
This needs further testing. At the moment only windsound has
this.
If nobody else looks into it for Qt, I'll take a look in a
few days.
Unless you kill the monster with one hit, it'll wake up
cranky and make noise - waking up other sleeping monsters.
This was a bit tricky with all the message sequencing; I tested
all the hit/throw/fire/zap combos I could think of, and it took
a while to get things looking right.
This code was in three different places; pet eating,
monster eating metal, and monster eating other objects.
Other than very minor changes (eg. rustproofing completely
protects pets from bad effects, rustproof items are no longer
giving apport, and monsters eating corpses are healed), it
should behave the same as before... But I haven't exhaustively
gone through every iteration.
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.
Groundwork for a more versatile interface for using
sound libraries. A lot of sound libraries work across
multiple platforms.
The current NetHack sound stuff is quite limited.
Binaries can have a variety of window ports linked into
them, and it makes sense to have something similar for
sound.
This tries to set things up in a more soundlib-centric way,
rather than inserting things in a platform-centric way.
It establishes a new top-level directory sound (akin to win
for the window interface routines, or "window-port") where
sound-related additions and sndprocs and support files can be
added and used across platforms.
The default interface is nosound and the 'nosound' interface
is in src/sounds.c
The interface for 'windsound', which contains the same minimal
USER_SOUNDS support using built-in routines that has been in the
windows port for a long time is added to
sound/windsound/windsound.c.
For now, the sound interface support for 'qtsound' has been added
to the existing Qt files win/Qt/qt_bind.h and win/Qt/qt_bind.cpp,
and a note has been placed in sound/qtsound/README.md to avoid
confusion.
New header file added: include/sndprocs.h.
The Gehennom changes broke the vibrating square, allowing hero to go
down into the Sanctum via stairs without performing the invocation.
Fix this by making the hellfill lua check for invocation level, and
placing down the vibrating square trap, instead of stairs.
When playing as a Samurai, add things like "osaku" to the discoveries
list even though they don't have separate descriptions to be used
when not yet discovered. Non-magic ones are pre-discovered and
players can now use the '\' command to figure out what things like
"tanko" mean without resorting to '/?'.
"wooden harp" has been getting changed to "koto (harp)"; make that be
| koto [wooden harp] (koto)
"magic harp" has been staying as "magic harp (harp)"; add it to the
list of Japanese item names. Since it's magic it isn't pre-discovered.
Once discovered it becomes
| magic koto [magic harp] (koto)
Those two needed special case handling, none of the other items did
aside from forcing them to be discoverable when lacking descriptions.
The discoveries list now has things like
| wakizashi [short sword]
| naginata [glaive] (single-edged polearm)
| gunyoki [food ration]
if--and only if--the hero is a Samurai.
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.
When hallucinating, random object selection for objects was including
the new generic objects. It was already excluding 'strange object'
by using 'rn2(NUM_OBJECTS - 1) + 1' to skip objects[0]; changing that
to be 'rn2(NUM_OBJECTS - MAXOCLASSES) + MAXOCLASSES' will skip the
first 18 objects, 'strange object' plus the 17 generic objects.
(I'm trying to convince myself that there's no off-by-1 or off-by-N
error and think I've succeeded.)
Try to fix a fuzzer issue. I wasn't able to reproduce it so am not
sure whether this actually fixes it. A mimic seemed to be mimicking
object #1 (generic ILLOBJ_CLASS object which shouldn't occur) rather
than #0 (strange object). Strange object always has dknown==1 and
generic objects should always have dknown==0 but farlook of mystery
object #1 had its dknown flag set.
An earlier fix to force non-Null oc_name when formatting objects in
order to pacify the static analyzer might have been the reason that
the problem couldn't be reproduced.
This includes a few miscellaneous changes made while unsuccessfully
hunting for the problem.
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.
A recent commit to alloc.c by Keni drew attention to the fact that
there are extern prototypes scattered around in various .c files.
Those can make use of ATTRNORETURN (non-gcc compilers and C23) the
same way the prototypes in extern.h can, and they were overlooked
when ATTRNORETURN was first added.
Add 17 fake objects to objects[], one for each object class. All
specific color as gray. They're grouped at the start--actually near
the start since "strange object" is still objects[0]--rather than
being among the objects for each class. init_object() knows to start
at [MAXOCLASSES] instead of [0]; other code that loops through every
object might need adjusting.
For potions, non-stone gems, and non-novel/non-Book_of_the_Dead
spellbooks that don't have obj->dknown set, display the corresponding
generic object rather the object itself. Fixes the longstanding bug
of seeing color for not-yet-seen objects whose primary distinguishing
characteristic is their color. Walking next to a generic object
while able to see its spot will set dknown and redraw as specific.
It's slightly disconcerting to have objects change as you reach them;
I hope it's just a matter of becoming used to that. (If there is any
code still changing the hero's location manually instead of using
u_on_newpos(), it should be changed to use that routine.)
Most of the new tiles are just a big rendering of punctuation
characters. The potion, gem, and spellbook ones could be cloned from
a specific object in their class and then have the color removed. I
started out that way but wasn't happy with the result. I'm not
artisticly inclined; hopefully someone else will do better. Each of
them is preceded by a comment beginning with "#_"; the underscore
isn't required, just being used to make the comments stand out a bit.
Invalidates existing save and bones files.
Instead of just plain old boring mazes, spice up Gehennom by
occasionally adding lava, iron bars, or even mines-style levels
(with lava, of course).
Of the fixed Gehennom levels, only Asmodeus' lair has been changed
to add some random lava pools.
Also some lua fixes and changes:
- Fixed a selection negation bounding box being wrong.
- Fixed a selection negated and ORed returning wrong results.
- des.map now returns a selection of the map grids it touched.
- When using des.map contents-function the commands following the
map are not relative to it.
From the newsgroup: identifying by menu pops up multiple menus in
succession if the player picks fewer invent entries than are being
granted, but the second and subsequent ones could cover up the
message window and hide the feedback from prior ones.
If multiple popup menus are needed when identifying, issue --More--
before each menu after the first. The code seemed to be trying to
do this already, but it should have used wait_synch() rather than
mark_synch(), or perhaps used display_nhwindow(WIN_MESSAGE, TRUE)
instead of either one of those. For curses, both mark_synch() and
wait_synch() were no-ops. Now they do something. X11's behavior
wasn't right either; it seemed to be lagging one message behind
(something I had noticed recently and then forgotten about; I still
don't remember the context then so don't know whether this fixes
that earlier situation).
Also includes support by paxed for polearm targeting using the
frame color.
Also renames USE_TILES to TILES_IN_GLYPHMAP which is a more
accurate description.
Not all window interfaces have full support for the color framing
of the background square yet.
MS-DOS needs further work (to bring it to both VESA and VGA, with
and without tiles.
Windows GUI is missing support.
X11 and Qt have been started, but may require further refinement.
tinklebear on IRC noticed that a hero paralyzed by a floating eye was
still "charmed" and capable of "removing her armor" as part of a nymph's
theft attack. The same thing was true of foocubus seduction: a
paralyzed hero was still able to respond to the questions about whether
particular pieces of armor should be removed (and also do whatever else
may be involved in a successful attack...).
I think paralysis should prevent both those things. Nymph theft will
still work, unless she needs the hero's active cooperation in removing a
bulky piece of armor. Foocubus attacks will be prevented entirely by
paralysis, making it interfere like unconsciousness already does.
Apply a similar constraint to hero vs monster seduction, as well.
The DUMP_ENUMS definition of 'MARKER()' had the expansion of its
arguments backwards but isn't even needed, so get rid of it rather
than reverse them. nethack --dumpenums handles them separately
from object definitions.
Replace FIRST_GEM and LAST_GEM with FIRST_REAL_GEM, LAST_REAL_GEM,
FIRST_GLASS_GEM, and LAST_GLASS_GEM and define those along with
objects[] rather than separately. Do the latter for FIRST_AMULET
and LAST_AMULET too. Also new FIRST_SPELL and LAST_SPELL used to
compute MAXSPELLS. (That value looks wrong to me, but this defines
it with the same value as before. If it gets fixed, EDITLEVEL will
need to be incremented.)
This started as just proof of concept that extra information could
be collected as objects[] gets initialized at compile time.
Allow the preferred sort order for the vanquished monsters list to
be specified in the run-time config file
|OPTIONS=sortvanquished:X
where X is t, d, a, c, n, or z. It can also be set to 'A' or 'C'
but those aren't documented and aren't offered as choices when
setting the value interactively, which can be done via 'm O' or by
using 'm #vanquished'.
Guidebook.mn has been updated but Guidebook.tex is lagging again.
Keep track of how a role|race|gender|alignment option got its value
so that role:!Tourist in .nethackrc and role:!Priest in NETHACKOPTIONS
yield 'role:!Priest' rather than merging into 'role:!Priest !Tourist'.
It also doesn't write the value into new config file for #saveoptions
if that value comes from environment or command line (not applicable
since the command line arguments for role,&c don't go through options
handling). Also, the old config file value takes precedence over
the current game's value file so that 'role:random' doesn't become
'role:Healer' or such in a new config after the random value gets
picked for play.
This only tracks the role, race, gender, and alignment options but the
concept could be extended to all options. The data would need to be
saved and restored if values set interactively need to be retained in
restore sessions (doesn't apply to role,&c since those don't change
during play).