SHARE
TWEET

voidresources.lua

rerere284 Mar 3rd, 2018 (edited) 84 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1.  
  2. local term = require("term")
  3. local serial = require("serialization")
  4. _G.recipes = _G.recipes or {}
  5.  
  6. local args = {...}
  7.  
  8.  
  9. local cmnd = args[1]
  10. table.remove(args,1)
  11. for i=1,#args do
  12.   if tonumber(args[i]) then
  13.     args[i] = tonumber(args[i])
  14.   end
  15. end
  16.  
  17.  
  18. --[[main actions:
  19.  
  20.  
  21.   get resources required for a craft/structure
  22.  
  23.   get crafting instructions for a craft
  24.  
  25.   get crafting instructions given you already have some resources
  26. ]]
  27.  
  28.  
  29. function addrecipe(name, outNum, ...)
  30.   local inp = {...}
  31.   local reqItems = {}
  32.   for i=1,#inp,2 do
  33.     table.insert(reqItems, { inp[i],inp[i+1] })
  34.   end
  35.   _G.recipes[name] = {outNum, reqItems}
  36.   print("added recipe for " .. name)
  37. end
  38.  
  39. function delrecipe(name)
  40.   _G.recipes[name] = nil
  41.   print("deleted recipe for " .. name)
  42. end
  43.  
  44. function addResources(...)
  45.   --add resource lists together
  46.   local inp = {...}
  47.   local final = {}
  48.   for i=1,#inp do--for each inputed list
  49.     for j=1,#inp[i] do--for each item
  50.       --collect a list 'final' of the amount of each resource totaled.
  51.       if final[ inp[i][j][1] ] then
  52.         final[ inp[i][j][1] ] = final[ inp[i][j][1] ] + inp[i][j][2]
  53.       else
  54.         final[ inp[i][j][1] ] = inp[i][j][2]
  55.       end
  56.     end
  57.   end
  58.   --convert 'final' to a normal format of a list of resources
  59.   local ret = {}
  60.   for k,v in pairs(final) do
  61.     table.insert(ret, {k, v})
  62.   end
  63.   return ret
  64. end
  65.  
  66. function addSetResources(reqA, ...)
  67.   --add resource lists to reqA
  68.   local inp = {...}
  69.   --make a map for reqA
  70.   local mp = {}
  71.   for i=1,#reqA do
  72.     mp[reqA[i][1]] = i
  73.   end
  74.   for i=1,#inp do--for each inputed list
  75.     for j=1,#inp[i] do--for each item
  76.       if mp[ inp[i][j][1] ] then--if we know where that resource is in reqA
  77.         --add to the amount of that resource
  78.         reqA[ mp[inp[i][j][1]] ][2] =
  79.           reqA[ mp[inp[i][j][1]] ][2] + inp[i][j][2]
  80.       else --add a new item to reqA
  81.         mp[ inp[i][j][1] ] = #reqA+1
  82.         reqA[#reqA+1] = {inp[i][j][1], inp[i][j][2]}
  83.       end
  84.     end
  85.   end
  86. end
  87.  
  88. function multResources(req, num)
  89.   --multiply resource amounts in req
  90.   for i=1,#req do
  91.     req[i][2] = req[i][2] * num
  92.   end
  93. end
  94.  
  95. function useSetResources(use, goal)
  96.   if not goal or #goal == 0 then return end
  97.   --make a map for use
  98.   local mpU = {}
  99.   for i=1,#use do
  100.     mpU[use[i][1]] = i
  101.   end
  102.   --make a map for goal
  103.   local mpG = {}
  104.   for i=1,#goal do
  105.     mpG[goal[i][1]] = i
  106.   end
  107.   --use the resources to craft goal
  108.   local remU, remG = {}, {}
  109.   for k,v in pairs(mpU) do
  110.     if mpG[k] then--for each resource in both
  111.       local nU, nG = use[mpU[k]][2], goal[mpG[k]][2]
  112.       if nG > nU then--if goal's resource > use's resource
  113.         --set goal's to goal's - use's
  114.         goal[mpG[k]][2] = goal[mpG[k]][2] - nU
  115.         table.insert(remU, k)
  116.         --table.remove(use, mpU[k])
  117.       elseif nG == nU then
  118.         --they cancel out equally
  119.         table.insert(remG, k)
  120.         --table.remove(goal, mpG[k])
  121.         table.insert(remU, k)
  122.         --table.remove(use, mpU[k])
  123.       else
  124.         --subtract that many from use
  125.         table.insert(remG, k)
  126.         --table.remove(goal, mpG[k])
  127.         use[mpU[k]][2] = use[mpU[k]][2] - nG
  128.       end
  129.     end
  130.   end
  131.   --remove spent stuff
  132.   for i=1,#remU do
  133.     for j=1,#use do
  134.       if use[j] and use[j][1] == remU[i] then
  135.         table.remove(use, j)
  136.       end
  137.     end
  138.   end
  139.   for i=1,#remG do
  140.     for j=1,#goal do
  141.       if goal[j] and goal[j][1] == remG[i] then
  142.         table.remove(goal, j)
  143.       end
  144.     end
  145.   end
  146. end
  147.  
  148. function calc(resource, amount, have)
  149.   amount = amount or 1
  150.   local requirements = {}
  151.   if _G.recipes[resource] then
  152.     local mat = _G.recipes[resource]
  153.     for i=1,#mat[2] do
  154.       local subReq = calc(mat[2][i][1], mat[2][i][2] * (amount/mat[1]), have)
  155.       useSetResources(subReq, have)
  156.       addSetResources(requirements, subReq)
  157.     end
  158.   else
  159.     local subReq = {{resource, amount}}
  160.     useSetResources(subReq, have)
  161.     addSetResources(requirements, subReq)
  162.   end
  163.   return requirements
  164. end
  165.  
  166. function oneCalc(resource, amount)
  167.   local requirements = {}
  168.   if _G.recipes[resource] then
  169.     local mat = _G.recipes[resource]
  170.     for i=1,#mat[2] do
  171.       local subReq = {mat[2][i][1], mat[2][i][2] * (amount/mat[1])}
  172.       addSetResources(requirements, subReq)
  173.     end
  174.   else
  175.     table.insert(requirements, {resource, amount})
  176.   end
  177.   return requirements
  178. end
  179.  
  180. local textY = 3
  181. function printLineWait(text)
  182.   print(text)
  183.   textY = textY + 1
  184.   local view = {term.getViewport()}
  185.   local h = view[2]
  186.   if textY > h then
  187.     term.read({ dobreak = true })
  188.     textY = 3
  189.   end
  190. end
  191.  
  192. function stackNumbers(num)
  193.   if type(num) ~= "number" then
  194.     if tonumber(num) then
  195.       num = tonumber(num)
  196.     else
  197.       print(num.." is not a number")
  198.     end
  199.   end
  200.   local ret = ""
  201.   if num > 64 then
  202.     for i=1,math.floor(num/64) do
  203.       ret = ret.."64".." "
  204.     end
  205.     ret = ret..(num%64)
  206.     if num%64 == 0 then
  207.       ret = string.sub(ret, 1, #ret-2)
  208.     end
  209.   else
  210.     ret = num
  211.   end
  212.   return ret
  213. end
  214.  
  215. function printResources(req)
  216.   if #req == 0 then
  217.     printLineWait("Resources: none.")
  218.     return
  219.   end
  220.   printLineWait("Resources:")
  221.   local enChar = ","
  222.   for i=1,#req do
  223.     if #req == 1 then enChar = ""
  224.     elseif #req == i then enChar = "." end
  225.     printLineWait(stackNumbers(req[i][2]) .. " " .. req[i][1]..enChar)
  226.   end
  227. end
  228.  
  229. function addSetCrafting(crfA, ...)
  230.   --add crafting lists to crfA
  231.   local inp = {...}
  232.   --make a map for crfA
  233.   local mp = {}
  234.   for i=1,#crfA do
  235.     mp[crfA[i][1]] = i
  236.   end
  237.   for i=1,#inp do--for each inputed list
  238.     for j=1,#inp[i] do--for each item
  239.       local ind = mp[ inp[i][j][1] ]
  240.       if ind then--if we know where that resource is in crfA
  241.         --add to the amount of that resource
  242.         crfA[ ind ][2] = crfA[ ind ][2] + inp[i][j][2]
  243.         if crfA[ ind ][3] < inp[i][j][3] then
  244.           --crfA gets highest tier for each material
  245.           crfA[ ind ][3] = inp[i][j][3]
  246.         end
  247.       else --add a new item to crfA
  248.         mp[ inp[i][j][1] ] = #crfA+1
  249.         crfA[#crfA+1] = {inp[i][j][1], inp[i][j][2], inp[i][j][3]}
  250.       end
  251.     end
  252.   end
  253. end
  254.  
  255. function calcCrafting(resource, amount, tier)
  256.   --[[
  257.     like calc(), but collects craftable items
  258.     items are given a tier
  259.     when merged, select higher tier
  260.   ]]
  261.   tier = tier or 1
  262.   local requirements = {}
  263.   if _G.recipes[resource] then--if this item has a recipe
  264.     --add itself to the requirements
  265.     addSetCrafting(requirements, {{resource, amount, tier}})
  266.     local mat = _G.recipes[resource]
  267.     for i=1,#mat[2] do--add its requirements to the requirements
  268.       local subReq = calcCrafting(mat[2][i][1],
  269.         mat[2][i][2] * (amount/mat[1]),
  270.         tier + 1)--later recipes have higher tier
  271.       addSetCrafting(requirements, subReq)
  272.     end
  273.   else--no recipe for this
  274.     requirements = {}
  275.   end
  276.   return requirements
  277. end
  278.  
  279. function printCrafting(crf)
  280.   --sort by largest tier first
  281.   table.sort(crf, function(a,b) return a[3] > b[3] end)
  282.   printLineWait("Crafting:")
  283.   --print crafting
  284.   local curTier = 0
  285.   for i=1,#crf do
  286.     if crf[i][3] ~= curTier then
  287.       curTier = crf[i][3]
  288.       printLineWait("Tier "..curTier..":")
  289.     end
  290.     printLineWait("craft "..stackNumbers(crf[i][2]).." "..crf[i][1])
  291.   end
  292. end
  293.  
  294. function listRecipes()
  295.   printLineWait("Recipes:")
  296.   for k,v in pairs(_G.recipes) do
  297.     printLineWait(k)
  298.     --printLineWait(v[1])--amount it crafts
  299.     --printLineWait(#v[2])--number of types of materials
  300.     --printResources(v[2])
  301.   end
  302. end
  303.  
  304. function recipeDetail(item)
  305.   if _G.recipes[item] then
  306.     printLineWait("Recipe: "..item)
  307.     printResources(_G.recipes[item][2])
  308.   else
  309.     printLineWait("I don't know about "..item..".")
  310.   end
  311. end
  312.  
  313. function stringSplit(inputstr, sep)
  314.   if sep == nil then
  315.     sep = "%s"
  316.   end
  317.   local t={}
  318.   for str in string.gmatch(inputstr..sep, "([^"..sep.."]*)"..sep) do
  319.     --print("\""..str.."\"")
  320.     table.insert(t,str)
  321.   end
  322.   return t
  323. end
  324.  
  325. function saveRecipes()
  326.   local file = io.open("craftingRecipes.txt","w")
  327.   file:write(serial.serialize(_G.recipes))
  328.   file:close()
  329. end
  330.  
  331. function loadRecipes()
  332.   local file = io.open("craftingRecipes.txt","r")
  333.   _G.recipes = serial.unserialize(file:read("*a"))
  334.   file:close()
  335. end
  336.  
  337.  
  338. cmdList = {}
  339. local function listCommands()
  340.   print("commands:")
  341.   for k,v in pairs(cmdList) do
  342.     print("  "..v)
  343.   end
  344. end
  345.  
  346. local commands = {
  347.   save = saveRecipes,
  348.   load = loadRecipes,
  349.   calculate = function(...)
  350.     local args = {...}
  351.     printResources( calc(args[1],args[2]) )
  352.     printCrafting( calcCrafting(args[1],args[2]) )
  353.   end,
  354.   fullcalculate = function(...)
  355.     local args = {...}
  356.     print("what do you have?")
  357.     local have = stringSplit(term.read(), ' ')
  358.     local haveItems = {}
  359.     for i=1,#have,2 do
  360.       table.insert(haveItems, { have[i],tonumber(have[i+1]) })
  361.     end
  362.     printResources(calc( args[1], args[2], haveItems ))
  363.     printCrafting(calcCrafting( args[1], args[2], haveItems ))
  364.   end,
  365.   setrecipe = addrecipe,
  366.   setstructure = function(name, ...)
  367.     addrecipe(name, 1, ...)
  368.   end,
  369.   delrecipe = delrecipe,
  370.   delstructure = delrecipie,
  371.   listrecipes = listRecipes,
  372.   recipedetail = recipeDetail,
  373.   commands = listCommands,
  374.   exit = function() end--dummy function, never called
  375. }
  376.  
  377. for k,v in pairs(commands) do--fill cmdList with list of commands
  378.   table.insert(cmdList, k)
  379. end
  380.  
  381. if cmnd and commands[cmnd] then--if a cmnd exists
  382.   --run it with args as inputs
  383.   commands[cmnd]( table.unpack(args) )
  384. else--no command, go into program loop
  385.   print("type \"commands\" for commands,")
  386.   print("type \"exit\" to exit.")
  387.  
  388.   local doExit = false
  389.   --while they haven't typed "exit", do this loop
  390.   while not doExit do
  391.     --take input of multiple items separated by spaces
  392.     local args = stringSplit(term.read(), "%s")
  393.     --print(#args)
  394.     if args[1] then--if they typed at least one thing
  395.       if args[1] == "exit" then break end
  396.       local cmnd = args[1]
  397.       table.remove(args,1)
  398.       if cmnd and commands[cmnd] then--if a cmnd exists
  399.         --run it with args as inputs
  400.         print("running "..cmnd)
  401.         commands[cmnd]( table.unpack(args) )
  402.       end
  403.     end
  404.   end
  405. end
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
 
Top