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

[lua] [error] attempt to call nil

Started by pixels_deth, 31 March 2013 - 07:17 PM
pixels_deth #1
Posted 31 March 2013 - 09:17 PM
Im kinda new to computercraft, and i'm writing a mining program for a mining turtle. However when I try to run it I get "mine:26: attempt to call nil". Here is the code:


local distance = 0

function invenClear()
  for i = 2 , 16 do
	turtle.select(i)
	turtle.drop()

function move()
  repeat
  turtle.dig()
  until turtle.forward()
  turtle.digup()
  distance = distance + 1
  print(distance)
  if turtle.getItemCount(16) >0 then
	turtle.turnLeft()
	turtle.forward(distance)
	InvenClear()
	turtle.turnLeft(2)
	distance = 0
	end

end
end
end
move(10)  
theoriginalbit #2
Posted 31 March 2013 - 09:20 PM
there are not 26 lines there. please post all the code or indicate where there are spaces. nvm, it was my fault :P/>

I notice however that you have bad cases on function calls, Lua IS case-sensitive so change things such as InvenClear() to invenClear() and turtle.digup() to turtle.digUp()

also turtle.turnLeft(2) there is no parameter for turtle functions that specify how many times to do it. same for turtle.forward(distance)

lastly you call move(10) but do not accept any parameters for the function
function move()
pixels_deth #3
Posted 31 March 2013 - 09:34 PM
Okay, thanks for the trouble shooting tips, I must remember them in every program. I have changed my program to:

local distance = 0
function invenClear()
  for i = 2 , 16 do
	turtle.select(i)
	turtle.drop()
function move()
  repeat
  turtle.dig()
  until turtle.forward()
  turtle.digUp()
  distance = distance + 1
  print(distance)
  if turtle.getItemCount(16) >0 then
	turtle.turnLeft()
	turtle.turnLeft()
	for i = 1,distance do
	  turtle.forward()
	invenClear()
	turtle.turnLeft()
	turtle.turnLeft()
	distance = 0
	end
end
end
end
end
move()

However I still get the "attempt to call nill" error. Also I'm afraid I dont understand what you mean by parameters. Surley the 10 is a parameter?
theoriginalbit #4
Posted 31 March 2013 - 09:45 PM
ok so im assuming the error was on line 27 this time… and this time I see why :P/>

you have your functions nested, so it cannot see the move function. if you end the for loop and the invenClear functions it should be all good…

local distance = 0

function invenClear()
  for i = 2 , 16 do
	turtle.select(i)
	turtle.drop()
  end
end

function move()
  repeat
	turtle.dig()
  until turtle.forward()

  turtle.digUp()
  distance = distance + 1
  print(distance)

  if turtle.getItemCount(16) >0 then
	turtle.turnLeft()
	turtle.turnLeft()
	for i = 1,distance do
	  turtle.forward()
	  invenClear()
	  turtle.turnLeft()
	  turtle.turnLeft()
	  distance = 0
	end
  end
end

move()

the 10 is a parameter, but your move function was not setup to receive the '10'… so it did not have a purpose…

to have it accept a parameter you do this

function move( parameterName )
  -- function code
end
pixels_deth #5
Posted 31 March 2013 - 10:17 PM
Thank you very much for all your help so far, I have changed my code to:

local distance = 0
function invenClear()
  for i = 2 , 16 do
	    turtle.select(i)
	    turtle.drop()
  end
end
function move( parameterName )
  repeat
	    turtle.dig()
  until turtle.forward()
  turtle.digUp()
  distance = distance + 1
  print(distance)
  if turtle.getItemCount(16) >0 then
	    turtle.turnLeft()
	    turtle.turnLeft()
	    for i = 1,distance do
		  turtle.forward()
		  invenClear()
		  turtle.turnLeft()
		  turtle.turnLeft()
		  distance = 0
	    end
  end
end
move(10)

It runs without any error, but it will only go one block forward. Sorry to be a pain, but I think im nearly there!
theoriginalbit #6
Posted 31 March 2013 - 10:24 PM
you need to change your repeat loop to use the parameter that is passed into the move function… also you can name it whatever you wish, it doesn't need to be named parameterName… :P/>
pixels_deth #7
Posted 31 March 2013 - 10:35 PM
Thanks, i changed the parameterName to moves, how do I make the repeat loop use the parameter?
remiX #8
Posted 31 March 2013 - 11:11 PM
Use a for loop rather

