Logical Operators/Truth Tests

Logical operators perform Boolean (TRUE/FALSE) comparisons on an expression. Since NWNScript does not support a strict Boolean data type, the result of a logical operation will be an int value of either FALSE (0) or TRUE (1).


Logical Operators

Symbol Conditional
== Equality test ("is equal to").
!= Inequality test ("is not equal to").
< Less than equality test.
> Greater than equality test.
<= Less than or equal to equality test.
>= Greater than or equal to equality test.
&& Short circuit logical AND.
& Bitwise AND.
|| Short circuit logical OR.
| Bitwise OR.
! Logical NOT.

The following expressions all equate to TRUE or 1:

// data
int nValue1 = 3;
int nValue2 = 3;

// expressions
int bTest = nValue1 == nValue2;
int bTest = nValue1 != 0;
int bTest = (nValue1 == 3) && (nValue2 != 0);
int bTest = (nValue1 == 3) || (nValue2 == 0);

The following examples all equate to FALSE or 0:

// data
int nValue1 = 3;
int nValue2 = 3;

// expressions
int bTest = nValue1 != nValue2;
int bTest = nValue1 == 0;
int bTest = (nValue1 == 3) && (nValue2 == 0);
int bTest = (nValue1 != 3) || (nValue2 == 0);

One good use for logical operators is to test multiple expressions in a single if statement. This will prevent unnecessary nested if statements which make code difficult to follow, and in some cases slower.


The Logical NOT operator is an exception because it's a unary operator (only operates on a single expression):

int bRunning = TRUE;
int bRunTest = !bRunning;

In this example bRunTest will equate to 0 or FALSE.


It should be noted that && and || are considered short-circuit operators: that is, in an && conditional the first condition to evaluate as FALSE from left-to-right stops evaluation of the remaining statements, and in an || conditional the first condition to evaluate as TRUE from left-to-right stops evaluation of the remaining statements. What does this mean? Suppose you had two functions and either function returns TRUE or FALSE:

int bFunction1()
{
     // check to see if a specific item is in the player's inventory
     int bRet = FALSE;
     bRet = GetItemPossessedBy(OBJECT_SELF, "some_item");
     PrintInteger(bRet); // out to the log file
     return bRet;
}

int bFunction2()
{
     // moves the camera around
     SetCameraFacing(270.0f, CAMERA_TRANSITION_TYPE_SLOW);
     // returns TRUE for absolutely no reason
     return TRUE;
}

bFunction2, above, has what is known as a side effect. That means that although it is a function, it also causes something else to happen as well. When we use a short circuit AND operator (&&)...

void main() 
{
     if (bFunction1() && bFunction2())
     {
          // do something here
     }
}

If OBJECT_SELF does not have the item "some_item" then bFunction2() will never be called, thus the camera angle will never change. Contrast that to the following:

void main()
{
     if (bFunction1() & bFunction2())
     {
          // do something
     }
}

In this second example, the camera angle will be changed because we are not using a short circuit operator; the entire statement will be evaluated.


Don't get "==" confused with the assignment operator "="! Assigning a statement to a value always returns TRUE and is a common source of bugs in code.

int nNumber = 4;
if (nNumber = 5) // assignment; assigns value and returns TRUE!
{
     PrintInt(nNumber);
}
// this will print "5" to the log file because nNumber is assigned
// the value of 5 during the "if" test
// if (nNumber == 5) is what should really appear above

Finally because "==", "!=", "<", ">", "<=", and ">=" return TRUE or FALSE, you can use them for shortcuts when assigning values to boolean (TRUE/FALSE) integers. For example, the following code:

int nNumber = 3;
int bCondition = FALSE;
if (nNumber == 3)
     bCondition = TRUE;
else
     bCondition = FALSE;

can become a single line of code:

int nNumber = 3;
int bCondition = nNumber == 3;




 author: Ryan Hunt, editors: Charles Feduke, Mistress, additional contributors: Bradley Beacham, ccaswell, Ken Cotterill