Implement wood farm
This commit is contained in:
parent
784106e5b7
commit
1f765d59a7
129
kai/lib.lua
129
kai/lib.lua
@ -1,5 +1,5 @@
|
|||||||
-- Do not lose state when reset (chunkloading etc)
|
-- Do not lose state when reset (chunkloading etc)
|
||||||
state = (function ()
|
local state = (function ()
|
||||||
local path = ".state"
|
local path = ".state"
|
||||||
local state_table = {}
|
local state_table = {}
|
||||||
|
|
||||||
@ -21,6 +21,8 @@ state = (function ()
|
|||||||
})
|
})
|
||||||
end)()
|
end)()
|
||||||
|
|
||||||
|
-- Not sure whether this is a good idea
|
||||||
|
--[[
|
||||||
if state.x == nil or state.y == nil or state.z == nil or state.o == nil then
|
if state.x == nil or state.y == nil or state.z == nil or state.o == nil then
|
||||||
printError("[lib] position is not set")
|
printError("[lib] position is not set")
|
||||||
printError("[lib] defaulting to 0, 0, 0, +z")
|
printError("[lib] defaulting to 0, 0, 0, +z")
|
||||||
@ -29,6 +31,21 @@ if state.x == nil or state.y == nil or state.z == nil or state.o == nil then
|
|||||||
state.z = 0
|
state.z = 0
|
||||||
state.o = 0
|
state.o = 0
|
||||||
end
|
end
|
||||||
|
]]
|
||||||
|
|
||||||
|
local function setPosition(x, y, z, direction)
|
||||||
|
local o = ({
|
||||||
|
["+z"] = 0,
|
||||||
|
["-x"] = 1,
|
||||||
|
["-z"] = 2,
|
||||||
|
["+x"] = 3,
|
||||||
|
})[direction]
|
||||||
|
|
||||||
|
state.x = x
|
||||||
|
state.y = y
|
||||||
|
state.z = z
|
||||||
|
state.o = o
|
||||||
|
end
|
||||||
|
|
||||||
--[[
|
--[[
|
||||||
orientation:
|
orientation:
|
||||||
@ -38,11 +55,7 @@ end
|
|||||||
3 = East (+x)
|
3 = East (+x)
|
||||||
]]
|
]]
|
||||||
|
|
||||||
function getOrientation()
|
local function move(raw_move, position_update)
|
||||||
return ({"+z", "-x", "-z", "+x"})[1 + state.o]
|
|
||||||
end
|
|
||||||
|
|
||||||
function move(raw_move, position_update)
|
|
||||||
return function()
|
return function()
|
||||||
success, err = raw_move()
|
success, err = raw_move()
|
||||||
if not success then
|
if not success then
|
||||||
@ -53,40 +66,80 @@ function move(raw_move, position_update)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local fwd = move(turtle.forward, function()
|
||||||
|
if state.o == 1 or state.o == 3 then
|
||||||
|
state.x = state.x + ((state.o == 1) and -1 or 1)
|
||||||
|
elseif state.o == 0 or state.o == 2 then
|
||||||
|
state.z = state.z + ((state.o == 2) and -1 or 1)
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
local back = move(turtle.back, function()
|
||||||
|
if state.o == 1 or state.o == 3 then
|
||||||
|
state.x = state.x + ((state.o == 1 and 1 or -1))
|
||||||
|
elseif state.o == 0 or state.o == 2 then
|
||||||
|
state.z = state.z + ((state.o == 2) and 1 or -1)
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
local up = move(turtle.up, function()
|
||||||
|
state.y = state.y + 1
|
||||||
|
end)
|
||||||
|
|
||||||
|
local down = move(turtle.down, function()
|
||||||
|
state.y = state.y - 1
|
||||||
|
end)
|
||||||
|
|
||||||
|
local left = move(turtle.turnLeft, function()
|
||||||
|
state.o = (state.o - 1) % 4
|
||||||
|
end)
|
||||||
|
|
||||||
|
local right = move(turtle.turnRight, function()
|
||||||
|
state.o = (state.o + 1) % 4
|
||||||
|
end)
|
||||||
|
|
||||||
|
local function getOrientation()
|
||||||
|
return ({"+z", "-x", "-z", "+x"})[1 + state.o]
|
||||||
|
end
|
||||||
|
|
||||||
|
local function rotateTowards(direction)
|
||||||
|
local target_o = ({
|
||||||
|
["+z"] = 0,
|
||||||
|
["-x"] = 1,
|
||||||
|
["-z"] = 2,
|
||||||
|
["+x"] = 3,
|
||||||
|
})[direction]
|
||||||
|
|
||||||
|
if not target_o then
|
||||||
|
error(tostring(direction) .. " is not a valid direction.")
|
||||||
|
end
|
||||||
|
|
||||||
|
local delta_o = (target_o - state.o) % 4
|
||||||
|
|
||||||
|
if delta_o == 0 then
|
||||||
|
-- orientation already correct
|
||||||
|
elseif delta_o == 1 then
|
||||||
|
right()
|
||||||
|
elseif delta_o == 2 then
|
||||||
|
right()
|
||||||
|
right()
|
||||||
|
elseif delta_o == 3 then
|
||||||
|
left()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
state = state,
|
state = state,
|
||||||
|
|
||||||
|
fwd = fwd,
|
||||||
|
back = back,
|
||||||
|
up = up,
|
||||||
|
down = down,
|
||||||
|
left = left,
|
||||||
|
right = right,
|
||||||
|
|
||||||
|
setPosition = setPosition,
|
||||||
getOrientation = getOrientation,
|
getOrientation = getOrientation,
|
||||||
|
rotateTowards = rotateTowards,
|
||||||
fwd = move(turtle.forward, function()
|
|
||||||
if state.o == 1 or state.o == 3 then
|
|
||||||
state.x = state.x + ((state.o == 1) and -1 or 1)
|
|
||||||
elseif state.o == 0 or state.o == 2 then
|
|
||||||
state.z = state.z + ((state.o == 2) and -1 or 1)
|
|
||||||
end
|
|
||||||
end),
|
|
||||||
|
|
||||||
back = move(turtle.back, function()
|
|
||||||
if state.o == 1 or state.o == 3 then
|
|
||||||
state.x = state.x + ((state.o == 1 and 1 or -1))
|
|
||||||
elseif state.o == 0 or state.o == 2 then
|
|
||||||
state.z = state.z + ((state.o == 2) and 1 or -1)
|
|
||||||
end
|
|
||||||
end),
|
|
||||||
|
|
||||||
up = move(turtle.up, function()
|
|
||||||
state.y = state.y + 1
|
|
||||||
end),
|
|
||||||
|
|
||||||
down = move(turtle.down, function()
|
|
||||||
state.y = state.y - 1
|
|
||||||
end),
|
|
||||||
|
|
||||||
left = move(turtle.turnLeft, function()
|
|
||||||
state.o = (state.o - 1) % 4
|
|
||||||
end),
|
|
||||||
|
|
||||||
right = move(turtle.turnRight, function()
|
|
||||||
state.o = (state.o + 1) % 4
|
|
||||||
end),
|
|
||||||
}
|
}
|
239
kai/woodfarm.lua
Normal file
239
kai/woodfarm.lua
Normal file
@ -0,0 +1,239 @@
|
|||||||
|
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
|
||||||
|
|
||||||
|
["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
|
Loading…
Reference in New Issue
Block a user