LeviathanV

Digging Program (OC)

Mar 10th, 2017
112
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 5.17 KB | None | 0 0
  1. --open computers
  2.  
  3. local component = require("component")
  4. local computer = require("computer")
  5. local robot = require("robot")
  6. local shell = require("shell")
  7. local sides = require("sides")
  8.  
  9. if not component.isAvailable("robot") then
  10.   io.stderr:write("can only run on robots")
  11.   return
  12. end
  13.  
  14. local args, options = shell.parse(...)
  15. if #args < 1 then
  16.   io.write("Usage: dig [-s] <size>\n")
  17.   io.write(" -s: shutdown when done.")
  18.   return
  19. end
  20.  
  21. local size = tonumber(args[1])
  22. if not size then
  23.   io.stderr:write("invalid size")
  24.   return
  25. end
  26.  
  27. local r = component.robot
  28. local x, y, z, f = 0, 0, 0, 0
  29. local dropping = false -- avoid recursing into drop()
  30. local delta = {[0] = function() x = x + 1 end, [1] = function() y = y + 1 end,
  31.                [2] = function() x = x - 1 end, [3] = function() y = y - 1 end}
  32.  
  33. local function turnRight()
  34.   robot.turnRight()
  35.   f = (f + 1) % 4
  36. end
  37.  
  38. local function turnLeft()
  39.   robot.turnLeft()
  40.   f = (f - 1) % 4
  41. end
  42.  
  43. local function turnTowards(side)
  44.   if f == side - 1 then
  45.     turnRight()
  46.   else
  47.     while f ~= side do
  48.       turnLeft()
  49.     end
  50.   end
  51. end
  52.  
  53. local checkedDrop -- forward declaration
  54.  
  55. local function clearBlock(side, cannotRetry)
  56.   while r.suck(side) do
  57.     checkedDrop()
  58.   end
  59.   local result, reason = r.swing(side)
  60.   if result then
  61.     checkedDrop()
  62.   else
  63.     local _, what = r.detect(side)
  64.     if cannotRetry and what ~= "air" and what ~= "entity" then
  65.       return false
  66.     end
  67.   end
  68.   return true
  69. end
  70.  
  71. local function tryMove(side)
  72.   side = side or sides.forward
  73.   local tries = 10
  74.   while not r.move(side) do
  75.     tries = tries - 1
  76.     if not clearBlock(side, tries < 1) then
  77.       return false
  78.     end
  79.   end
  80.   if side == sides.down then
  81.     z = z + 1
  82.   elseif side == sides.up then
  83.     z = z - 1
  84.   else
  85.     delta[f]()
  86.   end
  87.   return true
  88. end
  89.  
  90. local function moveTo(tx, ty, tz, backwards)
  91.   local axes = {
  92.     function()
  93.       while z > tz do
  94.         tryMove(sides.up)
  95.       end
  96.       while z < tz do
  97.         tryMove(sides.down)
  98.       end
  99.     end,
  100.     function()
  101.       if y > ty then
  102.         turnTowards(3)
  103.         repeat tryMove() until y == ty
  104.       elseif y < ty then
  105.         turnTowards(1)
  106.         repeat tryMove() until y == ty
  107.       end
  108.     end,
  109.     function()
  110.       if x > tx then
  111.         turnTowards(2)
  112.         repeat tryMove() until x == tx
  113.       elseif x < tx then
  114.         turnTowards(0)
  115.         repeat tryMove() until x == tx
  116.       end
  117.     end
  118.   }
  119.   if backwards then
  120.     for axis = 3, 1, -1 do
  121.       axes[axis]()
  122.     end
  123.   else
  124.     for axis = 1, 3 do
  125.       axes[axis]()
  126.     end
  127.   end
  128. end
  129.  
  130. function checkedDrop(force)
  131.   local empty = 0
  132.   for slot = 1, 16 do
  133.     if robot.count(slot) == 0 then
  134.       empty = empty + 1
  135.     end
  136.   end
  137.   if not dropping and empty == 0 or force and empty < 16 then
  138.     local ox, oy, oz, of = x, y, z, f
  139.     dropping = true
  140.     moveTo(0, 0, 0)
  141.     turnTowards(2)
  142.  
  143.     for slot = 1, 16 do
  144.       if robot.count(slot) > 0 then
  145.         robot.select(slot)
  146.         local wait = 1
  147.         repeat
  148.           if not robot.drop() then
  149.             os.sleep(wait)
  150.             wait = math.min(10, wait + 1)
  151.           end
  152.         until robot.count(slot) == 0
  153.       end
  154.     end
  155.     robot.select(1)
  156.  
  157.     dropping = false
  158.     moveTo(ox, oy, oz, true)
  159.     turnTowards(of)
  160.   end
  161. end
  162.  
  163. local function step()
  164.   clearBlock(sides.down)
  165.   if not tryMove() then
  166.     return false
  167.   end
  168.   clearBlock(sides.up)
  169.   return true
  170. end
  171.  
  172. local function turn(i)
  173.   if i % 2 == 1 then
  174.     turnRight()
  175.   else
  176.     turnLeft()
  177.   end
  178. end
  179.  
  180. local function digLayer()
  181.   --[[ We move in zig-zag lines, clearing three layers at a time. This means we
  182.        have to differentiate at the end of the last line between even and odd
  183.        sizes on which way to face for the next layer:
  184.        For either size we rotate once to the right. For even sizes this will
  185.        cause the next layer to be dug out rotated by ninety degrees. For odd
  186.        ones the return path is symmetrical, meaning we just turn around.
  187.        Examples for two layers:
  188.        s--x--x      e--x--x      s--x--x--x      x--x  x--x
  189.              |            |               |      |  |  |  |
  190.        x--x--x  ->  x--x--x      x--x--x--x      x  x  x  x
  191.        |            |            |           ->  |  |  |  |
  192.        x--x--e      x--x--s      x--x--x--x      x  x  x  x
  193.                                           |      |  |  |  |
  194.                                  e--x--x--x      s  x--x  e
  195.        Legend: s = start, x = a position, e = end, - = a move
  196.   ]]
  197.   for i = 1, size do
  198.     for j = 1, size - 1 do
  199.       if not step() then
  200.         return false
  201.       end
  202.     end
  203.     if i < size then
  204.       -- End of a normal line, move the "cap".
  205.       turn(i)
  206.       if not step() then
  207.         return false
  208.       end
  209.       turn(i)
  210.     else
  211.       turnRight()
  212.       if size % 2 == 1 then
  213.         turnRight()
  214.       end
  215.       for i = 1, 3 do
  216.         if not tryMove(sides.down) then
  217.           return false
  218.         end
  219.       end
  220.     end
  221.   end
  222.   return true
  223. end
  224.  
  225. repeat until not digLayer()
  226. moveTo(0, 0, 0)
  227. turnTowards(0)
  228. checkedDrop(true)
  229.  
  230. if options.s then
  231.   computer.shutdown()
  232. end
Add Comment
Please, Sign In to add comment