aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authororwell96 <orwell@bleipb.de>2018-10-07 22:21:49 +0200
committerorwell96 <orwell@bleipb.de>2018-10-07 22:21:49 +0200
commit8df7bcf6b6ea6333b3df925af528e23574974d69 (patch)
tree416d247272b6d6878b6e5024eca6965c21d81c22
parent8e70c070c1be102a679ff3fd6f71669c883ec510 (diff)
downloadadvtrains-8df7bcf6b6ea6333b3df925af528e23574974d69.tar.gz
advtrains-8df7bcf6b6ea6333b3df925af528e23574974d69.tar.bz2
advtrains-8df7bcf6b6ea6333b3df925af528e23574974d69.zip
Improve route programming:
- Formspec for TCBs instead of unhandy chatcommands - Ability to advance route over the next secction without punching end - Better visualization - Ability to route into dead-end sections
-rw-r--r--advtrains/init.lua17
-rw-r--r--advtrains_interlocking/database.lua12
-rw-r--r--advtrains_interlocking/route_prog.lua431
-rw-r--r--advtrains_interlocking/routesetting.lua18
-rw-r--r--advtrains_interlocking/textures/at_il_route_lock.pngbin382 -> 534 bytes
-rw-r--r--advtrains_interlocking/textures/at_il_route_lock_edit.pngbin514 -> 533 bytes
-rw-r--r--advtrains_interlocking/textures/at_il_routep_advance.pngbin0 -> 304 bytes
-rw-r--r--advtrains_interlocking/textures/at_il_routep_end_here.pngbin0 -> 243 bytes
-rw-r--r--advtrains_interlocking/textures/at_il_routep_end_over.pngbin0 -> 281 bytes
-rw-r--r--advtrains_interlocking/textures/at_il_routep_end_over_last.pngbin0 -> 277 bytes
-rw-r--r--advtrains_interlocking/train_related.lua2
-rw-r--r--assets/interlocking.html.LyXconv/interlocking.html78
-rw-r--r--assets/interlocking.lyx137
-rw-r--r--assets/interlocking.lyx~180
14 files changed, 638 insertions, 237 deletions
diff --git a/advtrains/init.lua b/advtrains/init.lua
index a02b377..46a73d4 100644
--- a/advtrains/init.lua
+++ b/advtrains/init.lua
@@ -11,6 +11,8 @@ end
--advtrains
+DUMP_DEBUG_SAVE = false
+
--Constant for maximum connection value/division of the circle
AT_CMAX = 16
@@ -108,9 +110,9 @@ sid=function(id) if id then return string.sub(id, -6) end end
--ONLY use this function for temporary debugging. for consistent debug prints use atprint
atdebug=function(t, ...)
--- local text=advtrains.print_concat_table({t, ...})
--- minetest.log("action", "[advtrains]"..text)
--- minetest.chat_send_all("[advtrains]"..text)
+ local text=advtrains.print_concat_table({t, ...})
+ minetest.log("action", "[advtrains]"..text)
+ minetest.chat_send_all("[advtrains]"..text)
end
if minetest.settings:get_bool("advtrains_enable_debugging") then
@@ -320,6 +322,15 @@ advtrains.avt_save = function(remove_players_from_wagons)
end
file:write(datastr)
file:close()
+
+ if DUMP_DEBUG_SAVE then
+ local file, err = io.open(advtrains.fpath.."_DUMP", "w")
+ if err then
+ return
+ end
+ file:write(dump(save_tbl))
+ file:close()
+ end
end
--## MAIN LOOP ##--
diff --git a/advtrains_interlocking/database.lua b/advtrains_interlocking/database.lua
index f71d911..f3df5e1 100644
--- a/advtrains_interlocking/database.lua
+++ b/advtrains_interlocking/database.lua
@@ -250,7 +250,7 @@ end
local function traverser(found_tcbs, pos, conns, connid, count, brk_when_found_n)
local adj_pos, adj_connid, conn_idx, nextrail_y, next_conns = advtrains.get_adjacent_rail(pos, conns, connid, advtrains.all_tracktypes)
if not adj_pos then
- atdebug("Traverser found end-of-track at",pos, connid)
+ --atdebug("Traverser found end-of-track at",pos, connid)
return
end
-- look whether there is a TCB here
@@ -258,14 +258,14 @@ local function traverser(found_tcbs, pos, conns, connid, count, brk_when_found_n
local tcb = ildb.get_tcb(adj_pos)
if tcb then
-- done with this branch
- atdebug("Traverser found tcb at",adj_pos, adj_connid)
+ --atdebug("Traverser found tcb at",adj_pos, adj_connid)
insert_sigd_nodouble(found_tcbs, {p=adj_pos, s=adj_connid})
return
end
end
-- recursion abort condition
if count > TRAVERSER_LIMIT then
- atdebug("Traverser hit counter at",adj_pos, adj_connid)
+ --atdebug("Traverser hit counter at",adj_pos, adj_connid)
return true
end
-- continue traversing
@@ -316,7 +316,7 @@ function ildb.sync_tcb_neighbors(pos, connid)
error("update_tcb_neighbors but node is NOK: "..minetest.pos_to_string(pos))
end
- atdebug("Traversing from ",pos, connid)
+ --atdebug("Traversing from ",pos, connid)
local counter_hit = traverser(found_tcbs, pos, conns, connid, 0)
local ts_id
@@ -328,7 +328,7 @@ function ildb.sync_tcb_neighbors(pos, connid)
for idx, sigd in pairs(found_tcbs) do
local tcbs = ildb.get_tcbs(sigd)
if not tcbs.ts_id then
- atdebug("Sync: put",sigd_to_string(sigd),"into list_eoi")
+ --atdebug("Sync: put",sigd_to_string(sigd),"into list_eoi")
table.insert(list_eoi, sigd)
elseif not ts_id and tcbs.ts_id then
if not ildb.get_ts(tcbs.ts_id) then
@@ -336,7 +336,7 @@ function ildb.sync_tcb_neighbors(pos, connid)
tcbs.ts_id = nil
table.insert(list_eoi, sigd)
else
- atdebug("Sync: put",sigd_to_string(sigd),"into list_ok")
+ --atdebug("Sync: put",sigd_to_string(sigd),"into list_ok")
ts_id = tcbs.ts_id
table.insert(list_ok, sigd)
end
diff --git a/advtrains_interlocking/route_prog.lua b/advtrains_interlocking/route_prog.lua
index 33be576..7abca664 100644
--- a/advtrains_interlocking/route_prog.lua
+++ b/advtrains_interlocking/route_prog.lua
@@ -112,13 +112,16 @@ route = {
next = <sigd>, -- of the next (note: next) TCB on the route
locks = {<pts> = "state"} -- route locks of this route segment
}
+ terminal =
}
The first item in the TCB path (namely i=0) is always the start signal of this route,
so this is left out.
All subsequent entries, starting from 1, contain:
- all route locks of the segment on TS between the (i-1). and the i. TCB
- the next TCB signal describer in proceeding direction of the route.
-
+'Terminal' once again repeats the "next" entry of the last route segment.
+It is needed for distant signal aspect determination. If it is not set,
+the distant signal aspect is determined as DANGER.
]]--
local function chat(pname, message)
@@ -129,6 +132,10 @@ local function clear_lock(locks, pname, pts)
chat(pname, pts.." is no longer affected when this route is set.")
end
+local function otherside(s)
+ if s==1 then return 2 else return 1 end
+end
+
function advtrains.interlocking.clear_visu_context(context)
if not markerent[context] then return end
for key, obj in pairs(markerent[context]) do
@@ -150,22 +157,51 @@ function advtrains.interlocking.visualize_route(origin, route, context, tmp_lcks
end
routemarker(context, origin.p, "rte_origin", "at_il_route_start.png", oyaw, route.name)
+ local c_sigd = origin
for k,v in ipairs(route) do
- local sigd = v.next
- local yaw = 0
- local node_ok, conns, rhe = advtrains.get_rail_info_at(sigd.p, advtrains.all_tracktypes)
- if node_ok then
- yaw = advtrains.dir_to_angle(conns[sigd.s].c)
+ c_sigd = v.next
+ -- display route path
+ -- Final "next" marker can be EOI, thus undefined. This is legitimate.
+ if c_sigd then
+ local yaw = 0
+ local node_ok, conns, rhe = advtrains.get_rail_info_at(c_sigd.p, advtrains.all_tracktypes)
+ if node_ok then
+ yaw = advtrains.dir_to_angle(conns[c_sigd.s].c)
+ end
+ local img = "at_il_route_set.png"
+ if k==#route and not tmp_lcks then
+ img = "at_il_route_end.png"
+ end
+ routemarker(context, c_sigd.p, "rte"..k, img, yaw, route.name.." #"..k)
end
- local img = "at_il_route_set.png"
- if k == #route then img = "at_il_route_end.png" end
- routemarker(context, sigd.p, "rte"..k, img, yaw, route.name.." #"..k)
+ -- display locks
for pts, state in pairs(v.locks) do
local pos = minetest.string_to_pos(pts)
routesprite(context, pos, "fix"..k..pts, "at_il_route_lock.png", "Fixed in state '"..state.."' by route "..route.name.." until segment #"..k.." is freed.")
end
end
+
+ -- The presence of tmp_lcks tells us that we are displaying during route programming.
if tmp_lcks then
+ -- display route end markers at appropriate places (check next TS, if it exists)
+ local terminal = c_sigd
+ if terminal then
+ local term_tcbs = advtrains.interlocking.db.get_tcbs(terminal)
+ if term_tcbs.ts_id then
+ local over_ts = advtrains.interlocking.db.get_ts(term_tcbs.ts_id)
+ for i, sigd in ipairs(over_ts.tc_breaks) do
+ if not vector.equals(sigd.p, terminal.p) then
+ local yaw = 0
+ local node_ok, conns, rhe = advtrains.get_rail_info_at(sigd.p, advtrains.all_tracktypes)
+ if node_ok then
+ yaw = advtrains.dir_to_angle(conns[otherside(sigd.s)].c)
+ end
+ routemarker(context, sigd.p, "rteterm"..i, "at_il_route_end.png", yaw, route.name.." Terminal "..i)
+ end
+ end
+ end
+ end
+ -- display locks set by player
for pts, state in pairs(tmp_lcks) do
local pos = minetest.string_to_pos(pts)
routesprite(context, pos, "fixp"..pts, "at_il_route_lock_edit.png", "Fixed in state '"..state.."' by route "..route.name.." (punch to unfix)",
@@ -201,10 +237,267 @@ local function get_last_route_item(origin, route)
return route[#route].next
end
-local function otherside(s)
- if s==1 then return 2 else return 1 end
+local function do_advance_route(pname, rp, sigd, tsname)
+ table.insert(rp.route, {next = sigd, locks = rp.tmp_lcks})
+ rp.tmp_lcks = {}
+ chat(pname, "Added track section '"..tsname.."' to the route (revert with /at_rp_back)")
+end
+
+local function finishrpform(pname)
+ local rp = player_rte_prog[pname]
+ if not rp then return end
+
+ local form = "size[7,6]label[0.5,0.5;Finish programming route]"
+ local terminal = get_last_route_item(rp.origin, rp.route)
+ if terminal then
+ local term_tcbs = advtrains.interlocking.db.get_tcbs(terminal)
+
+ if term_tcbs.signal then
+ form = form .. "label[0.5,1.5;Route ends at signal:]"
+ form = form .. "label[0.5,2 ;"..term_tcbs.signal_name.."]"
+ else
+ form = form .. "label[0.5,1.5;WARNING: Route does not end at a signal.]"
+ form = form .. "label[0.5,2 ;Routes should in most cases end at signals.]"
+ form = form .. "label[0.5,2.5;Cancel if you are unsure!]"
+ end
+ else
+ form = form .. "label[0.5,1.5;Route leads into]"
+ form = form .. "label[0.5,2 ;non-interlocked area]"
+ end
+ form = form.."field[0.8,3.5;5.2,1;name;Enter Route Name;]"
+ form = form.."button_exit[0.5,4.5; 5,1;save;Save Route]"
+
+
+ minetest.show_formspec(pname, "at_il_routepf", form)
+end
+
+
+local function check_advance_valid(tcbpos, rp)
+ -- track circuit break, try to advance route over it
+ local lri = get_last_route_item(rp.origin, rp.route)
+ if not lri then
+ return false, false
+ end
+
+ local is_endpoint = false
+
+ local this_sigd, this_ts, adv_side
+
+ if vector.equals(lri.p, tcbpos) then
+ -- If the player just punched the last TCB again, it's of course possible to
+ -- finish the route here (although it can't be advanced by here.
+ -- Fun fact: you can now program routes that end exactly where they begin :)
+ is_endpoint = true
+ this_sigd = lri
+ else
+ -- else, we need to check whether this TS actually borders
+ local start_tcbs = advtrains.interlocking.db.get_tcbs(lri)
+ if not start_tcbs.ts_id then
+ return false, false
+ end
+
+ this_ts = advtrains.interlocking.db.get_ts(start_tcbs.ts_id)
+ for _,sigd in ipairs(this_ts.tc_breaks) do
+ if vector.equals(sigd.p, tcbpos) then
+ adv_side = otherside(sigd.s)
+ end
+ end
+ if not adv_side then
+ -- this TCB is not bordering to the section
+ return false, false
+ end
+ this_sigd = {p=tcbpos, s=adv_side}
+ end
+
+ -- check whether the ts at the other end is capable of "end over"
+ local adv_tcbs = advtrains.interlocking.db.get_tcbs(this_sigd)
+ local next_tsid = adv_tcbs.ts_id
+ local can_over, over_ts, next_tc_bs = false, nil, nil
+ local cannotover_rsn = "Next section is diverging (>2 TCBs)"
+ if next_tsid then
+ -- you may not advance over EOI. While this is technically possible,
+ -- in practise this just enters an unnecessary extra empty route item.
+ over_ts = advtrains.interlocking.db.get_ts(adv_tcbs.ts_id)
+ next_tc_bs = over_ts.tc_breaks
+ can_over = #next_tc_bs <= 2
+ else
+ cannotover_rsn = "End of interlocking"
+ end
+
+ local over_sigd = nil
+ if can_over then
+ if next_tc_bs and #next_tc_bs == 2 then
+ local sdt
+ if vector.equals(next_tc_bs[1].p, tcbpos) then
+ sdt = next_tc_bs[2]
+ end
+ if vector.equals(next_tc_bs[2].p, tcbpos) then
+ sdt = next_tc_bs[1]
+ end
+ if not sdt then
+ error("Inconsistency: "..dump(next_ts))
+ end
+ -- swap TCB direction
+ over_sigd = {p = sdt.p, s = otherside(sdt.s) }
+ end
+ end
+
+ return is_endpoint, true, this_sigd, this_ts, can_over, over_ts, over_sigd, cannotover_rsn
+end
+
+local function show_routing_form(pname, tcbpos, message)
+
+ local rp = player_rte_prog[pname]
+
+ if not rp then return end
+
+ local is_endpoint, advance_valid, this_sigd, this_ts, can_over, over_ts, over_sigd, cannotover_rsn = check_advance_valid(tcbpos, rp)
+
+ -- at this place, advance_valid shows whether the current route can be advanced
+ -- over this TCB.
+ -- If it can:
+ -- Advance over (continue programming)
+ -- End here
+ -- Advance and end (only <=2 TCBs, terminal signal needs to be known)
+ -- if not:
+ -- show nothing at all
+ -- In all cases, Discard and Backtrack buttons needed.
+
+ local form = "size[7,9.5]label[0.5,0.5;Advance/Complete Route]"
+ if message then
+ form = form .. "label[0.5,1;"..message.."]"
+ end
+
+ if advance_valid and not is_endpoint then
+ form = form.. "label[0.5,1.8;Advance to next route section]"
+ form = form.."image_button[0.5,2.2; 5,1;at_il_routep_advance.png;advance;]"
+
+ form = form.. "label[0.5,3.5;-------------------------]"
+ else
+ form = form.. "label[0.5,2.3;This TCB is not suitable as]"
+ form = form.. "label[0.5,2.8;route continuation.]"
+ end
+ if advance_valid or is_endpoint then
+ form = form.. "label[0.5,3.8;Finish route HERE]"
+ form = form.."image_button[0.5, 4.2; 5,1;at_il_routep_end_here.png;endhere;]"
+ if can_over then
+ form = form.. "label[0.5,5.3;Finish route at end of NEXT section]"
+ form = form.."image_button[0.5,5.7; 5,1;at_il_routep_end_over.png;endover;]"
+ else
+ form = form.. "label[0.5,5.3;Advancing over next section is]"
+ form = form.. "label[0.5,5.8;impossible at this place.]"
+ if cannotover_rsn then
+ form = form.. "label[0.5,6.3;"..cannotover_rsn.."]"
+ end
+ end
+ end
+
+ form = form.. "label[0.5,7;-------------------------]"
+ if #rp.route > 0 then
+ form = form.."button[0.5,7.4; 5,1;retract;Step back one section]"
+ end
+ form = form.."button[0.5,8.4; 5,1;cancel;Cancel route programming]"
+
+ minetest.show_formspec(pname, "at_il_rprog_"..minetest.pos_to_string(tcbpos), form)
end
+minetest.register_on_player_receive_fields(function(player, formname, fields)
+ local pname = player:get_player_name()
+
+ local tcbpts = string.match(formname, "^at_il_rprog_([^_]+)$")
+ local tcbpos
+ if tcbpts then
+ tcbpos = minetest.string_to_pos(tcbpts)
+ end
+ if tcbpos then
+ -- RPROG form
+ local rp = player_rte_prog[pname]
+ if not rp then
+ minetest.close_formspec(pname, formname)
+ return
+ end
+
+ local is_endpoint, advance_valid, this_sigd, this_ts, can_over, over_ts, over_sigd = check_advance_valid(tcbpos, rp)
+
+ if advance_valid then
+ if fields.advance then
+ -- advance route
+ if not is_endpoint then
+ do_advance_route(pname, rp, this_sigd, this_ts.name)
+ end
+ end
+ if fields.endhere then
+ if not is_endpoint then
+ do_advance_route(pname, rp, this_sigd, this_ts.name)
+ end
+ finishrpform(pname)
+ end
+ if can_over and fields.endover then
+ if not is_endpoint then
+ do_advance_route(pname, rp, this_sigd, this_ts.name)
+ end
+ do_advance_route(pname, rp, over_sigd, over_ts and over_ts.name or "--EOI--")
+ finishrpform(pname)
+ end
+ end
+ if fields.retract then
+ if #rp.route <= 0 then
+ minetest.close_formspec(pname, formname)
+ return
+ end
+ rp.tmp_locks = rp.route[#rp.route].locks
+ rp.route[#rp.route] = nil
+ chat(pname, "Route section "..(#rp.route+1).." removed.")
+ end
+ if fields.cancel then
+ player_rte_prog[pname] = nil
+ advtrains.interlocking.clear_visu_context("prog_"..pname)
+ chat(pname, "Route discarded.")
+ minetest.close_formspec(pname, formname)
+ return
+ end
+
+ advtrains.interlocking.visualize_route(rp.origin, rp.route, "prog_"..pname, rp.tmp_lcks, pname)
+ minetest.close_formspec(pname, formname)
+ return
+ end
+
+ if formname == "at_il_routepf" then
+ if not fields.save or not fields.name then return end
+ if fields.name == "" then
+ -- show form again
+ finishrpform(pname)
+ return
+ end
+
+ local rp = player_rte_prog[pname]
+ if rp then
+ if #rp.route <= 0 then
+ chat(pname, "Cannot program route without a target")
+ return
+ end
+
+ local tcbs = advtrains.interlocking.db.get_tcbs(rp.origin)
+ if not tcbs then
+ chat(pname, "The origin TCB has become unknown during programming. Try again.")
+ return
+ end
+
+ local terminal = get_last_route_item(rp.origin, rp.route)
+ rp.route.terminal = terminal
+ rp.route.name = fields.name
+
+ table.insert(tcbs.routes, rp.route)
+
+ advtrains.interlocking.clear_visu_context("prog_"..pname)
+ player_rte_prog[pname] = nil
+ chat(pname, "Successfully programmed route.")
+ return
+ end
+ end
+end)
+
+
-- Central route programming punch callback
minetest.register_on_punchnode(function(pos, node, player, pointed_thing)
local pname = player:get_player_name()
@@ -224,38 +517,12 @@ minetest.register_on_punchnode(function(pos, node, player, pointed_thing)
end
local tcbpos = minetest.string_to_pos(tcbpts)
- -- track circuit break, try to advance route over it
- local lri = get_last_route_item(rp.origin, rp.route)
- if vector.equals(lri.p, tcbpos) then
- chat(pname, "You cannot continue the route to where you came from!")
- return
- end
-
- local start_tcbs = advtrains.interlocking.db.get_tcbs(lri)
- if not start_tcbs.ts_id then
- chat(pname, "The previous TCB was End of Interlocking. Please complete route programming using '/at_rp_set <name>'")
- return
- end
+ -- show formspec
- local ts = advtrains.interlocking.db.get_ts(start_tcbs.ts_id)
- if not ts then atwarn("Internal error, ts inexistant for id!") return end
- local found = nil
- for _,sigd in ipairs(ts.tc_breaks) do
- if vector.equals(sigd.p, tcbpos) then
- found = otherside(sigd.s)
- end
- end
- if not found then
- chat(pname, "Previous and this TCB belong to different track sections!")
- return
- end
- -- TODO check the path: are all route turnouts locked to the right position?
+ show_routing_form(pname, tcbpos)
- -- everything worked, just add the other side to the list
- table.insert(rp.route, {next = {p = tcbpos, s = found}, locks = rp.tmp_lcks})
- rp.tmp_lcks = {}
- chat(pname, "Added track section '"..ts.name.."' to the route (revert with /at_rp_back)")
advtrains.interlocking.visualize_route(rp.origin, rp.route, "prog_"..pname, rp.tmp_lcks, pname)
+
return
end
if advtrains.is_passive(pos) then
@@ -274,90 +541,6 @@ minetest.register_on_punchnode(function(pos, node, player, pointed_thing)
end
end)
-minetest.register_chatcommand("at_rp_set",
- {
- params = "<name>", -- Short parameter description
- description = "Completes route programming procedure", -- Full description
- privs = {interlocking = true},
- func = function(pname, param)
- return advtrains.pcall(function()
- if param=="" then
- return false, "Missing name parameter!"
- end
- local rp = player_rte_prog[pname]
- if rp then
- if #rp.route <= 0 then
- return false, "Cannot program route without a target"
- end
- rp.route.name = param
-
- local tcbs = advtrains.interlocking.db.get_tcbs(rp.origin)
- if not tcbs then
- return false, "The origin TCB of this route doesn't exist!"
- end
-
- table.insert(tcbs.routes, rp.route)
-
- advtrains.interlocking.clear_visu_context("prog_"..pname)
- player_rte_prog[pname] = nil
- return true, "Successfully programmed route"
- end
- return false, "You are not programming a route!"
- end)
- end,
- })
-
-minetest.register_chatcommand("at_rp_back",
- {
- params = "", -- Short parameter description
- description = "Remove last route segment", -- Full description
- privs = {interlocking = true},
- func = function(pname, param)
- return advtrains.pcall(function()
- local rp = player_rte_prog[pname]
- if rp then
- if #rp.route <= 0 then
- return false, "Cannot backtrack when there are no route elements"
- end
- rp.tmp_locks = rp.route[#rp.route].locks
- rp.route[#rp.route] = nil
- advtrains.interlocking.visualize_route(rp.origin, rp.route, "prog_"..pname)
- return true, "Route section "..(#rp.route+1).." removed."
- end
- return false, "You are not programming a route!"
- end)
- end,
- })
-minetest.register_chatcommand("at_rp_mark",
- {
- params = "", -- Short parameter description
- description = "Re-set route programming markers", -- Full description
- privs = {interlocking = true},
- func = function(pname, param)
- return advtrains.pcall(function()
- local rp = player_rte_prog[pname]
- if rp then
- advtrains.interlocking.visualize_route(rp.origin, rp.route, "prog_"..pname)
- return true, "Redrawn route markers"
- end
- return false, "You are not programming a route!"
- end)
- end,
- })
-minetest.register_chatcommand("at_rp_discard",
- {
- params = "", -- Short parameter description
- description = "Discards the currently programmed route", -- Full description
- privs = {interlocking = true},
- func = function(pname, param)
- return advtrains.pcall(function()
- player_rte_prog[pname] = nil
- advtrains.interlocking.clear_visu_context("prog_"..pname)
- return true, "Route discarded"
- end)
- end,
- })
-
--TODO on route setting
-- routes should end at signals. complete route setting by punching a signal, and command as exceptional route completion
diff --git a/advtrains_interlocking/routesetting.lua b/advtrains_interlocking/routesetting.lua
index 66f2d2b..2c61041 100644
--- a/advtrains_interlocking/routesetting.lua
+++ b/advtrains_interlocking/routesetting.lua
@@ -163,7 +163,7 @@ function ilrs.free_route_locks_indiv(pts, ts, nocallbacks)
local i = 1
while i <= #e do
if e[i].by == ts then
- atdebug("free_route_locks_indiv",pts,"clearing entry",e[i].by,e[i].rsn)
+ --atdebug("free_route_locks_indiv",pts,"clearing entry",e[i].by,e[i].rsn)
table.remove(e,i)
else
i = i + 1
@@ -244,7 +244,7 @@ function ilrs.update_route(sigd, tcbs, newrte, cancel)
tcbs.aspect = nil
if (newrte and tcbs.routeset and tcbs.routeset ~= newrte) or cancel then
if tcbs.route_committed then
- atdebug("Cancelling:",tcbs.routeset)
+ --atdebug("Cancelling:",tcbs.routeset)
advtrains.interlocking.route.cancel_route_from(sigd)
end
tcbs.route_committed = nil
@@ -253,24 +253,24 @@ function ilrs.update_route(sigd, tcbs, newrte, cancel)
end
if newrte or tcbs.routeset then
if newrte then tcbs.routeset = newrte end
- atdebug("Setting:",tcbs.routeset)
+ --atdebug("Setting:",tcbs.routeset)
local succ, rsn, cbts, cblk = ilrs.set_route(sigd, tcbs.routes[tcbs.routeset])
if not succ then
tcbs.route_rsn = rsn
- atdebug("Routesetting failed:",rsn)
+ --atdebug("Routesetting failed:",rsn)
-- add cbts or cblk to callback table
if cbts then
- atdebug("cbts =",cbts)
+ --atdebug("cbts =",cbts)
if not ilrs.rte_callbacks.ts[cbts] then ilrs.rte_callbacks.ts[cbts]={} end
advtrains.insert_once(ilrs.rte_callbacks.ts[cbts], sigd, sigd_equal)
end
if cblk then
- atdebug("cblk =",cblk)
+ --atdebug("cblk =",cblk)
if not ilrs.rte_callbacks.lck[cblk] then ilrs.rte_callbacks.lck[cblk]={} end
advtrains.insert_once(ilrs.rte_callbacks.lck[cblk], sigd, sigd_equal)
end
else
- atdebug("Committed Route:",tcbs.routeset)
+ --atdebug("Committed Route:",tcbs.routeset)
tcbs.route_committed = true
tcbs.route_rsn = false
tcbs.aspect = asp_generic_free
@@ -283,12 +283,12 @@ end
-- sys can be one of "ts" and "lck"
-- key is then ts_id or pts respectively
function ilrs.update_waiting(sys, key)
- atdebug("update_waiting:",sys,".",key)
+ --atdebug("update_waiting:",sys,".",key)
local t = ilrs.rte_callbacks[sys][key]
ilrs.rte_callbacks[sys][key] = nil
if t then
for _,sigd in ipairs(t) do
- atdebug("Updating", sigd)
+ --atdebug("Updating", sigd)
-- While these are run, the table we cleared before may be populated again, which is in our interest.
-- (that's the reason we needed to copy it)
local tcbs = ildb.get_tcbs(sigd)
diff --git a/advtrains_interlocking/textures/at_il_route_lock.png b/advtrains_interlocking/textures/at_il_route_lock.png
index 57eba71..6a5269b 100644
--- a/advtrains_interlocking/textures/at_il_route_lock.png
+++ b/advtrains_interlocking/textures/at_il_route_lock.png
Binary files differ
diff --git a/advtrains_interlocking/textures/at_il_route_lock_edit.png b/advtrains_interlocking/textures/at_il_route_lock_edit.png
index a743feb..df5f923 100644
--- a/advtrains_interlocking/textures/at_il_route_lock_edit.png
+++ b/advtrains_interlocking/textures/at_il_route_lock_edit.png
Binary files differ
diff --git a/advtrains_interlocking/textures/at_il_routep_advance.png b/advtrains_interlocking/textures/at_il_routep_advance.png
new file mode 100644
index 0000000..d971e85
--- /dev/null
+++ b/advtrains_interlocking/textures/at_il_routep_advance.png
Binary files differ
diff --git a/advtrains_interlocking/textures/at_il_routep_end_here.png b/advtrains_interlocking/textures/at_il_routep_end_here.png
new file mode 100644
index 0000000..9dd3088
--- /dev/null
+++ b/advtrains_interlocking/textures/at_il_routep_end_here.png
Binary files differ
diff --git a/advtrains_interlocking/textures/at_il_routep_end_over.png b/advtrains_interlocking/textures/at_il_routep_end_over.png
new file mode 100644
index 0000000..e03198b
--- /dev/null
+++ b/advtrains_interlocking/textures/at_il_routep_end_over.png
Binary files differ
diff --git a/advtrains_interlocking/textures/at_il_routep_end_over_last.png b/advtrains_interlocking/textures/at_il_routep_end_over_last.png
new file mode 100644
index 0000000..f4fb1aa
--- /dev/null
+++ b/advtrains_interlocking/textures/at_il_routep_end_over_last.png
Binary files differ
diff --git a/advtrains_interlocking/train_related.lua b/advtrains_interlocking/train_related.lua
index a92e18f..8bc9716 100644
--- a/advtrains_interlocking/train_related.lua
+++ b/advtrains_interlocking/train_related.lua
@@ -164,7 +164,7 @@ advtrains.te_register_on_create(function(id, train)
elseif ts_id==nil then
atwarn("Train",id,": Unable to determine whether to block a track section!")
else
- atdebug("Train",id,": Outside of interlocked area!")
+ --atdebug("Train",id,": Outside of interlocked area!")
end
end)
diff --git a/assets/interlocking.html.LyXconv/interlocking.html b/assets/interlocking.html.LyXconv/interlocking.html
index 98f5ac9..33a2d4e 100644
--- a/assets/interlocking.html.LyXconv/interlocking.html
+++ b/assets/interlocking.html.LyXconv/interlocking.html
@@ -443,33 +443,47 @@ of the route. Now:
<ul class="itemize1">
<li class="itemize">Put any turnouts you need to lock in the correct position (e.g. by right-clicking them). This includes flank protection.
</li>
- <li class="itemize">Punch them. This makes a marker saying &#8220;Route Lock Editing&#8221; appear.
+ <li class="itemize">Punch them. This makes a marker with a blue lock symbol appear.
</li>
<li class="itemize">If you punch a turnout again, or punch the marker, you can remove the lock again.
</li>
<li class="itemize">When you&#8217;ve locked all turnouts in the current section, go to and punch the TCB that is the border to the next track
section the train proceeds into.</li></ul>
-<!--l. 364--><p class="noindent" >Once you&#8217;ve done this, the lock markers change to &#8220;Route Lock&#8221;, telling they can&#8217;t be changed anymore. Repeat the above procedure until
-you have punched the final TCB, at which the route should end. As mentioned before, there should be a signal at this place,
-however this is not enforced. Now, run the chat command <span
-class="ectt-1000">/at_rp_set &#x003C;name of route&#x003E; </span>to complete programming the
-route.
-<!--l. 371--><p class="noindent" >A few hints:
+<!--l. 364--><p class="noindent" >Depending on the situation, you are now offered some possibilities to proceed:
+ <ul class="itemize1">
+ <li class="itemize">Click the &#8220;Advance to next section&#8221; button if your route consists of more sections with turnouts to lock, and you need to
+ continue programming. Follow the above steps to set locks for the next section.</li></ul>
+<!--l. 371--><p class="noindent" >Once you&#8217;ve clicked the &#8220;Advance&#8221; button, the lock markers change to a red lock symbol, telling they can&#8217;t be changed anymore. Repeat
+the above procedure until you are ready to complete the programming procedure:
+ <ul class="itemize1">
+ <li class="itemize">Click the &#8220;Finish route HERE&#8221; button when you&#8217;ve set up the locks for the last track section of the route and punched the
+ final TCB (the one with the next signal). You will be asked for a route name and your route will be saved.
+ </li>
+ <li class="itemize">The &#8220;Finish route at end of NEXT section&#8221; button (third button) is an useful quickhand to make the route proceed one
+ more section. Using this button is equivalent to first clicking the &#8220;Advance&#8221; button, then flying to the end of the next track
+ section and finishing the route there. You can not (officially) set turnout locks in the final section using this method.</li></ul>
+<!--l. 387--><p class="noindent" >A few hints:
<ul class="itemize1">
<li class="itemize">If one turnout should be locked by more than one section, set the lock only in the <span
class="ectt-1000">last </span>of those sections. Locking the same
turnout in multiple sections of a single route results in undefined behavior!
</li>
- <li class="itemize">If you accidentally punched a TCB, you can run <span
-class="ectt-1000">/at_rp_back </span>to undo this and return to the previous section. Due to a
- bug, you have to re-set all locks of this section.
+ <li class="itemize">If you accidentally advanced the route wrongly, you can use the &#8220;Step back one section&#8221; button to undo this.
+ </li>
+ <li class="itemize">If you want to stop programming the entire route without saving it, use the &#8220;Cancel route programming&#8221; button.
+ </li>
+ <li class="itemize">The third button is especially useful for programming simple block sections on a main running line, since you can stay at
+ the starting signal (punch starting TCB and select third button).
+ </li>
+ <li class="itemize">If a route should end in a dead end, you MUST use the &#8220;Finish in NEXT section&#8221; button, because there is no final TCB
+ that you could punch.
</li>
- <li class="itemize">If you want to stop programming the entire route without saving it, run <span
-class="ectt-1000">/at_rp_discard</span></li></ul>
-<!--l. 384--><p class="noindent" >
+ <li class="itemize">The third button does NOT work on sections with more than 2 exits, because the system won&#8217;t be able to determine the
+ final TCB of the route then.</li></ul>
+<!--l. 408--><p class="noindent" >
<a
id="x1-47r4"></a>
- <!--l. 384--><p class="noindent" ><span
+ <!--l. 408--><p class="noindent" ><span
class="ecsx-1200">4</span> <span
class="ecsx-1200">Interlocking</span>
<span
@@ -478,15 +492,15 @@ class="ecsx-1200">system</span>
class="ecsx-1200">operation</span>
<a
id="Q1-1-0"></a>
-<!--l. 386--><p class="noindent" >Setting up the interlocking for a portion of a railway network requires some time, experience and planning, but once done, there&#8217;s not
+<!--l. 410--><p class="noindent" >Setting up the interlocking for a portion of a railway network requires some time, experience and planning, but once done, there&#8217;s not
much to do anymore to make trains run on your, now safer, railway. This section covers some useful practices to route trains across your
network.
-<!--l. 391--><p class="noindent" >At the moment, routes can only be set by clicking the signal or via LuaATC, except if you use automatic working. It is planned to control
+<!--l. 415--><p class="noindent" >At the moment, routes can only be set by clicking the signal or via LuaATC, except if you use automatic working. It is planned to control
this via the onboard computer and via a &#8220;signal box&#8221; view based on the currently broken itrainmap.
-<!--l. 396--><p class="noindent" >
+<!--l. 420--><p class="noindent" >
<a
id="x1-48r1"></a>
- <!--l. 396--><p class="noindent" ><span
+ <!--l. 420--><p class="noindent" ><span
class="ecsx-1200">4.1</span> <span
class="ecsx-1200">Simple</span>
<span
@@ -499,44 +513,44 @@ class="ecsx-1200">and</span>
class="ecsx-1200">cancelling</span>
<a
id="Q1-1-0"></a>
-<!--l. 398--><p class="noindent" >To set a route, simply right-click the signal, select a route and click &#8220;set route&#8221;. If there are no conflicts, the signal turns green and the
+<!--l. 422--><p class="noindent" >To set a route, simply right-click the signal, select a route and click &#8220;set route&#8221;. If there are no conflicts, the signal turns green and the
train is allowed to proceed.
-<!--l. 402--><p class="noindent" >It may be possible that the route can not be set, because one or more other routes conflict with the current one, or a section is blocked. In
+<!--l. 426--><p class="noindent" >It may be possible that the route can not be set, because one or more other routes conflict with the current one, or a section is blocked. In
this case, the signal stays red, and the conflicting item is shown in the formspec. As soon as the conflict is resolved (by cancellation
or release of the conflicting route, or the section becoming free), the requested route will be set and the signal turns
green.
-<!--l. 409--><p class="noindent" >If a route is either requested or set, it can be cancelled from the signalling formspec. This means that all turnouts and sections are
+<!--l. 433--><p class="noindent" >If a route is either requested or set, it can be cancelled from the signalling formspec. This means that all turnouts and sections are
released, and the signal reverts back to red. This of course only works when the train has not passed the signal yet. There is no
mechanism for Approach Locking.
-<!--l. 415--><p class="noindent" >
+<!--l. 439--><p class="noindent" >
<a
id="x1-49r2"></a>
- <!--l. 415--><p class="noindent" ><span
+ <!--l. 439--><p class="noindent" ><span
class="ecsx-1200">4.2</span> <span
class="ecsx-1200">Automatic</span>
<span
class="ecsx-1200">Working</span>
<a
id="Q1-1-0"></a>
-<!--l. 417--><p class="noindent" >Block signals on main running lines usually only have a single route to set, the one proceeding along the main line. Their purpose is only
+<!--l. 441--><p class="noindent" >Block signals on main running lines usually only have a single route to set, the one proceeding along the main line. Their purpose is only
to show whether there are trains in the next section. So, it would be convenient if this only route would set itself again after a train
passed.
-<!--l. 423--><p class="noindent" >This is what Automatic Working is for. Set a route, click &#8220;Enable Automatic Working&#8221;, and as soon as a train passes, the route is
+<!--l. 447--><p class="noindent" >This is what Automatic Working is for. Set a route, click &#8220;Enable Automatic Working&#8221;, and as soon as a train passes, the route is
automatically re-set.
-<!--l. 427--><p class="noindent" >This function is nearly identical to SimSig automatic signals. It can also be useful on a line with high traffic, when there&#8217;s a
+<!--l. 451--><p class="noindent" >This function is nearly identical to SimSig automatic signals. It can also be useful on a line with high traffic, when there&#8217;s a
low-frequented access to a siding. You&#8217;d enable automatic working for the main route and cancel it only when you need a train to go into
the siding.
-<!--l. 432--><p class="noindent" >
+<!--l. 456--><p class="noindent" >
<a
id="x1-50r5"></a>
- <!--l. 432--><p class="noindent" ><span
+ <!--l. 456--><p class="noindent" ><span
class="ecsx-1200">5</span> <span
class="ecsx-1200">Final</span>
<span
class="ecsx-1200">notes</span>
<a
id="Q1-1-0"></a>
-<!--l. 434--><p class="noindent" >The interlocking system is mainly finished, though there are still some plans and ideas. They include:
+<!--l. 458--><p class="noindent" >The interlocking system is mainly finished, though there are still some plans and ideas. They include:
<ul class="itemize1">
<li class="itemize">Setting routes from inside a train (via onboard computer)
</li>
@@ -547,11 +561,11 @@ class="ecsx-1200">notes</span>
<li class="itemize">Distant signals
</li>
<li class="itemize">On-Train head-up display for oncoming signals (they have something like this in Czech Republic, I forgot how it&#8217;s called.)</li></ul>
-<!--l. 444--><p class="noindent" >Apart from this, there&#8217;s the large oncoming project of a new timetable-based train automation system, but this will take some time to
+<!--l. 468--><p class="noindent" >Apart from this, there&#8217;s the large oncoming project of a new timetable-based train automation system, but this will take some time to
evolve and is out of the scope of this document.
-<!--l. 448--><p class="noindent" >If you have any suggestions, corrections, improvements, criticism or cute kittens and stuff, you can always contact me by various means
+<!--l. 472--><p class="noindent" >If you have any suggestions, corrections, improvements, criticism or cute kittens and stuff, you can always contact me by various means
(Forum PM, E-Mail (orwell@bleipb.de), Linuxworks server chat a.s.o.). Have fun!
-<!--l. 453--><p class="noindent" >- orwell
+<!--l. 477--><p class="noindent" >- orwell
</body></html>
diff --git a/assets/interlocking.lyx b/assets/interlocking.lyx
index 9e9e94f..08e47da 100644
--- a/assets/interlocking.lyx
+++ b/assets/interlocking.lyx
@@ -933,15 +933,7 @@ Put any turnouts you need to lock in the correct position (e.g.
\begin_layout Itemize
Punch them.
- This makes a marker saying
-\begin_inset Quotes eld
-\end_inset
-
-Route Lock Editing
-\begin_inset Quotes erd
-\end_inset
-
- appear.
+ This makes a marker with a blue lock symbol appear.
\end_layout
\begin_layout Itemize
@@ -956,24 +948,75 @@ When you've locked all turnouts in the current section, go to and punch
\end_layout
\begin_layout Standard
-Once you've done this, the lock markers change to
+Depending on the situation, you are now offered some possibilities to proceed:
+\end_layout
+
+\begin_layout Itemize
+Click the
\begin_inset Quotes eld
\end_inset
-Route Lock
+Advance to next section
\begin_inset Quotes erd
\end_inset
-, telling they can't be changed anymore.
- Repeat the above procedure until you have punched the final TCB, at which
- the route should end.
- As mentioned before, there should be a signal at this place, however this
- is not enforced.
- Now, run the chat command
-\family typewriter
-/at_rp_set <name of route>
-\family default
- to complete programming the route.
+ button if your route consists of more sections with turnouts to lock, and
+ you need to continue programming.
+ Follow the above steps to set locks for the next section.
+\end_layout
+
+\begin_layout Standard
+Once you've clicked the
+\begin_inset Quotes eld
+\end_inset
+
+Advance
+\begin_inset Quotes erd
+\end_inset
+
+ button, the lock markers change to a red lock symbol, telling they can't
+ be changed anymore.
+ Repeat the above procedure until you are ready to complete the programming
+ procedure:
+\end_layout
+
+\begin_layout Itemize
+Click the
+\begin_inset Quotes eld
+\end_inset
+
+Finish route HERE
+\begin_inset Quotes erd
+\end_inset
+
+ button when you've set up the locks for the last track section of the route
+ and punched the final TCB (the one with the next signal).
+ You will be asked for a route name and your route will be saved.
+\end_layout
+
+\begin_layout Itemize
+The
+\begin_inset Quotes eld
+\end_inset
+
+Finish route at end of NEXT section
+\begin_inset Quotes erd
+\end_inset
+
+ button (third button) is an useful quickhand to make the route proceed
+ one more section.
+ Using this button is equivalent to first clicking the
+\begin_inset Quotes eld
+\end_inset
+
+Advance
+\begin_inset Quotes erd
+\end_inset
+
+ button, then flying to the end of the next track section and finishing
+ the route there.
+ You can not (officially) set turnout locks in the final section using this
+ method.
\end_layout
\begin_layout Standard
@@ -994,19 +1037,51 @@ last
\end_layout
\begin_layout Itemize
-If you accidentally punched a TCB, you can run
-\family typewriter
-/at_rp_back
-\family default
- to undo this and return to the previous section.
- Due to a bug, you have to re-set all locks of this section.
+If you accidentally advanced the route wrongly, you can use the
+\begin_inset Quotes eld
+\end_inset
+
+Step back one section
+\begin_inset Quotes erd
+\end_inset
+
+ button to undo this.
\end_layout
\begin_layout Itemize
-If you want to stop programming the entire route without saving it, run
-
-\family typewriter
-/at_rp_discard
+If you want to stop programming the entire route without saving it, use
+ the
+\begin_inset Quotes eld
+\end_inset
+
+Cancel route programming
+\begin_inset Quotes erd
+\end_inset
+
+ button.
+\end_layout
+
+\begin_layout Itemize
+The third button is especially useful for programming simple block sections
+ on a main running line, since you can stay at the starting signal (punch
+ starting TCB and select third button).
+\end_layout
+
+\begin_layout Itemize
+If a route should end in a dead end, you MUST use the
+\begin_inset Quotes eld
+\end_inset
+
+Finish in NEXT section
+\begin_inset Quotes erd
+\end_inset
+
+ button, because there is no final TCB that you could punch.
+\end_layout
+
+\begin_layout Itemize
+The third button does NOT work on sections with more than 2 exits, because
+ the system won't be able to determine the final TCB of the route then.
\end_layout
\begin_layout Section
diff --git a/assets/interlocking.lyx~ b/assets/interlocking.lyx~
index 0a881dc..ea118c0 100644
--- a/assets/interlocking.lyx~
+++ b/assets/interlocking.lyx~
@@ -933,15 +933,7 @@ Put any turnouts you need to lock in the correct position (e.g.
\begin_layout Itemize
Punch them.
- This makes a marker saying
-\begin_inset Quotes eld
-\end_inset
-
-Route Lock Editing
-\begin_inset Quotes erd
-\end_inset
-
- appear.
+ This makes a marker with a blue lock symbol appear.
\end_layout
\begin_layout Itemize
@@ -956,24 +948,75 @@ When you've locked all turnouts in the current section, go to and punch
\end_layout
\begin_layout Standard
-Once you've done this, the lock markers change to
+Depending on the situation, you are now offered some possibilities to proceed:
+\end_layout
+
+\begin_layout Itemize
+Click the
\begin_inset Quotes eld
\end_inset
-Route Lock
+Advance to next section
\begin_inset Quotes erd
\end_inset
-, telling they can't be changed anymore.
- Repeat the above procedure until you have punched the final TCB, at which
- the route should end.
- As mentioned before, there should be a signal at this place, however this
- is not enforced.
- Now, run the chat command
-\family typewriter
-/at_rp_set <name of route>
-\family default
- to complete programming the route.
+ button if your route consists of more sections with turnouts to lock, and
+ you need to continue programming.
+ Follow the above steps to set locks for the next section.
+\end_layout
+
+\begin_layout Standard
+Once you've clicked the
+\begin_inset Quotes eld
+\end_inset
+
+Advance
+\begin_inset Quotes erd
+\end_inset
+
+ button, the lock markers change to a red lock symbol, telling they can't
+ be changed anymore.
+ Repeat the above procedure until you are ready to complete the programming
+ procedure:
+\end_layout
+
+\begin_layout Itemize
+Click the
+\begin_inset Quotes eld
+\end_inset
+
+Finish route HERE
+\begin_inset Quotes erd
+\end_inset
+
+ button when you've set up the locks for the last track section of the route
+ and punched the final TCB (the one with the next signal).
+ You will be asked for a route name and your route will be saved.
+\end_layout
+
+\begin_layout Itemize
+The
+\begin_inset Quotes eld
+\end_inset
+
+Finish route at end of NEXT section
+\begin_inset Quotes erd
+\end_inset
+
+ button (third button) is an useful quickhand to make the route proceed
+ one more section.
+ Using this button is equivalent to first clicking the
+\begin_inset Quotes eld
+\end_inset
+
+Advance
+\begin_inset Quotes erd
+\end_inset
+
+ button, then flying to the end of the next track section and finishing
+ the route there.
+ You can not (officially) set turnout locks in the final section using this
+ method.
\end_layout
\begin_layout Standard
@@ -994,19 +1037,46 @@ last
\end_layout
\begin_layout Itemize
-If you accidentally punched a TCB, you can run
-\family typewriter
-/at_rp_back
-\family default
- to undo this and return to the previous section.
- Due to a bug, you have to re-set all locks of this section.
+If you accidentally advanced the route wrongly, you can use the
+\begin_inset Quotes eld
+\end_inset
+
+Step back one section
+\begin_inset Quotes erd
+\end_inset
+
+ button to undo this.
\end_layout
\begin_layout Itemize
-If you want to stop programming the entire route without saving it, run
-
-\family typewriter
-/at_rp_discard
+If you want to stop programming the entire route without saving it, use
+ the
+\begin_inset Quotes eld
+\end_inset
+
+Cancel route programming
+\begin_inset Quotes erd
+\end_inset
+
+ button.
+\end_layout
+
+\begin_layout Itemize
+The third button is especially useful for programming simple block sections
+ on a main running line, since you can stay at the starting signal (punch
+ starting TCB and select third button).
+\end_layout
+
+\begin_layout Itemize
+If a route should end in a dead end, you MUST use the
+\begin_inset Quotes eld
+\end_inset
+
+Finish in NEXT section
+\begin_inset Quotes erd
+\end_inset
+
+ button, because there is no final TCB that you could punch.
\end_layout
\begin_layout Section
@@ -1105,5 +1175,53 @@ d access to a siding.
you need a train to go into the siding.
\end_layout
+\begin_layout Section
+Final notes
+\end_layout
+
+\begin_layout Standard
+The interlocking system is mainly finished, though there are still some
+ plans and ideas.
+ They include:
+\end_layout
+
+\begin_layout Itemize
+Setting routes from inside a train (via onboard computer)
+\end_layout
+
+\begin_layout Itemize
+Signalbox panels, as revival of itrainmap
+\end_layout
+
+\begin_layout Itemize
+Individual signal aspects for routes
+\end_layout
+
+\begin_layout Itemize
+Distant signals
+\end_layout
+
+\begin_layout Itemize
+On-Train head-up display for oncoming signals (they have something like
+ this in Czech Republic, I forgot how it's called.)
+\end_layout
+
+\begin_layout Standard
+Apart from this, there's the large oncoming project of a new timetable-based
+ train automation system, but this will take some time to evolve and is
+ out of the scope of this document.
+\end_layout
+
+\begin_layout Standard
+If you have any suggestions, corrections, improvements, criticism or cute
+ kittens and stuff, you can always contact me by various means (Forum PM,
+ E-Mail (orwell@bleipb.de), Linuxworks server chat a.s.o.).
+ Have fun!
+\end_layout
+
+\begin_layout Standard
+- orwell
+\end_layout
+
\end_body
\end_document