turtles/kai/woodfarm.lua
Kai Vogelgesang 3a4aa8bf60 Fix
2020-07-08 05:49:47 +02:00

240 lines
5.8 KiB
Lua

local T = require("lib.lua")
--[[
States:
- MOVE_TO_TREE
- CHECK_TREE
- ASCEND_TREE
- FINALIZE_TREE
- OUTPUT
- RESUPPLY_SAPS
- RESUPPLY_FUEL
Persistent Variables:
- current_state
- current_tree [1,14]
- current_row [1,6]
Inventory:
64 + 20 Saplings in Slots 1 and 2
]]
local MAX_TREE = 14
local MAX_ROW = 6
local OUTPUT_TARGET = { x = 2, z = 0, o = "+z" }
local SAPS_TARGET = { x = 1, z = 0, o = "+z" }
local FUEL_TARGET = { x = 0, z = 0, o = "+z" }
local TREE_MAX_HEIGHT = 7
-- Saplings are at y = -1 (and coordinates are zero-based)
local TREE_MAX_Y = TREE_MAX_HEIGHT - 2
local LOG_NAME = "minecraft:birch_log"
local SAP_SLOT = 1
local BACKUP_SAP_SLOT = 2
local REFUEL_SLOT = 3
local SAP_SLOT_TARGET_COUNT = 64
local BACKUP_SAP_SLOT_TARGET_COUNT = 20
-- Should be enough even if every tree is fully grown
local FUEL_LEVEL_TARGET = 1000
local function calculate_tree_position(row_index, tree_index)
local x = (row_index - 1) * 5
local z
if row_index % 2 == 0 then
z = -2 * tree_index
else
z = -30 + 2 * tree_index
end
return x, z
end
local function greedy_move(x, z, o)
if z ~= T.state.z then
if z > T.state.z then
T.rotateTowards("+z")
else
T.rotateTowards("-z")
end
for _ = 1, math.abs(z - T.state.z) do
T.fwd()
end
end
if x ~= T.state.x then
if x > T.state.x then
T.rotateTowards("+x")
else
T.rotateTowards("-x")
end
for _ = 1, math.abs(x - T.state.x) do
T.fwd()
end
end
T.rotateTowards(o)
end
local function ensure_item_count(count)
if turtle.getItemCount() >= count then
return
end
turtle.suck(count - turtle.getItemCount())
-- turtle.suck might not suck enough items if the target container does not have them
-- but it won't tell us if this happened...
while turtle.getItemCount() ~= count do
sleep(1)
turtle.suck(count - turtle.getItemCount())
end
end
local state_machine = {
["MOVE_TO_TREE"] = function()
-- get target tree coordinates
-- and move such that we are facing it
local x, z = calculate_tree_position(T.state.current_row, T.state.current_tree)
local o
if T.state.current_row ~= 1 and T.state.current_tree == 1 then
-- we just turned towards a new row and are approaching in positive x direction
x = x - 1
o = "+x"
else
-- we are approaching in negative z direction
z = z + 1
o = "-z"
end
greedy_move(x, z, o)
return "CHECK_TREE"
end,
["CHECK_TREE"] = function()
if not turtle.detect() then
-- no tree, so skip ascending
T.fwd()
return "FINALIZE_TREE"
else
-- tree present, chop it down
turtle.dig()
T.fwd()
turtle.digDown()
return "ASCEND_TREE"
end
end,
["ASCEND_TREE"] = function()
local success, data = turtle.inspectUp()
if not s and T.state.y < TREE_MAX_Y - 1 then
-- probably reset after chopping a block
T.up()
end
while true do
local success, data = turtle.inspectUp()
if not s or data.name ~= LOG_NAME then
-- chopped all the wood
break
end
turtle.digUp()
if T.state.y == TREE_MAX_Y - 1 then
-- we are below the last log, no need to move up
break
end
T.up()
end
return "FINALIZE_TREE"
end,
["FINALIZE_TREE"] = function()
-- make sure we are directly above the sapling target
while T.state.y > 0 do
T.down()
end
turtle.select(SAP_SLOT)
-- make sure we have a sapling
if turtle.getItemCount() == 0 then
turtle.select(BACKUP_SAP_SLOT)
turtle.transferTo(SAP_SLOT)
turtle.select(SAP_SLOT)
end
if T.state.current_tree < MAX_TREE then
-- go to the next tree in this row
T.state.current_tree = T.state.current_tree + 1
return "MOVE_TO_TREE"
elseif T.state.current_row < MAX_ROW then
-- go to the first tree in the next row
T.state.current_tree = 0
T.state.current_row = T.state.current_row + 1
return "MOVE_TO_TREE"
else
-- went through the entire farm once
return "OUTPUT"
end
end,
["OUTPUT"] = function()
greedy_move(OUTPUT_TARGET.x, OUTPUT_TARGET.z, OUTPUT_TARGET.o)
-- Drop all logs
for slot = 1, 16 do
turtle.select(slot)
data = turtle.getItemDetail()
if data and data.name == LOG_NAME then
turtle.drop()
end
end
return "RESUPPLY_SAPS"
end,
["RESUPPLY_SAPS"] = function()
greedy_move(SAPS_TARGET.x, SAPS_TARGET.z, SAPS_TARGET.o)
turtle.select(SAP_SLOT)
ensure_item_count(SAP_SLOT_TARGET_COUNT)
turtle.select(BACKUP_SAP_SLOT)
ensure_item_count(BACKUP_SAP_SLOT_TARGET_COUNT)
return "RESUPPLY_FUEL"
end,
["RESUPPLY_FUEL"] = function()
greedy_move(FUEL_TARGET.x, FUEL_TARGET.z, FUEL_TARGET.o)
local fuel_count = math.ceil(FUEL_LEVEL_TARGET - turtle.getFuelLevel() / 80)
turtle.select(REFUEL_SLOT)
ensure_item_count(fuel_count)
turtle.refuel()
T.state.current_row = 0
T.state.current_tree = 0
return "MOVE_TO_TREE"
end,
}
-- initial setup
if not T.state.current_state then
T.setPosition(0, 0, 0, "-z")
T.state.current_state = "RESUPPLY_FUEL"
end
-- main loop
while true do
T.state.current_state = state_machine[T.state.current_state]()
end