RPGToolkit 3 — Online Help [ home, back, forward ]

RPGCodeLanguage Features — Program Flow

Contents


Programming Constructs

All of the programs that we've made so far have run from top to bottom in perfect order. We've played with variables and shown messages, but right now they don't seem to be very useful. One of the best ways to really take control of how your program operates is program flow. With program flow, we can, instead of having the program run from top to bottom, make things stop, go back up, skip parts, or make things happen more than once.

The "If" statement:

One of the most used and most useful commands in all of programming is the If statement. The If statement is a construct that allows you to do something only if a condition is true (Editor's Note: non-zero). What do I mean by that exactly? Here's an example of using If in a real sentence:

If I were the King of the world, Then I would have a pet monkey.

Let's look at this closely. First, "If I were the King of the world". Is this statement true or false? If I am the king of the world, then it's true. And I would have a monkey for a pet. However, if I am not the king of the world, then it's false. And I would not have a monkey for a pet. As you will notice, everything after "Then" would only happen if everything before "then" was true. This is exactly how the If statement works. Here's the general form of an If statement:

if (condition)
{
	command1
	command2
	etc...
}

So what does all of that mean? Well, the If statement works very similar to our everyday speech. It tests if some condition is true, and if it is true, then one or more commands get executed. If the condition is false, then the commands don't get executed. It's that easy. So what is this condition that gets tested? The most basic is comparing two values. Seeing if one thing equals another. Here's an example:

testvar! = 12

if (testvar! == 12)
{
	mwin("Yay! The condition was true!")
	wait()
	mwincls()
	// This block of code will get executed
	// because testvar! is equal to 12.
}
if (testvar! == 0)
{
	mwin("testvar! was equal to 0.")
	wait()
	mwincls()
	// This block of commands will not get executed
	// because testvar! is NOT equal to 0. So the
	// commands here will be skipped.
}

In the above example, only the first block of statements is run (a block of statements are a bunch of commands enclosed in { and } brackets). Only the first set is run because "testvar!==12" is true (testvar! is equal to 12). Why the two equal signs? In Languages like C++, '=' is used to assign a value to a variable, whereas '==' is used to compare two values. The same is true in RPGCode. Notice that the second block doesn't get run at all. The condition "testvar!==0" is false -- testvar! is not equal to zero, so the block that follows does not get run. Notice also the way I indented my commands inside the blocks. This isn't necessary, but it sure looks cool, doesn't it? It just makes the code more readable.

The 'Else' Statement:

In the last example, you saw how two If statements were used together to check if either one or the other was true. That, however, is not the prefered way to do it. The statement "if (testvar! == 0)" is irrelevant, because if testvar! is something other than 12, then it could be any number. So, how can we fix this? Check every probable number? Well, you could. But that'd take forever, and it would be very slow. Instead, we'll use the 'Else' statement to get the job done. Here's the same program again, but with the Else statement:

testvar! = 12
if (testvar! == 12)
{
	mwin("Yay! The condition was true!")
	wait()
	mwincls()
	// This block of code will get executed
	// because testvar! is equal to 12.
}
else
{
	mwin("testvar! wasn't equal to 12.")
	wait()
	mwincls()
	// This block of commands will not get executed
	// because testvar! IS equal to 12. So the
	// commands here will be skipped.
}

As you can see, the If and Else commands share similarity. Both contain the opening and closing braces (the { and }), and they work together. The Else command executes the block of code inside it's braces as long as the preceeding If statement is false. So, in the example above, the Else statement isn't run. The If statement, however, is.

The 'Switch' Statement

In the last two program flow sections, you learned how to use conditional statements (if/else) to control the flow of certain parts of your program. In this section, you will find out how to use the 'Switch' statement. The basic form of a Switch statement looks like this:

switch (variable)
{
	case (value)
	{
		command1
		command2
		etc...
	}
}

As you can see, this is a bit different from the if/else commands. In this, we use Switch(variable), where variable can be either a literal or numeric value, and a Case(value) command between the Switch's brackets. Switch Cases are practically ideal for checking if a value is equal to another value. In fact - that's what it's there for.

Switch() holds the variable that you want to check the value of. Whereas Case() compares the value of the Switch() variable to whatever is presented inside of it's parentheses (hard to understand? It'll be clearer soon!). An example of using Switch Cases might be that you have a cheat prompt in your game somewhere (say, a menu). You could check what the values are by using If statements like so:

