This is a read-only snapshot of the ComputerCraft forums, taken in April 2020.
ZeekDaGeek's profile picture

Circle Program

Started by ZeekDaGeek, 22 November 2012 - 03:18 AM
ZeekDaGeek #1
Posted 22 November 2012 - 04:18 AM
One of the simple programs I needed to create was something to draw circles in the world. This is not the most complex program out there and the main reason I want to post it is to get feedback and possible improvements.

Code:
local r = 0
currSlot = 1
print("What radius of circle would you like me to create?")
r = tonumber(io.read())

if r == 0 then
  print("Radius 0 circle? Done!")
end

function findBlock ()

  if turtle.getItemCount(currSlot) ~= 0 then
    return true
  end
 
  local tmp = 1
  turtle.select(1)
 
  while (turtle.getItemCount(tmp) == 0 and tmp <= 15) do
    tmp=tmp+1
    turtle.select(tmp)  
  end

  while (turtle.getItemCount(tmp) == 0 and tmp == 16) do
    -- Send a message to the evil demon Speaking Turtle.
    rednet.open("right")
    rednet.send(8, "Bunny needs blocks!", false)
    rednet.close("right")
    print("Bunny needs blocks!")
    sleep(5)
  end
 
  return true
   
end

function tryPlaceDown ()
  if turtle.placeDown() == false then
    exit()
  end
end

round = function (inputN)

  if inputN % 2 ~= 0.5 then
    return math.floor(inputN + 0.5)
  end
  return inputN - 0.5

end

turtle.select(currSlot)

local coords = {}
local coordsCount = 0

local f = 1 - r
local ddF_x = 1
local ddF_y = -2 * r
local x = 0
local y = r

coords[0 .. "," .. round(0+r)] = true
coords[0 .. "," .. round(0-r)] = true
coords[0+r .. "," .. 0] = true
coords[0-r .. "," .. 0] = true
coordsCount = 4

while (x < y) do

  if (f >= 0) then
    y = y - 1
    ddF_y = ddF_y + 2
    f = f + ddF_y
  end

  x = x + 1
  ddF_x = ddF_x + 2
  f = f + ddF_x

  coords[round(0+x) .. "," .. round(0+y)] = true
  coords[round(0-x) .. "," .. round(0+y)] = true
  coords[round(0+x) .. "," .. round(0-y)] = true
  coords[round(0-x) .. "," .. round(0-y)] = true

  coords[round(0+y) .. "," .. round(0+x)] = true
  coords[round(0-y) .. "," .. round(0+x)] = true
  coords[round(0+y) .. "," .. round(0-x)] = true
  coords[round(0-y) .. "," .. round(0-x)] = true

  coordsCount = coordsCount + 8

end

checkCoords = function (x0,y0)

  if coords[x0 .. "," .. y0] == true then
    return true
  else
    return false
  end

end

-- Move from the center to the first position it can find.
x = 0
y = 0

while checkCoords(x,y) ~= true do

  turtle.forward()
  x = x + 1

end

-- Place a block in the first position.
findBlock()
turtle.placeDown()

-- Keep track of which way the turtle is facing.
facingX = 1
facingY = 0

-- Look clockwise from each block and find the next block in the space.
spinsDone = 0
while (coordsCount > 0 and spinsDone < 5) do

  cX = x + facingX
  cY = y + facingY

  if checkCoords(cX, cY) then

    turtle.forward()
    findBlock()
    turtle.placeDown()

    x = cX
    y = cY
    coords[x .. "," .. y] = nil
    coordsCount = coordsCount - 1

    spinsDone = 0

  else

    -- Check diagnals
    if facingX == 1 then

	  cY = y + 1
	  newFacingX = 0
	  newFacingY = 1

    elseif facingX == -1 then

	  cY = y - 1
	  newFacingX = 0
	  newFacingY = -1

    elseif facingY == 1 then

	  cX = x - 1
	  newFacingX = -1
	  newFacingY = 0

    elseif facingY == -1 then

	  cX = x + 1
	  newFacingX = 1
	  newFacingY = 0

    end


    if checkCoords(cX,cY) then

	  turtle.forward()
	  turtle.turnRight()
	  turtle.forward()
	  turtle.turnLeft()
	  findBlock()
	  turtle.placeDown()

	  x = cX
	  y = cY
	  coords[x .. "," .. y] = nil
	  coordsCount = coordsCount - 1

	  spinsDone = 0

    else

	  turtle.turnRight()

	  facingX = newFacingX
	  facingY = newFacingY

	  spinsDone = spinsDone + 1

    end

  end

