Moving Libraries
authorOlav Bakke Svendsen <mail@olavbs.no>
Fri, 24 May 2024 19:57:29 +0000 (21:57 +0200)
committerOlav Bakke Svendsen <mail@olavbs.no>
Fri, 24 May 2024 19:57:29 +0000 (21:57 +0200)
common/dl.lua
lib/inventory.lua [new file with mode: 0644]
lib/turtle-utils.lua [deleted file]
lib/turtle.lua [new file with mode: 0644]
vineyard/turtle/package

index 940029887ccd2dcaeb05af39343f9d6560b7c155..8ada45bb4ee70c174e57e1cf50a2e87e0b6ac012 100644 (file)
@@ -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 (file)
index 0000000..c047b76
--- /dev/null
@@ -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 (file)
index ab9f375..0000000
+++ /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 (file)
index 0000000..ab9f375
--- /dev/null
@@ -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
index 5b91eeeea3b8fc0ed336d214f98b1dfe91eeffa8..a1ade87e040e765ff76592b97b9d3dd29a3ebe30 100644 (file)
@@ -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