naschorr

mine-return-magnet

May 17th, 2017
80
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 7.06 KB | None | 0 0
  1. -- Globals
  2. local SQUARE_SIZE = 3
  3. local DOWN_SQUARE = 0
  4. local UP_SQUARE = 1
  5. local CONTAINER_SUBSTRINGS = {"chest"}
  6.  
  7. local squareType = DOWN_SQUARE
  8. local height = 1
  9. local magnet = nil
  10. local target = nil
  11.  
  12. -- http://lua-users.org/wiki/SimpleRound
  13. local function round(num, numDecimalPlaces)
  14. local mult = 10^(numDecimalPlaces or 0)
  15. return math.floor(num * mult + 0.5) / mult
  16. end
  17.  
  18. -- Gets a magnet located on <side> of turtle
  19. local function getMagnet(side)
  20. local name = peripheral.getType(side)
  21. if(not name:lower():find("magnet")) then
  22. print("No magnet attached to " .. side)
  23. return nil
  24. end
  25.  
  26. return peripheral.wrap(side)
  27. end
  28.  
  29. -- Determines if the block in front of a turtle is a chest
  30. local function isChest()
  31. local status, data = turtle.inspect()
  32.  
  33. if(not status) then
  34. print("No chest available")
  35. return false
  36. end
  37.  
  38. local itemName = data["name"]:match(":(.+)"):lower()
  39. for index, container in pairs(CONTAINER_SUBSTRINGS) do
  40. if(itemName:find(container)) then
  41. return true
  42. end
  43. end
  44.  
  45. return false
  46. end
  47.  
  48. -- Attempt to refuel the turtle
  49. local function attemptRefuel(amount)
  50. local amount = amount or 1
  51.  
  52. if(turtle.getFuelLevel() >= amount) then
  53. return
  54. end
  55.  
  56. local index = 1
  57. local hasRefueled = false
  58. while(index <= 16 and not hasRefueled) do
  59. turtle.select(index)
  60. local refuelling = true
  61. while(refuelling) do
  62. if(turtle.refuel(0)) then
  63. if(turtle.getFuelLevel() < amount) then
  64. turtle.refuel(1)
  65. else
  66. refuelling = false
  67. hasRefueled = true
  68. end
  69. else
  70. refuelling = false
  71. end
  72. end
  73. index = index + 1
  74. end
  75. end
  76.  
  77. -- Attempt to dump non-fuel items into a chest in front of the turtle
  78. local function attemptDumpInv()
  79. if(not isChest()) then
  80. return
  81. end
  82.  
  83. for index=1, 16 do
  84. turtle.select(index)
  85. if(not turtle.refuel(0)) then
  86. turtle.drop()
  87. end
  88. end
  89. end
  90.  
  91. -- Wraps magnet.setTarget to also keep a local target state
  92. local function setTargetWrapper(x, y, z)
  93. target = {["x"] = x, ["y"] = y, ["z"] = z}
  94. magnet.setTarget(x, y, z)
  95. end
  96.  
  97. -- Orbits the magnet around the turtle right or left in 90 deg turns
  98. local function orbitMagnet(direction)
  99. attemptRefuel(5)
  100.  
  101. local x = target["x"]
  102. local y = target["y"]
  103. local z = target["z"]
  104. local theta = 0
  105.  
  106. if(direction == "cw") then
  107. theta = -math.pi/2
  108. elseif(direction == "ccw") then
  109. theta = math.pi/2
  110. else
  111. print("Direction: " .. direction .. " not a valid magnet orbit")
  112. return false
  113. end
  114.  
  115. -- TODO split this out into own function
  116. if(squareType == DOWN_SQUARE) then
  117. if(height >= 2) then
  118. y = 0 -- Drop magnet one block so it doesn't get hit
  119. end
  120. else
  121. if(height <= 2) then
  122. y = 1 -- Raise magnet one block
  123. end
  124. end
  125.  
  126. local x_ = round(z * math.cos(theta) + z * -math.sin(theta))
  127. local z_ = round(x * math.sin(theta) + x * math.cos(theta))
  128.  
  129. print(x, " ", y, " ", z, "\t->", x_, " ", y, " ", z_)
  130. setTargetWrapper(x_, y, z_)
  131. end
  132.  
  133. -- Turns in a direction one or more times, also tries to keep magnet in same orientation. Assumes magnet is behind turtle
  134. local function turn(direction, turns)
  135. local turns = tonumber(distance) or 1
  136.  
  137. if(direction == "right") then
  138. turtle.turnRight()
  139. if(magnet) then
  140. orbitMagnet("ccw")
  141. end
  142. elseif(direction == "left") then
  143. turtle.turnLeft()
  144. if(magnet) then
  145. orbitMagnet("cw")
  146. end
  147. else
  148. print("Direction: " .. direction .. " not a valid rotation")
  149. return false
  150. end
  151.  
  152. if(turns > 1) then
  153. turn(direction, turns - 1, magnetAttached)
  154. end
  155.  
  156. os.sleep(5) -- sleep to let magnet catch up
  157. return true
  158. end
  159.  
  160. -- Move in a direction 1 or more times
  161. local function move(direction, distance)
  162. local distance = tonumber(distance) or 1
  163. attemptRefuel()
  164.  
  165. if(direction == "up") then
  166. turtle.up()
  167. height = height + 1
  168. elseif(direction == "down") then
  169. turtle.down()
  170. height = height - 1
  171. elseif(direction == "forward") then
  172. turtle.forward()
  173. elseif(direction == "back") then
  174. turtle.back()
  175. else
  176. print("Direction: " .. direction .. " not a valid movement")
  177. return false
  178. end
  179.  
  180. if(distance > 1) then
  181. move(direction, distance - 1)
  182. end
  183. return true
  184. end
  185.  
  186. -- Dig out a block and move into it
  187. local function digMove(direction)
  188. if(direction == "up") then
  189. turtle.digUp()
  190. move("up")
  191. elseif(direction == "down") then
  192. turtle.digDown()
  193. move("down")
  194. elseif(direction == "forward") then
  195. turtle.dig()
  196. move("forward")
  197. elseif(direction == "back") then
  198. turn("left", 2)
  199. turtle.dig()
  200. turn("left", 2)
  201. move("back")
  202. else
  203. print("Direction: " .. direction .. " not a valid movement")
  204. return false
  205. end
  206. return true
  207. end
  208.  
  209. -- Dig out a 3x3 vertical square
  210. local function tunnelSquare()
  211. -- Dig out adjacent left and right blocks
  212. local function tunnelAdjacentLR()
  213. turn("left")
  214. turtle.dig()
  215. turn("left", 2)
  216. turtle.dig()
  217. turn("left")
  218. end
  219.  
  220. digMove("forward") -- Move into next vertical square
  221. for i=1, SQUARE_SIZE do
  222. tunnelAdjacentLR()
  223. if(i < 3) then
  224. if(DOWN_SQUARE == squareType) then
  225. digMove("up")
  226. else
  227. digMove("down")
  228. end
  229. end
  230. end
  231.  
  232. if(DOWN_SQUARE == squareType) then
  233. squareType = UP_SQUARE
  234. else
  235. squareType = DOWN_SQUARE
  236. end
  237. end
  238.  
  239. -- Tunnel
  240. local function tunnel(distance, tunnelFunc)
  241. -- Don't bother with tunnelling negative distances
  242. if(distance < 1) then
  243. return
  244. end
  245.  
  246. -- Default to tunnelSquare
  247. local tunnelFunc = tunnelFunc or tunnelSquare
  248.  
  249. -- Tunnel over a distance using specified tunneling function
  250. for i=1, distance do
  251. tunnelFunc()
  252. end
  253. end
  254.  
  255. -- Display usage info
  256. local function help()
  257. local name = "<name>"
  258. if(shell) then
  259. name = shell.getRunningProgram()
  260. end
  261.  
  262. print("Usage: " .. name .. " <distance to tunnel >= 3> [shaft center spacing (- left, + right)]\nAlso, if a chest is placed to the turtle's right it'll dump non-fuel items into that")
  263. end
  264.  
  265. -- Main
  266. local function main(distance, spacing, magnetSide)
  267. -- Handle args
  268. local distance = tonumber(distance) or 0
  269. local spacing = tonumber(spacing) or 0
  270. local magnetSide = magnetSide or "left"
  271.  
  272. if(distance < 3) then
  273. -- Small distances cause inaccuracies
  274. help()
  275. return
  276. end
  277.  
  278. -- Init the magnet and get the anchor
  279. attemptRefuel(5)
  280. magnet = getMagnet(magnetSide)
  281. magnet.activate()
  282. setTargetWrapper(-1, 1, 0)
  283. os.sleep(2)
  284. magnet.toggle()
  285.  
  286. -- Initial tunneling distance
  287. tunnel(distance)
  288.  
  289. magnet.toggle()
  290. magnet.deactivate()
  291.  
  292. -- Tunnel over to return shaft
  293. move("back")
  294. if(spacing > 0) then
  295. turn("right")
  296. move("forward")
  297. tunnel(spacing)
  298. move("back")
  299. turn("right")
  300. elseif(spacing < 0) then
  301. turn("left")
  302. move("forward")
  303. tunnel(spacing * -1)
  304. move("back")
  305. turn("left")
  306. else
  307. turn("left", 2)
  308. end
  309.  
  310. -- Move to edge of return shaft
  311. move("forward")
  312.  
  313. -- Tunnel/move back to start
  314. if(spacing == 0) then
  315. move("forward", distance - 2)
  316. else
  317. tunnel(distance - 3)
  318. move("forward")
  319. end
  320.  
  321. if(UP_SQUARE == squareType) then
  322. move("down", 2)
  323. end
  324.  
  325. -- Spin back around, dump non-fuel into adjacent chest
  326. turn("left")
  327. attemptDumpInv()
  328. turn("left")
  329. end
  330.  
  331. main(unpack({...}))
Advertisement
Add Comment
Please, Sign In to add comment