end
Mikeyhun #2
Posted 28 December 2012 - 03:07 AM
Hi there
Good program you got there but there were 2 problems with it.:S
1.no fuel checker were in there and wasn't moving if fuel wasn't set "unlimited"
2.if you made a circle and then tried to make another the variables still existed and the new circle was miscalculated
So i updated your script a bit

Update: - slot #1 always reserved for fuel and will check for fuel lvl before every move and refuel if needed
- will send message to a "monitor terminal" if it has a modem and if you want it so no need to check up every time on it.
it will send messages like,"out of fuel","out of blocks","can't place block"(you forgot to use your own function tryPlaceDown :D/>)
with the message it will send it's location based on gps if any, if there's no gps it will send it's relative coordinates based on the starting point
it will only send messages once
-if finished building it will return to the starting point

So with this code it's a bit more useable but your original code was great so cookie for you :D/>
And there can be more improvements in the future like:
-pathfinding:
- if moving to the next placement area is blocked (ie a pillar is in the way) move around to find another way if theres one, if not then discard placement,send message,and move to the next placement area
- if it's a mining turtle try to mine the block and resume or discard
- if out of blocks go back to starting point or to a location wheres a chest and it can restock from it and go back and continue
-at the start ask for level so it could make circles like 5 high without further interaction
-at startup save the radius and maybe the coordinates and if server restarts it can resume it's operation if it has a logfile

Well these are my ideas and sorry if i made any grammer mistake, not naitive english:D
if anything is unclear ask it:D

And here's the updated code:

local r = 0
currSlot = 2 --reserve slot #1 for fuel all time!
mfid = 0 --monitor computer's id
osid = os.getComputerID() --turtle's computer id
isSent = false --send all messages just once
fReserve = 10 --fuel can't go below this
print("What radius of circle would you like me to create?")
r = tonumber(io.read())
if r == 0 then
  print("Radius 0 circle? Done!")
end
--send message to monitor computer(if any) and write it out locally
function sendM(message)
  if peripheral.isPresent("right") and peripheral.getType("right") == "modem" then
	rednet.open("right")
	rednet.send(mfid, "Turtle("..osid.."):"..message, false)
	rednet.close("right")
  end
  print(message)
end
--return gps location if it has a modem and can retrive turtles's location
--if not then return x,y based on turtle's startup location
function gpsLoc(fx,fy)
  if peripheral.isPresent("right") and peripheral.getType("right") == "modem" then
	rednet.open("right")
	local x, y, z = gps.locate(5)
	rednet.close("right")
	if x == nil then
	  return "x:"..tostring(fx)..",y:"..tostring(fy).."(rel)"
	else
	  return "x:"..tostring(x)..",y:"..tostring(y)..",z:"..tostring(z)
	end
  else
	return "x:"..tostring(fx)..",y:"..tostring(fy).."(rel)"
  end
end
function findBlock ()
  if turtle.getItemCount(currSlot) ~= 0 then
	return true
  end

  local tmp = 2
  turtle.select(tmp)

  while (turtle.getItemCount(tmp) == 0 and tmp <= 16) do
	if tmp == 16 then
	  if isSent == false then --only print once
		sendM("Out of blocks! Turtle at "..gpsLoc(x,y))
		isSent = true
	  end
	  sleep(5)
	  tmp = 2
	  turtle.select(tmp)
	else
	  tmp = tmp + 1
	  turtle.select(tmp)
	end
  end
  isSent = false
  currSlot = tmp
  tmp = 2

  return true
