-- 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")