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
Add options 'showvers' (boolean) and 'versinfo' (numeric mask) to
show nethack's version on the status lines during play. It won't be
particularly interesting to ordinary players but should be useful
when making screenshots or video to be streamed, or for someone who
switches between git branches or between nethack and variants.
I worked on this several months back but it was combined with
unfinished changes to 'hitpointbar'. I've separated it out so that
it can be put into use. When enabled, one or more components of
"<name> <branch> <version>" will be shown right justified after
status conditions. At present the default is "<branch>" if that is
available and overall status isn't 'released', or "<version>" if
'released' or if branch isn't available. That might need some
refinement.
It works as intended for tty and curses, although some abbreviation
mechanism would be useful if/when the program resorts to abbreviating
status conditions to make things narrow enough to fit.
For X11, it works ok for fancy_status:True (the default, controlled
via NetHack.ad settings) but is messed up for tty-style status. The
text is positioned correctly but there are gaps in it, making it
appear garbled, similar to what I saw when I tried and failed to
implement statuslines:3 for X11. [It might be due to having empty
condition widgets be 1 pixel wide instead of being totally removed
but I don't think the situation is that simple.]
For Qt, if the text needs to be truncated in order to fit, the center
portion of the string will be shown, discarding parts from the left
and right. That ought to discard from left and retain rightmost
portion instead.
For win32|mswin|Win GUI, no attempt to support it has been included.
Things should be ok when 'showvers' is left as False (the default)
but I don't know what will happen if that gets toggled to True. At a
minimum, the version info won't be right justified. The information,
or at least some of it, is displayed in the game window's title bar
so there isn't any pressing need to add it to status, but toggling
the option will need to behave sensibly if it doesn't already.
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
^ ^
The definition of enc_stat[] got changed by a pull request nearly a
year ago ('const char *enc_stat[]' -> 'const char *const enc_stat[]')
but the separate declarations for it weren't changed to match.
Make the same change for hu_stat[]. Not sure why the pull request
didn't include it since the old declaration and the usage are same.
The curses one is in code that isn't used.
invent.c: In function 'getobj':
invent.c:1579:29: warning: 'cnt' may be used uninitialized [-Wmaybe-uninitialized]
1579 | if (cnt < 1 || otmp->quan <= cnt)
| ~~~~~~~~^~~~~~~~~~~~~~~~~~~~
invent.c:1529:10: note: 'cnt' was declared here
1529 | long cnt;
| ^~~
../win/X11/winstat.c: In function 'update_fancy_status_field':
../win/X11/winstat.c:1920:28: warning: declaration of 'active' shadows a global declaration [-Wshadow]
1920 | static boolean active = FALSE;
| ^~~~~~
In file included from ../include/hack.h:196,
from ../win/X11/winstat.c:36:
../include/wintype.h:180:5: note: shadowed declaration is here
180 | active = 0x001,
| ^~~~~~
Fix up the level descriptions used when logging an "entered new level"
event. Most of the change is for adding an extra argument to calls
to describe_level(). The curses portion is in a big chunk of old code
suppressed by #if 0.
I didn't notice that the level entry events are classified as LL_DEBUG
until all the work was done. This promotes the entry events for the
four Plane of <Element> levels from debug events to major ones instead.
It doesn't do that for the Astral Plane because the entered-the-Astral-
Plane achievement already produces a major event for that. Most other
key level entry events are in a similar situation--or will become that
way once another set of achievements eventually gets added--so there
aren't any other event classification promotions.
Fix the warnings issued when compiling win/X11/. The error handler
one is presumeably due to a change in /usr/include/X11/Intrinsic.h
between different releases of X11 and is inconsequential. The
indentation ones represented real bugs. The X11 convention of using
'foo(); argcount++;' requires braces when preceded by 'if' or 'else'.
I don't know why the convention doesn't use comma instead of semi-colon
between the function that adds an entry to an argument list and the
accumulating count of the number of those arguments.
A few years ago I added code to zero out various argument lists prior
to their use, which shouldn't have been necessary. The wrong argument
count being used when the 'if (whatever)' check fails could possibly
have been the reason that pre-zeroing solved mystery problems. I don't
remember enough details to attempt to go back and retest with this fix
in place.
Fix a couple of warnings and do some reformatting.
Also tracks current color and attributes for each status field
and only updates them if they're being changed instead of every
time the value changes. Not very thoroughly tested so far.
The only attribute being supported is inverse but tty-style
status supports the full set. Also, changed values are always
highlighted in inverse even if there is no highlight rule.
That should probably only apply when 'statushilites' is 0,
giving the old fancy status highlighting when regular hilites
are turned off.
for 'fancy status'. This is from an emailed diff rather than
directly from git, and the git code has a bunch of commits,
so this may or may not match the latest. It needs formatting
cleanup and triggers a couple of warnings on OSX. Fix to follow.
Status highlight colors use the same names as menu coloring
but this uses different X11 colors for the two sets. That
will have to be changed so that yellow either means yellow all
the time or goldenrod all the time instead of sometimes yellow
and sometimes goldenrod.
Adopts #443
add MALE, FEMALE, and gender-neutral names for individual monster species
to the mons array. The gender-neutral name (NEUTRAL) is mandatory, the
MALE and FEMALE versions are not.
replace code uses of the mname field of permonst with one of the three
potentially-available gender-specific names.
consolidate some separate mons entries that differed only by species into a
single mons entry (caveman, cavewoman and priest,priestess etc.)
consolidate several "* lord" and "* queen/* king" monst entries into
their single species, and allow both genders on some where it makes some
sense (there is probably more work and cleanup to come out of this at some
point, and the chosen gender-neutral name variations are not cast in stone
if someone has better suggestions).
related function or macro additions:
pmname(pm, gender) to get the gender variation of the permonst name. It
guards against monsters that haven't got anything except NEUTRAL naming
and falls back to the NEUTRAL version if FEMALE and MALE versions are
missing.
Ugender to obtain the current hero gender.
Mgender(mtmp) to obtain the gender of a monster
While the code can safely refer directly to pmnames[NEUTRAL] safely in the
code because it always exists, the other two (pmnames[MALE] and
pmnames[FEMALE] may not exist so use:
pmname(ptr, gidx)
where -ptr is a permonst *
-gidx is an index into the pmnames array field of the
permonst struct
pmname() checks for a valid index and checks for null-pointers for
pmnames[MALE] and pmnames[FEMALE], and will fall back to pmnames[NEUTRAL] if
the pointer requested if the requested variation is unavailable, or if the
gidx is out-of-range.
Allow code to specify makemon flags to request female or male (via MM_MALE
and MM_FEMALE flags respectively)to makedefs, since the species alone doesn't
distinguish male/female anymore. Specifying MM_MALE or MM_FEMALE won't
override the pm M2_MALE and M2_FEMALE flags on a mons[] entry.
male and female tiles have been added to win/share/monsters.txt.
The majority are duplicated placeholders except for those that were
separate mons entries before. Perhaps someone will contribute artwork in the
future to make the male and female variations visually distinguishable.
tilemapping via has the MALE tile indexes in the glyph2tile[]
array produced at build time. If a window port has information that the
FEMALE tile is required, it just has to increment the index returned
from the glyph2tile[] array by 1.
statues already preserved gender of the monster through STATUE_FEMALE
and STATUE_MALE, so ensure that pmnames takes that into consideration.
I expect some refinement will be required after broad play-testing puts it to
the test.
consolidate caveman,cavewoman and priest,priestess monst.c entries etc
This commit will require a bump of editlevel in patchlevel.h because it alters
the index numbers of the monsters due to the consolidation of some. Those
index numbers are saved in some other structures, even though the mons[] array
itself is not part of the savefile.
Window Port Interface Change
Also add a parameter to print_glyph to convey additional information beyond
the glyph to the window ports. Every single window port was calling back to
mapglyph for the information anyway, so just included it in the interface and
produce the information right in the display core.
The mapglyph() function uses will be eliminated, although there are still some
in the code yet to be dealt with.
win32, tty, x11, Qt, msdos window ports have all had adjustments done to
utilize the new parameter instead of calling mapglyph, but some of those
window ports have not been thoroughly tested since the changes.
Interface change additional info:
print_glyph(window, x, y, glyph, bkglyph, *glyphmod)
-- Print the glyph at (x,y) on the given window. Glyphs are
integers at the interface, mapped to whatever the window-
port wants (symbol, font, color, attributes, ...there's
a 1-1 map between glyphs and distinct things on the map).
-- bkglyph is a background glyph for potential use by some
graphical or tiled environments to allow the depiction
to fall against a background consistent with the grid
around x,y. If bkglyph is NO_GLYPH, then the parameter
should be ignored (do nothing with it).
-- glyphmod provides extended information about the glyph
that window ports can use to enhance the display in
various ways.
unsigned int glyphmod[NUM_GLYPHMOD]
where:
glyphmod[GM_TTYCHAR] is the text characters associated
with the original NetHack display.
glyphmod[GM_FLAGS] are the special flags that denote
additional information that window
ports can use.
glyphmod[GM_COLOR] is the text character
color associated with the original
NetHack display.
Support for including the glyphmod info in the display glyph buffer
alongside the glyph itself was added and is the default operation.
That can be turned off by defining UNBUFFERED_GLYPHMOD at compile time.
With UNBUFFERED_GLYPHMOD operation, a call will be placed to map_glyphmod()
immediately prior to every print_glyph() call.
Add 'tethered' and 'holding' as displable status conditions for X11.
For tty-style status, they're ordinary. For 'fancy status', tethered
is displayed in the 'trapped' slot (since they'll never both be shown
at the same time) and holding is displayed in the 'held' slot (same
situation).
It's more proof of concept for overloading of status conditions than
adding useful specific conditions. This was the third iteration; the
first two were either too fragile or used even more code. It could
probably be simplified by making some mutally exclusive conditions be
more like hunger and encumbrance instead of being distinct flags
X11's "fancy status" does its own highlighting that predates
STATUS_HILITES, showing things which have changed in inverse video
for a turn. However, it excluded conditions plus hunger and
encumbrance. Make it highlight those similarly when they come On
(and when they change from one non-blank state to another in the
case of hunger or encumbrance). There's no corresponding
unhighlight when going Off because they're blanked out instead.
I started out adding a few new status conditions to X11's "fancy status"
(the default) to gauge how difficult it was going to be. In the process
I found several latent bugs. After fixing those, I decided that the same
status conditions should be added to the alternate "tty-style status".
Lots more latent bugs, some of the same nature, others different. Things
spiraled until the code change is very substantial.
Code for the old two-line status is still present but I don't know how
to activate it. Unlike tty-style status, it composes and displays two
lines of text and isn't capable of highlighting portions of that text,
so it would be considered deprecated anyway.
All testing was done with the default NetHack.ad (except when turning
'fancy_status' off) so I don't know whether the new code might override
previously customizable status settings. I'm not sure whether this list
covers all the fixes....
both tty-style and fancy
add new status conditions 'grabbed' (by eel), 'held', 'trapped', and
'sinking-into-lava' (others will eventually follow); grab and lava
are on by default, the others have to be enabled via options
both tty-style (not handled) and fancy (faulty boolean logic)
polymorphing didn't change Xp to HD (silver lining: rehumanizing
didn't need to reverse it)
tty-style only; fancy was ok
force white text (on black background) instead of settling for gray
turning on optional showexp, showscore, and/or time worked but turning
them back off again didn't remove the relevant fields
polymorphing when showexp was on didn't suppress Exp-points
tty-style only; fancy uses different layout
condense conditions into simple left-to-right space separated list
instead of giving them specific locations and having gaps of blank
space for conditions that aren't in effect
tty-style only; not applicable for fancy (status_hilites not implemented)
all highlights stuck if 'statushilites' was reset to 0 to disable them
displaying anything with bold attribute stuck; it wouldn't revert to
normal text if a different highlight rule without bold was used for
subsequent updates
avoid inverting leading space that separates from preceding field when
highlighting with inverse video attribute
add support for 'dim' attribute using gray foreground (only viable
after the fix for white foreground)
fancy only
reorganize the field layout so that things line up nicely instead of
having columns with six, seven, or eight lines be spread over same
amount of vertical space
line up the values of the six characteristics, similar to how vertical
status works in curses: all two digits; when exceptional strength is
present, the '18' lines up and rest goes past implicit right margin
use status conditions as provided by core instead of duplicating them
(other fields still duplicate stuff done in botl.c); doing this
required forcing 'VIA_WINDOWPORT()' if built without STATUS_HILITES
Separate out the reformatting from other changes I'm working on
for X11 "fancy status". Splits a few wide lines but mostly just
switches to the X11 idiom of combining
XSetArg(arglist[argcount], ...);
argcount++;
onto one line:
XSetArg(arglist[argcount], ...); argcount++;
Set X resource NetHack*fancy_status: False to enable the TTY-style
status lines. Default is the fancy status.
This patch is somewhat unfinished - even though the TTY-style status
allow for status hilites, the colors don't work correctly yet.
Also changes the fancy status to use the windowport notification code.
Update X11's status display to include the expanded set of status
conditions. This time the order is
Petrifying <hunger> Blind
Slimed <encumbrance> Deaf
Strangled Levitating Stunned
Food Pois Flying Confused
Term Ill Riding Hallucinating
with the application defaults file specifying red text for the first
column and black for the other two. Previously it was all one column
with seven entries. [Slimed was missing along with the six new ones
(deaf, stone, strngl, lev, fly, ride) and both types of sickness were
shown as 'FoodPois' or 'Ill' or 'FoodPois Ill' on one line.]
So now basic bot2, #if STATUS_VIA_WINDOWPORT genl_status_update, and
#if !STATUS_VIA_WINDOWPORT X11 fancy status have three different
orderings. genl_status_update has hunger and encumbrance first
because all the other status conditions are grouped together as one
bitmask item. bot2 has 'lev', 'fly', 'ride' last so that they're
the first things to be sacrificed if the string of status conditions
ends up being truncated. (genl_status_update also has those last.)
In addition to updating status conditions, I reordered the Hp, Pw, &c
section too so that it's closer to tty in organization.
Hit points Maximum HP
Power Maximum Power
Armor Class Alignment
Exp.Level Exp.Points (if 'showexp')
Gold Moves (if 'time')
Score (if 'showscore')
I didn't have SCORE_OR_BOTL set so haven't seen the last one, but
it's in the same position as it was before.
I'll push a formatting guide at some point. There may still be
outstanding changes, but please feel free to resolve those as you arrive
a them.
To the best of my knowledge, there is no changes to the actual code
content, but the formatter does have the occasional bug. If you run into
an issue, please fix it!
Suppress close to 400 warnings generated by gcc on the win/X11/*.c code,
most due to -Wwrite-strings which makes string literals implicitly have
the 'const' attribute. (Since modifying a string literal results in
undefined behavior, that is an appropriate check to have enabled, but
it can be troublesome since string literals have type 'char *' and code
that uses them that way is correct provided it avoids modifying them.)
113 warning: initialization discards qualifiers from pointer target type
127 warning: assignment discards qualifiers from pointer target type
29 warning: passing argument discards qualifiers from pointer target type
109 warning: unused parameter
12 warning: comparison between signed and unsigned
The nhStr() hack casts to 'char *', explicitly removing 'const', for
situations where it isn't feasible to make code directly honor const.
The vast marjority of uses are for the second parameter to XtSetArg(),
which is a macro that actually performs an assignment with the second
argument rather than passing it in a function. It takes values like
'XtNtop', which doesn't need to be altered (although in many places I
changed that to nhStr(XtNtop) for uniformity with the surrounding code,
and 'XtNbottom', which does need to have the extra const stripping to
avoid a warning. Go figure.
The nhUse() hack actually uses its argument in a meaningless way if the
code is compiled with FORCE_ARG_USAGE defined. When GCC_WARN is defined,
FORCE_ARG_USAGE will be enabled if it hasn't been already. Example:
/*ARGUSED*/
int foo(arg)
int arg; /* not used */
{
+ nhUse(arg);
return 0;
}
The extra line will expand to ';' when FORCE_ARG_USAGE is not defined
or too
nhUse_dummy += (unsigned)arg;
when it is. I figured direct assignment might lead to a different
warning by some compilers in a situation like
nhUse(arg);
nhUse(otherarg);
where the first assignment would be clobbered by the second, and using
bitwise operations or safer '+= (arg != 0)' would most likely generate
more non-useful code. Some tweaking might turn out to be necessary.