This shows you the differences between two versions of the page.
Next revision | Previous revision | ||
usage:atlatc:examples:linuxforks_subway_code [2022-06-28 09:37] 56independent created |
usage:atlatc:examples:linuxforks_subway_code [2024-05-23 03:03] (current) blockhead Fix indentation of subway stat counter digiline message |
||
---|---|---|---|
Line 1: | Line 1: | ||
- | ====== Linuxforks Subway ====== | + | ====== Linuxforks Subway |
===== Introduction ===== | ===== Introduction ===== | ||
**Note**: This is actually taken from a [[https:// | **Note**: This is actually taken from a [[https:// | ||
Line 5: | Line 5: | ||
I've actually wanted to make a video about the subway code just because I think it's of historical interest but also as an example of how to make an interlocking system out of just LuaATC. Consider this like a partial script dump for that video. | I've actually wanted to make a video about the subway code just because I think it's of historical interest but also as an example of how to make an interlocking system out of just LuaATC. Consider this like a partial script dump for that video. | ||
- | The subway code is something like (A? | + | The subway code is written by orwell, and uses the GPLv3 license. It's a form of interlocking that predates what we call "TSS Interlocking" |
The current code is as follows (it's not all properly indented, much of it may have been edited in-game. It probably started back in 2017, but has barely changed since 2019 due to maturity, stability and decreasing relevance. | The current code is as follows (it's not all properly indented, much of it may have been edited in-game. It probably started back in 2017, but has barely changed since 2019 due to maturity, stability and decreasing relevance. | ||
Line 41: | Line 41: | ||
===== Code ===== | ===== Code ===== | ||
+ | The current code is as follows (< | ||
+ | |||
<code lua> | <code lua> | ||
+ | --[[ | ||
+ | Linuxforks Subway Code | ||
+ | Copyright (C) 2017-2021 orwell96 and other LinuxForks contributors. | ||
+ | Licensed under the terms of the GNU General Public License, Version 3 or later | ||
+ | --]] | ||
-- ' | -- ' | ||
--F.stn_union=function(line1, | --F.stn_union=function(line1, | ||
- | F.stationnames={ | + | F.stationnames = { |
- | Ewb=" | + | Ewb = " |
- | Ban=" | + | Ban = " |
- | ctr=" | + | ctr = " |
- | Cht=" | + | Cht = " |
- | Bbe=" | + | Bbe = "Birch Bay East", |
- | Bap=" | + | Bap = " |
- | Icm=" | + | Icm = "Ice Mountain", |
- | Eft=" | + | Eft = " |
- | Apl=" | + | Apl = "Apple Plains", |
- | Pal=" | + | Pal = "Palm Bay", |
- | Slh=" | + | Slh = " |
- | Lks=" | + | Lks = " |
- | Ta1=" | + | Ta1 = " |
- | Ta2=" | + | Ta2 = " |
- | Ahr=" | + | Ahr = " |
- | Ahz=" | + | Ahz = "Large Beach", |
- | Wim=" | + | Wim = "Windy Mountains", |
- | Dam=" | + | Dam = " |
- | Wva=" | + | Wva = "Windy Mountains Valley 1", |
- | Wvb=" | + | Wvb = "Windy Mountains Valley 2", |
- | Wvc=" | + | Wvc = "Windy Mountains Valley 3", |
- | App=" | + | App = "Apple Grove", |
- | Dem=" | + | Dem = " |
- | Dev=" | + | Dev = " |
- | Lvc=" | + | Lvc = " |
- | Gho=" | + | Gho = "Green Hope", |
- | Snb=" | + | Snb = "Snake Bend", |
- | Adb=" | + | Adb = " |
- | Duf=" | + | Duf = "Duff Road", |
- | Wat=" | + | Wat = " |
- | Ram=" | + | Ram = " |
- | Per=" | + | Per = " |
- | Trp=" | + | Trp = "Trump Park", |
- | Sfs=" | + | Sfs = "South Forest Station", |
- | Lok=" | + | Lok = "Jude Milhon Street", |
- | Bam=" | + | Bam = " |
- | Sfa=" | + | Sfa = " |
- | Gcl=" | + | Gcl = "Green Cliffs", |
- | Dri=" | + | Dri = "Dry Island", |
- | Ged=" | + | Ged = "Green Edge", |
- | Ghb=" | + | Ghb = "Green Hill Beach", |
- | Acm=" | + | Acm = " |
- | Ghm=" | + | Ghm = " |
- | Pna=" | + | Pna = "Pence Avenue", |
- | Dbl=" | + | Dbl = " |
- | Sws=" | + | Sws = " |
- | Mnk=" | + | Mnk = " |
- | Rgs=" | + | Rgs = " |
- | Ehl=" | + | Ehl = " |
- | Lus=" | + | Lus = "Lusin Street", |
- | Lin=" | + | Lin = " |
- | Boz=" | + | Boz = "Booze Grove", |
- | Mrh=" | + | Mrh = " |
- | Plt=" | + | Plt = " |
- | Mcf=" | + | Mcf = "McFly Street", |
- | Tha=" | + | Tha = " |
- | Oni=" | + | Oni = " |
- | Ora=" | + | Ora = " |
- | Uaa=" | + | Uaa = " |
- | Leo=" | + | Leo = " |
- | Bby=" | + | Bby = "Birch Bay", |
- | Stb=" | + | Stb = "Stone Beach", |
- | Jis=" | + | Jis = " |
- | Ice=" | + | Ice = " |
- | Bnt=" | + | Bnt = " |
- | Osa=" | + | Osa = " |
- | OBa=" | + | OBa = " |
- | OOr=" | + | OOr = " |
- | OSc=" | + | OSc = " |
- | ONb=" | + | ONb = "Intel ME Stairs", |
- | OIs=" | + | OIs = "SCSI Connector Mess", |
- | OSm=" | + | OSm = " |
- | ioa=" | + | ioa = "Cow Bridge", |
- | iob=" | + | iob = " |
- | Wcs=" | + | Wcs = " |
- | Rru=" | + | Rru = " |
- | Ewd=" | + | Ewd = " |
- | Chu=" | + | Chu = " |
- | Erd=" | + | Erd = "Erdos Street", |
- | Uni=" | + | Uni = " |
- | Mar=" | + | Mar = " |
- | Wac=" | + | Wac = " |
- | OLv=" | + | OLv = " |
- | Irk=" | + | Irk = "Ice Rink", |
- | Sbr=" | + | Sbr = " |
- | Unv=" | + | Unv = " |
- | Arc=" | + | Arc = " |
- | Dar=" | + | Dar = " |
- | Hmi=" | + | Hmi = " |
- | Zoo=" | + | Zoo = " |
- | Bea=" | + | Bea = " |
- | Yos=" | + | Yos = "Yoshi Island", |
- | Krs=" | + | Krs = " |
- | Rkb=" | + | Rkb = " |
- | Rsi=" | + | Rsi = " |
- | Swr=" | + | Swr = " |
- | Wbb=" | + | Wbb = " |
- | Ori=" | + | Ori = " |
- | Snl=" | + | Snl = " |
- | Sys=" | + | Sys = "Ship Rock", |
- | Rfo=" | + | Rfo = " |
- | Moj=" | + | Moj = "Mom Junction", |
- | Wfr=" | + | Wfr = "Wolf Rock", |
- | Spa=" | + | Spa = " |
- | Thh=" | + | Thh = " |
- | Stn=" | + | Stn = "Main station", |
- | WB1=" | + | WB1 = " |
- | WB2=" | + | WB2 = " |
- | WB3=" | + | WB3 = " |
- | WB4=" | + | WB4 = " |
- | WB5=" | + | WB5 = "White Beaches", |
- | Shn=" | + | Shn = " |
- | Jus=" | + | Jus = "Tom Lehrer Street", |
- | Fre=" | + | Fre = "Frege Street", |
- | Min=" | + | Min = " |
- | Vlc=" | + | Vlc = " |
- | Mio=" | + | Mio = " |
- | Wpy=" | + | Wpy = "Water Pyramid", |
- | Cat=" | + | Cat = " |
- | Dca=" | + | Dca = " |
- | Spn=" | + | Spn = " |
- | Brn=" | + | Brn = " |
- | Kav=" | + | Kav = "Knuth Avenue", |
- | Lvf=" | + | Lvf = " |
- | Fms=" | + | Fms = "John Horton Conway Street", |
- | Mnt=" | + | Mnt = " |
- | Mnv=" | + | Mnv = " |
- | Mnn=" | + | Mnn = " |
- | Max=" | + | Max = " |
- | Snp=" | + | Snp = "Snowy Peak", |
- | Scl=" | + | Scl = " |
- | Lza=" | + | Lza = " |
- | Bld=" | + | Bld = " |
- | Hts=" | + | Hts = "Hotel Shanielle", |
- | Fmn=" | + | Fmn = "Euler Street", |
- | Gpl=" | + | Gpl = " |
- | Jun=" | + | Jun = " |
- | Jng=" | + | Jng = " |
- | Uic=" | + | Uic = " |
- | Grs=" | + | Grs = " |
- | Lih=" | + | Lih = " |
- | Rea=" | + | Rea = " |
- | Hhs=" | + | Hhs = " |
- | Ack=" | + | Ack = " |
- | Lis=" | + | Lis = "Lone Island", |
- | Pyr=" | + | Pyr = " |
- | Nha=" | + | Nha = "North Harbour", |
- | STn=" | + | STn = " |
- | SPo=" | + | SPo = "Post Office", |
- | SSw=" | + | SSw = " |
- | SSe=" | + | SSe = " |
- | SPa=" | + | SPa = " |
- | STo=" | + | STo = " |
- | SMi=" | + | SMi = " |
- | MR1=" | + | MR1 = "Euler Street", |
- | MSt=" | + | MSt = "Main Station (Spawn)", |
- | MOr=" | + | MOr = " |
} | } | ||
--[[ | --[[ | ||
Line 218: | Line 225: | ||
]] | ]] | ||
--Warning: Expects line to be a string! | --Warning: Expects line to be a string! | ||
- | local linet={ | + | local linet = { |
- | [" | + | [" |
- | [" | + | [" |
- | [" | + | [" |
- | [" | + | [" |
- | [" | + | [" |
- | [" | + | [" |
} | } | ||
+ | |||
F.lineterm = function(line, | F.lineterm = function(line, | ||
- | if linet[line] and linet[line][terminal] then return linet[line][terminal] end | + | |
- | return terminal | + | |
+ | | ||
+ | return terminal | ||
end | end | ||
+ | |||
F.lineset = function(line, | F.lineset = function(line, | ||
- | | + | |
- | atc_set_text_outside(" | + | atc_set_text_outside(" |
- | S.line[atc_id] = line | + | S.line[atc_id] = line |
- | set_line(tonumber(line)) | + | set_line(tonumber(line)) |
- | end | + | end |
end | end | ||
- | F.rant=function() | + | F.rant = function() |
- | return math.random(5, | + | return math.random(5, |
end | end | ||
- | F.stnname=function(cap) | + | F.stnname = function(cap) |
- | return F.stationnames[string.sub(cap, | + | return F.stationnames[string.sub(cap, |
end | end | ||
- | F.stn=function(prev, | + | F.stn = function(prev, |
- | F.stn_union(nil, | + | F.stn_union(nil, |
end | end | ||
- | F.stn_return=function(prev, | + | F.stn_return = function(prev, |
- | F.stn_union(nil, | + | F.stn_union(nil, |
end | end | ||
- | F.stn_return_nohalt=function(prev, | + | F.stn_return_nohalt = function(prev, |
- | F.stn_union(nil, | + | F.stn_union(nil, |
end | end | ||
- | F.stn_return_free=function(prev, | + | F.stn_return_free = function(prev, |
- | if event.train then | + | if event.train then |
- | setstate(prev, | + | setstate(prev, |
- | setstate(switch, | + | setstate(switch, |
- | end | + | end |
end | end | ||
- | F.stn_nohalt=function(prev, | + | F.stn_nohalt = function(prev, |
- | F.stn_union(nil, | + | F.stn_union(nil, |
end | end | ||
- | F.union_wait=function(sect) | + | F.union_wait = function(sect) |
- | S.union_waiting[sect] = not depart | + | S.union_waiting[sect] = not depart |
end | end | ||
- | F.stn_union=function(line1, | + | F.stn_union = function(line1, |
- | if not atc_id then | + | if not atc_id then |
- | atc_send(" | + | atc_send(" |
- | error(" | + | error(" |
- | end | + | end |
- | if not atc_arrow then | + | if not atc_arrow then |
- | atc_send(" | + | atc_send(" |
- | error(" | + | error(" |
- | end | + | end |
- | depart=false | + | depart = false |
- | if event.train then | + | if event.train then |
- | setstate(prev1, | + | setstate(prev1, |
- | if prev2 then setstate(prev2, | + | if prev2 then |
- | atc_send(" | + | |
+ | | ||
+ | atc_send(" | ||
- | if atc_speed and atc_speed > 10 then | + | |
- | local dt = os.date() | + | local dt = os.date() |
- | atc_set_text_outside(" | + | atc_set_text_outside( |
- | error(" | + | |
- | end | + | |
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | error(" | ||
+ | end | ||
- | | + | |
- | | + | interrupt(waittime or (ret_sw and 20 or 7), " |
- | | + | atc_set_text_inside(F.stnname(this)) |
+ | end | ||
end | end | ||
- | end | + | |
- | | + | if getstate(this) == " |
- | if getstate(this)==" | + | if ret_sw then |
- | if ret_sw then | + | atc_send(" |
- | atc_send(" | + | setstate(ret_sw, |
- | setstate(ret_sw, | + | |
- | else | + | |
- | atc_send(" | + | |
- | setstate(prev1, | + | |
- | if line1 then --this call did not come from F.stn, do union stuff | + | |
- | setstate(prev2, | + | |
- | if S.line[atc_id]==line1 then | + | |
- | if S.union_waiting[prev2] then setstate(prev1, | + | |
else | else | ||
- | if S.union_waiting[prev1] then setstate(prev2, | + | atc_send(" |
+ | setstate(prev1, | ||
+ | if line1 then --this call did not come from F.stn, do union stuff | ||
+ | setstate(prev2, | ||
+ | if S.line[atc_id] == line1 then | ||
+ | if S.union_waiting[prev2] then | ||
+ | setstate(prev1, | ||
+ | end | ||
+ | else | ||
+ | | ||
+ | | ||
+ | end | ||
+ | end | ||
+ | end | ||
+ | end | ||
+ | setstate(this, | ||
+ | atc_set_text_inside(" | ||
+ | depart = true | ||
+ | nodepartc = nil | ||
+ | else | ||
+ | interrupt(F.rant(), | ||
+ | nodepartc = nodepartc and nodepartc + 1 or 0 | ||
+ | if nodepartc >= 10 then | ||
+ | atc_set_text_inside(F.stnname(this) .. " | ||
+ | else | ||
+ | if (not osig or getstate(osig) == " | ||
+ | atc_set_text_inside(F.stnname(this) .. " | ||
+ | else | ||
+ | atc_set_text_inside(F.stnname(this) .. " | ||
+ | | ||
end | end | ||
end | end | ||
- | end | ||
- | setstate(this, | ||
- | atc_set_text_inside(" | ||
- | depart=true | ||
- | nodepartc=nil | ||
- | else | ||
- | | ||
- | | ||
- | if nodepartc> | ||
- | | ||
- | else | ||
- | if (not osig or getstate(osig)==" | ||
- | | ||
- | else | ||
- | | ||
- | end | ||
- | end | ||
end | end | ||
- | end | ||
end | end | ||
- | F.pre=function(signal) | + | F.pre = function(signal) |
- | | + | if getstate(signal) == " |
- | | + | atc_send(" |
end | end | ||
end | end | ||
- | F.uiclog = function () | + | F.uiclog = function() |
- | return | + | return |
end | end | ||
--L197 | --L197 | ||
- | F.stat=function(line, | + | F.stat = function(line, |
- | --statistics | + | --statistics |
- | -- init | + | -- init |
- | if init then | + | if init then |
- | reftrain = atc_id | + | reftrain = atc_id |
- | a_tbt = 30 | + | a_tbt = 30 |
- | a_tbtmax = 30 | + | a_tbtmax = 30 |
- | a_rtt = 500 | + | a_rtt = 500 |
- | a_not = 0 | + | a_not = 0 |
- | c_not = 0 | + | c_not = 0 |
- | c_tbtmax = 0 | + | c_tbtmax = 0 |
- | time_lt = os.time() | + | time_lt = os.time() |
- | time_rt=os.time() | + | time_rt = os.time() |
- | end | + | end |
- | if not a_tbtmax then a_tbtmax = 30 end | + | if not a_tbtmax then |
- | if not c_tbtmax then c_tbtmax = 0 end | + | |
- | --real code | + | |
- | if event.train then | + | if not c_tbtmax then |
- | local time = os.time() | + | |
- | c_not = c_not + 1 | + | |
- | a_tbt = (a_tbt + (time - time_lt)) / 2 | + | --real code |
- | c_tbtmax = math.max(c_tbtmax, | + | if event.train then |
- | if atc_id == reftrain then | + | local time = os.time() |
- | a_rtt = (a_rtt*0.2 + (time - time_rt)*0.8) | + | c_not = c_not + 1 |
- | a_not = c_not | + | a_tbt = (a_tbt + (time - time_lt)) / 2 |
- | c_not = 0 | + | c_tbtmax = math.max(c_tbtmax, |
- | a_tbtmax = (a_tbtmax + c_tbtmax) / 2 | + | if atc_id == reftrain then |
- | c_tbtmax = 0 | + | a_rtt = (a_rtt * 0.2 + (time - time_rt) * 0.8) |
- | end | + | a_not = c_not |
- | digiline_send(" | + | c_not = 0 |
- | " NoT:" | + | a_tbtmax = (a_tbtmax + c_tbtmax) / 2 |
- | " TbT:" | + | c_tbtmax = 0 |
- | " Tmx:" | + | end |
- | " R:" | + | digiline_send(" |
- | ) | + | " NoT:" |
- | time_lt = time | + | " TbT:" |
- | if atc_id == reftrain then | + | " Tmx:" |
- | time_rt = time | + | " R:" |
- | end | + | ) |
- | end | + | time_lt = time |
+ | if atc_id == reftrain then | ||
+ | time_rt = time | ||
+ | end | ||
+ | end | ||
end | end | ||
local function aspect_is_free(asp) | local function aspect_is_free(asp) | ||
- | | + | |
- | return asp.main.free | + | return asp.main.free |
- | else | + | else |
- | return asp.main ~= 0 | + | return asp.main ~= 0 |
- | end | + | end |
end | end | ||
-- 21.1.19, the rise of tss | -- 21.1.19, the rise of tss | ||
- | F.stn_ilk=function(prev, | + | F.stn_ilk = function(prev, |
- | depart = false | + | depart = false |
- | if event.train then | + | if event.train then |
- | atc_send(" | + | atc_send(" |
- | atc_set_text_inside(F.stnname(this)) | + | atc_set_text_inside(F.stnname(this)) |
- | interrupt(7, | + | interrupt(7, |
- | elseif event.int then | + | elseif event.int then |
- | local asp = get_aspect(this) | + | local asp = get_aspect(this) |
- | if not asp then | + | if not asp then |
- | atc_set_text_inside(F.stnname(this).." | + | atc_set_text_inside(F.stnname(this) .. "\nNo aspect for " .. this) |
- | else | + | else |
- | if aspect_is_free(asp) then | + | if aspect_is_free(asp) then |
- | atc_set_text_inside(" | + | atc_set_text_inside(" |
- | atc_send(" | + | atc_send(" |
- | depart = true | + | depart = true |
- | return | + | return |
- | else | + | else |
- | atc_set_text_inside(F.stnname(this).." | + | atc_set_text_inside(F.stnname(this) .. " |
- | end | + | end |
+ | end | ||
+ | interrupt(7, | ||
end | end | ||
- | interrupt(7, | ||
- | end | ||
end | end | ||
- | F.stn_ilkentry=function(prev, | + | F.stn_ilkentry = function(prev, |
- | F.stn_ilk(prev, | + | F.stn_ilk(prev, |
- | if depart then setstate(prev, | + | if depart then |
+ | | ||
+ | | ||
end | end | ||
</ | </ | ||