1
0
cc-utilities/randbuild.lua
2023-05-11 21:45:49 +03:00

123 lines
3.2 KiB
Lua

-- Removes blocks which are not placeable
local function removeNonBlocks()
-- Travel to the ground to test if it can place each item
local traveled = 0
while not turtle.detectDown() do turtle.down() traveled = traveled + 1 end
local blocks = {}
-- Try placing each item and look at the error message produced
-- If the message contains 'item' then it is an item
for i=1, 16 do
blocks[i] = turtle.getItemDetail(i)
if blocks[i] then
turtle.select(i)
local _, reason = turtle.placeDown()
if reason:match("item") then
print(("Found non-block in slot '%s'"):format(i))
blocks[i] = true
end
end
end
-- Travel back up to where the turtle started
for _=1, traveled do turtle.up() end
-- Drop all the items marked as non-blocks
for i, details in pairs(blocks) do
if type(details) ~= "table" then
turtle.select(i)
turtle.drop()
blocks[i] = nil
end
end
return blocks
end
local function followPath(walk_path)
local command_lookup = {
U = turtle.up, D = turtle.down,
F = turtle.forward, B = turtle.back,
L = turtle.turnLeft, R = turtle.turnRight
}
local count, op = 0, ""
local pattern_iterator = walk_path:gmatch("(%d+)([UDFBLR])")
return function()
while true do
if count == 0 then
count, op = pattern_iterator()
if not (count and op) then return end
end
command_lookup[op]()
count = count - 1
if op ~= "L" and op ~= "R" then
return count, op
end
end
end
end
local function getTravelCost(walk_path)
local distance = 0
for count, op in walk_path:gmatch("(%d+)([UDFBLR])") do
if op ~= "L" and op ~= "R" then
distance = distance + count
end
end
return distance
end
-- Main
math.randomseed(os.epoch())
local build_path = "6F 1R 20F 1R 14F 1R 20F 1R 5F"
local travel_cost = getTravelCost(build_path)
if travel_cost > turtle.getFuelLevel() then
print(("- Insufficient fuel level %s, needed %s"):format(turtle.getFuelLevel(), travel_cost))
return
end
print(("- Sufficient fuel level %s, needed %s"):format(turtle.getFuelLevel(), travel_cost))
print("- Removing items which are not blocks")
local blocks_lookup = {}
local total_blocks = 0
for i, details in pairs(removeNonBlocks()) do
local name = ("%s/%s"):format(details.name, details.damage or 0)
blocks_lookup[name] = blocks_lookup[name] or {}
blocks_lookup[name][i] = details.count
blocks_lookup[name].total = (blocks_lookup[name].total or 0) + details.count
total_blocks = total_blocks + details.count
end
turtle.up()
if travel_cost > total_blocks then
print(("- Insufficient block count %s, needed %s"):format(total_blocks, travel_cost))
return
end
print(("- Sufficient block count %s, needed %s"):format(total_blocks, travel_cost))
print(("- Following path and building: '%s'"):format(build_path))
for _ in followPath(build_path) do
local target_name, target_score
for name, details in pairs(blocks_lookup) do
local score = details.total * math.random()
if not target_score or score > target_score then
target_score = score
target_name = name
end
end
local target_block = blocks_lookup[target_name]
for i=1, 16 do
if target_block[i] and target_block[i] > 0 then
turtle.select(i)
target_block[i] = target_block[i] - 1
target_block.total = target_block.total - 1
break
end
end
turtle.placeDown()
end
print("- Finished")