I was working on this at the time 3.6.0 was released and set it aside
until later. Later has finally arrived. Redo the Blind, Blinded,
Blindfolded,&c macros to make more complete use of intrinsic property
handling. Blinded was being treated as a number which could be added
to or subtracted from; now that has to be done via TIMEOUT mask
because it has FROMOUTSIDE (OPTIONS:blind) and FROMFORM (poly'd into
!haseyes() form) bits included. Object definitions for blindfold and
towel now specify the BLINDED property; overriding blindness via the
Eyes of the Overworld is accomplished via props[BLINDED].blocked.
Code generated for the scores of Blind and !Blind tests throughout
the program should be smaller.
One bug that has been fixed is that putting on the Eyes of the
Overworld cured permanent blindness (from OPTIONS:blind). The
u.uroleplay.blind flag was cleared and stayed so after taking them
off. Putting the Eyes on still breaks blind-from-birth conduct but
now blindness will resume when they are removed.
This was untested at the time it was set aside and is only lightly
tested now. A large number of the changes here are just to switch
from Blinded to BlindedTimeout for current timed value and to call
set_itimeout() for setting a new value.
This is fairly ridiculous but it prevents the bogus complaints
when compiling eat.c with 'gcc -fanalyzer' about some fields in
gc.context.victual being used without having been initialized.
There's bound to be a better way to handle this and I'm curious
whether it will work with the 'onefile' testing.
scan-build from llvm-14 (clang) doesn't complain about bite() or
maybe_finished_meal() so this is unlikely to fix those. But this
does fix one bogus complaint it has for doeat(). Testing whether
the result from touchfood() is Null was fooling it into thinking
that that was a possibility when it's not.
Also, use plain 1 and 0 instead of TRUE and FALSE when assigning
to the victual bit-fields. The analyzer doesn't care but the type
was mismatched due to the cast to (boolean) hidden in their macro
definitions.
Insert the calls to trigger a number of potential soundeffects
into the core.
If no additional soundlib support is integrated into the
build, then the Soundeffect macro (sndprocs.h) expands to nothing:
[#define Soundeffect(seid, vol)
]
If, however, at least one additional soundlib support is integrated
into the build, then the Soundeffect macro gets defined as this
in sndprocs.h:
[#define Soundeffect(seid, vol) \
do { \
if (!Deaf && soundprocs.sound_soundeffect \
&& ((soundprocs.sndcap & SNDCAP_SOUNDEFFECTS) != 0)) \
(*soundprocs.sound_soundeffect)(emptystr, (seid), (vol)); \
} while(0)
]
That macro definition checks for the hero not being Deaf; it checks
to ensure that the active soundlib interface has a non-null
sound_soundeffect() function pointer; and it checks to ensure
that the active soundlib interface has declared that it supports
soundeffects by setting the SNDCAP_SOUNDEFFECTS bit in its sndcap
entry. That just means that the interface routines are prepared to
accept and deal with the calls from the core, whether or not it
actually produces the desired soundeffect.
The complaint is that victual.canchoke might be used without having
been initialized. I'm fairly sure that that isn't correct but get
dizzy trying to trace through the eating code.
This might improve the situation, or maybe not.
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.
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
^ ^
Since losestr and losehp calls go together most of the time, this feels
like it probably makes more sense than repeating the killer name/format
twice in a row all over the place.
Remove callers' responsibility to deal with possible hero death when
calling losestr. This is less fragile and error-prone than leaving it
in the caller's hands, but it means that death from the monster spell
'weaken target' no longer goes through done_in_by, and the death reason
is no longer "killed by <monster name>".
Monster purple worms can now gain intrinsics from swallowing foes whole,
so maybe the hero should be able to do so too. Intrinsics aren't
granted immediately upon swallowing (that would probably have been
easier), but only once a corpse is created and then entirely digested.
I'm not sure if this is too powerful and was being avoided deliberately
for that reason, since it includes potential level gain from wraith
corpses in addition to other intrinsics. That's consistent with monster
purple worms but may be a bit too much in the hands of the hero, though
it is limited by needing the corpse creation roll to succeed.
Pull request #607 by Vivit-R proposed renaming "huge chunk of meat"
to "giant meatball" to better reflect the similarity to meatball.
But an object name that contains a monster name prefix requires extra
work in the wishing code. I considered "huge meatball" which retains
more of the original name but decided to go with "enormous meatball"
becaues it seems more evocative.
Supersedes #607Closes#607
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.
The pull request included some changes that were neither accidental nor
unintentional, so only a subset of the changes from pull request #869
submitted by klorpa were manually applied.
behaviour -> behavior
speach -> speech
knowlege -> knowledge
incrments -> increments
stethscope -> stethoscope
staiway -> stairway
arifact -> artifact
extracing -> extracting
The uses of "iff" were left alone.
Close#869
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.
... unless there's some other form that would override the choice,
such as a worn dragon armor, lycanthropy, or vampirism.
The polymorph will be in effect for 10-24 turns.
There was already handling in place to prevent showing the "continue
eating?" prompt for one-gulp food (like a wraith corpse), since the hero
would finish eating the food on that turn regardless of what the player
answered to the prompt. Resuming an interrupted multi-bite meal with
only a single bite remaining had the same problem, but wasn't accounted
for in the special "one gulp" handling. Modify the condition so it
checks for the number of bites remaining in the food, not the number of
bites total, and show the prompt only when there's more than one bite
left.
Issue #769, reported by k2 and diagnosed by entrez: eating a troll
corpse that revives on the last turn of the meal was using up the
corpse while the revival was in progress (unless the hero couldn't
observe the resulting monster), leading to a panic when trying to
use it up at the end of revival. Brought on by a recent change to
interrupt an occupied hero who can observe a hostile monster being
created nearby.
The fix isn't perfect. If revival fails because there's no place
to put the revived troll, the meal will be interrupted with one bite
left instead of finishing. If that happens, the interruption will
include a "you stop eating" message, just with no explanation why.
The partly eaten--almost completely eaten--corpse will remain.
Closes#769
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).
An end of line comment that spans multiple lines needs to start the
continuation line(s) with '*' or clang-format will convert it into
a block comment that follows the initial line.
foo(); /* call foo
but not bar */
would become
foo();
/*
* call foo but not bar
*/
however
foo(); /* call foo
* but not bar */
would stay as-is.
All that for a one-line change, and then I've changed this particular
instance to be
/* call foo but not bar */
foo();
There are lots of these that should eventually be fixed. I just
happened to notice this one when looking for something else.
Reported by vultur-cadens: slow digestion from wearing white dragon
scales/mail blocked per-turn hunger and didn't cause any hunger,
unlike ring of slow digestion which blocks per-turn hunger but still
causes some hunger as a worn ring itself. If no rings or amulet
were worn, wearing the suit prevented the hero from ever burning any
nutrition.
Change to treat wearing the suit to be quite a bit like wearing a
ring, unless hero is also wearing an actual ring of slow digestion
(then the hunger cost of the suit is 'free').
Wearing a ring of slow digestion and another ring consumes two units
of nutrition every 20 turns, no matter what suit. Wearing white
dragon scales/mail and two non-slow digestion rings now consumes three
units of nutrition every 20 turns. Using the suit to effectively get
an extra ring finger isn't free.
Fixes#742
Issue #729 by argrath points out that one of the checks in
edibility_prompts() couldn't work.
For the next-meal effect after reading a blessed scroll of food
detection, the check whether a corpse was tainted but not dangerous
because the hero had sickness resistance could never be evaluated.
An earlier condition would cause the routine to return before
reaching that check.
Move it sooner, even though doing so violates the "order by most
to least dangerous" guideline. It was either that or eliminate it
altogether.
edibility_prompts() had a lot of repetitive code that has now been
condensed.
Simplify acid blob corpse handling--for all of eating, not just for
edibility_prompts()--by treating that as "never rots" so that the
'rotted' variable always stays 0. Now checks for that variable
being greater than some threshold don't need to include "and not an
acid blob corpse" as an exception. A side-effect of this change is
that not only do they never become tainted, they'll no longer yield
the "you feel sick" outcome when they're old but not old enough to
exceed the tainted threshold.
Bug fix: edibility testing stopped warning about green slimes.
That worked in 3.6.x, but 3.7 changed the 'cadaver' variable to
exclude them so the check for eating a glob of green slime could no
longer be reached.
Fixes#729
Fix eat floor food and drink from dungeon feature via #herecmdmenu.
That uses queued commands, but those two actions were changed to
skip the floor when queued input was present because asking about
floor items interfered with context-sensitive inventory item-actions.
I was misled by a comment that says it couldn't insert an m-prefix;
that was for treating the 'm' key as typed text rather than as a
command. There's no problem with inserting a #reqmenu command which
is what 'm' is these days. So item actions can force 'm' to skip the
floor and go directly to inventory, also the #eat and #quaff commands
don't have to alter their behavior when queued input is pending so
the #herecmdmenu usage for them gets fixed.
Make being offered floor food and declining behave similarly to
being offered a chance to drink from or dip into a fountain and
declining: insert "else" into
| "You don't have anything [else] to {eat | offer | tin}."
when there is nothing applicable in inventory.
Picking a corpse while looking at inventory issued a menu that had
entry for eating that and if on an altar another one for offering
that. Picking the eat or offer choice worked as long as there
weren't any other corpses on the ground or altar. If there were
others, they'd be skipped but you'd get prompted for which item in
inventory to eat or offer instead of operating on the one that was
used to initiate the action.
When eating a meal that is affected by acid resistance or stoning
resistance and protected by temporary resistance, increase the timeout
so that the resistance doesn't expire until after the meal finishes.
That avoids getting the "you no longer feel safe from {acid,stoning}"
during the meal and not being affected by the dangerous food despite
that message. Useful because the protection is checked at the start
of the meal and not rechecked during; extending the duration hides
the latter.
It turns out that there were a bunch more monsters with the corpse-
conveys-stoning-resistance flag than just green mold. Instead of
stripping it off, give them (including green mold) a chance to confer
timed resistance against stoning and also against acid.
All of these can convey either of those two resistances. Like other
intrinsics obtained via eating, at most one can be obtained from any
given corpse.
green mold, acid blob, spotted jelly, ochre jelly, black naga,
yellow dragon, Chromatic Dragon
These can confer temporary stoning resistance but not acid resistance:
lizard, chickatrice, cockatrice, gargoyle, winged gargoyle,
xorn, Medusa
There aren't any that confer just acid resistance without a chance for
stoning resistance.
The effect lasts for 3d6 turns, or is extended by 3d6 more if randomly
chosen and applied when already in effect.
Having temporary acid resistance time out during another meal when
eating a corpse that ends up conferring acid resistance seems strange.
The protection against acid is granted at the start of the meal and
continues to the end (in regards to eating, not external attacks) even
when the intrinisic is lost in between. I'm not sure whether that
needs some form of fixing, and if so, what that fixing should be.
Fix a minor 'fixme': if hero breaks vegetarian conduct by eating
something made of bone, leather, or dragon-hide while polymorphed
into a shape which can eat such things, change the message from
"ate meat for first time" to "ate meat by-products for first time".
It took me a while to arrive at a sequence of actions which would
successfully test this. You need to break foodless and vegan
conducts first, then break vegetarian with leather/bone separately
or it won't trigger a livelog event for that. Wish for and eat a
candy bar to break vegan conduct, polymorph into a gelatinous cube,
wish for and eat leather armor, then use the #chronicle command.
Life-saving has been setting u.uhpmax to max(2 * u.ulevel, 10)
and if it took place during level drain that could make u.uhpmax
increase instead of decrease, confusing healing which gets applied
to a monster who has drained the hero with Stormbringer or the
Staff of Aesculapius. Change the setting to be max(u.ulevel, 10)
(removing the times two part) and also have level drain force it
to be set back to previous value if/when it gets increased.
Max HP loss due to strength trying to drop below 3 or to fire trap
or to being hit by Death now uses a mininum max HP of u.ulevel
rather than 1. They don't have the alternate minimum of 10; I'm
uneasy that there are still two different minimum values.
I changed adjattrib() to set the flag to request a status update
before it gave its optional message rather than after so that the
new characteristic value would be visible during the message. That
resulted in not updating status when eating royal jelly changed HP
or max HP after boosting strength. But the same missing update
would have occurred--or rather, failed to occur--without the change
in sequencing if the strength boost causes a change in encumbrance.
trycall() is a short docall() wrapper that is a no-op if the item is
already identified or the player has called the object type already. For
some reason, many calls to docall() did those same exact checks
beforehand.
This commit eliminates that redundancy by converting those calls into
trycall(), which is now made extern rather than local to do.c. No
behavior should be changed by this commit; I've checked that none of the
affected places could take a different code path now that the
oc_name_known and oc_uname checks are removed.
Shorten the livelog messages for food conduct a little by changing a
bunch of "the first time" to just "first time". Will result in fewer
instances of tty condensing whitespace for a too-wide line written
into a text window. That includes stripping off indentation, which
messes up the alignment of #chronicle output.
Also, eliminate one redundant livelog printf. Breaking vegan conduct
by eating wax when poly'd can be folded into same message for eating
leather/bones/dragon hide. [The breaking vegetarian conduct for those
says "eating meat" which seems wrong but hasn't been changed.]
This is just reformatting some relatively recently added code.
There's a lot of redundancy in eating conduct tracking and livelog
reporting of that, but this doesn't attempt to streamline it. I may
try again some other time....