Starting as a pauper and executing #conduct during play reported
"you have gone without possessions", which wasn't accurate unless
your inventory remained empty from start until the time #conduct was
examined. That isn't tracked. I don't think it needs to be since
staying possessionless from start to finish is not a viable goal
unless you're on a suicide mission.
Change #conduct feedback for pauper to "you are without possessions"
if inventory is currently empty and "you started without possessions"
when it isn't.
Also, report pauper before nudist (which is enabled implicitly when
starting without any equipment). The other way around struct me as
being a bit strange, although if nudist was specified in addition
to pauper it probably makes sense.
If hero survives a killing blow via saving-grace, report that to
livelog but hide it from player's own #chronicle.
Only reveal whether saving-grace was used up during end-of-game
disclosure. Omit that during enlightenment unless running in
explore mode (or wizard mode).
Issue a livelog/#chronicle message if saving-grace saves the hero.
Right now it's classified as conduct for livelog filtering, because
I didn't want to implement a new category (needs update of global.h
and also the template 'sysconf') and conduct felt like the best fit
of the existing classifications.
Report whether saving-grace is available or already used, among
the attributes of magical enlightenment or end-of-game disclosure.
And move the fixes entry for it from the fixes section to the new
features section of fixes3-7-0.txt.
It seems likely that someone will want to turn not using saving-
grace into a tracked conduct. That seems like overkill to me, not
to mention inflating the N for "N conduct games".
If player uses the 'm' prefix before the #vanquished command when
the vanquished monsters list has fewer than two types so far,
select the preferred sort for #vanquished even though it won't be
applicable yet.
Also, when prompting about vanquished monsters during end of game
disclosure, where an 'a' response is given special meaning, use
"[ynq]" instead of "[ynaq]" if there is only one type of monster
vanquished. It's skipped altogether when the list has zero types
and there's no point in picking sort order when there is just one
type. The player can still answer with 'a' when [ynq] doesn't show
that (for tty and curses at least, probably X11); 'a' will end up
behaving as 'y' in that case.
Explicitly sort and label Riders before major demons when displaying
vanquished monsters with sort-by-class. They're lumped in with '&'
but they aren't really demons.
When looking at a monster that's inside a gas cloud, include that
fact in the output for farlook and for probing. When the monster
being examined is sensed rather than seen, you'll sense the presense
of the cloud as well as the monster even if the cloud can't be seen.
Do likewise for self when using look-here (':'). Bonus fix: zapping
wand of probing at self while engulfed reported that you were just
held by the engulfer.
Also fix an old comment typo/thinko.
The g? structs had a mix of variables that were written to
the savefile, and those that were not.
For better clarity and to distinguish those that end up in
the savefile, relocate some g? variables that get written
directly to the savefile into different structs.
This updates EDITLEVEL, although technically it probably
didn't need to, since savefile contents are not changing.
Details:
gb.bases -> svb.bases
gb.bbubbles -> svb.bbubbles
gb.branches -> svb.branches
gc.context -> svc.context
gd.disco -> svd.disco
gd.dndest -> svd.dndest
gd.doors -> svd.doors
gd.doors_alloc -> svd.doors_alloc
gd.dungeon_topology -> svd.dungeon_topology
gd.dungeons -> svd.dungeons
ge.exclusion_zones -> sve.exclusion_zones
gh.hackpid -> svh.hackpid
gi.inv_pos -> svi.inv_pos
gk.killer -> svk.killer
gl.lastseentyp -> svl.lastseentyp
gl.level -> svl.level
gl.level_info -> svl.level_info
gm.mapseenchn -> svm.mapseenchn
gm.moves -> svm.moves
gm.mvitals -> svm.mvitals
gn.n_dgns -> svn.n_dgns
gn.n_regions -> svn.n_regions
gn.nroom -> svn.nroom
go.oracle_cnt -> svo.oracle_cnt
gp.pl_character -> svp.pl_character
gp.pl_fruit -> svp.pl_fruit
gp.plname -> svp.plname
gp.program_state -> svp.program_state
gq.quest_status -> svq.quest_status
gr.rooms -> svr.rooms
gs.sp_levchn -> svs.sp_levchn
gs.spl_book -> svs.spl_book
gt.timer_id -> svt.timer_id
gt.tune -> svt.tune
gu.updest -> svu.updest
gx.xmax -> svx.xmax
gx.xmin -> svx.xmin
gy.ymax -> svy.ymax
gy.ymin -> svy.ymin
Related note:
There are some pointer variables that are heads of chains that were not
moved from 'g?' to 'sv?', because they are not actually written to the
savefile directly, but the objects/monst/trap/lightsource/timer in the
chains they point to are. That can be changed, if desired.
Examples: gi.invent, gm.migrating_objs, gb.billobjs, gm.migrating_mons,
gf.ftrap, gl.light_base, gt.timer_base
When a camera flash hit a mimic which was posing as something, the
feedback mentioned the mimic but didn't bring it out of hiding.
Change to make light pass over a mimic impersonating an object but
unhide one impersonating furniture. Ones impersonating some other
monster are woken up but wakeup doesn't force it back to mimic shape.
Trying to get the messages right brought on more code changes than
antipated. I changed one of the arguments to mhidden_description()
so had to change its callers; fortunately there aren't very many.
Donning elven boots while riding and not already stealthy, you'd get
the message "you walk quietly" when not walking at all. Instead of
just changing the message, make riding a non-flying steed block
stealth. Riding a flying steed (or one you take aloft with an amulet
of flying) does not. It would have been quite a bit simpler to have
made riding anything block stealth, but the hard part is done.
Fixup some of the inconsistently formatted code that has been
introduced recently or been building up for a while. Done manually.
I wasn't systematic except for looking for lines ending in '&' or '|'
(which wouldn't find such things if they're followed by a comment)
so there might be lots more. I changed a bunch of C++-style //...
comments to old style C /*...*/ so that they'll match the rest of
the core's code rather than because they shouldn't be used.
The same checks were being repeated for every damage type; this
sends them through two centralised functions (one for checking
whether an extrinsic blocks a specific instance of item destruction
and one for the enlightenment message), so that new mechanisms of
item destruction prevention will need to change only one point in
the code.
Instead of just accepting an attribute, it's now possible to
use a color, or both color and attribute, for example:
OPTIONS=menu_headings:inverse
OPTIONS=menu_headings:red
OPTIONS=menu_headings:red&underline
Default is still just inverse.
This lets the player change the menu heading color without
needing to use menu colors for them.
Also makes it so the core uses NO_COLOR instead of 0, for all
the menu lines which don't have any prefedefined color.
Tested for tty, curses, x11, qt, and win32
Reported by entrez, some putstr() to text window got changed to
add_menu_str(). I didn't test with curses; with tty some headers
ended up in limbo: "Artifacts" header for '` a y' (wizard mode show
artifacts, something I had forgotten even existed) and also monster
class headers for 'm #vanquished by-class' (available to everyone).
Qt lost them too, but at least it didn't panic.
Not due to over-simplification: end of game disclosure suppresses
header line highlighting, except when disclosing final inventory.
Change it to do so, although it would be simpler overall to just not
bother with any menu_headings highlight suppression.
Report suggested that "can not" should be "cannot". Both forms are
acceptable. This switches them to use contractions for various "You
<verb> not subject" phrases: "You can't subject", "hadn't", and so
forth. Not exhaustively tested; there may be some sentences where the
informal contraction makes things worse rather than better.
The goal here was compactness rather than efficiency since the code
involved doesn't execute very often.
At either of the genocide prompts,
|What type of monster do you want to genocide?
or
|What class of monsters do you want to genocide?
answering "?<return>" will show the list of monster types that have
already been genocided, then re-prompt.
Monster size affects knockback but it wasn't provided anywhere within
the game. Have wand of probing and stethscope feedback for monsters
include tiny|small|medium|large|huge|gigantic as applicable.
The #genocided command was revealing extinct monster species when used
during normal play. That was not intended, so stop. Change to only
reveal them in wizard or explore modes and also during end-of-game
disclosure but suppress them during normal play.
The full description of #genocided is now dynamically updated for '# ?'
during normal play to remove its reference to extinctions. Also, check
for skipping wizard mode commands before doing description searching.
\#genocided was out of alphabetical order in the full commands list.
Both it and #vanquished should have had the GENERALCMD flag; they
don't affect game state.
Change #genocided to use the sort order currently set for #vanquished,
and allow 'm #genocided' to put up the same menu as 'm #vanquished'.
(Not quite the same. Sorting by count of monster deaths isn't
appropriate for listing genocides where an arbitrary number may have
been killed before the genocide occurred. If the preferred order for
vanquished is set that way, alphabetical will be used for genocided.)
Setting the order via menu for either command sets the order for both,
but doing so via #genocided doesn't offer the count-high-to-low and
count-low-to-high choices. During disclosure, you can answer 'a' when
asked whether to disclose genocided and extinct monster types and like
for vanquished monsters, that lets you choose an order at end-of-game.
Doing so won't affect disclosing of vanquished monsters--it'll be too
late for them.
A chunk of this diff is due to moving the #wizborn code out of the
middle of #vanquished handling.
Guidebook.ms has been updated but Guidebook.tex is lagging.
I was working on this at the time 3.6.0 was released and set it aside
until later. Later has finally arrived. Redo the Blind, Blinded,
Blindfolded,&c macros to make more complete use of intrinsic property
handling. Blinded was being treated as a number which could be added
to or subtracted from; now that has to be done via TIMEOUT mask
because it has FROMOUTSIDE (OPTIONS:blind) and FROMFORM (poly'd into
!haseyes() form) bits included. Object definitions for blindfold and
towel now specify the BLINDED property; overriding blindness via the
Eyes of the Overworld is accomplished via props[BLINDED].blocked.
Code generated for the scores of Blind and !Blind tests throughout
the program should be smaller.
One bug that has been fixed is that putting on the Eyes of the
Overworld cured permanent blindness (from OPTIONS:blind). The
u.uroleplay.blind flag was cleared and stayed so after taking them
off. Putting the Eyes on still breaks blind-from-birth conduct but
now blindness will resume when they are removed.
This was untested at the time it was set aside and is only lightly
tested now. A large number of the changes here are just to switch
from Blinded to BlindedTimeout for current timed value and to call
set_itimeout() for setting a new value.
Undefine some macros when the file that uses them is done so that
they won't be seen by any other source files if combined into one
huge source file. I only looked at the few files where an #undef was
needed, not all the files, but in those few files I used #undef for
[almost] all their local macros instead of just the troublesome one.
display.c is the exception; it still has lots of macros which persist
through end of file. nhlobj.c is another exception; I misremembered
the fixup for lua's lobject.c at the time and decided to include the
one #undef for nhlobj.c anyway even though 'onefile' isn't affected.
monst.c includes some reformatting. display.c's sign() macro was
redone; it's intended for efficiency compared to calling hacklib.c's
sgn() function so streamline it.
[Keni, most of the file-specific #undef fixups in genonefile.pl can
now be removed. It'll still need one for lua source file lobject.c;
addstr() there conflicts with curses.h, not with nethack's own code.]
Comparable to #vanquished, be able to view info normally available
during end of game disclosure while the game is still in progress.
The new #genocided command lists all genocided and extincted types
of monsters. Unlike #vanquished, there aren't any sorting choices.
Potential future enhancement: provide a way to view the genocided
list at the "what do you want to genocide?" prompt.
Switch to using the term "sound triggers" for things that
result in a call to one of the soundlib routines.
SNDCAP_* renamed to SOUND_TRIGGER_*
sndcap field in the sound_procs struct changed to sound_triggers
Groundwork for a more versatile interface for using
sound libraries. A lot of sound libraries work across
multiple platforms.
The current NetHack sound stuff is quite limited.
Binaries can have a variety of window ports linked into
them, and it makes sense to have something similar for
sound.
This tries to set things up in a more soundlib-centric way,
rather than inserting things in a platform-centric way.
It establishes a new top-level directory sound (akin to win
for the window interface routines, or "window-port") where
sound-related additions and sndprocs and support files can be
added and used across platforms.
The default interface is nosound and the 'nosound' interface
is in src/sounds.c
The interface for 'windsound', which contains the same minimal
USER_SOUNDS support using built-in routines that has been in the
windows port for a long time is added to
sound/windsound/windsound.c.
For now, the sound interface support for 'qtsound' has been added
to the existing Qt files win/Qt/qt_bind.h and win/Qt/qt_bind.cpp,
and a note has been placed in sound/qtsound/README.md to avoid
confusion.
New header file added: include/sndprocs.h.
Allow the preferred sort order for the vanquished monsters list to
be specified in the run-time config file
|OPTIONS=sortvanquished:X
where X is t, d, a, c, n, or z. It can also be set to 'A' or 'C'
but those aren't documented and aren't offered as choices when
setting the value interactively, which can be done via 'm O' or by
using 'm #vanquished'.
Guidebook.mn has been updated but Guidebook.tex is lagging again.
The consolidation of global variables from scattered source
files into decl.c and declared in decl.h was begun in 3.7.0.
Their placement in common files was done for centralized
initialization and potential re-initialization during a
"play again" scenario.
It wasn't really necessary for all of them to be housed in a
single huge structure to meet the "play again" requirement,
and the single huge structure has been a little unwieldy when
it comes to maintenance.
Following this commit, instead of one single extremely large structure
named 'g' to house all of the relocated global variables, they
are distributed into several ga through gz.
To make things easy for the developer, each variable is placed
into the struct corresponding to the starting letter of the variable.
That way, no lookup is required in order to know which struct houses
a particular variable, it is a simple match to the starting letter
for all the centralized global variables.
A global variable named 'amulets', would be found in ga.
ga.amulets
^ ^
A global varable named 'move', would be found in gm.
gm.moves
^ ^
A global variable named 'val_for_n_or_more' would be found in gv.
gv.val_for_n_or_more
^ ^
A global variable named 'youmonst' would be found in gy.
gy.youmonst
^ ^
Make the existing '#vanquished' command be available during regular
play, with M-V bound to it. 'm #vanquished' or 'm M-V' brings up
the sorting menu that you get when answering 'a' rather than 'y' at
the end-of-game "disclose vanquished creatures?" prompt.
The original #vanquished came from slash'em, where it was available
in normal play. When added to nethack, it was put in as wizard-mode-
only. I added the sorting capability several years ago.
The chosen sort is remembered and re-used if not reset but only for
the remainder of the current session. It probably ought of become
a run-time option so be settable in advance and across sessions but
I haven't done that.
Instead of using index() macro defined to strchr, use C99 strchr.
Instead of using rindex() macro defined to strrchr, use C99 strrchr.
If you want to try building on a platform that doesn't offer those
two functions, these are available:
define NOT_C99 /* to make some non-C99 code available */
define NEED_INDEX /* to define a macro for index() */
define NEED_RINDX /* to define a macro for rindex() */
The #wizborn command shows 'E' for an extinct species and 'G' for a
genocided one, but if a species first becomes extinct and then later
gets genocided, instead of showing both flags it stopped showing
either. I was going to add a second flag column and show 'E' and 'G'
separately but decided to stick with one column and display 'X' for
the unlikely 'both extinct and genocided' case.
When not carrying any contained gold, or the only contained gold is
inside container(s) whose contents aren't known, ^X writes one line
about the hero's "wallet". When known contained gold is present, it
writes two lines for gold, first one about wallet with the second
one about contained gold being a continuation of the first. Move
the conjunction that combines them from the start of the second line
to the end of the first.
So change
|Your wallet contains M zorkmids,
|and you have N more contained in your pack.
to
|Your wallet contains M zorkmids, and
|you have N more contained in your pack.
and
|Your wallet is empty,
|but you have N zorkmids contained in your pack.
to
|Your wallet is empty, but
|you have N zorkmids contained in your pack.
It evens out the line lengths a little bit and starting the second
line with uncapitalized "you" seems slightly less jarring than with
"and" or "but".