Some examples, to help the binary impaired!
Let's take two numbers:
Represented as binary, these numbers would be:
Let's say I do this, now:
Remember: (x & y) returns a value where the bit values that are 'on' in BOTH variables are on, but otherwise, are off. Look at the bit values for i and e, and you'll see that they do not share ANY bit values. So, f will equal 0 here.
Let's say I do this, then:
Code: Select all
var x := 2; // x := 0100;
var g := (x & i);
With the binary representation of 2 being 0100, and the binary of i being 0110, we can look, and see that the 2nd bit will be returned in the value, and only that bit (since it's the only one that both have.) Therefore, g will equal 2.
Now, let's try this:
Code: Select all
var y := 7; // y := 1110;
var z := (y & i);
Here we have 1110 AND 0110. This has bits 2 and 3 on, meaning z will equal 6.
Finally, let's do this:
Code: Select all
var a := 12; //a := 0011;
var b := (a & i);
Here, we have i as 0110. a is 0011. If you look at this, only bit 3 is on on both. Meaning b will equal 4.
Of course, all of the above would not generally be of much use for when testing bit-coded values. You are usually testing for the presence of a single value. But the info above should make it easy to figure out how to do so, to come to the same conclusion I did in my post above.
Let's say we have this:
Code: Select all
var p_fire := 1; //1000;
var p_water := 2; //0100;
var p_energy := 4; //0010;
var p_magic := 8; //0001;
Now, a quick primer on 'OR' and how you use it to 'add' bit fields;
Let's say you want to give me protection from fire and water. You could do it like this:
Code: Select all
var my_prots := p_fire + p_water; //Not proper!
That will happen to work in this case, but it is NOT how you are supposed to work with bit-coded values.
It works in this case because p_fire and p_water both only have a single bit set, meaning adding the numbers together will give you a number that has both their bits set. fire (1) plus water(2) = 3, which is 1100, which is correct, in this case. But...
The better way to combine bit-coded values is to OR them together:
Code: Select all
var my_prots := (p_fire | p_water);
OR gives you a value that looks at both numbers, and sets the return value's bits whereever EITHER value has it on, or if both do. So 1 OR 2 (1000 OR 0100) will happen also to be 3 (1100).
However, imagine you wanted to take someone's existing protections and 'add' a new protection to them; Say, we want to add 'fire' protection to whatever you might have now.
Doing this with mathematical addition can cause trouble:
What if I already HAD fire protection? The result would be, I no longer have fire protection, and have WATER protection instead! Not good! To fix this, I would have to first test for fire protection before 'adding' it in. But why do that, when I can simply do this:
This will have the result that no matter whether I have fire protection or not now, I will have it afterward. Let's say I have fire and water now: (1100). So, if I do (1100 OR 1000), the result is 1100. Say I have water and magic now (0101). If I do (0101 OR 1000) the result is (1101), which is correct; Fire, water and magic. OR turns on any bits that are on in either of the values, or both. Addition, on the other hand, is not what we want, just to be safe.
Now, then, testing for these values is easy;
Code: Select all
function HasProtection(protection)
return (my_prots & protection) == protection);
endfunction
If you AND a bit-coded value against the bit-coded value you are testing for, your result will be the value you are testing for, if those bits exist. Otherwise, it will be something different.
Say I currently have fire and water protection (1100). Say I call HasProtection(p_water)
(1100 & 0100) == 0100
So yes; that will work.
Say I call HasProtection(p_magic)
(1100 & 0001) == 0
So no, that will fail.
I could even do this:
Code: Select all
var p_magical_fire := p_fire | p_magic; //needs BOTH fire and magic. Note the |, and not +
If I then call HasProtection(p_magical_fire) I will get false, because I only have fire and water... not magic:
(1100 & 1001) == 1000;
The result is only the first bit on; for fire, because that's all I have that's also in the test. So I will fail that protection test. The code above WILL check that properly; It will be looking for the return value to equal the protection bit mask, which is 1001, but the result was 1000. So that's false.
Hope that helps some!