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

Turtle Should be Detecting Items in all Slots yet Doesn't

Started by Shadow_Assailant, 19 June 2013 - 01:50 AM
Shadow_Assailant #1
Posted 19 June 2013 - 03:50 AM
Hey! Me again! I'm still working on my Dark Iron Forge script for a mining turtle in the Mindcrack FTB pack. As it stands right now it's working almost 100% up to what I expect it to, except for one problem. In the link that I will post in a little bit you'll see my script for creating dark iron. The only major flaw that I can see at this point is that the turtle should constantly be detecting whether or not items are in its inventory. It does detect when items are in the inventory, but only when items are in the first slot. If I put the items in the middle of the inventory, the turtle continues to wait. I'm off to bed, so I won't be able to respond to any help anyone may give, so I'll be sure to respond ASAP. Not sure what's wrong with the script, but I'm grateful to anyone that helps. :)/>

Here's the pastebin. :)/>

Note: I'm sort of tired, so I haven't added many comments for reference between this version and the old one. Also, there are still some old comments. Sorry. :P/>
Bomb Bloke #2
Posted 19 June 2013 - 08:25 AM
In your main code block, you define "b", "m", and a number of other variables as local to the "while" block they're in. You then pass the contents of these variables to functions such as "checkInv" and "wait".

Those functions load that data into new variables with the same names as the old, but these are not the same variables - they're separate ones, local to the functions, which just happen to have the same names. When those functions finish, they get deleted.

There are two ways around this: One is to return the contents of the function's local variables as a "result", the other is to just treat the variables as global and not worry about passing them into and out of the functions at all. For the sake of presenting the more useful example I'll go with the former, and rename the variables to make it clearer how it works:

local function wait(anotherM)
  anotherM = anotherM + 1
  if anotherM >= 10 then
    -- etc
  end

  return anotherM
end

.
.
.

m = wait(m)

Furthermore, the "turtle.getItemCount" function returns the amount of items in the specified slot. If you have 64 items in the first, 35 in the second and 0 in the third, then running this loop:

for f=1,16 do
  q = turtle.getItemCount(f)
end

… will result in "q" being set to 0 when it's complete. When "f" was 1, "q" got set to 64. When "f" was 2, "q" got set to 35. For every other value of "f", "q" got set to 0, so that's the final result.

This would result in "q" being set to 99 when it's complete:

q = 0
for f=1,16 do
  q = q + turtle.getItemCount(f)
end

I'm not sure why you've created a "t" loop and an "f" loop.
Shadow_Assailant #3
Posted 19 June 2013 - 03:27 PM
Well I took into account your advice and it does seem to move slightly smoother. My only problems now are:

1) When I place items into any slot except 1 or 16, it seems the turtle takes a few seconds more than it should. I.e. when I place an item into slots 1 or 16, the turtle immediately recognizes it, but when I place a block into slots 2 - 15 the turtle takes sometimes up to and over 10 seconds.

2) If I place items into slot 16 and items elsewhere in the inventory, the turtle only takes into account the items placed into 16. So, if I put 5 blocks into slot 2 and 4 in slot 16, the blocks in 16 will move to slot 1 and the turtle will only mine 4 times rather than 9.

Here's the new version. – Sorry lack of comments. In a rush.

I'll be back soon to try to fix some of this and try any more advice anyone may have. :P/> Thanks!

Edit: Yeah. I haven't had any luck with this.
Bomb Bloke #4
Posted 19 June 2013 - 08:10 PM
Your main issues seem to revolve around a mis-understanding as to how loops work. Let's run through the code logic.

The program starts an infinite "while" loop on line 45, then on line 50, a "for" loop where "f" counts from 1 to 15. On line 53 you perform a conditional check.

The check wants to know if there are any items in slot "f", or if there are any items in slot 16. On the first iteration of the "for" loop, "f" is set to 1, so this condition checks only slots 1 and 16 for items. If neither has anything, it immediately skips down to the "else" statement on line 84. That code block contains two one-second sleep statements, and also does nasty things to your variables that you probably don't want it to do.

Once that's processed, the "for" loop starts its second iteration. "f" is increased by 1 to a total of 2 and execution carries on from under line 50 again. The conditional check on line 53 gets processed a second time, and inspects slots 2 and 16 only. Etc, etc, etc. Slots 15 and 16 are checked on the last iteration of the "for" loop - after that the loop ends, but is then restarted anew thanks to the "while" loop it's in.

Hence you can see that if you put items in slot 10 only, the "for" loop must iterate ten times before it finds them, which involves sleeping for about twenty seconds all up.

In regards to your second issue, your "transfering" function only transfers items from slot 16, and where it puts them is somewhat hard to track. The first time it's called it puts them into slot 1. The second time, slot 2, and so on - until a slot without items is found, in which case your "else" block on line 84 will've reset z for some reason. It seems you want to instead set it to take items first from slot "f", then from slot 16, and only ever put them into slot 1:

local function transfering()
  turtle.select(f)
  turtle.transferTo(1,turtle.getItemSpace(1))
  turtle.select(16)
  turtle.transferTo(1,turtle.getItemSpace(1))
end

