local robotApi = require('robot') local turtleUtils = require('turtle-utils') local config = { startY = 109, targetY = 109, height = 1, size = 4 } local TARGET_Y = config.targetY - config.startY local TARGET_Z = config.size - 1 local TARGET_X = config.size - 1 local MAX_X = TARGET_X local MAX_Y = TARGET_Y + (config.height - 1) local MAX_Z = TARGET_Z local LOWER_LIMIT = 2; local HIGHER_LIMIT = 128; local robot = robotApi.create() local MAX_INVENTORY_BLOCKS = 16 * 64 local ADDITIONAL_FUEL_NEEDED = 512 local MIN_FUEL_NEEDED = (config.size * 2) + TARGET_Y + MAX_INVENTORY_BLOCKS + ADDITIONAL_FUEL_NEEDED local miner = { robot = robot, mission = 'unload', -- "unload" | "refuel" | "mine" | "return-home" | "return-mine" | nil finished = false, lastPositionState = nil -- { x, y, z, dir } } local function isOdd(x) return (x % 2) == 1 end local function checkConfig() if config.targetY > config.startY then error('targetY cannot be higher that startY') end if config.height < 1 then error('height cannot be lower than 1') end if config.size < LOWER_LIMIT then error('size cannot be lower than ' .. LOWER_LIMIT) end if config.size > HIGHER_LIMIT then error('size is too large (higher limit is ' .. HIGHER_LIMIT .. ')') end if isOdd(config.size) then error('configured size should be even') end end local function prepareTurtle() turtle.select(1) end local function isProgramFinished() if miner.mission ~= nil then return false end local robotState = miner.robot.getSate() return robotState.x == 0 and robotState.y == 0 and robotState.z == 0 end local function unloadProcedure() print('> Starting unload procedure...') turtleUtils.waitForInventory('front') for i=1, 16, 1 do turtle.select(i) turtleUtils.tryDrop() end turtle.select(1) miner.mission = 'refuel' end local function refuelProcedure() print('> Starting refuel procedure (' .. turtleUtils.getFuelPercentage() .. '%)') turtleUtils.waitForInventory('top') turtle.select(1) while turtle.getFuelLevel() < MIN_FUEL_NEEDED do turtleUtils.trySuckUp() local ok = turtle.refuel() if not ok then turtleUtils.tryDrop() end end print('> Refuel done.') miner.mission = 'return-mine' end local function returnMineProcedure() if miner.robot.finished then miner.mission = nil -- it will stop the loop return end if robot.lastPositionState then local robotState = miner.robot.getState() if robotState.y > miner.lastPositionState.y then miner.robot.down() elseif robotState.z < miner.lastPositionState.z then miner.robot.forward() else miner.robot.turnRight() for i=1, miner.lastPositionState.x, 1 do miner.robot.forward() end while miner.robot.getState().dir ~= miner.lastPositionState.dir do miner.robot.turnRight() end miner.mission = 'mine' end else miner.mission = 'mine' end end local function mineProcedure() print('> Starting mine procedure...') local robotState = miner.robot.getState() local targetY = TARGET_Y local targetZ = TARGET_Z -- 1. Move if robotState.y > targetY then turtle.digDown() miner.robot.down() elseif robotState.dir == 'FORWARD' and robotState.z < targetZ then turtleUtils.digAll() miner.robot.forward() elseif robotState.dir == 'FORWARD' and robotState.z == targetZ then miner.robot.turnRight() turtleUtils.digAll() miner.robot.forward() miner.robot.turnRight() elseif robotState.dir == 'BACKWARD' and robotState.z > 0 then turtleUtils.digAll() miner.robot.forward() elseif robotState.dir == 'BACKWARD' and robotState.z == 0 then miner.robot.turnLeft() turtleUtils.digAll() miner.robot.forward() miner.robot.turnLeft() end -- 2. Check if robotState.x == MAX_X and robotState.y == MAX_Y and robotState.z == MAX_Z then miner.finished = true miner.mission = 'return-home' miner.lastPositionState = miner.robot.getState() elseif robotState.x == MAX_X and robotState.z == MAX_Z then -- this part assume that the size of the mine is even miner.robot.turnRight() for i=1, config.size - 1, 1 do miner.robot.forward() end miner.robot.turnRight() miner.robot.up() end if turtleUtils.countFreeSlots() < 1 then miner.mission = 'return-home' miner.lastPositionState = miner.robot.getState() end end local function returnHomeProcedure() print('> Starting return home procedure...') local robotState = miner.robot.getState() if robotState.x == 0 and robotState.y == 0 and robotState.z == 0 then miner.mission = 'unload' elseif robotState.x == 0 and robotState.z == 0 then miner.robot.up() elseif robotState.x > 0 then if robotState.dir == 'FORWARD' then miner.robot.turnLeft() elseif robotState.dir == 'BACKWARD' then miner.robot.turnRight() end for i=1, robotState.x, 1 do miner.robot.forward() end miner.robot.turnLeft() elseif robotState.z > 0 then for i=1, robotState.z, 1 do miner.robot.forward() end miner.robot.turnLeft() miner.robot.turnLeft() end end checkConfig() prepareTurtle() print("> Miner program started, minimum fuel needed: " .. MIN_FUEL_NEEDED) while not isProgramFinished() do if miner.mission == 'unload' then unloadProcedure() elseif miner.mission == 'refuel' then refuelProcedure() elseif miner.mission == 'mine' then mineProcedure() elseif miner.mission == 'return-home' then returnHomeProcedure() elseif miner.mission == 'return-mine' then returnMineProcedure() end end print("> Miner program finished!")