1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
|
-- smartroute.lua
-- Implementation of the advtrains auto-route search
local atil = advtrains.interlocking
local ildb = atil.db
local sr = {}
local function otherside(s)
if s==1 then return 2 else return 1 end
end
--route search implementation
-- Note this is similar to recursively_find_routes in database.lua, there used for the rscache
local function recursively_find_routes(s_pos, s_connid, searching_shunt, tcbseq, mark_pos, result_table, scan_limit)
--atdebug("Recursively restarting at ",s_pos, s_connid, "limit left", scan_limit)
local ti = advtrains.get_track_iterator(s_pos, s_connid, scan_limit, false)
local pos, connid, bconnid = ti:next_branch()
pos, connid, bconnid = ti:next_track()-- step once to get ahead of previous turnout
local last_pos
repeat
-- record position in mark_pos
local pts = advtrains.encode_pos(pos)
mark_pos[pts] = true
local node = advtrains.ndb.get_node_or_nil(pos)
atdebug("(SmartRoute) Walk ",pos, "nodename", node.name, "entering at conn",bconnid)
local ndef = minetest.registered_nodes[node.name]
if ndef.advtrains and ndef.advtrains.node_state_map then
-- Stop, this is a switchable node. Find out which conns we can go at
atdebug("(SmartRoute) Found turnout ",pos, "nodename", node.name, "entering at conn",bconnid)
local out_conns = ildb.get_possible_out_connids(node.name, bconnid)
for oconnid, state in pairs(out_conns) do
--atdebug("Going in direction",oconnid,"state",state)
recursively_find_routes(pos, oconnid, searching_shunt, table.copy(tcbseq), table.copy(mark_pos), result_table, ti.limit)
end
return
end
--otherwise, this might be a tcb
local tcb = ildb.get_tcb(pos)
if tcb then
local fsigd = { p = pos, s = connid }
atdebug("(SmartRoute) Encounter TCB ",fsigd)
tcbseq[#tcbseq+1] = fsigd
-- check if this is a possible route endpoint
local tcbs = tcb[connid]
if tcbs.signal then
local ndef = advtrains.ndb.get_ndef(tcbs.signal)
if ndef and ndef.advtrains then
if ndef.advtrains.route_role == "main" or ndef.advtrains.route_role == "main_distant"
or ndef.advtrains.route_role == "end" or ndef.advtrains.route_role == "shunt" then
-- signal is suitable target
local is_mainsignal = ndef.advtrains.route_role ~= "shunt"
-- record the found route in the results
result_table[#result_table+1] = {
tcbseq = table.copy(tcbseq),
mark_pos = table.copy(mark_pos),
shunt_route = not is_mainsignal,
to_end_of_track = false,
name = tcbs.signal_name or atil.sigd_to_string(fsigd)
}
-- if this is a main signal and/or we are only searching shunt routes, stop the search here
if is_mainsignal or searching_shunt then
atdebug("(SmartRoute) Terminating here because it is main or only shunt routes searched")
return
end
end
end
end
end
-- Go forward
last_pos = pos
pos, connid, bconnid = ti:next_track()
until not pos -- this stops the loop when either the track end is reached or the limit is hit
--atdebug("recursively_find_routes: Reached track end or limit at", last_pos, ". This path is not saved, returning")
end
local function build_route_from_foundroute(froute, name)
local route = {
name = froute.name,
use_rscache = true,
smartroute_generated = true,
}
for _, sigd in ipairs(froute.tcbseq) do
route[#route+1] = { next = sigd, locks = {} }
end
return route
end
-- Maximum scan length for track iterator
local TS_MAX_SCAN = 1000
function sr.init(pname, sigd)
-- is start signal a shunt signal?
local is_startsignal_shunt = false
local tcbs = ildb.get_tcbs(sigd)
if tcbs.signal then
local ndef = advtrains.ndb.get_ndef(tcbs.signal)
if ndef and ndef.advtrains then
if ndef.advtrains.route_role == "shunt" then
is_startsignal_shunt = true
end
end
end
local result_table = {}
recursively_find_routes(sigd.p, sigd.s, is_startsignal_shunt, {}, {}, result_table, TS_MAX_SCAN)
atdebug("Smartroute search finished:",result_table)
-- Short-circuit logic right now for testing
-- go through and delete all routes that are autogenerated
local i = 1
while i<=#tcbs.routes do
if tcbs.routes[i].smartroute_generated then
table.remove(tcbs.routes, i)
else
i=i+1
end
end
-- just plainly create routes!
for idx, froute in ipairs(result_table) do
tcbs.routes[#tcbs.routes+1] = build_route_from_foundroute(froute)
end
atwarn("Smartroute done!")
end
--[[
player1 = {
origin = <sigd>
found_routes = {
{ tcbseq = {<sigd1>, <sigd2>, <end_sigd>}, mark_pos = { table with keys being encoded_pos of rails constituting route }, to_end_of_track = false, shunt_route = false }
}
}
]]--
local player_smartroute = {}
minetest.register_on_punchnode(function(pos, node, player, pointed_thing)
local pname = player:get_player_name()
if not minetest.check_player_privs(pname, "interlocking") then
return
end
-- TODO
end)
advtrains.interlocking.smartroute = sr
|