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

Robot automatically selecting next slot, when slot empty?

Started by michaelcampbell229, 16 December 2015 - 06:45 AM
michaelcampbell229 #1
Posted 16 December 2015 - 07:45 AM
I've created a program that controls a (advanced) wireless mining turtle using a (advanced) wireless pocket computer. ASWD controls direction, f breaks block in front of the robot, g moves the robot upwards and h moves it down, when it moves forwards it adds one to the forwards count, takes one (from the forwards count) when it moves backwards and counts vertical distance. I'm playing on the Sky Factory mod pack (AT launcher) and rather than manually building out a new platform I created a code so a robot could do it for me!
Only have one small problem: once the robot has placed one stack, of blocks, it keeps moving forwards without placing anymore blocks as the wrong slot number is selected, so I made this code:

local level = turtle.getItemCount()
local slotnum = turtle.getSelectedSlot()
while true do
  if level == 0 then
	  if slotnum <= 18 then
		   slotnum = slotnum+1
			sleep(0.1)
		 turtle.select(slotnum)
	   end
  end
end

I thought it would do
1. every second start the program – that works (while true do)
2. if local level == 0 (i.e. no items in selected slot and the number of items is found using turtle.getItemCount)
then: if the slotnum is less than 18 - as there is 18 slots - go to the next slot. this would repeat this until it found a slot that had items (unless it didn't have any items)
4. when it found a slot with items it would select that slot and stop "searching" (allowing me to place blocks)
5. When that slot runs out it would start again until it found another slot.
What it actually does:
selects slots from 1 to 18 one after the other but doesn't check if these slots contains items then exits the code saying there isn't 17 slots.

The full code can be found here:
Turtle coderednet.open("right")

If you get rid from here

local level = turtle.getItemCount()
local slotnum = turtle.getSelectedSlot()
while true do
if level == 0 then
if slotnum >= 18 then
slotnum = slotnum+1
sleep(0.1)
turtle.select(slotnum)

end
end
end

To here it works fine - but doesn't change slot number

while true do
local sender, message, protocol = rednet.receive()

if message == "left" then
turtle.turnLeft()
end
if message == "right" then
turtle.turnRight()
end
if message == "forward" then
turtle.forward()
end
if message == "back" then
turtle.back()
end
if message == "placedown" then
turtle.placeDown()
end
if message == "placeup" then
turtle.placeUp()
end
if message == "up" then
turtle.up()
end
if message == "down" then
turtle.down()
end
if message == "break" then
turtle.dig()
end
end
Computer coderednet.open("back")
local disf = 0
local disb = 0
local disr = 0
local disl = 0
local disv = 0
while true do
term.clear()
term.setCursorPos(1,1)
print("Height "..disv)
– print("Right "..disr)
– print("Left "..disl)
print("Forwards "..disf)
print("Back "..disb)

local event, character = os.pullEvent("char")

if character == "p" and "o" then
disf = 0
disb = 0
disr = 0
disl = 0
disv = 0
end

if disr == -4 then
disr = 0
end
if disl == -4 then
disl = 0
end

if character == "w" then
rednet.broadcast("forward")
if disb >= 1 then
disb = disb-1
else
disb = 0
disf = disf+1
end
end

if character == "a" then
rednet.broadcast("left")
if disr >= 1 then
disr = disr-1
else
disl = disl+1
disr = 0
end
end

if character == "s" then
rednet.broadcast("back")
if disf >= 1 then
disf = disf-1
else
disb = disb+1
disf = 0
end
end

if character == "d" then
rednet.broadcast("right")
if disl >= 1 then
disr = disr-1
else
disl = disl+1
disr = 0
end
end

if character == "g" then
rednet.broadcast("down")
if disv >= 0 then
disv = disv-1
end
end

if character == "h" then
rednet.broadcast("up")
if disv >= 0 then
disv = disv+1
end
end

if character == "e" then
rednet.broadcast("placedown")
end
if character == "q" then
rednet.broadcast("placeup")
end
if character == "f" then
rednet.broadcast("break")
end
end
Any ideas on how to change my code?
Edited on 16 December 2015 - 06:46 AM
Bomb Bloke #2
Posted 16 December 2015 - 07:53 AM
This:

local level = turtle.getItemCount()
local slotnum = turtle.getSelectedSlot()

… sets "level" and "slotnum" to whatever those functions returned at the time you called them.

If you want to see what the item count of the selected slot is after switching slots, call turtle.getItemCount() again after each switch (within your loop); though truth be told it's not needed to switch slots to get their counts:

for i = turtle.getSelectedSlot(), 16 do     -- Loop "i" from the current slot to the maximum slot.
	if turtle.getItemCount(i) > 0 then   -- If the i'th slot has items, then
		turtle.select(i)              -- select it
		break                         -- and quit the loop early.
	end
end

See this tutorial if you're unfamiliar with "for" loops.
Edited on 16 December 2015 - 06:54 AM
michaelcampbell229 #3
Posted 16 December 2015 - 10:54 PM
Right, why didn't I notice that. I usually with JavaScript so I should have seen the problem. Out of curiosity in your code in your code you use i, could that be another letter or word?
KingofGamesYami #4
Posted 16 December 2015 - 11:29 PM
You can use any variable name. i is simply the traditional way of doing it.
Lupus590 #5
Posted 16 December 2015 - 11:35 PM
i stands for iterator (I think), as for-loops are commonly used to traverse lists/arrays/tables.

edit: see below
Edited on 16 December 2015 - 11:53 PM
Bomb Bloke #6
Posted 17 December 2015 - 12:10 AM
You can make it stand for "iterator" if you like, but that's not why we tend to use it.

http://stackoverflow.com/questions/4137785/why-are-variables-i-and-j-used-for-counters
michaelcampbell229 #7
Posted 17 December 2015 - 03:06 AM
Sorry to rain on your parade but it doesn't quite work.
Firstly when a stack is consumed it will move to the next stack but, only when the program is restarted - fixed by placing inside "while true do" i.e. infinitely running
When it has consumed everything it gets stuck in the last used slot that had items and the program times out - saying startup:9: Too long without yielding - does that mean it is only checking the slots after slot selected, therefore does it need to start check from slot 1 and check ever slot once, then time out or does it mean that when the program is started it needs to reset back to the first slot and check from slot 1 and time out if it finds nothing?
KingofGamesYami #8
Posted 17 December 2015 - 03:32 AM
You'll need to rescan each time your program places a block.

Your fix (putting it inside while true do) caused the "Too long without yielding" error. This error means that loop is not allowing any other code on that computer, or any other computer in your minecraft world, to execute. In order to allow other code to execute, you need to yield - os.pullEvent, and functions that call os.pullEvent (read, sleep, etc.) will yield.

In short, you need to throw a sleep( 1 ) inside your infinite loop. Although, you won't be able to move, build, etc.

Instead, I've modified your code a bit

Spoiler

while true do
local sender, message, protocol = rednet.receive()

--#every time you receive a message, check the slots.  If you didn't get a message, your turtle didn't move or place a block, so there should be no reason to check.

for i = turtle.getSelectedSlot(), 16 do     --# Loop "i" from the current slot to the maximum slot.
        if turtle.getItemCount(i) > 0 then   --# If the i'th slot has items, then
                turtle.select(i)              --# select it
                break                         --# and quit the loop early.
        end
end

if message == "left" then
turtle.turnLeft()
end
if message == "right" then
turtle.turnRight()
end
if message == "forward" then
turtle.forward()
end
if message == "back" then
turtle.back()
end
if message == "placedown" then
turtle.placeDown()
end
if message == "placeup" then
turtle.placeUp()
end
if message == "up" then
turtle.up()
end
if message == "down" then
turtle.down()
end
if message == "break" then
turtle.dig()
end
end
Edited on 17 December 2015 - 02:32 AM
michaelcampbell229 #9
Posted 17 December 2015 - 04:46 AM
You'll need to rescan each time your program places a block.

Your fix (putting it inside while true do) caused the "Too long without yielding" error. This error means that loop is not allowing any other code on that computer, or any other computer in your minecraft world, to execute. In order to allow other code to execute, you need to yield - os.pullEvent, and functions that call os.pullEvent (read, sleep, etc.) will yield.

In short, you need to throw a sleep( 1 ) inside your infinite loop. Although, you won't be able to move, build, etc.

Instead, I've modified your code a bit
Yes that works fine except once it has used all the items it wont go back to the first slot
KingofGamesYami #10
Posted 18 December 2015 - 01:53 AM
Where did you ever say you wanted it to go to the first slot in that situation? Besides, that's an extremely easy addition to your program… I'll let you figure it out yourself.
michaelcampbell229 #11
Posted 18 December 2015 - 03:58 AM
….. does it need to start check from slot 1 and check ever slot once, then time out or does it mean that when the program is started it needs to reset back to the first slot and check from slot 1 and time out if it finds nothing?

Fixed it by adding:

else if turtle.getItemCount == 0 then
turtle.select(1)
KingofGamesYami #12
Posted 18 December 2015 - 04:42 AM
First, I apologize for missing that information you helpfully placed inside a run-on question.

Second, turtle.getItemCount will never equal 0 (as it is a function), so I assume the code you actually added looked a bit different.
snowbeavers #13
Posted 18 March 2016 - 06:54 AM
Sorry but I need help with the visual progamming (I am using with my students). We want the turtle to automatically change item slots when it is out of items. Could someone please show the visual programming for this? Thanks
Bomb Bloke #14
Posted 20 March 2016 - 12:22 AM
Here's an example as to how it might be done in CCEdu:



This script constantly moves the turtle forward, placing blocks underneath it as it goes. If the currently selected slot empties, it'll stop and loop through its slots until it finds one which has items (looping forever if it entirely runs out - or at least, until someone either gives it more or stops the script).

You could also use "Inspect Item" (to get the name of what's in the current slot) and compare that to a "Block Name" in order to make the turtle look for specific types of blocks to place.