While running the tutorial, the Save command is disabled. When the
tutorial was extended to two levels, stashing and restoring the
hero's equipment stopped working as intended if player entered the
second level. The attempted fix for that broke re-enabling Save
even if the player left the tutorial without entering its second
level.
This seems to fix things, but I'm flailing around with barely a clue
here. A couple of simpler attempts didn't work and I haven't figured
out why, so this is a bit more complex than what I wanted.
Reorganizing nhl_callback() isn't part of the fix, just avoids use
of some redundant code.
Noticed when testing erodeproof Mitre of Holiness: the cloud of
stinking gas released by Nalzok when he died ending up killing my pet
and my hero got blamed for that. Don't blame--or credit--the hero for
monsters affected by the gas cloud when a dying nemesis produces such.
Issue reported by loggersviii: dipping a container into an uncursed
potion of water mentions water getting into the container. That
happens even when that type of potion hasn't been discovered yet.
Make POT_WATER become discovered if this occurs. Doesn't apply when
hallucinating where a random liquid is mentioned instead of water.
Fixes#1061
Issue reported by vultur-cadens: changing helm of brilliance to
crystal made it stop being classified as "hard helmet" so it gave
less protection against things falling onto the hero's head.
Change the is_metallic() tests used on helmets to new hard_helmet().
Unlike when thrown, crystal helmets don't break when objects fall
on them.
Fixes#1060
Issue reported by AndrioCelos: if you arrived at the Wine Cellar
variation of Mines' End by falling or by level teleportion instead
of via the stairs, you could end up in the treasure chamber. If
you lacked a way to dig or to level teleport, you would be stuck.
Since most of that level is undiggable, it would likely fill up with
monsters before one that could dig would appear close enough to dig
to you and you'd eventually starve.
The initial report suggested including an escape item in the treasure
chamber. This adds a teleport region to control hero's arrival spot
instead. There was a suggestion fix things this way from copperwater
but I didn't notice that until I had already chosen this method....
Fixes#1025
Noticed while considering the pull request about loosening
restrictions on trap creation at furniture locations. If you wish
for a terrain feature while on a fountain or sink, the counters
used to control whether sounds for those should be given will be
off by one.
It was incrementing the appropriate counter if you wished for a
fountain or sink, but it shouldn't do that if recreating the same
feature (perhaps to reset a magic fountain or looted sink) and it
needed to decrement when replacing either of those with some other
feature. After the count became wrong, if all fountains or sinks
on the level were destroyed, those splashing, gurgling, &c sounds
would continue to be generated periodically.
Add a new debugging option, 'montelecontrol', that allows a wizard-
mode player to choose a teleporting monster's destination. If player
picks a bad spot, confirmation will be requested. If accepted, the
spot will be used even though the consequences could be bad; that's
on the player. If rejected, the destination will be assigned as if
no control had been attempted rather than try again.
The fuzzer isn't allowed to override a bad spot if it tries to pick
one. That would probably trigger a sanity_check warning; the fuzzer
causes impossible warnings to behave as if panic, so accepting a bad
spot would just be fuzzer suicide. It is allowed to randomly set the
option and maybe--though extremely unlikely--randomly pick a valid
controlled destination.
Reported by copperwater "on behalf of Maud": when hero hears an
unseen monster read a not-yet-discovered scroll of create monster
and doesn't see any new monster appear, the player is given a chance
to call the scroll something. When hearing an unseen monster read
a not-yet-discovered scroll of teleportation, the label is revealed
but no such 'call it' opportunity is offered, so the player could
deduce which of the two scroll types it was for either case.
Provide an opportunity to supply a 'called' name for scrolls of
teleportation when heard being read, same as with create monster.
Surprisingly complicated to achieve.
Eliminated a couple of goto's in the process.
Fixes#1046
Reported by Noisytoot: going from level tut-1 to tut-2 returned the
hero's starting equipment too soon, and exiting the tutorial from
tut-2 let the hero keep any equipment acquired within the tutorial.
Entering and leaving the tutorial was being handled by lua code in
the level description of tut-1 and adding a second level messed that
up. I didn't see any way of handing that with level-specific lua
code so I made it become the core's responsibility. gotolevel()
knows when the hero is moving from one dungeon branch to another so
it can recognize entry to or exit from the tutorial easily.
While fixing this, prevent #invoke of the Eye of the Aethiopica from
offering the tutorial as a candidate destination (was feasible if it
had been entered at start of game).
Not fixed: levels visited in the tutorial become part of #overview.
Show location as "Tutorial:1" instead of "Dlvl:1" on status lines.
Only tested with tty; some interfaces handle location themselves and
may need their own fixup for this.
Fixes#1046
Entering a multi-digit count when selecting from a menu in the curses
interface causes the menu to disappear. Report was about putting a
large subset of an object stack into a container but the bug affected
all menus that accepted counts.
curses_get_count() was changed to call core's get_count() quite a
while back. get_count() calls mark_synch() when more that one digit
is typed or when backspace to remove the first digit occurs.
curses_mark_synch() had been a no-op but more recently it was changed
to try to make sure that the screen was up to date. But it did that
by refreshing the persistent windows, making any temporary popup menu
or text window become hidden. Also, the count-in-progress is being
sent to the message window with the no-history flag, so refreshing
the message window removed that too.
Switch curses_mark_synch() to use the basic screen refresh call that
doesn't do anything window-specific. This also changes menu count
handling to have get_count() echo the number starting with the first
digit instead of waiting until the second.
If anything in the menu makes it be very wide it can cover up the
message window and any count being echoed there won't be visible.
I'm not going to try to figure out how to deal with that; it isn't
all that different from the old single-digit/unseen-count behavior.
Reported by vultur-cadens: if Vlad made it to a level which allowed
bones and was in wolf or bat or cloud form when the hero died, he
would not be excluded from the bones file as intended. When those
bones got loaded in another game, Vlad would become flagged as
extinct. If that happened before his own level was reached, he
wouldn't be created when hero arrived thus there would be no way to
acquire the Candelabrum of Invocation. (Even if his vampshifted
form had been carrying it, it wouldn't be present in the bones data
because it would have been converted into candles.)
Fixes#1038
If an monster hides under and object or under water while in view,
say so.
Also, the sanity check for a hidden eel wasn't consistent with the
hiding criteria for it. An eel can't hide on the Plane of Water even
when it's in the water rather than in an air bubble.
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.
Reported by copperwater: entering the tutorial sets 'u.nofollowers',
changing to the tutorial level saves a copy of 'u', post-level change
from entering the tutorial level resets u.followers, but subsequently
changing levels to return to the original level 1 restores 'u' from
the saved copy with has 'u.nofollowers==True', overriding the reset.
Move the nofollowers flag from 'u' to 'iflags'. Invalides save and
bones files.
Fixes#1027
Pull request from saltwaterterrapin: record current move's pending
movement points in save file. They were being thrown away during
save and hero given 12 at time of restore. Hero had to have had at
least 12 in order for player to issue the S command, but might have
had more than that if able to move faster than normal speed.
This implements it differently from the suggested commit. Add new
field umovement to 'struct u' instead of using youmonst.movement and
needing to save and restore that separately.
Invalidates existing save and bones files.
Closes#1024
when applying an object.
Pull request form copperwater: applying a cream pie always uses it up
and applying a lump of royal jelly sometimes uses it up, then after
that use the apply got checked for a talking artifact. If it had been
used up when the apply routine would access memory which had already
been freed.
Closes#1037
Normally when sanity_check is enabled it will take place for every
command executed. Avoid that when the command is ^P because if a
sanity warning is a recurring one and the msg_window setting is
single or combination (tty-only) which shows one message, ^P will
just repeat each new warning without having any chance to cycle back
to earlier messages.
for monsters that haven't died, when being removed from play to keep
them out of bones.
Reported by copperwater: if the quest nemesis was present on a level
being saved as bones, it was removed from the map to keep it out of
the bones level but the quest feedback for nemesis death was given
in the process. Would happen for blessed genocide of "*" too. (It
didn't happen for #wizmakemap and I'm not sure why.)
This was an unintended side-effect of moving some common stuff from
mondead() and mongone() into m_detach(). The quest feedback isn't
actually common to both. Instead of moving that back, pass a flag
that m_detach() can use to determine which routine called it.
Fixes#1029
Don't allow stick/wrap/engulf attacks directed at long worm tails
to succeed. Achieved by making sure that 'notonhead' is up do date
in a bunch of places and utilizing the fairly recent can't-{stick,wrap,
engulf}-unsolid-monsters code.
Should prevent a 'sanity_check' warning about being too far from
u.ustuck that would happen when holding the tail while the head was
not adjacent to the hero.
Also don't let pet ranged attacks from choosing a long worm's tail
as target. They'll still be able to target long worms provided that
the head is lined up and not shielded by tail segment(s).
Extracted from a larger pending commit. While trying to make sure
that bhitpos and notonhead are up to date when attacks are processed,
I noticed that covetous monster handling was buggy. For dist2(),
a value of 1 means adjacent in an orthogonal direction, so testing
for less than 2 unintentionally excluded diagonal adjacency.
Make recently added collect_coords() global even though it is still
only being used in teleport.c.
Add CC_SKIP_INACCS flag to only collect accessible locations so that
there's no need for a custom filter callback or of collecting spots
that will always be rejected when put to use. Caller needs to check
Passes_walls/passes_walls() to decide whether that is suitable.
Merge some of the old safe_teleds() with the new, making it try
randomly 40 times before collecting coordinates for an exhaustive
selection. Prior to the recent change which added collect_coords()
it was trying 400 times and giving up if that didn't find a good spot.
Start using collect_coords() for rloc() as well as for safe_teleds().
Only try to pick a spot randomly 50 times now instead of 1000. If
those all fail, it does an exhaustive search of a randomized list of
candidates instead of old left-to-right, top-to-bottom map traversal.
Has not had nearly as much testing as safe_teleds() underwent.
rloc() was explicilty ignoring map column 1 for some reason. Unlike
reserved column 0, column 1 is part of every level and should be
considered for monster teleport destination even though most levels
don't utilize it.
Monster size affects knockback but it wasn't provided anywhere within
the game. Have wand of probing and stethscope feedback for monsters
include tiny|small|medium|large|huge|gigantic as applicable.
'sanity_check' complains if it finds a boulder in water or lava.
Polymorphig a statue usually produces another statue but might
produce a boulder. If done it water, keeping the boulder intact
would trigger the sanity warning. Break it into rocks if object
polymorph produces a boulder at water or lava location.
While testing the fix for unicorn horn vs blindness, I noticed that
when 'blind from birth' (OPTIONS=blind) you would get "your vision
seems to dim for a moment but is normal now" when timed blindness
was added to persistent blindness. That happened for both 3.6.x and
to-be-3.7. Change it "you have a strange feeling for a moment".
In 3.7, having temporary blindness timeout while permanently blind
produced "your vision seems to brighten for a moment but is normal
now". Change that to strange feeling too. For some reason I haven't
tried to figure out, 3.6.x stayed silent when this took place.
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
Life-saving from being burned up in lava attempts to teleport the
hero to safely. If that fails, hero immediately burns up again.
For fuzz testing, that results in an infinite loop.
While implementing a fix (in done(), not just lava-specific), I
noticed that hangup while running interactively in explore or
wizard mode could be subject to similar effect.
For the fuzzer, if hero dies 15 times without advancing the move
count (not 'moves', the turn count), don't life-save again. With
hangup, don't prompt for "Die?" more than once.
Normal interactive declining to die still works. The more exotic
situations aren't tested.
Knocking a monster into lava triggering impossible warnig "deleting
worn object" for a wooden shield. The monster had to be wearning
flammable armor and be fire resistant to survive instead dying and
dropping inventory, and it couldn't be a creature that can survive at
lava locations like a salamander and the armor needed to already be
thoroughly burnt.
It wasn't hard to figure out what needed to be fixed, but it was very
hard to reproduce the situation in order to verify that fix. The
report was for monster vs monster knockback but I jousted with a lance
instead. I still don't understand why burning up a worn wooden shield
triggered the warning but burning up a worn orcish cloak did not.
Delete engravings made in a breach of a shop's wall or of a vault's
wall or in the guard's temporary corridor when the wall is repaired
or the corridor removed. If 'sanity_check' was On, those would
trigger impossible warning "engraving sanity: illegal surface (x)"
where x was the terrain type code for solid rock or relevant walls.
Adding del_engr_at() calls to the shop code was straightforward.
The vault code is very complicated and I'm not sure that all the
calls I added were actually necessary.
Engraving in an empty doorway and then using locking magic to create
a door there resulted in an impossible warning: "engraving sanity:
illegal surface (23)" if the 'sanity_check' option was On (wizard
mode only). Engraving in an open doorway and then simply closing
the existing door produced the same effect.
Accept engravings at closed doors. Presumably hero will be using
Passes_walls to attempt that so treat closed doors same as open ones.
Update the engraving sanity check to deal with that.
Bonus fix: engraving sanity checking stopped after the first problem
instead of checking every engraving. Have it continue instead.
Not fixed: vault wall repair and temporary corridor removal does
not delete engravings and can trigger the illegal surface warning if
player engraves before the repairs. I didn't test shop wall repair
but it doesn't have any engr references so probably has the same bug.
Avoid impossible warning "breaking odd object?" when throwing a helm
of brilliance causes it to break. Presumably dropping one while
levitating or zapping one of the floor with striking/force bolt would
yield similar result.
While in there, reduce the chance of breakage from 99% to 5% for both
helm of brilliance and crystal plate mail.
The #genocided command was revealing extinct monster species when used
during normal play. That was not intended, so stop. Change to only
reveal them in wizard or explore modes and also during end-of-game
disclosure but suppress them during normal play.
The full description of #genocided is now dynamically updated for '# ?'
during normal play to remove its reference to extinctions. Also, check
for skipping wizard mode commands before doing description searching.
\#genocided was out of alphabetical order in the full commands list.
Both it and #vanquished should have had the GENERALCMD flag; they
don't affect game state.
Change #genocided to use the sort order currently set for #vanquished,
and allow 'm #genocided' to put up the same menu as 'm #vanquished'.
(Not quite the same. Sorting by count of monster deaths isn't
appropriate for listing genocides where an arbitrary number may have
been killed before the genocide occurred. If the preferred order for
vanquished is set that way, alphabetical will be used for genocided.)
Setting the order via menu for either command sets the order for both,
but doing so via #genocided doesn't offer the count-high-to-low and
count-low-to-high choices. During disclosure, you can answer 'a' when
asked whether to disclose genocided and extinct monster types and like
for vanquished monsters, that lets you choose an order at end-of-game.
Doing so won't affect disclosing of vanquished monsters--it'll be too
late for them.
A chunk of this diff is due to moving the #wizborn code out of the
middle of #vanquished handling.
Guidebook.ms has been updated but Guidebook.tex is lagging.
Burying an olog-hai corpse with a boulder resulted in a panic when
its time to revive occurred. I was able to reproduce this once but
failed with "you feel less hassled" several times (using same save
file for multiple tests) so I'm not quite sure what was happening.
A buried corpse was allowed to revive if it was for a zombie. This
fix extends that to auto-revivers (trolls and Riders). The corpse
keeps its revive_mon timer rather than changing that to zombify_mon.
If/when revival of a buried troll or Rider happens while in view, it
will "claw itself out of the ground" like zombies do.
Reported by vultur-cadens: it was possible to encounter ettin zombies
and giant zombies at shallow levels if those levels were generated
with the "buried zombies" theme room.
This uses a simpler fix than the suggestion(s); it's only applicable
to the zombie room though.
Also, vary the zombify_mon timeout. If the hero happened to be in
the room at the time that that expired, they would all claw their way
out of the ground at once. The new variation is quite small so they
still escape burial as a group, but over the span of 21 turns rather
than all on one turn.
Fixes#1016
Reported by copperwater, it was possible for a web to be created
at a water or lava location. It would not be displayed even after
being discovered; showing the terrain superseded showing the trap.
But it functioned normally and could trap the hero. Webs pull the
victim to the floor so hero would drown or burn up on next move
even if the spot had been reached while floating or flying.
A monster spider couldn't survive at a water or lava location, but
a poly'd hero could. Creating a web via #monster or wizard mode
wish could result in it affecting some unsuspecting player via bones.
Disallow creation of webs at water, lava, and air or cloud spots.
(They're already disallowed at furniture spots.)
Fixes#1017
When lastseentyp[x][y] is different from levl[x][y].typ and #terrain
tries to show <x,y>, the value of levl[x][y].flags might not have an
approrpriate value for the remembered terrain type. The reported
problem was an impossible() about wall mode.
rm.wall_info == 4 corresponds to rm.doormask == D_OPEN and both of
them are overloaded on rm.flags. A spot remembered as a wall but
actually a secret door might cause this if it has become discovered
('wall' changed to closed door) and then opened (with door intact)
while out of view. [I'm not sure how that could happen though.]
I was unable to reproduce it so haven't verified that the fix works.
Reported directly to devteam: a fake player monster was petrified
and when creating its statue yielded "Calculating weight of 0 gold
pieces?".
Fake player monsters on the Astral Plane level were being created
with rn2(1000) gold pieces so had a 1 in 1000 chance of that being 0.
Gold gets created with a non-zero amount but the routine that gives
it to a monster sets the amount to the requested value. That didn't
update the weight so didn't notice the 0. Putting it into a container
(the statue) did recalculate the weight and did notice.
There was a choice between forcing a non-zero amount or allowing 0
and bypassing its creation and placement in monster's inventory.
I went with the latter.
Discussed a long time ago, change helm of brilliance from iron to
crystal so that it doesn't need to be a special case for metallic
armor's affect on spell casting. It now has a fixed description of
"crystal helmet" but is not pre-discovered.
Add new helm of caution to retain the "etched helmet" description
among the shuffled helms. Wearing it confers the Warning attribute.
That's fairly lame but not necessarily useless. It's iron and gets
half the former probability for a random piece of armor being helm
of brilliance so is not likely to be popular.
Helm of caution keeps the old helm of brilliance tile and new helm
of brilliance is basically the same image with different color and
pointed on the top.
Not changed: the etched helmet was marked as green and is drawn
that way for text but the tile doesn't actually use green for it.
Crystal helmet started as hi_glass (rendered as 'bright cyan') but
has been changed to clr_white to match crystal plate mail.
Old save and bones files are invalidated.
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.
pline() already skips sprintf/vsnprintf if the format doesn't contain
any percent signs. Do the same if the entire format is "%s".
Also, if ESC is used to suppress messages for the rest of the current
move, the text for any impossible warnings issued during that time
would be suppressed too so not be seen.
Noticed when working on the add_menu() crash earlier, using a mouse
rather than the keyboard to pick an entry in the sub-sub menus for
'm O' -> 'disclose' -> {any disclosure category} didn't work properly.
The problem was in post-3.6.x menu code for the Qt interface.