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

Having trouble with changing code from recursive infinite loop to another infinite loop.

Started by con_man_is_here, 03 May 2013 - 01:16 PM
con_man_is_here #1
Posted 03 May 2013 - 03:16 PM
Title: Having trouble with changing code from recursive infinite loop to another infinite loop.

I am having trouble trying to get my program to work. I spent a while trying to create a program to get a Felling Turtle to chop down rows of trees that I have another turtle planting. So I created this program but go the Error message java.lang.ArrayIndexOutOfBoundsException:256. I know this means that I have a recursive infinite loop but I don't know how to adapt the code for a 'while true do'. Any help would be gratefully appreciated.


Here is the code:

function start()
x = 0
y = 0
z = 0
if turtle.detect() == true
then tree()
else oneforward()
end
end

function oneforward()
turtle.forward()
start()
end

function tree()
turtle.dig()
turtle.forward()
digup()
end

function digup()
turtle.digUp()
turtle.up()
if turtle.detectUp() == true
then digup()
else down()
end
end

function down()
turtle.down()
if turtle.detectDown() == true
then forward()
else down()
end
end

function forward()
x = x + 1
turtle.forward()
turtle.forward()
turtle.forward()
if x == 22
then turncounter()
else tree()
end
end

function turncounter()
z = z + 1
if z == 5
then print("Done")
else turncheck()
end
end

function turncheck()
if y == 0
then turnright()
else turnleft()
end
end

function turnright()
turtle.turnRight()
turtle.forward()
turtle.forward()
turtle.forward()
turtle.forward()
turtle.turnRight()
turtle.forward()
turtle.forward()
y = 1
tree()
end

function turnleft()
turtle.turnLeft()
turtle.forward()
turtle.forward()
turtle.forward()
turtle.forward()
turtle.turnLeft()
turtle.forward()
turtle.forward()
y = 0
tree()
end

start()
Sariaz #2
Posted 04 May 2013 - 11:08 AM
To switch it you would want to make a main while true do loop. Inside it would do anything that you can repeat to achieve your goal. An example would be making it do a row of trees then turn to the start of the next one. Another way would be to use you checks and just have it do one tree then check for what to do next. Also for your functions like your down function that either does something or calls itself you can use a repeat until loop. Example code for the down function:

repeat
	  turtle.down()
until turtle.detectDown()
forward()
If your not familiar with repeat loops they run like a while true do until a condition is met (met being anything not nil or false). So if you convert your functions that recall them selves. Then place them in a loop in the order they would get called so that they do a repeating pattern you should be good. If you need more help let me know
con_man_is_here #3
Posted 06 May 2013 - 09:38 AM
Thanks for helping me, I understand what you are trying to say however I have literally no idea of how to implement it. How would I create a main while true do loop and how could I get all of this to repeat inside it? Sorry, for being a pain.
Sariaz #4
Posted 15 May 2013 - 08:25 PM
Ok i can think of three ways to try and help you. One is with concrete examples, one is metaphor to math, and the last is with a theoretical idea. Im going to put all three ways as separate posts please like whichever one helps you. If none of them help then try adding me as a contact on skype with the contact msg being need help. My skype name is sariaz90.
W00dyR #5
Posted 15 May 2013 - 08:37 PM
Thanks for helping me, I understand what you are trying to say however I have literally no idea of how to implement it. How would I create a main while true do loop and how could I get all of this to repeat inside it? Sorry, for being a pain.


repeat
  whatever()
until turtle.detect()

Is the same as


while not turtle.detect() do
  whatever()
end
Sariaz #6
Posted 15 May 2013 - 08:59 PM
On second thought all three methods kind of tie together so I'm going to put them all togeather in the next post it might be a bit though before I get that all typed/thought out.
Sariaz #7
Posted 15 May 2013 - 09:17 PM
So here is method one concrete examples:

For your functions most of them will be repeat loops or integrated into a main loop. Here would be a example of your digup function turned into a repeat loop.

NOTE: Any repeat loop could be made into a while loop and any while loop into a repeat loop. Only difference is they are opposites so a infinite while true do loop's equivalent repeat loop would be repeat until false. Looking at them you can see that the main body of the loop would be the same the only difference is that you the ending conditions are opposites. For this reason if any of your repeat or while loops have nots in them you could switch them to the other kind should you choose. For my examples though I will use only repeat loops for simplicity. Now for that digup function in repeat form



