-- ayangd's Mine V1.0 -- Made by ayangd -- Import required modules geo = require("component").geolyzer robot = require("robot") sides = require("sides") shell = require("shell") computer = require("computer") -- Parse command line arguments args = shell.parse(...) if #args < 2 then print("Tell me where am I facing and how deep can I dig.") return end facing = args[1] deep = tonumber(args[2]) -- If some ore is skipped, it can be broken tool or bedrock. skipped = 0 -- Take first table content and return the first content and the remaining table -- If table is nil, return nil -- If table is not a table, return the passed argument back (Unpacking has already done) function div(t) if t == nil then return nil end if type(t) == 'table' then a = t[1] table.remove(t, 1) return a, table.unpack(t) end return t end -- Wrap function inside functions, so they will automatically go back to its initial state. function ru(fu, ar) robot.up(); fu(div(ar)); robot.down(); end function rd(fu, ar) robot.down(); fu(div(ar)); robot.up(); end function rl(fu, ar) robot.turnLeft(); fu(div(ar)); robot.turnRight(); end function rr(fu, ar) robot.turnRight(); fu(div(ar)); robot.turnLeft(); end -- Forward function moved below! function rb(fu, ar) robot.back(); fu(div(ar)); robot.forward(); end -- Wrap a swing function that makes sure the block or an entity is gone. Otherwise, repeat. -- Try 10 times. If it still can't, just ignore. function sw(fu) try = 0 fures, fue = fu() while ((not fures) and (fue == 'block')) or ((fures) and (fue == 'entity')) do if (try >= 10) then skipped = skipped + 1 break end try = try + 1 print(fures, fue) computer.beep(300, 0.1) computer.beep(100, 0.1) os.sleep(0.8) fures = fu() end end -- Gravels falling down prevents the robot from going back. Dig it! function rf(fu, ar) robot.forward(); fu(div(ar)); if not robot.back() then rl(rl, {sw, robot.swing}) robot.back() end end -- Wrap move functions to make sure nothing is in the way. function fobs(fu, ar) if robot.detect() then sw(robot.swing); end; rf(fu, ar); end function uobs(fu, ar) if robot.detectUp() then sw(robot.swingUp); end; ru(fu, ar); end function dobs(fu, ar) if robot.detectDown() then sw(robot.swingDown); end; rd(fu, ar); end -- Return if the value is within ore hardness or not. -- Weirdly, fluid blocks has hardness 100 and bedrock has hardness -1. -- Noise is about +-0.5 within 4 blocks from the robot. -- Iron ore, gold ore, has 3 hardness. function isOre(v) if v > 2 and v < 45 then return true else return false end end -- Make sure the robot faces the right direction -- Since the geolyzer's scan is in fixed coordinate direction (world coordinate direction) function faceTo(face, fu, ar) if facing == 'south' then if face == 'east' then facing = face rl(fu, ar) facing = 'south' elseif face == 'west' then facing = face rr(fu, ar) facing = 'south' elseif face == 'north' then facing = face rr(rr, {fu, ar}) facing = 'south' else fu(div(ar)) end elseif facing == 'east' then if face == 'south' then facing = face rr(fu, ar) facing = 'east' elseif face == 'north' then facing = face rl(fu, ar) facing = 'east' elseif face == 'west' then facing = face rr(rr, {fu, ar}) facing = 'east' else fu(div(ar)) end elseif facing == 'north' then if face == 'east' then facing = face rr(fu, ar) facing = 'north' elseif face == 'west' then facing = face rl(fu, ar) facing = 'north' elseif face == 'south' then facing = face rr(rr, {fu, ar}) facing = 'north' else fu(div(ar)) end elseif facing == 'west' then if face == 'north' then facing = face rr(fu, ar) facing = 'west' elseif face == 'south' then facing = face rl(fu, ar) facing = 'west' elseif face == 'east' then facing = face rr(rr, {fu, ar}) facing = 'west' else fu(div(ar)) end end end -- Wraps face function and going forward without failure together function moveToward(face, fu, ar) faceTo(face, fobs, {fu, ar}) end -- Scan for neighbouring ore by the robot (1 block far from the robot) function nextOre() computer.beep(1000, 0.01) tn = geo.scan(-1, -1, -1, 3, 3, 3) if isOre(tn[5]) then computer.beep(1500, 0.01) dobs(nextOre) nextOre() end if isOre(tn[11]) then computer.beep(1500, 0.01) moveToward('north', nextOre) nextOre() end if isOre(tn[13]) then computer.beep(1500, 0.01) moveToward('west', nextOre) nextOre() end if isOre(tn[15]) then computer.beep(1500, 0.01) moveToward('east', nextOre) nextOre() end if isOre(tn[17]) then computer.beep(1500, 0.01) moveToward('south', nextOre) nextOre() end if isOre(tn[23]) then computer.beep(1500, 0.01) uobs(nextOre) nextOre() end end -- Moves to the desired relative coordinate function relCoordMove(x, z, fu, ar) fui, ari = fu, ar if x > 0 then for i = 1, x do fui, ari = moveToward, {'east', fui, ari} end elseif x < 0 then for i = 1, math.abs(x) do fui, ari = moveToward, {'west', fui, ari} end end if z > 0 then for i = 1, z do fui, ari = moveToward, {'south', fui, ari} end elseif z < 0 then for i = 1, math.abs(z) do fui, ari = moveToward, {'north', fui, ari} end end fui(div(ari)) end -- Just maps value to other scale function map(vmin1, vmax1, vmin2, vmax2, val) return (val - vmin1) / (vmax1 - vmin1) * (vmax2 - vmin2) + vmin2 end -- Scans periodically from 1 block far to 3 blocks far function steppedScan() for i = 1, 3 do -- Message: Starting to scan i block(s) far. computer.beep(220 * i * 2, 0.01) computer.beep(220 * i, 0.01) s = i*2 + 1 t = geo.scan(-i, -i, 0, s, s, 1) l = 0 gout = false for j = -i, i do m = 0 for k = -i, i do if ((j == -i) or (j == i)) or ((k == -i) or (k == i)) then if isOre(t[l * s + m + 1]) then computer.beep(100, 0.01); relCoordMove(k, j, nextOre); gout = true; break; end end m = m + 1 end if gout then break end l = l + 1 end -- Message: Done scanning i block(s) far. computer.beep(220 * i, 0.01) computer.beep(220 * i * 2, 0.01) end end -- Scans for a 3x3 flat area to see if there's some ore around function quickScan() t = geo.scan(-3, -3, 0, 7, 7, 1) for i = 1, 49 do if isOre(t[i]) then computer.beep(1320) -- Message: I found some ore nearby! steppedScan() break end end end --------------------------- -- -- -- The main program! -- -- -- --------------------------- down = 0 for depth = 1, deep do if not robot.detect() then robot.place() end if robot.detectDown() then if not robot.swingDown() then break end end -- Stop if the robot can't mine down further robot.down() down = down + 1 quickScan() end for depth = 1, down do robot.up() end for i = 1, 5 do -- Message: I'm done. computer.beep(220 * i, 0.01) end print(string.format('Skipped %d ores.', skipped))