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

turtle program

Started by Epicmonkeydude, 19 December 2012 - 04:17 AM
Epicmonkeydude #1
Posted 19 December 2012 - 05:17 AM
Works like a charm. :D/> Thank you Orwell and ChunLing. Now mining will be twice as fast. He better mine me some diamonds so I can have a fleet of mining turtles. Oops forgot to remove full() so it had no clue as to what to do.


function empty()
   if turtle.getItemCount(1)<=1 then
	  return true
   end
   return false
end

function turnleft(number)
   for i = 1,number do
	  turtle.turnLeft()
   end
end

function turnright(number)
   for i = 1,number do
	  turtle.turnRight()
   end
end

function Layer()
   turtle.digDown()
   turtle.down()
   turtle.dig()
   turtle.forward()
   turtle.turnRight()
   turtle.dig()
   turnleft(2)
   turtle.dig()
   turtle.turnRight()
   turtle.back()
   turtle.turnLeft()
   turtle.dig()
   turnright(2)
   turtle.dig()
   turtle.turnRight()
   turtle.dig()
   turtle.forward()
   turtle.turnRight()
   turtle.dig()
   turnleft(2)
   turtle.dig()
   turtle.turnLeft()
   turtle.forward()
   turtle.place()
end

local i = 0
local done = nil
print("How many layers would you like me to dig?")
local layers = tostring( read() )

for i = 1,layers do
   Layer()
   if i==layers then
	  done=true
   end
   if turtle.getItemCount(16) >=2 then
	  for a = 1,i do
		 turtle.up()
	print("Full inventory!")
	  end
return
   end
   if empty() then
	  for b = 1,i do
		 turtle.up()
	print("Out of ladders!")
	  end
return
   end
end

if done==true then
   for i = 1,layers do
	  turtle.up()
	  print("Goin' up!")
   end
end
Orwell #2
Posted 19 December 2012 - 05:19 AM
Well, the error message told you on what line it was, do you mind sharing it with us?

Edit: pretty sure that this line doesn't work:

if turtle.getItemCount(f)==>32 then
Did you mean this?

if turtle.getItemCount(f) >=32 then -- greater than or equal

Edit2: Maybe it's due to copy pasting, but these lines have concatenated words:

endfunction turnright(number)
should be:

end function turnright(number)

same for:

endlocal item(1), ...
and:

endif done==yes then
Epicmonkeydude #3
Posted 19 December 2012 - 07:29 AM
thanks for the >=32 part but the endfunction and that stuff was just a copy and paste fail derp :/
Orwell #4
Posted 20 December 2012 - 07:16 AM
Oh man, you gotta read up on some stuff. 'yes' and 'no' mean nothin in Lua, you'd want to use true and false. Also, item(f) is not valid at all, put this at the top:

local item = {}   -- creates a table called item
and instead of using item(), use item[] everywhere.

This line isn't right:

local item(1), item(2), item(3), item(4), item(5), item(6), item(7), item(8), item(9), item(10), item(11), item(12), item(13), item(14), item(15), item(16)
drop it.

You can't use 'empty' both as variable and as function name. Rename the variable 'empty'.

There seems to be a dozen more errors, but fix all that first.
Epicmonkeydude #5
Posted 20 December 2012 - 09:15 AM
Thank you, again. I've updated the code again, please could you take another look.
ChunLing #6
Posted 20 December 2012 - 07:11 PM
Explain exactly what you want to happen and exactly what happens instead.
Epicmonkeydude #7
Posted 21 December 2012 - 08:28 AM
Explain exactly what you want to happen and exactly what happens instead.
I want my turtle to dig a 3 by 3 hole down. There should be three conditions for the turtle returning to the surface. One is when it's dug what you asked, another is when it's out of ladders, the third is when it's got a certain amount of blocks in it's inventory.
'c' records how many layers it's dug down.
Once it has '?' amount of blocks the turtle should use 'c' to return to it's exact point it started. Just continues to mine when has '?' amount of blocks.
or
Once it has next to no ladders left the turtle should use 'c' to return to it's exact point it started. Doesn't seem to detect just ends up placing other blocks instead of ladders. Then continues to mine.
ChunLing #8
Posted 21 December 2012 - 02:25 PM
Okay, you're still using that "if done==yes then" thing, which is a bit dangerous since you may not be aware that "yes = nil" in your code, it's an unassigned global identifier you've created. Fortunately, nil ~= false, but the redundant comparisons should be eliminated for proper lua coding, and if you do that, then nil is pretty much the same thing as false. But that shouldn't be your current problem.