end
function tryPlaceDown (x,y)
  if turtle.detectDown() == true then
	if turtle.compareDown() == true then
	  return true
	else
	  sendM("Can't place block("..gpsLoc(x,y)..")!")
	  return false
	end
  else
	if turtle.placeDown() == true then
	  return true
	else
	  sendM("Can't place block("..gpsLoc(x,y)..")!")
	  return false
	end
  end
end
round = function (inputN)
  if inputN % 2 ~= 0.5 then
	return math.floor(inputN + 0.5)
  end
  return inputN - 0.5
end
turtle.select(currSlot)
local coords = {}
local coordsCount = 0
local f = 1 - r
local ddF_x = 1
local ddF_y = -2 * r
x = 0
y = r
coords[0 .. "," .. round(0+r)] = true
coords[0 .. "," .. round(0-r)] = true
coords[0+r .. "," .. 0] = true
coords[0-r .. "," .. 0] = true
coordsCount = 4
while (x < y) do
  if (f >= 0) then
	y = y - 1
	ddF_y = ddF_y + 2
	f = f + ddF_y
  end
  x = x + 1
  ddF_x = ddF_x + 2
  f = f + ddF_x
  coords[round(0+x) .. "," .. round(0+y)] = true
  coords[round(0-x) .. "," .. round(0+y)] = true
  coords[round(0+x) .. "," .. round(0-y)] = true
  coords[round(0-x) .. "," .. round(0-y)] = true
  coords[round(0+y) .. "," .. round(0+x)] = true
  coords[round(0-y) .. "," .. round(0+x)] = true
  coords[round(0+y) .. "," .. round(0-x)] = true
  coords[round(0-y) .. "," .. round(0-x)] = true
  coordsCount = coordsCount + 8
end
checkCoords = function (x0,y0)
  if coords[x0 .. "," .. y0] == true then
	return true
  else
	return false
  end
end
--watch fuel level and if smaller than the reserve level refuel from slot #1
function fuelProc()
  local flvl = turtle.getFuelLevel()
  if flvl == "unlimited" then
	return true
  elseif flvl > fReserve then
	return true
  else
	turtle.select(1)
	while turtle.refuel(1) == false do
	  if isSent == false then
		sendM("Out of fuel! turtle at "..gpsLoc(x,y))
		print("Please insert fuel to slot #1 to resume!")
		isSent = true
	  end
	  sleep(5)
	end
	isSent = false
	turtle.select(currSlot)
  end
end
-- Move from the center to the first position it can find.
local x = 0
local y = 0
while checkCoords(x,y) ~= true do
  fuelProc()
  turtle.forward()
  x = x + 1
end
-- Place a block in the first position.
--findBlock()
--tryPlaceDown() <-block will be placed last so won't be any route blocking at multi lvl structures
-- Keep track of which way the turtle is facing.
facingX = 1
facingY = 0
-- Look clockwise from each block and find the next block in the space.
spinsDone = 0
while (coordsCount > 0 and spinsDone < 5) do
  fuelProc()
  cX = x + facingX
  cY = y + facingY
  if checkCoords(cX, cY) then
	turtle.forward()
	findBlock()
	tryPlaceDown(x,y)
	x = cX
	y = cY
	coords[x .. "," .. y] = nil
	coordsCount = coordsCount - 1
	spinsDone = 0
  else
	-- Check diagnals
	if facingX == 1 then
		  cY = y + 1
		  newFacingX = 0
		  newFacingY = 1
	elseif facingX == -1 then
		  cY = y - 1
		  newFacingX = 0
		  newFacingY = -1
	elseif facingY == 1 then
		  cX = x - 1
		  newFacingX = -1
		  newFacingY = 0
	elseif facingY == -1 then
		  cX = x + 1
		  newFacingX = 1
		  newFacingY = 0
	end

	if checkCoords(cX,cY) then
		  turtle.forward()
		  turtle.turnRight()
		  turtle.forward()
		  turtle.turnLeft()
		  findBlock()
		  tryPlaceDown(x,y)
		  x = cX
		  y = cY
		  coords[x .. "," .. y] = nil
		  coordsCount = coordsCount - 1
		  spinsDone = 0
	else
		  turtle.turnRight()
		  facingX = newFacingX
		  facingY = newFacingY
		  spinsDone = spinsDone + 1
	end
  end
