Even out the difficulty (from one game to another) somewhat. Instead
of a 75% chance that two large areas will be opened up on the left
and right sides of the arrival area plus 13.5 (avg) * 1.5 (avg) extra
monsters in that region, change to 60% chance that the left side will
be opened up with 7 (avg) * 1.5 (avg) extra monsters and a separate
60% chance that the right side will be opened up with 7 * 1.5 (avg)
extra monsters. The chance that both sides get opened up drops to
36% but the chance that neither side gets opened drops to 16%, with
difference made up by 24% chance each for just one side or the other.
I was a little surprised that this actually worked. I hope there's
a less clumsy way to have a loop index.
Separate the compiler flags used for compiling X11 code from the rest
of CFLAGS. Affects hints/macosx10.8 and later.
Add an explicit output argument to the generated compile rules.
The 'O' handling for bouldersym was updating the display value for
boulder even if the value had been rejected, and if it still had the
default of '\0', the map would end up with <NUL> characters. (When
examined via '//' or ';', those matched dummy monster class #0 and
led to the impossible "Alphabet soup: 'an("")'" that was suppressed
yesterday.)
Attempting to set bouldersym to ^@ or \0 would also be rejected as
duplicating a monster symbol. That is now accepted and used to reset
the boulder symbol to default. However, other control characters are
also accepted--not due to this patch, they already are, and from a
config file in addition to via 'O'--so bouldersym can still disrupt
the map. But that's no different from putting control characters
into a symbol set or setting them from config file via S_foo:^C.
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.
Fix another inconsistency with containers in shops: prices shown when
looking inside. Apply had them (because shop goods in containers are
flagged as 'unpaid' when hero carries the container), and loot did not
(because they aren't flagged that way).
stolen_value() treated hero-owned container holding shop-owned goods
as free for the taking.
The fix I'm working on which led to discovering this first added
stolen_value() then eventually stopped using it so I don't have an
example of where it is giving the wrong result.
get_cost_of_item() was giving different information from shop #chat
when dealing with containers owned by hero containing objects owned
by the shop. And when it was legitimately reporting a price of 0,
doname_with_price() wasn't reporting 'no charge' for items inside a
shop that were owned by hero or that shopkeeper didn't care about.
Extend the shop price reveal to far-look, but only when hero and item
being examined are inside the same shop.