fix(merc): always dismiss the panel the merc check opens (CHRONICLE stayed up all game)

resurrect_merc confirms a live merc by pressing 'o' and looking for MercPanelText, then
closed the panel ONLY when that check passed:

    keyboard.send("o")
    merc_panel_open = is_visible(ScreenObjects.MercPanelText)
    if merc_panel_open:
        keyboard.send("o")     # the only path that closed anything

On this client 'o' (skill slot 54) opens the CHRONICLE collection panel, not the merc panel.
MercPanelText never matched, the closing keypress was never sent, and Chronicle stayed open
for the rest of the game — a large centred panel that blanks every later template match. The
run then died on click_red_portal after ~66s of clicking at a covered screen.

The health manager's guard did not catch it either: it looks for LeftPanel/RightPanel, and
Chronicle is centred and matches neither.

Fix: always dismiss whatever appeared. When MercPanelText is absent, send esc, then re-check
LeftPanel/RightPanel and esc again if something is still up.

Diagnosed straight from the new FAIL> record, which named the culprit without any log
archaeology:

    FAIL> g90 r83 | at=False | step=resurrect_merc | shot=...
    FAIL> g90 r83 | trail: town.repair(12s) > town.maintenance(18s) > run.approach!(66s)

The step named in the failure reason was click_red_portal; the step that actually caused it
was resurrect_merc, three entries earlier in the trail. That is exactly the case the trail
was added for.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
alexpolo1
2026-08-27 20:17:38 +02:00
parent 4de8f6192e
commit 6ac1105fc7
2 changed files with 44 additions and 0 deletions

View File

@@ -662,6 +662,38 @@ Note `NAME_TAG_THRESHOLD = 0.26` (the hover path, line ~289) is deliberately muc
was NOT changed — Akara genuinely hovers at ~0.28 (Bug 3). The two thresholds serve different
paths; don't unify them.
### Bug 31: merc panel check left the CHRONICLE panel open for the whole game (2026-08-27)
**File:** `src/bot.py` — `on_maintenance()`, merc-alive confirmation
`resurrect_merc` confirms a live merc by pressing `o` and looking for `MercPanelText`. It
then closed the panel **only when that check passed**:
```python
keyboard.send("o")
merc_panel_open = is_visible(ScreenObjects.MercPanelText)
if merc_panel_open:
keyboard.send("o") # the ONLY path that closed anything
```
On this client `o` (skill slot 54) opens the **CHRONICLE** collection panel, not the merc
panel. So `MercPanelText` never matched, the closing keypress was never sent, and Chronicle
stayed open for the rest of the game — a large centred panel that blanks every subsequent
template match. The run then died on `click_red_portal` after ~66s of clicking at a covered
screen.
**Why nothing caught it:** the health manager's panel guard looks for `LeftPanel` /
`RightPanel`. Chronicle is centred and matches neither, so it was never auto-escaped.
**Fix:** always dismiss whatever appeared. If `MercPanelText` is not found, send `esc`, then
re-check `LeftPanel`/`RightPanel` and send `esc` again if something is still up.
**The general rule:** *any* keypress that may open a panel must be paired with an
unconditional dismiss. Closing only on the happy path leaves the UI wedged on every other
path — and here that cost a whole run each time.
**Symptom to grep for:** `FAIL>` records showing `step=resurrect_merc` followed by
`run.approach!` with a long duration, or an error screenshot with a UI panel covering the map.
---
## The run timeline — `grep "TL>"`

View File

@@ -974,6 +974,18 @@ class Bot:
keyboard.send("o")
wait(0.2, 0.3)
merc_visible = True
else:
# 'o' opened SOMETHING that is not the merc panel and nothing closed it.
# On this client it opens the CHRONICLE collection panel, which covers
# the screen and blanks every later template match — the run then dies
# on click_red_portal after ~66s of flailing at a covered screen
# (g90 2026-08-27). Always dismiss whatever appeared, then confirm.
keyboard.send("esc")
wait(0.25, 0.35)
if is_visible(ScreenObjects.LeftPanel) or is_visible(ScreenObjects.RightPanel):
Logger.warning("Merc check: a panel is still open after esc — sending esc again")
keyboard.send("esc")
wait(0.25, 0.35)
gs = self._game_stats
skip_until = getattr(gs, "_merc_resurrect_skip_until", 0)
if not merc_visible and gs._game_counter < skip_until: