new .h files: hacklib.h selvar.h stairs.h
new .c files: calendar.c, getpos.c, report.c, selvar.c, stairs.c,
strutil.c, wizcmds.c
cleanup of hacklib.c and mdlib.c
hacklib contains functions that do not have to link with the core
relocate wiz commands from cmd.c to wizcmds.c
relocate CRASHREPORT stuff to report.c
relocate getpos stuff from do_name.c to getpos.c
remove temporary struct definition from extern.h
cross-compile PRE-section split into cross-pre1.370 and cross-pre2.370
Windows sys/windows/Makefile.nmake and sys/windows/Makefile.mingw32 and
visual studio project file updates
Unix sys/unix/Makefile.src, sys/unix/Makefile.utl
populate selvar.c and selvar.h
build on MS-DOS (not cross-compile) Makefile updates
for sys/msdos/Makefile.GCC (untested)
vms updates for above (untested)
- add nhl_pcall_handle() to wrap all nhl_pcall calls that didn't check
return value and either panic() or impossible()
- add --loglua (unix only) to dump Lua memory and steps info to livelog
- remove old logging
- set memory and step limits on all Lua VMs
Update several places where lazy lastseentyp[] might be an issue.
I think it isn't updated in a timely fashion when newsym() shows
a spot covered by an object or trap, but didn't manage to find any
cases where that caused a problem. This is more in the nature of
a precaution.
Callgrind showed recalc_mapseen was three times more expensive (in terms
of instructions read) than anything else in our codebase. It was being
called in every vision change, re-evaluating the last seen map terrain
type for every map location in sight.
Remove updating the lastseen info in the vision code, and make a small
change so newsym() uses update_lastseentyp.
From my short tests, this seems to work correctly ...
u_on_newpos() bit: player can't see the map while swallowed so hero
can't see objects on the map, hence shouldn't gain more info about
any generic objects if engulfer moves closer to some.
At the moment engulfer movement is manipulating <u.ux,u.uy> directly
rather than going through u_on_newpos(), but that's about to change.
Otherwise a clipped map doesn't get updated properly until the hero
is eventually expelled.
When using the 'm' prefix with #overview to get a menu of visited
levels and then picking one to annotate, replace the generic prompt
"what do you want to call this dungeon level?" with more specific
location information. Location details are visible while within the
menu but as soon as you choose something that goes away.
Sometimes I annotate a level with a note like "watch out, chameleon
below", which is useful to remind myself of some danger or thing to
remember when returning to the level -- but if saving and restoring on
the level itself there's no reminder of that annotation. If you restore
on a level with an annotation, print it as part of the "welcome back"
message.
Simplify suppression of highlighting for menu header lines during end
of game disclosure. Didn't actually affect as many things as I was
expecting.
Plus a bit left out of the optfn_dogname() parsing commit.
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.
Reported by entrez: it was possible for #overview to show a line of
just "." if a temple was known and its altar was unknown and no other
features such as thrones or fountains were known on the level.
It now lists "M temples and N altars" when both are present and the
case that yielded "." becomes "a temple". That's an improvement but
there might be edge cases it gets wrong. A listing of "a temple and
an altar" is ambiguous because there isn't any way to tell whether the
altar it mentions is inside the temple. That seems acceptable to me.
I think it should include more alignment information about temples and
altars, instead of just adding "to <your god>" when all known altars
are of hero's alignment, but this doesn't attempt to address that.
Adds a new lua command
des.exclusion({ type = "teleport", region = { x1,y1, x2,y2 } });
which allows defining "exclusion zones" in the level, areas where
random teleports (or falling into the level) will never place the hero.
Does not prevent targeted teleportation into the area.
Breaks saves and bones.
When returning to play from within the tutorial, remove the level files
similar to how they're discarded for the rest of the dungeon when going
into the endgame. It turned out to be a bit messier than anticipated.
The dungeon.c bit is sufficient for #overview, which now hides regular
level 1 while in the tutorial and hides all tutorial levels once exited.
Those will still appear in end-of-game disclosure.
The FIXME comment noted that builds_up would return an incorrect false
value for a dungeon branch that builds upwards but is only 1 level, but
that this is a latent problem because no such branch exists in NetHack.
Such a branch does exist in xNetHack, and it causes the debug fuzzer to
crash ("mon_arrive: no corresponding portal" because it can't find the
correct-direction stairs), so I figured I might as well fix it upstream.
Reported by Noisytoot: going from level tut-1 to tut-2 returned the
hero's starting equipment too soon, and exiting the tutorial from
tut-2 let the hero keep any equipment acquired within the tutorial.
Entering and leaving the tutorial was being handled by lua code in
the level description of tut-1 and adding a second level messed that
up. I didn't see any way of handing that with level-specific lua
code so I made it become the core's responsibility. gotolevel()
knows when the hero is moving from one dungeon branch to another so
it can recognize entry to or exit from the tutorial easily.
While fixing this, prevent #invoke of the Eye of the Aethiopica from
offering the tutorial as a candidate destination (was feasible if it
had been entered at start of game).
Not fixed: levels visited in the tutorial become part of #overview.
Show location as "Tutorial:1" instead of "Dlvl:1" on status lines.
Only tested with tty; some interfaces handle location themselves and
may need their own fixup for this.
Fixes#1046
Engraving in an empty doorway and then using locking magic to create
a door there resulted in an impossible warning: "engraving sanity:
illegal surface (23)" if the 'sanity_check' option was On (wizard
mode only). Engraving in an open doorway and then simply closing
the existing door produced the same effect.
Accept engravings at closed doors. Presumably hero will be using
Passes_walls to attempt that so treat closed doors same as open ones.
Update the engraving sanity check to deal with that.
Bonus fix: engraving sanity checking stopped after the first problem
instead of checking every engraving. Have it continue instead.
Not fixed: vault wall repair and temporary corridor removal does
not delete engravings and can trigger the illegal surface warning if
player engraves before the repairs. I didn't test shop wall repair
but it doesn't have any engr references so probably has the same bug.
The revised #overview (displaying info in a menu instead of text
window), works as intended for tty and curses, during play and also
during end of game disclosure.
For X11 it worked during play but during disclosure it issued a
call to impossible() for every line of overview output and there
was no overview shown. ("add_menu: called before start_menu",
sent to stdout where the player may not have a chance to see it.)
For Qt things were worse, working during play but with indentation
that isn't what is intended, and during disclosure it crashed in
add_menu().
This avoids the impossible and the crash, by changing how the core
treats the menu rather than by updating how FOO_add_menu() deals
with the offending previous usage.
I suspect that to fix the Qt indentation, #overview might need to
be changed to behave like #attributes: use a menu during play but
a text window during disclosure. It has a hack for text windows
to switch from the default font to a fixed-width one if any line
in the text contains four consecutive spaces. Either menu windows
aren't doing the same thing, or the two-column layout they use to
render their text is messing that up. (I haven't looked.)
Require the 'm' prefix to treat #overview as a menu with selectable
entries. During end-of-game disclosure it shows every level that was
visited, but during play it only shows levels which have annotations
(typically automatically generated ones). The menu wasn't offering
any chance to add an annotation to levels without such, so force
'm #overview' to show every visited level. Continue to avoid that
(and also avoid the clutter introduced by menu entry selector letters)
for normal #overview.
relocate surface(), ceiling(), and avoid_ceiling() to dungeon.c
adjacent to has_ceiling() etc.
astral and fire, like airlevel and waterlevel return FALSE
for has_ceiling()
if a caller does happen to call ceiling() on fire level,
return "flames above"
if a caller does happen to call ceiling() on quest level,
return a more-generic "expanse above", instead of the
word "ceiling"
add "stairs" return to surface()
remove recent update to engrave.c to special-case "stairs"
since surface() will return that now
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.
Add 17 fake objects to objects[], one for each object class. All
specific color as gray. They're grouped at the start--actually near
the start since "strange object" is still objects[0]--rather than
being among the objects for each class. init_object() knows to start
at [MAXOCLASSES] instead of [0]; other code that loops through every
object might need adjusting.
For potions, non-stone gems, and non-novel/non-Book_of_the_Dead
spellbooks that don't have obj->dknown set, display the corresponding
generic object rather the object itself. Fixes the longstanding bug
of seeing color for not-yet-seen objects whose primary distinguishing
characteristic is their color. Walking next to a generic object
while able to see its spot will set dknown and redraw as specific.
It's slightly disconcerting to have objects change as you reach them;
I hope it's just a matter of becoming used to that. (If there is any
code still changing the hero's location manually instead of using
u_on_newpos(), it should be changed to use that routine.)
Most of the new tiles are just a big rendering of punctuation
characters. The potion, gem, and spellbook ones could be cloned from
a specific object in their class and then have the color removed. I
started out that way but wasn't happy with the result. I'm not
artisticly inclined; hopefully someone else will do better. Each of
them is preceded by a comment beginning with "#_"; the underscore
isn't required, just being used to make the comments stand out a bit.
Invalidates existing save and bones files.
Just zero out the allocated memory.
Explicitly setting struct field values isn't enough, because field alignment
means there can be several unused bytes which are written to savefile.
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
^ ^
Although gcc specifies support for declaring a function as
noreturn after the function name and parameters, other compilers
do so via an attribute at the start of the declaration. Add some
macro support for the attribute-at-the-beginning method:
o MS Visual Studio compiler
o Upcoming C23 standard (untested at this point)
Condense the setup of PCHAR/PCHAR2 and OBJCLASS/OBJCLASS2 (last one
renamed from OBJCLASS7) so that it's easier to see the variations
at once on an ordinary size terminal/window. Revise some of the
indentation and other spacing, also to try to enhance readability
a little.
Unrelated: remove a trailing space that crept in with a recent pull
request.
Permit levelport by name to "delphi". That is what the Oracle calls the
level (or at least her room) in-game, so it seems like a natural guess
for the name of the level.