local turtlePos, direction local startPos, startDir local function getGPSPosition() local x, y, z = gps.locate() if not x then print("Error: GPS not available") return nil end return {x = math.floor(x), y = math.floor(y), z = math.floor(z)} end local function negative(vec) return {x = -vec.x, y = -vec.y, z = -vec.z} end local function add(vec1, vec2) return {x = vec1.x + vec2.x, y = vec1.y + vec2.y, z = vec1.z + vec2.z} end local function sub(vec1, vec2) return add(vec1, negative(vec2)) end local function multiply(s, vec) return {x = s * vec.x, y = s * vec.y, z = s * vec.z} end local function getSign(number) return number / math.abs(number) end local function isEqual(vec1, vec2) return vec1.x == vec2.x and vec1.y == vec2.y and vec1.z == vec2.z end -- === Basic Movement === local function moveForward() if turtle.forward() then turtlePos = add(turtlePos, direction) return true end return false end local function moveUp() if turtle.up() then turtlePos.y = turtlePos.y + 1 return true end return false end local function moveDown() if turtle.down() then turtlePos.y = turtlePos.y - 1 return true end return false end local function forceMoveForward() while not moveForward() do turtle.dig() end end local function forceMoveUp() while not moveUp() do turtle.digUp() end end local function forceMoveDown() while not moveDown() do turtle.digDown() end end -- === Basic Turning === local function turnInDirection(dir) if not direction then return end if dir == "left" then turtle.turnLeft() direction = {x = direction.z, y = 0, z = -direction.x} elseif dir == "right" then turtle.turnRight() direction = {x = -direction.z, y = 0, z = direction.x} elseif dir == "around" then turtle.turnLeft() turtle.turnLeft() direction = {x = -direction.x, y = 0, z = -direction.z} end end local function getTurnDirection(from, to) local function vectorsEqual(a, b) return a.x == b.x and a.z == b.z end if vectorsEqual(from, to) then return nil end local left = {x = from.z, y = 0, z = -from.x} local right = {x = -from.z, y = 0, z = from.x} local back = {x = -from.x, y = 0, z = -from.z} if vectorsEqual(to, left) then return "left" elseif vectorsEqual(to, right) then return "right" elseif vectorsEqual(to, back) then return "around" else error("Invalid target direction") end end local function getDirection() local pos1 = getGPSPosition() if not pos1 then error("GPS failure, cannot get direction") end for i = 1, 4 do if turtle.forward() then local pos2 = getGPSPosition() if not pos2 then error("GPS failure after move") end -- turtlePos = pos2 -- Richtung berechnen direction = sub(pos2, pos1) -- zurück zur ursprünglichen Position turnInDirection("around") forceMoveForward() -- Sicherheitsprüfung local posBack = getGPSPosition() if not isEqual(pos1, posBack) then error("Warnung: Position hat sich beim Rückweg verschoben!") turtlePos = posBack -- explizit wieder auf GPS setzen else turtlePos = pos1 end turnInDirection("around") return else turtle.turnLeft() end end error("Unable to move forward in any direction for direction detection") end -- === Positioning === local function goToPos(coord) local deltaX = coord.x - turtlePos.x local deltaY = coord.y - turtlePos.y local deltaZ = coord.z - turtlePos.z local dirX = startDir.x local dirZ = startDir.z local function moveToEqualX() while not (deltaX == 0) do turnInDirection(getTurnDirection(direction, {x = getSign(deltaX), y = 0, z = 0})) forceMoveForward() deltaX = coord.x - turtlePos.x end end local function moveToEqualZ() while not (deltaZ == 0) do turnInDirection(getTurnDirection(direction, {x = 0, y = 0, z = getSign(deltaZ)})) forceMoveForward() deltaZ = coord.z - turtlePos.z end end local function moveToEqualY() while not (deltaY == 0) do if deltaY > 0 then forceMoveUp() elseif deltaY < 0 then forceMoveDown() end deltaY = coord.y - turtlePos.y end end if dirX == 0 then moveToEqualZ() moveToEqualX() elseif dirZ == 0 then moveToEqualX() moveToEqualZ() end if not (deltaY == 0) then moveToEqualY() deltaX = coord.x - turtlePos.x deltaZ = coord.z - turtlePos.z end end local function goToStartOfTree() startTreePos = add(startPos, multiply(7, startDir)) goToPos(startTreePos) turnInDirection(getTurnDirection(direction, startDir)) end -- === Tasks === local function isSapling(item) if not item or not item.name then return false end local saplingSuffix = "_propagule" return item.name:match(":.*" .. saplingSuffix .. "$") ~= nil end local function isBoneMeal(item) if not item or not item.name then return false end return item.name == "minecraft:bone_meal" end local function isLog(item) if not item or not item.name then return false end local logSuffix = "_log" return item.name:match(":.*" .. logSuffix .. "$") ~= nil end local function getBoneMealCount() local num = 0 for i = 1, 16 do local item = turtle.getItemDetail(i) if isBoneMeal(item) then num = num + turtle.getItemCount(i) end end return num end local function selectSaplingSlot() for i = 1, 16 do local item = turtle.getItemDetail(i) if isSapling(item) then turtle.select(i) return true end end return false end local function selectBoneMealSlot() for i = 1, 16 do local item = turtle.getItemDetail(i) if isBoneMeal(item) then turtle.select(i) return true end end return false end local function plantSapling() if not selectSaplingSlot() then return false end if not turtle.place() then return false end return true end local function fellBranch(bDown) -- if turtle goes down the tree bDown = bDown or false local suc, item = turtle.inspect() if not(suc and isLog(item)) then return false end if bDown then forceMoveDown() fellBranch() forceMoveUp() end branchDir = direction forceMoveForward() local function advanceInBranch() forceMoveForward() local suc, item = turtle.inspectUp() if suc and isLog(item) then forceMoveUp() advanceInBranch() forceMoveDown() end turnInDirection(getTurnDirection(direction, negative(branchDir))) forceMoveForward() end advanceInBranch() turnInDirection(getTurnDirection(direction, negative(branchDir))) forceMoveForward() turnInDirection(getTurnDirection(direction, branchDir)) return true end local function fellTree() forceMoveForward() cnt = 0 suc, item = turtle.inspectUp() while not (suc and isLog(item)) do forceMoveUp() suc, item = turtle.inspectUp() cnt = cnt + 1 if cnt >= 25 then goToStartOfTree() return false end end forceMoveUp() startLogY = turtlePos.y fellBranch() suc, item = turtle.inspectUp() while suc and isLog(item) do forceMoveUp() fellBranch() suc, item = turtle.inspectUp() end endLogY = turtlePos.y turnInDirection("right") fellBranch(true) while not (turtlePos.y == startLogY) do forceMoveDown() fellBranch(true) end turnInDirection("right") fellBranch() while not (turtlePos.y == endLogY) do forceMoveUp() fellBranch() end turnInDirection("right") fellBranch(true) while not (turtlePos.y == startLogY) do forceMoveDown() fellBranch(true) end goToStartOfTree() return true end -- === Initialization === local function saveStartingParameters() local parameterList = {pos = turtlePos, dir = direction} local file = fs.open("startingParameters.txt", "w") file.write(textutils.serialize(parameterList)) file.close() end local function loadStartingParameters() if not fs.exists("startingParameters.txt") then return false end local file = fs.open("startingParameters.txt", "r") local data = textutils.unserialize(file.readAll()) file.close() startPos = data.pos startDir = data.dir return true end local function initProgram() turtlePos = getGPSPosition() if not turtlePos then error("GPS failure, cannot run the program") end getDirection() if not loadStartingParameters() then startPos = turtlePos startDir = direction saveStartingParameters() end end -- === Main === local function main() initProgram() goToStartOfTree() fellTree() end main()