Advertisement
hoblin

Sphere with fuel

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