chore: save

This commit is contained in:
Guillaume ARM 2024-05-08 18:27:47 +02:00
commit fd40a52ddc
3 changed files with 408 additions and 0 deletions

241
miner.lua Normal file
View File

@ -0,0 +1,241 @@
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 = (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!")

114
robot.lua Normal file
View File

@ -0,0 +1,114 @@
-- robot api
local api = {}
api.create = function()
local state = {
y = 0,
x = 0,
z = 0,
-- | BACKWARD | LEFT | RIGHT
dir = 'FORWARD'
}
local mutateRobotPosition = function(isBackward)
local incValue = 1
if isBackward then invValue = -1 end
if dir == 'FORWARD' then
state.z = state.z + incValue
elseif dir == 'BACKWARD' then
state.z = state.z - incValue
elseif dir == 'LEFT' then
state.x = state.x - incValue
elseif dir == 'RIGHT' then
state.x = state.x + incValue
end
end
local robot = {}
robot.forward = function()
local ok, err = turtle.forward()
if ok then
mutateRobotPosition(false)
end
return ok, err
end
robot.backward = function()
local ok, err = turtle.back()
if ok then
mutateRobotPosition(true)
end
return ok, err
end
robot.up = function()
local ok, err = turtle.up()
if ok then
state.y = state.y + 1
end
return ok, err
end
robot.down = function()
local ok, err = turtle.down()
if ok then
state.y = state.y - 1
end
return ok, err
end
robot.turnLeft = function()
local ok, err = turtle.turnLeft()
if ok then
if state.dir == 'FORWARD' then
state.dir = 'LEFT'
elseif state.dir == 'LEFT' then
state.dir = 'BACKWARD'
elseif state.dir == 'RIGHT' then
state.dir = 'FORWARD'
elseif state.dir == 'BACKWARD' then
state.dir = 'RIGHT'
end
end
return ok, err
end
robot.turnRight = function()
local ok, err = turtle.turnRight()
if ok then
if state.dir == 'FORWARD' then
state.dir = 'RIGHT'
elseif state.dir == 'LEFT' then
state.dir = 'FORWARD'
elseif state.dir == 'RIGHT' then
state.dir = 'BACKWARD'
elseif state.dir == 'BACKWARD' then
state.dir = 'LEFT'
end
end
return ok, err
end
robot.getState = function()
return state
end
return robot
end
return api

53
turtle-utils.lua Normal file
View File

@ -0,0 +1,53 @@
local turtleUtils = {}
local IDLE_TIME = 2
turtleUtils.waitForInventory = function(side)
local inv = nil
while true do
inv = peripheral.wrap(side)
if inv and peripheral.hasType(inv, 'inventory') then
break
end
os.sleep(IDLE_TIME)
end
return inv
end
turtleUtils.trySuckUp = function()
while not turtle.suckUp() do
os.sleep(IDLE_TIME)
end
end
turtleUtils.tryDrop = function()
while not turtle.drop() do
os.sleep(IDLE_TIME)
end
end
turtleUtils.digAll = function()
while turtle.dig() do end
end
turtleUtils.countFreeSlots = function()
local freeSlots = 0
for i=1, 16, 1 do
if turtle.getItemCount(i) == 0 then
freeSlots = freeSlots + 1
end
end
return freeSlots
end
turtleUtils.getFuelPercentage = function()
return (turtle.getFuelLevel() / turtle.getFuelLimit()) * 100
end
return turtleUtils