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

Multiple if commands?

Started by velox, 11 April 2013 - 11:12 AM
velox #1
Posted 11 April 2013 - 01:12 PM
Hi,

Wonder if someone could help - I'm building a solar panel factory and have a counter program (which I finally managed to get working tonight yaaay) that counts a certain number of redstone pulses then outputs another pulse. I have that bit sorted (mainly as a result of all the excellent info on this forum) but i'm just wondering if there is a cleaner way to achieve what i'm trying to do. I'm pretty new to programming so please excuse any newb questions..

I have multiple coloured inputs pulsing and i'm counting these inputs into variables. I would usually use elseifs but the issue with that is that it breaks the if chain as soon as one of them receives a pulse. I need it to monitor all of them. Any way to reduce the number of ifs? I'd imagine i'll end up with over 10 of these so just wonder if there is an 'if or' or similar that would function better? I've done some searching but i'm not getting any hits.

As a side question, any way to only count a redstone pulse only once? This program ends up adding 2 or 3 to the counter on each iteration which isnt really an issue as I just increase the total count but again wonder if there is a better way? I could up the sleep at the end but then I run a risk of missing a pulse (which isnt a disaster but isnt very clean)

Many thanks

Example code below (its a snippet):



while 1 == 1 do
  if testIn("back", colors.white) then
	pWhite = pWhite + 1
  end
  if testIn("back", colors.lightBlue) then
	pLightBlue = pLightBlue + 1
  end
  if testIn("back", colors.yellow) then
	pYellow = pYellow + 1
  end
end
Engineer #2
Posted 11 April 2013 - 01:25 PM
You could make another function wich accepts the color and the variable in question.

function replaceIf( color, variable )
     if testIn('back', color) then
           variable = variable + 1
     end
end

this will reduce your 16 ifs to 16 function calls. Its still the same but compacted. And for your iteration problem, you want to use:

os.pullEvent('redstone')

this waits until a redstone signal changed: on to off and off to on.

And by the way, welcome to the forums! I think its a good community here, so enjoy!;)/>

Edit: I dont think my function works as expected. It doesnt add to variable unfortunately
Brandhout #3
Posted 11 April 2013 - 01:38 PM
I assume you want to count pulses of the different color of inputs. In that case in addition to what Engineer said, u might want to create a table which keeps track of the different colors, and whether they were previously on. So everytime a redstone event is triggered you want to check if a color is on and whether is was on before.

As an example, blue and red are on. Now yellow turns on aswell, a redstone event is triggered. Using the previous script pred, pblue and pyellow all increase by one. You probably however just want yellow to be incremented by one.

A simple solution

-- create a table of the different colors.
prevOn = {[colours.yellow] = false, [colours.blue] = false} --etc etc.
function replaceIf( color, variable )
	 if testIn('back', color) and prevOn[color]==false then --checking if that colour turned from off to on.
		   variable = variable + 1
		   prevOn[color] = true
	 elseif not testIn('back', color) then --resetting the prevOn table if that colour input is false.
		  prevOn[color] = false
	 end
end
SuicidalSTDz #4
Posted 11 April 2013 - 02:00 PM
Just as to not confuse you:


while 1 == 1 do
  if testIn("back", colors.white) then
        pWhite = pWhite + 1
  elseif testIn("back", colors.lightBlue) then
        pLightBlue = pLightBlue + 1
  elseif testIn("back", colors.yellow) then
        pYellow = pYellow + 1
  end
end

This is basically all you need. Plain and simple.
velox #5
Posted 11 April 2013 - 02:02 PM
Hah just to prove how much of a nub I am, I thought I'd hit reply to your post Engineer, but instead I reported you lol. Presume they'll see I meant to respond & ignore it but apologies all the same!

Thanks to both. I didn't know you could call a function from within a function but yeah that makes perfect sense. I'll have a play around using both suggestions and see which works for me. Also didnt know that a variable in a function can be used elsewhere so i'm learning lots here :)/>

Can you use the os.pullEvent('redstone') in conjunction with rs.testBundledInput? Sorry I didnt mention I was using bundled cable.

Thanks for the super fast replies.

Velox
Engineer #6
Posted 11 April 2013 - 02:02 PM
Just as to not confuse you:


while 1 == 1 do
  if testIn("back", colors.white) then
        pWhite = pWhite + 1
  elseif testIn("back", colors.lightBlue) then
        pLightBlue = pLightBlue + 1
  elseif testIn("back", colors.yellow) then
        pYellow = pYellow + 1
  end
end

This is basically all you need. Plain and simple.
You forgot to add the redstone pullEvent! :P/>
velox #7
Posted 11 April 2013 - 02:06 PM
Just as to not confuse you:


while 1 == 1 do
  if testIn("back", colors.white) then
		pWhite = pWhite + 1
  elseif testIn("back", colors.lightBlue) then
		pLightBlue = pLightBlue + 1
  elseif testIn("back", colors.yellow) then
		pYellow = pYellow + 1
  end
end

This is basically all you need. Plain and simple.

