A site can be paired with a bank it cannot walk to #243

Closed
opened 2026-08-19 02:09:09 +00:00 by sickday · 1 comment
Owner

Bot.Sites pairs a gathering site with the nearest bank by chebyshev/2
inside the same map area, and nearest-by-distance is not the same question as
can a bot walk there. A bank sealed in a small room is caught now; a bank on
the far side of a river or a gate is not.

Measured

A net fisher spawned at the Lumbridge-side spot {0, 3239, 3145}, whose
derived bank is Al Kharid at {0, 3269, 3164} — 30 tiles by chebyshev/2,
and on the other side of the river:

World.Movement.route(flags, {3260, 3166}, {3239, 3145}) => []

Nothing walkable connects them: crossing wants the toll gate, which the route
planner will not open. The bot failed its leg five times, Bot.Travel.recover/2
relocated it to a bank, and it spent roughly ninety seconds cycling before it
happened to re-roll a ground on its own side of the water and carried on.

What already covers half of it

Bot.Sites.enclosure/1 (added with the bank-stand fix) runs a bounded
3,000-tile fill from each bank's stand at derivation. A fill that saturates is
the open world and pairs with anything; one that stops short is a pocket, and
only a site standing inside it may have that bank. That catches the Cooking
Guild — fourteen tiles behind a door — and twenty-four others.

It cannot catch this one. The fill saturates on both banks of a river, so
both sides look like the same open world to it. The rule is "not shut in a
small room", not "reachable from here".

What would actually answer it

Connectivity between the site and the bank, which is a component identity
rather than a distance. Ideas, cheapest first:

  • Label connected components once at boot and pair only within a label. One
    pass over the collision map, and every consumer gets it — including
    nearest_bank/1, which is asked at runtime and today can still hand a
    wedged bot a bank across a river.
  • Or keep the fill but seed it from the site and stop at the first bank
    found, accepting a bounded search per site (~900 of them at derivation).

Both want a decision about doors: a gate a bot could open makes two components
one, and nothing opens a door out in the open world today —
Bot.Obstacle.between/2 asks whether the bot is shut in rather than whether
the destination is, so outside a sealed region the fill hits its budget,
answers not shut in, and no door is ever tried. Whatever labels components
has to say what it assumes about doors.

Sites whose only bank in range is unreachable are worked and then abandoned,
which reads as a bot that wandered off. The wedge is survivable — the goal
re-rolls a ground eventually — but it burns a recovery relocation each time,
and Bot.Travel.recover/2 relocating into a place it cannot leave is its own
hazard.

`Bot.Sites` pairs a gathering site with the nearest bank by `chebyshev/2` inside the same map area, and nearest-by-distance is not the same question as *can a bot walk there*. A bank sealed in a small room is caught now; a bank on the far side of a river or a gate is not. ## Measured A net fisher spawned at the Lumbridge-side spot `{0, 3239, 3145}`, whose derived bank is Al Kharid at `{0, 3269, 3164}` — 30 tiles by `chebyshev/2`, and on the **other side of the river**: World.Movement.route(flags, {3260, 3166}, {3239, 3145}) => [] Nothing walkable connects them: crossing wants the toll gate, which the route planner will not open. The bot failed its leg five times, `Bot.Travel.recover/2` relocated it to a bank, and it spent roughly ninety seconds cycling before it happened to re-roll a ground on its own side of the water and carried on. ## What already covers half of it `Bot.Sites.enclosure/1` (added with the bank-stand fix) runs a bounded 3,000-tile fill from each bank's stand at derivation. A fill that saturates is the open world and pairs with anything; one that stops short is a pocket, and only a site standing inside it may have that bank. That catches the Cooking Guild — fourteen tiles behind a door — and twenty-four others. It cannot catch this one. The fill saturates on **both** banks of a river, so both sides look like the same open world to it. The rule is "not shut in a small room", not "reachable from here". ## What would actually answer it Connectivity between the site and the bank, which is a component identity rather than a distance. Ideas, cheapest first: * Label connected components once at boot and pair only within a label. One pass over the collision map, and every consumer gets it — including `nearest_bank/1`, which is asked at runtime and today can still hand a wedged bot a bank across a river. * Or keep the fill but seed it from the **site** and stop at the first bank found, accepting a bounded search per site (~900 of them at derivation). Both want a decision about doors: a gate a bot could open makes two components one, and nothing opens a door out in the open world today — `Bot.Obstacle.between/2` asks whether the *bot* is shut in rather than whether the *destination* is, so outside a sealed region the fill hits its budget, answers *not shut in*, and no door is ever tried. Whatever labels components has to say what it assumes about doors. ## Related, and what it costs today Sites whose only bank in range is unreachable are worked and then abandoned, which reads as a bot that wandered off. The wedge is survivable — the goal re-rolls a ground eventually — but it burns a recovery relocation each time, and `Bot.Travel.recover/2` relocating into a place it cannot leave is its own hazard.
Author
Owner

Fixed on main: Bot.Sites now pairs a site with a bank only when Bot.Route.reachable?/3 finds a walkable route, so a bank across a river or a toll gate is no longer paired. The runtime half, nearest_bank/1 still answering by distance, is carried over on forge.home.arpa as https://forge.home.arpa/Revenant/Server/issues/45.

Fixed on main: `Bot.Sites` now pairs a site with a bank only when `Bot.Route.reachable?/3` finds a walkable route, so a bank across a river or a toll gate is no longer paired. The runtime half, `nearest_bank/1` still answering by distance, is carried over on forge.home.arpa as https://forge.home.arpa/Revenant/Server/issues/45.
Sign in to join this conversation.
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
Revenant/Server#243
No description provided.