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.
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.
... on the floor, in monster inventory, and in hero's inventory.
Items in your inventory being ignited produce a message even if you're
blind - you can see the lit-state by viewing inventory anyway, so just
give player the message.
(via xNetHack)
Prevent corpses left by cancelled trolls from reviving. Their
revival is an innate ability but is clearly a magical one, so make
that be subject to cancellation magic.
Change existing corpses that are scheduled to revive to rot instead
if they get cancelled as objects. Rider corpses are excluded.
Uncancel an ice troll whose corpse is put into an ice box.
Commit e9f53ab7f6 at the end of May
to fix corpses taken out of ice boxes by monsters changed removing
corpses from ice boxes by anybody to always give them rot-away
timers, even for trolls. Make an exception for ice troll corpses:
give those revive timers instead.
Noticed when checking the sokoban conduct's counter. Breaking
a line of boulders in one zap reported seeing the first but only
hearing the others, despite the first one being gone by the time
the second one was hit and so on down the line for the rest.
The report about problems after stone-to-flesh on a petrified
long worm included stethoscope feedback of 0(-1) hit points, after
life-draining. I was unable to reproduce a maximum hp of -1 and hope
that it was a side-effect of the [already fixed] stale mon->wormno
value used when resurrecting the long worm. Anyway, this changes
life-draining to never take mon->hpmax below mon->m_lev + 1 (the +1
is needed to cope with m_lev==0 monsters). The same limit is also
applied to monster life-saving but more to avoid replicating the
arbitrary minimum of 10 (four instances) then because it might be
less than m_lev+1 somehow.
Sanity checking now tests whether a monster's max HP is less than
its level + 1 so if there are ways other than life-drain attacks for
it to drop that low, the fuzzer will choke. The new check also tests
whether a monster's current HP is greater than max HP.
Polymophred hero killing a golem or vortex by vampire bite reported
"<Mon> dies." Give an alternate message since those aren't alive.
montraits() didn't have any handling for long worm tails, makemon()
didn't have any provision for creating a long worm without a tail,
replmon() uses place_wegs() to put tail segments on the map when
replacing a dummy new monster with the mtraits one but place_wsegs()
wasn't updating the head segment since it isn't put on the map.
That turned out to be key because there is always an extra segment
co-located with the monster and when its coordinates were wrong,
worm_known() gave bad results for visibility checking. The
statue-goes-away message was the one for not being able to see the
monster that it just animated into, even though 'w' appeared at the
spot. It took quite a while to track down what was going on there.
Sanity checking for worms has been updated and could conceivably
start triggering complaints about things that it used ignore.
Wishing for an item uses hold_another_object to put it into inventory
and hold_another_object wasn't reporting changes in encumbrance. That
feedback would happen at start of next turn so its lack usually wasn't
noticeable, but encumbrance could be off for remainder of the current
turn which might include additional move(s). Report indicated that
dropping something seemed to increase encumbrance instead of decrease
it, but it was dropped on an extra move and actually a delayed report
of the increase that hold_another_object failed to show.
I fixed a couple of other things with hold_another_object: it would
add an item to inventory, which triggered an update of persistent
inventory if that was enabled, then remove it from inventory in order
to drop it if fumbling or inventory had too many items or encumbrance
was going to become too high, triggering a second update of persistent
inventory to reverse the first one. Also, "encumbrance becoming too
high" was using hardcoded Stressed instead of the 'pickup_burden'
option that manages the same situation during pickup. Not because
hold_another_object isn't pickup, but because its use of hardcoded
Stressed predated implementation of that option.
There was another fix for hold_another_object recently and I've moved
the fixes entry for that one to group it with the new ones.
Also, update an obsolete (from !GOLDOBJ config) comment in makewish().
Implement the suggested feature that a camera's flash actually update
hero's memory of the map as it traverses across the level. Turned
out to be more work than anticipated despite having the code for a
thrown or kicked lit candle or lamp to build upon.
Among other things it needed to update the circle code to handle
previously unused radius 0 to operate on the center point only. I've
never touched that before and hope this hasn't introduced any bugs.
Also removes several instances of vision code operating on column #0.
(At least one is still present.)
Change obj->oextra->omid from a usually-Null pointer field in
oextra to a simple 'unsigned' that doesn't need any allocation
beyond obj->oextra itself. Value 0 means that it is not in use;
it is used to hold a monst.m_id and those are always non-zero.
Delete unused obj->oextra->olong. 'olong' used to be the last
field in struct obj, put there to force alignment of anything
which followed it back when obj structures were over-allocated to
append extra information. It had a comment about being used for
temporary gold but whatever that was, temporary gold was gone long
before obj->oextra got introduced.
Bump EDITLEVEL since this invalidates existing 3.7 save files.
Remove a bunch of tabs from obj.h and save.c.
Allow crystal ball to search for furniture (stairs and ladders,
altar, throne, sink, fountain) as well as for a class or objects
or of monsters or all traps. Giving any of '<','>','_','\','#',
or '{' will find all of those rather than just the individual type
specified. Because of the default character conflict, '_' can no
longer be used to find chains; looking for altars is more useful.
The chance of getting the cursed effect due to failing a saving
throw against intelligence when the ball isn't actually cursed has
been reduced. If it is the hero's own quest artifact, it will
happen if rnd(8) is greater than Int, so Int of 8 or more will
never yield that effect. Otherwise if it is blessed, rnd(16) is
used so 16 or better Int means it can't act like it is cursed.
When uncursed and not hero's quest artifact, the old rnd(20) > Int
test is still used.
Crystal balls now start with 3..7 charges rather than 1..5, and
blessed charging sets the amount to 7 charges rather than 6 and
also blesses the ball. Recharing with uncursed scroll of charging
is slightly better (adds 1..2 charges instead of always just 1,
caps the amount at 7 rather than 5) and uncurses the ball. Cursed
scroll strips off all charges even if the ball is blessed and also
curses the ball so is harsher than before.
Crystal balls now cancel to -1 instead of 0, like wands, and using
one effect will destroy it, like zapping cancelled wands.
Also a minor tweak to the initial charges for can of grease (5..25
instead of 1..25) and horn of plenty and bag of tricks (both now
3..20 instead of 1..20).
This adds a superset of the code from github pull request #328
to create a short-lived cloud of steam when fire hits a pool or
fountain. The original code required C99; this doesn't. It also
allowed vapor clouds on the Plane of Water where they don't work
sanely becaure regions don't understand air bubble movement and/or
vice versa. This inhibits the clouds there [the same ought to be
done for scrolls of stinking cloud]. It also left as-is the code
that reported when fountains got used up even though conceptually
the steam should interfere with being able to see that. This adds
a glyph-check hack to augment cansee() so that fountains that boil
away entirely are hidden at the time.
Regions that block line of slight should be calling block_point()
when created and unblock_point() when removed but a naive attempt
to introduce that didn't work as expected so I'm giving up on.
Fixes#328
Testing a forthcoming extension of monsters using wands of undead
turning revealed a couple of pre-existing bugs. Previously only
noticeable if hero zaps self or breaks a wand of undead turning so
unlikely to have happened much.
"Your <mon> corpse comes alive" was given even if it was revived
as an undead. Also, it was "your <mon> corpse" instead of "one of
your <mon> corpses" even when one from a stack was involved. If
done by hero to self that message follows "one of your <mon>
corpses glows iridescently" so the comes alive message was ok but
verbose. Change that to "it comes alive" or "it reanimates" when
following the glow message.
when hero is wielding a cockatrice corpse. Wands of undead turning
aren't generated as starting equipment but they will now be picked
up if come across while the hero is carrying any corpse, and used
in preference to any other item when carried and non-empty and hero
is wielding a petrifier's corpse.
Hero shouldn't be able to zap wands when polymorphed into a form which
lacks hands.
The other tweaks to dozap() shouldn't produce any change in behavior.
That message implied something to do with an effect happening to the
hero that causes them to feel cold, such as taking cold damage.
Change it to "You hear a deep cracking sound" instead.
Fixes#240
Monster versus monster (melee and throwing) didn't handle shades
(need silver or blessed weapon to take damage) or silver feedback
(extra info when silver-haters are hit).
I did a lot of test, revise, re-test but didn't always re-test
everything that had previously been tested, so bugs that I thought
were quashed might have crept in.
Now if a missile weapon "passes harmlessly through the shade" it
will continue on and maybe hit something else. (Regular misses
still stop at the missed target.)
A couple of minor ball&chain changes accidentally got included.
With 3.7+ aspirations of improving savefile interoperability between 32-bit
and 64-bit builds, as well as between platforms, it is better to not have
the underlying struct/array content be conditional.
This splits off some of the MAIL code into MAIL_STRUCTURES code. In theory,
since MAIL_STRUCTURES is unconditionally included, the macro could
just go away and leave that code unconditional, but this commit doesn't
go that far.
Flag existing occurrences of "You hear" as "Deaf-aware" so
that a grep for that string in the future doesn't need to
trigger further investigation of those.
If you ask for help when wishing, don't leave "help" in the buffer
for EDIT_GETLIN to use as default answer on next retry. It does still
leave anything rejected as unknown so that the player has a change to
review the spelling and conceivably add and/or remove from the end
witout having to retype everything.
Throwing or kicking a lit lamp, lit candle, or lit potion of oil
wasn't giving off any light as it travelled to its destination.
Now it does, and dungeon features, objects, or monsters that are
temporarily seen as it moves from square to square till appear on
the map. In the monster case, they go away as soon as the light
moves beyond range, but when it finishes moving the "remembered,
unseen monster" glyph will be drawn at their location. I think that
part has some room for improvement, but mapping temporarily seen
terrain features is the primary impetus for this change.
Also, any message delivery while the "lit missile" travelled still
showed its light around the hero. Noticeable for lamps or stacks
of sufficient candles if hero has no other light source.
This cannibalizes the monst->mburied bit for temporarily seeing a
monster. It has been present but unused for ages. I needed to
replace a couple of vision macros to make sure they didn't examine
it any more so that overloading for transient lighting doesn't
introduce any vision oddities. For version $NEXT, monst->mtemplit
can be given its own bit. It is only set during bhit() execution
and cleared by the time that returns, so has no effect on save files.
If a corpse with a revive timer included obj->oextra->omonst for
remembering the original monster (I think all corpses do these days)
and makemon() failed to create a new monster when the timer expired,
the copy of the original wasn't freed. makemon() will fail if there
is no room for the monster.
Carried containers could have their contents-known state and/or
lock-known state changed without persistent inventory window being
updated to show the new information.
This also changes the behavior when player has hero zap self with
wand of locking or wizard lock spell. If it doesn't trigger a
holding trap then the effect will hit inventory, similar to how
opening/knock operates (releasing hero from holding trap or hiting
inventory when that doesn't happen).
Preserve temporary fake object's previous dknown value by storing it
as a flag value within the m_ap_type field of the posing monster, and
recalling it when it is needed.
This is intended to help eliminate observable differences in price display
between real objects and mimics posing as objects.
98% of this is just switching the code to utilize macro M_AP_TYPE(mon)
everywhere to ensure that the flag bits are stripped off when needed.
Report forwarded from spam filter so not included in bugzilla list.
Make corpse revival feedback be more consistent. Some of the healer-
specific flavor is still there.
This is branched from Alex's hallu-rng-stability branch,
with two build corrections (detect.c, zap.c), and merged
with the isaac64 branch that we have ready to go.
Alex's dual rng is supported by setting up the array
of multiple isaac64 contexts.
I stuck with Alex's approach of passing the rng function
name around as the parameter (rng or rn2_on_display_rng)
for the new additional parameter needed for
set_random(), init_random(), reseed_random(),
and init_isaac64().
This is based on the multiple-RNGs code fron NetHack4, but using
only the parts relevant to the display RNG (and with substantial
changes, both because of post-3.4.3 changes, and because Nethack4's
display code is based on Slash'EM's rather than NetHack's).