Not sure how this would work and it didnt when I tried it. When I tested it like this, once it hit the first if, it broke out so the other counters never incremented (very possible for 2 counters to go off at the same time) I was testing it with a redstone timer onto three bundled inputs and it only ever incremented the first one. Or am I missing something?

*edit* I didnt have the redstone pull event thingy though so maybe that was it?
SuicidalSTDz #8
Posted 11 April 2013 - 02:29 PM
Just as to not confuse you:


while 1 == 1 do
  if testIn("back", colors.white) then
		pWhite = pWhite + 1
  elseif testIn("back", colors.lightBlue) then
		pLightBlue = pLightBlue + 1
  elseif testIn("back", colors.yellow) then
		pYellow = pYellow + 1
  end
end

This is basically all you need. Plain and simple.
You forgot to add the redstone pullEvent! :P/>
Blah! I'm not going to do all the work!


Just as to not confuse you:


while 1 == 1 do
  if testIn("back", colors.white) then
		pWhite = pWhite + 1
  elseif testIn("back", colors.lightBlue) then
		pLightBlue = pLightBlue + 1
  elseif testIn("back", colors.yellow) then
		pYellow = pYellow + 1
  end
end

This is basically all you need. Plain and simple.

Not sure how this would work and it didnt when I tried it. When I tested it like this, once it hit the first if, it broke out so the other counters never incremented (very possible for 2 counters to go off at the same time) I was testing it with a redstone timer onto three bundled inputs and it only ever incremented the first one. Or am I missing something?

*edit* I didnt have the redstone pull event thingy though so maybe that was it?
I never said the code was going to work as is :P/> I am a person that 'helps', not 'gives' ^_^/> Effort must be put forth to get an output.

EDIT: All I did was add your elseif statements. You can do the rest, unless someone else wants to pitch in. However, if you have any questions, we will be happy to help ( I do not speak for everyone )
LordIkol #9
Posted 11 April 2013 - 06:50 PM
Thanks to both. I didn't know you could call a function from within a function but yeah that makes perfect sense. I'll have a play around using both suggestions and see which works for me. Also didnt know that a variable in a function can be used elsewhere so i'm learning lots here :)/>/>

About using variables in a function somewhere else.
If you define the variable as local inside the function it will only work inside this function.
If you declare it without local it can be accessed anywhere but global variables can lead to other problems cause they are kind of persistant.
Best way to use a variable inside a program is to declare it as local at the beginning so it is accessable within this program from any point but will be reset when the program ends.

Greets loki
Smiley43210 #10
Posted 11 April 2013 - 08:38 PM
-snip-
-snippety-
When I tested it like this, once it hit the first if, it broke out so the other counters never incremented (very possible for 2 counters to go off at the same time) I was testing it with a redstone timer onto three bundled inputs and it only ever incremented the first one.
-snippety snip-
-snip-
EDIT: All I did was add your elseif statements. You can do the rest, unless someone else wants to pitch in. However, if you have any questions, we will be happy to help ( I do not speak for everyone )

Aside from the os.pullEvent being missing, there's another point: He wants to check each color, regardless if one if conditional evaluates true. Like he said, multiple counters may go off at the same time. If that happens, with elseifs, you only catch one.
theoriginalbit #11
Posted 11 April 2013 - 08:51 PM
SpoilerYou could make another function wich accepts the color and the variable in question.

function replaceIf( color, variable )
	 if testIn('back', color) then
		   variable = variable + 1
	 end
end

this will reduce your 16 ifs to 16 function calls. Its still the same but compacted. And for your iteration problem, you want to use:

os.pullEvent('redstone')

this waits until a redstone signal changed: on to off and off to on.

And by the way, welcome to the forums! I think its a good community here, so enjoy! ;)/>

Edit: I dont think my function works as expected. It doesnt add to variable unfortunately
SpoilerI assume you want to count pulses of the different color of inputs. In that case in addition to what Engineer said, u might want to create a table which keeps track of the different colors, and whether they were previously on. So everytime a redstone event is triggered you want to check if a color is on and whether is was on before.

As an example, blue and red are on. Now yellow turns on aswell, a redstone event is triggered. Using the previous script pred, pblue and pyellow all increase by one. You probably however just want yellow to be incremented by one.

A simple solution

-- create a table of the different colors.
prevOn = {[colours.yellow] = false, [colours.blue] = false} --etc etc.
function replaceIf( color, variable )
	 if testIn('back', color) and prevOn[color]==false then --checking if that colour turned from off to on.
		   variable = variable + 1
		   prevOn[color] = true
	 elseif not testIn('back', color) then --resetting the prevOn table if that colour input is false.
		  prevOn[color] = false
	 end
end
These would not work, they would not update the variable… the variable is not a table and thus is not passed by reference, but instead it is passed by value… meaning you cannot modify the variable.

However I do agree that a function would make this the easiest… also combined with a table would make it the cleanest…. something like this would count all the inputs of the bundled cables… (I've commented the code to help you understand it, but if there is anything that confuses you, just ask :)/> )

-- this is a table to store all the counts
local counterTotals = {}

-- this initializes our table will all the 16 colors
for i = 1, 16 do
  -- set our count for the current colour to 0
  counterTotals[2 ^ i] = 0
end

local function checkColor( col )
  -- if the supplied colour is on
  if rs.redstone.testBundledInput('back', col) then
	-- increment its count
	counterTotals[col] = counterTotals[col] + 1
  end
end

-- infinitely loop
while true do
  -- wait for a redstone event
  os.pullEvent('redstone')

  -- check all the colours
  for i = 1, 16 do
	-- call our check function with the current colour
	checkColor(2 ^ i)
  end

  -- you can put other code here to print the counts or whatever you want
end
velox #12
Posted 11 April 2013 - 11:25 PM
Thanks for all the really helpful replies. I'll let you know how I get on!
velox #13
Posted 12 April 2013 - 10:24 AM
Theoriginalbit, the last code you posted I can't seem to get to work &amp; i'm trying to work out the problem. Could you (or anyone) possibly just explain what the ^ operator does? (is it an operator?) I can't seem to find anything about it and it isnt listed with the other operators such as ~ < > etc. I tried experimenting with it but it seems pretty bonkers to me I.E. 2 ^ 8 = 256

Thanks

Velox
Engineer #14
Posted 12 April 2013 - 10:33 AM
^ is to the power. So:
2 ^ 1 == 2
2 ^ 2 == 2*2 == 4
2 ^ 3 == 2*2*2 == 8

Etc.
theoriginalbit #15
Posted 12 April 2013 - 05:07 PM
Theoriginalbit, the last code you posted I can't seem to get to work &amp; i'm trying to work out the problem. Could you (or anyone) possibly just explain what the ^ operator does? (is it an operator?) I can't seem to find anything about it and it isnt listed with the other operators such as ~ < > etc. I tried experimenting with it but it seems pretty bonkers to me I.E. 2 ^ 8 = 256
ok what is the problem? error message?

the ^ operator (yes you had the correct word) is to the power, just as Engineer stated, and he actually gave a good example of how it calculates, so the reason 2 ^ 8 is 256 is because 2 ^ 8 is actually 2*2*2*2*2*2*2*2.
Now to explain a bit more. Hope you feel like some binary theory :P/>
The reason I use this (without trying to be too confusing) is because the colours in Minecraft are stored in 2 bytes of information, or 16 bits (16 bits, 16 colours, not a coincidence, this is why there are only 16 colours)… Now these colours are, as I stated stored in binary. now to get a colour we could type the number representation, however the developers have made it easier for us by giving the variables in the colour API. but when it comes to trying to make efficient code that loops through all the colours we cannot just simply use these variables unless we make our own table. This is where the power of the binary scale comes in. Now with say an 8 bit binary zero is represented by 0000 0000, now 1 is represented by 0000 0001, 2 is 0000 0010, 3 is 0000 0011, etc. Now this can be visualised like so:

| 128 | 64 | 32 | 16 | 8 | 4 | 2 | 1 |
now if we put our binary 0010 0101 to this

| 128 | 64 | 32 | 16 | 8 | 4 | 2 | 1 |
|   0 |  0 |  1 |  0 | 0 | 1 | 0 | 1 |
all we do is add all these top numbers together where a 1 appears below and that is our decimal number, so in this case 00100101 is 37…
now if you didn't notice the numbers double from right to left. so each time we get further to the left, it is double the previous. so 16 bits would be this

| 32768 | 16384 | 8192 | 4096 | 2048 | 1024 | 512 | 256 | 128 | 64 | 32 | 16 | 8 | 4 | 2 | 1 |
now if you actually look at the numbers in the colours api black is 32768, red is 16384, all the way down to orange which is 2 and white which is 1…
now to work out any binary value we can use 2 to the power of the bit we want to check, so 2 ^ 16 (which is the next one to the left of the above diagram) is 65536… now on a side note, to figure out how many states we can represent in a given amount of bits we can use the formula (2^n)-1, where n is the number of bits, so with 16 bits of information we can store; (2^16)-1 = 65536 - 1 = 65535… so that is a number no bigger than 65535, or 65535 states of data, for example maybe storing the value of which way lots of levers are, or which levels someone has access to, etc, etc…
so knowing this we can use it to our advantage and create a loop that increments up the binary scale from 1-32768 or 0-15…
so by doing 2 ^ n, where n is 0-15 we are able to get these numbers which are our colours.

hope that all made sense. I'm pretty tired atm and explaining binary can be difficult at the best of times
velox #16
Posted 12 April 2013 - 09:50 PM
It kind of made sense and I know binary when I have to (which isn't often to be honest) - sometimes have to calculate IP bit masks etc. Thanks for the huge explanation. Will see if I can do some real world tests on it to understand it.

I ended up using a heavily bastardised version of engineers code as nothing I was trying on here would work. I your code it kept telling me something about nil I think (not very helpful but I can't get in front of it to test right now) i then tried engineers code but that complained about the brackets on the table so I dumped the table. At the very least, its all in functions now and it only counts up once per iteration and it now does what I was trying to get it to do. It just isn't very pretty…. :)/>

Will try and test again later and confirm.