1. Add "engraved room floor" pchar sym (S_engroom). The symbol that
displays at the engraved part of a room (not a corridor though).
The default symbol is '`' which is currently never shown if people
have defined the boulder symbol to '0' and statues are displayed as
monster symbols. It is bright blue.
Add some stylized variations of the S_engroom symset to some of
the symsets.
2. Add "engraved corridor" pchar sym (S_engrcorr). The symbol that
displays at the engraved part of a corridor. The default symbol is
'#', and it matches the symbol for corridor from for whatever the
current symset uses. It is bright blue to match the color of the
S_engroom symbol. Using the normal corridor symbol for display
preserves the lines of the corridor so is not as visually-disruptive
as a smaller symbol would be. Explicit entries that match the S_corr
symbol have been added to the symset file.
Magic mapping and clairvoyance impacts yet to be determined.
The Guidebook updates will come later.
Issue reported by jeremyhetzler: left and right arrows produced
unexpected characters when trying to use them to edit text that is
being entered.
The curses interface converts arrow keys and function keys related
to the keypad into movement keys (hjkl or 4286 depending on the
number_pad setting). But it was doing that all the time, not just
when nethack wanted movement keys. This extends the existing
program_state.getting_a_command flag to getdir() so that it can be
used for controlling that in addition to 'altmeta' support.
Typing an arrow when interacting with the map (actual command or
getpos, now getdir too) will still work. Typing one when making a
wish or naming a pet will issue a beep and be treated as if '\0' had
been typed, and that normally gets treated as if ESC had been typed.
[Possible room for improvement there. Losing the whole text when
trying to back up a character feels a bit harsh.]
Treating left arrow as escape rather than as h or 4 will probably be
enough to train players not to try to edit text with it after they
get burned by that a time or two.
Bonus fix: curses' keystroke conversion only supported traditional
number_pad behavior, not the inverted phone number pad layout.
Closes#987
The Makefiles and some of the hints have already been updated to
specify that C99 is required in response to #K3863. The code was
evidently being compiled in the default mode of an old version of
gcc and that mode complained that C99 was required to specify a
declaration in the initializer clause of a
'for(initialize;test;update)statement'. Other C99 features used
by nethack were apparently accepted as extensions in the default
conformance mode.
There's only one such declaration in the core code so replace it
with a separate declaration and ordinary 'for' loop.
win/Qt/{lots}.cpp and win/win32/{few}.c have these declarations but
the core didn't.
Comparable to #vanquished, be able to view info normally available
during end of game disclosure while the game is still in progress.
The new #genocided command lists all genocided and extincted types
of monsters. Unlike #vanquished, there aren't any sorting choices.
Potential future enhancement: provide a way to view the genocided
list at the "what do you want to genocide?" prompt.
I was looking at backporting an X11 build fix to 3.6 and decided
that the hangup handling wasn't correct if SAFERHANGUP is defined
(which it is by default). It didn't attempt to perform a hangup
save. Also, the handler might return when the X code calling it
expected it to not do so.
I don't know how to force a hangup within X11 so haven't tested
this properly. It works fine when there's no hangup. :-/
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.
When attached iron ball was in a pit (or a pool) with a monster,
and your levitation ended, you were put on top of the monster.
Add a sanity check for hero over monster.
When using mouse to move to a location next to the hero,
the test_move result was reversed, causing the click to fall
in to the travel case instead of normal movement.
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.
You can attempt to smell a monster at particular coordinates even if you
can't see it. Revert the message for the 'can't find a monster there to
smell' case to "That is not a monster", as it was before, since the
change makes it so that you only reach that line if there genuinely is
no monster there (previously it would be reached if there was a hidden
or undetected monster on the specified spot).
I know this is inane, especially for a little-used debug-mode-only
command, but I can't get it out of my head...
The use of the actual monster data instead of the glyph as a proxy ought
to make it somewhat more consistent as well (e.g. hallucination and
'showrace' won't affect the results), though I think that'd hardly be
worth it were it not for the incredibly funny message.
yn() and company show the list of possible responses in square
brackets and the default response in parentheses:
|Do foo? [ynaq] (y)
but paranoid_querty() was using the punctuation chars backwards
|Do foo? (yes) [n]
or
|Do foo? (yes|no)
depending on the level of paranoid. Change those to be
|Do foo? [yes|n] (n)
(default gets used for <return> but unlike yn(), not for <space>)
and
|Do foo? [yes|no]
(with no default for the latter).
When running #wizkill, if hero was swallowed and you killed the
engulfer and that dropped hero onto a level teleporter, the targetting
loop for selecting the next monster to kill kept going after changing
to another level. Terminate #wizkill if killing something sends you
to a different level.
Not fixed, and an old bug, or variation of one: the cursor got
positioned at the coordinates of your spot on the prior level even
though the part of the new level where you actually arrived was
displayed.
The hack.c and trap.c bits are just reformatting.
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
^ ^
Make the existing '#vanquished' command be available during regular
play, with M-V bound to it. 'm #vanquished' or 'm M-V' brings up
the sorting menu that you get when answering 'a' rather than 'y' at
the end-of-game "disclose vanquished creatures?" prompt.
The original #vanquished came from slash'em, where it was available
in normal play. When added to nethack, it was put in as wizard-mode-
only. I added the sorting capability several years ago.
The chosen sort is remembered and re-used if not reset but only for
the remainder of the current session. It probably ought of become
a run-time option so be settable in advance and across sessions but
I haven't done that.
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() */
I've implemented targetted dismount such that being knocked out of
the saddle will place the hero opposite the attacker in preference
to a random spot adjacent to the steed. If that opposite spot
isn't appropriate, the two spots next to it get tried.
In these map fragments, H is knocking mounted hero off of u. The
digits indicate priority of potential destinations.
|..... |..21.
|...2. |..u2.
|.Hu1. |.H...
|...2. |.....
If spot 1 isn't acceptable, both of spots 2 (in random order) will
be tried next. If those aren't acceptable either, it will try the
other 5 spots adjacent to the steed (the one of those with the
attacker will always be unacceptable). And as before, it none of
those work, it uses enexto() to pick a random spot as close to the
steed as feasible.
Not knockback: when dismounting due to polymorph, avoid diagonal
adjacent spots if hero's new form can't move diagonally. (The hero
can't already be in no-diagonal form because riding requires that
the rider be humanoid. I keep thinking the restriction is "can't
be polymorphed" but that isn't correct.)
Shorten the name of the recently added debug command that validates
monster difficulty values. 'wizcheckmdifficulty' was 19 characters
long, the next longest is 14 ('wiztelekinesis'). The extra width
messed up the Qt interface's extended command selection dialog when
wizard mode commands are included. It sizes the button for every
command to fit the longest name; the increase in size from 14 to 19
made the button grid become too big for the screen.
Add monsters' base difficulty level to the #wizmondiff output.
Add #wizmondiff and #wizdispmacros to 'wizhelp'.
Wizard-mode command to cast any spell without checks that would
prevent casting, and with no energy use.
Mainly to allow the fuzzer to exercise the spell code paths.
The menu for #herecmdmenu includes "look at map symbol" but if you
choose that it auto-picks the hero's location. Looking at your own
'@' isn't particularly useful so only include that menu option if
the symbol or tile being displayed isn't the normal one.
When you were busy with an occupation, such as digging with
a pickaxe, and a prompt showed up to ask you enter something,
the game just hung with infinite loop.
Remove the occupation check returning a NUL from the input
function. I didn't notice any side effects, but I would not
be surprised if something comes up ...
I didn't investigate which commit caused this, but I suspect my
rhack or parse changes.
Some discrepencies between glyph_is_cmap and glyph_to_cmap
arose after b14b830b because the change resulted in
glyph_is_cmap matching on zap beams which weren't accounted
for in the glyph_to_cmap macro. It is unlikely that
glyph_to_cmap will ever be used on such a glyph, but at least
have glyph_to_cmap return a sane value rather than drop through
to the last-resort value (currently NO_GLYPH) which is far
outside the range of the defsyms[] array indices.
Enable 'debugging' function calls, including error(), from the lua files
called by the wizard-mode #wizloadlua command. Without enabling them,
calling error() still produces an error but with a message like
"attempt to call a nil value (global 'error')" instead of the one
specified in the lua file.
I think this is the right way to do this without just enabling
everything across the board (which I assume would contradict the goals
of NHL_SANDBOX), but I will admit to being a little confused by trying
to understand exactly how the sandbox permissions work, so it's possible
this isn't the right solution.
Incidentally, I am probably misunderstanding this, but considering a lua
error still occurs when error() is called, just with a different error
message, is the function really "disabled" successfully by NHL_SANDBOX?
Make #migratemons command be unconditional. The show existing
ones part is now always present. Compile-time DEBUG_MIGRATING_MONS
controls whether the create N new migrators part is available.
Fix creating new ones from the Castle level. It knew how to find
the next level (Valley) but wouldn't send monsters there because of
its Is_botlevel() check.
- Don't show attacking a peaceful or tame monster, as
that is actually swapping places with them - so add that.
- Don't show naming a hostile monster - it's usually not
wanted, and this way when clicking a hostile monster, the
only entry is the attack, so will be executed automatically.
This makes it much more usable.
Previously the mouse clicklook mentioned every tile that matched
the character symbol, leading to overload of information and
if playing with tiles, it was mostly useless. Also the most
important bit - the tile info - was last in the text.
Now mouse clicklook only reports the exact tile information
that was clicked on.
If there are any migrating monsters, #migratemons offers a chance
to view them; display the list in arrival destination order rather
than the arbitrary migrating_mons order. Doesn't change the list's
order and doesn't apply to viewing 'c' (mons aimed at current level)
or 'n' (mons aimed at next level), just to 'o' (other, neither 'c'
nor 'n') and 'a' (all migrating mons).
A typo in the code added to #migratemons resulted in bad output when
listing a subset of migrating monsters if there were any aimed at the
next level. Didn't affect listing 'a'll because the incorrect code
wasn't reached in that situation.
My change to allow binding the mouse buttons made getpos
push the mouse commands into a command queue, so when you
were asked for a map location, clicked on it with a mouse,
you'd first get the expected effect, and then (most likely)
immediately traveled there.
Change getpos to clear the commands bound to the mouse buttons,
and restore the binds afterwards.
Instead of hardcoding mouse button actions, allow the user to
bind mouse buttons to extended commands. For example the new
defaults are:
BIND=mouse1:therecmdmenu
BIND=mouse2:clicklook
Currently a bit rudimentary; the defaults should be OK, but
documentation is bit lacking, and in-game binding and option
saving are missing.
Allowed commands to bind are "nothing", "therecmdmenu", "clicklook",
and "mouseaction". Clicklook replaces the "clicklook" boolean option,
and mouseaction does what mouse 1 button used to do - a context sensitive
action.