Log game events, such as entering a new dungeon level, breaking
a conduct, or killing a unique monster, in a new "Major events"
chronicle. The entries record the turn when the event happened.
The log can be viewed with #chronicle -command, and the entries
also show up in the end-of-game dump, if that is available.
This feature is on by default, but can be disabled by
defining NO_CHRONICLE compile-time option.
This also contains "live logging", writing the events as they
happen into a single livelog-file. This is mostly useful for
public servers. The livelog is off by default, and must be
compiled in with LIVELOG, and then turned on in sysconf.
Mostly this a version of livelogging from the Hardfought server,
with some changes.
The priest/cleric quest provides unlimited wraiths and a player
(not a robot with limitless patience) posting on reddit gave up
building up his character by killing them and eating the corpses
after accumulating 40K HP and 20K En. (Or something close to that;
I can't get back to the post right now.) His character might have
been capable of surviving decapitation or bisection.
Make it very much harder to get to 5 digits of HP or En via level
gains after reaching level 30. If maxhp < 300, new gains will be
capped at 5 extra HP; 300..599, cap is 4; 600..899, cap is 3;
900..1199, cap is 2; and once 1200 is reached, further level gains
will only add 1 HP. For maxen < 200, extra En is capped at 4;
200..399, cap is 3; 400..599, cap is 2; and once 600 is reached,
further gains only add 1 En. Note: this only kicks in when gaining
levels while already at level 30.
moveloop() has been calling restore_attrib() every turn, and
restore_attrib() loops through all six characteristics every time
to check for ones that have temporary adjustments timing out. But
ATIME(characteristic) is never set anywhere and no time outs would
occur. So delete the call to restore_attrib() from moveloop().
This leaves that no-longer-called routine in place and updates it
to handle Wounded_legs properly in case it ever does get used.
Also, add a comment about "restore ability" not fixing temporarily
lost characteristics due to hunger or wounded legs. And update
unfixable_trouble_count() to check for those so that restore ability
won't say "you feel great" when it fails to fix them.
when polymorphing into "new man". Characteristic stats are shuffled
if turning into new man, but when already polymorphed those get
overridden by the old pre-polymorph characteristics, resulting in
another encumbrance check which might contradict the one that just
happened. Skip the encumbrance check done when shuffling stats so
that there's only one and it comes after all changes are finished.
Fixes#548
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’
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.
Make wearing a wet towel confer new attribute Half_gas_damage in
addition to the usual blindness. It reduces damage from being inside
a gas cloud region and from being hit by poison gas breath attack.
It also fully blocks breathing of potion vapors.
Might make the Plane of Fire easier although overcoming its blindness
with telepathy won't reveal elementals. Definitely has the potential
to make blind-from-birth conduct easier which wasn't the intent and
probably isn't significant.
I went through the places that set context.botl/botlx in src/a*.c to
see whether I could find any unnecessary status updates. I didn't
find anything interesting, mostly some minor sequencing issues plus
a couple of redundant sets (call foo() which includes setting botl,
then explicitly set botl after it returns). If you issue pline first
and then set context.botl, bottom lines won't be updated until the
next message or next pass through moveloop. If you order those the
other way around, status will be updated as the message describing
the reason for the update is being delivered.
A hero run by the fuzzer that has characteristics plummet to 3 and
then sometimes hang around there instead of being recovered by restore
ability is happening because loss that tries to reduce the base value
below 3 lowers the max (peak) value instead, and once that also gets
down to 3, restore ability is no longer able to do anything with it.
This changes an attempt to reduce a characteristic by N points below 3
to reduce it by rn2(N + 1) instead. That's N/2 on average and a 50%
chance to be 0 when N is 1, so the peak value reached doesn't plummet
to 3 quite to quickly. It can still drop to that though.
There is a pull request dealing with simplifying attribute handling
and part of it affects the code being changed here, but the bit of
simplification included in this patch doesn't use it.
It was possible to arbitrarily boost strength (up to its race-specific
limit) by wearing a ring of sustain ability, becoming weak from hunger
(but not actually losing strength due to Fixed_abil), removing the ring,
eating enough to stop being Weak, then repeat as desired. I think you
could substitute polymorph for wearing ring, and rehumanize for removing
ring and get similar results, although that would be more tedious.
My first attempt to fix this was a lot more complicated. This one puts
the temporary strength loss in ATEMP(A_STR) where it carries over from
normal form to polymophed form and back. Fixed_abil doesn't prevent the
loss any more, nor its recovery.
One side-effect of the change is that the possibility of dying when
becoming weak from hunger (if Str gets down to 3, further attempts to
lower it take away HP instead of Str) no longer exists. Using ATEMP()
instead of directly manipulating ABASE() means that current strength is
less but underlying base strength does not actually drop any more.
Report was for losing strength when sitting on a throne, but the
message issue was more general than that. Character was wearing
gauntlets of power, so no visible change in strength took place,
but player was told "you're already as weak as you can get" (because
the attempt to reduce strength didn't change current strength;
however, it did change the hero's underlying strength, observable
once the gloves were removed).
There was a beta report last January that was related: in that case
the player thought that gauntlets of power were preventing blessed
potion of gain ability from raising strength, but it was actually
giving a misleading message claiming that strength was already as
high as it could get.
Fix: vary the message when something prevents an attribute change
from being noticeable.
For "the poison was deadly" against hero, hit points were set to -1
(which gets displayed as 0 when shown) but the status lines weren't
being updated, so stale positive HP value was visible during final
disclosure.
This is from the pull request for the assertion failure fix. It
did not mention how to reproduce the assertion failure, just added
casts to a bunch of isspace/isprint/tolower calls that didn't already
have such.
I removed an obsolete change for win/tty/topl.c and changed the
win/win32/mswproc.c code to avoid using an expression with side-effects
(*colorstring++) in calls to tolower() in case someone overrides that
with a macro which evaluates its argument more than once as some pre-
ANSI ones used to do. Not tested, might have typos....
sys/wince/*.c still needs similar casts.
Fast and Very_fast share the same property index, but from_what()
didn't handle that. Enlightenment for a Very_fast hero--which
can only happen via worn equipment (speed boots) or timed effect
(potion of speed or spell of haste self)--would be erroneously
described as "very fast innately" for roles who get intrinsic
speed at level 1, or "very fast because of experience" when high
enough level for roles who get intrinsic speed later.
Another OS upgrade (OSX 10.6.8 -> 10.8.5) with different toolset,
another change in compiler behavior. Earlier 'gcc -Wwrite-strings'
didn't complain about passing string literals as 'char *' paremeters
if there was no prototype in scope. This one found one or two of
those in options.c and several in makedefs.c (fix coming soon in a
separate commit...). This adds some missing prototypes and reorders
the existing ones to match their order within the file. There were
also several functions which were declared static in their advance
declarations but not in the definitions, which can be confusing when
reading the source.
A change earlier today resulted in infravision being described by
enlightenment (wizard mode only) as "from current creature form" when
it was actually due to hero's non-human race. Now it'll be "innately".
Duplicate of another recent report as far as drain resistance from
Excalibur/Stormbringer/Staff of Aesculapius not being shown by
enlightenment goes, but this one mentioned that it also wasn't being
shown for lycanthropy. Being inflicted by that does confers level-
drain resistance. were_change() wasn't calling set_uasmon() since
it isn't changing youmonst.data, but set_uasmon() is were intrinsics
conferred by creature form are set up. So call it when changing
were-form. Direct access to u.ulycn wasn't calling it either, so add
a new routine to assign the value to that instead doing so directly.
Enlightenment/attribute disclosure while in wizard mode shows reasons
for some of the intrinsics. This adds some more of those: innately
due to polymorph for lots of things, and innately due to role for
knight's jumping. (Drain_resistance from equipped item came with the
'resistance from Excalibur' patch.)
With DEBUG suppressed, I started getting
16 warning: empty body in an if-statement
and 2 warning: empty body in an else-statement
from gcc.
Using braces for an empty block instead of just ';' avoids the warning:
if (foo)
debugpline("foo");
is bad,
if (bar) {
debugpline("bar");
}
is good. ;-)
The changes to lint.h are just precautionary.
modified:
include/lint.h
src/attrib.c, bones.c, dbridge.c, dig.c, eat.c,
makemon.c, mkmaze.c, mon.c, sp_lev.c
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!
For those pro players who really want to try their hand
at that zen samurai, without needing to reroll thousands
of times to start with blindfold. Nudist starts without
any armor, and keeps tabs whether you wore any during
the game, for even more bragging rights.
Also makes the Book of the Dead readable even while
blind, for obvious reasons.
* Replace variadic debugpline() with fixed argument debugpline0(str),
debugpline1(fmt,arg), and so on so that C99 support isn't required;
* showdebug() becomes a function rather than a macro and handles a
bit more;
* two debugpline() calls in light.c have been changed to impossible();
* DEBUGFILES macro (in sys.c) can substitute for SYSCF's DEBUGFILES
setting in !SYSCF configuration (I hope that's temporary).
Move debugging output into couple preprocessor defines, which
are no-op without DEBUG. To show debugging output from a
certain source files, use sysconf:
DEBUGFILES=dungeon.c questpgr.c
Also fix couple debug lines which did not compile.
This also includes fixes due to Derek Ray to depugpline to work better
on other platforms.