Bimgo

Turtle-Sphere and dome v1

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