I'm getting this error at line 259, according to the turtle. Any help is much appreciated!
This is a read-only snapshot of the ComputerCraft forums,
taken in April 2020.
attempt to compare nil with number
Started by grabmyrooster, 18 September 2016 - 06:25 AMPosted 18 September 2016 - 08:25 AM
I've been debugging for about 3 hours and this is the only persisting error. I've taken bits and pieces of mining programs people have written (and shared freely, no theft here) to create a turtle that mines a 3x3 tunnel, then waits for GPS coordinates for the next tunnel. I'm getting stuck when it tries to communicate via rednet to the terminal that I would use to send the coordinates. The full code is at the pastebin here: http://pastebin.com/G5W4Pzab
I'm getting this error at line 259, according to the turtle. Any help is much appreciated!
I'm getting this error at line 259, according to the turtle. Any help is much appreciated!
Posted 18 September 2016 - 08:57 AM
You've got some "end"s in the wrong positions; I guess you're intending line 259 to be part of your moveY() function, but it's not. This'd be clearer to you if you went through and cleaned up your indentation.
Posted 18 September 2016 - 09:03 AM
You've got some "end"s in the wrong positions; I guess you're intending line 259 to be part of your moveY() function, but it's not. This'd be clearer to you if you went through and cleaned up your indentation.
I'm going through now cleaning it up, a lot of formatting was lost when copying things over from my test files. Are there specific 'end's causing the issue?
Posted 18 September 2016 - 09:16 AM
The first spot that stands out to me is where you start to define the forward() function (line 119) within sendRequest().
Edited on 18 September 2016 - 07:16 AM
Posted 18 September 2016 - 09:23 AM
I've updated that local function, it seemed clean enough afterwards and produced the same result.
local function sendRequest()
rednet.open("right") --Open rednet and clear the console
term.clear()
term.setCursorPos(1,1)
local digBlocks = false --Extra parameters: whether to dig blocks or attempt to go over
local goneUp = 0 --dir and goneUp are used to keep track of position
local dir = 0
function forward()
while not turtle.forward() do --If turtle cannot go forward (either out of fuel or block blocking)
print("Can't move, checking fuel")
if turtle.getFuelLevel() == 0 then
checkdig()
turtle.select(14) --This selects the ender chest connected to a fuel supply
turtle.place() --This places the ender chest
turtle.select(1) --This selects slot 1, where fuel would go
turtle.suck() --This pulls a stack out of the chest
turtle.refuel()
turtle.select(14)
turtle.dig()
end
if digBlocks then --If digBlocks var was true the turtle will dig thorugh the blockage otherwise will go over
turtle.dig()
else
turtle.up()
goneUp = goneUp + 1
end
end
while goneUp > 0 and not turtle.detectDown() do --Make sure to compensate for going up and over blocks by going down when next possible
turtle.down()
goneUp = goneUp - 1
end
end
function up() --Same as forward, for up
while not turtle.up() do
print("Can't move, checking fuel")
if turtle.getFuelLevel() == 0 then
checkdig()
turtle.select(14)
turtle.place()
turtle.select(1)
turtle.suck()
turtle.refuel()
turtle.select(14)
turtle.dig()
end
if digBlocks then
turtle.digUp()
end
end
end
function down() --Same as forward, for down
while not turtle.down() do
print("Can't move, checking fuel")
if turtle.getFuelLevel() == 0 then
checkdig()
turtle.select(14)
turtle.place()
turtle.select(1)
turtle.suck()
turtle.refuel()
turtle.select(14)
turtle.dig()
end
if digBlocks then
turtle.digDown()
end
end
end
function getPos() --Gets the position of the turtle from local GPS towers
print("Getting position")
cx, cy, cz = gps.locate(10)
print(cx, cy, cz)
end
function getDir() --Gets the heading of the turtle by taking position, moving forward 1 and comparing the 2 positions
print("Getting direction")
getPos()
ox, oy, oz = cx, cy, cz
forward()
getPos()
if oz > cz then dir = 0
elseif oz < cz then dir = 2
elseif ox < cx then dir = 1
elseif ox > cx then dir = 3 end
print(dir)
turtle.back()
getPos()
end
function turn(d) --Turns to heading "d", uses getDir() to calculate how many turns are needed
getDir()
print("Aligning")
print(dir, d)
while dir ~= d do
turtle.turnRight()
dir = dir + 1
if dir == 4 then dir = 0 end
end
end
function moveX() --Combine the past functions to move along the x axis
print("Moving X")
getPos()
if abx > cx then --The current and destination coordinates are compared to decide which heading is needed and distance to move
turn(1)
for x = 1, abx - cx do
forward()
cx = cx + 1
end
elseif abx < cx then
turn(3)
for x = 1, cx - abx do
forward()
cx = cx - 1
end
end
end
function moveZ() --The same as moveX() but for the Z axis
print("Moving Z")
getPos()
if abz > cz then
turn(2)
for z = 1, abz - cz do
forward()
cz = cz + 1
end
elseif abz < cz then
turn(0)
for z = 1, cz - abz do
forward()
cz = cz - 1
end
end
end
function moveY() --The same as moveX() but for the Y axis, as the movement is vertical no turn calcuations are needed so this function is shorter
print("Moving Y")
getPos()
if aby > cy then
for z = 1, aby - cy do
up()
cy = cy + 1
end
elseif aby < cy then
for z = 1, cy - aby do
down()
cy = cy - 1
end
end
end
getPos()
if aby > cy then --If the turtle has to move upwards to get to the destination if moves up first, if it needs to move down if moves down last
moveY()
moveX()
moveZ()
else
moveX()
moveZ()
moveY()
end
end
Posted 18 September 2016 - 11:29 AM
You're still defining functions within functions, although now it appears intentional. There's no apparent reason to do it here, though - declaring the moveY() / moveX() / etc functions in the global scope every time sendRequest() is called will simply overwrite the old pointers over and over (all blocks within your script share the same global environment table unless you specifically define and assign different ones). If you made them local to sendRequest() instead, you'd still be wasting time redeclaring functions that need only be defined once.
Though it does now appear that aby and cy can be defined before reaching that line. If they're not, then either the third argument passed to the script was not a numeric representation (making aby nil - see line 9), or the system was unable to get a GPS response (making cy nil - see line 182). You can narrow it down by printing the types before 259:
Though it does now appear that aby and cy can be defined before reaching that line. If they're not, then either the third argument passed to the script was not a numeric representation (making aby nil - see line 9), or the system was unable to get a GPS response (making cy nil - see line 182). You can narrow it down by printing the types before 259:
print("aby: " .. type(aby) .. " cy: " .. type(cy))
Posted 18 September 2016 - 10:26 PM
I would've thought that lines 7-10 would be giving aby, abx, abz numerical values as tArgs and function getPos() would give cx, cy, cz numerical values as well. Does it have something to do with the beginning lines?
I moved all functions out of local function sendRequest() and made them local functions that are defined on their own, and it gives the same problem so it didn't do anything other than make it cleaner.
local tArgs={...}
local abx = tonumber(tArgs[2])
local aby = tonumber(tArgs[3])
local abz = tonumber(tArgs[4])
I moved all functions out of local function sendRequest() and made them local functions that are defined on their own, and it gives the same problem so it didn't do anything other than make it cleaner.
Posted 18 September 2016 - 10:58 PM
I separated the program back into its original 3 programs, and found the underlying problem. The goto function is attempting to call gox, goy, goz (which are abx, aby, and abz but i found/replaced all of them) from the request file. Since the goto program hasn't called the coordinates on its own, it doesn't have them and treats them as nil. All I need to do is combine goto and request in a way that it sends the request and waits for a response, then once a response is received. goes to those coordinates.
Posted 19 September 2016 - 12:03 AM
I've gotten it to the point where it will send the rednet broadcast requesting coordinates, and will connect to the terminal that is listening for turtles. However it is still throwing the same error in the title. So either gox or cx isn't being properly defined and I can't for the life of me figure out which.
This pastebin is the terminal script: http://pastebin.com/DkdjbFDz
This pastebin is the goto/request hybrid script, throwing an error on line 104 currently: http://pastebin.com/bMf8XZgY
This pastebin is the terminal script: http://pastebin.com/DkdjbFDz
This pastebin is the goto/request hybrid script, throwing an error on line 104 currently: http://pastebin.com/bMf8XZgY
Posted 19 September 2016 - 02:51 AM
Just in case anyone takes a peek at this and can help: still no dice. I've determined the issue is the gox, goy, goz coordinates (abx, aby, abz). cx, cy, cz all work fine and are successfully called and defined any time getPos() is run. I've found no way to properly define gox, goy, goz since they are acquired from the terminal. So it's either an issue with the terminal coding, the goto coding, or both of them communicating.
Edited on 19 September 2016 - 12:53 AM
Posted 19 September 2016 - 10:50 AM
At this point I'm suspecting you've got another system in the area sending out rednet broadcasts. You're not performing any checks to ensure that the messages you're receiving are all coming from the same source.
Truth be told, unless you're using a very old build of ComputerCraft (something prior to 1.53), you could simply bundle a whole bunch of values together and send them within a single table. Even with an older build, you could do that by employing textutils.serialise().
I'm not sure how far you'd have to go back before you'd lose the ability to send numbers directly. Rather, I suspect it's always been possible to send those.
Because only strings can be send over rednet the coordinates are changed to and from strings on each side of the message
Truth be told, unless you're using a very old build of ComputerCraft (something prior to 1.53), you could simply bundle a whole bunch of values together and send them within a single table. Even with an older build, you could do that by employing textutils.serialise().
I'm not sure how far you'd have to go back before you'd lose the ability to send numbers directly. Rather, I suspect it's always been possible to send those.
Posted 19 September 2016 - 06:43 PM
I've got no internet on my desktop, so any help I've been getting including this forum I've been doing on my phone. I transfer the files to my phone then copy it all over to pastebin. I am using ComputerCraft version 1.5, because I'm unable to update my whole modpack on just my phone. What's an example of using textutils.serialise() so I can try that after work tonight, if you don't mind?
Posted 20 September 2016 - 05:15 AM
Spoiler
rednet.open("right")
local function clear() term.clear() term.setCursorPos(1, 1) end
while true do
clear()
print("Connected, ID: ", os.computerID(), ". Listening for turtles")
local id, msg = rednet.receive() --Wait for a turtle to say it is "Listening"
if msg == "Listening" then
local toSend = {"goto"} -- toSend will point to a table, toSend[1] == "goto"
clear()
-- Alarm:
rs.setOutput("back", true)
sleep(3)
rs.setOutput("back", false)
print("Turtle found, enter goto coordinates.")
repeat
write("Enter X: ") -- Ask this over and over...
toSend[2] = tonumber(read()) -- ... because tonumber() returns nil if passed something it can't convert...
until toSend[2] -- ... so we'd best loop until toSend[2] is non-nil.
repeat
write("Enter Y: ")
toSend[3] = tonumber(read())
until toSend[3]
repeat
write("Enter Z: ")
toSend[4] = tonumber(read())
until toSend[4]
clear()
print("Coordinates are: ")
print("X: ",toSend[2])
print("Y: ",toSend[3])
print("Z: ",toSend[4])
print("Sending coordinates...")
rednet.send(id, textutils.serialize(toSend)) -- Convert table to string representation, and send that.
sleep(2) -- This merely serves to keep the text on the screen a moment.
end
end
Spoiler
rednet.open("right") --Open rednet and clear the console
term.clear()
term.setCursorPos(1,1)
-- Variable definitions:
local digBlocks = false --Extra parameters: whether to dig blocks or attempt to go over
local goneUp = 0 --dir and goneUp are used to keep track of position
local dir = 0
local cx, cy, cz, gox, goy, goz
-- Function definitions:
local function checkFuel()
if turtle.getFuelLevel() < 10 then
if digBlocks then
turtle.dig()
elseif turtle.detect() then
print("Low on fuel, chest location blocked, will try refuelling later...")
return
end
turtle.select(14)
turtle.place()
turtle.suck()
turtle.refuel()
turtle.dig()
if turtle.getFuelLevel() == 0 then print("Warning: Out of fuel, can't refuel!") end
end
end
local function forward()
while not turtle.forward() do --If turtle cannot go forward (either out of fuel or block blocking)
turtle.attack()
checkFuel()
if digBlocks then --If digBlocks var was true the turtle will dig thorugh the blockage otherwise will go over
turtle.dig()
else
turtle.up()
goneUp = goneUp + 1
cy = cy + 1
end
end
while goneUp > 0 and not turtle.detectDown() do --Make sure to compensate for going up and over blocks by going down when next possible
turtle.down()
goneUp = goneUp - 1
cy = cy - 1
end
if dir == 0 then
cz = cz - 1
elseif dir == 1 then
cx = cx + 1
elseif dir == 2 then
cz = cz + 1
elseif dir == 3 then
cx = cx - 1
end
end
local function up() --Same as forward, for up
while not turtle.up() do
turtle.attackUp()
checkFuel()
if digBlocks then
turtle.digUp()
else
print("Warning: I'm obstructed from going up!")
end
end
cy = cy + 1
end
local function down() --Same as forward, for down
while not turtle.down() do
turtle.attackDown()
checkFuel()
if digBlocks then
turtle.digDown()
else
print("Warning: I'm obstructed from going down!")
end
end
cy = cy - 1
end
local function getPos() --Gets the position of the turtle from local GPS towers
print("Getting position")
while true do
cx, cy, cz = gps.locate()
if cx then
break
else
print("Warning: Unable to query GPS!")
sleep(5)
end
end
print("I'm at " .. cx .. "x" .. cy .. "x" .. cz)
end
local function turn(d) --Turns to heading "d"
print("Aligning")
print(dir, d)
while dir ~= d do
turtle.turnRight()
dir = dir + 1
if dir == 4 then dir = 0 end
end
end
local function moveHorizontal() --Combine the past functions to move along the x axis
print("Moving X")
if gox > cx then --The current and destination coordinates are compared to decide which heading is needed and distance to move
turn(1)
elseif gox < cx then
turn(3)
end
for x = 1, math.abs(gox - cx) do forward() end
print("Moving Z")
if goz > cz then
turn(2)
elseif goz < cz then
turn(0)
end
for z = 1, math.abs(goz - cz) do forward() end
end
local function moveVertical() --The same as moveX() but for the Y axis, as the movement is vertical no turn calcuations are needed so this function is shorter
print("Moving Y")
if goy > cy then
for z = 1, goy - cy do up() end
elseif goy < cy then
for z = 1, cy - goy do down() end
end
end
-- Initialisation:
print("Getting direction") -- We only need to do this once, no need for a function
getPos()
local ox, oy, oz = cx, cy, cz
while not forward() do turtle.turnRight() end
getPos()
if oz > cz then
dir = 0
elseif oz < cz then
dir = 2
elseif ox < cx then
dir = 1
elseif ox > cx then
dir = 3
end
print(dir)
-- Main program loop:
while true do
print("Connected, ID: ", os.computerID(), ". Listening for requests.")
rednet.broadcast("Listening") --Tell all other computers in the area that this turtle is ready and waiting for orders
local id, msg = rednet.receive(10) --Wait for a return message for 10 seconds, then repeat
msg = textutils.unserialise(msg)
if type(msg) == "table" then
if msg[1] == "goto" then
print("Goto request from ", id, "...")
gox, goy, goz = msg[2], msg[3], msg[4]
if goy > cy then --If the turtle has to move upwards to get to the destination if moves up first, if it needs to move down if moves down last
moveVertical()
moveHorizontal()
else
moveHorizontal()
moveVertical()
end
end
end
end
Can't say I've tested it, but you should be able to get the general idea.
Edited on 20 September 2016 - 03:17 AM
Posted 24 September 2016 - 06:22 AM
So in the past few days I've had basically no luck. I'm putting it to rest until I get internet hopefully next week because doing all of this from my phone is a little tedious. For right now since all 8 turtles follow the same pattern, I'm going to set up a script that just has them follow the same set path over and over again, a certain number of times. I'll make a new thread most likely or attempt to figure it out another way. Thanks for all the help!!