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

Turtle stops after one block - Possible loop error

Started by lauchlan105, 24 February 2016 - 11:05 AM
lauchlan105 #1
Posted 24 February 2016 - 12:05 PM
Using latest version of FTB infinity evolved.

link to pastebin code: http://pastebin.com/mTsFaMjf

The Problem:
There are no error messages showing up.
If there ARE blocks in front of it it will mine the block in front and stop without having moving or digging up or down. The program is still running.
If there ARE NOT blocks in front it will move forward once and repetitively dig down. The program is still running.
So from my knowledge it is getting stuck in the digDown() loop if there aren't any blocks. but why?

Sections Explained:
Section 1:
for each dig function it is saying
if the detected block is not air, keep mining until it is.

Section 2:
mine forward till there is an airblock
move forward
mine up until there is an airblock
mine down until there is an airblock

Section3:
repeat section 2 until i > x

Does the data need to be constantly refreshed? Perhaps move the data sets into the function code?
Cant figure out a solution. I hope the code is neat enough for you :)/>
Lyqyd #2
Posted 24 February 2016 - 06:21 PM
Moved to Ask a Pro.
Sewbacca #3
Posted 24 February 2016 - 06:36 PM
Edit in every function this:

repeat
  local success = turtle.inspectUp() --Is there a block?
  if sucess then --If there is a block, then dig.
	turtle.dig()
	sleep(1)
  end
until not sucess --Repeat until there isn't a block.

I propose you, to edit your digDown function into this:

function digDown()
  local success = turtle.inspectDown()
  if sucess then
    turtle.digDown()
  end
end
Edited on 24 February 2016 - 05:43 PM
eniallator #4
Posted 24 February 2016 - 07:02 PM
Edit in every function this:

repeat
  local success = turtle.inspectUp() --Is there a block?
  if sucess then --If there is a block, then dig.
	turtle.dig()
	sleep(1)
  end
until not sucess --Repeat until there isn't a block.

I propose you, to edit your digDown function into this:

function digDown()
  local success = turtle.inspectDown()
  if sucess then
	turtle.digDown()
  end
end

or even better:

function digDown()
  while turtle.digDown() do end
end
Edited on 24 February 2016 - 06:05 PM
Sewbacca #5
Posted 24 February 2016 - 07:04 PM
Edit in every function this:

repeat
  local success = turtle.inspectUp() --Is there a block?
  if sucess then --If there is a block, then dig.
	turtle.dig()
	sleep(1)
  end
until not sucess --Repeat until there isn't a block.

I propose you, to edit your digDown function into this:

function digDown()
  local success = turtle.inspectDown()
  if sucess then
	turtle.digDown()
  end
end

or even better:

function digDown()
  while turtle.digDown() do end
end
I forgot that :D/>
lauchlan105 #6
Posted 24 February 2016 - 09:36 PM
Completely overlooked the use of ''if success''. thanks guys :D/> hopefully this helps

Edit: okay so i've added suggested changes but how can I get around lava and water? they don't return as false they return as "minecraft:flowing_water" or something similar. I also added two more if/else-if statements to each function so that it doesn't sleep if its not gravel or sand… The program runs really slowly though. Is that just the way it is due to processing speeds or due to the way i've written it? Also I am reluctant to add eniallator's ''do end'' function because I prefer knowing how the code is read by the computer so if someone could explain that in layman terms that'd be great. Thanks again guys.

PB: http://pastebin.com/edit/mTsFaMjf
Edited on 25 February 2016 - 02:35 AM
eniallator #7
Posted 25 February 2016 - 09:45 AM
Completely overlooked the use of ''if success''. thanks guys :D/> hopefully this helps

Edit: okay so i've added suggested changes but how can I get around lava and water? they don't return as false they return as "minecraft:flowing_water" or something similar. I also added two more if/else-if statements to each function so that it doesn't sleep if its not gravel or sand… The program runs really slowly though. Is that just the way it is due to processing speeds or due to the way i've written it? Also I am reluctant to add eniallator's ''do end'' function because I prefer knowing how the code is read by the computer so if someone could explain that in layman terms that'd be great. Thanks again guys.

PB: http://pastebin.com/edit/mTsFaMjf

