265 lines
6.7 KiB
Lua
265 lines
6.7 KiB
Lua
local T = require("lib")
|
|
|
|
--[[
|
|
|
|
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 breakpoint()
|
|
write("Enter to step ")
|
|
repeat e, d = os.pullEvent() until e == "key" and d == 257
|
|
print("(OK)")
|
|
end
|
|
|
|
local function calculate_tree_position(row_index, tree_index)
|
|
|
|
local x = (row_index - 1) * 5
|
|
local z
|
|
|
|
if row_index % 2 == 1 then
|
|
z = -2 * tree_index
|
|
else
|
|
z = -30 + 2 * tree_index
|
|
end
|
|
|
|
return x, z
|
|
end
|
|
|
|
local function greedy_move(x, z, o)
|
|
print("Move Target: " .. 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_tree < 3 or T.state.current_tree > 12 then
|
|
breakpoint()
|
|
end
|
|
|
|
if T.state.current_row ~= 1 and T.state.current_tree == 1 then
|
|
print("new row")
|
|
-- we just turned towards a new row and are approaching in positive x direction
|
|
x = x - 1
|
|
o = "+x"
|
|
elseif T.state.current_row % 2 == 0 then
|
|
print("even row")
|
|
-- we are in an even row and approaching in positive z direction
|
|
z = z - 1
|
|
o = "+z"
|
|
else
|
|
print("odd row")
|
|
-- 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 success 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 success or data.name ~= LOG_NAME then
|
|
-- chopped all the wood
|
|
break
|
|
end
|
|
turtle.digUp()
|
|
if T.state.y == TREE_MAX_Y - 1 then
|
|
print("below last log")
|
|
breakpoint()
|
|
-- 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
|
|
turtle.placeDown()
|
|
|
|
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)
|
|
|
|
if turtle.getFuelLevel() < FUEL_LEVEL_TARGET then
|
|
local fuel_count = math.ceil((FUEL_LEVEL_TARGET - turtle.getFuelLevel()) / 80)
|
|
turtle.select(REFUEL_SLOT)
|
|
ensure_item_count(fuel_count)
|
|
turtle.refuel()
|
|
end
|
|
|
|
T.state.current_row = 1
|
|
T.state.current_tree = 1
|
|
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
|
|
print("---------------")
|
|
print("State: " .. T.state.current_state)
|
|
print("Pos: " .. T.state.x .. "," .. T.state.z .. "(" .. T.getOrientation() .. ")")
|
|
T.state.current_state = state_machine[T.state.current_state]()
|
|
end |