function move( moves )
  for i = 1, moves do
            turtle.dig()
  end
  turtle.digUp()
  distance = distance + 1
  print(distance)
  if turtle.getItemCount(16) >0 then
            turtle.turnLeft()
            turtle.turnLeft()
            for i = 1,distance do
                  turtle.forward()
                  invenClear()
                  turtle.turnLeft()
                  turtle.turnLeft()
                  distance = 0
            end
  end
end
pixels_deth #9
Posted 31 March 2013 - 11:53 PM
Remix, I dont think you understand the purpose of the repeat loop. I put it there to deal with gravel and sand, so that the turtle would dig until it could move forward. If I were to use the for loop, the turtle would just dig 10 times without moving.
theoriginalbit #10
Posted 01 April 2013 - 12:01 AM
Remix, I dont think you understand the purpose of the repeat loop. I put it there to deal with gravel and sand, so that the turtle would dig until it could move forward. If I were to use the for loop, the turtle would just dig 10 times without moving.
oh is that what it's for. I assumed the same as remiX.

here is a solution

function move( moves )
  for i = 1, moves do -- this makes it run the amount of times we want
	while turtle.detect() do
	  turtle.dig()
	  sleep(0.8) -- wait for how long it takes for gravel/sand to fall
	end

	if not turtle.forward() then
	  if turtle.getFuelLevel() <= 0 then
		-- handle the fact we are out of fuel
	  elseif not turtle.attack() then
		while turtle.attack() do end -- it was a mob
	  else
		error('We cannot move for some reason', 0)
	  end
	end

	while turtle.detectUp() do -- we should do this gravel too
	  turtle.digUp()
	  sleep(0.8) -- wait for how long it takes for gravel/sand to fall
	end

	distance = distance + 1
	print(distance)

	if turtle.getItemCount(16) > 0 then
	  turtle.turnLeft()
	  turtle.turnLeft()
	  for i = 1,distance do
		turtle.forward()
		invenClear()
		turtle.turnLeft()
		turtle.turnLeft()
		distance = 0
	  end
	end
  end
end

TheOddByte #11
Posted 01 April 2013 - 12:03 AM
Remix, I dont think you understand the purpose of the repeat loop. I put it there to deal with gravel and sand, so that the turtle would dig until it could move forward. If I were to use the for loop, the turtle would just dig 10 times without moving.
What if you put a 'while <condition> do' at the top + end at the bottom?
With the code Remix put there.
Spoiler


function move( moves )
while true do
  for i = 1, moves do
            turtle.dig()
       sleep(0.8) --The time for gravel and sand to fall
  end
  turtle.digUp()
  distance = distance + 1
  print(distance)
  if turtle.getItemCount(16) >0 then
            turtle.turnLeft()
            turtle.turnLeft()
            for i = 1,distance do
                  turtle.forward()
                  invenClear()
                  turtle.turnLeft()
                  turtle.turnLeft()
                  distance = 0
            end
     end
end
      end
theoriginalbit #12
Posted 01 April 2013 - 12:30 AM
What if you put a 'while <condition> do' at the top + end at the bottom?
remiX's solution doesn't fit even with the infinite loop. if would have problems with sand/gravel still…
TheOddByte #13
Posted 01 April 2013 - 12:53 AM
What if you put a 'while <condition> do' at the top + end at the bottom?
remiX's solution doesn't fit even with the infinite loop. if would have problems with sand/gravel still…
But isn't the falling time of sand/gravel 0.8 ?
I think it is, And if you look at the code I added that there.
theoriginalbit #14
Posted 01 April 2013 - 12:54 AM
But isn't the falling time of sand/gravel 0.8 ?
I think it is, And if you look at the code I added that there.
yes but it also means that it will only dig 10 gravel (if it can) and then it will move forever… if you take a look at the code I posted and compare it to remix/yours you should see what I mean…
pixels_deth #15
Posted 01 April 2013 - 02:32 AM
Thank you for all the help everyone. It seems that after every solution theres another problem. I've decided to just use someone else's mining program for now, but I'll keep trying and hopefully I'll succeed eventually.
theoriginalbit #16
Posted 01 April 2013 - 02:35 AM
It seems that after every solution theres another problem.
Welcome to the world of programming… here is a breakdown of how I spend my time when making programs in ComputerCraft:
  • ~15-20% of my time figuring out the problem and how I am going to approach it
  • ~20% of my time design
  • ~5-10% of my time coding the solution
  • 55% of my time debugging the code and getting it work as best as possible for release
