I made more things in dump_enums() static and/or const. In the
process I discovered both compile problems for NODUMPENUMS and when
fixed, link problems for NODUMPENUMS+ENHANCED_SYMBOLS.
The uft8map.c portion has no changes, just reformatting.
Option parsing rejected
|OPTIONS=!cond_X
for all valid X.
Using the menu to unselect all condition options treated that as not
having made any choice and didn't make any changes. That would be
reasonable if nothing was preselected, but things are so unselecting
all of them is a choice. (A bizarre one, but still should be viable.)
Mostly this deals with including cond_X options when #saveoptions is
used to write a new RC file. It now produces something like
|OPTIONS=!cond_barehanded,cond_blind,!cond_busy,cond_conf,!cond_deaf,\
| cond_iron,cond_fly,cond_foodPois,!cond_glowhands,cond_grab,\
| cond_hallucinat,!cond_held,!cond_ice,cond_lava,cond_levitate,\
| !cond_paralyzed,cond_ride,!cond_sleep,cond_slime,!cond_slip,\
| cond_stone,cond_strngl,cond_stun,!cond_submerged,cond_termIll,\
| !cond_tethered,!cond_trap,!cond_unconscious,!cond_woundedlegs,\
| !cond_holding
after the last alphabetical option and before the bound keys, menu
colors, and others which aren't simple OPTIONS=X settings. This only
happens if there is already one or more OPTIONS=cond_X entries in the
old file when it was read or if 'mO' gets used to make any changes.
Not fixed: after my RC had something similar to the above and before
I changed status conditions to accept negation, I was getting several
"the cond_ option may not both have a value and be negated" messages
written to stdout instead of the config file error handler. So they
vanished when the screen was initialized without providing a --More--
prompt to acknowledge that they have been seen.
Instead of using index() macro defined to strchr, use C99 strchr.
Instead of using rindex() macro defined to strrchr, use C99 strrchr.
If you want to try building on a platform that doesn't offer those
two functions, these are available:
define NOT_C99 /* to make some non-C99 code available */
define NEED_INDEX /* to define a macro for index() */
define NEED_RINDX /* to define a macro for rindex() */
Reverts 690e072, which changed the various is_foo macros from this:
| #define is_elf(ptr) ((((ptr)->mflags2 & M2_ELF) != 0L)
to this:
| #define is_elf(ptr) ((((ptr)->mflags2 & M2_ELF) != 0L) \
| || ((ptr) == g.youmonst.data && \
| !Upolyd && Race_if(PM_ELF)))
This is a problem because g.youmonst.data is not unique to the hero:
the '(ptr) == g.youmonst.data' test will also be true of all player
monsters of the same role. For this reason, any of those player
monsters will be treated as sharing the hero's race, producing strange
results. For example, if the player is an elven ranger, any ranger
player monster generated will be considered 'elven' too (so will get a
to-hit bonus when attacking orcs, etc) -- but only while the hero is
unpolymorphed.
There are already other ways of checking the hero's race in addition to
her current polyform, most notably the maybe_polyd() macro. maybe_polyd
or something similar is already used in nearly all the cases where the
hero's race is being evaluated, meaning Race_if gets used instead when
the hero is in her natural form. So I think the check of the hero's
race in is_foo had very little effect except for the unintended
side-effects on player monsters.
In reviewing all the uses of is_{elf,dwarf,gnome,orc,human}, I noticed
only one case that relied on the hero-race-checking behavior. That has
been changed in this commit to use maybe_polyd (there's another 'raw'
is_human(g.youmonst.data) a few lines down, but it doesn't need
maybe_polyd since it already distinguishes between 'hero in nonhuman
polyform' vs 'nonpolyd or human polyform'). same_race(mondata.c) is
another case where &g.youmonst.data can be passed to is_foo, but
everywhere that calls it for the hero also calls your_race() or
same_race(&mons[Race_switch]) to handle the racial case.
There was a TODO about this; not exactly a great challenge but it feels
like a worthwhile change since the name was misleading. I also updated
the name of the do_intrinsics parameter of extract_from_minvent(worn.c),
since it was in a similar situation (and directly related, since it
controls whether to call update_mon_{in/ex}trinsics).
A giant mummy starts out with a mummy wrapping but couldn't wear it.
Allow humanoids who are bigger than human size (including poly'd hero
when applicable) to wear such cloaks. They won't do so if they are
invisible and the cloak would let hero start seeing them.
cansee(), couldsee(), and templit() are macros which are described
as boolean and used as if boolean, but they've been using bit
masking to return integer values greater than 1. That works since
C treats any non-zero as True but doesn't match boolean intent.
Reported by entrez: using ^A instead of #retravel after interrupted
travel can pick wrong location if cursor was previously positioned
with movement commands rather than feature targeting because it
won't be starting from the original spot. Also, ^A after ';' will
just redescribe whatever was examined previously instead of having
the player pick a new spot.
This suppresses cursor positioning from the do-again queue so that
repeating travel or quick-look or other command that needs player
to choose a position will repeat the command but then need to have
a position chosen. For interrupted #travel, the cursor will already
be placed on the previous destination so that's relatively painless,
but also allows a different destination to be chosen.
It adds iflags.remember_getpos that callers of getpos() could set to
be able to restore the old behavior but none do so far.
Fixes#905
Issue reported by vultur-cadens: Elbereth used to be effective in
inhibiting monster movement when an object was present on the same
spot, but since 3.6.0 it isn't. It only functions that way when the
hero--or hero's displaced image--is present these days. So special
levels that have been using engraved Elbereth to try to protect
objects from monsters haven't been providing any useful protection.
This makes Elbereth that's engraved during level creation work like
it used to in 3.4.3 and earlier: when there's at least one object
on the engraving's spot, monsters who are affected by Elbereth will
be affected. [I'm fairly sure that that behavior started out
unintentionally, as a side-effect of an optimization to only check
for scroll of scare monster when there was at least one item present
which is a necessary condition for such a scroll.]
Old-style Elbereth includes Elbereth chosen as a random engraving
during level creation in addition to engravings specified in special
level definitions. Engravings by the player don't have the required
attribute and player-engraved Elbereth behaves in the 3.6 way.
This ought to be replaced by something more general. Perhaps a new
engraving type not usable by the player?
Fixes#900
Fix most of the things pointed out by #wizmondiff.
Weakening of placeholder 'elf' is due to recent removal of M2_STRONG
for it as part of the "orc strongmonst" changes.
I assume that the discrepancies for multiple quest leaders came about
as part of the change that allows killing the leader as an alternate
way to gain access to the lower levels of the quest, but didn't check.
I don't know what's up with 'piranha' but just changed it to match
generated value.
'{freezing,flaming,shocking} sphere' still show up as discrepancies
with hardcoded (mons[].difficulty) value higher than generated value.
They got harder when their explosion was beefed up, so the formula to
calculate difficulty ought to be updated to account for that.
Force windowtype to be the first option written to new RC file since
its value can affect how other options are processed. (Only saved if
comes from existing RC file, not command line.) doset() lists a few
compound options before the rest too. Combine the two sets of want-
to-be-first and move the handling for that to optlist.h where the only
cost is that the options are no longer in alphabetical order.
Handle alternate values for hero poly'd into a 'strongmonst' form
more thoroughly by propagating max values other than 18/100 to the
attribute manipulation routines.
ATTRMAX(A_STR), which used to be a relatively simple expression, now
contains a function call.
Along the way, change the races[] terminator's value for 'mnum' from
0 (giant ant) to NON_PM.
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>".
Killer format isn't a boolean, since it has 3 possible values
(KILLED_BY_AN, KILLED_BY, NO_KILLER_PREFIX). It shouldn't make any
difference behind the scenes, but it's confusing to use 'boolean' for
it.
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.
Issue reported by eakaye: for a 'hugs' attack to succeed, the
monster must have at least three attacks and the two preceding the
hug attack need to both hit. Guardian nagas had three attacks but
the first was melee 'bite' and the second was ranged 'spit'. Those
are mutually exclusive, so they would never both hit and nagas never
grabbed their prey.
Make the spit attack be first, the bite attack be second, insert a
touch attack for 0 damage third, and make the hug be fourth. Also,
change their hug damage type from 'phys' to 'wrap'. The first and
2nd+3rd+4th are still mutually exclusive.
The resulting message feedback left something to be desired and has
been tweaked.
The difficulty-level formula used by deprecated 'makedefs -m' now
generates 17 rather than 16 for guardian naga so I changed revised
monster to match. They are definitely more difficult now that their
constriction attack has a chance to hit.
Fixes#894
An Xcode update has started causing the same problem that was experienced on
Linux with newer compiler or glibc a while back.
˜
In file included from monst.c:6:
In file included from ../include/config.h:670:
In file included from ../include/integer.h:54:
In file included from /Applications/Xcode_14.0.1.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/clang/14.0.0/include/stdint.h:52:
In file included from /Applications/Xcode_14.0.1.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/stdint.h:52:
In file included from /Applications/Xcode_14.0.1.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types.h:32:
/Applications/Xcode_14.0.1.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/cdefs.h:302:39: error: too few arguments provided to function-like macro invocation
^
1 error generated.
make[1]: *** [monst.o] Error 1
Please enter the commit message for your changes. Lines starting
I was trying to reproduce the reported "no monster to remove" warning
from remove_monster() when a mounted hero was knocked off jabberwocky
steed but so far haven't been able to.
While trying, I came across a more minor bug. The hero got knocked
off a flying steed and got feedback of "you fly off" rather than
"you fall off". Flying capability came from the steed and dismount
feedback is aware of that but calls u_locomotion() which isn't. This
commit fixes that.
This adds some groundwork (DISMOUNT_KNOCKED) for better dismount
control. With a map fragment of
|....
|.Du.
|....
I got knocked off my steed by the attacking dragon and ended up with
|..@.
|.Du.
|....
It would be better to prefer spot 1, then the 2s, then 3s, then 4s
(not sure about farther spots if none of those are available)
|.432
|.D@1
|.432
when forced to dismount by knockback. This does _not_ implement that.
Reported by eakaye: orcish hero has maximum strength of 18/50 but
hero poly'd into an orc was given 18/100 strength. Also, a comment
from vultur-cadens pointed out that orcish heroes start with poison
resistance while monster orcs lack it.
Even though the boost to 18/100 is only temporary until the poly
times out, make orcs a special case where strongmonst from poly'ing
into them only gives 18/50 strength instead of 18/100. Adopt the
suggestion that Uruk-hai be an exception and continue to give hero
poly'd into them 18/100.
If any gnome becomes strongmonst (currently none are), treat them
as 18/50 too. Elvenking and elf-lord are strongmonst; treat their
forms as plain 18 though, matching the limit of elf heroes. Lesser
monster elves aren't strongmost.
While in there, add another special case so that hero poly'd into a
giant gets 19 strength. Monster giants are still plain strongmonst
so might warrant some sort of adjustment.
Give orcs poison resistance, but eating their corpses doesn't provide
an opportunity to confer it. Note goblins and hobgoblins still don't
have the resistance (to distinguish them from orcs a bit).
Take away strongmonst from orc shamans and give it to orc mummies.
Human mummies should have it too (at least according to movies) but
I didn't alter them becuase they're already pretty dangerous at the
point they start occurring. Take away strongmonst from plain 'elf'
placeholder.
New: when hero polymorphs into a form that lacks the strongmonst
attribute, take away any exceptional strength (drop 18/01 through
18/100 down to 18; as mentioned above, the drop is only temporary).
There's no attempt to set the maximum even lower for wimpy forms.
Fixes#679
The macro (currently unused, I think) for checking whether a particular
index designates a subroom was off by one on the maximum allowable
value.
Because of the dedicated extra space for the g.rooms array terminator
flag (hx == -1), subroom indices in g.rooms are set out in the range
[MAXNROFROOMS+1, MAXNROFROOMS*2], inclusive.
Also some minor formatting tweaks.
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
Refine commit 4885653014.
> I'm not sure whether gcc 3 is really the right test for whether the
> returns_nonnull attribute setting is available.
The gcc.gnu.org website only goes back to 5.1, and searching the
documentation of that version for returns_nonnull finds it. I used
ftp to get gcc-core-3.0.0 and gcc-core-4.0.0 and their doc files don't
mention this attribute. It might have been added for some later 4.x
but that really doesn't matter for nethack's purposes.
Use __GNUC__ >= 5 instead of __GNUC__ >= 3 when testing whether
__attribute__(returns_nonnull) is available.
This is an alternate way to deal with pull request #876, where
splitting a stack that has a name assigned updated perm_invent when
cloning the name and ran into trouble with shop billing when trying
to format for persistent inventory display.
The PR#876 fix has been left in place but wouldn't have been needed
if this had gone in first.
Mark alloc()--also dupstr() and re_alloc()--for gcc and clang as
always returning non-Null. This should silence some of the static
analysis complaints.
Almost all the monster and object naming functions (anything that
returns an mbuf or an obuf) should be marked this way too but I'll
leave that for somebody else to deal with.
I didn't attempt to mark alloc() with the 'malloc' attribute because
macro definitions could end up causing trouble. Specifying its
deallocator would probably be useful but is at even bigger risk of
macro interference.
I'm not sure whether gcc 3 is really the right test for whether the
returns_nonnull attribute setting is available.
Trap doors saved their destinations as an absolute level, rather than a
relative one, so if you loaded bones from a special level their
destinations would reflect the dungeon layout from the bones player's
game. For example, die on the Oracle level, on dlvl5, with a trap door
that goes to dlvl6. Another player gets those bones on their Oracle
level, which is dlvl8... the trap door would still go to dlvl6. Pretty
amazing trap door -- something you might see in a funhouse!
Include relative rather than absolute destinations in save and bones
files, much like stairs do, to avoid this problem.
I bumped EDITLEVEL because although this won't break save files in an
obvious way, it will interpret the (absolute) destinations in existing
save and bones files as relative, leading to some crazy long falls. :)
Use verbiage for mon vs mon and hero (mostly hero) engulf attacks that
matches recent changes to monster vs hero engulf attacks more closely
(e.g. "swallows whole" instead of "engulfs" for purple worm, other
changes in b07fe59...). Also ensure non-AD_DGST engulf attacks
(e.g. from revamped trapper or lurker above polyforms) aren't treated as
"eating" (or as involving "debris").
Also change the enfolds and digests macros so they produce booleans
rather than attack pointers (I got a compiler warning about casting
struct attack * to boolean when I did 'boolean b = digests(ptr);').
Reported by Umbire:
|You kill SpaceMannSpiff! SpaceMannSpiff puts on a dwarvish cloak.
|SpaceMannSpiff puts on a dwarvish iron helm.
|The seemingly dead SpaceMannSpiff suddenly transforms and rises as
| a Vampire.
This was tough to reproduce but I finally managed it. The issue
text mentions that it was fixed by copperwater in xNetHack with
commit 8c4af50f0aa3e72522f3eb98df039ff25c2a1ea0 to the repository
for that variant. My attempt to cherry-pick that failed--I'm not
even sure whether it should have been expected to work--and some of
the code has been impinged upon by changes, so I ended up applying
the contents of that commit manually.
The commit changes how/when monsters put on new armor rather than
anything directly related to vampires. Circumstances similar to
the example above now yield:
|You kill SpaceMannSpiff!
|The seemingly dead SpaceMannSpiff suddenly transforms and rises as
| a Vampire.
on one turn, then on the next turn the revived vampire produces:
|SpaceMannSpiff puts on a dwarvish cloak.
My test case only had one item of interest; I assume that the second
item of armor gets worn on a subsequent turn rather than at the same
time as the first one.
Fixes#843
Format a horn of plenty whose charge count is unknown but is known to
be empty as "empty horn of plenty" like is done for real containers.
This was too easy; I must have missed something....
Previously, the tetris-shaped rooms were always either
normal rooms, or turned into shops or other special rooms
in NetHack core. Now, the themed room lua code first picks
the themed room (which can be a themed or shaped), and some
of those will then pick a random filling (eg. ice floor,
traps, corpses, 3 altars).
Adds a new lua binding to create a selection picking locations
in current room.
The content-function in special level regions now get passed
the room data as a parameter.
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