krom

Excav3alpha

Mar 26th, 2019
132
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. -- Author: KROM
  2. --
  3. -- NOTE: This is still buggy, turtle might run off :|
  4. --
  5. -- v0.1 - first code
  6. -- v0.2 - added cave mode, x|y can be set independently
  7. -- v0.2a - disabled rednet
  8. --
  9. -- known bugs:
  10. -- * moves one step to far on y, when resuming after abort on 1st floor.
  11. -- * x/y dimensions need to be uneven
  12. -- * calc. of energy requirement somewhat strange/not exact
  13. -- * reserved slots not implemented
  14. -- --------------------------------
  15. local sBotLabel = "MiningBot 01"
  16. -- those are reserved at end of inventory
  17. local nReservedSlots = 2
  18. -- where's the fuel?
  19. local nBatterySlot = 1
  20. -- set this to ID of master computer
  21. -- get id by: lua(); os.getComputerID(); exit();
  22. local nMasterComputerID = 31
  23. -- when should me unloadz?
  24. local nEmptySlotsMargin = 1
  25.  
  26. -- internal vars
  27. local nRuns    = 0
  28. local nEnergy  = 0
  29. local nEnergySafetyMargin = 30
  30. local bNoError = true
  31. local bRedNet = false
  32. local nRadius   = 0 -- should be obsolete
  33. local nMaxDepth = 0
  34. local bResume   = false
  35. local startX,startY,startZ = 0,0,0
  36. local currentX,currentY,currentZ = 0,0,0
  37. local nDepth    = 0
  38. local nMined    = 0
  39. local stopCause = 0
  40. local xDir,yDir = 0,-1
  41. local nDigDir   = -1 -- -1 = down, 1 = up
  42. local nRadiusX, nRadiusY = 0,0
  43. local tmpDepth = -1 -- backup, when returning home
  44. -- ----------------------------------------------------------
  45. function saySingle(str)
  46.     write(str)
  47. end
  48. -- ----------------------------------------------------------
  49. local function say(message)
  50.     if bRedNet == true then
  51.         rednet.send(nMasterComputerID, message)
  52.     end
  53.     print(message)
  54.     -- sleep(0.2)
  55. end
  56. -- ----------------------------------------------------------
  57. local function turnLeft()
  58.     turtle.turnLeft()
  59.     xDir, yDir = -yDir, xDir
  60. end
  61. -- ----------------------------------------------------------
  62. local function turnRight()
  63.     turtle.turnRight()
  64.     xDir, yDir = yDir, -xDir
  65. end
  66. -- ----------------------------------------------------------
  67. local function recharge()
  68.     say("trying to recharge")
  69.     turtle.select(nBatterySlot)
  70.     local e = turtle.getFuelLevel()
  71.     turtle.refuel()
  72.     nEnergy = turtle.getFuelLevel()
  73.     say("fuel: "..e.." -> "..nEnergy)
  74.     if nEnergy > e then
  75.         return true
  76.     end
  77.     return false
  78. end
  79. -- ----------------------------------------------------------
  80. local function unloadCargo()
  81.     local ende = 16 - nReservedSlots
  82.     for invloop=1,16 do
  83.         if invloop ~= nBatterySlot then
  84.             -- say("Drop item in Slot "..invloop)
  85.             turtle.select(invloop)
  86.             turtle.drop()
  87.         end
  88.     end
  89. end
  90. -- ----------------------------------------------------------
  91. local function getFreeSlots()
  92.     local nSpace = 0
  93.     for invloop=1,16 do
  94.         local items = turtle.getItemCount(invloop)
  95.         if items == 0 then
  96.             nSpace = nSpace + 1
  97.         end
  98.     end
  99.     return nSpace
  100. end
  101. -- ----------------------------------------------------------
  102. local function collect()
  103.     nMined = nMined + 1
  104.     if math.fmod(nMined, 25) == 0 then
  105.         say( "Mined "..nMined.." blocks." )
  106.     end
  107.    
  108.     if getFreeSlots() > 0 then
  109.         return true
  110.     end
  111.    
  112.     say( "No empty slots left." )
  113.     return false
  114. end
  115. -- ----------------------------------------------------------
  116. local function attackMode()
  117.     local bAttacked = false
  118.     while turtle.attack() do
  119.         say("Attacking!!1")
  120.         bAttacked = true
  121.     end
  122.     return bAttacked
  123. end
  124. -- ----------------------------------------------------------
  125. local function tryForwards()
  126.  
  127.     local nMaxTries = 10
  128.     local nTries = 0
  129.  
  130.     stopCause = 0
  131.  
  132.     while not turtle.forward() do
  133.         if nTries > 0 then
  134.             say("Try to move forward, "..nTries.." try.")
  135.         end
  136.         if turtle.dig() then
  137.             if not collect() then
  138.                 say("abort reason 2")
  139.                 stopCause = 2
  140.                 return false
  141.             end
  142.         else
  143.             if attackMode() then
  144.                 -- attacking should not reduce tries
  145.                 nTries = nTries - 1
  146.                 if nTries < 0 then
  147.                     nTries = 0
  148.                 end
  149.             end
  150.         end
  151.  
  152.         -- give sand a chance to fall
  153.         sleep(0.8)
  154.         nTries = nTries + 1
  155.         if nTries >= nMaxTries then
  156.             say("abort reason 2")
  157.             return false
  158.         end
  159.     end
  160.     --xPos = xPos + xDir
  161.     --zPos = zPos + zDir   
  162.     return true
  163. end
  164. -- ----------------------------------------------------------
  165. local function tryDown()
  166.     stopCause = 0
  167.     if currentZ == nMaxDepth then
  168.         say("tryDown: already at max depth")
  169.         return false
  170.     end
  171.  
  172.     if not turtle.down() then
  173.         if turtle.digDown() then
  174.             if not collect() then
  175.                 stopCause = 2
  176.                 return false
  177.             end
  178.         end
  179.         if not turtle.down() then
  180.             stopCause = 1
  181.             return false
  182.         end
  183.     end
  184.    
  185.     currentZ = currentZ + 1
  186.  
  187.     --if math.fmod( nDepth, 10 ) == 0 then
  188.     say( ">>> Descended "..currentZ.." metres. <<<" )
  189.  
  190.     return true
  191. end
  192. -- ----------------------------------------------------------
  193. local function tryUp()
  194.     stopCause = 0
  195.     if currentZ == nMaxDepth then
  196.         say("tryDown: already at max depth")
  197.         return false
  198.     end
  199.  
  200.     if not turtle.up() then
  201.         if turtle.digUp() then
  202.             if not collect() then
  203.                 stopCause = 2
  204.                 return false
  205.             end
  206.         end
  207.         if not turtle.up() then
  208.             stopCause = 1
  209.             return false
  210.         end
  211.     end
  212.    
  213.     currentZ = currentZ + 1
  214.  
  215.     --if math.fmod( nDepth, 10 ) == 0 then
  216.     say( ">>> Ascended "..currentZ.." metres. <<<" )
  217.  
  218.     return true
  219. end
  220. -- ----------------------------------------------------------
  221.  
  222. -- ----------------------------------------------------------
  223. -- S T A R T
  224. -- ----------------------------------------------------------
  225.  
  226. say("Mining Bot v0.1 - Welcome!")
  227. say("Turtle "..sBotLabel.." ready for action.")
  228. say("")
  229. saySingle("Radius Y (forward, uneven): ")
  230. nRadiusY = read()
  231. saySingle("Radius X (to the right, uneven, Y default): ")
  232. nRadiusX = read()
  233. saySingle("Radius Z (up/down): ")
  234. nMaxDepth = read()
  235. saySingle("Dig (d)own or (u)p? (default down) ")
  236. nDigDir = read()
  237. saySingle("Is this a resume? (y/n): ")
  238. bResume = read()
  239.  
  240. -- todo: verify input. for now just convert
  241. -- nRadius = tonumber( nRadius )
  242. nMaxDepth = tonumber( nMaxDepth )
  243. if bResume == "y" then
  244.     bResume = true
  245. else
  246.     bResume = false
  247. end
  248. if nMaxDepth < 1 then
  249.     say("Depth provided too shallow" )
  250.     return
  251. end
  252.  
  253. nRadiusX = tonumber( nRadiusX )
  254. if nRadiusX == 0 then
  255.     nRadiusX = nRadiusY
  256. end
  257.  
  258. if nDigDir ~= nil then
  259.     if nDigDir == "u" then
  260.         nDigDir = 1
  261.     else
  262.         nDigDir = -1
  263.     end
  264. else
  265.     nDigDir = -1
  266. end
  267.  
  268.  
  269. -- Repeat what we understood
  270. say("I should mine in a radius of "..nRadiusX..","..nRadiusY.."to a nDepth of "..nMaxDepth)
  271. if bResume == true then
  272.     say("This is a resume operation")
  273. else
  274.     say("This is not a resume operation")
  275. end
  276.  
  277. -- ----------------------------------------------------------
  278.  
  279. -- -------------------------
  280. -- init wireless
  281. ----------------------------
  282. -- bRedNet = rednet.open("right")
  283. -- if bRedNet ~= true then
  284. --  bRedNet = rednet.open("left")
  285. -- end
  286. bRedNet = false
  287. if bRedNet == true then
  288.     say("Rednet enabled")
  289.     rednet.send(nMasterComputerID, sBotLabel.." reporting in.")
  290. else
  291.     say("no rednet available")
  292. end
  293.  
  294.  
  295. -- ----------------------------------------------------------
  296. local function isOperational()
  297.  
  298.     -- get energy
  299.     local nEnergyLevel = turtle.getFuelLevel()
  300.     -- get needed energy for way back home
  301.     local nSteps = currentX + currentY + currentZ
  302.     local required = 0
  303.    
  304.     if nEnergyLevel < nSteps then
  305.         say("ALERT: Not enough energy to return home.")
  306.         say("Current Energy: "..nEnergyLevel.."E")
  307.         say("Needed :"..nSteps.."E")
  308.         say("We will do what we can... :-/")
  309.         return false
  310.     end
  311.     --   y*(x + 2) for movement
  312.     required = required + (nRadiusX * (nRadiusY+2))
  313.     -- + (x*y) for dig
  314.     required = required + (nRadiusX * nRadiusY)
  315.     -- + energy for way back home
  316.     required = required + nSteps
  317.     -- + safety margin
  318.     required = required + nEnergySafetyMargin
  319.     -- = energy requirement
  320.     say("Energy: "..required.."E req. "..nEnergyLevel.."E avail.")
  321.  
  322.     if nEnergyLevel <= required then
  323.         say("Not enough energy for a full cycle.")
  324.         -- Try to recharge
  325.         if recharge() == true then
  326.             -- recheck energy
  327.             if nEnergyLevel <= required then
  328.                 say("Still not enough energy for a full cycle.")
  329.                 return false
  330.             end
  331.         else
  332.             -- failed to recharge, abort.
  333.             say("Could not recharge.")
  334.             return false
  335.         end
  336.     end
  337.  
  338.     -- check inventory
  339.     local emptySlots = getFreeSlots()  
  340.     if emptySlots < nEmptySlotsMargin then
  341.         say(emptySlots.." Slots left. Need "..nEmptySlotsMargin)
  342.         return false
  343.     end
  344.  
  345.     -- all cool
  346.     return true
  347. end
  348. -- ----------------------------------------------------------
  349. local function saveStatus()
  350.     -- save which depth we have been on
  351.     -- for sake of simplicity, we will restart on that layer
  352.     -- when resuming, not returning to exact last position.
  353.     tmpDepth = currentZ
  354. end
  355. -- ----------------------------------------------------------
  356. local function waitForEnergy()  
  357.     local count = 0
  358.     local hasEnergy = false
  359.     say("Waiting for energy in Slot "..nBatterySlot)
  360.  
  361.     while not hasEnergy do
  362.         if recharge() == true then
  363.             hasEnergy = true
  364.             return true
  365.         else
  366.             sleep(5)
  367.             count = count + 1
  368.             if count == 5 then
  369.                 say("Waiting for energy in Slot "..nBatterySlot)
  370.                 count = 0
  371.             end
  372.         end
  373.     end
  374.     return true
  375. end
  376. -- ----------------------------------------------------------
  377. local function goHome(vDir, bResume)
  378.     say("Going Home :)")
  379.  
  380.     say("Dir: "..xDir..","..yDir)
  381.  
  382.     -- needs to face left
  383.     if yDir == -1 then
  384.         if xDir == 1 then
  385.             turnRight()
  386.         elseif xDir == -1 then
  387.             turnLeft()
  388.         else
  389.             turnLeft()
  390.             turnLeft()
  391.         end
  392.     elseif yDir == 0 then
  393.         if xDir > 0 then
  394.             turnLeft()
  395.         else
  396.             turnRight()
  397.         end
  398.     elseif xDir > 0 or xDir < 0 then
  399.         if xDir > 0 then
  400.             turnRight()
  401.         else
  402.             turnLeft()
  403.         end
  404.     end
  405.  
  406.     -- if energy too low, go to a wait-for-recharge loop
  407.     nEnergy = turtle.getFuelLevel()
  408.     if nEnergy < 5 then
  409.         waitForEnergy()
  410.     end
  411.  
  412.     say("I am at "..currentX..","..currentY..","..currentZ)
  413.  
  414.     if nDigDir == 1 then
  415.         while currentZ > 0 do
  416.             if not turtle.down() then
  417.                 say("ALERT: Failed to move down while returning")
  418.                 return false
  419.             end
  420.             currentZ = currentZ - 1
  421.         end
  422.     else
  423.         while currentZ > 0 do
  424.             if not turtle.up() then
  425.                 say("ALERT: Failed to move up while returning")
  426.                 return false
  427.             end
  428.             currentZ = currentZ - 1
  429.         end
  430.     end
  431.  
  432.     if currentX > 0 then
  433.         turnRight()
  434.         while currentX > 0 do
  435.             if not tryForwards() then
  436.                 say("ALERT: Failed to move forward(X) while returning")
  437.                 return false
  438.             end
  439.             currentX = currentX - 1
  440.         end
  441.         turnLeft()
  442.     end
  443.  
  444.     while currentY > 0 do
  445.         if not tryForwards() then
  446.             say("ALERT: Failed to move forward(Y) while returning")
  447.             return false
  448.         end
  449.         currentY = currentY - 1
  450.     end
  451.  
  452.     say("Should be at home. hopefully. :)")
  453.     return true
  454. end
  455. -- ----------------------------------------------------------
  456. local function waitForInput()
  457.     local id,message,distance = rednet.receive(0.05)
  458.     if id ~= nil then
  459.         if message == "terminate" then
  460.             say("Message: Terminate")
  461.             exit()
  462.         elseif message == "home" then
  463.             say("Message: Go home")
  464.             goHome()
  465.             exit()
  466.         end
  467.     end
  468. end
  469. -- ----------------------------------------------------------
  470. -- 0 = normal, like 1st layer
  471. -- 1 = reverse direction, every 2nd layer
  472. layerdirection = 1
  473. startX,startY,startZ = 0,0,0
  474. local v
  475.  
  476. local function work(nHowDeep, nSizeX, nSizeY, nDir)
  477.     local depth,x,y
  478.     local startZ = currentZ
  479. say("StartZ: "..startZ)
  480.  
  481.     local bFirstLoop = false
  482.  
  483.     for depth=startZ,nHowDeep do
  484.  
  485.         -- full check each layer
  486.         if not isOperational() then
  487.             say("Depth-Check: returning home")
  488.             saveStatus()
  489.             goHome(v, true)
  490.             return true
  491.         end
  492.  
  493.         for x=0,(nSizeX-1) do
  494.  
  495.             -- waitForInput()
  496.  
  497.             -- first row has no turn move
  498.             -- which needs to be offset
  499.             local startY = 1
  500.  
  501.             if x == 0 and startZ == 0 and depth == 0 then
  502.                 startY = 0
  503.             elseif bFirstLoop == true then
  504.                 startY = 0
  505.             end
  506.  
  507.             if x == 0 then
  508.                 say("SY: "..startY)
  509.             end
  510.  
  511.             for y=startY,(nSizeY-1) do
  512.  
  513.                 local start = currentX..","..currentY..","..currentZ
  514.                
  515.                 v = math.fmod(x,2)
  516.                 -- v == 0 = facing away. like start
  517.                 -- v == 1 = facing to start
  518.                 -- say("V: "..v.." LD: "..layerdirection.." SY: "..startY.." xyz: "..x..","..y..","..depth)
  519.  
  520.  
  521.                 -- checks
  522.                 -- simple inventory check here
  523.                 local emptySlots = getFreeSlots()
  524.                 if emptySlots < nEmptySlotsMargin then
  525.                     say(emptySlots.." Slots left. Need "..nEmptySlotsMargin)
  526.                     saveStatus()
  527.                     goHome(v, true)
  528.                     return true
  529.                 end
  530.  
  531.                 if not tryForwards() then
  532.                     if stopCause == 2 then
  533.                         -- inventory full?!
  534.                         say("Failed to move forward. Inv. full?!")
  535.                         saveStatus()
  536.                         goHome(v, true)
  537.                         return true
  538.                     else
  539.                         say("Failed to move forward.")
  540.                         saveStatus()
  541.                         goHome(v, false)
  542.                         return false
  543.                     end
  544.                 end
  545.  
  546.                 if layerdirection == 1 then
  547.                     if v == 0 then
  548.                         currentY = currentY + 1
  549.                     else
  550.                         currentY = currentY - 1
  551.                     end
  552.                 else
  553.                     if v == 0 then
  554.                         currentY = currentY - 1
  555.                     else
  556.                         currentY = currentY + 1
  557.                     end
  558.                 end
  559.  
  560.                 -- say("P: "..start.." -> "..currentX..","..currentY..","..currentZ)
  561.                 -- say("Dir: "..xDir..","..yDir)
  562.             -- end y loop
  563.             end
  564.  
  565.             bFirstLoop = false;
  566.  
  567.             say("completed one line")
  568.  
  569.             -- if not on last line
  570.             if  x < nSizeX-1 then
  571.                 -- move to next line (turn, move, turn)
  572.                 if v == 0 then
  573.  
  574.                     say("Moving to next row (1)")
  575.                     turnRight()
  576.                     -- to be on the safe side:
  577.                     if not isOperational() then
  578.                         saveStatus()
  579.                         goHome(v, true)
  580.                         return true
  581.                     end
  582.  
  583.                     if not tryForwards() then
  584.  
  585.                         if stopCause == 2 then
  586.                             -- inventory full?!
  587.                             say("Failed to move forward. Inv. full?!")
  588.                             saveStatus()
  589.                             goHome(v, true)
  590.                             return true
  591.                         else
  592.                             saveStatus()
  593.                             goHome(v, false)
  594.                             return false
  595.                         end                    
  596.                     end
  597.  
  598.                     turnRight()
  599.                 else
  600.                     say("Moving to next row (2)")
  601.                     turnLeft()
  602.  
  603.                     -- to be on the safe side:
  604.                     if not isOperational() then
  605.                         saveStatus()
  606.                         goHome(v, true)
  607.                         return true
  608.                     end
  609.  
  610.                     if not tryForwards() then
  611.                         if stopCause == 2 then
  612.                             -- inventory full?!
  613.                             say("Failed to move forward. Inv. full?!")
  614.                             saveStatus()
  615.                             goHome(v, true)
  616.                             return true
  617.                         else
  618.                             saveStatus()
  619.                             goHome(v, false)
  620.                             return false
  621.                         end
  622.                     end
  623.  
  624.                     turnLeft()
  625.                 end
  626.  
  627.                 if layerdirection == 1 then
  628.                     currentX = currentX + 1
  629.                 else
  630.                     currentX = currentX - 1
  631.                 end
  632.             end
  633.  
  634.  
  635.         -- end x loop
  636.         end
  637.  
  638.         say("completed one layer")
  639.  
  640.         -- checks if depth reached
  641.         if depth < nHowDeep then
  642.  
  643.             if nDir == 1 then
  644.                 if not tryUp() then
  645.                     -- unable to move down?
  646.                     -- assume we hit bedrock
  647.                     goHome(v, false)
  648.                     return true
  649.                 end
  650.             else
  651.                 if not tryDown() then
  652.                     -- unable to move down?
  653.                     -- assume we hit bedrock
  654.                     goHome(v, false)
  655.                     return true
  656.                 end
  657.             end
  658.  
  659.             if layerdirection == 1 then
  660.                 layerdirection = 0
  661.             else
  662.                 layerdirection = 1
  663.             end
  664.  
  665.             turnLeft()
  666.             turnLeft()
  667.         else
  668.             say("finished all layer")
  669.             -- finished
  670.             saveStatus()
  671.             goHome(v, false)
  672.             return true
  673.         end
  674.         -- end z loop
  675.     end
  676.     say("should not hit this code line")
  677. end
  678. -- ----------------------------------------------------------
  679. local function resume()
  680.     local depthcounter = 0
  681.  
  682.     -- move away from start
  683.     tryForwards()
  684.     currentY = currentY + 1
  685.  
  686.     -- if tmpZ isgiven, go down to that Z
  687.     if tmpDepth == -1 then
  688.         if nDigDir == 1 then
  689.             while turtle.up() == true do
  690.                 depthcounter = depthcounter + 1
  691.             end
  692.             say("Resume: We hit ceiling at "..depthcounter)
  693.         else
  694.             while turtle.down() == true do
  695.                 depthcounter = depthcounter + 1
  696.             end
  697.             say("Resume: We hit ground at "..depthcounter)
  698.         end
  699.         -- find ground
  700.         currentZ = depthcounter
  701.     else
  702.         -- resuming last position
  703.         while depthcounter < tmpDepth do
  704.  
  705.             if nDigDir == 1 then
  706.                 if turtle.up() == true then
  707.                     depthcounter = depthcounter + 1
  708.                 else
  709.                     -- we hit something.
  710.                     say("We hit something while going up.")
  711.                     say("Starting a new, full cycle at this position.")
  712.                     currentZ = depthcounter
  713.                     return
  714.                 end
  715.             else
  716.                 if turtle.down() == true then
  717.                         depthcounter = depthcounter + 1
  718.                 else
  719.                     -- we hit something.
  720.                     say("We hit something while going down.")
  721.                     say("Starting a new, full cycle at this position.")
  722.                     currentZ = depthcounter
  723.                     return
  724.                 end
  725.             end
  726.         end
  727.         currentZ = depthcounter
  728.     end
  729. end
  730.  
  731. -- ----------------------------------------------------------
  732. -- END MAIN LOOP FUNCTION
  733. -- ----------------------------------------------------------
  734.  
  735.  
  736. local done = false
  737.  
  738. while not done do
  739.  
  740.     sleep(5)
  741.  
  742.     -- determine min. energy for next cycle
  743.     local required = 0
  744.     -- z for going back down
  745.     required = required + tmpDepth
  746.     -- + enough for at least two full layers
  747.     required = required + (2 * (nRadiusX * (nRadiusY+2)))
  748.     required = required + (2 * (nRadiusX * nRadiusY))
  749.     -- + energy for way back home
  750.     required = required + (nRadiusX + nRadiusY + nMaxDepth)
  751.     -- + safety margin
  752.     required = required + nEnergySafetyMargin
  753.     nEnergy = turtle.getFuelLevel()
  754.     say("Need about "..required.."E for resuming. Have: "..nEnergy.."E")
  755.  
  756.     -- recharge if needed.
  757.     while nEnergy < required do
  758.         if not recharge() then
  759.             waitForEnergy()
  760.         end
  761.     end
  762.  
  763.     -- first run, still in original position
  764.     -- fill face other direction when returning
  765.     if tmpDepth == -1 then
  766.         turnLeft()
  767.         turnLeft()
  768.     end
  769.    
  770.     -- unload cargo
  771.     say("Unloading Cargo")
  772.     unloadCargo()
  773.  
  774.     turnLeft()
  775.     turnLeft()
  776.  
  777.     -- reset vars
  778.     layerdirection = 1
  779.     startX,startY,startZ = 0,0,0
  780.  
  781.     -- if resuming by prompt or resuming running operation
  782.     if bResume == true or tmpDepth > -1 then
  783.         resume()
  784.     end
  785.  
  786.     -- start normal operation
  787.     local status = work(nMaxDepth, nRadiusX, nRadiusY, nDigDir)
  788.  
  789.     if not status then
  790.         -- either something went wrong, or we have finished
  791.         done = true
  792.  
  793.         if tmpDepth == nMaxDepth then
  794.             say("**** Successfully finished ****")
  795.         else
  796.             say("Something went wrong")
  797.         end
  798.     else
  799.         -- we assume a successful cycle.
  800.         say("Finished a successful cycle")     
  801.         if tmpDepth == nMaxDepth then
  802.             done = true
  803.             say("**** Successfully finished ****")
  804.             say("Unloading Cargo")
  805.             unloadCargo()
  806.             turnLeft()
  807.             turnLeft()
  808.         else
  809.             -- resume
  810.             say("Resuming")
  811.         end
  812.     end
  813.     nRuns = nRuns + 1
  814. end
  815.  
  816. say( "Mined "..nMined.." blocks total in "..nRuns.." runs." )
Add Comment
Please, Sign In to add comment