Report #H9243 misinterpreted W_WEAPON as W_WEP and attributed a
hypothetical ball and chain sanity checking problem to that.
Rename the former to W_WEAPONS to emphasize that it includes
alternate/secondary weapon and quivered stack as well as wielded
weapon.
A couple of early returns could result in temporary windows getting
left around instead of being released for re-use, which in turn might
lead to a panic due to lack of available window slots. The first
one is accompanied by an 'impossible' warning which no one has ever
reported and the second one could only happen if data file 'keyhelp'
was missing, so panic due to either of these is hypothetical as far
as released versions go. Somebody making modifications could run
afoul of either of them though.
query_category() - switch from early return to 'goto' so that the
temporary window used for a menu will always be destroyed;
whatdoes_help() - defer creating the display window until after the
data file has been successfully opened so that early return won't
need any window cleanup.
The pull request #226 commentary follows:
One major limitation of the autopickup exception system is that you can't
define an exception from an exception, despite both menucolors and msgtypes
prioritizing rules based on the order they are defined in .nethackrc. This
is because the "always pickup" and "never pickup" exceptions are tracked in
different lists, and at runtime, when the player steps over an object, the
game checks these lists seperately, with "never pickup" taking precedence.
This means that if you want to pick up some but not all items matching a
given expression, you may need to write a long and kludgy list of regexes
to get the behavior you want.
I've edited the autopickup exception code to remove this necessity: now
the exceptions are stored in one list, and conflicts between them are
resolved based on their relative position in that list. Whether an
exception was inclusive or exclusive was already tracked individually;
I don't know why they were stored separately in the first place. This
edit makes the system both more convenient and more consistent with the
semantics of menucolors and msgtypes.
With these changes, the 33 autopickup exception rules in the wiki article
linked above may be replaced with the following 7 much simpler rules for
the exact same effect:
AUTOPICKUP_EXCEPTION=">.* corpse.*"
AUTOPICKUP_EXCEPTION="<.* newt corpse.*"
AUTOPICKUP_EXCEPTION="<.* lichen corpse.*"
AUTOPICKUP_EXCEPTION="<.* lizard corpse.*"
AUTOPICKUP_EXCEPTION="<.* floating eye corpse.*"
AUTOPICKUP_EXCEPTION="<.* wraith corpse.*
AUTOPICKUP_EXCEPTION=">.*\>.*"
closes#226
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.
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).
Changing an inventory item's bknown flag wasn't followed by a call to
update_inventory() in many circumstances, so information which should
have appeared wasn't showing up until some other event triggered an
update.
Unfreed memory noticed after interrupting the fuzzer and quitting.
query_objlist() has an early return--for touching a cockatrice
corpse--that was skipping release of sortloot info (an array with
one element per object from whichever object list was being used).
Some formatting that's been sitting around for a while got mixed in
and I decided not to take that back out.
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).
Dropping an existing fragile item while levitating will usually
break it. Getting a new wished-for fragile item and dropping it
because of fumbling or overfull inventory never would.
Some callers of hold_another_object() held on to its return value,
others discarded that. That return value was unsafe if the item
was dropped and fell down a hole (or broke [after this change]).
Return Null if we can't be sure of the value, and make sure all
callers are prepared to deal with Null.
Fixes#163Fixes#153
Encumbrance calculations for taking things out of a bag of holding
where subject to rounding issues due to integer division. This may
improve things, although I think taking out a partial stack might not
be much better than before.
I simplified the contributed code, then decided that it wasn't an
improvement. In the process of switching back and forth I may have
introduced bugs which weren't present originally.
If hero was carrying Schroedinger's Box at end of game, disclosing
inventory converted it into an ordinary box. That interferred with
subsequent disclosure when writing DUMPLOG, which saw an empty box
if inventory had been shown or the special box with newly-determined
contents if not. I tried a couple of ways to fix it and decided
that redoing it was better in the long run.
Schroedinger's box is still flagged with box->spe = 1, but instead
of having that affect the box's weight, now there is always a cat
corpse in the box. When opened, that will already be in place for
a dead cat or be discarded for a live one, but the weight will be
standard for container+contents and when box->cknown is set it will
always be "containing 1 item" (which might turn out to be a monster).
Some temporary code fixes up old save/bones files to stay compatible.
TODO: food detection used to skip Schroedinger's Box; now it will
always find a corpse, so some fixup like the ridiculous probing code
is needed.
Followup to 'fix #148' patch: looting a container with menustyle:Full
wasn't offering a chance to remove everything in one go. That was due
to an error I introuduced 2.5 years ago with commit
529dad8ef1 when I changed how the flags
passed to query_category() were being set up. It accidentally switched
'A' from take-out to put-in but the only code to handle 'A' at that
time would take everything out (from container to inventory).
Prior to that, removing everything worked as intended and putting in
everything wasn't supported. Now 'A - autoselect all' is a viable
choice for both in and out.
Fixes#154
With menustyle:Full, picking 'A - autoselect all' when putting items
into a container ran code for taking things out and there wasn't any
corresponding code for putting things in.
Add some put-in-everything code. Taking things out doesn't offer
'A - autoselect all' as a choice so the code mentioned above may now
be dead. Taking everything out seems like something that's much more
likely to be desired than putting everything in.
Yesterday's sortloot() overhaul didn't include some cockatrice corpse
handling for pickup. If there's an object class filter in place and
pickup has been told to care about cockatrice corpses, have sortloot()
include them in the loot array even if food class isn't accepted by
the filter. In the pre-sortloot days, and in 3.6.[01] which didn't
attempt to deliver a filtered subset of loot, the check for such
corpses was done before pickup checks the filter. They need to be in
the loot array to retain the same behavior.
H7205 - full-pack identify might skip items if perm_invent is on
because updating the inventory window might reorder 'invent'
while the identify code is in the midst of traversing it;
H7120 - pickup that doesn't pick anything up can change the glyph
shown on the map because the pile might be reordered such
that a different item is on top;
H5216 - performing a sortloot operation on a pile and then switching
back to sortloot:none doesn't restore pile's original order.
The 'revamp' that changed the contributed sortloot feature to switch
to simpler usage (object list itself was sorted rather than having a
parallel array that needed to be constructed, sorted, traversed, and
discarded) turns out to have too many problems. This reverts to a
hybrid solution that constructs an array for traversal, leaving the
linked list in its original order, but hides most of the details of
that from sortloot() callers. The 'revamp' benefit of being able to
use normal list traversal is lost, as is the potential to skip
sorting when the list turns out to already be in the desired order.
This could stand to have a lot more testing than it's had so far.
Mentioned in the newsgroup: picked up items have stopped merging with
compatible stacks in inventory.
The commit 0c51555849 by me on January 5
|
| fix #H6713 - unpaid_cost: object not on any bill
|
| Stealing a shop object from outside the shop with a grappling hook
| would result in that item being left marked 'unpaid' after the shop's
| bill was treated as being bought and not yet paid for. This led to
| "unpaid_cost: object wasn't on any bill" every time inventory was
| examined. The problem was caused by handling the shop robbery after
| removing the object from the floor but before adding it to inventory,
| so it couldn't be found to have its unpaid bit cleared.
|
inadvertently caused that. The effect was actually deliberate but it
wasn't intended to be so widespread. Handle extract/bill/addinv/rob
sequencing differently instead of overriding inventory merging.
Stealing a shop object from outside the shop with a grappling hook
would result in that item being left marked 'unpaid' after the shop's
bill was treated as being bought and not yet paid for. This led to
"unpaid_cost: object wasn't on any bill" every time inventory was
examined. The problem was caused by handling the shop robbery after
removing the object from the floor but before adding it to inventory,
so it couldn't be found to have its unpaid bit cleared.
When investigating this I came across a more severe bug: if the hero
had never entered the shop, the shopkeeper's bill wasn't initialized
properly and add_one_tobill() could crash while attempting to execute
bp->bo_id = obj->o_id;
because 'bp' was Null.
Poly'd into a giant with a full inventory that already contains at
least one boulder, moving onto a boulder (that can't be pushed due
to a wall or other obstacle) yielded
You try to move the boulder, but in vain.
However, you can easily pick it up.
You are carrying too much stuff to pick up another boulder.
You see here a boulder.
The second and third statements contradict each other. Make the
code that dishes out the second message smarter. If autopickup is
set for it and you will pick up the boulder:
However, you easily pick it up.
If autopickup is not set for it but would have worked if it was:
However, you could easily pick it up.
If your inventory is full and you have a boulder (or are in Sokoban)
However, you easily push it aside.
That last one is instead of "however, you can squeeze yourself into
a small opening" that you'd get if not a giant and not carrying much.
Reported directly to the devteam. Set hilite_pile on, become
invisible, pick up all but one item from a pile on the floor,
the pile symbol was still there afterwards.
This is yet another case of evil hack, because the gbuf doesn't
distinguish between object piles and single items, see
commit 854fe40609
Add support for filtering by unpaid status for container-in and
container-out actions. When taking out of a container, it works as
expected if you're carrying the container while in a shop, but won't
find any unpaid items if the container is on the floor. That's
because they're only flagged as unpaid while in the hero's inventory.
(And when it doesn't find any unpaid items it won't list 'unpaid' as
a category of item to manipulate, so while that might be suboptimal
for taking items out of shop containers, it shouldn't be a problem.
Typically all the contents are shop-owned anyway, so using unpaid as
a filter wouldn't gain any advantage over just taking stuff out.)
The different menustyle settings have been offering different degrees
of support for BUCX filtering:
Full : multi-drop, container-in, container-out
Trad, Combo: multi-drop
Partial : none (to be expected; it explicitly jumps past class
filtering, where BUCX gets handled, to a menu of all objects)
This adds pickup, container-in, container-out, multi-unwear/unwield,
and object-ID for Trad and Combo, and multi-unwear/unwield for Full.
(Full behaves like Partial for pickup--not sure why--and for object-ID,
bypassing filters to go straight to a menu of all applicable items.)
There are probably several new bugs--this stuff is very convoluted....
Report #5426 was classified as not-a-bug, but the underlying issue
can be improved.
For item selection where BUCX (bless/curse state) filtering is
supported (mostly for menustyle:Full, but there are a few actions
where Traditional and Combination handle BUCX too), 3.4.3 took the
union of object class and bless/curse state (so ?!B gave all scrolls
and all potions and every blessed item from other classes) but 3.6.0
changed that to the intersection (so ?!B gives blessed scrolls and
blessed potions, period). Since gold is inherently not blessed or
cursed it has been getting excluded during intersection handling
when that includes BUCX filtering. Report #5426 was from a player
who was used to choosing $X when putting newly acquired loot into a
container asking to have the old behavior reinstated.
The ideal fix would be to support both union ($ | X) and intersection
(?! & B), but implementation would be bug prone and the interface,
especially when done for menus, would be cumbersome. Instead, this
adds new boolean option, goldX, to allow the player to decide whether
gold is classified as uncursed--even though it is never described as
such--or unknown. The new-loot-into-container issued can be solved
either via $abcX, where abc lists all classes that have any X items
(when gold is included as one of the classes, its BUCX state is now
ignored for the current selection), or by setting the goldX option
and then just picking X for the types of items to put into the
container (or drop or whatever other action supports BUCX filtering).
The situations where menustyle:Full allows BUCX filtering during
object class specification and styles Traditional and Combination
don't should to be fixed (by extending BUCX support to Traditional
and Combination rather than removing it from Full, obviously).
Autopickup for pickup_types is disabled for unpaid shop goods, but
always-pick-up autopickup_exception still picked things up, as did
pickup_thrown for thrown objects. Now they'll only work in shops
for no_charge items (dropped by hero and shk didn't want, or hero
declined to sell).
costly_spot() was being recalculated for every item which passed
pickup_types. This changes autopickup to check it once for a given
autopickup operation and cache the result. [Whenever the hero moves,
a room entry check is performed. That ought to be extended to cache
costly_spot() for <u.ux,u.uy> in iflags or u.]
The #tip command tries to reduce verbosity by formatting drop messages
with just the object name instead of with full sentences, yielding
Objects spill out: obj1, obj2, obj3, ..., objN.
where the trailing comma or period is included with each successive
object. If an intervening message occurs, such "25 zorkmids are
added to your credit", the rest of the objects will no longer be
extending the original sentence and end up looking silly.
Objects spill out: obj1, obj2,--More--
25 zorkmids are added to your credit. obj3, ..., objN.
This fix causes the post-interruption messages to revert to verbose
format.
Objects spill out: obj1, obj2,--More--
25 zorkmids are added to your credit.--More--
obj3 drops to the floor.--More--
...
objN drops to the floor.
The interrupting message still follows the comma of the partial
sentence, but I don't see any sane way to fix that other than to
abandon the terse format altogether, and doing that makes #tip way
too verbose when the container has a lot of items in it. But #tip
inside shops now does that, since there will always be buy/not-
interested feedback interrupting the terse format in that situation.
For other situations, a full sentence message might end up following
a partial sentence list of dropped items.
There was a more significant bug. Dropping a hero-owned container
with gold in it onto shop floor sold the gold to shk, giving hero
credit. Subsequent #tip gave the hero credit for that same gold
when it spilled out. addtobill(obj) relies on obj->ox,oy to
determine whether events are taking place in a shop, and #tip was
relying on placement onto floor to set those, too late for shop
billing. The fix yields suboptimal results: you're given credit
when you drop the container, then during #tip when you spill the
contents, credit for the gold is removed, then new credit for it
is given. That's down to shop insanity, not tipping behavior.
Previous fix was 'me' to eat from inventory without checking current
location for edible items. The report describing the need for that
also mentioned that you could #loot while blind and without gloves
and not touch any objects except for the container you pick to loot.
This adds a corpse touch check, plus `m#loot' to skip floor containers
and go directly to using #loot for adjacent saddled creature. That,
as well as the open command, will reveal adjacent container in some
circumstances but I'm going to pretend that that doesn't matter.
doloot() has turned into spaghetti. We should probably add #unsaddle
or something of the sort and return #loot to container-access only.