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

Program only works once after reboot

Started by Reflexx, 03 June 2016 - 06:21 PM
Reflexx #1
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.


Emma #2
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
Reflexx #3
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?
Bomb Bloke #4
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.
apemanzilla #5
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.
Dragon53535 #6
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.
Reflexx #7
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
Bomb Bloke #8
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.