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:
1 parent
ea23aa1dc5
commit
e77fabb772
2 files changed
+41
-3
No files matched your search
@@ -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))
|
||||
|
||||
Reference in new issue
Block a user