Reach strategy missing for wall shape 9 and loc shapes 12-21 #25

Open
opened 2026-07-27 22:32:10 +00:00 by sickday · 1 comment
Owner

World.reachable?/1 now routes wall locs (shapes 0-3) through
World.Collision.Flags.reach_wall?/5 and everything else through
World.Collision.Flags.interactable_from?/3. Two ranges are still handled by
the more permissive branch than they should be:

  • Shape 9, the diagonal wall. The client files it as an object for collision
    purposes — class60 calls addGameObject for it, and Flags.place/5 matches
    that — but reach for a diagonal wall is edge-based, not footprint-based: the
    four cardinal neighbours, each conditional on the facing wall being clear.
    Ours gives it the footprint test.
  • Shapes 12-21. These get the footprint test here and are not considered
    reachable at all by the engine's own strategy table. They are roof and
    diagonal variants that are not normally clicked, so this has not surfaced.

Both are the same direction of wrong — more permissive than the client — which
is the direction that produces "I used that through a wall" rather than "I could
not use that", and so does not get reported.

Flags.reach_wall?/5 already has the structure; shape 9 is four clauses. The
harder half is routing: dispatch/2 sends a wall click to
Movement.route/3 targeting the loc's own tile, which for shape 9 is solid, so
the route falls back to the nearest reachable tile rather than one that can
actually reach it.

Worth doing when a real interactive loc in either range turns up, with the loc
in hand rather than from the shape table alone.

`World.reachable?/1` now routes wall locs (shapes 0-3) through `World.Collision.Flags.reach_wall?/5` and everything else through `World.Collision.Flags.interactable_from?/3`. Two ranges are still handled by the more permissive branch than they should be: * **Shape 9**, the diagonal wall. The client files it as an object for collision purposes — `class60` calls `addGameObject` for it, and `Flags.place/5` matches that — but reach for a diagonal wall is edge-based, not footprint-based: the four cardinal neighbours, each conditional on the facing wall being clear. Ours gives it the footprint test. * **Shapes 12-21.** These get the footprint test here and are not considered reachable at all by the engine's own strategy table. They are roof and diagonal variants that are not normally clicked, so this has not surfaced. Both are the same direction of wrong — more permissive than the client — which is the direction that produces "I used that through a wall" rather than "I could not use that", and so does not get reported. `Flags.reach_wall?/5` already has the structure; shape 9 is four clauses. The harder half is routing: `dispatch/2` sends a wall click to `Movement.route/3` targeting the loc's own tile, which for shape 9 is solid, so the route falls back to the nearest reachable tile rather than one that can actually reach it. Worth doing when a real interactive loc in either range turns up, with the loc in hand rather than from the shape table alone.
Author
Owner

Leaving this open — the condition it sets for itself (a real interactive loc in either range, with the loc in hand rather than the shape table alone) has not come up yet.

One thing has moved under it, though. World.reachable?/1 is gone: the per-kind reach rules now live in Contract.Reach, pure and taking a flags snapshot, with one clause per kind of target and no catch-all. So shape 9 becomes a clause there plus the four wall_reach/2 entries in Flags, and it can be tested without a running world — which is most of what made this look expensive.

The routing half is unchanged and is still the harder one: dispatch/2 sends a wall click to Movement.route/3 targeting the loc's own tile, which for shape 9 is solid, so the route falls back to the nearest reachable tile rather than one that can actually reach it.

Leaving this open — the condition it sets for itself (a real interactive loc in either range, with the loc in hand rather than the shape table alone) has not come up yet. One thing has moved under it, though. `World.reachable?/1` is gone: the per-kind reach rules now live in `Contract.Reach`, pure and taking a flags snapshot, with one clause per kind of target and no catch-all. So shape 9 becomes a clause there plus the four `wall_reach/2` entries in `Flags`, and it can be tested without a running world — which is most of what made this look expensive. The routing half is unchanged and is still the harder one: `dispatch/2` sends a wall click to `Movement.route/3` targeting the loc's own tile, which for shape 9 is solid, so the route falls back to the nearest reachable tile rather than one that can actually reach it.
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#25
No description provided.