ChoiceScript Wiki

     

A loop - in programming - is a list or sequence of instructions that is repeatedly run (or processed) until a certain condition or parameter is met. They usually serve a specific purpose and are, more often than not, part of subroutines (or subroutines themselves).

While not strictly necessary for the standard choicescript game, the use of loops can be very beneficial, particularly to those who are interested in developing something more technically involved than the average choice-novel.

Loops can:

  • Result in smaller file sizes
  • Make your code easier to read
  • Make bug finding much easier
  • Allow you to change various parameters for a common system without extensive use of find & replace

The basics (full explanation)

To fully understand this section, you should already be familiar with: Variables, arithmetic operators, if conditions, labels and the goto command.

Typically, loops do not add functionality to a program (or a choicescript game). In fact the majority of current CoG titles, are likely to not use loops at all. This is because loops are merely a method of efficiency. They allow us to do the same things we've always done but with a lot less repeated code.

Let's take a look at a really basic example, where we print five numbers, utilizing a temporary variable n (for number):

NON-LOOPING FORMAT

*temp n
*set n 1
${n}
*set n 2
${n}
*set n 3
${n}
*set n 4
${n}
*set n 5
${n}
*finish

*comment 12 lines of code

If run, this choicescript scene would print the following text:

1 2 3 4 5

LOOPING FORMAT

*temp n
*set n 0
*label loop
*set n (n+1)
${n}
*if (n = 5)
 *finish
*goto loop

*comment 8 lines of code

This scene, although four lines shorter, will print exactly the same text as the former:

1 2 3 4 5


How they work

The easiest way to imagine it, is through a methodical table, like so:
LOOP CYCLE n = (n +1) NEW VALUE of N *IF RESULT ACTION
1 n = (0 + 1) 1 *if (n = 5) - false *goto loop
2 n = (1 + 1) 2 *if (n = 5) - false *goto loop
3 n = (2 + 1) 3 *if (n = 5) - false *goto loop
4 n = (3 + 1) 4 *if (n = 5) - false *goto loop
5 n = (4 + 1) 5 *if (n = 5) - true *finish

Every time *goto loop is run (because the if condition was false) our game returns to *label loop which is above our set command and our print command, we call this a 'cycle'.

Every cycle prints the value 'n' after it performs the calculation n = (n +1), as you can see in the table, n is not reset at any point, so increases by one every cycle. This continues until n is equal to five, at which point our if condition (which is being checked every cycle, but has proven false thus far) will finally return as 'true', subsequently executing the *finish command and breaking the loop.


Loop benefits

Four lines of code isn't a big deal, so why go through all that trouble to make the print routine a loop? Imagine for a second that you decided that you wanted to print up to ten, not five. Consider how we'd have to change each routine to make it print those additional numbers:

NON-LOOPING FORMAT

*temp n
*set n 1
${n}
*set n 2
${n}
*set n 3
${n}
*set n 4
${n}
*set n 5
${n}
*set n 6
${n}
*set n 7
${n}
*set n 8
${n}
*set n 9
${n}
*set n 10
${n}
*finish

*comment 21 lines of code

Even if you forgot about the variable and just typed 12345678910 on separate lines, it'd still be two lines longer than our looping routine.

LOOPING FORMAT

*temp n
*set n 0
*label loop
*set n (n+1)
${n}
*if (n = 10)
 *finish
*goto loop

*comment 8 lines of code, note that our *if is now (n = 10) not (n = 5)

Which one is easier? What if you needed to print one hundred numbers, or a thousand? Think about it.


Infinite/Never-ending loops

As amazing and useful as loops are, they can also cause quite a few problems if setup incorrectly. One of the most common problems with loops is a poorly designed (or non-existent) fallout/exit condition (like our *if (n = 5)). If a loop is never told to end or doesn't match its condition, it will run indefinitely and cause your game or browser to crash.

For example:

The following routine adds 3 to n every cycle and n starts at 0. This would mean that n goes from 0 to 3 to 6 to 9 to 12. It will never equal 10 and thus our exit line will never execute.

*temp n
*set n 0
*label loop
*set n (n+3)
${n}
*if (n = 10) <- 5 is now 10
 *finish
*goto loop

We could fix this by making our if condition read *if (n > 10) - as 12 and all numbers above it are 'greater than' 10.


Your turn (exercises)

1. Consider which line you'd need to change (and what you'd need to change it to) in order to make the loop routine print every other number (2, 4, 6...)
2. If you change *set n (n+1) to *set n (n * 2) the code will break, why (and how might we fix it)?

Advanced loops & useful examples (TODO)

Related articles