Bot.Travel wedges any leg whose straight line crosses water, mountain or building #123

Closed
opened 2026-08-05 23:52:08 +00:00 by sickday · 2 comments
Owner

Bot.Travel.hop/2 picks its waypoint by straight-line interpolation, so any leg
whose direct line crosses water, a mountain or a building wedges the bot
permanently.

hop/2 is the whole of long-leg travel: for a destination further than @hop
(80) tiles it returns

{plane, x + div((dx - x) * @hop, distance), y + div((dy - y) * @hop, distance)}

which is a point 80 tiles along the straight line to the destination.
Nothing asks whether that point is standable, or whether a route to it exists.
When it lands inside terrain the planner cannot reach, the bot issues a walk,
does not move, stuck climbs, reroutes reaches @max_reroutes (3), and the
leg ends :stuck. The goal fails, loops, re-chooses, and — because the
geography has not changed — usually picks a destination on the same side of the
same obstacle and wedges again.

Observed

Three times in one sitting, with fishing bots but nothing fishing-specific
about it:

  • Draynor (3091,3240) routing to the Al Kharid ground (3267,3149), 176
    tiles east across the River Lum. Leg state
    %{steps: 6, stuck: 4, reroutes: 4, walked?: true}.
  • Fishing Guild (2598,3420) to Catherby (2835,3432), into the mountains —
    two bots, both parked at 2697,3409.
  • Catherby back to the Fishing Guild — two bots, both parked, same range.

The log signature is a line repeated forever at one tile:

[world] dray1 walking to 3171,3189 (run=false) -- 0 step(s)

0 step(s) is the tell: a walk was issued and the planner produced no path.

Why it matters beyond bots

This is the leash on where a bot can be usefully spawned — anywhere whose
bank or resource lies across water is unreachable in practice — and it is the
same fact that keeps a pker rising at Edgeville rather than walking in from
further out. Any future goal that travels between regions inherits it.

Shape of a fix

The waypoint is the wrong thing to guess. Options, cheapest first:

  1. Fall back to the reachable prefix. If no route to the hop exists, ask the
    planner for a route toward it and walk as far as it actually reached, then
    hop again from there. This is close to what a person does and needs no map
    knowledge.
  2. Reject an unstandable hop and try a fan. Sample a few candidate
    waypoints off the straight line before giving up.
  3. A coarse region graph with real crossings (bridges, gates), which is the
    durable answer and the most work.

Worth reading #23 first — closed, and about Movement.route truncating at 128
steps. Different mechanism, adjacent symptom: both are a bound that produces a
bot standing still with nothing said about why.

`Bot.Travel.hop/2` picks its waypoint by straight-line interpolation, so any leg whose direct line crosses water, a mountain or a building wedges the bot permanently. `hop/2` is the whole of long-leg travel: for a destination further than `@hop` (80) tiles it returns {plane, x + div((dx - x) * @hop, distance), y + div((dy - y) * @hop, distance)} which is a point 80 tiles along the **straight line** to the destination. Nothing asks whether that point is standable, or whether a route to it exists. When it lands inside terrain the planner cannot reach, the bot issues a walk, does not move, `stuck` climbs, `reroutes` reaches `@max_reroutes` (3), and the leg ends `:stuck`. The goal fails, loops, re-chooses, and — because the geography has not changed — usually picks a destination on the same side of the same obstacle and wedges again. ### Observed Three times in one sitting, with fishing bots but nothing fishing-specific about it: * Draynor (`3091,3240`) routing to the Al Kharid ground (`3267,3149`), 176 tiles east across the River Lum. Leg state `%{steps: 6, stuck: 4, reroutes: 4, walked?: true}`. * Fishing Guild (`2598,3420`) to Catherby (`2835,3432`), into the mountains — two bots, both parked at `2697,3409`. * Catherby back to the Fishing Guild — two bots, both parked, same range. The log signature is a line repeated forever at one tile: [world] dray1 walking to 3171,3189 (run=false) -- 0 step(s) `0 step(s)` is the tell: a walk was issued and the planner produced no path. ### Why it matters beyond bots This is the leash on where a bot can be *usefully* spawned — anywhere whose bank or resource lies across water is unreachable in practice — and it is the same fact that keeps a pker rising at Edgeville rather than walking in from further out. Any future goal that travels between regions inherits it. ### Shape of a fix The waypoint is the wrong thing to guess. Options, cheapest first: 1. **Fall back to the reachable prefix.** If no route to the hop exists, ask the planner for a route toward it and walk as far as it actually reached, then hop again from there. This is close to what a person does and needs no map knowledge. 2. **Reject an unstandable hop and try a fan.** Sample a few candidate waypoints off the straight line before giving up. 3. **A coarse region graph** with real crossings (bridges, gates), which is the durable answer and the most work. Worth reading #23 first — closed, and about `Movement.route` truncating at 128 steps. Different mechanism, adjacent symptom: both are a bound that produces a bot standing still with nothing said about why.
Author
Owner

