Reordering "killed for the first time" and "hit with a wielded weapon
for the first time" was done by moving the latter to hmon(). Hitting
with an applied polearm also gave the first-hit message since it
bypassed the routine that had been doing so. But the throwing code
that handles applied polearms calls hmon() for damage, so after that
reordering, the first-hit log message became duplicated if triggered
by polearm usage.
Also, fix a quibble with the wizard mode conduct message given after
never-hit-with-wielded-weapon conduct has been broken. The message
said "used a wielded weapon N times" when it meant "hit with a wielded
weapon N times". "Used" is misleading if that wielded weapon happens
to be a pick-axe, so change the message to say "hit with".
Move a bunch of stuff out of main() into new early_options(): '-dpath'
playground directory handling, '-s ...' show scores instead of playing,
and the 'argcheck()' options: --version, --showpaths, --dumpenums,
and --debug (not to be confused with -D). Also introduce
| --nethackrc=filename
| --no-nethackrc
to control RC file without using NETHACKOPTIONS so that that is still
available for setting other options. They can start with either one
or two dashes. --no-nethackrc is just --nethackrc=/dev/null under the
hood. '-dpath' can now be '--directory=path' or '--directory path'
but the old syntax should still work. '-s ...' can be '--scores ...'.
Basic call sequence in unixmain relating to options is now
|main() {
| early_options(argc, argv[]);
| initoptions(); /* process sysconf, .nethackrc, NETHACKOPTIONS */
| process_options(possibly_modified_argc, possibly_modified_argv[]);
|}
Options processed by early_options() that don't terminate the program
are moved to the end of argv[], with argc reduced accordingly. Then
process_options() only sees the ones that early_options() declines to
handle.
Most early options were using plain exit() instead of nh_terminate()
so not performing any nethack-specific cleanup. However, since they
run before the game starts, there wasn't much cleanup being overlooked.
chdirx() takes a boolean as second argument but all its callers were
passing int (with value of 1 or 0, so it still worked after being
implicitly fixed by prototype). Change them to pass TRUE or FALSE.
argcheck() was refusing (argc,argv[]) with count of 1 but then it was
checking 0..N-1 rather than 1..N-1, so it tested whether argv[0] was
an argument instead of skipping that as the program name. Change to
allow count of 1 with modified argv that has an option name in argv[0].
That happens to fit well with how early_options() wanted to use it.
From EvilHack, under the basis that anyone trained in martial arts (or
is in a powerful kicking polyform or wearing kicking boots) should be
immune from landing such a poor kick. This bypass used to happen only
50% of the time; now it happens all the time.
Note that this only averts the "Your clumsy kick does no damage" case:
it remains possible for a powerfully kicking player to kick clumsily and
have the monster evade or block, for example if they are fumbling or
wearing bulky armor.
Also, documentation: I added a comment explaining what the incredibly
dense and confusing logic is with i and j happening here, for the next
poor soul that has to read that code.
When you have a polearm as secondary weapon, have a fireassist on,
and press 'f' to fire, the code tries to swapweapon to the polearm.
This failed badly and got stuck in a loop if you were also wearing
a shield - as polearms are two-handed and shield prevents wielding
those.
Add a new "command failed" result, and clear the command queue
in that case. Also make swapweapon and wield actually return
the ECMD flags back to the rhack loop.
When hallucinating, use nonsensical names for the rays
(wands, spells, and breath weapons), and random ray glyphs.
Original code from xNetHack by copperwater <aosdict@gmail.com>,
inspired by a YANI by Kahran042.
I've implemented 'nethack -nethackrc=filename' as an alternative to
'NETHACKOPTIONS='@filename' nethack' but at the moment it doesn't
work because the command line parsing comes after the run-time config
file has already been processed. But this part should work, or maybe
have problems spotted and fixed if it doesn't. The RC file part of
initoptions_finish() has been rewritten so that it won't need extra
replication of
| set_error_handling()
| process_file()
| reset_error_handling()
| if (NETHACKOPTIONS) {
| set_error_handling()
| process_options()
| reset_error_handling()
| }
I've tried to test all the combinations mentioned in the comment but
am not sure that I covered everything, particulary for repeating
earlier tests after making incremental changes.
I wanted to be able to specify -windowtype:foo on the command line so
that I didn't have to use "NETHACKOPTIONS='windowtype:foo' nethack"
and it turned out that such an option already exists, as "-wfoo".
I either never knew about that or had completely forgotten it. Anyway,
this makes specifying windowtype be more versatile.
"-wX11" still works; now "-w X11", "-windowtype=X11", "-windowtype:X11"
work too, with "--" variations of the latter too also supported. The
long name can be truncated to any leading substring of "windowtype",
although it has to be at least "wi" for "--"; "--w" is rejected.
Also, any errors reported while processing the command line are
treated like config file processing errors rather than just delivered
with raw_printf(). On tty at least, they used to vanish when the
screen cleared to start the game, with no chance to read them. Here's
an example from after this change. It sets windowtype to tty and then
overrides that with X11.
|% ./nethack --w:Qt --win tty -wX11 -windowtype
|
|
| * Unknown option: --w:Qt.
| * Window type [nothing] not recognized. Choices are: tty, curses, X11, Qt.
|
|2 errors on command line.
|
|
|Hit return to continue:
This should probably be better integrated with argcheck() or vice
versa but the only change to that was a couple of formatting bits.
Anything that already worked should continue to work just the same,
aside from the improvement to the error feedback.
In the name of accessibility: Prevent moving into dangerous liquids.
Now with themed rooms, water and lava are more common, and it's
unreasonable to expect blind players to check every step for those.
With paranoid:swim, just prevent normal walking into those liquids,
unless you prefix the movement with 'm', or if the liquid would not
harm you.
Doesn't completely prevent an accidental dunking - for example
if the hero is impaired or couldn't see the liquid.
This comes from xNetHack by copperwater <aosdict@gmail.com>
with some changes to the code.
If the first monster the hero kills is killed by the hero's first hit
with a wielded weapon, report the hit first and kill second instead of
the other way around. Not as hard to manage as I feared, but bound to
be more fragile than the simpler handling that produced the odd order.
Also while testing it I knocked something into a polymorph trap and it
changed form without any feedback. Give foo-changes-into-bar message
if the hero is moving and can see it happening. It isn't needed with
a monster moves deliberately into a polymorph trap but probably would
be useful when that's is unintentional.
The "<hero> enters the dungeon" log message had a trailing period but
other log messages don't have sentence punctuation, so take that off.
When a thrown item lands in a pool of water, it immediately
rusts - but don't give that message unless the hero is at the same
location and also under the water. My reasoning: hero can't see items
under water, and by the time the item rusts, it's in the water.
I don't try to toggle 'number_pad' very often, but when I do I almost
always type '0' instead of 'a' for Off or '1' instead of 'b' for On
on the first attempt. The menu shows
| a - 0 (off)
| b - 1 (on)
| c - 2 (on, MSDOS compatible)
| d - 3 (on, phone-style digit layout)
| e - 4 (on, phone-style layout, MSDOS compatible)
| f - -1 (off, 'z' to move upper-left, 'y' to zap wands)
This change makes '0' through '4' be undocumented group accelerators
for 'a' through 'e' (and '5' for 'f') in the sub-menu put up by 'O'.
tty and X11 worked as-is for '0' and required what amounts to a pair
of one-line changes to handle the other digits.
It doesn't work for curses and Qt (no idea about Windows GUI) because
they insist on treating any typed digit as the start of a count even
if one or more menu entries include that digit as a group accelerator.
(They also fail to support '0' as the group accelerator for iron-ball
class in the menu for multiple-drop.)
MONITOR_HEAP+heaputil pointed out some unreleased memory. The livelog
stuff wasn't being freed. Not surpringly the data used for collecting
and formatting build-options that just got changed from strdup() to
dupstr() wasn't being freed. And a couple of date/version bits.
mdlib.c was avoiding alloc() and dupstr() because mdlib.o gets linked
with makedefs and makedefs used to need to avoid those. But makedefs
doesn't avoid those anymore, so mdlib.c doesn't need to either.
Replace a couple of other strdup() calls in other files too.
The livelog message for losing a level had an off-by-1 error, showing
the level the hero ended up at rather than the level that was lost.
There was a message for regaining a previously lost level when rank
title stayed the same but no such message if the title changed (the
achievement of gaining a particular title only occurs once).
Say "regained" rather than "gained" when gaining a previously lost
level. (Blessed potions of full healing regain levels but can also
reduce u.ulevelmax so a different way to remember peak experience
level has been added.)
Report level change due to polymorphing into new man/woman/elf/&c.
I hadn't realized that that hasn't been recording achievement for new
rank when applicable and decided to leave things that way.
Report gender change when putting on an amulet of change or becoming
a new man/&c unless hero is polymorphed at the time or experience
level is also changing.
Call growl even if you are deaf, because growling also
wakes up nearby monsters. Just make growl not show the message
if you can't hear or see the monster.
Log all level gains and loses. For the existing logging of changes
in rank, mention the level number with the new title. Classifying
level loss as "minor achievement" seems weird but I didn't see any
choice more appropriate.
Make '#chronicle' autocomplete. That makes "#ch" ambiguous, but
better to have to type #cha to chat than to have to completely spell
out #chronicle. (Changing it to #journal would make #j ambigious
but might still be an improvement.)
Call display_nhwindow(WIN_MAP) after curs_on_u(). Instead of calling
it a second time, it's simplest to just update status before updating
the map.
If anything is still leaving the cursor dangling at the end of status
I think it will now dangle at the last updated position on the map.