Skip to content

Instantly share code, notes, and snippets.

@dyc3
Last active May 25, 2025 23:27
Show Gist options
  • Select an option

  • Save dyc3/06014e1c94911b639dda081e96c183b1 to your computer and use it in GitHub Desktop.

Select an option

Save dyc3/06014e1c94911b639dda081e96c183b1 to your computer and use it in GitHub Desktop.
-- Torus Stripe Builder for ComputerCraft
-- Adds horizontal stripes to an existing torus structure
-- Direction tracking
local directions = {"north", "east", "south", "west"}
local currentDirection = 1 -- 1=north, 2=east, 3=south, 4=west
-- Forward declarations
local moveToPosition
-- Configuration
local config = {
-- Torus parameters
centerX = 1570, -- Torus center coordinates
centerY = 139, -- Torus center coordinates
centerZ = 506, -- Torus center coordinates
outerRadius = 200, -- Distance from center to tube center
tubeRadius = 41, -- Radius of the tube itself
-- Stripe parameters
stripeOffset = 10, -- Distance from midY to stripe centers
stripeWidth = 4, -- Width of stripes in Y direction
-- Block types
stripeBlock = "chisel:concrete_black1", -- Block to place for stripes
breakableBlock = "chisel:laboratory", -- Only block type we're allowed to break
-- Operational parameters
fuelChestPos = {x = 1574, y = 151, z = 509}, -- Position of fuel chest
blockChestPos = {x = 1572, y = 151, z = 509}, -- Position of block chest
minFuel = 1000, -- Minimum fuel before refueling
fuelItem = "minecraft:charcoal", -- Fuel type
}
-- 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 turnAround()
turtle.turnRight()
turtle.turnRight()
currentDirection = ((currentDirection + 1) % 4) + 1
print(string.format("Turned around, now facing %s", directions[currentDirection]))
end
local function faceDirection(targetDirection)
-- targetDirection: 1=north, 2=east, 3=south, 4=west
while currentDirection ~= targetDirection do
local clockwiseTurns = (targetDirection - currentDirection) % 4
if clockwiseTurns <= 2 then
turnRight()
else
turnLeft()
end
end
end
local function determineInitialDirection()
print("=== Direction Calibration Test ===")
print("Determining initial facing direction using GPS...")
print("WARNING: This test will NOT break any blocks - please ensure clear path!")
local startX, startY, startZ = gps.locate()
if not startX then
error("GPS not available! Please ensure GPS towers are set up.")
end
print(string.format("Starting position: (%d, %d, %d)", startX, startY, startZ))
-- Try all 4 directions to find one that's clear
local foundDirection = false
for attempt = 1, 4 do
print(string.format("Testing direction %d/4...", attempt))
-- Check if path is clear
local canMove = not turtle.detect()
if canMove then
print("Path is clear, moving forward one block...")
if turtle.forward() then
local newX, newY, newZ = gps.locate()
print(string.format("New position: (%d, %d, %d)", newX, newY, newZ))
-- Calculate direction based on movement
local deltaX = newX - startX
local deltaZ = newZ - startZ
if deltaX > 0 then
currentDirection = 2 -- east
elseif deltaX < 0 then
currentDirection = 4 -- west
elseif deltaZ > 0 then
currentDirection = 3 -- south
elseif deltaZ < 0 then
currentDirection = 1 -- north
else
print("Warning: No movement detected, trying next direction...")
-- Turn to try next direction
if attempt < 4 then
turtle.turnRight()
end
-- Continue to next iteration
end
if deltaX ~= 0 or deltaZ ~= 0 then
print(string.format("Detected facing direction: %s", directions[currentDirection]))
print("Moving back to starting position...")
-- Move back to starting position
turtle.turnRight()
turtle.turnRight()
currentDirection = ((currentDirection + 1) % 4) + 1
if not turtle.forward() then
print("Warning: Cannot return to starting position!")
else
-- Turn back to original direction
turtle.turnRight()
turtle.turnRight()
currentDirection = ((currentDirection + 1) % 4) + 1
print(string.format("Returned to starting position, facing %s", directions[currentDirection]))
end
foundDirection = true
break
end
else
print("Failed to move forward despite clear path, trying next direction...")
end
else
print("Path blocked, trying next direction...")
end
-- Turn to try next direction
if attempt < 4 then
turtle.turnRight()
end
end
if not foundDirection then
print("ERROR: Could not find a clear direction for calibration!")
print("Please ensure the turtle has at least one clear path (no blocks) in any direction.")
print("Alternative: You can manually specify the direction:")
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) or 0 to abort: ")
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]))
foundDirection = true
else
print("Calibration aborted.")
return false
end
end
print("Direction calibration complete!")
print()
return foundDirection
end
-- Utility functions
local function distance3D(x1, y1, z1, x2, y2, z2)
return math.sqrt((x2-x1)^2 + (y2-y1)^2 + (z2-z1)^2)
end
local function getPosition()
local x, y, z = gps.locate()
if not x then
error("GPS not available! Please ensure GPS towers are set up.")
end
return x, y, z
end
local function moveToChestPosition(chestX, chestY, chestZ)
-- Try to find an adjacent position to the chest
local adjacentPositions = {
{x = chestX + 1, y = chestY, z = chestZ, face = 4}, -- East of chest, face west
{x = chestX - 1, y = chestY, z = chestZ, face = 2}, -- West of chest, face east
{x = chestX, y = chestY, z = chestZ + 1, face = 1}, -- South of chest, face north
{x = chestX, y = chestY, z = chestZ - 1, face = 3}, -- North of chest, face south
{x = chestX, y = chestY + 1, z = chestZ, face = 0}, -- Above chest, no specific facing
{x = chestX, y = chestY - 1, z = chestZ, face = 0}, -- Below chest, no specific facing
}
print(string.format("Finding position adjacent to chest at (%d, %d, %d)", chestX, chestY, chestZ))
for _, pos in ipairs(adjacentPositions) do
if moveToPosition(pos.x, pos.y, pos.z, true) then
-- Face the chest if we're not above/below it
if pos.face ~= 0 then
faceDirection(pos.face)
end
print(string.format("Positioned adjacent to chest at (%d, %d, %d)", pos.x, pos.y, pos.z))
return true
end
end
print("Warning: Could not find accessible position adjacent to chest!")
return false
end
local function canBreakBlock(direction)
local success, data
if direction == "forward" then
success, data = turtle.inspect()
elseif direction == "up" then
success, data = turtle.inspectUp()
elseif direction == "down" then
success, data = turtle.inspectDown()
end
if not success then
return true -- No block, can move
end
return data.name == config.breakableBlock
end
local function safeMove(direction)
local moveFunc, digFunc
if direction == "forward" then
moveFunc = turtle.forward
digFunc = turtle.dig
elseif direction == "up" then
moveFunc = turtle.up
digFunc = turtle.digUp
elseif direction == "down" then
moveFunc = turtle.down
digFunc = turtle.digDown
end
local attempts = 0
while not moveFunc() do
attempts = attempts + 1
if attempts > 10 then
return false -- Give up after 10 attempts
end
if canBreakBlock(direction) then
digFunc()
else
-- Can't break the block, need to find alternate path
return false
end
end
return true
end
local function findAlternatePath(targetX, targetY, targetZ)
local currentX, currentY, currentZ = getPosition()
-- Try different approaches to reach the target
local approaches = {
{x = targetX, y = targetY + 1, z = targetZ}, -- Above target
{x = targetX, y = targetY - 1, z = targetZ}, -- Below target
{x = targetX + 1, y = targetY, z = targetZ}, -- Adjacent positions
{x = targetX - 1, y = targetY, z = targetZ},
{x = targetX, y = targetY, z = targetZ + 1},
{x = targetX, y = targetY, z = targetZ - 1},
}
for _, approach in ipairs(approaches) do
if moveToPosition(approach.x, approach.y, approach.z, true) then
return approach
end
end
return nil -- No alternate path found
end
-- Main movement function (now properly declared after findAlternatePath)
function moveToPosition(targetX, targetY, targetZ, pathfinding)
local currentX, currentY, currentZ = getPosition()
print(string.format("Moving from (%d,%d,%d) to (%d,%d,%d), currently facing %s",
currentX, currentY, currentZ, targetX, targetY, targetZ, directions[currentDirection]))
-- Move in Y direction first to avoid getting stuck
local deltaY = targetY - currentY
if deltaY > 0 then
for i = 1, deltaY do
if not safeMove("up") then
if pathfinding then
return false
else
print("Blocked moving up, trying alternate path...")
local altPos = findAlternatePath(targetX, targetY, targetZ)
if not altPos then
print("Warning: Could not reach target position, skipping...")
return false
end
return true
end
end
end
elseif deltaY < 0 then
for i = 1, -deltaY do
if not safeMove("down") then
if pathfinding then
return false
else
print("Blocked moving down, trying alternate path...")
local altPos = findAlternatePath(targetX, targetY, targetZ)
if not altPos then
print("Warning: Could not reach target position, skipping...")
return false
end
return true
end
end
end
end
-- Update current position after Y movement
currentX, currentY, currentZ = getPosition()
-- Move in X direction
local deltaX = targetX - currentX
if deltaX > 0 then
-- Need to go east (positive X)
faceDirection(2) -- east
for i = 1, deltaX do
if not safeMove("forward") then
if pathfinding then
return false
else
print("Blocked moving east, trying alternate path...")
local altPos = findAlternatePath(targetX, targetY, targetZ)
if not altPos then
print("Warning: Could not reach target position, skipping...")
return false
end
return true
end
end
end
elseif deltaX < 0 then
-- Need to go west (negative X)
faceDirection(4) -- west
for i = 1, -deltaX do
if not safeMove("forward") then
if pathfinding then
return false
else
print("Blocked moving west, trying alternate path...")
local altPos = findAlternatePath(targetX, targetY, targetZ)
if not altPos then
print("Warning: Could not reach target position, skipping...")
return false
end
return true
end
end
end
end
-- Update current position after X movement
currentX, currentY, currentZ = getPosition()
-- Move in Z direction
local deltaZ = targetZ - currentZ
if deltaZ > 0 then
-- Need to go south (positive Z)
faceDirection(3) -- south
for i = 1, deltaZ do
if not safeMove("forward") then
if pathfinding then
return false
else
print("Blocked moving south, trying alternate path...")
local altPos = findAlternatePath(targetX, targetY, targetZ)
if not altPos then
print("Warning: Could not reach target position, skipping...")
return false
end
return true
end
end
end
elseif deltaZ < 0 then
-- Need to go north (negative Z)
faceDirection(1) -- north
for i = 1, -deltaZ do
if not safeMove("forward") then
if pathfinding then
return false
else
print("Blocked moving north, trying alternate path...")
local altPos = findAlternatePath(targetX, targetY, targetZ)
if not altPos then
print("Warning: Could not reach target position, skipping...")
return false
end
return true
end
end
end
end
return true
end
local function checkFuel()
if turtle.getFuelLevel() < config.minFuel then
print("Low fuel, returning to refuel...")
local currentX, currentY, currentZ = getPosition()
-- Move to position adjacent to fuel chest
if moveToChestPosition(config.fuelChestPos.x, config.fuelChestPos.y, config.fuelChestPos.z) then
-- Try to get fuel from chest in all directions
local chestFound = false
for direction = 1, 4 do
faceDirection(direction)
if turtle.suck() then
chestFound = true
for slot = 1, 16 do
turtle.select(slot)
local item = turtle.getItemDetail()
if item and turtle.refuel() then
print("Refueled successfully")
break
end
end
break
end
end
-- Try above and below if horizontal directions failed
if not chestFound then
if turtle.suckUp() then
chestFound = true
for slot = 1, 16 do
turtle.select(slot)
local item = turtle.getItemDetail()
if item and turtle.refuel() then
print("Refueled successfully from above")
break
end
end
elseif turtle.suckDown() then
chestFound = true
for slot = 1, 16 do
turtle.select(slot)
local item = turtle.getItemDetail()
if item and turtle.refuel() then
print("Refueled successfully from below")
break
end
end
end
end
if not chestFound then
print("Warning: Fuel chest not found or empty!")
end
else
print("Warning: Could not reach fuel chest!")
end
-- Return to work position
moveToPosition(currentX, currentY, currentZ)
end
end
local function checkBlocks()
local hasStripeBlocks = false
for slot = 1, 16 do
turtle.select(slot)
local item = turtle.getItemDetail()
if item and item.name == config.stripeBlock then
hasStripeBlocks = true
break
end
end
if not hasStripeBlocks then
print("No stripe blocks, getting more...")
local currentX, currentY, currentZ = getPosition()
-- Move to position adjacent to block chest
if moveToChestPosition(config.blockChestPos.x, config.blockChestPos.y, config.blockChestPos.z) then
-- Try to get blocks from chest in all directions
local chestFound = false
for direction = 1, 4 do
faceDirection(direction)
if turtle.suck() then
chestFound = true
for slot = 1, 16 do
turtle.select(slot)
if turtle.getItemCount() == 0 then
turtle.suck(64)
end
end
break
end
end
-- Try above and below if horizontal directions failed
if not chestFound then
if turtle.suckUp() then
chestFound = true
for slot = 1, 16 do
turtle.select(slot)
if turtle.getItemCount() == 0 then
turtle.suckUp(64)
end
end
elseif turtle.suckDown() then
chestFound = true
for slot = 1, 16 do
turtle.select(slot)
if turtle.getItemCount() == 0 then
turtle.suckDown(64)
end
end
end
end
if not chestFound then
print("Warning: Block chest not found or empty!")
end
else
print("Warning: Could not reach block chest!")
end
-- Return to work position
moveToPosition(currentX, currentY, currentZ)
end
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 isInTorus(x, y, z)
local dx = x - config.centerX
local dz = z - config.centerZ
local dy = y - config.centerY
-- Distance from center to point in XZ plane
local distanceFromCenter = math.sqrt(dx^2 + dz^2)
-- Distance from the torus tube center
local tubeCenter = config.outerRadius
local distanceFromTube = math.sqrt((distanceFromCenter - tubeCenter)^2 + dy^2)
return distanceFromTube <= config.tubeRadius
end
local function isInStripe(y)
local midY = config.centerY
local stripe1Start = midY + config.stripeOffset
local stripe1End = stripe1Start + config.stripeWidth - 1
local stripe2Start = midY - config.stripeOffset - config.stripeWidth + 1
local stripe2End = midY - config.stripeOffset
return (y >= stripe1Start and y <= stripe1End) or (y >= stripe2Start and y <= stripe2End)
end
local function shouldPlaceStripe(x, y, z)
return isInTorus(x, y, z) and isInStripe(y)
end
local function placeStripeBlock()
local success, data = turtle.inspect()
if success then
-- There's a block here
if data.name == config.breakableBlock then
-- We can break this block
if selectStripeBlock() then
turtle.dig()
return turtle.place()
end
else
-- Block exists but we can't break it
print(string.format("Cannot break %s at current position, skipping...", data.name))
return false
end
else
-- No block here, just place
if selectStripeBlock() then
return turtle.place()
end
end
return false
end
local function buildStripes()
print("Starting stripe construction...")
print(string.format("Will only break: %s", config.breakableBlock))
-- Calculate bounding box for efficiency
local minX = config.centerX - config.outerRadius - config.tubeRadius
local maxX = config.centerX + config.outerRadius + config.tubeRadius
local minZ = config.centerZ - config.outerRadius - config.tubeRadius
local maxZ = config.centerZ + config.outerRadius + config.tubeRadius
-- Calculate Y ranges for stripes
local midY = config.centerY
local stripe1Y = {midY + config.stripeOffset, midY + config.stripeOffset + config.stripeWidth - 1}
local stripe2Y = {midY - config.stripeOffset - config.stripeWidth + 1, midY - config.stripeOffset}
local blocksPlaced = 0
local blocksSkipped = 0
-- Process each stripe
for stripeNum = 1, 2 do
local yStart, yEnd
if stripeNum == 1 then
yStart, yEnd = stripe1Y[1], stripe1Y[2]
else
yStart, yEnd = stripe2Y[1], stripe2Y[2]
end
print(string.format("Building stripe %d (Y %d to %d)", stripeNum, yStart, yEnd))
for y = yStart, yEnd do
for x = minX, maxX do
for z = minZ, maxZ do
if shouldPlaceStripe(x, y, z) then
checkFuel()
checkBlocks()
if moveToPosition(x, y, z) then
if placeStripeBlock() then
blocksPlaced = blocksPlaced + 1
if blocksPlaced % 50 == 0 then
print(string.format("Placed %d blocks, skipped %d", blocksPlaced, blocksSkipped))
end
else
blocksSkipped = blocksSkipped + 1
end
else
blocksSkipped = blocksSkipped + 1
end
end
end
end
end
end
print(string.format("Stripe construction complete! Placed %d blocks, skipped %d blocks", blocksPlaced, blocksSkipped))
end
local function getUserInput()
print("=== Torus Stripe Builder ===")
print("Current configuration:")
print(string.format(" Torus center: (%d, %d, %d)", config.centerX, config.centerY, config.centerZ))
print(string.format(" Outer radius: %d, Tube radius: %d", config.outerRadius, config.tubeRadius))
print(string.format(" Stripe block: %s", config.stripeBlock))
print(string.format(" Will only break: %s", config.breakableBlock))
print(string.format(" Fuel chest: (%d, %d, %d)", config.fuelChestPos.x, config.fuelChestPos.y, config.fuelChestPos.z))
print(string.format(" Block chest: (%d, %d, %d)", config.blockChestPos.x, config.blockChestPos.y, config.blockChestPos.z))
print()
io.write("Use default configuration? (y/n): ")
local useDefaults = io.read()
if useDefaults:lower() ~= "y" then
print("Enter new values (press Enter to keep current value):")
-- Get user input for torus center
print("Torus center coordinates:")
io.write(string.format("X (current: %d): ", config.centerX))
local input = io.read()
if input ~= "" then config.centerX = tonumber(input) end
io.write(string.format("Y (current: %d): ", config.centerY))
input = io.read()
if input ~= "" then config.centerY = tonumber(input) end
io.write(string.format("Z (current: %d): ", config.centerZ))
input = io.read()
if input ~= "" then config.centerZ = tonumber(input) end
-- Get fuel chest position
print("Fuel chest coordinates:")
io.write(string.format("X (current: %d): ", config.fuelChestPos.x))
input = io.read()
if input ~= "" then config.fuelChestPos.x = tonumber(input) end
io.write(string.format("Y (current: %d): ", config.fuelChestPos.y))
input = io.read()
if input ~= "" then config.fuelChestPos.y = tonumber(input) end
io.write(string.format("Z (current: %d): ", config.fuelChestPos.z))
input = io.read()
if input ~= "" then config.fuelChestPos.z = tonumber(input) end
-- Get block chest position
print("Block chest coordinates:")
io.write(string.format("X (current: %d): ", config.blockChestPos.x))
input = io.read()
if input ~= "" then config.blockChestPos.x = tonumber(input) end
io.write(string.format("Y (current: %d): ", config.blockChestPos.y))
input = io.read()
if input ~= "" then config.blockChestPos.y = tonumber(input) end
io.write(string.format("Z (current: %d): ", config.blockChestPos.z))
input = io.read()
if input ~= "" then config.blockChestPos.z = tonumber(input) end
-- Get block type
io.write(string.format("Stripe block type (current: %s): ", config.stripeBlock))
input = io.read()
if input ~= "" then config.stripeBlock = input end
-- Get breakable block type
io.write(string.format("Breakable block type (current: %s): ", config.breakableBlock))
input = io.read()
if input ~= "" then config.breakableBlock = input end
print()
print("Updated configuration:")
print(string.format(" Torus center: (%d, %d, %d)", config.centerX, config.centerY, config.centerZ))
print(string.format(" Outer radius: %d, Tube radius: %d", config.outerRadius, config.tubeRadius))
print(string.format(" Stripe block: %s", config.stripeBlock))
print(string.format(" Will only break: %s", config.breakableBlock))
print(string.format(" Fuel chest: (%d, %d, %d)", config.fuelChestPos.x, config.fuelChestPos.y, config.fuelChestPos.z))
print(string.format(" Block chest: (%d, %d, %d)", config.blockChestPos.x, config.blockChestPos.y, config.blockChestPos.z))
end
print()
io.write("Start stripe construction? (y/n): ")
local confirm = io.read()
if confirm:lower() ~= "y" then
print("Operation cancelled.")
return false
end
return true
end
-- Main function
local function main()
-- First, determine the turtle's initial facing direction
if not determineInitialDirection() then
return
end
if getUserInput() then
buildStripes()
print("=== Operation Complete ===")
end
end
-- Run the program
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment