Skip to content

Instantly share code, notes, and snippets.

@ZeekDaGeek
Created July 23, 2015 11:56
Show Gist options
  • Save ZeekDaGeek/527b71fea87cec4953f4 to your computer and use it in GitHub Desktop.
Save ZeekDaGeek/527b71fea87cec4953f4 to your computer and use it in GitHub Desktop.
-- Very specifically created script to build a circle.
-- Would probably have to be tweaked for your own operations.
-- By: ZeekDaGeek
local component = require("component")
local gpu = component.getPrimary("gpu")
local keyboard = require("keyboard")
local computer = require("computer")
local robot = require("robot")
local navi = component.getPrimary("navigation")
local sides = require("sides")
local fs = require("filesystem")
local ser = require("serialization")
-- Accept arguments
local args = { ... }
if #args == 0 or (args[1] ~= "resume" and tonumber(args[1]) <= 0) then
print("Usage: buildCircle [resume / radius]")
return false
end
-- Circle save
fileCircleCoords = "/home/circleCoords.dat"
-- Define types
circleFillType = 1
circleFillAltType = 1
circleBorderType = 2
completeType = 3
-- Center the robot
local curX, curY, curZ, posError = navi.getPosition()
local curX = math.floor(curX)
local curY = math.floor(curY)
local curZ = math.floor(curZ)
-- Integers to plug into equation,
local intX, intY = 0, 0
-- Track robot
worker = {
coords = {
x = curX,
y = curY,
z = curZ
},
facing = navi.getFacing()
}
-- Circle information
local radius = args[1]
local centerPoint = true
local circleCoords = {}
if centerPoint == true then
offsetQ1x = 2
offsetQ3y = -2
offsetQ4x = 2
offsetQ4y = -2
else
offsetQ1x = 0
offsetQ3y = 0
offsetQ4x = 0
offsetQ4y = 0
end
-- Equation
-- (x - a)^2 + (y - b)^2 = r^2
if args[1] ~= "resume" then
local genCircle = true
while genCircle == true do
intX = 0
local testX = true
if (intY ^ 2 > radius ^ 2) then
intY = intY - 1
currentPalette = circleBorderType
genCircle = false
break
else
while testX == true do
if ((intX ^ 2 + intY ^ 2) < radius ^ 2) then
if false then
if (math.fmod(intX, 2) == 0) and (currentPalette ~= circleBorderType) then
currentPalette = circleFillType
else
currentPalette = circleFillAltType
end
local tmpX, tmpY, tmpZ = curX + intX + offsetQ1x, curY, curZ + intY
tmpIndex = string.format("%i,%i,%i", tmpX, tmpY, tmpZ)
circleCoords[tmpIndex] = {
coords = { x = tmpX, y = tmpY, z = tmpZ },
type = currentPalette,
}
local tmpX, tmpY, tmpZ = curX - intX , curY, curZ + intY
tmpIndex = string.format("%i,%i,%i", tmpX, tmpY, tmpZ)
circleCoords[tmpIndex] = {
coords = { x = tmpX, y = tmpY, z = tmpZ },
type = currentPalette,
}
local tmpX, tmpY, tmpZ = curX + intX + offsetQ4x, curY, curZ - intY + offsetQ4y
tmpIndex = string.format("%i,%i,%i", tmpX, tmpY, tmpZ)
circleCoords[tmpIndex] = {
coords = { x = tmpX, y = tmpY, z = tmpZ },
type = currentPalette,
}
local tmpX, tmpY, tmpZ = curX - intX , curY, curZ - intY + offsetQ3y
tmpIndex = string.format("%i,%i,%i", tmpX, tmpY, tmpZ)
circleCoords[tmpIndex] = {
coords = { x = tmpX, y = tmpY, z = tmpZ },
type = currentPalette,
}
end
else
intX = intX - 1
currentPalette = circleBorderType
local tmpX, tmpY, tmpZ = curX + intX + offsetQ1x, curY, curZ + intY
tmpIndex = string.format("%i,%i,%i", tmpX, tmpY, tmpZ)
circleCoords[tmpIndex] = {
coords = { x = tmpX, y = tmpY, z = tmpZ },
type = currentPalette,
}
local tmpX, tmpY, tmpZ = curX - intX , curY, curZ + intY
tmpIndex = string.format("%i,%i,%i", tmpX, tmpY, tmpZ)
circleCoords[tmpIndex] = {
coords = { x = tmpX, y = tmpY, z = tmpZ },
type = currentPalette,
}
local tmpX, tmpY, tmpZ = curX + intX + offsetQ4x, curY, curZ - intY + offsetQ4y
tmpIndex = string.format("%i,%i,%i", tmpX, tmpY, tmpZ)
circleCoords[tmpIndex] = {
coords = { x = tmpX, y = tmpY, z = tmpZ },
type = currentPalette,
}
local tmpX, tmpY, tmpZ = curX - intX , curY, curZ - intY + offsetQ3y
tmpIndex = string.format("%i,%i,%i", tmpX, tmpY, tmpZ)
circleCoords[tmpIndex] = {
coords = { x = tmpX, y = tmpY, z = tmpZ },
type = currentPalette,
}
intY = intY - 1
testSubX = true
while testSubX == true and intY > 0 do
if ((intX ^ 2 + intY ^ 2) < radius ^ 2) then
local tmpX, tmpY, tmpZ = curX + intX + offsetQ1x, curY, curZ + intY
tmpIndex = string.format("%i,%i,%i", tmpX, tmpY, tmpZ)
circleCoords[tmpIndex] = {
coords = { x = tmpX, y = tmpY, z = tmpZ },
type = currentPalette,
}
local tmpX, tmpY, tmpZ = curX - intX , curY, curZ + intY
tmpIndex = string.format("%i,%i,%i", tmpX, tmpY, tmpZ)
circleCoords[tmpIndex] = {
coords = { x = tmpX, y = tmpY, z = tmpZ },
type = currentPalette,
}
local tmpX, tmpY, tmpZ = curX + intX + offsetQ4x, curY, curZ - intY + offsetQ4y
tmpIndex = string.format("%i,%i,%i", tmpX, tmpY, tmpZ)
circleCoords[tmpIndex] = {
coords = { x = tmpX, y = tmpY, z = tmpZ },
type = currentPalette,
}
local tmpX, tmpY, tmpZ = curX - intX , curY, curZ - intY + offsetQ3y
tmpIndex = string.format("%i,%i,%i", tmpX, tmpY, tmpZ)
circleCoords[tmpIndex] = {
coords = { x = tmpX, y = tmpY, z = tmpZ },
type = currentPalette,
}
else
testSubX = false
end
intX = intX + 1
end
intY = intY + 1
currentPalette = circleFillType
testX = false
end
intX = intX + 1
end
end
currentPalette = circleFillType
intY = intY + 1
end
else
local fh = fs.open(fileCircleCoords, "r")
local fContents = fh:read(32768)
circleCoords = ser.unserialize(fContents)
fh:close()
end
function saveCircle()
local fh = fs.open(fileCircleCoords, "w")
fh:write(ser.serialize(circleCoords))
fh:close()
end
-- worker movements.
function worker:moveUp()
local newCoords = {}
newCoords.x = self.coords.x
newCoords.y = self.coords.y + 1
newCoords.z = self.coords.z
if (robot.up()) then
-- Change the coords.
self.coords.x = newCoords.x
self.coords.y = newCoords.y
self.coords.z = newCoords.z
-- print(string.format(" Moved UP to %i,%i,%i", newCoords.x, newCoords.y, newCoords.z))
return true
else
return false
end
end
function worker:moveDown()
local newCoords = {}
newCoords.x = self.coords.x
newCoords.y = self.coords.y - 1
newCoords.z = self.coords.z
if (robot.down()) then
-- Change the coords.
self.coords.x = newCoords.x
self.coords.y = newCoords.y
self.coords.z = newCoords.z
-- print(string.format(" Moved DOWN to %i,%i,%i", newCoords.x, newCoords.y, newCoords.z))
return true
else
return false
end
end
function worker:moveNorth()
local newCoords = {}
newCoords.x = self.coords.x
newCoords.y = self.coords.y
newCoords.z = self.coords.z - 1
if worker.facing == sides.north then
-- Just move forward
elseif worker.facing == sides.east then
robot.turnLeft()
elseif worker.facing == sides.south then
robot.turnLeft()
robot.turnLeft()
elseif worker.facing == sides.west then
robot.turnRight()
end
self.facing = sides.north
if (robot.forward()) then
-- Change the coords.
self.coords.x = newCoords.x
self.coords.y = newCoords.y
self.coords.z = newCoords.z
-- print(string.format(" Moved NORTH to %i,%i,%i", newCoords.x, newCoords.y, newCoords.z))
return true
else
return false
end
end
function worker:moveSouth()
local newCoords = {}
newCoords.x = self.coords.x
newCoords.y = self.coords.y
newCoords.z = self.coords.z + 1
if worker.facing == sides.north then
robot.turnRight()
robot.turnRight()
elseif worker.facing == sides.east then
robot.turnRight()
elseif worker.facing == sides.south then
-- Just move forward
elseif worker.facing == sides.west then
robot.turnLeft()
end
self.facing = sides.south
if (robot.forward()) then
-- Change the coords.
self.coords.x = newCoords.x
self.coords.y = newCoords.y
self.coords.z = newCoords.z
-- print(string.format(" Moved SOUTH to %i,%i,%i", newCoords.x, newCoords.y, newCoords.z))
return true
else
return false
end
end
function worker:moveEast()
local newCoords = {}
newCoords.x = self.coords.x + 1
newCoords.y = self.coords.y
newCoords.z = self.coords.z
if worker.facing == sides.north then
robot.turnRight()
elseif worker.facing == sides.east then
-- Just move forward
elseif worker.facing == sides.south then
robot.turnLeft()
elseif worker.facing == sides.west then
robot.turnLeft()
robot.turnLeft()
end
self.facing = sides.east
if (robot.forward()) then
-- Change the coords.
self.coords.x = newCoords.x
self.coords.y = newCoords.y
self.coords.z = newCoords.z
-- print(string.format(" Moved EAST to %i,%i,%i", newCoords.x, newCoords.y, newCoords.z))
return true
else
return false
end
end
function worker:moveWest()
local newCoords = {}
newCoords.x = self.coords.x - 1
newCoords.y = self.coords.y
newCoords.z = self.coords.z
if worker.facing == sides.north then
robot.turnLeft()
elseif worker.facing == sides.east then
robot.turnRight()
robot.turnRight()
elseif worker.facing == sides.south then
robot.turnRight()
elseif worker.facing == sides.west then
-- Just move forward
end
self.facing = sides.west
if (robot.forward()) then
-- Change the coords.
self.coords.x = newCoords.x
self.coords.y = newCoords.y
self.coords.z = newCoords.z
-- print(string.format(" Moved WEST to %i,%i,%i", newCoords.x, newCoords.y, newCoords.z))
return true
else
return false
end
end
function worker:moveto (toLoc)
-- Track state of movement.
workerStuck = false
workerArrived = false
-- Keep track of failed attempts at movement in a row
-- If this happens too much then we're stuck
failedMoves = 0
-- Main loop of movement
while failedMoves <= 10 and workerArrived == false do
if self.coords.x == toLoc.coords.x and self.coords.y == toLoc.coords.y and self.coords.z == toLoc.coords.z then
workerArrived = true
return true
end
-- Match height first.
while self.coords.y ~= toLoc.coords.y do
if self.coords.y > toLoc.coords.y then
if worker:moveDown() == false then
failedMoves = failedMoves + 1
break
else
failedMoves = 0
end
elseif self.coords.y < toLoc.coords.y then
if worker:moveUp() == false then
failedMoves = failedMoves + 1
break
else
failedMoves = 0
end
end
end
-- Then match X next.
while self.coords.x ~= toLoc.coords.x do
if self.coords.x > toLoc.coords.x then
if worker:moveWest() == false then
failedMoves = failedMoves + 1
break
else
failedMoves = 0
end
elseif self.coords.x < toLoc.coords.x then
if worker:moveEast() == false then
failedMoves = failedMoves + 1
break
else
failedMoves = 0
end
end
end
-- Then match Z next.
while self.coords.z ~= toLoc.coords.z do
if self.coords.z > toLoc.coords.z then
if worker:moveNorth() == false then
failedMoves = failedMoves + 1
break
else
failedMoves = 0
end
elseif self.coords.z < toLoc.coords.z then
if worker:moveSouth() == false then
failedMoves = failedMoves + 1
break
else
failedMoves = 0
end
end
end
end
return false
end
function worker:repair()
print("Repairs needed.")
worker:moveto({ coords = { x = -75, y = 90, z = -15 }})
worker:moveWest()
print(" Emptying inventory")
slotSelect = 1
while slotSelect <= 16 and robot.detect() do
robot.select(slotSelect)
while robot.drop() == false and robot.count() > 0 do
if robot.down() then
self.coords.y = self.coords.y - 1
end
end
slotSelect = slotSelect + 1
end
print(" Moving to charge station")
-- Move to the bottom of the stack of chests
while robot.down() do
-- Do nothing, the robot is just moving down
self.coords.y = self.coords.y - 1
end
print(" Charging to full")
-- Charge the robot
while ((computer.energy() / computer.maxEnergy()) <= 0.9) do
os.sleep(10)
end
return true
end
function worker:digDown(forceDown)
local targetCoords = {}
targetCoords.x = self.coords.x
targetCoords.y = self.coords.y - 1
targetCoords.z = self.coords.z
if forceDown == true or robot.detectDown() then
-- Attempt to mind down to bedrock.
while self.coords.y > 6 do
-- Check if the robot needs charging
if computer.energy() <= 10000 then
worker:repair()
end
-- Check if there's any room for additonal blocks.
slotCheck = 1
slotSpace = false
while slotCheck <= 16 and slotSpace == false do
if robot.count(slotCheck) == 0 then
slotSpace = true
end
slotCheck = slotCheck + 1
end
-- No space so do the repair action
if slotSpace == false then
worker:repair()
-- Go back to previous place and force a dig
local moveCoords = { coords = { x = targetCoords.x, y = targetCoords.y + 1, z = targetCoords.z } }
worker:moveto(moveCoords)
worker:digDown(true)
return false
end
if robot.down() then
self.coords.y = self.coords.y - 1
end
if robot.detectDown() then
if robot.swingDown() then
-- Continue mining
else
worker:repair()
-- Go back to previous place and force a dig
local moveCoords = { coords = { x = targetCoords.x, y = targetCoords.y + 1, z = targetCoords.z } }
worker:moveto(moveCoords)
worker:digDown(true)
return false
end
end
end
end
tmpCoordsString = string.format("%i,%i,%i", targetCoords.x, targetCoords.y, targetCoords.z)
if (type(circleCoords[tmpCoordsString].type) ~= "nil") then
circleCoords[tmpCoordsString].type = completeType
end
return true
end
saveCircle()
-- Process the circle with the robot.
local processingCircle = true
while processingCircle == true do
local closestCoord = { coords = { x = 0, y = 0, z = 0 }, distance = -1 }
-- Find the nearest point.
for coordString,coordData in pairs(circleCoords) do
local tmpDistance = math.sqrt(
(worker.coords.x - coordData.coords.x)^2 +
(worker.coords.y - coordData.coords.y)^2 +
(worker.coords.z - coordData.coords.z)^2
)
if (closestCoord.distance == -1 or tmpDistance < closestCoord.distance) and coordData.type == circleBorderType then
closestCoord.coords.x = coordData.coords.x
closestCoord.coords.y = coordData.coords.y + 1
closestCoord.coords.z = coordData.coords.z
closestCoord.distance = tmpDistance
end
end
print(string.format("Moving to %i, %i, %i (%f)", closestCoord.coords.x, closestCoord.coords.y, closestCoord.coords.z, closestCoord.distance))
if worker:moveto(closestCoord) then
worker:digDown(false)
else
print(string.format(" Failed to move to %i, %i, %i (%f)", closestCoord.coords.x, closestCoord.coords.y, closestCoord.coords.z, closestCoord.distance))
end
if closestCoord.distance == -1 then
processingCircle = false
end
saveCircle()
if keyboard.isKeyDown(keyboard.keys.w) and keyboard.isControlDown() then
os.exit()
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment