CCCPaste

31cb798df8830

-- Farm settings
local farmLength = 15  -- Farm length
local farmWidth = 15   -- Farm width
local homePosition = {x=0, y=0, z=0, facing=0}  -- Home position and direction
local sleepDuration = 120  -- Sleep time in seconds
local seedItem = "minecraft:wheat_seeds"  -- Seed ID

-- Turtle's current position
local currentPos = {x=0, y=0, z=0, facing=0}  -- facing: 0=north, 1=east, 2=south, 3=west

-- Logging system
local logFile = "farm_log.txt"
local maxLogSize = 10000  -- Maximum lines in log file before rotation

-- Initialize logging
function initLog()
    -- Rotate log if it gets too big
    if fs.exists(logFile) then
        local file = fs.open(logFile, "r")
        local lineCount = 0
        while file.readLine() do
            lineCount = lineCount + 1
        end
        file.close()
        
        if lineCount > maxLogSize then
            local backupFile = "farm_log_old.txt"
            if fs.exists(backupFile) then
                fs.delete(backupFile)
            end
            fs.move(logFile, backupFile)
        end
    end
end

-- Log message to file and console
function log(message)
    local timestamp = os.date("%Y-%m-%d %H:%M:%S")
    local logMessage = "[" .. timestamp .. "] " .. message
    
    -- Print to console
    print(logMessage)
    
    -- Write to log file
    local file = fs.open(logFile, "a")
    if file then
        file.writeLine(logMessage)
        file.close()
    end
end

-- Main farm function
function main()
    -- Initialize logging
    initLog()
    log("Farm turtle program starting...")
    
    -- Initialize position
    currentPos = {x=0, y=0, z=0, facing=0}
    homePosition = {x=0, y=0, z=0, facing=0}
    
    while true do
        local collected = false
        local outOfSeeds = false
        
        log("Starting farm traversal. Farm size: " .. farmLength .. "x" .. farmWidth)
        
        -- Farm traversal
        for i = 1, farmLength do
            log("Processing row " .. i .. " of " .. farmLength)
            
            for j = 1, farmWidth do
                local success, needsResupply = checkAndHarvest()
                if needsResupply then
                    outOfSeeds = true
                    log("Out of seeds at position: " .. currentPos.x .. ", " .. currentPos.z)
                    break
                end
                
                -- Move forward
                if j < farmWidth then
                    if not moveForward() then
                        -- If can't move forward, skip this block
                        log("Cannot move forward at row " .. i .. ", column " .. j .. ", skipping block")
                    else
                        log("Moved to position: " .. currentPos.x .. ", " .. currentPos.z)
                    end
                end
            end
            
            if outOfSeeds then
                log("Breaking due to out of seeds")
                break
            end
            
            -- Turn and move to next row
            if i < farmLength then
                log("Moving to next row from row " .. i)
                if i % 2 == 1 then
                    turnRight()
                    if not moveForward() then
                        log("Cannot move to next row from row " .. i)
                        break
                    end
                    turnRight()
                else
                    turnLeft()
                    if not moveForward() then
                        log("Cannot move to next row from row " .. i)
                        break
                    end
                    turnLeft()
                end
                log("Successfully moved to next row. New position: " .. currentPos.x .. ", " .. currentPos.z)
            else
                log("Finished all rows")
            end
        end
        
        -- Return home using coordinates
        log("Farm traversal completed. Returning home.")
        returnToHomeByCoords()
        
        -- If out of seeds, resupply
        if outOfSeeds then
            if resupplySeeds() then
                log("Seeds resupplied, continuing work")
            else
                log("Failed to resupply seeds! Waiting...")
                os.sleep(60)
            end
        end
        
        -- Unload harvest
        if emptyInventory() then
            collected = true
        end
        
        -- Wait
        if collected then
            log("Harvest collected. Resting for " .. sleepDuration .. " seconds...")
            os.sleep(sleepDuration)
        else
            log("No harvest. Short rest for 60 seconds...")
            os.sleep(60)
        end
    end
end

-- Move forward with position tracking
function moveForward()
    local success = turtle.forward()
    if success then
        -- Update position based on direction
        if currentPos.facing == 0 then      -- North
            currentPos.z = currentPos.z - 1
        elseif currentPos.facing == 1 then  -- East
            currentPos.x = currentPos.x + 1
        elseif currentPos.facing == 2 then  -- South
            currentPos.z = currentPos.z + 1
        elseif currentPos.facing == 3 then  -- West
            currentPos.x = currentPos.x - 1
        end
        return true
    else
        return false
    end
end

-- Turn right with direction tracking
function turnRight()
    turtle.turnRight()
    currentPos.facing = (currentPos.facing + 1) % 4
    log("Turned right. Now facing: " .. currentPos.facing)
end

-- Turn left with direction tracking
function turnLeft()
    turtle.turnLeft()
    currentPos.facing = (currentPos.facing - 1) % 4
    if currentPos.facing < 0 then
        currentPos.facing = 3
    end
    log("Turned left. Now facing: " .. currentPos.facing)
end

-- Find seeds in inventory
function findSeeds()
    for i = 1, 16 do
        local item = turtle.getItemDetail(i)
        if item and item.name == seedItem then
            return i  -- Return slot number with seeds
        end
    end
    return nil  -- Seeds not found
end

