Skip to content

Instantly share code, notes, and snippets.

@dyc3
Last active May 26, 2025 00:10
Show Gist options
  • Select an option

  • Save dyc3/8be236e95d41009358725eb2fc64d01c to your computer and use it in GitHub Desktop.

Select an option

Save dyc3/8be236e95d41009358725eb2fc64d01c to your computer and use it in GitHub Desktop.
-- Wall Following Stripe Builder for ComputerCraft
-- Follows walls and replaces breakable blocks on the current Y level only
-- Direction tracking
local directions = {"north", "east", "south", "west"}
local currentDirection = 1 -- 1=north, 2=east, 3=south, 4=west
-- Configuration
local config = {
stripeBlock = "chisel:concrete_black1", -- Block to place for stripes
breakableBlock = "chisel:laboratory", -- Only block type we're allowed to break
minFuel = 100, -- Minimum fuel needed to start
}
-- Fuel management functions
local function checkAndRefuelAtStart()
print("=== Initial Fuel Check ===")
local currentFuel = turtle.getFuelLevel()
if currentFuel == "unlimited" then
print("Fuel is unlimited - ready to proceed")
return true
end
print(string.format("Current fuel level: %d", currentFuel))
if currentFuel < config.minFuel then
print(string.format("Low fuel! Need at least %d fuel to start.", config.minFuel))
print("Please add fuel to the turtle's inventory.")
while currentFuel < config.minFuel do
io.write("Press Enter after adding fuel...")
io.read()
-- Try to refuel from inventory
local refueled = false
for slot = 1, 16 do
turtle.select(slot)
if turtle.refuel(0) then -- Check if item can be used as fuel
local beforeFuel = turtle.getFuelLevel()
turtle.refuel() -- Consume the fuel
local afterFuel = turtle.getFuelLevel()
if afterFuel > beforeFuel then
print(string.format("Refueled! Fuel level: %d -> %d", beforeFuel, afterFuel))
refueled = true
currentFuel = afterFuel
break
end
end
end
if not refueled then
print("No fuel found in inventory. Please add fuel items.")
currentFuel = turtle.getFuelLevel()
end
end
end
print(string.format("Fuel check complete. Current fuel: %d", currentFuel))
print()
return true
end
-- Direction management functions
local function turnRight()
turtle.turnRight()
currentDirection = (currentDirection % 4) + 1
print(string.format("Turned right, now facing %s", directions[currentDirection]))
end
local function turnLeft()
turtle.turnLeft()
currentDirection = ((currentDirection - 2) % 4) + 1
print(string.format("Turned left, now facing %s", directions[currentDirection]))
end
local function getPosition()
local x, y, z = gps.locate()
if not x then
print("Warning: GPS not available!")
return nil, nil, nil
end
return x, y, z
end
local function determineInitialDirection()
print("=== Direction Calibration ===")
print("Determining initial facing direction using GPS...")
local startX, startY, startZ = getPosition()
if not startX then
print("GPS not available - using manual direction entry")
print("1 = North (negative Z)")
print("2 = East (positive X)")
print("3 = South (positive Z)")
print("4 = West (negative X)")
io.write("Enter direction (1-4): ")
local manualDir = tonumber(io.read())
if manualDir and manualDir >= 1 and manualDir <= 4 then
currentDirection = manualDir
print(string.format("Set direction to: %s", directions[currentDirection]))
return true
else
print("Invalid direction.")
return false
end
end
print(string.format("Starting position: (%d, %d, %d)", startX, startY, startZ))
print("Testing movement to determine direction...")
-- Try to move forward to determine direction
for attempt = 1, 4 do
print(string.format("Attempt %d/4", attempt))
local directionFound = false
if not turtle.detect() then
print("Path clear, testing movement...")
if turtle.forward() then
local newX, newY, newZ = getPosition()
if newX then
local deltaX = newX - startX
local deltaZ = newZ - startZ
print(string.format("Moved from (%d,%d,%d) to (%d,%d,%d)",
startX, startY, startZ, newX, newY, newZ))
if deltaX > 0 then
currentDirection = 2 -- east
directionFound = true
elseif deltaX < 0 then
currentDirection = 4 -- west
directionFound = true
elseif deltaZ > 0 then
currentDirection = 3 -- south
directionFound = true
elseif deltaZ < 0 then
currentDirection = 1 -- north
directionFound = true
else
print("No coordinate change detected, trying next direction...")
end
if directionFound then
print(string.format("Detected direction: %s", directions[currentDirection]))
-- Return to start position
print("Returning to starting position...")
turtle.turnRight()
turtle.turnRight()
if not turtle.forward() then
print("Warning: Could not return to starting position!")
end
turtle.turnRight()
turtle.turnRight()
currentDirection = ((currentDirection + 1) % 4) + 1
print("Direction calibration successful!")
return true
end
else
print("GPS failed during movement test")
end
else
print("Failed to move forward despite clear path")
end
else
print("Path blocked, trying next direction...")
end
-- If we haven't found direction yet and have more attempts, turn right
if not directionFound and attempt < 4 then
turtle.turnRight()
end
end
print("Could not determine direction automatically")
print("1 = North (negative Z)")
print("2 = East (positive X)")
print("3 = South (positive Z)")
print("4 = West (negative X)")
io.write("Enter direction manually (1-4): ")
local manualDir = tonumber(io.read())
if manualDir and manualDir >= 1 and manualDir <= 4 then
currentDirection = manualDir
print(string.format("Manually set direction to: %s", directions[currentDirection]))
return true
else
print("Invalid direction.")
return false
end
end
local function inspectBlock(direction)
local success, data
if direction == "forward" then
success, data = turtle.inspect()
elseif direction == "right" then
turnRight()
success, data = turtle.inspect()
turnLeft()
elseif direction == "left" then
turnLeft()
success, data = turtle.inspect()
turnRight()
elseif direction == "back" then
turnRight()
turnRight()
success, data = turtle.inspect()
turnRight()
turnRight()
end
if not success then
return nil -- No block
end
return data.name
end
local function selectStripeBlock()
for slot = 1, 16 do
turtle.select(slot)
local item = turtle.getItemDetail()
if item and item.name == config.stripeBlock then
return true
end
end
return false
end
local function waitForBlocks()
while not selectStripeBlock() do
print("No stripe blocks available. Please fill turtle inventory with stripe blocks.")
io.write("Press Enter when ready...")
io.read()
end
end
local function replaceBlockIfNeeded(direction)
local blockName = inspectBlock(direction)
if blockName == config.breakableBlock then
print(string.format("Found breakable block (%s) in %s direction - replacing with stripe block",
config.breakableBlock, direction))
waitForBlocks()
if direction == "forward" then
turtle.dig()
turtle.place()
elseif direction == "right" then
turnRight()
turtle.dig()
turtle.place()
turnLeft()
elseif direction == "left" then
turnLeft()
turtle.dig()
turtle.place()
turnRight()
elseif direction == "back" then
turnRight()
turnRight()
turtle.dig()
turtle.place()
turnRight()
turnRight()
end
return true
end
return false
end
local function scanAndReplace()
print("Scanning current position for breakable blocks on same Y level...")
local x, y, z = getPosition()
if x then
print(string.format("Position: (%d, %d, %d), facing %s", x, y, z, directions[currentDirection]))
end
local replaced = 0
-- Check all 4 horizontal directions only (same Y level)
if replaceBlockIfNeeded("forward") then replaced = replaced + 1 end
if replaceBlockIfNeeded("right") then replaced = replaced + 1 end
if replaceBlockIfNeeded("left") then replaced = replaced + 1 end
if replaceBlockIfNeeded("back") then replaced = replaced + 1 end
if replaced > 0 then
print(string.format("Replaced %d blocks at this position", replaced))
end
return replaced
end
local function canMoveForward()
return not turtle.detect()
end
local function hasWallOnRight()
turnRight()
local hasWall = turtle.detect()
turnLeft()
return hasWall
end
local function moveForward()
if turtle.forward() then
local x, y, z = getPosition()
if x then
print(string.format("Moved to (%d, %d, %d)", x, y, z))
end
return true
end
return false
end
local function followWall()
print("=== Starting Wall Following ===")
print(string.format("Target blocks to replace: %s -> %s", config.breakableBlock, config.stripeBlock))
print("Only checking blocks on the current Y level (horizontal plane)")
print("Instructions:")
print("- Turtle will follow walls and replace breakable blocks")
print("- When out of blocks, turtle will pause and wait")
print("- Press Ctrl+T to stop the program")
print()
local totalReplaced = 0
local stepCount = 0
local startY = nil
-- Record starting Y level
local x, y, z = getPosition()
if y then
startY = y
print(string.format("Working on Y level: %d", startY))
end
while true do
stepCount = stepCount + 1
-- Check if we're still on the same Y level
local currentX, currentY, currentZ = getPosition()
if currentY and startY and currentY ~= startY then
print(string.format("Warning: Y level changed from %d to %d", startY, currentY))
startY = currentY
end
-- Scan and replace blocks at current position
local replaced = scanAndReplace()
totalReplaced = totalReplaced + replaced
-- Wall following algorithm (right-hand rule)
if not hasWallOnRight() then
-- No wall on right, turn right and try to move
turnRight()
if canMoveForward() then
moveForward()
else
-- Can't move right, turn back left
turnLeft()
end
elseif canMoveForward() then
-- Wall on right, path clear ahead - move forward
moveForward()
else
-- Wall on right, wall ahead - turn left
turnLeft()
end
-- Status update every 20 steps
if stepCount % 20 == 0 then
if currentY then
print(string.format("Step %d: Y=%d, Replaced %d blocks total, Fuel: %d",
stepCount, currentY, totalReplaced, turtle.getFuelLevel()))
else
print(string.format("Step %d: Replaced %d blocks total, Fuel: %d",
stepCount, totalReplaced, turtle.getFuelLevel()))
end
end
-- Small delay to prevent overwhelming the system
os.sleep(0.1)
end
end
local function getUserInput()
print("=== Wall Following Stripe Builder (Y-Level Only) ===")
print("Current configuration:")
print(string.format(" Stripe block: %s", config.stripeBlock))
print(string.format(" Will replace: %s", config.breakableBlock))
print(" Scope: Current Y level only (no up/down)")
print()
io.write("Change stripe block type? (y/n): ")
local changeStripe = io.read()
if changeStripe:lower() == "y" then
io.write("Enter stripe block type: ")
config.stripeBlock = io.read()
end
io.write("Change breakable block type? (y/n): ")
local changeBreakable = io.read()
if changeBreakable:lower() == "y" then
io.write("Enter breakable block type: ")
config.breakableBlock = io.read()
end
print()
print("Final configuration:")
print(string.format(" Stripe block: %s", config.stripeBlock))
print(string.format(" Will replace: %s", config.breakableBlock))
print(" Scope: Current Y level only")
print()
io.write("Start wall following? (y/n): ")
local confirm = io.read()
return confirm:lower() == "y"
end
-- Main function
local function main()
-- FIRST: Check fuel before anything else
if not checkAndRefuelAtStart() then
print("Failed to ensure adequate fuel. Exiting.")
return
end
-- SECOND: Determine initial direction (now that we have fuel)
if not determineInitialDirection() then
print("Failed to determine direction. Exiting.")
return
end
-- THIRD: Get user configuration
if not getUserInput() then
print("Operation cancelled.")
return
end
-- FOURTH: Start wall following
followWall()
end
-- Run the program
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment