1. Add "engraved room floor" pchar sym (S_engroom). The symbol that
displays at the engraved part of a room (not a corridor though).
The default symbol is '`' which is currently never shown if people
have defined the boulder symbol to '0' and statues are displayed as
monster symbols. It is bright blue.
Add some stylized variations of the S_engroom symset to some of
the symsets.
2. Add "engraved corridor" pchar sym (S_engrcorr). The symbol that
displays at the engraved part of a corridor. The default symbol is
'#', and it matches the symbol for corridor from for whatever the
current symset uses. It is bright blue to match the color of the
S_engroom symbol. Using the normal corridor symbol for display
preserves the lines of the corridor so is not as visually-disruptive
as a smaller symbol would be. Explicit entries that match the S_corr
symbol have been added to the symset file.
Magic mapping and clairvoyance impacts yet to be determined.
The Guidebook updates will come later.
Add "walls of lava", basically lava which blocks vision and
require a bit more than just levitation or flight to move through.
No levels use this yet, as testing isn't thorough enough.
When hallucinating, random object selection for objects was including
the new generic objects. It was already excluding 'strange object'
by using 'rn2(NUM_OBJECTS - 1) + 1' to skip objects[0]; changing that
to be 'rn2(NUM_OBJECTS - MAXOCLASSES) + MAXOCLASSES' will skip the
first 18 objects, 'strange object' plus the 17 generic objects.
(I'm trying to convince myself that there's no off-by-1 or off-by-N
error and think I've succeeded.)
Try to fix a fuzzer issue. I wasn't able to reproduce it so am not
sure whether this actually fixes it. A mimic seemed to be mimicking
object #1 (generic ILLOBJ_CLASS object which shouldn't occur) rather
than #0 (strange object). Strange object always has dknown==1 and
generic objects should always have dknown==0 but farlook of mystery
object #1 had its dknown flag set.
An earlier fix to force non-Null oc_name when formatting objects in
order to pacify the static analyzer might have been the reason that
the problem couldn't be reproduced.
This includes a few miscellaneous changes made while unsuccessfully
hunting for the problem.
A number of C compiler suites have a math.h library that includes a yn()
function name that conflicts with NetHack's yn() macro:
"The y0(), y1(), and yn() functions are Bessel functions of the second kind,
for orders 0, 1, and n, respectively. The argument x must be positive. The
argument n should be greater than or equal to zero. If n is less than zero,
there will be a negative exponent in the result."
At one point, isaac64.h included math.h, although that has since been removed.
Some libraries used in NetHack (Qt for one) do include math.h and that required
build work-arounds to avoid the conflict.
Rename the NetHack macro from yn() to y_n() and avoid the math.h conflict
altogether, eliminating the need for that particular work-around.
Redo the way coordinate pairs are lined up for /m /O &c.
Original
| <8,9> $ gold pieces
| <10,10> * rocks
| <9,12> % newt corpse
Previous
| <8, 9> $ gold pieces
| <10,10> * rocks
| <9,12> % newt corpse
Now
| <8,9> $ gold pieces
| <10,10> * rocks
| <9,12> % newt corpse
Override right justification instead of inserting a space. It looks
better for the situation where all y values are 1 digit.
When /m or /M or /o or /O shows monsters or objects with locations
displayed as map coordinates, make those line up by their commas.
Old
| <8,9> $ gold pieces
| <10,10> * rocks
| <9,12> % newt corpse
New
| <8, 9> $ gold pieces
| <10,10> * rocks
| <9,12> % newt corpse
(The data is gathered by row so implicitly sorted by y.)
If someone is crazy enough to set ROWNO to three digits, values
will only line up by the comma when all values have row less than
100 or all are 100+. Setting COLNO to three digits isn't an issue
unless the total witdh of "<" + xxx + "," + yy ">" is more than 8
(which would push object class letter and object description one or
more extra columns to the right, messing up overall alignment but
still showing accurate data).
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
^ ^
Instead of using a compile-time macro to suppress inclusion of the
menu entry to show UNIX command-line usage in the help menu, use a
sysconf setting instead.
Default is HIDEUSAGE=0, to include the entry for command-line usage.
Set HIDEUSAGE=1 to exclude that. Does not affect 'nethack --usage'
if player actually has access to the command-line.
Write up a description of how the command line works on UNIX and put
that in new file dat/usagehlp. Add support for
|nethack --usage | --help | -? | ?
to display it and exit.
Also add a menu entry for nethack's help command to show it during
play. That can be suppressed by uncommenting new '#define HIDE_USAGE'
in config.h since it won't be useful on servers that don't give
players access to command lines.
New genl_display_file() just writes to stdout. opt_usage(), which
calls it, might need some suid/sgid handling to make sure the output
is done as the player rather than as nethack.
doc/nethack.6 is already out of date again.
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() */
Update the menu for the help command to change
"i - using the 'O' command to set options"
to
"i - using the '#optionsfull' or 'm O' command to set options"
(examples assume default key bindings but the actual help menu shows
currently bound keys; the "or 'foo'" part is omitted if #optionsfull
is bound to a key).
dat/opthelp should probably be updated to describe how doset_simple
works since that is different from normal menus and explicitly
contradicts the existing description for boolean settings being
deferred until the menu gets dismissed. Any changes need to make
sense if displayed in the context of picking '?' in #optionsfull.
Maybe a separate help file and separate entry for it in '?' menu?
Change trappers and lurkers above to remove digestion damage. They
fold themselves around rather than swallow the victim. There were
are lot of places that assumed that an engulfer which is an animal
would swallow and digest the victim. In hindsight, it might have
been simpler to take the M1_ANIMAL flag off of trappers and lurkers
above.
This adds a new digests() predicate for creatures with AT_ENGL+AD_DGST
(purple worm) and also enfolds() for AT_ENGL+AD_WRAP (both 't'-class
critters).
There are several minor fixes mixed in with this. I didn't record
them as I went along but the two I remember are
1) if poly'd into a holder and holding on to a monster, the '<' and
'>' commands refursed to work; release the held creature first
and then treat those commands as normal;
2) throwing a non-weapon while engulfed by an ochre jelly reported
"the <item> vanishes into the ochre jelly's /currents/".
This needs a lot more testing. I found and fixed multiple minor
details before my own testing burned out.
This replaces the old pushq/saveq arrays (which were used to save
the keys pressed by the user for repeating a previous command)
with a new command queue. This means there's no hard-coded limit
to the saved keys, and it can repeat extended commands which are
not bound to any key.
One of the drivers of this change was that screen coordinates require a
type that can hold values greater than 127. Parameters to the window
port routines require a large type in order to be able to have values
a fair bit larger than COLNO and ROWNO passed to them, particularly for
their use to the right of the map window.
This splits the uses of xchar into 3 different situations, and adjusts
their type and size:
xchar
|
-----------------------
| | |
coordxy xint16 xint8
coordxy: Actual x or y coordinates for various things (moved to 16-bits).
xint16: Same data size as coordxy, but for non-coordinate use (16-bits).
xint8: There are only a few use cases initially, where it was very
plain to see that the variable could remain as 8-bits, rather
than be bumped to 16-bits. There are probably more such cases
that could be changed after additional review.
Note: This first changed all xchar variables to coordxy. Some were
reviewed and got changed to xint16 or xint8 when it became apparent that
their usage was not for coordinates.
This increments EDITLEVEL in patchlevel.h
(user-side decisions really, but as it stands right now
user-side decisions/options are made and processed by the core)
add a parameter to add_menu so color can be passed
For what a key does, when operating on 'm' which produces two lines
of output, append a command to the first line so that the combination
forms a complete sentence. Also, expand on the explanattion of what
is going on in dowhatdoes().
For the description of what a keystroke does, augment 'm' (or whatever
key has been bound to #reqmenu) to replace the default description
|m prefix: request menu or modify command (#reqmenu).
with
|m movement prefix: move without autopickup and without attacking
|m non-movement prefix: request menu or modify command (#reqmenu).
The text is delivered by pline so tty will issue --More-- between the
two lines.
Switch to using a macro invocation Verbos(n, s) in place of the
flags.verbose checks.
Provide the mechanics for individual suppression of any of the
existing messages that were considered verbose.
Mechanics only - this code update does not provide any means of
setting the suppression bits.
iflags.verbose = 0
is still a master suppression of all the verbose messages.
iflags.verbose = 1
turns on the verbose messages only for those whose suppression
bit is 0 (not set).
High altars and normal temple altars had identical altarmasks, so
there was no way to distinguish between the two based on the altarmask
alone. Instead, anywhere it was necessary to determine whether an altar
was a high altar included a check whether the hero was currently the
Astral Plane or Moloch's Sanctum, and assumed any temple altar was the
high altar.
Since there's an extra, unused bit in altarmask anyway, use it to
explicitly mark high altars -- the lua level files already distinguish
between normal temple altars and so-called 'sanctum' altars anyway, so
rather than throwing away this distinction when generating the level,
keep it in the altarmask and use it in place of various u.uz checks.
I think this would require incrementing EDITLEVEL again...
instead of as fake bear traps
Use the new traps and their tiles when confused gold detection finds
trapped doors and trapped chests. (Large boxes can be trapped too;
they use the trapped chest trap and corresponding tile rather than
have their own.)
Usually these pseudo-traps go away when as soon as they are within
line of sight. (While testing, I noticed that seeing a trapped door
from outside its room rather than inside didn't behave that way.
The door was created by wizard mode wishing; I don't know whether
that was a factor.)
I also discovered that secret doors weren't being handled correctly.
They can't be trapped because of their use of both the doormask and
wall_info overlays of levl[][].flags, but I had a secret door be
falsely displayed as a trap. This fixes that.
We should have obj->tknown and rm->D_TRAPKNOWN so that the hero won't
forget about these traps after declining to attempt to untrap them.
But that's more work than I care to tackle.
When trap detection finds trapped doors and trapped chests, it shows
those as bear traps. When the hero comes within view, they revert to
normal and the detected trap is forgotten. This doesn't change that,
it is just groundwork to be able to show them distinctly. Like the
TT_BEARTRAP patch, it increments EDITLEVEL so this seemed like a good
time to put the groudwork in place.
There shouldn't be any visible changes even though internal glyph and
tile values have been renumbered after inserting two new entries.
Adding traps after S_vibrating_square was quite a hassle and suffered
though a couple of off-by-one errors that weren't trivial to find and
fix.
Extend the PR#660 change that shows whether a monster is asleep when
examined by farlook/quicklook/autodescribe to monsters that aren't
moving due to timed sleep as well as those that are asleep for an
unspecified amount of time. Unfortunately 'mfrozen' isn't specific
about why a monster can't move so the phrasing is less than ideal.
Redo how do_screen_description() handles water. Mainly by using
waterbody_name() for farlook/quicklook and autodescribe to get
hallucinatory descriptions, but it replaces some old hackery with
quite a bit of new hackery. Applies to lava and ice too. The latter
is now "frozen <foo>" when hallucinating, where <foo> has a small
chance to be "water" but will usually be something like "tea" or
"clotted blood".
For ^G, throttle the monster creation feedback. Don't say "suddenly"
and don't exclaim the message, just say "<Mon> appears." Also, use
Norep() so creating lots of similar monsters at once only gives a few
messages (just one unless varied by "next to you" vs "nearby" vs no
qualifier for farther away). And for mimics created as objects or
furniture, report the sudden appearance of new object or furniture.
The wall of water goaded me into updating waterbody_name(). It's
mostly the same, aside from being moved from mkmaze.c to pager.c and
adding "{wall of|limitless} water" instead of plain "water" for WATER
terrain. I'm not very happy with "limitless" for the Plane of Water
because limits imposed by air bubbles are all over the place. "Wall
of water" might work ok for that level.
Water on Medusa's level is now described as "shallow sea" rather than
lame "water". The two unusual pools on the Samurai home level are
described as "pond" rather than previous "water" which replaced 3.6's
ridiculous "moat". When lava is hallucinated, it is described as
"molten <substance>" (yielding silly things like "molten yoghurt"),
rather than just "<substance>" to distinguish it from hallucinated
water. 'autodescribe' doesn't use waterbody_name() though.
Move the help text for the 'O' command from the code into its own file
and allow that to be accessed from the '?' menu as well as by choosing
entry '?' in the 'O' menu.
sys/unix/Makefile.top has been updated to handle new 'optmenu', others
need to catch up. The game will still build and run without the file
but asking for options menu help won't work until they do.
Instead of returning ECMD_OK, the commands now return ECMD_CANCEL
when user declined to pick a direction or an object to act on.
Note that this can be ORed with ECMD_TIME, if the command still
took a turn.
For now this has no gameplay meaning.
Instead of returning 0 or 1, we'll now use ECMD_OK or ECMD_TURN.
These have the same meaning as the hardcoded numbers; ECMD_TURN
means the command uses a turn.
In future, could add eg. a flag denoting "user cancelled command"
or "command failed", and should clear eg. the cmdq.
Mostly this was simply replacing return values with the defines
in the extended commands, so hopefully I didn't break anything.
Replace some
(foo &&
bar)
that had crept back into the code with
(foo
&& bar)
to match the reformatting which took place before 3.6.0. There are a
couple of lines ending in '||' still present but they look intentional.
isaac64.c has some trailing '|' bit operators that could/should be
moved to the start of the next line but I didn't touch that file.
While in the affected files, I tried to shorten most overly wide lines
(the right margin is supposed to at column 78 and there are quite a
few lines which are 79 characters long, but I left most of those
rather than introduce new line splits). Also replace a handful of
tabs with spaces. I was a little surprised not find any trailing
spaces (in the dozen or so files being updated). I didn't look for
trailing arithmetic or '?'/':' operators which aught to be moved to
the start of the next line.
The walls for the mines, gehennom, knox, and sokoban had been
changed at the "tile"-level, with no awareness of the core game,
or non-tile interfaces.
- Expand the glyphs to include a set of walls for the main level
as well as each of those mentioned above.
Altars had been adjusted at the map_glyphinfo() level to substitute
some color variations on-the-fly for unaligned, chaotic, neutral,
lawful altars, and shrines. The tile interface had no awareness of
the feature.
- Expand the glyphs to include each of the altar variations that
had been implemented in the display code for tty-only. This required
the addition of four placeholder tiles in other.txt. Someone with
artistic skill will hopefully alter the additional tiles to better
reflect their intended purpose.
Explosions had unique tiles in the tile window port, and the display
code for tty tinkered with the colors, but the game had very little
awareness of the different types of explosions.
- Expand the glyphs to include each of the explosion types: dark,
noxious, muddy, wet, magical, fiery and frosty.
Pile-markers to represent a pile had been introduced at the
display-level, without little to no awareness by the core game.
- Expand the glyphs to include piletops, including objects,
bodys, and statues.
Recently male and female variations of tiles and monsters had been
had been introduced, but the mechanics had been mostly done at the
display-level through a marker flag. The window port interface then
had to increment the tile mapped to the glyph to get the female version
of the tile.
- Expand the glyphs to include the male and female versions of the
monsters, and their corresponding pet versions, ridden, detected
versions and statues of them.
Direct references to GLYPH_BODY_OFF and GLYPH_STATUE_OFF
in object_from_map() in pager.c were getting incomplete results.
- Add macros glyph_to_body_corpsenm(glyph) and
glyph_to_statue_corpsenm(glyph) macros for obtaining the corpsenm
value after passing the glyph_is_body() or glyph_is_statue() test.
Other relevant notes:
- The tile ordering in the win/share/*.txt tile files has been altered,
other.txt in particular.
- tilemap.c has had a lot of alterations to accommodate the expanded
glyphs. Output that is useful for troubleshooting will end up in
tilemappings.lst if OBTAIN_TILEMAP is defined during build.
It lists all of the glyphs and which tile it gets mapped to, and also
lists each tile and some of the references to it by various glyphs.
- An array glyphmap[MAXGLYPH] is now used. It has an entry for each
glyph, ordered by glyph, and once reset_glyphs(glyph) has been run, it
contains the mapped symindex, default color, glyphflags, and tile
index.
If USE_TILES is defined during build, the tile.c produced from the
tilemap utility populates the tileidx field of each array element with
a glyph-to-tile mapping for the glyph. Later on, when reset_glyphmap()
is run, the other fields of each element will get populated.
- The glyph-to-tile mapping is an added field available to a window
port via the glyphinfo struct passed in the documented interface. The
old glyph2tile[] array is gone. The various active window ports that
had been using glyph2tile[] have been updated to use the new interface
mechanism. Disclaimer: There may be some bug fixing or tidying
required in the window port code.
- reset_glyphmap() is called after config file options parsing
has finished, because some config file settings can impact the results
produced by reset_glyphmap().
- Everything that passes the glyph_is_cmap(glyph) test must
return a valid cmap value from glyph_to_cmap(glyph).
- An 'extern glyph_info glyphmap[MAX_GLYPH];' is inserted into the
top of only the files which need awareness of it, not inserted into
display.h. Presently, the only files that actually need to directly
reference the glyphmap[] array are display.c, o_init.c (for shuffling
the tiles), and the generated tile.c (if USE_TILES is defined).
- Added an MG_MALE glyphflag to complement the MG_FEMALE glyphflag.
- Provide an array for wall colorizations. reset_glyphmap() will draw
the colors from this array: int array wallcolors[sokoban_walls + 1];
The indices of the wallcolors array are main_walls (0), mines_walls
(1), gehennom_walls (2), knox_walls (3), and sokoban_walls (4).
In future, a config file option for adjusting the wall colors and/or
an 'O' option menu to do the same could be added. Right now, the
initializaton of the wallcolors[] array entries in display.c leaves the
walls at CLR_GRAY, matching the defsym color.
- Most of the display-level kludges for some of the on-the-fly
interface features have been removed from map_glyphinfo() as they
aren't needed any longer. These glyph expansions adhere more closely to
the original glyph mechanics of the game.
- Because the glyphs are re-ordered and expanded, an update to
editlevel will be required upon merge of these changes.
More for issue #524.
The revised append_str() was still vulnerable to unsigned subtraction
overflowing from small negative value to huge positive one, if caller
ever passed an outbuf buffer which already had more than BUFSZ
characters in it.
Also the semantics were changed. If there wasn't room for the whole
" or "+string to be appended, it used to add as much as would fit.
The revised version changed that to all-or-nothing. This changes it
back, although players will probably never know the difference.
Like /m for nearby monsters and /O for all objects, implement /^
and /" to view a list of nearby traps or all known traps. Only
lists discovered traps (or mimics immitating traps, or detected
door or chest traps iff still shown as such on map), but lists
map traps even when an object or monster at the same location is
blocking view of them.
For traps on the Water and Air levels that have been mapped, they
will only be listed when within line of sight so that this feature
can't be used to track portal location as it moves around. However,
when within line of sight it does allow the portal to be recognized
if that has become covered.
For the time being at least, take out "uninjured/barely wounded/
slightly wounded/wounded/heavily wounded/nearly dead" description
on monsters examined with ';' or '//' or '/m' and on final tombstone
and logfile entry if hero gets directly killed by a monster.
Maybe it will be revisited later....
Whitelist all the verified existing triggers:
makedefs.c: In function ‘name_file’
attrib.c: one compiler balks at a ? b : c for fmtstring
cmd.c: In function ‘extcmd_via_menu’
cmd.c: In function ‘wiz_levltyp_legend’
do.c: In function ‘goto_level’
do_name.c: In function ‘coord_desc’
dungeon.c: In function ‘overview_stats’
eat.c: one compiler balks at a ? b : c for fmtstring
end.c: one compiler balks at a ? b : c for fmtstring
engrave.c: In function ‘engr_stats’
hack:c one compiler balks at a ? b : c for fmtstring
hacklib.c: one compiler balks at a ? b : c for fmtstring
insight.c: one compiler balks at a ? b : c for fmtstring
invent.c: In function ‘let_to_name’
light.c: In function ‘light_stats’
mhitm.c: In function ‘missmm’
options.c: In function ‘handler_symset’
options.c: In function ‘basic_menu_colors’
options.c: In function ‘optfn_o_autopickup_exceptions’
options.c: In function ‘optfn_o_menu_colors’
options.c: In function ‘optfn_o_message_types’
options.c: In function ‘optfn_o_status_cond’
options.c: In function ‘optfn_o_status_hilites’
options.c: In function ‘doset’
options.c: In function ‘doset_add_menu’
options.c: In function ‘show_menu_controls’
options.c: In function ‘handle_add_list_remove’
pager.c: In function ‘do_supplemental_info’
pager.c: In function ‘dohelp’
region.c: In function ‘region_stats’
rumors.c: sscanf usage
sounds.c: In function ‘domonnoise’
spell.c: In function ‘dospellmenu’
timeout.c: In function ‘timer_stats’
topten.c: In function ‘outentry’, fscanf, sscanf, fprintf usage
windows.c: In function ‘genl_status_update’
zap.c: one compiler balks at a ? b : c for fmtstring
win/curses/cursstat.c: In function ‘curses_status_update’
win/tty/wintty.c: In function ‘tty_status_update’
win/win32/mswproc.c: In function ‘mswin_status_update’