fix(inventory): stash protected items instead of stranding them in the inventory

A charm pickit rejects gets keep=False, but protect_charms_from_sell blocks both
the sell and the drop, and the stash branch only transfers keep==True. The item
could therefore leave the inventory by no route at all: the same 8 charms were
re-hovered, re-OCR'd and re-rejected every game (~12s of town time each cycle),
and every new junk charm picked off the ground joined the set permanently.

_without_protected now flips a blocked item to keep=True so the stash step takes
it, mirroring the recovery inspect_inventory already does per item at the vendor.
bot.py recomputes keep_items after buy_consumables, since it is evaluated before
that call and would otherwise stay stale and skip the stash entirely.

The protection intent is preserved: a misread charm is still never sold or
dropped, it just goes to the stash rather than clogging the inventory.

Co-Authored-By: Claude Opus 5 <[email protected]>
(cherry picked from commit 914d4a911e)
This commit is contained in:
alexpolo1
2026-09-04 13:01:42 +02:00
parent 3ed47ed822
commit 1b3219de3f
2 changed files with 11 additions and 1 deletions
+4
View File
@@ -930,6 +930,10 @@ class Bot:
if self._curr_loc:
items = result_items
sell_items = any([item.sell for item in items]) if items else None
# Recompute: a protected item (e.g. a charm) blocked at the vendor is
# flipped to keep=True so the stash step below picks it up. keep_items
# was computed before this call and would otherwise still be stale.
keep_items = any([item.keep for item in items]) if items else keep_items
Logger.debug(f"Needs: {consumables.get_needs()}")
_step("buy_consumables", "ok", f"at {self._curr_loc} | after: {consumables.get_needs()}")
else:
+7 -1
View File
@@ -462,8 +462,14 @@ def transfer_items(items: list, action: str = "drop", img: np.ndarray = None) ->
safe = []
for item in candidates:
if _is_protected(item):
Logger.warning(f"Blocked {action_name} for protected item: {item.name} at {item.pos}")
Logger.warning(f"Blocked {action_name} for protected item: {item.name} at {item.pos} — marking for stash")
item.sell = False
# Send it to the stash instead of leaving it in limbo. Without this a
# protected item pickit rejected (keep=False) can be neither sold, nor
# dropped, nor stashed (the stash branch only takes keep==True), so it
# sits in the inventory forever and is re-hovered every single game.
# This mirrors the per-item recovery already done by inspect_inventory.
item.keep = True
continue
safe.append(item)
return safe