Merge pull request #36 from alexpolo1/fix/walk-hud-guard

fix: walk() had the same unguarded HUD click as move()
This commit is contained in:
Alex
2026-08-28 17:04:11 +02:00
committed by GitHub
3 changed files with 45 additions and 2 deletions
+4 -1
View File
@@ -227,7 +227,10 @@ skill_hesitation_max_ms = 300
; Raised to 10 for an overnight run: the budget is rolled at 0.65-1.35x, so 6
; could have stopped the bot after 3.9h and left it idle. 10 guarantees at
; least ~6.5h while keeping the day-to-day variation.
session_budget_h = 10
; Set to 8 for a >= 5h run (2026-08-28). The value is rolled at 0.65-1.35x, so
; session_budget_h=5 would average 5h but could stop after 3.25h. 8 gives a
; 5.2-10.8h window, guaranteeing the 5 hours while keeping day-to-day variation.
session_budget_h = 8
; Small cursor movement during long idles. Between actions the cursor otherwise
; sits exactly where the last click left it.
idle_drift_enabled = 1
+3 -1
View File
@@ -309,7 +309,9 @@ class IChar:
adjust_factor = max(max_wd, min(min_wd, dist - 50)) / max(min_wd, dist)
pos_abs = [int(pos_abs[0] * adjust_factor), int(pos_abs[1] * adjust_factor)]
x, y = convert_abs_to_monitor(pos_abs)
mouse.move(x, y, randomize=5, delay_factor=[factor*0.1, factor*0.14])
# Same HUD guard as move(). walk() had the identical unguarded click.
x, y = self._hud_safe_target((x, y), 5)
mouse.move(x, y, randomize=0, delay_factor=[factor*0.1, factor*0.14])
wait(0.012, 0.02)
if force_move:
keyboard.send(Config().char["force_move"])
+38
View File
@@ -108,3 +108,41 @@ def test_move_clicks_with_randomization_disabled():
f"move() still randomizes after the guard, which can re-enter "
f"the HUD: {line.strip()}"
)
def test_every_movement_click_in_ichar_is_guarded():
"""Scope the invariant to every MOVEMENT method, not one of them.
The first version of this guard covered move(), and its tests asserted only
on move(). walk() carried the identical unguarded click and was missed it
is reached from bot.py's walk-back-to-town path and from poison_necro, so it
was a live second route to the same loot-filter toggle.
Only movement clicks may be relocated. Clicks that must land on a specific
thing are deliberately excluded, because moving them breaks what they do:
pick_up_item must hit the item itself
_remap_skill_hotkey deliberately clicks the UI
cast_in_arc aims a cast direction, not a destination
"""
import inspect
from char.i_char import IChar
MOVEMENT = ("move", "walk")
offenders = []
for name in MOVEMENT:
fn = getattr(IChar, name, None)
if fn is None:
continue
src = inspect.getsource(fn)
body = chr(10).join(l for l in src.splitlines() if not l.strip().startswith("#"))
parts = body.split('"""')
body = parts[0] + "".join(parts[2:]) if len(parts) > 2 else parts[0]
for line in body.splitlines():
if "mouse.move(" in line and "randomize=0" not in line:
offenders.append(f"{name}: {line.strip()}")
assert not offenders, (
"movement clicks that can land on the HUD (must go through "
"_hud_safe_target then move with randomize=0): " + "; ".join(offenders)
)