jseely

DomeSphere

Mar 27th, 2013
95
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 7.85 KB | None | 0 0
  1. -- Dome and sphere builder.
  2. -- Copyright (C) 2012 Timothy Goddard
  3. --
  4. -- Permission is hereby granted, free of charge, to any person obtaining a copy of
  5. -- this software and associated documentation files (the "Software"), to deal in
  6. -- the Software without restriction, including without limitation the rights to
  7. -- use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
  8. -- the Software, and to permit persons to whom the Software is furnished to do so,
  9. -- subject to the following conditions:
  10. --
  11. -- The above copyright notice and this permission notice shall be included in all
  12. -- copies or substantial portions of the Software.
  13. --
  14. -- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. -- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
  16. -- FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
  17. -- COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
  18. -- IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  19. -- CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  20. --
  21. -- usage: sdbuild <type> <radius> [-c]
  22. -- type should be either dome or sphere
  23. -- radius is distance from centre - total width is actually 2 * radius + 1
  24. -- the structure will be built with its lowest point on the level the turtle is at
  25. -- the block the turtle starts on will be the horizontal centre
  26. -- if -c is passed, will only calculate number of blocks required and not build
  27.  
  28. local arg = { ... }
  29.  
  30. type = arg[1]
  31. radius = tonumber(arg[2])
  32.  
  33. cost_only = false
  34. blocks = 0
  35. if arg[3] == "-c" then
  36.   cost_only = true
  37. end
  38.  
  39. -- Navigation features
  40. -- allow the turtle to move while tracking its position
  41. -- this allows us to just give a destination point and have it go there
  42.  
  43. positionx = radius
  44. positiony = radius
  45. facing = 0
  46.  
  47. function turnRightTrack()
  48.   turtle.turnRight()
  49.   facing = facing + 1
  50.   if facing >= 4 then
  51.     facing = 0
  52.   end
  53. end
  54.  
  55. function turnLeftTrack()
  56.   turtle.turnLeft()
  57.   facing = facing - 1
  58.   if facing < 0 then
  59.     facing = 3
  60.   end
  61. end
  62.  
  63. function safeForward()
  64.   success = false
  65.   while not success do
  66.     turtle.dig()
  67.     success = turtle.forward()
  68.     if not success then
  69.       print("Blocked attempting to move forward.")
  70.       print("Please clear and press enter to continue.")
  71.       io.read()
  72.     end
  73.   end
  74. end
  75.  
  76. function safeBack()
  77.   success = false
  78.   while not success do
  79.     success = turtle.back()
  80.     if not success then
  81.       print("Blocked attempting to move back.")
  82.       print("Please clear and press enter to continue.")
  83.       io.read()
  84.     end
  85.   end
  86. end
  87.  
  88. function safeUp()
  89.   success = false
  90.   while not success do
  91.     turtle.digUp()
  92.     success = turtle.up()
  93.     if not success then
  94.       print("Blocked attempting to move up.")
  95.       print("Please clear and press enter to continue.")
  96.       io.read()
  97.     end
  98.   end
  99. end
  100.  
  101. function moveY(targety)
  102.   if targety == positiony then
  103.     return
  104.   end
  105.  
  106.   if (facing ~= 0 and facing ~= 2) then -- check axis
  107.     turnRightTrack()
  108.   end
  109.  
  110.   while targety > positiony do
  111.     if facing == 0 then
  112.       safeForward()
  113.     else
  114.       safeBack()
  115.     end
  116.     positiony = positiony + 1
  117.   end
  118.  
  119.   while targety < positiony do
  120.     if facing == 2 then
  121.       safeForward()
  122.     else
  123.       safeBack()
  124.     end
  125.     positiony = positiony - 1
  126.   end
  127. end
  128.  
  129. function moveX(targetx)
  130.   if targetx == positionx then
  131.     return
  132.   end
  133.  
  134.   if (facing ~= 1 and facing ~= 3) then -- check axis
  135.     turnRightTrack()
  136.   end
  137.  
  138.   while targetx > positionx do
  139.     if facing == 1 then
  140.       safeForward()
  141.     else
  142.       safeBack()
  143.     end
  144.     positionx = positionx + 1
  145.   end
  146.  
  147.   while targetx < positionx do
  148.     if facing == 3 then
  149.       safeForward()
  150.     else
  151.       safeBack()
  152.     end
  153.     positionx = positionx - 1
  154.   end
  155. end
  156.  
  157. function navigateTo(targetx, targety)
  158.   -- Cost calculation mode - don't move
  159.   if cost_only then
  160.     return
  161.   end
  162.  
  163.   if facing == 0 or facing == 2 then -- Y axis
  164.     moveY(targety)
  165.     moveX(targetx)
  166.   else
  167.     moveX(targetx)
  168.     moveY(targety)
  169.   end
  170. end
  171.  
  172. cslot = 1
  173. function placeBlock()
  174.   -- Cost calculation mode - don't move
  175.   blocks = blocks + 1
  176.   if cost_only then
  177.     return
  178.   end
  179.  
  180.   if turtle.getItemCount(cslot) == 0 then
  181.     foundSlot = false
  182.     while not foundSlot do
  183.       for i = 1,9 do
  184.         if turtle.getItemCount(i) > 0 then
  185.           foundSlot = i
  186.           break
  187.         end
  188.       end
  189.       if not foundSlot then
  190.         -- No resources
  191.         print("Out of building materials. Please refill and press enter to continue.")
  192.         io.read()
  193.       end
  194.     end
  195.     cslot = foundSlot
  196.     turtle.select(foundSlot)
  197.   end
  198.  
  199.   turtle.placeDown()
  200. end
  201.  
  202. -- Main dome and sphere building routine
  203.  
  204. width = radius * 2 + 1
  205. sqrt3 = 3 ^ 0.5
  206. boundary_radius = radius + 1.0
  207. boundary2 = boundary_radius ^ 2
  208.  
  209. if type == "dome" then
  210.   zstart = radius
  211. elseif type == "sphere" then
  212.   zstart = 0
  213. else
  214.   print("Usage: sdbuild <shape> <radius> [-c]")
  215.   os.exit(1)
  216. end
  217. zend = width - 1
  218.  
  219. -- This loop is for each vertical layer through the sphere or dome.
  220. for z = zstart,zend do
  221.   if not cost_only then
  222.     safeUp()
  223.   end
  224.   print("Layer " .. z)
  225.   cz2 = (radius - z) ^ 2
  226.  
  227.   limit_offset_y = (boundary2 - cz2) ^ 0.5
  228.   max_offset_y = math.ceil(limit_offset_y)
  229.  
  230.   -- We do first the +x side, then the -x side to make movement efficient
  231.   for side = 0,1 do
  232.     -- On the right we go from small y to large y, on the left reversed
  233.     -- This makes us travel clockwise around each layer
  234.     if (side == 0) then
  235.       ystart = radius - max_offset_y
  236.       yend = radius + max_offset_y
  237.       ystep = 1
  238.     else
  239.       ystart = radius + max_offset_y
  240.       yend = radius - max_offset_y
  241.       ystep = -1
  242.     end
  243.    
  244.     for y = ystart,yend,ystep do
  245.       cy2 = (radius - y) ^ 2
  246.      
  247.       remainder2 = (boundary2 - cz2 - cy2)
  248.      
  249.      
  250.       if remainder2 >= 0 then
  251.         -- This is the maximum difference in x from the centre we can be without definitely being outside the radius
  252.         max_offset_x = math.ceil((boundary2 - cz2 - cy2) ^ 0.5)
  253.        
  254.         -- Only do either the +x or -x side
  255.         if (side == 0) then
  256.           -- +x side
  257.           xstart = radius
  258.           xend = radius + max_offset_x
  259.         else
  260.           -- -x side
  261.           xstart = radius - max_offset_x
  262.           xend = radius - 1
  263.         end
  264.        
  265.         -- Reverse direction we traverse xs when in -y side
  266.         if y > radius then
  267.           temp = xstart
  268.           xstart = xend
  269.           xend = temp
  270.           xstep = -1
  271.         else
  272.           xstep = 1
  273.         end
  274.        
  275.         for x = xstart,xend,xstep do
  276.           cx2 = (radius - x) ^ 2
  277.           distance_to_centre = (cx2 + cy2 + cz2) ^ 0.5
  278.           -- Only blocks within the radius but still within 1 3d-diagonal block of the edge are eligible
  279.           if distance_to_centre < boundary_radius and distance_to_centre + sqrt3 >= boundary_radius then
  280.             offsets = {{0, 1, 0}, {0, -1, 0}, {1, 0, 0}, {-1, 0, 0}, {0, 0, 1}, {0, 0, -1}}
  281.             for i=1,6 do
  282.               offset = offsets[i]
  283.               dx = offset[1]
  284.               dy = offset[2]
  285.               dz = offset[3]
  286.               if ((radius - (x + dx)) ^ 2 + (radius - (y + dy)) ^ 2 + (radius - (z + dz)) ^ 2) ^ 0.5 >= boundary_radius then
  287.                 -- This is a point to use
  288.                 navigateTo(x, y)
  289.                 placeBlock()
  290.                 break
  291.               end
  292.             end
  293.           end
  294.         end
  295.       end
  296.     end
  297.   end
  298. end
  299.  
  300. -- Return to where we started in x,y place and turn to face original direction
  301. -- Don't change vertical place though - should be solid under us!
  302. navigateTo(radius, radius)
  303. while (facing > 0) do
  304.   turnLeftTrack()
  305. end
  306.  
  307. print("Blocks used: " .. blocks)
Advertisement
Add Comment
Please, Sign In to add comment