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

Turtle call script help.

Started by subzero22, 15 March 2013 - 04:40 AM
subzero22 #1
Posted 15 March 2013 - 05:40 AM
I've pretty much got the code down. it might have a few errors I haven't found yet but one thing that I just thought of is. when script is running how do I get it to get the x y z cords from a rednet message or is what I have sufficient? I don't think it is as I'd need some kind of loop until it can get the cords to go to.

Here's my code:
Spoiler

-- Turtle Call

-- Check for gps cords and location to go to.

local BF() = turtle.detect
local BU() = turtle.detectUp
local BD() = turtle.detectDown
local ID, a, b, c = rednet.receive()
local x, y, z = gps.locate(60)
local fuel() = turtle.getFuelLevel

rednet.open("right")

if x == nil then
   rednet.broadcast("No GPS found aborting operation")
   exit()
else
  turtle.refuel(all)
   if fuel() < 10 then
	rednet.broadcast("Fuel level low")
rednet.broadcast("Aporting operation")
rednet.broadcast("Currently at" .. x .. y .. z)
exit()
   else
	rednet.broadcast("Currently at" .. x .. y .. z)
	rednet.broadcast("Moving to" .. a .. b .. c)
  end
end

--Moving turtle down/up

while not y == b do
local x, y, z = gps.locate(60)
if y < b then
  if fuel() > 0 then
	if BU() = true then
	 turtle.digUp()
	else
	 turtle.up()
end
  else
   rednet.broadcast("Out of Fuel")
   rednet.broadcast("Aporting operation")
   rednet.broadcast("Currently at" .. x .. y .. z)
   exit()
  end
end

if y > b then
  if fuel() > 0 then
	if BD() = true then
	 turtle.digDown()
	else
	 turtle.down()
end
  else
   rednet.broadcast("Out of Fuel")
   rednet.broadcast("Aporting operation")
   rednet.broadcast("Currently at" .. x .. y .. z)
   exit()
  end
end
end
-- Moving turtle on x axis and getting orientation
if fuel() < 10 then
local x, y, z = gps.locate(60)
rednet.broadcast("Fuel level low")
rednet.broadcast("Aporting operation")
rednet.broadcast("Currently at" .. x .. y .. z)
exit()
end

while not xmath == 1 do
  local x, y, z = gps.locate(10)
  local firstx = vector.new(x)
  while not turtle.forward() do turtle.dig() end
  local x, y, z = gps.locate(10)
  local secondx = vector.new(x)
  local xmath = firstx:sub(secondx)
if xmath == 0 then
   turtle.turnLeft()
  else
   turtle.turnLeft()
   turtle.turnLeft()
   local xmath = 0
end
end
if x > a then
turtle.turnLeft()
turtle.turnLeft()
end

while not x == a do
local x, y, z = gps.locate(60)
if x < a then
  if fuel() > 0 then
	if BF() = true then
  turtle.dig()
else
  turtle.forward()
end
  else
   rednet.broadcast("Out of Fuel")
   rednet.broadcast("Aporting operation")
   rednet.broadcast("Currently at" .. x .. y .. z)
   exit()
  end
end
if x > a then
  if fuel() > 0 then
	if BF() = true then
  turtle.dig()
else
  turtle.forward()
end
  else
   rednet.broadcast("Out of Fuel")
   rednet.broadcast("Aporting operation")
   rednet.broadcast("Currently at" .. x .. y .. z)
   exit()
  end
end
end
-- Moving turtle on z axis and getting orientation
if fuel() < 10 then
local x, y, z = gps.locate(60)
rednet.broadcast("Fuel level low")
rednet.broadcast("Aporting operation")
rednet.broadcast("Currently at" .. x .. y .. z)
exit()
end

turtle.turnLeft()
while not zmath == 1 do
  local x, y, z = gps.locate(10)
  local firstz = vector.new(z)
  while not turtle.forward() do turtle.dig() end
  local x, y, z = gps.locate(10)
  local secondz = vector.new(z)
  local zmath = firstz:sub(secondz)
if zmath == 0 then
   turtle.turnLeft()
  else
   turtle.turnLeft()
   turtle.turnLeft()
   local zmath = 0
end
end
if z > c then
turtle.turnLeft()
turtle.turnLeft()
end

while not z == c do
local x, y, z = gps.locate(60)
if z < c then
  if fuel() > 0 then
	if BF() = true then
  turtle.dig()
else
  turtle.forward()