end
--return to starting point
repeat
  fuelProc()
  turtle.forward()
  x = x - 1
until x == 0
turtle.turnRight()
turtle.turnRight()
sendM("Work done!")
x = nil
y = nil
r = nil
coords = nil
coordsCount = nil
jay2006 #3
Posted 31 December 2012 - 09:40 PM
Digging Version


Hi, I made a digging Version out of the code and added some extra functions!

# Can dig out a complet 2 high Circle
# Can replace the floor with a other Block
# Can place torches
# Can drop items in chest

Have fun with it! :)/>

-Jay2006

currSlot = 2 --reserve slot #1 for fuel all time!
mfid = 0 --monitor computer's id
osid = os.getComputerID() --turtle's computer id
isSent = false --send all messages just once
fReserve = 10 --fuel can't go below this

print("What innerradius of circle would you like me to dig?")
r = tonumber(io.read())
print("What outerradius of circle would you like me to dig?")
j = tonumber(io.read())

print("Should I replace the floor with the Block in Slot 2? 0 or 1!")
m = tonumber(io.read())

print("Should I place torches (Slot 3)? 1 or 0!")
l = tonumber(io.read())

print("Should I drop the items in the chest behind me? 1 or 0!")
d = tonumber(io.read())

n=0
-------------
function gpsLoc(fx,fy)
if peripheral.isPresent("right") and peripheral.getType("right") == "modem" then
rednet.open("right")
local x, y, z = gps.locate(5)
rednet.close("right")
if x == nil then
return "x:"..tostring(fx)..",y:"..tostring(fy).."(rel)"
else
return "x:"..tostring(x)..",y:"..tostring(y)..",z:"..tostring(z)
end
else
return "x:"..tostring(fx)..",y:"..tostring(fy).."(rel)"
end
end
------------
function findBlock ()
if turtle.getItemCount(currSlot) ~= 0 then
return true
end
local tmp = 2
turtle.select(tmp)
while (turtle.getItemCount(tmp) == 0 and tmp <= 16) do
if tmp == 16 then
 if isSent == false then --only print once
isSent = true
 end
 sleep(5)
 tmp = 2
 turtle.select(tmp)
else
 tmp = tmp + 1
 turtle.select(tmp)
end
end
isSent = false
currSlot = tmp
tmp = 2
return true
end
-----------
function tryPlaceDown (x,y)
turtle.select(2)