This will only dip in to the contents of slot 16 if slot "f" wasn't enough to do the job. You would then rig the rest of the program so that block placements and whatnot are performed using that first slot.
Shadow_Assailant #5
Posted 20 June 2013 - 12:30 AM
Your main issues seem to revolve around a mis-understanding as to how loops work. Let's run through the code logic.

The program starts an infinite "while" loop on line 45, then on line 50, a "for" loop where "f" counts from 1 to 15. On line 53 you perform a conditional check.

The check wants to know if there are any items in slot "f", or if there are any items in slot 16. On the first iteration of the "for" loop, "f" is set to 1, so this condition checks only slots 1 and 16 for items. If neither has anything, it immediately skips down to the "else" statement on line 84. That code block contains two one-second sleep statements, and also does nasty things to your variables that you probably don't want it to do.

Once that's processed, the "for" loop starts its second iteration. "f" is increased by 1 to a total of 2 and execution carries on from under line 50 again. The conditional check on line 53 gets processed a second time, and inspects slots 2 and 16 only. Etc, etc, etc. Slots 15 and 16 are checked on the last iteration of the "for" loop - after that the loop ends, but is then restarted anew thanks to the "while" loop it's in.

Hence you can see that if you put items in slot 10 only, the "for" loop must iterate ten times before it finds them, which involves sleeping for about twenty seconds all up.

Ah makes a lot more sense now. Lol. You can obviously tell I'm just getting my feet wet with this. :P/> Makes it understandable as to why it delayed so much. Is their any way to make it so the check is instantaneous without typing out this?:


if turtle.getItemCount(1)>0 or turtle.getItemCount(2)>0 or turtle.getItemCount(3)>0 or -- -- -- --

In regards to your second issue, your "transfering" function only transfers items from slot 16, and where it puts them is somewhat hard to track. The first time it's called it puts them into slot 1. The second time, slot 2, and so on - until a slot without items is found, in which case your "else" block on line 84 will've reset z for some reason. It seems you want to instead set it to take items first from slot "f", then from slot 16, and only ever put them into slot 1:

local function transfering()
  turtle.select(f)
  turtle.transferTo(1,turtle.getItemSpace(1))
  turtle.select(16)
  turtle.transferTo(1,turtle.getItemSpace(1))
end

This will only dip in to the contents of slot 16 if slot "f" wasn't enough to do the job. You would then rig the rest of the program so that block placements and whatnot are performed using that first slot.

Yeah. This totally simplifies my transfering() function and from what I can tell totally makes my checkInv() function obsolete! Thanks!
Bomb Bloke #6
Posted 20 June 2013 - 07:44 AM
Is their any way to make it so the check is instantaneous without typing out this?:

if turtle.getItemCount(1)>0 or turtle.getItemCount(2)>0 or turtle.getItemCount(3)>0 or -- -- -- --

Yes, by rigging up a function to perform a loop:

local function holdingAnything()
  for i=1,16 do
    if turtle.getItemCount(i) > 0 then
      return true  -- Function ends if the "return" statement is triggered.
    end
  end
  return false   -- If none of the slots already prompted a return of "true",
end              -- then all are empty, so return "false".

.
.
.

if holdingAnything() then
  -- Turtle has something somewhere in its inventory...
else
  -- Turtle has a completely empty inventory!
end
Shadow_Assailant #7
Posted 20 June 2013 - 03:57 PM
Awesome.

Well, the code seemed to be flawless after all of this, but after some fiddling with the script, I might have messed something up. How? I have no idea because everything should be working properly but it's not.
This is the current version of the code.

The turtle recognizes items are in its inventory and everything and I believe it does count properly, yet the turtle seems to totally skip over this block of code:


while q>0 do
	  turtle.place()
	  sleep(3.3) -- Sleeps to make sure iron has converted.
	  turtle.dig()
	  wait() -- Checks to see if 10 blocks have been converted. Waits if so.
	  transfering() -- Keeps slot 1 full.
	  q = q - 1 -- One less block needs to be converted, so must take that into account.
    end

I say so because the turtle will turn right twice the initial time to face the flame, but then it immediately turns right twice again to face the player and then drops its inventory and then proceeds to wait. I'm not sure why. It seems to automatically count "q" to equal zero, but I have the statement in the code that should change "q" from zero to the correct amount of items that are in the inventory. Very confusing. :S
Bomb Bloke #8
Posted 20 June 2013 - 08:05 PM
Around line 45 you should have:

    q = 0
    for f = 1, 15 do
      q = q + turtle.getItemCount(f) -- Gets current count of inventory slots 1 - 15
    end

In addition, while line 44 will work, there's never any point in checking whether something "==true". This:

if holdingAnything() then

… works just as well, as "holdingAnything()" already returns as either "true" or "false".
Shadow_Assailant #9
Posted 20 June 2013 - 10:15 PM
Quite awkward how just slight change in where the variables are initially called drastically changes everything, but okay! :P/>

In addition, while line 44 will work, there's never any point in checking whether something "==true". This:

if holdingAnything() then

… works just as well, as "holdingAnything()" already returns as either "true" or "false".

Yeah. I figured as much so from looking at the example script you gave me a few posts back, but with the slight bug I had, I wanted to make sure that this wasn't causing any harm, though, I don't see how it possibly could have. :P/>

Thanks so much for your help Bomb!

Here's the finished script. :)/>