end
  else
   rednet.broadcast("Out of Fuel")
   rednet.broadcast("Aporting operation")
   rednet.broadcast("Currently at" .. x .. y .. z)
   exit()
  end
end
if z > c then
  if fuel() > 0 then
	if BF() = true then
  turtle.dig()
else
  turtle.forward()
end
  else
   rednet.broadcast("Out of Fuel")
   rednet.broadcast("Aporting operation")
   rednet.broadcast("Currently at" .. x .. y .. z)
   exit()
  end
end
end
Bubba #2
Posted 15 March 2013 - 07:06 AM
Edit: My guess is that you want to get some requested x,y,z coordinates from rednet? If so, then you might want to look into textutils.serialize and textutils.unserialize. Here's an example:
Server Program

local tArgs = {...}
if #tArgs ~= 3 then
  print("Program requires x,y,z")
  return
end
rednet.send(idOfYourTurtle, textutils.serialize(tArgs))
print("Successfully sent coordinates")

Turtle code inserted somewhere at the beginning:

local newX, newY, newZ
local function getCoords()
  local id, msg = rednet.receive()
  local temp = textutils.unserialize(msg)
  if not temp then
    print("Not a serialized table.")
    return false
  end
  newX, newY, newZ = tonumber(temp[1]), tonumber(temp[2]), tonumber(temp[3])
  return true
end

getCoords()

What exactly are you having an issue with? I see several coding errors: have you actually tried to run it? Additionally, with the system you are using right now whenever the turtle broadcasts its current position it will just be a long, nonsensical string of numbers. You'll want to put some separators in there like so:

rednet.send(id, "Currently at: "..x..", "..y..", "..z)

Or something like that.

Also this is wrong:

local BF() = turtle.detect
local BU() = turtle.detectUp
local BD() = turtle.detectDown
local ID, a, b, c = rednet.receive()
local x, y, z = gps.locate(60)
local fuel() = turtle.getFuelLevel

It should be something like this:

local BF, BU, BD = turtle.detect, turtle.detectUp, turtle.detectDown --I just shortened this and removed the parentheses. See below for an explanation
local ID, a, b, c = rednet.receive() --This line was correct
local x,y,z = gps.locate(60) --Assuming that gps.locate works correctly this was correct too
local fuel = turtle.getFuelLevel --You're just creating a shortcut. Adding parentheses after the variable will cause an error. Same with the BF, BU, and BD vars.

What precisely do you mean by "how do you get coordinates from a rednet message"?gps.locate(60) should work fine assuming you have gps programs up and running.

I also do not believe that exit() is a function except for in the lua program (may be wrong, but can't test right now). Try using return instead.
Example:

if not x then
  print("GPS program not running or issues contacting server. Aborting.")
  return
end
subzero22 #3
Posted 15 March 2013 - 10:23 AM
ok thanks. I just started learning a couple days ago. I just learned a lot right now. I haven't been able to test it as I've been at work.

What are tArgs? never seen that before. I'm thinking it's like an arg.

I also want it to be more of a universal or select/input the id of my turtle than having to put it in the code. It's mainly to recall my turtles after a server reset if I wasn't able to get them back before then.

On the locals when I go to call them do I put BF() later in the script then or should I put the () back into the api's? I never fully understood taking the () off the end of them.

On the part for newX, newY, newZ can I use the a, b, c instead?

Would I still need the local ID, a, b, c = rednet.receive() as it seems the turtle code will be getting the values that I'm needing?

what are tonumbers used for as I've never seen that either?

Thanks again for helping me.

Edit: oh ya could I have a 4th tArg to get the is of the computer that sent it. instead of having to manually put it in or do a broadcast?
Bubba #4
Posted 15 March 2013 - 11:55 AM
What are tArgs? never seen that before. I'm thinking it's like an arg.
Edit: oh ya could I have a 4th tArg to get the is of the computer that sent it. instead of having to manually put it in or do a broadcast?

tArgs just captures any input when you run the program. It's actually the … (ellipsis type thing) that captures arguments, and you then put them into the table tArgs. I could call tArgs anything I wanted to and it would still work the same way. Here's an example:

local input = ... --Will only capture one argument because I do not capture it in a table
print(input)

Example 2:

local input = {...} --As many arguments as you give the program will be inserted into this table.
local a,b,c,d = input[1], input[2], input[3], input[4]
print("First arg: "..a)
print("Second arg: "..B)/>/>
--etc. etc.

I also want it to be more of a universal or select/input the id of my turtle than having to put it in the code. It's mainly to recall my turtles after a server reset if I wasn't able to get them back before then.
In that case you'll need to use rednet.broadcast rather than rednet.send.
Usage:

rednet.open("right") --Assuming there is a modem on the right
rednet.broadcast("To everybody listening, here is a message!")

On the locals when I go to call them do I put BF() later in the script then or should I put the () back into the api's? I never fully understood taking the () off the end of them.

Indeed you will. Just not when you are creating a shortcut. The parentheses signify that you are calling (running) the function, whereas a lack of parentheses mean you are setting a variable.
Example:

local myPrintCopy = print

myPrintCopy("Hello world!") --Works exactly the same as the regular print function

On the part for newX, newY, newZ can I use the a, b, c instead?
Certainly! You can use whatever you'd like there.

Would I still need the local ID, a, b, c = rednet.receive() as it seems the turtle code will be getting the values that I'm needing?
rednet.receive() will return three values: The ID, message, and distance to the sender. So it depends on what you want to do with those arguments
Example:

local id, message, distance = rednet.receive()
print("The sender ID was: "..id)
print("The message was: "..message)
print("The distance to the sender is: "..distance)

what are tonumbers used for as I've never seen that either?
tonumbers(arg) will convert any numerical object (a string, in your case) into a number. The reason I used it in my example was because rednet will return a string and for mathematical operations an actual number is required.

For example:

local strNumber = "500" --That's a string. I can't add a string to a number using + so I need to convert it to an actual number now
local n = tonumber(strNumber) --Okay, now it's a number. Let's add it!
print("500 + 300 = "..n + 300)

Thanks again for helping me.

No problem :)/> I'm glad to do so.
subzero22 #5
Posted 15 March 2013 - 11:10 PM
Not sure if you saw the edit but I also have a couple more questions lol

Could I have a 4th tArg to get the is of the computer that sent it. instead of having to manually put it in or do a broadcast?

On the returns like the return false, return true is that a type of loop or would i have to do some kind of repeat … untill type thing?

Edit: Ok I finally got around to testing my code. I get a couple errors.

The server code gives me.
turtle-call:4: attempt to get length of nil
Spoiler


rednet.open("back")

local tArgs = (...)
if #tArgs ~= 3 then
 print("Program requires x, y, z")
 return
end
rednet.broadcast(textutils.serialize(tArgs))
print("Successfully sent cordinates")

textutils.slowPrint ("rednet is starting...")
sleep (2)
local open = rednet.isOpen("back")
  if open == true then
   print("rednet started")
   sleep (0.5)
   print("now recieving messages")
   sleep (0.5)
    while true do
     local ID, message, distance = rednet.receive()
     write(ID)
     write(": ")
     write(message)
     print()
    end
  else
   print("rednet failed to start")
   print("check modem and start again")
end

The turtle call code gives me.
bios:338: [string "startup"]:63: 'then' expected
Spoiler

-- Turtle Call
-- Check for gps cords and location to go to.
local BF, BU, BD = turtle.detect, turtle.detectUp, turtle.detectDown
local ID, a, b, c = rednet.receive()
local fuel = turtle.getFuelLevel
rednet.open("right")

local a, b, c
local function getCoords()
  local id, msg = rednet.receive()
  local temp = textutils.unserialize(msg)
  if not temp then
	print("Not a serialized table.")
	return false
  end
  a, b, c = tonumber(temp[1]), tonumber(temp[2]), tonumber(temp[3])
  return true
end
getCoords()
if x == nil then
   rednet.broadcast("GPS program not running or issues contacting server. Aborting.")
   return
else
  turtle.refuel(all)
   if fuel() < 10 then
	rednet.broadcast("Fuel level low")
rednet.broadcast("Aporting operation")
rednet.broadcast("Currently at: "..x..", "..y..", "..z)
return
   else
	rednet.broadcast("Currently at: "..x..", "..y..", "..z)
	rednet.broadcast("Moving to: "..a..", "..b..", "..c)
  end
end
--Moving turtle down/up

while not y == b do
local x, y, z = gps.locate(60)
if y < b then
  if fuel() > 0 then
	if BU() = true then
	 turtle.digUp()
	else
	 turtle.up()
end
  else
   rednet.broadcast("Out of Fuel")
   rednet.broadcast("Aporting operation")
   rednet.broadcast("Currently at: "..x..", "..y..", "..z)
   return
  end
