Guest User

sbuilde

a guest
Aug 24th, 2013
728
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  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.  
  36. clear_blocks = true
  37. ender_fill = true
  38.  
  39. if arg[3] == "-c" then
  40. cost_only = true
  41. end
  42.  
  43. -- Navigation features
  44. -- allow the turtle to move while tracking its position
  45. -- this allows us to just give a destination point and have it go there
  46.  
  47. positionx = radius
  48. positiony = radius
  49. facing = 0
  50.  
  51. function turnRightTrack()
  52. turtle.turnRight()
  53. facing = facing + 1
  54. if facing >= 4 then
  55. facing = 0
  56. end
  57. end
  58.  
  59. function turnLeftTrack()
  60. turtle.turnLeft()
  61. facing = facing - 1
  62. if facing < 0 then
  63. facing = 3
  64. end
  65. end
  66.  
  67. function safeForward()
  68. success = false
  69. while not success do
  70. success = turtle.forward()
  71. if not success then
  72. if clear_blocks then
  73. turtle.select(15)
  74. turtle.attack()
  75. turtle.dig()
  76. turtle.drop()
  77. turtle.select(1)
  78. else
  79. print("Blocked attempting to move forward.")
  80. print("Please clear and press enter to continue.")
  81. io.read()
  82. end
  83. end
  84. end
  85. end
  86.  
  87. function safeBack()
  88. success = false
  89. while not success do
  90. success = turtle.back()
  91. if not success then
  92. if clear_blocks then
  93. turtle.select(15)
  94. turtle.turnLeft()
  95. turtle.turnLeft()
  96. turtle.attack()
  97. turtle.dig()
  98. turtle.drop()
  99. turtle.turnRight()
  100. turtle.turnRight()
  101. turtle.select(1)
  102. else
  103. print("Blocked attempting to move back.")
  104. print("Please clear and press enter to continue.")
  105. io.read()
  106. end
  107. end
  108. end
  109. end
  110.  
  111. function safeUp()
  112. success = false
  113. while not success do
  114. success = turtle.up()
  115. if not success then
  116. if clear_blocks then
  117. turtle.select(15)
  118. turtle.attackUp()
  119. turtle.digUp()
  120. turtle.drop()
  121. turtle.select(1)
  122. else
  123. print("Blocked attempting to move up.")
  124. print("Please clear and press enter to continue.")
  125. io.read()
  126. end
  127. end
  128. end
  129. end
  130.  
  131. function moveY(targety)
  132. if targety == positiony then
  133. return
  134. end
  135.  
  136. if (facing ~= 0 and facing ~= 2) then -- check axis
  137. turnRightTrack()
  138. end
  139.  
  140. while targety > positiony do
  141. if facing == 0 then
  142. safeForward()
  143. else
  144. safeBack()
  145. end
  146. positiony = positiony + 1
  147. end
  148.  
  149. while targety < positiony do
  150. if facing == 2 then
  151. safeForward()
  152. else
  153. safeBack()
  154. end
  155. positiony = positiony - 1
  156. end
  157. end
  158.  
  159. function moveX(targetx)
  160. if targetx == positionx then
  161. return
  162. end
  163.  
  164. if (facing ~= 1 and facing ~= 3) then -- check axis
  165. turnRightTrack()
  166. end
  167.  
  168. while targetx > positionx do
  169. if facing == 1 then
  170. safeForward()
  171. else
  172. safeBack()
  173. end
  174. positionx = positionx + 1
  175. end
  176.  
  177. while targetx < positionx do
  178. if facing == 3 then
  179. safeForward()
  180. else
  181. safeBack()
  182. end
  183. positionx = positionx - 1
  184. end
  185. end
  186.  
  187. function navigateTo(targetx, targety)
  188. -- Cost calculation mode - don't move
  189. if cost_only then
  190. return
  191. end
  192.  
  193. if facing == 0 or facing == 2 then -- Y axis
  194. moveY(targety)
  195. moveX(targetx)
  196. else
  197. moveX(targetx)
  198. moveY(targety)
  199. end
  200. end
  201.  
  202. cslot = 1
  203. function placeBlock()
  204. -- Cost calculation mode - don't move
  205. blocks = blocks + 1
  206. if cost_only then
  207. return
  208. end
  209.  
  210. if turtle.getItemCount(cslot) == 0 then
  211. foundSlot = false
  212. while not foundSlot do
  213. for i = 1,9 do
  214. if turtle.getItemCount(i) > 0 then
  215. foundSlot = i
  216. break
  217. end
  218. end
  219. if not foundSlot then
  220. if ender_fill then
  221. turtle.attackUp()
  222. turtle.digUp()
  223. turtle.select(16)
  224. turtle.placeUp()
  225. turtle.select(1)
  226. turtle.dropDown()
  227. turtle.suckUp()
  228. turtle.select(16)
  229. turtle.digUp()
  230. turtle.select(1)
  231. else
  232. -- No resources
  233. print("Out of building materials. Please refill and press enter to continue.")
  234. io.read()
  235. end
  236. end
  237. end
  238. cslot = foundSlot
  239. turtle.select(foundSlot)
  240. end
  241.  
  242. turtle.placeDown()
  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