druidbruce

charge station quarry

Jun 5th, 2013
188
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 62.22 KB | None | 0 0
  1. -- ********************************************************************************** --
  2. -- ** ** --
  3. -- ** Minecraft Mining Turtle Ore Quarry v0.7 by AustinKK ** --
  4. -- ** --------------------------------------------------- ** --
  5. -- ** ** --
  6. -- ** For instructions on how to use: ** --
  7. -- ** ** --
  8. -- ** http://www.youtube.com/watch?v=PIugLVzUz3g ** --
  9. -- ** ** --
  10. -- ** Change Log: ** --
  11. -- ** 27th Dec 2012: [v0.2] Initial Draft Release ** --
  12. -- ** 29th Dec 2012: [v0.3] Minor Performance Improvements ** --
  13. -- ** 30th Dec 2012: [v0.4] Further Performance Improvements ** --
  14. -- ** 9th Jan 2013: [v0.5] Debug Version (dropping off chest) ** --
  15. -- ** 10th Jan 2013: [v0.51] Further Debug (dropping off chest) ** --
  16. -- ** 10th Jan 2013: [v0.52] Fix for dropping off chest bug ** --
  17. -- ** 11th Jan 2013: [v0.53] Fix for dropping off chest bug (release) ** --
  18. -- ** 12th Jan 2013: [v0.6] Added support for resume ** --
  19. -- ** 31st Mar 2013: [v0.7] Fixes for ComputerCraft v1.52 ** --
  20. -- ** ** --
  21. -- ********************************************************************************** --
  22.  
  23. -- Enumeration to store the the different types of message that can be written
  24. messageLevel = { DEBUG=0, INFO=1, WARNING=2, ERROR=3, FATAL=4 }
  25.  
  26. -- Enumeration to store names for the 6 directions
  27. direction = { FORWARD=0, RIGHT=1, BACK=2, LEFT=3, UP=4, DOWN=5 }
  28.  
  29. -- Enumeration of mining states
  30. miningState = { START=0, LAYER=1, EMPTYCHESTDOWN=2, EMPTYINVENTORY=3 }
  31.  
  32. local messageOutputLevel = messageLevel.INFO
  33. local messageOutputFileName
  34. local fuelLevelToRefuelAt = 50
  35. local refuelItemsToUseWhenRefuelling = 63
  36. local emergencyFuelToRetain = 0
  37. local maximumGravelStackSupported = 25 -- The number of stacked gravel or sand blocks supported
  38. local noiseBlocksCount
  39. local bottomLayer = 5 -- The y co-ords of the layer immediately above bedrock
  40. local returningToStart = false
  41. local lookForChests = false -- Determines if chests should be located as part of the quarrying
  42. local miningOffset -- The offset to the mining layer. This is set depending on whether chests are being looked for or not
  43. local lastEmptySlot -- The last inventory slot that was empty when the program started (is either 15 if not looking for chests or 14 if we are)
  44. local turtleId
  45. local isWirelessTurtle
  46. local currentlySelectedSlot = 0 -- The slot that the last noise block was found in
  47. local lastMoveNeededDig = true -- Determines whether the last move needed a dig first
  48. local haveBeenAtZeroZeroOnLayer -- Determines whether the turtle has been at (0, 0) in this mining layer
  49. local orientationAtZeroZero -- The turtle's orientation when it was at (0, 0)
  50. local levelToReturnTo -- The level that the turtle should return to in order to head back to the start to unload
  51.  
  52. -- Variables used to support a resume
  53. local startupParamsFile = "OreQuarryParams.txt"
  54. local oreQuarryLocation = "OreQuarryLocation.txt"
  55. local returnToStartFile = "OreQuarryReturn.txt"
  56. local startupBackup = "startup_bak"
  57. local supportResume = true -- Determines whether the turtle is being run in the mode that supports resume
  58. local resuming = false -- Determines whether the turtle is currently in the process of resuming
  59. local resumeX
  60. local resumeY
  61. local resumeZ
  62. local resumeOrient
  63. local resumeMiningState
  64.  
  65. -- Variables to store the current location and orientation of the turtle. x is right, left, y is up, down and
  66. -- z is forward, back with relation to the starting orientation. Y is the actual turtle level, x and z are
  67. -- in relation to the starting point (i.e. the starting point is (0, 0))
  68. local currX
  69. local currY
  70. local currZ
  71. local currOrient
  72. local currMiningState = miningState.START
  73.  
  74. -- Command line parameters
  75. local startHeight -- Represents the height (y co-ord) that the turtle started at
  76. local quarryWidth -- Represents the length of the mines that the turtle will dig
  77.  
  78. -- ********************************************************************************** --
  79. -- Writes an output message
  80. -- ********************************************************************************** --
  81. function writeMessage(message, msgLevel)
  82. if (msgLevel >= messageOutputLevel) then
  83. print(message)
  84.  
  85. -- If this turtle has a modem, then write the message to red net
  86. if (isWirelessTurtle == true) then
  87. if (turtleId == nil) then
  88. rednet.broadcast(message)
  89. else
  90. -- Broadcast the message (prefixed with the turtle's id)
  91. rednet.broadcast("[".. turtleId.."] "..message)
  92. end
  93. end
  94.  
  95. if (messageOutputFileName ~= nil) then
  96. -- Open file, write message and close file (flush doesn't seem to work!)
  97. local outputFile = io.open(messageOutputFileName, "a")
  98. outputFile:write(message)
  99. outputFile:write("\n")
  100. outputFile:close()
  101. end
  102. end
  103. end
  104.  
  105. -- ********************************************************************************** --
  106. -- Ensures that the turtle has fuel
  107. -- ********************************************************************************** --
  108. function ensureFuel()
  109.  
  110. -- Determine whether a refuel is required
  111. local fuelLevel = turtle.getFuelLevel()
  112. if (fuelLevel ~= "unlimited") then
  113. if (fuelLevel < fuelLevelToRefuelAt) then
  114. -- Need to refuel
  115. while (turtle.getFuelLevel()<6000) do
  116. returnToStartAndUnload(false)
  117. sleep(10)
  118. print(turtle.getFuelLevel())
  119.  
  120. end
  121. returnToStartAndUnload(true)
  122. end
  123. end
  124. end
  125.  
  126. -- ********************************************************************************** --
  127. -- Checks that the turtle has inventory space by checking for spare slots and returning
  128. -- to the starting point to empty out if it doesn't.
  129. --
  130. -- Takes the position required to move to in order to empty the turtle's inventory
  131. -- should it be full as arguments
  132. -- ********************************************************************************** --
  133. function ensureInventorySpace()
  134.  
  135. -- If already returning to start, then don't need to do anything
  136. if (returningToStart == false) then
  137.  
  138. -- If the last inventory slot is full, then need to return to the start and empty
  139. if (turtle.getItemCount(lastEmptySlot) > 0) then
  140.  
  141. -- Return to the starting point and empty the inventory, then go back to mining
  142. returnToStartAndUnload(true)
  143. end
  144. end
  145. end
  146.  
  147. -- ********************************************************************************** --
  148. -- Function to move to the starting point, call a function that is passed in
  149. -- and return to the same location (if required)
  150. -- ********************************************************************************** --
  151. function returnToStartAndUnload(returnBackToMiningPoint)
  152.  
  153. writeMessage("returnToStartAndUnload called", messageLevel.DEBUG)
  154. returningToStart = true
  155. local storedX, storedY, storedZ, storedOrient
  156. local prevMiningState = currMiningState
  157.  
  158. if (resuming == true) then
  159. -- Get the stored parameters from the necessary file
  160. local resumeFile = fs.open(returnToStartFile, "r")
  161. if (resumeFile ~= nil) then
  162. -- Restore the parameters from the file
  163. local beenAtZero = resumeFile.readLine()
  164. if (beenAtZero == "y") then
  165. haveBeenAtZeroZeroOnLayer = true
  166. else
  167. haveBeenAtZeroZeroOnLayer = false
  168. end
  169.  
  170. local miningPointFlag = resumeFile.readLine()
  171. if (miningPointFlag == "y") then
  172. returnBackToMiningPoint = true
  173. else
  174. returnBackToMiningPoint = false
  175. end
  176.  
  177. currX = readNumber(resumeFile)
  178. currY = readNumber(resumeFile)
  179. currZ = readNumber(resumeFile)
  180. currOrient = readNumber(resumeFile)
  181. levelToReturnTo = readNumber(resumeFile)
  182. prevMiningState = readNumber(resumeFile)
  183. orientationAtZeroZero = readNumber(resumeFile)
  184. resumeFile.close()
  185.  
  186. else
  187. writeMessage("Failed to read return to start file", messageLevel.ERROR)
  188. end
  189. elseif (supportResume == true) then
  190.  
  191. local outputFile = io.open(returnToStartFile, "w")
  192.  
  193. if (haveBeenAtZeroZeroOnLayer == true) then
  194. outputFile:write("y\n")
  195. else
  196. outputFile:write("n\n")
  197. end
  198. if (returnBackToMiningPoint == true) then
  199. outputFile:write("y\n")
  200. else
  201. outputFile:write("n\n")
  202. end
  203.  
  204. outputFile:write(currX)
  205. outputFile:write("\n")
  206. outputFile:write(currY)
  207. outputFile:write("\n")
  208. outputFile:write(currZ)
  209. outputFile:write("\n")
  210. outputFile:write(currOrient)
  211. outputFile:write("\n")
  212. outputFile:write(levelToReturnTo)
  213. outputFile:write("\n")
  214. outputFile:write(prevMiningState)
  215. outputFile:write("\n")
  216. outputFile:write(orientationAtZeroZero)
  217. outputFile:write("\n")
  218.  
  219. outputFile:close()
  220. end
  221.  
  222. storedX = currX
  223. storedY = currY
  224. storedZ = currZ
  225. storedOrient = currOrient
  226.  
  227. -- Store the current location and orientation so that it can be returned to
  228. currMiningState = miningState.EMPTYINVENTORY
  229. writeMessage("last item count = "..turtle.getItemCount(lastEmptySlot), messageLevel.DEBUG)
  230.  
  231. if ((turtle.getItemCount(lastEmptySlot) > 0) or (returnBackToMiningPoint == false)) then
  232.  
  233. writeMessage("Heading back to surface", messageLevel.DEBUG)
  234.  
  235. -- Move down to the correct layer to return via
  236. if (currY > levelToReturnTo) then
  237. while (currY > levelToReturnTo) do
  238. turtleDown()
  239. end
  240. elseif (currY < levelToReturnTo) then
  241. while (currY < levelToReturnTo) do
  242. turtleUp()
  243. end
  244. end
  245.  
  246. if ((haveBeenAtZeroZeroOnLayer == false) or (orientationAtZeroZero == direction.FORWARD)) then
  247. -- Move back to the correct X position first
  248. if (currX > 0) then
  249. turtleSetOrientation(direction.LEFT)
  250. while (currX > 0) do
  251. turtleForward()
  252. end
  253. elseif (currX < 0) then
  254. -- This should never happen
  255. writeMessage("Current x is less than 0 in returnToStartAndUnload", messageLevel.ERROR)
  256. end
  257.  
  258. -- Then move back to the correct Z position
  259. if (currZ > 0) then
  260. turtleSetOrientation(direction.BACK)
  261. while (currZ > 0) do
  262. turtleForward()
  263. end
  264. elseif (currZ < 0) then
  265. -- This should never happen
  266. writeMessage("Current z is less than 0 in returnToStartAndUnload", messageLevel.ERROR)
  267. end
  268. else
  269. -- Move back to the correct Z position first
  270. if (currZ > 0) then
  271. turtleSetOrientation(direction.BACK)
  272. while (currZ > 0) do
  273. turtleForward()
  274. end
  275. elseif (currZ < 0) then
  276. -- This should never happen
  277. writeMessage("Current z is less than 0 in returnToStartAndUnload", messageLevel.ERROR)
  278. end
  279.  
  280. -- Then move back to the correct X position
  281. if (currX > 0) then
  282. turtleSetOrientation(direction.LEFT)
  283. while (currX > 0) do
  284. turtleForward()
  285. end
  286. elseif (currX < 0) then
  287. -- This should never happen
  288. writeMessage("Current x is less than 0 in returnToStartAndUnload", messageLevel.ERROR)
  289. end
  290. end
  291.  
  292. -- Return to the starting layer
  293. if (currY < startHeight) then
  294. while (currY < startHeight) do
  295. turtleUp()
  296. end
  297. elseif (currY > startHeight) then
  298. -- This should never happen
  299. writeMessage("Current height is greater than start height in returnToStartAndUnload", messageLevel.ERROR)
  300. end
  301.  
  302. -- Empty the inventory
  303. local slotLoop = 1
  304.  
  305. -- Face the chest
  306. turtleSetOrientation(direction.BACK)
  307.  
  308. -- Loop over each of the slots (except the 16th one which stores fuel)
  309. while (slotLoop < 16) do
  310. -- If this is one of the slots that contains a noise block, empty all blocks except
  311. -- one
  312. turtle.select(slotLoop) -- Don't bother updating selected slot variable as it will set later in this function
  313. if ((slotLoop <= noiseBlocksCount) or ((slotLoop == 15) and (lastEmptySlot == 14))) then
  314. writeMessage("Dropping (n-1) from slot "..slotLoop.." ["..turtle.getItemCount(slotLoop).."]", messageLevel.DEBUG)
  315. if (turtle.getItemCount(slotLoop) > 0) then
  316. turtle.drop(turtle.getItemCount(slotLoop) - 1)
  317. end
  318. else
  319. -- Not a noise block, drop all of the items in this slot
  320. writeMessage("Dropping (all) from slot "..slotLoop.." ["..turtle.getItemCount(slotLoop).."]", messageLevel.DEBUG)
  321. if (turtle.getItemCount(slotLoop) > 0) then
  322. turtle.drop()
  323. end
  324. end
  325.  
  326. slotLoop = slotLoop + 1
  327. end
  328.  
  329. -- While we are here, refill the fuel items if there is capacity
  330. if (turtle.getItemCount(16) < 64) then
  331. turtleSetOrientation(direction.LEFT)
  332. turtle.select(16) -- Don't bother updating selected slot variable as it will set later in this function
  333. local currFuelItems = turtle.getItemCount(16)
  334. turtle.suck()
  335. while ((currFuelItems ~= turtle.getItemCount(16)) and (turtle.getItemCount(16) < 64)) do
  336. currFuelItems = turtle.getItemCount(16)
  337. turtle.suck()
  338. end
  339.  
  340. slotLoop = noiseBlocksCount + 1
  341. -- Have now picked up all the items that we can. If we have also picked up some
  342. -- additional fuel in some of the other slots, then drop it again
  343. while (slotLoop <= lastEmptySlot) do
  344. -- Drop any items found in this slot
  345. if (turtle.getItemCount(slotLoop) > 0) then
  346. turtle.select(slotLoop) -- Don't bother updating selected slot variable as it will set later in this function
  347. turtle.drop()
  348. end
  349. slotLoop = slotLoop + 1
  350. end
  351. end
  352.  
  353. -- Select the 1st slot because sometimes when leaving the 15th or 16th slots selected it can result
  354. -- in that slot being immediately filled (resulting in the turtle returning to base again too soon)
  355. turtle.select(1)
  356. currentlySelectedSlot = 1
  357. end
  358.  
  359. -- If required, move back to the point that we were mining at before returning to the start
  360. if (returnBackToMiningPoint == true) then
  361.  
  362. -- If resuming, refresh the starting point to be the top of the return shaft
  363. if (resuming == true) then
  364. currX = 0
  365. currY = startHeight
  366. currZ = 0
  367. currOrient = resumeOrient
  368. end
  369.  
  370. -- Return back to the required layer
  371. while (currY > levelToReturnTo) do
  372. turtleDown()
  373. end
  374.  
  375. if ((haveBeenAtZeroZeroOnLayer == false) or (orientationAtZeroZero == direction.FORWARD)) then
  376. -- Move back to the correct Z position first
  377. writeMessage("Stored Z: "..storedZ..", currZ: "..currZ, messageLevel.DEBUG)
  378. if (storedZ > currZ) then
  379. writeMessage("Orienting forward", messageLevel.DEBUG)
  380. writeMessage("Moving in z direction", messageLevel.DEBUG)
  381. turtleSetOrientation(direction.FORWARD)
  382. while (storedZ > currZ) do
  383. turtleForward()
  384. end
  385. elseif (storedZ < currZ) then
  386. -- This should never happen
  387. writeMessage("Stored z is less than current z in returnToStartAndUnload", messageLevel.ERROR)
  388. end
  389.  
  390. -- Then move back to the correct X position
  391. if (storedX > currX) then
  392. writeMessage("Stored X: "..storedX..", currX: "..currX, messageLevel.DEBUG)
  393. writeMessage("Orienting right", messageLevel.DEBUG)
  394. writeMessage("Moving in x direction", messageLevel.DEBUG)
  395. turtleSetOrientation(direction.RIGHT)
  396. while (storedX > currX) do
  397. turtleForward()
  398. end
  399. elseif (storedX < currX) then
  400. -- This should never happen
  401. writeMessage("Stored x is less than current x in returnToStartAndUnload", messageLevel.ERROR)
  402. end
  403. else
  404. -- Move back to the correct X position first
  405. if (storedX > currX) then
  406. writeMessage("Stored X: "..storedX..", currX: "..currX, messageLevel.DEBUG)
  407. writeMessage("Orienting right", messageLevel.DEBUG)
  408. writeMessage("Moving in x direction", messageLevel.DEBUG)
  409. turtleSetOrientation(direction.RIGHT)
  410. while (storedX > currX) do
  411. turtleForward()
  412. end
  413. elseif (storedX < currX) then
  414. -- This should never happen
  415. writeMessage("Stored x is less than current x in returnToStartAndUnload", messageLevel.ERROR)
  416. end
  417.  
  418. -- Then move back to the correct Z position
  419. writeMessage("Stored Z: "..storedZ..", currZ: "..currZ, messageLevel.DEBUG)
  420. if (storedZ > currZ) then
  421. writeMessage("Orienting forward", messageLevel.DEBUG)
  422. writeMessage("Moving in z direction", messageLevel.DEBUG)
  423. turtleSetOrientation(direction.FORWARD)
  424. while (storedZ > currZ) do
  425. turtleForward()
  426. end
  427. elseif (storedZ < currZ) then
  428. -- This should never happen
  429. writeMessage("Stored z is less than current z in returnToStartAndUnload", messageLevel.ERROR)
  430. end
  431. end
  432.  
  433. -- Move back to the correct layer
  434. if (storedY < currY) then
  435. while (storedY < currY) do
  436. turtleDown()
  437. end
  438. elseif (storedY > currY) then
  439. while (storedY > currY) do
  440. turtleUp()
  441. end
  442. end
  443.  
  444. -- Finally, set the correct orientation
  445. turtleSetOrientation(storedOrient)
  446.  
  447. writeMessage("Have returned to the mining point", messageLevel.DEBUG)
  448. end
  449.  
  450. -- Store the current location and orientation so that it can be returned to
  451. currMiningState = prevMiningState
  452.  
  453. returningToStart = false
  454.  
  455. end
  456.  
  457. -- ********************************************************************************** --
  458. -- Empties a chest's contents
  459. -- ********************************************************************************** --
  460. function emptyChest(suckFn)
  461.  
  462. local prevInventoryCount = {}
  463. local inventoryLoop
  464. local chestEmptied = false
  465.  
  466. -- Record the number of items in each of the inventory slots
  467. for inventoryLoop = 1, 16 do
  468. prevInventoryCount[inventoryLoop] = turtle.getItemCount(inventoryLoop)
  469. end
  470.  
  471. while (chestEmptied == false) do
  472. -- Pick up the next item
  473. suckFn()
  474.  
  475. -- Determine the number of items in each of the inventory slots now
  476. local newInventoryCount = {}
  477. for inventoryLoop = 1, 16 do
  478. newInventoryCount[inventoryLoop] = turtle.getItemCount(inventoryLoop)
  479. end
  480.  
  481. -- Now, determine whether there have been any items taken from the chest
  482. local foundDifferentItemCount = false
  483. inventoryLoop = 1
  484. while ((foundDifferentItemCount == false) and (inventoryLoop <= 16)) do
  485. if (prevInventoryCount[inventoryLoop] ~= newInventoryCount[inventoryLoop]) then
  486. foundDifferentItemCount = true
  487. else
  488. inventoryLoop = inventoryLoop + 1
  489. end
  490. end
  491.  
  492. -- If no items have been found with a different item count, then the chest has been emptied
  493. chestEmptied = not foundDifferentItemCount
  494.  
  495. if (chestEmptied == false) then
  496. prevInventoryCount = newInventoryCount
  497. -- Check that there is sufficient inventory space as may have picked up a block
  498. ensureInventorySpace()
  499. end
  500. end
  501.  
  502. writeMessage("Finished emptying chest", messageLevel.DEBUG)
  503. end
  504.  
  505. -- ********************************************************************************** --
  506. -- Write the current location to a file
  507. -- ********************************************************************************** --
  508. function saveLocation()
  509.  
  510. -- Write the x, y, z and orientation to the file
  511. if ((supportResume == true) and (resuming == false)) then
  512. local outputFile = io.open(oreQuarryLocation, "w")
  513. outputFile:write(currMiningState)
  514. outputFile:write("\n")
  515. outputFile:write(currX)
  516. outputFile:write("\n")
  517. outputFile:write(currY)
  518. outputFile:write("\n")
  519. outputFile:write(currZ)
  520. outputFile:write("\n")
  521. outputFile:write(currOrient)
  522. outputFile:write("\n")
  523. outputFile:close()
  524. end
  525.  
  526. end
  527.  
  528. -- ********************************************************************************** --
  529. -- If the turtle is resuming and the current co-ordinates, orientation and
  530. -- mining state have been matched, then no longer resuming
  531. -- ********************************************************************************** --
  532. function updateResumingFlag()
  533.  
  534. if (resuming == true) then
  535. if ((resumeMiningState == currMiningState) and (resumeX == currX) and (resumeY == currY) and (resumeZ == currZ) and (resumeOrient == currOrient)) then
  536. resuming = false
  537. end
  538. end
  539.  
  540. end
  541.  
  542. -- ********************************************************************************** --
  543. -- Generic function to move the Turtle (pushing through any gravel or other
  544. -- things such as mobs that might get in the way).
  545. --
  546. -- The only thing that should stop the turtle moving is bedrock. Where this is
  547. -- found, the function will return after 15 seconds returning false
  548. -- ********************************************************************************** --
  549. function moveTurtle(moveFn, detectFn, digFn, attackFn, compareFn, suckFn, maxDigCount, newX, newY, newZ)
  550.  
  551. local moveSuccess = false
  552.  
  553. -- If we are resuming, then don't do anything in this function other than updating the
  554. -- co-ordinates as if the turtle had moved
  555. if (resuming == true) then
  556. -- Set the move success to true (but don't move) - unless this is below bedrock level
  557. -- in which case return false
  558. if (currY <= 0) then
  559. moveSuccess = false
  560. else
  561. moveSuccess = true
  562. end
  563.  
  564. -- Update the co-ordinates to reflect the movement
  565. currX = newX
  566. currY = newY
  567. currZ = newZ
  568.  
  569. else
  570. local prevX, prevY, prevZ
  571. prevX = currX
  572. prevY = currY
  573. prevZ = currZ
  574.  
  575. ensureFuel()
  576.  
  577. -- Flag to determine whether digging has been tried yet. If it has
  578. -- then pause briefly before digging again to allow sand or gravel to
  579. -- drop
  580. local digCount = 0
  581.  
  582. if (lastMoveNeededDig == false) then
  583. -- Didn't need to dig last time the turtle moved, so try moving first
  584.  
  585. currX = newX
  586. currY = newY
  587. currZ = newZ
  588. saveLocation()
  589.  
  590. moveSuccess = moveFn()
  591.  
  592. -- If move failed, update the co-ords back to the previous co-ords
  593. if (moveSuccess == false) then
  594. currX = prevX
  595. currY = prevY
  596. currZ = prevZ
  597. saveLocation()
  598. end
  599.  
  600. -- Don't need to set the last move needed dig. It is already false, if
  601. -- move success is now true, then it won't be changed
  602. else
  603. -- If we are looking for chests, then check that this isn't a chest before trying to dig it
  604. if (lookForChests == true) then
  605. if (isNoiseBlock(compareFn) == false) then
  606. if (detectFn() == true) then
  607. -- Determine if it is a chest before digging it
  608. if (isChestBlock(compareFn) == true) then
  609. -- Have found a chest, empty it before continuing
  610. emptyChest (suckFn)
  611. end
  612. end
  613. end
  614. end
  615.  
  616. -- Try to dig (without doing a detect as it is quicker)
  617. local digSuccess = digFn()
  618. if (digSuccess == true) then
  619. digCount = 1
  620. end
  621.  
  622. currX = newX
  623. currY = newY
  624. currZ = newZ
  625. saveLocation()
  626.  
  627. moveSuccess = moveFn()
  628.  
  629. if (moveSuccess == true) then
  630. lastMoveNeededDig = digSuccess
  631. else
  632. currX = prevX
  633. currY = prevY
  634. currZ = prevZ
  635. saveLocation()
  636. end
  637.  
  638. end
  639.  
  640. -- Loop until we've successfully moved
  641. if (moveSuccess == false) then
  642. while ((moveSuccess == false) and (digCount < maxDigCount)) do
  643.  
  644. -- If there is a block in front, dig it
  645. if (detectFn() == true) then
  646.  
  647. -- If we've already tried digging, then pause before digging again to let
  648. -- any sand or gravel drop, otherwise check for a chest before digging
  649. if(digCount == 0) then
  650. -- Am about to dig a block - check that it is not a chest if necessary
  651. -- If we are looking for chests, then check that this isn't a chest before moving
  652. if (lookForChests == true) then
  653. if (isNoiseBlock(compareFn) == false) then
  654. if (detectFn() == true) then
  655. -- Determine if it is a chest before digging it
  656. if (isChestBlock(compareFn) == true) then
  657. -- Have found a chest, empty it before continuing
  658. emptyChest (suckFn)
  659. end
  660. end
  661. end
  662. end
  663. else
  664. sleep(0.1)
  665. end
  666.  
  667. digFn()
  668. digCount = digCount + 1
  669. else
  670. -- Am being stopped from moving by a mob, attack it
  671. attackFn()
  672. end
  673.  
  674. currX = newX
  675. currY = newY
  676. currZ = newZ
  677. saveLocation()
  678.  
  679. -- Try the move again
  680. moveSuccess = moveFn()
  681.  
  682. if (moveSuccess == false) then
  683. currX = prevX
  684. currY = prevY
  685. currZ = prevZ
  686. saveLocation()
  687. end
  688. end
  689.  
  690. if (digCount == 0) then
  691. lastMoveNeededDig = false
  692. else
  693. lastMoveNeededDig = true
  694. end
  695. end
  696. end
  697.  
  698. -- If we are resuming and the current co-ordinates and orientation are the resume point
  699. -- then are no longer resuming
  700. if (moveSuccess == true) then
  701. updateResumingFlag()
  702. end
  703.  
  704. -- Return the move success
  705. return moveSuccess
  706.  
  707. end
  708.  
  709. -- ********************************************************************************** --
  710. -- Move the turtle forward one block (updating the turtle's position)
  711. -- ********************************************************************************** --
  712. function turtleForward()
  713.  
  714. -- Determine the new co-ordinate that the turtle will be moving to
  715. local newX, newZ
  716.  
  717. -- Update the current co-ordinates
  718. if (currOrient == direction.FORWARD) then
  719. newZ = currZ + 1
  720. newX = currX
  721. elseif (currOrient == direction.LEFT) then
  722. newX = currX - 1
  723. newZ = currZ
  724. elseif (currOrient == direction.BACK) then
  725. newZ = currZ - 1
  726. newX = currX
  727. elseif (currOrient == direction.RIGHT) then
  728. newX = currX + 1
  729. newZ = currZ
  730. else
  731. writeMessage ("Invalid currOrient in turtleForward function", messageLevel.ERROR)
  732. end
  733.  
  734. local returnVal = moveTurtle(turtle.forward, turtle.detect, turtle.dig, turtle.attack, turtle.compare, turtle.suck, maximumGravelStackSupported, newX, currY, newZ)
  735.  
  736. if (returnVal == true) then
  737. -- Check that there is sufficient inventory space as may have picked up a block
  738. ensureInventorySpace()
  739. end
  740.  
  741. return returnVal
  742. end
  743.  
  744. -- ********************************************************************************** --
  745. -- Move the turtle up one block (updating the turtle's position)
  746. -- ********************************************************************************** --
  747. function turtleUp()
  748.  
  749. local returnVal = moveTurtle(turtle.up, turtle.detectUp, turtle.digUp, turtle.attackUp, turtle.compareUp, turtle.suckUp, maximumGravelStackSupported, currX, currY + 1, currZ)
  750.  
  751. if (returnVal == true) then
  752. -- Check that there is sufficient inventory space as may have picked up a block
  753. ensureInventorySpace()
  754. end
  755.  
  756. return returnVal
  757. end
  758.  
  759. -- ********************************************************************************** --
  760. -- Move the turtle down one block (updating the turtle's position)
  761. -- ********************************************************************************** --
  762. function turtleDown()
  763.  
  764. local returnVal = moveTurtle(turtle.down, turtle.detectDown, turtle.digDown, turtle.attackDown, turtle.compareDown, turtle.suckDown, 1, currX, currY - 1, currZ)
  765.  
  766. if (returnVal == true) then
  767. -- Check that there is sufficient inventory space as may have picked up a block
  768. ensureInventorySpace()
  769. end
  770.  
  771. return returnVal
  772.  
  773. end
  774.  
  775. -- ********************************************************************************** --
  776. -- Move the turtle back one block (updating the turtle's position)
  777. -- ********************************************************************************** --
  778. function turtleBack()
  779.  
  780. -- Assume that the turtle will move, and switch the co-ords back if it doesn't
  781. -- (do this so that we can write the co-ords to a file before moving)
  782. local newX, newZ
  783. local prevX, prevZ
  784. prevX = currX
  785. prevZ = currZ
  786.  
  787. -- Update the current co-ordinates
  788. if (currOrient == direction.FORWARD) then
  789. newZ = currZ - 1
  790. newX = currX
  791. elseif (currOrient == direction.LEFT) then
  792. newX = currX + 1
  793. newZ = currZ
  794. elseif (currOrient == direction.BACK) then
  795. newZ = currZ + 1
  796. newX = currX
  797. elseif (currOrient == direction.RIGHT) then
  798. newX = currX - 1
  799. newZ = currZ
  800. else
  801. writeMessage ("Invalid currOrient in turtleBack function", messageLevel.ERROR)
  802. end
  803.  
  804. -- First try to move back using the standard function
  805.  
  806. currX = newX
  807. currZ = newZ
  808. saveLocation()
  809. local returnVal = turtle.back()
  810.  
  811. if (returnVal == false) then
  812. -- Didn't move. Reset the co-ordinates to the previous value
  813. currX = prevX
  814. currZ = prevZ
  815.  
  816. -- Reset the location back to the previous location (because the turn takes 0.8 of a second
  817. -- so could be stopped before getting to the forward function)
  818. saveLocation()
  819.  
  820. turtle.turnRight()
  821. turtle.turnRight()
  822.  
  823. -- Try to move by using the forward function (note, the orientation will be set as
  824. -- the same way as this function started because if the function stops, that is the
  825. -- direction that we want to consider the turtle to be pointing)
  826.  
  827. returnVal = moveTurtle(turtle.forward, turtle.detect, turtle.dig, turtle.attack, turtle.compare, turtle.suck, maximumGravelStackSupported, newX, currY, newZ)
  828.  
  829. turtle.turnRight()
  830. turtle.turnRight()
  831. end
  832.  
  833. if (returnVal == true) then
  834. -- Check that there is sufficient inventory space as may have picked up a block
  835. ensureInventorySpace()
  836. end
  837.  
  838. return returnVal
  839. end
  840.  
  841. -- ********************************************************************************** --
  842. -- Turns the turtle (updating the current orientation at the same time)
  843. -- ********************************************************************************** --
  844. function turtleTurn(turnDir)
  845.  
  846. if (turnDir == direction.LEFT) then
  847. if (currOrient == direction.FORWARD) then
  848. currOrient = direction.LEFT
  849. elseif (currOrient == direction.LEFT) then
  850. currOrient = direction.BACK
  851. elseif (currOrient == direction.BACK) then
  852. currOrient = direction.RIGHT
  853. elseif (currOrient == direction.RIGHT) then
  854. currOrient = direction.FORWARD
  855. else
  856. writeMessage ("Invalid currOrient in turtleTurn function", messageLevel.ERROR)
  857. end
  858.  
  859. -- If we are resuming, just check to see whether have reached the resume point, otherwise
  860. -- turn
  861. if (resuming == true) then
  862. updateResumingFlag()
  863. else
  864. -- Write the new orientation and turn
  865. saveLocation()
  866. turtle.turnLeft()
  867. end
  868.  
  869. elseif (turnDir == direction.RIGHT) then
  870. if (currOrient == direction.FORWARD) then
  871. currOrient = direction.RIGHT
  872. elseif (currOrient == direction.LEFT) then
  873. currOrient = direction.FORWARD
  874. elseif (currOrient == direction.BACK) then
  875. currOrient = direction.LEFT
  876. elseif (currOrient == direction.RIGHT) then
  877. currOrient = direction.BACK
  878. else
  879. writeMessage ("Invalid currOrient in turtleTurn function", messageLevel.ERROR)
  880. end
  881.  
  882. -- If we are resuming, just check to see whether have reached the resume point, otherwise
  883. -- turn
  884. if (resuming == true) then
  885. updateResumingFlag()
  886.  
  887. writeMessage("["..currMiningState..", "..currX..", "..currY..", "..currZ..", "..currOrient.."]", messageLevel.DEBUG)
  888. else
  889. -- Write the new orientation and turn
  890. saveLocation()
  891. turtle.turnRight()
  892. end
  893. else
  894. writeMessage ("Invalid turnDir in turtleTurn function", messageLevel.ERROR)
  895. end
  896. end
  897.  
  898. -- ********************************************************************************** --
  899. -- Sets the turtle to a specific orientation, irrespective of its current orientation
  900. -- ********************************************************************************** --
  901. function turtleSetOrientation(newOrient)
  902.  
  903. if (currOrient ~= newOrient) then
  904. if (currOrient == direction.FORWARD) then
  905. if (newOrient == direction.RIGHT) then
  906. currOrient = newOrient
  907.  
  908. -- If resuming, check whether the resume point has been reached, otherwise turn
  909. if (resuming == true) then
  910. updateResumingFlag()
  911. else
  912. -- Write the new orientation and turn
  913. saveLocation()
  914. turtle.turnRight()
  915. end
  916. elseif (newOrient == direction.BACK) then
  917. currOrient = newOrient
  918.  
  919. -- If resuming, check whether the resume point has been reached, otherwise turn
  920. if (resuming == true) then
  921. updateResumingFlag()
  922. else
  923. -- Write the new orientation and turn
  924. saveLocation()
  925. turtle.turnRight()
  926. turtle.turnRight()
  927. end
  928. elseif (newOrient == direction.LEFT) then
  929. currOrient = newOrient
  930.  
  931. -- If resuming, check whether the resume point has been reached, otherwise turn
  932. if (resuming == true) then
  933. updateResumingFlag()
  934. else
  935. -- Write the new orientation and turn
  936. saveLocation()
  937. turtle.turnLeft()
  938. end
  939. else
  940. writeMessage ("Invalid newOrient in turtleSetOrientation function", messageLevel.ERROR)
  941. end
  942. elseif (currOrient == direction.RIGHT) then
  943. if (newOrient == direction.BACK) then
  944. currOrient = newOrient
  945.  
  946. -- If resuming, check whether the resume point has been reached, otherwise turn
  947. if (resuming == true) then
  948. updateResumingFlag()
  949. else
  950. -- Write the new orientation and turn
  951. saveLocation()
  952. turtle.turnRight()
  953. end
  954. elseif (newOrient == direction.LEFT) then
  955. currOrient = newOrient
  956.  
  957. -- If resuming, check whether the resume point has been reached, otherwise turn
  958. if (resuming == true) then
  959. updateResumingFlag()
  960. else
  961. -- Write the new orientation and turn
  962. saveLocation()
  963. turtle.turnRight()
  964. turtle.turnRight()
  965. end
  966. elseif (newOrient == direction.FORWARD) then
  967. currOrient = newOrient
  968.  
  969. -- If resuming, check whether the resume point has been reached, otherwise turn
  970. if (resuming == true) then
  971. updateResumingFlag()
  972. else
  973. -- Write the new orientation and turn
  974. saveLocation()
  975. turtle.turnLeft()
  976. end
  977. else
  978. writeMessage ("Invalid newOrient in turtleSetOrientation function", messageLevel.ERROR)
  979. end
  980. elseif (currOrient == direction.BACK) then
  981. if (newOrient == direction.LEFT) then
  982. currOrient = newOrient
  983.  
  984. -- If resuming, check whether the resume point has been reached, otherwise turn
  985. if (resuming == true) then
  986. updateResumingFlag()
  987. else
  988. -- Write the new orientation and turn
  989. saveLocation()
  990. turtle.turnRight()
  991. end
  992. elseif (newOrient == direction.FORWARD) then
  993. currOrient = newOrient
  994.  
  995. -- If resuming, check whether the resume point has been reached, otherwise turn
  996. if (resuming == true) then
  997. updateResumingFlag()
  998. else
  999. -- Write the new orientation and turn
  1000. saveLocation()
  1001. turtle.turnRight()
  1002. turtle.turnRight()
  1003. end
  1004. elseif (newOrient == direction.RIGHT) then
  1005. currOrient = newOrient
  1006.  
  1007. -- If resuming, check whether the resume point has been reached, otherwise turn
  1008. if (resuming == true) then
  1009. updateResumingFlag()
  1010. else
  1011. -- Write the new orientation and turn
  1012. saveLocation()
  1013. turtle.turnLeft()
  1014. end
  1015. else
  1016. writeMessage ("Invalid newOrient in turtleSetOrientation function", messageLevel.ERROR)
  1017. end
  1018. elseif (currOrient == direction.LEFT) then
  1019. if (newOrient == direction.FORWARD) then
  1020. currOrient = newOrient
  1021.  
  1022. -- If resuming, check whether the resume point has been reached, otherwise turn
  1023. if (resuming == true) then
  1024. updateResumingFlag()
  1025. else
  1026. -- Write the new orientation and turn
  1027. saveLocation()
  1028. turtle.turnRight()
  1029. end
  1030. elseif (newOrient == direction.RIGHT) then
  1031. currOrient = newOrient
  1032.  
  1033. -- If resuming, check whether the resume point has been reached, otherwise turn
  1034. if (resuming == true) then
  1035. updateResumingFlag()
  1036. else
  1037. -- Write the new orientation and turn
  1038. saveLocation()
  1039. turtle.turnRight()
  1040. turtle.turnRight()
  1041. end
  1042. elseif (newOrient == direction.BACK) then
  1043. currOrient = newOrient
  1044.  
  1045. -- If resuming, check whether the resume point has been reached, otherwise turn
  1046. if (resuming == true) then
  1047. updateResumingFlag()
  1048. else
  1049. -- Write the new orientation and turn
  1050. saveLocation()
  1051. turtle.turnLeft()
  1052. end
  1053. else
  1054. writeMessage ("Invalid newOrient in turtleSetOrientation function", messageLevel.ERROR)
  1055. end
  1056. else
  1057. writeMessage ("Invalid currOrient in turtleTurn function", messageLevel.ERROR)
  1058. end
  1059. end
  1060. end
  1061.  
  1062. -- ********************************************************************************** --
  1063. -- Determines if a particular block is considered a noise block or not. A noise
  1064. -- block is one that is a standard block in the game (stone, dirt, gravel etc.) and
  1065. -- is one to ignore as not being an ore. Function works by comparing the block
  1066. -- in question against a set of blocks in the turtle's inventory which are known not to
  1067. -- be noise blocks. Param is the function to use to compare the block for a noise block
  1068. -- ********************************************************************************** --
  1069. function isNoiseBlock(compareFn)
  1070.  
  1071. -- Consider air to be a noise block
  1072. local returnVal = false
  1073.  
  1074. if (resuming == true) then
  1075. returnVal = true
  1076. else
  1077. local seamLoop = 1
  1078. local prevSelectedSlot
  1079.  
  1080. -- If the currently selected slot is a noise block, then compare against this first
  1081. -- so that the slot doesn't need to be selected again (there is a 0.05s cost to do
  1082. -- this even if it is the currently selected slot)
  1083. if (currentlySelectedSlot <= noiseBlocksCount) then
  1084. returnVal = compareFn()
  1085. end
  1086.  
  1087. if (returnVal == false) then
  1088. prevSelectedSlot = currentlySelectedSlot
  1089. while((returnVal == false) and (seamLoop <= noiseBlocksCount)) do
  1090. if (seamLoop ~= prevSelectedSlot) then
  1091. turtle.select(seamLoop)
  1092. currentlySelectedSlot = seamLoop
  1093. returnVal = compareFn()
  1094. end
  1095. seamLoop = seamLoop + 1
  1096. end
  1097. end
  1098. end
  1099.  
  1100. -- Return the calculated value
  1101. return returnVal
  1102.  
  1103. end
  1104.  
  1105. -- ********************************************************************************** --
  1106. -- Determines if a particular block is a chest. Returns false if it is not a chest
  1107. -- or chests are not being detected
  1108. -- ********************************************************************************** --
  1109. function isChestBlock(compareFn)
  1110.  
  1111. -- Check the block in the appropriate direction to see whether it is a chest. Only
  1112. -- do this if we are looking for chests
  1113. local returnVal = false
  1114. if (lookForChests == true) then
  1115. turtle.select(15)
  1116. currentlySelectedSlot = 15
  1117. returnVal = compareFn()
  1118. end
  1119.  
  1120. -- Return the calculated value
  1121. return returnVal
  1122.  
  1123. end
  1124.  
  1125. -- ********************************************************************************** --
  1126. -- Function to calculate the number of non seam blocks in the turtle's inventory. This
  1127. -- is all of the blocks at the start of the inventory (before the first empty slot is
  1128. -- found
  1129. -- ********************************************************************************** --
  1130. function determineNoiseBlocksCountCount()
  1131. -- Determine the location of the first empty inventory slot. All items before this represent
  1132. -- noise items.
  1133. local foundFirstBlankInventorySlot = false
  1134. noiseBlocksCount = 1
  1135. while ((noiseBlocksCount < 16) and (foundFirstBlankInventorySlot == false)) do
  1136. if (turtle.getItemCount(noiseBlocksCount) > 0) then
  1137. noiseBlocksCount = noiseBlocksCount + 1
  1138. else
  1139. foundFirstBlankInventorySlot = true
  1140. end
  1141. end
  1142. noiseBlocksCount = noiseBlocksCount - 1
  1143.  
  1144. -- Determine whether a chest was provided, and hence whether we should support
  1145. -- looking for chests
  1146. if (turtle.getItemCount(15) > 0) then
  1147. lookForChests = true
  1148. lastEmptySlot = 14
  1149. miningOffset = 0
  1150. writeMessage("Looking for chests...", messageLevel.DEBUG)
  1151. else
  1152. lastEmptySlot = 15
  1153. miningOffset = 1
  1154. writeMessage("Ignoring chests...", messageLevel.DEBUG)
  1155. end
  1156. end
  1157.  
  1158. -- ********************************************************************************** --
  1159. -- Creates a quarry mining out only ores and leaving behind any noise blocks
  1160. -- ********************************************************************************** --
  1161. function createQuarry()
  1162.  
  1163. -- Determine the top mining layer layer. The turtle mines in layers of 3, and the bottom layer
  1164. -- is the layer directly above bedrock.
  1165. --
  1166. -- The actual layer that the turtle operates in is the middle of these three layers,
  1167. -- so determine the top layer
  1168. local topMiningLayer = startHeight + ((bottomLayer - startHeight - 2) % 3) - 1 + miningOffset
  1169.  
  1170. -- If the top layer is up, then ignore it and move to the next layer
  1171. if (topMiningLayer > currY) then
  1172. topMiningLayer = topMiningLayer - 3
  1173. end
  1174.  
  1175. local startedLayerToRight = true -- Only used where the quarry is of an odd width
  1176.  
  1177. -- Loop over each mining row
  1178. local miningLevel
  1179. for miningLevel = (bottomLayer + miningOffset), topMiningLayer, 3 do
  1180. writeMessage("Mining Layer: "..miningLevel, messageLevel.INFO)
  1181. haveBeenAtZeroZeroOnLayer = false
  1182.  
  1183. -- While the initial shaft is being dug out, set the level to return to in order to unload
  1184. -- to the just take the turtle straight back up
  1185. if (miningLevel == (bottomLayer + miningOffset)) then
  1186. levelToReturnTo = startHeight
  1187. end
  1188.  
  1189. -- Move to the correct level to start mining
  1190. if (currY > miningLevel) then
  1191. while (currY > miningLevel) do
  1192. turtleDown()
  1193. end
  1194. elseif (currY < miningLevel) then
  1195. while (currY < miningLevel) do
  1196. turtleUp()
  1197. end
  1198. end
  1199.  
  1200. -- Am now mining the levels (update the mining state to reflect that fact)
  1201. currMiningState = miningState.LAYER
  1202.  
  1203. -- Set the layer to return via when returning to the surface as the one below the currently
  1204. -- mined one
  1205. if (miningLevel == (bottomLayer + miningOffset)) then
  1206. levelToReturnTo = (bottomLayer + miningOffset)
  1207. else
  1208. levelToReturnTo = miningLevel - 3
  1209. end
  1210.  
  1211. -- Move turtle into the correct orientation to start mining (if this is the
  1212. -- first row to be mined, then don't need to turn, otherwise turn towards the next
  1213. -- mining section)
  1214.  
  1215. writeMessage("Mining Level: "..miningLevel..", Bottom Layer: "..bottomLayer..", Mining Offset: "..miningOffset, messageLevel.DEBUG)
  1216.  
  1217. if (miningLevel > (bottomLayer + miningOffset)) then
  1218. -- Turn towards the next mining layer
  1219. if (quarryWidth % 2 == 0) then
  1220. -- An even width quarry, always turn right
  1221. turtleTurn(direction.RIGHT)
  1222. else
  1223. -- Turn the opposite direction to that which we turned before
  1224. if (startedLayerToRight == true) then
  1225. turtleTurn(direction.LEFT)
  1226. startedLayerToRight = false
  1227. else
  1228. turtleTurn(direction.RIGHT)
  1229. startedLayerToRight = true
  1230. end
  1231. end
  1232. end
  1233.  
  1234. local mineRows
  1235. local onNearSideOfQuarry = true
  1236. local diggingAway = true
  1237. for mineRows = 1, quarryWidth do
  1238.  
  1239. -- If this is not the first row, then get into position to mine the next row
  1240. if ((mineRows == 1) and (lookForChests == false)) then
  1241. -- Not looking for chests, check the block below for being an ore. Only do this
  1242. -- if we're not looking for chests since the program doesn't support chests in
  1243. -- bedrock
  1244. if (isNoiseBlock(turtle.compareDown) == false) then
  1245. turtle.digDown()
  1246. ensureInventorySpace()
  1247. end
  1248. elseif (mineRows > 1) then
  1249. -- Move into position for mining the next row
  1250. if (onNearSideOfQuarry == diggingAway) then
  1251. if (startedLayerToRight == true) then
  1252. turtleTurn(direction.LEFT)
  1253. else
  1254. turtleTurn(direction.RIGHT)
  1255. end
  1256. else
  1257. if (startedLayerToRight == true) then
  1258. turtleTurn(direction.RIGHT)
  1259. else
  1260. turtleTurn(direction.LEFT)
  1261. end
  1262. end
  1263.  
  1264. turtleForward()
  1265.  
  1266. -- Before making the final turn, check the block below. Do this
  1267. -- now because if it is a chest, then we want to back up and
  1268. -- approach it from the side (so that we don't lose items if we
  1269. -- have to return to the start through it).
  1270. --
  1271. -- This is the point at which it is safe to back up without moving
  1272. -- out of the quarry area (unless at bedrock in which case don't bother
  1273. -- as we'll be digging down anyway)
  1274. if (miningLevel ~= bottomLayer) then
  1275. if (isNoiseBlock(turtle.compareDown) == false) then
  1276. -- If we are not looking for chests, then just dig it (it takes
  1277. -- less time to try to dig and fail as it does to do detect and
  1278. -- only dig if there is a block there)
  1279. if (lookForChests == false) then
  1280. turtle.digDown()
  1281. ensureInventorySpace()
  1282. elseif (turtle.detectDown() == true) then
  1283. if (isChestBlock(turtle.compareDown) == true) then
  1284. -- There is a chest block below. Move back and approach
  1285. -- from the side to ensure that we don't need to return to
  1286. -- start through the chest itself (potentially losing items)
  1287. turtleBack()
  1288. turtleDown()
  1289. currMiningState = miningState.EMPTYCHESTDOWN
  1290. emptyChest(turtle.suck)
  1291. currMiningState = miningState.LAYER
  1292. turtleUp()
  1293. turtleForward()
  1294. turtle.digDown()
  1295. ensureInventorySpace()
  1296. else
  1297. turtle.digDown()
  1298. ensureInventorySpace()
  1299. end
  1300. end
  1301. end
  1302. end
  1303.  
  1304. -- Move into final position for mining the next row
  1305. if (onNearSideOfQuarry == diggingAway) then
  1306. if (startedLayerToRight == true) then
  1307. turtleTurn(direction.LEFT)
  1308. else
  1309. turtleTurn(direction.RIGHT)
  1310. end
  1311. else
  1312. if (startedLayerToRight == true) then
  1313. turtleTurn(direction.RIGHT)
  1314. else
  1315. turtleTurn(direction.LEFT)
  1316. end
  1317. end
  1318. end
  1319.  
  1320. -- Dig to the other side of the quarry
  1321. local blocksMined
  1322. for blocksMined = 0, (quarryWidth - 1) do
  1323. if (blocksMined > 0) then
  1324. -- Only move forward if this is not the first space
  1325. turtleForward()
  1326. end
  1327.  
  1328. -- If the current block is (0,0), then record the fact that the
  1329. -- turtle has been through this block and what it's orientation was and update the layer
  1330. -- that it should return via to get back to the surface (it no longer needs to go down
  1331. -- a level to prevent losing ores).
  1332. if ((currX == 0) and (currZ == 0)) then
  1333. -- Am at (0, 0). Remember this, and what direction I was facing so that the quickest route
  1334. -- to the surface can be taken
  1335. levelToReturnTo = miningLevel
  1336. haveBeenAtZeroZeroOnLayer = true
  1337. orientationAtZeroZero = currOrient
  1338. end
  1339.  
  1340. -- If currently at bedrock, just move down until the turtle can't go any
  1341. -- further. This allows the blocks within the bedrock to be mined
  1342. if (miningLevel == bottomLayer) then
  1343. -- Temporarily turn off looking for chests to increase bedrock mining speed (this
  1344. -- means that the program doesn't support chests below level 5 - but I think
  1345. -- they they don't exist anyway)
  1346. local lookForChestsPrev = lookForChests
  1347. lookForChests = false
  1348.  
  1349. -- Manually set the flag to determine whether the turtle should try to move first or
  1350. -- dig first. At bedrock, is very rarely any space
  1351.  
  1352. -- Just above bedrock layer, dig down until can't dig any lower, and then
  1353. -- come back up. This replicates how the quarry functions
  1354. lastMoveNeededDig = true
  1355. local moveDownSuccess = turtleDown()
  1356. while (moveDownSuccess == true) do
  1357. moveDownSuccess = turtleDown()
  1358. end
  1359.  
  1360. -- Know that we are moving back up through air, therefore set the flag to force the
  1361. -- turtle to try moving first
  1362. lastMoveNeededDig = false
  1363.  
  1364. -- Have now hit bedrock, move back to the mining layer
  1365. while (currY < bottomLayer) do
  1366. turtleUp()
  1367. end
  1368.  
  1369. -- Now back at the level above bedrock, again reset the flag to tell the turtle to
  1370. -- try digging again (because it is rare to find air at bedrock level)
  1371. lastMoveNeededDig = false
  1372.  
  1373. -- Reset the look for chests value
  1374. lookForChests = lookForChestsPrev
  1375. elseif ((blocksMined > 0) and ((currX ~= 0) or (currZ ~= 0))) then
  1376. -- This isn't the first block of the row, nor are we at (0, 0) so we need to check the
  1377. -- block below
  1378.  
  1379. -- Check the block down for being a noise block (don't need to check the first
  1380. -- block as it has already been checked in the outer loop)
  1381. if (isNoiseBlock(turtle.compareDown) == false) then
  1382. -- If we are not looking for chests, then just dig it (it takes
  1383. -- less time to try to dig and fail as it does to do detect and
  1384. -- only dig if there is a block there)
  1385. if (lookForChests == false) then
  1386. turtle.digDown()
  1387. ensureInventorySpace()
  1388. elseif (turtle.detectDown() == true) then
  1389. if (isChestBlock(turtle.compareDown) == true) then
  1390. -- There is a chest block below. Move back and approach
  1391. -- from the side to ensure that we don't need to return to
  1392. -- start through the chest itself (potentially losing items)
  1393. turtleBack()
  1394. currMiningState = miningState.EMPTYCHESTDOWN
  1395. turtleDown()
  1396. emptyChest(turtle.suck)
  1397. currMiningState = miningState.LAYER
  1398. turtleUp()
  1399. turtleForward()
  1400. turtle.digDown()
  1401. ensureInventorySpace()
  1402. else
  1403. turtle.digDown()
  1404. ensureInventorySpace()
  1405. end
  1406. end
  1407. end
  1408. end
  1409.  
  1410. -- Check the block above for ores (if we're not a (0, 0) in which case
  1411. -- we know it's air)
  1412. if ((currX ~= 0) or (currZ ~= 0)) then
  1413. if (isNoiseBlock(turtle.compareUp) == false) then
  1414. -- If we are not looking for chests, then just dig it (it takes
  1415. -- less time to try to dig and fail as it does to do detect and
  1416. -- only dig if there is a block there)
  1417. if (lookForChests == false) then
  1418. turtle.digUp()
  1419. ensureInventorySpace()
  1420. elseif (turtle.detectUp() == true) then
  1421. -- Determine if it is a chest before digging it
  1422. if (isChestBlock(turtle.compareUp) == true) then
  1423. -- There is a chest block above. Empty it before digging it
  1424. emptyChest(turtle.suckUp)
  1425. turtle.digUp()
  1426. ensureInventorySpace()
  1427. else
  1428. turtle.digUp()
  1429. ensureInventorySpace()
  1430. end
  1431. end
  1432. end
  1433. end
  1434. end
  1435.  
  1436. -- Am now at the other side of the quarry
  1437. onNearSideOfQuarry = not onNearSideOfQuarry
  1438. end
  1439.  
  1440. -- If we were digging away from the starting point, will be digging
  1441. -- back towards it on the next layer
  1442. diggingAway = not diggingAway
  1443. end
  1444.  
  1445. -- Return to the start
  1446. returnToStartAndUnload(false)
  1447.  
  1448. -- Face forward
  1449. turtleSetOrientation(direction.FORWARD)
  1450. end
  1451.  
  1452. -- ********************************************************************************** --
  1453. -- Reads the next number from a given file
  1454. -- ********************************************************************************** --
  1455. function readNumber(inputFile)
  1456.  
  1457. local returnVal
  1458. local nextLine = inputFile.readLine()
  1459. if (nextLine ~= nil) then
  1460. returnVal = tonumber(nextLine)
  1461. end
  1462.  
  1463. return returnVal
  1464. end
  1465.  
  1466. -- ********************************************************************************** --
  1467. -- Startup function to support resuming mining turtle
  1468. -- ********************************************************************************** --
  1469. function isResume()
  1470.  
  1471. local returnVal = false
  1472.  
  1473. -- Try to open the resume file
  1474. local resumeFile = fs.open(startupParamsFile, "r")
  1475. if (resumeFile == nil) then
  1476. -- No resume file (presume that we are not supporting it)
  1477. supportResume = false
  1478. else
  1479. writeMessage("Found startup params file", messageLevel.DEBUG)
  1480.  
  1481. -- Read in the startup params
  1482. quarryWidth = readNumber(resumeFile)
  1483. startHeight = readNumber(resumeFile)
  1484. noiseBlocksCount = readNumber(resumeFile)
  1485. lastEmptySlot = readNumber(resumeFile)
  1486. resumeFile.close()
  1487.  
  1488. -- If the parameters were successfully read, then set the resuming flag to true
  1489. if ((quarryWidth ~= nil) and (startHeight ~= nil) and (noiseBlocksCount ~= nil) and (lastEmptySlot ~= nil)) then
  1490.  
  1491. resuming = true
  1492. writeMessage("Read params", messageLevel.DEBUG)
  1493.  
  1494. -- Determine the look for chest and mining offset
  1495. if (lastEmptySlot == 14) then
  1496. lookForChests = true
  1497. miningOffset = 0
  1498. else
  1499. lookForChests = false
  1500. miningOffset = 1
  1501. end
  1502.  
  1503. -- Get the turtle resume location
  1504. resumeFile = fs.open(oreQuarryLocation, "r")
  1505. if (resumeFile ~= nil) then
  1506.  
  1507. resumeMiningState = readNumber(resumeFile)
  1508. resumeX = readNumber(resumeFile)
  1509. resumeY = readNumber(resumeFile)
  1510. resumeZ = readNumber(resumeFile)
  1511. resumeOrient = readNumber(resumeFile)
  1512. resumeFile.close()
  1513.  
  1514. -- Ensure that the resume location has been found
  1515. if ((resumeMiningState ~= nil) and (resumeX ~= nil) and (resumeY ~= nil) and (resumeZ ~= nil) and (resumeOrient ~= nil)) then
  1516. returnVal = true
  1517. local emptiedInventory = false
  1518.  
  1519. -- Perform any mining state specific startup
  1520. if (resumeMiningState == miningState.EMPTYINVENTORY) then
  1521. -- Am mid way through an empty inventory cycle. Complete it before
  1522. -- starting the main Quarry function
  1523. returnToStartAndUnload(true)
  1524. resuming = true
  1525.  
  1526. -- Continue from the current position
  1527. resumeX = currX
  1528. resumeY = currY
  1529. levelToReturnTo = resumeY
  1530. resumeZ = currZ
  1531. resumeOrient = currOrient
  1532.  
  1533. writeMessage("Resuming with state of "..currMiningState, messageLevel.DEBUG)
  1534. resumeMiningState = currMiningState
  1535. emptiedInventory = true
  1536. end
  1537.  
  1538. -- If was emptying a chest when the program stopped, then move back
  1539. -- to a point which the Quarry
  1540. if (resumeMiningState == miningState.EMPTYCHESTDOWN) then
  1541.  
  1542. -- Set the current X, Y, Z and orientation to the true position that
  1543. -- the turtle is at
  1544. if (emptiedInventory == false) then
  1545. currX = resumeX
  1546. currY = resumeY
  1547. currZ = resumeZ
  1548. currOrient = resumeOrient
  1549. end
  1550.  
  1551. -- Set the mining state as layer, assume haven't been through zero
  1552. -- zero and set the level to return to as the one below the current one
  1553. currMiningState = miningState.LAYER
  1554. levelToReturnTo = currY - 2
  1555. haveBeenAtZeroZeroOnLayer = false
  1556.  
  1557. -- Temporarily disable resuming (so that the new location is written to the file
  1558. -- in case the program stops again)
  1559. resuming = false
  1560. turtleUp()
  1561. resuming = true
  1562.  
  1563. resumeY = currY
  1564. resumeMiningState = miningState.LAYER
  1565. end
  1566. end
  1567. end
  1568. end
  1569.  
  1570. if (returnVal == false) then
  1571. writeMessage("Failed to resume", messageLevel.ERROR)
  1572. end
  1573. end
  1574.  
  1575. return returnVal
  1576. end
  1577.  
  1578. -- ********************************************************************************** --
  1579. -- Main Function
  1580. -- ********************************************************************************** --
  1581. -- Process the input arguments - storing them to global variables
  1582. local args = { ... }
  1583. local paramsOK = true
  1584.  
  1585. -- Detect whether this is a wireless turtle, and if so, open the modem
  1586. isWirelessTurtle = peripheral.isPresent("right")
  1587. if (isWirelessTurtle == true) then
  1588. turtleId = os.getComputerLabel()
  1589. rednet.open("right")
  1590. end
  1591.  
  1592. if (#args == 0) then
  1593. -- Is this a resume?
  1594. if (isResume() == false) then
  1595. paramsOK = false
  1596. end
  1597. elseif (#args == 1) then
  1598. quarryWidth = tonumber(args[1])
  1599. local x, y, z = gps.locate(5)
  1600. startHeight = y
  1601. if (startHeight == nil) then
  1602. writeMessage("Can't locate GPS", messageLevel.FATAL)
  1603. paramsOK = false
  1604. end
  1605. elseif (#args == 2) then
  1606. if (args[2] == "/r") then
  1607. quarryWidth = tonumber(args[1])
  1608. supportResume = false
  1609. else
  1610. quarryWidth = tonumber(args[1])
  1611. startHeight = tonumber(args[2])
  1612. end
  1613. elseif (#args == 3) then
  1614. quarryWidth = tonumber(args[1])
  1615. startHeight = tonumber(args[2])
  1616. if (args[3] == "/r") then
  1617. supportResume = false
  1618. else
  1619. paramsOK = false
  1620. end
  1621. end
  1622.  
  1623. if ((paramsOK == false) and (resuming == false)) then
  1624. writeMessage("Usage: "..shell.getRunningProgram().." <diameter> [turtleY] [/r]", messageLevel.FATAL)
  1625. paramsOK = false
  1626. end
  1627.  
  1628. if (paramsOK == true) then
  1629. if ((startHeight < 6) or (startHeight > 128)) then
  1630. writeMessage("turtleY must be between 6 and 128", messageLevel.FATAL)
  1631. paramsOK = false
  1632. end
  1633.  
  1634. if ((quarryWidth < 2) or (quarryWidth > 64)) then
  1635. writeMessage("diameter must be between 2 and 64", messageLevel.FATAL)
  1636. paramsOK = false
  1637. end
  1638. end
  1639.  
  1640. if (paramsOK == true) then
  1641. writeMessage("---------------------------------", messageLevel.INFO)
  1642. writeMessage("** Ore Quarry v0.7 by AustinKK **", messageLevel.INFO)
  1643. writeMessage("---------------------------------", messageLevel.INFO)
  1644. if (resuming == true) then
  1645. writeMessage("Resuming...", messageLevel.INFO)
  1646. end
  1647.  
  1648. -- Set the turtle's starting position
  1649. currX = 0
  1650. currY = startHeight
  1651. currZ = 0
  1652. currOrient = direction.FORWARD
  1653.  
  1654. -- Calculate which blocks in the inventory signify noise blocks
  1655. if (resuming == false) then
  1656. determineNoiseBlocksCountCount()
  1657. end
  1658.  
  1659. if ((noiseBlocksCount == 0) or (noiseBlocksCount > 13)) then
  1660. writeMessage("No noise blocks have been been added. Please place blocks that the turtle should not mine (e.g. Stone, Dirt, Gravel etc.) in the first few slots of the turtle\'s inventory. The first empty slot signifies the end of the noise blocks.", messageLevel.FATAL)
  1661. else
  1662. -- If we are supporting resume (and are not currently in the process of resuming)
  1663. -- then store startup parameters in appropriate files
  1664. if ((supportResume == true) and (resuming == false)) then
  1665. -- Write the startup parameters to file
  1666. local outputFile = io.open(startupParamsFile, "w")
  1667. outputFile:write(quarryWidth)
  1668. outputFile:write("\n")
  1669. outputFile:write(startHeight)
  1670. outputFile:write("\n")
  1671. outputFile:write(noiseBlocksCount)
  1672. outputFile:write("\n")
  1673. outputFile:write(lastEmptySlot)
  1674. outputFile:write("\n")
  1675. outputFile:close()
  1676.  
  1677. -- Setup the startup file
  1678.  
  1679. -- Take a backup of the current startup file
  1680. if (fs.exists("startup") == true) then
  1681. fs.copy("startup", startupBackup)
  1682. end
  1683.  
  1684. -- Write a new startup file to resume the turtle
  1685. outputFile = io.open("startup", "a")
  1686. outputFile:write("\nshell.run(\"")
  1687. outputFile:write(shell.getRunningProgram())
  1688. outputFile:write("\")\n")
  1689. outputFile:close()
  1690.  
  1691. end
  1692.  
  1693. -- Create a Quarry
  1694. turtle.select(1)
  1695. currentlySelectedSlot = 1
  1696. createQuarry()
  1697.  
  1698. -- Restore the file system to its original configuration
  1699. if (supportResume == true) then
  1700. fs.delete("startup")
  1701. if (fs.exists(startupBackup) == true) then
  1702. fs.move(startupBackup, "startup")
  1703. end
  1704.  
  1705. if (fs.exists(startupParamsFile) == true) then
  1706. fs.delete(startupParamsFile)
  1707. end
  1708.  
  1709. if (fs.exists(oreQuarryLocation) == true) then
  1710. fs.delete(oreQuarryLocation)
  1711. end
  1712.  
  1713. if (fs.exists(returnToStartFile) == true) then
  1714. fs.delete(returnToStartFile)
  1715. end
  1716. end
  1717. end
  1718. end
Advertisement
Add Comment
Please, Sign In to add comment