end

if y > b then
  if fuel() > 0 then
	if BD() = true then
	 turtle.digDown()
	else
	 turtle.down()
end
  else
   rednet.broadcast("Out of Fuel")
   rednet.broadcast("Aporting operation")
   rednet.broadcast("Currently at: "..x..", "..y..", "..z)
   return
  end
end
end
-- Moving turtle on x axis and getting orientation
if fuel() < 10 then
local x, y, z = gps.locate(60)
rednet.broadcast("Fuel level low")
rednet.broadcast("Aporting operation")
rednet.broadcast("Currently at: "..x..", "..y..", "..z)
return
end

while not xmath == 1 do
  local x, y, z = gps.locate(10)
  local firstx = vector.new(x)
  while not turtle.forward() do turtle.dig() end
  local x, y, z = gps.locate(10)
  local secondx = vector.new(x)
  local xmath = firstx:sub(secondx)
if xmath == 0 then
   turtle.turnLeft()
  else
   turtle.turnLeft()
   turtle.turnLeft()
   local xmath = 0
end
end
if x > a then
turtle.turnLeft()
turtle.turnLeft()
end

while not x == a do
local x, y, z = gps.locate(60)
if x < a then
  if fuel() > 0 then
	if BF() = true then
  turtle.dig()
else
  turtle.forward()
end
  else
   rednet.broadcast("Out of Fuel")
   rednet.broadcast("Aporting operation")
   rednet.broadcast("Currently at: "..x..", "..y..", "..z)
   return
  end
end
if x > a then
  if fuel() > 0 then
	if BF() = true then
  turtle.dig()
else
  turtle.forward()
end
  else
   rednet.broadcast("Out of Fuel")
   rednet.broadcast("Aporting operation")
   rednet.broadcast("Currently at: "..x..", "..y..", "..z)
   return
  end
end
end
-- Moving turtle on z axis and getting orientation
if fuel() < 10 then
local x, y, z = gps.locate(60)
rednet.broadcast("Fuel level low")
rednet.broadcast("Aporting operation")
rednet.broadcast("Currently at: "..x..", "..y..", "..z)
return
end

turtle.turnLeft()
while not zmath == 1 do
  local x, y, z = gps.locate(10)
  local firstz = vector.new(z)
  while not turtle.forward() do turtle.dig() end
  local x, y, z = gps.locate(10)
  local secondz = vector.new(z)
  local zmath = firstz:sub(secondz)
if zmath == 0 then
   turtle.turnLeft()
  else
   turtle.turnLeft()
   turtle.turnLeft()
   local zmath = 0
end
end
if z > c then
turtle.turnLeft()
turtle.turnLeft()
end

while not z == c do
local x, y, z = gps.locate(60)
if z < c then
  if fuel() > 0 then
	if BF() = true then
  turtle.dig()
else
  turtle.forward()
end
  else
   rednet.broadcast("Out of Fuel")
   rednet.broadcast("Aporting operation")
   rednet.broadcast("Currently at: "..x..", "..y..", "..z)
   return
  end
end
if z > c then
  if fuel() > 0 then
	if BF() = true then
  turtle.dig()
else
  turtle.forward()
end
  else
   rednet.broadcast("Out of Fuel")
   rednet.broadcast("Aporting operation")
   rednet.broadcast("Currently at: "..x..", "..y..", "..z)
   return
  end
end
end
Edited on 15 March 2013 - 11:06 PM
Bubba #6
Posted 16 March 2013 - 01:57 AM
Well I can't tell which line is line 63 (on a tablet right now), but I believe it's this line:

if BF() = true then

Should be if BF() == true then

For the server code, you need to have this-> {…} not this-> (…) Curly brackets signify a table, so you're just capturing data in a table.

For broadcast, an ID is sent just as it is with rednet.send
Example:

local id, message, distance = rednet.receive()
Whether I use rednet.broadcast() or rednet.send(), you will be able to get the ID of the sender from that first variable.

On the returns like the return false, return true is that a type of loop or would i have to do some kind of repeat … untill type thing?

Not really sure what you mean by this. Return will return any values to the "parent" code, for a lack of a better word. Here's an example:

local function giveMeText()
  return "Hello world!"
end

print(giveMeText())
This will print "Hello world!", because that string was returned by the function giveMeText. The reason I use "return true" or "return false" is because I want to signify the status of the function. If it failed to work, then I will return false. If it did work, I will return true.
subzero22 #7
Posted 16 March 2013 - 09:11 AM
Thanks again