cheat$ = prompt("Enter a cheat:")
if (cheat$ == "HEAL")
{
	giveHP("Frap", 100)
}
elseIf(cheat$ == "I_WANT_GP")
{
	giveGP(10000)
}
elseIf(cheat$ == "SUPER_COOL_CHARACTER")
{
	addPlayer("cool.tem")
}
else
{
	mwin("That's not a cheat!")
	wait()
}

This, however, can get somewhat annoying, always having to type "cheat$ ==" before the actual value. Luckily, using Switch Cases, you can achieve the same affect without having to go through the whole process of using equal signs and the variable. Let's take a look at the same program using Switch Cases instead of if/else statements:

cheat$ = Prompt("Enter a cheat:")
switch (cheat$)
{
	case ("HEAL")
	{
		giveHP("Frap", 100)
	}
	case ("I_WANT_GP")
	{
		giveGP(10000)
	}
	case ("SUPER_COOL_CHARACTER")
	{
		addPlayer("cool.tem")
	}
	case (else)
	{
		mwin("That's not a cheat!")
		wait()
	}
}

There you have it - a Switch statement. Each Case() command checks to see if the variable specified in Switch() is equal to some value. This is much easier to read, and much more organized (because you can now clearly see that each Case() statement belongs to the Switch() statement. With If statements, you could check for random things at any time).

Operators:

As mentioned before, the If statement can be used to do more things than just checking if two things are equal to each other. The following section lists the 'operators' you can use.

Equal To (==):
Tests if two values are equal to each other.
Example:

if (var$ == "Hello")
{
	mwin("Hello to you too!")
}

Not Equal To (~=):
Tests if two values are NOT equal to each other.
Example:

if (var$ ~= "Hello")
{
	mwin("It doesn't say hello!")
}

Addition (+=):
Adds a value to a variable. This can be used for either numerical or literal variables.
Example:

x! = 1
y! = 5
x! += y!
// Adds 5 to 1 (y to x)
// This is the old way to do it: x! = x! + y!

Subtraction (-=):
Deducts a value from a variable. This can be used for only numerical variables.
Example:

x! = 1
y! = 5
y! -= x!
// Deducts 1 from 5 (x from y)
// This is the old way to do it: y! = y! - x!

Multiplied by (*=):
Multiplies a value by another value. This can only be used for numerical variables.
Example:

x! = 2

y! = 5
x! *= y!
// Multiplies x! by y!
// This is the old way to do it: x! = x!*y!

Divided by (/=):
Divides a value by another value. This can only be used for numerical variables.
Example:

x! = 10
y! = 2
x! /= y!
// Devides x! by y!
// This is the old way to do it: x! = x!/y!

Increment (++):
Adds 1 to a variable. This can only be used for numerical variables.
Example:

x! = 5
x!++ // Increments x! by 1
// This is the old way to do it: x! = x! + 1

Decrement (--):
Deducts 1 from a variable. This can only be used for numerical variables.
Example:

x! = 5
x!-- // Decrements x! by 1
// This is the old way to do it: x! = x! - 1

Exponent (^):
Raises a value to the power of another value. This can only be used for numerical variables.
Example:

x! = 2
show(x! ^ 2) // Output: 4
show(x! ^ 3) // Output: 8
show(x! ^ 4) // Output: 16

Greater Than (>), Less Than (<):
Tests if a value is greater than another value, or if a value is less than another value.

Editor's Note: These operators should be thought of as functions; they return 1 if "true"; otherwise, 0. This means that they are not restricted to usages illustrated in this help file (e.g., func(5 > 6)).