You declare c as a local iteration value in "for c = 1,layers do", which means that c no longer exists with the value you assigned it when you exit that loop. Instead, c is another unassigned global identifier with a nil value (it is obscured by the local iteration value c during the one loop, which goes out of scope and takes any value you've given it with it when the loop ends).

You try to check if function identifiers are == true rather than calling them and checking if their returns are true. This is an important difference, a function identifier will never be equal to true unless you reassign the identifier (in which case it will no longer be associated with the function).

That's kinda fortunate? At least, by never having those conditionals succeed, you avoid the bits of your code where you try to use the unassigned global identifier c as a number.

I'll think about fixing this if nobody else is eager to do it. Currently it's a bit messed up.
Epicmonkeydude #9
Posted 22 December 2012 - 04:07 AM
Wow I never realized it had that many problems…
Oh well, I have no clue as to how to fix this.
Should I be declaring a local variable to store the value of 'c'?
How do I call and check their returns are true?

By the way Thank You!
ChunLing #10
Posted 22 December 2012 - 11:26 AM
Well, first the function has to have returns. Your current functions don't…and empty does something quite strange, it sets its own identifier to instead be associated with the value true, meaning that you can no longer access the function.

To make that work with a return of true if slot one is empty and false otherwise, just redo the function like so:
function empty()
    if turtle.getItemCount(1)<=1 then
        return true
    end
    return false
end
A return terminates execution of the function and returns the associated value. Thus a return (and return value, if any) should always be immediately before a chunk end, since anything between a return value and the end would never be executed anyway. This also means that only one return in a function will ever be reached, and thus only the values associated with that return are returned (you can have multiple return values by using "return value1,value2,value3" and so on).

So, now empty will return true if slot one is empty and false otherwise. So you can use the function call in a conditional, and the outcome will use the return value.
if empty() then
  -- do stuff
end
You can also check "if empty() == true" (or false), but this just adds an additional compare operation and has no functional effect, it is thus not recommended for a boolean function. You can assign the value of the function's return to a variable, using "var = empty()", and then use var in your conditional checks (if empty were very calculation intensive and you needed to use the return value multiple times this would be appropriate). You cannot, however, assign another value to the return of a function call (like "empty() = 4").

If you want to use the value of a for iterator outside of that loop, you need to associate it with a variable that has scope outside the loop. So this doesn't work:
for i = 1,layers do
--various things
  if someCondition then
    local c = i
  end
end
The scope of c in this case would be even smaller than the scope of i, i exists for the duration of the for loop, c only exists till the end of the if/then. You need to declare c before the loop:
local c = nil
for i = 1,layers do
--various things
  if someCondition then
    c = i
  end
end
It is generally good practice to explicitly assign a value when declaring, even if that value is nil. In this case, it might be better to use 0 than nil, since i cannot be 0 in our loop and thus we can easily tell that 0 means someCondition was never true, but we also can use c as a number (for instance, in another for loop) with confidence that it won't cause an error.

Hopefully this will help you write your program. I'm a little surprised that nobody has jumped in and written it for you already, that's not really what we're supposed to do here, but frequently someone does.
Epicmonkeydude #11
Posted 22 December 2012 - 12:54 PM
Thank you a lot ChunLing I will update the code when I have these changes made and hopefully it will work with very few problems. :D/>
Epicmonkeydude #12
Posted 22 December 2012 - 01:31 PM
Hi guys hopefully one last problem. I think it's something to do with [f] more details in my first post which I updated. Thank you
remiX #13
Posted 22 December 2012 - 01:33 PM
Hi guys hopefully one last problem. I think it's something to do with [f] more details in my first post which I updated. Thank you

What value is 'f'? You're trying to set index 'f' in table 'item' but 'f' does not exist?
Orwell #14
Posted 22 December 2012 - 01:50 PM
Hi guys hopefully one last problem. I think it's something to do with [f] more details in my first post which I updated. Thank you

What value is 'f'? You're trying to set index 'f' in table 'item' but 'f' does not exist?
'f' is declared in the for loop :P/> just change this:

if turtle.getItemCount[f] >=2 then
to this:

if turtle.getItemCount(f) >=2 then
You still need to call it as a function. I'm not sure for the semantics however. I'm just correcting your syntax for now.
remiX #15
Posted 22 December 2012 - 02:23 PM
'f' is declared in the for loop :P/>

Lmao, I looked through the code about 3 times and couldn't see it -_-/>
ChunLing #16
Posted 22 December 2012 - 05:21 PM
I thought I said to use "i" as your iteration value. Oh well, "f" works once you pass it to turtle.getItemCount() as an argument rather than trying to index it like a table.

You've still got some oddness happening with the main body at the bottom, like that "if full==true then" (full is a function, it is never == true, it is only == to itself). You're using c very wrong, the local you declare first is "obscured" by the iteration value with the same identifier during the course of the for loop (iteration values are always a new variable allocated with a scope of the loop that iterates them). When you try to access it later during a different loop, it's still going to be nil because the version that got altered has gone out of scope. You've got a returns in the main program body, those will cause the program to terminate entirely, dumping you back to the shell (this is valid if that's what you want to happen there, but I don't think it is).

There may be some other problems. But address those first.

Use "i" as the iterator value for every loop, unless you are nesting loops (which you aren't, calling a function with a loop in another loop doesn't count). That will help fix some of your irregularities. Also, call functions, and use their returns.
Epicmonkeydude #17
Posted 23 December 2012 - 12:38 AM
First of I shall say that one of the things your saying won't work actually is :blink:/>
For example with the c value it does work since when my turtles out of ladders it returns to where it started.
I'll try fixing the rest up in a minute though.
ChunLing #18
Posted 23 December 2012 - 01:00 AM
Wait, if the program's actually working then don't mess with it for a bit. I may have misinterpreted the intent of some of what you're trying to do here (like I misread the scope of the for loop, it's got the other loop nested inside of it).

