Advertisement
NTins

build

Aug 28th, 2014
249
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 6.96 KB | None | 0 0
  1. local computer = require("computer")
  2. local event = require("event")
  3. local fs = require("filesystem")
  4. local process = require("process")
  5. local robot = require("robot")
  6. local shell = require("shell")
  7.  
  8. local args = {...}
  9. if #args < 1 then
  10.   print("Please enter a file name with the schematic to build.")
  11.   return
  12. end
  13.  
  14. local file, reason = io.open(shell.resolve(args[1], "plan"))
  15. if not file then
  16.   io.stderr:write(reason .. "\n")
  17.   return
  18. end
  19.  
  20. print("Analyzing schematic...")
  21.  
  22. local counts = {}
  23. local width, height, depth = 0, 1, 0
  24. do
  25.   local lx, lz = 0, 0
  26.   while true do
  27.     local line = file:read()
  28.     if line == nil then
  29.       width = math.max(width, lx)
  30.       depth = math.max(depth, lz)
  31.       file:seek("set")
  32.       break
  33.     end
  34.     line = line:gsub("\r", "")
  35.     if line:sub(1, 1) == "#" then
  36.       height = height + 1
  37.       width = math.max(width, lx)
  38.       depth = math.max(depth, lz)
  39.       lx, lz = 0, 0
  40.     else
  41.       lz = lz + 1
  42.       lx = math.max(lx, #line)
  43.       for i = 1, #line do
  44.         if line:sub(i, i) == "1" then
  45.           counts[lz] = (counts[lz] or 0) + 1
  46.         end
  47.       end
  48.     end
  49.   end
  50. end
  51.  
  52. print("Model bounds: " .. width .. "x" .. height .. "x" .. depth)
  53.  
  54. local SLOT_DIRT = 1
  55. local SLOT_STONE = 2
  56. local y, z = 0, 0
  57. local offset, count = 0, depth
  58.  
  59. if #args > 1 then
  60.   offset = tonumber(args[2]) or 0
  61.   count = tonumber(args[3]) or (depth - offset)
  62. end
  63.  
  64. local cost = count * height -- the "wall"
  65. for z = offset + 1, offset + count do
  66.   cost = cost + (counts[z] or 0)
  67. end
  68.  
  69. do
  70.   local path = fs.path(process.running())
  71.   local stateFile = io.open(fs.concat(path, ".state"))
  72.   if stateFile then
  73.     print("State file found, loading...")
  74.     file:seek("set", tonumber(stateFile:read()))
  75.     y = tonumber(stateFile:read())
  76.     z = tonumber(stateFile:read())
  77.     offset = tonumber(stateFile:read())
  78.     count = tonumber(stateFile:read())
  79.     cost = tonumber(stateFile:read())
  80.     stateFile:close()
  81.     print("Resuming work on slabs " .. (offset + 1) .. " through " .. (offset + count) .. ".")
  82.     print("Continuing at height " .. y .. ", depth " .. z .. ".")
  83.     print("There's a total number of " .. cost .. " blocks left to place.")
  84.   else
  85.     robot.select(SLOT_DIRT)
  86.     print("I'll be working on slabs " .. (offset + 1) .. " through " .. (offset + count) .. ".")
  87.     print("That'll take a total of " .. cost .. " blocks. Put them in a chest in front of me.")
  88.     print("Also put a stack of dirt into my first inventory slot (the selected one).")
  89.   end
  90. end
  91.  
  92. print("Press any key when ready.")
  93. os.sleep(0.5)
  94. event.pull("key")
  95. print("Starting in 3 seconds...")
  96. os.sleep(3)
  97.  
  98. local function save()
  99.   local path = fs.path(process.running())
  100.   local stateFile, reason = io.open(fs.concat(path, ".state"), "w")
  101.   if not stateFile then
  102.     io.stderr:write("Failed saving state: " .. tostring(reason))
  103.     return
  104.   end
  105.   stateFile:write(tostring(file:seek("cur")) .. "\n")
  106.   stateFile:write(tostring(y) .. "\n")
  107.   stateFile:write(tostring(z) .. "\n")
  108.   stateFile:write(tostring(offset) .. "\n")
  109.   stateFile:write(tostring(count) .. "\n")
  110.   stateFile:write(tostring(cost) .. "\n")
  111.   stateFile:close()
  112.   print("State saved.")
  113. end
  114.  
  115. function restock()
  116.   local slot = SLOT_STONE
  117.   robot.select(slot)
  118.   while cost > 0 and slot <= 16 do
  119.     -- fill up this slot, stop if we have all we need.
  120.     while true do
  121.       local count = robot.count(slot)
  122.       local space = robot.space(slot)
  123.       local wantCount = math.min(cost, space) -- avoid overflow
  124.       if wantCount <= 0 then
  125.         break
  126.       end
  127.       robot.suck(wantCount)
  128.       local suckCount = robot.count(slot) - count
  129.       cost = cost - suckCount
  130.       if suckCount == 0 then
  131.         -- not enough materials in chest
  132.         os.sleep(5)
  133.       end
  134.     end
  135.     slot = slot + 1
  136.   end
  137.   local energy = computer.energy()
  138.   if energy < computer.maxEnergy() * 0.5 then
  139.     repeat
  140.       os.sleep(1)
  141.       if computer.energy() < energy and computer.energy() < computer.maxEnergy() * 0.05 then
  142.         print("Emergency shutdown - out of energy!")
  143.         save()
  144.         print("Shutting down in 3 seconds...")
  145.         os.sleep(3)
  146.         computer.shutdown()
  147.       end
  148.     until computer.energy() > computer.maxEnergy() * 0.95
  149.   end
  150. end
  151.  
  152. local function selectStone()
  153.   local didPrint = false
  154.   while true do
  155.     for slot = SLOT_STONE, 16 do
  156.       if robot.count(slot) > 0 then
  157.         robot.select(slot)
  158.         return
  159.       end
  160.     end
  161.     if not didPrint then
  162.       print("I need more materials!")
  163.       didPrint = true
  164.     end
  165.     os.sleep(5)
  166.   end
  167. end
  168.  
  169. local function gotoWork()
  170.   -- PRE: looks at chest
  171.   robot.turnLeft()
  172.   repeat until robot.back()
  173.   robot.turnRight()
  174.   for _ = 1, z do
  175.     repeat until robot.back()
  176.   end
  177.   for _ = 1, y do
  178.     repeat until robot.up()
  179.   end
  180.   robot.turnLeft()
  181.   repeat until robot.back()
  182.   repeat until robot.back()
  183.   -- POST: stands at job pos, facing -x
  184. end
  185.  
  186. local function moveToChest(force)
  187.   -- PRE: stands at job pos, facing -x
  188.   local stones = 0
  189.   for slot = SLOT_STONE, 16 do
  190.     stones = stones + robot.count(slot)
  191.   end
  192.   if force or (stones < width and cost > 0) or (computer.energy() > 0 and computer.energy() < computer.maxEnergy() * 0.1) then
  193.     repeat until robot.forward()
  194.     repeat until robot.forward()
  195.     robot.turnRight()
  196.     for _ = 1, y do
  197.       repeat until robot.down()
  198.     end
  199.     for _ = 1, z do
  200.       repeat until robot.forward()
  201.     end
  202.     robot.turnLeft()
  203.     repeat until robot.forward()
  204.     robot.turnRight()
  205.     restock()
  206.     return true
  207.   end
  208. end
  209.  
  210. restock()
  211. gotoWork()
  212. for _ = 1, offset do
  213.   file:read()
  214. end
  215. while true do
  216.   local row = file:read()
  217.   if not row then
  218.     moveToChest(true)
  219.     return
  220.   end
  221.   if string.sub(row, 1, 1) == "#" then
  222.     -- skip, handled in z == depth below
  223.     for _ = 1, offset do
  224.       file:read()
  225.     end
  226.   else
  227.     -- PRE: at job pos, facing -x
  228.     selectStone()
  229.     repeat until robot.place()
  230.     local placed = 0
  231.     for x = 1, width do
  232.       if not string.find(row, "1", x, true) then
  233.         break
  234.       end
  235.       repeat until robot.back()
  236.       if string.sub(row, x, x) == "0" then
  237.         robot.select(SLOT_DIRT)
  238.       else
  239.         selectStone()
  240.       end
  241.       repeat until robot.place()
  242.       placed = placed + 1
  243.     end
  244.     repeat until robot.up()
  245.     robot.select(SLOT_DIRT)
  246.     for _ = 1, placed do
  247.       repeat until robot.forward()
  248.       robot.swingDown()
  249.     end
  250.     -- POST: above job pos, facing -x
  251.     if z + 1 < count then
  252.       robot.turnLeft()
  253.       repeat until robot.forward()
  254.       robot.turnRight()
  255.       repeat until robot.down()
  256.       z = z + 1
  257.       if moveToChest() then
  258.         gotoWork()
  259.       end
  260.     else
  261.       for _ = 1, depth - offset - count do
  262.         file:read()
  263.       end
  264.       y = y + 1
  265.       moveToChest(true)
  266.       z = 0
  267.       gotoWork()
  268.     end
  269.   end
  270. end
  271.  
  272. file:close()
  273. fs.remove(fs.concat(fs.path(process.running()), ".state"))
  274. print("Done!")
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement