From: Olav Bakke Svendsen Date: Fri, 24 May 2024 19:57:29 +0000 (+0200) Subject: Moving Libraries X-Git-Tag: skystone~4 X-Git-Url: http://git.olavbs.no/?a=commitdiff_plain;h=984d426db7a407fb3bf6d1b0dcdae50b8f5859a1;p=cc.git Moving Libraries --- diff --git a/common/dl.lua b/common/dl.lua index 9400298..8ada45b 100644 --- a/common/dl.lua +++ b/common/dl.lua @@ -30,10 +30,11 @@ for _, file in pairs(files) do if fs.exists(file.to) and file.overwrite then local tmp = textutils.serialize(math.random(100000,999999)) local ok = shell.run("wget "..url.." "..tmp) - if ok then + if ok then -- not working? print("Overwriting "..file.to) fs.delete(file.to) - fs.move(tmp,file.to) +-- fs.move(tmp,file.to) -- fails with no such file + shell.run("mv "..tmp.." "..file.to) -- workaround end else shell.run("wget "..url.." "..file.to) diff --git a/lib/inventory.lua b/lib/inventory.lua new file mode 100644 index 0000000..c047b76 --- /dev/null +++ b/lib/inventory.lua @@ -0,0 +1,97 @@ +local t = {} + +-- index: find items in inventories +-- inventory_address: string +-- items: list of strings or nil/false. if nil/false, indexes all items. +-- returns a table that maps item names to { amount = 0, slots = {} } where +-- amount is the total amount of the item in the inventory and slots is a +-- table where the keys are slot numbers and the values are how many items +-- are in the slot. +t.index = function(inventory_address, items) + local inventory = peripheral.wrap(inventory_address) + local slots = inventory.list() + local index = {} + + local should_index = {} + if items then + for _, name in pairs(items) do + should_index[name] = true + end + end + + for slot, item in pairs(slots) do + if not items or (item.name and should_index[item.name]) then + index[item.name] = index[item.name] or { amount = 0, slots = {} } + index[item.name].amount = index[item.name].amount + item.count + index[item.name].slots[slot] = item.count + end + end + return index +end + +-- find: similar to index, but stops indexing once the required amount of each +-- item is found. +-- inventory_address: string +-- item_amounts: a table that maps item names to amounts +-- returns bool, table where table maps item names to { amount = 0, slots = {} } +-- much like the index function, but where the amounts are less than or equal +-- to the amounts provided in item_amounts and slots is a table where the keys +-- are slot numbers end values are how many items "was found" in the slot. bool +-- is whether all the items in item_amounts were found or not. +t.find = function(inventory_address, item_amounts) + local inventory = peripheral.wrap(inventory_address) + local slots = inventory.list() + + local missing = {} + for name, amount in pairs(item_amounts) do + missing[name].amount = amount + end + + local index = {} + local found_all = false + for slot, item in pairs(slots) do + if missing == {} then + found_all = true + break + end + if item.name and missing[item.name] then + index[item.name] = index[item.name] or { amount = 0, slots = {} } + if item.count < missing[item.name] then + index[item.name].amount = index[item.name].amount + item.count + index[item.name].slots[slot] = item.count + missing[item.name] = missing[item.name] - item.count + else + index[item.name].amount = index[item.name].amount + missing[item.name] + index[item.name].slots[slot] = missing[item.name] + missing[item.name] = nil + end + end + end + return found_all, index +end + +-- move: tries to move items from one inventory to another +-- source_address: string +-- destination_address: string +-- item_amounts: a table that maps item names to amounts +-- returns true on success and false, string on fail +t.move = function(source_address, destination_address, item_amounts) + local source_inventory = peripheral.wrap(source_address) + local ok, index = t.find(source_address, item_amounts) + local err = false + if not ok then + err = "not enough items" + else + for item_name, slots in pairs(index) do + for slot, amount in pairs(slots) do + source_inventory.pushItems(destination_address, slot, amount) + -- todo: pushItems may fail + end + end + end + return not err or table.unpack({ false, "Could not move: "..err }) +end + + + +return t diff --git a/lib/turtle-utils.lua b/lib/turtle-utils.lua deleted file mode 100644 index ab9f375..0000000 --- a/lib/turtle-utils.lua +++ /dev/null @@ -1,152 +0,0 @@ --- turtle-utils.lua --- --- depends on: --- oneOf --- --- implements: --- findItem : list of item names -> index | false message --- findEmpty : index | false message --- count : list of item names -> count --- selectItem : list of item names -> true | false message --- transferAndSelect : index -> list of items -> true | false message --- movementMap : t f --- runStringCommand : string -> true | false message --- rep : number of repeats -> string -> string | nil - ---------------------------------------- for now --- t a -> a -> bool --- returns whether a is found in t -local oneOf = function(t, a) - for _,b in pairs(t) do - if b == a then return true end - end - return false -end --------------------------------------- - -local lib = {} - --- findItem : list of item names -> index | false message --- returns the first inventory index containing an item from list t --- if no item is found, returns nil -lib.findItem = function(t) - for i = 1, 16 do - local item = turtle.getItemDetail(i) - if item and oneOf(t, item.name) then return i end - end - return false, "Item(s) not found" -end - --- findEmpty : index | false message --- returns the first empty slot --- if no empty slot is found, returns nil -lib.findEmpty = function() - for i = 1, 16 do if not turtle.getItemDetail(i) then return i end end - return false, "No empty slot" -end - --- count : list of item names -> count --- counts how many slots contain an item from list t --- (does not count individual items) -lib.count = function(t) - local c = 0 - for i = 1, 16 do - local item = turtle.getItemDetail(i) - if item and oneOf(t, item.name) then - c = c + 1 - break - end - end -end - --- selectItem : list of item names -> true | false message --- select first slot containing an item from list t if not already selected. --- returns bool. -lib.selectItem = function(t) - local item = turtle.getItemDetail() - if item and oneOf(t, item.name) then - return true - else - local i, e = find(t) - if i then - turtle.select(i) - return true - end - end - return false, "Nothing to select: " .. e -end - --- transferAndSelect : index -> list of items -> true | false message --- like selectItem, selects item from list, but tries to move it to the first slot. --- requires an empty slot to move items around. --- (this function exists because weak automata cannot digBlock with tools in slots >9) -lib.transferAndSelect = function(i, t) - if i < 1 or i > 16 then return false, msg .. "Index out of range" end - -- if a wanted item already is in the wanted slot, select it and return early - local item = turtle.getItemDetail(i) - if item and oneOf(t, item.name) then - turtle.select(i) - return true - end - local msg = "Could not transfer and select: " - local i_tmp, e = lib.findEmpty() - if not i_tmp then return false, msg .. e end - local i_from, e = lib.findItem(t) - if not i_from then return false, msg .. e end - -- if the i'th slot is free, skip the unnecessary item shuffle - if not turtle.getItemDetail(i) then - turtle.select(i_from) - turtle.transferTo(i) - else - turtle.select(i) - turtle.transferTo(i_tmp) - turtle.select(i_from) - turtle.transferTo(i) --- turtle.select(i_tmp) --- turtle.transferTo(i_from) - end - turtle.select(i) - return true -end - - --- commands as strings --- chars corresponds to actions, when immediatel followed by a number, repeats the action that many times --- "udfblrh" = up -> down -> forward -> backward -> turn left -> turn right -> harvest --- "u15r" = 15x up -> turn right --- "u15 r" = 15x up -> turn right --- "u1 5r" = invalid - --- movementMap : t f -lib.movementMap = - { ["u"] = turtle.up - , ["d"] = turtle.down - , ["f"] = turtle.forward - , ["b"] = turtle.back - , ["l"] = turtle.turnLeft - , ["r"] = turtle.turnRight - } - --- runStringCommand : string -> true | false message -lib.runStringCommand = function(str, map) - local c, n, rest = string.match(string.gsub(str, "^%s+", ""), "^(%w)(%d*)(.*)") - if not c then return true end - if n == "" then n = 1 else n = tonumber(n) end - for i = 1, n do map[c]() end --- print(cmd, tostring(i).."/"..tostring(n)) --- end - return lib.runStringCommand(rest, map) -end - --- rep : number of repeats -> string -> string | nil --- repeats string n times -lib.rep = function(n, str) - if not n or n < 0 then return nil end - local s = "" - for i = 1, n do - s = s .. str - end - return s -end - -return lib diff --git a/lib/turtle.lua b/lib/turtle.lua new file mode 100644 index 0000000..ab9f375 --- /dev/null +++ b/lib/turtle.lua @@ -0,0 +1,152 @@ +-- turtle-utils.lua +-- +-- depends on: +-- oneOf +-- +-- implements: +-- findItem : list of item names -> index | false message +-- findEmpty : index | false message +-- count : list of item names -> count +-- selectItem : list of item names -> true | false message +-- transferAndSelect : index -> list of items -> true | false message +-- movementMap : t f +-- runStringCommand : string -> true | false message +-- rep : number of repeats -> string -> string | nil + +--------------------------------------- for now +-- t a -> a -> bool +-- returns whether a is found in t +local oneOf = function(t, a) + for _,b in pairs(t) do + if b == a then return true end + end + return false +end +-------------------------------------- + +local lib = {} + +-- findItem : list of item names -> index | false message +-- returns the first inventory index containing an item from list t +-- if no item is found, returns nil +lib.findItem = function(t) + for i = 1, 16 do + local item = turtle.getItemDetail(i) + if item and oneOf(t, item.name) then return i end + end + return false, "Item(s) not found" +end + +-- findEmpty : index | false message +-- returns the first empty slot +-- if no empty slot is found, returns nil +lib.findEmpty = function() + for i = 1, 16 do if not turtle.getItemDetail(i) then return i end end + return false, "No empty slot" +end + +-- count : list of item names -> count +-- counts how many slots contain an item from list t +-- (does not count individual items) +lib.count = function(t) + local c = 0 + for i = 1, 16 do + local item = turtle.getItemDetail(i) + if item and oneOf(t, item.name) then + c = c + 1 + break + end + end +end + +-- selectItem : list of item names -> true | false message +-- select first slot containing an item from list t if not already selected. +-- returns bool. +lib.selectItem = function(t) + local item = turtle.getItemDetail() + if item and oneOf(t, item.name) then + return true + else + local i, e = find(t) + if i then + turtle.select(i) + return true + end + end + return false, "Nothing to select: " .. e +end + +-- transferAndSelect : index -> list of items -> true | false message +-- like selectItem, selects item from list, but tries to move it to the first slot. +-- requires an empty slot to move items around. +-- (this function exists because weak automata cannot digBlock with tools in slots >9) +lib.transferAndSelect = function(i, t) + if i < 1 or i > 16 then return false, msg .. "Index out of range" end + -- if a wanted item already is in the wanted slot, select it and return early + local item = turtle.getItemDetail(i) + if item and oneOf(t, item.name) then + turtle.select(i) + return true + end + local msg = "Could not transfer and select: " + local i_tmp, e = lib.findEmpty() + if not i_tmp then return false, msg .. e end + local i_from, e = lib.findItem(t) + if not i_from then return false, msg .. e end + -- if the i'th slot is free, skip the unnecessary item shuffle + if not turtle.getItemDetail(i) then + turtle.select(i_from) + turtle.transferTo(i) + else + turtle.select(i) + turtle.transferTo(i_tmp) + turtle.select(i_from) + turtle.transferTo(i) +-- turtle.select(i_tmp) +-- turtle.transferTo(i_from) + end + turtle.select(i) + return true +end + + +-- commands as strings +-- chars corresponds to actions, when immediatel followed by a number, repeats the action that many times +-- "udfblrh" = up -> down -> forward -> backward -> turn left -> turn right -> harvest +-- "u15r" = 15x up -> turn right +-- "u15 r" = 15x up -> turn right +-- "u1 5r" = invalid + +-- movementMap : t f +lib.movementMap = + { ["u"] = turtle.up + , ["d"] = turtle.down + , ["f"] = turtle.forward + , ["b"] = turtle.back + , ["l"] = turtle.turnLeft + , ["r"] = turtle.turnRight + } + +-- runStringCommand : string -> true | false message +lib.runStringCommand = function(str, map) + local c, n, rest = string.match(string.gsub(str, "^%s+", ""), "^(%w)(%d*)(.*)") + if not c then return true end + if n == "" then n = 1 else n = tonumber(n) end + for i = 1, n do map[c]() end +-- print(cmd, tostring(i).."/"..tostring(n)) +-- end + return lib.runStringCommand(rest, map) +end + +-- rep : number of repeats -> string -> string | nil +-- repeats string n times +lib.rep = function(n, str) + if not n or n < 0 then return nil end + local s = "" + for i = 1, n do + s = s .. str + end + return s +end + +return lib diff --git a/vineyard/turtle/package b/vineyard/turtle/package index 5b91eee..a1ade87 100644 --- a/vineyard/turtle/package +++ b/vineyard/turtle/package @@ -1,2 +1,3 @@ -cc lib/turtle-utils.lua:/lib/turtle-utils.lua:o +cc lib/turtle.lua:/lib/turtle.lua:o +cc lib/inventory.lua:/lib/inventory.lua:o cc vineyard/turtle/harvest.lua:/bin/harvest.lua:o