added missing train handling

This commit is contained in:
Monica Moniot
2022-09-24 17:03:03 -05:00
parent de5b7500c2
commit 5ce9363f90

151
main.lua
View File

@@ -2,37 +2,96 @@ local function get_item_amount(station, item_id)
return 0
end
local function get_valid_train(stations, r_station_i, p_station_i, available_trains)
return 0
end
local function get_distance(stations, r_station_i, p_station_i)
return 0
end
local function send_train_between(stations, r_station_i, p_station_i)
stations[r_station_i].last_p_station_i = p_station_i
stations[p_station_i].last_r_station_i = r_station_i
local function send_train_between(stations, r_station_i, p_station_i, train)
local r_station = stations[r_station_i]
local p_station = stations[p_station_i]
r_station.last_p_station_i = p_station_i
p_station.last_r_station_i = r_station_i
r_station.deliveries_total = r_station.deliveries_total + 1
p_station.deliveries_total = p_station.deliveries_total + 1
local r_amount = get_item_amount(r_station, item_id) + r_station.delivery_amount[item_id]
local p_amount = get_item_amount(p_station, item_id) + p_station.delivery_amount[item_id]
local transfer_amount = math.min(train.capacity, -r_amount, p_amount)
assert(transfer_amount > 0, "main.lua error, transfer amount was not positive")
r_station.delivery_amount[item_id] = r_station.delivery_amount[item_id] + transfer_amount
p_station.delivery_amount[item_id] = p_station.delivery_amount[item_id] - transfer_amount
end
--[[
station:
station: {
deliveries_total: int
train_limit: int
requester_limit: int
provider_limit: int
requester_limit: int > 0
provider_limit: int > 0
priority: int
last_delivery_tick: int
train_layout: [ [ {
[car_type]: true|nil
} ] ]
accepted_layouts: {
[layout_id]: true|nil
}
}
available_trains: [{
layout_id: int
capacity: int
}]
]]
local function tick(stations, all_items)
for _, item_id in pairs(all_items) do
--local function check_train_layouts(station, available_layouts)
-- for _, layout_id in ipairs(available_layouts) do
-- if station.accepted_layouts[layout_id] then
-- return true
-- end
-- end
-- return false
--end
local function icpairs(a, start_i)
start_i = start_i%#a + 1
local i = start_i - 1
local flag = true
return function()
i = i%#a + 1
if i ~= start_i or flag then
flag = false
local v = a[i]
if v then
return i, v
end
end
end
end
local function tick(stations, all_items, available_trains, ticks_total)
if #all_items == 0 then
return
end
local failed_because_missing_trains_total = 0
--psuedo-randomize what item (and what station) to check first so if trains available is low they choose orders psuedo-randomly
for _, item_id in icpairs(all_items, ticks_total) do
local r_stations = {}
local p_stations = {}
for station_i, station in pairs(stations) do
if station.deliveries_total < station.train_limit then
local item_amount = get_item_amount(station, item_id)
local delivery_amount = station.delivery_amount
local item_amount = get_item_amount(station, item_id) + station.delivery_amount[item_id]
if -(item_amount + delivery_amount) >= station.requester_limit then
if -item_amount >= station.requester_limit then
table.insert(r_stations, station_i)
elseif item_amount + delivery_amount >= station.provider_limit then
elseif item_amount >= station.provider_limit then
table.insert(p_stations, station_i)
end
end
@@ -43,43 +102,65 @@ local function tick(stations, all_items)
if #r_stations > 0 and #p_stations > 0 then
if #r_stations <= #p_stations then
--backpressure, prioritize locality
for i, r_station_i in ipairs(r_stations) do
local best = 1
for i, r_station_i in icpairs(r_stations, ticks_total) do
local best = 0
local best_train = nil
local best_dist = math.huge
local highest_prior = -math.huge
local could_have_been_serviced = false
for j, p_station_i in ipairs(p_stations) do
local d = get_distance(stations, r_station_i, p_station_i)
local prior = stations[p_station_i].priority
if prior > highest_prior then
best = j
best_dist = d
highest_prior = prior
elseif prior == highest_prior and d < best_dist then
best = j
best_dist = d
if prior > highest_prior or (prior == highest_prior and d < best_dist) then
local train, is_possible = get_valid_train(stations, r_station_i, p_station_i, available_trains)
if train then
best = j
best_dist = d
best_train = train
highest_prior = prior
elseif is_possible then
could_have_been_serviced = true
end
end
end
send_train_between(stations, r_station_i, p_stations[best])
table.remove(p_stations, best)
if best > 0 then
send_train_between(stations, r_station_i, p_stations[best], best_train)
table.remove(p_stations, best)
elseif could_have_been_serviced then
failed_because_missing_trains_total = failed_because_missing_trains_total + 1
end
end
else
--prioritize round robin
for j, p_station_i in ipairs(p_stations) do
local best = 1
for j, p_station_i in icpairs(p_stations, ticks_total) do
local best = 0
local best_train = nil
local lowest_tick = math.huge
local highest_prior = -math.huge
local last_r_station_i = stations[p_station_i].last_r_station_i
local could_have_been_serviced = false
for i, r_station_i in ipairs(r_stations) do
local prior = stations[r_station_i].priority
if r_stations[i] > last_r_station_i then
prior = prior + .5
end
if prior > highest_prior then
best = i
highest_prior = prior
local r_station = stations[r_station_i]
local prior = r_station.priority
if prior > highest_prior or (prior == highest_prior and r_station.last_delivery_tick < lowest_tick) then
local train, is_possible = get_valid_train(stations, r_station_i, p_station_i, available_trains)
if train then
best = i
best_train = train
lowest_tick = r_station.last_delivery_tick
highest_prior = prior
elseif is_possible then
could_have_been_serviced = true
end
end
end
send_train_between(stations, r_stations[best], p_station_i)
table.remove(r_stations, best)
if best > 0 then
send_train_between(stations, r_stations[best], p_station_i, best_train)
table.remove(r_stations, best)
elseif could_have_been_serviced then
failed_because_missing_trains_total = failed_because_missing_trains_total + 1
end
end
end
end