3 posts
Posted 03 June 2016 - 08:21 PM
Hey guys, I really hope you can help me!
I tried to write a small program that scans for a specific reusable Safari Net in an inventory next to the computer.
term.clear()
term.setCursorPos(1,1)
inventory = peripheral.wrap("left")
inventory.condenseItems()
print("Insert searched Net")
typeS = io.read()
function searchNet()
maxCount = inventory.getInventorySize()
for k = 1,maxCount do
item = inventory.getStackInSlot(k)
itemName = item.name
if(itemName == "safarinet.reusable") then
typeC = item.safari_net.captured
end
if(typeC == typeS) then
print("Slot: "..k)
break
end
end
end
searchNet()
So here's the problem:
If I run the program once, it works exactly as intended. It gives out the slot number of the searched
item and ends. But when i run it a second time it will always give out 1 as the slot number, no matter
if i change the item sequence or don't touch it at all. If I reboot the computer it works as intended again, but
only for the first time.
218 posts
Location
tmpim
Posted 03 June 2016 - 10:27 PM
The problem you are experiencing is an issue with
scope.
All the variables you are declaring are in the global scope because none of them are defined locally (ie with the 'local' token)
So, when you run it the second time, typeC still exists (because it is in the global environment and is still accessible when you leave your program's scope), and still contains the string of the safari net type you are looking for, because the if statement has not been triggered to overwrite the value of typeC.
It is a simple solution; whenever you declare a variable for the first time, use the 'local' token and it will limit it's scope to the block it was defined in.
While in this case only typeC
needs to be local for this to work as intended, localizing your variables is a good practice.
Edited on 04 June 2016 - 02:45 AM
3 posts
Posted 03 June 2016 - 11:29 PM
Thank you so much for the quick help!
It first seemed a bit tricky to me because the typeC was not in the same block as it was used in.
But I managed to do it like this:
term.clear()
term.setCursorPos(1,1)
inventory = peripheral.wrap("left")
inventory.condenseItems()
print("Insert searched Net")
typeS = io.read()
function searchNet()
local maxCount = inventory.getInventorySize()
for k = 1,maxCount do
item = inventory.getStackInSlot(k)
if(item.name == "safarinet.reusable") then
local typeC = item.safari_net.captured
if(typeC == typeS) then
print("Slot: "..k)
break
end
end
sleep(0.1)
end
end
searchNet()
… and it works perfectly!
Just out of curiosity, is there a way to clear global variables? I could theoretically just set it to anything that is not a Safari Net at the beginning of the code, couldn't I? Are there any smarter ways to do this?
7083 posts
Location
Tasmania (AU)
Posted 04 June 2016 - 01:25 AM
Just out of curiosity, is there a way to clear global variables? I could theoretically just set it to anything that is not a Safari Net at the beginning of the code, couldn't I? Are there any smarter ways to do this?
The "smarter way to do it" is to not use globals in the first place. But yes, you could indeed manually set globals to nil at the start of your script.
1610 posts
Posted 04 June 2016 - 01:37 AM
Thank you so much for the quick help!
It first seemed a bit tricky to me because the typeC was not in the same block as it was used in.
But I managed to do it like this:
term.clear()
term.setCursorPos(1,1)
inventory = peripheral.wrap("left")
inventory.condenseItems()
print("Insert searched Net")
typeS = io.read()
function searchNet()
local maxCount = inventory.getInventorySize()
for k = 1,maxCount do
item = inventory.getStackInSlot(k)
if(item.name == "safarinet.reusable") then
local typeC = item.safari_net.captured
if(typeC == typeS) then
print("Slot: "..k)
break
end
end
sleep(0.1)
end
end
searchNet()
… and it works perfectly!
Just out of curiosity, is there a way to clear global variables? I could theoretically just set it to anything that is not a Safari Net at the beginning of the code, couldn't I? Are there any smarter ways to do this?
Your code here is better, but still has some unnecessary globals. For example:
inventory on line 3
typeS on line 6
searchNet on line 8 (yep, functions are variables too! Just stick
local before
function and it will work fine)
item on line 11
The rest of the code looks good, and this will help prevent future issues.
To answer your other question - yes, there are a couple ways that you can 'reset' globals - by setting them to nil manually, or changing the program's environment. However, as BB said, it's still better not to use globals in the first place.
1080 posts
Location
In the Matrix
Posted 04 June 2016 - 08:30 AM
Local variables are accessed faster than globals. So it's always better to use locals over globals.
Nice scope tutorial.
3 posts
Posted 04 June 2016 - 10:16 AM
Thank you guys again for the quick answers!
I tried to use my knowledge and started to write the actual program i want to use for my spawner sorting system.
I want to create a function that takes any Safari Net type and gives out the slot it is located in.
local inventorySide = "right"
local inventory = peripheral.wrap(inventorySide)
inventory.condenseItems()
local function getNetSlot(_vNet)
local invSlots = inventory.getInventorySize()
for k = 1,invSlots do
local item = inventory.getStackInSlot(k)
if(item.name == "safarinet.reusable") then
local captured = item.safari_net.captured
if(captured == _vNet) then
return k
break
end
end
sleep(0.01)
end
end
print("Slot: "..getNetSlot(Skeleton))
When I run this code it says
'end' expected (to close 'if' at line 13)
but I can't see where I did something wrong
Edited on 04 June 2016 - 10:43 AM
7083 posts
Location
Tasmania (AU)
Posted 04 June 2016 - 12:44 PM
If you return something, an "end" must come immediately after. You can't "break" your loop there and you don't need to.