aboutsummaryrefslogtreecommitdiff
path: root/advtrains/path.lua
diff options
context:
space:
mode:
Diffstat (limited to 'advtrains/path.lua')
-rw-r--r--advtrains/path.lua59
1 files changed, 56 insertions, 3 deletions
diff --git a/advtrains/path.lua b/advtrains/path.lua
index 714781a..7676947 100644
--- a/advtrains/path.lua
+++ b/advtrains/path.lua
@@ -119,7 +119,7 @@ function advtrains.path_invalidate(train, ignore_lock)
if train.path then
for i,p in pairs(train.path) do
- advtrains.occ.clear_item(train.id, advtrains.round_vector_floor_y(p))
+ advtrains.occ.clear_all_items(train.id, advtrains.round_vector_floor_y(p))
end
end
train.path = nil
@@ -162,7 +162,7 @@ function advtrains.path_invalidate_ahead(train, start_idx, ignore_when_passed)
-- leave current node in path, it won't change. What might change is the path onward from here (e.g. switch)
local i = idx + 1
while train.path[i] do
- advtrains.occ.clear_item(train.id, advtrains.round_vector_floor_y(train.path[i]))
+ advtrains.occ.clear_specific_item(train.id, advtrains.round_vector_floor_y(train.path[i]), i)
i = i+1
end
train.path_ext_f=idx
@@ -375,12 +375,25 @@ function advtrains.path_get_index_by_offset(train, index, offset)
return c_idx + frac
end
+
+-- The path_dist[] table contains absolute distance values for every whole index.
+-- Use this function to retrieve the correct absolute distance for a fractional index value (interpolate between floor and ceil index)
+-- returns: absolute distance from path item 0
+function advtrains.path_get_path_dist_fractional(train, index)
+ local start_index_f = atfloor(index)
+ local frac = index - start_index_f
+ -- ensure path exists
+ advtrains.path_get_adjacent(train, index)
+ local dist1, dist2 = train.path_dist[start_index_f], train.path_dist[start_index_f+1]
+ return dist1 + (dist2-dist1)*frac
+end
+
local PATH_CLEAR_KEEP = 4
function advtrains.path_clear_unused(train)
local i
for i = train.path_ext_b, train.path_req_b - PATH_CLEAR_KEEP do
- advtrains.occ.clear_item(train.id, advtrains.round_vector_floor_y(train.path[i]))
+ advtrains.occ.clear_specific_item(train.id, advtrains.round_vector_floor_y(train.path[i]), i)
train.path[i] = nil
train.path_dist[i-1] = nil
train.path_cp[i] = nil
@@ -417,3 +430,43 @@ function advtrains.path_lookup(train, pos)
end
return nil
end
+
+-- Projects the path of "train" onto the path of "onto_train_id", and returns the index on onto_train's path
+-- that corresponds to "index" on "train"'s path, as well as whether both trains face each other
+-- index may be fractional
+-- heuristic: see advtrains.occ.reverse_lookup_sel()
+-- returns: res_index, trains_facing
+-- returns nil when path can not be projected, either because trains are on different tracks or
+-- node at "index" happens to be on a turnout and it's the wrong direction
+-- Note - duplicate with similar functionality is in train_step_b() - that code combines train detection with projecting
+function advtrains.path_project(train, index, onto_train_id, heuristic)
+ local base_idx = atfloor(index)
+ local frac_part = index - base_idx
+ local base_pos = advtrains.path_get(train, base_idx)
+ local base_cn = train.path_cn[base_idx]
+ local otrn = advtrains.trains[onto_train_id]
+ -- query occupation
+ local occ = advtrains.occ.reverse_lookup_sel(base_pos, heuristic)
+ -- is wanted train id contained?
+ local ob_idx = occ[onto_train_id]
+ if not ob_idx then
+ return nil
+ end
+
+ -- retrieve other train's cn and cp
+ local ocn = otrn.path_cn[ob_idx]
+ local ocp = otrn.path_cp[ob_idx]
+
+ if base_cn == ocn then
+ -- same direction
+ return ob_idx + frac_part, false
+ elseif base_cn == ocp then
+ -- facing trains - subtract index frac
+ return ob_idx - frac_part, true
+ else
+ -- same path item but no common connections - deny
+ return nil
+ end
+end
+
+