Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- local component=require('component')
- local SEED_SLOT = 1
- local machine_name='thermal_expansion:machine'
- local machines = nil
- local output_inventory = nil
- local item_requests = {}
- local item_seeds = {}
- function remove_seed(machine)
- assert(component.invoke(machine.address,'transferItem',machine.machine_side,machine.inventoy_side,1,SEED_SLOT)==1,'cannot remove seed from '..machine.address..':'..machine.side)
- end
- function insert_seed(machine, slot)
- assert(component.invoke(machine.address,'transferItem',machine.inventoy_side,machine.machine_side,1,slot)==1,'cannot insert seed into '..machine.address..':'..machine.side..'from slot '..slot)
- end
- function get_seed(machine)
- return (component.invoke(machine.address,'getStackInSlot',machine.machine_side,SEED_SLOT) or {}).name
- end
- -- scan environemnt
- function get_blocks()
- local seed_inventory=nil
- output_inventory=nil
- machines= {}
- for transposer in component.list('transposer') do
- local any_machines=false
- local non_machine_inventory=nil
- for side in 0,5 do
- local inv=component.invoke(transposer,'getInventoryName',side)
- if inv==machine_name then
- any_machines=true
- else if inv then
- assert(non_machine_inventory==nil,'multiple non machine inventories at '..transposer)
- non_machine_inventory=inv
- end
- end
- assert(non_machine_inventory ~=nil, 'transposer '..transposer..' has no non machine inventories')
- if any_machines then
- assert(seed_inventory == non_machine_inventory or seed_inventory ==nil,'multiple candidates for seed inventory: '..non_machine_inventory..', '..seed_inventory)
- seed_inventory=non_machine_inventory
- for side in 0,5 do
- if component.invoke(transposer,'getInventoryName',i)==machine_name then
- machines[#machines]={
- address=transposer,
- machine_side=i,
- inventoy_side=non_machine_inventory,
- }
- end
- end
- else
- assert(output_inventory ==nil,'multiple candidates for output inventory at transposers: '..output_inventory.address..', ,'..transposer)
- output_inventory={
- address=transposer,
- side=non_machine_inventory
- }
- end
- end
- end
- end
- -- configuration file
- function get_item_info()
- local f, err = loadfile("item_requests")
- if not f then
- error(err)
- end
- local r, s = f()
- assert(type(r) == "table", "item_requests not a table")
- assert(type(s) == "table", "item_seeds not a table")
- item_requests = r
- item_seeds = s
- end
- --
- function find_seed_slot(name)
- local i=1
- for stack in component.invoke(machines[1].address,'getAllStacks',machines[1].inventoy_side) do
- if stack.name==name then
- return i
- end
- i=i+1
- end
- end
- -- main function, called in loop
- function allocate_machines()
- get_blocks()
- get_item_info()
- local item_counts = {}
- for stack in component.invoke(output_inventory.address,'getAllStacks',output_inventory.side) do
- if item_requests[item.name] then
- item_counts[item.name] = (item_counts[item.name] or 0) + stack.size
- end
- end
- local seeds = {}
- local weights = {[0] = 0}
- for item_name, request in pairs(item_requests) do
- local available = item_counts[item_name] or 0
- if available < request then
- local weight = request / (available + 1)
- local index = #weights + 1
- weights[index] = weight
- seeds[index] = item_seeds[item_name]
- end
- end
- for i = 2, #weights do
- weights[i] = weights[i] + weights[i - 1]
- end
- for _, machine in pairs(machines) do
- if get_seed(machine) ~= nil then
- remove_seed(machine)
- end
- end
- for _, machine in pairs(machines) do
- local ni, ns = get_new_item_position(weights, seeds)
- if ni ~= nil then
- insert_seed(machine, ni, ns)
- end
- end
- end
- -- seed allocation logic
- function get_new_item_position(weights, items)
- local function remove_weight(weights, items, index)
- if index < #weights then
- local removed = weights[index] - weights[index - 1] or 0
- local last = weights[#weights] - weights[#weights - 1]
- local difference = last - removed
- items[index] = items[#weights]
- repeat
- weights[index] = weights[index] + difference
- index = index + 1
- until index == #weights
- end
- weights[index] = nil
- items[index] = nil
- end
- local function choose_weighted(weights)
- local not_enough = 0
- local enough = #weights
- if enough == 0 then
- return nil
- end
- local rand = math.random() * weights[#weights]
- while not_enough + 1 < enough do
- local mid = math.floor((not_enough + enough) / 2)
- if weights[mid] < rand then
- not_enough = mid
- else
- enough = mid
- end
- end
- return enough
- end
- local chosen_index = choose_weighted(weights)
- if chosen_index == nil then
- return nil
- end
- local s = find_seed_slot(items[chosen_index])
- if s ~= nil then
- return s
- else
- remove_weight(weights, items, chosen_index)
- return get_new_item_position(weights, items)
- end
- end
- while true do
- ok, err = pcall(allocate_machines)
- if ok then
- io.write("ok ")
- sleep(300)
- else
- print()
- print(err)
- sleep(5)
- end
- end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement