emily99

CC Turtle: Excavate 2

Jun 19th, 2023 (edited)
90
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 9.59 KB | Gaming | 0 0
  1. if not turtle then
  2.     printError("Requires a Turtle")
  3.     return
  4. end
  5.  
  6. local tArgs = { ... }
  7. if #tArgs < 1 or #tArgs > 4 then
  8.     local programName = arg[0] or fs.getName(shell.getRunningProgram())
  9.     print("Usage: " .. programName .. " <diameter> [startDepth] [maxDepth] [startForward]")
  10.     return
  11. end
  12.  
  13. -- Mine in a quarry pattern until we hit something we can't dig
  14. local size = tonumber(tArgs[1])
  15. if size < 1 then
  16.     print("Excavate diameter must be positive")
  17.     return
  18. end
  19.  
  20. -- Mine straight down this far first
  21. local startDepth = 0
  22. if #tArgs > 1 then
  23.     startDepth = tonumber(tArgs[2])
  24. end
  25. -- Max distance to mine down before stopping, even if no bedrock reached
  26. local maxDepth = 999
  27. if #tArgs > 2 then
  28.     maxDepth = tonumber(tArgs[3])
  29. end
  30. -- Extra distance to travel forwards before starting mining
  31. local wanderDist = 0
  32. if #tArgs > 3 then
  33.     wanderDist = tonumber(tArgs[4])
  34. end
  35.  
  36. local depth = 0
  37. local unloaded = 0
  38. local collected = 0
  39. local triedTerminate = false
  40.  
  41. local xPos, zPos = 0, 0
  42. local xDir, zDir = 0, 1
  43.  
  44. local goTo -- Filled in further down
  45. local refuel -- Filled in further down
  46. local _await, _awaitRefuel, _exit, _tryTerm -- Filled in further down
  47.  
  48. local function turnLeft()
  49.     turtle.turnLeft()
  50.     xDir, zDir = -zDir, xDir
  51. end
  52.  
  53. local function turnRight()
  54.     turtle.turnRight()
  55.     xDir, zDir = zDir, -xDir
  56. end
  57.  
  58. local function unload(_bKeepOneFuelStack)
  59.     print("Unloading items...")
  60.     --Never hold fuel stack if fuel is infinite
  61.     if turtle.getFuelLevel() == "unlimited" then
  62.         _bKeepOneFuelStack = false
  63.     end
  64.     for n = 1, 16 do
  65.         local nCount = turtle.getItemCount(n)
  66.         if nCount > 0 then
  67.             turtle.select(n)
  68.             local bDrop = true
  69.             if _bKeepOneFuelStack and turtle.refuel(0) then
  70.                 bDrop = false
  71.                 _bKeepOneFuelStack = false
  72.             end
  73.             if bDrop then
  74.                 --First drop into any container above
  75.                 if turtle.detectUp() then
  76.                     turtle.dropUp()
  77.                 end
  78.                 if turtle.getItemCount(n) > 0 then
  79.                     --Then to each side, if there's any left
  80.                     for _ = 1,4 do
  81.                         if turtle.detect() and turtle.getItemCount(n) > 0 then
  82.                             turtle.drop()
  83.                            
  84.                         end
  85.                         turnLeft()
  86.                     end
  87.                 end
  88.                 --finally, if anything remains, just drop it on the ground
  89.                 if turtle.getItemCount(n) > 0 then
  90.                     turtle.drop()
  91.                 end
  92.                
  93.                 unloaded = unloaded + nCount
  94.             end
  95.         end
  96.     end
  97.     collected = 0
  98.     turtle.select(1)
  99. end
  100.  
  101. local function returnSupplies()
  102.     local x, y, z, xd, zd = xPos, depth, zPos, xDir, zDir
  103.     print("Returning to surface...")
  104.     goTo(0, 0, 0, 0, -1)
  105.  
  106.     local fuelNeeded = 3 * (x + y + z) + 1
  107.     if not refuel(fuelNeeded) then
  108.         unload(true)
  109.         print("Waiting for fuel")
  110.         redstone.setOutput("top", true)
  111.         _awaitRefuel()
  112.         redstone.setOutput("top", false)
  113.         unload(true) --prevent >1 stack of fuel from being stored
  114.     else
  115.         unload(true)
  116.     end
  117.    
  118.     if triedTerminate then
  119.         print("Paused at surface. Press 'c' to continue, terminate to exit.")
  120.         repeat
  121.             local evt, c = os.pullEvent("char")
  122.         until evt == "char" and c == "c"
  123.         triedTerminate = false
  124.     end
  125.  
  126.     print("Resuming mining...")
  127.     goTo(x, y, z, xd, zd)
  128. end
  129.  
  130. local function collect()
  131.     local bFull = true
  132.     local nTotalItems = 0
  133.     for n = 1, 16 do
  134.         local nCount = turtle.getItemCount(n)
  135.         if nCount == 0 then
  136.             bFull = false
  137.         end
  138.         nTotalItems = nTotalItems + nCount
  139.     end
  140.    
  141.     if nTotalItems > collected then
  142.         collected = nTotalItems
  143.         if math.fmod(collected + unloaded, 50) == 0 then
  144.             print("Mined " .. collected + unloaded .. " items.")
  145.         end
  146.     end
  147.  
  148.     if bFull then
  149.         print("No empty slots left.")
  150.         return false
  151.     end
  152.     return true
  153. end
  154.  
  155. local function countSlots()
  156.     local slotcount = 0
  157.     for n = 1, 16 do
  158.         if turtle.getItemCount(n) == 0 then
  159.             slotcount = slotcount + 1
  160.         end
  161.     end
  162.     return slotcount
  163. end
  164.  
  165. function refuel(ammount)
  166.     local fuelLevel = turtle.getFuelLevel()
  167.     if fuelLevel == "unlimited" then
  168.         return true
  169.     end
  170.  
  171.     local needed = ammount or xPos + zPos + depth + 64
  172.     if turtle.getFuelLevel() < needed then
  173.         for n = 1, 16 do
  174.             if turtle.getItemCount(n) > 0 then
  175.                 turtle.select(n)
  176.                 if turtle.refuel(1) then
  177.                     while turtle.getItemCount(n) > 0 and turtle.getFuelLevel() < needed do
  178.                         turtle.refuel(1)
  179.                     end
  180.                     if turtle.getFuelLevel() >= needed then
  181.                         turtle.select(1)
  182.                         return true
  183.                     end
  184.                 end
  185.             end
  186.         end
  187.         turtle.select(1)
  188.         return false
  189.     end
  190.  
  191.     return true
  192. end
  193.  
  194. local function fuelCheck()
  195.     if turtle.getFuelLevel() < 16 then
  196.         refuel(16)
  197.     end
  198.     _await(0)
  199. end
  200.  
  201. local function tryForwards()
  202.     if not refuel() then
  203.         print("Not enough Fuel")
  204.         returnSupplies()
  205.     end
  206.  
  207.     while not turtle.forward() do
  208.         if turtle.detect() then
  209.             if turtle.dig() then
  210.                 if not collect() then
  211.                     returnSupplies()
  212.                 end
  213.             else
  214.                 return false
  215.             end
  216.         elseif turtle.attack() then
  217.             if not collect() then
  218.                 returnSupplies()
  219.             end
  220.         else
  221.             _await()
  222.         end
  223.         fuelCheck()
  224.     end
  225.  
  226.     xPos = xPos + xDir
  227.     zPos = zPos + zDir
  228.     return true
  229. end
  230.  
  231. local function tryDown()
  232.     if not refuel() then
  233.         print("Not enough Fuel")
  234.         returnSupplies()
  235.     end
  236.  
  237.     if depth + 1 > maxDepth then
  238.         return false
  239.     end
  240.    
  241.     while not turtle.down() do
  242.         if turtle.detectDown() then
  243.             if turtle.digDown() then
  244.                 if not collect() then
  245.                     returnSupplies()
  246.                 end
  247.             else
  248.                 return false
  249.             end
  250.         elseif turtle.attackDown() then
  251.             if not collect() then
  252.                 returnSupplies()
  253.             end
  254.         else
  255.             _await()
  256.         end
  257.         fuelCheck()
  258.     end
  259.  
  260.     depth = depth + 1
  261.     if math.fmod(depth, 10) == 0 then
  262.         print("Descended " .. depth .. " metres.")
  263.     end
  264.  
  265.     return true
  266. end
  267.  
  268. local function goY(y)
  269.     while depth > y do
  270.         if turtle.up() then
  271.             depth = depth - 1
  272.         elseif turtle.digUp() or turtle.attackUp() then
  273.             collect()
  274.         else
  275.             _await()
  276.         end
  277.         fuelCheck()
  278.     end
  279.    
  280.     while depth < y do
  281.         if turtle.down() then
  282.             depth = depth + 1
  283.         elseif turtle.digDown() or turtle.attackDown() then
  284.             collect()
  285.         else
  286.             _await()
  287.         end
  288.         fuelCheck()
  289.     end
  290. end
  291.  
  292. local function goX(x)
  293.     if xPos > x then
  294.         while xDir ~= -1 do
  295.             turnLeft()
  296.         end
  297.         while xPos > x do
  298.             if turtle.forward() then
  299.                 xPos = xPos - 1
  300.             elseif turtle.dig() or turtle.attack() then
  301.                 collect()
  302.             else
  303.                 _await()
  304.             end
  305.             fuelCheck()
  306.         end
  307.     elseif xPos < x then
  308.         while xDir ~= 1 do
  309.             turnLeft()
  310.         end
  311.         while xPos < x do
  312.             if turtle.forward() then
  313.                 xPos = xPos + 1
  314.             elseif turtle.dig() or turtle.attack() then
  315.                 collect()
  316.             else
  317.                 _await()
  318.             end
  319.             fuelCheck()
  320.         end
  321.     end
  322. end
  323.  
  324. local function goZ(z)
  325.     if zPos > z then
  326.         while zDir ~= -1 do
  327.             turnLeft()
  328.         end
  329.         while zPos > z do
  330.             if turtle.forward() then
  331.                 zPos = zPos - 1
  332.             elseif turtle.dig() or turtle.attack() then
  333.                 collect()
  334.             else
  335.                 _await()
  336.             end
  337.             fuelCheck()
  338.         end
  339.     elseif zPos < z then
  340.         while zDir ~= 1 do
  341.             turnLeft()
  342.         end
  343.         while zPos < z do
  344.             if turtle.forward() then
  345.                 zPos = zPos + 1
  346.             elseif turtle.dig() or turtle.attack() then
  347.                 collect()
  348.             else
  349.                 _await()
  350.             end
  351.             fuelCheck()
  352.         end
  353.     end
  354. end
  355.  
  356. local function goXZ(x,z)
  357.     goZ(z)
  358.     goX(x)
  359. end
  360.  
  361. function goTo(x, y, z, xd, zd)
  362.     if startDepth >= y and depth > startDepth then
  363.         goY(startDepth)
  364.         goXZ(0,0)
  365.         goY(y)
  366.         goXZ(x,z)
  367.     elseif startDepth <= y and depth < startDepth then
  368.         goXZ(0, 0)
  369.         goY(startDepth)
  370.         goXZ(x,z)
  371.         goY(y)
  372.     else
  373.         goXZ(x,z)
  374.         goY(y)
  375.     end
  376.    
  377.     while zDir ~= zd or xDir ~= xd do
  378.         turnLeft()
  379.     end
  380. end
  381.  
  382. -- End of basic functions
  383.  
  384. -- Exit handler stuff
  385. function _tryTerm()
  386.     if triedTerminate then
  387.         _exit()
  388.     else
  389.         triedTerminate = true
  390.         print("Terminate recieved; attempting to return to surface")
  391.         returnSupplies()
  392.     end
  393. end
  394.  
  395. local oldPullEvent = os.pullEvent
  396. os.pullEvent = function(_filter)
  397.     eventData = {os.pullEventRaw(_filter)}
  398.     if eventData[1] == "terminate" then
  399.         _tryTerm()
  400.     end
  401.     return unpack(eventData)
  402. end
  403.  
  404. function _await(s)
  405.     os.startTimer(s or 0.5)
  406.     os.pullEvent("timer")
  407. end
  408.  
  409. function _awaitRefuel()
  410.     local t = triedTerminate
  411.     triedTerminate = true
  412.     repeat
  413.         os.pullEvent("turtle_inventory")
  414.     until refuel(fuelNeeded)
  415.     triedTerminate = t
  416. end
  417.  
  418. function _exit()
  419.     print("Exiting program. Goodbye!")
  420.     os.pullEvent = oldPullEvent
  421.     error()
  422. end
  423.  
  424.  
  425.  
  426. if not refuel(256) then
  427.     print("Waiting for fuel...")
  428.     redstone.setOutput("top", true)
  429.     while not refuel(256) do
  430.         os.pullEvent("turtle_inventory")
  431.     end
  432.     redstone.setOutput("top", false)
  433. end
  434.  
  435. if countSlots() < 15 then
  436.     print("Depositing down to 1 stack of fuel...")
  437.     unload(true)
  438. end
  439.  
  440. print("Excavating...")
  441.  
  442. turtle.select(1)
  443.  
  444. if startDepth > 0 then
  445.     goTo(0, startDepth, 0, 0, 1)
  446. end
  447.  
  448. if wanderDist ~= 0 then
  449.     goTo(0, startDepth, wanderDist, 0, 1)
  450. end
  451.  
  452. local alternate = 0
  453. local done = false
  454. while not done do
  455.     for n = 1, size do
  456.         for _ = 1, size - 1 do
  457.             if not tryForwards() then
  458.                 done = true
  459.                 break
  460.             end
  461.         end
  462.         if done then
  463.             break
  464.         end
  465.         if n < size then
  466.             if math.fmod(n + alternate, 2) == 0 then
  467.                 turnLeft()
  468.                 if not tryForwards() then
  469.                     done = true
  470.                     break
  471.                 end
  472.                 turnLeft()
  473.             else
  474.                 turnRight()
  475.                 if not tryForwards() then
  476.                     done = true
  477.                     break
  478.                 end
  479.                 turnRight()
  480.             end
  481.         end
  482.     end
  483.     if done then
  484.         break
  485.     end
  486.  
  487.     if size > 1 then
  488.         if math.fmod(size, 2) == 0 then
  489.             turnRight()
  490.         else
  491.             if alternate == 0 then
  492.                 turnLeft()
  493.             else
  494.                 turnRight()
  495.             end
  496.             alternate = 1 - alternate
  497.         end
  498.     end
  499.  
  500.     if not tryDown() then
  501.         done = true
  502.         break
  503.     end
  504. end
  505.  
  506. print("Returning to surface...")
  507.  
  508. -- Return to where we started
  509. goTo(0, 0, 0, 0, -1)
  510. unload(false)
  511. goTo(0, 0, 0, 0, 1)
  512.  
  513. print("Mined " .. collected + unloaded .. " items total - Excavate complete.")
Add Comment
Please, Sign In to add comment