crameep

Untitled

Mar 14th, 2013
41
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 44.98 KB | None | 0 0
  1. -- ********************************************************************************** --
  2. -- **                                                                              ** --
  3. -- **   Minecraft Mining Turtle Ore Quarry v0.53 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] Released fix for chest bug                         ** --
  18. -- **                                                                              ** --
  19. -- ********************************************************************************** --
  20.  
  21. -- Enumeration to store the the different types of message that can be written
  22. messageLevel = { DEBUG=0, INFO=1, WARNING=2, ERROR=3, FATAL=4 }
  23.  
  24. -- Enumeration to store names for the 6 directions
  25. direction = { FORWARD=0, RIGHT=1, BACK=2, LEFT=3, UP=4, DOWN=5 }
  26.  
  27. local messages = {}
  28. local messageOutputLevel = messageLevel.INFO
  29. local messageOutputFileName
  30. local fuelLevelToRefuelAt = 5
  31. local refuelItemsToUseWhenRefuelling = 63
  32. local emergencyFuelToRetain = 0
  33. local maximumGravelStackSupported = 25 -- The number of stacked gravel or sand blocks supported
  34. local noiseBlocksCount
  35. local bottomLayer = 5 -- The y co-ords of the layer immediately above bedrock
  36. local returningToStart = false
  37. local lookForChests = false -- Determines if chests should be located as part of the quarrying
  38. local miningOffset -- The offset to the mining layer. This is set depending on whether chests are being looked for or not
  39. 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)
  40. local turtleId
  41. local currentlySelectedSlot = 0 -- The slot that the last noise block was found in
  42. local lastMoveNeededDig = true -- Determines whether the last move needed a dig first
  43. local haveBeenAtZeroZeroOnLayer -- Determines whether the turtle has been at (0, 0) in this mining layer
  44. local orientationAtZeroZero -- The turtle's orientation when it was at (0, 0)
  45. local levelToReturnTo -- The level that the turtle should return to in order to head back to the start to unload
  46.  
  47. -- Variables to store the current location and orientation of the turtle. x is right, left, y is up, down and
  48. -- z is forward, back with relation to the starting orientation. Y is the actual turtle level, x and z are
  49. -- in relation to the starting point (i.e. the starting point is (0, 0))
  50. local currX
  51. local currY
  52. local currZ
  53. local currOrient
  54.  
  55. -- Command line parameters
  56. local startHeight -- Represents the height (y co-ord) that the turtle started at
  57. local quarryWidth -- Represents the length of the mines that the turtle will dig
  58.  
  59. -- ********************************************************************************** --
  60. -- Writes an output message
  61. -- ********************************************************************************** --
  62. function writeMessage(message, msgLevel)
  63.   if (msgLevel >= messageOutputLevel) then
  64.     print(message)
  65.     if (turtleId == nil) then
  66.       rednet.broadcast(message)
  67.     else
  68.       -- Broadcast the message (prefixed with the turtle's id)
  69.       rednet.broadcast("[".. turtleId.."] "..message)
  70.     end
  71.  
  72.     if (messageOutputFileName ~= nil) then
  73.       -- Open file, write message and close file (flush doesn't seem to work!)
  74.       local outputFile = io.open(messageOutputFileName, "a")
  75.       outputFile:write(message)
  76.       outputFile:write("\n")
  77.       outputFile:close()
  78.     end
  79.   end
  80. end
  81.  
  82. -- ********************************************************************************** --
  83. -- Ensures that the turtle has fuel
  84. -- ********************************************************************************** --
  85. function ensureFuel()
  86.  
  87.   -- Determine whether a refuel is required
  88.   local fuelLevel = turtle.getFuelLevel()
  89.   if (fuelLevel ~= "unlimited") then
  90.     if (fuelLevel < fuelLevelToRefuelAt) then
  91.       -- Need to refuel
  92.       turtle.select(16)
  93.       currentlySelectedSlot = 16
  94.       local fuelItems = turtle.getItemCount(16)
  95.  
  96.       -- Do we need to impact the emergency fuel to continue? (always  
  97.       -- keep one fuel item in slot 16)
  98.       if (fuelItems == 0) then
  99.         writeMessage("Completely out of fuel!", messageLevel.FATAL)
  100.       elseif (fuelItems == 1) then
  101.         writeMessage("Out of Fuel!", messageLevel.ERROR)
  102.         turtle.refuel()
  103.       elseif (fuelItems <= (emergencyFuelToRetain + 1)) then
  104.         writeMessage("Consuming emergency fuel supply. "..(fuelItems - 2).." emergency fuel items remain", messageLevel.WARNING)
  105.         turtle.refuel(1)
  106.       else
  107.         -- Refuel the lesser of the refuelItemsToUseWhenRefuelling and the number of items more than
  108.         -- the emergency fuel level
  109.         if (fuelItems - (emergencyFuelToRetain + 1) < refuelItemsToUseWhenRefuelling) then
  110.           turtle.refuel(fuelItems - (emergencyFuelToRetain + 1))
  111.         else
  112.           turtle.refuel(refuelItemsToUseWhenRefuelling)
  113.         end
  114.       end
  115.     end
  116.   end
  117. end        
  118.  
  119. -- ********************************************************************************** --
  120. -- Checks that the turtle has inventory space by checking for spare slots and returning
  121. -- to the starting point to empty out if it doesn't.
  122. --
  123. -- Takes the position required to move to in order to empty the turtle's inventory
  124. -- should it be full as arguments
  125. -- ********************************************************************************** --
  126. function ensureInventorySpace()
  127.  
  128.   -- If already returning to start, then don't need to do anything
  129.   if (returningToStart == false) then
  130.      for key,value in pairs (messages) do
  131.       if (value.msg == "stop" ) then
  132.     returnToStartAndUnload(true)
  133.       end
  134.     print(tostring(key)..": "..value.msg)
  135.        end  
  136.     -- If the last inventory slot is full, then need to return to the start and empty
  137.     if (turtle.getItemCount(lastEmptySlot) > 0) then
  138.  
  139.       -- Return to the starting point and empty the inventory, then go back to mining
  140.       returnToStartAndUnload(true)
  141.     end
  142.   end
  143. end
  144.  
  145. -- ********************************************************************************** --
  146. -- Function to move to the starting point, call a function that is passed in
  147. -- and return to the same location (if required)
  148. -- ********************************************************************************** --
  149. function returnToStartAndUnload(returnBackToMiningPoint)
  150.  
  151.   writeMessage("returnToStartAndUnload called", messageLevel.DEBUG)
  152.   returningToStart = true
  153.  
  154.   -- Store the current location and orientation so that it can be returned to
  155.   local storedX = currX
  156.   local storedY = currY
  157.   local storedZ = currZ
  158.   local storedOrient = currOrient
  159.  
  160.   writeMessage("Return to start, return level: "..levelToReturnTo, messageLevel.DEBUG)
  161.  
  162.   -- Move down to the correct layer to return via
  163.   if (currY > levelToReturnTo) then
  164.     while (currY > levelToReturnTo) do
  165.       turtleDown()
  166.     end
  167.   elseif (currY < levelToReturnTo) then
  168.     while (currY < levelToReturnTo) do
  169.       turtleUp()
  170.     end
  171.   end
  172.  
  173.   if ((haveBeenAtZeroZeroOnLayer == false) or (orientationAtZeroZero == direction.FORWARD)) then
  174.     -- Move back to the correct X position first
  175.     if (currX > 0) then
  176.       turtleSetOrientation(direction.LEFT)
  177.       while (currX > 0) do
  178.         turtleForward()
  179.       end
  180.     elseif (currX < 0) then
  181.       -- This should never happen
  182.       writeMessage("Current x is less than 0 in returnToStartAndUnload", messageLevel.ERROR)
  183.     end
  184.  
  185.     -- Then move back to the correct Z position
  186.     if (currZ > 0) then
  187.       turtleSetOrientation(direction.BACK)
  188.       while (currZ > 0) do
  189.         turtleForward()
  190.       end
  191.     elseif (currZ < 0) then
  192.       -- This should never happen
  193.       writeMessage("Current z is less than 0 in returnToStartAndUnload", messageLevel.ERROR)
  194.     end
  195.   else
  196.     -- Move back to the correct Z position first
  197.     if (currZ > 0) then
  198.       turtleSetOrientation(direction.BACK)
  199.       while (currZ > 0) do
  200.         turtleForward()
  201.       end
  202.     elseif (currZ < 0) then
  203.       -- This should never happen
  204.       writeMessage("Current z is less than 0 in returnToStartAndUnload", messageLevel.ERROR)
  205.     end
  206.  
  207.     -- Then move back to the correct X position
  208.     if (currX > 0) then
  209.       turtleSetOrientation(direction.LEFT)
  210.       while (currX > 0) do
  211.         turtleForward()
  212.       end
  213.     elseif (currX < 0) then
  214.       -- This should never happen
  215.       writeMessage("Current x is less than 0 in returnToStartAndUnload", messageLevel.ERROR)
  216.     end
  217.   end
  218.  
  219.   -- Return to the starting layer
  220.   if (currY < startHeight) then
  221.     while (currY < startHeight) do
  222.       turtleUp()
  223.     end
  224.   elseif (currY > startHeight) then
  225.     -- This should never happen
  226.     writeMessage("Current height is greater than start height in returnToStartAndUnload", messageLevel.ERROR)
  227.   end
  228.  
  229.   -- Empty the inventory
  230.   local slotLoop = 1
  231.  
  232.   -- Face the chest
  233.   turtleSetOrientation(direction.BACK)
  234.  
  235.   -- Loop over each of the slots (except the 16th one which stores fuel)
  236.   while (slotLoop < 16) do
  237.     -- If this is one of the slots that contains a noise block, empty all blocks except
  238.     -- one
  239.     turtle.select(slotLoop) -- Don't bother updating selected slot variable as it will set later in this function
  240.     if ((slotLoop <= noiseBlocksCount) or ((slotLoop == 15) and (lastEmptySlot == 14))) then
  241.       writeMessage("Dropping (n-1) from slot "..slotLoop.." ["..turtle.getItemCount(slotLoop).."]", messageLevel.DEBUG)  
  242.       turtle.drop(turtle.getItemCount(slotLoop) - 1)
  243.     else
  244.       -- Not a noise block, drop all of the items in this slot
  245.       writeMessage("Dropping (all) from slot "..slotLoop.." ["..turtle.getItemCount(slotLoop).."]", messageLevel.DEBUG)  
  246.       turtle.drop()
  247.     end
  248.      
  249.     slotLoop = slotLoop + 1
  250.   end
  251.  
  252.   -- While we are here, refill the fuel items if there is capacity
  253.   if (turtle.getItemCount(16) < 64) then
  254.     turtleSetOrientation(direction.LEFT)
  255.     turtle.select(16) -- Don't bother updating selected slot variable as it will set later in this function
  256.     local currFuelItems = turtle.getItemCount(16)
  257.     turtle.suck()
  258.     while ((currFuelItems ~= turtle.getItemCount(16)) and (turtle.getItemCount(16) < 64)) do
  259.       currFuelItems = turtle.getItemCount(16)
  260.       turtle.suck()
  261.     end
  262.  
  263.     slotLoop = noiseBlocksCount + 1
  264.     -- Have now picked up all the items that we can. If we have also picked up some
  265.     -- additional fuel in some of the other slots, then drop it again
  266.     while (slotLoop <= lastEmptySlot) do
  267.       -- Drop any items found in this slot
  268.       turtle.select(slotLoop) -- Don't bother updating selected slot variable as it will set later in this function
  269.       turtle.drop()
  270.       slotLoop = slotLoop + 1
  271.     end
  272.   end
  273.  
  274.   -- Select the 1st slot because sometimes when leaving the 15th or 16th slots selected it can result
  275.   -- in that slot being immediately filled (resulting in the turtle returning to base again too soon)
  276.   turtle.select(1)
  277.   currentlySelectedSlot = 1
  278.  
  279.   -- If required, move back to the point that we were mining at before returning to the start
  280.   if (returnBackToMiningPoint == true) then
  281.     -- Return back to the required layer
  282.     while (currY > levelToReturnTo) do
  283.       turtleDown()
  284.     end
  285.  
  286.     if ((haveBeenAtZeroZeroOnLayer == false) or (orientationAtZeroZero == direction.FORWARD)) then
  287.       -- Move back to the correct Z position first
  288.       writeMessage("Stored Z: "..storedZ..", currZ: "..currZ, messageLevel.DEBUG)
  289.       if (storedZ > currZ) then
  290.         writeMessage("Orienting forward", messageLevel.DEBUG)
  291.         writeMessage("Moving in z direction", messageLevel.DEBUG)
  292.         turtleSetOrientation(direction.FORWARD)
  293.         while (storedZ > currZ) do
  294.           turtleForward()
  295.         end
  296.       elseif (storedZ < currZ) then
  297.         -- This should never happen
  298.         writeMessage("Stored z is less than current z in returnToStartAndUnload", messageLevel.ERROR)
  299.       end
  300.  
  301.       -- Then move back to the correct X position
  302.       if (storedX > currX) then
  303.         writeMessage("Stored X: "..storedX..", currX: "..currX, messageLevel.DEBUG)
  304.         writeMessage("Orienting right", messageLevel.DEBUG)
  305.         writeMessage("Moving in x direction", messageLevel.DEBUG)
  306.         turtleSetOrientation(direction.RIGHT)
  307.         while (storedX > currX) do
  308.           turtleForward()
  309.         end
  310.       elseif (storedX < currX) then
  311.         -- This should never happen
  312.         writeMessage("Stored x is less than current x in returnToStartAndUnload", messageLevel.ERROR)
  313.       end
  314.     else
  315.       -- Move back to the correct X position first
  316.       if (storedX > currX) then
  317.         writeMessage("Stored X: "..storedX..", currX: "..currX, messageLevel.DEBUG)
  318.         writeMessage("Orienting right", messageLevel.DEBUG)
  319.         writeMessage("Moving in x direction", messageLevel.DEBUG)
  320.         turtleSetOrientation(direction.RIGHT)
  321.         while (storedX > currX) do
  322.           turtleForward()
  323.         end
  324.       elseif (storedX < currX) then
  325.         -- This should never happen
  326.         writeMessage("Stored x is less than current x in returnToStartAndUnload", messageLevel.ERROR)
  327.       end
  328.  
  329.       -- Then move back to the correct Z position
  330.       writeMessage("Stored Z: "..storedZ..", currZ: "..currZ, messageLevel.DEBUG)
  331.       if (storedZ > currZ) then
  332.         writeMessage("Orienting forward", messageLevel.DEBUG)
  333.         writeMessage("Moving in z direction", messageLevel.DEBUG)
  334.         turtleSetOrientation(direction.FORWARD)
  335.         while (storedZ > currZ) do
  336.           turtleForward()
  337.         end
  338.       elseif (storedZ < currZ) then
  339.         -- This should never happen
  340.         writeMessage("Stored z is less than current z in returnToStartAndUnload", messageLevel.ERROR)
  341.       end
  342.     end
  343.  
  344.     -- Move back to the correct layer
  345.     if (storedY < currY) then
  346.       while (storedY < currY) do
  347.         turtleDown()
  348.       end
  349.     elseif (storedY > currY) then
  350.       while (storedY > currY) do
  351.         turtleUp()
  352.       end
  353.     end
  354.  
  355.     -- Finally, set the correct orientation
  356.     turtleSetOrientation(storedOrient)
  357.  
  358.     writeMessage("Have returned to the mining point", messageLevel.DEBUG)
  359.   end
  360.  
  361.   returningToStart = false
  362.  
  363. end
  364.  
  365. -- ********************************************************************************** --
  366. -- Empties a chest's contents
  367. -- ********************************************************************************** --
  368. function emptyChest(suckFn)
  369.  
  370.   local prevInventoryCount = {}
  371.   local inventoryLoop
  372.   local chestEmptied = false
  373.  
  374.   -- Record the number of items in each of the inventory slots
  375.   for inventoryLoop = 1, 16 do
  376.     prevInventoryCount[inventoryLoop] = turtle.getItemCount(inventoryLoop)
  377.   end
  378.  
  379.   while (chestEmptied == false) do
  380.     -- Pick up the next item
  381.     suckFn()
  382.  
  383.     -- Determine the number of items in each of the inventory slots now
  384.     local newInventoryCount = {}
  385.     for inventoryLoop = 1, 16 do
  386.       newInventoryCount[inventoryLoop] = turtle.getItemCount(inventoryLoop)
  387.     end
  388.  
  389.     -- Now, determine whether there have been any items taken from the chest
  390.     local foundDifferentItemCount = false
  391.     inventoryLoop = 1
  392.     while ((foundDifferentItemCount == false) and (inventoryLoop <= 16)) do
  393.       if (prevInventoryCount[inventoryLoop] ~= newInventoryCount[inventoryLoop]) then
  394.         foundDifferentItemCount = true
  395.       else
  396.         inventoryLoop = inventoryLoop + 1
  397.       end
  398.     end
  399.    
  400.     -- If no items have been found with a different item count, then the chest has been emptied
  401.     chestEmptied = not foundDifferentItemCount
  402.  
  403.     if (chestEmptied == false) then
  404.       prevInventoryCount = newInventoryCount
  405.       -- Check that there is sufficient inventory space as may have picked up a block
  406.       ensureInventorySpace()
  407.     end
  408.   end
  409.  
  410.   writeMessage("Finished emptying chest", messageLevel.DEBUG)
  411. end
  412.  
  413.  
  414. -- ********************************************************************************** --
  415. -- Generic function to move the Turtle (pushing through any gravel or other
  416. -- things such as mobs that might get in the way).
  417. --
  418. -- The only thing that should stop the turtle moving is bedrock. Where this is
  419. -- found, the function will return after 15 seconds returning false
  420. -- ********************************************************************************** --
  421. function moveTurtle(moveFn, detectFn, digFn, attackFn, compareFn, suckFn, maxDigCount)
  422.  
  423.   ensureFuel()
  424.  
  425.   -- Flag to determine whether digging has been tried yet. If it has
  426.   -- then pause briefly before digging again to allow sand or gravel to
  427.   -- drop
  428.   local digCount = 0
  429.   local moveSuccess = false
  430.  
  431.   if (lastMoveNeededDig == false) then
  432.     -- Didn't need to dig last time the turtle moved, so try moving first
  433.     moveSuccess = moveFn()
  434.  
  435.     -- Don't need to set the last move needed dig. It is already false, if
  436.     -- move success is now true, then it won't be changed
  437.   else    
  438.     -- If we are looking for chests, then check that this isn't a chest before trying to dig it
  439.     if (lookForChests == true) then
  440.       if (isNoiseBlock(compareFn) == false) then
  441.         if (detectFn() == true) then
  442.           -- Determine if it is a chest before digging it
  443.           if (isChestBlock(compareFn) == true) then
  444.             -- Have found a chest, empty it before continuing
  445.             emptyChest (suckFn)
  446.           end
  447.         end
  448.       end
  449.     end
  450.  
  451.     -- Try to dig (without doing a detect as it is quicker)
  452.     local digSuccess = digFn()
  453.     if (digSuccess == true) then
  454.       digCount = 1
  455.     end
  456.     moveSuccess = moveFn()
  457.  
  458.     if (moveSuccess == true) then
  459.       lastMoveNeededDig = digSuccess
  460.     end
  461.   end
  462.  
  463.   -- Loop until we've successfully moved
  464.   if (moveSuccess == false) then
  465.     while ((moveSuccess == false) and (digCount < maxDigCount)) do
  466.  
  467.       -- If there is a block in front, dig it
  468.       if (detectFn() == true) then
  469.        
  470.           -- If we've already tried digging, then pause before digging again to let
  471.           -- any sand or gravel drop, otherwise check for a chest before digging
  472.           if(digCount == 0) then
  473.             -- Am about to dig a block - check that it is not a chest if necessary
  474.             -- If we are looking for chests, then check that this isn't a chest before moving
  475.             if (lookForChests == true) then
  476.               if (isNoiseBlock(compareFn) == false) then
  477.                 if (detectFn() == true) then
  478.                   -- Determine if it is a chest before digging it
  479.                   if (isChestBlock(compareFn) == true) then
  480.                     -- Have found a chest, empty it before continuing
  481.                     emptyChest (suckFn)
  482.                   end
  483.                 end
  484.               end
  485.             end
  486.           else
  487.             sleep(0.1)
  488.           end
  489.  
  490.           digFn()
  491.           digCount = digCount + 1
  492.       else
  493.          -- Am being stopped from moving by a mob, attack it
  494.          attackFn()
  495.       end
  496.  
  497.       -- Try the move again
  498.       moveSuccess = moveFn()
  499.     end
  500.  
  501.     if (digCount == 0) then
  502.       lastMoveNeededDig = false
  503.     else
  504.       lastMoveNeededDig = true
  505.     end
  506.   end
  507.  
  508.   -- Return the move success
  509.   return moveSuccess
  510.  
  511. end
  512.  
  513. -- ********************************************************************************** --
  514. -- Move the turtle forward one block (updating the turtle's position)
  515. -- ********************************************************************************** --
  516. function turtleForward()
  517.   local returnVal = moveTurtle(turtle.forward, turtle.detect, turtle.dig, turtle.attack, turtle.compare, turtle.suck, maximumGravelStackSupported)
  518.   if (returnVal == true) then
  519.     -- Update the current co-ordinates
  520.     if (currOrient == direction.FORWARD) then
  521.       currZ = currZ + 1
  522.     elseif (currOrient == direction.LEFT) then
  523.       currX = currX - 1
  524.     elseif (currOrient == direction.BACK) then
  525.       currZ = currZ - 1
  526.     elseif (currOrient == direction.RIGHT) then
  527.       currX = currX + 1
  528.     else
  529.       writeMessage ("Invalid currOrient in turtleForward function", messageLevel.ERROR)
  530.     end
  531.  
  532.     -- Check that there is sufficient inventory space as may have picked up a block
  533.     ensureInventorySpace()
  534.   end
  535.  
  536.   return returnVal
  537. end
  538.  
  539. -- ********************************************************************************** --
  540. -- Move the turtle up one block (updating the turtle's position)
  541. -- ********************************************************************************** --
  542. function turtleUp()
  543.   local returnVal = moveTurtle(turtle.up, turtle.detectUp, turtle.digUp, turtle.attackUp, turtle.compareUp, turtle.suckUp, maximumGravelStackSupported)
  544.   if (returnVal == true) then
  545.     currY = currY + 1
  546.  
  547.     -- Check that there is sufficient inventory space as may have picked up a block
  548.     ensureInventorySpace()
  549.   end
  550.   return returnVal
  551. end
  552.  
  553. -- ********************************************************************************** --
  554. -- Move the turtle down one block (updating the turtle's position)
  555. -- ********************************************************************************** --
  556. function turtleDown()
  557.   local returnVal
  558.  
  559.   -- Because the turtle is digging down, can fail fast (only allow 1 dig attempt).
  560.   returnVal = moveTurtle(turtle.down, turtle.detectDown, turtle.digDown, turtle.attackDown, turtle.compareDown, turtle.suckDown, 1)
  561.   if (returnVal == true) then
  562.     currY = currY - 1
  563.  
  564.     -- Check that there is sufficient inventory space as may have picked up a block
  565.     ensureInventorySpace()
  566.   end
  567.   return returnVal
  568. end
  569.  
  570. -- ********************************************************************************** --
  571. -- Move the turtle back one block (updating the turtle's position)
  572. -- ********************************************************************************** --
  573. function turtleBack()
  574.   -- First try to move back using the standard function
  575.   local returnVal = turtle.back()
  576.  
  577.   -- Moving back didn't work (might be a block or a mob in the way). Turn round and move
  578.   -- forward instead (whereby anything in the way can be cleared)
  579.   if(returnVal == false) then
  580.     turtle.turnRight()
  581.     turtle.turnRight()
  582.     returnVal = turtleForward()
  583.     turtle.turnRight()
  584.     turtle.turnRight()
  585.   end  
  586.  
  587.   if (returnVal == true) then
  588.     -- Update the current co-ordinates
  589.     if (currOrient == direction.FORWARD) then
  590.       currZ = currZ - 1
  591.     elseif (currOrient == direction.LEFT) then
  592.       currX = currX + 1
  593.     elseif (currOrient == direction.BACK) then
  594.       currZ = currZ + 1
  595.     elseif (currOrient == direction.RIGHT) then
  596.       currX = currX - 1
  597.     else
  598.       writeMessage ("Invalid currOrient in turtleBack function", messageLevel.ERROR)
  599.     end
  600.  
  601.     -- Check that there is sufficient inventory space as may have picked up a block
  602.     ensureInventorySpace()
  603.   end
  604.    
  605.   return returnVal
  606. end
  607.  
  608. -- ********************************************************************************** --
  609. -- Turns the turtle (updating the current orientation at the same time)
  610. -- ********************************************************************************** --
  611. function turtleTurn(turnDir)
  612.  
  613.   if (turnDir == direction.LEFT) then
  614.     if (currOrient == direction.FORWARD) then
  615.       currOrient = direction.LEFT
  616.       turtle.turnLeft()
  617.     elseif (currOrient == direction.LEFT) then
  618.       currOrient = direction.BACK
  619.       turtle.turnLeft()
  620.     elseif (currOrient == direction.BACK) then
  621.       currOrient = direction.RIGHT
  622.       turtle.turnLeft()
  623.     elseif (currOrient == direction.RIGHT) then
  624.       currOrient = direction.FORWARD
  625.       turtle.turnLeft()
  626.     else
  627.       writeMessage ("Invalid currOrient in turtleTurn function", messageLevel.ERROR)
  628.     end
  629.   elseif (turnDir == direction.RIGHT) then
  630.     if (currOrient == direction.FORWARD) then
  631.       currOrient = direction.RIGHT
  632.       turtle.turnRight()
  633.     elseif (currOrient == direction.LEFT) then
  634.       currOrient = direction.FORWARD
  635.       turtle.turnRight()
  636.     elseif (currOrient == direction.BACK) then
  637.       currOrient = direction.LEFT
  638.       turtle.turnRight()
  639.     elseif (currOrient == direction.RIGHT) then
  640.       currOrient = direction.BACK
  641.       turtle.turnRight()
  642.     else
  643.       writeMessage ("Invalid currOrient in turtleTurn function", messageLevel.ERROR)
  644.     end
  645.   else
  646.     writeMessage ("Invalid turnDir in turtleTurn function", messageLevel.ERROR)
  647.   end
  648. end
  649.  
  650. -- ********************************************************************************** --
  651. -- Sets the turtle to a specific orientation, irrespective of its current orientation
  652. -- ********************************************************************************** --
  653. function turtleSetOrientation(newOrient)
  654.  
  655.   if (currOrient ~= newOrient) then
  656.     if (currOrient == direction.FORWARD) then
  657.       if (newOrient == direction.RIGHT) then
  658.         turtle.turnRight()
  659.         currOrient = newOrient
  660.       elseif (newOrient == direction.BACK) then
  661.         turtle.turnRight()
  662.         turtle.turnRight()
  663.         currOrient = newOrient
  664.       elseif (newOrient == direction.LEFT) then
  665.         turtle.turnLeft()
  666.         currOrient = newOrient
  667.       else
  668.         writeMessage ("Invalid newOrient in turtleSetOrientation function", messageLevel.ERROR)
  669.       end
  670.     elseif (currOrient == direction.RIGHT) then
  671.       if (newOrient == direction.BACK) then
  672.         turtle.turnRight()
  673.         currOrient = newOrient
  674.       elseif (newOrient == direction.LEFT) then
  675.         turtle.turnRight()
  676.         turtle.turnRight()
  677.         currOrient = newOrient
  678.       elseif (newOrient == direction.FORWARD) then
  679.         turtle.turnLeft()
  680.         currOrient = newOrient
  681.       else
  682.         writeMessage ("Invalid newOrient in turtleSetOrientation function", messageLevel.ERROR)
  683.       end
  684.     elseif (currOrient == direction.BACK) then
  685.       if (newOrient == direction.LEFT) then
  686.         turtle.turnRight()
  687.         currOrient = newOrient
  688.       elseif (newOrient == direction.FORWARD) then
  689.         turtle.turnRight()
  690.         turtle.turnRight()
  691.         currOrient = newOrient
  692.       elseif (newOrient == direction.RIGHT) then
  693.         turtle.turnLeft()
  694.         currOrient = newOrient
  695.       else
  696.         writeMessage ("Invalid newOrient in turtleSetOrientation function", messageLevel.ERROR)
  697.       end
  698.     elseif (currOrient == direction.LEFT) then
  699.       if (newOrient == direction.FORWARD) then
  700.         turtle.turnRight()
  701.         currOrient = newOrient
  702.       elseif (newOrient == direction.RIGHT) then
  703.         turtle.turnRight()
  704.         turtle.turnRight()
  705.         currOrient = newOrient
  706.       elseif (newOrient == direction.BACK) then
  707.         turtle.turnLeft()
  708.         currOrient = newOrient
  709.       else
  710.         writeMessage ("Invalid newOrient in turtleSetOrientation function", messageLevel.ERROR)
  711.       end
  712.     else
  713.       writeMessage ("Invalid currOrient in turtleTurn function", messageLevel.ERROR)
  714.     end
  715.   end
  716. end
  717.  
  718. -- ********************************************************************************** --
  719. -- Determines if a particular block is considered a noise block or not. A noise
  720. -- block is one that is a standard block in the game (stone, dirt, gravel etc.) and
  721. -- is one to ignore as not being an ore. Function works by comparing the block
  722. -- in question against a set of blocks in the turtle's inventory which are known not to
  723. -- be noise blocks. Param is the function to use to compare the block for a noise block
  724. -- ********************************************************************************** --
  725. function isNoiseBlock(compareFn)
  726.  
  727.   -- Consider air to be a noise block
  728.   local returnVal = false
  729.   local seamLoop = 1
  730.   local prevSelectedSlot  
  731.  
  732.   -- If the currently selected slot is a noise block, then compare against this first
  733.   -- so that the slot doesn't need to be selected again (there is a 0.05s cost to do
  734.   -- this even if it is the currently selected slot)
  735.   if (currentlySelectedSlot <= noiseBlocksCount) then
  736.     returnVal = compareFn()
  737.   end
  738.  
  739.   if (returnVal == false) then
  740.     prevSelectedSlot = currentlySelectedSlot
  741.     while((returnVal == false) and (seamLoop <= noiseBlocksCount)) do
  742.       if (seamLoop ~= prevSelectedSlot) then
  743.         turtle.select(seamLoop)
  744.         currentlySelectedSlot = seamLoop
  745.         returnVal = compareFn()
  746.       end
  747.       seamLoop = seamLoop + 1
  748.     end
  749.   end
  750.  
  751.   -- Return the calculated value
  752.   return returnVal
  753.  
  754. end
  755.  
  756. -- ********************************************************************************** --
  757. -- Determines if a particular block is a chest. Returns false if it is not a chest
  758. -- or chests are not being detected
  759. -- ********************************************************************************** --
  760. function isChestBlock(compareFn)
  761.  
  762.   -- Check the block in the appropriate direction to see whether it is a chest. Only
  763.   -- do this if we are looking for chests
  764.   local returnVal = false
  765.   if (lookForChests == true) then
  766.     turtle.select(15)
  767.     currentlySelectedSlot = 15
  768.     returnVal = compareFn()
  769.   end
  770.  
  771.   -- Return the calculated value
  772.   return returnVal
  773.  
  774. end
  775.  
  776. -- ********************************************************************************** --
  777. -- Function to calculate the number of non seam blocks in the turtle's inventory. This
  778. -- is all of the blocks at the start of the inventory (before the first empty slot is
  779. -- found
  780. -- ********************************************************************************** --
  781. function determineNoiseBlocksCountCount()
  782.   -- Determine the location of the first empty inventory slot. All items before this represent
  783.   -- noise items.
  784.   local foundFirstBlankInventorySlot = false
  785.   noiseBlocksCount = 1
  786.   while ((noiseBlocksCount < 16) and (foundFirstBlankInventorySlot == false)) do
  787.     if (turtle.getItemCount(noiseBlocksCount) > 0) then
  788.       noiseBlocksCount = noiseBlocksCount + 1
  789.     else
  790.       foundFirstBlankInventorySlot = true
  791.     end
  792.   end
  793.   noiseBlocksCount = noiseBlocksCount - 1
  794.  
  795.   -- Determine whether a chest was provided, and hence whether we should support
  796.   -- looking for chests
  797.   if (turtle.getItemCount(15) > 0) then
  798.     lookForChests = true
  799.     lastEmptySlot = 14
  800.     miningOffset = 0
  801.     writeMessage("Looking for chests...", messageLevel.DEBUG)
  802.   else
  803.     lastEmptySlot = 15
  804.     miningOffset = 1
  805.     writeMessage("Ignoring chests...", messageLevel.DEBUG)
  806.   end
  807. end
  808.  
  809. -- ********************************************************************************** --
  810. -- Creates a quarry mining out only ores and leaving behind any noise blocks
  811. -- ********************************************************************************** --
  812. function createQuarry()
  813.  
  814.   -- Determine the top mining layer layer. The turtle mines in layers of 3, and the bottom layer
  815.   -- is the layer directly above bedrock.
  816.   --
  817.   -- The actual layer that the turtle operates in is the middle of these three layers,
  818.   -- so determine the top layer
  819.   local topMiningLayer = startHeight + ((bottomLayer - startHeight - 2) % 3) - 1 + miningOffset
  820.  
  821.   -- If the top layer is up, then ignore it and move to the next layer
  822.   if (topMiningLayer > currY) then
  823.     topMiningLayer = topMiningLayer - 3
  824.   end
  825.  
  826.   local startedLayerToRight = true -- Only used where the quarry is of an odd width
  827.  
  828.   -- Loop over each mining row
  829.   local miningLevel
  830.   for miningLevel = (bottomLayer + miningOffset), topMiningLayer, 3 do
  831.     writeMessage("Mining Layer: "..miningLevel, messageLevel.INFO)
  832.     haveBeenAtZeroZeroOnLayer = false
  833.  
  834.     -- While the initial shaft is being dug out, set the level to return to in order to unload
  835.     -- to the just take the turtle straight back up
  836.     if (miningLevel == (bottomLayer + miningOffset)) then
  837.       levelToReturnTo = startHeight
  838.     end
  839.  
  840.     -- Move to the correct level to start mining
  841.     if (currY > miningLevel) then
  842.       while (currY > miningLevel) do
  843.         turtleDown()
  844.       end
  845.     elseif (currY < miningLevel) then
  846.       while (currY < miningLevel) do
  847.         turtleUp()
  848.       end
  849.     end
  850.  
  851.     -- Set the layer to return via when returning to the surface as the one below the currently
  852.     -- mined one
  853.     if (miningLevel == (bottomLayer + miningOffset)) then
  854.       levelToReturnTo = (bottomLayer + miningOffset)
  855.     else
  856.       levelToReturnTo = miningLevel - 3
  857.     end
  858.  
  859.     -- Move turtle into the correct orientation to start mining (if this is the
  860.     -- first row to be mined, then don't need to turn, otherwise turn towards the next
  861.     -- mining section)
  862.  
  863.     writeMessage("Mining Level: "..miningLevel..", Bottom Layer: "..bottomLayer..", Mining Offset: "..miningOffset, messageLevel.DEBUG)
  864.  
  865.     if (miningLevel > (bottomLayer + miningOffset)) then
  866.       -- Turn towards the next mining layer
  867.       if (quarryWidth % 2 == 0) then
  868.         -- An even width quarry, always turn right
  869.         turtleTurn(direction.RIGHT)
  870.       else
  871.         -- Turn the opposite direction to that which we turned before
  872.         if (startedLayerToRight == true) then
  873.           turtleTurn(direction.LEFT)
  874.           startedLayerToRight = false
  875.         else
  876.           turtleTurn(direction.RIGHT)
  877.           startedLayerToRight = true
  878.         end
  879.       end
  880.     end
  881.  
  882.     local mineRows
  883.     local onNearSideOfQuarry = true
  884.     local diggingAway = true
  885.     for mineRows = 1, quarryWidth do
  886.  
  887.       -- If this is not the first row, then get into position to mine the next row
  888.       if ((mineRows == 1) and (lookForChests == false)) then
  889.         -- Not looking for chests, check the block below for being an ore. Only do this
  890.         -- if we're not looking for chests since the program doesn't support chests in
  891.         -- bedrock
  892.         if (isNoiseBlock(turtle.compareDown) == false) then
  893.           turtle.digDown()
  894.           ensureInventorySpace()
  895.         end
  896.       elseif (mineRows > 1) then
  897.         -- Move into position for mining the next row
  898.         if (onNearSideOfQuarry == diggingAway) then
  899.           if (startedLayerToRight == true) then
  900.             turtleTurn(direction.LEFT)
  901.           else
  902.             turtleTurn(direction.RIGHT)
  903.           end
  904.         else
  905.           if (startedLayerToRight == true) then
  906.             turtleTurn(direction.RIGHT)
  907.           else
  908.             turtleTurn(direction.LEFT)
  909.           end
  910.         end
  911.  
  912.         turtleForward()
  913.  
  914.         -- Before making the final turn, check the block below. Do this
  915.         -- now because if it is a chest, then we want to back up and
  916.         -- approach it from the side (so that we don't lose items if we
  917.         -- have to return to the start through it).
  918.         --
  919.         -- This is the point at which it is safe to back up without moving
  920.         -- out of the quarry area (unless at bedrock in which case don't bother
  921.         -- as we'll be digging down anyway)
  922.         if (miningLevel ~= bottomLayer) then
  923.           if (isNoiseBlock(turtle.compareDown) == false) then
  924.             -- If we are not looking for chests, then just dig it (it takes
  925.             -- less time to try to dig and fail as it does to do detect and
  926.             -- only dig if there is a block there)
  927.             if (lookForChests == false) then
  928.               turtle.digDown()
  929.               ensureInventorySpace()
  930.             elseif (turtle.detectDown() == true) then
  931.               if (isChestBlock(turtle.compareDown) == true) then
  932.                 -- There is a chest block below. Move back and approach
  933.                 -- from the side to ensure that we don't need to return to
  934.                 -- start through the chest itself (potentially losing items)
  935.                 turtleBack()
  936.                 turtleDown()
  937.                 emptyChest(turtle.suck)
  938.                 turtleUp()
  939.                 turtleForward()
  940.                 turtle.digDown()
  941.                 ensureInventorySpace()
  942.               else
  943.                 turtle.digDown()
  944.                 ensureInventorySpace()
  945.               end
  946.             end
  947.           end
  948.         end
  949.  
  950.         -- Move into final position for mining the next row
  951.         if (onNearSideOfQuarry == diggingAway) then
  952.           if (startedLayerToRight == true) then
  953.             turtleTurn(direction.LEFT)
  954.           else
  955.             turtleTurn(direction.RIGHT)
  956.           end
  957.         else
  958.           if (startedLayerToRight == true) then
  959.             turtleTurn(direction.RIGHT)
  960.           else
  961.             turtleTurn(direction.LEFT)
  962.           end
  963.         end
  964.       end
  965.  
  966.       -- Dig to the other side of the quarry
  967.       local blocksMined
  968.       for blocksMined = 0, (quarryWidth - 1) do
  969.         if (blocksMined > 0) then
  970.           -- Only move forward if this is not the first space
  971.           turtleForward()
  972.         end
  973.  
  974.         -- If the current block is (0,0), then record the fact that the
  975.         -- turtle has been through this block and what it's orientation was and update the layer
  976.         -- that it should return via to get back to the surface (it no longer needs to go down
  977.         -- a level to prevent losing ores).
  978.         if ((currX == 0) and (currZ == 0)) then
  979.           -- Am at (0, 0). Remember this, and what direction I was facing so that the quickest route
  980.           -- to the surface can be taken
  981.           levelToReturnTo = miningLevel
  982.           haveBeenAtZeroZeroOnLayer = true
  983.           orientationAtZeroZero = currOrient
  984.         end
  985.  
  986.         -- If currently at bedrock, just move down until the turtle can't go any
  987.         -- further. This allows the blocks within the bedrock to be mined
  988.         if (miningLevel == bottomLayer) then
  989.           -- Temporarily turn off looking for chests to increase bedrock mining speed (this
  990.           -- means that the program doesn't support chests below level 5 - but I think
  991.           -- they they don't exist anyway)
  992.           local lookForChestsPrev = lookForChests
  993.           lookForChests = false
  994.  
  995.           -- Manually set the flag to determine whether the turtle should try to move first or
  996.           -- dig first. At bedrock, is very rarely any space
  997.  
  998.           -- Just above bedrock layer, dig down until can't dig any lower, and then
  999.           -- come back up. This replicates how the quarry functions
  1000.           lastMoveNeededDig = true
  1001.           local moveDownSuccess = turtleDown()
  1002.           while (moveDownSuccess == true) do
  1003.             moveDownSuccess = turtleDown()
  1004.           end
  1005.  
  1006.           -- Know that we are moving back up through air, therefore set the flag to force the
  1007.           -- turtle to try moving first
  1008.           lastMoveNeededDig = false
  1009.  
  1010.           -- Have now hit bedrock, move back to the mining layer
  1011.           while (currY < bottomLayer) do
  1012.             turtleUp()
  1013.           end
  1014.  
  1015.           -- Now back at the level above bedrock, again reset the flag to tell the turtle to
  1016.           -- try digging again (because it is rare to find air at bedrock level)
  1017.           lastMoveNeededDig = false
  1018.  
  1019.           -- Reset the look for chests value
  1020.           lookForChests = lookForChestsPrev
  1021.         elseif ((blocksMined > 0) and ((currX ~= 0) or (currZ ~= 0))) then
  1022.           -- This isn't the first block of the row, nor are we at (0, 0) so we need to check the
  1023.           -- block below
  1024.  
  1025.           -- Check the block down for being a noise block (don't need to check the first
  1026.           -- block as it has already been checked in the outer loop)
  1027.           if (isNoiseBlock(turtle.compareDown) == false) then
  1028.             -- If we are not looking for chests, then just dig it (it takes
  1029.             -- less time to try to dig and fail as it does to do detect and
  1030.             -- only dig if there is a block there)
  1031.             if (lookForChests == false) then
  1032.               turtle.digDown()
  1033.               ensureInventorySpace()
  1034.             elseif (turtle.detectDown() == true) then
  1035.               if (isChestBlock(turtle.compareDown) == true) then
  1036.                 -- There is a chest block below. Move back and approach
  1037.                 -- from the side to ensure that we don't need to return to
  1038.                 -- start through the chest itself (potentially losing items)
  1039.                 turtleBack()
  1040.                 turtleDown()
  1041.                 emptyChest(turtle.suck)
  1042.                 turtleUp()
  1043.                 turtleForward()
  1044.                 turtle.digDown()
  1045.                 ensureInventorySpace()
  1046.               else
  1047.                 turtle.digDown()
  1048.                 ensureInventorySpace()
  1049.               end
  1050.             end
  1051.           end
  1052.         end
  1053.        
  1054.         -- Check the block above for ores (if we're not a (0, 0) in which case
  1055.         -- we know it's air)
  1056.         if ((currX ~= 0) or (currZ ~= 0)) then
  1057.           if (isNoiseBlock(turtle.compareUp) == false) then
  1058.             -- If we are not looking for chests, then just dig it (it takes
  1059.             -- less time to try to dig and fail as it does to do detect and
  1060.             -- only dig if there is a block there)
  1061.             if (lookForChests == false) then
  1062.               turtle.digUp()
  1063.               ensureInventorySpace()
  1064.             elseif (turtle.detectUp() == true) then
  1065.               -- Determine if it is a chest before digging it
  1066.               if (isChestBlock(turtle.compareUp) == true) then
  1067.                 -- There is a chest block above. Empty it before digging it
  1068.                 emptyChest(turtle.suckUp)
  1069.                 turtle.digUp()
  1070.                 ensureInventorySpace()
  1071.               else
  1072.                 turtle.digUp()
  1073.                 ensureInventorySpace()
  1074.               end
  1075.             end
  1076.           end
  1077.         end
  1078.       end
  1079.  
  1080.       -- Am now at the other side of the quarry
  1081.       onNearSideOfQuarry = not onNearSideOfQuarry
  1082.     end
  1083.  
  1084.     -- If we were digging away from the starting point, will be digging
  1085.     -- back towards it on the next layer
  1086.     diggingAway = not diggingAway
  1087.   end
  1088.  
  1089.   -- Return to the start
  1090.   returnToStartAndUnload(false)
  1091.  
  1092.   -- Face forward
  1093.   turtleSetOrientation(direction.FORWARD)
  1094. end
  1095.  
  1096. -- ********************************************************************************** --
  1097. -- Main Function                                          
  1098. -- ********************************************************************************** --
  1099. -- Process the input arguments - storing them to global variables
  1100. local args = { ... }
  1101. local paramsOK = true
  1102.  
  1103. turtleId = os.getComputerLabel()
  1104. rednet.open("right")
  1105.  
  1106. if (#args == 1) then
  1107.   quarryWidth = tonumber(args[1])
  1108.   local x, y, z = gps.locate(5)
  1109.   startHeight = y
  1110.   if (startHeight == nil) then
  1111.     writeMessage("Can't locate GPS", messageLevel.FATAL)
  1112.     paramsOK = false
  1113.   end
  1114. elseif (#args == 2) then
  1115.   quarryWidth = tonumber(args[1])
  1116.   startHeight = tonumber(args[2])
  1117. else
  1118.   writeMessage("Usage: OreQuarry <diameter> <turtleY>", messageLevel.FATAL)
  1119.   paramsOK = false
  1120. end
  1121.  
  1122. if (paramsOK == true) then
  1123.   if ((startHeight < 6) or (startHeight > 128)) then
  1124.     writeMessage("turtleY must be between 6 and 128", messageLevel.FATAL)
  1125.     paramsOK = false
  1126.   end
  1127.  
  1128.   if ((quarryWidth < 2) or (quarryWidth > 64)) then
  1129.     writeMessage("diameter must be between 2 and 64", messageLevel.FATAL)
  1130.     paramsOK = false
  1131.   end
  1132. end
  1133.  
  1134. if (paramsOK == true) then
  1135.   writeMessage("----------------------------------", messageLevel.INFO)
  1136.   writeMessage("** Ore Quarry v0.53 by AustinKK **", messageLevel.INFO)
  1137.   writeMessage("----------------------------------", messageLevel.INFO)
  1138.  
  1139.   -- Set the turtle's starting position
  1140.   currX = 0
  1141.   currY = startHeight
  1142.   currZ = 0
  1143.   currOrient = direction.FORWARD
  1144.  
  1145.   -- Calculate which blocks in the inventory signify noise blocks
  1146.   determineNoiseBlocksCountCount()
  1147.  
  1148.   if ((noiseBlocksCount == 0) or (noiseBlocksCount > 13)) then
  1149.     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)
  1150.   else
  1151.     -- Create a Quarry
  1152.     turtle.select(1)
  1153.     currentlySelectedSlot = 1
  1154.     parallel.waitForAll(createQuarry, receive)
  1155.     --createQuarry()
  1156.   end
  1157. end
  1158.  
  1159. local messages = {}
  1160.  
  1161. function receive()
  1162.     while true do
  1163.         local sid, smsg, sdis = rednet.receive()
  1164.         table.insert(messages,{id = sid, msg = smsg, dis = sdis})
  1165.     end
  1166. end
Advertisement
Add Comment
Please, Sign In to add comment