Example:

if (var! < 5)
{
	show(var!)
}
if (var! > 5)
{
	mwin("Too high!")
}

Greater Than Or Equal To (>=), Less Than Or Equal To (<=):
Tests if a value is either greater than or equal to another value, or if a value is either less than or equal to another value.

Editor's Note: These operators should be thought of as functions; they return 1 if "true"; otherwise, 0. This means that they are not restricted to usages illustrated in this help file (e.g., func(5 <= 6)).

Example:

if (var! <= 4)
{
	show(var!)
}
if (var! >= 5)
{
	mwin("Too high!")
}

Logical Not (!):
Tests if a value is false (if it is equal to 0), or a non-zero value. This can only be used for numeric variables.

Editor's Note: The logical NOT operator should be thought of as a function ("command"). It returns 1 if its operand is 0; otherwise, it returns 0.

Example:

done! = 0

if (!done!)
{
	// The ! operator before the variable checks
	// if done! is equal to 1 or not. If done! is
	// a non-zero value, it evaluates to false.

	// Additionally, if you take out the logical not
	// operator, and leave only the variable, it checks
	// if done! is a non-zero value (executing the black
	// of code if it is).

	mwin("done! is false!")
	wait()
}

Logical AND (&&, AND):
Tests if two conditions are true. When using a Logical And, you can either use the Logical And symbol (&&) or just use the word "and".

Editor's Note: In actuality, the logical AND operator returns 1 if both its operands are non-zero, or 0 if both its operands are 0. This works for multiple comparisons because the comparison operators return 1 or 0 based on their success.

Example:

// This example uses the 'logical AND' operator, '&&'

if (var! == 5 && var2! < 10)
{
	// This block of code will only be executed
	// if var! is equal to 5 AND var2! is less than
	// 10.
	mwin("Wow, var! is 5 and var2! is less than 10!")
}

// This does the same, using the 'AND' keyword.
if (var! == 5 AND var2! < 10)
{
	// This block of code will only be executed
	// if var! is equal to 5 AND var2! is less than
	// 10.
	mwin("Wow, var! is 5 and var2! is less than 10!")
}

Logical OR (||, OR):
Tests if one of two conditions is true. When using a Logical Or, you can either use the Logical Or symbol (||) or just use the word "OR".

Editor's Note: In actuality, the logical OR operator returns 1 if either of its operands are non-zero, or 0 if both its operands are 0. This works for multiple comparisons because the comparison operators return 1 or 0 based on their success.

Example:

// This example uses the 'logical OR' operator, '||'
if (var! == 5 || var2! < 10)
{
	// This block of code will only get executed
	// if var! is equal to 5 OR var2! is less than
	// 10.
	mwin("Hmm. Either var! equals 5 or var2! is less than 10.")
	mwin("Either way, we still get to see this pretty block!")
}

// This does the same, using the 'OR' keyword.

if (var! == 5 OR var2! < 10)
{
	// This block of code will only get executed
	// if var! is equal to 5 OR var2! is less than
	// 10.
	mwin("Hmm. Either var! equals 5 or var2! is less than 10.")
	mwin("Either way, we still get to see this pretty block!")
}

Editor's Note: The following, more complex, operators also exist, but will not be covered in detail:

& and &= bitwise AND
| and |= bitwise OR
` and `= bitwise XOR
<< and <<= left bit-shift
>> and >>= right bit-shift
~ bitwise NOT

Your First practical program:

Since you know how to use If's and variables, I think it's about time we make a real program. It'll just be a short, simple program to start you on your path to game making. What it will do is simple: Ask the user a question and let them decide what the answer is by pressing either 1 or 2. Let's take a look:

// This small program will just ask the user
// a question and let them select either 1
// or 2.
mwin("What do you want to do?")
mwin("1 - Say something nice")
mwin("2 - Say something mean")

result$ = wait()  // Get the input
mwincls()         // Clear the window



// Now, check to see what the user pressed...
// If result$ is "1", say something nice
if (result$ == "1")
{
	mwin("Hello! Aren't you looking nice today!")
	wait()
	mwincls()
}


// If result$ is "2", say something not so nice.
elseIf(result$ == "2")
{
	mwin("You're a dummy!")
	wait()
	mwincls()
}

Here's our first semi-practical program. The computer actually does something based upon what the user has done. The comments pretty much explain the program, so I won't say anything about it except for this: What happens if the user doesn't press '1' or '2'? what if they pressed 'm' by mistake? Well, both If statements would be false, and neither program block would get run. What do we do if the user does press something different? That's dealt with next...

While Loops:

Consider that program for a while. If the user didn't press '1' or '2', we'd want the computer to ask again until they pressed either '1' or '2'. Well, how do we do this? Just retype the same lines of code over and over until we think it's enough? That could go on forever. So instead, we'll use a 'while loop'. Before I explain what a while loop is, here's the program again with a while loop added (it will keep prompting until the user presses '1' or '2'):

// This small program will just ask the user
// a question and let them select either 1
// or 2.

// Run the While loop while done! is equal to false (0)...
done! = false
while (!done!)
{
	mwin("What do you want to do?")
	mwin("1 - Say something nice")
	mwin("2 - Say something mean")

	result$ = wait()  // Get user input
	mwincls()         // Clear the window

	// Now, check to see what the user pressed...
	// If result$ is "1", say something nice
	if (result$ == "1")
	{
		mwin("Hello! Aren't you looking nice today!")
		wait()
		mwincls()

		// Set done! to true. We do this so the while loop
		// doesn't repeat after the desired action is performed.
		done! = true
	}

	// If result$ is "2", say something not so nice.
	elseIf(result$ == "2")
	{
		mwin("You're a dummy!")
		wait()
		mwincls()

		// Set done! to 1. We do this so the while loop
		// doesn't repeat after the desired action is performed.
		done! = true
	}
}

The program is a little longer now, but more efficient. With the while loop added, if the user does not press '1' or '2', it will go back to where the while loop starts and execute the code again, waiting for the keypress. So how does the while loop work? Let's take a look...

A While Loop is just a block of statements that gets run over and over again until a certain condition is false. In the program above, the condition that was used was like saying "While the variable 'done' equals 0, repeat this block of code". Here's the general form of a while loop:

while (condition)
{
	command1
	command2
	etc...
}

Looks like the If statement, right? That's because a While loop is just like an If statement that repeats itself zero or more times. The block of code inside of the brackets (the { and }) will get executed as long as the condition is true. Once the end of the block is reached, it skips back up to the top of the while () command and tests if the condition is still true. If the condition is still true, the block will run again. Then it will skip back up to the while () statement. If the condition is true, the block will run again. The block will continue to be run over and over again as long as the condition is true. Once it is false, the commands in the block won't get run, and the program will continue along leaving the while () loop behind.

So how do you exit a while loop? Well, you have to leave it manually. For instance, let's take a look at this piece of code:

done! = false
while (!done!)
{
	mwin("Hi!")
}

This loop will run forever (at least until you ctrl + alt + delete out of it. Not a good idea!). You need something to exit the while loop. So how do we do that? Simply set 'done!' to equal something other than false. Here's how you would exit the loop:

done! = false
while (!done!)
{
	mwin("Hi!")
	done! = true
}

Please note: When you assign 'false' to a variable, it's like assigning 0. When you assign 'true', it's like assigning 1. So, things like, "while (!done!)" just says, "While done! is not true."

After it prints "Hi!" to the screen, it then exits the while loop by setting done! to equal true instead of false. That example, however, isn't very useful because you don't need that to repeat at all. Here's something you might want to repeat:

count! = 1
while (count! <= 5)
{
	show(count!) // Show the value of count! in the message window
	count!++     // Increment done! by 1
}

This small program prints the value of count! onto the screen using the Show() command. Note that instead of setting count! to an exact number to exit the loop, I increment it by 1. This block runs until count! is less than or equal to 5. So, it prints the numbers 1 through 5 on separate lines. Then it exits the loop, resuming the program. When dealing with loops, remember to always check them and make sure that they will eventually end. If your loop doesn't end, you will have to endtask the program and shut it down. There is also a 'better form' of a While loop, which is called a For loop. That's exactly what we're learning next...

For loops

In a way, you've already done a For loop. Not the actual command, but a different representation. A for loop is basically a while loop that lets you initialize and increment/decrement. This is the form of a For loop:

for (initialization; condition; increment)
{
	command1
	command2
	etc...
}

Let's start with the initialization. Initialization just means that you create a variable to be used in the condition. For example, I could create the the variable i! and give it the value 0. That would be our base variable to use in the condition. The condition is the same as in a While loop and an If statement. All of the conditional operators can be used here. Next, we have increment. All we do here is increment or decrement the base variable. Let's take a look at an example:

for (count! = 1; count! <= 5; count!++)
{
	show(count!)
}

If you look at the last example in the While loops section, you may notice that this does the same thing. First, it creates the variable count! and assigns it the value 1. Then, it checks if the condition is true (if count! is less than or equal to 5). If so, it runs through the loop and then increments the number. It repeats step two and step three while the condition is true. Where it takes three lines of code to do this with the While loop, it only takes one line with the For loop.

The above examples output will be:
1
2
3
4
5

Throughout this section of the document, you've learned how to control program flow with conditional statements and loops. It is worth noting that you don't always need to include the opening and closing braces ({ and }). This works for everything you've seen so far (if, else, switch, while, and for). If your conditional statement or loop is only supposed to run one line of code, you don't need the braces. However, the braces are required if the conditional statement or loop is supposed to run more than one line of code. Example:

a! = 1
if (a! == 1)
	mwin("a! is 1")
else
	mwin("a! is not 1")

Statements that use {}'s are called 'compound statements.'

Editor's Note: We encourage using brackets even where they are not required for long term code readabilitiy.


Multitasking

Most programs you write will be programs that you set on the board using the Board Editor. However, items that are placed on the board can run multitasking programs -- that is, they can run while other programs are running at the same time. Multitasking programs work basically the same as normal programs, except for a few variations.

A multitasking program is usually set up as an infinite loop, because it usually just makes the item walk around the screen repeatedly. In TK2, there were issues with multitasking, because you had to use the Branch() command to make the loop, and they were quite slow. You couldn't use 'real' loops like For and While because they would 'lock' up the computer (in other words, the computer would stall).

If you're a veteran of TK2, you'll notice that TK3 makes things much easier. In the case of multitasking, you can now use For and While loops in your threads for faster, more efficient threaded programs (we'll discuss what 'thread' means in a moment). Here's an example of a simple multitasking program that makes an NPC wander around the board.

// Makes an NPC wander around the board infinitely.
while (true)
{
	wander("target", 0)
}

Threading:

In TK2, the only way to use multitasking programs was to use them with an item placed on the board. However, TK3 is much more convenient. It allows you to use 'threads'. A 'thread' is a multitasking program that you can run from another program. So instead of going through the trouble of making an item with the multitask program and setting it on the board, you can easily type in the Thread() command to have a multitask program run. This is much more efficient and easier. Let's take a look at how you use the Thread() command:

id! = Thread("my_program.prg", 0) 
// Sets the multitask program "my_program.prg".
// Only runs while player is on the board.

As the comments explain, that runs a multitasking program called 'my_program.prg'. It only runs while the player is on the board, so it will stop once the player leaves or you stop it using the ThreadSleep() command. The ThreadSleep() command puts your thread to 'sleep'. Basically, it stops your thread from running for a matter of seconds. If you want to 'wake the thread up' again, just use ThreadWake(). For information on how to use the various threading commands, look in the Command Reference.


previous, forward