krom

MineCraft - Mining Excavate+

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