summaryrefslogtreecommitdiff
path: root/auto_yards/init_code.lua
diff options
context:
space:
mode:
Diffstat (limited to 'auto_yards/init_code.lua')
-rw-r--r--auto_yards/init_code.lua385
1 files changed, 384 insertions, 1 deletions
diff --git a/auto_yards/init_code.lua b/auto_yards/init_code.lua
index fc73c3a..1ac90df 100644
--- a/auto_yards/init_code.lua
+++ b/auto_yards/init_code.lua
@@ -1 +1,384 @@
-F.pickup = function(yard,dir,lane) local y = yard if S[y].yard_active then if atc_arrow then if S[y].dir == dir then set_route(yard..dir.."_"..lane, "HEADSHUNT") local plen = train_length() local rc = split_at_fc("B0") local trc = yard..dir.."_"..rc if plen == train_length() and (rc == "" or S[y].rc:match(trc)) then S[y].exiting = true end if rc and rc ~= "" then set_rc(yard..dir.."_"..rc) else set_rc(S[y].rc) S[y].exiting = true end else -- if S[y].dir ~= dir if S[y].RTS then -- loop around to other HS S[y].RTS = nil set_route(yard..dir.."_"..lane,"AROUND") split_off_locomotive("B0") set_rc("AROUND_"..S[y].dir) return else atc_send("B0WRS4") end end end -- nothing to do if train goes against arrow end end F.EOL = function(yard,dir,lane) local y = yard if S[y].yard_active then if S[y].dir == dir then if atc_arrow then if not S[y].exiting then --return to PICKUP via headshunt split_off_locomotive("B0") set_rc("PICKUP") set_route(yard..dir.."_"..lane, "HEADSHUNT") else --if S[y].exiting then loco has already sorted to correct lane for departure --S[y].exiting set by the pickup track set_rc(S[y].rc) set_route(yard..dir.."_"..lane, "EXIT") S[y].exiting = nil end end else -- EOL Bounce atc_send("B0WD1RS4") end end end \ No newline at end of file
+--Environment Code
+-------------------------------------------------------------------------------------
+-- Yard Information
+if event.init then
+ S.yards = {
+ TY = {
+ active_indicator_pos = POS(-4025,14,-2659),
+ dir_indicator_pos = POS(-4025,13,-2665),
+ error_indicator_pos = POS(-4025,13,-2671),
+ },
+ BY = {
+ active_indicator_pos = POS(-2002,3,-1099),
+ dir_indicator_pos = POS(-2009,3,-1099),
+ error_indicator_pos = POS(-1999,3,-1099),
+ },
+ -- HY = {
+ -- active_indicator_pos = POS(-4025,14,-2659),
+ -- dir_indicator_pos = POS(-4025,13,-2665),
+ -- error_indicator_pos = POS(-4025,13,-2671),
+ -- },
+ }
+end
+------------------------------------------------------------------------------------
+-- Utility Functions
+F.indicator = function(indicator,set)
+ if set ~= nil then
+ setstate(indicator,(set and "on") or "off")
+ end
+ return (getstate(indicator) == "on") or false
+end
+
+F.get_rc_safe = function()
+ return get_rc() or ""
+end
+
+F.has_rc = function(query,rc_list) -- query = string, single entry
+ if not atc_id then return false end
+ if rc_list == "" or query == nil or query=="" then return false end
+ if not rc_list then rc_list = F.get_rc_safe() end
+ for word in rc_list:gmatch("[^%s]+") do
+ if word == query then return true end
+ end
+ print(F.get_rc_safe())
+ return false
+end
+
+F.has_rc_match = function(query,rc_list) -- query = pattern string, single entry
+ if not atc_id then return false end
+ if rc_list == "" or query == nil or query=="" then return false end
+ if not rc_list then rc_list = F.get_rc_safe() end
+
+ local rc = {}
+ for v in rc_list:gmatch("("..query..")") do
+ table.insert(rc,v)
+ end
+
+ if rc[1] == true then
+ return true, rc
+ else
+ return nil
+ end
+end
+
+F.add_rc = function(rc_list) -- rc_list = string or table, eg: {"rc1","rc2"} OR "rc1 rc2"
+ if not atc_id then return false end
+ if type(rc_list) == "table" then
+ rc_list = table.concat(rc_list," ")
+ end
+ set_rc(F.get_rc_safe().." "..rc_list)
+ print(F.get_rc_safe())
+ return true
+end
+
+F.remove_rc = function(rc_list,arrow_mode) -- rc_list = string eg: "rc1 rc2 rc3" OR table eg: {"rc1","rc2","rc3"}
+ -- Arrow Modes:
+ -- true: with arrow direction
+ -- false: against arrow direction
+ -- nil: ignores arrow direction
+
+ if not atc_id then return false end
+ if not rc_list then return false end
+
+ if (arrow_mode == nil) or (atc_arrow == arrow_mode) then
+ -- prep rc_list to useable format
+ local rc_remove = {}
+ if type(rc_list) == "string" then
+ for word in pairs(rc_list:gmatch("[^%s]+")) do
+ rc_remove[word] = true
+ end
+ elseif type(rc_list) == "table" then
+ for word in pairs(rc_list) do
+ rc_remove[word] = true
+ end
+ end
+
+ -- remove codes from train's rc
+ local rc = F.get_rc_safe()
+ local reinsert = {}
+ for token in rc:gmatch("[^%s]+") do
+ if not rc_remove[token] then
+ table.insert(reinsert,token)
+ end
+ end
+ -- insert new string to train's rc
+ set_rc(table.concat(reinsert," "))
+ end
+ print(F.get_rc_safe())
+ return reinsert
+end
+
+F.remove_rc_match = function(rc_list) -- rc_list = pattern string, single entry, eg: "rc_%d+"
+ if not atc_id then return false end
+ if not rc_list then return false end
+ local rm = {}
+ for v in F.get_rc_safe():gmatch("("..rc_list..")") do
+ table.insert(rm,v)
+ end
+ F.remove_rc(rm)
+ print(F.get_rc_safe())
+ return rm
+end
+
+-------------------------------------------------------------------------------------
+-- Superseded by universal indicator function. to be updated in trackside functions
+-- F.error = function(set)
+ -- local error_indicator = POS(-4025,13,-2671)
+ -- if set ~= nil then
+ -- setstate(error_indicator,(set and "on") or "off")
+ -- end
+ -- return (getstate(error_indicator) == "on") or false
+-- end
+
+-- F.yard_active = function(set) --if set == true then yard = active
+ -- local yard_indicator = POS(-4025,14,-2659)
+ -- if set ~= nil then
+ -- setstate(yard_indicator,(set and "on") or "off")
+ -- end
+ -- return (getstate(yard_indicator) == "on") or false
+-- end
+
+-- F.dir = function(set) -- if set == true then dir = pointing north
+ -- local dir_indicator = POS(-4025,13,-2665)
+ -- if set ~= nil then
+ -- setstate(dir_indicator,(set and "on") or "off")
+ -- end
+ -- return (getstate(dir_indicator) == "on") or false
+-- end
+
+----------------------------------------------------------------------------------------------
+-- Trackside Functions
+F.yard_arrival = function(yard_id,this_dir) -- arrow points towards yard
+ local yard = S.yards[yard_id] --yard ref
+
+ if F.has_rc(yard_id.."_NOSHUNT") then return end
+
+ local function enter_yard()
+ F.indicator(yard.dir_indicator_pos,this_dir)
+ F.add_rc({yard_id.."_ARRIVE"})
+ atc_set_ars_disable(false)
+ atc_send("S6")
+ return
+ end
+
+ __approach_callback_mode = 1
+ if event.approach and not event.has_entered then
+ atc_set_ars_disable(true)
+ atc_set_lzb_tsr(1)
+ return
+ end
+
+ if event.train then
+ if F.indicator(yard.active_indicator_pos) then
+ schedule_in(";10","recheck")
+ return
+ else
+ enter_yard()
+ end
+ end
+
+ if event.schedule then
+ if F.indicator(yard.active_indicator_pos) then
+ schedule_in(";10","recheck")
+ return
+ else
+ enter_yard()
+ end
+ end
+end
+
+F.classification = function(yard_id, this_dir) -- arrow points towards headshunt
+ local yard = S.yards[yard_id] --yard ref
+
+ -- this_dir == true for north end, false for south end
+ if F.indicator(yard.active_indicator_pos) then
+ if atc_arrow then -- loco is at working end
+ F.remove_rc({yard_id.."_PICKUP"})
+ if F.has_rc(yard_id.."_ARRIVE") and F.indicator(yard.dir_indicator_pos) == this_dir then --first pass, prep train for working
+ F.remove_rc({yard_id.."_AROUND"})
+ if not F.has_rc_match(yard_id.."_LOCOS_%d+") or not F.has_rc_match(yard_id.."_WAGONS_%d+") then
+ local full_length = train_length()
+ split_off_locomotive("A0B0")
+ F.add_rc({yard_id.."_HEADSHUNT"}) -- train will end up going through headshunt no matter what. there shouldn't be any trains entering that pass straight through.
+ if train_length() == full_length then --train is either only here for collection or there's no FC's in the wagons. can't differentiate
+ local lane = F.get_rc_safe():match(yard_id.."_COLLECT_(%S+)") or ""
+ F.add_rc({yard_id.."_LAST_CLASS",yard_id.."_CLASS_"..lane}) -- direct train to correct lane for collection
+ else --identify and save loco:wagon ratio, then bounce back from headshunt. it's easier than trying to reconnect
+ F.add_rc({yard_id.."_LOCOS_"..train_length(), yard_id.."_WAGONS_"..(full_length-train_length()),yard_id.."_PICKUP"})
+ end
+ return -- train has departed for headshunt
+ end
+ if F.has_rc(yard_id.."_RTS") then
+ F.indicator(yard.dir_indicator_pos,not F.indicator(yard.dir_indicator_pos))
+ F.remove_rc({yard_id.."_RTS"})
+ F.add_rc({yard_id.."_AROUND"}) -- send loco around to the other end
+ split_off_locomotive("A0B0")
+ atc_set_ars_disable(false)
+ return -- train has departed for RTS loop
+ end
+ F.remove_rc({yard_id.."_ARRIVE"})
+ step_fc()
+ end
+ if this_dir == F.indicator(yard.dir_indicator_pos) then --train has bounced and is ready to classify wagon(s)
+ -- local pre_split = train_length()
+ local lane = split_at_fc("A0B0",5) -- where to classify this rake -- headshunt length
+ local locos = tonumber(F.get_rc_safe():match(yard_id.."_LOCOS_(%d+)")) or 1 --saved loco count
+ local wagons = tonumber(F.get_rc_safe():match(yard_id.."_WAGONS_(%d+)")) or 0 -- wagon_count from last classification split
+ local this_rake = train_length() - locos-- subtract these wagons from the overall wagon count
+ if this_rake == wagons then -- mark for last_classification
+ F.add_rc({yard_id.."_LAST_CLASS"})
+ end
+ if lane ~= "" then
+ F.add_rc({yard_id.."_CLASS_"..lane})
+ end
+ F.remove_match(yard_id.."_WAGONS_%d+")
+ F.add_rc({yard_id.."_HEADSHUNT",yard_id.."_WAGONS_"..wagons-this_rake})
+ atc_set_ars_disable(false)
+ set_autocouple()
+ else --bounce train back towards working end
+ atc_set_ars_disable(true)
+ atc_send("S0WRD1S3")
+ unset_autocouple()
+ end
+ else -- train entering from the far end. set autocouple so it pushes all the way through to the bounce
+ set_autocouple()
+ end
+ end
+end
+
+F.headshunt_yard = function(yard_id,this_dir) -- arrow points toward yard
+ local yard = S.yards[yard_id] --yard ref
+
+ if not F.indicator(yard.active_indicator_pos) then return end
+
+ __approach_callback_mode = 1
+ if event.approach and not event.has_entered then
+ atc_set_ars_disable(true)
+ atc_set_lzb_tsr(1)
+ return
+ end
+
+ if event.train then
+ if not atc_arrow then --train has entered headshunt from yard. bounce or depart
+ atc_set_ars_disable(true)
+ F.remove_rc({yard_id.."_HEADSHUNT"})
+ if not F.has_rc(yard_id.."_FINAL_COLLECT") then
+ if not F.has_rc(yard_id.."_DEPART") then
+ schedule_in(";01",atc_id)
+ return
+ else
+ local collect = F.get_rc_safe():match(yard_id.."_COLLECT_(%S+)")
+ if collect then --train needs to collect a rake from the yard before departing
+ F.add_rc({yard_id.."_FINAL_COLLECT",yard_id.."_CLASS_"..collect})
+ schedule_in(";01",atc_id)
+ return
+ end
+ end
+
+ --else let train proceed forward to the exit controller without a rake
+ end --else train has already collected rake. let it exit yard
+ else --train has bounced
+ if F.has_rc(yard_id.."_AROUND") then
+ if this_dir == F.indicator(yard.dir_indicator_pos) then --send train to Classification
+ F.remove_rc({yard_id.."_AROUND"})
+ F.add_rc({yard_id.."_PICKUP"})
+ atc_set_ars_disable(false)
+ return
+ end --if at wrong end, do nothing. train will follow TY_AROUND ARS to relevant headshunt
+ end -- if doesn't have TY_AROUND then let ARS classify the train
+
+ atc_set_ars_disable(false)
+ end
+ return
+ end
+
+ if event.schedule then
+ if not atc_id then --bounce the train that just passed
+ atc_send_to_train(event.msg,"B0WRD1S3A1")
+ else
+ if atc_id == event.msg then --train hasn't fully passed yet, wait a bit longer
+ schedule_in(";01",atc_id)
+ else -- somehow another train crossed the controller before the first one returned. Unlikely but possible
+ atc_send_to_train(event.msg,"BBOL")
+ atc_send("BBOL")
+ F.indicator(yard.error_indicator_pos,true)
+ end
+ end
+ return
+ end
+end
+
+F.headshunt_exit = function(yard_id,this_dir) -- arrow points out of yard
+ local yard = S.yards[yard_id] --yard ref
+
+ if not F.indicator(yard.active_indicator_pos) then return end
+ __approach_callback_mode = 1
+ if event.approach and not event.has_entered then
+ atc_set_ars_disable(true)
+ atc_set_lzb_tsr(1)
+ return
+ end
+
+ if event.train then
+ if atc_arrow and (F.indicator(yard.dir_indicator_pos) == this_dir) then
+ if F.has_rc(yard_id.."_DEPART") then
+ print("Train departs yard to mainline at full speed")
+ unset_autocouple()
+ F.remove_rc({yard_id.."_FINAL_COLLECT",yard_id.."_DEPART"})
+ F.remove_rc_match(yard_id.."_LOCOS_%d+")
+ F.remove_rc_match(yard_id.."_WAGONS_%d+")
+ atc_set_ars_disable(false)
+ -- set_route(exit_signal,"Exit Yard")
+ atc_send("S6D10SM")
+ schedule_in(";05","deactivate_check") -- wait a little to ensure train is clear from headshunt to deactivate yard
+ print(F.get_rc_safe())
+ return
+ end
+ else
+ atc_send("BBOL")
+ F.indicator(yard.error_indicator_pos,true)
+ end
+ end
+
+ if event.schedule then
+ if event.msg == "deactivate_check" then
+ if not atc_id then
+ F.indicator(yard.active_indicator_pos,false)
+ print("Yard Disabled")
+ else
+ schedule_in(";05","deactivate_check")
+ return
+ end
+ end
+ end
+end
+
+F.lane_EOL = function(yard_id,this_dir) -- arrow points towards headshunt
+ local yard = S.yards[yard_id] --yard ref
+
+ if not F.indicator(yard.active_indicator_pos) then return end
+ if atc_arrow then
+ if F.indicator(yard.dir_indicator_pos) == this_dir then --train has bounced and needs to leave the rake or depart with it
+ if F.has_rc(yard_id.."_LAST_CLASS") then -- this is the last clasification move
+ F.remove_rc({yard_id.."_LAST_CLASS"})
+ F.add_rc({yard_id.."_DEPART"})
+ split_off_locomotive("A0B0")
+ elseif not F.has_rc(yard_id.."_FINAL_COLLECT") then
+ -- disconnect loco and return to pickup
+ split_off_locomotive("A0B0")
+ F.add_rc({yard_id.."_PICKUP"})
+ end --if has FINAL_COLLECT then don't split off the loco. take the full rake
+ F.add_rc({yard_id.."_HEADSHUNT"})
+ else --train needs to bounce
+ atc_send("B0WRD1S4")
+ end
+ else
+ if F.indicator(yard.dir_indicator_pos) == this_dir then
+ --train is clasifying wagons, let it pass and couple to the rest of the rake
+ F.remove_rc_match(yard_id.."_CLASS_%S+")
+ else --this should never come into play as it means the train has entered from the wrong end somehow
+ atc_send("BBOL") --stop the train and open the doors (if available) to signify assistance required
+ F.indicator(yard.error_indicator_pos,true)
+ end
+ end
+end \ No newline at end of file