diff --git a/docs/research/vehicle-probe.md b/docs/research/vehicle-probe.md index 424f0af..f9400a5 100644 --- a/docs/research/vehicle-probe.md +++ b/docs/research/vehicle-probe.md @@ -107,3 +107,4 @@ The human confirmed in game what the log showed: rebuilding the segment under a - Third run setup: passing lanes at 20 m/s (normal lanes 22.22 m/s), everything else unchanged. Question: does a lower limit keep vehicles in the normal lane and send them to the passing lane only when the normal lane is blocked? - Third run (20 m/s passing lanes): **no change.** Slow buses still sat in the left passing lane (29849 and 29851: 29/29 samples in lane 3); fast 29251 split 8/11. The engine doesn't pick lanes by speed limit (the slow buses top out at 16.67 < 20 anyway). Observed pattern: a vehicle gets a lane when it enters the stretch and keeps it; it doesn't move over when blocked; passes happen only when fast and slow happen to be in different lanes. - Lane connections are editable: `BaseNodeConfig.laneConnections` (`LaneConnection{segment0, lane0, segment1, lane1, withRoad, withTram}`, lanes zero-based left-to-right seen from the node) plus `userModifiedLaneConnections`, scriptable via `SimpleStreetProposal.nodeConfigsToAdd`. The game also has a native **crossing tool** ("allows to change the road and tram lanes at crossings", `UI::LaneModifier` in the executable). Next test (option a, by hand): at the stretch's entry junction, connect the normal road only to the right lane, to see whether entry control works and whether a blocked fast bus moves left inside the stretch. +- Fourth run (after the human's crossing-tool edits): **entry control not effective.** Slow buses 29849, 29851 and 29852 still entered prototype stretches (segments 21304, 29012) in the left lane 3 and stayed there (12–14/12–14 samples). 29850, 29848 and the fast 29251 entered in lane 4. No vehicle switched lanes inside a stretch. It's unknown whether or where the edits were saved, so the probe now logs the lane connections (`NODE … userModified= conns=`) at both nodes of every occupied prototype segment. diff --git a/mod/content/overtake_probe.script.tl b/mod/content/overtake_probe.script.tl index 59f2f41..2b67a72 100644 --- a/mod/content/overtake_probe.script.tl +++ b/mod/content/overtake_probe.script.tl @@ -33,10 +33,31 @@ local function roadOf(seg : integer) : string return (tostring(be.roadTemplate):match("([^/]+)%.street_template$")) or tostring(be.roadTemplate) end +-- lane connections at both nodes of a segment, to check whether crossing-tool edits exist where vehicles enter +local function nodeLog(seg : integer) + local be = api.engine.getComponent(seg, api.type.ComponentType.BASE_EDGE) as Engine.Component.BaseEdge + if be == nil then return end + for _, node in ipairs({ be.node0, be.node1 }) do + local cfg = api.engine.getComponent(node, api.type.ComponentType.BASE_NODE_CONFIG) as Engine.Component.BaseNodeConfig + if cfg == nil then + p(string.format("NODE seg=%d node=%d no BaseNodeConfig (default connections)", seg, node)) + else + local conns : {string} = {} + for _, lc in ipairs(cfg.laneConnections) do + if lc.segment0 == seg or lc.segment1 == seg then + table.insert(conns, string.format("%d:%d->%d:%d", lc.segment0, lc.lane0, lc.segment1, lc.lane1)) + end + end + p(string.format("NODE seg=%d node=%d userModified=%s conns=%s", seg, node, tostring(cfg.userModifiedLaneConnections), table.concat(conns, " "))) + end + end +end + local function dump(dt : number) 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", ticks, tostring(dt), #vehicles)) + local protoSegs : {integer : boolean} = {} for _, v in ipairs(vehicles) do local lv = api.engine.getComponent(v, api.type.ComponentType.LAND_VEHICLE) as Engine.Component.LandVehicle local mp = api.engine.getComponent(v, api.type.ComponentType.MOVE_PATH) as Engine.Component.MovePath @@ -48,8 +69,10 @@ local function dump(dt : number) v, edge and roadOf(edge.entity) or "-", edge and edge.entity or -1, 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 edge ~= nil and roadOf(edge.entity) == "overtake_proto_b" then protoSegs[edge.entity] = true end end end + for seg, _ in pairs(protoSegs) do nodeLog(seg) end end local ret : GameScript = {