Advertisement
1ng0

OpenComputer Robot dome and sphere builder

May 14th, 2014
143
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 6.82 KB | None | 0 0
  1. -- OpenComputer Robot dome and sphere builder.
  2. -- Copyright © 2014 by 1ng0
  3. -- Insert the Hover-Upgrade in the Robot to place items in the Air!
  4. -- usage: sdbuild <type> <radius> [-c]
  5. -- type should be either dome or sphere
  6. -- radius is distance from centre - total width is actually 2 * radius + 1
  7. -- the structure will be built with its lowest point on the level the robot is at
  8. -- the block the robot starts on will be the horizontal centre
  9. -- if -c is passed, will only calculate number of blocks required and not build
  10.  
  11. local arg = { ... }
  12. local robot = require("robot")
  13.  
  14. type = arg[1]
  15. radius = tonumber(arg[2])
  16.  
  17. cost_only = false
  18. blocks = 0
  19. if arg[3] == "-c" then
  20.   cost_only = true
  21. end
  22.  
  23. -- Navigation features
  24. -- allow the robot to move while tracking its position
  25. -- this allows us to just give a destination point and have it go there
  26.  
  27. positionx = radius
  28. positiony = radius
  29. facing = 0
  30.  
  31. function turnRightTrack()
  32.   robot.turnRight()
  33.   facing = facing + 1
  34.   if facing >= 4 then
  35.     facing = 0
  36.   end
  37. end
  38.  
  39. function turnLeftTrack()
  40.   robot.turnLeft()
  41.   facing = facing - 1
  42.   if facing < 0 then
  43.     facing = 3
  44.   end
  45. end
  46.  
  47. function safeForward()
  48.   success = false
  49.   while not success do
  50.     success = robot.forward()
  51.     if not success then
  52.       print("Blocked attempting to move forward.")
  53.       print("Please clear and press enter to continue.")
  54.       io.read()
  55.     end
  56.   end
  57. end
  58.  
  59. function safeBack()
  60.   success = false
  61.   while not success do
  62.     success = robot.back()
  63.     if not success then
  64.       print("Blocked attempting to move back.")
  65.       print("Please clear and press enter to continue.")
  66.       io.read()
  67.     end
  68.   end
  69. end
  70.  
  71. function safeUp()
  72.   success = false
  73.   while not success do
  74.     success = robot.up()
  75.     if not success then
  76.       print("Blocked attempting to move up.")
  77.       print("Please clear and press enter to continue.")
  78.       io.read()
  79.     end
  80.   end
  81. end
  82.  
  83. function moveY(targety)
  84.   if targety == positiony then
  85.     return
  86.   end
  87.  
  88.   if (facing ~= 0 and facing ~= 2) then -- check axis
  89.     turnRightTrack()
  90.   end
  91.  
  92.   while targety > positiony do
  93.     if facing == 0 then
  94.       safeForward()
  95.     else
  96.       safeBack()
  97.     end
  98.     positiony = positiony + 1
  99.   end
  100.  
  101.   while targety < positiony do
  102.     if facing == 2 then
  103.       safeForward()
  104.     else
  105.       safeBack()
  106.     end
  107.     positiony = positiony - 1
  108.   end
  109. end
  110.  
  111. function moveX(targetx)
  112.   if targetx == positionx then
  113.     return
  114.   end
  115.  
  116.   if (facing ~= 1 and facing ~= 3) then -- check axis
  117.     turnRightTrack()
  118.   end
  119.  
  120.   while targetx > positionx do
  121.     if facing == 1 then
  122.       safeForward()
  123.     else
  124.       safeBack()
  125.     end
  126.     positionx = positionx + 1
  127.   end
  128.  
  129.   while targetx < positionx do
  130.     if facing == 3 then
  131.       safeForward()
  132.     else
  133.       safeBack()
  134.     end
  135.     positionx = positionx - 1
  136.   end
  137. end
  138.  
  139. function navigateTo(targetx, targety)
  140.   -- Cost calculation mode - don't move
  141.   if cost_only then
  142.     return
  143.   end
  144.  
  145.   if facing == 0 or facing == 2 then -- Y axis
  146.     moveY(targety)
  147.     moveX(targetx)
  148.   else
  149.     moveX(targetx)
  150.     moveY(targety)
  151.   end
  152. end
  153.  
  154. cslot = 1
  155. function placeBlock()
  156.   -- Cost calculation mode - don't move
  157.   blocks = blocks + 1
  158.   if cost_only then
  159.     return
  160.   end
  161.  
  162.   if robot.count(cslot) == 0 then
  163.     foundSlot = false
  164.     while not foundSlot do
  165.       for i = 1,16 do
  166.         if robot.count(i) > 0 then
  167.           foundSlot = i
  168.           break
  169.         end
  170.       end
  171.       if not foundSlot then
  172.         -- No resources
  173.         print("Out of building materials. Please refill and press enter to continue.")
  174.         io.read()
  175.       end
  176.     end
  177.     cslot = foundSlot
  178.     robot.select(foundSlot)
  179.   end
  180.  
  181.   robot.placeDown()
  182. end
  183.  
  184. -- Main dome and sphere building routine
  185.  
  186. width = radius * 2 + 1
  187. sqrt3 = 3 ^ 0.5
  188. boundary_radius = radius + 1.0
  189. boundary2 = boundary_radius ^ 2
  190.  
  191. if type == "dome" then
  192.   zstart = radius
  193. elseif type == "sphere" then
  194.   zstart = 0
  195. else
  196.   print("Usage: sdbuild <shape> <radius> [-c]")
  197.   os.exit(1)
  198. end
  199. zend = width - 1
  200.  
  201. -- This loop is for each vertical layer through the sphere or dome.
  202. for z = zstart,zend do
  203.   if not cost_only then
  204.     safeUp()
  205.   end
  206.   print("Layer " .. z)
  207.   cz2 = (radius - z) ^ 2
  208.  
  209.   limit_offset_y = (boundary2 - cz2) ^ 0.5
  210.   max_offset_y = math.ceil(limit_offset_y)
  211.  
  212.   -- We do first the +x side, then the -x side to make movement efficient
  213.   for side = 0,1 do
  214.     -- On the right we go from small y to large y, on the left reversed
  215.     -- This makes us travel clockwise around each layer
  216.     if (side == 0) then
  217.       ystart = radius - max_offset_y
  218.       yend = radius + max_offset_y
  219.       ystep = 1
  220.     else
  221.       ystart = radius + max_offset_y
  222.       yend = radius - max_offset_y
  223.       ystep = -1
  224.     end
  225.    
  226.     for y = ystart,yend,ystep do
  227.       cy2 = (radius - y) ^ 2
  228.      
  229.       remainder2 = (boundary2 - cz2 - cy2)
  230.      
  231.       if remainder2 >= 0 then
  232.         -- This is the maximum difference in x from the centre we can be without definitely being outside the radius
  233.         max_offset_x = math.ceil((boundary2 - cz2 - cy2) ^ 0.5)
  234.        
  235.         -- Only do either the +x or -x side
  236.         if (side == 0) then
  237.           -- +x side
  238.           xstart = radius
  239.           xend = radius + max_offset_x
  240.         else
  241.           -- -x side
  242.           xstart = radius - max_offset_x
  243.           xend = radius - 1
  244.         end
  245.        
  246.         -- Reverse direction we traverse xs when in -y side
  247.         if y > radius then
  248.           temp = xstart
  249.           xstart = xend
  250.           xend = temp
  251.           xstep = -1
  252.         else
  253.           xstep = 1
  254.         end
  255.        
  256.         for x = xstart,xend,xstep do
  257.           cx2 = (radius - x) ^ 2
  258.           distance_to_centre = (cx2 + cy2 + cz2) ^ 0.5
  259.           -- Only blocks within the radius but still within 1 3d-diagonal block of the edge are eligible
  260.           if distance_to_centre < boundary_radius and distance_to_centre + sqrt3 >= boundary_radius then
  261.             offsets = {{0, 1, 0}, {0, -1, 0}, {1, 0, 0}, {-1, 0, 0}, {0, 0, 1}, {0, 0, -1}}
  262.             for i=1,6 do
  263.               offset = offsets[i]
  264.               dx = offset[1]
  265.               dy = offset[2]
  266.               dz = offset[3]
  267.               if ((radius - (x + dx)) ^ 2 + (radius - (y + dy)) ^ 2 + (radius - (z + dz)) ^ 2) ^ 0.5 >= boundary_radius then
  268.                 -- This is a point to use
  269.                 navigateTo(x, y)
  270.                 placeBlock()
  271.                 break
  272.               end
  273.             end
  274.           end
  275.         end
  276.       end
  277.     end
  278.   end
  279. end
  280.  
  281. -- Return to where we started in x,y place and turn to face original direction
  282. -- Don't change vertical place though - should be solid under us!
  283. navigateTo(radius, radius)
  284. while (facing > 0) do
  285.   turnLeftTrack()
  286. end
  287.  
  288. print("Blocks used: " .. blocks)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement