Contents Back Forward |
Appendix A: Using binary operators |
A.1 Why binary operators? ToT uses a lot of information coded using binary mask. For example, living civilizations in a particular game are represented by a binary number. Thus the number 11010001 (209 decimal) means that in that game only 4 civilizations are active and particularly the first (barbarian), the fifth , the seventh and the eighth. This kind of code appeared often in Civ2 data (read Allard Höfelt's HexEditing document to see for yourself), and if you want to fully utilize CSPL you should have confidence with this kind of code. Without getting too far into the details, I'll describe operations commonly used to manage these binary numbers. If you only want to see the final formulae just look below at the conclusion section of this appendix. | |
A.2 AND operator The AND operator works exactly as it works in logic (if you consider 0=FALSE and 1=TRUE) So 0 AND 0 = 0 (FALSE AND FALSE = FALSE) 0 AND 1 = 0 (FALSE AND TRUE = FALSE) 1 AND 0 = 0 (TRUE AND FALSE = FALSE) 1 AND 1 = 1 (TRUE AND TRUE = TRUE) The important thing to understand about this operator is that if the first operand is TRUE then the result is exactly the second operand while if the first operand is FALSE then the result will be always FALSE (and vice versa) If we have a set of bits (for example a byte) we can use the AND operator bit-to-bit Example: byte1 = 01010101 AND byte2 = 00001111 ----------------------- result = 00000101 In C++ the AND operator is expressed by '&' character. | |
A.3 OR operator Also the OR operator works as in logic: 0 OR 0 = 0 (FALSE OR FALSE = FALSE) 0 OR 1 = 1 (FALSE OR TRUE = TRUE) 1 OR 0 = 1 (TRUE OR FALSE = TRUE) 1 OR 1 = 1 (TRUE OR TRUE = TRUE) The important thing to understand about this operator is that if the first operator is FALSE then the result is exactly the second operator while if the first operator is TRUE the result will be always TRUE (and vice versa) If we have a set of bits (for example a byte) we can use the OR operator bit-to-bit Example: byte1 = 01010101 OR byte2 = 00001111 ----------------------- result = 01011111 In C++ the OR operator is expressed by '|' character. | |
A.4 XOR operator The XOR operator is not well known in logic, where it is called "eXclusive OR": It works exactly as OR but when the first operand and the second one are TRUE the answer is FALSE instead of TRUE as in the OR operand (it translate the phrase "the first OR the second but not both") 0 XOR 0 = 0 (FALSE XOR FALSE = FALSE) 0 XOR 1 = 1 (FALSE XOR TRUE = TRUE) 1 XOR 0 = 1 (TRUE XOR FALSE = TRUE) 1 XOR 1 = 0 (TRUE XOR TRUE = FALSE) If we have a set of bits (for example a byte) we can use the XOR operator bit-to-bit Example: byte1 = 01010101 XOR byte2 = 00001111 ----------------------- result = 01011010      columns different with respect to OR operator In C++ the XOR operator is expressed by '^' character. | |
A.5 Yeah, but why do I need this in Civ? Ok, it's time to come back to our preferred game: When do you need to use these things? Let's say you want to trigger a particular event ONLY if the fourth Civ is still alive: How can you translate this request in C++ code? You know that CSPL gives you a function called GetCivInPlay, which returns a byte which represents civs still active in the following way: The n-th bit in the byte is 0 if n-th civ is dead or 1 if n-th civ is alive; so 11010001 means that only civs nr 1,5,7 and 8 are alive (remember civ 1 is barbarian). So assuming you are just interested in the fourth bit of the byte, how can you extract this information in a simple way? The easiest way is to use the AND operator, putting the result of function GetCivInPlay in AND with the bit mask 00010000. See if you can follow:
                        5th civ is
alive    5th civ is dead
If the fifth civ is dead the result will be 0 while if the fourth civ is alive the result will be a number != 0 As you can imagine if we were interested in the first civ (barbarians) the bit mask to use would be 00000001 (1 decimal), while if we were interested in the second civ the bit mask to use is 00000010 (2 decimal) and so on. In C++ code you'll have:
{
For an example of the use of OR operator keep using the GetCivInPlay function. Let's say we don't want to test if a particular civ is active but that we want to resurrect a civ (if it is dead). The problem here is quite different. First we want to SET a particular bit:
                        5th civ is
dead          5th civ is dead
As you can see the result of OR operator is exactly the GetCivInPlay result with the fifth bit set. This ensures that CSPL will not touch other Civilizations, it will just add the fifth one to the game. For an example of the use of XOR operator keep using GetCivInPlay function. Let's say we want to destroy an existing civilization without touching the other civs. The problem is easily solved with the XOR operator: 5th civ is alive 5th civ is alive
                        5th civ is
dead            5th civ is dead
As you can see the result of XOR operator is exactly the GetCivInPlay result with the fifth bit unset, thus ensuring that CSPL will not touch any other Civilizations. It just eliminates the fifth one from the game. | |
A.6 Conclusions OK, here I'll briefly discuss the use of the binary operator in CSPL structures:
|