repeat
  turtle.digUp()
  turtle.up()
until not turtle.detectUp()
down()

As you can see the main body of the function stayed the same all I did was change how it looped. So in this case instead of recalling the main body if it detected something above it then stoping when it didn't detect something. I repeated the main body of the function until it stopped detecting something above it. You will notice at the end I called the down function this is because in your function you kept recalling until it stopped detecting something above it then it called down. So in mine after my loop finished and stopped detecting stuff above it I also called the down function. Now what about your oneforward function? That does not repeat itself so what do you do then?

Well this is where the main loop comes in your main loop. The main loop is a loop that when run once will do what you want then return you to the beginning to do it again. Im getting off topic for the one forward function that function would just go at the end of the main loop. This is because if you think of the main loop as your start function then you would have what is in the start function run then have what is in the oneforward function run then because you would be at the end of the loop it would run again(AKA running your start function again) if that makes sense.

So now onto the way of thinking your way though this. The basic idea is that if a function calls itself then you can turn it into a loop then if another function is called after put that after the loop. And for any functions that don't call themselves just have them run their stuff then run the next bit of code. This is where the math metaphor comes in. Remember solving those pesky equations where you had multiple variables? The same principle can be applied here.

If you don't remember those equations heres a refresher if you do remember skip this. Take the equation x+5 = y+3 simple except that you can't just isolate a variable to get its answer because you don't know what the other variable is. So what you have to do is this: minus 3 from both sides giving you x+2 = y now to finish the equation you substitute what y equals for y so the old x+5 = y+3 becomes x+5 = 3+what y equals giving you x+5 = (x+2)+3. That substitution is the principle you can use here.

So now that you understand the principle or remember it lets use it to help morph your equation into one made of loops instead of functions. Now remember you can still use functions but best not to use them unless your going to be calling it from multiple places in your script. So thinking of a function call as a variable and the functions body as the equation you substitute for it all you need to do is look at the top to turn those functions into code that doesn't need to call itself.

So to summarize turn your functions into loops by taking any code that is getting repeated and putting it as the body of your loop then figuring out when you stop recalling the function and make that the ending condition of the loop. Then once you have your functions turned into loops put those loops in where ever you call the function. Also you can make your start function be the main loop and put the oneforward function at its end so that when the oneforward function ends it will start the loop back at the beginning.
KaoS #8
Posted 16 May 2013 - 01:56 AM
another thing you may want to do that fits your coding style better is just return your function calls.
EXAMPLE

local myVar=0
local function a()
  myVar=myVar+1
  print(myVar)
  sleep(0.1)
  return a()
end
will work perfectly, you do not get the ArrayIndexOutOfBounds error if you are returning the function you are recursively calling so


function start()
		    x = 0
		    y = 0
		    z = 0
		    if turtle.detect() == true
		    then return tree()
		    else return oneforward()
		    end
end
function oneforward()
		    turtle.forward()
		    return start()
end
function tree()
		    turtle.dig()
		    turtle.forward()
		    return digup()
end
function digup()
		    turtle.digUp()
		    turtle.up()
		    if turtle.detectUp() == true
		    then return digup()
		    else return down()
		    end
end
function down()
		    turtle.down()
		    if turtle.detectDown() == true
		    then return forward()
		    else return down()
		    end
end
function forward()
		    x = x + 1
		    turtle.forward()
		    turtle.forward()
		    turtle.forward()
		    if x == 22
		    then return turncounter()
		    else return tree()
		    end
end
function turncounter()
		    z = z + 1
		    if z == 5
		    then print("Done")
		    else return turncheck()
		    end
end
function turncheck()
		    if y == 0
		    then return turnright()
		    else return turnleft()
		    end
end
function turnright()
		    turtle.turnRight()
		    turtle.forward()
		    turtle.forward()
		    turtle.forward()
		    turtle.forward()
		    turtle.turnRight()
		    turtle.forward()
		    turtle.forward()
		    y = 1
		    return tree()
end
function turnleft()
		    turtle.turnLeft()
		    turtle.forward()
		    turtle.forward()
		    turtle.forward()
		    turtle.forward()
		    turtle.turnLeft()
		    turtle.forward()
		    turtle.forward()
		    y = 0
		    return tree()
end
start()