From 6ac1105fc7ca2e2f9bad767ce60eddae6dc42528 Mon Sep 17 00:00:00 2001 From: alexpolo1 Date: Thu, 27 Aug 2026 20:17:38 +0200 Subject: [PATCH] fix(merc): always dismiss the panel the merc check opens (CHRONICLE stayed up all game) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- CLAUDE.md | 32 ++++++++++++++++++++++++++++++++ src/bot.py | 12 ++++++++++++ 2 files changed, 44 insertions(+) diff --git a/CLAUDE.md b/CLAUDE.md index b1fc206..8b571ef 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -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>"` diff --git a/src/bot.py b/src/bot.py index e9dce12..ab7a74d 100644 --- a/src/bot.py +++ b/src/bot.py @@ -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: