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

Table Issues

Started by campicus, 01 November 2013 - 05:22 AM
campicus #1
Posted 01 November 2013 - 06:22 AM
So, I am trying to make a program that will control all my spawners. I have a table that looks like this:

local spawn = {
creeper = true,
witch = true,
skeleton = true,
blaze = true,
pigmen = true,
slime = true,
chicken = true,
witch = true,
cow = true,
zombie = true,
}

Which I want to use in this sort of way:


for i, v in pairs(spawn) do
  if [i] then
    --"leave a rs signal to that spawner"
  end
end

The thing is, I need to tell the program what color cable to turn on/off, which is where this table comes in:

local cableColor = {
colors.green = "creeper",
colors.red = "witch",
colors.white = "skeleton",
colors.orange = "blaze",
colors.yellow = "pigmen",
colors.lime = "slime",
colors.pink = "chicken",
colors.purple = "witch",
colors.brown = "cow",
colors.lightgrey = "zombie",
}

How do I incorporate the cableColor table in?

e.g.,


for i, v in pairs(spawn) do
  if [i] then
    rs.setBundledOutput("back", cableColor[i])
  end
end
MKlegoman357 #2
Posted 01 November 2013 - 06:47 AM
You're going in the right direction.

First, you should swap cableColor keys and values:


local cableColor = {
creeper = colors.green,
witch = colors.red,
skeleton = colors.white,
blaze = colors.orange,
pigmen = colors.yellow,
slime = colors.lime,
chicken = colors.pink,
witch = colors.purple,
cow = colors.brown,
zombie = colors.lightGray --// it's lightGray, not lightgrey
}

Now, with that for loop:


for mob, enable in pairs(spawn) do
  if enable then --// if mob spawner is set to true
	rs.setBundledOutput("back", cableColor[mob])
  end
end
Engineer #3
Posted 01 November 2013 - 06:58 AM
That for-loop iterates through a table and returns the key and value:

for key, value in pairs( cableColor ) do
	 --# you dont need to check if a value exists, ipairs ony returns valid key and value pairs
	 --# so a simple rs call is only needed:
	rs.setBundledOutput( "back", value )
end

This more of a response to MKlegoman357 then to the OP. But this is a little more in-depth I guess.

Herp derp
Bomb Bloke #4
Posted 01 November 2013 - 07:34 AM
Engineer, there are two tables that the loop needs to reference: One which keeps track of which spawners should be on, and one which keeps track of the colours in the cable to activate if the spawners should be on. This is the reason for the check.

There is, however, a bit of a catch with that use of rs.setBundledOutput in that just switching it like that means you can only operate one spawner at a time. Using MKlegoman357's "cableColor" table with campicus' original "spawn" table, I would do this:

local rsSide = "back"

for mob, enable in pairs(spawn) do
  if enable and bit.band(rs.getBundledOutput(rsSide),cableColor[mob]) ~= cableColor[mob] then -- If mob spawner should be on but isn't
        rs.setBundledOutput(rsSide, rs.getBundledOutput(rsSide)+cableColor[mob])
  elseif bit.band(rs.getBundledOutput(rsSide),cableColor[mob]) == cableColor[mob] and not enable then -- If mob spawner should be off by isn't
        rs.setBundledOutput(rsSide, rs.getBundledOutput(rsSide)-cableColor[mob])
  end
end

If you wanted to parse the resulting redstone output from a remote computer, you could then use something like this:

local rsSide = "back"

for mob, enable in pairs(spawn) do
  if bit.band(rs.getBundledInput(rsSide),cableColor[mob]) == cableColor[mob] then
    print(mob.." is on")
  else
    print(mob.." is off")
  end
end

Edit: Or use the functions in the Colors API instead of the Bit API, whatever makes more sense to you.
campicus #5
Posted 01 November 2013 - 11:58 PM
Thanks so much for the help guys!
campicus #6
Posted 03 November 2013 - 07:45 PM
Bomb Bloke, could you recommend a good bit API tutorial or offer an explanation into bit.band? I have done a bit of googling and wiki-ing but am still a little confused how it all works.
Bomb Bloke #7
Posted 04 November 2013 - 02:56 AM
Alright, you asked for it… :lol:/>

Before starting, a quick recap on the use of "and" with true/false values. You've likely already used this when creating if/then statements. The basic "if" statement goes something like this:

if condition then action

To add "and" into this mix, you'd use something like:

if condition1 and condition2 then action

In this latter case, both conditions must evaluate as "true" for the entirety of the statement to evaluate as "true". If either is false, then the action won't be performed.

Next up, a recap on how CC deals with colours. Go read the bottom bit of the Color API, and you'll notice that each colour is really represented by a number, and each number is a power of 2 (from 2 to the power of 0 (1), up to 2 to the power of 15 (32768)). In particular, take a look at the binary representations of those numbers and the pattern it forms as you read down the list.

Now, when you set your bundled output to green, what ComputerCraft is actually doing is assigning a value of 8192 to that cable (0010000000000000). If you set it to purple, then the number ends up as 1024 (0000010000000000). If you wish to enable both those colours, then CC simply adds them together to get 9216. In binary, that looks like:

 0000010000000000
+0010000000000000
-----------------
 0010010000000000

0000000000000000 hence means "no colours", 1111111111111111 means "all colours", 1111111111101111 means "all colours except yellow" and so on.

So with all of the above in mind, what bit.band() does is perform the "and" operation logic that you'd usually use on your true/false statements and apply that to the bits in the binary representations of two numbers. The result is a new number that only has the bits set to 1 that were 1 in both of the originals (a "bitwise and").

Eg:

    0110010010001010
AND 0010010100111110
--------------------
    0010010000001010

Hence, if you take the "bitwise and" of the number assigned to your cable output along with any individual colour, then if the resulting number equals the value of your colour, you know that colour is enabled in your cable (otherwise the result will be 0).

    0101000101000010  -- Some value in your bundled cable...
AND 0000000001000000  -- The colour pink...
--------------------
    0000000001000000  -- Also the colour pink!

Which is pretty much exactly what the colors.test() function is there to check for you (something I only remembered after writing my previous post).

That is to say, this:

if bit.band(rs.getBundledInput(rsSide),cableColor[mob]) == cableColor[mob] then

… gives the exact same result as this:

if colors.test(rs.getBundledInput(rsSide),cableColor[mob]) then

Anyway, an interesting quirk of numbers written in binary is that any odd number will have the right-most bit set to 1, whereas any even number has it set to 0. Hence checking what "bit.band(number,1)==1" returns can tell you whether a number is odd or not. This is computationally faster then dividing by two and checking the remainder (ie, getting the modulus), because it's not performing any division - it's simply looking at that last bit, no matter how big or complex-looking the rest of the number really is.
campicus #8
Posted 04 November 2013 - 07:00 PM
Thank you for the explanation, it is starting to make a bit of sense now that I can think of colours as a number :)/> I think I understand your code now :D/>

Thanks again for taking the time to explain it all