It's redundant with g.moves, so there is no more need for it.
Way, way back, it looks like g.moves and g.monstermoves can and did
desync, where g.moves would track the amount of moves the player had
gotten (and would therefore increase faster if the player were hasted)
and g.monstermoves would track the amount of monster move cycles, aka
turns. But this has not been the case for a long time, and they both
increment together in the same location in allmain.c. There are no
longer any cases where they will not be the same value.
This is a save-breaking change because it changes struct
instance_globals, but I have not updated the editlevel in this commit.
When discussing the recent commit that removed makedefs -o from the
build process, nhmall pointed out that a sanity check ensuring all
objects within one class add up to 1000 probability had been removed as
well. This requirement was a perennial thorn in the side for anyone
doing anything that touches object probabilities, because allocating
probability to something meant deciding what to take it away from,
without a good way to evenly distribute that across all the other
members of the object class.
I had gotten around this in xNetHack by removing the sanity check and
making mkobj() total up the probability within an object class and then
using that instead of 1000. This commit takes a similar approach, but
instead of inefficiently recalculating the sum every time mkobj() is
called, it instead computes it at the start of the game or when
restoring the save file and stores it in a global variable.
This fixes a slight bias problem with rings - they are all supposed to
be of equal probability, but there are 28 of them and 1000 is not evenly
divisible by that, so the old formula made the later rings slightly more
likely. Now instead of a 35/1000 or 36/1000 chance, they are all
uniformly 1/28. (Internally they have a oc_prob of 1 now, not 0).
Gems are also weird, because their oc_prob values change every level.
This ought to have still worked without a change, because the arcane
formula for assigning the probabilities would still end up with them
adding to 1000. But I added in code to reset the total gem probability
anyway; this may help make the formula less arcane in the future.
There is still a sanity check against object classes having a nonzero
number of objects but zero total probability, in which case an
impossible will be thrown and every member of the class will be given
equal probability. I also downgraded the "probtype error" panic in
mkobj() to an impossible because it has a reasonable failure case -
return the first item in that class.
This evolves and hopefully eases the game-build requirements by
removing game-compile dependencies on any header files generated
by the makedefs utility, including:
date.h dependency and its inclusion is removed and comparable functionality
is produced at runtime via new file src/date.c.
pm.h dependency and its inclusion is removed and comparable functionality is
produced by moving the monster definitions from monst.c into new header
file called monsters.h and altering them slightly. The former pm.h header
file #define PM_ values are now replaced with appropriate emitted enum
entries during the compiler preprocessing.
onames.h dependency and its inclusion is removed and comparable functionality
is produced by moving the object definitions from objects.c into new header
file called objects.h and altering them slightly. The former onames.h header
file #define values are now replaced with appropriate emitted enum entries
during the compiler preprocessing.
artilist.h has been slightly altered, and the former onames.h artifact-related
header file #define ART_ values are now replaced with appropriate emitted enum
entries during the compiler preprocessing.
makedefs can still produce date.h (makedefs -v), pm.h (makedefs -p), and
onames.h (makedefs -o) for reference purposes. They won't be used during
the compiler.
The other uses for makedefs remain. They are used to prepare external
file content that the game utilizes, not prerequisite code for the
compile:
makedefs -d (database)
makedefs -r (rumors)
makedefs -h (oracles)
makedefs -s (epitaphs, engravings, bogusmons)
date.c
Pull the code for date/time stamping from mdlib.c into date.c.
Set date.o to be dependent on source files, header files, and .o files
so that date.o is rebuilt from date.c when any of those changes, thus
ensuring an accurate date/time stamp. It also includes git sha
functionality formerly done by makedefs writing #define directives
into include/date.h. For unix it passes the git info on
the compile line for date.c (via sys/unix/hints/linux.2020, macOS.2020)
nethack --dumpenums (optional, but on by default)
Allow developer to obtain some internal enum values from NetHack
without having to resort to an external utility such as
makedefs.
Uncomment #define NODUMPENUMS in config.h to disable this.
The updates to sys/windows/Makefile.gcc have not been tested yet.
Put the flag that parse() uses to tell readchar() that the next
keystroke is a command into the program_state structure instead of
having it be a static variable in cmd.c. Conceivably an interface
could make use of it, and even if none do, it is program state....
More #558
Retravel travels to the previously selected destination.
Also changes the travel-via-mouse to execute the extended command
instead of faking a special key.
Put the rush and run movement keys into g.Cmd instead of bit twiddling
the normal walk keys in multiple places to get the run and rush keys.
Allow meta keys in getpos. Use the normal running keys to fast-move
in getpos, instead of explicit HJKL - I polled couple places online,
and number_pad users did not use the HJKL keys in getpos.
Make meta keys work even after a prefix key.
Allows the fire-command to autowield a launcher; it will now
do either swapweapon or wield an appropriate launcher, if you
have ammo quivered.
This assistance can be turned off with the fireassist boolean option.
Adds a rudimentary command queue, which allows the code to add keys
or extended commands into the queue, and they're executed as if
the user did them. Time passes normally when doing the queue,
and the queue will get cleared if hero is interrupted.
Adds possible callbacks for "start_new_game", "restore_old_game",
"moveloop_turn", and "game_exit" which when defined, will be called
from core code at the appropriate time.
Adds lua hooks for dump_fmtstr (only if DUMPLOG), dnum_name, u.moves,
u.uhave_amulet, and u.depth.
If the killer and the paralyzer are the same monster, truncate
that to "Killed by a foo, while paralyzed". When not the same,
spell out the paralyzer's monster type instead of using generic
"monster". "Killed by a fox, while paralyzed by a ghoul", or
"Killed by a ghoul, while paralyzed by a ghoul" *if* they were
two different ghouls.
'final_fpos' shouldn't have been moved to the 'g' struct. Even if
a game went all the way through topten and was restarted as a new
game that also went all the way through topten, 'final_fpos' would
get a new value rather than being messed up by a stale old one.
Change Trollsbane versus troll corpse revival: instead of revival
failing if Trollsbane is wielded at time of revival attempt, mark
the corpse no-revive if killed by Trollsbane (whether by the hero
or a monster).
If a no-revive corpse is within view when time to revive occurs,
give "the troll corpse twitches feebly" even when the hero isn't
responsible. That used to only apply if the hero zapped the
corpse with undead turning, which would have become inoperative
because now being zapped by undead turning clears the no-revive
flag and revives as normal. In other words, undead turning magic
overrides killed-by-Trollsbane or non-ice troll having been in an
ice box.
further adjustments to the window port interface to pass a pointer
to a glyph_info struct which describes not just the glyph number
itself, but also the ttychar, the color, the glyphflags, and the
symset index.
This affects two existing window port calls that get passed glyphs
and does the parameter consistently for both of them using the
glyph_info struct pointer:
print_glyph()
add_menu().
The recently added glyphmod parameter is now unnecessary and has been
removed.
ensure that monster female name variation ends up as a female during ^G
arbitrate when there is a conflict between gender term (male or female) and
a gender-tied monster name (cavewoman) during ^G; gender term wins
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.
number_pad==1 adds
'5' => 'G'
M-5 => 'g'
'0' => 'i'
number_pad==2 swaps 5 and M-5 and adds M-0
'5' => 'g'
M-5 => 'G'
'0' => 'i'
M-0 => 'I'
M-5 and M-0 were missing from the bound key handling; they still
used hardcoded digits even though the actions for plain 5 and
plain 0 can be bound to other keys these days. This implements
the M-5 variation as NHKF_RUSH2. Changing numpad from 1 to 2
or vice versa will swap the NHKF_RUN2 and NHKF_RUSH2 actions
regardless of what keys they're assigned to. I haven't done
anything for unimplemented NHKF_DOINV2 though (and am not
planning to in case someone else wants to jump in...).
This also fixes the description of the 'I' command. The extended
command name for that still misleadingly refers to "type" rather
than "class" though.
I started activating new program_state.saving and discovered that
saving of ball and chain could access freed memory. The change
for the former and fix for the latter are mixed together here (but
easily distinguishable).
The saving flag inhibits status updating and perm_invent updating,
also map updating that goes through flush_screen(). That should
fix the exception triggered after an impossible warning was issued
during a save operation. impossible() goes through pline() which
tries to bring the screen up to date before issuing a message.
During save, data for that update can be in an inconsistent state.
The code to save ball and/or chain when not on floor or in invent
(I think swallowed is the only expected case) was examining the
memory pointed to by uball and uchain even if saving the level had
just freed floor objects and saving invent had just freed carried
objects. So for the usual cases, stale pointer values for uball
and uchain would be present and checking their obj->where field
was not reliable.
Move the core's global restoring flag (not the same as main()'s
local resuming flag) to a more logical place. Add a saving flag
in the process, but it isn't being set or cleared anywhere yet.
(Once in use it will probably fix the exception during save that
was just reported, but before that it would be useful to figure
out what specifically caused the event.)
The program_state struct really ought to be standalone rather
than part of struct g but I haven't made that change.
Removing an unused variable for wishing and some reformatting
that whent along with it got mixed in. Removes some trailing
whitespace in sfstruct.c too.
Only lightly tested...
If we ever want huge maps with COLNO or ROWNO larger than signed char,
this will at least allow the game to compile and start when typedef'ing
xchar to int. Trying to use huge maps exposes more bugs.
Use a linked list to store stair and ladder information, instead
of having fixed up/down stairs/ladders and a single "special" (branch)
stair.
Breaks saves and bones.
Adds information to migrating objects and monsters for the dungeon
and level where they are migrating from.
When a zombie (or lich) kills a monster in melee without a weapon,
the monster can rise few turns later as a zombie.
The only creatures that can be zombified are ones that actually have
a zombie counterpart monster. A zombie cannot turn a jackal into
a zombie, for instance. But it could turn a shopkeeper into a human
zombie, or a dwarf king into a dwarf zombie.
Zombies will fight with monsters that can be turned into zombies.
Originally this was a SliceHack feature, but this is based on xNetHack
version of it, with some modifications.
Since teleporation gives a "you matrialize" message even when
arriving close by, the old behavior of not learning a scroll of
teleportation when you land quite close to your original spot
no longer made sense. Always [almost] discover teleport scroll
when reading it.
Also adds one-shot teleport control when reading a blessed scroll
of teleportation. I changed that to be prevented when hero is
stunned, same as with full-fledged teleport control.
I reworded or reformatted several of the comments. And removed
the EDITLEVEL increment in patchlevel.h; save and bones file
contents are not affected.
I've also added an unrelated comment about reading mechanics to
doread().
Closes#386
Similar to how the pick-an-attribute menu for menu colors and
status highlights shows the attribute names using the attribute
so that you can see how it looks (or whether it is supported),
have the pick-a-color menu show the color names in the
corresponding color. Does so by temporarily removing any
user-specified menu colors and setting up another list of such
for matching color names.
Forces the 'menucolors' option On while the pick-a-color menu is
in use, then restores the previous setting along with the user's
menu colorings. Might need some way to avoid setting that for a
configuration where colors don't work.
When a mind flayer scores a hit against a headless target (or worm's
tail), there's a message that says that the attack hits and that the
target is unharmed. Since an ordinary mind flayer has 3 such attacks
per turn and a master mind flayer has 5, it can become excessively
verbose.
This doesn't eliminate the attacks until a hit fails to do harm, so
ordinary misses still get repeated if they happen first. Once a
successful hit doesn't do anything, any remaining AT_TENT+AD_DRIN
attacks are silently skipped. That way feedback isn't as verbose
and mind flayers don't seem to be quite so stupid about using their
tentacles when those won't work. Unfortunately they need to relearn
the lesson every turn they attack.
A check into github issue 364 confirmed that
ba6edbe5dc
had incorrectly updated the bwrite sizeof entry for sysflags.
The SYSFLAGS and MFLOPPY code is all in the outdated part of the tree, so just
remove it rather than re-correct it.
Closes#364Closes#207
A thieving monster could be killed while the hero was busy taking
off armor which needs multiple turns (normally a suit) and if that
happened on the same turn as the take-off finished, the warning
"stealarm(): dead monster stealing" was issued. Cited case was
having the thief be killed by a stinking cloud but it could happen
if the death was caused by a pet or by some other monster trying
to attack the hero. If the thief died sooner, the situation was
silently ignored. So this could have been fixed by just getting
rid of the impossible() feedback.
'stealmid' and 'stealoid' should have been static in steal.c rather
than global and as such should have been moved into 'struct g'.
This moves them there and then takes advantage of having access to
'stealmid' outside of steal.c. That's just a minor optimization
since m_detach() could call new thiefdead() unconditionally and the
latter could check whether the dead monster matches 'stealmid'.
Fixes#354
Fix for $USER, $LOGNAME, getlogin() values that have dashes in them:
keep dash and whatever follows as part of the name instead of stripping
it off for role/race/gender/alignment.
Before:
% USER=test-bar-fem ./nethack
|Shall I pick your female Barbarian's race and alignment for you?
and character ended up named 'test'.
After:
% USER=test-bar-fem ./nethack
|Shall I pick character's race, role, gender and alignment for you?
and character ends up named 'test-bar-fem'. However,
% ./nethack -u test-bar-fem
still behaves like the 'before' case.
|Shall I pick your female Barbarian's race and alignment for you?
Dash handling is only changed when the dash comes from user name (or
from envionment overriding user name), not from direct player input
or run-time config file.
and out of save files so restore doesn't need to clear stale data.
Behavior should be the same as before, except that when entering
the endgame branch and discarding the main dungeon and its other
branches, lua theme context is now discarded for those too.
The bases[] array allows finding the index of the first object in
a particular class. Extend it so that bases[class + 1] - 1 is a
reliable way to find the last object in any class. The array had
to be extended by one so that the last class has a [class+1] entry
available, and object initialization now makes sure that classes
within objects[] are in ascending order so that [class+1] always
holds a higher index than [class].
Allows creating shaped or themed rooms for the Dungeons of Doom
via lua script.
Invalidates bones and saves.
Makefiles updated for unix/linux by adding themerms.lua, but other
OSes need to have that added.
When rest and search refuse to operate because a hostile monster is
adjacent, include a reminder of how to force them to operate. Every
time if 'cmdassist' is On, or just once until after some subsequent
try actually does something.
This new rest and search behavior probably needs to be optional and
default to the old behavior. It isn't uncommon to deliberately rest
while adjacent to a hostile monster if also adjacent to a peaceful
one and trying to wait for Stun or Confusion to time out, or maybe
search while next to such a monster hoping to find a secret door to
run away through. A count prefix won't work and needing an extra
keystroke each time is going to be an annoyance.
Get rid of a couple of variables that were file scope and then
incorporated into 'g'. This should prevent the situation where
attacking a shade gave bogus feedback about glorkum although I
never did reproduce that.
This eliminates g.otmp and g.dieroll but leaves a couple of others.
g.vis really should go away....
combine boolean and compound options into a single allopt[] array for
processing in options.c.
move the definitions of the options into new include/optlist.h file which
uses a set of macros to define them appropriately.
during compile of options.c each option described in include/optlist.h:
1. automatically results in a function prototype for an optfn called
optfn_xxxx (xxxx is the option name).
2. automatically results in an opt_xxxx enum value for referencing
its index throughout options.c (xxxx is the option name).
3. is used to initialize an element of the allopt[] array at index
opt_xxxx (xxxx is the option name) based on the settings in the
NHOPTB, NHOPTC, NHOPTP macros. Those macros only live during the
compilation of include/optlist.h.
each optfn_xxxx() function can be called with a req id of: do_init, do_set,
get_val or do_handler.
req do_init is called from options_init, and if initialization or memory
allocation or other initialization for that particular option is needed,
it can be done in response to the init req.
req do_set is called from parseoptions() for each option it encounters
and the optfn_xxxx() function is expected to react and set the option
based on the string values that parseoptions() passes to it.
req get_val expects each optfn_xxxx() function to write the current
option value into the buffer it is passed.
req do_handler is called during doset() operations in response to player
selections most likely from the 'O' option-setting menu, but only if the
option is identified as having do_handler support in the allopts[]
'has_handler' boolean flag. Not every optfn_xxxx() does.
function special_handling() is eliminated. It's code has been redistributed
to individual handler functions for the option or purpose that they serve.
moved reglyph_darkroom() function from options.c to display.c
Eliminate the cache that was supporting rndmonst() and pick a random
monster in a single pass through mons[] via "weighted reservoir
sampling", a term I'm not familiar with.
It had a couple of bugs: if the first monster examined happened to
be given a weighting of 0, rn2() would divide by 0. I didn't try
to figure out how to trigger that. But the second one was easy to
trigger: if all eligible monsters were extinct or genocided, it
would issue a warning even though the situation isn't impossible.
Aside from fixing those, the rest is mostly as-is. I included a bit
of formatting in decl.c, moved some declarations to not require C99,
and changed a couple of macros to not hide and duplicate a call to
level_difficulty().
Fixes#286
When a special level is created, there's a chance it gets flipped
horizontally and/or vertically.
Add new level flags "noflip", "noflipx", and "noflipy" to prevent
flipping the level. Add a wiz-mode command #wizlevelflip to test
the flipping on current level - although this doesn't flip everything,
as level flipping is meant to happen during level creation.
This adds a pair of new glyphs: GLYPH_UNEXPLORED and GLYPH_NOTHING
GLYPH_UNEXPLORED is meant to be the glyph for areas of the map that
haven't been explored yet.
GLYPH_NOTHING is a glyph that represents that which cannot be seen,
for instance the dark part of a room when the dark_room option is
not set. Since the symbol for stone can now be overridden to
a players choice, it no longer made sense using S_stone for the
dark areas of the room with dark_room off. This allows the same
intended result even if S_stone symbol is mapped to something visible.
GLYPH_UNEXPLORED is what areas of the map get initialized to now
instead of STONE.
This adds a pair of new symbols: S_unexplored and S_nothing.
S_nothing is meant to be left as an unseen character (space) in
order to achieve the intended effect on the display.
S_unexplored is the symbol that is mapped to GLYPH_UNEXPLORED, and
is a distinct symbol from S_stone, even if they are set to the same
character. They don't have to be set to the same character.
Hopefully there are minimal bugs, but it is a deviation from a
fairly long-standing approach so there could be some unintended
glitches that will need repair.
recover had deviated somewhat from NetHack in its
file expectations:
1) A couple of 3.7 fields needed to be accommodated.
2) hard-coded file size values had deviated.
The file sizes are now in an added header file named "filesize.h",
which is included at the bottom of config.h.
There will likely be another commit to write the filename size ahead
of the file name so that the precise number of characters can be read,
but since that will break existing saves, it can go in along with another
save-breaking commit.
This commit doesn't not alter savefiles written by nethack so does not
require an editlevel bump. It does alter the read-in expectation in
recover to match the game and this get recover working again.