SHARE
    TWEET
    ferrybig

    computercraft sphere

    Apr 6th, 2014
    485
    0
    Never
    Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
    Lua 7.82 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. local arg = { ... }
    28. type = arg[1]
    29. radius = tonumber(arg[2])
    30. cost_only = false
    31. blocks = 0
    32. if arg[3] == "-c" then
    33. cost_only = true
    34. end
    35. -- Navigation features
    36. -- allow the turtle to move while tracking its position
    37. -- this allows us to just give a destination point and have it go there
    38. positionx = radius
    39. positiony = radius
    40. facing = 0
    41. function turnRightTrack()
    42. turtle.turnRight()
    43. facing = facing + 1
    44. if facing >= 4 then
    45. facing = 0
    46. end
    47. end
    48. function turnLeftTrack()
    49. turtle.turnLeft()
    50. facing = facing - 1
    51. if facing < 0 then
    52. facing = 3
    53. end
    54. end
    55. function safeForward()
    56. success = false
    57. while not success do
    58. success = turtle.forward()
    59. if not success then
    60. print("Blocked attempting to move forward.")
    61. print("Please clear and press enter to continue.")
    62. io.read()
    63. end
    64. end
    65. end
    66. function safeBack()
    67. success = false
    68. while not success do
    69. success = turtle.back()
    70. if not success then
    71. print("Blocked attempting to move back.")
    72. print("Please clear and press enter to continue.")
    73. io.read()
    74. end
    75. end
    76. end
    77. function safeUp()
    78. success = false
    79. while not success do
    80. success = turtle.up()
    81. if not success then
    82. print("Blocked attempting to move up.")
    83. print("Please clear and press enter to continue.")
    84. io.read()
    85. end
    86. end
    87. end
    88. function moveY(targety)
    89. if targety == positiony then
    90. return
    91. end
    92. if (facing ~= 0 and facing ~= 2) then -- check axis
    93. turnRightTrack()
    94. end
    95. while targety > positiony do
    96. if facing == 0 then
    97. safeForward()
    98. else
    99. safeBack()
    100. end
    101. positiony = positiony + 1
    102. end
    103. while targety < positiony do
    104. if facing == 2 then
    105. safeForward()
    106. else
    107. safeBack()
    108. end
    109. positiony = positiony - 1
    110. end
    111. end
    112. function moveX(targetx)
    113. if targetx == positionx then
    114. return
    115. end
    116. if (facing ~= 1 and facing ~= 3) then -- check axis
    117. turnRightTrack()
    118. end
    119. while targetx > positionx do
    120. if facing == 1 then
    121. safeForward()
    122. else
    123. safeBack()
    124. end
    125. positionx = positionx + 1
    126. end
    127. while targetx < positionx do
    128. if facing == 3 then
    129. safeForward()
    130. else
    131. safeBack()
    132. end
    133. positionx = positionx - 1
    134. end
    135. end
    136. function navigateTo(targetx, targety)
    137. -- Cost calculation mode - don't move
    138. if cost_only then
    139. return
    140. end
    141. if facing == 0 or facing == 2 then -- Y axis
    142. moveY(targety)
    143. moveX(targetx)
    144. else
    145. moveX(targetx)
    146. moveY(targety)
    147. end
    148. end
    149. cslot = 1
    150. function placeBlock()
    151. -- Cost calculation mode - don't move
    152. blocks = blocks + 1
    153. if cost_only then
    154. return
    155. end
    156. if turtle.getItemCount(cslot) == 0 then
    157. foundSlot = false
    158. while not foundSlot do
    159. for i = 1,9 do
    160. if turtle.getItemCount(i) > 0 then
    161. foundSlot = i
    162. break
    163. end
    164. end
    165. if not foundSlot then
    166. -- No resources
    167. print("Out of building materials. Please refill and press enter to continue.")
    168. io.read()
    169. end
    170. end
    171. cslot = foundSlot
    172. turtle.select(foundSlot)
    173. end
    174. turtle.placeDown()
    175. end
    176. -- Main dome and sphere building routine
    177. width = radius * 2 + 1
    178. sqrt3 = 3 ^ 0.5
    179. boundary_radius = radius + 1.0
    180. boundary2 = boundary_radius ^ 2
    181. if type == "dome" then
    182. zstart = radius
    183. elseif type == "sphere" then
    184. zstart = 0
    185. else
    186. print("Usage: sdbuild <shape> <radius> [-c]")
    187. os.exit(1)
    188. end
    189. zend = width - 1
    190. -- This loop is for each vertical layer through the sphere or dome.
    191. for z = zstart,zend do
    192. if not cost_only then
    193. safeUp()
    194. end
    195. print("Layer " .. z)
    196. cz2 = (radius - z) ^ 2
    197. limit_offset_y = (boundary2 - cz2) ^ 0.5
    198. max_offset_y = math.ceil(limit_offset_y)
    199. -- We do first the +x side, then the -x side to make movement efficient
    200. for side = 0,1 do
    201. -- On the right we go from small y to large y, on the left reversed
    202. -- This makes us travel clockwise around each layer
    203. if (side == 0) then
    204. ystart = radius - max_offset_y
    205. yend = radius + max_offset_y
    206. ystep = 1
    207. else
    208. ystart = radius + max_offset_y
    209. yend = radius - max_offset_y
    210. ystep = -1
    211. end
    212. for y = ystart,yend,ystep do
    213. cy2 = (radius - y) ^ 2
    214. remainder2 = (boundary2 - cz2 - cy2)
    215. if remainder2 >= 0 then
    216. -- This is the maximum difference in x from the centre we can be without definitely being outside the radius
    217. max_offset_x = math.ceil((boundary2 - cz2 - cy2) ^ 0.5)
    218. -- Only do either the +x or -x side
    219. if (side == 0) then
    220. -- +x side
    221. xstart = radius
    222. xend = radius + max_offset_x
    223. else
    224. -- -x side
    225. xstart = radius - max_offset_x
    226. xend = radius - 1
    227. end
    228. -- Reverse direction we traverse xs when in -y side
    229. if y > radius then
    230. temp = xstart
    231. xstart = xend
    232. xend = temp
    233. xstep = -1
    234. else
    235. xstep = 1
    236. end
    237. for x = xstart,xend,xstep do
    238. cx2 = (radius - x) ^ 2
    239. distance_to_centre = (cx2 + cy2 + cz2) ^ 0.5
    240. -- Only blocks within the radius but still within 1 3d-diagonal block of the edge are eligible
    241. if distance_to_centre < boundary_radius and distance_to_centre + sqrt3 >= boundary_radius then
    242. offsets = {{0, 1, 0}, {0, -1, 0}, {1, 0, 0}, {-1, 0, 0}, {0, 0, 1}, {0, 0, -1}}
    243. for i=1,6 do
    244. offset = offsets[i]
    245. dx = offset[1]
    246. dy = offset[2]
    247. dz = offset[3]
    248. if ((radius - (x + dx)) ^ 2 + (radius - (y + dy)) ^ 2 + (radius - (z + dz)) ^ 2) ^ 0.5 >= boundary_radius then
    249. -- This is a point to use
    250. navigateTo(x, y)
    251. placeBlock()
    252. break
    253. end
    254. end
    255. end
    256. end
    257. end
    258. end
    259. end
    260. end
    261. -- Return to where we started in x,y place and turn to face original direction
    262. -- Don't change vertical place though - should be solid under us!
    263. navigateTo(radius, radius)
    264. while (facing > 0) do
    265. turnLeftTrack()
    266. end
    267. print("Blocks used: " .. blocks)
    Add Comment
    Please, Sign In to add comment
    Public Pastes
    We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
    Not a member of Pastebin yet?
    Sign Up, it unlocks many cool features!

    AltStyle によって変換されたページ (->オリジナル) /