Advertisement
hoblin

Sphere

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