I ran the fuzzer with MONITOR_HEAP enabled and heaputil found a dozen
or so un-free'd allocations, all made by the same dupstr() call in
special_handling() for "symset" and "roguesymset". (Reproducible with
a few tens of thousands of fuzzer moves, although you have to take
over from the fuzzer and make a clean exit rather than just interrupt
it or there'll be lots of other un-free'd memory.) I haven't actually
figured out how/why it was leaking, but reorganizing the code has made
the leak go away (according to a couple of even longer fuzzer runs) so
I'm settling for that.
A recently added impossible to check for an(Null) and an("") was
triggered by the fuzzer: Alphabet soup: 'an("")'. I reproduced it a
couple of times and tracked it do_screen_description(for '/' command)
matching the symbol from mapglyph to monster class #0, a placeholder
with symbol value '\0'. So mapglyph() returned a symbol of '\0', but
not necessary from showsyms[0 + SYM_OFF_M].
The pager lookup code's monster loop shouldn't have been attempting
to match against class #0, and since this fix I haven't been able to
reproduce the situation again. But I also didn't trigger it with a
bunch of temporary checks in mapglyph() so don't know what is really
going on under the hood.
Back out '#include "date.h"' so that cursinit.c won't be recompiled
every time any other file(s) need to be compiled. It doesn't need
patchlevel.h either. There is already a straightforward way to fetch
the copyright banner lines from version.c.
The splash screen (ascii art spelling "NetHack" preceding the normal
copyright lines) was invisible when showing white text on white-ish
background. Make it honor !guicolor.
"Shall I pick a character's role, race, gender and alignment for you?
[ynaq] (y) " was too wide to accept the answer on the same line on
an 80-column display so "(y) " was placed on the second line. That's
constructed in the core; change the construction to omit " a" when
using "character" rather than a role name. (tty shortens it by omitting
the default " (y)"; with " a" gone, it could revert to normal prompt.)
Also a bit of lint cleanup and some reformatting of cursinit.c....
The change to Makefile.src for X11+XPM on linux broke linking X11 on
OSX. This updates the hints files (except for the -qt one) so that
make WANT_WIN_X11=1
and
make WANT_WIN_X11=1 USE_XPM=1
work correctly.
The comment in macosx10.14 about what version(s) it's intended for
and been tested on is just cloned from 10.10 and should be updated.
The inventory window used a line to say "Inventory:", which is pretty
useless, and that was the only window showing such a label.
Also don't duplicate the "Not carrying anything" text from core.
People have been wondering how to change the tiles on the X11
version, and the old default of NetHack-specific binary tile data
isn't directly editable with image editing tools.
Also show in the #version info if xpm and graphic rip are enabled.
The revised mkclass() [actually new mkclass_aligned()] has an extra
check which didn't used to be there, and attempting to create a
monster of class 'I' with ^G triggered impossible "mkclass found no
class 35 monsters" which the fuzzer escalates to panic.
Fixes#170
Monsters never throw athames or scalpels but some fake player monsters
on the Astral Plane are given those. Since they're stackable the
quantity usually gets boosted but there's no point in having more than
one if they won't be thrown.
This could have been fixed by letting monsters throw those two items,
but I prevented the quantity from being boosted instead.
When merging one stack into another and they have different obj->o_id
price adjustments, keep the o_id of whichever one commands the higher
shop price.
I misread part of the original code and the revision introduced a bug
based on that. obj->o_id price variations are used for all types of
non-IDed items, not just non-glass gems.
Player came across a stack of 2 gray stones in a shop and kicked one.
That one ended up with a different (in his case, lower) price once it
was separate. This behavior only applies to non-glass gems which add
a price variation derived from internal ID (obj->o_id) number. Make
splitting stacks always yield the same price per item in the new stack
as was being charged in the old stack by choosing a similar o_id. Do
it for all splits (that can vary price by ID, so just non-glass gems),
not just ones performed inside shops.
He picked up the lower priced one and dropped it back on the original
higher priced one; the combined stack took on the lower price. That
will no longer happen if they come from splitting a stack, but this
fix doesn't address merging with different prices when they start out
as separate stacks. (Unpaid items won't merge in inventory if prices
are different, but shop-owned items will merge on floor.)
It was possible to have the guaranteed luckstone at Mines' End become
merged with a random one and lose its specialness for achievement
tracking. Mark it 'nomerge' when created and clear that if/when the
achievement is recorded.