The reason i had put returns in my other code was because I was using exit() then someone told me it wouldn't work and to try to use return instead. Would that work or should I do a shell.run or something else?

what I want for the turtle is to wait till it gets cords in the script. mainly for this part of the code you showed me.


local a, b, c
local function getCoords()
  local id, msg = rednet.receive()
  local temp = textutils.unserialize(msg)
  if not temp then
		print("Not a serialized table.")
		return false
  end
  a, b, c = tonumber(temp[1]), tonumber(temp[2]), tonumber(temp[3])
  return true
end
getCoords()

So I'm thinking I would do something like


-- will repeat untill it receives a renet message. I mainly want it to just wait at this part of the code until it gets the a b c cords.
repeat

local a, b, c
local function getCoords()
  local id, msg = rednet.receive()
  local temp = textutils.unserialize(msg)
  if not temp then
		print("Not a serialized table.")
		return false
  end
  a, b, c = tonumber(temp[1]), tonumber(temp[2]), tonumber(temp[3])
  return true
end


until rednet.receive()

getCoords()

Edit:

Oh ya the server script works now if I do it on the monitor but if I do monitor side(left in this case) turtle-call (and put in the cords) it will give me the message program requires x, y, z. yet without the monitor it works. I've never came across that problem before.

The other problem is when I do run it on the monitor. the turtle just sits there doing nothing. At first I thought it was cause I forgot to put in fuel so I put in 3 stacks of coal lol. But it still does nothing. Doesn't send any messages or prints anything on it's own screen. I don't get any error messages though which is good.
Edited on 16 March 2013 - 08:46 AM
Bubba #8
Posted 17 March 2013 - 02:22 PM
The reason i had put returns in my other code was because I was using exit() then someone told me it wouldn't work and to try to use return instead. Would that work or should I do a shell.run or something else?

Yup, you should use return. Keep in mind that you won't be able to use return from a function - it will have to come from the main program.
e.g.

local function test()
  return 1==2 --This will return false, because 1 does not equal 2
end

if not test() then --If test is false, then reverse that boolean to true and continue with the if statement
  print("1 does not equal 2")
  return --The program will exit here
else
  print("The universe is broken.")
  --Continues with the rest of the program because there is no return statement
end

what I want for the turtle is to wait till it gets cords in the script. mainly for this part of the code you showed me.


local a, b, c
local function getCoords()
  local id, msg = rednet.receive()
  local temp = textutils.unserialize(msg)
  if not temp then
		print("Not a serialized table.")
		return false
  end
  a, b, c = tonumber(temp[1]), tonumber(temp[2]), tonumber(temp[3])
  return true
end
getCoords()

So I'm thinking I would do something like


-- will repeat untill it receives a renet message. I mainly want it to just wait at this part of the code until it gets the a b c cords.
repeat

local a, b, c
local function getCoords()
  local id, msg = rednet.receive()
  local temp = textutils.unserialize(msg)
  if not temp then
		print("Not a serialized table.")
		return false
  end
  a, b, c = tonumber(temp[1]), tonumber(temp[2]), tonumber(temp[3])
  return true
end


until rednet.receive()

getCoords()

That's not going to work because you "eat" the rednet_message event with the line

until rednet.receive()
This means that you can't capture the data from it. A better solution would be a while loop:

while not getCoords() do
  --Keep this blank so that it will repeat forever until getCoords() is true
end --While getCoords() returns false (which it does in the event that you are not sending a table), continue running the function

Oh ya the server script works now if I do it on the monitor but if I do monitor side(left in this case) turtle-call (and put in the cords) it will give me the message program requires x, y, z. yet without the monitor it works. I've never came across that problem before.

The other problem is when I do run it on the monitor. the turtle just sits there doing nothing. At first I thought it was cause I forgot to put in fuel so I put in 3 stacks of coal lol. But it still does nothing. Doesn't send any messages or prints anything on it's own screen. I don't get any error messages though which is good.

Hmm… You are typing "monitor left turtle-call 3 4 5", just like that? The monitor program should provide arguments to turtle-call…

Edit: It is possible that you need to set the monitor cursor position to (1,1) at the start of the program. Do so by adding inserting the following code into your own on the first line:

local mon = peripheral.wrap("left")
mon.clear()
mon.setCursorPos(1,1)