I was baffled about why moving the cursor across a fire elemental
kept putting up --More-- until I remembered that I once used
MSGTYPE=stop "[Ff]ire"
to test Qt's handling for that. Turns out that I left it in my
config file. autodescribe feedback should not be honoring that;
honoring MSGTYPE=norepeat is not as clear-cut but this disables
it too.
User sounds were also kept enabled during autodescribe but I have
no way to test them. Like norepeat, disabling just falls into
place.
The pline.c change is unrelated. It just eliminates a wide line
(from adding 'g.') in the source by using a shorter variable name.
fixes#361
Also, experminental introduction of vt_sounddata to enable tty to pass
a sound file index to the terminal side of things where perhaps someone
can add code to something like hterm to take the information relayed by
NetHack to trigger user_sounds locally even if playing on a server.
Compile time option TTY_SOUND_ESCCODES required to build that support in.
It should be independent of TTY_TILE_ESCCODES.
Fix 'Bugs 4, 5, and 6' which all use a similar fix but would have
conflicts over '#define BIGBUFSZ' if committed separately.
Format ("short explanation %s", string_argument), where the
explanation always has modest length but the string is potentially
up to 4*BUFSZ in length, into a 5*BUFSZ buffer. Then truncate the
result to at most BUFSZ-1 characters so that it can be safely passed
to interface-specific putstr() or raw_print().
Applies to pline(), raw_printf(), and config_error_add(). Also done
for impossible() although there's no evidence that its buffer could
be overflowed in a controlled manner.
Rather than just informing the player that saving and reloading might
fix the problem, they are now encouraged to report the problem to the
value of DEVTEAM_EMAIL. If the sysconf specifies SUPPORT, that is also
presented as an option.
Backported from TNNT. Only affects dumplog pline history, not any other
form of pline history.
The impetus for this is to avoid dumplogs full of "Unknown command foo."
messages which don't provide any value for people reading the file. In
many cases, these messages crowd out the actual message history, making
it hard to reconstruct what happened.
Flag existing occurrences of "You hear" as "Deaf-aware" so
that a grep for that string in the future doesn't need to
trigger further investigation of those.
Extend 'putstr(WIN_MESSAGE, attribute, string)'s attribute so that
'custompline(SUPPRESS_HISTORY, ...)' can work with ^P's message
history like DUMPLOG history, in order to keep autodescribe feedback
and intermediate prompts for multi-digit count ('Count: 12', 'Count:
123') prompts out of recall history. The old autodescribe behavior
could easily push all real messages out of the recall buffer when
moving the cursor around for getpos, and the count behavior looked
silly for a four or five digit gold count if you set the msg_window
option to 'full' or 'combination' and viewed them all at once.
Other interfaces may want to follow suit, but this doesn't force them
to make any changes. I added a hook for "urgent messages" that might
be rendered in bold or red or some such and/or override the use of
ESC at --More-- from suppressing further messages, but there aren't
any custompline(URGENT_MESSAGE, ...) calls (potentially "You die...",
for instance) to exercise it. Other people have implemented similar
feature it different ways and I'm not sure whether this one is really
the way to go since the core needs to categorize each message that it
deems to be urgent. MSG_TYPE:stop may be sufficent, although MSG_TYPE
matching can entail a lot of regexp execution overhead at run-time.
New: call to panic() in impossible() used arbitrary string as a
format so was vulnerable to percent signs in that string. (This
potentially serious problem is not limited to USE_OLDARGS.)
Old: revised message string for impossible ("save/restore might fix
this" instead of "perhaps you'd better quit") passed wrong number of
arguments to pline() when using the clumsy VA_PASSx() mechanism (was
missing arg 0 for the fixed-arg format argument).
Old: varargs config_error_add() in files.c wouldn't compile for
USE_OLDARGS. Evidently no one has been impacted by that but this
fixes it anyway. (Two problems: prototype used FDECL() when it
should have been using VDECL(), and calls to config_error_add() in
the same file would need the VA_PASSx() stuff to force presence of
all optional args. I moved it instead of adding the latter.)
Add code to run a fuzz tester, simulating (more-or-less) random
keyboard mashing. There's no option to turn it on, you need to
set iflags.debug_fuzzer on via a debugger or something along
those lines.
The use of debugpline() in tty_curs() got me wondering what would
happen if debugpline() was called while pline() is in progress. I
don't know how to trigger the bad coordinate situation, so I put an
unconditional debugpline() in the NHW_MESSAGE case of tty_putstr()
and used DEBUGFILES=wintty.c to enable it. Instant segfault, and
the backtrace was short and not useful so the stack might have been
clobbered. I didn't spend any time trying to figure where or why
the segfault occurred.
Change pline() so that if it is called while the previous pline()
hasn't finished yet (ie, recursively), use raw_print() and return
early. The raw_print message isn't very useful--it pops up wherever
the cursor happens to be, just like the cursor position bug that has
been an issue recently--but does get delivered without any segualt
and isn't completely useless if DUMPLOG is enabled and you save or
quit before the message buffer gets recycled. Message readability
situation could be improved but avoiding the segfault was my goal.
Putting any debugpline() into *_raw_print() would be inadvisable....
Reorder some code in pline() so that early pline messages which use
raw_print() instead of putstr(WIN_MESSAGE) are included in the DUMPLOG
message buffer. If the game ends soon enough they'll be shown in the
final log; otherwise they'll get pushed out of the buffer once enough
later messages are delivered.
For USE_OLDARGS, the varargs calls in pline.c actually need to pass a
fixed number of arguments (padded with dummies for unused ones) when
using a compiler which checks argument usage for consistency.
pline.c used to be the only core source file which needs VA_PASSx()
handling, but it looks like calls to config_error_add() in files.c now
need it too. (If there were any calls to panic() in end.c, they would
need it as well, but there aren't.)
Telling people to #quit due to something going wrong internally is
probably a bad idea; the game might or might not be corrupted, but
even if it is, most players will want to play on rather than lose
their game entirely.
Instead, advise saving and reloading; this will fix the underlying
cause of many impossible()s (which are normally related to
inconsistent internal structures; the save file format has much
less redundancy, therefore less chance of inconsistency, than the
in-memory format).
Thanks to AmyBSOD for reminding me to do this.
Files modified:
include/extern.h
src/pline.c, priest.c, potion.c, mkobj.c
A bunch of calls to pline() in pline.c started triggering warnings
either as-is or possibly after the changes to tradstdc.h. Fixing
them in place would include intrusive VA_PASSx() like in lev_main.c.
Moving them to other files is much simpler (and they didn't
particularly belong in pline.c in the first place, although I didn't
actually find any better place for them....).
The probing/stethoscope feedback went to priest.c, where there's a
comment stating that it should move to wherever englightenment ends
up once that is moved out of its completely inappropriate current
home in cmd.c. (Holdover from when ^X was wizard-mode only but even
the other wizard mode commands don't really belong with the command
processing code.)
I couldn't reproduce the reported problem of the "In what direction?"
being issued after the screen was cleared, but bypassing pline() in
favor of putstr(WIN_MESSAGE) for tty prompts did also bypass
if (vision_full_recalc) vision_recalc(0);
if (u.ux) flush_screen(1);
done in pline(). Inadvertent loss of the latter could conceivably be
responsible for the problem. If so, the escape code used by cl_end()
may be broken for somebody's termcap or terminfo setup since clearing
to the end of the line in the message window shouldn't erase the rest
of the screen.
Regardless, the prompting change also bypassed the ability to show
the prompt with raw_printf() if the display wasn't fully intialized
yet, so some change to the revised prompting was necessary anyway.
Switching back from putstr(WIN_MESSAGE) to pline() resulted in
duplicated entries in DUMPLOG message history, one with bare prompt
followed by another with response appended, so more tweaking was
needed. The result is use of new custompline() instead of normal
pline(). custompline() accepts some message handling flags to give
more control over pline()'s behavior. It's a more general variation
of Norep() but its caller needs to specify an extra argument.
Separate the message logging out of pline so that other things (for
instance, one-line summary for quest block messages) can be logged.
The code that utilizes this isn't ready for prime time yet.
For FREE_ALL_MEMORY, release DUMPLOG message history when saving.
(Actually, this frees it unconditionally rather just doing so for
FREE_ALL_MEMORY.) It was being freed when logged at end of game,
but not during save. If dumplog message history and interface
message history get integrated, the existing message history
save/restore handling should become applicable instead.
Use a simple ring buffer instead of a flat array that needed to have
49 pointers shifted down a slot every time a pline message was issued.
'saved_plines[saved_pline_index]' is the oldest message in the buffer
and the next slot to use when adding a new one.