diff options
Diffstat (limited to 'auto_yards/init_code.lua')
-rw-r--r-- | auto_yards/init_code.lua | 385 |
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 |