local robotApi = require('robot') local turtleUtils = require('turtle-utils') local config = { startY = 109, targetY = 109, height = 4, size = 16 } local LOWER_SIZE_LIMIT = 2; local HIGHER_SIZE_LIMIT = 128; local ADDITIONAL_FUEL_NEEDED = 256 local INITIAL_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 = INITIAL_TARGET_Y + (config.height - 1) local MAX_Z = TARGET_Z local robot = robotApi.create() local MAX_INVENTORY_BLOCKS = 16 * 64 local MIN_FUEL_NEEDED = 2 * ((config.size * 2) + INITIAL_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 } targetY = INITIAL_TARGET_Y } local function isOdd(x) return (x % 2) == 1 end local function checkConfig() if config.targetY >= config.startY then error('targetY should be lower than startY') end if config.height < 1 then error('height cannot be lower than 1') end if config.size < LOWER_SIZE_LIMIT then error('size cannot be lower than ' .. LOWER_SIZE_LIMIT) end if config.size > HIGHER_SIZE_LIMIT then error('size is too large (higher limit is ' .. HIGHER_SIZE_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.getState() 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) turtle.refuel() turtleUtils.tryDrop() end 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.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' print('> Starting mining procedure...') end else miner.mission = 'mine' print('> Starting mining procedure...') end end local function mineProcedure() local robotState = miner.robot.getState() local targetY = miner.targetY 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 == 0 then miner.finished = true miner.mission = 'return-home' miner.lastPositionState = miner.robot.getState() print('> Starting return home procedure because mining session is finished...') elseif robotState.x == MAX_X and robotState.z == 0 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() -- mine the next stage miner.robot.up() miner.targetY = miner.targetY + 1 end if turtleUtils.countFreeSlots() < 1 then print('> Starting return home procedure because inventory is almost full...') miner.mission = 'return-home' miner.lastPositionState = miner.robot.getState() end end local function returnHomeProcedure() 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 while miner.robot.getState().dir ~= 'FORWARD' do miner.robot.turnRight() end 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!")