basically the way that the function that i made works is by simply using the turtle.digDown() as the conditional in the while loop. If you would like to see for yourself and try it out, then try turtle.dig() (or digup or digDown, it doesn't matter) with a block that it will dig and without a block there/a block it can't dig. Basically the way the turtle.dig() (as like any other function of the turtle API) function works is it will return either true or false depending on whether it has successfully ran. In this case it will return true if it has dug a block and it will return false if it hasn't.

The reason that i have put the
while turtle.digDown() do end
is because its already trying to execute turtle.digDown() in the condition of the while loop so if i put for example turtle.digDown() in the body of the loop then it would run turtle.digDown() twice before it checks if it was successful.

Edit:
I just noticed you are checking for gravel/sand in the pastebin, This is not necessary for turtle.dig() because the function either is hardcoded to take a little longer or in the API theres a sleep() because if you have a while loop and you do turtle.dig() it is enough time for any falling sand to fall down and turn back into a block so if ran again it will dig the sand block rather than the falling sand.
Edited on 25 February 2016 - 08:54 AM
lauchlan105 #8
Posted 26 February 2016 - 01:48 AM
basically the way that the function that i made works is by simply using the turtle.digDown() as the conditional in the while loop. If you would like to see for yourself and try it out, then try turtle.dig() (or digup or digDown, it doesn't matter) with a block that it will dig and without a block there/a block it can't dig. Basically the way the turtle.dig() (as like any other function of the turtle API) function works is it will return either true or false depending on whether it has successfully ran. In this case it will return true if it has dug a block and it will return false if it hasn't.

The reason that i have put the
while turtle.digDown() do end
is because its already trying to execute turtle.digDown() in the condition of the while loop so if i put for example turtle.digDown() in the body of the loop then it would run turtle.digDown() twice before it checks if it was successful.

Edit:
I just noticed you are checking for gravel/sand in the pastebin, This is not necessary for turtle.dig() because the function either is hardcoded to take a little longer or in the API theres a sleep() because if you have a while loop and you do turtle.dig() it is enough time for any falling sand to fall down and turn back into a block so if ran again it will dig the sand block rather than the falling sand.

Okay that makes sense now… I'm sort of new to this stuff and was reading it as if the turtle digs down and then executes ''end''. That will be a lot better, a lot cleaner and also solve the issue of not being able to dig liquid blocks leaving it stuck.

I've typed up a new one (http://pastebin.com/HivCDCY6) that needs a lot of cleaning up but so far works and includes more features such as…
- user input for LxWxH
- ''Press space to refresh'' the script from pastebin automatically
- check if inventory is full (not working 100%)

Here's the code for the inventory check if you'd like to hep - hopefully i'm using these tags right
Spoiler

function invCheck() -- Checks if inventory is full
local int = 1
repeat
turtle.getItemCount(int)
if turtle.getItemCount(int) == 0 then --\
int = int + 16 ---- If it finds an empty space then keep mining
local full = "false" --/
elseif int < 16 then
int = int + 1 ---- If the slot has something in it but its not the last slot, keep checking
else
print("Inventory Full!!") --\
local full = "true" ---- If the last slot is full then the inventory is full.
int = int + 16 --/
end
until int > 16

if full == "true" then
print("Press enter once a space has been cleared")  -- This pauses the program until enter has been pressed confirming space has been made
local event, key4 = os.pullEvent( "key" )
if key4 == keys.enter then
clearScreen()
print("Check in again soon!")
end
end
end

I've commented where it stops, or more so doesn't stop. I was hoping that the turtle would stop mining and the code would stop being read until enter had been pressed but it prints press enter once a space… but the turtle keeps mining.
Perhaps
repeat
sleep(1)
until key4 == keys.enter ??
Dragon53535 #9
Posted 26 February 2016 - 01:53 PM
The problem isn't at the bottom of that part, it's at the top. Read this tutorial for variable scope.

I will try to explain your problem.


local int = 1
repeat
  turtle.getItemCount(int)
  if turtle.getItemCount(int) == 0 then
    int = int + 16
    local full = "false"--#Error is here
  elseif int < 16 then
    int = int + 1
  else
    print("Inventory Full!!")
    local full = "true" --# And here
    int = int + 16
  end
until int > 16

When you determine that something is local, it only then exists inside of it's respective code block, for example this random code:

local x = 10
print(x) --#10
do --#This just starts another code block, think of it like an if or while or function
  local x = 200 --#Create a NEW local variable called x for this code block
  print(x) --#200
end
print(x) --#10

You're encountering that problem because you're creating a variable, and putting it as local only to the part of the if statement it is declared in.

It's an absolutely simple fix:


local int = 1
local full --#Say full is a local variable here
repeat
  turtle.getItemCount(int)
  if turtle.getItemCount(int) == 0 then
    int = int + 16
    full = "false"--#Set full here
  elseif int < 16 then
    int = int + 1
  else
    print("Inventory Full!!")
    full = "true" --#Or here
    int = int + 16
  end
until int > 16
lauchlan105 #10
Posted 29 February 2016 - 07:11 AM
The problem isn't at the bottom of that part, it's at the top. Read this tutorial for variable scope.

I will try to explain your problem.


local int = 1
repeat
  turtle.getItemCount(int)
  if turtle.getItemCount(int) == 0 then
	int = int + 16
	local full = "false"--#Error is here
  elseif int < 16 then
	int = int + 1
  else
	print("Inventory Full!!")
	local full = "true" --# And here
	int = int + 16
  end
until int > 16

When you determine that something is local, it only then exists inside of it's respective code block, for example this random code:

local x = 10
print(x) --#10
do --#This just starts another code block, think of it like an if or while or function
  local x = 200 --#Create a NEW local variable called x for this code block
  print(x) --#200
end
print(x) --#10

You're encountering that problem because you're creating a variable, and putting it as local only to the part of the if statement it is declared in.

It's an absolutely simple fix:


local int = 1
local full --#Say full is a local variable here
repeat
  turtle.getItemCount(int)
  if turtle.getItemCount(int) == 0 then
	int = int + 16
	full = "false"--#Set full here
  elseif int < 16 then
	int = int + 1
  else
	print("Inventory Full!!")
	full = "true" --#Or here
	int = int + 16
  end
until int > 16

Holy wow. That is going to make things so much simpler. I never looked into how to actually define variables but saw it done that way and kept it that way. I have gone a round about way of getting the locals to work by calling out the function with the data in the brackets. So level(inputH,inputW,inputL) and they all flow through to their respective places. The code is working for the most part now and is usable with an error occurring only in specific circumstances.

Here is the updated code (sorry if its messy): http://pastebin.com/nDhkxked
Download it and try it out for yourself :D/>


The program now checks for available inventory space every time it moves forward a block. It slows down the process and I'm sure i'm doing it in an unconventional way but it works and the only thing on the ground is useless stuff.
Currently features
- User defined area
- Press space to sync code with pastebin
- Automatic inventory checks w/ chest dump if full
- Fuel calculator - tells you if it needs more fuel to complete the area (enter to continue doesn't work)
- Errors - The errors are totally supposed to be there to complete the ''in development'' feel.