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
cg.zeroobj was originally added (under its previous unprefixed name)
for providing a one-line way to zero out the fields of a struct obj.
struct obj tempobj;
tempobj = cg.zeroobj;
initfn(struct obj *otmp)
{
if (otmp)
*otmp = cg.zeroobj;
}
More recently, the address of cg.zeroobj began to be used as a return
flag to indicate some things, but the 'const struct obj zeroobj' wasn't
an ideal fit for the purpose and required a number of casts, including
casting away const.
Provide a better fitting variable (gi.invalid_obj) and eliminate a
number of casts.
Pull request from NullCGT: applying gold from inventory will flip
one coin and report "heads" or "tails". If impaired, that coin will
be dropped, otherwise it will remain part of the stack in inventory.
Can be done via 'a $' or with context-senstive item action via 'i $ a'.
I've used 'git merge --squash' and 'git commit -C <commit#>' to
flatten four commits into one and it seems to have accomplished what
I wanted, including retaining the log message from <commit#>.
I also changed
|You flip a gold piece. The gold pieces slips between your fingers.
to
|You flip a gold piece. It slips between your fingers.
when impaired and applying one from a stack.
Closes#1107
Applying one or more gold pieces now flips one of them, which will
cause it to come up heads or tails. This is NetHack, so there are
special cases for flipping a coin underwater or while fumbling or
greasy.
I've tried to future-proof this commit so that the code will not
need to be modified if other items are eventually added to the
coin class.
If memory serves, there was a patch for this on the bilious patch
database, but I was unable to locate it or who the original author
was. In any case, the code is entirely original.
Using apply to unlight a lit potion of oil makes it unlit, removes
it from inventory, and then re-adds it to try to force it to merge
with other potions of oil. If it was wielded and the other potions
were quivered, the game would panic. When merging, they get forced
into the weapon slot in preference to the quiver slot.
Unwearing it before freeinv+addinv would solve this but also leave
the hero with nothing wielded, even if it didn't merge with another
stack. Instead, don't try to merge if the potion being unlit happens
to be worn.
3.6.x was subject to this too and the fix is small+isolated but the
situation is so uncommon that I haven't bothered backporting it.
Applying a lump of royal jelly and then not picking anything to rub
it on had a similar problem. It also panicked if the applied lump
was wielded and other lumps were quivered. The fix is different
because the stack it gets split from during apply is known. This one
doesn't impact 3.6.x; applying jelly to eggs wasn't implemented yet.
When a hidden pet was relocated via magic whistle, a message was given
about "your <pet> appears" but it didn't show up on the map.
It was being marked as no longer undetected, but that was after rloc()
had moved it and redrawn its location. use_magic_whistle() needed to
redraw its location again after clearing monst->mundetected.
Treat a trap object that has become the focus of trap setting
occupation as if it had already been used up. (No discernable change
in behavior unless someone adds an artifact bear trap or landmine
that talks.)
Shouldn't 'trapinfo' be part of 'context' and be saved and restored?
(If so, it will need to include o_id and undergo pointer fixup during
restore.) When trap arming is in progress hero will be too busy for
player to issue S(ave) command but a hangup save could take place.
Found this running the fuzzer with address sanitizer. After applying an
object, the game checks whether it's a talking artifact so that it can
speak to you afterwards.
If, however, the object got destroyed in the process of applying it,
this will read and dereference obj after they have been freed. I found
this with a cream pie, which is always destroyed when someone applies
it.
To fix this, I tracked the obj pointer for what I think are the only two
cases in the big switch statement that don't track this - royal jelly
and cream pie. Royal jelly is only conditionally destroyed depending on
further input, so its function had to be refactored to take a struct
obj**, but cream pies are unconditionally destroyed so it can just be
set to null.
Reported by argrath: the test for whether blindness could be fixed
by applying a unicorn horn got broken by the recent change to the
Blinded macro.
While in there, undefine macros once they stop being useful. I put
these #undef lines closer to their #define instead of at end of file.
Also, remove an out of date comment about encoding property troubles.
It became obsolete when unicorn horn stop fixing lost Str, Dex, &c.
Fixes#1020
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.
To get the Magic Mirror of Merlin to speak, you could apply it in
any direction (or wield it). To get the Master Key of Thievery to
speak, you had to apply it toward an adjacent doorway or down while
on a container (or wield it). Make the key behave like the mirror.
sound_verbal(char *text, int32_t gender, int32_t tone, int32_t vol,
int32_t moreinfo);
-- NetHack will call this function when it wants to pass text of
spoken language by a character or creature within the game.
-- text is a transcript of what has been spoken.
-- gender indicates MALE or FEMALE sounding voice.
-- tone indicates the tone of the voice.
-- vol is the volume (1% - 100%) for the sound.
-- moreinfo is used to provide additional information to the soundlib.
-- there may be some accessibility uses for this function.
It may be useful for accessibility purposes too.
A preliminary implementation has been attempted for macsound to test
the interface on macOS. No tinkering of the voices has been done.
Use of the test implementation requires the following at build time with make.
WANT_SPEECH=1
That needs to be included on the make command line to enable the test code,
otherwise just the interface update is compiled in.
I don't know for certain when AVSpeechSynthesizer went into macOS, but older versions
likely don't support it, and would just leave off the WANT_SPEECH=1.
If built with WANT_SPEECH=1, the 'voices' NetHack option needs to be enabled.
It was a bit strange, when I first started up the test, to hear Asidonhopo,
the shopkeeper, talking to me as I entered his shop and interacted with him.
Use macOS AppKit framework routines for a first cut at a
macsound soundlib interface.
Requires WANT_MACSOUND=1 on build.
Nothing has been done to move the stock sounds into the resources
of a bundle, so after building, if you want to try the stock sounds
out:
cp sound/wav/*.wav ~/Library/Sounds
Because the NSSound macOS routines always do the search, supposedly
the following locations are searched in this order:
1. the application’s main bundle
2. ~/Library/Sounds
3. /Library/Sounds
4. /Network/Library/Sounds
5. /System/Library/Sounds
Although not specifically implemented as of yet, it may be pretty
close to being able to put soundeffects wav files (by se_ name)
into ~/Library/Sounds working for the SND_SOUNDEFFECTS_AUTOMAP feature.
Feedback is welcome. Contributions for improving it are even more
welcome.
The new soundlib supporting file is named
sound/macsound/macsound.m since it's got objective C in it.
Known bugs and glitches:
The Hero_playnotes on a set of 5 notes goes too fast, so there
needs to be a slight delay added between the note of a multi-note
play.
Underwater vision was updated only once per turn, so if the hero had
more than one move per turn it could cause some spots to be left behind
on the map. For example, after moving around underwater while very fast
for a while:
}
}}}
}}}}
} }}@}
} }}}
Not only does the radius of vision appear to "smear" temporarily, but if
the hero moves fast enough, isolated spots can be left entirely behind
(since the normal underwater vision update only clears nearby spots, not
the entire map). Both these effects are visible in the example above.
The fix in this commit is to update the frequency of underwater vision
updates to "once-per-time-taken" rather than "once-per-turn", so that it
updates with every move. I'm not sure if it needs to happen more
frequently than that (i.e. in the "once-per-input" section) but I might
be overlooking something.
Also add missing punctuation to the message for applying a lamp
underwater.
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.
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
^ ^
Short for distu(mtmp->mx, mtmp->my) (i.e. the distance between the hero
and the specified monster), which is a very common use of distu(). The
idea is that this would be a convenient shorthand for it; I actually
thought it (or something very similar) existed already, but couldn't
find it when I tried to use it earlier. Based on the number of uses of
fully-spelled-out 'distu(mtmp->mx, mtmp->my)' replaced in this commit
I'm guessing I just imagined it.
For tipping purposes, a horn of plenty is treated like a container.
But using one as the source container in a container-to-container tip
wasn't supported. Implement that.
Also, #tip was offering carried bags of tricks as candidate containers
to tip some other carried container into. Only do that for ones which
aren't known to be bags of tricks (so when type not discovered yet, or
specific bag not seen yet due to blindness).
Reported by k2: tipping one container's contents directly into
another container allowed transferring a wand of cancellation (not
mentioned: or a bag of holding or a bag of tricks) into a bag of
holding without blowing it up.
That's now fixed. There are other issues that this doesn't touch:
I think it's odd that you can transfer stuff from one carried
container to another but not from a carried container to a floor
container nor from one floor container to another one at same spot.
I didn't test shop billing so an not sure what happens when #tip
blows up a bag of holding and there are some unpaid items involved.
Using #tip on horn of plenty treats it like a container, but doing
that when it's carried doesn't offer the chance to tip its contents
directly into a carried container.
Tipping a carried container does not require free hands or even
limbs (for playability) but tipping such into another container
should require at least one free hand.
Fixes#872
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
Wizard-mode command to cast any spell without checks that would
prevent casting, and with no energy use.
Mainly to allow the fuzzer to exercise the spell code paths.
Some static analyzers flagged the last-resort values as
out of bounds (which they were).
There's a small number of other complaint-suppression items in here too,
but nothing drastic.
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.
Issue reported by GorillaSapiens: you get notified if a lamp burns
out even if you're blind at the time.
That is intended behavior; you can feel the heat or lack of heat
from a lamp or candle. But the comment from copperwater pointed out
that you shouldn't be able to feel that for a brass lantern.
This suppresses the "power has run out" feedback if blind at the
time. However, applying a lantern to turn it on or off still gives
the on/off feedback on the assumption that there's a switch and you
can feel its position. When hero is blind and lantern is out of
power, trying to turn it on yields "nothing seems to happen". It's
not completely consistent since you would feel the switch in its On
position but claiming that the lantern is on would be a lie.
The basic on and off messages referred to "lamp" even when using a
brass lantern. I thought that that had been fixed a long time ago.
Fixes#842
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.
An amorphous engulfer like a fog cloud could engulf the hero, then carry
him into a closed door. If it was killed or decided to spit out the
hero, he would be left occupying the same spot as a closed/locked door.
Make an amorphous monster unable to move into a door if currently
engulfing the hero.
Something more complicated could be done along the lines of allowing the
move if the hero is himself in an amorphous polyform, but that verges on
being a little too silly, maybe.
I also included fixes to a couple miscellaneous, unrelated formatting
issues that I noticed recently.