Last active
May 26, 2025 00:10
-
-
Save dyc3/8be236e95d41009358725eb2fc64d01c to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| -- 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