A second mechanism reaching the same wedge, measured 2026-08-19 on a 75-bot
fishing fleet: Movement's @max_path (128) truncates the route, and a
truncated route is indistinguishable from the hop's for the bot walking it.

[movement] route capped at 128 steps -- stopping at {2807, 3351},
           dropping 5 step(s) to {2802, 3347}

Twelve of those in one sixteen-minute sitting, all from bots on the Falador
coast ({0, 2874, 3341} and {0, 2875, 3332}) whose banks are 70 and 71
tiles away. The path is found and then cut short, so the bot walks to a tile
that is not where it asked to go and re-issues from there — which is the same
observable as the hop landing somewhere unroutable, and would be read as the
hop unless the warning is in the log.

Worth separating when this is fixed, because the two want different answers: a
straight-line hop that lands in terrain wants a reachable waypoint, whereas a
path capped at 128 steps is already a good path and wants either a larger cap
or a caller that walks it in stages and re-plans. @max_path's own docs say it
drops work; nothing downstream treats a capped route as different from a
complete one.

Bot.Goals.Fish and Bot.Goals.GatherAndBank now spurn a ground whose leg
fails and choose another, so a failed leg is no longer a permanent loop. That
is a mitigation and it is measurably not a fix:

  • the Al Kharid ground it was tested on recovered fully — three bots
    spurned three grounds, settled at Draynor and banked 108 fish each;
  • the two Falador coast grounds did not — their bots now spurn thirteen or
    fourteen grounds and roam without banking anything, because every ground in
    reach of them is on the far side of this.

So the spurn buys a bot an escape wherever a reachable alternative exists, and
nothing at all where the whole neighbourhood is beyond the planner. That makes
this issue the one that decides whether large fishing fleets work.

A second mechanism reaching the same wedge, measured 2026-08-19 on a 75-bot fishing fleet: **`Movement`'s `@max_path` (128) truncates the route**, and a truncated route is indistinguishable from the hop's for the bot walking it. [movement] route capped at 128 steps -- stopping at {2807, 3351}, dropping 5 step(s) to {2802, 3347} Twelve of those in one sixteen-minute sitting, all from bots on the Falador coast (`{0, 2874, 3341}` and `{0, 2875, 3332}`) whose banks are 70 and 71 tiles away. The path is found and then cut short, so the bot walks to a tile that is not where it asked to go and re-issues from there — which is the same observable as the hop landing somewhere unroutable, and would be read as the hop unless the warning is in the log. Worth separating when this is fixed, because the two want different answers: a straight-line hop that lands in terrain wants a *reachable* waypoint, whereas a path capped at 128 steps is already a good path and wants either a larger cap or a caller that walks it in stages and re-plans. `@max_path`'s own docs say it drops work; nothing downstream treats a capped route as different from a complete one. ### Related, and what a partial fix showed `Bot.Goals.Fish` and `Bot.Goals.GatherAndBank` now spurn a ground whose leg fails and choose another, so a failed leg is no longer a permanent loop. That is a mitigation and it is measurably not a fix: * the Al Kharid ground it was tested on **recovered fully** — three bots spurned three grounds, settled at Draynor and banked 108 fish each; * the two Falador coast grounds **did not** — their bots now spurn thirteen or fourteen grounds and roam without banking anything, because every ground in reach of them is on the far side of this. So the spurn buys a bot an escape wherever a reachable alternative exists, and nothing at all where the whole neighbourhood is beyond the planner. That makes this issue the one that decides whether large fishing fleets work.
Author
Owner

Superseded: Bot.Travel no longer uses the straight-line hop/2. A leg now asks Bot.Route for the whole path and walks it in forty-step waypoints, which also covers the 128-step route cap from the comment. Remaining travel problems are tracked on forge.home.arpa (#45, #49).

Superseded: `Bot.Travel` no longer uses the straight-line `hop/2`. A leg now asks `Bot.Route` for the whole path and walks it in forty-step waypoints, which also covers the 128-step route cap from the comment. Remaining travel problems are tracked on forge.home.arpa (#45, #49).
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#123
No description provided.