pixels_deth #17
Posted 01 April 2013 - 09:58 AM
Okay, decided to give this another try, wrote this:


local distance = 0

function forward()
repeat
turtle.dig()
until turtle.forward()
turtle.digUp()
distance = distance + 1
print(distance)
end

function invCheck()
  if turtle.getItemCount(15) >= 1 then
  print( "Returning items to chest" )
  turtle.turnLeft()
  turtle.turnLeft()
  for i = 1,distance do
    turtle.forward()
      end
  for i =1,15 do
  turtle.select(i)
  turtle.drop()
    end
  turtle.select(1)
  turtle.turnLeft()
  turtle.turnLeft()
  distance = 0
    end
repeat
forward()
invCheck()
until distance == 100

turtle.turnLeft()
turtle.turnLeft()

for i = 1,100 do
turtle.forward()
end
end

It runs without displaying any error messages, but it also doesn't do anything else! The program ends immediatly.
theoriginalbit #18
Posted 01 April 2013 - 04:21 PM
It runs without displaying any error messages, but it also doesn't do anything else! The program ends immediatly.
you have 2 functions there, neither of which you call… Lua needs a function call to run a function. so which ever is your main function (im assuming invCheck) run it at the bottom of your code
pixels_deth #19
Posted 01 April 2013 - 09:49 PM
How could I have missed that? Anyway, added both the functions at the end:

local distance = 0

-- making the turtle dig and move
function forward()
repeat
turtle.dig()
until turtle.forward()
turtle.digUp()
distance = distance + 1
print(distance)
end

-- checking for near full inventory
function invCheck()
  if turtle.getItemCount(15) >= 1 then
  print( "Returning items to chest" )
  turtle.turnLeft()
  turtle.turnLeft()
  for i = 1,distance do -- returning to chest at the front of the tunnel
    turtle.forward()
      end
  for i =1,15 do
  turtle.select(i)
  turtle.drop()
    end
  turtle.select(1)
  turtle.turnLeft()
  turtle.turnLeft()
  distance = 0
    end

repeat -- repeat both until turtle has mined 100 blocks
forward()
invCheck()
until distance == 100

turtle.turnLeft() -- move the turtle into position
turtle.turnLeft()

for i = 1,100 do -- return to the chest
turtle.forward()
end
end

Still nothing. I dont understand why its not doing anything.
Ray_Anor #20
Posted 02 April 2013 - 12:42 AM

--tunneling programm
local distance = 0
local complete = 0
function invCheck()
return turtle.getItemCount(15) >= 1
end
function returnBack()
print("Returning back")
turtle.turnLeft()
turtle.turnLeft()
for i = 1,distance do -- returning to chest at the front of the tunnel
  --Im recommend insert there call of function for fuel checking and refueling
  turtle.forward()
end
end
function unloadItems()
print("Unloading items")
for i=1,15 do
  turtle.select(i)
  turtle.drop()
end
turtle.select(1)
end

function mineForward(up,down,aggresive)
while turtle.detect() do
  turtle.dig()
end
if up then
  while turtle.detectUp() do
   turtle.digUp()
  end
end

if down then
  while turtle.detectDown() do
   turtle.digDown()
  end
end
if not turtle.forward() then
  if aggresive then
   turtle.attack() --if blocking way by monster/player
  end
  mineForward(up,down,aggresive)	--recursing for again attack monster/player and trying move forward
end
end
function tunneling(len,up,down,aggresive)
print("Starting tunneling. Tunnel length == "..tostring(len))
while distance<len do
  while not invCheck do
   --Im recommend insert there call of function for fuel checking and refueling
   turtle.select(1)
   mineForward(up,down,aggresive)
  end
  returnBack()
  unloadItems()
  turtle.turnLeft()
  turtle.turnLeft()
  distance = 0
  if distance % 10 == distance / 10 then
   if distance>complete then
	print("Complete "..tostring(distance).." of "..tostring(len).." tunneling.")
	complete=distance
   end
  end
end
returnBack()
unloadItems()
turtle.turnLeft()
turtle.turnLeft()
print("Tunneling complete. Tunnel length == "..tostring(len))
end
tunneling(100,true,false,false)

Try this programm.
theoriginalbit #21
Posted 02 April 2013 - 03:12 AM

--tunneling programm
local distance = 0
local complete = 0
function invCheck()
return turtle.getItemCount(15) >= 1
end
function returnBack()
print("Returning back")
turtle.turnLeft()
turtle.turnLeft()
for i = 1,distance do -- returning to chest at the front of the tunnel
  --Im recommend insert there call of function for fuel checking and refueling
  turtle.forward()