if m==1 then
if turtle.compareDown() then
return true
else
turtle.digDown()
turtle.placeDown()
return true
end
else
if turtle.detect() then
return true
else
turtle.placeDown()
return true
end
end 
end
--------------
--watch fuel level and if smaller than the reserve level refuel from slot #1
function fuelProc()
local flvl = turtle.getFuelLevel()
if flvl == "unlimited" then
return true
elseif flvl > fReserve then
return true
else
turtle.select(1)
while turtle.refuel(1) == false do
if isSent == false then
print("Please insert fuel to slot #1 to resume!")
isSent = true
end
sleep(5)
end
isSent = false
turtle.select(currSlot)
end
end
---------
function chest()
if d==1 then
c=4
while c<=16 do
turtle.select(c)
turtle.drop()
c=c+1
end
turtle.turnRight()
turtle.turnRight()
end
end
----------
function torch()
if l==1 then
n=n+1
if math.fmod(n,4)==0 and math.fmod(r,2)==0 then
turtle.select(3)
turtle.turnRight()
turtle.place()
turtle.turnLeft()
turtle.select(currSlot)
end
end
end
-------------
function sdig()
while turtle.detect() do
turtle.dig()
os.sleep(1)
end
turtle.digUp()
turtle.suck()
end
---------
while r<=j do
round = function (inputN)
if inputN % 2 ~= 0.5 then
return math.floor(inputN + 0.5)
end
return inputN - 0.5
end
turtle.select(currSlot)
local coords = {}
local coordsCount = 0
local f = 1 - r
local ddF_x = 1
local ddF_y = -2 * r
x = 0
y = r
coords[0 .. "," .. round(0+r)] = true
coords[0 .. "," .. round(0-r)] = true
coords[0+r .. "," .. 0] = true
coords[0-r .. "," .. 0] = true
coordsCount = 4
while (x < y) do
if (f >= 0) then
y = y - 1
ddF_y = ddF_y + 2
f = f + ddF_y
end
x = x + 1
ddF_x = ddF_x + 2
f = f + ddF_x
coords[round(0+x) .. "," .. round(0+y)] = true
coords[round(0-x) .. "," .. round(0+y)] = true
coords[round(0+x) .. "," .. round(0-y)] = true
coords[round(0-x) .. "," .. round(0-y)] = true
coords[round(0+y) .. "," .. round(0+x)] = true
coords[round(0-y) .. "," .. round(0+x)] = true
coords[round(0+y) .. "," .. round(0-x)] = true
coords[round(0-y) .. "," .. round(0-x)] = true
coordsCount = coordsCount + 8
end

checkCoords = function (x0,y0)
if coords[x0 .. "," .. y0] == true then
return true
else
return false
end
end
-- Move from the center to the first position it can find.
local x = 0
local y = 0
while checkCoords(x,y) ~= true do
fuelProc()
sdig()
turtle.forward()
x = x + 1
end
-- Place a block in the first position.
--findBlock()
--tryPlaceDown() <-block will be placed last so won't be any route blocking at multi lvl structures
-- Keep track of which way the turtle is facing.
facingX = 1
facingY = 0
-- Look clockwise from each block and find the next block in the space.
spinsDone = 0
while (coordsCount > 0 and spinsDone < 5) do
fuelProc()
cX = x + facingX
cY = y + facingY
if checkCoords(cX, cY) then
sdig()
turtle.forward()
torch()
findBlock()
tryPlaceDown(x,y)
x = cX
y = cY
coords[x .. "," .. y] = nil
coordsCount = coordsCount - 1
spinsDone = 0
else
-- Check diagnals
if facingX == 1 then
cY = y + 1
newFacingX = 0
newFacingY = 1
elseif facingX == -1 then
cY = y - 1
newFacingX = 0
newFacingY = -1
elseif facingY == 1 then
cX = x - 1
newFacingX = -1
newFacingY = 0
elseif facingY == -1 then
cX = x + 1
newFacingX = 1
newFacingY = 0
end
if checkCoords(cX,cY) then
sdig()
turtle.forward()
turtle.turnRight()
sdig()
turtle.forward()
turtle.turnLeft()
findBlock()
tryPlaceDown(x,y)
x = cX
y = cY
coords[x .. "," .. y] = nil
coordsCount = coordsCount - 1
spinsDone = 0
else
turtle.turnRight()
facingX = newFacingX
facingY = newFacingY
spinsDone = spinsDone + 1
end
end
end
--return to starting point
repeat
 fuelProc()
 sdig()
 turtle.forward()
 x = x - 1
until x == 0
chest()
x = 0
y = 0
r = r+1
n=0
coords = 0
coordsCount = 0
end