Commit Graph

4831 Commits

Author SHA1 Message Date
Bart House
7e72bc0944 mklev() set xxstairs_room pointers back to NULL upon completion.
When mklev() is called multiple times, previous state stored in the
xxstairs_room pointers can be mistakenly used when making decisions about
the new level being constructed.  This caused non-deterministic level
creation behavior when replaying from a snapshot.
2019-07-06 14:18:02 -07:00
Bart House
f75deae0bc When fuzzing, use the number of moves as a proxy for the hour.
Every 1000 moves simulates one hour.
2019-07-04 18:06:56 -07:00
PatR
79ff4cd9c3 fix github issue #202 - worn items inside engulfer
Fixes #202

When swallowed, you can take things from the engulfer's inventory, if
there are any, via pickup.  Items might be worn by the engulfer and
when "picked up" those weren't being unworn before being added to
hero's inventory.  Then they would be formatted as "(being worn)" and
could trigger warnings or worse.

Conceptually they should be worn on the outside and not be accessible
from the inside, so I've made attempts to pick up worn items fail
rather than fix up the unwearing.

Using ':' when swallowed to look at the engulfer's inventory describes
that inventory as "contents of <mon>'s stomach".  That's weird for any
worn items, but the situation is so rare I haven't made any attempt to
deal with it.
2019-07-03 18:30:55 -07:00
PatR
4a74968a58 shk doname for containers
Rescue some old code from bit rot.  It may be useful if the shop
side of things ever gets fixed.  (Itemized billing reveals container
contents.  I'm sure that it's in the bugzilla list but can't find it.)
2019-07-03 13:43:24 -07:00
Bart House
25ea6c8f3c Fix crash that can occur in decode_mixed.
If a player names an object with a name that ends in '\\', drops
that object on the floor nearby and does a look at nearby objects,
then the game will crash.  This is caused by stack corruption when
the decode loop skips over the decode string terminator.
2019-07-02 19:08:50 -07:00
PatR
1e7fb839a3 status_hilite for Xp and Exp by percent rules
Extend support for highlight rules that specify percentages from HP
and spell power to experience level and experience points.  For both
of those, the percentage is based on progress from the start of the
current Xp level to the start of the next Xp level.  100% isn't
possible so is used to enable highlighting a special case:  1 point
shy of next level, most likely to occur after losing a level.

This is something I had in mind a long time ago and then forgot all
about until fiddling with the final disclosure of experience points
recently.  It turned out to be trickier than expected because it needs
to check whether Xp should have a status update when it hasn't changed
but Exp has gone up.  The latter might hit a percentage threshold that
switches to another highlight rule.  Fortunately changes to Exp, at
least that aren't part of level gain or loss (which always trigger
status updating), are all funnelled through a single place (I hope).
2019-07-02 17:39:23 -07:00
Bart House
1b0d47911f When restoring game we should not need to invoke rnd to test for hiding. 2019-06-30 16:41:24 -07:00
Bart House
c928cda775 Need to check ball and chain after we have procesed floor objects. 2019-06-30 16:34:41 -07:00
PatR
4db3b55057 wishing vs EDIT_GETLIN
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.
2019-06-30 13:45:14 -07:00
PatR
93ddb5c6d8 attributes disclosure: experience points
Wizard mode shows the number of points needed to reach the next level
(unless already maxxed out at 30) for ^X and end of game disclosure.
Do it in normal play for the latter too.  (I think it would ok to do
that for ^X too but haven't gone that far.)

Even when it was wizard mode only, the phrasing for past tense had a
minor grammar bug, and it could make the line a little too long for
tty and curses (not sure about others) when level was high, resulting
in wrapped text.  That looked bad for tty, which first tries removing
indentation (just 1 space in this case), making that line outdented
as well as wrapped.  So change the phrasing slightly when experience
level is 'too high'.  I had a version which formatted, measured, and
re-formatted if necessary but that was overkill; simple hardcoded
rephrasing suffices particularly when measuring was against assumed
display width (80) rather than actual width.
2019-06-30 10:51:00 -07:00
PatR
7013563415 ^I vs perm_invent again
A recent fix for #wizidentify showing "Not carrying anything" after
listing inventory items still showed "Not carrying anything" after
"(all items are already identified)".  Fix is easy.

Trickier bug was that ^I performs object ID on selected items while
the inventory routine is still in progress (but after it has processed
every item) and the ID routine will call update_inventory() which
will call the inventory routine to reformat invent.  So the inventory
display routine was called recursively without having returned to
wizidentify where iflags.override_ID gets cleared to revert to normal
inventory.  The nested call was unintentionally narrowing the contents
of persistent inventory window to whatever items were still unIDed.
(Any inventory update, including ^R, restored it to full inventory.)
2019-06-28 12:50:08 -07:00
PatR
928534509f UNIX|VMS compile warning
So no one on Unix or Unix-like ever builds without tty support?

options.c:694:11: warning: unused variable 'opts' [-Wunused-variable]

Noticed when producing a curses-only binary to verify that erase_char
and kill_char weren't relying on tty being present.
2019-06-27 17:42:56 -07:00
PatR
fa4f9bb8ae coalescing partly eaten globs
Another one which has been around for a while.  When merging two
globs, the result is partly eaten if either (or both) of them was
partly eaten, not just when the one that's going to stick around as
the combined glob already was.
2019-06-26 15:37:17 -07:00
PatR
54e2e71319 mpickobj sanity, ball&chain theft feedback
Something I've had sitting around for quite a while.  Add a sanity
check to mpickobj().  (It will need tweaking if b&c are changed to be
in engulfer's inventory.)

Also, include more information in the feedback when a nymph steals
attached iron ball:  "Nymph removed your chain and stole a heavy iron
ball".

And don't set the avenge-ok flag if uball is the item stolen since
thief was doing hero a favor, or for anything when the thief is under
the influence of Conflict.
2019-06-26 15:33:40 -07:00
PatR
88f19c57e4 ball&chain bit
A check for bad restoration (ball without chain or vice versa) issued
a warning but then left the problem around to trip up other code.
'Fix' the problem by clearing those owornmask slots and their pointers.
Doesn't try to recover memory if the one that's found is OBJ_FREE.

Also some formatting.
2019-06-25 11:02:07 -07:00
PatR
8a9c06f5c1 'sortpack' vs 'perm_invent'
The persistent inventory window wasn't being updated if you toggled
the 'sortpack' option interactively.  (The new setting was honored
once something else triggered a 'perm_invent' update.)

The logic for toggling 'fixinv' seemed backwards.  I hope this "fix"
for that hasn't actually broken it.
2019-06-24 18:54:38 -07:00
PatR
cfc8599e69 fix "Bad fruit #N" warnings when saving bones
savebones() sets all the fruit indices negative, then resets to the
normal positive value for each fruit it actually writes into the bones
file.  But if 'perm_invent' is enabled and something triggers an
update_inventory() while bones saving is in progress, object formatting
for the inventory display won't be able to find any fruits, resulting
in impossible "Bad fruit #N".  Fix is to turn off 'perm_invent' when
the game ends, so it won't be On when bones are written.  Disclosure
uses a popup for inventory so persistent window is obsolete by then
anyway.

[I don't know what is triggering update_inventory() while savebones()
is executing.  Also, I don't see where the fruits whose index stayed
negative--because there aren't any on level being saved--get purged.
Maybe when those bones are loaded by another game?]
2019-06-24 15:11:51 -07:00
Bart House
ed08938ada Fix dangling chain bug.
If a punished player picks up the iron ball, gets engulfed and
saves, then the saved game will have missed saving the dangling
chain since it was not on the floor or in the inventory.  Upon
restoring the saved game, the game will be in a bad state since
the ball will be worn but the chain will be missing.
2019-06-23 21:39:22 -07:00
PatR
87be6fad43 worm segment placement
random_dir() for picking a spot to put a segment of a long worm's tail
(when it is being placed on the map, perhaps after teleport, not when
movement allows it to grow) had mistakes in three of the four compass
directions.  The one for the top of the map was benign; it just
neglected to use the top row (#0).  But it could pick a value off the
edge of the map for bottom and right or both.

This doesn't explain a couple of long worm [segment] oddities on the
Astral level because that level doesn't go all the way to the edge.
2019-06-23 18:48:13 -07:00
PatR
68d28bd748 level overcrowding tweaks
A couple changes dealing with overcrowded levels.  So many monsters
are moving from the Plane of Water to the Astral Plane that the
latter can start out completely full.

Give monsters who trigger the endgame portals a 6/7 chance to not go
through ('home' elementals or any monster carrying the Amulet already
wouldn't go through).  They should learn about magic portal trap in
the process and not voluntarily step on that afterward.

When the Wizard or other covetous monster tries to teleport next to
the hero and fails, he was being sent to limbo.  There's no need for
that; he's already on the map and can just stay where he is.  That
doesn't actually help with the endgame population issue, it just
fixes a couple of uses of mnearto().

I have significant changes for mnearto() and elemental_clog() that
also help with this but will test those more before committing.
2019-06-23 17:27:15 -07:00
PatR
83410a3d4f \#wizidentify bug - 'Not carrying anything.'
when carrying things.  The fuzzer toggled on 'perm_invent' and after
interrupting it I used ^I.  Having 'perm_invent' enabled makes the
inventory code avoid having a totally empty inventory display (by
supplying "Not carrying anything" instead--in the menu rather than
via normal pline) so that interface code will see a change and know
that an update is needed.  But to decide whether the menu was empty,
the inventory code was testing union 'any' field 'a_char' to check
whether some item had used the union (implying that something had
been passed to add_menu()), but wizidentify (^I) uses field 'a_obj'
instead.  Apparently the a_char bits stayed 0 because the menu ended
up with "Not carrying anything" after a list of inventory items.
Switch to a separate variable to track whether anything has been put
into the menu instead of trying to rely on the union.

Unrelated but noticed when checking other "Not carrying anything"
instances, the #adjust command ends early when there's no inventory
but it was asking for a letter to adjust even when the only thing in
inventory was gold in '$' slot, which isn't allowed to be adjusted
away from that slot.  Treat gold-only like no-invent.
2019-06-23 11:31:21 -07:00
PatR
c968f03af3 makemon() and clone_mon()
Express the logic of various early returns more consistently.

clone_mon() wasn't handling mon->isminion correctly.  I'm not sure
whether it is actually possible to clone a minion (maybe after
polymorphing it into a gremlin or blue jelly?).  When it wasn't tame,
which is the case for every minion other than the guardian angel on
Astral, the emin structure wasn't being allocated for the clone but
its isminion flag was left set.

Also, clones inherited mon->mtrack[] so would unnecessarily avoid
moving onto spots the original had recently moved across.

Cloned pets are inheriting various pet-specific fields that they
probably should be starting with a clean slate on but I haven't made
any attempt to address that.
2019-06-22 13:47:35 -07:00
PatR
456996509b fix #H8922 - no "you finish eating" message
after being interrupted and then resuming.  Resuming a multi-turn
food when it only had one bite left was the culprit.
2019-06-22 13:03:50 -07:00
nhmall
eaa8c278c8 code in parse_conf_file() to trim trailing blanks/cr was missing them
Observed on a text file with crlf endings on Linux, where the
so-called blank lines weren't being ignored as they should
have been, despite there being a line to remove \r from the
end.

A pointer was being pre-decremented before the check for a
matching whitespace character.
2019-06-22 00:05:16 -04:00
PatR
2fe57af3f3 fix #H8833 - wishing for "<foo> amulet"
and receiving a random amulet instead of an "amulet of <foo>".
Although the failure to produce the 'right' amulet wasn't a regression
compared to earlier versions as the report indicated, supporting that
wish is straightforward.
2019-06-20 18:42:35 -07:00
PatR
2da552e22f fix #8924 - demonic bribery while hero is deaf
Even though it isn't using verbalize() to make a specific statement,
don't let a demon ask the hero for a bribe when the hero is deaf.

Also, give alternate setup messages in a couple of places where a
divine voice is overriding deafness.
2019-06-20 13:08:47 -07:00
PatR
72afb0d4f6 muse wand/horn feedback for monst zapping at self
Recent commit 5d59b288c9 changed monster
zapping a fire horn at self to cure sliming to not use the wand-zap
feedback routine, but inadvertently did for zaps of wands of fire too.
Use the zap routine for wand and play-instrument routine for horn.
2019-06-20 10:54:59 -07:00
PatR
8bfe6f82f1 Re-do the formatting for help on menu control keys
and add the non-configurable keys:  space, return, and escape.
2019-06-20 02:26:48 -07:00
PatR
3ea0cc1483 fuzzer tweak tweak
Recent fuzzer tweak had an unintended side-effect:  NUL character is
used to indicate a mouse click and we weren't setting up fake value
for one of those.  Go back to avoiding NUL when obtaining a random
value for user's keystroke.
2019-06-20 00:53:45 -07:00
PatR
7e1f020846 curing green slime bit
A recent change to make_slimed() overlooked a different recent change
in how mon->m_ap_type and youmonst.m_ap_type are referenced.  In this
case it had no impact; fix on general principles.
2019-06-18 02:39:45 -07:00
PatR
273662c58c monster overflow on Plane of Air
Make Air behave the same as Earth, Fire, and Water if monsters are
forced off the level for some reason.
2019-06-17 10:09:16 -07:00
PatR
24d6d6b070 fuzzer tweaks
Prevent the fuzzer from randomly toggling the 'silent' option.  If
you use the default value of True then this eliminates most--but not
all--of the beeping that happens when it is running.  I'm not sure
where the remaining beeps are coming from.

Modify the random keystroke selection to implement some bias towards
direction keys that I thought had already been there, plus a higher
chance to entering digits to initiate number responses.
2019-06-17 09:31:01 -07:00
PatR
820320ba55 EDIT_GETLIN when naming monsters and objects
Like #annotate, #name monster, #name individual object, and #name
object type are places where it makes some sense to have an existing
name be the default for the new name, in case taking off from the end
and/or adding to the end is more convenient than retyping everything.

When there is an existing name used as default, clearing that default
and hitting <return> is not enough to remove the name, you still need
to 'assign a new name' of <space> to do that.
2019-06-15 08:19:32 -07:00
PatR
f0633e6541 EDIT_GETLIN vs monpolycontrol
For wizard mode 'monpolycontrol', the getlin() answer buffer for the
"Change <monster> @ <x,y> into what kind of monster?" prompt is also
used to format the coordinate portion of that prompt, so when
EDIT_GETLIN is enabled getlin() was inadvertently given "<x,y>" to use
as default response.  Clear it after the prompt is formatted instead
of via an initializer.  Also, shorten the prompt on the first try:
"Change <monster> @ <x,y> into what?", expanding to the old prompt if
retry is needed.

This also allows specifying 'chameleon' when <monster> is a chameleon,
'doppelganger' when it's a doppelganger, and 'sandestin' when it's one
of those (but not 'doppelganger' when it's a chameleon or sandestin,
and so forth), instead of blanket refusal to accept any non-vampire
shapechanger as the choice.
2019-06-15 04:13:34 -07:00
PatR
a336caf461 do_mname bit
Couple of tweaks I made to do_mname() while investigating the tty
autodescribe wrapping issue.
2019-06-12 18:04:00 -07:00
PatR
cf088d2126 mklev.c formatting and comments
I made these to 3.7.0- and decided to bring them back to 3.6.2+
because of the 'TODO'.
2019-06-11 18:54:32 -07:00
PatR
9ee6e1c839 wizweight vs globs
The wizard mode runtime option 'wizweight' appends an object's weight
to its formatted description, but that was skipped for globs on the
assumption that it had already been included.  But that inclusion only
happens in shops so most globs lacked weight feedback.
2019-06-10 09:52:34 -07:00
PatR
5d59b288c9 muse wand/horn feedback
One of the claims in #H8849 was that a monster which zapped a wand
that the hero had fully identified made hero's knowledge of it revert
to "a wand".  That doesn't happen; it had to have been a different
wand which hadn't been seen up close yet.  But the hero should lose
track of known number of charges if a wand is zapped outside his/her
view.  When implementing that I noticed that a monster playing a fire
horn to burn away slime was using the routine that gives wand
feedback.  Add a separate, similar routine for magical horn feedback.

Half this diff is due to moving a naming support routine from mhitm.c
to do_name.c.
2019-06-10 03:16:52 -07:00
PatR
56d16fc7ee more ^G of "hidden <monster>"
Fix a couple of glitches and add an enchancement.  The monster
attributes structure left the 'hidden' field uninitialized unless user
specified "hidden".  Mimics were being flagged with mon->mundetected
because they pass the is_hider() test but they 'hide' by taking on an
appearance rather than being unseen due to mundetected.  hides_under()
monsters fail the is_hider() test, but can become mundetected if there
is at least one object present.  Eels/other fish are neither is_hider()
nor hides_under() but can be mundetected at water locations.  So alter
'hidden' handling to deal with these various circumstances.

Asking for 'hidden' for any type of creature will result in having its
location be highlighted if it can't be actively seen or detected.  So
using '2000 ^G piranha' will fill up the Plane of Water "normally" but
'2000 ^G hidden piranha' will result in a ton of draw-glyph/delay/
draw-other-glyph/delay sequences and take a painfully long time.  Moral
of the story:  don't combine 'hidden' with a large count unless you
want to spend quite a while watching the level's fill pattern.  Turning
off the 'sparkle' option will cut the flashing in half but still take
a long time.  If you really need to fill a level with hidden creatures
and can't bear the flashing/highlighting, use blessed potion of monster
detection or #wizintrinsics to have extended detect.  Then all created
monsters will be seen so none will trigger location highlighting.

If you create a 'stalker' or 'invisible stalker' or 'invisible <other-
mon>' its location won't be highlighted, but for 'hidden stalker' or
'hidden invisible stalker' or 'hidden invisible <other-mon>' it will
(provided you don't actually see it due to See_invisible or sensemon()).
2019-06-09 06:11:09 -07:00
nhmall
f1f085c7fd display effect bits 2019-06-09 08:08:50 -04:00
nhmall
5f676aa56c extend wizard-mode display effect to unseen invisible monsters 2019-06-09 07:46:14 -04:00
nhmall
8a82a67d41 overlooked rn2_on_display_rng bit 2019-06-09 07:41:11 -04:00
nhmall
54d24d0333 make display effect code reusable and move it to display.c 2019-06-08 23:19:29 -04:00
nhmall
ea9a385d67 fixes entry and a display effect related to is_hider wishing 2019-06-08 22:40:51 -04:00
nhmall
15fa1f0ac7 debug mode wishing for hidden hiders 2019-06-08 21:54:06 -04:00
PatR
7ea69225e9 fix github issue #198 - mon wielding cursed weapon
Fixes #198

Watching a monster try to switch from a cursed weapon to some other
weapon (of any bless/curse state) reported that the old weapon was
welded to the monster's hand and wouldn't switch to the new one.
But watching a monster try to wield a cursed weapon didn't say that
it was becoming welded at the time.  Report correctly pointed out
that the weld-to-hand check wouldn't work unless the weapon was
already flagged as wielded, and the code in question was deferring
wielding so that the message wouldn't include "(weapon in hand)" in
the formatted object description.  There was also another problem:
it was erroneously testing the monster's old weapon (if any, after
unwielding it), instead of the new one being wielded.

Also, Sunsword starting to emit light when first wielded by a monster
only reported that it was shining if hero could see the monster.
Give an alternate message if hero sees the location instead.  (Just
the monster's/Sunsword's location rather than any newly lit spot
within Sunsword's radius.)
2019-06-08 05:58:42 -07:00
PatR
c741d6c7c9 missile light sources
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.
2019-06-08 04:50:40 -07:00
PatR
fabfe276fe \#turn comment
Remove a potential 'TODO' since it turned out [pun intended] to be a
no-op.
2019-06-06 13:30:43 -07:00
PatR
f4353a3c15 \#turn mechanics
When looking at something else I stumbled across this.  Using #turn
is described as chanting a formula but was allowed even if hero wasn't
able to speak due to strangulation or speechless polymorph form.
Also, the check for whether a potential target monster was in range
used 'cansee(mx,my)' which required the hero to be able to see but
not necessarily to be able to see the target.  I've changed that to
'couldsee(mx,my)' on the assumption that it was intended to prevent
\#turn from operating through walls.

Also, the comment about the effective range was wrong.  I changed the
comment to match the code rather than vice versa.
2019-06-05 18:36:55 -07:00
PatR
b982e6c526 location viability on Plane of Water
While testing, I noticed that I could completely fill the Water level
with air elementals.

Hero can't fly or levitate or water walk into/onto water locations
on Water level without drowning/crawling out the water, and monsters
shouldn't have been able to but could, then they were hit by drowning
since minliquid used different criteria than movement.  But goodpos(),
used for teleport destination and new monster creation among other
things, consided water locations acceptable on that level for
non-aquadic creatures with Fly/Lev/Wwalk ability.

It explains why so many dragons and other 'nasty' monsters have been
ending up on the vanquished monsters list when hero uses level
teleport to go directly there from level 1.  They've either been
getting created in water and then they drown when it's their turn to
move or moving into it to approach the hero and drowning (not sure
whether that case is immediate or on next move).  There's no message
since hero doesn't see it, and air elementals didn't drown since thy
don't breathe.
2019-06-05 04:16:34 -07:00