chore(prototype): try re-path via makeVehicleSetLineCmd; record failed rebuild

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
haylanandClaude Bot committed 2026-10-05 22:51:26 +02:00
1 parent ea23aa1dc5
commit e77fabb772
2 files changed
+41 -3

No files matched your search

+35 -3
View File
@@ -8,7 +8,8 @@
local TAG = "[overtake_probe] "
local INTERVAL = 2.0
local MAX_GAP = 40.0
local MAX_REBUILDS = 3 -- per save; counted in GameScriptState because module locals don't persist
local MAX_REBUILDS = 0 -- rebuild disabled: proposals were silently rejected (segments kept their ids)
local MAX_SETLINES = 5 -- EXPERIMENT: re-assign the follower to its own line + current stop to force a re-path
local elapsed = 0.0
local ticks = 0
@@ -38,6 +39,7 @@ end
local record ProbeState
rebuilds : integer
setlines : integer
watch : {integer} -- vehicles involved in the last rebuild, flagged in later dumps
end
@@ -78,16 +80,34 @@ local function rebuild(seg : integer)
api.cmd.sendCommand(api.cmd.makeWorldBuildProposalCmd(proposal, nil, true, false))
end
-- lanes of the next few path edges, to see whether a re-path changes the lane choice
local function lanesAhead(mp : Engine.Component.MovePath) : string
local out : {string} = {}
local edges = mp.path.edges as {any}
for k = mp.dyn.pathPos.edgeIndex + 1, math.min(#edges, mp.dyn.pathPos.edgeIndex + 4) do
local e = edges[k] as UtilPathfinding.EdgeIdDir
table.insert(out, e.edgeId.entity .. ":" .. e.edgeId.index)
end
return table.concat(out, " ")
end
local function setLine(v : integer)
local tv = api.engine.getComponent(v, api.type.ComponentType.TRANSPORT_VEHICLE) as Engine.Component.TransportVehicle
p(string.format("SETLINE_TEST send veh=%d line=%s stopIndex=%s", v, tostring(tv.line), tostring(tv.stopIndex)))
api.cmd.sendCommand(api.cmd.makeVehicleSetLineCmd(v, tv.line, tv.stopIndex))
end
local function dump(dt : number, state : GameScriptState<ProbeState>)
local st = state:get()
st.rebuilds = st.rebuilds or 0
st.setlines = st.setlines or 0
st.watch = st.watch or {}
local watched : {integer : boolean} = {}
for _, w in ipairs(st.watch) do watched[w] = true end
local player = api.engine.util.getPlayer()
local vehicles = api.engine.getEntitiesWithComponent(api.type.ComponentType.TRANSPORT_VEHICLE, { requireOwnedByPlayer = player })
p(string.format("tick=%d dt=%s playerVehicles=%d rebuilds=%d", ticks, tostring(dt), #vehicles, st.rebuilds))
p(string.format("tick=%d dt=%s playerVehicles=%d rebuilds=%d setlines=%d", ticks, tostring(dt), #vehicles, st.rebuilds, st.setlines))
local byLane : {string : {Car}} = {}
local laneSeg : {string : integer} = {}
@@ -103,6 +123,7 @@ local function dump(dt : number, state : GameScriptState<ProbeState>)
watched[v] and "WATCH " or "", v, seg, tostring(edge and edge.index), tostring(dir), tostring(edge and turnaround(edge)),
mp.dyn.pathPos.edgeIndex, #(mp.path.edges as {any}), mp.dyn.pathPos.pos, mp.dyn.speed, tostring(mp.state),
tostring(tv and tv.state), tostring(tv and tv.line), mp.dyn.timeStanding))
if watched[v] then p("WATCH lanesAhead veh=" .. v .. " " .. lanesAhead(mp)) end
if edge ~= nil then
local key = seg .. ":" .. edge.index
byLane[key] = byLane[key] or {}
@@ -112,7 +133,7 @@ local function dump(dt : number, state : GameScriptState<ProbeState>)
end
end
if st.rebuilds >= MAX_REBUILDS then return end
if st.rebuilds >= MAX_REBUILDS and st.setlines >= MAX_SETLINES then return end
for key, cars in pairs(byLane) do
for i = 1, #cars do
for j = 1, #cars do
@@ -122,6 +143,17 @@ local function dump(dt : number, state : GameScriptState<ProbeState>)
-- leader must be moving, otherwise it's a queue at a stop or junction, not a slow vehicle
if i ~= j and ahead and math.abs(b.pos - a.pos) < MAX_GAP and b.speed > 1.0 then
local seg = laneSeg[key]
if st.setlines < MAX_SETLINES then
local amp = api.engine.getComponent(a.v, api.type.ComponentType.MOVE_PATH) as Engine.Component.MovePath
p(string.format("SETLINE_TEST candidate seg=%d follower=%d (v=%.2f) leader=%d (v=%.2f) lanesAhead before: %s",
seg, a.v, a.speed, b.v, b.speed, lanesAhead(amp)))
setLine(a.v)
st.setlines = st.setlines + 1
st.watch = { a.v, b.v }
state:set(st)
return -- one experiment per dump
end
if st.rebuilds >= MAX_REBUILDS then return end
local ok, why = rebuildable(seg)
p(string.format("REBUILD_TEST candidate seg=%d follower=%d (pos=%.1f v=%.2f) leader=%d (pos=%.1f v=%.2f) ok=%s %s",
seg, a.v, a.pos, a.speed, b.v, b.pos, b.speed, tostring(ok), why))