Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- -- drop_line.lua (CC:Tweaked)
- -- Usage:
- -- drop_line <incrementDir> [numPasses]
- -- Examples:
- -- drop_line right 4
- -- drop_line up
- --
- -- Behavior:
- -- 1) right 4 -> Measure first pass length until front obstacle; then do 4 passes,
- -- shifting 1 block to the right between passes in zig-zag (R,R then L,L ...).
- -- 2) up -> After each pass, move up 1 and turn around; repeat until "up" is blocked.
- -- When "up" is blocked, do ONE FINAL opposite-direction pass that also places
- -- a block behind on each step, then stop.
- local args = {...}
- if #args < 1 then
- print("Usage: drop_line <right|left|up|down> [numPasses]")
- return
- end
- local incDir = string.lower(args[1])
- local fixedPasses = nil
- if args[2] ~= nil then
- fixedPasses = tonumber(args[2])
- if not fixedPasses or fixedPasses < 1 then
- print("Invalid numPasses: "..tostring(args[2]))
- return
- end
- end
- local function isUnlimitedFuel()
- return turtle.getFuelLevel() == "unlimited"
- end
- local function tryRefuelAll()
- if isUnlimitedFuel() then return true end
- for slot=1,16 do
- local detail = turtle.getItemDetail(slot)
- if detail then
- turtle.select(slot)
- -- One big gulp; if not fuel, refuel() returns false and nothing is consumed
- turtle.refuel(64)
- if isUnlimitedFuel() then return true end
- end
- end
- return turtle.getFuelLevel() > 0 or isUnlimitedFuel()
- end
- local function ensureFuel()
- if not tryRefuelAll() then
- print("Warning: out of fuel and no refuel items found.")
- end
- end
- local function attackClear(moveFn, detectFn, digFn, attackFn)
- -- Keep trying to clear entities; return true if space is clear after attempts
- local tries = 0
- while detectFn() do
- digFn()
- attackFn()
- tries = tries + 1
- if tries > 8 then break end
- end
- return not detectFn()
- end
- local function forward()
- local tries = 0
- while not turtle.forward() do
- -- If blocked, try to dig/attack
- attackClear(turtle.forward, turtle.detect, turtle.dig, turtle.attack)
- if turtle.forward() then return true end
- tries = tries + 1
- if tries > 8 then return false end
- sleep(0.1)
- end
- return true
- end
- local function up()
- local tries = 0
- while not turtle.up() do
- attackClear(turtle.up, turtle.detectUp, turtle.digUp, turtle.attackUp)
- if turtle.up() then return true end
- tries = tries + 1
- if tries > 6 then return false end
- sleep(0.1)
- end
- return true
- end
- local function down()
- local tries = 0
- while not turtle.down() do
- attackClear(turtle.down, turtle.detectDown, turtle.digDown, turtle.attackDown)
- if turtle.down() then return true end
- tries = tries + 1
- if tries > 6 then return false end
- sleep(0.1)
- end
- return true
- end
- local function turnRight() turtle.turnRight() end
- local function turnLeft() turtle.turnLeft() end
- local function turnAround() turnRight(); turnRight() end
- local function selectPlaceableSlot()
- -- Pick any slot with an item; prefer non-fuel if possible by trying all slots
- -- We just cycle from 1..16 each time; quickest working heuristic.
- for slot=1,16 do
- local data = turtle.getItemDetail(slot)
- if data and data.count > 0 then
- turtle.select(slot)
- return true
- end
- end
- return false
- end
- local function placeDownEnsured()
- if turtle.detectDown() then return true end
- if not selectPlaceableSlot() then return false end
- return turtle.placeDown()
- end
- local function placeFrontEnsured()
- if turtle.detect() then return true end
- if not selectPlaceableSlot() then return false end
- return turtle.place()
- end
- local function placeBehindEnsured()
- -- Turn around, place forward, turn back
- turnAround()
- local ok = placeFrontEnsured()
- turnAround()
- return ok
- end
- local function stepForwardWithPlacement(opts)
- -- opts: { dropDown=true/false, dropBehind=false }
- local dropDown = opts and opts.dropDown ~= false -- default true
- local dropBehind = opts and opts.dropBehind == true
- if dropDown then
- if not placeDownEnsured() then
- print("No placeable blocks for placeDown()")
- return false
- end
- end
- if not forward() then
- print("Blocked: cannot move forward.")
- return false
- end
- if dropBehind then
- if not placeBehindEnsured() then
- print("No placeable blocks for placeBehind()")
- -- Not fatal; keep going
- end
- end
- return true
- end
- local function measureFirstPassLength()
- -- Perform the measuring pass WITHOUT consuming its endpoint turn logic.
- -- We drop down each step, move forward until front is blocked.
- local steps = 0
- while not turtle.detect() do
- if not stepForwardWithPlacement({dropDown=true}) then
- return nil, "Failed during first-pass forward movement."
- end
- steps = steps + 1
- end
- return steps
- end
- local function doPass(steps, opts)
- -- Walk exactly 'steps' forward-steps, dropping blocks each step.
- -- opts: { dropDown=true/false, dropBehind=false }
- for i=1,steps do
- if not stepForwardWithPlacement(opts) then
- return false, "Pass interrupted by obstacle."
- end
- end
- return true
- end
- local function incrementRightTurnback(passIndex)
- -- Zig-zag lateral shift "right": odd passes end -> R, forward 1, R; even -> L, forward 1, L
- if passIndex % 2 == 1 then
- turnRight()
- if not forward() then return false, "Cannot shift right between passes." end
- turnRight()
- else
- turnLeft()
- if not forward() then return false, "Cannot shift right between passes." end
- turnLeft()
- end
- return true
- end
- local function incrementLeftTurnback(passIndex)
- -- Mirror of "right"
- if passIndex % 2 == 1 then
- turnLeft()
- if not forward() then return false, "Cannot shift left between passes." end
- turnLeft()
- else
- turnRight()
- if not forward() then return false, "Cannot shift left between passes." end
- turnRight()
- end
- return true
- end
- local function incrementUpTurnback()
- if not up() then return false end
- turnAround()
- return true
- end
- local function incrementDownTurnback()
- if not down() then return false end
- turnAround()
- return true
- end
- local function doRightFixedPasses(totalPasses, passLen)
- for p=1,totalPasses-1 do
- -- After each pass except the last, increment lateral + turnback
- local ok, msg = nil, nil
- if p % 2 == 1 then
- ok, msg = incrementRightTurnback(p)
- else
- ok, msg = incrementRightTurnback(p)
- end
- if not ok then return false, msg end
- -- next pass runs opposite direction but same length
- end
- return true
- end
- local function doLeftFixedPasses(totalPasses, passLen)
- for p=1,totalPasses-1 do
- local ok, msg = incrementLeftTurnback(p)
- if not ok then return false, msg end
- end
- return true
- end
- -- MAIN FLOW
- ensureFuel()
- -- Validate increment direction
- local inc = incDir
- if inc ~= "right" and inc ~= "left" and inc ~= "up" and inc ~= "down" then
- print("incrementDir must be one of: right, left, up, down")
- return
- end
- -- 1) First pass: go forward, drop-down each step, stop when front obstacle encountered
- local firstLen, err = measureFirstPassLength()
- if not firstLen then
- print("First pass failed: "..tostring(err))
- return
- end
- -- If zero-length (immediately blocked), just stop
- if firstLen == 0 then
- print("First pass length 0; nothing to do.")
- return
- end
- -- 2) Execute the remaining passes per mode:
- if fixedPasses ~= nil then
- -- Fixed number of passes (e.g., "right 4")
- -- We already completed pass #1 (at current position, facing the obstacle).
- -- Now we must do (fixedPasses-1) further passes of the same length,
- -- shifting in the requested lateral direction between passes.
- for p=2,fixedPasses do
- -- Increment step+turnback before each new pass (except pass #1 which we already did)
- local ok, msg
- if inc == "right" then
- ok, msg = incrementRightTurnback(p-1)
- elseif inc == "left" then
- ok, msg = incrementLeftTurnback(p-1)
- elseif inc == "up" then
- ok, msg = incrementUpTurnback()
- elseif inc == "down" then
- ok, msg = incrementDownTurnback()
- end
- if not ok then
- print("Increment failed between passes: "..tostring(msg or ""))
- return
- end
- local ok2, msg2 = doPass(firstLen, {dropDown=true})
- if not ok2 then
- print("Pass "..p.." failed: "..tostring(msg2 or ""))
- return
- end
- end
- print("Completed "..fixedPasses.." passes of length "..firstLen..".")
- else
- -- Variable passes until blocked in increment direction (intended for "up" case).
- -- After each pass, try to increment; if increment fails (blocked), then do ONE FINAL
- -- opposite-direction pass with "dropBehind=true" on each step, then stop.
- if inc ~= "up" and inc ~= "down" then
- print("When numPasses is omitted, use 'up' or 'down'.")
- return
- end
- while true do
- -- Try to increment (move up/down and turn around)
- local incOK = false
- if inc == "up" then incOK = incrementUpTurnback()
- else incOK = incrementDownTurnback()
- end
- if not incOK then
- -- Final pass with blocks behind on each step, then finish
- local okFinal, msgFinal = doPass(firstLen, {dropDown=true, dropBehind=true})
- if not okFinal then
- print("Final behind-pass failed: "..tostring(msgFinal or ""))
- else
- print("Reached increment obstacle; final behind-pass completed.")
- end
- return
- end
- -- Normal opposite-direction pass, same length
- local ok2, msg2 = doPass(firstLen, {dropDown=true})
- if not ok2 then
- print("Pass failed after increment: "..tostring(msg2 or ""))
- return
- end
- -- Loop continues: attempt another increment until blocked
- end
- end
Add Comment
Please, Sign In to add comment