-- Resupply seeds from chest
function resupplySeeds()
    log("Resupplying seeds...")
    
    -- Assume chest is in front of turtle at home position
    turtle.select(1)  -- Select first slot for seed pickup
    
    local success = turtle.suckDown(64)  -- Take seeds from chest
    if success then
        log("Seeds successfully resupplied")
        return true
    else
        log("Failed to get seeds from chest")
        return false
    end
end

-- Check and harvest crops
function checkAndHarvest()
    local success, data = turtle.inspectDown()
    local needsResupply = false
    
    if success then
        if data.name == "minecraft:wheat" then
            if data.state.age == 7 then
                log("Harvesting mature wheat at " .. currentPos.x .. ", " .. currentPos.z)
                harvestAndReplant()
            else
                log("Wheat not ready (age: " .. data.state.age .. ") at " .. currentPos.x .. ", " .. currentPos.z)
            end
        elseif data.name == "minecraft:water" or data.name:find("slab") or data.name:find("stairs") then
            -- Skip water blocks and half-blocks
            log("Found unsuitable block: " .. data.name .. ", skipping at " .. currentPos.x .. ", " .. currentPos.z)
            return true, false
        else
            log("Found block: " .. data.name .. " at " .. currentPos.x .. ", " .. currentPos.z)
        end
    else
        -- If no block - plant seeds
        log("No block found, planting seeds at " .. currentPos.x .. ", " .. currentPos.z)
        local planted = plantSeed()
        if not planted then
            needsResupply = true
        end
    end
    return true, needsResupply
end

-- Harvest and replant
function harvestAndReplant()
    local slot = turtle.getSelectedSlot()
    turtle.digDown()
    plantSeed()
    turtle.select(slot)
end

-- Plant seeds
function plantSeed()
    local seedSlot = findSeeds()
    
    if seedSlot then
        local currentSlot = turtle.getSelectedSlot()
        turtle.select(seedSlot)
        local success = turtle.placeDown()
        turtle.select(currentSlot)
        if success then
            log("Planted seeds successfully")
        else
            log("Failed to plant seeds")
        end
        return success
    else
        log("Out of seeds! Returning home...")
        return false
    end
end

-- Return home using coordinates
function returnToHomeByCoords()
    log("Returning home from position: " .. currentPos.x .. ", " .. currentPos.z .. ", facing: " .. currentPos.facing)
    
    -- First turn towards home
    local dx = homePosition.x - currentPos.x
    local dz = homePosition.z - currentPos.z
    
    log("Distance to home: X=" .. dx .. ", Z=" .. dz)
    
    -- Determine needed direction for X movement
    if dx > 0 then
        -- Need to move east
        while currentPos.facing ~= 1 do
            turnRight()
        end
    elseif dx < 0 then
        -- Need to move west
        while currentPos.facing ~= 3 do
            turnRight()
        end
    end
    
    -- Move along X axis
    for i = 1, math.abs(dx) do
        if not moveForward() then
            -- If can't move straight, find alternative path
            findAlternativePath()
        end
    end
    
    -- Determine needed direction for Z movement
    if dz > 0 then
        -- Need to move south
        while currentPos.facing ~= 2 do
            turnRight()
        end
    elseif dz < 0 then
        -- Need to move north
        while currentPos.facing ~= 0 do
            turnRight()
        end
    end
    
    -- Move along Z axis
    for i = 1, math.abs(dz) do
        if not moveForward() then
            -- If can't move straight, find alternative path
            findAlternativePath()
        end
    end
    
    -- Turn to home direction
    while currentPos.facing ~= homePosition.facing do
        turnRight()
    end
    
    log("Successfully returned home!")
end

-- Find alternative path when blocked
function findAlternativePath()
    log("Looking for alternative path...")
    
    -- Try to bypass obstacle
    turnRight()
    if moveForward() then
        turnLeft()
        if moveForward() then
            turnLeft()
            if moveForward() then
                turnRight()
                return true
            end
        end
    end
    
    -- If that didn't work, try other side
    turnLeft()
    turnLeft()
    if moveForward() then
        turnRight()
        if moveForward() then
            turnRight()
            if moveForward() then
                turnLeft()
                return true
            end
        end
    end
    
    log("Cannot find alternative path!")
    return false
end

-- Unload items to chest
function emptyInventory()
    local collected = false
    
    -- Preserve seed slot if exists
    local seedSlot = findSeeds()
    
    for i = 1, 16 do
        -- Skip seed slot and fuel slot
        if i ~= (seedSlot or 0) and i ~= 16 then
            turtle.select(i)
            local count = turtle.getItemCount()
            if count > 0 then
                local item = turtle.getItemDetail()
                log("Dropping " .. count .. " of " .. (item and item.name or "unknown"))
                turtle.dropDown()
                collected = true
            end
        end
    end
    
    -- Move seeds to first slot for convenience
    if seedSlot and seedSlot ~= 1 then
        turtle.select(seedSlot)
        turtle.transferTo(1, 64)
    end
    
    turtle.select(1)  -- Return seeds to main slot
    return collected
end

-- Check fuel level
function checkFuel()
    local fuelLevel = turtle.getFuelLevel()
    local neededFuel = farmLength * farmWidth * 2 + 10
    
    log("Current fuel: " .. fuelLevel .. ", needed: " .. neededFuel)
    
    if fuelLevel < neededFuel then
        turtle.select(16)
        if turtle.refuel(1) then
            log("Fuel refilled. New level: " .. turtle.getFuelLevel())
        else
            log("No fuel in slot 16!")
        end
    end
end

-- Start program
checkFuel()
main()