Resolves the 11 conflicting files blocking PR #41. Where both branches fixed
the same problem, the fixes are combined rather than one side dropped:
- a5.py: main's dual WP templates + require_visible pre-scan, bounded by
baalxp's town_world ROI (excludes the HUD band and party column)
- pindle.py: main's removal of the town-false-positive "already in temple"
shortcut (also dropped baalxp's post-nudge copy of it); kept baalxp's nudge,
click tuning and PORTAL_APPROACH node; main's detect-act retry
- town_manager.py: main's act-margin check in wait_for_town_spawn, then
baalxp's marker->location resolution; baalxp's in_act repair skip before
main's repair_npc destination table
- bot.py: baalxp's restructured leech cycle, with main's death recovery and
InGame miss tolerance ported into _baal_xp_hide_and_wait
- game_browser.py, skill_preflight.py, [hammerdin] binds: baalxp (lobby join
flow; binds verified against the live client 2026-09-04)
- params.ini: baalxp's "leech stays out of order=" rule with order=run_trav
- CLAUDE.md: both bug writeups kept; baalxp's 23-25 renumbered to 32-34 since
tests/docs reference main's numbering
- test_stealth_config.py: AFK-break invariant exempts the whole baal_xp block
instead of a 6-line window (the branch grew several handoffs)
Tests: 272 passed. Remaining failures are pre-existing on origin/main
(gems-tab transmute test, smoke_test/test_version_consistency collection).
Co-Authored-By: Claude Opus 5 <[email protected]>
The state list was missing baal_xp (and cold_plains) even though the
route has been in bot.py since August. One short paragraph on how the
cycle works, since it deliberately bypasses the run_wrapper pattern.
run_pindle had a 100% failure rate, and worse, was reporting success while doing
nothing. Five root causes, found by recording the client and replaying the pather's
own matching against the captured failure frames.
1. a5_red_portal.png was the only MASKED template in a5_town/ (4-chan, 60.9% opaque)
because a hover tooltip had been baked into the capture and hidden with alpha.
That routed it to cv2.matchTemplate(TM_CCOEFF_NORMED, mask=...), which OpenCV only
supports for TM_SQDIFF/TM_CCORR_NORMED — hence 0.50-0.60 scores and match positions
that wandered onto unrelated scenery. Recaptured as a plain 3-channel opaque crop of
the portal's upper arch (the lower ring is occluded by branches).
Present 0.949-1.000 / absent 0.398-0.514, straddling the 0.68 threshold.
2. pindle.approach() opened with an "already in Pindle area?" shortcut. Harrogath
scenery scores 0.76-0.79 on PINDLE_7, over its 0.62 bar, so it fired in town and
returned A5_PINDLE_START without ever clicking the portal — the bot "killed Pindle"
in town for five straight games with zero loot and zero XP while logging
runs_failed_total: 0. Shortcut removed; entry is proven by the loading screen.
3. pather.find_abs_node_pos fell back to a 0.55 first-match search that fabricated node
positions (A5_TOWN_1 at 0.60-0.62 on scenery, three different frames, three different
phantom positions), steering the char into the town wall. Raised to 0.62, forced
best_match, and added a per-node heading gate that rejects a low-confidence match
implying a >90 deg reversal. Confident matches are never gated.
4. Walking onto the waypoint opened the WP panel, which health_manager counted toward a
chicken — 3 of 6 games died at full health. WP panels are now escaped without
counting, bounded at 6 attempts.
5. pindle retry re-pathed from a hardcoded A5_TOWN_START; it now verifies the act first.
Verified live: +349,890 XP over baseline, loot drops (Ring, gold), 6 games,
runs_failed_total 0. Docs updated with all four bugs, template asset conventions, and
how to verify a boss run actually killed something (XP delta + loot, never failed:false).
Co-Authored-By: Claude Opus 5 <[email protected]>
- Updated bot behavior to end the game when no TP charges are left, instead of attempting to walk back to town.
- Refined item processing logic in `processing_helpers.py` to use identity checks for item comparisons and improved item removal methods.
- Enhanced game stats logging to include failure reasons and send Discord notifications for failed games.
- Improved health management logic to trigger chicken behavior based on health percentage after rapid rejuvination.
- Added error handling for item pickup failures in `pickit.py` to blacklist items that cannot be picked up.
- Introduced walking fallback nodes for Countess, Andariel, Mephisto, and Baal runs in `pather.py`.
- Implemented path data validation in run scripts for Countess, Andariel, Mephisto, and Baal to ensure paths are correctly defined.
- Enhanced item identification and stash processes in `diablo.py` with retry logic for failures.
- Updated town management to handle identification failures gracefully and log appropriate warnings.
- Improved character selection logic to provide clearer logging messages.
- Modified game restart logic to launch the game via PowerShell for better session handling.
- Added documentation for recording paths for the Countess run and created a PowerShell script for scheduled task management.