daoek

smartQuary computercraft

Jul 23rd, 2025
373
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 16.89 KB | Software | 0 0
  1. local function TurtleState()
  2.     local x, y, z = 0, 0, 0
  3.     local dir = "n"
  4.     local path = "/data/turtleState.json"
  5.  
  6.     local function load()
  7.         if not fs.exists("/data") then
  8.             fs.makeDir("/data")
  9.         end
  10.  
  11.         if fs.exists(path) then
  12.             local file = fs.open(path, "r")
  13.             local data = textutils.unserializeJSON(file.readAll())
  14.             file.close()
  15.             x = data.x or 0
  16.             y = data.y or 0
  17.             z = data.z or 0
  18.             dir = data.dir or "n"
  19.         end
  20.     end
  21.  
  22.     local function save(newX, newY, newZ, newDir)
  23.         x = newX or x
  24.         y = newY or y
  25.         z = newZ or z
  26.         dir = newDir or dir
  27.  
  28.         local file = fs.open(path, "w")
  29.         file.write(textutils.serializeJSON({
  30.             x = x,
  31.             y = y,
  32.             z = z,
  33.             dir = dir
  34.         }))
  35.         file.close()
  36.     end
  37.  
  38.     local function get()
  39.         return x, y, z, dir
  40.     end
  41.  
  42.     load()
  43.  
  44.     return {
  45.         load = load,
  46.         save = save,
  47.         get = get
  48.     }
  49. end
  50.  
  51. dirIndex = { n = 0, e = 1, s = 2, w = 3 }
  52. dirNames = { "n", "e", "s", "w" }
  53.  
  54. turtleState = TurtleState()
  55. x, y, z, dir = turtleState.get()
  56.  
  57. local function refuelAll(limit)
  58.     if turtle.getFuelLevel() < limit then
  59.         for i = 1, 16, 1 do
  60.             turtle.select(i)
  61.             turtle.refuel()
  62.         end
  63.     end
  64. end
  65.  
  66. local function resetState()
  67.     x, y, z, dir = 0, 0, 0, "n"
  68.     turtleState.save(x, y, z, dir)
  69.     print("Turtle state reset to 0, 0, 0, facing north.")
  70. end
  71.  
  72. local function isOre(dir)
  73.     local inspectFn
  74.  
  75.     if dir == "" or dir == "forward" then
  76.         inspectFn = turtle.inspect
  77.     elseif dir == "up" then
  78.         inspectFn = turtle.inspectUp
  79.     elseif dir == "down" then
  80.         inspectFn = turtle.inspectDown
  81.     else
  82.         error("Invalid direction: expected '', 'forward', 'up', or 'down'", 2)
  83.     end
  84.  
  85.     local success, data = inspectFn()
  86.     if not success or not data.name then
  87.         return false
  88.     end
  89.  
  90.     local name = data.name
  91.  
  92.     local blacklist = {
  93.         "grass", "stone", "dirt", "gravel",
  94.         "obsidian", "water", "lava", "bedrock", "turtle", "chest", "sand", "cactus"
  95.     }
  96.  
  97.     for _, bad in ipairs(blacklist) do
  98.         if name:find(bad) then
  99.             return false
  100.         end
  101.     end
  102.  
  103.     return true
  104. end
  105.  
  106. local function isInventoryFull()
  107.     for i = 1, 16 do
  108.         if turtle.getItemCount(i) == 0 then
  109.             return false
  110.         end
  111.     end
  112.     return true
  113. end
  114.  
  115. local function dumpInventory(dir)
  116.     local dropFn
  117.  
  118.     if dir == "" or dir == "forward" then
  119.         dropFn = turtle.drop
  120.     elseif dir == "up" then
  121.         dropFn = turtle.dropUp
  122.     elseif dir == "down" then
  123.         dropFn = turtle.dropDown
  124.     else
  125.         error("Invalid direction: must be '', 'up', or 'down'", 2)
  126.     end
  127.  
  128.     for i = 1, 16 do
  129.         turtle.select(i)
  130.         dropFn()
  131.     end
  132.  
  133.     turtle.select(1) -- Restore selection
  134. end
  135.  
  136. local function SmartDig(dir)
  137.  
  138.     local digFunction, inspectFunction, attempts
  139.  
  140.     if dir == "" or dir == "forward" then
  141.         digFunction = turtle.dig
  142.         inspectFunction = turtle.inspect
  143.     elseif dir == "up" then
  144.         digFunction = turtle.digUp
  145.         inspectFunction = turtle.inspectUp
  146.     elseif dir == "down" then
  147.         digFunction = turtle.digDown
  148.         inspectFunction = turtle.inspectDown
  149.     else
  150.         error("Invalid direction: expected '', 'forward', 'up', or 'down'", 2)
  151.     end
  152.  
  153.     attempts = 2
  154.  
  155.     local function DigFallingEntity()
  156.         while digFunction() do
  157.             os.sleep(0.5)
  158.         end
  159.     end
  160.  
  161.     local function DigNormal()
  162.         digFunction()
  163.     end
  164.  
  165.     while attempts > 0 do
  166.         local success, data = inspectFunction()
  167.         if not success then
  168.             return
  169.         end
  170.  
  171.         local name = data.name or ""
  172.         if name:find("gravel") or name:find("sand") then
  173.             DigFallingEntity()
  174.         elseif name:find("turtle") or name:find("lava") or name:find("water") or name:find("bedrock") then
  175.             return
  176.         else  
  177.             DigNormal()
  178.         end
  179.  
  180.         -- Check again in case something fell
  181.         local again, newData = inspectFunction()
  182.  
  183.         if again then
  184.             attempts = attempts - 1
  185.         else
  186.             return
  187.         end
  188.     end
  189. end
  190.  
  191. local function forward()
  192.     SmartDig("forward")
  193.  
  194.     if turtle.forward() then
  195.         if dir == "n" then
  196.             z = z - 1
  197.         elseif dir == "s" then
  198.             z = z + 1
  199.         elseif dir == "e" then
  200.             x = x + 1
  201.         elseif dir == "w" then
  202.             x = x - 1
  203.         end
  204.  
  205.         turtleState.save(x, y, z, dir)
  206.         return true
  207.     end
  208.  
  209.     return false
  210. end
  211.  
  212. local function back()
  213.     if turtle.back() then
  214.         if dir == "n" then
  215.             z = z + 1
  216.         elseif dir == "s" then
  217.             z = z - 1
  218.         elseif dir == "e" then
  219.             x = x - 1
  220.         elseif dir == "w" then
  221.             x = x + 1
  222.         end
  223.  
  224.         turtleState.save(x, y, z, dir)
  225.         return true
  226.     end
  227.  
  228.     return false
  229. end
  230.  
  231. local function up()
  232.     SmartDig("up")
  233.     if turtle.up() then
  234.         y = y + 1
  235.         turtleState.save(x, y, z, dir)
  236.         return true
  237.     end
  238.  
  239.     return false
  240. end
  241.  
  242. local function down()
  243.  
  244.     SmartDig("down")
  245.  
  246.     if turtle.down() then
  247.         y = y - 1
  248.         turtleState.save(x, y, z, dir)
  249.         return true
  250.     end
  251.  
  252.     return false
  253. end
  254.  
  255. local function turnLeft()
  256.     turtle.turnLeft()
  257.     local idx = (dirIndex[dir] - 1) % 4
  258.     dir = dirNames[idx + 1]
  259.     turtleState.save(x, y, z, dir)
  260. end
  261.  
  262. local function turnRight()
  263.     turtle.turnRight()
  264.     local idx = (dirIndex[dir] + 1) % 4
  265.     dir = dirNames[idx + 1]
  266.     turtleState.save(x, y, z, dir)
  267. end
  268.  
  269. local function turnToDirection(desiredDir)
  270.     if dir == desiredDir then return end
  271.  
  272.     local current = dirIndex[dir]
  273.     local target = dirIndex[desiredDir]
  274.     local diff = (target - current) % 4
  275.  
  276.     if diff == 1 then
  277.         turnRight()
  278.     elseif diff == 2 then
  279.         turnRight()
  280.         turnRight()
  281.     elseif diff == 3 then
  282.         turnLeft()
  283.     end
  284. end
  285.  
  286. local function moveToLocation(desiredX, desiredY, desiredZ)
  287.     -- Move vertically first (Y axis)
  288.     while y < desiredY do
  289.         if not up() then return false end
  290.     end
  291.     while y > desiredY do
  292.         if not down() then return false end
  293.     end
  294.  
  295.     -- Move along X axis
  296.     if desiredX > x then
  297.         turnToDirection("e")
  298.         while x < desiredX do
  299.             if not forward() then return false end
  300.         end
  301.     elseif desiredX < x then
  302.         turnToDirection("w")
  303.         while x > desiredX do
  304.             if not forward() then return false end
  305.         end
  306.     end
  307.  
  308.     -- Move along Z axis
  309.     if desiredZ > z then
  310.         turnToDirection("s")
  311.         while z < desiredZ do
  312.             if not forward() then return false end
  313.         end
  314.     elseif desiredZ < z then
  315.         turnToDirection("n")
  316.         while z > desiredZ do
  317.             if not forward() then return false end
  318.         end
  319.     end
  320.  
  321.     return true
  322. end
  323.  
  324. local function removeDataFromArray(array, data)
  325.     local foundIndex = -1
  326.    
  327.     for i, v in ipairs(array) do
  328.         if data == v then
  329.             foundIndex = i
  330.         end
  331.     end
  332.  
  333.     if foundIndex ~= -1 then
  334.         table.remove(array, foundIndex)
  335.     end
  336.  
  337. end
  338.  
  339. local function doesArrayContain(array, data)
  340.     for i, v in ipairs(array) do
  341.         if data == v then
  342.             return true
  343.         end
  344.     end
  345.  
  346.     return false
  347. end
  348.  
  349. local function createPositionKey(x, y, z)
  350.     return string.format("%d,%d,%d", x, y, z)
  351. end
  352.  
  353. local function getPositionKeyWithDirection(relativeDir)
  354.     local dx, dy, dz = 0, 0, 0
  355.  
  356.     if relativeDir == "up" then
  357.         dy = 1
  358.     elseif relativeDir == "down" then
  359.         dy = -1
  360.     elseif relativeDir == "forward" then
  361.         if dir == "n" then dz = -1
  362.         elseif dir == "s" then dz = 1
  363.         elseif dir == "e" then dx = 1
  364.         elseif dir == "w" then dx = -1 end
  365.     elseif relativeDir == "back" then
  366.         if dir == "n" then dz = 1
  367.         elseif dir == "s" then dz = -1
  368.         elseif dir == "e" then dx = -1
  369.         elseif dir == "w" then dx = 1 end
  370.     elseif relativeDir == "left" then
  371.         if dir == "n" then dx = -1
  372.         elseif dir == "s" then dx = 1
  373.         elseif dir == "e" then dz = -1
  374.         elseif dir == "w" then dz = 1 end
  375.     elseif relativeDir == "right" then
  376.         if dir == "n" then dx = 1
  377.         elseif dir == "s" then dx = -1
  378.         elseif dir == "e" then dz = 1
  379.         elseif dir == "w" then dz = -1 end
  380.     else
  381.         error("Invalid direction for getPositionKeyWithDirection: " .. tostring(relativeDir))
  382.     end
  383.  
  384.     return createPositionKey(x + dx, y + dy, z + dz)
  385. end
  386.  
  387. local function smartMineOreVeinWorker(noOreDetected, oreDetected, backTrackLog)
  388.  
  389.     local targetPos = getPositionKeyWithDirection("forward")
  390.     if not doesArrayContain(noOreDetected, targetPos) and not doesArrayContain(oreDetected, targetPos) then
  391.         if isOre("forward") then
  392.             table.insert(oreDetected, targetPos)
  393.         else
  394.             table.insert(noOreDetected, targetPos)
  395.         end
  396.     end
  397.  
  398.     targetPos = getPositionKeyWithDirection("down")
  399.     if not doesArrayContain(noOreDetected, targetPos) and not doesArrayContain(oreDetected, targetPos) then
  400.         if isOre("down") then
  401.             table.insert(oreDetected, targetPos)
  402.         else
  403.             table.insert(noOreDetected, targetPos)
  404.         end
  405.     end
  406.  
  407.     targetPos = getPositionKeyWithDirection("up")
  408.     if not doesArrayContain(noOreDetected, targetPos) and not doesArrayContain(oreDetected, targetPos) then
  409.         if isOre("up") then
  410.             table.insert(oreDetected, targetPos)
  411.         else
  412.             table.insert(noOreDetected, targetPos)
  413.         end
  414.     end
  415.  
  416.     targetPos = getPositionKeyWithDirection("right")
  417.     if not doesArrayContain(noOreDetected, targetPos) and not doesArrayContain(oreDetected, targetPos) then
  418.     turnRight()
  419.  
  420.         if isOre("forward") then
  421.             table.insert(oreDetected, targetPos)
  422.         else
  423.             table.insert(noOreDetected, targetPos)
  424.         end
  425.  
  426.     turnLeft()
  427.     end
  428.  
  429.     targetPos = getPositionKeyWithDirection("left")
  430.     if not doesArrayContain(noOreDetected, targetPos) and not doesArrayContain(oreDetected, targetPos) then
  431.         turnLeft()
  432.        
  433.         if isOre("forward") then
  434.             table.insert(oreDetected, targetPos)
  435.         else
  436.             table.insert(noOreDetected, targetPos)
  437.         end
  438.  
  439.         turnRight()
  440.     end
  441.  
  442.  
  443.  
  444.  
  445.     -- Mine down if there is ore
  446.     targetPos = getPositionKeyWithDirection("down")
  447.     if doesArrayContain(oreDetected, targetPos) then
  448.  
  449.         if down() then
  450.             table.insert(backTrackLog, "up")
  451.  
  452.             --remove ore and add to no ore list
  453.             removeDataFromArray(oreDetected,targetPos)
  454.             table.insert(noOreDetected, targetPos)
  455.  
  456.         else
  457.             return false
  458.         end
  459.         smartMineOreVeinWorker(noOreDetected,oreDetected,backTrackLog)
  460.     end
  461.  
  462.     -- Mine left if there is ore
  463.     targetPos = getPositionKeyWithDirection("left")
  464.     if doesArrayContain(oreDetected, targetPos) then
  465.         turnLeft()
  466.         table.insert(backTrackLog, "turnright")
  467.  
  468.         if forward() then
  469.             table.insert(backTrackLog, "back")
  470.  
  471.             --remove ore and add to no ore list
  472.             removeDataFromArray(oreDetected,targetPos)
  473.             table.insert(noOreDetected, targetPos)
  474.  
  475.         else
  476.             return false
  477.         end
  478.         smartMineOreVeinWorker(noOreDetected,oreDetected,backTrackLog)
  479.     end
  480.  
  481.     -- Mine forward if there is ore
  482.     targetPos = getPositionKeyWithDirection("forward")
  483.     if doesArrayContain(oreDetected, targetPos) then
  484.         if forward() then
  485.             table.insert(backTrackLog, "back")
  486.            
  487.             --remove ore and add to no ore list
  488.             removeDataFromArray(oreDetected,targetPos)
  489.             table.insert(noOreDetected, targetPos)
  490.  
  491.         else
  492.             return false
  493.         end
  494.         smartMineOreVeinWorker(noOreDetected,oreDetected,backTrackLog)
  495.     end
  496.  
  497.     -- Mine right if there is ore
  498.     targetPos = getPositionKeyWithDirection("right")
  499.     if doesArrayContain(oreDetected, targetPos) then
  500.         turnRight()
  501.         table.insert(backTrackLog, "turnleft")
  502.  
  503.         if forward() then
  504.             table.insert(backTrackLog, "back")
  505.  
  506.             --remove ore and add to no ore list
  507.             removeDataFromArray(oreDetected,targetPos)
  508.             table.insert(noOreDetected, targetPos)
  509.         else
  510.             return false
  511.         end
  512.         smartMineOreVeinWorker(noOreDetected,oreDetected,backTrackLog)
  513.     end
  514.  
  515.     -- Mine up if there is ore
  516.     targetPos = getPositionKeyWithDirection("up")
  517.     if doesArrayContain(oreDetected, targetPos) then
  518.  
  519.         if up() then
  520.             table.insert(backTrackLog, "down")
  521.  
  522.             --remove ore and add to no ore list
  523.             removeDataFromArray(oreDetected,targetPos)
  524.             table.insert(noOreDetected, targetPos)
  525.  
  526.         else
  527.             return false
  528.         end
  529.         smartMineOreVeinWorker(noOreDetected,oreDetected,backTrackLog)
  530.     end
  531.  
  532.     --no ores next to turtle need to backtrack if there are any ores left
  533.     if #oreDetected > 0 and #backTrackLog > 0 then
  534.         local action = table.remove(backTrackLog)
  535.  
  536.         --back tracked
  537.         if action == "turnright" then
  538.             turnRight()
  539.         elseif action == "turnleft" then
  540.             turnLeft()
  541.         elseif action == "back" then
  542.             back()
  543.         elseif action == "down" then
  544.             down()
  545.         elseif action == "up" then
  546.             up()
  547.         end
  548.  
  549.             --check backtracked location
  550.         smartMineOreVeinWorker(noOreDetected,oreDetected,backTrackLog)
  551.        
  552.  
  553.        
  554.  
  555.     else
  556.         return true
  557.     end
  558.  
  559. end
  560.  
  561. local function smartMineOreVein()
  562.  
  563.     local noOreDetected = {}
  564.     local oreDetected = {}
  565.     local backTrackLog = {}
  566.  
  567.     local startXPos, startYPos, startZPos, startDir = x, y, z, dir
  568.     smartMineOreVeinWorker(noOreDetected,oreDetected,backTrackLog, true)
  569.  
  570.     moveToLocation(startXPos,startYPos,startZPos)
  571.     turnToDirection(startDir)
  572. end
  573.  
  574. local function mineWellAndCollectOres()
  575.     local startXPos, startYPos, startZPos = x, y, z
  576.  
  577.     while down() do
  578.         for i = 1, 4, 1 do
  579.             turnLeft()
  580.             if isOre("forward") then
  581.                 smartMineOreVein()
  582.             end
  583.         end
  584.     end
  585.  
  586.     moveToLocation(startXPos,startYPos,startZPos)
  587. end
  588.  
  589. local function mineWellInGrid(width, depth)
  590.     local wellLocations = {}
  591.     local startXPos, startYPos, startZPos, startDir = x, y, z, dir
  592.  
  593.     -- Generate initial well positions
  594.     for z = 0, -(depth - 1), -1 do
  595.         for x = 0, (width - 1), 1 do
  596.             if z % 4 == 0 and x % 4 == 0 then
  597.                 table.insert(wellLocations, {x, y, z}) -- assumes y is global
  598.             end
  599.         end
  600.     end
  601.  
  602.     -- Duplicate with (2, 0, -2) offset
  603.     local originalCount = #wellLocations
  604.     for index = 1, originalCount do
  605.         local loc = wellLocations[index]
  606.         table.insert(wellLocations, {loc[1] + 2, loc[2], loc[3] - 2})
  607.     end
  608.  
  609.     -- Remove locations out of bounds
  610.     local i = 1
  611.     while i <= #wellLocations do
  612.         local x, _, z = table.unpack(wellLocations[i])
  613.         if x < 0 or x >= width or math.abs(z) > depth then
  614.             table.remove(wellLocations, i)
  615.         else
  616.             i = i + 1
  617.         end
  618.     end
  619.  
  620.     for i = 1, #wellLocations, 1 do
  621.        
  622.         moveToLocation(wellLocations[i][1], wellLocations[i][2], wellLocations[i][3])
  623.         mineWellAndCollectOres()
  624.        
  625.         moveToLocation(startXPos,startYPos,startZPos)
  626.         turnToDirection(startDir)
  627.  
  628.         turnLeft()
  629.         turnLeft()
  630.  
  631.         refuelAll(2000)
  632.        
  633.         dumpInventory("forward")
  634.     end
  635. end
  636.  
  637. --go to starting location when loaded again
  638. moveToLocation(0,0,0)
  639. turnToDirection("n")
  640.  
  641. local args = { ... }
  642.  
  643. if not args[1] then
  644.     print("Usage:")
  645.     print("mine reset (Reset turtle origin point)")
  646.     print("mine smartQuary <width> <depth> (Mine a grid of ore wells)")
  647.     return
  648.  
  649. elseif args[1] == "reset" then
  650.     resetState()
  651.     return
  652.  
  653. elseif args[1] == "smartQuary" then
  654.     local width = tonumber(args[2])
  655.     local depth = tonumber(args[3])
  656.  
  657.     if width and depth then
  658.         mineWellInGrid(width, depth)
  659.     else
  660.         print("Usage: mine smartQuary <width> <depth>")
  661.         print("Example: mine smartQuary 16 20")
  662.     end
  663.     return
  664.  
  665. else
  666.     print("Unknown subcommand: " .. tostring(args[1]))
  667.     print("Use one of the following:")
  668.     print("reset")
  669.     print("smartQuary <width> <depth>")
  670.     return
  671. end
  672.  
  673.  
  674.  
  675.  
  676.  
  677.  
  678.  
  679.  
  680.  
  681.  
  682.  
Advertisement
Add Comment
Please, Sign In to add comment