Okay, you do seem to intend to exit the program with those returns in the main body. Get rid of the "done=true" business, and turn "full==true" into "turtle.getItemCount(16) >=2", and you should have things about how you want. You are only ever using c inside the for loop where it is the iteration value, so you don't need the one outside the loop.

So your main program body looks like this:
print("How many layers would you like me to dig?")
local layers = tostring( read() )

for c = 1,layers do
    Layer()
    if turtle.getItemCount(16) >=2 then
        for g = 1,c do
            turtle.up()
            print("Full inventory!")
        end
        return
    end
    if empty() then
        for h = 1,c do
            turtle.up()
            print("Out of ladders!")
        end
        return
    end
end
for e = 1,layers do
    turtle.up()
    print("Goin' up!")
end
You no longer need full, it wasn't really working out anyway. The turtle just decides it's full once it starts getting stuff in slot 16.
Edited on 23 December 2012 - 12:16 AM
Epicmonkeydude #19
Posted 23 December 2012 - 01:24 AM
Okay re-updated the code and now it works like a charm. :D/>
ChunLing #20
Posted 23 December 2012 - 01:36 AM
You're trying to call item, a table, as a function. Who told you to do that? I didn't suggest any such thing.

Just forget the whole item table and full() function. "if turtle.getItemCount(16) >=2 then" your turtle is full.

You don't need the item table, you don't need local i (the iteration count is in scope for the for loop it iterates), you don't need local done (when the for loop reaches the completion value layer, it's done, and you can just use a for loop to go back up).

I should reiterate what I said before
Use "i" as the iterator value for every loop, unless you are nesting loops
You weren't nesting loops before, but now you are (I think that you had already changed to having nested loops by the time I said that, actually, but I missed it). When you have a for loop inside of another for loop, you should give the inner for loop a different identifier for the iterator value ("j" is common, followed by "k","l", and so on for further nested loops). This helps you (and us) track the nesting, and allows you to still use the iteration value of the outer loops (which you are attempting to do).

That would look like this:
for i = 1,layers do
    Layer()
    if turtle.getItemCount(16) >=2 then
	    for j = 1,i do --we need to tell i from j
		    turtle.up()
		    print("Full inventory!")
	    end
	    return
    end
    if empty() then
	    for j = 1,i do --we need to tell i from j
		    turtle.up()
		    print("Out of ladders!")
	    end
	    return
    end
end
for i = 1,layers do
    turtle.up()
    print("Goin' up!")
end
This is still a somewhat odd program design, for the task. One notable problem is that the ladder checking function isn't very reliable, you use multiple ladders per Layer(), and dig about which will put stuff into the selected slot if it's empty. If you run out of ladders in the middle of a Layer() and dig some cobble, your turtle will never notice running out of ladders.

The way to fix that is to have a replacement function that specifically places from slot one and then immediately checks to see if slot one is empty, or to select slot one to place and then switch to slot two for digging (still has a slight risk of overflowing wrap-around to slot one, if you are nearly full and then dig out a couple of types of blocks you haven't before). Or just not bother with the ladders, I usually don't (if I need a safe pit I put a water source at the top, you can place ladders yourself when you're climbing back out).

But the ladder problem is secondary. Getting the code to work at all comes first.
Edited on 23 December 2012 - 12:55 AM
Epicmonkeydude #21
Posted 23 December 2012 - 02:07 AM
Actually in Layer() I only use a single ladder and it works fine. I'm guessing this was a response from when I updated the code then looked and saw that I actually completely messed it up. Now it's working fine though.
ChunLing #22
Posted 23 December 2012 - 02:23 AM
Must have been tired, I could have sworn you were placing more than one ladder.