Previous: Pointers

If - Else branching

If my bills grow bigger than 1500 USD I need to find a new job, else I will keep the existing job.

Yes, my brain is still working ok, thank you for asking. That was just an example of if - else branching; its associated code is listed below:

if (my_bills > 1500)
    find_new_job( );
else
    keep_existing_job( );

You will need to use "if" instructions when you'll want your program to behave differently depending on some conditions: user input, a random number, the result of a mathematical operation, etc. Here's the basic form of the "if" instruction:

if (some condition is true)
    do_something(); // execute this instruction (a single instruction!)

or

if (some condition is true)
{
    // execute one or several instructions that are placed inside the curly brackets
}

A more complex form of the "if" instruction is listed below:

if (some condition is true)
{
    // execute one or several instructions that are placed inside the curly brackets
}
else
{
    // execute one or several instructions that are placed inside these curly brackets
}

The instructions placed inside the "else" part are executed only if "some condition" isn't true. Here's a practical example:

if (my_age > 65)
    income = 2000;
else // age less than or equal to 65?
    income = 3000;

It is pretty clear that income can be either 2000 or 3000 because only one of the branches will be executed (income = 2000 or income = 3000, not both).

Let's draw some conclusions:
- "
if" branching instructions start with the if keyword followed by a pair of parentheses;
- the parentheses contain a comparison, an expression ("some condition") that can be true or false;
- if the expression is true, the following instruction or the set of instructions placed inside the first pair of curly brackets is executed;
- if the expression is false and we don't use "
else", the set of instructions placed between the curly brackets is skipped (it isn't executed);
- if the expression is false and we are using the "
else" branch as well, the set of instructions placed inside the first pair of curly brackets is skipped, and the set of instructions placed inside the second pair of curly brackets is executed.

You'll be mastering these branching techniques in no time, trust me! Let's open the script12 file:

////////////////////////////////////////////////////////////////////
var weight = 300;
STRING* fluffy_str = "Fluffy!";
STRING* skinny_str = "Skinny!";
////////////////////////////////////////////////////////////////////
TEXT* weight_txt =
{
   pos_x = 300;
   pos_y = 230;
   flags = SHOW;
}
/////////////////////////////////////////////////////////////////////
function main()
{
   video_mode = 7; // create a program window of 800x600 pixels
   screen_color.blue = 1; // make the background dark
   while (1)
   {
      if (weight > 200)
         (weight_txt.pstring)[0] = fluffy_str;
      else
         (weight_txt.pstring)[0] = skinny_str;
      wait (1);
   }
}

The code doesn't look that complicated; we have defined a var named weight which receives an initial value of 300 and two strings: "Fluffy!" and "Skinny!". We will also display a text that uses the built-in font. The interesting part of the code is the while (1) loop placed inside function main:

while (1)
{
    if (weight > 200)
        (weight_txt.pstring)[0] = fluffy_str;
    else
        (weight_txt.pstring)[0] = skinny_str;
    wait (1);
}

I hope that you have noticed the "wait (1);" instruction inside the while loop; as we already know, this instruction interrupts the loop every frame cycle, allowing the other actions and functions to run at the same time. The rest of the code is simple: if weight is bigger than 200, we tell the weight_txt text to display the fluffy_str string, using the dot method. If weight is smaller than or equal to 200, we tell the weight_txt text to use the skinny_str string. We can omit the if / else pairs of curly brackets mentioned above when their content consists of a single line of code.

As you might have guessed,
pstring is the text property that allows us to set or replace (using the dot method) the strings that will be used for our texts. Since each text can use one or several strings (remember the 7th workshop?), (weight_txt.pstring)[0] will access the first string of our weight_txt text, (weight_txt.pstring)[1] will access the second string of the text, and so on. We are going to use texts with a single string most of the time, so "(some_txt.pstring)[0] = some_string;" will be enough for most of our needs.

Run the script and you will see the following text in the center of the screen:

Now press [Tab] on your keyboard and type the following line of code at the console:

weight = 100;

Once you've pressed [Enter] the text changes from "Fluffy!" to "Skinny!" because the "else" branch is executed if weight is less than or equal to 200.

We have used a while loop because we need to keep checking the value of "weight" all the time in order to display the proper text when the user types in a new value at the console.

Let's assume that you want to shut down the program when the user inputs this line:

weight = 0;

at the console. How would you do that? You must add a new "if" that compares weight with zero; copy and paste the code below inside the
while loop:

if (weight == 0)
    sys_exit(NULL);

The code should look like this:

////////////////////////////////////////////////////////////////////
#include <acknex.h>
#include <default.c>
////////////////////////////////////////////////////////////////////
var weight = 300;

STRING* fluffy_str = "Fluffy!";
STRING* skinny_str = "Skinny!";
////////////////////////////////////////////////////////////////////
TEXT* weight_txt =
{
    pos_x = 300;
    pos_y = 230;
    flags = SHOW;
}
/////////////////////////////////////////////////////////////////////
function main()
{    
    video_mode = 7; // create a program window of 800x600 pixels
    screen_color.blue = 1; // and the background dark
    while (1)
    {
        if (weight == 0)
            sys_exit(NULL);
        if (weight > 200)
            (weight_txt.pstring)[0] = fluffy_str;
        else
            (weight_txt.pstring)[0] = skinny_str;
        wait (1);
    }
}

The new code doesn't look too complicated; if weight is zero, the engine is supposed to shut down (you should remember "sys_exit" from the 6th workshop). Run the script and type

weight = 0;

at the console. The engine will shut down because the new "if" has done its job.

Wait a minute! What's with that "==" in the first new line of code? Is this a typing error? No, it isn't a typing error. Whenever you compare two expressions (weight and zero in the example above) you have to use "==" instead of "=", because a line of code that looks like this:

if (weight = 0)
{
    // do some stuff
}

will set weight to zero instead of comparing weight with zero. This is one of the most frequent mistakes; even an experienced programmer might set a variable to a certain value by mistake, instead of comparing it with that value.

Important tip

Using one instead of two equality signs for comparing two expressions inside a while loop, if branching, etc. is a very frequent mistake. Don't forget this!

if (a == 3) // correct
{
    do_some_stuff
}

if (a = 3) // wrong!
{
    do_some_stuff
}

You can avoid this mistake is you make it a habit to put the constant value on the left side of a comparison and the variable on the right side. The weight comparison instruction would look this way:

if (0 == weight) // correct
    sys_exit(NULL);

If you then accidentally put a single '=' instead of '==' the compiler will report an error because it knows that 0 can't be set to a different value.

We've talked a lot about expressions, but what is an expression? An (arithmetic) expression is a sequence of variables, numbers, operators, etc that are linked together. While it is nice to have simple expressions that look like the one below:

if (energy < 50) // simple expression inside the parenthesis
{
    health = 10;
}

it is entirely possible to work with more complicated expressions that could look like the ones below:

if ((armor + energy * 0.25) > (health * (1 - class / 3))) // more complicated expression
{
    health += 5;
}

Important tip

You can combine as many expressions as you want, using parenthesis, just like in the example above. The same rules from your math classes apply here, too. Sadly, you have to know some math if you want to be a good programmer.

Take a look at the table to see how you can compare two different expressions (you can use the same table for "if", "while", etc):

Sometimes you need to check if several conditions are met at once. Let's imagine that you want to fire a bullet; the code that takes care of that should check if:
a) Your health is above zero (dead players shouldn't be able to fire bullets);
b) Your ammo is bigger than zero (you need to have at least one bullet if you want to be able to shoot something or somebody).

There are several methods to solve this problem but one of them uses nested if branches, which translated to English means "if branches placed inside the curly brackets of other if branches". Let's see a clear, simple example:

if (player_health > 0)
{
    if (ammo > 0)
    {
        fire_bullets();
    }
}

What's happening here? First of all, player's health is compared with zero; if player_health <= 0, the rest of the code will be ignored. If the player is alive (player_health > 0), we will get to check if ammo is greater than zero. If the player hasn't got enough ammo (ammo <= 0) the rest of the code will be ignored; otherwise, if ammo > 0, function fire_bullets will run.


Next: Using the keyboard