phase_of_moon and friday_13th determined using rn2() instead of local
time if fuzzing. Don't reseed using init_random() if fuzzing. Allow
set_random to be called outside of hacklib. rn2_on_display_rng uses
rn2 if fuzzing so that we have a single source of random that we can
ensure is reproducible. Implement rul() that returns a random unsigned
long. Fix bug in fuzzer handling of ntposkey which would cause us to use
unitialized values for x and y. Added command line arguments to allow
auto starting and stopping of fuzzer. Add a logging facility for the
fuzzer to use to record activity. Added some scripts used to automate
fuzzer testing on windows.
Extend support for highlight rules that specify percentages from HP
and spell power to experience level and experience points. For both
of those, the percentage is based on progress from the start of the
current Xp level to the start of the next Xp level. 100% isn't
possible so is used to enable highlighting a special case: 1 point
shy of next level, most likely to occur after losing a level.
This is something I had in mind a long time ago and then forgot all
about until fiddling with the final disclosure of experience points
recently. It turned out to be trickier than expected because it needs
to check whether Xp should have a status update when it hasn't changed
but Exp has gone up. The latter might hit a percentage threshold that
switches to another highlight rule. Fortunately changes to Exp, at
least that aren't part of level gain or loss (which always trigger
status updating), are all funnelled through a single place (I hope).
Make some progress on a couple of next minor release checklist
items, hopefully without introducing too many new bugs. This
is just the initial commit, and work continues.
Checklist items:
Savefiles compatible between Windows versions, whether 64-bit
or 32-bit in little-endian field format.
Selection of file formats:
historical (structlevel saves),
lendian (little-endian, fieldlevel saves),
and just for proof-of-concept, ascii fieldlevel saves
(the ascii is huge! 10x bigger than little-endian).
For the fieldlevel save, all complex data structures recursively
get broken down until until it is one of the simple types that
can't be broken down any further, and that gets when it gets
written to the output file.
New files needed for this build:
hand-coded:
include/sfprocs.h
src/sfbase.c - really a dispatcher to one of the
output/input format routines.
src/sflendian.c - little-endian output writer/reader.
src/sfascii.c - ascii text output writer/reader.
auto-coded (generated):
include/sfproto.h
src/sfdata.c
This is just one approach. I'm sure there are countless others
and they have different pros and cons.
For producing the auto-coded files a utility called
universal-ctags, that is actively maintained and evolving,
was used to do all the heavy-lifting of parsing the
NetHack C sources to tabulate the data fields, and store
them in an intermediate file called util/nethack.tags
(not required for building NetHack if you already have a
generated include/sfproto.h and src/sfdata.c)
util/readtags (also not required for building NetHack
itself) will decipher the nethack.tags file and produce
the functions that can deal with the NetHack struct data
fields.
You can obtain the source for universal-ctags by cloning it
from here:
https://github.com/universal-ctags/ctags.git
The combination universal-ctags + util/readtags has been
tried and tested under both Windows and Linux, so it is
not tied to a particular platform.
Note: util/readtags will work only with universal-ctags
output, so other ctags are unlikely to work as-is.
Universal-ctags can be build from source very easily
under Linux, or under Windows using visual studio.
One of the claims in #H8849 was that a monster which zapped a wand
that the hero had fully identified made hero's knowledge of it revert
to "a wand". That doesn't happen; it had to have been a different
wand which hadn't been seen up close yet. But the hero should lose
track of known number of charges if a wand is zapped outside his/her
view. When implementing that I noticed that a monster playing a fire
horn to burn away slime was using the routine that gives wand
feedback. Add a separate, similar routine for magical horn feedback.
Half this diff is due to moving a naming support routine from mhitm.c
to do_name.c.
Fix a couple of glitches and add an enchancement. The monster
attributes structure left the 'hidden' field uninitialized unless user
specified "hidden". Mimics were being flagged with mon->mundetected
because they pass the is_hider() test but they 'hide' by taking on an
appearance rather than being unseen due to mundetected. hides_under()
monsters fail the is_hider() test, but can become mundetected if there
is at least one object present. Eels/other fish are neither is_hider()
nor hides_under() but can be mundetected at water locations. So alter
'hidden' handling to deal with these various circumstances.
Asking for 'hidden' for any type of creature will result in having its
location be highlighted if it can't be actively seen or detected. So
using '2000 ^G piranha' will fill up the Plane of Water "normally" but
'2000 ^G hidden piranha' will result in a ton of draw-glyph/delay/
draw-other-glyph/delay sequences and take a painfully long time. Moral
of the story: don't combine 'hidden' with a large count unless you
want to spend quite a while watching the level's fill pattern. Turning
off the 'sparkle' option will cut the flashing in half but still take
a long time. If you really need to fill a level with hidden creatures
and can't bear the flashing/highlighting, use blessed potion of monster
detection or #wizintrinsics to have extended detect. Then all created
monsters will be seen so none will trigger location highlighting.
If you create a 'stalker' or 'invisible stalker' or 'invisible <other-
mon>' its location won't be highlighted, but for 'hidden stalker' or
'hidden invisible stalker' or 'hidden invisible <other-mon>' it will
(provided you don't actually see it due to See_invisible or sensemon()).
Throwing or kicking a lit lamp, lit candle, or lit potion of oil
wasn't giving off any light as it travelled to its destination.
Now it does, and dungeon features, objects, or monsters that are
temporarily seen as it moves from square to square till appear on
the map. In the monster case, they go away as soon as the light
moves beyond range, but when it finishes moving the "remembered,
unseen monster" glyph will be drawn at their location. I think that
part has some room for improvement, but mapping temporarily seen
terrain features is the primary impetus for this change.
Also, any message delivery while the "lit missile" travelled still
showed its light around the hero. Noticeable for lamps or stacks
of sufficient candles if hero has no other light source.
This cannibalizes the monst->mburied bit for temporarily seeing a
monster. It has been present but unused for ages. I needed to
replace a couple of vision macros to make sure they didn't examine
it any more so that overloading for transient lighting doesn't
introduce any vision oddities. For version $NEXT, monst->mtemplit
can be given its own bit. It is only set during bhit() execution
and cleared by the time that returns, so has no effect on save files.
Hero polymorphed into a vampire or v.lord can use #monster to switch
to vampire bat or fog cloud [or wolf for lord] but it was a one shot
polymorph. Remember when current form is a shape-shifted vampire and
allow #monster in shifted form to pick another shifted form or the
vampire form.
Genocide of the alternate shape forces back to base vampire. Genocide
of base vampire does too, then reverts to human (or dwarf, &c) as
vampires go away. Being killed while shafe-shifted reverts all the
way to human rather than to vampire. [Just realized: interaction
with Unchanging wasn't taken into consideration so hasn't been tested.]
Since 'youmonst' isn't saved and restored, I had to add a field to 'u'
to hold youmonst.cham during save/restore.
Tested with 3.6.2+ and seemed to be working (except saving while
shape-shifted restored as ordinary bat/cloud/wolf because new u.mcham
wasn't there to hold youmonst.cham yet). Builds with 3.7.0- but not
execution tested yet (I didn't want to clobber my current playground).
placebc was triggering an impossible sometimes on the plane of
water
It turned out to be because movebubbles issued an
unplacebc(), but a downstream function called
placebc(), so when movebubbles() issued its own
placebc() there was a problem.
The downstream function that beat movebubbles to the placebc()
turned out to be unstuck(). There could be others.
Changing an inventory item's bknown flag wasn't followed by a call to
update_inventory() in many circumstances, so information which should
have appeared wasn't showing up until some other event triggered an
update.
Even though a goodpos failure in mnearto() would return 0 to
the caller and trigger proper overcrowding handling for mtmp,
the 'othermon' would be left with its mx,my set to 0,0 under
that circumstance and then trigger a mon_sanity_check()
failure and accompanying impossible() message a short while
afterwards.
This also includes the addition of some flags that proved useful
for troubleshooting the mystery sanity_check failure and helping
to understand some of the code paths the struct monst data had
been through. They are only used for inspection when issues are
reported or when debugging, they don't presently control the
code flow. Their setting and use is done in an overloaded way
that should not intrude on the existing use of mspare1 for
MIGR_LEFTOVERS. mon->mstate is just a pseudonym for mon->mspare1
and does not alter save file content.
Add a bc sanity check. It seems to work ok--in other words, not
trigger--under normal punishment. I don't have any test cases to
exercise its warnings.
This dragged in a couple of minor bc changes that were pending. I
should have cleared those out before tackling the sanity checking.
During shop repair, give a message about the shopkeeper using a spell
(if hero is close enough) before "Suddenly, <various repairs occur>."
And when shop repair is for a single untrap of landmine or bear trap
adjacent to shk (and the hero can see it happen), say "<Shk> untraps
<trap>" rather than just "Suddenly, a trap is removed from the floor!"
Change in meaning of mnearto()'s return value wasn't progagated to
shkcatch(). Make it an int instead of boolean so that it can
communicate both 'moved successfully' and 'moved but had to move
another monster out of the way to do so'.
Take care of a minor 'TODO' and make another stab at getting truncated
encumbrance and/or level-description to reset to full size when enough
space becomes available.
Put the prototypes for routines in botl.c into the same order as the
corresponding functions are in the file. Also a few were missing and
another few used STATIC_OVL when STATIC_DCL was appropriate.
When the 'time' option is on and context.botl isn't already set,
call a simpler status update routine that ignores all other fields.
When that flag is already set, full status update takes care of time
along with the other fields.
Expected to reduce bottom lines processing time but not screen I/O.
Only lightly tested.
Noticed while testing statuslines on a small terminal window. Using
the cursor to pick locations that panned the map to view a new subset
would end up showing a new view of the regular map rather than a
different section of what was currently displayed. For farlook that
caused monsters to take on new hallucinatory forms which was fairly
inconsequential, but for #terrain and various forms of detection it
reverted to the ordinary map instead of showing the map features that
the player requested or the temporarily revealed monsters and such.
Most interfaces keep track of the whole map and just show their view
of the new subset when panning, similar to redisplay after being
covered up and then re-exposed, but tty isn't doing that. I made
same change to Amiga as to tty since the code it was using was very
similar. I haven't touched any of the other interfaces and assume
that they don't need this. I've verified that curses and X11 don't.