end
end
function unloadItems()
print("Unloading items")
for i=1,15 do
  turtle.select(i)
  turtle.drop()
end
turtle.select(1)
end

function mineForward(up,down,aggresive)
while turtle.detect() do
  turtle.dig()
end
if up then
  while turtle.detectUp() do
   turtle.digUp()
  end
end

if down then
  while turtle.detectDown() do
   turtle.digDown()
  end
end
if not turtle.forward() then
  if aggresive then
   turtle.attack() --if blocking way by monster/player
  end
  mineForward(up,down,aggresive)	--recursing for again attack monster/player and trying move forward
end
end
function tunneling(len,up,down,aggresive)
print("Starting tunneling. Tunnel length == "..tostring(len))
while distance<len do
  while not invCheck do
   --Im recommend insert there call of function for fuel checking and refueling
   turtle.select(1)
   mineForward(up,down,aggresive)
  end
  returnBack()
  unloadItems()
  turtle.turnLeft()
  turtle.turnLeft()
  distance = 0
  if distance % 10 == distance / 10 then
   if distance>complete then
	print("Complete "..tostring(distance).." of "..tostring(len).." tunneling.")
	complete=distance
   end
  end
end
returnBack()
unloadItems()
turtle.turnLeft()
turtle.turnLeft()
print("Tunneling complete. Tunnel length == "..tostring(len))
end
tunneling(100,true,false,false)

Try this programm.
why oh why are you using recursion…. no! bad Ray_Anor! bad! you should use a loop there.
SuicidalSTDz #22
Posted 02 April 2013 - 03:22 AM
why oh why are you using recursion…. no! bad Ray_Anor! bad! you should use a loop there.
Recursion loops are obviously the better choice at hand. Duh! (Not really.. Use a while loop or repeat until condition is met loop like TOBIT said ^_^/>)
Ray_Anor #23
Posted 02 April 2013 - 04:28 AM
why oh why are you using recursion…. no! bad Ray_Anor! bad! you should use a loop there.

it's work fine for me. :)/>

But! Better choise to insert some counter for this… and break recursion…

Maybe - insert also os.sleep(0.2) there if wil too bugging….

But! It's work fine in my look :)/>
Ray_Anor #24
Posted 02 April 2013 - 04:30 AM
why oh why are you using recursion…. no! bad Ray_Anor! bad! you should use a loop there.
Recursion loops are obviously the better choice at hand. Duh! (Not really.. Use a while loop or repeat until condition is met loop like TOBIT said ^_^/>)

and.. it's not my task in this algorithm to do ideal algorithm… it's only give chance to take a look for asker for him errors - how to do better him idea ;)/>
pixels_deth #25
Posted 02 April 2013 - 05:17 AM
Okay, here's my finished product, I may add torches and refuelling if I get around to it. Not much of an issue for me though, I'm on a peaceful world with stacks and stacks of coal.


local distance = 0
function move()
  repeat
    turtle.dig()
    until turtle.forward()
    turtle.digUp()
  distance = distance + 1
  print(distance)
end
 
function invCheck()
  if turtle.getItemCount(15) >= 1 then
  print("Returning items to chest...")
  turtle.turnLeft()
  turtle.turnLeft()
  for i = 1,distance do
  turtle.forward()
end
  for i = 1,15 do
  turtle.select(i)
  turtle.drop()
end
  turtle.select(1)
  turtle.turnLeft()
  turtle.turnLeft()
  distance = 0
end
end
repeat
move()
invCheck()
until distance == 500
turtle.turnLeft()
turtle.turnLeft()
for i = 1,500 do
turtle.forward()
end

I think ill refine it a bit more to allow user configuration, and then upload it.
SuicidalSTDz #26
Posted 02 April 2013 - 05:21 AM
why oh why are you using recursion…. no! bad Ray_Anor! bad! you should use a loop there.

it's work fine for me. :)/>
That's the thing. It works fine until the stack fills up with function calls then crashes.. Use loops, not recursion(function calls to keep a program running is defined as recursion)

Pixel's latest code does not use recursion to my knowledge. Congratulations, you have achieved world peace(In a Lua generated world that is)

This is more glorious, wear it with pride young grasshopper:





However, I would do this instead of your repeat loop:

while distance <500 and distance ~=500 do --Just safety precautions :)/>
 move()
 invCheck()
end