Implement wood farm
This commit is contained in:
parent
784106e5b7
commit
1f765d59a7
99
kai/lib.lua
99
kai/lib.lua
@ -1,5 +1,5 @@
|
||||
-- Do not lose state when reset (chunkloading etc)
|
||||
state = (function ()
|
||||
local state = (function ()
|
||||
local path = ".state"
|
||||
local state_table = {}
|
||||
|
||||
@ -21,6 +21,8 @@ state = (function ()
|
||||
})
|
||||
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
|
||||
printError("[lib] position is not set")
|
||||
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.o = 0
|
||||
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:
|
||||
@ -38,11 +55,7 @@ end
|
||||
3 = East (+x)
|
||||
]]
|
||||
|
||||
function getOrientation()
|
||||
return ({"+z", "-x", "-z", "+x"})[1 + state.o]
|
||||
end
|
||||
|
||||
function move(raw_move, position_update)
|
||||
local function move(raw_move, position_update)
|
||||
return function()
|
||||
success, err = raw_move()
|
||||
if not success then
|
||||
@ -53,40 +66,80 @@ function move(raw_move, position_update)
|
||||
end
|
||||
end
|
||||
|
||||
return {
|
||||
state = state,
|
||||
|
||||
getOrientation = getOrientation,
|
||||
|
||||
fwd = move(turtle.forward, function()
|
||||
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),
|
||||
end)
|
||||
|
||||
back = move(turtle.back, function()
|
||||
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),
|
||||
end)
|
||||
|
||||
up = move(turtle.up, function()
|
||||
local up = move(turtle.up, function()
|
||||
state.y = state.y + 1
|
||||
end),
|
||||
end)
|
||||
|
||||
down = move(turtle.down, function()
|
||||
local down = move(turtle.down, function()
|
||||
state.y = state.y - 1
|
||||
end),
|
||||
end)
|
||||
|
||||
left = move(turtle.turnLeft, function()
|
||||
local left = move(turtle.turnLeft, function()
|
||||
state.o = (state.o - 1) % 4
|
||||
end),
|
||||
end)
|
||||
|
||||
right = move(turtle.turnRight, function()
|
||||
local right = move(turtle.turnRight, function()
|
||||
state.o = (state.o + 1) % 4
|
||||
end),
|
||||
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 {
|
||||
state = state,
|
||||
|
||||
fwd = fwd,
|
||||
back = back,
|
||||
up = up,
|
||||
down = down,
|
||||
left = left,
|
||||
right = right,
|
||||
|
||||
setPosition = setPosition,
|
||||
getOrientation = getOrientation,
|
||||
rotateTowards = rotateTowards,
|
||||
}
|
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