A* was searching almost the whole island for every road. Godot's stock
estimate-to-goal is plain straight-line distance, which assumes every step
costs 1 — but a step through mountains costs up to 401 and a step near an
existing road cost 10,001. With the estimate that far below reality, A* cannot
rule anything out, so it degenerates toward Dijkstra.
Two changes, both aimed at that:
1. RoadPathGrid overrides the estimate to scale it by HEURISTIC_WEIGHT (3.0),
i.e. weighted A*. Paths may be up to 3x costlier than the theoretical best
in exchange for exploring far less. This does NOT push roads over mountains:
a ridge costs hundreds of times more than going around, which a 3x bias
nowhere near pays for.
2. ROAD_REPULSION_PENALTY replaces the hardcoded +10000 with 250. The old value
made ground near a road effectively infinite, and it compounded — each road
drawn made the next search slower. 250 still strongly discourages roads from
running alongside each other.
Terrain weights are untouched: the mountain curve (1 + elevation^3 * 400),
beach and wasteland costs are exactly as before, so mountains remain expensive
and roads still avoid them. Routing, tiers, smoothing and grid resolution are
also unchanged.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Every road path search — highway, branch, county — now goes through one
function instead of three direct GetPointPath calls. The function body is
exactly the call it replaced, so behaviour is unchanged.
This exists so the next commit's pathfinding change can be judged on its own:
if the generated map changes after this point, it was the heuristic, not a
refactor slip.
Routing is untouched: which towns connect, loop order, Prim's daisy-chain,
tier assignment and the abandon protocol all deal only in town positions and
never touch the grid.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>